172 changed files with 16181 additions and 0 deletions
Split View
Diff Options
-
40app.js
-
23app.json
-
28app.wxss
-
BINassets/image/icon_address.png
-
BINassets/image/icon_kefu.png
-
BINassets/image/icon_share.png
-
BINassets/image/list_empty.png
-
BINassets/image/login_logo.png
-
BINassets/image/me_logo.png
-
BINassets/raw/ding.mp3
-
184colorui/animation.wxss
-
58colorui/components/cu-custom.js
-
4colorui/components/cu-custom.json
-
16colorui/components/cu-custom.wxml
-
1colorui/components/cu-custom.wxss
-
1226colorui/icon.wxss
-
2624colorui/main.wxss
-
382components/animation-group/index.js
-
3components/animation-group/index.json
-
3components/animation-group/index.wxml
-
206components/animation-group/index.wxss
-
62components/backdrop/index.js
-
6components/backdrop/index.json
-
1components/backdrop/index.wxml
-
15components/backdrop/index.wxss
-
146components/button/index.js
-
3components/button/index.json
-
26components/button/index.wxml
-
356components/button/index.wxss
-
68components/cell-group/index.js
-
3components/cell-group/index.json
-
7components/cell-group/index.wxml
-
31components/cell-group/index.wxss
-
187components/cell/index.js
-
3components/cell/index.json
-
42components/cell/index.wxml
-
98components/cell/index.wxss
-
264components/dialog/index.js
-
6components/dialog/index.json
-
56components/dialog/index.wxml
-
115components/dialog/index.wxss
-
42components/divider/index.js
-
3components/divider/index.json
-
6components/divider/index.wxml
-
53components/divider/index.wxss
-
1components/helpers/arrayTreeFilter.js
-
1components/helpers/baseComponent.js
-
1components/helpers/checkIPhoneX.js
-
1components/helpers/classNames.js
-
1components/helpers/compareVersion.js
-
1components/helpers/computedBehavior.js
-
1components/helpers/debounce.js
-
1components/helpers/eventsMixin.js
-
1components/helpers/funcBehavior.js
-
1components/helpers/isEmpty.js
-
1components/helpers/relationsBehavior.js
-
1components/helpers/safeAreaBehavior.js
-
1components/helpers/safeSetDataBehavior.js
-
1components/helpers/shallowEqual.js
-
1components/helpers/styleToCssString.js
-
47components/icon/index.js
-
3components/icon/index.json
-
1components/icon/index.wxml
-
2820components/icon/index.wxss
-
153components/image/index.js
-
3components/image/index.json
-
24components/image/index.wxml
-
87components/image/index.wxss
-
20components/index.js
-
287components/input-number/index.js
-
6components/input-number/index.json
-
9components/input-number/index.wxml
-
118components/input-number/index.wxss
-
135components/input-number/utils.js
-
78components/password-box/index.js
-
4components/password-box/index.json
-
17components/password-box/index.wxml
-
73components/password-box/index.wxss
-
193components/popup/index.js
-
7components/popup/index.json
-
26components/popup/index.wxml
-
114components/popup/index.wxss
-
56components/refresh-view/index.js
-
4components/refresh-view/index.json
-
9components/refresh-view/index.wxml
-
158components/refresh-view/index.wxs
-
68components/refresh-view/index.wxss
-
110components/result/index.js
-
6components/result/index.json
-
58components/result/index.wxml
-
36components/result/index.wxss
-
88components/step/index.js
-
4components/step/index.json
-
21components/step/index.wxml
-
122components/step/index.wxss
-
49components/steps/index.js
-
3components/steps/index.json
-
3components/steps/index.wxml
-
4components/steps/index.wxss
-
126components/tab/index.js
@ -0,0 +1,40 @@ |
|||
//app.js
|
|||
App({ |
|||
|
|||
release: false, |
|||
httpUrl: 'http://192.168.0.106:9000', |
|||
|
|||
globalData: { |
|||
userInfo: {}, |
|||
openId: null, |
|||
token: null |
|||
}, |
|||
|
|||
onLaunch: function () { |
|||
// 获取全局尺寸的一些配置
|
|||
// var sysInfo = wx.getAccountInfoSync()
|
|||
// if (sysInfo.miniProgram.appId == 'wx9e774103645f5c54') {
|
|||
// this.httpUrl = 'http://192.168.0.106:9000'
|
|||
// } else if (sysInfo.miniProgram.appId == 'wx5371934de00d6215') {
|
|||
// this.httpUrl = 'https://mini.qniao.cn'
|
|||
// }
|
|||
if (this.release) { |
|||
this.httpUrl = 'https://mini.qniao.cn' |
|||
} else { |
|||
this.httpUrl = 'http://192.168.0.106:9000' |
|||
} |
|||
wx.getSystemInfo({ |
|||
success: e => { |
|||
this.globalData.StatusBar = e.statusBarHeight; |
|||
let custom = wx.getMenuButtonBoundingClientRect(); |
|||
this.globalData.Custom = custom; |
|||
this.globalData.CustomBar = custom.bottom + custom.top - e.statusBarHeight; |
|||
let windowHeight = e.windowHeight * (750 / e.windowWidth); |
|||
let statusBarHeight = this.globalData.CustomBar * (750 / e.windowWidth); |
|||
this.globalData.fragmentHeight = windowHeight - statusBarHeight |
|||
// console.log('fragmentHeight>>>' + this.globalData.fragmentHeight + ',windowHeight=' + windowHeight)
|
|||
} |
|||
}) |
|||
} |
|||
|
|||
}) |
|||
@ -0,0 +1,23 @@ |
|||
{ |
|||
"pages": [ |
|||
"pages/mall/shops/index", |
|||
"pages/index/index", |
|||
"pages/mall/search-list/index", |
|||
"pages/mall/order-list/index", |
|||
"pages/mall/order-info/index", |
|||
"pages/mall/order-offer/index", |
|||
"pages/mall/order-result/index", |
|||
"pages/mall/order-detail/index", |
|||
"pages/home/password/index" |
|||
], |
|||
"window": { |
|||
"navigationBarBackgroundColor": "#009EE0", |
|||
"navigationBarTitleText": "", |
|||
"navigationStyle": "custom", |
|||
"navigationBarTextStyle": "black" |
|||
}, |
|||
"usingComponents": { |
|||
"cu-custom": "/colorui/components/cu-custom" |
|||
}, |
|||
"sitemapLocation": "sitemap.json" |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
@import "colorui/main.wxss"; |
|||
@import "colorui/icon.wxss"; |
|||
@import "colorui/animation.wxss"; |
|||
|
|||
/**app.wxss**/ |
|||
.scrollPage { |
|||
height: 100vh; |
|||
} |
|||
|
|||
.flex-center{ |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.flex-column { |
|||
-webkit-box-orient: vertical; |
|||
-webkit-flex-direction: column; |
|||
-ms-flex-direction: column; |
|||
flex-direction: column; |
|||
} |
|||
|
|||
.flex-justify { |
|||
align-items: center; |
|||
-webkit-box-pack: justify; |
|||
-webkit-justify-content: space-between; |
|||
-ms-flex-pack: justify; |
|||
justify-content: space-between; |
|||
} |
|||
@ -0,0 +1,184 @@ |
|||
/* |
|||
Animation 微动画 |
|||
基于ColorUI组建库的动画模块 by 文晓港 2019年3月26日19:52:28 |
|||
*/ |
|||
|
|||
/* css 滤镜 控制黑白底色gif的 */ |
|||
.gif-black{ |
|||
mix-blend-mode: screen; |
|||
} |
|||
.gif-white{ |
|||
mix-blend-mode: multiply; |
|||
} |
|||
|
|||
|
|||
/* Animation css */ |
|||
[class*=animation-] { |
|||
animation-duration: .5s; |
|||
animation-timing-function: ease-out; |
|||
animation-fill-mode: both |
|||
} |
|||
|
|||
.animation-fade { |
|||
animation-name: fade; |
|||
animation-duration: .8s; |
|||
animation-timing-function: linear |
|||
} |
|||
|
|||
.animation-scale-up { |
|||
animation-name: scale-up |
|||
} |
|||
|
|||
.animation-scale-down { |
|||
animation-name: scale-down |
|||
} |
|||
|
|||
.animation-slide-top { |
|||
animation-name: slide-top |
|||
} |
|||
|
|||
.animation-slide-bottom { |
|||
animation-name: slide-bottom |
|||
} |
|||
|
|||
.animation-slide-left { |
|||
animation-name: slide-left |
|||
} |
|||
|
|||
.animation-slide-right { |
|||
animation-name: slide-right |
|||
} |
|||
|
|||
.animation-shake { |
|||
animation-name: shake |
|||
} |
|||
|
|||
.animation-reverse { |
|||
animation-direction: reverse |
|||
} |
|||
|
|||
@keyframes fade { |
|||
0% { |
|||
opacity: 0 |
|||
} |
|||
|
|||
100% { |
|||
opacity: 1 |
|||
} |
|||
} |
|||
|
|||
@keyframes scale-up { |
|||
0% { |
|||
opacity: 0; |
|||
transform: scale(.2) |
|||
} |
|||
|
|||
100% { |
|||
opacity: 1; |
|||
transform: scale(1) |
|||
} |
|||
} |
|||
|
|||
@keyframes scale-down { |
|||
0% { |
|||
opacity: 0; |
|||
transform: scale(1.8) |
|||
} |
|||
|
|||
100% { |
|||
opacity: 1; |
|||
transform: scale(1) |
|||
} |
|||
} |
|||
|
|||
@keyframes slide-top { |
|||
0% { |
|||
opacity: 0; |
|||
transform: translateY(-100%) |
|||
} |
|||
|
|||
100% { |
|||
opacity: 1; |
|||
transform: translateY(0) |
|||
} |
|||
} |
|||
|
|||
@keyframes slide-bottom { |
|||
0% { |
|||
opacity: 0; |
|||
transform: translateY(100%) |
|||
} |
|||
|
|||
100% { |
|||
opacity: 1; |
|||
transform: translateY(0) |
|||
} |
|||
} |
|||
|
|||
@keyframes shake { |
|||
|
|||
0%, |
|||
100% { |
|||
transform: translateX(0) |
|||
} |
|||
|
|||
10% { |
|||
transform: translateX(-9px) |
|||
} |
|||
|
|||
20% { |
|||
transform: translateX(8px) |
|||
} |
|||
|
|||
30% { |
|||
transform: translateX(-7px) |
|||
} |
|||
|
|||
40% { |
|||
transform: translateX(6px) |
|||
} |
|||
|
|||
50% { |
|||
transform: translateX(-5px) |
|||
} |
|||
|
|||
60% { |
|||
transform: translateX(4px) |
|||
} |
|||
|
|||
70% { |
|||
transform: translateX(-3px) |
|||
} |
|||
|
|||
80% { |
|||
transform: translateX(2px) |
|||
} |
|||
|
|||
90% { |
|||
transform: translateX(-1px) |
|||
} |
|||
} |
|||
|
|||
@keyframes slide-left { |
|||
0% { |
|||
opacity: 0; |
|||
transform: translateX(-100%) |
|||
} |
|||
|
|||
100% { |
|||
opacity: 1; |
|||
transform: translateX(0) |
|||
} |
|||
} |
|||
|
|||
@keyframes slide-right { |
|||
0% { |
|||
opacity: 0; |
|||
transform: translateX(100%) |
|||
} |
|||
|
|||
100% { |
|||
opacity: 1; |
|||
transform: translateX(0) |
|||
} |
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
const app = getApp(); |
|||
Component({ |
|||
/** |
|||
* 组件的一些选项 |
|||
*/ |
|||
options: { |
|||
addGlobalClass: true, |
|||
multipleSlots: true |
|||
}, |
|||
/** |
|||
* 组件的对外属性 |
|||
*/ |
|||
properties: { |
|||
bgColor: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
isCustom: { |
|||
type: [Boolean, String], |
|||
default: false |
|||
}, |
|||
isBack: { |
|||
type: [Boolean, String], |
|||
default: false |
|||
}, |
|||
bgImage: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
}, |
|||
/** |
|||
* 组件的初始数据 |
|||
*/ |
|||
data: { |
|||
StatusBar: app.globalData.StatusBar, |
|||
CustomBar: app.globalData.CustomBar, |
|||
Custom: app.globalData.Custom |
|||
}, |
|||
/** |
|||
* 组件的方法列表 |
|||
*/ |
|||
methods: { |
|||
BackPage() { |
|||
if(getCurrentPages().length == 1){ |
|||
this.toHome() |
|||
} else { |
|||
wx.navigateBack({ |
|||
delta: 1 |
|||
}); |
|||
} |
|||
}, |
|||
toHome(){ |
|||
wx.reLaunch({ |
|||
url: '/pages/mall/shops/index', |
|||
}) |
|||
} |
|||
} |
|||
}) |
|||
@ -0,0 +1,4 @@ |
|||
{ |
|||
"component": true, |
|||
"usingComponents": {} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
<view class="cu-custom" style="height:{{CustomBar}}px"> |
|||
<view class="cu-bar fixed {{bgImage!=''?'none-bg text-white bg-img':''}} {{bgColor}}" style="height:{{CustomBar}}px;padding-top:{{StatusBar}}px;{{bgImage?'background-image:url(' + bgImage+')':''}}"> |
|||
<view class="action" bindtap="BackPage" wx:if="{{isBack}}"> |
|||
<text class="cuIcon-back"></text> |
|||
<slot name="backText"></slot> |
|||
</view> |
|||
<view class="action border-custom" wx:if="{{isCustom}}" style="width:{{Custom.width}}px;height:{{Custom.height}}px;margin-left:calc(750rpx - {{Custom.right}}px)"> |
|||
<text class="cuIcon-back" bindtap="BackPage"></text> |
|||
<text class="cuIcon-homefill" bindtap="toHome"></text> |
|||
</view> |
|||
<view class="content" style="top:{{StatusBar}}px"> |
|||
<slot name="content"></slot> |
|||
</view> |
|||
<slot name="right"></slot> |
|||
</view> |
|||
</view> |
|||
@ -0,0 +1 @@ |
|||
/* colorui/components/cu-custom.wxss */ |
|||
1226
colorui/icon.wxss
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2624
colorui/main.wxss
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,382 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import styleToCssString from '../helpers/styleToCssString' |
|||
|
|||
const ENTER = 'enter' |
|||
const ENTERING = 'entering' |
|||
const ENTERED = 'entered' |
|||
const EXIT = 'exit' |
|||
const EXITING = 'exiting' |
|||
const EXITED = 'exited' |
|||
const UNMOUNTED = 'unmounted' |
|||
|
|||
const TRANSITION = 'transition' |
|||
const ANIMATION = 'animation' |
|||
|
|||
const TIMEOUT = 1000 / 60 |
|||
|
|||
const defaultClassNames = { |
|||
enter: '', // 进入过渡的开始状态,在过渡过程完成之后移除
|
|||
enterActive: '', // 进入过渡的结束状态,在过渡过程完成之后移除
|
|||
enterDone: '', // 进入过渡的完成状态
|
|||
exit: '', // 离开过渡的开始状态,在过渡过程完成之后移除
|
|||
exitActive: '', // 离开过渡的结束状态,在过渡过程完成之后移除
|
|||
exitDone: '', // 离开过渡的完成状态
|
|||
} |
|||
|
|||
baseComponent({ |
|||
properties: { |
|||
// 触发组件进入或离开过渡的状态
|
|||
in: { |
|||
type: Boolean, |
|||
value: false, |
|||
observer(newVal) { |
|||
if (this.data.isMounting) { |
|||
this.updated(newVal) |
|||
} |
|||
}, |
|||
}, |
|||
// 过渡的类名
|
|||
classNames: { |
|||
type: null, |
|||
value: defaultClassNames, |
|||
}, |
|||
// 过渡持续时间
|
|||
duration: { |
|||
type: null, |
|||
value: null, |
|||
}, |
|||
// 过渡动效的类型
|
|||
type: { |
|||
type: String, |
|||
value: TRANSITION, |
|||
}, |
|||
// 首次挂载时是否触发进入过渡
|
|||
appear: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
// 是否启用进入过渡
|
|||
enter: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
// 是否启用离开过渡
|
|||
exit: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
// 首次进入过渡时是否懒挂载组件
|
|||
mountOnEnter: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
// 离开过渡完成时是否卸载组件
|
|||
unmountOnExit: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
// 自定义类名
|
|||
wrapCls: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
// 自定义样式
|
|||
wrapStyle: { |
|||
type: [String, Object], |
|||
value: '', |
|||
observer(newVal) { |
|||
this.setData({ |
|||
extStyle: styleToCssString(newVal), |
|||
}) |
|||
}, |
|||
}, |
|||
disableScroll: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
}, |
|||
data: { |
|||
animateCss: '', // 动画样式
|
|||
animateStatus: EXITED, // 动画状态,可选值 entering、entered、exiting、exited
|
|||
isMounting: false, // 是否首次挂载
|
|||
extStyle: '', // 组件样式
|
|||
}, |
|||
methods: { |
|||
/** |
|||
* 监听过渡或动画的回调函数 |
|||
*/ |
|||
addEventListener() { |
|||
const { animateStatus } = this.data |
|||
const { enter, exit } = this.getTimeouts() |
|||
|
|||
if (animateStatus === ENTERING && !enter && this.data.enter) { |
|||
this.performEntered() |
|||
} |
|||
|
|||
if (animateStatus === EXITING && !exit && this.data.exit) { |
|||
this.performExited() |
|||
} |
|||
}, |
|||
/** |
|||
* 会在 WXSS transition 或 wx.createAnimation 动画结束后触发 |
|||
*/ |
|||
onTransitionEnd() { |
|||
if (this.data.type === TRANSITION) { |
|||
this.addEventListener() |
|||
} |
|||
}, |
|||
/** |
|||
* 会在一个 WXSS animation 动画完成时触发 |
|||
*/ |
|||
onAnimationEnd() { |
|||
if (this.data.type === ANIMATION) { |
|||
this.addEventListener() |
|||
} |
|||
}, |
|||
/** |
|||
* 更新组件状态 |
|||
* @param {String} nextStatus 下一状态,ENTERING 或 EXITING |
|||
* @param {Boolean} mounting 是否首次挂载 |
|||
*/ |
|||
updateStatus(nextStatus, mounting = false) { |
|||
if (nextStatus !== null) { |
|||
this.cancelNextCallback() |
|||
this.isAppearing = mounting |
|||
|
|||
if (nextStatus === ENTERING) { |
|||
this.performEnter() |
|||
} else { |
|||
this.performExit() |
|||
} |
|||
} |
|||
}, |
|||
/** |
|||
* 进入过渡 |
|||
*/ |
|||
performEnter() { |
|||
const { className, activeClassName } = this.getClassNames(ENTER) |
|||
const { enter } = this.getTimeouts() |
|||
const enterParams = { |
|||
animateStatus: ENTER, |
|||
animateCss: className, |
|||
} |
|||
const enteringParams = { |
|||
animateStatus: ENTERING, |
|||
animateCss: `${className} ${activeClassName}`, |
|||
} |
|||
|
|||
// 若已禁用进入过渡,则更新状态至 ENTERED
|
|||
if (!this.isAppearing && !this.data.enter) { |
|||
return this.performEntered() |
|||
} |
|||
|
|||
// 第一阶段:设置进入过渡的开始状态,并触发 ENTER 事件
|
|||
// 第二阶段:延迟一帧后,设置进入过渡的结束状态,并触发 ENTERING 事件
|
|||
// 第三阶段:若已设置过渡的持续时间,则延迟指定时间后触发进入过渡完成 performEntered,否则等待触发 onTransitionEnd 或 onAnimationEnd
|
|||
this.safeSetData(enterParams, () => { |
|||
this.triggerEvent('change', { animateStatus: ENTER }) |
|||
this.triggerEvent(ENTER, { isAppearing: this.isAppearing }) |
|||
|
|||
// 由于有些时候不能正确的触发动画完成的回调,具体原因未知
|
|||
// 所以采用延迟一帧的方式来确保可以触发回调
|
|||
this.delayHandler(TIMEOUT, () => { |
|||
this.safeSetData(enteringParams, () => { |
|||
this.triggerEvent('change', { animateStatus: ENTERING }) |
|||
this.triggerEvent(ENTERING, { isAppearing: this.isAppearing }) |
|||
|
|||
if (enter) { |
|||
this.delayHandler(enter, this.performEntered) |
|||
} |
|||
}) |
|||
}) |
|||
}) |
|||
}, |
|||
/** |
|||
* 进入过渡完成 |
|||
*/ |
|||
performEntered() { |
|||
const { doneClassName } = this.getClassNames(ENTER) |
|||
const enteredParams = { |
|||
animateStatus: ENTERED, |
|||
animateCss: doneClassName, |
|||
} |
|||
|
|||
// 第三阶段:设置进入过渡的完成状态,并触发 ENTERED 事件
|
|||
this.safeSetData(enteredParams, () => { |
|||
this.triggerEvent('change', { animateStatus: ENTERED }) |
|||
this.triggerEvent(ENTERED, { isAppearing: this.isAppearing }) |
|||
}) |
|||
}, |
|||
/** |
|||
* 离开过渡 |
|||
*/ |
|||
performExit() { |
|||
const { className, activeClassName } = this.getClassNames(EXIT) |
|||
const { exit } = this.getTimeouts() |
|||
const exitParams = { |
|||
animateStatus: EXIT, |
|||
animateCss: className, |
|||
} |
|||
const exitingParams = { |
|||
animateStatus: EXITING, |
|||
animateCss: `${className} ${activeClassName}`, |
|||
} |
|||
|
|||
// 若已禁用离开过渡,则更新状态至 EXITED
|
|||
if (!this.data.exit) { |
|||
return this.performExited() |
|||
} |
|||
|
|||
// 第一阶段:设置离开过渡的开始状态,并触发 EXIT 事件
|
|||
// 第二阶段:延迟一帧后,设置离开过渡的结束状态,并触发 EXITING 事件
|
|||
// 第三阶段:若已设置过渡的持续时间,则延迟指定时间后触发离开过渡完成 performExited,否则等待触发 onTransitionEnd 或 onAnimationEnd
|
|||
this.safeSetData(exitParams, () => { |
|||
this.triggerEvent('change', { animateStatus: EXIT }) |
|||
this.triggerEvent(EXIT) |
|||
|
|||
this.delayHandler(TIMEOUT, () => { |
|||
this.safeSetData(exitingParams, () => { |
|||
this.triggerEvent('change', { animateStatus: EXITING }) |
|||
this.triggerEvent(EXITING) |
|||
|
|||
if (exit) { |
|||
this.delayHandler(exit, this.performExited) |
|||
} |
|||
}) |
|||
}) |
|||
}) |
|||
}, |
|||
/** |
|||
* 离开过渡完成 |
|||
*/ |
|||
performExited() { |
|||
const { doneClassName } = this.getClassNames(EXIT) |
|||
const exitedParams = { |
|||
animateStatus: EXITED, |
|||
animateCss: doneClassName, |
|||
} |
|||
|
|||
// 第三阶段:设置离开过渡的完成状态,并触发 EXITED 事件
|
|||
this.safeSetData(exitedParams, () => { |
|||
this.triggerEvent('change', { animateStatus: EXITED }) |
|||
this.triggerEvent(EXITED) |
|||
|
|||
// 判断离开过渡完成时是否卸载组件
|
|||
if (this.data.unmountOnExit) { |
|||
this.setData({ animateStatus: UNMOUNTED }, () => { |
|||
this.triggerEvent('change', { animateStatus: UNMOUNTED }) |
|||
}) |
|||
} |
|||
}) |
|||
}, |
|||
/** |
|||
* 获取指定状态下的类名 |
|||
* @param {String} type 过渡类型,enter 或 exit |
|||
*/ |
|||
getClassNames(type) { |
|||
const { classNames } = this.data |
|||
const className = typeof classNames !== 'string' ? classNames[type] : `${classNames}-${type}` |
|||
const activeClassName = typeof classNames !== 'string' ? classNames[`${type}Active`] : `${classNames}-${type}-active` |
|||
const doneClassName = typeof classNames !== 'string' ? classNames[`${type}Done`] : `${classNames}-${type}-done` |
|||
|
|||
return { |
|||
className, |
|||
activeClassName, |
|||
doneClassName, |
|||
} |
|||
}, |
|||
/** |
|||
* 获取过渡持续时间 |
|||
*/ |
|||
getTimeouts() { |
|||
const { duration } = this.data |
|||
|
|||
if (duration !== null && typeof duration === 'object') { |
|||
return { |
|||
enter: duration.enter, |
|||
exit: duration.exit, |
|||
} |
|||
} else if (typeof duration === 'number') { |
|||
return { |
|||
enter: duration, |
|||
exit: duration, |
|||
} |
|||
} |
|||
|
|||
return {} |
|||
}, |
|||
/** |
|||
* 属性值 in 被更改时的响应函数 |
|||
* @param {Boolean} newVal 触发组件进入或离开过渡的状态 |
|||
*/ |
|||
updated(newVal) { |
|||
let { animateStatus } = this.pendingData || this.data |
|||
let nextStatus = null |
|||
|
|||
if (newVal) { |
|||
if (animateStatus === UNMOUNTED) { |
|||
animateStatus = EXITED |
|||
this.setData({ animateStatus: EXITED }, () => { |
|||
this.triggerEvent('change', { animateStatus: EXITED }) |
|||
}) |
|||
} |
|||
if (animateStatus !== ENTER && animateStatus !== ENTERING && animateStatus !== ENTERED) { |
|||
nextStatus = ENTERING |
|||
} |
|||
} else { |
|||
if (animateStatus === ENTER || animateStatus === ENTERING || animateStatus === ENTERED) { |
|||
nextStatus = EXITING |
|||
} |
|||
} |
|||
|
|||
this.updateStatus(nextStatus) |
|||
}, |
|||
/** |
|||
* 延迟一段时间触发回调 |
|||
* @param {Number} timeout 延迟时间 |
|||
* @param {Function} handler 回调函数 |
|||
*/ |
|||
delayHandler(timeout, handler) { |
|||
if (timeout) { |
|||
this.setNextCallback(handler) |
|||
setTimeout(this.nextCallback, timeout) |
|||
} |
|||
}, |
|||
/** |
|||
* 点击事件 |
|||
*/ |
|||
onTap() { |
|||
this.triggerEvent('click') |
|||
}, |
|||
/** |
|||
* 阻止移动触摸 |
|||
*/ |
|||
noop() {}, |
|||
}, |
|||
attached() { |
|||
let animateStatus = null |
|||
let appearStatus = null |
|||
|
|||
if (this.data.in) { |
|||
if (this.data.appear) { |
|||
animateStatus = EXITED |
|||
appearStatus = ENTERING |
|||
} else { |
|||
animateStatus = ENTERED |
|||
} |
|||
} else { |
|||
if (this.data.unmountOnExit || this.data.mountOnEnter) { |
|||
animateStatus = UNMOUNTED |
|||
} else { |
|||
animateStatus = EXITED |
|||
} |
|||
} |
|||
|
|||
// 由于小程序组件首次挂载时 observer 事件总是优先于 attached 事件
|
|||
// 所以使用 isMounting 来强制优先触发 attached 事件
|
|||
this.safeSetData({ animateStatus, isMounting: true }, () => { |
|||
this.triggerEvent('change', { animateStatus }) |
|||
this.updateStatus(appearStatus, true) |
|||
}) |
|||
}, |
|||
}) |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"component": true |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<view class="wux-class {{ wrapCls }} {{ animateCss }}" bindtap="onTap" catchtouchmove="{{ disableScroll ? 'noop' : '' }}" bindtransitionend="onTransitionEnd" bindanimationend="onAnimationEnd" wx:if="{{ animateStatus !== 'unmounted' }}" style="{{ extStyle }}"> |
|||
<slot></slot> |
|||
</view> |
|||
@ -0,0 +1,206 @@ |
|||
.wux-animate--fadeIn-enter { |
|||
transition: opacity .3s; |
|||
opacity: 0 |
|||
} |
|||
.wux-animate--fadeIn-enter-active, |
|||
.wux-animate--fadeIn-enter-done { |
|||
opacity: 1 |
|||
} |
|||
.wux-animate--fadeIn-exit { |
|||
transition: opacity .3s; |
|||
opacity: 1 |
|||
} |
|||
.wux-animate--fadeIn-exit-active, |
|||
.wux-animate--fadeIn-exit-done { |
|||
opacity: 0 |
|||
} |
|||
.wux-animate--fadeInDown-enter { |
|||
transition: opacity .3s,transform .3s; |
|||
opacity: 0; |
|||
transform: translate3d(0,-100%,0) |
|||
} |
|||
.wux-animate--fadeInDown-enter-active, |
|||
.wux-animate--fadeInDown-enter-done { |
|||
opacity: 1; |
|||
transform: none |
|||
} |
|||
.wux-animate--fadeInDown-exit { |
|||
transition: opacity .3s,transform .3s; |
|||
opacity: 1; |
|||
transform: none |
|||
} |
|||
.wux-animate--fadeInDown-exit-active, |
|||
.wux-animate--fadeInDown-exit-done { |
|||
opacity: 0; |
|||
transform: translate3d(0,-100%,0) |
|||
} |
|||
.wux-animate--fadeInLeft-enter { |
|||
transition: opacity .3s,transform .3s; |
|||
opacity: 0; |
|||
transform: translate3d(-100%,0,0) |
|||
} |
|||
.wux-animate--fadeInLeft-enter-active, |
|||
.wux-animate--fadeInLeft-enter-done { |
|||
opacity: 1; |
|||
transform: none |
|||
} |
|||
.wux-animate--fadeInLeft-exit { |
|||
transition: opacity .3s,transform .3s; |
|||
opacity: 1; |
|||
transform: none |
|||
} |
|||
.wux-animate--fadeInLeft-exit-active, |
|||
.wux-animate--fadeInLeft-exit-done { |
|||
opacity: 0; |
|||
transform: translate3d(-100%,0,0) |
|||
} |
|||
.wux-animate--fadeInRight-enter { |
|||
transition: opacity .3s,transform .3s; |
|||
opacity: 0; |
|||
transform: translate3d(100%,0,0) |
|||
} |
|||
.wux-animate--fadeInRight-enter-active, |
|||
.wux-animate--fadeInRight-enter-done { |
|||
opacity: 1; |
|||
transform: none |
|||
} |
|||
.wux-animate--fadeInRight-exit { |
|||
transition: opacity .3s,transform .3s; |
|||
opacity: 1; |
|||
transform: none |
|||
} |
|||
.wux-animate--fadeInRight-exit-active, |
|||
.wux-animate--fadeInRight-exit-done { |
|||
opacity: 0; |
|||
transform: translate3d(100%,0,0) |
|||
} |
|||
.wux-animate--fadeInUp-enter { |
|||
transition: opacity .3s,transform .3s; |
|||
opacity: 0; |
|||
transform: translate3d(0,100%,0) |
|||
} |
|||
.wux-animate--fadeInUp-enter-active, |
|||
.wux-animate--fadeInUp-enter-done { |
|||
opacity: 1; |
|||
transform: none |
|||
} |
|||
.wux-animate--fadeInUp-exit { |
|||
transition: opacity .3s,transform .3s; |
|||
opacity: 1; |
|||
transform: none |
|||
} |
|||
.wux-animate--fadeInUp-exit-active, |
|||
.wux-animate--fadeInUp-exit-done { |
|||
opacity: 0; |
|||
transform: translate3d(0,100%,0) |
|||
} |
|||
.wux-animate--slideInUp-enter { |
|||
transition: transform .3s; |
|||
transform: translate3d(0,100%,0); |
|||
visibility: visible |
|||
} |
|||
.wux-animate--slideInUp-enter-active, |
|||
.wux-animate--slideInUp-enter-done { |
|||
transform: translateZ(0) |
|||
} |
|||
.wux-animate--slideInUp-exit { |
|||
transition: transform .3s; |
|||
transform: translateZ(0) |
|||
} |
|||
.wux-animate--slideInUp-exit-active, |
|||
.wux-animate--slideInUp-exit-done { |
|||
transform: translate3d(0,100%,0); |
|||
visibility: visible |
|||
} |
|||
.wux-animate--slideInDown-enter { |
|||
transition: transform .3s; |
|||
transform: translate3d(0,-100%,0); |
|||
visibility: visible |
|||
} |
|||
.wux-animate--slideInDown-enter-active, |
|||
.wux-animate--slideInDown-enter-done { |
|||
transform: translateZ(0) |
|||
} |
|||
.wux-animate--slideInDown-exit { |
|||
transition: transform .3s; |
|||
transform: translateZ(0) |
|||
} |
|||
.wux-animate--slideInDown-exit-active, |
|||
.wux-animate--slideInDown-exit-done { |
|||
transform: translate3d(0,-100%,0); |
|||
visibility: visible |
|||
} |
|||
.wux-animate--slideInLeft-enter { |
|||
transition: transform .3s; |
|||
transform: translate3d(-100%,0,0); |
|||
visibility: visible |
|||
} |
|||
.wux-animate--slideInLeft-enter-active, |
|||
.wux-animate--slideInLeft-enter-done { |
|||
transform: translateZ(0) |
|||
} |
|||
.wux-animate--slideInLeft-exit { |
|||
transition: transform .3s; |
|||
transform: translateZ(0) |
|||
} |
|||
.wux-animate--slideInLeft-exit-active, |
|||
.wux-animate--slideInLeft-exit-done { |
|||
transform: translate3d(-100%,0,0); |
|||
visibility: visible |
|||
} |
|||
.wux-animate--slideInRight-enter { |
|||
transition: transform .3s; |
|||
transform: translate3d(100%,0,0); |
|||
visibility: visible |
|||
} |
|||
.wux-animate--slideInRight-enter-active, |
|||
.wux-animate--slideInRight-enter-done { |
|||
transform: none |
|||
} |
|||
.wux-animate--slideInRight-exit { |
|||
transition: transform .3s; |
|||
transform: none |
|||
} |
|||
.wux-animate--slideInRight-exit-active, |
|||
.wux-animate--slideInRight-exit-done { |
|||
transform: translate3d(100%,0,0); |
|||
visibility: visible |
|||
} |
|||
.wux-animate--zoom-enter { |
|||
transition: all .3s cubic-bezier(.215,.61,.355,1); |
|||
opacity: .01; |
|||
transform: scale(.75) |
|||
} |
|||
.wux-animate--zoom-enter-active, |
|||
.wux-animate--zoom-enter-done { |
|||
opacity: 1; |
|||
transform: none |
|||
} |
|||
.wux-animate--zoom-exit { |
|||
transition: all .25s linear; |
|||
transform: none |
|||
} |
|||
.wux-animate--zoom-exit-active, |
|||
.wux-animate--zoom-exit-done { |
|||
opacity: .01; |
|||
transform: scale(.75) |
|||
} |
|||
.wux-animate--punch-enter { |
|||
transition: all .3s cubic-bezier(.215,.61,.355,1); |
|||
opacity: .01; |
|||
transform: scale(1.35) |
|||
} |
|||
.wux-animate--punch-enter-active, |
|||
.wux-animate--punch-enter-done { |
|||
opacity: 1; |
|||
transform: none |
|||
} |
|||
.wux-animate--punch-exit { |
|||
transition: all .25s linear; |
|||
transform: none |
|||
} |
|||
.wux-animate--punch-exit-active, |
|||
.wux-animate--punch-exit-done { |
|||
opacity: .01; |
|||
transform: scale(1.35) |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
|
|||
baseComponent({ |
|||
properties: { |
|||
prefixCls: { |
|||
type: String, |
|||
value: 'wux-backdrop', |
|||
}, |
|||
transparent: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
zIndex: { |
|||
type: Number, |
|||
value: 1000, |
|||
}, |
|||
classNames: { |
|||
type: null, |
|||
value: 'wux-animate--fadeIn', |
|||
}, |
|||
}, |
|||
computed: { |
|||
classes: ['prefixCls, transparent', function(prefixCls, transparent) { |
|||
const wrap = transparent ? `${prefixCls}--transparent` : prefixCls |
|||
|
|||
return { |
|||
wrap, |
|||
} |
|||
}], |
|||
}, |
|||
methods: { |
|||
/** |
|||
* 保持锁定 |
|||
*/ |
|||
retain() { |
|||
if (typeof this.backdropHolds !== 'number' || !this.backdropHolds) { |
|||
this.backdropHolds = 0 |
|||
} |
|||
|
|||
this.backdropHolds = this.backdropHolds + 1 |
|||
|
|||
if (this.backdropHolds === 1) { |
|||
this.setData({ in: true }) |
|||
} |
|||
}, |
|||
/** |
|||
* 释放锁定 |
|||
*/ |
|||
release() { |
|||
if (this.backdropHolds === 1) { |
|||
this.setData({ in: false }) |
|||
} |
|||
this.backdropHolds = Math.max(0, this.backdropHolds - 1) |
|||
}, |
|||
/** |
|||
* 点击事件 |
|||
*/ |
|||
onClick() { |
|||
this.triggerEvent('click') |
|||
}, |
|||
}, |
|||
}) |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"component": true, |
|||
"usingComponents": { |
|||
"wux-animation-group": "../animation-group/index" |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
<wux-animation-group wux-class="{{ classes.wrap }}" in="{{ in }}" classNames="{{ classNames }}" bind:click="onClick" wrapStyle="{{ { zIndex } }}" disableScroll /> |
|||
@ -0,0 +1,15 @@ |
|||
.wux-backdrop { |
|||
background: rgba(0,0,0,.4) |
|||
} |
|||
.wux-backdrop, |
|||
.wux-backdrop--transparent { |
|||
position: fixed; |
|||
z-index: 1000; |
|||
top: 0; |
|||
right: 0; |
|||
left: 0; |
|||
bottom: 0 |
|||
} |
|||
.wux-backdrop--transparent { |
|||
background: 0 0 |
|||
} |
|||
@ -0,0 +1,146 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import classNames from '../helpers/classNames' |
|||
|
|||
baseComponent({ |
|||
properties: { |
|||
prefixCls: { |
|||
type: String, |
|||
value: 'wux-button', |
|||
}, |
|||
type: { |
|||
type: String, |
|||
value: 'stable', |
|||
}, |
|||
clear: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
round: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
block: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
full: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
outline: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
bordered: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
size: { |
|||
type: String, |
|||
value: 'default', |
|||
}, |
|||
disabled: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
loading: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
formType: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
openType: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
hoverClass: { |
|||
type: String, |
|||
value: 'default', |
|||
}, |
|||
hoverStopPropagation: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
hoverStartTime: { |
|||
type: Number, |
|||
value: 20, |
|||
}, |
|||
hoverStayTime: { |
|||
type: Number, |
|||
value: 70, |
|||
}, |
|||
lang: { |
|||
type: String, |
|||
value: 'en', |
|||
}, |
|||
sessionFrom: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
sendMessageTitle: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
sendMessagePath: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
sendMessageImg: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
showMessageCard: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
appParameter: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
}, |
|||
computed: { |
|||
classes: ['prefixCls, hoverClass, type, size, block, full, clear, outline, round, bordered, disabled', function (prefixCls, hoverClass, type, size, block, full, clear, outline, round, bordered, disabled) { |
|||
const wrap = classNames(prefixCls, { |
|||
[`${prefixCls}--${type}`]: type, |
|||
[`${prefixCls}--${size}`]: size, |
|||
[`${prefixCls}--block`]: block, |
|||
[`${prefixCls}--full`]: full, |
|||
[`${prefixCls}--clear`]: clear, |
|||
[`${prefixCls}--round`]: round, |
|||
[`${prefixCls}--outline`]: outline, |
|||
[`${prefixCls}--bordered`]: bordered, |
|||
[`${prefixCls}--disabled`]: disabled, |
|||
}) |
|||
const hover = hoverClass && hoverClass !== 'default' ? hoverClass : `${prefixCls}--hover` |
|||
|
|||
return { |
|||
wrap, |
|||
hover, |
|||
} |
|||
}], |
|||
}, |
|||
methods: { |
|||
onTap() { |
|||
if (!this.data.disabled && !this.data.loading) { |
|||
this.triggerEvent('click') |
|||
} |
|||
}, |
|||
bindgetuserinfo(e) { |
|||
this.triggerEvent('getuserinfo', e.detail) |
|||
}, |
|||
bindcontact(e) { |
|||
this.triggerEvent('contact', e.detail) |
|||
}, |
|||
bindgetphonenumber(e) { |
|||
this.triggerEvent('getphonenumber', e.detail) |
|||
}, |
|||
bindopensetting(e) { |
|||
this.triggerEvent('opensetting', e.detail) |
|||
}, |
|||
onError(e) { |
|||
this.triggerEvent('error', e.detail) |
|||
}, |
|||
}, |
|||
}) |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"component": true |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
<button |
|||
class="wux-class {{ classes.wrap }}" |
|||
disabled="{{ disabled }}" |
|||
loading="{{ loading }}" |
|||
form-type="{{ formType }}" |
|||
open-type="{{ openType }}" |
|||
hover-class="wux-hover-class {{ !disabled ? classes.hover : 'none' }}" |
|||
hover-stop-propagation="{{ hoverStopPropagation }}" |
|||
hover-start-time="{{ hoverStartTime }}" |
|||
hover-stay-time="{{ hoverStayTime }}" |
|||
lang="{{ lang }}" |
|||
bindgetuserinfo="bindgetuserinfo" |
|||
session-from="{{ sessionFrom }}" |
|||
send-message-title="{{ sendMessageTitle }}" |
|||
send-message-path="{{ sendMessagePath }}" |
|||
send-message-img="{{ sendMessageImg }}" |
|||
show-message-card="{{ showMessageCard }}" |
|||
bindcontact="bindcontact" |
|||
bindgetphonenumber="bindgetphonenumber" |
|||
app-parameter="{{ appParameter }}" |
|||
binderror="onError" |
|||
bindopensetting="bindopensetting" |
|||
bindtap="onTap" |
|||
> |
|||
<slot></slot> |
|||
</button> |
|||
@ -0,0 +1,356 @@ |
|||
.wux-button { |
|||
color: inherit!important; |
|||
background: 0 0!important; |
|||
font-weight: 400; |
|||
text-decoration: none; |
|||
overflow: visible; |
|||
width: auto!important; |
|||
-webkit-tap-highlight-color: transparent; |
|||
position: relative; |
|||
display: inline-block; |
|||
box-sizing: border-box; |
|||
margin: 0; |
|||
padding: 0 24rpx; |
|||
min-width: 104rpx; |
|||
min-height: 88rpx!important; |
|||
border: none; |
|||
border-radius: 8rpx; |
|||
vertical-align: middle; |
|||
text-align: center; |
|||
text-overflow: ellipsis; |
|||
font-size: 32rpx; |
|||
line-height: 84rpx; |
|||
cursor: pointer |
|||
} |
|||
.wux-button:after { |
|||
display: block; |
|||
position: static; |
|||
top: auto; |
|||
left: auto; |
|||
width: auto; |
|||
height: auto; |
|||
border: none; |
|||
border-radius: 0; |
|||
transform: none; |
|||
transform-origin: 0 0 |
|||
} |
|||
.wux-button:after { |
|||
content: " "; |
|||
width: 100%; |
|||
height: 100%; |
|||
position: absolute; |
|||
top: -12rpx; |
|||
right: -12rpx; |
|||
bottom: -12rpx; |
|||
left: -12rpx; |
|||
border: none; |
|||
transform: none; |
|||
transform-origin: 0 0; |
|||
box-sizing: border-box; |
|||
border-radius: 0 |
|||
} |
|||
.wux-button--bordered { |
|||
border: 2rpx solid transparent |
|||
} |
|||
.wux-button--disabled { |
|||
opacity: .4!important |
|||
} |
|||
.wux-button--small { |
|||
padding: 4rpx 8rpx 2rpx; |
|||
min-width: 56rpx; |
|||
min-height: 60rpx!important; |
|||
font-size: 24rpx; |
|||
line-height: 52rpx |
|||
} |
|||
.wux-button--large { |
|||
padding: 0 32rpx; |
|||
min-width: 136rpx; |
|||
min-height: 118rpx!important; |
|||
font-size: 40rpx; |
|||
line-height: 106rpx |
|||
} |
|||
.wux-button--block, |
|||
.wux-button--full { |
|||
width: 100%!important; |
|||
margin-top: 20rpx; |
|||
margin-bottom: 20rpx |
|||
} |
|||
.wux-button--block { |
|||
display: block; |
|||
clear: both |
|||
} |
|||
.wux-button--block:after { |
|||
clear: both |
|||
} |
|||
.wux-button--full { |
|||
display: block; |
|||
margin-right: 0!important; |
|||
margin-left: 0!important; |
|||
border-right-width: 0; |
|||
border-left-width: 0; |
|||
border-radius: 0 |
|||
} |
|||
.wux-button--outline.wux-button--hover { |
|||
color: #fff!important |
|||
} |
|||
.wux-button--light, |
|||
.wux-button--light--disabled { |
|||
border-color: transparent!important; |
|||
background-color: #fff!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--light.wux-button--outline, |
|||
.wux-button--light.wux-button--outline.wux-button--disabled { |
|||
border-color: #fff!important; |
|||
background-color: transparent!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--light.wux-button--clear, |
|||
.wux-button--light.wux-button--clear.wux-button--disabled { |
|||
background-color: transparent!important; |
|||
color: #e6e6e6!important |
|||
} |
|||
.wux-button--light.wux-button--clear.wux-button--hover { |
|||
background-color: rgba(0,0,0,0)!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--light.wux-button--hover { |
|||
background-color: #e6e6e6!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--stable, |
|||
.wux-button--stable--disabled { |
|||
border-color: transparent!important; |
|||
background-color: #f8f8f8!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--stable.wux-button--outline, |
|||
.wux-button--stable.wux-button--outline.wux-button--disabled { |
|||
border-color: #f8f8f8!important; |
|||
background-color: transparent!important; |
|||
color: #f8f8f8!important |
|||
} |
|||
.wux-button--stable.wux-button--clear, |
|||
.wux-button--stable.wux-button--clear.wux-button--disabled { |
|||
background-color: transparent!important; |
|||
color: #dfdfdf!important |
|||
} |
|||
.wux-button--stable.wux-button--clear.wux-button--hover { |
|||
background-color: rgba(0,0,0,0)!important; |
|||
color: #f8f8f8!important |
|||
} |
|||
.wux-button--stable.wux-button--hover { |
|||
background-color: #dfdfdf!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--positive, |
|||
.wux-button--positive--disabled { |
|||
border-color: transparent!important; |
|||
background-color: #008AFF!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--positive.wux-button--outline, |
|||
.wux-button--positive.wux-button--outline.wux-button--disabled { |
|||
border-color: #008AFF!important; |
|||
background-color: transparent!important; |
|||
color: #008AFF!important |
|||
} |
|||
.wux-button--positive.wux-button--clear, |
|||
.wux-button--positive.wux-button--clear.wux-button--disabled { |
|||
background-color: transparent!important; |
|||
color: #0c60ee!important |
|||
} |
|||
.wux-button--positive.wux-button--clear.wux-button--hover { |
|||
background-color: rgba(0,0,0,0)!important; |
|||
color: #008AFF!important |
|||
} |
|||
.wux-button--positive.wux-button--hover { |
|||
background-color: #0c60ee!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--calm, |
|||
.wux-button--calm--disabled { |
|||
border-color: transparent!important; |
|||
background-color: #11c1f3!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--calm.wux-button--outline, |
|||
.wux-button--calm.wux-button--outline.wux-button--disabled { |
|||
border-color: #11c1f3!important; |
|||
background-color: transparent!important; |
|||
color: #11c1f3!important |
|||
} |
|||
.wux-button--calm.wux-button--clear, |
|||
.wux-button--calm.wux-button--clear.wux-button--disabled { |
|||
background-color: transparent!important; |
|||
color: #0a9dc7!important |
|||
} |
|||
.wux-button--calm.wux-button--clear.wux-button--hover { |
|||
background-color: rgba(0,0,0,0)!important; |
|||
color: #11c1f3!important |
|||
} |
|||
.wux-button--calm.wux-button--hover { |
|||
background-color: #0a9dc7!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--assertive, |
|||
.wux-button--assertive--disabled { |
|||
border-color: transparent!important; |
|||
background-color: #ef473a!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--assertive.wux-button--outline, |
|||
.wux-button--assertive.wux-button--outline.wux-button--disabled { |
|||
border-color: #ef473a!important; |
|||
background-color: transparent!important; |
|||
color: #ef473a!important |
|||
} |
|||
.wux-button--assertive.wux-button--clear, |
|||
.wux-button--assertive.wux-button--clear.wux-button--disabled { |
|||
background-color: transparent!important; |
|||
color: #e42112!important |
|||
} |
|||
.wux-button--assertive.wux-button--clear.wux-button--hover { |
|||
background-color: rgba(0,0,0,0)!important; |
|||
color: #ef473a!important |
|||
} |
|||
.wux-button--assertive.wux-button--hover { |
|||
background-color: #e42112!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--balanced, |
|||
.wux-button--balanced--disabled { |
|||
border-color: transparent!important; |
|||
background-color: #33cd5f!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--balanced.wux-button--outline, |
|||
.wux-button--balanced.wux-button--outline.wux-button--disabled { |
|||
border-color: #33cd5f!important; |
|||
background-color: transparent!important; |
|||
color: #33cd5f!important |
|||
} |
|||
.wux-button--balanced.wux-button--clear, |
|||
.wux-button--balanced.wux-button--clear.wux-button--disabled { |
|||
background-color: transparent!important; |
|||
color: #28a54c!important |
|||
} |
|||
.wux-button--balanced.wux-button--clear.wux-button--hover { |
|||
background-color: rgba(0,0,0,0)!important; |
|||
color: #33cd5f!important |
|||
} |
|||
.wux-button--balanced.wux-button--hover { |
|||
background-color: #28a54c!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--energized, |
|||
.wux-button--energized--disabled { |
|||
border-color: transparent!important; |
|||
background-color: #ffc900!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--energized.wux-button--outline, |
|||
.wux-button--energized.wux-button--outline.wux-button--disabled { |
|||
border-color: #ffc900!important; |
|||
background-color: transparent!important; |
|||
color: #ffc900!important |
|||
} |
|||
.wux-button--energized.wux-button--clear, |
|||
.wux-button--energized.wux-button--clear.wux-button--disabled { |
|||
background-color: transparent!important; |
|||
color: #cca100!important |
|||
} |
|||
.wux-button--energized.wux-button--clear.wux-button--hover { |
|||
background-color: rgba(0,0,0,0)!important; |
|||
color: #ffc900!important |
|||
} |
|||
.wux-button--energized.wux-button--hover { |
|||
background-color: #cca100!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--royal, |
|||
.wux-button--royal--disabled { |
|||
border-color: transparent!important; |
|||
background-color: #886aea!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--royal.wux-button--outline, |
|||
.wux-button--royal.wux-button--outline.wux-button--disabled { |
|||
border-color: #886aea!important; |
|||
background-color: transparent!important; |
|||
color: #886aea!important |
|||
} |
|||
.wux-button--royal.wux-button--clear, |
|||
.wux-button--royal.wux-button--clear.wux-button--disabled { |
|||
background-color: transparent!important; |
|||
color: #643de4!important |
|||
} |
|||
.wux-button--royal.wux-button--clear.wux-button--hover { |
|||
background-color: rgba(0,0,0,0)!important; |
|||
color: #886aea!important |
|||
} |
|||
.wux-button--royal.wux-button--hover { |
|||
background-color: #643de4!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--dark, |
|||
.wux-button--dark--disabled { |
|||
border-color: transparent!important; |
|||
background-color: #444!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--dark.wux-button--outline, |
|||
.wux-button--dark.wux-button--outline.wux-button--disabled { |
|||
border-color: #444!important; |
|||
background-color: transparent!important; |
|||
color: #444!important |
|||
} |
|||
.wux-button--dark.wux-button--clear, |
|||
.wux-button--dark.wux-button--clear.wux-button--disabled { |
|||
background-color: transparent!important; |
|||
color: #2b2b2b!important |
|||
} |
|||
.wux-button--dark.wux-button--clear.wux-button--hover { |
|||
background-color: rgba(0,0,0,0)!important; |
|||
color: #444!important |
|||
} |
|||
.wux-button--dark.wux-button--hover { |
|||
background-color: #2b2b2b!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--light { |
|||
border-color: transparent!important; |
|||
background-color: #fff!important; |
|||
color: #444!important |
|||
} |
|||
.wux-button--light.wux-button--outline { |
|||
border-color: #ddd!important; |
|||
background-color: transparent!important; |
|||
color: #ddd!important |
|||
} |
|||
.wux-button--light.wux-button--clear.wux-button--hover { |
|||
background-color: rgba(0,0,0,0)!important; |
|||
color: #ddd!important |
|||
} |
|||
.wux-button--light.wux-button--hover { |
|||
background-color: #e6e6e6!important; |
|||
color: #fff!important |
|||
} |
|||
.wux-button--stable { |
|||
border-color: transparent!important; |
|||
background-color: #f8f8f8!important; |
|||
color: #444!important |
|||
} |
|||
.wux-button--stable.wux-button--outline { |
|||
border-color: #b2b2b2!important; |
|||
background-color: transparent!important; |
|||
color: #b2b2b2!important |
|||
} |
|||
.wux-button--stable.wux-button--clear.wux-button--hover { |
|||
background-color: rgba(0,0,0,0)!important; |
|||
color: #b2b2b2!important |
|||
} |
|||
.wux-button--stable.wux-button--hover { |
|||
background-color: #dfdfdf!important; |
|||
color: #fff!important |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import classNames from '../helpers/classNames' |
|||
|
|||
baseComponent({ |
|||
options: { |
|||
multipleSlots: false, |
|||
}, |
|||
relations: { |
|||
'../cell/index': { |
|||
type: 'descendant', |
|||
observer() { |
|||
this.debounce(this.updateIsLastElement) |
|||
}, |
|||
}, |
|||
}, |
|||
properties: { |
|||
prefixCls: { |
|||
type: String, |
|||
value: 'wux-cell-group', |
|||
}, |
|||
title: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
label: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
}, |
|||
computed: { |
|||
classes: ['prefixCls', function(prefixCls) { |
|||
const wrap = classNames(prefixCls) |
|||
const hd = `${prefixCls}__hd` |
|||
const bd = `${prefixCls}__bd` |
|||
const ft = `${prefixCls}__ft` |
|||
|
|||
return { |
|||
wrap, |
|||
hd, |
|||
bd, |
|||
ft, |
|||
} |
|||
}], |
|||
}, |
|||
methods: { |
|||
updateIsLastElement() { |
|||
const elements = this.getRelationNodes('../cell/index') |
|||
if (elements.length > 0) { |
|||
const lastIndex = elements.length - 1 |
|||
elements.forEach((element, index) => { |
|||
element.updateIsLastElement(index === lastIndex) |
|||
}) |
|||
} |
|||
}, |
|||
getBoundingClientRect(callback) { |
|||
const className = `.${this.data.prefixCls}` |
|||
wx |
|||
.createSelectorQuery() |
|||
.in(this) |
|||
.select(className) |
|||
.boundingClientRect((rect) => { |
|||
if (!rect) return |
|||
callback.call(this, rect.height) |
|||
}) |
|||
.exec() |
|||
}, |
|||
}, |
|||
}) |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"component": true |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
<view class="wux-class {{ classes.wrap }}"> |
|||
<view class="{{ classes.hd }}" wx:if="{{ title }}">{{ title }}</view> |
|||
<view class="{{ classes.bd }}"> |
|||
<slot></slot> |
|||
</view> |
|||
<view class="{{ classes.ft }}" wx:if="{{ label }}">{{ label }}</view> |
|||
</view> |
|||
@ -0,0 +1,31 @@ |
|||
.wux-cell-group__hd { |
|||
padding: 30rpx 30rpx 18rpx; |
|||
font-size: 28rpx; |
|||
color: #888; |
|||
width: 100%; |
|||
box-sizing: border-box |
|||
} |
|||
.wux-cell-group__bd { |
|||
position: relative; |
|||
background-color: #fff |
|||
} |
|||
.wux-cell-group__bd:after { |
|||
content: " "; |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
width: 200%; |
|||
height: 200%; |
|||
transform: scale(.5); |
|||
transform-origin: 0 0; |
|||
pointer-events: none; |
|||
box-sizing: border-box; |
|||
/* border: 0 solid #d9d9d9; |
|||
border-top-width: 1rpx; |
|||
border-bottom-width: 1rpx */ |
|||
} |
|||
.wux-cell-group__ft { |
|||
padding: 18rpx 30rpx 30rpx; |
|||
font-size: 28rpx; |
|||
color: #888 |
|||
} |
|||
@ -0,0 +1,187 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import classNames from '../helpers/classNames' |
|||
import eventsMixin from '../helpers/eventsMixin' |
|||
|
|||
const defaultEvents = { |
|||
onClick() {}, |
|||
onError() {}, |
|||
} |
|||
|
|||
baseComponent({ |
|||
behaviors: [eventsMixin({ defaultEvents })], |
|||
relations: { |
|||
'../cell-group/index': { |
|||
type: 'ancestor', |
|||
}, |
|||
'../picker/index': { |
|||
type: 'parent', |
|||
}, |
|||
'../date-picker/index': { |
|||
type: 'parent', |
|||
}, |
|||
'../popup-select/index': { |
|||
type: 'parent', |
|||
}, |
|||
}, |
|||
properties: { |
|||
prefixCls: { |
|||
type: String, |
|||
value: 'wux-cell', |
|||
}, |
|||
disabled: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
hoverClass: { |
|||
type: String, |
|||
value: 'default', |
|||
}, |
|||
hoverStopPropagation: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
hoverStartTime: { |
|||
type: Number, |
|||
value: 20, |
|||
}, |
|||
hoverStayTime: { |
|||
type: Number, |
|||
value: 70, |
|||
}, |
|||
lang: { |
|||
type: String, |
|||
value: 'en', |
|||
}, |
|||
sessionFrom: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
sendMessageTitle: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
sendMessagePath: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
sendMessageImg: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
showMessageCard: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
appParameter: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
thumb: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
title: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
label: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
extra: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
isLink: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
openType: { |
|||
type: String, |
|||
value: 'navigateTo', |
|||
}, |
|||
url: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
delta: { |
|||
type: Number, |
|||
value: 1, |
|||
}, |
|||
}, |
|||
data: { |
|||
isLast: false, |
|||
}, |
|||
computed: { |
|||
classes: ['prefixCls, hoverClass, isLast, isLink, disabled', function(prefixCls, hoverClass, isLast, isLink, disabled) { |
|||
const wrap = classNames(prefixCls, { |
|||
[`${prefixCls}--last`]: isLast, |
|||
[`${prefixCls}--access`]: isLink, |
|||
[`${prefixCls}--disabled`]: disabled, |
|||
}) |
|||
const hd = `${prefixCls}__hd` |
|||
const thumb = `${prefixCls}__thumb` |
|||
const bd = `${prefixCls}__bd` |
|||
const text = `${prefixCls}__text` |
|||
const desc = `${prefixCls}__desc` |
|||
const ft = `${prefixCls}__ft` |
|||
const hover = hoverClass && hoverClass !== 'default' ? hoverClass : `${prefixCls}--hover` |
|||
|
|||
return { |
|||
wrap, |
|||
hd, |
|||
thumb, |
|||
bd, |
|||
text, |
|||
desc, |
|||
ft, |
|||
hover, |
|||
} |
|||
}], |
|||
}, |
|||
methods: { |
|||
onTap() { |
|||
if (!this.data.disabled) { |
|||
this.triggerEvent('click') |
|||
this.linkTo() |
|||
} |
|||
}, |
|||
bindgetuserinfo(e) { |
|||
this.triggerEvent('getuserinfo', e.detail) |
|||
}, |
|||
bindcontact(e) { |
|||
this.triggerEvent('contact', e.detail) |
|||
}, |
|||
bindgetphonenumber(e) { |
|||
this.triggerEvent('getphonenumber', e.detail) |
|||
}, |
|||
bindopensetting(e) { |
|||
this.triggerEvent('opensetting', e.detail) |
|||
}, |
|||
onError(e) { |
|||
this.triggerEvent('error', e.detail) |
|||
}, |
|||
linkTo() { |
|||
const { url, isLink, openType, delta } = this.data |
|||
const navigate = [ |
|||
'navigateTo', |
|||
'redirectTo', |
|||
'switchTab', |
|||
'navigateBack', |
|||
'reLaunch', |
|||
] |
|||
|
|||
// openType 属性可选值为 navigateTo、redirectTo、switchTab、navigateBack、reLaunch
|
|||
if (!isLink || !url || !navigate.includes(openType)) { |
|||
return false |
|||
} else if (openType === 'navigateBack') { |
|||
return wx[openType].call(wx, { delta }) |
|||
} else { |
|||
return wx[openType].call(wx, { url }) |
|||
} |
|||
}, |
|||
updateIsLastElement(isLast) { |
|||
this.setData({ isLast }) |
|||
}, |
|||
}, |
|||
}) |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"component": true |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
<button |
|||
class="wux-class {{ classes.wrap }}" |
|||
disabled="{{ disabled }}" |
|||
open-type="{{ openType }}" |
|||
hover-class="{{ !disabled ? classes.hover : 'none' }}" |
|||
hover-stop-propagation="{{ hoverStopPropagation }}" |
|||
hover-start-time="{{ hoverStartTime }}" |
|||
hover-stay-time="{{ hoverStayTime }}" |
|||
lang="{{ lang }}" |
|||
bindgetuserinfo="bindgetuserinfo" |
|||
session-from="{{ sessionFrom }}" |
|||
send-message-title="{{ sendMessageTitle }}" |
|||
send-message-path="{{ sendMessagePath }}" |
|||
send-message-img="{{ sendMessageImg }}" |
|||
show-message-card="{{ showMessageCard }}" |
|||
bindcontact="bindcontact" |
|||
bindgetphonenumber="bindgetphonenumber" |
|||
app-parameter="{{ appParameter }}" |
|||
binderror="onError" |
|||
bindopensetting="bindopensetting" |
|||
bindtap="onTap" |
|||
> |
|||
<view class="{{ classes.hd }}"> |
|||
<block wx:if="{{ thumb }}"> |
|||
<image class="{{ classes.thumb }}" src="{{ thumb }}" /> |
|||
</block> |
|||
<block wx:else> |
|||
<slot name="header"></slot> |
|||
</block> |
|||
</view> |
|||
<view class="{{ classes.bd }}"> |
|||
<view wx:if="{{ title }}" class="{{ classes.text }}">{{ title }}</view> |
|||
<view wx:if="{{ label }}" class="{{ classes.desc }}">{{ label }}</view> |
|||
<slot></slot> |
|||
</view> |
|||
<view class="{{ classes.ft }}"> |
|||
<block wx:if="{{ extra }}">{{ extra }}</block> |
|||
<block wx:else> |
|||
<slot name="footer"></slot> |
|||
</block> |
|||
</view> |
|||
</button> |
|||
@ -0,0 +1,98 @@ |
|||
.wux-cell { |
|||
margin: 0; |
|||
border-radius: 0; |
|||
color: inherit!important; |
|||
background: 0 0!important; |
|||
font-size: inherit; |
|||
font-weight: 400; |
|||
line-height: inherit; |
|||
text-align: inherit; |
|||
text-decoration: none; |
|||
overflow: visible; |
|||
min-height: 100rpx!important; |
|||
width: auto!important; |
|||
box-sizing: border-box; |
|||
-webkit-tap-highlight-color: transparent; |
|||
padding: 20rpx 30rpx; |
|||
position: relative; |
|||
display: -ms-flexbox; |
|||
display: flex; |
|||
-ms-flex-align: center; |
|||
align-items: center; |
|||
background: #fff |
|||
} |
|||
.wux-cell:after { |
|||
display: block; |
|||
position: static; |
|||
top: auto; |
|||
left: auto; |
|||
width: auto; |
|||
height: auto; |
|||
border: none; |
|||
border-radius: 0; |
|||
transform: none; |
|||
transform-origin: 0 0 |
|||
} |
|||
.wux-cell:after { |
|||
content: " "; |
|||
position: absolute; |
|||
bottom: 0; |
|||
right: 0; |
|||
height: 1rpx; |
|||
border-bottom: 1rpx solid #d9d9d9; |
|||
color: #d9d9d9; |
|||
transform-origin: 0 100%; |
|||
transform: scaleY(.5); |
|||
left: 30rpx |
|||
} |
|||
.wux-cell--last:after { |
|||
display: none |
|||
} |
|||
.wux-cell--hover { |
|||
background-color: #ececec!important |
|||
} |
|||
.wux-cell--disabled { |
|||
opacity: .3 |
|||
} |
|||
.wux-cell__thumb { |
|||
display: block; |
|||
width: 40rpx; |
|||
height: 40rpx; |
|||
margin-right: 10rpx |
|||
} |
|||
.wux-cell__bd { |
|||
-ms-flex: 1; |
|||
flex: 1 |
|||
} |
|||
.wux-cell__text { |
|||
text-align: left |
|||
} |
|||
.wux-cell__desc { |
|||
text-align: left; |
|||
line-height: 1.2; |
|||
font-size: 24rpx; |
|||
color: grey |
|||
} |
|||
.wux-cell__ft { |
|||
text-align: right; |
|||
color: grey |
|||
} |
|||
.wux-cell--access .wux-cell__ft { |
|||
padding-right: 26rpx; |
|||
position: relative |
|||
} |
|||
.wux-cell--access .wux-cell__ft:after { |
|||
content: " "; |
|||
display: inline-block; |
|||
height: 16rpx; |
|||
width: 16rpx; |
|||
border-width: 2rpx 2rpx 0 0; |
|||
border-color: #999999; |
|||
border-style: solid; |
|||
transform: matrix(.71,.71,-.71,.71,0,0); |
|||
top: -4rpx; |
|||
position: absolute; |
|||
top: 50%; |
|||
margin-top: -8rpx; |
|||
right: 4rpx |
|||
} |
|||
@ -0,0 +1,264 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import classNames from '../helpers/classNames' |
|||
|
|||
const defaults = { |
|||
prefixCls: 'wux-dialog', |
|||
title: '', |
|||
content: '', |
|||
buttons: [], |
|||
verticalButtons: !1, |
|||
resetOnClose: false, |
|||
closable: false, |
|||
mask: true, |
|||
maskClosable: true, |
|||
zIndex: 1000, |
|||
} |
|||
|
|||
const defaultOptions = { |
|||
onCancel() {}, |
|||
cancelText: '取消', |
|||
cancelType: 'default', |
|||
onConfirm() {}, |
|||
confirmText: '确定', |
|||
confirmType: 'primary', |
|||
} |
|||
|
|||
baseComponent({ |
|||
useFunc: true, |
|||
data: defaults, |
|||
computed: { |
|||
classes: ['prefixCls, buttons, verticalButtons', function(prefixCls, btns, verticalButtons) { |
|||
const prompt = `${prefixCls}__prompt` |
|||
const input = `${prefixCls}__input` |
|||
const buttons = classNames(`${prefixCls}__buttons`, { |
|||
[`${prefixCls}__buttons--${verticalButtons ? 'vertical' : 'horizontal'}`]: true, |
|||
}) |
|||
const button = btns.map((button) => { |
|||
const wrap = classNames(`${prefixCls}__button`, { |
|||
[`${prefixCls}__button--${button.type || 'default'}`]: button.type || 'default', |
|||
[`${prefixCls}__button--bold`]: button.bold, |
|||
[`${prefixCls}__button--disabled`]: button.disabled, |
|||
[`${button.className}`]: button.className, |
|||
}) |
|||
const hover = button.hoverClass && button.hoverClass !== 'default' ? button.hoverClass : `${prefixCls}__button--hover` |
|||
|
|||
return { |
|||
wrap, |
|||
hover, |
|||
} |
|||
}) |
|||
|
|||
return { |
|||
prompt, |
|||
input, |
|||
buttons, |
|||
button, |
|||
} |
|||
}], |
|||
}, |
|||
methods: { |
|||
/** |
|||
* 组件关闭时重置其内部数据 |
|||
*/ |
|||
onClosed() { |
|||
if (this.data.resetOnClose) { |
|||
const params = { |
|||
...this.$$mergeOptionsToData(defaults), |
|||
prompt: null, |
|||
} |
|||
|
|||
this.$$setData(params) |
|||
} |
|||
}, |
|||
/** |
|||
* 点击 x 或 mask 回调 |
|||
*/ |
|||
onClose() { |
|||
this.hide() |
|||
}, |
|||
/** |
|||
* 隐藏 |
|||
*/ |
|||
hide(cb) { |
|||
this.$$setData({ in: false }) |
|||
if (typeof cb === 'function') { |
|||
cb.call(this) |
|||
} |
|||
}, |
|||
/** |
|||
* 显示 |
|||
*/ |
|||
show(opts = {}) { |
|||
const options = this.$$mergeOptionsAndBindMethods(Object.assign({}, defaults, opts)) |
|||
this.$$setData({ in: true, ...options }) |
|||
this.originalButtons = options.buttons |
|||
return this.hide.bind(this) |
|||
}, |
|||
/** |
|||
* 触发事件 |
|||
*/ |
|||
runCallbacks(e, method) { |
|||
const { index } = e.currentTarget.dataset |
|||
const button = this.originalButtons[index] |
|||
|
|||
if (!button.disabled) { |
|||
this.hide(() => typeof button[method] === 'function' && button[method](e)) |
|||
} |
|||
}, |
|||
/** |
|||
* 按钮点击事件 |
|||
*/ |
|||
buttonTapped(e) { |
|||
this.runCallbacks(e, 'onTap') |
|||
}, |
|||
/** |
|||
* 用户点击该按钮时,会返回获取到的用户信息,回调的detail数据与wx.getUserInfo返回的一致,open-type="getUserInfo"时有效 |
|||
*/ |
|||
bindgetuserinfo(e) { |
|||
this.runCallbacks(e, 'onGetUserInfo') |
|||
}, |
|||
/** |
|||
* 客服消息回调,open-type="contact"时有效 |
|||
*/ |
|||
bindcontact(e) { |
|||
this.runCallbacks(e, 'onContact') |
|||
}, |
|||
/** |
|||
* 获取用户手机号回调,open-type=getPhoneNumber时有效 |
|||
*/ |
|||
bindgetphonenumber(e) { |
|||
this.runCallbacks(e, 'onGotPhoneNumber') |
|||
}, |
|||
/** |
|||
* 在打开授权设置页后回调,open-type=openSetting时有效 |
|||
*/ |
|||
bindopensetting(e) { |
|||
this.runCallbacks(e, 'onOpenSetting') |
|||
}, |
|||
/** |
|||
* 当使用开放能力时,发生错误的回调,open-type=launchApp时有效 |
|||
*/ |
|||
onError(e) { |
|||
this.runCallbacks(e, 'onError') |
|||
}, |
|||
/** |
|||
* 当键盘输入时,触发 input 事件 |
|||
*/ |
|||
bindinput(e) { |
|||
this.$$setData({ |
|||
'prompt.response': e.detail.value, |
|||
}) |
|||
}, |
|||
/** |
|||
* 显示dialog组件 |
|||
* @param {Object} opts 配置项 |
|||
* @param {String} opts.title 提示标题 |
|||
* @param {String} opts.content 提示文本 |
|||
* @param {Boolean} opts.verticalButtons 是否显示垂直按钮布局 |
|||
* @param {Array} opts.buttons 按钮 |
|||
* @param {String} opts.buttons.text 按钮的文字 |
|||
* @param {String} opts.buttons.type 按钮的类型 |
|||
* @param {Boolean} opts.buttons.bold 是否加粗按钮的文字 |
|||
* @param {Function} opts.buttons.onTap 按钮的点击事件 |
|||
*/ |
|||
open(opts = {}) { |
|||
return this.show(opts) |
|||
}, |
|||
/** |
|||
* 显示dialog组件 |
|||
* @param {Object} opts 配置项 |
|||
* @param {String} opts.title 提示标题 |
|||
* @param {String} opts.content 提示文本 |
|||
* @param {String} opts.confirmText 确定按钮的文字,默认为"确定" |
|||
* @param {String} opts.confirmType 确定按钮的类型 |
|||
* @param {Function} opts.onConfirm 确定按钮的点击事件 |
|||
*/ |
|||
alert(opts = {}) { |
|||
return this.open(Object.assign({ |
|||
buttons: [{ |
|||
text: opts.confirmText || defaultOptions.confirmText, |
|||
type: opts.confirmType || defaultOptions.confirmType, |
|||
onTap: (e) => { |
|||
typeof opts.onConfirm === 'function' && opts.onConfirm(e) |
|||
}, |
|||
}, ], |
|||
}, opts)) |
|||
}, |
|||
/** |
|||
* 显示dialog组件 |
|||
* @param {Object} opts 配置项 |
|||
* @param {String} opts.title 提示标题 |
|||
* @param {String} opts.content 提示文本 |
|||
* @param {String} opts.confirmText 确定按钮的文字,默认为"确定" |
|||
* @param {String} opts.confirmType 确定按钮的类型 |
|||
* @param {Function} opts.onConfirm 确定按钮的点击事件 |
|||
* @param {String} opts.cancelText 取消按钮的文字,默认为"取消" |
|||
* @param {String} opts.cancelType 取消按钮的类型 |
|||
* @param {Function} opts.onCancel 取消按钮的点击事件 |
|||
*/ |
|||
confirm(opts = {}) { |
|||
return this.open(Object.assign({ |
|||
buttons: [{ |
|||
text: opts.cancelText || defaultOptions.cancelText, |
|||
type: opts.cancelType || defaultOptions.cancelType, |
|||
onTap: (e) => { |
|||
typeof opts.onCancel === 'function' && opts.onCancel(e) |
|||
}, |
|||
}, |
|||
{ |
|||
text: opts.confirmText || defaultOptions.confirmText, |
|||
type: opts.confirmType || defaultOptions.confirmType, |
|||
onTap: (e) => { |
|||
typeof opts.onConfirm === 'function' && opts.onConfirm(e) |
|||
}, |
|||
}, |
|||
], |
|||
}, opts)) |
|||
}, |
|||
/** |
|||
* 显示dialog组件 |
|||
* @param {Object} opts 配置项 |
|||
* @param {String} opts.title 提示标题 |
|||
* @param {String} opts.content 提示文本 |
|||
* @param {String} opts.fieldtype input 的类型,有效值:text, number, idcard, digit |
|||
* @param {Boolean} opts.password 是否是密码类型 |
|||
* @param {String} opts.defaultText 默认值 |
|||
* @param {String} opts.placeholder 输入框为空时占位符 |
|||
* @param {Number} opts.maxlength 最大输入长度,设置为 -1 的时候不限制最大长度 |
|||
* @param {String} opts.confirmText 确定按钮的文字,默认为"确定" |
|||
* @param {String} opts.confirmType 确定按钮的类型 |
|||
* @param {Function} opts.onConfirm 确定按钮的点击事件 |
|||
* @param {String} opts.cancelText 取消按钮的文字,默认为"取消" |
|||
* @param {String} opts.cancelType 取消按钮的类型 |
|||
* @param {Function} opts.onCancel 取消按钮的点击事件 |
|||
*/ |
|||
prompt(opts = {}) { |
|||
const prompt = { |
|||
fieldtype: opts.fieldtype ? opts.fieldtype : 'text', |
|||
password: !!opts.password, |
|||
response: opts.defaultText ? opts.defaultText : '', |
|||
placeholder: opts.placeholder ? opts.placeholder : '', |
|||
maxlength: opts.maxlength ? parseInt(opts.maxlength) : '', |
|||
} |
|||
|
|||
return this.open(Object.assign({ |
|||
prompt: prompt, |
|||
buttons: [{ |
|||
text: opts.cancelText || defaultOptions.cancelText, |
|||
type: opts.cancelType || defaultOptions.cancelType, |
|||
onTap: (e) => { |
|||
typeof opts.onCancel === 'function' && opts.onCancel(e) |
|||
}, |
|||
}, |
|||
{ |
|||
text: opts.confirmText || defaultOptions.confirmText, |
|||
type: opts.confirmType || defaultOptions.confirmType, |
|||
onTap: (e) => { |
|||
typeof opts.onConfirm === 'function' && opts.onConfirm(e, this.data.prompt.response) |
|||
}, |
|||
}, |
|||
], |
|||
}, opts)) |
|||
}, |
|||
}, |
|||
}) |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"component": true, |
|||
"usingComponents": { |
|||
"wux-popup": "../popup/index" |
|||
} |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
<wux-popup |
|||
visible="{{ in }}" |
|||
z-index="{{ zIndex }}" |
|||
closable="{{ closable }}" |
|||
mask="{{ mask }}" |
|||
mask-closable="{{ maskClosable }}" |
|||
bind:close="onClose" |
|||
bind:closed="onClosed" |
|||
> |
|||
<view slot="header" class="text-xl">{{ title }}</view> |
|||
<view wx:if="{{ content || prompt }}"> |
|||
<text>{{ content }}</text> |
|||
<view class="{{ classes.prompt }}" wx:if="{{ prompt }}"> |
|||
<label> |
|||
<input |
|||
type="{{ prompt.fieldtype }}" |
|||
class="{{ classes.input }}" |
|||
value="{{ prompt.response }}" |
|||
password="{{ prompt.password }}" |
|||
placeholder="{{ prompt.placeholder }}" |
|||
maxlength="{{ maxlength }}" |
|||
bindinput="bindinput" |
|||
/> |
|||
</label> |
|||
</view> |
|||
</view> |
|||
<view slot="footer" class="{{ classes.buttons }}"> |
|||
<block wx:for="{{ buttons }}" wx:for-item="button" wx:key="index"> |
|||
<button |
|||
class="{{ classes.button[index].wrap }}" |
|||
disabled="{{ button.disabled }}" |
|||
open-type="{{ button.openType }}" |
|||
hover-class="{{ !button.disabled ? classes.button[index].hover : 'none' }}" |
|||
hover-stop-propagation="{{ button.hoverStopPropagation }}" |
|||
hover-start-time="{{ button.hoverStartTime || 20 }}" |
|||
hover-stay-time="{{ button.hoverStayTime || 70 }}" |
|||
lang="{{ button.lang || 'en' }}" |
|||
bindgetuserinfo="bindgetuserinfo" |
|||
session-from="{{ button.sessionFrom }}" |
|||
send-message-title="{{ button.sendMessageTitle }}" |
|||
send-message-path="{{ button.sendMessagePath }}" |
|||
send-message-img="{{ button.sendMessageImg }}" |
|||
show-message-card="{{ button.showMessageCard }}" |
|||
bindcontact="bindcontact" |
|||
bindgetphonenumber="bindgetphonenumber" |
|||
app-parameter="{{ button.appParameter }}" |
|||
binderror="onError" |
|||
bindopensetting="bindopensetting" |
|||
data-index="{{ index }}" |
|||
bindtap="buttonTapped" |
|||
> |
|||
{{ button.text }} |
|||
</button> |
|||
</block> |
|||
</view> |
|||
</wux-popup> |
|||
@ -0,0 +1,115 @@ |
|||
.wux-dialog__button { |
|||
padding: 0; |
|||
margin: 0; |
|||
border-radius: 0; |
|||
background: 0 0!important; |
|||
font-size: inherit; |
|||
font-weight: 400; |
|||
line-height: inherit; |
|||
text-align: inherit; |
|||
text-decoration: none; |
|||
overflow: visible; |
|||
min-height: 0!important; |
|||
width: auto!important; |
|||
box-sizing: border-box; |
|||
-webkit-tap-highlight-color: transparent; |
|||
display: block; |
|||
-ms-flex: 1; |
|||
flex: 1; |
|||
color: #33cd5f!important; |
|||
position: relative |
|||
} |
|||
.wux-dialog__button:after { |
|||
display: block; |
|||
position: static; |
|||
top: auto; |
|||
left: auto; |
|||
width: auto; |
|||
height: auto; |
|||
border: none; |
|||
border-radius: 0; |
|||
transform: none; |
|||
transform-origin: 0 0 |
|||
} |
|||
.wux-dialog__button--default { |
|||
color: #353535!important |
|||
} |
|||
.wux-dialog__button--primary { |
|||
color: #009ddf!important |
|||
} |
|||
.wux-dialog__button--bold { |
|||
font-weight: 500!important |
|||
} |
|||
.wux-dialog__button--hover { |
|||
background-color: #ececec!important |
|||
} |
|||
.wux-dialog__button--disabled { |
|||
opacity: .3 |
|||
} |
|||
.wux-dialog__prompt { |
|||
position: relative; |
|||
margin-top: 20rpx |
|||
} |
|||
.wux-dialog__prompt:after { |
|||
content: " "; |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
width: 200%; |
|||
height: 200%; |
|||
transform: scale(.5); |
|||
transform-origin: 0 0; |
|||
pointer-events: none; |
|||
box-sizing: border-box; |
|||
border: 0 solid #d5d5d6; |
|||
border-top-width: 2rpx; |
|||
border-right-width: 2rpx; |
|||
border-bottom-width: 2rpx; |
|||
border-left-width: 2rpx; |
|||
border-radius: 12rpx |
|||
} |
|||
.wux-dialog__input { |
|||
padding: 8rpx 12rpx; |
|||
height: 72rpx; |
|||
line-height: 1; |
|||
width: 100%; |
|||
text-align: left; |
|||
box-sizing: border-box |
|||
} |
|||
.wux-dialog__buttons { |
|||
display: -ms-flexbox; |
|||
display: flex; |
|||
-ms-flex: 1; |
|||
flex: 1 |
|||
} |
|||
.wux-dialog__buttons--horizontal .wux-dialog__button:after { |
|||
content: " "; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
width: 2rpx; |
|||
bottom: 0; |
|||
border-left: 2rpx solid #d5d5d6; |
|||
color: #d5d5d6; |
|||
transform-origin: 0 0; |
|||
transform: scaleX(.5) |
|||
} |
|||
.wux-dialog__buttons--horizontal .wux-dialog__button:first-child:after { |
|||
display: none |
|||
} |
|||
.wux-dialog__buttons--vertical { |
|||
display: block; |
|||
height: auto |
|||
} |
|||
.wux-dialog__buttons--vertical .wux-dialog__button:after { |
|||
content: " "; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
right: 0; |
|||
height: 2rpx; |
|||
border-top: 2rpx solid #d5d5d6; |
|||
color: #d5d5d6; |
|||
transform-origin: 0 0; |
|||
transform: scaleY(.5) |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import classNames from '../helpers/classNames' |
|||
|
|||
baseComponent({ |
|||
properties: { |
|||
prefixCls: { |
|||
type: String, |
|||
value: 'wux-divider', |
|||
}, |
|||
position: { |
|||
type: String, |
|||
value: 'center', |
|||
}, |
|||
dashed: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
text: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
showText: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
}, |
|||
computed: { |
|||
classes: ['prefixCls, dashed, showText, position', function(prefixCls, dashed, showText, position) { |
|||
const wrap = classNames(prefixCls, { |
|||
[`${prefixCls}--dashed`]: dashed, |
|||
[`${prefixCls}--text`]: showText, |
|||
[`${prefixCls}--text-${position}`]: showText && position, |
|||
}) |
|||
const text = `${prefixCls}__text` |
|||
|
|||
return { |
|||
wrap, |
|||
text, |
|||
} |
|||
}], |
|||
}, |
|||
}) |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"component": true |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
<view class="wux-class {{ classes.wrap }}"> |
|||
<view class="{{ classes.text }}" wx:if="{{ showText }}"> |
|||
{{ text }} |
|||
<slot></slot> |
|||
</view> |
|||
</view> |
|||
@ -0,0 +1,53 @@ |
|||
.wux-divider { |
|||
display: block; |
|||
height: 2rpx; |
|||
width: 100%; |
|||
margin: 30rpx 0; |
|||
clear: both; |
|||
border-top: 2rpx solid #e8e8e8 |
|||
} |
|||
.wux-divider--text { |
|||
display: table; |
|||
white-space: nowrap; |
|||
text-align: center; |
|||
background: 0 0; |
|||
font-weight: 500; |
|||
color: rgba(0,0,0,.85); |
|||
font-size: 32rpx; |
|||
border-top: none!important |
|||
} |
|||
.wux-divider--text:after, |
|||
.wux-divider--text:before { |
|||
content: ''; |
|||
display: table-cell; |
|||
position: relative; |
|||
top: 50%; |
|||
width: 50%; |
|||
border-top-width: 2rpx; |
|||
border-top-style: solid; |
|||
border-top-color: #e8e8e8; |
|||
transform: translateY(50%) |
|||
} |
|||
.wux-divider--dashed { |
|||
border-top: 2rpx dashed #e8e8e8 |
|||
} |
|||
.wux-divider--dashed.wux-divider--text:after, |
|||
.wux-divider--dashed.wux-divider--text:before { |
|||
border-top-style: dashed |
|||
} |
|||
.wux-divider--text-left:before { |
|||
width: 5% |
|||
} |
|||
.wux-divider--text-left:after { |
|||
width: 95% |
|||
} |
|||
.wux-divider--text-right:before { |
|||
width: 95% |
|||
} |
|||
.wux-divider--text-right:after { |
|||
width: 5% |
|||
} |
|||
.wux-divider__text { |
|||
display: inline-block; |
|||
padding: 0 30rpx |
|||
} |
|||
@ -0,0 +1 @@ |
|||
"use strict";function arrayTreeFilter(e,r,t){(t=t||{}).childrenKeyName=t.childrenKeyName||"children";var a=e||[],l=[],i=0;do{var d=a.filter(function(e){return r(e,i)})[0];if(!d)break;l.push(d),a=d[t.childrenKeyName]||[],i+=1}while(0<a.length);return l}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _default=arrayTreeFilter;exports.default=_default; |
|||
@ -0,0 +1 @@ |
|||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _computedBehavior=_interopRequireDefault(require("./computedBehavior")),_relationsBehavior=_interopRequireDefault(require("./relationsBehavior")),_safeAreaBehavior=_interopRequireDefault(require("./safeAreaBehavior")),_safeSetDataBehavior=_interopRequireDefault(require("./safeSetDataBehavior")),_funcBehavior=_interopRequireDefault(require("./funcBehavior")),_compareVersion=_interopRequireDefault(require("./compareVersion"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function ownKeys(r,e){var t=Object.keys(r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(r);e&&(o=o.filter(function(e){return Object.getOwnPropertyDescriptor(r,e).enumerable})),t.push.apply(t,o)}return t}function _objectSpread(r){for(var e=1;e<arguments.length;e++){var t=null!=arguments[e]?arguments[e]:{};e%2?ownKeys(t,!0).forEach(function(e){_defineProperty(r,e,t[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(t)):ownKeys(t).forEach(function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(t,e))})}return r}function _defineProperty(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function _toConsumableArray(e){return _arrayWithoutHoles(e)||_iterableToArray(e)||_nonIterableSpread()}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function _iterableToArray(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}function _arrayWithoutHoles(e){if(Array.isArray(e)){for(var r=0,t=new Array(e.length);r<e.length;r++)t[r]=e[r];return t}}var _wx$getSystemInfoSync=wx.getSystemInfoSync(),platform=_wx$getSystemInfoSync.platform,SDKVersion=_wx$getSystemInfoSync.SDKVersion,libVersion="2.6.6";"devtools"===platform&&(0,_compareVersion.default)(SDKVersion,libVersion)<0&&wx&&wx.showModal&&wx.showModal({title:"提示",content:"当前基础库版本(".concat(SDKVersion,")过低,无法使用 Wux Weapp 组件库,请更新基础库版本 >=").concat(libVersion," 后重试。")});var baseComponent=function(e){var r=0<arguments.length&&void 0!==e?e:{};return r.externalClasses=["wux-class","wux-hover-class"].concat(_toConsumableArray(r.externalClasses=r.externalClasses||[])),r.behaviors=[_relationsBehavior.default,_safeSetDataBehavior.default].concat(_toConsumableArray(r.behaviors=r.behaviors||[]),[_computedBehavior.default]),r.useSafeArea&&(r.behaviors=[].concat(_toConsumableArray(r.behaviors),[_safeAreaBehavior.default]),delete r.useSafeArea),r.useFunc&&(r.behaviors=[].concat(_toConsumableArray(r.behaviors),[_funcBehavior.default]),delete r.useFunc),r.useField&&(r.behaviors=[].concat(_toConsumableArray(r.behaviors),["wx://form-field"]),delete r.useField),r.useExport&&(r.behaviors=[].concat(_toConsumableArray(r.behaviors),["wx://component-export"]),r.methods=_objectSpread({export:function(){return this}},r.methods),delete r.useExport),r.options=_objectSpread({multipleSlots:!0,addGlobalClass:!0},r.options),Component(r)},_default=baseComponent;exports.default=_default; |
|||
@ -0,0 +1 @@ |
|||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.checkIPhoneX=exports.safeAreaInset=exports.getSystemInfo=void 0;var systemInfo=null,getSystemInfo=function(e){if(!systemInfo||e)try{systemInfo=wx.getSystemInfoSync()}catch(e){}return systemInfo};exports.getSystemInfo=getSystemInfo;var safeAreaInset={top:88,left:0,right:0,bottom:34};exports.safeAreaInset=safeAreaInset;var isIPhoneX=function(e){var t=e.model,o=e.platform;return/iPhone X/.test(t)&&"ios"===o},checkIPhoneX=function(e){return isIPhoneX(getSystemInfo(e))};exports.checkIPhoneX=checkIPhoneX; |
|||
@ -0,0 +1 @@ |
|||
"use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var hasOwn={}.hasOwnProperty;function classNames(){for(var e=[],t=0;t<arguments.length;t++){var o=arguments[t];if(o){var r=_typeof(o);if("string"===r||"number"===r)e.push(o);else if(Array.isArray(o)&&o.length){var n=classNames.apply(null,o);n&&e.push(n)}else if("object"===r)for(var s in o)hasOwn.call(o,s)&&o[s]&&e.push(s)}}return e.join(" ")}var _default=classNames;exports.default=_default; |
|||
@ -0,0 +1 @@ |
|||
"use strict";function compareVersion(e,r){for(var t=e.split("."),a=r.split("."),n=Math.max(t.length,a.length);t.length<n;)t.push("0");for(;a.length<n;)a.push("0");for(var o=0;o<n;o++){var s=parseInt(t[o]),u=parseInt(a[o]);if(u<s)return 1;if(s<u)return-1}return 0}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _default=compareVersion;exports.default=_default; |
|||
@ -0,0 +1 @@ |
|||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _isEmpty=_interopRequireDefault(require("./isEmpty")),_shallowEqual=_interopRequireDefault(require("./shallowEqual"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _toConsumableArray(e){return _arrayWithoutHoles(e)||_iterableToArray(e)||_nonIterableSpread()}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function _iterableToArray(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}function _arrayWithoutHoles(e){if(Array.isArray(e)){for(var r=0,t=new Array(e.length);r<e.length;r++)t[r]=e[r];return t}}function ownKeys(r,e){var t=Object.keys(r);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(r);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(r,e).enumerable})),t.push.apply(t,n)}return t}function _objectSpread(r){for(var e=1;e<arguments.length;e++){var t=null!=arguments[e]?arguments[e]:{};e%2?ownKeys(t,!0).forEach(function(e){_defineProperty(r,e,t[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(t)):ownKeys(t).forEach(function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(t,e))})}return r}function _defineProperty(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function _slicedToArray(e,r){return _arrayWithHoles(e)||_iterableToArrayLimit(e,r)||_nonIterableRest()}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}function _iterableToArrayLimit(e,r){var t=[],n=!0,o=!1,i=void 0;try{for(var a,u=e[Symbol.iterator]();!(n=(a=u.next()).done)&&(t.push(a.value),!r||t.length!==r);n=!0);}catch(e){o=!0,i=e}finally{try{n||null==u.return||u.return()}finally{if(o)throw i}}return t}function _arrayWithHoles(e){if(Array.isArray(e))return e}var ALL_DATA_KEY="**",trim=function(e){return(0<arguments.length&&void 0!==e?e:"").replace(/\s/g,"")},_default=Behavior({lifetimes:{attached:function(){this.initComputed()}},definitionFilter:function(e){var r=e.computed,n=void 0===r?{}:r,a=Object.keys(n).reduce(function(e,i){var r=_slicedToArray(Array.isArray(n[i])?n[i]:[ALL_DATA_KEY,n[i]],2),t=r[0],a=r[1];return _objectSpread({},e,_defineProperty({},t,function(){if("function"==typeof a){for(var e=arguments.length,r=new Array(e),t=0;t<e;t++)r[t]=arguments[t];var n=a.apply(this,r),o=this.data[i];(0,_isEmpty.default)(n)||(0,_shallowEqual.default)(n,o)||this.setData(_defineProperty({},i,n))}}))},{});Object.assign(e.observers=e.observers||{},a),Object.assign(e.methods=e.methods||{},{initComputed:function(e,r){var t=0<arguments.length&&void 0!==e?e:{},n=1<arguments.length&&void 0!==r&&r;if(!this.runInitComputed||n){this.runInitComputed=!1;var o=this,i=_objectSpread({},this.data,{},t);Object.keys(a).forEach(function(e){var r=trim(e).split(",").reduce(function(e,r){return[].concat(_toConsumableArray(e),[i[r]])},[]);a[e].apply(o,r)}),this.runInitComputed=!0}}})}});exports.default=_default; |
|||
@ -0,0 +1 @@ |
|||
"use strict";function debounce(t,o,i){var n,u,r,a,c;function d(){var e=+new Date-a;e<o&&0<=e?n=setTimeout(d,o-e):(n=void 0,i||(c=t.apply(r,u),n||(u=r=void 0)))}function e(){r=this,u=arguments,a=+new Date;var e=i&&!n;return n=n||setTimeout(d,o),e&&(c=t.apply(r,u),u=r=void 0),c}return e.cancel=function(){void 0!==n&&(clearTimeout(n),n=void 0),u=r=void 0},e}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=debounce; |
|||
@ -0,0 +1 @@ |
|||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=eventsMixin;var defaultEvents={onChange:function(){}};function eventsMixin(){return Behavior({lifetimes:{created:function(){this._oriTriggerEvent=this.triggerEvent,this.triggerEvent=this._triggerEvent}},properties:{events:{type:Object,value:defaultEvents}},data:{inputEvents:defaultEvents},definitionFilter:function(t){Object.assign(t.data=t.data||{},{inputEvents:Object.assign({},defaultEvents,t.inputEvents)}),Object.assign(t.methods=t.methods||{},{_triggerEvent:function(t,e,n,i){var s=!(2<arguments.length&&void 0!==n)||n,a=3<arguments.length?i:void 0,r=this.data.inputEvents["on".concat(t[0].toUpperCase()).concat(t.slice(1))];s&&"function"==typeof r&&r.call(this,e),this._oriTriggerEvent(t,e,a)}}),Object.assign(t.observers=t.observers||{},{events:function(t){this.setData({inputEvents:Object.assign({},defaultEvents,this.data.inputEvents,t)})}})}})} |
|||
@ -0,0 +1 @@ |
|||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var mergeOptionsToData=function(t){var e=0<arguments.length&&void 0!==t?t:{},n=Object.assign({},e);for(var r in n)n.hasOwnProperty(r)&&"function"==typeof n[r]&&delete n[r];return n},bind=function(r,i){return function(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];return e.length?r.apply(i,e):r.call(i)}},assign=function(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];return Object.assign.apply(Object,[{}].concat(e))},_default=Behavior({definitionFilter:function(t){t.data=mergeOptionsToData(t.data),t.data.in=!1,t.data.visible=!1},methods:{$$mergeOptionsToData:mergeOptionsToData,$$mergeOptionsAndBindMethods:function(t,e){var n=0<arguments.length&&void 0!==t?t:{},r=1<arguments.length&&void 0!==e?e:this.fns,i=Object.assign({},n);for(var a in i)i.hasOwnProperty(a)&&"function"==typeof i[a]&&(r[a]=bind(i[a],this),delete i[a]);return i},$$setData:function(){for(var e=this,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];var i=assign.apply(void 0,[{}].concat(n));return new Promise(function(t){e.setData(i,t)})},$$requestAnimationFrame:function(t,e){var n=0<arguments.length&&void 0!==t?t:function(){},r=1<arguments.length&&void 0!==e?e:1e3/60;return new Promise(function(t){return setTimeout(t,r)}).then(n)}},created:function(){this.fns={}},detached:function(){this.fns={}}});exports.default=_default; |
|||
@ -0,0 +1 @@ |
|||
"use strict";function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function isEmpty(t){if(Array.isArray(t))return 0===t.length;if("object"!==_typeof(t))return!t;if(t)for(var e in t)return!1;return!0}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _default=isEmpty;exports.default=_default; |
|||
@ -0,0 +1 @@ |
|||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _isEmpty=_interopRequireDefault(require("./isEmpty")),_debounce2=_interopRequireDefault(require("./debounce"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function bindFunc(e,t,n){var i=e[t];e[t]=function(e){n&&n.call(this,e,_defineProperty({},t,!0)),i&&i.call(this,e)}}var methods=["linked","linkChanged","unlinked"],extProps=["observer"],_default=Behavior({lifetimes:{created:function(){this._debounce=null},detached:function(){this._debounce&&this._debounce.cancel&&this._debounce.cancel()}},definitionFilter:function(e){var n=e.relations;if(!(0,_isEmpty.default)(n)){var t=function(e){var t=n[e];methods.forEach(function(e){return bindFunc(t,e,t.observer)}),extProps.forEach(function(e){return delete t[e]})};for(var i in n)t(i)}Object.assign(e.methods=e.methods||{},{getRelationsName:function(e){var t=0<arguments.length&&void 0!==e?e:["parent","child","ancestor","descendant"];return Object.keys(n||{}).map(function(e){return n[e]&&t.includes(n[e].type)?e:null}).filter(function(e){return!!e})},debounce:function(e,t,n){var i=1<arguments.length&&void 0!==t?t:0,r=2<arguments.length&&void 0!==n&&n;return(this._debounce=this._debounce||(0,_debounce2.default)(e.bind(this),i,r)).call(this)}})}});exports.default=_default; |
|||
@ -0,0 +1 @@ |
|||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _checkIPhoneX=require("./checkIPhoneX");function _defineProperty(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var defaultSafeArea={top:!1,bottom:!1},setSafeArea=function(e){return"boolean"==typeof e?Object.assign({},defaultSafeArea,{top:e,bottom:e}):null!==e&&"object"===_typeof(e)?Object.assign({},defaultSafeArea):"string"==typeof e?Object.assign({},defaultSafeArea,_defineProperty({},e,!0)):defaultSafeArea},_default=Behavior({properties:{safeArea:{type:[Boolean,String,Object],value:!1}},observers:{safeArea:function(e){this.setData({safeAreaConfig:setSafeArea(e)})}},definitionFilter:function(e){var t=((0,_checkIPhoneX.getSystemInfo)()||{}).statusBarHeight,o=(0,_checkIPhoneX.checkIPhoneX)();Object.assign(e.data=e.data||{},{safeAreaConfig:defaultSafeArea,statusBarHeight:t,isIPhoneX:o})}});exports.default=_default; |
|||
@ -0,0 +1 @@ |
|||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _default=Behavior({lifetimes:{created:function(){this.nextCallback=null},detached:function(){this.cancelNextCallback()}},methods:{safeSetData:function(t,a){var e=this;this.pendingData=Object.assign({},this.data,t),a=this.setNextCallback(a),this.setData(t,function(){e.pendingData=null,a()})},setNextCallback:function(a){var e=this,l=!0;return this.nextCallback=function(t){l&&(l=!1,e.nextCallback=null,a.call(e,t))},this.nextCallback.cancel=function(){l=!1},this.nextCallback},cancelNextCallback:function(){null!==this.nextCallback&&(this.nextCallback.cancel(),this.nextCallback=null)}}});exports.default=_default; |
|||
@ -0,0 +1 @@ |
|||
"use strict";function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var hasOwnProperty=Object.prototype.hasOwnProperty;function is(t,e){return t===e?0!==t||0!==e||1/t==1/e:t!=t&&e!=e}function shallowEqual(t,e){if(is(t,e))return!0;if("object"!==_typeof(t)||null===t||"object"!==_typeof(e)||null===e)return!1;var o=Object.keys(t),r=Object.keys(e);if(o.length!==r.length)return!1;for(var n=0;n<o.length;n++)if(!hasOwnProperty.call(e,o[n])||!is(t[o[n]],e[o[n]]))return!1;return!0}var _default=shallowEqual;exports.default=_default; |
|||
@ -0,0 +1 @@ |
|||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var isUnitlessNumber={boxFlex:!(exports.default=void 0),boxFlexGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0};function prefixKey(e,t){return e+t.charAt(0).toUpperCase()+t.substring(1)}var prefixes=["Webkit","ms","Moz","O"];Object.keys(isUnitlessNumber).forEach(function(t){prefixes.forEach(function(e){isUnitlessNumber[prefixKey(e,t)]=isUnitlessNumber[t]})});var msPattern=/^ms-/,_uppercasePattern=/([A-Z])/g;function hyphenate(e){return e.replace(_uppercasePattern,"-$1").toLowerCase()}function hyphenateStyleName(e){return hyphenate(e).replace(msPattern,"-ms-")}var isArray=Array.isArray,keys=Object.keys,counter=1,unquotedContentValueRegex=/^(normal|none|(\b(url\([^)]*\)|chapter_counter|attr\([^)]*\)|(no-)?(open|close)-quote|inherit)((\b\s*)|$|\s+))+)$/;function buildRule(e,t){return isUnitlessNumber[e]||"number"!=typeof t?"content"!==e||unquotedContentValueRegex.test(t)||(t="'"+t.replace(/'/g,"\\'")+"'"):t+="px",hyphenateStyleName(e)+": "+t+"; "}function styleToCssString(e){var t="";if("string"==typeof e)return e;if(!e||0===keys(e).length)return t;for(var r=keys(e),n=0,s=r.length;n<s;n++){var o=r[n],i=e[o];if(isArray(i))for(var a=0,u=i.length;a<u;a++)t+=buildRule(o,i[a]);else t+=buildRule(o,i)}return t}var _default=styleToCssString;exports.default=_default; |
|||
@ -0,0 +1,47 @@ |
|||
Component({ |
|||
externalClasses: ['wux-class'], |
|||
properties: { |
|||
type: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
size: { |
|||
type: [String, Number], |
|||
value: 32, |
|||
observer: 'updated', |
|||
}, |
|||
color: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
hidden: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
}, |
|||
data: { |
|||
fontSize: '', |
|||
}, |
|||
methods: { |
|||
updated(size = this.data.size) { |
|||
let fontSize = size |
|||
|
|||
if (typeof size === 'number') { |
|||
fontSize = `${size}px` |
|||
} else if (typeof size === 'string') { |
|||
if (!isNaN(Number(size))) { |
|||
fontSize = `${size}px` |
|||
} |
|||
} |
|||
|
|||
if (this.data.fontSize !== fontSize) { |
|||
this.setData({ |
|||
fontSize, |
|||
}) |
|||
} |
|||
}, |
|||
}, |
|||
attached() { |
|||
this.updated() |
|||
}, |
|||
}) |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"component": true |
|||
} |
|||
@ -0,0 +1 @@ |
|||
<view class="wux-class ion {{ type ? 'ion-' + type : '' }}" style="font-size: {{ fontSize }}; {{ color ? 'color: ' + color : '' }}" hidden="{{ hidden }}"></view> |
|||
2820
components/icon/index.wxss
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,153 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import classNames from '../helpers/classNames' |
|||
|
|||
const EMPTY = 'empty' |
|||
const LOADING = 'loading' |
|||
const LOADED = 'loaded' |
|||
const ERROR = 'error' |
|||
const UNMOUNTED = 'unmounted' |
|||
|
|||
const calcStyle = (value) => typeof value === 'number' ? `${value}px` : value |
|||
|
|||
baseComponent({ |
|||
properties: { |
|||
prefixCls: { |
|||
type: String, |
|||
value: 'wux-image', |
|||
}, |
|||
src: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
mode: { |
|||
type: String, |
|||
value: 'aspectFill', |
|||
}, |
|||
lazyLoad: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
shape: { |
|||
type: String, |
|||
value: 'normal', |
|||
}, |
|||
width: { |
|||
type: null, |
|||
value: 300, |
|||
}, |
|||
height: { |
|||
type: null, |
|||
value: 225, |
|||
}, |
|||
unmountOnEmpty: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
unmountOnError: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
empty: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
loading: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
error: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
}, |
|||
data: { |
|||
status: '', |
|||
}, |
|||
computed: { |
|||
classes: ['prefixCls, shape, mode, status, empty, loading, error', function(prefixCls, shape, mode, status, empty, loading, error) { |
|||
const wrap = classNames(prefixCls, { |
|||
[`${prefixCls}--${shape}`]: shape, |
|||
[`${prefixCls}--${mode}`]: mode, |
|||
[`${prefixCls}--${status}`]: status, |
|||
}) |
|||
const inner = `${prefixCls}__inner` |
|||
const thumb = `${prefixCls}__thumb` |
|||
const mask = classNames(`${prefixCls}__mask`, { |
|||
[`${prefixCls}__mask--text`]: empty || loading || error, |
|||
}) |
|||
const text = `${prefixCls}__text` |
|||
|
|||
return { |
|||
wrap, |
|||
inner, |
|||
thumb, |
|||
mask, |
|||
text, |
|||
} |
|||
}], |
|||
}, |
|||
observers: { |
|||
src(newVal) { |
|||
this.updated(newVal) |
|||
}, |
|||
['width, height'](...args) { |
|||
this.updateStyle(...args) |
|||
}, |
|||
}, |
|||
methods: { |
|||
/** |
|||
* 更新资源地址 |
|||
*/ |
|||
updated(src) { |
|||
this.updateStatus(!!src ? LOADING : this.data.unmountOnEmpty ? UNMOUNTED : EMPTY) |
|||
}, |
|||
/** |
|||
* 更新组件样式 |
|||
*/ |
|||
updateStyle(width, height) { |
|||
const style = `width: ${calcStyle(width)}; height: ${calcStyle(height)}` |
|||
|
|||
this.setData({ |
|||
style, |
|||
}) |
|||
}, |
|||
/** |
|||
* 更新组件状态 |
|||
*/ |
|||
updateStatus(status) { |
|||
if (this.data.status !== status) { |
|||
this.setData({ |
|||
status, |
|||
}) |
|||
} |
|||
|
|||
this.triggerEvent('change', { status }) |
|||
}, |
|||
/** |
|||
* 资源加载完成时的回调函数 |
|||
*/ |
|||
onLoad(e) { |
|||
this.updateStatus(LOADED) |
|||
this.triggerEvent('load', { ...e.detail, status: LOADED }) |
|||
}, |
|||
/** |
|||
* 资源加载失败时的回调函数 |
|||
*/ |
|||
onError(e) { |
|||
const status = this.data.unmountOnError ? UNMOUNTED : ERROR |
|||
this.updateStatus(status) |
|||
this.triggerEvent('error', { ...e.detail, status }) |
|||
}, |
|||
/** |
|||
* 点击事件 |
|||
*/ |
|||
onTap(e) { |
|||
this.triggerEvent('click', { ...e.detail, status: this.data.status }) |
|||
}, |
|||
}, |
|||
attached() { |
|||
const { width, height, src } = this.data |
|||
this.updateStyle(width, height) |
|||
this.updated(src) |
|||
}, |
|||
}) |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"component": true |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
<view class="wux-class {{ classes.wrap }}" style="{{ style }}" bindtap="onTap" wx:if="{{ status !== 'unmounted' }}"> |
|||
<view class="{{ classes.inner }}"> |
|||
<image class="{{ classes.thumb }}" lazy-load="{{ lazyLoad }}" mode="{{ mode }}" src="{{ src }}" bindload="onLoad" binderror="onError" wx:if="{{ src }}" /> |
|||
<slot></slot> |
|||
</view> |
|||
<view class="{{ classes.mask }}" wx:if="{{ status === 'empty' }}"> |
|||
<view class="{{ classes.text }}" wx:if="{{ empty }}">{{ empty }}</view> |
|||
<block wx:else> |
|||
<slot name="empty"></slot> |
|||
</block> |
|||
</view> |
|||
<view class="{{ classes.mask }}" wx:elif="{{ status === 'loading' }}"> |
|||
<view class="{{ classes.text }}" wx:if="{{ loading }}">{{ loading }}</view> |
|||
<block wx:else> |
|||
<slot name="loading"></slot> |
|||
</block> |
|||
</view> |
|||
<view class="{{ classes.mask }}" wx:elif="{{ status === 'error' }}"> |
|||
<view class="{{ classes.text }}" wx:if="{{ error }}">{{ error }}</view> |
|||
<block wx:else> |
|||
<slot name="error"></slot> |
|||
</block> |
|||
</view> |
|||
</view> |
|||
@ -0,0 +1,87 @@ |
|||
.wux-image { |
|||
position: relative; |
|||
overflow: hidden; |
|||
display: -ms-flexbox; |
|||
display: flex; |
|||
box-sizing: border-box |
|||
} |
|||
.wux-image--rounded { |
|||
border-radius: 8rpx |
|||
} |
|||
.wux-image--circle { |
|||
border-radius: 50% |
|||
} |
|||
.wux-image--thumbnail { |
|||
background-color: #fff; |
|||
border-radius: 8rpx |
|||
} |
|||
.wux-image--thumbnail:after { |
|||
content: " "; |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
width: 200%; |
|||
height: 200%; |
|||
transform: scale(.5); |
|||
transform-origin: 0 0; |
|||
pointer-events: none; |
|||
box-sizing: border-box; |
|||
border: 0 solid #d9d9d9; |
|||
border-width: 2rpx; |
|||
border-radius: 16rpx |
|||
} |
|||
.wux-image--thumbnail .wux-image__inner, |
|||
.wux-image--thumbnail .wux-image__mask { |
|||
top: 8rpx; |
|||
right: 8rpx; |
|||
bottom: 8rpx; |
|||
left: 8rpx; |
|||
width: calc(100% - 16rpx)!important; |
|||
height: calc(100% - 16rpx)!important |
|||
} |
|||
.wux-image--widthFix .wux-image__inner { |
|||
position: relative |
|||
} |
|||
.wux-image image, |
|||
.wux-image__thumb { |
|||
display: inline-block; |
|||
overflow: hidden; |
|||
width: 100%; |
|||
height: 100%; |
|||
vertical-align: middle |
|||
} |
|||
.wux-image__inner { |
|||
position: absolute; |
|||
top: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
left: 0; |
|||
z-index: 10; |
|||
width: 100%; |
|||
height: 100%; |
|||
opacity: 0 |
|||
} |
|||
.wux-image--loaded .wux-image__inner { |
|||
opacity: 1 |
|||
} |
|||
.wux-image__mask { |
|||
position: absolute; |
|||
top: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
left: 0; |
|||
z-index: 20 |
|||
} |
|||
.wux-image__mask--text { |
|||
display: -ms-flexbox; |
|||
display: flex; |
|||
-ms-flex-align: center; |
|||
align-items: center; |
|||
-ms-flex-pack: center; |
|||
justify-content: center |
|||
} |
|||
.wux-image__text { |
|||
color: #373a3c; |
|||
text-align: center; |
|||
padding: 20rpx |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
/** |
|||
* 使用选择器选择组件实例节点,返回匹配到的第一个组件实例对象 |
|||
* @param {String} selector 节点选择器 |
|||
* @param {Object} ctx 页面栈或组件的实例,默认为当前页面栈实例 |
|||
*/ |
|||
const getCtx = (selector, ctx = getCurrentPages()[getCurrentPages().length - 1]) => { |
|||
const componentCtx = ctx.selectComponent(selector) |
|||
if (!componentCtx) { |
|||
throw new Error('无法找到对应的组件,请按文档说明使用组件') |
|||
} |
|||
return componentCtx |
|||
} |
|||
|
|||
const $wuxBackdrop = (selector = '#wux-backdrop', ctx) => getCtx(selector, ctx) |
|||
const $wuxDialog = (selector = '#wux-dialog', ctx) => getCtx(selector, ctx) |
|||
|
|||
export { |
|||
$wuxBackdrop, |
|||
$wuxDialog |
|||
} |
|||
@ -0,0 +1,287 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import classNames from '../helpers/classNames' |
|||
import eventsMixin from '../helpers/eventsMixin' |
|||
import NP from './utils' |
|||
|
|||
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1 |
|||
|
|||
const toNumberWhenUserInput = (num) => { |
|||
if (/\.\d*0$/.test(num) || num.length > 16) { |
|||
return num |
|||
} |
|||
|
|||
if (isNaN(num)) { |
|||
return num |
|||
} |
|||
|
|||
return Number(num) |
|||
} |
|||
|
|||
const getValidValue = (value, min, max) => { |
|||
let val = parseFloat(value) |
|||
|
|||
if (isNaN(val)) { |
|||
return value |
|||
} |
|||
|
|||
if (val < min) { |
|||
val = min |
|||
} |
|||
|
|||
if (val > max) { |
|||
val = max |
|||
} |
|||
|
|||
return val |
|||
} |
|||
|
|||
const defaultEvents = { |
|||
onChange() {}, |
|||
onFocus() {}, |
|||
onBlur() {}, |
|||
} |
|||
|
|||
baseComponent({ |
|||
behaviors: [eventsMixin({ defaultEvents })], |
|||
externalClasses: ['wux-sub-class', 'wux-input-class', 'wux-add-class'], |
|||
relations: { |
|||
'../field/index': { |
|||
type: 'ancestor', |
|||
}, |
|||
}, |
|||
properties: { |
|||
prefixCls: { |
|||
type: String, |
|||
value: 'wux-input-number', |
|||
}, |
|||
shape: { |
|||
type: String, |
|||
value: 'square', |
|||
}, |
|||
min: { |
|||
type: Number, |
|||
value: -MAX_SAFE_INTEGER, |
|||
}, |
|||
max: { |
|||
type: Number, |
|||
value: MAX_SAFE_INTEGER, |
|||
}, |
|||
step: { |
|||
type: Number, |
|||
value: 1, |
|||
}, |
|||
defaultValue: { |
|||
type: Number, |
|||
value: 0, |
|||
}, |
|||
value: { |
|||
type: Number, |
|||
value: 0, |
|||
}, |
|||
disabled: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
longpress: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
color: { |
|||
type: String, |
|||
value: 'balanced', |
|||
}, |
|||
controlled: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
}, |
|||
data: { |
|||
inputValue: 0, |
|||
disabledMin: false, |
|||
disabledMax: false, |
|||
}, |
|||
computed: { |
|||
classes: ['prefixCls, shape, color, disabledMin, disabledMax', function(prefixCls, shape, color, disabledMin, disabledMax) { |
|||
const wrap = classNames(prefixCls, { |
|||
[`${prefixCls}--${shape}`]: shape, |
|||
}) |
|||
const sub = classNames(`${prefixCls}__selector`, { |
|||
[`${prefixCls}__selector--sub`]: true, |
|||
[`${prefixCls}__selector--${color}`]: color, |
|||
[`${prefixCls}__selector--disabled`]: disabledMin, |
|||
}) |
|||
const add = classNames(`${prefixCls}__selector`, { |
|||
[`${prefixCls}__selector--add`]: true, |
|||
[`${prefixCls}__selector--${color}`]: color, |
|||
[`${prefixCls}__selector--disabled`]: disabledMax, |
|||
}) |
|||
const icon = `${prefixCls}__icon` |
|||
const input = `${prefixCls}__input` |
|||
|
|||
return { |
|||
wrap, |
|||
sub, |
|||
add, |
|||
icon, |
|||
input, |
|||
} |
|||
}], |
|||
}, |
|||
observers: { |
|||
value(newVal) { |
|||
if (this.data.controlled) { |
|||
this.setValue(newVal, false) |
|||
} |
|||
}, |
|||
'inputValue, min, max'(inputValue, min, max) { |
|||
const disabledMin = inputValue <= min |
|||
const disabledMax = inputValue >= max |
|||
|
|||
this.setData({ |
|||
disabledMin, |
|||
disabledMax, |
|||
}) |
|||
}, |
|||
}, |
|||
methods: { |
|||
/** |
|||
* 更新值 |
|||
*/ |
|||
updated(inputValue) { |
|||
if (this.hasFieldDecorator) return |
|||
if (this.data.inputValue !== inputValue) { |
|||
this.setData({ inputValue }) |
|||
} |
|||
}, |
|||
/** |
|||
* 设置值 |
|||
*/ |
|||
setValue(value, runCallbacks = true) { |
|||
const { min, max } = this.data |
|||
const inputValue = NP.strip(getValidValue(value, min, max)) |
|||
|
|||
this.updated(inputValue) |
|||
|
|||
if (runCallbacks) { |
|||
this.triggerEvent('change', { value: inputValue }) |
|||
} |
|||
}, |
|||
/** |
|||
* 数字计算函数 |
|||
*/ |
|||
calculation(type, isLoop) { |
|||
const { |
|||
disabledMax, |
|||
disabledMin, |
|||
inputValue, |
|||
step, |
|||
longpress, |
|||
controlled, |
|||
} = this.data |
|||
|
|||
// add
|
|||
if (type === 'add') { |
|||
if (disabledMax) return |
|||
this.setValue(NP.plus(inputValue, step)) |
|||
} |
|||
|
|||
// sub
|
|||
if (type === 'sub') { |
|||
if (disabledMin) return |
|||
this.setValue(NP.minus(inputValue, step)) |
|||
} |
|||
|
|||
// longpress
|
|||
if (longpress && isLoop) { |
|||
this.timeout = setTimeout(() => this.calculation(type, isLoop), 100) |
|||
} |
|||
}, |
|||
/** |
|||
* 当键盘输入时,触发 input 事件 |
|||
*/ |
|||
onInput(e) { |
|||
this.clearInputTimer() |
|||
this.inputTime = setTimeout(() => { |
|||
const value = toNumberWhenUserInput(e.detail.value) |
|||
this.setValue(value) |
|||
}, 300) |
|||
}, |
|||
/** |
|||
* 输入框聚焦时触发 |
|||
*/ |
|||
onFocus(e) { |
|||
this.triggerEvent('focus', e.detail) |
|||
}, |
|||
/** |
|||
* 输入框失去焦点时触发 |
|||
*/ |
|||
onBlur(e) { |
|||
// always set input value same as value
|
|||
this.setData({ |
|||
inputValue: this.data.inputValue, |
|||
}) |
|||
|
|||
this.triggerEvent('blur', e.detail) |
|||
}, |
|||
/** |
|||
* 手指触摸后,超过350ms再离开 |
|||
*/ |
|||
onLongpress(e) { |
|||
const { type } = e.currentTarget.dataset |
|||
const { longpress } = this.data |
|||
if (longpress) { |
|||
this.calculation(type, true) |
|||
} |
|||
}, |
|||
/** |
|||
* 手指触摸后马上离开 |
|||
*/ |
|||
onTap(e) { |
|||
const { type } = e.currentTarget.dataset |
|||
const { longpress } = this.data |
|||
if (!longpress || longpress && !this.timeout) { |
|||
this.calculation(type, false) |
|||
} |
|||
}, |
|||
/** |
|||
* 手指触摸动作结束 |
|||
*/ |
|||
onTouchEnd() { |
|||
this.clearTimer() |
|||
}, |
|||
/** |
|||
* 手指触摸动作被打断,如来电提醒,弹窗 |
|||
*/ |
|||
onTouchCancel() { |
|||
this.clearTimer() |
|||
}, |
|||
/** |
|||
* 清除长按的定时器 |
|||
*/ |
|||
clearTimer() { |
|||
if (this.timeout) { |
|||
clearTimeout(this.timeout) |
|||
this.timeout = null |
|||
} |
|||
}, |
|||
/** |
|||
* 清除输入框的定时器 |
|||
*/ |
|||
clearInputTimer() { |
|||
if (this.inputTime) { |
|||
clearTimeout(this.inputTime) |
|||
this.inputTime = null |
|||
} |
|||
}, |
|||
}, |
|||
attached() { |
|||
const { defaultValue, value, controlled } = this.data |
|||
const inputValue = controlled ? value : defaultValue |
|||
|
|||
this.setValue(inputValue, false) |
|||
}, |
|||
detached() { |
|||
this.clearTimer() |
|||
this.clearInputTimer() |
|||
}, |
|||
}) |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"component": true, |
|||
"usingComponents": { |
|||
"wux-icon": "../icon/index" |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
<view class="wux-class {{ classes.wrap }}"> |
|||
<view bindlongpress="onLongpress" bindtap="onTap" bindtouchend="onTouchEnd" touchcancel="onTouchCancel" data-type="sub" class="wux-sub-class {{ classes.sub }}"> |
|||
<wux-icon wux-class="{{ classes.icon }}" type="ios-remove"></wux-icon> |
|||
</view> |
|||
<input bindinput="onInput" bindfocus="onFocus" bindblur="onBlur" value="{{ inputValue }}" disabled="{{ disabled }}" type="number" class="wux-input-class {{ classes.input }}" /> |
|||
<view bindlongpress="onLongpress" bindtap="onTap" bindtouchend="onTouchEnd" touchcancel="onTouchCancel" data-type="add" class="wux-add-class {{ classes.add }}"> |
|||
<wux-icon wux-class="{{ classes.icon }}" type="ios-add"></wux-icon> |
|||
</view> |
|||
</view> |
|||
@ -0,0 +1,118 @@ |
|||
.wux-input-number { |
|||
position: relative; |
|||
display: -ms-flexbox; |
|||
display: flex |
|||
} |
|||
.wux-input-number__input { |
|||
width: 96rpx; |
|||
height: 52rpx; |
|||
font-size: 32rpx; |
|||
line-height: 52rpx; |
|||
color: #666; |
|||
-webkit-appearance: none; |
|||
-moz-appearance: none; |
|||
appearance: none; |
|||
border: 2rpx solid #ececec; |
|||
padding: 6rpx 0; |
|||
text-align: center; |
|||
min-height: inherit; |
|||
box-sizing: border-box |
|||
} |
|||
.wux-input-number__selector { |
|||
width: 68rpx; |
|||
height: 52rpx; |
|||
font-size: 48rpx; |
|||
line-height: 52rpx; |
|||
color: #33cd5f; |
|||
border: 2rpx solid #ececec; |
|||
box-sizing: border-box; |
|||
display: -ms-flexbox; |
|||
display: flex; |
|||
-ms-flex-align: center; |
|||
align-items: center; |
|||
-ms-flex-pack: center; |
|||
justify-content: center |
|||
} |
|||
.wux-input-number__selector--disabled { |
|||
color: #ccc!important |
|||
} |
|||
.wux-input-number__selector--sub { |
|||
border-right: none; |
|||
padding: 6rpx 20rpx; |
|||
border-radius: 4rpx 0 0 4rpx |
|||
} |
|||
.wux-input-number__selector--add { |
|||
border-left: none; |
|||
padding: 6rpx 16rpx; |
|||
border-radius: 0 4rpx 4rpx 0 |
|||
} |
|||
.wux-input-number__icon { |
|||
font-size: inherit!important; |
|||
vertical-align: middle; |
|||
line-height: inherit |
|||
} |
|||
.wux-input-number--circle .wux-input-number__input { |
|||
border-color: transparent |
|||
} |
|||
.wux-input-number--circle .wux-input-number__selector { |
|||
width: 52rpx; |
|||
border-radius: 50%; |
|||
border: 2rpx solid #33cd5f |
|||
} |
|||
.wux-input-number--circle .wux-input-number__selector--disabled { |
|||
border-color: #ccc!important |
|||
} |
|||
.wux-input-number .wux-input-number__selector--light { |
|||
color: #ddd |
|||
} |
|||
.wux-input-number--circle .wux-input-number__selector--light { |
|||
border-color: #ddd |
|||
} |
|||
.wux-input-number .wux-input-number__selector--stable { |
|||
color: #b2b2b2 |
|||
} |
|||
.wux-input-number--circle .wux-input-number__selector--stable { |
|||
border-color: #b2b2b2 |
|||
} |
|||
.wux-input-number .wux-input-number__selector--positive { |
|||
color: #387ef5 |
|||
} |
|||
.wux-input-number--circle .wux-input-number__selector--positive { |
|||
border-color: #387ef5 |
|||
} |
|||
.wux-input-number .wux-input-number__selector--calm { |
|||
color: #11c1f3 |
|||
} |
|||
.wux-input-number--circle .wux-input-number__selector--calm { |
|||
border-color: #11c1f3 |
|||
} |
|||
.wux-input-number .wux-input-number__selector--assertive { |
|||
color: #ef473a |
|||
} |
|||
.wux-input-number--circle .wux-input-number__selector--assertive { |
|||
border-color: #ef473a |
|||
} |
|||
.wux-input-number .wux-input-number__selector--balanced { |
|||
color: #33cd5f |
|||
} |
|||
.wux-input-number--circle .wux-input-number__selector--balanced { |
|||
border-color: #33cd5f |
|||
} |
|||
.wux-input-number .wux-input-number__selector--energized { |
|||
color: #ffc900 |
|||
} |
|||
.wux-input-number--circle .wux-input-number__selector--energized { |
|||
border-color: #ffc900 |
|||
} |
|||
.wux-input-number .wux-input-number__selector--royal { |
|||
color: #886aea |
|||
} |
|||
.wux-input-number--circle .wux-input-number__selector--royal { |
|||
border-color: #886aea |
|||
} |
|||
.wux-input-number .wux-input-number__selector--dark { |
|||
color: #444 |
|||
} |
|||
.wux-input-number--circle .wux-input-number__selector--dark { |
|||
border-color: #444 |
|||
} |
|||
@ -0,0 +1,135 @@ |
|||
/** |
|||
* https://github.com/nefe/number-precision
|
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
Object.defineProperty(exports, '__esModule', { value: true }); |
|||
|
|||
/** |
|||
* @desc 解决浮动运算问题,避免小数点后产生多位数和计算精度损失。 |
|||
* 问题示例:2.3 + 2.4 = 4.699999999999999,1.0 - 0.9 = 0.09999999999999998 |
|||
*/ |
|||
/** |
|||
* 把错误的数据转正 |
|||
* strip(0.09999999999999998)=0.1 |
|||
*/ |
|||
function strip(num, precision) { |
|||
if (precision === void 0) { precision = 12; } |
|||
return +parseFloat(num.toPrecision(precision)); |
|||
} |
|||
/** |
|||
* Return digits length of a number |
|||
* @param {*number} num Input number |
|||
*/ |
|||
function digitLength(num) { |
|||
// Get digit length of e
|
|||
var eSplit = num.toString().split(/[eE]/); |
|||
var len = (eSplit[0].split('.')[1] || '').length - (+(eSplit[1] || 0)); |
|||
return len > 0 ? len : 0; |
|||
} |
|||
/** |
|||
* 把小数转成整数,支持科学计数法。如果是小数则放大成整数 |
|||
* @param {*number} num 输入数 |
|||
*/ |
|||
function float2Fixed(num) { |
|||
if (num.toString().indexOf('e') === -1) { |
|||
return Number(num.toString().replace('.', '')); |
|||
} |
|||
var dLen = digitLength(num); |
|||
return dLen > 0 ? strip(num * Math.pow(10, dLen)) : num; |
|||
} |
|||
/** |
|||
* 检测数字是否越界,如果越界给出提示 |
|||
* @param {*number} num 输入数 |
|||
*/ |
|||
function checkBoundary(num) { |
|||
if (_boundaryCheckingState) { |
|||
if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) { |
|||
console.warn(num + " is beyond boundary when transfer to integer, the results may not be accurate"); |
|||
} |
|||
} |
|||
} |
|||
/** |
|||
* 精确乘法 |
|||
*/ |
|||
function times(num1, num2) { |
|||
var others = []; |
|||
for (var _i = 2; _i < arguments.length; _i++) { |
|||
others[_i - 2] = arguments[_i]; |
|||
} |
|||
if (others.length > 0) { |
|||
return times.apply(void 0, [times(num1, num2), others[0]].concat(others.slice(1))); |
|||
} |
|||
var num1Changed = float2Fixed(num1); |
|||
var num2Changed = float2Fixed(num2); |
|||
var baseNum = digitLength(num1) + digitLength(num2); |
|||
var leftValue = num1Changed * num2Changed; |
|||
checkBoundary(leftValue); |
|||
return leftValue / Math.pow(10, baseNum); |
|||
} |
|||
/** |
|||
* 精确加法 |
|||
*/ |
|||
function plus(num1, num2) { |
|||
var others = []; |
|||
for (var _i = 2; _i < arguments.length; _i++) { |
|||
others[_i - 2] = arguments[_i]; |
|||
} |
|||
if (others.length > 0) { |
|||
return plus.apply(void 0, [plus(num1, num2), others[0]].concat(others.slice(1))); |
|||
} |
|||
var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2))); |
|||
return (times(num1, baseNum) + times(num2, baseNum)) / baseNum; |
|||
} |
|||
/** |
|||
* 精确减法 |
|||
*/ |
|||
function minus(num1, num2) { |
|||
var others = []; |
|||
for (var _i = 2; _i < arguments.length; _i++) { |
|||
others[_i - 2] = arguments[_i]; |
|||
} |
|||
if (others.length > 0) { |
|||
return minus.apply(void 0, [minus(num1, num2), others[0]].concat(others.slice(1))); |
|||
} |
|||
var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2))); |
|||
return (times(num1, baseNum) - times(num2, baseNum)) / baseNum; |
|||
} |
|||
/** |
|||
* 精确除法 |
|||
*/ |
|||
function divide(num1, num2) { |
|||
var others = []; |
|||
for (var _i = 2; _i < arguments.length; _i++) { |
|||
others[_i - 2] = arguments[_i]; |
|||
} |
|||
if (others.length > 0) { |
|||
return divide.apply(void 0, [divide(num1, num2), others[0]].concat(others.slice(1))); |
|||
} |
|||
var num1Changed = float2Fixed(num1); |
|||
var num2Changed = float2Fixed(num2); |
|||
checkBoundary(num1Changed); |
|||
checkBoundary(num2Changed); |
|||
return times((num1Changed / num2Changed), Math.pow(10, digitLength(num2) - digitLength(num1))); |
|||
} |
|||
/** |
|||
* 四舍五入 |
|||
*/ |
|||
function round(num, ratio) { |
|||
var base = Math.pow(10, ratio); |
|||
return divide(Math.round(times(num, base)), base); |
|||
} |
|||
var _boundaryCheckingState = true; |
|||
/** |
|||
* 是否进行边界检查,默认开启 |
|||
* @param flag 标记开关,true 为开启,false 为关闭,默认为 true |
|||
*/ |
|||
function enableBoundaryChecking(flag) { |
|||
if (flag === void 0) { flag = true; } |
|||
_boundaryCheckingState = flag; |
|||
} |
|||
|
|||
var index = { strip: strip, plus: plus, minus: minus, times: times, divide: divide, round: round, digitLength: digitLength, float2Fixed: float2Fixed, enableBoundaryChecking: enableBoundaryChecking }; |
|||
|
|||
export default index; |
|||
@ -0,0 +1,78 @@ |
|||
// components/password-box.js
|
|||
Component({ |
|||
/** |
|||
* 组件的属性列表 |
|||
*/ |
|||
properties: { |
|||
// 输入框的数量
|
|||
inputLength: { |
|||
type: Number, |
|||
value: 6 |
|||
}, |
|||
// 单个输入框的宽度
|
|||
inputWidth: { |
|||
type: String, |
|||
value: '100rpx' |
|||
}, |
|||
inputHeight: { |
|||
type: String, |
|||
value: '100rpx' |
|||
}, |
|||
// 是否显示输入的值,默认隐藏
|
|||
showValue: { |
|||
type: Boolean, |
|||
value: false |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* 组件的初始数据 |
|||
*/ |
|||
data: { |
|||
// input是否获取焦点
|
|||
inputFocus: false, |
|||
// 初始input值为空
|
|||
currentValue: '' |
|||
}, |
|||
|
|||
/** |
|||
* 组件的方法列表 |
|||
*/ |
|||
methods: { |
|||
// 设置当前的值
|
|||
_setCurrentValue(e) { |
|||
// 在此处判断满6(inputLength)位,把值返回给上级父组件或页面
|
|||
let currentValue = e.detail.value |
|||
// 改变时,派发一个事件,如果父组件或页面中需要实时获取改变后的值,可以监听这个事件。
|
|||
this.triggerEvent('change', e.detail.value) |
|||
|
|||
this.setData({ |
|||
currentValue |
|||
}) |
|||
if (currentValue.length >= this.data.inputLength) { |
|||
this._complate() |
|||
} |
|||
}, |
|||
// 点击伪装的input时,让隐藏的input获得焦点
|
|||
_focusInput() { |
|||
this.setData({ |
|||
inputFocus: true |
|||
}) |
|||
}, |
|||
_complate() { |
|||
this.triggerEvent('inputComplate', this.data.currentValue) |
|||
}, |
|||
// 提供给外部调用的方法,显示/隐藏密码。接收一个参数,可以显性修改展示的状态。
|
|||
toggleValue(state) { |
|||
this.setData({ |
|||
showValue: state != undefined ? state : !this.data.showValue |
|||
}) |
|||
}, |
|||
// 清除input当前的值
|
|||
clearCurrentValue() { |
|||
this.setData({ |
|||
currentValue: '' |
|||
}) |
|||
} |
|||
} |
|||
}) |
|||
@ -0,0 +1,4 @@ |
|||
{ |
|||
"component": true, |
|||
"usingComponents": {} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
<!--components/password-box.wxml--> |
|||
<view class="password-box"> |
|||
<view class='password-wrapper'> |
|||
<!-- 伪装的input --> |
|||
<block wx:for="{{inputLength}}" wx:key="item"> |
|||
<!-- 宽高可以由外部指定 --> |
|||
<view class="{{item===(inputLength-1)?'password-item-last':'password-item'}}" style="width: {{inputWidth}}; height: {{inputHeight}}" catchtap='_focusInput'> |
|||
<!-- 隐藏密码时显示的小圆点【自定义】 --> |
|||
<view wx:if="{{!showValue && currentValue.length>=index+1}}" class="hidden"></view> |
|||
<!-- 显示密码时显示对应的值 --> |
|||
<view wx:if="{{showValue}}" class="show">{{currentValue.length>=index+1?currentValue[index]:''}}</view> |
|||
</view> |
|||
</block> |
|||
</view> |
|||
<!-- 隐藏的输入框 --> |
|||
<input type="number" password="{{true}}" value="{{currentValue}}" class='hidden-input' maxlength="{{inputLength}}" focus="{{inputFocus}}" bindinput="_setCurrentValue"></input> |
|||
</view> |
|||
@ -0,0 +1,73 @@ |
|||
/* components/password-box.wxss */ |
|||
.password-box .password-wrapper { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
.password-box .password-item { |
|||
position: relative; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
.password-box .password-item::after { |
|||
display: block; |
|||
content: ''; |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
border-left: 2px solid #999; |
|||
border-top: 2px solid #999; |
|||
border-bottom: 2px solid #999; |
|||
border-spacing: 0; |
|||
box-sizing: border-box; |
|||
width: 200%; |
|||
height: 200%; |
|||
border-radius: 0rpx; |
|||
transform: scale(0.5); |
|||
transform-origin: left top; |
|||
} |
|||
|
|||
.password-box .password-item-last { |
|||
position: relative; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
.password-box .password-item-last::after { |
|||
display: block; |
|||
content: ''; |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
border-left: 2px solid #999; |
|||
border-top: 2px solid #999; |
|||
border-right: 2px solid #999; |
|||
border-bottom: 2px solid #999; |
|||
border-spacing: 0; |
|||
box-sizing: border-box; |
|||
width: 200%; |
|||
height: 200%; |
|||
border-radius: 0rpx; |
|||
transform: scale(0.5); |
|||
transform-origin: left top; |
|||
} |
|||
|
|||
.password-box .password-item + .password-item { |
|||
margin-left: -1rpx; |
|||
} |
|||
.password-box .password-wrapper .hidden { |
|||
width: 36rpx; |
|||
height: 36rpx; |
|||
border-radius: 50%; |
|||
background: #999; |
|||
} |
|||
.password-box .password-wrapper .show { |
|||
color: #333333; |
|||
font-size: 48rpx; |
|||
} |
|||
.password-box .hidden-input { |
|||
width: 0; |
|||
height: 0; |
|||
min-height: 0; |
|||
} |
|||
@ -0,0 +1,193 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import classNames from '../helpers/classNames' |
|||
import styleToCssString from '../helpers/styleToCssString' |
|||
import { $wuxBackdrop } from '../../utils/index' |
|||
|
|||
baseComponent({ |
|||
useSafeArea: true, |
|||
externalClasses: ['wux-content-class', 'wux-header-class', 'wux-body-class', 'wux-footer-class', 'wux-close-class'], |
|||
properties: { |
|||
prefixCls: { |
|||
type: String, |
|||
value: 'wux-popup', |
|||
}, |
|||
animationPrefixCls: { |
|||
type: String, |
|||
value: 'wux-animate', |
|||
}, |
|||
title: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
content: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
extra: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
position: { |
|||
type: String, |
|||
value: 'center', |
|||
observer: 'getTransitionName', |
|||
}, |
|||
wrapStyle: { |
|||
type: [String, Object], |
|||
value: '', |
|||
observer(newVal) { |
|||
this.setData({ |
|||
extStyle: styleToCssString(newVal), |
|||
}) |
|||
}, |
|||
}, |
|||
closable: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
mask: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
maskClosable: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
visible: { |
|||
type: Boolean, |
|||
value: false, |
|||
observer: 'setPopupVisible', |
|||
}, |
|||
zIndex: { |
|||
type: Number, |
|||
value: 1000, |
|||
}, |
|||
hasHeader: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
hasFooter: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
mountOnEnter: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
unmountOnExit: { |
|||
type: Boolean, |
|||
value: true, |
|||
}, |
|||
}, |
|||
data: { |
|||
transitionName: '', |
|||
popupVisible: false, |
|||
extStyle: '', |
|||
}, |
|||
computed: { |
|||
classes: ['prefixCls, position, safeAreaConfig, isIPhoneX', function(prefixCls, position, safeAreaConfig, isIPhoneX) { |
|||
const wrap = classNames(`${prefixCls}-position`, { |
|||
[`${prefixCls}-position--${position}`]: position, |
|||
[`${prefixCls}-position--is-iphonex`]: safeAreaConfig.bottom && isIPhoneX, |
|||
}) |
|||
const content = `${prefixCls}__content` |
|||
const hd = `${prefixCls}__hd` |
|||
const title = `${prefixCls}__title` |
|||
const bd = `${prefixCls}__bd` |
|||
const ft = `${prefixCls}__ft` |
|||
const extra = `${prefixCls}__extra` |
|||
const close = `${prefixCls}__close` |
|||
const x = `${prefixCls}__close-x` |
|||
|
|||
return { |
|||
wrap, |
|||
content, |
|||
hd, |
|||
title, |
|||
bd, |
|||
ft, |
|||
extra, |
|||
close, |
|||
x, |
|||
} |
|||
}], |
|||
}, |
|||
methods: { |
|||
/** |
|||
* 点击关闭按钮事件 |
|||
*/ |
|||
close() { |
|||
this.triggerEvent('close') |
|||
}, |
|||
/** |
|||
* 点击蒙层事件 |
|||
*/ |
|||
onMaskClick() { |
|||
if (this.data.maskClosable) { |
|||
this.close() |
|||
} |
|||
}, |
|||
/** |
|||
* 组件关闭后的回调函数 |
|||
*/ |
|||
onExited() { |
|||
this.triggerEvent('closed') |
|||
}, |
|||
/** |
|||
* 获取过渡的类名 |
|||
*/ |
|||
getTransitionName(value = this.data.position) { |
|||
const { animationPrefixCls } = this.data |
|||
let transitionName = '' |
|||
|
|||
switch (value) { |
|||
case 'top': |
|||
transitionName = `${animationPrefixCls}--slideInDown` |
|||
break |
|||
case 'right': |
|||
transitionName = `${animationPrefixCls}--slideInRight` |
|||
break |
|||
case 'bottom': |
|||
transitionName = `${animationPrefixCls}--slideInUp` |
|||
break |
|||
case 'left': |
|||
transitionName = `${animationPrefixCls}--slideInLeft` |
|||
break |
|||
default: |
|||
transitionName = `${animationPrefixCls}--fadeIn` |
|||
break |
|||
} |
|||
|
|||
this.setData({ transitionName }) |
|||
}, |
|||
/** |
|||
* 设置 popup 组件的显示隐藏 |
|||
*/ |
|||
setPopupVisible(popupVisible) { |
|||
if (this.data.popupVisible !== popupVisible) { |
|||
this.setData({ popupVisible }) |
|||
this.setBackdropVisible(popupVisible) |
|||
if(popupVisible){ |
|||
this.triggerEvent('show') |
|||
} |
|||
} |
|||
}, |
|||
/** |
|||
* 设置 backdrop 组件的显示隐藏 |
|||
*/ |
|||
setBackdropVisible(visible) { |
|||
if (this.data.mask && this.$wuxBackdrop) { |
|||
this.$wuxBackdrop[visible ? 'retain' : 'release']() |
|||
} |
|||
}, |
|||
}, |
|||
created() { |
|||
if (this.data.mask) { |
|||
this.$wuxBackdrop = $wuxBackdrop('#wux-backdrop', this) |
|||
} |
|||
}, |
|||
attached() { |
|||
this.setPopupVisible(this.data.visible) |
|||
this.getTransitionName() |
|||
}, |
|||
}) |
|||
@ -0,0 +1,7 @@ |
|||
{ |
|||
"component": true, |
|||
"usingComponents": { |
|||
"wux-animation-group": "../animation-group/index", |
|||
"wux-backdrop": "../backdrop/index" |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
<wux-backdrop id="wux-backdrop" wx:if="{{ mask }}" bind:click="onMaskClick" zIndex="{{ zIndex }}" /> |
|||
<view class="wux-class {{ classes.wrap }}" style="{{ extStyle }}"> |
|||
<wux-animation-group wux-class="{{ prefixCls }}" in="{{ popupVisible }}" classNames="{{ transitionName }}" bind:exited="onExited" wrapStyle="{{ { zIndex } }}" mountOnEnter="{{ mountOnEnter }}" unmountOnExit="{{ unmountOnExit }}"> |
|||
<view class="wux-content-class {{ classes.content }}"> |
|||
<view class="wux-header-class {{ classes.hd }}" wx:if="{{ hasHeader }}"> |
|||
<view class="{{ classes.title }}" wx:if="{{ title }}">{{ title }}</view> |
|||
<block wx:else> |
|||
<slot name="header"></slot> |
|||
</block> |
|||
</view> |
|||
<view class="wux-body-class {{ classes.bd }}"> |
|||
<view wx:if="{{ content }}">{{ content }}</view> |
|||
<slot></slot> |
|||
</view> |
|||
<view class="wux-footer-class {{ classes.ft }}" wx:if="{{ hasFooter }}"> |
|||
<view class="{{ classes.extra }}" wx:if="{{ extra }}">{{ extra }}</view> |
|||
<block wx:else> |
|||
<slot name="footer"></slot> |
|||
</block> |
|||
</view> |
|||
<view class="wux-close-class {{ classes.close }}" wx:if="{{ closable }}" bindtap="close"> |
|||
<text class="{{ classes.x }}"></text> |
|||
</view> |
|||
</view> |
|||
</wux-animation-group> |
|||
</view> |
|||
@ -0,0 +1,114 @@ |
|||
.wux-popup { |
|||
position: fixed; |
|||
z-index: 1000; |
|||
width: 80%; |
|||
max-width: 600rpx |
|||
} |
|||
.wux-popup-position.wux-popup-position--center .wux-popup { |
|||
top: 50%; |
|||
left: 50%; |
|||
transform: translate(-50%,-50%) |
|||
} |
|||
.wux-popup-position.wux-popup-position--center .wux-popup__content { |
|||
border-radius: 6rpx |
|||
} |
|||
.wux-popup-position.wux-popup-position--center .wux-popup__hd { |
|||
padding: 1.3em 1.6em .5em |
|||
} |
|||
.wux-popup-position.wux-popup-position--center .wux-popup__bd { |
|||
padding: 0 1.6em .8em |
|||
} |
|||
.wux-popup-position.wux-popup-position--center .wux-popup__ft:after { |
|||
content: " "; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
right: 0; |
|||
height: 2rpx; |
|||
border-top: 2rpx solid #d5d5d6; |
|||
color: #d5d5d6; |
|||
transform-origin: 0 0; |
|||
transform: scaleY(.5) |
|||
} |
|||
.wux-popup-position.wux-popup-position--top .wux-popup { |
|||
position: fixed; |
|||
left: 0; |
|||
top: 0; |
|||
width: 100%; |
|||
max-width: 100% |
|||
} |
|||
.wux-popup-position.wux-popup-position--right .wux-popup { |
|||
position: fixed; |
|||
top: 0; |
|||
right: 0; |
|||
width: 80%; |
|||
max-width: 100%; |
|||
height: 100%; |
|||
max-height: 100% |
|||
} |
|||
.wux-popup-position.wux-popup-position--bottom .wux-popup { |
|||
position: fixed; |
|||
left: 0; |
|||
bottom: 0; |
|||
width: 100%; |
|||
max-width: 100% |
|||
} |
|||
.wux-popup-position.wux-popup-position--left .wux-popup { |
|||
position: fixed; |
|||
left: 0; |
|||
top: 0; |
|||
width: 80%; |
|||
max-width: 100%; |
|||
height: 100%; |
|||
max-height: 100% |
|||
} |
|||
.wux-popup-position.wux-popup-position--is-iphonex .wux-popup__content { |
|||
padding-bottom: 68rpx |
|||
} |
|||
.wux-popup__content { |
|||
position: relative; |
|||
background-color: #fff; |
|||
border: 0; |
|||
background-clip: padding-box; |
|||
height: 100%; |
|||
text-align: center; |
|||
overflow: hidden |
|||
} |
|||
.wux-popup__title { |
|||
font-weight: 400; |
|||
font-size: 36rpx |
|||
} |
|||
.wux-popup__bd { |
|||
min-height: 80rpx; |
|||
font-size: 30rpx; |
|||
line-height: 1.3; |
|||
word-wrap: break-word; |
|||
word-break: break-all; |
|||
color: #999 |
|||
} |
|||
.wux-popup__ft { |
|||
position: relative; |
|||
line-height: 96rpx; |
|||
font-size: 36rpx; |
|||
display: -ms-flexbox; |
|||
display: flex |
|||
} |
|||
.wux-popup__close { |
|||
border: 0; |
|||
padding: 6rpx; |
|||
background-color: transparent; |
|||
outline: 0; |
|||
position: absolute; |
|||
top: 12rpx; |
|||
right: 12rpx; |
|||
height: 42rpx; |
|||
width: 42rpx |
|||
} |
|||
.wux-popup__close-x { |
|||
display: inline-block; |
|||
width: 30rpx; |
|||
height: 30rpx; |
|||
background-repeat: no-repeat; |
|||
background-size: cover; |
|||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='30' height='30' viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23888' fill-rule='evenodd'%3E%3Cpath d='M1.414 0l28.284 28.284-1.414 1.414L0 1.414z'/%3E%3Cpath d='M28.284 0L0 28.284l1.414 1.414L29.698 1.414z'/%3E%3C/g%3E%3C/svg%3E") |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
// 使用的时候,用本组件包裹可以触发下拉刷新的内容。enablePullDownRefresh需要设置为false。
|
|||
Component({ |
|||
properties: { |
|||
refreshed: { // 必选,通知本组件收起
|
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
refreshing: { // 可选,通知本组件直接进入refreshing状态
|
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
distMax: { // 可选,可以下拉的最大高度,回弹的高度为最大高度的75%
|
|||
type: Number, |
|||
value: 45, |
|||
}, |
|||
color: { // 可选,圆弧颜色
|
|||
type: String, |
|||
value: "#000", |
|||
}, |
|||
backgroundColor: { // 可选,背景颜色
|
|||
type: String, |
|||
value: "#fff", |
|||
}, |
|||
type: { |
|||
type: Number, |
|||
value: 0 |
|||
} |
|||
}, |
|||
data: { |
|||
reachTop: false, |
|||
}, |
|||
methods: { |
|||
initObserver() { |
|||
this.observer = this.createIntersectionObserver() |
|||
this.observer.relativeToViewport().observe(".intersection-dot", (res) => { |
|||
if (res.intersectionRatio > 0) { |
|||
this.setData({ reachTop: true, }) |
|||
} else { |
|||
this.setData({ reachTop: false,}) |
|||
} |
|||
}) |
|||
}, |
|||
clearObserver() { |
|||
if (this.observer) { |
|||
this.observer.disconnect() |
|||
this.observer = null |
|||
} |
|||
}, |
|||
}, |
|||
ready() { |
|||
this.initObserver() |
|||
}, |
|||
detached() { |
|||
this.clearObserver() |
|||
}, |
|||
}) |
|||
@ -0,0 +1,4 @@ |
|||
{ |
|||
"component": true, |
|||
"usingComponents": {} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
<wxs module="refresher" src="./index.wxs"></wxs> |
|||
<view class="refresh-wrap" style="{{backgroundColor ? 'background-color:' + backgroundColor + ';' : ''}}"> |
|||
<view class="refresh" style="{{color ? 'border-color:' + color + ';' : ''}}"></view> |
|||
</view> |
|||
<view class="wrap" change:refreshed="{{refresher.onRefreshed}}" refreshed="{{refreshed}}" change:refreshing="{{refresher.onRefreshing}}" refreshing="{{refreshing}}" data-dist-max="{{distMax}}" data-type="{{type}}" data-reach-top="{{reachTop}}" bind:touchstart="{{refresher.touchStart}}" |
|||
bind:touchmove="{{refresher.touchMove}}" bind:touchend="{{refresher.touchEnd}}"> |
|||
<view class="intersection-dot"></view> |
|||
<slot></slot> |
|||
</view> |
|||
@ -0,0 +1,158 @@ |
|||
// 文档:https://developers.weixin.qq.com/miniprogram/dev/framework/view/interactive-animation.html |
|||
|
|||
/* eslint-disable */ |
|||
function calcResistance(distExtra, distMax) { |
|||
return Math.min(1, distExtra / distMax / 1.2) * Math.min(distMax, distExtra) |
|||
} |
|||
|
|||
function touchStart(e, ins) { |
|||
var dataset = e.instance.getDataset() |
|||
var state = e.instance.getState() |
|||
state.distMax = dataset.distMax |
|||
state.type = dataset.type |
|||
state.distThreshold = state.distMax * 0.75 |
|||
state.reachTop = dataset.reachTop |
|||
state.status = state.status || "pending" // pending、pulling、releasing、refreshing |
|||
|
|||
if (state.status === "pending" && state.reachTop) { |
|||
state.startPulling = true |
|||
state.pullStartX = e.touches[0].clientX |
|||
state.pullStartY = e.touches[0].clientY |
|||
state.distance = 0 |
|||
|
|||
state.component = state.component || ins.selectComponent(".refresh-wrap") |
|||
state.component.removeClass("transition") |
|||
state.component.removeClass("animation") |
|||
state.component.removeClass("fadeout") |
|||
state.component.setStyle({ |
|||
top: (state.distance * 2 - 20) + "rpx", |
|||
opacity: 0, |
|||
transform: "rotate(0)", |
|||
"-webkit-transform": "rotate(0)" |
|||
}) |
|||
} |
|||
} |
|||
|
|||
function touchMove(e, ins) { |
|||
var state = e.instance.getState() |
|||
if (!state.startPulling || state.status === "refreshing") { |
|||
return true |
|||
} |
|||
state.pullMoveX = e.touches[0].clientX |
|||
state.pullMoveY = e.touches[0].clientY |
|||
if (state.status === "pending") { |
|||
state.status = "pulling" |
|||
} |
|||
var distExtraX = state.pullMoveX - state.pullStartX |
|||
var distExtraY = state.pullMoveY - state.pullStartY |
|||
if (distExtraY > 0 && Math.abs(distExtraY) >= Math.abs(distExtraX)) { |
|||
state.distance = calcResistance(distExtraY, state.distMax) |
|||
state.component.setStyle({ |
|||
top: setop(state.distance, state.type), |
|||
opacity: Math.min(1, state.distance / state.distThreshold), |
|||
transform: "rotate(" + (245 * state.distance / state.distMax) + "deg)", |
|||
"-webkit-transform": "rotate(" + (245 * state.distance / state.distMax) + "deg)" |
|||
}) |
|||
|
|||
if (state.status === "pulling" && state.distance > state.distThreshold) { |
|||
state.status = "releasing" |
|||
} |
|||
if (state.status === "releasing" && state.distance < state.distThreshold) { |
|||
state.status = "pulling" |
|||
} |
|||
return false |
|||
} |
|||
return true |
|||
} |
|||
|
|||
function touchEnd(e, ins) { |
|||
var state = e.instance.getState() |
|||
|
|||
if (!state.startPulling || state.status === "refreshing") { |
|||
return |
|||
} |
|||
state.startPulling = false |
|||
if (state.status === "releasing" && state.distance > state.distThreshold) { |
|||
state.status = "refreshing" |
|||
state.distance = state.distThreshold |
|||
|
|||
state.component.addClass("animation") |
|||
state.component.setStyle({ |
|||
top: setop(state.distance, state.type), |
|||
opacity: Math.min(1, state.distance / state.distThreshold), |
|||
}) |
|||
|
|||
ins.triggerEvent("refresh") |
|||
} else { |
|||
reset(state) |
|||
} |
|||
} |
|||
|
|||
function reset(state) { |
|||
state.status = "pending" |
|||
state.startPulling = false |
|||
state.distance = 0 |
|||
state.component.addClass("transition") |
|||
state.component.setStyle({ |
|||
top: setop(state.distance, state.type), |
|||
opacity: 0, |
|||
transform: "rotate(0)", |
|||
"-webkit-transform": "rotate(0)" |
|||
}) |
|||
} |
|||
|
|||
function onRefreshed(newValue, oldValue, ins, itemIns) { |
|||
if (newValue) { |
|||
var state = itemIns.getState() |
|||
state.status = "pending" |
|||
state.startPulling = false |
|||
|
|||
var component = state.component || ins.selectComponent(".refresh-wrap") |
|||
component.removeClass("animation") |
|||
component.addClass("fadeout") |
|||
component.setStyle({ |
|||
top: (state.distance * 2 - (state.type? 12 : 30)) + "rpx", |
|||
opacity: 0, |
|||
transform: "scale(0)", |
|||
"-webkit-transform": "rotate(0)" |
|||
}) |
|||
} |
|||
} |
|||
|
|||
function setop(distance, type){ |
|||
var top = (distance * 2 + (type == 0 ? 120 : -30)) + "rpx" |
|||
return top |
|||
} |
|||
|
|||
function onRefreshing(newValue, oldValue, ins, itemIns) { |
|||
if (newValue) { |
|||
var dataset = itemIns.getDataset() |
|||
var state = itemIns.getState() |
|||
state.distMax = state.distMax || dataset.distMax |
|||
state.distThreshold = state.distThreshold || state.distMax * 0.75 |
|||
|
|||
state.status = "refreshing" |
|||
state.distance = state.distThreshold |
|||
state.startPulling = false |
|||
state.component = state.component || ins.selectComponent(".refresh-wrap") |
|||
|
|||
state.component.removeClass("transition") |
|||
state.component.removeClass("fadeout") |
|||
state.component.addClass("animation") |
|||
state.component.setStyle({ |
|||
top: setop(state.distance, state.type), |
|||
opacity: 1, |
|||
transition: "none", |
|||
}) |
|||
// ins.triggerEvent("refresh") |
|||
} |
|||
} |
|||
|
|||
module.exports = { |
|||
touchStart: touchStart, |
|||
touchMove: touchMove, |
|||
touchEnd: touchEnd, |
|||
onRefreshed: onRefreshed, |
|||
onRefreshing: onRefreshing, |
|||
} |
|||
/* eslint-enable */ |
|||
@ -0,0 +1,68 @@ |
|||
@keyframes rolling { |
|||
0% { |
|||
transform: rotate(135deg); |
|||
} |
|||
100% { |
|||
transform: rotate(495deg); |
|||
} |
|||
} |
|||
@keyframes fadeout { |
|||
0% { |
|||
opacity: 1; |
|||
transform: rotate(135deg) scale(1); |
|||
} |
|||
100% { |
|||
opacity: 0; |
|||
transform: rotate(135deg) scale(0); |
|||
} |
|||
} |
|||
.refresh-wrap { |
|||
position: fixed; |
|||
width: 42px; |
|||
height: 42px; |
|||
left: 50%; |
|||
margin-left: -21px; |
|||
top: 50px; |
|||
z-index: 88; |
|||
background-color: #fff; |
|||
border-radius: 50%; |
|||
box-shadow: 0 0 6px 1px #ccc; |
|||
opacity: 0; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
.refresh-wrap.transition { |
|||
transition: top 0.3s ease-in-out, opacity 0.3s ease-in-out, transform 0.3s ease-in-out; |
|||
} |
|||
.refresh-wrap.animation { |
|||
transition: top 0.3s ease-in-out, opacity 0.3s ease-in-out; |
|||
animation: rolling 0.6s linear infinite; |
|||
} |
|||
.refresh-wrap.fadeout { |
|||
animation: fadeout 0.3s ease-in-out; |
|||
} |
|||
.refresh-wrap .refresh { |
|||
box-sizing: border-box; |
|||
width: 24px; |
|||
height: 24px; |
|||
border-radius: 50%; |
|||
border: 3px solid #000; |
|||
border-top-color: transparent !important; |
|||
} |
|||
.refresh-wrap.fadeout .refresh { |
|||
opacity: 0; |
|||
} |
|||
.wrap { |
|||
width: 100%; |
|||
height: 100%; |
|||
position: relative; |
|||
} |
|||
.wrap .intersection-dot { |
|||
position: absolute; |
|||
width: 10px; |
|||
height: 10px; |
|||
left: 0; |
|||
top: 0; |
|||
visibility: hidden; |
|||
} |
|||
@ -0,0 +1,110 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import classNames from '../helpers/classNames' |
|||
|
|||
const defaultIcon = { |
|||
type: 'success', |
|||
size: 93, |
|||
color: '#33cd5f', |
|||
} |
|||
|
|||
const getIcon = (icon) => { |
|||
if (icon !== null && typeof icon === 'object') { |
|||
return Object.assign({}, defaultIcon, icon) |
|||
} else if (typeof icon === 'string') { |
|||
return Object.assign({}, defaultIcon, { |
|||
type: icon, |
|||
}) |
|||
} |
|||
return defaultIcon |
|||
} |
|||
|
|||
baseComponent({ |
|||
properties: { |
|||
prefixCls: { |
|||
type: String, |
|||
value: 'wux-result', |
|||
}, |
|||
icon: { |
|||
type: null, |
|||
value: defaultIcon, |
|||
observer(newVal) { |
|||
this.setData({ |
|||
resultIcon: getIcon(newVal), |
|||
}) |
|||
}, |
|||
}, |
|||
title: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
label: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
buttons: { |
|||
type: Array, |
|||
value: [], |
|||
}, |
|||
extra: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
fixed: { |
|||
type: Boolean, |
|||
value: false, |
|||
}, |
|||
}, |
|||
data: { |
|||
resultIcon: null, |
|||
}, |
|||
computed: { |
|||
classes: ['prefixCls, fixed', function(prefixCls, fixed) { |
|||
const wrap = classNames(prefixCls, { |
|||
[`${prefixCls}--fixed`]: fixed, |
|||
}) |
|||
const hd = `${prefixCls}__hd` |
|||
const icon = `${prefixCls}__icon` |
|||
const bd = `${prefixCls}__bd` |
|||
const title = `${prefixCls}__title` |
|||
const desc = `${prefixCls}__desc` |
|||
const buttons = `${prefixCls}__buttons` |
|||
const ft = `${prefixCls}__ft` |
|||
|
|||
return { |
|||
wrap, |
|||
hd, |
|||
icon, |
|||
bd, |
|||
title, |
|||
desc, |
|||
buttons, |
|||
ft, |
|||
} |
|||
}], |
|||
}, |
|||
methods: { |
|||
onClick(e) { |
|||
this.triggerEvent('click', e.currentTarget.dataset) |
|||
}, |
|||
bindgetuserinfo(e) { |
|||
this.triggerEvent('getuserinfo', {...e.detail, ...e.currentTarget.dataset }) |
|||
}, |
|||
bindcontact(e) { |
|||
this.triggerEvent('contact', {...e.detail, ...e.currentTarget.dataset }) |
|||
}, |
|||
bindgetphonenumber(e) { |
|||
this.triggerEvent('getphonenumber', {...e.detail, ...e.currentTarget.dataset }) |
|||
}, |
|||
bindopensetting(e) { |
|||
this.triggerEvent('opensetting', {...e.detail, ...e.currentTarget.dataset }) |
|||
}, |
|||
onError(e) { |
|||
this.triggerEvent('error', {...e.detail, ...e.currentTarget.dataset }) |
|||
}, |
|||
}, |
|||
attached() { |
|||
this.setData({ |
|||
resultIcon: getIcon(this.data.icon), |
|||
}) |
|||
}, |
|||
}) |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"component": true, |
|||
"usingComponents": { |
|||
"wux-button": "../button/index" |
|||
} |
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
<view class="wux-class {{ classes.wrap }}"> |
|||
<view class="{{ classes.hd }}"> |
|||
<view wx:if="{{ resultIcon }}" class="{{ classes.icon }}"> |
|||
<icon type="{{ resultIcon.type }}" size="{{ resultIcon.size }}" color="{{ resultIcon.color }}" /> |
|||
</view> |
|||
<block wx:else> |
|||
<slot name="header"></slot> |
|||
</block> |
|||
</view> |
|||
<view class="{{ classes.bd }}"> |
|||
<view wx:if="{{ title }}" class="{{ classes.title }}">{{ title }}</view> |
|||
<view wx:if="{{ label }}" class="{{ classes.desc }}">{{ label }}</view> |
|||
<view wx:if="{{ buttons.length }}" class="{{ classes.buttons }}"> |
|||
<block wx:for="{{ buttons }}" wx:for-item="button" wx:key="index"> |
|||
<wux-button |
|||
type="{{ button.type }}" |
|||
clear="{{ button.clear }}" |
|||
block="{{ button.block }}" |
|||
full="{{ button.full }}" |
|||
outline="{{ button.outline }}" |
|||
size="{{ button.size }}" |
|||
disabled="{{ button.disabled }}" |
|||
loading="{{ button.loading }}" |
|||
form-type="{{ button.formType }}" |
|||
open-type="{{ button.openType }}" |
|||
hover-stop-propagation="{{ button.hoverStopPropagation }}" |
|||
hover-start-time="{{ button.hoverStartTime }}" |
|||
hover-stay-time="{{ button.hoverStayTime }}" |
|||
lang="{{ button.lang }}" |
|||
bind:getuserinfo="bindgetuserinfo" |
|||
session-from="{{ button.sessionFrom }}" |
|||
send-message-title="{{ button.sendMessageTitle }}" |
|||
send-message-path="{{ button.sendMessagePath }}" |
|||
send-message-img="{{ button.sendMessageImg }}" |
|||
show-message-card="{{ button.showMessageCard }}" |
|||
bind:contact="bindcontact" |
|||
bind:getphonenumber="bindgetphonenumber" |
|||
app-parameter="{{ button.appParameter }}" |
|||
binderror="onError" |
|||
bindopensetting="bindopensetting" |
|||
data-index="{{ index }}" |
|||
bind:click="onClick" |
|||
> |
|||
{{ button.text }} |
|||
</wux-button> |
|||
</block> |
|||
</view> |
|||
<slot></slot> |
|||
</view> |
|||
<view class="{{ classes.ft }}"> |
|||
<block wx:if="{{ extra }}"> |
|||
<text>{{ extra }}</text> |
|||
</block> |
|||
<block wx:else> |
|||
<slot name="footer"></slot> |
|||
</block> |
|||
</view> |
|||
</view> |
|||
@ -0,0 +1,36 @@ |
|||
.wux-result { |
|||
padding-top: 0; |
|||
text-align: center |
|||
} |
|||
.wux-result__bd { |
|||
padding: 60rpx 40rpx |
|||
} |
|||
.wux-result__icon { |
|||
padding-top: 72rpx; |
|||
text-align: center |
|||
} |
|||
.wux-result__title { |
|||
margin-bottom: 10rpx; |
|||
font-weight: 400; |
|||
font-size: 40rpx |
|||
} |
|||
.wux-result__desc { |
|||
font-size: 28rpx; |
|||
color: grey |
|||
} |
|||
.wux-result__buttons { |
|||
margin-top: 60rpx |
|||
} |
|||
.wux-result__ft { |
|||
font-size: 28rpx; |
|||
color: grey |
|||
} |
|||
.wux-result--fixed .wux-result__ft { |
|||
position: fixed; |
|||
left: 0; |
|||
bottom: 0; |
|||
width: 100%; |
|||
padding: 30rpx; |
|||
text-align: center; |
|||
box-sizing: border-box |
|||
} |
|||
@ -0,0 +1,88 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import classNames from '../helpers/classNames' |
|||
|
|||
const defaultStatus = ['wait', 'process', 'finish', 'error'] |
|||
const defaultIcon = 'ios-checkmark' |
|||
|
|||
baseComponent({ |
|||
relations: { |
|||
'../steps/index': { |
|||
type: 'parent', |
|||
}, |
|||
}, |
|||
properties: { |
|||
prefixCls: { |
|||
type: String, |
|||
value: 'wux-step', |
|||
}, |
|||
status: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
title: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
content: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
icon: { |
|||
type: String, |
|||
value: '', |
|||
}, |
|||
}, |
|||
data: { |
|||
width: '100%', |
|||
length: 1, |
|||
index: 0, |
|||
current: 0, |
|||
direction: 'horizontal', |
|||
}, |
|||
computed: { |
|||
classes: ['prefixCls, direction', function(prefixCls, direction) { |
|||
const wrap = classNames(prefixCls, { |
|||
[`${prefixCls}--${direction}`]: direction, |
|||
}) |
|||
const hd = `${prefixCls}__hd` |
|||
const icon = `${prefixCls}__icon` |
|||
const thumb = `${prefixCls}__thumb` |
|||
const bd = `${prefixCls}__bd` |
|||
const title = `${prefixCls}__title` |
|||
const content = `${prefixCls}__content` |
|||
const ft = `${prefixCls}__ft` |
|||
|
|||
return { |
|||
wrap, |
|||
hd, |
|||
icon, |
|||
thumb, |
|||
bd, |
|||
title, |
|||
content, |
|||
ft, |
|||
} |
|||
}], |
|||
}, |
|||
methods: { |
|||
updateCurrent(opts = {}) { |
|||
const width = opts.direction === 'horizontal' ? 100 / opts.length + '%' : '100%' |
|||
const index = defaultStatus.indexOf(this.data.status) |
|||
const hasIcon = opts.index < opts.current || this.data.icon |
|||
const thumb = this.data.icon || defaultIcon |
|||
const suffix = index !== -1 ? defaultStatus[index] : opts.index < opts.current ? 'finish' : opts.index === opts.current ? 'process' : '' |
|||
const className = `${this.data.prefixCls}--${suffix}` |
|||
const options = Object.assign({ |
|||
width, |
|||
className, |
|||
hasIcon, |
|||
thumb, |
|||
}, opts) |
|||
|
|||
this.setData(options) |
|||
}, |
|||
}, |
|||
attached() { |
|||
this.updateCurrent(this.data) |
|||
}, |
|||
}) |
|||
@ -0,0 +1,4 @@ |
|||
{ |
|||
"component": true, |
|||
"usingComponents": { } |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
<view class="wux-class {{ classes.wrap }} {{ className }}" style="width: {{ width }}"> |
|||
<view class="{{ classes.hd }}"> |
|||
<view class="{{ classes.icon }}" wx:if="{{ !hasIcon }}">{{ index + 1 }}</view> |
|||
<text wx:else class="cuIcon-roundcheck text-blue" style="font-size:54rpx"></text> |
|||
</view> |
|||
<view class="{{ classes.bd }}"> |
|||
<view class="{{ classes.title }}" wx:if="{{ title }}"> |
|||
{{ title }} |
|||
</view> |
|||
<view class="{{ classes.title }}" wx:else> |
|||
<slot name="title"></slot> |
|||
</view> |
|||
<view class="{{ classes.content }}" wx:if="{{ content }}"> |
|||
{{ content }} |
|||
</view> |
|||
<view class="{{ classes.content }}" wx:else> |
|||
<slot name="content"></slot> |
|||
</view> |
|||
</view> |
|||
<view class="{{ classes.ft }}" wx:if="{{ index !== length - 1 }}"></view> |
|||
</view> |
|||
@ -0,0 +1,122 @@ |
|||
.wux-step { |
|||
font-size: 0; |
|||
position: relative; |
|||
display: inline-block; |
|||
box-sizing: border-box; |
|||
padding: 0 10rpx; |
|||
vertical-align: top |
|||
} |
|||
.wux-step--vertical { |
|||
padding-bottom: 60rpx |
|||
} |
|||
.wux-step--vertical .wux-step__hd { |
|||
float: left |
|||
} |
|||
.wux-step--vertical .wux-step__bd { |
|||
overflow: hidden; |
|||
display: block; |
|||
margin-left: 80rpx; |
|||
margin-top: 0; |
|||
text-align: left; |
|||
clear: inherit |
|||
} |
|||
.wux-step--vertical .wux-step__ft { |
|||
position: absolute; |
|||
left: 40rpx; |
|||
top: 0; |
|||
height: 100%; |
|||
width: 2rpx; |
|||
padding: 60rpx 0 8rpx; |
|||
margin-left: 0 |
|||
} |
|||
.wux-step--vertical .wux-step__ft:after { |
|||
width: 2rpx; |
|||
height: 100% |
|||
} |
|||
.wux-step__ft { |
|||
position: absolute; |
|||
left: 50%; |
|||
width: 100%; |
|||
top: 24rpx; |
|||
padding: 0 48rpx; |
|||
margin-left: 6rpx; |
|||
box-sizing: border-box |
|||
} |
|||
.wux-step__ft:after { |
|||
content: ""; |
|||
display: inline-block; |
|||
background: #ddd; |
|||
height: 2rpx; |
|||
border-radius: 2rpx; |
|||
width: 100%; |
|||
transition: background .3s; |
|||
position: relative; |
|||
left: -4rpx |
|||
} |
|||
.wux-step__icon { |
|||
box-sizing: border-box; |
|||
font-size: 24rpx; |
|||
width: 48rpx; |
|||
height: 100%; |
|||
border-radius: 50%; |
|||
background: #fff; |
|||
position: relative; |
|||
z-index: 2; |
|||
margin: 0 auto; |
|||
border: #e9eaec solid 2rpx; |
|||
margin-left: 2px |
|||
} |
|||
.wux-step__thumb { |
|||
width: 100%; |
|||
height: 100%; |
|||
display: inline-block; |
|||
overflow: hidden |
|||
} |
|||
.wux-step--process .wux-step__icon { |
|||
border: #009ee0 solid 2rpx; |
|||
color: #fff; |
|||
background: #009ee0 |
|||
} |
|||
.wux-step--wait .wux-step__icon { |
|||
border: #e9eaec solid 2rpx; |
|||
color: #e9eaec |
|||
} |
|||
.wux-step--wait .wux-step__ft:after { |
|||
background: #009ee0 |
|||
} |
|||
.wux-step--finish .wux-step__icon { |
|||
border: #009ee0 solid 2rpx; |
|||
color: #009ee0 |
|||
} |
|||
.wux-step--finish .wux-step__ft:after { |
|||
background: #009ee0 |
|||
} |
|||
.wux-step--error .wux-step__icon { |
|||
border: #ef473a solid 2rpx; |
|||
color: #ef473a |
|||
} |
|||
.wux-step--error .wux-step__ft:after { |
|||
background: #ef473a |
|||
} |
|||
.wux-step__hd { |
|||
width: auto; |
|||
height: 48rpx; |
|||
line-height: 48rpx; |
|||
text-align: center; |
|||
box-sizing: border-box |
|||
} |
|||
.wux-step__bd { |
|||
margin-top: 20rpx; |
|||
text-align: center; |
|||
clear: both |
|||
} |
|||
.wux-step__title { |
|||
font-size: 32rpx; |
|||
font-weight: 700; |
|||
color: #000 |
|||
} |
|||
.wux-step__content { |
|||
font-size: 24rpx; |
|||
margin-top: 6rpx; |
|||
color: #b2b2b2 |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
import baseComponent from '../helpers/baseComponent' |
|||
import classNames from '../helpers/classNames' |
|||
|
|||
baseComponent({ |
|||
relations: { |
|||
'../step/index': { |
|||
type: 'child', |
|||
observer() { |
|||
this.debounce(this.updateCurrent) |
|||
}, |
|||
}, |
|||
}, |
|||
properties: { |
|||
prefixCls: { |
|||
type: String, |
|||
value: 'wux-steps', |
|||
}, |
|||
current: { |
|||
type: Number, |
|||
value: 0, |
|||
observer: 'updateCurrent', |
|||
}, |
|||
// status: {
|
|||
// type: String,
|
|||
// value: '',
|
|||
// },
|
|||
direction: { |
|||
type: String, |
|||
value: 'horizontal', |
|||
}, |
|||
}, |
|||
methods: { |
|||
updateCurrent() { |
|||
const elements = this.getRelationNodes('../step/index') |
|||
const { current, direction } = this.data |
|||
|
|||
if (elements.length > 0) { |
|||
elements.forEach((element, index) => { |
|||
element.updateCurrent({ |
|||
length: elements.length, |
|||
index, |
|||
current, |
|||
direction, |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"component": true |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<view class="wux-class {{ prefixCls }}"> |
|||
<slot></slot> |
|||
</view> |
|||
@ -0,0 +1,4 @@ |
|||
.wux-steps { |
|||
position: relative; |
|||
width: 100% |
|||
} |
|||
@ -0,0 +1,126 @@ |
|||
Component({ |
|||
properties: { |
|||
// 数据源
|
|||
tabData: { |
|||
type: Array, |
|||
value: [], |
|||
observer: "dataChange" |
|||
}, |
|||
// 是否可以超出滚动
|
|||
tabCur: { |
|||
type: Number, |
|||
value: 0, |
|||
observer: "tabCurChange" |
|||
}, |
|||
// 是否可以超出滚动
|
|||
scroll: { |
|||
type: Boolean, |
|||
value: false |
|||
}, |
|||
// tab高度
|
|||
size: { |
|||
type: Number, |
|||
value: 90, |
|||
observer: "sizeChange" |
|||
}, |
|||
// 颜色
|
|||
color: { |
|||
type: String, |
|||
value: "" |
|||
} |
|||
}, |
|||
data: { |
|||
/* 未渲染数据 */ |
|||
windowWidth: 0, // 屏幕宽度
|
|||
tabItems: [], // 所有 tab 节点信息
|
|||
|
|||
/* 渲染数据 */ |
|||
scrolling: true, // 控制 scroll-view 滚动以在异步加载数据的时候能正确获得 dom 信息
|
|||
needTransition: false, // 下划线是否需要过渡动画
|
|||
translateX: 0, // 下划 line 的左边距离
|
|||
lineWidth: 0, // 下划 line 宽度
|
|||
scrollLeft: 0, // scroll-view 左边滚动距离
|
|||
}, |
|||
methods: { |
|||
/** |
|||
* 切换菜单 |
|||
*/ |
|||
toggleTab(e) { |
|||
this.triggerEvent('change', {index: e.currentTarget.dataset.index}); |
|||
this.scrollByIndex(e.currentTarget.dataset.index); |
|||
}, |
|||
/** |
|||
* 滑动到指定位置 |
|||
* @param tabCur: 当前激活的tabItem的索引 |
|||
* @param needTransition: 下划线是否需要过渡动画, 第一次进来应设置为false |
|||
*/ |
|||
scrollByIndex(tabCur, needTransition = true) { |
|||
let item = this.data.tabItems[tabCur]; |
|||
if (!item) return; |
|||
let itemWidth = item.width || 0, |
|||
itemLeft = item.left || 0; |
|||
|
|||
this.setData({needTransition: needTransition}); |
|||
|
|||
if (this.data.scroll) { // 超出滚动的情况
|
|||
// 保持滚动后当前 item '尽可能' 在屏幕中间
|
|||
let scrollLeft = itemLeft - (this.data.windowWidth - itemWidth) / 2; |
|||
|
|||
this.setData({ |
|||
tabCur: tabCur, |
|||
scrollLeft: scrollLeft, |
|||
translateX: itemLeft, |
|||
lineWidth: itemWidth |
|||
}); |
|||
} else { // 不超出滚动的情况
|
|||
this.setData({ |
|||
tabCur: tabCur, |
|||
translateX: itemLeft, |
|||
lineWidth: itemWidth |
|||
}); |
|||
} |
|||
}, |
|||
/** |
|||
* 监听数据变化, 如果改变重新初始化参数 |
|||
*/ |
|||
dataChange(newVal, oldVal) { |
|||
this.setData({ |
|||
scrolling: false |
|||
}); |
|||
// 异步加载数据时候, 延迟执行 init 方法, 防止基础库 2.7.1 版本及以下无法正确获取 dom 信息
|
|||
setTimeout(() => this.init(), 10); |
|||
}, |
|||
/** |
|||
* 监听 tabCur 变化, 做对应处理 |
|||
*/ |
|||
tabCurChange(newVal, oldVal) { |
|||
this.scrollByIndex(newVal); |
|||
}, |
|||
/** |
|||
* 监听 tab 高度变化, 最小值为80rpx |
|||
*/ |
|||
sizeChange(newVal, oldVal) { |
|||
if (newVal <= 80) { |
|||
this.setData({size: 80}); |
|||
} |
|||
}, |
|||
/** |
|||
* 初始化函数 |
|||
*/ |
|||
init() { |
|||
const {windowWidth} = wx.getSystemInfoSync(); |
|||
this.setData({windowWidth: windowWidth || 375}); |
|||
|
|||
this.createSelectorQuery().selectAll(".tabs__item-child").boundingClientRect((res) => { |
|||
this.setData({ |
|||
scrolling: true, |
|||
tabItems: res |
|||
}); |
|||
this.scrollByIndex(this.data.tabCur, false); |
|||
}).exec(); |
|||
} |
|||
}, |
|||
ready() { |
|||
this.init(); |
|||
} |
|||
}); |
|||
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save