@siven-li/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 (78) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc +55 -0
  3. package/README.md +201 -0
  4. package/app/controller/base.js +37 -0
  5. package/app/controller/project.js +65 -0
  6. package/app/controller/view.js +20 -0
  7. package/app/extend/logger.js +35 -0
  8. package/app/middleware/api-params-verify.js +97 -0
  9. package/app/middleware/api-sign-verify.js +30 -0
  10. package/app/middleware/error-handler.js +34 -0
  11. package/app/middleware/project-handler.js +22 -0
  12. package/app/middleware.js +37 -0
  13. package/app/pages/assets/custom.css +16 -0
  14. package/app/pages/boot.js +53 -0
  15. package/app/pages/common/curl.js +74 -0
  16. package/app/pages/common/utils.js +2 -0
  17. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +35 -0
  18. package/app/pages/dashboard/complex-view/header-view/header-view.vue +132 -0
  19. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +45 -0
  20. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +37 -0
  21. package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +130 -0
  22. package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
  23. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +90 -0
  24. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +110 -0
  25. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +133 -0
  26. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +125 -0
  27. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +97 -0
  28. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +35 -0
  29. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +127 -0
  30. package/app/pages/dashboard/dashboard.vue +94 -0
  31. package/app/pages/dashboard/entry.dashboard.js +43 -0
  32. package/app/pages/store/index.js +3 -0
  33. package/app/pages/store/menu.js +59 -0
  34. package/app/pages/store/project.js +17 -0
  35. package/app/pages/widgets/header-container/assets/avatar.png +0 -0
  36. package/app/pages/widgets/header-container/assets/logo.png +0 -0
  37. package/app/pages/widgets/header-container/header-container.vue +124 -0
  38. package/app/pages/widgets/schema-form/complex-view/input/input.vue +143 -0
  39. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +141 -0
  40. package/app/pages/widgets/schema-form/complex-view/select/select.vue +127 -0
  41. package/app/pages/widgets/schema-form/form-item-config.js +22 -0
  42. package/app/pages/widgets/schema-form/schema-form.vue +129 -0
  43. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +49 -0
  44. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +65 -0
  45. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +43 -0
  46. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +50 -0
  47. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +133 -0
  48. package/app/pages/widgets/schema-search-bar/search-item-config.js +26 -0
  49. package/app/pages/widgets/schema-table/schema-table.vue +234 -0
  50. package/app/pages/widgets/sider-container/sider-container.vue +32 -0
  51. package/app/public/static/logo.png +0 -0
  52. package/app/public/static/normalize.css +239 -0
  53. package/app/router/project.js +6 -0
  54. package/app/router/view.js +9 -0
  55. package/app/router-schema/project.js +30 -0
  56. package/app/service/base.js +12 -0
  57. package/app/service/project.js +44 -0
  58. package/app/view/entry.tpl +26 -0
  59. package/app/webpack/config/webpack.base.js +194 -0
  60. package/app/webpack/config/webpack.dev.js +58 -0
  61. package/app/webpack/config/webpack.prod.js +114 -0
  62. package/app/webpack/dev.js +48 -0
  63. package/app/webpack/libs/blank.js +1 -0
  64. package/app/webpack/prod.js +18 -0
  65. package/config/config.default.js +3 -0
  66. package/elpis-core/env.js +20 -0
  67. package/elpis-core/index.js +88 -0
  68. package/elpis-core/loader/config.js +55 -0
  69. package/elpis-core/loader/controller.js +56 -0
  70. package/elpis-core/loader/extend.js +45 -0
  71. package/elpis-core/loader/middleware.js +58 -0
  72. package/elpis-core/loader/router-schema.js +38 -0
  73. package/elpis-core/loader/router.js +40 -0
  74. package/elpis-core/loader/service.js +56 -0
  75. package/index.js +39 -0
  76. package/model/index.js +104 -0
  77. package/package.json +93 -0
  78. package/test/controll/project.test.js +203 -0
