@dmqweb/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.
Files changed (81) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc +59 -0
  3. package/.vscode/settings.json +15 -0
  4. package/README.md +198 -0
  5. package/app/controller/base.js +41 -0
  6. package/app/controller/project.js +98 -0
  7. package/app/controller/view.js +24 -0
  8. package/app/extend/logger.js +43 -0
  9. package/app/middleware/api-params-verify.js +89 -0
  10. package/app/middleware/api-sign-verify.js +47 -0
  11. package/app/middleware/error-handler.js +41 -0
  12. package/app/middleware/project-handler.js +27 -0
  13. package/app/middleware.js +40 -0
  14. package/app/pages/asserts/custom.css +12 -0
  15. package/app/pages/boot.js +59 -0
  16. package/app/pages/common/curl.js +88 -0
  17. package/app/pages/common/util.js +3 -0
  18. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +40 -0
  19. package/app/pages/dashboard/complex-view/header-view/header-view.vue +141 -0
  20. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +43 -0
  21. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +39 -0
  22. package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +146 -0
  23. package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +24 -0
  24. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +118 -0
  25. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +177 -0
  26. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +157 -0
  27. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +150 -0
  28. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +113 -0
  29. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +35 -0
  30. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +134 -0
  31. package/app/pages/dashboard/dashboard.vue +127 -0
  32. package/app/pages/dashboard/entry.dashboard.js +46 -0
  33. package/app/pages/store/index.js +5 -0
  34. package/app/pages/store/menu.js +61 -0
  35. package/app/pages/store/project.js +13 -0
  36. package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
  37. package/app/pages/widgets/header-container/asserts/logo.png +0 -0
  38. package/app/pages/widgets/header-container/header-container.vue +144 -0
  39. package/app/pages/widgets/schema-form/complex-view/input/input.vue +165 -0
  40. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +166 -0
  41. package/app/pages/widgets/schema-form/complex-view/select/select.vue +144 -0
  42. package/app/pages/widgets/schema-form/form-item.config.js +24 -0
  43. package/app/pages/widgets/schema-form/schema-form.vue +144 -0
  44. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +57 -0
  45. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +77 -0
  46. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +51 -0
  47. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +58 -0
  48. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +138 -0
  49. package/app/pages/widgets/schema-search-bar/search-item-config.js +27 -0
  50. package/app/pages/widgets/schema-table/schema-table.vue +254 -0
  51. package/app/pages/widgets/sider-container/sider-container.vue +32 -0
  52. package/app/router/business.js +15 -0
  53. package/app/router/project.js +10 -0
  54. package/app/router/view.js +11 -0
  55. package/app/router-schema/business.js +82 -0
  56. package/app/router-schema/project.js +40 -0
  57. package/app/service/base.js +13 -0
  58. package/app/service/project.js +55 -0
  59. package/app/view/entry.tpl +27 -0
  60. package/app/webpack/config/blank.js +3 -0
  61. package/app/webpack/config/webpack.base.js +269 -0
  62. package/app/webpack/config/webpack.dev.js +61 -0
  63. package/app/webpack/config/webpack.prod.js +149 -0
  64. package/app/webpack/dev.js +58 -0
  65. package/app/webpack/prod.js +21 -0
  66. package/config/config.default.js +3 -0
  67. package/elpis-core/env.js +22 -0
  68. package/elpis-core/index.js +99 -0
  69. package/elpis-core/loader/config.js +51 -0
  70. package/elpis-core/loader/controller.js +75 -0
  71. package/elpis-core/loader/extend.js +54 -0
  72. package/elpis-core/loader/middleware.js +69 -0
  73. package/elpis-core/loader/router-schema.js +50 -0
  74. package/elpis-core/loader/router.js +52 -0
  75. package/elpis-core/loader/service.js +74 -0
  76. package/index.js +29 -0
  77. package/jsconfig.json +16 -0
  78. package/logs/applocation.log +3 -0
  79. package/model/index.js +119 -0
  80. package/package.json +93 -0
  81. package/test/controller/project.test.js +216 -0
