@isxiaoyuan/elpis 1.0.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/.eslintignore +3 -0
- package/.eslintrc +52 -0
- package/.vscode/settings.json +8 -0
- package/REMADE.md +228 -0
- package/app/controller/base.js +43 -0
- package/app/controller/project.js +106 -0
- package/app/controller/view.js +21 -0
- package/app/extend/logger.js +36 -0
- package/app/middleware/api-params-verify.js +73 -0
- package/app/middleware/api-sign-verify.js +43 -0
- package/app/middleware/error-handler.js +33 -0
- package/app/middleware/project-handle.js +26 -0
- package/app/middleware.js +41 -0
- package/app/pages/asserts/custom.css +11 -0
- package/app/pages/boot.js +43 -0
- package/app/pages/common/curl.js +88 -0
- package/app/pages/common/utils.js +2 -0
- package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +19 -0
- package/app/pages/dashboard/complex-view/header-view/header-view.vue +138 -0
- package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +51 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +41 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +128 -0
- package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +20 -0
- package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +95 -0
- package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +98 -0
- package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +123 -0
- package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +129 -0
- package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +98 -0
- package/app/pages/dashboard/complex-view/silder-view/silder-view.vue +127 -0
- package/app/pages/dashboard/dashboard.vue +96 -0
- package/app/pages/dashboard/entry.dashboard.js +48 -0
- package/app/pages/store/index.js +5 -0
- package/app/pages/store/menu.js +70 -0
- package/app/pages/store/project.js +17 -0
- package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
- package/app/pages/widgets/header-container/asserts/logo.png +0 -0
- package/app/pages/widgets/header-container/header-container.vue +102 -0
- package/app/pages/widgets/schema-form/complex-view/input/input.vue +137 -0
- package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +136 -0
- package/app/pages/widgets/schema-form/complex-view/select/select.vue +122 -0
- package/app/pages/widgets/schema-form/form-item-config.js +20 -0
- package/app/pages/widgets/schema-form/schema-form.vue +136 -0
- package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +55 -0
- package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +69 -0
- package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +45 -0
- package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +53 -0
- package/app/pages/widgets/schema-search-bar/schema-item-config.js +24 -0
- package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +115 -0
- package/app/pages/widgets/schema-table/schema-table.vue +255 -0
- package/app/pages/widgets/sider-container/complex-view/sub-menu/sub-menu.vue +18 -0
- package/app/pages/widgets/sider-container/sider-container.vue +29 -0
- package/app/public/dist/entry.dashboard.tpl +27 -0
- package/app/public/dist/entry.page1.tpl +25 -0
- package/app/public/dist/entry.page2.tpl +25 -0
- package/app/public/dist/entry.project-list.tpl +27 -0
- package/app/public/static/logo.png +0 -0
- package/app/public/static/normalize.css +239 -0
- package/app/router/project.js +12 -0
- package/app/router/view.js +7 -0
- package/app/router-schema/project.js +30 -0
- package/app/service/base.js +13 -0
- package/app/service/project.js +58 -0
- package/app/view/entry.tpl +27 -0
- package/app/webpack/config/webpack.base.js +305 -0
- package/app/webpack/config/webpack.dev.js +62 -0
- package/app/webpack/config/webpack.prod.js +120 -0
- package/app/webpack/dev.js +62 -0
- package/app/webpack/libs/blank.js +1 -0
- package/app/webpack/prod.js +22 -0
- package/config/config.beta.js +3 -0
- package/config/config.default.js +3 -0
- package/config/config.prod.js +3 -0
- package/elpis-core/env.js +20 -0
- package/elpis-core/index.js +97 -0
- package/elpis-core/loader/config.js +66 -0
- package/elpis-core/loader/controller.js +86 -0
- package/elpis-core/loader/extend.js +66 -0
- package/elpis-core/loader/middleware.js +74 -0
- package/elpis-core/loader/router-schema.js +56 -0
- package/elpis-core/loader/router.js +49 -0
- package/elpis-core/loader/service.js +82 -0
- package/index.js +42 -0
- package/model/index.js +109 -0
- package/package.json +92 -0
- package/test/controller/project.test.js +188 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-drawer
|
|
3
|
+
v-model="isShow"
|
|
4
|
+
direction="rtl"
|
|
5
|
+
:destroy-on-close="true"
|
|
6
|
+
:size="550"
|
|
7
|
+
>
|
|
8
|
+
<template #header>
|
|
9
|
+
<h3>{{ title }}</h3>
|
|
10
|
+
</template>
|
|
11
|
+
<template #default>
|
|
12
|
+
<el-card v-loading="loading" shadow="always" class="detail-panel">
|
|
13
|
+
<el-row
|
|
14
|
+
v-for="(item, key) in components[name]?.schema?.properties"
|
|
15
|
+
:key="key"
|
|
16
|
+
type="flex"
|
|
17
|
+
align="middle"
|
|
18
|
+
class="row-item"
|
|
19
|
+
>
|
|
20
|
+
<el-row class="item-label">{{ item.label }}:</el-row>
|
|
21
|
+
<el-row class="item-value">{{ dtoModel[key] }}</el-row>
|
|
22
|
+
</el-row>
|
|
23
|
+
</el-card>
|
|
24
|
+
</template>
|
|
25
|
+
<template #footer> </template>
|
|
26
|
+
</el-drawer>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<script setup>
|
|
30
|
+
import { ref, inject } from "vue";
|
|
31
|
+
import $curl from "$elpisCommon/curl.js";
|
|
32
|
+
|
|
33
|
+
const name = ref("detailPanel");
|
|
34
|
+
const { api, components } = inject("schemaViewData");
|
|
35
|
+
const isShow = ref(false);
|
|
36
|
+
const title = ref("");
|
|
37
|
+
const mainKey = ref("");
|
|
38
|
+
const mainValue = ref("");
|
|
39
|
+
const dtoModel = ref({});
|
|
40
|
+
const loading = ref(false);
|
|
41
|
+
|
|
42
|
+
const show = (rowData) => {
|
|
43
|
+
const { config } = components.value[name.value];
|
|
44
|
+
title.value = config.title;
|
|
45
|
+
mainKey.value = config.mainKey;
|
|
46
|
+
mainValue.value = rowData[mainKey.value];
|
|
47
|
+
dtoModel.value = {};
|
|
48
|
+
|
|
49
|
+
isShow.value = true;
|
|
50
|
+
|
|
51
|
+
fetchFormData();
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const fetchFormData = async () => {
|
|
55
|
+
if (loading.value) return;
|
|
56
|
+
loading.value = true;
|
|
57
|
+
try {
|
|
58
|
+
const res = await $curl({
|
|
59
|
+
url: api.value,
|
|
60
|
+
method: "get",
|
|
61
|
+
query: {
|
|
62
|
+
[mainKey.value]: mainValue.value,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
if (res && res.success) {
|
|
66
|
+
dtoModel.value = res.data;
|
|
67
|
+
}
|
|
68
|
+
loading.value = false;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
loading.value = false;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
defineExpose({
|
|
75
|
+
name,
|
|
76
|
+
show,
|
|
77
|
+
});
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<style scoped lang="less">
|
|
81
|
+
.detail-panel {
|
|
82
|
+
border: 1px solid #a6a6a6;
|
|
83
|
+
padding: 30px;
|
|
84
|
+
.row-item {
|
|
85
|
+
height: 40px;
|
|
86
|
+
line-height: 40px;
|
|
87
|
+
font-size: 20px;
|
|
88
|
+
.item-label {
|
|
89
|
+
margin-right: 20px;
|
|
90
|
+
width: 120px;
|
|
91
|
+
color: #fff;
|
|
92
|
+
}
|
|
93
|
+
.item-value {
|
|
94
|
+
color: #d2dae4;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
</style>
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-drawer
|
|
3
|
+
v-model="isShow"
|
|
4
|
+
direction="rtl"
|
|
5
|
+
:destroy-on-close="true"
|
|
6
|
+
:size="550"
|
|
7
|
+
>
|
|
8
|
+
<template #header>
|
|
9
|
+
<h3>{{ title }}</h3>
|
|
10
|
+
</template>
|
|
11
|
+
<template #default>
|
|
12
|
+
<schema-form
|
|
13
|
+
v-loading="loading"
|
|
14
|
+
ref="schemaFormRef"
|
|
15
|
+
:schema="components[name]?.schema"
|
|
16
|
+
:model="dtoModel"
|
|
17
|
+
/>
|
|
18
|
+
</template>
|
|
19
|
+
<template #footer>
|
|
20
|
+
<el-button type="primary" @click="save">{{ saveBtnText }}</el-button>
|
|
21
|
+
</template>
|
|
22
|
+
</el-drawer>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup>
|
|
26
|
+
import { ref, inject } from "vue";
|
|
27
|
+
import { ElNotification } from "element-plus";
|
|
28
|
+
import $curl from "$elpisCommon/curl.js";
|
|
29
|
+
import SchemaForm from "$elpisWidgets/schema-form/schema-form.vue";
|
|
30
|
+
|
|
31
|
+
const { api, components } = inject("schemaViewData");
|
|
32
|
+
|
|
33
|
+
const emit = defineEmits(["command"]);
|
|
34
|
+
|
|
35
|
+
const name = ref("editForm");
|
|
36
|
+
|
|
37
|
+
const isShow = ref(false);
|
|
38
|
+
const loading = ref(false);
|
|
39
|
+
const title = ref("");
|
|
40
|
+
const saveBtnText = ref("");
|
|
41
|
+
const mainKey = ref("");
|
|
42
|
+
const mainValue = ref();
|
|
43
|
+
const dtoModel = ref({});
|
|
44
|
+
const schemaFormRef = ref(null);
|
|
45
|
+
|
|
46
|
+
const show = (rowData) => {
|
|
47
|
+
const { config } = components.value[name.value];
|
|
48
|
+
|
|
49
|
+
title.value = config.title;
|
|
50
|
+
saveBtnText.value = config.saveBtnText;
|
|
51
|
+
mainKey.value = config.mainKey; // 表单主键
|
|
52
|
+
mainValue.value = rowData[config.mainKey]; // 主键值
|
|
53
|
+
dtoModel.value = {};
|
|
54
|
+
|
|
55
|
+
isShow.value = true;
|
|
56
|
+
|
|
57
|
+
fetchFormData();
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const close = () => {
|
|
61
|
+
isShow.value = false;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const fetchFormData = async () => {
|
|
65
|
+
if (loading.value) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
loading.value = true;
|
|
69
|
+
try {
|
|
70
|
+
const res = await $curl({
|
|
71
|
+
url: api.value,
|
|
72
|
+
method: "get",
|
|
73
|
+
query: {
|
|
74
|
+
[mainKey.value]: mainValue.value,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
dtoModel.value = res.data;
|
|
78
|
+
loading.value = false;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
loading.value = false;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const save = async () => {
|
|
85
|
+
if (loading.value) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (!schemaFormRef.value.validate()) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
loading.value = true;
|
|
92
|
+
try {
|
|
93
|
+
const res = await $curl({
|
|
94
|
+
url: api.value,
|
|
95
|
+
method: "put",
|
|
96
|
+
data: {
|
|
97
|
+
[mainKey.value]: mainValue.value,
|
|
98
|
+
...schemaFormRef.value.getValue(),
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
dtoModel.value = res.data;
|
|
102
|
+
ElNotification({
|
|
103
|
+
title: "修改成功",
|
|
104
|
+
message: "修改成功",
|
|
105
|
+
type: "success",
|
|
106
|
+
});
|
|
107
|
+
close();
|
|
108
|
+
loading.value = false;
|
|
109
|
+
emit("command", {
|
|
110
|
+
event: "loadTableData",
|
|
111
|
+
});
|
|
112
|
+
} catch (error) {
|
|
113
|
+
loading.value = false;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
defineExpose({
|
|
118
|
+
name,
|
|
119
|
+
show,
|
|
120
|
+
});
|
|
121
|
+
</script>
|
|
122
|
+
|
|
123
|
+
<style scoped lang="less"></style>
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { ref, watch, onMounted, nextTick } from "vue";
|
|
2
|
+
import { useRoute } from "vue-router";
|
|
3
|
+
import { useMenuStore } from "$elpisStore/menu.js";
|
|
4
|
+
|
|
5
|
+
export const useSchema = () => {
|
|
6
|
+
const route = useRoute();
|
|
7
|
+
const menuStore = useMenuStore();
|
|
8
|
+
|
|
9
|
+
const api = ref("");
|
|
10
|
+
const tableSchema = ref({});
|
|
11
|
+
const tableConfig = ref();
|
|
12
|
+
const searchSchema = ref({});
|
|
13
|
+
const searchConfig = ref();
|
|
14
|
+
const components = ref({});
|
|
15
|
+
|
|
16
|
+
// 构造 schemaConfig 相关配置 输送给 schemaView 解析
|
|
17
|
+
const buildData = async () => {
|
|
18
|
+
const { key, sider_key: siderKey } = route.query;
|
|
19
|
+
|
|
20
|
+
const mItem = menuStore.findMenuItem({
|
|
21
|
+
key: "key",
|
|
22
|
+
value: siderKey ?? key,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (mItem && mItem.schemaConfig) {
|
|
26
|
+
const { schemaConfig: sConfig } = mItem;
|
|
27
|
+
|
|
28
|
+
const configSchema = JSON.parse(JSON.stringify(sConfig.schema));
|
|
29
|
+
|
|
30
|
+
api.value = sConfig.api ?? "";
|
|
31
|
+
tableSchema.value = {};
|
|
32
|
+
tableConfig.value = undefined;
|
|
33
|
+
searchSchema.value = {};
|
|
34
|
+
searchConfig.value = undefined;
|
|
35
|
+
components.value = {};
|
|
36
|
+
|
|
37
|
+
await nextTick();
|
|
38
|
+
//处理构造 tableSchema 和 tableConfig
|
|
39
|
+
tableSchema.value = buildDtoSchema(configSchema, "table");
|
|
40
|
+
tableConfig.value = sConfig.tableConfig;
|
|
41
|
+
//处理构造 searchSchema 和 searchConfig
|
|
42
|
+
const dtoSearchSchema = buildDtoSchema(configSchema, "search");
|
|
43
|
+
for (const key in dtoSearchSchema.properties) {
|
|
44
|
+
if (route.query[key] !== undefined) {
|
|
45
|
+
dtoSearchSchema.properties[key].option.default = route.query[key];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
searchSchema.value = dtoSearchSchema;
|
|
49
|
+
searchConfig.value = sConfig.searchConfig;
|
|
50
|
+
|
|
51
|
+
// 构造components = { key: { schema: {},config: {} } }
|
|
52
|
+
const { componentConfig } = sConfig;
|
|
53
|
+
if (componentConfig && Object.keys(componentConfig).length > 0) {
|
|
54
|
+
const dtoComponent = {};
|
|
55
|
+
for (const comName in componentConfig) {
|
|
56
|
+
dtoComponent[comName] = {
|
|
57
|
+
schema: buildDtoSchema(configSchema, comName),
|
|
58
|
+
config: componentConfig[comName],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
components.value = dtoComponent;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// 通用构建 schema
|
|
68
|
+
const buildDtoSchema = (_schema, comName) => {
|
|
69
|
+
if (!_schema?.properties) return {};
|
|
70
|
+
|
|
71
|
+
const dtoSchema = {
|
|
72
|
+
type: "object",
|
|
73
|
+
properties: {},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// 提取有效 shema 字段信息
|
|
77
|
+
for (const key in _schema.properties) {
|
|
78
|
+
const props = _schema.properties[key];
|
|
79
|
+
//xxxOption
|
|
80
|
+
if (props[`${comName}Option`]) {
|
|
81
|
+
let dtoProps = {};
|
|
82
|
+
// 提取props中非Option字段
|
|
83
|
+
for (const pkey in props) {
|
|
84
|
+
if (pkey.indexOf("Option") < 0) {
|
|
85
|
+
dtoProps[pkey] = props[pkey];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// 处理comname option
|
|
89
|
+
dtoProps = Object.assign({}, dtoProps, {
|
|
90
|
+
option: props[`${comName}Option`],
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// 处理 required 字段
|
|
94
|
+
const { required } = _schema;
|
|
95
|
+
if (required && required.find((pk) => pk === key)) {
|
|
96
|
+
dtoProps.option.required = true;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
dtoSchema.properties[key] = dtoProps;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return dtoSchema;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
watch(
|
|
106
|
+
[
|
|
107
|
+
() => route.query.key, // 菜单改变
|
|
108
|
+
() => route.query.sider_key, // 菜单改变
|
|
109
|
+
() => menuStore.menuList,
|
|
110
|
+
],
|
|
111
|
+
() => {
|
|
112
|
+
buildData();
|
|
113
|
+
},
|
|
114
|
+
{ deep: true },
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
onMounted(() => {
|
|
118
|
+
buildData();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
api,
|
|
123
|
+
tableSchema,
|
|
124
|
+
tableConfig,
|
|
125
|
+
searchSchema,
|
|
126
|
+
searchConfig,
|
|
127
|
+
components,
|
|
128
|
+
};
|
|
129
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-row class="schema-view">
|
|
3
|
+
<search-panel
|
|
4
|
+
v-if="
|
|
5
|
+
searchSchema?.properties &&
|
|
6
|
+
Object.keys(searchSchema.properties).length > 0
|
|
7
|
+
"
|
|
8
|
+
@search="onSearch"
|
|
9
|
+
>
|
|
10
|
+
</search-panel>
|
|
11
|
+
<table-panel ref="tablePanelRef" @operate="onTableOperate"></table-panel>
|
|
12
|
+
<component
|
|
13
|
+
v-for="(item, key) in components"
|
|
14
|
+
:key="key"
|
|
15
|
+
:is="ComponentConfig[key]?.component"
|
|
16
|
+
ref="comListRef"
|
|
17
|
+
@command="onComponentCommand"
|
|
18
|
+
/>
|
|
19
|
+
</el-row>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script setup>
|
|
23
|
+
import { ref, provide } from "vue";
|
|
24
|
+
import SearchPanel from "./complex-view/search-panel/search-panel.vue";
|
|
25
|
+
import TablePanel from "./complex-view/table-panel/table-panel.vue";
|
|
26
|
+
import { useSchema } from "./hook/schema.js";
|
|
27
|
+
import ComponentConfig from "./components/component-config.js";
|
|
28
|
+
const {
|
|
29
|
+
api,
|
|
30
|
+
tableSchema,
|
|
31
|
+
tableConfig,
|
|
32
|
+
searchSchema,
|
|
33
|
+
searchConfig,
|
|
34
|
+
components,
|
|
35
|
+
} = useSchema();
|
|
36
|
+
|
|
37
|
+
const apiParams = ref({});
|
|
38
|
+
// 感觉
|
|
39
|
+
provide("schemaViewData", {
|
|
40
|
+
api,
|
|
41
|
+
apiParams,
|
|
42
|
+
tableSchema,
|
|
43
|
+
tableConfig,
|
|
44
|
+
searchSchema,
|
|
45
|
+
searchConfig,
|
|
46
|
+
components,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const tablePanelRef = ref(null);
|
|
50
|
+
const comListRef = ref([]);
|
|
51
|
+
|
|
52
|
+
const onSearch = (searchValObj) => {
|
|
53
|
+
apiParams.value = searchValObj;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// table 事件映射
|
|
57
|
+
const EventHandleMap = {
|
|
58
|
+
showComponent: showComponent,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const onTableOperate = ({ btnConfig, rowData }) => {
|
|
62
|
+
const { eventKey } = btnConfig;
|
|
63
|
+
if (EventHandleMap[eventKey]) {
|
|
64
|
+
EventHandleMap[eventKey]({ btnConfig, rowData });
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// showComponent 展示动态组件
|
|
69
|
+
function showComponent({ btnConfig, rowData }) {
|
|
70
|
+
const { comName } = btnConfig.eventOption;
|
|
71
|
+
if (!comName) {
|
|
72
|
+
console.error("无组件配置");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const comRef = comListRef.value.find((item) => item.name === comName);
|
|
76
|
+
if (!comRef || typeof comRef.show !== "function") {
|
|
77
|
+
console.error(`找不到组件${comName}`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
comRef.show(rowData);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const onComponentCommand = (data) => {
|
|
84
|
+
const { event } = data;
|
|
85
|
+
if (event === "loadTableData") {
|
|
86
|
+
tablePanelRef.value.loadTableData();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<style scoped lang="less">
|
|
92
|
+
.schema-view {
|
|
93
|
+
display: flex;
|
|
94
|
+
flex-direction: column;
|
|
95
|
+
height: 100%;
|
|
96
|
+
width: 100%;
|
|
97
|
+
}
|
|
98
|
+
</style>
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<sider-container>
|
|
3
|
+
<template #menu-container>
|
|
4
|
+
<el-menu
|
|
5
|
+
:default-active="activeKey"
|
|
6
|
+
:ellipsis="false"
|
|
7
|
+
@select="onMenuSelect"
|
|
8
|
+
>
|
|
9
|
+
<template v-for="item in menuList">
|
|
10
|
+
<!-- group -->
|
|
11
|
+
<sub-menu
|
|
12
|
+
v-if="item.subMenu && item.subMenu.length > 0"
|
|
13
|
+
:menu-item="item"
|
|
14
|
+
>
|
|
15
|
+
</sub-menu>
|
|
16
|
+
<el-menu-item v-else :index="item.key">{{ item.name }}</el-menu-item>
|
|
17
|
+
<!-- module -->
|
|
18
|
+
</template>
|
|
19
|
+
</el-menu>
|
|
20
|
+
</template>
|
|
21
|
+
<template #main-container>
|
|
22
|
+
<router-view />
|
|
23
|
+
</template>
|
|
24
|
+
</sider-container>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup>
|
|
28
|
+
import { ref, onMounted, watch } from "vue";
|
|
29
|
+
import { useRoute, useRouter } from "vue-router";
|
|
30
|
+
import { useMenuStore } from "$elpisStore/menu.js";
|
|
31
|
+
import SiderContainer from "$elpisWidgets/sider-container/sider-container.vue";
|
|
32
|
+
import SubMenu from "../header-view/complex-view/sub-menu/sub-menu.vue";
|
|
33
|
+
|
|
34
|
+
const route = useRoute();
|
|
35
|
+
const router = useRouter();
|
|
36
|
+
const menuStore = useMenuStore();
|
|
37
|
+
|
|
38
|
+
const menuList = ref([]);
|
|
39
|
+
|
|
40
|
+
const activeKey = ref("");
|
|
41
|
+
|
|
42
|
+
const setActiveKey = () => {
|
|
43
|
+
let siderMenuItem = menuStore.findMenuItem({
|
|
44
|
+
key: "key",
|
|
45
|
+
value: route.query.sider_key,
|
|
46
|
+
});
|
|
47
|
+
// 默认选中第一个
|
|
48
|
+
if (!siderMenuItem) {
|
|
49
|
+
const headerMenuItem = menuStore.findMenuItem({
|
|
50
|
+
key: "key",
|
|
51
|
+
value: route.query.key,
|
|
52
|
+
});
|
|
53
|
+
const siderMenuList = headerMenuItem?.siderConfig?.menu || [];
|
|
54
|
+
if (siderMenuList && siderMenuList.length > 0) {
|
|
55
|
+
//找出左侧菜单第一项
|
|
56
|
+
siderMenuItem = menuStore.findFirstMemuItem(siderMenuList);
|
|
57
|
+
if (siderMenuItem) {
|
|
58
|
+
// TODE: 处理选中菜单逻辑
|
|
59
|
+
handleMenuSelect(siderMenuItem.key);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
activeKey.value = siderMenuItem?.key || "";
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const setMenuList = () => {
|
|
67
|
+
const menuItem = menuStore.findMenuItem({
|
|
68
|
+
key: "key",
|
|
69
|
+
value: route.query.key,
|
|
70
|
+
});
|
|
71
|
+
menuList.value = menuItem?.siderConfig?.menu || [];
|
|
72
|
+
// if (menuItem && menuItem.siderConfig && menuItem.siderConfig.menu) {
|
|
73
|
+
// menuList.value = menuItem.siderConfig || [];
|
|
74
|
+
// }
|
|
75
|
+
};
|
|
76
|
+
watch(
|
|
77
|
+
() => route.query.key,
|
|
78
|
+
() => {
|
|
79
|
+
setMenuList();
|
|
80
|
+
setActiveKey();
|
|
81
|
+
},
|
|
82
|
+
);
|
|
83
|
+
watch(
|
|
84
|
+
() => menuStore.menuList,
|
|
85
|
+
() => {
|
|
86
|
+
setMenuList();
|
|
87
|
+
setActiveKey();
|
|
88
|
+
},
|
|
89
|
+
{ deep: true },
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const onMenuSelect = (menuKey) => {
|
|
93
|
+
handleMenuSelect(menuKey);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const handleMenuSelect = (menuKey) => {
|
|
97
|
+
const menuItem = menuStore.findMenuItem({
|
|
98
|
+
key: "key",
|
|
99
|
+
value: menuKey,
|
|
100
|
+
});
|
|
101
|
+
const { moduleType, key, customConfig } = menuItem;
|
|
102
|
+
|
|
103
|
+
if (key === route.query.sider_key) return;
|
|
104
|
+
|
|
105
|
+
const pathMap = {
|
|
106
|
+
iframe: "/iframe",
|
|
107
|
+
schema: "/schema",
|
|
108
|
+
custom: customConfig?.path,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
router.push({
|
|
112
|
+
path: `/view/dashboard/sider${pathMap[moduleType]}`,
|
|
113
|
+
query: {
|
|
114
|
+
key: route.query.key,
|
|
115
|
+
sider_key: key,
|
|
116
|
+
proj_key: route.query.proj_key,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
onMounted(() => {
|
|
122
|
+
setMenuList();
|
|
123
|
+
setActiveKey();
|
|
124
|
+
});
|
|
125
|
+
</script>
|
|
126
|
+
|
|
127
|
+
<style scoped lang="scss"></style>
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-config-provider :locale="zhCn">
|
|
3
|
+
<header-view :projName="projName" @menu-select="onMenuSelect">
|
|
4
|
+
<template #main-content>
|
|
5
|
+
<router-view></router-view>
|
|
6
|
+
</template>
|
|
7
|
+
</header-view>
|
|
8
|
+
</el-config-provider>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script setup>
|
|
12
|
+
import { ref, onMounted } from "vue";
|
|
13
|
+
import { useRoute, useRouter } from "vue-router";
|
|
14
|
+
import $curl from "$elpisCommon/curl.js";
|
|
15
|
+
import { useProjectStore } from "$elpisStore/project.js";
|
|
16
|
+
import { useMenuStore } from "$elpisStore/menu.js";
|
|
17
|
+
import zhCn from "element-plus/es/locale/lang/zh-cn";
|
|
18
|
+
import HeaderView from "./complex-view/header-view/header-view.vue";
|
|
19
|
+
|
|
20
|
+
const router = useRouter();
|
|
21
|
+
const route = useRoute();
|
|
22
|
+
const projectStore = useProjectStore();
|
|
23
|
+
const menuStore = useMenuStore();
|
|
24
|
+
|
|
25
|
+
const projName = ref("");
|
|
26
|
+
|
|
27
|
+
// 请求 /project/list 接口 存store里面
|
|
28
|
+
const getProjectList = async () => {
|
|
29
|
+
try {
|
|
30
|
+
const res = await $curl({
|
|
31
|
+
url: "/api/project/list",
|
|
32
|
+
method: "get",
|
|
33
|
+
query: {
|
|
34
|
+
proj_key: route.query.proj_key,
|
|
35
|
+
},
|
|
36
|
+
// errorMessage: "获取项目列表失败",
|
|
37
|
+
});
|
|
38
|
+
projectStore.setProjectList(res.data || []);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.log(error);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// 请求 /api/project 接口
|
|
45
|
+
const getProjectConfig = async () => {
|
|
46
|
+
try {
|
|
47
|
+
const res = await $curl({
|
|
48
|
+
url: "/api/project",
|
|
49
|
+
method: "get",
|
|
50
|
+
query: {
|
|
51
|
+
proj_key: route.query.proj_key,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
projName.value = res.data?.name || "";
|
|
55
|
+
menuStore.setMenuList(res.data?.menu || []);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.log(error);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// 点击菜单回调
|
|
62
|
+
const onMenuSelect = (menuItem) => {
|
|
63
|
+
const { customConfig, key, moduleType } = menuItem;
|
|
64
|
+
// 当前页不处理
|
|
65
|
+
if (key === route.query.key) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const pathMap = {
|
|
70
|
+
sider: "/sider",
|
|
71
|
+
iframe: "/iframe",
|
|
72
|
+
schema: "/schema",
|
|
73
|
+
custom: customConfig?.path || "/",
|
|
74
|
+
};
|
|
75
|
+
const path = pathMap[moduleType] || "/";
|
|
76
|
+
router.push({
|
|
77
|
+
path: `/view/dashboard${path}`,
|
|
78
|
+
query: {
|
|
79
|
+
key,
|
|
80
|
+
proj_key: route.query.proj_key,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
onMounted(async () => {
|
|
86
|
+
await getProjectList();
|
|
87
|
+
await getProjectConfig();
|
|
88
|
+
});
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<style lang="less" scoped>
|
|
92
|
+
:deep(.el-main) {
|
|
93
|
+
height: 100%;
|
|
94
|
+
--el-main-padding: 0 20px;
|
|
95
|
+
}
|
|
96
|
+
</style>
|