@scx-js/scx-admin 0.0.3
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/components/crud/crud-add-button.vue +28 -0
- package/components/crud/crud-batch-delete.vue +27 -0
- package/components/crud/crud-edit-dialog.vue +36 -0
- package/components/crud/crud-edit-form.vue +28 -0
- package/components/crud/crud-form-footer.vue +28 -0
- package/components/crud/crud-pagination.vue +51 -0
- package/components/crud/crud-reset-button.vue +19 -0
- package/components/crud/crud-search-button.vue +25 -0
- package/components/crud/crud-table-delete-button.vue +31 -0
- package/components/crud/crud-table-edit-button.vue +26 -0
- package/components/crud/crud-table.vue +131 -0
- package/components/crud/index.css +46 -0
- package/components/crud/index.vue +37 -0
- package/components/easy-ckeditor/default-editor-config.js +199 -0
- package/components/easy-ckeditor/easy-ckeditor-lazy.css +17 -0
- package/components/easy-ckeditor/easy-ckeditor-lazy.vue +106 -0
- package/components/easy-ckeditor/index.css +3 -0
- package/components/easy-ckeditor/index.vue +58 -0
- package/components/easy-ckeditor/plugins/scx-upload-adapter.js +39 -0
- package/components/easy-form-item/index.vue +168 -0
- package/components/easy-image/index.css +24 -0
- package/components/easy-image/index.vue +75 -0
- package/components/easy-monaco-editor/index.css +8 -0
- package/components/easy-monaco-editor/index.vue +70 -0
- package/components/easy-monaco-editor/use-worker.js +27 -0
- package/components/easy-select/index.vue +29 -0
- package/components/easy-upload/index.vue +94 -0
- package/components/easy-upload-list/index.vue +107 -0
- package/components/index.js +69 -0
- package/components/left-tree/index.css +74 -0
- package/components/left-tree/index.vue +130 -0
- package/components/scx-container/index.css +19 -0
- package/components/scx-container/index.vue +22 -0
- package/components/user-profile/change-password-dialog.vue +100 -0
- package/components/user-profile/change-user-avatar.vue +43 -0
- package/components/user-profile/change-username-dialog.vue +82 -0
- package/components/user-profile/index.css +8 -0
- package/components/user-profile/index.vue +77 -0
- package/index.js +4 -0
- package/layout/img/default-avatar.gif +0 -0
- package/layout/index.vue +24 -0
- package/layout/scx-app.vue +110 -0
- package/layout/scx-input.vue +84 -0
- package/layout/scx-logo.vue +65 -0
- package/layout/scx-main.vue +48 -0
- package/layout/scx-menu-item.vue +47 -0
- package/layout/scx-menu-toggle.vue +69 -0
- package/layout/scx-menu.vue +122 -0
- package/layout/scx-navbar.vue +47 -0
- package/layout/scx-notice.vue +211 -0
- package/layout/scx-sidebar.vue +70 -0
- package/layout/scx-theme-switch.vue +54 -0
- package/layout/scx-user-panel.vue +193 -0
- package/package.json +30 -0
- package/routes.js +57 -0
- package/scx/ali-oss.js +87 -0
- package/scx/auth-fetch.js +68 -0
- package/scx/crud-context.js +522 -0
- package/scx/easy-option.js +131 -0
- package/scx/index.js +8 -0
- package/scx/scx-auth-info.js +48 -0
- package/scx/scx-auth.js +197 -0
- package/scx/scx-config-manager.js +105 -0
- package/scx/scx-router.js +273 -0
- package/styles/index.css +37 -0
- package/util/cities.js +350 -0
- package/util/duration-format.js +27 -0
- package/util/element-plus-helper.js +114 -0
- package/util/get-order-number.js +7 -0
- package/util/index.js +4 -0
- package/util/nations.js +16 -0
- package/util/provinces.js +41 -0
- package/views/error-page.vue +79 -0
- package/views/login/index.css +95 -0
- package/views/login/login-and-register.vue +66 -0
- package/views/login/login-bg.vue +121 -0
- package/views/login/login-form-bg.vue +61 -0
- package/views/login/login-form.vue +137 -0
- package/views/login/login-message.js +28 -0
- package/views/login/login.vue +29 -0
- package/views/login/register-form.vue +148 -0
- package/views/no-perm.vue +7 -0
- package/views/not-found.vue +7 -0
- package/views/rocket.vue +84 -0
@@ -0,0 +1,522 @@
|
|
1
|
+
import {JsonVOError, ScxReq, useScxReq} from "@scx-js/scx-http";
|
2
|
+
import {CRUDListParam, ScxCrud} from "@scx-js/scx-app-x";
|
3
|
+
import {focusFirstErrorElement} from "../util/index.js";
|
4
|
+
import {useScxUserInfo} from "./scx-auth-info.js";
|
5
|
+
import {ElMessage, ElNotification} from "element-plus";
|
6
|
+
import {inject, isReactive, nextTick, provide, reactive} from "vue";
|
7
|
+
import {and, eq, in_, OrderBy, query} from "@scx-js/scx-data";
|
8
|
+
import {deepCopy, notBlank} from "@scx-js/scx-common";
|
9
|
+
|
10
|
+
/**
|
11
|
+
*
|
12
|
+
* @type {string}
|
13
|
+
*/
|
14
|
+
const crudContextKey = "crud-context";
|
15
|
+
|
16
|
+
/**
|
17
|
+
* crud 上下文 , 方便操作进行简单的页面 crud
|
18
|
+
*/
|
19
|
+
class CrudContext {
|
20
|
+
|
21
|
+
/**
|
22
|
+
* req 对象 用于调用 api
|
23
|
+
* @type {ScxReq}
|
24
|
+
*/
|
25
|
+
req = null;
|
26
|
+
|
27
|
+
/**
|
28
|
+
* 用于判断后台是否允许真实删除
|
29
|
+
* @type {ScxAuthInfo}
|
30
|
+
*/
|
31
|
+
userInfo = null;
|
32
|
+
|
33
|
+
/**
|
34
|
+
* @type {ScxCrud}
|
35
|
+
*/
|
36
|
+
scxCrud;
|
37
|
+
|
38
|
+
/**
|
39
|
+
* 表格的 ref 用来调用 el-table 表格的相关操作 如清除多选数据
|
40
|
+
*/
|
41
|
+
scxTableRef = null;
|
42
|
+
|
43
|
+
/**
|
44
|
+
* 添加或修改 Form 的 ref , 用来调用 el-form 相关的操作 如校验表单中数据是否合法
|
45
|
+
*/
|
46
|
+
scxCreateAndUpdateFormRef = null;
|
47
|
+
|
48
|
+
/**
|
49
|
+
* 默认 where
|
50
|
+
*/
|
51
|
+
defaultWhere = {};
|
52
|
+
|
53
|
+
/**
|
54
|
+
* 默认 临时对象
|
55
|
+
*/
|
56
|
+
defaultTemp = {};
|
57
|
+
|
58
|
+
/**
|
59
|
+
* [orderBy pagination selectFilterBody where] 会在 getQueryParam 方法中组合为 listApi 需要的最终查询参数对象
|
60
|
+
*
|
61
|
+
* 排序字段 model (注意: 虽然 list api 支持多排序字段 但目前前台还是使用单排序字段 即每次查询只支持一列排序)
|
62
|
+
* @type {{fieldName: string, sortType: string}}
|
63
|
+
*/
|
64
|
+
orderBy = {fieldName: "id", sortType: "DESC"};
|
65
|
+
|
66
|
+
/**
|
67
|
+
* 分页字段 model 和 orderBy 功能类似 (注意 : listApi 的分页起始 为 0 ,前台 ui 这里为 1 ,所以在转换为 listApi 查询对象的时候需要注意 -1 )
|
68
|
+
* @type {{pageSize: number, currentPage: number}}
|
69
|
+
*/
|
70
|
+
pagination = {currentPage: 1, pageSize: 10};
|
71
|
+
|
72
|
+
/**
|
73
|
+
* 查询列过滤条件 对象 一般我们将其设置为 null 即查询所有字段
|
74
|
+
*/
|
75
|
+
selectFilterBody = null;
|
76
|
+
|
77
|
+
/**
|
78
|
+
* 查询参数绑定 model 这里默认都是以 like 的方式发送到后台 具体如有变化请自行继承 CrudContext 并重写 getQueryParam 方法
|
79
|
+
* @type {{}}
|
80
|
+
*/
|
81
|
+
where = {};
|
82
|
+
|
83
|
+
/**
|
84
|
+
* 默认 不需要更新的字段名称
|
85
|
+
* @type Array
|
86
|
+
*/
|
87
|
+
needUpdateFieldNames = null;
|
88
|
+
|
89
|
+
/**
|
90
|
+
* 表单绑定的临时操作对象 很重要!!!
|
91
|
+
*/
|
92
|
+
temp = {};
|
93
|
+
|
94
|
+
/**
|
95
|
+
* 当前页面类型 是处于添加还是处于修改 取值 [create, update]
|
96
|
+
* @type {string}
|
97
|
+
*/
|
98
|
+
pageFlag = "";
|
99
|
+
|
100
|
+
/**
|
101
|
+
* 表格列表数据
|
102
|
+
* @type {[]}
|
103
|
+
*/
|
104
|
+
tableBody = [];
|
105
|
+
|
106
|
+
/**
|
107
|
+
* 表格加载状态
|
108
|
+
* @type {boolean}
|
109
|
+
*/
|
110
|
+
tableLoading = true;
|
111
|
+
|
112
|
+
/**
|
113
|
+
* 总条数
|
114
|
+
* @type {number}
|
115
|
+
*/
|
116
|
+
total = 0; // 总条数
|
117
|
+
|
118
|
+
/**
|
119
|
+
* 编辑弹窗
|
120
|
+
* @type {{visible: boolean, confirmButtonLoading: boolean}}
|
121
|
+
*/
|
122
|
+
editDialog = {
|
123
|
+
|
124
|
+
/**
|
125
|
+
* 添加或修改页面的 确认按钮是否处于 loading 状态 防止重复点击 造成多条数据添加
|
126
|
+
*/
|
127
|
+
confirmButtonLoading: false,
|
128
|
+
|
129
|
+
/**
|
130
|
+
* 添加和删除的的 dialog 显示状态
|
131
|
+
*/
|
132
|
+
visible: false,
|
133
|
+
|
134
|
+
};
|
135
|
+
|
136
|
+
/**
|
137
|
+
* 保存多选项的对象
|
138
|
+
* @type {[]}
|
139
|
+
*/
|
140
|
+
multipleSelection = [];
|
141
|
+
|
142
|
+
/**
|
143
|
+
*
|
144
|
+
* @param baseCrudApi a
|
145
|
+
* @param scxTableRef a
|
146
|
+
* @param defaultTemp a
|
147
|
+
* @param defaultWhere a
|
148
|
+
*/
|
149
|
+
constructor({
|
150
|
+
baseCrudApi,
|
151
|
+
defaultTemp = {},
|
152
|
+
defaultWhere = {},
|
153
|
+
} = {}) {
|
154
|
+
this.req = useScxReq();
|
155
|
+
this.userInfo = useScxUserInfo();
|
156
|
+
this.defaultTemp = defaultTemp;
|
157
|
+
this.defaultWhere = defaultWhere;
|
158
|
+
this.scxCrud = new ScxCrud(this.req, baseCrudApi);
|
159
|
+
|
160
|
+
//重置全部对象
|
161
|
+
this.resetPagination();
|
162
|
+
this.resetOrderBy();
|
163
|
+
this.resetSelectFilterBody();
|
164
|
+
this.resetWhere();
|
165
|
+
this.resetTemp();
|
166
|
+
}
|
167
|
+
|
168
|
+
/**
|
169
|
+
* 删除单条数据实现
|
170
|
+
* @param row
|
171
|
+
*/
|
172
|
+
deleteOne(row) {
|
173
|
+
if (!row.id) {
|
174
|
+
ElNotification({title: "待删除数据 id 不能为空 !!!", type: "warning", duration: 5000});
|
175
|
+
return;
|
176
|
+
}
|
177
|
+
let msg = `已成功删除 : ${this.getMainInfo(row)}`;// 删除消息
|
178
|
+
let en = null; // 弹出框对象
|
179
|
+
//这里针对后台是否采用墓碑机制给予用户删除的两种不同交互策略
|
180
|
+
this.scxCrud.delete({query: eq("id", row.id)}).then(data => {
|
181
|
+
en = ElNotification({
|
182
|
+
title: "删除成功 !!!",
|
183
|
+
message: msg,
|
184
|
+
type: "success",
|
185
|
+
dangerouslyUseHTMLString: true,
|
186
|
+
duration: 5000,
|
187
|
+
});
|
188
|
+
this.tableBody = this.tableBody.filter(b => b.id !== row.id);
|
189
|
+
this.total = this.total - 1;
|
190
|
+
}).catch(e => ElNotification({title: "删除失败 !!!", message: e, type: "error", duration: 5000}));
|
191
|
+
}
|
192
|
+
|
193
|
+
batchDelete() {
|
194
|
+
const deleteIDs = this.multipleSelection.map(d => d.id);
|
195
|
+
//如果 数据为空 显示提示框
|
196
|
+
if (deleteIDs.length === 0) {
|
197
|
+
ElNotification({
|
198
|
+
title: "未选中任何数据!!!", type: "warning", duration: 5000,
|
199
|
+
});
|
200
|
+
return;
|
201
|
+
}
|
202
|
+
//数据校验全部没问题 可以进行 批量删除
|
203
|
+
this.scxCrud.delete({query: in_("id", deleteIDs)})
|
204
|
+
.then(deletedCount => {
|
205
|
+
ElNotification({
|
206
|
+
title: "已删除全部选中数据 , 共" + deletedCount + "条 !", type: "success", duration: 5000,
|
207
|
+
});
|
208
|
+
//清空多选数据
|
209
|
+
this.scxTableRef.clearSelection();
|
210
|
+
if (deletedCount >= this.tableBody.length) {
|
211
|
+
this.pagination.currentPage = 1;
|
212
|
+
}
|
213
|
+
this.getList();
|
214
|
+
})
|
215
|
+
.catch(e => ElNotification({
|
216
|
+
title: "批量删除失败 !!!", type: "error", duration: 5000,
|
217
|
+
}));
|
218
|
+
}
|
219
|
+
|
220
|
+
getList() {
|
221
|
+
//开启表格加载动画
|
222
|
+
this.tableLoading = true;
|
223
|
+
this.scxCrud.list(this.getQueryParam()).then(data => {
|
224
|
+
this.tableBody = data.items;
|
225
|
+
this.total = data.total;
|
226
|
+
}).catch(e => {
|
227
|
+
if (e instanceof JsonVOError) {
|
228
|
+
ElMessage.error(e.message);
|
229
|
+
} else {
|
230
|
+
ElMessage.error("请求发生错误 !!!");
|
231
|
+
console.error(e);
|
232
|
+
}
|
233
|
+
}).finally(() => {
|
234
|
+
this.tableLoading = false;
|
235
|
+
});
|
236
|
+
};
|
237
|
+
|
238
|
+
/**
|
239
|
+
*
|
240
|
+
* @return {CRUDListParam}
|
241
|
+
*/
|
242
|
+
getQueryParam() {
|
243
|
+
const q = query();
|
244
|
+
//1, 设置分页
|
245
|
+
q.limit(this.pagination.pageSize);
|
246
|
+
q.offset((this.pagination.currentPage - 1) * this.pagination.pageSize);
|
247
|
+
|
248
|
+
//2, 设置 orderBy
|
249
|
+
q.orderBy(new OrderBy(this.orderBy.fieldName, this.orderBy.sortType));
|
250
|
+
|
251
|
+
//3, 设置 where
|
252
|
+
|
253
|
+
|
254
|
+
//4, 设置 selectFilter
|
255
|
+
const f = this.selectFilterBody;
|
256
|
+
|
257
|
+
const a = and();
|
258
|
+
//获取所有 like的查询项
|
259
|
+
for (let key in this.where) {
|
260
|
+
if (this.where.hasOwnProperty(key)) {
|
261
|
+
const value1 = this.where[key];
|
262
|
+
if (notBlank(value1)) {
|
263
|
+
a.like(key, value1);
|
264
|
+
}
|
265
|
+
}
|
266
|
+
}
|
267
|
+
|
268
|
+
q.where(a);
|
269
|
+
|
270
|
+
return {
|
271
|
+
query: q,
|
272
|
+
fieldFilter: f,
|
273
|
+
extParams: {},
|
274
|
+
};
|
275
|
+
}
|
276
|
+
|
277
|
+
validateScxCreateAndUpdateFormRef() {
|
278
|
+
return new Promise((resolve, reject) => {
|
279
|
+
this.editDialog.confirmButtonLoading = true;
|
280
|
+
this.scxCreateAndUpdateFormRef.validate((valid) => {
|
281
|
+
//如果所有数据都没有问题
|
282
|
+
if (valid) {
|
283
|
+
resolve();
|
284
|
+
} else {
|
285
|
+
//校验未通过 先取消确认按钮的loading 状态
|
286
|
+
this.editDialog.confirmButtonLoading = false;
|
287
|
+
focusFirstErrorElement();
|
288
|
+
reject();
|
289
|
+
}
|
290
|
+
});
|
291
|
+
});
|
292
|
+
};
|
293
|
+
|
294
|
+
clearValidateScxCreateAndUpdateFormRef() {
|
295
|
+
nextTick(() => this.scxCreateAndUpdateFormRef.clearValidate()).then();
|
296
|
+
}
|
297
|
+
|
298
|
+
createOrUpdateModel() {
|
299
|
+
if (this.pageFlag === "create") {
|
300
|
+
return this.createModel();
|
301
|
+
} else if (this.pageFlag === "edit") {
|
302
|
+
return this.updateModel();
|
303
|
+
}
|
304
|
+
}
|
305
|
+
|
306
|
+
createModel(modelData = this.temp) {
|
307
|
+
return new Promise((resolve, reject) => this.validateScxCreateAndUpdateFormRef().then(() => {
|
308
|
+
//此处进行拷贝 防止 table 中的数据和 temp 产生影响
|
309
|
+
let modelDataCopy = deepCopy(modelData);
|
310
|
+
modelDataCopy.id = null;
|
311
|
+
this.scxCrud.add(modelDataCopy).then(data => {
|
312
|
+
this.tableBody.unshift(data);
|
313
|
+
this.total = this.total + 1;
|
314
|
+
this.editDialog.visible = false;
|
315
|
+
ElNotification({
|
316
|
+
title: "添加成功", message: "成功添加 : " + this.getMainInfo(data), type: "success", duration: 5000,
|
317
|
+
});
|
318
|
+
resolve(data);
|
319
|
+
}).catch(e => reject(this.reqErrorHandler(e))).finally(() => this.editDialog.confirmButtonLoading = false);
|
320
|
+
}).catch(e => reject(e)));
|
321
|
+
}
|
322
|
+
|
323
|
+
updateModel(modelData = this.temp) {
|
324
|
+
return new Promise((resolve, reject) => this.validateScxCreateAndUpdateFormRef().then(() => {
|
325
|
+
//此处进行拷贝 防止table 中的数据和 temp 产生影响
|
326
|
+
let modelDataCopy = deepCopy(modelData);
|
327
|
+
this.scxCrud.update({
|
328
|
+
updateModel: modelDataCopy,
|
329
|
+
needUpdateFieldNames: this.needUpdateFieldNames,
|
330
|
+
}).then(data => {
|
331
|
+
//修改页面上 id 和 当前修改id 相同的 数据 实现页面的数据刷新
|
332
|
+
this.updateTableBody(data);
|
333
|
+
this.editDialog.visible = false;
|
334
|
+
ElNotification({
|
335
|
+
title: "更新成功", message: "成功更新 : " + this.getMainInfo(data), type: "success", duration: 5000,
|
336
|
+
});
|
337
|
+
resolve(data);
|
338
|
+
}).catch(e => reject(this.reqErrorHandler(e))).finally(() => this.editDialog.confirmButtonLoading = false);
|
339
|
+
}).catch(e => reject(e)));
|
340
|
+
}
|
341
|
+
|
342
|
+
updateTableBody(data) {
|
343
|
+
//修改页面上 id 和 当前修改id 相同的 数据 实现页面的数据刷新
|
344
|
+
for (const v of this.tableBody) {
|
345
|
+
if (v.id === data.id) {
|
346
|
+
//获取要修改的 index 值
|
347
|
+
const index = this.tableBody.indexOf(v);
|
348
|
+
// 用 temp 进行替换
|
349
|
+
this.tableBody.splice(index, 1, data);
|
350
|
+
//因为 id 只可能出现一次 所以一旦找到相同的 id 直接 break 即可
|
351
|
+
break;
|
352
|
+
}
|
353
|
+
}
|
354
|
+
}
|
355
|
+
|
356
|
+
handleCreate() {
|
357
|
+
//设置添加确认按钮loading 为false 表示可以点击
|
358
|
+
this.editDialog.confirmButtonLoading = false;
|
359
|
+
//设置当前页面的 flag 是 create 还是 update
|
360
|
+
this.pageFlag = "create";
|
361
|
+
//清洗临时数据
|
362
|
+
this.resetTemp();
|
363
|
+
//准备添加页面的下拉选 自动完成框等数据并添加校验规则
|
364
|
+
this.editDialog.visible = true;
|
365
|
+
//清空当前表单的校验
|
366
|
+
this.clearValidateScxCreateAndUpdateFormRef();
|
367
|
+
}
|
368
|
+
|
369
|
+
handleUpdate(row) {
|
370
|
+
this.scxCrud.info(row.id).then(data => {
|
371
|
+
this.editDialog.confirmButtonLoading = false;
|
372
|
+
this.pageFlag = "edit";
|
373
|
+
this.temp = data;
|
374
|
+
//显示页面
|
375
|
+
this.editDialog.visible = true;
|
376
|
+
//清空当前表单的校验
|
377
|
+
this.clearValidateScxCreateAndUpdateFormRef();
|
378
|
+
}).catch(e => {
|
379
|
+
console.error(e);
|
380
|
+
});
|
381
|
+
}
|
382
|
+
|
383
|
+
handleQuery() {
|
384
|
+
this.pagination.currentPage = 1;
|
385
|
+
this.getList();
|
386
|
+
}
|
387
|
+
|
388
|
+
checkUnique(rule, value, callback, name) {
|
389
|
+
if (value) {
|
390
|
+
this.scxCrud.checkUnique(rule.field, value, this.pageFlag !== "create" ? this.temp.id : null)
|
391
|
+
.then(res => {
|
392
|
+
if (res.isUnique) {
|
393
|
+
callback();
|
394
|
+
} else {
|
395
|
+
callback(new Error(name + "已被占用 !!!"));
|
396
|
+
}
|
397
|
+
})
|
398
|
+
.catch(e => {
|
399
|
+
ElMessage.error("校验唯一值时发生错误, 请联系管理员 !!!");
|
400
|
+
console.error(e);
|
401
|
+
});
|
402
|
+
} else {
|
403
|
+
callback();
|
404
|
+
}
|
405
|
+
}
|
406
|
+
|
407
|
+
/**
|
408
|
+
* 当我们进行 添加 修改 时会给用户提示 具体哪条数据被操作了
|
409
|
+
* 此方法便是从 具体的对象中提取某一字段作为基本信息返回
|
410
|
+
* 如 数据为 {name:'小明'} 返回值则为 '小明' 默认取对象的第一个不为 id 的属性
|
411
|
+
*/
|
412
|
+
getMainInfo(row) {
|
413
|
+
const keys = Object.keys(row);
|
414
|
+
for (let key of keys) {
|
415
|
+
//id createDate updateDate 对用户来说并未太大意义 这里默认排除
|
416
|
+
if (key !== "id" && key !== "createdDate" && key !== "updatedDate") {
|
417
|
+
return row[key];
|
418
|
+
}
|
419
|
+
}
|
420
|
+
}
|
421
|
+
|
422
|
+
reqErrorHandler(e) {
|
423
|
+
if (e instanceof JsonVOError) {
|
424
|
+
ElMessage.error(e.message);
|
425
|
+
} else {
|
426
|
+
ElMessage.error("请求发生错误 !!!");
|
427
|
+
console.error(e);
|
428
|
+
}
|
429
|
+
return e;
|
430
|
+
}
|
431
|
+
|
432
|
+
getDialogTitle() {
|
433
|
+
return this.pageFlag === "create" ? "添加" : "编辑";
|
434
|
+
}
|
435
|
+
|
436
|
+
resetPagination() {
|
437
|
+
this.pagination = deepCopy(this.getDefaultPagination());
|
438
|
+
return this;
|
439
|
+
}
|
440
|
+
|
441
|
+
resetOrderBy() {
|
442
|
+
this.orderBy = deepCopy(this.getDefaultOrderBy());
|
443
|
+
return this;
|
444
|
+
}
|
445
|
+
|
446
|
+
resetSelectFilterBody() {
|
447
|
+
this.selectFilterBody = deepCopy(this.getDefaultSelectFilterBody());
|
448
|
+
return this;
|
449
|
+
}
|
450
|
+
|
451
|
+
resetWhere() {
|
452
|
+
this.where = deepCopy(this.getDefaultWhere());
|
453
|
+
return this;
|
454
|
+
}
|
455
|
+
|
456
|
+
resetTemp() {
|
457
|
+
this.temp = deepCopy(this.getDefaultTemp());
|
458
|
+
return this;
|
459
|
+
}
|
460
|
+
|
461
|
+
getDefaultPagination() {
|
462
|
+
return {currentPage: 1, pageSize: 10};
|
463
|
+
}
|
464
|
+
|
465
|
+
getDefaultOrderBy() {
|
466
|
+
return {fieldName: "id", sortType: "DESC"};
|
467
|
+
}
|
468
|
+
|
469
|
+
getDefaultSelectFilterBody() {
|
470
|
+
return null;
|
471
|
+
}
|
472
|
+
|
473
|
+
getDefaultWhere() {
|
474
|
+
return this.defaultWhere;
|
475
|
+
}
|
476
|
+
|
477
|
+
//默认的 临时状态对象
|
478
|
+
getDefaultTemp() {
|
479
|
+
return this.defaultTemp;
|
480
|
+
}
|
481
|
+
|
482
|
+
handleSelectionChange(columns) {
|
483
|
+
this.multipleSelection = columns;
|
484
|
+
}
|
485
|
+
|
486
|
+
tableSelect(columns) {
|
487
|
+
|
488
|
+
}
|
489
|
+
|
490
|
+
tableSelectAll(columns) {
|
491
|
+
|
492
|
+
}
|
493
|
+
|
494
|
+
install(app) {
|
495
|
+
app.provide(crudContextKey, this);
|
496
|
+
}
|
497
|
+
|
498
|
+
}
|
499
|
+
|
500
|
+
|
501
|
+
/**
|
502
|
+
*
|
503
|
+
* @returns {CrudContext}
|
504
|
+
*/
|
505
|
+
function useCrudContext() {
|
506
|
+
return inject(crudContextKey);
|
507
|
+
}
|
508
|
+
|
509
|
+
/**
|
510
|
+
*
|
511
|
+
* @param crudContext
|
512
|
+
* @returns {CrudContext}
|
513
|
+
*/
|
514
|
+
function installCrudContext(crudContext) {
|
515
|
+
if (!isReactive(crudContext)) {
|
516
|
+
crudContext = reactive(crudContext);
|
517
|
+
}
|
518
|
+
provide(crudContextKey, crudContext);
|
519
|
+
return crudContext;
|
520
|
+
}
|
521
|
+
|
522
|
+
export {CrudContext, installCrudContext, useCrudContext};
|
@@ -0,0 +1,131 @@
|
|
1
|
+
import {copyArray, isFunction, isNull, isObject, notNull} from "@scx-js/scx-common";
|
2
|
+
|
3
|
+
function myEqual(value1, value2) {
|
4
|
+
return String(value1) === String(value2);
|
5
|
+
}
|
6
|
+
|
7
|
+
function myIncludes(array, value) {
|
8
|
+
return array.some(item => myEqual(item, value));
|
9
|
+
}
|
10
|
+
|
11
|
+
class EasyOption {
|
12
|
+
|
13
|
+
/**
|
14
|
+
* options
|
15
|
+
* @type Array
|
16
|
+
*/
|
17
|
+
options = [];
|
18
|
+
|
19
|
+
/**
|
20
|
+
*
|
21
|
+
* @type {string|Function}
|
22
|
+
*/
|
23
|
+
labelKey;
|
24
|
+
|
25
|
+
/**
|
26
|
+
*
|
27
|
+
* @type {string|Function}
|
28
|
+
*/
|
29
|
+
valueKey;
|
30
|
+
|
31
|
+
/**
|
32
|
+
* 构建 Url
|
33
|
+
*/
|
34
|
+
buildUrl;
|
35
|
+
|
36
|
+
/**
|
37
|
+
* 构建 Url 参数
|
38
|
+
*/
|
39
|
+
buildUrlParams;
|
40
|
+
|
41
|
+
/**
|
42
|
+
* 默认选项
|
43
|
+
*/
|
44
|
+
defaultOptions;
|
45
|
+
|
46
|
+
/**
|
47
|
+
* req 对象
|
48
|
+
*/
|
49
|
+
req;
|
50
|
+
|
51
|
+
/**
|
52
|
+
*
|
53
|
+
* @param labelKey {string|Function}
|
54
|
+
* @param valueKey {string|Function}
|
55
|
+
* @param defaultOptions
|
56
|
+
* @param buildUrl
|
57
|
+
* @param buildUrlParams
|
58
|
+
*/
|
59
|
+
constructor({labelKey = "label", valueKey = "value", defaultOptions = [], buildUrl, buildUrlParams = {}} = {}) {
|
60
|
+
this.labelKey = labelKey;
|
61
|
+
this.valueKey = valueKey;
|
62
|
+
this.defaultOptions = defaultOptions;
|
63
|
+
this.buildUrl = buildUrl;
|
64
|
+
this.buildUrlParams = buildUrlParams;
|
65
|
+
this.req = useScxReq();
|
66
|
+
//如果只是普通的 options 我们直接刷新
|
67
|
+
if (isNull(this.buildUrl)) {
|
68
|
+
this.refresh();
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
async refresh() {
|
73
|
+
this.options = []; // 清空原数据
|
74
|
+
|
75
|
+
if (this.defaultOptions.length > 0) {
|
76
|
+
if (isObject(this.defaultOptions[0])) {
|
77
|
+
this.options = copyArray(this.defaultOptions); // 复制一下原数组防止产生引用影响
|
78
|
+
} else {
|
79
|
+
console.warn("检测到 options 元素 不为对象已自动转换 !!! ");
|
80
|
+
this.options = this.defaultOptions.map(o => {
|
81
|
+
const s = {};
|
82
|
+
s[this.labelKey] = o;
|
83
|
+
s[this.valueKey] = o;
|
84
|
+
return s;
|
85
|
+
});
|
86
|
+
}
|
87
|
+
}
|
88
|
+
if (notNull(this.buildUrl)) {
|
89
|
+
const data = await this.req.post(this.buildUrl, this.buildUrlParams);
|
90
|
+
this.options.push(...data.items);
|
91
|
+
}
|
92
|
+
return this;
|
93
|
+
}
|
94
|
+
|
95
|
+
getLabelByValue(value) {
|
96
|
+
if (Array.isArray(value)) {
|
97
|
+
const options = this.getByValue(value).map(o => this.labelSupplier(o));
|
98
|
+
return options.length > 0 ? options.join(", ") : "-";
|
99
|
+
} else {
|
100
|
+
const option = this.getByValue(value);
|
101
|
+
return option != null ? this.labelSupplier(option) : "-";
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
getByValue(value) {
|
106
|
+
if (Array.isArray(value)) {
|
107
|
+
return this.options.filter(c => myIncludes(value, this.valueSupplier(c)));
|
108
|
+
} else {
|
109
|
+
return this.options.find(c => myEqual(this.valueSupplier(c), value));
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
labelSupplier(c) {
|
114
|
+
if (isFunction(this.labelKey)) {
|
115
|
+
return this.labelKey(c);
|
116
|
+
} else {
|
117
|
+
return c[this.labelKey];
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
valueSupplier(c) {
|
122
|
+
if (isFunction(this.valueKey)) {
|
123
|
+
return this.valueKey(c);
|
124
|
+
} else {
|
125
|
+
return c[this.valueKey];
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
}
|
130
|
+
|
131
|
+
export {EasyOption};
|
package/scx/index.js
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
export * from "./ali-oss.js";
|
2
|
+
export * from "./auth-fetch.js";
|
3
|
+
export * from "./crud-context.js";
|
4
|
+
export * from "./easy-option.js";
|
5
|
+
export * from "./scx-auth.js";
|
6
|
+
export * from "./scx-config-manager.js";
|
7
|
+
export * from "./scx-router.js";
|
8
|
+
export * from "./scx-auth-info.js";
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import {inject} from "vue";
|
2
|
+
|
3
|
+
/**
|
4
|
+
* 用户信息类
|
5
|
+
*/
|
6
|
+
class ScxAuthInfo {
|
7
|
+
|
8
|
+
loginStatus = false; // 登录状态
|
9
|
+
user = {}; // 用户 id
|
10
|
+
perms = {};//权限
|
11
|
+
|
12
|
+
reset() {
|
13
|
+
this.user = {};
|
14
|
+
this.perms = {};
|
15
|
+
}
|
16
|
+
|
17
|
+
fill(rawOptions) {
|
18
|
+
this.user = rawOptions.user;
|
19
|
+
this.perms = rawOptions.perms;
|
20
|
+
return this;
|
21
|
+
}
|
22
|
+
|
23
|
+
install(app) {
|
24
|
+
app.provide(scxUserInfoKey, this);
|
25
|
+
}
|
26
|
+
|
27
|
+
}
|
28
|
+
|
29
|
+
|
30
|
+
/**
|
31
|
+
*
|
32
|
+
* @type {string}
|
33
|
+
*/
|
34
|
+
const scxUserInfoKey = "scx-user-info";
|
35
|
+
|
36
|
+
/**
|
37
|
+
*
|
38
|
+
* @returns {ScxAuthInfo}
|
39
|
+
*/
|
40
|
+
function useScxUserInfo() {
|
41
|
+
return inject(scxUserInfoKey);
|
42
|
+
}
|
43
|
+
|
44
|
+
export {
|
45
|
+
ScxAuthInfo,
|
46
|
+
useScxUserInfo,
|
47
|
+
scxUserInfoKey,
|
48
|
+
};
|