From c94826da81b6ebed4a62ed44f6e6bc30cb65f467 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期日, 21 六月 2026 10:39:24 +0800
Subject: [PATCH] fix: 已审核订单的分页组件不展示

---
 src/views/equipmentManagement/ledger/Form.vue |  359 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 343 insertions(+), 16 deletions(-)

diff --git a/src/views/equipmentManagement/ledger/Form.vue b/src/views/equipmentManagement/ledger/Form.vue
index 108dbe4..98e735a 100644
--- a/src/views/equipmentManagement/ledger/Form.vue
+++ b/src/views/equipmentManagement/ledger/Form.vue
@@ -1,5 +1,5 @@
 <template>
-  <el-form :model="form" label-width="100px" :rules="formRules" ref="formRef">
+  <el-form :model="form" label-width="120px" :rules="formRules" ref="formRef">
     <el-row :gutter="20">
       <el-col :span="12">
         <el-form-item label="璁惧鍚嶇О" prop="deviceName">
@@ -8,12 +8,51 @@
       </el-col>
       <el-col :span="12">
         <el-form-item label="瑙勬牸鍨嬪彿" prop="deviceModel">
-          <el-input v-model="form.deviceModel" :disabled="(form.deviceModel != null && operationType === 'edit')" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" />
+          <el-input v-model="form.deviceModel" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" />
         </el-form-item>
       </el-col>
       <el-col :span="12">
         <el-form-item label="璁惧鍝佺墝" prop="deviceBrand">
           <el-input v-model="form.deviceBrand" placeholder="璇疯緭鍏ヨ澶囧搧鐗�" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="璁惧绫诲瀷" prop="type">
+          <el-select
+            v-model="form.type"
+            placeholder="璇烽�夋嫨鎴栬緭鍏ヨ澶囩被鍨�"
+            clearable
+            filterable
+            allow-create
+            default-first-option
+            style="width: 100%"
+            @change="handleDeviceTypeChange"
+          >
+            <el-option
+              v-for="item in deviceTypeOptions"
+              :key="item"
+              :label="item"
+              :value="item"
+            />
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="宸ュ簭" prop="productProcessId">
+          <el-select
+            v-model="form.productProcessId"
+            placeholder="璇烽�夋嫨宸ュ簭"
+            clearable
+            filterable
+            style="width: 100%"
+          >
+            <el-option
+              v-for="item in processOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
         </el-form-item>
       </el-col>
       <el-col :span="12">
@@ -32,14 +71,26 @@
         </el-form-item>
       </el-col>
       <el-col :span="12">
-        <el-form-item label="鍚敤鎶樻棫" prop="enableDepreciation">
-          <el-switch v-model="form.enableDepreciation" :active-value="true" :inactive-value="false" />
+        <el-form-item label="鍚敤鎶樻棫" prop="isDepr">
+          <el-switch v-model="form.isDepr" :active-value="1" :inactive-value="2" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12" v-if="form.isDepr === 1">
+        <el-form-item label="姣忓勾鎶樻棫閲戦" prop="annualDepreciationAmount">
+          <el-input-number 
+            :step="0.01" 
+            :min="0" 
+            style="width: 100%"
+            v-model="form.annualDepreciationAmount"
+            placeholder="璇疯緭鍏ユ瘡骞存姌鏃ч噾棰�"
+          />
         </el-form-item>
       </el-col>
       <el-col :span="12">
         <el-form-item label="鏁伴噺" prop="number">
-          <el-input-number :step="0.01" :min="0" style="width: 100%"
+          <el-input-number :min="1" style="width: 100%"
             v-model="form.number"
+													 disabled
             placeholder="璇疯緭鍏ユ暟閲�"
             @change="mathNum"
           />
@@ -81,7 +132,9 @@
             @change="mathNum"
           >
             <el-option label="1" :value="1" />
+            <el-option label="3" :value="3" />
             <el-option label="6" :value="6" />
+            <el-option label="9" :value="9" />
             <el-option label="13" :value="13" />
           </el-select>
         </el-form-item>
@@ -114,53 +167,137 @@
           />
         </el-form-item>
       </el-col>
