@skyfox2000/webui 1.0.13 → 1.2.0

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 (162) hide show
  1. package/lib/assets/modules/file-upload-CBUcsUnR.js +170 -0
  2. package/lib/assets/modules/form-validate-CgX7aR7T.js +297 -0
  3. package/lib/assets/modules/index-Civhd8xG.js +112 -0
  4. package/lib/assets/modules/index-DQMdt51R.js +726 -0
  5. package/lib/assets/modules/{index-BEWJ_qAH.js → index-DmWrkTXX.js} +1 -1
  6. package/lib/assets/modules/{menuTabs-BXdbFZor.js → menuTabs-BRYvFWA-.js} +131 -121
  7. package/lib/assets/modules/settingInfo-BZakNKIN.js +999 -0
  8. package/lib/assets/modules/uploadList-B7XoxGOh.js +278 -0
  9. package/lib/components/common/icon/index.vue.d.ts +1 -1
  10. package/lib/components/content/dialog/index.vue.d.ts +1 -1
  11. package/lib/components/content/drawer/index.vue.d.ts +1 -1
  12. package/lib/components/content/form/index.vue.d.ts +1 -1
  13. package/lib/components/content/search/index.vue.d.ts +1 -1
  14. package/lib/components/content/table/index.vue.d.ts +1 -1
  15. package/lib/components/content/table/tableOperate.vue.d.ts +1 -1
  16. package/lib/components/content/toolbar/icontool.vue.d.ts +1 -1
  17. package/lib/components/content/toolbar/index.vue.d.ts +1 -1
  18. package/lib/components/content/tree/index.vue.d.ts +1 -1
  19. package/lib/components/form/transfer/transferTable.vue.d.ts +1 -1
  20. package/lib/components/form/treeSelect/index.vue.d.ts +1 -1
  21. package/lib/components/form/upload/uploadList.vue.d.ts +1 -1
  22. package/lib/const/options.d.ts +32 -0
  23. package/lib/directives/enter-submit.d.ts +4 -0
  24. package/lib/directives/index.d.ts +2 -0
  25. package/lib/directives/permission.d.ts +5 -0
  26. package/lib/es/AceEditor/index.js +9 -8
  27. package/lib/es/BasicLayout/index.js +28 -24
  28. package/lib/es/Error403/index.js +15 -10
  29. package/lib/es/Error404/index.js +15 -10
  30. package/lib/es/ExcelForm/index.js +380 -175
  31. package/lib/es/UploadForm/index.js +23 -20
  32. package/lib/index.d.ts +42 -2
  33. package/lib/router/index.d.ts +16 -0
  34. package/lib/stores/appInfo.d.ts +34 -0
  35. package/lib/stores/hostInfo.d.ts +9 -0
  36. package/lib/stores/pageInfo.d.ts +18 -0
  37. package/lib/stores/pinia.d.ts +3 -0
  38. package/lib/stores/settingInfo.d.ts +8 -0
  39. package/lib/stores/userInfo.d.ts +21 -0
  40. package/lib/typings/data.d.ts +80 -0
  41. package/lib/typings/form.d.ts +171 -0
  42. package/lib/typings/menu.d.ts +7 -0
  43. package/lib/typings/option.d.ts +175 -0
  44. package/lib/typings/page.d.ts +69 -0
  45. package/lib/typings/table.d.ts +181 -0
  46. package/lib/typings/tools.d.ts +130 -0
  47. package/lib/typings/tree.d.ts +72 -0
  48. package/lib/typings/upload.d.ts +161 -0
  49. package/lib/typings/urls.d.ts +69 -0
  50. package/lib/utils/cache.d.ts +23 -0
  51. package/lib/utils/data.d.ts +6 -0
  52. package/lib/utils/download.d.ts +4 -0
  53. package/lib/utils/eventbus.d.ts +16 -0
  54. package/lib/utils/export-table.d.ts +12 -0
  55. package/lib/utils/file-upload.d.ts +15 -0
  56. package/lib/utils/form-excel.d.ts +30 -0
  57. package/lib/utils/form-validate.d.ts +29 -0
  58. package/lib/utils/form.d.ts +9 -0
  59. package/lib/utils/icon-loader.d.ts +125 -0
  60. package/lib/utils/isEmpty.d.ts +1 -0
  61. package/lib/utils/main-openapis.d.ts +9 -0
  62. package/lib/utils/menu.d.ts +6 -0
  63. package/lib/utils/options.d.ts +10 -0
  64. package/lib/utils/page.d.ts +25 -0
  65. package/lib/utils/table.d.ts +21 -0
  66. package/lib/utils/tools.d.ts +18 -0
  67. package/lib/utils/tree.d.ts +3 -0
  68. package/lib/vite-env.d.ts +8 -0
  69. package/lib/webui.css +1 -1
  70. package/lib/webui.es.js +1020 -854
  71. package/package.json +7 -6
  72. package/src/components/common/icon/appicon.vue +1 -1
  73. package/src/components/common/icon/fullscreen.vue +2 -1
  74. package/src/components/common/icon/index.vue +1 -1
  75. package/src/components/common/icon/layoutIcon.vue +1 -1
  76. package/src/components/common/icon/projectIcon.vue +1 -1
  77. package/src/components/common/icon/toolIcon.vue +1 -1
  78. package/src/components/content/dialog/excelForm.vue +2 -2
  79. package/src/components/content/dialog/index.vue +1 -1
  80. package/src/components/content/dialog/uploadForm.vue +7 -6
  81. package/src/components/content/drawer/index.vue +43 -18
  82. package/src/components/content/form/formItem.vue +1 -1
  83. package/src/components/content/form/index.vue +1 -1
  84. package/src/components/content/search/index.vue +1 -1
  85. package/src/components/content/search/searchItem.vue +1 -1
  86. package/src/components/content/table/index.vue +8 -5
  87. package/src/components/content/table/tableOperate.vue +8 -4
  88. package/src/components/content/toolbar/icontool.vue +2 -2
  89. package/src/components/content/toolbar/index.vue +9 -5
  90. package/src/components/content/tree/index.vue +1 -1
  91. package/src/components/error/error403.vue +2 -2
  92. package/src/components/error/error404.vue +2 -2
  93. package/src/components/form/autoComplete/index.vue +1 -1
  94. package/src/components/form/cascader/index.vue +1 -2
  95. package/src/components/form/checkbox/index.vue +11 -5
  96. package/src/components/form/datePicker/index.vue +1 -1
  97. package/src/components/form/input/index.vue +1 -1
  98. package/src/components/form/input/inputNumber.vue +1 -1
  99. package/src/components/form/input/inputPassword.vue +1 -1
  100. package/src/components/form/radio/index.vue +1 -1
  101. package/src/components/form/radio/radioStatus.vue +1 -1
  102. package/src/components/form/rangePicker/index.vue +1 -1
  103. package/src/components/form/select/index.vue +1 -1
  104. package/src/components/form/switch/index.vue +7 -3
  105. package/src/components/form/textarea/index.vue +1 -1
  106. package/src/components/form/transfer/index.vue +1 -1
  107. package/src/components/form/transfer/transferTable.vue +42 -22
  108. package/src/components/form/treeSelect/index.vue +2 -3
  109. package/src/components/form/upload/uploadList.vue +1 -1
  110. package/src/components/layout/breadcrumb/index.vue +1 -1
  111. package/src/components/layout/header/headerExits.vue +1 -1
  112. package/src/components/layout/header/index.vue +1 -1
  113. package/src/components/layout/header/user.vue +2 -1
  114. package/src/components/layout/menu/index.vue +9 -3
  115. package/src/components/layout/menu/menuTabs.vue +10 -12
  116. package/src/components/layout/page/basicLayout.vue +1 -1
  117. package/src/const/options.ts +114 -0
  118. package/src/directives/enter-submit.ts +13 -0
  119. package/src/directives/index.ts +26 -0
  120. package/src/directives/permission.ts +144 -0
  121. package/src/index.ts +201 -0
  122. package/src/router/index.ts +196 -0
  123. package/src/stores/appInfo.ts +471 -0
  124. package/src/stores/hostInfo.ts +117 -0
  125. package/src/stores/pageInfo.ts +131 -0
  126. package/src/stores/pinia.ts +10 -0
  127. package/src/stores/settingInfo.ts +53 -0
  128. package/src/stores/userInfo.ts +392 -0
  129. package/src/typings/data.d.ts +81 -0
  130. package/src/typings/form.d.ts +172 -0
  131. package/src/typings/menu.d.ts +7 -0
  132. package/src/typings/option.d.ts +177 -0
  133. package/src/typings/page.d.ts +70 -0
  134. package/src/typings/table.d.ts +182 -0
  135. package/src/typings/tools.d.ts +131 -0
  136. package/src/typings/tree.d.ts +73 -0
  137. package/src/typings/upload.d.ts +162 -0
  138. package/src/typings/urls.d.ts +70 -0
  139. package/src/utils/cache.ts +175 -0
  140. package/src/utils/data.ts +189 -0
  141. package/src/utils/download.ts +80 -0
  142. package/src/utils/eventbus.ts +78 -0
  143. package/src/utils/export-table.ts +155 -0
  144. package/src/utils/file-upload.ts +304 -0
  145. package/src/utils/form-excel.ts +523 -0
  146. package/src/utils/form-validate.ts +368 -0
  147. package/src/utils/form.ts +188 -0
  148. package/src/utils/icon-loader.ts +412 -0
  149. package/src/utils/isEmpty.ts +18 -0
  150. package/src/utils/main-openapis.ts +72 -0
  151. package/src/utils/menu.ts +89 -0
  152. package/src/utils/options.ts +324 -0
  153. package/src/utils/page.ts +262 -0
  154. package/src/utils/table.ts +274 -0
  155. package/src/utils/tools.ts +362 -0
  156. package/src/utils/tree.ts +28 -0
  157. package/tsconfig.json +1 -8
  158. package/vite.config.ts +7 -4
  159. package/lib/assets/modules/index-BahGnrAq.js +0 -415
  160. package/lib/assets/modules/index-BoKIa2sr.js +0 -109
  161. package/lib/assets/modules/index-D47Ci-T3.js +0 -107
  162. package/lib/assets/modules/uploadList-Dzlg47V0.js +0 -182
