Browse Source

Merge branch 'master' of http://192.168.101.4:3000/jiaxiaoqiang/JG-ADMIN-TEMP

jiaxiaoqiang 1 year ago
parent
commit
39e10a32fb
31 changed files with 1900 additions and 784 deletions
  1. 1 0
      package.json
  2. 7 0
      src/api/craft/process/index.ts
  3. 8 0
      src/api/device/index.ts
  4. 9 2
      src/api/process/index.ts
  5. 7 0
      src/api/station/index.ts
  6. 43 0
      src/api/system/message/index.ts
  7. 1 0
      src/common/configs/dictDataUtil.ts
  8. 67 0
      src/components/CommonTable/configs/tableConfig.ts
  9. 11 2
      src/components/CommonTable/index.vue
  10. 163 8
      src/layout/components/NavBar/components/NavbarRight.vue
  11. 1 1
      src/store/modules/dictionary.ts
  12. 149 0
      src/views/base/accessories/index.vue
  13. 3 3
      src/views/base/craftManagement/route/bindProcess.vue
  14. 92 18
      src/views/base/craftManagement/route/components/bottomTable.vue
  15. 244 237
      src/views/base/craftManagement/route/components/configs.ts
  16. 1 1
      src/views/base/craftManagement/route/index.vue
  17. 25 2
      src/views/base/defectCheck/index.vue
  18. 191 198
      src/views/base/modeling/factory/index.vue
  19. 22 3
      src/views/device/instance/index.vue
  20. 154 143
      src/views/device/metering/index.vue
  21. 28 2
      src/views/device/repair/index.vue
  22. 1 1
      src/views/device/rule/index.vue
  23. 0 13
      src/views/plan/order/index.vue
  24. 112 126
      src/views/plan/prepare/index.vue
  25. 4 0
      src/views/plan/requisition/index.vue
  26. 20 4
      src/views/plan/schedule/index.vue
  27. 9 5
      src/views/plan/workOrder/components/choice-route-page.vue
  28. 36 9
      src/views/plan/workOrder/components/work-order-seq.vue
  29. 63 6
      src/views/plan/workOrder/index.vue
  30. 100 0
      src/views/system/message/editor/index.vue
  31. 328 0
      src/views/system/message/index.vue

+ 1 - 0
package.json

@@ -44,6 +44,7 @@
     "@element-plus/icons-vue": "^2.3.1",
     "@smallwei/avue": "^3.3.3",
     "@types/smallwei__avue": "^3.0.5",
+    "@vueup/vue-quill": "1.0.0-alpha.40",
     "@vueuse/core": "^10.9.0",
     "@wangeditor/editor": "^5.1.23",
     "@wangeditor/editor-for-vue": "5.1.10",

+ 7 - 0
src/api/craft/process/index.ts

@@ -41,3 +41,10 @@ export function getBomVersion(data: object) {
     data: data,
   });
 }
+
+export function getRouteMaxVersion(routeId: string) {
+  return request({
+    url: `/api/v1/op/route/getRouteMaxVersion/${routeId}`,
+    method: "get",
+  });
+}

+ 8 - 0
src/api/device/index.ts

@@ -115,4 +115,12 @@ export function updateProtocol(params: any) {
   });
 }
 
+export function meteringUpdate(params: any) {
+  return request({
+    url: "/api/v1/device/metering/meteringUpdate",
+    method: "post",
+    data: params,
+  });
+}
+
 

+ 9 - 2
src/api/process/index.ts

@@ -20,6 +20,15 @@ export function updateOutSourceApply(
   });
 }
 
+export function queryChildrenInfo(
+    workOrderCode: object
+): AxiosPromise<any> {
+  return request({
+    url: "/api/v1/process/info/childrenInfo/" + workOrderCode,
+    method: "get",
+  });
+}
+
 export function traceabilityTabCount(
     params: object
 ): AxiosPromise<any> {
@@ -29,5 +38,3 @@ export function traceabilityTabCount(
     data: params
   });
 }
-
-

+ 7 - 0
src/api/station/index.ts

@@ -29,3 +29,10 @@ export function addStationDevice(data: StationDevice) {
     data: data,
   });
 }
+
+export function queryStationByLineId(lineId: any) {
+  return request({
+    url: "/api/v1/base/station/queryStationByLineId/"+lineId,
+    method: "get",
+  });
+}

+ 43 - 0
src/api/system/message/index.ts

@@ -0,0 +1,43 @@
+import request from "@/utils/request";
+
+export function addMessage(data: any) {
+  return request({
+    url: "/api/v1/sys/message/add",
+    method: "post",
+    data: data,
+  });
+}
+
+export function updateMessage( data: any) {
+  return request({
+    url: "/api/v1/sys/message/update",
+    method: "post",
+    data: data,
+  });
+}
+
+
+export function userMessageNum( data: any) {
+  return request({
+    url: "/api/v1/sys/message/userMessageNum",
+    method: "post",
+    data: data,
+  });
+}
+
+export function readMessage( data: any) {
+  return request({
+    url: "/api/v1/sys/message/readMessage",
+    method: "post",
+    data: data,
+  });
+}
+
+export function userMessage( data: any) {
+  return request({
+    url: "/api/v1/sys/message/userMessage",
+    method: "post",
+    data: data,
+  });
+}
+

+ 1 - 0
src/common/configs/dictDataUtil.ts

@@ -59,6 +59,7 @@ const DictDataUtil = {
     requisition_state:"requisition_state",
     //委外状态
     outsource_state: "outsource_state",
+    work_order_seq_state: "work_order_seq_state"
   },
   EXPAND_FIELD_TABLE: {
     //字段类型

+ 67 - 0
src/components/CommonTable/configs/tableConfig.ts

@@ -462,6 +462,73 @@ export const tableConfig = {
 		],
 	},
 
+	OP_CHECK: {
+		url: "/api/v1/op/base/check",
+		column: [
+			{
+			  label: "点检项名称",
+			  prop: "checkName",
+			  span: 12,
+			  labelWidth: '150',
+			  search: true,
+			  editDisabled: true,
+			},
+			{
+			  label: "点检项编码",
+			  prop: "checkCode",
+			  labelWidth: '150',
+			  editDisabled: true,
+			  span: 12,
+			  search: true,
+			},
+			{
+			  label: "内容",
+			  prop: "content",
+			  span: 12,
+			  search: false,
+			},
+		],
+	},
+	
+	ESOP: {
+		url: "/api/v1/base/drawing",
+		column: [
+			{
+			  label: "图纸编码",
+			  prop: "drawingCode",
+			  span: 12,
+			  labelWidth: '150',
+			  search: true,
+			  editDisabled: true,
+			},
+			{
+			  label: "标题",
+			  prop: "drawingTitle",
+			  labelWidth: '150',
+			  editDisabled: true,
+			  span: 12,
+			  search: false,
+			},
+			{
+			  label: "版本号",
+			  prop: "drawingVersion",
+			  span: 12,
+			  search: false,
+			},
+			{
+			  label: "图纸",
+			  prop: "drawingPath",
+			  type: "img",
+			  span: 24,
+			  display: false,
+			  slot: true,
+			  // formatter: (row, column, cellValue, index) => {
+			  //   return `${row.drawingPath}`;
+			  // },
+			}
+		],
+	},
+
 	USERS: {
 		url: "/api/v1/sys/employeeSkill/users",
 		column: [

+ 11 - 2
src/components/CommonTable/index.vue

@@ -69,6 +69,15 @@ const refreshDictData = (propName, dictData, keyName = "value") => {
   });
 };
 
+/**
+ * op 对象的字段要跟option实际字段一直 才能进行合并操作
+ */
+const mergeOption = (op) => {
+  for (const key of Object.keys(op)) {
+    option.value[key] = op[key];
+  }
+};
+
 // 传入一个url,后面不带/
 const {
   url,
@@ -147,7 +156,7 @@ watch(
         col.minWidth = calculateColumnWidth(col);
       }
     }
-    dataList();
+    //dataList();
   }
 );
 
@@ -165,5 +174,5 @@ const onSelected = () => {
   isShowTable.value = false;
 };
 
-defineExpose({ startSelect, refreshDictData });
+defineExpose({ startSelect, refreshDictData, mergeOption });
 </script>

+ 163 - 8
src/layout/components/NavBar/components/NavbarRight.vue

@@ -24,14 +24,21 @@
     <!-- 用户头像 -->
     <el-dropdown class="setting-item" trigger="click">
       <div class="flex-center h100% p10px">
-        <img
-          :src="userStore.user.avatar + '?imageView2/1/w/80/h/80'"
-          class="rounded-full mr-10px w24px w24px"
-        />
-        <span>{{ userStore.user.username }}</span>
+        <img :src="userStore.user.avatar + '?imageView2/1/w/80/h/80'"
+          class="rounded-full mr-10px w24px w24px" />
+        <el-badge v-if="unReadMessageNum > 0" :value="unReadMessageNum" :max="10">
+          <span>{{ userStore.user.username }}</span>
+        </el-badge>
+        <span v-else>{{ userStore.user.username }}</span>
       </div>
       <template #dropdown>
         <el-dropdown-menu>
+          <el-dropdown-item divided @click="openMessageDialog">
+            <el-badge v-if="unReadMessageNum > 0" :value="unReadMessageNum" :max="10">
+              <span>消息中心</span>
+            </el-badge>
+            <span v-else>消息中心</span>
+          </el-dropdown-item>
           <el-dropdown-item divided @click="logout">
             {{ $t("navbar.logout") }}
           </el-dropdown-item>
@@ -45,9 +52,46 @@
         <svg-icon icon-class="setting" />
       </div>
     </template>
+
+    <el-dialog
+        v-model="dialog.visible"
+        :title="dialog.title"
+        width="980px"
+        min-height="800px"
+        @close="dialog.visible = false">
+      <el-tabs type="border-card" @tab-click="clickTab">
+        <el-tab-pane label="通知消息">
+          <div class="mainContentBox">
+            <avue-crud
+                :option="options"
+                v-model:page="page"
+                :table-loading="loading"
+                @size-change="handleQuery"
+                @current-change="handleQuery"
+                :data="pageData"
+            >
+            </avue-crud>
+          </div>
+        </el-tab-pane>
+        <el-tab-pane label="系统消息">
+          <div class="mainContentBox">
+            <avue-crud
+                :option="options"
+                v-model:page="page1"
+                :table-loading="loading"
+                @size-change="handleQuery1"
+                @current-change="handleQuery1"
+                :data="pageData1"
+            >
+            </avue-crud>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+
+    </el-dialog>
   </div>
 </template>
-<script setup lang="ts">
+<script setup>
 import {
   useAppStore,
   useTagsViewStore,
@@ -56,19 +100,74 @@ import {
 } from "@/store";
 import defaultSettings from "@/settings";
 import { DeviceEnum } from "@/enums/DeviceEnum";
-
+import {userMessageNum,userMessage,readMessage} from "@/api/system/message"
 const appStore = useAppStore();
+const options = ref({});
+const loading = ref(false);
 const tagsViewStore = useTagsViewStore();
 const userStore = useUserStore();
 const settingStore = useSettingsStore();
-
+const unReadMessageNum = ref(null)
 const route = useRoute();
 const router = useRouter();
+const page = ref({ total: 0, currentPage: 1, pageSize: 10 });
+const page1 = ref({ total: 0, currentPage: 1, pageSize: 10 });
+const pageData = ref([]);
+const pageData1 = ref([]);
+const dialog = reactive({
+  title: "消息管理",
+  visible: false,
+  type: "0",
+  state: "0"
+});
 
+const openMessageDialog = ()=>{
+  handleQuery()
+  dialog.visible = true
+}
 const isMobile = computed(() => appStore.device === DeviceEnum.MOBILE);
 
 const { isFullscreen, toggle } = useFullscreen();
 
+const checkUnReadMessageNum =() =>{
+  userMessageNum({}).then((data)=>{
+    unReadMessageNum.value = data.data
+  })
+}
+options.value = {
+  border: true,
+  align: "center",
+  menuBtn: false,
+  menuAlign: "center",
+  viewBtn: false,
+  editBtn: false,
+  menu: false,
+  addBtn: false,
+  refreshBtn: false,
+  column: [
+    {
+      label: "标题",
+      prop: "title",
+      width: 150,
+      overHidden: true
+
+    },
+    {
+      label: "内容",
+      prop: "content",
+      width: 450,
+      overHidden: true,
+      html: true,
+      formatter: (val) => {
+        return val.content;
+      },
+    },
+    {
+      label: "时间",
+      prop: "created"
+    }
+  ],
+};
 /**
  * 注销
  */
@@ -89,6 +188,55 @@ function logout() {
       });
   });
 }
