浏览代码

1、床垫报价-内布套新增侧覆列
2、床垫报价-修复已有审核副规格,无法新增/修改其他副规格问题
3、软床报价-开放部件、公式列编辑
4、软床报价-公式部分均使用公式编辑器编辑
5、优化公式编辑器

MY 1 月之前
父节点
当前提交
e90634a030
共有 28 个文件被更改,包括 889 次插入492 次删除
  1. 25 0
      JLHHJSvr/Com/DeleteSoftBedFormula.cs
  2. 1 0
      JLHHJSvr/Com/GetFormulaVarList.cs
  3. 1 0
      JLHHJSvr/Com/Model/u_mattress_mx_mtrl.cs
  4. 2 1
      JLHHJSvr/DBA/ParkDBVersion.cs
  5. 33 0
      JLHHJSvr/DataStore/_Mapper_softbed_fixed_params.xml
  6. 10 14
      JLHHJSvr/DataStore/_Mapper_softbed_mtrltype.xml
  7. 1 0
      JLHHJSvr/DataStore/web_mattress_formulalist.xml
  8. 2 1
      JLHHJSvr/DataStore/web_mattress_mx.xml
  9. 3 1
      JLHHJSvr/DataStore/web_mattress_mx_neibutao.xml
  10. 53 0
      JLHHJSvr/Excutor/DeleteSoftBedFormulaExcutor.cs
  11. 75 36
      JLHHJSvr/Excutor/GetFormulaVarListExcutor.cs
  12. 17 3
      JLHHJSvr/Excutor/SaveMattressSubSpecsExcutor.cs
  13. 1 0
      JLHHJSvr/GlobalVar/GlobalVar.cs
  14. 8 0
      JLHHJSvr/Helper/BasicInfoHelper.cs
  15. 1 1
      JLHHJSvr/Helper/ERPHelper.cs
  16. 19 12
      JLHHJSvr/Helper/MattressHelper.cs
  17. 1 1
      JLHHJSvr/Helper/SoftBedHelper.cs
  18. 2 0
      JLHHJSvr/JLHHJSvr.csproj
  19. 3 3
      JLHWEB/src/api/modules/basicinfo.ts
  20. 1 12
      JLHWEB/src/views/baseinfo/softbedformula/detail.vue
  21. 33 62
      JLHWEB/src/views/baseinfo/softbedformula/hooks/index.tsx
  22. 4 5
      JLHWEB/src/views/quote/mattressQuote/detail.vue
  23. 15 0
      JLHWEB/src/views/quote/mattressQuote/hooks/index.tsx
  24. 15 1
      JLHWEB/src/views/quote/softbedQuote/detail.vue
  25. 135 37
      JLHWEB/src/views/quote/softbedQuote/hooks/index.tsx
  26. 246 236
      JLHWEB/src/views/system/formula-editor/editor.vue
  27. 83 0
      JLHWEB/src/views/system/formula-editor/editorModel.vue
  28. 99 66
      JLHWEB/src/views/system/formula-editor/index.vue

+ 25 - 0
JLHHJSvr/Com/DeleteSoftBedFormula.cs

@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using JLHHJSvr.Com.Model;
+using LJLib.Net.SPI.Com;
+
+namespace JLHHJSvr.Com
+{
+    public sealed class DeleteSoftBedFormulaRequest : ILJTokenRequest<DeleteSoftBedFormulaResponse>
+    {
+        public override string GetApiName()
+        {
+            return "DeleteSoftBedFormula";
+        }
+        /// <summary>
+        /// 软床公式id
+        /// </summary>
+        public List<u_softbed_formula> list { get; set; }
+    }
+
+    public sealed class DeleteSoftBedFormulaResponse : LJResponse
+    {
+    }
+}

+ 1 - 0
JLHHJSvr/Com/GetFormulaVarList.cs

@@ -14,6 +14,7 @@ namespace JLHHJSvr.Com
             return "GetFormulaVarList";
         }
         public string token { get; set; }
+        public byte type { get; set; }
     }
 
     public sealed class GetFormulaVarListResponse : LJResponse

+ 1 - 0
JLHHJSvr/Com/Model/u_mattress_mx_mtrl.cs

@@ -29,6 +29,7 @@ namespace JLHHJSvr.Com.Model
         public string replace_formula { get; set; }
         public string priceunit { get; set; }
         public byte? if_areaprice { get; set; }
+        public decimal? sidecover { get; set; }
         public decimal? thickness { get; set; }
         public string chastr { get; set; }
         public string dv_dscrp { get; set; }

+ 2 - 1
JLHHJSvr/DBA/ParkDBVersion.cs

@@ -30,7 +30,7 @@ namespace JLHHJSvr.DBA
     {
         protected override string currentVersion
         {
-            get { return "1.0.251010"; }
+            get { return "1.0.251022"; }
         }
 
         protected override string dbname
@@ -329,6 +329,7 @@ BEGIN
 END
 ", ""),
 new Script("1.0.251010", @"ALTER TABLE u_mattress ADD total_mtrl_hr_cost decimal(18, 5) NOT NULL CONSTRAINT DF_u_mattress_total_mtrl_hr_cost DEFAULT(0)", ""),
+new Script("1.0.251022", @"ALTER TABLE u_mattress_mx_mtrl ADD sidecover decimal(18, 5) NOT NULL CONSTRAINT DF_u_mattress_mx_mtrl_sidecover DEFAULT(0)", ""),
                 };
             }
         }

+ 33 - 0
JLHHJSvr/DataStore/_Mapper_softbed_fixed_params.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<data>
+  <json>
+    [
+      { label: "下料长", value: 1 },
+      { label: "下料宽", value: 1 },
+      { label: "下料数量", value: 1 },
+      { label: "用料量", value: 1 },
+      { label: "损耗率", value: 1 },
+      { label: "材料单价", value: 1 },
+      { label: "实际用量", value: 1 },
+      { label: "成本单价", value: 1 },
+      { label: "成本金额", value: 1 },
+      { label: "部门利润率", value: 1 },
+      { label: "佣金点数", value: 1 },
+      { label: "额外点数", value: 1 },
+      { label: "额外费用", value: 1 },
+      { label: "汇率", value: 1 },
+      { label: "税率", value: 1 },
+      { label: "工厂利润率", value: 1 },
+      { label: "FOB", value: 1 },
+      { label: "外销加点", value: 1 },
+      { label: "总材料成本", value: 1 },
+      { label: "总人力成本", value: 1 },
+      { label: "不含税出厂价", value: 1 },
+      { label: "部门不含税价", value: 1 },
+      { label: "部门含税价", value: 1 },
+      { label: "税金", value: 1 },
+      { label: "外币价", value: 1 },
+      { label: "车间成本", value: 1 }
+    ]
+  </json>
+</data>

+ 10 - 14
JLHHJSvr/DataStore/_Mapper_softbed_mtrltype.xml

@@ -1,15 +1,11 @@
 <?xml version="1.0" encoding="utf-8" ?>
-<data>
-	<json>
-		[
-			{
-				"label": "海绵",
-				"value": "海绵"
-			},
-			{
-				"label": "外套",
-				"value": "外套"
-			}
-		]
-	</json>
-</data>
+<select>
+	<selectstr>
+		SELECT u_mtrltype_erp.mtrltype AS value,u_mtrltype_erp.mtrltype AS label
+		FROM u_mtrltype_erp
+	</selectstr>
+	<where>
+  </where>
+  <displayfields>
+  </displayfields>
+</select>

+ 1 - 0
JLHHJSvr/DataStore/web_mattress_formulalist.xml

@@ -21,6 +21,7 @@ SELECT formulaid
 	,default_mtrlid1
 	,default_mtrlid2
 FROM u_mattress_formula
+WHERE formulatype = 101
   </selectstr>
   <where>
 	  <when notempty="@@arg_array_formulakind@@">

+ 2 - 1
JLHHJSvr/DataStore/web_mattress_mx.xml

@@ -42,7 +42,8 @@
 			u_mattress_mx_mtrl.mattress_width,
 			u_mattress_mx_mtrl.mattress_length,
 			CASE WHEN u_mattress_formula.formulatype = 99 THEN vv_bednetmx.spring_qty_width ELSE 0 END AS spring_qty_width,
-			CASE WHEN u_mattress_formula.formulatype = 99 THEN vv_bednetmx.spring_qty_length ELSE 0 END AS spring_qty_length
+			CASE WHEN u_mattress_formula.formulatype = 99 THEN vv_bednetmx.spring_qty_length ELSE 0 END AS spring_qty_length,
+			u_mattress_mx_mtrl.sidecover
 		From u_mattress_mx_mtrl
 		Left join u_mattress_formula On u_mattress_formula.formulaid = u_mattress_mx_mtrl.formulaid 
 		left outer join u_mtrl_price on u_mattress_mx_mtrl.mtrlid = u_mtrl_price.mtrlid

+ 3 - 1
JLHHJSvr/DataStore/web_mattress_mx_neibutao.xml

@@ -38,7 +38,8 @@
 			u_mattress_mx_mtrl.replace_useformula ,
 			u_mattress_mx_mtrl.gydscrp,
 			u_mattress_mx_mtrl.mattress_width,
-			u_mattress_mx_mtrl.mattress_length
+			u_mattress_mx_mtrl.mattress_length,
+			u_mattress_mx_mtrl.sidecover
 		From u_mattress_mx_mtrl
 		Left JOIN u_mattress_formula On u_mattress_formula.formulaid = u_mattress_mx_mtrl.formulaid left outer join u_mtrl_price on
 			u_mattress_mx_mtrl.mtrlid = u_mtrl_price.mtrlid
@@ -74,6 +75,7 @@
 		<field field="chastr">位置</field>
 		<field field="formulakind" table="u_mattress_formula" mapper="" ddd="ddd_mattress_formula_formulakind">公式名</field>
 		<field field="if_mtrl" table="u_mattress_formula" datatype="checkbox">按物料?</field>
+		<field field="sidecover" datatype="number">侧覆cm/条数</field>
 		<field field="thickness" datatype="number">厚度cm/条数</field>
 		<field field="mtrlname">物料</field>
 		<field field="qty" datatype="number">数量/长度</field>

