zyejMAll-mobile/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
2024-08-07 10:31:42 +08:00

537 lines
12 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="">
<view
class="uni-forms-item"
:class="{
'uni-forms-item--border': border,
'is-first-border': border && isFirstBorder,
'uni-forms-item-error': msg
}"
>
<view class="uni-forms-item__box">
<view class="uni-forms-item__inner" :class="['is-direction-' + labelPos]">
<view class="uni-forms-item__label" :style="{ width: labelWid, justifyContent: justifyContent }">
<slot name="label">
<text v-if="required" class="is-required">*</text>
<uni-icons
v-if="leftIcon"
class="label-icon"
size="16"
:type="leftIcon"
:color="iconColor"
/>
<text class="label-text">{{ label }}</text>
<view v-if="label" class="label-seat"></view>
</slot>
</view>
<view class="uni-forms-item__content" :class="{ 'is-input-error-border': msg }"><slot></slot></view>
</view>
<view
v-if="msg"
class="uni-error-message"
:class="{ 'uni-error-msg--boeder': border }"
:style="{
paddingLeft: labelLeft
}"
>
<text class="uni-error-message-text">{{ showMsg === 'undertext' ? msg : '' }}</text>
</view>
</view>
</view>
</view>
</template>
<script>
/**
* Field 输入框
* @description 此组件可以实现表单的输入与校验,包括 "text" 和 "textarea" 类型。
* @tutorial https://ext.dcloud.net.cn/plugin?id=21001
* @property {Boolean} required 是否必填,左边显示红色"*"号默认false
* @property {String} validateTrigger = [bind|submit] 校验触发器方式 默认 submit 可选
* @value bind 发生变化时触发
* @value submit 提交时触发
* @property {String } leftIcon label左边的图标限 uni-ui 的图标名称
* @property {String } iconColor 左边通过icon配置的图标的颜色默认#606266
* @property {String } label 输入框左边的文字提示
* @property {Number } labelWidth label的宽度单位px默认65
* @property {String } labelAlign = [left|center|right] label的文字对齐方式默认left
* @value left label 左侧显示
* @value center label 居中
* @value right label 右侧对齐
* @property {String } labelPosition = [top|left] label的文字的位置默认left
* @value top 顶部显示 label
* @value left 左侧显示 label
* @property {String } errorMessage 显示的错误提示内容如果为空字符串或者false则不显示错误信息
* @property {String } name 表单域的属性名,在使用校验规则时必填
*/
export default {
name: 'uniFormsItem',
props: {
// 自定义内容
custom: {
type: Boolean,
default: false
},
// 是否显示报错信息
showMessage: {
type: Boolean,
default: true
},
name: String,
required: Boolean,
validateTrigger: {
type: String,
default: ''
},
leftIcon: String,
iconColor: {
type: String,
default: '#606266'
},
label: String,
// 左边标题的宽度单位px
labelWidth: {
type: [Number, String],
default: ''
},
// 对齐方式left|center|right
labelAlign: {
type: String,
default: ''
},
// lable的位置可选为 left-左边top-上边
labelPosition: {
type: String,
default: ''
},
errorMessage: {
type: [String, Boolean],
default: ''
},
// 表单校验规则
rules: {
type: Array,
default() {
return [];
}
}
},
data() {
return {
errorTop: false,
errorBottom: false,
labelMarginBottom: '',
errorWidth: '',
errMsg: '',
val: '',
labelPos: '',
labelWid: '',
labelAli: '',
showMsg: 'undertext',
border: false,
isFirstBorder: false,
isArray: false,
arrayField: ''
};
},
computed: {
msg() {
return this.errorMessage || this.errMsg;
},
fieldStyle() {
let style = {};
if (this.labelPos == 'top') {
style.padding = '0 0';
this.labelMarginBottom = '6px';
}
if (this.labelPos == 'left' && this.msg !== false && this.msg != '') {
style.paddingBottom = '0px';
this.errorBottom = true;
this.errorTop = false;
} else if (this.labelPos == 'top' && this.msg !== false && this.msg != '') {
this.errorBottom = false;
this.errorTop = true;
} else {
// style.paddingBottom = ''
this.errorTop = false;
this.errorBottom = false;
}
return style;
},
// uni不支持在computed中写style.justifyContent = 'center'的形式,故用此方法
justifyContent() {
if (this.labelAli === 'left') return 'flex-start';
if (this.labelAli === 'center') return 'center';
if (this.labelAli === 'right') return 'flex-end';
},
labelLeft() {
return (this.labelPos === 'left' ? parseInt(this.labelWid) : 0) + 'rpx';
}
},
watch: {
validateTrigger(trigger) {
this.formTrigger = trigger;
}
},
created() {
this.form = this.getForm();
this.group = this.getForm('uniGroup');
this.formRules = [];
this.formTrigger = this.validateTrigger;
// 处理 name是否数组
if (this.name && this.name.indexOf('[') !== -1 && this.name.indexOf(']') !== -1) {
this.isArray = true;
this.arrayField = this.name;
// fix by mehaotian 修改不修改的情况,动态值不检验的问题
this.form.formData[this.name] = this.form._getValue(this.name, '');
}
},
mounted() {
if (this.form) {
this.form.childrens.push(this);
}
this.init();
},
// #ifndef VUE3
destroyed() {
if (this.__isUnmounted) return;
this.unInit();
},
// #endif
// #ifdef VUE3
unmounted() {
this.__isUnmounted = true;
this.unInit();
},
// #endif
methods: {
init() {
if (this.form) {
let {
formRules,
validator,
formData,
value,
labelPosition,
labelWidth,
labelAlign,
errShowType
} = this.form;
this.labelPos = this.labelPosition ? this.labelPosition : labelPosition;
if (this.label) {
this.labelWid = this.labelWidth ? this.labelWidth : labelWidth || 140;
} else {
this.labelWid = this.labelWidth ? this.labelWidth : labelWidth || 'auto';
}
if (this.labelWid && this.labelWid !== 'auto') {
this.labelWid += 'rpx';
}
this.labelAli = this.labelAlign ? this.labelAlign : labelAlign;
// 判断第一个 item
if (!this.form.isFirstBorder) {
this.form.isFirstBorder = true;
this.isFirstBorder = true;
}
// 判断 group 里的第一个 item
if (this.group) {
if (!this.group.isFirstBorder) {
this.group.isFirstBorder = true;
this.isFirstBorder = true;
}
}
this.border = this.form.border;
this.showMsg = errShowType;
let name = this.isArray ? this.arrayField : this.name;
if (!name) return;
if (formRules && this.rules.length > 0) {
if (!formRules[name]) {
formRules[name] = {
rules: this.rules
};
}
validator.updateSchema(formRules);
}
this.formRules = formRules[name] || {};
this.validator = validator;
} else {
this.labelPos = this.labelPosition || 'left';
this.labelWid = this.labelWidth || 130;
this.labelAli = this.labelAlign || 'left';
}
},
unInit() {
if (this.form) {
this.form.childrens.forEach((item, index) => {
if (item === this) {
this.form.childrens.splice(index, 1);
delete this.form.formData[item.name];
}
});
}
},
/**
* 获取父元素实例
*/
getForm(name = 'uniForms') {
let parent = this.$parent;
let parentName = parent.$options.name;
while (parentName !== name) {
parent = parent.$parent;
if (!parent) return false;
parentName = parent.$options.name;
}
return parent;
},
/**
* 移除该表单项的校验结果
*/
clearValidate() {
this.errMsg = '';
},
/**
* 子组件调用,如 easyinput
* @param {Object} value
*/
setValue(value) {
let name = this.isArray ? this.arrayField : this.name;
if (name) {
if (this.errMsg) this.errMsg = '';
// 给组件赋值
this.form.formData[name] = this.form._getValue(name, value);
if (!this.formRules || (typeof this.formRules && JSON.stringify(this.formRules) === '{}')) return;
this.triggerCheck(this.form._getValue(this.name, value));
}
},
/**
* 校验规则
* @param {Object} value
*/
async triggerCheck(value, formTrigger) {
let promise = null;
this.errMsg = '';
// fix by mehaotian 解决没有检验规则的情况下,抛出错误的问题
if (!this.validator || Object.keys(this.formRules).length === 0) return;
const isNoField = this.isRequired(this.formRules.rules || []);
let isTrigger = this.isTrigger(
this.formRules.validateTrigger,
this.validateTrigger,
this.form.validateTrigger
);
let result = null;
if (!!isTrigger || formTrigger) {
let name = this.isArray ? this.arrayField : this.name;
result = await this.validator.validateUpdate(
{
[name]: value
},
this.form.formData
);
}
// 判断是否必填,非必填,不填不校验,填写才校验
if (!isNoField && (value === undefined || value === '')) {
result = null;
}
const inputComp = this.form.inputChildrens.find(child => child.rename === this.name);
if ((isTrigger || formTrigger) && result && result.errorMessage) {
if (inputComp) {
inputComp.errMsg = result.errorMessage;
}
if (this.form.errShowType === 'toast') {
uni.showToast({
title: result.errorMessage || '校验错误',
icon: 'none'
});
}
if (this.form.errShowType === 'modal') {
uni.showModal({
title: '提示',
content: result.errorMessage || '校验错误'
});
}
} else {
if (inputComp) {
inputComp.errMsg = '';
}
}
this.errMsg = !result ? '' : result.errorMessage;
// 触发validate事件
this.form.validateCheck(result ? result : null);
// typeof callback === 'function' && callback(result ? result : null);
// if (promise) return promise
return result ? result : null;
},
/**
* 触发时机
* @param {Object} event
*/
isTrigger(rule, itemRlue, parentRule) {
let rl = true;
// bind submit
if (rule === 'submit' || !rule) {
if (rule === undefined) {
if (itemRlue !== 'bind') {
if (!itemRlue) {
return parentRule === 'bind' ? true : false;
}
return false;
}
return true;
}
return false;
}
return true;
},
// 是否有必填字段
isRequired(rules) {
let isNoField = false;
for (let i = 0; i < rules.length; i++) {
const ruleData = rules[i];
if (ruleData.required) {
isNoField = true;
break;
}
}
return isNoField;
}
}
};
</script>
<style lang="scss">
.uni-forms-item {
position: relative;
padding: 0px;
text-align: left;
color: #333;
font-size: 14px;
// margin-bottom: 22px;
}
.uni-forms-item__box {
position: relative;
}
.uni-forms-item__inner {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
// flex-direction: row;
// align-items: center;
padding-bottom: 22px;
// margin-bottom: 22px;
}
.is-direction-left {
flex-direction: row;
}
.is-direction-top {
flex-direction: column;
}
.uni-forms-item__label {
/* #ifndef APP-NVUE */
display: flex;
flex-shrink: 0;
box-sizing: border-box;
/* #endif */
flex-direction: row;
align-items: center;
width: 65px;
// line-height: 2;
// margin-top: 3px;
padding: 5px 0;
height: 72rpx;
// margin-right: 5px;
.label-text {
font-size: 28rpx;
color: #333333;
}
.label-seat {
margin-right: 5px;
}
}
.uni-forms-item__content {
/* #ifndef APP-NVUE */
width: 100%;
box-sizing: border-box;
min-height: 36px;
/* #endif */
flex: 1;
}
.label-icon {
margin-right: 5px;
margin-top: -1px;
}
// 必填
.is-required {
// color: $uni-color-error;
color: #dd524d;
font-weight: bold;
}
.uni-error-message {
position: absolute;
bottom: 0px;
left: 0;
text-align: left;
}
.uni-error-message-text {
line-height: 44rpx;
color: #dd524d;
font-size: 24rpx;
}
.uni-error-msg--boeder {
position: relative;
bottom: 0;
line-height: 22px;
}
.is-input-error-border {
border-color: #dd524d;
}
.uni-forms-item--border {
margin-bottom: 0;
padding: 10px 0;
border-top: 1px #eee solid;
.uni-forms-item__inner {
padding: 0;
}
}
.uni-forms-item-error {
// padding-bottom: 0;
}
.is-first-border {
/* #ifndef APP-NVUE */
border: none;
/* #endif */
/* #ifdef APP-NVUE */
border-width: 0;
/* #endif */
}
.uni-forms--no-padding {
padding: 0;
}
</style>