+const clickTab = (targetName) => {
+  if (targetName.index === "0") {
+    handleQuery(null, null);
+  } else {
+    handleQuery1(null, null);
+  }
+};
+const handleQuery = (params, done) => {
+  loading.value = true;
+  const querySearch = {
+    type: "1",
+    pageSize: page.value.pageSize,
+    pageNo: page.value.currentPage,
+  };
+  queryMessageList(querySearch,page,pageData,done)
+};
+const queryMessageList = (searchParams,pageObj,pageDataList,done) =>{
+  userMessage(searchParams)
+      .then(({ data }) => {
+        pageDataList.value = data.records;
+        pageObj.value.total = data.totalCount;
+        pageObj.value.currentPage = data.pageNo;
+        pageObj.value.pageSize = data.pageSize;
+
+        if(data.records){
+          let unreadIds = data.records.filter((item)=>item.readState === '0').map((mes)=>mes.id)
+          if(unreadIds.length > 0){
+            readMessage(unreadIds).then((data)=>{})
+          }
+        }
+      })
+      .finally(() => {
+        loading.value = false;
+        if (done) { done(); }
+      });
+}
+const handleQuery1 = (params, done) => {
+  loading.value = true;
+  const querySearch = {
+    type: "0",
+    pageSize: page1.value.pageSize,
+    pageNo: page1.value.currentPage,
+  };
+  queryMessageList(querySearch,page1,pageData1,done)
+};
+
+onMounted(() => {
+  checkUnReadMessageNum()
+});
 </script>
 <style lang="scss" scoped>
 .setting-item {
@@ -116,4 +264,11 @@ function logout() {
 .dark .setting-item:hover {
   background: rgb(255 255 255 / 20%);
 }
+:deep(.el-badge__content.is-fixed) {
+  position: absolute;
+  right: calc(1px + var(--el-badge-size) / 2);
+  top: 0;
+  transform: translateX(125%);
+  z-index: var(--el-index-normal);
+}
 </style>

+ 1 - 1
src/store/modules/dictionary.ts

@@ -19,7 +19,7 @@ export const useDictionaryStore = defineStore("dictionaryStore", () => {
     "process_type",
     "workshop_section",
     "skill_requirements",
-    "station_type",
+    "accessories_type",
     "danwei_type",
     "trace_type",
     "skill_type",

+ 149 - 0
src/views/base/accessories/index.vue

@@ -0,0 +1,149 @@
+<template>
+  <div class="mainContentBox">
+    <avue-crud
+      ref="crudRef"
+      v-model:search="search"
+      v-model="form"
+      :data="data"
+      :option="option"
+      v-model:page="page"
+      @row-save="createRow"
+      @row-update="updateRow"
+      @row-del="deleteRow"
+      @search-change="searchChange"
+      @search-reset="resetChange"
+      @size-change="dataList"
+      @current-change="dataList"
+      @selection-change="selectionChange"
+    >
+      <template #menu-left="{ size }">
+        <el-button
+          :disabled="toDeleteIds.length < 1"
+          type="danger"
+          icon="el-icon-delete"
+          :size="size"
+          @click="multipleDelete"
+          >删除</el-button
+        >
+      </template>
+    </avue-crud>
+    <CommonTable
+      ref="ctableRef"
+      tableTitle="物料"
+      tableType="MARTERIAL"
+      @selected-sure="onSelectedFinish"
+    />
+  </div>
+</template>
+<script setup>
+import { ref, getCurrentInstance } from "vue";
+import { useCrud } from "@/hooks/userCrud";
+import dictDataUtil from "@/common/configs/dictDataUtil";
+import ButtonPermKeys from "@/common/configs/buttonPermission";
+import { useCommonStoreHook, useDictionaryStoreHook } from "@/store";
+
+// 数据字典相关
+const { dicts } = useDictionaryStoreHook();
+
+// 传入一个url,后面不带/
+const { form, data, option, search, page, toDeleteIds, Methords, Utils } =
+  useCrud({
+    src: "/api/v1/base/accessories/material",
+  });
+const { dataList, createRow, updateRow, deleteRow, searchChange, resetChange } =
+  Methords; //增删改查
+const { selectionChange, multipleDelete } = Methords; //选中和批量删除事件
+const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等工具
+
+const crudRef = ref(null); //crudRef.value 获取avue-crud对象
+const repeatObj = ref({});
+onMounted(() => {
+  // console.log("crudRef", crudRef)
+  dataList();
+});
+// 公共弹窗相关
+const ctableRef = ref(null);
+const startCreat = () => {
+  if (ctableRef.value) {
+    ctableRef.value.startSelect();
+  }
+};
+defineExpose({ startCreat });
+/**
+ * 上传excel相关
+ */
+const uploadRef = ref(null);
+const uploadFinished = () => {
+  // 上传完成后的刷新操作
+  page.currentPage = 1;
+  dataList();
+};
+const importExcelData = () => {
+  if (uploadRef.value) {
+    uploadRef.value.show("/api/v1/plan/order/import");
+  }
+};
+
+const onSelectedFinish = (selectedValue) => {
+  form.value.materialCode = selectedValue.materialCode;
+  repeatObj.value.showCreate = false;
+};
+
+// 设置表格列或者其他自定义的option
+const switchOp = [
+  {
+    label: "",
+    value: 0,
+  },
+  {
+    label: "",
+    value: 1,
+  },
+];
+option.value = Object.assign(option.value, {
+  selection: true,
+  labelWidth: 110,
+  searchLabelWidth: 110,
+  column: [
+    {
+      label: "辅料类型",
+      prop: "accessoriesType",
+      search: true,
+      type: "select",
+      dicData: dicts.accessories_type,
+      props: {
+        label: "dictLabel",
+        value: "dictValue",
+      },
+      rules: [
+        {
+          required: true,
+          message: "辅料类型不能为空",
+          trigger: "blur",
+        },
+      ],
+    },
+    {
+      label: "生产物料编码",
+      prop: "materialCode",
+      clearable: false,
+      rules: [
+        {
+          required: true,
+          message: "生产物料编码不能为空",
+          trigger: "blur",
+        },
+      ],
+      click: ({ value, column }) => {
+        repeatObj.value.showCreate = true;
+        startCreat();
+      },
+      change: ({ value, column }) => {
+        if (value != form.value.materialCode && !repeatObj.value.showCreate) {
+          startCreat();
+        }
+      },
+    },
+  ],
+});
+</script>

+ 3 - 3
src/views/base/craftManagement/route/bindProcess.vue

@@ -238,9 +238,9 @@ const editProComponent = async () => {
   let res = await updateProcess(currentProcess.value);
   ElMessage.success("保存成功");
   router.push({
-		path: `/base/craftManagement/processCom/${currentProcess.value.id}`,
-		query: {prodtCode:route.query.prodtCode}
-	});
+    path: `/base/craftManagement/processCom/${currentProcess.value.id}`,
+    query: { prodtCode: route.query.prodtCode, routeId: route.query.routeId },
+  });
 };
 
 // 全局=======

+ 92 - 18
src/views/base/craftManagement/route/components/bottomTable.vue

@@ -17,14 +17,15 @@
       @size-change="dataList"
       @current-change="dataList"
     >
-      <template #imgUrl-form="scope">
-        <single-upload v-model="form.imgUrl" />
-      </template>
-      <template #imgUrl="{ row }">
+      <!-- <template #filePath-form="scope">
+        <single-upload v-model="form.filePath" />
+        <FilesUpload v-model:src="form.filePath" v-model:src-list="form.filePath" />
+      </template> -->
+      <!-- <template #filePath="{ row }">
         <el-button link type="primary" @click.stop="imgUrlClick(row)">{{
-          row.imgUrl
+          row.filePath
         }}</el-button>
-      </template>
+      </template> -->
     </avue-crud>
     <CommonTable
       ref="commonTableRef"
@@ -41,7 +42,11 @@
 import { ref, getCurrentInstance } from "vue";
 import { useCrud } from "@/hooks/userCrud";
 import { getTableConfig } from "./configs";
-import { saveCompoents } from "@/api/craft/process/index";
+import {
+  saveCompoents,
+  getBomVersion,
+  getRouteMaxVersion,
+} from "@/api/craft/process/index";
 import SingleUpload from "@/components/Upload/SingleUpload.vue";
 
 const props = defineProps({
@@ -69,18 +74,63 @@ const { dataList, createRow, updateRow, deleteRow, searchChange, resetChange } =
 const { selectionChange, multipleUpdate } = Methords; //选中和批量删除事件
 
 const crudRef = ref(null); //crudRef.value 获取avue-crud对象
-
+const bomVersion = ref(null);
 const startCreat = () => {
   if (props.tableType === "wuliaocaiji") {
-    //根据物料编码获取对应的物料BOM
-    commonTableRef.value &&
-      commonTableRef.value.startSelect(
-        {
-          materialCode: route.query.prodtCode,
-          bomVersion: 1.0,
-        },
-        { tableName: "wuliaocaiji" }
-      );
+    if (data.value && data.value.length > 0) {
+      bomVersion.value = data.value[0].recordVersion;
+    }
+
+    if (!route.query.prodtCode) {
+      ElMessage.error("物料编号读取错误");
+      return;
+    }
+    //根据物料编码和版本号获取对应的物料BOM
+    let bomParam = {
+      materialCode: route.query.prodtCode,
+    };
+    getBomVersion(bomParam).then((res) => {
+      let resListMap = [];
+      //说明时物料采集的添加框 进行物料采集的下拉框数据获取
+      res?.data.forEach((versions) => {
+        resListMap.push({
+          label: versions.bomVersion,
+          value: versions.bomVersion,
+        });
+      });
+      //查询参数
+      let configParam = {};
+      configParam.materialCode = route.query.prodtCode;
+      if (bomVersion.value) {
+        configParam.bomVersion = bomVersion.value;
+      }
+      //根据物料编码和版本号获取对应的物料BOM
+      commonTableType.value = "MARTERIAL_BOM";
+      nextTick(() => {
+        commonTableRef.value?.startSelect(configParam);
+        commonTableRef.value?.refreshDictData(
+          "bomVersion",
+          resListMap,
+          "value"
+        );
+        commonTableRef.value?.mergeOption({
+          searchShow: bomVersion.value ? false : true,
+        });
+      });
+    });
+  } else if (props.tableType === "dianjian") {
+    commonTableType.value = "OP_CHECK";
+    nextTick(() => {
+      commonTableRef.value?.startSelect();
+    });
+  } else if (props.tableType === "ESOP") {
+    commonTableType.value = "ESOP";
+    nextTick(() => {
+      commonTableRef.value?.startSelect({
+        materialCode: route.query.prodtCode,
+        enable: 1,
+      });
+    });
   } else {
     crudRef.value && crudRef.value.rowAdd();
   }
@@ -110,7 +160,21 @@ const onSelectedFinish = (itemValue) => {
     form.value.recordVersion = itemValue.bomVersion;
     form.value.num = itemValue.bomMaterialNumber;
     form.value.traceType = "S";
-    form.value.unit = itemValue.unitDictValue;
+    form.value.unit = itemValue.unit;
+  } else if (props.tableType === "dianjian") {
+    form.value.checkName = itemValue.checkName;
+    form.value.checkCode = itemValue.checkCode;
+    form.value.content = itemValue.content;
+    form.value.standard = itemValue.standard;
+    form.value.upper = itemValue.upper;
+    form.value.lower = itemValue.lower;
+    form.value.content = itemValue.content;
+  } else if (props.tableType === "ESOP") {
+    form.value.filePath = itemValue.drawingPath;
+    form.value.drawingCode = itemValue.drawingCode;
+    form.value.recordVersion = itemValue.drawingVersion;
+    form.value.sortNum = itemValue.sort;
+    form.value.title = itemValue.drawingTitle;
   }
 };
 
@@ -132,6 +196,11 @@ onMounted(() => {
     column: tableConfig[props.tableType].column,
   });
   dataList();
+  getRouteMaxVersion(route.query.routeId).then(({ data }) => {
+    if (data) {
+      bomVersion.value = data;
+    }
+  });
 });
 
 watch(
@@ -147,6 +216,11 @@ watch(
       column: tableConfig[props.tableType].column,
     });
     dataList();
+    getRouteMaxVersion(route.query.routeId).then(({ data }) => {
+      if (data) {
+        bomVersion.value = data;
+      }
+    });
   }
 );
 </script>

+ 244 - 237
src/views/base/craftManagement/route/components/configs.ts

@@ -1,245 +1,252 @@
 import { useDictionaryStoreHook } from "@/store";
 const { dicts } = useDictionaryStoreHook();
 