@@ -0,0 +1,118 @@
1
+ <template>
2
+ <el-drawer
3
+ v-model="isShow"
4
+ directory="rtl"
5
+ size="550"
6
+ destroy-on-close
7
+ >
8
+ <template #header>
9
+ <h2>
10
+ {{ title }}
11
+ </h2>
12
+ </template>
13
+ <template #default>
14
+ <schema-form
15
+ ref="schemaFormRef"
16
+ v-loading="loading"
17
+ :schema="currentSchema"
18
+ />
19
+ </template>
20
+ <template #footer>
21
+ <el-button
22
+ type="primary"
23
+ @click="save"
24
+ >
25
+ {{ saveBtnText }}
26
+ </el-button>
27
+ </template>
28
+ </el-drawer>
29
+ </template>
30
+
31
+ <script setup>
32
+ import { inject, ref, computed } from 'vue';
33
+ import schemaForm from '$elpisWidgets/schema-form/schema-form.vue';
34
+ import $curl from '$elpisCommon/curl.js'
35
+ import { ElNotification } from 'element-plus';
36
+ const {
37
+ api,
38
+ components
39
+ } = inject('schemaViewData')
40
+ const emit = defineEmits(['command'])
41
+ const title = ref('')
42
+ const saveBtnText = ref('')
43
+ // 用来外部识别组件名称
44
+ const name = ref('createForm')
45
+
46
+ // 使用 computed 确保响应式更新
47
+ const currentSchema = computed(() => {
48
+ return components.value?.[name.value]?.schema || {}
49
+ })
50
+
51
+ const schemaFormRef = ref(null)
52
+ const loading = ref(false)
53
+
54
+ // 抽屉窗口是否显示
55
+ const isShow = ref(false)
56
+ // 显示表单
57
+ const show = () => {
58
+ const { config } = components.value[name.value]
59
+
60
+ title.value = config.title
61
+ saveBtnText.value = config.saveBtnText
62
+
63
+ isShow.value = true
64
+ }
65
+
66
+ // 关闭表单
67
+ const close = () => {
68
+ isShow.value = false
69
+ }
70
+
71
+ // 表单点击
72
+ const save = async () => {
73
+ // 防止重复提交
74
+ if(loading.value) return
75
+
76
+ // 校验表单
77
+ if(!schemaFormRef.value.validate()) {
78
+ console.log('表单校验失败')
79
+ return
80
+ }
81
+
82
+ loading.value = true
83
+ const res = await $curl({
84
+ method: 'post',
85
+ url: api.value,
86
+ data: {
87
+ ...schemaFormRef.value.getValue()
88
+ }
89
+ })
90
+ loading.value = false
91
+ if(!res || !res.success) {
92
+ ElNotification({
93
+ title: '保存失败',
94
+ message: '保存失败',
95
+ type: 'error'
96
+ })
97
+ return
98
+ }
99
+ ElNotification({
100
+ title: '创建成功',
101
+ message: '创建成功',
102
+ type: 'success'
103
+ })
104
+ close()
105
+ emit('command', {
106
+ event: 'loadTableData'
107
+ })
108
+ }
109
+
110
+ defineExpose({
111
+ name,
112
+ show
113
+ })
114
+ </script>
115
+
116
+ <style lang="less" scoped>
117
+
118
+ </style>
@@ -0,0 +1,177 @@
1
+ <template>
2
+ <el-drawer
3
+ v-model="isShow"
4
+ directory="rtl"
5
+ size="550"
6
+ destroy-on-close
7
+ >
8
+ <!-- -->
9
+ <template #header>
10
+ <h2>
11
+ {{ title }}
12
+ </h2>
13
+ </template>
14
+ <template #default>
15
+ <el-card
16
+ v-loading="loading"
17
+ shadow="always"
18
+ class="detail-panel"
19
+ >
20
+ <el-row
21
+ v-for="(item, key) in components[name]?.schema?.properties"
22
+ :key="key"
23
+ type="flex"
24
+ align="middle"
25
+ class="row-item"
26
+ >
27
+ <el-row class="item-label">
28
+ {{ item.label }}:
29
+ <br>
30
+ </el-row>
31
+ <el-row class="item-value">
32
+ {{ dotModel[key] }}
33
+ </el-row>
34
+ </el-row>
35
+ </el-card>
36
+ </template>
37
+ </el-drawer>
38
+ </template>
39
+
40
+ <script setup>
41
+ import { ref, inject } from 'vue';
42
+ import $curl from '$elpisCommon/curl.js'
43
+ import { ElNotification } from 'element-plus';
44
+
45
+ const isShow = ref(false)
46
+ const loading = ref(false)
47
+ const name = ref('detailPanel')
48
+ const title = ref('')
49
+ const mainKey = ref('')
50
+ const mainValue = ref('')
51
+ const dotModel = ref({})
52
+
53
+ const {
54
+ api,
55
+ components
56
+ } = inject('schemaViewData')
57
+
58
+
59
+ // 显示表单
60
+ const show = (rowData) => {
61
+ const { config } = components.value[name.value]
62
+
63
+ title.value = config.title
64
+ mainKey.value = config.mainKey // 表单的主键
65
+ mainValue.value = rowData[mainKey.value] // 主键的值
66
+ dotModel.value = {}
67
+
68
+ isShow.value = true
69
+
70
+ fetchFormData()
71
+ }
72
+
73
+
74
+ // 获取表单数据
75
+ const fetchFormData = async () => {
76
+ // 防止重复提交
77
+ if(loading.value) return
78
+
79
+ loading.value = true
80
+ const res = await $curl({
81
+ method: 'get',
82
+ url: api.value,
83
+ params: {
84
+ [mainKey.value]: mainValue.value
85
+ }
86
+ })
87
+ loading.value = false
88
+
89
+ if(!res || !res.success || !res.data) {
90
+ ElNotification({
91
+ title: '提示',
92
+ message: '获取数据失败',
93
+ type: 'error'
94
+ })
95
+ return // 添加return防止继续执行
96
+ }
97
+
98
+ // 确保res.data是对象类型,如果是数字则包装成对象
99
+ if (typeof res.data === 'object' && res.data !== null) {
100
+ dotModel.value = res.data
101
+ } else {
102
+ // 如果res.data不是对象,可能是直接返回的值,需要包装
103
+ console.warn('API返回的数据格式不正确,期望对象但收到:', typeof res.data, res.data)
104
+ dotModel.value = {}
105
+ }
106
+ }
107
+
108
+ defineExpose({
109
+ show,
110
+ name
111
+ })
112
+ </script>
113
+
114
+ <style lang="less" scoped>
115
+ .detail-panel {
116
+ background: linear-gradient(135deg, #f5f7fa 0%, #e4edf9 100%);
117
+ border-radius: 12px;
118
+ padding: 30px;
119
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
120
+ border: none;
121
+
122
+ .row-item {
123
+ height: auto;
124
+ min-height: 50px;
125
+ line-height: 1.6;
126
+ padding: 15px 0;
127
+ border-bottom: 1px solid #eaeef5;
128
+
129
+ &:last-child {
130
+ border-bottom: none;
131
+ }
132
+
133
+ .item-label {
134
+ margin-right: 20px;
135
+ width: 130px;
136
+ font-weight: 600;
137
+ color: #2d3748;
138
+ font-size: 15px;
139
+ }
140
+
141
+ .item-value {
142
+ color: #4a5568;
143
+ font-size: 15px;
144
+ flex: 1;
145
+ word-break: break-word;
146
+ }
147
+ }
148
+ }
149
+
150
+ // 响应式设计,适配不同屏幕尺寸
151
+ @media (max-width: 768px) {
152
+ .detail-panel {
153
+ padding: 20px;
154
+
155
+ .row-item {
156
+ flex-direction: column;
157
+ align-items: flex-start;
158
+
159
+ .item-label {
160
+ width: 100%;
161
+ margin-right: 0;
162
+ margin-bottom: 5px;
163
+ }
164
+ }
165
+ }
166
+ }
167
+
168
+ // 暗色主题适配
169
+ :deep(.el-card) {
170
+ background: transparent;
171
+ border: none;
172
+ }
173
+
174
+ :deep(.el-drawer__body) {
175
+ padding: 20px;
176
+ }
177
+ </style>
@@ -0,0 +1,157 @@
1
+ <template>
2
+ <el-drawer
3
+ v-model="isShow"
4
+ directory="rtl"
5
+ size="550"
6
+ destroy-on-close
7
+ >
8
+ <template #header>
9
+ <h2>
10
+ {{ title }}
11
+ </h2>
12
+ </template>
13
+ <template #default>
14
+ <schema-form
15
+ ref="schemaFormRef"
16
+ v-loading="loading"
17
+ :schema="currentSchema"
18
+ :model="dotModel"
19
+ />
20
+ </template>
21
+ <template #footer>
22
+ <el-button
23
+ type="primary"
24
+ @click="save"
25
+ >
26
+ {{ saveBtnText }}
27
+ </el-button>
28
+ </template>
29
+ </el-drawer>
30
+ </template>
31
+
32
+ <script setup>
33
+ import { ref, inject, computed } from 'vue';
34
+ import schemaForm from '$elpisWidgets/schema-form/schema-form.vue';
35
+ import $curl from '$elpisCommon/curl.js'
36
+ import { ElNotification } from 'element-plus';
37
+
38
+ const {
39
+ api,
40
+ components
41
+ } = inject('schemaViewData')
42
+
43
+ const emit = defineEmits(['command'])
44
+
45
+ const name = ref('editForm')
46
+
47
+ const schemaFormRef = ref(null)
48
+ const isShow = ref(false)
49
+ const loading = ref(false)
50
+ const title = ref('')
51
+ const saveBtnText = ref('')
52
+ const mainKey = ref('')
53
+ const mainValue = ref('')
54
+ const dotModel = ref({})
55
+
56
+ // 使用 computed 确保响应式更新
57
+ const currentSchema = computed(() => {
58
+ return components.value?.[name.value]?.schema || {}
59
+ })
60
+
61
+ const show = (rowData) => {
62
+ const { config } = components.value[name.value]
63
+
64
+ title.value = config.title
65
+ saveBtnText.value = config.saveBtnText
66
+ mainKey.value = config.mainKey // 表单的主键
67
+ mainValue.value = rowData[mainKey.value] // 主键的值
68
+ dotModel.value = {}
69
+
70
+ isShow.value = true
71
+
72
+ fetchFormData()
73
+ }
74
+ const close = () => {
75
+ isShow.value = false
76
+ }
77
+ // 获取表单数据
78
+ const fetchFormData = async () => {
79
+ // 防止重复提交
80
+ if(loading.value) return
81
+
82
+ loading.value = true
83
+ const res = await $curl({
84
+ method: 'get',
85
+ url: api.value,
86
+ params: {
87
+ [mainKey.value]: mainValue.value
88
+ }
89
+ })
90
+ loading.value = false
91
+
92
+ if(!res || !res.success || !res.data) {
93
+ ElNotification({
94
+ title: '提示',
95
+ message: '获取数据失败',
96
+ type: 'error'
97
+ })
98
+ return // 添加return防止继续执行
99
+ }
100
+
101
+ // 确保res.data是对象类型,如果是数字则包装成对象
102
+ if (typeof res.data === 'object' && res.data !== null) {
103
+ dotModel.value = res.data
104
+ } else {
105
+ // 如果res.data不是对象,可能是直接返回的值,需要包装
106
+ console.warn('API返回的数据格式不正确,期望对象但收到:', typeof res.data, res.data)
107
+ dotModel.value = {}
108
+ }
109
+ }
110
+
111
+ // 表单点击
112
+ const save = async () => {
113
+ if(loading.value) return
114
+ // 校验表单
115
+ if(!schemaFormRef.value.validate()) {
116
+ console.log('表单校验失败')
117
+ return
118
+ }
119
+
120
+ loading.value = true
121
+ const res = await $curl({
122
+ method: 'put',
123
+ url: api.value,
124
+ data: {
125
+ [mainKey.value]: mainValue.value,
126
+ ...schemaFormRef.value.getValue()
127
+ }
128
+ })
129
+ loading.value = false
130
+ if(!res || !res.success) {
131
+ ElNotification({
132
+ title: '提示',
133
+ message: '修改失败',
134
+ type: 'error'
135
+ })
136
+ return
137
+ }
138
+ ElNotification({
139
+ title: '提示',
140
+ message: '修改成功',
141
+ type: 'success'
142
+ })
143
+ close()
144
+ emit('command', {
145
+ event: 'loadTableData'
146
+ })
147
+ }
148
+
149
+ defineExpose({
150
+ name,
151
+ show
152
+ })
153
+ </script>
154
+
155
+ <style lang="less" scoped>
156
+
157
+ </style>
@@ -0,0 +1,150 @@
1
+ import { ref, watch } from 'vue'
2
+ import { useRoute } from 'vue-router'
3
+ import { useMenuStore } from '$elpisStore/menu'
4
+ import { cloneDeep } from 'lodash';
5
+ export const useSchema = function() {
6
+ const route = useRoute()
7
+ const menuStore = useMenuStore()
8
+
9
+ const api = ref('')
10
+ const tableConfig = ref()
11
+ const tableSchema = ref({})
12
+ const searchConfig = ref()
13
+ const searchSchema = ref({})
14
+ const components = ref()
15
+
16
+ // 构造 schemaConfig 相关配置, 输送给 schemaView 解释
17
+ const buildData = function() {
18
+ const { key, sider_key } = route.query
19
+
20
+ // 添加菜单项存在性检查
21
+ if (!key && !sider_key) {
22
+ resetSchemaData()
23
+ return
24
+ }
25
+ if (!menuStore.menuList || menuStore.menuList.length === 0) {
26
+ // 初始化早期静默返回,等 watch 触发
27
+ return
28
+ }
29
+
30
+ const mItem = menuStore.findMenuItem({
31
+ key: 'key',
32
+ value: key ?? sider_key
33
+ })
34
+
35
+ // 不是 schema 模块时,清空并退出(不警告)
36
+ if (!mItem || mItem.moduleType !== 'schema') {
37
+ resetSchemaData()
38
+ return
39
+ }
40
+
41
+ const sConfig = mItem.schemaConfig
42
+ if (!sConfig) {
43
+ // 理论上继承后会有;异常也静默,避免刷屏
44
+ resetSchemaData()
45
+ return
46
+ }
47
+
48
+ const configSchema = cloneDeep((sConfig.schema ?? {}))
49
+ api.value = sConfig.api ?? ''
50
+ tableConfig.value = undefined
51
+ tableSchema.value = {}
52
+ searchConfig.value = undefined
53
+ searchSchema.value = {}
54
+ components.value = {}
55
+
56
+ // 构造 tableSchema 和 tableConfig
57
+ tableSchema.value = buildDtoSchema(configSchema, 'table')
58
+ tableConfig.value = sConfig.tableConfig ?? {}
59
+
60
+ // 构造 searchSchema 和 searchConfig
61
+ const dtoSearchSchema = buildDtoSchema(configSchema, 'search')
62
+ // 循环遍历searchSchema的属性,将路由参数的值赋给searchSchema的属性的option的default属性
63
+ for(const key in dtoSearchSchema.properties) {
64
+ if(route.query[key] !== undefined) {
65
+ dtoSearchSchema.properties[key].option.default = route.query[key]
66
+ }
67
+ }
68
+ searchSchema.value = dtoSearchSchema
69
+ searchConfig.value = sConfig.searchConfig ?? {}
70
+
71
+ // 构造 components = { comKey: { schema:{} config: {} }
72
+ const { componentConfig } = sConfig
73
+ if(componentConfig && Object.keys(componentConfig).length > 0){
74
+ const dtoComponents = {}
75
+
76
+ for(const comKey in componentConfig) {
77
+ dtoComponents[comKey] = {
78
+ schema: buildDtoSchema(configSchema, comKey),
79
+ config: componentConfig[comKey]
80
+ }
81
+ }
82
+ components.value = dtoComponents
83
+ }
84
+ }
85
+
86
+ // 重置所有schema相关数据为默认值
87
+ const resetSchemaData = function() {
88
+ tableSchema.value = {}
89
+ tableConfig.value = {}
90
+ searchConfig.value = {}
91
+ searchSchema.value = {}
92
+ api.value = ''
93
+ components.value = {}
94
+ }
95
+
96
+ // 通用构建 schema 方法 (清除掉无效字段)
97
+ const buildDtoSchema = (_schema, comName) => {
98
+ if (!_schema?.properties) return {}
99
+
100
+ const dtoSchema = {
101
+ type: 'object',
102
+ properties: {}
103
+ }
104
+
105
+ // 提取有效 schema 字段信息
106
+ // 循环遍历每个properties字段属性
107
+ for (const key in _schema.properties) {
108
+ // 拿取properties下的每个字段key
109
+ const props = _schema.properties[key]
110
+ // 筛选出需要显示的字段
111
+ if (props[`${comName}Option`]) {
112
+ let dtoProps = {}
113
+ // 循环遍历key下的每个属性
114
+ for (const pKey in props) {
115
+ // 过滤掉非option的属性, 筛选出存储基本属性先存放到dtoProps中,
116
+ if (pKey.indexOf('Option') < 0) {
117
+ dtoProps[pKey] = props[pKey]
118
+ }
119
+ }
120
+ // 将指定的comName的option属性存放到dtoProps中
121
+ dtoProps = Object.assign({},dtoProps, {option: props[`${comName}Option`]})
122
+
123
+ const { required } = _schema
124
+ if(required && required.find(item => item === key)){
125
+ dtoProps.option.required = true
126
+ }
127
+ // 将处理好的字段存放到dtoSchema的properties中
128
+ dtoSchema.properties[key] = dtoProps
129
+ }
130
+ }
131
+ return dtoSchema
132
+ }
133
+
134
+ watch([
135
+ () => route.query.key,
136
+ () => route.query.sider_key,
137
+ () => menuStore.menuList
138
+ ], () => {
139
+ buildData()
140
+ }, { deep: true, immediate: true})
141
+
142
+ return {
143
+ api,
144
+ tableConfig,
145
+ tableSchema,
146
+ searchConfig,
147
+ searchSchema,
148
+ components
149
+ }
150
+ }
@@ -0,0 +1,113 @@
1
+ <template>
2
+ <el-row
3
+ v-loading="loading"
4
+ class="schema-view"
5
+ >
6
+ <search-panel
7
+ v-if="searchSchema?.properties && Object.keys(searchSchema.properties).length > 0"
8
+ @search="onSearch"
9
+ />
10
+ <table-panel
11
+ ref="tablePanelRef"
12
+ @operate="onTableOperate"
13
+ />
14
+ <component
15
+ :is="ComponentConfig[key]?.component"
16
+ v-for="(component, key) in components"
17
+ :key="key"
18
+ ref="comListRef"
19
+ @command="handleComCommand"
20
+ />
21
+ </el-row>
22
+ </template>
23
+
24
+ <script setup>
25
+ import { ref, provide, computed } from 'vue';
26
+ import SearchPanel from './complex-view/search-panel/search-panel.vue'
27
+ import TablePanel from './complex-view/table-panel/table-panel.vue'
28
+ import ComponentConfig from './components/component-config';
29
+ import { useSchema } from './hook/schema';
30
+
31
+ const apiParams = ref({});
32
+ // 从menulist中获取各种配置
33
+ const {
34
+ api,
35
+ tableSchema,
36
+ tableConfig,
37
+ searchSchema,
38
+ searchConfig,
39
+ components
40
+ } = useSchema();
41
+
42
+ const loading = computed(() => {
43
+ return !tableSchema.value || Object.keys(tableSchema.value).length === 0
44
+ })
45
+ // 跨层级传递数据
46
+ provide('schemaViewData', {
47
+ api,
48
+ apiParams,
49
+ tableSchema,
50
+ tableConfig,
51
+ searchSchema,
52
+ searchConfig,
53
+ components
54
+ });
55
+
56
+ const comListRef = ref([]);
57
+ const tablePanelRef = ref(null);
58
+
59
+ const onSearch = (searchValObj) => {
60
+ apiParams.value = searchValObj;
61
+ }
62
+
63
+ const eventHandlerMap = {
64
+ showComponent: showComponent
65
+ }
66
+
67
+ // 表格操作
68
+ const onTableOperate = ({ btnConfig, rowData }) => {
69
+ const { eventKey } = btnConfig;
70
+ if(eventHandlerMap[eventKey]){
71
+ eventHandlerMap[eventKey]({ btnConfig, rowData })
72
+ }
73
+ }
74
+
75
+ // 显示组件
76
+ function showComponent({ btnConfig, rowData }) {
77
+ const { comName } = btnConfig.eventOption;
78
+ if(!comName) {
79
+ console.error('请配置组件名称');
80
+ return
81
+ };
82
+
83
+ const comRef = comListRef.value.find(item => item.name === comName);
84
+ if(!comRef && typeof comRef.show !== 'function') {
85
+ console.error('配置不正确');
86
+ return
87
+ };
88
+
89
+ comRef.show(rowData);
90
+ }
91
+
92
+ // 处理来自子组件的命令
93
+ const handleComCommand = (data) => {
94
+ const { event } = data;
95
+ if(event === 'loadTableData'){
96
+ tablePanelRef.value.loadTableData();
97
+ }
98
+ }
99
+ </script>
100
+
101
+ <style lang="less" scoped>
102
+ .schema-view {
103
+ width: 100%;
104
+ height: 100%;
105
+ display: flex;
106
+ flex-direction: column;
107
+ }
108
+ .loading-container {
109
+ flex: 1;
110
+ position: relative;
111
+ min-height: 400px;
112
+ }
113
+ </style>