@skyfox2000/webui 1.3.15 → 1.3.17

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 (132) hide show
  1. package/package.json +1 -1
  2. package/src/components/form/select/index.vue +27 -14
  3. package/src/components/layout/page/baseLayout.vue +44 -0
  4. package/src/components/layout/page/basicLayout.vue +11 -44
  5. package/src/components/layout/page/menuLayout.vue +35 -0
  6. package/src/typings/option.d.ts +2 -2
  7. package/src/utils/data.ts +5 -1
  8. package/src/utils/options.ts +2 -2
  9. package/vite.config.ts +1 -0
  10. package/lib/AceEditor.d.ts +0 -1
  11. package/lib/BasicLayout.d.ts +0 -1
  12. package/lib/Error403.d.ts +0 -1
  13. package/lib/Error404.d.ts +0 -1
  14. package/lib/ExcelForm.d.ts +0 -1
  15. package/lib/UploadForm.d.ts +0 -1
  16. package/lib/assets/modules/_plugin-vue_export-helper-CHgC5LLL.js +0 -9
  17. package/lib/assets/modules/file-upload-D8Ln4vVV.js +0 -204
  18. package/lib/assets/modules/index-B2AK2Li9.js +0 -380
  19. package/lib/assets/modules/index-BnDOMkVL.js +0 -109
  20. package/lib/assets/modules/index-C8qhSdva.js +0 -112
  21. package/lib/assets/modules/menuTabs-FUxE-a2D.js +0 -671
  22. package/lib/assets/modules/toolIcon-bJ_WgHLU.js +0 -50
  23. package/lib/assets/modules/uploadList-BAX79qeV.js +0 -382
  24. package/lib/assets/modules/uploadList-BNkHE3fR.js +0 -2394
  25. package/lib/components/common/alert/index.vue.d.ts +0 -13
  26. package/lib/components/common/button/index.vue.d.ts +0 -41
  27. package/lib/components/common/icon/appicon.vue.d.ts +0 -11
  28. package/lib/components/common/icon/fullscreen.vue.d.ts +0 -3
  29. package/lib/components/common/icon/helper.vue.d.ts +0 -23
  30. package/lib/components/common/icon/index.vue.d.ts +0 -243
  31. package/lib/components/common/icon/layoutIcon.vue.d.ts +0 -43
  32. package/lib/components/common/icon/projectIcon.vue.d.ts +0 -59
  33. package/lib/components/common/icon/toolIcon.vue.d.ts +0 -43
  34. package/lib/components/common/index.d.ts +0 -22
  35. package/lib/components/common/loading/index.vue.d.ts +0 -3
  36. package/lib/components/common/tooltip/index.vue.d.ts +0 -21
  37. package/lib/components/content/dialog/index.vue.d.ts +0 -35
  38. package/lib/components/content/drawer/index.vue.d.ts +0 -28
  39. package/lib/components/content/form/formItem.vue.d.ts +0 -28
  40. package/lib/components/content/form/index.vue.d.ts +0 -25
  41. package/lib/components/content/index.d.ts +0 -22
  42. package/lib/components/content/search/index.vue.d.ts +0 -32
  43. package/lib/components/content/search/searchItem.vue.d.ts +0 -23
  44. package/lib/components/content/table/index.vue.d.ts +0 -127
  45. package/lib/components/content/table/tableOperate.vue.d.ts +0 -18
  46. package/lib/components/content/toolbar/icontool.vue.d.ts +0 -7
  47. package/lib/components/content/toolbar/index.vue.d.ts +0 -18
  48. package/lib/components/content/tree/index.vue.d.ts +0 -46
  49. package/lib/components/form/aceEditor/aceConfig.d.ts +0 -8
  50. package/lib/components/form/autoComplete/index.vue.d.ts +0 -101
  51. package/lib/components/form/cascader/index.vue.d.ts +0 -80
  52. package/lib/components/form/checkbox/index.vue.d.ts +0 -100
  53. package/lib/components/form/datePicker/index.vue.d.ts +0 -6
  54. package/lib/components/form/index.d.ts +0 -41
  55. package/lib/components/form/input/index.vue.d.ts +0 -29
  56. package/lib/components/form/input/inputIcon.vue.d.ts +0 -10
  57. package/lib/components/form/input/inputNumber.vue.d.ts +0 -3
  58. package/lib/components/form/input/inputPassword.vue.d.ts +0 -3
  59. package/lib/components/form/propEditor/index.vue.d.ts +0 -15
  60. package/lib/components/form/radio/index.vue.d.ts +0 -105
  61. package/lib/components/form/radio/radioStatus.vue.d.ts +0 -31
  62. package/lib/components/form/rangePicker/index.vue.d.ts +0 -16
  63. package/lib/components/form/select/index.vue.d.ts +0 -110
  64. package/lib/components/form/switch/index.vue.d.ts +0 -76
  65. package/lib/components/form/textarea/index.vue.d.ts +0 -3
  66. package/lib/components/form/timePicker/index.vue.d.ts +0 -6
  67. package/lib/components/form/transfer/index.vue.d.ts +0 -38
  68. package/lib/components/form/transfer/transferTable.vue.d.ts +0 -38
  69. package/lib/components/form/treeSelect/index.vue.d.ts +0 -47
  70. package/lib/components/form/upload/uploadList.vue.d.ts +0 -488
  71. package/lib/components/index.d.ts +0 -4
  72. package/lib/components/layout/breadcrumb/index.vue.d.ts +0 -3
  73. package/lib/components/layout/content/index.vue.d.ts +0 -22
  74. package/lib/components/layout/datetime/index.vue.d.ts +0 -3
  75. package/lib/components/layout/header/headerExits.vue.d.ts +0 -3
  76. package/lib/components/layout/header/index.vue.d.ts +0 -3
  77. package/lib/components/layout/header/user.vue.d.ts +0 -3
  78. package/lib/components/layout/index.d.ts +0 -14
  79. package/lib/components/layout/menu/index.vue.d.ts +0 -6
  80. package/lib/components/layout/menu/menuTabs.vue.d.ts +0 -3
  81. package/lib/const/options.d.ts +0 -32
  82. package/lib/directives/enter-submit.d.ts +0 -4
  83. package/lib/directives/index.d.ts +0 -2
  84. package/lib/directives/permission.d.ts +0 -5
  85. package/lib/es/AceEditor/index.js +0 -167
  86. package/lib/es/BasicLayout/index.js +0 -101
  87. package/lib/es/Error403/index.js +0 -39
  88. package/lib/es/Error404/index.js +0 -39
  89. package/lib/es/ExcelForm/index.js +0 -491
  90. package/lib/es/UploadForm/index.js +0 -110
  91. package/lib/index.d.ts +0 -46
  92. package/lib/router/index.d.ts +0 -15
  93. package/lib/stores/appInfo.d.ts +0 -31
  94. package/lib/stores/hostInfo.d.ts +0 -11
  95. package/lib/stores/pageInfo.d.ts +0 -18
  96. package/lib/stores/pinia.d.ts +0 -3
  97. package/lib/stores/settingInfo.d.ts +0 -8
  98. package/lib/stores/userInfo.d.ts +0 -25
  99. package/lib/typings/data.d.ts +0 -80
  100. package/lib/typings/form.d.ts +0 -206
  101. package/lib/typings/menu.d.ts +0 -7
  102. package/lib/typings/option.d.ts +0 -209
  103. package/lib/typings/page.d.ts +0 -70
  104. package/lib/typings/table.d.ts +0 -181
  105. package/lib/typings/tools.d.ts +0 -130
  106. package/lib/typings/tree.d.ts +0 -72
  107. package/lib/typings/upload.d.ts +0 -161
  108. package/lib/typings/urls.d.ts +0 -69
  109. package/lib/utils/cache.d.ts +0 -23
  110. package/lib/utils/data.d.ts +0 -6
  111. package/lib/utils/download.d.ts +0 -6
  112. package/lib/utils/eventbus.d.ts +0 -16
  113. package/lib/utils/excel-preview.d.ts +0 -24
  114. package/lib/utils/excel-view.d.ts +0 -25
  115. package/lib/utils/export-table.d.ts +0 -12
  116. package/lib/utils/file-upload.d.ts +0 -17
  117. package/lib/utils/form-csv.d.ts +0 -18
  118. package/lib/utils/form-excel.d.ts +0 -36
  119. package/lib/utils/form-validate.d.ts +0 -29
  120. package/lib/utils/form.d.ts +0 -9
  121. package/lib/utils/icon-loader.d.ts +0 -125
  122. package/lib/utils/isEmpty.d.ts +0 -1
  123. package/lib/utils/main-openapis.d.ts +0 -8
  124. package/lib/utils/menu.d.ts +0 -6
  125. package/lib/utils/options.d.ts +0 -7
  126. package/lib/utils/page.d.ts +0 -30
  127. package/lib/utils/table.d.ts +0 -21
  128. package/lib/utils/tools.d.ts +0 -18
  129. package/lib/utils/tree.d.ts +0 -3
  130. package/lib/vite-env.d.ts +0 -8
  131. package/lib/webui.css +0 -1
  132. package/lib/webui.es.js +0 -2345
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyfox2000/webui",
3
- "version": "1.3.15",
3
+ "version": "1.3.17",
4
4
  "description": "后台前端通用组件定义",
