@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.
- package/lib/assets/modules/file-upload-CBUcsUnR.js +170 -0
- package/lib/assets/modules/form-validate-CgX7aR7T.js +297 -0
- package/lib/assets/modules/index-Civhd8xG.js +112 -0
- package/lib/assets/modules/index-DQMdt51R.js +726 -0
- package/lib/assets/modules/{index-BEWJ_qAH.js → index-DmWrkTXX.js} +1 -1
- package/lib/assets/modules/{menuTabs-BXdbFZor.js → menuTabs-BRYvFWA-.js} +131 -121
- package/lib/assets/modules/settingInfo-BZakNKIN.js +999 -0
- package/lib/assets/modules/uploadList-B7XoxGOh.js +278 -0
- package/lib/components/common/icon/index.vue.d.ts +1 -1
- package/lib/components/content/dialog/index.vue.d.ts +1 -1
- package/lib/components/content/drawer/index.vue.d.ts +1 -1
- package/lib/components/content/form/index.vue.d.ts +1 -1
- package/lib/components/content/search/index.vue.d.ts +1 -1
- package/lib/components/content/table/index.vue.d.ts +1 -1
- package/lib/components/content/table/tableOperate.vue.d.ts +1 -1
- package/lib/components/content/toolbar/icontool.vue.d.ts +1 -1
- package/lib/components/content/toolbar/index.vue.d.ts +1 -1
- package/lib/components/content/tree/index.vue.d.ts +1 -1
- package/lib/components/form/transfer/transferTable.vue.d.ts +1 -1
- package/lib/components/form/treeSelect/index.vue.d.ts +1 -1
- package/lib/components/form/upload/uploadList.vue.d.ts +1 -1
- package/lib/const/options.d.ts +32 -0
- package/lib/directives/enter-submit.d.ts +4 -0
- package/lib/directives/index.d.ts +2 -0
- package/lib/directives/permission.d.ts +5 -0
- package/lib/es/AceEditor/index.js +9 -8
- package/lib/es/BasicLayout/index.js +28 -24
- package/lib/es/Error403/index.js +15 -10
- package/lib/es/Error404/index.js +15 -10
- package/lib/es/ExcelForm/index.js +380 -175
- package/lib/es/UploadForm/index.js +23 -20
- package/lib/index.d.ts +42 -2
- package/lib/router/index.d.ts +16 -0
- package/lib/stores/appInfo.d.ts +34 -0
- package/lib/stores/hostInfo.d.ts +9 -0
- package/lib/stores/pageInfo.d.ts +18 -0
- package/lib/stores/pinia.d.ts +3 -0
- package/lib/stores/settingInfo.d.ts +8 -0
- package/lib/stores/userInfo.d.ts +21 -0
- package/lib/typings/data.d.ts +80 -0
- package/lib/typings/form.d.ts +171 -0
- package/lib/typings/menu.d.ts +7 -0
- package/lib/typings/option.d.ts +175 -0
- package/lib/typings/page.d.ts +69 -0
- package/lib/typings/table.d.ts +181 -0
- package/lib/typings/tools.d.ts +130 -0
- package/lib/typings/tree.d.ts +72 -0
- package/lib/typings/upload.d.ts +161 -0
- package/lib/typings/urls.d.ts +69 -0
- package/lib/utils/cache.d.ts +23 -0
- package/lib/utils/data.d.ts +6 -0
- package/lib/utils/download.d.ts +4 -0
- package/lib/utils/eventbus.d.ts +16 -0
- package/lib/utils/export-table.d.ts +12 -0
- package/lib/utils/file-upload.d.ts +15 -0
- package/lib/utils/form-excel.d.ts +30 -0
- package/lib/utils/form-validate.d.ts +29 -0
- package/lib/utils/form.d.ts +9 -0
- package/lib/utils/icon-loader.d.ts +125 -0
- package/lib/utils/isEmpty.d.ts +1 -0
- package/lib/utils/main-openapis.d.ts +9 -0
- package/lib/utils/menu.d.ts +6 -0
- package/lib/utils/options.d.ts +10 -0
- package/lib/utils/page.d.ts +25 -0
- package/lib/utils/table.d.ts +21 -0
- package/lib/utils/tools.d.ts +18 -0
- package/lib/utils/tree.d.ts +3 -0
- package/lib/vite-env.d.ts +8 -0
- package/lib/webui.css +1 -1
- package/lib/webui.es.js +1020 -854
- package/package.json +7 -6
- package/src/components/common/icon/appicon.vue +1 -1
- package/src/components/common/icon/fullscreen.vue +2 -1
- package/src/components/common/icon/index.vue +1 -1
- package/src/components/common/icon/layoutIcon.vue +1 -1
- package/src/components/common/icon/projectIcon.vue +1 -1
- package/src/components/common/icon/toolIcon.vue +1 -1
- package/src/components/content/dialog/excelForm.vue +2 -2
- package/src/components/content/dialog/index.vue +1 -1
- package/src/components/content/dialog/uploadForm.vue +7 -6
- package/src/components/content/drawer/index.vue +43 -18
- package/src/components/content/form/formItem.vue +1 -1
- package/src/components/content/form/index.vue +1 -1
- package/src/components/content/search/index.vue +1 -1
- package/src/components/content/search/searchItem.vue +1 -1
- package/src/components/content/table/index.vue +8 -5
- package/src/components/content/table/tableOperate.vue +8 -4
- package/src/components/content/toolbar/icontool.vue +2 -2
- package/src/components/content/toolbar/index.vue +9 -5
- package/src/components/content/tree/index.vue +1 -1
- package/src/components/error/error403.vue +2 -2
- package/src/components/error/error404.vue +2 -2
- package/src/components/form/autoComplete/index.vue +1 -1
- package/src/components/form/cascader/index.vue +1 -2
- package/src/components/form/checkbox/index.vue +11 -5
- package/src/components/form/datePicker/index.vue +1 -1
- package/src/components/form/input/index.vue +1 -1
- package/src/components/form/input/inputNumber.vue +1 -1
- package/src/components/form/input/inputPassword.vue +1 -1
- package/src/components/form/radio/index.vue +1 -1
- package/src/components/form/radio/radioStatus.vue +1 -1
- package/src/components/form/rangePicker/index.vue +1 -1
- package/src/components/form/select/index.vue +1 -1
- package/src/components/form/switch/index.vue +7 -3
- package/src/components/form/textarea/index.vue +1 -1
- package/src/components/form/transfer/index.vue +1 -1
- package/src/components/form/transfer/transferTable.vue +42 -22
- package/src/components/form/treeSelect/index.vue +2 -3
- package/src/components/form/upload/uploadList.vue +1 -1
- package/src/components/layout/breadcrumb/index.vue +1 -1
- package/src/components/layout/header/headerExits.vue +1 -1
- package/src/components/layout/header/index.vue +1 -1
- package/src/components/layout/header/user.vue +2 -1
- package/src/components/layout/menu/index.vue +9 -3
- package/src/components/layout/menu/menuTabs.vue +10 -12
- package/src/components/layout/page/basicLayout.vue +1 -1
- package/src/const/options.ts +114 -0
- package/src/directives/enter-submit.ts +13 -0
- package/src/directives/index.ts +26 -0
- package/src/directives/permission.ts +144 -0
- package/src/index.ts +201 -0
- package/src/router/index.ts +196 -0
- package/src/stores/appInfo.ts +471 -0
- package/src/stores/hostInfo.ts +117 -0
- package/src/stores/pageInfo.ts +131 -0
- package/src/stores/pinia.ts +10 -0
- package/src/stores/settingInfo.ts +53 -0
- package/src/stores/userInfo.ts +392 -0
- package/src/typings/data.d.ts +81 -0
- package/src/typings/form.d.ts +172 -0
- package/src/typings/menu.d.ts +7 -0
- package/src/typings/option.d.ts +177 -0
- package/src/typings/page.d.ts +70 -0
- package/src/typings/table.d.ts +182 -0
- package/src/typings/tools.d.ts +131 -0
- package/src/typings/tree.d.ts +73 -0
- package/src/typings/upload.d.ts +162 -0
- package/src/typings/urls.d.ts +70 -0
- package/src/utils/cache.ts +175 -0
- package/src/utils/data.ts +189 -0
- package/src/utils/download.ts +80 -0
- package/src/utils/eventbus.ts +78 -0
- package/src/utils/export-table.ts +155 -0
- package/src/utils/file-upload.ts +304 -0
- package/src/utils/form-excel.ts +523 -0
- package/src/utils/form-validate.ts +368 -0
- package/src/utils/form.ts +188 -0
- package/src/utils/icon-loader.ts +412 -0
- package/src/utils/isEmpty.ts +18 -0
- package/src/utils/main-openapis.ts +72 -0
- package/src/utils/menu.ts +89 -0
- package/src/utils/options.ts +324 -0
- package/src/utils/page.ts +262 -0
- package/src/utils/table.ts +274 -0
- package/src/utils/tools.ts +362 -0
- package/src/utils/tree.ts +28 -0
- package/tsconfig.json +1 -8
- package/vite.config.ts +7 -4
- package/lib/assets/modules/index-BahGnrAq.js +0 -415
- package/lib/assets/modules/index-BoKIa2sr.js +0 -109
- package/lib/assets/modules/index-D47Ci-T3.js +0 -107
- 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
|
-
//
|
|
26
|
-
include: ['src
|
|
25
|
+
// 确保所有文件都能生成类型
|
|
26
|
+
include: ['src/**/*.ts', 'src/**/*.vue', 'src/**/*.d.ts'],
|
|
27
27
|
// 排除不需要的文件
|
|
28
|
-
exclude: ['node_modules/**', 'src
|
|
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/
|
|
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',
|