123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- 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<ClForm.Item>[]
- };
- // 表格
- const table = {
- columns: [] as DeepPartial<ClTable.Column>[]
- };
- // 选项
- 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 `<!-- 筛选${item.label} -->\n<cl-filter label="${item.label}">\n<cl-select prop="${field}" :options="options.${field}" />\n</cl-filter>`;
- })
- .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 = `<template>
- <cl-crud ref="Crud">
- <cl-row>
- <!-- 刷新按钮 -->
- <cl-refresh-btn />
- ${perms.add ? "<!-- 新增按钮 -->\n <cl-add-btn />" : ""}
- ${perms.del ? "<!-- 删除按钮 -->\n <cl-multi-delete-btn />" : ""}
- ${clFilter}
- <cl-flex1 />
- <!-- 关键字搜索 -->
- <cl-search-key placeholder="搜索${clSearchKeyPlaceholder || "关键字"}" />
- </cl-row>
- <cl-row>
- <!-- 数据表格 -->
- <cl-table ref="Table" />
- </cl-row>
- <cl-row>
- <cl-flex1 />
- <!-- 分页控件 -->
- <cl-pagination />
- </cl-row>
- <!-- 新增、编辑 -->
- <cl-upsert ref="Upsert" />
- </cl-crud>
- </template>
- <script lang="ts" name="${router.replace(/^\//, "").replace(/\//g, "-")}" setup>
- import { useCrud, useTable, useUpsert } from "@cool-vue/crud";
- import { useCool } from "/@/cool";
- ${ImportVue}
- const { service } = useCool();
- ${ConstOptions}
- // cl-upsert
- const Upsert = useUpsert(${toCodeString(upsert)});
- // cl-table
- const Table = useTable(${toCodeString(table)});
- // cl-crud
- const Crud = useCrud(
- {
- service: ${service.join(".")}
- },
- (app) => {
- app.refresh();
- }
- );
- // 刷新
- function refresh(params?: any) {
- Crud.value?.refresh(params);
- }
- </script>`;
- 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
- };
- }
|