liyu-pc-base 1.0.921 → 1.0.925
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{FieldRender-BOg7nm5z.js → FieldRender-DnOLSXTl.js} +1 -1
- package/dist/{FieldRender2-_MtcDkI5.js → FieldRender2-CvxGe238.js} +2 -2
- package/dist/{FormRender3-BtY9d91e.js → FormRender3-CAxOQgue.js} +1 -1
- package/dist/{RemoteSelectPro-CcWTS4f6.js → RemoteSelectPro-CcL_vU1K.js} +1 -1
- package/dist/{SearchRender-ByarFel1.js → SearchRender-Dr_qnvZM.js} +1 -1
- package/dist/components/index.js +7 -7
- package/dist/{dbViewConfig-RGSyUx3F.js → dbViewConfig-BF0QZ_mT.js} +1 -1
- package/dist/{detailTablePro-CqcVbn8O.js → detailTablePro-DxgfGYN3.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/liyu-pc-base.css +1 -1
- package/dist/{tableModal-DSKuV-hn.js → tableModal-DZE5wntG.js} +1 -1
- package/dist/{tablePageHost-B_BOlBNA.js → tablePageHost-hE_1hQv4.js} +82 -44
- package/dist/{tablePro-IAcxxAGI.js → tablePro-t2yDX9oW.js} +16 -11
- package/package.json +1 -1
- package/dist/AttributeNomTable-DHED22ju.js.map +0 -1
- package/dist/AttributeTable-muxdKpWW.js.map +0 -1
- package/dist/FieldRender-BOg7nm5z.js.map +0 -1
- package/dist/FieldRender2-_MtcDkI5.js.map +0 -1
- package/dist/FormRender3-BtY9d91e.js.map +0 -1
- package/dist/ImportExcelModal-Dds857L2.js.map +0 -1
- package/dist/JsonObj-CmylW4Or.js.map +0 -1
- package/dist/JsonStr-JwOPdAYW.js.map +0 -1
- package/dist/RemoteCascader-B2ytkZp7.js.map +0 -1
- package/dist/RemoteFilterSelect-BthY6Fyt.js.map +0 -1
- package/dist/RemoteModal-Dqy32RFN.js.map +0 -1
- package/dist/RemoteSelect-27xLYvyg.js.map +0 -1
- package/dist/RemoteSelectPro-CcWTS4f6.js.map +0 -1
- package/dist/RemoteTable-D_12PvNS.js.map +0 -1
- package/dist/RemoteTable2-DF7gWHYf.js.map +0 -1
- package/dist/RemoteText-DwRLI0xq.js.map +0 -1
- package/dist/RemoteTreeSelectPro-CXMOariR.js.map +0 -1
- package/dist/SearchRender-ByarFel1.js.map +0 -1
- package/dist/TinymceEditor-waI-dlC5.js.map +0 -1
- package/dist/aiGenModel-C9E1ahu8.js.map +0 -1
- package/dist/api/api-model.js.map +0 -1
- package/dist/api/typing.js.map +0 -1
- package/dist/batchCreateUser-B4zAXSR6.js.map +0 -1
- package/dist/boldenText-Bv8Zo7Vh.js.map +0 -1
- package/dist/components/FormRender/utils.js.map +0 -1
- package/dist/components/gridPage/utils.js.map +0 -1
- package/dist/components/index.js.map +0 -1
- package/dist/components/remotePages/utils.js.map +0 -1
- package/dist/dbDataSourceConfig-Hj90tvTR.js.map +0 -1
- package/dist/dbViewConfig-RGSyUx3F.js.map +0 -1
- package/dist/default-DmCqrYQi.js.map +0 -1
- package/dist/detailTablePro-CqcVbn8O.js.map +0 -1
- package/dist/exceljs.min-BPhBd8yF.js.map +0 -1
- package/dist/function-BhYSb8ls.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/init-plugin-CvgtEpwY.js.map +0 -1
- package/dist/lodash-CMVwnWxD.js.map +0 -1
- package/dist/md5-WIoeWMjT.js.map +0 -1
- package/dist/modal-tools-CrXdI5sg.js.map +0 -1
- package/dist/props-util-D7nkeN4W.js.map +0 -1
- package/dist/remotePages-CvjMLjTh.js.map +0 -1
- package/dist/role-manage-C7O8b2SF.js.map +0 -1
- package/dist/syncDataSourceConfig-OZ2mJCJs.js.map +0 -1
- package/dist/syncExportRawData-Dpi-VJuu.js.map +0 -1
- package/dist/syncModelTypeConfig-B2vV_kKb.js.map +0 -1
- package/dist/tableModal-DSKuV-hn.js.map +0 -1
- package/dist/tablePageHost-B_BOlBNA.js.map +0 -1
- package/dist/tablePro-IAcxxAGI.js.map +0 -1
- package/dist/utils/excel.js.map +0 -1
- package/dist/utils/hooks/useFetchData.js.map +0 -1
- package/dist/utils/hooks/useTableColumn.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"api-model.js","names":[],"sources":["../../src/api/api-model.ts"],"sourcesContent":["import { useRequest } from '../init-plugin';\n\nexport async function getApiData(\n params: { [key: string]: any },\n url: string,\n is_tree?: boolean,\n options: any = {},\n): Promise<any> {\n if (is_tree) {\n const res: any = await useRequest().post(url, params, options);\n // 创建一个映射,用于快速查找元素\n const map = new Map<string, any>(\n res.data.map(item => [\n item.id,\n { ...item, key: item.id, value: item.id, title: item.name, children: [] },\n ]),\n );\n const result = [];\n\n // 构建嵌套结构\n res.data.forEach(item => {\n item.key = item.id;\n item.value = item.id;\n item.title = item.name;\n if (item.parent_id !== null && map.get(item.parent_id)?.children) {\n map.get(item.parent_id).children.push(map.get(item.id));\n } else {\n // 根节点直接添加到结果数组中\n result.push(map.get(item.id));\n }\n });\n\n // 递归排序函数\n function sortChildren(nodes) {\n nodes.forEach(node => {\n if (node?.children && node.children.length > 0) {\n node.children.sort((a, b) => a.sort - b.sort); // 按照sort排序\n sortChildren(node.children); // 递归排序子节点\n } else {\n delete node.children;\n }\n });\n }\n\n // 对结果数组中的每个根节点进行排序和子节点排序\n result.sort((a, b) => a.sort - b.sort); // 先对根节点排序\n sortChildren(result); // 然后递归地对每个根节点的子节点排序\n\n res.data = result;\n if (result.length != 0) {\n res.data = result;\n res.total = result.length;\n } else {\n res.total = res.data.length;\n }\n return res;\n } else {\n return useRequest().post(url, params, options);\n }\n}\n\nexport async function getApiUpload(\n params: Record<string, any>,\n url: string,\n options,\n): Promise<any> {\n return useRequest().post(url, params, options);\n}\n\nexport async function getApiUploadPut(\n params: Record<string, any>,\n url: string,\n options,\n): Promise<any> {\n return useRequest().put(url, params, options);\n}\n\nconst apiDataCache = {};\nexport function cachedGetApiData(\n cache_key: string,\n params: { [key: string]: any },\n url: string,\n is_tree?: boolean,\n options: any = {},\n): Promise<any> {\n if (apiDataCache[cache_key]) {\n return apiDataCache[cache_key];\n } else {\n return (apiDataCache[cache_key] = getApiData(params, url, is_tree, options));\n }\n}\n"],"mappings":";;AAEA,eAAsB,EACpB,GACA,GACA,GACA,IAAe,CAAC,GACF;CACd,IAAI,GAAS;EACX,IAAM,IAAW,MAAM,EAAW,CAAC,CAAC,KAAK,GAAK,GAAQ,CAAO,GAEvD,IAAM,IAAI,IACd,EAAI,KAAK,KAAI,MAAQ,CACnB,EAAK,IACL;GAAE,GAAG;GAAM,KAAK,EAAK;GAAI,OAAO,EAAK;GAAI,OAAO,EAAK;GAAM,UAAU,CAAC;EAAE,CAC1E,CAAC,CACH,GACM,IAAS,CAAC;EAGhB,EAAI,KAAK,SAAQ,MAAQ;GAIvB,AAHA,EAAK,MAAM,EAAK,IAChB,EAAK,QAAQ,EAAK,IAClB,EAAK,QAAQ,EAAK,MACd,EAAK,cAAc,QAAQ,EAAI,IAAI,EAAK,SAAS,CAAC,EAAE,WACtD,EAAI,IAAI,EAAK,SAAS,CAAC,CAAC,SAAS,KAAK,EAAI,IAAI,EAAK,EAAE,CAAC,IAGtD,EAAO,KAAK,EAAI,IAAI,EAAK,EAAE,CAAC;EAEhC,CAAC;EAGD,SAAS,EAAa,GAAO;GAC3B,EAAM,SAAQ,MAAQ;IACpB,AAAI,GAAM,YAAY,EAAK,SAAS,SAAS,KAC3C,EAAK,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI,GAC5C,EAAa,EAAK,QAAQ,KAE1B,OAAO,EAAK;GAEhB,CAAC;EACH;EAaA,OAVA,EAAO,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI,GACrC,EAAa,CAAM,GAEnB,EAAI,OAAO,GACP,EAAO,UAAU,IAInB,EAAI,QAAQ,EAAI,KAAK,UAHrB,EAAI,OAAO,GACX,EAAI,QAAQ,EAAO,SAId;CACT,OACE,OAAO,EAAW,CAAC,CAAC,KAAK,GAAK,GAAQ,CAAO;AAEjD;AAEA,eAAsB,EACpB,GACA,GACA,GACc;CACd,OAAO,EAAW,CAAC,CAAC,KAAK,GAAK,GAAQ,CAAO;AAC/C;AAEA,eAAsB,EACpB,GACA,GACA,GACc;CACd,OAAO,EAAW,CAAC,CAAC,IAAI,GAAK,GAAQ,CAAO;AAC9C;AAEA,IAAM,IAAe,CAAC;AACtB,SAAgB,EACd,GACA,GACA,GACA,GACA,IAAe,CAAC,GACF;CAIZ,OAHE,EAAa,KACR,EAAa,KAEZ,EAAa,KAAa,EAAW,GAAQ,GAAK,GAAS,CAAO;AAE9E"}
|
package/dist/api/typing.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"typing.js","names":[],"sources":["../../src/api/typing.ts"],"sourcesContent":["export interface ResponseBody<T = any> {\n message: string;\n code: number;\n data?: T | T[];\n}\n\n/** 统一返回结构体 */\n\nexport interface PageResult<T = any> {\n data: T[];\n current?: number;\n pageSize?: number;\n total?: number;\n success: boolean;\n}\n\nexport interface RequestResult<T = any> {\n data: T;\n success: boolean;\n errorMessage: string;\n}\n\nexport const ConditionOperatorMap = {\n lt: '小于', // 小于\n lte: '小于等于', // 小于等于\n gt: '大于', // 大于\n gte: '大于等于', // 大于等于\n between: '介于', // 介于\n notbetween: '不介于', // 不介于\n in: '包含', // 包含,针对多个值\n eq: '等于', // 等于\n not_eq: '不等于', // 不等于\n contains: '包含(大小写)',\n icontains: '包含',\n startswith: '开头(大小写)',\n istartswith: '开头',\n endswith: '结尾(大小写)',\n iendswith: '结尾',\n notin: '不包含', // 不包含,针对多个值\n notcontains: '不包含(大小写)', // 不包含,针对字符串区分大小写\n noticontains: '不包含', // 不包含,针对字符串不区分大小写\n notstartswith: '不以...开头', // 不包含,针对字符串区分大小写\n notistartswith: '不以...开头,不区分大小写', // 不包含,针对字符串不区分大小写\n notendswith: '不以...结尾(大小写)',\n notiendswith: '不以...结尾',\n _eq: '选择', // 特殊日期\n is_or_not_blank_or_null: '是否为空字符串',\n is_or_not_null: '是否为空',\n} as const;\nexport const operator_params_count = {\n between: 2,\n gt: 1,\n lt: 1,\n gte: 1,\n lte: 1,\n in: 0,\n eq: 1,\n _eq: 1,\n contains: 1,\n icontains: 1,\n startswith: 1,\n notbetween: 2,\n notin: 0,\n notcontains: 1,\n not_eq: 1,\n not_blank_not_null: 1,\n json_list_not_blank_not_null: 1,\n json_list_is_blank_is_null: 1,\n is_or_not_blank_or_null: 1,\n is_or_not_null: 1,\n\n // ---- 以下为补齐的键 ----\n istartswith: 1, // 对应 'istartswith'\n endswith: 1, // 对应 'endswith'\n iendswith: 1, // 对应 'iendswith'\n noticontains: 1, // 对应 'noticontains'\n notstartswith: 1, // 对应 'notstartswith'\n notistartswith: 1, // 对应 'notistartswith'\n notendswith: 1, // 对应 'notendswith'\n notiendswith: 1, // 对应 'notiendswith'\n};\nexport type ConditionOperator = keyof typeof ConditionOperatorMap;\n\nexport const BtnTypeMap = {\n dropdown: 'dropdown', // 下拉\n} as const;\ntype BtnType = keyof typeof BtnTypeMap;\n\nexport const ModelKindMap = {\n confirm: '确认提示框', // (定义显示的title 和 content,和ok 和 cancel 分别调用的接口)\n form: '通用表单', // 带有操作组件的表单\n custom_component: '自定义组件', // 自定义组件\n} as const;\ntype ModelKind = keyof typeof ModelKindMap;\n\nexport interface ConditionConfig {\n flag: string; //字段\n type: string; // 字段类型\n operator: ConditionOperator; // 操作符\n value: any[]; // 值\n}\n\nexport interface ConfirmModelConfig {\n title: string; // 标题\n content: string; // 内容\n ok_url?: string | null; // 确定按钮回调\n cancel_url?: string | null; // 取消按钮回调\n method?: 'post' | 'get' | 'put' | 'delete' | null; // 请求方法,默认post\n init_data?: Record<string, any>; // 初始化数据\n api_fields?: Record<string, string>; // key为提交字段,value为数据来源字段, head_btn 无效\n batch_api_fields?: Record<string, string>; // 批量操作时, 从dataSource中获取数据\n}\nexport interface ComponentModelConfig {\n title?: string | null; // 标题\n component: string; // 组件名称\n ok_url?: string | null; // 确定按钮回调\n cancel_url?: string | null; // 取消按钮回调\n method?: 'post' | 'get' | 'put' | 'delete' | null; // 请求方法,默认post\n init_data?: Record<string, any>; // 初始化数据\n api_fields?: Record<string, string>; // key为提交字段,value为数据来源字段, head_btn 无效\n batch_api_fields?: Record<string, string>; // 批量操作时, 从dataSource中获取数据\n}\n\nexport interface FormConfig {\n settings: Object;\n dynamicFieldList: Object[];\n model: Object;\n rules: Object;\n options: Object;\n}\nexport interface FormModelConfig {\n title: string; // 标题\n form: FormConfig;\n ok_url: string | null; // 确定按钮回调\n cancel_url: string | null; // 取消按钮回调\n method?: 'post' | 'get' | 'put' | 'delete' | null; // 请求方法,默认post\n init_data?: Record<string, any>; // 初始化数据\n api_fields?: Record<string, string>; // key为提交字段,value为数据来源字段\n batch_api_fields?: Record<string, string>; // 批量操作时, 从dataSource中获取数据\n}\n\ntype BtnConfigBase = {\n name: string; // 按钮名称\n type?: BtnType | null; // 按钮类型\n authority?: string | null; // 按钮权限\n order?: number | null; // 按钮显示顺序\n clazz?: string | null; // 按钮样式\n children?: BtnConfigBase[]; // 子按钮\n show_condition?: ConditionConfig[][] | null; // 按钮显示条件\n disabled_condition?: ConditionConfig[][] | null; // 按钮禁用条件\n urls?: string[] | null; // 使用cb 时所需的urls,用于权限配置\n} & (\n | {\n model_kind?: ModelKind; // 模态框类型\n model_config?: ConfirmModelConfig | ComponentModelConfig | FormModelConfig; // 模态框配置\n cb?: never | null;\n }\n | {\n cb?: (Object) => void; // 按钮点击事件,特殊情况下使用,如果定义了model_kind,model_config,则该配置无效\n model_kind?: never | null;\n model_config?: never | null;\n }\n);\n\nexport type BtnConfig = BtnConfigBase & {\n is_show?: Boolean | (({ record }: { record: any }) => boolean) | null; // 按钮是否显示, 配置了show_condition后,is_show无效\n is_disabled?: Boolean | (({ record }: { record: any }) => boolean) | null; // 按钮是否禁用\n preProcessData?: ({ record }: { record: any }) => any; // 数据预处理函数\n beforeCommitProcessData?: ({ record, data }: { record: any; data: any }) => any; // 数据提交前预处理函数\n children?: BtnConfig[];\n};\nexport type HeadBtnConfig = BtnConfigBase & {\n is_show?:\n | Boolean\n | (({ dataSource, selectedRowKeys }: { dataSource: any[]; selectedRowKeys: any[] }) => boolean)\n | null; // 按钮是否显示\n is_disabled?:\n | Boolean\n | (({ dataSource, selectedRowKeys }: { dataSource: any[]; selectedRowKeys: any[] }) => boolean)\n | null; // 按钮是否禁用\n preProcessData?: ({\n dataSource,\n selectedRowKeys,\n }: {\n dataSource: any[];\n selectedRowKeys: any[];\n }) => any[]; // 数据预处理函数\n beforeCommitProcessData?: ({\n dataSource,\n selectedRowKeys,\n data,\n }: {\n dataSource: any[];\n selectedRowKeys: any[];\n data: any;\n }) => any[]; // 数据提交前预处理函数\n children?: HeadBtnConfig[];\n};\n\nexport type BtnListConfig = BtnConfig[];\nexport type HeadBtnListConfig = HeadBtnConfig[];\n\nexport type TitleListSubConfig = {\n show_condition?: ConditionConfig[][] | null; // 按钮显示条件\n disabled_condition?: ConditionConfig[][] | null; // 按钮禁用条件\n is_show?: Boolean | (({ record }: { record: any }) => boolean) | null; // 按钮是否显示, 配置了show_condition后,is_show无效\n is_disabled?: Boolean | (({ record }: { record: any }) => boolean) | null; // 按钮是否禁用\n};\nexport type TitleListCreateSubConfig = {\n show_condition?: ConditionConfig[][] | null; // 按钮显示条件\n disabled_condition?: ConditionConfig[][] | null; // 按钮禁用条件\n is_show?:\n | Boolean\n | (({ dataSource, selectedRowKeys }: { dataSource: any[]; selectedRowKeys: any[] }) => boolean)\n | null; // 按钮是否显示\n is_disabled?:\n | Boolean\n | (({ dataSource, selectedRowKeys }: { dataSource: any[]; selectedRowKeys: any[] }) => boolean)\n | null; // 按钮是否禁用\n};\nexport type TitleListConfig = {\n title: string; // 标题\n addModalTitle: string; // 新建按钮及模态框标题\n updateTitle: string; // 修改模态框标题\n is_create: boolean | string; // 创建按钮权限\n is_update: boolean | string; // 修改按钮权限\n is_remove: boolean | string; // 删除按钮权限\n is_recover: boolean | string; // 恢复按钮权限\n create_config?: TitleListCreateSubConfig;\n update_config?: TitleListSubConfig;\n remove_config?: TitleListSubConfig;\n recover_config?: TitleListSubConfig;\n};\n"],"mappings":";AAsBA,IAAa,IAAuB;CAClC,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL,SAAS;CACT,YAAY;CACZ,IAAI;CACJ,IAAI;CACJ,QAAQ;CACR,UAAU;CACV,WAAW;CACX,YAAY;CACZ,aAAa;CACb,UAAU;CACV,WAAW;CACX,OAAO;CACP,aAAa;CACb,cAAc;CACd,eAAe;CACf,gBAAgB;CAChB,aAAa;CACb,cAAc;CACd,KAAK;CACL,yBAAyB;CACzB,gBAAgB;AAClB,GACa,IAAwB;CACnC,SAAS;CACT,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,UAAU;CACV,WAAW;CACX,YAAY;CACZ,YAAY;CACZ,OAAO;CACP,aAAa;CACb,QAAQ;CACR,oBAAoB;CACpB,8BAA8B;CAC9B,4BAA4B;CAC5B,yBAAyB;CACzB,gBAAgB;CAGhB,aAAa;CACb,UAAU;CACV,WAAW;CACX,cAAc;CACd,eAAe;CACf,gBAAgB;CAChB,aAAa;CACb,cAAc;AAChB,GAGa,IAAa,EACxB,UAAU,WACZ,GAGa,IAAe;CAC1B,SAAS;CACT,MAAM;CACN,kBAAkB;AACpB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"batchCreateUser-B4zAXSR6.js","names":[],"sources":["../src/components/batchCreateUser/batchCreateUser.vue","../src/components/batchCreateUser/batchCreateUser.vue"],"sourcesContent":["<template>\n <a-modal\n :title=\"title\"\n width=\"900px\"\n :open=\"open\"\n :bodyStyle=\"{ height: '75vh', overflowY: 'auto', padding: '0 24px' }\"\n :confirm-loading=\"loading\"\n cancel-text=\"取消\"\n ok-text=\"确定\"\n centered\n destroy-on-close\n @cancel=\"handleCancel\"\n @ok=\"handleOk\"\n >\n <a-form\n layout=\"vertical\"\n size=\"small\"\n >\n <a-row :gutter=\"16\">\n <a-col :span=\"12\">\n <a-form-item\n label=\"组织\"\n required\n >\n <a-select\n v-model:value=\"orgIds\"\n mode=\"multiple\"\n placeholder=\"请选择组织(可多选)\"\n :options=\"orgOptions\"\n :field-names=\"{ label: 'name', value: 'id' }\"\n allow-clear\n show-search\n option-filter-prop=\"name\"\n />\n </a-form-item>\n </a-col>\n <a-col :span=\"12\">\n <a-form-item\n label=\"用户类型\"\n required\n >\n <a-select\n v-model:value=\"manageType\"\n placeholder=\"请选择用户类型\"\n :options=\"manageTypeOptions\"\n />\n </a-form-item>\n </a-col>\n </a-row>\n </a-form>\n\n <div class=\"batch-toolbar\">\n <a-button\n type=\"primary\"\n @click=\"handleAddRow\"\n >\n <plus-outlined />\n 添加\n </a-button>\n <a-upload\n :show-upload-list=\"false\"\n :before-upload=\"beforeImportUpload\"\n accept=\".xlsx,.xls\"\n >\n <a-button>\n <upload-outlined />\n 导入\n </a-button>\n </a-upload>\n <a-button @click=\"handleDownloadTemplate\">\n <download-outlined />\n 下载导入模板\n </a-button>\n <a-popconfirm\n title=\"确认清空所有数据?\"\n @confirm=\"handleClear()\"\n v-if=\"dataSource.length > 0\"\n >\n <a-button\n type=\"default\"\n danger\n >\n 清空\n </a-button>\n </a-popconfirm>\n <span class=\"batch-tip\">共 {{ dataSource.length }} 条</span>\n </div>\n\n <s-table\n :columns=\"columns\"\n :data-source=\"dataSource\"\n :rowKey=\"rowKey\"\n :bordered=\"true\"\n size=\"small\"\n :pagination=\"false\"\n :scroll=\"{ y: 320 }\"\n >\n <template #bodyCell=\"{ column, index, record, recordIndexs }\">\n <template v-if=\"column.dataIndex === 'index'\">\n {{ index + 1 }}\n </template>\n <template v-else-if=\"column.dataIndex === 'username'\">\n <a-input\n v-if=\"record.id === currentEditId\"\n v-model:value=\"dataSource[recordIndexs[0]].username\"\n placeholder=\"请输入账号\"\n allow-clear\n />\n <span v-else>{{ record.username }}</span>\n </template>\n <template v-else-if=\"column.dataIndex === 'realname'\">\n <a-input\n v-if=\"record.id === currentEditId\"\n v-model:value=\"dataSource[recordIndexs[0]].realname\"\n placeholder=\"请输入姓名\"\n allow-clear\n />\n <span v-else>{{ record.realname }}</span>\n </template>\n <template v-else-if=\"column.dataIndex === 'action'\">\n <a-space>\n <a-button\n type=\"link\"\n size=\"small\"\n v-if=\"record.id !== currentEditId\"\n @click=\"handleEdit(record)\"\n >\n 编辑\n </a-button>\n <a-button\n type=\"link\"\n size=\"small\"\n v-else\n @click=\"handleComplete()\"\n >\n 完成\n </a-button>\n <a-popconfirm\n title=\"确认删除该行?\"\n @confirm=\"handleDelete(record)\"\n >\n <a-button\n type=\"link\"\n size=\"small\"\n danger\n >\n 删除\n </a-button>\n </a-popconfirm>\n </a-space>\n </template>\n </template>\n </s-table>\n </a-modal>\n</template>\n\n<script setup lang=\"ts\">\nimport { DownloadOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons-vue';\nimport { message } from 'ant-design-vue';\nimport { read, utils } from 'xlsx';\nimport type { Ref } from 'vue';\nimport { onMounted, ref } from 'vue';\nimport { event_obj, useUserStore } from 'liyu-pc-base/init-plugin';\nimport { getApiData } from 'liyu-pc-base/api/api-model';\nimport { exportJsonToExcel } from 'liyu-pc-base/utils/excel';\n\ninterface Props {\n title?: string;\n record?: any;\n}\nconst props = defineProps<Props>();\nconst emit = defineEmits(['cancel', 'ok']);\n\nconst open = ref(true);\nconst loading = ref(false);\nconst orgIds = ref<any[]>([]);\nconst manageType = ref<number>(0);\nconst orgOptions = ref<any[]>([]);\nconst dataSource = ref<any[]>([]);\nconst currentEditId = ref<string>('');\n\nconst userStore = useUserStore();\nconst current_org = userStore.currentOrg;\n\n// 用户类型可选项:受当前账号 manage_type 约束(与 permission-user 保持一致)\nconst manageTypeOptions = (() => {\n const curr = userStore.person?.manage_type;\n if (curr === 2) {\n return [\n { label: '普通用户', value: 0 },\n { label: '管理员', value: 1 },\n { label: '超级管理员', value: 2 },\n ];\n } else if (curr === 1) {\n return [\n { label: '普通用户', value: 0 },\n { label: '管理员', value: 1 },\n ];\n }\n return [{ label: '普通用户', value: 0 }];\n})();\n\nconst columns = [\n { title: '序号', dataIndex: 'index', width: 70, fixed: 'left' },\n { title: '账号', dataIndex: 'username', width: 220 },\n { title: '姓名', dataIndex: 'realname', width: 220 },\n { title: '操作', dataIndex: 'action', width: 140, fixed: 'right' },\n];\nconst rowKey = 'id';\n\nlet uid = 0;\nconst genId = () => `row_${++uid}`;\n\nconst handleAddRow = () => {\n const id = genId();\n currentEditId.value = id;\n dataSource.value = [...dataSource.value, { id, username: '', realname: '' }];\n};\n\nconst handleEdit = (record: any) => {\n currentEditId.value = record.id;\n dataSource.value = [...dataSource.value];\n};\nconst handleComplete = () => {\n currentEditId.value = '';\n dataSource.value = [...dataSource.value];\n};\nconst handleClear = () => {\n dataSource.value = [];\n};\n\nconst handleDelete = (record: any) => {\n const idx = dataSource.value.findIndex(r => r.id === record.id);\n if (idx > -1) dataSource.value.splice(idx, 1);\n dataSource.value = [...dataSource.value];\n};\n\n// 下载导入模板(账号 / 姓名 两列)\nconst handleDownloadTemplate = () => {\n const percent: Ref<number> = ref(0);\n exportJsonToExcel({\n header: ['账号', '姓名'],\n data: [],\n filename: '批量创建用户导入模板',\n bookType: 'xlsx',\n autoWidth: true,\n percent,\n } as any);\n};\n\n// 导入 Excel:解析“账号 / 姓名”列,追加到表格\nconst beforeImportUpload = (file: any) => {\n const reader = new FileReader();\n reader.onload = (e: any) => {\n try {\n const data = new Uint8Array(e.target.result);\n const workbook = read(data, { type: 'array' });\n const firstSheet = workbook.SheetNames[0];\n const worksheet = workbook.Sheets[firstSheet];\n const sheetData: any[][] = utils.sheet_to_json(worksheet, { header: 1 });\n const headers = (sheetData[0] || []).map((h: any) =>\n String(h ?? '')\n .trim()\n .toLowerCase(),\n );\n const userCol = headers.findIndex(h => ['账号', '用户名', 'username'].includes(h));\n const nameCol = headers.findIndex(h => ['姓名', '名字', 'realname', 'name'].includes(h));\n if (userCol === -1 && nameCol === -1) {\n message.warning('未识别到“账号/姓名”列,请使用下载的模板');\n return;\n }\n const rows = sheetData\n .slice(1)\n .filter((row: any[]) => row && row.some(c => c !== '' && c != null));\n let added = 0;\n const newRows = [];\n rows.forEach((row: any[]) => {\n const username = userCol > -1 ? String(row[userCol] ?? '').trim() : '';\n const realname = nameCol > -1 ? String(row[nameCol] ?? '').trim() : '';\n if (!username && !realname) return;\n newRows.push({ id: genId(), username, realname });\n added++;\n });\n dataSource.value = [...dataSource.value, ...newRows];\n if (added > 0) message.success(`已导入 ${added} 条`);\n else message.info('文件中没有可导入的数据');\n } catch (err) {\n console.error(err);\n message.error('解析 Excel 失败');\n }\n };\n reader.readAsArrayBuffer(file);\n return false; // 阻止自动上传\n};\n\nconst handleOk = async () => {\n // 前置校验\n if (!orgIds.value || orgIds.value.length === 0) {\n message.error('请至少选择一个组织');\n return;\n }\n if (manageType.value === null || manageType.value === undefined) {\n message.error('请选择用户类型');\n return;\n }\n if (dataSource.value.length === 0) {\n message.error('请至少添加一条用户信息');\n return;\n }\n // 校验账号/姓名非空,且账号不重复\n const seen = new Set<string>();\n for (const row of dataSource.value) {\n const username = (row.username || '').trim();\n const realname = (row.realname || '').trim();\n if (!username) {\n message.error('账号不能为空,请检查表格');\n return;\n }\n if (!realname) {\n message.error(`账号 [${username}] 的姓名不能为空`);\n return;\n }\n if (seen.has(username)) {\n message.error(`账号 [${username}] 重复,请检查`);\n return;\n }\n seen.add(username);\n }\n\n const payload = {\n org_ids: orgIds.value,\n manage_type: manageType.value,\n user_list: dataSource.value.map(r => ({\n username: (r.username || '').trim(),\n realname: (r.realname || '').trim(),\n })),\n org_id: current_org?.id,\n };\n\n loading.value = true;\n try {\n await getApiData(payload, '/sys/create_batch_user');\n message.success(`批量创建完成`);\n event_obj()?.emit('refresh');\n emit('ok');\n } catch (err) {\n console.error(err);\n // 错误提示已由请求拦截器统一处理\n } finally {\n loading.value = false;\n }\n};\n\nconst handleCancel = () => emit('cancel');\n\nonMounted(async () => {\n try {\n const res: any = await getApiData({ is_pagination: false }, '/org/query_org_for_person_admin');\n const list = res?.data ?? res ?? [];\n orgOptions.value = Array.isArray(list) ? list : [];\n } catch (err) {\n console.error('加载组织列表失败', err);\n }\n});\n</script>\n\n<style scoped lang=\"less\">\n.batch-toolbar {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n}\n.batch-tip {\n margin-left: auto;\n color: #999;\n font-size: 12px;\n}\n</style>\n","<template>\n <a-modal\n :title=\"title\"\n width=\"900px\"\n :open=\"open\"\n :bodyStyle=\"{ height: '75vh', overflowY: 'auto', padding: '0 24px' }\"\n :confirm-loading=\"loading\"\n cancel-text=\"取消\"\n ok-text=\"确定\"\n centered\n destroy-on-close\n @cancel=\"handleCancel\"\n @ok=\"handleOk\"\n >\n <a-form\n layout=\"vertical\"\n size=\"small\"\n >\n <a-row :gutter=\"16\">\n <a-col :span=\"12\">\n <a-form-item\n label=\"组织\"\n required\n >\n <a-select\n v-model:value=\"orgIds\"\n mode=\"multiple\"\n placeholder=\"请选择组织(可多选)\"\n :options=\"orgOptions\"\n :field-names=\"{ label: 'name', value: 'id' }\"\n allow-clear\n show-search\n option-filter-prop=\"name\"\n />\n </a-form-item>\n </a-col>\n <a-col :span=\"12\">\n <a-form-item\n label=\"用户类型\"\n required\n >\n <a-select\n v-model:value=\"manageType\"\n placeholder=\"请选择用户类型\"\n :options=\"manageTypeOptions\"\n />\n </a-form-item>\n </a-col>\n </a-row>\n </a-form>\n\n <div class=\"batch-toolbar\">\n <a-button\n type=\"primary\"\n @click=\"handleAddRow\"\n >\n <plus-outlined />\n 添加\n </a-button>\n <a-upload\n :show-upload-list=\"false\"\n :before-upload=\"beforeImportUpload\"\n accept=\".xlsx,.xls\"\n >\n <a-button>\n <upload-outlined />\n 导入\n </a-button>\n </a-upload>\n <a-button @click=\"handleDownloadTemplate\">\n <download-outlined />\n 下载导入模板\n </a-button>\n <a-popconfirm\n title=\"确认清空所有数据?\"\n @confirm=\"handleClear()\"\n v-if=\"dataSource.length > 0\"\n >\n <a-button\n type=\"default\"\n danger\n >\n 清空\n </a-button>\n </a-popconfirm>\n <span class=\"batch-tip\">共 {{ dataSource.length }} 条</span>\n </div>\n\n <s-table\n :columns=\"columns\"\n :data-source=\"dataSource\"\n :rowKey=\"rowKey\"\n :bordered=\"true\"\n size=\"small\"\n :pagination=\"false\"\n :scroll=\"{ y: 320 }\"\n >\n <template #bodyCell=\"{ column, index, record, recordIndexs }\">\n <template v-if=\"column.dataIndex === 'index'\">\n {{ index + 1 }}\n </template>\n <template v-else-if=\"column.dataIndex === 'username'\">\n <a-input\n v-if=\"record.id === currentEditId\"\n v-model:value=\"dataSource[recordIndexs[0]].username\"\n placeholder=\"请输入账号\"\n allow-clear\n />\n <span v-else>{{ record.username }}</span>\n </template>\n <template v-else-if=\"column.dataIndex === 'realname'\">\n <a-input\n v-if=\"record.id === currentEditId\"\n v-model:value=\"dataSource[recordIndexs[0]].realname\"\n placeholder=\"请输入姓名\"\n allow-clear\n />\n <span v-else>{{ record.realname }}</span>\n </template>\n <template v-else-if=\"column.dataIndex === 'action'\">\n <a-space>\n <a-button\n type=\"link\"\n size=\"small\"\n v-if=\"record.id !== currentEditId\"\n @click=\"handleEdit(record)\"\n >\n 编辑\n </a-button>\n <a-button\n type=\"link\"\n size=\"small\"\n v-else\n @click=\"handleComplete()\"\n >\n 完成\n </a-button>\n <a-popconfirm\n title=\"确认删除该行?\"\n @confirm=\"handleDelete(record)\"\n >\n <a-button\n type=\"link\"\n size=\"small\"\n danger\n >\n 删除\n </a-button>\n </a-popconfirm>\n </a-space>\n </template>\n </template>\n </s-table>\n </a-modal>\n</template>\n\n<script setup lang=\"ts\">\nimport { DownloadOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons-vue';\nimport { message } from 'ant-design-vue';\nimport { read, utils } from 'xlsx';\nimport type { Ref } from 'vue';\nimport { onMounted, ref } from 'vue';\nimport { event_obj, useUserStore } from 'liyu-pc-base/init-plugin';\nimport { getApiData } from 'liyu-pc-base/api/api-model';\nimport { exportJsonToExcel } from 'liyu-pc-base/utils/excel';\n\ninterface Props {\n title?: string;\n record?: any;\n}\nconst props = defineProps<Props>();\nconst emit = defineEmits(['cancel', 'ok']);\n\nconst open = ref(true);\nconst loading = ref(false);\nconst orgIds = ref<any[]>([]);\nconst manageType = ref<number>(0);\nconst orgOptions = ref<any[]>([]);\nconst dataSource = ref<any[]>([]);\nconst currentEditId = ref<string>('');\n\nconst userStore = useUserStore();\nconst current_org = userStore.currentOrg;\n\n// 用户类型可选项:受当前账号 manage_type 约束(与 permission-user 保持一致)\nconst manageTypeOptions = (() => {\n const curr = userStore.person?.manage_type;\n if (curr === 2) {\n return [\n { label: '普通用户', value: 0 },\n { label: '管理员', value: 1 },\n { label: '超级管理员', value: 2 },\n ];\n } else if (curr === 1) {\n return [\n { label: '普通用户', value: 0 },\n { label: '管理员', value: 1 },\n ];\n }\n return [{ label: '普通用户', value: 0 }];\n})();\n\nconst columns = [\n { title: '序号', dataIndex: 'index', width: 70, fixed: 'left' },\n { title: '账号', dataIndex: 'username', width: 220 },\n { title: '姓名', dataIndex: 'realname', width: 220 },\n { title: '操作', dataIndex: 'action', width: 140, fixed: 'right' },\n];\nconst rowKey = 'id';\n\nlet uid = 0;\nconst genId = () => `row_${++uid}`;\n\nconst handleAddRow = () => {\n const id = genId();\n currentEditId.value = id;\n dataSource.value = [...dataSource.value, { id, username: '', realname: '' }];\n};\n\nconst handleEdit = (record: any) => {\n currentEditId.value = record.id;\n dataSource.value = [...dataSource.value];\n};\nconst handleComplete = () => {\n currentEditId.value = '';\n dataSource.value = [...dataSource.value];\n};\nconst handleClear = () => {\n dataSource.value = [];\n};\n\nconst handleDelete = (record: any) => {\n const idx = dataSource.value.findIndex(r => r.id === record.id);\n if (idx > -1) dataSource.value.splice(idx, 1);\n dataSource.value = [...dataSource.value];\n};\n\n// 下载导入模板(账号 / 姓名 两列)\nconst handleDownloadTemplate = () => {\n const percent: Ref<number> = ref(0);\n exportJsonToExcel({\n header: ['账号', '姓名'],\n data: [],\n filename: '批量创建用户导入模板',\n bookType: 'xlsx',\n autoWidth: true,\n percent,\n } as any);\n};\n\n// 导入 Excel:解析“账号 / 姓名”列,追加到表格\nconst beforeImportUpload = (file: any) => {\n const reader = new FileReader();\n reader.onload = (e: any) => {\n try {\n const data = new Uint8Array(e.target.result);\n const workbook = read(data, { type: 'array' });\n const firstSheet = workbook.SheetNames[0];\n const worksheet = workbook.Sheets[firstSheet];\n const sheetData: any[][] = utils.sheet_to_json(worksheet, { header: 1 });\n const headers = (sheetData[0] || []).map((h: any) =>\n String(h ?? '')\n .trim()\n .toLowerCase(),\n );\n const userCol = headers.findIndex(h => ['账号', '用户名', 'username'].includes(h));\n const nameCol = headers.findIndex(h => ['姓名', '名字', 'realname', 'name'].includes(h));\n if (userCol === -1 && nameCol === -1) {\n message.warning('未识别到“账号/姓名”列,请使用下载的模板');\n return;\n }\n const rows = sheetData\n .slice(1)\n .filter((row: any[]) => row && row.some(c => c !== '' && c != null));\n let added = 0;\n const newRows = [];\n rows.forEach((row: any[]) => {\n const username = userCol > -1 ? String(row[userCol] ?? '').trim() : '';\n const realname = nameCol > -1 ? String(row[nameCol] ?? '').trim() : '';\n if (!username && !realname) return;\n newRows.push({ id: genId(), username, realname });\n added++;\n });\n dataSource.value = [...dataSource.value, ...newRows];\n if (added > 0) message.success(`已导入 ${added} 条`);\n else message.info('文件中没有可导入的数据');\n } catch (err) {\n console.error(err);\n message.error('解析 Excel 失败');\n }\n };\n reader.readAsArrayBuffer(file);\n return false; // 阻止自动上传\n};\n\nconst handleOk = async () => {\n // 前置校验\n if (!orgIds.value || orgIds.value.length === 0) {\n message.error('请至少选择一个组织');\n return;\n }\n if (manageType.value === null || manageType.value === undefined) {\n message.error('请选择用户类型');\n return;\n }\n if (dataSource.value.length === 0) {\n message.error('请至少添加一条用户信息');\n return;\n }\n // 校验账号/姓名非空,且账号不重复\n const seen = new Set<string>();\n for (const row of dataSource.value) {\n const username = (row.username || '').trim();\n const realname = (row.realname || '').trim();\n if (!username) {\n message.error('账号不能为空,请检查表格');\n return;\n }\n if (!realname) {\n message.error(`账号 [${username}] 的姓名不能为空`);\n return;\n }\n if (seen.has(username)) {\n message.error(`账号 [${username}] 重复,请检查`);\n return;\n }\n seen.add(username);\n }\n\n const payload = {\n org_ids: orgIds.value,\n manage_type: manageType.value,\n user_list: dataSource.value.map(r => ({\n username: (r.username || '').trim(),\n realname: (r.realname || '').trim(),\n })),\n org_id: current_org?.id,\n };\n\n loading.value = true;\n try {\n await getApiData(payload, '/sys/create_batch_user');\n message.success(`批量创建完成`);\n event_obj()?.emit('refresh');\n emit('ok');\n } catch (err) {\n console.error(err);\n // 错误提示已由请求拦截器统一处理\n } finally {\n loading.value = false;\n }\n};\n\nconst handleCancel = () => emit('cancel');\n\nonMounted(async () => {\n try {\n const res: any = await getApiData({ is_pagination: false }, '/org/query_org_for_person_admin');\n const list = res?.data ?? res ?? [];\n orgOptions.value = Array.isArray(list) ? list : [];\n } catch (err) {\n console.error('加载组织列表失败', err);\n }\n});\n</script>\n\n<style scoped lang=\"less\">\n.batch-toolbar {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n}\n.batch-tip {\n margin-left: auto;\n color: #999;\n font-size: 12px;\n}\n</style>\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"boldenText-Bv8Zo7Vh.js","names":[],"sources":["../src/components/FormRender/RemoteSelect/boldenText.vue","../src/components/FormRender/RemoteSelect/boldenText.vue"],"sourcesContent":["<template>\n <div>\n <div v-html=\"boldenText\"></div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, ref, computed } from 'vue';\n\nexport default defineComponent({\n name: 'BoldMatcher',\n props: {\n text: {\n type: String,\n required: true,\n },\n pattern: {\n type: String,\n required: true,\n },\n color: {\n type: String,\n default: () => '',\n },\n },\n setup(props) {\n const boldenText = computed(() => {\n // 使用正则表达式找到所有匹配项\n const regex = new RegExp(`(${props.pattern})`, 'g');\n // 使用replace方法将匹配项包裹在<b>标签中\n if (!props.text) {\n return '';\n }\n return props.text?.replace(\n regex,\n `<span style='font-weight: 700; color: ${props.color}'>$&</span>`,\n );\n });\n\n return {\n boldenText,\n };\n },\n});\n</script>\n","<template>\n <div>\n <div v-html=\"boldenText\"></div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, ref, computed } from 'vue';\n\nexport default defineComponent({\n name: 'BoldMatcher',\n props: {\n text: {\n type: String,\n required: true,\n },\n pattern: {\n type: String,\n required: true,\n },\n color: {\n type: String,\n default: () => '',\n },\n },\n setup(props) {\n const boldenText = computed(() => {\n // 使用正则表达式找到所有匹配项\n const regex = new RegExp(`(${props.pattern})`, 'g');\n // 使用replace方法将匹配项包裹在<b>标签中\n if (!props.text) {\n return '';\n }\n return props.text?.replace(\n regex,\n `<span style='font-weight: 700; color: ${props.color}'>$&</span>`,\n );\n });\n\n return {\n boldenText,\n };\n },\n});\n</script>\n"],"mappings":";;;AASA,IAAA,IAAe,EAAgB;CAC7B,MAAM;CACN,OAAO;EACL,MAAM;GACJ,MAAM;GACN,UAAU;EACZ;EACA,SAAS;GACP,MAAM;GACN,UAAU;EACZ;EACA,OAAO;GACL,MAAM;GACN,eAAe;EACjB;CACF;CACA,MAAM,GAAO;EAcX,OAAO,EACL,YAdiB,QAAe;GAEhC,IAAM,IAAY,OAAO,IAAI,EAAM,QAAQ,IAAI,GAAG;GAKlD,OAHK,EAAM,OAGJ,EAAM,MAAM,QACjB,GACA,yCAAyC,EAAM,MAAM,YACvD,IALS;EAMX,CAGE,EACF;CACF;AACF,CAAC,OC3CD,CAAA,WAAA;;aACE,EAEM,OAAA,MAAA,CADJ,EAA+B,OAAA,EAA1B,WAAQ,EAAA,WAAU,GAAA,MAAA,GAF3B,CAAA,CAAA,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":[],"sources":["../../../src/components/FormRender/utils.ts"],"sourcesContent":["import type { PageResult } from 'liyu-pc-base/api/typing';\nimport { remoteSelectStore, useUserStore } from 'liyu-pc-base/init-plugin';\nimport { message } from 'ant-design-vue';\n\n/**\n * 从嵌套对象中按路径取值。\n * 支持点号写法 a.b.c 和数组索引写法 params[0].name。\n */\nexport function getNestedValue(obj: any, path: string): any {\n if (!path) return undefined;\n const tokens = path.match(/[^.\\[\\]]+|\\[\\d+\\]/g);\n if (!tokens) return undefined;\n return tokens.reduce((current, token) => {\n if (token.startsWith('[')) {\n return current?.[parseInt(token.slice(1, -1), 10)];\n }\n return current?.[token];\n }, obj);\n}\n\n/**\n * 解析相对于 baseKeyPath 的表达式,从 context 中获取值。\n *\n * baseKeyPath 是扁平路径段数组:string 段为对象属性名,number 段为数组索引。\n * 例如 [\"formModel\", \"formtemplate_75589\", 0, \"formtemplate_37262\", 0] 表示\n * 当前节点位于 context.formModel.formtemplate_75589[0].formtemplate_37262[0]。\n *\n * 表达式语法(以 @ 开头时触发):\n *\n * 1. @<key>.<path>\n * 在 baseKeyPath 中找到 <key>,构建从 context 到该 key(含自动跟随的数组索引)的完整路径,再追加 <path>。\n * 示例: baseKeyPath = [\"formModel\", \"a\", 0, \"b\", 0]\n * @a.name → context.formModel.a[0].name\n * @b.name → context.formModel.a[0].b[0].name\n * @formModel.x → context.formModel.x (formModel 后面不是数字,不加索引)\n *\n * 2. @<key>[<index>].<path>\n * 同上,但将该层级的数组索引覆盖为 <index>,用于获取同级数组其他项的属性。\n * @b[1].name → context.formModel.a[0].b[1].name\n * @a[2].name → context.formModel.a[2].name\n *\n * 3. @<level><rest> (level 为数字,按路径段逐层回退)\n * 每个路径段是一个 key 或一个 index,@N 表示从末尾去掉 N 个段。\n * rest 可以是 .property 或 [index].property 等追加路径。\n * @0.name → context.formModel.a[0].b[0].name (当前项)\n * @1 → context.formModel.a[0].b (退掉最后的 [0],得到数组)\n * @1[1].name → context.formModel.a[0].b[1].name (同级数组第1项的 name)\n * @2.name → context.formModel.a[0].name (再退掉 b,得到父项)\n *\n * 4. 不以 @ 开头\n * 向后兼容:直接作为完整路径从 context 中取值。\n * a[0].b[0].name → context.a[0].b[0].name\n */\nexport function resolveContextValue(selectName: string, context: any, baseKeyPath: any[]): any {\n if (!selectName) return undefined;\n\n // 不以 @ 开头:向后兼容,直接作为完整路径解析\n if (!selectName.startsWith('@')) {\n return getNestedValue(context, selectName);\n }\n\n const basePath = baseKeyPath || [];\n if (!basePath || basePath.length === 0) {\n return getNestedValue(context, selectName.slice(1));\n }\n\n // 去掉 @ 前缀\n const expr = selectName.slice(1);\n\n // 辅助函数:将 baseKeyPath 的段数组构建为路径字符串\n // string 段 → .propertyName,number 段 → [index]\n const buildPathFromSegments = (segments: any[]): string => {\n let path = '';\n for (const seg of segments) {\n if (typeof seg === 'number') {\n path += `[${seg}]`;\n } else {\n path += path ? `.${seg}` : seg;\n }\n }\n return path;\n };\n\n // 尝试匹配数字层级语法:@<level><rest>\n const levelMatch = expr.match(/^(\\d+)(.*)$/);\n if (levelMatch) {\n const [, levelStr, restRaw] = levelMatch;\n const level = parseInt(levelStr, 10);\n const keepSegments = basePath.length - level;\n\n let fullPath = '';\n if (keepSegments > 0) {\n fullPath = buildPathFromSegments(basePath.slice(0, keepSegments));\n }\n\n if (restRaw) {\n if (restRaw.startsWith('.') || restRaw.startsWith('[')) {\n fullPath += restRaw;\n } else {\n fullPath += `.${restRaw}`;\n }\n }\n\n if (keepSegments <= 0 && !restRaw) {\n return context;\n }\n return getNestedValue(context, fullPath);\n }\n\n // 匹配 key 名称语法:@<key>[<index>].<path> 或 @<key>.<path>\n const keyMatch = expr.match(/^([a-zA-Z_]\\w*)(?:\\[(\\d+)\\])?\\.?(.*)$/);\n if (!keyMatch) {\n return getNestedValue(context, expr);\n }\n\n const [, targetKey, keyIdxOverride, keyRestPath] = keyMatch;\n\n // 在 baseKeyPath 中查找 targetKey(从后往前,取最深的匹配)\n let targetKeyIndex = -1;\n for (let i = basePath.length - 1; i >= 0; i--) {\n if (basePath[i] === targetKey) {\n targetKeyIndex = i;\n break;\n }\n }\n\n if (targetKeyIndex === -1) {\n return getNestedValue(context, expr);\n }\n\n // 构建从 context 到目标 key 的完整路径(包含 key 本身及其前面的所有段)\n const segments = basePath.slice(0, targetKeyIndex + 1);\n let fullPath = buildPathFromSegments(segments);\n\n // 处理 key 后面的数组索引:\n // - 如果手动指定了 index(@key[N]),用指定的 N\n // - 否则如果 key 后面紧跟一个数字段,自动包含该索引(key[index])\n if (keyIdxOverride !== undefined) {\n fullPath += `[${keyIdxOverride}]`;\n } else if (targetKeyIndex + 1 < basePath.length && typeof basePath[targetKeyIndex + 1] === 'number') {\n fullPath += `[${basePath[targetKeyIndex + 1]}]`;\n }\n\n if (keyRestPath) {\n fullPath += `.${keyRestPath}`;\n }\n return getNestedValue(context, fullPath);\n}\n\nconst obj2json = (obj: any): string => {\n if (obj instanceof Array) {\n return obj.join();\n } else if (obj instanceof Object) {\n return JSON.stringify(obj);\n } else {\n return obj.toString();\n }\n};\n\nconst obj2str = (obj: any): string => {\n if (obj instanceof Array) {\n return obj.join();\n } else if (typeof obj === 'number') {\n return String(obj);\n } else if (obj === undefined) {\n return 'undefined';\n } else if (obj === null) {\n return 'null';\n } else if (typeof obj === 'boolean') {\n return String(obj);\n } else if (typeof obj === 'object') {\n return Object.keys(obj)\n .sort((a, b) => a.localeCompare(b))\n .map((key: string) => {\n return `${key}-${obj2json(obj[key])}`;\n })\n .join();\n } else {\n console.error('error type' + typeof obj);\n return obj.toString();\n }\n};\n\nexport default (api_fun: any, api_url?: string): any => {\n const fun = (params: Record<string, any>, noCache?: boolean): Promise<PageResult> => {\n const userStore = useUserStore();\n const org = userStore.currentOrg;\n const paramsKey = Object.keys(params)\n .sort((a, b) => a.localeCompare(b))\n .map((key: string) => {\n return `${key}-${obj2str(params[key])}`;\n })\n .join();\n const time = new Date().getTime() + 3600 * 1000;\n const obj = remoteSelectStore().get(`${org?.id}_${api_url}`);\n\n return new Promise(resolve => {\n if (!noCache && obj && obj.time > new Date().getTime() && obj.paramsKey == paramsKey) {\n resolve(obj.data);\n } else {\n api_fun(params)\n .then((res: any) => {\n remoteSelectStore().set(`${org?.id}_${api_url}`, {\n data: res,\n time: time,\n paramsKey: paramsKey,\n });\n resolve(res);\n })\n .catch(() => {\n message.destroy();\n message.error('接口调用失败', 10);\n });\n }\n });\n };\n return fun;\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":[],"sources":["../../../src/components/gridPage/utils.ts"],"sourcesContent":["import { inject, Ref } from 'vue';\nimport { Emitter } from 'mitt';\n\nexport const gridPageStateSymbol = Symbol('gridPageState');\nexport interface GridPageState {\n context: Ref<any>;\n eventBus: Emitter<Record<string, any>>;\n}\nexport const useGridPageState = (): GridPageState => {\n const state = inject<GridPageState>(gridPageStateSymbol);\n return state;\n};\n"],"mappings":";;AAGA,IAAa,IAAsB,OAAO,eAAe,GAK5C,UACG,EAAsB,CAC7B"}
|