@skyfox2000/webui 1.2.8 → 1.2.10

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 (148) hide show
  1. package/package.json +1 -1
  2. package/scripts/userInput.py +2 -0
  3. package/src/components/common/index.ts +3 -0
  4. package/src/components/common/loading/index.vue +11 -0
  5. package/src/components/content/dialog/index.vue +15 -8
  6. package/src/components/content/dialog/uploadForm.vue +38 -79
  7. package/src/components/content/drawer/index.vue +26 -6
  8. package/src/components/content/form/formItem.vue +21 -5
  9. package/src/components/content/form/index.vue +4 -2
  10. package/src/components/content/search/searchItem.vue +1 -1
  11. package/src/components/form/autoComplete/index.vue +12 -4
  12. package/src/components/form/cascader/index.vue +1 -1
  13. package/src/components/form/datePicker/index.vue +1 -1
  14. package/src/components/form/index.ts +1 -0
  15. package/src/components/form/input/inputIcon.vue +1 -1
  16. package/src/components/form/propEditor/index.vue +113 -33
  17. package/src/components/form/select/index.vue +27 -17
  18. package/src/components/form/upload/uploadList.vue +174 -34
  19. package/src/components/index.ts +13 -1
  20. package/src/directives/permission.ts +2 -2
  21. package/src/index.ts +3 -1
  22. package/src/stores/userInfo.ts +28 -2
  23. package/src/typings/form.d.ts +18 -2
  24. package/src/typings/option.d.ts +16 -2
  25. package/src/typings/page.d.ts +1 -0
  26. package/src/utils/download.ts +1 -1
  27. package/src/utils/eventbus.ts +1 -1
  28. package/src/utils/file-upload.ts +75 -14
  29. package/src/utils/form-excel.ts +50 -1
  30. package/src/utils/form-validate.ts +18 -1
  31. package/src/utils/form.ts +3 -1
  32. package/src/utils/options.ts +38 -12
  33. package/lib/AceEditor.d.ts +0 -1
  34. package/lib/BasicLayout.d.ts +0 -1
  35. package/lib/Error403.d.ts +0 -1
  36. package/lib/Error404.d.ts +0 -1
  37. package/lib/ExcelForm.d.ts +0 -1
  38. package/lib/UploadForm.d.ts +0 -1
  39. package/lib/assets/modules/file-upload-CZO-pMJd.js +0 -176
  40. package/lib/assets/modules/form-excel-N-2OYqKv.js +0 -211
  41. package/lib/assets/modules/index-BnHnS9ug.js +0 -111
  42. package/lib/assets/modules/index-CTVMLeDF.js +0 -109
  43. package/lib/assets/modules/index-D9kzQ23e.js +0 -2213
  44. package/lib/assets/modules/menuTabs-BtOiocOC.js +0 -676
  45. package/lib/assets/modules/toolIcon-B9Mw9Ktm.js +0 -50
  46. package/lib/assets/modules/uploadList-B4LxzsC6.js +0 -210
  47. package/lib/components/common/button/index.vue.d.ts +0 -41
  48. package/lib/components/common/icon/appicon.vue.d.ts +0 -11
  49. package/lib/components/common/icon/fullscreen.vue.d.ts +0 -3
  50. package/lib/components/common/icon/helper.vue.d.ts +0 -22
  51. package/lib/components/common/icon/index.vue.d.ts +0 -243
  52. package/lib/components/common/icon/layoutIcon.vue.d.ts +0 -43
  53. package/lib/components/common/icon/projectIcon.vue.d.ts +0 -59
  54. package/lib/components/common/icon/toolIcon.vue.d.ts +0 -43
  55. package/lib/components/common/index.d.ts +0 -18
  56. package/lib/components/common/tooltip/index.vue.d.ts +0 -21
  57. package/lib/components/content/dialog/index.vue.d.ts +0 -34
  58. package/lib/components/content/drawer/index.vue.d.ts +0 -26
  59. package/lib/components/content/form/formItem.vue.d.ts +0 -25
  60. package/lib/components/content/form/index.vue.d.ts +0 -25
  61. package/lib/components/content/index.d.ts +0 -22
  62. package/lib/components/content/search/index.vue.d.ts +0 -30
  63. package/lib/components/content/search/searchItem.vue.d.ts +0 -23
  64. package/lib/components/content/table/index.vue.d.ts +0 -36
  65. package/lib/components/content/table/tableOperate.vue.d.ts +0 -18
  66. package/lib/components/content/toolbar/icontool.vue.d.ts +0 -7
  67. package/lib/components/content/toolbar/index.vue.d.ts +0 -18
  68. package/lib/components/content/tree/index.vue.d.ts +0 -46
  69. package/lib/components/form/aceEditor/aceConfig.d.ts +0 -8
  70. package/lib/components/form/autoComplete/index.vue.d.ts +0 -139
  71. package/lib/components/form/cascader/index.vue.d.ts +0 -109
  72. package/lib/components/form/checkbox/index.vue.d.ts +0 -128
  73. package/lib/components/form/datePicker/index.vue.d.ts +0 -6
  74. package/lib/components/form/index.d.ts +0 -38
  75. package/lib/components/form/input/index.vue.d.ts +0 -26
  76. package/lib/components/form/input/inputIcon.vue.d.ts +0 -10
  77. package/lib/components/form/input/inputNumber.vue.d.ts +0 -3
  78. package/lib/components/form/input/inputPassword.vue.d.ts +0 -3
  79. package/lib/components/form/propEditor/index.vue.d.ts +0 -12
  80. package/lib/components/form/radio/index.vue.d.ts +0 -133
  81. package/lib/components/form/radio/radioStatus.vue.d.ts +0 -31
  82. package/lib/components/form/rangePicker/index.vue.d.ts +0 -16
  83. package/lib/components/form/select/index.vue.d.ts +0 -142
  84. package/lib/components/form/switch/index.vue.d.ts +0 -43
  85. package/lib/components/form/textarea/index.vue.d.ts +0 -3
  86. package/lib/components/form/transfer/index.vue.d.ts +0 -38
  87. package/lib/components/form/transfer/transferTable.vue.d.ts +0 -38
  88. package/lib/components/form/treeSelect/index.vue.d.ts +0 -38
  89. package/lib/components/form/upload/uploadList.vue.d.ts +0 -476
  90. package/lib/components/index.d.ts +0 -4
  91. package/lib/components/layout/breadcrumb/index.vue.d.ts +0 -3
  92. package/lib/components/layout/content/index.vue.d.ts +0 -22
  93. package/lib/components/layout/datetime/index.vue.d.ts +0 -3
  94. package/lib/components/layout/header/headerExits.vue.d.ts +0 -3
  95. package/lib/components/layout/header/index.vue.d.ts +0 -3
  96. package/lib/components/layout/header/user.vue.d.ts +0 -3
  97. package/lib/components/layout/index.d.ts +0 -14
  98. package/lib/components/layout/menu/index.vue.d.ts +0 -6
  99. package/lib/components/layout/menu/menuTabs.vue.d.ts +0 -3
  100. package/lib/const/options.d.ts +0 -32
  101. package/lib/directives/enter-submit.d.ts +0 -4
  102. package/lib/directives/index.d.ts +0 -2
  103. package/lib/directives/permission.d.ts +0 -5
  104. package/lib/es/AceEditor/index.js +0 -167
  105. package/lib/es/BasicLayout/index.js +0 -101
  106. package/lib/es/Error403/index.js +0 -39
  107. package/lib/es/Error404/index.js +0 -39
  108. package/lib/es/ExcelForm/index.js +0 -321
  109. package/lib/es/UploadForm/index.js +0 -137
  110. package/lib/index.d.ts +0 -45
  111. package/lib/router/index.d.ts +0 -15
  112. package/lib/stores/appInfo.d.ts +0 -31
  113. package/lib/stores/hostInfo.d.ts +0 -9
  114. package/lib/stores/pageInfo.d.ts +0 -18
  115. package/lib/stores/pinia.d.ts +0 -3
  116. package/lib/stores/settingInfo.d.ts +0 -8
  117. package/lib/stores/userInfo.d.ts +0 -24
  118. package/lib/typings/data.d.ts +0 -80
  119. package/lib/typings/form.d.ts +0 -171
  120. package/lib/typings/menu.d.ts +0 -7
  121. package/lib/typings/option.d.ts +0 -175
  122. package/lib/typings/page.d.ts +0 -69
  123. package/lib/typings/table.d.ts +0 -181
  124. package/lib/typings/tools.d.ts +0 -130
  125. package/lib/typings/tree.d.ts +0 -72
  126. package/lib/typings/upload.d.ts +0 -161
  127. package/lib/typings/urls.d.ts +0 -69
  128. package/lib/utils/cache.d.ts +0 -23
  129. package/lib/utils/data.d.ts +0 -6
  130. package/lib/utils/download.d.ts +0 -4
  131. package/lib/utils/eventbus.d.ts +0 -16
  132. package/lib/utils/export-table.d.ts +0 -12
  133. package/lib/utils/file-upload.d.ts +0 -15
  134. package/lib/utils/form-excel.d.ts +0 -30
  135. package/lib/utils/form-validate.d.ts +0 -29
  136. package/lib/utils/form.d.ts +0 -9
  137. package/lib/utils/icon-loader.d.ts +0 -125
  138. package/lib/utils/isEmpty.d.ts +0 -1
  139. package/lib/utils/main-openapis.d.ts +0 -8
  140. package/lib/utils/menu.d.ts +0 -6
  141. package/lib/utils/options.d.ts +0 -10
  142. package/lib/utils/page.d.ts +0 -25
  143. package/lib/utils/table.d.ts +0 -21
  144. package/lib/utils/tools.d.ts +0 -18
  145. package/lib/utils/tree.d.ts +0 -3
  146. package/lib/vite-env.d.ts +0 -8
  147. package/lib/webui.css +0 -1
  148. package/lib/webui.es.js +0 -2240
