@lixianwei/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 +2 -0
- package/.eslintrc +55 -0
- package/.idea/dictionaries/project.xml +8 -0
- package/.idea/elpis.iml +8 -0
- package/.idea/git_toolbox_prj.xml +15 -0
- package/.idea/inspectionProfiles/Project_Default.xml +329 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/README.md +201 -0
- package/app/controller/base.js +77 -0
- package/app/controller/project.js +69 -0
- package/app/controller/view.js +20 -0
- package/app/extend/logger.js +35 -0
- package/app/middleware/api-params-verify.js +74 -0
- package/app/middleware/api-sign-verify.js +33 -0
- package/app/middleware/error-hander.js +32 -0
- package/app/middleware/project-handler.js +25 -0
- package/app/middleware.js +37 -0
- package/app/pages/asserts/custom.css +11 -0
- package/app/pages/boot.js +43 -0
- package/app/pages/common/curl.js +83 -0
- package/app/pages/common/index.js +2 -0
- package/app/pages/common/utils.js +0 -0
- package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +23 -0
- package/app/pages/dashboard/complex-view/header-view/header-view.vue +117 -0
- package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +40 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +45 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/tabel-panel/tabel-panel.vue +134 -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 +89 -0
- package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +101 -0
- package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +128 -0
- package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +119 -0
- package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +96 -0
- package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +21 -0
- package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +117 -0
- package/app/pages/dashboard/dashboard.vue +88 -0
- package/app/pages/dashboard/entry.dashboard.js +41 -0
- package/app/pages/router/index.js +11 -0
- package/app/pages/store/index.js +4 -0
- package/app/pages/store/menu.js +65 -0
- package/app/pages/store/project.js +16 -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 +103 -0
- package/app/pages/widgets/schema-form/complex-view/input/input.vue +142 -0
- package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +143 -0
- package/app/pages/widgets/schema-form/complex-view/select/select.vue +130 -0
- package/app/pages/widgets/schema-form/form-item-config.js +20 -0
- package/app/pages/widgets/schema-form/schema-form.vue +132 -0
- package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +48 -0
- package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +67 -0
- package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +40 -0
- package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +50 -0
- package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +142 -0
- package/app/pages/widgets/schema-search-bar/search-item-config.js +24 -0
- package/app/pages/widgets/schema-table/schema-table.vue +238 -0
- package/app/pages/widgets/sider-container/sider-container.vue +31 -0
- package/app/public/static/logo.png +0 -0
- package/app/public/static/normalize.css +239 -0
- package/app/router/project.js +9 -0
- package/app/router/view.js +7 -0
- package/app/router-schema/project.js +32 -0
- package/app/service/base.js +12 -0
- package/app/service/project.js +42 -0
- package/app/view/entry.tpl +26 -0
- package/app/webpack/config/webpack.base.js +219 -0
- package/app/webpack/config/webpack.dev.js +55 -0
- package/app/webpack/config/webpack.prod.js +118 -0
- package/app/webpack/dev.js +52 -0
- package/app/webpack/libs/blank.js +2 -0
- package/app/webpack/prod.js +18 -0
- package/config/config.default.js +3 -0
- package/elpis-core/env.js +20 -0
- package/elpis-core/index.js +92 -0
- package/elpis-core/loader/config.js +54 -0
- package/elpis-core/loader/controller.js +61 -0
- package/elpis-core/loader/extend.js +55 -0
- package/elpis-core/loader/middleware.js +61 -0
- package/elpis-core/loader/router-schema.js +39 -0
- package/elpis-core/loader/router.js +42 -0
- package/elpis-core/loader/service.js +64 -0
- package/index.js +41 -0
- package/model/index.js +105 -0
- package/package.json +94 -0
- package/test/controller/project.test.js +194 -0
|
@@ -0,0 +1,128 @@
|
|
|
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
|
+
ref="schemaFormRef"
|
|
14
|
+
v-loading="loading"
|
|
15
|
+
:schema="components[name].schema"
|
|
16
|
+
:model="dtoModel"
|
|
17
|
+
/>
|
|
18
|
+
</template>
|
|
19
|
+
<template #footer>
|
|
20
|
+
<el-button
|
|
21
|
+
type="primary"
|
|
22
|
+
@click="save"
|
|
23
|
+
>
|
|
24
|
+
{{ saveBtnText }}
|
|
25
|
+
</el-button>
|
|
26
|
+
</template>
|
|
27
|
+
</el-drawer>
|
|
28
|
+
</template>
|
|
29
|
+
<script setup>
|
|
30
|
+
import {ref, inject} from 'vue'
|
|
31
|
+
import {ElNotification} from 'element-plus'
|
|
32
|
+
import $curl from '$elpisCommon/curl.js'
|
|
33
|
+
import SchemaForm from '$elpisWidgets/schema-form/schema-form.vue'
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
const {api,components} = inject('schemaViewData')
|
|
37
|
+
const emit = defineEmits(['command'])
|
|
38
|
+
|
|
39
|
+
const name = ref('editForm')
|
|
40
|
+
const schemaFormRef = ref(null)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
const title =ref('')
|
|
44
|
+
const saveBtnText = ref('')
|
|
45
|
+
const isShow = ref(false)
|
|
46
|
+
const loading = ref(false)
|
|
47
|
+
|
|
48
|
+
const mainKey = ref('')
|
|
49
|
+
const mainValue = ref({})
|
|
50
|
+
const dtoModel = ref({})
|
|
51
|
+
|
|
52
|
+
const show = async (rowData)=>{
|
|
53
|
+
const {config} = components.value[name.value]
|
|
54
|
+
title.value = config.title
|
|
55
|
+
saveBtnText.value = config.saveBtnText
|
|
56
|
+
// 获取设置数据的唯一值字段
|
|
57
|
+
mainKey.value = config.mainKey
|
|
58
|
+
// 获取数据唯一值字段的值
|
|
59
|
+
mainValue.value = rowData[config.mainKey]
|
|
60
|
+
|
|
61
|
+
isShow.value = true
|
|
62
|
+
|
|
63
|
+
fetchFormData()
|
|
64
|
+
}
|
|
65
|
+
// 关闭弹窗
|
|
66
|
+
const close =()=>{
|
|
67
|
+
isShow.value = false
|
|
68
|
+
}
|
|
69
|
+
// 获取form详情
|
|
70
|
+
const fetchFormData = async ()=>{
|
|
71
|
+
if(loading.value){ return}
|
|
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
|
+
if(!res || !res.success || !res.data){
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
dtoModel.value = res.data
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 保存
|
|
88
|
+
|
|
89
|
+
const save = async (rowData)=>{
|
|
90
|
+
if(loading.value){ return }
|
|
91
|
+
if(!schemaFormRef.value.validate()){return}
|
|
92
|
+
loading.value = true
|
|
93
|
+
const res = await $curl({
|
|
94
|
+
method: 'put',
|
|
95
|
+
url:api.value,
|
|
96
|
+
data:{
|
|
97
|
+
[mainKey.value]:mainValue.value,
|
|
98
|
+
...schemaFormRef.value.getValue()
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
loading.value = false
|
|
102
|
+
|
|
103
|
+
if(!res || !res.success ){
|
|
104
|
+
return
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
ElNotification({
|
|
108
|
+
title:"修改成功",
|
|
109
|
+
message:"修改成功",
|
|
110
|
+
type: 'success'
|
|
111
|
+
})
|
|
112
|
+
close()
|
|
113
|
+
emit('command',{
|
|
114
|
+
event:'loadTableData',
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
defineExpose({
|
|
119
|
+
name,
|
|
120
|
+
show
|
|
121
|
+
})
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
<style scoped lang="less">
|
|
127
|
+
|
|
128
|
+
</style>
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import {ref,watch,onMounted,nextTick} from 'vue';
|
|
2
|
+
import {useRoute} from "vue-router";
|
|
3
|
+
import {userMenuStore} from "$elpisStore/menu";
|
|
4
|
+
|
|
5
|
+
export const useSchema = function (){
|
|
6
|
+
const menuStore = userMenuStore()
|
|
7
|
+
const route = useRoute()
|
|
8
|
+
const api = ref('')
|
|
9
|
+
const tableSchema = ref({})
|
|
10
|
+
const tableConfig = ref()
|
|
11
|
+
const searchSchema = ref({})
|
|
12
|
+
const searchConfig = ref()
|
|
13
|
+
const components = ref({})
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
// 构造schemaConfig 相关配置,输送给schemaView解释
|
|
17
|
+
const buildData = () => {
|
|
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
|
+
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
|
+
|
|
33
|
+
nextTick(()=>{
|
|
34
|
+
|
|
35
|
+
// 构造tableSchema和tableConfig
|
|
36
|
+
tableSchema.value = bindDtoSchema(configSchema,'table')
|
|
37
|
+
tableConfig.value = sConfig.tableConfig
|
|
38
|
+
// 构造searchSchema和searchConfig
|
|
39
|
+
const dtoSearchSchema= bindDtoSchema(configSchema,'search')
|
|
40
|
+
// 处理路由传参的现象,使用schema里面的数据和路由的数据进行匹配,查看是否有值,有值的情况下就进行赋值
|
|
41
|
+
for(const key in dtoSearchSchema.properties){
|
|
42
|
+
if(route.query[key] !== undefined){
|
|
43
|
+
dtoSearchSchema.properties[key].option.default = route.query[key]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
searchSchema.value = dtoSearchSchema
|
|
48
|
+
searchConfig.value = sConfig.searchConfig
|
|
49
|
+
|
|
50
|
+
// 构造 components = {key:{schema:{},config:{}}}
|
|
51
|
+
const {componentConfig} = sConfig
|
|
52
|
+
if(componentConfig && Object.keys(componentConfig).length>0){
|
|
53
|
+
const dtoComponents ={}
|
|
54
|
+
for(const comName in componentConfig){
|
|
55
|
+
dtoComponents[comName]={
|
|
56
|
+
schema: bindDtoSchema(configSchema,comName),
|
|
57
|
+
config: componentConfig[comName]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
components.value = dtoComponents
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// 通用构建schema方法
|
|
67
|
+
const bindDtoSchema =(_schema,comName)=>{
|
|
68
|
+
if(!_schema?.properties){ return {}}
|
|
69
|
+
const dtoSchema ={
|
|
70
|
+
type:'object',
|
|
71
|
+
properties:{}
|
|
72
|
+
}
|
|
73
|
+
// 提取有效的schema 字段信息
|
|
74
|
+
for(let key in _schema.properties){
|
|
75
|
+
const props = _schema.properties[key]
|
|
76
|
+
if(props[`${comName}Option`]){
|
|
77
|
+
let dtoProps={}
|
|
78
|
+
// 提取props中非option的部分 存放到dtoProps中
|
|
79
|
+
for(const pKey in props){
|
|
80
|
+
if(pKey.indexOf('Option') < 0 ){
|
|
81
|
+
dtoProps[pKey] = props[pKey]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// 处理comName Option
|
|
85
|
+
dtoProps = Object.assign({},dtoProps,{option:props[`${comName}Option`]})
|
|
86
|
+
dtoSchema.properties[key] = dtoProps;
|
|
87
|
+
|
|
88
|
+
// 处理required 字段
|
|
89
|
+
const {required} = _schema
|
|
90
|
+
if(required && required.find(pk=>pk===key)){
|
|
91
|
+
dtoProps.option.required = true
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return dtoSchema
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
watch([
|
|
100
|
+
()=> route.query.key,
|
|
101
|
+
()=> route.query.sider_key,
|
|
102
|
+
()=> menuStore.menuList
|
|
103
|
+
],()=>{
|
|
104
|
+
buildData()
|
|
105
|
+
},{deep:true})
|
|
106
|
+
|
|
107
|
+
onMounted(()=>{
|
|
108
|
+
buildData()
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
api,
|
|
113
|
+
tableSchema,
|
|
114
|
+
tableConfig,
|
|
115
|
+
searchSchema,
|
|
116
|
+
searchConfig,
|
|
117
|
+
components
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
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
|
+
/>
|
|
7
|
+
<table-panel @operate="handelOperate" ref="tablePanelRef" />
|
|
8
|
+
|
|
9
|
+
<component
|
|
10
|
+
v-for="(item,key) in Object.keys(components)"
|
|
11
|
+
:is="ComponentConfig[item].component"
|
|
12
|
+
:key="key"
|
|
13
|
+
ref="comListRef"
|
|
14
|
+
@command="onComponentCommand"
|
|
15
|
+
/>
|
|
16
|
+
</el-row>
|
|
17
|
+
</template>
|
|
18
|
+
<script setup>
|
|
19
|
+
import { provide,ref} from "vue";
|
|
20
|
+
import SearchPanel from './complex-view/search-panel/search-panel.vue'
|
|
21
|
+
import TablePanel from './complex-view/tabel-panel/tabel-panel.vue'
|
|
22
|
+
import { useSchema } from './hook/schema.js'
|
|
23
|
+
import ComponentConfig from "./components/component-config";
|
|
24
|
+
const {api,tableConfig,tableSchema,searchSchema,searchConfig,components} = useSchema()
|
|
25
|
+
|
|
26
|
+
// console.log
|
|
27
|
+
|
|
28
|
+
const apiParams = ref({})
|
|
29
|
+
provide('schemaViewData',{
|
|
30
|
+
api,
|
|
31
|
+
tableConfig,
|
|
32
|
+
tableSchema,
|
|
33
|
+
searchSchema,
|
|
34
|
+
searchConfig,
|
|
35
|
+
apiParams,
|
|
36
|
+
components
|
|
37
|
+
})
|
|
38
|
+
const tablePanelRef = ref(null)
|
|
39
|
+
const comListRef = ref([])
|
|
40
|
+
|
|
41
|
+
// 搜索
|
|
42
|
+
const onSearch =(searchValObj)=>{
|
|
43
|
+
console.log(searchValObj)
|
|
44
|
+
apiParams.value =searchValObj
|
|
45
|
+
}
|
|
46
|
+
// showComponent 展示动态组件
|
|
47
|
+
const showComponent =({btnConfig,rowData})=>{
|
|
48
|
+
// 提取规则配置里面的组件名称
|
|
49
|
+
const {comName} = btnConfig.eventOption
|
|
50
|
+
// 如果没有就阻止进行
|
|
51
|
+
if(!comName) {
|
|
52
|
+
console.error(`找不到组件:${comName}`)
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// 如果存在就根据组件名在组件中循环找到这相对应的组件
|
|
56
|
+
const comRef = comListRef.value.find((item)=>item.name === comName)
|
|
57
|
+
console.log(comRef)
|
|
58
|
+
// 如果没有找到,或者组件中没有 show 方法也阻止
|
|
59
|
+
if(!comRef || typeof comRef.show !== 'function') {return;}
|
|
60
|
+
// 如果找到了就调用组件中的 show 方法
|
|
61
|
+
comRef.show(rowData)
|
|
62
|
+
}
|
|
63
|
+
// table 事件映射
|
|
64
|
+
const EventHandlerMap ={
|
|
65
|
+
showComponent:showComponent
|
|
66
|
+
}
|
|
67
|
+
// 点击按钮事件
|
|
68
|
+
const handelOperate =({btnConfig,rowData})=>{
|
|
69
|
+
// 找到规则中的eventKey 事件名称
|
|
70
|
+
const {eventKey} = btnConfig;
|
|
71
|
+
// 判断事件映射是否存在
|
|
72
|
+
if(EventHandlerMap[eventKey]){
|
|
73
|
+
// 如果存在就调用这个方法
|
|
74
|
+
EventHandlerMap[eventKey]({btnConfig,rowData})
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const onComponentCommand=(data)=>{
|
|
79
|
+
const {event} = data
|
|
80
|
+
if(event==='loadTableData'){
|
|
81
|
+
tablePanelRef.value.loadTableData()
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
<style scoped lang="less">
|
|
90
|
+
.schema-view {
|
|
91
|
+
display: flex;
|
|
92
|
+
flex-direction: column;
|
|
93
|
+
width: 100%;
|
|
94
|
+
height: 100%;
|
|
95
|
+
}
|
|
96
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
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 v-else :index="item.key">{{item.name}}</el-menu-item>
|
|
12
|
+
</div>
|
|
13
|
+
</el-sub-menu>
|
|
14
|
+
</template>
|
|
15
|
+
<script setup >
|
|
16
|
+
const {menuItem} = defineProps(['menuItem'])
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<style scoped lang="less">
|
|
20
|
+
|
|
21
|
+
</style>
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
<template>
|
|
4
|
+
<sider-container>
|
|
5
|
+
<template #menu-content>
|
|
6
|
+
<el-menu :default-active="activeKey" :ellipsis="false" @select="onMenuSelect">
|
|
7
|
+
<template v-for="item in menuList" :key="item.key">
|
|
8
|
+
<sub-menu
|
|
9
|
+
v-if="item.subMenu &&item.subMenu.length>0"
|
|
10
|
+
:menu-item="item"
|
|
11
|
+
>
|
|
12
|
+
</sub-menu>
|
|
13
|
+
<el-menu-item v-else :index="item.key">{{item.name}}</el-menu-item>
|
|
14
|
+
</template>
|
|
15
|
+
</el-menu>
|
|
16
|
+
</template>
|
|
17
|
+
<template #main-content>
|
|
18
|
+
<router-view />
|
|
19
|
+
</template>
|
|
20
|
+
</sider-container>
|
|
21
|
+
</template>
|
|
22
|
+
<script setup>
|
|
23
|
+
import {ref,watch,onMounted} from 'vue'
|
|
24
|
+
import {useRouter,useRoute} from 'vue-router'
|
|
25
|
+
import {userMenuStore} from "$elpisStore/menu";
|
|
26
|
+
import SiderContainer from "$elpisWidgets/sider-container/sider-container.vue";
|
|
27
|
+
import SubMenu from './complex-view/sub-menu/sub-menu.vue'
|
|
28
|
+
|
|
29
|
+
const router = useRouter();
|
|
30
|
+
const route = useRoute();
|
|
31
|
+
const menuStore = userMenuStore()
|
|
32
|
+
|
|
33
|
+
const menuList = ref([])
|
|
34
|
+
const setMenuList = ()=>{
|
|
35
|
+
const menuItem = menuStore.findMenuItem({
|
|
36
|
+
key:'key',
|
|
37
|
+
value:route.query.key
|
|
38
|
+
})
|
|
39
|
+
if(menuItem && menuItem.siderConfig && menuItem.siderConfig.menu) {
|
|
40
|
+
menuList.value = menuItem.siderConfig.menu
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
const activeKey = ref('');
|
|
46
|
+
const setActiveKey = () => {
|
|
47
|
+
let siderMenuItem = menuStore.findMenuItem({
|
|
48
|
+
key:'key',
|
|
49
|
+
value:route.query.sider_key
|
|
50
|
+
})
|
|
51
|
+
// 如果是首次加载 sider-view 用户未选中左侧菜单 需要默认选中第一个
|
|
52
|
+
if(!siderMenuItem) {
|
|
53
|
+
const hMenuItem = menuStore.findMenuItem({key:'key', value:route.query.key});
|
|
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
|
+
|
|
67
|
+
watch(()=> route.query.key, () => {
|
|
68
|
+
setActiveKey()
|
|
69
|
+
setMenuList()
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
watch(() => menuStore.menuList, () => {
|
|
73
|
+
setActiveKey()
|
|
74
|
+
setMenuList()
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
onMounted(() => {
|
|
78
|
+
setActiveKey()
|
|
79
|
+
setMenuList()
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
const onMenuSelect =(menuKey)=>{
|
|
84
|
+
handleMenuSelect(menuKey)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const handleMenuSelect = (menuKey)=>{
|
|
88
|
+
const menuItem = menuStore.findMenuItem({key:'key',value:menuKey})
|
|
89
|
+
if(!menuItem) {return}
|
|
90
|
+
|
|
91
|
+
const {moduleType,key,customConfig} = menuItem
|
|
92
|
+
|
|
93
|
+
// 与顶部菜单的 key 区分:这里应判断当前左侧已选中的 sider_key
|
|
94
|
+
if(key === route.query.sider_key) {return }
|
|
95
|
+
|
|
96
|
+
const pathMap={
|
|
97
|
+
iframe:'/iframe',
|
|
98
|
+
schema:'/schema',
|
|
99
|
+
custom:customConfig?.path,
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
router.push({
|
|
103
|
+
path:`/view/dashboard/sider${pathMap[moduleType]}`,
|
|
104
|
+
query:{
|
|
105
|
+
key: route.query.key,
|
|
106
|
+
sider_key:key,
|
|
107
|
+
proj_key:route.query.proj_key
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
</script>
|
|
114
|
+
|
|
115
|
+
<style scoped lang="less">
|
|
116
|
+
|
|
117
|
+
</style>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
<template>
|
|
4
|
+
<el-config-provider :locale="zhCn">
|
|
5
|
+
<header-view :proj-name="projName" @menu-select="onMenuSelect">
|
|
6
|
+
<template #main-content>
|
|
7
|
+
<router-view></router-view>
|
|
8
|
+
</template>
|
|
9
|
+
</header-view>
|
|
10
|
+
</el-config-provider>
|
|
11
|
+
|
|
12
|
+
</template>
|
|
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 {userMenuStore} from '$elpisStore/menu.js'
|
|
20
|
+
import {userProjectStore} from '$elpisStore/project.js'
|
|
21
|
+
|
|
22
|
+
const router = useRouter()
|
|
23
|
+
const route = useRoute()
|
|
24
|
+
const menuStore = userMenuStore()
|
|
25
|
+
const projectStore = userProjectStore()
|
|
26
|
+
onMounted(()=>{
|
|
27
|
+
getProjectList();
|
|
28
|
+
getProjectConfig();
|
|
29
|
+
})
|
|
30
|
+
const projName = ref('')
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
// 请求/api/project/list 接口 并缓存到project-store中
|
|
34
|
+
async function getProjectList(){
|
|
35
|
+
const res = await $curl({
|
|
36
|
+
url:'/api/project/list',
|
|
37
|
+
method:'get',
|
|
38
|
+
query:{
|
|
39
|
+
proj_key:route.query.proj_key,
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
if(!res || !res.success || !res.data){
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
projectStore.setProjectList(res.data)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 请求 /api/project 接口 并缓存到menu-store 中
|
|
49
|
+
async function getProjectConfig(){
|
|
50
|
+
const res = await $curl({
|
|
51
|
+
url:'/api/project',
|
|
52
|
+
method:'get',
|
|
53
|
+
query:{
|
|
54
|
+
proj_key:route.query.proj_key,
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
if(!res || !res.success || !res.data){
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
const {name,menu} = res.data;
|
|
61
|
+
projName.value=name;
|
|
62
|
+
menuStore.setMenuList(menu)
|
|
63
|
+
}
|
|
64
|
+
// 点击菜单回调
|
|
65
|
+
const onMenuSelect =(menuItem)=>{
|
|
66
|
+
const {moduleType,key,customConfig} = menuItem
|
|
67
|
+
// 如果时当前页面 不处理
|
|
68
|
+
if(key === route.query.key){return}
|
|
69
|
+
let pathMap={
|
|
70
|
+
sider:'/sider',
|
|
71
|
+
iframe:'/iframe',
|
|
72
|
+
schema:'/schema',
|
|
73
|
+
custom:customConfig?.path,
|
|
74
|
+
}
|
|
75
|
+
router.push({
|
|
76
|
+
path:`/view/dashboard${pathMap[moduleType]}`,
|
|
77
|
+
query:{
|
|
78
|
+
key,
|
|
79
|
+
proj_key:route.query.proj_key,
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
</script>
|
|
84
|
+
<style scoped lang="less">
|
|
85
|
+
:deep(.el-main){
|
|
86
|
+
padding: 0 ;
|
|
87
|
+
}
|
|
88
|
+
</style>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import boot from '$elpisPages/boot.js'
|
|
2
|
+
import dashBoard from './dashboard.vue'
|
|
3
|
+
import businessDashboradRouterConfig from '$businessDashboradRouterConfig'
|
|
4
|
+
|
|
5
|
+
let routes =[]
|
|
6
|
+
routes.push({
|
|
7
|
+
path: '/view/dashboard/iframe',
|
|
8
|
+
component:()=>import('./complex-view/iframe-view/iframe-view.vue')
|
|
9
|
+
})
|
|
10
|
+
routes.push({
|
|
11
|
+
path: '/view/dashboard/schema',
|
|
12
|
+
component:()=>import('./complex-view/schema-view/schema-view.vue')
|
|
13
|
+
})
|
|
14
|
+
const siderRouters = [
|
|
15
|
+
{
|
|
16
|
+
path: 'iframe',
|
|
17
|
+
component:()=>import('./complex-view/iframe-view/iframe-view.vue')
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
path: 'schema',
|
|
21
|
+
component:()=>import('./complex-view/schema-view/schema-view.vue')
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
// 侧边栏(子路由必须用相对路径,才会挂到 /sider/* 下,供 sider-view 的 <router-view> 渲染)
|
|
25
|
+
routes.push({
|
|
26
|
+
path: '/view/dashboard/sider',
|
|
27
|
+
component:()=>import('./complex-view/sider-view/sider-view.vue'),
|
|
28
|
+
children:siderRouters
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
if(typeof businessDashboradRouterConfig === 'function') {
|
|
32
|
+
businessDashboradRouterConfig({routes,siderRouters})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
// 侧边栏兜底策略
|
|
37
|
+
routes.push({
|
|
38
|
+
path:'/view/dashboard/sider/:chapters+',
|
|
39
|
+
component:()=>import('./complex-view/sider-view/sider-view.vue')
|
|
40
|
+
})
|
|
41
|
+
boot(dashBoard,{routes})
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {defineStore} from 'pinia'
|
|
2
|
+
import {ref} from 'vue'
|
|
3
|
+
export const userMenuStore = defineStore('menu',()=>{
|
|
4
|
+
// 菜单列表
|
|
5
|
+
const menuList =ref([])
|
|
6
|
+
|
|
7
|
+
// 设置菜单列表
|
|
8
|
+
const setMenuList= function (list){
|
|
9
|
+
menuList.value = list
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* 找出菜单目录
|
|
14
|
+
* @param key 搜索字段
|
|
15
|
+
* @param value 搜索值
|
|
16
|
+
* @param mList 要搜索的菜单列表
|
|
17
|
+
* */
|
|
18
|
+
const findMenuItem= function ({key,value},mList= menuList.value){
|
|
19
|
+
for(let i=0;i<mList.length;i++){
|
|
20
|
+
const menuItem = mList[i]
|
|
21
|
+
if(!menuItem){
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const {menuType,moduleType} = menuItem
|
|
25
|
+
|
|
26
|
+
if(menuItem[key]===value){
|
|
27
|
+
return menuItem
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if(menuType==='group' && menuItem.subMenu){
|
|
31
|
+
const mItem = findMenuItem({key,value},menuItem.subMenu)
|
|
32
|
+
if(mItem){
|
|
33
|
+
return mItem
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if(moduleType==='sider' && menuItem.siderConfig && menuItem.siderConfig.menu){
|
|
38
|
+
const mItem = findMenuItem({key,value},menuItem.siderConfig.menu)
|
|
39
|
+
if(mItem){
|
|
40
|
+
return mItem
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/*
|
|
46
|
+
* 找出左侧第一个菜单
|
|
47
|
+
* @param mList 菜单列表
|
|
48
|
+
* */
|
|
49
|
+
|
|
50
|
+
const findFirstMenuItem =(mList = menuList.value)=>{
|
|
51
|
+
if(!mList || !mList[0]){return}
|
|
52
|
+
let firstMenuItem = mList[0]
|
|
53
|
+
if(firstMenuItem.subMenu){
|
|
54
|
+
firstMenuItem = findFirstMenuItem(firstMenuItem.subMenu)
|
|
55
|
+
}
|
|
56
|
+
return firstMenuItem
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
menuList,
|
|
61
|
+
setMenuList,
|
|
62
|
+
findMenuItem,
|
|
63
|
+
findFirstMenuItem
|
|
64
|
+
}
|
|
65
|
+
})
|