Files
tangguo_admin/src/components/ConfigForms/index.vue
T
rootandClaude Opus 5 d999a5c0e6 Initial commit
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 12:02:35 +08:00

234 lines
5.5 KiB
Vue

<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>