@mangjuxiong/elpis 1.0.2

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/.babelrc +5 -0
  2. package/.eslintignore +3 -0
  3. package/.eslintrc +66 -0
  4. package/README.md +214 -0
  5. package/app/controller/base.js +39 -0
  6. package/app/controller/project.js +75 -0
  7. package/app/controller/view.js +19 -0
  8. package/app/extend/database.js +5 -0
  9. package/app/extend/logger.js +38 -0
  10. package/app/middleware/api-params-verify.js +74 -0
  11. package/app/middleware/api-sign-verify.js +36 -0
  12. package/app/middleware/error-handle.js +32 -0
  13. package/app/middleware/project-handler.js +26 -0
  14. package/app/middleware.js +39 -0
  15. package/app/pages/asserts/custom.css +14 -0
  16. package/app/pages/boot.js +48 -0
  17. package/app/pages/common/curl.js +80 -0
  18. package/app/pages/common/utils.js +34 -0
  19. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +24 -0
  20. package/app/pages/dashboard/complex-view/header-view/head-view.vue +113 -0
  21. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +43 -0
  22. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +35 -0
  23. package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +118 -0
  24. package/app/pages/dashboard/complex-view/schema-view/components/components-config.js +23 -0
  25. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +85 -0
  26. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +103 -0
  27. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +112 -0
  28. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +124 -0
  29. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +90 -0
  30. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +22 -0
  31. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +113 -0
  32. package/app/pages/dashboard/dashboard.vue +85 -0
  33. package/app/pages/dashboard/entry.dashboard.js +46 -0
  34. package/app/pages/store/index.js +4 -0
  35. package/app/pages/store/menu.js +54 -0
  36. package/app/pages/store/project.js +13 -0
  37. package/app/pages/widgets/head-container/asserts/logo.png +0 -0
  38. package/app/pages/widgets/head-container/head-container.vue +77 -0
  39. package/app/pages/widgets/schema-form/complex-view/input/input.vue +134 -0
  40. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +135 -0
  41. package/app/pages/widgets/schema-form/complex-view/select/select.vue +120 -0
  42. package/app/pages/widgets/schema-form/form-item-config.js +23 -0
  43. package/app/pages/widgets/schema-form/schema-form.vue +130 -0
  44. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +51 -0
  45. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +55 -0
  46. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +38 -0
  47. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +40 -0
  48. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +100 -0
  49. package/app/pages/widgets/schema-search-bar/search-item-config.js +31 -0
  50. package/app/pages/widgets/schema-table/schema-table.vue +225 -0
  51. package/app/pages/widgets/sider-container/sider-container.vue +27 -0
  52. package/app/public/output/entry.page1.tpl +42 -0
  53. package/app/public/static/logo.jpg +0 -0
  54. package/app/public/static/normalize.css +267 -0
  55. package/app/router/project.js +6 -0
  56. package/app/router/view.js +7 -0
  57. package/app/router-schema/project.js +30 -0
  58. package/app/service/base.js +13 -0
  59. package/app/service/project.js +42 -0
  60. package/app/view/entry.tpl +25 -0
  61. package/app/webpack/config/babel.config.js +4 -0
  62. package/app/webpack/config/webpack.base.js +229 -0
  63. package/app/webpack/config/webpack.dev.js +57 -0
  64. package/app/webpack/config/webpack.prod.js +120 -0
  65. package/app/webpack/libs/blank.js +1 -0
  66. package/app/webpack/libs/dev.js +53 -0
  67. package/app/webpack/libs/prod.js +22 -0
  68. package/config/config.default.js +4 -0
  69. package/elpis-core/env.js +20 -0
  70. package/elpis-core/index.js +81 -0
  71. package/elpis-core/loader/config.js +52 -0
  72. package/elpis-core/loader/controller.js +59 -0
  73. package/elpis-core/loader/extend.js +47 -0
  74. package/elpis-core/loader/middleware.js +57 -0
  75. package/elpis-core/loader/router-schema.js +41 -0
  76. package/elpis-core/loader/router.js +42 -0
  77. package/elpis-core/loader/service.js +59 -0
  78. package/index.js +39 -0
  79. package/model/index.js +107 -0
  80. package/package.json +90 -0
  81. package/test/controller/project.test.js +194 -0
