The form enclosed
Because of the versatility of the form, a UView-based form is encapsulated, because the backend needs to save one for every edit and expose the userLeave event in it. Currently there are only a few common components, and common extensions can be added later
ComForm/index.vue
<template>
<view class="com-form">
<u-form
v-if="formRest"
:model="formData"
ref="uForm"
label-width="140"
>
<u-form-item
v-for="(item, key) in formDesc"
:key="key"
:label="['rate', 'PropertyType'].includes(item.type) ? '' : item.label"
:label-style="item.labelStyle"
>
<! -- input -->
<u-input @blur="onUserLeave({item, value: formData[key]})" :clearable="false" v-if="item.type === 'input'" v-model="formData[key]" :input-align="item.attr.inputAlign" :placeholder="item.attr.placeholder" />
<! -- select -->
<template v-if="item.type === 'select'">
<u-input
type="select"
:value="formData[key]"
@click="item.show = true"
:placeholder="item.attr.placeholder"
:input-align="item.attr.inputAlign"
/>
<u-select
v-model="item.show"
:mode="item.mode"
:list="item.options"
:label-name="item.attr.labelName"
:value-name="item.attr.valueName"
@confirm="e => select(e, key, item)"
/>
</template>
<! -- houseType -->
<u-input
v-if="item.type === 'houseType'"
:value="formData[key]"
type="select"
@click="houseSelectOpen(key, item)"
:placeholder="item.attr.placeholder"
:input-align="item.attr.inputAlign"
/>
<! -- region -->
<template v-if="item.type === 'region'">
<u-input
:value="formData[key] && (formData[key].province.label + formData[key].city.label + formData[key].area.label)"
type="select"
@click="regionShow = true"
:placeholder="item.attr.placeholder"
:input-align="item.attr.inputAlign"
/>
<u-picker
mode="region"
v-model="regionShow"
:default-region="formData[key] && [formData[key].province.label, formData[key].city.label, formData[key].area.label]"
@confirm="e => regionChange(e, key, item)"
/>
</template>
<! -- rate -->
<rate
v-if="item.type === 'rate'"
:label="item.label"
:init-data="formData[key]"
@change="e => rateChange(e, key, item)"
/>
<! -- Tags -->
<tags
v-if="item.type === 'PropertyType'"
v-model="formData[key]"
@tagChange="onUserLeave({item, value: formData[key]})"
:label="item.label"
:custom="item.allowCustom"
/>
</u-form-item>
</u-form>
<house-select ref="houseSelect" :seleData="houseListData" label="House Type Selection" @change="numSeleChange" />
</view>
</template>
<script>
import HouseSelect from '@/components/houseType/compoundNumSele'
import Rate from './components/Rate'
import Tags from './components/Tags'
export default {
name: 'ComForm'.components: {
HouseSelect,
Rate,
Tags
},
model: {
prop: 'formData'.event: 'input'
},
props: {
// Form description
formDesc: {
type: Object.required: true
},
// Form data
formData: {
type: Object.required: true
}
},
data () {
return {
defaultRegion: ['Jiangxi'.'Nanchang'.'West Lake District'].regionShow: false.formRest: true.houseListData: [{label: "Number of bedrooms".key: "Field name".value: "Selected value".unit: "Room".custom: false.// Whether the current value is custom
customValue:' '.// A custom value
data: [{label: "1".value: "1".cheched: false },
{ label: "2".value: "2".cheched: false },
{ label: "3".value: "3".cheched: false}]}, {label: "Number of living rooms and restaurants".key: "Field name".value: "Selected value".unit: "Hall".custom: false.// Whether the current value is custom
customValue:' '.// A custom value
data: [{label: "0".value: "0".cheched: false },
{ label: "1".value: "1".cheched: false },
{ label: "2".value: "2".cheched: false}]}, {label: "Number of toilets".key: "Field name".value: "Selected value".unit: "Who".custom: false.// Whether the current value is custom
customValue:' '.// A custom value
data: [{label: "0".value: "0".cheched: false },
{ label: "1".value: "1".cheched: false },
{ label: "2".value: "2".cheched: false}]}]}},methods: {
getValue(field) {
return this.formData[field]
},
houseSelectOpen (key, item) {
this.$refs.houseSelect.open(key, item)
},
onUserLeave(e) { // The user leaves the event
this.$emit('userLeave', e)
},
numSeleChange ({list, key, item}) {
this.houseListData = list
let value = ' '
this.houseListData.map((item, index) = > {
if (item.custom) {
value === ' ' ? value = item.customValue + item.unit : value = value + item.customValue + item.unit
} else {
value === ' ' ? value = item.value + item.unit : value = value + item.value + item.unit
}
})
this.formData[key] = value
this.onUserLeave({item, value: this.formData[key]})
},
regionChange (e, key, item) {
this.formData[key] = e
this.onUserLeave({item, value: this.formData[key]})
},
select (e, key, item) {
let str = ' '
e.forEach(item= > {
str += item.value
})
this.formData[key] = str
this.onUserLeave({item, value: this.formData[key]})
},
rateChange (e, key, item) {
this.formData[key] = e
this.onUserLeave({item, value: this.formData[key]})
}
}
}
</script>
Copy the code
Star component
ComForm/components/Rate.vue
<template>
<view class="rate">
<view class="title">
<view>{{label}}</view>
<! </view> -->
</view>
<view class="rate__content">
<u-rate
:count="count"
:size="size"
:active-color="activeColor"
v-model="rate"
@change="e => $emit('change', e)"
/>
</view>
</view>
</template>
<script>
export default {
name: 'Rate'.props: {
label: {
type: String.default: 'Customer intent'
},
initData: {
type: Number.default: 0
}
},
data () {
return {
count: 10.size: '53'.rate: 0.activeColor: '#FF7716'
}
},
created () {
this.rate = this.initData
}
}
</script>
<style lang="scss" scoped>
.rate {
width: 100vw;
margin: -20rpx -32rpx 0;
border-top: 10rpx solid #F7F8FA;
padding: 27rpx 32rpx;
background: white;
.title {
display: flex;
justify-content: space-between;
}
&__content {
margin-top: 30rpx;
margin-left: -5rpx; }}</style>
Copy the code
The label component
ComForm/components/Tags.vue
<template>
<view class="tags">
<view class="title">{{label}}</view>
<view>
<template v-for="(tag, index) in tags">
<u-tag
v-if="tag.selected"
:key="tag.text + index"
:text="tag.text"
mode="dark"
type="primary"
:closeable="custom"
@click="tag.selected = false"
@close="removeTag(index)"
/>
<u-tag
v-else
:key="tag.text + index"
:text="tag.text"
mode="dark"
type="info"
bg-color="#F7F8FA"
color="# 323233"
:closeable="custom"
@click="tag.selected = true"
@close="removeTag(index)"
/>
</template>
<view v-if="custom" class="add" @click="modalShow = true">
<text class="iconfont icon-jiahao" />Add tags</view>
</view>
<u-modal
v-model="modalShow"
show-cancel-button
:mask-close-able="true"
title="Add labels"
confirm-text="Save"
@confirm="addTag"
>
<view class="slot-content">
<u-field
v-model="modalValue"
label-width="0"
placeholder="Labels of no more than 8 characters"
:border-bottom="false"
focus
maxlength="8"
confirm-type="Save"
:field-style="fieldStyle"
/>
</view>
</u-modal>
</view>
</template>
<script>
export default {
name: 'Tags'.model: {
prop: 'tags'.event: 'input'
},
props: {
tags: {
type: Array.default: () = >[]},label: {
type: String.default: 'Type of Property'
},
custom: {
type: Boolean.default: false}},watch: {
tags: {
deep: true,
handler (newVal) {
this.$emit('tagChange')
// this.$emit('input', newVal)
}
}
},
data () {
return {
modalShow: false.modalValue: ' '.fieldStyle: {
border: '1px solid #C0C4CC'.padding: '13rpx 21rpx'.borderRadius: '4px'}}},methods: {
addTag () {
this.tags.push({
text: this.modalValue,
selected: true
})
this.modalValue = ' '
},
removeTag (index) {
this.tags.splice(index, 1)}}}</script>
<style lang="scss" scoped>
.tags {
margin-bottom: 25rpx;
.title {
margin-bottom: 18rpx;
}
u-tag, .u-tag {
display: inline-block;
margin-right: 20rpx;
margin-bottom: 20rpx;
font-size: 26rpx;
&:last-child {
margin-right: 0; }}.add {
position: relative;
display: inline-block;
line-height: initial;
font-size: 24rpx;
padding: 12rpx 22rpx;
padding-left: 70rpx;
background: #F7F8FA;
border-radius: 3px;
.iconfont {
position: absolute;
top: 50%;
left: 22rpx;
margin-right: 10rpx;
transform: translateY(-50%); }}}</style>
Copy the code
use
<template>
<com-form
v-model="form"
:form-desc="formDesc"
@userLeave="onUserLeave"
/>
</template>
<script>
const formType = [
'input'.// Single line of text
'textarea'.// Multi-line text
'region'./ / address
'date'./ / time
'select'./ / a drop-down box
'PropertyType'.// Label selection
'houseType'.// Select the house type
'rate'.// Star intention degree
]
export default {
data () {
return {
formDesc: {
name: {
type: 'input'.label: 'name'.attr: {
placeholder: 'Please note customer name'.inputAlign: 'right'}},phone: {
type: 'input'.label: 'phone'.attr: {
placeholder: 'Please note customer phone number'.inputAlign: 'right'}},houseType: {
type: 'houseType'.label: 'room'.attr: {
placeholder: 'Please comment on house type'.inputAlign: 'right'}},region: {
type: 'region'.label: '地区范围'.attr: {
placeholder: 'Please specify area'.inputAlign: 'right'}},rate: {
type: 'rate'}},form: {}}}.methods: {
setFormDesc (data) { / / render the form
const formDesc = {}
const form = {}
data.forEach((item, index) = > {
formDesc[item.code] = {
type: formType[item.dataType],
label: item.label,
allowCustom: item.allowCustom,
attr: {
placeholder: item.placeholder,
inputAlign: 'right'.customIntentionId: item.customIntentionId,
id: item.id,
code: item.code
}
}
if (formType[item.dataType] === 'region') { // region processing
let splitArr = []
let data = {
province: {
label: ' '
},
city: {
label: ' '
},
area: {
label: ' '}}if (item.customerIntentionValue) {
splitArr = item.customerIntentionValue.split('|')}else if (item.initData) {
splitArr = item.initData.split('|')}if (splitArr.length) {
data = {
province: {
label: splitArr[0]},city: {
label: splitArr[1]},area: {
label: splitArr[2]
}
}
}
form[item.code] = data
} else if (formType[item.dataType] === 'PropertyType') { // Label type special processing
const data = []
let splitArr = item.initData ? item.initData.split('|') : []
let splitSelectedArr = item.customerIntentionValue ? item.customerIntentionValue.split('|') : []
// if (item.customerIntentionValue) {
// splitArr = item.customerIntentionValue.split('|')
// } else if (item.initData) {
// splitArr = item.initData.split('|')
// }
if(item.allowCustom && splitSelectedArr ! = =' ') { // Back end requirements, custom tags only selected
splitSelectedArr.forEach(el= > {
let tagItem = {
text: el,
selected: true
}
data.push(tagItem)
})
form[item.code] = data
return
}
if(splitArr ! = =' ') { // Common tags
splitArr.forEach(el= > { / / assignment
let tagItem = {
text: el,
selected: false
}
if(splitSelectedArr ! = =' ') {
let splitSelected = splitSelectedArr.find(selectedItem= > selectedItem === el)
if (splitSelected) {
tagItem.selected = true
}
}
data.push(tagItem)
})
}
form[item.code] = data
} else if (formType[item.dataType] === 'rate') { // Convert the string passed from the back end
form[item.code] = Number(item.customerIntentionValue) || Number(item.initData)
} else {
form[item.code] = item.customerIntentionValue || item.initData
}
})
this.formDesc = formDesc
this.form = form
}
}
}
</script>
Copy the code