5
5
  "type": "module",
6
6
  "keywords": [],
@@ -40,8 +40,20 @@ const props = defineProps({
40
40
  type: String as PropType<string>,
41
41
  required: false,
42
42
  },
43
+ /**
44
+ * 清空时设置的值
45
+ * - false,则清空时设置为 null
46
+ * - true,则清空时设置为 undefined
47
+ */
48
+ undefValue: {
49
+ type: Boolean,
50
+ default: false,
51
+ },
43
52
  });
44
53
 
54
+ // 如果初始value为undefined,自动设置undefValue为true
55
+ const undefVal = props.value === undefined ? true : props.undefValue;
56
+
45
57
  const inputFactory = useInputFactory();
46
58
  const { editorCtrl, errInfo, labelText } = inputFactory;
47
59
 
@@ -63,11 +75,10 @@ const url = ref<IUrlInfo>({
63
75
  loadingText: false,
64
76
  });
65
77
 
66
- const defaultVal = ref(props.value);
67
78
  const placeholder = ref(attrs.placeholder);
68
79
 
69
80
  /// 避免类型错误
70
- const innerValue = ref<string | number | string[] | number[] | undefined>(optionCtrl?.selected.value || undefined);
81
+ const innerValue = ref<SelectValue>(optionCtrl?.selected.value as SelectValue);
71
82
  const emit = defineEmits(['change', 'update:value', 'update:label', 'update:labels']);
