From e3179b9da9ed718bb8240ee8a45b3f8c2ad479cb Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 18 十一月 2025 14:48:29 +0800
Subject: [PATCH] 1.设备台帐二维码上加上设备名称 2.设备保养和保修加上每次的保养保修金额 3.加一个汇总页面,可以看到每个设备的每个月的金额,也可以选择看每年的金额

---
 src/views/equipmentManagement/upkeep/index.vue                  |   16 
 /dev/null                                                       |   97 --------
 src/views/equipmentManagement/amountSummary/index.vue           |   82 ++++++
 src/views/equipmentManagement/repair/Modal/MaintainModal.vue    |   76 +++++-
 src/api/system/post.js                                          |    8 
 src/views/equipmentManagement/repair/Modal/RepairModal.vue      |  130 +++++++++-
 src/views/equipmentManagement/repair/index.vue                  |   18 -
 src/views/equipmentManagement/upkeep/Modal/MaintenanceModal.vue |   91 ++++++-
 src/views/equipmentManagement/ledger/index.vue                  |   43 +++
 src/views/lavorissue/ledger/index.vue                           |    8 
 src/components/filePreview/index.vue                            |    1 
 src/views/equipmentManagement/upkeep/Modal/PlanModal.vue        |  123 ++++++++-
 12 files changed, 498 insertions(+), 195 deletions(-)

diff --git a/src/api/system/post.js b/src/api/system/post.js
index 8faa266..4014b8e 100644
--- a/src/api/system/post.js
+++ b/src/api/system/post.js
@@ -8,6 +8,14 @@
     params: query
   })
 }
+// 鏌ヨ宀椾綅鍒楄〃鍏ㄩ儴
+export function listPostAll(query) {
+  return request({
+    url: '/system/post/listAll',
+    method: 'get',
+    params: query
+  })
+}
 
 // 鏌ヨ宀椾綅璇︾粏
 export function getPost(postId) {
diff --git a/src/components/filePreview/index.vue b/src/components/filePreview/index.vue
index cda5b56..5dea304 100644
--- a/src/components/filePreview/index.vue
+++ b/src/components/filePreview/index.vue
@@ -88,7 +88,6 @@
 });
 
 const isPdf = computed(() => {
-  console.log(fileUrl.value)
   return /\.pdf$/i.test(fileUrl.value);
 });
 
diff --git a/src/views/equipmentManagement/amountSummary/index.vue b/src/views/equipmentManagement/amountSummary/index.vue
new file mode 100644
index 0000000..051eb83
--- /dev/null
+++ b/src/views/equipmentManagement/amountSummary/index.vue
@@ -0,0 +1,82 @@
+<template>
+  <div class="app-container">
+    <el-form :inline="true" :model="filters">
+      <el-form-item label="鏌ョ湅妯″紡">
+        <el-radio-group v-model="mode" @change="buildColumns">
+          <el-radio-button :value="'month'">鎸夋湀</el-radio-button>
+          <el-radio-button :value="'year'">鎸夊勾</el-radio-button>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item v-if="mode === 'month' || mode === 'year'" label="骞翠唤">
+        <el-date-picker v-model="year" type="year" value-format="YYYY" format="YYYY" placeholder="璇烽�夋嫨骞翠唤" @change="refresh" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="refresh">鏌ヨ</el-button>
+        <el-button @click="reset">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <div class="table_list">
+      <PIMTable
+        rowKey="deviceId"
+        :column="columns"
+        :tableData="tableData"
+        :page="{ current: 1, size: tableData.length || 10, total: tableData.length }"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from "vue";
+
+defineOptions({ name: "閲戦姹囨��" });
+
+const mode = ref("month");
+const year = ref(new Date().getFullYear().toString());
+const filters = ref({});
+
+const columns = ref([]);
+const tableData = ref([]);
+
+const buildColumns = () => {
+  const base = [{ label: "璁惧鍚嶇О", align: "center", prop: "deviceName", width: 180 }];
+  if (mode.value === "month") {
+    const monthCols = Array.from({ length: 12 }, (_, i) => ({
+      label: `${i + 1}鏈坄,
+      align: "center",
+      prop: `m${i + 1}`,
+    }));
+    columns.value = [
+      ...base,
+      ...monthCols,
+      { label: "鎬昏", align: "center", prop: "total" },
+    ];
+  } else {
+    columns.value = [
+      ...base,
+      { label: "閲戦", align: "center", prop: "yearAmount" },
+    ];
+  }
+};
+
+const refresh = async () => {
+  buildColumns();
+  tableData.value = [];
+};
+
+const reset = () => {
+  mode.value = "month";
+  year.value = new Date().getFullYear().toString();
+  refresh();
+};
+
+buildColumns();
+refresh();
+</script>
+
+<style scoped>
+.table_list {
+  margin-top: 10px;
+}
+</style>
diff --git a/src/views/equipmentManagement/ledger/index.vue b/src/views/equipmentManagement/ledger/index.vue
index 83512ae..1119f60 100644
--- a/src/views/equipmentManagement/ledger/index.vue
+++ b/src/views/equipmentManagement/ledger/index.vue
@@ -85,6 +85,7 @@
     <el-dialog v-model="qrDialogVisible" title="浜岀淮鐮�" width="300px">
       <div style="text-align:center;">
         <img :src="qrCodeUrl" alt="浜岀淮鐮�" style="width:200px;height:200px;" />
+        <div style="margin-top:6px;font-size:14px;color:#333;">{{ qrRowData?.deviceName }}</div>
         <div style="margin:10px 0;">
           <el-button type="primary" @click="downloadQRCode">涓嬭浇浜岀淮鐮佸浘鐗�</el-button>
         </div>
@@ -299,10 +300,44 @@
 };
 
 const downloadQRCode = () => {
-  const a = document.createElement("a");
-  a.href = qrCodeUrl.value;
-  a.download = `${qrRowData.value.deviceName || "浜岀淮鐮�"}.png`;
-  a.click();
+  const name = qrRowData.value?.deviceName || "浜岀淮鐮�";
+  const img = new Image();
+  img.src = qrCodeUrl.value;
+  img.onload = () => {
+    const padding = 10;
+    const qrSize = 200;
+    const textHeight = 24; // space for text
+    const width = qrSize + padding * 2;
+    const height = qrSize + padding * 2 + textHeight;
+    const canvas = document.createElement("canvas");
+    canvas.width = width;
+    canvas.height = height;
+    const ctx = canvas.getContext("2d");
+    // background
+    ctx.fillStyle = "#ffffff";
+    ctx.fillRect(0, 0, width, height);
+    // draw QR centered
+    ctx.drawImage(img, padding, padding, qrSize, qrSize);
+    // draw name centered below
+    ctx.fillStyle = "#333";
+    ctx.font = "14px Arial";
+    ctx.textAlign = "center";
+    ctx.textBaseline = "middle";
+    const maxTextWidth = width - padding * 2;
+    let displayName = name;
+    // ellipsis if too long
+    while (ctx.measureText(displayName).width > maxTextWidth && displayName.length > 0) {
+      displayName = displayName.slice(0, -1);
+    }
+    if (displayName !== name) displayName = displayName + "鈥�";
+    ctx.fillText(displayName, width / 2, qrSize + padding + textHeight / 2);
+
+    const dataUrl = canvas.toDataURL("image/png");
+    const a = document.createElement("a");
+    a.href = dataUrl;
+    a.download = `${name}.png`;
+    a.click();
+  };
 };
 
 onMounted(() => {
diff --git a/src/views/equipmentManagement/repair/Form/MaintainForm.vue b/src/views/equipmentManagement/repair/Form/MaintainForm.vue
deleted file mode 100644
index bbb25c1..0000000
--- a/src/views/equipmentManagement/repair/Form/MaintainForm.vue
+++ /dev/null
@@ -1,58 +0,0 @@
-<template>
-  <el-form :model="form" label-width="80px">
-    <el-form-item label="缁翠慨浜�">
-      <el-input v-model="form.maintenanceName" placeholder="璇疯緭鍏ョ淮淇汉" />
-    </el-form-item>
-    <el-form-item label="缁翠慨缁撴灉">
-      <el-input v-model="form.maintenanceResult" placeholder="璇疯緭鍏ョ淮淇粨鏋�" />
-    </el-form-item>
-    <el-form-item label="缁翠慨鏃ユ湡">
-      <el-date-picker
-        v-model="form.maintenanceTime"
-        placeholder="璇烽�夋嫨缁翠慨鏃ユ湡"
-        format="YYYY-MM-DD HH:mm:ss"
-        value-format="YYYY-MM-DD HH:mm:ss"
-        type="datetime"
-        clearable
-        style="width: 100%"
-      />
-    </el-form-item>
-  </el-form>
-</template>
-
-<script setup>
-import useFormData from "@/hooks/useFormData";
-import useUserStore from "@/store/modules/user";
-import dayjs from "dayjs";
-
-defineOptions({
-  name: "璁惧缁翠慨琛ㄥ崟",
-});
-
-const userStore = useUserStore();
-const { form, resetForm } = useFormData({
-  maintenanceName: undefined, // 缁翠慨鍚嶇О
-  maintenanceResult: undefined, // 缁翠慨缁撴灉
-  maintenanceTime: undefined, // 缁翠慨鏃ユ湡
-});
-
-const setForm = (data) => {
-  form.maintenanceName = data.maintenanceName ?? userStore.nickName;
-  form.maintenanceResult = data.maintenanceResult;
-  form.maintenanceTime =
-    dayjs(data.maintenanceTime).format("YYYY-MM-DD HH:mm:ss") ??
-    dayjs().format("YYYY-MM-DD HH:mm:ss");
-};
-
-const getForm = () => {
-  return form;
-};
-
-defineExpose({
-  getForm,
-  setForm,
-  resetForm,
-});
-</script>
-
-<style lang="scss" scoped></style>
diff --git a/src/views/equipmentManagement/repair/Form/RepairForm.vue b/src/views/equipmentManagement/repair/Form/RepairForm.vue
deleted file mode 100644
index 1fadde4..0000000
--- a/src/views/equipmentManagement/repair/Form/RepairForm.vue
+++ /dev/null
@@ -1,113 +0,0 @@
-<template>
-  <el-form :model="form" label-width="100px">
-    <el-row>
-      <el-col :span="12">
-        <el-form-item label="璁惧鍚嶇О">
-          <el-select v-model="form.deviceLedgerId" @change="setDeviceModel">
-            <el-option
-              v-for="(item, index) in deviceOptions"
-              :key="index"
-              :label="item.deviceName"
-              :value="item.id"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="瑙勬牸鍨嬪彿">
-          <el-input
-            v-model="form.deviceModel"
-            placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
-            disabled
-          />
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="鎶ヤ慨鏃ユ湡">
-          <el-date-picker
-            v-model="form.repairTime"
-            placeholder="璇烽�夋嫨鎶ヤ慨鏃ユ湡"
-            format="YYYY-MM-DD"
-            value-format="YYYY-MM-DD"
-            type="date"
-            clearable
-            style="width: 100%"
-          />
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="鎶ヤ慨浜�">
-          <el-input v-model="form.repairName" placeholder="璇疯緭鍏ユ姤淇汉" />
-        </el-form-item>
-      </el-col>
-      <el-col :span="24">
-        <el-form-item label="鏁呴殰鐜拌薄">
-          <el-input
-            v-model="form.remark"
-            :rows="2"
-            type="textarea"
-            placeholder="璇疯緭鍏ユ晠闅滅幇璞�"
-          />
-        </el-form-item>
-      </el-col>
-    </el-row>
-  </el-form>
-</template>
-
-<script setup>
-import useFormData from "@/hooks/useFormData";
-import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
-import useUserStore from "@/store/modules/user";
-
-defineOptions({
-  name: "璁惧鎶ヤ慨琛ㄥ崟",
-});
-
-const userStore = useUserStore();
-const deviceOptions = ref([]);
-
-const loadDeviceName = async () => {
-  const { data } = await getDeviceLedger();
-  deviceOptions.value = data;
-};
-
-const { form, resetForm } = useFormData({
-  deviceLedgerId: undefined, // 璁惧Id
-  deviceName: undefined, // 璁惧鍚嶇О
-  deviceModel: undefined, // 瑙勬牸鍨嬪彿
-  repairTime: undefined, // 鎶ヤ慨鏃ユ湡
-  repairName: userStore.nickName, // 鎶ヤ慨浜�
-  remark: undefined, // 鏁呴殰鐜拌薄
-});
-
-const setDeviceModel = (id) => {
-  const option = deviceOptions.value.find((item) => item.id === id);
-  form.deviceModel = option.deviceModel;
-};
-
-const getForm = () => {
-  return form;
-};
-
-const setForm = (data) => {
-  form.deviceLedgerId = data.deviceLedgerId;
-  form.deviceName = data.deviceName;
-  form.deviceModel = data.deviceModel;
-  form.repairTime = data.repairTime;
-  form.repairName = data.repairName;
-  form.remark = data.remark;
-};
-
-// onMounted(() => {
-//   loadDeviceName();
-// });
-
-defineExpose({
-  loadDeviceName,
-  resetForm,
-  getForm,
-  setForm,
-});
-</script>
-
-<style lang="scss" scoped></style>
diff --git a/src/views/equipmentManagement/repair/Modal/MaintainModal.vue b/src/views/equipmentManagement/repair/Modal/MaintainModal.vue
index 309be0e..06f7cc9 100644
--- a/src/views/equipmentManagement/repair/Modal/MaintainModal.vue
+++ b/src/views/equipmentManagement/repair/Modal/MaintainModal.vue
@@ -1,6 +1,27 @@
 <template>
   <el-dialog v-model="visible" :title="modalOptions.title" direction="ltr">
-    <MaintainForm ref="maintainFormRef" />
+    <el-form :model="form" :rules="rules" label-width="110px" ref="formRef">
+      <el-form-item label="缁翠慨浜�" prop="maintenanceName">
+        <el-input v-model="form.maintenanceName" placeholder="璇疯緭鍏ョ淮淇汉" />
+      </el-form-item>
+      <el-form-item label="缁翠慨缁撴灉" prop="maintenanceResult">
+        <el-input v-model="form.maintenanceResult" placeholder="璇疯緭鍏ョ淮淇粨鏋�" />
+      </el-form-item>
+      <el-form-item label="鏈缁翠慨閲戦" prop="money">
+        <el-input-number v-model="form.money" :min="0" :precision="2" style="width: 100%" />
+      </el-form-item>
+      <el-form-item label="缁翠慨鏃ユ湡" prop="maintenanceTime">
+        <el-date-picker
+          v-model="form.maintenanceTime"
+          placeholder="璇烽�夋嫨缁翠慨鏃ユ湡"
+          format="YYYY-MM-DD HH:mm:ss"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="datetime"
+          clearable
+          style="width: 100%"
+        />
+      </el-form-item>
+    </el-form>
     <template #footer>
 			<el-button type="primary" @click="sendForm" :loading="loading">
 				{{ modalOptions.confirmText }}
@@ -11,15 +32,17 @@
 </template>
 
 <script setup>
+import { ref, nextTick } from "vue";
 import { useModal } from "@/hooks/useModal";
-import MaintainForm from "../Form/MaintainForm.vue";
+import useFormData from "@/hooks/useFormData";
+import useUserStore from "@/store/modules/user";
+import dayjs from "dayjs";
 import { addMaintain } from "@/api/equipmentManagement/repair";
 
 defineOptions({
   name: "缁翠慨妯℃�佹",
 });
 
-const maintainFormRef = ref();
 const emits = defineEmits(["ok"]);
 
 const {
@@ -32,22 +55,49 @@
   closeModal,
 } = useModal({ title: "璁惧缁翠慨" });
 
+const userStore = useUserStore();
+const formRef = ref();
+const { form, resetForm } = useFormData({
+  maintenanceName: undefined, // 缁翠慨鍚嶇О
+  maintenanceResult: undefined, // 缁翠慨缁撴灉
+  maintenanceTime: undefined, // 缁翠慨鏃ユ湡
+  money: undefined, // 鏈缁翠慨閲戦
+});
+
+const rules = {
+  maintenanceName: [{ required: true, message: "璇疯緭鍏ョ淮淇汉", trigger: "blur" }],
+  maintenanceResult: [{ required: true, message: "璇疯緭鍏ョ淮淇粨鏋�", trigger: "blur" }],
+  money: [{ required: true, message: "璇疯緭鍏ユ湰娆$淮淇噾棰�", trigger: "change" }],
+  maintenanceTime: [{ required: true, message: "璇烽�夋嫨缁翠慨鏃ユ湡", trigger: "change" }],
+};
+
+const setForm = (data) => {
+  form.maintenanceName = data.maintenanceName ?? userStore.nickName;
+  form.maintenanceResult = data.maintenanceResult;
+  form.money = data.money;
+  form.maintenanceTime =
+    dayjs(data.maintenanceTime).format("YYYY-MM-DD HH:mm:ss") ??
+    dayjs().format("YYYY-MM-DD HH:mm:ss");
+};
+
 const sendForm = async () => {
-  loading.value = true;
-  const form = await maintainFormRef.value.getForm();
-  const { code } = await addMaintain({ id: id.value, ...form });
-  if (code == 200) {
-    emits("ok");
-    maintainFormRef.value.resetForm();
-    closeModal();
-  }
-  loading.value = false;
+  await formRef.value.validate(async (valid) => {
+    if (!valid) return;
+    loading.value = true;
+    const { code } = await addMaintain({ id: id.value, ...form });
+    if (code == 200) {
+      emits("ok");
+      resetForm();
+      closeModal();
+    }
+    loading.value = false;
+  });
 };
 
 const open = async (id, row) => {
   openModal(id);
   await nextTick();
-  maintainFormRef.value.setForm(row);
+  setForm(row);
 };
 
 defineExpose({
diff --git a/src/views/equipmentManagement/repair/Modal/RepairModal.vue b/src/views/equipmentManagement/repair/Modal/RepairModal.vue
index 8441da2..7809188 100644
--- a/src/views/equipmentManagement/repair/Modal/RepairModal.vue
+++ b/src/views/equipmentManagement/repair/Modal/RepairModal.vue
@@ -1,6 +1,49 @@
 <template>
   <el-dialog v-model="visible" :title="modalOptions.title" @close="close">
-    <RepairForm ref="repairFormRef" />
+    <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
+      <el-row>
+        <el-col :span="12">
+          <el-form-item label="璁惧鍚嶇О" prop="deviceLedgerId">
+            <el-select v-model="form.deviceLedgerId" @change="setDeviceModel">
+              <el-option
+                v-for="(item, index) in deviceOptions"
+                :key="index"
+                :label="item.deviceName"
+                :value="item.id"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="瑙勬牸鍨嬪彿">
+            <el-input v-model="form.deviceModel" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="鎶ヤ慨鏃ユ湡" prop="repairTime">
+            <el-date-picker
+              v-model="form.repairTime"
+              placeholder="璇烽�夋嫨鎶ヤ慨鏃ユ湡"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
+              type="date"
+              clearable
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="鎶ヤ慨浜�" prop="repairName">
+            <el-input v-model="form.repairName" placeholder="璇疯緭鍏ユ姤淇汉" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+          <el-form-item label="鏁呴殰鐜拌薄" prop="remark">
+            <el-input v-model="form.remark" :rows="2" type="textarea" placeholder="璇疯緭鍏ユ晠闅滅幇璞�" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
     <template #footer>
 			<el-button type="primary" @click="sendForm" :loading="loading">
 				{{ modalOptions.confirmText }}
@@ -8,16 +51,20 @@
       <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
     </template>
   </el-dialog>
+  
 </template>
 
 <script setup>
+import { ref, nextTick } from "vue";
 import { useModal } from "@/hooks/useModal";
-import RepairForm from "../Form/RepairForm.vue";
+import useFormData from "@/hooks/useFormData";
+import useUserStore from "@/store/modules/user";
 import {
   addRepair,
   editRepair,
   getRepairById,
 } from "@/api/equipmentManagement/repair";
+import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
 import { ElMessage } from "element-plus";
 
 defineOptions({
@@ -25,8 +72,6 @@
 });
 
 const emits = defineEmits(["ok"]);
-
-const repairFormRef = ref();
 const {
   id,
   visible,
@@ -37,36 +82,77 @@
   closeModal,
 } = useModal({ title: "璁惧鎶ヤ慨" });
 
+const userStore = useUserStore();
+const deviceOptions = ref([]);
+const formRef = ref();
+const { form, resetForm } = useFormData({
+  deviceLedgerId: undefined, // 璁惧Id
+  deviceName: undefined, // 璁惧鍚嶇О
+  deviceModel: undefined, // 瑙勬牸鍨嬪彿
+  repairTime: undefined, // 鎶ヤ慨鏃ユ湡
+  repairName: userStore.nickName, // 鎶ヤ慨浜�
+  remark: undefined, // 鏁呴殰鐜拌薄
+});
+
+const rules = {
+  deviceLedgerId: [{ required: true, message: "璇烽�夋嫨璁惧鍚嶇О", trigger: "change" }],
+  repairTime: [{ required: true, message: "璇烽�夋嫨鎶ヤ慨鏃ユ湡", trigger: "change" }],
+  repairName: [{ required: true, message: "璇疯緭鍏ユ姤淇汉", trigger: "blur" }],
+  remark: [{ required: true, message: "璇疯緭鍏ユ晠闅滅幇璞�", trigger: "blur" }],
+};
+
+const loadDeviceName = async () => {
+  const { data } = await getDeviceLedger();
+  deviceOptions.value = data;
+};
+
+const setDeviceModel = (id) => {
+  const option = deviceOptions.value.find((item) => item.id === id);
+  form.deviceModel = option ? option.deviceModel : undefined;
+};
+
+const setForm = (data) => {
+  form.deviceLedgerId = data.deviceLedgerId;
+  form.deviceName = data.deviceName;
+  form.deviceModel = data.deviceModel;
+  form.repairTime = data.repairTime;
+  form.repairName = data.repairName ?? userStore.nickName;
+  form.remark = data.remark;
+};
+
 const sendForm = async () => {
-  loading.value = true;
-  const form = await repairFormRef.value.getForm();
-  const { code } = id.value
-    ? await editRepair({ id: unref(id), ...form })
-    : await addRepair(form);
-  if (code == 200) {
-    ElMessage.success(`${id ? "缂栬緫" : "鏂板"}鎶ヤ慨鎴愬姛`);
-    closeModal();
-    emits("ok");
-  }
-  loading.value = false;
+  await formRef.value.validate(async (valid) => {
+    if (!valid) return;
+    loading.value = true;
+    const payload = { ...form };
+    const { code } = id.value
+      ? await editRepair({ id: id.value, ...payload })
+      : await addRepair(payload);
+    if (code == 200) {
+      ElMessage.success(`${id.value ? "缂栬緫" : "鏂板"}鎶ヤ慨鎴愬姛`);
+      closeModal();
+      emits("ok");
+    }
+    loading.value = false;
+  });
 };
 
 const openAdd = async () => {
   openModal();
   await nextTick();
-  await repairFormRef.value.loadDeviceName();
+  await loadDeviceName();
 };
 
-const openEdit = async (id) => {
-  const { data } = await getRepairById(id);
-  openModal(id);
+const openEdit = async (editId) => {
+  const { data } = await getRepairById(editId);
+  openModal(editId);
   await nextTick();
-  await repairFormRef.value.loadDeviceName();
-  await repairFormRef.value.setForm(data);
+  await loadDeviceName();
+  setForm(data);
 };
 
 const close = () => {
-  repairFormRef.value.resetForm();
+  resetForm();
   closeModal();
 };
 
diff --git a/src/views/equipmentManagement/repair/index.vue b/src/views/equipmentManagement/repair/index.vue
index 1a2ff1e..1302ef6 100644
--- a/src/views/equipmentManagement/repair/index.vue
+++ b/src/views/equipmentManagement/repair/index.vue
@@ -7,7 +7,6 @@
             style="width: 240px"
             placeholder="璇疯緭鍏ヨ澶囧悕绉�"
             clearable
-            :prefix-icon="Search"
             @change="getTableData"
         />
       </el-form-item>
@@ -17,7 +16,6 @@
             style="width: 240px"
             placeholder="璇烽�夋嫨瑙勬牸鍨嬪彿"
             clearable
-            :prefix-icon="Search"
             @change="getTableData"
         />
       </el-form-item>
@@ -27,7 +25,6 @@
             style="width: 240px"
             placeholder="璇疯緭鍏ユ晠闅滅幇璞�"
             clearable
-            :prefix-icon="Search"
             @change="getTableData"
         />
       </el-form-item>
@@ -37,7 +34,6 @@
             style="width: 240px"
             placeholder="璇疯緭鍏ョ淮淇汉"
             clearable
-            :prefix-icon="Search"
             @change="getTableData"
         />
       </el-form-item>
@@ -68,6 +64,9 @@
       <div class="actions">
         <el-text class="mx-1" size="large">璁惧鎶ヤ慨</el-text>
         <div>
+					<el-button type="success" icon="Van" @click="addRepair">
+						鏂板鎶ヤ慨
+					</el-button>
           <el-button
             type="primary"
             icon="Plus"
@@ -75,9 +74,6 @@
             @click="addMaintain"
           >
             鏂板缁翠慨
-          </el-button>
-          <el-button type="success" icon="Van" @click="addRepair">
-            鏂板鎶ヤ慨
           </el-button>
           <el-button @click="handleOut">
             瀵煎嚭
@@ -112,16 +108,14 @@
         <template #operation="{ row }">
           <el-button
             type="primary"
-            text
-            icon="editPen"
+            link
             @click="editRepair(row.id)"
           >
             缂栬緫
           </el-button>
           <el-button
             type="danger"
-            text
-            icon="delete"
+						link
             @click="delRepairByIds(row.id)"
           >
             鍒犻櫎
@@ -231,7 +225,7 @@
       dataType: "slot",
       slot: "operation",
       align: "center",
-      width: "200px",
+      width: "150px",
     },
   ]
 );
diff --git a/src/views/equipmentManagement/upkeep/Form/MaintenanceForm.vue b/src/views/equipmentManagement/upkeep/Form/MaintenanceForm.vue
deleted file mode 100644
index bc3db70..0000000
--- a/src/views/equipmentManagement/upkeep/Form/MaintenanceForm.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-<template>
-  <el-form :model="form" label-width="100px">
-    <el-form-item label="瀹為檯淇濆吇浜�">
-      <el-input
-        v-model="form.maintenanceActuallyName"
-        placeholder="璇疯緭鍏ュ疄闄呬繚鍏讳汉"
-      ></el-input>
-    </el-form-item>
-    <el-form-item label="瀹為檯淇濆吇鏃ユ湡">
-      <el-date-picker
-        v-model="form.maintenanceActuallyTime"
-        placeholder="璇烽�夋嫨瀹為檯淇濆吇鏃ユ湡"
-        format="YYYY-MM-DD HH:mm:ss"
-        value-format="YYYY-MM-DD HH:mm:ss"
-        type="datetime"
-        clearable
-        style="width: 100%"
-      />
-    </el-form-item>
-    <el-form-item label="淇濆吇缁撴灉">
-      <el-select v-model="form.maintenanceResult" placeholder="璇烽�夋嫨淇濆吇缁撴灉">
-        <el-option label="瀹屽ソ" :value="1"></el-option>
-        <el-option label="缁翠慨" :value="0"></el-option>
-      </el-select>
-    </el-form-item>
-  </el-form>
-</template>
-
-<script setup>
-import useFormData from "@/hooks/useFormData";
-import dayjs from "dayjs";
-import useUserStore from "@/store/modules/user";
-
-defineOptions({
-  name: "淇濆吇琛ㄥ崟",
-});
-
-const userStore = useUserStore();
-const { form, resetForm } = useFormData({
-  maintenanceActuallyName: undefined, // 瀹為檯淇濆吇浜�
-  maintenanceActuallyTime: undefined, // 瀹為檯淇濆吇鏃ユ湡
-  maintenanceResult: undefined, // 淇濆吇缁撴灉
-});
-
-const setForm = (data) => {
-  form.maintenanceActuallyName =
-    data.maintenanceActuallyName ?? userStore.nickName;
-  form.maintenanceActuallyTime =
-    dayjs(data.maintenanceActuallyTime).format("YYYY-MM-DD HH:mm:ss") ??
-    dayjs().format("YYYY-MM-DD HH:mm:ss");
-  form.maintenanceResult = data.maintenanceResult;
-};
-
-const getForm = () => {
-  return form;
-};
-
-defineExpose({
-  getForm,
-  setForm,
-  resetForm,
-});
-</script>
-
-<style lang="scss" scoped></style>
diff --git a/src/views/equipmentManagement/upkeep/Form/PlanForm.vue b/src/views/equipmentManagement/upkeep/Form/PlanForm.vue
deleted file mode 100644
index 1d94b68..0000000
--- a/src/views/equipmentManagement/upkeep/Form/PlanForm.vue
+++ /dev/null
@@ -1,97 +0,0 @@
-<template>
-  <el-form :model="form" label-width="100px">
-    <el-form-item label="璁惧鍚嶇О">
-      <el-select
-        v-model="form.deviceLedgerId"
-        @change="setDeviceModel"
-        placeholder="璇烽�夋嫨璁惧"
-      >
-        <el-option
-          v-for="(item, index) in deviceOptions"
-          :key="index"
-          :label="item.deviceName"
-          :value="item.id"
-        ></el-option>
-      </el-select>
-    </el-form-item>
-    <el-form-item label="瑙勬牸鍨嬪彿">
-      <el-input
-        v-model="form.deviceModel"
-        placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
-        disabled
-      />
-    </el-form-item>
-    <el-form-item label="璁″垝淇濆吇鏃ユ湡">
-      <el-date-picker
-        style="width: 100%"
-        v-model="form.maintenancePlanTime"
-        format="YYYY-MM-DD"
-        value-format="YYYY-MM-DD HH:mm:ss"
-        type="date"
-        placeholder="璇烽�夋嫨璁″垝淇濆吇鏃ユ湡鏃ユ湡"
-        clearable
-      />
-    </el-form-item>
-  </el-form>
-</template>
-
-<script setup>
-import useFormData from "@/hooks/useFormData";
-import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
-import { onMounted } from "vue";
-import dayjs from "dayjs";
-
-defineOptions({
-  name: "璁″垝琛ㄥ崟",
-});
-
-const deviceOptions = ref([]);
-const loadDeviceName = async () => {
-  const { data } = await getDeviceLedger();
-  deviceOptions.value = data;
-};
-
-const { form, resetForm } = useFormData({
-  deviceLedgerId: undefined, // 璁惧Id
-  deviceName: undefined, // 璁惧鍚嶇О
-  deviceModel: undefined, // 瑙勬牸鍨嬪彿
-  maintenancePlanTime: undefined, // 璁″垝淇濆吇鏃ユ湡
-});
-
-const setDeviceModel = (id) => {
-  const option = deviceOptions.value.find((item) => item.id === id);
-  form.deviceModel = option.deviceModel;
-};
-
-const getForm = () => {
-  return form;
-};
-
-/**
- * @desc 璁剧疆琛ㄥ崟鍐呭
- * @param data 璁惧淇℃伅
- */
-const setForm = (data) => {
-  form.deviceLedgerId = data.deviceLedgerId;
-  form.deviceName = data.deviceName;
-  form.deviceModel = data.deviceModel;
-  form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format(
-    "YYYY-MM-DD HH:mm:ss"
-  );
-};
-
-const loadForm = () => {};
-
-onMounted(() => {
-  loadDeviceName();
-});
-
-defineExpose({
-  loadForm,
-  resetForm,
-  getForm,
-  setForm,
-});
-</script>
-
-<style lang="scss" scoped></style>
diff --git a/src/views/equipmentManagement/upkeep/Modal/MaintenanceModal.vue b/src/views/equipmentManagement/upkeep/Modal/MaintenanceModal.vue
index 0afd512..727f797 100644
--- a/src/views/equipmentManagement/upkeep/Modal/MaintenanceModal.vue
+++ b/src/views/equipmentManagement/upkeep/Modal/MaintenanceModal.vue
@@ -1,6 +1,33 @@
 <template>
   <el-dialog v-model="visible" :title="modalOptions.title" direction="ltr">
-    <MaintenanceForm ref="maintenanceFormRef" />
+    <el-form :model="form" :rules="rules" label-width="110px" ref="formRef">
+      <el-form-item label="瀹為檯淇濆吇浜�" prop="maintenanceActuallyName">
+        <el-input
+          v-model="form.maintenanceActuallyName"
+          placeholder="璇疯緭鍏ュ疄闄呬繚鍏讳汉"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="瀹為檯淇濆吇鏃ユ湡" prop="maintenanceActuallyTime">
+        <el-date-picker
+          v-model="form.maintenanceActuallyTime"
+          placeholder="璇烽�夋嫨瀹為檯淇濆吇鏃ユ湡"
+          format="YYYY-MM-DD HH:mm:ss"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="datetime"
+          clearable
+          style="width: 100%"
+        />
+      </el-form-item>
+      <el-form-item label="淇濆吇缁撴灉" prop="maintenanceResult">
+        <el-select v-model="form.maintenanceResult" placeholder="璇烽�夋嫨淇濆吇缁撴灉">
+          <el-option label="瀹屽ソ" :value="1"></el-option>
+          <el-option label="缁翠慨" :value="0"></el-option>
+        </el-select>
+      </el-form-item>
+			<el-form-item label="鏈缁翠慨閲戦" prop="money">
+				<el-input-number v-model="form.money" :min="0" :precision="2" style="width: 100%" />
+			</el-form-item>
+    </el-form>
     <template #footer>
 			<el-button type="primary" @click="sendForm" :loading="loading">
 				{{ modalOptions.confirmText }}
@@ -11,15 +38,17 @@
 </template>
 
 <script setup>
-import MaintenanceForm from "../Form/MaintenanceForm.vue";
+import { ref, nextTick } from "vue";
 import { useModal } from "@/hooks/useModal";
+import useFormData from "@/hooks/useFormData";
+import useUserStore from "@/store/modules/user";
+import dayjs from "dayjs";
 import { addMaintenance } from "@/api/equipmentManagement/upkeep";
 
 defineOptions({
   name: "淇濆吇妯℃�佹",
 });
 
-const maintenanceFormRef = ref();
 const emits = defineEmits(["ok"]);
 
 const {
@@ -35,22 +64,58 @@
 /**
  * @desc 淇濆瓨淇濆吇
  */
+const userStore = useUserStore();
+const formRef = ref();
+const { form, resetForm } = useFormData({
+  maintenanceActuallyName: undefined, // 瀹為檯淇濆吇浜�
+  maintenanceActuallyTime: undefined, // 瀹為檯淇濆吇鏃ユ湡
+  maintenanceResult: undefined, // 淇濆吇缁撴灉
+	money: undefined, // 淇濆吇閲戦
+});
+
+const rules = {
+  maintenanceActuallyName: [
+    { required: true, message: "璇疯緭鍏ュ疄闄呬繚鍏讳汉", trigger: "blur" },
+  ],
+  maintenanceActuallyTime: [
+    { required: true, message: "璇烽�夋嫨瀹為檯淇濆吇鏃ユ湡", trigger: "change" },
+  ],
+  maintenanceResult: [
+    { required: true, message: "璇烽�夋嫨淇濆吇缁撴灉", trigger: "change" },
+  ],
+	money: [
+    { required: true, message: "璇疯緭鍏ユ湰娆′繚鍏婚噾棰�", trigger: "change" },
+  ],
+};
+
 const sendForm = async () => {
-  loading.value = true;
-  const form = await maintenanceFormRef.value.getForm();
-  const { code } = await addMaintenance({ id: id.value, ...form });
-  if (code == 200) {
-    emits("ok");
-    maintenanceFormRef.value.resetForm();
-    closeModal();
-  }
-  loading.value = false;
+  await formRef.value.validate(async (valid) => {
+    if (!valid) return;
+    loading.value = true;
+    const { code } = await addMaintenance({ id: id.value, ...form });
+    if (code == 200) {
+      emits("ok");
+      resetForm();
+      closeModal();
+    }
+    loading.value = false;
+  });
 };
 
 const open = async (id, row) => {
   openModal(id);
   await nextTick();
-  maintenanceFormRef.value.setForm(row);
+  if (!row) {
+    resetForm();
+    form.maintenanceActuallyName = userStore.nickName;
+    return;
+  }
+  form.maintenanceActuallyName = row.maintenanceActuallyName ?? userStore.nickName;
+  form.maintenanceActuallyTime = row.maintenanceActuallyTime
+    ? dayjs(row.maintenanceActuallyTime).format("YYYY-MM-DD HH:mm:ss")
+    : undefined;
+  form.maintenanceResult = row.maintenanceResult;
+  form.money = row.money;
 };
 defineExpose({
   open,
diff --git a/src/views/equipmentManagement/upkeep/Modal/PlanModal.vue b/src/views/equipmentManagement/upkeep/Modal/PlanModal.vue
index d9cf246..65a9640 100644
--- a/src/views/equipmentManagement/upkeep/Modal/PlanModal.vue
+++ b/src/views/equipmentManagement/upkeep/Modal/PlanModal.vue
@@ -5,7 +5,40 @@
     width="30%"
     @close="close"
   >
-    <PlanForm ref="planFormRef"></PlanForm>
+    <el-form :model="form" :rules="rules" ref="formRef" label-width="110px">
+      <el-form-item label="璁惧鍚嶇О" prop="deviceLedgerId">
+        <el-select
+          v-model="form.deviceLedgerId"
+          @change="setDeviceModel"
+          placeholder="璇烽�夋嫨璁惧"
+        >
+          <el-option
+            v-for="(item, index) in deviceOptions"
+            :key="index"
+            :label="item.deviceName"
+            :value="item.id"
+          ></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="瑙勬牸鍨嬪彿">
+        <el-input
+          v-model="form.deviceModel"
+          placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
+          disabled
+        />
+      </el-form-item>
+      <el-form-item label="璁″垝淇濆吇鏃ユ湡" prop="maintenancePlanTime">
+        <el-date-picker
+          style="width: 100%"
+          v-model="form.maintenancePlanTime"
+          format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="date"
+          placeholder="璇烽�夋嫨璁″垝淇濆吇鏃ユ湡鏃ユ湡"
+          clearable
+        />
+      </el-form-item>
+    </el-form>
     <template #footer>
 			<el-button type="primary" @click="sendForm" :loading="loading">
 				{{ modalOptions.confirmText }}
@@ -16,8 +49,11 @@
 </template>
 
 <script setup>
+import { ref, nextTick, watch } from "vue";
 import { useModal } from "@/hooks/useModal";
-import PlanForm from "../Form/PlanForm";
+import useFormData from "@/hooks/useFormData";
+import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
+import dayjs from "dayjs";
 import {
   addUpkeep,
   editUpkeep,
@@ -30,7 +66,6 @@
 });
 
 const emits = defineEmits(["ok"]);
-const planFormRef = ref();
 const {
   id,
   visible,
@@ -41,32 +76,82 @@
   closeModal,
 } = useModal({ title: "璁惧淇濆吇璁″垝" });
 
-const openEdit = async (id) => {
-  const { data } = await getUpkeepById(id);
-  openModal(id);
+const deviceOptions = ref([]);
+const formRef = ref();
+const { form, resetForm } = useFormData({
+  deviceLedgerId: undefined, // 璁惧Id
+  deviceName: undefined, // 璁惧鍚嶇О
+  deviceModel: undefined, // 瑙勬牸鍨嬪彿
+  maintenancePlanTime: undefined, // 璁″垝淇濆吇鏃ユ湡
+});
+
+const rules = {
+  deviceLedgerId: [{ required: true, message: "璇烽�夋嫨璁惧", trigger: "change" }],
+  maintenancePlanTime: [
+    { required: true, message: "璇烽�夋嫨璁″垝淇濆吇鏃ユ湡", trigger: "change" },
+  ],
+};
+
+const loadDeviceName = async () => {
+  const { data } = await getDeviceLedger();
+  deviceOptions.value = data;
+};
+
+const setDeviceModel = (id) => {
+  const option = deviceOptions.value.find((item) => item.id === id);
+  form.deviceModel = option ? option.deviceModel : undefined;
+};
+
+const setForm = (data) => {
+  form.deviceLedgerId = data.deviceLedgerId;
+  form.deviceName = data.deviceName;
+  form.deviceModel = data.deviceModel;
+  form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format(
+    "YYYY-MM-DD HH:mm:ss"
+  );
+};
+
+const openEdit = async (editId) => {
+  const { data } = await getUpkeepById(editId);
+  openModal(editId);
   await nextTick();
-  await planFormRef.value.setForm(data);
+  await loadDeviceName();
+  setForm(data);
 };
 
 const sendForm = async () => {
-  loading.value = true;
-  const form = await planFormRef.value.getForm();
-  const { code } = id.value
-    ? await editUpkeep({ id: unref(id), ...form })
-    : await addUpkeep(form);
-  if (code == 200) {
-    ElMessage.success(`${id ? "缂栬緫" : "鏂板"}璁″垝鎴愬姛`);
-    closeModal();
-    emits("ok");
-  }
-  loading.value = false;
+  await formRef.value.validate(async (valid) => {
+    if (!valid) return;
+    loading.value = true;
+    const payload = { ...form };
+    const { code } = id.value
+      ? await editUpkeep({ id: id.value, ...payload })
+      : await addUpkeep(payload);
+    if (code == 200) {
+      ElMessage.success(`${id.value ? "缂栬緫" : "鏂板"}璁″垝鎴愬姛`);
+      closeModal();
+      emits("ok");
+    }
+    loading.value = false;
+  });
 };
 
 const close = () => {
-  planFormRef.value.resetForm();
+  resetForm();
   closeModal();
 };
 
+// load device options whenever the dialog opens (covers add and edit)
+watch(
+  () => visible.value,
+  async (val) => {
+    if (val) {
+      await nextTick();
+      await loadDeviceName();
+    }
+  }
+);
+
 defineExpose({
   openModal,
   openEdit,
diff --git a/src/views/equipmentManagement/upkeep/index.vue b/src/views/equipmentManagement/upkeep/index.vue
index 5612bb6..2659ae0 100644
--- a/src/views/equipmentManagement/upkeep/index.vue
+++ b/src/views/equipmentManagement/upkeep/index.vue
@@ -7,7 +7,6 @@
             style="width: 240px"
             placeholder="璇疯緭鍏ヨ澶囧悕绉�"
             clearable
-            :prefix-icon="Search"
             @change="getTableData"
         />
       </el-form-item>
@@ -35,7 +34,6 @@
             style="width: 240px"
             placeholder="璇疯緭鍏ュ疄闄呬繚鍏讳汉"
             clearable
-            :prefix-icon="Search"
             @change="getTableData"
         />
       </el-form-item>
@@ -48,6 +46,9 @@
       <div class="actions">
         <el-text class="mx-1" size="large">璁惧淇濆吇</el-text>
         <div>
+					<el-button type="success" icon="Van" @click="addPlan">
+						鏂板璁″垝
+					</el-button>
           <el-button
             type="primary"
             icon="Plus"
@@ -55,9 +56,6 @@
             @click="addMaintain"
           >
             鏂板淇濆吇
-          </el-button>
-          <el-button type="success" icon="Van" @click="addPlan">
-            鏂板璁″垝
           </el-button>
           <el-button @click="handleOut">
             瀵煎嚭
@@ -100,16 +98,14 @@
         <template #operation="{ row }">
           <el-button
             type="primary"
-            text
-            icon="editPen"
+            link
             @click="editPlan(row.id)"
           >
             缂栬緫
           </el-button>
           <el-button
             type="danger"
-            text
-            icon="delete"
+						link
             @click="delRepairByIds(row.id)"
           >
             鍒犻櫎
@@ -225,7 +221,7 @@
     dataType: "slot",
     slot: "operation",
     align: "center",
-    width: "200px",
+    width: "150px",
   },
 ]);
 // type == 1瀹為檯淇濆吇鏃堕棿 2璁″垝淇濆吇鏃堕棿
diff --git a/src/views/lavorissue/ledger/index.vue b/src/views/lavorissue/ledger/index.vue
index 19d0e59..385dfe3 100644
--- a/src/views/lavorissue/ledger/index.vue
+++ b/src/views/lavorissue/ledger/index.vue
@@ -9,7 +9,7 @@
             placeholder="璇烽�夋嫨"
             :clearable="false"
         >
-          <el-option :label="item.label" :value="item.value" v-for="(item,index) in jidu" :key="value" />
+          <el-option :label="item.label" :value="item.value" v-for="(item,index) in jidu" :key="item.value" />
         </el-select>
       </el-form-item>
       <el-form-item label="鍛樺伐鍚嶇О:">
@@ -57,10 +57,10 @@
           @pagination="changePage"
       >
         <template #operation="{ row }">
-          <el-button type="primary" text @click="edit(row)" icon="editPen">
+          <el-button type="primary" link @click="edit(row)">
             缂栬緫
           </el-button>
-          <el-button type="primary" :disabled="row.adoptedDate ? true : false" text @click="adopted(row)">
+          <el-button type="success" :disabled="row.adoptedDate ? true : false" link @click="adopted(row)">
             棰嗙敤
           </el-button>
         </template>
@@ -162,7 +162,7 @@
         dataType: "slot",
         slot: "operation",
         align: "center",
-        width: "200px",
+        width: "150px",
       },
     ]
 );

--
Gitblit v1.9.3