@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.
- package/.browserslistrc +3 -0
- package/.eslintignore +4 -0
- package/.eslintrc +63 -0
- package/.husky/commit-msg +1 -0
- package/.husky/pre-commit +1 -0
- package/.prettierignore +16 -0
- package/.prettierrc +10 -0
- package/README.md +248 -0
- package/app/controller/base.js +41 -0
- package/app/controller/project.js +75 -0
- package/app/controller/view.js +28 -0
- package/app/extend/logger.js +39 -0
- package/app/middleware/api-params-verify.js +90 -0
- package/app/middleware/api-sign-veriyf.js +47 -0
- package/app/middleware/error-handler.js +33 -0
- package/app/middleware/project-handler.js +30 -0
- package/app/middleware.js +45 -0
- package/app/pages/asserts/custom.css +13 -0
- package/app/pages/boot.js +56 -0
- package/app/pages/common/api/business-api.js +19 -0
- package/app/pages/common/api/project-api.js +27 -0
- package/app/pages/common/request.js +119 -0
- package/app/pages/common/utils.js +2 -0
- package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +20 -0
- package/app/pages/dashboard/complex-view/header-view/header-view.vue +116 -0
- package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +44 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +37 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +122 -0
- package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
- package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +86 -0
- package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +82 -0
- package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +115 -0
- package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +135 -0
- package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +93 -0
- package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +21 -0
- package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +115 -0
- package/app/pages/dashboard/dashboard.vue +93 -0
- package/app/pages/dashboard/entry.dashboard.js +45 -0
- package/app/pages/store/index.js +4 -0
- package/app/pages/store/menu.js +61 -0
- package/app/pages/store/project.js +17 -0
- package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
- package/app/pages/widgets/header-container/asserts/logo.png +0 -0
- package/app/pages/widgets/header-container/header-container.vue +111 -0
- package/app/pages/widgets/schema-form/complex-view/input/input.vue +141 -0
- package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +142 -0
- package/app/pages/widgets/schema-form/complex-view/select/select.vue +119 -0
- package/app/pages/widgets/schema-form/form-item-config.js +23 -0
- package/app/pages/widgets/schema-form/schema-form.vue +130 -0
- package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +50 -0
- package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +62 -0
- package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +40 -0
- package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +48 -0
- package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +121 -0
- package/app/pages/widgets/schema-search-bar/search-item-config.js +27 -0
- package/app/pages/widgets/schema-table/schema-table.vue +243 -0
- package/app/pages/widgets/sider-container/sider-container.vue +26 -0
- package/app/public/static/logo.png +0 -0
- package/app/public/static/md5.js +950 -0
- package/app/public/static/normalize.css +267 -0
- package/app/router/project.js +11 -0
- package/app/router/view.js +13 -0
- package/app/router-schema/project.js +33 -0
- package/app/service/base.js +14 -0
- package/app/service/project.js +43 -0
- package/app/view/entry.tpl +27 -0
- package/app/webpack/config/utils.js +49 -0
- package/app/webpack/config/webpack-dev.js +55 -0
- package/app/webpack/config/webpack-prod.js +192 -0
- package/app/webpack/config/webpack.base.js +273 -0
- package/app/webpack/dev.js +60 -0
- package/app/webpack/libs/blank.js +1 -0
- package/app/webpack/prod.js +27 -0
- package/babel.config.js +15 -0
- package/commitlint.config.js +3 -0
- package/config/config.default.js +4 -0
- package/elpis-core/env.js +20 -0
- package/elpis-core/index.js +86 -0
- package/elpis-core/loader/config.js +54 -0
- package/elpis-core/loader/controller.js +69 -0
- package/elpis-core/loader/extend.js +57 -0
- package/elpis-core/loader/middleware.js +66 -0
- package/elpis-core/loader/router-schema.js +49 -0
- package/elpis-core/loader/router.js +50 -0
- package/elpis-core/loader/service.js +69 -0
- package/index.js +47 -0
- package/jsconfig.json +19 -0
- package/model/index.js +103 -0
- package/package.json +105 -0
- 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
|
+
};
|