72
83
  inputFactory.inputEmit = emit;
73
84
 
@@ -96,13 +107,13 @@ const updateInnerValue = (newVal: OptionItemProps[]) => {
96
107
  const item = newVal[i];
97
108
 
98
109
  if (item.disabled === undefined || item.disabled === false) {
99
- innerValue.value = item.value;
110
+ innerValue.value = item.value as SelectValue;
100
111
  break;
101
112
  }
102
113
  }
103
114
  } else if (newVal.length > 0) {
104
115
  // 当选项加载完成后,设置实际的 value 值
105
- innerValue.value = props.value === null ? undefined : props.value;
116
+ innerValue.value = (props.value === null ? undefined : props.value) as SelectValue;
106
117
  }
107
118
  if (newVal.length > 0 && innerValue.value !== undefined) onChanged(innerValue.value);
108
119
  };
@@ -119,7 +130,7 @@ if (optionCtrl) {
119
130
  watch(
120
131
  () => optionCtrl.selected.value,
121
132
  (newVal) => {
122
- innerValue.value = newVal;
133
+ innerValue.value = newVal as SelectValue;
123
134
  },
124
135
  );
125
136
  }
@@ -140,21 +151,23 @@ watch(
140
151
  { immediate: true },
141
152
  );
142
153
 