@@ -0,0 +1,274 @@
1
+ import { GridControl } from '@/typings/table.d';
2
+ import { ExecuteOptions } from '@/typings/data.d';
3
+ import { RowRecord } from '@/typings/tools.d';
4
+ import { AnyData, AnyJsonData, ApiResponse, FindResult, IUrlInfo, ReqParams, ResStatus } from '@skyfox2000/fapi';
5
+ import { doQuery, doSave, doDelete } from './data';
6
+ import { setFormData } from './form';
7
+ import { useUserInfo } from '@/stores/userInfo';
8
+ import AppRouter from '@/router';
9
+ import { combineParams } from '@skyfox2000/microbase';
10
+
11
+ interface TableColumn {
12
+ role?: string;
13
+ permit?: string;
14
+ visible?: boolean | (() => boolean);
15
+ [key: string]: any;
16
+ }
17
+
18
+ /**
19
+ * 过滤表格列
20
+ * - 角色/权限控制的列,如无权限将不显示
21
+ * - 受function控制的列,如返回false将不显示
22
+ * @param columns 表格列
23
+ * @param toolCtl 是否工具栏控制
24
+ * @returns 过滤后的表格列
25
+ */
26
+ export const filterColumns = (columns: TableColumn[], toolCtl?: boolean) => {
27
+ const userInfoStore = useUserInfo();
28
+
29
+ return columns.filter((column) => {
30
+ // 角色权限检查
31
+ if (column.role && !userInfoStore.hasRole(column.role)) {
32
+ return false;
33
+ }
34
+
35
+ // 操作权限检查
36
+ if (column.permit && !userInfoStore.hasPermit(AppRouter.currentRoute.value.path, column.permit)) {
37
+ return false;
38
+ }
39
+
40
+ if (!toolCtl) {
41
+ // 可见性检查
42
+ if (column.visible === false) {
43
+ return false;
44
+ }
45
+
46
+ if (typeof column.visible === 'function') {
47
+ return column.visible();
48
+ }
49
+ }
50
+
51
+ return true;
52
+ });
53
+ };
54
+
55
+ /**
56
+ * 比较表头
57
+ * - 对比新旧表头
58
+ * - 如果新表头中存在旧表头中没有的列,则将旧表头中对应的列删除
59
+ * - 如果新表头中存在旧表头中有的列,则将旧表头中对应的列更新
60
+ * - 如果新表头中不存在旧表头中的列,则将新表头中对应的列添加
61
+ * - 返回合并后的表头
62
+ */
63
+ export const mergeColumns = (newColumns: TableColumn[], oldColumns?: TableColumn[]) => {
64
+ const mergeColumns = oldColumns?.filter((oldColumn) => {
65
+ const newColumn = newColumns.find(
66
+ (newColumn) =>
67
+ newColumn.dataIndex === oldColumn.dataIndex ||
68
+ newColumn.key === oldColumn.key ||
69
+ newColumn.title === oldColumn.title,
70
+ );
71
+ if (newColumn) {
72
+ return { ...oldColumn, ...newColumn };
73
+ }
74
+ return false;
75
+ });
76
+
77
+ return [...(mergeColumns || []), ...newColumns.filter((newColumn) => !mergeColumns?.includes(newColumn))];
78
+ };
79
+
80
+ /**
81
+ * 发起表格数据查询
82
+ * @param gridCtrl 表格控制对象
83
+ * @returns
84
+ */
85
+ export const gridQueryList = <T>(gridCtrl: GridControl<T>): Promise<T[]> => {
86
+ gridCtrl.remotePage = false;
87
+ return gridQueryFind(gridCtrl).then((result) => {
88
+ return result.rows as T[];
89
+ });
90
+ };
91
+
92
+ /**
93
+ * 发起表格数据查询
94
+ * @param gridCtrl 表格控制对象
95
+ * @returns
96
+ */
97
+ export const gridQueryFind = <T>(gridCtrl: GridControl<T>): Promise<FindResult> => {
98
+ // 设置查询参数
99
+ if (!gridCtrl.gridQuery) gridCtrl.gridQuery = {};
100
+ const urlKey = gridCtrl.remotePage ? 'find' : 'list';
101
+
102
+ return doQuery<FindResult>(gridCtrl, {
103
+ urlKey,
104
+ url: gridCtrl.gridUrl,
105
+ params: gridCtrl.gridQuery,
106
+ loadingState: gridCtrl.isGridLoading,
107
+ processParams: (params) => {
108
+ // 处理分页参数
109
+ if (gridCtrl.remotePage) {
110
+ params.Query!.$limit = [(gridCtrl.pageNo.value! - 1) * gridCtrl.pageSize.value!, gridCtrl.pageSize.value!];
111
+ }
112
+
113
+ const newParams = combineParams(gridCtrl.gridUrl?.params, params, gridCtrl.gridQuery);
114
+
115
+ return newParams;
116
+ },
117
+ }).then((result: ApiResponse<FindResult> | null) => {
118
+ if (result?.status === ResStatus.SUCCESS) {
119
+ let findResult = result.data as FindResult;
120
+ if (findResult.rows) {
121
+ gridCtrl.tableData.value = findResult.rows as unknown as T[];
122
+ gridCtrl.total.value = findResult.total;
123
+ } else {
124
+ gridCtrl.tableData.value = result.data as unknown as T[];
125
+ gridCtrl.total.value = (result.data as unknown as T[]).length;
126
+ findResult = {
127
+ total: gridCtrl.total.value,
128
+ rows: result.data as unknown as Record<string, any>[],
129
+ };
130
+
131
+ if (gridCtrl.afterLoad) gridCtrl.afterLoad(findResult);
132
+ }
133
+ return findResult;
134
+ }
135
+
136
+ gridCtrl.tableData.value = [];
137
+ gridCtrl.total.value = 0;
138
+ return {
139
+ total: 0,
140
+ rows: [],
141
+ };
142
+ });
143
+ };
144
+
145
+ /**
146
+ * 表格数据行更新
147
+ * @param gridCtrl 表格控制对象
148
+ * @param record 表格行数据
149
+ * - 记录行主键pageGrid.primaryKey默认为Id
150
+ * - 仅更新record内的字段
151
+ * @returns
152
+ */
153
+ export const gridRowUpdate = <T>(
154
+ gridCtrl: GridControl<T>,
155
+ record: Record<string, any>,
156
+ options: Partial<ExecuteOptions<T>> = {},
157
+ ): Promise<any | undefined> => {
158
+ return doSave<T>(gridCtrl, {
159
+ urlKey: 'update',
160
+ url: gridCtrl.updateUrl,
161
+ params: {
162
+ Query: { [gridCtrl.primaryKey]: record[gridCtrl.primaryKey] },
163
+ Data: record,
164
+ },
165
+ loadingState: gridCtrl.isGridSaving,
166
+ ...options,
167
+ }).then((result) => {
168
+ if (result?.status === ResStatus.SUCCESS) {
169
+ setTimeout(() => {
170
+ gridCtrl.reload.value = true;
171
+ if (gridCtrl.afterUpdate) gridCtrl.afterUpdate(record as T);
172
+ }, 50);
173
+ }
174
+ return result;
175
+ });
176
+ };
177
+
178
+ /**
179
+ * 表格数据行状态更新
180
+ * @param gridCtrl 表格控制对象
181
+ * @param record 表格行数据
182
+ * - 记录行主键pageGrid.primaryKey默认为Id
183
+ * - 记录行状态pageGrid.statusKey默认为Enabled
184
+ * @returns
185
+ */
186
+ export const gridStatusUpdate = <T>(
187
+ gridCtrl: GridControl<T>,
188
+ record: Record<string, any>,
189
+ ): Promise<any | undefined> => {
190
+ const rowStatus: Record<string, any> = {};
191
+ rowStatus[gridCtrl.primaryKey] = record[gridCtrl.primaryKey];
192
+ rowStatus[gridCtrl.statusKey] = record[gridCtrl.statusKey];
193
+ return gridRowUpdate(gridCtrl, rowStatus, {
194
+ loadingText: false,
195
+ hideErrorToast: true,
196
+ });
197
+ };
198
+
199
+ /**
200
+ * 获取数据记录详情
201
+ * @param pageCtrl 页面控制对象
202
+ * @param params 查询条件
203
+ * @param url 调用接口
204
+ * @returns
205
+ */
206
+ export const getRecordDetail = async <T>(
207
+ gridCtrl: GridControl<T>,
208
+ params: ReqParams,
209
+ url?: IUrlInfo,
210
+ ): Promise<ApiResponse<AnyJsonData> | null> => {
211
+ const response = await doQuery<AnyJsonData>(gridCtrl, {
212
+ urlKey: 'detail',
213
+ url,
214
+ params: params,
215
+ loadingState: gridCtrl.isGridLoading,
216
+ });
217
+
218
+ return response;
219
+ };
220
+
221
+ /**
222
+ * 表格记录展开详情
223
+ * @param gridCtrl 表格控制对象
224
+ * @param record 表格行数据
225
+ * @returns
226
+ */
227
+ export const onGridRowExpand = <T>(gridCtrl: GridControl<T>, record: T) => {
228
+ const recordData = record as Record<string, AnyData>;
229
+
230
+ return getRecordDetail(gridCtrl, { [gridCtrl.primaryKey]: recordData[gridCtrl.primaryKey] }).then((result) => {
231
+ if (result?.status === ResStatus.SUCCESS && result.data) {
232
+ gridCtrl.expandRows.value[recordData[gridCtrl.primaryKey]] = result;
233
+ }
234
+ return result;
235
+ });
236
+ };
237
+
238
+ /**
239
+ * 打开表单编辑表格记录
240
+ * @param gridCtrl 表格控制对象
241
+ * @param record 表格行数据
242
+ * @returns
243
+ */
244
+ export const onGridRowEdit = <T>(gridCtrl: GridControl<T>, record: T) => {
245
+ let editorCtrl = gridCtrl.editor;
246
+ gridCtrl.rowData!.value = record;
247
+ if (editorCtrl) {
248
+ setFormData(editorCtrl, record);
249
+ editorCtrl.visible.value = true;
250
+ }
251
+ };
252
+
253
+ /**
254
+ * 删除表格记录
255
+ * @param gridCtrl 表格控制对象
256
+ * @param record 表格行数据
257
+ * @returns
258
+ */
259
+ export const onGridRowDelete = <T>(gridCtrl: GridControl<T>, record: string[] | RowRecord | T) => {
260
+ return doDelete<T>(gridCtrl, record as any, {
261
+ url: gridCtrl.deleteUrl,
262
+ primaryKey: gridCtrl.primaryKey,
263
+ }).then((result) => {
264
+ if (result?.status === ResStatus.SUCCESS) {
265
+ setTimeout(() => {
266
+ gridCtrl.reload.value = true;
267
+ if (gridCtrl.afterDelete && !Array.isArray(record)) {
268
+ gridCtrl.afterDelete(record as T);
269
+ }
270
+ }, 50);
271
+ }
272
+ return result;
273
+ });
274
+ };
@@ -0,0 +1,362 @@
1
+ import { useSettingInfo } from '@/index';
2
+ import { GridControl } from '@/typings/table.d';
3
+ import { PageControl } from '@/typings/page.d';
4
+ import { RowRecord, ButtonTool, IconTool } from '@/typings/tools';
5
+
6
+ import message from 'vue-m-message';
7
+ import { AnyData } from '@skyfox2000/fapi';
8
+
9
+ /**
10
+ * 查找工具项
11
+ * @param defaultTools 默认工具栏
12
+ * @param key 关键字
13
+ * @returns
14
+ */
15
+ export const getToolByKey = (
16
+ defaultTools: (IconTool | ButtonTool)[],
17
+ key: string,
18
+ ): ButtonTool | IconTool | undefined => {
19
+ // 首先在顶层查找
20
+ const foundInTopLevel = defaultTools.find((tool) => tool.key === key);
21
+
22
+ // 如果在顶层找到了,直接返回
23
+ if (foundInTopLevel) {
24
+ return foundInTopLevel;
25
+ }
26
+
27
+ // 如果没有找到,递归地在每个工具项的 children 中查找
28
+ for (const tool of defaultTools) {
29
+ if (tool.children) {
30
+ const foundInChildren = getToolByKey(tool.children, key);
31
+ if (foundInChildren) {
32
+ return foundInChildren; // 如果在子级找到了,返回找到的工具项
33
+ }
34
+ }
35
+ }
36
+
37
+ // 如果整个树都查找完毕,没有找到,返回 undefined
38
+ return undefined;
39
+ };
40
+
41
+ /**
42
+ * 将按钮数组处理返回按钮组和菜单组
43
+ * @param defaultTools 默认按钮
44
+ * @param autoFlat 平铺数量,超出折叠成菜单,0不折叠
45
+ * @param tools 需要返回的工具栏
46
+ * @returns 按钮组,菜单组
47
+ */
48
+ export const getToolGroup = (
49
+ defaultTools: (IconTool | ButtonTool)[],
50
+ autoFlat: number,
51
+ tools?: (IconTool | ButtonTool | string)[],
52
+ ) => {
53
+ const buttons: (IconTool | ButtonTool)[] = [];
54
+ const menus: (IconTool | ButtonTool)[] = [];
55
+ if (!tools) tools = [...defaultTools];
56
+ if (tools.length) {
57
+ tools.forEach((toolItem, index) => {
58
+ let button: IconTool | ButtonTool;
59
+
60
+ if (typeof toolItem === 'string') {
61
+ const matchedButton = getToolByKey(defaultTools, toolItem);
62
+ button = matchedButton ? { ...matchedButton } : { key: toolItem, label: toolItem };
63
+ } else {
64
+ const matchedButton = getToolByKey(defaultTools, toolItem.key);
65
+ button = matchedButton ? { ...matchedButton, ...toolItem } : { ...toolItem };
66
+ }
67
+ if (!button.click) {
68
+ button.click = (_: PageControl<AnyData>, grid?: GridControl<AnyData>, record?: AnyData) => {
69
+ if (grid) grid.rowData.value = record;
70
+ if (button.formVisible) {
71
+ button.formVisible.value = false;
72
+ setTimeout(() => {
73
+ button.formVisible!.value = true;
74
+ }, 1);
75
+ } else {
76
+ message.warning('未配置点击处理事件!');
77
+ }
78
+ };
79
+ }
80
+
81
+ if (autoFlat === 0 || index < autoFlat) {
82
+ buttons.push(button);
83
+ } else {
84
+ menus.push(button);
85
+ }
86
+ });
87
+ }
88
+
89
+ return { buttons, menus };
90
+ };
91
+
92
+ /**
93
+ * 判断工具项是否禁用
94
+ * @param item 工具项
95
+ * @param record 相关数据
96
+ * @returns 禁用状态
97
+ */
98
+ export const getToolStatus = (item: IconTool | ButtonTool, record?: Record<string, any>) => {
99
+ if (item.disabled && typeof item.disabled == 'function') {
100
+ return item.disabled(record);
101
+ }
102
+ return item.disabled;
103
+ };
104
+
105
+ /**
106
+ * 判断工具项是否可见
107
+ * @param item 工具项
108
+ * @param record 相关数据
109
+ * @returns 可见状态
110
+ */
111
+ export const getToolVisible = (item: IconTool | ButtonTool, record?: Record<string, any>) => {
112
+ if (item.visible && typeof item.visible == 'function') {
113
+ return item.visible(record);
114
+ }
115
+ return item.visible ?? true;
116
+ };
117
+
118
+ /**
119
+ * 重新加载表格
120
+ * @param gridCtrl 表格控制对象
121
+ */
122
+ export const onReloadClick = <T>(_: PageControl<T>, gridCtrl?: GridControl<T>) => {
123
+ gridCtrl!.reload.value = true;
124
+ };
125
+
126
+ /**
127
+ * 搜索框显示
128
+ * @param gridCtrl 表格控制对象
129
+ */
130
+ const onSearchClick = <T>(_: PageControl<T>, gridCtrl?: GridControl<T>) => {
131
+ gridCtrl!.searchBar.value = !gridCtrl!.searchBar.value;
132
+ };
133
+
134
+ /**
135
+ * 行高控制显示
136
+ * @param gridCtrl 表格控制对象
137
+ */
138
+ const onRowHeightClick = <T>(_: PageControl<T>, gridCtrl?: GridControl<T>) => {
139
+ switch (gridCtrl!.tableSize.value) {
140
+ case 'large':
141
+ gridCtrl!.tableSize.value = 'middle';
142
+ break;
143
+ case 'middle':
144
+ gridCtrl!.tableSize.value = 'small';
145
+ break;
146
+ case 'small':
147
+ gridCtrl!.tableSize.value = 'large';
148
+ break;
149
+ }
150
+ };
151
+
152
+ /**
153
+ * 表格多选框显示
154
+ * @param gridCtrl 表格控制对象
155
+ */
156
+ const onCheckboxClick = <T>(_: PageControl<T>, gridCtrl?: GridControl<T>) => {
157
+ gridCtrl!.selectable.value = !gridCtrl!.selectable.value;
158
+ if (!gridCtrl!.selectable.value) {
159
+ gridCtrl!.selectKeys.value = [];
160
+ gridCtrl!.selectRows.value = [];
161
+ }
162
+ };
163
+
164
+ /**
165
+ * 全部记录行展开/合并控制
166
+ * @param pageCtrl 页面数据控制
167
+ */
168
+ const onAllRowExpandClick = <T>(_: PageControl<T>, gridCtrl?: GridControl<T>) => {
169
+ gridCtrl!.rowExpand.value = !gridCtrl!.rowExpand.value;
170
+ };
171
+
172
+ /**
173
+ * TODO: 表格导出Excel
174
+ * @param pageCtrl 页面数据控制
175
+ */
176
+ const onExportExcelClick = <T>(_: PageControl<T>, gridCtrl?: GridControl<T>) => {
177
+ gridCtrl!.selectable.value = !gridCtrl!.selectable.value;
178
+ };
179
+
180
+ /**
181
+ * 统一按钮操作
182
+ * @param item 按钮
183
+ * @param pageCtrl 页面控制对象
184
+ * @param record 数据表行记录
185
+ * @param confirm 确认执行
186
+ */
187
+ export const onToolClicked = <T>(
188
+ item: IconTool | ButtonTool,
189
+ pageCtrl?: PageControl<T>,
190
+ gridCtrl?: GridControl<T>,
191
+ record?: T | RowRecord | string[],
192
+ confirm?: true,
193
+ ) => {
194
+ /**
195
+ * 是否启用确认弹窗,或者已确认执行
196
+ */
197
+ if (!item.confirm || confirm) {
198
+ // 不使用弹窗或者已确认执行
199
+ if (item.click) {
200
+ if (pageCtrl) item.click(pageCtrl, gridCtrl, record);
201
+ else item.click(null as unknown as PageControl<T>, gridCtrl, record);
202
+ }
203
+ }
204
+ toolStatusUpdate(item);
205
+ };
206
+ /**
207
+ * TODO: 表格导出PDF
208
+ * @param pageCtrl 页面数据控制
209
+ */
210
+ const onExportPDFClick = <T>(_: PageControl<T>, gridCtrl?: GridControl<T>) => {
211
+ gridCtrl!.selectable.value = !gridCtrl!.selectable.value;
212
+ };
213
+
214
+ /**
215
+ * 全屏或退出全屏显示
216
+ */
217
+ export const onFullscreenClick = () => {
218
+ const settingInfoStore = useSettingInfo();
219
+ settingInfoStore.setFullscreen(!settingInfoStore.fullscreen);
220
+ };
221
+
222
+ /**
223
+ * 工具栏状态更新
224
+ * - 提示文字修改
225
+ * - 图标位修改
226
+ * - 根据外部状态更新特定图标状态
227
+ */
228
+ const toolStatusUpdate = (tool: IconTool | ButtonTool, iconStatus?: number) => {
229
+ if (tool.icons || tool.labels) {
230
+ if (iconStatus !== undefined) {
231
+ tool.iconStatus = iconStatus;
232
+ } else {
233
+ tool.iconStatus = tool.iconStatus || 0;
234
+ tool.iconStatus += 1;
235
+ }
236
+ if (tool.labels && tool.labels.length) tool.label = tool.labels[tool.iconStatus % tool.labels.length];
237
+ if (tool.icons && tool.icons.length) tool.icon = tool.icons[tool.iconStatus % tool.icons.length];
238
+ }
239
+ };
240
+
241
+ /**
242
+ * 控制表格字段是否显示
243
+ * @param column 表格字段
244
+ * @param checked 是否选中
245
+ */
246
+ export const onColumnVisibleChanged = (column: any, checked: boolean) => {
247
+ if (checked) {
248
+ delete column.visible;
249
+ } else {
250
+ column.visible = false;
251
+ }
252
+ };
253
+
254
+ /**
255
+ * 表格常用工具栏工具列表
256
+ * @param key参数规范
257
+ * - key 参数配置成tool.xxx.xxx
258
+ * - TODO: 支持用户权限控制判断
259
+ * @param click参数规范
260
+ * - <T>(pageCtrl: PageData<T>) => void
261
+ */
262
+ export const defaultTools: IconTool[] = [
263
+ {
264
+ key: 'Reload',
265
+ label: '刷新表格',
266
+ icon: 'icon-reload',
267
+ click: onReloadClick,
268
+ },
269
+ {
270
+ key: 'Query',
271
+ label: '展开搜索栏',
272
+ labels: ['展开搜索栏', '折叠搜索栏'],
273
+ icon: 'icon-search',
274
+ iconStatus: 0,
275
+ click: onSearchClick,
276
+ },
277
+ {
278
+ key: 'RowHeight',
279
+ label: '行高调整',
280
+ icon: 'icon-row-height',
281
+ click: onRowHeightClick,
282
+ },
283
+ {
284
+ key: 'tool.multiple.checkbox',
285
+ label: '显示多选框',
286
+ labels: ['显示多选框', '隐藏多选框'],
287
+ icon: 'icon-checkbox',
288
+ click: onCheckboxClick,
289
+ },
290
+ {
291
+ key: 'tool.expand.rows',
292
+ label: '展开记录行',
293
+ labels: ['展开记录行', '折叠记录行'],
294
+ icon: 'icon-row-collapse',
295
+ iconStatus: 0,
296
+ icons: ['icon-row-collapse', 'icon-row-expand'],
297
+ click: onAllRowExpandClick,
298
+ },
299
+ {
300
+ key: 'tool.export.excel',
301
+ label: '导出Excel',
302
+ icon: 'icon-export-excel',
303
+ children: [
304
+ {
305
+ key: 'tool.export.excel.all',
306
+ label: '全部记录',
307
+ click: onExportExcelClick,
308
+ },
309
+ {
310
+ key: 'tool.export.excel.selected',
311
+ label: '选中的记录',
312
+ click: onExportExcelClick,
313
+ },
314
+ ],
315
+ },
316
+ {
317
+ key: 'tool.export.pdf',
318
+ label: '导出PDF',
319
+ icon: 'icon-export-pdf',
320
+ children: [
321
+ {
322
+ key: 'tool.export.pdf.selected',
323
+ label: '选中的记录',
324
+ click: onExportPDFClick,
325
+ },
326
+ ],
327
+ },
328
+ {
329
+ key: 'TableHeadset',
330
+ label: '表头设置',
331
+ icon: 'icon-headset',
332
+ dropdown: 'headset',
333
+ click: () => {}, // 不设置点击事件
334
+ },
335
+ {
336
+ key: 'Fullscreen',
337
+ label: '设置全屏',
338
+ labels: ['设置全屏', '取消全屏'],
339
+ icon: 'icon-fullscreen',
340
+ iconStatus: 0,
341
+ icons: ['icon-fullscreen', 'icon-exitscreen'],
342
+ click: onFullscreenClick,
343
+ },
344
+ ];
345
+
346
+ /**
347
+ * 工具栏工厂
348
+ */
349
+ export const useToolFactory = <T>(gridCtrl: GridControl<T>) => {
350
+ if (!gridCtrl.tools || gridCtrl.tools.length > 0) {
351
+ const icons = [];
352
+ if (!gridCtrl.tools) icons.push(...defaultTools);
353
+ else {
354
+ icons.push(...gridCtrl.tools);
355
+ }
356
+ return { tools: getToolGroup(defaultTools as ButtonTool[], 0, icons).buttons as IconTool[] };
357
+ }
358
+
359
+ return {
360
+ tools: [],
361
+ };
362
+ };
@@ -0,0 +1,28 @@
1
+ import { TreeControl, TreeNode } from '@/typings/tree.d';
2
+ import { ApiResponse, ReqParams, ResStatus } from '@skyfox2000/fapi';
3
+ import { doQuery } from './data';
4
+ import { combineParams } from '@skyfox2000/microbase';
5
+
6
+ /**
7
+ * 树加载数据
8
+ * @param treeCtrl 树控制对象
9
+ * @returns Promise<TreeNode[] | undefined>
10
+ */
11
+ export const queryTree = (treeCtrl: TreeControl, params?: ReqParams): Promise<TreeNode[]> => {
12
+ // 设置树查询选项
13
+ return doQuery<TreeNode>(treeCtrl, {
14
+ urlKey: 'tree',
15
+ params: {},
16
+ loadingState: treeCtrl.isTreeLoading,
17
+ loadingText: false,
18
+ processParams: () => {
19
+ return combineParams(treeCtrl.treeQuery, params);
20
+ },
21
+ }).then((result: ApiResponse<TreeNode> | null) => {
22
+ if (result?.status === ResStatus.SUCCESS) {
23
+ treeCtrl.data.value = result.data as unknown as TreeNode[];
24
+ return treeCtrl.data.value as unknown as TreeNode[];
25
+ }
26
+ return [];
27
+ });
28
+ };
package/tsconfig.json CHANGED
@@ -41,13 +41,6 @@
41
41
  "sourceMap": true,