+ 53 - 0
JLHHJSvr/Excutor/DeleteSoftBedFormulaExcutor.cs

@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using DirectService.Tools;
+using JLHHJSvr.BLL;
+using JLHHJSvr.Com;
+using JLHHJSvr.Helper;
+using JLHHJSvr.LJException;
+using LJLib.DAL.SQL;
+using LJLib.Net.SPI.Server;
+using LJLib.SQLEX;
+
+namespace JLHHJSvr.Excutor
+{
+    internal sealed class DeleteSoftBedFormulaExcutor : ExcutorBase<DeleteSoftBedFormulaRequest, DeleteSoftBedFormulaResponse>
+    {
+        protected override void ExcuteInternal(DeleteSoftBedFormulaRequest request, object state, DeleteSoftBedFormulaResponse rslt)
+        {
+            var tokendata = BllHelper.GetToken(request.token);
+            if (!request.list.Any())
+            {
+                rslt.ErrMsg = "至少提交一条需要删除的记录";
+                return;
+            }
+
+            using (var con = GlobalVar.ConnectionString.NewSqlConnection())
+            using (var cmd = con.CreateCommand())
+            {
+                con.Open();
+
+                var basicHelper = HelperBase.GetHelper<BasicInfoHelper>(cmd);
+                using (cmd.Transaction = con.BeginTransaction())
+                {
+                    try
+                    {
+                        foreach (var formula in request.list)
+                        {
+                            basicHelper.DeleteSoftBedFormula(formula);
+                        }
+                        cmd.Transaction.Commit();
+                    }
+                    catch (Exception e)
+                    {
+                        cmd.Transaction?.Rollback();
+                        rslt.ErrMsg = e.Message;
+                    }
+                }
+            }
+        }
+    }
+}

+ 75 - 36
JLHHJSvr/Excutor/GetFormulaVarListExcutor.cs

@@ -23,17 +23,10 @@ namespace JLHHJSvr.Excutor
                 return;
             }
 
+            var index = 0;
             rslt.recursionList = new List<Recursion2>();
-            // 变量定义
-            var varRecusionChilds = new List<Recursion2>();
-            rslt.recursionList.Add(new Recursion2() { text = "变量定义", value = 0, children = varRecusionChilds });
-            // 工艺加点设置
-            var workShipChilds = new List<Recursion2>();
-            rslt.recursionList.Add(new Recursion2() { text = "工艺加点设置", value = 0, children = workShipChilds });
             // 固定参数
             var fixedVarChilds = new List<Recursion2>();
-            rslt.recursionList.Add(new Recursion2() { text = "固定变量", value = 0, children = fixedVarChilds });
-
             using (var con = GlobalVar.ConnectionString.NewSqlConnection())
             using (var cmd = con.CreateCommand())
             {
@@ -43,51 +36,97 @@ namespace JLHHJSvr.Excutor
                 var param = new Dictionary<string, object>();
                 var outputFields = string.Empty;
 
-                // 变量定义
-                selectStr = "SELECT varname FROM u_bednet_var";
-                outputFields = "varname";
-                var bednetVarList = new List<u_bednet_var>();
-                DbSqlHelper.SelectJoin(cmd, selectStr, null, param, "varid", outputFields, 0, 0, bednetVarList);
-                foreach(var child in bednetVarList)
+                if (request.type == 0)
                 {
-                    varRecusionChilds.Add(new Recursion2()
+                    // 变量定义
+                    var varRecusionChilds = new List<Recursion2>();
+                    rslt.recursionList.Add(new Recursion2() { text = "变量定义", value = index++, children = varRecusionChilds });
+                    // 工艺加点设置
+                    var workShipChilds = new List<Recursion2>();
+                    rslt.recursionList.Add(new Recursion2() { text = "工艺加点设置", value = index++, children = workShipChilds });
+
+                    // 变量定义
+                    selectStr = "SELECT varname FROM u_bednet_var";
+                    outputFields = "varname";
+                    var bednetVarList = new List<u_bednet_var>();
+                    DbSqlHelper.SelectJoin(cmd, selectStr, null, param, "varid", outputFields, 0, 0, bednetVarList);
+                    foreach (var child in bednetVarList)
                     {
-                        text = child.varname,
-                        value = 1
-                    });
-                }
+                        varRecusionChilds.Add(new Recursion2()
+                        {
+                            text = child.varname,
+                            value = 100 + index++
+                        });
+                    }
 
-                // 加点工艺
-                selectStr = "SELECT workmanshipname FROM u_workmanship_add";
-                outputFields = "workmanshipname";
-                var workshipList = new List<u_workmanship_add>();
-                DbSqlHelper.SelectJoin(cmd, selectStr, null, param, "workmanshipid", outputFields, 0, 0, workshipList);
-                foreach (var child in workshipList)
+                    // 加点工艺
+                    selectStr = "SELECT workmanshipname FROM u_workmanship_add";
+                    outputFields = "workmanshipname";
+                    var workshipList = new List<u_workmanship_add>();
+                    DbSqlHelper.SelectJoin(cmd, selectStr, null, param, "workmanshipid", outputFields, 0, 0, workshipList);
+                    foreach (var child in workshipList)
+                    {
+                        workShipChilds.Add(new Recursion2()
+                        {
+                            text = child.workmanshipname,
+                            value = 100 + index++
+                        });
+                    }
+                } else if(request.type == 1)
                 {
-                    workShipChilds.Add(new Recursion2()
+                    // 软床公式
+                    var softFormulaChilds = new List<Recursion2>();
+                    rslt.recursionList.Add(new Recursion2() { text = "软床公式", value = index++, children = softFormulaChilds });
+
+                    selectStr = "SELECT formulaname FROM u_softbed_formula";
+                    outputFields = "workmanshipname";
+                    var softList = new List<u_softbed_formula>();
+                    DbSqlHelper.SelectJoin(cmd, selectStr, null, param, "formulaid", outputFields, 0, 0, softList);
+                    foreach (var child in softList)
                     {
-                        text = child.workmanshipname,
-                        value = 1
-                    });
+                        softFormulaChilds.Add(new Recursion2()
+                        {
+                            text = child.formulaname,
+                            value = 100 + index++
+                        });
+                    }
                 }
+
+                // 固定变量
+                rslt.recursionList.Add(new Recursion2() { text = "固定变量", value = index++, children = fixedVarChilds });
             }
 
+
             var queryparams = new JObject();
             var commonExcutor = new CommonDynamicSelectExcutor();
-            var commonRequest = new CommonDynamicSelectRequest()
+            var commonRequest = new CommonDynamicSelectRequest();
+            if (request.type == 0)
+            {
+                // 
+                commonRequest = new CommonDynamicSelectRequest()
+                {
+                    token = request.token,
+                    dsname = "_Mapper_fixedParamters",
+                    queryparams = queryparams
+                };
+            } else if(request.type == 1)
             {
-                token = request.token,
-                dsname = "_Mapper_fixedParamters",
-                queryparams = queryparams
-            };
+                // 软床固定变量
+                commonRequest = new CommonDynamicSelectRequest()
+                {
+                    token = request.token,
+                    dsname = "_Mapper_softbed_fixed_params",
+                    queryparams = queryparams
+                };
+            }
 
             var billResponse = commonExcutor.Excute(commonRequest, state) as CommonDynamicSelectResponse;
             if (billResponse != null && billResponse.datatable != null && billResponse.datatable.Any())
             {
                 var fiexdList = billResponse.datatable;
-                foreach(var item in fiexdList)
+                foreach (var item in fiexdList)
                 {
-                    fixedVarChilds.Add(new Recursion2() { text = Convert.ToString(item["label"]),value = Convert.ToInt32(item["value"]) });
+                    fixedVarChilds.Add(new Recursion2() { text = Convert.ToString(item["label"]), value = 100 + index++ });
                 }
             }
         }

+ 17 - 3
JLHHJSvr/Excutor/SaveMattressSubSpecsExcutor.cs

@@ -14,6 +14,7 @@ using JLHHJSvr.Tools;
 using LJLib.DAL.SQL;
 using LJLib.Net.SPI.Server;
 using LJLib.SQLEX;
+using NPOI.SS.Formula.Functions;
 
 namespace JLHHJSvr.Excutor
 {
@@ -45,15 +46,28 @@ namespace JLHHJSvr.Excutor
                 _mattress.extraCostList = mattressHelper.GetMattressMxExtra(request.mattress.mattressid, 2);
                 _mattress.subspecsList = request.subspecsList;
 
+                var existing = mattressHelper.GetMattressSubspecs(request.mattress.mattressid, "mattressid,mattresscode,flag,js1_flag") ?? new List<u_mattress>();
+                var oldIdSet = new HashSet<int>(existing.Where(t => t.flag == 0 && t.js1_flag == 0).Select(x => x.mattressid));
+                var toUpdate = request.subspecsList.Where(x => oldIdSet.Contains(x.mattressid)).ToList();
+                var toInsert = request.subspecsList.Where(x => x.mattressid == 0).ToList();
+
+                var subspecsList = new List<u_mattress>();
+                foreach (var child in toInsert)
+                {
+                    subspecsList.Add(child);
+                }
+                foreach (var child in toUpdate)
+                {
+                    subspecsList.Add(child);
+                }
+
                 using (cmd.Transaction = con.BeginTransaction())
                 {
                     try
                     {
-                        mattressHelper.ProcessSubSpecs(_mattress, false);
-
+                        mattressHelper.SaveSubSpecs(_mattress, subspecsList, false);
                         rslt.mattressid = _mattress.mattressid;
                         rslt.mattresscode = _mattress.mattresscode;
-
                         cmd.Transaction.Commit();
                     }
                     catch (Exception e)

+ 1 - 0
JLHHJSvr/GlobalVar/GlobalVar.cs

@@ -261,6 +261,7 @@ namespace JLHHJSvr
                 excutorManager.AddMap("AuditSoftBedQuote", typeof(AuditSoftBedQuoteRequest), new AuditSoftBedQuoteExcutor()); // 审核软床报价
                 excutorManager.AddMap("GetSoftBedMxList", typeof(GetSoftBedMxListRequest), new GetSoftBedMxListExcutor()); // 获取软床报价明细
                 excutorManager.AddMap("GetSoftBedConfigureList", typeof(GetSoftBedConfigureListRequest), new GetSoftBedConfigureListExcutor()); // 获取软床报价部件选配
+                excutorManager.AddMap("DeleteSoftBedFormula", typeof(DeleteSoftBedFormulaRequest), new DeleteSoftBedFormulaExcutor()); // 删除软床公式定义
                 excutorManager.AddMap("SaveSoftBedFormula", typeof(SaveSoftBedFormulaRequest), new SaveSoftBedFormulaExcutor()); // 保存软床公式定义
                 excutorManager.AddMap("SaveErpMtrlPriceList", typeof(SaveErpMtrlPriceListRequest), new SaveErpMtrlPriceListExcutor()); // 保存物料价格
                 excutorManager.AddMap("GetErpMtrlPriceList", typeof(GetErpMtrlPriceListRequest), new GetErpMtrlPriceListExcutor()); // 获取ERP物料资料定义

+ 8 - 0
JLHHJSvr/Helper/BasicInfoHelper.cs

@@ -67,6 +67,14 @@ namespace JLHHJSvr.Helper
                 DbSqlHelper.Update(cmd, "u_configure_codemx", null, codeMx, "pzid,printid", fields);
             }
         }
