kouxiangtang 0.1.29 → 0.1.31
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/README.md +411 -411
- package/dist/{AttachmentUploader-Gl4uwpi0.js → AttachmentUploader-kjI75NG4.js} +16 -16
- package/dist/AttachmentUploader-kjI75NG4.js.map +1 -0
- package/dist/{ImageUploader-Ecxbu5yB.js → ImageUploader-CDBMZ9Q4.js} +15 -15
- package/dist/ImageUploader-CDBMZ9Q4.js.map +1 -0
- package/dist/{ImagesUploader-DiaKghBH.js → ImagesUploader-DR1NdrIX.js} +7 -7
- package/dist/ImagesUploader-DR1NdrIX.js.map +1 -0
- package/dist/{RichTextEditor-bJlEkb34.js → RichTextEditor-M8WpX6JI.js} +2 -2
- package/dist/{RichTextEditor-bJlEkb34.js.map → RichTextEditor-M8WpX6JI.js.map} +1 -1
- package/dist/color-DbNhHNpt.js.map +1 -1
- package/dist/{config-Bmby6rfL.js → config-2BP5-eb_.js} +5 -5
- package/dist/config-2BP5-eb_.js.map +1 -0
- package/dist/{config-DQerJfRt.js → config-BAjlIeLU.js} +2 -2
- package/dist/config-BAjlIeLU.js.map +1 -0
- package/dist/{config-ys3nFgYd.js → config-BQByyFaI.js} +2 -2
- package/dist/config-BQByyFaI.js.map +1 -0
- package/dist/{config-BMdtWu5R.js → config-CQA1bx3f.js} +15 -15
- package/dist/config-CQA1bx3f.js.map +1 -0
- package/dist/{config-CEbwLzea.js → config-CVao0Cla.js} +6 -6
- package/dist/config-CVao0Cla.js.map +1 -0
- package/dist/{config-Dr_SXi5U.js → config-CVslr70e.js} +2 -2
- package/dist/config-CVslr70e.js.map +1 -0
- package/dist/{config-C8MFDKwG.js → config-C_d1djj4.js} +2 -2
- package/dist/config-C_d1djj4.js.map +1 -0
- package/dist/{config-CDG1L4Oi.js → config-CqR0uCa_.js} +3 -3
- package/dist/config-CqR0uCa_.js.map +1 -0
- package/dist/{config-DSE87t_O.js → config-Csw0On0x.js} +8 -8
- package/dist/config-Csw0On0x.js.map +1 -0
- package/dist/{config-yVymOXO_.js → config-D_FDegBc.js} +2 -2
- package/dist/config-D_FDegBc.js.map +1 -0
- package/dist/{config-Xk01hDVk.js → config-DbXMEYLj.js} +2 -2
- package/dist/config-DbXMEYLj.js.map +1 -0
- package/dist/{config-Bbs_ly6P.js → config-Dq4y7P21.js} +2 -2
- package/dist/config-Dq4y7P21.js.map +1 -0
- package/dist/{config-B04hLt3e.js → config-HKkdk6wZ.js} +3 -3
- package/dist/config-HKkdk6wZ.js.map +1 -0
- package/dist/{config-KtTeOyV6.js → config-LPjXlVUG.js} +2 -2
- package/dist/config-LPjXlVUG.js.map +1 -0
- package/dist/{config-BNxcHvPM.js → config-Ob9gEzh5.js} +12 -12
- package/dist/config-Ob9gEzh5.js.map +1 -0
- package/dist/{config-Dh16WhJb.js → config-czbw2bDq.js} +14 -14
- package/dist/config-czbw2bDq.js.map +1 -0
- package/dist/{config-ssH8d7K9.js → config-d7n2dlpo.js} +2 -2
- package/dist/config-d7n2dlpo.js.map +1 -0
- package/dist/{config-DrJPQ_iz.js → config-h20uQgYE.js} +11 -11
- package/dist/config-h20uQgYE.js.map +1 -0
- package/dist/{config-BSYmo88x.js → config-jR1X5xVh.js} +2 -2
- package/dist/config-jR1X5xVh.js.map +1 -0
- package/dist/{config-CE-gN7KM.js → config-z9izRzg4.js} +15 -15
- package/dist/config-z9izRzg4.js.map +1 -0
- package/dist/{index-lFCbFvdk.js → index-DXK7K7iB.js} +78 -83
- package/dist/index-DXK7K7iB.js.map +1 -0
- package/dist/kouxiangtang.js +1 -1
- package/dist/kouxiangtang.umd.cjs +4 -4
- package/dist/kouxiangtang.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +56 -56
- package/dist/AttachmentUploader-Gl4uwpi0.js.map +0 -1
- package/dist/ImageUploader-Ecxbu5yB.js.map +0 -1
- package/dist/ImagesUploader-DiaKghBH.js.map +0 -1
- package/dist/config-B04hLt3e.js.map +0 -1
- package/dist/config-BMdtWu5R.js.map +0 -1
- package/dist/config-BNxcHvPM.js.map +0 -1
- package/dist/config-BSYmo88x.js.map +0 -1
- package/dist/config-Bbs_ly6P.js.map +0 -1
- package/dist/config-Bmby6rfL.js.map +0 -1
- package/dist/config-C8MFDKwG.js.map +0 -1
- package/dist/config-CDG1L4Oi.js.map +0 -1
- package/dist/config-CE-gN7KM.js.map +0 -1
- package/dist/config-CEbwLzea.js.map +0 -1
- package/dist/config-DQerJfRt.js.map +0 -1
- package/dist/config-DSE87t_O.js.map +0 -1
- package/dist/config-Dh16WhJb.js.map +0 -1
- package/dist/config-DrJPQ_iz.js.map +0 -1
- package/dist/config-Dr_SXi5U.js.map +0 -1
- package/dist/config-KtTeOyV6.js.map +0 -1
- package/dist/config-Xk01hDVk.js.map +0 -1
- package/dist/config-ssH8d7K9.js.map +0 -1
- package/dist/config-yVymOXO_.js.map +0 -1
- package/dist/config-ys3nFgYd.js.map +0 -1
- package/dist/index-lFCbFvdk.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,411 +1,411 @@
|
|
|
1
|
-
## kouxiangtang
|
|
2
|
-
|
|
3
|
-
### 介绍
|
|
4
|
-
`kouxiangtang` 通用的管理后台前端框架,此框架带有明确的后台数据管理目的。
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
### (一)安装使用
|
|
8
|
-
通过 `npm` 命令行安装
|
|
9
|
-
```
|
|
10
|
-
npm install kouxiangtang -S
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
### (二)定义一个领域模型(`domain`)
|
|
14
|
-
* src下创建`domains`文件夹
|
|
15
|
-
|
|
16
|
-
* 文件夹中创建 `config.js` ,export `domainConfigs`
|
|
17
|
-
``` JAVASCRIPT
|
|
18
|
-
const domainConfigs = {
|
|
19
|
-
admin: {
|
|
20
|
-
admins: { name: "管理员" },
|
|
21
|
-
user: { name: "用户" },
|
|
22
|
-
"city-users": { name: "城市用户统计" }
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export default domainConfigs;
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
* 创建如命名为`admin`文件夹,文件夹内包含页面结构信息
|
|
30
|
-
<img src="https://bloodcare-1251596343.cos.ap-shanghai.myqcloud.com/assets/mdImage/image-5.png" width="400" height="200" style="margin: 20px auto;">
|
|
31
|
-
|
|
32
|
-
* src下创建`layouts`文件夹
|
|
33
|
-
* layout.vue
|
|
34
|
-
|
|
35
|
-
``` HTML
|
|
36
|
-
<template>
|
|
37
|
-
<BaseLayout :config="props.config">
|
|
38
|
-
<template #user-profile>
|
|
39
|
-
<UserProfile />
|
|
40
|
-
</template>
|
|
41
|
-
</BaseLayout>
|
|
42
|
-
</template>
|
|
43
|
-
|
|
44
|
-
<script setup>
|
|
45
|
-
import { BaseLayout } from "kouxiangtang";
|
|
46
|
-
import UserProfile from "./UserProfile.vue";
|
|
47
|
-
|
|
48
|
-
const props = defineProps({
|
|
49
|
-
config: {
|
|
50
|
-
type: Object,
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
</script>
|
|
54
|
-
|
|
55
|
-
<style scoped lang="scss"></style>
|
|
56
|
-
```
|
|
57
|
-
* side-menus.js ,用于项目菜单管理。
|
|
58
|
-
|
|
59
|
-
``` javascript
|
|
60
|
-
import {
|
|
61
|
-
House,
|
|
62
|
-
PieChart,
|
|
63
|
-
Refrigerator,
|
|
64
|
-
Setting,
|
|
65
|
-
Location
|
|
66
|
-
} from "@element-plus/icons-vue";
|
|
67
|
-
|
|
68
|
-
const adminMenus = [
|
|
69
|
-
{ title: "首页", home: true, icon: House, route: "/admin/home" },
|
|
70
|
-
{ title: "统计", home: true, icon: PieChart, route: "/admin/statistics" },
|
|
71
|
-
{
|
|
72
|
-
title: "用户",
|
|
73
|
-
icon: User,
|
|
74
|
-
children: [
|
|
75
|
-
{ title: "用户", route: "/admin/user/list" },
|
|
76
|
-
{ title: "SSO", route: "/admin/user-sso/list" },
|
|
77
|
-
{ title: "城市用户统计", route: "/admin/city-users/list" },
|
|
78
|
-
{ title: "信息更正申请", route: "/admin/identity-update-apply/list" },
|
|
79
|
-
{ title: "登录日志", route: "/admin/user-login-ip/list" },
|
|
80
|
-
{ title: "黑名单", route: "/admin/black-list/list" },
|
|
81
|
-
],
|
|
82
|
-
}
|
|
83
|
-
];
|
|
84
|
-
|
|
85
|
-
export default {
|
|
86
|
-
admin: adminMenus,
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
* UserProfile.vue
|
|
92
|
-
|
|
93
|
-
``` HTML
|
|
94
|
-
<template>
|
|
95
|
-
<el-dropdown trigger="click">
|
|
96
|
-
<span class="username">
|
|
97
|
-
{{ currentUser }}
|
|
98
|
-
<el-icon class="el-icon--right">
|
|
99
|
-
<ArrowDown />
|
|
100
|
-
</el-icon>
|
|
101
|
-
</span>
|
|
102
|
-
<template #dropdown>
|
|
103
|
-
<el-dropdown-menu>
|
|
104
|
-
<el-dropdown-item @click="logout"> 退出</el-dropdown-item>
|
|
105
|
-
</el-dropdown-menu>
|
|
106
|
-
</template>
|
|
107
|
-
</el-dropdown>
|
|
108
|
-
</template>
|
|
109
|
-
|
|
110
|
-
<script setup>
|
|
111
|
-
import { useRouter } from "vue-router";
|
|
112
|
-
import { ArrowDown } from "@element-plus/icons-vue";
|
|
113
|
-
import { ref, watch } from "vue";
|
|
114
|
-
import adminApi from "@/requests/admin";
|
|
115
|
-
|
|
116
|
-
const router = useRouter();
|
|
117
|
-
const currentUser = ref("...");
|
|
118
|
-
|
|
119
|
-
function logout() {
|
|
120
|
-
ElMessageBox.confirm("确定注销并退出系统吗?", "提示", {
|
|
121
|
-
confirmButtonText: "确定",
|
|
122
|
-
cancelButtonText: "取消",
|
|
123
|
-
type: "warning",
|
|
124
|
-
}).then(() => {
|
|
125
|
-
localStorage.clear();
|
|
126
|
-
router.replace("/sso/login");
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
watch(
|
|
131
|
-
() => router.currentRoute.value,
|
|
132
|
-
() => {
|
|
133
|
-
currentUser.value = localStorage.getItem("currentUser");
|
|
134
|
-
},
|
|
135
|
-
{ immediate: true },
|
|
136
|
-
);
|
|
137
|
-
</script>
|
|
138
|
-
<style lang="scss" scoped>
|
|
139
|
-
.username {
|
|
140
|
-
cursor: pointer;
|
|
141
|
-
display: flex;
|
|
142
|
-
align-items: center;
|
|
143
|
-
}
|
|
144
|
-
</style>
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
### (三)每个领域模型都有列表页
|
|
149
|
-
<img src="https://bloodcare-1251596343.cos.ap-shanghai.myqcloud.com/assets/mdImage/image-6.png" width="400" height="200" style="margin: 20px auto;">
|
|
150
|
-
|
|
151
|
-
页面文件夹下fields.js
|
|
152
|
-
* 字段为列表,详情,编辑 通用字段
|
|
153
|
-
* 可通过`editable: true,`等属性控制具体的页面显示。`showInList: false,`等。
|
|
154
|
-
|
|
155
|
-
``` JAVASCRIPT
|
|
156
|
-
import SSOTenant from "./components/SSOTenant.vue";
|
|
157
|
-
import bannerTypes from "@/constants/banner-types";
|
|
158
|
-
|
|
159
|
-
const fields = [
|
|
160
|
-
{
|
|
161
|
-
code: "id",
|
|
162
|
-
label: "ID",
|
|
163
|
-
rowQuery: (row) => {
|
|
164
|
-
return { stationCode: row.code };
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
code: "indexLetter",
|
|
169
|
-
label: "索引",
|
|
170
|
-
width: 50,
|
|
171
|
-
editable: true,
|
|
172
|
-
showInList: false,
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
code: "enabled",
|
|
176
|
-
label: "启用",
|
|
177
|
-
type: "boolean",
|
|
178
|
-
width: 60,
|
|
179
|
-
editable: true,
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
code: "mode",
|
|
183
|
-
label: "首页模版",
|
|
184
|
-
editable: true,
|
|
185
|
-
type: "select",
|
|
186
|
-
options: () =>
|
|
187
|
-
bannerTypes.filter((item) => {
|
|
188
|
-
return item.code?.toString().charAt(0) == 6;
|
|
189
|
-
}),
|
|
190
|
-
width: 150,
|
|
191
|
-
},
|
|
192
|
-
{ code: "createdAt", label: "创建时间" },
|
|
193
|
-
{ code: "updatedAt", label: "更新时间" },
|
|
194
|
-
];
|
|
195
|
-
|
|
196
|
-
export default fields;
|
|
197
|
-
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### (四)每个领域模型都有详情页
|
|
201
|
-
```javascript
|
|
202
|
-
{
|
|
203
|
-
code: "id",
|
|
204
|
-
label: "ID",
|
|
205
|
-
rowQuery: (row) => {
|
|
206
|
-
return { stationCode: row.code };
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
### (五)每个领域模型根据 `API` 接口情况提供标准的增删改查的操作
|
|
212
|
-
页面文件夹下rest.js
|
|
213
|
-
* 为领域下的接口请求,`getList` `update` `create` 等。
|
|
214
|
-
|
|
215
|
-
``` JAVASCRIPT
|
|
216
|
-
import http from "@/utils/http";
|
|
217
|
-
|
|
218
|
-
function getList(data) {
|
|
219
|
-
return http.get("stations", data).then((res) => ({ data: res }));
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
function getOne({ id }) {
|
|
223
|
-
return http.get(`stations/${id}`).then((res) => ({ data: res }));
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
function update(station) {
|
|
227
|
-
return http.put(`stations/${station.id}`, station);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
function create(station) {
|
|
231
|
-
return http.post("stations", station);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function getBound(data) {
|
|
235
|
-
return http.get("station-customers/binds", data);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
function getUnbound() {
|
|
239
|
-
return http.get("station-customers/unbound");
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function updateStationCustomers(data) {
|
|
243
|
-
return http.put(`station-customers/${data.id}/bind`, data);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
function removeStationCustomers(id) {
|
|
247
|
-
return http.remove(`station-customers/${id}/bind`);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function bindStationCustomers(data) {
|
|
251
|
-
return http.post(`station-customers/bind`, data);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
export default {
|
|
255
|
-
getList,
|
|
256
|
-
getOne,
|
|
257
|
-
update,
|
|
258
|
-
create,
|
|
259
|
-
getBound,
|
|
260
|
-
getUnbound,
|
|
261
|
-
updateStationCustomers,
|
|
262
|
-
removeStationCustomers,
|
|
263
|
-
bindStationCustomers,
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
### (六)列表页提供可配置的数据过滤方式
|
|
270
|
-
页面文件夹下filters.js
|
|
271
|
-
* 为领域下的设置搜索条件。
|
|
272
|
-
``` JAVASCRIPT
|
|
273
|
-
import http from "@/utils/http";
|
|
274
|
-
|
|
275
|
-
const filters = {
|
|
276
|
-
name: {
|
|
277
|
-
name: "名称",
|
|
278
|
-
},
|
|
279
|
-
cityCode: {
|
|
280
|
-
name: "城市",
|
|
281
|
-
},
|
|
282
|
-
enabled: {
|
|
283
|
-
name: "启用",
|
|
284
|
-
type: "boolean",
|
|
285
|
-
},
|
|
286
|
-
defaultStation: {
|
|
287
|
-
name: "默认",
|
|
288
|
-
type: "boolean",
|
|
289
|
-
},
|
|
290
|
-
hasLocalService: {
|
|
291
|
-
name: "开通服务",
|
|
292
|
-
type: "boolean",
|
|
293
|
-
},
|
|
294
|
-
isPriority: {
|
|
295
|
-
name: "重要客户",
|
|
296
|
-
type: "boolean",
|
|
297
|
-
},
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
export default filters;
|
|
301
|
-
|
|
302
|
-
```
|
|
303
|
-
### (七)提供针对列表页数据集的批量操作(`PageAction`)
|
|
304
|
-
页面文件夹下page-actions.js
|
|
305
|
-
* 为列表数据集的批量操作。
|
|
306
|
-
``` JAVASCRIPT
|
|
307
|
-
import Test from "./components/Test.vue";
|
|
308
|
-
|
|
309
|
-
const pageActions = [
|
|
310
|
-
{
|
|
311
|
-
name: "敏感词测试",
|
|
312
|
-
component: Test,
|
|
313
|
-
},
|
|
314
|
-
];
|
|
315
|
-
|
|
316
|
-
export default pageActions;
|
|
317
|
-
|
|
318
|
-
```
|
|
319
|
-
### (八)提供针对单条数据的操作(`RowAction`)
|
|
320
|
-
页面文件夹下row-actions.js
|
|
321
|
-
* 为针对单挑数据操作。
|
|
322
|
-
``` JAVASCRIPT
|
|
323
|
-
import RegionEditor from "./components/ToExamine.vue";
|
|
324
|
-
|
|
325
|
-
const rowActions = [
|
|
326
|
-
{
|
|
327
|
-
component: RegionEditor,
|
|
328
|
-
isVisible: (data) => {
|
|
329
|
-
return true;
|
|
330
|
-
},
|
|
331
|
-
},
|
|
332
|
-
];
|
|
333
|
-
|
|
334
|
-
export default rowActions;
|
|
335
|
-
```
|
|
336
|
-
### (九)提供针对数据关联的显示
|
|
337
|
-
|
|
338
|
-
* 从属于:`belongs-to`
|
|
339
|
-
|
|
340
|
-
* 为跳转到其他功能的详情页面。
|
|
341
|
-
``` JAVASCRIPT
|
|
342
|
-
{
|
|
343
|
-
code: "messageRuleId",
|
|
344
|
-
label: "规则名称",
|
|
345
|
-
width: 150,
|
|
346
|
-
type: "belongs-to",
|
|
347
|
-
belongsTo: "message-send-rule",
|
|
348
|
-
},
|
|
349
|
-
|
|
350
|
-
```
|
|
351
|
-
* `belongs-to`对应为目标功能页面的code
|
|
352
|
-
``` JAVASCRIPT
|
|
353
|
-
export default defineDomain("admin", {
|
|
354
|
-
name: "消息发送规则",
|
|
355
|
-
code: "message-send-rule",
|
|
356
|
-
fields,
|
|
357
|
-
filters,
|
|
358
|
-
rest,
|
|
359
|
-
hasMany: ["message-push"],
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
* 一对多:`has-many`。
|
|
365
|
-
* 功能页面 `config.js` 配置 `hasMany` ,对应为此功能页面的子功能。
|
|
366
|
-
* 可以为系统内的任何其他功能页面,hasMany对应数组,item为子功能的code。
|
|
367
|
-
|
|
368
|
-
``` JAVASCRIPT
|
|
369
|
-
import { defineDomain } from "kouxiangtang";
|
|
370
|
-
import rest from "./rest.js";
|
|
371
|
-
import fields from "./fields.js";
|
|
372
|
-
import filters from "./filters.js";
|
|
373
|
-
import rowActions from "./row-actions.js";
|
|
374
|
-
|
|
375
|
-
export default defineDomain("admin", {
|
|
376
|
-
name: "资产",
|
|
377
|
-
code: "currency",
|
|
378
|
-
fields,
|
|
379
|
-
rest,
|
|
380
|
-
filters,
|
|
381
|
-
rowActions,
|
|
382
|
-
actionsWidth: 240,
|
|
383
|
-
hasMany: ["account", "asset-details", "rewards-rules"],
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
```
|
|
387
|
-
* 如下图
|
|
388
|
-

|
|
389
|
-
### (十)组件的使用
|
|
390
|
-
页面文件夹下`components`
|
|
391
|
-
|
|
392
|
-

|
|
393
|
-
* 使用组件示例。
|
|
394
|
-
|
|
395
|
-
``` JAVASCRIPT
|
|
396
|
-
import Approved from "./components/Approved.vue";
|
|
397
|
-
|
|
398
|
-
const rowActions = [
|
|
399
|
-
{
|
|
400
|
-
component: Approved,
|
|
401
|
-
isVisible: (data) => {
|
|
402
|
-
return true;
|
|
403
|
-
},
|
|
404
|
-
},
|
|
405
|
-
];
|
|
406
|
-
|
|
407
|
-
export default rowActions;
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
1
|
+
## kouxiangtang
|
|
2
|
+
|
|
3
|
+
### 介绍
|
|
4
|
+
`kouxiangtang` 通用的管理后台前端框架,此框架带有明确的后台数据管理目的。
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
### (一)安装使用
|
|
8
|
+
通过 `npm` 命令行安装
|
|
9
|
+
```
|
|
10
|
+
npm install kouxiangtang -S
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### (二)定义一个领域模型(`domain`)
|
|
14
|
+
* src下创建`domains`文件夹
|
|
15
|
+
|
|
16
|
+
* 文件夹中创建 `config.js` ,export `domainConfigs`
|
|
17
|
+
``` JAVASCRIPT
|
|
18
|
+
const domainConfigs = {
|
|
19
|
+
admin: {
|
|
20
|
+
admins: { name: "管理员" },
|
|
21
|
+
user: { name: "用户" },
|
|
22
|
+
"city-users": { name: "城市用户统计" }
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default domainConfigs;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
* 创建如命名为`admin`文件夹,文件夹内包含页面结构信息
|
|
30
|
+
<img src="https://bloodcare-1251596343.cos.ap-shanghai.myqcloud.com/assets/mdImage/image-5.png" width="400" height="200" style="margin: 20px auto;">
|
|
31
|
+
|
|
32
|
+
* src下创建`layouts`文件夹
|
|
33
|
+
* layout.vue
|
|
34
|
+
|
|
35
|
+
``` HTML
|
|
36
|
+
<template>
|
|
37
|
+
<BaseLayout :config="props.config">
|
|
38
|
+
<template #user-profile>
|
|
39
|
+
<UserProfile />
|
|
40
|
+
</template>
|
|
41
|
+
</BaseLayout>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<script setup>
|
|
45
|
+
import { BaseLayout } from "kouxiangtang";
|
|
46
|
+
import UserProfile from "./UserProfile.vue";
|
|
47
|
+
|
|
48
|
+
const props = defineProps({
|
|
49
|
+
config: {
|
|
50
|
+
type: Object,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<style scoped lang="scss"></style>
|
|
56
|
+
```
|
|
57
|
+
* side-menus.js ,用于项目菜单管理。
|
|
58
|
+
|
|
59
|
+
``` javascript
|
|
60
|
+
import {
|
|
61
|
+
House,
|
|
62
|
+
PieChart,
|
|
63
|
+
Refrigerator,
|
|
64
|
+
Setting,
|
|
65
|
+
Location
|
|
66
|
+
} from "@element-plus/icons-vue";
|
|
67
|
+
|
|
68
|
+
const adminMenus = [
|
|
69
|
+
{ title: "首页", home: true, icon: House, route: "/admin/home" },
|
|
70
|
+
{ title: "统计", home: true, icon: PieChart, route: "/admin/statistics" },
|
|
71
|
+
{
|
|
72
|
+
title: "用户",
|
|
73
|
+
icon: User,
|
|
74
|
+
children: [
|
|
75
|
+
{ title: "用户", route: "/admin/user/list" },
|
|
76
|
+
{ title: "SSO", route: "/admin/user-sso/list" },
|
|
77
|
+
{ title: "城市用户统计", route: "/admin/city-users/list" },
|
|
78
|
+
{ title: "信息更正申请", route: "/admin/identity-update-apply/list" },
|
|
79
|
+
{ title: "登录日志", route: "/admin/user-login-ip/list" },
|
|
80
|
+
{ title: "黑名单", route: "/admin/black-list/list" },
|
|
81
|
+
],
|
|
82
|
+
}
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
export default {
|
|
86
|
+
admin: adminMenus,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
* UserProfile.vue
|
|
92
|
+
|
|
93
|
+
``` HTML
|
|
94
|
+
<template>
|
|
95
|
+
<el-dropdown trigger="click">
|
|
96
|
+
<span class="username">
|
|
97
|
+
{{ currentUser }}
|
|
98
|
+
<el-icon class="el-icon--right">
|
|
99
|
+
<ArrowDown />
|
|
100
|
+
</el-icon>
|
|
101
|
+
</span>
|
|
102
|
+
<template #dropdown>
|
|
103
|
+
<el-dropdown-menu>
|
|
104
|
+
<el-dropdown-item @click="logout"> 退出</el-dropdown-item>
|
|
105
|
+
</el-dropdown-menu>
|
|
106
|
+
</template>
|
|
107
|
+
</el-dropdown>
|
|
108
|
+
</template>
|
|
109
|
+
|
|
110
|
+
<script setup>
|
|
111
|
+
import { useRouter } from "vue-router";
|
|
112
|
+
import { ArrowDown } from "@element-plus/icons-vue";
|
|
113
|
+
import { ref, watch } from "vue";
|
|
114
|
+
import adminApi from "@/requests/admin";
|
|
115
|
+
|
|
116
|
+
const router = useRouter();
|
|
117
|
+
const currentUser = ref("...");
|
|
118
|
+
|
|
119
|
+
function logout() {
|
|
120
|
+
ElMessageBox.confirm("确定注销并退出系统吗?", "提示", {
|
|
121
|
+
confirmButtonText: "确定",
|
|
122
|
+
cancelButtonText: "取消",
|
|
123
|
+
type: "warning",
|
|
124
|
+
}).then(() => {
|
|
125
|
+
localStorage.clear();
|
|
126
|
+
router.replace("/sso/login");
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
watch(
|
|
131
|
+
() => router.currentRoute.value,
|
|
132
|
+
() => {
|
|
133
|
+
currentUser.value = localStorage.getItem("currentUser");
|
|
134
|
+
},
|
|
135
|
+
{ immediate: true },
|
|
136
|
+
);
|
|
137
|
+
</script>
|
|
138
|
+
<style lang="scss" scoped>
|
|
139
|
+
.username {
|
|
140
|
+
cursor: pointer;
|
|
141
|
+
display: flex;
|
|
142
|
+
align-items: center;
|
|
143
|
+
}
|
|
144
|
+
</style>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
### (三)每个领域模型都有列表页
|
|
149
|
+
<img src="https://bloodcare-1251596343.cos.ap-shanghai.myqcloud.com/assets/mdImage/image-6.png" width="400" height="200" style="margin: 20px auto;">
|
|
150
|
+
|
|
151
|
+
页面文件夹下fields.js
|
|
152
|
+
* 字段为列表,详情,编辑 通用字段
|
|
153
|
+
* 可通过`editable: true,`等属性控制具体的页面显示。`showInList: false,`等。
|
|
154
|
+
|
|
155
|
+
``` JAVASCRIPT
|
|
156
|
+
import SSOTenant from "./components/SSOTenant.vue";
|
|
157
|
+
import bannerTypes from "@/constants/banner-types";
|
|
158
|
+
|
|
159
|
+
const fields = [
|
|
160
|
+
{
|
|
161
|
+
code: "id",
|
|
162
|
+
label: "ID",
|
|
163
|
+
rowQuery: (row) => {
|
|
164
|
+
return { stationCode: row.code };
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
code: "indexLetter",
|
|
169
|
+
label: "索引",
|
|
170
|
+
width: 50,
|
|
171
|
+
editable: true,
|
|
172
|
+
showInList: false,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
code: "enabled",
|
|
176
|
+
label: "启用",
|
|
177
|
+
type: "boolean",
|
|
178
|
+
width: 60,
|
|
179
|
+
editable: true,
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
code: "mode",
|
|
183
|
+
label: "首页模版",
|
|
184
|
+
editable: true,
|
|
185
|
+
type: "select",
|
|
186
|
+
options: () =>
|
|
187
|
+
bannerTypes.filter((item) => {
|
|
188
|
+
return item.code?.toString().charAt(0) == 6;
|
|
189
|
+
}),
|
|
190
|
+
width: 150,
|
|
191
|
+
},
|
|
192
|
+
{ code: "createdAt", label: "创建时间" },
|
|
193
|
+
{ code: "updatedAt", label: "更新时间" },
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
export default fields;
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### (四)每个领域模型都有详情页
|
|
201
|
+
```javascript
|
|
202
|
+
{
|
|
203
|
+
code: "id",
|
|
204
|
+
label: "ID",
|
|
205
|
+
rowQuery: (row) => {
|
|
206
|
+
return { stationCode: row.code };
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### (五)每个领域模型根据 `API` 接口情况提供标准的增删改查的操作
|
|
212
|
+
页面文件夹下rest.js
|
|
213
|
+
* 为领域下的接口请求,`getList` `update` `create` 等。
|
|
214
|
+
|
|
215
|
+
``` JAVASCRIPT
|
|
216
|
+
import http from "@/utils/http";
|
|
217
|
+
|
|
218
|
+
function getList(data) {
|
|
219
|
+
return http.get("stations", data).then((res) => ({ data: res }));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function getOne({ id }) {
|
|
223
|
+
return http.get(`stations/${id}`).then((res) => ({ data: res }));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function update(station) {
|
|
227
|
+
return http.put(`stations/${station.id}`, station);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function create(station) {
|
|
231
|
+
return http.post("stations", station);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function getBound(data) {
|
|
235
|
+
return http.get("station-customers/binds", data);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function getUnbound() {
|
|
239
|
+
return http.get("station-customers/unbound");
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function updateStationCustomers(data) {
|
|
243
|
+
return http.put(`station-customers/${data.id}/bind`, data);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function removeStationCustomers(id) {
|
|
247
|
+
return http.remove(`station-customers/${id}/bind`);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function bindStationCustomers(data) {
|
|
251
|
+
return http.post(`station-customers/bind`, data);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export default {
|
|
255
|
+
getList,
|
|
256
|
+
getOne,
|
|
257
|
+
update,
|
|
258
|
+
create,
|
|
259
|
+
getBound,
|
|
260
|
+
getUnbound,
|
|
261
|
+
updateStationCustomers,
|
|
262
|
+
removeStationCustomers,
|
|
263
|
+
bindStationCustomers,
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### (六)列表页提供可配置的数据过滤方式
|
|
270
|
+
页面文件夹下filters.js
|
|
271
|
+
* 为领域下的设置搜索条件。
|
|
272
|
+
``` JAVASCRIPT
|
|
273
|
+
import http from "@/utils/http";
|
|
274
|
+
|
|
275
|
+
const filters = {
|
|
276
|
+
name: {
|
|
277
|
+
name: "名称",
|
|
278
|
+
},
|
|
279
|
+
cityCode: {
|
|
280
|
+
name: "城市",
|
|
281
|
+
},
|
|
282
|
+
enabled: {
|
|
283
|
+
name: "启用",
|
|
284
|
+
type: "boolean",
|
|
285
|
+
},
|
|
286
|
+
defaultStation: {
|
|
287
|
+
name: "默认",
|
|
288
|
+
type: "boolean",
|
|
289
|
+
},
|
|
290
|
+
hasLocalService: {
|
|
291
|
+
name: "开通服务",
|
|
292
|
+
type: "boolean",
|
|
293
|
+
},
|
|
294
|
+
isPriority: {
|
|
295
|
+
name: "重要客户",
|
|
296
|
+
type: "boolean",
|
|
297
|
+
},
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
export default filters;
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
### (七)提供针对列表页数据集的批量操作(`PageAction`)
|
|
304
|
+
页面文件夹下page-actions.js
|
|
305
|
+
* 为列表数据集的批量操作。
|
|
306
|
+
``` JAVASCRIPT
|
|
307
|
+
import Test from "./components/Test.vue";
|
|
308
|
+
|
|
309
|
+
const pageActions = [
|
|
310
|
+
{
|
|
311
|
+
name: "敏感词测试",
|
|
312
|
+
component: Test,
|
|
313
|
+
},
|
|
314
|
+
];
|
|
315
|
+
|
|
316
|
+
export default pageActions;
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
### (八)提供针对单条数据的操作(`RowAction`)
|
|
320
|
+
页面文件夹下row-actions.js
|
|
321
|
+
* 为针对单挑数据操作。
|
|
322
|
+
``` JAVASCRIPT
|
|
323
|
+
import RegionEditor from "./components/ToExamine.vue";
|
|
324
|
+
|
|
325
|
+
const rowActions = [
|
|
326
|
+
{
|
|
327
|
+
component: RegionEditor,
|
|
328
|
+
isVisible: (data) => {
|
|
329
|
+
return true;
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
];
|
|
333
|
+
|
|
334
|
+
export default rowActions;
|
|
335
|
+
```
|
|
336
|
+
### (九)提供针对数据关联的显示
|
|
337
|
+
|
|
338
|
+
* 从属于:`belongs-to`
|
|
339
|
+
|
|
340
|
+
* 为跳转到其他功能的详情页面。
|
|
341
|
+
``` JAVASCRIPT
|
|
342
|
+
{
|
|
343
|
+
code: "messageRuleId",
|
|
344
|
+
label: "规则名称",
|
|
345
|
+
width: 150,
|
|
346
|
+
type: "belongs-to",
|
|
347
|
+
belongsTo: "message-send-rule",
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
* `belongs-to`对应为目标功能页面的code
|
|
352
|
+
``` JAVASCRIPT
|
|
353
|
+
export default defineDomain("admin", {
|
|
354
|
+
name: "消息发送规则",
|
|
355
|
+
code: "message-send-rule",
|
|
356
|
+
fields,
|
|
357
|
+
filters,
|
|
358
|
+
rest,
|
|
359
|
+
hasMany: ["message-push"],
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
* 一对多:`has-many`。
|
|
365
|
+
* 功能页面 `config.js` 配置 `hasMany` ,对应为此功能页面的子功能。
|
|
366
|
+
* 可以为系统内的任何其他功能页面,hasMany对应数组,item为子功能的code。
|
|
367
|
+
|
|
368
|
+
``` JAVASCRIPT
|
|
369
|
+
import { defineDomain } from "kouxiangtang";
|
|
370
|
+
import rest from "./rest.js";
|
|
371
|
+
import fields from "./fields.js";
|
|
372
|
+
import filters from "./filters.js";
|
|
373
|
+
import rowActions from "./row-actions.js";
|
|
374
|
+
|
|
375
|
+
export default defineDomain("admin", {
|
|
376
|
+
name: "资产",
|
|
377
|
+
code: "currency",
|
|
378
|
+
fields,
|
|
379
|
+
rest,
|
|
380
|
+
filters,
|
|
381
|
+
rowActions,
|
|
382
|
+
actionsWidth: 240,
|
|
383
|
+
hasMany: ["account", "asset-details", "rewards-rules"],
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
```
|
|
387
|
+
* 如下图
|
|
388
|
+

|
|
389
|
+
### (十)组件的使用
|
|
390
|
+
页面文件夹下`components`
|
|
391
|
+
|
|
392
|
+

|
|
393
|
+
* 使用组件示例。
|
|
394
|
+
|
|
395
|
+
``` JAVASCRIPT
|
|
396
|
+
import Approved from "./components/Approved.vue";
|
|
397
|
+
|
|
398
|
+
const rowActions = [
|
|
399
|
+
{
|
|
400
|
+
component: Approved,
|
|
401
|
+
isVisible: (data) => {
|
|
402
|
+
return true;
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
];
|
|
406
|
+
|
|
407
|
+
export default rowActions;
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
|