@@ -0,0 +1,54 @@
1
+ import { defineStore } from 'pinia';
2
+ import { ref } from 'vue';
3
+
4
+ export const useMenuStore = defineStore('menu', () => {
5
+ // 菜单列表
6
+ const menuList = ref([]);
7
+ // 设置菜单列表
8
+ const setMenuList = (newMenuList) => {
9
+ menuList.value = newMenuList;
10
+ };
11
+
12
+ /**
13
+ * 找出菜单目录
14
+ * @param key 搜索字段
15
+ * @param value 搜索值
16
+ * @param mList 要搜索的菜单列表
17
+ * @returns
18
+ */
19
+ const findMenuItem = ({ key, value }, mList = menuList.value) => {
20
+ for (let i = 0; i < mList.length; i++) {
21
+ const menuItem = mList[i];
22
+
23
+ if (!menuItem) return;
24
+
25
+ const { menuType, moduleType } = menuItem;
26
+ if (menuItem[key] === value) {
27
+ return menuItem;
28
+ }
29
+ if (menuType === 'group' && menuItem.subMenu) {
30
+ const mItem = findMenuItem({ key, value }, menuItem.subMenu);
31
+ if (mItem) return mItem;
32
+ }
33
+ if (moduleType === 'sider' && menuItem.siderConfig && menuItem.siderConfig.menu) {
34
+ const mItem = findMenuItem({ key, value }, menuItem.siderConfig.menu);
35
+ if (mItem) return mItem;
36
+ }
37
+ }
38
+ };
39
+
40
+ /**
41
+ * 找出第一个菜单
42
+ * @param {菜单列表} mList
43
+ */
44
+ const findFirstMenuItem = (mList = menuList.value) => {
45
+ if (!mList || !mList[0]) return;
46
+ let firstMenuItem = mList[0];
47
+ if (firstMenuItem.subMenu) {
48
+ firstMenuItem = findFirstMenuItem(firstMenuItem.subMenu);
49
+ }
50
+ return firstMenuItem;
51
+ };
52
+
53
+ return { menuList, setMenuList, findMenuItem, findFirstMenuItem };
54
+ });
@@ -0,0 +1,13 @@
1
+ import { defineStore } from "pinia";
2
+ import { ref } from 'vue';
3
+
4
+ export const useProjectStore = defineStore('project', () => {
5
+ // 项目列表
6
+ const projectList = ref([]);
7
+ // 设置项目列表
8
+ const setProjectList = (newProjectList)=>{
9
+ projectList.value = newProjectList;
10
+ };
11
+
12
+ return { projectList,setProjectList };
13
+ });
@@ -0,0 +1,77 @@
1
+ <template>
2
+ <el-container class="header-container">
3
+ <el-header class="header">
4
+ <el-row type="flex" align="middle" class="header-row">
5
+ <!-- 左上方title -->
6
+ <el-row type="flex" align="middle" class="title-panel">
7
+ <img src="./asserts/logo.png" class="logo" />
8
+ <el-row class="text">
9
+ {{ title }}
10
+ </el-row>
11
+ </el-row>
12
+ <!-- 插槽:菜单区域 -->
13
+ <slot name="menu-content" />
14
+ <!-- 右上方区域 -->
15
+ <el-row type="flex" align="middle" justify="end" class="setting-panel">
16
+ <!-- 插槽:设置区域 -->
17
+ <slot name="setting-content" />
18
+ <component v-if="BussinessHeaderConfig?.userPanel" :is="BussinessHeaderConfig?.userPanel.component" />
19
+ </el-row>
20
+ </el-row>
21
+ </el-header>
22
+ <el-main class="main-container">
23
+ <!-- 外部拓展填充区域 -->
24
+ <slot name="main-content" />
25
+ </el-main>
26
+ </el-container>
27
+ </template>
28
+
29
+ <script setup>
30
+ import BussinessHeaderConfig from '@bussinessHeaderConfig';
31
+
32
+ defineProps({
33
+ title: {
34
+ type: String,
35
+ default: 'elpis',
36
+ },
37
+ });
38
+ </script>
39
+
40
+ <style lang="less" scoped>
41
+ .header-container {
42
+ height: 100%;
43
+ min-width: 1000px;
44
+ overflow: hidden;
45
+ .header {
46
+ max-height: 120px;
47
+ border-bottom: 1px solid #ebeef5;
48
+ .header-row {
49
+ height: 60px;
50
+ padding: 0 20px;
51
+ .title-panel {
52
+ width: 180px;
53
+ .logo {
54
+ margin-right: 10px;
55
+ width: 25px;
56
+ border-radius: 50%;
57
+ }
58
+ .text {
59
+ font-size: 16px;
60
+ line-height: 60px;
61
+ font-weight: 800;
62
+ }
63
+ }
64
+ .setting-panel {
65
+ margin-left: auto;
66
+ min-width: 180px;
67
+ }
68
+ }
69
+ }
70
+ .main-container {
71
+ }
72
+ }
73
+
74
+ :deep(.el-header) {
75
+ padding: 0;
76
+ }
77
+ </style>
@@ -0,0 +1,134 @@
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.options?.required" type="flex" class="required">*</el-row>
6
+ {{ schema.label }}
7
+ </el-row>
8
+ <!-- value -->
9
+ <el-row class="item-value">
10
+ <el-input
11
+ v-model="dtoValue"
12
+ v-bind="schema.options"
13
+ class="component"
14
+ :class="validTips ? 'valid-boder' : ''"
15
+ :placeholder="placeholder"
16
+ @focus="onFocus"
17
+ @blur="onBlur"
18
+ />
19
+ </el-row>
20
+ <!-- 错误信息 -->
21
+ <el-row v-if="validTips" class="valid-tips">
22
+ {{ validTips }}
23
+ </el-row>
24
+ </el-row>
25
+ </template>
26
+
27
+ <script setup>
28
+ import { ref, toRefs, watch, inject, onMounted } from 'vue';
29
+ const ajv = inject('ajv');
30
+
31
+ const props = defineProps({
32
+ schemaKey: String,
33
+ schema: Object,
34
+ model: String,
35
+ });
36
+ const { schemaKey, schema } = props;
37
+ const { model } = toRefs(props);
38
+
39
+ const name = ref('input');
40
+ const dtoValue = ref();
41
+ const validTips = ref('');
42
+ const placeholder = ref('');
43
+
44
+ const initData = () => {
45
+ dtoValue.value = model.value ?? schema.options?.default;
46
+ validTips.value = '';
47
+
48
+ const { minLength, maxLength, pattern } = schema;
49
+
50
+ const ruleList = [];
51
+ if (schema.options?.placeholder) {
52
+ ruleList.push(schema.options.placeholder);
53
+ }
54
+ if (minLength) {
55
+ ruleList.push(`最小长度为:${minLength}`);
56
+ }
57
+ if (maxLength) {
58
+ ruleList.push(`最大长度为:${maxLength}`);
59
+ }
60
+ if (pattern) {
61
+ ruleList.push(`格式为:${pattern}`);
62
+ }
63
+
64
+ placeholder.value = ruleList.join(' | ');
65
+ };
66
+
67
+ onMounted(() => {
68
+ initData();
69
+ });
70
+
71
+ watch(
72
+ [model, schema],
73
+ () => {
74
+ initData();
75
+ },
76
+ { deep: true }
77
+ );
78
+
79
+ const validate = () => {
80
+ validTips.value = '';
81
+ const { type } = schema;
82
+
83
+ // 检验是否必填
84
+ if (schema.options?.required && !dtoValue.value) {
85
+ validTips.value = '不能为空';
86
+ return false;
87
+ }
88
+ // ajv校验schema
89
+ if (dtoValue.value) {
90
+ const validate = ajv.compile(schema);
91
+ const valid = validate(dtoValue.value);
92
+ if (!valid && validate.errors && validate.errors[0]) {
93
+ const { keyword, params } = validate.errors[0];
94
+ if (keyword === 'type') {
95
+ validTips.value = `类型必须为 ${type}`;
96
+ } else if (keyword === 'maxLength') {
97
+ validTips.value = `最大长度应为 ${params.limit}`;
98
+ } else if (keyword === 'minLength') {
99
+ validTips.value = `最小长度应为 ${params.limit}`;
100
+ } else if (keyword === 'pattern') {
101
+ validTips.value = '格式不正确';
102
+ } else {
103
+ console.log(validate.errors[0]);
104
+ validTips.value = '不符合要求';
105
+ }
106
+ return false;
107
+ }
108
+ }
109
+ return true;
110
+ };
111
+ const getValue = () => {
112
+ return dtoValue.value !== undefined
113
+ ? {
114
+ [schemaKey]: dtoValue.value,
115
+ }
116
+ : {};
117
+ };
118
+
119
+ const onFocus = () => {
120
+ validTips.value = '';
121
+ };
122
+
123
+ const onBlur = () => {
124
+ validate();
125
+ };
126
+
127
+ defineExpose({
128
+ validate,
129
+ getValue,
130
+ name,
131
+ });
132
+ </script>
133
+
134
+ <style lang="less" scpoed></style>
@@ -0,0 +1,135 @@
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.options?.required" type="flex" class="required">*</el-row>
6
+ {{ schema.label }}
7
+ </el-row>
8
+ <!-- value -->
9
+ <el-row class="item-value">
10
+ <el-input-number
11
+ v-model="dtoValue"
12
+ v-bind="schema.options"
13
+ class="component"
14
+ :class="validTips ? 'valid-boder' : ''"
15
+ :placeholder="placeholder"
16
+ :controls="false"
17
+ @focus="onFocus"
18
+ @blur="onBlur"
19
+ />
20
+ </el-row>
21
+ <!-- 错误信息 -->
22
+ <el-row v-if="validTips" class="valid-tips">
23
+ {{ validTips }}
24
+ </el-row>
25
+ </el-row>
26
+ </template>
27
+
28
+ <script setup>
29
+ import { ref, toRefs, watch, inject, onMounted } from 'vue';
30
+ const ajv = inject('ajv');
31
+
32
+ const props = defineProps({
33
+ schemaKey: String,
34
+ schema: Object,
35
+ model: Number,
36
+ });
37
+ const { schemaKey, schema } = props;
38
+ const { model } = toRefs(props);
39
+
40
+ const name = ref('input-number');
41
+ const dtoValue = ref();
42
+ const validTips = ref('');
43
+ const placeholder = ref('');
44
+
45
+ const initData = () => {
46
+ dtoValue.value = model.value ?? schema.options?.default;
47
+ validTips.value = '';
48
+
49
+ const { minimum, maximum } = schema;
50
+
51
+ const ruleList = [];
52
+
53
+ if (schema.options?.placeholder) {
54
+ ruleList.push(schema.options.placeholder);
55
+ }
56
+ if (minimum !== undefined) {
57
+ ruleList.push(`最小值:${minimum}`);
58
+ }
59
+ if (maximum !== undefined) {
60
+ ruleList.push(`最大值:${maximum}`);
61
+ }
62
+
63
+ placeholder.value = ruleList.join(' | ');
64
+ };
65
+
66
+ onMounted(() => {
67
+ initData();
68
+ });
69
+
70
+ watch(
71
+ [model, schema],
72
+ () => {
73
+ initData();
74
+ },
75
+ { deep: true }
76
+ );
77
+
78
+ const validate = () => {
79
+ validTips.value = '';
80
+ const { type } = schema;
81
+
82
+ // 检验是否必填
83
+ if (schema.options?.required && !dtoValue.value) {
84
+ validTips.value = '不能为空';
85
+ return false;
86
+ }
87
+ // ajv校验schema
88
+ if (dtoValue.value) {
89
+ const validate = ajv.compile(schema);
90
+ const valid = validate(dtoValue.value);
91
+ if (!valid && validate.errors && validate.errors[0]) {
92
+ const { keyword, params } = validate.errors[0];
93
+ if (keyword === 'type') {
94
+ validTips.value = `类型必须为 ${type}`;
95
+ } else if (keyword === 'minimum') {
96
+ validTips.value = `最小值应为${params.limit}`;
97
+ } else if (keyword === 'maximum') {
98
+ validTips.value = `最大值应为:${params.limit}`;
99
+ } else {
100
+ console.log(validate.errors[0]);
101
+ validTips.value = '不符合要求';
102
+ }
103
+ return false;
104
+ }
105
+ }
106
+ return true;
107
+ };
108
+ const getValue = () => {
109
+ return dtoValue.value !== undefined
110
+ ? {
111
+ [schemaKey]: dtoValue.value,
112
+ }
113
+ : {};
114
+ };
115
+
116
+ const onFocus = () => {
117
+ validTips.value = '';
118
+ };
119
+
120
+ const onBlur = () => {
121
+ validate();
122
+ };
123
+
124
+ defineExpose({
125
+ validate,
126
+ getValue,
127
+ name,
128
+ });
129
+ </script>
130
+
131
+ <style lang="less" scoped>
132
+ :deep(.el-input-number .el-input__inner) {
133
+ text-align: left !important;
134
+ }
135
+ </style>
@@ -0,0 +1,120 @@
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.options?.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.options"
13
+ class="component"
14
+ :class="validTips ? 'valid-boder' : ''"
15
+ @change="onChange"
16
+ >
17
+ <el-option
18
+ v-for="item in schema.options?.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">
27
+ {{ validTips }}
28
+ </el-row>
29
+ </el-row>
30
+ </template>
31
+
32
+ <script setup>
33
+ import { ref, toRefs, watch, inject, onMounted } from 'vue';
34
+ const ajv = inject('ajv');
35
+
36
+ const props = defineProps({
37
+ schemaKey: String,
38
+ schema: Object,
39
+ model: [String, Number],
40
+ });
41
+ const { schemaKey, schema } = props;
42
+ const { model } = toRefs(props);
43
+
44
+ const name = ref('select');
45
+ const dtoValue = ref();
46
+ const validTips = ref('');
47
+
48
+ const initData = () => {
49
+ dtoValue.value = model.value ?? schema.options?.default;
50
+ validTips.value = '';
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 = '';
67
+
68
+ // 检验是否必填
69
+ if (schema.options?.required && !dtoValue.value) {
70
+ validTips.value = '不能为空';
71
+ return false;
72
+ }
73
+ // ajv校验schema
74
+ if (dtoValue.value) {
75
+ let dtoEnum = [];
76
+ if (schema.options?.enumList) {
77
+ dtoEnum = schema.options.enumList.map((item) => item.value);
78
+ }
79
+ const validate = ajv.compile({
80
+ schema,
81
+ ...{ enum: dtoEnum },
82
+ });
83
+
84
+ const valid = validate(dtoValue.value);
85
+ if (!valid && validate.errors && validate.errors[0]) {
86
+ if (validate.errors[0].keyword === 'enum') {
87
+ validTips.value = '取值超出枚举范围';
88
+ } else {
89
+ console.log(validate.errors[0]);
90
+ validTips.value = '不符合要求';
91
+ }
92
+ return false;
93
+ }
94
+ }
95
+ return true;
96
+ };
97
+ const getValue = () => {
98
+ return dtoValue.value !== undefined
99
+ ? {
100
+ [schemaKey]: dtoValue.value,
101
+ }
102
+ : {};
103
+ };
104
+
105
+ const onChange = () => {
106
+ validate();
107
+ };
108
+
109
+ defineExpose({
110
+ validate,
111
+ getValue,
112
+ name,
113
+ });
114
+ </script>
115
+
116
+ <style lang="less" scpoed>
117
+ :deep(.el-input-number .el-input__inner) {
118
+ text-align: 'left';
119
+ }
120
+ </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
+ ...FormItemConfig,
22
+ ...BusinessFormItemConfig,
23
+ };
@@ -0,0 +1,130 @@
1
+ <template>
2
+ <el-row
3
+ v-if="schema && schema.properties"
4
+ class="schema-form"
5
+ >
6
+ <template v-for="(itemSchema, key) in schema.properties">
7
+ <component
8
+ :is="FormItemConfig[itemSchema.options?.comType]?.component"
9
+ v-show="itemSchema.options.visible !== false"
10
+ ref="formComList"
11
+ :schema-key="key"
12
+ :schema="itemSchema"
13
+ :model="model ? model[key] : undefined"
14
+ />
15
+ </template>
16
+ </el-row>
17
+ </template>
18
+
19
+ <script setup>
20
+ import { toRefs, provide, ref } from 'vue';
21
+ import FormItemConfig from './form-item-config';
22
+
23
+ const Ajv = require('ajv');
24
+ const ajv = new Ajv();
25
+ provide('ajv', ajv);
26
+
27
+ // 属性
28
+ const props = defineProps({
29
+ /**
30
+ * schema配置
31
+ * { // 板块数据结构
32
+ type:'object',
33
+ properties:{
34
+ key:{
35
+ ...schema,// 标准的shema配置
36
+ type:'',// 字段类型
37
+ label:'',// 字段的中文名
38
+ // 字段在 createForm 中相关配置
39
+ options: {
40
+ ...eleComponentConfig,// 标准的el-component配置
41
+ comType: '', // 空间类型 input/select/input-number
42
+ visible: true, // 是否展示(true/flase), 默认为true
43
+ disable: false, // 是否禁用
44
+ default: '', // 默认值
45
+ required: false, // 表单项是否必填,默认为false
46
+
47
+ // comType === 'select' 时生效
48
+ enumList: [], // 枚举列表
49
+ }
50
+ },
51
+ ...
52
+ },
53
+ }
54
+ */
55
+ schema: Object,
56
+
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((component) => component.validate());
69
+ };
70
+ // 获取表单值
71
+ const getValue = () => {
72
+ return formComList.value.reduce((dtoObj, component) => {
73
+ return {
74
+ ...dtoObj,
75
+ ...component.getValue(),
76
+ };
77
+ }, {});
78
+ };
79
+
80
+ defineExpose({
81
+ validate,
82
+ getValue,
83
+ });
84
+ </script>
85
+
86
+ <style lang="less">
87
+ .schema-form {
88
+ .form-item {
89
+ margin-bottom: 20px;
90
+ min-width: 500px;
91
+ .item-label {
92
+ margin-right: 15px;
93
+ min-width: 70px;
94
+ text-align: right;
95
+ font-size: 14px;
96
+ color: #ffffff;
97
+ word-break: break-all;
98
+ .required {
99
+ top: 2px;
100
+ padding-left: 4px;
101
+ color: #f56c6c;
102
+ font-size: 20px;
103
+ }
104
+ }
105
+ .item-value {
106
+ .component {
107
+ width: 320px;
108
+ }
109
+ .valid-boder {
110
+ .el-input__wrapper {
111
+ border: 1px solid #f93f3f;
112
+ box-shadow: 0 0 0 0;
113
+ }
114
+ .el-select__wrapper {
115
+ border: 1px solid #f93f3f;
116
+ box-shadow: 0 0 0 0;
117
+ }
118
+ }
119
+ }
120
+ .valid-tips {
121
+ margin-left: 10px;
122
+ height: 36px;
123
+ line-height: 36px;
124
+ overflow: hidden;
125
+ font-size: 12px;
126
+ color: #f93f3f;
127
+ }
128
+ }
129
+ }
130
+ </style>