基于vue3.0和element-plus的组件库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
3.5 KiB

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<any>;
handleAdd?: (value) => Promise<void>;
handleEdit?: (value) => Promise<void>;
handleCancel?: () => Promise<void>;
handleError?: (kind: "validation" | "internal", err?) => void;
handleClose?: () => void;
init?: any;
extraProps?: string[] | "any" | ((code: string) => boolean);
}
export function useModifyForm(options: Options) {
const { formRef, handleAdd, handleEdit, handleCancel, handleClose, 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<string, any>) =>
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<string, any> }>({
dialog: null,
model: { ...initValue },
}),
clearModel() {
clearAndAssign(this.data.model, initValue);
},
assignModel(newModel: Record<string, any>) {
const normalized = normalizeModel(newModel);
this.clearModel();
Object.assign(this.data.model, normalized);
},
openAdd(toAdd: Record<string, any> = {}) {
this.assignModel(toAdd);
formRef?.value?.clearValidate();
this.data.dialog = this.flagOnAdd;
},
openEdit(toEdit: Record<string, any>) {
this.assignModel(toEdit);
formRef?.value?.clearValidate();
this.data.dialog = this.flagOnEdit;
},
close() {
handleClose?.();
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();
},
};
}