Browse Source

feat: 新增erp号推荐选择

liaojiaxing 1 week ago
parent
commit
53198d9552

+ 3 - 0
components.d.ts

@@ -12,12 +12,15 @@ declare module 'vue' {
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
+    ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElInput: typeof import('element-plus/es')['ElInput']
     ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
     ElOption: typeof import('element-plus/es')['ElOption']
+    ElRadio: typeof import('element-plus/es')['ElRadio']
+    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElTable: typeof import('element-plus/es')['ElTable']

+ 3 - 7
src/components/mindmap/Mindmap.vue

@@ -130,7 +130,7 @@ onMounted(() => {
               )}
               {data?.is_change && (
                 <ElTooltip content={data?.change_content} placement="top">
-                  <img src={changIco} class="w-20px h-20px inline-block" />
+                  <img src={changIco} class="w-20px h-20px inline-block" alt="" />
                 </ElTooltip>
               )}
               {!id && (
@@ -138,7 +138,7 @@ onMounted(() => {
               )}
               {data?.is_deleted && (
                 <ElTooltip content='删除标记' placement="top">
-                  <img src={deleteIcon} class="w-20px h-20px inline-block" />
+                  <img src={deleteIcon} class="w-20px h-20px inline-block" alt="" />
                 </ElTooltip>
               )}
             </div>
@@ -189,13 +189,9 @@ onMounted(() => {
     } 
   });
 
-  // 视图数据改变
-  // instance.on("view_data_change", (data: any) => {
-  //   console.log("view_data_change", data);
-  // });
-
   // 数据变化详情 delete create update
   instance.on("data_change_detail", (data: any) => {
+    console.log('date change detail', data)
     emit("dataChange", data);
   });
 

+ 49 - 36
src/pages/excel/ConfigDrawer.vue

@@ -41,9 +41,38 @@
           </el-form-item>
         </el-col>
 
+        <el-col :span="12">
+          <el-form-item
+            label="零件名/描述"
+            prop="part_name"
+            :rules="[
+              { required: true, message: '零件名不能为空', trigger: 'blur' },
+            ]"
+          >
+            <el-input placeholder="请输入" v-model="formData.part_name" />
+          </el-form-item>
+        </el-col>
+
         <el-col :span="12">
           <el-form-item label="ERP号" name="erp_code">
-            <el-input placeholder="请输入" v-model="formData.erp_code" />
+            <div class="flex gap-8px">
+              <el-input placeholder="请输入" v-model="formData.erp_code" />
+              <el-button
+                type="text"
+                :icon="CirclePlus"
+                @click="openRecomendModal"
+                >推荐</el-button
+              >
+            </div>
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12">
+          <el-form-item label="客户零件号" name="customer_part_code">
+            <el-input
+              placeholder="请输入"
+              v-model="formData.customer_part_code"
+            />
           </el-form-item>
         </el-col>
 
@@ -66,24 +95,6 @@
           </el-form-item>
         </el-col> -->
 
-        <el-col :span="12">
-          <el-form-item
-            label="客户零件号"
-            name="customer_part_code"
-            :rules="[
-              {
-                required: true,
-                message: '客户零件号不能为空',
-                trigger: 'blur',
-              },
-            ]"
-          >
-            <el-input
-              placeholder="请输入"
-              v-model="formData.customer_part_code"
-            />
-          </el-form-item>
-        </el-col>
         <el-col :span="12">
           <el-form-item label="客户版本号" name="customer_part_vesion">
             <el-input
@@ -93,18 +104,6 @@
           </el-form-item>
         </el-col>
 
-        <el-col :span="12">
-          <el-form-item
-            label="零件名/描述"
-            prop="part_name"
-            :rules="[
-              { required: true, message: '零件名不能为空', trigger: 'blur' },
-            ]"
-          >
-            <el-input placeholder="请输入" v-model="formData.part_name" />
-          </el-form-item>
-        </el-col>
-
         <el-col :span="12">
           <el-form-item label="材料名称" name="material_name">
             <el-input placeholder="请输入" v-model="formData.material_name" />
@@ -243,12 +242,16 @@
       <el-button type="primary" @click="handleSubmit">确定</el-button>
     </template>
   </el-drawer>
