1. 将ns-newform组件从pages_tool/_components移动到项目标准components目录 2. 更新所有文件中对该组件的导入路径和文档引用 3. 优化diy-form组件的表单数据处理逻辑,兼容更多数据格式
1091 lines
30 KiB
Vue
1091 lines
30 KiB
Vue
<template>
|
||
<view class="form-wrap form-component">
|
||
<view v-for="(item, index) in formData" :key="index">
|
||
<!-- 文本输入框 -->
|
||
<view v-if="item.controller == 'Text'" class="order-wrap">
|
||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]">
|
||
<view class="name" :style="[nameWidthStyle, labelStyle]">
|
||
<text class="tit">{{ item.value.title }}</text>
|
||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||
</view>
|
||
<view :class="['box', 'align-left']">
|
||
<input
|
||
type="text"
|
||
:placeholder="item.value.placeholder"
|
||
placeholder-class="placeholder color-tip"
|
||
v-model="item.val"
|
||
/>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 多行文本输入框 -->
|
||
<view v-if="item.controller == 'Textarea'" class="order-wrap">
|
||
<view :class="['order-cell', 'flex-box', 'textarea', { 'vertical-layout': mode === 'vertical' }]">
|
||
<view class="name" :style="[nameWidthStyle, labelStyle]">
|
||
<text class="tit">{{ item.value.title }}</text>
|
||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||
</view>
|
||
<view :class="['box', 'align-left']">
|
||
<textarea
|
||
:placeholder="item.value.placeholder"
|
||
placeholder-class="placeholder color-tip"
|
||
v-model="item.val"
|
||
></textarea>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 下拉选择器 -->
|
||
<view v-if="item.controller == 'Select'" class="order-wrap">
|
||
<picker
|
||
mode="selector"
|
||
:range="item.value.options"
|
||
@change="pickerChange($event, index)"
|
||
>
|
||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]">
|
||
<view class="name" :style="[nameWidthStyle, labelStyle]">
|
||
<text class="tit">{{ item.value.title }}</text>
|
||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||
</view>
|
||
<view :class="['box', 'align-right']">
|
||
<text v-if="item.val != ''">{{ item.val }}</text>
|
||
<text v-else class="color-tip">请选择</text>
|
||
</view>
|
||
<text class="iconfont icon-right"></text>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
|
||
<!-- 复选框 -->
|
||
<view v-if="item.controller == 'Checkbox'" class="order-wrap">
|
||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]">
|
||
<view class="name" :style="[nameWidthStyle, labelStyle]">
|
||
<text class="tit">{{ item.value.title }}</text>
|
||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||
</view>
|
||
<view :class="['box', 'check-group-box', 'align-left']">
|
||
<checkbox-group @change="checkboxChange($event, index)">
|
||
<label v-for="(v, k) in item.option_lists" :key="k">
|
||
<checkbox :value="v.value" :checked="v.checked"></checkbox>
|
||
<view class="checkbox">
|
||
<text
|
||
:class="[
|
||
'iconfont',
|
||
!v.checked ? 'icon-fuxuankuang2' : '',
|
||
v.checked ? 'icon-fuxuankuang1 color-base-text' : ''
|
||
]"
|
||
></text>
|
||
{{ v.value }}
|
||
</view>
|
||
</label>
|
||
</checkbox-group>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 单选框 -->
|
||
<view v-if="item.controller == 'Radio'" class="order-wrap">
|
||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]">
|
||
<view class="name" :style="[nameWidthStyle, labelStyle]">
|
||
<text class="tit">{{ item.value.title }}</text>
|
||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||
</view>
|
||
<view :class="['box', 'radio-group-box', 'align-left']">
|
||
<radio-group @change="radioChange($event, index)">
|
||
<label v-for="(v, k) in item.option_lists" :key="k">
|
||
<radio :value="v.value" :checked="item.val == v.value"></radio>
|
||
<view class="radio-box">
|
||
<text
|
||
:class="[
|
||
'iconfont',
|
||
item.val != v.value ? 'icon-yuan_checkbox' : '',
|
||
item.val == v.value ? 'icon-yuan_checked color-base-text' : ''
|
||
]"
|
||
></text>
|
||
{{ v.value }}
|
||
</view>
|
||
</label>
|
||
</radio-group>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 图片上传 -->
|
||
<view v-if="item.controller == 'Img'" class="order-wrap">
|
||
<view :class="['order-cell', 'flex-box', { 'vertical-layout': mode === 'vertical' }]">
|
||
<view class="name" :style="[nameWidthStyle, labelStyle]">
|
||
<text class="tit">{{ item.value.title }}</text>
|
||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||
</view>
|
||
<view :class="['box', 'img-boxs', 'align-left']">
|
||
<view v-for="(v, k) in item.img_lists" :key="k" class="img-box" @tap="uploadImg(index)">
|
||
<image :src="$util.img(v)" mode="aspectFill" show-menu-by-longpress></image>
|
||
<text class="iconfont icon-guanbi" @tap.stop="delImg(k, index)"></text>
|
||
</view>
|
||
<view class="img-box" @tap="addImg(index)">
|
||
<text class="iconfont icon-add1"></text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 日期选择器 -->
|
||
<view v-if="item.controller == 'Date'" class="order-wrap">
|
||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]">
|
||
<view class="name" :style="[nameWidthStyle, labelStyle]">
|
||
<text class="tit">{{ item.value.title }}</text>
|
||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||
</view>
|
||
<view :class="['box', 'box-flex', 'align-right']">
|
||
<picker
|
||
mode="date"
|
||
:value="item.val"
|
||
@change="bindDateChange($event, index)"
|
||
>
|
||
<view :class="['uni-input', !item.val ? 'color-tip' : '']">
|
||
{{ item.val ? item.val : item.value.placeholder }}
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
<text class="iconfont icon-right"></text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 日期范围选择器 -->
|
||
<view v-if="item.controller == 'Datelimit'" class="order-wrap">
|
||
<view :class="['order-cell', 'flex-box', { 'vertical-layout': mode === 'vertical' }]">
|
||
<view class="name" :style="[nameWidthStyle, labelStyle]">
|
||
<text class="tit">{{ item.value.title }}</text>
|
||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||
</view>
|
||
<view :class="['box', 'date-boxs', 'align-center']">
|
||
<view class="date-box">
|
||
<picker
|
||
mode="date"
|
||
:value="item.start_date"
|
||
@change="bindStartDateChange($event, index)"
|
||
>
|
||
<view class="picker-box">
|
||
<view :class="['uni-input', !item.start_date ? 'color-tip' : '']">
|
||
{{ item.start_date ? item.start_date : item.value.placeholder_start }}
|
||
</view>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
<view class="interval iconfont icon-jian"></view>
|
||
<view class="date-box">
|
||
<picker
|
||
mode="date"
|
||
:value="item.end_date"
|
||
@change="bindEndDateChange($event, index)"
|
||
>
|
||
<view class="picker-box">
|
||
<view :class="['uni-input', !item.end_date ? 'color-tip' : '']">
|
||
{{ item.end_date ? item.end_date : item.value.placeholder_end }}
|
||
</view>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 时间选择器 -->
|
||
<view v-if="item.controller == 'Time'" class="order-wrap">
|
||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]">
|
||
<view class="name" :style="[nameWidthStyle, labelStyle]">
|
||
<text class="tit">{{ item.value.title }}</text>
|
||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||
</view>
|
||
<view :class="['box', 'box-flex', 'align-right']">
|
||
<picker
|
||
mode="time"
|
||
:value="item.val"
|
||
@change="bindTimeChange($event, index)"
|
||
>
|
||
<view :class="['uni-input', !item.val ? 'color-tip' : '']">
|
||
{{ item.val ? item.val : item.value.placeholder }}
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
<text class="iconfont icon-right"></text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 时间范围选择器 -->
|
||
<view v-if="item.controller == 'Timelimit'" class="order-wrap">
|
||
<view :class="['order-cell', 'flex-box', { 'vertical-layout': mode === 'vertical' }]">
|
||
<view class="name" :style="[nameWidthStyle, labelStyle]">
|
||
<text class="tit">{{ item.value.title }}</text>
|
||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||
</view>
|
||
<view :class="['box', 'date-boxs', 'align-center']">
|
||
<view class="date-box">
|
||
<picker
|
||
mode="time"
|
||
:value="item.start_time"
|
||
@change="bindStartTimeChange($event, index)"
|
||
>
|
||
<view class="picker-box">
|
||
<view :class="['uni-input', !item.start_time ? 'color-tip' : '']">
|
||
{{ item.start_time ? item.start_time : item.value.placeholder_start }}
|
||
</view>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
<view class="interval iconfont icon-jian"></view>
|
||
<view class="date-box">
|
||
<picker
|
||
mode="time"
|
||
:value="item.end_time"
|
||
@change="bindEndTimeChange($event, index)"
|
||
>
|
||
<view class="picker-box">
|
||
<view :class="['uni-input', !item.end_time ? 'color-tip' : '']">
|
||
{{ item.end_time ? item.end_time : item.value.placeholder_end }}
|
||
</view>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 城市选择器 -->
|
||
<view v-if="item.controller == 'City'" class="order-wrap">
|
||
<view :class="['order-cell', 'box-flex', { 'vertical-layout': mode === 'vertical' }]">
|
||
<view class="name" :style="[nameWidthStyle, labelStyle]">
|
||
<text class="tit">{{ item.value.title }}</text>
|
||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||
</view>
|
||
<view :class="['box', 'align-right']">
|
||
<pick-regions
|
||
:defaultRegions="item.default_regions"
|
||
:selectArr="item.select_arr"
|
||
@getRegions="handleGetRegions($event, index)"
|
||
>
|
||
<view :class="['select-address', !item.val ? 'empty' : '', !item.val ? 'color-tip' : '']">
|
||
{{ item.val ? item.val : (item.select_arr == '2' ? '请选择省市' : '请选择省市区/县') }}
|
||
</view>
|
||
</pick-regions>
|
||
</view>
|
||
<text class="iconfont icon-right"></text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'ns-newform',
|
||
props: {
|
||
data: {
|
||
type: Array,
|
||
default: () => []
|
||
},
|
||
customAttr: {
|
||
type: Object,
|
||
default: () => ({})
|
||
},
|
||
mode: {
|
||
type: String,
|
||
default: 'horizontal',
|
||
validator: (value) => !value || ['horizontal', 'vertical'].includes(value)
|
||
},
|
||
labelWidthMode: {
|
||
type: String,
|
||
default: 'auto',
|
||
validator: (value) => !value || ['auto', 'fixed'].includes(value)
|
||
},
|
||
labelFixedWidth: {
|
||
type: [String, Number],
|
||
default: 180
|
||
},
|
||
labelFontSize: {
|
||
type: [String, Number],
|
||
default: 26
|
||
},
|
||
labelColor: {
|
||
type: String,
|
||
default: '#303133'
|
||
},
|
||
requiredColor: {
|
||
type: String,
|
||
default: '#F56C6C'
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
formData: [],
|
||
maxLabelWidth: 0
|
||
}
|
||
},
|
||
created() {
|
||
// 避免直接修改 prop,初始化本地数据
|
||
this.initFormData();
|
||
},
|
||
mounted() {
|
||
this.$nextTick(() => {
|
||
this.calculateMaxLabelWidth();
|
||
});
|
||
},
|
||
watch: {
|
||
data: {
|
||
handler() {
|
||
this.initFormData();
|
||
this.$nextTick(() => {
|
||
this.calculateMaxLabelWidth();
|
||
});
|
||
},
|
||
deep: true
|
||
}
|
||
},
|
||
computed: {
|
||
nameWidthStyle() {
|
||
if (this.mode === 'vertical') {
|
||
return {};
|
||
}
|
||
let width;
|
||
if (this.labelWidthMode === 'fixed') {
|
||
width = `${this.labelFixedWidth}rpx`;
|
||
} else {
|
||
width = this.maxLabelWidth ? `${this.maxLabelWidth}rpx` : 'auto';
|
||
}
|
||
return {
|
||
width: width
|
||
};
|
||
},
|
||
labelStyle() {
|
||
let style = {};
|
||
let fontSize = this.labelFontSize;
|
||
if (typeof fontSize === 'number') {
|
||
fontSize = `${fontSize}rpx`;
|
||
} else if (typeof fontSize === 'string' && !fontSize.endsWith('rpx') && !fontSize.endsWith('px')) {
|
||
fontSize = `${fontSize}rpx`;
|
||
}
|
||
style.fontSize = fontSize;
|
||
style.color = this.labelColor;
|
||
return style;
|
||
}
|
||
},
|
||
methods: {
|
||
calculateMaxLabelWidth() {
|
||
if (this.mode === 'vertical' || !this.formData || this.formData.length === 0) {
|
||
return;
|
||
}
|
||
|
||
let maxWidth = 0;
|
||
|
||
this.formData.forEach((item) => {
|
||
if (item.value && item.value.title) {
|
||
let text = item.value.title;
|
||
if (item.value.required) {
|
||
text += '*';
|
||
}
|
||
let width = 0;
|
||
for (let i = 0; i < text.length; i++) {
|
||
const char = text[i];
|
||
if (/[\u4e00-\u9fa5]/.test(char)) {
|
||
width += 1;
|
||
} else {
|
||
width += 0.5;
|
||
}
|
||
}
|
||
const fontSize = parseInt(this.labelFontSize) || 30;
|
||
width = width * fontSize * 0.85 + 30;
|
||
maxWidth = Math.max(maxWidth, width);
|
||
}
|
||
});
|
||
|
||
maxWidth = Math.max(maxWidth, 60);
|
||
maxWidth = Math.min(maxWidth, 160);
|
||
|
||
this.maxLabelWidth = maxWidth;
|
||
},
|
||
|
||
initFormData() {
|
||
// 深拷贝 prop 数据到本地状态
|
||
this.formData = JSON.parse(JSON.stringify(this.data || []));
|
||
this.processFormData();
|
||
},
|
||
|
||
setFormData() {
|
||
// 重置为初始值
|
||
this.initFormData();
|
||
},
|
||
|
||
processFormData() {
|
||
this.formData.forEach((item) => {
|
||
if (!item.val) {
|
||
item.val = item.value.default ? item.value.default : '';
|
||
}
|
||
|
||
if (item.value.options) {
|
||
item.option_lists = [];
|
||
item.value.options.forEach((option, index) => {
|
||
let optionItem = {};
|
||
optionItem.value = option;
|
||
optionItem.checked = false;
|
||
|
||
if (item.controller == 'Radio') {
|
||
if ((!item.val && index == 0) || (item.val && item.val == option)) {
|
||
optionItem.checked = true;
|
||
item.val = option;
|
||
}
|
||
}
|
||
|
||
if (item.controller == 'Checkbox' && item.val) {
|
||
let valArray = item.val.split(',');
|
||
optionItem.checked = valArray.indexOf(option) != -1;
|
||
}
|
||
|
||
item.option_lists.push(optionItem);
|
||
});
|
||
}
|
||
|
||
if (item.controller == 'Img') {
|
||
item.img_lists = item.val ? item.val.split(',') : [];
|
||
}
|
||
|
||
if (item.controller == 'Date' && !item.val) {
|
||
if (item.value.is_show_default) {
|
||
if (item.value.is_current) {
|
||
item.val = this.getDate();
|
||
} else {
|
||
item.val = item.value.default;
|
||
}
|
||
} else {
|
||
item.val = '';
|
||
}
|
||
}
|
||
|
||
if (item.controller == 'Datelimit') {
|
||
if (item.val) {
|
||
let dateArray = item.val.split(' - ');
|
||
item.start_date = dateArray[0];
|
||
item.end_date = dateArray[1];
|
||
} else {
|
||
item.val = '';
|
||
|
||
if (item.value.is_show_default_start) {
|
||
if (item.value.is_current_start) {
|
||
item.start_date = this.getDate();
|
||
} else {
|
||
item.start_date = item.value.default_start;
|
||
}
|
||
} else {
|
||
item.start_date = '';
|
||
}
|
||
|
||
if (item.value.is_show_default_end) {
|
||
if (item.value.is_current_end) {
|
||
item.end_date = this.getDate();
|
||
} else {
|
||
item.end_date = item.value.default_end;
|
||
}
|
||
}
|
||
|
||
if (item.start_date && item.end_date) {
|
||
item.val = item.start_date + ' - ' + item.end_date;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (item.controller == 'Time' && !item.val) {
|
||
if (item.value.is_show_default) {
|
||
if (item.value.is_current) {
|
||
item.val = this.getTime();
|
||
} else {
|
||
item.val = item.value.default;
|
||
}
|
||
} else {
|
||
item.val = '';
|
||
}
|
||
}
|
||
|
||
if (item.controller == 'Timelimit') {
|
||
if (item.val) {
|
||
let timeArray = item.val.split(' - ');
|
||
item.start_time = timeArray[0];
|
||
item.end_time = timeArray[1];
|
||
} else {
|
||
item.val = '';
|
||
|
||
if (item.value.is_show_default_start) {
|
||
if (item.value.is_current_start) {
|
||
item.start_time = this.getTime();
|
||
} else {
|
||
item.start_time = item.value.default_start;
|
||
}
|
||
} else {
|
||
item.start_time = '';
|
||
}
|
||
|
||
if (item.value.is_show_default_end) {
|
||
if (item.value.is_current_end) {
|
||
item.end_time = this.getTime();
|
||
} else {
|
||
item.end_time = item.value.default_end;
|
||
}
|
||
}
|
||
|
||
if (item.start_time && item.end_time) {
|
||
item.val = item.start_time + ' - ' + item.end_time;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (item.controller == 'City') {
|
||
item.full_address = '';
|
||
item.select_arr = item.value.default_type == 1 ? '2' : '3';
|
||
if (item.val) {
|
||
item.default_regions = item.val.split('-');
|
||
} else {
|
||
item.default_regions = [];
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
verify() {
|
||
for (let i = 0; i < this.formData.length; i++) {
|
||
let item = this.formData[i];
|
||
|
||
if (item.controller == 'Text') {
|
||
if (item.value.required && !item.val) {
|
||
this.$util.showToast({ title: '请输入' + item.value.title });
|
||
return false;
|
||
}
|
||
|
||
if (item.name == 'ID_CARD' && !/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(item.val)) {
|
||
if (!item.value.required) {
|
||
this.$util.showToast({ title: '身份证输入不合法' });
|
||
return false;
|
||
}
|
||
if (item.val != '') {
|
||
this.$util.showToast({ title: '身份证输入不合法' });
|
||
return false;
|
||
}
|
||
}
|
||
|
||
if (item.name == 'MOBILE' && !this.$util.verifyMobile(item.val)) {
|
||
if (!item.value.required) {
|
||
this.$util.showToast({ title: '手机号输入不合法' });
|
||
return false;
|
||
}
|
||
if (item.val != '') {
|
||
this.$util.showToast({ title: '手机号输入不合法' });
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (item.controller == 'Textarea' && item.value.required && !item.val) {
|
||
this.$util.showToast({ title: '请输入' + item.value.title });
|
||
return false;
|
||
}
|
||
|
||
if (item.controller == 'Select' && item.value.required && !item.val) {
|
||
this.$util.showToast({ title: '请选择' + item.value.title });
|
||
return false;
|
||
}
|
||
|
||
if (item.controller == 'Checkbox' && item.value.required && !item.val) {
|
||
this.$util.showToast({ title: '请至少选择一个' + item.value.title });
|
||
return false;
|
||
}
|
||
|
||
if (item.controller == 'Img' && item.value.required && !item.val) {
|
||
this.$util.showToast({ title: '请至少上传一张' + item.value.title });
|
||
return false;
|
||
}
|
||
|
||
if (item.controller == 'Date' && item.value.required && !item.val) {
|
||
this.$util.showToast({ title: '请选择' + item.value.title });
|
||
return false;
|
||
}
|
||
|
||
if (item.controller == 'Datelimit') {
|
||
if (item.value.required && !item.val) {
|
||
this.$util.showToast({ title: '请选择' + item.value.title });
|
||
return false;
|
||
}
|
||
|
||
if (this.$util.timeTurnTimeStamp(item.start_date) > this.$util.timeTurnTimeStamp(item.end_date)) {
|
||
this.$util.showToast({ title: '结束日期不能小于开始日期' });
|
||
return false;
|
||
}
|
||
}
|
||
|
||
if (item.controller == 'Time' && item.value.required && !item.val) {
|
||
this.$util.showToast({ title: '请选择' + item.value.title });
|
||
return false;
|
||
}
|
||
|
||
if (item.controller == 'Timelimit') {
|
||
if (item.value.required && !item.val) {
|
||
this.$util.showToast({ title: '请选择' + item.value.title });
|
||
return false;
|
||
}
|
||
|
||
if (item.start_time >= item.end_time) {
|
||
this.$util.showToast({ title: '结束时间必须大于开始时间' });
|
||
return false;
|
||
}
|
||
}
|
||
|
||
if (item.controller == 'City' && item.value.required && !item.val) {
|
||
this.$util.showToast({ title: '请选择' + item.value.title });
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return this.formData;
|
||
},
|
||
|
||
pickerChange(event, index) {
|
||
this.formData[index].val = this.data[index].value.options[event.detail.value];
|
||
this.$forceUpdate();
|
||
},
|
||
|
||
checkboxChange(event, index) {
|
||
this.formData[index].val = event.detail.value.toString();
|
||
this.formData[index].option_lists.forEach((option) => {
|
||
option.checked = event.detail.value.indexOf(option.value) != -1;
|
||
});
|
||
this.$forceUpdate();
|
||
},
|
||
|
||
radioChange(event, index) {
|
||
this.formData[index].val = event.detail.value;
|
||
this.$forceUpdate();
|
||
},
|
||
|
||
uploadImg(index) {
|
||
let self = this;
|
||
this.$util.upload(Number(this.formData[index].value.max_count), { path: 'evaluateimg' }, function(res) {
|
||
if (res.length > 0) {
|
||
res.forEach(function(img) {
|
||
if (self.formData[index].img_lists.length >= Number(self.formData[index].value.max_count)) {
|
||
self.$util.showToast({ title: '最多上传' + self.formData[index].value.max_count + '张图片' });
|
||
return false;
|
||
}
|
||
self.formData[index].img_lists.push(img);
|
||
});
|
||
self.formData[index].val = self.formData[index].img_lists.toString();
|
||
self.$forceUpdate();
|
||
}
|
||
});
|
||
},
|
||
|
||
addImg(index) {
|
||
let self = this;
|
||
if (this.formData[index].img_lists.length >= Number(this.formData[index].value.max_count)) {
|
||
this.$util.showToast({ title: '最多上传' + this.formData[index].value.max_count + '张图片' });
|
||
return false;
|
||
}
|
||
|
||
this.$util.upload(Number(this.formData[index].value.max_count), { path: 'evaluateimg' }, function(res) {
|
||
if (res.length > 0) {
|
||
res.forEach(function(img) {
|
||
self.formData[index].img_lists.push(img);
|
||
});
|
||
self.formData[index].val = self.formData[index].img_lists.toString();
|
||
self.$forceUpdate();
|
||
}
|
||
});
|
||
},
|
||
|
||
delImg(imgIndex, formIndex) {
|
||
this.formData[formIndex].img_lists.splice(imgIndex, 1);
|
||
this.formData[formIndex].val = this.formData[formIndex].img_lists.toString();
|
||
this.$forceUpdate();
|
||
},
|
||
|
||
getDate() {
|
||
let date = new Date();
|
||
let year = date.getFullYear();
|
||
let month = date.getMonth() + 1;
|
||
let day = date.getDate();
|
||
month = month > 9 ? month : '0' + month;
|
||
day = day > 9 ? day : '0' + day;
|
||
return `${year}-${month}-${day}`;
|
||
},
|
||
|
||
getTime() {
|
||
let date = new Date();
|
||
let hours = date.getHours();
|
||
let minutes = date.getMinutes();
|
||
hours = hours > 9 ? hours : '0' + hours;
|
||
minutes = minutes > 9 ? minutes : '0' + minutes;
|
||
return `${hours}:${minutes}`;
|
||
},
|
||
|
||
bindDateChange(event, index) {
|
||
this.formData[index].val = event.detail.value;
|
||
this.$forceUpdate();
|
||
},
|
||
|
||
bindStartDateChange(event, index) {
|
||
this.$set(this.formData[index], 'start_date', event.detail.value);
|
||
this.$set(this.formData[index], 'val', this.formData[index].start_date + ' - ' + this.formData[index].end_date);
|
||
this.$forceUpdate();
|
||
},
|
||
|
||
bindEndDateChange(event, index) {
|
||
this.$set(this.formData[index], 'end_date', event.detail.value);
|
||
this.$set(this.formData[index], 'val', this.formData[index].start_date + ' - ' + this.formData[index].end_date);
|
||
this.$forceUpdate();
|
||
},
|
||
|
||
bindTimeChange(event, index) {
|
||
this.formData[index].val = event.detail.value;
|
||
this.$forceUpdate();
|
||
},
|
||
|
||
bindStartTimeChange(event, index) {
|
||
this.formData[index].start_time = event.detail.value;
|
||
this.$forceUpdate();
|
||
},
|
||
|
||
bindEndTimeChange(event, index) {
|
||
this.formData[index].end_time = event.detail.value;
|
||
this.formData[index].val = this.formData[index].start_time + ' - ' + this.formData[index].end_time;
|
||
this.$forceUpdate();
|
||
},
|
||
|
||
handleGetRegions(regions, index) {
|
||
this.formData[index].val = '';
|
||
this.formData[index].val += regions[0] != undefined ? regions[0].label : '';
|
||
this.formData[index].val += regions[1] != undefined ? '-' + regions[1].label : '';
|
||
this.formData[index].val += regions[2] != undefined ? '-' + regions[2].label : '';
|
||
this.$forceUpdate();
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.form-wrap {
|
||
background: #ffffff;
|
||
}
|
||
|
||
.order-wrap {
|
||
padding: 4rpx 14rpx;
|
||
transition: all 0.3s ease;
|
||
position: relative;
|
||
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
left: 14rpx;
|
||
bottom: 0;
|
||
right: 14rpx;
|
||
height: 1rpx;
|
||
background: #f0f0f0;
|
||
}
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
border-bottom: 0;
|
||
|
||
&::after {
|
||
display: none;
|
||
}
|
||
}
|
||
|
||
.order-cell {
|
||
display: flex;
|
||
align-items: center;
|
||
background: #fff;
|
||
position: relative;
|
||
padding: 0;
|
||
min-height: 60rpx;
|
||
|
||
// 水平布局(默认):标签自动宽度(以最大为准),根据组件特性对齐
|
||
&:not(.vertical-layout) {
|
||
.name {
|
||
flex-shrink: 0;
|
||
margin-bottom: 0;
|
||
margin-right: 16rpx;
|
||
}
|
||
}
|
||
|
||
&.vertical-layout {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
|
||
.name {
|
||
width: 100%;
|
||
margin-bottom: 12rpx;
|
||
margin-right: 0;
|
||
}
|
||
|
||
.box {
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
&.textarea {
|
||
align-items: flex-start;
|
||
|
||
.name {
|
||
padding-top: 16rpx;
|
||
height: auto;
|
||
line-height: 44rpx;
|
||
}
|
||
}
|
||
|
||
&.clear-flex {
|
||
display: block;
|
||
|
||
.box {
|
||
margin-top: 12rpx;
|
||
text-align: left;
|
||
}
|
||
}
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
&.align-top {
|
||
align-items: flex-start;
|
||
}
|
||
|
||
text {
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.name {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
display: flex;
|
||
align-items: center;
|
||
height: 60rpx;
|
||
line-height: 60rpx;
|
||
|
||
.tit {
|
||
text-align: left;
|
||
font-size: 26rpx;
|
||
color: #1f2937;
|
||
font-weight: 500;
|
||
letter-spacing: 0.2rpx;
|
||
|
||
text {
|
||
font-size: 26rpx;
|
||
}
|
||
}
|
||
|
||
.required {
|
||
color: #ef4444;
|
||
font-size: 28rpx;
|
||
margin-left: 4rpx;
|
||
display: inline-block;
|
||
vertical-align: middle;
|
||
}
|
||
}
|
||
|
||
.box {
|
||
flex: 1;
|
||
padding: 0;
|
||
line-height: inherit;
|
||
|
||
// 对齐方式
|
||
&.align-left {
|
||
text-align: left;
|
||
}
|
||
|
||
&.align-right {
|
||
text-align: right;
|
||
}
|
||
|
||
&.align-center {
|
||
text-align: center;
|
||
}
|
||
|
||
input {
|
||
font-size: 26rpx;
|
||
text-align: left;
|
||
height: 60rpx;
|
||
border: 2rpx solid #f3f4f6;
|
||
border-radius: 10rpx;
|
||
line-height: 60rpx;
|
||
padding: 0 16rpx;
|
||
background: #f9fafb;
|
||
color: #1f2937;
|
||
transition: all 0.3s ease;
|
||
|
||
&:focus {
|
||
background: #fff;
|
||
border-color: #3b82f6;
|
||
box-shadow: 0 0 0 4rpx rgba(59, 130, 246, 0.08);
|
||
}
|
||
|
||
&::placeholder {
|
||
color: #9ca3af;
|
||
}
|
||
}
|
||
|
||
textarea {
|
||
font-size: 26rpx;
|
||
width: 100%;
|
||
min-height: 180rpx;
|
||
line-height: 40rpx;
|
||
text-align: left;
|
||
border: 2rpx solid #f3f4f6;
|
||
border-radius: 10rpx;
|
||
padding: 12rpx 16rpx;
|
||
background: #f9fafb;
|
||
color: #1f2937;
|
||
transition: all 0.3s ease;
|
||
box-sizing: border-box;
|
||
height: auto;
|
||
|
||
&:focus {
|
||
background: #fff;
|
||
border-color: #3b82f6;
|
||
box-shadow: 0 0 0 4rpx rgba(59, 130, 246, 0.08);
|
||
}
|
||
|
||
&::placeholder {
|
||
color: #9ca3af;
|
||
}
|
||
}
|
||
|
||
.uni-input, .select-address {
|
||
display: inline-block;
|
||
padding: 8rpx 16rpx;
|
||
border-radius: 10rpx;
|
||
background: #f9fafb;
|
||
border: 2rpx solid #f3f4f6;
|
||
color: #1f2937;
|
||
font-size: 26rpx;
|
||
transition: all 0.3s ease;
|
||
min-height: 60rpx;
|
||
box-sizing: border-box;
|
||
|
||
&.color-tip {
|
||
color: #9ca3af;
|
||
}
|
||
|
||
&.empty {
|
||
color: #9ca3af;
|
||
}
|
||
|
||
&:active {
|
||
background: #f3f4f6;
|
||
}
|
||
}
|
||
|
||
checkbox-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
radio-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
label {
|
||
display: flex;
|
||
align-items: center;
|
||
line-height: 1;
|
||
margin: 0;
|
||
padding: 6rpx 14rpx;
|
||
border: 2rpx solid #e5e7eb;
|
||
border-radius: 6rpx;
|
||
background: #fff;
|
||
transition: all 0.3s ease;
|
||
|
||
&:active {
|
||
background: #f3f4f6;
|
||
}
|
||
}
|
||
|
||
&.img-boxs {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
gap: 16rpx;
|
||
|
||
.img-box {
|
||
margin: 0;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
width: 120rpx;
|
||
height: 120rpx;
|
||
border: 2rpx dashed #d1d5db;
|
||
border-radius: 8rpx;
|
||
position: relative;
|
||
background: #f9fafb;
|
||
transition: all 0.3s ease;
|
||
overflow: hidden;
|
||
|
||
&:active {
|
||
background: #f3f4f6;
|
||
border-color: #3b82f6;
|
||
}
|
||
|
||
.icon-guanbi {
|
||
position: absolute;
|
||
top: -10rpx;
|
||
right: -10rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
line-height: 1;
|
||
color: #fff;
|
||
background: #ef4444;
|
||
border-radius: 50%;
|
||
font-size: 20rpx;
|
||
z-index: 10;
|
||
}
|
||
|
||
.icon-add1 {
|
||
font-size: 48rpx;
|
||
color: #9ca3af;
|
||
}
|
||
}
|
||
}
|
||
|
||
&.date-boxs {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.date-box {
|
||
flex: 1;
|
||
|
||
.picker-box {
|
||
.uni-input {
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
}
|
||
}
|
||
}
|
||
|
||
.interval {
|
||
padding: 0 16rpx;
|
||
color: #9ca3af;
|
||
font-size: 32rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.icon-right {
|
||
color: #9ca3af;
|
||
font-size: 32rpx;
|
||
margin-left: 12rpx;
|
||
}
|
||
}
|
||
}
|
||
</style> |