+        public void DeleteSoftBedFormula(u_softbed_formula formula)
+        {
+            if (formula == null || formula.formulaid <= 0)
+            {
+                throw new LJCommonException("未提交软床公式定义信息");
+            }
+            DbSqlHelper.Delete(cmd, formula);
+        }
         /// <summary>
         /// 核价软床公式定义-保存
         /// </summary>

+ 1 - 1
JLHHJSvr/Helper/ERPHelper.cs

@@ -342,7 +342,7 @@ namespace JLHHJSvr.Helper
         /// </summary>
         /// <param name="mtrl">核价物料资料</param>
         /// <returns>错误信息</returns>
-        public string SaveMtrldef(u_mattress mtrl, List<u_mattress_interface> interfaceList = null, string fields = "mtrlname,mtrlmode,mtrltypeid,mtrltype,unit,mtrlengname,configcode,configname,model,configcodetype,moddate,modemp,ifautodd,piccode,zxmtrlmode,flag,secflag,GYAuditdate")
+        public string SaveMtrldef(u_mattress mtrl, List<u_mattress_interface> interfaceList = null, string fields = "mtrlname,mtrlmode,mtrltypeid,mtrltype,unit,mtrlengname,configcode,configname,model,configcodetype,moddate,modemp,ifautodd,piccode,zxmtrlmode,flag,secflag,GYAuditdate,clcost")
         {
             var errMsg = string.Empty;
 

+ 19 - 12
JLHHJSvr/Helper/MattressHelper.cs

@@ -14,6 +14,7 @@ using System.Collections.Generic;
 using System.Data.SqlClient;
 using System.Linq;
 using System.Runtime.InteropServices;
+using System.Runtime.Remoting.Metadata.W3cXsd2001;
 using System.Text;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
@@ -321,7 +322,7 @@ namespace JLHHJSvr.Helper
                 }
                 if (!string.IsNullOrEmpty(keyStr))
                 {
-                    mxDict.Add(keyStr, mx.thickness);
+                    mxDict.Add(keyStr, mx.sidecover);
                 }
             } 
             else if (new List<int>() { 103 }.Contains(mx.formulatype.Value))
@@ -1667,7 +1668,7 @@ namespace JLHHJSvr.Helper
         public List<u_mattress_mx_mtrl> GetMattressMxMtrl(int mattressid,List<string> extraWhere = null)
         {
             var mxList = new List<u_mattress_mx_mtrl>();
-            var outputFields = @"mattressmxid, mattressid, formulakind, formula, formulaid, mtrlid, mtrlname, price, gram_weight, cloth_width, if_inputqty, qty , costamt, if_areaprice, formulatype, sortcode, if_mtrl, if_success, replace_formula, priceunit, shrinkage, name, dannum1_rate, dannum2_rate, dannum3_rate, dannum4_rate, thickness, chastr, xu, useqty, useformula, replace_useformula , gydscrp, mattress_width, mattress_length, spring_qty_width, spring_qty_length";
+            var outputFields = @"mattressmxid, mattressid, formulakind, formula, formulaid, mtrlid, mtrlname, price, gram_weight, cloth_width, if_inputqty, qty , costamt, if_areaprice, formulatype, sortcode, if_mtrl, if_success, replace_formula, priceunit, shrinkage, name, dannum1_rate, dannum2_rate, dannum3_rate, dannum4_rate, thickness, chastr, xu, useqty, useformula, replace_useformula , gydscrp, mattress_width, mattress_length, spring_qty_width, spring_qty_length,sidecover";
             var selectStr = @"
 		                        SELECT
 			                        u_mattress_mx_mtrl.mattressmxid,
@@ -1707,6 +1708,7 @@ namespace JLHHJSvr.Helper
 			                        u_mattress_mx_mtrl.gydscrp,
 			                        u_mattress_mx_mtrl.mattress_width,
 			                        u_mattress_mx_mtrl.mattress_length,
+			                        u_mattress_mx_mtrl.sidecover,
 	                                CASE WHEN u_mattress_formula.formulatype = 99 THEN vv_bednetmx.spring_qty_width ELSE 0 END AS spring_qty_width,
 	                                CASE WHEN u_mattress_formula.formulatype = 99 THEN vv_bednetmx.spring_qty_length ELSE 0 END AS spring_qty_length
 		                        From u_mattress_mx_mtrl
@@ -2603,7 +2605,7 @@ namespace JLHHJSvr.Helper
                             if_w_butao, if_m_wbutao_way, s_cover_qty, z_cover_qty, x_cover_qty, biandai_qty, s_m_cover_qty, z_m_cover_qty, x_m_cover_qty, chaizhuang_point, 
                             haimian_point, if_zhedie_type, qr_auditingrep, qr_auditingdate, if_bcp_type, zhizao_amt, foreign_cost_bz,  cubage, extras_cost, extras_cost_dscrp, 
                             parentid, flag, xd_flag, dannum_type,dannum_cost1,dannum_cost2, dannum_cost3, dannum_cost4, dijia_cost1,dijia_cost2,dijia_cost3,dijia_cost4,version,total_mtrl_hr_cost";
-            var fieldsMx = "mattressmxid,mattressid,formulaid,formula,replace_formula,if_success,priceunit,shrinkage,mtrlid,price,gram_weight,cloth_width,if_inputqty,qty ,costamt,if_areaprice,thickness,chastr,xu,useqty,useformula,replace_useformula,gydscrp,mattress_width,mattress_length";
+            var fieldsMx = "mattressmxid,mattressid,formulaid,formula,replace_formula,if_success,priceunit,shrinkage,mtrlid,price,gram_weight,cloth_width,if_inputqty,qty ,costamt,if_areaprice,thickness,chastr,xu,useqty,useformula,replace_useformula,gydscrp,mattress_width,mattress_length,sidecover";
             var fieldsExtra = "mattressmxid,mattressid, extraid, extramxid, extraname, price, qty, dscrp, mtrlid";
 
             mattress.qr_auditingdate = context.opdate;
@@ -2838,7 +2840,7 @@ namespace JLHHJSvr.Helper
         {
             if (mattress.subspecsList == null) return;
             var existing = GetMattressSubspecs(mattress.mattressid, "mattressid,mattresscode,flag,js1_flag") ?? new List<u_mattress>();
-
+            // TODO
             foreach (var child in existing)
             {
                 if (child.flag == 1) throw new LJCommonException($"存在副规格[{child.mattresscode}]已财务审核,无法修改主规格!");
@@ -2854,16 +2856,22 @@ namespace JLHHJSvr.Helper
             toDelete.ForEach(x => DeleteMattress(x.mattressid));
 
             var subspecsList = new List<u_mattress>();
-
             foreach (var child in toInsert)
             {
-                var copy = CreateSubSpecClone(mattress, child);
-                subspecsList.Add(copy);
+                subspecsList.Add(child);
             }
-
             foreach (var child in toUpdate)
             {
-                var copy = CreateSubSpecClone(mattress, child);
+                subspecsList.Add(child);
+            }
+            SaveSubSpecs(mattress, subspecsList, ifErp);
+        }
+        public void SaveSubSpecs(u_mattress parent,List<u_mattress> childs,bool ifErp)
+        {
+            var subspecsList = new List<u_mattress>();
+            foreach (var child in childs)
+            {
+                var copy = CreateSubSpecClone(parent, child);
                 subspecsList.Add(copy);
             }
 
@@ -2877,13 +2885,12 @@ namespace JLHHJSvr.Helper
             {
                 // 已经审核的不进行再次保存/修改
                 if (child.flag == 1 || child.yw_flag == 1 || child.xd_flag == 1) continue;
-                InitMattressSubSpecs(mattress, child);
+                InitMattressSubSpecs(parent, child);
 
                 MattressCalculateCost(child, child.mxList, child.extraList, child.extraCostList);
                 SaveMattressPro(child, ifErp, true);
             }
-
-            mattress.subspecsList = subspecsList;
+            parent.subspecsList = subspecsList;
         }
         /// <summary>
         /// 子规格复制逻辑

+ 1 - 1
JLHHJSvr/Helper/SoftBedHelper.cs

@@ -408,7 +408,7 @@ namespace JLHHJSvr.Helper
 					}
 					var cnt = bomList.Where(t => t.has_type == mx.has_type && t.mtrlid == mx.mtrlid).Count();
 					if (cnt > 1) throw new LJCommonException($"保存失败,原因:{configureList[mx.has_type].contfigtypename}的{mx.mtrlname}存在多个清单,但没有设置部件!");
-					else if (cnt == 0) throw new LJCommonException($"保存失败,原因:{configureList[mx.has_type].contfigtypename}的{mx.mtrlname}不存在于物料清单中,请检查!");
+					//else if (cnt == 0) throw new LJCommonException($"保存失败,原因:{configureList[mx.has_type].contfigtypename}的{mx.mtrlname}不存在于物料清单中,请检查!");
                 }
             }
         }

