@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.
Files changed (86) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc +55 -0
  3. package/.idea/dictionaries/project.xml +8 -0
  4. package/.idea/elpis.iml +8 -0
  5. package/.idea/git_toolbox_prj.xml +15 -0
  6. package/.idea/inspectionProfiles/Project_Default.xml +329 -0
  7. package/.idea/modules.xml +8 -0
  8. package/.idea/vcs.xml +6 -0
  9. package/README.md +201 -0
  10. package/app/controller/base.js +77 -0
  11. package/app/controller/project.js +69 -0
  12. package/app/controller/view.js +20 -0
  13. package/app/extend/logger.js +35 -0
  14. package/app/middleware/api-params-verify.js +74 -0
  15. package/app/middleware/api-sign-verify.js +33 -0
  16. package/app/middleware/error-hander.js +32 -0
  17. package/app/middleware/project-handler.js +25 -0
  18. package/app/middleware.js +37 -0
  19. package/app/pages/asserts/custom.css +11 -0
  20. package/app/pages/boot.js +43 -0
  21. package/app/pages/common/curl.js +83 -0
  22. package/app/pages/common/index.js +2 -0
  23. package/app/pages/common/utils.js +0 -0
  24. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +23 -0
  25. package/app/pages/dashboard/complex-view/header-view/header-view.vue +117 -0
  26. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +40 -0
  27. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +45 -0
  28. package/app/pages/dashboard/complex-view/schema-view/complex-view/tabel-panel/tabel-panel.vue +134 -0
  29. package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +20 -0
  30. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +89 -0
  31. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +101 -0
  32. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +128 -0
  33. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +119 -0
  34. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +96 -0
  35. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +21 -0
  36. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +117 -0
  37. package/app/pages/dashboard/dashboard.vue +88 -0
  38. package/app/pages/dashboard/entry.dashboard.js +41 -0
  39. package/app/pages/router/index.js +11 -0
  40. package/app/pages/store/index.js +4 -0
  41. package/app/pages/store/menu.js +65 -0
  42. package/app/pages/store/project.js +16 -0
  43. package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
  44. package/app/pages/widgets/header-container/asserts/logo.png +0 -0
  45. package/app/pages/widgets/header-container/header-container.vue +103 -0
  46. package/app/pages/widgets/schema-form/complex-view/input/input.vue +142 -0
  47. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +143 -0
  48. package/app/pages/widgets/schema-form/complex-view/select/select.vue +130 -0
  49. package/app/pages/widgets/schema-form/form-item-config.js +20 -0
  50. package/app/pages/widgets/schema-form/schema-form.vue +132 -0
  51. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +48 -0
  52. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +67 -0
  53. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +40 -0
  54. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +50 -0
  55. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +142 -0
  56. package/app/pages/widgets/schema-search-bar/search-item-config.js +24 -0
  57. package/app/pages/widgets/schema-table/schema-table.vue +238 -0
  58. package/app/pages/widgets/sider-container/sider-container.vue +31 -0
  59. package/app/public/static/logo.png +0 -0
  60. package/app/public/static/normalize.css +239 -0
  61. package/app/router/project.js +9 -0
  62. package/app/router/view.js +7 -0
  63. package/app/router-schema/project.js +32 -0
  64. package/app/service/base.js +12 -0
  65. package/app/service/project.js +42 -0
  66. package/app/view/entry.tpl +26 -0
  67. package/app/webpack/config/webpack.base.js +219 -0
  68. package/app/webpack/config/webpack.dev.js +55 -0
  69. package/app/webpack/config/webpack.prod.js +118 -0
  70. package/app/webpack/dev.js +52 -0
  71. package/app/webpack/libs/blank.js +2 -0
  72. package/app/webpack/prod.js +18 -0
  73. package/config/config.default.js +3 -0
  74. package/elpis-core/env.js +20 -0
  75. package/elpis-core/index.js +92 -0
  76. package/elpis-core/loader/config.js +54 -0
  77. package/elpis-core/loader/controller.js +61 -0
  78. package/elpis-core/loader/extend.js +55 -0
  79. package/elpis-core/loader/middleware.js +61 -0
  80. package/elpis-core/loader/router-schema.js +39 -0
  81. package/elpis-core/loader/router.js +42 -0
  82. package/elpis-core/loader/service.js +64 -0
  83. package/index.js +41 -0
  84. package/model/index.js +105 -0
  85. package/package.json +94 -0
  86. package/test/controller/project.test.js +194 -0
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <el-date-picker
3
+ v-model="dtoValue"
4
+ v-bind="schema.option"
5
+ type="daterange"
6
+ :start-placeholder="schema.label+'(开始)'"
7
+ :end-placeholder="schema.label+'(结束)'"
8
+ class="date-range"
9
+ ></el-date-picker>
10
+ </template>
11
+
12
+ <script setup>
13
+ import {ref,onMounted} from 'vue'
14
+ import moment from 'moment'
15
+ const {schemaKey,schema} = defineProps({
16
+ schemaKey: String,
17
+ schema: Object,
18
+ })
19
+
20
+ const emit = defineEmits(['loaded'])
21
+
22
+ const dtoValue = ref([])
23
+ const getValue=()=>{
24
+ return dtoValue.value.length === 2 ?{
25
+ [`${schemaKey}_start`]:moment(dtoValue.value[0]).format('YYYY-MM-DD'),
26
+ [`${schemaKey}_end`]:moment(dtoValue.value[1]).format('YYYY-MM-DD')
27
+ }:{}
28
+ }
29
+
30
+ const reset=()=>{
31
+ dtoValue.value = [];
32
+ }
33
+
34
+ onMounted(() => {
35
+ reset()
36
+ emit('loaded')
37
+ })
38
+ defineExpose({
39
+ getValue,
40
+ reset
41
+ })
42
+ </script>
43
+
44
+
45
+
46
+ <style scoped lang="less">
47
+
48
+ </style>
@@ -0,0 +1,67 @@
1
+ <template>
2
+ <el-select v-model="dtoValue" v-bind="schema.option" class="dynamic-select">
3
+ <el-option
4
+ v-for="item in enumList"
5
+ :key="item.value"
6
+ :label="item.label"
7
+ :value="item.value"
8
+ >
9
+ </el-option>
10
+ </el-select>
11
+ </template>
12
+
13
+ <script setup>
14
+ import {ref,onMounted} from 'vue'
15
+ import $curl from '$elpisCommon/curl.js'
16
+
17
+ const {schemaKey,schema} = defineProps({
18
+ schemaKey: String,
19
+ schema: Object,
20
+ })
21
+
22
+ const emit = defineEmits(['loaded'])
23
+
24
+ const dtoValue = ref()
25
+ const getValue=()=>{
26
+ return dtoValue.value !==undefined?{
27
+ [schemaKey]:dtoValue.value
28
+ }:{}
29
+ }
30
+
31
+ const reset=()=>{
32
+ dtoValue.value = schema?.option?.default ?? enumList.value?.[0]?.value;
33
+ }
34
+
35
+ const enumList =ref([])
36
+
37
+ const fetchEnumList = async () => {
38
+ const res = await $curl({
39
+ method:'get',
40
+ url:schema.option?.api,
41
+ data:{}
42
+ })
43
+
44
+ if(res?.data?.length>0){
45
+ enumList.value.push(...res.data)
46
+ }
47
+ }
48
+
49
+ onMounted(async () => {
50
+ await fetchEnumList()
51
+ reset()
52
+ emit('loaded')
53
+ })
54
+
55
+
56
+
57
+ defineExpose({
58
+ getValue,
59
+ reset
60
+ })
61
+ </script>
62
+
63
+
64
+
65
+ <style scoped lang="less">
66
+
67
+ </style>
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <el-input v-model="dtoValue" v-bind="schema.option" class="input"></el-input>
3
+ </template>
4
+
5
+ <script setup>
6
+ import {ref,onMounted} from 'vue'
7
+
8
+ const {schemaKey,schema} = defineProps({
9
+ schemaKey: String,
10
+ schema: Object,
11
+ })
12
+
13
+ const emit = defineEmits(['loaded'])
14
+
15
+ const dtoValue = ref()
16
+ const getValue=()=>{
17
+ return dtoValue.value !==undefined?{
18
+ [schemaKey]:dtoValue.value
19
+ }:{}
20
+ }
21
+
22
+ const reset=()=>{
23
+ dtoValue.value = schema?.option?.default;
24
+ }
25
+
26
+ onMounted(() => {
27
+ reset()
28
+ emit('loaded')
29
+ })
30
+ defineExpose({
31
+ getValue,
32
+ reset
33
+ })
34
+ </script>
35
+
36
+
37
+
38
+ <style scoped lang="less">
39
+
40
+ </style>
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <el-select v-model="dtoValue" v-bind="schema.option" class="select">
3
+ <el-option
4
+ v-for="item in schema.option?.enumList"
5
+ :key="item.value"
6
+ :label="item.label"
7
+ :value="item.value"
8
+ >
9
+ </el-option>
10
+
11
+ </el-select>
12
+ </template>
13
+
14
+ <script setup>
15
+ import {ref,onMounted} from 'vue'
16
+
17
+ const {schemaKey,schema} = defineProps({
18
+ schemaKey: String,
19
+ schema: Object,
20
+ })
21
+
22
+ const emit = defineEmits(['loaded'])
23
+
24
+ const dtoValue = ref()
25
+ const getValue=()=>{
26
+ return dtoValue.value !==undefined?{
27
+ [schemaKey]:dtoValue.value
28
+ }:{}
29
+ }
30
+
31
+ const reset=()=>{
32
+ dtoValue.value = schema?.option?.default ?? schema?.option?.enumList?.[0]?.value;
33
+ }
34
+
35
+ onMounted(() => {
36
+ console.log('select111')
37
+ reset()
38
+ emit('loaded')
39
+ })
40
+ defineExpose({
41
+ getValue,
42
+ reset
43
+ })
44
+ </script>
45
+
46
+
47
+
48
+ <style scoped lang="less">
49
+
50
+ </style>
@@ -0,0 +1,142 @@
1
+ <template>
2
+ <el-form
3
+ v-if="schema && schema.properties"
4
+ inline
5
+ class="schema-search-bar"
6
+ >
7
+ <!-- 动态组件-->
8
+ <el-form-item
9
+ v-for="(schemaItem, key) in schema.properties"
10
+ :key="key"
11
+ :label="schemaItem.label"
12
+ >
13
+ <component
14
+ :is="SearchItemConfig[schemaItem?.option?.comType]?.component"
15
+ ref="searchComList"
16
+ :schema-key="key"
17
+ :schema="schemaItem"
18
+ @loaded="handleChildLoad"
19
+ />
20
+ </el-form-item>
21
+ <!-- 操作区域-->
22
+ <el-form-item>
23
+ <el-button
24
+ type="primary"
25
+ plain
26
+ class="search-btn"
27
+ @click="search"
28
+ >
29
+ 搜索
30
+ </el-button>
31
+ <el-button
32
+ plain
33
+ class="reset-btn"
34
+ @click="reset"
35
+ >
36
+ 重置
37
+ </el-button>
38
+ </el-form-item>
39
+ </el-form>
40
+ </template>
41
+
42
+ <script setup>
43
+ import {ref,toRefs,onMounted} from "vue";
44
+
45
+ import SearchItemConfig from "./search-item-config";
46
+ const props = defineProps({
47
+ /*
48
+ * {
49
+ * type:'object',
50
+ properties: {
51
+ key:{
52
+ ...schema,//标准schema 配置
53
+ type:'',//字段类型
54
+ label:'',//字段的中文名
55
+ // 字段在search-bar 中的相关配置
56
+ option:{
57
+ ...eleComponentConfig, //标准 el-component-column 配置
58
+ comType:"",//配置组件类型 input /select/...
59
+ default:'',//默认值
60
+ }
61
+ },
62
+ }
63
+ * }
64
+ * */
65
+ schema:Object
66
+ })
67
+
68
+ // 设置响应式
69
+ const { schema } = toRefs(props)
70
+
71
+ const emit = defineEmits(['load','search','reset'])
72
+ // 获取动态组件的ref元素
73
+ const searchComList = ref([])
74
+ // const handleSearchComList=(el)=>{
75
+ // if(el){
76
+ // searchComList.value.push(el)
77
+ // }
78
+ // }
79
+
80
+ onMounted(()=>{
81
+ console.log(SearchItemConfig,'SearchItemConfig')
82
+ })
83
+
84
+ // 获取最新的值 编辑每个动态组件获取组件里面的最新数据
85
+ const getValue =()=>{
86
+ let dtoObj ={};
87
+ searchComList.value.forEach((component)=>{
88
+ dtoObj={
89
+ ...dtoObj,
90
+ ...component?.getValue()
91
+ }
92
+ })
93
+ return dtoObj;
94
+ }
95
+
96
+ // 进行每个组件循环出发load事件
97
+ let childComLoadedCount =0;
98
+ const handleChildLoad =()=>{
99
+ childComLoadedCount++;
100
+ if(childComLoadedCount>=Object.keys(schema?.value?.properties).length){
101
+ emit('load',getValue())
102
+ }
103
+ }
104
+
105
+ // 搜索
106
+ const search = ()=>{
107
+ emit("search",getValue())
108
+ }
109
+ // 重置
110
+ const reset = ()=>{
111
+ // 遍历每个组件进行重置数据
112
+ searchComList.value.forEach((component)=>component?.reset())
113
+ emit("reset")
114
+ }
115
+ defineExpose({
116
+ reset,
117
+ getValue
118
+ })
119
+ </script>
120
+
121
+
122
+
123
+ <style scoped lang="less">
124
+ .schema-search-bar{
125
+ min-width: 500px;
126
+ .input{
127
+ width: 180px;
128
+ }
129
+ .select{
130
+ width: 180px;
131
+ }
132
+ .dynamic-select{
133
+ width: 180px;
134
+ }
135
+ .search-btn{
136
+ width: 100px;
137
+ }
138
+ .reset-btn{
139
+ width: 100px;
140
+ }
141
+ }
142
+ </style>
@@ -0,0 +1,24 @@
1
+ import input from './complex-view/input/input.vue'
2
+ import select from './complex-view/select/select.vue'
3
+ import dynamicSelect from './complex-view/dynamic-select/dynamic-select.vue'
4
+ import dateRange from './complex-view/date-range/date-range.vue'
5
+ import businessSearchItemConfig from '$businessSearchItemConfig'
6
+
7
+ const SearchItemConfig = {
8
+ input:{
9
+ component: input,
10
+ },
11
+ select:{
12
+ component: select,
13
+ },
14
+ dynamicSelect:{
15
+ component: dynamicSelect,
16
+ },
17
+ dateRange:{
18
+ component: dateRange,
19
+ }
20
+ }
21
+ export default {
22
+ ...SearchItemConfig,
23
+ ...businessSearchItemConfig
24
+ }
@@ -0,0 +1,238 @@
1
+ <template>
2
+ <div class="schema-table">
3
+ <el-table
4
+ class="table"
5
+ v-if="schema &&schema.properties"
6
+ v-loading="loading"
7
+ :data="tableData"
8
+ >
9
+ <template v-for="(schemaItem,key) in schema.properties">
10
+ <el-table-column
11
+ v-if="schemaItem.option.visible !== false"
12
+ :key="key"
13
+ :prop="key"
14
+ :label="schemaItem.label"
15
+ v-bind="schemaItem.option"
16
+ ></el-table-column>
17
+ </template>
18
+ <el-table-column
19
+ v-if="buttons?.length > 0"
20
+ label="操作"
21
+ fixed="right"
22
+ :width="operationWidth"
23
+ >
24
+ <template #default="scoped">
25
+ <el-button
26
+ v-for="item in buttons"
27
+ link
28
+ v-bind="item"
29
+ @click="operationHandler({btnConfig:item,rowData:scoped.row})"
30
+ >
31
+ {{item.label}}
32
+ </el-button>
33
+ </template>
34
+ </el-table-column>
35
+
36
+ </el-table>
37
+ <el-row justify="end" class="pagination">
38
+ <el-pagination
39
+ v-model:current-page="currentPage"
40
+ :page-size="pageSize"
41
+ :page-sizes="[10, 20, 50, 100]"
42
+ :total="total"
43
+ layout="total, sizes, prev, pager, next, jumper"
44
+ @size-change="onPageSizeChange"
45
+ @current-change="onCurrentPageChange"
46
+ />
47
+ </el-row>
48
+ </div>
49
+ </template>
50
+ <script setup>
51
+ import {ref,toRefs,computed,watch,onMounted,nextTick} from "vue";
52
+ import $curl from '$elpisCommon/curl.js'
53
+
54
+ const props = defineProps({
55
+ /*
56
+ * schema 配置 结构如下
57
+ * { //板块数据结构
58
+ type:'object',
59
+ properties: {
60
+ key:{
61
+ ...schema,//标准schema 配置
62
+ type:'',//字段类型
63
+ label:'',//字段的中文名
64
+ option:{
65
+ ...elTableColumnConfig,//标准的el-table-column 配置
66
+ visiable:true //默认为true (false 或者不配置时 表示不在表单中显示)
67
+ }
68
+ },
69
+ ...
70
+ }
71
+ },
72
+ * */
73
+ schema:Object,
74
+ /*
75
+ * 表格数据源 api
76
+ * */
77
+ api:String,
78
+
79
+ /*
80
+ * 请求参数,请求api 时携带
81
+ * */
82
+ apiParams:Object,
83
+ /*
84
+ * buttons:[
85
+ * {
86
+ * label:'',//按钮中文名
87
+ eventKey:'',//按钮事件名
88
+ eventOption:{},//按钮事件具体配置
89
+ ...elButtonConfig //标准el-button配置
90
+ * },
91
+ * ...
92
+ * ]
93
+ *
94
+ * */
95
+ buttons:Array
96
+ })
97
+
98
+
99
+ const {schema,api,buttons,apiParams} = toRefs(props)
100
+
101
+ const emit = defineEmits([ 'operate'])
102
+
103
+ // 计算按钮操作栏的长度
104
+ const operationWidth = computed(()=>{
105
+ return buttons?.value.length>0 ? buttons.value.reduce((pre,cur)=>{
106
+ return pre + cur.label.length *18
107
+ },50) : 50
108
+ })
109
+
110
+ const loading = ref(false)
111
+ const tableData=ref([])
112
+ const currentPage = ref(1)
113
+ const pageSize = ref(50)
114
+ const total = ref(0)
115
+
116
+
117
+
118
+ onMounted(() => {
119
+ initData()
120
+ })
121
+
122
+ watch([api,schema,apiParams],() =>{
123
+ initData()
124
+ },{deep:true})
125
+
126
+
127
+
128
+ const initData = () => {
129
+ currentPage.value = 1
130
+ pageSize.value = 50
131
+ nextTick(async ()=>{
132
+ await loadTableData()
133
+ })
134
+ }
135
+
136
+ let timerId = null
137
+ const loadTableData = async () => {
138
+ clearTimeout(timerId)
139
+ timerId = setTimeout(async () =>{
140
+ await fetchTableData()
141
+ timerId = null
142
+ },100)
143
+ }
144
+
145
+ const fetchTableData =async ()=>{
146
+ if(!api.value) {return }
147
+
148
+ showLoading()
149
+
150
+ // 请求table数据
151
+ const res = await $curl({
152
+ method:"get",
153
+ url:`${api.value}/list`,
154
+ query:{
155
+ ...apiParams.value,
156
+ page:currentPage.value,
157
+ size:pageSize.value
158
+ }
159
+ })
160
+
161
+ hideLoading()
162
+
163
+ if(!res || !res.success || !Array.isArray(res.data)){
164
+ tableData.value = []
165
+ total.value = 0
166
+ return
167
+ }
168
+
169
+ tableData.value = buildTableData(res.data)
170
+ total.value = res.metadata.total
171
+ }
172
+
173
+ /*
174
+ * 对后端返回的数据进行渲染前的处理
175
+ * @parma {Object} data 列表渲染
176
+ * */
177
+
178
+ const buildTableData =(listData)=>{
179
+ if(!schema.value?.properties){
180
+ return listData
181
+ }
182
+ return listData.map(rowData=>{
183
+ for(let dKey in rowData){
184
+ const schemaItem = schema.value.properties[dKey];
185
+ if(schemaItem?.option?.toFixed){
186
+ rowData[dKey] = rowData[dkey].toFixed &&rowData[dKey].toFixed(schemaItem.option.toFixed)
187
+ }
188
+ }
189
+ return rowData
190
+ })
191
+ }
192
+
193
+ const showLoading=()=>{
194
+ loading.value = true
195
+ }
196
+ const hideLoading=()=>{
197
+ loading.value = false
198
+ }
199
+
200
+ const operationHandler=({btnConfig,rowData})=>{
201
+ emit('operate',{btnConfig,rowData})
202
+ }
203
+
204
+ const onPageSizeChange= async (vale)=>{
205
+ pageSize.value=vale
206
+ await loadTableData()
207
+ }
208
+
209
+ const onCurrentPageChange=async (vale)=>{
210
+ currentPage.value=vale
211
+ await loadTableData()
212
+ }
213
+
214
+ defineExpose({
215
+ initData,
216
+ loadTableData,
217
+ showLoading,
218
+ hideLoading
219
+ })
220
+ </script>
221
+
222
+
223
+
224
+ <style scoped lang="less">
225
+ .schema-table{
226
+ flex: 1;
227
+ display: flex;
228
+ flex-direction: column;
229
+ overflow: auto;
230
+ .table{
231
+ flex: 1;
232
+ }
233
+ .pagination{
234
+ margin: 10px 0;
235
+ text-align: right;
236
+ }
237
+ }
238
+ </style>
@@ -0,0 +1,31 @@
1
+
2
+ <template>
3
+ <el-container class="sider-container">
4
+ <el-aside width="200px" class="aside">
5
+ <slot name="menu-content"></slot>
6
+ </el-aside>
7
+ <el-main class="main">
8
+ <slot name="main-content"></slot>
9
+ </el-main>
10
+ </el-container>
11
+ </template>
12
+ <script setup>
13
+
14
+ </script>
15
+
16
+
17
+ <style scoped lang="less">
18
+ .sider-container {
19
+ height: 100%;
20
+ .aside{
21
+ border-right: 1px solid #e8e8e8;
22
+ }
23
+ .main{
24
+ overflow: scroll;
25
+ }
26
+ }
27
+
28
+ :deep(.el-menu){
29
+ border-right: 0;
30
+ }
31
+ </style>
Binary file