import { reactive, Ref, toRaw } from "vue"; import {} from "noob-mengyxu"; import * as Element from "../element"; import { clearAndAssign, deepCopy } from "../util/objectUtil"; const { showMessage } = Element; export interface FormProp { code: string; name?: string; i18n?: string; dict?: string; slot?: boolean; [others: string]: any; } interface Options { props?: FormProp[]; formRef?: Ref; handleAdd?: (value) => Promise; handleEdit?: (value) => Promise; handleCancel?: () => Promise; handleError?: (kind: "validation" | "internal", err?) => void; init?: any; extraProps?: string[] | "any" | ((code: string) => boolean); } export function useModifyForm(options: Options) { const { formRef, handleAdd, handleEdit, handleCancel, init, extraProps } = options; const initValue = init ?? {}; const props = options.props ?? []; const propMap = Object.fromEntries(props.map((prop) => [prop.code, prop])); let isValidProp: (code: string) => boolean; if (typeof extraProps === "function") { isValidProp = (code: string) => extraProps(code) as boolean; } else if (Array.isArray(extraProps)) { isValidProp = (code: string) => extraProps.includes(code); } else { isValidProp = (_code: string) => extraProps === "any"; } const normalizeValue = (code: string, value: any) => { const prop = propMap[code]; if (!prop && !isValidProp(code)) return null; if (prop?.dict) { const parsed = parseInt(value); return isNaN(parsed) ? value : parsed; } return value; }; const normalizeModel = (newModel: Record) => Object.fromEntries( Object.entries(newModel).flatMap(([code, value]) => { const normalized = normalizeValue(code, value); return normalized != null ? [[code, normalized]] : []; }) ); const handleError = options.handleError ?? ((kind, err) => { if (kind === "validation") { showMessage("error", "Validation Error"); } else if (kind === "internal") { const msg = `Internal Error: ${err}`; showMessage("error", msg); console.error(msg); } }); return { flagOnClose: null, flagOnAdd: "add", flagOnEdit: "edit", data: reactive<{ dialog: any; model: Record }>({ dialog: null, model: { ...initValue }, }), clearModel() { clearAndAssign(this.data.model, initValue); }, assignModel(newModel: Record) { const normalized = normalizeModel(newModel); this.clearModel(); Object.assign(this.data.model, normalized); }, openAdd() { this.clearModel(); formRef?.value?.clearValidate(); this.data.dialog = this.flagOnAdd; }, openEdit(toEdit: Record) { this.assignModel(toEdit); formRef?.value?.clearValidate(); this.data.dialog = this.flagOnEdit; }, close() { this.data.dialog = this.flagOnClose; }, async onConfirm() { const value = deepCopy(toRaw(this.data.model)); try { if (this.data.dialog === this.flagOnAdd) { await handleAdd?.(value); } else if (this.data.dialog === this.flagOnEdit) { await handleEdit?.(value); } } catch (err) { handleError?.("internal", err); } this.close(); }, async onCancel() { await handleCancel?.(); this.close(); }, }; }