@xujingquan/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 (90) hide show
  1. package/.browserslistrc +3 -0
  2. package/.eslintignore +4 -0
  3. package/.eslintrc +63 -0
  4. package/.husky/commit-msg +1 -0
  5. package/.husky/pre-commit +1 -0
  6. package/.prettierignore +16 -0
  7. package/.prettierrc +10 -0
  8. package/README.md +248 -0
  9. package/app/controller/base.js +41 -0
  10. package/app/controller/project.js +75 -0
  11. package/app/controller/view.js +28 -0
  12. package/app/extend/logger.js +39 -0
  13. package/app/middleware/api-params-verify.js +90 -0
  14. package/app/middleware/api-sign-veriyf.js +47 -0
  15. package/app/middleware/error-handler.js +33 -0
  16. package/app/middleware/project-handler.js +30 -0
  17. package/app/middleware.js +45 -0
  18. package/app/pages/asserts/custom.css +13 -0
  19. package/app/pages/boot.js +56 -0
  20. package/app/pages/common/api/business-api.js +19 -0
  21. package/app/pages/common/api/project-api.js +27 -0
  22. package/app/pages/common/request.js +119 -0
  23. package/app/pages/common/utils.js +2 -0
  24. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +20 -0
  25. package/app/pages/dashboard/complex-view/header-view/header-view.vue +116 -0
  26. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +44 -0
  27. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +37 -0
  28. package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +122 -0
  29. package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
  30. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +86 -0
  31. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +82 -0
  32. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +115 -0
  33. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +135 -0
  34. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +93 -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 +115 -0
  37. package/app/pages/dashboard/dashboard.vue +93 -0
  38. package/app/pages/dashboard/entry.dashboard.js +45 -0
  39. package/app/pages/store/index.js +4 -0
  40. package/app/pages/store/menu.js +61 -0
  41. package/app/pages/store/project.js +17 -0
  42. package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
  43. package/app/pages/widgets/header-container/asserts/logo.png +0 -0
  44. package/app/pages/widgets/header-container/header-container.vue +111 -0
  45. package/app/pages/widgets/schema-form/complex-view/input/input.vue +141 -0
  46. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +142 -0
  47. package/app/pages/widgets/schema-form/complex-view/select/select.vue +119 -0
  48. package/app/pages/widgets/schema-form/form-item-config.js +23 -0
  49. package/app/pages/widgets/schema-form/schema-form.vue +130 -0
  50. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +50 -0
  51. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +62 -0
  52. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +40 -0
  53. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +48 -0
  54. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +121 -0
  55. package/app/pages/widgets/schema-search-bar/search-item-config.js +27 -0
  56. package/app/pages/widgets/schema-table/schema-table.vue +243 -0
  57. package/app/pages/widgets/sider-container/sider-container.vue +26 -0
  58. package/app/public/static/logo.png +0 -0
  59. package/app/public/static/md5.js +950 -0
  60. package/app/public/static/normalize.css +267 -0
  61. package/app/router/project.js +11 -0
  62. package/app/router/view.js +13 -0
  63. package/app/router-schema/project.js +33 -0
  64. package/app/service/base.js +14 -0
  65. package/app/service/project.js +43 -0
  66. package/app/view/entry.tpl +27 -0
  67. package/app/webpack/config/utils.js +49 -0
  68. package/app/webpack/config/webpack-dev.js +55 -0
  69. package/app/webpack/config/webpack-prod.js +192 -0
  70. package/app/webpack/config/webpack.base.js +273 -0
  71. package/app/webpack/dev.js +60 -0
  72. package/app/webpack/libs/blank.js +1 -0
  73. package/app/webpack/prod.js +27 -0
  74. package/babel.config.js +15 -0
  75. package/commitlint.config.js +3 -0
  76. package/config/config.default.js +4 -0
  77. package/elpis-core/env.js +20 -0
  78. package/elpis-core/index.js +86 -0
  79. package/elpis-core/loader/config.js +54 -0
  80. package/elpis-core/loader/controller.js +69 -0
  81. package/elpis-core/loader/extend.js +57 -0
  82. package/elpis-core/loader/middleware.js +66 -0
  83. package/elpis-core/loader/router-schema.js +49 -0
  84. package/elpis-core/loader/router.js +50 -0
  85. package/elpis-core/loader/service.js +69 -0
  86. package/index.js +47 -0
  87. package/jsconfig.json +19 -0
  88. package/model/index.js +103 -0
  89. package/package.json +105 -0
  90. package/test/controller/project.test.js +200 -0
