@yukihong/schema-admin-x 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.
Files changed (80) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc +55 -0
  3. package/README.md +208 -0
  4. package/app/controller/base.js +39 -0
  5. package/app/controller/project.js +80 -0
  6. package/app/controller/view.js +20 -0
  7. package/app/extend/logger.js +39 -0
  8. package/app/middleware/api-params-verify.js +79 -0
  9. package/app/middleware/api-sign-verify.js +34 -0
  10. package/app/middleware/error-handler.js +34 -0
  11. package/app/middleware/project-handler.js +27 -0
  12. package/app/middleware.js +40 -0
  13. package/app/pages/asserts/custom.css +13 -0
  14. package/app/pages/boot.js +53 -0
  15. package/app/pages/common/curl.js +91 -0
  16. package/app/pages/common/utils.js +3 -0
  17. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +21 -0
  18. package/app/pages/dashboard/complex-view/header-view/header-view.vue +127 -0
  19. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +44 -0
  20. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +41 -0
  21. package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +131 -0
  22. package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
  23. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +100 -0
  24. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +106 -0
  25. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +131 -0
  26. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +126 -0
  27. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +102 -0
  28. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +26 -0
  29. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +128 -0
  30. package/app/pages/dashboard/dashboard.vue +99 -0
  31. package/app/pages/dashboard/entry.dashboard.js +44 -0
  32. package/app/pages/store/index.js +4 -0
  33. package/app/pages/store/menu.js +61 -0
  34. package/app/pages/store/project.js +17 -0
  35. package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
  36. package/app/pages/widgets/header-container/asserts/logo.png +0 -0
  37. package/app/pages/widgets/header-container/header-container.vue +109 -0
  38. package/app/pages/widgets/schema-form/complex-view/input/input.vue +146 -0
  39. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +140 -0
  40. package/app/pages/widgets/schema-form/complex-view/select/select.vue +121 -0
  41. package/app/pages/widgets/schema-form/form-item-config.js +23 -0
  42. package/app/pages/widgets/schema-form/schema-form.vue +131 -0
  43. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +50 -0
  44. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +65 -0
  45. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +44 -0
  46. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +51 -0
  47. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +127 -0
  48. package/app/pages/widgets/schema-search-bar/search-item-config.js +27 -0
  49. package/app/pages/widgets/schema-table/schema-table.vue +248 -0
  50. package/app/pages/widgets/sider-container/sider-container.vue +28 -0
  51. package/app/public/static/logo.png +0 -0
  52. package/app/public/static/normalize.css +239 -0
  53. package/app/router/project.js +7 -0
  54. package/app/router/view.js +10 -0
  55. package/app/router-schema/project.js +30 -0
  56. package/app/service/base.js +13 -0
  57. package/app/service/project.js +50 -0
  58. package/app/view/entry.tpl +25 -0
  59. package/app/webpack/config/webpack.base.js +213 -0
  60. package/app/webpack/config/webpack.dev.js +61 -0
  61. package/app/webpack/config/webpack.prod.js +124 -0
  62. package/app/webpack/dev.js +63 -0
  63. package/app/webpack/libs/blank.js +1 -0
  64. package/app/webpack/prod.js +19 -0
  65. package/config/config.beta.js +3 -0
  66. package/config/config.default.js +3 -0
  67. package/config/config.prod.js +3 -0
  68. package/elpis-core/env.js +20 -0
  69. package/elpis-core/index.js +99 -0
  70. package/elpis-core/loader/config.js +52 -0
  71. package/elpis-core/loader/controller.js +75 -0
  72. package/elpis-core/loader/extend.js +55 -0
  73. package/elpis-core/loader/middleware.js +64 -0
  74. package/elpis-core/loader/router-schema.js +47 -0
  75. package/elpis-core/loader/router.js +59 -0
  76. package/elpis-core/loader/service.js +75 -0
  77. package/index.js +40 -0
  78. package/model/index.js +102 -0
  79. package/package.json +93 -0
  80. package/test/controller/project.test.js +217 -0
