From 1c4e88c1cb0639663f77a33dbab26c3cac71ad93 Mon Sep 17 00:00:00 2001
From: zhang_12370 <z2864490065@outlook.com>
Date: 星期四, 26 六月 2025 13:28:05 +0800
Subject: [PATCH] 开发通用 删除 优化文档管理模块

---
 src/hooks/useFormData.js |  326 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 324 insertions(+), 2 deletions(-)

diff --git a/src/hooks/useFormData.js b/src/hooks/useFormData.js
index 7363aa8..325e981 100644
--- a/src/hooks/useFormData.js
+++ b/src/hooks/useFormData.js
@@ -1,8 +1,330 @@
-import { reactive } from "vue";
+/**
+ * 閫氱敤琛ㄥ崟鏁版嵁绠$悊缁勫悎寮忓嚱鏁�
+ * 鎻愪緵琛ㄥ崟鏁版嵁鐨勫鍒犳敼鏌ャ�侀獙璇併�侀噸缃瓑鍔熻兘
+ */
+import { ref, reactive, computed, nextTick } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
 import { clone } from "lodash";
 
+/**
+ * 鍒涘缓琛ㄥ崟鏁版嵁绠$悊鍔熻兘
+ * @param {Object} options 閰嶇疆閫夐」
+ * @param {Object} options.defaultForm 榛樿琛ㄥ崟缁撴瀯
+ * @param {Function} options.addApi 鏂板API鍑芥暟
+ * @param {Function} options.updateApi 鏇存柊API鍑芥暟
+ * @param {Function} options.getDetailApi 鑾峰彇璇︽儏API鍑芥暟
+ * @param {Object} options.rules 琛ㄥ崟楠岃瘉瑙勫垯
+ * @param {Function} options.beforeSubmit 鎻愪氦鍓嶇殑鏁版嵁澶勭悊鍑芥暟
+ * @param {Function} options.afterSubmit 鎻愪氦鍚庣殑鍥炶皟鍑芥暟
+ * @param {Boolean} options.autoReset 鎻愪氦鎴愬姛鍚庢槸鍚﹁嚜鍔ㄩ噸缃〃鍗�
+ * @returns {Object} 杩斿洖琛ㄥ崟绠$悊鐩稿叧鐨勬柟娉曞拰鐘舵��
+ */
+export function useFormData(options = {}) {
+  const {
+    defaultForm = {},
+    addApi,
+    updateApi,
+    getDetailApi,
+    rules = {},
+    beforeSubmit,
+    afterSubmit,
+    autoReset = true
+  } = options;
 
-export default function useFormData(initData) {
+  // 琛ㄥ崟鐘舵��
+  const form = ref({ ...defaultForm });
+  const originalForm = ref({ ...defaultForm });
+  const loading = ref(false);
+  const dialogVisible = ref(false);
+  const mode = ref('add'); // 'add', 'edit', 'view'
+  const title = ref('');
+  const formRef = ref(null);
+
+  // 璁$畻灞炴��
+  const isAdd = computed(() => mode.value === 'add');
+  const isEdit = computed(() => mode.value === 'edit');
+  const isView = computed(() => mode.value === 'view');
+  const isReadonly = computed(() => mode.value === 'view');
+  const submitButtonText = computed(() => {
+    return isAdd.value ? '鏂板' : '淇濆瓨';
+  });
+
+  /**
+   * 鎵撳紑琛ㄥ崟瀵硅瘽妗�
+   * @param {String} formMode 琛ㄥ崟妯″紡锛�'add', 'edit', 'view'
+   * @param {Object} data 缂栬緫/鏌ョ湅鏃剁殑鏁版嵁
+   * @param {String} customTitle 鑷畾涔夋爣棰�
+   */
+  const openForm = async (formMode = 'add', data = null, customTitle = '') => {
+    mode.value = formMode;
+    
+    // 璁剧疆鏍囬
+    if (customTitle) {
+      title.value = customTitle;
+    } else {
+      const titleMap = {
+        add: '鏂板',
+        edit: '缂栬緫', 
+        view: '鏌ョ湅'
+      };
+      title.value = titleMap[formMode] || '琛ㄥ崟';
+    }
+
+    // 鏍规嵁妯″紡澶勭悊鏁版嵁
+    if (formMode === 'add') {
+      resetForm();
+    } else if (data) {
+      // 缂栬緫/鏌ョ湅妯″紡锛屽鏋滄湁璇︽儏API鍒欒幏鍙栨渶鏂版暟鎹�
+      if (getDetailApi && data.id) {
+        loading.value = true;
+        try {
+          const res = await getDetailApi(data.id);
+          if (res.code === 200) {
+            setFormData(res.data);
+          } else {
+            ElMessage.error('鑾峰彇璇︽儏澶辫触');
+            setFormData(data);
+          }
+        } catch (error) {
+          console.error('鑾峰彇璇︽儏澶辫触:', error);
+          setFormData(data);
+        } finally {
+          loading.value = false;
+        }
+      } else {
+        setFormData(data);
+      }
+    }
+
+    dialogVisible.value = true;
+  };
+
+  /**
+   * 璁剧疆琛ㄥ崟鏁版嵁
+   * @param {Object} data 琛ㄥ崟鏁版嵁
+   */
+  const setFormData = (data) => {
+    form.value = { ...defaultForm, ...data };
+    originalForm.value = { ...form.value };
+  };
+
+  /**
+   * 閲嶇疆琛ㄥ崟
+   */
+  const resetForm = () => {
+    form.value = { ...defaultForm };
+    originalForm.value = { ...defaultForm };
+    if (formRef.value) {
+      formRef.value.resetFields();
+    }
+  };
+
+  /**
+   * 鎭㈠琛ㄥ崟鍒板師濮嬬姸鎬�
+   */
+  const restoreForm = () => {
+    form.value = { ...originalForm.value };
+    if (formRef.value) {
+      formRef.value.clearValidate();
+    }
+  };
+
+  /**
+   * 琛ㄥ崟楠岃瘉
+   * @returns {Promise<Boolean>} 楠岃瘉缁撴灉
+   */
+  const validateForm = async () => {
+    if (!formRef.value) return true;
+    
+    try {
+      await formRef.value.validate();
+      return true;
+    } catch (error) {
+      console.log('琛ㄥ崟楠岃瘉澶辫触:', error);
+      return false;
+    }
+  };
+
+  /**
+   * 鎻愪氦琛ㄥ崟
+   * @param {Object} customData 鑷畾涔夋彁浜ゆ暟鎹�
+   * @returns {Promise<Boolean>} 鎻愪氦缁撴灉
+   */
+  const submitForm = async (customData = null) => {
+    // 楠岃瘉琛ㄥ崟
+    const isValid = await validateForm();
+    if (!isValid) {
+      ElMessage.warning('璇锋鏌ヨ〃鍗曟暟鎹�');
+      return false;
+    }
+
+    // 鍑嗗鎻愪氦鏁版嵁
+    let submitData = customData || { ...form.value };
+    
+    // 鎵ц鎻愪氦鍓嶅鐞�
+    if (beforeSubmit && typeof beforeSubmit === 'function') {
+      try {
+        submitData = await beforeSubmit(submitData, mode.value);
+      } catch (error) {
+        console.error('鎻愪氦鍓嶅鐞嗗け璐�:', error);
+        ElMessage.error('鏁版嵁澶勭悊澶辫触');
+        return false;
+      }
+    }
+
+    loading.value = true;
+    
+    try {
+      let res;
+      
+      if (isAdd.value && addApi) {
+        res = await addApi(submitData);
+      } else if (isEdit.value && updateApi) {
+        res = await updateApi(submitData);
+      } else {
+        ElMessage.error('鏈厤缃浉搴旂殑API鎺ュ彛');
+        return false;
+      }
+
+      if (res.code === 200) {
+        const action = isAdd.value ? '鏂板' : '鏇存柊';
+        ElMessage.success(`${action}鎴愬姛`);
+        
+        // 鎵ц鎻愪氦鍚庡洖璋�
+        if (afterSubmit && typeof afterSubmit === 'function') {
+          await afterSubmit(res.data, mode.value, submitData);
+        }
+
+        // 鑷姩閲嶇疆琛ㄥ崟
+        if (autoReset) {
+          closeForm();
+        }
+
+        return true;
+      } else {
+        ElMessage.error(res.msg || '鎿嶄綔澶辫触');
+        return false;
+      }
+    } catch (error) {
+      console.error('鎻愪氦澶辫触:', error);
+      ElMessage.error('鎿嶄綔澶辫触锛岃绋嶅悗閲嶈瘯');
+      return false;
+    } finally {
+      loading.value = false;
+    }
+  };
+
+  /**
+   * 鍏抽棴琛ㄥ崟瀵硅瘽妗�
+   */
+  const closeForm = () => {
+    dialogVisible.value = false;
+    resetForm();
+  };
+
+  /**
+   * 妫�鏌ヨ〃鍗曟槸鍚︽湁鍙樻洿
+   * @returns {Boolean} 鏄惁鏈夊彉鏇�
+   */
+  const hasChanges = computed(() => {
+    return JSON.stringify(form.value) !== JSON.stringify(originalForm.value);
+  });
+
+  /**
+   * 甯︾‘璁ょ殑鍏抽棴琛ㄥ崟
+   */
+  const closeFormWithConfirm = async () => {
+    if (hasChanges.value && !isView.value) {
+      try {
+        await ElMessageBox.confirm('琛ㄥ崟鏁版嵁宸蹭慨鏀癸紝纭畾瑕佺寮�鍚楋紵', '鎻愮ず', {
+          confirmButtonText: '纭畾',
+          cancelButtonText: '鍙栨秷',
+          type: 'warning',
+        });
+        closeForm();
+      } catch {
+        // 鐢ㄦ埛鍙栨秷
+      }
+    } else {
+      closeForm();
+    }
+  };
+
+  /**
+   * 璁剧疆琛ㄥ崟瀛楁鍊�
+   * @param {String} field 瀛楁鍚�
+   * @param {Any} value 瀛楁鍊�
+   */
+  const setFieldValue = (field, value) => {
+    form.value[field] = value;
+  };
+
+  /**
+   * 鑾峰彇琛ㄥ崟瀛楁鍊�
+   * @param {String} field 瀛楁鍚�
+   * @returns {Any} 瀛楁鍊�
+   */
+  const getFieldValue = (field) => {
+    return form.value[field];
+  };
+
+  /**
+   * 鎵归噺璁剧疆琛ㄥ崟瀛楁鍊�
+   * @param {Object} values 瀛楁鍊煎璞�
+   */
+  const setFieldValues = (values) => {
+    Object.keys(values).forEach(key => {
+      if (form.value.hasOwnProperty(key)) {
+        form.value[key] = values[key];
+      }
+    });
+  };
+
+  /**
+   * 娓呴櫎瀛楁楠岃瘉
+   * @param {String|Array} fields 瀛楁鍚嶆垨瀛楁鍚嶆暟缁�
+   */
+  const clearValidate = (fields = null) => {
+    if (formRef.value) {
+      formRef.value.clearValidate(fields);
+    }
+  };
+
+  return {
+    // 鐘舵��
+    form,
+    loading,
+    dialogVisible,
+    mode,
+    title,
+    formRef,
+    
+    // 璁$畻灞炴��
+    isAdd,
+    isEdit,
+    isView,
+    isReadonly,
+    submitButtonText,
+    hasChanges,
+    
+    // 鏂规硶
+    openForm,
+    setFormData,
+    resetForm,
+    restoreForm,
+    validateForm,
+    submitForm,
+    closeForm,
+    closeFormWithConfirm,
+    setFieldValue,
+    getFieldValue,
+    setFieldValues,
+    clearValidate
+  };
+}
+
+// 鍚戝悗鍏煎鐨勯粯璁ゅ鍑�
+export default function useFormDataSimple(initData) {
   const form = reactive(clone(initData, true));
 
   function resetForm() {

--
Gitblit v1.9.3