@jiangliffey/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 +55 -0
  3. package/CLAUDE.md +81 -0
  4. package/README.md +200 -0
  5. package/app/controller/base.js +38 -0
  6. package/app/controller/project.js +74 -0
  7. package/app/controller/view.js +22 -0
  8. package/app/extend/logger.js +35 -0
  9. package/app/middleware/api-params-verify.js +81 -0
  10. package/app/middleware/api-sign-verify.js +35 -0
  11. package/app/middleware/error-handler.js +33 -0
  12. package/app/middleware/project-handler.js +27 -0
  13. package/app/middleware.js +37 -0
  14. package/app/pages/asserts/custom.css +12 -0
  15. package/app/pages/boot.js +50 -0
  16. package/app/pages/common/curl.js +89 -0
  17. package/app/pages/common/utils.js +2 -0
  18. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +21 -0
  19. package/app/pages/dashboard/complex-view/header-view/header-view.vue +123 -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 +40 -0
  22. package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +124 -0
  23. package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
  24. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +87 -0
  25. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +100 -0
  26. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +118 -0
  27. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +124 -0
  28. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +80 -0
  29. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +21 -0
  30. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +135 -0
  31. package/app/pages/dashboard/dashboard.vue +96 -0
  32. package/app/pages/dashboard/entry.dashboard.js +45 -0
  33. package/app/pages/dashboard/todo/todo.vue +11 -0
  34. package/app/pages/store/index.js +4 -0
  35. package/app/pages/store/menu.js +58 -0
  36. package/app/pages/store/project.js +14 -0
  37. package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
  38. package/app/pages/widgets/header-container/asserts/logo.png +0 -0
  39. package/app/pages/widgets/header-container/header-container.vue +106 -0
  40. package/app/pages/widgets/schema-form/complex-view/input/input.vue +134 -0
  41. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +136 -0
  42. package/app/pages/widgets/schema-form/complex-view/select/select.vue +116 -0
  43. package/app/pages/widgets/schema-form/form-item-config.js +23 -0
  44. package/app/pages/widgets/schema-form/schema-form.vue +135 -0
  45. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +50 -0
  46. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +67 -0
  47. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +44 -0
  48. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +51 -0
  49. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +129 -0
  50. package/app/pages/widgets/schema-search-bar/search-item-config.js +27 -0
  51. package/app/pages/widgets/schema-table/schema-table.vue +235 -0
  52. package/app/pages/widgets/sider-container/sider-container.vue +31 -0
  53. package/app/public/static/logo.png +0 -0
  54. package/app/public/static/normalize.css +239 -0
  55. package/app/router/project.js +6 -0
  56. package/app/router/view.js +8 -0
  57. package/app/router-schema/project.js +30 -0
  58. package/app/service/base.js +11 -0
  59. package/app/service/project.js +56 -0
  60. package/app/view/entry.tpl +26 -0
  61. package/app/webpack/config/webpack.base.js +203 -0
  62. package/app/webpack/config/webpack.dev.js +59 -0
  63. package/app/webpack/config/webpack.prod.js +107 -0
  64. package/app/webpack/dev.js +53 -0
  65. package/app/webpack/libs/blank.js +3 -0
  66. package/app/webpack/prod.js +17 -0
  67. package/config/config.default.js +3 -0
  68. package/docs/dashboard-model.js +153 -0
  69. package/elpis-core/env.js +23 -0
  70. package/elpis-core/index.js +96 -0
  71. package/elpis-core/loader/config.js +50 -0
  72. package/elpis-core/loader/controller.js +54 -0
  73. package/elpis-core/loader/extend.js +49 -0
  74. package/elpis-core/loader/middleware.js +53 -0
  75. package/elpis-core/loader/router-schema.js +41 -0
  76. package/elpis-core/loader/router.js +45 -0
  77. package/elpis-core/loader/service.js +54 -0
  78. package/index.js +40 -0
  79. package/model/index.js +99 -0
  80. package/package.json +92 -0
  81. package/test/controller/project.test.js +225 -0