@@ -0,0 +1,119 @@
1
+ <template>
2
+ <el-row type="flex" align="middle" class="form-item">
3
+ <!-- label -->
4
+ <el-row class="item-label" justify="end">
5
+ <el-row v-if="schema?.option?.required" type="flex" class="required">*</el-row>
6
+ {{ schema.label ?? '' }}
7
+ </el-row>
8
+ <!-- value -->
9
+ <el-row class="item-value">
10
+ <el-select
11
+ v-model="dtoValue"
12
+ v-bind="schema.option"
13
+ class="component"
14
+ :class="validTips ? 'valid-border' : ''"
15
+ @change="onChange"
16
+ >
17
+ <el-option
18
+ v-for="item in schema.option?.enumList"
19
+ :key="item.value"
20
+ :label="item.label"
21
+ :value="item.value"
22
+ />
23
+ </el-select>
24
+ </el-row>
25
+ <!-- 错误信息 -->
26
+ <el-row v-if="validTips" class="valid-tips">{{ validTips }}</el-row>
27
+ </el-row>
28
+ </template>
29
+
30
+ <script setup>
31
+ import { ref, toRefs, watch, inject, onMounted } from 'vue';
32
+
33
+ const ajv = inject('ajv');
34
+
35
+ const props = defineProps({
36
+ schemaKey: String,
37
+ schema: Object,
38
+ model: Number || String,
39
+ });
40
+
41
+ const { schemaKey, schema } = props;
42
+ const { model } = toRefs(props);
43
+
44
+ const name = ref('select');
45
+ const dtoValue = ref(undefined);
46
+ const validTips = ref(null);
47
+
48
+ const initData = () => {
49
+ dtoValue.value = model.value ?? schema?.option?.default;
50
+ validTips.value = null;
51
+ };
52
+
53
+ onMounted(() => {
54
+ initData();
55
+ });
56
+
57
+ watch(
58
+ [model, schema],
59
+ () => {
60
+ initData();
61
+ },
62
+ { deep: true }
63
+ );
64
+
65
+ const validate = () => {
66
+ validTips.value = null;
67
+
68
+ // 校验是否必填
69
+ if (schema.option?.required && !dtoValue.value) {
70
+ validTips.value = '不能为空';
71
+ return false;
72
+ }
73
+
74
+ // ajv 校验 schema
75
+ if (dtoValue.value) {
76
+ let dtoEnum = [];
77
+ if (schema.option?.enumList) {
78
+ dtoEnum = schema.option.enumList.map((item) => item.value);
79
+ }
80
+ const validate = ajv.compile({
81
+ schema,
82
+ ...{ enum: dtoEnum },
83
+ });
84
+
85
+ const valid = validate(dtoValue.value);
86
+ if (!valid && validate.errors?.[0]) {
87
+ if (validate.error[0].keyword === 'enum') {
88
+ validTips.value = '取值超出枚举范围';
89
+ } else {
90
+ console.error('不符合要求');
91
+ validTips.value = '不符合要求';
92
+ }
93
+ return false;
94
+ }
95
+ }
96
+
97
+ return true;
98
+ };
99
+
100
+ const getValue = () => {
101
+ return dtoValue.value !== undefined
102
+ ? {
103
+ [schemaKey]: dtoValue.value,
104
+ }
105
+ : {};
106
+ };
107
+
108
+ const onChange = () => {
109
+ validate();
110
+ };
111
+
112
+ defineExpose({
113
+ name,
114
+ validate,
115
+ getValue,
116
+ });
117
+ </script>
118
+
119
+ <style lang="less" scoped></style>
@@ -0,0 +1,23 @@
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 BusinessFormItemConfig from '$businessFormItemConfig';
7
+
8
+ const FormItemConfig = {
9
+ input: {
10
+ component: input,
11
+ },
12
+ inputNumber: {
13
+ component: inputNumber,
14
+ },
15
+ select: {
16
+ component: select,
17
+ },
18
+ };
19
+
20
+ export default {
21
+ ...BusinessFormItemConfig,
22
+ ...FormItemConfig,
23
+ };
@@ -0,0 +1,130 @@
1
+ <template>
2
+ <el-row v-if="schema && schema.properties" class="schema-form">
3
+ <template v-for="(itemSchema, key) in schema.properties">
4
+ <component
5
+ :is="FormItemConfig[itemSchema.option?.comType]?.component"
6
+ v-show="itemSchema.option.visible !== false"
7
+ ref="formComList"
8
+ :schemaKey="key"
9
+ :schema="itemSchema"
10
+ :model="model ? model[key] : undefined"
11
+ />
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';
19
+
20
+ import Ajv from 'ajv';
21
+ const ajv = new Ajv();
22
+ provide('ajv', ajv);
23
+
24
+ const props = defineProps({
25
+ /**
26
+ * schema 配置如下
27
+ * schema: {
28
+ * // 板块数据结构
29
+ * type: 'object',
30
+ * properties: {
31
+ * key: {
32
+ * ...schema, // 标准 schema 配置
33
+ * type: '', //字段类型
34
+ * label: '', // 字段的中文名
35
+ * // 字段在不同动态 component 中的相关配置,前缀对应 componentConfig 中的键值
36
+ * // 如 componentConfig.createForm 这里对应 createFormOption
37
+ * createFormOption: {
38
+ * ...eleComponentConfig, // 标准 el-component-column 配置
39
+ * comType: '', // 控件类型 如 input/select/input-number
40
+ * required: false, // 是否必填,默认false
41
+ * visible: true, // 是否展示 true/false 默认 true
42
+ * disabled: false, // 是否禁用 true/false 默认 fasle
43
+ * default: '', // 默认值
44
+ *
45
+ * // 当 comType === 'select' 时生效
46
+ * enumList: [] // 枚举列表
47
+ * }
48
+ * },
49
+ * ...,
50
+ * },
51
+ * },
52
+ * */
53
+ schema: Object,
54
+ /**
55
+ * 表单数据
56
+ * */
57
+ model: Object,
58
+ });
59
+
60
+ const { schema } = toRefs(props);
61
+
62
+ const formComList = ref([]);
63
+ // 表单校验
64
+ const validate = () => {
65
+ return formComList.value.every((com) => com.validate());
66
+ };
67
+
68
+ // 获取表单项
69
+ const getValue = () => {
70
+ return formComList.value.reduce((dtoObj, component) => {
71
+ return {
72
+ ...dtoObj,
73
+ ...component.getValue(),
74
+ };
75
+ }, {});
76
+ };
77
+
78
+ defineExpose({
79
+ validate,
80
+ getValue,
81
+ });
82
+ </script>
83
+
84
+ <style lang="less">
85
+ .schema-form {
86
+ .form-item {
87
+ min-width: 500px;
88
+ margin-bottom: 20px;
89
+
90
+ .item-label {
91
+ min-width: 70px;
92
+ margin-right: 15px;
93
+ color: #ffffff;
94
+ font-size: 14px;
95
+ text-align: right;
96
+ word-break: break-all;
97
+
98
+ .required {
99
+ top: 2px;
100
+ padding-left: 4px;
101
+ color: #f56c6c;
102
+ font-size: 20px;
103
+ }
104
+ }
105
+
106
+ .item-value {
107
+ .component {
108
+ width: 320px;
109
+ }
110
+
111
+ .valid-border {
112
+ .el-input__wrapper,
113
+ .el-select__wrapper {
114
+ border: 1px solid #f93f3f;
115
+ box-shadow: 0 0 0 0;
116
+ }
117
+ }
118
+ }
119
+
120
+ .valid-tips {
121
+ height: 36px;
122
+ margin-left: 10px;
123
+ overflow: hidden;
124
+ color: #f93f3f;
125
+ font-size: 12px;
126
+ line-height: 36px;
127
+ }
128
+ }
129
+ }
130
+ </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 moment from 'moment';
15
+ import { ref, onMounted } from 'vue';
16
+
17
+ const { schemaKey, schema } = defineProps({
18
+ schemaKey: String,
19
+ schema: Object,
20
+ });
21
+
22
+ const emits = defineEmits(['loaded']);
23
+
24
+ const dtoValue = ref(undefined);
25
+
26
+ const getValue = function () {
27
+ return dtoValue.value.length === 2
28
+ ? {
29
+ [`${schemaKey}_start`]: moment(dtoValue.value[0]).format('YYYY-MM-DD'),
30
+ [`${schemaKey}_end`]: moment(dtoValue.value[1]).format('YYYY-MM-DD'),
31
+ }
32
+ : {};
33
+ };
34
+
35
+ const reset = function () {
36
+ dtoValue.value = [];
37
+ };
38
+
39
+ onMounted(() => {
40
+ reset();
41
+ emits('loaded');
42
+ });
43
+
44
+ defineExpose({
45
+ getValue,
46
+ reset,
47
+ });
48
+ </script>
49
+
50
+ <style lang="less" scoped></style>
@@ -0,0 +1,62 @@
1
+ <template>
2
+ <el-select v-model="dtoValue" v-bind="schema.option" class="dynamic-select">
3
+ <el-option v-for="item in enumList" :key="item.value" :label="item.label" :value="item.value">
4
+ </el-option>
5
+ </el-select>
6
+ </template>
7
+
8
+ <script setup>
9
+ import { ref, onMounted } from 'vue';
10
+ import { tableDataPort } from '$elpisCommon/api/business-api';
11
+
12
+ const { schemaKey, schema } = defineProps({
13
+ schemaKey: String,
14
+ schema: Object,
15
+ });
16
+
17
+ const emits = defineEmits(['loaded']);
18
+
19
+ const dtoValue = ref(undefined);
20
+
21
+ const getValue = function () {
22
+ return dtoValue.value !== 'undefined'
23
+ ? {
24
+ [schemaKey]: dtoValue.value,
25
+ }
26
+ : {};
27
+ };
28
+
29
+ const reset = function () {
30
+ dtoValue.value = schema?.option?.default ?? enumList.value?.[0]?.value;
31
+ };
32
+
33
+ const enumList = ref([]);
34
+ const fetchEnumList = async function () {
35
+ try {
36
+ const req = {
37
+ method: 'get',
38
+ url: schema?.option?.api ?? '',
39
+ data: {},
40
+ };
41
+ const res = await tableDataPort(req);
42
+
43
+ if (res?.data?.length > 0) {
44
+ enumList.value = res?.data;
45
+ }
46
+ } finally {
47
+ }
48
+ };
49
+
50
+ onMounted(async () => {
51
+ await fetchEnumList();
52
+ reset();
53
+ emits('loaded');
54
+ });
55
+
56
+ defineExpose({
57
+ getValue,
58
+ reset,
59
+ });
60
+ </script>
61
+
62
+ <style lang="less" scoped></style>
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <el-input v-model="dtoValue" v-bind="schema.option" class="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 emits = defineEmits(['loaded']);
14
+
15
+ const dtoValue = ref(undefined);
16
+
17
+ const getValue = function () {
18
+ return dtoValue.value !== 'undefined'
19
+ ? {
20
+ [schemaKey]: dtoValue.value,
21
+ }
22
+ : {};
23
+ };
24
+
25
+ const reset = function () {
26
+ dtoValue.value = schema?.option?.default;
27
+ };
28
+
29
+ onMounted(() => {
30
+ reset();
31
+ emits('loaded');
32
+ });
33
+
34
+ defineExpose({
35
+ getValue,
36
+ reset,
37
+ });
38
+ </script>
39
+
40
+ <style lang="less" scoped></style>
@@ -0,0 +1,48 @@
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
+ </el-select>
11
+ </template>
12
+
13
+ <script setup>
14
+ import { ref, onMounted } from 'vue';
15
+
16
+ const { schemaKey, schema } = defineProps({
17
+ schemaKey: String,
18
+ schema: Object,
19
+ });
20
+
21
+ const emits = defineEmits(['loaded']);
22
+
23
+ const dtoValue = ref(undefined);
24
+
25
+ const getValue = function () {
26
+ return dtoValue.value !== 'undefined'
27
+ ? {
28
+ [schemaKey]: dtoValue.value,
29
+ }
30
+ : {};
31
+ };
32
+
33
+ const reset = function () {
34
+ dtoValue.value = schema?.option?.default ?? schema.option?.enumList[0]?.value;
35
+ };
36
+
37
+ onMounted(() => {
38
+ reset();
39
+ emits('loaded');
40
+ });
41
+
42
+ defineExpose({
43
+ getValue,
44
+ reset,
45
+ });
46
+ </script>
47
+
48
+ <style lang="less" scoped></style>
@@ -0,0 +1,121 @@
1
+ <template>
2
+ <el-form v-if="schema?.properties" :inline="true" class="schema-search-bar">
3
+ <!-- 动态组件 -->
4
+ <el-form-item
5
+ v-for="(schemaItem, key) in schema.properties"
6
+ :key="key"
7
+ :label="schemaItem.label"
8
+ >
9
+ <!--展示子组件 -->
10
+ <!-- component 动态组件使用 https://cn.vuejs.org/api/built-in-special-elements.html#component -->
11
+ <!-- schemaItem.option?.comType 是schemaConfig 中的配置 -->
12
+ <!-- component 是 SearchItemConfig 中的key -->
13
+ <component
14
+ :is="SearchItemConfig[schemaItem.option?.comType].component"
15
+ :ref="handleSearchComList"
16
+ :schemaKey="key"
17
+ :schema="schemaItem"
18
+ @loaded="handleChildLoaded"
19
+ />
20
+ </el-form-item>
21
+ <!-- 操作区域 -->
22
+ <el-form-item>
23
+ <el-button type="primary" plain class="search-btn" @click="search">搜索</el-button>
24
+ <el-button plain class="reset-btn" @click="reset">重置</el-button>
25
+ </el-form-item>
26
+ </el-form>
27
+ </template>
28
+
29
+ <script setup>
30
+ import { ref, toRefs } from 'vue';
31
+ import SearchItemConfig from './search-item-config';
32
+
33
+ const props = defineProps({
34
+ /**
35
+ * schema 配置结构如下:
36
+ {
37
+ type: 'object',
38
+ properties: {
39
+ key: {
40
+ ...schema, // 标准 schema 配置
41
+ type: '', //字段类型
42
+ label: '', // 字段的中文名
43
+ // 字段在 table 中的相关配置
44
+ option: {
45
+ ...eleComponentConfig, // 标准 el-component-column 配置
46
+ comType: '', // 配置控件类型 input/select/...
47
+ default: '', // 默认值
48
+ }
49
+ },
50
+ ...,
51
+ }
52
+ }
53
+ */
54
+ schema: Object,
55
+ });
56
+
57
+ const emits = defineEmits(['load', 'search', 'reset']);
58
+
59
+ const { schema } = toRefs(props);
60
+
61
+ const searchComList = ref([]);
62
+ const handleSearchComList = (el) => {
63
+ searchComList.value.push(el);
64
+ };
65
+
66
+ // 所有子组件value
67
+ const getValue = function () {
68
+ let dtoObj = {};
69
+ searchComList.value.forEach((component) => {
70
+ dtoObj = {
71
+ ...dtoObj,
72
+ ...component?.getValue(),
73
+ };
74
+ });
75
+
76
+ return dtoObj;
77
+ };
78
+
79
+ let childComLoadedCount = 0;
80
+ const handleChildLoaded = function () {
81
+ childComLoadedCount++;
82
+ if (childComLoadedCount >= Object.keys(schema?.value?.properties).length) {
83
+ // 加载完成调用,将子组件的 value 返回
84
+ emits('load', getValue());
85
+ }
86
+ };
87
+
88
+ const search = function () {
89
+ emits('search', getValue());
90
+ };
91
+
92
+ const reset = function () {
93
+ searchComList.value.forEach((component) => component?.reset());
94
+ emits('reset');
95
+ };
96
+
97
+ defineExpose({
98
+ reset,
99
+ getValue,
100
+ });
101
+ </script>
102
+
103
+ <style lang="less">
104
+ .schema-search-bar {
105
+ min-width: 500px;
106
+
107
+ .input,
108
+ .select,
109
+ .dynamic-select {
110
+ width: 180px;
111
+ }
112
+
113
+ .search-btn {
114
+ width: 100px;
115
+ }
116
+
117
+ .reset-btn {
118
+ width: 100px;
119
+ }
120
+ }
121
+ </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
+ ...BusinessSearchItemConfig,
26
+ ...SearchItemConfig,
27
+ };