+ 2 - 0
JLHHJSvr/JLHHJSvr.csproj

@@ -106,6 +106,7 @@
     <Compile Include="Com\DeleteConfigureBomList.cs" />
     <Compile Include="Com\DeleteMattressExtraType.cs" />
     <Compile Include="Com\DeleteMattressExtra.cs" />
+    <Compile Include="Com\DeleteSoftBedFormula.cs" />
     <Compile Include="Com\DeleteSoftBedQuote.cs" />
     <Compile Include="Com\DeleteSysPostMessage.cs" />
     <Compile Include="Com\GetBedNetInterfaceList.cs" />
@@ -349,6 +350,7 @@
     <Compile Include="Excutor\DeleteConfigureBomListExcutor.cs" />
     <Compile Include="Excutor\DeleteMattressExtraTypeExcutor.cs" />
     <Compile Include="Excutor\DeleteMattressExtraExcutor.cs" />
+    <Compile Include="Excutor\DeleteSoftBedFormulaExcutor.cs" />
     <Compile Include="Excutor\DeleteSoftBedQuoteExcutor.cs" />
     <Compile Include="Excutor\DeleteSysPostMessageExcutor.cs" />
     <Compile Include="Excutor\FormulaCheckExcutor.cs" />

+ 3 - 3
JLHWEB/src/api/modules/basicinfo.ts

@@ -552,8 +552,8 @@ export const DeleteMattressExtraType = (params: Basicinfo.ReqDeleteBasicinfo) =>
 /**
  * @name 获取 公式
  */
