@misstalor17/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 +56 -0
- package/README.md +6 -0
- package/app/controller/base.js +43 -0
- package/app/controller/business.js +121 -0
- package/app/controller/project.js +75 -0
- package/app/controller/view.js +24 -0
- package/app/extend/logger.js +37 -0
- package/app/middleware/api-params-verify.js +70 -0
- package/app/middleware/api-sign-verify.js +31 -0
- package/app/middleware/error-handler.js +32 -0
- package/app/middleware/project-handler.js +28 -0
- package/app/middleware.js +44 -0
- package/app/pages/asserts/custom.css +12 -0
- package/app/pages/boot.js +45 -0
- package/app/pages/common/curl.js +96 -0
- package/app/pages/common/utils.js +2 -0
- package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu.vue +22 -0
- package/app/pages/dashboard/complex-view/header-view/header-view.vue +106 -0
- package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +45 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +33 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +105 -0
- package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
- package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +85 -0
- package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +90 -0
- package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +113 -0
- package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +109 -0
- package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +66 -0
- package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +17 -0
- package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +116 -0
- package/app/pages/dashboard/dashboard.vue +96 -0
- package/app/pages/dashboard/entry.dashboard.js +45 -0
- package/app/pages/store/index.js +3 -0
- package/app/pages/store/menu.js +60 -0
- package/app/pages/store/project.js +17 -0
- package/app/pages/widgets/header-container/asserts/logo.png +0 -0
- package/app/pages/widgets/header-container/asserts/user.png +0 -0
- package/app/pages/widgets/header-container/header-container.vue +105 -0
- package/app/pages/widgets/schema-form/complex-view/input/input.vue +120 -0
- package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +121 -0
- package/app/pages/widgets/schema-form/complex-view/select/select.vue +106 -0
- package/app/pages/widgets/schema-form/form-item-config.js +20 -0
- package/app/pages/widgets/schema-form/schema-form.vue +122 -0
- package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +42 -0
- package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +55 -0
- package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +37 -0
- package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +41 -0
- package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +109 -0
- package/app/pages/widgets/schema-search-bar/search-item-config.js +23 -0
- package/app/pages/widgets/schema-table/schema.table.vue +191 -0
- package/app/pages/widgets/sider-container/sider-container.vue +34 -0
- package/app/public/static/logo.png +0 -0
- package/app/public/static/normalize.css +240 -0
- package/app/router/business.js +9 -0
- package/app/router/project.js +6 -0
- package/app/router/view.js +13 -0
- package/app/router-schema/business.js +82 -0
- package/app/router-schema/project.js +31 -0
- package/app/service/base.js +13 -0
- package/app/service/project.js +40 -0
- package/app/view/entry.tpl +25 -0
- package/app/webpack/config/webpack.base.js +204 -0
- package/app/webpack/config/webpack.dev.js +56 -0
- package/app/webpack/config/webpack.prod.js +116 -0
- package/app/webpack/dev.js +52 -0
- package/app/webpack/libs/blank.js +1 -0
- package/app/webpack/prod.js +17 -0
- package/config/config.default.js +3 -0
- package/docs/dashboard-model.js +143 -0
- package/elpis-core/env.js +23 -0
- package/elpis-core/index.js +93 -0
- package/elpis-core/loader/config.js +52 -0
- package/elpis-core/loader/controller.js +61 -0
- package/elpis-core/loader/extend.js +52 -0
- package/elpis-core/loader/middleware.js +61 -0
- package/elpis-core/loader/router-schema.js +46 -0
- package/elpis-core/loader/router.js +43 -0
- package/elpis-core/loader/service.js +61 -0
- package/index.js +38 -0
- package/model/buiness/model.js +200 -0
- package/model/index.js +93 -0
- package/npminstall-debug.log +218 -0
- package/package.json +92 -0
- package/test/controller/project.test.js +194 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-drawer v-model="isShow" direction="rtl" :destroy-on-close="true" :size="550">
|
|
3
|
+
<template #header>
|
|
4
|
+
<h3>{{ title }}</h3>
|
|
5
|
+
</template>
|
|
6
|
+
<template #default>
|
|
7
|
+
<schema-form v-loading="loading" ref="schemaFormRef" :schema="components[name]?.schema"
|
|
8
|
+
:model="dtoModel"></schema-form>
|
|
9
|
+
</template>
|
|
10
|
+
<template #footer>
|
|
11
|
+
<el-button type="primary" @click="save">{{ saveBtnText }}</el-button>
|
|
12
|
+
</template>
|
|
13
|
+
</el-drawer>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script setup>
|
|
17
|
+
import { ref, inject } from 'vue'
|
|
18
|
+
import { ElNotification } from 'element-plus';
|
|
19
|
+
import $curl from '$elpisCommon/curl'
|
|
20
|
+
import SchemaForm from '$elpisWidgets/schema-form/schema-form.vue';
|
|
21
|
+
|
|
22
|
+
const { api, components } = inject('schemaViewData')
|
|
23
|
+
|
|
24
|
+
const emit = defineEmits(['command'])
|
|
25
|
+
const schemaFormRef = ref(null)
|
|
26
|
+
const name = ref('editForm')
|
|
27
|
+
const isShow = ref(false)
|
|
28
|
+
const title = ref('')
|
|
29
|
+
const saveBtnText = ref('')
|
|
30
|
+
const mainKey = ref('')
|
|
31
|
+
const mainValue = ref()
|
|
32
|
+
const dtoModel = ref({})
|
|
33
|
+
const loading = ref(false)
|
|
34
|
+
|
|
35
|
+
const show = (rowData) => {
|
|
36
|
+
const { config } = components.value[name.value]
|
|
37
|
+
|
|
38
|
+
title.value = config.title
|
|
39
|
+
saveBtnText.value = config.saveBtnText
|
|
40
|
+
mainKey.value = config.mainKey //表单主键
|
|
41
|
+
mainValue.value = rowData[config.mainKey] //表单主键值
|
|
42
|
+
dtoModel.value = {}
|
|
43
|
+
|
|
44
|
+
isShow.value = true
|
|
45
|
+
|
|
46
|
+
fetchFormData()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const fetchFormData = async () => {
|
|
50
|
+
if (loading.value) { return; }
|
|
51
|
+
loading.value = true
|
|
52
|
+
|
|
53
|
+
const res = await $curl({
|
|
54
|
+
method: 'get',
|
|
55
|
+
url: api.value,
|
|
56
|
+
query: {
|
|
57
|
+
[mainKey.value]: mainValue.value
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
loading.value = false
|
|
61
|
+
|
|
62
|
+
if (!res || !res.success || !res.data) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
dtoModel.value = res.data
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const close = () => {
|
|
69
|
+
isShow.value = false
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const save = async () => {
|
|
73
|
+
if (loading.value) { return; }
|
|
74
|
+
|
|
75
|
+
//校验表单
|
|
76
|
+
if (!schemaFormRef.value.validate()) { return; }
|
|
77
|
+
|
|
78
|
+
loading.value = true
|
|
79
|
+
const res = await $curl({
|
|
80
|
+
method: 'put',
|
|
81
|
+
url: api.value,
|
|
82
|
+
data: {
|
|
83
|
+
[mainKey.value]: mainValue.value,
|
|
84
|
+
...schemaFormRef.value.getValue()
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
loading.value = false
|
|
88
|
+
|
|
89
|
+
if (!res || !res.success) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
ElNotification({
|
|
94
|
+
title: '修改成功',
|
|
95
|
+
message: '修改成功',
|
|
96
|
+
type: 'success'
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
close()
|
|
100
|
+
|
|
101
|
+
emit('command', {
|
|
102
|
+
event: 'loadTableData'
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
defineExpose({
|
|
107
|
+
name, show
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
</script>
|
|
111
|
+
|
|
112
|
+
<style lang='less' scoped></style>
|
|
113
|
+
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { ref, onMounted, watch, 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
|
+
const buildData = function () {
|
|
17
|
+
const { key, sider_key: siderKey } = route.query;
|
|
18
|
+
|
|
19
|
+
const mItem = menuStore.findMenuItem({
|
|
20
|
+
key: 'key',
|
|
21
|
+
value: siderKey ?? key
|
|
22
|
+
})
|
|
23
|
+
if (mItem && mItem.schemaConfig) {
|
|
24
|
+
const { schemaConfig: sConfig } = mItem
|
|
25
|
+
const configSchema = JSON.parse(JSON.stringify(sConfig.schema))
|
|
26
|
+
api.value = sConfig.api ?? ''
|
|
27
|
+
tableSchema.value = {}
|
|
28
|
+
tableConfig.value = undefined;
|
|
29
|
+
searchSchema.value = {}
|
|
30
|
+
searchConfig.value = undefined;
|
|
31
|
+
components.value = {}
|
|
32
|
+
nextTick(() => {
|
|
33
|
+
//构造tableSchema 和tableConfig
|
|
34
|
+
tableSchema.value = buildDtoSchema(configSchema, 'table')
|
|
35
|
+
tableConfig.value = sConfig.schema.tableConfig
|
|
36
|
+
//构造searchSchema和searchConfig
|
|
37
|
+
const dtoSearchSchema = buildDtoSchema(configSchema, 'search')
|
|
38
|
+
for (const key in dtoSearchSchema.properties) {
|
|
39
|
+
if (route.query[key] !== undefined) {
|
|
40
|
+
dtoSearchSchema.properties[key].option.default = route.query[key]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
searchSchema.value = dtoSearchSchema
|
|
44
|
+
searchConfig.value = sConfig.schema.searchConfig
|
|
45
|
+
|
|
46
|
+
//构造 compoents = { comKey:{schema:{},config:{}} }
|
|
47
|
+
const { componentConfig } = sConfig
|
|
48
|
+
if (componentConfig && Object.keys(componentConfig).length > 0) {
|
|
49
|
+
const dtoComponents = {}
|
|
50
|
+
for (const comName in componentConfig) {
|
|
51
|
+
dtoComponents[comName] = {
|
|
52
|
+
schema: buildDtoSchema(configSchema, comName),
|
|
53
|
+
config: componentConfig[comName]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
components.value = dtoComponents
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//通用构建 schema 方法(清楚噪音)
|
|
63
|
+
const buildDtoSchema = (_schema, comName) => {
|
|
64
|
+
if (!_schema?.properties) { return {} }
|
|
65
|
+
|
|
66
|
+
const dtoSchema = {
|
|
67
|
+
type: 'object',
|
|
68
|
+
properties: {}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//提取有效 scema 字段信息
|
|
72
|
+
for (const key in _schema.properties) {
|
|
73
|
+
const props = _schema.properties[key]
|
|
74
|
+
if (props[`${comName}Option`]) {
|
|
75
|
+
let dtoProps = {}
|
|
76
|
+
//提取 props 中 非 option 的部分,放到dtoProps 中
|
|
77
|
+
for (const pKey in props) {
|
|
78
|
+
if (pKey.indexOf('Option') < 0) {
|
|
79
|
+
dtoProps[pKey] = props[pKey]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//处理 comName Option
|
|
83
|
+
dtoProps = Object.assign({}, dtoProps, { option: props[`${comName}Option`] })
|
|
84
|
+
|
|
85
|
+
//处理 required 字段
|
|
86
|
+
const { required } = _schema
|
|
87
|
+
if (required && required.find(pk => pk === key)) {
|
|
88
|
+
dtoProps.option.required = true
|
|
89
|
+
}
|
|
90
|
+
dtoSchema.properties[key] = dtoProps
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return dtoSchema;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
watch([
|
|
97
|
+
() => route.query.key,
|
|
98
|
+
() => route.query.sider_key,
|
|
99
|
+
() => menuStore.menuList,
|
|
100
|
+
], () => {
|
|
101
|
+
buildData()
|
|
102
|
+
}, { deep: true })
|
|
103
|
+
|
|
104
|
+
onMounted(() => {
|
|
105
|
+
buildData()
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
return { api, tableSchema, tableConfig, searchSchema, searchConfig, components };
|
|
109
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-row class="schema-view">
|
|
3
|
+
<search-panel v-if="searchSchema?.properties && Object.keys(searchSchema.properties).length > 0"
|
|
4
|
+
@search="onSearch"></search-panel>
|
|
5
|
+
<table-panel ref="tablePanelRef" @operate="onTableOperate"></table-panel>
|
|
6
|
+
<component v-for="(item, key) in components" :key="key" :is="ComponentConfig[key]?.component" ref="comListRef"
|
|
7
|
+
@command="onComponentCommand"></component>
|
|
8
|
+
</el-row>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script setup>
|
|
12
|
+
import { ref, provide } from 'vue';
|
|
13
|
+
import SearchPanel from './complex-view/search-panel/search-panel.vue'
|
|
14
|
+
import TablePanel from './complex-view/table-panel/table-panel.vue'
|
|
15
|
+
import ComponentConfig from './components/component-config';
|
|
16
|
+
import { useSchema } from './hook/schema'
|
|
17
|
+
|
|
18
|
+
const { api, tableSchema, tableConfig, searchSchema, searchConfig, components } = useSchema()
|
|
19
|
+
const apiParams = ref({})
|
|
20
|
+
provide('schemaViewData', {
|
|
21
|
+
api, tableSchema, tableConfig, searchSchema, searchConfig, apiParams, components
|
|
22
|
+
})
|
|
23
|
+
const tablePanelRef = ref(null)
|
|
24
|
+
const comListRef = ref([])
|
|
25
|
+
const onSearch = (searchValObj) => {
|
|
26
|
+
apiParams.value = searchValObj
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//table 事件映射
|
|
30
|
+
const EventHandlerMap = {
|
|
31
|
+
showComponent: showComponent
|
|
32
|
+
}
|
|
33
|
+
const onTableOperate = ({ btnConfig, rowData }) => {
|
|
34
|
+
const { eventKey } = btnConfig;
|
|
35
|
+
if (EventHandlerMap[eventKey]) {
|
|
36
|
+
EventHandlerMap[eventKey]({ btnConfig, rowData })
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function showComponent({ btnConfig, rowData }) {
|
|
41
|
+
console.log({ btnConfig, rowData }, '99999');
|
|
42
|
+
const { comName } = btnConfig.eventOption
|
|
43
|
+
if (!comName) { return; }
|
|
44
|
+
const comRef = comListRef.value.find(item => item.name === comName)
|
|
45
|
+
|
|
46
|
+
if (!comRef || typeof comRef.show !== 'function') { return; }
|
|
47
|
+
comRef.show(rowData)
|
|
48
|
+
}
|
|
49
|
+
//响应组件事件
|
|
50
|
+
const onComponentCommand = (data) => {
|
|
51
|
+
const { event } = data
|
|
52
|
+
if (event === 'loadTableData') {
|
|
53
|
+
tablePanelRef.value.loadTableData()
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<style lang='less' scoped>
|
|
59
|
+
.schema-view {
|
|
60
|
+
display: flex;
|
|
61
|
+
flex-direction: column;
|
|
62
|
+
height: 100%;
|
|
63
|
+
width: 100%;
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
66
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-sub-menu :index="menuItem.key">
|
|
3
|
+
<template #title>{{ menuItem.name }}</template>
|
|
4
|
+
<div :key="item.key" v-for="item in menuItem.subMenu">
|
|
5
|
+
<sub-menu v-if="item.subMenu && item.subMenu.length > 0" :menu-item="item"></sub-menu>
|
|
6
|
+
<el-menu-item v-else :index="item.key">{{ item.name }}</el-menu-item>
|
|
7
|
+
</div>
|
|
8
|
+
</el-sub-menu>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script setup>
|
|
12
|
+
// import { ref } from 'vue'
|
|
13
|
+
const { menuItem } = defineProps(['menuItem'])
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<style lang='less' scoped></style>
|
|
17
|
+
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<sider-container>
|
|
3
|
+
<template #menu-content>
|
|
4
|
+
<el-menu :default-active="activeKey" :ellipsis="false" @select="onMenuSelect">
|
|
5
|
+
<template v-for="item in menuList">
|
|
6
|
+
<sub-menu v-if="item.subMenu && item.subMenu.length > 0" :menu-item="item"></sub-menu>
|
|
7
|
+
<el-menu-item v-else :index="item.key">{{ item.name }}</el-menu-item>
|
|
8
|
+
</template>
|
|
9
|
+
</el-menu>
|
|
10
|
+
</template>
|
|
11
|
+
<template #main-content>
|
|
12
|
+
<router-view></router-view>
|
|
13
|
+
</template>
|
|
14
|
+
</sider-container>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script setup>
|
|
18
|
+
import { ref, watch, onMounted } from 'vue'
|
|
19
|
+
import { useRoute, useRouter } from 'vue-router'
|
|
20
|
+
import { useMenuStore } from '$elpisStore/menu.js'
|
|
21
|
+
import siderContainer from '$elpisWidgets/sider-container/sider-container.vue';
|
|
22
|
+
import SubMenu from './complex-view/sub-menu/sub-menu.vue'
|
|
23
|
+
|
|
24
|
+
const route = useRoute()
|
|
25
|
+
const router = useRouter()
|
|
26
|
+
const menuStore = useMenuStore()
|
|
27
|
+
|
|
28
|
+
const menuList = ref([])
|
|
29
|
+
const setMenuList = function () {
|
|
30
|
+
const menuItem = menuStore.findMenuItem({
|
|
31
|
+
key: 'key',
|
|
32
|
+
value: route.query.key
|
|
33
|
+
})
|
|
34
|
+
console.log(menuItem, 'menuItem');
|
|
35
|
+
if (menuItem && menuItem.siderConfig && menuItem.siderConfig.menu) {
|
|
36
|
+
menuList.value = menuItem.siderConfig.menu
|
|
37
|
+
}
|
|
38
|
+
console.log(menuList, 'menuList');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const activeKey = ref('')
|
|
42
|
+
const setActiveKey = function () {
|
|
43
|
+
let siderMenuItem = menuStore.findMenuItem({
|
|
44
|
+
key: 'key',
|
|
45
|
+
value: route.query.sider_key
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
//如果首次加载 sider-view,用户未选中左侧菜单,需要默认选中第一个
|
|
49
|
+
if (!siderMenuItem) {
|
|
50
|
+
const hmenuItem = menuStore.findMenuItem({
|
|
51
|
+
key: 'key',
|
|
52
|
+
value: route.query.key
|
|
53
|
+
})
|
|
54
|
+
if (hmenuItem && hmenuItem.siderConfig && hmenuItem.siderConfig.menu) {
|
|
55
|
+
const siderMenuList = hmenuItem.siderConfig.menu
|
|
56
|
+
siderMenuItem = menuStore.findFirstMenuItem(siderMenuList);//找出左侧菜单第一项
|
|
57
|
+
if (siderMenuItem) {
|
|
58
|
+
//处理选中菜单逻辑
|
|
59
|
+
handleMenuSelect(siderMenuItem.key)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
activeKey.value = siderMenuItem?.key
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
watch(() => route.query.key, () => {
|
|
67
|
+
setMenuList()
|
|
68
|
+
setActiveKey();
|
|
69
|
+
|
|
70
|
+
})
|
|
71
|
+
watch(() => menuStore.menuList, () => {
|
|
72
|
+
setMenuList();
|
|
73
|
+
setActiveKey();
|
|
74
|
+
|
|
75
|
+
}, { deep: true })
|
|
76
|
+
onMounted(() => {
|
|
77
|
+
setMenuList();
|
|
78
|
+
setActiveKey();
|
|
79
|
+
console.log('进入----');
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
const onMenuSelect = function (menuKey) {
|
|
84
|
+
handleMenuSelect(menuKey)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const handleMenuSelect = function (menuKey) {
|
|
88
|
+
const menuItem = menuStore.findMenuItem({
|
|
89
|
+
key: 'key',
|
|
90
|
+
value: menuKey
|
|
91
|
+
})
|
|
92
|
+
//处理选中菜单逻辑
|
|
93
|
+
const { moduleType, key, customConfig } = menuItem
|
|
94
|
+
//如果是当前页,不处理
|
|
95
|
+
if (key === route.query.sider_key) { return; }
|
|
96
|
+
|
|
97
|
+
const pathMap = {
|
|
98
|
+
iframe: '/iframe',
|
|
99
|
+
schema: '/schema',
|
|
100
|
+
custom: customConfig?.path
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
router.push({
|
|
104
|
+
path: `/view/dashboard/sider${pathMap[moduleType]}`,
|
|
105
|
+
query: {
|
|
106
|
+
key: route.query.key,
|
|
107
|
+
sider_key: key,
|
|
108
|
+
proj_key: route.query.proj_key,
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
</script>
|
|
114
|
+
|
|
115
|
+
<style lang='less' scoped></style>
|
|
116
|
+
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-config-provider :locale="zhCn">
|
|
3
|
+
<header-view :proj-name="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 { useRouter, useRoute } from 'vue-router'
|
|
14
|
+
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
|
15
|
+
import HeaderView from './complex-view/header-view/header-view.vue'
|
|
16
|
+
import $curl from '$elpisCommon/curl.js'
|
|
17
|
+
import { useMenuStore } from '$elpisStore/menu.js'
|
|
18
|
+
import { useProjectStore } from '$elpisStore/project.js'
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
const route = useRoute()
|
|
22
|
+
const router = useRouter()
|
|
23
|
+
const menuStore = useMenuStore()
|
|
24
|
+
const projectStore = useProjectStore()
|
|
25
|
+
const projName = ref(' ')
|
|
26
|
+
onMounted(() => {
|
|
27
|
+
getProjectList();
|
|
28
|
+
getProjectConfig();
|
|
29
|
+
})
|
|
30
|
+
//请求/api/project/list 接口,并缓存到 project-store 中
|
|
31
|
+
async function getProjectList() {
|
|
32
|
+
const res = await $curl({
|
|
33
|
+
method: 'get',
|
|
34
|
+
url: '/api/project/list',
|
|
35
|
+
query: {
|
|
36
|
+
//TODO: 动态获取当前项目的key
|
|
37
|
+
proj_key: route.query.proj_key
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (!res || !res.success || !res.data) {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
projectStore.setProjectList(res.data)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//请求/api/project接口,并缓存到 menu-store 中
|
|
49
|
+
async function getProjectConfig() {
|
|
50
|
+
const res = await $curl({
|
|
51
|
+
method: 'get',
|
|
52
|
+
url: '/api/project',
|
|
53
|
+
query: {
|
|
54
|
+
//TODO: 动态获取当前项目的key
|
|
55
|
+
proj_key: route.query.proj_key
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (!res || !res.success || !res.data) {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
const { name, menu } = res.data
|
|
63
|
+
projName.value = name
|
|
64
|
+
menuStore.setMenuList(menu)
|
|
65
|
+
}
|
|
66
|
+
//点击菜单回调
|
|
67
|
+
const onMenuSelect = function (menuItme) {
|
|
68
|
+
console.log(menuItme, 'menuItme');
|
|
69
|
+
const { moduleType, key, customConfig } = menuItme
|
|
70
|
+
//如果是当前页,不处理
|
|
71
|
+
if (key === route.query.key) { return; }
|
|
72
|
+
|
|
73
|
+
const pathMap = {
|
|
74
|
+
sider: '/sider',
|
|
75
|
+
iframe: '/iframe',
|
|
76
|
+
schema: '/schema',
|
|
77
|
+
custom: customConfig?.path
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
router.push({
|
|
81
|
+
path: `/view/dashboard${pathMap[moduleType]}`,
|
|
82
|
+
query: {
|
|
83
|
+
key,
|
|
84
|
+
proj_key: route.query.proj_key
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<style lang='less' scoped>
|
|
92
|
+
:deep(.el-main) {
|
|
93
|
+
padding: 0;
|
|
94
|
+
}
|
|
95
|
+
</style>
|
|
96
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import boot from '$elpisPages/boot.js'
|
|
2
|
+
import dashboard from './dashboard.vue'
|
|
3
|
+
import businessDashboardRouterConfig from '$businessDashboardRouterConfig'
|
|
4
|
+
|
|
5
|
+
const routes = []
|
|
6
|
+
|
|
7
|
+
//头部菜单路由
|
|
8
|
+
routes.push({
|
|
9
|
+
path: '/view/dashboard/iframe',
|
|
10
|
+
component: () => import('./complex-view/iframe-view/iframe-view.vue')
|
|
11
|
+
})
|
|
12
|
+
routes.push({
|
|
13
|
+
path: '/view/dashboard/schema',
|
|
14
|
+
component: () => import('./complex-view/schema-view/schema-view.vue')
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const siderRoutes = [{
|
|
18
|
+
path:'iframe',
|
|
19
|
+
component:() => import('./complex-view/iframe-view/iframe-view.vue')
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
path:'schema',
|
|
23
|
+
component:() => import('./complex-view/schema-view/schema-view.vue')
|
|
24
|
+
}]
|
|
25
|
+
|
|
26
|
+
//侧边栏菜单路由
|
|
27
|
+
routes.push({
|
|
28
|
+
path: '/view/dashboard/sider',
|
|
29
|
+
component: () => import('./complex-view/sider-view/sider-view.vue'),
|
|
30
|
+
// 所有子路由都放在 children 数组里
|
|
31
|
+
children:siderRoutes
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
//业务扩展路由
|
|
35
|
+
if(typeof businessDashboardRouterConfig === 'function'){
|
|
36
|
+
businessDashboardRouterConfig({routes,siderRoutes})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//侧边栏兜底菜单路由
|
|
40
|
+
routes.push({
|
|
41
|
+
path:'/view/dashboard/sider/:chapters+',
|
|
42
|
+
component: () => import('./complex-view/sider-view/sider-view.vue')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
boot(dashboard, { routes })
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
export const useMenuStore = defineStore('menu', () => {
|
|
5
|
+
// 菜单列表
|
|
6
|
+
const menuList = ref([])
|
|
7
|
+
|
|
8
|
+
//设置菜单配置
|
|
9
|
+
const setMenuList = function (list) {
|
|
10
|
+
menuList.value = list
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 找出菜单目录
|
|
14
|
+
* @param {key} 搜索字段
|
|
15
|
+
* @param {value} 搜索值
|
|
16
|
+
* @param {mList} 要搜索的菜单列表
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const findMenuItem = function ({ key, value }, mList = menuList.value) {
|
|
20
|
+
for (let i = 0; i < mList.length; i++) {
|
|
21
|
+
const menuItem = mList[i]
|
|
22
|
+
|
|
23
|
+
if (!menuItem) { continue; }
|
|
24
|
+
|
|
25
|
+
const { menuType, moduleType } = menuItem
|
|
26
|
+
if (menuItem[key] === value) {
|
|
27
|
+
return menuItem;
|
|
28
|
+
}
|
|
29
|
+
if (menuType === 'group' && menuItem.subMenu) {
|
|
30
|
+
const mItem = findMenuItem({ key, value }, menuItem.subMenu)
|
|
31
|
+
if (mItem) { return mItem };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (moduleType === 'sider' && menuItem.siderConfig && menuItem.siderConfig.menu) {
|
|
35
|
+
const mItme = findMenuItem({ key, value }, menuItem.siderConfig.menu)
|
|
36
|
+
if (mItme) { return mItme }
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 找出第一个菜单目录
|
|
43
|
+
* @param {mList} 要搜索的菜单列表
|
|
44
|
+
*/
|
|
45
|
+
const findFirstMenuItem = function(mList = menuList.value) {
|
|
46
|
+
if(!mList || !mList[0]){return;}
|
|
47
|
+
let firstMenuItme = mList[0]
|
|
48
|
+
if(firstMenuItme.subMenu){
|
|
49
|
+
firstMenuItme = findFirstMenuItem(firstMenuItme.subMenu)
|
|
50
|
+
}
|
|
51
|
+
return firstMenuItme;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
menuList,
|
|
56
|
+
setMenuList,
|
|
57
|
+
findMenuItem,
|
|
58
|
+
findFirstMenuItem
|
|
59
|
+
}
|
|
60
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
export const useProjectStore = defineStore('project',() => {
|
|
5
|
+
// 菜单列表
|
|
6
|
+
const projectList = ref([])
|
|
7
|
+
|
|
8
|
+
//设置菜单配置
|
|
9
|
+
const setProjectList = function(list){
|
|
10
|
+
projectList.value = list
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
projectList,
|
|
15
|
+
setProjectList
|
|
16
|
+
}
|
|
17
|
+
})
|
|
Binary file
|
|
Binary file
|