+			<el-col :span="12">
+				<el-form-item label="棰勮杩愯鏃堕棿" prop="planRuntimeTime">
+					<el-date-picker
+						style="width: 100%"
+						v-model="form.planRuntimeTime"
+						format="YYYY-MM-DD"
+						value-format="YYYY-MM-DD"
+						type="date"
+						placeholder="璇烽�夋嫨褰曞叆鏃ユ湡"
+						clearable
+					/>
+				</el-form-item>
+			</el-col>
+      <el-col :span="24">
+        <el-form-item label="璁惧鍥剧墖" prop="deviceImage">
+          <div v-if="displayedExistingProblems.length" class="problem-existing-wrap">
+            <div v-for="img in displayedExistingProblems" :key="img.id" class="problem-thumb">
+              <el-image :src="img.url" fit="cover" class="problem-thumb-img" @click="previewProblem(img.url)" />
+              <el-icon class="problem-thumb-remove" @click.stop="markProblemRemove(img.id)"><Close /></el-icon>
+            </div>
+          </div>
+          <el-upload
+            class="repair-attachment-upload"
+            v-model:file-list="attachmentFileList"
+            drag
+            multiple
+            :auto-upload="false"
+            :limit="9"
+            accept="image/png,image/jpeg,image/jpg"
+            :before-upload="beforeUpload"
+          >
+            <el-icon class="repair-upload-icon"><UploadFilled /></el-icon>
+            <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴� <em>鐐瑰嚮閫夋嫨鏂囦欢</em></div>
+            <template #tip>
+              <div class="el-upload__tip">
+                鏀寔 png / jpg / jpeg锛屽崟寮犱笉瓒呰繃 50MB锛屾渶澶� 9 寮�
+              </div>
+            </template>
+          </el-upload>
+        </el-form-item>
+      </el-col>
     </el-row>
   </el-form>
 </template>
 
 <script setup>
 import useFormData from "@/hooks/useFormData";
-// import useUserStore from "@/store/modules/user";
-import { getLedgerById } from "@/api/equipmentManagement/ledger";
+import { getLedgerById, getLedgerFileList, uploadLedgerFile, deleteLedgerFile } from "@/api/equipmentManagement/ledger";
+import { processList } from "@/api/productionManagement/productionProcess";
 import dayjs from "dayjs";
 import {
   calculateTaxIncludeTotalPrice,
   calculateTaxExclusiveTotalPrice,
 } from "@/utils/summarizeTable";
 import { ElMessage } from "element-plus";
-import {ref} from "vue";
+import { ref, onMounted, getCurrentInstance } from "vue";
+import { UploadFilled, Close } from "@element-plus/icons-vue";
+import { getToken } from "@/utils/auth";
 
 defineOptions({
   name: "璁惧鍙拌处琛ㄥ崟",
 });
 const formRef = ref(null);
 const operationType = ref('');
+// 璁惧绫诲瀷鍥哄畾閫夐」
+const deviceTypeOptions = ref([
+  '鐢熶骇璁惧',
+  '鍔炲叕璁惧',
+  '妫�娴嬭澶�',
+  '杩愯緭璁惧',
+  '鍏朵粬璁惧'
+]);
+const processOptions = ref([]);
 const formRules = {
 	deviceName: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
 	deviceModel: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
+	type: [{ required: true, trigger: "change", message: "璇烽�夋嫨鎴栬緭鍏ヨ澶囩被鍨�" }],
 	supplierName: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
 	unit: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
 	number: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
 	taxIncludingPriceUnit: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
 	taxRate: [{ required: true, trigger: "change", message: "璇疯緭鍏�" }],
+	planRuntimeTime: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }],
+	annualDepreciationAmount: [
+		{ 
+			validator: (rule, value, callback) => {
+				if (form.isDepr === 1 && (value === undefined || value === null || value === '')) {
+					callback(new Error('鍚敤鎶樻棫鏃讹紝璇疯緭鍏ユ瘡骞存姌鏃ч噾棰�'));
+				} else {
+					callback();
+				}
+			}, 
+			trigger: "blur" 
+		}
+	],
 }
 
 const { form, resetForm } = useFormData({
   deviceName: undefined, // 璁惧鍚嶇О
   deviceModel: undefined, // 瑙勬牸鍨嬪彿
   deviceBrand: undefined, // 璁惧鍝佺墝
+  type: undefined, // 璁惧绫诲瀷
+  productProcessId: undefined, // 宸ュ簭ID
   supplierName: undefined, // 渚涘簲鍟�
   storageLocation: undefined, // 瀛樻斁浣嶇疆
-  enableDepreciation: false, // 鏄惁鍚敤鎶樻棫
+  isDepr: 2, // 鏄惁鍚敤鎶樻棫 1-鏄� 2-鍚�
+  annualDepreciationAmount: undefined, // 姣忓勾鎶樻棫閲戦
   unit: undefined, // 鍗曚綅
-  number: undefined, // 鏁伴噺
+  number: 1, // 鏁伴噺
   taxIncludingPriceUnit: undefined, // 鍚◣鍗曚环
   taxIncludingPriceTotal: undefined, // 鍚◣鎬讳环
   taxRate: undefined, // 绋庣巼
   unTaxIncludingPriceTotal: undefined, // 涓嶅惈绋庢�讳环
   // createUser: useUserStore().nickName, // 褰曞叆浜�
   createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 褰曞叆鏃ユ湡
+	planRuntimeTime: dayjs().format("YYYY-MM-DD"), // 褰曞叆鏃ユ湡
 });
