Commit 5c9923ce authored by wlxuqu's avatar wlxuqu

1. 修改基础,让其更加简单明了,易用

2. 优化navbar自定义导航栏嵌入的搜索框示例
3. 给verificationCode验证码倒计时组件新增倒计时防刷新和返回功能
parent 2954f6da
...@@ -33,9 +33,10 @@ const app = new Vue({ ...@@ -33,9 +33,10 @@ const app = new Vue({
store, store,
...App ...App
}) })
app.$mount()
// http拦截器 // http拦截器,将此部分放在new Vue()和app.$mount()之间,才能App.vue中正常使用
import httpInterceptor from '@/common/http.interceptor.js' import httpInterceptor from '@/common/http.interceptor.js'
Vue.use(httpInterceptor, app) Vue.use(httpInterceptor, app)
app.$mount()
...@@ -61,5 +61,5 @@ ...@@ -61,5 +61,5 @@
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.u-demo {}
</style> </style>
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
<u-navbar title-color="#fff" back-icon-color="#ffffff" :is-fixed="isFixed" :is-back="isBack" :background="background" :back-text-style="{color: '#fff'}" :title="title" :back-icon-name="backIconName" :back-text="backText"> <u-navbar title-color="#fff" back-icon-color="#ffffff" :is-fixed="isFixed" :is-back="isBack" :background="background" :back-text-style="{color: '#fff'}" :title="title" :back-icon-name="backIconName" :back-text="backText">
<view class="slot-wrap" v-if="useSlot"> <view class="slot-wrap" v-if="useSlot">
<view class="search-wrap" v-if="search"> <view class="search-wrap" v-if="search">
<u-search :show-action="showAction" height="56" :action-style="{color: '#fff'}"></u-search> <!-- 如果使用u-search组件,必须要给v-model绑定一个变量 -->
<u-search v-model="keyword" :show-action="showAction" height="56" :action-style="{color: '#fff'}"></u-search>
</view> </view>
<view class="navbar-right" v-if="rightSlot"> <view class="navbar-right" v-if="rightSlot">
<view class="message-box right-item"> <view class="message-box right-item">
...@@ -81,10 +82,9 @@ ...@@ -81,10 +82,9 @@
search: false, search: false,
custom: false, custom: false,
isFixed: true, isFixed: true,
keyword: ''
} }
}, },
onLoad() {
},
methods: { methods: {
titleChange(index) { titleChange(index) {
this.useSlot = false; this.useSlot = false;
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
</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 :current="0" :list="['5s', '10s', '60s']" @change="secondsChange"></u-subsection> <u-subsection vibrateShort :current="0" :list="['60s', '10s', '5s']" @change="secondsChange"></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>
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
data() { data() {
return { return {
tips: '', tips: '',
seconds: 5, seconds: 60,
refCode: null, refCode: null,
startText: '获取验证码', startText: '获取验证码',
changeText: 'X秒重新获取', changeText: 'X秒重新获取',
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
}, },
methods: { methods: {
codeChange(text) { codeChange(text) {
// console.log(text);
this.tips = text; this.tips = text;
}, },
getCode() { getCode() {
...@@ -66,7 +67,7 @@ ...@@ -66,7 +67,7 @@
} }
}, },
secondsChange(index) { secondsChange(index) {
this.seconds = index == 0 ? 5 : index == 1 ? 10 : 60; this.seconds = index == 0 ? 60 : index == 1 ? 10 : 5;
}, },
textChange(index) { textChange(index) {
if(index == 0) { if(index == 0) {
......
...@@ -5,71 +5,59 @@ ...@@ -5,71 +5,59 @@
* @LastEditTime: 2020-04-22 18:33:28 * @LastEditTime: 2020-04-22 18:33:28
--> -->
<template> <template>
<view class="u-demo"> <view class="u-demo">
<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-gap :bg-color="bgColor" :height="height" :margin="margin"></u-gap> <u-gap :bg-color="bgColor" :height="height" :margin-top="marginTop" :margin-bottom="marginBottom"></u-gap>
</view> </view>
</view> </view>
<view class="u-config-wrap"> <view class="u-config-wrap">
<view class="u-config-title u-border-bottom">参数配置</view> <view class="u-config-title u-border-bottom">参数配置</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 <u-subsection vibrateShort :list="['default', 'primary', 'error', 'warning', 'success']" @change="bgColorChange"></u-subsection>
vibrateShort </view>
:list="['default', 'primary', 'error', 'warning', 'success']" <view class="u-config-item">
@change="bgColorChange" <view class="u-item-title">高度</view>
></u-subsection> <u-subsection vibrateShort :list="['30', '50', '70']" @change="heightChange"></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="['30', '50', '70']" @change="heightChange"></u-subsection> <u-subsection vibrateShort :list="['30', '50', '70']" @change="marginChange"></u-subsection>
</view> </view>
<view class="u-config-item"> </view>
<view class="u-item-title">上下外边距</view> </view>
<u-subsection vibrateShort :list="['30', '50', '70']" @change="marginChange"></u-subsection>
</view>
</view>
</view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
height: 30, height: 30,
margin: 0, bgColor: this.$u.color.bgColor,
bgColor: this.$u.color.bgColor marginTop: 30,
}; marginBottom: 30
}, };
methods: { },
bgColorChange(index) { methods: {
let color = bgColorChange(index) {
index == 0 let color = index == 0 ? 'default' : index == 1 ? 'primary' : index == 2 ? 'error' : index == 3 ? 'warning' : 'success';
? "default" this.bgColor = color == 'default' ? this.$u.color['bgColor'] : this.$u.color[color];
: index == 1 },
? "primary" heightChange(index) {
: index == 2 this.height = index == 0 ? 30 : index == 1 ? 50 : 70;
? "error" },
: index == 3 marginChange(index) {
? "warning" this.marginTop = ['30', '50', '70'][index];
: "success"; this.marginBottom = this.marginTop;
this.bgColor = }
color == "default" ? this.$u.color["bgColor"] : this.$u.color[color]; }
},
heightChange(index) {
this.height = index == 0 ? 30 : index == 1 ? 50 : 70;
},
marginChange(index) {
this.margin = index == 0 ? 30 : index == 1 ? 50 : 70;
}
}
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.wrap { .wrap {
padding: 24rpx; padding: 24rpx;
} }
</style> </style>
<template> <template>
<view class="wrap u-flex"> <view>
<u-dropdown-list :dropdown-list="dropdownList" @change="handleDropChange"></u-dropdown-list>
</view> </view>
</template> </template>
<script> <script>
export default { const dropdownOption1 = [
onLoad() { { text: '类型', value: '', select: false },
getApp().globalData.username = 'test12'; { text: '全场券', value: 1, select: false },
} { text: '品类券', value: 2, select: false },
} { text: '单品券', value: 3, select: false },
{ text: '业务券', value: 4, select: false }
]
const dropdownOption2 = [
{ text: '状态', value: '', select: false },
{ text: '可使用', value: 1, select: false },
{ text: '已过期', value: 2, select: false }
]
const dropdownOption3 = [
{ text: '优惠力度', value: '', select: false },
{ text: '满100-20', value: 1, select: false },
{ text: '满100-50', value: 2, select: false }
]
export default {
props: {},
data() {
return {
dropdownList: [
{ name: '类型', show: false, options: dropdownOption1 },
{ name: '状态', show: false, options: dropdownOption2 },
{ name: '优惠力度', show: false, options: dropdownOption3 }
]
}
},
methods: {
handleDropChange(select, options) {
console.log(select, options)
}
}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
</style> </style>
<template>
<view class="dropdown-list-wapper u-flex u-flex-1">
<view
v-for="(drop, index) in dropdownListFromFather"
:key="drop.name"
:show="drop.show"
class="u-selected-class u-dropdown-list"
:style="{ zIndex: zIndex + 1 }"
>
<slot name="selectionbox">
<view
:style="{ height: top + 'rpx' }"
class="drop-item u-flex u-justify-center"
@click="handleDropClick(drop)"
>
<text :style="{ color: drop.show ? activeColor : '#999' }">
{{ getTitle(drop.options) }}
</text>
<view
class="u-animation"
:class="[drop.show ? 'u-animation-show' : '']"
>
<u-icon
v-if="drop.show"
name="arrow-up-fill"
:size="18"
:color="activeColor"
></u-icon>
<u-icon v-else name="arrow-down-fill" :size="18"></u-icon>
</view>
</view>
</slot>
<view
class="u-dropdown-view"
:class="[drop.show ? 'u-dropdownlist-show' : '']"
:style="{
background: bgcolor,
height: drop.show ? 'auto' : 0,
top: top + 'rpx'
}"
>
<slot name="dropdownbox">
<view class="u-selected-list">
<view
class="select-item u-flex u-align-center u-border-bottom u-align-between"
:style="{ color: select.select ? activeColor : '#666666' }"
@tap="handleSelected(select, drop.options)"
v-for="(select, n) in drop.options"
:key="n"
>
<text>{{ select.text }}</text>
<u-icon
v-if="select.select"
class="select-icon"
:color="activeColor"
size="35"
name="checkmark"
></u-icon>
</view>
</view>
</slot>
</view>
</view>
<u-mask
duration="100"
:show="dropdownShow"
@click="closeMask"
:z-index="zIndex"
></u-mask>
</view>
</template>
<script>
const dropdownOption1 = [
{ id: 0, text: '类型', value: '', select: false },
{ id: 1, text: '全场券', value: 1, select: false },
{ id: 2, text: '品类券', value: 2, select: false },
{ id: 3, text: '单品券', value: 3, select: false },
{ id: 4, text: '业务券', value: 4, select: false }
]
const dropdownOption2 = [
{ id: 5, text: '状态', value: '', select: false },
{ id: 6, text: '可使用', value: 1, select: false },
{ id: 7, text: '已过期', value: 2, select: false }
]
const dropdownOption3 = [
{ id: 8, text: '优惠力度', value: '', select: false },
{ id: 9, text: '满100-20', value: 1, select: false },
{ id: 10, text: '满100-50', value: 2, select: false }
]
export default {
props: {
// 下拉框数据
dropdownList: {
type: Array,
default: () => [
{ show: false, options: dropdownOption1 },
{ show: false, options: dropdownOption2 },
{ show: false, options: dropdownOption3 }
],
required: true,
validator: value =>
value.every(item => Array.isArray(item.options) && item.options.length)
},
//背景颜色
bgcolor: {
type: String,
default: 'none'
},
//top rpx 选择框高度也用这个值
top: {
type: Number,
default: 90
},
// 菜单标题和选项的选中态颜色
activeColor: {
type: String,
default: '#e7141a'
},
// mask和下拉列表的z-index
zIndex: {
type: [String, Number],
default: 21
}
},
data() {
return {
dropdownShow: false,
dropdownListFromFather: this.dropdownList
}
},
computed: {},
methods: {
getTitle(item = []) {
const obj = item.find(v => v.select) || {}
if (obj.select) {
return obj.text
} else {
if (item[0]) {
item[0].select = true
return item[0].text
}
}
return ''
},
handleDropClick(item) {
if (item.show) {
item.show = false
this.dropdownShow = false
return
}
this.dropdownListFromFather.map(item => {
item.show = false
})
const t = setTimeout(() => {
item.show = true
this.dropdownShow = true
clearTimeout(t)
}, 100)
},
closeMask() {
this.dropdownShow = false
this.dropdownListFromFather.map(item => {
item.show = false
})
},
handleSelected(select, options) {
options.map(item => {
item.select = false
})
select.select = true
this.closeMask()
// 返回选中对象和下拉列表数组
this.$emit('change', select, options)
}
},
watch: {
dropdownList: {
handler(v) {
this.dropdownListFromFather = v
},
deep: true
}
}
}
</script>
<style lang="scss" scoped>
.dropdown-list-wapper {
position: relative;
}
.u-dropdown-view {
width: 100%;
overflow: hidden;
position: absolute;
z-index: 9999;
left: 0;
right: 0;
/* opacity: 0; */
visibility: hidden;
transition: height 0.5s ease-in-out;
.u-selected-list {
background-color: #fff;
.select-item {
color: #666666;
font-size: 28rpx;
padding: 30rpx 54rpx 30rpx 30rpx;
margin-left: 30rpx;
}
.select-item.selectActive {
color: #e7141a;
}
}
}
.u-dropdownlist-show {
/* opacity: 1; */
visibility: visible;
}
.u-dropdown-list {
flex: 1;
// z-index: 22;
background: #fff;
position: static;
}
.drop-item {
justify-content: center;
color: #999999;
font-size: 30rpx;
> text {
margin-right: 10rpx;
}
/deep/ {
.uicon {
position: relative;
top: -2rpx;
}
}
}
</style>
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* @property {String} start-text 开始前的提示语,见官网说明(默认获取验证码) * @property {String} start-text 开始前的提示语,见官网说明(默认获取验证码)
* @property {String} change-text 倒计时期间的提示语,必须带有字母"x",见官网说明(默认X秒重新获取) * @property {String} change-text 倒计时期间的提示语,必须带有字母"x",见官网说明(默认X秒重新获取)
* @property {String} end-text 倒计结束的提示语,见官网说明(默认重新获取) * @property {String} end-text 倒计结束的提示语,见官网说明(默认重新获取)
* @property {Boolean} keep-running 是否在H5刷新或各端返回再进入时继续倒计时(默认false)
* @event {Function} change 倒计时期间,每秒触发一次 * @event {Function} change 倒计时期间,每秒触发一次
* @event {Function} start 开始倒计时触发 * @event {Function} start 开始倒计时触发
* @event {Function} end 结束倒计时触发 * @event {Function} end 结束倒计时触发
...@@ -41,8 +42,11 @@ ...@@ -41,8 +42,11 @@
type: String, type: String,
default: '重新获取' default: '重新获取'
}, },
// 是否在H5中,即使刷新也保存当前的倒计时 // 是否在H5刷新或各端返回再进入时继续倒计时
// 暂不处理,看需求而定 keepRunning: {
type: Boolean,
default: false
}
}, },
data() { data() {
return { return {
...@@ -52,12 +56,38 @@ ...@@ -52,12 +56,38 @@
} }
}, },
mounted() { mounted() {
this.changeEvent(this.startText); this.checkKeepRunning();
},
watch: {
seconds: {
immediate: true,
handler(n) {
this.secNum = n;
}
}
}, },
methods: { methods: {
checkKeepRunning() {
// 获取上一次退出页面(H5还包括刷新)时的时间戳,如果没有上次的保存,此值可能为空
let lastTimestamp = Number(uni.getStorageSync('$uCountDownTimestamp'));
// 当前秒的时间戳
let nowTimestamp = Math.floor((+ new Date()) / 1000);
// 判断当前的时间戳,是否小于上一次的本该按设定结束,却提前结束的时间戳
if(this.keepRunning && lastTimestamp && lastTimestamp > nowTimestamp) {
// 剩余尚未执行完的倒计秒数
this.secNum = lastTimestamp - nowTimestamp;
// 清除本地保存的变量
uni.setStorageSync('$uCountDownTimestamp', 0);
// 开始倒计时
this.start();
} else {
// 如果不存在需要继续上一次的倒计时,执行正常的逻辑
this.changeEvent(this.startText);
}
},
// 开始倒计时 // 开始倒计时
start() { start() {
this.secNum = this.seconds; //this.secNum = this.seconds;
this.$emit('start'); this.$emit('start');
this.canGetCode = false; this.canGetCode = false;
// 这里放这句,是为了一开始时就提示,否则要等setInterval的1秒后才会有提示 // 这里放这句,是为了一开始时就提示,否则要等setInterval的1秒后才会有提示
...@@ -73,6 +103,7 @@ ...@@ -73,6 +103,7 @@
this.$emit('end'); this.$emit('end');
this.canGetCode = true; this.canGetCode = true;
} }
this.setTimeToStorage();
}, 1000); }, 1000);
}, },
// 重置,可以让用户再次获取验证码 // 重置,可以让用户再次获取验证码
...@@ -84,11 +115,29 @@ ...@@ -84,11 +115,29 @@
}, },
changeEvent(text) { changeEvent(text) {
this.$emit('change', text); this.$emit('change', text);
},
// 保存时间戳,为了防止倒计时尚未结束,H5刷新或者各端的右上角返回上一页再进来
setTimeToStorage() {
if(!this.keepRunning) return ;
// 记录当前的时间戳,为了下次进入页面,如果还在倒计时内的话,继续倒计时
// 倒计时尚未结束,结果大于0;倒计时已经开始,就会小于初始值,如果等于初始值,说明没有开始倒计时,无需处理
if(this.secNum > 0 && this.secNum < this.seconds) {
// 获取当前时间戳(+ new Date()为特殊写法),除以1000变成秒,再去除小数部分
let nowTimestamp = Math.floor((+ new Date()) / 1000);
// 将本该结束时候的时间戳保存起来 => 当前时间戳 + 剩余的秒数
uni.setStorage({
key: '$uCountDownTimestamp',
data: nowTimestamp + this.secNum
})
}
} }
}, },
// 组件销毁的时候,清除定时器,否则定时器会继续存在,系统不会自动清除
beforeDestroy() { beforeDestroy() {
clearTimeout(this.timer) clearTimeout(this.timer);
}, this.timer = null;
this.setTimeToStorage();
}
} }
</script> </script>
......
// 引入公共基础类 // 引入公共基础类
@import "@/uview/libs/css/common.scss"; @import "./libs/css/common.scss";
@import "@/uview/libs/css/color.scss"; @import "./libs/css/color.scss";
page { page {
color: $u-main-color; color: $u-main-color;
......
// 此版本发布于2020-04-29 // 此版本发布于2020-04-30
let version = '1.1.4'; let version = '1.1.5';
export default { export default {
v: version, v: version,
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
.u-font-md { .u-font-md {
font-size: 28rpx; font-size: 28rpx;
color: $u-content-color;
} }
.u-font-lg { .u-font-lg {
...@@ -34,31 +33,35 @@ ...@@ -34,31 +33,35 @@
flex-wrap: nowrap; flex-wrap: nowrap;
} }
.u-align-center { .u-col-center {
align-items: center; align-items: center;
} }
.u-align-top { .u-col-top {
align-items: flex-start; align-items: flex-start;
} }
.u-align-bottom { .u-col-bottom {
align-items: flex-end; align-items: flex-end;
} }
.u-align-left { .u-row-center {
justify-content: center;
}
.u-row-left {
justify-content: flex-start; justify-content: flex-start;
} }
.u-align-right { .u-row-right {
justify-content: flex-end; justify-content: flex-end;
} }
.u-align-between { .u-row-between {
justify-content: space-between; justify-content: space-between;
} }
.u-align-around { .u-row-around {
justify-content: space-around; justify-content: space-around;
} }
...@@ -114,7 +117,7 @@ ...@@ -114,7 +117,7 @@
padding: $i + rpx; padding: $i + rpx;
} }
@each $short, $long in l left, t top, r right, b botttom { @each $short, $long in l left, t top, r right, b bottom {
// 缩写版,结果如: u-m-l-30 // 缩写版,结果如: u-m-l-30
// 定义外边距 // 定义外边距
.u-m-#{$short}-#{$i} { .u-m-#{$short}-#{$i} {
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* *
* @param {Object} rules 验证字段的规则 * @param {Object} rules 验证字段的规则
* @param {Object} messages 验证字段的提示信息 * @param {Object} messages 验证字段的提示信息
* 更多: https://github.com/skyvow/wx-extend/blob/master/docs/components/validate.md
*/ */
class Uvalidattion { class Uvalidattion {
constructor(rules = {}, messages = {}) { constructor(rules = {}, messages = {}) {
......
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