Commit 5e5b3da2 authored by wlxuqu's avatar wlxuqu

1. 修复select和picker组件在微信小程序滑动过快,快速点击确定按钮时选择值可能不对的问题

2. 废弃color.js文件,颜色值全部改由css提供,为自定义主题做准备
3. 修复form表单综合演示中,switch没有垂直居中的问题
parent b6fac515
...@@ -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/componentsA/select/index", //启动页面,必选
// "query": "id=1&name=2" //启动参数,在页面的onLoad函数里面得到 "query": "id=1&name=2" //启动参数,在页面的onLoad函数里面得到
// }] }]
// }, },
"pages": [ "pages": [
// 演示-组件 // 演示-组件
{ {
......
...@@ -32,32 +32,32 @@ export default { ...@@ -32,32 +32,32 @@ export default {
list: [], list: [],
list1: [ list1: [
{ {
id: '', value: '',
name: '' label: ''
}, },
{ {
id: '', value: '',
name: '' label: ''
}, },
{ {
id: '', value: '',
name: '' label: ''
}, },
{ {
id: '', value: '',
name: '' label: ''
}, },
{ {
id: '', value: '',
name: '' label: ''
}, },
{ {
id: '', value: '',
name: '' label: ''
}, },
{ {
id: '', value: '',
name: '' label: ''
} }
], ],
list2: [ list2: [
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<view class="u-demo-wrap"> <view class="u-demo-wrap">
<view class="u-demo-title">演示效果</view> <view class="u-demo-title">演示效果</view>
<view class="u-demo-area"> <view class="u-demo-area">
<u-steps :current="current" :list="steps" :mode="mode" :type="type"></u-steps> <u-steps :current="current" :list="steps" :mode="mode" :icon="icon"></u-steps>
</view> </view>
</view> </view>
<view class="u-config-wrap"> <view class="u-config-wrap">
...@@ -15,8 +15,8 @@ ...@@ -15,8 +15,8 @@
<u-subsection vibrateShort :list="['number', 'dot']" @change="modeChange"></u-subsection> <u-subsection vibrateShort :list="['number', 'dot']" @change="modeChange"></u-subsection>
</view> </view>
<view class="u-config-item"> <view class="u-config-item">
<view class="u-item-title">主题选择</view> <view class="u-item-title">自定义图标</view>
<u-subsection vibrateShort :list="['primary', 'success', 'error', 'warning', 'info']" @change="typeChange"></u-subsection> <u-subsection vibrateShort :list="['否', '是']" @change="iconChange"></u-subsection>
</view> </view>
<view class="u-config-item"> <view class="u-config-item">
<view class="u-item-title">当前步值</view> <view class="u-item-title">当前步值</view>
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
name: '签收' name: '签收'
}, ], }, ],
current: 0, current: 0,
type: 'primary', icon: 'checkmark',
mode: 'number' mode: 'number'
} }
}, },
...@@ -48,11 +48,11 @@ ...@@ -48,11 +48,11 @@
modeChange(index) { modeChange(index) {
this.mode = index == 0 ? 'number' : 'dot'; this.mode = index == 0 ? 'number' : 'dot';
}, },
typeChange(index) {
this.type = index == 0 ? 'primary' : index == 1 ? 'success' : index == 2 ? 'error' : index == 3 ? 'warning' : 'info';
},
stepChange(index) { stepChange(index) {
this.current = index == 0 ? 0 : index == 1 ? 1 : index == 2 ? 2 : 3; this.current = index == 0 ? 0 : index == 1 ? 1 : index == 2 ? 2 : 3;
},
iconChange(index) {
this.icon = index == 0 ? 'checkmark' : 'map-fill';
} }
} }
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<view class="u-demo-wrap"> <view class="u-demo-wrap">
<view class="u-demo-title">演示效果</view> <view class="u-demo-title">演示效果</view>
<view class="u-demo-area"> <view class="u-demo-area">
<u-button @click="btnClick" :loading="loading" :plain="plain" :shape="shape" :size="size" :ripple="ripple" :hairLine="hairLine" :type="type">山川异域,风月同天</u-button> <u-button disabled @click="btnClick" :loading="loading" :plain="plain" :shape="shape" :size="size" :ripple="ripple" :hairLine="hairLine" :type="type">山川异域,风月同天</u-button>
</view> </view>
</view> </view>
<view class="u-config-wrap"> <view class="u-config-wrap">
......
<template> <template>
<view> <view class="wrap">
<view class="wed"> <u-swiper :list="list"></u-swiper>
<!-- 单选日期 -->
<text @click="WE=!WE">开始</text>
<input type="text" v-model="result" />
<u-calendar v-model="WE" :mode="WEmode" @change="WEchange" start-text="开始" end-text="结束"></u-calendar>
</view>
<view class="wed">
<!-- 多选日期 -->
<text @click="WED=!WED">开始</text>
<input type="text" v-model="startDate" />
<text@click="WED=!WED">结束</text>
<input type="text" v-model="endDate" />
<u-calendar v-model="WED" :mode="WEDmode" @change="WEDchange" start-text="开始" end-text="结束"></u-calendar>
</view>
<view class="">
<u-read-more class="u-read-more" :toggle="true" show-height="100" font-size="12" close-text="更多" :shadow-style="shadowStyle">
<rich-text :nodes="content"></rich-text>
</u-read-more>
<u-read-more class="u-read-more" :toggle="true" show-height="100" font-size="12" close-tex t="更多" :shadow-style="shadowStyle">
<rich-text :nodes="content"></rich-text>
</u-read-more>
</view>
<view>
<!-- 字段少的表格 -->
<u-table>
<u-tr>
<u-th width="30%">学校</u-th>
<u-th>班级</u-th>
<u-th>年龄</u-th>
<u-th>爱好</u-th>
</u-tr>
<u-tr v-for="(item, index) in itemList" :key="index">
<u-td width="6%">
<u-checkbox-group @change="checkboxGroupChange1(index)">
<u-checkbox @change="checkboxChange" v-model="item.checked"></u-checkbox>
</u-checkbox-group>
</u-td>
<u-td>{{item.warehouseid}}</u-td>
<u-td>{{item.warehouseid}}</u-td>
<u-td>{{item.desc}}</u-td>
<u-td>{{item.desc}}</u-td>
</u-tr>
</u-table>
</view>
<view>
<u-table>
<u-tr>
<u-th width="38%">名称</u-th>
<u-th>别名</u-th>
<u-th>座右铭</u-th>
</u-tr>
<u-tr v-for="(item, index) in itemList" :key="index">
<u-td width="6%">
<u-radio-group v-model="value" label-disabled="true" @change="radioGroupChange(index)">
<u-radio @change="radioChange" :name="item.warehouseid">
</u-radio>
</u-radio-group>
</u-td>
<u-td>{{item.warehouseid}}</u-td>
<u-td>{{item.warehouseid}}</u-td>
<u-td>{{item.desc}}</u-td>
</u-tr>
</u-table>
</view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
// ----单选------------ list: [{
WE: false, image: '/static/uView/swiper/swiper1.jpg',
WEmode: "date", title: '蒹葭苍苍,白露为霜。所谓伊人,在水一方'
result: '',
// ---------------------
// ----多选--------------
WED: false,
WEDmode: 'range',
startDate: "",
endDate: '',
// ----------------------
content: `客户:山不在高,有仙则名。水不在深,有龙则灵。斯是陋室,惟吾德馨。
苔痕上阶绿,草色入帘青。谈笑有鸿儒,往来无白丁。可以调素琴,阅金经。
无丝竹之乱耳,无案牍之劳形。南阳诸葛庐,西蜀子云亭。孔子云:何陋之有?`,
shadowStyle: {
// backgroundImage: "linear-gradient(-180deg, rgba(255, 255, 255, 0) 0%, #fff 80%)",
paddingTop: "300rpx",
marginTop: "-300rpx",
},
//-------------单选框
checked: false,
checked1: false,
currentSort: 0,
itemList: {},
value: 'orange',
bangkList: [{
name: '英雄联盟',
alias: '撸啊撸',
else: '玩你**',
}, },
{ {
name: '守望先锋', image: '/static/uView/swiper/swiper2.jpg',
alias: '守望屁股', title: '溯洄从之,道阻且长。溯游从之,宛在水中央'
else: '打你**',
}, },
{ {
name: '炉石传说', image: '/static/uView/swiper/swiper3.jpg',
alias: '非酋玩家', title: '蒹葭萋萋,白露未晞。所谓伊人,在水之湄'
else: '冲你**',
} }
], ]
// u-radio-group的v-model绑定的值如果设置为某个radio的name,就会被默认选中
// value: false,
} }
}, },
created() { onLoad() {
//页面一进来就发送请求 setTimeout(() => {
uni.request({ this.list.pop();
url: 'http://47.99.173.114:9999/wms/wmmdwarehouse/list', }, 2000)
method: 'GET',
success: res => {
this.itemList = res.data
}
})
}, },
methods: { methods: {
// 选中某个单选框时,由radio时触发
radioChange(e) {
// console.log(e);
},
// 选中任一radio时,由radio-group触发
radioGroupChange(index) {
console.log(index);
},
checkboxGroupChange1(index) {
console.log("下标为:" + index);
},
// 选中某个复选框时,由checkbox时触发
checkboxChange(e) {
console.log(e);
},
// 选中任一checkbox时,由checkbox-group触发
checkboxGroupChange(e) {
console.log("全部选按钮" + e);
},
WEchange(e) {
console.log(e); //打印出来的值
// ----------时间单选-----------
this.result = e.result
},
WEDchange(e) {
console.log(e); //打印出来的值
// ----------时间多选择-----------
this.startDate = e.startDate //赋值
this.endDate = e.endDate //赋值
},
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.u-read-more { .wrap {
border: 1px solid #007AFF; padding: 40rpx;
margin-top: 10rpx;
}
.u-content {
font-size: 12;
}
.wed {
rich-text {
font-size: 12rpx;
color: #0066CC
}
text {
width: 100rpx;
height: 100%;
}
width: 100%;
height: 100%;
display: flex;
border: 2rpx solid #007AFF;
// justify-content: center;
.red {
uni-view,
uni-text {
border: 1px solid #007aff;
}
}
} }
</style> </style>
\ No newline at end of file
...@@ -43,7 +43,7 @@ const store = new Vuex.Store({ ...@@ -43,7 +43,7 @@ const store = new Vuex.Store({
let nameArr = payload.name.split('.'); let nameArr = payload.name.split('.');
let saveKey = ''; let saveKey = '';
let len = nameArr.length; let len = nameArr.length;
if(nameArr.length >= 2) { if(len >= 2) {
let obj = state[nameArr[0]]; let obj = state[nameArr[0]];
for(let i = 1; i < len - 1; i ++) { for(let i = 1; i < len - 1; i ++) {
obj = obj[nameArr[i]]; obj = obj[nameArr[i]];
......
<template> <template>
<view class="u-alert-tips" v-if="show" :class="{'u-close-alert-tips': !show}" :style="{ <view class="u-alert-tips" v-if="show" :class="[
backgroundColor: computeBgColor, !show ? 'u-close-alert-tips': '',
borderColor: computeBorderColor type ? 'u-alert-tips--bg--' + type + '-light' : '',
type ? 'u-alert-tips--border--' + type + '-disabled' : '',
]" :style="{
backgroundColor: borderColor,
borderColor: bgColor
}"> }">
<view class="u-icon-wrap"> <view class="u-icon-wrap">
<u-icon v-if="showIcon" :name="$u.type2icon(type)" :size="description ? 40 : 32" class="u-icon" :color="computeColor"></u-icon> <u-icon v-if="showIcon" :name="$u.type2icon(type)" :size="description ? 40 : 32" class="u-icon" :color="type"></u-icon>
</view> </view>
<view class="u-alert-content" @tap.stop="click"> <view class="u-alert-content" @tap.stop="click">
<view class="u-alert-title" :style="{fontWeight: description ? 500 : 'normal'}"> <view class="u-alert-title" :style="{fontWeight: description ? 500 : 'normal'}">
...@@ -98,22 +102,6 @@ ...@@ -98,22 +102,6 @@
return { return {
} }
}, },
computed: {
// 计算字体颜色,如果没有自定义的,就用uview主题颜色
computeColor() {
if (this.color) return this.color;
else return this.$u.color[this.type];
},
// 计算背景颜色
computeBgColor() {
if (this.bgColor) return this.bgColor;
return this.$u.color[this.type + 'Light'];
},
computeBorderColor() {
if (this.borderColor) return this.borderColor;
return this.$u.color[this.type + 'Disabled'];
}
},
methods: { methods: {
// 点击内容 // 点击内容
click() { click() {
...@@ -138,6 +126,46 @@ ...@@ -138,6 +126,46 @@
position: relative; position: relative;
transition: all 0.3s linear; transition: all 0.3s linear;
border: 1px solid #fff; border: 1px solid #fff;
&--bg--primary-light {
background-color: $u-type-primary-light;
}
&--bg--info-light {
background-color: $u-type-info-light;
}
&--bg--success-light {
background-color: $u-type-success-light;
}
&--bg--warning-light {
background-color: $u-type-warning-light;
}
&--bg--error-light {
background-color: $u-type-error-light;
}
&--border--primary-disabled {
border-color: $u-type-primary-disabled;
}
&--border--success-disabled {
border-color: $u-type-success-disabled;
}
&--border--error-disabled {
border-color: $u-type-error-disabled;
}
&--border--warning-disabled {
border-color: $u-type-warning-disabled;
}
&--border--info-disabled {
border-color: $u-type-info-disabled;
}
} }
.u-close-alert-tips { .u-close-alert-tips {
......
<template> <template>
<view v-if="show" class="u-badge-box" :class="[isDot ? 'u-badge-dot' : 'u-badge', size == 'mini' ? 'u-badge-mini' : '']" :style="[{ <view v-if="show" class="u-badge" :class="[
top: offset[0] + 'rpx', isDot ? 'u-badge-dot' : '',
right: offset[1] + 'rpx', size == 'mini' ? 'u-badge-mini' : '',
fontSize: fontSize + 'rpx', type ? 'u-badge--bg--' + type : ''
position: absolute ? 'absolute' : 'static', ]" :style="[{
color: color, top: offset[0] + 'rpx',
backgroundColor: backgroundColor right: offset[1] + 'rpx',
}, boxStyle]"> fontSize: fontSize + 'rpx',
position: absolute ? 'absolute' : 'static',
color: color,
backgroundColor: bgColor
}, boxStyle]"
>
{{showText}} {{showText}}
</view> </view>
</template> </template>
...@@ -127,10 +132,6 @@ ...@@ -127,10 +132,6 @@
// 如果count的值为0,并且showZero设置为false,不显示组件 // 如果count的值为0,并且showZero设置为false,不显示组件
if(this.count == 0 && this.showZero == false) return false; if(this.count == 0 && this.showZero == false) return false;
else return true; else return true;
},
// 获取背景颜色,如果定义了bgColor参数,就放弃type主题色
backgroundColor() {
return this.bgColor ? this.bgColor : this.$u.color[this.type];
} }
} }
} }
...@@ -139,16 +140,33 @@ ...@@ -139,16 +140,33 @@
<style lang="scss" scoped> <style lang="scss" scoped>
@import "../../libs/css/style.components.scss"; @import "../../libs/css/style.components.scss";
.u-badge-box { .u-badge {
display: inline-flex; display: inline-flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
}
.u-badge {
line-height: 24rpx; line-height: 24rpx;
padding: 4rpx 8rpx; padding: 4rpx 8rpx;
border-radius: 100rpx; border-radius: 100rpx;
&--bg--primary {
background-color: $u-type-primary;
}
&--bg--error {
background-color: $u-type-error;
}
&--bg--success {
background-color: $u-type-success;
}
&--bg--info {
background-color: $u-type-info;
}
&--bg--warning {
background-color: $u-type-warning;
}
} }
.u-badge-dot { .u-badge-dot {
......
...@@ -4,10 +4,13 @@ ...@@ -4,10 +4,13 @@
class="u-btn u-line-1 u-fix-ios-appearance" class="u-btn u-line-1 u-fix-ios-appearance"
:class="[ :class="[
'u-size-' + size, 'u-size-' + size,
plain ? 'u-' + type + '-plain' : '', plain ? 'u-btn--' + type + '--plain' : '',
loading ? 'u-loading' : '', loading ? 'u-loading' : '',
shape == 'circle' ? 'u-round-circle' : '', shape == 'circle' ? 'u-round-circle' : '',
hairLine ? showHairLineBorder : 'u-bold-border' hairLine ? showHairLineBorder : 'u-bold-border',
'u-btn--' + type,
disabled ? `u-btn--${type}--disabled` : '',
]" ]"
:disabled="disabled" :disabled="disabled"
:form-type="formType" :form-type="formType"
...@@ -209,39 +212,39 @@ export default { ...@@ -209,39 +212,39 @@ export default {
// 按钮主题 // 按钮主题
buttonStyle() { buttonStyle() {
let style = {}; let style = {};
if (this.type == 'default') { // if (this.type == 'default') {
if (this.disabled) { // if (this.disabled) {
style.color = '#c0c4cc'; // style.color = '#c0c4cc';
style.backgroundColor = '#ffffff'; // style.backgroundColor = '#ffffff';
style.borderColor = '#e4e7ed'; // style.borderColor = '#e4e7ed';
} else { // } else {
style.color = this.$u.color['contentColor']; // style.color = this.$u.color['contentColor'];
style.backgroundColor = '#ffffff'; // style.backgroundColor = '#ffffff';
style.borderColor = '#c0c4cc'; // style.borderColor = '#c0c4cc';
} // }
} else { // } else {
if (this.disabled) { // if (this.disabled) {
if (this.plain) { // if (this.plain) {
style.color = this.$u.color[this.type + 'Disabled']; // style.color = this.$u.color[this.type + 'Disabled'];
style.backgroundColor = this.$u.color[this.type + 'Light']; // style.backgroundColor = this.$u.color[this.type + 'Light'];
style.borderColor = this.$u.color[this.type + 'Disabled']; // style.borderColor = this.$u.color[this.type + 'Disabled'];
} else { // } else {
style.color = '#ffffff'; // style.color = '#ffffff';
style.backgroundColor = this.$u.color[this.type + 'Disabled']; // style.backgroundColor = this.$u.color[this.type + 'Disabled'];
style.borderColor = this.$u.color[this.type + 'Disabled']; // style.borderColor = this.$u.color[this.type + 'Disabled'];
} // }
} else { // } else {
if (this.plain) { // if (this.plain) {
style.color = this.$u.color[this.type]; // style.color = this.$u.color[this.type];
style.backgroundColor = this.$u.color[this.type + 'Light']; // style.backgroundColor = this.$u.color[this.type + 'Light'];
style.borderColor = this.$u.color[this.type + 'Disabled']; // style.borderColor = this.$u.color[this.type + 'Disabled'];
} else { // } else {
style.color = '#ffffff'; // style.color = '#ffffff';
style.backgroundColor = this.$u.color[this.type]; // style.backgroundColor = this.$u.color[this.type];
style.borderColor = this.$u.color[this.type]; // style.borderColor = this.$u.color[this.type];
} // }
} // }
} // }
return Object.assign(style, this.customStyle); return Object.assign(style, this.customStyle);
}, },
...@@ -370,6 +373,90 @@ export default { ...@@ -370,6 +373,90 @@ export default {
z-index: 1; z-index: 1;
box-sizing: border-box; box-sizing: border-box;
transition: all 0.15s; transition: all 0.15s;
&--default {
color: $u-content-color;
border-color: $u-type-warning;
background-color: #ffffff;
}
&--primary {
color: #ffffff;
border-color: $u-type-primary;
background-color: $u-type-primary;
}
&--success {
color: #ffffff;
border-color: $u-type-success;
background-color: $u-type-success;
}
&--error {
color: #ffffff;
border-color: $u-type-error;
background-color: $u-type-error;
}
&--warning {
color: #ffffff;
border-color: $u-type-warning;
background-color: $u-type-warning;
}
&--default--disabled {
color: #ffffff;
border-color: #e4e7ed;
background-color: #ffffff;
}
&--primary--disabled {
color: #ffffff!important;
border-color: $u-type-primary-disabled!important;
background-color: $u-type-primary-disabled!important;
}
&--success--disabled {
color: #ffffff!important;
border-color: $u-type-success-disabled!important;
background-color: $u-type-success-disabled!important;
}
&--error--disabled {
color: #ffffff!important;
border-color: $u-type-error-disabled!important;
background-color: $u-type-error-disabled!important;
}
&--warning--disabled {
color: #ffffff!important;
border-color: $u-type-warning-disabled!important;
background-color: $u-type-warning-disabled!important;
}
&--primary--plain {
color: $u-type-primary!important;
border-color: $u-type-primary-disabled!important;
background-color: $u-type-primary-light!important;
}
&--success--plain {
color: $u-type-success!important;
border-color: $u-type-success-disabled!important;
background-color: $u-type-success-light!important;
}
&--error--plain {
color: $u-type-error!important;
border-color: $u-type-error-disabled!important;
background-color: $u-type-error-light!important;
}
&--warning--plain {
color: $u-type-warning!important;
border-color: $u-type-warning-disabled!important;
background-color: $u-type-warning-light!important;
}
} }
.u-hairline-border:after { .u-hairline-border:after {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
</view> </view>
<slot v-else name="title" /> <slot v-else name="title" />
<view class="u-icon-wrap"> <view class="u-icon-wrap">
<u-icon v-if="arrow" :color="arrowColor ? arrowColor : $u.color.tipsColor" :class="{ 'u-arrow-down-icon-active': isShow }" <u-icon v-if="arrow" :color="arrowColor" :class="{ 'u-arrow-down-icon-active': isShow }"
class="u-arrow-down-icon" name="arrow-down"></u-icon> class="u-arrow-down-icon" name="arrow-down"></u-icon>
</view> </view>
</block> </block>
......
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
// 箭头的颜色 // 箭头的颜色
arrowColor: { arrowColor: {
type: String, type: String,
default: '' default: '#909399'
}, },
// 标题部分按压时的样式类,"none"为无效果 // 标题部分按压时的样式类,"none"为无效果
hoverClass: { hoverClass: {
......
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
background: computeBgColor, background: computeBgColor,
padding: padding padding: padding
}" }"
:class="[
type ? `u-type-${type}-light-bg` : ''
]"
> >
<view class="u-icon-wrap"> <view class="u-icon-wrap">
<u-icon class="u-left-icon" v-if="volumeIcon" name="volume-fill" :size="volumeSize" :color="computeColor"></u-icon> <u-icon class="u-left-icon" v-if="volumeIcon" name="volume-fill" :size="volumeSize" :color="computeColor"></u-icon>
...@@ -13,11 +16,9 @@ ...@@ -13,11 +16,9 @@
<swiper-item v-for="(item, index) in list" :key="index" class="u-swiper-item"> <swiper-item v-for="(item, index) in list" :key="index" class="u-swiper-item">
<view <view
class="u-news-item u-line-1" class="u-news-item u-line-1"
:style="{ :style="[textStyle]"
color: computeColor,
fontSize: fontSize + 'rpx'
}"
@tap="click(index)" @tap="click(index)"
:class="['u-type-' + type]"
> >
{{ item }} {{ item }}
</view> </view>
...@@ -136,8 +137,17 @@ export default { ...@@ -136,8 +137,17 @@ export default {
// 计算字体颜色,如果没有自定义的,就用uview主题颜色 // 计算字体颜色,如果没有自定义的,就用uview主题颜色
computeColor() { computeColor() {
if (this.color) return this.color; if (this.color) return this.color;
else if(this.type == 'none') return this.$u.color['contentColor']; // 如果是无主题,就默认使用content-color
else return this.$u.color[this.type]; else if(this.type == 'none') return '#606266';
else return this.type;
},
// 文字内容的样式
textStyle() {
let style = {};
if (this.color) style.color = this.color;
else if(this.type == 'none') style.color = '#606266';
style.fontSize = this.fontSize + 'rpx';
return style;
}, },
// 垂直或者水平滚动 // 垂直或者水平滚动
vertical() { vertical() {
...@@ -148,7 +158,6 @@ export default { ...@@ -148,7 +158,6 @@ export default {
computeBgColor() { computeBgColor() {
if (this.bgColor) return this.bgColor; if (this.bgColor) return this.bgColor;
else if(this.type == 'none') return 'transparent'; else if(this.type == 'none') return 'transparent';
else return this.$u.color[this.type + 'Light'];
} }
}, },
data() { data() {
......
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
marginBottom: marginBottom + 'rpx', marginBottom: marginBottom + 'rpx',
marginTop: marginTop + 'rpx' marginTop: marginTop + 'rpx'
}" @tap="click"> }" @tap="click">
<view class="u-divider-line" :style="[lineStyle]"></view> <view class="u-divider-line" :class="[type ? 'u-divider-line--bordercolor--' + type : '']" :style="[lineStyle]"></view>
<view v-if="useSlot" class="u-divider-text" :style="{ <view v-if="useSlot" class="u-divider-text" :style="{
color: color, color: color,
fontSize: fontSize + 'rpx' fontSize: fontSize + 'rpx'
}"><slot /></view> }"><slot /></view>
<view class="u-divider-line" :style="[lineStyle]"></view> <view class="u-divider-line" :class="[type ? 'u-divider-line--bordercolor--' + type : '']" :style="[lineStyle]"></view>
</view> </view>
</template> </template>
...@@ -93,7 +93,6 @@ export default { ...@@ -93,7 +93,6 @@ export default {
else style.width = this.halfWidth + 'rpx'; else style.width = this.halfWidth + 'rpx';
// borderColor优先级高于type值 // borderColor优先级高于type值
if(this.borderColor) style.borderColor = this.borderColor; if(this.borderColor) style.borderColor = this.borderColor;
else style.borderColor = this.$u.color[this.type];
return style; return style;
} }
}, },
...@@ -122,6 +121,26 @@ export default { ...@@ -122,6 +121,26 @@ export default {
border-bottom: 1px solid $u-border-color; border-bottom: 1px solid $u-border-color;
transform: scale(1, 0.5); transform: scale(1, 0.5);
transform-origin: center; transform-origin: center;
&--bordercolor--primary {
border-color: $u-type-primary;
}
&--bordercolor--success {
border-color: $u-type-success;
}
&--bordercolor--error {
border-color: $u-type-primary;
}
&--bordercolor--info {
border-color: $u-type-info;
}
&--bordercolor--warning {
border-color: $u-type-warning;
}
} }
.u-divider-text { .u-divider-text {
......
...@@ -39,7 +39,7 @@ export default { ...@@ -39,7 +39,7 @@ export default {
type: String, type: String,
default: '' default: ''
}, },
// 图标颜色 // 图标颜色,可接受主题色(组件内部使用,不对外)
color: { color: {
type: String, type: String,
default: '' default: ''
...@@ -110,10 +110,7 @@ export default { ...@@ -110,10 +110,7 @@ export default {
default() { default() {
return {} return {}
} }
} },
},
data() {
return {};
}, },
computed: { computed: {
customClass() { customClass() {
...@@ -122,6 +119,8 @@ export default { ...@@ -122,6 +119,8 @@ export default {
// uView的自定义图标类名为u-iconfont // uView的自定义图标类名为u-iconfont
if (this.customPrefix == 'uicon') classes.push('u-iconfont'); if (this.customPrefix == 'uicon') classes.push('u-iconfont');
else classes.push(this.customPrefix); else classes.push(this.customPrefix);
// 主题色,通过类配置
if (this.color && this.$u.config.type.includes(this.color)) classes.push('u-icon__icon--' + this.color);
// 阿里,头条,百度小程序通过数组绑定类名时,无法直接使用[a, b, c]的形式,否则无法识别 // 阿里,头条,百度小程序通过数组绑定类名时,无法直接使用[a, b, c]的形式,否则无法识别
// 故需将其拆成一个字符串的形式,通过空格隔开各个类名 // 故需将其拆成一个字符串的形式,通过空格隔开各个类名
//#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU //#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
...@@ -135,7 +134,8 @@ export default { ...@@ -135,7 +134,8 @@ export default {
fontSize: this.size == 'inherit' ? 'inherit' : this.size + 'rpx', fontSize: this.size == 'inherit' ? 'inherit' : this.size + 'rpx',
fontWeight: this.bold ? 'bold' : 'normal' fontWeight: this.bold ? 'bold' : 'normal'
}; };
if (this.color) style.color = this.color; // 非主题色值时,才当作颜色值
if (this.color && !this.$u.config.type.includes(this.color)) style.color = this.color;
return style; return style;
}, },
// 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式 // 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式
...@@ -166,10 +166,32 @@ export default { ...@@ -166,10 +166,32 @@ export default {
.u-icon { .u-icon {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
}
&__icon {
.u-icon__img { &--primary {
height: auto; color: $u-type-primary;
will-change: transform; }
&--success {
color: $u-type-success;
}
&--error {
color: $u-type-error;
}
&--warning {
color: $u-type-warning;
}
&--info {
color: $u-type-info;
}
}
&__img {
height: auto;
will-change: transform;
}
} }
</style> </style>
...@@ -4,7 +4,12 @@ ...@@ -4,7 +4,12 @@
height: height + 'rpx', height: height + 'rpx',
backgroundColor: inactiveColor backgroundColor: inactiveColor
}"> }">
<view :class="{'u-striped': striped, 'u-striped-active': striped && stripedActive}" class="u-active" :style="[progressStyle]">{{showPercent ? percent + '%' : ''}}</view> <view :class="[
type ? `u-type-${type}-bg` : '',
striped ? 'u-striped' : '',
striped && stripedActive ? 'u-striped-active' : ''
]" class="u-active" :style="[progressStyle]">{{showPercent ? percent + '%' : ''}}
</view>
</view> </view>
</template> </template>
...@@ -81,9 +86,7 @@ ...@@ -81,9 +86,7 @@
progressStyle() { progressStyle() {
let style = {}; let style = {};
style.width = this.percent + '%'; style.width = this.percent + '%';
if (['success', 'error', 'info', 'primary', 'warning'].indexOf(this.type) >= 0) style.backgroundColor = this.$u.color[ if(this.activeColor) style.backgroundColor = this.activeColor;
this.type];
else style.backgroundColor = this.activeColor;
return style; return style;
} }
}, },
......
<template> <template>
<u-popup :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto" <u-popup :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex">
:safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex">
<view class="u-datetime-picker" @tap.stop> <view class="u-datetime-picker" @tap.stop>
<view class="u-picker-header" @touchmove.stop.prevent="stop" catchtouchmove="stop"> <view class="u-picker-header" @touchmove.stop.prevent="stop" catchtouchmove="stop">
<view class="u-btn-picker u-btn-picker--tips" :style="{ color: cancelColor }" hover-class="u-opacity" :hover-stay-time="150" <view class="u-btn-picker u-btn-picker--tips" :style="{ color: cancelColor }" hover-class="u-opacity" :hover-stay-time="150" @tap="getResult('cancel')">取消</view>
@tap="getResult('cancel')">取消</view> <view class="u-picker__title">{{ title }}</view>
<view class="u-btn-picker u-btn-picker--primary" :style="{ color: confirmColor }" hover-class="u-opacity" :hover-stay-time="150" <view
@touchmove.stop="" @tap.stop="getResult('confirm')">确定</view> class="u-btn-picker u-btn-picker--primary"
:style="{ color: moving ? cancelColor : confirmColor }"
hover-class="u-opacity"
:hover-stay-time="150"
@touchmove.stop=""
@tap.stop="getResult('confirm')"
>
确定
</view>
</view> </view>
<view class="u-picker-body"> <view class="u-picker-body">
<picker-view v-if="mode == 'region'" :value="valueArr" @change="change" class="u-picker-view"> <picker-view v-if="mode == 'region'" :value="valueArr" @change="change" class="u-picker-view" @pickstart="pickstart" @pickend="pickend">
<picker-view-column v-if="params.province"> <picker-view-column v-if="params.province">
<view class="u-column-item" v-for="(item,index) in provinces" :key="index"> <view class="u-column-item" v-for="(item, index) in provinces" :key="index">
<view class="u-line-1"> <view class="u-line-1">{{ item.label }}</view>
{{item.label}}
</view>
</view> </view>
</picker-view-column> </picker-view-column>
<picker-view-column v-if="params.city"> <picker-view-column v-if="params.city">
<view class="u-column-item" v-for="(item,index) in citys" :key="index"> <view class="u-column-item" v-for="(item, index) in citys" :key="index">
<view class="u-line-1"> <view class="u-line-1">{{ item.label }}</view>
{{item.label}}
</view>
</view> </view>
</picker-view-column> </picker-view-column>
<picker-view-column v-if="params.area"> <picker-view-column v-if="params.area">
<view class="u-column-item" v-for="(item,index) in areas" :key="index"> <view class="u-column-item" v-for="(item, index) in areas" :key="index">
<view class="u-line-1"> <view class="u-line-1">{{ item.label }}</view>
{{item.label}}
</view>
</view> </view>
</picker-view-column> </picker-view-column>
</picker-view> </picker-view>
<picker-view v-else-if="mode == 'time'" :value="valueArr" @change="change" class="u-picker-view"> <picker-view v-else-if="mode == 'time'" :value="valueArr" @change="change" class="u-picker-view" @pickstart="pickstart" @pickend="pickend">
<picker-view-column v-if="!reset && params.year"> <picker-view-column v-if="!reset && params.year">
<view class="u-column-item" v-for="(item,index) in years" :key="index"> <view class="u-column-item" v-for="(item, index) in years" :key="index">
{{ item }}<text class="u-text" v-if="showTimeTag"></text> {{ item }}
<text class="u-text" v-if="showTimeTag"></text>
</view> </view>
</picker-view-column> </picker-view-column>
<picker-view-column v-if="!reset && params.month"> <picker-view-column v-if="!reset && params.month">
<view class="u-column-item" v-for="(item,index) in months" :key="index"> <view class="u-column-item" v-for="(item, index) in months" :key="index">
{{ formatNumber(item)}}<text class="u-text" v-if="showTimeTag"></text> {{ formatNumber(item) }}
<text class="u-text" v-if="showTimeTag"></text>
</view> </view>
</picker-view-column> </picker-view-column>
<picker-view-column v-if="!reset && params.day"> <picker-view-column v-if="!reset && params.day">
<view class="u-column-item" v-for="(item,index) in days" :key="index"> <view class="u-column-item" v-for="(item, index) in days" :key="index">
{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag"></text> {{ formatNumber(item) }}
<text class="u-text" v-if="showTimeTag"></text>
</view> </view>
</picker-view-column> </picker-view-column>
<picker-view-column v-if="!reset && params.hour"> <picker-view-column v-if="!reset && params.hour">
<view class="u-column-item" v-for="(item,index) in hours" :key="index"> <view class="u-column-item" v-for="(item, index) in hours" :key="index">
{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag"></text> {{ formatNumber(item) }}
<text class="u-text" v-if="showTimeTag"></text>
</view> </view>
</picker-view-column> </picker-view-column>
<picker-view-column v-if="!reset && params.minute"> <picker-view-column v-if="!reset && params.minute">
<view class="u-column-item" v-for="(item,index) in minutes" :key="index"> <view class="u-column-item" v-for="(item, index) in minutes" :key="index">
{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag"></text> {{ formatNumber(item) }}
<text class="u-text" v-if="showTimeTag"></text>
</view> </view>
</picker-view-column> </picker-view-column>
<picker-view-column v-if="!reset && params.second"> <picker-view-column v-if="!reset && params.second">
<view class="u-column-item" v-for="(item,index) in seconds" :key="index"> <view class="u-column-item" v-for="(item, index) in seconds" :key="index">
{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag"></text> {{ formatNumber(item) }}
<text class="u-text" v-if="showTimeTag"></text>
</view> </view>
</picker-view-column> </picker-view-column>
</picker-view> </picker-view>
<picker-view v-else-if="mode == 'selector'" :value="defaultSelector" @change="change" class="u-picker-view"> <picker-view v-else-if="mode == 'selector'" :value="defaultSelector" @change="change" class="u-picker-view" @pickstart="pickstart" @pickend="pickend">
<picker-view-column> <picker-view-column>
<view class="u-column-item" v-for="(item,index) in range" :key="index"> <view class="u-column-item" v-for="(item, index) in range" :key="index">
<view class="u-line-1"> <view class="u-line-1">{{ getItemValue(item, 'selector') }}</view>
{{getItemValue(item, 'selector')}}
</view>
</view> </view>
</picker-view-column> </picker-view-column>
</picker-view> </picker-view>
<picker-view v-else-if="mode == 'multiSelector'" :value="defaultSelector" @change="change" class="u-picker-view"> <picker-view v-else-if="mode == 'multiSelector'" :value="defaultSelector" @change="change" class="u-picker-view" @pickstart="pickstart" @pickend="pickend">
<picker-view-column v-for="(item,index) in range" :key="index"> <picker-view-column v-for="(item, index) in range" :key="index">
<view class="u-column-item" v-for="(item1,index1) in item" :key="index1"> <view class="u-column-item" v-for="(item1, index1) in item" :key="index1">
<view class="u-line-1"> <view class="u-line-1">{{ getItemValue(item1, 'multiSelector') }}</view>
{{getItemValue(item1, 'multiSelector')}}
</view>
</view> </view>
</picker-view-column> </picker-view-column>
</picker-view> </picker-view>
...@@ -88,532 +91,555 @@ ...@@ -88,532 +91,555 @@
</template> </template>
<script> <script>
import provinces from '../../libs/util/province.js'; import provinces from '../../libs/util/province.js';
import citys from '../../libs/util/city.js'; import citys from '../../libs/util/city.js';
import areas from '../../libs/util/area.js'; import areas from '../../libs/util/area.js';
/** /**
* picker picker弹出选择器 * picker picker弹出选择器
* @description 此选择器有两种弹出模式:一是时间模式,可以配置年,日,月,时,分,秒参数 二是地区模式,可以配置省,市,区参数 * @description 此选择器有两种弹出模式:一是时间模式,可以配置年,日,月,时,分,秒参数 二是地区模式,可以配置省,市,区参数
* @tutorial https://www.uviewui.com/components/picker.html * @tutorial https://www.uviewui.com/components/picker.html
* @property {Object} params 需要显示的参数,见官网说明 * @property {Object} params 需要显示的参数,见官网说明
* @property {String} mode 模式选择,region-地区类型,time-时间类型(默认time) * @property {String} mode 模式选择,region-地区类型,time-时间类型(默认time)
* @property {String Number} start-year 可选的开始年份,mode=time时有效(默认1950) * @property {String Number} start-year 可选的开始年份,mode=time时有效(默认1950)
* @property {String Number} end-year 可选的结束年份,mode=time时有效(默认2050) * @property {String Number} end-year 可选的结束年份,mode=time时有效(默认2050)
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配(默认false) * @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配(默认false)
* @property {Boolean} show-time-tag 时间模式时,是否显示后面的年月日中文提示 * @property {Boolean} show-time-tag 时间模式时,是否显示后面的年月日中文提示
* @property {String} cancel-color 取消按钮的颜色(默认#606266) * @property {String} cancel-color 取消按钮的颜色(默认#606266)
* @property {String} confirm-color 确认按钮的颜色(默认#2979ff) * @property {String} confirm-color 确认按钮的颜色(默认#2979ff)
* @property {String} default-time 默认选中的时间,mode=time时有效 * @property {String} default-time 默认选中的时间,mode=time时有效
* @property {String} default-region 默认选中的地区,中文形式,mode=region时有效 * @property {String} default-region 默认选中的地区,中文形式,mode=region时有效
* @property {String} default-code 默认选中的地区,编号形式,mode=region时有效 * @property {String} default-code 默认选中的地区,编号形式,mode=region时有效
* @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭Picker(默认true) * @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭Picker(默认true)
* @property {String Number} z-index 弹出时的z-index值(默认1075) * @property {String Number} z-index 弹出时的z-index值(默认1075)
* @property {Array} default-selector 数组形式,其中每一项表示选择了range对应项中的第几个 * @property {Array} default-selector 数组形式,其中每一项表示选择了range对应项中的第几个
* @property {Array} range 自定义选择的数据,mode=selector或mode=multiSelector时有效 * @property {Array} range 自定义选择的数据,mode=selector或mode=multiSelector时有效
* @property {String} range-key 当range参数的元素为对象时,指定Object中的哪个key的值作为选择器显示内容 * @property {String} range-key 当range参数的元素为对象时,指定Object中的哪个key的值作为选择器显示内容
* @event {Function} confirm 点击确定按钮,返回当前选择的值 * @event {Function} confirm 点击确定按钮,返回当前选择的值
* @event {Function} cancel 点击取消按钮,返回当前选择的值 * @event {Function} cancel 点击取消按钮,返回当前选择的值
* @example <u-picker v-model="show" mode="time"></u-picker> * @example <u-picker v-model="show" mode="time"></u-picker>
*/ */
export default { export default {
name: "u-picker", name: 'u-picker',
props: { props: {
// picker中需要显示的参数 // picker中需要显示的参数
params: { params: {
type: Object, type: Object,
default () { default() {
return { return {
year: true, year: true,
month: true, month: true,
day: true, day: true,
hour: false, hour: false,
minute: false, minute: false,
second: false, second: false,
province: true, province: true,
city: true, city: true,
area: true area: true
} };
}
},
// 当mode=selector或者mode=multiSelector时,提供的数组
range: {
type: Array,
default() {
return []
}
},
// 当mode=selector或者mode=multiSelector时,提供的默认选中的下标
defaultSelector: {
type: Array,
default() {
return [0]
}
},
// 当 range 是一个 Array<Object> 时,通过 range-key 来指定 Object 中 key 的值作为选择器显示内容
rangeKey: {
type: String,
default: ''
},
// 模式选择,region-地区类型,time-时间类型,selector-单列模式,multiSelector-多列模式
mode: {
type: String,
default: 'time'
},
// 年份开始时间
startYear: {
type: [String, Number],
default: 1950
},
// 年份结束时间
endYear: {
type: [String, Number],
default: 2050
},
// "取消"按钮的颜色
cancelColor: {
type: String,
default: '#606266'
},
// "确定"按钮的颜色
confirmColor: {
type: String,
default: '#2979ff'
},
// 默认显示的时间,2025-07-02 || 2025-07-02 13:01:00 || 2025/07/02
defaultTime: {
type: String,
default: ''
},
// 默认显示的地区,可传类似["河北省", "秦皇岛市", "北戴河区"]
defaultRegion: {
type: Array,
default () {
return [];
}
},
// 时间模式时,是否显示后面的年月日中文提示
showTimeTag: {
type: Boolean,
default: true
},
// 默认显示地区的编码,defaultRegion和areaCode同时存在,areaCode优先,可传类似["13", "1303", "130304"]
areaCode: {
type: Array,
default () {
return [];
}
},
safeAreaInsetBottom: {
type: Boolean,
default: false
},
// 是否允许通过点击遮罩关闭Picker
maskCloseAble: {
type: Boolean,
default: true
},
// 通过双向绑定控制组件的弹出与收起
value: {
type: Boolean,
default: false
},
// 弹出的z-index值
zIndex: {
type: [String, Number],
default: 0
} }
}, },
data() { // 当mode=selector或者mode=multiSelector时,提供的数组
return { range: {
years: [], type: Array,
months: [], default() {
days: [], return [];
hours: [],
minutes: [],
seconds: [],
year: 0,
month: 0,
day: 0,
hour: 0,
minute: 0,
second: 0,
startDate: "",
endDate: "",
valueArr: [],
reset: false,
provinces: provinces,
citys: citys[0],
areas: areas[0][0],
province: 0,
city: 0,
area: 0,
} }
}, },
mounted() { // 当mode=selector或者mode=multiSelector时,提供的默认选中的下标
this.init(); defaultSelector: {
}, type: Array,
computed: { default() {
propsChange() { return [0];
// 引用这几个变量,是为了监听其变化
return `${this.mode}-${this.defaultTime}-${this.startYear}-${this.endYear}-${this.defaultRegion}-${this.areaCode}`;
},
regionChange() {
// 引用这几个变量,是为了监听其变化
return `${this.province}-${this.city}`;
},
yearAndMonth() {
return `${this.year}-${this.month}`;
},
uZIndex() {
// 如果用户有传递z-index值,优先使用
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
} }
}, },
watch: { // 当 range 是一个 Array<Object> 时,通过 range-key 来指定 Object 中 key 的值作为选择器显示内容
propsChange() { rangeKey: {
type: String,
default: ''
},
// 模式选择,region-地区类型,time-时间类型,selector-单列模式,multiSelector-多列模式
mode: {
type: String,
default: 'time'
},
// 年份开始时间
startYear: {
type: [String, Number],
default: 1950
},
// 年份结束时间
endYear: {
type: [String, Number],
default: 2050
},
// "取消"按钮的颜色
cancelColor: {
type: String,
default: '#606266'
},
// "确定"按钮的颜色
confirmColor: {
type: String,
default: '#2979ff'
},
// 默认显示的时间,2025-07-02 || 2025-07-02 13:01:00 || 2025/07/02
defaultTime: {
type: String,
default: ''
},
// 默认显示的地区,可传类似["河北省", "秦皇岛市", "北戴河区"]
defaultRegion: {
type: Array,
default() {
return [];
}
},
// 时间模式时,是否显示后面的年月日中文提示
showTimeTag: {
type: Boolean,
default: true
},
// 默认显示地区的编码,defaultRegion和areaCode同时存在,areaCode优先,可传类似["13", "1303", "130304"]
areaCode: {
type: Array,
default() {
return [];
}
},
safeAreaInsetBottom: {
type: Boolean,
default: false
},
// 是否允许通过点击遮罩关闭Picker
maskCloseAble: {
type: Boolean,
default: true
},
// 通过双向绑定控制组件的弹出与收起
value: {
type: Boolean,
default: false
},
// 弹出的z-index值
zIndex: {
type: [String, Number],
default: 0
},
// 顶部标题
title: {
type: String,
default: ''
}
},
data() {
return {
years: [],
months: [],
days: [],
hours: [],
minutes: [],
seconds: [],
year: 0,
month: 0,
day: 0,
hour: 0,
minute: 0,
second: 0,
startDate: '',
endDate: '',
valueArr: [],
reset: false,
provinces: provinces,
citys: citys[0],
areas: areas[0][0],
province: 0,
city: 0,
area: 0,
moving: false // 列是否还在滑动中,微信小程序如果在滑动中就点确定,结果可能不准确
};
},
mounted() {
this.init();
},
computed: {
propsChange() {
// 引用这几个变量,是为了监听其变化
return `${this.mode}-${this.defaultTime}-${this.startYear}-${this.endYear}-${this.defaultRegion}-${this.areaCode}`;
},
regionChange() {
// 引用这几个变量,是为了监听其变化
return `${this.province}-${this.city}`;
},
yearAndMonth() {
return `${this.year}-${this.month}`;
},
uZIndex() {
// 如果用户有传递z-index值,优先使用
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
watch: {
propsChange() {
this.reset = true;
setTimeout(() => this.init(), 10);
},
// 如果地区发生变化,为了让picker联动起来,必须重置this.citys和this.areas
regionChange(val) {
this.citys = citys[this.province];
this.areas = areas[this.province][this.city];
},
// watch监听月份的变化,实时变更日的天数,因为不同月份,天数不一样
// 一个月可能有30,31天,甚至闰年2月的29天,平年2月28天
yearAndMonth(val) {
if (this.params.year) this.setDays();
},
// 微信和QQ小程序由于一些奇怪的原因(故同时对所有平台均初始化一遍),需要重新初始化才能显示正确的值
value(n) {
if (n) {
this.reset = true; this.reset = true;
setTimeout(() => this.init(), 10); setTimeout(() => this.init(), 10);
}, }
// 如果地区发生变化,为了让picker联动起来,必须重置this.citys和this.areas }
regionChange(val) { },
this.citys = citys[this.province]; methods: {
this.areas = areas[this.province][this.city]; // 标识滑动开始,只有微信小程序才有这样的事件
}, pickstart() {
// watch监听月份的变化,实时变更日的天数,因为不同月份,天数不一样 // #ifdef MP-WEIXIN
// 一个月可能有30,31天,甚至闰年2月的29天,平年2月28天 this.moving = true;
yearAndMonth(val) { // #endif
if (this.params.year) this.setDays(); },
}, // 标识滑动结束
// 微信和QQ小程序由于一些奇怪的原因(故同时对所有平台均初始化一遍),需要重新初始化才能显示正确的值 pickend() {
value(n) { // #ifdef MP-WEIXIN
if (n) { this.moving = false;
this.reset = true; // #endif
setTimeout(() => this.init(), 10); },
// 对单列和多列形式的判断是否有传入变量的情况
getItemValue(item, mode) {
// 目前(2020-05-25)uni-app对微信小程序编译有错误,导致v-if为false中的内容也执行,错误导致
// 单列模式或者多列模式中的getItemValue同时被执行,故在这里再加一层判断
if (this.mode == mode) {
return typeof item == 'object' ? item[this.rangeKey] : item;
}
},
// 小于10前面补0,用于月份,日期,时分秒等
formatNumber(num) {
return +num < 10 ? '0' + num : String(num);
},
// 生成递进的数组
generateArray: function(start, end) {
end = end > start ? end : start;
// 生成数组,获取其中的索引,并剪出来
return [...Array(end + 1).keys()].slice(start);
},
getIndex: function(arr, val) {
let index = arr.indexOf(val);
// 如果index为-1(即找不到index值),~(-1)=-(-1)-1=0,导致条件不成立
return ~index ? index : 0;
},
//日期时间处理
initTimeValue() {
// 格式化时间,在IE浏览器(uni不存在此情况),无法识别日期间的"-"间隔符号
let fdate = this.defaultTime.replace(/\-/g, '/');
fdate = fdate && fdate.indexOf('/') == -1 ? `2020/01/01 ${fdate}` : fdate;
let time = null;
if (fdate) time = new Date(fdate);
else time = new Date();
// 获取年日月时分秒
this.year = time.getFullYear();
this.month = Number(time.getMonth()) + 1;
this.day = time.getDate();
this.hour = time.getHours();
this.minute = time.getMinutes();
this.second = time.getSeconds();
},
init() {
this.valueArr = [];
this.reset = false;
if (this.mode == 'time') {
this.initTimeValue();
if (this.params.year) {
this.valueArr.push(0);
this.setYears();
}
if (this.params.month) {
this.valueArr.push(0);
this.setMonths();
}
if (this.params.day) {
this.valueArr.push(0);
this.setDays();
}
if (this.params.hour) {
this.valueArr.push(0);
this.setHours();
}
if (this.params.minute) {
this.valueArr.push(0);
this.setMinutes();
} }
if (this.params.second) {
this.valueArr.push(0);
this.setSeconds();
}
} else if (this.mode == 'region') {
if (this.params.province) {
this.valueArr.push(0);
this.setProvinces();
}
if (this.params.city) {
this.valueArr.push(0);
this.setCitys();
}
if (this.params.area) {
this.valueArr.push(0);
this.setAreas();
}
} else if (this.mode == 'selector') {
this.valueArr = this.defaultSelector;
} else if (this.mode == 'multiSelector') {
this.valueArr = this.defaultSelector;
this.multiSelectorValue = this.defaultSelector;
} }
this.$forceUpdate();
},
// 设置picker的某一列值
setYears() {
// 获取年份集合
this.years = this.generateArray(this.startYear, this.endYear);
// 设置this.valueArr某一项的值,是为了让picker预选中某一个值
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.years, this.year));
}, },
methods: { setMonths() {
// 对单列和多列形式的判断是否有传入变量的情况 this.months = this.generateArray(1, 12);
getItemValue(item, mode) { this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.months, this.month));
// 目前(2020-05-25)uni-app对微信小程序编译有错误,导致v-if为false中的内容也执行,错误导致 },
// 单列模式或者多列模式中的getItemValue同时被执行,故在这里再加一层判断 setDays() {
if(this.mode == mode) { let totalDays = new Date(this.year, this.month, 0).getDate();
return typeof item == 'object' ? item[this.rangeKey] : item this.days = this.generateArray(1, totalDays);
let index = 0;
// 这里不能使用类似setMonths()中的this.valueArr.splice(this.valueArr.length - 1, xxx)做法
// 因为this.month和this.year变化时,会触发watch中的this.setDays(),导致this.valueArr.length计算有误
if (this.params.year && this.params.month) index = 2;
else if (this.params.month) index = 1;
else if (this.params.year) index = 1;
else index = 0;
this.valueArr.splice(index, 1, this.getIndex(this.days, this.day));
},
setHours() {
this.hours = this.generateArray(0, 23);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.hours, this.hour));
},
setMinutes() {
this.minutes = this.generateArray(0, 59);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.minutes, this.minute));
},
setSeconds() {
this.seconds = this.generateArray(0, 59);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.seconds, this.second));
},
setProvinces() {
// 判断是否需要province参数
if (!this.params.province) return;
let tmp = '';
let useCode = false;
// 如果同时配置了defaultRegion和areaCode,优先使用areaCode参数
if (this.areaCode.length) {
tmp = this.areaCode[0];
useCode = true;
} else if (this.defaultRegion.length) tmp = this.defaultRegion[0];
else tmp = 0;
// 历遍省份数组匹配
provinces.map((v, k) => {
if (useCode ? v.value == tmp : v.label == tmp) {
tmp = k;
} }
}, });
// 小于10前面补0,用于月份,日期,时分秒等 this.province = tmp;
formatNumber(num) { this.provinces = provinces;
return +num < 10 ? '0' + num : String(num); // 设置默认省份的值
}, this.valueArr.splice(0, 1, this.province);
// 生成递进的数组 },
generateArray: function(start, end) { setCitys() {
end = end > start ? end : start; if (!this.params.city) return;
// 生成数组,获取其中的索引,并剪出来 let tmp = '';
return [...Array(end + 1).keys()].slice(start); let useCode = false;
}, if (this.areaCode.length) {
getIndex: function(arr, val) { tmp = this.areaCode[1];
let index = arr.indexOf(val); useCode = true;
// 如果index为-1(即找不到index值),~(-1)=-(-1)-1=0,导致条件不成立 } else if (this.defaultRegion.length) tmp = this.defaultRegion[1];
return ~index ? index : 0; else tmp = 0;
}, citys[this.province].map((v, k) => {
//日期时间处理 if (useCode ? v.value == tmp : v.label == tmp) {
initTimeValue() { tmp = k;
// 格式化时间,在IE浏览器(uni不存在此情况),无法识别日期间的"-"间隔符号
let fdate = this.defaultTime.replace(/\-/g, '/');
fdate = fdate && fdate.indexOf("/") == -1 ? `2020/01/01 ${fdate}` : fdate
let time = null;
if (fdate)
time = new Date(fdate);
else
time = new Date();
// 获取年日月时分秒
this.year = time.getFullYear()
this.month = Number(time.getMonth()) + 1;
this.day = time.getDate();
this.hour = time.getHours();
this.minute = time.getMinutes();
this.second = time.getSeconds();
},
init() {
this.valueArr = [];
this.reset = false;
if (this.mode == 'time') {
this.initTimeValue();
if (this.params.year) {
this.valueArr.push(0);
this.setYears();
}
if (this.params.month) {
this.valueArr.push(0);
this.setMonths();
}
if (this.params.day) {
this.valueArr.push(0);
this.setDays();
}
if (this.params.hour) {
this.valueArr.push(0);
this.setHours();
}
if (this.params.minute) {
this.valueArr.push(0);
this.setMinutes();
}
if (this.params.second) {
this.valueArr.push(0);
this.setSeconds();
}
} else if(this.mode == 'region') {
if (this.params.province) {
this.valueArr.push(0);
this.setProvinces();
}
if (this.params.city) {
this.valueArr.push(0);
this.setCitys();
}
if (this.params.area) {
this.valueArr.push(0);
this.setAreas();
}
} else if(this.mode == 'selector') {
this.valueArr = this.defaultSelector;
} else if(this.mode == 'multiSelector') {
this.valueArr = this.defaultSelector;
this.multiSelectorValue = this.defaultSelector;
} }
this.$forceUpdate(); });
}, this.city = tmp;
// 设置picker的某一列值 this.citys = citys[this.province];
setYears() { this.valueArr.splice(1, 1, this.city);
// 获取年份集合 },
this.years = this.generateArray(this.startYear, this.endYear); setAreas() {
// 设置this.valueArr某一项的值,是为了让picker预选中某一个值 if (!this.params.area) return;
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.years, this.year)); let tmp = '';
}, let useCode = false;
setMonths() { if (this.areaCode.length) {
this.months = this.generateArray(1, 12); tmp = this.areaCode[2];
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.months, this.month)); useCode = true;
}, } else if (this.defaultRegion.length) tmp = this.defaultRegion[2];
setDays() { else tmp = 0;
let totalDays = new Date(this.year, this.month, 0).getDate(); areas[this.province][this.city].map((v, k) => {
this.days = this.generateArray(1, totalDays); if (useCode ? v.value == tmp : v.label == tmp) {
let index = 0; tmp = k;
// 这里不能使用类似setMonths()中的this.valueArr.splice(this.valueArr.length - 1, xxx)做法
// 因为this.month和this.year变化时,会触发watch中的this.setDays(),导致this.valueArr.length计算有误
if (this.params.year && this.params.month) index = 2;
else if (this.params.month) index = 1;
else if (this.params.year) index = 1;
else index = 0;
this.valueArr.splice(index, 1, this.getIndex(this.days, this.day));
},
setHours() {
this.hours = this.generateArray(0, 23);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.hours, this.hour));
},
setMinutes() {
this.minutes = this.generateArray(0, 59);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.minutes, this.minute));
},
setSeconds() {
this.seconds = this.generateArray(0, 59);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.seconds, this.second));
},
setProvinces() {
// 判断是否需要province参数
if (!this.params.province) return;
let tmp = '';
let useCode = false;
// 如果同时配置了defaultRegion和areaCode,优先使用areaCode参数
if (this.areaCode.length) {
tmp = this.areaCode[0];
useCode = true;
} else if (this.defaultRegion.length) tmp = this.defaultRegion[0];
else tmp = 0;
// 历遍省份数组匹配
provinces.map((v, k) => {
if (useCode ? v.value == tmp : v.label == tmp) {
tmp = k;
}
})
this.province = tmp;
this.provinces = provinces;
// 设置默认省份的值
this.valueArr.splice(0, 1, this.province);
},
setCitys() {
if (!this.params.city) return;
let tmp = '';
let useCode = false;
if (this.areaCode.length) {
tmp = this.areaCode[1];
useCode = true;
} else if (this.defaultRegion.length) tmp = this.defaultRegion[1];
else tmp = 0;
citys[this.province].map((v, k) => {
if (useCode ? v.value == tmp : v.label == tmp) {
tmp = k;
}
})
this.city = tmp;
this.citys = citys[this.province];
this.valueArr.splice(1, 1, this.city);
},
setAreas() {
if (!this.params.area) return;
let tmp = '';
let useCode = false;
if (this.areaCode.length) {
tmp = this.areaCode[2];
useCode = true;
} else if (this.defaultRegion.length) tmp = this.defaultRegion[2];
else tmp = 0;
areas[this.province][this.city].map((v, k) => {
if (useCode ? v.value == tmp : v.label == tmp) {
tmp = k;
}
})
this.area = tmp;
this.areas = areas[this.province][this.city];
this.valueArr.splice(2, 1, this.area);
},
close() {
this.$emit('input', false);
},
// 用户更改picker的列选项
change(e) {
this.valueArr = e.detail.value;
let i = 0;
if (this.mode == 'time') {
// 这里使用i++,是因为this.valueArr数组的长度是不确定长度的,它根据this.params的值来配置长度
// 进入if规则,i会加1,保证了能获取准确的值
if (this.params.year) this.year = this.years[this.valueArr[i++]];
if (this.params.month) this.month = this.months[this.valueArr[i++]];
if (this.params.day) this.day = this.days[this.valueArr[i++]];
if (this.params.hour) this.hour = this.hours[this.valueArr[i++]];
if (this.params.minute) this.minute = this.minutes[this.valueArr[i++]];
if (this.params.second) this.second = this.seconds[this.valueArr[i++]];
} else if(this.mode == 'region') {
if (this.params.province) this.province = this.valueArr[i++];
if (this.params.city) this.city = this.valueArr[i++];
if (this.params.area) this.area = this.valueArr[i++];
} else if(this.mode == 'multiSelector') {
let index = null;
// 对比前后两个数组,寻找变更的是哪一列,如果某一个元素不同,即可判定该列发生了变化
this.defaultSelector.map((val, idx) => {
if(val != e.detail.value[idx]) index = idx;
})
// 为了让用户对多列变化时,对动态设置其他列的变更
if(index != null) {
this.$emit('columnchange', {
column: index,
index: e.detail.value[index]
})
}
}
},
// 用户点击确定按钮
getResult(event = null) {
let result = {};
// 只返回用户在this.params中配置了为true的字段
if (this.mode == 'time') {
if (this.params.year) result.year = this.formatNumber(this.year || 0);
if (this.params.month) result.month = this.formatNumber(this.month || 0);
if (this.params.day) result.day = this.formatNumber(this.day || 0);
if (this.params.hour) result.hour = this.formatNumber(this.hour || 0);
if (this.params.minute) result.minute = this.formatNumber(this.minute || 0);
if (this.params.second) result.second = this.formatNumber(this.second || 0);
} else if (this.mode == 'region') {
if (this.params.province) result.province = provinces[this.province];
if (this.params.city) result.city = citys[this.province][this.city];
if (this.params.area) result.area = areas[this.province][this.city][this.area];
} else if (this.mode == 'selector') {
result = this.valueArr;
} else if (this.mode == 'multiSelector') {
result = this.valueArr;
} }
if (event) this.$emit(event, result); });
this.close(); this.area = tmp;
this.areas = areas[this.province][this.city];
this.valueArr.splice(2, 1, this.area);
},
close() {
this.$emit('input', false);
},
// 用户更改picker的列选项
change(e) {
this.valueArr = e.detail.value;
let i = 0;
if (this.mode == 'time') {
// 这里使用i++,是因为this.valueArr数组的长度是不确定长度的,它根据this.params的值来配置长度
// 进入if规则,i会加1,保证了能获取准确的值
if (this.params.year) this.year = this.years[this.valueArr[i++]];
if (this.params.month) this.month = this.months[this.valueArr[i++]];
if (this.params.day) this.day = this.days[this.valueArr[i++]];
if (this.params.hour) this.hour = this.hours[this.valueArr[i++]];
if (this.params.minute) this.minute = this.minutes[this.valueArr[i++]];
if (this.params.second) this.second = this.seconds[this.valueArr[i++]];
} else if (this.mode == 'region') {
if (this.params.province) this.province = this.valueArr[i++];
if (this.params.city) this.city = this.valueArr[i++];
if (this.params.area) this.area = this.valueArr[i++];
} else if (this.mode == 'multiSelector') {
let index = null;
// 对比前后两个数组,寻找变更的是哪一列,如果某一个元素不同,即可判定该列发生了变化
this.defaultSelector.map((val, idx) => {
if (val != e.detail.value[idx]) index = idx;
});
// 为了让用户对多列变化时,对动态设置其他列的变更
if (index != null) {
this.$emit('columnchange', {
column: index,
index: e.detail.value[index]
});
}
}
},
// 用户点击确定按钮
getResult(event = null) {
// #ifdef MP-WEIXIN
if (this.moving) return;
// #endif
let result = {};
// 只返回用户在this.params中配置了为true的字段
if (this.mode == 'time') {
if (this.params.year) result.year = this.formatNumber(this.year || 0);
if (this.params.month) result.month = this.formatNumber(this.month || 0);
if (this.params.day) result.day = this.formatNumber(this.day || 0);
if (this.params.hour) result.hour = this.formatNumber(this.hour || 0);
if (this.params.minute) result.minute = this.formatNumber(this.minute || 0);
if (this.params.second) result.second = this.formatNumber(this.second || 0);
} else if (this.mode == 'region') {
if (this.params.province) result.province = provinces[this.province];
if (this.params.city) result.city = citys[this.province][this.city];
if (this.params.area) result.area = areas[this.province][this.city][this.area];
} else if (this.mode == 'selector') {
result = this.valueArr;
} else if (this.mode == 'multiSelector') {
result = this.valueArr;
} }
if (event) this.$emit(event, result);
this.close();
} }
} }
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "../../libs/css/style.components.scss"; @import '../../libs/css/style.components.scss';
.u-datetime-picker {
position: relative;
z-index: 999;
}
.u-picker-view { .u-datetime-picker {
height: 100%; position: relative;
box-sizing: border-box; z-index: 999;
} }
.u-picker-header { .u-picker-view {
width: 100%; height: 100%;
height: 90rpx; box-sizing: border-box;
padding: 0 40rpx; }
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
font-size: 32rpx;
background: #fff;
position: relative;
}
.u-picker-header::after { .u-picker-header {
content: ''; width: 100%;
position: absolute; height: 90rpx;
border-bottom: 1rpx solid #eaeef1; padding: 0 40rpx;
-webkit-transform: scaleY(0.5); display: flex;
transform: scaleY(0.5); justify-content: space-between;
bottom: 0; align-items: center;
right: 0; box-sizing: border-box;
left: 0; font-size: 30rpx;
} background: #fff;
position: relative;
}
.u-picker-body { .u-picker-header::after {
width: 100%; content: '';
height: 500rpx; position: absolute;
overflow: hidden; border-bottom: 1rpx solid #eaeef1;
background-color: #fff; -webkit-transform: scaleY(0.5);
} transform: scaleY(0.5);
bottom: 0;
right: 0;
left: 0;
}
.u-column-item { .u-picker__title {
display: flex; color: $u-content-color;
align-items: center; }
justify-content: center;
font-size: 32rpx;
color: $u-main-color;
padding: 0 8rpx;
}
.u-text { .u-picker-body {
font-size: 24rpx; width: 100%;
padding-left: 8rpx; height: 500rpx;
} overflow: hidden;
background-color: #fff;
}
.u-btn-picker { .u-column-item {
padding: 16rpx; display: flex;
box-sizing: border-box; align-items: center;
text-align: center; justify-content: center;
text-decoration: none; font-size: 32rpx;
} color: $u-main-color;
padding: 0 8rpx;
}
.u-opacity { .u-text {
opacity: 0.5; font-size: 24rpx;
} padding-left: 8rpx;
}
.u-btn-picker--primary {
color: $u-type-primary; .u-btn-picker {
} padding: 16rpx;
box-sizing: border-box;
.u-btn-picker--tips { text-align: center;
color: $u-tips-color; text-decoration: none;
} }
.u-opacity {
opacity: 0.5;
}
.u-btn-picker--primary {
color: $u-type-primary;
}
.u-btn-picker--tips {
color: $u-tips-color;
}
</style> </style>
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
background: computeBgColor, background: computeBgColor,
padding: padding padding: padding
}" }"
:class="[
type ? `u-type-${type}-light-bg` : ''
]"
> >
<view class="u-direction-row"> <view class="u-direction-row">
<view class="u-icon-wrap"> <view class="u-icon-wrap">
...@@ -17,13 +20,11 @@ ...@@ -17,13 +20,11 @@
id="u-notice-content" id="u-notice-content"
:style="{ :style="{
animationDuration: animationDuration, animationDuration: animationDuration,
color: computeColor,
animationPlayState: animationPlayState, animationPlayState: animationPlayState,
}" }"
> >
<text class="u-notice-text" @tap="click" :style="{ <text class="u-notice-text" @tap="click" :style="[textStyle]"
fontSize: fontSize + 'rpx', :class="['u-type-' + type]">{{showText}}</text>
}">{{showText}}</text>
</view> </view>
</view> </view>
<view class="u-icon-wrap"> <view class="u-icon-wrap">
...@@ -141,14 +142,22 @@ export default { ...@@ -141,14 +142,22 @@ export default {
// 计算字体颜色,如果没有自定义的,就用uview主题颜色 // 计算字体颜色,如果没有自定义的,就用uview主题颜色
computeColor() { computeColor() {
if (this.color) return this.color; if (this.color) return this.color;
else if(this.type == 'none') return this.$u.color['contentColor']; // 如果是无主题,就默认使用content-color
else return this.$u.color[this.type]; else if(this.type == 'none') return '#606266';
else return this.type;
},
// 文字内容的样式
textStyle() {
let style = {};
if (this.color) style.color = this.color;
else if(this.type == 'none') style.color = '#606266';
style.fontSize = this.fontSize + 'rpx';
return style;
}, },
// 计算背景颜色 // 计算背景颜色
computeBgColor() { computeBgColor() {
if (this.bgColor) return this.bgColor; if (this.bgColor) return this.bgColor;
else if(this.type == 'none') return 'transparent'; else if(this.type == 'none') return 'transparent';
else return this.$u.color[this.type + 'Light'];
} }
}, },
mounted() { mounted() {
......
...@@ -21,9 +21,12 @@ ...@@ -21,9 +21,12 @@
> >
取消 取消
</view> </view>
<view class="u-select__header__title">
{{title}}
</view>
<view <view
class="u-select__header__confirm u-select__header__btn" class="u-select__header__confirm u-select__header__btn"
:style="{ color: confirmColor }" :style="{ color: moving ? cancelColor : confirmColor }"
hover-class="u-hover-class" hover-class="u-hover-class"
:hover-stay-time="150" :hover-stay-time="150"
@touchmove.stop="" @touchmove.stop=""
...@@ -33,7 +36,7 @@ ...@@ -33,7 +36,7 @@
</view> </view>
</view> </view>
<view class="u-select__body"> <view class="u-select__body">
<picker-view @change="columnChange" class="u-select__body__picker-view" :value="defaultSelector"> <picker-view @change="columnChange" class="u-select__body__picker-view" :value="defaultSelector" @pickstart="pickstart" @pickend="pickend">
<picker-view-column v-for="(item, index) in columnData" :key="index"> <picker-view-column v-for="(item, index) in columnData" :key="index">
<view class="u-select__body__picker-view__item" v-for="(item1, index1) in item" :key="index1"> <view class="u-select__body__picker-view__item" v-for="(item1, index1) in item" :key="index1">
<view class="u-line-1">{{ item1[labelName] }}</view> <view class="u-line-1">{{ item1[labelName] }}</view>
...@@ -116,6 +119,11 @@ export default { ...@@ -116,6 +119,11 @@ export default {
childName: { childName: {
type: String, type: String,
default: 'children' default: 'children'
},
// 顶部标题
title: {
type: String,
default: ''
} }
}, },
data() { data() {
...@@ -130,6 +138,8 @@ export default { ...@@ -130,6 +138,8 @@ export default {
lastSelectIndex: [], lastSelectIndex: [],
// 列数 // 列数
columnNum: 0, columnNum: 0,
// 列是否还在滑动中,微信小程序如果在滑动中就点确定,结果可能不准确
moving: false
}; };
}, },
watch: { watch: {
...@@ -148,6 +158,18 @@ export default { ...@@ -148,6 +158,18 @@ export default {
}, },
}, },
methods: { methods: {
// 标识滑动开始,只有微信小程序才有这样的事件
pickstart() {
// #ifdef MP-WEIXIN
this.moving = true;
// #endif
},
// 标识滑动结束
pickend() {
// #ifdef MP-WEIXIN
this.moving = false;
// #endif
},
init() { init() {
this.setColumnNum(); this.setColumnNum();
this.setDefaultSelector(); this.setDefaultSelector();
...@@ -281,6 +303,9 @@ export default { ...@@ -281,6 +303,9 @@ export default {
}, },
// 点击确定或者取消 // 点击确定或者取消
getResult(event = null) { getResult(event = null) {
// #ifdef MP-WEIXIN
if (this.moving) return;
// #endif
if (event) this.$emit(event, this.selectValue); if (event) this.$emit(event, this.selectValue);
this.close(); this.close();
}, },
...@@ -295,6 +320,7 @@ export default { ...@@ -295,6 +320,7 @@ export default {
@import "../../libs/css/style.components.scss"; @import "../../libs/css/style.components.scss";
.u-select { .u-select {
&__action { &__action {
position: relative; position: relative;
line-height: $u-form-item-height; line-height: $u-form-item-height;
...@@ -314,6 +340,12 @@ export default { ...@@ -314,6 +340,12 @@ export default {
} }
} }
&__hader {
&__title {
color: $u-content-color;
}
}
&--border { &--border {
border-radius: 6rpx; border-radius: 6rpx;
border-radius: 4px; border-radius: 4px;
......
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
<view class="u-steps"> <view class="u-steps">
<view class="u-steps-item" v-for="(item,index) in list" :key="index"> <view class="u-steps-item" v-for="(item,index) in list" :key="index">
<view class="u-steps-item-num" v-if="mode == 'number' && current < index">{{index+1}}</view> <view class="u-steps-item-num" v-if="mode == 'number' && current < index">{{index+1}}</view>
<view class="u-steps-item-dot" v-if="mode == 'dot'" :style="{backgroundColor: index <= current ? innerActiveColor : unActiveColor}"></view> <view class="u-steps-item-dot" v-if="mode == 'dot'" :style="{backgroundColor: index <= current ? activeColor : unActiveColor}"></view>
<u-icon size="22" class="u-steps-item-checked" :style="{backgroundColor: index <= current ? innerActiveColor : unActiveColor}" <u-icon size="22" class="u-steps-item-checked" :style="{backgroundColor: index <= current ? activeColor : unActiveColor}"
v-if="mode == 'number' && current >= index" name="checkmark"></u-icon> v-if="mode == 'number' && current >= index" :name="icon"></u-icon>
<text :style="{color: index <= current ? innerActiveColor : unActiveColor}">{{item.name}}</text> <text :style="{color: index <= current ? activeColor : unActiveColor}">{{item.name}}</text>
<view class="u-steps-item-line" :style="{backgroundColor: index <= current ? innerActiveColor : unActiveColor, top: mode == 'dot' ? '24rpx' : '36rpx'}"> <view class="u-steps-item-line" :style="{backgroundColor: index <= current ? activeColor : unActiveColor, top: mode == 'dot' ? '24rpx' : '36rpx'}">
</view> </view>
</view> </view>
</view> </view>
...@@ -55,12 +55,17 @@ ...@@ -55,12 +55,17 @@
// 激活步骤的颜色 // 激活步骤的颜色
activeColor: { activeColor: {
type: String, type: String,
default: '' default: '#2979ff'
}, },
// 未激活的颜色 // 未激活的颜色
unActiveColor: { unActiveColor: {
type: String, type: String,
default: '#606266' default: '#606266'
},
// 自定义图标
icon: {
type: String,
default: 'checkmark'
} }
}, },
data() { data() {
...@@ -68,13 +73,6 @@ ...@@ -68,13 +73,6 @@
} }
}, },
computed: {
innerActiveColor() {
if (this.activeColor) return this.activeColor;
else if (this.type) return this.$u.color[this.type];
else return "#2979ff";
},
}
} }
</script> </script>
......
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
class="u-tag" :style="[customStyle]" @tap="clickTag"> class="u-tag" :style="[customStyle]" @tap="clickTag">
{{text}} {{text}}
<view class="u-icon-wrap" @tap.stop> <view class="u-icon-wrap" @tap.stop>
<u-icon @click="close" size="22" v-if="closeable" name="close" class="u-close-icon" :style="[iconStyle]"></u-icon> <u-icon @click="close" size="22" v-if="closeable" :color="closeIconColor"
name="close" class="u-close-icon" :style="[iconStyle]"></u-icon>
</view> </view>
</view> </view>
</template> </template>
...@@ -124,10 +125,21 @@ ...@@ -124,10 +125,21 @@
let style = {}; let style = {};
if(this.size == 'mini') style.fontSize = '20rpx'; if(this.size == 'mini') style.fontSize = '20rpx';
else style.fontSize = '22rpx'; else style.fontSize = '22rpx';
if(this.mode == 'plain' || this.mode == 'light') style.color = this.$u.color[this.type]; if(this.mode == 'plain' || this.mode == 'light') style.color = this.type;
else if(this.mode == 'dark') style.color = "#ffffff"; else if(this.mode == 'dark') style.color = "#ffffff";
if(this.closeColor) style.color = this.closeColor; if(this.closeColor) style.color = this.closeColor;
return style; return style;
},
// 关闭图标的颜色
closeIconColor() {
// 如果定义了关闭图标的颜色,就用此值,否则用字体颜色的值
// 如果上面的二者都没有,如果是dark深色模式,图标就为白色
// 最后如果上面的三者都不合适,就返回type值给图标获取颜色
let color = '';
if(this.closeColor) return this.closeColor;
else if(this.color) return this.color;
else if(this.mode == 'dark') return '#ffffff';
else return this.type;
} }
}, },
methods: { methods: {
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
zIndex: uZIndex zIndex: uZIndex
}"> }">
<view class="u-icon-wrap"> <view class="u-icon-wrap">
<u-icon v-if="config.icon" class="u-icon" :name="iconName" :size="30" :color="$u.color[config.type]"></u-icon> <u-icon v-if="config.icon" class="u-icon" :name="iconName" :size="30" :color="config.type"></u-icon>
</view> </view>
<text class="u-text">{{config.title}}</text> <text class="u-text">{{config.title}}</text>
</view> </view>
......
<template> <template>
<view class="u-upload" v-if="!disabled"> <view class="u-upload" v-if="!disabled">
<view v-if="showUploadList" class="u-list-item u-preview-wrap" v-for="(item, index) in lists" :key="index" :style="{ <view
width: width + 'rpx', v-if="showUploadList"
height: width + 'rpx' class="u-list-item u-preview-wrap"
}"> v-for="(item, index) in lists"
<view v-if="deletable" class="u-delete-icon" @tap.stop="deleteItem(index)" :style="{ :key="index"
background: delBgColor :style="{
}"> width: width + 'rpx',
height: width + 'rpx'
}"
>
<view
v-if="deletable"
class="u-delete-icon"
@tap.stop="deleteItem(index)"
:style="{
background: delBgColor
}"
>
<u-icon class="u-icon" :name="delIcon" size="20" :color="delColor"></u-icon> <u-icon class="u-icon" :name="delIcon" size="20" :color="delColor"></u-icon>
</view> </view>
<u-line-progress v-if="showProgress && item.progress > 0 && !item.error" :show-percent="false" height="16" class="u-progress" :percent="item.progress"></u-line-progress> <u-line-progress
v-if="showProgress && item.progress > 0 && !item.error"
:show-percent="false"
height="16"
class="u-progress"
:percent="item.progress"
></u-line-progress>
<view @tap.stop="retry(index)" v-if="item.error" class="u-error-btn">点击重试</view> <view @tap.stop="retry(index)" v-if="item.error" class="u-error-btn">点击重试</view>
<image @tap.stop="doPreviewImage(item.url || item.path, index)" class="u-preview-image" v-if="!item.isImage" :src=" item.url || item.path " <image @tap.stop="doPreviewImage(item.url || item.path, index)" class="u-preview-image" v-if="!item.isImage" :src="item.url || item.path" :mode="imageMode"></image>
:mode="imageMode"></image>
</view> </view>
<slot name="file" :file="lists"></slot> <slot name="file" :file="lists"></slot>
<view style="display: inline-block;" @tap="selectFile" v-if="maxCount > lists.length"> <view style="display: inline-block;" @tap="selectFile" v-if="maxCount > lists.length">
<slot name="addBtn"></slot> <slot name="addBtn"></slot>
<view v-if="!customBtn" class="u-list-item u-add-wrap" hover-class="u-add-wrap__hover" hover-stay-time="150" :style="{ <view
width: width + 'rpx', v-if="!customBtn"
height: width + 'rpx' class="u-list-item u-add-wrap"
}"> hover-class="u-add-wrap__hover"
hover-stay-time="150"
:style="{
width: width + 'rpx',
height: width + 'rpx'
}"
>
<u-icon name="plus" class="u-add-btn" size="40"></u-icon> <u-icon name="plus" class="u-add-btn" size="40"></u-icon>
<view class="u-add-tips">{{uploadText}}</view> <view class="u-add-tips">{{ uploadText }}</view>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
/** /**
* upload 图片上传 * upload 图片上传
* @description 该组件用于上传图片场景 * @description 该组件用于上传图片场景
* @tutorial https://www.uviewui.com/components/upload.html * @tutorial https://www.uviewui.com/components/upload.html
* @property {String} action 服务器上传地址 * @property {String} action 服务器上传地址
* @property {String Number} max-count 最大选择图片的数量(默认99) * @property {String Number} max-count 最大选择图片的数量(默认99)
* @property {Boolean} custom-btn 如果需要自定义选择图片的按钮,设置为true(默认false) * @property {Boolean} custom-btn 如果需要自定义选择图片的按钮,设置为true(默认false)
* @property {Boolean} show-progress 是否显示进度条(默认true) * @property {Boolean} show-progress 是否显示进度条(默认true)
* @property {Boolean} disabled 是否启用(显示/移仓)组件(默认false) * @property {Boolean} disabled 是否启用(显示/移仓)组件(默认false)
* @property {String} image-mode 预览图片等显示模式,可选值为uni的image的mode属性值(默认aspectFill) * @property {String} image-mode 预览图片等显示模式,可选值为uni的image的mode属性值(默认aspectFill)
* @property {String} del-icon 右上角删除图标名称,只能为uView内置图标 * @property {String} del-icon 右上角删除图标名称,只能为uView内置图标
* @property {String} del-bg-color 右上角关闭按钮的背景颜色 * @property {String} del-bg-color 右上角关闭按钮的背景颜色
* @property {String} del-color 右上角关闭按钮图标的颜色 * @property {String} del-color 右上角关闭按钮图标的颜色
* @property {Object} header 上传携带的头信息,对象形式 * @property {Object} header 上传携带的头信息,对象形式
* @property {Object} form-data 上传额外携带的参数 * @property {Object} form-data 上传额外携带的参数
* @property {String} name 上传文件的字段名,供后端获取使用(默认file) * @property {String} name 上传文件的字段名,供后端获取使用(默认file)
* @property {Array<String>} size-type original 原图,compressed 压缩图,默认二者都有(默认['original', 'compressed']) * @property {Array<String>} size-type original 原图,compressed 压缩图,默认二者都有(默认['original', 'compressed'])
* @property {Array<String>} source-type 选择图片的来源,album-从相册选图,camera-使用相机,默认二者都有(默认['album', 'camera']) * @property {Array<String>} source-type 选择图片的来源,album-从相册选图,camera-使用相机,默认二者都有(默认['album', 'camera'])
* @property {Boolean} preview-full-image 是否可以通过uni.previewImage预览已选择的图片(默认true) * @property {Boolean} preview-full-image 是否可以通过uni.previewImage预览已选择的图片(默认true)
* @property {Boolean} multiple 是否开启图片多选,部分安卓机型不支持(默认true) * @property {Boolean} multiple 是否开启图片多选,部分安卓机型不支持(默认true)
* @property {Boolean} deletable 是否显示删除图片的按钮(默认true) * @property {Boolean} deletable 是否显示删除图片的按钮(默认true)
* @property {String Number} max-size 选择单个文件的最大大小,单位B(byte),默认不限制(默认Number.MAX_VALUE) * @property {String Number} max-size 选择单个文件的最大大小,单位B(byte),默认不限制(默认Number.MAX_VALUE)
* @property {Array<Object>} file-list 默认显示的图片列表,数组元素为对象,必须提供url属性 * @property {Array<Object>} file-list 默认显示的图片列表,数组元素为对象,必须提供url属性
* @property {Boolean} upload-text 选择图片按钮的提示文字(默认“选择图片”) * @property {Boolean} upload-text 选择图片按钮的提示文字(默认“选择图片”)
* @property {Boolean} auto-upload 选择完图片是否自动上传,见上方说明(默认true) * @property {Boolean} auto-upload 选择完图片是否自动上传,见上方说明(默认true)
* @property {Boolean} show-tips 特殊情况下是否自动提示toast,见上方说明(默认true) * @property {Boolean} show-tips 特殊情况下是否自动提示toast,见上方说明(默认true)
* @property {Boolean} show-upload-list 是否显示组件内部的图片预览(默认true) * @property {Boolean} show-upload-list 是否显示组件内部的图片预览(默认true)
* @event {Function} on-oversize 图片大小超出最大允许大小 * @event {Function} on-oversize 图片大小超出最大允许大小
* @event {Function} on-preview 全屏预览图片时触发 * @event {Function} on-preview 全屏预览图片时触发
* @event {Function} on-remove 移除图片时触发 * @event {Function} on-remove 移除图片时触发
* @event {Function} on-success 图片上传成功时触发 * @event {Function} on-success 图片上传成功时触发
* @event {Function} on-change 图片上传后,无论成功或者失败都会触发 * @event {Function} on-change 图片上传后,无论成功或者失败都会触发
* @event {Function} on-error 图片上传失败时触发 * @event {Function} on-error 图片上传失败时触发
* @event {Function} on-progress 图片上传过程中的进度变化过程触发 * @event {Function} on-progress 图片上传过程中的进度变化过程触发
* @event {Function} on-uploaded 所有图片上传完毕触发 * @event {Function} on-uploaded 所有图片上传完毕触发
* @event {Function} on-choose-complete 每次选择图片后触发,只是让外部可以得知每次选择后,内部的文件列表 * @event {Function} on-choose-complete 每次选择图片后触发,只是让外部可以得知每次选择后,内部的文件列表
* @example <u-upload :action="action" :file-list="fileList" ></u-upload> * @example <u-upload :action="action" :file-list="fileList" ></u-upload>
*/ */
export default { export default {
name: 'u-upload', name: 'u-upload',
props: { props: {
//是否显示组件自带的图片预览功能 //是否显示组件自带的图片预览功能
showUploadList: { showUploadList: {
type: Boolean, type: Boolean,
default: true default: true
}, },
// 后端地址 // 后端地址
action: { action: {
type: String, type: String,
default: '' default: ''
}, },
// 最大上传数量 // 最大上传数量
maxCount: { maxCount: {
type: [String, Number], type: [String, Number],
default: 52 default: 52
}, },
// 是否显示进度条 // 是否显示进度条
showProgress: { showProgress: {
type: Boolean, type: Boolean,
default: true default: true
}, },
// 是否启用 // 是否启用
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false default: false
}, },
// 预览上传的图片时的裁剪模式,和image组件mode属性一致 // 预览上传的图片时的裁剪模式,和image组件mode属性一致
imageMode: { imageMode: {
type: String, type: String,
default: 'aspectFill' default: 'aspectFill'
}, },
// 头部信息 // 头部信息
header: { header: {
type: Object, type: Object,
default () { default() {
return {} return {};
}
},
// 额外携带的参数
formData: {
type: Object,
default () {
return {}
}
},
// 上传的文件字段名
name: {
type: String,
default: 'file'
},
// 所选的图片的尺寸, 可选值为original compressed
sizeType: {
type: Array,
default () {
return ['original', 'compressed']
}
},
sourceType: {
type: Array,
default () {
return ['album', 'camera']
}
},
// 是否在点击预览图后展示全屏图片预览
previewFullImage: {
type: Boolean,
default: true
},
// 是否开启图片多选,部分安卓机型不支持
multiple: {
type: Boolean,
default: true
},
// 是否展示删除按钮
deletable: {
type: Boolean,
default: true
},
// 文件大小限制,单位为byte
maxSize: {
type: [String, Number],
default: Number.MAX_VALUE
},
// 显示已上传的文件列表
fileList: {
type: Array,
default () {
return []
}
},
// 上传区域的提示文字
uploadText: {
type: String,
default: '选择图片'
},
// 是否自动上传
autoUpload: {
type: Boolean,
default: true
},
// 是否显示toast消息提示
showTips: {
type: Boolean,
default: true
},
// 是否通过slot自定义传入选择图标的按钮
customBtn: {
type: Boolean,
default: false
},
// 内部预览图片区域和选择图片按钮的区域宽度,高等于宽
width: {
type: [String, Number],
default: 200
},
// 右上角关闭按钮的背景颜色
delBgColor: {
type: String,
default: '#fa3534'
},
// 右上角关闭按钮的叉号图标的颜色
delColor: {
type: String,
default: '#ffffff'
},
// 右上角删除图标名称,只能为uView内置图标
delIcon: {
type: String,
default: 'close'
} }
}, },
mounted() { // 额外携带的参数
formData: {
type: Object,
default() {
return {};
}
},
// 上传的文件字段名
name: {
type: String,
default: 'file'
}, },
data() { // 所选的图片的尺寸, 可选值为original compressed
return { sizeType: {
lists: [], type: Array,
isInCount: true, default() {
uploading: false return ['original', 'compressed'];
} }
}, },
watch: { sourceType: {
fileList: { type: Array,
immediate: true, default() {
handler(val) { return ['album', 'camera'];
val.map(value => { }
this.lists.push({url: value.url, error: false, progress: 100});
})
}
},
}, },
methods: { // 是否在点击预览图后展示全屏图片预览
// 清除列表 previewFullImage: {
clear() { type: Boolean,
this.lists = []; default: true
// 如果是清空形式的话,发出"on-list-change"事件 },
this.$emit('on-list-change', this.lists); // 是否开启图片多选,部分安卓机型不支持
}, multiple: {
// 重新上传队列中上传失败的所有文件 type: Boolean,
reUpload() { default: true
this.uploadFile(); },
}, // 是否展示删除按钮
// 选择图片 deletable: {
selectFile() { type: Boolean,
if (this.disabled) return; default: true
const { },
name = '', maxCount, multiple, maxSize, sizeType, lists, camera, compressed, maxDuration, sourceType // 文件大小限制,单位为byte
} = this; maxSize: {
let chooseFile = null; type: [String, Number],
const newMaxCount = maxCount - lists.length; default: Number.MAX_VALUE
// 设置为只选择图片的时候使用 chooseImage 来实现 },
chooseFile = new Promise((resolve, reject) => { // 显示已上传的文件列表
uni.chooseImage({ fileList: {
count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1, type: Array,
sourceType: sourceType, default() {
sizeType, return [];
success: resolve, }
fail: reject },
}); // 上传区域的提示文字
uploadText: {
type: String,
default: '选择图片'
},
// 是否自动上传
autoUpload: {
type: Boolean,
default: true
},
// 是否显示toast消息提示
showTips: {
type: Boolean,
default: true
},
// 是否通过slot自定义传入选择图标的按钮
customBtn: {
type: Boolean,
default: false
},
// 内部预览图片区域和选择图片按钮的区域宽度,高等于宽
width: {
type: [String, Number],
default: 200
},
// 右上角关闭按钮的背景颜色
delBgColor: {
type: String,
default: '#fa3534'
},
// 右上角关闭按钮的叉号图标的颜色
delColor: {
type: String,
default: '#ffffff'
},
// 右上角删除图标名称,只能为uView内置图标
delIcon: {
type: String,
default: 'close'
},
// 如果上传后的返回值为json字符串,是否自动转json
toJson: {
type: Boolean,
default: true
},
// 上传前的钩子,每个文件上传前都会执行
beforeUpload: {
type: Function,
default: null
}
},
mounted() {},
data() {
return {
lists: [],
isInCount: true,
uploading: false
};
},
watch: {
fileList: {
immediate: true,
handler(val) {
val.map(value => {
this.lists.push({ url: value.url, error: false, progress: 100 });
}); });
chooseFile }
.then((res) => { }
let file = null; },
let listOldLength = this.lists.length; methods: {
res.tempFiles.map((val, index) => { // 清除列表
// 如果是非多选,index大于等于1或者超出最大限制数量时,不处理 clear() {
if (!multiple && index >= 1) return; this.lists = [];
if (val.size > maxSize) { // 如果是清空形式的话,发出"on-list-change"事件
this.$emit('on-oversize', val, this.lists); this.$emit('on-list-change', this.lists);
this.showToast('超出允许的文件大小'); },
} else { // 重新上传队列中上传失败的所有文件
if(maxCount <= lists.length) { reUpload() {
this.$emit('on-exceed', val, this.lists); this.uploadFile();
this.showToast('超出最大允许的文件个数'); },
return ; // 选择图片
} selectFile() {
lists.push({ if (this.disabled) return;
url: val.path, const { name = '', maxCount, multiple, maxSize, sizeType, lists, camera, compressed, maxDuration, sourceType } = this;
progress: 0, let chooseFile = null;
error: false const newMaxCount = maxCount - lists.length;
}); // 设置为只选择图片的时候使用 chooseImage 来实现
// 列表发生改变,发出事件,第二个参数为当前发生变化的项的索引 chooseFile = new Promise((resolve, reject) => {
this.$emit('on-list-change', this.lists); uni.chooseImage({
} count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1,
}) sourceType: sourceType,
// 每次图片选择完,抛出一个事件,并将当前内部选择的图片数组抛出去 sizeType,
this.$emit('on-choose-complete', this.lists); success: resolve,
if(this.autoUpload) this.uploadFile(listOldLength); fail: reject
})
.catch(error => {
// this.$emit('on-error', error);
});
},
// 提示用户消息
showToast(message, force = false) {
if(this.showTips || force) {
uni.showToast({
title: message,
icon: "none"
});
}
},
// 该方法供用户通过ref调用,手动上传
upload() {
this.uploadFile();
},
// 对失败的图片重新上传
retry(index) {
this.lists[index].progress = 0;
this.lists[index].error = false;
this.lists[index].response = null;
uni.showLoading({
title: '重新上传'
}); });
this.uploadFile(index); });
}, chooseFile
// 上传图片 .then(res => {
uploadFile(index = 0) { let file = null;
if (this.disabled) return; let listOldLength = this.lists.length;
if(this.uploading) return ; res.tempFiles.map((val, index) => {
// 全部上传完成 // 如果是非多选,index大于等于1或者超出最大限制数量时,不处理
if (index >= this.lists.length) { if (!multiple && index >= 1) return;
this.$emit('on-uploaded', this.lists); if (val.size > maxSize) {
return ; this.$emit('on-oversize', val, this.lists);
} this.showToast('超出允许的文件大小');
// 检查上传地址
if (!this.action) {
this.showToast('请配置上传地址', true);
return;
}
// 检查是否是已上传或者正在上传中
if (this.lists[index].progress == 100) {
if(this.autoUpload == false) this.uploadFile(index + 1);
return;
}
this.lists[index].error = false;
this.uploading = true;
// 创建上传对象
const task = uni.uploadFile({
url: this.action,
filePath: this.lists[index].url,
name: this.name,
formData: this.formData,
header: this.header,
success: (res) => {
// 由于此处返回的res.data为字符串,将其转为json格式
let data = {};
try{
data = JSON.parse(res.data);
}catch(e){}
if (![200,201].includes(res.statusCode)) {
this.uploadError(index, data);
} else { } else {
// 上传成功 if (maxCount <= lists.length) {
this.lists[index].response = data; this.$emit('on-exceed', val, this.lists);
this.lists[index].progress = 100; this.showToast('超出最大允许的文件个数');
this.lists[index].error = false; return;
this.$emit('on-success', data, index, this.lists); }
lists.push({
url: val.path,
progress: 0,
error: false
});
// 列表发生改变,发出事件,第二个参数为当前发生变化的项的索引
this.$emit('on-list-change', this.lists);
} }
}, });
fail: (e) => { // 每次图片选择完,抛出一个事件,并将当前内部选择的图片数组抛出去
this.uploadError(index, e); this.$emit('on-choose-complete', this.lists);
}, if (this.autoUpload) this.uploadFile(listOldLength);
complete: (res) => { })
uni.hideLoading(); .catch(error => {
this.uploading = false; // this.$emit('on-error', error);
this.uploadFile(index + 1);
this.$emit('on-change', res, index, this.lists);
}
}); });
task.onProgressUpdate((res) => { },
if (res.progress > 0) { // 提示用户消息
this.lists[index].progress = res.progress; showToast(message, force = false) {
this.$emit('on-progress', res, index, this.lists); if (this.showTips || force) {
} uni.showToast({
title: message,
icon: 'none'
}); });
}, }
// 上传失败 },
uploadError(index, err) { // 该方法供用户通过ref调用,手动上传
this.lists[index].progress = 0; upload() {
this.lists[index].error = true; this.uploadFile();
this.lists[index].response = null; },
this.$emit('on-error', err, index, this.lists); // 对失败的图片重新上传
this.showToast('上传失败,请重试'); retry(index) {
}, this.lists[index].progress = 0;
// 删除一个图片 this.lists[index].error = false;
deleteItem(index) { this.lists[index].response = null;
uni.showModal({ uni.showLoading({
title: '提示', title: '重新上传'
content: '您确定要删除此项吗?', });
success: res => { this.uploadFile(index);
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(); uploadFile(index = 0) {
} if (this.disabled) return;
this.lists.splice(index, 1); if (this.uploading) return;
this.$forceUpdate(); // 全部上传完成
this.$emit('on-remove', index, this.lists); if (index >= this.lists.length) {
this.showToast('移除成功'); this.$emit('on-uploaded', this.lists);
// 列表发生改变,发出事件 return;
this.$emit('on-list-change', this.lists); }
// 检查上传地址
if (!this.action) {
this.showToast('请配置上传地址', true);
return;
}
// 检查是否是已上传或者正在上传中
if (this.lists[index].progress == 100) {
if (this.autoUpload == false) this.uploadFile(index + 1);
return;
}
// 执行before-upload钩子
// if(this.beforeUpload && typeof(this.beforeUpload) === 'function') {
// let beforeResponse = this.beforeUpload(index, this.lists);
// if (beforeResponse && beforeResponse.then) {
// }
// }
this.lists[index].error = false;
this.uploading = true;
// 创建上传对象
const task = uni.uploadFile({
url: this.action,
filePath: this.lists[index].url,
name: this.name,
formData: this.formData,
header: this.header,
success: res => {
// 判断是否json字符串,将其转为json格式
let data = this.toJson && this.checkIsJSON(res.data) ? JSON.parse(res.data) : res.data;
if (![200, 201].includes(res.statusCode)) {
this.uploadError(index, data);
} else {
// 上传成功
this.lists[index].response = data;
this.lists[index].progress = 100;
this.lists[index].error = false;
this.$emit('on-success', data, index, this.lists);
}
},
fail: e => {
this.uploadError(index, e);
},
complete: res => {
uni.hideLoading();
this.uploading = false;
this.uploadFile(index + 1);
this.$emit('on-change', res, index, this.lists);
}
});
task.onProgressUpdate(res => {
if (res.progress > 0) {
this.lists[index].progress = res.progress;
this.$emit('on-progress', res, index, this.lists);
}
});
},
// 上传失败
uploadError(index, err) {
this.lists[index].progress = 0;
this.lists[index].error = true;
this.lists[index].response = null;
this.$emit('on-error', err, index, this.lists);
this.showToast('上传失败,请重试');
},
// 删除一个图片
deleteItem(index) {
uni.showModal({
title: '提示',
content: '您确定要删除此项吗?',
success: 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();
} }
this.lists.splice(index, 1);
this.$forceUpdate();
this.$emit('on-remove', index, this.lists);
this.showToast('移除成功');
// 列表发生改变,发出事件
this.$emit('on-list-change', this.lists);
} }
});
},
// 用户通过ref手动的形式,移除一张图片
remove(index) {
// 判断索引的合法范围
if(index >= 0 && index < this.lists.length) {
this.lists.splice(index, 1);
this.$emit('on-list-change', this.lists);
} }
}, });
// 预览图片 },
doPreviewImage(url, index) { // 用户通过ref手动的形式,移除一张图片
if (!this.previewFullImage) remove(index) {
return; // 判断索引的合法范围
const images = this.lists.map(item => item.url || item.path); if (index >= 0 && index < this.lists.length) {
uni.previewImage({ this.lists.splice(index, 1);
urls: images, this.$emit('on-list-change', this.lists);
current: url, }
success: () => { },
this.$emit('on-preview', url, this.lists); // 预览图片
}, doPreviewImage(url, index) {
fail: () => { if (!this.previewFullImage) return;
uni.showToast({ const images = this.lists.map(item => item.url || item.path);
title: '预览图片失败', uni.previewImage({
icon: 'none' urls: images,
}); current: url,
success: () => {
this.$emit('on-preview', url, this.lists);
},
fail: () => {
uni.showToast({
title: '预览图片失败',
icon: 'none'
});
}
});
},
// 判断是否json字符串
checkIsJSON(str) {
if (typeof str == 'string') {
try {
var obj = JSON.parse(str);
if (typeof obj == 'object' && obj) {
return true;
} else {
return false;
} }
}); } catch (e) {
return false;
}
} }
return false;
} }
} }
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "../../libs/css/style.components.scss"; @import '../../libs/css/style.components.scss';
.u-upload {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.u-list-item { .u-upload {
width: 200rpx; display: flex;
height: 200rpx; flex-wrap: wrap;
overflow: hidden; align-items: center;
margin: 10rpx; }
background: rgb(244, 245, 246);
position: relative;
border-radius: 10rpx;
display: inline-flex;
align-items: center;
justify-content: center;
}
.u-preview-wrap { .u-list-item {
border: 1px solid rgb(235, 236, 238); width: 200rpx;
} height: 200rpx;
overflow: hidden;
margin: 10rpx;
background: rgb(244, 245, 246);
position: relative;
border-radius: 10rpx;
display: inline-flex;
align-items: center;
justify-content: center;
}
.u-add-wrap { .u-preview-wrap {
flex-direction: column; border: 1px solid rgb(235, 236, 238);
color: $u-content-color; }
font-size: 28rpx;
}
.u-add-tips { .u-add-wrap {
margin-top: 20rpx; flex-direction: column;
} color: $u-content-color;
font-size: 28rpx;
}
.u-add-wrap__hover { .u-add-tips {
background-color: rgb(235, 236, 238); margin-top: 20rpx;
} }
.u-preview-image { .u-add-wrap__hover {
display: block; background-color: rgb(235, 236, 238);
width: 100%; }
height: 100%;
border-radius: 10rpx;
}
.u-delete-icon { .u-preview-image {
position: absolute; display: block;
top: 10rpx; width: 100%;
right: 10rpx; height: 100%;
z-index: 10; border-radius: 10rpx;
background-color: $u-type-error; }
border-radius: 100rpx;
width: 44rpx; .u-delete-icon {
height: 44rpx; position: absolute;
display: flex; top: 10rpx;
align-items: center; right: 10rpx;
justify-content: center; z-index: 10;
} background-color: $u-type-error;
border-radius: 100rpx;
.u-icon { width: 44rpx;
display: flex; height: 44rpx;
align-items: center; display: flex;
justify-content: center; align-items: center;
} justify-content: center;
}
.u-progress {
position: absolute; .u-icon {
bottom: 10rpx; display: flex;
left: 8rpx; align-items: center;
right: 8rpx; justify-content: center;
z-index: 9; }
width: auto;
} .u-progress {
position: absolute;
.u-error-btn { bottom: 10rpx;
color: #FFFFFF; left: 8rpx;
background-color: $u-type-error; right: 8rpx;
font-size: 20rpx; z-index: 9;
padding: 4px 0; width: auto;
text-align: center; }
position: absolute;
bottom: 0; .u-error-btn {
left: 0; color: #ffffff;
right: 0; background-color: $u-type-error;
z-index: 9; font-size: 20rpx;
line-height: 1; padding: 4px 0;
} text-align: center;
position: absolute;
bottom: 0;
left: 0;
right: 0;
z-index: 9;
line-height: 1;
}
</style> </style>
...@@ -3,5 +3,13 @@ let version = '1.3.61'; ...@@ -3,5 +3,13 @@ let version = '1.3.61';
export default { export default {
v: version, v: version,
version: version version: version,
// 主题名称
type: [
'primary',
'success',
'info',
'error',
'warning'
]
} }
\ No newline at end of file
.u-type-primary-light { .u-type-primary-light {
color: $u-type-primary-light!important; color: $u-type-primary-light;
} }
.u-type-warning-light { .u-type-warning-light {
color: $u-type-warning-light!important; color: $u-type-warning-light;
} }
.u-type-success-light { .u-type-success-light {
color: $u-type-success-light!important; color: $u-type-success-light;
} }
.u-type-error-light { .u-type-error-light {
color: $u-type-error-light!important; color: $u-type-error-light;
} }
.u-type-info-light { .u-type-info-light {
color: $u-type-info-light!important; color: $u-type-info-light;
} }
.u-type-primary-light-bg { .u-type-primary-light-bg {
background-color: $u-type-primary-light!important; background-color: $u-type-primary-light;
} }
.u-type-warning-light-bg { .u-type-warning-light-bg {
background-color: $u-type-warning-light!important; background-color: $u-type-warning-light;
} }
.u-type-success-light-bg { .u-type-success-light-bg {
background-color: $u-type-success-light!important; background-color: $u-type-success-light;
} }
.u-type-error-light-bg { .u-type-error-light-bg {
background-color: $u-type-error-light!important; background-color: $u-type-error-light;
} }
.u-type-info-light-bg { .u-type-info-light-bg {
background-color: $u-type-info-light!important; background-color: $u-type-info-light;
} }
.u-type-primary-dark { .u-type-primary-dark {
color: $u-type-primary-dark!important; color: $u-type-primary-dark;
} }
.u-type-warning-dark { .u-type-warning-dark {
color: $u-type-warning-dark!important; color: $u-type-warning-dark;
} }
.u-type-success-dark { .u-type-success-dark {
color: $u-type-success-dark!important; color: $u-type-success-dark;
} }
.u-type-error-dark { .u-type-error-dark {
color: $u-type-error-dark!important; color: $u-type-error-dark;
} }
.u-type-info-dark { .u-type-info-dark {
color: $u-type-info-dark!important; color: $u-type-info-dark;
} }
.u-type-primary-dark-bg { .u-type-primary-dark-bg {
background-color: $u-type-primary-dark!important; background-color: $u-type-primary-dark;
} }
.u-type-warning-dark-bg { .u-type-warning-dark-bg {
background-color: $u-type-warning-dark!important; background-color: $u-type-warning-dark;
} }
.u-type-success-dark-bg { .u-type-success-dark-bg {
background-color: $u-type-success-dark!important; background-color: $u-type-success-dark;
} }
.u-type-error-dark-bg { .u-type-error-dark-bg {
background-color: $u-type-error-dark!important; background-color: $u-type-error-dark;
} }
.u-type-info-dark-bg { .u-type-info-dark-bg {
background-color: $u-type-info-dark!important; background-color: $u-type-info-dark;
} }
.u-type-primary-disabled { .u-type-primary-disabled {
color: $u-type-primary-disabled!important; color: $u-type-primary-disabled;
} }
.u-type-warning-disabled { .u-type-warning-disabled {
color: $u-type-warning-disabled!important; color: $u-type-warning-disabled;
} }
.u-type-success-disabled { .u-type-success-disabled {
color: $u-type-success-disabled!important; color: $u-type-success-disabled;
} }
.u-type-error-disabled { .u-type-error-disabled {
color: $u-type-error-disabled!important; color: $u-type-error-disabled;
} }
.u-type-info-disabled { .u-type-info-disabled {
color: $u-type-info-disabled!important; color: $u-type-info-disabled;
} }
.u-type-primary { .u-type-primary {
color: $u-type-primary!important; color: $u-type-primary;
} }
.u-type-warning { .u-type-warning {
color: $u-type-warning!important; color: $u-type-warning;
} }
.u-type-success { .u-type-success {
color: $u-type-success!important; color: $u-type-success;
} }
.u-type-error { .u-type-error {
color: $u-type-error!important; color: $u-type-error;
} }
.u-type-info { .u-type-info {
color: $u-type-info!important; color: $u-type-info;
} }
.u-type-primary-bg { .u-type-primary-bg {
background-color: $u-type-primary!important; background-color: $u-type-primary;
} }
.u-type-warning-bg { .u-type-warning-bg {
background-color: $u-type-warning!important; background-color: $u-type-warning;
} }
.u-type-success-bg { .u-type-success-bg {
background-color: $u-type-success!important; background-color: $u-type-success;
} }
.u-type-error-bg { .u-type-error-bg {
background-color: $u-type-error!important; background-color: $u-type-error;
} }
.u-type-info-bg { .u-type-info-bg {
background-color: $u-type-info!important; background-color: $u-type-info;
} }
.u-main-color { .u-main-color {
......
...@@ -24,5 +24,10 @@ u-grid { ...@@ -24,5 +24,10 @@ u-grid {
u-line { u-line {
flex: 1; flex: 1;
} }
u-switch {
display: inline-flex;
align-items: center;
}
/* #endif */ /* #endif */
/* end-微信小程序编译后页面有组件名的元素,特别处理--end */ /* end-微信小程序编译后页面有组件名的元素,特别处理--end */
\ No newline at end of file
// 为了让用户能够自定义主题,会逐步弃用此文件,各颜色通过css提供
// 为了给某些特殊场景使用和向后兼容,无需删除此文件(2020-06-20)
let color = { let color = {
primary: "#2979ff", primary: "#2979ff",
primaryDark: "#2b85e4", primaryDark: "#2b85e4",
......
...@@ -19,7 +19,7 @@ function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') { ...@@ -19,7 +19,7 @@ function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
switch (arrayFormat) { switch (arrayFormat) {
case 'indices': case 'indices':
// 结果: ids[0]=1&ids[1]=2&ids[2]=3 // 结果: ids[0]=1&ids[1]=2&ids[2]=3
for (i = 0; i < value.length; i++) { for (let i = 0; i < value.length; i++) {
_result.push(key + '[' + i + ']=' + value[i]) _result.push(key + '[' + i + ']=' + value[i])
} }
break; break;
......
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