增加环形进度组件,增加卖场评分页面
This commit is contained in:
@@ -69,19 +69,23 @@
|
||||
"pages/signup/index",
|
||||
"pages/signup/status",
|
||||
"pages/clues/index",
|
||||
"pages/clues/detail/index"
|
||||
"pages/clues/detail/index",
|
||||
"pages/score/index",
|
||||
"pages/score/detail"
|
||||
],
|
||||
"permission": {
|
||||
"scope.userLocation": {
|
||||
"desc": "你的位置信息将用于线下车卖场到访签到"
|
||||
}
|
||||
},
|
||||
"echarts": [{
|
||||
"echarts": [
|
||||
{
|
||||
"root": "ecCanvas",
|
||||
"pages": [
|
||||
"pages/index/index"
|
||||
]
|
||||
}],
|
||||
}
|
||||
],
|
||||
"window": {
|
||||
"backgroundTextStyle": "light",
|
||||
"navigationBarBackgroundColor": "#fff",
|
||||
|
||||
@@ -40,3 +40,15 @@
|
||||
|
||||
.bg-f0f4ff{background-color:#f0f4ff;}
|
||||
.bg-fffaf3{background-color:#fffaf3;}
|
||||
|
||||
.bg-size-cover{background-size: cover;}
|
||||
.bg-size-fullwidth{background-size: 100% auto;}
|
||||
.bg-size-fullheight{background-size: auto 100%;}
|
||||
.bg-no-repeat{background-repeat: no-repeat;}
|
||||
.bg-repeat-x{background-repeat:repeat-x;}
|
||||
.bg-repeat-y{background-repeat: repeat-y;}
|
||||
.bg-pos-top{background-position: top center;}
|
||||
.bg-pos-bottom{background-position: bottom center;}
|
||||
.bg-pos-center{background-position: center;}
|
||||
|
||||
.bg-custom-linear-bottom{background-image: linear-gradient(to bottom, var(--linearcolor), transparent);}
|
||||
@@ -25,3 +25,5 @@
|
||||
.bbs-1-474a65{border-bottom:#474a65 1rpx solid; box-sizing:border-box;}
|
||||
|
||||
.last-b-none:last-child{border-bottom:none;}
|
||||
|
||||
.bbs-1-f6{border-bottom:#f6f6f6 1rpx solid;box-sizing:border-box;}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
.img-24x24{width:24rpx;height:24rpx;box-sizing:border-box;}
|
||||
.img-28x28{width:28rpx;height:28rpx;box-sizing:border-box;}
|
||||
.img-32x32{width:32rpx;height:32rpx;box-sizing:border-box;}
|
||||
.img-38x38{width:38rpx;height:38rpx;box-sizing:border-box;}
|
||||
.img-45x45{width:45rpx;height:45rpx;box-sizing:border-box;}
|
||||
.img-50x50{width:50rpx;height:50rpx;box-sizing:border-box;}
|
||||
.img-55x55{width:55rpx;height:55rpx;box-sizing:border-box;}
|
||||
@@ -15,6 +18,7 @@
|
||||
.img-130x130{width:130rpx;height:130rpx;box-sizing:border-box;}
|
||||
.img-135x135{width:135rpx;height:135rpx;box-sizing:border-box;}
|
||||
.img-140x140{width:140rpx;height:140rpx;box-sizing:border-box;}
|
||||
.img-154x154{width:154rpx;height:154rpx;box-sizing:border-box;}
|
||||
.img-160x160{width:160rpx;height:160rpx;box-sizing:border-box;}
|
||||
.img-190x175{width:190rpx;height:175rpx;box-sizing:border-box;}
|
||||
.img-200x180{width:200rpx;height:180rpx;box-sizing:border-box;}
|
||||
|
||||
@@ -20,8 +20,16 @@
|
||||
.overflowXhidden{overflow-x:hidden;}
|
||||
.overflow-initial{overflow:initial;}
|
||||
.opacity-0{opacity:0;}
|
||||
.opacity-5{opacity:.05;}
|
||||
.opacity-10{opacity:.1;}
|
||||
.opacity-20{opacity:.2;}
|
||||
.opacity-30{opacity:.3;}
|
||||
.opacity-40{opacity:.4;}
|
||||
.opacity-50{opacity:.5;}
|
||||
.opacity-60{opacity:.6;}
|
||||
.opacity-70{opacity:.7;}
|
||||
.opacity-80{opacity:.8;}
|
||||
.opacity-90{opacity:.9;}
|
||||
|
||||
/*line-clamp*/
|
||||
.line-clamp-2{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;}
|
||||
@@ -44,6 +52,7 @@
|
||||
.fn-flex-around{justify-content: space-around;}/*各项周围留有空白*/
|
||||
.fn-flex-middle{align-items:center;}/*交叉轴上上下居中对齐*/
|
||||
.fn-flex-center{justify-content: center;}/*居中对齐*/
|
||||
.fn-flex-column{flex-direction:column;}
|
||||
|
||||
.wp25{width:25%;box-sizing:border-box;}
|
||||
.wp31{width:31%;box-sizing:border-box;}
|
||||
@@ -136,3 +145,5 @@
|
||||
|
||||
.datecell{width:14.28%;padding:30rpx 0;text-align:center;box-sizing:border-box;}
|
||||
.datecell.active{background-color:#36afa2;color:#fff;}
|
||||
|
||||
.transition-all{transition: all .2s ease;}
|
||||
@@ -61,6 +61,7 @@
|
||||
.mr50{margin-right:50rpx;}
|
||||
.mr60{margin-right:60rpx;}
|
||||
.mr70{margin-right:70rpx;}
|
||||
.mr100{margin-right:100rpx;}
|
||||
.mr150{margin-right:150rpx;}
|
||||
.mr160{margin-right:160rpx;}
|
||||
.mr170{margin-right:170rpx;}
|
||||
|
||||
@@ -189,6 +189,8 @@ api = {
|
||||
//远程图片存储地址
|
||||
var imgUrl = 'https://qs.haodian.cn/wechat_app/lichebao/'
|
||||
|
||||
var licheImgUrl = 'https://img.liche.cn/lichebao/'
|
||||
|
||||
|
||||
/**
|
||||
* 默认头像
|
||||
@@ -238,6 +240,7 @@ export default {
|
||||
version,
|
||||
app_id,
|
||||
imgUrl,
|
||||
licheImgUrl,
|
||||
defaultAvartar,
|
||||
elementScrollTop,
|
||||
bookTmpId,
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
/*!
|
||||
* mp-html v2.4.0
|
||||
* https://github.com/jin-yufeng/mp-html
|
||||
*
|
||||
* Released under the MIT license
|
||||
* Author: Jin Yufeng
|
||||
*/
|
||||
const Parser = require('./parser')
|
||||
const plugins = []
|
||||
|
||||
Component({
|
||||
data: {
|
||||
nodes: []
|
||||
},
|
||||
properties: {
|
||||
/**
|
||||
* @description 容器的样式
|
||||
* @type {String}
|
||||
*/
|
||||
containerStyle: String,
|
||||
|
||||
/**
|
||||
* @description 用于渲染的 html 字符串
|
||||
* @type {String}
|
||||
*/
|
||||
content: {
|
||||
type: String,
|
||||
value: '',
|
||||
observer (content) {
|
||||
this.setContent(content)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 是否允许外部链接被点击时自动复制
|
||||
* @type {Boolean}
|
||||
* @default true
|
||||
*/
|
||||
copyLink: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 主域名,用于拼接链接
|
||||
* @type {String}
|
||||
*/
|
||||
domain: String,
|
||||
|
||||
/**
|
||||
* @description 图片出错时的占位图链接
|
||||
* @type {String}
|
||||
*/
|
||||
errorImg: String,
|
||||
|
||||
/**
|
||||
* @description 是否开启图片懒加载
|
||||
* @type {Boolean}
|
||||
* @default false
|
||||
*/
|
||||
lazyLoad: Boolean,
|
||||
|
||||
/**
|
||||
* @description 图片加载过程中的占位图链接
|
||||
* @type {String}
|
||||
*/
|
||||
loadingImg: String,
|
||||
|
||||
/**
|
||||
* @description 是否在播放一个视频时自动暂停其他视频
|
||||
* @type {Boolean}
|
||||
* @default true
|
||||
*/
|
||||
pauseVideo: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 是否允许图片被点击时自动预览
|
||||
* @type {Boolean}
|
||||
* @default true
|
||||
*/
|
||||
previewImg: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 是否给每个表格添加一个滚动层使其能单独横向滚动
|
||||
* @type {Boolean}
|
||||
* @default false
|
||||
*/
|
||||
scrollTable: Boolean,
|
||||
|
||||
/**
|
||||
* @description 是否开启长按复制
|
||||
* @type {Boolean | String}
|
||||
* @default false
|
||||
*/
|
||||
selectable: null,
|
||||
|
||||
/**
|
||||
* @description 是否将 title 标签的内容设置到页面标题
|
||||
* @type {Boolean}
|
||||
* @default true
|
||||
*/
|
||||
setTitle: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 是否允许图片被长按时显示菜单
|
||||
* @type {Boolean}
|
||||
* @default true
|
||||
*/
|
||||
showImgMenu: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 标签的默认样式
|
||||
* @type {Object}
|
||||
*/
|
||||
tagStyle: Object,
|
||||
|
||||
/**
|
||||
* @description 是否使用锚点链接
|
||||
* @type {Boolean | Number}
|
||||
* @default false
|
||||
*/
|
||||
useAnchor: null
|
||||
},
|
||||
|
||||
created () {
|
||||
this.plugins = []
|
||||
for (let i = plugins.length; i--;) {
|
||||
this.plugins.push(new plugins[i](this))
|
||||
}
|
||||
|
||||
// #ifdef MP-ALIPAY
|
||||
if (this.properties.content) {
|
||||
this.setContent(this.properties.content)
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
|
||||
// #ifdef MP-ALIPAY
|
||||
didUpdate (e) {
|
||||
if (e.content !== this.properties.content) {
|
||||
this.setContent(this.properties.content)
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
|
||||
detached () {
|
||||
// 注销插件
|
||||
this._hook('onDetached')
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* @description 将锚点跳转的范围限定在一个 scroll-view 内
|
||||
* @param {Object} page scroll-view 所在页面的示例
|
||||
* @param {String} selector scroll-view 的选择器
|
||||
* @param {String} scrollTop scroll-view scroll-top 属性绑定的变量名
|
||||
*/
|
||||
in (page, selector, scrollTop) {
|
||||
if (page && selector && scrollTop) {
|
||||
this._in = {
|
||||
page,
|
||||
selector,
|
||||
scrollTop
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 锚点跳转
|
||||
* @param {String} id 要跳转的锚点 id
|
||||
* @param {Number} offset 跳转位置的偏移量
|
||||
* @returns {Promise}
|
||||
*/
|
||||
navigateTo (id, offset) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.properties.useAnchor) {
|
||||
reject(Error('Anchor is disabled'))
|
||||
return
|
||||
}
|
||||
// 跨组件选择器
|
||||
const deep =
|
||||
// #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO
|
||||
'>>>'
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU || MP-ALIPAY
|
||||
' ' // eslint-disable-line
|
||||
// #endif
|
||||
const selector = wx.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this._in ? this._in.page : this)
|
||||
// #endif
|
||||
.select((this._in ? this._in.selector : '._root') + (id ? `${deep}#${id}` : '')).boundingClientRect()
|
||||
if (this._in) {
|
||||
selector.select(this._in.selector).scrollOffset()
|
||||
.select(this._in.selector).boundingClientRect()
|
||||
} else {
|
||||
// 获取 scroll-view 的位置和滚动距离
|
||||
selector.selectViewport().scrollOffset() // 获取窗口的滚动距离
|
||||
}
|
||||
selector.exec(res => {
|
||||
if (!res[0]) {
|
||||
reject(Error('Label not found'))
|
||||
return
|
||||
}
|
||||
const scrollTop = res[1].scrollTop + res[0].top - (res[2] ? res[2].top : 0) + (offset || parseInt(this.properties.useAnchor) || 0)
|
||||
if (this._in) {
|
||||
// scroll-view 跳转
|
||||
this._in.page.setData({
|
||||
[this._in.scrollTop]: scrollTop
|
||||
})
|
||||
} else {
|
||||
// 页面跳转
|
||||
wx.pageScrollTo({
|
||||
scrollTop,
|
||||
duration: 300
|
||||
})
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 获取文本内容
|
||||
* @returns {String}
|
||||
*/
|
||||
getText (nodes) {
|
||||
let text = '';
|
||||
(function traversal (nodes) {
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i]
|
||||
if (node.type === 'text') {
|
||||
text += node.text.replace(/&/g, '&')
|
||||
} else if (node.name === 'br') {
|
||||
text += '\n'
|
||||
} else {
|
||||
// 块级标签前后加换行
|
||||
const isBlock = node.name === 'p' || node.name === 'div' || node.name === 'tr' || node.name === 'li' || (node.name[0] === 'h' && node.name[1] > '0' && node.name[1] < '7')
|
||||
if (isBlock && text && text[text.length - 1] !== '\n') {
|
||||
text += '\n'
|
||||
}
|
||||
// 递归获取子节点的文本
|
||||
if (node.children) {
|
||||
traversal(node.children)
|
||||
}
|
||||
if (isBlock && text[text.length - 1] !== '\n') {
|
||||
text += '\n'
|
||||
} else if (node.name === 'td' || node.name === 'th') {
|
||||
text += '\t'
|
||||
}
|
||||
}
|
||||
}
|
||||
})(nodes || this.data.nodes)
|
||||
return text
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 获取内容大小
|
||||
* @returns {Promise}
|
||||
*/
|
||||
getRect () {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this)
|
||||
// #endif
|
||||
.select('._root').boundingClientRect().exec(res => res[0] ? resolve(res[0]) : reject(Error('Root label not found')))
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 暂停播放媒体
|
||||
*/
|
||||
pauseMedia () {
|
||||
for (let i = (this._videos || []).length; i--;) {
|
||||
this._videos[i].pause()
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 设置媒体播放速率
|
||||
* @param {Number} rate 播放速率
|
||||
*/
|
||||
setPlaybackRate (rate) {
|
||||
this.playbackRate = rate
|
||||
for (let i = (this._videos || []).length; i--;) {
|
||||
this._videos[i].playbackRate(rate)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 设置富文本内容
|
||||
* @param {string} content 要渲染的 html 字符串
|
||||
* @param {boolean} append 是否在尾部追加
|
||||
*/
|
||||
setContent (content, append) {
|
||||
if (!this.imgList || !append) {
|
||||
this.imgList = []
|
||||
}
|
||||
this._videos = []
|
||||
|
||||
const data = {}
|
||||
const nodes = new Parser(this).parse(content)
|
||||
// 尾部追加内容
|
||||
if (append) {
|
||||
for (let i = this.data.nodes.length, j = nodes.length; j--;) {
|
||||
data[`nodes[${i + j}]`] = nodes[j]
|
||||
}
|
||||
} else {
|
||||
data.nodes = nodes
|
||||
}
|
||||
|
||||
this.setData(data,
|
||||
// #ifndef MP-TOUTIAO
|
||||
() => {
|
||||
this._hook('onLoad')
|
||||
this.triggerEvent('load')
|
||||
}
|
||||
// #endif
|
||||
)
|
||||
|
||||
// #ifdef MP-TOUTIAO
|
||||
this.selectComponent('#_root', child => {
|
||||
child.root = this
|
||||
this._hook('onLoad')
|
||||
this.triggerEvent('load')
|
||||
})
|
||||
// #endif
|
||||
|
||||
if (this.properties.lazyLoad || this.imgList._unloadimgs < this.imgList.length / 2) {
|
||||
// 设置懒加载,每 350ms 获取高度,不变则认为加载完毕
|
||||
let height
|
||||
const callback = rect => {
|
||||
// 350ms 总高度无变化就触发 ready 事件
|
||||
if (rect.height === height) {
|
||||
this.triggerEvent('ready', rect)
|
||||
} else {
|
||||
height = rect.height
|
||||
setTimeout(() => {
|
||||
this.getRect().then(callback)
|
||||
}, 350)
|
||||
}
|
||||
}
|
||||
this.getRect().then(callback)
|
||||
} else {
|
||||
// 未设置懒加载,等待所有图片加载完毕
|
||||
if (!this.imgList._unloadimgs) {
|
||||
this.getRect(rect => {
|
||||
this.triggerEvent('ready', rect)
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 调用插件的钩子函数
|
||||
* @private
|
||||
*/
|
||||
_hook (name) {
|
||||
for (let i = plugins.length; i--;) {
|
||||
if (this.plugins[i][name]) {
|
||||
this.plugins[i][name]()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// #ifndef MP-TOUTIAO
|
||||
/**
|
||||
* @description 添加子组件
|
||||
* @private
|
||||
*/
|
||||
_add (e) {
|
||||
e
|
||||
// #ifndef MP-ALIPAY
|
||||
.detail
|
||||
// #endif
|
||||
.root = this
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"node": "./node/node"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<!-- 主组件 -->
|
||||
<view class="_root {{selectable?'_select':''}}" style="{{containerStyle}}">
|
||||
<!-- 加载完成前显示自定义 loading -->
|
||||
<slot wx:if="{{!nodes[0]}}" />
|
||||
<!-- 节点树 -->
|
||||
<node id="_root" childs="{{nodes}}" opts="{{[lazyLoad,loadingImg,errorImg,showImgMenu,selectable]}}" catchadd="_add" />
|
||||
</view>
|
||||
@@ -0,0 +1,2 @@
|
||||
._root{padding:0;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
|
||||
._select{-webkit-user-select:text;user-select:text;}
|
||||
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* @fileoverview 递归子组件,用于显示节点树
|
||||
*/
|
||||
Component({
|
||||
data: {
|
||||
ctrl: {}, // 控制信号
|
||||
// #ifdef MP-WEIXIN
|
||||
isiOS: wx.getSystemInfoSync().system.includes('iOS')
|
||||
// #endif
|
||||
},
|
||||
properties: {
|
||||
childs: Array, // 子节点列表
|
||||
opts: Array // 设置 [是否开启懒加载, 加载中占位图, 错误占位图, 是否使用长按菜单]
|
||||
},
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
// #ifndef MP-TOUTIAO
|
||||
attached () {
|
||||
// #ifndef MP-ALIPAY
|
||||
this.triggerEvent('add', this, {
|
||||
bubbles: true,
|
||||
composed: true
|
||||
})
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
// this.props.onAdd(this)
|
||||
// #endif
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
noop () { },
|
||||
/**
|
||||
* @description 获取标签
|
||||
* @param {String} path 路径
|
||||
*/
|
||||
getNode (path) {
|
||||
try {
|
||||
const nums = path.split('_')
|
||||
let node = this.properties.childs[nums[0]]
|
||||
for (let i = 1; i < nums.length; i++) {
|
||||
node = node.children[nums[i]]
|
||||
}
|
||||
return node
|
||||
} catch {
|
||||
return {
|
||||
text: '',
|
||||
attrs: {},
|
||||
children: []
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @description 播放视频事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
play (e) {
|
||||
this.root.triggerEvent('play')
|
||||
if (this.root.properties.pauseVideo) {
|
||||
let flag = false
|
||||
const id = e.target.id
|
||||
for (let i = this.root._videos.length; i--;) {
|
||||
if (this.root._videos[i].id === id) {
|
||||
flag = true
|
||||
} else {
|
||||
this.root._videos[i].pause() // 自动暂停其他视频
|
||||
}
|
||||
}
|
||||
// 将自己加入列表
|
||||
if (!flag) {
|
||||
const ctx = wx.createVideoContext(id
|
||||
// #ifndef MP-BAIDU
|
||||
, this
|
||||
// #endif
|
||||
)
|
||||
ctx.id = id
|
||||
if (this.root.playbackRate) {
|
||||
ctx.playbackRate(this.root.playbackRate)
|
||||
}
|
||||
this.root._videos.push(ctx)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 图片点击事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
imgTap (e) {
|
||||
const node = this.getNode(e.target.dataset.i)
|
||||
// 父级中有链接
|
||||
if (node.a) return this.linkTap(node.a)
|
||||
if (node.attrs.ignore) return
|
||||
this.root.triggerEvent('imgtap', node.attrs)
|
||||
if (this.root.properties.previewImg) {
|
||||
const current =
|
||||
// #ifndef MP-ALIPAY
|
||||
this.root.imgList[node.i]
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
node.i // eslint-disable-line
|
||||
// #endif
|
||||
// 自动预览图片
|
||||
wx.previewImage({
|
||||
// #ifdef MP-WEIXIN
|
||||
showmenu: this.root.properties.showImgMenu,
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
enablesavephoto: this.root.properties.showImgMenu,
|
||||
enableShowPhotoDownload: this.root.properties.showImgMenu,
|
||||
// #endif
|
||||
current,
|
||||
urls: this.root.imgList
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 图片加载完成事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
imgLoad (e) {
|
||||
const i = e.target.dataset.i
|
||||
const node = this.getNode(i)
|
||||
let val
|
||||
if (!node.w) {
|
||||
val = e.detail.width
|
||||
} else if ((this.properties.opts[1] && !this.data.ctrl[i]) || this.data.ctrl[i] === -1) {
|
||||
// 加载完毕,取消加载中占位图
|
||||
val = 1
|
||||
}
|
||||
if (val
|
||||
// #ifdef MP-TOUTIAO
|
||||
&& val !== this.data.ctrl[i] // eslint-disable-line
|
||||
// #endif
|
||||
) {
|
||||
this.setData({
|
||||
['ctrl.' + i]: val
|
||||
})
|
||||
}
|
||||
this.checkReady()
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 检查是否所有图片加载完毕
|
||||
*/
|
||||
checkReady () {
|
||||
if (!this.root.properties.lazyLoad) {
|
||||
this.root.imgList._unloadimgs -= 1
|
||||
if (!this.root.imgList._unloadimgs) {
|
||||
setTimeout(() => {
|
||||
this.root.getRect().then(rect => {
|
||||
this.root.triggerEvent('ready', rect)
|
||||
})
|
||||
}, 350)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 链接点击事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
linkTap (e) {
|
||||
const node = e.currentTarget ? this.getNode(e.currentTarget.dataset.i) : {}
|
||||
const attrs = node.attrs || e
|
||||
const href = attrs.href
|
||||
this.root.triggerEvent('linktap', Object.assign({
|
||||
innerText: this.root.getText(node.children || []) // 链接内的文本内容
|
||||
}, attrs))
|
||||
if (href) {
|
||||
if (href[0] === '#') {
|
||||
// 跳转锚点
|
||||
this.root.navigateTo(href.substring(1)).catch(() => { })
|
||||
} else if (href.split('?')[0].includes('://')) {
|
||||
// 复制外部链接
|
||||
if (this.root.properties.copyLink) {
|
||||
wx.setClipboardData({
|
||||
data: href,
|
||||
success: () =>
|
||||
wx.showToast({
|
||||
title: '链接已复制'
|
||||
})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 跳转页面
|
||||
wx.navigateTo({
|
||||
url: href,
|
||||
fail () {
|
||||
wx.switchTab({
|
||||
url: href,
|
||||
fail () { }
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 错误事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
mediaError (e) {
|
||||
const i = e.target.dataset.i
|
||||
const node = this.getNode(i)
|
||||
if (node.name === 'video' || node.name === 'audio') {
|
||||
// 加载其他源
|
||||
let index = (this.data.ctrl[i] || 0) + 1
|
||||
if (index > node.src.length) {
|
||||
index = 0
|
||||
}
|
||||
if (index < node.src.length) {
|
||||
return this.setData({
|
||||
['ctrl.' + i]: index
|
||||
})
|
||||
}
|
||||
} else if (node.name === 'img') {
|
||||
// 显示错误占位图
|
||||
if (this.properties.opts[2]) {
|
||||
this.setData({
|
||||
['ctrl.' + i]: -1
|
||||
})
|
||||
}
|
||||
this.checkReady()
|
||||
}
|
||||
if (this.root) {
|
||||
this.root.triggerEvent('error', {
|
||||
source: node.name,
|
||||
attrs: node.attrs,
|
||||
errMsg: e.detail.errMsg
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"node": "./node"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<!-- node 递归子组件 -->
|
||||
<!-- #ifdef MP-WEIXIN || MP-QQ -->
|
||||
<wxs module="isInline">
|
||||
// 行内标签列表
|
||||
var inlineTags = {
|
||||
abbr: true,
|
||||
b: true,
|
||||
big: true,
|
||||
code: true,
|
||||
del: true,
|
||||
em: true,
|
||||
i: true,
|
||||
ins: true,
|
||||
label: true,
|
||||
q: true,
|
||||
small: true,
|
||||
span: true,
|
||||
strong: true,
|
||||
sub: true,
|
||||
sup: true
|
||||
}
|
||||
/**
|
||||
* @description 判断是否为行内标签
|
||||
*/
|
||||
module.exports = function (tagName, style) {
|
||||
return inlineTags[tagName] || (style || '').indexOf('inline') !== -1
|
||||
}
|
||||
</wxs>
|
||||
<!-- #endif -->
|
||||
<template name="el">
|
||||
<!-- 图片 -->
|
||||
<block wx:if="{{n.name==='img'}}">
|
||||
<!-- 表格中的图片,使用 rich-text 防止大小不正确 -->
|
||||
<rich-text wx:if="{{n.t}}" style="display:{{n.t}}" nodes="<img class='_img' style='{{n.attrs.style}}' src='{{n.attrs.src}}'>" data-i="{{i}}" catchtap="imgTap" />
|
||||
<block wx:else>
|
||||
<!-- 占位图 -->
|
||||
<image wx:if="{{(opts[1]&&!ctrl[i])||ctrl[i]<0}}" class="_img _img_block" style="{{n.attrs.style}};" src="{{ctrl[i]<0?opts[2]:opts[1]}}" mode="widthFix" />
|
||||
<!-- 显示图片 -->
|
||||
<image id="{{n.attrs.id}}" class="_img _img_block {{n.attrs.class}}" style="{{ctrl[i]===-1?'display:none;':''}}width:{{ctrl[i]||1}}px;height:1px;{{n.attrs.style}}" src="{{n.attrs.src}}" mode="{{!n.h?'widthFix':(!n.w?'heightFix':'')}}" lazy-load="{{opts[0]}}" webp="{{n.webp}}" show-menu-by-longpress="{{opts[3]&&!n.attrs.ignore}}" mp-baidu:image-menu-prevent="{{!opts[3]||n.attrs.ignore}}" data-i="{{i}}" bindload="imgLoad" binderror="mediaError" catchtap="imgTap" bindlongpress="noop" />
|
||||
</block>
|
||||
</block>
|
||||
<!-- 文本 -->
|
||||
<!-- #ifdef MP-WEIXIN || MP-QQ -->
|
||||
<text wx:elif="{{n.text}}" user-select="{{opts[4]=='force'&&isiOS}}" decode>{{n.text}}</text>
|
||||
<!-- #endif -->
|
||||
<text wx:elif="{{n.name==='br'}}">\n</text>
|
||||
<!-- 链接 -->
|
||||
<view wx:elif="{{n.name==='a'}}" id="{{n.attrs.id}}" class="{{n.attrs.href?'_a ':''}}{{n.attrs.class}}" hover-class="_hover" style="display:inline;{{n.attrs.style}}" data-i="{{i}}" catchtap="linkTap">
|
||||
<!-- #ifdef MP-WEIXIN || MP-QQ -->
|
||||
<node childs="{{n.children}}" opts="{{opts}}" style="display:inherit" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP-BAIDU -->
|
||||
<block wx:for="{{n.children}}" wx:key="index">
|
||||
<template is="el" data="{{n:item,i:i+'_'+index,opts:opts,ctrl:ctrl}}"></template>
|
||||
</block>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP-ALIPAY || MP-TOUTIAO -->
|
||||
<template is="node" data="{{childs:n.children,path:i+'_',opts:opts,ctrl:ctrl}}"></template>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<!-- 视频 -->
|
||||
<video wx:elif="{{n.name==='video'}}" id="{{n.attrs.id}}" class="{{n.attrs.class}}" style="{{n.attrs.style}}" autoplay="{{n.attrs.autoplay}}" controls="{{n.attrs.controls}}" loop="{{n.attrs.loop}}" muted="{{n.attrs.muted}}" object-fit="{{n.attrs['object-fit']}}" poster="{{n.attrs.poster}}" src="{{n.src[ctrl[i]||0]}}" data-i="{{i}}" bindplay="play" binderror="mediaError" />
|
||||
<!-- #ifndef MP-TOUTIAO -->
|
||||
<!-- 音频 -->
|
||||
<audio wx:elif="{{n.name==='audio'}}" id="{{n.attrs.id}}" class="{{n.attrs.class}}" style="{{n.attrs.style}}" author="{{n.attrs.author}}" controls="{{n.attrs.controls}}" loop="{{n.attrs.loop}}" name="{{n.attrs.name}}" poster="{{n.attrs.poster}}" src="{{n.src[ctrl[i]||0]}}" data-i="{{i}}" bindplay="play" binderror="mediaError" />
|
||||
<!-- #endif -->
|
||||
<!-- insert -->
|
||||
<!-- 富文本 -->
|
||||
<rich-text wx:else id="{{n.attrs.id}}" mp-baidu:mp-toutiao:style="{{n.f}}" mp-alipay:style="{{n.f}};display:inline" mp-baidu:selectable="{{opts[4]}}" user-select="{{opts[4]}}" nodes="{{[n]}}" />
|
||||
</template>
|
||||
<!-- #ifdef MP-ALIPAY || MP-TOUTIAO -->
|
||||
<!-- <template name="node">
|
||||
<block wx:for="{{childs}}" wx:for-item="n" wx:for-index="i" wx:key="i">
|
||||
<template wx:if="{{!n.c}}" is="el" data="{{n:n,i:path+i,opts:opts,ctrl:ctrl}}" />
|
||||
<view wx:else id="{{n.attrs.id}}" class="_{{n.name}} {{n.attrs.class}}" style="{{n.attrs.style}}">
|
||||
<template is="node" data="{{childs:n.children,path:path+i+'_',opts:opts,ctrl:ctrl}}"></template>
|
||||
</view>
|
||||
</block>
|
||||
</template>
|
||||
<template is="node" data="{{childs:childs,path:'',opts:opts,ctrl:ctrl}}"></template> -->
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-ALIPAY || MP-TOUTIAO -->
|
||||
<!-- 第 1 层 -->
|
||||
<block wx:for="{{childs}}" wx:for-item="n1" wx:for-index="i1" wx:key="i1">
|
||||
<template wx:if="{{!n1.c&&(!n1.children||n1.name==='a'||!isInline(n1.name,n1.attrs.style))}}" mp-baidu:wx:if="{{!n1.c}}" is="el" data="{{n:n1,i:''+i1,opts:opts,ctrl:ctrl}}" />
|
||||
<view wx:else id="{{n1.attrs.id}}" class="_{{n1.name}} {{n1.attrs.class}}" style="{{n1.attrs.style}}">
|
||||
<!-- 第 2 层 -->
|
||||
<block wx:for="{{n1.children}}" wx:for-item="n2" wx:for-index="i2" wx:key="i2">
|
||||
<template wx:if="{{!n2.c&&(!n2.children||n2.name==='a'||!isInline(n2.name,n2.attrs.style))}}" mp-baidu:wx:if="{{!n2.c}}" is="el" data="{{n:n2,i:i1+'_'+i2,opts:opts,ctrl:ctrl}}" />
|
||||
<view wx:else id="{{n2.attrs.id}}" class="_{{n2.name}} {{n2.attrs.class}}" style="{{n2.attrs.style}}">
|
||||
<!-- 第 3 层 -->
|
||||
<block wx:for="{{n2.children}}" wx:for-item="n3" wx:for-index="i3" wx:key="i3">
|
||||
<template wx:if="{{!n3.c&&(!n3.children||n3.name==='a'||!isInline(n3.name,n3.attrs.style))}}" mp-baidu:wx:if="{{!n3.c}}" is="el" data="{{n:n3,i:i1+'_'+i2+'_'+i3,opts:opts,ctrl:ctrl}}" />
|
||||
<view wx:else id="{{n3.attrs.id}}" class="_{{n3.name}} {{n3.attrs.class}}" style="{{n3.attrs.style}}">
|
||||
<!-- 第 4 层 -->
|
||||
<block wx:for="{{n3.children}}" wx:for-item="n4" wx:for-index="i4" wx:key="i4">
|
||||
<template wx:if="{{!n4.c&&(!n4.children||n4.name==='a'||!isInline(n4.name,n4.attrs.style))}}" mp-baidu:wx:if="{{!n4.c}}" is="el" data="{{n:n4,i:i1+'_'+i2+'_'+i3+'_'+i4,opts:opts,ctrl:ctrl}}" />
|
||||
<view wx:else id="{{n4.attrs.id}}" class="_{{n4.name}} {{n4.attrs.class}}" style="{{n4.attrs.style}}">
|
||||
<!-- 第 5 层 -->
|
||||
<block wx:for="{{n4.children}}" wx:for-item="n5" wx:for-index="i5" wx:key="i5">
|
||||
<template wx:if="{{!n5.c&&(!n5.children||n5.name==='a'||!isInline(n5.name,n5.attrs.style))}}" mp-baidu:wx:if="{{!n5.c}}" is="el" data="{{n:n5,i:i1+'_'+i2+'_'+i3+'_'+i4+'_'+i5,opts:opts,ctrl:ctrl}}" />
|
||||
<node wx:else id="{{n5.attrs.id}}" class="_{{n5.name}} {{n5.attrs.class}}" style="{{n5.attrs.style}}" childs="{{n5.children}}" opts="{{opts}}" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
<!-- #endif -->
|
||||
@@ -0,0 +1,169 @@
|
||||
/* a 标签默认效果 */
|
||||
._a {
|
||||
padding: 1.5px 0 1.5px 0;
|
||||
color: #366092;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* a 标签点击态效果 */
|
||||
._hover {
|
||||
text-decoration: underline;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* 图片默认效果 */
|
||||
._img {
|
||||
max-width: 100%;
|
||||
-webkit-touch-callout: none;
|
||||
vertical-align:top;
|
||||
margin-bottom: -2rpx;
|
||||
}
|
||||
._img_block{
|
||||
/* display: block!important; */
|
||||
}
|
||||
|
||||
/* 内部样式 */
|
||||
|
||||
._b,
|
||||
._strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
._code {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
._del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
._em,
|
||||
._i {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
._h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
._h2 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
._h3 {
|
||||
font-size: 1.17em;
|
||||
}
|
||||
|
||||
._h5 {
|
||||
font-size: 0.83em;
|
||||
}
|
||||
|
||||
._h6 {
|
||||
font-size: 0.67em;
|
||||
}
|
||||
|
||||
._h1,
|
||||
._h2,
|
||||
._h3,
|
||||
._h4,
|
||||
._h5,
|
||||
._h6 {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
._ins {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
._li {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
._ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
._ol,
|
||||
._ul {
|
||||
display: block;
|
||||
padding-left: 40px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
._q::before {
|
||||
content: '"';
|
||||
}
|
||||
|
||||
._q::after {
|
||||
content: '"';
|
||||
}
|
||||
|
||||
._sub {
|
||||
font-size: smaller;
|
||||
vertical-align: sub;
|
||||
}
|
||||
|
||||
._sup {
|
||||
font-size: smaller;
|
||||
vertical-align: super;
|
||||
}
|
||||
|
||||
._thead,
|
||||
._tbody,
|
||||
._tfoot {
|
||||
display: table-row-group;
|
||||
}
|
||||
|
||||
._tr {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
._td,
|
||||
._th {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
._th {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
._ul {
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
._ul ._ul {
|
||||
margin: 0;
|
||||
list-style-type: circle;
|
||||
}
|
||||
|
||||
._ul ._ul ._ul {
|
||||
list-style-type: square;
|
||||
}
|
||||
|
||||
._abbr,
|
||||
._b,
|
||||
._code,
|
||||
._del,
|
||||
._em,
|
||||
._i,
|
||||
._ins,
|
||||
._label,
|
||||
._q,
|
||||
._span,
|
||||
._strong,
|
||||
._sub,
|
||||
._sup {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* #ifndef MP-ALIPAY || MP-TOUTIAO */
|
||||
._blockquote,
|
||||
._div,
|
||||
._p {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -66,6 +66,29 @@ Page({
|
||||
// '修改【保单上传】的相应内容,上传后需补充相应保单信息。',
|
||||
],
|
||||
},
|
||||
//0924 新增参数
|
||||
data_bg_img: _.config.licheImgUrl + 'score/index-panel-bg.png',
|
||||
icon_trend_up: _.config.licheImgUrl + 'score/score-trend-up.png',
|
||||
icon_trend_down: _.config.licheImgUrl + 'score/score-trend-down.png',
|
||||
icon_score_top_1: _.config.licheImgUrl + 'score/score-top-1.png',
|
||||
icon_score_top_2: _.config.licheImgUrl + 'score/score-top-2.png',
|
||||
icon_score_top_3: _.config.licheImgUrl + 'score/score-top-3.png',
|
||||
score_index_bg_up: _.config.licheImgUrl + 'score/score-bg-up.jpg',
|
||||
score_index_bg_down: _.config.licheImgUrl + 'score/score-bg-down.jpg',
|
||||
score_detail_bg_up: _.config.licheImgUrl + 'score/score-detail-up.png',
|
||||
score_detail_bg_down: _.config.licheImgUrl + 'score/score-detail-up.jpg',
|
||||
score_up_color: '#31cbad',
|
||||
score_down_color: '#ff895b',
|
||||
score_trend: 1, //用这个参数控制样式:1 上升 、2 下降
|
||||
score_role_tab: [{
|
||||
id: 1,
|
||||
name: '个人'
|
||||
},{
|
||||
id: 2,
|
||||
name: '门店'
|
||||
}],
|
||||
score_role_cur: 0
|
||||
//0924 end
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
@@ -518,6 +541,13 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
//0924
|
||||
changeScoreRoleTab(e){
|
||||
this.setData({
|
||||
score_role_cur:e.currentTarget.dataset.index
|
||||
})
|
||||
},
|
||||
|
||||
//页面相关事件处理函数--监听用户下拉动作
|
||||
onPullDownRefresh: function () {
|
||||
this.setData({
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"backgroundColor": "#ffffff",
|
||||
"backgroundColorTop": "#1a1c26",
|
||||
"usingComponents": {
|
||||
"ec-canvas": "../../ecCanvas/components/ec-canvas/ec-canvas"
|
||||
"ec-canvas": "../../ecCanvas/components/ec-canvas/ec-canvas",
|
||||
"van-circle": "/vant/circle/index"
|
||||
}
|
||||
}
|
||||
+42
-5
@@ -39,14 +39,13 @@
|
||||
</view>
|
||||
</view>
|
||||
<!-- 数据看板 -->
|
||||
<view class="bg-fff mb30 inner30 box-shadow-000-10-10 ulib-r10">
|
||||
<view class="bg-fff mb30 box-shadow-000-10-10 ulib-r10 bg-size-fullwidth bg-no-repeat bg-pos-top" style="background-image:url({{data_bg_img}});">
|
||||
<view class="inner30">
|
||||
<view bindtap="pushLink" data-url="/pages/storeData/index" wx:if="{{userInfo.group_id>1}}">
|
||||
<view class="fn-flex fn-flex-middle">
|
||||
<text class="font-36">数据看板</text>
|
||||
<text class="font-36">今日看榜</text>
|
||||
<view class="fn-flex-item text-right pt10">
|
||||
<view class="font-22 color-999">详细
|
||||
<i class="iconfont icon-gengduo ml5 text-middle font-26"></i>
|
||||
</view>
|
||||
<view class="font-22 color-999">详情<i class="iconfont icon-gengduo ml5 text-middle font-26"></i></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -59,6 +58,44 @@
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 0924 新增运营分 up:#31cbad, down:#ff895b-->
|
||||
<view class="relative inner30" style="--circle-text-color:{{score_trend>1?score_down_color:score_up_color}};--linearcolor:{{score_trend>1?score_down_color:score_up_color}};">
|
||||
<view class="absolute left-0 top-0 right-0 bottom-0 bg-custom-linear-bottom opacity-10"></view>
|
||||
<view class="fn-flex fn-flex-middle fn-flex-between relative">
|
||||
<text class="font-36">最新运营分</text>
|
||||
<view class="text-right pt10">
|
||||
<view class="ulib-r10 fn-flex overflowhidden font-24">
|
||||
<block wx:for="{{score_role_tab}}" wx:key="index">
|
||||
<view data-index="{{index}}" bindtap="changeScoreRoleTab" class="{{score_role_cur===index?'bg-ccc':'bg-fff'}} transition-all pl15 pr15 pt5 pb5">{{item.name}}</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="fn-flex fn-flex-middle pt20 pb20 relative">
|
||||
<view class="mr20 pt20">
|
||||
<van-circle
|
||||
value="{{ 30 }}"
|
||||
stroke-width="10"
|
||||
text="50"
|
||||
layer-color="#ebebeb"
|
||||
size="60"
|
||||
color="{{score_trend>1?score_down_color:score_up_color}}"></van-circle>
|
||||
</view>
|
||||
<view class="fn-flex-item line-height-16">
|
||||
<view class="fn-flex fn-flex-middle font-30">
|
||||
<image src="{{score_trend>1?icon_trend_down:icon_trend_up}}" class="img-28x28 block mr10"/>
|
||||
<text>较上日上升100分</text>
|
||||
</view>
|
||||
<view class="font-24 color-999">
|
||||
<view>*更新于09月10日</view>
|
||||
<view>当前显示为昨日运营情况评分</view>
|
||||
</view>
|
||||
</view>
|
||||
<view data-url="" bindtap="pushLink" class="font-30 color-999 text-middle"><text>详情</text><i class="iconfont icon-gengduo ml5 font-30"></i></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 0924 end -->
|
||||
</view>
|
||||
<!--客户代办事项-->
|
||||
<view class="bg-fff mb30 box-shadow-000-10-10 ulib-r10">
|
||||
<!-- <view class="bg-ffedeb ulib-rt10" style="height:140rpx;" wx:if="{{remindTab.length > 0}}">
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
// pages/score/detail.js
|
||||
import _ from '../../commons/js/commons'
|
||||
const app = getApp()
|
||||
Page({
|
||||
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
data_bg_img: _.config.licheImgUrl + 'score/index-panel-bg.png',
|
||||
icon_trend_up: _.config.licheImgUrl + 'score/score-trend-up.png',
|
||||
icon_trend_down: _.config.licheImgUrl + 'score/score-trend-down.png',
|
||||
icon_score_top_1: _.config.licheImgUrl + 'score/score-top-1.png',
|
||||
icon_score_top_2: _.config.licheImgUrl + 'score/score-top-2.png',
|
||||
icon_score_top_3: _.config.licheImgUrl + 'score/score-top-3.png',
|
||||
score_index_bg_up: _.config.licheImgUrl + 'score/score-bg-up.jpg',
|
||||
score_index_bg_down: _.config.licheImgUrl + 'score/score-bg-down.jpg',
|
||||
score_detail_bg_up: _.config.licheImgUrl + 'score/score-detail-up.png',
|
||||
score_detail_bg_down: _.config.licheImgUrl + 'score/score-detail-down.png',
|
||||
score_up_color: '#31cbad',
|
||||
score_down_color: '#ff895b',
|
||||
score_trend: 1, //用这个参数控制样式:1 上升 、2 下降
|
||||
list: [{
|
||||
name: '基础分',
|
||||
score: 60,
|
||||
trend: 1,
|
||||
data: [{
|
||||
name: '正常开工',
|
||||
score: '+180'
|
||||
}]
|
||||
}, {
|
||||
name: '线索分',
|
||||
score: 660,
|
||||
trend: 1,
|
||||
data: [{
|
||||
name: '线索建档',
|
||||
score: '+180'
|
||||
},{
|
||||
name: '添加微信',
|
||||
score: '+180'
|
||||
},{
|
||||
name: '跟进小记',
|
||||
score: '+180'
|
||||
},{
|
||||
name: '语音通话',
|
||||
score: '+180'
|
||||
},{
|
||||
name: '二次派发',
|
||||
score: '+180'
|
||||
},{
|
||||
name: '首次跟进',
|
||||
score: '+180'
|
||||
}]
|
||||
}, {
|
||||
name: '订单分',
|
||||
score: 260,
|
||||
trend: 1,
|
||||
data: [{
|
||||
name: '成交数',
|
||||
score: '+180'
|
||||
},{
|
||||
name: '成交率',
|
||||
score: '+180'
|
||||
},{
|
||||
name: '开票率',
|
||||
score: '+180'
|
||||
},{
|
||||
name: '交付率',
|
||||
score: '+180'
|
||||
}]
|
||||
}, {
|
||||
name: '扣分项',
|
||||
score: 260,
|
||||
trend: 2,
|
||||
data: [{
|
||||
name: '逾期未跟进',
|
||||
score: '-80'
|
||||
},{
|
||||
name: '战败未处理',
|
||||
score: '-180'
|
||||
},{
|
||||
name: '开票后录单',
|
||||
score: '-180'
|
||||
},{
|
||||
name: '建档即订单',
|
||||
score: '-180'
|
||||
}]
|
||||
}]
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad(options) {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<!-- pages/score/detail.wxml -->
|
||||
<view class="container relative" style="min-height:100vh;--circle-text-color:{{score_trend>1?score_down_color:score_up_color}};--linearcolor:{{score_trend>1?score_down_color:score_up_color}};">
|
||||
<view class="absolute left-0 top-0 right-0 bg-custom-linear-bottom opacity-60" style="height:10vh;"></view>
|
||||
<view class="relative">
|
||||
<view class="inner40 relative fn-flex fn-flex-middle fn-flex-between">
|
||||
<view class="text-left">
|
||||
<view class="font-28 color-666">昨日运营分</view>
|
||||
<view class="font-72" style="color:{{score_trend>1?score_down_color:score_up_color}}">798</view>
|
||||
</view>
|
||||
<view class="text-right">
|
||||
<view class="font-28 color-666">上一日运营分</view>
|
||||
<view class="font-72" style="color:{{score_trend>1?score_down_color:score_up_color}}">798</view>
|
||||
</view>
|
||||
<view
|
||||
class="ulib-r750 fn-flex fn-flex-middle absolute box-center-middle font-28 pl20 pr20 pt10 pb10 overflowhidden"
|
||||
style="border:2rpx solid {{score_trend>1?score_down_color:score_up_color}};"
|
||||
>
|
||||
<view class="absolute left-0 top-0 right-0 bottom-0 opacity-10" style="background-color:var(--circle-text-color);"></view>
|
||||
<image src="{{score_trend>1?icon_trend_down:icon_trend_up}}" class="relative img-28x28 block mr10"/>
|
||||
<text class="color-666 relative">较上日上升100分</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="ml30 mr30 pb30">
|
||||
<view class="font-40 text-center color-333 mb30">本期分数组成</view>
|
||||
<view class="bg-fff box-shadow-000-10-10 ulib-r10">
|
||||
<block wx:for="{{list}}" wx:key="index">
|
||||
<view class="inner40 bbs-1-f6 fn-flex fn-flex-middle">
|
||||
<view class="mr100 relative" style="width:154rpx;height:120rpx;">
|
||||
<image class="img-154x154 block" src="{{item.trend>1?score_detail_bg_down:score_detail_bg_up}}" />
|
||||
<text class="absolute wp100 box-center-middle text-center font-52" style="color:{{item.trend>1?score_down_color:score_up_color}}">{{item.score}}</text>
|
||||
<text class="absolute wp100 left-0 text-center bottom-0 font-24 color-888">{{item.name}}</text>
|
||||
</view>
|
||||
<view class="fn-flex-item">
|
||||
<block wx:for="{{item.data}}" wx:for-item="it" wx:for-index="idx" wx:key="idx">
|
||||
<view class="fn-flex fn-flex-middle fn-flex-between pt10 pb10 font-26 color-666">
|
||||
<view >{{it.name}}</view>
|
||||
<view >{{it.score}}</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1 @@
|
||||
/* pages/score/detail.wxss */
|
||||
@@ -0,0 +1,187 @@
|
||||
// pages/score/index.js
|
||||
import _ from '../../commons/js/commons'
|
||||
const app = getApp()
|
||||
Page({
|
||||
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
data_bg_img: _.config.licheImgUrl + 'score/index-panel-bg.png',
|
||||
icon_trend_up: _.config.licheImgUrl + 'score/score-trend-up.png',
|
||||
icon_trend_down: _.config.licheImgUrl + 'score/score-trend-down.png',
|
||||
icon_score_top_1: _.config.licheImgUrl + 'score/score-top-1.png',
|
||||
icon_score_top_2: _.config.licheImgUrl + 'score/score-top-2.png',
|
||||
icon_score_top_3: _.config.licheImgUrl + 'score/score-top-3.png',
|
||||
score_index_bg_up: _.config.licheImgUrl + 'score/score-bg-up.jpg',
|
||||
score_index_bg_down: _.config.licheImgUrl + 'score/score-bg-down.jpg',
|
||||
score_detail_bg_up: _.config.licheImgUrl + 'score/score-detail-up.png',
|
||||
score_detail_bg_down: _.config.licheImgUrl + 'score/score-detail-up.jpg',
|
||||
score_up_color: '#31cbad',
|
||||
score_down_color: '#ff895b',
|
||||
score_trend: 1, //用这个参数控制样式:1 上升 、2 下降
|
||||
tab_date: [{
|
||||
id: 1,
|
||||
name: '昨日'
|
||||
}, {
|
||||
id: 2,
|
||||
name: '本月'
|
||||
}],
|
||||
tab_date_cur: 0,
|
||||
|
||||
score_detail_data: [{
|
||||
name: '998',
|
||||
tip: '运营分'
|
||||
}, {
|
||||
name: '=',
|
||||
tip: ''
|
||||
}, {
|
||||
name: '98',
|
||||
tip: '运营分'
|
||||
}, {
|
||||
name: '+',
|
||||
tip: ''
|
||||
}, {
|
||||
name: '98',
|
||||
tip: '运营分'
|
||||
}, {
|
||||
name: '+',
|
||||
tip: ''
|
||||
}, {
|
||||
name: '98',
|
||||
tip: '运营分'
|
||||
}, {
|
||||
name: '+',
|
||||
tip: ''
|
||||
}, {
|
||||
name: '98',
|
||||
tip: '运营分'
|
||||
}],
|
||||
|
||||
tab_rank: [{
|
||||
id: 1,
|
||||
name: '店内排名'
|
||||
}, {
|
||||
id: 2,
|
||||
name: '门店排名'
|
||||
}],
|
||||
tab_rank_cur: 0,
|
||||
rank_data: [{
|
||||
name: '张三',
|
||||
is_manager: true,
|
||||
trend: 1, //1 上升 、2 下降
|
||||
score: '180分'
|
||||
}, {
|
||||
name: '张三',
|
||||
is_manager: false,
|
||||
trend: 2, //1 上升 、2 下降
|
||||
score: '5分'
|
||||
}, {
|
||||
name: '张三',
|
||||
is_manager: false,
|
||||
trend: 2, //1 上升 、2 下降
|
||||
score: '80分'
|
||||
}, {
|
||||
name: '张三',
|
||||
is_manager: false,
|
||||
trend: 1, //1 上升 、2 下降
|
||||
score: '80分'
|
||||
}, {
|
||||
name: '张三',
|
||||
is_manager: false,
|
||||
trend: 2, //1 上升 、2 下降
|
||||
score: '5分'
|
||||
}, {
|
||||
name: '张三',
|
||||
is_manager: false,
|
||||
trend: 2, //1 上升 、2 下降
|
||||
score: '80分'
|
||||
}, {
|
||||
name: '张三',
|
||||
is_manager: false,
|
||||
trend: 1, //1 上升 、2 下降
|
||||
score: '80分'
|
||||
}, {
|
||||
name: '张三',
|
||||
is_manager: false,
|
||||
trend: 2, //1 上升 、2 下降
|
||||
score: '5分'
|
||||
}, {
|
||||
name: '张三',
|
||||
is_manager: false,
|
||||
trend: 2, //1 上升 、2 下降
|
||||
score: '80分'
|
||||
}, {
|
||||
name: '张三',
|
||||
is_manager: false,
|
||||
trend: 1, //1 上升 、2 下降
|
||||
score: '80分'
|
||||
}],
|
||||
content: '<p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p><p>asdfasdf</p>',
|
||||
setid: ''
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad(options) {
|
||||
wx.setNavigationBarTitle({
|
||||
'title': '个人运营分'
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
|
||||
},
|
||||
|
||||
scrollToRule(){
|
||||
this.setData({
|
||||
setid: 'richhtml'
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"van-circle": "/vant/circle/index",
|
||||
"com-html": "/components/mp-html/index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<!-- pages/score/index.wxml -->
|
||||
<view class="container relative" style="min-height:100vh;--circle-text-color:{{score_trend>1?score_down_color:score_up_color}};">
|
||||
<scroll-view class="relative" scroll-y="{{true}}" scroll-into-view="{{setid}}" scroll-with-animation="{{true}}" style="height:100vh">
|
||||
<view class="absolute left-0 top-0 bottom-0 right-0 bg-size-fullwidth bg-no-repeat bg-pos-top" style="background-image:url({{score_trend>1?score_index_bg_down:score_index_bg_up}});"></view>
|
||||
<view class="relative inner30">
|
||||
<view class="fn-flex fn-flex-middle fn-flex-between inner20">
|
||||
<view class="fn-flex">
|
||||
<block wx:for="{{tab_date}}" wx:key="index">
|
||||
<view class="font-34 relative {{(tab_date.length-1)==index?'':'mr70'}} tab-item transition-all {{tab_date_cur==index?'tab-item-cur':'color-999'}}">{{item.name}}</view>
|
||||
</block>
|
||||
</view>
|
||||
<view wx:if="{{content}}" bindtap="scrollToRule" class="font-20 ulib-r750 bg-f6 color-999 pt5 pb5 pl10 pr10">
|
||||
<text class="iconfont icon-tishi mr5"></text><text>规则说明</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="fn-flex fn-flex-column fn-flex-middle mb40">
|
||||
<view class="font-66 text-bold pt30">
|
||||
<van-circle
|
||||
value="{{ 30 }}"
|
||||
stroke-width="15"
|
||||
text="500"
|
||||
layer-color="#ebebeb"
|
||||
size="120"
|
||||
color="{{score_trend>1?score_down_color:score_up_color}}"></van-circle>
|
||||
</view>
|
||||
<view class="fn-flex fn-flex-middle fn-flex-center pt30 color-666 font-32">
|
||||
<image src="{{score_trend>1?icon_trend_down:icon_trend_up}}" class="img-32x32 block mr10"/>
|
||||
<text>较上日上升100分</text>
|
||||
</view>
|
||||
<view class="fn-flex fn-flex-middle fn-flex-center pt15 font-26 color-999">
|
||||
<view>*更新于09月10日</view>
|
||||
<view>当前显示为昨日运营情况评分</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bg-fff mb30 box-shadow-000-10-10 ulib-r10 pt40 pb40">
|
||||
<view class="fn-flex fn-flex-middle fn-flex-center text-center">
|
||||
<block wx:for="{{score_detail_data}}" wx:key="index">
|
||||
<view class="pr15 pl15">
|
||||
<view class="font-34">{{item.name}}</view>
|
||||
<view class="mt5 color-666 font-22">{{item.tip}}</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="text-center pt20">
|
||||
<view class="ulib-r10 font-24 link-detail relative link-detail inline-block pt10 pb10 pl20 pr20 overflowhidden"><text>查看明细</text><text class="iconfont icon-gengduo ml5"></text></view>
|
||||
</view>
|
||||
|
||||
<view class="text-center pt40">
|
||||
<view class="ulib-r10 overflowhidden font-24 inline-block">
|
||||
<block wx:for="{{tab_rank}}" wx:key="index">
|
||||
<view data-index="{{index}}" bindtap="changeRankTab" class="{{tab_rank_cur===index?'bg-ccc color-666':'bg-f6 color-999'}} transition-all pl20 pr20 pt10 pb10 inline-block">{{item.name}}</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="">
|
||||
<block wx:for="{{rank_data}}" wx:key="index">
|
||||
<view class="fn-flex fn-flex-middle fn-flex-between pt25 pb25 pl60 pr60">
|
||||
<view class="fn-flex fn-flex-middle font-28 color-444">
|
||||
<text class="text-center mr20" style="width:38rpx;" wx:if="{{index>2}}">{{index+1}}</text>
|
||||
<image wx:else class="img-38x38 mr20" src="{{index==0?icon_score_top_1:index==1?icon_score_top_2:icon_score_top_3}}" />
|
||||
<text>{{item.name}}</text>
|
||||
<view class="ulib-r750 color-fff font-20 pl15 pr15 pb5 ml15" style="background-color:{{score_up_color}};" wx:if="{{item.is_manager}}">店长</view>
|
||||
</view>
|
||||
<view class="fn-flex fn-flex-middle font-28 color-666" style="width:130rpx;">
|
||||
<image src="{{item.trend>1?icon_trend_down:icon_trend_up}}" class="img-32x32 block mr10"/>
|
||||
<text>{{item.score}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view wx:if="{{content}}" id="richhtml" class="bg-fff mb30 box-shadow-000-10-10 ulib-r10 inner40">
|
||||
<com-html content="{{content}}" lazy-load="{{true}}"></com-html>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
@@ -0,0 +1,34 @@
|
||||
/* pages/score/index.wxss */
|
||||
.tab-item::before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -12rpx;
|
||||
left:50%;
|
||||
transform: translateX(-50%);
|
||||
width: 0;
|
||||
height: 6rpx;
|
||||
border-radius: 100rpx;
|
||||
background-color: var(--circle-text-color);
|
||||
}
|
||||
.tab-item-cur{
|
||||
color: var(--circle-text-color);
|
||||
}
|
||||
.tab-item-cur::before{
|
||||
width: 50rpx;
|
||||
}
|
||||
|
||||
.link-detail{
|
||||
color: var(--circle-text-color);
|
||||
/* background-color: ; */
|
||||
}
|
||||
|
||||
.link-detail::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: var(--circle-text-color);
|
||||
opacity: 0.1;
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
type CanvasContext = WechatMiniprogram.CanvasContext;
|
||||
export declare function adaptor(ctx: CanvasContext & Record<string, unknown>): CanvasContext;
|
||||
export {};
|
||||
@@ -0,0 +1,43 @@
|
||||
export function adaptor(ctx) {
|
||||
// @ts-ignore
|
||||
return Object.assign(ctx, {
|
||||
setStrokeStyle(val) {
|
||||
ctx.strokeStyle = val;
|
||||
},
|
||||
setLineWidth(val) {
|
||||
ctx.lineWidth = val;
|
||||
},
|
||||
setLineCap(val) {
|
||||
ctx.lineCap = val;
|
||||
},
|
||||
setFillStyle(val) {
|
||||
ctx.fillStyle = val;
|
||||
},
|
||||
setFontSize(val) {
|
||||
ctx.font = String(val);
|
||||
},
|
||||
setGlobalAlpha(val) {
|
||||
ctx.globalAlpha = val;
|
||||
},
|
||||
setLineJoin(val) {
|
||||
ctx.lineJoin = val;
|
||||
},
|
||||
setTextAlign(val) {
|
||||
ctx.textAlign = val;
|
||||
},
|
||||
setMiterLimit(val) {
|
||||
ctx.miterLimit = val;
|
||||
},
|
||||
setShadow(offsetX, offsetY, blur, color) {
|
||||
ctx.shadowOffsetX = offsetX;
|
||||
ctx.shadowOffsetY = offsetY;
|
||||
ctx.shadowBlur = blur;
|
||||
ctx.shadowColor = color;
|
||||
},
|
||||
setTextBaseline(val) {
|
||||
ctx.textBaseline = val;
|
||||
},
|
||||
createCircularGradient() { },
|
||||
draw() { },
|
||||
});
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,197 @@
|
||||
import { BLUE, WHITE } from '../common/color';
|
||||
import { VantComponent } from '../common/component';
|
||||
import { getSystemInfoSync } from '../common/utils';
|
||||
import { isObj } from '../common/validator';
|
||||
import { canIUseCanvas2d } from '../common/version';
|
||||
import { adaptor } from './canvas';
|
||||
function format(rate) {
|
||||
return Math.min(Math.max(rate, 0), 100);
|
||||
}
|
||||
const PERIMETER = 2 * Math.PI;
|
||||
const BEGIN_ANGLE = -Math.PI / 2;
|
||||
const STEP = 1;
|
||||
VantComponent({
|
||||
props: {
|
||||
text: String,
|
||||
lineCap: {
|
||||
type: String,
|
||||
value: 'round',
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
observer: 'reRender',
|
||||
},
|
||||
speed: {
|
||||
type: Number,
|
||||
value: 50,
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
value: 100,
|
||||
observer() {
|
||||
this.drawCircle(this.currentValue);
|
||||
},
|
||||
},
|
||||
fill: String,
|
||||
layerColor: {
|
||||
type: String,
|
||||
value: WHITE,
|
||||
},
|
||||
color: {
|
||||
type: null,
|
||||
value: BLUE,
|
||||
observer() {
|
||||
this.setHoverColor().then(() => {
|
||||
this.drawCircle(this.currentValue);
|
||||
});
|
||||
},
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
strokeWidth: {
|
||||
type: Number,
|
||||
value: 4,
|
||||
},
|
||||
clockwise: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
hoverColor: BLUE,
|
||||
},
|
||||
methods: {
|
||||
getContext() {
|
||||
const { type, size } = this.data;
|
||||
if (type === '' || !canIUseCanvas2d()) {
|
||||
const ctx = wx.createCanvasContext('van-circle', this);
|
||||
return Promise.resolve(ctx);
|
||||
}
|
||||
const dpr = getSystemInfoSync().pixelRatio;
|
||||
return new Promise((resolve) => {
|
||||
wx.createSelectorQuery()
|
||||
.in(this)
|
||||
.select('#van-circle')
|
||||
.node()
|
||||
.exec((res) => {
|
||||
const canvas = res[0].node;
|
||||
const ctx = canvas.getContext(type);
|
||||
if (!this.inited) {
|
||||
this.inited = true;
|
||||
canvas.width = size * dpr;
|
||||
canvas.height = size * dpr;
|
||||
ctx.scale(dpr, dpr);
|
||||
}
|
||||
resolve(adaptor(ctx));
|
||||
});
|
||||
});
|
||||
},
|
||||
setHoverColor() {
|
||||
const { color, size } = this.data;
|
||||
if (isObj(color)) {
|
||||
return this.getContext().then((context) => {
|
||||
if (!context)
|
||||
return;
|
||||
const LinearColor = context.createLinearGradient(size, 0, 0, 0);
|
||||
Object.keys(color)
|
||||
.sort((a, b) => parseFloat(a) - parseFloat(b))
|
||||
.map((key) => LinearColor.addColorStop(parseFloat(key) / 100, color[key]));
|
||||
this.hoverColor = LinearColor;
|
||||
});
|
||||
}
|
||||
this.hoverColor = color;
|
||||
return Promise.resolve();
|
||||
},
|
||||
presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) {
|
||||
const { strokeWidth, lineCap, clockwise, size } = this.data;
|
||||
const position = size / 2;
|
||||
const radius = position - strokeWidth / 2;
|
||||
context.setStrokeStyle(strokeStyle);
|
||||
context.setLineWidth(strokeWidth);
|
||||
context.setLineCap(lineCap);
|
||||
context.beginPath();
|
||||
context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
|
||||
context.stroke();
|
||||
if (fill) {
|
||||
context.setFillStyle(fill);
|
||||
context.fill();
|
||||
}
|
||||
},
|
||||
renderLayerCircle(context) {
|
||||
const { layerColor, fill } = this.data;
|
||||
this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
|
||||
},
|
||||
renderHoverCircle(context, formatValue) {
|
||||
const { clockwise } = this.data;
|
||||
// 结束角度
|
||||
const progress = PERIMETER * (formatValue / 100);
|
||||
const endAngle = clockwise
|
||||
? BEGIN_ANGLE + progress
|
||||
: 3 * Math.PI - (BEGIN_ANGLE + progress);
|
||||
this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle);
|
||||
},
|
||||
drawCircle(currentValue) {
|
||||
const { size } = this.data;
|
||||
this.getContext().then((context) => {
|
||||
if (!context)
|
||||
return;
|
||||
context.clearRect(0, 0, size, size);
|
||||
this.renderLayerCircle(context);
|
||||
const formatValue = format(currentValue);
|
||||
if (formatValue !== 0) {
|
||||
this.renderHoverCircle(context, formatValue);
|
||||
}
|
||||
context.draw();
|
||||
});
|
||||
},
|
||||
reRender() {
|
||||
// tofector 动画暂时没有想到好的解决方案
|
||||
const { value, speed } = this.data;
|
||||
if (speed <= 0 || speed > 1000) {
|
||||
this.drawCircle(value);
|
||||
return;
|
||||
}
|
||||
this.clearMockInterval();
|
||||
this.currentValue = this.currentValue || 0;
|
||||
const run = () => {
|
||||
this.interval = setTimeout(() => {
|
||||
if (this.currentValue !== value) {
|
||||
if (Math.abs(this.currentValue - value) < STEP) {
|
||||
this.currentValue = value;
|
||||
}
|
||||
else if (this.currentValue < value) {
|
||||
this.currentValue += STEP;
|
||||
}
|
||||
else {
|
||||
this.currentValue -= STEP;
|
||||
}
|
||||
this.drawCircle(this.currentValue);
|
||||
run();
|
||||
}
|
||||
else {
|
||||
this.clearMockInterval();
|
||||
}
|
||||
}, 1000 / speed);
|
||||
};
|
||||
run();
|
||||
},
|
||||
clearMockInterval() {
|
||||
if (this.interval) {
|
||||
clearTimeout(this.interval);
|
||||
this.interval = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.currentValue = this.data.value;
|
||||
this.setHoverColor().then(() => {
|
||||
this.drawCircle(this.currentValue);
|
||||
});
|
||||
},
|
||||
destroyed() {
|
||||
this.clearMockInterval();
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<wxs src="../wxs/utils.wxs" module="utils" />
|
||||
|
||||
<view class="van-circle">
|
||||
<canvas class="van-circle__canvas" type="{{ type }}" style="width: {{ utils.addUnit(size) }};height:{{ utils.addUnit(size) }}" id="van-circle" canvas-id="van-circle"></canvas>
|
||||
<view wx:if="{{ !text }}" class="van-circle__text">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<cover-view wx:else class="van-circle__text">{{ text }}</cover-view>
|
||||
</view>
|
||||
@@ -0,0 +1 @@
|
||||
@import '../common/index.wxss';.van-circle{display:inline-block;position:relative;text-align:center}.van-circle__text{color:var(--circle-text-color,#323233);left:0;position:absolute;top:50%;transform:translateY(-50%);width:100%}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
export declare const RED = "#ee0a24";
|
||||
export declare const BLUE = "#1989fa";
|
||||
export declare const WHITE = "#fff";
|
||||
export declare const GREEN = "#07c160";
|
||||
export declare const ORANGE = "#ff976a";
|
||||
export declare const GRAY = "#323233";
|
||||
export declare const GRAY_DARK = "#969799";
|
||||
@@ -0,0 +1,7 @@
|
||||
export const RED = '#ee0a24';
|
||||
export const BLUE = '#1989fa';
|
||||
export const WHITE = '#fff';
|
||||
export const GREEN = '#07c160';
|
||||
export const ORANGE = '#ff976a';
|
||||
export const GRAY = '#323233';
|
||||
export const GRAY_DARK = '#969799';
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
import { VantComponentOptions } from 'definitions/index';
|
||||
declare function VantComponent<Data extends WechatMiniprogram.Component.DataOption, Props extends WechatMiniprogram.Component.PropertyOption, Methods extends WechatMiniprogram.Component.MethodOption>(vantOptions: VantComponentOptions<Data, Props, Methods>): void;
|
||||
export { VantComponent };
|
||||
@@ -0,0 +1,46 @@
|
||||
import { basic } from '../mixins/basic';
|
||||
function mapKeys(source, target, map) {
|
||||
Object.keys(map).forEach((key) => {
|
||||
if (source[key]) {
|
||||
target[map[key]] = source[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
function VantComponent(vantOptions) {
|
||||
const options = {};
|
||||
mapKeys(vantOptions, options, {
|
||||
data: 'data',
|
||||
props: 'properties',
|
||||
watch: 'observers',
|
||||
mixins: 'behaviors',
|
||||
methods: 'methods',
|
||||
beforeCreate: 'created',
|
||||
created: 'attached',
|
||||
mounted: 'ready',
|
||||
destroyed: 'detached',
|
||||
classes: 'externalClasses',
|
||||
});
|
||||
// add default externalClasses
|
||||
options.externalClasses = options.externalClasses || [];
|
||||
options.externalClasses.push('custom-class');
|
||||
// add default behaviors
|
||||
options.behaviors = options.behaviors || [];
|
||||
options.behaviors.push(basic);
|
||||
// add relations
|
||||
const { relation } = vantOptions;
|
||||
if (relation) {
|
||||
options.relations = relation.relations;
|
||||
options.behaviors.push(relation.mixin);
|
||||
}
|
||||
// map field to form-field behavior
|
||||
if (vantOptions.field) {
|
||||
options.behaviors.push('wx://form-field');
|
||||
}
|
||||
// add default options
|
||||
options.options = {
|
||||
multipleSlots: true,
|
||||
addGlobalClass: true,
|
||||
};
|
||||
Component(options);
|
||||
}
|
||||
export { VantComponent };
|
||||
@@ -0,0 +1 @@
|
||||
.van-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{clear:both;content:"";display:table}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{border:0 solid #ebedf0;bottom:-50%;box-sizing:border-box;content:" ";left:-50%;pointer-events:none;position:absolute;right:-50%;top:-50%;transform:scale(.5);transform-origin:center}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
|
||||
export declare function useParent(name: string, onEffect?: (this: TrivialInstance) => void): {
|
||||
relations: {
|
||||
[x: string]: WechatMiniprogram.Component.RelationOption;
|
||||
};
|
||||
mixin: string;
|
||||
};
|
||||
export declare function useChildren(name: string, onEffect?: (this: TrivialInstance, target: TrivialInstance) => void): {
|
||||
relations: {
|
||||
[x: string]: WechatMiniprogram.Component.RelationOption;
|
||||
};
|
||||
mixin: string;
|
||||
};
|
||||
export {};
|
||||
@@ -0,0 +1,56 @@
|
||||
export function useParent(name, onEffect) {
|
||||
const path = `../${name}/index`;
|
||||
return {
|
||||
relations: {
|
||||
[path]: {
|
||||
type: 'ancestor',
|
||||
linked() {
|
||||
onEffect && onEffect.call(this);
|
||||
},
|
||||
linkChanged() {
|
||||
onEffect && onEffect.call(this);
|
||||
},
|
||||
unlinked() {
|
||||
onEffect && onEffect.call(this);
|
||||
},
|
||||
},
|
||||
},
|
||||
mixin: Behavior({
|
||||
created() {
|
||||
Object.defineProperty(this, 'parent', {
|
||||
get: () => this.getRelationNodes(path)[0],
|
||||
});
|
||||
Object.defineProperty(this, 'index', {
|
||||
// @ts-ignore
|
||||
get: () => { var _a, _b; return (_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.indexOf(this); },
|
||||
});
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
export function useChildren(name, onEffect) {
|
||||
const path = `../${name}/index`;
|
||||
return {
|
||||
relations: {
|
||||
[path]: {
|
||||
type: 'descendant',
|
||||
linked(target) {
|
||||
onEffect && onEffect.call(this, target);
|
||||
},
|
||||
linkChanged(target) {
|
||||
onEffect && onEffect.call(this, target);
|
||||
},
|
||||
unlinked(target) {
|
||||
onEffect && onEffect.call(this, target);
|
||||
},
|
||||
},
|
||||
},
|
||||
mixin: Behavior({
|
||||
created() {
|
||||
Object.defineProperty(this, 'children', {
|
||||
get: () => this.getRelationNodes(path) || [],
|
||||
});
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.van-clearfix:after{clear:both;content:"";display:table}
|
||||
@@ -0,0 +1 @@
|
||||
.van-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.van-multi-ellipsis--l3{-webkit-line-clamp:3}
|
||||
@@ -0,0 +1 @@
|
||||
.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{border:0 solid #ebedf0;bottom:-50%;box-sizing:border-box;content:" ";left:-50%;pointer-events:none;position:absolute;right:-50%;top:-50%;transform:scale(.5);transform-origin:center}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
/// <reference types="node" />
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
export { isDef } from './validator';
|
||||
export { getSystemInfoSync } from './version';
|
||||
export declare function range(num: number, min: number, max: number): number;
|
||||
export declare function nextTick(cb: (...args: any[]) => void): void;
|
||||
export declare function addUnit(value?: string | number): string | undefined;
|
||||
export declare function requestAnimationFrame(cb: () => void): NodeJS.Timeout;
|
||||
export declare function pickExclude(obj: unknown, keys: string[]): {};
|
||||
export declare function getRect(context: WechatMiniprogram.Component.TrivialInstance, selector: string): Promise<WechatMiniprogram.BoundingClientRectCallbackResult>;
|
||||
export declare function getAllRect(context: WechatMiniprogram.Component.TrivialInstance, selector: string): Promise<WechatMiniprogram.BoundingClientRectCallbackResult[]>;
|
||||
export declare function groupSetData(context: WechatMiniprogram.Component.TrivialInstance, cb: () => void): void;
|
||||
export declare function toPromise(promiseLike: Promise<unknown> | unknown): Promise<unknown>;
|
||||
export declare function addNumber(num1: any, num2: any): number;
|
||||
export declare const clamp: (num: any, min: any, max: any) => number;
|
||||
export declare function getCurrentPage<T>(): T & WechatMiniprogram.OptionalInterface<WechatMiniprogram.Page.ILifetime> & WechatMiniprogram.Page.InstanceProperties & WechatMiniprogram.Page.InstanceMethods<WechatMiniprogram.IAnyObject> & WechatMiniprogram.Page.Data<WechatMiniprogram.IAnyObject> & WechatMiniprogram.IAnyObject;
|
||||
export declare const isPC: boolean;
|
||||
export declare const isWxWork: boolean;
|
||||
@@ -0,0 +1,86 @@
|
||||
import { isDef, isNumber, isPlainObject, isPromise } from './validator';
|
||||
import { canIUseGroupSetData, canIUseNextTick, getSystemInfoSync, } from './version';
|
||||
export { isDef } from './validator';
|
||||
export { getSystemInfoSync } from './version';
|
||||
export function range(num, min, max) {
|
||||
return Math.min(Math.max(num, min), max);
|
||||
}
|
||||
export function nextTick(cb) {
|
||||
if (canIUseNextTick()) {
|
||||
wx.nextTick(cb);
|
||||
}
|
||||
else {
|
||||
setTimeout(() => {
|
||||
cb();
|
||||
}, 1000 / 30);
|
||||
}
|
||||
}
|
||||
export function addUnit(value) {
|
||||
if (!isDef(value)) {
|
||||
return undefined;
|
||||
}
|
||||
value = String(value);
|
||||
return isNumber(value) ? `${value}px` : value;
|
||||
}
|
||||
export function requestAnimationFrame(cb) {
|
||||
return setTimeout(() => {
|
||||
cb();
|
||||
}, 1000 / 30);
|
||||
}
|
||||
export function pickExclude(obj, keys) {
|
||||
if (!isPlainObject(obj)) {
|
||||
return {};
|
||||
}
|
||||
return Object.keys(obj).reduce((prev, key) => {
|
||||
if (!keys.includes(key)) {
|
||||
prev[key] = obj[key];
|
||||
}
|
||||
return prev;
|
||||
}, {});
|
||||
}
|
||||
export function getRect(context, selector) {
|
||||
return new Promise((resolve) => {
|
||||
wx.createSelectorQuery()
|
||||
.in(context)
|
||||
.select(selector)
|
||||
.boundingClientRect()
|
||||
.exec((rect = []) => resolve(rect[0]));
|
||||
});
|
||||
}
|
||||
export function getAllRect(context, selector) {
|
||||
return new Promise((resolve) => {
|
||||
wx.createSelectorQuery()
|
||||
.in(context)
|
||||
.selectAll(selector)
|
||||
.boundingClientRect()
|
||||
.exec((rect = []) => resolve(rect[0]));
|
||||
});
|
||||
}
|
||||
export function groupSetData(context, cb) {
|
||||
if (canIUseGroupSetData()) {
|
||||
context.groupSetData(cb);
|
||||
}
|
||||
else {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
export function toPromise(promiseLike) {
|
||||
if (isPromise(promiseLike)) {
|
||||
return promiseLike;
|
||||
}
|
||||
return Promise.resolve(promiseLike);
|
||||
}
|
||||
// 浮点数精度处理
|
||||
export function addNumber(num1, num2) {
|
||||
const cardinal = Math.pow(10, 10);
|
||||
return Math.round((num1 + num2) * cardinal) / cardinal;
|
||||
}
|
||||
// 限制value在[min, max]之间
|
||||
export const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
|
||||
export function getCurrentPage() {
|
||||
const pages = getCurrentPages();
|
||||
return pages[pages.length - 1];
|
||||
}
|
||||
export const isPC = ['mac', 'windows'].includes(getSystemInfoSync().platform);
|
||||
// 是否企业微信
|
||||
export const isWxWork = getSystemInfoSync().environment === 'wxwork';
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
export declare function isFunction(val: unknown): val is Function;
|
||||
export declare function isPlainObject(val: unknown): val is Record<string, unknown>;
|
||||
export declare function isPromise<T = unknown>(val: unknown): val is Promise<T>;
|
||||
export declare function isDef(value: unknown): boolean;
|
||||
export declare function isObj(x: unknown): x is Record<string, unknown>;
|
||||
export declare function isNumber(value: string): boolean;
|
||||
export declare function isBoolean(value: unknown): value is boolean;
|
||||
export declare function isImageUrl(url: string): boolean;
|
||||
export declare function isVideoUrl(url: string): boolean;
|
||||
@@ -0,0 +1,31 @@
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export function isFunction(val) {
|
||||
return typeof val === 'function';
|
||||
}
|
||||
export function isPlainObject(val) {
|
||||
return val !== null && typeof val === 'object' && !Array.isArray(val);
|
||||
}
|
||||
export function isPromise(val) {
|
||||
return isPlainObject(val) && isFunction(val.then) && isFunction(val.catch);
|
||||
}
|
||||
export function isDef(value) {
|
||||
return value !== undefined && value !== null;
|
||||
}
|
||||
export function isObj(x) {
|
||||
const type = typeof x;
|
||||
return x !== null && (type === 'object' || type === 'function');
|
||||
}
|
||||
export function isNumber(value) {
|
||||
return /^\d+(\.\d+)?$/.test(value);
|
||||
}
|
||||
export function isBoolean(value) {
|
||||
return typeof value === 'boolean';
|
||||
}
|
||||
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
|
||||
const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i;
|
||||
export function isImageUrl(url) {
|
||||
return IMAGE_REGEXP.test(url);
|
||||
}
|
||||
export function isVideoUrl(url) {
|
||||
return VIDEO_REGEXP.test(url);
|
||||
}
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
interface WxWorkSystemInfo extends WechatMiniprogram.SystemInfo {
|
||||
environment?: 'wxwork';
|
||||
}
|
||||
interface SystemInfo extends WxWorkSystemInfo, WechatMiniprogram.SystemInfo {
|
||||
}
|
||||
export declare function getSystemInfoSync(): SystemInfo;
|
||||
export declare function canIUseModel(): boolean;
|
||||
export declare function canIUseFormFieldButton(): boolean;
|
||||
export declare function canIUseAnimate(): boolean;
|
||||
export declare function canIUseGroupSetData(): boolean;
|
||||
export declare function canIUseNextTick(): boolean;
|
||||
export declare function canIUseCanvas2d(): boolean;
|
||||
export declare function canIUseGetUserProfile(): boolean;
|
||||
export {};
|
||||
@@ -0,0 +1,59 @@
|
||||
let systemInfo;
|
||||
export function getSystemInfoSync() {
|
||||
if (systemInfo == null) {
|
||||
systemInfo = wx.getSystemInfoSync();
|
||||
}
|
||||
return systemInfo;
|
||||
}
|
||||
function compareVersion(v1, v2) {
|
||||
v1 = v1.split('.');
|
||||
v2 = v2.split('.');
|
||||
const len = Math.max(v1.length, v2.length);
|
||||
while (v1.length < len) {
|
||||
v1.push('0');
|
||||
}
|
||||
while (v2.length < len) {
|
||||
v2.push('0');
|
||||
}
|
||||
for (let i = 0; i < len; i++) {
|
||||
const num1 = parseInt(v1[i], 10);
|
||||
const num2 = parseInt(v2[i], 10);
|
||||
if (num1 > num2) {
|
||||
return 1;
|
||||
}
|
||||
if (num1 < num2) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function gte(version) {
|
||||
const system = getSystemInfoSync();
|
||||
return compareVersion(system.SDKVersion, version) >= 0;
|
||||
}
|
||||
export function canIUseModel() {
|
||||
return gte('2.9.3');
|
||||
}
|
||||
export function canIUseFormFieldButton() {
|
||||
return gte('2.10.3');
|
||||
}
|
||||
export function canIUseAnimate() {
|
||||
return gte('2.9.0');
|
||||
}
|
||||
export function canIUseGroupSetData() {
|
||||
return gte('2.4.0');
|
||||
}
|
||||
export function canIUseNextTick() {
|
||||
try {
|
||||
return wx.canIUse('nextTick');
|
||||
}
|
||||
catch (e) {
|
||||
return gte('2.7.1');
|
||||
}
|
||||
}
|
||||
export function canIUseCanvas2d() {
|
||||
return gte('2.9.0');
|
||||
}
|
||||
export function canIUseGetUserProfile() {
|
||||
return !!wx.getUserProfile;
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const basic: string;
|
||||
@@ -0,0 +1,26 @@
|
||||
export const basic = Behavior({
|
||||
methods: {
|
||||
$emit(name, detail, options) {
|
||||
this.triggerEvent(name, detail, options);
|
||||
},
|
||||
set(data) {
|
||||
this.setData(data);
|
||||
return new Promise((resolve) => wx.nextTick(resolve));
|
||||
},
|
||||
// high performance setData
|
||||
setView(data, callback) {
|
||||
const target = {};
|
||||
let hasChange = false;
|
||||
Object.keys(data).forEach((key) => {
|
||||
if (data[key] !== this.data[key]) {
|
||||
target[key] = data[key];
|
||||
hasChange = true;
|
||||
}
|
||||
});
|
||||
if (hasChange) {
|
||||
return this.setData(target, callback);
|
||||
}
|
||||
return callback && callback();
|
||||
},
|
||||
},
|
||||
});
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const button: string;
|
||||
@@ -0,0 +1,51 @@
|
||||
import { canIUseGetUserProfile } from '../common/version';
|
||||
export const button = Behavior({
|
||||
externalClasses: ['hover-class'],
|
||||
properties: {
|
||||
id: String,
|
||||
buttonId: String,
|
||||
lang: String,
|
||||
businessId: Number,
|
||||
sessionFrom: String,
|
||||
sendMessageTitle: String,
|
||||
sendMessagePath: String,
|
||||
sendMessageImg: String,
|
||||
showMessageCard: Boolean,
|
||||
appParameter: String,
|
||||
ariaLabel: String,
|
||||
openType: String,
|
||||
getUserProfileDesc: String,
|
||||
},
|
||||
data: {
|
||||
canIUseGetUserProfile: canIUseGetUserProfile(),
|
||||
},
|
||||
methods: {
|
||||
onGetUserInfo(event) {
|
||||
this.triggerEvent('getuserinfo', event.detail);
|
||||
},
|
||||
onContact(event) {
|
||||
this.triggerEvent('contact', event.detail);
|
||||
},
|
||||
onGetPhoneNumber(event) {
|
||||
this.triggerEvent('getphonenumber', event.detail);
|
||||
},
|
||||
onGetRealTimePhoneNumber(event) {
|
||||
this.triggerEvent('getrealtimephonenumber', event.detail);
|
||||
},
|
||||
onError(event) {
|
||||
this.triggerEvent('error', event.detail);
|
||||
},
|
||||
onLaunchApp(event) {
|
||||
this.triggerEvent('launchapp', event.detail);
|
||||
},
|
||||
onOpenSetting(event) {
|
||||
this.triggerEvent('opensetting', event.detail);
|
||||
},
|
||||
onAgreePrivacyAuthorization(event) {
|
||||
this.triggerEvent('agreeprivacyauthorization', event.detail);
|
||||
},
|
||||
onChooseAvatar(event) {
|
||||
this.triggerEvent('chooseavatar', event.detail);
|
||||
},
|
||||
},
|
||||
});
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const link: string;
|
||||
@@ -0,0 +1,23 @@
|
||||
export const link = Behavior({
|
||||
properties: {
|
||||
url: String,
|
||||
linkType: {
|
||||
type: String,
|
||||
value: 'navigateTo',
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
jumpLink(urlKey = 'url') {
|
||||
const url = this.data[urlKey];
|
||||
if (url) {
|
||||
if (this.data.linkType === 'navigateTo' &&
|
||||
getCurrentPages().length > 9) {
|
||||
wx.redirectTo({ url });
|
||||
}
|
||||
else {
|
||||
wx[this.data.linkType]({ url });
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
type IPageScrollOption = WechatMiniprogram.Page.IPageScrollOption;
|
||||
type Scroller = (this: WechatMiniprogram.Component.TrivialInstance, event?: IPageScrollOption) => void;
|
||||
export declare function pageScrollMixin(scroller: Scroller): string;
|
||||
export {};
|
||||
@@ -0,0 +1,42 @@
|
||||
import { isFunction } from '../common/validator';
|
||||
import { getCurrentPage, isDef } from '../common/utils';
|
||||
function onPageScroll(event) {
|
||||
const { vanPageScroller = [] } = getCurrentPage();
|
||||
vanPageScroller.forEach((scroller) => {
|
||||
if (typeof scroller === 'function') {
|
||||
// @ts-ignore
|
||||
scroller(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
export function pageScrollMixin(scroller) {
|
||||
return Behavior({
|
||||
attached() {
|
||||
const page = getCurrentPage();
|
||||
if (!isDef(page)) {
|
||||
return;
|
||||
}
|
||||
const _scroller = scroller.bind(this);
|
||||
const { vanPageScroller = [] } = page;
|
||||
if (isFunction(page.onPageScroll) && page.onPageScroll !== onPageScroll) {
|
||||
vanPageScroller.push(page.onPageScroll.bind(page));
|
||||
}
|
||||
vanPageScroller.push(_scroller);
|
||||
page.vanPageScroller = vanPageScroller;
|
||||
page.onPageScroll = onPageScroll;
|
||||
this._scroller = _scroller;
|
||||
},
|
||||
detached() {
|
||||
const page = getCurrentPage();
|
||||
if (!isDef(page) || !isDef(page.vanPageScroller)) {
|
||||
return;
|
||||
}
|
||||
const { vanPageScroller } = page;
|
||||
const index = vanPageScroller.findIndex((v) => v === this._scroller);
|
||||
if (index > -1) {
|
||||
page.vanPageScroller.splice(index, 1);
|
||||
}
|
||||
this._scroller = undefined;
|
||||
},
|
||||
});
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare const touch: string;
|
||||
@@ -0,0 +1,37 @@
|
||||
// @ts-nocheck
|
||||
const MIN_DISTANCE = 10;
|
||||
function getDirection(x, y) {
|
||||
if (x > y && x > MIN_DISTANCE) {
|
||||
return 'horizontal';
|
||||
}
|
||||
if (y > x && y > MIN_DISTANCE) {
|
||||
return 'vertical';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
export const touch = Behavior({
|
||||
methods: {
|
||||
resetTouchStatus() {
|
||||
this.direction = '';
|
||||
this.deltaX = 0;
|
||||
this.deltaY = 0;
|
||||
this.offsetX = 0;
|
||||
this.offsetY = 0;
|
||||
},
|
||||
touchStart(event) {
|
||||
this.resetTouchStatus();
|
||||
const touch = event.touches[0];
|
||||
this.startX = touch.clientX;
|
||||
this.startY = touch.clientY;
|
||||
},
|
||||
touchMove(event) {
|
||||
const touch = event.touches[0];
|
||||
this.deltaX = touch.clientX - this.startX;
|
||||
this.deltaY = touch.clientY - this.startY;
|
||||
this.offsetX = Math.abs(this.deltaX);
|
||||
this.offsetY = Math.abs(this.deltaY);
|
||||
this.direction =
|
||||
this.direction || getDirection(this.offsetX, this.offsetY);
|
||||
},
|
||||
},
|
||||
});
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
export declare function transition(showDefaultValue: boolean): string;
|
||||
@@ -0,0 +1,129 @@
|
||||
// @ts-nocheck
|
||||
import { requestAnimationFrame } from '../common/utils';
|
||||
import { isObj } from '../common/validator';
|
||||
const getClassNames = (name) => ({
|
||||
enter: `van-${name}-enter van-${name}-enter-active enter-class enter-active-class`,
|
||||
'enter-to': `van-${name}-enter-to van-${name}-enter-active enter-to-class enter-active-class`,
|
||||
leave: `van-${name}-leave van-${name}-leave-active leave-class leave-active-class`,
|
||||
'leave-to': `van-${name}-leave-to van-${name}-leave-active leave-to-class leave-active-class`,
|
||||
});
|
||||
export function transition(showDefaultValue) {
|
||||
return Behavior({
|
||||
properties: {
|
||||
customStyle: String,
|
||||
// @ts-ignore
|
||||
show: {
|
||||
type: Boolean,
|
||||
value: showDefaultValue,
|
||||
observer: 'observeShow',
|
||||
},
|
||||
// @ts-ignore
|
||||
duration: {
|
||||
type: null,
|
||||
value: 300,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
value: 'fade',
|
||||
},
|
||||
},
|
||||
data: {
|
||||
type: '',
|
||||
inited: false,
|
||||
display: false,
|
||||
},
|
||||
ready() {
|
||||
if (this.data.show === true) {
|
||||
this.observeShow(true, false);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
observeShow(value, old) {
|
||||
if (value === old) {
|
||||
return;
|
||||
}
|
||||
value ? this.enter() : this.leave();
|
||||
},
|
||||
enter() {
|
||||
if (this.enterFinishedPromise)
|
||||
return;
|
||||
this.enterFinishedPromise = new Promise((resolve) => {
|
||||
const { duration, name } = this.data;
|
||||
const classNames = getClassNames(name);
|
||||
const currentDuration = isObj(duration) ? duration.enter : duration;
|
||||
if (this.status === 'enter') {
|
||||
return;
|
||||
}
|
||||
this.status = 'enter';
|
||||
this.$emit('before-enter');
|
||||
requestAnimationFrame(() => {
|
||||
if (this.status !== 'enter') {
|
||||
return;
|
||||
}
|
||||
this.$emit('enter');
|
||||
this.setData({
|
||||
inited: true,
|
||||
display: true,
|
||||
classes: classNames.enter,
|
||||
currentDuration,
|
||||
});
|
||||
requestAnimationFrame(() => {
|
||||
if (this.status !== 'enter') {
|
||||
return;
|
||||
}
|
||||
this.transitionEnded = false;
|
||||
this.setData({ classes: classNames['enter-to'] });
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
leave() {
|
||||
if (!this.enterFinishedPromise)
|
||||
return;
|
||||
this.enterFinishedPromise.then(() => {
|
||||
if (!this.data.display) {
|
||||
return;
|
||||
}
|
||||
const { duration, name } = this.data;
|
||||
const classNames = getClassNames(name);
|
||||
const currentDuration = isObj(duration) ? duration.leave : duration;
|
||||
this.status = 'leave';
|
||||
this.$emit('before-leave');
|
||||
requestAnimationFrame(() => {
|
||||
if (this.status !== 'leave') {
|
||||
return;
|
||||
}
|
||||
this.$emit('leave');
|
||||
this.setData({
|
||||
classes: classNames.leave,
|
||||
currentDuration,
|
||||
});
|
||||
requestAnimationFrame(() => {
|
||||
if (this.status !== 'leave') {
|
||||
return;
|
||||
}
|
||||
this.transitionEnded = false;
|
||||
setTimeout(() => {
|
||||
this.onTransitionEnd();
|
||||
this.enterFinishedPromise = null;
|
||||
}, currentDuration);
|
||||
this.setData({ classes: classNames['leave-to'] });
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
onTransitionEnd() {
|
||||
if (this.transitionEnded) {
|
||||
return;
|
||||
}
|
||||
this.transitionEnded = true;
|
||||
this.$emit(`after-${this.status}`);
|
||||
const { show, display } = this.data;
|
||||
if (!show && display) {
|
||||
this.setData({ display: false });
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* eslint-disable */
|
||||
var REGEXP = getRegExp('^-?\d+(\.\d+)?$');
|
||||
|
||||
function addUnit(value) {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return REGEXP.test('' + value) ? value + 'px' : value;
|
||||
}
|
||||
|
||||
module.exports = addUnit;
|
||||
@@ -0,0 +1,5 @@
|
||||
function isArray(array) {
|
||||
return array && array.constructor === 'Array';
|
||||
}
|
||||
|
||||
module.exports.isArray = isArray;
|
||||
@@ -0,0 +1,39 @@
|
||||
/* eslint-disable */
|
||||
var array = require('./array.wxs');
|
||||
var object = require('./object.wxs');
|
||||
var PREFIX = 'van-';
|
||||
|
||||
function join(name, mods) {
|
||||
name = PREFIX + name;
|
||||
mods = mods.map(function(mod) {
|
||||
return name + '--' + mod;
|
||||
});
|
||||
mods.unshift(name);
|
||||
return mods.join(' ');
|
||||
}
|
||||
|
||||
function traversing(mods, conf) {
|
||||
if (!conf) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof conf === 'string' || typeof conf === 'number') {
|
||||
mods.push(conf);
|
||||
} else if (array.isArray(conf)) {
|
||||
conf.forEach(function(item) {
|
||||
traversing(mods, item);
|
||||
});
|
||||
} else if (typeof conf === 'object') {
|
||||
object.keys(conf).forEach(function(key) {
|
||||
conf[key] && mods.push(key);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function bem(name, conf) {
|
||||
var mods = [];
|
||||
traversing(mods, conf);
|
||||
return join(name, mods);
|
||||
}
|
||||
|
||||
module.exports = bem;
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Simple memoize
|
||||
* wxs doesn't support fn.apply, so this memoize only support up to 2 args
|
||||
*/
|
||||
/* eslint-disable */
|
||||
|
||||
function isPrimitive(value) {
|
||||
var type = typeof value;
|
||||
return (
|
||||
type === 'boolean' ||
|
||||
type === 'number' ||
|
||||
type === 'string' ||
|
||||
type === 'undefined' ||
|
||||
value === null
|
||||
);
|
||||
}
|
||||
|
||||
// mock simple fn.call in wxs
|
||||
function call(fn, args) {
|
||||
if (args.length === 2) {
|
||||
return fn(args[0], args[1]);
|
||||
}
|
||||
|
||||
if (args.length === 1) {
|
||||
return fn(args[0]);
|
||||
}
|
||||
|
||||
return fn();
|
||||
}
|
||||
|
||||
function serializer(args) {
|
||||
if (args.length === 1 && isPrimitive(args[0])) {
|
||||
return args[0];
|
||||
}
|
||||
var obj = {};
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
obj['key' + i] = args[i];
|
||||
}
|
||||
return JSON.stringify(obj);
|
||||
}
|
||||
|
||||
function memoize(fn) {
|
||||
var cache = {};
|
||||
|
||||
return function() {
|
||||
var key = serializer(arguments);
|
||||
if (cache[key] === undefined) {
|
||||
cache[key] = call(fn, arguments);
|
||||
}
|
||||
|
||||
return cache[key];
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = memoize;
|
||||
@@ -0,0 +1,13 @@
|
||||
/* eslint-disable */
|
||||
var REGEXP = getRegExp('{|}|"', 'g');
|
||||
|
||||
function keys(obj) {
|
||||
return JSON.stringify(obj)
|
||||
.replace(REGEXP, '')
|
||||
.split(',')
|
||||
.map(function(item) {
|
||||
return item.split(':')[0];
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.keys = keys;
|
||||
@@ -0,0 +1,42 @@
|
||||
/* eslint-disable */
|
||||
var object = require('./object.wxs');
|
||||
var array = require('./array.wxs');
|
||||
|
||||
function kebabCase(word) {
|
||||
var newWord = word
|
||||
.replace(getRegExp("[A-Z]", 'g'), function (i) {
|
||||
return '-' + i;
|
||||
})
|
||||
.toLowerCase()
|
||||
|
||||
return newWord;
|
||||
}
|
||||
|
||||
function style(styles) {
|
||||
if (array.isArray(styles)) {
|
||||
return styles
|
||||
.filter(function (item) {
|
||||
return item != null && item !== '';
|
||||
})
|
||||
.map(function (item) {
|
||||
return style(item);
|
||||
})
|
||||
.join(';');
|
||||
}
|
||||
|
||||
if ('Object' === styles.constructor) {
|
||||
return object
|
||||
.keys(styles)
|
||||
.filter(function (key) {
|
||||
return styles[key] != null && styles[key] !== '';
|
||||
})
|
||||
.map(function (key) {
|
||||
return [kebabCase(key), [styles[key]]].join(':');
|
||||
})
|
||||
.join(';');
|
||||
}
|
||||
|
||||
return styles;
|
||||
}
|
||||
|
||||
module.exports = style;
|
||||
@@ -0,0 +1,10 @@
|
||||
/* eslint-disable */
|
||||
var bem = require('./bem.wxs');
|
||||
var memoize = require('./memoize.wxs');
|
||||
var addUnit = require('./add-unit.wxs');
|
||||
|
||||
module.exports = {
|
||||
bem: memoize(bem),
|
||||
memoize: memoize,
|
||||
addUnit: addUnit
|
||||
};
|
||||
Reference in New Issue
Block a user