@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skyfox2000/webui",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.8",
|
|
4
4
|
"description": "后台前端通用组件定义",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [],
|
|
@@ -24,6 +24,12 @@
|
|
|
24
24
|
"types": "./lib/*.d.ts"
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
|
+
"files": [
|
|
28
|
+
"lib",
|
|
29
|
+
"src",
|
|
30
|
+
"package.json",
|
|
31
|
+
"README.md"
|
|
32
|
+
],
|
|
27
33
|
"scripts": {
|
|
28
34
|
"build": "pnpm i && vue-tsc -b && vite build",
|
|
29
35
|
"build:dts": "vue-tsc -b && vite-dts-declaration",
|
|
@@ -65,4 +71,4 @@
|
|
|
65
71
|
"vite-plugin-dts": "^4.5.4",
|
|
66
72
|
"vue-tsc": "^2.2.0"
|
|
67
73
|
}
|
|
68
|
-
}
|
|
74
|
+
}
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
import { Popover } from 'ant-design-vue';
|
|
3
3
|
import ToolIcon from './toolIcon.vue';
|
|
4
4
|
import { useAttrs } from 'vue';
|
|
5
|
+
import { TooltipPlacement } from 'ant-design-vue/es/tooltip';
|
|
5
6
|
|
|
6
7
|
defineProps<{
|
|
7
8
|
text?: string;
|
|
8
9
|
maxWidth?: string;
|
|
9
10
|
size?: number;
|
|
11
|
+
placement?: TooltipPlacement;
|
|
10
12
|
}>();
|
|
11
13
|
// 关闭自动继承属性到根元素
|
|
12
14
|
defineOptions({
|
|
@@ -16,7 +18,7 @@ const attrs = useAttrs(); // 手动获取 $attrs
|
|
|
16
18
|
</script>
|
|
17
19
|
|
|
18
20
|
<template>
|
|
19
|
-
<Popover placement="topRight">
|
|
21
|
+
<Popover :placement="placement ?? 'topRight'">
|
|
20
22
|
<template #content>
|
|
21
23
|
<slot>
|
|
22
24
|
<div class="text-[14px]" :class="[maxWidth]">
|
|
@@ -100,19 +100,21 @@ const doDialogClose = () => {
|
|
|
100
100
|
<slot></slot>
|
|
101
101
|
</div>
|
|
102
102
|
<template #footer>
|
|
103
|
-
<
|
|
104
|
-
<
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
103
|
+
<slot name="footer">
|
|
104
|
+
<Space>
|
|
105
|
+
<Button @click="doDialogClose" v-if="cancelText !== ''">
|
|
106
|
+
{{ cancelText ?? '取消' }}
|
|
107
|
+
</Button>
|
|
108
|
+
<Button @click="doDialogSaveAs" v-if="saveAsText !== '' && editorCtrl?.saveAsBtnVisible !== false"
|
|
109
|
+
type="primary" :loading="editorCtrl?.isFormSaving.value">
|
|
110
|
+
{{ saveAsText ?? '另存为' }}
|
|
111
|
+
</Button>
|
|
112
|
+
<Button @click="doDialogSave" v-if="saveText !== '' && editorCtrl?.saveBtnVisible !== false"
|
|
113
|
+
type="primary" :loading="editorCtrl?.isFormSaving.value">
|
|
114
|
+
{{ saveText ?? '保存' }}
|
|
115
|
+
</Button>
|
|
116
|
+
</Space>
|
|
117
|
+
</slot>
|
|
116
118
|
</template>
|
|
117
119
|
</Modal>
|
|
118
120
|
</template>
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { watch, ref, onMounted, PropType } from 'vue';
|
|
3
|
+
import { Button } from '../../common';
|
|
4
|
+
import { Modal, Space } from 'ant-design-vue';
|
|
5
|
+
import { doQuery, EditorControl, MinioFile, UploadFile, UploadStatus } from '@/index';
|
|
6
|
+
import { AnyData, ApiResponse, IUrlInfo, ResStatus } from '@skyfox2000/fapi';
|
|
7
|
+
import UploadList from '../../form/upload/uploadList.vue';
|
|
8
|
+
import { AsyncUploader } from '@/utils/file-upload';
|
|
9
|
+
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
/**
|
|
12
|
+
* 模板API域名配置
|
|
13
|
+
* 默认使用父级API
|
|
14
|
+
*/
|
|
15
|
+
api: {
|
|
16
|
+
type: String as PropType<string>,
|
|
17
|
+
required: false,
|
|
18
|
+
},
|
|
19
|
+
/**
|
|
20
|
+
* 模板类别
|
|
21
|
+
*/
|
|
22
|
+
templateType: {
|
|
23
|
+
type: String as PropType<string>,
|
|
24
|
+
required: true,
|
|
25
|
+
},
|
|
26
|
+
/**
|
|
27
|
+
* 文件后缀限制
|
|
28
|
+
*/
|
|
29
|
+
fileExt: {
|
|
30
|
+
type: Array as PropType<string[]>,
|
|
31
|
+
required: false,
|
|
32
|
+
},
|
|
33
|
+
/**
|
|
34
|
+
* 弹窗控制器
|
|
35
|
+
*/
|
|
36
|
+
uploadForm: {
|
|
37
|
+
type: Object as PropType<EditorControl<AnyData>>,
|
|
38
|
+
required: true,
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* 文件列表地址
|
|
42
|
+
*/
|
|
43
|
+
fileListUrl: {
|
|
44
|
+
type: Object as PropType<IUrlInfo>,
|
|
45
|
+
required: false,
|
|
46
|
+
},
|
|
47
|
+
/**
|
|
48
|
+
* 上传地址和参数
|
|
49
|
+
*/
|
|
50
|
+
uploadUrl: {
|
|
51
|
+
type: Object as PropType<IUrlInfo>,
|
|
52
|
+
required: false,
|
|
53
|
+
},
|
|
54
|
+
/**
|
|
55
|
+
* 下载地址和参数
|
|
56
|
+
*/
|
|
57
|
+
downloadUrl: {
|
|
58
|
+
type: Object as PropType<IUrlInfo>,
|
|
59
|
+
required: false,
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* 删除地址和参数
|
|
63
|
+
*/
|
|
64
|
+
deleteUrl: {
|
|
65
|
+
type: Object as PropType<IUrlInfo>,
|
|
66
|
+
required: false,
|
|
67
|
+
},
|
|
68
|
+
/**
|
|
69
|
+
* 是否显示删除按钮
|
|
70
|
+
*/
|
|
71
|
+
showDelete: {
|
|
72
|
+
type: Boolean as PropType<boolean>,
|
|
73
|
+
required: false,
|
|
74
|
+
default: true,
|
|
75
|
+
},
|
|
76
|
+
/**
|
|
77
|
+
* 最多上传文件数
|
|
78
|
+
*/
|
|
79
|
+
maxCount: {
|
|
80
|
+
type: Number as PropType<number>,
|
|
81
|
+
required: false,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
/**
|
|
85
|
+
* minio桶名称template
|
|
86
|
+
*
|
|
87
|
+
* 子目录templateType
|
|
88
|
+
*/
|
|
89
|
+
const fileListUrl = ref(props.fileListUrl || {
|
|
90
|
+
api: props.api,
|
|
91
|
+
authorize: true,
|
|
92
|
+
url: '/api/TemplateFileSrv/list',
|
|
93
|
+
});
|
|
94
|
+
const uploadUrl = ref(props.uploadUrl || {
|
|
95
|
+
api: props.api,
|
|
96
|
+
authorize: true,
|
|
97
|
+
url: '/api/TemplateFileSrv/upload',
|
|
98
|
+
});
|
|
99
|
+
const downloadUrl = ref(props.downloadUrl || {
|
|
100
|
+
api: props.api,
|
|
101
|
+
authorize: true,
|
|
102
|
+
url: '/api/TemplateFileSrv/download',
|
|
103
|
+
});
|
|
104
|
+
const deleteUrl = ref(props.deleteUrl || {
|
|
105
|
+
api: props.api,
|
|
106
|
+
authorize: true,
|
|
107
|
+
url: '/api/TemplateFileSrv/delete',
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const uploadFormCtrl = props.uploadForm;
|
|
111
|
+
const open = ref<boolean>(false);
|
|
112
|
+
|
|
113
|
+
const fileList = ref<UploadFile[]>([]);
|
|
114
|
+
const emit = defineEmits<{
|
|
115
|
+
/**
|
|
116
|
+
* 显示预处理
|
|
117
|
+
*/
|
|
118
|
+
'before:file-list': [EditorControl<AnyData>, UploadFile[]];
|
|
119
|
+
/**
|
|
120
|
+
* 上传前预处理
|
|
121
|
+
*/
|
|
122
|
+
'before:upload': [UploadFile[]];
|
|
123
|
+
/**
|
|
124
|
+
* 上传结束,处理上传后的文件
|
|
125
|
+
*/
|
|
126
|
+
'after:upload': [boolean, UploadFile[]];
|
|
127
|
+
/**
|
|
128
|
+
* 上传进度
|
|
129
|
+
*/
|
|
130
|
+
'on:progress': [UploadFile];
|
|
131
|
+
}>();
|
|
132
|
+
|
|
133
|
+
watch(
|
|
134
|
+
() => uploadFormCtrl.visible.value,
|
|
135
|
+
() => {
|
|
136
|
+
open.value = uploadFormCtrl.visible.value;
|
|
137
|
+
},
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* 加载现有模板文件列表
|
|
143
|
+
*/
|
|
144
|
+
const loadFileList = async () => {
|
|
145
|
+
const res: ApiResponse<MinioFile[]> | null = await doQuery<MinioFile[]>(props.uploadForm, {
|
|
146
|
+
urlKey: 'list',
|
|
147
|
+
url: fileListUrl.value,
|
|
148
|
+
params: {
|
|
149
|
+
Query: {
|
|
150
|
+
PrefixPath: props.templateType,
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
if (res?.status === ResStatus.SUCCESS && res.data) {
|
|
155
|
+
const files = res.data as MinioFile[];
|
|
156
|
+
const list = files.map((file) => {
|
|
157
|
+
const uploadFile: UploadFile = {
|
|
158
|
+
uid: file.Key,
|
|
159
|
+
size: file.Size,
|
|
160
|
+
name: file.FileName!,
|
|
161
|
+
status: UploadStatus.Online,
|
|
162
|
+
lastModified: file.UpdateTime ? new Date(file.UpdateTime).getTime() : 0,
|
|
163
|
+
lastModifiedDate: file.UpdateTime ? new Date(file.UpdateTime) : new Date(),
|
|
164
|
+
params: {},
|
|
165
|
+
minioFile: file,
|
|
166
|
+
}
|
|
167
|
+
return uploadFile;
|
|
168
|
+
})
|
|
169
|
+
emit('before:file-list', uploadFormCtrl, list);
|
|
170
|
+
fileList.value.push(...list);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const dialogSave = async () => {
|
|
175
|
+
emit('before:upload', fileList.value);
|
|
176
|
+
const uploader = new AsyncUploader(uploadUrl.value, 3);
|
|
177
|
+
await uploader.doUpload(
|
|
178
|
+
fileList.value,
|
|
179
|
+
uploadFormCtrl.isFormLoading,
|
|
180
|
+
true,
|
|
181
|
+
async (result, files) => {
|
|
182
|
+
emit('after:upload', result, files);
|
|
183
|
+
if (result) {
|
|
184
|
+
uploadFormCtrl.visible.value = false;
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
(file) => {
|
|
188
|
+
emit('on:progress', file);
|
|
189
|
+
},
|
|
190
|
+
);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
onMounted(() => {
|
|
194
|
+
if (!fileListUrl.value.api) {
|
|
195
|
+
fileListUrl.value.api = uploadFormCtrl.page.api;
|
|
196
|
+
}
|
|
197
|
+
if (!uploadUrl.value.api) {
|
|
198
|
+
uploadUrl.value.api = uploadFormCtrl.page.api;
|
|
199
|
+
}
|
|
200
|
+
if (!downloadUrl.value.api) {
|
|
201
|
+
downloadUrl.value.api = uploadFormCtrl.page.api;
|
|
202
|
+
}
|
|
203
|
+
if (!deleteUrl.value.api) {
|
|
204
|
+
deleteUrl.value.api = uploadFormCtrl.page.api;
|
|
205
|
+
}
|
|
206
|
+
loadFileList();
|
|
207
|
+
|
|
208
|
+
open.value = uploadFormCtrl.visible.value;
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const dialogClose = () => {
|
|
212
|
+
uploadFormCtrl.visible.value = false;
|
|
213
|
+
};
|
|
214
|
+
</script>
|
|
215
|
+
<template>
|
|
216
|
+
<Modal title="模板文件管理" v-model:open="open"
|
|
217
|
+
:wrapClassName="'modal mx-auto ' + ($attrs.width ? 'w-[' + $attrs.width + ']' : 'w-[500px]')"
|
|
218
|
+
@close="dialogClose">
|
|
219
|
+
<UploadList v-model:file-list="fileList" :parent-path="props.templateType" :upload-url="uploadUrl"
|
|
220
|
+
:download-url="downloadUrl" :delete-url="deleteUrl" :max-count="maxCount" :file-ext="fileExt"
|
|
221
|
+
:show-delete="showDelete" />
|
|
222
|
+
<template #footer>
|
|
223
|
+
<Space>
|
|
224
|
+
<Button @click="dialogClose">关闭</Button>
|
|
225
|
+
<Button @click="dialogSave" type="primary" :loading="uploadFormCtrl.isFormSaving.value"
|
|
226
|
+
:disabled="fileList.length === 0">
|
|
227
|
+
上传保存
|
|
228
|
+
</Button>
|
|
229
|
+
</Space>
|
|
230
|
+
</template>
|
|
231
|
+
</Modal>
|
|
232
|
+
</template>
|
|
233
|
+
<style>
|
|
234
|
+
.modal {
|
|
235
|
+
.ant-modal-content {
|
|
236
|
+
padding: 16px;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.full-modal {
|
|
241
|
+
.ant-modal {
|
|
242
|
+
width: 100% !important;
|
|
243
|
+
max-width: 100%;
|
|
244
|
+
top: 0;
|
|
245
|
+
padding-bottom: 0;
|
|
246
|
+
margin: 0;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.ant-modal-content {
|
|
250
|
+
display: flex;
|
|
251
|
+
flex-direction: column;
|
|
252
|
+
height: calc(100vh);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.ant-modal-body {
|
|
256
|
+
flex: 1;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
</style>
|
|
@@ -136,24 +136,16 @@ const dialogClose = () => {
|
|
|
136
136
|
};
|
|
137
137
|
</script>
|
|
138
138
|
<template>
|
|
139
|
-
<Modal
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
:
|
|
143
|
-
|
|
144
|
-
>
|
|
145
|
-
<UploadList
|
|
146
|
-
v-model:file-list="fileList"
|
|
147
|
-
:upload-url="uploadUrl!"
|
|
148
|
-
:download-url="downloadUrl"
|
|
149
|
-
:max-count="maxCount"
|
|
150
|
-
:file-ext="fileExt"
|
|
151
|
-
/>
|
|
139
|
+
<Modal title="文件上传" v-model:open="open"
|
|
140
|
+
:wrapClassName="'modal mx-auto ' + ($attrs.width ? 'w-[' + $attrs.width + ']' : 'w-[500px]')"
|
|
141
|
+
@close="dialogClose">
|
|
142
|
+
<UploadList v-model:file-list="fileList" :upload-url="uploadUrl!" :download-url="downloadUrl"
|
|
143
|
+
:max-count="maxCount" :file-ext="fileExt" />
|
|
152
144
|
<template #footer>
|
|
153
145
|
<Space>
|
|
154
146
|
<Button @click="dialogClose">取消</Button>
|
|
155
147
|
<Button @click="dialogSave" type="primary" :loading="uploadFormCtrl.isFormSaving.value">
|
|
156
|
-
|
|
148
|
+
上传保存
|
|
157
149
|
</Button>
|
|
158
150
|
</Space>
|
|
159
151
|
</template>
|
|
@@ -74,65 +74,43 @@ const doDrawerClose = () => {
|
|
|
74
74
|
};
|
|
75
75
|
</script>
|
|
76
76
|
<template>
|
|
77
|
-
<Drawer
|
|
78
|
-
|
|
79
|
-
:
|
|
80
|
-
:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
:body-style="{
|
|
87
|
-
padding: '10px 16px',
|
|
88
|
-
}"
|
|
89
|
-
:footer-style="{
|
|
90
|
-
textAlign: 'right',
|
|
91
|
-
}"
|
|
92
|
-
:style="{
|
|
77
|
+
<Drawer v-model:open="open" :get-container="false" :closable="false" :header-style="{
|
|
78
|
+
height: '40px',
|
|
79
|
+
padding: '10px 6px 10px 16px',
|
|
80
|
+
backgroundColor: token.colorBgLayout,
|
|
81
|
+
}" :body-style="{
|
|
82
|
+
padding: '10px 16px',
|
|
83
|
+
}" :footer-style="{
|
|
84
|
+
textAlign: 'right',
|
|
85
|
+
}" :style="{
|
|
93
86
|
position: 'absolute',
|
|
94
87
|
boxShadow: 'rgba(0, 0, 0, 0.3) -2px 0px 8px',
|
|
95
|
-
}"
|
|
96
|
-
width="420px"
|
|
97
|
-
@close="doDrawerClose"
|
|
98
|
-
>
|
|
88
|
+
}" width="420px" @close="doDrawerClose">
|
|
99
89
|
<template #extra>
|
|
100
|
-
<
|
|
101
|
-
<
|
|
102
|
-
class="top-[-2px] left-[2px] w-6 h-6"
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
clickable
|
|
107
|
-
color="#666"
|
|
108
|
-
:position="[0, 0]"
|
|
109
|
-
@click="doDrawerClose"
|
|
110
|
-
/>
|
|
111
|
-
</div>
|
|
90
|
+
<slot name="extra">
|
|
91
|
+
<div class="hover:bg-gray-200 w-[24px] h-[24px] rounded-md">
|
|
92
|
+
<ToolIcon class="top-[-2px] left-[2px] w-6 h-6" icon="icon-new" :angle="45" fontsize="24px" clickable
|
|
93
|
+
color="#666" :position="[0, 0]" @click="doDrawerClose" />
|
|
94
|
+
</div>
|
|
95
|
+
</slot>
|
|
112
96
|
</template>
|
|
113
97
|
<template #default>
|
|
114
98
|
<slot></slot>
|
|
115
99
|
</template>
|
|
116
100
|
<template #footer>
|
|
117
|
-
<
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
@click="doDrawerSaveAs"
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
type="primary"
|
|
131
|
-
:loading="editorCtrl.isFormSaving.value"
|
|
132
|
-
>
|
|
133
|
-
{{ saveText ?? '保存' }}
|
|
134
|
-
</Button>
|
|
135
|
-
</Space>
|
|
101
|
+
<slot name="footer">
|
|
102
|
+
<Space>
|
|
103
|
+
<Button @click="doDrawerClose" v-if="cancelText !== ''">{{ cancelText ?? '取消' }}</Button>
|
|
104
|
+
<Button @click="doDrawerSaveAs" v-if="saveAsText !== '' && editorCtrl.saveAsBtnVisible !== false"
|
|
105
|
+
type="primary" :loading="editorCtrl.isFormSaving.value">
|
|
106
|
+
{{ saveAsText ?? '另存为' }}
|
|
107
|
+
</Button>
|
|
108
|
+
<Button @click="doDrawerSave" v-if="saveText !== '' && editorCtrl.saveBtnVisible !== false"
|
|
109
|
+
type="primary" :loading="editorCtrl.isFormSaving.value">
|
|
110
|
+
{{ saveText ?? '保存' }}
|
|
111
|
+
</Button>
|
|
112
|
+
</Space>
|
|
113
|
+
</slot>
|
|
136
114
|
</template>
|
|
137
115
|
</Drawer>
|
|
138
116
|
</template>
|
|
@@ -3,9 +3,8 @@ import { onMounted, ref, useAttrs, watch } from 'vue';
|
|
|
3
3
|
import { Tree } from 'ant-design-vue';
|
|
4
4
|
import { ToolIcon } from '../../common';
|
|
5
5
|
import { TreeControl, TreeNode, queryTree } from '@/index';
|
|
6
|
-
import { TreeDataNode } from 'ant-design-vue/es/vc-tree-select/interface';
|
|
7
|
-
import { EventDataNode } from 'ant-design-vue/es/vc-tree/interface';
|
|
8
6
|
import { fieldMapping } from '@skyfox2000/fapi';
|
|
7
|
+
import { findNodeByKey, TreeNodeInfo } from '@/utils/tree';
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* 组件属性定义
|
|
@@ -31,6 +30,7 @@ const attrs = useAttrs();
|
|
|
31
30
|
const treeCtrl = props.treeCtrl;
|
|
32
31
|
// 树节点数据
|
|
33
32
|
const treeData = ref<TreeNode[]>([]);
|
|
33
|
+
// const treeRef = ref();
|
|
34
34
|
|
|
35
35
|
// 监听树数据变化
|
|
36
36
|
watch(
|
|
@@ -38,7 +38,26 @@ watch(
|
|
|
38
38
|
(newVal) => {
|
|
39
39
|
if (newVal) {
|
|
40
40
|
treeData.value = treeCtrl.fieldMap ? fieldMapping(treeCtrl.fieldMap, newVal) : newVal;
|
|
41
|
-
|
|
41
|
+
// 获取当前选中的节点
|
|
42
|
+
const selectedNode = findNodeByKey(treeData.value, selectedKeys.value[0]);
|
|
43
|
+
|
|
44
|
+
if (selectedNode) {
|
|
45
|
+
// 构建info对象
|
|
46
|
+
const info: TreeNodeInfo = {
|
|
47
|
+
event: 'select',
|
|
48
|
+
node: {
|
|
49
|
+
// 根据你的TreeNode结构构建node对象
|
|
50
|
+
key: selectedNode.key,
|
|
51
|
+
title: selectedNode.title,
|
|
52
|
+
checked: true,
|
|
53
|
+
dataRef: selectedNode
|
|
54
|
+
},
|
|
55
|
+
selected: true,
|
|
56
|
+
selectedNodes: [selectedNode]
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
handleSelect(selectedKeys.value, info);
|
|
60
|
+
}
|
|
42
61
|
}
|
|
43
62
|
},
|
|
44
63
|
);
|
|
@@ -47,12 +66,7 @@ const emit = defineEmits<{
|
|
|
47
66
|
(
|
|
48
67
|
e: 'select',
|
|
49
68
|
selectedKeys: (string | number)[],
|
|
50
|
-
info?:
|
|
51
|
-
event: 'select';
|
|
52
|
-
node: EventDataNode;
|
|
53
|
-
selected: boolean;
|
|
54
|
-
selectedNodes: TreeDataNode[];
|
|
55
|
-
},
|
|
69
|
+
info?: TreeNodeInfo,
|
|
56
70
|
): void;
|
|
57
71
|
(e: 'update:selectedKeys', value: (string | number)[]): void;
|
|
58
72
|
}>();
|
|
@@ -81,12 +95,7 @@ watch(
|
|
|
81
95
|
// 值变化事件
|
|
82
96
|
const handleSelect = (
|
|
83
97
|
keys: (string | number)[],
|
|
84
|
-
info?:
|
|
85
|
-
event: 'select';
|
|
86
|
-
node: EventDataNode;
|
|
87
|
-
selected: boolean;
|
|
88
|
-
selectedNodes: TreeDataNode[];
|
|
89
|
-
},
|
|
98
|
+
info?: TreeNodeInfo,
|
|
90
99
|
) => {
|
|
91
100
|
if (keys.length === 0) {
|
|
92
101
|
keys.push(...selectedKeys.value);
|
|
@@ -118,16 +127,8 @@ onMounted(() => {
|
|
|
118
127
|
</script>
|
|
119
128
|
|
|
120
129
|
<template>
|
|
121
|
-
<Tree
|
|
122
|
-
|
|
123
|
-
:show-line="true"
|
|
124
|
-
:tree-data="treeData"
|
|
125
|
-
v-model:expanded-keys="expandedKeys"
|
|
126
|
-
:selected-keys="selectedKeys"
|
|
127
|
-
:loading="treeCtrl.isTreeLoading"
|
|
128
|
-
@select="handleSelect"
|
|
129
|
-
v-bind="attrs"
|
|
130
|
-
>
|
|
130
|
+
<Tree class="w-full" :show-line="true" :tree-data="treeData" v-model:expanded-keys="expandedKeys"
|
|
131
|
+
:selected-keys="selectedKeys" :loading="treeCtrl.isTreeLoading" @select="handleSelect" v-bind="attrs">
|
|
131
132
|
<template #title="{ key, label, icon }">
|
|
132
133
|
<slot name="title" :label="label" :key="key" :icon="icon">
|
|
133
134
|
<div class="flex items-center gap-1">
|
|
@@ -89,7 +89,7 @@ const onChanged = (value: any) => {
|
|
|
89
89
|
innerValue.value = value;
|
|
90
90
|
emit('update:labels', labels);
|
|
91
91
|
emit('update:label', labels.join(";"));
|
|
92
|
-
emit('change', value);
|
|
92
|
+
emit('change', value, selectedOptions);
|
|
93
93
|
|
|
94
94
|
if (errInfo?.value.errClass && editorCtrl) {
|
|
95
95
|
/// 重新开始验证
|