-export const GetFormulaVarList = () => {
-  return http.post(PORT1 + `/GetFormulaVarList`, {});
+export const GetFormulaVarList = (params: Basicinfo.ReqBanBasicinfo) => {
+  return http.post(PORT1 + `/GetFormulaVarList`, params);
 };
 
 /**
@@ -597,7 +597,7 @@ export const SaveSoftBedFormula = (params: Basicinfo.ReqSoftBedFormula) => {
  * @name 删除 床垫公式定义
  */
 export const DeleteSoftBedFormula = (params: Basicinfo.ReqDeleteBasicinfo) => {
-  return http.post<Basicinfo.ResDeleteBasicinfo>(PORT1 + `/DeleteMattressFormula`, params);
+  return http.post<Basicinfo.ResDeleteBasicinfo>(PORT1 + `/DeleteSoftBedFormula`, params);
 };
 /**
  * @name 保存 ERP物料价格

+ 1 - 12
JLHWEB/src/views/baseinfo/softbedformula/detail.vue

@@ -15,8 +15,6 @@
   >
     <!-- :action="orderStatus ? orderEditAction : orderDefaultAction" -->
   </LjDetail>
-
-  <MtrldefDialog ref="MtrldefDialogRef" v-bind="MtrldefDialogProps" />
 </template>
 
 <script setup lang="tsx" name="mattressFormulaListDetail">
@@ -27,7 +25,6 @@ import { DetailProp } from "@/components/LjDetail/interface";
 import { useI18n } from "vue-i18n";
 import { useHooks } from "./hooks/index";
 import { useAuthButtons } from "@/hooks/useAuthButtons";
-import MtrldefDialog from "@/views/system/selector/mtrldefNoPrice/index.vue";
 
 interface detailProp {
   /**
@@ -51,8 +48,7 @@ interface detailProp {
 
 const props = withDefaults(defineProps<detailProp>(), {});
 const { t } = useI18n();
-const { LjDetailRef, columns, MtrldefDialogRef, MtrldefDialogProps } = useHooks(t);
-const { CheckPower, CheckOption, buttonNew, buttonDefault } = useAuthButtons(t);
+const { LjDetailRef, columns } = useHooks(t);
 
 const mainData = ref([{}]);
 
@@ -84,13 +80,7 @@ const detailProps = reactive<DetailProp>({
 watch(
   () => props.data,
   val => {
-    console.log("props.data, val :>> ", val);
     mainData.value = [val];
-    // initParam.value.cusid = val.cusid;
-
-    // getDetailData(val).then(res => {
-    //   detailData.value = res;
-    // });
   },
   { immediate: true }
 );
@@ -98,7 +88,6 @@ watch(
 watch(
   () => props.status,
   val => {
-    console.log("props.status val :>> ", val);
     orderStatus.value = val;
   },
   { immediate: true, deep: true }

+ 33 - 62
JLHWEB/src/views/baseinfo/softbedformula/hooks/index.tsx

@@ -2,10 +2,9 @@ import { ref, reactive, computed, toRefs, nextTick } from "vue";
 import { Table } from "@/hooks/interface";
 import { ColumnProps } from "@/components/LjVxeTable/interface";
 import { ALLOW_EDIT_STATE } from "@/config/index";
-import MtrldefSelect from "@/views/system/selector/mtrldefNoPrice/select.vue";
-import { SaveSoftBedFormula, DeleteMattressFormula, getMtrlType } from "@/api/modules/basicinfo";
-import { ElMessage, ElMessageBox } from "element-plus";
-import { transformTreeData } from "@/utils/index";
+import { SaveSoftBedFormula, DeleteSoftBedFormula } from "@/api/modules/basicinfo";
+import { ElMessage, ElMessageBox, ElRow, ElCol, ElInput, ElButton } from "element-plus";
+import EditorModel from "@/views/system/formula-editor/editorModel.vue";
 
 interface defaultState {
   /**
@@ -22,6 +21,14 @@ interface defaultState {
   LjDetailRef: any;
   MtrldefDialogRef: any;
   MtrldefDialogProps: any;
+  /**
+   * @description 公式编辑弹窗Ref
+   */
+  formulaEditorRef: any;
+  /**
+   * @description 编辑行
+   */
+  editRow: any;
 }
 
 const state = reactive<defaultState>({
@@ -29,7 +36,9 @@ const state = reactive<defaultState>({
   VxeTableRef: null,
   LjDetailRef: null,
   MtrldefDialogRef: null,
-  MtrldefDialogProps: {}
+  MtrldefDialogProps: {},
+  formulaEditorRef: null,
+  editRow: null
 });
 /**
  * @description 表格多选数据操作
@@ -44,7 +53,7 @@ export const useHooks = (t?: any) => {
       title: "公式名",
       basicinfo: {
         el: "input",
-        order: 5,
+        // order: 5,
         span: 3,
         editable: ALLOW_EDIT_STATE,
         rules: [{ required: true }]
@@ -55,10 +64,15 @@ export const useHooks = (t?: any) => {
       title: "用料量公式",
       basicinfo: {
         el: "input",
-        order: 13,
+        // order: 13,
         span: 6,
-        editable: ALLOW_EDIT_STATE,
-        props: { type: "textarea", rows: 3 }
+        render: (scope: any) => {
+          return (
+            <>
+              <EditorModel v-model={scope.searchParam.use_formula} title="用料量公式编辑器" />
+            </>
+          );
+        }
       }
     },
     {
@@ -66,10 +80,15 @@ export const useHooks = (t?: any) => {
       title: "单价公式",
       basicinfo: {
         el: "input",
-        order: 12,
+        // order: 12,
         span: 6,
-        editable: ALLOW_EDIT_STATE,
-        props: { type: "textarea", rows: 3 }
+        render: (scope: any) => {
+          return (
+            <>
+              <EditorModel v-model={scope.searchParam.price_formula} title="单价公式编辑器" />
+            </>
+          );
+        }
       }
     }
   ];
@@ -106,7 +125,7 @@ export const useHooks = (t?: any) => {
       return;
     }
     const delArr = checkDate.map((item: any) => {
-      return { formulaid: parseInt(item.formulaid), formulakind: item.formulakind };
+      return { formulaid: parseInt(item.formulaid) };
     });
     ElMessageBox.confirm("是否确定要删除吗?", "询问", {
       confirmButtonText: "是",
@@ -114,7 +133,7 @@ export const useHooks = (t?: any) => {
       type: "warning"
     })
       .then(() => {
-        DeleteMattressFormula({ list: delArr }).then(() => {
+        DeleteSoftBedFormula({ list: delArr }).then(() => {
           ElMessage.success("删除成功!");
           state.VxeTableRef?.refresh();
         });
@@ -127,54 +146,6 @@ export const useHooks = (t?: any) => {
       });
   };
 
-  /**
-   * @description 弹窗模块:客户选择
-   * @param data 当前数据
-   * @param status 当前订单状态
-   * @returns Promise
-   */
-  const fModelChoseMtrl = (data: any, params: any, label?: string) => {
-    return new Promise((resolve, reject) => {
-      // if (!ALLOW_EDIT_STATE.includes(status)) return;
-
-      let _params = {
-        keyword: "",
-        arg_mtrltype: params.mtrltype,
-        arg_pricelistid: params.pricelistid
-      };
-      state.MtrldefDialogProps = {
-        onSubmit: (res: any) => {
-          // submit
-          console.log("openCustDialog res", res);
-          nextTick(() => {
-            rModelSetMtrl(data, res.value[0]);
-            resolve(1);
-          });
-        },
-        onCancel: (error: any) => {
-          // cancel 回调
-          console.log("openCustDialog error", error);
-        }
-      };
-      state.MtrldefDialogRef.show(_params, label);
-    });
-  };
-
-  /**
-   * @description 数据赋值: 联系人
-   * @param data 当前数据
-   * @param item 当前选择的数据
-   */
-  const rModelSetMtrl = (data: any, item: any) => {
-    data.default_mtrlid = Number(item.mtrlid);
-    data.default_mtrlname = item.name;
-  };
-
-  const rModelClearMtrl = (data: any) => {
-    data.default_mtrlid = 0;
-    data.default_mtrlname = "";
-  };
-
   return {
     ...toRefs(state),
     columns,

+ 4 - 5
JLHWEB/src/views/quote/mattressQuote/detail.vue

@@ -739,7 +739,7 @@
             <el-button type="primary" @click="toAddMx_subSpecs">{{ t("common.addText") }}</el-button>
             <el-button type="danger" @click="toDelMx_subSpecs">{{ t("common.delText") }}</el-button>
           </el-space>
-          <el-space wrap v-else-if="!LjDetailRef._mainData.parentid && Number(LjDetailRef._mainData.flag) == 1">
+          <el-space wrap v-else-if="!LjDetailRef._mainData.parentid">
             <template v-if="!editSubSpecs">
               <el-button type="primary" @click="toEdit_subSpecs">{{ t("common.editText") }}</el-button>
             </template>
@@ -2077,6 +2077,7 @@ const save_subSpecs = async () => {
             router.replace("/mattressQuote");
           }
           loadingStatus.save = false;
+          editSubSpecs.value = false;
         })
         .catch(error => {
           loadingStatus.save = false;
@@ -3285,8 +3286,7 @@ const editSubSpecs = ref(false);
 
 const toEdit_subSpecs = () => {
   editSubSpecs.value = true;
-
-  tableProps_subSpecs.value.editConfig.enabled = true;
+  tableProps_subSpecs.value.editConfig.enabled = editSubSpecs.value;
 };
 
 const toCancel_subSpecs = () => {
@@ -3296,8 +3296,7 @@ const toCancel_subSpecs = () => {
 
 const toSave_subSpecs = async () => {
   await save_subSpecs();
-
-  editSubSpecs.value = false;
+  tableProps_subSpecs.value.editConfig.enabled = editSubSpecs.value;
 };
 
 const gotoMainMattress = () => {

+ 15 - 0
JLHWEB/src/views/quote/mattressQuote/hooks/index.tsx

@@ -4843,6 +4843,21 @@ export const useHooks = (t?: any) => {
     },
     {
       title: "侧覆cm",
+      field: "sidecover",
+      datatype: "number",
+      editRender: {},
+      editColRender: (scope: any) => {
+        // const { $table, column, row, status } = scope;
+        // const _disabled = !(
+        //   (row.if_inputqty == 0 && [50, 51, 52, 53, 54, 104, 114, 11, 14, 32, 33].includes(row.formulakind)) ||
+        //   row.formulakind == 202 ||
+        //   row.formulakind == 203
+        // );
+        return <el-input v-model={scope.row.sidecover} type="number"></el-input>;
+      }
+    },
+    {
+      title: "厚度cm",
       field: "thickness",
       datatype: "number",
       editRender: {},

+ 15 - 1
JLHWEB/src/views/quote/softbedQuote/detail.vue

@@ -91,6 +91,8 @@
   />
   <ErpMtrlPriceDialog ref="ErpMtrlPriceDialogRef" v-bind="ErpMtrlPriceDialogProps" />
   <SoftBedTemplateDialog ref="SoftBedTemplateDialogRef" v-bind="SoftBedTemplateDialogProps" />
+  <!-- <FormulaEditorDialog ref="formulaEditorRef" @confirm="handleFormulaConfirm" /> -->
+  <FormulaEditor ref="sharedFormulaEditorRef" @confirm="handleFormulaConfirm" />
 </template>
 
 <script setup lang="tsx" name="softBedQuoteDetail">
@@ -106,6 +108,8 @@ import { useUserStore } from "@/stores/modules/user";
 import BedConfigModal from "./components/BedConfigModal.vue";
 import ErpMtrlPriceDialog from "@/views/system/selector/erpMtrlPrice/index.vue";
 import SoftBedTemplateDialog from "@/views/system/selector/softbedTemplate/index.vue";
+import FormulaEditorDialog from "@/views/system/formula-editor/index.vue";
+import FormulaEditor from "@/views/system/formula-editor/index.vue";
 import { usePageRouter } from "@/hooks/usePageRouter";
 
 const { t } = useI18n();
@@ -117,6 +121,8 @@ const {
   VxeTableHeadBoardMxRef,
   VxeTableNightStandMxRef,
   VxeTableBedFrameMxRef,
+  formulaEditorRef,
+  sharedFormulaEditorRef,
   columns,
   columnsMx,
   softBed,
@@ -144,7 +150,9 @@ const {
   onCAudit,
   onDelete,
   onConfirmConfigureDialog,
-  GetSoftBedFormulaMapper
+  GetSoftBedFormulaMapper,
+  openSharedFormulaEditor,
+  handleFormulaConfirm
 } = useHooks(t);
 const { CheckPower, CheckOption, buttonNew, buttonDefault } = useAuthButtons(t);
 const { pageRefresh } = usePageRouter();
@@ -221,6 +229,9 @@ const tableProps_mx = ref({
   },
   mouseConfig: {
     selected: true
+  },
+  cellClick: (data: any) => {
+    console.log(data);
   }
 });
 
@@ -462,6 +473,9 @@ const funcAfterMound = async (data: any) => {
   detail_getData(initParams.value);
   GetSoftBedFormulaMapper();
 };
+
+// 返回绑定的事件
+const tableEvents = {};
 </script>
 <style lang="scss">
 .select-text-right {

+ 135 - 37
JLHWEB/src/views/quote/softbedQuote/hooks/index.tsx

@@ -11,6 +11,7 @@ import { cloneDeep } from "lodash-es";
 import { getCurrentRecords } from "@/utils/index";
 import ErpMtrlPriceSelect from "@/views/system/selector/erpMtrlPrice/select.vue";
 import { useUserStore } from "@/stores/modules/user";
+import FormulaEditor from "@/views/system/formula-editor/index.vue";
 interface defaultState {
   /**
    * @description 单据当前状态
@@ -36,6 +37,22 @@ interface defaultState {
    * @description 详情页明细表格Ref
    */
   VxeTableBedFrameMxRef: any;
+  /**
+   * @description 公式编辑弹窗Ref
+   */
+  formulaEditorRef: any;
+  /**
+   * @description 当前编辑的行数据
+   */
+  currentEditRow: any;
+  /**
+   * @description 当前编辑的列
+   */
+  currentEditCol: any;
+  /**
+   * @description 共享公式编辑器Ref
+   */
+  sharedFormulaEditorRef: any;
   /**
    *
    */
@@ -103,6 +120,10 @@ export const useHooks = (t?: any) => {
     VxeTableHeadBoardMxRef: null,
     VxeTableBedFrameMxRef: null,
     VxeTableNightStandMxRef: null,
+    formulaEditorRef: null,
+    currentEditRow: null,
+    currentEditCol: null,
+    sharedFormulaEditorRef: null,
     softBed: {},
     headBoardMx: [],
     nightStandMx: [],
@@ -297,13 +318,24 @@ export const useHooks = (t?: any) => {
     {
       field: "mtrlmode",
       title: "物料规格",
-      enum: async () => {
-        const data = (await GetSoftBedMtrlmodeMapper()).datatable;
-        return data;
-      },
+      // enum: async () => {
+      //   const data = (await GetSoftBedMtrlmodeMapper()).datatable;
+      //   return data;
+      // },
       basicinfo: {
-        el: "select",
+        el: "input",
         editable: ALLOW_EDIT_STATE,
+        props: {
+          placeholder: "请输入规格,格式如:长*宽(例如:100*200 或 100 * 200)"
+        },
+        rules: [
+          {
+            required: true,
+            pattern: new RegExp(/^\d+\s*\*\s*\d+$/),
+            message: "格式不正确,请使用 长*宽 格式(数字),如:100*200 或 100 * 200",
+            trigger: "blur"
+          }
+        ],
         span: 1,
         row: 1,
         order: 8,
@@ -831,19 +863,19 @@ export const useHooks = (t?: any) => {
           8: "bedframeConfigOptions"
         };
         const targetArray = partTypes[row.has_type] || "headboardConfigOptions";
-
-        const options = state[targetArray]?.map(item => <el-option key={item.pzid} label={item.pzname} value={item} />) || [];
-
+        // const options = state[targetArray]?.map(item => <el-option key={item.pzid} label={item.pzname} value={item} />) || [];
         return (
-          <el-select
+          <el-autocomplete
             v-model={row.pzname}
             disabled={_disabled}
-            valueKey={"pzid"}
             clearable={true}
-            onChange={val => fModelChosePzName(row, val)}
-          >
-            {options}
-          </el-select>
+            fetch-suggestions={(queryString, cb) => {
+              const results =
+                state[targetArray]?.filter(item => item.pzname?.toLowerCase().includes(queryString.toLowerCase())) || [];
+              cb(results);
+            }}
+            onSelect={val => fModelChosePzName(row, val)}
+          />
         );
       }
     },
@@ -974,7 +1006,19 @@ export const useHooks = (t?: any) => {
     },
     {
       field: "use_formula",
-      title: "用料量公式"
+      title: "用料量公式",
+      editRender: {},
+      editColRender: (scope: any) => {
+        const { $table, column, row, status } = scope;
+        return (
+          <el-input
+            v-model={scope.row.use_formula}
+            readonly
+            placeholder="点击编辑公式"
+            onClick={() => openSharedFormulaEditor(scope.row.use_formula, row, column)}
+          />
+        );
+      }
     },
     {
       field: "use_formula_str",
@@ -1013,7 +1057,19 @@ export const useHooks = (t?: any) => {
     },
     {
       field: "price_formula",
-      title: "单价公式"
+      title: "单价公式",
+      editRender: {},
+      editColRender: (scope: any) => {
+        const { $table, column, row, status } = scope;
+        return (
+          <el-input
+            v-model={scope.row.price_formula}
+            readonly
+            placeholder="点击编辑公式"
+            onClick={() => openSharedFormulaEditor(scope.row.price_formula, row, column)}
+          />
+        );
+      }
     },
     {
       field: "price_formula_str",
@@ -1488,25 +1544,39 @@ export const useHooks = (t?: any) => {
 
   const toAddMx = async (tableRef: any) => {
     const { _mainData } = state.LjDetailRef;
-    const $table = tableRef.element;
-    if ($table) {
-      // 新增
-      const records = {
-        softbed_id: _mainData.softbed_id,
-        has_type: getHasType(tableRef),
-        mtrlname: "",
-        mtrlcode: "",
-        mtrlmode: "",
-        unit: "",
-        allow_edit: 0,
-        cutting_length: 0,
-        cutting_width: 0,
-        cutting_qty: 0,
-        loss_rate: 0,
-        price: 0
-      };
-      const { row } = await $table.insertAt(records, -1);
-      await $table.setCurrentRow(row);
+
+    // 检测是否有勾
+    const has_type = getHasType(tableRef);
+    if (
+      (has_type === 1 && _mainData.has_headboard === 1) ||
+      (has_type === 2 && _mainData.has_nightstand === 1) ||
+      (has_type === 4 && _mainData.has_bedframe === 1)
+    ) {
+      const $table = tableRef.element;
+      if ($table) {
+        // 新增
+        const records = {
+          softbed_id: _mainData.softbed_id,
+          has_type: has_type,
+          mtrlname: "",
+          mtrlcode: "",
+          mtrlmode: "",
+          unit: "",
+          allow_edit: 0,
+          cutting_length: 0,
+          cutting_width: 0,
+          cutting_qty: 0,
+          loss_rate: 0,
+          price: 0
+        };
+        const { row } = await $table.insertAt(records, -1);
+        await $table.setCurrentRow(row);
+      }
+    } else {
+      ElMessage({
+        type: "info",
+        message: "请先勾选对应类型"
+      });
     }
   };
 
@@ -1522,7 +1592,7 @@ export const useHooks = (t?: any) => {
       })
       .catch((e: TypeError) => {
         ElMessage({
-          type: "info",
+          type: "warning",
           message: "操作取消"
         });
       });
@@ -1601,6 +1671,32 @@ export const useHooks = (t?: any) => {
     data.pzname = val.pzname;
   };
 
+  /**
+   * 打开共享公式编辑器
+   */
+  const openSharedFormulaEditor = (formula: string, row: any, col: any) => {
+    state.currentEditRow = row;
+    state.currentEditCol = col;
+    state.sharedFormulaEditorRef?.show?.(0, false, formula);
+  };
+
+  /**
+   * 处理公式确认
+   */
+  const handleFormulaConfirm = (payload: { formula: string; valid: boolean; parameters: any[] }) => {
+    if (payload.valid && state.currentEditRow && state.currentEditCol) {
+      state.currentEditRow[state.currentEditCol.field] = payload.formula;
+    }
+  };
+
+  /**
+   * 打开部件配置弹窗
+   */
+  const onOpenEditFormulaDialog = async () => {
+    const { _mainData } = state.LjDetailRef;
+    console.log("sadfasdfasfasdfasfda");
+  };
+
   return {
     ...toRefs(state),
     columns,
@@ -1615,6 +1711,8 @@ export const useHooks = (t?: any) => {
     onCopyQuote,
     onShowFormula,
     onConfirmConfigureDialog,
-    GetSoftBedFormulaMapper
+    GetSoftBedFormulaMapper,
+    openSharedFormulaEditor,
+    handleFormulaConfirm
   };
 };

+ 246 - 236
JLHWEB/src/views/system/formula-editor/editor.vue

@@ -11,10 +11,11 @@
               v-wave
               class="operator-btn"
               :title="op.name"
-              @click="insertOperator(op.value)"
+              @click="() => insertOperator(op.value)"
             >
               <span class="symbol">{{ op.symbol }}</span>
             </el-button>
+
             <el-dropdown @command="insertFunction" trigger="click">
               <el-button type="primary" class="func-btn">
                 <span>函数列表</span>
@@ -38,43 +39,33 @@
             resize="none"
             class="editor-input"
             spellcheck="false"
-          >
-          </el-input>
-
-          <!-- <div class="action-buttons">
-            <el-button type="default" @click="handleReset">清空</el-button>
-            <el-button type="warning" @click="handleCheck">检查公式</el-button>
-            <el-button type="primary" @click="handleConfirm">确认</el-button>
-          </div> -->
+          />
         </div>
       </el-col>
 
       <!-- 右侧参数面板 -->
       <el-col :xs="24" :span="8" class="right-panel">
         <div class="param-tree">
-          <!-- <div class="header">
-            <span>参数选择</span>
-          </div> -->
-
           <el-input
             v-model="filterText"
+            size="default"
             placeholder="搜索参数..."
             clearable
             class="search-box"
-            @input="handleSearchInput"
-            @keyup.enter="handleSearchEnter"
-            @clear="handleSearchClear"
+            @input="onFilterInput"
+            @keyup.enter="onFilterEnter"
+            @clear="onFilterClear"
           />
 
           <div class="tree-container">
-            <el-tree
+            <el-tree-v2
               ref="treeRef"
-              :data="props.mockParameters"
+              :data="treeData"
               :props="defaultProps"
               :filter-node-method="filterNode"
               @node-click="handleNodeClick"
-              default-expand-all
               node-key="text"
+              :height="treeHeight"
             />
           </div>
         </div>
@@ -83,201 +74,231 @@
   </div>
 </template>
 
-<script setup lang="ts">
-import { ref, computed, watch, nextTick } from "vue";
+<script lang="ts" setup>
+import { ref, watch, nextTick, computed, onMounted, onUnmounted } from "vue";
 import { ElMessage, ElTree } from "element-plus";
-import { debounce, cloneDeepWith, isObject } from "lodash-es";
+import { debounce } from "lodash-es";
 import { pinyin } from "pinyin-pro";
 import { FormulaCheck } from "@/api/modules/basicinfo";
 
+/**
+ *
+ */
 interface TreeNode {
   text: string;
-  value?: number;
+  value?: number | string | null;
   children?: TreeNode[];
 }
-interface FormulaEditorProps {
-  /** 初始公式值 */
+
+interface Props {
   modelValue: string;
-  /** 参数树数据 */
-  mockParameters: TreeNode[];
+  treeData: TreeNode[];
 }
 
-// Props定义
-const props = withDefaults(defineProps<FormulaEditorProps>(), {
+const props = withDefaults(defineProps<Props>(), {
   modelValue: "",
-  mockParameters: () => [] as TreeNode[]
+  treeData: () => []
 });
 
-// Emits定义
 const emits = defineEmits<{
-  "update:modelValue": [value: string]; // v-model标准事件
+  "update:modelValue": [v: string];
 }>();
 
-// 响应式状态
+// 引用与状态
+const editorRef = ref<any | null>(null);
+const treeRef = ref<InstanceType<typeof ElTree> | null>(null);
 const formulaValue = ref<string>(props.modelValue);
-const filterText = ref("");
-const treeRef = ref<InstanceType<typeof ElTree>>();
-// 调整默认props配置
-const defaultProps = {
-  children: "children",
-  label: "text" // 与ElementUI Tree组件默认字段对齐
-};
-// 监听本地修改
-watch(formulaValue, newVal => {
-  emits("update:modelValue", newVal);
+const filterText = ref<string>("");
+const treeHeight = ref<number>(200); // 默认高度
+
+// 监听v-model同步
+watch(formulaValue, val => {
+  emits("update:modelValue", val);
 });
 
-// 常量
+/**
+ * 左边区域
+ */
 const operatorMap = ref([
-  {
-    value: "+",
-    symbol: "+",
-    name: "加"
-  },
-  {
-    value: "-",
-    symbol: "-",
-    name: "减"
-  },
-  {
-    value: "*",
-    symbol: "×",
-    name: "乘"
-  },
-  {
-    value: "/",
-    symbol: "÷",
-    name: "除"
-  },
-  {
-    value: "(",
-    symbol: "(",
-    name: "左括号"
-  },
-  {
-    value: ")",
-    symbol: ")",
-    name: "右括号"
-  },
-  {
-    value: "**",
-    symbol: "^",
-    name: "幂"
-  },
-  {
-    value: "%",
-    symbol: "%",
-    name: "模"
-  }
+  { value: "+", symbol: "+", name: "加" },
+  { value: "-", symbol: "-", name: "减" },
+  { value: "*", symbol: "×", name: "乘" },
+  { value: "/", symbol: "÷", name: "除" },
+  { value: "(", symbol: "(", name: "左括号" },
+  { value: ")", symbol: ")", name: "右括号" },
+  { value: "**", symbol: "^", name: "幂" },
+  { value: "%", symbol: "%", name: "模" }
 ]);
 const functions = ["SUM", "AVG", "IF", "MAX", "MIN"];
 
+// 插入运算符
+const insertOperator = (op: string) => handleInsertFormula(op);
+// 插入函数(光标定位到括号内)
+const insertFunction = (func: string) => handleInsertFormula(`${func}()`, { cursorOffset: -1 });
+
+// 重置公式
+const reset = () => {
+  formulaValue.value = "";
+};
+
+// 校验公式
+const handleCheck = async (): Promise<boolean> => {
+  if (!formulaValue.value?.trim()) {
+    // ElMessage.warning("请先输入公式");
+    return true;
+  }
+
+  try {
+    const result = await FormulaCheck({
+      formula: formulaValue.value
+    });
+
+    if (result) {
+      ElMessage.success("公式检查通过");
+      return true;
+    }
+    return false;
+  } catch (error) {
+    return false;
+  }
+};
+
+/**
+ * 右边区域
+ */
+const defaultProps = {
+  value: "value",
+  label: "text",
+  children: "children"
+};
+
+// 搜索优化:扁平索引 + 拼音缓存
+const pinyinCache = new Map<string, string>();
+// 构建扁平索引(提升搜索性能)
+const buildIndex = (list: TreeNode[], parentPath: string[] = []) => {
+  const result: { node: TreeNode; path: string[] }[] = [];
+  for (const n of list) {
+    const currentPath = parentPath.concat(n.text);
+    result.push({ node: n, path: currentPath });
+    if (n.children && n.children.length) {
+      result.push(...buildIndex(n.children, currentPath));
+    }
+  }
+  return result;
+};
+
+// 节点过滤方法(使用缓存提升性能)
 const filterNode = (value: string, data: TreeNode, node: any): boolean => {
-  // 空搜索时保留有效结构
+  // 空搜索:保留有效节点(有值或有子节点)
   if (!value) {
-    // 空搜索时:保留所有有效节点及其祖先路径
-    const selfValid = !!data.value || data.children !== undefined;
-    const keepForStructure = node.parent?.expanded || selfValid;
-    return keepForStructure;
+    const selfValid = !!data.value || !!(data.children && data.children.length);
+    return selfValid;
   }
 
-  // 核心匹配逻辑(不依赖pinyinFilterTree的树裁剪)
-  const isSelfMatch = [data.text].some(
-    text =>
-      text &&
-      (text.includes(value) ||
-        pinyin(text, { toneType: "none", type: "array" }).join("").includes(value.toLowerCase()) ||
-        pinyin(text, { pattern: "first", type: "array", toneType: "none" }).join("").includes(value.toLowerCase()))
-  );
+  const q = value.trim().toLowerCase();
 
-  // 子节点匹配状态(需要展开父节点)
-  const hasChildMatch = node.childNodes?.some(child => child.data && filterNode(value, child.data, child));
+  // 文本与拼音匹配检查
+  const text = data.text || "";
+  const cachedPinyin = pinyinCache.get(text) ?? pinyin(text, { toneType: "none", type: "array" }).join("").toLowerCase();
+  if (!pinyinCache.has(text)) pinyinCache.set(text, cachedPinyin);
 
-  // 保留逻辑:自身匹配或子节点匹配
-  const shouldShow = isSelfMatch || hasChildMatch;
+  const selfMatch = (text && text.toLowerCase().includes(q)) || (cachedPinyin && cachedPinyin.includes(q));
 
-  return shouldShow;
-};
+  // 子节点匹配检查
+  if (selfMatch) return true;
+  if (data.children && data.children.length) {
+    return data.children.some(child => filterNode(value, child, node));
+  }
 
-// 优化有效性判断
-const isNodeValid = (node: TreeNode): boolean => {
-  // 有效条件:有code 或 有有效子节点
-  return !!node.value || (node.children?.some(isNodeValid) ?? false);
+  return false;
 };
 
-// 搜索处理逻辑
-const handleSearchInput = debounce((value: string) => {
-  treeRef.value?.filter(value);
-}, 300);
+// 防抖处理搜索输入
+const doFilter = debounce((val: string) => {
+  treeRef.value?.filter?.(val ?? "");
+}, 200);
 
-// 回车键立即搜索
-const handleSearchEnter = () => {
-  treeRef.value?.filter(filterText.value);
+const onFilterInput = (val: string) => {
+  doFilter(val);
 };
-
-// 清空时立即刷新
-const handleSearchClear = () => {
-  treeRef.value?.filter("");
+const onFilterEnter = () => {
+  treeRef.value?.filter?.(filterText.value ?? "");
+};
+const onFilterClear = () => {
+  filterText.value = "";
+  treeRef.value?.filter?.("");
 };
 
-const insertOperator = (op: string) => {
-  handleInsertFormula(op);
+// 插入公式辅助方法(精确控制光标位置)
+const getTextarea = (): HTMLTextAreaElement | null => {
+  const el = (editorRef.value as any)?.$el ?? null;
+  if (!el) return null;
+  return el.querySelector("textarea");
 };
 
-const insertFunction = (func: string) => {
-  handleInsertFormula(`${func}()`, -1);
+const handleInsertFormula = async (insertText: string, options?: { cursorOffset?: number }) => {
+  if (!insertText) return;
+  await nextTick();
+  const textarea = getTextarea();
+  if (!textarea) {
+    // 降级处理:直接拼接到末尾
+    formulaValue.value = formulaValue.value + insertText;
+    return;
+  }
+  const start = textarea.selectionStart ?? textarea.value.length;
+  const end = textarea.selectionEnd ?? textarea.value.length;
+
+  // 插入文本
+  formulaValue.value = formulaValue.value.slice(0, start) + insertText + formulaValue.value.slice(end);
+
+  await nextTick();
+  // 调整光标位置
+  const offset = options?.cursorOffset ?? 0;
+  const newPos = start + insertText.length + offset;
+  try {
+    textarea.setSelectionRange(newPos, newPos);
+    textarea.focus();
+  } catch (err) {
+    textarea.focus();
+  }
 };
 
+// 点击树节点插入参数
 const handleNodeClick = (data: TreeNode) => {
-  if (!data.value) return;
+  if (data.children?.length < 100) return;
   handleInsertFormula(`【${data.text}】`);
 };
 
-const handleInsertFormula = (data: string, pm: number = 0) => {
-  if (!data) return;
-  const textarea = document.querySelector(".editor-input textarea") as HTMLTextAreaElement;
-  if (!textarea) return;
-  const start = textarea.selectionStart;
-  const end = textarea.selectionEnd;
-  // 更新公式值
-  formulaValue.value = formulaValue.value.slice(0, start) + data + formulaValue.value.slice(end);
-  // 更新光标位置
+// 动态计算树高度
+const calculateTreeHeight = () => {
   nextTick(() => {
-    // 计算新光标位置(插入内容末尾)
-    const newPos = start + data.length;
-    textarea.setSelectionRange(newPos + pm, newPos + pm);
-    textarea.focus();
+    const treeContainer = document.querySelector(".tree-container") as HTMLElement;
+    if (treeContainer) {
+      // 获取tree-container的实际高度,减去可能的padding/margin
+      const containerHeight = treeContainer.clientHeight;
+      // 设置一个最小高度,确保树至少有200px高
+      treeHeight.value = Math.max(containerHeight, 200);
+    }
   });
 };
 
-const handleReset = () => {
-  formulaValue.value = "";
+// 监听窗口大小变化
+const handleResize = () => {
+  calculateTreeHeight();
 };
 
-const handleCheck = async (): Promise<boolean> => {
-  if (!formulaValue.value) {
-    ElMessage.warning("请先输入公式");
-    return false;
-  }
-
-  try {
-    const result = await FormulaCheck({
-      formula: formulaValue.value
-    });
+onMounted(() => {
+  calculateTreeHeight();
+  window.addEventListener("resize", handleResize);
+});
 
-    if (result) {
-      ElMessage.success("公式检查通过");
-      return true;
-    }
-    return false;
-  } catch (error) {
-    return false;
-  }
-};
+onUnmounted(() => {
+  window.removeEventListener("resize", handleResize);
+});
 
-// 暴露方法供父组件调用
+// 暴露方法给父组件
 defineExpose({
-  reset: handleReset,
+  reset,
   check: handleCheck
 });
 </script>
@@ -286,111 +307,100 @@ defineExpose({
 .formula-container {
   height: 100%;
   width: 100%;
-  min-height: 510px;
   --editor-border: #dcdfe6;
   --panel-bg: #f8f9fa;
 
   .formula-editor {
     height: calc(100% - 20px);
     margin-top: 12px;
+    display: flex;
 
     .left-panel {
+      width: 100%;
+      height: 100%;
+
       .editor-area {
-        // border-color: var(--editor-border);
-        // box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+        display: flex;
+        flex-direction: column;
+        padding: 8px;
       }
 
       .operator-toolbar {
         gap: 12px;
-        .operator-btn {
-          min-width: 36px;
-          padding: 8px 12px;
-        }
+        display: flex;
+        flex-wrap: wrap;
+        padding-bottom: 12px;
       }
-    }
 
-    .right-panel {
-      .param-tree {
-        border-color: var(--editor-border);
-        padding: 8px;
-
-        .header {
-          padding: 12px 16px;
-          font-size: 14px;
-          background: white;
-        }
-
-        .el-tree-node__content:hover {
-          background: rgba(64, 158, 255, 0.08);
-        }
+      .operator-btn {
+        min-width: 36px;
+        padding: 8px 12px;
       }
-    }
 
-    .right-panel {
-      .search-box {
-        padding: 0 12px;
-        flex-shrink: 0;
-      }
+      .editor-input {
+        border-radius: 4px;
+        transition: border-color 0.2s;
 
-      .tree-container {
-        .el-tree {
-          padding: 0px 12px;
+        &:focus-within {
+          border-color: #4096ff;
+          box-shadow: 0 0 0 2px rgba(64, 150, 255, 0.2);
         }
       }
     }
-  }
 
-  .editor-area {
-    flex: 1;
-    display: flex;
-    flex-direction: column;
-    // border: 1px solid var(--el-border-color);
-    // border-radius: 4px;
-    // background: var(--el-bg-color);
-    padding: 8px;
-  }
+    .right-panel {
+      width: 100%;
+      height: 100%;
 
-  .param-tree {
-    flex: 1;
-    display: flex;
-    flex-direction: column;
-    // border: 1px solid var(--el-border-color);
-    // border-radius: 4px;
-    // background: var(--el-bg-color);
-    height: 100%;
-
-    .header {
-      padding: 16px;
-      font-weight: 500;
-    }
+      .param-tree {
+        padding: 8px;
+        display: flex;
+        flex-direction: column;
+        height: 100%;
 
-    .tree-container {
-      flex: 1;
-      min-height: 0; /* 关键修复 */
-      overflow: hidden;
+        .search-box {
+          flex-shrink: 0;
+          margin-bottom: 8px;
+          border-radius: 4px;
+        }
 
-      .el-tree {
-        height: 100%;
-        :deep(.el-tree-node__content) {
-          padding: 6px 0;
+        .tree-container {
+          flex: 1;
+          min-height: 0;
+          /* 允许垂直滚动,禁止水平滚动 */
+          overflow-y: auto;
+          overflow-x: hidden;
+          /* 添加边框样式 */
+          border: 1px solid var(--editor-border);
+          border-radius: 4px;
+
+          /* 优化滚动条样式 */
+          &::-webkit-scrollbar {
+            width: 6px;
+          }
+          &::-webkit-scrollbar-thumb {
+            background-color: #ddd;
+            border-radius: 3px;
+          }
+          &::-webkit-scrollbar-track {
+            background-color: #f5f5f5;
+          }
+
+          .el-tree {
+            padding: 0 12px;
+            height: 100%;
+
+            :deep(.el-tree-node__content) {
+              padding: 6px 0;
+              cursor: pointer;
+              &:hover {
+                background-color: #f5f7fa;
+              }
+            }
+          }
         }
       }
     }
   }
-
-  .operator-toolbar {
-    display: flex;
-    gap: 8px;
-    flex-wrap: wrap;
-    padding-bottom: 16px;
-  }
-
-  .action-buttons {
-    margin-top: auto;
-    padding-top: 16px;
-    display: flex;
-    gap: 12px;
-    justify-content: flex-end;
-  }
 }
 </style>

+ 83 - 0
JLHWEB/src/views/system/formula-editor/editorModel.vue

@@ -0,0 +1,83 @@
+<template>
+  <div class="formula-editor-with-model">
+    <!-- 显示当前公式值的输入框 -->
+    <el-input v-model="displayValue" :type="type" :rows="3" placeholder="点击编辑公式" readonly @click="openFormulaEditor">
+    </el-input>
+
+    <!-- 公式编辑器弹窗 -->
+    <FormulaEditorDialog ref="formulaEditorRef" :title="title" @confirm="handleFormulaConfirm" />
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ref, watch, computed } from "vue";
+import { Edit } from "@element-plus/icons-vue";
+import FormulaEditorDialog from "./index.vue";
+
+interface Props {
+  modelValue?: string;
+  title?: string;
+  type?: string;
+}
+
+const props = withDefaults(defineProps<Props>(), {
+  modelValue: "",
+  title: "公式编辑器",
+  type: "textarea"
+});
+
+const emit = defineEmits<{
+  (e: "update:modelValue", value: string): void;
+}>();
+
+// 组件引用
+const formulaEditorRef = ref<InstanceType<typeof FormulaEditorDialog>>();
+
+// 显示值(用于输入框显示)
+const displayValue = computed({
+  get: () => props.modelValue,
+  set: value => emit("update:modelValue", value)
+});
+
+// 打开公式编辑器
+const openFormulaEditor = () => {
+  formulaEditorRef.value?.show(1, false, props.modelValue);
+};
+
+// 处理公式确认
+const handleFormulaConfirm = ({ formula, valid, parameters }: { formula: string; valid: boolean; parameters: any[] }) => {
+  if (valid) {
+    displayValue.value = formula;
+  }
+};
+
+// 暴露方法给父组件
+const show = (type = 0, refresh = false, formula = "") => {
+  formulaEditorRef.value?.show(type, refresh, formula);
+};
+
+const hide = () => {
+  formulaEditorRef.value?.hide();
+};
+
+defineExpose({
+  show,
+  hide
+});
+</script>
+
+<style lang="scss" scoped>
+.formula-editor-with-model {
+  width: 100%;
+
+  :deep(.el-textarea) {
+    .el-textarea__inner {
+      cursor: pointer;
+
+      &:hover {
+        border-color: var(--el-color-primary);
+      }
+    }
+  }
+}
+</style>

+ 99 - 66
JLHWEB/src/views/system/formula-editor/index.vue

@@ -1,25 +1,28 @@
 <template>
   <LjDialog
-    ref="LjSelectorRef"
+    ref="ljDialogRef"
     class="is-selector lj-selector"
-    v-bind="{
-      ...drawerDefineProp
-    }"
+    :draggable="drawerProps.draggable"
+    :overflow="drawerProps.overflow"
+    :width="drawerProps.width"
+    :modal-class="drawerProps.modalClass"
     :modal="false"
     :style="{ height: '60%' }"
+    @close="onDialogClose"
   >
     <template #header>
       <div class="flx-1">
         <span class="text-h5-b">{{ props.title }}</span>
       </div>
     </template>
+
     <div class="flx-col h-full">
-      <LjHeaderMenu :update="dialogVisible" :data="initParams" :action="btnGroup" />
-      <LjFoldLayoutDouble v-bind="showLayout" class="flx-1 overflow-hidden">
+      <LjHeaderMenu :update="isDialogVisible" :data="initParams" :action="btnGroup" />
+      <LjFoldLayoutDouble v-bind="layoutConfig" class="flx-1 overflow-hidden">
         <template #secondMain>
           <div class="flx h-full">
             <div class="flx-col w-full">
-              <FormulaEditor ref="formulaEditorRef" v-model="localFormula" :mock-parameters="mockParameters" />
+              <FormulaEditor ref="formulaEditorRef" v-model="localFormula" :tree-data="treeData" />
             </div>
           </div>
         </template>
@@ -27,115 +30,146 @@
     </div>
   </LjDialog>
 </template>
-<script setup lang="ts">
-import { ref, computed, onMounted, onBeforeUnmount, nextTick, watch } from "vue";
+
+<script lang="ts" setup>
+import { ref, reactive, nextTick, onMounted } from "vue";
+import { useI18n } from "vue-i18n";
 import LjDialog from "@/components/LjDialog/index.vue";
 import LjFoldLayoutDouble from "@/components/LjFoldLayoutDouble/index.vue";
 import FormulaEditor from "./editor.vue";
-import { GetFormulaVarList, FormulaCheck } from "@/api/modules/basicinfo";
+import { GetFormulaVarList } from "@/api/modules/basicinfo";
 import { useAuthButtons } from "@/hooks/useAuthButtons";
-import { useI18n } from "vue-i18n";
 
 const { t } = useI18n();
 const { buttonDefault } = useAuthButtons(t);
 
 const props = defineProps({
-  title: {
-    type: String,
-    default: "公式编辑器"
-  }
+  title: { type: String, default: "公式编辑器" }
 });
 
-const emit = defineEmits(["confirm"]);
-const localFormula = ref<string>("");
-const mockParameters = ref([]);
+const emit = defineEmits<{
+  (e: "confirm", payload: { formula: string; valid: boolean; parameters: any[] }): void;
+}>();
 
-const LjSelectorRef = ref();
-const dialogVisible = ref(false);
+interface TreeNode {
+  text: string;
+  value?: number | string | null;
+  children?: TreeNode[];
+}
 
+// ---------- 状态 ----------
+const ljDialogRef = ref();
 const formulaEditorRef = ref();
-/*
- * @description 抽屉默认属性
- */
-const drawerDefineProp = {
+const localFormula = ref<string>("");
+const requestType = ref<number>(0);
+const treeData = ref<TreeNode[]>([]);
+const isDialogVisible = ref(false);
+const initParams = ref<any>();
+
+// 抽屉配置(用 reactive 明确类型)
+const drawerProps = reactive({
   draggable: true,
   overflow: true,
   width: "60%",
   modalClass: "lj-file-dialog"
-};
-const showLayout = ref<any>(false);
-const initParams = ref<any>();
-const btnGroup = ref<any>([
+});
+
+// 布局配置(命名语义化)
+const layoutConfig = ref<Record<string, any>>({
+  // 这里放置需要传给 LjFoldLayoutDouble 的配置项(若无可保持空对象)
+});
+
+// 按钮组
+const btnGroup = ref([
   buttonDefault({
     label: "取消",
-    clickFunc: item => {
+    clickFunc: () => {
       hide();
     }
   }),
   buttonDefault({
     label: "清空",
-    clickFunc: item => {
-      formulaEditorRef.value.reset();
+    clickFunc: () => {
+      formulaEditorRef.value?.reset?.();
+      localFormula.value = "";
     }
   }),
   buttonDefault({
     label: "检查公式",
-    clickFunc: item => {
-      formulaEditorRef.value.check();
+    clickFunc: async () => {
+      // 子组件的 check 方法返回 boolean
+      const ok = await formulaEditorRef.value?.check?.();
+      // 提示逻辑由子组件处理(这里仅作为动作触发)
+      return ok;
     }
   }),
   buttonDefault({
     label: "确认",
-    clickFunc: item => {
-      handleConfirm();
+    clickFunc: async () => {
+      await handleConfirm();
     }
   })
 ]);
 
-const handleConfirm = async () => {
-  // 调用子组件检查方法
-  const isValid = await formulaEditorRef.value?.check();
-
-  if (!isValid) {
-    return;
-  }
-
-  // 提交有效公式
-  emit("confirm", localFormula.value);
-  hide();
-};
-
+// ---------- 方法 ----------
 const getFormulaVarList = async () => {
-  const res = (await GetFormulaVarList()) as any;
-  mockParameters.value = res.recursionList;
+  try {
+    const res: any = await GetFormulaVarList({ list: [], type: 1 });
+    treeData.value = res?.recursionList ?? [];
+  } catch (err) {
+    treeData.value = [];
+  }
 };
 
-/**
- * @description 展示组件
- * @param params 入参
- * @param activeName 多选时 活动面板入参
- */
-const show = (refresh?: boolean, formula: string = "") => {
-  localFormula.value = formula;
-  LjSelectorRef.value.show(refresh);
+const show = (type = 0, refresh = false, formula = "") => {
+  localFormula.value = formula ?? "";
+  requestType.value = type ?? 0;
+  ljDialogRef.value?.show?.(refresh);
   nextTick(() => {
-    dialogVisible.value = true;
+    isDialogVisible.value = true;
   });
 };
 
-/**
- * @description cancel 取消
- */
 const hide = () => {
-  // 关闭弹窗
-  LjSelectorRef.value.hide();
-  dialogVisible.value = false;
+  ljDialogRef.value?.hide?.();
+  isDialogVisible.value = false;
+};
+
+const onDialogClose = () => {
+  // 当对话框关闭时需要同步状态
+  isDialogVisible.value = false;
+};
+
+const handleConfirm = async () => {
+  // 调用子组件的校验方法
+  let valid = true;
+  if (formulaEditorRef.value?.check) {
+    try {
+      valid = await formulaEditorRef.value.check();
+    } catch (err) {
+      console.warn("公式校验出错:", err);
+      valid = false;
+    }
+  }
+
+  if (!valid) return;
+
+  // 返回更丰富的上下文
+  emit("confirm", {
+    formula: localFormula.value,
+    valid,
+    parameters: treeData.value
+  });
+
+  hide();
 };
 
+// ---------- 生命周期 ----------
 onMounted(() => {
   getFormulaVarList();
 });
 
+// 暴露给父组件使用
 defineExpose({
   show,
   hide
@@ -153,7 +187,6 @@ defineExpose({
   height: 100%;
   display: flex;
   flex-direction: column;
-  // background-color: $color-gray-2;
 
   .el-collapse-item {
     display: flex;