@@ -0,0 +1,135 @@
1
+ <template>
2
+ <el-row v-if="schema && schema.properties" class="schema-form">
3
+ <template v-for="(itemSchema, key) in schema.properties" :key="key">
4
+ <component
5
+ v-show="itemSchema.option.visible !== false"
6
+ ref="formComList"
7
+ :is="FormItemConfig[itemSchema.option?.comType]?.component"
8
+ :schemaKey="key"
9
+ :schema="itemSchema"
10
+ :model="model ? model[key] : undefined"
11
+ ></component>
12
+ </template>
13
+ </el-row>
14
+ </template>
15
+
16
+ <script setup>
17
+ import { ref, toRefs, provide } from 'vue';
18
+ import FormItemConfig from './form-item-config.js';
19
+
20
+ const Ajv = require('ajv');
21
+ const ajv = new Ajv();
22
+ provide('ajv', ajv);
23
+
24
+ const props = defineProps({
25
+ /**
26
+ * schema 配置,结构如下:
27
+ * {
28
+ * type: 'object',
29
+ properties: {
30
+ key: {
31
+ ...schema, // 标准 schema 配置
32
+ type: '', // 字段类型
33
+ label: '', // 字段中文名
34
+ // 字段在 search-bar 中的相关配置
35
+ option: {
36
+ ...elComponentConfig, // 标准 el-table-column 配置
37
+ comType: '', // 配置组件类型 input/select/...
38
+ required: false, // 表单项是否必填 默认false
39
+ visible: true, // 默认为 true
40
+ disable: false, // 是否禁用,默认false
41
+ default: '', // 默认值
42
+ // comType === 'select' 时生效
43
+ enumList: [], // 枚举列表
44
+ },
45
+ },
46
+ ...
47
+ },
48
+ }
49
+ */
50
+ schema: Object,
51
+ /**
52
+ * 表单数据
53
+ */
54
+ model: Object,
55
+ });
56
+
57
+ const { schema, model } = toRefs(props);
58
+
59
+ const formComList = ref([]); // 存储表单项组件实例的列表
60
+
61
+ // 表单校验
62
+ const validate = () => {
63
+ return formComList.value.every(component => {
64
+ if (component && component.validate) {
65
+ return component.validate();
66
+ }
67
+ return true; // 如果组件没有 validate 方法,则认为该组件校验通过
68
+ });
69
+ };
70
+
71
+ // 获取表单值
72
+ const getValue = () => {
73
+ return formComList.value.reduce((dtoObj, component) => {
74
+ return {
75
+ ...dtoObj,
76
+ ...component.getValue(),
77
+ };
78
+ }, {});
79
+ };
80
+
81
+ defineExpose({
82
+ validate,
83
+ getValue,
84
+ });
85
+ </script>
86
+
87
+ <style lang="less">
88
+ .schema-form {
89
+ .form-item {
90
+ margin-bottom: 20px;
91
+ min-width: 500px;
92
+
93
+ .item-label {
94
+ margin-right: 15px;
95
+ min-width: 70px;
96
+ text-align: right;
97
+ font-size: 14px;
98
+ color: white;
99
+ word-break: break-all;
100
+
101
+ .required {
102
+ top: 2px;
103
+ padding-left: 4px;
104
+ color: #f56c6c;
105
+ font-size: 20px;
106
+ }
107
+ }
108
+
109
+ .item-value {
110
+ .component {
111
+ width: 320px;
112
+ }
113
+ .valid-border {
114
+ .el-input__wrapper {
115
+ border: 1px solid #f93f3f;
116
+ box-shadow: 0 0 0 0;
117
+ }
118
+ .el-select__wrapper {
119
+ border: 1px solid #f93f3f;
120
+ box-shadow: 0 0 0 0;
121
+ }
122
+ }
123
+ }
124
+
125
+ .valid-tips {
126
+ margin-left: 10px;
127
+ height: 36px;
128
+ line-height: 36px;
129
+ overflow: hidden;
130
+ font-size: 12px;
131
+ color: #f93f3f;
132
+ }
133
+ }
134
+ }
135
+ </style>
@@ -0,0 +1,50 @@
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
+ ></el-date-picker>
11
+ </template>
12
+
13
+ <script setup>
14
+ import { ref, onMounted } from 'vue';
15
+ import moment from 'moment/moment';
16
+
17
+ // schemaKey: 当前搜索字段的 key,schema 是该字段经过 buildDtoSchema 处理后的配置
18
+ const { schemaKey, schema } = defineProps({
19
+ schemaKey: String,
20
+ schema: Object
21
+ })
22
+
23
+ const emit = defineEmits(['loaded']);
24
+
25
+ const dtoValue = ref();
26
+
27
+ // 有值时返回 { 字段key: 输入值 },无值时不参与搜索。
28
+ const getValue = () => {
29
+ return dtoValue.value?.length === 2 ? {
30
+ [`${schemaKey}_start`]: moment(dtoValue.value[0]).format('YYYY-MM-DD'),
31
+ [`${schemaKey}_end`]: moment(dtoValue.value[1]).format('YYYY-MM-DD')
32
+ } : {}
33
+ }
34
+
35
+ const reset = () => {
36
+ dtoValue.value = [];
37
+ }
38
+
39
+ onMounted(() => {
40
+ reset();
41
+ emit('loaded');
42
+ });
43
+
44
+ // 暴露给父组件调用,用于获取输入框的值和执行重置。
45
+ defineExpose({ getValue, reset });
46
+ </script>
47
+
48
+ <style lang="less" scoped>
49
+
50
+ </style>
@@ -0,0 +1,67 @@
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
+ // schemaKey: 当前搜索字段的 key,schema 是该字段经过 buildDtoSchema 处理后的配置
21
+ const { schemaKey, schema } = defineProps({
22
+ schemaKey: String,
23
+ schema: Object
24
+ })
25
+
26
+ const emit = defineEmits(['loaded']);
27
+
28
+ const dtoValue = ref();
29
+
30
+ // 有值时返回 { 字段key: 输入值 },无值时不参与搜索。
31
+ const getValue = () => {
32
+ return dtoValue.value !== undefined ? {
33
+ [schemaKey]: dtoValue.value
34
+ } : {}
35
+ }
36
+
37
+ const reset = () => {
38
+ dtoValue.value = schema?.option?.default ?? enumList.value[0]?.value;
39
+ }
40
+
41
+ const enumList = ref([]);
42
+ const fetchEnumList = async () => {
43
+ const res = await $curl({
44
+ method: 'get',
45
+ url: schema.option?.api,
46
+ data: {}
47
+ });
48
+
49
+ if(res?.data?.length > 0) {
50
+ enumList.value.push(...res?.data);
51
+ }
52
+ }
53
+
54
+
55
+ onMounted(async() => {
56
+ await fetchEnumList();
57
+ reset();
58
+ emit('loaded');
59
+ });
60
+
61
+ // 暴露给父组件调用,用于获取输入框的值和执行重置。
62
+ defineExpose({ getValue, reset });
63
+ </script>
64
+
65
+ <style lang="less" scoped>
66
+
67
+ </style>
@@ -0,0 +1,44 @@
1
+ <template>
2
+ <el-input
3
+ v-model="dtoValue"
4
+ v-bind="schema.option"
5
+ class="input"
6
+ ></el-input>
7
+ </template>
8
+
9
+ <script setup>
10
+ import { ref, onMounted } from 'vue';
11
+
12
+ // schemaKey: 当前搜索字段的 key,schema 是该字段经过 buildDtoSchema 处理后的配置
13
+ const { schemaKey, schema } = defineProps({
14
+ schemaKey: String,
15
+ schema: Object
16
+ })
17
+
18
+ const emit = defineEmits(['loaded']);
19
+
20
+ const dtoValue = ref();
21
+
22
+ // 有值时返回 { 字段key: 输入值 },无值时不参与搜索。
23
+ const getValue = () => {
24
+ return dtoValue.value !== undefined ? {
25
+ [schemaKey]: dtoValue.value
26
+ } : {}
27
+ }
28
+
29
+ const reset = () => {
30
+ dtoValue.value = schema?.option?.default;
31
+ }
32
+
33
+ onMounted(() => {
34
+ reset();
35
+ emit('loaded');
36
+ });
37
+
38
+ // 暴露给父组件调用,用于获取输入框的值和执行重置。
39
+ defineExpose({ getValue, reset });
40
+ </script>
41
+
42
+ <style lang="less" scoped>
43
+
44
+ </style>
@@ -0,0 +1,51 @@
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
+ // schemaKey: 当前搜索字段的 key,schema 是该字段经过 buildDtoSchema 处理后的配置
20
+ const { schemaKey, schema } = defineProps({
21
+ schemaKey: String,
22
+ schema: Object
23
+ })
24
+
25
+ const emit = defineEmits(['loaded']);
26
+
27
+ const dtoValue = ref();
28
+
29
+ // 有值时返回 { 字段key: 输入值 },无值时不参与搜索。
30
+ const getValue = () => {
31
+ return dtoValue.value !== undefined ? {
32
+ [schemaKey]: dtoValue.value
33
+ } : {}
34
+ }
35
+
36
+ const reset = () => {
37
+ dtoValue.value = schema?.option?.default ?? schema?.option?.enumList[0]?.value;
38
+ }
39
+
40
+ onMounted(() => {
41
+ reset();
42
+ emit('loaded');
43
+ });
44
+
45
+ // 暴露给父组件调用,用于获取输入框的值和执行重置。
46
+ defineExpose({ getValue, reset });
47
+ </script>
48
+
49
+ <style lang="less" scoped>
50
+
51
+ </style>
@@ -0,0 +1,129 @@
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
+ :ref="searchComList"
16
+ :is="SearchItemConfig[schemaItem.option?.comType]?.component"
17
+ :schemaKey="key"
18
+ :schema="schemaItem"
19
+ @loaded="handleChildLoaded"
20
+ ></component>
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
+ >搜索</el-button>
30
+ <el-button
31
+ plain
32
+ class="reset-btn"
33
+ @click="reset"
34
+ >重置</el-button>
35
+ </el-form-item>
36
+ </el-form>
37
+ </template>
38
+
39
+ <script setup>
40
+ import { ref, toRefs } from 'vue';
41
+ import SearchItemConfig from './search-item-config.js';
42
+
43
+ const props = defineProps({
44
+ /**
45
+ * schema 配置,结构如下:
46
+ * {
47
+ * type: 'object',
48
+ properties: {
49
+ key: {
50
+ ...schema, // 标准 schema 配置
51
+ type: '', // 字段类型
52
+ label: '', // 字段中文名
53
+ // 字段在 search-bar 中的相关配置
54
+ option: {
55
+ ...elComponentConfig, // 标准 el-table-column 配置
56
+ comType: '', // 配置组件类型 input/select/...
57
+ default: '', // 默认值
58
+ },
59
+ },
60
+ ...
61
+ },
62
+ }
63
+ */
64
+ schema: Object
65
+ })
66
+
67
+ const { schema } = toRefs(props);
68
+
69
+ const emit = defineEmits(['load', 'search', 'reset']);
70
+
71
+ const searchComList = ref([]);
72
+
73
+ const getValue = () => {
74
+ let dtoObj = {};
75
+ // 遍历所有子组件,调用其 getValue 方法,获取输入值,组合成最终的 dtoObj
76
+ searchComList.value.forEach(component => {
77
+ dtoObj = {
78
+ ...dtoObj,
79
+ ...component?.getValue()
80
+ }
81
+ });
82
+
83
+ return dtoObj;
84
+ }
85
+
86
+ let childComLoadedCount = 0;
87
+ const handleChildLoaded = () => {
88
+ childComLoadedCount++;
89
+ // 当所有子组件都加载完成后,触发 load 事件,通知父组件
90
+ if (childComLoadedCount >= Object.keys(schema?.value?.properties).length) {
91
+ emit('load', getValue());
92
+ }
93
+ }
94
+
95
+ const search = () => {
96
+ emit('search', getValue());
97
+ }
98
+ const reset = () => {
99
+ searchComList.value.forEach(component => {
100
+ component?.reset();
101
+ });
102
+ emit('reset', getValue());
103
+ }
104
+
105
+ defineExpose({ reset, getValue });
106
+ </script>
107
+
108
+ <style lang="less">
109
+ .schema-search-bar {
110
+ min-width: 500px;
111
+
112
+ .select {
113
+ width: 180px;
114
+ }
115
+
116
+ .dynamic-select {
117
+ width: 180px;
118
+ }
119
+
120
+ .date-range {}
121
+
122
+ .search-btn {
123
+ width: 100px;
124
+ }
125
+ .reset-btn {
126
+ width: 100px;
127
+ }
128
+ }
129
+ </style>
@@ -0,0 +1,27 @@
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
+ // 业务拓展 search-item 配置
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
+
24
+ export default {
25
+ ...SearchItemConfig,
26
+ ...BusinessSearchItemConfig
27
+ };