@@ -2,44 +2,108 @@
2
2
  import { ref, watch } from 'vue';
3
3
  import { Input, Button } from 'ant-design-vue';
4
4
 
5
- interface ConfigItem {
5
+ export interface PropConfigItem {
6
6
  id: number;
7
+ /**
8
+ * 文本
9
+ */
10
+ text?: string;
11
+ /**
12
+ * 配置名
13
+ */
7
14
  field: string;
15
+ /**
16
+ * 配置值
17
+ */
8
18
  value: string;
9
19
  }
10
20
 
11
21
  const props = defineProps<{
22
+ /**
23
+ * 配置值
24
+ */
12
25
  value: Record<string, string>;
26
+ /**
27
+ * 配置项
28
+ */
29
+ selectList?: PropConfigItem[];
30
+ /**
31
+ * 配置名宽度%
32
+ */
33
+ fieldWidth?: number;
34
+ /**
35
+ * 标签占位符
36
+ */
13
37
  labelHolder?: string;
14
- valueHolder: string;
38
+ /**
39
+ * 值占位符
40
+ */
41
+ valueHolder?: string;
42
+ /**
43
+ * 新增配置行
44
+ */
45
+ addMore?: boolean;
15
46
  }>();
16
47
  const emit = defineEmits(['update:value']);
17
48
 
18
- const configList = ref<ConfigItem[]>([]);
19
- let isInnerChange = false; // 标记是否为内部输入变更
49
+ // 当有selectList时,不允许添加更多配置项
50
+ const addMore = ref(props.selectList && props.selectList.length > 0 ? false : (props.addMore ?? true));
20
51
 
52
+ const configList = ref<PropConfigItem[]>([]);
53
+ // 标记是否为内部输入变更
54
+ // 避免重复触发 update:value
55
+ let isInnerChange = false;
56
+
57
+ // 初始化配置列表
58
+ // 1、有selectList时,只能使用selectList里面的内容,且不允许重复
59
+ // 2、没有selectList时,可动态添加新的项目
60
+ // 3、value有值时,能够正常显示值,value的key对应field
21
61
  const initConfigList = () => {
22
- configList.value = Object.entries(props.value).map(([field, value]) => ({
23
- id: Date.now() + Math.random(),
24
- field,
25
- value,
26
- }));
62
+ if (props.selectList && props.selectList.length > 0) {
63
+ // 有selectList的情况:使用selectList作为基础,合并value值
64
+ configList.value = props.selectList.map((item) => ({
65
+ id: Date.now() + Math.random(),
66
+ text: item.text,
67
+ field: item.field,
68
+ // 如果value中有对应的field,使用value中的值,否则使用selectList中的默认值
69
+ value: props.value[item.field] ?? item.value,
70
+ }));
71
+ } else {
72
+ // 没有selectList的情况:基于value动态生成配置项
73
+ if (props.value && Object.keys(props.value).length > 0) {
74
+ configList.value = Object.entries(props.value).map(([field, value]) => ({
75
+ id: Date.now() + Math.random(),
76
+ field,
77
+ value,
78
+ }));
79
+ } else {
80
+ // value为空时,初始化为空数组
81
+ configList.value = [];
82
+ }
83
+ }
27
84
  };
28
85
 
29
- watch(() => props.value, () => {
30
- if (!isInnerChange) {
31
- initConfigList();
32
- }
33
- isInnerChange = false;
34
- }, { immediate: true });
86
+ watch(
87
+ () => props.value,
88
+ () => {
89
+ if (!isInnerChange) {
90
+ initConfigList();
91
+ }
92
+ isInnerChange = false;
93
+ },
94
+ { immediate: true },
95
+ );
35
96
 
36
97
  const updateConfig = () => {
37
- const newConfig = configList.value.reduce((acc: Record<string, string>, item: ConfigItem) => {
38
- if (item.field) {
39
- acc[item.field] = item.value;
40
- }
41
- return acc;
42
- }, {} as Record<string, string>);
98
+ const newConfig = configList.value.reduce(
99
+ (acc: Record<string, string>, item: PropConfigItem) => {
100
+ if (item.field) {
101
+ acc[item.field] = item.value;
102
+ }
103
+ return acc;
104
+ },
105
+ {} as Record<string, string>,
106
+ );
43
107
  isInnerChange = true;
44
108
  emit('update:value', newConfig);
45
109
  };
@@ -60,22 +124,38 @@ const handleInputChange = () => {
60
124
  <template>
61
125
  <div class="flex flex-col gap-2">
62
126
  <div v-for="item in configList" :key="item.id" class="flex items-center gap-2">
63
- <div class="w-[33%]">
64
- <Input v-model:value="item.field" :title="item.field" class="w-full" :placeholder="labelHolder || '配置名'"
65
- @input="handleInputChange" />
66
- </div>
67
- <div class="w-[3%]">
68
- =
127
+ <div :class="[fieldWidth ? `w-[${fieldWidth}%]` : 'w-[33%]']">
128
+ <Input
129
+ v-if="!selectList || selectList.length === 0"
130
+ v-model:value="item.field"
131
+ :title="item.text || item.field"
132
+ class="w-full"
133
+ :placeholder="item.text || labelHolder || '配置名'"
134
+ @input="handleInputChange"
135
+ :disabled="!addMore"
136
+ />
137
+ <div v-else>
138
+ <Input v-model:value="item.text" :title="item.text" :disabled="true" class="w-[100%]" />
139
+ <Input type="hidden" v-model:value="item.field" />
140
+ </div>
69
141
  </div>
70
- <div class="w-[64%]">
71
- <Input v-model:value="item.value" :placeholder="valueHolder" @input="handleInputChange"
72
- :title="item.value" />
142
+ <div class="w-[3%]">=</div>
143
+ <div :class="[fieldWidth ? `w-[${97 - fieldWidth}%]` : 'w-[64%]']">
144
+ <Input
145
+ v-model:value="item.value"
146
+ :placeholder="valueHolder || '请输入' + item.text || '请输入配置值'"
147
+ @input="handleInputChange"
148
+ :title="item.value"
149
+ />
73
150
  </div>
74
151
  </div>
75
- <Button @click="addNewLine"
152
+ <Button
153
+ v-if="addMore"
154
+ @click="addNewLine"
76
155
  class="mt-1 w-[80px] !text-[12px] text-[#666] bg-[#e6f7ff] border-[#b3e0ff] hover:bg-[#b3e0ff] hover:border-[#8abeff]"
77
- size="small">
156
+ size="small"
157
+ >
78
158
  新增配置行
79
159
  </Button>
80
160
  </div>
81
- </template>
161
+ </template>
@@ -73,28 +73,45 @@ const url = ref<IUrlInfo>({
73
73
  const inputFactory = useInputFactory();
74
74
  const { editorCtrl, errInfo, labelText } = inputFactory;
75
75
 
76
+ const defaultVal = ref(props.value);
77
+ const placeholder = ref(attrs.placeholder);
78
+
76
79
  /// 避免类型错误
77
80
  const innerValue = ref<string | number | string[] | number[] | undefined>(undefined);
78
81
  const emit = defineEmits(['change', 'update:value', 'update:labels']);
79
82
  inputFactory.inputEmit = emit;
83
+
80
84
  /**
81
85
  * 实际的选择项
82
86
  */
83
87
  const selectOptions = ref<OptionItemProps[]>([]);
88
+ const onChanged = (value: any) => {
89
+ const selectedOptions = onOptionChanged(props, value as SelectValue, selectOptions, inputFactory);
90
+ const labels: string[] = getSelectedLabels(selectedOptions);
91
+
92
+ innerValue.value = value;
93
+ emit('update:labels', labels);
94
+ emit('change', value);
95
+
96
+ if (errInfo?.value.errClass && editorCtrl) {
97
+ /// 重新开始验证
98
+ formValidate(editorCtrl);
99
+ }
100
+ };
101
+
84
102
  watch(
85
103
  () => selectOptions.value,
86
104
  (newVal) => {
87
- if (newVal.length > 0 && isEmpty(props.value) && props.selectFirst) {
105
+ if (newVal.length && isEmpty(props.value) && props.selectFirst) {
88
106
  innerValue.value = newVal[0].value;
89
- onChanged(newVal[0].value);
90
107
  } else {
91
108
  // 当选项加载完成后,设置实际的 value 值
92
109
  innerValue.value = props.value === null ? undefined : props.value;
93
110
  }
111
+ if (newVal.length > 0 && innerValue.value) onChanged(innerValue.value);
94
112
  },
95
113
  );
96
114
 
97
- const placeholder = ref(attrs.placeholder);
98
115
  watch(
99
116
  () => url.value.loading,
100
117
  (newVal) => {
@@ -104,7 +121,6 @@ watch(
104
121
  { immediate: true },
105
122
  );
106
123
 
107
- const defaultVal = ref(props.value);
108
124
  watch(
109
125
  () => innerValue.value,
110
126
  (newVal) => {
@@ -118,19 +134,13 @@ watch(
118
134
  },
119
135
  );
120
136
 
121
- const onChanged = (value: any) => {
122
- const selectedOptions = onOptionChanged(props, value as SelectValue, selectOptions, inputFactory);
123
- const labels: string[] = getSelectedLabels(selectedOptions);
124
-
125
- innerValue.value = value;
126
- emit('update:labels', labels);
127
- emit('change', value);
128
-
129
- if (errInfo?.value.errClass && editorCtrl) {
130
- /// 重新开始验证
131
- formValidate(editorCtrl);
132
- }
133
- };
137
+ watch(
138
+ () => props.params,
139
+ (newVal) => {
140
+ loadOption(true, props, selectOptions, inputFactory, url.value, newVal);
141
+ },
142
+ { deep: true },
143
+ );
134
144
 
135
145
  onMounted(() => {
136
146
  if (url.value && !url.value.fieldMap) {
@@ -1,10 +1,11 @@
1
1
  <script setup lang="ts">
2
- import { Button } from '../../common';
2
+ import { Button, ToolIcon, Tooltip } from '../../common';
3
3
  import { computed, ref, watch } from 'vue';
4
4
  import message from 'vue-m-message';
5
5
  import type { UploadProps } from 'ant-design-vue';
6
- import { Upload, Progress, Tag } from 'ant-design-vue';
7
- import { UploadFile, UploadStatus, donwloadFromMinio, path } from '@/index';
6
+ import { Upload, Progress, Tag, Popconfirm } from 'ant-design-vue';
7
+ import { UploadFile, UploadStatus, donwloadFromMinio, path, Switch } from '@/index';
8
+ import { useInputFactory } from '@/utils/form-validate';
8
9
  import { IUrlInfo } from '@skyfox2000/fapi';
9
10
 
10
11
  export interface UploadListProps {
@@ -12,14 +13,19 @@ export interface UploadListProps {
12
13
  * 是否自动上传
13
14
  */
14
15
  autoUpload?: boolean;
16
+ /**
17
+ * 上传Url
18
+ */
19
+ uploadUrl: IUrlInfo;
20
+ /**
15
21
  /*
16
22
  * 下载Url
17
23
  */
18
- downloadUrl: IUrlInfo;
24
+ downloadUrl?: IUrlInfo;
19
25
  /**
20
26
  * 文件列表
21
27
  */
22
- fileList: UploadFile<any>[];
28
+ fileList: UploadFile[];
23
29
  /**
24
30
  * 提示文字
25
31
  */
@@ -36,10 +42,30 @@ export interface UploadListProps {
36
42
  * 最大数量
37
43
  */
38
44
  maxCount?: number;
45
+ /**
46
+ * 最大数量提示
47
+ */
48
+ maxCountTip?: boolean;
49
+ /**
50
+ * 文件大小提示
51
+ */
52
+ maxFileSizeTip?: boolean;
53
+ /**
54
+ * 文件类型提示
55
+ */
56
+ fileExtTip?: boolean;
39
57
  /**
40
58
  * 文件路径
41
59
  */
42
60
  parentPath?: string;
61
+ /**
62
+ * 显示操作文字
63
+ */
64
+ showActionText?: boolean;
65
+ /**
66
+ * 是否显示上线或下线
67
+ */
68
+ showOnlineSwitch?: boolean;
43
69
  }
44
70
 
45
71
  const props = withDefaults(defineProps<UploadListProps>(), {
@@ -48,12 +74,20 @@ const props = withDefaults(defineProps<UploadListProps>(), {
48
74
  placeholder: '',
49
75
  maxFileSize: 20,
50
76
  maxCount: 5,
77
+ maxCountTip: false,
78
+ maxFileSizeTip: true,
79
+ fileExtTip: true,
80
+ showActionText: true,
81
+ showOnlineSwitch: false,
51
82
  });
52
83
 
84
+ const inputFactory = useInputFactory();
85
+ const { errInfo } = inputFactory;
86
+
53
87
  const fileList = ref<UploadFile[]>(props.fileList);
54
88
  const fileUploader = ref();
55
89
  const emit = defineEmits(['update:file-list']);
56
-
90
+ const confirmOpen = ref(false);
57
91
  const acceptString = computed(() => (props.fileExt?.length ? props.fileExt.map((ext) => `.${ext}`).join(',') : ''));
58
92
 
59
93
  const beforeUpload: UploadProps['beforeUpload'] = (file) => {
@@ -75,13 +109,18 @@ const beforeUpload: UploadProps['beforeUpload'] = (file) => {
75
109
  return false;
76
110
  }
77
111
 
112
+ confirmOpen.value = false;
78
113
  return props.autoUpload;
79
114
  };
80
115
 
81
116
  const updateFileList: UploadProps['onUpdate:fileList'] = (fileList) => {
82
117
  fileList.forEach((file) => {
83
- if (!file.fileName) file.fileName = file.name;
84
- if (props.parentPath) file.name = path.join('/', props.parentPath, file.fileName);
118
+ const fileInfo = file as UploadFile<any>;
119
+ if (!fileInfo.fileName) fileInfo.fileName = fileInfo.name;
120
+ if (props.parentPath) fileInfo.name = path.join('/', props.parentPath, fileInfo.fileName);
121
+ if (!fileInfo.params) fileInfo.params = {};
122
+ fileInfo.params.FileKey = fileInfo.name;
123
+ fileInfo.status = UploadStatus.Pending;
85
124
  });
86
125
  };
87
126
 
@@ -101,6 +140,14 @@ const uploadProps = computed<UploadProps>(() => ({
101
140
  },
102
141
  }));
103
142
 
143
+ watch(
144
+ () => props.fileList,
145
+ (newVal) => {
146
+ fileList.value = newVal;
147
+ },
148
+ { deep: true, immediate: true },
149
+ );
150
+
104
151
  watch(
105
152
  () => fileList.value,
106
153
  (newVal) => {
@@ -109,16 +156,27 @@ watch(
109
156
  { deep: true },
110
157
  );
111
158
 
159
+ watch(
160
+ () => props.parentPath,
161
+ (newVal) => {
162
+ if (newVal) {
163
+ fileList.value.forEach((file) => {
164
+ file.params.FileKey = path.join('/', newVal, file.fileName);
165
+ });
166
+ }
167
+ },
168
+ );
169
+
112
170
  const downloadFile = (index: number) => {
113
- const fileInfo = fileList.value[index].minioFile!;
171
+ if (!props.downloadUrl) return;
172
+ const minioFile = fileList.value[index].minioFile!;
114
173
  const url: IUrlInfo = {
115
174
  api: props.downloadUrl.api,
116
175
  authorize: props.downloadUrl.authorize,
117
176
  url: props.downloadUrl.url,
118
- // url: props.pageData.urls.download!.url,
119
177
  params: {
120
178
  Query: {
121
- FileKey: fileInfo.Key,
179
+ FileKey: minioFile.Key,
122
180
  },
123
181
  },
124
182
  };
@@ -127,23 +185,34 @@ const downloadFile = (index: number) => {
127
185
  };
128
186
 
129
187
  const onlineOrOffline = (file: UploadFile) => {
130
- file.status = file.status === UploadStatus.Offline ? UploadStatus.Online : UploadStatus.Offline;
131
- file.minioFile!.Status = file.status;
188
+ if (file.minioFile) {
189
+ file.minioFile.Status = file.status!;
190
+ }
132
191
  };
133
192
 
134
193
  // const previewFile = (index: number) => {
135
- // const fileInfo = fileList.value[index].minioFile;
194
+ // const fileInfo = internalFileList.value[index].minioFile;
136
195
  // console.log(fileInfo);
137
196
  // };
138
197
 
139
198
  const removeFile = (index: number) => {
140
199
  fileList.value.splice(index, 1);
200
+ confirmOpen.value = false;
201
+ };
202
+
203
+ const confirmDelFile = (index: number, status?: UploadStatus) => {
204
+ if (status === UploadStatus.Pending) {
205
+ removeFile(index);
206
+ return;
207
+ }
208
+ confirmOpen.value = true;
141
209
  };
142
210
 
143
211
  const getPlaceholder = (): string => {
144
- const typeMsg = props.fileExt && props.fileExt.length ? `文件必须为 ${props.fileExt.join('/')}` : '';
145
- const sizeMsg = props.maxFileSize !== 0 ? `单文件最大 ${props.maxFileSize}MB` : '';
146
- const countMsg = props.maxCount !== 0 ? `最多 ${props.maxCount} 个文件` : '';
212
+ const typeMsg =
213
+ props.fileExt && props.fileExt.length && props.fileExtTip ? `文件必须为 ${props.fileExt.join('/')}` : '';
214
+ const sizeMsg = props.maxFileSize !== 0 && props.maxFileSizeTip ? `单文件最大 ${props.maxFileSize}MB` : '';
215
+ const countMsg = props.maxCount !== 0 && props.maxCountTip ? `最多 ${props.maxCount} 个文件` : '';
147
216
 
148
217
  return [sizeMsg, typeMsg, countMsg].filter(Boolean).join(',');
149
218
  };
@@ -164,12 +233,13 @@ const getStatusColor = (status?: UploadStatus) => {
164
233
  return 'cyan';
165
234
  }
166
235
  };
236
+
167
237
  const getStatus = (status?: UploadStatus) => {
168
238
  switch (status) {
169
239
  case UploadStatus.Uploading:
170
240
  return '上传中';
171
241
  case UploadStatus.Success:
172
- return '已完成';
242
+ return '上传完成';
173
243
  case UploadStatus.Error:
174
244
  return '上传失败';
175
245
  case UploadStatus.Online:
@@ -183,14 +253,20 @@ const getStatus = (status?: UploadStatus) => {
183
253
  </script>
184
254
 
185
255
  <template>
186
- <div class="w-full border border-solid border-gray-100 mt-1 rounded-md py-5">
256
+ <div class="w-full border border-solid border-gray-100 mt-1 rounded-md py-5" :class="[errInfo?.errClass]">
187
257
  <div class="flex items-center justify-between w-full">
188
258
  <div class="w-35 mx-3">
189
- <Upload ref="fileUploader" v-bind="uploadProps">
190
- <Button>选择文件</Button>
259
+ <Upload
260
+ ref="fileUploader"
261
+ v-bind="uploadProps"
262
+ v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:upload' }"
263
+ >
264
+ <Button :class="[errInfo?.errClass + '-text']">选择文件</Button>
191
265
  </Upload>
192
266
  </div>
193
- <div class="flex-1 text-sm text-gray-500">{{ getPlaceholder() }}</div>
267
+ <div class="flex-1 text-sm text-gray-500" :class="[errInfo?.errClass + '-text']">
268
+ {{ getPlaceholder() }}
269
+ </div>
194
270
  <!-- <Button v-if="!autoUpload" @click="manualUpload" class="mr-3">开始上传</Button> -->
195
271
  </div>
196
272
 
@@ -208,28 +284,92 @@ const getStatus = (status?: UploadStatus) => {
208
284
  </span>
209
285
  </div>
210
286
  <div class="flex items-center">
211
- <span
212
- class="text-blue-500 hover:text-blue-700 mr-4 cursor-pointer"
213
- v-if="file.status == UploadStatus.Offline || file.status == UploadStatus.Online"
214
- @click="onlineOrOffline(file)"
215
- >{{ file.status == UploadStatus.Offline ? '上线' : '下线' }}</span
287
+ <div
288
+ class="mr-2"
289
+ v-if="
290
+ showOnlineSwitch && (file.status == UploadStatus.Online || file.status == UploadStatus.Offline)
291
+ "
216
292
  >
217
- <span
218
- v-if="file.status == UploadStatus.Offline || file.status == UploadStatus.Online"
219
- class="text-blue-500 hover:text-blue-700 mr-4 cursor-pointer"
220
- @click="downloadFile(index)"
221
- >下载</span
293
+ <Tooltip title="上线或下线">
294
+ <Switch
295
+ v-model:checked="file.status"
296
+ :data="[
297
+ { label: '上线', value: UploadStatus.Online },
298
+ { label: '下线', value: UploadStatus.Offline },
299
+ ]"
300
+ @change="onlineOrOffline(file)"
301
+ v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:online' }"
302
+ />
303
+ </Tooltip>
304
+ </div>
305
+ <div
306
+ class="flex items-center text-blue-500 hover:text-blue-700 mr-1 cursor-pointer"
307
+ v-if="downloadUrl && (file.status == UploadStatus.Online || file.status == UploadStatus.Offline)"
222
308
  >
309
+ <Tooltip title="下载">
310
+ <ToolIcon
311
+ icon="icon-download"
312
+ v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:download' }"
313
+ clickable
314
+ @click="downloadFile(index)"
315
+ />
316
+ <span
317
+ v-if="showActionText"
318
+ class="mr-2 text-sm text-nowrap"
319
+ v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:download' }"
320
+ @click="downloadFile(index)"
321
+ >下载</span
322
+ >
323
+ </Tooltip>
324
+ </div>
223
325
  <!-- <span class="text-blue-500 hover:text-blue-700 mr-4" @click="previewFile(index)">预览</span> -->
224
- <span class="text-red-500 hover:text-red-700 cursor-pointer" @click="removeFile(index)">删除</span>
326
+ <div class="flex items-center text-red-500 hover:text-red-700 cursor-pointer">
327
+ <Popconfirm
328
+ v-model:open="confirmOpen"
329
+ cancelText="否"
330
+ okText="是"
331
+ title="确定删除该文件吗?"
332
+ :okButtonProps="{ size: 'small' }"
333
+ :cancelButtonProps="{ size: 'small' }"
334
+ @confirm="removeFile(index)"
335
+ @cancel="confirmOpen = false"
336
+ >
337
+ <Tooltip title="删除">
338
+ <div @click="confirmDelFile(index, file.status)">
339
+ <ToolIcon
340
+ icon="icon-new"
341
+ :angle="45"
342
+ v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:delete' }"
343
+ clickable
344
+ />
345
+ <span
346
+ v-if="showActionText"
347
+ class="text-sm text-nowrap"
348
+ v-auth="{ role: ['Super', 'Admin'], permit: ':uploadlist:delete' }"
349
+ >删除</span
350
+ >
351
+ </div>
352
+ </Tooltip>
353
+ </Popconfirm>
354
+ </div>
225
355
  </div>
226
356
  </div>
227
357
 
228
358
  <!-- 上传进度条 -->
229
- <div>
359
+ <div v-if="file.status !== UploadStatus.Online && file.status !== UploadStatus.Offline && file.status !== UploadStatus.Success">
230
360
  <Progress :percent="file.percent" :stroke-width="2" :show-info="false" style="height: 2px"></Progress>
231
361
  </div>
232
362
  </div>
233
363
  </div>
234
364
  </div>
235
365
  </template>
366
+
367
+ <style scoped>
368
+ .error {
369
+ border-color: #ff4d4f80;
370
+ box-shadow: 0 0 3px 0 #ff4d4f;
371
+ }
372
+ .error-text {
373
+ color: #ff4d4f !important;
374
+ }
375
+ </style>
@@ -1,5 +1,16 @@
1
1
  // 基础组件
2
- export { Button, Tooltip, AppIcon, Fullscreen, Helper, Icon, LayoutIcon, ProjectIcon, ToolIcon } from './common';
2
+ export {
3
+ Button,
4
+ Tooltip,
5
+ AppIcon,
6
+ Fullscreen,
7
+ Helper,
8
+ Icon,
9
+ LayoutIcon,
10
+ ProjectIcon,
11
+ ToolIcon,
12
+ Loading,
13
+ } from './common';
3
14
 
4
15
  // 内容组件
5
16
  export {
@@ -27,6 +38,7 @@ export {
27
38
  InputPassword,
28
39
  InputNumber,
29
40
  PropEditor,
41
+ type PropConfigItem,
30
42
  Radio,
31
43
  RadioStatus,
32
44
  RangePicker,
@@ -12,7 +12,7 @@ type BehaviorType = 'remove' | 'disable';
12
12
  * 权限参数类型
13
13
  */
14
14
  interface PermissionParams {
15
- url: string;
15
+ url?: string;
16
16
  role?: string | string[];
17
17
  permit?: string;
18
18
  behavior?: BehaviorType;
@@ -83,7 +83,7 @@ const checkPermission = (params: PermissionParams): boolean => {
83
83
  }
84
84
 
85
85
  // 获取当前URL,优先使用传入的url,否则使用当前路由路径
86
- const currentUrl = url;
86
+ const currentUrl = url ?? window.location.hash?.split('#')?.[1] ?? window.location.pathname;
87
87
 
88
88
  if (EnvConfig.VITE_PERMISSION_MODE === 'role') {
89
89
  // 仅判断角色权限
package/src/index.ts CHANGED
@@ -155,7 +155,7 @@ export {
155
155
  } from '@/utils/form-validate';
156
156
 
157
157
  // form-excel 工具
158
- export { validateExcel, checkExcelDuplicates, processExcelFile } from '@/utils/form-excel';
158
+ export { validateExcel, checkExcelDuplicates, processExcelFile, appendExcelData } from '@/utils/form-excel';
159
159
  export type { ExcelMarkCell, ExcelMarkInfo } from '@/utils/form-excel';
160
160
 
161
161
  // table 工具
@@ -207,6 +207,7 @@ export {
207
207
  LayoutIcon,
208
208
  ProjectIcon,
209
209
  ToolIcon,
210
+ Loading,
210
211
  Dialog,
211
212
  Drawer,
212
213
  Form,
@@ -227,6 +228,7 @@ export {
227
228
  InputPassword,
228
229
  InputNumber,
229
230
  PropEditor,
231
+ type PropConfigItem,
230
232
  Radio,
231
233
  RadioStatus,
232
234
  RangePicker,