+  <TableModal ref="recomendRef" @ok="handleRecomend" />
 </template>
 
 <script setup lang="ts">
 import { ref, defineExpose, defineEmits } from 'vue';
 import type { FormInstance } from 'element-plus';
 import { cloneDeep } from 'lodash-es';
+import { CirclePlus } from '@element-plus/icons-vue';
+import TableModal from './TableModal.vue';
+import type { IRecomend } from './TableModal.vue';
 
 const keyMap = {
   type: '类型',
@@ -307,6 +310,8 @@ let originFormData: any = null;
 const emit = defineEmits(['ok']);
 // 节点数据
 const nodeData = ref<any>(null);
+// 推荐弹窗
+const recomendRef = ref<{ open: (partName: string) => void }>();
 
 const editType = ref<'add' | 'edit'>('edit');
 const open = (node: any, type?: 'add' | 'edit') => {
@@ -319,10 +324,7 @@ const open = (node: any, type?: 'add' | 'edit') => {
     if (type === 'add' || !node?.id) {
       originFormData = cloneDeep(node.data);
       formData.value = {
-        ...node.data,
-        part_name: node.data?.name,
-        part_type: node.data?.type,
-        bom_det: {},
+        ...node.data?.bom_det,
       };
     } else {
       // 编辑 通过接口获取详情
@@ -371,6 +373,18 @@ const open = (node: any, type?: 'add' | 'edit') => {
     loading.value = false;
   }
 };
+
+// 打开推荐
+const openRecomendModal = () => {
+  recomendRef.value?.open(formData.value?.part_name);
+};
+
+// 添加推荐
+const handleRecomend = (record: IRecomend) => {
+  formData.value.erp_code = record.erp_code;
+};
+
+// 关闭
 const close = () => {
   visible.value = false;
   originFormData = null;
@@ -409,7 +423,6 @@ const handleSubmit = async () => {
         str += `${str ? ',' : ''}${keyMap[key as keyof typeof keyMap]}: ${
           originFormData[key] ?? '空'
         }->${value ?? ''}`;
-      console.log(str, editType.value)
       // 更新内部数据
       if (Object.hasOwnProperty.call(nodeData.value || {}, key)) {
         nodeData.value[key] = value;

+ 67 - 19
src/pages/excel/MindmapModal.vue

@@ -42,7 +42,7 @@
       </el-form>
       <div class="flex gap-4px">
         <el-button type="primary" link @click="handleSave" class="mr-8px"
-          ><img class="w-1em mr-4px" :src="saveImg" />保存</el-button
+          ><img class="w-1em mr-4px" :src="saveImg" alt="" />保存</el-button
         >
         <el-tooltip content="添加">
           <el-button
@@ -70,7 +70,7 @@
         </el-tooltip>
         <el-tooltip content="自适应">
           <el-button type="default" circle @click="autoFit">
-            <img :src="AutoIcon" style="width: 1em" />
+            <img :src="AutoIcon" style="width: 1em" alt="" />
           </el-button>
         </el-tooltip>
         <el-tooltip content="定位到根节点">
@@ -110,7 +110,16 @@
 </template>
 
 <script setup lang="ts">
-import { ref, defineExpose, reactive, defineProps, watch, onMounted, onBeforeUnmount, defineEmits } from 'vue';
+import {
+  ref,
+  defineExpose,
+  reactive,
+  defineProps,
+  watch,
+  onMounted,
+  onBeforeUnmount,
+  defineEmits,
+} from 'vue';
 import {
   Aim,
   CirclePlusFilled,
@@ -130,6 +139,7 @@ import ConfigDrawer from './ConfigDrawer.vue';
 import AutoIcon from '@/assets/auto.svg';
 import saveImg from '@/assets/save.svg';
 import { BOMItem } from './data';
+import { cloneDeep } from 'lodash-es';
 
 const props = defineProps<{
   defaultOpen?: boolean;
@@ -245,7 +255,9 @@ const addNode = () => {
 // 删除节点
 const removeNode = () => {
   const mindmap = mindmapRef.value?.getInstance();
-  const activeList = mindmapRef.value?.getActiveNodeList()?.filter(node => !node?.isRoot);
+  const activeList = mindmapRef.value
+    ?.getActiveNodeList()
+    ?.filter((node) => !node?.isRoot);
   if (!activeList?.length) {
     ElMessage.warning('请选择删除节点');
     return;
@@ -271,7 +283,11 @@ const removeNode = () => {
       if (action === 'confirm') {
         deleteNodes.length && mindmap?.execCommand('REMOVE_NODE', deleteNodes);
         updateNodes.forEach((node) => {
-          handleConfigOk({ ...node?.nodeData.data, is_deleted: true });
+          handleConfigOk({
+            ...node?.nodeData.data,
+            is_deleted: true,
+            bom_det: node?.nodeData.data?.bom_det || {},
+          });
         });
       }
     },
@@ -330,26 +346,30 @@ const handleSave = () => {
   const mindmap = mindmapRef.value?.getInstance();
   const data = mindmap?.getData(false);
   let valid = true;
+  let hasAddData = false;
 
   bfsWalk(data, (node: any) => {
-    delete node.smmVersion;
-    delete node.data.uid;
-    delete node.data.expand;
-    delete node.data.isActive;
-    delete node.data.richText;
-    delete node.data.text;
-    delete node.data.id;
+    delete node?.smmVersion;
+    delete node.data?.uid;
+    delete node.data?.expand;
+    delete node.data?.isActive;
+    delete node.data?.richText;
+    delete node.data?.text;
+    delete node.data?.id;
     // TODO: 业务校验
     if (!node.data.name?.trim()) {
       valid = false;
     }
+    if(node.data.is_add) {
+      hasAddData = true;
+    }
   });
 
   if (!valid) {
     ElMessage.error('请检查数据是否填写完整!');
     return;
   }
-  console.log('handleSave', data);
+
   try {
     window.parent?.BpmTools?.program(
       {
@@ -357,8 +377,7 @@ const handleSave = () => {
         model: data,
       },
       (res: any) => {
-        console.log('保存结果:', res);
-        ElMessage.success('保存成功!');
+        ElMessage.success(`保存成功!${hasAddData ? '存在新增数据,待审批后即可展示!' : ''}`);
         emit('refresh');
       }
     );
@@ -378,8 +397,17 @@ const handleDataChange = (newData: any) => {
     const newNodeData = {
       ...(addItem?.data || {}),
       data: {
-        ...newItemData,
         ...addItem?.data?.data,
+        is_deleted: false,
+        is_disable: false,
+        is_change: false,
+        is_add: true,
+        qty: 89,
+        name: '',
+        type: '',
+        bom_code: '',
+        change_content: '',
+        bom_det: newItemData,
       },
     };
     handleConfigOk(newNodeData.data);
@@ -419,17 +447,37 @@ defineExpose({
 
 const handlePressDel = (e: KeyboardEvent) => {
   // 删除节点
-  if ((e.key === 'Delete') && visible.value) {
+  if (e.key === 'Delete' && visible.value) {
     e.preventDefault();
     removeNode();
   }
 };
 
-onMounted(() => { 
+watch(
+  () => data.value,
+  () => {
+    const result = cloneDeep(data.value);
+    if (result?.id && result.id !== 'root') {
+      bfsWalk(result, (node: any) => {
+        delete node.smmVersion;
+        delete node.data?.uid;
+        delete node.data?.expand;
+        delete node.data?.isActive;
+        delete node.data?.richText;
+        delete node.data?.text;
+        delete node.data?.id;
+      });
+      // 缓存编辑结果
+      sessionStorage.setItem(result.id, JSON.stringify(result));
+    }
+  }
+);
+
+onMounted(() => {
   addEventListener('keydown', handlePressDel);
 });
 
-onBeforeUnmount(() => { 
+onBeforeUnmount(() => {
   removeEventListener('keydown', handlePressDel);
 });
 </script>

+ 157 - 0
src/pages/excel/TableModal.vue

@@ -0,0 +1,157 @@
+<template>
+  <el-dialog title="推荐零件" v-model="open">
+    <el-input
+      class="mb-12px"
+      v-model="part_name"
+      placeholder="输入零件名模糊匹配"
+    >
+      <template #append>
+        <el-button :icon="Search" @click="getData" />
+      </template>
+    </el-input>
+    <el-table
+      :loading="loading"
+      :data="dataSource"
+      :max-height="400"
+      @current-change="handleSelect"
+      highlight-current-row
+    >
+      <el-table-column prop="part_name" label="零件名" width="180" />
+      <el-table-column prop="erp_code" label="ERP号" width="180" />
+      <el-table-column prop="part_type" label="类型" width="180">
+        <template #default="{ row }">
+          <span>{{
+            options.find((item) => item.value === row.part_type)?.label
+          }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="appreance_treat" label="表面处理" width="180" />
+      <el-table-column prop="color" label="颜色" width="180" />
+      <el-table-column prop="color_config" label="颜色配置" width="180" />
+      <el-table-column prop="material_grade" label="材料牌号" width="180" />
+      <el-table-column prop="material_name" label="材料名称" width="180" />
+      <el-table-column
+        prop="technology_consume"
+        label="工艺消耗定额"
+        width="180"
+      />
+      <el-table-column prop="length" label="长" width="180" />
+      <el-table-column prop="width" label="宽" width="180" />
+      <el-table-column prop="height" label="高" width="180" />
+      <el-table-column prop="process" label="生产工艺" width="180" />
+      <el-table-column prop="net_weight" label="每件净重" width="180" />
+      <el-table-column prop="rate" label="利用率" width="180" />
+      <el-table-column prop="spec_standards" label="规格及标准" width="180" />
+      <el-table-column prop="supplier" label="供应商" width="180" />
+      <el-table-column prop="unit" label="单位" width="180" />
+    </el-table>
+    <template #footer>
+      <div class="flex justify-between">
+        <div>
+          <span class="text-green text-12px"
+            >当前选择(点击行选择):{{ currentRow?.erp_code }}</span
+          >
+        </div>
+        <div class="dialog-footer">
+          <el-button @click="open = false">取消</el-button>
+          <el-button type="primary" :disabled="!currentRow" @click="handleOk">
+            确定
+          </el-button>
+        </div>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { Search } from '@element-plus/icons-vue';
+import { ref, defineExpose, defineEmits } from 'vue';
+
+export interface IRecomend {
+  process: string;
+  color: string;
+  color_config: string;
+  technology_consume: number;
+  length: number;
+  part_type: string;
+  erp_code: string;
+  appreance_treat: string;
+  width: number;
+  id: string;
+  material_grade: string;
+  material_name: string;
+  part_name: string;
+  height: number;
+}
+
+const options = [
+  { label: '自制', value: 'M' },
+  { label: '外购', value: 'P' },
+  { label: '标准件', value: 'S' },
+  { label: '领用件', value: 'CSMT' },
+  { label: 'DB', value: 'DB' },
+  { label: 'CCC', value: 'CCC' },
+  { label: 'NA', value: 'NA' },
+];
+
+const emit = defineEmits(['ok']);
+
+const open = ref(false);
+const part_name = ref('');
+const dataSource = ref([]);
+const loading = ref(false);
+const currentRow = ref<IRecomend>();
+
+const getData = () => {
+  if (window.parent?.BpmTools?.program) {
+    loading.value = true;
+  }
+
+  // 测试接口
+  // fetch(`https://sl-yf-bommgr-admin-dev.shalu.com/api/module/Invoke`, {
+  //   method: 'POST',
+  //   headers: {
+  //     Authorization: 'bpm_client_1425496253931720704',
+  //     'content-type': 'application/json;charset=UTF-8',
+  //   },
+  //   body: JSON.stringify({
+  //     interfaceCode: 'Common.getPartRecomendList',
+  //     part_name: part_name.value,
+  //   }),
+  // })
+  //   .then((res) => res.json())
+  //   .then((res) => {
+  //     console.log('res', res);
+  //     dataSource.value = res?.result || [];
+  //   });
+
+  window.parent?.BpmTools?.program(
+    {
+      interfaceCode: 'Common.getPartRecomendList',
+      part_name: part_name.value,
+    },
+    (res: any) => {
+      dataSource.value = res || [];
+      loading.value = false;
+    }
+  );
+};
+
+const handleOk = () => {
+  emit('ok', currentRow.value);
+  open.value = false;
+  currentRow.value = undefined;
+};
+
+const handleSelect = (val: IRecomend) => {
+  currentRow.value = val;
+};
+
+defineExpose({
+  open: (str: string = '') => {
+    open.value = true;
+    part_name.value = str;
+    getData();
+  },
+});
+</script>

+ 47 - 13
src/pages/mindmap/index.vue

@@ -12,6 +12,11 @@
 import { onMounted, ref } from 'vue';
 import MindmapModal from '../excel/MindmapModal.vue';
 import { useRoute } from 'vue-router';
+// import { isEqual } from 'lodash-es';
+import {
+  ElLoading,
+  // ElMessageBox
+} from 'element-plus';
 
 const mindmapModalRef = ref<InstanceType<typeof MindmapModal>>();
 const route = useRoute();
@@ -19,15 +24,33 @@ const mindmapData = ref<any>();
 
 const getData = () => {
   if (!route.query?.id) return;
+  // const cache = sessionStorage.getItem(route.query.id as string);
+  // const cacheData = cache ? JSON.parse(cache) : undefined;
+  const loading = window.parent?.BpmTools?.program
+    ? ElLoading.service({
+        lock: true,
+        text: 'Loading',
+        background: 'rgba(0, 0, 0, 0.7)',
+      })
+    : undefined;
   window.parent?.BpmTools?.program(
     {
       interfaceCode: 'Common.getBOMAiImageData',
       bom_id: route.query.id,
     },
     (res: any) => {
-      if (res?.code) {
-        mindmapData.value = res?.data;
-      }
+      loading?.close();
+      // if (cacheData && res?.data && !isEqual(cacheData, res?.data)) {
+      //   ElMessageBox.confirm('当前存在编辑未保存的数据,是否加载缓存数据?')
+      //     .then(() => {
+      //       mindmapData.value = cacheData;
+      //     })
+      //     .catch(() => {
+      //       mindmapData.value = res?.data;
+      //     });
+      // } else if (res?.code) {
+      if (res?.data) mindmapData.value = res.data;
+      // }
     }
   );
 };
@@ -35,24 +58,35 @@ const getData = () => {
 onMounted(() => {
   // 测试接口
   // fetch(`https://sl-yf-bommgr-admin-dev.shalu.com/api/module/Invoke`, {
-  //   method: "POST",
+  //   method: 'POST',
   //   headers: {
-  //     'Authorization': "bpm_client_1421883752157548544",
-  //     "content-type": "application/json;charset=UTF-8",
+  //     Authorization: 'bpm_client_1425496253931720704',
+  //     'content-type': 'application/json;charset=UTF-8',
   //   },
   //   body: JSON.stringify({
-  //     interfaceCode: "Common.getBOMAiImageData",
-  //     bom_id: "7f492047-5127-45fc-9398-b5effd640f79",
+  //     interfaceCode: 'Common.getBOMAiImageData',
+  //     bom_id: '7f492047-5127-45fc-9398-b5effd640f79',
   //   }),
   // })
   //   .then((res) => res.json())
-  //   .then((res) => {
-  //     console.log("res", res);
-  //     mindmapData.value = res.result.data;
+  //   .then((resp) => {
+  //     const res = resp.result
+  //     const cache = sessionStorage.getItem('7f492047-5127-45fc-9398-b5effd640f79');
+  //     const cacheData = cache ? JSON.parse(cache) : undefined;
+  //     console.log('res', res, cacheData);
+  //     if (cacheData && res?.data && !isEqual(cacheData, res?.data)) {
+  //       ElMessageBox.confirm(
+  //         '当前存在编辑未保存的数据,是否加载缓存数据?'
+  //       ).then(() => {
+  //         mindmapData.value = cacheData;
+  //       }).catch(() => {
+  //         mindmapData.value = res?.data;
+  //       });
+  //     } else if (res?.code) {
+  //       mindmapData.value = res?.data;
+  //     }
   //   });
 
   getData();
 });
 </script>
-
-<style scoped></style>

File diff suppressed because it is too large
+ 1 - 1
stats.html