From a175709baa7777575d054f928d4d2d029a04bd60 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 29 十二月 2025 17:41:06 +0800
Subject: [PATCH] 陕西昭德-app巡检上传修改

---
 src/pages/management/mould/equipmentRequisitionDialog.vue |  853 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 853 insertions(+), 0 deletions(-)

diff --git a/src/pages/management/mould/equipmentRequisitionDialog.vue b/src/pages/management/mould/equipmentRequisitionDialog.vue
new file mode 100644
index 0000000..d92e779
--- /dev/null
+++ b/src/pages/management/mould/equipmentRequisitionDialog.vue
@@ -0,0 +1,853 @@
+<template>
+  <u-popup
+    :show="visible"
+    mode="center"
+    :closeable="true"
+    @close="handleClose"
+    :round="10"
+    width="90%"
+    :safe-area-inset-bottom="true"
+  >
+    <view class="popup-content">
+      <view class="popup-header">
+        <text class="popup-title">{{ isReturnMode ? '璁惧褰掕繕' : isEdit ? '缂栬緫璁惧棰嗙敤' : '鏂板璁惧棰嗙敤' }}</text>
+      </view>
+      
+      <scroll-view class="form-scroll" scroll-y>
+        <u-form :model="form" :rules="rules" ref="formRef" label-width="110" input-align="right">
+          <u-form-item label="棰嗙敤浜�" prop="userId" border-bottom required>
+            <u-input
+              v-model="displayUserName"
+              placeholder="璇烽�夋嫨棰嗙敤浜�"
+              readonly
+              @click="showUserPicker = true"
+              :disabled="isViewMode || isReturnMode"
+            />
+            <template #right>
+              <u-icon name="arrow-right" @click="showUserPicker = true"></u-icon>
+            </template>
+          </u-form-item>
+          
+          <u-form-item label="璁惧鍚嶇О" prop="equipmentId" border-bottom required>
+            <u-input
+              v-model="displayEquipmentName"
+              placeholder="璇烽�夋嫨璁惧鍚嶇О"
+              readonly
+              @click="showEquipmentPicker = true"
+              :disabled="isViewMode || isReturnMode"
+            />
+            <template #right>
+              <u-icon name="arrow-right" @click="showEquipmentPicker = true"></u-icon>
+            </template>
+          </u-form-item>
+          
+          <u-form-item label="鏄惁涓烘秷鑰楀搧" prop="consumables" border-bottom required>
+            <u-input
+              v-model="displayConsumables"
+              placeholder="璇烽�夋嫨鏄惁涓烘秷鑰楀搧"
+              readonly
+              @click="showConsumablesPicker = true"
+              :disabled="isViewMode || isReturnMode"
+            />
+            <template #right>
+              <u-icon name="arrow-right" @click="showConsumablesPicker = true"></u-icon>
+            </template>
+          </u-form-item>
+          
+          <u-form-item v-if="!isReturnMode && formData.status !== 2" label="棰嗙敤鏁伴噺" prop="usageQuantity" border-bottom required>
+            <view class="number-box-wrapper">
+              <u-number-box
+                v-model="form.usageQuantity"
+                :min="1"
+                :max="maxQuantity || 999"
+                :disabled="isViewMode"
+                integer
+                @change="onUsageQuantityChange"
+              />
+              <text v-if="maxQuantity !== null" class="info-text">(鏈�澶歿{ maxQuantity }}鍙�)</text>
+            </view>
+          </u-form-item>
+          
+          <u-form-item v-if="isReturnMode" label="鏈褰掕繕鏁伴噺" prop="returnQuantity" border-bottom required>
+            <view class="number-box-wrapper">
+              <u-number-box
+                v-model="form.returnQuantity"
+                :min="1"
+                :max="Math.max(1, remainingReturnQuantity)"
+                :disabled="remainingReturnQuantity <= 0"
+                integer
+              />
+              <text class="info-text" v-if="remainingReturnQuantity > 0">(鏈�澶歿{ remainingReturnQuantity }}鍙�)</text>
+              <text class="info-text" v-else>(宸插叏閮ㄥ綊杩�)</text>
+            </view>
+          </u-form-item>
+          
+          <u-form-item v-if="!isReturnMode" label="浣跨敤寮�濮嬫椂闂�" prop="usageStartTime" border-bottom required>
+            <u-input
+              v-model="form.usageStartTime"
+              placeholder="璇烽�夋嫨寮�濮嬫椂闂�"
+              readonly
+              @click="showDatePicker('usageStartTime')"
+            />
+            <template #right>
+              <u-icon name="arrow-right" @click="showDatePicker('usageStartTime')"></u-icon>
+            </template>
+          </u-form-item>
+
+          <u-form-item v-if="isReturnMode" label="褰掕繕鏃堕棿" prop="returnTime" border-bottom required>
+            <u-input
+              v-model="form.returnTime"
+              placeholder="璇烽�夋嫨褰掕繕鏃堕棿"
+              readonly
+              @click="showDatePicker('returnTime')"
+            />
+            <template #right>
+              <u-icon name="arrow-right" @click="showDatePicker('returnTime')"></u-icon>
+            </template>
+          </u-form-item>
+          
+          <u-form-item label="澶囨敞" border-bottom>
+            <u-textarea
+              v-model="form.remarks"
+              placeholder="璇疯緭鍏ュ娉�"
+              :disabled="isViewMode"
+              :autoHeight="true"
+              count
+            />
+          </u-form-item>
+        </u-form>
+      </scroll-view>
+      
+      <view class="popup-footer">
+        <u-button @click="handleClose" :customStyle="{ marginRight: '10px', flex: 1 }" :disabled="isSubmitting">鍙栨秷</u-button>
+        <u-button type="primary" @click="debouncedSubmit" v-if="!isViewMode" :customStyle="{ flex: 1 }" :loading="isSubmitting">纭畾</u-button>
+      </view>
+    </view>
+    
+    <!-- 鏃ユ湡閫夋嫨鍣� -->
+    <u-datetime-picker
+      :show="showDatePickerVisible"
+      v-model="datePickerValue"
+      mode="date"
+      @confirm="onDateConfirm"
+      @cancel="showDatePickerVisible = false"
+    />
+    
+    <!-- 鐢ㄦ埛閫夋嫨鍣� -->
+    <up-action-sheet
+      :show="showUserPicker"
+      :actions="userActionList"
+      title="閫夋嫨棰嗙敤浜�"
+      @select="onUserSelect"
+      @close="showUserPicker = false"
+    />
+    
+    <!-- 璁惧閫夋嫨鍣� -->
+    <up-action-sheet
+      :show="showEquipmentPicker"
+      :actions="equipmentActionList"
+      title="閫夋嫨璁惧鍚嶇О"
+      @select="onEquipmentSelect"
+      @close="showEquipmentPicker = false"
+    />
+    
+    <!-- 娑堣�楀搧閫夋嫨鍣� -->
+    <up-action-sheet
+      :show="showConsumablesPicker"
+      :actions="consumablesActionList"
+      title="閫夋嫨鏄惁涓烘秷鑰楀搧"
+      @select="onConsumablesSelect"
+      @close="showConsumablesPicker = false"
+    />
+  </u-popup>
+</template>
+
+<script setup>
+import { ref, watch, computed, onMounted, nextTick } from "vue";
+import { useToast, useModal } from "@/utils/uviewplus";
+import { getEquipmentList, userListAll } from "@/api/publicApi/index.js";
+import { addOrEditUsageRecord } from "@/api/equipment/requisition/index.js";
+
+import useUserStore from "@/store/modules/user";
+
+const { showToast } = useToast();
+const { showModal } = useModal();
+
+const userStore = useUserStore();
+let userList = ref([]);
+
+// 鑾峰彇鐢ㄦ埛鍒楄〃
+const fetchUserList = async () => {
+  try {
+    const res = await userListAll();
+    if (res.code === 200) {
+      userList.value = res.data || res.rows || [];
+      console.log('鐢ㄦ埛鍒楄〃鑾峰彇鎴愬姛:', userList.value);
+    } else {
+      showToast('鑾峰彇鐢ㄦ埛鍒楄〃澶辫触', 'error');
+    }
+  } catch (error) {
+    console.error('鑾峰彇鐢ㄦ埛鍒楄〃澶辫触:', error);
+    showToast('鑾峰彇鐢ㄦ埛鍒楄〃澶辫触', 'error');
+  }
+};
+
+// 閫夋嫨鍣ㄦ樉绀虹姸鎬�
+const showUserPicker = ref(false);
+const showEquipmentPicker = ref(false);
+const showConsumablesPicker = ref(false);
+
+// 鐢ㄦ埛閫夋嫨鍒楄〃锛堢敤浜� action-sheet锛�
+const userActionList = computed(() => {
+  return userList.value.map(item => ({
+    name: item.nickName || item.nickname || item.userName || item.name || '鏈煡',
+    value: item.userId || item.id
+  }));
+});
+
+// 璁惧閫夋嫨鍒楄〃锛堢敤浜� action-sheet锛�
+const equipmentActionList = computed(() => {
+  return equipmentList.value.map(item => ({
+    name: item.equipmentName || item.name || '鏈煡璁惧',
+    value: item.id || item.equipmentId
+  }));
+});
+
+// 鏄剧ず鐢ㄧ殑鏂囨湰锛堜娇鐢� ref 纭繚鍝嶅簲寮忥級
+const displayUserName = ref('');
+const displayEquipmentName = ref('');
+const displayConsumables = ref('');
+
+// 娑堣�楀搧閫夋嫨鍒楄〃
+const consumablesActionList = computed(() => [
+  { name: '鏄�', value: true },
+  { name: '鍚�', value: false }
+]);
+
+// 鐩戝惉 form 鍙樺寲锛屾洿鏂版樉绀烘枃鏈�
+watch(
+  () => form.value.userId,
+  (userId) => {
+    if (userId) {
+      const user = userList.value.find(u => {
+        const uId = u.userId || u.id;
+        return uId == userId || String(uId) === String(userId);
+      });
+      displayUserName.value = user ? (user.nickName || user.nickname || user.userName || user.name) : '';
+    } else {
+      displayUserName.value = '';
+    }
+  },
+  { immediate: true }
+);
+
+watch(
+  () => form.value.equipmentId,
+  (equipmentId) => {
+    if (equipmentId) {
+      const equipment = equipmentList.value.find(e => {
+        const eId = e.id || e.equipmentId;
+        return eId == equipmentId || String(eId) === String(equipmentId);
+      });
+      displayEquipmentName.value = equipment ? (equipment.equipmentName || equipment.name) : '';
+    } else {
+      displayEquipmentName.value = '';
+    }
+  },
+  { immediate: true }
+);
+
+watch(
+  () => form.value.consumables,
+  (consumables) => {
+    if (consumables === true || consumables === 'true' || consumables === 1) {
+      displayConsumables.value = '鏄�';
+    } else if (consumables === false || consumables === 'false' || consumables === 0) {
+      displayConsumables.value = '鍚�';
+    } else {
+      displayConsumables.value = '';
+    }
+  },
+  { immediate: true }
+);
+
+// 鐢ㄦ埛閫夋嫨
+const onUserSelect = (item) => {
+  const userId = item.value || item.userId || item.id;
+  form.value.userId = userId;
+  // 绔嬪嵆鏇存柊鏄剧ず鏂囨湰
+  const user = userList.value.find(u => {
+    const uId = u.userId || u.id;
+    return uId == userId || String(uId) === String(userId);
+  });
+  displayUserName.value = user ? (user.nickName || user.nickname || user.userName || user.name) : '';
+  showUserPicker.value = false;
+  // 閫夋嫨鐢ㄦ埛鍚庤幏鍙栬澶囧垪琛�
+  getEquipment();
+  nextTick(() => {
+    if (formRef.value) {
+      formRef.value.validateField('userId');
+    }
+  });
+};
+
+// 璁惧閫夋嫨
+const onEquipmentSelect = (item) => {
+  const equipmentId = item.value || item.id || item.equipmentId;
+  form.value.equipmentId = equipmentId;
+  // 绔嬪嵆鏇存柊鏄剧ず鏂囨湰
+  const equipment = equipmentList.value.find(e => {
+    const eId = e.id || e.equipmentId;
+    return eId == equipmentId || String(eId) === String(equipmentId);
+  });
+  displayEquipmentName.value = equipment ? (equipment.equipmentName || equipment.name) : '';
+  showEquipmentPicker.value = false;
+  nextTick(() => {
+    if (formRef.value) {
+      formRef.value.validateField('equipmentId');
+    }
+  });
+};
+
+// 娑堣�楀搧閫夋嫨
+const onConsumablesSelect = (item) => {
+  const consumables = item.value !== undefined ? item.value : (item.name === '鏄�' ? true : false);
+  form.value.consumables = consumables;
+  // 绔嬪嵆鏇存柊鏄剧ず鏂囨湰
+  displayConsumables.value = consumables ? '鏄�' : '鍚�';
+  showConsumablesPicker.value = false;
+  nextTick(() => {
+    if (formRef.value) {
+      formRef.value.validateField('consumables');
+    }
+  });
+};
+
+// 棰嗙敤鏁伴噺鍙樺寲
+const onUsageQuantityChange = (value) => {
+  // 纭繚鍊兼槸鏁板瓧绫诲瀷
+  const numValue = Number(value) || 1;
+  form.value.usageQuantity = numValue;
+  // 鍙湁鍦ㄥ�兼湁鏁堟椂鎵嶈Е鍙戦獙璇侊紝閬垮厤榛樿鍊�1瑙﹀彂閿欒鎻愮ず
+  if (numValue >= 1) {
+    nextTick(() => {
+      if (formRef.value) {
+        // 娓呴櫎涔嬪墠鐨勯敊璇紝鐒跺悗閲嶆柊楠岃瘉
+        formRef.value.clearValidate('usageQuantity');
+        formRef.value.validateField('usageQuantity');
+      }
+    });
+  }
+};
+
+// 鑾峰彇璁惧鍒楄〃
+const equipmentList = ref([]);
+// 鑾峰彇鏈�鏂版暟鎹�
+const getEquipment = async () => {
+  try {
+    const res = await getEquipmentList();
+    if (res.code === 200) {
+      equipmentList.value = res.data || res.rows || [];
+      console.log('璁惧鍒楄〃鑾峰彇鎴愬姛:', equipmentList.value);
+    } else {
+      showToast("鑾峰彇璁惧鍒楄〃澶辫触", 'error');
+    }
+  } catch (error) {
+    console.error("鑾峰彇璁惧鍒楄〃澶辫触:", error);
+    showToast("鑾峰彇璁惧鍒楄〃澶辫触", 'error');
+  }
+};
+const props = defineProps({
+  modelValue: Boolean,
+  formData: {
+    type: Object,
+    default: () => ({}),
+  },
+  addOrEdit: {
+    type: String,
+    default: "add",
+  },
+});
+
+// 榛樿琛ㄥ崟鍒濆鍊�
+const defaultForm = {
+  userId: "",
+  equipmentId: "",
+  consumables: false,
+  usageQuantity: 1,
+  usageStartTime: "",
+  returnQuantity: 1,
+  returnTime: "",
+  remarks: "",
+};
+const form = ref({ ...defaultForm });
+
+const maxQuantity = computed(() => {
+  if (!form.value.equipmentId) return 0;
+  const eq = equipmentList.value.find(
+    (item) => item.id == form.value.equipmentId
+  );
+  // 闃叉涓�0鎴栬礋鏁帮紝鏈�灏忎负1
+  return eq && eq.quantity > 0 ? eq.quantity : 999;
+});
+const emit = defineEmits(["update:modelValue", "submit"]);
+
+const visible = computed({
+  get: () => {
+    console.log('寮圭獥 visible get:', props.modelValue);
+    return props.modelValue;
+  },
+  set: (v) => {
+    console.log('寮圭獥 visible set:', v);
+    emit("update:modelValue", v);
+  },
+});
+
+// 鐩戝惉 modelValue 鍙樺寲
+watch(
+  () => props.modelValue,
+  (newVal) => {
+    console.log('寮圭獥 modelValue 鍙樺寲:', newVal);
+  },
+  { immediate: true }
+);
+
+// 鐩戝惉璁惧閫夋嫨鍙樺寲
+watch(
+  () => form.value.equipmentId,
+  (newId) => {
+    if (newId) {
+      const eq = equipmentList.value.find(item => item.id == newId);
+    }
+  }
+);
+const isViewMode = computed(
+  () => props.addOrEdit === "view" || props.addOrEdit === "viewRow"
+);
+
+// 鍒ゆ柇鏄惁涓哄綊杩樻ā寮�
+const isReturnMode = computed(() => props.addOrEdit === "return");
+
+// 璁$畻鍓╀綑鍙綊杩樻暟閲�
+const remainingReturnQuantity = computed(() => {
+  if (!isReturnMode.value || !props.formData.usageQuantity) return 0;
+
+  const totalUsageQuantity = props.formData.usageQuantity || 0; // 鎬讳娇鐢ㄦ暟閲�
+  const alreadyReturnedQuantity = props.formData.totalReturnNo || 0; // 宸插綊杩樻暟閲�
+  const remaining = totalUsageQuantity - alreadyReturnedQuantity; // 鍓╀綑鍙綊杩樻暟閲�
+
+  return Math.max(0, remaining); // 纭繚涓嶄负璐熸暟
+});
+
+const isEdit = computed(() => !!props.formData?.id);
+const formRef = ref();
+const isSubmitting = ref(false);
+
+// 鏃ユ湡閫夋嫨鍣�
+const showDatePickerVisible = ref(false);
+const datePickerValue = ref(Date.now());
+const currentDateField = ref('');
+
+// 鏄剧ず鏃ユ湡閫夋嫨鍣�
+const showDatePicker = (field) => {
+  if (isViewMode.value) return;
+  currentDateField.value = field;
+  if (form.value[field]) {
+    datePickerValue.value = new Date(form.value[field]).getTime();
+  } else {
+    datePickerValue.value = Date.now();
+  }
+  showDatePickerVisible.value = true;
+};
+
+// 鏃ユ湡纭
+const onDateConfirm = (e) => {
+  const date = new Date(e.value);
+  const year = date.getFullYear();
+  const month = String(date.getMonth() + 1).padStart(2, "0");
+  const day = String(date.getDate()).padStart(2, "0");
+  form.value[currentDateField.value] = `${year}-${month}-${day}`;
+  showDatePickerVisible.value = false;
+};
+
+// 鑾峰彇褰撳墠鏃ユ湡锛圷YYY-MM-DD鏍煎紡锛�
+const getCurrentDate = () => {
+  const now = new Date();
+  const year = now.getFullYear();
+  const month = String(now.getMonth() + 1).padStart(2, "0");
+  const day = String(now.getDate()).padStart(2, "0");
+  return `${year}-${month}-${day}`;
+};
+
+// 纭繚鍒濆鍖栨椂鑾峰彇鏁版嵁
+onMounted(() => {
+  fetchUserList();
+  getEquipment();
+});
+
+
+// 鏍囪鏄惁宸茬粡鍒濆鍖栵紝閬垮厤 watch 瑕嗙洊鐢ㄦ埛閫夋嫨
+const isInitialized = ref(false);
+
+watch(
+  () => props.formData,
+  (val) => {
+    // 鍙湪鍒濆鍖栨椂鎴栬�� formData 鏈夊疄闄呭彉鍖栨椂鎵嶆洿鏂�
+    if (!isInitialized.value) {
+      if (val && Object.keys(val).length > 0) {
+        // 鍚堝苟鐜版湁鍊硷紝閬垮厤瑕嗙洊鐢ㄦ埛宸查�夋嫨鐨勫��
+        form.value = { ...defaultForm, ...val };
+
+        // 褰掕繕妯″紡鍒濆鍖�
+        if (isReturnMode.value) {
+          form.value.returnTime = getCurrentDate();
+          const maxReturnQuantity = remainingReturnQuantity.value;
+          form.value.returnQuantity =
+            maxReturnQuantity > 0 ? Math.min(1, maxReturnQuantity) : 0;
+        }
+      } else {
+        form.value = { ...defaultForm };
+      }
+      isInitialized.value = true;
+      console.log('formData watch 鍒濆鍖栵紝form.value:', form.value);
+    }
+  },
+  { immediate: true }
+);
+
+// 鐩戝惉寮圭獥鎵撳紑锛岄噸缃垵濮嬪寲鏍囪骞惰幏鍙栨暟鎹�
+watch(
+  () => props.modelValue,
+  (newVal) => {
+    if (newVal) {
+      // 寮圭獥鎵撳紑鏃堕噸缃垵濮嬪寲鏍囪锛屽厑璁� formData watch 閲嶆柊鍒濆鍖�
+      isInitialized.value = false;
+      // 寮圭獥鎵撳紑鏃堕噸鏂拌幏鍙栨暟鎹�
+      if (userList.value.length === 0) {
+        fetchUserList();
+      }
+      if (equipmentList.value.length === 0) {
+        getEquipment();
+      }
+    } else {
+      // 寮圭獥鍏抽棴鏃堕噸缃�
+      isInitialized.value = false;
+    }
+  }
+);
+
+const rules = computed(() => {
+  const baseRules = {
+    userId: [
+      { 
+        required: true, 
+        message: "璇烽�夋嫨棰嗙敤浜�", 
+        trigger: "change",
+        validator: (rule, value, callback) => {
+          if (!form.value.userId) {
+            callback(new Error("璇烽�夋嫨棰嗙敤浜�"));
+          } else {
+            callback();
+          }
+        }
+      }
+    ],
+    equipmentId: [
+      { 
+        required: true, 
+        message: "璇烽�夋嫨璁惧鍚嶇О", 
+        trigger: "change",
+        validator: (rule, value, callback) => {
+          if (!form.value.equipmentId) {
+            callback(new Error("璇烽�夋嫨璁惧鍚嶇О"));
+          } else {
+            callback();
+          }
+        }
+      }
+    ],
+    consumables: [
+      { 
+        required: true, 
+        message: "璇烽�夋嫨鏄惁涓烘秷鑰楀搧", 
+        trigger: "change",
+        validator: (rule, value, callback) => {
+          if (form.value.consumables === undefined || form.value.consumables === null || form.value.consumables === '') {
+            callback(new Error("璇烽�夋嫨鏄惁涓烘秷鑰楀搧"));
+          } else {
+            callback();
+          }
+        }
+      }
+    ],
+  };
+
+  if (isReturnMode.value) {
+    // 褰掕繕妯″紡鐨勯獙璇佽鍒�
+    return {
+      ...baseRules,
+      returnQuantity: [
+        { required: true, message: "璇疯緭鍏ュ綊杩樻暟閲�", trigger: "blur" },
+        { type: "number", min: 1, message: "鑷冲皯褰掕繕1鍙�", trigger: "blur" },
+        {
+          validator: (rule, value, callback) => {
+            const remaining = remainingReturnQuantity.value;
+            if (remaining <= 0) {
+              callback(new Error("宸插叏閮ㄥ綊杩橈紝鏃犳硶缁х画褰掕繕"));
+            } else if (value > remaining) {
+              callback(
+                new Error(`褰掕繕鏁伴噺涓嶈兘澶т簬鍓╀綑鍙綊杩樻暟閲�(${remaining}鍙�)`)
+              );
+            } else {
+              callback();
+            }
+          },
+          trigger: "blur",
+        },
+      ],
+      returnTime: [
+        { required: true, message: "璇烽�夋嫨褰掕繕鏃堕棿", trigger: "change" },
+      ],
+    };
+  } else {
+    // 鏂板/缂栬緫妯″紡鐨勯獙璇佽鍒�
+    return {
+      ...baseRules,
+      usageQuantity: [
+        { 
+          required: true, 
+          message: "璇疯緭鍏ラ鐢ㄦ暟閲�", 
+          trigger: "blur",
+          validator: (rule, value, callback) => {
+            const numValue = Number(value) || 0;
+            // 濡傛灉鍊间负绌烘垨鏈畾涔夛紝鎵嶆姤閿�
+            if (value === null || value === undefined || value === '') {
+              callback(new Error("璇疯緭鍏ラ鐢ㄦ暟閲�"));
+            } else if (numValue < 1) {
+              callback(new Error("鑷冲皯棰嗙敤1鍙�"));
+            } else if (maxQuantity.value !== null && maxQuantity.value > 0 && numValue > maxQuantity.value) {
+              callback(new Error("棰嗙敤鏁伴噺涓嶈兘澶т簬璁惧鏁伴噺"));
+            } else {
+              callback();
+            }
+          }
+        },
+      ],
+      usageStartTime: [
+        { required: true, message: "璇烽�夋嫨寮�濮嬫椂闂�", trigger: "change" },
+      ],
+    };
+  }
+});
+
+function handleClose() {
+  emit("update:modelValue", false);
+  isSubmitting.value = false;
+}
+
+// 閫氱敤闃叉姈鍑芥暟
+function debounce(fn, delay = 800) {
+  let timer = null;
+  return function (...args) {
+    if (timer) clearTimeout(timer);
+    timer = setTimeout(() => {
+      fn.apply(this, args);
+      timer = null;
+    }, delay);
+  };
+}
+
+// 闃叉姈鍚庣殑鎻愪氦鏂规硶
+const debouncedSubmit = debounce(handleSubmit, 800);
+
+async function handleSubmit() {
+  console.log('handleSubmit 琚皟鐢�');
+  console.log('formRef.value:', formRef.value);
+  console.log('褰撳墠琛ㄥ崟鏁版嵁:', JSON.stringify(form.value));
+  
+  if (isSubmitting.value) {
+    console.log('姝e湪鎻愪氦涓紝蹇界暐閲嶅鐐瑰嚮');
+    return;
+  }
+  
+  if (!formRef.value) {
+    console.error('formRef 涓嶅瓨鍦�');
+    showToast('琛ㄥ崟寮曠敤涓嶅瓨鍦紝璇峰埛鏂伴〉闈㈤噸璇�', 'error');
+    return;
+  }
+  
+  try {
+    console.log('寮�濮嬮獙璇佽〃鍗�...');
+    const valid = await formRef.value.validate().catch((errors) => {
+      console.log('琛ㄥ崟楠岃瘉澶辫触锛岄敊璇俊鎭�:', errors);
+      // 濡傛灉楠岃瘉澶辫触锛宔rrors 鍙兘鏄敊璇暟缁勬垨 false
+      if (errors && Array.isArray(errors) && errors.length > 0) {
+        const firstError = errors[0];
+        showToast(firstError.message || '璇峰畬鍠勮〃鍗曚俊鎭�', 'error');
+      } else {
+        showToast('璇峰畬鍠勮〃鍗曚俊鎭�', 'error');
+      }
+      return false;
+    });
+    console.log('琛ㄥ崟楠岃瘉缁撴灉:', valid);
+    
+    if (!valid) {
+      console.log('琛ㄥ崟楠岃瘉澶辫触锛屽仠姝㈡彁浜�');
+      return;
+    }
+
+    console.log('琛ㄥ崟楠岃瘉閫氳繃锛屽紑濮嬫彁浜�');
+    isSubmitting.value = true;
+    
+    let submitData = { ...form.value };
+
+    // 褰掕繕妯″紡澶勭悊
+    if (isReturnMode.value) {
+      const currentReturnQuantity = form.value.returnQuantity;
+      const totalUsageQuantity = props.formData.usageQuantity;
+      const alreadyReturnedQuantity = props.formData.totalReturnNo || 0;
+      const newTotalReturnedQuantity =
+        alreadyReturnedQuantity + currentReturnQuantity;
+
+      // 鍒ゆ柇鏄惁鍏ㄩ儴褰掕繕瀹屾垚
+      let equipmentStatus = 2; // 榛樿涓洪儴鍒嗗綊杩�
+      let isFullyReturned = newTotalReturnedQuantity >= totalUsageQuantity;
+
+      if (isFullyReturned) {
+        equipmentStatus = 3; // 鍏ㄩ儴褰掕繕瀹屾垚
+
+        // 鍏ㄩ儴褰掕繕鏃剁殑纭鎻愮ず
+        try {
+          const result = await showModal({
+            title: '纭鍏ㄩ儴褰掕繕',
+            content: `纭灏嗚澶�"${props.formData.equipmentName || '鏈煡璁惧'}"鍏ㄩ儴褰掕繕鍚楋紵褰掕繕鍚庤澶囩姸鎬佸皢鍙樹负"宸插綊杩�"銆俙,
+            confirmText: '纭褰掕繕',
+            cancelText: '鍙栨秷',
+            type: 'success'
+          });
+          
+          if (!result) {
+            showToast('宸插彇娑堝綊杩樻搷浣�', 'info');
+            isSubmitting.value = false;
+            return;
+          }
+        } catch (error) {
+          showToast('宸插彇娑堝綊杩樻搷浣�', 'info');
+          isSubmitting.value = false;
+          return;
+        }
+
+        console.log("璁惧褰掕繕瀹屾垚:", {
+          璁惧鍚嶇О: props.formData.equipmentName,
+          鎬讳娇鐢ㄦ暟閲�: totalUsageQuantity,
+          鏂扮殑褰掕繕鎬绘暟: newTotalReturnedQuantity,
+          鐘舵��: "宸插叏閮ㄥ綊杩�",
+        });
+      } else {
+        console.log("璁惧閮ㄥ垎褰掕繕:", {
+          璁惧鍚嶇О: props.formData.equipmentName,
+          鎬讳娇鐢ㄦ暟閲�: totalUsageQuantity,
+          宸插綊杩樻暟閲�: newTotalReturnedQuantity,
+          鍓╀綑鏈綊杩�: totalUsageQuantity - newTotalReturnedQuantity,
+          鐘舵��: "閮ㄥ垎褰掕繕",
+        });
+      }
+
+      submitData = {
+        ...props.formData,
+        totalReturnNo: newTotalReturnedQuantity,
+        returnQuantity: currentReturnQuantity,
+        returnTime: form.value.returnTime,
+        equipmentStatus: equipmentStatus,
+        remarks: form.value.remarks,
+        usageQuantity: totalUsageQuantity,
+      };
+    }
+
+    let { code, data } = await addOrEditUsageRecord(submitData);
+    if (code !== 200) {
+      showToast(data.msg || "鎿嶄綔澶辫触", 'error');
+      isSubmitting.value = false;
+      return;
+    }
+    if (code == 200 && data == 1) {
+      showToast('鎿嶄綔鎴愬姛', 'success');
+      emit("submit", submitData);
+      handleClose();
+    } else {
+      showToast(data.msg || "鎿嶄綔澶辫触", 'error');
+      isSubmitting.value = false;
+    }
+  } catch (error) {
+    console.error("鎻愪氦澶辫触:", error);
+    showToast("鎿嶄綔澶辫触锛岃绋嶅悗鍐嶈瘯", 'error');
+    isSubmitting.value = false;
+  }
+}
+</script>
+
+<style scoped lang="scss">
+@import '@/static/scss/form-common.scss';
+
+.popup-content {
+  width: 90vw;
+  max-width: 500px;
+  background-color: #fff;
+  border-radius: 10px;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+  max-height: 80vh;
+}
+
+.popup-header {
+  padding: 20px;
+  text-align: center;
+  border-bottom: 1px solid #f0f0f0;
+  flex-shrink: 0;
+}
+
+.popup-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #333;
+}
+
+.form-scroll {
+  flex: 1;
+  max-height: calc(80vh - 140px);
+  overflow-y: auto;
+}
+
+.popup-footer {
+  display: flex;
+  justify-content: center;
+  padding: 15px 20px;
+  border-top: 1px solid #f0f0f0;
+  background-color: #fafafa;
+  flex-shrink: 0;
+}
+
+.number-box-wrapper {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  width: 100%;
+  justify-content: flex-end;
+}
+
+.info-text {
+  font-size: 12px;
+  color: #999;
+  margin-left: 8px;
+}
+
+.tip-text {
+  font-size: 12px;
+  color: #2979ff;
+  margin-top: 8px;
+  padding: 8px 12px;
+  background: #f0f7ff;
+  border-radius: 4px;
+}
+</style>

--
Gitblit v1.9.3