@@ -0,0 +1,127 @@
1
+ <template>
2
+ <el-row
3
+ type="flex"
4
+ align="middle"
5
+ class="form-item"
6
+ >
7
+ <!-- label -->
8
+ <el-row
9
+ justify="end"
10
+ class="item-label"
11
+ >
12
+ <el-row
13
+ v-if="schema.option?.required"
14
+ type="flex"
15
+ class="required"
16
+ >
17
+ *
18
+ </el-row>
19
+ {{ schema.label }}
20
+ </el-row>
21
+ <!-- value -->
22
+ <el-row class="item-value">
23
+ <el-select
24
+ v-model="dtoValue"
25
+ v-bind="schema.option"
26
+ class="component"
27
+ :class="{'valid-border': validTips}"
28
+ @change="onChange"
29
+ >
30
+ <el-option
31
+ v-for="item in schema.option?.enumList"
32
+ :key="item.value"
33
+ :label="item.label"
34
+ :value="item.value"
35
+ />
36
+ </el-select>
37
+ </el-row>
38
+ <el-row
39
+ v-if="validTips"
40
+ class="valid-tips"
41
+ >
42
+ {{ validTips }}
43
+ </el-row>
44
+ </el-row>
45
+ </template>
46
+ <script setup>
47
+ import { ref, onMounted, watch, inject, toRefs } from 'vue';
48
+
49
+ const ajv = inject('ajv');
50
+
51
+ const props = defineProps({
52
+ schemaKey: String,
53
+ schema: Object,
54
+ model: null
55
+ });
56
+ const { schemaKey, schema } = props;
57
+ const { model } = toRefs(props);
58
+
59
+ const name = ref('select');
60
+
61
+ const dtoValue = ref();
62
+ const validTips = ref(null);
63
+ const initData = () => {
64
+ validTips.value = null;
65
+ dtoValue.value = model.value ?? schema.option?.default;
66
+
67
+ }
68
+
69
+ onMounted(() => {
70
+ initData();
71
+ });
72
+
73
+ watch([model, schema], () => {
74
+ initData();
75
+ }, { deep: true });
76
+
77
+ const validate = () => {
78
+ validTips.value = null;
79
+
80
+ // 检验是否必填
81
+ if (schema.option?.required && !dtoValue.value) {
82
+ validTips.value = '不能为空';
83
+ return false;
84
+ }
85
+ // 校验 schema
86
+ if (dtoValue.value) {
87
+ let dtoEnum = [];
88
+ if (schema.option?.enumList) {
89
+ dtoEnum = schema.option.enumList.map(item => item.value);
90
+ }
91
+
92
+ const validate = ajv.compile({
93
+ schema,
94
+ ... { enum: dtoEnum }
95
+ });
96
+ const valid = validate(dtoValue.value);
97
+ if (!valid && validate.errors && validate.errors[0]) {
98
+ if (validate.errors[0].keyword === 'enum') {
99
+ validTips.value = '取值超出枚举范围';
100
+ } else {
101
+ console.log(validate.errors[0]);
102
+ validTips.value = '不符合要求';
103
+ }
104
+ return false;
105
+ }
106
+ }
107
+ return true;
108
+ }
109
+ const getValue = () => {
110
+ return dtoValue.value !== undefined ? {
111
+ [schemaKey]: dtoValue.value
112
+ } : {}
113
+ }
114
+
115
+ const onChange = () => {
116
+ validate();
117
+ }
118
+
119
+ defineExpose({
120
+ name,
121
+ validate,
122
+ getValue
123
+ })
124
+ </script>
125
+ <style lang="less" scoped>
126
+
127
+ </style>
@@ -0,0 +1,22 @@
1
+ import input from './complex-view/input/input.vue';
2
+ import inputNumber from './complex-view/input-number/input-number.vue';
3
+ import select from './complex-view/select/select.vue';
4
+
5
+ // 业务拓展 form-item 配置
6
+ import BusinessFromItmeConfig from '$businessFromItmeConfig'
7
+
8
+ const FormItemConfig = {
9
+ input: {
10
+ component: input
11
+ },
12
+ inputNumber: {
13
+ component: inputNumber
14
+ },
15
+ select: {
16
+ component: select
17
+ }
18
+ };
19
+ export default {
20
+ ...FormItemConfig,
21
+ ...BusinessFromItmeConfig
22
+ }
@@ -0,0 +1,129 @@
1
+ <!-- eslint-disable vue/no-v-for-template-key -->
2
+ <template>
3
+ <el-row
4
+ v-if="schema && schema.properties"
5
+ class="schema-form"
6
+ >
7
+ <template
8
+ v-for="(itemSchema, key) in schema.properties"
9
+ :key="key"
10
+ >
11
+ <component
12
+ :is="FormItemConfig[itemSchema.option?.comType]?.component"
13
+ v-show="itemSchema.option.visible !== false"
14
+ ref="formComList"
15
+ :schema-key="key"
16
+ :schema="itemSchema"
17
+ :model="model ? model[key] : undefined"
18
+ />
19
+ </template>
20
+ </el-row>
21
+ </template>
22
+ <script setup>
23
+ import { ref, toRefs, provide } from 'vue';
24
+ import FormItemConfig from './form-item-config.js'
25
+
26
+ const Ajv = require('ajv');
27
+ const ajv = new Ajv();
28
+ provide('ajv', ajv);
29
+
30
+ const props = defineProps({
31
+ /**
32
+ * schema 配置,结构如下:
33
+ * {
34
+ type: 'object',
35
+ properties: {
36
+ key: {
37
+ ...schema, // 标准 schema 配置
38
+ type: '', // 字段类型
39
+ label: '', // 字段中文名
40
+ option: {
41
+ ...elFormItemConfig, // 标准 el-form-item 配置
42
+ comType: '', // 空间类型 input / select / input-number / ...
43
+ required: false, // 表单项是否必填,默认 false
44
+ visible: true, // 是否展示 (true/false),默认为 true
45
+ disabled: false, // 是否禁用 (true/false),默认为 false
46
+ default: '', // 默认值
47
+
48
+ // comType === 'select'时生效
49
+ enumList: [], // 下拉选项列表
50
+ },
51
+ },
52
+ ...
53
+ }
54
+ }
55
+ */
56
+ schema: Object,
57
+ /**
58
+ * 表单数据
59
+ */
60
+ model: Object
61
+ });
62
+ const { schema } = toRefs(props);
63
+
64
+ const formComList = ref([]);
65
+
66
+ // 表单校验
67
+ const validate = () => {
68
+ return formComList.value.every(item => item.validate());
69
+ }
70
+ // 获取表单值
71
+ const getValue = () => {
72
+ return formComList.value.reduce((dtoObj, item) => {
73
+ return {
74
+ ...dtoObj,
75
+ ...item.getValue()
76
+ }
77
+ }, {});
78
+ }
79
+
80
+ defineExpose({
81
+ validate,
82
+ getValue
83
+ })
84
+ </script>
85
+ <style lang="less">
86
+ .schema-form {
87
+ .form-item {
88
+ margin-bottom: 20px;
89
+ min-width: 500px;
90
+ .item-label {
91
+ margin-right: 15px;
92
+ min-width: 70px;
93
+ text-align: right;
94
+ font-size: 14px;
95
+ color: #ffffff;
96
+ word-break: break-all;
97
+ .required {
98
+ top: 2px;
99
+ padding-left: 4px;
100
+ color: #f56c6c;
101
+ font-size: 20px;
102
+ }
103
+ }
104
+ .item-value {
105
+ .component {
106
+ width: 320px;
107
+ }
108
+ .valid-border {
109
+ .el-input__wrapper {
110
+ border: 1px solid #F93F3F;
111
+ box-shadow: 0 0 0 0;
112
+ }
113
+ .el-slect__wrapper {
114
+ border: 1px solid #F93F3F;
115
+ box-shadow: 0 0 0 0;
116
+ }
117
+ }
118
+ }
119
+ .valid-tips {
120
+ margin-left: 10px;
121
+ height: 36px;
122
+ line-height: 36px;
123
+ overflow: hidden;
124
+ font-size: 12px;
125
+ color: #F93F3F;
126
+ }
127
+ }
128
+ }
129
+ </style>
@@ -0,0 +1,49 @@
1
+ <template>
2
+ <el-date-picker
3
+ v-model="dtoValue"
4
+ v-bind="schema.option"
5
+ type="daterange"
6
+ range-separator="至"
7
+ :start-placeholder="schema.label + '开始'"
8
+ :end-placeholder="schema.label + '结束'"
9
+ class="date-range"
10
+ />
11
+ </template>
12
+
13
+ <script setup>
14
+ import { ref, onMounted } from 'vue';
15
+ import moment from 'moment';
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?.length === 2 ? {
27
+ [`${schemaKey}_start`]: moment(dtoValue.value[0]).format('YYYY-MM-DD'),
28
+ [`${schemaKey}_end`]: moment(dtoValue.value[1]).format('YYYY-MM-DD')
29
+ } : {}
30
+ }
31
+
32
+ const reset = () => {
33
+ dtoValue.value = [];
34
+ }
35
+
36
+ onMounted(async () => {
37
+ reset();
38
+ emit('loaded');
39
+ });
40
+
41
+ defineExpose({
42
+ getValue,
43
+ reset
44
+ });
45
+ </script>
46
+
47
+ <style lang="less" scoped>
48
+
49
+ </style>
@@ -0,0 +1,65 @@
1
+ <template>
2
+ <el-select
3
+ v-model="dtoValue"
4
+ v-bind="schema.option"
5
+ class="dynamic-select"
6
+ >
7
+ <el-option
8
+ v-for="item in enumList"
9
+ :key="item.value"
10
+ :label="item.label"
11
+ :value="item.value"
12
+ />
13
+ </el-select>
14
+ </template>
15
+
16
+ <script setup>
17
+ import { ref, onMounted } from 'vue';
18
+ import $curl from '$elpisCommon/curl.js'
19
+
20
+ const { schemaKey, schema } = defineProps({
21
+ schemaKey: String,
22
+ schema: Object
23
+ })
24
+
25
+ const emit = defineEmits(['loaded']);
26
+
27
+ const dtoValue = ref();
28
+ const getValue = () => {
29
+ return dtoValue.value !== undefined ? {
30
+ [schemaKey]: dtoValue.value
31
+ } : {}
32
+ }
33
+
34
+ const enumList = ref([]);
35
+ const fetchEnumList = async () => {
36
+ const res = await $curl({
37
+ method: 'get',
38
+ url: schema.option?.api,
39
+ data: {}
40
+ });
41
+
42
+ if (res?.data?.length > 0) {
43
+ enumList.value.push(...res.data);
44
+ }
45
+ }
46
+
47
+ const reset = () => {
48
+ dtoValue.value = schema?.option?.default ?? enumList.value?.[0].value;
49
+ }
50
+
51
+ onMounted(async () => {
52
+ await fetchEnumList();
53
+ reset();
54
+ emit('loaded');
55
+ });
56
+
57
+ defineExpose({
58
+ getValue,
59
+ reset
60
+ });
61
+ </script>
62
+
63
+ <style lang="less" scoped>
64
+
65
+ </style>
@@ -0,0 +1,43 @@
1
+ <template>
2
+ <el-input
3
+ v-model="dtoValue"
4
+ v-bind="schema.option"
5
+ class="input"
6
+ />
7
+ </template>
8
+
9
+ <script setup>
10
+ import { ref, onMounted } from 'vue';
11
+
12
+ const { schemaKey, schema } = defineProps({
13
+ schemaKey: String,
14
+ schema: Object
15
+ })
16
+
17
+ const emit = defineEmits(['loaded']);
18
+
19
+ const dtoValue = ref();
20
+ const getValue = () => {
21
+ return dtoValue.value !== undefined ? {
22
+ [schemaKey]: dtoValue.value
23
+ } : {}
24
+ }
25
+
26
+ const reset = () => {
27
+ dtoValue.value = schema?.option?.default;
28
+ }
29
+
30
+ onMounted(() => {
31
+ reset();
32
+ emit('loaded');
33
+ });
34
+
35
+ defineExpose({
36
+ getValue,
37
+ reset
38
+ });
39
+ </script>
40
+
41
+ <style lang="less" scoped>
42
+
43
+ </style>
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <el-select
3
+ v-model="dtoValue"
4
+ v-bind="schema.option"
5
+ class="select"
6
+ >
7
+ <el-option
8
+ v-for="item in schema.option?.enumList"
9
+ :key="item.value"
10
+ :label="item.label"
11
+ :value="item.value"
12
+ />
13
+ </el-select>
14
+ </template>
15
+
16
+ <script setup>
17
+ import { ref, onMounted } from 'vue';
18
+
19
+ const { schemaKey, schema } = defineProps({
20
+ schemaKey: String,
21
+ schema: Object
22
+ })
23
+
24
+ const emit = defineEmits(['loaded']);
25
+
26
+ const dtoValue = ref();
27
+ const getValue = () => {
28
+ return dtoValue.value !== undefined ? {
29
+ [schemaKey]: dtoValue.value
30
+ } : {}
31
+ }
32
+
33
+ const reset = () => {
34
+ dtoValue.value = schema?.option?.default ?? schema?.option?.enumList?.[0].value;
35
+ }
36
+
37
+ onMounted(() => {
38
+ reset();
39
+ emit('loaded');
40
+ });
41
+
42
+ defineExpose({
43
+ getValue,
44
+ reset
45
+ });
46
+ </script>
47
+
48
+ <style lang="less" scoped>
49
+
50
+ </style>
@@ -0,0 +1,133 @@
1
+ <template>
2
+ <el-form
3
+ v-if="schema && schema.properties"
4
+ :inline="true"
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
+ <!-- 展示子组件 -->
14
+ <component
15
+ :is="SearchItemConfig[schemaItem.option?.comType]?.component"
16
+ :ref="handleSearchComList"
17
+ :schema-key="key"
18
+ :schema="schemaItem"
19
+ @loaded="handleChildLoaded"
20
+ />
21
+ </el-form-item>
22
+ <!-- 操作区域 -->
23
+ <el-form-item>
24
+ <el-button
25
+ type="primary"
26
+ plain
27
+ class="search-btn"
28
+ @click="search"
29
+ >
30
+ 搜索
31
+ </el-button>
32
+ <el-button
33
+ plain
34
+ class="reset-btn"
35
+ @click="reset"
36
+ >
37
+ 重置
38
+ </el-button>
39
+ </el-form-item>
40
+ </el-form>
41
+ </template>
42
+ <script setup>
43
+ import { ref, toRefs } from "vue";
44
+ import SearchItemConfig from "./search-item-config";
45
+
46
+ const props = defineProps({
47
+ /**
48
+ * schema 配置,结构如下:
49
+ * {
50
+ type: 'object',
51
+ properties: {
52
+ key: {
53
+ ...schema, // 标准 schema 配置
54
+ type: '', // 字段类型
55
+ label: '', // 字段中文名
56
+ // 字段在 search 中的相关配置
57
+ option: {
58
+ ...elComponentConfig, // 标准 el-component 配置
59
+ comType: '', // 组件类型 input / select / date-picker / cascader / ...
60
+ default: '' // 搜索默认值
61
+ }
62
+ },
63
+ ...
64
+ }
65
+ * }
66
+ */
67
+ schema: {
68
+ type: Object,
69
+ default: () => ({})
70
+ }
71
+ })
72
+
73
+ const { schema } = toRefs(props);
74
+
75
+ const emit = defineEmits(['search', 'load', 'reset']);
76
+
77
+
78
+ const searchComList = ref([]);
79
+ const handleSearchComList = (el) => {
80
+ searchComList.value.push(el);
81
+ }
82
+
83
+ const getValue = () => {
84
+ return searchComList.value.reduce((dtoObj, item) => {
85
+ return {
86
+ ...dtoObj,
87
+ ...item.getValue()
88
+ }
89
+ }, {});
90
+ }
91
+
92
+ let childComLoadedCount = 0;
93
+ const handleChildLoaded = () => {
94
+ childComLoadedCount++;
95
+ if (childComLoadedCount >= Object.keys(schema?.value?.properties).length) {
96
+ emit('load', getValue());
97
+ }
98
+ }
99
+
100
+ const search = () => {
101
+ emit('search', getValue());
102
+ }
103
+
104
+ const reset = () => {
105
+ searchComList.value.forEach(com => com?.reset());
106
+ emit('reset');
107
+ }
108
+
109
+ defineExpose({
110
+ getValue,
111
+ reset
112
+ })
113
+ </script>
114
+ <style lang="less">
115
+ .schema-search-bar {
116
+ min-width: 500px;
117
+ .input {
118
+ width: 180px;
119
+ }
120
+ .select {
121
+ width: 180px;
122
+ }
123
+ .dynamic-select {
124
+ width: 180px;
125
+ }
126
+ .search-btn {
127
+ width: 100px;
128
+ }
129
+ .reset-btn {
130
+ width: 100px;
131
+ }
132
+ }
133
+ </style>
@@ -0,0 +1,26 @@
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
+
6
+ // 业务拓展 searchItem 配置
7
+ import BusinessSearchItemConfig from '$businessSearchItemConfig';
8
+
9
+ const SearchItemConfig = {
10
+ input: {
11
+ component: input
12
+ },
13
+ select: {
14
+ component: select
15
+ },
16
+ dynamicSelect: {
17
+ component: dynamicSelect
18
+ },
19
+ dateRange: {
20
+ component: dateRange
21
+ }
22
+ }
23
+ export default {
24
+ ...SearchItemConfig,
25
+ ...BusinessSearchItemConfig
26
+ }