154
+ // 监听值变化
155
+ watch(
156
+ () => props.value,
157
+ (newVal) => {
158
+ innerValue.value = newVal as SelectValue;
159
+ },
160
+ { immediate: true },
161
+ );
143
162
  watch(
144
163
  () => innerValue.value,
145
164
  (newVal) => {
165
+ // 保存原始值用于update:value事件
166
+ const emitValue = newVal === undefined ? (undefVal ? undefined : null) : newVal;
146
167
  if (optionCtrl) {
147
- optionCtrl.selected.value = newVal;
168
+ optionCtrl.selected.value = emitValue;
148
169
  }
149
- // 保存原始值用于update:value事件
150
- const emitValue = newVal === undefined ? null : newVal;
151
170
 
152
- if (attrs.mode === 'multiple') {
153
- if (isEmpty(newVal) && isEmpty(defaultVal.value)) {
154
- emit('update:value', defaultVal.value);
155
- return;
156
- }
157
- }
158
171
  emit('update:value', emitValue);
159
172
  },
160
173
  );
@@ -0,0 +1,44 @@
1
+ <script lang="ts" setup>
2
+ import { onMounted } from 'vue';
3
+ import { Layout, LayoutSider } from 'ant-design-vue';
4
+ import Tooltip from '../../common/tooltip/index.vue';
5
+ import Icon from '../../common/icon/index.vue';
6
+ import Menu from '../menu/index.vue';
7
+ import Header from '../header/index.vue';
8
+ import MenuTabs from '../menu/menuTabs.vue';
9
+ import AppIcon from '../../common/icon/appicon.vue';
10
+ import { useAppInfo, usePageInfo, useSettingInfo } from '@/index';
11
+ import message from 'vue-m-message';
12
+
13
+ const props = defineProps<{ routes: any }>();
14
+
15
+ const appInfoStore = useAppInfo();
16
+ const settingInfoStore = useSettingInfo();
17
+ const pageInfoStore = usePageInfo();
18
+
19
+ onMounted(() => {
20
+ message.closeAll();
21
+ });
22
+ </script>
23
+ <template>
24
+ <Layout class="h-screen">
25
+ <LayoutSider class="overflow-auto h-screen left-0 top-0 bottom-0"
26
+ v-model:collapsed="settingInfoStore.menuCollapse" collapsible v-if="!settingInfoStore.fullscreen">
27
+ <div
28
+ class="h-[40px] max-h-[40px] bg-[rgba(240,240,240,0.2)] flex flex-nowrap items-center justify-center text-white font-bold text-lg overflow-hidden text-ellipsis">
29
+ <Tooltip :title="settingInfoStore.menuCollapse ? appInfoStore.appInfo.Name : ''" placement="right">
30
+ <Icon v-if="appInfoStore.appInfo.Icon?.startsWith('sym-')" :icon="appInfoStore.appInfo.Icon"
31
+ fontsize="30px" size="26px" />
32
+ <AppIcon v-else :icon="appInfoStore.appInfo.Icon" class="mx-1" />
33
+ </Tooltip>
34
+ <span v-if="!settingInfoStore.menuCollapse" class="ml-[10px]">{{ appInfoStore.appInfo.Name }}</span>
35
+ </div>
36
+ <Menu :routes="props.routes"></Menu>
37
+ </LayoutSider>
38
+ <Layout class="overflow-y-auto block">
39
+ <Header v-if="!settingInfoStore.fullscreen"></Header>
40
+ <MenuTabs v-if="pageInfoStore.TabEnabled"></MenuTabs>
41
+ <slot></slot>
42
+ </Layout>
43
+ </Layout>
44
+ </template>
@@ -1,20 +1,13 @@
1
1
  <script lang="ts" setup>
2
2
  import { onMounted, ref, watch } from 'vue';
3
- import { Layout, LayoutSider } from 'ant-design-vue';
4
- import Tooltip from '../../common/tooltip/index.vue';
5
- import Icon from '../../common/icon/index.vue';
6
- import Menu from '../menu/index.vue';
7
- import Header from '../header/index.vue';
8
- import MenuTabs from '../menu/menuTabs.vue';
9
- import AppIcon from '../../common/icon/appicon.vue';
10
- import { useAppInfo, usePageInfo, useSettingInfo } from '@/index';
3
+ import BaseLayout from './baseLayout.vue';
4
+ import { useAppInfo, useSettingInfo } from '@/index';
11
5
  import message from 'vue-m-message';
12
6
 
13
7
  const props = defineProps<{ routes: any }>();
14
8
 
15
9
  const appInfoStore = useAppInfo();
16
10
  const settingInfoStore = useSettingInfo();
17
- const pageInfoStore = usePageInfo();
18
11
 