42
42
  "verbatimModuleSyntax": false
43
43
  },
44
- "include": [
45
- "src/**/**.ts",
46
- "src/**/**.d.ts",
47
- "src/**/**.vue",
48
- "types/**/*.d.ts",
49
- "vite.config.ts",
50
- "plugins/**/*.ts"
51
- ],
44
+ "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue", "env.d.ts", "vite.config.ts"],
52
45
  "exclude": ["node_modules", "lib", "dist"]
53
46
  }
package/vite.config.ts CHANGED
@@ -22,10 +22,10 @@ export default defineConfig(({ mode }: ConfigEnv) => {
22
22
  dts({
23
23
  outDir: 'lib',
24
24
  entryRoot: 'src',
25
- // 确保Vue文件也能生成类型
26
- include: ['src/components/**/*.ts', 'src/components/**/*.vue'],
25
+ // 确保所有文件都能生成类型
26
+ include: ['src/**/*.ts', 'src/**/*.vue', 'src/**/*.d.ts'],
27
27
  // 排除不需要的文件
28
- exclude: ['node_modules/**', 'src/components/**/*.test.ts'],
28
+ exclude: ['node_modules/**', 'src/**/*.test.ts'],
29
29
  // 不使用API Extractor来生成类型
30
30
  rollupTypes: false,
31
31
  // 启用静态导入,避免某些Vue模块解析问题
@@ -47,7 +47,7 @@ export default defineConfig(({ mode }: ConfigEnv) => {
47
47
  '@': path.resolve('./src'),
48
48
  '@skyfox2000/fapi': path.resolve('../502417_fapi'),
49
49
  '@skyfox2000/microbase': path.resolve('../502424_MicroBase'),
50
- '@skyfox2000/webabase': path.resolve('../502428_WebBase'),
50
+ '@skyfox2000/webbase': path.resolve('../502428_WebBase'),
51
51
  },
52
52
  extensions: ['.js', '.ts', '.vue', 'json'],
53
53
  },
@@ -85,6 +85,9 @@ export default defineConfig(({ mode }: ConfigEnv) => {
85
85
  '@skyfox2000/microbase',
86
86
 
87
87
  '@vue-office/excel',
88
+ '@json2csv/plainjs',
89
+ 'async-validator',
90
+ 'exceljs',
88
91
  // 添加ace相关的依赖为external
89
92
  'ace-builds',
90
93
  'vue3-ace-editor',