-export const getTableConfig = (id: string) => {
-  return {
-    // 获取工序记录项信息信息
-    jiluxiang: {
-      url: `/api/v1/op/operationRecord`,
-      column: [
-        {
-          label: "工序id",
-          prop: "operationId",
-          display: false,
-          hide: true,
-          value: id,
-        },
-        { label: "记录项", prop: "thName" },
-        {
-          label: "单位",
-          prop: "unit",
-          search: true,
-          filterable: true,
-          type: "select",
-          dataType: "string",
-          dicData: dicts.danwei_type,
-          props: { label: "dictLabel", value: "dictValue" },
-        },
-        { label: "标准值", prop: "standard" },
-        { label: "上限值", prop: "upper" },
-        { label: "下限值", prop: "lower" },
-      ],
-    },
-    //工序物料
-    wuliaocaiji: {
-      url: "/api/v1/op/operationItem",
-      column: [
-        {
-          label: "工序id",
-          prop: "operationId",
-          display: false,
-          hide: true,
-          value: id,
-        },
-        { label: "物料名称", prop: "itemName" },
-		{ label: "物料版本号", prop: "recordVersion" },
-        { label: "物料编码", prop: "itemCode" },
-        { label: "物料规格", prop: "itemModel" },
-        { label: "所需数量", prop: "num" },
-        {
-          label: "追溯类型",
-          prop: "traceType",
-          search: true,
-          filterable: true,
-          type: "select",
-          dataType: "string",
-          dicData: dicts.trace_type,
-          props: { label: "dictLabel", value: "dictValue" },
-        },
-        {
-          label: "单位",
-          prop: "unit",
-          search: true,
-          filterable: true,
-          type: "select",
-          dataType: "string",
-          dicData: dicts.danwei_type,
-          props: { label: "dictLabel", value: "dictValue" },
-        },
-        {
-          label: "是否需要",
-          prop: "isTrace",
-          type: "radio", //类型为单选框
-          dicData: [
-            {
-              label: "需采集物料",
-              value: 1,
-            },
-            {
-              label: "非必须采集物料",
-              value: 0,
-            },
-          ],
-          value: 1,
-          rules: [
-            {
-              required: true,
-              message: "是否需要",
-              trigger: "blur",
-            },
-          ],
-        },
-      ],
-    },
-    dianjian: {
-      url: `/api/v1/op/operationCheck`,
-      column: [
-        {
-          label: "工序id",
-          prop: "operationId",
-          display: false,
-          hide: true,
-          value: id,
-        },
-        { label: "点检名称", prop: "checkName" },
-        { label: "点检编码", prop: "checkCode" },
-        { label: "内容", prop: "content" },
-        {
-          label: "单位",
-          prop: "unit",
-          search: true,
-          filterable: true,
-          type: "select",
-          dataType: "string",
-          dicData: dicts.danwei_type,
-          props: { label: "dictLabel", value: "dictValue" },
-        },
-        { label: "标准值", prop: "standard" },
-        { label: "上限值", prop: "upper" },
-        { label: "下限值", prop: "lower" },
-      ],
-    },
-    shebeijilu: {
-      url: "/api/v1/op/operationEquit",
-      column: [
-        {
-          label: "工序id",
-          prop: "operationId",
-          display: false,
-          hide: true,
-          value: id,
-        },
-        { label: "精度要求", prop: "accuracy" },
-        { label: "所需数量", prop: "num", display: false, hide: true },
-        {
-          label: "设备类型",
-          prop: "equitType",
-          search: true,
-          filterable: true,
-          type: "select",
-          dataType: "string",
-          dicData: dicts.device_type,
-          props: { label: "dictLabel", value: "dictValue" },
-        },
-        {
-          label: "必须采集",
-          prop: "collection",
-          type: "radio", //类型为单选框
-          dicData: [
-            {
-              label: "必须",
-              value: 1,
-            },
-            {
-              label: "非必须",
-              value: 0,
-            },
-          ],
-          value: 1,
-          rules: [
-            {
-              required: true,
-              message: "是否必须采集",
-              trigger: "blur",
-            },
-          ],
-        },
-      ],
-    },
-    ESOP: {
-      url: "/api/v1/op/esop",
-      column: [
-        {
-          label: "工序id",
-          prop: "operationId",
-          display: false,
-          hide: true,
-          value: id,
-        },
-        { label: "内容", prop: "content" },
-        { label: "标题", prop: "title" },
-		{ label: "展示页数", prop: "showAppointPageNum",type: "number" },
-		{ label: "文件页数", prop: "pageNum",type: "number" },
-		{ label: "版本号", prop: "recordVersion",type: "number",
-		rules: [
-            {
-              required: true,
-              message: "版本号",
-              trigger: "blur",
-            },
-          ], },
-        {
-          label: "文件",
-          prop: "imgUrl",
-          span: 24,
-          slot: true,
-          viewDisplay: false,
-        },
-      ],
-    },
-  };
+export const getTableConfig = (id : string) => {
+	return {
+		// 获取工序记录项信息信息
+		jiluxiang: {
+			url: `/api/v1/op/operationRecord`,
+			column: [
+				{
+					label: "工序id",
+					prop: "operationId",
+					display: false,
+					hide: true,
+					value: id,
+				},
+				{ label: "记录项", prop: "thName" },
+				{
+					label: "单位",
+					prop: "unit",
+					search: true,
+					filterable: true,
+					type: "select",
+					dataType: "string",
+					dicData: dicts.danwei_type,
+					props: { label: "dictLabel", value: "dictValue" },
+				},
+				{ label: "标准值", prop: "standard" },
+				{ label: "上限值", prop: "upper" },
+				{ label: "下限值", prop: "lower" },
+			],
+		},
+		//工序物料
+		wuliaocaiji: {
+			url: "/api/v1/op/operationItem",
+			column: [
+				{
+					label: "工序id",
+					prop: "operationId",
+					display: false,
+					hide: true,
+					value: id,
+				},
+				{ label: "物料名称", prop: "itemName", addDisabled: true, editDisabled: true },
+				{ label: "物料版本号", prop: "recordVersion", addDisabled: true, editDisabled: true },
+				{ label: "物料编码", prop: "itemCode", addDisabled: true, editDisabled: true },
+				{ label: "物料规格", prop: "itemModel", addDisabled: true, editDisabled: true },
+				{ label: "所需数量", prop: "num" },
+				{
+					label: "追溯类型",
+					prop: "traceType",
+					search: true,
+					filterable: true,
+					type: "select",
+					dataType: "string",
+					dicData: dicts.trace_type,
+					props: { label: "dictLabel", value: "dictValue" },
+				},
+				{
+					label: "单位",
+					prop: "unit",
+					search: true,
+					filterable: true,
+					type: "select",
+					dataType: "string",
+					dicData: dicts.danwei_type,
+					props: { label: "dictLabel", value: "dictValue" },
+				},
+				{
+					label: "是否需要",
+					prop: "isTrace",
+					type: "radio", //类型为单选框
+					dicData: [
+						{
+							label: "需采集物料",
+							value: 1,
+						},
+						{
+							label: "非必须采集物料",
+							value: 0,
+						},
+					],
+					value: 1,
+					rules: [
+						{
+							required: true,
+							message: "是否需要",
+							trigger: "blur",
+						},
+					],
+				},
+			],
+		},
+		dianjian: {
+			url: `/api/v1/op/operationCheck`,
+			column: [
+				{
+					label: "工序id",
+					prop: "operationId",
+					display: false,
+					hide: true,
+					value: id,
+				},
+				{ label: "点检名称", prop: "checkName", addDisabled: true, editDisabled: true },
+				{ label: "点检编码", prop: "checkCode", addDisabled: true, editDisabled: true },
+				{ label: "内容", prop: "content" },
+				{
+					label: "单位",
+					prop: "unit",
+					search: true,
+					filterable: true,
+					type: "select",
+					dataType: "string",
+					dicData: dicts.danwei_type,
+					props: { label: "dictLabel", value: "dictValue" },
+				},
+				{ label: "标准值", prop: "standard" },
+				{ label: "上限值", prop: "upper" },
+				{ label: "下限值", prop: "lower" },
+			],
+		},
+		shebeijilu: {
+			url: "/api/v1/op/operationEquit",
+			column: [
+				{
+					label: "工序id",
+					prop: "operationId",
+					display: false,
+					hide: true,
+					value: id,
+				},
+				{ label: "精度要求", prop: "accuracy" },
+				{ label: "所需数量", prop: "num", display: false, hide: true },
+				{
+					label: "设备类型",
+					prop: "equitType",
+					search: true,
+					filterable: true,
+					type: "select",
+					dataType: "string",
+					dicData: dicts.device_type,
+					props: { label: "dictLabel", value: "dictValue" },
+				},
+				{
+					label: "必须采集",
+					prop: "collection",
+					type: "radio", //类型为单选框
+					dicData: [
+						{
+							label: "必须",
+							value: 1,
+						},
+						{
+							label: "非必须",
+							value: 0,
+						},
+					],
+					value: 1,
+					rules: [
+						{
+							required: true,
+							message: "是否必须采集",
+							trigger: "blur",
+						},
+					],
+				},
+			],
+		},
+		ESOP: {
+			url: "/api/v1/op/esop",
+			column: [
+				{
+					label: "工序id",
+					prop: "operationId",
+					display: false,
+					hide: true,
+					value: id,
+				},
+
+				{ label: "标题", prop: "title", addDisabled: true, editDisabled: true },
+				{ label: "展示页数", prop: "showAppointPageNum", type: "number" },
+				{ label: "总页数", prop: "pageNum", type: "number" },
+				{
+					label: "版本号", prop: "recordVersion", type: "number", addDisabled: true, editDisabled: true,
+					rules: [
+						{
+							required: true,
+							message: "版本号",
+							trigger: "blur",
+						},
+					],
+				},
+				{ label: "图纸编码", prop: "drawingCode", hide: true, addDisabled: true, editDisabled: true, },
+				{ label: "内容", prop: "content", hide: true,addDisabled: true, editDisabled: true, },
+				{ label: "排序", prop: "sortNum", hide: true,addDisabled: true, editDisabled: true, },
+				{
+					label: "文件",
+					prop: "filePath",
+					span: 24,
+					type: "img",
+					slot: true,
+					viewDisplay: false,
+					addDisabled: true, editDisabled: true
+				},
+			],
+		},
+	};
 };
 
 // 工艺工序组件路径的组件类别
 interface comType {
-  compentName: string;
-  compentType: string;
+	compentName : string;
+	compentType : string;
 }
-export const comTypes: comType[] = [
-  {
-    compentName: "记录项",
-    compentType: "jiluxiang",
-  },
-  {
-    compentName: "物料采集",
-    compentType: "wuliaocaiji",
-  },
-  {
-    compentName: "ESOP",
-    compentType: "ESOP",
-  },
-  {
-    compentName: "点检",
-    compentType: "dianjian",
-  },
-  {
-    compentName: "设备记录",
-    compentType: "shebeijilu",
-  },
-  {
-    compentName: "紧固",
-    compentType: "jingu",
-  },
-  {
-    compentName: "调试配对",
-    compentType: "tiaoshipipei",
-  },
-  {
-    compentName: "铭牌绑定",
-    compentType: "mingpai",
-  },
-  {
-    compentName: "多媒体采集",
-    compentType: "duomeiticaiji",
-  },
-];
+export const comTypes : comType[] = [
+	{
+		compentName: "记录项",
+		compentType: "jiluxiang",
+	},
+	{
+		compentName: "物料采集",
+		compentType: "wuliaocaiji",
+	},
+	{
+		compentName: "ESOP",
+		compentType: "ESOP",
+	},
+	{
+		compentName: "点检",
+		compentType: "dianjian",
+	},
+	{
+		compentName: "设备记录",
+		compentType: "shebeijilu",
+	},
+	{
+		compentName: "紧固",
+		compentType: "jingu",
+	},
+	{
+		compentName: "调试配对",
+		compentType: "tiaoshipipei",
+	},
+	{
+		compentName: "铭牌绑定",
+		compentType: "mingpai",
+	},
+	{
+		compentName: "多媒体采集",
+		compentType: "duomeiticaiji",
+	},
+];

+ 1 - 1
src/views/base/craftManagement/route/index.vue

@@ -188,7 +188,7 @@ const router = useRouter();
 const bindProcess = (row) => {
   router.push({
     path: `/base/craftManagement/bindProcess/${row.id}`,
-    query: { prodtCode: row.prodtCode },
+    query: { prodtCode: row.prodtCode,routeId: row.id},
   });
 };
 

+ 25 - 2
src/views/base/defectCheck/index.vue

@@ -26,7 +26,6 @@
           >删除</el-button
         >
       </template>
-
     </avue-crud>
     <ExcelUpload ref="uploadRef" @finished="uploadFinished" />
   </div>
@@ -106,7 +105,7 @@ option.value = Object.assign(option.value, {
     {
       label: "点检项编码",
       prop: "checkCode",
-	  editDisabled: true,
+      editDisabled: true,
       span: 12,
       search: true,
       rules: [
@@ -123,6 +122,30 @@ option.value = Object.assign(option.value, {
       span: 12,
       search: false,
     },
+    {
+      label: "标准值",
+      prop: "standard",
+      span: 12,
+      search: false,
+    },
+    {
+      label: "上限值",
+      prop: "upper",
+      span: 12,
+      search: false,
+    },
+    {
+      label: "下限值",
+      prop: "lower",
+      span: 12,
+      search: false,
+    },
+    {
+      label: "单位",
+      prop: "unit",
+      span: 12,
+      search: false,
+    },
   ],
 });
 </script>

+ 191 - 198
src/views/base/modeling/factory/index.vue

@@ -9,7 +9,7 @@
       v-model:page="page"
       @row-save="createRow"
       @row-update="updateRow"
-      @row-del="delete(row,index,done)"
+      @row-del="deletes(row, index, done)"
       @search-change="searchChange"
       @search-reset="resetChange"
       @size-change="dataList"
@@ -23,25 +23,22 @@
           icon="el-icon-delete"
           :size="size"
           @click="multipleDelete"
-        >删除</el-button
+          >删除</el-button
         >
       </template>
-      <template #menu="{row,index,type}">
-        <el-button @click="binding(row)"
-                   icon="el-icon-link"
-                   text
-                   type="primary"
-                   >绑定子项</el-button>
+      <template #menu="{ row, index, type }">
+        <el-button @click="binding(row)" icon="el-icon-link" text type="primary"
+          >绑定子项</el-button
+        >
       </template>
-
     </avue-crud>
 
-      <CommonTable
-        ref="ctableRef"
-        tableTitle="绑定子项"
-        tableType="FACTORY"
-        @selected-sure="onSelectedFinish"
-      />
+    <CommonTable
+      ref="ctableRef"
+      tableTitle="绑定子项"
+      tableType="FACTORY"
+      @selected-sure="onSelectedFinish"
+    />
     <CommonTable
       ref="workShopRef"
       tableTitle="绑定子项"
@@ -59,205 +56,201 @@
   </div>
 </template>
 <script setup lang="ts">
-  import { ref, getCurrentInstance } from "vue";
-  import { useCrud } from "@/hooks/userCrud";
-  import ButtonPermKeys from "@/common/configs/buttonPermission";
-  import { useCommonStoreHook } from "@/store";
-  const { isShowTable, tableType } = toRefs(useCommonStoreHook());
-  import {
-    updateWorkShop,
-  } from "@/api/workShop";
-
-  import {
-    updateProductionLine,
-  } from "@/api/productionLine";
-  import {
-    updateStation,
-  } from "@/api/station";
-  // 公共弹窗相关
-  const ctableRef = ref(null);
-  const workShopRef=ref(null);
-  const productionLineRef=ref(null);
-  const factory=ref({});
-  const binding = (row) => {
-    factory.value=row;
-    if (row.level==="first") {
-      ctableRef.value.startSelect();
-    }
-    if(row.level==="second"){
-      workShopRef.value.startSelect();
-    }
-    if(row.level==="third"){
-      productionLineRef.value.startSelect();
-    }
+import { ref, getCurrentInstance } from "vue";
+import { useCrud } from "@/hooks/userCrud";
+import ButtonPermKeys from "@/common/configs/buttonPermission";
+import { useCommonStoreHook } from "@/store";
+const { isShowTable, tableType } = toRefs(useCommonStoreHook());
+import { updateWorkShop } from "@/api/workShop";
 
-  };
-  const delete=(row,index,done)=>{
-    if(row.level==="first"){
-      deleteRow(row,index,done);
-    }
-    if(row.level==="second"){
-      workShopRef.value.startSelect();
-    }
-    if(row.level==="third"){
-      productionLineRef.value.startSelect();
-    }
+import { updateProductionLine } from "@/api/productionLine";
+import { updateStation } from "@/api/station";
+// 公共弹窗相关
+const ctableRef = ref(null);
+const workShopRef = ref(null);
+const productionLineRef = ref(null);
+const factory = ref({});
+const binding = (row) => {
+  factory.value = row;
+  if (row.level === "first") {
+    ctableRef.value.startSelect();
   }
-  const dialog = reactive({
-    title: "绑定子项",
-    visible: false,
-  });
+  if (row.level === "second") {
+    workShopRef.value.startSelect();
+  }
+  if (row.level === "third") {
+    productionLineRef.value.startSelect();
+  }
+};
+const deletes = (row, index, done) => {
+  if (row.level === "first") {
+    deleteRow(row, index, done);
+  }
+  if (row.level === "second") {
+    workShopRef.value.startSelect();
+  }
+  if (row.level === "third") {
+    productionLineRef.value.startSelect();
+  }
+};
+const dialog = reactive({
+  title: "绑定子项",
+  visible: false,
+});
 
-  // 传入一个url,后面不带/
-  const { form, data, option, search, page, toDeleteIds, Methords, Utils } =
-    useCrud({
-      src: "/api/v1/base/factory",
-    });
-  const { dataList, createRow, updateRow, deleteRow, searchChange, resetChange } =
-    Methords; //增删改查
-  const { selectionChange, multipleDelete } = Methords; //选中和批量删除事件
-  const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等工具
-  // checkBtnPerm(ButtonPermKeys.PLAN.BTNS.order_add) :permission="permission"
-  // const permission = reactive({
-  //   delBtn: checkPerm(buttonPermission.PLAN.BTNS.order_del),
-  //   addBtn: checkPerm(buttonPermission.PLAN.BTNS.order_add),
-  //   editBtn: checkPerm(buttonPermission.PLAN.BTNS.order_edit),
-  //   menu: true,
-  // });
+// 传入一个url,后面不带/
+const { form, data, option, search, page, toDeleteIds, Methords, Utils } =
+  useCrud({
+    src: "/api/v1/base/factory",
+  });
+const { dataList, createRow, updateRow, deleteRow, searchChange, resetChange } =
+  Methords; //增删改查
+const { selectionChange, multipleDelete } = Methords; //选中和批量删除事件
+const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等工具
+// checkBtnPerm(ButtonPermKeys.PLAN.BTNS.order_add) :permission="permission"
+// const permission = reactive({
+//   delBtn: checkPerm(buttonPermission.PLAN.BTNS.order_del),
+//   addBtn: checkPerm(buttonPermission.PLAN.BTNS.order_add),
+//   editBtn: checkPerm(buttonPermission.PLAN.BTNS.order_edit),
+//   menu: true,
+// });
 
-  const crudRef = ref(null); //crudRef.value 获取avue-crud对象
+const crudRef = ref(null); //crudRef.value 获取avue-crud对象
 
-  onMounted(() => {
-    // console.log("crudRef", crudRef)
-    dataList();
-  });
+onMounted(() => {
+  // console.log("crudRef", crudRef)
+  dataList();
+});
 
-  /**
-   * 上传excel相关
-   */
-  const uploadRef = ref(null);
-  const uploadFinished = () => {
-    // 上传完成后的刷新操作
-    page.currentPage = 1;
-    dataList();
-  };
-  const importExcelData = () => {
-    if (uploadRef.value) {
-      uploadRef.value.show("/api/v1/plan/order/import");
-    }
-  };
-  const formData=ref({});
-  // 设置表格列或者其他自定义的option
-  option.value = Object.assign(option.value, {
-    selection: true,
-    menuWidth: 320,
-    border: true,
-    index: true,
-    rowKey: 'code',
-    rowParentKey: 'parentCode',
-    column: [
-      {
-        label: "厂区名称",
-        prop: "name",
-        search: true,
-        overHidden:true,
-        span: 24,
-        labelWidth: 100,
-        rules: [{
+/**
+ * 上传excel相关
+ */
+const uploadRef = ref(null);
+const uploadFinished = () => {
+  // 上传完成后的刷新操作
+  page.currentPage = 1;
+  dataList();
+};
+const importExcelData = () => {
+  if (uploadRef.value) {
+    uploadRef.value.show("/api/v1/plan/order/import");
+  }
+};
+const formData = ref({});
+// 设置表格列或者其他自定义的option
+option.value = Object.assign(option.value, {
+  selection: true,
+  menuWidth: 320,
+  border: true,
+  index: true,
+  rowKey: "code",
+  rowParentKey: "parentCode",
+  column: [
+    {
+      label: "厂区名称",
+      prop: "name",
+      search: true,
+      overHidden: true,
+      span: 24,
+      labelWidth: 100,
+      rules: [
+        {
           required: true,
           message: "请输入工厂名称",
-          trigger: "blur"
-        }]
-      },
-      {
-        label: "负责人",
-        prop: "manager",
-        span: 24,
-        labelWidth: 100,
-        rules: [{
+          trigger: "blur",
+        },
+      ],
+    },
+    {
+      label: "负责人",
+      prop: "manager",
+      span: 24,
+      labelWidth: 100,
+      rules: [
+        {
           required: true,
           message: "请选择厂区负责人",
-          trigger: "blur"
-        }],
-        type: 'select',
-        dicUrl:import.meta.env.VITE_APP_BASE_API+"/api/v1/sys/user/list",
-        dicMethod:"post",
-        props: {
-          label: "userName", // 下拉菜单显示的字段
-          value: "userName" // 下拉菜单值的字段
+          trigger: "blur",
         },
+      ],
+      type: "select",
+      dicUrl: import.meta.env.VITE_APP_BASE_API + "/api/v1/sys/user/list",
+      dicMethod: "post",
+      props: {
+        label: "userName", // 下拉菜单显示的字段
+        value: "userName", // 下拉菜单值的字段
       },
-      {
-        label: "厂区位置",
-        prop: "position",
-        overHidden:true,
-        span: 24,
-        labelWidth: 100,
-        rules: [{
+    },
+    {
+      label: "厂区位置",
+      prop: "position",
+      overHidden: true,
+      span: 24,
+      labelWidth: 100,
+      rules: [
+        {
           required: true,
           message: "请输入厂区位置",
-          trigger: "blur"
-        }]
-      },
-      {
-        label: "创建时间",
-        prop: "created",
-        display:false
-      },
-      {
-        label: "备注",
-        span: 24,
-        labelWidth: 100,
-        overHidden:true,
-        prop: "remark",
-        type: 'textarea',
-      },
-    ],
-  });
-
+          trigger: "blur",
+        },
+      ],
+    },
+    {
+      label: "创建时间",
+      prop: "created",
+      display: false,
+    },
+    {
+      label: "备注",
+      span: 24,
+      labelWidth: 100,
+      overHidden: true,
+      prop: "remark",
+      type: "textarea",
+    },
+  ],
+});
 
-  const onSelectedFinish = (selectedValue) => {
-    formData.code=selectedValue.code;
-    formData.parentCode=factory.value.code;
-    formData.id=selectedValue.id;
-    updateWorkShop(formData).then((data: any) => {
-      ElMessage({
-        message: data.msg,
-        type: "success",
-      });
-      // 上传完成后的刷新操作
-      page.currentPage = 1;
-      dataList();
+const onSelectedFinish = (selectedValue) => {
+  formData.value.code = selectedValue.code;
+  formData.value.parentCode = factory.value.code;
+  formData.value.id = selectedValue.id;
+  updateWorkShop(formData).then((data: any) => {
+    ElMessage({
+      message: data.msg,
+      type: "success",
     });
-  };
-  const onSelectedLineFinish = (selectedValue) => {
-    formData.code=selectedValue.code;
-    formData.parentCode=factory.value.code;
-    formData.id=selectedValue.id;
-    updateProductionLine(formData).then((data: any) => {
-      ElMessage({
-        message: data.msg,
-        type: "success",
-      });
-      // 上传完成后的刷新操作
-      page.currentPage = 1;
-      dataList();
+    // 上传完成后的刷新操作
+    page.currentPage = 1;
+    dataList();
+  });
+};
+const onSelectedLineFinish = (selectedValue) => {
+  formData.value.code = selectedValue.code;
+  formData.value.parentCode = factory.value.code;
+  formData.value.id = selectedValue.id;
+  updateProductionLine(formData).then((data: any) => {
+    ElMessage({
+      message: data.msg,
+      type: "success",
     });
-  };
-  const onSelectedStationFinish = (selectedValue) => {
-    formData.code=selectedValue.code;
-    formData.parentCode=factory.value.code;
-    formData.id=selectedValue.id;
-    updateStation(formData).then((data: any) => {
-      ElMessage({
-        message: data.msg,
-        type: "success",
-      });
-      // 上传完成后的刷新操作
-      page.currentPage = 1;
-      dataList();
+    // 上传完成后的刷新操作
+    page.currentPage = 1;
+    dataList();
+  });
+};
+const onSelectedStationFinish = (selectedValue) => {
+  formData.value.code = selectedValue.code;
+  formData.value.parentCode = factory.value.code;
+  formData.value.id = selectedValue.id;
+  updateStation(formData).then((data: any) => {
+    ElMessage({
+      message: data.msg,
+      type: "success",
     });
-  };
+    // 上传完成后的刷新操作
+    page.currentPage = 1;
+    dataList();
+  });
+};
 </script>
-
-

+ 22 - 3
src/views/device/instance/index.vue

@@ -207,6 +207,7 @@ const crudRef = ref(null); //crudRef.value 获取avue-crud对象
 option.value = Object.assign(option.value, {
   delBtn: false,
   selection: true,
+  labelWidth: 120,
   column: [
     {
       label: "设备编号",
@@ -262,7 +263,7 @@ option.value = Object.assign(option.value, {
       label: "设备状态",
       prop: "state",
       type: "select",
-      width: 160,
+      width: 120,
       overHidden: true,
       search: true,
       dicUrl:
@@ -297,7 +298,7 @@ option.value = Object.assign(option.value, {
     {
       label: "负责人",
       prop: "head",
-      width: 160,
+      width: 120,
       overHidden: true,
       rules: [
         {
@@ -308,10 +309,26 @@ option.value = Object.assign(option.value, {
       ],
     },
     {
+      label: "计量有效期",
+      prop: "meteringDate",
+      type: "date",
+      width: 160,
+      format: 'YYYY-MM-DD',
+      valueFormat: 'YYYY-MM-DD',
+      overHidden: true,
+      rules: [
+        {
+          required: true,
+          message: "计量有效期不能为空",
+          trigger: "trigger",
+        },
+      ],
+    },
+    {
       label: "所属PAC",
       prop: "terminal",
       type: "select",
-      width: 160,
+      width: 120,
       overHidden: true,
       search: true,
       dicUrl:import.meta.env.VITE_APP_BASE_API + "/api/v1/device/pacList",
@@ -323,6 +340,8 @@ option.value = Object.assign(option.value, {
     {
       label: "是否采集",
       prop: "collect",
+      editDisplay: false,
+      addDisplay: false,
       slot: true,
       width: 100,
     },

+ 154 - 143
src/views/device/metering/index.vue

@@ -16,7 +16,7 @@
         @current-change="dataList"
         @selection-change="selectionChange"
     >
-      <template #menu-left="{ size }">
+<!--      <template #menu-left="{ size }">
         <el-button
           :disabled="toDeleteIds.length < 1"
           type="danger"
@@ -25,25 +25,21 @@
           @click="multipleDelete"
           >删除</el-button
         >
-      </template>
+      </template>-->
       <template #menu="{size,row,index}">
         <el-button @click="maintenance(row)"
                    icon="el-icon-setting"
                    text
-                   v-if="row.state === 0"
-                   type="primary"
-                   :size="size">流程</el-button>
-        <el-button disabled
-                   icon="el-icon-setting"
-                   text
-                   v-if="row.state === 1"
                    type="primary"
-                   :size="size">流程</el-button>
-        <el-button @click="maintenanceList(row)"
-                   icon="el-icon-fold"
-                   text
-                   type="primary"
-                   :size="size">记录</el-button>
+                   :size="size">计量</el-button>
+      </template>
+      <template #menu-right="{}">
+        <el-button
+            class="ml-3"
+            @click="exportData('/api/v1/device/export')"
+        >
+          <template #icon> <i-ep-download /> </template>导出
+        </el-button>
       </template>
     </avue-crud>
     <el-dialog
@@ -62,7 +58,7 @@
         height="80%"
         @close="dialog1.visible = false">
       <el-timeline style="max-width: 500px;margin-left: 100px">
-        <el-timeline-item center color="#0bbd87" type="success" placement="top">
+<!--        <el-timeline-item center color="#0bbd87" type="success" placement="top">
           <el-card>
             <h4>维护计划</h4>
             <p>设备编号: {{maintenanceInfo.deviceNo}}</p>
@@ -70,15 +66,15 @@
             <p>维护内容:{{maintenanceInfo.remark}}</p>
             <p>计划时间:{{maintenanceInfo.nextTime}}</p>
           </el-card>
-        </el-timeline-item>
-        <el-timeline-item center placement="top" :type="maintenanceInfo.state === 0 ? 'primary' : 'success'">
+        </el-timeline-item>-->
+<!--        <el-timeline-item center placement="top" :type="maintenanceInfo.state === 0 ? 'primary' : 'success'">-->
           <el-card>
-            <h4>设备维护</h4>
+            <h4>设备计量</h4>
             <el-form ref="maintenanceInfoForm" :model="maintenanceInfo" label-width="auto" style="max-width: 400px" :rules="rules">
-              <el-form-item label="维护人员" prop="userName">
+              <el-form-item label="计量人员" prop="userName">
                 <el-select
                     v-model="maintenanceInfo.userName"
-                    placeholder="维护人员"
+                    placeholder="计量人员"
                     size="large"
                     style="width: 240px">
                   <el-option
@@ -89,27 +85,35 @@
                   />
                 </el-select>
               </el-form-item>
-              <el-form-item label="维护结果">
+              <el-form-item label="计量结果">
                 <el-radio-group v-model="maintenanceInfo.result" class="ml-4">
-                  <el-radio :value="0">正常</el-radio>
-                  <el-radio :value="1">报故</el-radio>
+                  <el-radio :value="0">已计量</el-radio>
                 </el-radio-group>
               </el-form-item>
-              <el-form-item v-if="maintenanceInfo.result === 1" label="报故内容">
+<!--              <el-form-item v-if="maintenanceInfo.result === 1" label="报故内容">
                 <el-input v-model="maintenanceInfo.maintenanceContent" />
+              </el-form-item>-->
+              <el-form-item label="下次计量日期" prop="nextTime">
+                <el-date-picker
+                    v-model="maintenanceInfo.nextTime"
+                    type="date"
+                    style="width:240px;"
+                    :disabled-date="disabledDate"
+                    placeholder="请选择时间"
+                    format="YYYY-MM-DD"
+                    value-format="YYYY-MM-DD"
+                />
+<!--                <el-input v-model="maintenanceInfo.nextTime" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"/>-->
               </el-form-item>
-              <el-form-item v-if="maintenanceInfo.result === 0" label="下次维护日期">
-                <el-input v-model="maintenanceInfo.nextTime" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"/>
-              </el-form-item>
-              <el-form-item v-if="maintenanceInfo.result === 0" label="下次维护内容">
+<!--              <el-form-item v-if="maintenanceInfo.result === 0" label="下次维护内容">
                 <el-input v-model="maintenanceInfo.maintenanceContent" />
-              </el-form-item>
+              </el-form-item>-->
               <el-form-item style="margin-left: 45%">
                 <el-button type="primary" @click="maintenanceSubmit">保存</el-button>
               </el-form-item>
             </el-form>
           </el-card>
-        </el-timeline-item>
+<!--        </el-timeline-item>-->
       </el-timeline>
     </el-dialog>
 
@@ -129,7 +133,7 @@ import { ref, getCurrentInstance } from "vue";
 import { useCrud } from "@/hooks/userCrud";
 import ButtonPermKeys from "@/common/configs/buttonPermission";
 import {getUserList} from "@/api/system/user"
-import {maintenanceUpdate} from "@/api/device/index";
+import {maintenanceUpdate,meteringUpdate} from "@/api/device/index";
 import { useCommonStoreHook } from "@/store";
 import dictDataUtil from "@/common/configs/dictDataUtil";
 import RecordPage from "./components/metering-record.vue";
@@ -138,7 +142,9 @@ const test = () => {
   isShowTable.value = true;
   tableType.value = tableType.value == 1 ? 2 : 1;
 };
-
+const disabledDate = (time) =>{
+  return time.getTime() < Date.now(); // 8.64e7 毫秒数代表一天
+}
 const dialog = reactive({
   title: "设备选择",
   visible: false,
@@ -155,7 +161,7 @@ const userList = ref([])
 // 传入一个url,后面不带/
 const { form, data, option, search, page, toDeleteIds, Methords, Utils } =
   useCrud({
-    src: "/api/v1/device/metering",
+    src: "/api/v1/device",
   });
 const { dataList, createRow, updateRow, deleteRow, searchChange, resetChange } = Methords; //增删改查
 const { selectionChange, multipleDelete } = Methords; //选中和批量删除事件
@@ -168,7 +174,7 @@ const deviceInfo = (value) => {
 const maintenanceInfo = ref(null)
 const maintenance = (row)=>{
   maintenanceInfo.value = row
-  maintenanceInfo.value.maintenanceContent = row.remark
+  maintenanceInfo.value.deviceId = row.id
   maintenanceInfo.value.result = 0
   dialog1.visible = true
 }
@@ -186,7 +192,7 @@ const maintenanceSubmit =()=>{
   //alert(JSON.stringify(maintenanceInfo.value))
   maintenanceInfoForm.value.validate((isValid, invalidFields) => {
     if (isValid) {
-      maintenanceUpdate(maintenanceInfo.value).then((data)=>{
+      meteringUpdate(maintenanceInfo.value).then((data)=>{
         ElMessage({
           message: data.msg,
           type: "success",
@@ -204,169 +210,174 @@ const rules = reactive({
     // trigger触发此条规则校验的时机,有两个值, blur 或 change,默认就是blur和change都会进行校验
     // min此字段的最小长度,max此字段的最大长度
     // pattern 正则表达式
-    { required: true, message: '维护人员不能为空', trigger: 'blur' }
+    { required: true, message: '计量人员不能为空', trigger: 'blur' }
+  ],
+  nextTime: [
+    { required: true, message: '计量日期不能为空', trigger: 'blur' }
   ]
 })
 // 设置表格列或者其他自定义的option
 option.value = Object.assign(option.value, {
   delBtn: false,
-  selection: true,
+  selection: false,
   labelWidth: 150,
+  addBtn: false,
+  editBtn: false,
   viewBtn: false,
   column: [
     {
       label: "设备编号",
       prop: "deviceNo",
       search: true,
-      rules: [
-        {
-          required: true,
-          message: "设备编号不能为空",
-          trigger: "trigger",
-        },
-      ],
-      click: ({ value, column }) => {
-        if(column.boxType){
-          dialog.visible = true
-        }
-      },
+      width: 160,
+      overHidden: true,
     },
     {
       label: "设备名称",
       prop: "deviceName",
-      display: false,
       search: true,
+      width: 160,
+      overHidden: true,
+    },
+    {
+      label: "计量日期",
+      prop: "meteringSearch",
+      width: 160,
+      type: 'daterange',
+      searchRange: true,
+      hide: true,
+      startPlaceholder: '开始范围',
+      endPlaceholder: '结束范围',
+      format: 'YYYY-MM-DD',
+      valueFormat: 'YYYY-MM-DD',
+      overHidden: true,
+      search: true
     },
     {
       label: "设备类型",
       prop: "deviceType",
       type: "select",
+      width: 130,
+      overHidden: true,
       search: true,
-      display: false,
       dicUrl:
-        dictDataUtil.request_url +
-        dictDataUtil.TYPE_CODE.device_type,
+          dictDataUtil.request_url +
+          dictDataUtil.TYPE_CODE.device_type,
       props: {
         label: "dictLabel",
         value: "dictValue",
       },
-      rules: [
-        {
-          required: true,
-          message: "设备类型不能为空",
-          trigger: "trigger",
-        },
-      ],
     },
     {
-      label: "设备位置",
-      prop: "devicePosition",
-      display: false,
-    },
-    {
-      label: "运行状态",
-      prop: "runState",
+      label: "设备状态",
+      prop: "state",
       type: "select",
-      display: false,
+      width: 160,
+      overHidden: true,
+      search: true,
       dicUrl:
           dictDataUtil.request_url +
-          dictDataUtil.TYPE_CODE.device_run_status,
+          dictDataUtil.TYPE_CODE.device_status,
       props: {
         label: "dictLabel",
         value: "dictValue",
       },
-      rules: [
-        {
-          required: true,
-          message: "运行状态不能为空",
-          trigger: "trigger",
-        },
-      ],
     },
     {
-      label: "计量负责人",
-      prop: "meteringUser",
-      search: true,
-      rules: [
-        {
-          required: true,
-          message: "计量负责人不能为空",
-          trigger: "trigger",
-        },
-      ],
+      label: "在线状态",
+      prop: "onlineState",
+      width: 100,
+      display: false,
+      html: true,
+      formatter: (val) => {
+        if (val.onlineState === "1") {
+          return '<b class="el-tag el-tag--success el-tag--light">在线</b>';
+        } else {
+          return '<b class="el-tag el-tag--warning el-tag--light">离线</b>';
+        }
+      },
+    },
+    {
+      label: "负责人",
+      prop: "head",
+      width: 160,
+      overHidden: true,
     },
     {
-      label: "计量单位",
-      prop: "meteringUnit",
-      rules: [
-        {
-          required: true,
-          message: "计量单位不能为空",
-          trigger: "trigger",
-        },
-      ],
+      label: "计量有效期",
+      prop: "meteringDate",
+      type: "date",
+      width: 160,
+      format: 'YYYY-MM-DD',
+      valueFormat: 'YYYY-MM-DD',
+      overHidden: true,
     },
     {
-      label: "计量周期",
-      prop: "cycle",
+      label: "所属PAC",
+      prop: "terminal",
       type: "select",
-      dicUrl:
-          dictDataUtil.request_url +
-          dictDataUtil.TYPE_CODE.device_maintenance_cycle,
+      width: 160,
+      overHidden: true,
+      dicUrl:import.meta.env.VITE_APP_BASE_API + "/api/v1/device/pacList",
       props: {
-        label: "dictLabel",
-        value: "dictValue",
-      },
-      rules: [
-        {
-          required: true,
-          message: "计量周期不能为空",
-          trigger: "trigger",
-        },
-      ],
+        label: "deviceName",
+        value: "deviceNo",
+      }
     },
     {
-      label: "计量状态",
-      prop: "state",
-      type: "select",
-      addDisplay: false,
-      dicData: [{label: '待审批',value:0},{label: '带计量',value:1},{label: '已计量',value:2}],
-      rules: [
-        {
-          required: true,
-          message: "计量状态不能为空",
-          trigger: "trigger",
-        },
-      ],
+      label: "供应厂商",
+      prop: "manufacturer",
+      width: 160,
+      overHidden: true,
     },
     {
-      label: "计量日期",
-      prop: "nextTime",
-      type: "date",
-      addDisplay: false,
-      width: "120",
-      format: "YYYY-MM-DD", //前端展示格式
-      valueFormat: "YYYY-MM-DD", //设置后端接收的日期格式
-      rules: [
-        {
-          required: true,
-          message: "计量日期不能为空",
-          trigger: "trigger",
-        },
-      ],
+      label: "所属部门",
+      prop: "deptId",
+      width: 160,
+      overHidden: true,
+      type: "tree",
+      dicUrl: dictDataUtil.dept_tree_url,
+      props: {
+        label: "deptName",
+        value: "id",
+      }
+    },
+    {
+      label: "所在车间",
+      prop: "workshop",
+      width: 160,
+      overHidden: true,
+    },
+    {
+      label: "所在工位",
+      prop: "station",
+      width: 160,
+      overHidden: true,
+    },
+    {
+      label: "设备位置",
+      prop: "devicePosition",
+      width: 160,
+      overHidden: true,
+    },
+    {
+      label: "规格",
+      prop: "specifications",
+      width: 160,
+      overHidden: true,
     },
     {
-      label: "备注",
-      prop: "remark",
-      minRows: 2, //最小行/最小值
-      type: "textarea", //类型为多行文本域框
-      maxlength: 512, //最大输入长度
-      overHidden: true
+      label: "品牌",
+      width: 160,
+      overHidden: true,
+      prop: "brand",
     },
   ],
 });
 
 onMounted(() => {
+  search.value.needMetering = "1"
+  maintenanceInfo.result = "0"
   dataList();
   queryUserList()
 });

+ 28 - 2
src/views/device/repair/index.vue

@@ -77,7 +77,20 @@
             <h4>设备维修</h4>
             <el-form ref="maintenanceInfoForm1" :model="maintenanceInfo" label-width="auto" style="max-width: 400px" :rules="rules1">
               <el-form-item label="维修人员" prop="handleUser">
-                <el-input :disabled="maintenanceInfo.state !== 0" v-model="maintenanceInfo.handleUser" />
+<!--                <el-input :disabled="maintenanceInfo.state !== 0" v-model="maintenanceInfo.handleUser" />-->
+                <el-select
+                    v-model="maintenanceInfo.handleUser"
+                    placeholder="维修人员"
+                    :disabled="maintenanceInfo.state !== 0"
+                    size="large"
+                    filterable>
+                  <el-option
+                      v-for="item in userList"
+                      :key="item.userName"
+                      :label="item.userName"
+                      :value="item.userName"
+                  />
+                </el-select>
               </el-form-item>
               <el-form-item label="维修内容" prop="handleContent">
                 <el-input :disabled="maintenanceInfo.state !== 0" type="textarea" :rows="2" v-model="maintenanceInfo.handleContent" />
@@ -104,7 +117,20 @@
             <h4>设备审批</h4>
             <el-form ref="maintenanceInfoForm2" v-if="maintenanceInfo.state >= 1" :model="maintenanceInfo" label-width="auto" style="max-width: 400px" :rules="rules2">
               <el-form-item label="审批人员" prop="auditUser">
-                <el-input :disabled="maintenanceInfo.state !== 1 && readonly"  v-model="maintenanceInfo.auditUser" />
+<!--                <el-input :disabled="maintenanceInfo.state !== 1 && readonly"  v-model="maintenanceInfo.auditUser" />-->
+                <el-select
+                    v-model="maintenanceInfo.auditUser"
+                    placeholder="审批人员"
+                    :disabled="maintenanceInfo.state !== 1 && readonly"
+                    size="large"
+                    filterable>
+                  <el-option
+                      v-for="item in userList"
+                      :key="item.userName"
+                      :label="item.userName"
+                      :value="item.userName"
+                  />
+                </el-select>
               </el-form-item>
               <el-form-item label="审批结果">
                 <el-radio-group :disabled="maintenanceInfo.state !== 1 && readonly" v-model="maintenanceInfo.auditResult" class="ml-4">

+ 1 - 1
src/views/device/rule/index.vue

@@ -185,7 +185,7 @@ const queryAliasField = (deviceType)=>{
   })
 }
 const fieldOptions = ref([])
-const clickId = ref([])
+const clickId = ref(null)
 /** 查询 */
 function handleQuery() {
   loading.value = true;

+ 0 - 13
src/views/plan/order/index.vue

@@ -270,19 +270,6 @@ option.value = {
       prop: "materialModel",
     },
     {
-      label: "产品版本",
-      width: 120,
-      overHidden: true,
-      prop: "materialVersion",
-      rules: [
-        {
-          required: true,
-          message: "产品版本不能为空",
-          trigger: "trigger",
-        },
-      ],
-    },
-    {
       label: "订单状态",
       prop: "orderState",
       display: false,

+ 112 - 126
src/views/plan/prepare/index.vue

@@ -10,26 +10,44 @@
         @row-save="createRow"
         @row-update="updateRow"
         @row-del="deleteRow"
+        @tree-load="treeLoad"
         @search-change="searchChange"
         @search-reset="resetChange"
         @size-change="dataList"
         @current-change="dataList"
         @selection-change="selectionChange"
+        :span-method="spanMethod"
     >
-
+      <template #orderCode="{ row }">
+        <el-text v-if="row.orderCode">{{row.orderCode}}</el-text>
+        <div style="width: 100%; height: 100%;display: flex" v-if="!row.orderCode && row.operationDetails">
+          <div style="width: 120px;height: 100%"  v-for="item in row.operationDetails">
+            <el-progress
+                :text-inside="true"
+                :stroke-width="35"
+                :font-color="'#ff0000'"
+                :percentage="item.completeNum/row.workOrderNum * 100"
+                status="success"
+            >{{item.operationName}}(完成{{item.completeNum}})
+            </el-progress>
+          </div>
+        </div>
+        <el-tag v-if="row.workOrderCode === '-' && row.stockNum > 0" type="primary">库存数量:{{ row.stockNum }}</el-tag>
+        <el-tag v-if="row.workOrderCode === '-' && row.stockNum === '0'" type="danger">库存数量:{{ row.stockNum }}</el-tag>
+      </template>
       <template #menu="{size,row,index}">
-        <el-button
+<!--        <el-button
             type="primary"
             link
             v-if="row.bom === '0' || row.dataFile === '0'|| row.routeId === '0'|| row.craftFile === '0'"
             size="small"
             @click="handleEdit(row,0)"
         ><i-ep-edit />编辑
-        </el-button>
+        </el-button>-->
         <el-button
             type="primary"
             link
-            v-if="row.materialState === '0' || row.deviceState === '0'"
+            v-if="row.materialState === '-' || row.deviceState === '-' || row.bom === '-' || row.craftFile === '-'"
             size="small"
             @click="handleRefresh(row.workOrderCode)"
         ><i-ep-edit />刷新
@@ -69,9 +87,10 @@
 import { ref, getCurrentInstance } from "vue";
 import { useCrud } from "@/hooks/userCrud";
 import {prepareCheckInfo,refreshPrepareCheckInfo} from "@/api/order"
-
+import {queryChildrenInfo} from "@/api/process"
 import { useCommonStoreHook } from "@/store";
 const { isShowTable, tableType } = toRefs(useCommonStoreHook());
+const router = useRouter();
 const test = () => {
   isShowTable.value = true;
   tableType.value = tableType.value == 1 ? 2 : 1;
@@ -91,6 +110,26 @@ const dialog = reactive({
   title: "订单选择",
   visible: false,
 });
+const merginState = ref(false)
+const spanMethod = ({ row, column, rowIndex, columnIndex })=>{
+  if(row.hasParent){
+    if(columnIndex === 6){
+      merginState.value = true
+      return [1, 11]
+    }else if(columnIndex > 6 && merginState){
+      return [0,0]
+    }
+  }else{
+    merginState.value = false
+  }
+  /*if (rowIndex % 2 === 0) {
+    if (columnIndex === 0) {
+      return [1, 2]
+    } else if (columnIndex === 1) {
+      return [0, 0]
+    }
+  }*/
+}
 const checkInfo = (code) =>{
   prepareCheckInfo(code).then((data)=>{
     form.value.deviceStr = data.data.deviceStr
@@ -99,6 +138,11 @@ const checkInfo = (code) =>{
     form.value.materialStr = data.data.materialStr
   })
 }
+const treeLoad = (tree, treeNode, resolve) =>{
+  queryChildrenInfo(tree.workOrderCode).then((data)=>{
+    resolve(data.data)
+  })
+}
 const handleEdit =(row,index)=>{
   crudRef.value && crudRef.value.rowEdit(row,index);
 }
@@ -126,6 +170,11 @@ option.value = Object.assign(option.value, {
   delBtn: false,
   selection: false,
   editBtn: false,
+  tree: true,
+  viewBtn: false,
+  lazy: true,
+  menuWidth: 100,
+  rowKey: 'workOrderCode',
   addBtn: false,
   dialogWidth: '45%', // 设置编辑弹窗的宽度为50%
   column: [
@@ -133,8 +182,7 @@ option.value = Object.assign(option.value, {
       label: "工单号",
       prop: "workOrderCode",
       search: true,
-      width: 140,
-      overHidden: true,
+      minWidth: 200,
       editDisabled : true,
       rules: [
         {
@@ -155,83 +203,90 @@ option.value = Object.assign(option.value, {
       }
     },
     {
-      label: "计划单号",
-      prop: "orderCode",
+      label: "产品编码",
+      prop: "materialCode",
       search: true,
-      width: 140,
+      width: 130,
       overHidden: true,
       disabled: true,
       rules: [
         {
           required: true,
-          message: "计划单号不能为空",
+          message: "产品编码不能为空",
           trigger: "trigger",
         },
       ],
     },
     {
-      label: "计划名称",
-      prop: "orderName",
-      search: true,
+      label: "产品名称",
+      prop: "materialName",
       disabled: true,
-      width: 150,
+      width: 140,
       overHidden: true,
+      search: true,
       rules: [
         {
           required: true,
-          message: "计划名称不能为空",
+          message: "产品名称不能为空",
           trigger: "trigger",
         },
       ],
     },
     {
-      label: "产品编码",
-      prop: "materialCode",
+      label: "产品规格",
+      prop: "materialModel",
+      disabled: true,
       search: true,
       width: 140,
       overHidden: true,
-      disabled: true,
       rules: [
         {
           required: true,
-          message: "产品编码不能为空",
+          message: "产品规格不能为空",
           trigger: "trigger",
         },
       ],
     },
     {
-      label: "产品名称",
-      prop: "materialName",
+      label: "数量",
+      prop: "workOrderNum",
       disabled: true,
-      width: 150,
+      width: 80,
       overHidden: true,
+    },
+    {
+      label: "计划单号",
+      prop: "orderCode",
       search: true,
+      width: 130,
+      overHidden: true,
+      disabled: true,
       rules: [
         {
           required: true,
-          message: "产品名称不能为空",
+          message: "计划单号不能为空",
           trigger: "trigger",
         },
       ],
     },
     {
-      label: "产品规格",
-      prop: "materialModel",
-      disabled: true,
+      label: "计划名称",
+      prop: "orderName",
       search: true,
-      width: 150,
+      disabled: true,
+      width: 140,
       overHidden: true,
       rules: [
         {
           required: true,
-          message: "产品规格不能为空",
+          message: "计划名称不能为空",
           trigger: "trigger",
         },
       ],
     },
     {
-      label: "工艺文件",
-      width: 115,
+      label: "文件资料",
+      width: 350,
       overHidden: true,
       prop: "craftFile",
       addDisplay: false,
@@ -239,15 +294,15 @@ option.value = Object.assign(option.value, {
       editDisplay: false,
       html: true,
       formatter: (val) => {
-        if (val.craftFile === '1') {
-          return '<b class="el-tag el-tag--success el-tag--light">已齐套</b>';
+        if (val.craftFile !== '-') {
+          return '<b class="el-tag el-tag--success el-tag--light">'+val.craftFile+'</b>';
         }
-        return '<b class="el-tag el-tag--danger el-tag--light">未齐套</b>';
+        return '<b class="el-tag el-tag--danger el-tag--light">-</b>';
       },
     },
     {
       label: "工艺BOM",
-      width: 115,
+      width: 90,
       overHidden: true,
       prop: "bom",
       viewDisplay: false,
@@ -255,15 +310,15 @@ option.value = Object.assign(option.value, {
       editDisplay: false,
       html: true,
       formatter: (val) => {
-        if (val.bom === '1') {
-          return '<b class="el-tag el-tag--success el-tag--light">已齐套</b>';
+        if (val.bom !== '-') {
+          return '<b class="el-tag el-tag--success el-tag--light">'+val.bom+'</b>';
         }
-        return '<b class="el-tag el-tag--danger el-tag--light">未齐套</b>';
+        return '<b class="el-tag el-tag--danger el-tag--light">-</b>';
       },
     },
     {
       label: "工艺路线",
-      width: 115,
+      width: 160,
       overHidden: true,
       viewDisplay: false,
       addDisplay: false,
@@ -271,100 +326,18 @@ option.value = Object.assign(option.value, {
       prop: "routeId",
       html: true,
       formatter: (val) => {
-        if (val.routeId === '1') {
-          return '<b class="el-tag el-tag--success el-tag--light">已齐套</b>';
-        }
-        return '<b class="el-tag el-tag--danger el-tag--light">未齐套</b>';
-      },
-    },
-    {
-      label: "设计文件",
-      prop: "dataFile",
-      width: 115,
-      overHidden: true,
-      viewDisplay: false,
-      addDisplay: false,
-      editDisplay: false,
-      html: true,
-      formatter: (val) => {
-        if (val.dataFile === '1') {
-          return '<b class="el-tag el-tag--success el-tag--light">已齐套</b>';
+        if (val.routeId !== '-') {
+          return '<b class="el-tag el-tag--success el-tag--light">'+val.routeId+'</b>';
         }
-        return '<b class="el-tag el-tag--danger el-tag--light">未齐套</b>';
+        return '<b class="el-tag el-tag--danger el-tag--light">-</b>';
       },
     },
     {
-      label: "工艺文件",
-      width: 115,
-      overHidden: true,
-      prop: "craftFiles",
-      type: 'checkbox',
-      span: 12,
-      hide: true,
-      dicData: [{label: '已齐套', value: '1'}],
-    },
-    {
-      label: "工艺BOM",
-      width: 150,
-      span: 12,
-      type: "checkbox",
-      overHidden: true,
-      prop: "boms",
-      hide: true,
-      dicData: [ { label: "已齐套", value: "1", }, ],
-    },
-    {
-      label: "工艺路线",
-      width: 150,
-      span: 12,
-      type: "checkbox",
-      overHidden: true,
-      hide: true,
-      prop: "routeIds",
-      dicData: [ { label: "已齐套", value: "1", }, ],
-    },
-    {
-      label: "设计文件",
-      prop: "dataFiles",
-      width: 150,
-      overHidden: true,
-      type: 'checkbox',
-      span: 12,
-      multiple: true,
-      hide: true,
-      dicData: [ { label: "已齐套", value: "1", }, ],
-    },
-    {
-      label: "设备状况",
-      prop: "deviceState",
-      width: 150,
-      hide: true,
-      addDisplay: false,
-      overHidden: true,
-      viewDisplay: false,
-      editDisplay: false,
-      span: 24,
-      dicData: [ { label: "已齐套", value: "1", },{ label: "未齐套", value: "0", }, ],
-    },
-    {
-      label: "物料状态",
-      prop: 'materialState',
-      width: 130,
-      hide: true,
-      editDisplay: false,
-      addDisplay: false,
-      viewDisplay: false,
-      overHidden: true,
-      span: 24,
-      dicData: [ { label: "已齐套", value: "1", },{ label: "未齐套", value: "0", },  ],
-    },
-    {
       label: "设备状况",
       prop: "deviceStr",
       disabled: true,
       width: 200,
       overHidden: true,
-      span: 24,
       html: true,
       formatter: (val) => {
         if (val.deviceState === '1') {
@@ -391,11 +364,12 @@ option.value = Object.assign(option.value, {
     {
       label: "创建时间",
       prop: "created",
-      width: 160,
+      width: 200,
       display: false
     },
     {
       label: "创建人",
+      width: 200,
       prop: "creator",
       display: false
     },
@@ -406,8 +380,20 @@ option.value = Object.assign(option.value, {
 onMounted(() => {
   form.value.routeId = "1"
   form.value.materialState = 1
-  // console.log("crudRef", crudRef)
+  let url = window.location.href
+  if(url.includes("workOrderCode")){
+    search.value.workOrderCode = url.substring(url.indexOf("workOrderCode")+ 14)
+  }
   dataList();
 });
 
 </script>
+<style scoped>
+:deep(.el-progress-bar__innerText) {
+  color: #737674;
+  display: inline-block;
+  font-size: 12px;
+  margin: 0 5px;
+  vertical-align: middle;
+}
+</style>

+ 4 - 0
src/views/plan/requisition/index.vue

@@ -581,6 +581,10 @@ option.value = Object.assign(option.value, {
 });
 
 onMounted(() => {
+  let url = window.location.href
+  if(url.includes("workOrderCode")){
+    search.value.workOrderCode = url.substring(url.indexOf("workOrderCode")+ 14)
+  }
   queryWorkOrderList({}).then((data)=>{
     if(!data.data){
       ElMessage.warning("请维护物料BOM")

+ 20 - 4
src/views/plan/schedule/index.vue

@@ -36,7 +36,7 @@
 import { ref } from "vue";
 import { useCrud } from "@/hooks/userCrud";
 import dictDataUtil from "@/common/configs/dictDataUtil";
-
+import {queryStationByLineId} from "@/api/station"
 import { useDictionaryStoreHook } from "@/store";
 import { getStatistics } from "@/api/order/index";
 import * as echarts from "echarts";
@@ -55,9 +55,12 @@ const { selectionChange, multipleDelete } = Methords; //选中和批量删除事
 const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等工具
 
 const crudRef = ref(null); //crudRef.value 获取avue-crud对象
-
+const stationList = ref([])
 const charts = ref(null);
 const handleEdit =(row,index) =>{
+  queryStationByLineId(row.productLineId).then((data)=>{
+    stationList.value = data.data
+  })
   crudRef.value && crudRef.value.rowEdit(row, index);
 }
 onMounted(() => {
@@ -119,7 +122,21 @@ option.value = Object.assign(option.value, {
       label: "工位名称",
       prop: "stationName",
       search: true,
-      editDisabled: true,
+      display: false,
+    },
+    {
+      label: "工位名称",
+      hide: true,
+      editDisabled: false,
+      type: 'select',
+      dicData: stationList,
+      prop: "stationId",
+      props: { label: "name", value: "id" },
+      rules: [{
+        required: true,
+        message: "请选择工位名称",
+        trigger: "blur"
+      }],
     },
     {
       label: "工单编码",
@@ -128,7 +145,6 @@ option.value = Object.assign(option.value, {
       width: 125,
       editDisabled: true,
     },
-
     {
       label: "产线名称",
       prop: "productLineName",

+ 9 - 5
src/views/plan/workOrder/components/choice-route-page.vue

@@ -38,21 +38,25 @@ const props = defineProps({
     default: () => {
       return '';
     }
+  },
+  processRouteType: {
+    type: String,
+    default: () => {
+      return '';
+    }
   }
 })
 watch(
   () => props.materialCode,
   () => {
     search.value.prodtCode = props.materialCode
-    search.value.enabled = "0"
     dataList();
   }
 );
 watch(
-    () => props.materialVersion,
+    () => props.processRouteType,
     () => {
-      search.value.processRouteVersion = props.materialVersion
-      search.value.enabled = "0"
+      search.value.processRouteType = props.processRouteType
       dataList();
     }
 );
@@ -182,8 +186,8 @@ option.value = Object.assign(option.value, {
 });
 
 onMounted(() => {
-  search.value.processRouteVersion = props.materialVersion
   search.value.prodtCode = props.materialCode
+  search.value.processRouteType =  props.processRouteType
   search.value.enabled = "0"
   dataList();
 });

+ 36 - 9
src/views/plan/workOrder/components/work-order-seq.vue

@@ -52,9 +52,26 @@
         @close="dialog.visible = false"
     >
       <div style="display: flex;flex-wrap: wrap;" ref="toPrintRef">
-        <div v-for="item of toDeleteIds" style="width: 200px;height:220px;">
+        <div v-for="item of toDeleteIds" style="width: 238px;height:325px;font-size:10px;">
           <vue-qrcode  :value="item.seqNo"  size="45" error-level="H"></vue-qrcode>
-          <div style="font-size:14px;">{{item.seqNo}}</div>
+          <div>
+            <el-text>{{item.seqNo}}</el-text>
+          </div>
+          <div>
+            <el-text>工单号:</el-text><el-text>{{info.workOrderCode}}</el-text>
+          </div>
+          <div>
+            <el-text>计划单号:</el-text><el-text>{{info.orderCode}}</el-text>
+          </div>
+          <div>
+            <el-text>物料号:</el-text><el-text>{{info.materialCode}}</el-text>
+          </div>
+          <div>
+            <el-text>物料名称:</el-text><el-text>{{info.materialName}}</el-text>
+          </div>
+          <div>
+            <el-text>物料型号:</el-text><el-text>{{info.materialModel}}</el-text>
+          </div>
         </div>
       </div>
       <div class="dialog-footer" align="center">
@@ -69,6 +86,7 @@
 import {defineProps, ref} from "vue";
 import { useCrud } from "@/hooks/userCrud";
 import { useCommonStoreHook } from "@/store";
+import dictDataUtil from "@/common/configs/dictDataUtil";
 import { html2CanvasPrint } from "@/utils/common";
 const { isShowTable, tableType } = toRefs(useCommonStoreHook());
 const toPrintRef = ref(null);
@@ -76,11 +94,12 @@ const test = () => {
   isShowTable.value = true;
   tableType.value = tableType.value == 1 ? 2 : 1;
 };
+const info = ref({})
 const props = defineProps({
-  workOrderCode: {
-    type: String,
+  workOrderInfo: {
+    type: Object,
     default: () => {
-      return 0;
+      return null;
     }
   }
 })
@@ -95,9 +114,10 @@ const selectionChange1 =(row)=>{
   toDeleteIds.value = row
 }
 watch(
-    () => props.workOrderCode,
+    () => props.workOrderInfo,
     () => {
-      search.value.workOrderCode = props.workOrderCode
+      info.value = props.workOrderInfo
+      search.value.workOrderCode = props.workOrderInfo.workOrderCode
       dataList();
     }
 );
@@ -152,13 +172,20 @@ option.value = Object.assign(option.value, {
       prop: "state",
       minWidth: 60,
       type: "select",
-      dicData: [{label: '正常',value: 0},{label: '冻结',value: 1},{label: '完成',value: 2}],
+      dicUrl:
+          dictDataUtil.request_url +
+          dictDataUtil.TYPE_CODE.work_order_seq_state,
+      props: {
+        label: "dictLabel",
+        value: "dictValue",
+      }
     },
   ],
 });
 
 onMounted(() => {
-  search.value.workOrderCode = props.workOrderCode
+  info.value = props.workOrderInfo
+  search.value.workOrderCode = props.workOrderInfo.workOrderCode
   dataList();
 });
 /**

+ 63 - 6
src/views/plan/workOrder/index.vue

@@ -63,7 +63,7 @@
         <el-button
             icon="el-icon-setting"
             text
-            @click="showSeqPage(row.workOrderCode)"
+            @click="showSeqPage(row)"
             type="primary"
             :size="size">流转卡号</el-button>
         <el-button
@@ -73,6 +73,18 @@
             @click="revoke(row.id)"
             type="primary"
             :size="size">撤销</el-button>
+        <el-button
+            icon="el-icon-setting"
+            text
+            @click="jumpPage(row.workOrderCode,1)"
+            type="primary"
+            :size="size">领用申请</el-button>
+        <el-button
+            icon="el-icon-setting"
+            text
+            @click="jumpPage(row.workOrderCode,2)"
+            type="primary"
+            :size="size">生产准备</el-button>
       </template>
     </avue-crud>
     <el-dialog
@@ -90,7 +102,7 @@
         width="80%"
         @close="dialog1.visible = false"
     >
-      <choice-route-page :material-version="materialVersion" :material-code="form.materialCode" @routeInfo="routeInfo"/>
+      <choice-route-page :processRouteType="processRouteType" :material-code="form.materialCode" @routeInfo="routeInfo"/>
     </el-dialog>
 
     <el-dialog
@@ -117,7 +129,7 @@
         width="950px"
         @close="dialog4.visible = false"
     >
-      <work-order-seq :workOrderCode="form.workOrderCode"/>
+      <work-order-seq :workOrderInfo="form"/>
     </el-dialog>
 
     <el-dialog
@@ -180,10 +192,12 @@ import WorkOrderSeq from "./components/work-order-seq.vue";
 import { checkPerm } from "@/directive/permission";
 import {queryDictDataByType} from "@/api/system/dict"
 const { isShowTable, tableType } = toRefs(useCommonStoreHook());
+const router = useRouter();
 const test = () => {
   isShowTable.value = true;
   tableType.value = tableType.value == 1 ? 2 : 1;
 };
+const processRouteType = ref('')
 const permission = reactive({
   delBtn: checkPerm(buttonPermission.PLAN.BTNS.work_order_del),
   addBtn: checkPerm(buttonPermission.PLAN.BTNS.work_order_add),
@@ -193,6 +207,14 @@ const permission = reactive({
 const disabledDate = (time) =>{
   return time.getTime() < Date.now(); // 8.64e7 毫秒数代表一天
 }
+
+const jumpPage= (workOrderCode,type) =>{
+  if(type === 1){
+    router.push('/requisition?workOrderCode=' + workOrderCode);
+  }else{
+    router.push('/plan/prepare?workOrderCode=' + workOrderCode);
+  }
+}
 const dialog = reactive({
   title: "订单选择",
   visible: false,
@@ -224,7 +246,7 @@ const aps =(id)=>{
   dialog5.visible = true
 }
 const showSeqPage =(workOrderCode)=>{
-  form.value.workOrderCode = workOrderCode
+  form.value = workOrderCode
   dialog4.visible = true
 }
 const distribute = (id)=>{
@@ -293,7 +315,7 @@ const handleSubmit =()=>{
     }
   });
 }
-const materialVersion = ref(null)
+
 const orderInfo = (value) => {
   form.value.orderCode = value.orderCode
   form.value.orderName = value.orderName
@@ -301,7 +323,16 @@ const orderInfo = (value) => {
   form.value.materialName = value.materialName
   form.value.materialModel = value.materialModel
   form.value.priority = value.priority
-  materialVersion.value = value.materialVersion
+  form.value.orderType = value.orderType
+  form.value.processRouteId = ''
+  form.value.processRouteCode = ''
+  form.value.processRouteName = ''
+  form.value.processRouteVersion = ''
+  form.value.productLineId = ''
+  form.value.productLineName = ''
+  form.value.workshopName = ''
+  form.value.workshopCode = ''
+  form.value.workshopName = ''
   dialog.visible = false
 }
 const lineInfo = (value) => {
@@ -319,6 +350,7 @@ const routeInfo = (value) => {
   form.value.processRouteId = value.id
   form.value.processRouteCode = value.processRouteCode
   form.value.processRouteName = value.processRouteName
+  form.value.processRouteVersion = value.processRouteVersion
   dialog1.visible = false
 }
 // 传入一个url,后面不带/
@@ -375,6 +407,19 @@ option.value = Object.assign(option.value, {
       overHidden: true,
     },
     {
+      label: "订单类型",
+      prop: "orderType",
+      type: "select", //类型为下拉选择框
+      width: 100,
+      disabled: true,
+      overHidden: true,
+      dicUrl: dictDataUtil.request_url + dictDataUtil.TYPE_CODE.plan_order_type,
+      props: {
+        label: "dictLabel",
+        value: "dictValue",
+      },
+    },
+    {
       label: "产品编号",
       width: 125,
       overHidden: true,
@@ -445,11 +490,23 @@ option.value = Object.assign(option.value, {
             })
             return;
           }
+          processRouteType.value = form.value.orderType === '1' ? "ZC" : "FG"
           dialog1.visible = true
         }
       },
     },
     {
+    label: "工艺版本",
+    width: 100,
+    overHidden: true,
+    prop: "processRouteVersion",
+    display: false,
+      html: true,
+      formatter: (val) => {
+        return '<b class="el-tag el-tag--success el-tag--light">'+val.processRouteVersion+'</b>';
+      },
+  },
+    {
       label: "生产车间",
       prop: "workshopName",
       width: 120,

+ 100 - 0
src/views/system/message/editor/index.vue

@@ -0,0 +1,100 @@
+<template>
+  <div>
+    <!-- 此处注意写法v-model:content -->
+    <QuillEditor ref="myQuillEditor"
+                 theme="snow"
+                 v-model:content="content"
+                 :options="data.editorOption"
+                 contentType="html"
+                 @update:content="setValue()"
+    />
+    <!-- 使用自定义图片上传 -->
+<!--    <input type="file" hidden accept=".jpg,.png" ref="fileBtn" @change="handleUpload" />-->
+  </div>
+</template>
+
+<script setup>
+import { QuillEditor } from '@vueup/vue-quill'
+import '@vueup/vue-quill/dist/vue-quill.snow.css'
+import { reactive, onMounted, ref, toRaw, watch } from 'vue'
+
+const props = defineProps(['value'])
+const emit = defineEmits(['updateValue'])
+const content = ref('')
+const myQuillEditor = ref()
+// 通过watch监听回显,笔者这边使用v-model:content 不能正常回显
+watch(() => props.value, (val) => {
+  toRaw(myQuillEditor.value).setHTML(val)
+}, { deep: true })
+const fileBtn = ref()
+const data = reactive({
+  content: '',
+  editorOption: {
+    modules: {
+      toolbar: [
+        ['bold', 'italic', 'underline', 'strike'],
+        [{ 'size': ['small', false, 'large', 'huge'] }],
+        [{ 'font': [] }],
+        [{ 'align': [] }],
+        [{ 'list': 'ordered' }, { 'list': 'bullet' }],
+        [{ 'indent': '-1' }, { 'indent': '+1' }],
+        [{ 'header': 1 }, { 'header': 2 }],
+       /* ['image'],*/
+        [{ 'direction': 'rtl' }],
+        [{ 'color': [] }, { 'background': [] }]
+      ]
+    },
+    placeholder: '请输入内容...'
+  }
+})
+const imgHandler = (state) => {
+  if (state) {
+    fileBtn.value.click()
+  }
+}
+// 抛出更改内容,此处避免出错直接使用文档提供的getHTML方法
+const setValue = () => {
+  const text = toRaw(myQuillEditor.value).getHTML()
+  emit("updateValue", text)
+
+  /*const quill = toRaw(myQuillEditor.value).getQuill()
+  quill.setSelection(quill.getLength(),quill.getLength()+1)*/
+}
+/*const handleUpload = (e) => {
+  const files = Array.prototype.slice.call(e.target.files)
+  // console.log(files, "files")
+  if (!files) {
+    return
+  }
+  const formdata = new FormData()
+  formdata.append('file', files[0])
+  backsite.uploadFile(formdata)  // 此处使用服务端提供上传接口
+      .then(res => {
+        if (res.data.url) {
+          const quill = toRaw(myQuillEditor.value).getQuill()
+          const length = quill.getSelection().index
+          quill.insertEmbed(length, 'image', res.data.url)
+          quill.setSelection(length + 1)
+        }
+      })
+}*/
+// 初始化编辑器
+onMounted(() => {
+  /*const quill = toRaw(myQuillEditor.value).getQuill()
+  if (myQuillEditor.value) {
+    quill.getModule('toolbar').addHandler('image', imgHandler)
+  }*/
+  toRaw(myQuillEditor.value).setHTML(props.value)
+})
+</script>
+<style scoped lang="scss">
+// 调整样式
+:deep(.ql-editor) {
+  min-height: 180px;
+}
+:deep(.ql-formats) {
+  height: 21px;
+  line-height: 21px;
+}
+</style>
+

+ 328 - 0
src/views/system/message/index.vue

@@ -0,0 +1,328 @@
+<template>
+  <div class="mainContentBox">
+    <avue-crud
+        ref="crudRef"
+        v-model:search="search"
+        v-model="form"
+        :data="data"
+        :option="option"
+        v-model:page="page"
+        @row-save="createRow"
+        @row-update="updateRow"
+        @row-del="deleteRow"
+        @search-change="searchChange"
+        @search-reset="resetChange"
+        @size-change="dataList"
+        @current-change="dataList"
+        @selection-change="selectionChange"
+    >
+      <template #menu-left="{ size }">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          :size="size"
+          @click="messageDialog"
+          >新增</el-button
+        >
+      </template>
+      <template #menu="{size,row,index}">
+        <el-button
+            v-if="row.state === '0'"
+            type="primary"
+            link
+            size="small"
+            @click="handleEdit(row,0)"
+        ><i-ep-edit />编辑
+        </el-button>
+
+        <el-button
+            type="primary"
+            link
+            v-if="row.state === '0'"
+            size="small"
+            @click="handleSend(row,0)"
+        ><i-ep-edit />发送
+        </el-button>
+      </template>
+    </avue-crud>
+    <el-dialog
+        v-model="dialog.visible"
+        :title="dialog.title"
+        width="800px"
+        @close="dialog.visible = false"
+    >
+      <el-form
+          ref="userFormRef"
+          :model="message"
+          :rules="rules"
+          label-width="90px"
+      >
+        <el-row :gutter="22">
+          <el-col :span="11">
+            <el-form-item label="标题" prop="title">
+              <el-input class="!w-[220px]" v-model="message.title" placeholder="请输入标题" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="11">
+            <el-form-item label="类型" prop="type">
+              <el-select
+                  disabled
+                  v-model="message.type"
+                  placeholder="类型"
+                  clearable
+                  class="!w-[220px]"
+              >
+                <el-option
+                    v-for="item in messageTypes"
+                    :key="item.dictValue"
+                    :label="item.dictLabel"
+                    :value="item.dictValue"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="22" v-if="message.type === '1'">
+          <el-col :span="22">
+            <el-form-item label="接收人员" prop="receiveUsers">
+              <el-select
+                  v-model="message.receiveUsers"
+                  placeholder="类型"
+                  clearable
+                  multiple
+                  filterable
+                  class="!w-[500px]"
+              >
+                <el-option
+                    v-for="item in userList"
+                    :key="item.id"
+                    :label="item.userName"
+                    :value="item.id"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="22">
+          <el-col :span="22">
+            <el-form-item label="内容" prop="content">
+              <Editor :value="editorContent" @updateValue="getMsg" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div class="dialog-footer" align="center">
+        <el-button type="primary" @click="handleSubmit">确 定</el-button>
+        <el-button @click="dialog.visible = false">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script setup>
+import { ref, getCurrentInstance } from "vue";
+import { useCrud } from "@/hooks/userCrud";
+import Editor from '@/views/system/message/editor/index.vue'
+import {addMessage, updateMessage} from '@/api/system/message'
+import { useCommonStoreHook } from "@/store";
+import {getUserList} from "@/api/system/user"
+import {queryDictDataByType} from "@/api/system/dict"
+const { isShowTable, tableType } = toRefs(useCommonStoreHook());
+const userFormRef = ref(ElForm); // 用户表单
+const message = ref({
+  title: "",
+  content: "",
+  type: "0",
+  receiveUsers: []
+});
+const test = () => {
+  isShowTable.value = true;
+  tableType.value = tableType.value == 1 ? 2 : 1;
+};
+const  handleSubmit = ()=>{
+  userFormRef.value.validate((valid) => {
+    if (valid) {
+      if(message.value.id){
+        updateMessage(message.value).then((data)=>{
+          if(data.code === '200'){
+            ElMessage.success(data.msg)
+            dialog.visible = false
+            dataList()
+          }else{
+            ElMessage.error(data.msg)
+          }
+        })
+      }else{
+        addMessage(message.value).then((data)=>{
+          if(data.code === '200'){
+            ElMessage.success(data.msg)
+            dialog.visible = false
+            dataList()
+          }else{
+            ElMessage.error(data.msg)
+          }
+        })
+      }
+    }
+  });
+}
+const handleEdit =(row,index)=>{
+  message.value = row
+  editorContent.value = row.content
+  dialog.visible = true
+}
+const handleSend =(row,index)=>{
+  ElMessageBox.confirm("确定要发送吗?", "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+    lockScroll: false,
+  }).then(() => {
+    row.state = 1
+    updateMessage(row).then((data)=>{
+      if(data.code === '200'){
+        ElMessage.success(data.msg)
+        dialog.visible = false
+        dataList()
+      }else{
+        ElMessage.error(data.msg)
+      }
+    })
+  });
+}
+const editorContent = ref(null)
+const crudRef = ref(null); //crudRef.value 获取avue-crud对象
+const dialog = reactive({
+  title: "消息管理",
+  visible: false,
+  type: "0",
+  state: "0"
+});
+
+const rules = reactive({
+  title: [{ required: true, message: "标题不能为空", trigger: "blur" }],
+  content: [{ required: true, message: "内容不能为空", trigger: "blur" }],
+  receiveUsers: [{ required: true, message: "人员不能为空", trigger: "blur" }],
+});
+// 传入一个url,后面不带/
+const { form, data, option, search, page, toDeleteIds, Methords, Utils } =
+  useCrud({
+    src: "/api/v1/sys/message",
+  });
+const { dataList, createRow, updateRow, deleteRow, searchChange, resetChange } = Methords; //增删改查
+const { selectionChange, multipleDelete } = Methords; //选中和批量删除事件
+const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等工具
+
+const getMsg =(val)=>{
+  message.value.content = val
+}
+const messageDialog = ()=>{
+  message.value.title = ''
+  message.value.content = ''
+  message.value.receiveUsers = []
+  editorContent.value = ""
+  dialog.visible = true
+}
+const messageTypes = ref([])
+const userList = ref([])
+const queryUserList = ()=>{
+  getUserList({}).then((data)=>{
+    userList.value = data.data
+  })
+  queryDictDataByType("system_message_type").then((data)=>{
+    messageTypes.value = data.data
+  })
+}
+// 设置表格列或者其他自定义的option
+option.value = Object.assign(option.value, {
+  delBtn: false,
+  selection: false,
+  addBtn: false,
+  editBtn: false,
+  viewBtn: false,
+  column: [
+    {
+      label: "标题",
+      prop: "title",
+      rules: [
+        {
+          required: true,
+          message: "标题不能为空",
+          trigger: "trigger",
+        },
+      ],
+    },
+    {
+      label: "内容",
+      prop: "content",
+      width: 300,
+      overHidden: true,
+      rules: [
+        {
+          required: true,
+          message: "内容不能为空",
+          trigger: "trigger",
+        },
+      ],
+      html: true,
+      formatter: (val) => {
+        return val.content;
+      },
+    },
+    {
+      label: "类型",
+      prop: "type",
+      overHidden: true,
+      type: 'select',
+      width: 150,
+      dicData: [{label: '系统消息',value: '0'},{label: '用户消息',value:'1'}],
+      rules: [
+        {
+          required: true,
+          message: "类型不能为空",
+          trigger: "trigger",
+        },
+      ],
+      html: true,
+      formatter: (val) => {
+        if (val.type === "0") {
+          return '<b class="el-tag el-tag--danger el-tag--light">系统消息</b>';
+        } else if (val.type === "1") {
+          return '<b class="el-tag el-tag--success el-tag--light">用户消息</b>';
+        }
+      },
+    },
+    {
+      label: "状态",
+      prop: "state",
+      display: false,
+      width: 150,
+      dicData: [{label: '暂存',value: '0'},{label: '已发送',value:'1'}],
+      html: true,
+      formatter: (val) => {
+        if (val.state === "0") {
+          return '<b class="el-tag el-tag--warning el-tag--light">暂存</b>';
+        } else if (val.state === "1") {
+          return '<b class="el-tag el-tag--success el-tag--light">已发送</b>';
+        }
+      },
+    },
+    {
+      label: "创建人",
+      prop: "creator",
+      display: false,
+    },
+    {
+      label: "创建时间",
+      prop: "created",
+      display: false,
+    },
+  ],
+});
+
+onMounted(() => {
+  // console.log("crudRef", crudRef)
+  search.value.type = "0"
+  dataList();
+  queryUserList()
+});
+</script>