import { isEmpty, isFunction, isRegExp, isString } from "lodash-es"; import { PropRules } from "../dict"; import type { EpsColumn, EpsModule } from "../types"; export function useCode() { // 特殊情况处理 const handler = { // 单选 dict({ comment }: EpsColumn) { const [label, ...arr] = comment.split(" "); // 选项列表 const list: any[] = arr.map((e) => { const [value, label] = e.split("-"); return { label, value: isNaN(Number(value)) ? value : Number(value) }; }); // boolean if (list.length == 2) { list.forEach((e) => { if (e.value == 1) { e.type = "success"; } else { e.type = "danger"; } }); } const d = { table: { label, dict: list, minWidth: 120 }, form: { label, component: { name: "", options: list } } as ClForm.Item }; // 默认值 if (list[0]) { d.form.value = list[0].value; } // 匹配组件 d.form.component!.name = arr.length > 4 ? "el-select" : "el-radio-group"; return d; }, // 多选 dict_multiple(column: EpsColumn) { const { table, form } = handler.dict(column); if (!form.component?.props) { form.component!.props = {}; } if (!form.value) { form.value = []; } switch (form.component?.name) { case "el-select": Object.assign(form.component.props, { multiple: true, filterable: true }); break; case "el-radio-group": form.component.name = "el-checkbox-group"; break; } return { table, form }; } }; // 创建组件 function createComponent(column: EpsColumn, columns: EpsColumn[]) { const prop = column.propertyName; let label = column.comment || ""; let d: any; let isHidden = false; // 根据规则匹配组件 PropRules.find((r) => { let s = false; // 已知组件的情况下 if (column.component) { if (column.component == r.value) { s = true; } } else { // 根据规则匹配 if (r.test) { s = !!r.test.find((e) => { if (isRegExp(e)) { return e.test(prop); } if (isFunction(e)) { return e(prop); } if (isString(e)) { if (e == prop) { return true; } const re = new RegExp(`${e}$`); return re.test(prop.toLocaleLowerCase()); } return false; }); } } if (r.group) { if ( r.group.includes(prop) && r.group.some((e) => columns.find((c) => c.propertyName == e)) ) { if (r.group[0] == prop) { s = true; } else { isHidden = true; } } } if (s) { if (r.handler) { // @ts-ignore const fn = isString(r.handler) ? handler[r.handler] : r.handler; if (isFunction(fn)) { d = fn(column); } } else { d = { ...r, test: undefined }; } } return s; }); // 没找到则默认input if (!d) { d = PropRules.find((e) => e.value == "input")?.render; } // 格式化标题 label = label?.split?.(" ")?.[0] || column.propertyName; return { column: { label, prop, ...d?.table }, item: { label, prop, ...d?.form }, isHidden }; } // 创建 vue 代码 function createVue({ router = "", columns = [], prefix = "", api = [], fieldEq = [], keyWordLikeFields = [] }: EpsModule) { // 新增、编辑 const upsert = { items: [] as DeepPartial[] }; // 表格 const table = { columns: [] as DeepPartial[] }; // 选项 const options = {}; // 遍历 columns.forEach((e) => { // 创建组件 const { item, column, isHidden } = createComponent(e, columns); // 过滤隐藏 if (isHidden) { return false; } // 验证规则 if (!e.nullable) { item.required = true; } // 字典 const dict = item.component?.options || column.dict; if (!isEmpty(dict)) { options[item.prop] = dict; const str = `$$options.${item.prop}$$`; if (!column.component) { column.dict = str; } item.component.options = str; } // 表单忽略 if (!["createTime", "updateTime", "id", "endTime", "endDate"].includes(item.prop)) { upsert.items.push(item); } // 表格忽略 if (!["id"].includes(item.prop)) { // 默认排序 if (item.prop == "createTime") { column.sortable = "desc"; } table.columns.push(column); } // 时间范围处理 if (["startTime", "startDate"].includes(item.prop)) { const key = item.prop.replace("start", ""); if (columns.find((e) => e.propertyName == "end" + key)) { item.prop = key.toLocaleLowerCase(); const isTime = item.prop == "time"; item.label = isTime ? "时间范围" : "日期范围"; item.hook = "datetimeRange"; item.component = { name: "el-date-picker", props: { type: isTime ? "datetimerange" : "daterange", valueFormat: isTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD 00:00:00", defaultTime: [ new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59) ] } }; } } }); // 请求服务 const service = prefix.replace("/admin", "service").split("/"); // 请求地址 const paths = api.map((e) => e.path); // 权限 const perms = { add: paths.includes("/add"), del: paths.includes("/delete"), update: paths.includes("/info") && paths.includes("/update"), page: paths.includes("/page"), upsert: true }; perms.upsert = perms.add || perms.update; // 是否有操作栏 if (perms.del || perms.upsert) { const buttons: ClTable.OpButton = []; if (perms.upsert) { buttons.push("edit"); } if (perms.del) { buttons.push("delete"); } table.columns.push({ type: "op", buttons }); } // 是否多选、序号 if (perms.del) { table.columns.unshift({ type: "selection" }); } else { table.columns.unshift({ label: "#", type: "index" }); } // 筛选 const clFilter = fieldEq .map((field) => { if (isEmpty(options[field])) { return ""; } const item = upsert.items.find((e) => e.prop == field); if (!item) { return ""; } return `\n\n\n`; }) .filter(Boolean) .join("\n"); // 关键字搜索 const clSearchKeyPlaceholder = keyWordLikeFields .map((field) => { return table.columns.find((e) => e.prop == field)?.label; }) .filter((e) => !!e) .join("、"); // 选项 const ConstOptions = `${ isEmpty(options) ? "" : "\n// 选项\nconst options = reactive(" + toCodeString(options) + ")\n" }`; // Vue 依赖 let ImportVue = ""; if (ConstOptions) { ImportVue = "import { reactive } from 'vue';\n"; } // 代码模板 const temp = ` `; return temp.replace(/"\$\$|\$\$"/g, ""); } // 转成代码字符串 function toCodeString(data: any) { const arr: string[][] = []; let code = JSON.stringify(data, (key, value) => { if (isFunction(value)) { const str = value.toString(); arr.push([JSON.stringify({ [key]: str }), str]); return str; } else { return value; } }); arr.forEach((e) => { code = code.replace(e[0].substring(1, e[0].length - 1), e[1]); }); return code; } return { handler, createVue, createComponent, toCodeString }; }