Forráskód Böngészése

床垫报价代码更新

JohnnyChan 7 hónapja
szülő
commit
fdad875d5c

+ 49 - 95
JLHWEB/src/api/interface/index.ts

@@ -1073,83 +1073,57 @@ export namespace Basicinfo {
   export interface ReqSaveBedNetType {
     bednet: any;
   }
-  export interface ResSaveBedNetType {
-
-  }
+  export interface ResSaveBedNetType {}
   export interface ReqDeleteBedNetType {
     list: any[];
   }
-  export interface ResDeleteBedNetType {
-    
-  }
+  export interface ResDeleteBedNetType {}
   export interface ReqSaveMattressType {
     mattress: any;
   }
-  export interface ResSaveMattressType {
-
-  }
+  export interface ResSaveMattressType {}
   export interface ReqDeleteMattressType {
     list: any[];
   }
-  export interface ResDeleteMattressType {
-    
-  }
+  export interface ResDeleteMattressType {}
   export interface ReqSaveMattressFormula {
     mattress: any;
   }
-  export interface ResSaveMattressFormula {
-
-  }
+  export interface ResSaveMattressFormula {}
   export interface ReqDeleteMattressFormula {
     list: any[];
   }
-  export interface ResDeleteMattressFormula {
-    
-  }
+  export interface ResDeleteMattressFormula {}
   export interface ReqSaveShrinkage {
     shrinkage: any;
   }
-  export interface ResSaveShrinkage {
-
-  }
+  export interface ResSaveShrinkage {}
   export interface ReqDeleteShrinkage {
     list: any[];
   }
-  export interface ResDeleteShrinkage {
-    
-  }
+  export interface ResDeleteShrinkage {}
 
   export interface ReqSaveSpring {
     spring: any;
   }
-  export interface ResSaveSpring {
-
-  }
+  export interface ResSaveSpring {}
   export interface ReqDeleteSpring {
     list: any[];
   }
-  export interface ResDeleteSpring {
-    
-  }
+  export interface ResDeleteSpring {}
   export interface ReqAuditSpring {
     list: any[];
     type: number;
   }
-  export interface ResAuditSpring {
-    
-  }
+  export interface ResAuditSpring {}
   export interface ReqSaveBedNetVar {
     bednetvar: any;
   }
-  export interface ResSaveBedNetVar {
-
-  }
+  export interface ResSaveBedNetVar {}
   export interface ReqDeleteBedNetVar {
     list: any[];
   }
-  export interface ResDeleteBedNetVar {
-    
-  }
+  export interface ResDeleteBedNetVar {}
   export interface ResGetMtrlTypeList {
     list: any[];
     reList: any[];
@@ -1157,101 +1131,69 @@ export namespace Basicinfo {
   export interface ReqSaveMtrlType {
     mtrltype: any;
   }
-  export interface ResSaveMtrlType {
-
-  }
+  export interface ResSaveMtrlType {}
   export interface ReqDeleteMtrlType {
     list: any[];
   }
-  export interface ResDeleteMtrlType {
-    
-  }
+  export interface ResDeleteMtrlType {}
   export interface ReqSaveMtrlDef {
     mtrldef: any;
   }
-  export interface ResSaveMtrlDef {
-
-  }
+  export interface ResSaveMtrlDef {}
   export interface ReqDeleteMtrlDef {
     list: any[];
   }
-  export interface ResDeleteMtrlDef {
-    
-  }
+  export interface ResDeleteMtrlDef {}
   export interface ReqBanMtrlDef {
     list: any[];
     type: Number;
   }
-  export interface ResBanMtrlDef {
-    
-  }
+  export interface ResBanMtrlDef {}
   export interface ReqSaveMultiPrice {
     price: any;
   }
-  export interface ResSaveMultiPrice {
-
-  }
+  export interface ResSaveMultiPrice {}
   export interface ReqDeleteMultiPrice {
     list: any[];
   }
-  export interface ResDeleteMultiPrice {
-    
-  }
+  export interface ResDeleteMultiPrice {}
   export interface ReqBanMultiPrice {
     list: any[];
     type: Number;
   }
-  export interface ResBanMultiPrice {
-    
-  }
+  export interface ResBanMultiPrice {}
   export interface ReqSaveBedNetArea {
     area: any;
   }
-  export interface ResSaveBedNetArea {
-
-  }
+  export interface ResSaveBedNetArea {}
   export interface ReqDeleteBedNetArea {
     list: any[];
   }
-  export interface ResDeleteBedNetArea {
-    
-  }
+  export interface ResDeleteBedNetArea {}
   export interface ReqSaveConfigureType {
     area: any;
   }
-  export interface ResSaveConfigureType {
-
-  }
+  export interface ResSaveConfigureType {}
   export interface ReqDeleteConfigureType {
     list: any[];
   }
-  export interface ResDeleteConfigureType {
-    
-  }
+  export interface ResDeleteConfigureType {}
   export interface ReqSaveConfigureCode {
     area: any;
   }
-  export interface ResSaveConfigureCode {
-
-  }
+  export interface ResSaveConfigureCode {}
   export interface ReqDeleteConfigureCode {
     list: any[];
   }
-  export interface ResDeleteConfigureCode {
-    
-  }
+  export interface ResDeleteConfigureCode {}
   export interface ReqSaveConfigureCodeMx {
     area: any;
   }
-  export interface ResSaveConfigureCodeMx {
-
-  }
+  export interface ResSaveConfigureCodeMx {}
   export interface ReqDeleteConfigureCodeMx {
     list: any[];
   }
-  export interface ResDeleteConfigureCodeMx {
-    
-  }
+  export interface ResDeleteConfigureCodeMx {}
 }
 
 export namespace SalePrice {
@@ -1275,23 +1217,35 @@ export namespace SalePrice {
     list: any[];
   }
 
-  export interface ResSaveProfitrate {
-
-  }
+  export interface ResSaveProfitrate {}
 
   export interface ReqSaveWorkmanShip {
     workmanship: any;
   }
 
-  export interface ResSaveWorkmanShip {
-
-  }
+  export interface ResSaveWorkmanShip {}
 
   export interface ReqDeleteWorkmanShip {
     list: any[];
   }
 
-  export interface ResDeleteWorkmanShip {
-    
+  export interface ResDeleteWorkmanShip {}
+}
+
+export namespace Mattress {
+  export interface ReqSaveMattress {
+    mattress: any;
+    mattressMx: any[];
+  }
+  export interface ReqMultiMattress {
+    mattressids: number[];
+    /**
+     * @description 业务下单
+     */
+    xd_flag?: number;
+    /**
+     * @description 审核
+     */
+    flag?: number;
   }
 }

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

@@ -1,48 +1,24 @@
-// import { Quote } from "@/api/interface/index";
-// import { PORT1 } from "@/api/config/servicePort";
-// import authMenuList from "@/assets/json/authMenuList.json";
-// import authButtonList from "@/assets/json/authButtonList.json";
-// import http from "@/api";
-// import type { Menu } from "@/typings/global";
+import { Mattress } from "@/api/interface/index";
+import { PORT1 } from "@/api/config/servicePort";
+import http from "@/api";
 
-// /**
-//  * @name 供应商询价单
-//  */
-// export const getQuote = (params: Quote.ReqQuote) => {
-//   return http.post<Quote.ResQuote>(PORT1 + `/GetQuote`, params);
-// };
+/**
+ * @name 床垫报价保存
+ */
+export const SaveMattress = (params: Mattress.ReqSaveMattress) => {
+  return http.post(PORT1 + `/SaveMattress`, params);
+};
 
-// /**
-//  * @name 供应商询价单明细
-//  */
-// export const getQuoteMx = (params: Quote.ReqQuoteMx) => {
-//   return http.post<Quote.ResQuoteMx>(PORT1 + `/GetQuoteMx`, params);
-// };
+/**
+ * @name 床垫报价:业务下单/取消/审核
+ */
+export const SaveMattressAuditing = (params: Mattress.ReqMultiMattress) => {
+  return http.post(PORT1 + `/SaveMattressAuditing`, params);
+};
 
-// /**
-//  * @name 最新报价统计表-根据物料获取其历史报价记录
-//  */
-// export const getMtrlQuoteHistory = (params: Quote.ReqQuote) => {
-//   return http.post<Quote.ResQuote>(PORT1 + `/GetMtrlQuoteHistory`, params);
-// };
-
-// /**
-//  * @name 保存 供应商询价单
-//  */
-// export const saveQuote = (params: Quote.ReqSaveQuote) => {
-//   return http.post(PORT1 + `/SaveQuote`, params, { loading: true });
-// };
-
-// /**
-//  * @name 发送 供应商询价单
-//  */
-// export const sendQuote = (params: Quote.ReqQuoteMx) => {
-//   return http.post(PORT1 + `/SendQuote`, params, { loading: true });
-// };
-
-// /**
-//  * @name 物料监控表
-//  */
-// export const getL1APPRpMtrlWillRqQty = (params: Quote.ReqQuoteMx) => {
-//   return http.post(PORT1 + `/GetL1APPRpMtrlWillRqQty`, params, { loading: true });
-// };
+/**
+ * @name 床垫报价:删除
+ */
+export const DelMattress = (params: Mattress.ReqMultiMattress) => {
+  return http.post(PORT1 + `/DelMattress`, params);
+};

+ 32 - 30
JLHWEB/src/components/LjDetail/components/ButtonGroup.vue

@@ -9,7 +9,7 @@ import mittBus from "@/utils/mittBus";
 import { MittEnum } from "@/enums/mittEnum";
 import { cloneDeep, pick, get, omit, defaultsDeep } from "lodash-es";
 import { More, ArrowDown, ArrowRight } from "@element-plus/icons-vue";
-import { isArray, isObject } from "@/utils/is";
+import { isArray, isFunction, isObject } from "@/utils/is";
 
 type Props = {
   /**
@@ -89,9 +89,19 @@ const resize = (e: UIEvent) => {
 const getNotLimited = (data: any) => {
   let arr = data.map((item: any) => {
     if (isArray(item)) {
-      return item.filter(itm => !itm?.limited);
+      return item.filter(itm => {
+        if (isFunction(itm?.limited)) {
+          return !itm?.limited();
+        } else {
+          return !itm?.limited;
+        }
+      });
     } else if (isObject(item)) {
-      return !item?.limited && item;
+      if (isFunction(item?.limited)) {
+        return !item?.limited() && item;
+      } else {
+        return !item?.limited && item;
+      }
     }
   });
   return arr.filter((item: any) => item);
@@ -118,6 +128,17 @@ const getIconSlot = (item: any) => {
   return iconRender;
 };
 
+/**
+ * @description el-skeleton loading
+ */
+const isLoading = computed(() => {
+  if (typeof props.data == "undefined") {
+    return false;
+  } else {
+    return Object.keys(props.data).length == 0;
+  }
+});
+
 /**
  * @description 按钮组渲染
  */
@@ -177,14 +198,7 @@ const buttonItemRender = (item: any) => {
     }
   };
 
-  return (
-    <el-skeleton
-      animated={true}
-      loading={!props.data || Object.keys(props.data).length == 0}
-      class="mr-12"
-      v-slots={childrenSlot}
-    ></el-skeleton>
-  );
+  return <el-skeleton animated={true} loading={isLoading.value} class="mr-12" v-slots={childrenSlot}></el-skeleton>;
 };
 
 /**
@@ -263,7 +277,7 @@ const bottonDropdownRender = (item: any, placement?: string) => {
   /**
    * @description 判断是否为菜单按钮
    */
-  let ifMenu = !_item.hasOwnProperty("clickFunc") ?? false;
+  let ifMenu = !_item.hasOwnProperty("clickFunc");
   let idx = ifMenu ? 1 : 0; // 若是菜单按钮,下拉菜单跳过第一个
   let ifShowDot = false;
   let _buttonsRd = item.map((itm: any, index: number) => {
@@ -352,13 +366,7 @@ const bottonDropdownRender = (item: any, placement?: string) => {
     }
   };
 
-  return (
-    <el-skeleton
-      animated={true}
-      loading={!props.data || Object.keys(props.data).length == 0}
-      v-slots={childrenSlot}
-    ></el-skeleton>
-  );
+  return <el-skeleton animated={true} loading={isLoading.value} v-slots={childrenSlot}></el-skeleton>;
 };
 
 const RenderButtonGroup = () => {
@@ -390,9 +398,10 @@ const RenderButtonGroup = () => {
       }
     });
     btnListRender = btnListRender.filter((item: any) => item);
-    // console.log("RenderButtonGroup btnListRender :>> ", btnListRender);
+    // console.log("RenderButtonGroup btnListRender :>> ", btnListRender, butttons);
 
-    if (btnListRender.length < butttons?.length) {
+    let curButtons = butttons?.filter(item => !Array.isArray(item) || item.length > 0);
+    if (btnListRender.length < curButtons?.length) {
       let dropdownRender = butttons.map((item: any, index: number) => {
         if (index + 1 <= keyIndex) return;
 
@@ -445,19 +454,12 @@ const RenderButtonGroup = () => {
         }
       };
 
-      menuListRender.push(
-        <el-skeleton
-          animated
-          loading={!props.data || Object.keys(props.data).length == 0}
-          class="mr-12"
-          v-slots={childrenSlot}
-        ></el-skeleton>
-      );
+      menuListRender.push(<el-skeleton animated loading={isLoading.value} class="mr-12" v-slots={childrenSlot}></el-skeleton>);
     }
   }
 
   // console.log("btnListRender :>> ", btnListRender);
-  // console.log("menuListRender :>> ", menuListRender);
+  // console.log("RenderButtonGroup menuListRender :>> ", menuListRender);
   return (
     <>
       <el-button-group class="detail-menu__btn-group">{btnListRender}</el-button-group>

+ 2 - 1
JLHWEB/src/components/LjDetail/index.vue

@@ -1535,7 +1535,7 @@ const RenderTabs = (rProps: DetailProp) => {
           return tasItemRender(item, () => {
             let val = _detailData.value && _detailData.value[item.id];
             return slots[item.id]?.({
-              data: val,
+              data: _mainData.value,
               props: item,
               orderStatus: orderStatus.value,
               isScrollspy: isScrollspy.value,
@@ -1772,6 +1772,7 @@ defineExpose({
   layoutHeader,
   enumMap,
   currentMould,
+  tabsActive,
   toSaveFoldLayout,
   toSetFloatBtnChange,
   refresh: layoutRefresh

+ 3 - 3
JLHWEB/src/components/LjSelector/select.vue

@@ -64,9 +64,9 @@ const emit = defineEmits(["select", "update:value", "openModal", "focus"]);
 const LjSelectSelectRef = ref();
 
 const handleSelect = (item: any) => {
-  if (item.disabled) {
-    return;
-  }
+  // if (item.disabled) {
+  //   return;
+  // }
   if (!props.beforeSelect(item)) {
     return;
   }

+ 2 - 68
JLHWEB/src/components/ToastWidget/Formula/index.vue

@@ -65,7 +65,7 @@ export interface formulasProp {
 }
 
 // 接收父组件参数并设置默认值
-interface LjOaFlowProps {
+interface WidgetProps {
   /**
    * @description i18n
    */
@@ -105,7 +105,7 @@ interface LjOaFlowProps {
   fields: formulasProp[];
   showFormula?: boolean;
 }
-const props = withDefaults(defineProps<LjOaFlowProps>(), {
+const props = withDefaults(defineProps<WidgetProps>(), {
   requestAuto: true,
   hideClose: false,
   data: () => {}
@@ -122,23 +122,6 @@ const { itemData, oaFlowList, tabsValue, currentOaflow, oaDocStatus, isCurEmp, h
   props.powerid
 );
 
-// watch(
-//   [() => props.scid, () => props.billid],
-//   (val: any) => {
-//     console.log("watch oaflow val :>> ", val);
-//     getOaFlowList(val[0], val[1]).then(() => {
-//       if (oaFlowList.value.length > 0) {
-//         let _index: any = tabsValue.value ?? 0;
-//         console.log("onMounted oaFlowList.value :>> ", oaFlowList.value);
-//         console.log("onMounted _index :>> ", _index);
-//         let { docid } = oaFlowList.value[_index];
-//         getOaFlowItem(docid);
-//       }
-//     });
-//   },
-//   {}
-// );
-
 const getOaFlowItem = async (docid: number) => {
   // 流转状况
   let { datatable } = await CommonDynamicSelect({
@@ -151,55 +134,6 @@ const getOaFlowItem = async (docid: number) => {
   itemData.value = datatable;
 
   console.log("currentOaflow :>> ", currentOaflow.value);
-
-  // if (currentOaflow.value) {
-  //   let _data = currentOaflow.value;
-  //   toast(
-  //     {
-  //       component: ToastErrCopy,
-  //       props: {
-  //         type: "info",
-  //         title: "待你审批",
-  //         message: _data.doctitle + "<br/>" + _data.flowstepname + ":" + _data.flowinfo,
-  //         actions: [
-  //           {
-  //             label: t("common.agree"),
-  //             value: 1,
-  //             props: {
-  //               type: "success"
-  //             }
-  //           },
-  //           {
-  //             label: t("common.oppose"),
-  //             value: 0,
-  //             props: {
-  //               type: "danger"
-  //             }
-  //           }
-  //         ]
-  //       },
-  //       listeners: {
-  //         actionClick: (data: any) => {
-  //           console.log("data :>> ", data);
-  //           if (data.value) {
-  //             // agree
-  //             handleOpenBox(true);
-  //           } else {
-  //             // oppose
-  //             handleOpenBox(false);
-  //           }
-  //         }
-  //       }
-  //     },
-  //     {
-  //       position: POSITION.BOTTOM_RIGHT,
-  //       icon: false,
-  //       timeout: 0,
-  //       closeButton: false,
-  //       toastClassName: "longjoe-toast"
-  //     }
-  //   );
-  // }
 };
 const handleClickTabs = () => {
   console.log(tabsValue.value);

+ 168 - 0
JLHWEB/src/components/ToastWidget/HistoryPrice/components/Item.vue

@@ -0,0 +1,168 @@
+<template>
+  <div class="oa-flow-item flx">
+    <div class="oa-flow-item__left flx-shrink text-body-r">
+      <!-- <template v-if="index == 0">
+        {{ t("table.oa_doc.opd") }}
+      </template>
+      <template v-else>
+        {{ item.flowstepname }}
+      </template> -->
+      <span class="icon">
+        <!-- <i v-if="index == 0" class="iconfont iconSend"></i> -->
+        <i v-if="Number(item.oarowid)" class="iconfont iconLocation"></i>
+        <i v-else-if="Number(item.passed)" class="iconfont iconcheck-circle-fill"></i>
+        <span v-else class="undone"></span>
+      </span>
+    </div>
+    <main class="oa-flow-item__right flx-1">
+      <header class="flx">
+        <span class="flx-1">
+          {{ item.cmpemp }}
+        </span>
+        <span class="text-body-r" :title="item.cmpdate">
+          <el-icon><Calendar /></el-icon>
+          {{ isFilterTime(item.cmpdate) }}
+        </span>
+      </header>
+      <section class="flx-justify-between mt-4">
+        <!-- <div style="margin: auto; margin-top: 0">
+          <AvatarIcon size="small" :username="item.empname"></AvatarIcon>
+        </div> -->
+        <!-- <div class="oa-flow-item__right-content flx-1 flx"> -->
+        <div class="oa-flow-item__right-content-title flx-col flx-center">
+          <div class="text-f-c text-disable">不含税部门价</div>
+          <span class="text-h5-b text-primary-text">
+            {{ isFilterPrice(item.nottax_dept_cost) }}
+          </span>
+        </div>
+        <div class="oa-flow-item__right-content-title flx-col flx-center">
+          <div class="text-f-c text-disable">含税部门价</div>
+          <span class="text-h5-b text-primary-text">
+            {{ isFilterPrice(item.dept_cost) }}
+          </span>
+        </div>
+        <div class="oa-flow-item__right-content-title flx-col flx-center">
+          <div class="text-f-c text-disable">外币价</div>
+          <span class="text-h5-b text-primary-text">
+            {{ isFilterPrice(item.foreign_cost) }}
+          </span>
+        </div>
+        <!-- </div> -->
+      </section>
+    </main>
+  </div>
+</template>
+
+<script setup lang="tsx" name="LjToastOaFlowItem">
+import { ref, watch } from "vue";
+import { formatTime, formatAmount3 } from "@/utils/index";
+import { Calendar } from "@element-plus/icons-vue";
+
+interface wigetProps {
+  t: any;
+  item: any;
+  /**
+   * @description 索引
+   */
+  index: number;
+  /**
+   * @argument 当前待审批
+   */
+  current?: any;
+  nowtime?: string;
+}
+
+const props = withDefaults(defineProps<wigetProps>(), {
+  // item: {},
+  current: undefined
+});
+
+const isFilterTime = time => {
+  return formatTime(time, "", true);
+};
+
+const isFilterPrice = data => {
+  return formatAmount3({ val: data });
+};
+</script>
+
+<style lang="scss" scoped>
+.oa-flow-item {
+  margin-top: $space-a2;
+  padding-top: $space-b1;
+  padding-bottom: $space-b1;
+  &__left {
+    position: relative;
+    width: 0;
+    text-align: right;
+    padding-right: $space-a2;
+    // line-height: 1;
+
+    .icon {
+      position: absolute;
+      right: 0;
+      top: 0;
+      transform: translateX(50%);
+
+      // .iconfont {
+      //   background-color: $color-gray-1;
+      // }
+
+      .undone {
+        margin-top: $space-a1;
+        display: block;
+        border-radius: 50%;
+        width: $space-b2;
+        height: $space-b2;
+        background-color: $color-gray-6;
+      }
+    }
+  }
+  &__right {
+    padding-left: $space-a2;
+    &-content {
+      margin-left: $space-a1;
+      // border-radius: $br-sm;
+      // background-color: $color-gray-3;
+      // padding: $space-a1;
+    }
+    .limittime {
+      color: $color-dust-red-6;
+    }
+  }
+
+  &.is-done {
+    // color: $color-text-primary-text;
+    color: $color-gray-8;
+    .oa-flow-item__left {
+      .icon {
+        // color: $color-polar-green-6;
+        // color: $color-polar-green-6;
+        color: $color-gray-8;
+      }
+    }
+  }
+  &.no-done {
+    color: $color-gray-6;
+    .oa-flow-item__left {
+      .icon {
+        color: $color-gray-6;
+      }
+    }
+  }
+  &.is-current {
+    background-color: $color-primary-000;
+    border-radius: $br-md;
+    .oa-flow-item__left {
+      font-weight: bold;
+      .icon {
+        color: $color-primary-500;
+
+        .iconfont {
+          font-size: $space-b3;
+        }
+      }
+    }
+  }
+}
+</style>

+ 138 - 0
JLHWEB/src/components/ToastWidget/HistoryPrice/index.vue

@@ -0,0 +1,138 @@
+<template>
+  <div class="lj-toast-hisprice flx-col w-full">
+    <header class="flx">
+      <span class="flx-1 text-h5-b">{{ t("business.detail.historyPrice") }}</span>
+      <el-button v-if="!hideClose" circle text :icon="Refresh" @click="refresh(id, typeid, true)"></el-button>
+      <el-button v-if="!hideClose" circle text :icon="CloseBold" @click="emit('close-toast')"></el-button>
+    </header>
+    <main class="w-full lj-toast-hisprice__main" :class="{ 'is-empty': !data.length }">
+      <div class="lj-toast-hisprice__main-content" v-if="data.length">
+        <HisItem :data-ref="'item' + index" v-for="(itm, index) in data" :t="t" :item="itm" :index="index" :key="index" />
+      </div>
+      <el-empty v-else :description="t('sys.empty.nodate')" />
+    </main>
+    <footer></footer>
+  </div>
+</template>
+
+<script setup lang="ts" name="LjToastOaFlow">
+import { ref, onMounted, computed, watch } from "vue";
+import { useDesign } from "@/hooks/useDesign";
+import { CommonDynamicSelect } from "@/api/modules/common";
+import { useUserStore } from "@/stores/modules/user";
+import HisItem from "./components/Item.vue";
+import { CloseBold, Refresh } from "@element-plus/icons-vue";
+import { ElButton, ElMessage } from "element-plus";
+
+// 接收父组件参数并设置默认值
+interface WidgetProps {
+  /**
+   * @description i18n
+   */
+  t: any;
+  /**
+   * @description 单据id
+   */
+  id?: any;
+  /**
+   * @description 单据类型id
+   */
+  typeid?: any;
+  /**
+   * @description 状态enum
+   */
+  statusEnum?: any;
+  /**
+   * @description 是否隐藏关闭按钮
+   */
+  hideClose?: boolean;
+}
+const props = withDefaults(defineProps<WidgetProps>(), {
+  hideClose: false
+  // showFooter: true
+});
+const emit = defineEmits(["close-toast", "refresh"]);
+
+const data = ref<any>([]);
+
+// const { t } = useI18n();
+const { userInfo } = useUserStore();
+// const { prefixCls } = useDesign("toast-oa-flow");
+
+const refresh = async (id: number, typeid: number, tips?: boolean) => {
+  let _params = {
+    dsname: "web_his_price",
+    queryparams: {
+      arg_id: id,
+      arg_typeid: typeid
+    }
+  };
+  let res = await CommonDynamicSelect(_params);
+  console.log("watch res :>> ", res);
+  data.value = res?.datatable?.length ? res?.datatable : [];
+
+  if (tips) {
+    ElMessage.success(props.t("sys.api.sueccessToRefresh"));
+  }
+};
+
+watch(
+  [() => props.id, () => props.typeid],
+  (val: any) => {
+    console.log("watch oaflow val :>> ", val);
+    // refresh(val[0], val[1])
+    refresh(0, 1);
+  },
+  { immediate: true }
+);
+
+// onMounted(() => {
+//   console.log("onMounted props.data 初始化:>> ", props.data);
+//   // if (props.data) {
+//   //   oaFlowList.value = props.data;
+//   //   oaFlowList.value.length > 0 && handleClickTabs();
+//   // }
+// });
+</script>
+
+<style lang="scss" scoped>
+.lj-toast-hisprice {
+  width: 240px;
+
+  :deep(.el-tabs__header) {
+    margin-bottom: 0;
+  }
+
+  &__main {
+    &-content {
+      overflow-y: auto;
+      max-height: 60vh;
+    }
+  }
+  &__main:not(.is-empty) {
+    position: relative;
+
+    &:before {
+      content: "";
+      position: absolute;
+      left: 0;
+      width: 1px;
+      top: 0;
+      bottom: 0;
+      // height: 100%;
+      transform: translateX($space-a2);
+      z-index: -1;
+
+      background: repeating-linear-gradient(
+        to bottom,
+        $color-gray-6,
+        $color-gray-6 10px,
+        transparent 10px,
+        transparent 20px
+      ); /* 创建一条虚线背景 */
+      // height: 1px; /* 设置元素的高度为1像素 */
+      // width: 100%; /* 设置元素的宽度为100% */
+    }
+  }
+}
+</style>

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

@@ -17,5 +17,9 @@ export enum MittEnum {
   /**
    * @description 组件LjOAFlow,获取流转状况的信息
    */
-  OAFlowChange = "OAFlowChange"
+  OAFlowChange = "OAFlowChange",
+  /**
+   * @description 床垫报价刷新
+   */
+  MattressList = "MattressList"
 }

+ 7 - 0
JLHWEB/src/languages/modules/zh-cn/business.json

@@ -332,6 +332,11 @@
     },
     "cust": {
       "name": "输入客户编号/名称"
+    },
+    "mattress": {
+      "records": "请先选择需要操作的数据",
+      "addMx": "是否确定要增加明细行吗?",
+      "delMx": "是否确定要删除当前明细行吗?"
     }
   },
   "searchProject": {
@@ -426,6 +431,8 @@
     "delConfirm": "确定要删除用户:",
     "formula": "计算公式",
     "summaryOfQuote": "报价汇总",
+    "quoteList": "报价清单",
+    "historyPrice": "历史报价",
     "fabric": "面料",
     "bednet": "床网",
     "cushions": "垫层",

+ 9 - 1
JLHWEB/src/languages/modules/zh-cn/common.json

@@ -189,6 +189,7 @@
   "quit": "退出",
   "copyQuote": "复制报价",
   "businessOrder": "业务下单",
+  "businessOrderCancel": "取消业务下单",
   "viewHistoricalQuotes": "查看历史报价",
   "showFormula": "显示计算公式",
   "enabled": "开启",
@@ -197,5 +198,12 @@
   "insert": "插入",
   "moveUp": "上移",
   "moveDown": "下移",
-  "delAllMx": "删除所有明细"
+  "delAllMx": "删除所有明细",
+  "copyFromMulitFlag": "已审批复制",
+  "recalculateFromNotFlag": "未审批重算",
+  "showQuoteList": "显示报价清单",
+  "exportQuoteList": "导出报价清单",
+  "dataTransmission": "数据发送",
+  "businessSupplement": "业务补充",
+  "recalculateERPCost": "重算ERP成本"
 }

+ 6 - 2
JLHWEB/src/styles/element.scss

@@ -119,11 +119,15 @@
 
   // 表格 header 样式
   .table-header {
+    display: flex;
     .header-button-lf {
-      float: left;
+      // float: left;
+      flex: 1;
     }
     .header-button-ri {
-      float: right;
+      // float: right;
+      flex-shrink: 0;
+      margin-left: $space-a2;
 
       .el-dropdown + .el-button {
         margin-left: 12px;

+ 38 - 5
JLHWEB/src/utils/index.ts

@@ -1069,7 +1069,8 @@ const parseTime = (time: any, cFormat?: string) => {
  * @param {string} option
  * @returns {Number} (秒)
  */
-const formatTime = function (time: string | number, option: string, ifshort: boolean, nowtime?: string) {
+export const formatTime = function (time: string | number, option: string, ifshort: boolean, nowtime?: string) {
+  const _time = new Date(time);
   const d = new Date(time);
   const now = nowtime ? new Date(nowtime) : new Date();
 
@@ -1087,7 +1088,7 @@ const formatTime = function (time: string | number, option: string, ifshort: boo
       // 1~6小时
       return Math.ceil(diff / 3600) + "小时前";
     }
-    let hourMins = parseTime(time, "{h}:{i}");
+    let hourMins = parseTime(_time, "{h}:{i}");
     let isSameDay = now.setHours(0, 0, 0, 0) - d.setHours(0, 0, 0, 0);
     switch (isSameDay) {
       case 0:
@@ -1098,14 +1099,14 @@ const formatTime = function (time: string | number, option: string, ifshort: boo
       //     return `前天 ${hourMins}`
     }
     if (now.getFullYear() == d.getFullYear()) {
-      return parseTime(time, "{m}-{d} {h}:{i}");
+      return parseTime(_time, "{m}-{d} {h}:{i}");
     } else {
-      return parseTime(time, "{y}-{m}-{d} {h}:{i}");
+      return parseTime(_time, "{y}-{m}-{d} {h}:{i}");
     }
   }
 
   if (option) {
-    return parseTime(time, option);
+    return parseTime(_time, option);
   }
 };
 
@@ -1202,3 +1203,35 @@ export const calculateFormula = async (formulaList, fieldList, valueList) => {
     return [];
   }
 };
+
+/**
+ * @description LjVxeTable获取当前表格选中数据;默认第一条记录
+ * @param targetRef 表格ref
+ * @returns {$table, curRecords} 当前表格对象,当前选中数据
+ */
+export const getCurrentRecords = (targetRef: any) => {
+  const $table = targetRef.element;
+
+  const _records = $table.getCheckboxRecords() ?? [];
+  const _cRecords = $table.getCurrentRecord() ?? null;
+
+  let curRecords = [];
+  if ($table) {
+    if (_records.length) {
+      // 获取勾选列表
+      curRecords = _records;
+    } else if (_cRecords) {
+      // 获取当前选中数据
+      curRecords = [_cRecords];
+    } else {
+      // 默认获取第一条记录
+      let fullData = $table.getTableData().fullData;
+      if (fullData.length) {
+        curRecords = [fullData[0]];
+        $table.setCurrentRow(fullData[0]);
+      }
+    }
+  }
+
+  return { $table, curRecords };
+};

+ 1 - 1
JLHWEB/src/utils/pinyin.ts

@@ -36,7 +36,7 @@ export function pinyinFilter(inputValue: string, totalList: any, props: string |
 
   // Helper函数来检查节点是否匹配
   function isNodeMatch(node: any, prop: string): boolean {
-    const value = get(node, prop, "") as string;
+    const value = String(get(node, prop, ""));
     return value.includes(inputValue) || getMatch(value, pyInput);
   }
 

+ 68 - 1
JLHWEB/src/views/baseinfo/user/detail.vue

@@ -21,6 +21,20 @@
           <el-col :xs="24" :sm="12" :md="8" :lg="8" :xl="8" class="h-full overflow-auto">
             <div class="flx-col">
               <LjHeader class="flx-shrink" size="small" :title="$t('business.detail.syspwr')">
+                <template #title>
+                  <div class="flx">
+                    <span>{{ $t("business.detail.syspwr") }}</span>
+                    <el-input
+                      ref="filterInputRef"
+                      v-model="filterText"
+                      class="flx-1 ml-12 mr-12"
+                      clearable
+                      title="支持拼音、首字母,检索名称、funcid"
+                      placeholder="支持拼音、首字母,检索名称、funcid"
+                    ></el-input>
+                  </div>
+                  <!-- <el-button :icon="!ifSearch ? Search : Close" circle @click.stop="searchCompany" /> -->
+                </template>
                 <template #toolButton>
                   <el-checkbox v-model="ifAllFuncpwr" :indeterminate="isIndeterminate" @change="handleSelectAllFuncpwr">{{
                     $t("common.table.selectAll")
@@ -38,6 +52,7 @@
                   :default-checked-keys="defaultCheckedKeys_sysfunc"
                   :expand-on-click-node="false"
                   check-on-click-node
+                  :filter-node-method="filterNode"
                   @check-change="autoCheckSysFuncPwr"
                 >
                 </el-tree>
@@ -135,8 +150,10 @@ import { useAuthButtons } from "@/hooks/useAuthButtons";
 import LjHeader from "@/components/LjHeader/index.vue";
 import LjVxeTable from "@/components/LjVxeTable/index.vue";
 import { cloneDeep } from "lodash-es";
-import { ElMessage } from "element-plus";
+import { ElMessage, ElNotification } from "element-plus";
 import { saveUserList, delUserList } from "@/api/modules/basicinfo";
+// import { Search, Close } from "@element-plus/icons-vue";
+import { pinyinFilter } from "@/utils/pinyin";
 
 interface detailProp {
   /**
@@ -604,6 +621,56 @@ const tableEvents = {
   // "edit-closed": autoEditClosed
 };
 
+const ifSearch = ref(false);
+const filterText = ref();
+const filterInputRef = ref();
+
+// /**
+//  * @description 搜索
+//  */
+//  const searchCompany = () => {
+//   // if (!ifSearch.value) {
+//   //   ifSearch.value = true;
+//     nextTick(() => {
+//       filterInputRef.value.focus();
+//     });
+//   // } else {
+//   //   ifSearch.value = false;
+//   //   filterText.value = "";
+//   //   sysFuncPwrTreeRef.value!.filter("");
+//   // }
+// };
+// 关键字,筛选
+watch(filterText, val => {
+  sysFuncPwrTreeRef.value!.filter(val);
+});
+
+// 筛选钩子
+const filterNode = (value: string, data: any, node: any) => {
+  if (!value) return true;
+  return partentFilter(value, data, node);
+};
+
+/**
+ * 拼音筛选,父级符合,其自己,孙集均符合
+ * @param value keyword
+ * @param data 当前层级数据
+ * @param node 节点
+ */
+const partentFilter = (value: string, data: any, node: any): boolean => {
+  let arr = pinyinFilter(value, [data], ["treename", "menuname", "funcid"]);
+  console.log("arr :>> ", arr);
+  console.log("data :>> ", data);
+  console.log("node.parent level :>> ", node.parent.level);
+  if (arr.length > 0) {
+    return true;
+  } else if (node.parent.level > 0) {
+    return partentFilter(value, node.parent.data, node.parent);
+  } else {
+    return false;
+  }
+};
+
 defineExpose({
   refresh
 });

+ 484 - 0
JLHWEB/src/views/quote/mattressQuote/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>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 726 - 240
JLHWEB/src/views/quote/mattressQuote/detail.vue


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1116 - 94
JLHWEB/src/views/quote/mattressQuote/hooks/index.tsx


+ 302 - 9
JLHWEB/src/views/quote/mattressQuote/index.vue

@@ -16,14 +16,15 @@
     >
       <!-- 表格 header 按钮 -->
       <template #tableHeader>
-        <el-button-group>
-          <el-button>{{ $t("common.add") }}</el-button>
-          <el-button>{{ $t("common.delText") }}</el-button>
-          <el-button>{{ $t("common.auditFinance") }}</el-button>
-          <el-button>{{ $t("common.copyQuote") }}</el-button>
-          <el-button>{{ $t("common.businessOrder") }}</el-button>
-          <el-button>{{ $t("common.viewHistoricalQuotes") }}</el-button>
-        </el-button-group>
+        <LjHeaderMenu :update="dialogVisible" :action="action" />
+        <!-- <el-button-group>
+          <el-button @click="toAdd">{{ $t("common.add") }}</el-button>
+          <el-button @click="toDel">{{ $t("common.delText") }}</el-button>
+          <el-button @click="toA">{{ $t("common.auditFinance") }}</el-button>
+          <el-button @click="toAdd">{{ $t("common.copyQuote") }}</el-button>
+          <el-button @click="toAdd">{{ $t("common.businessOrder") }}</el-button>
+          <el-button @click="toAdd">{{ $t("common.viewHistoricalQuotes") }}</el-button>
+        </el-button-group> -->
       </template>
     </LjVxeTable>
   </div>
@@ -32,7 +33,7 @@
 <script setup lang="ts" name="mattressQuote">
 import { ref, onMounted, inject } from "vue";
 import { useRouter } from "vue-router";
-import { getPriceList } from "@/api/modules/saleprice";
+import { SaveMattressAuditing, DelMattress } from "@/api/modules/quote";
 import { CommonDynamicSelect } from "@/api/modules/common";
 import { ColumnProps } from "@/components/LjVxeTable/interface";
 import LjDrawer from "@/components/LjDrawer/index.vue";
@@ -46,6 +47,13 @@ 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();
@@ -54,6 +62,8 @@ const { columns } = 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);
@@ -148,4 +158,287 @@ const tableEvents = {
   "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: 72,
+    clickFunc: item => {
+      router.push(`/mattressQuote/new?id=0`);
+    }
+  }),
+  buttonDefault({
+    label: t("common.editText"),
+    power: 72,
+    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(`/mattressQuote/edit?id=${_cur.mattressid}&code=${_cur.mattresscode}`);
+      } else {
+        const _cur = curRecords[curRecords.length - 1];
+        router.push(`/mattressQuote/edit?id=${_cur.mattressid}&code=${_cur.mattresscode}`);
+      }
+    }
+  }),
+  buttonDefault({
+    label: t("common.delText"),
+    power: 77,
+    disabledTextCallBack: (data: any) => {
+      if (!CheckPower(77)) {
+        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 _mattressids = curRecords.map((item: any) => Number(item.mattressid));
+
+      ElMessageBox.confirm(`是否确定要删除${curRecords.length}张床垫报价单吗?`, "询问", {
+        confirmButtonText: t("common.delText"),
+        cancelButtonText: "否",
+        type: "warning"
+      })
+        .then(() => {
+          DelMattress({ mattressids: _mattressids }).then(() => {
+            ElMessage.success("删除成功!");
+
+            vxeTableRef.value.refresh();
+          });
+        })
+        .catch((e: TypeError) => {
+          console.log("e :>> ", e);
+          ElMessage({
+            type: "info",
+            message: "操作取消"
+          });
+        });
+    }
+  }),
+  buttonDefault({
+    label: t("common.copyQuote"),
+    power: 75,
+    clickFunc: item => {
+      router.push(`/mattressQuote/new?id=0`);
+    }
+  }),
+  [
+    buttonDefault({
+      label: t("common.businessOrder"),
+      power: 94,
+      clickFunc: item => {
+        toAuditing({ xd_flag: 1 }, t("common.businessOrder"));
+      }
+    }),
+    buttonDefault({
+      label: t("common.businessOrderCancel"),
+      power: 95,
+      clickFunc: item => {
+        toAuditing({ xd_flag: 0 }, t("common.businessOrder"));
+      }
+    })
+  ],
+  [
+    buttonDefault({
+      label: t("common.auditFinance"),
+      power: 73,
+      clickFunc: item => {
+        toAuditing({ flag: 1 }, t("common.auditFinance"));
+      }
+    }),
+    buttonDefault({
+      label: t("common.withdrawAuditFinance"),
+      power: 74,
+      clickFunc: item => {
+        toAuditing({ flag: 0 }, t("common.withdrawAuditFinance"));
+      }
+    })
+  ],
+  buttonDefault({
+    label: t("common.copyFromMulitFlag"),
+    power: 72,
+    clickFunc: item => {
+      router.push(`/mattressQuote/new?id=0`);
+    }
+  }),
+  buttonDefault({
+    label: t("common.recalculateFromNotFlag"),
+    power: 72,
+    clickFunc: item => {
+      router.push(`/mattressQuote/new?id=0`);
+    }
+  }),
+  buttonDefault({
+    label: t("common.viewHistoricalQuotes"),
+    power: 72,
+    clickFunc: item => {
+      router.push(`/mattressQuote/new?id=0`);
+    }
+  }),
+  buttonDefault({
+    label: t("common.showQuoteList"),
+    power: 72,
+    clickFunc: item => {
+      router.push(`/mattressQuote/new?id=0`);
+    }
+  }),
+  buttonDefault({
+    label: t("common.dataTransmission"),
+    power: 72,
+    clickFunc: item => {
+      router.push(`/mattressQuote/new?id=0`);
+    }
+  }),
+  buttonDefault({
+    label: t("common.businessSupplement"),
+    power: 72,
+    clickFunc: item => {
+      // const Exceljs = require("exceljs"); // 引入exceljs
+      const workbook = new Exceljs.Workbook(); // 创建工作簿
+      const workSheet = workbook.addWorksheet("总报价"); // 创建工作表(sheet1)
+      let cols = vxeTableRef.value.tableColumns.map((t: any) => {
+        let res = {
+          header: t.title,
+          key: t.field
+          // width: t.width
+        };
+        return res;
+      });
+      console.log("cols :>> ", cols, vxeTableRef.value.tableData);
+      workSheet.columns = cols; // 工作表添加表头
+      workSheet.addRows(vxeTableRef.value.tableData); // 往工作表插入数据
+      // workSheet.mergeCells("A1:M1"); //将A1到M1的单元格合并
+      // const cell = workSheet.getCell("A1"); // 获取A1单元格
+      // cell.value = "我是A1各自的数据";
+
+      //======================================= 第一行 =================================
+      // 合并A1到L1的单元格 (大标题)
+      workSheet.mergeCells("A1:M1");
+      const cell = workSheet.getCell("A1");
+      cell.value = "Mechanical  CO., LTD. - Quotation \n - 报价单";
+
+      // 设置第一行的单元格样式
+      cell.font = { size: 16, bold: true, name: "仿宋" }; // 设置字体大小为16,加粗,仿宋
+      cell.alignment = {
+        vertical: "middle", // 垂直居中
+        horizontal: "center", // 水平居中
+        wrapText: true // 自动换行
+      };
+      // 调整第一行的高度
+      workSheet.getRow(1).height = 70;
+
+      // 下载工作簿
+      workbook.xlsx.writeBuffer().then(buffer => {
+        saveAs(new Blob([buffer], { type: "application/octet-stream" }), "测试导出.xlsx");
+      });
+    }
+  }),
+  buttonDefault({
+    label: t("common.recalculateERPCost"),
+    power: 72,
+    clickFunc: item => {
+      const $table = vxeTableRef.value.element;
+
+      // 自定义内容
+      const customContent = [
+        ["公司名称", "XX科技有限公司"],
+        ["地址", "XX市XX区XX路XX号"],
+        ["联系方式", "000-0000000"]
+      ];
+      // 导出表格数据
+      $table.exportData({
+        filename: "导出的文件",
+        sheetName: "Sheet1",
+        type: "csv",
+        data: vxeTableRef.value._mainData,
+        original: false,
+        columnFilterMethod({ column }) {
+          // 可以在这里过滤不需要导出的列
+          return true;
+        },
+        getCellFormat({ cellValue, cellColumn }) {
+          // 可以在这里自定义单元格格式
+          return cellValue;
+        },
+        footerFilterMethod() {
+          // 返回自定义的底部内容
+          return customContent;
+        }
+      });
+    }
+  })
+];
+
+/**
+ * @description 监听框架属性变化
+ */
+mittBus.on(MittEnum.MattressList, () => {
+  vxeTableRef.value.refresh();
+});
 </script>

+ 1 - 0
JLHWEB/src/views/system/selector/mtrldef/select.vue

@@ -4,6 +4,7 @@
     v-model:value="props.value"
     value-key="mtrlid"
     :loading="loading"
+    v-bind="$attrs"
     :remote-method="remoteMethod"
     @select="handleSelect"
     @open-modal="openModal"