Quellcode durchsuchen

半成品报价前端代码

MY vor 7 Monaten
Ursprung
Commit
bec24a13e4

+ 7 - 0
JLHWEB/src/api/interface/index.ts

@@ -1177,4 +1177,11 @@ export namespace Mattress {
      */
     flag?: number;
   }
+  export interface ReqMultiMattressBcp {
+    list: any[];
+    type?: number;
+  }
+  export interface ResSaveMattressBcp {
+    mattress: any;
+  }
 }

+ 21 - 0
JLHWEB/src/api/modules/quote.ts

@@ -22,3 +22,24 @@ export const SaveMattressAuditing = (params: Mattress.ReqMultiMattress) => {
 export const DelMattress = (params: Mattress.ReqMultiMattress) => {
   return http.post(PORT1 + `/DelMattress`, params);
 };
+
+/**
+ * @name 半成品报价保存
+ */
+export const SaveMattressBcp = (params: Mattress.ReqSaveMattress) => {
+  return http.post<Mattress.ResSaveMattressBcp>(PORT1 + `/SaveMattressBcp`, params);
+};
+
+/**
+ * @name 半成品报价:审核
+ */
+export const AuditMattressBcp = (params: Mattress.ReqMultiMattressBcp) => {
+  return http.post(PORT1 + `/AuditMattressBcp`, params);
+};
+
+/**
+ * @name 半成品报价:删除
+ */
+export const DeleteMattressBcp = (params: Mattress.ReqMultiMattressBcp) => {
+  return http.post(PORT1 + `/DeleteMattressBcp`, params);
+};

+ 14 - 0
JLHWEB/src/api/modules/saleprice.ts

@@ -83,3 +83,17 @@ export const SaveWorkmanShip = (params: SalePrice.ReqSaveWorkmanShip) => {
 export const DeleteWorkmanShip = (params: SalePrice.ReqDeleteWorkmanShip) => {
   return http.post<SalePrice.ResDeleteWorkmanShip>(PORT1 + `/DeleteWorkmanship`, params);
 };
+
+/**
+ * @name 获取 无效物料对应报价查询
+ */
+export const getInvalidMtrlList = (params: any) => {
+  let newParams: any = {};
+  newParams.dsname = "web_invalid_mtrllist";
+  newParams.queryparams = params;
+  params.pageNum && (newParams.pageindex = params.pageNum);
+  params.pageSize && (newParams.pagesize = params.pageSize);
+  delete params.pageNum;
+  delete params.pageSize;
+  return CommonDynamicSelect(newParams, "web_invalid_mtrllist");
+};

+ 9 - 1
JLHWEB/src/enums/dwnameEnum.ts

@@ -105,5 +105,13 @@ export enum DwnameEnum {
   /*
    * @description 床网分区定义
    */
-  configurecodemxlist = "web_configure_codemxlist"
+  configurecodemxlist = "web_configure_codemxlist",
+  /*
+   * @description 半成品报价
+   */
+  semifinprodQuote = "u_semi_finished_product",
+  /**
+   * @description 半成品报价明细
+   */
+  semifinprodQuoteMx = "u_semi_finished_product_mx"
 }

+ 5 - 1
JLHWEB/src/enums/mittEnum.ts

@@ -21,5 +21,9 @@ export enum MittEnum {
   /**
    * @description 床垫报价刷新
    */
-  MattressList = "MattressList"
+  MattressList = "MattressList",
+  /**
+   * @description 床垫半成品报价刷新
+   */
+  MattressBcpList = "MattressBcpList"
 }

+ 5 - 1
JLHWEB/src/languages/modules/zh-cn/menu.json

@@ -153,5 +153,9 @@
   "mattressQuoteAdd": "新建床垫报价",
   "bednetQuote": "床网报价",
   "user": "用户权限",
-  "bednetvar": "变量定义"
+  "bednetvar": "变量定义",
+  "semifinprodQuote": "半成品报价",
+  "semifinprodQuoteDetail": "半成品报价详情",
+  "semifinprodQuoteEdit": "修改半成品垫报价",
+  "semifinprodQuoteAdd": "新建半成品报价"
 }

+ 75 - 0
JLHWEB/src/routers/modules/selmifinprodRouter.ts

@@ -0,0 +1,75 @@
+import type { Menu } from "@/typings/global";
+/**
+ * @argument name 床垫报价
+ */
+export const semifinprodQuoteRouter: Menu.MenuOptions[] = [
+  {
+    path: "/semifinprodQuote",
+    name: "semifinprodQuote",
+    component: "/quote/semifinprodQuote/index",
+    meta: {
+      icon: "Common_Business.png",
+      title: "半成品报价",
+      isLink: "",
+      isHide: false,
+      isFull: false,
+      isAffix: false,
+      isKeepAlive: true,
+      funid: 121
+    },
+    children: [
+      {
+        path: "/semifinprodQuote/detail",
+        name: "semifinprodQuoteDetail",
+        component: "/quote/semifinprodQuote/detail2",
+        meta: {
+          icon: "iconpackage",
+          title: "半成品报价详情",
+          isLink: "",
+          isHide: true,
+          isFull: false,
+          isAffix: false,
+          isKeepAlive: true,
+          funid: 121,
+          activeMenu: "/semifinprodQuote"
+        }
+      },
+      {
+        path: "/semifinprodQuote/new",
+        name: "semifinprodQuoteAdd",
+        component: "/quote/semifinprodQuote/detail2",
+        meta: {
+          icon: "iconuser-01",
+          title: "新增半成品报价",
+          isLink: "",
+          isHide: true,
+          isFull: false,
+          isAffix: false,
+          isKeepAlive: true,
+          funid: 124,
+          activeMenu: "/semifinprodQuote"
+        }
+      },
+      {
+        path: "/semifinprodQuote/edit",
+        name: "semifinprodQuoteEdit",
+        component: "/quote/semifinprodQuote/detail2",
+        meta: {
+          icon: "iconuser-01",
+          title: "修改半成品报价",
+          isLink: "",
+          isHide: true,
+          isFull: false,
+          isAffix: false,
+          isKeepAlive: true,
+          funid: 124,
+          activeMenu: "/semifinprodQuote"
+        }
+      }
+    ]
+    //     }
+    //   ]
+    // }
+    // ]
+  }
+];

+ 9 - 1
JLHWEB/src/stores/modules/auth.ts

@@ -13,6 +13,7 @@ import { baseRouter } from "@/routers/modules/baseRouter";
 import { salePriceRouter } from "@/routers/modules/salePriceRouter";
 import { mattressQtuoteRouter } from "@/routers/modules/mattressQtuoteRouter";
 import { bednetQtuoteRouter } from "@/routers/modules/bednetQtuoteRouter";
+import { semifinprodQuoteRouter } from "@/routers/modules/selmifinprodRouter";
 import { useUserStore } from "@/stores/modules/user";
 import { concat } from "lodash-es";
 import { isArray } from "@/utils/is";
@@ -74,7 +75,14 @@ export const useAuthStore = defineStore({
       // const { data } = await getAuthMenuListApi();
       // console.log("getAuthMenuList data :>> ", data);
       // this.authMenuList = data;
-      this.authMenuList = concat(menuRouter, baseRouter, salePriceRouter, mattressQtuoteRouter, bednetQtuoteRouter);
+      this.authMenuList = concat(
+        menuRouter,
+        baseRouter,
+        salePriceRouter,
+        mattressQtuoteRouter,
+        bednetQtuoteRouter,
+        semifinprodQuoteRouter
+      );
       console.log("getAuthMenuList authMenuList :>> ", this.authMenuList);
     },
     // Set RouteName

+ 3 - 1
JLHWEB/src/views/baseinfo/mtrldef/hooks/index.tsx

@@ -142,7 +142,9 @@ export const useHooks = (t?: any) => {
       basicinfo: {
         el: "input",
         span: 4,
-        editable: ALLOW_EDIT_STATE
+        editable: ALLOW_EDIT_STATE,
+        props: { type: "textarea", rows: 5 },
+        row: 3
       }
     }
   ];

+ 1 - 0
JLHWEB/src/views/home/components/formula/index.vue

@@ -0,0 +1 @@
+<div>1231231</div>

+ 484 - 0
JLHWEB/src/views/quote/semifinprodQuote/components/QuoteList.vue

@@ -0,0 +1,484 @@
+<template>
+  <LjDrawer ref="LjDrawerRef" size="40%" :class="prefixCls">
+    <template #header>
+      <div class="flx-1">
+        {{ $t("business.detail.quoteList") }}
+      </div>
+    </template>
+
+    <el-descriptions :column="3">
+      <template #title>
+        <span class="text-body-b">报价日期:</span>
+        <span class="text-body-b" v-if="data.createtime">{{ isFilterTime(data.createtime) }}</span>
+      </template>
+      <template #extra>
+        <span class="text-body-b">报价金额:</span>
+        <span class="text-body-b">{{ isFilterPrice(data.foreign_cost) + isCurrency }}</span>
+      </template>
+      <el-descriptions-item v-for="item in fields" :key="item.field" width="80">
+        <template #label>
+          <span class="text-secondary-text"> {{ item.label }}: </span>
+        </template>
+        <span class="text-body-m">{{ isFilterPrice(data[item.field]) }}</span>
+      </el-descriptions-item>
+    </el-descriptions>
+
+    <el-table
+      :data="tableData"
+      size="small"
+      border
+      style="width: 100%"
+      show-summary
+      :summary-method="getSummaries"
+      :span-method="objectSpanMethod"
+    >
+      <el-table-column prop="label" label="项目" />
+      <el-table-column prop="dscrp" label="内容" width="160" />
+      <el-table-column prop="qty" label="数量" align="right" />
+      <el-table-column prop="costamt" label="金额" align="right" />
+      <el-table-column prop="useqty" label="用量" align="right" />
+      <el-table-column prop="price" label="单价" align="right" />
+    </el-table>
+  </LjDrawer>
+</template>
+
+<script setup lang="tsx" name="mattressQuoteLjDrawerQuoteList">
+import { ref, computed } from "vue";
+import LjDrawer from "@/components/LjDrawer/index.vue";
+import { useDesign } from "@/hooks/useDesign";
+import { formatTime, formatAmount3, floatAdd } from "@/utils/index";
+import { isFunction } from "@/utils/is";
+import { cloneDeep, pick } from "lodash-es";
+import { useUserStore } from "@/stores/modules/user";
+import { CommonDynamicSelect } from "@/api/modules/common";
+
+interface WidgetProps {
+  data: any;
+  mxdata?: any;
+  /**
+   * @description 属性枚举
+   */
+  enumMap?: any;
+  /**
+   * @description 面料tab分类
+   */
+  fabricMx?: any;
+  formulakindenum?: any;
+}
+
+interface WidgetTableItem {
+  label: string;
+  dscrp: any;
+  qty?: number | string;
+  costamt?: number | string;
+  useqty?: number | string;
+  price?: number | string;
+  [key: string]: any;
+}
+
+const props = withDefaults(defineProps<WidgetProps>(), {});
+
+const { prefixCls } = useDesign("ljdrawer-quotelist");
+const { userInfo } = useUserStore();
+
+const LjDrawerRef = ref();
+
+const isCurrency = computed(() => {
+  return props.data?.moneyrate != 1 ? "美金" : "人民币";
+});
+
+const show = () => {
+  wf_retrieve_qingdang();
+  LjDrawerRef.value.show();
+};
+
+const isFilterPrice = data => {
+  return formatAmount3({ val: data });
+};
+
+const isFilterTime = time => {
+  return formatTime(time, "{y}-{m}-{d}", false);
+};
+
+const tableData = ref<WidgetTableItem[]>([]);
+
+const fields = [
+  { label: "财务底价", field: "nottax_dept_cost" },
+  { label: "佣金点数", field: "commission" },
+  { label: "税率", field: "taxrate" },
+  { label: "额外点数", field: "other_rate" },
+  { label: "额外费用", field: "extras_cost" },
+  { label: "汇率", field: "moneyrate" },
+  { label: "款式费用", field: "hrcost1" },
+  { label: "边带费用", field: "biandaicost1" },
+  { label: "总成本", field: "total_cost_1" },
+  { label: "工厂利润率", field: "profitrate" },
+  { label: "工艺点数", field: "profitrate_point" },
+  { label: "不含税出厂价", field: "nottax_factory_cost_1" },
+  { label: "部门利润率", field: "dept_profitrate" },
+  { label: "FOB费用", field: "fob" },
+  { label: "部门售价", field: "nottax_dept_cost_1" },
+  { label: "让利点数", field: "dept_profitrate_rangli" },
+  { label: "海绵款扣点", field: "haimian_point" }
+];
+
+const oriTableData = ref<WidgetTableItem[]>([
+  {
+    label: "床垫编码",
+    dscrp: () => props.data.mattresscode
+  },
+  {
+    label: "床垫名称",
+    dscrp: () => props.data.mattressname
+  },
+  {
+    label: "床垫类别",
+    dscrp: () => {
+      let _enum = props.enumMap.get("mattresstypeid");
+      let result = "";
+      if (_enum) {
+        result = _enum.find(t => t.value == props.data.mattresstypeid).label ?? "";
+      }
+      return result;
+    }
+  },
+  {
+    label: "床垫规格",
+    dscrp: () => {
+      return `${props.data.mattress_width} * ${props.data.mattress_length} * ${props.data.mattress_height}`;
+    }
+  },
+  {
+    label: "拆装、布套",
+    dscrp: () => {
+      let arr = [];
+      if (Number(props.data.if_m_chai) == 1) {
+        arr.push("面拆");
+      }
+      if (Number(props.data.if_z_chai) == 1) {
+        arr.push("中拆");
+      }
+      if (Number(props.data.if_d_chai) == 1) {
+        arr.push("底拆");
+      }
+      if (Number(props.data.if_n_butao) == 1) {
+        arr.push("内布套");
+      }
+      if (Number(props.data.if_w_butao) == 1) {
+        arr.push("外布套");
+      }
+      return arr.join(" ");
+    }
+  }
+]);
+
+const getSummaries = (param: any) => {
+  const { columns, data } = param;
+  console.log("getSummaries param :>> ", param);
+  const sums: any[] = [];
+  columns.forEach((column, index) => {
+    if (index === 0) {
+      sums[index] = <div>材料合计:</div>;
+      return;
+    }
+    const values = data.map(item => Number(item[column.property]?.toString().replace(/,/g, "")));
+    if (column.property == "costamt" && !values.every(value => Number.isNaN(value))) {
+      console.log("values :>> ", values);
+      sums[index] = `${values.reduce((prev, curr) => {
+        console.log("prev,curr :>> ", prev, curr);
+        const value = Number(curr);
+        if (!Number.isNaN(value)) {
+          return floatAdd(prev, curr);
+        } else {
+          return prev;
+        }
+      }, 0)}`;
+    } else {
+      sums[index] = "";
+    }
+  });
+
+  return sums;
+};
+
+// const f_get_bednet_qingdan = (data: any) => {
+//   let _params = {
+//       dsname: "web_his_price",
+//       queryparams: {
+//         arg_id: 0,
+//         arg_typeid: 1
+//       }
+//     };
+//     let res = await CommonDynamicSelect(_params);
+//     let _data = [];
+//     if (res?.datatable?.length) {
+//       _data=res?.datatable
+//     }
+// };
+
+/**
+ * @description 刷新报价清单
+ */
+const wf_retrieve_qingdang = () => {
+  tableData.value = [];
+  let _tData = cloneDeep(oriTableData.value);
+  tableData.value = _tData.map(item => {
+    for (const key in item) {
+      if (isFunction(item[key])) {
+        item[key] = item[key]();
+      }
+    }
+    return item;
+  });
+
+  console.log("props.mxdata data:>> ", props.mxdata, props.data);
+  let _mxitm = null;
+  props.mxdata.map(item => {
+    switch (item.field) {
+      case "tabpage_8":
+      case "tabpage_9":
+      case "tabpage_10":
+      case "tabpage_11":
+      case "tabpage_12":
+        _mxitm = props.fabricMx.find(t => t.name == item.field);
+        item.data.map(itm => {
+          if ((Number(itm.mtrlid ?? 0) > 0 || Number(itm.costamt ?? 0) != 0) && _mxitm.type.includes(Number(itm.formulakind))) {
+            let result: any = {};
+            result.label = itm.chastr != "" ? itm.chastr : item.label;
+            let _formulaName = "";
+            if (props.formulakindenum) {
+              _formulaName = props.formulakindenum.find(t => t.value == itm.formulakind)?.label ?? "";
+            }
+
+            _formulaName = _formulaName.replace(item.replace, "");
+
+            console.log("_formulaName  rp:>> ", _formulaName, item.replace);
+            result.dscrp = `${_formulaName}:${itm.mtrlname}`;
+
+            if (Number(itm.thickness) > 0) {
+              result.dscrp += ` 厚度:${isFilterPrice(itm.thickness)}`;
+            }
+            result.qty = Number(itm.qty);
+            if (userInfo.usermode == 0) {
+              result.costamt = isFilterPrice(itm.costamt ?? 0);
+              result.useqty = Number(itm.useqty ?? 0);
+              result.price = isFilterPrice(itm.price ?? 0);
+            }
+            tableData.value.push(result);
+          }
+        });
+        break;
+      case "tabpage_13":
+        _mxitm = props.fabricMx.find(t => t.name == item.field);
+        item.data.map(itm => {
+          if ((Number(itm.mtrlid ?? 0) > 0 || Number(itm.costamt ?? 0) != 0) && !_mxitm.type.includes(Number(itm.formulakind))) {
+            let result: any = {};
+            result.label = itm.label;
+            let _formulaName = "";
+            if (props.formulakindenum) {
+              _formulaName = props.formulakindenum.find(t => t.value == itm.formulakind)?.label ?? "";
+            }
+
+            _formulaName = _formulaName.replace(item.replace, "");
+            result.dscrp = `${_formulaName}:${itm.mtrlname}`;
+
+            if (Number(itm.thickness) > 0) {
+              result.dscrp += ` 厚度:${isFilterPrice(itm.thickness)}`;
+            }
+            result.qty = Number(itm.qty);
+            if (userInfo.usermode == 0) {
+              result.costamt = isFilterPrice(itm.costamt ?? 0);
+              result.useqty = Number(itm.useqty ?? 0);
+              result.price = isFilterPrice(itm.price ?? 0);
+            }
+            tableData.value.push(result);
+          }
+        });
+        break;
+      case "cushions": // 垫层
+        item.data.cushions.map(itm => {
+          if (Number(itm.mtrlid ?? 0) > 0 || Number(itm.costamt ?? 0) != 0 || [999].includes(Number(itm.formulakind))) {
+            let result: any = {};
+            let _formulaName = "";
+            if (props.formulakindenum) {
+              _formulaName = props.formulakindenum.find(t => t.value == itm.formulakind)?.label ?? "";
+            }
+
+            result.label = _formulaName;
+            result.dscrp = itm.mtrlname;
+
+            if (![999].includes(Number(itm.formulakind))) {
+              if (Number(itm.thickness) > 0) {
+                result.dscrp += ` 厚度:${isFilterPrice(itm.thickness)}`;
+              }
+              result.qty = Number(itm.qty);
+              if (userInfo.usermode == 0) {
+                result.costamt = isFilterPrice(itm.costamt ?? 0);
+                result.useqty = Number(itm.useqty ?? 0);
+                result.price = isFilterPrice(itm.price ?? 0);
+              }
+            } else {
+              // 999是床网
+              // long ll_bednetid = 0
+              // decimal ld_bednet_height = 0
+              // s_bednet_qd s_bednet_qingdan[]
+              // string arg_temp_msg
+              // ll_bednetid = 0
+              // if dw_chuangwang.rowcount() = 1 then //单床网
+              //   ll_bednetid = dw_chuangwang.object.mtrlid[1]
+              //   f_get_bednet_qingdan(ll_bednetid,s_bednet_qingdan,arg_temp_msg)
+              //   if upperbound(s_bednet_qingdan) > 0 then
+              //     dw_qingdan.Object.str1[ll_row] = s_bednet_qingdan[1].pznamemx
+              //     dw_qingdan.Object.str2[ll_row] = '1'
+              //     IF sys_usermode = 0 THEN //管理员模式
+              //       dw_qingdan.Object.str3[ll_row] = string( s_bednet_qingdan[1].amt,'#,##0.00')
+              //     end if
+              //   end if
+              // else //多床网
+              //   for k = 1 to dw_chuangwang.rowcount()
+              //     ll_bednetid = 0
+              //     ld_bednet_height = 0
+              //     ll_bednetid = dw_chuangwang.object.mtrlid[k]
+              //     SELECT u_bednetmx.bednet_height Into :ld_bednet_height From u_bednetmx Where bednetid = :ll_bednetid;
+              //     if isnull(ld_bednet_height) then ld_bednet_height = 0
+              //     if ld_bednet_height = dw_dianceng.object.thickness[i] then
+              //       ll_bednetid = dw_chuangwang.object.mtrlid[k]
+              //       f_get_bednet_qingdan(ll_bednetid,s_bednet_qingdan,arg_temp_msg)
+              //       if upperbound(s_bednet_qingdan) > 0 then
+              //         dw_qingdan.Object.str1[ll_row] = s_bednet_qingdan[1].pznamemx
+              //         dw_qingdan.Object.str2[ll_row] = '1'
+              //         IF sys_usermode = 0 THEN //管理员模式
+              //           dw_qingdan.Object.str3[ll_row] = string( s_bednet_qingdan[1].amt,'#,##0.00')
+              //         end if
+              //       end if
+              //     end if
+              //   next
+              // end if
+            }
+
+            tableData.value.push(result);
+          }
+        });
+        break;
+      case "accessories": // 辅料
+        item.data.map(itm => {
+          if (Number(itm.mtrlid ?? 0) > 0 || Number(itm.costamt ?? 0) != 0) {
+            let result: any = {};
+            result.label = itm.label;
+            let _formulaName = "";
+            if (props.formulakindenum) {
+              _formulaName = props.formulakindenum.find(t => t.value == itm.formulakind)?.label ?? "";
+            }
+
+            result.label = _formulaName;
+            result.dscrp = itm.mtrlname;
+
+            if (Number(itm.thickness) > 0) {
+              result.dscrp += ` 厚度:${isFilterPrice(itm.thickness)}`;
+            }
+            result.qty = Number(itm.qty);
+            if (userInfo.usermode == 0) {
+              result.costamt = isFilterPrice(itm.costamt ?? 0);
+              result.useqty = Number(itm.useqty ?? 0);
+              result.price = isFilterPrice(itm.price ?? 0);
+            }
+            tableData.value.push(result);
+          }
+        });
+        break;
+      case "packag":
+        console.log("packag item.data :>> ", item.data, props.formulakindenum);
+        item.data.map(itm => {
+          console.log("(Number(itm.mtrlid) > 0 |:>> ", Number(itm.mtrlid) > 0);
+          console.log(
+            "(N Number(itm.costamt) != 0) :>> ",
+            Number(itm.costamt) != 0,
+            Number(itm.costamt),
+            itm.costamt,
+            Number(itm?.costamt),
+            Number(itm?.costamt) != 0
+          );
+          console.log(
+            "(Number(itm.mtrlid) > 0 || Number(itm.costamt) != 0) :>> ",
+            Number(itm.mtrlid) > 0 || Number(itm.costamt) != 0
+          );
+          if (Number(itm.mtrlid ?? 0) > 0 || Number(itm.costamt ?? 0) != 0) {
+            let result: any = {};
+            result.label = itm.label;
+            let _formulaName = "";
+            if (props.formulakindenum) {
+              _formulaName = props.formulakindenum.find(t => t.value == itm.formulakind)?.label ?? "";
+            }
+            result.label = _formulaName;
+
+            result.dscrp = Number(itm.mtrlid) > 0 ? itm.mtrlname : _formulaName;
+
+            if (Number(itm.thickness) > 0) {
+              result.dscrp += ` 厚度:${isFilterPrice(itm.thickness)}`;
+            }
+            result.qty = Number(itm.qty);
+            if (userInfo.usermode == 0) {
+              result.costamt = isFilterPrice(itm.costamt ?? 0);
+              result.useqty = Number(itm.useqty ?? 0);
+              result.price = isFilterPrice(itm.price ?? 0);
+            }
+            tableData.value.push(result);
+          }
+        });
+        break;
+    }
+  });
+
+  console.log("wf_retrieve_qingdang tableData.value :>> ", tableData.value);
+
+  tableData.value.push({
+    label: "地区",
+    dscrp: props.data.area ?? ""
+  });
+  tableData.value.push({
+    label: "柜型",
+    dscrp: props.data.cabinet_type ?? ""
+  });
+};
+
+const objectSpanMethod = (data: any) => {
+  const { row, column, rowIndex, columnIndex } = data;
+  // console.log("objectSpanMethod row,column, rowIndex,columnIndex :>> ", data);
+  if (column.property == "label") {
+    let rowspan = 1;
+    let currentVal = row.label;
+    let lastVal = "";
+    // 上一个
+    if (rowIndex - 1 >= 0) {
+      lastVal = tableData.value[rowIndex - 1]?.label;
+    }
+
+    if (lastVal) {
+      if (lastVal != currentVal) {
+        // 计算合并行数
+        let _span = 0;
+        for (let i = rowIndex + 1; i < tableData.value.length; i++) {
+          if (tableData.value[i].label == currentVal) {
+            _span++;
+          } else {
+            break;
+          }
+        }
+        rowspan += _span;
+        console.log("rowspan _span :>> ", column.property, rowspan, _span);
+      } else {
+        rowspan = 0;
+      }
+    }
+
+    return {
+      rowspan,
+      colspan: rowspan > 0 ? 1 : 0
+    };
+  }
+};
+
+defineExpose({
+  show
+});
+</script>

+ 464 - 0
JLHWEB/src/views/quote/semifinprodQuote/detail.vue

@@ -0,0 +1,464 @@
+<template>
+  <LjDetail
+    name="rpMustPayCrmDetail"
+    ref="LjDetailRef"
+    v-bind="detailProps"
+    :request-api="getData"
+    :data-callback="dataCallback"
+    :init-param="initParams"
+    v-model:order-status="orderStatus"
+    :action="orderDefaultAction"
+    :after-mound="funcAfterMound"
+    :if-layout-editable="false"
+  >
+    <template #fabricMx>
+      <LjVxeTable
+        ref="fabricMxTab8Ref"
+        row-key="key"
+        table-cls=""
+        :data="fabricMxTab8"
+        :columns="columnsMx"
+        :dwname="DwnameEnum.semifinprodQuoteMx"
+        :table-props="tableProps_mx"
+        :tool-button="[]"
+        :auto-load-layout="false"
+        collapseButtons
+      >
+      </LjVxeTable>
+    </template>
+  </LjDetail>
+
+  <MtrldefDialog ref="MtrldefDialogRef" v-bind="MtrldefDialogProps" />
+  <!-- <LjDrawerQuoteList
+    ref="QuoteListDrawerRef"
+    :data="LjDetailRef && LjDetailRef._mainData"
+    :mxdata="isQuoteListMxData"
+    :enumMap="LjDetailRef && LjDetailRef.enumMap"
+    :fabricMx="fabricMxTabList"
+    :formulakindenum="formulaKindEnum"
+  /> -->
+</template>
+
+<script setup lang="ts" name="semifinprodQuoteDetail">
+import { ref, watch, reactive, inject, nextTick, computed, onMounted, getCurrentInstance } from "vue";
+import { DwnameEnum } from "@/enums/dwnameEnum";
+import LjDetail from "@/components/LjDetail/index.vue";
+import { DetailProp } from "@/components/LjDetail/interface";
+import { useI18n } from "vue-i18n";
+import { useHooks } from "./hooks/index";
+import { useAuthButtons } from "@/hooks/useAuthButtons";
+import LjVxeTable from "@/components/LjVxeTable/index.vue";
+// import { cloneDeep } from "lodash-es";
+import { useRoute, useRouter } from "vue-router";
+import { CommonDynamicSelect, GetFormulaCompute } from "@/api/modules/common";
+import { SaveMattress, SaveMattressAuditing, DelMattress } from "@/api/modules/quote";
+// import ToastFormula from "@/components/ToastWidget/Formula/index.vue";
+import { TYPE, useToast, POSITION } from "vue-toastification";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { ArrowDown } from "@element-plus/icons-vue";
+// import { calculateFormula } from "@/utils/index";
+import MtrldefDialog from "@/views/system/selector/mtrldef/index.vue";
+import LjDrawerQuoteList from "./components/QuoteList.vue";
+import mittBus from "@/utils/mittBus";
+import { MittEnum } from "@/enums/mittEnum";
+import { getCurrentRecords } from "@/utils/index";
+
+interface detailProp {
+  /**
+   * @argument any 页面数据
+   */
+  data1?: any;
+  /**
+   * @argument string 请求数据的api ==> 非必传
+   */
+  requestApi?: (params: any) => Promise<any>;
+  /**
+   * @argument any 基础信息,表格展示数据
+   */
+  // columns?: any;
+  /**
+   * @description 是否可编辑
+   */
+  status: "edit" | "new" | string;
+}
+
+const props = withDefaults(defineProps<detailProp>(), {});
+const { t } = useI18n();
+const route = useRoute();
+const router = useRouter();
+const { columns, columnsMx, LjDetailRef, MtrldefDialogRef, MtrldefDialogProps, orderStatus, initParams } = useHooks(t);
+const { CheckPower, CheckOption, buttonNew, buttonDefault } = useAuthButtons(t);
+// const toast = useToast();
+
+// const orderStatus = ref("");
+// const mainData = ref([]);
+const tabRemove: Function = inject("tabRemove") as Function;
+
+/**
+ * @description 明细表格组件基础配置
+ */
+const tableProps_mx = ref({
+  height: "auto",
+  align: "left",
+  // height: "",
+  minHeight: "300px",
+  editConfig: { trigger: "click", mode: "cell", enabled: false },
+  // exportConfig: {
+  //   filename: t("menu.saleTaskCrmDetail") + formatToDate(new Date(), "YYYY-MM-DDHH:mm:ss")
+  // }
+  keyboardConfig: {
+    isEdit: true,
+    isArrow: true,
+    isEnter: true,
+    isTab: true,
+    isDel: true,
+    isBack: true,
+    isEsc: true,
+    editMethod({ $table, row, column }) {
+      // 先清空原先的值
+      row[column.field] = "";
+      // 再激活编辑状态并输入新值
+      $table.setEditCell(row, column);
+    }
+  },
+  mouseConfig: {
+    selected: true
+  }
+});
+
+const keyboardConfig = ref<any>({
+  isEdit: true,
+  isArrow: true,
+  isEnter: true,
+  isTab: true,
+  isDel: true,
+  isBack: true,
+  isEsc: true,
+  editMethod({ $table, row, column }) {
+    // 先清空原先的值
+    row[column.field] = "";
+    // 再激活编辑状态并输入新值
+    $table.setEditCell(row, column);
+  }
+});
+
+const detailProps = reactive<DetailProp>({
+  dwname: DwnameEnum.semifinprodQuote,
+  columns: columns,
+  // headerstatus: ["status", "ifamt_ok"],
+  basicDefault: {},
+  header: {
+    fieldNames: {
+      code: "sptcode",
+      codeLabel: t("table.u_spt.sptcode") + ":",
+      name: "name"
+    }
+  },
+  mould: [
+    {
+      id: "fabricMx",
+      type: "table",
+      label: t("business.detail.fabric")
+    }
+  ]
+});
+
+const getData = (params: any) => {
+  console.log("getData params :>> ", params);
+  let newParams: any = {};
+  params.pageNum && (newParams.pageindex = params.pageNum);
+  params.pageSize && (newParams.pagesize = params.pageSize);
+  delete params.pageNum;
+  delete params.pageSize;
+  newParams.queryParams = params;
+  console.log("params :>> ", params);
+  newParams.dsname = "web_semi_finished_productlist";
+  return CommonDynamicSelect(newParams, DwnameEnum.semifinprodQuote);
+  // return [];
+};
+
+const orderDefaultAction = [
+  buttonDefault({
+    label: t("common.cancelText"),
+    icon: "iconchevron-left",
+    limited: () => {
+      return !orderStatus.value;
+    },
+    clickFunc: item => {
+      if (route.path.indexOf("/new") > -1) {
+        tabRemove(route.fullPath);
+        router.replace("/semifinprodQuote");
+      } else {
+        router.replace(
+          `/semifinprodQuote/detail?id=${LjDetailRef.value._mainData.mattressid}&code=${LjDetailRef.value._mainData.mattresscode}`
+        );
+      }
+    }
+  }),
+  buttonNew({
+    label: t("common.saveText"),
+    icon: "iconsave-01",
+    limited: () => {
+      return !orderStatus.value;
+    },
+    clickFunc: async () => {
+      console.log("save LjDetailRef.value._mainData :>> ", LjDetailRef.value._mainData);
+
+      let mattressMx = [];
+      // fabricMxTabList.value.map(t => {
+      //   if (t.ref) {
+      //     console.log("t.ref?.value :>> ", t.ref, dynamicRef(t.ref));
+      //     if (dynamicRef(t.ref)) {
+      //       const { fullData } = dynamicRef(t.ref)?.element.getTableData();
+      //       console.log("fullData :>> ", fullData);
+      //       mattressMx = mattressMx.concat(fullData);
+      //     }
+      //   }
+      // });
+
+      console.log("mattressMx all :>> ", mattressMx);
+
+      let _param_mf = {
+        mattress: LjDetailRef.value._mainData,
+        mattressMx: mattressMx
+      };
+      try {
+        await SaveMattress(_param_mf);
+      } catch (error) {
+        ElMessage.error(t("sys.api.operationFailed"));
+      }
+    }
+  }),
+  buttonDefault({
+    label: t("common.add"),
+    power: 72,
+    limited: () => {
+      return !!orderStatus.value;
+    },
+    clickFunc: item => {
+      router.push(`/semifinprodQuote/new?id=0`);
+    }
+  }),
+  buttonDefault({
+    power: 72,
+    label: t("common.editText"),
+    limited: () => {
+      return !!orderStatus.value;
+    },
+    clickFunc: item => {
+      router.replace(
+        `/semifinprodQuote/edit?id=${LjDetailRef.value._mainData.mattressid}&code=${LjDetailRef.value._mainData.mattresscode}`
+      );
+    }
+  }),
+  buttonDefault({
+    power: 77,
+    label: t("common.delText"),
+    limited: () => {
+      return !!orderStatus.value;
+    },
+    disabledTextCallBack: (data: any) => {
+      if (!CheckPower(77)) {
+        return "你没有【报价单-删除】的使用权限";
+      }
+      return "";
+    },
+    clickFunc: item => {
+      console.log("dellll clickFunc item :>> ", LjDetailRef.value);
+      ElMessageBox.confirm("是否确定要删除床垫报价单吗?", "询问", {
+        confirmButtonText: t("common.delText"),
+        cancelButtonText: "否",
+        type: "error"
+      })
+        .then(() => {
+          DelMattress({ mattressids: [Number(LjDetailRef.value._mainData.mattressid)] }).then(() => {
+            ElMessage.success("删除成功!");
+
+            tabRemove(route.fullPath);
+            router.replace("/semifinprodQuote");
+            mittBus.emit(MittEnum.MattressList);
+          });
+        })
+        .catch((e: TypeError) => {
+          console.log("e :>> ", e);
+          ElMessage({
+            type: "info",
+            message: "操作取消"
+          });
+        });
+    }
+  })
+];
+
+onMounted(async () => {
+  console.log("route onMounted:>> ", route);
+  console.log("route onMounted:>> ", route.params);
+  console.log("route onMounted:>> ", route.params.id);
+
+  if (route.query?.id) {
+    // 刷新数据
+    initParams.value.arg_mattressid = Number(route.query?.id);
+    console.log("detail onMounted initParams.value :>> ", initParams.value);
+  }
+
+  // getFormulakindEnum();
+});
+
+/**
+ * @description 详情页是否加载完成
+ */
+const ifAfterMound = ref(false);
+/**
+ * @description 页面数据加载完成
+ */
+const funcAfterMound = async () => {
+  console.log("onMounted detail sale start!!!! :>> ");
+  if (!orderStatus.value) {
+    // 详情页
+    gotoSummy(8000);
+  } else {
+    // 新增/编辑
+    tableProps_mx.value.editConfig.enabled = true;
+  }
+  ifAfterMound.value = true;
+
+  console.log("onMounted detail sale start LjDetailRef.value.mainData :>> ", LjDetailRef.value);
+
+  if (orderStatus.value != "new") {
+    getMattressType();
+
+    let res = await getData_mx(initParams.value);
+    oriMxData.value = dataCallback(res);
+    oriMxData.value.list = oriMxData.value.list.map(t => {
+      t.formulakind = Number(t.formulakind);
+      t.thickness = Number(t.thickness);
+      t.qty = Number(t.qty);
+      return t;
+    });
+
+    funcChaifenTab();
+    // funcGetFabricMxShowData(itmshow.name);
+    // console.log("funcAfterMound resData :>> ", fabricMxData.value);
+  }
+};
+
+const handleSelFabricMxNewMtrlGroup = (target: string, item: any) => {
+  console.log("handleSelFabricMxNewMtrlGroup target :>> ", target, item, fabricMxTab10.value);
+  if (target == "tabpage_10") {
+    let hasSame = fabricMxTab10.value.findIndex(t => t.sortcode == item.label);
+    if (hasSame > -1) {
+      ElMessage.error(item.label + "已存在");
+      return false;
+    }
+
+    const $table = fabricMxTab10Ref.value.element;
+    if ($table) {
+      let _arr = [];
+      fabricMxTab10.value.map(t => {
+        if (t.sortcode == "普通大侧") {
+          _arr.push(t);
+        }
+      });
+      $table.remove(_arr);
+    }
+
+    let _params = {
+      arg_array_formulakind: [2, 42, 52, 62, 72, 82],
+      arg_array_formulatype: [0, 1, 2, 3]
+    };
+    funcAddMxSide(_params, item, fabricMxTab10Ref.value);
+  } else if (target == "tabpage_11") {
+    let hasSame = fabricMxTab11.value.findIndex(t => t.sortcode == item.label);
+    if (hasSame > -1) {
+      ElMessage.error(item.label + "已存在");
+      return false;
+    }
+
+    const $table = fabricMxTab11Ref.value.element;
+    if ($table) {
+      let _arr = [];
+      fabricMxTab11.value.map(t => {
+        if (t.sortcode == "小侧1") {
+          _arr.push(t);
+        }
+      });
+      $table.remove(_arr);
+    }
+
+    let _params = {
+      arg_array_formulakind: [3, 83, 43, 53, 63, 73],
+      arg_array_formulatype: [0, 1, 2, 3]
+    };
+    funcAddMxSide(_params, item, fabricMxTab11Ref.value);
+  }
+};
+
+const handleDelFabricMxNewMtrlGroup = (target: string) => {
+  let sameMx = [];
+  let $table = null;
+  if (target == "tabpage_10") {
+    $table = fabricMxTab10Ref.value.element;
+  } else if (target == "tabpage_11") {
+    $table = fabricMxTab11Ref.value.element;
+  }
+
+  if ($table) {
+    const curRow = $table.getCurrentRecord();
+
+    if (!curRow) {
+      ElMessage.warning("请先选择要删除的行");
+      return;
+    }
+
+    sameMx = fabricMxTab10.value.filter(t => t.sortcode == curRow.sortcode);
+  }
+
+  ElMessageBox.confirm(`是否确定要删除${sameMx.length}条明细吗?`, "询问:" + sameMx[0].sortcode, {
+    confirmButtonText: t("common.delText"),
+    cancelButtonText: "否",
+    type: "error"
+  })
+    .then(() => {
+      if (target == "tabpage_10") {
+        let _arr = [];
+        let _idx = [];
+        fabricMxTab10.value.map((t, idx) => {
+          if (t.sortcode == sameMx[0].sortcode) {
+            _arr.push(t);
+            _idx.push(idx);
+          }
+        });
+        $table.remove(_arr);
+
+        fabricMxTab10.value = fabricMxTab10.value.filter((t, idx) => !_idx.includes(idx));
+      } else if (target == "tabpage_11") {
+        let _arr = [];
+        let _idx = [];
+        fabricMxTab11.value.map((t, idx) => {
+          if (t.sortcode == sameMx[0].sortcode) {
+            _arr.push(t);
+            _idx.push(idx);
+          }
+        });
+        $table.remove(_arr);
+
+        fabricMxTab11.value = fabricMxTab11.value.filter((t, idx) => !_idx.includes(idx));
+      }
+    })
+    .catch((e: TypeError) => {
+      console.log("e :>> ", e);
+      ElMessage({
+        type: "info",
+        message: "操作取消"
+      });
+    });
+};
+</script>
+
+<style lang="scss">
+.select-text-right {
+  .el-select__wrapper {
+    text-align: right;
+  }
+}
+</style>

+ 346 - 0
JLHWEB/src/views/quote/semifinprodQuote/detail2.vue

@@ -0,0 +1,346 @@
+<template>
+  <LjDetail
+    name="semifinprodQuoteDetail"
+    ref="LjDetailRef"
+    v-bind="detailProps"
+    :request-api="getData"
+    :data-callback="dataCallback"
+    :init-param="initParams"
+    v-model:order-status="orderStatus"
+    :action="orderDefaultAction"
+    :after-mound="funcAfterMound"
+    :if-layout-editable="false"
+    :search-col="{ xs: 3, sm: 3, md: 3, lg: 3, xl: 3 }"
+    :basic-group-col="{ xs: 3, sm: 3, md: 3, lg: 3, xl: 3 }"
+  >
+    <template #fabricMx>
+      <LjVxeTable
+        ref="VxeTableMxRef"
+        row-key="key"
+        table-cls=""
+        :data="fabricMxTab"
+        :columns="columnsMx"
+        :dwname="DwnameEnum.semifinprodQuoteMx"
+        :table-props="tableProps_mx"
+        :tool-button="[]"
+        :auto-load-layout="false"
+        collapseButtons
+      >
+      </LjVxeTable>
+    </template>
+  </LjDetail>
+
+  <MtrldefDialog ref="MtrldefDialogRef" v-bind="MtrldefDialogProps" />
+</template>
+
+<script setup lang="tsx" name="semifinprodQuoteDetail">
+import { ref, watch, reactive, inject, onMounted } from "vue";
+import { DwnameEnum } from "@/enums/dwnameEnum";
+import { SaveMattressBcp, AuditMattressBcp, DeleteMattressBcp } from "@/api/modules/quote";
+import LjDetail from "@/components/LjDetail/index.vue";
+import { DetailProp } from "@/components/LjDetail/interface";
+import { useI18n } from "vue-i18n";
+import { useRoute, useRouter } from "vue-router";
+import { useHooks } from "./hooks/index2";
+import { useAuthButtons } from "@/hooks/useAuthButtons";
+import { CommonDynamicSelect } from "@/api/modules/common";
+import { ElMessage, ElMessageBox } from "element-plus";
+import mittBus from "@/utils/mittBus";
+import { MittEnum } from "@/enums/mittEnum";
+import MtrldefDialog from "@/views/system/selector/mtrldefNoPrice/index.vue";
+import { formatToDate } from "@/utils/dateUtil";
+
+interface detailProp {
+  /**
+   * @argument any 页面数据
+   */
+  data?: any;
+  /**
+   * @argument string 请求数据的api ==> 非必传
+   */
+  requestApi?: (params: any) => Promise<any>;
+  /**
+   * @argument any 基础信息,表格展示数据
+   */
+  // columns?: any;
+  /**
+   * @description 是否可编辑
+   */
+  status: "edit" | "new" | string;
+  enum?: any;
+}
+
+const props = withDefaults(defineProps<detailProp>(), {});
+const { t } = useI18n();
+const route = useRoute();
+const router = useRouter();
+const {
+  orderStatus,
+  LjDetailRef,
+  VxeTableMxRef,
+  fabricMxTab,
+  oriMxData,
+  MtrldefDialogRef,
+  MtrldefDialogProps,
+  columns,
+  columnsMx,
+  getFormulakindEnum,
+  funcChaifenTab
+} = useHooks(t);
+const { CheckPower, CheckOption, buttonNew, buttonDefault } = useAuthButtons(t);
+
+const tabRemove: Function = inject("tabRemove") as Function;
+
+const mainData = ref([{}]);
+const initParams = ref({ billid: 0 as Number });
+
+/**
+ * @description 明细表格组件基础配置
+ */
+const tableProps_mx = ref({
+  height: "auto",
+  align: "left",
+  // height: "",
+  minHeight: "300px",
+  editConfig: { trigger: "click", mode: "cell", enabled: false },
+  // exportConfig: {
+  //   filename: t("menu.saleTaskCrmDetail") + formatToDate(new Date(), "YYYY-MM-DDHH:mm:ss")
+  // }
+  keyboardConfig: {
+    isEdit: true,
+    isArrow: true,
+    isEnter: true,
+    isTab: true,
+    isDel: true,
+    isBack: true,
+    isEsc: true,
+    editMethod({ $table, row, column }) {
+      // 先清空原先的值
+      row[column.field] = "";
+      // 再激活编辑状态并输入新值
+      $table.setEditCell(row, column);
+    }
+  },
+  mouseConfig: {
+    selected: true
+  }
+});
+
+const detailProps = reactive<DetailProp>({
+  dwname: DwnameEnum.semifinprodQuote,
+  columns: columns,
+  // headerstatus: ["status", "ifamt_ok"],
+  basicDefault: {},
+  header: {
+    fieldNames: {
+      code: "sptcode",
+      codeLabel: t("table.u_spt.sptcode") + ":",
+      name: "name"
+    }
+  },
+  mould: [
+    {
+      id: "fabricMx",
+      type: "table",
+      label: t("business.detail.fabric")
+    }
+  ]
+});
+
+const getData = (params: any) => {
+  console.log("getData params :>> ", params);
+  let newParams: any = {};
+  params.pageNum && (newParams.pageindex = params.pageNum);
+  params.pageSize && (newParams.pagesize = params.pageSize);
+  delete params.pageNum;
+  delete params.pageSize;
+  newParams.queryParams = params;
+  console.log("params :>> ", params);
+  newParams.dsname = "web_semi_finished_productlist";
+  return CommonDynamicSelect(newParams, DwnameEnum.semifinprodQuote);
+};
+
+const orderDefaultAction = [
+  buttonDefault({
+    label: t("common.cancelText"),
+    icon: "iconchevron-left",
+    limited: () => {
+      return !orderStatus.value;
+    },
+    clickFunc: item => {
+      if (route.path.indexOf("/new") > -1) {
+        tabRemove(route.fullPath);
+        router.replace("/semifinprodQuote");
+      } else {
+        router.replace(
+          `/semifinprodQuote/detail?id=${LjDetailRef.value._mainData.billid}&code=${LjDetailRef.value._mainData.billcode}`
+        );
+      }
+    }
+  }),
+  buttonNew({
+    label: t("common.saveText"),
+    icon: "iconsave-01",
+    limited: () => {
+      return !orderStatus.value;
+    },
+    clickFunc: async () => {
+      console.log("save LjDetailRef.value._mainData :>> ", LjDetailRef.value._mainData);
+      const { fullData } = VxeTableMxRef.value?.element.getTableData();
+      console.log("mattressMx all :>> ", fullData);
+      const mattress = LjDetailRef.value._mainData;
+      mattress.mxlist = fullData;
+
+      for (let key in mattress) {
+        if (key === "billdate") {
+          mattress[key] = formatToDate(mattress[key]);
+          break;
+        }
+      }
+
+      ElMessageBox.confirm("是否确定要保存吗?", "询问", {
+        confirmButtonText: "是",
+        cancelButtonText: "否",
+        type: "warning"
+      }).then(async () => {
+        let _param_mf = {
+          mattress,
+          mattressMx: []
+        };
+        try {
+          const res = await SaveMattressBcp(_param_mf);
+          router.replace(`/semifinprodQuote/detail?id=${res.mattress.billid}&code=${res.mattress.billcode}`);
+        } catch (error) {
+          ElMessage.error(t("sys.api.operationFailed"));
+        }
+      });
+    }
+  }),
+  buttonDefault({
+    label: t("common.add"),
+    power: 124,
+    limited: () => {
+      return !!orderStatus.value;
+    },
+    clickFunc: item => {
+      router.push(`/semifinprodQuote/new?id=0`);
+    }
+  }),
+  buttonDefault({
+    power: 124,
+    label: t("common.editText"),
+    limited: () => {
+      return !!orderStatus.value;
+    },
+    clickFunc: item => {
+      router.replace(
+        `/semifinprodQuote/edit?id=${LjDetailRef.value._mainData.billid}&code=${LjDetailRef.value._mainData.billcode}`
+      );
+    }
+  }),
+  buttonDefault({
+    power: 127,
+    label: t("common.delText"),
+    limited: () => {
+      return !!orderStatus.value;
+    },
+    disabledTextCallBack: (data: any) => {
+      if (!CheckPower(127)) {
+        return "你没有【报价单-删除】的使用权限";
+      }
+      return "";
+    },
+    clickFunc: item => {
+      console.log("dellll clickFunc item :>> ", LjDetailRef.value);
+      ElMessageBox.confirm("是否确定要删除床垫报价单吗?", "询问", {
+        confirmButtonText: t("common.delText"),
+        cancelButtonText: "否",
+        type: "error"
+      })
+        .then(() => {
+          DeleteMattressBcp({ list: [{ billid: Number(LjDetailRef.value._mainData.billid) }] }).then(() => {
+            ElMessage.success("删除成功!");
+
+            tabRemove(route.fullPath);
+            router.replace("/semifinprodQuote");
+            mittBus.emit(MittEnum.MattressBcpList);
+          });
+        })
+        .catch((e: TypeError) => {
+          console.log("e :>> ", e);
+          ElMessage({
+            type: "info",
+            message: "操作取消"
+          });
+        });
+    }
+  })
+];
+
+/**
+ * @description 页面数据加载完成
+ */
+const funcAfterMound = async () => {
+  console.log("onMounted detail sale start!!!! :>> ");
+  if (!orderStatus.value) {
+    // 详情页
+    // gotoSummy(8000);
+  } else {
+    // 新增/编辑
+    tableProps_mx.value.editConfig.enabled = true;
+  }
+
+  console.log("onMounted detail sale start LjDetailRef.value.mainData :>> ", LjDetailRef.value);
+
+  if (orderStatus.value != "new") {
+    // getMattressType();
+    let res = await getData_mx(initParams.value);
+    oriMxData.value = dataCallback(res);
+    oriMxData.value.list = oriMxData.value.list.map(t => {
+      t.formulakind = Number(t.formulakind);
+      t.thickness = Number(t.thickness);
+      t.qty = Number(t.qty);
+      return t;
+    });
+    funcChaifenTab();
+  }
+};
+
+const getData_mx = (params: any) => {
+  console.log("getData params :>> ", params);
+  let newParams: any = {};
+  params.pageNum && (newParams.pageindex = params.pageNum);
+  params.pageSize && (newParams.pagesize = params.pageSize);
+  delete params.pageNum;
+  delete params.pageSize;
+  newParams.queryParams = params;
+  console.log("params :>> ", params);
+  newParams.dsname = "web_semi_finished_productmxlist";
+  return CommonDynamicSelect(newParams, DwnameEnum.mattressQuoteMx);
+  // return [];
+};
+
+const dataCallback = (data: any) => {
+  return {
+    list: data.datatable,
+    tableinfo: data.tableinfo,
+    total: data.totalcnt,
+    pageNum: data.pageindex,
+    pageSize: data.pagesize
+  };
+};
+
+onMounted(async () => {
+  console.log("route onMounted:>> ", route);
+  console.log("route onMounted:>> ", route.params);
+  console.log("route onMounted:>> ", route.params.id);
+
+  if (route.query?.id) {
+    // 刷新数据
+    initParams.value.billid = Number(route.query?.id);
+    console.log("detail onMounted initParams.value :>> ", initParams.value);
+  }
+
+  getFormulakindEnum();
+});
+</script>

+ 649 - 0
JLHWEB/src/views/quote/semifinprodQuote/hooks/index.tsx

@@ -0,0 +1,649 @@
+import { ref, reactive, computed, toRefs, nextTick, inject } from "vue";
+import { Table } from "@/hooks/interface";
+import { ColumnProps } from "@/components/LjVxeTable/interface";
+import { ALLOW_EDIT_STATE, sys_arry_formulatype } from "@/config/index";
+import { CommonDynamicSelect } from "@/api/modules/common";
+import { useUserStore } from "@/stores/modules/user";
+import MtrldefSelect from "@/views/system/selector/mtrldef/select.vue";
+import { handleRowAccordingToProp } from "@/utils";
+import { ElButton, ElMessage, ElPopconfirm } from "element-plus";
+import { Minus, Plus, InfoFilled } from "@element-plus/icons-vue";
+import { DwnameEnum } from "@/enums/dwnameEnum";
+import { isArray } from "@/utils/is";
+import { calculateFormula } from "@/utils/index";
+import { cloneDeep, defaultsDeep } from "lodash-es";
+import { TYPE, useToast, POSITION } from "vue-toastification";
+import ToastFormula from "@/components/ToastWidget/Formula/index.vue";
+import ToastHistoryPrice from "@/components/ToastWidget/HistoryPrice/index.vue";
+
+interface defaultState {
+  /**
+   * @description 单据当前状态
+   */
+  orderStatus: string;
+  LjDetailRef: any;
+  MtrldefDialogRef: any;
+  MtrldefDialogProps: any;
+  initParams: any;
+}
+/**
+ * @description 表格多选数据操作
+ * @param {String} rowKey 当表格可以多选时,所指定的 id
+ * */
+export const useHooks = (t?: any) => {
+  const state = reactive<defaultState>({
+    orderStatus: "",
+    LjDetailRef: null,
+    MtrldefDialogRef: null,
+    MtrldefDialogProps: null,
+    initParams: { billid: 0 }
+  });
+
+  state.orderStatus = inject("orderStatus", "");
+
+  const getData_mx = (params: any) => {
+    console.log("getData params :>> ", params);
+    let newParams: any = {};
+    params.pageNum && (newParams.pageindex = params.pageNum);
+    params.pageSize && (newParams.pagesize = params.pageSize);
+    delete params.pageNum;
+    delete params.pageSize;
+    newParams.queryParams = params;
+    console.log("params :>> ", params);
+    newParams.dsname = "web_mattress_mx";
+    return CommonDynamicSelect(newParams, DwnameEnum.mattressQuoteMx);
+    // return [];
+  };
+
+  const dataCallback = (data: any) => {
+    console.log("dataCallback data :>> ", data);
+    return {
+      list: data.datatable,
+      tableinfo: data.tableinfo,
+      total: data.totalcnt,
+      pageNum: data.pageindex,
+      pageSize: data.pagesize
+    };
+  };
+
+  /**
+   * @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) => {
+    console.log("rModelSetMtrl data :>> ", data);
+    console.log("rModelSetMtrl item :>> ", item);
+    if (item) {
+      data.mattressid = state.LjDetailRef._mainData.mattressid;
+      data.mattressmxid = 0;
+      data.mtrlid = item.mtrlid;
+      data.price = item.pricelistprice;
+      data.gram_weight = item.gram_weight;
+      data.cloth_width = item.cloth_width;
+      data.if_inputqty = Number(item.if_inputqty);
+      data.if_areaprice = item.if_areaprice;
+      data.mtrlname = item.mtrlname;
+      data.priceunit = item.priceunit;
+      data.shrinkage = item.price;
+      Number(item.thickness) > 0 && (data.thickness = item.thickness);
+      data.price_formula = item.price_formula;
+    }
+  };
+
+  const rModelClearMtrl = (data: any) => {
+    console.log("rModelClearMtrl data :>> ", data);
+    data.mattressid = state.LjDetailRef._mainData.mattressid;
+    data.mattressmxid = 0;
+    data.mtrlid = 0;
+    data.price = 0;
+    data.gram_weight = 0;
+    data.cloth_width = 0;
+    data.if_inputqty = 0;
+    data.if_areaprice = 0;
+    data.mtrlname = "";
+    data.priceunit = "";
+    data.shrinkage = 0;
+    data.thickness = 0;
+    data.price_formula = "";
+    data.qty = "";
+  };
+
+  /**
+   * @description 面料-裥大、小侧,增加物料
+   */
+  const funcAddMxSide = async (params: any, data: any, targetRef?: any) => {
+    // arg_array_formulakind
+    let newParams: any = {};
+    newParams.queryParams = params;
+    newParams.dsname = "web_mattress_formulalist";
+    let res = await CommonDynamicSelect(newParams);
+    console.log("funcAddBigSide res :>> ", res);
+
+    if (res.datatable) {
+      if (targetRef) {
+        const $table = targetRef.element;
+        if ($table) {
+          res.datatable.map(itm => {
+            let records: any = {
+              formulatype: itm.formulatype,
+              if_mtrl: Number(itm.if_mtrl),
+              formulaid: itm.formulaid,
+              sortcode: data.label,
+              chastr: data.label,
+              formulakind: Number(itm.formulakind),
+              formula: itm.formula,
+              useformula: itm.useformula,
+              gydscrp: itm.gydscrp
+            };
+
+            if (records.if_mtrl > 1) {
+              records.addmx = "+";
+              records.delmx = "-";
+            }
+
+            $table.insertAt(records, -1);
+          });
+        }
+      } else {
+        let arr = [];
+        res.datatable.map(itm => {
+          let records: any = {
+            formulatype: itm.formulatype,
+            if_mtrl: Number(itm.if_mtrl),
+            formulaid: itm.formulaid,
+            sortcode: data.label,
+            chastr: data.label,
+            formulakind: Number(itm.formulakind),
+            formula: itm.formula,
+            useformula: itm.useformula,
+            gydscrp: itm.gydscrp
+          };
+
+          if (records.if_mtrl > 1) {
+            records.addmx = "+";
+            records.delmx = "-";
+          }
+
+          arr.push(records);
+        });
+        return arr;
+      }
+    } else {
+      return [];
+    }
+  };
+
+  /**
+   * @description 明细,新增
+   */
+  const funcAddMtrlMx = async (data: any) => {
+    console.log("state.LjDetail. :>> ", state.LjDetailRef);
+    console.log("funcAddMtrlMx data :>> ", data);
+    let { tabsActive } = state.LjDetailRef;
+    let { row, rowIndex, visibleData } = data;
+    let nextRow = visibleData[rowIndex + 1];
+    if (!nextRow) {
+      nextRow = visibleData[visibleData.length - 1];
+    }
+
+    let _target = tabsActive == "fabricMx" ? state.fabricMxTabs : tabsActive;
+
+    let currentTab = state.fabricMxTabList.find(t => t.name == _target);
+    const $table = state[currentTab.ref].element;
+    if ($table) {
+      const records = {
+        addmx: "+",
+        delmx: "-",
+        formulatype: row.formulatype,
+        if_mtrl: row.if_mtrl,
+        formulaid: row.formulaid,
+        sortcode: row.sortcode,
+        formulakind: row.formulakind,
+        formula: row.formula,
+        thickness: 0,
+        mtrlid: 0
+      };
+
+      const { row: newRow } = await $table.insertAt(records, nextRow);
+      await $table.setEditCell(newRow, "mtrlname");
+      await $table.setCurrentRow(newRow);
+    }
+  };
+
+  /**
+   * @description 明细,删除
+   */
+  const funcDelMtrlMx = (data: any) => {
+    let { row } = data;
+    let { tabsActive } = state.LjDetailRef;
+
+    // let _target = tabsActive == "fabricMx" ? state.fabricMxTabs : tabsActive;
+
+    // let currentTab = state.fabricMxTabList.find(t => t.name == _target);
+    // const $table = state[currentTab.ref].element;
+    // if ($table) {
+    //   $table.remove(row);
+    // }
+  };
+
+  // 表格配置项
+  const columns: ColumnProps<any>[] = [
+    { type: "checkbox", width: 50, fixed: "left" },
+    { title: "#", field: "pid", fixed: "left", width: 80 },
+    {
+      field: "billcode",
+      title: "报价唯一码",
+      align: "left",
+      table: "u_semi_finished_product",
+      search: {
+        el: "input",
+        props: {
+          placeholder: "唯一码/编码/名称"
+        },
+        order: 0
+      },
+      basicinfo: {
+        el: "input",
+        editable: ALLOW_EDIT_STATE
+      }
+    },
+    {
+      field: "semi_finished_code",
+      title: "半成品编码",
+      align: "left",
+      table: "u_semi_finished_product",
+      search: {
+        el: "input",
+        props: {
+          placeholder: "唯一码/编码/名称"
+        },
+        order: 0
+      },
+      basicinfo: {
+        el: "input",
+        editable: ALLOW_EDIT_STATE
+      }
+    },
+    {
+      field: "semi_finished_name",
+      title: "半成品名称",
+      align: "left",
+      table: "u_semi_finished_product",
+      search: {
+        el: "input",
+        props: {
+          placeholder: "唯一码/编码/名称"
+        },
+        order: 0
+      },
+      basicinfo: {
+        el: "input",
+        editable: ALLOW_EDIT_STATE
+      }
+    },
+    {
+      field: "flag",
+      title: "审核"
+    },
+    {
+      field: "opemp",
+      title: "登记人"
+    },
+    {
+      field: "opdate",
+      title: "登记时间"
+    },
+    {
+      field: "auditemp",
+      title: "审核人"
+    },
+    {
+      field: "auditdate",
+      title: "审核时间"
+    }
+  ];
+
+  const columnsMx: ColumnProps<any>[] = [
+    { title: "#", type: "seq", fixed: "left", width: 80 },
+    {
+      title: "计算成功?",
+      field: "if_success",
+      datatype: "checkbox",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "+",
+      field: "addmx",
+      width: 80,
+      render: (scope: any) => {
+        let _if_mtrl = Number(scope.row.if_mtrl);
+        if (_if_mtrl > 1) {
+          if (state.orderStatus) {
+            return (
+              <>
+                <ElPopconfirm
+                  width="220"
+                  icon={InfoFilled}
+                  title={t("business.tips.mattress.addMx")}
+                  confirm-button-text={t("common.addText")}
+                  onConfirm={() => funcAddMtrlMx(scope)}
+                >
+                  {{
+                    reference: () => {
+                      return <ElButton type="primary" plain circle icon={Plus}></ElButton>;
+                    }
+                  }}
+                </ElPopconfirm>
+              </>
+            );
+            // return <ElButton type="primary" plain circle icon={Plus} onClick={() => funcAddMtrlMx(scope)}></ElButton>;
+          } else {
+            return <>+</>;
+          }
+        } else {
+          return <></>;
+        }
+      }
+    },
+    {
+      title: "-",
+      field: "delmx",
+      width: 80,
+      render: (scope: any) => {
+        let _if_mtrl = Number(scope.row.if_mtrl);
+        if (_if_mtrl > 1) {
+          if (state.orderStatus) {
+            return (
+              <>
+                <ElPopconfirm
+                  width="220"
+                  icon={InfoFilled}
+                  title={t("business.tips.mattress.delMx")}
+                  confirm-button-text={t("common.delText")}
+                  confirm-button-type="danger"
+                  onConfirm={() => funcDelMtrlMx(scope)}
+                >
+                  {{
+                    reference: () => {
+                      return <ElButton type="danger" plain circle icon={Minus} />;
+                    }
+                  }}
+                </ElPopconfirm>
+              </>
+            );
+            // return <ElButton type="danger" plain circle icon={Minus} onClick={() => funcDelMtrlMx(scope)}></ElButton>;
+          } else {
+            return <>-</>;
+          }
+        } else {
+          return <></>;
+        }
+      }
+    },
+    {
+      title: "位置",
+      field: "chastr"
+    },
+    {
+      title: "公式名",
+      field: "formulakind",
+      table: "u_mattress_formula",
+      align: "left",
+      isFilterEnum: true,
+      fieldNames: { value: "value", label: "label" },
+      // enum: async () => {
+      //   let res = await CommonDynamicSelect({
+      //     dsname: "_Mapper_formulakind",
+      //     queryparams: {}
+      //   });
+      //   return { data: res.datatable };
+      // }
+      render: (scope: any) => {
+        const { column, row, status } = scope;
+        let itmName = state.formulaKindEnum.find(t => t.value == row.formulakind)?.label ?? "";
+        return <>{itmName}</>;
+      }
+    },
+    {
+      title: "按物料?",
+      field: "if_mtrl",
+      table: "u_mattress_formula",
+      enum: [
+        {
+          value: "0",
+          label: "无物料"
+        },
+        {
+          value: "1",
+          label: "单物料"
+        },
+        {
+          value: "2",
+          label: "多物料"
+        }
+      ]
+    },
+    {
+      title: "厚度cm",
+      field: "thickness",
+      datatype: "number",
+      editRender: {
+        name: "$input"
+      }
+    },
+    {
+      title: "物料",
+      field: "mtrlname",
+      editRender: {},
+      editColRender: (scope: any) => {
+        console.log("mtrlname hooks render scope :>> ", scope);
+        console.log("mtrlname hooks render LjDetailRef.value._mainData :>> ", state.LjDetailRef);
+        const { column, row, status } = scope;
+        let field = column.field;
+        let _label = column.title;
+        // if (column?.format) {
+        //   _label = handleRowAccordingToProp(searchParam, field, column?.format);
+        // }
+        let _deptid = state.LjDetailRef._mainData.deptid;
+        let deptEnum = state.LjDetailRef.enumMap.get("deptid");
+        let _pricelistid = 0;
+        console.log("deptEnum :>> ", deptEnum);
+        if (deptEnum) {
+          let depItem = deptEnum.find((item: any) => item.value == _deptid);
+          console.log("depItem :>> ", depItem);
+          if (depItem) {
+            _pricelistid = Number(depItem.pricelistid);
+          }
+        }
+        console.log("_pricelistid :>> ", _pricelistid, row.formulakind);
+
+        console.log("state.mtrltypeTabList :>> ", state.mtrltypeTabList);
+
+        let _mtrltypeItem = state.mtrltypeTabList.find(t => t.formulakinds.includes(Number(row.formulakind)));
+        !_mtrltypeItem && (_mtrltypeItem = { value: -1 });
+
+        let params = {
+          mtrltype: _mtrltypeItem.value,
+          pricelistid: _pricelistid
+        };
+
+        return (
+          <>
+            <MtrldefSelect
+              value={row.mtrlid}
+              {...params}
+              clearable
+              placeholder={_label}
+              onOpenModal={() => fModelChoseMtrl(row, params, _mtrltypeItem.label)}
+              onSelect={(val: any) => rModelSetMtrl(row, val)}
+              onClear={() => rModelClearMtrl(row)}
+            />
+          </>
+        );
+      }
+    },
+    {
+      title: "数量/长度",
+      field: "qty",
+      datatype: "number",
+      editRender: {
+        name: "input"
+      }
+    },
+    {
+      title: "物料单价",
+      field: "price",
+      datatype: "number",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "单位",
+      field: "priceunit"
+    },
+    {
+      title: "收缩率",
+      field: "shrinkage",
+      datatype: "number",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "克重",
+      field: "gram_weight",
+      datatype: "number",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "幅宽",
+      field: "cloth_width",
+      datatype: "number",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "固定厚度?",
+      field: "if_inputqty",
+      datatype: "checkbox",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "按面积单价?",
+      field: "if_areaprice",
+      datatype: "checkbox",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "成本金额",
+      field: "costamt",
+      datatype: "number",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "金额文本公式",
+      field: "formula",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "金额数字公式",
+      field: "replace_formula",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "清单用量",
+      field: "useqty",
+      datatype: "number",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "用量文本公式",
+      field: "useformula",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "用量数字公式",
+      field: "replace_useformula",
+      limited: () => {
+        const { userInfo } = useUserStore();
+        return userInfo.usermode != 0;
+      }
+    },
+    {
+      title: "工艺填写说明",
+      field: "gydscrp"
+    }
+  ];
+
+  return {
+    ...toRefs(state),
+    columns,
+    columnsMx
+  };
+};

Datei-Diff unterdrückt, da er zu groß ist
+ 1026 - 0
JLHWEB/src/views/quote/semifinprodQuote/hooks/index2.tsx


+ 342 - 0
JLHWEB/src/views/quote/semifinprodQuote/index.vue

@@ -0,0 +1,342 @@
+<template>
+  <div class="table-box">
+    <LjVxeTable
+      ref="vxeTableRef"
+      row-key="mattressid"
+      :columns="columns"
+      :init-param="initParams"
+      :request-api="getData"
+      :data-callback="dataCallback"
+      :dwname="DwnameEnum.semifinprodQuote"
+      :table-props="tableProps"
+      :table-events="tableEvents"
+      :auto-load-layout="false"
+      :search-btn-size-extent="[]"
+      pagination
+    >
+      <!-- 表格 header 按钮 -->
+      <template #tableHeader>
+        <LjHeaderMenu :update="dialogVisible" :action="action" />
+      </template>
+    </LjVxeTable>
+  </div>
+</template>
+
+<script setup lang="ts" name="semifinprodQuote">
+import { ref, onMounted, inject } from "vue";
+import { useRouter } from "vue-router";
+import { AuditMattressBcp, DeleteMattressBcp } from "@/api/modules/quote";
+import { CommonDynamicSelect } from "@/api/modules/common";
+import { ColumnProps } from "@/components/LjVxeTable/interface";
+import LjDrawer from "@/components/LjDrawer/index.vue";
+// import PriceListDetail from "./detail.vue";
+import { useHooks } from "./hooks/index2";
+import LjDialog from "@/components/LjDialog/index.vue";
+import LjHeaderMenu from "@/components/LjHeaderMenu/index.vue";
+import { useI18n } from "vue-i18n";
+import { useAuthButtons } from "@/hooks/useAuthButtons";
+import { DwnameEnum } from "@/enums/dwnameEnum";
+import { formatToDateTime, formatToDate } from "@/utils/dateUtil";
+import { cloneDeep } from "lodash-es";
+import { useGlobalStore } from "@/stores/modules/global";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { detailAction } from "@/components/LjDetail/interface";
+import mittBus from "@/utils/mittBus";
+import { MittEnum } from "@/enums/mittEnum";
+import { getCurrentRecords } from "@/utils/index";
+import * as Exceljs from "exceljs";
+import { saveAs } from "file-saver";
+
+const { t } = useI18n();
+const router = useRouter();
+const globalStore = useGlobalStore();
+const { columns, orderStatus } = useHooks();
+const { CheckPower, CheckOption, buttonNew, buttonDefault } = useAuthButtons(t);
+
+const initParams = ref({});
+const dialogVisible = ref(false);
+const vxeTableRef = ref();
+
+const getData = (params: any) => {
+  console.log("getData mattress params :>> ", params);
+  let newParams: any = {};
+  params.pageNum && (newParams.pageindex = params.pageNum);
+  params.pageSize && (newParams.pagesize = params.pageSize);
+  params.orderstr && (newParams.orderstr = params.orderstr);
+  delete params.pageNum;
+  delete params.pageSize;
+  delete params.orderstr;
+  let _params = cloneDeep(params);
+  newParams.queryParams = _params;
+  newParams.dsname = "web_semi_finished_productlist";
+
+  return CommonDynamicSelect(newParams, DwnameEnum.semifinprodQuote);
+};
+
+const dataCallback = (data: any) => {
+  console.log("data :>> ", data);
+  return {
+    list: data.datatable,
+    tableinfo: data.tableinfo,
+    total: data.totalcnt,
+    pageNum: data.pageindex,
+    pageSize: data.pagesize
+  };
+};
+
+const handleDBlClickTable = ({ row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, $event }: any) => {
+  if (globalStore.detailBlank) {
+    // 打开新的窗口
+    const routeUrl = router.resolve({
+      path: `/semifinprodQuote/detail`,
+      query: {
+        id: row.billid,
+        code: row.billcode
+      }
+    });
+    window.open(routeUrl.href, "_blank");
+  } else {
+    // if (currentLayout.value.right.hidden && globalStore.mxFloat?.includes("custCrmDetail")) {
+    //   // 弹窗
+    //   mainData.value = row;
+    //   LjDrawerRef.value.show();
+    // } else {
+    // 打开新的标签页
+    router.push(`/semifinprodQuote/detail?id=${row.billid}&code=${row.billcode}`);
+    // }
+  }
+};
+
+const rowClsNameFunc = (data: any) => {
+  const { row, rowIndex, $rowIndex } = data;
+  //   if (row.task_status == 2) {
+  //     return "vxecol-disable";
+  //   }
+  return "";
+};
+const tableProps = {
+  height: "auto",
+  editConfig: { trigger: "click", mode: "cell" },
+  rowClassName: rowClsNameFunc,
+  exportConfig: {
+    filename: t("menu.rpMsttake") + formatToDate(new Date(), "YYYY-MM-DD HH:mm:ss")
+  }
+};
+
+// 返回绑定的事件
+const tableEvents = {
+  // "checkbox-change": handleCheckboxChange,
+  // "checkbox-all": handleCheckboxChange,
+  // "checkbox-range-change": handleCheckboxChange,
+  // "current-change": handleCurrentChanged
+  "cell-dblclick": handleDBlClickTable
+  // "cell-click": handleClickTable
+};
+
+onMounted(() => {
+  dialogVisible.value = true;
+});
+
+/**
+ * @description 业务下单或财务审核操作
+ * @param params 对象,入参
+ */
+const toAuditing = (params: any, message: string) => {
+  const { curRecords } = getCurrentRecords(vxeTableRef.value);
+
+  console.log("curRecords :>> ", curRecords);
+  if (!curRecords.length) {
+    ElMessage.warning(t("business.tips.mattress.records"));
+    return;
+  }
+
+  let _mattressids = curRecords.map((item: any) => Number(item.mattressid));
+
+  ElMessageBox.confirm(`是否确定要对${curRecords.length}张床垫报价单进行操作`, "询问", {
+    confirmButtonText: message,
+    cancelButtonText: "否",
+    type: "warning"
+  })
+    .then(() => {
+      let _params = {
+        ...params,
+        mattressids: _mattressids
+      };
+      SaveMattressAuditing(_params).then(() => {
+        ElMessage.success(t("sys.api.operationSuccess"));
+
+        vxeTableRef.value.refresh();
+      });
+    })
+    .catch((e: TypeError) => {
+      ElMessage({
+        type: "info",
+        message: "操作取消"
+      });
+    });
+};
+
+/**
+ * @description 按钮展示
+ */
+const action: detailAction[] = [
+  buttonDefault({
+    label: t("common.redo"),
+    clickFunc: item => {
+      vxeTableRef.value.refresh();
+    }
+  }),
+  buttonDefault({
+    label: t("common.add"),
+    power: 124,
+    clickFunc: item => {
+      router.push(`/semifinprodQuote/new?id=0`);
+    }
+  }),
+  buttonDefault({
+    label: t("common.editText"),
+    power: 124,
+    clickFunc: item => {
+      const { $table, curRecords } = getCurrentRecords(vxeTableRef.value);
+
+      if (!curRecords.length) {
+        ElMessage.warning(t("business.tips.mattress.records"));
+        return;
+      }
+
+      const _cur = $table.getCurrentRecord() ?? null;
+      if (_cur) {
+        router.push(`/semifinprodQuote/edit?id=${_cur.billid}&code=${_cur.billcode}`);
+      } else {
+        const _cur = curRecords[curRecords.length - 1];
+        router.push(`/semifinprodQuote/edit?id=${_cur.billid}&code=${_cur.billcode}`);
+      }
+    }
+  }),
+  buttonDefault({
+    label: t("common.auditText"),
+    power: 125,
+    limited: () => {
+      return !!orderStatus.value;
+    },
+    disabledTextCallBack: (data: any) => {
+      if (!CheckPower(125)) {
+        return `你没有【报价单-${t("common.auditText")}】的使用权限`;
+      }
+      return "";
+    },
+    clickFunc: item => {
+      const { curRecords } = getCurrentRecords(vxeTableRef.value);
+      ElMessageBox.confirm("是否确定要审核单据吗?", "询问", {
+        confirmButtonText: "是",
+        cancelButtonText: "否",
+        type: "warning"
+      })
+        .then(() => {
+          let list = curRecords.map((item: any) => {
+            return { billid: Number(item.billid) };
+          });
+          AuditMattressBcp({ list, type: 1 }).then(() => {
+            ElMessage.success("审核成功!");
+
+            vxeTableRef.value.refresh();
+          });
+        })
+        .catch((e: TypeError) => {
+          ElMessage({
+            type: "info",
+            message: "操作取消"
+          });
+        });
+    }
+  }),
+  buttonDefault({
+    label: t("common.withdrawAuditText"),
+    power: 125,
+    limited: () => {
+      return !!orderStatus.value;
+    },
+    disabledTextCallBack: (data: any) => {
+      if (!CheckPower(125)) {
+        return `你没有【报价单-${t("common.withdrawAuditText")}】的使用权限`;
+      }
+      return "";
+    },
+    clickFunc: item => {
+      const { curRecords } = getCurrentRecords(vxeTableRef.value);
+      ElMessageBox.confirm("是否确定要撤审单据吗?", "询问", {
+        confirmButtonText: "是",
+        cancelButtonText: "否",
+        type: "warning"
+      })
+        .then(() => {
+          let list = curRecords.map((item: any) => {
+            return { billid: Number(item.billid) };
+          });
+          AuditMattressBcp({ list, type: 0 }).then(() => {
+            ElMessage.success("撤审成功!");
+
+            vxeTableRef.value.refresh();
+          });
+        })
+        .catch((e: TypeError) => {
+          ElMessage({
+            type: "info",
+            message: "操作取消"
+          });
+        });
+    }
+  }),
+  buttonDefault({
+    label: t("common.delText"),
+    power: 127,
+    disabledTextCallBack: (data: any) => {
+      if (!CheckPower(127)) {
+        return "你没有【报价单-删除】的使用权限";
+      }
+
+      return "";
+    },
+    clickFunc: item => {
+      const { curRecords } = getCurrentRecords(vxeTableRef.value);
+
+      console.log("curRecords :>> ", curRecords);
+      if (!curRecords.length) {
+        ElMessage.warning(t("business.tips.mattress.records"));
+        return;
+      }
+
+      let list = curRecords.map((item: any) => {
+        return { billid: Number(item.billid) };
+      });
+
+      ElMessageBox.confirm(`是否确定要删除${curRecords.length}张半成品报价单吗?`, "询问", {
+        confirmButtonText: t("common.delText"),
+        cancelButtonText: "否",
+        type: "warning"
+      })
+        .then(() => {
+          DeleteMattressBcp({ list }).then(() => {
+            ElMessage.success("删除成功!");
+
+            vxeTableRef.value.refresh();
+          });
+        })
+        .catch((e: TypeError) => {
+          console.log("e :>> ", e);
+          ElMessage({
+            type: "info",
+            message: "操作取消"
+          });
+        });
+    }
+  })
+];
+
+/**
+ * @description 监听框架属性变化
+ */
+mittBus.on(MittEnum.MattressBcpList, () => {
+  vxeTableRef.value.refresh();
+});
+</script>

+ 51 - 0
JLHWEB/src/views/saleprice/quoteinquiry/hooks/index.tsx

@@ -0,0 +1,51 @@
+import { ref, reactive, computed, toRefs } from "vue";
+import { Table } from "@/hooks/interface";
+import { ColumnProps } from "@/components/LjVxeTable/interface";
+import { ALLOW_EDIT_STATE } from "@/config/index";
+import { ElMessage, ElMessageBox } from "element-plus";
+interface defaultState {
+  /**
+   * @description 单据当前状态
+   */
+  orderStatus: string;
+  /**
+   * @description 列表Ref
+   */
+  VxeTableRef: any;
+  /**
+   * @description 详情页Ref
+   */
+  LjDetailRef: any;
+}
+
+const state = reactive<defaultState>({
+  orderStatus: "",
+  VxeTableRef: null,
+  LjDetailRef: null
+});
+/**
+ * @description 表格多选数据操作
+ * @param {String} rowKey 当表格可以多选时,所指定的 id
+ * */
+export const useHooks = (t?: any) => {
+  // 表格配置项
+  const columns: ColumnProps<any>[] = [
+    {
+      field: "billtype",
+      title: "报价类型",
+      search: {
+        el: "select",
+        key: "billtype",
+        props: {
+          filterable: false,
+          defaultFirstOption: false
+        }
+      }
+    }
+  ];
+
+  return {
+    ...toRefs(state),
+    columns
+  };
+};

+ 137 - 1
JLHWEB/src/views/saleprice/quoteinquiry/index.vue

@@ -1 +1,137 @@
-<template>123</template>
+<template>
+  <div class="table-box">
+    <LjVxeTable
+      ref="VxeTableRef"
+      row-key="billid"
+      :columns="columns"
+      :request-api="getData"
+      :data-callback="dataCallback"
+      :dwname="dwname"
+      :table-props="tableProps"
+      :table-events="tableEvents"
+      :init-param="initParams"
+      :auto-load-layout="false"
+      pagination
+    >
+    </LjVxeTable>
+  </div>
+</template>
+
+<script setup lang="ts" name="saleprice_invalidmtrllist">
+import { ref, onMounted, provide } from "vue";
+import { getInvalidMtrlList } from "@/api/modules/saleprice";
+import { ColumnProps } from "@/components/LjVxeTable/interface";
+import LjDrawer from "@/components/LjDrawer/index.vue";
+import { useHooks } from "./hooks/index";
+import LjDialog from "@/components/LjDialog/index.vue";
+import LjHeaderMenu from "@/components/LjHeaderMenu/index.vue";
+import { useI18n } from "vue-i18n";
+import { useAuthButtons } from "@/hooks/useAuthButtons";
+import { cloneDeep } from "lodash-es";
+
+const dwname = "web_invalid_mtrllist";
+const mainData = ref({});
+const tableProps = {
+  height: "auto",
+  editConfig: { trigger: "click", mode: "cell" }
+  // rowClassName: rowClsNameFunc
+  // exportConfig: {
+  //   filename: t("menu.saletaskmx") + formatToDate(new Date(), "YYYY-MM-DD HH:mm:ss")
+  // }
+};
+
+const { t } = useI18n();
+const { VxeTableRef, LjDetailRef, columns } = useHooks(t);
+const { CheckPower, CheckOption, buttonNew, buttonDefault } = useAuthButtons(t);
+
+const orderStatus = ref("");
+const deptname = ref("");
+const enumMap = ref(new Map());
+const initParams = ref({});
+
+// const orderDefaultAction = [
+//   buttonDefault({
+//     label: t("common.cancelText"),
+//     icon: "iconchevron-left"
+//   }),
+//   buttonNew({
+//     label: t("common.saveText"),
+//     icon: "iconsave-01",
+//     clickFunc: item => {
+//       const save_data = orderStatus.value == "new" ? LjDetailRef.value?.infoParam : LjDetailRef.value?._mainData;
+
+//       fSave({ dept: save_data }).then(() => {
+//         LjDrawerRef.value.hide();
+//       });
+//     }
+//   })
+// ];
+// const orderEditAction = [
+//   buttonNew({
+//     label: t("common.saveText"),
+//     icon: "iconsave-01",
+//     clickFunc: item => {
+//       const save_data = orderStatus.value == "new" ? LjDetailRef.value?.infoParam : LjDetailRef.value?._mainData;
+
+//       fSave({ dept: save_data }).then(() => {
+//         LjDrawerRef.value.hide();
+//       });
+//     }
+//   })
+// ];
+
+/*
+ * @description 抽屉默认属性
+ */
+const drawerDefineProp = {
+  draggable: true,
+  overflow: true,
+  width: "40%"
+  // modalClass: "lj-file-dialog"
+};
+
+const getData = (params: any) => {
+  return getInvalidMtrlList(params);
+};
+
+const dataCallback = (data: any) => {
+  if (data.tableinfo?.columns) {
+    data.tableinfo?.columns.map((item: any) => {
+      if (item?.enum) {
+        enumMap.value.set(item.field, item.enum);
+      }
+    });
+  }
+  return {
+    list: data.datatable,
+    tableinfo: data.tableinfo,
+    total: data.totalcnt,
+    pageNum: data.pageindex,
+    pageSize: data.pagesize
+  };
+};
+
+// const LjDrawerRef = ref();
+// const handleDBlClickTable = ({ row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, $event }: any) => {
+//   // 弹窗
+//   mainData.value = cloneDeep(row);
+//   deptname.value = row.deptname;
+//   orderStatus.value = "edit";
+//   LjDrawerRef.value.show();
+// };
+
+// const handleOpenNewTable = () => {
+//   mainData.value = {
+//     deptid: 0
+//   };
+//   deptname.value = "";
+//   orderStatus.value = "new";
+//   LjDrawerRef.value.show();
+// };
+
+// 返回绑定的事件
+const tableEvents = {
+  // "cell-dblclick": handleDBlClickTable
+  // "cell-click": handleClickTable
+};
+</script>

+ 0 - 0
JLHWEB/src/views/system/selector/formula/index.vue