@codertqy/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/.eslintignore +2 -0
- package/.eslintrc +55 -0
- package/README.md +218 -0
- package/app/controller/base.js +40 -0
- package/app/controller/project.js +81 -0
- package/app/controller/view.js +22 -0
- package/app/extend/logger.js +43 -0
- package/app/middleware/api-params-verify.js +73 -0
- package/app/middleware/api-sign-verify.js +49 -0
- package/app/middleware/error-handler.js +31 -0
- package/app/middleware/project-handler.js +26 -0
- package/app/middleware.js +44 -0
- package/app/pages/assets/custom.css +14 -0
- package/app/pages/boot.js +56 -0
- package/app/pages/common/curl.js +84 -0
- package/app/pages/common/index.css +3 -0
- package/app/pages/common/utils.js +1 -0
- package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +19 -0
- package/app/pages/dashboard/complex-view/header-view/header-view.vue +126 -0
- package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +45 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +35 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +120 -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 +87 -0
- package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +100 -0
- package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +122 -0
- package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +161 -0
- package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +95 -0
- package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +19 -0
- package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +135 -0
- package/app/pages/dashboard/dashboard.vue +86 -0
- package/app/pages/dashboard/entry.dashboard.js +48 -0
- package/app/pages/store/index.js +3 -0
- package/app/pages/store/menu.js +68 -0
- package/app/pages/store/project.js +12 -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 +107 -0
- package/app/pages/widgets/schema-form/complex-view/input/input.vue +138 -0
- package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +140 -0
- package/app/pages/widgets/schema-form/complex-view/select/select.vue +122 -0
- package/app/pages/widgets/schema-form/form-item-config.js +20 -0
- package/app/pages/widgets/schema-form/schema-form.vue +135 -0
- package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +51 -0
- package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +63 -0
- package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +41 -0
- package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +49 -0
- package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +126 -0
- package/app/pages/widgets/schema-search-bar/search-item-config.js +22 -0
- package/app/pages/widgets/schema-table/schema-table.vue +259 -0
- package/app/pages/widgets/sider-container/sider-container.vue +27 -0
- package/app/public/output/entry.page1.tpl +40 -0
- package/app/public/output/entry.page2.tpl +11 -0
- package/app/public/static/logo.png +0 -0
- package/app/public/static/normalize.css +239 -0
- package/app/router/project.js +22 -0
- package/app/router/view.js +17 -0
- package/app/router-schema/project.js +34 -0
- package/app/service/base.js +15 -0
- package/app/service/project.js +59 -0
- package/app/view/entry.tpl +25 -0
- package/app/webpack/config/webpack.base.js +280 -0
- package/app/webpack/config/webpack.dev.js +57 -0
- package/app/webpack/config/webpack.prod.js +127 -0
- package/app/webpack/dev.js +63 -0
- package/app/webpack/libs/blank.js +1 -0
- package/app/webpack/prod.js +22 -0
- package/config/config.beta.js +1 -0
- package/config/config.default.js +3 -0
- package/config/config.prod.js +1 -0
- package/elpis-core/env.js +27 -0
- package/elpis-core/index.js +98 -0
- package/elpis-core/loader/config.js +58 -0
- package/elpis-core/loader/controller.js +93 -0
- package/elpis-core/loader/extend.js +63 -0
- package/elpis-core/loader/middleware.js +84 -0
- package/elpis-core/loader/router-schema.js +56 -0
- package/elpis-core/loader/router.js +50 -0
- package/elpis-core/loader/service.js +85 -0
- package/index.js +38 -0
- package/model/index.js +129 -0
- package/package.json +92 -0
- package/test/controller/project.test.js +214 -0
|
@@ -0,0 +1,122 @@
|
|
|
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"
|
|
6
|
+
>*</el-row
|
|
7
|
+
>
|
|
8
|
+
{{ schema.label }}
|
|
9
|
+
</el-row>
|
|
10
|
+
<!-- value -->
|
|
11
|
+
<el-row class="item-value">
|
|
12
|
+
<el-select
|
|
13
|
+
v-model="dtoValue"
|
|
14
|
+
v-bind="schema.option"
|
|
15
|
+
class="component"
|
|
16
|
+
:class="validTips ? 'valid-border' : ''"
|
|
17
|
+
@change="onChange"
|
|
18
|
+
>
|
|
19
|
+
<el-option
|
|
20
|
+
v-for="item in schema.option?.enumList"
|
|
21
|
+
:key="item.value"
|
|
22
|
+
:label="item.label"
|
|
23
|
+
:value="item.value"
|
|
24
|
+
></el-option>
|
|
25
|
+
</el-select>
|
|
26
|
+
</el-row>
|
|
27
|
+
<!-- 错误信息 -->
|
|
28
|
+
<el-row v-if="validTips" class="valid-tips">{{ validTips }}</el-row>
|
|
29
|
+
</el-row>
|
|
30
|
+
</template>
|
|
31
|
+
<script setup>
|
|
32
|
+
import { ref, toRefs, watch, inject, onMounted } from "vue";
|
|
33
|
+
const ajv = inject("ajv");
|
|
34
|
+
|
|
35
|
+
const props = defineProps({
|
|
36
|
+
schemaKey: {
|
|
37
|
+
type: String,
|
|
38
|
+
},
|
|
39
|
+
schema: {
|
|
40
|
+
type: Object,
|
|
41
|
+
},
|
|
42
|
+
model: {
|
|
43
|
+
type: null,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
const { schemaKey, schema } = props;
|
|
47
|
+
const { model } = toRefs(props);
|
|
48
|
+
|
|
49
|
+
const dtoValue = ref();
|
|
50
|
+
const validTips = ref(null);
|
|
51
|
+
const name = ref("select");
|
|
52
|
+
|
|
53
|
+
const initData = () => {
|
|
54
|
+
dtoValue.value = model.value ?? schema.option.default;
|
|
55
|
+
validTips.value = null;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
onMounted(() => {
|
|
59
|
+
initData();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
watch(
|
|
63
|
+
[model, schema],
|
|
64
|
+
() => {
|
|
65
|
+
initData();
|
|
66
|
+
},
|
|
67
|
+
{ deep: true },
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const validate = () => {
|
|
71
|
+
validTips.value = null;
|
|
72
|
+
// const { type } = schema;
|
|
73
|
+
// 校验是否必填
|
|
74
|
+
if (schema.option?.required && !dtoValue.value) {
|
|
75
|
+
validTips.value = "不能为空";
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
// 校验 schema
|
|
79
|
+
if (dtoValue.value) {
|
|
80
|
+
let dtoEnum = [];
|
|
81
|
+
if (schema.option?.enumList) {
|
|
82
|
+
dtoEnum = schema.option?.enumList.map((item) => item.value);
|
|
83
|
+
}
|
|
84
|
+
const validate = ajv.compile({
|
|
85
|
+
schema,
|
|
86
|
+
...{ enum: dtoEnum },
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const valid = validate(dtoValue.value);
|
|
90
|
+
if (!valid && validate.errros && validate.errors[0]) {
|
|
91
|
+
if (validate.errors[0].keyword === "enum") {
|
|
92
|
+
validTips.value = "取值超出枚举范围";
|
|
93
|
+
} else {
|
|
94
|
+
console.log(validate.errors[0]);
|
|
95
|
+
validTips.value = "不符合要求";
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
};
|
|
102
|
+
const getValue = () => {
|
|
103
|
+
return dtoValue.value !== undefined
|
|
104
|
+
? {
|
|
105
|
+
[schemaKey]: dtoValue.value,
|
|
106
|
+
}
|
|
107
|
+
: {};
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// 监听 change
|
|
111
|
+
const onChange = (value) => {
|
|
112
|
+
validate();
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
defineExpose({
|
|
116
|
+
name,
|
|
117
|
+
validate,
|
|
118
|
+
getValue,
|
|
119
|
+
});
|
|
120
|
+
</script>
|
|
121
|
+
|
|
122
|
+
<style scoped lang="less"></style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import input from "./complex-view/input/input.vue";
|
|
2
|
+
import select from "./complex-view/select/select.vue";
|
|
3
|
+
import inputNumber from "./complex-view/input-number/input-number.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 { ...FormItemConfig, ...BusinessFormItemConfig };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-row v-if="schema && schema.properties" class="schema-form">
|
|
3
|
+
<!-- 这里遍历的是 对象,所以key是每一项的键名 -->
|
|
4
|
+
<template v-for="(itemSchema, key) in schema.properties">
|
|
5
|
+
<component
|
|
6
|
+
:is="FormItemConfig[itemSchema.option?.comType]?.component"
|
|
7
|
+
ref="formComList"
|
|
8
|
+
v-show="itemSchema.option.visible !== false"
|
|
9
|
+
:schemaKey="key"
|
|
10
|
+
:schema="itemSchema"
|
|
11
|
+
:model="model ? model[key] : undefined"
|
|
12
|
+
></component>
|
|
13
|
+
</template>
|
|
14
|
+
</el-row>
|
|
15
|
+
</template>
|
|
16
|
+
<script setup>
|
|
17
|
+
import { ref, toRefs, provide } from "vue";
|
|
18
|
+
import FormItemConfig from "./form-item-config";
|
|
19
|
+
|
|
20
|
+
// 校验工具
|
|
21
|
+
const Ajv = require("ajv");
|
|
22
|
+
const ajv = new Ajv();
|
|
23
|
+
provide("ajv", ajv);
|
|
24
|
+
|
|
25
|
+
const props = defineProps({
|
|
26
|
+
/** schema 配置结构如下
|
|
27
|
+
* {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
key: {
|
|
31
|
+
...schema, // 标准 schema 配置
|
|
32
|
+
type: "", // 字段类型
|
|
33
|
+
tabel: "", // 字段的中文名
|
|
34
|
+
option: {
|
|
35
|
+
...elTableColumnConfig, // 标准 el-component-column 配置
|
|
36
|
+
comType: "", // 控件类型 input/select/....
|
|
37
|
+
required: false, // 是否必填(true/false) 默认为 false
|
|
38
|
+
visible: true, // 是否展示(true/false) 默认为 true
|
|
39
|
+
disabled: false, //是否禁用(true/false) 默认为 false
|
|
40
|
+
default: "", //默认值
|
|
41
|
+
enumList: [], //枚举列表
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
*/
|
|
47
|
+
schema: {
|
|
48
|
+
type: Object,
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 表单数据
|
|
53
|
+
*/
|
|
54
|
+
model: {
|
|
55
|
+
type: Object,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
const { schema, model } = toRefs(props);
|
|
59
|
+
|
|
60
|
+
const formComList = ref([]);
|
|
61
|
+
// 表单校验
|
|
62
|
+
const validate = () => {
|
|
63
|
+
// 遍历所有组件,进行校验,有一个为false都是false
|
|
64
|
+
return formComList.value.every((component) => {
|
|
65
|
+
const result = component.validate();
|
|
66
|
+
return result;
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
// 获取表单值
|
|
70
|
+
const getValue = () => {
|
|
71
|
+
return formComList.value.reduce((dtoObj, component) => {
|
|
72
|
+
return { ...dtoObj, ...component.getValue() };
|
|
73
|
+
}, {});
|
|
74
|
+
// let dtoObj = {};
|
|
75
|
+
// // 遍历
|
|
76
|
+
// formComList.value.forEach((component) => {
|
|
77
|
+
// dtoObj = {
|
|
78
|
+
// ...dtoObj,
|
|
79
|
+
// ...component.getValue(),
|
|
80
|
+
// };
|
|
81
|
+
// });
|
|
82
|
+
// return dtoObj;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
defineExpose({
|
|
86
|
+
validate,
|
|
87
|
+
getValue,
|
|
88
|
+
});
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<style lang="less">
|
|
92
|
+
.schema-form {
|
|
93
|
+
.form-item {
|
|
94
|
+
margin-bottom: 20px;
|
|
95
|
+
min-width: 500px;
|
|
96
|
+
.item-label {
|
|
97
|
+
margin-right: 15px;
|
|
98
|
+
min-width: 70px;
|
|
99
|
+
text-align: right;
|
|
100
|
+
font-size: 14px;
|
|
101
|
+
color: #ffffff;
|
|
102
|
+
word-break: break-all;
|
|
103
|
+
.required {
|
|
104
|
+
top: 2px;
|
|
105
|
+
padding-left: 4px;
|
|
106
|
+
color: #f56c6c;
|
|
107
|
+
font-size: 20px;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
.item-value {
|
|
111
|
+
.component {
|
|
112
|
+
width: 320px;
|
|
113
|
+
}
|
|
114
|
+
.valid-border {
|
|
115
|
+
.el-input__warpper {
|
|
116
|
+
border: 1px solid #f93f3f;
|
|
117
|
+
box-shadow: 0 0 0 0;
|
|
118
|
+
}
|
|
119
|
+
.el-select__warpper {
|
|
120
|
+
border: 1px solid #f93f3f;
|
|
121
|
+
box-shadow: 0 0 0 0;
|
|
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,51 @@
|
|
|
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
|
+
<script setup>
|
|
13
|
+
import { ref, onMounted } from "vue";
|
|
14
|
+
import moment from "moment";
|
|
15
|
+
const { schemaKey, schema } = defineProps({
|
|
16
|
+
schemaKey: {
|
|
17
|
+
type: String,
|
|
18
|
+
},
|
|
19
|
+
schema: {
|
|
20
|
+
type: Object,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const emit = defineEmits(["loaded"]);
|
|
25
|
+
|
|
26
|
+
const dtoValue = ref([]);
|
|
27
|
+
const getValue = () => {
|
|
28
|
+
return dtoValue.value?.length === 2
|
|
29
|
+
? {
|
|
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
|
+
|
|
36
|
+
const reset = () => {
|
|
37
|
+
dtoValue.value = [];
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
onMounted(() => {
|
|
41
|
+
reset();
|
|
42
|
+
emit("loaded");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
defineExpose({
|
|
46
|
+
getValue,
|
|
47
|
+
reset,
|
|
48
|
+
});
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<style lang="less" scoped></style>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-select v-model="dtoValue" v-bind="schema.option" class="dynamic-select">
|
|
3
|
+
<el-option
|
|
4
|
+
v-for="item in enumList"
|
|
5
|
+
:key="item.value"
|
|
6
|
+
:label="item.label"
|
|
7
|
+
:value="item.value"
|
|
8
|
+
></el-option>
|
|
9
|
+
</el-select>
|
|
10
|
+
</template>
|
|
11
|
+
<script setup>
|
|
12
|
+
import { ref, onMounted } from "vue";
|
|
13
|
+
import $curl from "$elpisCommon/curl.js";
|
|
14
|
+
const { schemaKey, schema } = defineProps({
|
|
15
|
+
schemaKey: {
|
|
16
|
+
type: String,
|
|
17
|
+
},
|
|
18
|
+
schema: {
|
|
19
|
+
type: Object,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const emit = defineEmits(["loaded"]);
|
|
24
|
+
|
|
25
|
+
const dtoValue = ref();
|
|
26
|
+
const getValue = () => {
|
|
27
|
+
return dtoValue.value !== undefined
|
|
28
|
+
? {
|
|
29
|
+
[schemaKey]: dtoValue.value,
|
|
30
|
+
}
|
|
31
|
+
: {};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const reset = () => {
|
|
35
|
+
// 如果没有值,则给下拉框第一项
|
|
36
|
+
dtoValue.value = schema?.option?.default ?? enumList.value[0].value;
|
|
37
|
+
};
|
|
38
|
+
const enumList = ref([]);
|
|
39
|
+
const fetchEnumList = async () => {
|
|
40
|
+
const res = await $curl({
|
|
41
|
+
method: "get",
|
|
42
|
+
url: schema?.option?.api,
|
|
43
|
+
data: {},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (res?.data?.length > 0) {
|
|
47
|
+
enumList.value.push(...res?.data);
|
|
48
|
+
}
|
|
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></style>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-input v-model="dtoValue" v-bind="schema.option" class="input"></el-input>
|
|
3
|
+
</template>
|
|
4
|
+
<script setup>
|
|
5
|
+
import { ref, onMounted } from "vue";
|
|
6
|
+
|
|
7
|
+
const { schemaKey, schema } = defineProps({
|
|
8
|
+
schemaKey: {
|
|
9
|
+
type: String,
|
|
10
|
+
},
|
|
11
|
+
schema: {
|
|
12
|
+
type: Object,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const emit = defineEmits(["loaded"]);
|
|
17
|
+
const dtoValue = ref();
|
|
18
|
+
const getValue = () => {
|
|
19
|
+
return dtoValue.value !== undefined
|
|
20
|
+
? {
|
|
21
|
+
[schemaKey]: dtoValue.value,
|
|
22
|
+
}
|
|
23
|
+
: {};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
onMounted(() => {
|
|
27
|
+
reset();
|
|
28
|
+
emit("loaded");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const reset = () => {
|
|
32
|
+
dtoValue.value = schema?.option?.default;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
defineExpose({
|
|
36
|
+
getValue,
|
|
37
|
+
reset,
|
|
38
|
+
});
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<style lang="less" scoped></style>
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
></el-option>
|
|
9
|
+
</el-select>
|
|
10
|
+
</template>
|
|
11
|
+
<script setup>
|
|
12
|
+
import { ref, onMounted } from "vue";
|
|
13
|
+
|
|
14
|
+
const { schemaKey, schema } = defineProps({
|
|
15
|
+
schemaKey: {
|
|
16
|
+
type: String,
|
|
17
|
+
},
|
|
18
|
+
schema: {
|
|
19
|
+
type: Object,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const emit = defineEmits(["loaded"]);
|
|
24
|
+
|
|
25
|
+
const dtoValue = ref();
|
|
26
|
+
const getValue = () => {
|
|
27
|
+
return dtoValue.value !== undefined
|
|
28
|
+
? {
|
|
29
|
+
[schemaKey]: dtoValue.value,
|
|
30
|
+
}
|
|
31
|
+
: {};
|
|
32
|
+
};
|
|
33
|
+
onMounted(() => {
|
|
34
|
+
reset();
|
|
35
|
+
emit("loaded");
|
|
36
|
+
});
|
|
37
|
+
const reset = () => {
|
|
38
|
+
// 如果没有值,则给下拉框第一项
|
|
39
|
+
dtoValue.value =
|
|
40
|
+
schema?.option?.default ?? schema?.option?.enumList[0]?.value;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
defineExpose({
|
|
44
|
+
getValue,
|
|
45
|
+
reset,
|
|
46
|
+
});
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<style lang="less" scoped></style>
|
|
@@ -0,0 +1,126 @@
|
|
|
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 type="primary" plain class="search-btn" @click="search">
|
|
25
|
+
搜索
|
|
26
|
+
</el-button>
|
|
27
|
+
<el-button plain class="reset-btn" @click="reset"> 重置 </el-button>
|
|
28
|
+
</el-form-item>
|
|
29
|
+
</el-form>
|
|
30
|
+
</template>
|
|
31
|
+
<script setup>
|
|
32
|
+
import { ref, toRefs } from "vue";
|
|
33
|
+
import SearchItemConfig from "./search-item-config";
|
|
34
|
+
const props = defineProps({
|
|
35
|
+
/**
|
|
36
|
+
schema 配置,结构如下:
|
|
37
|
+
type: "object",
|
|
38
|
+
properties: {
|
|
39
|
+
key: {
|
|
40
|
+
...schema, // 标准 schema 配置
|
|
41
|
+
type: "", // 字段类型
|
|
42
|
+
tabel: "", // 字段的中文名
|
|
43
|
+
// 字段在 table 中的相关配置
|
|
44
|
+
tableOption: {
|
|
45
|
+
...elTableColumnConfig, // 标准 el-table-column 配置
|
|
46
|
+
visiable: true, // 默认为 true (false ,表示不在表单中显示)
|
|
47
|
+
toFixed: 2,
|
|
48
|
+
},
|
|
49
|
+
// 字段在 search-abr 中的相关配置
|
|
50
|
+
searchOption: {
|
|
51
|
+
...elComponentConfig, // 标准 el-component-column 配置 比如组件库中的input、form等
|
|
52
|
+
comType: "", // 配置组件类型 input/select/....
|
|
53
|
+
default: "", // 默认值
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
*/
|
|
58
|
+
schema: {
|
|
59
|
+
type: Object,
|
|
60
|
+
required: true,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
const { schema } = toRefs(props);
|
|
64
|
+
// 因为该组件也需要调用api来获取数据
|
|
65
|
+
const emit = defineEmits(["load", "search", "reset"]);
|
|
66
|
+
|
|
67
|
+
// 保存动态组件中的每个实例对象
|
|
68
|
+
const searchComList = ref([]);
|
|
69
|
+
const getValue = () => {
|
|
70
|
+
let dtoObj = {};
|
|
71
|
+
// 遍历
|
|
72
|
+
searchComList.value.forEach((component) => {
|
|
73
|
+
dtoObj = {
|
|
74
|
+
...dtoObj,
|
|
75
|
+
...component?.getValue(),
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
return dtoObj;
|
|
79
|
+
};
|
|
80
|
+
const search = () => {
|
|
81
|
+
emit("search", getValue());
|
|
82
|
+
};
|
|
83
|
+
const reset = () => {
|
|
84
|
+
// 调用每一个组件中的 reset 方法
|
|
85
|
+
searchComList.value.forEach((component) => {
|
|
86
|
+
component.reset();
|
|
87
|
+
});
|
|
88
|
+
emit("reset");
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 动态子组件中的加载完成之后,才会执行后续
|
|
93
|
+
*/
|
|
94
|
+
let childComLoadedCount = 0;
|
|
95
|
+
const handleChildLoaded = () => {
|
|
96
|
+
childComLoadedCount++;
|
|
97
|
+
if (childComLoadedCount === Object.keys(schema?.value?.properties).length) {
|
|
98
|
+
emit("load", getValue());
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
defineExpose({
|
|
102
|
+
reset,
|
|
103
|
+
getValue,
|
|
104
|
+
});
|
|
105
|
+
</script>
|
|
106
|
+
|
|
107
|
+
<style lang="less">
|
|
108
|
+
.schema-search-bar {
|
|
109
|
+
min-width: 500px;
|
|
110
|
+
.input {
|
|
111
|
+
width: 280px;
|
|
112
|
+
}
|
|
113
|
+
.select {
|
|
114
|
+
width: 180px;
|
|
115
|
+
}
|
|
116
|
+
.dynamic-select {
|
|
117
|
+
width: 180px;
|
|
118
|
+
}
|
|
119
|
+
.search-btn {
|
|
120
|
+
width: 100px;
|
|
121
|
+
}
|
|
122
|
+
.reset-btn {
|
|
123
|
+
width: 100px;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
const SearchItemConfig = {
|
|
9
|
+
input: {
|
|
10
|
+
component: input,
|
|
11
|
+
},
|
|
12
|
+
select: {
|
|
13
|
+
component: select,
|
|
14
|
+
},
|
|
15
|
+
dynamicSelect: {
|
|
16
|
+
component: dynamicSelect,
|
|
17
|
+
},
|
|
18
|
+
dateRange: {
|
|
19
|
+
component: dateRange,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
export default { ...SearchItemConfig, ...BusinessSearchItemConfig };
|