@skyfox2000/webui 1.4.6 → 1.4.8
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/lib/TemplateFile.d.ts +1 -0
- package/lib/assets/modules/{baseLayout-CUZpKmC0.js → baseLayout-DIny49tw.js} +6 -6
- package/lib/assets/modules/{file-upload-BrTPBL29.js → file-upload-DHUBZlX4.js} +1 -1
- package/lib/assets/modules/{index-NDOzpgzV.js → index-BIAdOoSj.js} +10 -10
- package/lib/assets/modules/{index-BqoqvtEv.js → index-CEffEFtI.js} +1 -1
- package/lib/assets/modules/index-DyRjXb_O.js +114 -0
- package/lib/assets/modules/{menuTabs-BaZAmaXz.js → menuTabs-CCrFWIOl.js} +7 -7
- package/lib/assets/modules/{toolIcon-DHKszGtC.js → toolIcon-BGZR_aUI.js} +1 -1
- package/lib/assets/modules/{uploadList-DSN9t4r8.js → uploadList-CMXuGRWT.js} +163 -153
- package/lib/assets/modules/{uploadList-C5R2XD5x.js → uploadList-l4q5o65m.js} +150 -138
- package/lib/components/common/icon/helper.vue.d.ts +2 -0
- package/lib/components/content/dialog/index.vue.d.ts +1 -0
- package/lib/components/content/drawer/index.vue.d.ts +2 -0
- package/lib/components/content/tree/index.vue.d.ts +3 -14
- package/lib/components/form/upload/uploadList.vue.d.ts +3 -0
- package/lib/es/AceEditor/index.js +3 -3
- package/lib/es/BasicLayout/index.js +6 -6
- package/lib/es/Error403/index.js +1 -1
- package/lib/es/Error404/index.js +1 -1
- package/lib/es/ExcelForm/index.js +5 -5
- package/lib/es/MenuLayout/index.js +6 -6
- package/lib/es/TemplateFile/index.js +208 -0
- package/lib/es/UploadForm/index.js +6 -6
- package/lib/utils/tree.d.ts +9 -0
- package/lib/webui.css +1 -1
- package/lib/webui.es.js +514 -489
- package/package.json +8 -2
- package/src/components/common/icon/helper.vue +3 -1
- package/src/components/content/dialog/index.vue +15 -13
- package/src/components/content/dialog/templateFile.vue +259 -0
- package/src/components/content/dialog/uploadForm.vue +6 -14
- package/src/components/content/drawer/index.vue +29 -51
- package/src/components/content/tree/index.vue +26 -25
- package/src/components/form/select/index.vue +1 -1
- package/src/components/form/upload/uploadList.vue +66 -89
- package/src/utils/tree.ts +20 -0
- package/.eslintrc.js +0 -23
- package/.prettierrc +0 -11
- package/.vscode/settings.json +0 -25
- package/env.d.ts +0 -11
- package/index.html +0 -19
- package/lib/assets/modules/index-DP1u2P1k.js +0 -112
- package/plugins/vite-plugin-auto-generate-vue.ts +0 -105
- package/postcss.config.ts +0 -6
- package/tailwind.config.ts +0 -11
- package/tsconfig.json +0 -46
- package/vite.config.ts +0 -120
- package//344/273/243/347/240/201/350/247/204/350/214/203/345/217/212/351/243/216/346/240/274/346/214/207/345/215/227.md +0 -116
|
@@ -6,7 +6,7 @@ import type { UploadProps } from 'ant-design-vue';
|
|
|
6
6
|
import { Upload, Progress, Tag, Popconfirm } from 'ant-design-vue';
|
|
7
7
|
import { UploadFile, UploadStatus, donwloadFromMinio, path, Switch, previewFromMinio } from '@/index';
|
|
8
8
|
import { useInputFactory } from '@/utils/form-validate';
|
|
9
|
-
import { IUrlInfo } from '@skyfox2000/fapi';
|
|
9
|
+
import { ApiResponse, httpPost, IUrlInfo, ResStatus } from '@skyfox2000/fapi';
|
|
10
10
|
|
|
11
11
|
export interface UploadListProps {
|
|
12
12
|
/**
|
|
@@ -26,6 +26,10 @@ export interface UploadListProps {
|
|
|
26
26
|
* 预览Url
|
|
27
27
|
*/
|
|
28
28
|
previewUrl?: IUrlInfo;
|
|
29
|
+
/**
|
|
30
|
+
* 删除Url
|
|
31
|
+
*/
|
|
32
|
+
deleteUrl?: IUrlInfo;
|
|
29
33
|
/**
|
|
30
34
|
* 文件列表
|
|
31
35
|
*/
|
|
@@ -70,6 +74,10 @@ export interface UploadListProps {
|
|
|
70
74
|
* 是否显示上线或下线
|
|
71
75
|
*/
|
|
72
76
|
showOnlineSwitch?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* 是否显示删除
|
|
79
|
+
*/
|
|
80
|
+
showDelete?: boolean;
|
|
73
81
|
}
|
|
74
82
|
|
|
75
83
|
const props = withDefaults(defineProps<UploadListProps>(), {
|
|
@@ -83,6 +91,7 @@ const props = withDefaults(defineProps<UploadListProps>(), {
|
|
|
83
91
|
fileExtTip: true,
|
|
84
92
|
showActionText: true,
|
|
85
93
|
showOnlineSwitch: false,
|
|
94
|
+
showDelete: true,
|
|
86
95
|
});
|
|
87
96
|
|
|
88
97
|
const inputFactory = useInputFactory();
|
|
@@ -210,7 +219,21 @@ const previewFile = (index: number) => {
|
|
|
210
219
|
};
|
|
211
220
|
|
|
212
221
|
const removeFile = (index: number) => {
|
|
213
|
-
fileList.value
|
|
222
|
+
const file = fileList.value[index];
|
|
223
|
+
if (props.deleteUrl) {
|
|
224
|
+
httpPost<ApiResponse>(props.deleteUrl, {
|
|
225
|
+
Query: {
|
|
226
|
+
FileKey: file.minioFile!.Key,
|
|
227
|
+
},
|
|
228
|
+
}).then((res) => {
|
|
229
|
+
if (res && res.status === ResStatus.SUCCESS) {
|
|
230
|
+
message.success('删除文件成功!');
|
|
231
|
+
fileList.value.splice(index, 1);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
} else {
|
|
235
|
+
fileList.value.splice(index, 1);
|
|
236
|
+
}
|
|
214
237
|
confirmOpen.value = false;
|
|
215
238
|
};
|
|
216
239
|
|
|
@@ -270,11 +293,8 @@ const getStatus = (status?: UploadStatus) => {
|
|
|
270
293
|
<div class="w-full border border-solid border-gray-100 mt-1 rounded-md py-5" :class="[errInfo?.errClass]">
|
|
271
294
|
<div class="flex items-center justify-between w-full">
|
|
272
295
|
<div class="w-35 mx-3">
|
|
273
|
-
<Upload
|
|
274
|
-
|
|
275
|
-
v-bind="uploadProps"
|
|
276
|
-
v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:upload' }"
|
|
277
|
-
>
|
|
296
|
+
<Upload ref="fileUploader" v-bind="uploadProps"
|
|
297
|
+
v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:upload' }">
|
|
278
298
|
<Button :class="[errInfo?.errClass + '-text']">选择文件</Button>
|
|
279
299
|
</Upload>
|
|
280
300
|
</div>
|
|
@@ -288,99 +308,57 @@ const getStatus = (status?: UploadStatus) => {
|
|
|
288
308
|
<div v-for="(file, index) in fileList" :key="index" class="mb-2 pb-1">
|
|
289
309
|
<div class="flex items-center justify-between">
|
|
290
310
|
<div class="flex items-center">
|
|
291
|
-
<span
|
|
292
|
-
class="
|
|
293
|
-
|
|
294
|
-
>{{ file.fileName ?? file.name }}</span
|
|
295
|
-
>
|
|
311
|
+
<span class="text-gray-700 mr-2"
|
|
312
|
+
:class="[file.status == UploadStatus.Offline ? 'line-through' : '']">{{ file.fileName ?? file.name
|
|
313
|
+
}}</span>
|
|
296
314
|
<span>
|
|
297
315
|
<Tag :color="getStatusColor(file.status)">{{ getStatus(file.status) }}</Tag>
|
|
298
316
|
</span>
|
|
299
317
|
</div>
|
|
300
318
|
<div class="flex items-center">
|
|
301
|
-
<div
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
showOnlineSwitch && (file.status == UploadStatus.Online || file.status == UploadStatus.Offline)
|
|
305
|
-
"
|
|
306
|
-
>
|
|
319
|
+
<div class="mr-2" v-if="
|
|
320
|
+
showOnlineSwitch && (file.status == UploadStatus.Online || file.status == UploadStatus.Offline)
|
|
321
|
+
">
|
|
307
322
|
<Tooltip title="上线或下线">
|
|
308
|
-
<Switch
|
|
309
|
-
|
|
310
|
-
:
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
]"
|
|
314
|
-
@change="onlineOrOffline(file)"
|
|
315
|
-
v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:online' }"
|
|
316
|
-
/>
|
|
323
|
+
<Switch v-model:checked="file.status" :data="[
|
|
324
|
+
{ label: '上线', value: UploadStatus.Online },
|
|
325
|
+
{ label: '下线', value: UploadStatus.Offline },
|
|
326
|
+
]" @change="onlineOrOffline(file)"
|
|
327
|
+
v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:online' }" />
|
|
317
328
|
</Tooltip>
|
|
318
329
|
</div>
|
|
319
|
-
<div
|
|
320
|
-
|
|
321
|
-
v-if="downloadUrl && (file.status == UploadStatus.Online || file.status == UploadStatus.Offline)"
|
|
322
|
-
>
|
|
330
|
+
<div class="flex items-center text-blue-500 hover:text-blue-700 mr-1 cursor-pointer"
|
|
331
|
+
v-if="downloadUrl && (file.status == UploadStatus.Online || file.status == UploadStatus.Offline)">
|
|
323
332
|
<Tooltip title="下载">
|
|
324
|
-
<ToolIcon
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
@click="downloadFile(index)"
|
|
329
|
-
/>
|
|
330
|
-
<span
|
|
331
|
-
v-if="showActionText"
|
|
332
|
-
class="mr-2 text-sm text-nowrap"
|
|
333
|
+
<ToolIcon icon="icon-download"
|
|
334
|
+
v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:download' }" clickable
|
|
335
|
+
@click="downloadFile(index)" />
|
|
336
|
+
<span v-if="showActionText" class="mr-2 text-sm text-nowrap"
|
|
333
337
|
v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:download' }"
|
|
334
|
-
@click="downloadFile(index)"
|
|
335
|
-
>下载</span
|
|
336
|
-
>
|
|
338
|
+
@click="downloadFile(index)">下载</span>
|
|
337
339
|
</Tooltip>
|
|
338
340
|
</div>
|
|
339
|
-
<div
|
|
340
|
-
|
|
341
|
-
v-if="previewUrl && (file.status == UploadStatus.Online || file.status == UploadStatus.Offline)"
|
|
342
|
-
>
|
|
341
|
+
<div class="flex items-center text-blue-500 hover:text-blue-700 mr-1 cursor-pointer"
|
|
342
|
+
v-if="previewUrl && (file.status == UploadStatus.Online || file.status == UploadStatus.Offline)">
|
|
343
343
|
<Tooltip title="预览">
|
|
344
|
-
<ToolIcon
|
|
345
|
-
|
|
344
|
+
<ToolIcon icon="icon-eye" v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:preview' }"
|
|
345
|
+
clickable @click="previewFile(index)" />
|
|
346
|
+
<span v-if="showActionText" class="mr-2 text-sm text-nowrap"
|
|
346
347
|
v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:preview' }"
|
|
347
|
-
|
|
348
|
-
@click="previewFile(index)"
|
|
349
|
-
/>
|
|
350
|
-
<span
|
|
351
|
-
v-if="showActionText"
|
|
352
|
-
class="mr-2 text-sm text-nowrap"
|
|
353
|
-
v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:preview' }"
|
|
354
|
-
@click="previewFile(index)"
|
|
355
|
-
>预览</span
|
|
356
|
-
>
|
|
348
|
+
@click="previewFile(index)">预览</span>
|
|
357
349
|
</Tooltip>
|
|
358
350
|
</div>
|
|
359
|
-
<div
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
title="确定删除该文件吗?"
|
|
365
|
-
:okButtonProps="{ size: 'small' }"
|
|
366
|
-
:cancelButtonProps="{ size: 'small' }"
|
|
367
|
-
@confirm="removeFile(index)"
|
|
368
|
-
@cancel="confirmOpen = false"
|
|
369
|
-
>
|
|
351
|
+
<div v-if="showDelete !== false"
|
|
352
|
+
class="flex items-center text-red-500 hover:text-red-700 cursor-pointer">
|
|
353
|
+
<Popconfirm v-model:open="confirmOpen" cancelText="否" okText="是" title="确定删除该文件吗?"
|
|
354
|
+
:okButtonProps="{ size: 'small' }" :cancelButtonProps="{ size: 'small' }"
|
|
355
|
+
@confirm="removeFile(index)" @cancel="confirmOpen = false">
|
|
370
356
|
<Tooltip title="删除">
|
|
371
357
|
<div @click="confirmDelFile(index, file.status)">
|
|
372
|
-
<ToolIcon
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:delete' }"
|
|
376
|
-
clickable
|
|
377
|
-
/>
|
|
378
|
-
<span
|
|
379
|
-
v-if="showActionText"
|
|
380
|
-
class="text-sm text-nowrap"
|
|
381
|
-
v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:delete' }"
|
|
382
|
-
>删除</span
|
|
383
|
-
>
|
|
358
|
+
<ToolIcon icon="icon-new" :angle="45"
|
|
359
|
+
v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:delete' }" clickable />
|
|
360
|
+
<span v-if="showActionText" class="text-sm text-nowrap"
|
|
361
|
+
v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:delete' }">删除</span>
|
|
384
362
|
</div>
|
|
385
363
|
</Tooltip>
|
|
386
364
|
</Popconfirm>
|
|
@@ -389,13 +367,11 @@ const getStatus = (status?: UploadStatus) => {
|
|
|
389
367
|
</div>
|
|
390
368
|
|
|
391
369
|
<!-- 上传进度条 -->
|
|
392
|
-
<div
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
"
|
|
398
|
-
>
|
|
370
|
+
<div v-if="
|
|
371
|
+
file.status !== UploadStatus.Online &&
|
|
372
|
+
file.status !== UploadStatus.Offline &&
|
|
373
|
+
file.status !== UploadStatus.Success
|
|
374
|
+
">
|
|
399
375
|
<Progress :percent="file.percent" :stroke-width="2" :show-info="false" style="height: 2px"></Progress>
|
|
400
376
|
</div>
|
|
401
377
|
</div>
|
|
@@ -408,6 +384,7 @@ const getStatus = (status?: UploadStatus) => {
|
|
|
408
384
|
border-color: #ff4d4f80;
|
|
409
385
|
box-shadow: 0 0 3px 0 #ff4d4f;
|
|
410
386
|
}
|
|
387
|
+
|
|
411
388
|
.error-text {
|
|
412
389
|
color: #ff4d4f !important;
|
|
413
390
|
}
|
package/src/utils/tree.ts
CHANGED
|
@@ -2,7 +2,15 @@ import { TreeControl, TreeNode } from '@/typings/tree.d';
|
|
|
2
2
|
import { ApiResponse, ReqParams, ResStatus } from '@skyfox2000/fapi';
|
|
3
3
|
import { doQuery } from './data';
|
|
4
4
|
import { combineParams } from '@skyfox2000/microbase';
|
|
5
|
+
import { TreeDataNode } from 'ant-design-vue/es/vc-tree-select/interface';
|
|
6
|
+
import { EventDataNode } from 'ant-design-vue/es/vc-tree/interface';
|
|
5
7
|
|
|
8
|
+
export interface TreeNodeInfo {
|
|
9
|
+
event: 'select';
|
|
10
|
+
node: EventDataNode;
|
|
11
|
+
selected: boolean;
|
|
12
|
+
selectedNodes: TreeDataNode[];
|
|
13
|
+
}
|
|
6
14
|
/**
|
|
7
15
|
* 树加载数据
|
|
8
16
|
* @param treeCtrl 树控制对象
|
|
@@ -28,3 +36,15 @@ export const queryTree = (treeCtrl: TreeControl, params?: ReqParams): Promise<Tr
|
|
|
28
36
|
return [];
|
|
29
37
|
});
|
|
30
38
|
};
|
|
39
|
+
|
|
40
|
+
// 辅助函数:根据key查找节点
|
|
41
|
+
export const findNodeByKey = (nodes: TreeNode[], key: string | number): TreeNode | null => {
|
|
42
|
+
for (const node of nodes) {
|
|
43
|
+
if (node.key === key) return node;
|
|
44
|
+
if (node.children) {
|
|
45
|
+
const found = findNodeByKey(node.children, key);
|
|
46
|
+
if (found) return found;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
};
|
package/.eslintrc.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
root: true,
|
|
3
|
-
env: {
|
|
4
|
-
browser: true,
|
|
5
|
-
es2021: true,
|
|
6
|
-
node: true,
|
|
7
|
-
},
|
|
8
|
-
extends: [
|
|
9
|
-
'eslint:recommended',
|
|
10
|
-
'plugin:vue/vue3-essential',
|
|
11
|
-
'plugin:@typescript-eslint/recommended',
|
|
12
|
-
'plugin:prettier/recommended',
|
|
13
|
-
],
|
|
14
|
-
parserOptions: {
|
|
15
|
-
ecmaVersion: 'latest',
|
|
16
|
-
sourceType: 'module',
|
|
17
|
-
parser: '@typescript-eslint/parser',
|
|
18
|
-
},
|
|
19
|
-
plugins: ['vue', '@typescript-eslint', 'prettier'],
|
|
20
|
-
rules: {
|
|
21
|
-
'prettier/prettier': 'error',
|
|
22
|
-
},
|
|
23
|
-
};
|
package/.prettierrc
DELETED
package/.vscode/settings.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// 控制相关文件嵌套展示
|
|
3
|
-
"explorer.fileNesting.enabled": true,
|
|
4
|
-
"explorer.fileNesting.expand": false,
|
|
5
|
-
"explorer.fileNesting.patterns": {
|
|
6
|
-
"*.ts": "$(capture).test.ts, $(capture).test.tsx",
|
|
7
|
-
"*.tsx": "$(capture).test.ts, $(capture).test.tsx",
|
|
8
|
-
"package.json": "index.html,pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitignore,.gitattributes,.gitpod.yml,CNAME,README*,.npmrc,.browserslistrc,.env.*,env.d.ts,.prettierrc,.eslintrc.js,*.md,.cursorignore,.npmignore",
|
|
9
|
-
"vite.config.ts": "tsconfig.*.json,postcss.config.ts,tailwind.config.ts,tsconfig.json"
|
|
10
|
-
},
|
|
11
|
-
"editor.formatOnSave": true,
|
|
12
|
-
|
|
13
|
-
"editor.codeActionsOnSave": {
|
|
14
|
-
"source.fixAll.eslint": "always"
|
|
15
|
-
},
|
|
16
|
-
"[typescript]": {
|
|
17
|
-
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
18
|
-
},
|
|
19
|
-
"[json]": {
|
|
20
|
-
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
21
|
-
},
|
|
22
|
-
"[vue]": {
|
|
23
|
-
"editor.defaultFormatter": "Vue.volar"
|
|
24
|
-
}
|
|
25
|
-
}
|
package/env.d.ts
DELETED
package/index.html
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" href="null">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>后台管理系统</title>
|
|
8
|
-
<style>
|
|
9
|
-
html {
|
|
10
|
-
overflow-y: hidden;
|
|
11
|
-
overflow-x: hidden;
|
|
12
|
-
}
|
|
13
|
-
</style>
|
|
14
|
-
</head>
|
|
15
|
-
<body>
|
|
16
|
-
<div id="app"></div>
|
|
17
|
-
<script type="module" src="/src/main.ts"></script>
|
|
18
|
-
</body>
|
|
19
|
-
</html>
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { defineComponent as F, provide as _, ref as w, watch as p, onMounted as B, createBlock as n, openBlock as r, unref as a, withCtx as i, createElementVNode as N, renderSlot as b, createVNode as V, createCommentVNode as d, createTextVNode as u, toDisplayString as v } from "vue";
|
|
2
|
-
import { _ as m } from "./index-BqoqvtEv.js";
|
|
3
|
-
import { Modal as D, Space as E } from "ant-design-vue";
|
|
4
|
-
import "@skyfox2000/fapi";
|
|
5
|
-
import { P as M, d as P, o as $, b as K } from "./uploadList-DSN9t4r8.js";
|
|
6
|
-
import "@skyfox2000/microbase";
|
|
7
|
-
import "vue-m-message";
|
|
8
|
-
import "async-validator";
|
|
9
|
-
import "dayjs";
|
|
10
|
-
import "vue-draggable-next";
|
|
11
|
-
const U = { class: "overflow-y-auto w-full h-full" }, R = /* @__PURE__ */ F({
|
|
12
|
-
__name: "index",
|
|
13
|
-
props: {
|
|
14
|
-
saveText: {},
|
|
15
|
-
saveAsText: {},
|
|
16
|
-
cancelText: {},
|
|
17
|
-
editorCtrl: {},
|
|
18
|
-
dialogSave: { type: Function },
|
|
19
|
-
dialogSaveAs: { type: Function },
|
|
20
|
-
width: {},
|
|
21
|
-
full: { type: Boolean },
|
|
22
|
-
open: { type: Boolean }
|
|
23
|
-
},
|
|
24
|
-
emits: ["update:open"],
|
|
25
|
-
setup(C, { emit: T }) {
|
|
26
|
-
const l = C, e = l.editorCtrl;
|
|
27
|
-
_(M.EditorControl, e);
|
|
28
|
-
const t = w(l.open ?? !1), A = T, h = w(l.width ?? 430);
|
|
29
|
-
p(
|
|
30
|
-
() => e == null ? void 0 : e.visible.value,
|
|
31
|
-
(o) => {
|
|
32
|
-
t.value = o ?? !1;
|
|
33
|
-
}
|
|
34
|
-
), p(
|
|
35
|
-
() => l.open,
|
|
36
|
-
(o) => {
|
|
37
|
-
t.value = o;
|
|
38
|
-
}
|
|
39
|
-
), p(
|
|
40
|
-
() => t.value,
|
|
41
|
-
(o) => {
|
|
42
|
-
A("update:open", o), o || f();
|
|
43
|
-
}
|
|
44
|
-
), B(() => {
|
|
45
|
-
t.value = (e == null ? void 0 : e.visible.value) ?? !1;
|
|
46
|
-
});
|
|
47
|
-
const k = () => {
|
|
48
|
-
l.dialogSave ? l.dialogSave() : e && $(e);
|
|
49
|
-
}, x = () => {
|
|
50
|
-
l.dialogSaveAs ? l.dialogSaveAs() : e && K(e);
|
|
51
|
-
}, f = () => {
|
|
52
|
-
e ? P(e) : t.value = !1;
|
|
53
|
-
};
|
|
54
|
-
return (o, c) => (r(), n(a(D), {
|
|
55
|
-
open: t.value,
|
|
56
|
-
"onUpdate:open": c[0] || (c[0] = (s) => t.value = s),
|
|
57
|
-
wrapClassName: "modal mx-auto min-w-[430px] " + (o.full ? "full-modal w-full" : ""),
|
|
58
|
-
width: h.value
|
|
59
|
-
}, {
|
|
60
|
-
footer: i(() => [
|
|
61
|
-
V(a(E), null, {
|
|
62
|
-
default: i(() => {
|
|
63
|
-
var s, g, S, y;
|
|
64
|
-
return [
|
|
65
|
-
o.cancelText !== "" ? (r(), n(a(m), {
|
|
66
|
-
key: 0,
|
|
67
|
-
onClick: f
|
|
68
|
-
}, {
|
|
69
|
-
default: i(() => [
|
|
70
|
-
u(v(o.cancelText ?? "取消"), 1)
|
|
71
|
-
]),
|
|
72
|
-
_: 1
|
|
73
|
-
})) : d("", !0),
|
|
74
|
-
o.saveAsText !== "" && ((s = a(e)) == null ? void 0 : s.saveAsBtnVisible) !== !1 ? (r(), n(a(m), {
|
|
75
|
-
key: 1,
|
|
76
|
-
onClick: x,
|
|
77
|
-
type: "primary",
|
|
78
|
-
loading: (g = a(e)) == null ? void 0 : g.isFormSaving.value
|
|
79
|
-
}, {
|
|
80
|
-
default: i(() => [
|
|
81
|
-
u(v(o.saveAsText ?? "另存为"), 1)
|
|
82
|
-
]),
|
|
83
|
-
_: 1
|
|
84
|
-
}, 8, ["loading"])) : d("", !0),
|
|
85
|
-
o.saveText !== "" && ((S = a(e)) == null ? void 0 : S.saveBtnVisible) !== !1 ? (r(), n(a(m), {
|
|
86
|
-
key: 2,
|
|
87
|
-
onClick: k,
|
|
88
|
-
type: "primary",
|
|
89
|
-
loading: (y = a(e)) == null ? void 0 : y.isFormSaving.value
|
|
90
|
-
}, {
|
|
91
|
-
default: i(() => [
|
|
92
|
-
u(v(o.saveText ?? "保存"), 1)
|
|
93
|
-
]),
|
|
94
|
-
_: 1
|
|
95
|
-
}, 8, ["loading"])) : d("", !0)
|
|
96
|
-
];
|
|
97
|
-
}),
|
|
98
|
-
_: 1
|
|
99
|
-
})
|
|
100
|
-
]),
|
|
101
|
-
default: i(() => [
|
|
102
|
-
N("div", U, [
|
|
103
|
-
b(o.$slots, "default")
|
|
104
|
-
])
|
|
105
|
-
]),
|
|
106
|
-
_: 3
|
|
107
|
-
}, 8, ["open", "wrapClassName", "width"]));
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
export {
|
|
111
|
-
R as _
|
|
112
|
-
};
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { Plugin } from 'vite';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 首字母大写的工具函数
|
|
7
|
-
*/
|
|
8
|
-
function capitalize(str: string): string {
|
|
9
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* 规范化路径,确保使用正斜杠
|
|
14
|
-
*/
|
|
15
|
-
function normalizePath(filePath: string): string {
|
|
16
|
-
return filePath.split(path.sep).join('/');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* 递归扫描目录中的 .vue 文件并生成导出语句
|
|
21
|
-
*/
|
|
22
|
-
function scanDir(dir: string, baseDir: string, skipDirFile: string[]): string[] {
|
|
23
|
-
const result: string[] = [];
|
|
24
|
-
const files = fs.readdirSync(dir);
|
|
25
|
-
files.forEach((file) => {
|
|
26
|
-
const filePath = path.join(dir, file);
|
|
27
|
-
if (skipDirFile.includes(filePath)) return;
|
|
28
|
-
|
|
29
|
-
const stat = fs.statSync(filePath);
|
|
30
|
-
|
|
31
|
-
if (stat.isDirectory()) {
|
|
32
|
-
// 递归扫描子目录
|
|
33
|
-
const subResult = scanDir(filePath, baseDir, skipDirFile);
|
|
34
|
-
result.push(...subResult);
|
|
35
|
-
} else if (file.endsWith('.vue')) {
|
|
36
|
-
// 获取相对路径并规范化
|
|
37
|
-
const relativePath = normalizePath(path.relative(baseDir, filePath));
|
|
38
|
-
const componentName = generateComponentName(filePath);
|
|
39
|
-
|
|
40
|
-
// 使用规范化的路径生成导入语句
|
|
41
|
-
result.push(`import ${componentName} from './${relativePath}';\nexport { ${componentName} };`);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
return result;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* 根据文件路径生成组件名
|
|
50
|
-
*/
|
|
51
|
-
function generateComponentName(filePath: string): string {
|
|
52
|
-
const dirName = path.basename(path.dirname(filePath));
|
|
53
|
-
const fileName = path.basename(filePath, '.vue');
|
|
54
|
-
|
|
55
|
-
if (fileName === 'index') {
|
|
56
|
-
return capitalize(dirName);
|
|
57
|
-
} else {
|
|
58
|
-
return capitalize(fileName);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* 插件主逻辑
|
|
64
|
-
*/
|
|
65
|
-
export default function AutoGenerateVue(options: { dir: string; skip: string[]; output: string }): Plugin {
|
|
66
|
-
return {
|
|
67
|
-
name: 'vite-plugin-auto-generate-vue',
|
|
68
|
-
config() {
|
|
69
|
-
const { dir, skip, output } = options;
|
|
70
|
-
|
|
71
|
-
// 检查output是否文件结尾
|
|
72
|
-
const isFile = path.extname(output) !== '';
|
|
73
|
-
if (!isFile) {
|
|
74
|
-
throw new Error(`The specified output file "${output}" must be a file.`);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// 规范化路径
|
|
78
|
-
const componentsDir = normalizePath(path.resolve(process.cwd(), dir));
|
|
79
|
-
const skipDirFile = skip.map((url) => {
|
|
80
|
-
return normalizePath(path.resolve(process.cwd(), url));
|
|
81
|
-
});
|
|
82
|
-
const outputFile = normalizePath(path.resolve(process.cwd(), output));
|
|
83
|
-
|
|
84
|
-
// 获取输出文件的目录路径
|
|
85
|
-
const baseDir = normalizePath(path.dirname(path.resolve(process.cwd(), output)));
|
|
86
|
-
|
|
87
|
-
if (!fs.existsSync(componentsDir)) {
|
|
88
|
-
throw new Error(`The specified directory "${componentsDir}" does not exist.`);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const result = scanDir(componentsDir, baseDir, skipDirFile);
|
|
92
|
-
const exportStatements = result.join('\n');
|
|
93
|
-
|
|
94
|
-
// 确保输出目录存在
|
|
95
|
-
const outputDir = path.dirname(outputFile);
|
|
96
|
-
if (!fs.existsSync(outputDir)) {
|
|
97
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// 写入到目标文件
|
|
101
|
-
fs.writeFileSync(outputFile, exportStatements, 'utf-8');
|
|
102
|
-
console.log(`[autoGenerateVue] Global components written to ${output}`);
|
|
103
|
-
},
|
|
104
|
-
};
|
|
105
|
-
}
|
package/postcss.config.ts
DELETED
package/tailwind.config.ts
DELETED
package/tsconfig.json
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
4
|
-
"declaration": true,
|
|
5
|
-
"declarationMap": false,
|
|
6
|
-
"emitDeclarationOnly": false,
|
|
7
|
-
"esModuleInterop": true,
|
|
8
|
-
"target": "ESNext",
|
|
9
|
-
"useDefineForClassFields": true,
|
|
10
|
-
"module": "ESNext",
|
|
11
|
-
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
12
|
-
"skipLibCheck": true,
|
|
13
|
-
"removeComments": true,
|
|
14
|
-
"forceConsistentCasingInFileNames": true,
|
|
15
|
-
|
|
16
|
-
"composite": true,
|
|
17
|
-
"allowSyntheticDefaultImports": true,
|
|
18
|
-
|
|
19
|
-
/* Bundler mode */
|
|
20
|
-
"moduleResolution": "Bundler",
|
|
21
|
-
"resolveJsonModule": true,
|
|
22
|
-
"isolatedModules": true,
|
|
23
|
-
"noEmit": false,
|
|
24
|
-
"jsx": "preserve",
|
|
25
|
-
|
|
26
|
-
/* Linting */
|
|
27
|
-
"strict": true,
|
|
28
|
-
"noUnusedLocals": true,
|
|
29
|
-
"noUnusedParameters": true,
|
|
30
|
-
"noFallthroughCasesInSwitch": true,
|
|
31
|
-
"baseUrl": ".",
|
|
32
|
-
"paths": {
|
|
33
|
-
"@/*": ["src/*"]
|
|
34
|
-
},
|
|
35
|
-
"typeRoots": ["./node_modules/@types", "./types"],
|
|
36
|
-
"rootDir": "./",
|
|
37
|
-
"outDir": "lib",
|
|
38
|
-
|
|
39
|
-
"allowJs": true,
|
|
40
|
-
"types": ["vite/client", "node"],
|
|
41
|
-
"sourceMap": true,
|
|
42
|
-
"verbatimModuleSyntax": false
|
|
43
|
-
},
|
|
44
|
-
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue", "env.d.ts", "vite.config.ts"],
|
|
45
|
-
"exclude": ["node_modules", "lib", "dist"]
|
|
46
|
-
}
|