Browse Source

添加不合格审理

qinhb 2 months ago
parent
commit
ef0e5d6690

+ 40 - 0
src/api/unqualified/index.ts

@@ -0,0 +1,40 @@
+import request from "@/utils/request";
+
+export function getUnqualifiedData(data: object) {
+  return request({
+    url: "/api/v1/unqualified/page",
+    method: "post",
+    data,
+  });
+}
+
+
+// 新增销售反馈表
+
+export function addFeedback(data: object) {
+  return request({
+    url: "/api/v1/unqualified/add",
+    method: "post",
+    data,
+  });
+}
+
+// 删除销售反馈表
+
+export function deleteFeedback(id: number) {
+  return request({
+    url: "/api/v1/unqualified/del",
+    method: "post",
+    data: { id },
+  });
+}
+
+//处理反馈表
+
+export function dealFeedback(data: object) {
+  return request({
+    url: "/api/v1/unqualified/handle",
+    method: "post",
+    data,
+  });
+}

+ 10 - 5
src/components/Search/index.vue

@@ -8,7 +8,8 @@
             class="tep"
             v-model="searchForm[option.prop]"
             placeholder="Please input"
-            size="small"
+            size="normal"
+            clearable
           />
         </div>
         <div class="item" v-if="option.type == 'select'">
@@ -17,7 +18,8 @@
           <el-select
             class="tep"
             v-model="searchForm[option.prop]"
-            size="small"
+            size="normal"
+            clearable
             placeholder="Select"
           >
             <el-option
@@ -37,7 +39,7 @@
             range-separator="-"
             start-placeholder="开始日期"
             end-placeholder="结束日期"
-            size="small"
+            size="normal"
             value-format="YYYY-MM-DD"
             format="YYYY-MM-DD"
           />
@@ -45,10 +47,10 @@
       </template>
     </div>
     <div class="oprea">
-      <el-button type="primary" size="small" class="btn" @click="getData"
+      <el-button type="primary" size="normal" class="btn" @click="getData"
         >查询</el-button
       >
-      <el-button class="btn" size="small" @click="reset">重置</el-button>
+      <el-button class="btn" size="normal" @click="reset">重置</el-button>
     </div>
   </div>
 </template>
@@ -106,6 +108,9 @@ defineExpose({ searchForm });
   .oprea {
     width: 240px;
     height: 100%;
+    display: flex;
+    justify-content: center; /* 水平居中 */
+    align-items: center;
   }
 }
 </style>

+ 9 - 0
src/router/modules/analysis.ts

@@ -66,5 +66,14 @@ export default {
         icon: "Guide",
       },
     },
+    {
+      path: "unqualified",
+      component: () => import("@/views/unqualified/index.vue"),
+      name: "Unqualified",
+      meta: {
+        title: "不合格处置",
+        icon: "Guide",
+      },
+    },
   ],
 };

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

@@ -33,6 +33,7 @@ export const useDictionaryStore = defineStore("dictionaryStore", () => {
     "excel_states",
     "spc_operation",
     "sales_info_type",
+      "unqualified_audit_type",
   ];
   const dicts = ref<{ [key: string]: any[] }>({});
 

+ 3 - 3
src/views/sales/add.vue

@@ -149,9 +149,9 @@ import { useDictionaryStore } from "@/store";
 const drawerVisible = ref(false);
 const disabledDate = (time)=> {
   //选择今天以及今天之后的日期
-  return time.getTime() < Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择
+ // return time.getTime() < Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择
   //选择今天以及今天之前的日期
-  //return time.getTime() > Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择今天的
+  return time.getTime() > Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择今天的
 }
 const { dicts } = useDictionaryStore();
 const baseInfoRef = ref(null);
@@ -210,7 +210,6 @@ const rules1 = {
 
 // 订单相关信息
 const orders = ref([]);
-const opOptions = ref([...dicts.spc_operation]);
 const typeList = dicts.sales_info_type
 const selectedOrder = ref({});
 const selectOrderCode = ref("");
@@ -299,6 +298,7 @@ const confirmClick = () => {
       let p = {
         ...saleForm,
         ...selectedOrder.value,
+        currentUserName: remark1.nextRemarkUser,
         remark1: JSON.stringify(remark1Copy),
         remark2: JSON.stringify(remark2),
       };

+ 9 - 5
src/views/sales/handle2.vue

@@ -18,7 +18,7 @@
           :autosize="{ minRows: 3, maxRows: 6 }"
         />
       </el-form-item>
-      <el-form-item label="日期" prop="time">
+<!--      <el-form-item label="日期" prop="time">
         <el-date-picker
           v-model="remark.time"
           type="date"
@@ -29,8 +29,8 @@
           value-format="YYYY年MM月DD日"
           style="width: 100%"
         />
-      </el-form-item>
-      <el-form-item label="下一步处理人" prop="nextRemarkUser">
+      </el-form-item>-->
+      <el-form-item label="下一步处理人" prop="nextRemarkUser" v-if="remark.state == 0">
         <el-tree-select
             v-model="remark.nextRemarkUser"
             :data="userList"
@@ -104,7 +104,7 @@ const remark = reactive({
   user: "",
   time: "",
   nextRemarkUser: "",
-  state: 1,
+  state: 0,
 });
 
 const cancelClick = () => {
@@ -125,13 +125,15 @@ const getUserInfo = async () => {
 };
 
 const confirmClick = () => {
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
   remark.user = userStore.user.username;
   remarkRef.value.validate((valid) => {
     if (valid) {
       let remark2Copy = {
         content: remark.content,
         user: remark.user,
-        time: remark.time,
+        time: now,
         state: remark.state,
       };
       let remark3 = {
@@ -142,7 +144,9 @@ const confirmClick = () => {
 
       let p = {
         id: saleModel.value.id,
+        currentUserName: remark.nextRemarkUser,
         remark2: JSON.stringify(remark2Copy),
+        state: remark.state,
         remark3: JSON.stringify(remark3),
         step: 1, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
       };

+ 9 - 17
src/views/sales/handle3.vue

@@ -32,7 +32,7 @@
           />
         </el-select>
       </el-form-item>-->
-      <el-form-item label="日期" prop="time">
+<!--      <el-form-item label="日期" prop="time">
         <el-date-picker
           v-model="remark.time"
           type="date"
@@ -43,20 +43,8 @@
           value-format="YYYY年MM月DD日"
           style="width: 100%"
         />
-      </el-form-item>
-      <el-form-item label="下一步处理人" prop="nextRemarkUser">
-<!--        <el-select
-          v-model="remark.nextRemarkUser"
-          placeholder="请选择处理人"
-          style="width: 100%"
-        >
-          <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="nextRemarkUser" v-if="remark.state == 0">
         <el-tree-select
             v-model="remark.nextRemarkUser"
             :data="userList"
@@ -131,7 +119,7 @@ const remark = reactive({
   user: "",
   time: "",
   nextRemarkUser: "",
-  state: 1,
+  state: 0,
 });
 
 const cancelClick = () => {
@@ -153,12 +141,14 @@ const getUserInfo = async () => {
 
 const confirmClick = () => {
   remark.user = userStore.user.username;
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
   remarkRef.value.validate((valid) => {
     if (valid) {
       let remark2Copy = {
         content: remark.content,
         user: remark.user,
-        time: remark.time,
+        time: now,
         state: remark.state,
       };
       let remark3 = {
@@ -171,6 +161,8 @@ const confirmClick = () => {
         id: saleModel.value.id,
         remark3: JSON.stringify(remark2Copy),
         remark4: JSON.stringify(remark3),
+        currentUserName: remark.nextRemarkUser,
+        state: remark.state,
         step: 3, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
       };
 

+ 9 - 5
src/views/sales/handle4.vue

@@ -32,7 +32,7 @@
                 />
               </el-select>
             </el-form-item>-->
-      <el-form-item label="日期" prop="time">
+<!--      <el-form-item label="日期" prop="time">
         <el-date-picker
             v-model="remark.time"
             type="date"
@@ -43,8 +43,8 @@
             value-format="YYYY年MM月DD日"
             style="width: 100%"
         />
-      </el-form-item>
-      <el-form-item label="下一步处理人" prop="nextRemarkUser">
+      </el-form-item>-->
+      <el-form-item label="下一步处理人" prop="nextRemarkUser" v-if="remark.state == 0">
         <!--        <el-select
                   v-model="remark.nextRemarkUser"
                   placeholder="请选择处理人"
@@ -131,7 +131,7 @@ const remark = reactive({
   user: "",
   time: "",
   nextRemarkUser: "",
-  state: 1,
+  state: 0,
 });
 
 const cancelClick = () => {
@@ -153,12 +153,14 @@ const getUserInfo = async () => {
 
 const confirmClick = () => {
   remark.user = userStore.user.username;
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
   remarkRef.value.validate((valid) => {
     if (valid) {
       let remark2Copy = {
         content: remark.content,
         user: remark.user,
-        time: remark.time,
+        time: now,
         state: remark.state,
       };
       let remark3 = {
@@ -169,7 +171,9 @@ const confirmClick = () => {
 
       let p = {
         id: saleModel.value.id,
+        currentUserName: remark.nextRemarkUser,
         remark4: JSON.stringify(remark2Copy),
+        state: remark.state,
         remark5: JSON.stringify(remark3),
         step: 4, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
       };

+ 9 - 5
src/views/sales/handle5.vue

@@ -32,7 +32,7 @@
                 />
               </el-select>
             </el-form-item>-->
-      <el-form-item label="日期" prop="time">
+<!--      <el-form-item label="日期" prop="time">
         <el-date-picker
             v-model="remark.time"
             type="date"
@@ -43,8 +43,8 @@
             value-format="YYYY年MM月DD日"
             style="width: 100%"
         />
-      </el-form-item>
-      <el-form-item label="下一步处理人" prop="nextRemarkUser">
+      </el-form-item>-->
+      <el-form-item label="下一步处理人" prop="nextRemarkUser" v-if="remark.state == 0">
         <!--        <el-select
                   v-model="remark.nextRemarkUser"
                   placeholder="请选择处理人"
@@ -131,7 +131,7 @@ const remark = reactive({
   user: "",
   time: "",
   nextRemarkUser: "",
-  state: 1,
+  state: 0,
 });
 
 const cancelClick = () => {
@@ -153,12 +153,14 @@ const getUserInfo = async () => {
 
 const confirmClick = () => {
   remark.user = userStore.user.username;
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
   remarkRef.value.validate((valid) => {
     if (valid) {
       let remark2Copy = {
         content: remark.content,
         user: remark.user,
-        time: remark.time,
+        time: now,
         state: remark.state,
       };
       let remark3 = {
@@ -171,6 +173,8 @@ const confirmClick = () => {
         id: saleModel.value.id,
         remark5: JSON.stringify(remark2Copy),
         remark6: JSON.stringify(remark3),
+        state: remark.state,
+        currentUserName: remark.nextRemarkUser,
         step: 5, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
       };
 

+ 9 - 5
src/views/sales/handle6.vue

@@ -32,7 +32,7 @@
                 />
               </el-select>
             </el-form-item>-->
-      <el-form-item label="日期" prop="time">
+<!--      <el-form-item label="日期" prop="time">
         <el-date-picker
             v-model="remark.time"
             type="date"
@@ -43,8 +43,8 @@
             value-format="YYYY年MM月DD日"
             style="width: 100%"
         />
-      </el-form-item>
-      <el-form-item label="下一步处理人" prop="nextRemarkUser">
+      </el-form-item>-->
+      <el-form-item label="下一步处理人" prop="nextRemarkUser" v-if="remark.state == 0">
         <!--        <el-select
                   v-model="remark.nextRemarkUser"
                   placeholder="请选择处理人"
@@ -131,7 +131,7 @@ const remark = reactive({
   user: "",
   time: "",
   nextRemarkUser: "",
-  state: 1,
+  state: 0,
 });
 
 const cancelClick = () => {
@@ -153,12 +153,14 @@ const getUserInfo = async () => {
 
 const confirmClick = () => {
   remark.user = userStore.user.username;
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
   remarkRef.value.validate((valid) => {
     if (valid) {
       let remark2Copy = {
         content: remark.content,
         user: remark.user,
-        time: remark.time,
+        time: now,
         state: remark.state,
       };
       let remark3 = {
@@ -171,6 +173,8 @@ const confirmClick = () => {
         id: saleModel.value.id,
         remark6: JSON.stringify(remark2Copy),
         remark7: JSON.stringify(remark3),
+        state: remark.state,
+        currentUserName: remark.nextRemarkUser,
         step: 6, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
       };
 

+ 8 - 10
src/views/sales/handle7.vue

@@ -32,7 +32,7 @@
                 />
               </el-select>
             </el-form-item>-->
-      <el-form-item label="日期" prop="time">
+<!--      <el-form-item label="日期" prop="time">
         <el-date-picker
             v-model="remark.time"
             type="date"
@@ -43,7 +43,7 @@
             value-format="YYYY年MM月DD日"
             style="width: 100%"
         />
-      </el-form-item>
+      </el-form-item>-->
 <!--      <el-form-item label="下一步处理人" prop="nextRemarkUser">
         &lt;!&ndash;        <el-select
                   v-model="remark.nextRemarkUser"
@@ -131,7 +131,7 @@ const remark = reactive({
   user: "",
   time: "",
   nextRemarkUser: "",
-  state: 1,
+  state: 0,
 });
 
 const cancelClick = () => {
@@ -153,23 +153,21 @@ const getUserInfo = async () => {
 
 const confirmClick = () => {
   remark.user = userStore.user.username;
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
   remarkRef.value.validate((valid) => {
     if (valid) {
       let remark2Copy = {
         content: remark.content,
         user: remark.user,
-        time: remark.time,
+        time: now,
         state: remark.state,
       };
-      let remark3 = {
-        content: "",
-        user: remark.nextRemarkUser, // qinhaibo和dengyu说是user1234的
-        time: "",
-      };
-
       let p = {
         id: saleModel.value.id,
         remark7: JSON.stringify(remark2Copy),
+        state: remark.state,
+        currentUserName: remark.nextRemarkUser,
         step: 7, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
       };
 

+ 6 - 5
src/views/sales/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="container">
     <div class="header">
-      <Search :searchOptions="searchForm" ref="searchRef" />
+      <Search :searchOptions="searchForm" ref="searchRef" @dataList="getData"/>
     </div>
     <div class="table">
       <el-button
@@ -17,6 +17,7 @@
         <el-table-column prop="materialName" label="物料名称" />
         <el-table-column prop="materialModel" label="物料型号" />
         <el-table-column prop="contacts" label="联系人" />
+        <el-table-column prop="currentUserName" label="审核人" overhidden="true" />
         <el-table-column prop="state" label="审核状态">
           <template #default="{ row }">
             <div :style="{ color: getColorByState(row.state) }">
@@ -42,7 +43,7 @@
             >
             <el-button
               link
-              v-if="row.state === 0 || row.state === 1"
+              v-if="(row.state === 0 || row.state === 1) && userStore.user.username == row.currentUserName"
               @click="handle(row)"
               type="primary"
               >处理</el-button
@@ -76,7 +77,7 @@
 
 <script setup>
 import Search from "@/components/Search/index.vue";
-import { useSpcStore } from "@/store";
+import { useSpcStore,useUserStore } from "@/store";
 import { deleteFeedback, getSalesData } from "@/api/sales/index";
 import Add from "@/views/sales/add.vue";
 import Detail from "@/views/sales/detail.vue";
@@ -91,7 +92,7 @@ defineOptions({
   name: "SPCSales",
 });
 const store = useSpcStore();
-
+const userStore = useUserStore();
 const router = useRouter();
 
 const addRef = ref(null);
@@ -202,7 +203,7 @@ const getColorByState = (state) => {
     case 1:
       return "#bba559";
     case 2:
-      return "909399";
+      return "#d96868";
     case 3:
       return "#67c23a";
     default:

+ 162 - 0
src/views/unqualified/DetailCom.vue

@@ -0,0 +1,162 @@
+<template>
+  <div>
+    <div class="sale-header">不合格品(质量问题)分析评审处置表</div>
+    <div class="sale-right">编号: {{saleModel.formNo}}</div>
+    <table border-collapse="collapse">
+        <tr>
+          <td>产品型号</td>
+          <td>{{ saleModel.materialModel }}</td>
+          <td>产品分类</td>
+          <td>{{ saleModel.type }}</td>
+          <td>生产批号</td>
+          <td>{{ saleModel.workOrderCode }}</td>
+        </tr>
+      <tr>
+        <td>产品编号</td>
+        <td colspan="2" style="font-weight: normal;text-align: left;">{{ saleModel.seqs }}</td>
+        <td>数量</td>
+        <td colspan="2" style="font-weight: normal;">{{ saleModel.seqNum }}</td>
+      </tr>
+        <tr>
+          <td>器件名称及型号</td>
+          <td>{{ saleModel.componentName }}</td>
+          <td>器件检验批号或器件生产批号</td>
+          <td>{{ saleModel.checkProduceNo }}</td>
+          <td>数量</td>
+          <td>{{ saleModel.num }}</td>
+        </tr>
+      <tr>
+        <td>供方单位</td>
+        <td colspan="5" style="font-weight: normal;text-align: left;">{{ saleModel.company }}</td>
+      </tr>
+      <tr>
+        <td>审理级别</td>
+        <td v-if="saleModel.level === '0'">▣ 一级 ▢ 二级</td>
+        <td v-else>▢ 一级 ▣ 二级</td>
+        <td>发生阶段</td>
+        <td>{{ saleModel.stage }}</td>
+        <td>发生时间</td>
+        <td>{{ saleModel.happenTime }}</td>
+      </tr>
+        <tr v-for="(item, index) in contentArray" :key="index">
+          <td colspan="6">
+            <div class="sale-box">
+              <div class="sale-title">{{ item.title }}</div>
+              <div class="sale-content">
+                {{ item.content }}
+              </div>
+              <div class="sale-bottom">
+                <div class="desc" v-if="index === 0">填表人:{{ item[`user`] }}</div>
+                <div class="desc" v-if="index === 0">检验人员:{{ item[`user1`] }}</div>
+
+                <div class="desc" v-if="index === 1">技术人员:{{ item[`user1`] }}</div>
+                <div class="desc" v-if="index === 1">联系电话:{{ item[`phone`] }}</div>
+                <div class="desc" v-if="index === 1">责任部门:{{ item[`user2`] }}</div>
+
+                <div class="desc" v-if="index === 2">分析单位:{{ item[`company`] }}</div>
+
+                <div class="desc" v-if="index === 3">责任部门:{{saleModel.auditType === '1' ? item[`users`] : item[`user`]}}</div>
+
+
+                <div class="desc" v-if="index === 4">责任部门:{{ item[`user`] }}</div>
+                <div class="desc" v-if="index === 5">签字:{{ item[`user`] }}</div>
+                <div class="desc" v-if="index === 6">签字:{{ item[`user`] }}</div>
+                <div class="desc">时间: {{ item.time }}</div>
+              </div>
+            </div>
+          </td>
+        </tr>
+    </table>
+  </div>
+</template>
+
+<script setup>
+const saleModel = ref({});
+
+const contentArray = ref([]);
+const refreshView = (row) => {
+  saleModel.value = row;
+
+  contentArray.value = [];
+
+  if (row.remark1 && JSON.parse(row.remark1).content) {
+    let remark1 = JSON.parse(row.remark1);
+    contentArray.value.push({ ...remark1, title: "不合格现象(质量问题)描述:" });
+  }
+  if (row.remark2 && JSON.parse(row.remark2).content) {
+    let remark2 = JSON.parse(row.remark2);
+    contentArray.value.push({ ...remark2, title: "分析处置要求:" });
+  }
+  if (row.remark3 && JSON.parse(row.remark3).content) {
+    let remark3 = JSON.parse(row.remark3);
+    contentArray.value.push({ ...remark3, title: "原因分析:" });
+  }
+  if (row.remark4 && JSON.parse(row.remark4).content) {
+    let remark4 = JSON.parse(row.remark4);
+    contentArray.value.push({ ...remark4, title: "采取的措施:" });
+  }
+  if (row.remark5 && JSON.parse(row.remark5).content) {
+    let remark5 = JSON.parse(row.remark5);
+    contentArray.value.push({ ...remark5, title: "措施落实:" });
+  }
+  if (row.remark6 && JSON.parse(row.remark6).content) {
+    let remark6 = JSON.parse(row.remark6);
+    contentArray.value.push({ ...remark6, title: "不合格品评审(审理)处置意见:" });
+  }
+  if (row.remark7 && JSON.parse(row.remark7).content) {
+    let remark7 = JSON.parse(row.remark7);
+    contentArray.value.push({ ...remark7, title: "组长(或分管领导)审批意见:" });
+  }
+};
+
+defineExpose({ refreshView });
+</script>
+
+<style scoped lang="scss">
+.sale-header {
+  text-align: center;
+  font-size: 20px;
+  //font-weight: bold;
+  margin-bottom: 10px;
+}
+.sale-right {
+  text-align: right;
+  width: 800px;
+}
+table {
+  width: 800px;
+  margin: 0 auto;
+  border: 1px solid #000000;
+  border-collapse: collapse;
+}
+
+th,
+td {
+  border: 1px solid #000000;
+  text-align: center;
+  padding: 3px;
+}
+
+.sale-box {
+  .sale-title {
+    font-size: 16px;
+    margin-bottom: 5px;
+    text-align: start;
+  }
+  .sale-content {
+    font-size: 16px;
+    min-height: 60px;
+    margin-bottom: 10px;
+    text-align: start;
+    padding: 0 8px;
+  }
+  .sale-bottom {
+    display: flex;
+    justify-content: flex-end;
+    margin-top: 10px;
+  }
+  .desc {
+    margin-right: 20px;
+  }
+}
+</style>

+ 390 - 0
src/views/unqualified/add.vue

@@ -0,0 +1,390 @@
+<template>
+  <div>
+    <el-drawer v-model="drawerVisible" size="800" :close-on-click-modal="false">
+      <template #header>
+        <h4>新增不合格审理</h4>
+      </template>
+      <template #default>
+        <el-form
+          ref="baseInfoRef"
+          :model="saleForm"
+          label-width="120"
+          :rules="rules"
+          style="max-width: 600px"
+        >
+          <el-form-item label="订单信息">
+            <el-select
+              v-model="selectOrderCode"
+              value-key="orderNo"
+              placeholder="请选择订单信息"
+              style="width: 100%"
+              @change="orderSelect"
+            >
+              <el-option
+                v-for="item in orders"
+                :key="item.orderNo"
+                :label="item.orderName + `(批号: ${item.workOrderCode})`"
+                :value="item"
+              />
+            </el-select>
+          </el-form-item>
+<!--
+          <el-form-item label="检验批号" hidden>
+            <div>{{ selectedOrder.workOrderCode }}</div>
+          </el-form-item>-->
+          <el-form-item label="流转卡号" prop="seqs">
+            <el-select
+              v-model="saleForm.seqs"
+              value-key="orderCode"
+              placeholder="请选择流转卡号"
+              style="width: 100%"
+              multiple
+            >
+              <el-option
+                v-for="item in seqList"
+                :key="item.label"
+                :label="item.label"
+                :value="item.label"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="产品分类" prop="type">
+            <el-select
+                v-model="saleForm.type"
+                value-key="value"
+                placeholder="请选择产品分类"
+                style="width: 100%"
+            >
+              <el-option
+                  v-for="item in typeList"
+                  :key="item.dictValue"
+                  :label="item.dictLabel"
+                  :value="item.dictValue"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="器件名称及型号" prop="componentName">
+            <el-input v-model="saleForm.componentName" />
+          </el-form-item>
+          <el-form-item label="检验批号或生产批号" prop="checkProduceNo">
+            <el-input v-model="saleForm.checkProduceNo"></el-input>
+            <input v-model="saleForm.workOrderCode" hidden="true"/>
+          </el-form-item>
+          <el-form-item label="数量" prop="num">
+            <el-input v-model="saleForm.num" type="number"/>
+          </el-form-item>
+          <el-form-item label="供方单位" prop="company">
+            <el-input v-model="saleForm.company"/>
+          </el-form-item>
+          <el-form-item label="审核类型" prop="auditType">
+            <el-select
+                v-model="saleForm.auditType"
+                value-key="value"
+                placeholder="请选择审核类型"
+                style="width: 100%"
+            >
+              <el-option
+                  v-for="item in auditTypes"
+                  :key="item.dictValue"
+                  :label="item.dictLabel"
+                  :value="item.dictValue"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="审理级别" prop="level">
+            <el-select
+                v-model="saleForm.level"
+                value-key="value"
+                placeholder="请选择审理级别"
+                style="width: 100%"
+            >
+              <el-option
+                  v-for="item in levelTypes"
+                  :key="item.dictValue"
+                  :label="item.dictLabel"
+                  :value="item.dictValue"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="发生阶段" prop="stage">
+            <el-input v-model="saleForm.stage"/>
+          </el-form-item>
+          <el-form-item label="发生日期" prop="happenTime">
+            <el-date-picker
+                v-model="remark1.happenTime"
+                type="date"
+                :disabled-date="disabledDate1"
+                placeholder="请选择日期"
+                clearable
+                format="YYYY年MM月DD日"
+                value-format="YYYY年MM月DD日"
+                style="width: 100%"
+            />
+          </el-form-item>
+        </el-form>
+
+
+        <el-form
+          ref="remark1Ref"
+          :model="remark1"
+          label-width="120"
+          :rules="rules1"
+          style="max-width: 600px"
+        >
+          <el-form-item label="不合格现象(质量问题)描述" prop="content">
+            <el-input v-model="remark1.content" type="textarea" />
+          </el-form-item>
+          <el-form-item label="填表人" prop="user">
+<!--            <el-select
+              v-model="remark1.user"
+              placeholder="请选择"
+              style="width: 100%"
+            >
+              <el-option
+                v-for="item in userList"
+                :key="item.userName"
+                :label="item.userName"
+                :value="item.userName"
+              />
+            </el-select>-->
+            <el-tree-select
+                v-model="remark1.user"
+                :data="userList"
+                filterable
+            />
+          </el-form-item>
+          <el-form-item label="检验人" prop="user1">
+            <el-tree-select
+                v-model="remark1.user1"
+                :data="userList"
+                filterable
+            />
+          </el-form-item>
+          <el-form-item label="日期" prop="time">
+            <el-date-picker
+              v-model="remark1.time"
+              type="date"
+              :disabled-date="disabledDate"
+              placeholder="请选择日期"
+              clearable
+              format="YYYY年MM月DD日"
+              value-format="YYYY年MM月DD日"
+              style="width: 100%"
+            />
+          </el-form-item>
+          <el-form-item label="下一步处理人" prop="nextRemarkUser">
+            <el-tree-select
+                v-model="remark1.nextRemarkUser"
+                :data="userList"
+                filterable
+            />
+          </el-form-item>
+        </el-form>
+      </template>
+      <template #footer>
+        <div class="drawer-bottom">
+          <el-button @click="cancelClick">取消</el-button>
+          <el-button type="primary" @click="confirmClick">提交</el-button>
+        </div>
+      </template>
+    </el-drawer>
+  </div>
+</template>
+
+<script setup>
+import { addFeedback } from "@/api/unqualified/index";
+import { getOrderList } from "@/api/sales/index";
+import { getUserTree } from "@/api/user/index";
+import { useDictionaryStore } from "@/store";
+const drawerVisible = ref(false);
+const disabledDate = (time)=> {
+  //选择今天以及今天之后的日期
+  return time.getTime() < Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择
+  //选择今天以及今天之前的日期
+  //return time.getTime() > Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择今天的
+}
+const disabledDate1 = (time)=> {
+  //选择今天以及今天之后的日期
+  return time.getTime() > Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择
+  //选择今天以及今天之前的日期
+  //return time.getTime() > Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择今天的
+}
+const { dicts } = useDictionaryStore();
+const auditTypes = dicts.unqualified_audit_type
+const levelTypes = ref([
+  {dictValue: "0",dictLabel: "一级"},{dictValue: "1",dictLabel: "二级"}
+])
+const baseInfoRef = ref(null);
+const saleForm = reactive({
+  customer: "",
+  address: "",
+  contacts: "",
+  phoneNo: "",
+  stage: "",
+  seqs: [],
+});
+// 顾客投诉或建议
+const remark1Ref = ref(null);
+
+const remark1 = reactive({
+  content: "",
+  user: "",
+  time: "",
+  nextRemarkUser: "",
+});
+
+const rules = {
+  type: [
+    { required: true, message: "请选择产品分类", trigger: "blur" },
+  ],
+  componentName: [
+    { required: true, message: "请输入器件名称及型号", trigger: "blur" },
+  ],
+  num: [
+    { required: true, message: "请输入数量", trigger: "blur" },
+  ],
+  auditType: [
+    { required: true, message: "请选择审核类型", trigger: "blur" },
+  ],
+  seqs: [{ required: true, message: "请选择订单信息", trigger: "change" }],
+  checkProduceNo: [{ required: true, message: "请输入检验批号或生产批号", trigger: "change" }],
+  level: [{ required: true, message: "请选择审理级别", trigger: "change" }],
+  company: [{ required: true, message: "请输入供方单位", trigger: "change" }],
+  happenTime: [{ required: true, message: "请选择发生时间", trigger: "change" }],
+  stage: [{ required: true, message: "请输入发生阶段", trigger: "change" }],
+};
+const rules1 = {
+  content: [
+    { required: true, message: "请输入不合格现象(质量问题)描述", trigger: "blur" },
+    { min: 2, max: 200, message: "长度在 2 到 200 个字符", trigger: "blur" },
+  ],
+  user: [
+    { required: true, message: "请输入姓名", trigger: "blur" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+  user1:[{ required: true, message: "检验人员不能为空", trigger: "blur" }],
+  time: [{ required: true, message: "请选择日期", trigger: "change" }],
+  nextRemarkUser: [
+    { required: true, message: "请选择处理人", trigger: "change" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+};
+
+// 订单相关信息
+const orders = ref([]);
+const opOptions = ref([...dicts.spc_operation]);
+const typeList = dicts.sales_info_type
+const selectedOrder = ref({});
+const selectOrderCode = ref("");
+const getOrders = async () => {
+  const res = await getOrderList({
+    pageNo: 0,
+    pageSize: 200,
+  });
+  orders.value = res.data.records;
+  if (orders.value.length > 0) {
+    // selectOrderCode.value = orders.value[0].orderCode;
+    // selectedOrder.value = orders.value[0];
+  }
+};
+const orderSelect = (value) => {
+  selectedOrder.value = value;
+  seqList.value = selectedOrder.value.seqs.map((item, index) => ({ value: item, label: item }));
+  saleForm.seqs = [];
+};
+
+const seqList = ref([]);
+
+// 用户信息
+const userInfo = ref({});
+const userList = ref([]);
+const getUserInfo = async () => {
+  //const res = await getUserList();
+  //userList.value = res.data;
+  // if (userList.value.length > 0) {
+  //   userInfo.value = userList.value[0];
+  // }
+  getUserTree().then((data) => {
+    userList.value = data.data;
+  });
+};
+
+const showDrawer = () => {
+  selectedOrder.value = {};
+  selectOrderCode.value = {};
+  getOrders();
+  getUserInfo();
+  drawerVisible.value = true;
+};
+
+defineExpose({ showDrawer });
+
+const cancelClick = () => {
+  drawerVisible.value = false;
+  baseInfoRef.value.resetFields();
+  remark1Ref.value.resetFields();
+  selectedOrder.value = {};
+};
+
+const feedBackEmit = defineEmits(["finish"]);
+
+const confirmClick = () => {
+  console.log(saleForm);
+  console.log(remark1);
+  console.log(selectedOrder.value);
+
+  // drawerVisible.value = false;
+
+  //
+  // // 验证表单
+  baseInfoRef.value.validate((valid) => {
+    if (valid) {
+      console.log("baseInfoRef valid");
+    } else {
+      console.log("baseInfoRef invalid");
+      return false;
+    }
+  });
+  remark1Ref.value.validate((valid) => {
+    if (valid) {
+      let remark1Copy = {
+        content: remark1.content,
+        user: remark1.user,
+        user1: remark1.user1,
+        time: remark1.time,
+      };
+      let remark2 = {
+        content: "",
+        user2: remark1.nextRemarkUser,
+        time: "",
+      };
+
+      let p = {
+        ...saleForm,
+        ...selectedOrder.value,
+        currentUserName: remark1.nextRemarkUser,
+        remark1: JSON.stringify(remark1Copy),
+        remark2: JSON.stringify(remark2),
+      };
+
+      p.seqs = saleForm.seqs.join(",");
+
+      addFeedback(p).then(() => {
+        feedBackEmit("finish");
+        cancelClick();
+      });
+    } else {
+      console.log("remark1Ref invalid");
+      return false;
+    }
+  });
+};
+</script>
+
+<style scoped lang="scss">
+.drawer-bottom {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+}
+</style>

+ 39 - 0
src/views/unqualified/detail.vue

@@ -0,0 +1,39 @@
+<template>
+  <el-drawer v-model="drawerVisible" size="1000">
+    <template #header>
+      <div><el-button type="primary" v-print="'#print'">打印</el-button></div>
+    </template>
+
+    <div id="print">
+      <DetailCom ref="detailComRef"></DetailCom>
+    </div>
+  </el-drawer>
+</template>
+
+<script setup>
+import DetailCom from "@/views/unqualified/DetailCom.vue";
+
+const drawerVisible = ref(false);
+const detailComRef = ref(null);
+
+const showDrawer = (row) => {
+  drawerVisible.value = true;
+
+  nextTick(() => {
+    detailComRef.value && detailComRef.value.refreshView(row);
+  });
+};
+
+defineExpose({ showDrawer });
+</script>
+
+<style scoped lang="scss">
+@media print {
+  #print {
+    position: absolute; /* 或 absolute, fixed, 根据需要调整 */
+    top: 20px; /* 调整顶部位置 */
+    margin: 0; /* 重置边距 */
+    width: 1000px;
+  }
+}
+</style>

+ 266 - 0
src/views/unqualified/handle20.vue

@@ -0,0 +1,266 @@
+<template>
+  <el-drawer v-model="drawerVisible" size="1000">
+    <div>
+      <DetailCom ref="detailComRef"></DetailCom>
+    </div>
+
+    <el-form
+        ref="remarkRef"
+        :model="remark"
+        label-width="150"
+        :rules="rules1"
+        style="max-width: 600px; margin-left: 80px; margin-top: 20px"
+    >
+      <el-form-item label="分析处置要求:" prop="content2">
+        <el-input
+            v-model="remark.content2"
+            type="textarea"
+            :autosize="{ minRows: 3, maxRows: 6 }"
+        />
+      </el-form-item>
+      <el-form-item label="技术人员" prop="user1">
+        <el-tree-select
+            v-model="remark.user1"
+            :data="userList"
+            filterable
+        />
+      </el-form-item>
+      <el-form-item label="联系电话" prop="phone">
+        <el-input v-model="remark.phone" />
+      </el-form-item>
+      <el-form-item label="责任部门" prop="user2">
+        <el-tree-select
+            v-model="remark.user2"
+            :data="userList"
+            filterable
+        />
+      </el-form-item>
+      <el-form-item label="原因分析:" prop="content3">
+        <el-input
+            v-model="remark.content3"
+            type="textarea"
+            :autosize="{ minRows: 3, maxRows: 6 }"
+        />
+      </el-form-item>
+      <el-form-item label="分析单位:" prop="company">
+        <el-input v-model="remark.company" />
+      </el-form-item>
+      <el-form-item label="采取的措施:" prop="content4">
+        <el-input
+            v-model="remark.content4"
+            type="textarea"
+            :autosize="{ minRows: 3, maxRows: 6 }"
+        />
+      </el-form-item>
+      <el-form-item label="责任部门" prop="users">
+        <el-tree-select
+            v-model="remark.users"
+            :data="userList"
+            multiple
+            filterable
+        />
+      </el-form-item>
+
+      <el-form-item label="措施落实:" prop="content5">
+        <el-input
+            v-model="remark.content5"
+            type="textarea"
+            :autosize="{ minRows: 3, maxRows: 6 }"
+        />
+      </el-form-item>
+      <el-form-item label="责任部门" prop="user5">
+        <el-tree-select
+            v-model="remark.user5"
+            :data="userList"
+            filterable
+        />
+      </el-form-item>
+
+
+      <el-form-item label="下一步处理人" prop="nextRemarkUser" v-if="remark.state == 0">
+        <el-tree-select
+            v-model="remark.nextRemarkUser"
+            :data="userList"
+            filterable
+        />
+      </el-form-item>
+      <el-form-item label="是否通过" prop="state">
+        <el-radio-group v-model="remark.state">
+          <el-radio :value="0">同意</el-radio>
+          <el-radio :value="1">不同意</el-radio>
+        </el-radio-group>
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <div class="drawer-bottom">
+        <el-button @click="cancelClick">取消</el-button>
+        <el-button type="primary" @click="confirmClick">提交</el-button>
+      </div>
+    </template>
+  </el-drawer>
+</template>
+
+<script setup>
+import DetailCom from "@/views/unqualified/DetailCom.vue";
+import { dealFeedback } from "@/api/unqualified/index";
+import { getUserTree } from "@/api/user/index";
+import {useUserStore} from "@/store";
+const drawerVisible = ref(false);
+const detailComRef = ref(null);
+const saleModel = ref({});
+const userStore = useUserStore();
+const showDrawer = (row) => {
+  drawerVisible.value = true;
+  saleModel.value = row;
+
+  nextTick(() => {
+    detailComRef.value && detailComRef.value.refreshView(row);
+  });
+
+  getUserInfo();
+};
+const disabledDate = (time)=> {
+  //选择今天以及今天之后的日期
+  return time.getTime() < Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择
+  //选择今天以及今天之前的日期
+  //return time.getTime() > Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择今天的
+}
+const rules1 = {
+  content2: [
+    { required: true, message: "请输入分析处置要求", trigger: "blur" },
+    { min: 2, max: 200, message: "长度在 2 到 200 个字符", trigger: "blur" },
+  ],
+  content3: [
+    { required: true, message: "请输入原因分析", trigger: "blur" },
+    { min: 2, max: 200, message: "长度在 2 到 200 个字符", trigger: "blur" },
+  ],
+  content4: [
+    { required: true, message: "请输入采取的措施", trigger: "blur" },
+    { min: 2, max: 200, message: "长度在 2 到 200 个字符", trigger: "blur" },
+  ],
+  content5: [
+    { required: true, message: "请输入措施落实", trigger: "blur" },
+    { min: 2, max: 200, message: "长度在 2 到 200 个字符", trigger: "blur" },
+  ],
+  users: [
+    { required: true, message: "请选择人员", trigger: "blur" },
+  ],
+  user1: [
+    { required: true, message: "请选择人员", trigger: "blur" },
+  ],
+  user2: [
+    { required: true, message: "请选择人员", trigger: "blur" },
+  ],
+  user5: [
+    { required: true, message: "请选择人员", trigger: "blur" },
+  ],
+  phone: [
+    { required: true, message: "请输入电话", trigger: "blur" },
+    { min: 11, max: 11, message: "长度在11个字符", trigger: "blur" },
+  ],
+  company: [{ required: true, message: "请输入分析单位", trigger: "change" }],
+  nextRemarkUser: [
+    { required: true, message: "请选择处理人", trigger: "change" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+};
+
+defineExpose({ showDrawer });
+
+const remarkRef = ref(null);
+
+const remark = reactive({
+  content: "",
+  user: "",
+  time: "",
+  nextRemarkUser: "",
+  state: 0,
+});
+
+const cancelClick = () => {
+  drawerVisible.value = false;
+
+  remarkRef.value.resetFields();
+};
+
+const feedBackEmit = defineEmits(["finish"]);
+
+// 用户信息
+const userInfo = ref({});
+const userList = ref([]);
+const getUserInfo = async () => {
+  getUserTree().then((data) => {
+    userList.value = data.data;
+  });
+};
+
+const confirmClick = () => {
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
+  remark.user = userStore.user.username;
+  remarkRef.value.validate((valid) => {
+    if (valid) {
+      let remark2Copy = {
+        content: remark.content2,
+        user: remark.user,
+        time: now,
+        user1: remark.user1,
+        user2: remark.user2,
+        phone: remark.phone,
+        state: remark.state,
+      };
+      let remark3 = {
+        content: remark.content3,
+        company: remark.company,
+        time: now,
+      };
+      let remark4 = {
+        content: remark.content4,
+        users: remark.users.join(","),
+        time: now,
+      };
+      let remark5 = {
+        content: remark.content5,
+        user: remark.user5,
+        time: now,
+      };
+      let remark6 = {
+        content: '',
+        user: remark.nextRemarkUser,
+      };
+
+      let p = {
+        id: saleModel.value.id,
+        remark2: JSON.stringify(remark2Copy),
+        remark3: JSON.stringify(remark3),
+        remark4: JSON.stringify(remark4),
+        remark5: JSON.stringify(remark5),
+        currentUserName: remark.nextRemarkUser,
+        remark6: JSON.stringify(remark6),
+        state: remark.state,
+        step: 1, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
+      };
+
+      dealFeedback(p).then(() => {
+        feedBackEmit("finish");
+        cancelClick();
+      });
+    } else {
+      console.log("remarkRef invalid");
+      return false;
+    }
+  });
+};
+</script>
+
+<style scoped lang="scss">
+@media print {
+  #print {
+    position: absolute; /* 或 absolute, fixed, 根据需要调整 */
+    top: 20px; /* 调整顶部位置 */
+    margin: 0; /* 重置边距 */
+    width: 1000px;
+  }
+}
+</style>

+ 187 - 0
src/views/unqualified/handle21.vue

@@ -0,0 +1,187 @@
+<template>
+  <el-drawer v-model="drawerVisible" size="1000">
+    <div>
+      <DetailCom ref="detailComRef"></DetailCom>
+    </div>
+
+    <el-form
+        ref="remarkRef"
+        :model="remark"
+        label-width="150"
+        :rules="rules1"
+        style="max-width: 600px; margin-left: 80px; margin-top: 20px"
+    >
+      <el-form-item label="分析处置要求" prop="content">
+        <el-input
+            v-model="remark.content"
+            type="textarea"
+            :autosize="{ minRows: 3, maxRows: 6 }"
+        />
+      </el-form-item>
+      <el-form-item label="技术人员" prop="user1">
+        <el-tree-select
+            v-model="remark.user1"
+            :data="userList"
+            filterable
+        />
+      </el-form-item>
+      <el-form-item label="联系电话" prop="phone">
+        <el-input v-model="remark.phone" />
+      </el-form-item>
+      <el-form-item label="责任部门" prop="user2">
+        <el-tree-select
+            v-model="remark.user2"
+            :data="userList"
+            filterable
+        />
+      </el-form-item>
+
+      <el-form-item label="下一步处理人" prop="nextRemarkUser" v-if="remark.state == 0">
+        <el-tree-select
+            v-model="remark.nextRemarkUser"
+            :data="userList"
+            filterable
+        />
+      </el-form-item>
+      <el-form-item label="是否通过" prop="state">
+        <el-radio-group v-model="remark.state">
+          <el-radio :value="0">同意</el-radio>
+          <el-radio :value="1">不同意</el-radio>
+        </el-radio-group>
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <div class="drawer-bottom">
+        <el-button @click="cancelClick">取消</el-button>
+        <el-button type="primary" @click="confirmClick">提交</el-button>
+      </div>
+    </template>
+  </el-drawer>
+</template>
+
+<script setup>
+import DetailCom from "@/views/unqualified/DetailCom.vue";
+import { dealFeedback} from "@/api/unqualified/index";
+import { getUserTree } from "@/api/user/index";
+import {useUserStore} from "@/store";
+const drawerVisible = ref(false);
+const detailComRef = ref(null);
+const saleModel = ref({});
+const userStore = useUserStore();
+const disabledDate = (time)=> {
+  //选择今天以及今天之后的日期
+  return time.getTime() < Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择
+  //选择今天以及今天之前的日期
+  //return time.getTime() > Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择今天的
+}
+const showDrawer = (row) => {
+  drawerVisible.value = true;
+  saleModel.value = row;
+
+  nextTick(() => {
+    detailComRef.value && detailComRef.value.refreshView(row);
+  });
+
+  getUserInfo();
+};
+
+const rules1 = {
+  content: [
+    { required: true, message: "请输入投诉或建议处置意见", trigger: "blur" },
+    { min: 2, max: 200, message: "长度在 2 到 200 个字符", trigger: "blur" },
+  ],
+  user1: [
+    { required: true, message: "请输入姓名", trigger: "blur" },
+  ],
+  user2: [
+    { required: true, message: "请输入姓名", trigger: "blur" },
+  ],
+
+  phone: [{ required: true, message: "请输入联系电话", trigger: "change" }],
+  nextRemarkUser: [
+    { required: true, message: "请选择处理人", trigger: "change" },
+  ],
+};
+
+defineExpose({ showDrawer });
+
+const remarkRef = ref(null);
+
+const remark = reactive({
+  content: "",
+  user: "",
+  time: "",
+  nextRemarkUser: "",
+  state: 0,
+});
+
+const cancelClick = () => {
+  drawerVisible.value = false;
+
+  remarkRef.value.resetFields();
+};
+
+const feedBackEmit = defineEmits(["finish"]);
+
+// 用户信息
+const userInfo = ref({});
+const userList = ref([]);
+const getUserInfo = async () => {
+  getUserTree().then((data) => {
+    userList.value = data.data;
+  });
+};
+
+const confirmClick = () => {
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
+  remark.user = userStore.user.username;
+  remarkRef.value.validate((valid) => {
+    if (valid) {
+      let remark2Copy = {
+        content: remark.content,
+        user: remark.user,
+        user1: remark.user1,
+        user2: remark.user2,
+        phone: remark.phone,
+        time: now,
+        state: remark.state,
+      };
+      let remark3 = {
+        content: "",
+        user: remark.nextRemarkUser, // qinhaibo和dengyu说是user1234的
+        time: "",
+      };
+
+      let p = {
+        id: saleModel.value.id,
+        remark2: JSON.stringify(remark2Copy),
+        remark3: JSON.stringify(remark3),
+        currentUserName: remark.nextRemarkUser,
+        state: remark.state,
+        step: 3, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
+      };
+
+      dealFeedback(p).then(() => {
+        feedBackEmit("finish");
+        cancelClick();
+      });
+    } else {
+      console.log("remarkRef invalid");
+      return false;
+    }
+  });
+};
+</script>
+
+<style scoped lang="scss">
+@media print {
+  #print {
+    position: absolute; /* 或 absolute, fixed, 根据需要调整 */
+    top: 20px; /* 调整顶部位置 */
+    margin: 0; /* 重置边距 */
+    width: 1000px;
+  }
+}
+</style>

+ 171 - 0
src/views/unqualified/handle3.vue

@@ -0,0 +1,171 @@
+<template>
+  <el-drawer v-model="drawerVisible" size="1000">
+    <div>
+      <DetailCom ref="detailComRef"></DetailCom>
+    </div>
+
+    <el-form
+      ref="remarkRef"
+      :model="remark"
+      label-width="150"
+      :rules="rules1"
+      style="max-width: 600px; margin-left: 80px; margin-top: 20px"
+    >
+      <el-form-item label="原因分析" prop="content">
+        <el-input
+          v-model="remark.content"
+          type="textarea"
+          :autosize="{ minRows: 3, maxRows: 6 }"
+        />
+      </el-form-item>
+
+      <el-form-item label="分析单位" prop="company">
+        <el-input
+            v-model="remark.company"
+        />
+      </el-form-item>
+      <el-form-item label="下一步处理人" prop="nextRemarkUser" v-if="remark.state == 0">
+        <el-tree-select
+            v-model="remark.nextRemarkUser"
+            :data="userList"
+            filterable
+        />
+      </el-form-item>
+      <el-form-item label="是否通过" prop="state">
+        <el-radio-group v-model="remark.state">
+          <el-radio :value="0">同意</el-radio>
+          <el-radio :value="1">不同意</el-radio>
+        </el-radio-group>
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <div class="drawer-bottom">
+        <el-button @click="cancelClick">取消</el-button>
+        <el-button type="primary" @click="confirmClick">提交</el-button>
+      </div>
+    </template>
+  </el-drawer>
+</template>
+
+<script setup>
+import DetailCom from "@/views/unqualified/DetailCom.vue";
+import { dealFeedback} from "@/api/unqualified/index";
+import { getUserTree } from "@/api/user/index";
+import {useUserStore} from "@/store";
+const drawerVisible = ref(false);
+const detailComRef = ref(null);
+const saleModel = ref({});
+const userStore = useUserStore();
+const disabledDate = (time)=> {
+  //选择今天以及今天之后的日期
+  return time.getTime() < Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择
+  //选择今天以及今天之前的日期
+  //return time.getTime() > Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择今天的
+}
+const showDrawer = (row) => {
+  drawerVisible.value = true;
+  saleModel.value = row;
+
+  nextTick(() => {
+    detailComRef.value && detailComRef.value.refreshView(row);
+  });
+
+  getUserInfo();
+};
+
+const rules1 = {
+  content: [
+    { required: true, message: "请输入投诉或建议处置意见", trigger: "blur" },
+    { min: 2, max: 200, message: "长度在 2 到 200 个字符", trigger: "blur" },
+  ],
+  user: [
+    { required: true, message: "请输入姓名", trigger: "blur" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+  company: [{ required: true, message: "请输入分析单位", trigger: "change" }],
+  nextRemarkUser: [
+    { required: true, message: "请选择处理人", trigger: "change" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+};
+
+defineExpose({ showDrawer });
+
+const remarkRef = ref(null);
+
+const remark = reactive({
+  content: "",
+  user: "",
+  time: "",
+  nextRemarkUser: "",
+  state: 0,
+});
+
+const cancelClick = () => {
+  drawerVisible.value = false;
+
+  remarkRef.value.resetFields();
+};
+
+const feedBackEmit = defineEmits(["finish"]);
+
+// 用户信息
+const userInfo = ref({});
+const userList = ref([]);
+const getUserInfo = async () => {
+  getUserTree().then((data) => {
+    userList.value = data.data;
+  });
+};
+
+const confirmClick = () => {
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
+  remark.user = userStore.user.username;
+  remarkRef.value.validate((valid) => {
+    if (valid) {
+      let remark2Copy = {
+        content: remark.content,
+        user: remark.user,
+        time: now,
+        company: remark.company,
+        state: remark.state,
+      };
+      let remark3 = {
+        content: "",
+        user: remark.nextRemarkUser, // qinhaibo和dengyu说是user1234的
+        time: "",
+      };
+
+      let p = {
+        id: saleModel.value.id,
+        remark3: JSON.stringify(remark2Copy),
+        remark4: JSON.stringify(remark3),
+        currentUserName: remark.nextRemarkUser,
+        state: remark.state,
+        step: 3, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
+      };
+
+      dealFeedback(p).then(() => {
+        feedBackEmit("finish");
+        cancelClick();
+      });
+    } else {
+      console.log("remarkRef invalid");
+      return false;
+    }
+  });
+};
+</script>
+
+<style scoped lang="scss">
+@media print {
+  #print {
+    position: absolute; /* 或 absolute, fixed, 根据需要调整 */
+    top: 20px; /* 调整顶部位置 */
+    margin: 0; /* 重置边距 */
+    width: 1000px;
+  }
+}
+</style>

+ 172 - 0
src/views/unqualified/handle4.vue

@@ -0,0 +1,172 @@
+<template>
+  <el-drawer v-model="drawerVisible" size="1000">
+    <div>
+      <DetailCom ref="detailComRef"></DetailCom>
+    </div>
+
+    <el-form
+        ref="remarkRef"
+        :model="remark"
+        label-width="150"
+        :rules="rules1"
+        style="max-width: 600px; margin-left: 80px; margin-top: 20px"
+    >
+      <el-form-item label="采取的措施" prop="content">
+        <el-input
+            v-model="remark.content"
+            type="textarea"
+            :autosize="{ minRows: 3, maxRows: 6 }"
+        />
+      </el-form-item>
+
+<!--      <el-form-item label="责任部门" prop="user">
+        <el-tree-select
+            v-model="remark.user"
+            :data="userList"
+            filterable
+        />
+      </el-form-item>-->
+      <el-form-item label="下一步处理人" prop="nextRemarkUser" v-if="remark.state == 0">
+        <el-tree-select
+            v-model="remark.nextRemarkUser"
+            :data="userList"
+            filterable
+        />
+      </el-form-item>
+      <el-form-item label="是否通过" prop="state">
+        <el-radio-group v-model="remark.state">
+          <el-radio :value="0">同意</el-radio>
+          <el-radio :value="1">不同意</el-radio>
+        </el-radio-group>
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <div class="drawer-bottom">
+        <el-button @click="cancelClick">取消</el-button>
+        <el-button type="primary" @click="confirmClick">提交</el-button>
+      </div>
+    </template>
+  </el-drawer>
+</template>
+
+<script setup>
+import DetailCom from "@/views/unqualified/DetailCom.vue";
+import { dealFeedback} from "@/api/unqualified/index";
+import { getUserTree } from "@/api/user/index";
+import {useUserStore} from "@/store";
+const drawerVisible = ref(false);
+const detailComRef = ref(null);
+const saleModel = ref({});
+const userStore = useUserStore();
+const disabledDate = (time)=> {
+  //选择今天以及今天之后的日期
+  return time.getTime() < Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择
+  //选择今天以及今天之前的日期
+  //return time.getTime() > Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择今天的
+}
+const showDrawer = (row) => {
+  drawerVisible.value = true;
+  saleModel.value = row;
+
+  nextTick(() => {
+    detailComRef.value && detailComRef.value.refreshView(row);
+  });
+
+  getUserInfo();
+};
+
+const rules1 = {
+  content: [
+    { required: true, message: "请输入投诉或建议处置意见", trigger: "blur" },
+    { min: 2, max: 200, message: "长度在 2 到 200 个字符", trigger: "blur" },
+  ],
+  user: [
+    { required: true, message: "请输入姓名", trigger: "blur" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+  time: [{ required: true, message: "请选择日期", trigger: "change" }],
+  nextRemarkUser: [
+    { required: true, message: "请选择处理人", trigger: "change" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+};
+
+defineExpose({ showDrawer });
+
+const remarkRef = ref(null);
+
+const remark = reactive({
+  content: "",
+  user: "",
+  time: "",
+  nextRemarkUser: "",
+  state: 0,
+});
+
+const cancelClick = () => {
+  drawerVisible.value = false;
+
+  remarkRef.value.resetFields();
+};
+
+const feedBackEmit = defineEmits(["finish"]);
+
+// 用户信息
+const userInfo = ref({});
+const userList = ref([]);
+const getUserInfo = async () => {
+  getUserTree().then((data) => {
+    userList.value = data.data;
+  });
+};
+
+const confirmClick = () => {
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
+  remark.user = userStore.user.username;
+  remarkRef.value.validate((valid) => {
+    if (valid) {
+      let remark2Copy = {
+        content: remark.content,
+        user: remark.user,
+        time: now,
+        state: remark.state,
+      };
+      let remark3 = {
+        content: "",
+        user: remark.nextRemarkUser, // qinhaibo和dengyu说是user1234的
+        time: "",
+      };
+
+      let p = {
+        id: saleModel.value.id,
+        remark4: JSON.stringify(remark2Copy),
+        remark5: JSON.stringify(remark3),
+        currentUserName: remark.nextRemarkUser,
+        state: remark.state,
+        step: 4, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
+      };
+
+      dealFeedback(p).then(() => {
+        feedBackEmit("finish");
+        cancelClick();
+      });
+    } else {
+      console.log("remarkRef invalid");
+      return false;
+    }
+  });
+};
+</script>
+
+<style scoped lang="scss">
+@media print {
+  #print {
+    position: absolute; /* 或 absolute, fixed, 根据需要调整 */
+    top: 20px; /* 调整顶部位置 */
+    margin: 0; /* 重置边距 */
+    width: 1000px;
+  }
+}
+</style>

+ 172 - 0
src/views/unqualified/handle5.vue

@@ -0,0 +1,172 @@
+<template>
+  <el-drawer v-model="drawerVisible" size="1000">
+    <div>
+      <DetailCom ref="detailComRef"></DetailCom>
+    </div>
+
+    <el-form
+        ref="remarkRef"
+        :model="remark"
+        label-width="150"
+        :rules="rules1"
+        style="max-width: 600px; margin-left: 80px; margin-top: 20px"
+    >
+      <el-form-item label="措施落实" prop="content">
+        <el-input
+            v-model="remark.content"
+            type="textarea"
+            :autosize="{ minRows: 3, maxRows: 6 }"
+        />
+      </el-form-item>
+
+      <!--      <el-form-item label="责任部门" prop="user">
+              <el-tree-select
+                  v-model="remark.user"
+                  :data="userList"
+                  filterable
+              />
+            </el-form-item>-->
+      <el-form-item label="下一步处理人" prop="nextRemarkUser" v-if="remark.state == 0">
+        <el-tree-select
+            v-model="remark.nextRemarkUser"
+            :data="userList"
+            filterable
+        />
+      </el-form-item>
+      <el-form-item label="是否通过" prop="state">
+        <el-radio-group v-model="remark.state">
+          <el-radio :value="0">同意</el-radio>
+          <el-radio :value="1">不同意</el-radio>
+        </el-radio-group>
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <div class="drawer-bottom">
+        <el-button @click="cancelClick">取消</el-button>
+        <el-button type="primary" @click="confirmClick">提交</el-button>
+      </div>
+    </template>
+  </el-drawer>
+</template>
+
+<script setup>
+import DetailCom from "@/views/unqualified/DetailCom.vue";
+import { dealFeedback} from "@/api/unqualified/index";
+import { getUserTree } from "@/api/user/index";
+import {useUserStore} from "@/store";
+const drawerVisible = ref(false);
+const detailComRef = ref(null);
+const saleModel = ref({});
+const userStore = useUserStore();
+const disabledDate = (time)=> {
+  //选择今天以及今天之后的日期
+  return time.getTime() < Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择
+  //选择今天以及今天之前的日期
+  //return time.getTime() > Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择今天的
+}
+const showDrawer = (row) => {
+  drawerVisible.value = true;
+  saleModel.value = row;
+
+  nextTick(() => {
+    detailComRef.value && detailComRef.value.refreshView(row);
+  });
+
+  getUserInfo();
+};
+
+const rules1 = {
+  content: [
+    { required: true, message: "请输入投诉或建议处置意见", trigger: "blur" },
+    { min: 2, max: 200, message: "长度在 2 到 200 个字符", trigger: "blur" },
+  ],
+  user: [
+    { required: true, message: "请输入姓名", trigger: "blur" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+  time: [{ required: true, message: "请选择日期", trigger: "change" }],
+  nextRemarkUser: [
+    { required: true, message: "请选择处理人", trigger: "change" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+};
+
+defineExpose({ showDrawer });
+
+const remarkRef = ref(null);
+
+const remark = reactive({
+  content: "",
+  user: "",
+  time: "",
+  nextRemarkUser: "",
+  state: 0,
+});
+
+const cancelClick = () => {
+  drawerVisible.value = false;
+
+  remarkRef.value.resetFields();
+};
+
+const feedBackEmit = defineEmits(["finish"]);
+
+// 用户信息
+const userInfo = ref({});
+const userList = ref([]);
+const getUserInfo = async () => {
+  getUserTree().then((data) => {
+    userList.value = data.data;
+  });
+};
+
+const confirmClick = () => {
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
+  remark.user = userStore.user.username;
+  remarkRef.value.validate((valid) => {
+    if (valid) {
+      let remark2Copy = {
+        content: remark.content,
+        user: remark.user,
+        time: now,
+        state: remark.state,
+      };
+      let remark3 = {
+        content: "",
+        user: remark.nextRemarkUser, // qinhaibo和dengyu说是user1234的
+        time: "",
+      };
+
+      let p = {
+        id: saleModel.value.id,
+        remark4: JSON.stringify(remark2Copy),
+        remark5: JSON.stringify(remark3),
+        state: remark.state,
+        currentUserName: remark.nextRemarkUser,
+        step: 5, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
+      };
+
+      dealFeedback(p).then(() => {
+        feedBackEmit("finish");
+        cancelClick();
+      });
+    } else {
+      console.log("remarkRef invalid");
+      return false;
+    }
+  });
+};
+</script>
+
+<style scoped lang="scss">
+@media print {
+  #print {
+    position: absolute; /* 或 absolute, fixed, 根据需要调整 */
+    top: 20px; /* 调整顶部位置 */
+    margin: 0; /* 重置边距 */
+    width: 1000px;
+  }
+}
+</style>

+ 165 - 0
src/views/unqualified/handle6.vue

@@ -0,0 +1,165 @@
+<template>
+  <el-drawer v-model="drawerVisible" size="1000">
+    <div>
+      <DetailCom ref="detailComRef"></DetailCom>
+    </div>
+
+    <el-form
+        ref="remarkRef"
+        :model="remark"
+        label-width="150"
+        :rules="rules1"
+        style="max-width: 600px; margin-left: 80px; margin-top: 20px"
+    >
+      <el-form-item label="不合格品评审(审理)处置意见" prop="content">
+        <el-input
+            v-model="remark.content"
+            type="textarea"
+            :autosize="{ minRows: 3, maxRows: 6 }"
+        />
+      </el-form-item>
+
+      <el-form-item label="下一步处理人" prop="nextRemarkUser" v-if="remark.state == 0">
+        <el-tree-select
+            v-model="remark.nextRemarkUser"
+            :data="userList"
+            filterable
+        />
+      </el-form-item>
+      <el-form-item label="是否通过" prop="state">
+        <el-radio-group v-model="remark.state">
+          <el-radio :value="0">同意</el-radio>
+          <el-radio :value="1">不同意</el-radio>
+        </el-radio-group>
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <div class="drawer-bottom">
+        <el-button @click="cancelClick">取消</el-button>
+        <el-button type="primary" @click="confirmClick">提交</el-button>
+      </div>
+    </template>
+  </el-drawer>
+</template>
+
+<script setup>
+import DetailCom from "@/views/unqualified/DetailCom.vue";
+import { dealFeedback } from "@/api/unqualified/index";
+import { getUserTree } from "@/api/user/index";
+import {useUserStore} from "@/store";
+const drawerVisible = ref(false);
+const detailComRef = ref(null);
+const saleModel = ref({});
+const userStore = useUserStore();
+const disabledDate = (time)=> {
+  //选择今天以及今天之后的日期
+  return time.getTime() < Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择
+  //选择今天以及今天之前的日期
+  //return time.getTime() > Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择今天的
+}
+const showDrawer = (row) => {
+  drawerVisible.value = true;
+  saleModel.value = row;
+
+  nextTick(() => {
+    detailComRef.value && detailComRef.value.refreshView(row);
+  });
+
+  getUserInfo();
+};
+
+const rules1 = {
+  content: [
+    { required: true, message: "请输入投诉或建议处置意见", trigger: "blur" },
+    { min: 2, max: 200, message: "长度在 2 到 200 个字符", trigger: "blur" },
+  ],
+  user: [
+    { required: true, message: "请输入姓名", trigger: "blur" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+  time: [{ required: true, message: "请选择日期", trigger: "change" }],
+  nextRemarkUser: [
+    { required: true, message: "请选择处理人", trigger: "change" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+};
+
+defineExpose({ showDrawer });
+
+const remarkRef = ref(null);
+
+const remark = reactive({
+  content: "",
+  user: "",
+  time: "",
+  nextRemarkUser: "",
+  state: 0,
+});
+
+const cancelClick = () => {
+  drawerVisible.value = false;
+
+  remarkRef.value.resetFields();
+};
+
+const feedBackEmit = defineEmits(["finish"]);
+
+// 用户信息
+const userInfo = ref({});
+const userList = ref([]);
+const getUserInfo = async () => {
+  getUserTree().then((data) => {
+    userList.value = data.data;
+  });
+};
+
+const confirmClick = () => {
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
+  remark.user = userStore.user.username;
+  remarkRef.value.validate((valid) => {
+    if (valid) {
+      let remark2Copy = {
+        content: remark.content,
+        user: remark.user,
+        time: now,
+        state: remark.state,
+      };
+      let remark3 = {
+        content: "",
+        user: remark.nextRemarkUser, // qinhaibo和dengyu说是user1234的
+        time: "",
+      };
+
+      let p = {
+        id: saleModel.value.id,
+        remark6: JSON.stringify(remark2Copy),
+        remark7: JSON.stringify(remark3),
+        state: remark.state,
+        currentUserName: remark.nextRemarkUser,
+        step: 6, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
+      };
+
+      dealFeedback(p).then(() => {
+        feedBackEmit("finish");
+        cancelClick();
+      });
+    } else {
+      console.log("remarkRef invalid");
+      return false;
+    }
+  });
+};
+</script>
+
+<style scoped lang="scss">
+@media print {
+  #print {
+    position: absolute; /* 或 absolute, fixed, 根据需要调整 */
+    top: 20px; /* 调整顶部位置 */
+    margin: 0; /* 重置边距 */
+    width: 1000px;
+  }
+}
+</style>

+ 168 - 0
src/views/unqualified/handle7.vue

@@ -0,0 +1,168 @@
+<template>
+  <el-drawer v-model="drawerVisible" size="1000">
+    <div>
+      <DetailCom ref="detailComRef"></DetailCom>
+    </div>
+
+    <el-form
+        ref="remarkRef"
+        :model="remark"
+        label-width="150"
+        :rules="rules1"
+        style="max-width: 600px; margin-left: 80px; margin-top: 20px"
+    >
+      <el-form-item label="组长(或分管领导)审批意见" prop="content">
+        <el-input
+            v-model="remark.content"
+            type="textarea"
+            :autosize="{ minRows: 3, maxRows: 6 }"
+        />
+      </el-form-item>
+<!--      <el-form-item label="日期" prop="time">
+        <el-date-picker
+            v-model="remark.time"
+            type="date"
+            placeholder="请选择日期"
+            clearable
+            :disabled-date="disabledDate"
+            format="YYYY年MM月DD日"
+            value-format="YYYY年MM月DD日"
+            style="width: 100%"
+        />
+      </el-form-item>-->
+      <el-form-item label="是否通过" prop="state">
+        <el-radio-group v-model="remark.state">
+          <el-radio :value="0">同意</el-radio>
+          <el-radio :value="1">不同意</el-radio>
+        </el-radio-group>
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <div class="drawer-bottom">
+        <el-button @click="cancelClick">取消</el-button>
+        <el-button type="primary" @click="confirmClick">提交</el-button>
+      </div>
+    </template>
+  </el-drawer>
+</template>
+
+<script setup>
+import DetailCom from "@/views/unqualified/DetailCom.vue";
+import { dealFeedback } from "@/api/unqualified/index";
+import { getUserTree } from "@/api/user/index";
+import {useUserStore} from "@/store";
+const drawerVisible = ref(false);
+const detailComRef = ref(null);
+const saleModel = ref({});
+const userStore = useUserStore();
+const disabledDate = (time)=> {
+  //选择今天以及今天之后的日期
+  return time.getTime() < Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择
+  //选择今天以及今天之前的日期
+  //return time.getTime() > Date.now() - 8.64e7;//如果没有后面的-8.64e7就是不可以选择今天的
+}
+const showDrawer = (row) => {
+  drawerVisible.value = true;
+  saleModel.value = row;
+
+  nextTick(() => {
+    detailComRef.value && detailComRef.value.refreshView(row);
+  });
+
+  getUserInfo();
+};
+
+const rules1 = {
+  content: [
+    { required: true, message: "请输入投诉或建议处置意见", trigger: "blur" },
+    { min: 2, max: 200, message: "长度在 2 到 200 个字符", trigger: "blur" },
+  ],
+  user: [
+    { required: true, message: "请输入姓名", trigger: "blur" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+  time: [{ required: true, message: "请选择日期", trigger: "change" }],
+  nextRemarkUser: [
+    { required: true, message: "请选择处理人", trigger: "change" },
+    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
+  ],
+};
+
+defineExpose({ showDrawer });
+
+const remarkRef = ref(null);
+
+const remark = reactive({
+  content: "",
+  user: "",
+  time: "",
+  nextRemarkUser: "",
+  state: 0,
+});
+
+const cancelClick = () => {
+  drawerVisible.value = false;
+
+  remarkRef.value.resetFields();
+};
+
+const feedBackEmit = defineEmits(["finish"]);
+
+// 用户信息
+const userInfo = ref({});
+const userList = ref([]);
+const getUserInfo = async () => {
+  getUserTree().then((data) => {
+    userList.value = data.data;
+  });
+};
+
+const confirmClick = () => {
+  const date = new Date();
+  const now = date.getFullYear() + "年" + date.getMonth() + "月" + date.getDate() + "日"
+  remark.user = userStore.user.username;
+  remarkRef.value.validate((valid) => {
+    if (valid) {
+      let remark2Copy = {
+        content: remark.content,
+        user: remark.user,
+        time: now,
+        state: remark.state,
+      };
+      let remark3 = {
+        content: "",
+        user: remark.nextRemarkUser, // qinhaibo和dengyu说是user1234的
+        time: "",
+      };
+
+      let p = {
+        id: saleModel.value.id,
+        remark7: JSON.stringify(remark2Copy),
+        state: remark.state,
+        currentUserName: remark.nextRemarkUser,
+        step: 7, //步骤 1 投书或建议处置意见 2 整改及纠正措施验证 3 处置情况的反馈意见
+      };
+
+      dealFeedback(p).then(() => {
+        feedBackEmit("finish");
+        cancelClick();
+      });
+    } else {
+      console.log("remarkRef invalid");
+      return false;
+    }
+  });
+};
+</script>
+
+<style scoped lang="scss">
+@media print {
+  #print {
+    position: absolute; /* 或 absolute, fixed, 根据需要调整 */
+    top: 20px; /* 调整顶部位置 */
+    margin: 0; /* 重置边距 */
+    width: 1000px;
+  }
+}
+</style>

+ 279 - 0
src/views/unqualified/index.vue

@@ -0,0 +1,279 @@
+<template>
+  <div class="container">
+    <div class="header">
+      <Search :searchOptions="searchForm" ref="searchRef" @dataList="getData"/>
+    </div>
+    <div class="table">
+      <el-button
+        type="primary"
+        size="small"
+        class="btn"
+        style="margin-bottom: 10px"
+        @click="toAdd"
+        >新增</el-button
+      >
+      <el-table :data="tableData" border>
+        <el-table-column prop="materialModel" label="产品型号" />
+        <el-table-column prop="type" label="产品分类" />
+        <el-table-column prop="workOrderCode" label="生产批号" />
+        <el-table-column prop="seqs" label="管号" width="200" overhidden="true"/>
+        <el-table-column prop="seqNum" label="数量" />
+        <el-table-column prop="componentName" label="器件名称及型号" />
+        <el-table-column prop="num" label="数量" />
+        <el-table-column prop="company" label="供方单位" overhidden="true" />
+        <el-table-column prop="currentUserName" label="审核人" overhidden="true" />
+        <el-table-column prop="auditType" label="审核类型">
+          <template #default="{ row }">
+              {{ getTextByAuditType(row.auditType) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="state" label="审核状态">
+          <template #default="{ row }">
+            <div :style="{ color: getColorByState(row.state) }">
+              {{ getTextByState(row.state) }}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="created" label="创建时间" />
+        <el-table-column
+          align="center"
+          width="160"
+          prop=""
+          label="操作"
+          id="opear"
+        >
+          <template #default="{ row }">
+            <el-button
+              v-if="row.state === 0"
+              link
+              type="danger"
+              @click="toDelete(row)"
+              >删除</el-button
+            >
+            <el-button
+              link
+              v-if="(row.state === 0 || row.state === 1) && userStore.user.username == row.currentUserName"
+              @click="handle(row)"
+              type="primary"
+              >处理</el-button
+            >
+            <el-button link @click="toDetail(row)" type="primary"
+              >详情</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+      <Pagination
+        :total="currentOption.total"
+        :page="currentOption.page"
+        :limit="currentOption.limit"
+        :pageSizes="currentOption.pageSizes"
+        v-model:page="currentOption.page"
+        v-model:limit="currentOption.limit"
+        @pagination="getData"
+      />
+      <Add ref="addRef" @finish="getData"></Add>
+      <Detail ref="detailRef"></Detail>
+      <Handle20 ref="handle20Ref" @finish="getData"></Handle20>
+      <Handle21 ref="handle21Ref" @finish="getData"></Handle21>
+      <Handle3 ref="handle3Ref" @finish="getData"></Handle3>
+      <Handle4 ref="handle4Ref" @finish="getData"></Handle4>
+      <Handle5 ref="handle5Ref" @finish="getData"></Handle5>
+      <Handle6 ref="handle6Ref" @finish="getData"></Handle6>
+      <Handle7 ref="handle7Ref" @finish="getData"></Handle7>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import Search from "@/components/Search/index.vue";
+import { useSpcStore,useUserStore,useDictionaryStore } from "@/store";
+const { dicts } = useDictionaryStore();
+import { deleteFeedback, getUnqualifiedData } from "@/api/unqualified/index";
+import Add from "@/views/unqualified/add.vue";
+import Detail from "@/views/unqualified/detail.vue";
+import Handle20 from "@/views/unqualified/handle20.vue";
+import Handle21 from "@/views/unqualified/handle21.vue";
+import Handle3 from "@/views/unqualified/handle3.vue";
+import Handle4 from "@/views/unqualified/handle4.vue";
+import Handle5 from "@/views/unqualified/handle5.vue";
+import Handle6 from "@/views/unqualified/handle6.vue";
+import Handle7 from "@/views/unqualified/handle7.vue";
+
+defineOptions({
+  name: "SPCUnqualified",
+});
+const userStore = useUserStore();
+const auditTypes = dicts.unqualified_audit_type
+const store = useSpcStore();
+
+const router = useRouter();
+
+const addRef = ref(null);
+
+const currentOption = reactive({
+  total: 0,
+  page: 1,
+  limit: 10,
+});
+const tableData = ref([]);
+const searchRef = ref(null);
+const searchForm = [
+  {
+    label: "工单号",
+    prop: "workOrderCode",
+    type: "input",
+  },
+  {
+    label: "供方单位",
+    prop: "company",
+    type: "input",
+  },
+  {
+    label: "元器件名称及型号",
+    prop: "componentName",
+    type: "input",
+  },
+];
+
+const getData = async (obj) => {
+  const { data, code } = await getUnqualifiedData({
+    ...searchRef.value.searchForm,
+    pageNo: currentOption.page,
+    pageSize: currentOption.limit,
+  });
+  if (code == "200") {
+    tableData.value = data.records;
+    currentOption.total = data.totalCount;
+  }
+};
+
+const toAdd = () => {
+  addRef.value && addRef.value.showDrawer();
+};
+
+const toDelete = async (row) => {
+  const res = await deleteFeedback(row.id);
+  currentOption.page = 1;
+  getData();
+  // const { code } = await deleteData({ id });
+  // if (code == "200") {
+  //   ElMessage.success("操作成功");
+  //   getData();
+  // }
+};
+
+// 处理相关
+const handle20Ref = ref(null);
+const handle21Ref = ref(null);
+const handle3Ref = ref(null);
+const handle4Ref = ref(null);
+const handle5Ref = ref(null);
+const handle6Ref = ref(null);
+const handle7Ref = ref(null);
+const handle = (row) => {
+  if (row.remark2 && !JSON.parse(row.remark2).content) {
+    if(row.auditType == '1'){
+      handle20Ref.value && handle20Ref.value.showDrawer(row); // 处理
+    }else{
+      handle21Ref.value && handle21Ref.value.showDrawer(row); // 处理
+    }
+  } else if (row.remark3 && !JSON.parse(row.remark3).content) {
+    handle3Ref.value && handle3Ref.value.showDrawer(row); // 处理
+  } else if (row.remark4 && !JSON.parse(row.remark4).content) {
+    handle4Ref.value && handle4Ref.value.showDrawer(row); // 处理
+  } else if (row.remark5 && !JSON.parse(row.remark5).content) {
+    handle5Ref.value && handle5Ref.value.showDrawer(row); // 处理
+  } else if (row.remark6 && !JSON.parse(row.remark6).content) {
+    handle6Ref.value && handle6Ref.value.showDrawer(row); // 处理
+  } else if (row.remark7 && !JSON.parse(row.remark7).content) {
+    handle7Ref.value && handle7Ref.value.showDrawer(row); // 处理
+  }else{
+    ElMessage.info("该工单正在处理中。。。");
+  }
+};
+
+// 详情
+const detailRef = ref(null);
+const toDetail = (row) => {
+  detailRef.value && detailRef.value.showDrawer(row); // 详情
+};
+const getTextByAuditType = (state) => {
+  if(state){
+    const item = auditTypes.filter((v)=>{
+      console.log("dictValue:"  + v.dictValue + ",state:" + state  + "..." + (v.dictValue === state))
+      return v.dictValue === state
+    })
+    if(item.length > 0){
+      return item[0].dictLabel
+    }
+  }
+};
+// 审核状态0待处理 1 审核中 2 审核驳回 3 审核完成
+const getTextByState = (state) => {
+  switch (state) {
+    case 0:
+      return "待处理";
+    case 1:
+      return "审核中";
+    case 2:
+      return "审核驳回";
+    case 3:
+      return "审核完成";
+    default:
+      return "";
+  }
+};
+const getColorByState = (state) => {
+  switch (state) {
+    case 0:
+      return "#59acbb";
+    case 1:
+      return "#bba559";
+    case 2:
+      return "#d96868";
+    case 3:
+      return "#67c23a";
+    default:
+      return "";
+  }
+};
+
+onMounted(() => {
+  getData();
+});
+</script>
+
+<style scoped lang="scss">
+.container {
+  background-color: white;
+  width: 100%;
+  height: 100%;
+  padding: 20px;
+  display: flex;
+  flex-direction: column;
+  .header {
+    width: 100%;
+    height: auto;
+  }
+  .table {
+    flex: 1;
+    padding-bottom: 20px;
+  }
+  .formView {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    .formTitle {
+      text-align: center;
+      font-size: 20px;
+      margin-bottom: 20px;
+    }
+    .formStyle {
+      width: 400px;
+    }
+  }
+}
+</style>