vome-core 0.0.28 → 0.0.32
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/admin/components/vm-aside-list-item.vue +18 -6
- package/dist/admin/components/vm-card.vue +13 -7
- package/dist/admin/components/vm-page-tabs.vue +3 -2
- package/dist/admin/components/vm-split-layout.vue +4 -0
- package/dist/admin/config/plugin-dev.js +1 -1
- package/dist/admin/crud/components/vm-form-hint.vue +40 -22
- package/dist/admin/crud/config.js +1 -1
- package/dist/admin/crud/confirm.js +1 -1
- package/dist/admin/crud/dict.js +1 -1
- package/dist/admin/crud/index.d.ts +1 -1
- package/dist/admin/crud/index.js +1 -1
- package/dist/admin/crud/key.js +1 -1
- package/dist/admin/crud/mitt.js +1 -1
- package/dist/admin/crud/plugins.js +1 -1
- package/dist/admin/crud/span.js +1 -1
- package/dist/admin/crud/style.js +1 -1
- package/dist/admin/crud/validate.js +1 -1
- package/dist/admin/crud/vm-import-btn.vue +686 -0
- package/dist/admin/crud/vm-toolbar.vue +16 -0
- package/dist/admin/directives/perm.js +1 -1
- package/dist/admin/hooks/useUpload.js +1 -1
- package/dist/admin/lib/browser.js +1 -1
- package/dist/admin/lib/cn.js +1 -1
- package/dist/admin/lib/dialog-float.js +1 -1
- package/dist/admin/lib/export-excel.js +1 -1
- package/dist/admin/lib/file-preview.js +1 -1
- package/dist/admin/lib/import-excel.d.ts +18 -0
- package/dist/admin/lib/import-excel.js +1 -0
- package/dist/admin/lib/json.js +1 -1
- package/dist/admin/lib/menu.js +1 -1
- package/dist/admin/lib/tree.js +1 -1
- package/dist/admin/lib/upload.js +1 -1
- package/dist/admin/lib/video-frame.js +1 -1
- package/dist/admin/router/index.js +13 -3
- package/dist/client/vite-plugin-eps.d.ts +3 -3
- package/dist/client/vite-plugin-eps.js +6 -2
- package/dist/index.js +1 -1
- package/dist/server/index.js +1 -1
- package/dist/shared/excel.d.ts +10 -0
- package/dist/shared/excel.js +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/tree.js +1 -1
- package/dist/src/core/index.d.ts +2 -2
- package/dist/src/ext/index.d.ts +1 -1
- package/dist/src/ext/load-plugin.d.ts +16 -0
- package/dist/src/orm/import-excel.d.ts +31 -0
- package/dist/src/routing/index.d.ts +1 -0
- package/dist/src/routing/public-routes.d.ts +6 -0
- package/dist/src/server/index.d.ts +2 -2
- package/dist/src/shared/excel.d.ts +10 -0
- package/dist/src/shared/index.d.ts +1 -1
- package/dist/typings/routing/crud.d.ts +5 -0
- package/package.json +8 -3
- package/src/shared/excel.d.ts +10 -0
- package/src/shared/excel.ts +77 -0
- package/src/shared/index.ts +4 -0
- package/dist/admin/crud/components/vm-json-viewer.vue +0 -147
package/dist/shared/excel.d.ts
CHANGED
|
@@ -3,8 +3,18 @@ export type ExcelColumn = {
|
|
|
3
3
|
label: string;
|
|
4
4
|
};
|
|
5
5
|
export type ExcelFormatCell = (prop: string, row: Record<string, unknown>) => string;
|
|
6
|
+
/** 导入模板排除的自动字段(实体公共列) */
|
|
7
|
+
export declare const IMPORT_SKIP_FIELDS: readonly ["id", "createTime", "updateTime", "deletedAt", "tenantId"];
|
|
8
|
+
export declare function isImportSkipField(name: string): boolean;
|
|
6
9
|
/** 二维表 → xlsx 二进制 */
|
|
7
10
|
export declare function buildExcelBuffer(columns: ExcelColumn[], rows: Record<string, unknown>[], formatCell?: ExcelFormatCell): Uint8Array;
|
|
11
|
+
/** 仅表头的导入模板 */
|
|
12
|
+
export declare function buildImportTemplateBuffer(columns: ExcelColumn[]): Uint8Array;
|
|
13
|
+
/**
|
|
14
|
+
* 解析 xlsx:首行表头 → 行对象。
|
|
15
|
+
* 表头可为字段名或中文 label(通过 columns 反查 prop)。
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseExcelBuffer(data: ArrayBuffer | Uint8Array, columns?: ExcelColumn[]): Record<string, unknown>[];
|
|
8
18
|
export declare function excelFilename(name: string): string;
|
|
9
19
|
/** Service 下载响应头 */
|
|
10
20
|
export declare function excelResponseHeaders(filename: string): {
|
package/dist/shared/excel.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
const _0x1921d2=_0x3dc7;(function(_0x159f93,_0x443a33){const _0x570d0c=_0x3dc7,_0x155501=_0x159f93();while(!![]){try{const _0x33c4d1=-parseInt(_0x570d0c(0xf6))/0x1*(parseInt(_0x570d0c(0xf3))/0x2)+-parseInt(_0x570d0c(0xeb))/0x3+-parseInt(_0x570d0c(0xe7))/0x4*(parseInt(_0x570d0c(0xf5))/0x5)+parseInt(_0x570d0c(0xfb))/0x6*(-parseInt(_0x570d0c(0xe9))/0x7)+parseInt(_0x570d0c(0xea))/0x8*(parseInt(_0x570d0c(0xde))/0x9)+-parseInt(_0x570d0c(0xe3))/0xa+-parseInt(_0x570d0c(0xe4))/0xb*(-parseInt(_0x570d0c(0xf9))/0xc);if(_0x33c4d1===_0x443a33)break;else _0x155501['push'](_0x155501['shift']());}catch(_0x5e4413){_0x155501['push'](_0x155501['shift']());}}}(_0x4bb4,0xe8333));function _0x3dc7(_0x4c8a58,_0x29f3a1){_0x4c8a58=_0x4c8a58-0xdb;const _0x4bb411=_0x4bb4();let _0x3dc7fa=_0x4bb411[_0x4c8a58];if(_0x3dc7['bMaXFZ']===undefined){var _0x44cbfa=function(_0x5c67c9){const _0x4fd771='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x41a123='',_0x5ad8cd='';for(let _0x3ac08d=0x0,_0x44e5e1,_0x463106,_0x4b44d7=0x0;_0x463106=_0x5c67c9['charAt'](_0x4b44d7++);~_0x463106&&(_0x44e5e1=_0x3ac08d%0x4?_0x44e5e1*0x40+_0x463106:_0x463106,_0x3ac08d++%0x4)?_0x41a123+=String['fromCharCode'](0xff&_0x44e5e1>>(-0x2*_0x3ac08d&0x6)):0x0){_0x463106=_0x4fd771['indexOf'](_0x463106);}for(let _0x146bfd=0x0,_0x13950a=_0x41a123['length'];_0x146bfd<_0x13950a;_0x146bfd++){_0x5ad8cd+='%'+('00'+_0x41a123['charCodeAt'](_0x146bfd)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x5ad8cd);};_0x3dc7['tWRTzm']=_0x44cbfa,_0x3dc7['IPHoZR']={},_0x3dc7['bMaXFZ']=!![];}const _0x324acb=_0x4bb411[0x0],_0x3f60fd=_0x4c8a58+_0x324acb,_0x2106d7=_0x3dc7['IPHoZR'][_0x3f60fd];return!_0x2106d7?(_0x3dc7fa=_0x3dc7['tWRTzm'](_0x3dc7fa),_0x3dc7['IPHoZR'][_0x3f60fd]=_0x3dc7fa):_0x3dc7fa=_0x2106d7,_0x3dc7fa;}import*as _0x41a123 from'xlsx';export const IMPORT_SKIP_FIELDS=['id',_0x1921d2(0xf8),_0x1921d2(0xf4),_0x1921d2(0xdc),'tenantId'];export function isImportSkipField(_0x5ad8cd){return IMPORT_SKIP_FIELDS['includes'](_0x5ad8cd);}export function buildExcelBuffer(_0x3ac08d,_0x44e5e1,_0x463106){const _0x20deb9=_0x1921d2,_0x4b44d7=_0x3ac08d[_0x20deb9(0xdf)](_0x2b91cc=>_0x2b91cc[_0x20deb9(0xf0)]||_0x2b91cc[_0x20deb9(0xe2)]),_0x146bfd=_0x44e5e1[_0x20deb9(0xdf)](_0x460d04=>_0x3ac08d['map'](_0x3fba6f=>{const _0x4b7260=_0x20deb9;if(_0x463106)return _0x463106(_0x3fba6f[_0x4b7260(0xe2)],_0x460d04);const _0x453007=_0x460d04[_0x3fba6f[_0x4b7260(0xe2)]];if(_0x453007==null)return'';return String(_0x453007);})),_0x13950a=_0x41a123[_0x20deb9(0xef)][_0x20deb9(0xfa)]([_0x4b44d7,..._0x146bfd]),_0x598068=_0x41a123['utils'][_0x20deb9(0xdb)]();return _0x41a123[_0x20deb9(0xef)]['book_append_sheet'](_0x598068,_0x13950a,_0x20deb9(0xf2)),_0x41a123[_0x20deb9(0xec)](_0x598068,{'bookType':_0x20deb9(0xee),'type':_0x20deb9(0xe6)});}export function buildImportTemplateBuffer(_0x5b2e68){return buildExcelBuffer(_0x5b2e68,[]);}export function parseExcelBuffer(_0x31d9b9,_0x37266f){const _0x9210db=_0x1921d2,_0x185146=_0x41a123[_0x9210db(0xe5)](_0x31d9b9,{'type':_0x9210db(0xe6),'cellDates':!![]}),_0x274ae9=_0x185146['SheetNames'][0x0];if(!_0x274ae9)return[];const _0x571171=_0x185146['Sheets'][_0x274ae9];if(!_0x571171)return[];const _0xefc132=_0x41a123[_0x9210db(0xef)][_0x9210db(0xf7)](_0x571171,{'header':0x1,'defval':'','raw':![]});if(!_0xefc132[_0x9210db(0xfd)])return[];const _0x2f1735=(_0xefc132[0x0]||[])[_0x9210db(0xdf)](_0x4c1514=>String(_0x4c1514??'')['trim']()),_0x34bd5b=new Map();if(_0x37266f?.[_0x9210db(0xfd)])for(const _0x162d73 of _0x37266f){_0x34bd5b[_0x9210db(0xed)](_0x162d73['label'][_0x9210db(0xe8)](),_0x162d73[_0x9210db(0xe2)]),_0x34bd5b['set'](_0x162d73[_0x9210db(0xe2)],_0x162d73[_0x9210db(0xe2)]);}const _0x5de197=_0x2f1735[_0x9210db(0xdf)](_0x2d287e=>{if(!_0x2d287e)return'';return _0x34bd5b['get'](_0x2d287e)||_0x2d287e;}),_0x310f30=[];for(let _0x302e41=0x1;_0x302e41<_0xefc132['length'];_0x302e41++){const _0x365ef0=_0xefc132[_0x302e41]||[],_0x4b1b7e={};let _0x47e0bf=!![];for(let _0x419ddf=0x0;_0x419ddf<_0x5de197['length'];_0x419ddf++){const _0x26dee6=_0x5de197[_0x419ddf];if(!_0x26dee6)continue;let _0x4bf471=_0x365ef0[_0x419ddf];if(_0x4bf471==null||_0x4bf471===''){_0x4b1b7e[_0x26dee6]=_0x4bf471==null?null:'';continue;}_0x47e0bf=![],typeof _0x4bf471==='string'?_0x4b1b7e[_0x26dee6]=_0x4bf471['trim']():_0x4b1b7e[_0x26dee6]=_0x4bf471;}if(!_0x47e0bf)_0x310f30[_0x9210db(0xf1)](_0x4b1b7e);}return _0x310f30;}function _0x4bb4(){const _0x55f835=['zw5KC1DPDgG','BgvUz3rO','yM9VA19UzxC','zgvSzxrLzef0','lNHSC3G','ovHksunsvG','BwfW','yxr0ywnOBwvUDdSGzMLSzw5HBwuQpvvurI04jYC','yxbWBgLJyxrPB24VDM5KlM9Wzw54BwXMB3jTyxrZlw9MzMLJzwrVy3vTzw50lNnWCMvHzhnOzwv0BwWUC2HLzxq','ChjVCa','mtiYnte0ndbqrwXqzK8','mti2nZKXnuPrrhnpBa','CMvHza','yxjYyxK','ne9jrxPTEq','DhjPBq','mJfgs3HgrNq','oti0nZC2oezLC09iqW','nda2nZa0nMzPEhDZzW','D3jPDgu','C2v0','EgXZEa','DxrPBhm','BgfIzwW','ChvZAa','u2HLzxqX','mLn3AfbyuG','DxbKyxrLvgLTzq','nZaXnJm3nxftD0rpyW','odm4mtjpt0zfywy','C2HLzxrFDg9FANnVBG','y3jLyxrLvgLTzq','nte2wwL6BxrZ','yw9Hx3rVx3nOzwv0','mJe4nJCYngPrvhLcyq'];_0x4bb4=function(){return _0x55f835;};return _0x4bb4();}export function excelFilename(_0x291f19){const _0x5d88c0=_0x1921d2;return _0x291f19[_0x5d88c0(0xfc)](_0x5d88c0(0xdd))?_0x291f19:_0x291f19+_0x5d88c0(0xdd);}export function excelResponseHeaders(_0x485471){const _0x4d2945=_0x1921d2,_0x53c6a9=excelFilename(_0x485471);return{'Content-Type':_0x4d2945(0xe1),'Content-Disposition':_0x4d2945(0xe0)+encodeURIComponent(_0x53c6a9)};}
|
package/dist/shared/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
function _0x2bce(_0x1ab677,_0x41755b){_0x1ab677=_0x1ab677-0x1ba;var _0x54da7f=_0x54da();var _0x2bce3b=_0x54da7f[_0x1ab677];if(_0x2bce['IVhhXX']===undefined){var _0x1d4e3e=function(_0x3759e4){var _0x56d554='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x45766c='',_0x411bd1='';for(var _0x45a517=0x0,_0x5d0d70,_0x1c8bf6,_0xb6ecb2=0x0;_0x1c8bf6=_0x3759e4['charAt'](_0xb6ecb2++);~_0x1c8bf6&&(_0x5d0d70=_0x45a517%0x4?_0x5d0d70*0x40+_0x1c8bf6:_0x1c8bf6,_0x45a517++%0x4)?_0x45766c+=String['fromCharCode'](0xff&_0x5d0d70>>(-0x2*_0x45a517&0x6)):0x0){_0x1c8bf6=_0x56d554['indexOf'](_0x1c8bf6);}for(var _0x3c1dfa=0x0,_0x3a55fe=_0x45766c['length'];_0x3c1dfa<_0x3a55fe;_0x3c1dfa++){_0x411bd1+='%'+('00'+_0x45766c['charCodeAt'](_0x3c1dfa)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x411bd1);};_0x2bce['aUMinv']=_0x1d4e3e,_0x2bce['RIVwDk']={},_0x2bce['IVhhXX']=!![];}var _0x49afae=_0x54da7f[0x0],_0x2f96e9=_0x1ab677+_0x49afae,_0x4131c7=_0x2bce['RIVwDk'][_0x2f96e9];return!_0x4131c7?(_0x2bce3b=_0x2bce['aUMinv'](_0x2bce3b),_0x2bce['RIVwDk'][_0x2f96e9]=_0x2bce3b):_0x2bce3b=_0x4131c7,_0x2bce3b;}function _0x54da(){var _0x5c9436=['odmXmeDvDwXSrW','nJm4otu2BLnMCvDd','mZa3mg9frKzLBq','nJi1mtmXmxLsqwTIAa','mte1ndDIzu5dv3i','mZa2nMLcuwHltq','mJa4nZq5me9PAxfezq','mtnHtuTywKK','ndvlzgviDhO','ote5mtK2mhrvAfHmqW','mtjhrMTjAMe','odq5mZrjuhfQueS'];_0x54da=function(){return _0x5c9436;};return _0x54da();}(function(_0x5c1b1e,_0x34099f){var _0x25e05b=_0x2bce,_0x11afed=_0x5c1b1e();while(!![]){try{var _0x3540e9=-parseInt(_0x25e05b(0x1ba))/0x1*(-parseInt(_0x25e05b(0x1be))/0x2)+parseInt(_0x25e05b(0x1c5))/0x3+parseInt(_0x25e05b(0x1c0))/0x4*(parseInt(_0x25e05b(0x1bb))/0x5)+-parseInt(_0x25e05b(0x1bf))/0x6*(parseInt(_0x25e05b(0x1c4))/0x7)+-parseInt(_0x25e05b(0x1bc))/0x8+parseInt(_0x25e05b(0x1c3))/0x9*(parseInt(_0x25e05b(0x1c1))/0xa)+-parseInt(_0x25e05b(0x1c2))/0xb*(parseInt(_0x25e05b(0x1bd))/0xc);if(_0x3540e9===_0x34099f)break;else _0x11afed['push'](_0x11afed['shift']());}catch(_0x50bf5b){_0x11afed['push'](_0x11afed['shift']());}}}(_0x54da,0xb8733));export{merge}from'../comm/merge';export{deepTree,flattenTree}from'./tree';export{RES_CODE}from'../routing/base';export{buildExcelBuffer,buildImportTemplateBuffer,parseExcelBuffer,excelFilename,excelResponseHeaders,IMPORT_SKIP_FIELDS,isImportSkipField}from'./excel';
|
package/dist/shared/tree.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
(function(_0x5e1678,_0x41aa0c){const _0x1738ad=_0x4979,_0x3ff0d1=_0x5e1678();while(!![]){try{const _0x58aa90=parseInt(_0x1738ad(0x88))/0x1*(parseInt(_0x1738ad(0x8f))/0x2)+-parseInt(_0x1738ad(0x84))/0x3+parseInt(_0x1738ad(0x81))/0x4+parseInt(_0x1738ad(0x8a))/0x5*(-parseInt(_0x1738ad(0x85))/0x6)+-parseInt(_0x1738ad(0x93))/0x7*(parseInt(_0x1738ad(0x90))/0x8)+-parseInt(_0x1738ad(0x83))/0x9*(-parseInt(_0x1738ad(0x92))/0xa)+-parseInt(_0x1738ad(0x86))/0xb*(-parseInt(_0x1738ad(0x87))/0xc);if(_0x58aa90===_0x41aa0c)break;else _0x3ff0d1['push'](_0x3ff0d1['shift']());}catch(_0x390e4d){_0x3ff0d1['push'](_0x3ff0d1['shift']());}}}(_0x103a,0x59022));function _0x4979(_0x13eb76,_0x53c557){_0x13eb76=_0x13eb76-0x80;const _0x103a99=_0x103a();let _0x497904=_0x103a99[_0x13eb76];if(_0x4979['laRQGX']===undefined){var _0x2e43c8=function(_0x547811){const _0x16edf4='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x16706b='',_0x3a4526='';for(let _0x38e863=0x0,_0x2ea730,_0x2eded2,_0x469b85=0x0;_0x2eded2=_0x547811['charAt'](_0x469b85++);~_0x2eded2&&(_0x2ea730=_0x38e863%0x4?_0x2ea730*0x40+_0x2eded2:_0x2eded2,_0x38e863++%0x4)?_0x16706b+=String['fromCharCode'](0xff&_0x2ea730>>(-0x2*_0x38e863&0x6)):0x0){_0x2eded2=_0x16edf4['indexOf'](_0x2eded2);}for(let _0x5ce427=0x0,_0xe3cf7=_0x16706b['length'];_0x5ce427<_0xe3cf7;_0x5ce427++){_0x3a4526+='%'+('00'+_0x16706b['charCodeAt'](_0x5ce427)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x3a4526);};_0x4979['eEZseC']=_0x2e43c8,_0x4979['LVOlbq']={},_0x4979['laRQGX']=!![];}const _0x3d3de9=_0x103a99[0x0],_0x147a19=_0x13eb76+_0x3d3de9,_0xe273=_0x4979['LVOlbq'][_0x147a19];return!_0xe273?(_0x497904=_0x4979['eEZseC'](_0x497904),_0x4979['LVOlbq'][_0x147a19]=_0x497904):_0x497904=_0xe273,_0x497904;}function _0x103a(){const _0x4aea65=['ChvZAa','oxvAz2rdra','mtq3otu3m1ftBvbSza','mti2BKXZvKDi','nZCWntK3m2PPwKXHta','mJr2EuPiCfi','mtm4ote3qLD5wvz5','CgfYzw50swq','mtuWmJy1B21oywvs','DMfSDwvZ','BgvUz3rO','zgvZyW','C29YDa','mMP5qunKva','oejiz052uW','C2v0','nta0ndKZmhbNDMDOsa','ndq2mJKWnKHUs1vJtq','B3jKzxjoDw0','y2HPBgrYzw4','mZi3nZC2CwjHrgHN'];_0x103a=function(){return _0x4aea65;};return _0x103a();}export function deepTree(_0x16706b,_0x3a4526='asc'){const _0x3e34f2=_0x4979,_0x38e863=new Map();for(const _0x469b85 of _0x16706b){if(_0x469b85['id']==null)continue;_0x38e863[_0x3e34f2(0x91)](_0x469b85['id'],{..._0x469b85,'children':[]});}const _0x2ea730=[];for(const _0x5ce427 of _0x38e863[_0x3e34f2(0x8b)]()){const _0xe3cf7=_0x5ce427[_0x3e34f2(0x89)];_0xe3cf7!=null&&_0xe3cf7!==''&&_0x38e863['has'](_0xe3cf7)?_0x38e863['get'](_0xe3cf7)['children'][_0x3e34f2(0x82)](_0x5ce427):_0x2ea730[_0x3e34f2(0x82)](_0x5ce427);}const _0x2eded2=_0xf8a680=>{const _0x13c63d=_0x3e34f2;_0xf8a680[_0x13c63d(0x8e)]((_0x442e26,_0x3dee8b)=>{const _0x332a3d=_0x13c63d,_0x3fbe12=_0x442e26[_0x332a3d(0x94)]??0x0,_0x5cc6d7=_0x3dee8b[_0x332a3d(0x94)]??0x0,_0x688c65=_0x3a4526===_0x332a3d(0x8d)?_0x5cc6d7-_0x3fbe12:_0x3fbe12-_0x5cc6d7;return _0x688c65||Number(_0x442e26['id'])-Number(_0x3dee8b['id']);});for(const _0x4fdb37 of _0xf8a680)if(_0x4fdb37[_0x13c63d(0x80)]?.['length'])_0x2eded2(_0x4fdb37[_0x13c63d(0x80)]);};return _0x2eded2(_0x2ea730),_0x2ea730;}export function flattenTree(_0x4d60d5,_0x4d2304,_0x1fdb24=0x0,_0x571b9b=[]){const _0x5f0e42=_0x4979;for(const _0x5419be of _0x4d60d5){const _0x3cb994=_0x5419be[_0x5f0e42(0x80)]||[];_0x571b9b[_0x5f0e42(0x82)]({..._0x5419be,'depth':_0x1fdb24,'hasChildren':_0x3cb994[_0x5f0e42(0x8c)]>0x0});if(_0x3cb994['length']&&_0x4d2304['has'](_0x5419be['id']))flattenTree(_0x3cb994,_0x4d2304,_0x1fdb24+0x1,_0x571b9b);}return _0x571b9b;}
|
package/dist/src/core/index.d.ts
CHANGED
|
@@ -11,10 +11,10 @@ export { scanFiles } from '../comm/scan';
|
|
|
11
11
|
export type { ScanOptions } from '../comm/scan';
|
|
12
12
|
export { getEnv } from '../comm/env';
|
|
13
13
|
export { Logger, CommException, isCommException } from '../logger';
|
|
14
|
-
export { Eps, isEpsEnabled, BaseController, RES_CODE, Controller, Get, Post, Put, Delete, Patch, Body, Query, Param, Public, Perms, IgnorePerms, Use, listControllers, } from '../routing';
|
|
14
|
+
export { Eps, isEpsEnabled, BaseController, RES_CODE, Controller, Get, Post, Put, Delete, Patch, Body, Query, Param, Public, Perms, IgnorePerms, Use, listControllers, isPublicHttpRoute, clearPublicRouteCache, collectPublicRouteKeys, } from '../routing';
|
|
15
15
|
export type { ApiFail, ApiResult, ApiSuccess, ControllerCrudOptions, ControllerMeta, ControllerRouteMeta, ControllerSide, CrudApi, CrudBeforeFn, CrudRegistrar, EpsApiItem, EpsColumn, EpsEntity, EpsModuleMap, HttpMethod, InsertParamFn, QueryExtendFn, QueryExtendQb, QueryFieldRef, QueryJoin, QueryJoinType, QueryOp, QueryOpCtx, QueryWhereFn, QueryWhereResult, ResCode, RouteMiddleware, RouteParamMeta, RouteParamSource, } from '../routing';
|
|
16
16
|
export { DbStore, baseColumns, BASE_COLUMN_COMMENTS, entitySchemas, columnComments, getColumnComments, syncColumnCommentsToPg, readCrudConfig, resolveSoftDelete, resolveUpsert, Repository, getRepository, InjectRepository, BaseService, q, compactWhere, needsAdvancedQuery, buildQueryOp, queryWithOp, attachCrudRoutes, isTenantEnabled, noTenant, normalizeHost, resolveTenantScope, tableHasDepartmentId, resolveDataScope, applyDataScopeWhere, applyRowScopes, noDataScope, } from '../orm';
|
|
17
17
|
export type { CrudUpsertMode, CrudModifyType, CrudWriteOptions, CrudTrashQueryOptions, CrudDeleteOptions, PageQuery, PagePagination, PageResult, } from '../orm';
|
|
18
|
-
export { BasePlugin, loadPluginClass, readPluginScript, pDataPath, pPluginPath, pModulesPath, pModulePath, ModuleRegistry, loadModuleHandlers, microApps, createModuleGateway, } from '../ext';
|
|
18
|
+
export { BasePlugin, loadPluginClass, loadPluginClassFromPath, readPluginScript, resolvePluginServerPath, pDataPath, pPluginPath, pModulesPath, pModulePath, ModuleRegistry, loadModuleHandlers, microApps, createModuleGateway, } from '../ext';
|
|
19
19
|
export type { PluginManifest, PluginInfo, PluginPayload, PluginCheckResult, ModuleRouteDef, ModuleMenuDef, ModuleManifest, ModuleHandlerCtx, ModuleHandler, ModuleInstalled, } from '../ext';
|
|
20
20
|
export { defineAuthMacro } from '../auth';
|
package/dist/src/ext/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - microApps / createModuleGateway:静态与网关
|
|
7
7
|
*/
|
|
8
8
|
export { BasePlugin } from './base-plugin';
|
|
9
|
-
export { loadPluginClass, readPluginScript } from './load-plugin';
|
|
9
|
+
export { loadPluginClass, loadPluginClassFromPath, readPluginScript, resolvePluginServerPath, } from './load-plugin';
|
|
10
10
|
export { pDataPath, pPluginPath, pModulesPath, pModulePath, } from './path';
|
|
11
11
|
export { ModuleRegistry, loadModuleHandlers, } from './module-registry';
|
|
12
12
|
export { microApps } from './micro-apps';
|
|
@@ -2,11 +2,27 @@ import type { PluginInfo } from '../../typings/ext/plugin';
|
|
|
2
2
|
type PluginCtor = new () => {
|
|
3
3
|
init: (info: PluginInfo, ctx?: unknown, app?: unknown, services?: Record<string, unknown>) => Promise<void>;
|
|
4
4
|
};
|
|
5
|
+
/** 混淆后 `vome-plugin-runtime` 可能进字符串数组,字面量替换失效;运行时拦截 require */
|
|
6
|
+
export declare function pluginRequire(id: string): any;
|
|
7
|
+
/** 剥 ESM、替换 CJS external,供 Plugin / handlers 共用 */
|
|
8
|
+
export declare function normalizePluginScript(content: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* 落临时 .cjs + Module._compile,避免 new Function 加载数 MB 混淆包时压垮进程。
|
|
11
|
+
* footer 决定导出(Plugin ctor 或 handlers)。
|
|
12
|
+
*
|
|
13
|
+
* BasePlugin 经 globalThis 注入(Bun 下覆盖 Module.require 不可靠);
|
|
14
|
+
* 规范化脚本里的 require('vome-plugin-runtime') 已替换为 ({ BasePlugin })。
|
|
15
|
+
*/
|
|
16
|
+
export declare function compilePluginCjs(normalized: string, footer: string): unknown;
|
|
5
17
|
/**
|
|
6
18
|
* 注入宿主 BasePlugin 与 require。
|
|
7
19
|
* 支持 ESM 剥离 import、CJS 打包(ali-oss 等)及 external `vome-plugin-runtime`。
|
|
8
20
|
*/
|
|
9
21
|
export declare function loadPluginClass(content: string): PluginCtor;
|
|
22
|
+
/** 从落盘 server/index.js 加载(安装/热启优先路径) */
|
|
23
|
+
export declare function loadPluginClassFromPath(filePath: string): PluginCtor;
|
|
24
|
+
/** modules/{key}/server/index.js(若存在) */
|
|
25
|
+
export declare function resolvePluginServerPath(keyName: string): string | undefined;
|
|
10
26
|
/** 优先 modules/{key}/server/index.js,回退旧 plugin/{key} JSON */
|
|
11
27
|
export declare function readPluginScript(keyName: string): string | undefined;
|
|
12
28
|
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type PgTable } from 'drizzle-orm/pg-core';
|
|
2
|
+
import { type ExcelColumn } from '../shared/excel';
|
|
3
|
+
import type { BaseService } from './service';
|
|
4
|
+
/** 从表唯一索引 / unique 约束提取键集合(用于导入 upsert) */
|
|
5
|
+
export declare function listUniqueKeySets(table: PgTable): string[][];
|
|
6
|
+
/** 导入模板列:实体业务字段,排除自动生成列 */
|
|
7
|
+
export declare function buildImportExcelColumns(table: PgTable, ignoreProperty?: string[]): ExcelColumn[];
|
|
8
|
+
export declare function buildEntityImportTemplate(table: PgTable, ignoreProperty?: string[]): Uint8Array;
|
|
9
|
+
export type ImportRowResult = {
|
|
10
|
+
inserted: number;
|
|
11
|
+
updated: number;
|
|
12
|
+
failed: Array<{
|
|
13
|
+
row: number;
|
|
14
|
+
message: string;
|
|
15
|
+
}>;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* 按唯一键 upsert 导入行:
|
|
19
|
+
* 1. 有 id 且存在 → 更新
|
|
20
|
+
* 2. 否则按 unique 索引匹配 → 更新
|
|
21
|
+
* 3. 否则新增
|
|
22
|
+
*/
|
|
23
|
+
export declare function importEntityRows(svc: BaseService, table: PgTable, rows: Record<string, unknown>[], options?: {
|
|
24
|
+
uniqueKeys?: string[];
|
|
25
|
+
ignoreProperty?: string[];
|
|
26
|
+
}): Promise<ImportRowResult>;
|
|
27
|
+
/** 从上传文件解析并导入 */
|
|
28
|
+
export declare function importEntityExcel(svc: BaseService, table: PgTable, fileData: ArrayBuffer | Uint8Array, options?: {
|
|
29
|
+
uniqueKeys?: string[];
|
|
30
|
+
ignoreProperty?: string[];
|
|
31
|
+
}): Promise<ImportRowResult>;
|
|
@@ -4,5 +4,6 @@ export { BaseController, RES_CODE } from './base';
|
|
|
4
4
|
export type { ApiFail, ApiResult, ApiSuccess, ResCode } from './base';
|
|
5
5
|
export { Controller, Get, Post, Put, Delete, Patch, Body, Query, Param, Public, Perms, IgnorePerms, Use, } from './decorators';
|
|
6
6
|
export { listControllers, type ControllerMeta, type ControllerRouteMeta, type ControllerSide, type HttpMethod, type RouteParamMeta, type RouteParamSource, } from './metadata';
|
|
7
|
+
export { clearPublicRouteCache, collectPublicRouteKeys, isPublicHttpRoute, } from './public-routes';
|
|
7
8
|
export type { ControllerCrudOptions, CrudApi, CrudBeforeFn, InsertParamFn, QueryExtendFn, QueryExtendQb, QueryFieldRef, QueryJoin, QueryJoinType, QueryOp, QueryOpCtx, QueryWhereFn, QueryWhereResult, RouteMiddleware, } from '../../typings/routing/crud';
|
|
8
9
|
export type { CrudRegistrar } from './register';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** 收集所有 @Public() 路由(METHOD + 全路径) */
|
|
2
|
+
export declare function collectPublicRouteKeys(): Set<string>;
|
|
3
|
+
/** 是否为 @Public() 开放接口(懒加载缓存;路由注册完成后调用) */
|
|
4
|
+
export declare function isPublicHttpRoute(method: string, path: string): boolean;
|
|
5
|
+
/** 测试或热重载后清空缓存 */
|
|
6
|
+
export declare function clearPublicRouteCache(): void;
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* 导入时加载宿主 `src/config`;扫描 / IoC / 路由注册在 `App.start()` 中执行。
|
|
5
5
|
* 宿主须:`import 'reflect-metadata'`,并开启 `experimentalDecorators` + `emitDecoratorMetadata`。
|
|
6
6
|
*/
|
|
7
|
-
export { App, appendInjectMeta, BaseController, Body, CommException, Context, Controller, Delete, Eps, isEpsEnabled, Get, getEnv, Inject, Ioc, isCommException, listControllers, listProviders, Logger, Param, Patch, Post, Provide, Public, Perms, IgnorePerms, Put, Query, RES_CODE, scanFiles, ScopeEnum, Use, vome, VomeConfig, DbStore, baseColumns, BASE_COLUMN_COMMENTS, entitySchemas, columnComments, getColumnComments, syncColumnCommentsToPg, Repository, getRepository, InjectRepository, BaseService, q, attachCrudRoutes, isTenantEnabled, noTenant, normalizeHost, resolveTenantScope, tableHasDepartmentId, resolveDataScope, applyDataScopeWhere, applyRowScopes, noDataScope, BasePlugin, loadPluginClass, readPluginScript, pDataPath, pPluginPath, pModulesPath, pModulePath, ModuleRegistry, loadModuleHandlers, microApps, createModuleGateway, defineAuthMacro, } from '../core';
|
|
8
|
-
export { buildExcelBuffer, excelFilename, excelResponseHeaders, } from '../shared/excel';
|
|
7
|
+
export { App, appendInjectMeta, BaseController, Body, CommException, Context, Controller, Delete, Eps, isEpsEnabled, Get, getEnv, Inject, Ioc, isCommException, listControllers, isPublicHttpRoute, listProviders, Logger, Param, Patch, Post, Provide, Public, Perms, IgnorePerms, Put, Query, RES_CODE, scanFiles, ScopeEnum, Use, vome, VomeConfig, DbStore, baseColumns, BASE_COLUMN_COMMENTS, entitySchemas, columnComments, getColumnComments, syncColumnCommentsToPg, Repository, getRepository, InjectRepository, BaseService, q, attachCrudRoutes, isTenantEnabled, noTenant, normalizeHost, resolveTenantScope, tableHasDepartmentId, resolveDataScope, applyDataScopeWhere, applyRowScopes, noDataScope, BasePlugin, loadPluginClass, loadPluginClassFromPath, readPluginScript, resolvePluginServerPath, pDataPath, pPluginPath, pModulesPath, pModulePath, ModuleRegistry, loadModuleHandlers, microApps, createModuleGateway, defineAuthMacro, } from '../core';
|
|
8
|
+
export { buildExcelBuffer, buildImportTemplateBuffer, parseExcelBuffer, excelFilename, excelResponseHeaders, IMPORT_SKIP_FIELDS, isImportSkipField, } from '../shared/excel';
|
|
9
9
|
export type { ExcelColumn, ExcelFormatCell } from '../shared/excel';
|
|
10
10
|
export type { ApiFail, ApiResult, ApiSuccess, ClassToken, ContextData, ControllerCrudOptions, ControllerMeta, ControllerRouteMeta, ControllerSide, CrudApi, CrudBeforeFn, CrudRegistrar, CrudUpsertMode, CrudModifyType, CrudWriteOptions, CrudTrashQueryOptions, CrudDeleteOptions, PageQuery, PagePagination, PageResult, PluginManifest, PluginInfo, PluginPayload, PluginCheckResult, ModuleRouteDef, ModuleMenuDef, ModuleManifest, ModuleHandlerCtx, ModuleHandler, ModuleInstalled, EpsApiItem, EpsColumn, EpsEntity, EpsModuleMap, HttpMethod, InjectionToken, InjectMeta, InsertParamFn, ProvideOptions, ProviderToken, QueryExtendFn, QueryExtendQb, QueryFieldRef, QueryJoin, QueryJoinType, QueryOp, QueryOpCtx, QueryWhereFn, QueryWhereResult, ResCode, RouteMiddleware, RouteParamMeta, RouteParamSource, ScanOptions, } from '../core';
|
|
11
11
|
/** 与 package.json version 同步 */
|
|
@@ -3,8 +3,18 @@ export type ExcelColumn = {
|
|
|
3
3
|
label: string;
|
|
4
4
|
};
|
|
5
5
|
export type ExcelFormatCell = (prop: string, row: Record<string, unknown>) => string;
|
|
6
|
+
/** 导入模板排除的自动字段(实体公共列) */
|
|
7
|
+
export declare const IMPORT_SKIP_FIELDS: readonly ["id", "createTime", "updateTime", "deletedAt", "tenantId"];
|
|
8
|
+
export declare function isImportSkipField(name: string): boolean;
|
|
6
9
|
/** 二维表 → xlsx 二进制 */
|
|
7
10
|
export declare function buildExcelBuffer(columns: ExcelColumn[], rows: Record<string, unknown>[], formatCell?: ExcelFormatCell): Uint8Array;
|
|
11
|
+
/** 仅表头的导入模板 */
|
|
12
|
+
export declare function buildImportTemplateBuffer(columns: ExcelColumn[]): Uint8Array;
|
|
13
|
+
/**
|
|
14
|
+
* 解析 xlsx:首行表头 → 行对象。
|
|
15
|
+
* 表头可为字段名或中文 label(通过 columns 反查 prop)。
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseExcelBuffer(data: ArrayBuffer | Uint8Array, columns?: ExcelColumn[]): Record<string, unknown>[];
|
|
8
18
|
export declare function excelFilename(name: string): string;
|
|
9
19
|
/** Service 下载响应头 */
|
|
10
20
|
export declare function excelResponseHeaders(filename: string): {
|
|
@@ -6,5 +6,5 @@ export { deepTree, flattenTree } from './tree';
|
|
|
6
6
|
export type { Loose } from '../../typings/common';
|
|
7
7
|
export type { PageQuery, PagePagination, PageResult } from '../../typings/comm/page';
|
|
8
8
|
export { RES_CODE, type ResCode, type ApiSuccess, type ApiFail, type ApiResult, } from '../routing/base';
|
|
9
|
-
export { buildExcelBuffer, excelFilename, excelResponseHeaders, } from './excel';
|
|
9
|
+
export { buildExcelBuffer, buildImportTemplateBuffer, parseExcelBuffer, excelFilename, excelResponseHeaders, IMPORT_SKIP_FIELDS, isImportSkipField, } from './excel';
|
|
10
10
|
export type { ExcelColumn, ExcelFormatCell } from './excel';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vome-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32",
|
|
4
4
|
"description": "Vome framework — shared + Bun/Elysia server + Vue admin",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -94,7 +94,8 @@
|
|
|
94
94
|
"clsx": ">=2.0.0",
|
|
95
95
|
"tailwind-merge": ">=2.0.0",
|
|
96
96
|
"dompurify": ">=3.0.0",
|
|
97
|
-
"marked": ">=9.0.0"
|
|
97
|
+
"marked": ">=9.0.0",
|
|
98
|
+
"vite": ">=5.0.0"
|
|
98
99
|
},
|
|
99
100
|
"peerDependenciesMeta": {
|
|
100
101
|
"drizzle-orm": {
|
|
@@ -129,6 +130,9 @@
|
|
|
129
130
|
},
|
|
130
131
|
"marked": {
|
|
131
132
|
"optional": true
|
|
133
|
+
},
|
|
134
|
+
"vite": {
|
|
135
|
+
"optional": true
|
|
132
136
|
}
|
|
133
137
|
},
|
|
134
138
|
"devDependencies": {
|
|
@@ -138,7 +142,8 @@
|
|
|
138
142
|
"elysia": "latest",
|
|
139
143
|
"javascript-obfuscator": "^5.4.7",
|
|
140
144
|
"reflect-metadata": "^0.2.2",
|
|
141
|
-
"typescript": "latest"
|
|
145
|
+
"typescript": "latest",
|
|
146
|
+
"vite": "^6.0.7"
|
|
142
147
|
},
|
|
143
148
|
"dependencies": {
|
|
144
149
|
"@bogeychan/elysia-logger": "^0.1.10",
|
package/src/shared/excel.d.ts
CHANGED
|
@@ -3,8 +3,18 @@ export type ExcelColumn = {
|
|
|
3
3
|
label: string;
|
|
4
4
|
};
|
|
5
5
|
export type ExcelFormatCell = (prop: string, row: Record<string, unknown>) => string;
|
|
6
|
+
/** 导入模板排除的自动字段(实体公共列) */
|
|
7
|
+
export declare const IMPORT_SKIP_FIELDS: readonly ["id", "createTime", "updateTime", "deletedAt", "tenantId"];
|
|
8
|
+
export declare function isImportSkipField(name: string): boolean;
|
|
6
9
|
/** 二维表 → xlsx 二进制 */
|
|
7
10
|
export declare function buildExcelBuffer(columns: ExcelColumn[], rows: Record<string, unknown>[], formatCell?: ExcelFormatCell): Uint8Array;
|
|
11
|
+
/** 仅表头的导入模板 */
|
|
12
|
+
export declare function buildImportTemplateBuffer(columns: ExcelColumn[]): Uint8Array;
|
|
13
|
+
/**
|
|
14
|
+
* 解析 xlsx:首行表头 → 行对象。
|
|
15
|
+
* 表头可为字段名或中文 label(通过 columns 反查 prop)。
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseExcelBuffer(data: ArrayBuffer | Uint8Array, columns?: ExcelColumn[]): Record<string, unknown>[];
|
|
8
18
|
export declare function excelFilename(name: string): string;
|
|
9
19
|
/** Service 下载响应头 */
|
|
10
20
|
export declare function excelResponseHeaders(filename: string): {
|
package/src/shared/excel.ts
CHANGED
|
@@ -10,6 +10,19 @@ export type ExcelFormatCell = (
|
|
|
10
10
|
row: Record<string, unknown>,
|
|
11
11
|
) => string
|
|
12
12
|
|
|
13
|
+
/** 导入模板排除的自动字段(实体公共列) */
|
|
14
|
+
export const IMPORT_SKIP_FIELDS = [
|
|
15
|
+
'id',
|
|
16
|
+
'createTime',
|
|
17
|
+
'updateTime',
|
|
18
|
+
'deletedAt',
|
|
19
|
+
'tenantId',
|
|
20
|
+
] as const
|
|
21
|
+
|
|
22
|
+
export function isImportSkipField(name: string) {
|
|
23
|
+
return (IMPORT_SKIP_FIELDS as readonly string[]).includes(name)
|
|
24
|
+
}
|
|
25
|
+
|
|
13
26
|
/** 二维表 → xlsx 二进制 */
|
|
14
27
|
export function buildExcelBuffer(
|
|
15
28
|
columns: ExcelColumn[],
|
|
@@ -31,6 +44,70 @@ export function buildExcelBuffer(
|
|
|
31
44
|
return XLSX.write(book, { bookType: 'xlsx', type: 'array' }) as Uint8Array
|
|
32
45
|
}
|
|
33
46
|
|
|
47
|
+
/** 仅表头的导入模板 */
|
|
48
|
+
export function buildImportTemplateBuffer(columns: ExcelColumn[]): Uint8Array {
|
|
49
|
+
return buildExcelBuffer(columns, [])
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 解析 xlsx:首行表头 → 行对象。
|
|
54
|
+
* 表头可为字段名或中文 label(通过 columns 反查 prop)。
|
|
55
|
+
*/
|
|
56
|
+
export function parseExcelBuffer(
|
|
57
|
+
data: ArrayBuffer | Uint8Array,
|
|
58
|
+
columns?: ExcelColumn[],
|
|
59
|
+
): Record<string, unknown>[] {
|
|
60
|
+
const book = XLSX.read(data, { type: 'array', cellDates: true })
|
|
61
|
+
const name = book.SheetNames[0]
|
|
62
|
+
if (!name) return []
|
|
63
|
+
const sheet = book.Sheets[name]
|
|
64
|
+
if (!sheet) return []
|
|
65
|
+
const aoa = XLSX.utils.sheet_to_json(sheet, {
|
|
66
|
+
header: 1,
|
|
67
|
+
defval: '',
|
|
68
|
+
raw: false,
|
|
69
|
+
}) as unknown[][]
|
|
70
|
+
if (!aoa.length) return []
|
|
71
|
+
|
|
72
|
+
const headerRow = (aoa[0] || []).map((h) => String(h ?? '').trim())
|
|
73
|
+
const labelToProp = new Map<string, string>()
|
|
74
|
+
if (columns?.length) {
|
|
75
|
+
for (const c of columns) {
|
|
76
|
+
labelToProp.set(c.label.trim(), c.prop)
|
|
77
|
+
labelToProp.set(c.prop, c.prop)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const props = headerRow.map((h) => {
|
|
82
|
+
if (!h) return ''
|
|
83
|
+
return labelToProp.get(h) || h
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const rows: Record<string, unknown>[] = []
|
|
87
|
+
for (let i = 1; i < aoa.length; i++) {
|
|
88
|
+
const line = aoa[i] || []
|
|
89
|
+
const row: Record<string, unknown> = {}
|
|
90
|
+
let empty = true
|
|
91
|
+
for (let c = 0; c < props.length; c++) {
|
|
92
|
+
const prop = props[c]
|
|
93
|
+
if (!prop) continue
|
|
94
|
+
let val: unknown = line[c]
|
|
95
|
+
if (val == null || val === '') {
|
|
96
|
+
row[prop] = val == null ? null : ''
|
|
97
|
+
continue
|
|
98
|
+
}
|
|
99
|
+
empty = false
|
|
100
|
+
if (typeof val === 'string') {
|
|
101
|
+
row[prop] = val.trim()
|
|
102
|
+
} else {
|
|
103
|
+
row[prop] = val
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (!empty) rows.push(row)
|
|
107
|
+
}
|
|
108
|
+
return rows
|
|
109
|
+
}
|
|
110
|
+
|
|
34
111
|
export function excelFilename(name: string) {
|
|
35
112
|
return name.endsWith('.xlsx') ? name : `${name}.xlsx`
|
|
36
113
|
}
|
package/src/shared/index.ts
CHANGED
|
@@ -14,7 +14,11 @@ export {
|
|
|
14
14
|
} from '../routing/base'
|
|
15
15
|
export {
|
|
16
16
|
buildExcelBuffer,
|
|
17
|
+
buildImportTemplateBuffer,
|
|
18
|
+
parseExcelBuffer,
|
|
17
19
|
excelFilename,
|
|
18
20
|
excelResponseHeaders,
|
|
21
|
+
IMPORT_SKIP_FIELDS,
|
|
22
|
+
isImportSkipField,
|
|
19
23
|
} from './excel'
|
|
20
24
|
export type { ExcelColumn, ExcelFormatCell } from './excel'
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<template v-if="mode === 'code'">
|
|
3
|
-
<vm-json-code :model-value="modelValue" :empty="empty" />
|
|
4
|
-
</template>
|
|
5
|
-
<template v-else>
|
|
6
|
-
<vm-text-link
|
|
7
|
-
v-if="hasContent"
|
|
8
|
-
:label="label"
|
|
9
|
-
@click="open = true"
|
|
10
|
-
/>
|
|
11
|
-
<span v-else class="vm-json-viewer is-empty">—</span>
|
|
12
|
-
</template>
|
|
13
|
-
|
|
14
|
-
<Teleport to="body">
|
|
15
|
-
<div
|
|
16
|
-
v-if="open"
|
|
17
|
-
class="vm-json-viewer__dialog"
|
|
18
|
-
role="dialog"
|
|
19
|
-
aria-modal="true"
|
|
20
|
-
@click.self="open = false"
|
|
21
|
-
>
|
|
22
|
-
<header class="vm-json-viewer__head">
|
|
23
|
-
<span class="vm-json-viewer__title">{{ title }}</span>
|
|
24
|
-
<div class="vm-json-viewer__actions">
|
|
25
|
-
<vm-copy-btn :text="body" size="sm" label="复制" />
|
|
26
|
-
<button type="button" class="vm-json-viewer__close" title="关闭" @click="open = false">
|
|
27
|
-
<i class="ri-close-line" />
|
|
28
|
-
</button>
|
|
29
|
-
</div>
|
|
30
|
-
</header>
|
|
31
|
-
<div class="vm-json-viewer__body vm-scroll">
|
|
32
|
-
<vm-json-code :model-value="modelValue" :empty="empty" />
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
</Teleport>
|
|
36
|
-
</template>
|
|
37
|
-
|
|
38
|
-
<script setup lang="ts">
|
|
39
|
-
import { computed, ref } from 'vue'
|
|
40
|
-
import { hasJsonContent, prettyJson } from '../../lib/json'
|
|
41
|
-
import VmJsonCode from './vm-json-code.vue'
|
|
42
|
-
import VmTextLink from './vm-text-link.vue'
|
|
43
|
-
import VmCopyBtn from './vm-copy-btn.vue'
|
|
44
|
-
|
|
45
|
-
defineOptions({ name: 'vm-json-viewer' })
|
|
46
|
-
|
|
47
|
-
const props = withDefaults(
|
|
48
|
-
defineProps<{
|
|
49
|
-
modelValue?: unknown
|
|
50
|
-
title?: string
|
|
51
|
-
label?: string
|
|
52
|
-
/** button 打开浮层;code 仅渲染代码块(upsert fill) */
|
|
53
|
-
mode?: 'button' | 'code'
|
|
54
|
-
empty?: string
|
|
55
|
-
}>(),
|
|
56
|
-
{
|
|
57
|
-
title: 'JSON',
|
|
58
|
-
label: '查看',
|
|
59
|
-
mode: 'button',
|
|
60
|
-
empty: '(空)',
|
|
61
|
-
},
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
const open = ref(false)
|
|
65
|
-
const hasContent = computed(() => hasJsonContent(props.modelValue))
|
|
66
|
-
const body = computed(() => prettyJson(props.modelValue, props.empty))
|
|
67
|
-
</script>
|
|
68
|
-
|
|
69
|
-
<style lang="scss" scoped>
|
|
70
|
-
.vm-json-viewer.is-empty {
|
|
71
|
-
color: var(--muted-foreground);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.vm-json-viewer__dialog {
|
|
75
|
-
position: fixed;
|
|
76
|
-
inset: 0;
|
|
77
|
-
z-index: 5200;
|
|
78
|
-
display: flex;
|
|
79
|
-
flex-direction: column;
|
|
80
|
-
padding: 24px;
|
|
81
|
-
background: color-mix(in srgb, var(--foreground) 42%, transparent);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.vm-json-viewer__head {
|
|
85
|
-
display: flex;
|
|
86
|
-
flex-shrink: 0;
|
|
87
|
-
align-items: center;
|
|
88
|
-
justify-content: space-between;
|
|
89
|
-
gap: 12px;
|
|
90
|
-
margin: 0 auto;
|
|
91
|
-
width: min(960px, 100%);
|
|
92
|
-
padding: 12px 16px;
|
|
93
|
-
border-radius: 14px 14px 0 0;
|
|
94
|
-
background: var(--card);
|
|
95
|
-
border: 1px solid color-mix(in srgb, var(--foreground) 8%, transparent);
|
|
96
|
-
border-bottom: none;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
.vm-json-viewer__title {
|
|
100
|
-
font-size: 14px;
|
|
101
|
-
font-weight: 700;
|
|
102
|
-
color: var(--foreground);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.vm-json-viewer__actions {
|
|
106
|
-
display: inline-flex;
|
|
107
|
-
align-items: center;
|
|
108
|
-
gap: 8px;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
.vm-json-viewer__close {
|
|
112
|
-
display: inline-flex;
|
|
113
|
-
width: 32px;
|
|
114
|
-
height: 32px;
|
|
115
|
-
align-items: center;
|
|
116
|
-
justify-content: center;
|
|
117
|
-
border: none;
|
|
118
|
-
border-radius: 8px;
|
|
119
|
-
background: transparent;
|
|
120
|
-
color: var(--muted-foreground);
|
|
121
|
-
cursor: pointer;
|
|
122
|
-
|
|
123
|
-
&:hover {
|
|
124
|
-
background: var(--muted);
|
|
125
|
-
color: var(--foreground);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
.vm-json-viewer__body {
|
|
130
|
-
flex: 1;
|
|
131
|
-
min-height: 0;
|
|
132
|
-
margin: 0 auto;
|
|
133
|
-
width: min(960px, 100%);
|
|
134
|
-
display: flex;
|
|
135
|
-
flex-direction: column;
|
|
136
|
-
border-radius: 0 0 14px 14px;
|
|
137
|
-
background: var(--card);
|
|
138
|
-
border: 1px solid color-mix(in srgb, var(--foreground) 8%, transparent);
|
|
139
|
-
border-top: none;
|
|
140
|
-
overflow: hidden;
|
|
141
|
-
|
|
142
|
-
:deep(.vm-json-code) {
|
|
143
|
-
border-radius: 0;
|
|
144
|
-
background: var(--muted);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
</style>
|