@@ -0,0 +1,106 @@
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
+ <h4>{{title}}</h4>
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
+ </el-drawer>
26
+ </template>
27
+
28
+ <script setup>
29
+ import { ref, inject } from 'vue';
30
+ import $curl from '$elpisCommon/curl.js';
31
+
32
+ const {
33
+ api,
34
+ components
35
+ } = inject('schemaViewData');
36
+
37
+ const name = ref('detailPanel');
38
+ const isShow = ref(false);
39
+ const loading = ref(false);
40
+ const title = ref('');
41
+ const mainKey = ref('');
42
+ const mainValue = ref();
43
+ const dtoModel = ref({});
44
+
45
+ const show = (rowData) => {
46
+ const { config } = components.value[name.value];
47
+
48
+ title.value = config.title;
49
+ mainKey.value = config.mainKey; // 表单主键
50
+ mainValue.value = rowData[config.mainKey]; // 表单主键值
51
+ dtoModel.value = {};
52
+
53
+ isShow.value = true;
54
+
55
+ fetchFormData();
56
+ }
57
+
58
+
59
+ const fetchFormData = async () => {
60
+ if(loading.value) { return; }
61
+
62
+ loading.value = true;
63
+ const res = await $curl({
64
+ method: 'get',
65
+ url: api.value,
66
+ query: {
67
+ [mainKey.value]: mainValue.value
68
+ }
69
+ })
70
+ loading.value = false;
71
+
72
+ if(!res || !res.success || !res.data) {
73
+ return;
74
+ }
75
+
76
+ dtoModel.value = res.data;
77
+ }
78
+
79
+ defineExpose({
80
+ name,
81
+ show
82
+ });
83
+
84
+ </script>
85
+
86
+ <style lang="less" scoped>
87
+ .detail-panel {
88
+ border: 1px solid #a6a6a6;
89
+ padding: 30px;
90
+
91
+ .row-item {
92
+ height: 40px;
93
+ line-height: 40px;
94
+ font-size: 20px;
95
+
96
+ .item-label {
97
+ margin-right: 20px;
98
+ width: 120px;
99
+ color: #fff;
100
+ }
101
+ .item-value {
102
+ color: #d2dae4;
103
+ }
104
+ }
105
+ }
106
+ </style>
@@ -0,0 +1,131 @@
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
+ <h4>{{title}}</h4>
10
+ </template>
11
+ <template #default>
12
+ <schema-form
13
+ ref="schemaFormRef"
14
+ v-loading="loading"
15
+ :schema="components[name]?.schema"
16
+ :model="dtoModel"
17
+ ></schema-form>
18
+ </template>
19
+ <template #footer>
20
+ <el-button
21
+ type="primary"
22
+ @click="save"
23
+ >{{saveBtnText}}</el-button>
24
+ </template>
25
+ </el-drawer>
26
+ </template>
27
+
28
+ <script setup>
29
+ import { ref, inject } from 'vue';
30
+ import { ElNotification } from 'element-plus';
31
+ import $curl from '$elpisCommon/curl.js';
32
+ import SchemaForm from '$elpisWidgets/schema-form/schema-form.vue';
33
+
34
+ const {
35
+ api,
36
+ components
37
+ } = inject('schemaViewData');
38
+
39
+ const emit = defineEmits([ 'command' ]);
40
+
41
+ const name = ref('editForm');
42
+
43
+ const schemaFormRef = ref(null);
44
+ const isShow = ref(false);
45
+ const loading = ref(false);
46
+ const title = ref('');
47
+ const saveBtnText = ref('');
48
+ const mainKey = ref('');
49
+ const mainValue = ref();
50
+ const dtoModel = ref({});
51
+
52
+ const show = (rowData) => {
53
+ const { config } = components.value[name.value];
54
+ title.value = config.title;
55
+ saveBtnText.value = config.saveBtnText;
56
+ mainKey.value = config.mainKey; // 表单主键
57
+ mainValue.value = rowData[config.mainKey]; // 表单主键值
58
+ dtoModel.value = {};
59
+
60
+ isShow.value = true;
61
+
62
+ fetchFormData();
63
+ }
64
+
65
+ const close = () => {
66
+ isShow.value = false;
67
+ }
68
+
69
+ const fetchFormData = async () => {
70
+ if(loading.value) { return; }
71
+
72
+ loading.value = true;
73
+ const res = await $curl({
74
+ method: 'get',
75
+ url: api.value,
76
+ query: {
77
+ [mainKey.value]: mainValue.value
78
+ }
79
+ })
80
+ loading.value = false;
81
+
82
+ if(!res || !res.success || !res.data) {
83
+ return;
84
+ }
85
+
86
+ dtoModel.value = res.data;
87
+ }
88
+
89
+ const save = async () => {
90
+ if(loading.value) { return; }
91
+
92
+ if(!schemaFormRef.value.validate()) { return; }
93
+
94
+ loading.value = true;
95
+
96
+ const res = await $curl({
97
+ method: 'put',
98
+ url: api.value,
99
+ data: {
100
+ [mainKey.value]: mainValue.value,
101
+ ...schemaFormRef.value.getValue()
102
+ }
103
+ });
104
+
105
+ loading.value = false;
106
+
107
+ if(!res || !res.success) {
108
+ return;
109
+ }
110
+
111
+ ElNotification({
112
+ title: '修改成功',
113
+ message: '修改成功',
114
+ type: 'success'
115
+ });
116
+
117
+ close();
118
+
119
+ emit('command', {
120
+ event: 'loadTableData'
121
+ });
122
+ }
123
+
124
+ defineExpose({
125
+ name,
126
+ show
127
+ });
128
+ </script>
129
+
130
+ <style>
131
+ </style>
@@ -0,0 +1,126 @@
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 = function() {
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 = function() {
18
+ const { key, sider_key: siderKey } = route.query;
19
+ const mItem = menuStore.findMenuItem({
20
+ key: 'key',
21
+ value: siderKey ?? key
22
+ });
23
+ if(mItem && mItem.schemaConfig) {
24
+ const { schemaConfig: sConfig } = mItem;
25
+
26
+ const configSchema = JSON.parse(JSON.stringify(sConfig.schema));
27
+
28
+ api.value = sConfig.api ?? '';
29
+ tableSchema.value = {};
30
+ tableConfig.value = undefined;
31
+ searchSchema.value = {};
32
+ searchSchema.value = undefined;
33
+ components.value = {};
34
+
35
+ nextTick(() => {
36
+ // 构造 tableSchema 和 tableConfig
37
+ tableSchema.value = buildDtoSchema(configSchema, 'table');
38
+ tableConfig.value = sConfig.tableConfig;
39
+
40
+ // 构造 searchSchema 和 searchConfig
41
+ const dtoSearchSchema = buildDtoSchema(configSchema, 'search');
42
+ // 处理当路由带指定搜索项和内容时,给搜索控件赋默认值
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 = { comKey: { schema: {}, config: {} }}
52
+ const { componentConfig } = sConfig;
53
+ if(componentConfig && Object.keys(componentConfig).length > 0) {
54
+ const dtoComponents = {};
55
+
56
+ for(const comName in componentConfig) {
57
+ dtoComponents[comName] = {
58
+ schema: buildDtoSchema(configSchema, comName),
59
+ config: componentConfig[comName]
60
+ }
61
+ }
62
+ components.value = dtoComponents;
63
+ }
64
+ });
65
+ }
66
+ }
67
+
68
+ // 通用构建 schema 方法(清除噪音)
69
+ const buildDtoSchema = (_schema, comName) => {
70
+ if(!_schema?.properties) { return {}; }
71
+
72
+ const dtoSchema = {
73
+ type: 'object',
74
+ properties: {}
75
+ }
76
+
77
+ // 提取有效 schema 字段信息
78
+ for(const key in _schema.properties) {
79
+ const props = _schema.properties[key];
80
+ // tableOption searchBarOption ...
81
+ if(props[`${comName}Option`]) {
82
+ let dtoProps = {};
83
+ // 提取 props 中非 option 的部分,存放到 dtoProps 中
84
+ for(const pKey in props) {
85
+ if(pKey.indexOf(Option) < 0) {
86
+ dtoProps[pKey] = props[pKey];
87
+ }
88
+ }
89
+ // 处理 comName Option
90
+ dtoProps = Object.assign({}, dtoProps, { '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
+
103
+ return dtoSchema;
104
+ }
105
+
106
+ watch([
107
+ () => route.query.key,
108
+ () => route.query.sider_key,
109
+ () => menuStore.menuList
110
+ ], () => {
111
+ buildData();
112
+ }, { deep: true})
113
+
114
+ onMounted(() => {
115
+ buildData();
116
+ });
117
+
118
+ return {
119
+ api,
120
+ tableSchema,
121
+ tableConfig,
122
+ searchSchema,
123
+ searchConfig,
124
+ components
125
+ }
126
+ }
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <el-row class="schema-view">
3
+ <search-panel
4
+ v-if="searchSchema?.properties && Object.keys(searchSchema.properties).length > 0"
5
+ @search="onSearch"
6
+ ></search-panel>
7
+ <table-panel
8
+ ref="tablePanelRef"
9
+ @operate="onTableOperate"
10
+ ></table-panel>
11
+ <!-- 动态组件 -->
12
+ <component
13
+ v-for="(item,key) in components"
14
+ :key="key"
15
+ :is="ComponentConfig[key]?.component"
16
+ ref="comListRef"
17
+ @command="onComponentCommand"
18
+ ></component>
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 ComponentConfig from './components/component-config';
27
+ import { useSchema } from './hook/schema.js';
28
+
29
+ const {
30
+ api,
31
+ tableSchema,
32
+ tableConfig,
33
+ searchSchema,
34
+ searchConfig,
35
+ components
36
+ } = useSchema();
37
+
38
+ const apiParams = ref({});
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 EventHandlerMap = {
58
+ showComponent: showComponent
59
+ }
60
+
61
+ const onTableOperate = ({ btnConfig, rowData }) => {
62
+ const { eventKey } = btnConfig;
63
+ if(EventHandlerMap[eventKey]) {
64
+ EventHandlerMap[eventKey]({ btnConfig, rowData })
65
+ }
66
+ }
67
+
68
+ // 展示动态组件
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 => {
76
+ return item.name === comName
77
+ });
78
+ if(!comRef || typeof comRef.show !== 'function' ) {
79
+ console.error(`找不到组件:${comName}`);
80
+ return;
81
+ }
82
+ comRef.show(rowData);
83
+ }
84
+
85
+ // 响应组件事件
86
+ const onComponentCommand = (data) => {
87
+ const { event } = data;
88
+ if(event === 'loadTableData') {
89
+ tablePanelRef.value.loadTableData();
90
+ }
91
+ }
92
+
93
+ </script>
94
+
95
+ <style lang="less" scoped>
96
+ .schema-view {
97
+ display: flex;
98
+ flex-direction: column;
99
+ height: 100%;
100
+ width: 100%;
101
+ }
102
+ </style>
@@ -0,0 +1,26 @@
1
+ <template>
2
+ <el-sub-menu :index="menuItem.key" >
3
+ <template #title>
4
+ {{ menuItem.name }}
5
+ </template>
6
+ <div :key="item.key" v-for="item in menuItem.subMenu">
7
+ <sub-menu
8
+ v-if="item.subMenu && item.subMenu.length > 0"
9
+ :menu-item="item"
10
+ ></sub-menu>
11
+ <el-menu-item
12
+ v-else
13
+ :index="item.key"
14
+ >
15
+ {{ item.name }}
16
+ </el-menu-item>
17
+ </div>
18
+ </el-sub-menu>
19
+ </template>
20
+
21
+ <script setup>
22
+ const { menuItem } = defineProps(['menuItem']);
23
+ </script>
24
+
25
+ <style lang="less" scoped>
26
+ </style>
@@ -0,0 +1,128 @@
1
+ <template>
2
+ <sider-container>
3
+ <template #menu-content>
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
+ ></sub-menu>
15
+ <!-- module -->
16
+ <el-menu-item
17
+ v-else
18
+ :index="item.key"
19
+ >
20
+ {{item.name}}
21
+ </el-menu-item>
22
+ </template>
23
+ </el-menu>
24
+ </template>
25
+ <template #main-content>
26
+ <router-view></router-view>
27
+ </template>
28
+ </sider-container>
29
+ </template>
30
+
31
+ <script setup>
32
+ import { ref, watch, onMounted } from 'vue';
33
+ import { useRouter, useRoute } from 'vue-router';
34
+ import { useMenuStore } from '$elpisStore/menu.js';
35
+ import SiderContainer from '$elpisWidgets/sider-container/sider-container';
36
+ import SubMenu from './complex-view/sub-menu/sub-menu.vue';
37
+
38
+ const router = useRouter();
39
+ const route = useRoute();
40
+ const menuStore = useMenuStore();
41
+
42
+ const menuList = ref([]);
43
+ const setMenuList = function () {
44
+ const menuItem = menuStore.findMenuItem({
45
+ key: 'key',
46
+ value: route.query.key
47
+ });
48
+ if(menuItem && menuItem.siderConfig && menuItem.siderConfig.menu) {
49
+ menuList.value = menuItem.siderConfig.menu;
50
+ }
51
+ }
52
+
53
+
54
+ const activeKey = ref('');
55
+ const setActiveKey = function () {
56
+ let siderMenuItem = menuStore.findMenuItem({
57
+ key: 'key',
58
+ value: route.query.sider_key
59
+ });
60
+ // 如果首次加载 sider-view,用户未选中左侧菜单,需要默认选中第一个
61
+ if(!siderMenuItem) {
62
+ const hMenuItem = menuStore.findMenuItem({
63
+ key: 'key',
64
+ value: route.query.key
65
+ });
66
+ if(hMenuItem && hMenuItem.siderConfig && hMenuItem.siderConfig.menu) {
67
+ const siderMenuList = hMenuItem.siderConfig.menu;
68
+ siderMenuItem = menuStore.findFirstMenuItem(siderMenuList); // 找出左侧菜单中的第一项
69
+ if(siderMenuItem) {
70
+ handleMenuSelect(siderMenuItem.key);
71
+ }
72
+ }
73
+ }
74
+ activeKey.value = siderMenuItem?.key;
75
+ }
76
+
77
+
78
+
79
+ watch(() => route.query.key, () => {
80
+ setMenuList();
81
+ setActiveKey();
82
+ })
83
+
84
+ watch(() => menuStore.menuList, () => {
85
+ setMenuList();
86
+ setActiveKey();
87
+ }, { deep: true})
88
+
89
+ onMounted(() => {
90
+ setMenuList();
91
+ setActiveKey();
92
+ })
93
+
94
+ const onMenuSelect = function (menuKey) {
95
+ handleMenuSelect(menuKey);
96
+ }
97
+
98
+ const handleMenuSelect = function(menuKey) {
99
+ const menuItem = menuStore.findMenuItem({
100
+ key: 'key',
101
+ value: menuKey
102
+ });
103
+
104
+ const { moduleType, key, customConfig } = menuItem;
105
+
106
+ // 如果是当前页面,不处理
107
+ if(key === route.query.sider_key) { return; }
108
+
109
+ const pathMap = {
110
+ iframe: '/iframe',
111
+ schema: '/schema',
112
+ custom: customConfig?.path
113
+ };
114
+
115
+ router.push({
116
+ path: `/view/dashboard/sider${pathMap[moduleType]}`,
117
+ query: {
118
+ key:route.query.key,
119
+ sider_key: key,
120
+ proj_key: route.query.proj_key
121
+ }
122
+ })
123
+ }
124
+
125
+ </script>
126
+
127
+ <style lang="less" scoped>
128
+ </style>
@@ -0,0 +1,99 @@
1
+ <template>
2
+
3
+ <el-config-provider :locale="zhCn">
4
+ <header-view :proj-name="projName" @menu-select="onMenuSelect">
5
+ <template #main-content>
6
+ <router-view></router-view>
7
+ </template>
8
+ </header-view>
9
+ </el-config-provider>
10
+
11
+ </template>
12
+
13
+ <script setup>
14
+ import { ref, onMounted } from 'vue';
15
+ import { useRouter, useRoute } from 'vue-router';
16
+ import zhCn from 'element-plus/es/locale/lang/zh-cn';
17
+ import HeaderView from './complex-view/header-view/header-view.vue';
18
+ import $curl from '$elpisCommon/curl.js';
19
+ import { useMenuStore } from '$elpisStore/menu';
20
+ import { useProjectStore } from '$elpisStore/project';
21
+
22
+ const router = useRouter();
23
+ const route = useRoute();
24
+ const menuStore = useMenuStore();
25
+ const projectStore = useProjectStore();
26
+
27
+ onMounted(() => {
28
+ getProjectList();
29
+ getProjectConfig();
30
+ });
31
+
32
+ const projName = ref('');
33
+
34
+
35
+ // 请求 /api/project/list 接口,并缓存到 project-store 中
36
+ async function getProjectList() {
37
+ const res = await $curl({
38
+ method: 'get',
39
+ url: '/api/project/list',
40
+ query: {
41
+ proj_key: route.query.proj_key,
42
+ }
43
+ });
44
+
45
+ if(!res || !res.success || !res.data) {
46
+ return;
47
+ }
48
+ projectStore.setProjectList(res.data);
49
+ }
50
+
51
+
52
+ // 请求 /api/project 接口,并缓存到 menu-store 中
53
+ async function getProjectConfig() {
54
+ const res = await $curl({
55
+ method: 'get',
56
+ url: '/api/project',
57
+ query: {
58
+ proj_key: route.query.proj_key,
59
+ }
60
+ });
61
+
62
+ if(!res || !res.success || !res.data) {
63
+ return;
64
+ }
65
+ const { name, menu } = res.data;
66
+ projName.value = name;
67
+ menuStore.setMenuList(menu);
68
+ }
69
+
70
+ // 点击菜单回调方法
71
+ const onMenuSelect = function(menuItem) {
72
+ const { moduleType, key, customConfig } = menuItem;
73
+
74
+ // 如果是当前页面,不处理
75
+ if(key === route.query.key) { return; }
76
+
77
+ const pathMap = {
78
+ sider: '/sider',
79
+ iframe: '/iframe',
80
+ schema: '/schema',
81
+ custom: customConfig?.path
82
+ };
83
+
84
+ router.push({
85
+ path: `/view/dashboard${pathMap[moduleType]}`,
86
+ query: {
87
+ key,
88
+ proj_key: route.query.proj_key
89
+ }
90
+ })
91
+ }
92
+
93
+ </script>
94
+
95
+ <style lang="less" scoped>
96
+ :deep(.el-main) {
97
+ padding: 0;
98
+ }
99
+ </style>