@skyfox2000/webui 1.4.5 → 1.4.7

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.
Files changed (42) hide show
  1. package/lib/TemplateFile.d.ts +1 -0
  2. package/lib/assets/modules/{baseLayout-BT7tGUB1.js → baseLayout-DOrecPPK.js} +6 -6
  3. package/lib/assets/modules/{file-upload-DicHRX1r.js → file-upload-lbkluj3p.js} +3 -3
  4. package/lib/assets/modules/{index-BURe9YrF.js → index-B1MSCuqH.js} +2 -2
  5. package/lib/assets/modules/{index-iozooZXX.js → index-BLNKcgk-.js} +1 -1
  6. package/lib/assets/modules/{index-BjXLzCF2.js → index-DQ-VDAr-.js} +10 -10
  7. package/lib/assets/modules/{menuTabs-D_UlXkmm.js → menuTabs-DOtYQ9Zu.js} +7 -7
  8. package/lib/assets/modules/{toolIcon-BiWBb2pJ.js → toolIcon-CqJWc5B7.js} +1 -1
  9. package/lib/assets/modules/{uploadList-61wZlPUk.js → uploadList-3SuA7du0.js} +150 -138
  10. package/lib/assets/modules/{uploadList-C_hqJ4X1.js → uploadList-DafDrGgh.js} +251 -239
  11. package/lib/components/content/tree/index.vue.d.ts +3 -14
  12. package/lib/components/form/upload/uploadList.vue.d.ts +3 -0
  13. package/lib/es/AceEditor/index.js +3 -3
  14. package/lib/es/BasicLayout/index.js +6 -6
  15. package/lib/es/Error403/index.js +1 -1
  16. package/lib/es/Error404/index.js +1 -1
  17. package/lib/es/ExcelForm/index.js +5 -5
  18. package/lib/es/MenuLayout/index.js +6 -6
  19. package/lib/es/TemplateFile/index.js +208 -0
  20. package/lib/es/UploadForm/index.js +6 -6
  21. package/lib/utils/tree.d.ts +9 -0
  22. package/lib/webui.css +1 -1
  23. package/lib/webui.es.js +396 -378
  24. package/package.json +7 -1
  25. package/src/components/content/dialog/templateFile.vue +259 -0
  26. package/src/components/content/dialog/uploadForm.vue +6 -14
  27. package/src/components/content/tree/index.vue +26 -25
  28. package/src/components/form/upload/uploadList.vue +66 -89
  29. package/src/stores/userInfo.ts +6 -0
  30. package/src/utils/file-upload.ts +2 -2
  31. package/src/utils/tree.ts +20 -0
  32. package/.eslintrc.js +0 -23
  33. package/.prettierrc +0 -11
  34. package/.vscode/settings.json +0 -25
  35. package/env.d.ts +0 -11
  36. package/index.html +0 -19
  37. package/plugins/vite-plugin-auto-generate-vue.ts +0 -105
  38. package/postcss.config.ts +0 -6
  39. package/tailwind.config.ts +0 -11
  40. package/tsconfig.json +0 -46
  41. package/vite.config.ts +0 -120
  42. 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.5",
3
+ "version": "1.4.7",
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",
@@ -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
- title="文件上传"
141
- v-model:open="open"
142
- :wrapClassName="'modal mx-auto ' + ($attrs.width ? 'w-[' + $attrs.width + ']' : 'w-[430px]')"
143
- @close="dialogClose"
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>
@@ -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
- handleSelect(props.selectedKeys ?? []);
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
- class="w-full"
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">
@@ -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.splice(index, 1);
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
- ref="fileUploader"
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="text-gray-700 mr-2"
293
- :class="[file.status == UploadStatus.Offline ? 'line-through' : '']"
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
- class="mr-2"
303
- v-if="
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
- v-model:checked="file.status"
310
- :data="[
311
- { label: '上线', value: UploadStatus.Online },
312
- { label: '下线', value: UploadStatus.Offline },
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
- class="flex items-center text-blue-500 hover:text-blue-700 mr-1 cursor-pointer"
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
- icon="icon-download"
326
- v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:download' }"
327
- clickable
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
- class="flex items-center text-blue-500 hover:text-blue-700 mr-1 cursor-pointer"
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
- icon="icon-eye"
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
- clickable
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 class="flex items-center text-red-500 hover:text-red-700 cursor-pointer">
360
- <Popconfirm
361
- v-model:open="confirmOpen"
362
- cancelText=""
363
- okText=""
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
- icon="icon-new"
374
- :angle="45"
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
- v-if="
394
- file.status !== UploadStatus.Online &&
395
- file.status !== UploadStatus.Offline &&
396
- file.status !== UploadStatus.Success
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
  }
@@ -4,6 +4,7 @@ import message from 'vue-m-message';
4
4
  import { isMicroApp, LoginInfo, UserInfo } from '@skyfox2000/microbase';
5
5
  import { ref } from 'vue';
6
6
  import { useAppInfo } from './appInfo';
7
+ import { MicroOpenApis } from '@/utils/micro-openapis';
7
8
 
8
9
  const TokenError = 'Token解析失败';
9
10
  export const LoginExpiredError = 1400;
@@ -375,6 +376,11 @@ export const useUserInfo = defineStore('userInfo', {
375
376
  * @returns
376
377
  */
377
378
  async logout(exit: boolean): Promise<void> {
379
+ if (isMicroApp()) {
380
+ // 调用基座退出登录
381
+ MicroOpenApis.userLogout();
382
+ return Promise.resolve();
383
+ }
378
384
  try {
379
385
  if (exit) {
380
386
  // 调用后端登出接口
@@ -206,7 +206,7 @@ export class AsyncUploader {
206
206
  file.status = UploadStatus.Uploading;
207
207
 
208
208
  // 以 Promise 化的方式处理上传请求
209
- return new Promise((resolve, reject) => {
209
+ return new Promise(async (resolve, reject) => {
210
210
  // 创建表单数据
211
211
  const formData = new FormData();
212
212
  formData.append('file', file.originFileObj as File);
@@ -235,7 +235,7 @@ export class AsyncUploader {
235
235
 
236
236
  // 添加授权 Token(如果需要)
237
237
  if (this.urlInfo.authorize) {
238
- const token = isMicroApp() ? MicroOpenApis.getToken() : useUserInfo().getToken(); // 假设 getToken 是获取 Token 的方法
238
+ const token = isMicroApp() ? await MicroOpenApis.getToken() : useUserInfo().getToken(); // 假设 getToken 是获取 Token 的方法
239
239
  if (!token) {
240
240
  reject(new Error('未授权或授权过期'));
241
241
  return;