编辑性表单
<!-- eslint-disable vue/no-mutating-props -->
<!-- eslint-disable vue/valid-v-for -->
<template>
<van-form
@submit="onSubmit"
validate-first
scroll-to-error
colon
v-bind="$attrs"
>
<template v-for="item in formItemList">
<slot :name="item.slotName" v-if="item.slotName"></slot>
<van-field
v-else
v-model="formData[item.prop]"
:error="false"
:disabled="$attrs.disabled || item.disabled"
:name="item.prop"
:label="item.label"
:type="item.type"
:readonly="item.readonly"
:clickable="item.clickable"
@click="
() => {
!$attrs.disabled &&
!item.disabled &&
item.clickable &&
((item.onClick && item.onClick()) ||
(!item.onClick &&
showPopupPicker(
{
textKey: item.prop,
valueKey: item.valueKey,
dateType: item.dateType,
},
item.columns
)));
}
"
:placeholder="
item.placeholder
? item.placeholder
: `${item.clickable ? '请选择' : '请输入'}${item.label}`
"
:rules="item.rules"
>
<template
#extra
v-if="item.extraText || item.extraIcon || item.clickable"
>
<span v-if="item.extraText">{{ item.extraText }}</span>
<van-icon :name="item.extraIcon || 'arrow'" v-else />
</template>
</van-field>
</template>
<slot name="submitBtn">
<div style="margin: 16px">
<van-button
round
block
type="info"
native-type="button"
@click="onGetForm"
>提交</van-button
>
</div>
</slot>
<van-popup v-model="showPicker" position="bottom">
<van-datetime-picker
v-if="['date'].includes(activePickerInfo.dateType)"
v-model="currentDate"
:type="activePickerInfo.dateType"
title="选择年月日"
@confirm="onDatePickerConfirm"
@cancel="showPicker = false"
/>
<van-picker
v-else
show-toolbar
:columns="columns"
@confirm="onColumnPickerConfirm"
:default-index="selectedIndex"
@cancel="showPicker = false"
/>
</van-popup>
</van-form>
</template>
<script>
import moment from "moment";
export default {
name: "EditForm",
components: {},
props: {
formItemList: {
type: Array,
default: () => [],
},
formData: {
type: Object,
default: () => {},
},
},
data() {
return {
selectedIndex: 0,
showPicker: false,
columns: [],
currentDate: null,
activePickerInfo: {
textKey: "",
valueKey: "",
dateType: "",
},
};
},
computed: {},
watch: {
},
created() {},
methods: {
onSubmit() {
console.log("submit---passed");
console.log("formData:", this.formData);
},
onDatePickerConfirm(value) {
console.log("value", value);
this.formData[this.activePickerInfo.textKey] =
moment(value).format("YYYY-MM-DD");
this.showPicker = false;
},
onColumnPickerConfirm(selectedItem, index) {
console.log(
"onColumnPickerConfirm",
selectedItem,
index,
this.activePickerInfo
);
this.formData[this.activePickerInfo.textKey] = selectedItem?.text;
this.formData[this.activePickerInfo.valueKey] = selectedItem?.value;
this.showPicker = false;
},
showPopupPicker(
activePickerInfo = { textKey: "", valueKey: "", dateType: "" },
columns
) {
console.log("showPopupPicker", activePickerInfo);
this.activePickerInfo.dateType = activePickerInfo?.dateType;
this.activePickerInfo.textKey = activePickerInfo?.textKey;
if (activePickerInfo?.dateType) {
this.showDatePicker(activePickerInfo);
} else {
this.showColumnsPicker(activePickerInfo, columns);
}
},
showDatePicker() {
if (this.formData[this.activePickerInfo.textKey]) {
this.currentDate = new Date(
this.formData[this.activePickerInfo.textKey]
);
}
this.showPicker = true;
},
showColumnsPicker(
activePickerInfo = { textKey: "", valueKey: "" },
columns
) {
console.log("showColumnsPicker", columns);
this.activePickerInfo.dateType = "";
this.activePickerInfo.valueKey = activePickerInfo?.valueKey;
this.columns = columns;
const findIndex = this.columns.findIndex(
(item) => item.value === this.formData[this.activePickerInfo.valueKey]
);
this.selectedIndex = findIndex < 0 ? 0 : findIndex;
this.showPicker = true;
},
onGetForm() {
console.log("onGetForm---form:", this.formData);
localStorage.setItem("formData", JSON.stringify(this.formData));
},
},
};
</script>
<template>
<div>
<EditForm
:formData="formData"
:formItemList="formItemList"
ref="editFormRef"
>
<template #address>
<van-field
v-model="formData.address"
:error="false"
:disabled="false"
name="address"
label="地址"
placeholder="请输入地址"
:rules="[{ required: true, message: '请输入地址' }]"
/>
</template>
<template #addressInfo>
<van-field
v-model="formData.addressInfo"
:error="false"
:disabled="false"
name="addressInfo"
label="详细地址"
placeholder="请输入详细地址"
:rules="[{ required: true, message: '请输入详细地址' }]"
/>
</template>
</EditForm>
</div>
</template>
<script>
import EditForm from "@/components/EditForm.vue";
export default {
name: "App",
components: {
EditForm,
},
data() {
return {
formData: {
address: "",
addressInfo: "",
username: "",
phone: "",
staffsNum: "",
city: "",
income: "",
code: "",
status: "",
},
formItemList: [
{
slotName: "address",
},
{
prop: "username",
label: "联系人姓名",
rules: [{ required: true, message: "请输入联系人姓名" }],
},
{
slotName: "addressInfo",
},
{
prop: "phone",
label: "电话号码",
rules: [
{ required: true, message: "请输入电话号码" },
{ pattern: /^1[34578]\d{9}$/g, message: "请输入正确的电话号码" },
],
},
{
prop: "staffsNum",
label: "员工人数",
type: "digit",
extraText: "人",
rules: [{ required: true, message: "请输入员工人数" }],
},
{
prop: "income",
label: "营业收入",
type: "number",
extraText: "元",
rules: [{ required: true, message: "请输入营业收入" }],
},
{
prop: "city",
valueKey: "cityCode",
label: "城市",
readonly: true,
clickable: true,
showExtra: true,
columns: [
{
text: "杭州",
value: "1",
},
{
text: "宁波",
value: "2",
},
{
text: "温州",
value: "3",
},
],
},
{
prop: "code",
label: "中征码",
readonly: true,
},
{
prop: "startDate",
label: "起始日期",
dateType: "date",
readonly: true,
clickable: true,
},
{
prop: "endDate",
label: "截止日期",
dateType: "date",
readonly: true,
clickable: true,
},
{
prop: "status",
label: "存续状态",
readonly: true,
clickable: true,
showExtra: true,
onClick: () => {
this.onshowStatusPicker();
},
},
],
};
},
created() {
this.formData = JSON.parse(localStorage.getItem("formData")) ?? {};
setTimeout(() => {
this.formData.code = "zh223";
}, 2000);
},
methods: {
async onshowStatusPicker() {
console.log("onshowStatusPicker---start");
setTimeout(() => {
const mockDictColumns = [
{
text: "完成",
value: "1",
},
{
text: "继续",
value: "2",
},
{
text: "开始",
value: "3",
},
];
this.$refs.editFormRef.showPopupPicker(
{ textKey: "status", valueKey: "statusCode" },
mockDictColumns
);
}, 2000);
},
},
};
</script>

