@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
root = true |
||||
|
||||
[*] |
||||
charset = utf-8 |
||||
indent_style = space |
||||
indent_size = 2 |
||||
end_of_line = lf |
||||
insert_final_newline = true |
||||
trim_trailing_whitespace = true |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
module.exports = { |
||||
root: true, |
||||
globals: { wx: true }, |
||||
parser: 'babel-eslint', |
||||
parserOptions: { |
||||
sourceType: 'module' |
||||
}, |
||||
env: { |
||||
browser: true |
||||
}, |
||||
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
|
||||
extends: 'standard', |
||||
// required to lint *.wpy files
|
||||
plugins: [ |
||||
'html' |
||||
], |
||||
settings: { |
||||
'html/html-extensions': ['.html', '.wpy'] |
||||
}, |
||||
// add your custom rules here
|
||||
'rules': { |
||||
// allow paren-less arrow functions
|
||||
'arrow-parens': 0, |
||||
'semi': ["error", "always"], |
||||
// allow async-await
|
||||
'generator-star-spacing': 0, |
||||
// allow debugger during development
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, |
||||
'space-before-function-paren': 0 |
||||
} |
||||
} |
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
node_modules |
||||
dist |
||||
.DS_Store |
||||
.idea |
||||
.wepycache |
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
node_modules |
||||
dist |
||||
.DS_Store |
||||
*.wpy___jb_tmp___ |
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
{ |
||||
"name": "sport2", |
||||
"version": "0.0.2", |
||||
"description": "糖友运动", |
||||
"main": "dist/app.js", |
||||
"scripts": { |
||||
"dev": "wepy build --watch", |
||||
"build": "cross-env NODE_ENV=production wepy build --no-cache", |
||||
"dev:web": "wepy build --output web", |
||||
"clean": "find ./dist -maxdepth 1 -not -name 'project.config.json' -not -name 'dist' | xargs rm -rf", |
||||
"test": "echo \"Error: no test specified\" && exit 1" |
||||
}, |
||||
"wepy": { |
||||
"module-a": false, |
||||
"./src/components/list": "./src/components/wepy-list.wpy" |
||||
}, |
||||
"author": "ygc <guocun.yang@dnurse.cn>", |
||||
"license": "MIT", |
||||
"dependencies": { |
||||
"moment": "^2.24.0", |
||||
"wepy": "^1.6.0", |
||||
"wepy-async-function": "^1.4.4", |
||||
"wepy-com-toast": "^1.0.2" |
||||
}, |
||||
"devDependencies": { |
||||
"babel-eslint": "^7.2.1", |
||||
"babel-plugin-global-define": "^1.0.3", |
||||
"babel-plugin-transform-class-properties": "^6.24.1", |
||||
"babel-plugin-transform-decorators-legacy": "^1.3.4", |
||||
"babel-plugin-transform-export-extensions": "^6.22.0", |
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0", |
||||
"babel-preset-env": "^1.6.1", |
||||
"cross-env": "^5.1.3", |
||||
"eslint": "^3.18.0", |
||||
"eslint-config-standard": "^7.1.0", |
||||
"eslint-friendly-formatter": "^2.0.7", |
||||
"eslint-plugin-html": "^2.0.1", |
||||
"eslint-plugin-promise": "^3.5.0", |
||||
"eslint-plugin-standard": "^2.0.1", |
||||
"less": "^3.8.1", |
||||
"wepy-compiler-babel": "^1.5.1", |
||||
"wepy-compiler-less": "^1.3.10", |
||||
"wepy-eslint": "^1.5.3", |
||||
"wepy-plugin-imagemin": "^1.5.3", |
||||
"wepy-plugin-uglifyjs": "^1.3.7" |
||||
} |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
{ |
||||
"description": "糖友运动", |
||||
"setting": { |
||||
"urlCheck": true, |
||||
"es6": true, |
||||
"postcss": true, |
||||
"minified": false, |
||||
"babelSetting": { |
||||
"ignore": [], |
||||
"disablePlugins": [], |
||||
"outputPath": "" |
||||
}, |
||||
"enhance": true |
||||
}, |
||||
"compileType": "miniprogram", |
||||
"appid": "wxc06a18569e063fdd", |
||||
"projectname": "sport2", |
||||
"miniprogramRoot": "dist/", |
||||
"libVersion": "3.3.4", |
||||
"srcMiniprogramRoot": "dist/", |
||||
"packOptions": { |
||||
"ignore": [], |
||||
"include": [] |
||||
}, |
||||
"condition": {}, |
||||
"editorSetting": { |
||||
"tabIndent": "insertSpaces", |
||||
"tabSize": 4 |
||||
} |
||||
} |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
{ |
||||
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", |
||||
"projectname": "sport2", |
||||
"setting": { |
||||
"compileHotReLoad": true, |
||||
"urlCheck": true |
||||
}, |
||||
"condition": { |
||||
"miniprogram": { |
||||
"list": [ |
||||
{ |
||||
"name": "pages/index", |
||||
"pathName": "pages/index", |
||||
"query": "scene=wid%3Da000025f", |
||||
"launchMode": "default", |
||||
"scene": null |
||||
} |
||||
] |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,608 @@
@@ -0,0 +1,608 @@
|
||||
<style lang="less"> |
||||
@import "style/reset.less"; |
||||
|
||||
page { |
||||
line-height: 1.6; |
||||
font-family: @novoFontDefault; |
||||
background:rgba(245,247,250,1); |
||||
} |
||||
|
||||
icon{ |
||||
vertical-align: middle; |
||||
} |
||||
|
||||
.container { |
||||
height: 100%; |
||||
display: flex; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
box-sizing: border-box; |
||||
padding: 0 40rpx 0 40rpx; |
||||
} |
||||
|
||||
.right-arrow { |
||||
|
||||
} |
||||
|
||||
.page-bg { |
||||
position: absolute; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height:100%; |
||||
z-index:-1; |
||||
} |
||||
.top-auth-btn { |
||||
padding: 0; |
||||
width: 100%; |
||||
height: 60rpx; |
||||
z-index: 1; |
||||
border-radius: 0; |
||||
background: linear-gradient(270deg,rgba(246,187,66,1) 0%,rgba(255,124,28,1) 100%); |
||||
&::after { |
||||
border: none; |
||||
} |
||||
.auth-font { |
||||
position: relative; |
||||
padding: 0 30rpx; |
||||
height: 100%; |
||||
font-size: 30rpx; |
||||
line-height: 60rpx; |
||||
color: #fff; |
||||
text-align: left; |
||||
&::after { |
||||
content: " "; |
||||
.setArrow(right, 20rpx, #fff, 4rpx); |
||||
position: absolute; |
||||
top: 50%; |
||||
margin-top: -12rpx; |
||||
right: 30rpx; |
||||
} |
||||
} |
||||
.award-tips { |
||||
span { |
||||
position: absolute; |
||||
right: 55rpx; |
||||
color: #48CFAD; |
||||
} |
||||
&::after { |
||||
content: " "; |
||||
.setArrow(right, 20rpx, #48CFAD, 4rpx); |
||||
position: absolute; |
||||
top: 50%; |
||||
margin-top: -12rpx; |
||||
right: 30rpx; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.rules-popup { |
||||
position: fixed; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
background: rgba(0, 0, 0, .6); |
||||
text-align: center; |
||||
font-size: 0; |
||||
z-index: 3; |
||||
|
||||
.popup-content { |
||||
overflow: scroll; |
||||
margin: 240rpx 55rpx 0; |
||||
border: 5rpx solid #2f4b84; |
||||
padding: 30rpx 35rpx 20rpx; |
||||
max-height: 78%; |
||||
background: #fff; |
||||
border-radius: 30rpx; |
||||
text-align: left; |
||||
color: #2350ad; |
||||
|
||||
h2 { |
||||
display: block; |
||||
margin-bottom: 25rpx; |
||||
text-align: center; |
||||
font-size: 55rpx; |
||||
line-height: 55rpx; |
||||
font-weight: bold; |
||||
} |
||||
p { |
||||
position: relative; |
||||
display: block; |
||||
padding-left: 50rpx; |
||||
font-size: 32rpx; |
||||
line-height: 36rpx; |
||||
margin-bottom: 13rpx; |
||||
|
||||
span { |
||||
position: absolute; |
||||
left: 0; |
||||
} |
||||
} |
||||
|
||||
p.tips { |
||||
font-weight: bold; |
||||
color: #ea6160; |
||||
} |
||||
|
||||
& > span { |
||||
display: block; |
||||
margin-top: 35rpx; |
||||
font-size: 24rpx; |
||||
line-height: 24rpx; |
||||
text-align: center; |
||||
} |
||||
} |
||||
|
||||
image { |
||||
margin-top: 30rpx; |
||||
width: 68rpx; |
||||
height: 68rpx; |
||||
} |
||||
} |
||||
|
||||
.rank-rules-popup { |
||||
position: fixed; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
background: rgba(0, 0, 0, .6); |
||||
text-align: center; |
||||
font-size: 0; |
||||
z-index: 3; |
||||
|
||||
.popup-content { |
||||
position: relative; |
||||
margin: 35% auto 0; |
||||
padding: 46rpx 0 90rpx; |
||||
width: 640rpx; |
||||
font-size: 0; |
||||
text-align: center; |
||||
background: #FFAF00; |
||||
border-radius: 20rpx; |
||||
box-sizing: border-box; |
||||
|
||||
& > image { |
||||
width: 270rpx; |
||||
} |
||||
.font { |
||||
padding: 52rpx 50rpx 0 118rpx; |
||||
text-align: left; |
||||
p { |
||||
position: relative; |
||||
display: block; |
||||
margin-bottom: 30rpx; |
||||
font-size: 30rpx; |
||||
font-family: PingFangSC-Regular, PingFang SC; |
||||
font-weight: 400; |
||||
color: #FFF; |
||||
line-height: 48rpx; |
||||
image { |
||||
position: absolute; |
||||
top: 12rpx; |
||||
left: -64rpx; |
||||
width: 34rpx; |
||||
} |
||||
} |
||||
p:first-child { |
||||
image { |
||||
left: -52rpx; |
||||
width: 22rpx; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
& > image { |
||||
margin: 42rpx 0 0; |
||||
width: 68rpx; |
||||
} |
||||
|
||||
} |
||||
|
||||
</style> |
||||
|
||||
<script> |
||||
import wepy from 'wepy'; |
||||
import moment from 'moment'; |
||||
import 'wepy-async-function'; |
||||
import httpUtils from './utils/network'; |
||||
|
||||
const TOKEN_KEY = 'token'; |
||||
|
||||
export default class extends wepy.app { |
||||
config = { |
||||
pages: [ |
||||
'pages/index', |
||||
'pages/share-assist-page', |
||||
'pages/activity-rule', |
||||
'pages/activity-daily-steps', |
||||
'pages/not-bind', |
||||
'pages/award', |
||||
'pages/activity', |
||||
'pages/steps-rank', |
||||
'pages/assist-rank', |
||||
'pages/address', |
||||
'pages/prize-list', |
||||
'pages/article-list', |
||||
'pages/article-detail', |
||||
'pages/step-history', |
||||
'pages/pledge-score', |
||||
'pages/share-page', |
||||
'pages/share-history-page', |
||||
'pages/sport-web', |
||||
'pages/logistics-web', |
||||
'pages/login' |
||||
], |
||||
window: { |
||||
backgroundTextStyle: 'light', |
||||
navigationBarBackgroundColor: '#333333', |
||||
navigationBarTitleText: 'WeChat', |
||||
navigationBarTextStyle: 'white', |
||||
navigationStyle: 'custom' |
||||
}, |
||||
networkTimeout: { |
||||
'request': 1000000, |
||||
'connectSocket': 1000000, |
||||
'uploadFile': 1000000, |
||||
'downloadFile': 1000000 |
||||
} |
||||
} |
||||
|
||||
globalData = { |
||||
userInfo: null, |
||||
isBind: false, |
||||
status: 20, |
||||
navHeight: 44 |
||||
} |
||||
|
||||
customData = { |
||||
|
||||
} |
||||
|
||||
constructor() { |
||||
super(); |
||||
this.use('requestfix'); |
||||
// this.use('promisify'); |
||||
} |
||||
|
||||
onLaunch(option) { |
||||
if (option.query.scene && option.query.scene !== undefined) { |
||||
let indexScene = decodeURIComponent(option.query.scene); |
||||
// 保存当前用户uid |
||||
if (indexScene && indexScene.indexOf('STORE_UID:') !== -1) { |
||||
let CurOpenUid = indexScene.substr(indexScene.indexOf('STORE_UID:') + 'STORE_UID:'.length, indexScene.length); |
||||
wx.setStorageSync('cur_open_uid', CurOpenUid); |
||||
} |
||||
// 保存当前环境,是否为慢病平台 |
||||
if (indexScene && indexScene.indexOf('STORE') !== -1) { |
||||
wx.setStorageSync('plat_form', 'STORE'); |
||||
} |
||||
// 保存运动wid |
||||
if (indexScene && indexScene.indexOf('wid=') !== -1) { |
||||
let wid = indexScene.substr(indexScene.indexOf('wid=') + 'wid='.length, indexScene.length); |
||||
wx.setStorageSync('sport_wid', wid); |
||||
} |
||||
|
||||
let shareOpenUId = decodeURIComponent(option.query.share_open_uid); |
||||
// 保存分享的用户 |
||||
if (shareOpenUId && shareOpenUId !== 'undefined') { |
||||
wx.setStorageSync('share_open_uid', shareOpenUId); |
||||
} |
||||
|
||||
let publicName = decodeURIComponent(option.query.public_name); |
||||
// 保存分享的药店信息 |
||||
if (publicName && publicName !== 'undefined') { |
||||
wx.setStorageSync('public_name', publicName); |
||||
} |
||||
} |
||||
|
||||
// this.testAsync(); |
||||
// this.checkToken(); |
||||
// 通过获取系统信息计算导航栏高度 |
||||
let that = this; |
||||
wx.getSystemInfo({ |
||||
success (res) { |
||||
let statusHeight = res.statusBarHeight; |
||||
let isiOS = res.system.indexOf('iOS') > -1; |
||||
let navHeight; |
||||
if (!isiOS) { |
||||
navHeight = 48; |
||||
} else { |
||||
navHeight = 44; |
||||
} |
||||
that.globalData.status = statusHeight; |
||||
that.globalData.navHeight = navHeight; |
||||
} |
||||
}); |
||||
} |
||||
|
||||
sleep(s) { |
||||
return new Promise((resolve, reject) => { |
||||
setTimeout(() => { |
||||
resolve('promise resolved'); |
||||
}, s * 1000); |
||||
}); |
||||
} |
||||
|
||||
async testAsync() { |
||||
const data = await this.sleep(3); |
||||
console.log(data); |
||||
} |
||||
|
||||
async bindFun(toUnBind) { |
||||
if (wx.getStorageSync('plat_form').indexOf('STORE') !== -1 || !wx.getStorageSync('sport_wid')) { |
||||
toUnBind(); |
||||
} else { |
||||
let data = await httpUtils.post({url: 'mini-sport/new-bind-code', params: {token: wx.getStorageSync('token').token, id: wx.getStorageSync('sport_wid')}}); |
||||
if (data.statusCode === 200 && data.data && data.data.success) { |
||||
console.log('绑定成功'); |
||||
let tokenInfo = wx.getStorageSync('token'); |
||||
tokenInfo.isBindCode = 1; |
||||
wx.setStorageSync('token', tokenInfo); |
||||
this.globalData.token = tokenInfo; |
||||
wepy.redirectTo({ |
||||
url: '/pages/index' |
||||
}); |
||||
} else { |
||||
if (data.data.msg === '登录过期,请重新登录') { |
||||
this.userLogin(); |
||||
} else { |
||||
wx.showToast({ |
||||
title: data.data.msg, |
||||
duration: 1500 |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
checkToken(fun) { |
||||
let that = this; |
||||
return new Promise((resolve, reject) => { |
||||
if (that.globalData.token) { |
||||
if (!that.isBindUser()) { |
||||
that.bindFun(() => { |
||||
wepy.redirectTo({ |
||||
url: '/pages/login' |
||||
}); |
||||
}); |
||||
} else { |
||||
resolve(true); |
||||
} |
||||
} else { |
||||
wepy.getStorage({ |
||||
key: TOKEN_KEY, |
||||
complete(res) { |
||||
console.log('checkToken:', res); |
||||
if (res.data) { |
||||
that.globalData.token = res.data; |
||||
if (!that.isBindUser()) { |
||||
that.bindFun(() => { |
||||
wepy.redirectTo({ |
||||
url: '/pages/login' |
||||
}); |
||||
}); |
||||
} else { |
||||
resolve(true); |
||||
} |
||||
} else { |
||||
that.userLogin(fun); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
checkShareToken(fun) { |
||||
let that = this; |
||||
return new Promise((resolve, reject) => { |
||||
if (that.globalData.token) { |
||||
if (!that.isBindUser(1)) { |
||||
that.userShareLogin(fun); |
||||
} else { |
||||
resolve(true); |
||||
} |
||||
} else { |
||||
wepy.getStorage({ |
||||
key: TOKEN_KEY, |
||||
complete(res) { |
||||
console.log('checkToken:', res); |
||||
if (res.data) { |
||||
that.globalData.token = res.data; |
||||
if (!that.isBindUser(1)) { |
||||
that.userShareLogin(fun); |
||||
} else { |
||||
resolve(true); |
||||
} |
||||
} else { |
||||
that.userShareLogin(fun); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
userLogin(fun, clearStorageNo = 0) { |
||||
let that = this; |
||||
wepy.login({ |
||||
complete(res) { |
||||
if (res.code) { |
||||
// 发起网络请求 |
||||
that.loginFun(res.code, fun, clearStorageNo); |
||||
} else { |
||||
wx.showToast({ |
||||
// icon: 'none', |
||||
title: '登录失败!' + res.errMsg, |
||||
duration: 1500 |
||||
}); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
userShareLogin(fun, clearStorageNo = 0) { |
||||
let that = this; |
||||
wepy.login({ |
||||
complete(res) { |
||||
if (res.code) { |
||||
// 发起网络请求 |
||||
that.loginFun(res.code, fun, clearStorageNo, 1); |
||||
} else { |
||||
wx.showToast({ |
||||
// icon: 'none', |
||||
title: '登录失败!' + res.errMsg, |
||||
duration: 1500 |
||||
}); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
async loginFun(code, fun, clearStorageNo, type = 0) { |
||||
let that = this; |
||||
let params = {code: code}; |
||||
if (type === 1) { |
||||
params.login_source = 'assist_act'; |
||||
} |
||||
let CurOpenUid = wx.getStorageSync('cur_open_uid'); |
||||
if (CurOpenUid) { |
||||
params.open_uid = CurOpenUid; |
||||
} |
||||
|
||||
let platform = wx.getStorageSync('plat_form'); |
||||
let shareOpenUId = wx.getStorageSync('share_open_uid'); |
||||
let publicName = wx.getStorageSync('public_name'); |
||||
let sportWid = wx.getStorageSync('sport_wid'); |
||||
|
||||
let data = await httpUtils.post({url: 'mini-sport/login', params: params}); |
||||
console.log('登录接口'); |
||||
console.log(data); |
||||
if (data.statusCode === 200 && data.data && data.data.success) { |
||||
that.globalData.token = data.data.detail; |
||||
if (clearStorageNo !== 1) { |
||||
wx.clearStorage({ |
||||
success() { |
||||
wx.setStorageSync('cur_open_uid', CurOpenUid); |
||||
wx.setStorageSync('plat_form', platform); |
||||
wx.setStorageSync('share_open_uid', shareOpenUId); |
||||
wx.setStorageSync('public_name', publicName); |
||||
wx.setStorageSync('sport_wid', sportWid); |
||||
// 登录完成看是哪个公众号的 |
||||
if (data.data.detail.public_name && data.data.detail.public_name !== 'undefined') { |
||||
wx.setStorageSync('public_name', data.data.detail.public_name); |
||||
} |
||||
that.saveToken(data.data.detail); |
||||
if (!that.isBindUser(type)) { |
||||
that.bindFun(() => { |
||||
wepy.redirectTo({ |
||||
url: '/pages/login' |
||||
}); |
||||
}); |
||||
} else { |
||||
let now = moment().hours(0).minutes(0).seconds(0).milliseconds(0); |
||||
if (!wx.getStorageSync('indexAchieve')) { |
||||
let info = { |
||||
day: now.format('YYYY-MM-DD'), |
||||
show: false |
||||
}; |
||||
wx.setStorageSync('indexAchieve', info); |
||||
} else { |
||||
let info = wx.getStorageSync('indexAchieve'); |
||||
if (info.day !== now.format('YYYY-MM-DD')) { |
||||
info.day = now.format('YYYY-MM-DD'); |
||||
info.show = false; |
||||
} |
||||
wx.setStorageSync('indexAchieve', info); |
||||
} |
||||
if (!wx.getStorageSync('indexStake')) { |
||||
let info = { |
||||
day: now.format('YYYY-MM-DD'), |
||||
getFun: false |
||||
}; |
||||
wx.setStorageSync('indexStake', info); |
||||
} else { |
||||
let info = wx.getStorageSync('indexStake'); |
||||
if (info.day !== now.format('YYYY-MM-DD')) { |
||||
info.day = now.format('YYYY-MM-DD'); |
||||
info.getFun = false; |
||||
} |
||||
wx.setStorageSync('indexStake', info); |
||||
} |
||||
fun(); |
||||
} |
||||
} |
||||
}); |
||||
} else { |
||||
that.saveToken(data.data.detail); |
||||
if (!that.isBindUser(type)) { |
||||
that.bindFun(() => { |
||||
wepy.redirectTo({ |
||||
url: '/pages/login' |
||||
}); |
||||
}); |
||||
} else { |
||||
fun(); |
||||
} |
||||
} |
||||
} else { |
||||
wx.showToast({ |
||||
// icon: 'none', |
||||
title: data.data.msg, |
||||
duration: 1500 |
||||
}); |
||||
} |
||||
} |
||||
saveToken(token) { |
||||
wepy.setStorage({ |
||||
key: TOKEN_KEY, |
||||
data: token |
||||
}); |
||||
} |
||||
|
||||
isBindUser(type = 0) { |
||||
if (type === 1) { |
||||
return this.globalData.token != null; |
||||
} else { |
||||
return this.globalData.token != null && this.globalData.token.isBindCode; |
||||
} |
||||
} |
||||
|
||||
getHeader() { |
||||
if (this.globalData.token) { |
||||
return this.globalData.token.headImg !== '' ? this.globalData.token.headImg : '/images/header.png'; |
||||
} else { |
||||
return '/images/header.png'; |
||||
} |
||||
} |
||||
|
||||
getUserName() { |
||||
if (this.globalData.token) { |
||||
return this.globalData.token.userName; |
||||
} else { |
||||
return ''; |
||||
} |
||||
} |
||||
|
||||
checkUserAuth(auth) { |
||||
return new Promise((resolve, reject) => { |
||||
wx.getSetting({ |
||||
success (res) { |
||||
let ret = -1; |
||||
if (res.authSetting.hasOwnProperty(auth)) { |
||||
if (res.authSetting[auth] === true) { |
||||
ret = 1; |
||||
} else { |
||||
ret = 0; |
||||
} |
||||
} |
||||
console.log(res, ret); |
||||
resolve(ret); |
||||
} |
||||
}); |
||||
}); |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,206 @@
@@ -0,0 +1,206 @@
|
||||
<style lang="less"> |
||||
@import "../style/reset.less"; |
||||
.circle-view { |
||||
position: relative; |
||||
width: 150px; |
||||
height: 150px; |
||||
left: 50%; |
||||
transform: translateX(-50%); |
||||
|
||||
image { |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
} |
||||
|
||||
.progress-layer { |
||||
position: absolute; |
||||
width: 100%; |
||||
height: 100%; |
||||
top: 0; |
||||
left: 0; |
||||
} |
||||
.information-container { |
||||
position: absolute; |
||||
width: 100%; |
||||
height: 100%; |
||||
top: 0; |
||||
left: 0; |
||||
display: flex; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
box-sizing: border-box; |
||||
justify-content: center; |
||||
|
||||
font-size:14px; |
||||
font-weight:400; |
||||
color:rgba(255,255,255,1); |
||||
line-height:20px; |
||||
|
||||
.steps { |
||||
font-size:30px; |
||||
color: white; |
||||
font-weight:500; |
||||
padding: 10px 0; |
||||
} |
||||
|
||||
.dest { |
||||
padding: 0 8px 10px; |
||||
|
||||
position: relative; |
||||
|
||||
|
||||
} |
||||
} |
||||
|
||||
</style> |
||||
<template> |
||||
<view class="circle-view" @tap="onTargetClick"> |
||||
<canvas style="top: {{showImg?'-200%':'0'}}" class="progress-layer" canvas-id="data-progress"> |
||||
|
||||
</canvas> |
||||
<image style="display: {{showImg?'':'none'}}" src="{{canvasImg}}"></image> |
||||
<view class= "information-container"> |
||||
<text>{{isStakePage==0?'今日步数':'今日已完成'}}</text> |
||||
<text class="steps">{{isStakePage==0?steps:percentage}}<text>{{isStakePage==0?'':'%'}}</text></text> |
||||
<text class="dest">目标:{{targets}}</text> |
||||
</view> |
||||
|
||||
</view> |
||||
</template> |
||||
<script> |
||||
import wepy from 'wepy'; |
||||
|
||||
export default class CircleView extends wepy.component { |
||||
props = { |
||||
steps: { |
||||
type: [Number, String], |
||||
default: 2500 |
||||
}, |
||||
targets: { |
||||
type: [Number, String], |
||||
coerce: function (v) { |
||||
return +v; |
||||
}, |
||||
default: 6000 |
||||
}, |
||||
isStakePage: { |
||||
type: Number, |
||||
default: 0 |
||||
}, |
||||
showImg: { |
||||
type: Boolean, |
||||
default: false |
||||
} |
||||
} |
||||
|
||||
centerX = 150 / 2 |
||||
centerY = 150 / 2 |
||||
progressWidth= 10 |
||||
radius= 70 |
||||
|
||||
computed = { |
||||
percentage () { |
||||
let num = Math.round((Number(this.steps) / Number(this.targets)).toFixed(2) * 100); |
||||
num = num === Infinity ? '--' : (num > 100 ? 100 : num); |
||||
return num; |
||||
} |
||||
} |
||||
watch = { |
||||
steps (curVal, oldVal) { |
||||
this.draw(); |
||||
}, |
||||
targets (curVal, oldVal) { |
||||
this.draw(); |
||||
}, |
||||
showImg (curVal, oldVal) { |
||||
this.draw(); |
||||
} |
||||
} |
||||
|
||||
data = { |
||||
canvasImg: '' |
||||
} |
||||
|
||||
methods = { |
||||
onTargetClick() { |
||||
this.$emit('onTargetClick'); |
||||
} |
||||
} |
||||
|
||||
onLoad() { |
||||
this.draw(); |
||||
} |
||||
draw() { |
||||
const context = wx.createCanvasContext('data-progress'); |
||||
|
||||
this.drawBackground(context); |
||||
this.drawProgress(context); |
||||
this.getImg(); |
||||
} |
||||
|
||||
getImg() { |
||||
let that = this; |
||||
let a = setTimeout(function () { |
||||
wx.canvasToTempFilePath({ |
||||
x: 0, |
||||
y: 0, |
||||
width: 150, |
||||
height: 150, |
||||
destWidth: 300, |
||||
destHeight: 300, |
||||
canvasId: 'data-progress', |
||||
success: function (res) { |
||||
that.canvasImg = res.tempFilePath; |
||||
that.$apply(); |
||||
clearTimeout(a); |
||||
console.log('tempFilePath-------', res.tempFilePath); |
||||
}, |
||||
fail: function (res) { |
||||
that.getImg(); |
||||
} |
||||
}); |
||||
}, 500); |
||||
} |
||||
|
||||
drawBackground(context) { |
||||
context.save(); |
||||
|
||||
context.beginPath(); |
||||
// context.setLineDash([5, 3], 2); |
||||
context.setLineWidth(this.progressWidth); |
||||
context.setGlobalAlpha(0.2); |
||||
context.setStrokeStyle('white'); |
||||
context.arc(this.centerX, this.centerY, this.radius, 0, 2 * Math.PI); |
||||
context.stroke(); |
||||
|
||||
context.restore(); |
||||
} |
||||
|
||||
drawProgress(context) { |
||||
if (Number(this.steps) > 0) { |
||||
let progress = Number(this.steps) * 1.0 / Number(this.targets); |
||||
context.save(); |
||||
context.beginPath(); |
||||
context.setLineWidth(this.progressWidth); |
||||
let gr = context.createLinearGradient(0, 100, 200, 100); |
||||
gr.addColorStop(0, '#48CFAD'); |
||||
gr.addColorStop(1, '#A0D486'); |
||||
// context.setStrokeStyle('white'); |
||||
context.strokeStyle = gr; |
||||
context.setLineCap('round'); |
||||
if (progress > 0) { |
||||
if (progress < 1) { |
||||
context.arc(this.centerX, this.centerY, this.radius, 1.5 * Math.PI, progress * 2 * Math.PI - 0.5 * Math.PI, false); |
||||
} else { |
||||
context.arc(this.centerX, this.centerY, this.radius, 0, 2 * Math.PI); |
||||
} |
||||
} |
||||
context.stroke(); |
||||
context.draw(); |
||||
} else { |
||||
context.draw(); |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,174 @@
@@ -0,0 +1,174 @@
|
||||
<style lang="less"> |
||||
@import "../style/reset.less"; |
||||
.nav { |
||||
position: fixed; |
||||
top: 0; |
||||
width: 100%; |
||||
z-index: 21; |
||||
} |
||||
.navbar{ |
||||
position: relative |
||||
} |
||||
.back-icon, .home-icon{ |
||||
width: 28px; |
||||
height: 100%; |
||||
position: absolute; |
||||
transform: translateY(-50%); |
||||
top: 50%; |
||||
display: flex; |
||||
} |
||||
.back-icon{ |
||||
left: 10px; |
||||
} |
||||
.home-icon{ |
||||
left: 44px |
||||
} |
||||
.home-icon:first-child { |
||||
left: 10px; |
||||
} |
||||
.back-icon image{ |
||||
width: 28px; |
||||
height: 28px; |
||||
margin: auto; |
||||
} |
||||
.home-icon image{ |
||||
width: 20px; |
||||
height: 20px; |
||||
margin: auto; |
||||
} |
||||
.nav-title, .nav-icon{ |
||||
position: absolute; |
||||
transform: translate(-50%, -50%); |
||||
left: 50%; |
||||
top: 50%; |
||||
font-size: 0; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
</style> |
||||
<template> |
||||
<view class='nav' style='height: {{status + navHeight}}px'> |
||||
<view class='status' style='height: {{status}}px;{{containerStyle}}'></view> |
||||
<view class='navbar' style='height:{{navHeight}}px;{{containerStyle}}'> |
||||
<view class='back-icon' wx:if="{{backIcon}}" @tap='back'> |
||||
<image src='{{backIcon}}'></image> |
||||
</view> |
||||
<view class='home-icon' wx:if="{{homeIcon}}" @tap='home'> |
||||
<image src='{{homeIcon}}'></image> |
||||
</view> |
||||
<view class='nav-icon' wx:if="{{titleImg}}"> |
||||
<image src='{{titleImg}}' style='{{iconStyle}}'></image> |
||||
</view> |
||||
<view class='nav-title' wx:if="{{titleText && !titleImg}}"> |
||||
<text style='{{textStyle}}'>{{titleText}}</text> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
<script> |
||||
import wepy from 'wepy'; |
||||
|
||||
export default class CircleView extends wepy.component { |
||||
props = { |
||||
background: { |
||||
type: String, |
||||
default: '#333' |
||||
}, |
||||
color: { |
||||
type: String, |
||||
default: 'rgba(255, 255, 255, 1)' |
||||
}, |
||||
titleText: { |
||||
type: String, |
||||
default: '导航栏' |
||||
}, |
||||
titleImg: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
backIcon: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
homeIcon: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
fontSize: { |
||||
type: Number, |
||||
default: 16 |
||||
}, |
||||
iconHeight: { |
||||
type: Number, |
||||
default: 19 |
||||
}, |
||||
iconWidth: { |
||||
type: Number, |
||||
default: 58 |
||||
} |
||||
}; |
||||
|
||||
data = { |
||||
status: 20, |
||||
navHeight: 44, |
||||
containerStyle: [], |
||||
textStyle: [], |
||||
iconStyle: [] |
||||
}; |
||||
methods = { |
||||
// 返回事件 |
||||
back() { |
||||
wx.navigateBack({ |
||||
delta: 1 |
||||
}); |
||||
// this.triggerEvent('back', {back: 1}); |
||||
}, |
||||
home() { |
||||
wx.reLaunch({ |
||||
url: '/pages/index' |
||||
}); |
||||
// this.triggerEvent('home', {}); |
||||
} |
||||
} |
||||
|
||||
onLoad() { |
||||
this.setNavSize(); |
||||
this.setStyle(); |
||||
} |
||||
// 通过获取系统信息计算导航栏高度 |
||||
setNavSize() { |
||||
let sysinfo = wx.getSystemInfoSync(); |
||||
let statusHeight = sysinfo.statusBarHeight; |
||||
let isiOS = sysinfo.system.indexOf('iOS') > -1; |
||||
let navHeight; |
||||
if (!isiOS) { |
||||
navHeight = 48; |
||||
} else { |
||||
navHeight = 44; |
||||
} |
||||
this.status = statusHeight; |
||||
this.navHeight = navHeight; |
||||
this.$apply(); |
||||
} |
||||
setStyle() { |
||||
let containerStyle; |
||||
let textStyle; |
||||
let iconStyle; |
||||
containerStyle = [ |
||||
'background:' + this.background |
||||
].join(';'); |
||||
textStyle = [ |
||||
'color:' + this.color, |
||||
'font-size:' + this.fontSize + 'px' |
||||
].join(';'); |
||||
iconStyle = [ |
||||
'width: ' + this.iconWidth + 'px', |
||||
'height: ' + this.iconHeight + 'px' |
||||
].join(';'); |
||||
this.containerStyle = containerStyle; |
||||
this.textStyle = textStyle; |
||||
this.iconStyle = iconStyle; |
||||
this.$apply(); |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
<style lang="less"> |
||||
|
||||
.common-toast { |
||||
/*display: none;*/ |
||||
position: fixed; |
||||
bottom: 100rpx; |
||||
left: 15%; |
||||
padding: 20rpx 10rpx; |
||||
width: 70%; |
||||
background: rgba(255, 255, 255, .9); |
||||
color: #333; |
||||
font-size: 36rpx; |
||||
line-height: 46rpx; |
||||
border-radius: 20rpx; |
||||
text-align: center; |
||||
white-space: normal; |
||||
z-index: 1; |
||||
} |
||||
</style> |
||||
<template> |
||||
<cover-view class="common-toast" wx:if="{{showToast}}"> |
||||
{{message}} |
||||
</cover-view> |
||||
</template> |
||||
<script> |
||||
import wepy from 'wepy'; |
||||
|
||||
export default class CommonToast extends wepy.component { |
||||
props = { |
||||
showToast: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
message: { |
||||
type: String, |
||||
default: '提示内容' |
||||
} |
||||
}; |
||||
watch = { |
||||
showToast (curVal, oldVal) { |
||||
if (curVal === true && oldVal === false) { |
||||
this.$emit('hide'); |
||||
} |
||||
} |
||||
} |
||||
methods = { |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
<style lang="less"> |
||||
@import "../plugins/wxParse/wxParse.wxss"; |
||||
.wxParse-img { |
||||
margin: 0 auto; |
||||
width: 100%; |
||||
min-height: 200rpx; |
||||
display: block; |
||||
background-color: transparent; |
||||
} |
||||
</style> |
||||
<template> |
||||
<import src="../plugins/wxParse/wxParse.wxml"/> |
||||
<block wx:for="{{htmlParserTpl.nodes}}" wx:key="{{index}}"> |
||||
<template is="wxParse0" data="{{item}}"/> |
||||
</block> |
||||
</template> |
||||
<script> |
||||
import wepy from 'wepy'; |
||||
import WxParse from '../plugins/wxParse/wxParse'; |
||||
export default class HTMLParser extends wepy.component { |
||||
props = { |
||||
parserName: { |
||||
type: String, |
||||
default: 'htmlParserName' |
||||
}, |
||||
parserContent: { |
||||
type: String, |
||||
default: "<p style='font-size: 32rpx; padding: 30rpx 0; text-align: center;'>没有任何内容</p>" |
||||
}, |
||||
parserType: { |
||||
type: String, |
||||
default: 'html' |
||||
}, |
||||
parserPadding: { |
||||
type: Number, |
||||
default: 0 |
||||
} |
||||
}; |
||||
data = { |
||||
htmlParserTpl: {} |
||||
}; |
||||
events = { |
||||
'htmlParser-broadcast': ($event, ...args) => { |
||||
} |
||||
}; |
||||
methods = { |
||||
htmlParserNotice() { |
||||
this.htmlParse(); |
||||
} |
||||
}; |
||||
async onLoad() { |
||||
this.htmlParse(); |
||||
}; |
||||
wxParseImgLoad(image) { |
||||
// let imgInfo = image.detail; |
||||
}; |
||||
htmlParse() { |
||||
/** |
||||
* WxParse.wxParse(bindName , type, data, target,imagePadding) |
||||
* 1.bindName绑定的数据名(必填) |
||||
* 2.type可以为html或者md(必填) |
||||
* 3.data为传入的具体数据(必填) |
||||
* 4.target为Page对象,一般为this(必填) |
||||
* 5.imagePadding为当图片自适应是左右的单一padding(默认为0,可选) |
||||
*/ |
||||
try { |
||||
let htmlContent = WxParse.wxParse(this.parserName, this.parserType, this.parserContent || this.props.parserContent.default, this, this.parserPadding); |
||||
// this.htmlParserTpl = this[this.parserName]; |
||||
this.htmlParserTpl = htmlContent[this.parserName]; |
||||
this.$apply(); |
||||
} catch (e) { |
||||
console.warn('kinerHtmlParser:', '没有任何内容需要转换', e); |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
<style lang="less"> |
||||
|
||||
.icon-button-container { |
||||
width:100%; |
||||
|
||||
height: 86rpx; |
||||
background:linear-gradient(270deg,rgba(55,188,155,1) 0%,rgba(140,193,82,1) 100%); |
||||
border-radius: 44rpx; |
||||
.icon-button-button { |
||||
|
||||
font-size:18px; |
||||
font-weight:400; |
||||
color:rgba(255,255,255,1); |
||||
line-height: 86rpx; |
||||
text-align: center; |
||||
|
||||
position: relative; |
||||
display: flex; |
||||
flex-direction: row; |
||||
justify-content: center; |
||||
align-items: center; |
||||
.confirm-icon { |
||||
width: 48rpx; |
||||
height: 48rpx; |
||||
margin-right: 22rpx; |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
</style> |
||||
<template> |
||||
<view class="icon-button-container" @tap="onClick"> |
||||
<view class="icon-button-button"> |
||||
<image class="confirm-icon" src="{{icon}}"></image> |
||||
<view>{{title}}</view> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
<script> |
||||
import wepy from 'wepy'; |
||||
|
||||
export default class IconButton extends wepy.component { |
||||
props = { |
||||
title: { |
||||
type: [String, Number], |
||||
default: '确定' |
||||
}, |
||||
|
||||
icon: { |
||||
type: [String], |
||||
default: '/images/cali.png' |
||||
} |
||||
} |
||||
|
||||
methods = { |
||||
onClick() { |
||||
this.$emit('onButtonClick'); |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,73 @@
@@ -0,0 +1,73 @@
|
||||
<style lang="less"> |
||||
|
||||
.icon-counter-container { |
||||
display: flex; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
box-sizing: border-box; |
||||
justify-content: center; |
||||
width: 100%; |
||||
height: 100%; |
||||
|
||||
.counter-num { |
||||
/*width:100px;*/ |
||||
height: 50rpx; |
||||
font-size: 36rpx; |
||||
font-weight:500; |
||||
color:rgba(72,207,173,1); |
||||
line-height:50rpx; |
||||
text-align: center; |
||||
margin-top: 12rpx; |
||||
span { |
||||
display: inline-block; |
||||
font-size: 28rpx; |
||||
font-weight:400; |
||||
margin-left: 10rpx; |
||||
|
||||
color:rgba(227,227,227,1); |
||||
line-height:40rpx; |
||||
} |
||||
} |
||||
|
||||
.counter-icon { |
||||
height: 52rpx; |
||||
width: 52rpx; |
||||
} |
||||
} |
||||
|
||||
.sport-counter-text { |
||||
font-size:14px; |
||||
font-weight:400; |
||||
color:rgba(255,255,255,1); |
||||
line-height:20px; |
||||
} |
||||
</style> |
||||
<template> |
||||
<view @tap="onClick"> |
||||
<view class="icon-counter-container"> |
||||
<image class="counter-icon" src="{{icon}}" mode="aspectFit" ></image> |
||||
<view class="counter-num">{{title}}<span class="span-font">{{unit}}</span></view> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
<script> |
||||
import wepy from 'wepy'; |
||||
|
||||
export default class IconCounterView extends wepy.component { |
||||
props = { |
||||
title: { |
||||
type: [String, Number], |
||||
default: '无' |
||||
}, |
||||
unit: { |
||||
type: [String], |
||||
default: '单位' |
||||
}, |
||||
|
||||
icon: { |
||||
type: [String], |
||||
default: '/images/cali.png' |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
<style lang="less"> |
||||
|
||||
.share-container { |
||||
display: flex; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
box-sizing: border-box; |
||||
justify-content: center; |
||||
|
||||
image { |
||||
width: 48rpx; |
||||
height: 48rpx; |
||||
} |
||||
} |
||||
|
||||
.share-text { |
||||
font-size: 28rpx; |
||||
font-weight: 400; |
||||
color: rgba(255, 255, 255, 1); |
||||
line-height: 40rpx; |
||||
margin-top: 4rpx; |
||||
} |
||||
</style> |
||||
<template> |
||||
<button open-type="share"> |
||||
<view class="share-container"> |
||||
<image src="/images/share-icon.png"></image> |
||||
<view class="share-text">分享</view> |
||||
</view> |
||||
</button> |
||||
</template> |
||||
<script> |
||||
import wepy from 'wepy'; |
||||
|
||||
export default class ShareIcon extends wepy.component { |
||||
methods = { |
||||
// onClick() { |
||||
// this.$emit('onShareClick'); |
||||
// } |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
<style lang="less"> |
||||
|
||||
.sport-counter-container { |
||||
display: flex; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
box-sizing: border-box; |
||||
justify-content: center; |
||||
|
||||
|
||||
.counter-num { |
||||
margin-top: -4rpx; |
||||
font-size: 48rpx; |
||||
font-weight: 500; |
||||
color: #48CFAD; |
||||
line-height: 66rpx; |
||||
|
||||
span { |
||||
font-size:30rpx; |
||||
line-height: 42rpx; |
||||
} |
||||
} |
||||
.share-text { |
||||
margin-top: 2rpx; |
||||
font-size: 28rpx; |
||||
font-weight: 400; |
||||
color: rgba(255,255,255,1); |
||||
line-height: 40rpx; |
||||
} |
||||
} |
||||
|
||||
</style> |
||||
<template> |
||||
<view @tap="onClick"> |
||||
<view class="sport-counter-container"> |
||||
<view class="share-text">{{title}}</view> |
||||
<view class="counter-num">{{num}}<span>{{unit}}</span></view> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
<script> |
||||
import wepy from 'wepy'; |
||||
|
||||
export default class SportCounterView extends wepy.component { |
||||
props = { |
||||
title: { |
||||
type: [String], |
||||
default: '无' |
||||
}, |
||||
unit: { |
||||
type: [String], |
||||
default: '单位' |
||||
}, |
||||
|
||||
num: { |
||||
type: [Number], |
||||
default: 0 |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,350 @@
@@ -0,0 +1,350 @@
|
||||
<style lang="less"> |
||||
.sport-canvas-container { |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
</style> |
||||
<template> |
||||
<slot class="sport-canvas-container" name="canvas">默认内容</slot> |
||||
</template> |
||||
<script> |
||||
import wepy from 'wepy'; |
||||
import moment from 'moment'; |
||||
|
||||
// let hasLoaded = true; |
||||
export default class SportLineView extends wepy.component { |
||||
props = { |
||||
startDate: { |
||||
type: [Number, String], |
||||
default: 2500 |
||||
}, |
||||
endDate: { |
||||
type: [Number, String], |
||||
default: 2500 |
||||
}, |
||||
daySteps: { |
||||
type: [Array], |
||||
default: [] |
||||
}, |
||||
canvasId: String, |
||||
drawPaddingLeft: { |
||||
type: [Number], |
||||
default: 0 |
||||
}, |
||||
drawPaddingRight: { |
||||
type: [Number], |
||||
default: 4 |
||||
} |
||||
} |
||||
|
||||
watch = { |
||||
startDate (curVal, oldVal) { |
||||
if (this.hasLoaded) { |
||||
this.calculate(); |
||||
this.draw(); |
||||
} |
||||
}, |
||||
endDate (curVal, oldVal) { |
||||
if (this.hasLoaded) { |
||||
this.calculate(); |
||||
this.draw(); |
||||
} |
||||
}, |
||||
daySteps (curVal, oldVal) { |
||||
if (this.hasLoaded) { |
||||
this.calculate(); |
||||
this.draw(); |
||||
} |
||||
}, |
||||
drawPaddingLeft (curVal, oldVal) { |
||||
if (this.hasLoaded) { |
||||
this.calculate(); |
||||
this.draw(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
hasLoaded = false; |
||||
canvasWidth= 0; |
||||
canvasHeight =0; |
||||
axisY = 0; |
||||
axisYLablePos = []; |
||||
axisLabelX = 52; |
||||
axisDrawWidth=0; |
||||
axisDayDistance=0; |
||||
pointInfo = []; |
||||
retries = 0; |
||||
barWidth = 6; |
||||
today = moment().hours(0).minutes(0).seconds(0).milliseconds(0).unix(); |
||||
|
||||
onLoad() { |
||||
this.getSize(); |
||||
} |
||||
|
||||
getSize() { |
||||
let that = this; |
||||
console.log(that.canvasId); |
||||
const query = wx.createSelectorQuery(); |
||||
query.select('#' + this.canvasId).boundingClientRect(); |
||||
query.selectViewport().scrollOffset(); |
||||
query.exec(function (res) { |
||||
console.log('selectViewport:', res); |
||||
let found = false; |
||||
res.forEach(item => { |
||||
if (item != null && item.id === that.canvasId) { |
||||
that.canvasWidth = item.width; |
||||
that.canvasHeight = item.height; |
||||
found = true; |
||||
} |
||||
}); |
||||
|
||||
if (found) { |
||||
console.log('line view onLoad---------'); |
||||
that.calculate(); |
||||
that.draw(); |
||||
that.hasLoaded = true; |
||||
console.log('line view onLoad--------- set hasLoaded to true', that); |
||||
// hasLoaded = true; |
||||
} |
||||
// else { |
||||
// that.retries ++; |
||||
// if (that.retries < 5) { |
||||
// setTimeout(function () { |
||||
// that.getSize(); |
||||
// },0); |
||||
// } |
||||
// } |
||||
}); |
||||
} |
||||
|
||||
setDefaultAxisY() { |
||||
let that = this; |
||||
let maxY = 10000; |
||||
|
||||
this.axisYLablePos = []; |
||||
[10000, 6000, 3000].forEach(item => { |
||||
let pos = that.axisY - (that.axisY - 10) * item / maxY; |
||||
that.axisYLablePos.push({ |
||||
label: item, |
||||
pos: pos |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
calculate() { |
||||
let that = this; |
||||
this.axisY = this.canvasHeight - 20; |
||||
this.axisDrawWidth = this.canvasWidth - this.axisLabelX - this.drawPaddingLeft - this.barWidth - this.drawPaddingRight; |
||||
this.axisDayDistance = Math.floor(this.axisDrawWidth / 6); |
||||
|
||||
if (this.daySteps.length === 0) { |
||||
this.pointInfo = []; |
||||
this.setDefaultAxisY(); |
||||
} else { |
||||
let tempSteps = JSON.parse(JSON.stringify(this.daySteps)); |
||||
tempSteps.sort((a, b) => { |
||||
return a.steps > b.steps; |
||||
}); |
||||
|
||||
// console.log('sort:', this.daySteps, tempSteps); |
||||
|
||||
let maxValue = tempSteps[tempSteps.length - 1].steps; |
||||
if (maxValue <= 0) { |
||||
this.setDefaultAxisY(); |
||||
this.pointInfo = []; |
||||
|
||||
maxValue = 10000; |
||||
} else { |
||||
let roundValue = 1000; |
||||
if (maxValue < 1500) { |
||||
roundValue = 200; |
||||
} |
||||
|
||||
maxValue = Math.ceil(maxValue * 1.0 / roundValue) * roundValue; |
||||
let delta = Math.ceil(maxValue / (3 * roundValue)) * roundValue; |
||||
|
||||
that.axisYLablePos = []; |
||||
[maxValue, maxValue - delta, maxValue - delta * 2].forEach(item => { |
||||
let pos = that.axisY - (that.axisY - 10) * item / maxValue; |
||||
that.axisYLablePos.push({ |
||||
label: item, |
||||
pos: pos |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
let pointInfo = []; |
||||
this.daySteps.forEach(item => { |
||||
let drawX = that.axisLabelX + that.drawPaddingLeft + (item.date - that.startDate) * that.axisDrawWidth / (that.endDate - that.startDate); |
||||
let drawY = that.axisY - (that.axisY - 10) * item.steps / maxValue; |
||||
|
||||
pointInfo.push({ |
||||
x: drawX, |
||||
y: drawY |
||||
}); |
||||
}); |
||||
|
||||
this.pointInfo = pointInfo; |
||||
// console.log('point info:', this.pointInfo); |
||||
} |
||||
} |
||||
|
||||
draw() { |
||||
const context = wx.createCanvasContext(this.canvasId); |
||||
// console.log('start draw:', this.canvasWidth, this.canvasHeight, this.startDate, this.endDate, this.axisDayDistance); |
||||
|
||||
context.clearRect(0, 0, this.canvasWidth, this.canvasHeight); |
||||
|
||||
this.drawAxis(context); |
||||
this.drawStepPointBar(context); |
||||
this.drawAxisX(context); |
||||
|
||||
context.draw(); |
||||
} |
||||
|
||||
drawAxis(ctx) { |
||||
let that = this; |
||||
|
||||
// draw axis y |
||||
ctx.save(); |
||||
ctx.setFontSize(12); |
||||
ctx.setStrokeStyle('#E3E3E3'); |
||||
ctx.setFillStyle('#9B9B9B'); |
||||
ctx.setLineDash([2, 3], 1); |
||||
ctx.setLineWidth(1); |
||||
ctx.setTextAlign('right'); |
||||
ctx.setTextBaseline('middle'); |
||||
|
||||
this.axisYLablePos.forEach(item => { |
||||
ctx.fillText(item.label, that.axisLabelX - 5, item.pos); |
||||
ctx.beginPath(); |
||||
ctx.moveTo(that.axisLabelX, item.pos); |
||||
ctx.lineTo(that.axisLabelX + that.canvasWidth, item.pos); |
||||
ctx.stroke(); |
||||
}); |
||||
ctx.restore(); |
||||
} |
||||
|
||||
drawAxisX(ctx) { |
||||
// let that = this; |
||||
|
||||
// draw x axis |
||||
ctx.save(); |
||||
ctx.setStrokeStyle('#666666'); |
||||
ctx.setLineWidth(1); |
||||
ctx.beginPath(); |
||||
ctx.moveTo(0, this.axisY); |
||||
ctx.lineTo(this.canvasWidth, this.axisY); |
||||
ctx.stroke(); |
||||
ctx.restore(); |
||||
|
||||
// draw x label |
||||
ctx.save(); |
||||
let days = (this.endDate - this.startDate) / (3600 * 24); |
||||
let delta = Math.floor(days / 6); |
||||
// console.log('start draw days:', days, delta); |
||||
ctx.setFontSize(12); |
||||
ctx.setFillStyle('#666666'); |
||||
ctx.setTextAlign('center'); |
||||
ctx.setTextBaseline('top'); |
||||
let y = this.axisY; |
||||
let x = this.axisLabelX + this.drawPaddingLeft; |
||||
let curTime = moment.unix(this.startDate); |
||||
for (let i = 0; i < 7; i++) { |
||||
let dateText = curTime.format('MM.DD'); |
||||
if (curTime.unix() === this.today) { |
||||
dateText = '今天'; |
||||
ctx.setFillStyle('#E3E3E3'); |
||||
} else { |
||||
ctx.setFillStyle('#9B9B9B'); |
||||
} |
||||
|
||||
ctx.fillText(dateText, x, y); |
||||
|
||||
if (i < 6) { |
||||
curTime.add(delta, 'days'); |
||||
} else { |
||||
curTime = moment.unix(this.endDate); |
||||
} |
||||
x = x + this.axisDayDistance; |
||||
} |
||||
ctx.restore(); |
||||
} |
||||
|
||||
drawStepPoint(ctx) { |
||||
if (this.pointInfo.length === 0) { |
||||
return; |
||||
} |
||||
|
||||
ctx.save(); |
||||
ctx.beginPath(); |
||||
ctx.setStrokeStyle('#8CC152'); |
||||
ctx.setLineWidth(2); |
||||
|
||||
ctx.moveTo(this.pointInfo[0].x, this.pointInfo[0].y); |
||||
|
||||
let i; |
||||
for (i = 1; i < this.pointInfo.length; i++) { |
||||
let xm = (this.pointInfo[i - 1].x + this.pointInfo[i].x) / 2; |
||||
|
||||
let cx1 = xm; |
||||
let cy1 = this.pointInfo[i - 1].y; |
||||
let cx2 = xm; |
||||
let cy2 = this.pointInfo[i].y; |
||||
|
||||
ctx.bezierCurveTo(cx1, cy1, cx2, cy2, this.pointInfo[i].x, this.pointInfo[i].y); |
||||
} |
||||
ctx.stroke(); |
||||
ctx.restore(); |
||||
|
||||
ctx.save(); |
||||
// console.log('draw:', this.daySteps.length, this.daySteps); |
||||
|
||||
ctx.setStrokeStyle('#8CC152'); |
||||
ctx.setLineWidth(1); |
||||
ctx.setFillStyle('#ED5565'); |
||||
|
||||
this.pointInfo.forEach(item => { |
||||
ctx.beginPath(); |
||||
ctx.arc(item.x, item.y, 4, 0, 2 * Math.PI); |
||||
ctx.fill(); |
||||
}); |
||||
ctx.restore(); |
||||
} |
||||
|
||||
drawStepPointBar(ctx) { |
||||
if (this.pointInfo.length === 0) { |
||||
return; |
||||
} |
||||
|
||||
let lineWidth = 6; |
||||
let radiusCap = lineWidth / 2; |
||||
ctx.save(); |
||||
ctx.setStrokeStyle('#8CC152'); |
||||
ctx.setLineWidth(lineWidth); |
||||
ctx.setLineCap('round'); |
||||
|
||||
ctx.moveTo(this.pointInfo[0].x, this.pointInfo[0].y); |
||||
|
||||
this.pointInfo.forEach(point => { |
||||
let grd = ctx.createLinearGradient(point.x, this.axisY, point.x, point.y); |
||||
grd.addColorStop(0, '#48CFAD'); |
||||
grd.addColorStop(1, '#A0D486'); |
||||
ctx.setStrokeStyle(grd); |
||||
|
||||
ctx.save(); |
||||
ctx.rect(point.x - radiusCap, point.y, lineWidth, this.axisY - point.y); |
||||
ctx.clip(); |
||||
|
||||
ctx.beginPath(); |
||||
ctx.moveTo(point.x, this.axisY); |
||||
ctx.lineTo(point.x, point.y + radiusCap); |
||||
ctx.stroke(); |
||||
|
||||
ctx.restore(); |
||||
}); |
||||
|
||||
ctx.restore(); |
||||
} |
||||
} |
||||
</script> |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
export default { |
||||
apiHost: __API_HOST__, |
||||
getApiHost() { |
||||
var platForm = wx.getStorageSync('plat_form'); |
||||
console.log(platForm); |
||||
if (platForm.indexOf('STORE') !== -1) { |
||||
return __PRO__ |
||||
? 'https://education.diabetes.com.cn/api' |
||||
: 'https://nn-dp.chinacloudsites.cn/api'; |
||||
} |
||||
|
||||
return __PRO__ |
||||
? 'https://app.diabetes.hbraas.com' |
||||
: 'https://app.diabetes.hbraas.com'; |
||||
} |
||||
}; |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 219 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 197 B |
After Width: | Height: | Size: 334 B |
After Width: | Height: | Size: 301 B |
After Width: | Height: | Size: 529 B |
After Width: | Height: | Size: 326 B |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 371 B |
After Width: | Height: | Size: 726 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 432 B |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 8.8 KiB |
After Width: | Height: | Size: 387 B |
After Width: | Height: | Size: 695 B |
After Width: | Height: | Size: 764 B |
After Width: | Height: | Size: 1.1 KiB |