+
+const attachmentFileList = ref([]);
+const existingProblemImages = ref([]);
+const pendingRemoveProblemIds = ref([]);
+
+const displayedExistingProblems = computed(() =>
+  existingProblemImages.value.filter((img) => !pendingRemoveProblemIds.value.includes(img.id))
+);
+
+const markProblemRemove = (fileId) => {
+  if (!pendingRemoveProblemIds.value.includes(fileId)) {
+    pendingRemoveProblemIds.value.push(fileId);
+  }
+};
 
 const loadForm = async (id) => {
 	if (id) {
@@ -171,26 +308,88 @@
     form.deviceName = data.deviceName;
     form.deviceModel = data.deviceModel;
     form.deviceBrand = data.deviceBrand;
+    form.type = data.type;
+    const processName = data.productProcessName || data.processName || data.process;
+    form.productProcessId = data.productProcessId;
+    if (!form.productProcessId && processName) {
+      const matched = processOptions.value.find(item => item.label === processName);
+      form.productProcessId = matched?.value;
+    }
+    ensureProcessOptionExists(form.productProcessId, processName);
     form.supplierName = data.supplierName;
     form.storageLocation = data.storageLocation;
-    form.enableDepreciation = data.enableDepreciation;
+    form.isDepr = data.isDepr;
+    form.annualDepreciationAmount = data.annualDepreciationAmount;
     form.unit = data.unit;
-    form.number = data.number;
+    form.number = 1;
     form.taxIncludingPriceUnit = data.taxIncludingPriceUnit;
     form.taxIncludingPriceTotal = data.taxIncludingPriceTotal;
     form.taxRate = data.taxRate;
     form.unTaxIncludingPriceTotal = data.unTaxIncludingPriceTotal;
     form.createTime = data.createTime;
+    // 棰勮杩愯鏃堕棿锛氬悗绔繑鍥炲悗杞负 YYYY-MM-DD 浠ヤ究鏃ユ湡閫夋嫨鍣ㄦ纭睍绀�
+    if (data.planRuntimeTime) {
+      form.planRuntimeTime = dayjs(data.planRuntimeTime).format('YYYY-MM-DD');
+    } else {
+      form.planRuntimeTime = undefined;
+    }
+  }
+  
+  existingProblemImages.value = [];
+  pendingRemoveProblemIds.value = [];
+  attachmentFileList.value = [];
+  if (id) {
+    try {
+      const res = await getLedgerFileList(id);
+      const list = Array.isArray(res?.data) ? res.data : [];
+      existingProblemImages.value = list.map((item) => ({
+        id: item.id,
+        name: item.name,
+        url: getFileAccessUrl(item),
+      }));
+    } catch {
+      existingProblemImages.value = [];
+    }
+  }
+};
+
+const ensureProcessOptionExists = (id, name) => {
+  if (!id) return;
+  if (!processOptions.value.some(item => item.value === id)) {
+    processOptions.value.push({
+      value: id,
+      label: name || `${id}`,
+    });
+  }
+};
+
+const getProcessOptions = async () => {
+  try {
+    const { code, data } = await processList({});
+    if (code === 200 && Array.isArray(data)) {
+      processOptions.value = data
+        .filter(item => item?.id !== undefined && item?.id !== null)
+        .map(item => ({
+          value: item.id,
+          label: item?.name || `${item.id}`,
+        }));
+      ensureProcessOptionExists(form.productProcessId);
+    }
+  } catch (error) {
+    processOptions.value = [];
+  }
+};
+
+const handleDeviceTypeChange = (value) => {
+  // 濡傛灉杈撳叆鐨勬柊鍊间笉鍦ㄥ浐瀹氶�夐」涓紝鍒欐坊鍔犲埌閫夐」鍒楄〃
+  if (value && !deviceTypeOptions.value.includes(value)) {
+    deviceTypeOptions.value.push(value);
   }
 };
 
 const mathNum = () => {
   if (!form.taxIncludingPriceUnit) {
     ElMessage.error("璇疯緭鍏ュ崟浠�");
-    return;
-  }
-  if (!form.number) {
-    ElMessage.error("璇疯緭鍏ユ暟閲�");
     return;
   }
   form.taxIncludingPriceTotal = calculateTaxIncludeTotalPrice(
@@ -216,6 +415,81 @@
   clearValidate();
 };
 
+onMounted(() => {
+  getProcessOptions();
+});
+
+const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload");
+const headers = ref({ Authorization: "Bearer " + getToken() });
+const ATTACH_MAX_MB = 50;
+
+const beforeUpload = (rawFile) => {
+  const okType = ["image/jpeg", "image/jpg", "image/png"].includes(rawFile.type);
+  if (!okType) {
+    ElMessage.error("鍙兘涓婁紶 png / jpg / jpeg 鍥剧墖");
+    return false;
+  }
+  const maxBytes = ATTACH_MAX_MB * 1024 * 1024;
+  if (rawFile.size > maxBytes) {
+    ElMessage.error(`鍗曚釜鏂囦欢涓嶈兘瓒呰繃 ${ATTACH_MAX_MB}MB`);
+    return false;
+  }
+  return true;
+};
+
+const submitFiles = async (ledgerId) => {
+  for (const fileId of pendingRemoveProblemIds.value) {
+    await deleteLedgerFile(fileId);
+  }
+  pendingRemoveProblemIds.value = [];
+
+  const rows = attachmentFileList.value || [];
+  const files = rows.map((f) => f.raw).filter(Boolean);
+  if (!files.length || ledgerId == null) return;
+  
+  for (const file of files) {
+    const fd = new FormData();
+    fd.append("file", file);
+    fd.append("deviceLedgerId", String(ledgerId));
+    // 16 is the FileNameType for EQUIPMENT_LEDGER that we added
+    fd.append("fileType", "16");
+    const res = await uploadLedgerFile(fd);
+    if (res.code !== 200) {
+      throw new Error(res.msg || "闄勪欢涓婁紶澶辫触");
+    }
+  }
+  attachmentFileList.value = [];
+};
+
+const getFileAccessUrl = (file = {}) => {
+  let raw = file?.link || file?.url || "";
+  if (String(raw).startsWith("http")) return raw;
+  const javaApi = getCurrentInstance()?.proxy?.javaApi || import.meta.env.VITE_APP_BASE_API || "/dev-api";
+  let fileUrl = raw;
+  if (fileUrl.indexOf("\\") > -1) {
+    const lowerPath = fileUrl.toLowerCase();
+    const uploadPathIndex = lowerPath.indexOf("uploadpath");
+    if (uploadPathIndex > -1) {
+      fileUrl = fileUrl.substring(uploadPathIndex).replace(/\\/g, "/");
+    } else {
+      fileUrl = fileUrl.replace(/\\/g, "/");
+    }
+  }
+  fileUrl = fileUrl.replace(/^\/?uploadPath/, "/profile");
+  if (fileUrl.startsWith("upload/")) {
+    fileUrl = "/profile/" + fileUrl;
+  }
+  if (!fileUrl.startsWith("http")) {
+    if (!fileUrl.startsWith("/")) fileUrl = "/" + fileUrl;
+    fileUrl = javaApi + fileUrl;
+  }
+  return fileUrl;
+};
+
+const previewProblem = (url) => {
+  window.open(url, "_blank");
+};
+
 defineExpose({
   form,
   loadForm,
@@ -223,5 +497,58 @@
   clearValidate,
   resetFormAndValidate,
 	formRef,
+  submitFiles,
 });
 </script>
+
+<style lang="scss" scoped>
+.repair-attachment-upload {
+  width: 100%;
+  :deep(.el-upload) {
+    width: 100%;
+  }
+  :deep(.el-upload-dragger) {
+    width: 100%;
+    padding: 24px 16px;
+  }
+}
+.repair-upload-icon {
+  font-size: 48px;
+  color: var(--el-color-primary);
+  margin-bottom: 8px;
+}
+
+.problem-existing-wrap {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+  margin-bottom: 12px;
+}
+
+.problem-thumb {
+  position: relative;
+  width: 88px;
+  height: 88px;
+  border-radius: 6px;
+  overflow: hidden;
+  border: 1px solid var(--el-border-color);
+}
+
+.problem-thumb-img {
+  width: 100%;
+  height: 100%;
+  cursor: pointer;
+}
+
+.problem-thumb-remove {
+  position: absolute;
+  top: 2px;
+  right: 2px;
+  font-size: 16px;
+  color: #fff;
+  background: rgba(0, 0, 0, 0.45);
+  border-radius: 50%;
+  padding: 2px;
+  cursor: pointer;
+}
+</style>

--
Gitblit v1.9.3