增加环形进度组件,增加卖场评分页面

This commit is contained in:
xiaolian
2024-09-26 15:12:14 +08:00
committed by lcc
parent 8884afa9fa
commit e68a4311f9
73 changed files with 3889 additions and 24 deletions
+7 -3
View File
@@ -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",
+12
View File
@@ -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);}
+2
View File
@@ -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;}
+4
View File
@@ -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;}
+11
View File
@@ -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;}
+1
View File
@@ -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;}
+3
View File
@@ -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,
+393
View File
@@ -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(/&amp;/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
}
})
+6
View File
@@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"node": "./node/node"
}
}
+7
View File
@@ -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>
+2
View File
@@ -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;}
+237
View File
@@ -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
})
}
}
}
})
+6
View File
@@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"node": "./node"
}
}
+112
View File
@@ -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 -->
+169
View File
@@ -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
+30
View File
@@ -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({
+2 -1
View File
@@ -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
View File
@@ -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}}">
+146
View File
@@ -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() {
}
})
+3
View File
@@ -0,0 +1,3 @@
{
"usingComponents": {}
}
+46
View File
@@ -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>
+1
View File
@@ -0,0 +1 @@
/* pages/score/detail.wxss */
+187
View File
@@ -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'
})
}
})
+6
View File
@@ -0,0 +1,6 @@
{
"usingComponents": {
"van-circle": "/vant/circle/index",
"com-html": "/components/mp-html/index"
}
}
+78
View File
@@ -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>
+34
View File
@@ -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;
}
+4
View File
@@ -0,0 +1,4 @@
/// <reference types="miniprogram-api-typings" />
type CanvasContext = WechatMiniprogram.CanvasContext;
export declare function adaptor(ctx: CanvasContext & Record<string, unknown>): CanvasContext;
export {};
+43
View File
@@ -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() { },
});
}
+1
View File
@@ -0,0 +1 @@
export {};
+197
View File
@@ -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();
},
});
+3
View File
@@ -0,0 +1,3 @@
{
"component": true
}
+9
View File
@@ -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>
+1
View File
@@ -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%}
+7
View File
@@ -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";
+7
View File
@@ -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';
+4
View File
@@ -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 };
+46
View File
@@ -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 };
+1
View File
@@ -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}
+15
View File
@@ -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 {};
+56
View File
@@ -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) || [],
});
},
}),
};
}
+1
View File
@@ -0,0 +1 @@
.van-clearfix:after{clear:both;content:"";display:table}
+1
View File
@@ -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}
+1
View File
@@ -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}
View File
+21
View File
@@ -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;
+86
View File
@@ -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';
+9
View File
@@ -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;
+31
View File
@@ -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);
}
+15
View File
@@ -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 {};
+59
View File
@@ -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;
}
+1
View File
@@ -0,0 +1 @@
export declare const basic: string;
+26
View File
@@ -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();
},
},
});
+1
View File
@@ -0,0 +1 @@
export declare const button: string;
+51
View File
@@ -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);
},
},
});
+1
View File
@@ -0,0 +1 @@
export declare const link: string;
+23
View File
@@ -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 });
}
}
},
},
});
+6
View File
@@ -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 {};
+42
View File
@@ -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;
},
});
}
+1
View File
@@ -0,0 +1 @@
export declare const touch: string;
+37
View File
@@ -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);
},
},
});
+1
View File
@@ -0,0 +1 @@
export declare function transition(showDefaultValue: boolean): string;
+129
View File
@@ -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 });
}
},
},
});
}
+12
View File
@@ -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;
+5
View File
@@ -0,0 +1,5 @@
function isArray(array) {
return array && array.constructor === 'Array';
}
module.exports.isArray = isArray;
+39
View File
@@ -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;
+55
View File
@@ -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;
+13
View File
@@ -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;
+42
View File
@@ -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;
+10
View File
@@ -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
};