Initial commit
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,233 @@
|
||||
<template>
|
||||
<el-form
|
||||
ref="form"
|
||||
:label-width="labelWidth"
|
||||
label-position="right"
|
||||
size="medium"
|
||||
:model="formData"
|
||||
inline
|
||||
:rules="rules"
|
||||
:inline-message="false"
|
||||
>
|
||||
<el-form-item
|
||||
v-for="(item, i) in formItems"
|
||||
:key="i"
|
||||
:style="{ width: item.width }"
|
||||
:label="item.label"
|
||||
:prop="item.key"
|
||||
>
|
||||
<div :style="{ width: item.contentWidth || contentWidth }">
|
||||
<el-date-picker
|
||||
v-if="item.type === 'date'"
|
||||
v-model="formData[item.key]"
|
||||
type="date"
|
||||
size="normal"
|
||||
placeholder="请选择日期"
|
||||
></el-date-picker>
|
||||
<el-input-number
|
||||
v-else-if="item.type === 'number'"
|
||||
:style="{ width: item.width || '192px' }"
|
||||
v-model="formData[item.key]"
|
||||
size="small"
|
||||
:min="0"
|
||||
:placeholder="placeholderWidthFormItem(item)"
|
||||
></el-input-number>
|
||||
<el-switch
|
||||
v-else-if="item.type === 'switch'"
|
||||
v-model="formData[item.key]"
|
||||
:disabled="item.disabled"
|
||||
></el-switch>
|
||||
<el-select
|
||||
v-else-if="item.type === 'select'"
|
||||
v-model="formData[item.key]"
|
||||
:disabled="item.disabled"
|
||||
:placeholder="placeholderWidthFormItem(item)"
|
||||
size="small"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="(option, index) in item.options"
|
||||
:key="index"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<base-upload
|
||||
v-else-if="item.type === 'image'"
|
||||
v-model="formData[item.key]"
|
||||
:cover="formData[item.key]"
|
||||
:hide="true"
|
||||
width="100px"
|
||||
height="100px"
|
||||
@successCallback="(res) => {formData[item.key] = res.data.coverImg}"
|
||||
></base-upload>
|
||||
<imgs-upload
|
||||
ref="imgsUpload"
|
||||
v-else-if="item.type === 'images'"
|
||||
v-model="formData[item.key]"
|
||||
:hide="true"
|
||||
width="100px"
|
||||
height="100px"
|
||||
></imgs-upload>
|
||||
<el-input
|
||||
v-else
|
||||
:type="item.type"
|
||||
v-model="formData[item.key]"
|
||||
:placeholder="item.placeholder || placeholderWidthFormItem(item)"
|
||||
clearable
|
||||
size="small"
|
||||
></el-input>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<slot></slot>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import baseUpload from "../baseUpload.vue";
|
||||
import ImgsUpload from "../imgsUpload.vue";
|
||||
|
||||
export default {
|
||||
name: "ConfigForms",
|
||||
components: { baseUpload, ImgsUpload },
|
||||
props: {
|
||||
labelWidth: {
|
||||
type: String,
|
||||
default: "80px"
|
||||
},
|
||||
contentWidth: {
|
||||
type: String,
|
||||
default: "200px"
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Array<FormItem>
|
||||
* FormItem:
|
||||
* - label: string
|
||||
* - key: string | number
|
||||
* - required: bool
|
||||
* - type?: 'select' | 'date' | 'text' | 'textarea' | 'number' | 'tags'
|
||||
* - options?: FormOption[]
|
||||
*
|
||||
*
|
||||
* FormOption:
|
||||
* - label: string
|
||||
* - value: string | number
|
||||
*/
|
||||
formItems: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
formData: {},
|
||||
tagList: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
rules() {
|
||||
const rs = {};
|
||||
this.formItems.forEach((item) => {
|
||||
rs[item.key] = [
|
||||
{
|
||||
required: !!item.required,
|
||||
message: this.placeholderWidthFormItem(item)
|
||||
}
|
||||
];
|
||||
});
|
||||
return rs;
|
||||
},
|
||||
containTags() {
|
||||
return this.formItems.findIndex((v) => v.type === "tags") >= 0;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
formItems: {
|
||||
handler() {
|
||||
this.setFormDataDefault();
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
data: {
|
||||
handler(val, oldVal) {
|
||||
let isSame = false;
|
||||
if (val && oldVal) {
|
||||
isSame = val.id === oldVal.id;
|
||||
}
|
||||
if (this.$refs.imgsUpload && !isSame) {
|
||||
this.$refs.imgsUpload.forEach((el) => el.clearImg());
|
||||
}
|
||||
if (val && Object.keys(val).length) {
|
||||
this.assign(this.formData, val, "entry");
|
||||
} else {
|
||||
Object.keys(this.formData).forEach(
|
||||
(key) => (this.formData[key] = null)
|
||||
);
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
formData: {
|
||||
handler(val) {
|
||||
this.$emit("change", val);
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {},
|
||||
|
||||
methods: {
|
||||
async validate() {
|
||||
await this.$refs.form.validate();
|
||||
const data = {};
|
||||
this.assign(data, this.formData, "output");
|
||||
return data;
|
||||
},
|
||||
assign(target, source, type) {
|
||||
Object.keys(source).forEach((key) => {
|
||||
const itemVal = source[key];
|
||||
const config = this.formItems.find((v) => v.key === key);
|
||||
if (config) {
|
||||
const func = config[type];
|
||||
target[key] = func ? func(itemVal) : itemVal;
|
||||
} else {
|
||||
target[key] = itemVal;
|
||||
}
|
||||
});
|
||||
},
|
||||
placeholderWidthFormItem(item) {
|
||||
const prefix = {
|
||||
select: "请选择",
|
||||
date: "请选择",
|
||||
text: "请输入",
|
||||
number: "请输入",
|
||||
tags: "请选择",
|
||||
switch: "请选择",
|
||||
image: "请上传",
|
||||
images: "请上传"
|
||||
};
|
||||
const cur = prefix[item.type] || "请输入";
|
||||
return cur + item.label;
|
||||
},
|
||||
|
||||
setFormDataDefault() {
|
||||
this.formItems.forEach((v) => {
|
||||
this.$set(this.formData, v.key, null);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
Reference in New Issue
Block a user