diff --git a/src/common/utils/http-util.ts b/src/common/utils/http-util.ts index 6dc9e11..a5db4c1 100644 --- a/src/common/utils/http-util.ts +++ b/src/common/utils/http-util.ts @@ -5,7 +5,7 @@ import axios, { } from 'axios' import * as qs from 'qs' import { useAppUserStore } from '@/common/app/app-user-store.ts' -import { throttle } from '@/common/utils/index.ts' +import Utils from '@/common/utils/index.ts' import mime from '@/common/utils/mime.ts' import Evt from '@/common/utils/evt.ts' import { ElMessage } from 'element-plus' @@ -41,7 +41,7 @@ const paramsSerializer = (params: any) => { /* function errHandler(r?: R) { Toast.error(r?.message ?? '操作失败') } */ -const errHandler = throttle(500, (r?: AxiosResponse, any>) => { +const errHandler = Utils.throttle(500, (r?: AxiosResponse, any>) => { console.log('异常处理', r) ElMessage.error(r?.data?.message ?? '服务器错误') }) diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts index fac6e53..1aa1c24 100644 --- a/src/common/utils/index.ts +++ b/src/common/utils/index.ts @@ -1,3 +1,5 @@ +import type { ReactiveFlags } from 'vue' + /** * 类型标签,Object.prototype.toString.call(obj) 的返回值 */ @@ -29,7 +31,7 @@ export class TypeTag { * @param t 时间阈值(ms) * @return 包装后的函数 */ -export function throttle(t: number, fn: (...args: T) => void) { +function throttle(t: number, fn: (...args: T) => void) { let lastExecTime = 0 return function (this: any, ...args: T) { let now = Date.now() @@ -48,7 +50,7 @@ export function throttle(t: number, fn: (...args: T) => void) { * @param t 时间阈值(ms) * @return 包装后的函数 */ -export function debounce(t: number, fn: (...args: T) => void) { +function debounce(t: number, fn: (...args: T) => void) { let deferTimer: number | null = null return function (this: any, ...args: T) { if (deferTimer != null) { @@ -61,8 +63,66 @@ export function debounce(t: number, fn: (...args: T) => void) { } } -export function clone(t: T) { - return JSON.parse(JSON.stringify(t)) as T +function clone(value: T): T { + if (value === null || typeof value !== 'object') { + return value + } + const rawValue = isReactive(value) ? toRaw(value) : value + if (rawValue instanceof Date) { + return new Date(rawValue.getTime()) as T + } + if (rawValue instanceof RegExp) { + return new RegExp(rawValue.source, rawValue.flags) as T + } + if (Array.isArray(rawValue)) { + return rawValue.map((item) => clone(item)) as T + } + const clonedObj = {} as T + Object.keys(rawValue).forEach((key) => { + clonedObj[key as keyof T] = clone(rawValue[key as keyof T]) + }) + return clonedObj as T +} + +type ExtractRawType = +// 匹配 reactive 响应式对象(通过 Vue 内置的 RAW 标记提取原始类型) + T extends { [ReactiveFlags.RAW]: infer RawValue } + ? RawValue + // 递归处理数组(兼容 reactive([]) 场景) + : T extends Array + ? Array> + // 递归处理嵌套对象(兼容 reactive({ a: { b: 1 } }) 场景) + : T extends object + ? { [K in keyof T]: ExtractRawType } + // 非对象类型直接返回(如 string/number 等) + : T; + +type ResetAble = T & { $reset: (val?: Partial>) => void } + + +function resetAble(target: T): ResetAble { + const initialData = clone(target) as T + + (target as ResetAble).$reset = (val?: Partial>) => { + if (val == null) { + val = initialData + } + if (Array.isArray(val)) { + const arr = target as unknown as Array + const initialArr = val as unknown as Array + arr.splice(0, arr.length, ...initialArr) + } else { + Object.keys(val).forEach((key) => { + (target as Record)[key] = (val as Record)[key] + }) + Object.getOwnPropertyNames(target).forEach((key) => { + if (key !== '$reset' && !(key in val)) { + (target as Record)[key] = undefined + } + }) + } + } + return target as ResetAble } export default { @@ -70,4 +130,5 @@ export default { debounce, TypeTag, clone, + resetAble, } diff --git a/src/common/utils/times.ts b/src/common/utils/times.ts index 8cc79ab..6729bc6 100644 --- a/src/common/utils/times.ts +++ b/src/common/utils/times.ts @@ -61,7 +61,8 @@ function parse(date: Date | number | string | DateObjectUnits, fmt: string = FMT * @param date luxon 库的时间对象、JS 时间对象 * @param fmt 时间格式(仅时间字符串需要此参数,默认:yyyy-MM-dd HH:mm:ss) */ -function format(date: DateTime | Date, fmt: string = FMT.date_time_sec) { +function format(date?: DateTime | Date, fmt: string = FMT.date_time_sec) { + if (date == null) return '' if (isDate(date)) { return DateTime.fromJSDate(date as Date).toFormat(fmt) } else { diff --git a/src/dts/components.d.ts b/src/dts/components.d.ts index c81eea5..61330c3 100644 --- a/src/dts/components.d.ts +++ b/src/dts/components.d.ts @@ -5,7 +5,6 @@ // ------ // Generated by unplugin-vue-components // Read more: https://github.com/vuejs/core/pull/3399 -import { GlobalComponents } from 'vue' export {} @@ -15,11 +14,8 @@ declare module 'vue' { ElAside: typeof import('element-plus/es')['ElAside'] ElAvatar: typeof import('element-plus/es')['ElAvatar'] ElButton: typeof import('element-plus/es')['ElButton'] - ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] - ElCollapse: typeof import('element-plus/es')['ElCollapse'] - ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'] ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] ElContainer: typeof import('element-plus/es')['ElContainer'] ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] @@ -35,7 +31,6 @@ declare module 'vue' { ElFormItem: typeof import('element-plus/es')['ElFormItem'] ElHeader: typeof import('element-plus/es')['ElHeader'] ElIcon: typeof import('element-plus/es')['ElIcon'] - ElIconFilter: typeof import('@element-plus/icons-vue')['Filter'] ElIconPicture: typeof import('@element-plus/icons-vue')['Picture'] ElImage: typeof import('element-plus/es')['ElImage'] ElInput: typeof import('element-plus/es')['ElInput'] @@ -50,7 +45,6 @@ declare module 'vue' { ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] ElTabPane: typeof import('element-plus/es')['ElTabPane'] ElTabs: typeof import('element-plus/es')['ElTabs'] - ElTabsPane: typeof import('element-plus/es')['ElTabsPane'] ElTag: typeof import('element-plus/es')['ElTag'] ElText: typeof import('element-plus/es')['ElText'] ElTooltip: typeof import('element-plus/es')['ElTooltip'] @@ -70,11 +64,8 @@ declare global { const ElAside: typeof import('element-plus/es')['ElAside'] const ElAvatar: typeof import('element-plus/es')['ElAvatar'] const ElButton: typeof import('element-plus/es')['ElButton'] - const ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] const ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] const ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] - const ElCollapse: typeof import('element-plus/es')['ElCollapse'] - const ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'] const ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] const ElContainer: typeof import('element-plus/es')['ElContainer'] const ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] @@ -90,7 +81,6 @@ declare global { const ElFormItem: typeof import('element-plus/es')['ElFormItem'] const ElHeader: typeof import('element-plus/es')['ElHeader'] const ElIcon: typeof import('element-plus/es')['ElIcon'] - const ElIconFilter: typeof import('@element-plus/icons-vue')['Filter'] const ElIconPicture: typeof import('@element-plus/icons-vue')['Picture'] const ElImage: typeof import('element-plus/es')['ElImage'] const ElInput: typeof import('element-plus/es')['ElInput'] @@ -105,7 +95,6 @@ declare global { const ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] const ElTabPane: typeof import('element-plus/es')['ElTabPane'] const ElTabs: typeof import('element-plus/es')['ElTabs'] - const ElTabsPane: typeof import('element-plus/es')['ElTabsPane'] const ElTag: typeof import('element-plus/es')['ElTag'] const ElText: typeof import('element-plus/es')['ElText'] const ElTooltip: typeof import('element-plus/es')['ElTooltip'] @@ -114,4 +103,4 @@ declare global { const ElUpload: typeof import('element-plus/es')['ElUpload'] const RouterLink: typeof import('vue-router')['RouterLink'] const RouterView: typeof import('vue-router')['RouterView'] -} \ No newline at end of file +} diff --git a/src/pages/cst/customer/Customer.vue b/src/pages/cst/customer/Customer.vue index 12564a0..d694aee 100644 --- a/src/pages/cst/customer/Customer.vue +++ b/src/pages/cst/customer/Customer.vue @@ -89,10 +89,10 @@