@@ -0,0 +1,31 @@ | |||
/* | |||
* Eslint config file | |||
* Documentation: https://eslint.org/docs/user-guide/configuring/ | |||
* Install the Eslint extension before using this feature. | |||
*/ | |||
module.exports = { | |||
env: { | |||
es6: true, | |||
browser: true, | |||
node: true, | |||
}, | |||
ecmaFeatures: { | |||
modules: true, | |||
}, | |||
parserOptions: { | |||
ecmaVersion: 2018, | |||
sourceType: 'module', | |||
}, | |||
globals: { | |||
wx: true, | |||
App: true, | |||
Page: true, | |||
getCurrentPages: true, | |||
getApp: true, | |||
Component: true, | |||
requirePlugin: true, | |||
requireMiniProgram: true, | |||
}, | |||
// extends: 'eslint:recommended', | |||
rules: {}, | |||
} |
@@ -0,0 +1,9 @@ | |||
const {request} = require("../request/index") | |||
export const userLogin = function (data) { | |||
return request({ | |||
url: '/member/user', | |||
method: 'POST', | |||
data | |||
}) | |||
} |
@@ -0,0 +1,19 @@ | |||
// app.js | |||
App({ | |||
onLaunch() { | |||
// 展示本地存储能力 | |||
const logs = wx.getStorageSync('logs') || [] | |||
logs.unshift(Date.now()) | |||
wx.setStorageSync('logs', logs) | |||
// 登录 | |||
wx.login({ | |||
success: res => { | |||
// 发送 res.code 到后台换取 openId, sessionKey, unionId | |||
} | |||
}) | |||
}, | |||
globalData: { | |||
userInfo: null | |||
} | |||
}) |
@@ -0,0 +1,55 @@ | |||
{ | |||
"pages": [ | |||
"pages/home/home", | |||
"pages/task/task", | |||
"pages/mine/mine", | |||
"pages/login/login" | |||
], | |||
"tabBar": { | |||
"color": "#939393", | |||
"borderStyle": "white", | |||
"selectedColor": "#477DF3", | |||
"list": [ | |||
{ | |||
"pagePath": "pages/home/home", | |||
"text": "首页", | |||
"iconPath": "./assets/tabBar/home.png", | |||
"selectedIconPath": "./assets/tabBar/home_selected.png" | |||
}, | |||
{ | |||
"pagePath": "pages/task/task", | |||
"text": "任务", | |||
"iconPath": "./assets/tabBar/task.png", | |||
"selectedIconPath": "./assets/tabBar/task_selected.png" | |||
}, | |||
{ | |||
"pagePath": "pages/mine/mine", | |||
"text": "我的", | |||
"iconPath": "./assets/tabBar/mine.png", | |||
"selectedIconPath": "./assets/tabBar/mine_selected.png" | |||
} | |||
] | |||
}, | |||
"subPackages": [ | |||
{ | |||
"root": "package_A", | |||
"pages":[] | |||
}, | |||
{ | |||
"root": "package_B", | |||
"pages":[] | |||
}, | |||
{ | |||
"root": "package_C", | |||
"pages":[] | |||
} | |||
], | |||
"window": { | |||
"backgroundTextStyle": "light", | |||
"navigationBarBackgroundColor": "#fff", | |||
"navigationBarTitleText": "Weixin", | |||
"navigationBarTextStyle": "black" | |||
}, | |||
"style": "v2", | |||
"sitemapLocation": "sitemap.json" | |||
} |
@@ -0,0 +1,10 @@ | |||
/**app.wxss**/ | |||
.container { | |||
height: 100%; | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
justify-content: space-between; | |||
padding: 200rpx 0; | |||
box-sizing: border-box; | |||
} |
@@ -0,0 +1,48 @@ | |||
// components/List/index.js | |||
Component({ | |||
/** | |||
* 组件的属性列表 | |||
*/ | |||
properties: { | |||
url: { | |||
type: String | |||
}, | |||
dataPath: { | |||
type: String | |||
}, | |||
list: { | |||
type: Array | |||
}, | |||
params: { | |||
type: Object, | |||
}, | |||
limit: { | |||
type: Number, | |||
value: 10 | |||
}, | |||
scrolling:{ | |||
type:Boolean, | |||
value:true, | |||
}, | |||
emptyText:{ | |||
type:String, | |||
value:"" | |||
} | |||
}, | |||
/** | |||
* 组件的初始数据 | |||
*/ | |||
data: { | |||
page: 1, | |||
limit: 10, | |||
loading: false | |||
}, | |||
/** | |||
* 组件的方法列表 | |||
*/ | |||
methods: { | |||
} | |||
}) |
@@ -0,0 +1,4 @@ | |||
{ | |||
"component": true, | |||
"usingComponents": {} | |||
} |
@@ -0,0 +1,11 @@ | |||
<!--components/List/index.wxml--> | |||
<scroll-view class="list {{list.length>0?'':'min-height'}}" scroll-y="{{scrolling}}" bindscrolltolower="loadMore"> | |||
<slot></slot> | |||
<view class="empty" wx:if="{{!loading && list.length==0}}"> | |||
<image class="image" src="/assets/img/empty.png" mode="aspectFit" lazy-load="false"> | |||
</image> | |||
<view class="empty-text" wx:if="{{emptyText}}"> | |||
{{emptyText}} | |||
</view> | |||
</view> | |||
</scroll-view> |
@@ -0,0 +1 @@ | |||
/* components/List/index.wxss */ |
@@ -0,0 +1,23 @@ | |||
// components/Select/index.js | |||
Component({ | |||
/** | |||
* 组件的属性列表 | |||
*/ | |||
properties: { | |||
}, | |||
/** | |||
* 组件的初始数据 | |||
*/ | |||
data: { | |||
}, | |||
/** | |||
* 组件的方法列表 | |||
*/ | |||
methods: { | |||
} | |||
}) |
@@ -0,0 +1,4 @@ | |||
{ | |||
"component": true, | |||
"usingComponents": {} | |||
} |
@@ -0,0 +1,2 @@ | |||
<!--components/Select/index.wxml--> | |||
<text>components/Select/index.wxml</text> |
@@ -0,0 +1 @@ | |||
/* components/Select/index.wxss */ |
@@ -0,0 +1,23 @@ | |||
// components/Tab/index.js | |||
Component({ | |||
/** | |||
* 组件的属性列表 | |||
*/ | |||
properties: { | |||
}, | |||
/** | |||
* 组件的初始数据 | |||
*/ | |||
data: { | |||
}, | |||
/** | |||
* 组件的方法列表 | |||
*/ | |||
methods: { | |||
} | |||
}) |
@@ -0,0 +1,4 @@ | |||
{ | |||
"component": true, | |||
"usingComponents": {} | |||
} |
@@ -0,0 +1,2 @@ | |||
<!--components/Tab/index.wxml--> | |||
<text>components/Tab/index.wxml</text> |
@@ -0,0 +1 @@ | |||
/* components/Tab/index.wxss */ |
@@ -0,0 +1,24 @@ | |||
// package_C/component/table/table.js | |||
Component({ | |||
/** | |||
* 组件的属性列表 | |||
*/ | |||
properties: { | |||
data: {type: Array}, | |||
columns: {type: Array} | |||
}, | |||
/** | |||
* 组件的初始数据 | |||
*/ | |||
data: { | |||
}, | |||
/** | |||
* 组件的方法列表 | |||
*/ | |||
methods: { | |||
} | |||
}) |
@@ -0,0 +1,4 @@ | |||
{ | |||
"component": true, | |||
"usingComponents": {} | |||
} |
@@ -0,0 +1,16 @@ | |||
<!--package_C/component/table/table.wxml--> | |||
<view class="table_container"> | |||
<view class="table_title"> | |||
<text class="table_item" style="width:{{item.width}}" wx:for="{{columns}}" wx:key="index">{{item.title}}</text> | |||
</view> | |||
<view class="table_data"> | |||
<view style="background: {{ index%2 == 1 ? '#F5F7F9' : '#fff' }}" class="data_item" wx:for="{{data}}" wx:key="index"> | |||
<view class="table_item" style="width: {{columns[0].width}}">{{item.name}}</view> | |||
<view class="table_item" style="width: {{columns[1].width}}">{{item.y}}/{{item.countQu || item.sumqu}}</view> | |||
<view class="table_item" style="width: {{columns[2].width}}">{{item.a}}</view> | |||
<view class="table_item" style="width: {{columns[3].width}}">{{item.b}}</view> | |||
<view class="table_item" style="width: {{columns[4].width}}">{{item.c}}</view> | |||
<view class="table_item" style="width: {{columns[5].width}}">{{item.d}}</view> | |||
</view> | |||
</view> | |||
</view> |
@@ -0,0 +1,32 @@ | |||
/* package_C/component/table/table.wxss */ | |||
.table_container { | |||
width: 100%; | |||
margin: 24rpx 0; | |||
color: rgba(51, 51, 51, 1); | |||
border: 1rpx solid #efefef; | |||
} | |||
.table_title{ | |||
width: 100%; | |||
padding: 22rpx; | |||
background-color: #F5F7F9; | |||
display: flex; | |||
justify-content: space-between; | |||
align-items: center; | |||
font-size: 27rpx; | |||
font-weight: 700; | |||
} | |||
.table_data { | |||
width: 100%; | |||
color: rgba(51, 51, 51, 1); | |||
font-size: 26rpx; | |||
} | |||
.data_item { | |||
width: 100%; | |||
padding: 20rpx; | |||
display: flex; | |||
justify-content: space-between; | |||
align-items: center; | |||
} | |||
.table_item { | |||
text-align: center; | |||
} |
@@ -0,0 +1,222 @@ | |||
import WxCanvas from './wx-canvas'; | |||
import * as echarts from './echarts'; | |||
let ctx; | |||
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]) | |||
const num2 = parseInt(v2[i]) | |||
if (num1 > num2) { | |||
return 1 | |||
} else if (num1 < num2) { | |||
return -1 | |||
} | |||
} | |||
return 0 | |||
} | |||
Component({ | |||
properties: { | |||
canvasId: { | |||
type: String, | |||
value: 'ec-canvas' | |||
}, | |||
ec: { | |||
type: Object | |||
}, | |||
forceUseOldCanvas: { | |||
type: Boolean, | |||
value: false | |||
} | |||
}, | |||
data: { | |||
isUseNewCanvas: false | |||
}, | |||
ready: function () { | |||
// Disable prograssive because drawImage doesn't support DOM as parameter | |||
// See https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.drawImage.html | |||
echarts.registerPreprocessor(option => { | |||
if (option && option.series) { | |||
if (option.series.length > 0) { | |||
option.series.forEach(series => { | |||
series.progressive = 0; | |||
}); | |||
} | |||
else if (typeof option.series === 'object') { | |||
option.series.progressive = 0; | |||
} | |||
} | |||
}); | |||
if (!this.data.ec) { | |||
console.warn('组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" ' | |||
+ 'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>'); | |||
return; | |||
} | |||
if (!this.data.ec.lazyLoad) { | |||
this.init(); | |||
} | |||
}, | |||
methods: { | |||
init: function (callback) { | |||
const version = wx.getSystemInfoSync().SDKVersion | |||
const canUseNewCanvas = compareVersion(version, '2.9.0') >= 0; | |||
const forceUseOldCanvas = this.data.forceUseOldCanvas; | |||
const isUseNewCanvas = canUseNewCanvas && !forceUseOldCanvas; | |||
this.setData({ isUseNewCanvas }); | |||
if (forceUseOldCanvas && canUseNewCanvas) { | |||
console.warn('开发者强制使用旧canvas,建议关闭'); | |||
} | |||
if (isUseNewCanvas) { | |||
// console.log('微信基础库版本大于2.9.0,开始使用<canvas type="2d"/>'); | |||
// 2.9.0 可以使用 <canvas type="2d"></canvas> | |||
this.initByNewWay(callback); | |||
} else { | |||
const isValid = compareVersion(version, '1.9.91') >= 0 | |||
if (!isValid) { | |||
console.error('微信基础库版本过低,需大于等于 1.9.91。' | |||
+ '参见:https://github.com/ecomfe/echarts-for-weixin' | |||
+ '#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82'); | |||
return; | |||
} else { | |||
console.warn('建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能'); | |||
this.initByOldWay(callback); | |||
} | |||
} | |||
}, | |||
initByNewWay(callback) { | |||
// version >= 2.9.0:使用新的方式初始化 | |||
const query = wx.createSelectorQuery().in(this) | |||
query | |||
.select('.ec-canvas') | |||
.fields({ node: true, size: true }) | |||
.exec(res => { | |||
const canvasNode = res[0].node | |||
this.canvasNode = canvasNode | |||
const canvasDpr = wx.getSystemInfoSync().pixelRatio | |||
const canvasWidth = res[0].width | |||
const canvasHeight = res[0].height | |||
const ctx = canvasNode.getContext('2d') | |||
const canvas = new WxCanvas(ctx, this.data.canvasId, true, canvasNode) | |||
echarts.setCanvasCreator(() => { | |||
return canvas | |||
}) | |||
if (typeof callback === 'function') { | |||
this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr) | |||
} else if (this.data.ec && typeof this.data.ec.onInit === 'function') { | |||
this.chart = this.data.ec.onInit(canvas, canvasWidth, canvasHeight, canvasDpr) | |||
} else { | |||
this.triggerEvent('init', { | |||
canvas: canvas, | |||
width: canvasWidth, | |||
height: canvasHeight, | |||
dpr: canvasDpr | |||
}) | |||
} | |||
}) | |||
}, | |||
canvasToTempFilePath(opt) { | |||
if (this.data.isUseNewCanvas) { | |||
// 新版 | |||
const query = wx.createSelectorQuery().in(this) | |||
query | |||
.select('.ec-canvas') | |||
.fields({ node: true, size: true }) | |||
.exec(res => { | |||
const canvasNode = res[0].node | |||
opt.canvas = canvasNode | |||
wx.canvasToTempFilePath(opt) | |||
}) | |||
} else { | |||
// 旧的 | |||
if (!opt.canvasId) { | |||
opt.canvasId = this.data.canvasId; | |||
} | |||
ctx.draw(true, () => { | |||
wx.canvasToTempFilePath(opt, this); | |||
}); | |||
} | |||
}, | |||
touchStart(e) { | |||
if (this.chart && e.touches.length > 0) { | |||
var touch = e.touches[0]; | |||
var handler = this.chart.getZr().handler; | |||
handler.dispatch('mousedown', { | |||
zrX: touch.x, | |||
zrY: touch.y | |||
}); | |||
handler.dispatch('mousemove', { | |||
zrX: touch.x, | |||
zrY: touch.y | |||
}); | |||
handler.processGesture(wrapTouch(e), 'start'); | |||
} | |||
}, | |||
touchMove(e) { | |||
if (this.chart && e.touches.length > 0) { | |||
var touch = e.touches[0]; | |||
var handler = this.chart.getZr().handler; | |||
handler.dispatch('mousemove', { | |||
zrX: touch.x, | |||
zrY: touch.y | |||
}); | |||
handler.processGesture(wrapTouch(e), 'change'); | |||
} | |||
}, | |||
touchEnd(e) { | |||
if (this.chart) { | |||
const touch = e.changedTouches ? e.changedTouches[0] : {}; | |||
var handler = this.chart.getZr().handler; | |||
handler.dispatch('mouseup', { | |||
zrX: touch.x, | |||
zrY: touch.y | |||
}); | |||
handler.dispatch('click', { | |||
zrX: touch.x, | |||
zrY: touch.y | |||
}); | |||
handler.processGesture(wrapTouch(e), 'end'); | |||
} | |||
} | |||
} | |||
}); | |||
function wrapTouch(event) { | |||
for (let i = 0; i < event.touches.length; ++i) { | |||
const touch = event.touches[i]; | |||
touch.offsetX = touch.x; | |||
touch.offsetY = touch.y; | |||
} | |||
return event; | |||
} |
@@ -0,0 +1,4 @@ | |||
{ | |||
"component": true, | |||
"usingComponents": {} | |||
} |
@@ -0,0 +1,4 @@ | |||
<!-- 新的:接口对其了H5 --> | |||
<canvas wx:if="{{isUseNewCanvas}}" type="2d" class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas> | |||
<!-- 旧的 --> | |||
<canvas wx:else class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas> |
@@ -0,0 +1,4 @@ | |||
.ec-canvas { | |||
width: 100%; | |||
height: 100%; | |||
} |
@@ -0,0 +1,105 @@ | |||
export default class WxCanvas { | |||
constructor(ctx, canvasId, isNew, canvasNode) { | |||
this.ctx = ctx; | |||
this.canvasId = canvasId; | |||
this.chart = null; | |||
this.isNew = isNew | |||
if (isNew) { | |||
this.canvasNode = canvasNode; | |||
} | |||
else { | |||
this._initStyle(ctx); | |||
} | |||
// this._initCanvas(zrender, ctx); | |||
this._initEvent(); | |||
} | |||
getContext(contextType) { | |||
if (contextType === '2d') { | |||
return this.ctx; | |||
} | |||
} | |||
// canvasToTempFilePath(opt) { | |||
// if (!opt.canvasId) { | |||
// opt.canvasId = this.canvasId; | |||
// } | |||
// return wx.canvasToTempFilePath(opt, this); | |||
// } | |||
setChart(chart) { | |||
this.chart = chart; | |||
} | |||
attachEvent() { | |||
// noop | |||
} | |||
detachEvent() { | |||
// noop | |||
} | |||
_initCanvas(zrender, ctx) { | |||
zrender.util.getContext = function () { | |||
return ctx; | |||
}; | |||
zrender.util.$override('measureText', function (text, font) { | |||
ctx.font = font || '12px sans-serif'; | |||
return ctx.measureText(text); | |||
}); | |||
} | |||
_initStyle(ctx) { | |||
ctx.createRadialGradient = () => { | |||
return ctx.createCircularGradient(arguments); | |||
}; | |||
} | |||
_initEvent() { | |||
this.event = {}; | |||
const eventNames = [{ | |||
wxName: 'touchStart', | |||
ecName: 'mousedown' | |||
}, { | |||
wxName: 'touchMove', | |||
ecName: 'mousemove' | |||
}, { | |||
wxName: 'touchEnd', | |||
ecName: 'mouseup' | |||
}, { | |||
wxName: 'touchEnd', | |||
ecName: 'click' | |||
}]; | |||
eventNames.forEach(name => { | |||
this.event[name.wxName] = e => { | |||
const touch = e.touches[0]; | |||
this.chart.getZr().handler.dispatch(name.ecName, { | |||
zrX: name.wxName === 'tap' ? touch.clientX : touch.x, | |||
zrY: name.wxName === 'tap' ? touch.clientY : touch.y | |||
}); | |||
}; | |||
}); | |||
} | |||
set width(w) { | |||
if (this.canvasNode) this.canvasNode.width = w | |||
} | |||
set height(h) { | |||
if (this.canvasNode) this.canvasNode.height = h | |||
} | |||
get width() { | |||
if (this.canvasNode) | |||
return this.canvasNode.width | |||
return 0 | |||
} | |||
get height() { | |||
if (this.canvasNode) | |||
return this.canvasNode.height | |||
return 0 | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
const __request_base_url__ = { | |||
develop: "https://api.gongche.dev.taauav.com/api", | |||
trial: "https://api.gongche.dev.taauav.com/api", | |||
release: "https://api.gongche.taauav.com/api" | |||
} | |||
const platform = wx.getSystemInfoSync().platform | |||
const envVersion = wx.getAccountInfoSync().miniProgram.envVersion | |||
const env = platform === 'devtools' ? 'develop' : ( envVersion || 'release' ) | |||
const baseurl = __request_base_url__[env] | |||
export default baseurl |
@@ -0,0 +1,94 @@ | |||
// pages/home/home.js | |||
Page({ | |||
/** | |||
* 页面的初始数据 | |||
*/ | |||
data: { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面加载 | |||
*/ | |||
onLoad: function (options) { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面初次渲染完成 | |||
*/ | |||
onReady: function () { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面显示 | |||
*/ | |||
onShow: function () { | |||
let arr = [1, 2, 3, 4, 5] | |||
let k = 4, x = 3 | |||
/** * | |||
* @param {number[]} arr | |||
* @param {number} k | |||
* @param {number} x | |||
* @return {number[]} | |||
* */ | |||
var findClosestElements = function(arr, k, x) { | |||
var getCloseIndex = function(left,right){ | |||
if(left>=right) return left; | |||
let mid=(left+right)>>1; | |||
let result | |||
if(arr[mid]>=x){ | |||
result=getCloseIndex(left,mid-1) | |||
}else{ | |||
result=getCloseIndex(mid+1,right) | |||
} | |||
return result | |||
} | |||
const len=arr.length; | |||
let right=getCloseIndex(0,len-1); | |||
let left=0; | |||
if(right>0&&arr[right]>x) right--; | |||
if(right+1>=k) left=right+1-k; else right+=(k-(right+1)); | |||
while(right<len-1&&((x-arr[left])>(arr[right+1]-x))){ left++; right++; } return arr.slice(left,right+1); | |||
} | |||
const res = findClosestElements(arr, k, x) | |||
console.log(res); | |||
}, | |||
/** | |||
* 生命周期函数--监听页面隐藏 | |||
*/ | |||
onHide: function () { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面卸载 | |||
*/ | |||
onUnload: function () { | |||
}, | |||
/** | |||
* 页面相关事件处理函数--监听用户下拉动作 | |||
*/ | |||
onPullDownRefresh: function () { | |||
}, | |||
/** | |||
* 页面上拉触底事件的处理函数 | |||
*/ | |||
onReachBottom: function () { | |||
}, | |||
/** | |||
* 用户点击右上角分享 | |||
*/ | |||
onShareAppMessage: function () { | |||
} | |||
}) |
@@ -0,0 +1,3 @@ | |||
{ | |||
"usingComponents": {} | |||
} |
@@ -0,0 +1,4 @@ | |||
<!--pages/home/home.wxml--> | |||
<view class="home_container"> | |||
</view> |
@@ -0,0 +1 @@ | |||
/* pages/home/home.wxss */ |
@@ -0,0 +1,180 @@ | |||
// pages/login/login.js | |||
Page({ | |||
/** | |||
* 页面的初始数据 | |||
*/ | |||
data: { | |||
form: { | |||
username: '', | |||
password: '' | |||
}, | |||
remember: false, | |||
formRules: { | |||
username: { | |||
validator: function(value) { | |||
return value.trim() != '' | |||
}, | |||
tips: '请输入用户名', | |||
placeholder: '请输入用户名' | |||
}, | |||
password: { | |||
validator: function(value) { | |||
return value.trim() != '' | |||
}, | |||
tips: '请输入密码', | |||
placeholder: '请输入密码' | |||
} | |||
} | |||
}, | |||
/** | |||
* 生命周期函数--监听页面加载 | |||
*/ | |||
onLoad: function (options) { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面初次渲染完成 | |||
*/ | |||
onReady: function () { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面显示 | |||
*/ | |||
onShow: function () { | |||
// 隐藏返回图标 | |||
wx.hideHomeButton(); | |||
}, | |||
checkboxChange(e) { | |||
let checked = this.data.remember | |||
this.setData({remember: !checked}) | |||
}, | |||
bindValue(e) { | |||
let name = e.currentTarget.dataset.name; | |||
let form = this.data.form; | |||
form[name] = e.detail.value; | |||
this.setData({ | |||
form, | |||
}) | |||
this.validate(name, e.detail.value) | |||
}, | |||
validate(name) { | |||
let formRules = this.data.formRules; | |||
let validator = this.data.formRules[name].validator | |||
let result = validator ? !validator(this.data.form[name]) : false; | |||
formRules[name].warning = result | |||
this.setData({ | |||
formRules | |||
}) | |||
return result | |||
}, | |||
validateForm() { | |||
return new Promise((resolve, reject) => { | |||
try { | |||
let formRules = this.data.formRules; | |||
let result = false; | |||
for (let key in formRules) { | |||
let temp = this.validate(key) | |||
if (temp) { | |||
result = temp | |||
} | |||
} | |||
resolve(!result) | |||
} catch (e) { | |||
reject(e) | |||
} | |||
}) | |||
}, | |||
submitForm() { | |||
this.validateForm().then(res => { | |||
if (res) { | |||
wx.showLoading({title: "登录中", mask:true}); | |||
// 判断是否有记住密码 | |||
if(this.data.remember) { | |||
wx.setStorageSync('remember', true) | |||
wx.setStorageSync('loginForm', this.data.form) | |||
} else { | |||
wx.removeStorageSync('remember') | |||
wx.removeStorageSync('loginForm') | |||
} | |||
wx.request({ | |||
url: baseURL+"/member/login", | |||
method: "POST", | |||
data: this.data.form, | |||
header: { | |||
'content-type': 'application/json' | |||
}, | |||
success(res) { | |||
if (res.data.code == 0) { | |||
// 以token获取用户信息 | |||
let token = res.data.data | |||
wx.setStorageSync('token', token) // token存入storage | |||
wx.request({ | |||
url: baseURL+'/member/user', | |||
method: "POST", | |||
header: { | |||
'content-type': 'application/x-www-form-urlencoded', | |||
"authorization": token | |||
}, | |||
success: (res) => { | |||
wx.setStorageSync('userInfo', res.data.data) | |||
let app=getApp(); | |||
let observe=app.globalData.observe; | |||
let getToDoNum=app.getToDoNum; | |||
// 跳转至tabBar | |||
wx.switchTab({ | |||
url: '/pages/home/home' | |||
}) | |||
getToDoNum(observe).then((res)=>{ | |||
if(res){ | |||
if (observe.value > 0) { | |||
wx.setTabBarBadge({ | |||
index: 1, | |||
text: observe.value + "", | |||
}) | |||
} else { | |||
wx.removeTabBarBadge({ | |||
index: 1, | |||
}) | |||
} | |||
}else{ | |||
wx.removeTabBarBadge({ | |||
index: 1, | |||
}) | |||
} | |||
}).catch(e=>{console.log(e)}); | |||
}, | |||
fail: (res) => { | |||
}, | |||
complete: (res) => { | |||
wx.hideLoading() | |||
}, | |||
}) | |||
} | |||
else{ | |||
wx.hideLoading() | |||
wx.showToast({ | |||
title: res.data.msg, | |||
icon: 'error', | |||
image: '', | |||
duration: 1500, | |||
}); | |||
} | |||
}, | |||
fail(error) { | |||
wx.hideLoading(); | |||
wx.showToast({ | |||
title:error.errMsg, | |||
icon:"error", | |||
duration:1000, | |||
}) | |||
} | |||
}) | |||
} | |||
}) | |||
} | |||
}) |
@@ -0,0 +1,4 @@ | |||
{ | |||
"usingComponents": {}, | |||
"navigationBarTitleText": "登录" | |||
} |
@@ -0,0 +1,17 @@ | |||
<!--pages/login/login.wxml--> | |||
<view class="login_box"> | |||
<form class="form_box" bindsubmit="submitForm"> | |||
<view class="form-item {{item.warning?'warning':''}}" wx:for="{{formRules}}" wx:key="index"> | |||
<text>{{item.title}}</text> | |||
<input type="{{item.type||'text'}}" placeholder="{{item.placeholder}}" value="{{form[index]}}" | |||
password="{{item.isPassword}}" data-name="{{index}}" bindinput="bindValue" name="{{index}}" bindblur="bindValue" /> | |||
<text class="tips">{{item.tips}}</text> | |||
</view> | |||
<view class="check_contanier"> | |||
<label class="check_lable" bindtap="checkboxChange"> | |||
<checkbox checked="{{rememberChecked}}" class="check_box" />记住密码 | |||
</label> | |||
</view> | |||
<button size="default" style="width: 100%; height: 80rpx;" class="login_btn" formType="submit">登 录</button> | |||
</form> | |||
</view> |
@@ -0,0 +1,75 @@ | |||
/* pages/login/login.wxss */ | |||
.login_box { | |||
width: 100vw; | |||
height: 100vh; | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: center; | |||
align-items: center; | |||
} | |||
.form_box { | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: flex-start; | |||
align-items: flex-end; | |||
} | |||
.login_box .form-item{ | |||
padding-bottom:50rpx; | |||
position: relative; | |||
} | |||
.login_box .form-item input{ | |||
width: 532rpx; | |||
height: 80rpx; | |||
padding-left: 20px; | |||
border-radius: 39rpx; | |||
background-color: #fafafa; | |||
} | |||
.login_box .tips{ | |||
position: absolute; | |||
bottom: 0; | |||
left:0; | |||
color: red; | |||
font-size:26rpx; | |||
transform: translate(20rpx,-10rpx); | |||
display: none; | |||
} | |||
.login_box .form-item.warning .tips{ | |||
display: block; | |||
} | |||
.check_lable { | |||
box-sizing: border-box; | |||
height: 60rpx; | |||
display: flex; | |||
justify-content: flex-end; | |||
align-items: center; | |||
color: #b0b0b0; | |||
} | |||
.check_contanier { | |||
width: 100%; | |||
display: flex; | |||
justify-content: flex-end; | |||
align-items: center; | |||
} | |||
.check_box { | |||
width: 30rpx; | |||
height: 30rpx; | |||
margin-right: 20rpx; | |||
} | |||
radio-group { | |||
width: 200rpx; | |||
align-self: flex-end !important; | |||
} | |||
checkbox .wx-checkbox-input { | |||
width: 30rpx; | |||
height: 30rpx; | |||
margin-bottom: 10rpx; | |||
} | |||
.login_btn { | |||
margin-top: 80rpx; | |||
color: #fff; | |||
font-weight: normal; | |||
border-radius: 39rpx; | |||
background-color: #477DF3; | |||
} |
@@ -0,0 +1,66 @@ | |||
// pages/mine/mine.js | |||
Page({ | |||
/** | |||
* 页面的初始数据 | |||
*/ | |||
data: { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面加载 | |||
*/ | |||
onLoad: function (options) { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面初次渲染完成 | |||
*/ | |||
onReady: function () { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面显示 | |||
*/ | |||
onShow: function () { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面隐藏 | |||
*/ | |||
onHide: function () { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面卸载 | |||
*/ | |||
onUnload: function () { | |||
}, | |||
/** | |||
* 页面相关事件处理函数--监听用户下拉动作 | |||
*/ | |||
onPullDownRefresh: function () { | |||
}, | |||
/** | |||
* 页面上拉触底事件的处理函数 | |||
*/ | |||
onReachBottom: function () { | |||
}, | |||
/** | |||
* 用户点击右上角分享 | |||
*/ | |||
onShareAppMessage: function () { | |||
} | |||
}) |
@@ -0,0 +1,3 @@ | |||
{ | |||
"usingComponents": {} | |||
} |
@@ -0,0 +1,4 @@ | |||
<!--pages/mine/mine.wxml--> | |||
<view class="mine_container"> | |||
</view> |
@@ -0,0 +1 @@ | |||
/* pages/mine/mine.wxss */ |
@@ -0,0 +1,66 @@ | |||
// pages/task/task.js | |||
Page({ | |||
/** | |||
* 页面的初始数据 | |||
*/ | |||
data: { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面加载 | |||
*/ | |||
onLoad: function (options) { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面初次渲染完成 | |||
*/ | |||
onReady: function () { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面显示 | |||
*/ | |||
onShow: function () { | |||
console.log('======================'); | |||
}, | |||
/** | |||
* 生命周期函数--监听页面隐藏 | |||
*/ | |||
onHide: function () { | |||
}, | |||
/** | |||
* 生命周期函数--监听页面卸载 | |||
*/ | |||
onUnload: function () { | |||
}, | |||
/** | |||
* 页面相关事件处理函数--监听用户下拉动作 | |||
*/ | |||
onPullDownRefresh: function () { | |||
}, | |||
/** | |||
* 页面上拉触底事件的处理函数 | |||
*/ | |||
onReachBottom: function () { | |||
}, | |||
/** | |||
* 用户点击右上角分享 | |||
*/ | |||
onShareAppMessage: function () { | |||
} | |||
}) |
@@ -0,0 +1,3 @@ | |||
{ | |||
"usingComponents": {} | |||
} |
@@ -0,0 +1,4 @@ | |||
<!--pages/task/task.wxml--> | |||
<view class="mine_container"> | |||
</view> |
@@ -0,0 +1 @@ | |||
/* pages/task/task.wxss */ |
@@ -0,0 +1,74 @@ | |||
{ | |||
"description": "项目配置文件", | |||
"packOptions": { | |||
"ignore": [ | |||
{ | |||
"type": "file", | |||
"value": ".eslintrc.js" | |||
} | |||
] | |||
}, | |||
"setting": { | |||
"bundle": false, | |||
"userConfirmedBundleSwitch": false, | |||
"urlCheck": true, | |||
"scopeDataCheck": false, | |||
"coverView": true, | |||
"es6": true, | |||
"postcss": true, | |||
"compileHotReLoad": false, | |||
"lazyloadPlaceholderEnable": false, | |||
"preloadBackgroundData": false, | |||
"minified": true, | |||
"autoAudits": false, | |||
"newFeature": false, | |||
"uglifyFileName": false, | |||
"uploadWithSourceMap": true, | |||
"useIsolateContext": true, | |||
"nodeModules": false, | |||
"enhance": true, | |||
"useMultiFrameRuntime": true, | |||
"useApiHook": true, | |||
"useApiHostProcess": true, | |||
"showShadowRootInWxmlPanel": true, | |||
"packNpmManually": false, | |||
"enableEngineNative": false, | |||
"packNpmRelationList": [], | |||
"minifyWXSS": true, | |||
"showES6CompileOption": false, | |||
"minifyWXML": true | |||
}, | |||
"compileType": "miniprogram", | |||
"libVersion": "2.19.4", | |||
"appid": "wx0ba562a60cd958b4", | |||
"projectname": "weixin-app", | |||
"debugOptions": { | |||
"hidedInDevtools": [] | |||
}, | |||
"scripts": {}, | |||
"staticServerOptions": { | |||
"baseURL": "", | |||
"servePath": "" | |||
}, | |||
"isGameTourist": false, | |||
"condition": { | |||
"search": { | |||
"list": [] | |||
}, | |||
"conversation": { | |||
"list": [] | |||
}, | |||
"game": { | |||
"list": [] | |||
}, | |||
"plugin": { | |||
"list": [] | |||
}, | |||
"gamePlugin": { | |||
"list": [] | |||
}, | |||
"miniprogram": { | |||
"list": [] | |||
} | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
{ | |||
"condition": { | |||
"plugin": { | |||
"list": [] | |||
}, | |||
"game": { | |||
"list": [] | |||
}, | |||
"gamePlugin": { | |||
"list": [] | |||
}, | |||
"miniprogram": { | |||
"list": [ | |||
{ | |||
"name": "登录", | |||
"pathName": "pages/login/login", | |||
"query": "", | |||
"scene": null | |||
} | |||
] | |||
} | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
import baseurl from '../environments.js' | |||
import {isWithoutToken} from './whiteList.js' | |||
export const request = function(data) { | |||
return new Promise((resolve, reject) => { | |||
if(data.showLoading) { | |||
wx.showLoading({ | |||
title: '加载中', | |||
mask: true | |||
}) | |||
} | |||
// 接口api拼接环境地址 | |||
data.url = baseurl + data.url | |||
// 处理需要token的请求 | |||
if(!isWithoutToken(data)) { | |||
let baseHeader = {authorization: wx.getStorageSync('token')} | |||
data.header = Object.assign(data.header || {}, baseHeader) | |||
} | |||
wx.request({ | |||
...data, | |||
success: function(res) { | |||
// 处理请求 | |||
if(res.data.code == 0) { // 请求成功状态码 | |||
resolve(res.data) | |||
} else if ((res.data.code == 401) || (res.data.code == 402)) { // token过期状态码 | |||
reject(res.data.msg) | |||
// 重新登录 | |||
wx.reLaunch({ | |||
url: '/pages/login/login', | |||
}) | |||
} else { | |||
reject(res.data.msg) | |||
} | |||
}, | |||
fail: function (error) { | |||
reject(error) | |||
}, | |||
complete: function () { | |||
if (data.showLoading) { | |||
wx.hideLoading() | |||
} | |||
} | |||
}) | |||
}).catch(e => { | |||
wx.showToast({ | |||
icon: "error", | |||
title: e || '系统错误', | |||
}) | |||
}) | |||
} |
@@ -0,0 +1,5 @@ | |||
const WITHOUT_TOKEN_API = [{url: '/member/login', method: 'POST'}] | |||
export const isWithoutToken = function({url, method=''}){ | |||
return WITHOUT_TOKEN_API.some((item) => item.url === url && item.method === method.toUpperCase()) | |||
} |
@@ -0,0 +1,7 @@ | |||
{ | |||
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", | |||
"rules": [{ | |||
"action": "allow", | |||
"page": "*" | |||
}] | |||
} |
@@ -0,0 +1,19 @@ | |||
const formatTime = date => { | |||
const year = date.getFullYear() | |||
const month = date.getMonth() + 1 | |||
const day = date.getDate() | |||
const hour = date.getHours() | |||
const minute = date.getMinutes() | |||
const second = date.getSeconds() | |||
return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}` | |||
} | |||
const formatNumber = n => { | |||
n = n.toString() | |||
return n[1] ? n : `0${n}` | |||
} | |||
module.exports = { | |||
formatTime | |||
} |