Commit aa4d501e authored by wlxuqu's avatar wlxuqu

1. 【新增】grid-item组件新增custom-style参数

2. 【新增】action-sheet组件新增subText描述信息参数
3. 【新增】upload组件新增before-remove钩子
4. 【优化】优化badge组件的层级问题
5. 【修复】修复form组件label-style参数无效的问题
6. 【修复】修复message-input组件box模式下,active-color参数无效的问题
7. 【修复】修复form组件label-style参数无效的问题修复radio组件的默认值无效的问题
8. 【修复】修复notice-bar组件左侧喇叭图标不显示的问题
parent 46a53081
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
uView UI,是[uni-app](https://uniapp.dcloud.io/)生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水 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 @@ ...@@ -2,7 +2,7 @@
"name" : "uView", "name" : "uView",
"appid" : "__UNI__60F4B81", "appid" : "__UNI__60F4B81",
"description" : "多平台快速开发的UI框架", "description" : "多平台快速开发的UI框架",
"versionName" : "1.6.6", "versionName" : "1.6.8",
"versionCode" : "100", "versionCode" : "100",
"transformPx" : false, "transformPx" : false,
"app-plus" : { "app-plus" : {
......
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
"easycom": { "easycom": {
"^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue" "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
}, },
// "condition": { //模式配置,仅开发期间生效 "condition": { //模式配置,仅开发期间生效
// "current": 0, //当前激活的模式(list 的索引项) "current": 0, //当前激活的模式(list 的索引项)
// "list": [{ "list": [{
// "name": "test", //模式名称 "name": "test", //模式名称
// "path": "pages/componentsC/test/index", //启动页面,必选 "path": "pages/componentsC/test/index", //启动页面,必选
// "query": "id=1&name=2" //启动参数,在页面的onLoad函数里面得到 "query": "id=1&name=2" //启动参数,在页面的onLoad函数里面得到
// }] }]
// }, },
"pages": [ "pages": [
// 演示-组件 // 演示-组件
{ {
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
</u-form-item> </u-form-item>
<u-form-item :label-position="labelPosition" label="结算方式" prop="payType" label-width="150"> <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-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-radio-group>
</u-form-item> </u-form-item>
<u-form-item :label-position="labelPosition" label="所在地区" prop="region" label-width="150"> <u-form-item :label-position="labelPosition" label="所在地区" prop="region" label-width="150">
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
<u-switch v-model="model.remember" slot="right"></u-switch> <u-switch v-model="model.remember" slot="right"></u-switch>
</u-form-item> </u-form-item>
<u-form-item :label-position="labelPosition" label="上传图片" prop="photo" label-width="150"> <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-item>
</u-form> </u-form>
<view class="agreement"> <view class="agreement">
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
:percent="item.progress"></u-line-progress> :percent="item.progress"></u-line-progress>
</view> </view>
</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"> :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"> <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> <u-icon name="photo" size="60" :color="$u.color['lightColor']"></u-icon>
...@@ -140,6 +140,9 @@ ...@@ -140,6 +140,9 @@
// console.log('onListChange', lists); // console.log('onListChange', lists);
this.lists = lists; this.lists = lists;
}, },
beforeRemove(index, lists) {
return true;
}
} }
} }
</script> </script>
......
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
text: '朱颜辞镜花辞树', text: '朱颜辞镜花辞树',
disabled: true disabled: true
}, { }, {
text: '正是江南好风景' text: '正是江南好风景',
subText: '春江水暖鸭先知'
}, { }, {
text: '落花时节又逢君' text: '落花时节又逢君'
}], }],
......
<template> <template>
<view class=""> <view class="pageMain">
<u-button @click="show = true;">打开弹窗</u-button>
<u-popup mode="bottom" v-model="show"> <view class="title">完善个人信息</view>
<view class="content"> <view class="info">为了给您精准的推荐,请完善以下信息
<u-image class="image" width="500rpx" height="300rpx" src="https://cdn.uviewui.com/uview/example/fade.jpg"></u-image> </view>
<view class="my-form">
<view class="confrim-btn"> <u-form :model="form" ref="formRef">
<u-button @click="show = false;">确定</u-button>
<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>
</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> </view>
</template> </template>
...@@ -17,21 +89,298 @@ ...@@ -17,21 +89,298 @@
export default { export default {
data() { data() {
return { 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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.content { // 本页主体
padding: 24rpx; .pageMain {
text-align: center; padding: 65rpx;
position: relative; min-height: 100vh;
box-sizing: border-box;
// background-image: url(@/static/common/img/userLogin.jpg);
} }
.image { // 大标题
position: absolute; .title {
top: -200rpx; 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> </style>
\ No newline at end of file
...@@ -9,11 +9,12 @@ ...@@ -9,11 +9,12 @@
@touchmove.stop.prevent @touchmove.stop.prevent
@tap="itemClick(index)" @tap="itemClick(index)"
:style="[itemStyle(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' : '']" :class="[index < list.length - 1 ? 'u-border-bottom' : '']"
:hover-stay-time="150" :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> </view>
</block> </block>
<view class="u-gab" v-if="cancelBtn"> <view class="u-gab" v-if="cancelBtn">
...@@ -167,8 +168,15 @@ ...@@ -167,8 +168,15 @@
line-height: 1; line-height: 1;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
font-size: 34rpx; font-size: 32rpx;
padding: 34rpx 0; padding: 34rpx 0;
flex-direction: column;
}
.u-action-sheet-item__subtext {
font-size: 24rpx;
color: $u-tips-color;
margin-top: 20rpx;
} }
.u-gab { .u-gab {
......
...@@ -149,6 +149,7 @@ ...@@ -149,6 +149,7 @@
line-height: 24rpx; line-height: 24rpx;
padding: 4rpx 8rpx; padding: 4rpx 8rpx;
border-radius: 100rpx; border-radius: 100rpx;
z-index: 9;
&--bg--primary { &--bg--primary {
background-color: $u-type-primary; background-color: $u-type-primary;
......
...@@ -42,10 +42,10 @@ ...@@ -42,10 +42,10 @@
</template> </template>
<script> <script>
import Emitter from '../../libs/util/emitter.js'; import Emitter from '../../libs/util/emitter.js';
import schema from '../../libs/util/async-validator'; import schema from '../../libs/util/async-validator';
// 去除警告信息 // 去除警告信息
schema.warning = function(){}; schema.warning = function() {};
/** /**
* form-item 表单item * form-item 表单item
...@@ -66,257 +66,283 @@ schema.warning = function(){}; ...@@ -66,257 +66,283 @@ schema.warning = function(){};
* @example <u-form-item label="姓名"><u-input v-model="form.name" /></u-form-item> * @example <u-form-item label="姓名"><u-input v-model="form.name" /></u-form-item>
*/ */
export default { export default {
name: 'u-form-item', name: 'u-form-item',
mixins: [Emitter], mixins: [Emitter],
inject: { inject: {
uForm: { uForm: {
default() { default () {
return null 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 {}
} }
}, },
// 左侧图标的样式 props: {
rightIconStyle: { // input的label提示语
type: Object, label: {
default() { type: String,
return {} 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中配置 data() {
required: { return {
type: Boolean, initialValue: '', // 存储的默认值
default: false // isRequired: false, // 是否必填,由于人性化考虑,必填"*"号通过props的required配置,不再通过rules的规则自动生成
} validateState: '', // 是否校验成功
}, validateMessage: '', // 校验失败的提示语
data() { // 有错误时的提示方式,message-提示信息,border-如果input设置了边框,变成呈红色,
return { errorType: ['message'],
initialValue: '', // 存储的默认值 fieldValue: '', // 获取当前子组件input的输入的值
// isRequired: false, // 是否必填,由于人性化考虑,必填"*"号通过props的required配置,不再通过rules的规则自动生成 // 父组件的参数,在computed计算中,无法得知this.parent发生变化,故将父组件的参数值,放到data中
validateState: '', // 是否校验成功 parentData: {
validateMessage: '' ,// 校验失败的提示语 borderBottom: true,
// 有错误时的提示方式,message-提示信息,border-如果input设置了边框,变成呈红色, labelWidth: 90,
errorType: ['message'], labelPosition: 'left',
fieldValue: '', // 获取当前子组件input的输入的值 labelStyle: {},
}; labelAlign: 'left',
}, }
watch: { };
validateState(val) {
this.broadcastInputError();
},
// 监听u-form组件的errorType的变化
"uForm.errorType"(val) {
this.errorType = val;
this.broadcastInputError();
}, },
}, watch: {
computed: { validateState(val) {
// 计算后的label宽度,由于需要多个判断,故放到computed中 this.broadcastInputError();
uLabelWidth() { },
// 如果用户设置label为空字符串(微信小程序空字符串最终会变成字符串的'true'),意味着要将label的位置宽度设置为auto // 监听u-form组件的errorType的变化
return this.elLabelPosition == 'left' ? (this.label === 'true' || this.label === '' ? 'auto' : this.$u.addUnit(this.elLabelWidth)) : '100%'; "uForm.errorType"(val) {
this.errorType = val;
this.broadcastInputError();
},
}, },
showError() { computed: {
return type => { // 计算后的label宽度,由于需要多个判断,故放到computed中
// 如果errorType数组中含有none,或者toast提示类型 uLabelWidth() {
if(this.errorType.indexOf('none') >= 0) return false; // 如果用户设置label为空字符串(微信小程序空字符串最终会变成字符串的'true'),意味着要将label的位置宽度设置为auto
else if(this.errorType.indexOf(type) >= 0) return true; return this.elLabelPosition == 'left' ? (this.label === 'true' || this.label === '' ? 'auto' : this.$u.addUnit(this
else return false; .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的宽度 methods: {
elLabelWidth() { broadcastInputError() {
// label默认宽度为90,优先使用本组件的值,如果没有(如果设置为0,也算是配置了值,依然起效),则用u-form的值 // 子组件发出事件,第三个参数为true或者false,true代表有错误
return (this.labelWidth != 0 || this.labelWidth != '') ? this.labelWidth : (this.parent ? this.parent.labelWidth : 90); this.broadcast('u-input', 'on-form-item-error', this.validateState === 'error' && this.showError('border'));
}, },
// label的样式 // 判断是否需要required校验
elLabelStyle() { setRules() {
return Object.keys(this.labelStyle).length ? this.labelStyle : (this.parent ? this.parent.labelStyle : {}); let that = this;
}, // 由于人性化考虑,必填"*"号通过props的required配置,不再通过rules的规则自动生成
// label的位置,左侧或者上方 // 从父组件u-form拿到当前u-form-item需要验证 的规则
elLabelPosition() { // let rules = this.getRules();
return this.labelPosition ? this.labelPosition : (this.parent ? this.parent.labelPosition : 'left'); // if (rules.length) {
}, // this.isRequired = rules.some(rule => {
// label的对齐方式 // // 如果有必填项,就返回,没有的话,就是undefined
elLabelAlign() { // return rule.required;
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;
// });
// }
// blur事件 // blur事件
this.$on('on-form-blur', that.onFieldBlur); this.$on('on-form-blur', that.onFieldBlur);
// change事件 // change事件
this.$on('on-form-change', that.onFieldChange); this.$on('on-form-change', that.onFieldChange);
}, },
// 从u-form的rules属性中,取出当前u-form-item的校验规则 // 从u-form的rules属性中,取出当前u-form-item的校验规则
getRules() { getRules() {
// 父组件的所有规则 // 父组件的所有规则
let rules = this.parent.rules; let rules = this.parent.rules;
rules = rules ? rules[this.prop] : []; rules = rules ? rules[this.prop] : [];
// 保证返回的是一个数组形式 // 保证返回的是一个数组形式
return [].concat(rules || []); return [].concat(rules || []);
}, },
// blur事件时进行表单校验 // blur事件时进行表单校验
onFieldBlur() { onFieldBlur() {
this.validation('blur'); this.validation('blur');
}, },
// change事件进行表单校验 // change事件进行表单校验
onFieldChange() { onFieldChange() {
this.validation('change'); this.validation('change');
}, },
// 过滤出符合要求的rule规则 // 过滤出符合要求的rule规则
getFilteredRule(triggerType = '') { getFilteredRule(triggerType = '') {
let rules = this.getRules(); let rules = this.getRules();
// 整体验证表单时,triggerType为空字符串,此时返回所有规则进行验证 // 整体验证表单时,triggerType为空字符串,此时返回所有规则进行验证
if(!triggerType) return rules; if (!triggerType) return rules;
// 历遍判断规则是否有对应的事件,比如blur,change触发等的事件 // 历遍判断规则是否有对应的事件,比如blur,change触发等的事件
// 使用indexOf判断,是因为某些时候设置的验证规则的trigger属性可能为多个,比如['blur','change'] // 使用indexOf判断,是因为某些时候设置的验证规则的trigger属性可能为多个,比如['blur','change']
// 某些场景可能的判断规则,可能不存在trigger属性,故先判断是否存在此属性 // 某些场景可能的判断规则,可能不存在trigger属性,故先判断是否存在此属性
return rules.filter(res => res.trigger && res.trigger.indexOf(triggerType) !== -1); 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);
});
},
// 校验数据 // 清空当前的u-form-item
validation(trigger, callback = () => {}) { resetField() {
// 检验之间,先获取需要校验的值 this.parent.model[this.prop] = this.initialValue;
this.fieldValue = this.parent.model[this.prop]; // 设置为`success`状态,只是为了清空错误标记
// blur和change是否有当前方式的校验规则 this.validateState = 'success';
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);
});
}, },
// 清空当前的u-form-item // 组件创建完成时,将当前实例保存到u-form中
resetField() { mounted() {
this.parent.model[this.prop] = this.initialValue; // 支付宝、头条小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环应用
// 设置为`success`状态,只是为了清空错误标记 this.parent = this.$u.$parent.call(this, 'u-form');
this.validateState = 'success'; if (this.parent) {
} // 历遍parentData中的属性,将parent中的同名属性赋值给parentData
}, Object.keys(this.parentData).map(key => {
this.parentData[key] = this.parent[key];
// 组件创建完成时,将当前实例保存到u-form中 });
mounted() { // 如果没有传入prop,或者uForm为空(如果u-form-input单独使用,就不会有uForm注入),就不进行校验
// 支付宝、头条小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环应用 if (this.prop) {
this.parent = this.$u.$parent.call(this, 'u-form'); // 将本实例添加到父组件中
// 如果没有传入prop,或者uForm为空(如果u-form-input单独使用,就不会有uForm注入),就不进行校验 this.parent.fields.push(this);
if (this.prop || this.parent) { this.errorType = this.parent.errorType;
// 将本实例添加到父组件中 // 设置初始值
this.parent.fields.push(this); this.initialValue = this.fieldValue;
this.errorType = this.parent.errorType; // 添加表单校验,这里必须要写在$nextTick中,因为u-form的rules是通过ref手动传入的
// 设置初始值 // 不在$nextTick中的话,可能会造成执行此处代码时,父组件还没通过ref把规则给u-form,导致规则为空
this.initialValue = this.fieldValue; this.$nextTick(() => {
// 添加表单校验,这里必须要写在$nextTick中,因为u-form的rules是通过ref手动传入的 this.setRules();
// 不在$nextTick中的话,可能会造成执行此处代码时,父组件还没通过ref把规则给u-form,导致规则为空 })
this.$nextTick(() =>{ }
this.setRules(); }
}) },
}
},
// 组件销毁前,将实例从u-form的缓存中移除 // 组件销毁前,将实例从u-form的缓存中移除
beforeDestroy() { beforeDestroy() {
// 如果当前没有prop的话表示当前不要进行删除(因为没有注入) // 如果当前没有prop的话表示当前不要进行删除(因为没有注入)
if(this.parent && this.prop) { if (this.parent && this.prop) {
this.parent.fields.map((item, index) => { this.parent.fields.map((item, index) => {
if(item === this) this.parent.fields.splice(index, 1); if (item === this) this.parent.fields.splice(index, 1);
}) })
} }
}, },
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
background: bgColor, background: bgColor,
width: width, 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 /> <slot />
</view> </view>
</view> </view>
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
* @tutorial https://www.uviewui.com/components/grid.html * @tutorial https://www.uviewui.com/components/grid.html
* @property {String} bg-color 宫格的背景颜色(默认#ffffff) * @property {String} bg-color 宫格的背景颜色(默认#ffffff)
* @property {String Number} index 点击宫格时,返回的值 * @property {String Number} index 点击宫格时,返回的值
* @property {Object} custom-style 自定义样式,对象形式
* @event {Function} click 点击宫格触发 * @event {Function} click 点击宫格触发
* @example <u-grid-item></u-grid-item> * @example <u-grid-item></u-grid-item>
*/ */
...@@ -33,6 +34,15 @@ ...@@ -33,6 +34,15 @@
type: [Number, String], type: [Number, String],
default: '' default: ''
}, },
// 自定义样式,对象形式
customStyle: {
type: Object,
default() {
return {
padding: '30rpx 0'
}
}
}
}, },
data() { data() {
return { return {
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
<view class="u-char-box"> <view class="u-char-box">
<view class="u-char-flex"> <view class="u-char-flex">
<input :disabled="disabledKeyboard" :value="valueModel" type="number" :focus="focus" :maxlength="maxlength" class="u-input" @input="getVal"/> <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 loopCharArr" :key="index">
<view v-for="(item, index) in (new Array(maxlength).fill(0))" :key="index">
<view :class="[breathe && charArrLength == index ? 'u-breathe' : '', 'u-char-item', <view :class="[breathe && charArrLength == index ? 'u-breathe' : '', 'u-char-item',
charArrLength === index && mode == 'box' ? 'u-box-active' : '', charArrLength === index && mode == 'box' ? 'u-box-active' : '',
mode === 'box' ? 'u-box' : '']" :style="{ mode === 'box' ? 'u-box' : '']" :style="{
...@@ -11,7 +10,8 @@ ...@@ -11,7 +10,8 @@
fontSize: fontSize + 'rpx', fontSize: fontSize + 'rpx',
width: width + 'rpx', width: width + 'rpx',
height: width + 'rpx', height: width + 'rpx',
color: inactiveColor color: inactiveColor,
borderColor: charArrLength === index && mode == 'box' ? activeColor : 'none'
}"> }">
<view class="u-placeholder-line" :style="{ <view class="u-placeholder-line" :style="{
display: charArrLength === index ? 'block' : 'none', display: charArrLength === index ? 'block' : 'none',
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
// 激活样式 // 激活样式
activeColor: { activeColor: {
type: String, type: String,
default: '#2979ff' default: 'red'
}, },
// 未激活的样式 // 未激活的样式
inactiveColor: { inactiveColor: {
...@@ -155,6 +155,10 @@ ...@@ -155,6 +155,10 @@
}, },
charArrLength() { charArrLength() {
return this.charArr.length; return this.charArr.length;
},
// 根据长度,循环输入框的个数,因为头条小程序数值不能用于v-for
loopCharArr() {
return new Array(this.maxlength);
} }
}, },
methods: { methods: {
......
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
}, },
// 每个checkbox占u-checkbox-group的宽度 // 每个checkbox占u-checkbox-group的宽度
width: { width: {
type: String, type: [String, Number],
default: 'auto' default: 'auto'
}, },
// 是否每个checkbox都换行 // 是否每个checkbox都换行
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
// 通过子组件传递过来的val值(此被选中的子组件内部已将parentValue设置等于val的值),将其他 // 通过子组件传递过来的val值(此被选中的子组件内部已将parentValue设置等于val的值),将其他
// u-radio设置未选中的状态 // u-radio设置未选中的状态
this.children.map(child => { this.children.map(child => {
if(child.parentValue != val) child.parentValue = ''; if(child.parentData.value != val) child.parentData.value = '';
}) })
// 通过emit事件,设置父组件通过v-model双向绑定的值 // 通过emit事件,设置父组件通过v-model双向绑定的值
this.$emit('input', val); this.$emit('input', val);
......
...@@ -71,48 +71,62 @@ ...@@ -71,48 +71,62 @@
}, },
data() { data() {
return { 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() { created() {
this.parent = false; this.parent = false;
}, // 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用
mounted() {
// 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环应用
this.parent = this.$u.$parent.call(this, 'u-radio-group'); this.parent = this.$u.$parent.call(this, 'u-radio-group');
if(this.parent) { if(this.parent) {
// 历遍parentData中的属性,将parent中的同名属性赋值给parentData
Object.keys(this.parentData).map(key => {
this.parentData[key] = this.parent[key];
});
this.parent.children.push(this); this.parent.children.push(this);
} }
}, },
computed: { computed: {
// 是否禁用,如果父组件u-raios-group禁用的话,将会忽略子组件的配置 // 是否禁用,如果父组件u-raios-group禁用的话,将会忽略子组件的配置
elDisabled() { 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点击 // 是否禁用label点击
elLabelDisabled() { 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 // 组件尺寸,对应size的值,默认值为34rpx
elSize() { 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 // 组件的勾选图标的尺寸,默认20
elIconSize() { 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() { 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() { 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时才为选中状态 // 设置radio的状态,要求radio的name等于parent的value时才为选中状态
iconStyle() { iconStyle() {
let style = {}; let style = {};
if (this.elActiveColor && this.parentValue && !this.elDisabled) { if (this.elActiveColor && this.parentData.value == this.name && !this.elDisabled) {
style.borderColor = this.elActiveColor; style.borderColor = this.elActiveColor;
style.backgroundColor = this.elActiveColor; style.backgroundColor = this.elActiveColor;
} }
...@@ -121,32 +135,32 @@ ...@@ -121,32 +135,32 @@
return style; return style;
}, },
iconColor() { iconColor() {
return this.name == this.parentValue ? '#ffffff' : 'transparent'; return this.name == this.parentData.value ? '#ffffff' : 'transparent';
}, },
iconClass() { iconClass() {
let classes = []; let classes = [];
classes.push('u-radio__icon-wrap--' + this.elShape); 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.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'); 'u-radio__icon-wrap--disabled--checked');
// 支付宝小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效 // 支付宝小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
return classes.join(' '); return classes.join(' ');
}, },
radioStyle() { radioStyle() {
let style = {}; let style = {};
if (this.parent && this.parent.width) { if (this.parentData.width) {
style.width = this.parent.width; style.width = this.$u.addUnit(this.parentData.width);
// #ifdef MP // #ifdef MP
// 各家小程序因为它们特殊的编译结构,使用float布局 // 各家小程序因为它们特殊的编译结构,使用float布局
style.float = 'left'; style.float = 'left';
// #endif // #endif
// #ifndef MP // #ifndef MP
// H5和APP使用flex布局 // H5和APP使用flex布局
style.flex = `0 0 ${this.parent.width}`; style.flex = `0 0 ${this.$u.addUnit(this.parentData.width)}`;
// #endif // #endif
} }
if (this.parent && this.parent.wrap) { if (this.parentData.wrap) {
style.width = '100%'; style.width = '100%';
// #ifndef MP // #ifndef MP
// H5和APP使用flex布局,将宽度设置100%,即可自动换行 // H5和APP使用flex布局,将宽度设置100%,即可自动换行
...@@ -172,18 +186,18 @@ ...@@ -172,18 +186,18 @@
// 等待下一个周期再执行,因为this.$emit('input')作用于父组件,再反馈到子组件内部,需要时间 // 等待下一个周期再执行,因为this.$emit('input')作用于父组件,再反馈到子组件内部,需要时间
// 头条需要延时的时间比较长,这里给比较大的值 // 头条需要延时的时间比较长,这里给比较大的值
setTimeout(() => { 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); }, 80);
}, },
// 改变组件选中状态 // 改变组件选中状态
// 这里的改变的依据是,更改本组件的parentValue值为本组件的name值,同时通过父组件遍历所有u-radio实例 // 这里的改变的依据是,更改本组件的parentData.value值为本组件的name值,同时通过父组件遍历所有u-radio实例
// 将本组建外的其他u-radio的parentValue都设置为空(由computed计算后,都被取消选中状态),因而只剩下一个为选中状态 // 将本组件外的其他u-radio的parentData.value都设置为空(由computed计算后,都被取消选中状态),因而只剩下一个为选中状态
setRadioCheckedStatus() { setRadioCheckedStatus() {
this.emitEvent();
if(this.parent) { if(this.parent) {
this.parent.setValue(this.name); this.parent.setValue(this.name);
this.parentValue = this.name; this.parentData.value = this.name;
} }
this.emitEvent();
} }
} }
}; };
......
...@@ -224,7 +224,7 @@ export default { ...@@ -224,7 +224,7 @@ export default {
.u-left-icon { .u-left-icon {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: none; display: inline-flex;
/* #endif */ /* #endif */
align-items: center; align-items: center;
} }
......
...@@ -5,14 +5,14 @@ ...@@ -5,14 +5,14 @@
<swiper :current="elCurrent" @change="change" @animationfinish="animationfinish" :interval="interval" :circular="circular" :duration="duration" :autoplay="autoplay" <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'" :previous-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'" :next-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'"
:style="{ :style="{
height: height + 'rpx' height: height + 'rpx',
backgroundColor: bgColor
}"> }">
<swiper-item class="u-swiper-item" v-for="(item, index) in list" :key="index"> <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="{ <view class="u-list-image-wrap" @tap.stop.prevent="listClick(index)" :class="[uCurrent != index ? 'u-list-scale' : '']" :style="{
borderRadius: `${borderRadius}rpx`, borderRadius: `${borderRadius}rpx`,
transform: effect3d && uCurrent != index ? 'scaleY(0.9)' : 'scaleY(1)', transform: effect3d && uCurrent != index ? 'scaleY(0.9)' : 'scaleY(1)',
margin: effect3d && uCurrent != index ? '0 20rpx' : 0, margin: effect3d && uCurrent != index ? '0 20rpx' : 0,
backgroundColor: bgColor
}"> }">
<image class="u-swiper-image" :src="item[name] || item" :mode="imgMode"></image> <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="[{ <view v-if="title && item.title" class="u-swiper-title u-line-1" :style="[{
......
...@@ -237,6 +237,11 @@ export default { ...@@ -237,6 +237,11 @@ export default {
type: Function, type: Function,
default: null default: null
}, },
// 移除文件前的钩子
beforeRemove: {
type: Function,
default: null
},
// 允许上传的图片后缀 // 允许上传的图片后缀
limitType:{ limitType:{
type: Array, type: Array,
...@@ -394,8 +399,10 @@ export default { ...@@ -394,8 +399,10 @@ export default {
return this.uploadFile(index + 1); return this.uploadFile(index + 1);
}) })
} else if(beforeResponse === false) { } else if(beforeResponse === false) {
// 如果返回false,继续下一张图片的上传 // 如果返回false,继续下一张图片的上传
return this.uploadFile(index + 1); return this.uploadFile(index + 1);
} else {
// 此处为返回"true"的情形,这里不写代码,就跳过此处,继续执行当前的上传逻辑
} }
} }
// 检查上传地址 // 检查上传地址
...@@ -455,19 +462,48 @@ export default { ...@@ -455,19 +462,48 @@ export default {
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
content: '您确定要删除此项吗?', content: '您确定要删除此项吗?',
success: res => { success: async (res) => {
if (res.confirm) { if (res.confirm) {
if (this.lists[index].process < 100 && this.lists[index].process > 0) { // 先检查是否有定义before-remove移除前钩子
typeof this.lists[index].uploadTask != 'undefined' && this.lists[index].uploadTask.abort(); // 执行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手动的形式,移除一张图片 // 用户通过ref手动的形式,移除一张图片
remove(index) { remove(index) {
// 判断索引的合法范围 // 判断索引的合法范围
...@@ -539,7 +575,7 @@ export default { ...@@ -539,7 +575,7 @@ export default {
position: relative; position: relative;
border-radius: 10rpx; border-radius: 10rpx;
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: inline-block; display: flex;
/* #endif */ /* #endif */
align-items: center; align-items: center;
justify-content: center; justify-content: center;
......
// 此版本发布于2020-09-03 // 此版本发布于2020-09-07
let version = '1.6.6'; let version = '1.6.8';
export default { export default {
v: version, v: version,
......
...@@ -45,7 +45,7 @@ text { ...@@ -45,7 +45,7 @@ text {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
flex-direction: row!important; flex-direction: row;
align-items: center; align-items: center;
} }
......
{ {
"name": "uview-ui", "name": "uview-ui",
"version": "1.6.6", "version": "1.6.8",
"description": "uView UI,是uni-app生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水", "description": "uView UI,是uni-app生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水",
"main": "index.js", "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"], "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