From d420578cb8bc076be2f0c7dd5a4dbfca335d7cdb Mon Sep 17 00:00:00 2001
From: zhang_nuo <zhang_12370@163.com>
Date: 星期一, 17 八月 2026 21:44:51 +0800
Subject: [PATCH] feat(personnel,production): 新增年龄自动计算及工单数量支持小数

---
 src/views/equipmentManagement/upkeep/index.vue |  260 +++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 175 insertions(+), 85 deletions(-)

diff --git a/src/views/equipmentManagement/upkeep/index.vue b/src/views/equipmentManagement/upkeep/index.vue
index 0ee99eb..43474d7 100644
--- a/src/views/equipmentManagement/upkeep/index.vue
+++ b/src/views/equipmentManagement/upkeep/index.vue
@@ -2,8 +2,8 @@
   <div class="app-container">
     <el-tabs v-model="activeTab"
              @tab-change="handleTabChange">
-      <!-- 瀹氭椂浠诲姟绠$悊tab -->
-      <el-tab-pane label="瀹氭椂浠诲姟绠$悊"
+      <!-- 淇濆吇浠诲姟tab -->
+      <el-tab-pane label="淇濆吇浠诲姟"
                    name="scheduled">
         <div class="search_form">
           <el-form :model="scheduledFilters"
@@ -37,7 +37,7 @@
         <div class="table_list">
           <div class="actions">
             <el-text class="mx-1"
-                     size="large">瀹氭椂浠诲姟绠$悊</el-text>
+                     size="large">淇濆吇浠诲姟</el-text>
             <div>
               <el-button type="primary"
                          icon="Plus"
@@ -84,8 +84,8 @@
           </PIMTable>
         </div>
       </el-tab-pane>
-      <!-- 浠诲姟璁板綍tab锛堝師璁惧淇濆吇椤甸潰锛� -->
-      <el-tab-pane label="浠诲姟璁板綍"
+      <!-- 淇濆吇璁板綍tab锛堝師璁惧淇濆吇椤甸潰锛� -->
+      <el-tab-pane label="淇濆吇璁板綍"
                    name="record">
         <div class="search_form">
           <el-form :model="filters"
@@ -130,7 +130,7 @@
         <div class="table_list">
           <div class="actions">
             <el-text class="mx-1"
-                     size="large">浠诲姟璁板綍</el-text>
+                     size="large">淇濆吇璁板綍</el-text>
             <div>
               <el-button type="success"
                          icon="Van"
@@ -142,68 +142,91 @@
               </el-button>
               <el-button type="danger"
                          icon="Delete"
-                         :disabled="multipleList.length <= 0 || hasFinishedStatus"
+                         :disabled="multipleList.length <= 0"
                          @click="delRepairByIds(multipleList.map((item) => item.id))">
                 鎵归噺鍒犻櫎
               </el-button>
             </div>
           </div>
-          <PIMTable rowKey="id"
-                    isSelection
-                    :column="columns"
-                    :tableData="dataList"
-                    :page="{
-          current: pagination.currentPage,
-          size: pagination.pageSize,
-          total: pagination.total,
-        }"
-                    @selection-change="handleSelectionChange"
-                    @pagination="changePage">
-            <template #maintenanceResultRef="{ row }">
-              <div>{{ row.maintenanceResult || '-' }}</div>
-            </template>
-            <template #statusRef="{ row }">
-              <el-tag v-if="row.status === 2"
-                      type="danger">澶辫触</el-tag>
-              <el-tag v-if="row.status === 1"
-                      type="success">瀹岀粨</el-tag>
-              <el-tag v-if="row.status === 0"
-                      type="warning">寰呬繚鍏�</el-tag>
-            </template>
-            <template #operation="{ row }">
-              <!-- 杩欎釜鍔熻兘璺熸柊澧炰繚鍏诲姛鑳戒竴妯′竴鏍凤紝鏈夊暐鎰忎箟锛� -->
-              <!-- <el-button
-              type="primary"
-              text
-              @click="addMaintain(row)"
+          <el-table
+            :data="groupedDataList"
+            border
+            v-loading="tableLoading"
+            @selection-change="handleSelectionChange"
+            :expand-row-keys="expandedRowKeys"
+            :row-key="(row) => row.date"
+            @expand-change="onExpandChange"
           >
-            鏂板淇濆吇
-          </el-button> -->
-              <el-button type="primary"
-                         link
-                         :disabled="row.status === 1"
-                         @click="editPlan(row.id)">
-                缂栬緫
-              </el-button>
-              <el-button type="success"
-                         link
-                         :disabled="row.status === 1"
-                         @click="addMaintain(row)">
-                淇濆吇
-              </el-button>
-              <el-button type="danger"
-                         link
-                         :disabled="row.status === 1"
-                         @click="delRepairByIds(row.id)">
-                鍒犻櫎
-              </el-button>
-              <el-button type="primary"
-                         link
-                         @click="openFileDialog(row)">
-                闄勪欢
-              </el-button>
-            </template>
-          </PIMTable>
+            <el-table-column type="selection" width="55" />
+            <el-table-column type="expand">
+              <template #default="props">
+                <el-table :data="props.row.children" border row-key="id">
+                  <el-table-column label="璁惧鍚嶇О" prop="deviceName" align="center" />
+                  <el-table-column label="瑙勬牸鍨嬪彿" prop="deviceModel" align="center" />
+                  <el-table-column label="褰曞叆浜�" prop="createUserName" align="center" />
+                  <el-table-column label="淇濆吇椤圭洰" prop="machineryCategory" align="center">
+                    <template #default="{ row }">
+                      {{ row.machineryCategory || '--' }}
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="瀹為檯淇濆吇浜�" prop="maintenanceActuallyName" align="center" />
+                  <el-table-column label="瀹為檯淇濆吇鏃ユ湡" align="center">
+                    <template #default="{ row }">
+                      {{ row.maintenanceActuallyTime ? dayjs(row.maintenanceActuallyTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="淇濆吇缁撴灉" align="center">
+                    <template #default="{ row }">
+                      {{ row.maintenanceResult || '-' }}
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="鐘舵��" align="center">
+                    <template #default="{ row }">
+                      <el-tag v-if="row.status === 2" type="danger">澶辫触</el-tag>
+                      <el-tag v-if="row.status === 1" type="success">瀹岀粨</el-tag>
+                      <el-tag v-if="row.status === 0" type="warning">寰呬繚鍏�</el-tag>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="鎿嶄綔" align="center" width="300">
+                    <template #default="{ row }">
+                      <el-button type="primary" link :disabled="row.status === 1" @click="editPlan(row.id)">缂栬緫</el-button>
+                      <el-button type="success" link :disabled="row.status !== 0" @click="handleSingleComplete(row.id)">淇濆吇瀹屾垚</el-button>
+                      <el-button type="success" link :disabled="row.status === 1" @click="addMaintain(row)">淇濆吇</el-button>
+                      <el-button type="danger" link :disabled="row.status === 1" @click="delRepairByIds(row.id)">鍒犻櫎</el-button>
+                      <el-button type="primary" link @click="openFileDialog(row)">闄勪欢</el-button>
+                    </template>
+                  </el-table-column>
+                </el-table>
+              </template>
+            </el-table-column>
+            <el-table-column label="璁″垝淇濆吇鏃ユ湡" prop="date" align="center" />
+            <el-table-column label="淇濆吇璁板綍鏁�" prop="count" align="center" />
+            <el-table-column label="寰呬繚鍏绘暟" align="center" width="120">
+              <template #default="{ row }">
+                {{ row.children.filter(c => c.status === 0).length }}
+              </template>
+            </el-table-column>
+            <el-table-column label="鎿嶄綔" align="center" width="200">
+              <template #default="{ row }">
+                <el-button
+                  type="primary"
+                  size="small"
+                  :disabled="!row.children.some(c => c.status === 0)"
+                  @click="handleBatchComplete(row.date)"
+                >
+                  涓�閿繚鍏诲畬鎴�
+                </el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <Pagination
+            v-show="pagination.total > 0"
+            :total="pagination.total"
+            layout="total, sizes, prev, pager, next, jumper"
+            :page="pagination.currentPage"
+            :limit="pagination.pageSize"
+            @pagination="changePage"
+          />
         </div>
       </el-tab-pane>
     </el-tabs>
@@ -217,6 +240,7 @@
               v-model:visible="fileDialogVisible"
               :record-type="'device_maintenance'"
               :record-id="currentMaintenanceTaskId" />
+
   </div>
 </template>
 
@@ -240,8 +264,11 @@
     delUpkeep,
     deviceMaintenanceTaskList,
     deviceMaintenanceTaskDel,
+    batchCompleteMaintenance,
+    completeMaintenance,
   } from "@/api/equipmentManagement/upkeep";
   import dayjs from "dayjs";
+  import Pagination from "@/components/PIMTable/Pagination.vue";
 
   const { proxy } = getCurrentInstance();
   const FileList = defineAsyncComponent(() =>
@@ -262,7 +289,7 @@
   const fileDialogVisible = ref(false);
   const currentMaintenanceTaskId = ref(null);
 
-  // 浠诲姟璁板綍tab锛堝師璁惧淇濆吇椤甸潰锛夌浉鍏冲彉閲�
+  // 淇濆吇璁板綍tab锛堝師璁惧淇濆吇椤甸潰锛夌浉鍏冲彉閲�
   const filters = reactive({
     deviceName: "",
     maintenancePlanTime: "",
@@ -273,12 +300,58 @@
   const dataList = ref([]);
   const pagination = ref({
     currentPage: 1,
-    pageSize: 10,
+    pageSize: 100,
     total: 0,
   });
   const multipleList = ref([]);
+  const tableLoading = ref(false);
+  const expandedRowKeys = ref([]);
 
-  // 瀹氭椂浠诲姟绠$悊tab鐩稿叧鍙橀噺
+  const groupByDate = (list) => {
+    const map = {};
+    list.forEach(item => {
+      const date = item.dateStr || (item.maintenancePlanTime ? dayjs(item.maintenancePlanTime).format('YYYY-MM-DD') : (item.createTime ? dayjs(item.createTime).format('YYYY-MM-DD') : '鏈煡鏃ユ湡'));
+      if (!map[date]) map[date] = [];
+      map[date].push(item);
+    });
+    return Object.entries(map).map(([date, children]) => ({ date, children, count: children.length }));
+  };
+
+  const groupedDataList = computed(() => groupByDate(dataList.value));
+
+  // 鍗曟潯淇濆吇瀹屾垚
+  const handleSingleComplete = async (id) => {
+    try {
+      await ElMessageBox.confirm('纭灏嗚淇濆吇璁板綍鏍囪涓哄畬鎴愶紵', '鎻愮ず', { type: 'warning' });
+      const res = await completeMaintenance(id);
+      if (res.code === 200) {
+        ElMessage.success('淇濆吇瀹屾垚');
+        getTableData();
+      } else {
+        ElMessage.error(res.msg || '鎿嶄綔澶辫触');
+      }
+    } catch { /* 鍙栨秷 */ }
+  };
+
+  // 涓�閿繚鍏诲畬鎴�
+  const handleBatchComplete = async (dateStr) => {
+    try {
+      await ElMessageBox.confirm(`纭灏� ${dateStr} 鐨勬墍鏈夊緟淇濆吇璁板綍鏍囪涓哄畬鎴愶紵`, '鎻愮ず', { type: 'warning' });
+      const res = await batchCompleteMaintenance(dateStr);
+      if (res.code === 200) {
+        ElMessage.success(res.msg || '鎵归噺淇濆吇瀹屾垚鎴愬姛');
+        getTableData();
+      } else {
+        ElMessage.error(res.msg || '鎵归噺淇濆吇瀹屾垚澶辫触');
+      }
+    } catch { /* 鍙栨秷 */ }
+  };
+
+  const onExpandChange = (row, expandedRows) => {
+    expandedRowKeys.value = expandedRows.map(r => r.date);
+  };
+
+  // 淇濆吇浠诲姟tab鐩稿叧鍙橀噺
   const scheduledFilters = reactive({
     taskName: "",
     status: "",
@@ -292,12 +365,18 @@
   });
   const scheduledMultipleList = ref([]);
 
-  // 瀹氭椂浠诲姟绠$悊琛ㄦ牸鍒楅厤缃�
+  // 淇濆吇浠诲姟琛ㄦ牸鍒楅厤缃�
   const scheduledColumns = ref([
     { prop: "taskName", label: "璁惧鍚嶇О" },
     {
       label: "瑙勬牸鍨嬪彿",
       prop: "deviceModel",
+    },
+    {
+      label: "淇濆吇椤圭洰",
+      prop: "machineryCategory",
+      minWidth: 120,
+      formatData: cell => cell || "--",
     },
     {
       prop: "frequencyType",
@@ -336,8 +415,15 @@
         );
       },
     },
+    { prop: "maintenancePerson", label: "淇濆吇浜�", minWidth: 100 },
     { prop: "registrant", label: "鐧昏浜�", minWidth: 100 },
-    { prop: "registrationDate", label: "鐧昏鏃ユ湡", minWidth: 100 },
+    {
+      prop: "registrationDate",
+      label: "鐧昏鏃ユ湡",
+      minWidth: 100,
+      formatData: cell =>
+        cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : "-",
+    },
     {
       fixed: "right",
       label: "鎿嶄綔",
@@ -348,7 +434,7 @@
     },
   ]);
 
-  // 浠诲姟璁板綍琛ㄦ牸鍒楅厤缃紙鍘熻澶囦繚鍏昏〃鏍煎垪锛�
+  // 淇濆吇璁板綍琛ㄦ牸鍒楅厤缃紙鍘熻澶囦繚鍏昏〃鏍煎垪锛�
   const columns = ref([
     {
       label: "璁惧鍚嶇О",
@@ -364,7 +450,9 @@
       label: "璁″垝淇濆吇鏃ユ湡",
       align: "center",
       prop: "maintenancePlanTime",
-      formatData: cell => dayjs(cell).format("YYYY-MM-DD"),
+      formatData: cell => {
+        return cell == null ? "-" : dayjs(cell).format("YYYY-MM-DD");
+      },
     },
     {
       label: "褰曞叆浜�",
@@ -372,9 +460,10 @@
       prop: "createUserName",
     },
     {
-      label: "椤圭洰",
+      label: "淇濆吇椤圭洰",
       align: "center",
       prop: "machineryCategory",
+      formatData: cell => cell || "--",
     },
     // {
     //   label: "褰曞叆鏃ユ湡",
@@ -428,7 +517,7 @@
     }
   };
 
-  // 瀹氭椂浠诲姟绠$悊鐩稿叧鏂规硶
+  // 淇濆吇浠诲姟鐩稿叧鏂规硶
   const getScheduledTableData = async () => {
     try {
       const params = {
@@ -495,8 +584,9 @@
     ElMessage.info("瀵煎嚭瀹氭椂浠诲姟鍔熻兘寰呭疄鐜�");
   };
 
-  // 浠诲姟璁板綍鐩稿叧鏂规硶锛堝師璁惧淇濆吇椤甸潰鏂规硶锛�
+  // 淇濆吇璁板綍鐩稿叧鏂规硶锛堝師璁惧淇濆吇椤甸潰鏂规硶锛�
   const getTableData = async () => {
+    tableLoading.value = true;
     try {
       const params = {
         current: pagination.value.currentPage,
@@ -518,6 +608,8 @@
       }
     } catch (error) {
       console.log(error);
+    } finally {
+      tableLoading.value = false;
     }
   };
 
@@ -530,13 +622,15 @@
   };
 
   const handleSelectionChange = selection => {
-    multipleList.value = selection;
+    // 浠庨�変腑鐨勫垎缁勮涓敹闆嗘墍鏈夊瓙璁板綍ID
+    const ids = [];
+    selection.forEach(group => {
+      if (group.children) {
+        group.children.forEach(child => ids.push(child.id));
+      }
+    });
+    multipleList.value = ids;
   };
-
-  // 妫�鏌ラ�変腑鐨勮褰曚腑鏄惁鏈夊畬缁撶姸鎬佺殑
-  const hasFinishedStatus = computed(() => {
-    return multipleList.value.some(item => item.status === 1);
-  });
 
   const changePage = page => {
     pagination.value.currentPage = page.page;
@@ -557,12 +651,8 @@
   };
 
   const delRepairByIds = async ids => {
-    // 妫�鏌ユ槸鍚︽湁瀹岀粨鐘舵�佺殑璁板綍
-    const hasFinished = multipleList.value.some(item => item.status === 1);
-    if (hasFinished) {
-      ElMessage.warning("涓嶈兘鍒犻櫎鐘舵�佷负瀹岀粨鐨勮褰�");
-      return;
-    }
+    const idList = Array.isArray(ids) ? ids : [ids];
+    if (idList.length === 0) return;
 
     try {
       await ElMessageBox.confirm("纭鍒犻櫎淇濆吇鏁版嵁, 姝ゆ搷浣滀笉鍙��?", "璀﹀憡", {
@@ -571,7 +661,7 @@
         type: "warning",
       });
 
-      const { code } = await delUpkeep(ids);
+      const { code } = await delUpkeep(idList);
       if (code === 200) {
         ElMessage.success("鍒犻櫎鎴愬姛");
         getTableData();

--
Gitblit v1.9.3