19
12
  const bodyClass = ref('h-[calc(100vh-80px)]');
20
13
  watch(
@@ -29,39 +22,13 @@ onMounted(() => {
29
22
  });
30
23
  </script>
31
24
  <template>
32
- <Layout class="h-screen">
33
- <LayoutSider
34
- class="overflow-auto h-screen left-0 top-0 bottom-0"
35
- v-model:collapsed="settingInfoStore.menuCollapse"
36
- collapsible
37
- v-if="!settingInfoStore.fullscreen"
38
- >
39
- <div
40
- class="h-[40px] max-h-[40px] bg-[rgba(240,240,240,0.2)] flex flex-nowrap items-center justify-center text-white font-bold text-lg overflow-hidden text-ellipsis"
41
- >
42
- <Tooltip :title="settingInfoStore.menuCollapse ? appInfoStore.appInfo.Name : ''" placement="right">
43
- <Icon
44
- v-if="appInfoStore.appInfo.Icon?.startsWith('sym-')"
45
- :icon="appInfoStore.appInfo.Icon"
46
- fontsize="30px"
47
- size="26px"
48
- />
49
- <AppIcon v-else :icon="appInfoStore.appInfo.Icon" class="mx-1" />
50
- </Tooltip>
51
- <span v-if="!settingInfoStore.menuCollapse" class="ml-[10px]">{{ appInfoStore.appInfo.Name }}</span>
52
- </div>
53
- <Menu :routes="props.routes"></Menu>
54
- </LayoutSider>
55
- <Layout class="overflow-y-auto block">
56
- <Header v-if="!settingInfoStore.fullscreen"></Header>
57
- <MenuTabs v-if="pageInfoStore.TabEnabled"></MenuTabs>
58
- <div class="relative overflow-y-auto" :class="bodyClass">
59
- <router-view v-slot="{ Component, route }">
60
- <keep-alive :include="appInfoStore.CachedComponents" :exclude="appInfoStore.ExcludeComponents">
61
- <component :is="appInfoStore.cacheComponent(Component, route)" />
62
- </keep-alive>
63
- </router-view>
64
- </div>
65
- </Layout>
66
- </Layout>
25
+ <BaseLayout :routes="props.routes">
26
+ <div class="relative overflow-y-auto" :class="bodyClass">
27
+ <router-view v-slot="{ Component, route }">
28
+ <keep-alive :include="appInfoStore.CachedComponents" :exclude="appInfoStore.ExcludeComponents">
29
+ <component :is="appInfoStore.cacheComponent(Component, route)" />
30
+ </keep-alive>
31
+ </router-view>
32
+ </div>
33
+ </BaseLayout>
67
34
  </template>
@@ -0,0 +1,35 @@
1
+ <script lang="ts" setup>
2
+ import { onMounted, ref, watch } from 'vue';
3
+ import BaseLayout from './baseLayout.vue';
4
+ import { useAppInfo, useSettingInfo } from '@/index';
5
+ import message from 'vue-m-message';
6
+
7
+ const props = defineProps<{ routes: any }>();
8
+
9
+ const appInfoStore = useAppInfo();
10
+ const settingInfoStore = useSettingInfo();
11
+
12
+ const bodyClass = ref('h-[calc(100vh-82px)]');
13
+ watch(
14
+ () => settingInfoStore.fullscreen,
15
+ (newVal) => {
16
+ bodyClass.value = newVal ? 'h-[calc(100vh-40px)]' : 'h-[calc(100vh-80px)]';
17
+ },
18
+ );
19
+
20
+ onMounted(() => {
21
+ message.closeAll();
22
+ });
23
+ </script>
24
+ <template>
25
+ <BaseLayout :routes="props.routes">
26
+ <!-- 没有滚动条 -->
27
+ <div class="relative" :class="bodyClass">
28
+ <router-view v-slot="{ Component, route }">
29
+ <keep-alive :include="appInfoStore.CachedComponents" :exclude="appInfoStore.ExcludeComponents">
30
+ <component :is="appInfoStore.cacheComponent(Component, route)" />
31
+ </keep-alive>
32
+ </router-view>
33
+ </div>
34
+ </BaseLayout>
35
+ </template>
@@ -190,11 +190,11 @@ export type OptionControl = OptionControlOption & {
190
190
  /**
191
191
  * 基础选中数据
192
192
  */
193
- selected: Ref<string | number | string[] | number[] | undefined>;
193
+ selected: Ref<RawValue | RawValue[] | undefined | null>;
194
194
  /**
195
195
  * 选中数据
196
196
  */
197
- selectedOptions: Ref<OptionItemProps[]>;
197
+ selectedOptions: Ref<OptionItemProps | OptionItemProps[] | undefined | null>;
198
198
  /**
199
199
  * 查询接口
200
200
  * - 优先使用
package/src/utils/data.ts CHANGED
@@ -2,6 +2,7 @@ import { AnyControl, ExecuteOptions, PostOptions } from '@/typings/data.d';
2
2
  import { ApiResponse, httpPost, IUrlInfo, ResStatus } from '@skyfox2000/fapi';
3
3
  import message from 'vue-m-message';
4
4
  import { isEmpty } from './isEmpty';
5
+ import { combineParams } from '@skyfox2000/microbase';
5
6
 
6
7
  /**
7
8
  * 合并URL信息
@@ -43,7 +44,10 @@ const doPost = <T>(control: AnyControl, options: PostOptions<T>): Promise<ApiRes
43
44
  if (url.authorize === undefined) url.authorize = pageCtrl.authorize;
44
45
 
45
46
  // 合并请求参数
46
- let newParams = JSON.parse(JSON.stringify(options.params));
47
+ let newParams = combineParams(
48
+ JSON.parse(JSON.stringify(url.params ?? {})),
49
+ JSON.parse(JSON.stringify(options.params ?? {})),
50
+ );
47
51
 
48
52
  // 处理特殊参数
49
53
  if (options.processParams) {
@@ -335,7 +335,7 @@ export const outFormDataFields = (
335
335
  export const onOptionChanged = (
336
336
  optionCtrl: OptionControl,
337
337
  props: OptionProps,
338
- values: undefined | SelectValue,
338
+ values?: SelectValue,
339
339
  ): OptionItemProps | OptionItemProps[] | undefined => {
340
340
  const inputFactory = optionCtrl.inputFactory?.value;
341
341
  // 如果存在验证错误,重新检测
@@ -346,7 +346,7 @@ export const onOptionChanged = (
346
346
 
347
347
  // 获取选中的选项对象或对象数组
348
348
  const selectedValues = getSelectedValues(values, optionCtrl.options.value);
349
- optionCtrl.selectedOptions.value = selectedValues as OptionItemProps[];
349
+ optionCtrl.selectedOptions.value = selectedValues;
350
350
 
351
351
  // 如果配置了 formData 和 outFields,将选中的其它属性值映射到 formData 上
352
352
  if (props.formData && props.outFields) {
package/vite.config.ts CHANGED
@@ -62,6 +62,7 @@ export default defineConfig(({ mode }: ConfigEnv) => {
62
62
  Error403: 'src/components/error/error403.vue',
63
63
  Error404: 'src/components/error/error404.vue',
64
64
  BasicLayout: 'src/components/layout/page/basicLayout.vue',
65
+ MenuLayout: 'src/components/layout/page/menuLayout.vue',
65
66
  },
66
67
  fileName: (format, entryName) => {
67
68
  if (entryName === 'index') return `webui.${format}.js`;
@@ -1 +0,0 @@
1
- export {}
@@ -1 +0,0 @@
1
- export {}
package/lib/Error403.d.ts DELETED
@@ -1 +0,0 @@
1
- export {}
package/lib/Error404.d.ts DELETED
@@ -1 +0,0 @@
1
- export {}
@@ -1 +0,0 @@
1
- export {}
@@ -1 +0,0 @@
1
- export {}
@@ -1,9 +0,0 @@
1
- const s = (t, r) => {
2
- const o = t.__vccOpts || t;
3
- for (const [c, e] of r)
4
- o[c] = e;
5
- return o;
6
- };
7
- export {
8
- s as _
9
- };
@@ -1,204 +0,0 @@
1
- var m = Object.defineProperty;
2
- var E = (e, r, o) => r in e ? m(e, r, { enumerable: !0, configurable: !0, writable: !0, value: o }) : e[r] = o;
3
- var d = (e, r, o) => E(e, typeof r != "symbol" ? r + "" : r, o);
4
- import { hostUrl as v } from "@skyfox2000/fapi";
5
- import { ae as S, ad as w, u as g } from "./uploadList-BNkHE3fR.js";
6
- import { mainAppApis as a } from "@skyfox2000/microbase";
7
- import y from "dayjs";
8
- import p from "vue-m-message";
9
- var i = /* @__PURE__ */ ((e) => (e.Pending = "pending", e.Uploading = "uploading", e.Success = "success", e.Error = "error", e.Online = "online", e.Offline = "offline", e))(i || {});
10
- const U = () => a.value ? a.value.getHostInfo() : S().hostInfo, x = () => a.value && a.value.getAppInfo ? a.value.getAppInfo() : w().appInfo, L = (e) => a.value && a.value.userLogin ? a.value.userLogin(e) : g().login(e, !0), M = () => a.value && a.value.userLogout ? a.value.userLogout() : g().logout(), b = () => a.value && a.value.getToken ? a.value.getToken() : g().getToken(), N = () => a.value && a.value.getUserInfo ? a.value.getUserInfo() : g().getUserInfo();
11
- class z {
12
- /**
13
- * 连接路径参数,已判断 undefined 或 null 值
14
- * @param args 路径参数数组
15
- * @returns 连接后的路径字符串
16
- */
17
- static join(...r) {
18
- return r.filter((u) => u != null).join("/").replace(/[\/]+/, "/");
19
- }
20
- }
21
- class C {
22
- /**
23
- * AsyncUploader 构造函数
24
- * @param urlInfo 文件上传的 API 配置(IUrlInfo 对象)
25
- * @param maxConcurrent 最大允许并发上传的文件数量
26
- */
27
- constructor(r, o = 3) {
28
- /**
29
- * 设置 API 端点和最大并发数,所有上传文件通过该类控制
30
- */
31
- d(this, "urlInfo");
32
- /**
33
- * 最大并发上传数
34
- */
35
- d(this, "maxConcurrent");
36
- /**
37
- * 控制上传任务的中断信号
38
- */
39
- d(this, "abortController");
40
- this.urlInfo = r, this.maxConcurrent = o;
41
- }
42
- /**
43
- * 执行上传
44
- * @param fileList 文件列表
45
- * @param loading 加载状态
46
- * @param continueOnError 错误时是否继续上传
47
- * @param onComplete 上传完成回调
48
- * @param onProgress 上传进度回调
49
- * @returns 上传结果
50
- */
51
- async doUpload(r, o, c, u, n) {
52
- if (r.length) {
53
- if (r.length === 0) {
54
- p.warning("请选择上传的文件!");
55
- return;
56
- }
57
- o.value = !0, await this.uploadFiles(r, n, (f) => {
58
- let t = !1, h = 0;
59
- for (const s of f)
60
- s.status === i.Error && h++;
61
- h ? h < f.length ? c ? (p.error("上传结束,部分文件上传失败!"), p.warning("保存上传成功的文件!"), t = !0) : p.error("上传结束,部分文件上传失败,取消保存!") : p.error("上传结束,所有文件上传失败!") : (p.success("全部文件上传成功!"), t = !0), o.value = !1, u == null || u(t, f);
62
- });
63
- }
64
- }
65
- /**
66
- * 上传多个文件,控制并发数量
67
- * @param files 文件列表(File[] 或 FileList)
68
- * @param onProgress 上传进度回调
69
- * @param onComplete 上传完成回调
70
- */
71
- async uploadFiles(r, o, c) {
72
- if (!r.length) return;
73
- const u = Math.min(this.maxConcurrent, r.length), n = [];
74
- for (const t of r)
75
- switch (t.status) {
76
- case i.Success:
77
- case i.Online:
78
- case i.Offline:
79
- break;
80
- default:
81
- t.status = i.Pending, n.push(t);
82
- break;
83
- }
84
- const f = [];
85
- this.abortController = new AbortController();
86
- try {
87
- for (; f.length < u && n.length > 0; ) {
88
- const t = n.shift();
89
- if (!t) break;
90
- f.push(this.handleFileStatus(t, f, n, o));
91
- }
92
- await Promise.all(f);
93
- } catch (t) {
94
- r.forEach((h) => {
95
- h.status = i.Error, h.error = t instanceof Error ? t : new Error("上传失败"), o == null || o(h);
96
- });
97
- } finally {
98
- c == null || c(r);
99
- }
100
- }
101
- /**
102
- * 处理单个文件的上传逻辑
103
- * @param file 当前上传的文件
104
- * @param activeUploads 当前正在上传的文件列表
105
- * @param pendingFiles 等待上传的文件列表
106
- * @param onProgress 上传进度回调
107
- */
108
- async handleFileStatus(r, o, c, u) {
109
- try {
110
- await this.uploadFile(r, this.abortController.signal, (n) => {
111
- r.percent = n, u == null || u(r);
112
- });
113
- } catch (n) {
114
- r.error = n instanceof Error ? n : new Error("上传失败");
115
- } finally {
116
- if (c.length > 0) {
117
- const n = c.shift();
118
- n && o.push(this.handleFileStatus(n, o, c, u));
119
- }
120
- }
121
- }
122
- /**
123
- * 使用 XMLHttpRequest 上传文件
124
- * @param file 文件对象
125
- * @param signal 中断信号
126
- * @param onProgress 上传进度回调
127
- */
128
- async uploadFile(r, o, c) {
129
- return r.status = i.Uploading, new Promise((u, n) => {
130
- const f = new FormData();
131
- if (f.append("file", r.originFileObj), r.params)
132
- for (const s in r.params)
133
- f.append(s, r.params[s]);
134
- const t = new XMLHttpRequest(), h = v(this.urlInfo);
135
- if (h === !1) return Promise.resolve(r);
136
- if (t.open("POST", h, !0), this.urlInfo.header && typeof this.urlInfo.header == "object" && Object.entries(this.urlInfo.header).forEach(([s, l]) => {
137
- t.setRequestHeader(s, l);
138
- }), this.urlInfo.authorize) {
139
- const s = b();
140
- if (!s) {
141
- n(new Error("未授权或授权过期"));
142
- return;
143
- }
144
- t.setRequestHeader("Authorization", "Bearer " + s);
145
- }
146
- t.upload.addEventListener("progress", (s) => {
147
- if (s.lengthComputable && s.total > 0) {
148
- const l = Math.round(s.loaded / s.total * 100);
149
- c(l);
150
- }
151
- }), t.addEventListener("load", () => {
152
- if (t.status >= 200 && t.status < 300) {
153
- const s = t.getResponseHeader("Content-Type");
154
- if (!s || !s.includes("application/json")) {
155
- n(new Error("返回的结果不是 JSON 格式"));
156
- return;
157
- }
158
- try {
159
- const l = JSON.parse(t.response);
160
- if (l.status === "success")
161
- l.data && (r.minioFile = {
162
- ETag: l.data.ETag,
163
- Bucket: l.data.Bucket,
164
- FileName: r.fileName,
165
- Key: l.data.Key,
166
- Size: l.data.Size,
167
- Type: r.type,
168
- UpdateTime: y().format("YYYY-MM-DD HH:mm:ss"),
169
- Status: i.Success
170
- }), r.status = i.Success, u(r);
171
- else {
172
- const I = l.msg;
173
- r.status = i.Error, n(new Error(I));
174
- }
175
- } catch (l) {
176
- r.status = i.Error, n(new Error("无法解析返回的 JSON 数据: " + l));
177
- }
178
- } else
179
- r.status = i.Error, n(new Error(`上传失败,状态码:${t.status}`));
180
- }), t.addEventListener("error", () => {
181
- r.status = i.Error, n(new Error("上传失败,网络异常"));
182
- }), t.send(f), o.addEventListener("abort", () => {
183
- t.abort(), n(new Error("上传已取消"));
184
- });
185
- });
186
- }
187
- /**
188
- * 取消当前所有的上传任务
189
- */
190
- cancelUpload() {
191
- this.abortController && this.abortController.abort();
192
- }
193
- }
194
- export {
195
- C as A,
196
- i as U,
197
- x as a,
198
- M as b,
199
- b as c,
200
- N as d,
201
- U as g,
202
- z as p,
203
- L as u
204
- };