import type { Dropdown } from "@/types"; import type { InjectionKey } from "vue"; export const DROPDOWN_SYMBOL = Symbol('DROPDOWN_SYMBOL') as InjectionKey>; /** * 深拷贝一个值 * @param value 要拷贝的值 * @returns 深拷贝后的值 */ const deepClone = (value: any): any => { // 如果是基本类型或 null/undefined,直接返回 if (value == null || typeof value !== 'object') { return value; } // 如果是数组,递归拷贝每个元素 if (Array.isArray(value)) { return value.map(item => deepClone(item)); } // 如果是对象,递归拷贝所有属性 const cloned: Record = {}; for (const key in value) { if (Object.prototype.hasOwnProperty.call(value, key)) { cloned[key] = deepClone(value[key]); } } return cloned; }; /** * 深度比较两个值是否严格相等 * @param a 第一个值 * @param b 第二个值 * @returns 是否相等 */ const deepEqual = (a: any, b: any): boolean => { // 如果引用相同,直接返回 true if (a === b) return true; // 如果其中一个为 null 或 undefined if (a == null || b == null) return a === b; // 如果类型不同,返回 false if (typeof a !== typeof b) return false; // 如果是基本类型(非对象),直接比较 if (typeof a !== 'object') return a === b; // 如果是数组 if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) return false; return a.every((item, index) => deepEqual(item, b[index])); } // 如果一个是数组,另一个不是,返回 false if (Array.isArray(a) || Array.isArray(b)) return false; // 如果是对象,比较所有键值对 const keysA = Object.keys(a); const keysB = Object.keys(b); // 键的数量不同,返回 false if (keysA.length !== keysB.length) return false; // 检查所有键是否都存在且值相等 for (const key of keysA) { if (!keysB.includes(key)) return false; if (!deepEqual(a[key], b[key])) return false; } return true; }; export const useDropdown = (configs: Dropdown.DropdownItem[]) => { const list = computed(() => configs); const form = ref>({}); const openIndex = ref(-1); const open = (index: number) => { openIndex.value = index; } const close = () => { openIndex.value = -1; } const submit = (index: number, value: any) => { form.value = { ...form.value, [list.value[index].prop]: value }; } const reset = (index: number) => { form.value = { ...form.value, [list.value[index].prop]: list.value[index].value }; } const init = (initValue: Record) => { form.value = { ...initValue }; list.value.forEach(item => { item.value = initValue[item.prop] || item.value; }); } return { init, form, openIndex, open, close, submit, reset, deepEqual, deepClone } }