Commit 7d0c07f9 authored by wlxuqu's avatar wlxuqu

Merge branch 'yiruiwen' into dev

parents 5017be53 aa4d501e
......@@ -9,7 +9,7 @@
uView UI,是[uni-app](https://uniapp.dcloud.io/)生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水
### **欢迎加群交流反馈:1129077272**
## [点击加群交流反馈:1129077272](https://qm.qq.com/cgi-bin/qm/qr?k=1FfucLpozYbnb7FWo_KsqAdEi1mE3Qrf&jump_from=webapi)
## 特性
......
......@@ -2,7 +2,7 @@
"name" : "uView",
"appid" : "__UNI__60F4B81",
"description" : "多平台快速开发的UI框架",
"versionName" : "1.6.6",
"versionName" : "1.6.8",
"versionCode" : "100",
"transformPx" : false,
"app-plus" : {
......
......@@ -2,14 +2,14 @@
"easycom": {
"^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
},
// "condition": { //模式配置,仅开发期间生效
// "current": 0, //当前激活的模式(list 的索引项)
// "list": [{
// "name": "test", //模式名称
// "path": "pages/componentsC/test/index", //启动页面,必选
// "query": "id=1&name=2" //启动参数,在页面的onLoad函数里面得到
// }]
// },
"condition": { //模式配置,仅开发期间生效
"current": 0, //当前激活的模式(list 的索引项)
"list": [{
"name": "test", //模式名称
"path": "pages/componentsC/test/index", //启动页面,必选
"query": "id=1&name=2" //启动参数,在页面的onLoad函数里面得到
}]
},
"pages": [
// 演示-组件
{
......
......@@ -23,7 +23,7 @@
</u-form-item>
<u-form-item :label-position="labelPosition" label="结算方式" prop="payType" label-width="150">
<u-radio-group v-model="radio" @change="radioGroupChange" :width="radioCheckWidth" :wrap="radioCheckWrap">
<u-radio shape="circle" v-model="item.checked" v-for="(item, index) in radioList" :key="index" :name="item.name">{{ item.name }}</u-radio>
<u-radio shape="circle" v-for="(item, index) in radioList" :key="index" :name="item.name">{{ item.name }}</u-radio>
</u-radio-group>
</u-form-item>
<u-form-item :label-position="labelPosition" label="所在地区" prop="region" label-width="150">
......@@ -44,7 +44,7 @@
<u-switch v-model="model.remember" slot="right"></u-switch>
</u-form-item>
<u-form-item :label-position="labelPosition" label="上传图片" prop="photo" label-width="150">
<u-upload width="160"></u-upload>
<u-upload width="160" height="160"></u-upload>
</u-form-item>
</u-form>
<view class="agreement">
......
......@@ -14,7 +14,7 @@
:percent="item.progress"></u-line-progress>
</view>
</view>
<u-upload ref="uUpload" :custom-btn="customBtn" :show-upload-list="showUploadList" :action="action" :auto-upload="autoUpload" :file-list="fileList"
<u-upload :before-remove="beforeRemove" ref="uUpload" :custom-btn="customBtn" :show-upload-list="showUploadList" :action="action" :auto-upload="autoUpload" :file-list="fileList"
:show-progress="showProgress" :deletable="deletable" :max-count="maxCount" @on-list-change="onListChange">
<view v-if="customBtn" slot="addBtn" class="slot-btn" hover-class="slot-btn__hover" hover-stay-time="150">
<u-icon name="photo" size="60" :color="$u.color['lightColor']"></u-icon>
......@@ -140,6 +140,9 @@
// console.log('onListChange', lists);
this.lists = lists;
},
beforeRemove(index, lists) {
return true;
}
}
}
</script>
......
......@@ -35,7 +35,8 @@
text: '朱颜辞镜花辞树',
disabled: true
}, {
text: '正是江南好风景'
text: '正是江南好风景',
subText: '春江水暖鸭先知'
}, {
text: '落花时节又逢君'
}],
......
<template>
<view class="">
<u-button @click="show = true;">打开弹窗</u-button>
<u-popup mode="bottom" v-model="show">
<view class="content">
<u-image class="image" width="500rpx" height="300rpx" src="https://cdn.uviewui.com/uview/example/fade.jpg"></u-image>
<view class="confrim-btn">
<u-button @click="show = false;">确定</u-button>
<view class="pageMain">
<view class="title">完善个人信息</view>
<view class="info">为了给您精准的推荐,请完善以下信息
</view>
<view class="my-form">
<u-form :model="form" ref="formRef">
<view class="my-form-item" @tap="selectSchoolTap">
<view class="border padding position">
<u-icon name="dingwei" custom-prefix="iconfont" color="#A0A0A0"></u-icon>
<view class="collegeSelectValue">{{selectSchool.orgName}}{{selectSchool.regionName?(''+selectSchool.regionName+''):''}}</view>
<u-icon name="jiantou8" custom-prefix="iconfont" color="#A0A0A0"></u-icon>
</view>
</view>
<view v-for="(formItem,i) in needKeyArr">
<view class="my-form-item" v-if="formItem.name=='name'">
<u-form-item prop="name" :label-style="{display:'none'}" :border-bottom="false">
<view class="border padding">
<u-input class="my-input" v-model="form.name" placeholder="请输入姓名" />
</view>
</u-form-item>
</view>
<view class="my-form-item" v-else-if="formItem.name=='idNumber'">
<u-form-item prop="idNumber" label-width="0" :border-bottom="false">
<view class="border padding">
<u-input v-model="form.idNumber" placeholder="请输入身份证" />
</view>
</u-form-item>
</view>
<view class="my-form-item" v-else-if="formItem.name=='password'">
<u-form-item prop="password" label-width="0" :border-bottom="false">
<view class="border padding">
<u-input v-model="form.password" placeholder="请输入密码" />
</view>
</u-form-item>
</view>
<view class="my-form-item" v-else-if="formItem.name=='idNumberEncryption'">
<u-form-item prop="idNumberEncryption" label-width="0" :border-bottom="false">
<view class="border padding">
<u-input v-model="form.idNumberEncryption" placeholder="请输入身份证后六位" />
</view>
</u-form-item>
</view>
<view class="my-form-item" v-else-if="formItem.name=='jobNumber'">
<u-form-item prop="jobNumber" label-width="0" :border-bottom="false">
<view class="border padding">
<u-input v-model="form.jobNumber" placeholder="请输入学工号" />
</view>
</u-form-item>
</view>
<view class="my-form-item" v-else-if="formItem.name=='sex'">
<u-radio-group v-model="form.sex">
<u-radio v-for="(item, index) in sexList" :key="index" :name="item.name" :disabled="item.disabled" shape="circle"
@change="radioChange">
{{item.label}}
</u-radio>
</u-radio-group>
</view>
</view>
</view>
</u-popup>
</u-form>
</view>
<view class="submitButton" @tap="submitTap">
<text class="buttonText">确定</text>
</view>
<!-- 提交新建校区模态框 -->
<u-modal title="完善该校区信息" content="确认以上信息无误" v-model="collegeNewBuildMotalShow" @confirm="subNewBuildCollegeForm"
:show-cancel-button="true"></u-modal>
<view class="">
</view>
</view>
</template>
......@@ -17,21 +89,298 @@
export default {
data() {
return {
show: true
value: '',
// 性别列表
sexList: [{
label: '',
name: 'MALE',
disabled: false
},
{
label: '',
name: 'FEMALE',
disabled: false
}
],
//新建校区模态框显示
collegeNewBuildMotalShow: false,
// 新建校区传递过来的参数
selectSchool: {
orgId: 0,
orgName: "",
regionId: 0,
regionName: ""
},
// 需要提供的值数组
needKeyArr: [
],
// 表单数据
form: {
name: '',
password: '',
idNumber: '',
idNumberEncryption: '',
jobNumber: '',
sex: 'MALE'
},
// 表单规则
formRules: {
name: [{
required: true,
message: '请输入真实姓名',
trigger: ['blur']
}, {
pattern: /^[\u4E00-\u9FA5\uf900-\ufa2d·s]{1,20}$/,
message: '请输入中文',
trigger: ['blur']
}],
phone: [{
required: true,
message: '请输入手机号',
trigger: ['blur']
}, {
pattern: /^1[23456789]\d{9}$/,
message: '请输入正确手机号',
trigger: ['blur']
}],
password: [{
required: true,
message: '请输入密码',
trigger: ['blur']
}, ],
// todo 身份证号验证
idNumber: [{
required: true,
message: '请输入身份证号',
trigger: ['blur']
}, {
pattern: /^(\d{18,18}|\d{17,17}x|\d{17,17}X)$/,
message: '请输入正确身份证号码',
trigger: ['blur']
}],
// todo 加密身份证=====
idNumberEncryption: [{
required: true,
message: '请输入身份证号后六位',
trigger: ['blur']
}, {
pattern: /^(\d{6,6}|(\d{5}x))$/i,
message: '请输入正确身份证号码后六位',
trigger: ['blur']
}],
jobNumber: [{
required: true,
message: '请输入学工号',
trigger: ['blur']
}]
},
countdownTime: 0,
}
}
},
methods: {
// 学校选择点击时
selectSchoolTap() {
uni.navigateBack({})
},
// 获取验证码
getphonecode() {
if (this.countdownTime > 0) {
return;
}
this.countdownTime = 5
let intervalId = setInterval(() => {
if (this.countdownTime <= 0) {
clearTimeout(intervalId)
return;
}
this.countdownTime -= 1;
}, 1000)
},
submitTap() {
if (!this.needKeyArr || this.needKeyArr.length == 0) {
this.collegeNewBuildMotalShow = true;
return;
}
this.$refs.formRef.validate((v) => {
if (v) {
this.collegeNewBuildMotalShow = true;
}
})
},
// 点击模态框确定按钮提交新建校区表单信息
subNewBuildCollegeForm() {
uni.showToast({
title: '点击了确定',
icon: 'none'
})
return;
try {
let newObj = {}
this.needKeyArr.map(v => v.name).forEach(v => {
newObj[v] = this.form[v]
})
let school = {
orgId: parseInt(this.selectSchool.orgId),
orgRegionId: parseInt(this.selectSchool.regionId),
}
this.$u.$api.purchaser_perfection({ ...school,
...newObj
}).then(d => {
uni.reLaunch({
url: '/pages/home/index'
})
})
} catch (e) {
uni.showToast({
title: '有异常:' + JSON.stringify(e),
icon: 'none'
})
}
},
// 单选按钮点击时触发
radioChange(e) {
this.form.sex = e
}
},
onLoad(params) {
if (params) {
this.selectSchool = Object.keys(params).reduce((obj, curr) => {
if (!params[curr] || params[curr] == 'null') {
obj[curr] = ''
} else {
obj[curr] = params[curr]
}
return obj
}, {})
this.$u.$api.gate_orgCheckField({
orgId: params.orgId
}).then(d => {
if (!d.find(v => v.name == 'name')) {
d.push({
name: 'name',
notes: '姓名'
})
}
this.needKeyArr = d;
})
}
},
onReady() {
// 官方要求,设置表单验证规则
if (this.$refs.formRef) {
this.$refs.formRef.setRules(this.formRules);
}
},
}
</script>
<style lang="scss" scoped>
.content {
padding: 24rpx;
text-align: center;
position: relative;
// 本页主体
.pageMain {
padding: 65rpx;
min-height: 100vh;
box-sizing: border-box;
// background-image: url(@/static/common/img/userLogin.jpg);
}
.image {
position: absolute;
top: -200rpx;
// 大标题
.title {
font-weight: bold;
margin-top: 80rpx;
font-size: 52rpx;
color: #2A2A2A;
line-height: 52px;
}
// 标题下描述信息
.info {
font-size: 28rpx;
color: #6A6A6A;
margin-bottom: 100rpx;
}
// 表单信息
.my-form {
.my-form-item {
// 添加边框
.border {
border: 2rpx solid #E2E2E2;
border-radius: 12rpx;
display: flex;
width: 100%;
box-sizing: border-box;
.padding {
max-width: 330rpx;
}
}
// 添加边距
.padding {
padding: 20rpx 50rpx;
}
.my-input {
width: 100%;
}
// 获取短信验证码
.getphonecode {
min-width: 100rpx;
border-left: 2rpx solid #E2E2E2;
padding: 20rpx 20rpx;
color: #6A6A6A;
}
.getphonecode.hasTime {
color: #558BD3;
}
// 错误警告信息
// .u-form-item__message {
// font-size: 28rpx;
// margin-left: 50rpx !important;
// }
}
}
// 选择学校按钮行
.position {
display: flex;
align-items: center;
line-height: 70rpx;
// 定位、下拉-字体图标
.iconfont {
// color: #A0A0A0;
// padding-right: 20rpx;
}
// 文本区域
.collegeSelectValue {
flex: 1;
padding-left: 20rpx;
}
}
// 确定按钮
.submitButton {
background-color: #4990EE;
border: 1rpx solid #AEAEAE;
border-radius: 12rpx;
width: 100%;
padding: 25rpx 0;
text-align: center;
margin-top: 70rpx;
// 按钮文本
.buttonText {
font-size: 32rpx;
color: #FFFFFF;
}
}
</style>
\ No newline at end of file
</style>
......@@ -9,11 +9,12 @@
@touchmove.stop.prevent
@tap="itemClick(index)"
:style="[itemStyle(index)]"
class="u-action-sheet-item"
class="u-action-sheet-item u-line-1"
:class="[index < list.length - 1 ? 'u-border-bottom' : '']"
:hover-stay-time="150"
>
{{item.text}}
<text>{{item.text}}</text>
<text class="u-action-sheet-item__subtext u-line-1" v-if="item.subText">{{item.subText}}</text>
</view>
</block>
<view class="u-gab" v-if="cancelBtn">
......@@ -167,8 +168,15 @@
line-height: 1;
justify-content: center;
align-items: center;
font-size: 34rpx;
font-size: 32rpx;
padding: 34rpx 0;
flex-direction: column;
}
.u-action-sheet-item__subtext {
font-size: 24rpx;
color: $u-tips-color;
margin-top: 20rpx;
}
.u-gab {
......
......@@ -149,6 +149,7 @@
line-height: 24rpx;
padding: 4rpx 8rpx;
border-radius: 100rpx;
z-index: 9;
&--bg--primary {
background-color: $u-type-primary;
......
......@@ -42,10 +42,10 @@
</template>
<script>
import Emitter from '../../libs/util/emitter.js';
import schema from '../../libs/util/async-validator';
// 去除警告信息
schema.warning = function(){};
import Emitter from '../../libs/util/emitter.js';
import schema from '../../libs/util/async-validator';
// 去除警告信息
schema.warning = function() {};
/**
* form-item 表单item
......@@ -66,257 +66,283 @@ schema.warning = function(){};
* @example <u-form-item label="姓名"><u-input v-model="form.name" /></u-form-item>
*/
export default {
name: 'u-form-item',
mixins: [Emitter],
inject: {
uForm: {
default() {
return null
}
}
},
props: {
// input的label提示语
label: {
type: String,
default: ''
},
// 绑定的值
prop: {
type: String,
default: ''
},
// 是否显示表单域的下划线边框
borderBottom: {
type: [String, Boolean],
default: ''
},
// label的位置,left-左边,top-上边
labelPosition: {
type: String,
default: ''
},
// label的宽度,单位rpx
labelWidth: {
type: [String, Number],
default: ''
},
// lable的样式,对象形式
labelStyle: {
type: Object,
default() {
return {}
}
},
// lable字体的对齐方式
labelAlign: {
type: String,
default: ''
},
// 右侧图标
rightIcon: {
type: String,
default: ''
},
// 左侧图标
leftIcon: {
type: String,
default: ''
},
// 左侧图标的样式
leftIconStyle: {
type: Object,
default() {
return {}
export default {
name: 'u-form-item',
mixins: [Emitter],
inject: {
uForm: {
default () {
return null
}
}
},
// 左侧图标的样式
rightIconStyle: {
type: Object,
default() {
return {}
props: {
// input的label提示语
label: {
type: String,
default: ''
},
// 绑定的值
prop: {
type: String,
default: ''
},
// 是否显示表单域的下划线边框
borderBottom: {
type: [String, Boolean],
default: ''
},
// label的位置,left-左边,top-上边
labelPosition: {
type: String,
default: ''
},
// label的宽度,单位rpx
labelWidth: {
type: [String, Number],
default: ''
},
// lable的样式,对象形式
labelStyle: {
type: Object,
default () {
return {}
}
},
// lable字体的对齐方式
labelAlign: {
type: String,
default: ''
},
// 右侧图标
rightIcon: {
type: String,
default: ''
},
// 左侧图标
leftIcon: {
type: String,
default: ''
},
// 左侧图标的样式
leftIconStyle: {
type: Object,
default () {
return {}
}
},
// 左侧图标的样式
rightIconStyle: {
type: Object,
default () {
return {}
}
},
// 是否显示左边的必填星号,只作显示用,具体校验必填的逻辑,请在rules中配置
required: {
type: Boolean,
default: false
}
},
// 是否显示左边的必填星号,只作显示用,具体校验必填的逻辑,请在rules中配置
required: {
type: Boolean,
default: false
}
},
data() {
return {
initialValue: '', // 存储的默认值
// isRequired: false, // 是否必填,由于人性化考虑,必填"*"号通过props的required配置,不再通过rules的规则自动生成
validateState: '', // 是否校验成功
validateMessage: '' ,// 校验失败的提示语
// 有错误时的提示方式,message-提示信息,border-如果input设置了边框,变成呈红色,
errorType: ['message'],
fieldValue: '', // 获取当前子组件input的输入的值
};
},
watch: {
validateState(val) {
this.broadcastInputError();
},
// 监听u-form组件的errorType的变化
"uForm.errorType"(val) {
this.errorType = val;
this.broadcastInputError();
data() {
return {
initialValue: '', // 存储的默认值
// isRequired: false, // 是否必填,由于人性化考虑,必填"*"号通过props的required配置,不再通过rules的规则自动生成
validateState: '', // 是否校验成功
validateMessage: '', // 校验失败的提示语
// 有错误时的提示方式,message-提示信息,border-如果input设置了边框,变成呈红色,
errorType: ['message'],
fieldValue: '', // 获取当前子组件input的输入的值
// 父组件的参数,在computed计算中,无法得知this.parent发生变化,故将父组件的参数值,放到data中
parentData: {
borderBottom: true,
labelWidth: 90,
labelPosition: 'left',
labelStyle: {},
labelAlign: 'left',
}
};
},
},
computed: {
// 计算后的label宽度,由于需要多个判断,故放到computed中
uLabelWidth() {
// 如果用户设置label为空字符串(微信小程序空字符串最终会变成字符串的'true'),意味着要将label的位置宽度设置为auto
return this.elLabelPosition == 'left' ? (this.label === 'true' || this.label === '' ? 'auto' : this.$u.addUnit(this.elLabelWidth)) : '100%';
watch: {
validateState(val) {
this.broadcastInputError();
},
// 监听u-form组件的errorType的变化
"uForm.errorType"(val) {
this.errorType = val;
this.broadcastInputError();
},
},
showError() {
return type => {
// 如果errorType数组中含有none,或者toast提示类型
if(this.errorType.indexOf('none') >= 0) return false;
else if(this.errorType.indexOf(type) >= 0) return true;
else return false;
computed: {
// 计算后的label宽度,由于需要多个判断,故放到computed中
uLabelWidth() {
// 如果用户设置label为空字符串(微信小程序空字符串最终会变成字符串的'true'),意味着要将label的位置宽度设置为auto
return this.elLabelPosition == 'left' ? (this.label === 'true' || this.label === '' ? 'auto' : this.$u.addUnit(this
.elLabelWidth)) : '100%';
},
showError() {
return type => {
// 如果errorType数组中含有none,或者toast提示类型
if (this.errorType.indexOf('none') >= 0) return false;
else if (this.errorType.indexOf(type) >= 0) return true;
else return false;
}
},
// label的宽度
elLabelWidth() {
// label默认宽度为90,优先使用本组件的值,如果没有(如果设置为0,也算是配置了值,依然起效),则用u-form的值
return (this.labelWidth != 0 || this.labelWidth != '') ? this.labelWidth : (this.parentData.labelWidth ? this.parentData
.labelWidth :
90);
},
// label的样式
elLabelStyle() {
return Object.keys(this.labelStyle).length ? this.labelStyle : (this.parentData.labelStyle ? 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() {
// 子组件的borderBottom默认为空字符串,如果不等于空字符串,意味着子组件设置了值,优先使用子组件的值
return this.borderBottom !== '' ? this.borderBottom : this.parentData.borderBottom ? this.parentData.borderBottom :
true;
}
},
// label的宽度
elLabelWidth() {
// label默认宽度为90,优先使用本组件的值,如果没有(如果设置为0,也算是配置了值,依然起效),则用u-form的值
return (this.labelWidth != 0 || this.labelWidth != '') ? this.labelWidth : (this.parent ? this.parent.labelWidth : 90);
},
// label的样式
elLabelStyle() {
return Object.keys(this.labelStyle).length ? this.labelStyle : (this.parent ? this.parent.labelStyle : {});
},
// label的位置,左侧或者上方
elLabelPosition() {
return this.labelPosition ? this.labelPosition : (this.parent ? this.parent.labelPosition : 'left');
},
// label的对齐方式
elLabelAlign() {
return this.labelAlign ? this.labelAlign : (this.parent ? this.parent.labelAlign : 'left');
},
// label的下划线
elBorderBottom() {
// 子组件的borderBottom默认为空字符串,如果不等于空字符串,意味着子组件设置了值,优先使用子组件的值
return this.borderBottom !== '' ? this.borderBottom : this.parent ? this.parent.borderBottom : true;
}
},
methods: {
broadcastInputError() {
// 子组件发出事件,第三个参数为true或者false,true代表有错误
this.broadcast('u-input', 'on-form-item-error', this.validateState === 'error' && this.showError('border'));
},
// 判断是否需要required校验
setRules() {
let that = this;
// 由于人性化考虑,必填"*"号通过props的required配置,不再通过rules的规则自动生成
// 从父组件u-form拿到当前u-form-item需要验证 的规则
// let rules = this.getRules();
// if (rules.length) {
// this.isRequired = rules.some(rule => {
// // 如果有必填项,就返回,没有的话,就是undefined
// return rule.required;
// });
// }
methods: {
broadcastInputError() {
// 子组件发出事件,第三个参数为true或者false,true代表有错误
this.broadcast('u-input', 'on-form-item-error', this.validateState === 'error' && this.showError('border'));
},
// 判断是否需要required校验
setRules() {
let that = this;
// 由于人性化考虑,必填"*"号通过props的required配置,不再通过rules的规则自动生成
// 从父组件u-form拿到当前u-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);
},
// blur事件
this.$on('on-form-blur', that.onFieldBlur);
// change事件
this.$on('on-form-change', that.onFieldChange);
},
// 从u-form的rules属性中,取出当前u-form-item的校验规则
getRules() {
// 父组件的所有规则
let rules = this.parent.rules;
rules = rules ? rules[this.prop] : [];
// 保证返回的是一个数组形式
return [].concat(rules || []);
},
// 从u-form的rules属性中,取出当前u-form-item的校验规则
getRules() {
// 父组件的所有规则
let rules = this.parent.rules;
rules = rules ? rules[this.prop] : [];
// 保证返回的是一个数组形式
return [].concat(rules || []);
},
// blur事件时进行表单校验
onFieldBlur() {
this.validation('blur');
},
// blur事件时进行表单校验
onFieldBlur() {
this.validation('blur');
},
// change事件进行表单校验
onFieldChange() {
this.validation('change');
},
// change事件进行表单校验
onFieldChange() {
this.validation('change');
},
// 过滤出符合要求的rule规则
getFilteredRule(triggerType = '') {
let rules = this.getRules();
// 整体验证表单时,triggerType为空字符串,此时返回所有规则进行验证
if(!triggerType) return rules;
// 历遍判断规则是否有对应的事件,比如blur,change触发等的事件
// 使用indexOf判断,是因为某些时候设置的验证规则的trigger属性可能为多个,比如['blur','change']
// 某些场景可能的判断规则,可能不存在trigger属性,故先判断是否存在此属性
return rules.filter(res => res.trigger && res.trigger.indexOf(triggerType) !== -1);
},
// 过滤出符合要求的rule规则
getFilteredRule(triggerType = '') {
let rules = this.getRules();
// 整体验证表单时,triggerType为空字符串,此时返回所有规则进行验证
if (!triggerType) return rules;
// 历遍判断规则是否有对应的事件,比如blur,change触发等的事件
// 使用indexOf判断,是因为某些时候设置的验证规则的trigger属性可能为多个,比如['blur','change']
// 某些场景可能的判断规则,可能不存在trigger属性,故先判断是否存在此属性
return rules.filter(res => res.trigger && res.trigger.indexOf(triggerType) !== -1);
},
// 校验数据
validation(trigger, callback = () => {}) {
// 检验之间,先获取需要校验的值
this.fieldValue = this.parent.model[this.prop];
// blur和change是否有当前方式的校验规则
let rules = this.getFilteredRule(trigger);
// 判断是否有验证规则,如果没有规则,也调用回调方法,否则父组件u-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);
});
},
// 校验数据
validation(trigger, callback = () => {}) {
// 检验之间,先获取需要校验的值
this.fieldValue = this.parent.model[this.prop];
// blur和change是否有当前方式的校验规则
let rules = this.getFilteredRule(trigger);
// 判断是否有验证规则,如果没有规则,也调用回调方法,否则父组件u-form会因为
// 对count变量的统计错误而无法进入上一层的回调
if (!rules || rules.length === 0) {
return callback('');
// 清空当前的u-form-item
resetField() {
this.parent.model[this.prop] = this.initialValue;
// 设置为`success`状态,只是为了清空错误标记
this.validateState = 'success';
}
// 设置当前的装填,标识为校验中
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);
});
},
// 清空当前的u-form-item
resetField() {
this.parent.model[this.prop] = this.initialValue;
// 设置为`success`状态,只是为了清空错误标记
this.validateState = 'success';
}
},
// 组件创建完成时,将当前实例保存到u-form中
mounted() {
// 支付宝、头条小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环应用
this.parent = this.$u.$parent.call(this, 'u-form');
// 如果没有传入prop,或者uForm为空(如果u-form-input单独使用,就不会有uForm注入),就不进行校验
if (this.prop || this.parent) {
// 将本实例添加到父组件中
this.parent.fields.push(this);
this.errorType = this.parent.errorType;
// 设置初始值
this.initialValue = this.fieldValue;
// 添加表单校验,这里必须要写在$nextTick中,因为u-form的rules是通过ref手动传入的
// 不在$nextTick中的话,可能会造成执行此处代码时,父组件还没通过ref把规则给u-form,导致规则为空
this.$nextTick(() =>{
this.setRules();
})
}
},
// 组件创建完成时,将当前实例保存到u-form中
mounted() {
// 支付宝、头条小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环应用
this.parent = this.$u.$parent.call(this, 'u-form');
if (this.parent) {
// 历遍parentData中的属性,将parent中的同名属性赋值给parentData
Object.keys(this.parentData).map(key => {
this.parentData[key] = this.parent[key];
});
// 如果没有传入prop,或者uForm为空(如果u-form-input单独使用,就不会有uForm注入),就不进行校验
if (this.prop) {
// 将本实例添加到父组件中
this.parent.fields.push(this);
this.errorType = this.parent.errorType;
// 设置初始值
this.initialValue = this.fieldValue;
// 添加表单校验,这里必须要写在$nextTick中,因为u-form的rules是通过ref手动传入的
// 不在$nextTick中的话,可能会造成执行此处代码时,父组件还没通过ref把规则给u-form,导致规则为空
this.$nextTick(() => {
this.setRules();
})
}
}
},
// 组件销毁前,将实例从u-form的缓存中移除
beforeDestroy() {
// 如果当前没有prop的话表示当前不要进行删除(因为没有注入)
if(this.parent && this.prop) {
this.parent.fields.map((item, index) => {
if(item === this) this.parent.fields.splice(index, 1);
})
}
},
};
// 组件销毁前,将实例从u-form的缓存中移除
beforeDestroy() {
// 如果当前没有prop的话表示当前不要进行删除(因为没有注入)
if (this.parent && this.prop) {
this.parent.fields.map((item, index) => {
if (item === this) this.parent.fields.splice(index, 1);
})
}
},
};
</script>
<style lang="scss" scoped>
......
......@@ -4,7 +4,7 @@
background: bgColor,
width: width,
}">
<view class="u-grid-item-box" :class="[showBorder ? 'u-border-right u-border-bottom' : '']">
<view class="u-grid-item-box" :style="customStyle" :class="[showBorder ? 'u-border-right u-border-bottom' : '']">
<slot />
</view>
</view>
......@@ -17,6 +17,7 @@
* @tutorial https://www.uviewui.com/components/grid.html
* @property {String} bg-color 宫格的背景颜色(默认#ffffff)
* @property {String Number} index 点击宫格时,返回的值
* @property {Object} custom-style 自定义样式,对象形式
* @event {Function} click 点击宫格触发
* @example <u-grid-item></u-grid-item>
*/
......@@ -33,6 +34,15 @@
type: [Number, String],
default: ''
},
// 自定义样式,对象形式
customStyle: {
type: Object,
default() {
return {
padding: '30rpx 0'
}
}
}
},
data() {
return {
......
......@@ -2,8 +2,7 @@
<view class="u-char-box">
<view class="u-char-flex">
<input :disabled="disabledKeyboard" :value="valueModel" type="number" :focus="focus" :maxlength="maxlength" class="u-input" @input="getVal"/>
<!-- 这里需要通过new Array生成一个供循环的数组,是因为头条小程序不支持通过v-for历遍一个数值,其他端都是正常的 -->
<view v-for="(item, index) in (new Array(maxlength).fill(0))" :key="index">
<view v-for="(item, index) in loopCharArr" :key="index">
<view :class="[breathe && charArrLength == index ? 'u-breathe' : '', 'u-char-item',
charArrLength === index && mode == 'box' ? 'u-box-active' : '',
mode === 'box' ? 'u-box' : '']" :style="{
......@@ -11,7 +10,8 @@
fontSize: fontSize + 'rpx',
width: width + 'rpx',
height: width + 'rpx',
color: inactiveColor
color: inactiveColor,
borderColor: charArrLength === index && mode == 'box' ? activeColor : 'none'
}">
<view class="u-placeholder-line" :style="{
display: charArrLength === index ? 'block' : 'none',
......@@ -100,7 +100,7 @@
// 激活样式
activeColor: {
type: String,
default: '#2979ff'
default: 'red'
},
// 未激活的样式
inactiveColor: {
......@@ -155,6 +155,10 @@
},
charArrLength() {
return this.charArr.length;
},
// 根据长度,循环输入框的个数,因为头条小程序数值不能用于v-for
loopCharArr() {
return new Array(this.maxlength);
}
},
methods: {
......
......@@ -62,7 +62,7 @@
},
// 每个checkbox占u-checkbox-group的宽度
width: {
type: String,
type: [String, Number],
default: 'auto'
},
// 是否每个checkbox都换行
......@@ -81,7 +81,7 @@
// 通过子组件传递过来的val值(此被选中的子组件内部已将parentValue设置等于val的值),将其他
// u-radio设置未选中的状态
this.children.map(child => {
if(child.parentValue != val) child.parentValue = '';
if(child.parentData.value != val) child.parentData.value = '';
})
// 通过emit事件,设置父组件通过v-model双向绑定的值
this.$emit('input', val);
......
......@@ -71,48 +71,62 @@
},
data() {
return {
parentValue: ''
// 父组件的默认值,因为头条小程序不支持在computed中使用this.parent.shape的形式
// 故只能使用如此方法
parentData: {
iconSize: null,
labelDisabled: null,
disabled: null,
shape: null,
activeColor: null,
size: null,
width: null,
height: null,
value: null,
}
};
},
created() {
this.parent = false;
},
mounted() {
// 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环应用
// 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用
this.parent = this.$u.$parent.call(this, 'u-radio-group');
if(this.parent) {
// 历遍parentData中的属性,将parent中的同名属性赋值给parentData
Object.keys(this.parentData).map(key => {
this.parentData[key] = this.parent[key];
});
this.parent.children.push(this);
}
},
computed: {
// 是否禁用,如果父组件u-raios-group禁用的话,将会忽略子组件的配置
elDisabled() {
return this.disabled !== '' ? this.disabled : this.parent ? this.parent.disabled : false;
return this.disabled !== '' ? this.disabled : this.parentData.disabled !== null ? this.parentData.disabled : false;
},
// 是否禁用label点击
elLabelDisabled() {
return this.labelDisabled !== '' ? this.labelDisabled : this.parent ? this.parent.labelDisabled : false;
return this.labelDisabled !== '' ? this.labelDisabled : this.parentData.labelDisabled !== null ? this.parentData.labelDisabled : false;
},
// 组件尺寸,对应size的值,默认值为34rpx
elSize() {
return this.size ? this.size : (this.parent ? this.parent.size : 34);
return this.size ? this.size : (this.parentData.size ? this.parentData.size : 34);
},
// 组件的勾选图标的尺寸,默认20
elIconSize() {
return this.iconSize ? this.iconSize : (this.parent ? this.parent.iconSize : 20);
return this.iconSize ? this.iconSize : (this.parentData.iconSize ? this.parentData.iconSize : 20);
},
// 组件选中激活时的颜色
elActiveColor() {
return this.activeColor ? this.activeColor : (this.parent ? this.parent.activeColor : 'primary');
return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : 'primary');
},
// 组件的形状
elShape() {
return this.shape ? this.shape : (this.parent ? this.parent.shape : 'circle');
return this.shape ? this.shape : (this.parentData.shape ? this.parentData.shape : 'circle');
},
// 设置radio的状态,要求radio的name等于parent的value时才为选中状态
iconStyle() {
let style = {};
if (this.elActiveColor && this.parentValue && !this.elDisabled) {
if (this.elActiveColor && this.parentData.value == this.name && !this.elDisabled) {
style.borderColor = this.elActiveColor;
style.backgroundColor = this.elActiveColor;
}
......@@ -121,32 +135,32 @@
return style;
},
iconColor() {
return this.name == this.parentValue ? '#ffffff' : 'transparent';
return this.name == this.parentData.value ? '#ffffff' : 'transparent';
},
iconClass() {
let classes = [];
classes.push('u-radio__icon-wrap--' + this.elShape);
if (this.name == this.parentValue) classes.push('u-radio__icon-wrap--checked');
if (this.name == this.parentData.value) classes.push('u-radio__icon-wrap--checked');
if (this.elDisabled) classes.push('u-radio__icon-wrap--disabled');
if (this.name == this.parentValue && this.elDisabled) classes.push(
if (this.name == this.parentData.value && this.elDisabled) classes.push(
'u-radio__icon-wrap--disabled--checked');
// 支付宝小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
return classes.join(' ');
},
radioStyle() {
let style = {};
if (this.parent && this.parent.width) {
style.width = this.parent.width;
if (this.parentData.width) {
style.width = this.$u.addUnit(this.parentData.width);
// #ifdef MP
// 各家小程序因为它们特殊的编译结构,使用float布局
style.float = 'left';
// #endif
// #ifndef MP
// H5和APP使用flex布局
style.flex = `0 0 ${this.parent.width}`;
style.flex = `0 0 ${this.$u.addUnit(this.parentData.width)}`;
// #endif
}
if (this.parent && this.parent.wrap) {
if (this.parentData.wrap) {
style.width = '100%';
// #ifndef MP
// H5和APP使用flex布局,将宽度设置100%,即可自动换行
......@@ -172,18 +186,18 @@
// 等待下一个周期再执行,因为this.$emit('input')作用于父组件,再反馈到子组件内部,需要时间
// 头条需要延时的时间比较长,这里给比较大的值
setTimeout(() => {
if(this.parent && this.parent.value != this.name) this.$emit('change', this.name);
if(this.parentData.value != this.name) this.$emit('change', this.name);
}, 80);
},
// 改变组件选中状态
// 这里的改变的依据是,更改本组件的parentValue值为本组件的name值,同时通过父组件遍历所有u-radio实例
// 将本组建外的其他u-radio的parentValue都设置为空(由computed计算后,都被取消选中状态),因而只剩下一个为选中状态
// 这里的改变的依据是,更改本组件的parentData.value值为本组件的name值,同时通过父组件遍历所有u-radio实例
// 将本组件外的其他u-radio的parentData.value都设置为空(由computed计算后,都被取消选中状态),因而只剩下一个为选中状态
setRadioCheckedStatus() {
this.emitEvent();
if(this.parent) {
this.parent.setValue(this.name);
this.parentValue = this.name;
this.parentData.value = this.name;
}
this.emitEvent();
}
}
};
......
......@@ -224,7 +224,7 @@ export default {
.u-left-icon {
/* #ifndef APP-NVUE */
display: none;
display: inline-flex;
/* #endif */
align-items: center;
}
......
......@@ -5,14 +5,14 @@
<swiper :current="elCurrent" @change="change" @animationfinish="animationfinish" :interval="interval" :circular="circular" :duration="duration" :autoplay="autoplay"
:previous-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'" :next-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'"
:style="{
height: height + 'rpx'
height: height + 'rpx',
backgroundColor: bgColor
}">
<swiper-item class="u-swiper-item" v-for="(item, index) in list" :key="index">
<view class="u-list-image-wrap" @tap.stop.prevent="listClick(index)" :class="[uCurrent != index ? 'u-list-scale' : '']" :style="{
borderRadius: `${borderRadius}rpx`,
transform: effect3d && uCurrent != index ? 'scaleY(0.9)' : 'scaleY(1)',
margin: effect3d && uCurrent != index ? '0 20rpx' : 0,
backgroundColor: bgColor
}">
<image class="u-swiper-image" :src="item[name] || item" :mode="imgMode"></image>
<view v-if="title && item.title" class="u-swiper-title u-line-1" :style="[{
......
......@@ -237,6 +237,11 @@ export default {
type: Function,
default: null
},
// 移除文件前的钩子
beforeRemove: {
type: Function,
default: null
},
// 允许上传的图片后缀
limitType:{
type: Array,
......@@ -394,8 +399,10 @@ export default {
return this.uploadFile(index + 1);
})
} else if(beforeResponse === false) {
// 如果返回false,继续下一张图片的上传
// 如果返回false,继续下一张图片的上传
return this.uploadFile(index + 1);
} else {
// 此处为返回"true"的情形,这里不写代码,就跳过此处,继续执行当前的上传逻辑
}
}
// 检查上传地址
......@@ -455,19 +462,48 @@ export default {
uni.showModal({
title: '提示',
content: '您确定要删除此项吗?',
success: res => {
success: async (res) => {
if (res.confirm) {
if (this.lists[index].process < 100 && this.lists[index].process > 0) {
typeof this.lists[index].uploadTask != 'undefined' && this.lists[index].uploadTask.abort();
// 先检查是否有定义before-remove移除前钩子
// 执行before-remove钩子
if(this.beforeRemove && typeof(this.beforeRemove) === 'function') {
// 此处钩子执行 原理同before-remove参数,见上方注释
let beforeResponse = this.beforeRemove.bind(this.$u.$parent.call(this))(index, this.lists);
// 判断是否返回了promise
if (!!beforeResponse && typeof beforeResponse.then === 'function') {
await beforeResponse.then(res => {
// promise返回成功,不进行动作,继续上传
this.handlerDeleteItem(index);
}).catch(err => {
// 如果进入promise的reject,终止删除操作
this.showToast('已终止移除');
})
} else if(beforeResponse === false) {
// 返回false,终止删除
this.showToast('已终止移除');
} else {
// 如果返回true,执行删除操作
this.handlerDeleteItem(index);
}
} else {
// 如果不存在before-remove钩子,
this.handlerDeleteItem(index);
}
this.lists.splice(index, 1);
this.$forceUpdate();
this.$emit('on-remove', index, this.lists, this.index);
this.showToast('移除成功');
}
}
});
},
// 执行移除图片的动作,上方代码只是判断是否可以移除
handlerDeleteItem(index) {
// 如果文件正在上传中,终止上传任务,进度在0 < progress < 100则意味着正在上传
if (this.lists[index].process < 100 && this.lists[index].process > 0) {
typeof this.lists[index].uploadTask != 'undefined' && this.lists[index].uploadTask.abort();
}
this.lists.splice(index, 1);
this.$forceUpdate();
this.$emit('on-remove', index, this.lists, this.index);
this.showToast('移除成功');
},
// 用户通过ref手动的形式,移除一张图片
remove(index) {
// 判断索引的合法范围
......@@ -539,7 +575,7 @@ export default {
position: relative;
border-radius: 10rpx;
/* #ifndef APP-NVUE */
display: inline-block;
display: flex;
/* #endif */
align-items: center;
justify-content: center;
......
// 此版本发布于2020-09-03
let version = '1.6.6';
// 此版本发布于2020-09-07
let version = '1.6.8';
export default {
v: version,
......
......@@ -45,7 +45,7 @@ text {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row!important;
flex-direction: row;
align-items: center;
}
......
{
"name": "uview-ui",
"version": "1.6.6",
"version": "1.6.8",
"description": "uView UI,是uni-app生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水",
"main": "index.js",
"keywords": ["uview", "uView", "uni-app", "uni-app ui", "uniapp", "uviewui", "uview ui", "uviewUI", "uViewui", "uViewUI", "uView UI", "uni ui", "uni UI", "uniapp ui", "ui", "UI框架", "uniapp ui框架", "uniapp UI"],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment