增加other分包页面
我的页面里增加跳转other分包跳转(仅在ios不是浏览器审核时展示)
This commit is contained in:
457
tuniao-ui/components/tn-form-item/tn-form-item.vue
Normal file
457
tuniao-ui/components/tn-form-item/tn-form-item.vue
Normal file
@@ -0,0 +1,457 @@
|
||||
<template>
|
||||
<view
|
||||
class="tn-form-item-class tn-form-item"
|
||||
:class="{
|
||||
'tn-border-solid-bottom': elBorderBottom,
|
||||
'tn-form-item__border-bottom--error': validateState === 'error' && showError('border-bottom')
|
||||
}"
|
||||
>
|
||||
<view
|
||||
class="tn-form-item__body"
|
||||
:style="{
|
||||
flexDirection: elLabelPosition == 'left' ? 'row' : 'column'
|
||||
}"
|
||||
>
|
||||
<!-- 处理微信小程序中设置属性的问题,不设置值的时候会变成true -->
|
||||
<view
|
||||
class="tn-form-item--left"
|
||||
:style="{
|
||||
width: wLabelWidth,
|
||||
flex: `0 0 ${wLabelWidth}`,
|
||||
marginBottom: elLabelPosition == 'left' ? 0 : '10rpx'
|
||||
}"
|
||||
>
|
||||
<!-- 块对齐 -->
|
||||
<view v-if="required || leftIcon || label" class="tn-form-item--left__content"
|
||||
:style="[leftContentStyle]"
|
||||
>
|
||||
<!-- nvue不支持伪元素before -->
|
||||
<view v-if="leftIcon" class="tn-form-item--left__content__icon">
|
||||
<view :class="[`tn-icon-${leftIcon}`]" :style="leftIconStyle"></view>
|
||||
</view>
|
||||
<!-- <view
|
||||
class="tn-form-item--left__content__label"
|
||||
:style="[elLabelStyle, {
|
||||
'justify-content': elLabelAlign === 'left' ? 'flex-satrt' : elLabelAlign === 'center' ? 'center' : 'flex-end'
|
||||
}]"
|
||||
>
|
||||
{{label}}
|
||||
</view> -->
|
||||
<view
|
||||
class="tn-form-item--left__content__label"
|
||||
:style="[elLabelStyle]"
|
||||
>
|
||||
{{label}}
|
||||
</view>
|
||||
<text v-if="required" class="tn-form-item--left__content--required">*</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="tn-form-item--right tn-flex">
|
||||
<view class="tn-form-item--right__content">
|
||||
<view class="tn-form-item--right__content__slot">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<view v-if="$slots.right || rightIcon" class="tn-form-item--right__content__icon tn-flex">
|
||||
<view v-if="rightIcon" :class="[`tn-icon-${rightIcon}`]" :style="rightIconStyle"></view>
|
||||
<slot name="right"></slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
v-if="validateState === 'error' && showError('message')"
|
||||
class="tn-form-item__message"
|
||||
:style="{
|
||||
paddingLeft: elLabelPosition === 'left' ? elLabelWidth + 'rpx' : '0'
|
||||
}"
|
||||
>
|
||||
{{validateMessage}}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Emitter from '../../libs/utils/emitter.js'
|
||||
import schema from '../../libs/utils/async-validator.js'
|
||||
// 去除警告信息
|
||||
schema.warning = function() {}
|
||||
|
||||
export default {
|
||||
mixins: [Emitter],
|
||||
name: 'tn-form-item',
|
||||
inject: {
|
||||
tnForm: {
|
||||
default() {
|
||||
return null
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
// label提示语
|
||||
label: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 绑定的值
|
||||
prop: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 是否显示表单域的下划线边框
|
||||
borderBottom: {
|
||||
type:Boolean,
|
||||
default: true
|
||||
},
|
||||
// label(标签名称)的位置
|
||||
// left - 左边
|
||||
// top - 上边
|
||||
labelPosition: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// label的宽度
|
||||
labelWidth: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
// label的对齐方式
|
||||
// left - 左对齐
|
||||
// top - 上对齐
|
||||
// right - 右对齐
|
||||
// bottom - 下对齐
|
||||
labelAlign: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// label 的样式
|
||||
labelStyle: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
// 左侧图标
|
||||
leftIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 右侧图标
|
||||
rightIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 左侧图标样式
|
||||
leftIconStyle: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
// 右侧图标样式
|
||||
rightIconStyle: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
// 是否显示必填项的*,不做校验用途
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 处理微信小程序label的宽度
|
||||
wLabelWidth() {
|
||||
// 如果用户设置label为空字符串(微信小程序空字符串最终会变成字符串的'true'),意味着要将label的位置宽度设置为auto
|
||||
return this.elLabelPosition === 'left' ? (this.label === 'true' || this.label === '' ? 'auto' : this.elLabelWidth + 'rpx') : '100%'
|
||||
},
|
||||
// 是否显示错误提示
|
||||
showError() {
|
||||
return type => {
|
||||
if (this.errorType.indexOf('none') >= 0) return false
|
||||
else if (this.errorType.indexOf(type) >= 0) return true
|
||||
else return false
|
||||
}
|
||||
},
|
||||
// label的宽度(默认值为90)
|
||||
elLabelWidth() {
|
||||
return this.labelWidth != 0 ? this.labelWidth : (this.parentData.labelWidth != 0 ? this.parentData.labelWidth : 90)
|
||||
},
|
||||
// label的样式
|
||||
elLabelStyle() {
|
||||
return Object.keys(this.labelStyle).length ? this.labelStyle : (Object.keys(this.parentData.labelStyle).length ? this.parentData.labelStyle : {})
|
||||
},
|
||||
// label显示位置
|
||||
elLabelPosition() {
|
||||
return this.labelPosition ? this.labelPosition : (this.parentData.labelPosition ? this.parentData.labelPosition : 'left')
|
||||
},
|
||||
// label对齐方式
|
||||
elLabelAlign() {
|
||||
return this.labelAlign ? this.labelAlign : (this.parentData.labelAlign ? this.parentData.labelAlign : 'left')
|
||||
},
|
||||
// label下划线
|
||||
elBorderBottom() {
|
||||
return this.borderBottom !== '' ? this.borderBottom : (this.parentData.borderBottom !== '' ? this.parentData.borderBottom : true)
|
||||
},
|
||||
leftContentStyle() {
|
||||
let style = {}
|
||||
if (this.elLabelPosition === 'left') {
|
||||
switch(this.elLabelAlign) {
|
||||
case 'left':
|
||||
style.justifyContent = 'flex-start'
|
||||
break
|
||||
case 'center':
|
||||
style.justifyContent = 'center'
|
||||
break
|
||||
default:
|
||||
style.justifyContent = 'flex-end'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return style
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 默认值
|
||||
initialValue: '',
|
||||
// 是否校验成功
|
||||
validateState: '',
|
||||
// 校验失败提示信息
|
||||
validateMessage: '',
|
||||
// 错误的提示方式(参考form组件)
|
||||
errorType: ['message'],
|
||||
// 当前子组件输入的值
|
||||
fieldValue: '',
|
||||
// 父组件的参数
|
||||
// 由于再computed中无法得知this.parent的变化,所以放在data中
|
||||
parentData: {
|
||||
borderBottom: true,
|
||||
labelWidth: 90,
|
||||
labelPosition: 'left',
|
||||
labelAlign: 'left',
|
||||
labelStyle: {},
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
validateState(val) {
|
||||
this.broadcastInputError()
|
||||
},
|
||||
"tnForm.errorType"(val) {
|
||||
this.errorType = val
|
||||
this.broadcastInputError()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 组件创建完成后,保存当前实例到form组件中
|
||||
// 支付宝、头条小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环应用\
|
||||
this.parent = this.$t.$parent.call(this, 'tn-form')
|
||||
if (this.parent) {
|
||||
// 遍历parentData属性,将parent中同名的属性赋值给parentData
|
||||
Object.keys(this.parentData).map(key => {
|
||||
this.parentData[key] = this.parent[key]
|
||||
})
|
||||
// 如果没有传入prop或者tnForm为空(单独使用form-item组件的时候),就不进行校验
|
||||
if (this.prop) {
|
||||
// 将本实例添加到父组件中
|
||||
this.parent.fields.push(this)
|
||||
this.errorType = this.parent.errorType
|
||||
// 设置初始值
|
||||
this.initialValue = this.fieldValue
|
||||
// 添加表单校验,这里必须要写在$nextTick中,因为tn-form的rules是通过ref手动传入的
|
||||
// 不在$nextTick中的话,可能会造成执行此处代码时,父组件还没通过ref把规则给tn-form,导致规则为空
|
||||
this.$nextTick(() => {
|
||||
this.setRules()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
// 组件销毁前,将实例从tn-form的缓存中移除
|
||||
// 如果当前没有prop的话表示当前不进行删除
|
||||
if (this.parent && this.prop) {
|
||||
this.parent.fields.map((item, index) => {
|
||||
if (item === this) this.parent.fields.splice(index, 1)
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 向input组件发出错误事件
|
||||
broadcastInputError() {
|
||||
this.broadcast('tn-input', 'on-form-item-error', this.validateState === 'error' && this.showError('border'))
|
||||
},
|
||||
// 设置校验规则
|
||||
setRules() {
|
||||
let that = this
|
||||
// 从父组件tn-form拿到当前tn-form-item需要验证 的规则
|
||||
// let rules = this.getRules()
|
||||
// if (rules.length) {
|
||||
// this.isRequired = rules.some(rule => {
|
||||
// // 如果有必填项,就返回,没有的话,就是undefined
|
||||
// return rule.required
|
||||
// })
|
||||
// }
|
||||
|
||||
// blur事件
|
||||
this.$on('on-form-blur', that.onFieldBlur)
|
||||
// change事件
|
||||
this.$on('on-form-change', that.onFieldChange)
|
||||
},
|
||||
// 从form的rules属性中取出当前form-item的校验规则
|
||||
getRules() {
|
||||
let rules = this.parent.rules
|
||||
rules = rules ? rules[this.prop] : []
|
||||
|
||||
// 返回数值形式的值
|
||||
return [].concat(rules || [])
|
||||
},
|
||||
// blur事件时进行表单认证
|
||||
onFieldBlur() {
|
||||
this.validation('blur')
|
||||
},
|
||||
// change事件时进行表单认证
|
||||
onFieldChange() {
|
||||
this.validation('change')
|
||||
},
|
||||
// 过滤出符合要求的rule规则
|
||||
getFilterRule(triggerType = '') {
|
||||
let rules = this.getRules()
|
||||
// 整体验证表单时,triggerType为空字符串,此时返回所有规则进行验证
|
||||
if (!triggerType) return rules
|
||||
// 某些场景可能的判断规则,可能不存在trigger属性,故先判断是否存在此属性
|
||||
// 历遍判断规则是否有对应的事件,比如blur,change触发等的事件
|
||||
// 使用indexOf判断,是因为某些时候设置的验证规则的trigger属性可能为多个,比如['blur','change']
|
||||
return rules.filter(rule => rule.trigger && rule.trigger.indexOf(triggerType) !== -1)
|
||||
},
|
||||
// 校验数据
|
||||
validation(trigger, callback = ()=>{}) {
|
||||
// 校验之前先获取需要校验的值
|
||||
this.fieldValue = this.parent.model[this.prop]
|
||||
// blur和change是否有当前方式的校验规则
|
||||
let rules = this.getFilterRule(trigger)
|
||||
// 判断是否有验证规则,如果没有规则,也调用回调方法,否则父组件tn-form会因为
|
||||
// 对count变量的统计错误而无法进入上一层的回调
|
||||
if (!rules || rules.length === 0) {
|
||||
return callback('')
|
||||
}
|
||||
// 设置当前为校验中
|
||||
this.validateState = 'validating'
|
||||
// 调用async-validator的方法
|
||||
let validator = new schema({
|
||||
[this.prop]: rules
|
||||
})
|
||||
validator.validate({
|
||||
[this.prop]: this.fieldValue
|
||||
}, {
|
||||
firstFields: true
|
||||
}, (errors, fields) => {
|
||||
// 记录状态和报错信息
|
||||
this.validateState = !errors ? 'success' : 'error'
|
||||
this.validateMessage = errors ? errors[0].message : ''
|
||||
|
||||
callback(this.validateMessage)
|
||||
})
|
||||
},
|
||||
|
||||
// 清空当前item信息
|
||||
resetField() {
|
||||
this.parent.model[this.prop] = this.initialValue
|
||||
// 清空错误标记
|
||||
this.validateState = 'success'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tn-form-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20rpx 0;
|
||||
font-size: 28rpx;
|
||||
color: $tn-font-color;
|
||||
box-sizing: border-box;
|
||||
line-height: $tn-form-item-height;
|
||||
|
||||
&__border-bottom--error:after {
|
||||
border-color: $tn-color-red;
|
||||
}
|
||||
|
||||
&__body {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
&--left {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
&__content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
padding-right: 18rpx;
|
||||
flex: 1;
|
||||
|
||||
&--required {
|
||||
position: relative;
|
||||
right: 0;
|
||||
vertical-align: middle;
|
||||
color: $tn-color-red;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
color: $tn-font-sub-color;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
&__label {
|
||||
// display: flex;
|
||||
// flex-direction: row;
|
||||
// align-items: center;
|
||||
// flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&--right {
|
||||
flex: 1;
|
||||
|
||||
&__content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
|
||||
&__slot {
|
||||
flex: 1;
|
||||
/* #ifndef MP */
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
&__icon {
|
||||
margin-left: 10rpx;
|
||||
color: $tn-font-sub-color;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__message {
|
||||
font-size: 24rpx;
|
||||
line-height: 24rpx;
|
||||
color: $tn-color-red;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user