Commit bb19c791 by iambtr

维养小程序

parents
const { api, imgName, getUserInfo, wxLogin} =require('./lib/util.js')
App({
onLaunch: function () {
/**
*
// 展示本地存储能力
var logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
}
})
// 获取用户信息
wx.getSetting({
success: res => {
console.log(res)
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
wx.getUserInfo({
success: res => {
// 可以将 res 发送给后台解码出 unionId
console.log(res)
this.globalData.userInfo = res.userInfo
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if (this.userInfoReadyCallback) {
this.userInfoReadyCallback(res)
}
}
})
}
}
})
*/
},
globalData: {
authSetting:null,
userInfo: null,
}
})
\ No newline at end of file
{
"pages": [
"pages/welcome2/welcome2",
"pages/user_index/user_index",
"pages/server_items/server_items",
"pages/user_message/user_message",
"pages/device_bind/device_bind",
"pages/my/my",
"pages/qr_code/qr_code",
"pages/server_detail/server_detail",
"pages/server_sure/server_sure",
"pages/register2/register2",
"pages/user_list/user_list"
],
"window": {
"backgroundTextStyle": "dark",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTitleText": "智租保",
"navigationBarTextStyle": "black"
},
"tabBar": {
"selectedColor": "#d7193c",
"list": [
{
"pagePath": "pages/user_index/user_index",
"text": "首页",
"iconPath": "static/image/home.png",
"selectedIconPath": "static/image/homeactive.png"
},
{
"pagePath": "pages/user_message/user_message",
"text": "所有服务",
"iconPath": "static/image/server.png",
"selectedIconPath": "static/image/serveractive.png"
},
{
"pagePath": "pages/my/my",
"text": "我的网点",
"iconPath": "static/image/person.png",
"selectedIconPath": "static/image/personactive.png"
}
]
},
"networkTimeout": {
"request": 5000
}
}
\ No newline at end of file
page{
min-height: 100%;
box-sizing: border-box;
}
view{
box-sizing: border-box;
font-size: 32rpx
}
button{
color: #ffffff;
}
\ No newline at end of file
// pages/star/star.js
const { imgName } = require('../../lib/util.js')
Component({
/**
* 组件的属性列表
*/
properties: {
titleList:{
type: Array, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
observer: function (newVal, oldVal) {
} // 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串, 如:'_propertyChange'
},
},
/**
* 组件的初始数据
*/
data: {
activeNum: 0,
},
/**
* 组件的方法列表
*/
methods: {
//点击改变分数的函数
changeScore(e) {
// var myEventDetail = {} // detail对象,提供给事件监听函数
// var myEventOption = {} // 触发事件的选项
if (!this.data.edit) return
this.setData(
{
selfScore: Number(e.target.id) + 1
}
)
this._setStar()
},
_changeTab(e) {
let oldIndex = this.data.activeNum
let newIndex=Number(e.currentTarget.id)
let res=null//tabIn 返回false的情况可以取消tab
this.data.titleList.forEach((item,ix)=>{
if(ix == oldIndex){
if (item.tabOut){
item.tabOut()
}
}
if (ix == newIndex) {
if (item.tabIn) {
res = item.tabIn() == false ? false : true
} else {
res=true
}
}
return item
})
if(res){
this.setData({
activeNum: newIndex
})
this.triggerEvent('tabChange', { activeIndex: newIndex })
}
}
}
})
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<!--components/navbar/navbar.wxml-->
<view class='wr-tab-header'>
<view class='wr-tab-item {{activeNum==index?"active":""}}' wx:for='{{titleList}}' wx:key='{{index}}' id='{{index}}' catchtap='_changeTab'>
<text>{{item.name}}</text>
</view>
</view>
\ No newline at end of file
/* components/navbar/navbar.wxss */
.wr-tab-header{
flex: 0 0 auto;
display: flex;
justify-content: space-around;
}
.wr-tab-item{
flex: 1 0 10rpx;
text-align: center;
padding: 10rpx;
border-bottom: 2px solid transparent;
}
.active{
color: #d7193c;
border-bottom: 2px solid #d7193c;
}
\ No newline at end of file
// components/search/search.js
Component({
/**
* 组件的属性列表
*/
properties: {
maxLenth: { // 属性名
type: Number, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
value: 5, // 属性初始值(可选),如果未指定则会根据类型选择一个
},
placeholder: { // 属性名
type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
value: '输入搜索项', // 属性初始值(可选),如果未指定则会根据类型选择一个
},
showHistory: { // 属性名
type: Boolean, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
value: false, // 属性初始值(可选),如果未指定则会根据类型选择一个
},
},
/**
* 组件的初始数据
*/
data: {
searchHistory: [],
hasFocus:false,
searchValue:''
},
/**
* 组件的方法列表
*/
methods: {
//失去焦点
_blurInput(e){
let value = e.detail.value
setTimeout(()=>{
this.setData({
hasFocus: false,
})
},200)
this.triggerSearch(value)
},
//输入
_searchInput(e) {
let value=e.detail.value
this.triggerChange(value)
},
//聚焦
_focusInput(e){
this.setData({
hasFocus: true,
})
},
//更新历史记录
_updateHistory(key){
let historyArray=this.data.searchHistory
let newHistoryArray=null
if (historyArray.length < this.data.maxLenth){
this.data.searchHistory.unshift(key)
}else{
this.data.searchHistory.unshift(key)
this.data.searchHistory.pop()
}
this.setData({
searchHistory: this.data.searchHistory
})
},
_historyItemTap(e){
let historyValue=e.currentTarget.id
this.setData({
searchValue:historyValue
})
},
//触发搜索事件
triggerSearch(value){
this.setData({
searchValue: value
})
this.triggerEvent('search', { value })
this._updateHistory(value)
},
//触发改变事件
triggerChange(value) {
this.triggerEvent('change', { value })
}
}
})
{
"component": true,
"usingComponents": {
}
}
\ No newline at end of file
<view class='wr_search'>
<image src='./search.png'></image>
<input placeholder='{{placeholder}}' value='{{searchValue}}' confirm-type='search' bindfocus='_focusInput' bindblur='_blurInput' bindinput='_searchInput'></input>
</view>
<view class='history-box' wx:if='{{showHistory&&hasFocus}}'>
<view class='wr_search_item' wx:for='{{searchHistory}}' wx:key='{{item}}' catchtap='_historyItemTap' id='{{item}}'>{{item}}</view>
</view>
\ No newline at end of file
/* components/search/search.wxss */
.wr_search{
display: flex;
background-color: #fff;
border-radius: 6rpx;
padding: 0 20rpx;
align-items: center;
height: 80rpx;
font-size: 32rpx;
position: relative;
}
.wr_search image{
width: 36rpx;
height: 36rpx;
margin-right: 30rpx;
}
.wr_search input{
flex: 1 0 auto;
}
.history-box{
position: absolute;
width: 100%;
z-index: 1000;
background-color: #eee;
color: #fff;
}
.wr_search_item{
padding: 10rpx 10rpx 10rpx 86rpx;
}
\ No newline at end of file
// pages/star/star.js
const { imgName } = require('../../lib/util.js')
Component({
/**
* 组件的属性列表
*/
properties: {
score: { // 属性名
type: Number, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
value: 5, // 属性初始值(可选),如果未指定则会根据类型选择一个
observer: function (newVal, oldVal) {
this.setData({
selfScore: newVal
})
this._setStar()
} // 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串, 如:'_propertyChange'
},
edit:{
type: Boolean, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
value: false, // 属性初始值(可选),如果未指定则会根据类型选择一个
}
},
/**
* 组件的初始数据
*/
data: {
selfScore:5,
starList:[
imgName('score2.png'),
imgName('score2.png'),
imgName('score2.png'),
imgName('score2.png'),
imgName('score2.png')
]
},
/**
* 组件的方法列表
*/
methods: {
//点击改变分数的函数
changeScore(e){
// var myEventDetail = {} // detail对象,提供给事件监听函数
// var myEventOption = {} // 触发事件的选项
if(!this.data.edit) return
this.setData(
{
selfScore:Number(e.target.id)+1
}
)
this._setStar()
this.triggerEvent('scoreChange', { socre: this.data.selfScore})
},
_setStar(){
let newVal=this.data.selfScore
let starList = null
if (parseInt(newVal) != newVal) {
starList = this.data.starList.map((item, index) => {
if (index + 1 <= newVal) {
return item
} else {
if (index + 1 == parseInt(newVal) + 1) {
return imgName('score1.png')
} else {
return imgName('score0.png')
}
}
})
} else {
starList = this.data.starList.map((item, index) => {
if (index + 1 <= newVal) {
return imgName('score2.png')
} else {
return imgName('score0.png')
}
})
}
this.setData({
starList,
})
}
}
})
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<!--pages/star/star.wxml-->
<view class='box'>
<block wx:for='{{starList}}' wx:key="unique">
<image src='{{item}}' catchtap='changeScore' id='{{index}}'></image>
</block>
<text>{{selfScore}}分</text>
</view>
\ No newline at end of file
/* pages/star/star.wxss */
.box{
display: flex;
height: 40rpx;
font-size: 34rpx;
align-items: center;
}
image{
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
\ No newline at end of file
const type = 'dev'
// const type = 'pro'
var config = {
dev: {
appid: 'wx75c847665ef7211e',
appSecret: '392e69597c06b19d72327aa1ac24058a',
api: 'https://weiyang.zhizukj.com/repair/app/',
version: 'v1.0.00',
imgPath: '/static/image/'
},
pro: {
appid: 'wx75c847665ef7211e',
appSecret: '392e69597c06b19d72327aa1ac24058a',
api: 'https://zhizuxia.zhizukj.com/ydb/app/',
version: 'v1.0.00',
imgPath: '/static/image/'
}
}
module.exports = config[type]
\ No newline at end of file
const StateMachine=require('./state-machine.min.js')
const jsbuffer=require('./jsbuffer.min.js')
const deepcopy = require('./deepcopy.min.js')
/**
* 蓝牙接收类解决多数据包 组包和校验的返回完整数据hex
* iambtr
* option{
* timer:超时时长
* protocolHead:头部
* protocolType:协议编号
* }
*/
class BlueReadBuffer {
constructor(option) {
this.checkTimer = null
this.fsm=null
this.msgType=null
this.hexData=''
this.useData=[]
this.dataLength=null
this.checkSum = new Uint8Array(new ArrayBuffer(2))
this.opt={
timer:5000,
protocolHead: 'ffaa',
protocolType:'fa',
byteLength:47
}
this.init(option)
return this
}
init(option) {
deepcopy(this.opt,option)
this.fsm = new StateMachine({
init: 'HEAD',
transitions: [
{ name: 'head', from: 'HEAD', to: 'TYPE' },
{ name: 'type', from: 'TYPE', to: 'DATA' },
{ name: 'data', from: 'DATA', to: 'CHECK' },
{ name: 'ckeck', from: ['HEAD', 'TYPE', 'DATA', 'CHECK', 'DATA', 'END'], to: 'HEAD' }
]
});
}
reduceProcess(buff, successCallBack, failCallBack) {
//检查超时
this.check_timer(failCallBack);
let jsbuff=new jsbuffer().read(buff)
this.hexData+=jsbuff.hex
for (var i = 0; i < jsbuff.uint8array.length; i++) {
var chr = jsbuff.get[i];
switch (this.fsm.state) {
case 'HEAD':
if (chr == Number(`${this.opt.protocolHead}.slice(0,2)`)) {
this.useData.push(chr)
break
}
if ((chr == Number(`${this.opt.protocolHead}.slice(2)`))&&this.useData.length!=0) {
this.useData.push(chr)
this.fsm.head();
break
}
this.clear()
break
case 'TYPE':
if (this.useData.length==2) {
this.useData.push(chr)
break
}
else if(this.useData.length==3) {
this.useData.push(chr)
this.dataLength=chr
this.fsm.type()
break
}
this.clear()
break
case 'DATA':
if (this.useData.length < this.dataLength+4){
this.useData.push(chr)
if (this.useData.length == this.dataLngth + 4) {
this.fsm.data()
}
break
}
this.clear()
break
case 'CHECK':
if (this.useData.length < this.opt.byteLength) {
this.useData.push(chr)
if (this.useData.length == this.opt.byteLength) {
this.checkSum[0] = this.useData.pop()
this.checkSum[1] = this.useData.pop()
let cSum = new Uint16Array(this.checkSum.buffer)
let sum=this.useData.reduce((pre,cur)=>{
return pre + cur
})
if (cSum == sum) {
successCallBack && successCallBack(this.useData, this.hexData);
} else {
failCallBack && failCallBack('校验位不对')
}
this.clear()
}
}
break
case 'END':
if (this.use_data_cnt < this.use_data_len) {
this.use_data[this.use_data_cnt + 4] = chr;
this.use_data_cnt++;
}
if (this.use_data_cnt == this.use_data_len) {
this.fsm.sum1();
}
break;
}
}
}
clear() {
this.fsm.check()
clearTimeout(this.checkTimer)
this.useData = []
this.msgType = null
this.hexData = ''
this.dataLength = null
this.checkSum = new ArrayBuffer(2)
}
check_timer(failCallBack) {
clearTimeout(this.checkTimer)
this.checkTimer = setTimeout(() => {
this.clear();
failCallBack && failCallBack('帧解析数据超时')
}, this.opt.timer)
}
}
module.exports = BlueReadBuffer
\ No newline at end of file
/**
*create by iambtr
**/
"use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};function extend(t,o){if(0==Object.getOwnPropertyNames(o))return t;var r=JSON.parse(JSON.stringify(o));return function t(o,r){for(var n in r)o.hasOwnProperty(n)&&("object"===_typeof(o[n])?o[n].constructor===Array?o[n]=r[n]:t(o[n],r[n]):o[n]=r[n]);return o}(t,r),r=null,t}
\ No newline at end of file
/**
*create by wr
**/
"use strict";var _createClass=function(){function n(t,r){for(var e=0;e<r.length;e++){var n=r[e];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,r,e){return r&&n(t.prototype,r),e&&n(t,e),t}}();function _classCallCheck(t,r){if(!(t instanceof r))throw new TypeError("Cannot call a class as a function")}var jsbuffer=function(){function t(){return _classCallCheck(this,t),this.buffer=null,this.hex=null,this.uint8array=null,this}return _createClass(t,[{key:"from",value:function(t,r){var n=this;if(r&&"hex"==r)this.hex=t,this.buffer=new ArrayBuffer(t.length/2),this.uint8array=new Uint8Array(this.buffer),t.match(/.{2}/g).forEach(function(t,r){n.uint8array[r]=Number("0x"+t)});else{var e=t.split("");this.buffer=new ArrayBuffer(e.length),this.uint8array=new Uint8Array(this.buffer),this.hex="",e.forEach(function(t,r){var e=t.charCodeAt(0);e=1==e.toString(16).length?"0"+e.toString(16):e.toString(16),n.hex+=e,n.uint8array[r]=Number("0x"+e)})}return this}},{key:"read",value:function(t){return this.buffer=t,this.uint8array=new Uint8Array(this.buffer),this.setHex(),this}},{key:"set",value:function(t,r){return this.uint8array[t]=r,this.setHex(),this}},{key:"get",value:function(t,r){var e=this.uint8array[t];return r&&/hex/i.test(r)?1==e.toString(16).length?"0"+e.toString(16):e.toString(16):e}},{key:"setHex",value:function(){var r=this;this.hex="",this.uint8array.forEach(function(t){r.hex+=1==t.toString(16).length?"0"+t.toString(16):t.toString(16)})}}]),t}();module.exports=jsbuffer;
\ No newline at end of file
!(function () {
// alignment pattern
var adelta = [
0, 11, 15, 19, 23, 27, 31,
16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24,
26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28
];
// version block
var vpat = [
0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d,
0x928, 0xb78, 0x45d, 0xa17, 0x532, 0x9a6, 0x683, 0x8c9,
0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75,
0x250, 0x9d5, 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64,
0x541, 0xc69
];
// final format bits with mask: level << 3 | mask
var fmtword = [
0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, //L
0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, //M
0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, //Q
0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b //H
];
// 4 per version: number of blocks 1,2; data width; ecc width
var eccblocks = [
1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17,
1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28,
1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22,
1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16,
1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22,
2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28,
2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26,
2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26,
2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24,
2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28,
4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24,
2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28,
4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22,
3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24,
5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24,
5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30,
1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28,
5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28,
3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26,
3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28,
4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30,
2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24,
4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30,
6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30,
8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30,
10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30,
8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30,
3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30,
7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30,
5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30,
13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30,
17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30,
17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30,
13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30,
12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30,
6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30,
17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30,
4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30,
20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30,
19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30
];
// Galois field log table
var glog = [
0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
];
// Galios field exponent table
var gexp = [
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00
];
// Working buffers:
// data input and ecc append, image working buffer, fixed part of image, run lengths for badness
var strinbuf = [], eccbuf = [], qrframe = [], framask = [], rlens = [];
// Control values - width is based on version, last 4 are from table.
var version, width, neccblk1, neccblk2, datablkw, eccblkwid;
var ecclevel = 2;
// set bit to indicate cell in qrframe is immutable. symmetric around diagonal
function setmask(x, y) {
var bt;
if (x > y) {
bt = x;
x = y;
y = bt;
}
// y*y = 1+3+5...
bt = y;
bt *= y;
bt += y;
bt >>= 1;
bt += x;
framask[bt] = 1;
}
// enter alignment pattern - black to qrframe, white to mask (later black frame merged to mask)
function putalign(x, y) {
var j;
qrframe[x + width * y] = 1;
for (j = -2; j < 2; j++) {
qrframe[(x + j) + width * (y - 2)] = 1;
qrframe[(x - 2) + width * (y + j + 1)] = 1;
qrframe[(x + 2) + width * (y + j)] = 1;
qrframe[(x + j + 1) + width * (y + 2)] = 1;
}
for (j = 0; j < 2; j++) {
setmask(x - 1, y + j);
setmask(x + 1, y - j);
setmask(x - j, y - 1);
setmask(x + j, y + 1);
}
}
//========================================================================
// Reed Solomon error correction
// exponentiation mod N
function modnn(x) {
while (x >= 255) {
x -= 255;
x = (x >> 8) + (x & 255);
}
return x;
}
var genpoly = [];
// Calculate and append ECC data to data block. Block is in strinbuf, indexes to buffers given.
function appendrs(data, dlen, ecbuf, eclen) {
var i, j, fb;
for (i = 0; i < eclen; i++)
strinbuf[ecbuf + i] = 0;
for (i = 0; i < dlen; i++) {
fb = glog[strinbuf[data + i] ^ strinbuf[ecbuf]];
if (fb != 255) /* fb term is non-zero */
for (j = 1; j < eclen; j++)
strinbuf[ecbuf + j - 1] = strinbuf[ecbuf + j] ^ gexp[modnn(fb + genpoly[eclen - j])];
else
for (j = ecbuf; j < ecbuf + eclen; j++)
strinbuf[j] = strinbuf[j + 1];
strinbuf[ecbuf + eclen - 1] = fb == 255 ? 0 : gexp[modnn(fb + genpoly[0])];
}
}
//========================================================================
// Frame data insert following the path rules
// check mask - since symmetrical use half.
function ismasked(x, y) {
var bt;
if (x > y) {
bt = x;
x = y;
y = bt;
}
bt = y;
bt += y * y;
bt >>= 1;
bt += x;
return framask[bt];
}
//========================================================================
// Apply the selected mask out of the 8.
function applymask(m) {
var x, y, r3x, r3y;
switch (m) {
case 0:
for (y = 0; y < width; y++)
for (x = 0; x < width; x++)
if (!((x + y) & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
break;
case 1:
for (y = 0; y < width; y++)
for (x = 0; x < width; x++)
if (!(y & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
break;
case 2:
for (y = 0; y < width; y++)
for (r3x = 0, x = 0; x < width; x++ , r3x++) {
if (r3x == 3)
r3x = 0;
if (!r3x && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
break;
case 3:
for (r3y = 0, y = 0; y < width; y++ , r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = r3y, x = 0; x < width; x++ , r3x++) {
if (r3x == 3)
r3x = 0;
if (!r3x && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
case 4:
for (y = 0; y < width; y++)
for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < width; x++ , r3x++) {
if (r3x == 3) {
r3x = 0;
r3y = !r3y;
}
if (!r3y && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
break;
case 5:
for (r3y = 0, y = 0; y < width; y++ , r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = 0, x = 0; x < width; x++ , r3x++) {
if (r3x == 3)
r3x = 0;
if (!((x & y & 1) + !(!r3x | !r3y)) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
case 6:
for (r3y = 0, y = 0; y < width; y++ , r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = 0, x = 0; x < width; x++ , r3x++) {
if (r3x == 3)
r3x = 0;
if (!(((x & y & 1) + (r3x && (r3x == r3y))) & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
case 7:
for (r3y = 0, y = 0; y < width; y++ , r3y++) {
if (r3y == 3)
r3y = 0;
for (r3x = 0, x = 0; x < width; x++ , r3x++) {
if (r3x == 3)
r3x = 0;
if (!(((r3x && (r3x == r3y)) + ((x + y) & 1)) & 1) && !ismasked(x, y))
qrframe[x + y * width] ^= 1;
}
}
break;
}
return;
}
// Badness coefficients.
var N1 = 3, N2 = 3, N3 = 40, N4 = 10;
// Using the table of the length of each run, calculate the amount of bad image
// - long runs or those that look like finders; called twice, once each for X and Y
function badruns(length) {
var i;
var runsbad = 0;
for (i = 0; i <= length; i++)
if (rlens[i] >= 5)
runsbad += N1 + rlens[i] - 5;
// BwBBBwB as in finder
for (i = 3; i < length - 1; i += 2)
if (rlens[i - 2] == rlens[i + 2]
&& rlens[i + 2] == rlens[i - 1]
&& rlens[i - 1] == rlens[i + 1]
&& rlens[i - 1] * 3 == rlens[i]
// white around the black pattern? Not part of spec
&& (rlens[i - 3] == 0 // beginning
|| i + 3 > length // end
|| rlens[i - 3] * 3 >= rlens[i] * 4 || rlens[i + 3] * 3 >= rlens[i] * 4)
)
runsbad += N3;
return runsbad;
}
// Calculate how bad the masked image is - blocks, imbalance, runs, or finders.
function badcheck() {
var x, y, h, b, b1;
var thisbad = 0;
var bw = 0;
// blocks of same color.
for (y = 0; y < width - 1; y++)
for (x = 0; x < width - 1; x++)
if ((qrframe[x + width * y] && qrframe[(x + 1) + width * y]
&& qrframe[x + width * (y + 1)] && qrframe[(x + 1) + width * (y + 1)]) // all black
|| !(qrframe[x + width * y] || qrframe[(x + 1) + width * y]
|| qrframe[x + width * (y + 1)] || qrframe[(x + 1) + width * (y + 1)])) // all white
thisbad += N2;
// X runs
for (y = 0; y < width; y++) {
rlens[0] = 0;
for (h = b = x = 0; x < width; x++) {
if ((b1 = qrframe[x + width * y]) == b)
rlens[h]++;
else
rlens[++h] = 1;
b = b1;
bw += b ? 1 : -1;
}
thisbad += badruns(h);
}
// black/white imbalance
if (bw < 0)
bw = -bw;
var big = bw;
var count = 0;
big += big << 2;
big <<= 1;
while (big > width * width)
big -= width * width, count++;
thisbad += count * N4;
// Y runs
for (x = 0; x < width; x++) {
rlens[0] = 0;
for (h = b = y = 0; y < width; y++) {
if ((b1 = qrframe[x + width * y]) == b)
rlens[h]++;
else
rlens[++h] = 1;
b = b1;
}
thisbad += badruns(h);
}
return thisbad;
}
function genframe(instring) {
var x, y, k, t, v, i, j, m;
// find the smallest version that fits the string
t = instring.length;
version = 0;
do {
version++;
k = (ecclevel - 1) * 4 + (version - 1) * 16;
neccblk1 = eccblocks[k++];
neccblk2 = eccblocks[k++];
datablkw = eccblocks[k++];
eccblkwid = eccblocks[k];
k = datablkw * (neccblk1 + neccblk2) + neccblk2 - 3 + (version <= 9);
if (t <= k)
break;
} while (version < 40);
// FIXME - insure that it fits insted of being truncated
width = 17 + 4 * version;
// allocate, clear and setup data structures
v = datablkw + (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
for (t = 0; t < v; t++)
eccbuf[t] = 0;
strinbuf = instring.slice(0);
for (t = 0; t < width * width; t++)
qrframe[t] = 0;
for (t = 0; t < (width * (width + 1) + 1) / 2; t++)
framask[t] = 0;
// insert finders - black to frame, white to mask
for (t = 0; t < 3; t++) {
k = 0;
y = 0;
if (t == 1)
k = (width - 7);
if (t == 2)
y = (width - 7);
qrframe[(y + 3) + width * (k + 3)] = 1;
for (x = 0; x < 6; x++) {
qrframe[(y + x) + width * k] = 1;
qrframe[y + width * (k + x + 1)] = 1;
qrframe[(y + 6) + width * (k + x)] = 1;
qrframe[(y + x + 1) + width * (k + 6)] = 1;
}
for (x = 1; x < 5; x++) {
setmask(y + x, k + 1);
setmask(y + 1, k + x + 1);
setmask(y + 5, k + x);
setmask(y + x + 1, k + 5);
}
for (x = 2; x < 4; x++) {
qrframe[(y + x) + width * (k + 2)] = 1;
qrframe[(y + 2) + width * (k + x + 1)] = 1;
qrframe[(y + 4) + width * (k + x)] = 1;
qrframe[(y + x + 1) + width * (k + 4)] = 1;
}
}
// alignment blocks
if (version > 1) {
t = adelta[version];
y = width - 7;
for (; ;) {
x = width - 7;
while (x > t - 3) {
putalign(x, y);
if (x < t)
break;
x -= t;
}
if (y <= t + 9)
break;
y -= t;
putalign(6, y);
putalign(y, 6);
}
}
// single black
qrframe[8 + width * (width - 8)] = 1;
// timing gap - mask only
for (y = 0; y < 7; y++) {
setmask(7, y);
setmask(width - 8, y);
setmask(7, y + width - 7);
}
for (x = 0; x < 8; x++) {
setmask(x, 7);
setmask(x + width - 8, 7);
setmask(x, width - 8);
}
// reserve mask-format area
for (x = 0; x < 9; x++)
setmask(x, 8);
for (x = 0; x < 8; x++) {
setmask(x + width - 8, 8);
setmask(8, x);
}
for (y = 0; y < 7; y++)
setmask(8, y + width - 7);
// timing row/col
for (x = 0; x < width - 14; x++)
if (x & 1) {
setmask(8 + x, 6);
setmask(6, 8 + x);
}
else {
qrframe[(8 + x) + width * 6] = 1;
qrframe[6 + width * (8 + x)] = 1;
}
// version block
if (version > 6) {
t = vpat[version - 7];
k = 17;
for (x = 0; x < 6; x++)
for (y = 0; y < 3; y++ , k--)
if (1 & (k > 11 ? version >> (k - 12) : t >> k)) {
qrframe[(5 - x) + width * (2 - y + width - 11)] = 1;
qrframe[(2 - y + width - 11) + width * (5 - x)] = 1;
}
else {
setmask(5 - x, 2 - y + width - 11);
setmask(2 - y + width - 11, 5 - x);
}
}
// sync mask bits - only set above for white spaces, so add in black bits
for (y = 0; y < width; y++)
for (x = 0; x <= y; x++)
if (qrframe[x + width * y])
setmask(x, y);
// convert string to bitstream
// 8 bit data to QR-coded 8 bit data (numeric or alphanum, or kanji not supported)
v = strinbuf.length;
// string to array
for (i = 0; i < v; i++)
eccbuf[i] = strinbuf.charCodeAt(i);
strinbuf = eccbuf.slice(0);
// calculate max string length
x = datablkw * (neccblk1 + neccblk2) + neccblk2;
if (v >= x - 2) {
v = x - 2;
if (version > 9)
v--;
}
// shift and repack to insert length prefix
i = v;
if (version > 9) {
strinbuf[i + 2] = 0;
strinbuf[i + 3] = 0;
while (i--) {
t = strinbuf[i];
strinbuf[i + 3] |= 255 & (t << 4);
strinbuf[i + 2] = t >> 4;
}
strinbuf[2] |= 255 & (v << 4);
strinbuf[1] = v >> 4;
strinbuf[0] = 0x40 | (v >> 12);
}
else {
strinbuf[i + 1] = 0;
strinbuf[i + 2] = 0;
while (i--) {
t = strinbuf[i];
strinbuf[i + 2] |= 255 & (t << 4);
strinbuf[i + 1] = t >> 4;
}
strinbuf[1] |= 255 & (v << 4);
strinbuf[0] = 0x40 | (v >> 4);
}
// fill to end with pad pattern
i = v + 3 - (version < 10);
while (i < x) {
strinbuf[i++] = 0xec;
// buffer has room if (i == x) break;
strinbuf[i++] = 0x11;
}
// calculate and append ECC
// calculate generator polynomial
genpoly[0] = 1;
for (i = 0; i < eccblkwid; i++) {
genpoly[i + 1] = 1;
for (j = i; j > 0; j--)
genpoly[j] = genpoly[j]
? genpoly[j - 1] ^ gexp[modnn(glog[genpoly[j]] + i)] : genpoly[j - 1];
genpoly[0] = gexp[modnn(glog[genpoly[0]] + i)];
}
for (i = 0; i <= eccblkwid; i++)
genpoly[i] = glog[genpoly[i]]; // use logs for genpoly[] to save calc step
// append ecc to data buffer
k = x;
y = 0;
for (i = 0; i < neccblk1; i++) {
appendrs(y, datablkw, k, eccblkwid);
y += datablkw;
k += eccblkwid;
}
for (i = 0; i < neccblk2; i++) {
appendrs(y, datablkw + 1, k, eccblkwid);
y += datablkw + 1;
k += eccblkwid;
}
// interleave blocks
y = 0;
for (i = 0; i < datablkw; i++) {
for (j = 0; j < neccblk1; j++)
eccbuf[y++] = strinbuf[i + j * datablkw];
for (j = 0; j < neccblk2; j++)
eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
}
for (j = 0; j < neccblk2; j++)
eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
for (i = 0; i < eccblkwid; i++)
for (j = 0; j < neccblk1 + neccblk2; j++)
eccbuf[y++] = strinbuf[x + i + j * eccblkwid];
strinbuf = eccbuf;
// pack bits into frame avoiding masked area.
x = y = width - 1;
k = v = 1; // up, minus
/* inteleaved data and ecc codes */
m = (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
for (i = 0; i < m; i++) {
t = strinbuf[i];
for (j = 0; j < 8; j++ , t <<= 1) {
if (0x80 & t)
qrframe[x + width * y] = 1;
do { // find next fill position
if (v)
x--;
else {
x++;
if (k) {
if (y != 0)
y--;
else {
x -= 2;
k = !k;
if (x == 6) {
x--;
y = 9;
}
}
}
else {
if (y != width - 1)
y++;
else {
x -= 2;
k = !k;
if (x == 6) {
x--;
y -= 8;
}
}
}
}
v = !v;
} while (ismasked(x, y));
}
}
// save pre-mask copy of frame
strinbuf = qrframe.slice(0);
t = 0; // best
y = 30000; // demerit
// for instead of while since in original arduino code
// if an early mask was "good enough" it wouldn't try for a better one
// since they get more complex and take longer.
for (k = 0; k < 8; k++) {
applymask(k); // returns black-white imbalance
x = badcheck();
if (x < y) { // current mask better than previous best?
y = x;
t = k;
}
if (t == 7)
break; // don't increment i to a void redoing mask
qrframe = strinbuf.slice(0); // reset for next pass
}
if (t != k) // redo best mask - none good enough, last wasn't t
applymask(t);
// add in final mask/ecclevel bytes
y = fmtword[t + ((ecclevel - 1) << 3)];
// low byte
for (k = 0; k < 8; k++ , y >>= 1)
if (y & 1) {
qrframe[(width - 1 - k) + width * 8] = 1;
if (k < 6)
qrframe[8 + width * k] = 1;
else
qrframe[8 + width * (k + 1)] = 1;
}
// high byte
for (k = 0; k < 7; k++ , y >>= 1)
if (y & 1) {
qrframe[8 + width * (width - 7 + k)] = 1;
if (k)
qrframe[(6 - k) + width * 8] = 1;
else
qrframe[7 + width * 8] = 1;
}
return qrframe;
}
var _canvas = null;
var api = {
get ecclevel() {
return ecclevel;
},
set ecclevel(val) {
ecclevel = val;
},
get size() {
return _size;
},
set size(val) {
_size = val
},
get canvas() {
return _canvas;
},
set canvas(el) {
_canvas = el;
},
getFrame: function (string) {
return genframe(string);
},
//这里的utf16to8(str)是对Text中的字符串进行转码,让其支持中文
utf16to8: function (str) {
var out, i, len, c;
out = "";
len = str.length;
for (i = 0; i < len; i++) {
c = str.charCodeAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out += str.charAt(i);
} else if (c > 0x07FF) {
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
} else {
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
}
}
return out;
},
/**
* 新增$this参数,传入组件的this,兼容在组件中生成
*/
draw: function (str, canvas, cavW, cavH, $this, ecc) {
var that = this;
ecclevel = ecc || ecclevel;
canvas = canvas || _canvas;
if (!canvas) {
console.warn('No canvas provided to draw QR code in!')
return;
}
var size = Math.min(cavW, cavH);
str = that.utf16to8(str);//增加中文显示
var frame = that.getFrame(str),
// 组件中生成qrcode需要绑定this
ctx = wx.createCanvasContext(canvas,$this),
px = Math.round(size / (width + 8));
var roundedSize = px * (width + 8),
offset = Math.floor((size - roundedSize) / 2);
size = roundedSize;
//ctx.clearRect(0, 0, cavW, cavW);
ctx.setFillStyle('#ffffff')
ctx.fillRect(0, 0, cavW, cavW);
ctx.setFillStyle('#000000');
for (var i = 0; i < width; i++) {
for (var j = 0; j < width; j++) {
if (frame[j * width + i]) {
ctx.fillRect(px * (4 + i) + offset, px * (4 + j) + offset, px, px);
}
}
}
ctx.draw();
}
}
module.exports = api;
})();
\ No newline at end of file
!function(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define("StateMachine",[],n):"object"==typeof exports?exports.StateMachine=n():t.StateMachine=n()}(this,function(){return function(t){function n(e){if(i[e])return i[e].exports;var s=i[e]={i:e,l:!1,exports:{}};return t[e].call(s.exports,s,s.exports,n),s.l=!0,s.exports}var i={};return n.m=t,n.c=i,n.i=function(t){return t},n.d=function(t,i,e){n.o(t,i)||Object.defineProperty(t,i,{configurable:!1,enumerable:!0,get:e})},n.n=function(t){var i=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(i,"a",i),i},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="",n(n.s=5)}([function(t,n,i){"use strict";t.exports=function(t,n){var i,e,s;for(i=1;i<arguments.length;i++){e=arguments[i];for(s in e)e.hasOwnProperty(s)&&(t[s]=e[s])}return t}},function(t,n,i){"use strict";var e=i(0);t.exports={build:function(t,n){var i,s,r,o=n.plugins;for(i=0,s=o.length;i<s;i++)r=o[i],r.methods&&e(t,r.methods),r.properties&&Object.defineProperties(t,r.properties)},hook:function(t,n,i){var e,s,r,o,a=t.config.plugins,f=[t.context];for(i&&(f=f.concat(i)),e=0,s=a.length;e<s;e++)o=a[e],(r=a[e][n])&&r.apply(o,f)}}},function(t,n,i){"use strict";function e(t){if(0===t.length)return t;var n,i,e=t.split(/[_-]/);if(1===e.length&&e[0][0].toLowerCase()===e[0][0])return t;for(i=e[0].toLowerCase(),n=1;n<e.length;n++)i=i+e[n].charAt(0).toUpperCase()+e[n].substring(1).toLowerCase();return i}e.prepended=function(t,n){return n=e(n),t+n[0].toUpperCase()+n.substring(1)},t.exports=e},function(t,n,i){"use strict";function e(t,n){t=t||{},this.options=t,this.defaults=n.defaults,this.states=[],this.transitions=[],this.map={},this.lifecycle=this.configureLifecycle(),this.init=this.configureInitTransition(t.init),this.data=this.configureData(t.data),this.methods=this.configureMethods(t.methods),this.map[this.defaults.wildcard]={},this.configureTransitions(t.transitions||[]),this.plugins=this.configurePlugins(t.plugins,n.plugin)}var s=i(0),r=i(2);s(e.prototype,{addState:function(t){this.map[t]||(this.states.push(t),this.addStateLifecycleNames(t),this.map[t]={})},addStateLifecycleNames:function(t){this.lifecycle.onEnter[t]=r.prepended("onEnter",t),this.lifecycle.onLeave[t]=r.prepended("onLeave",t),this.lifecycle.on[t]=r.prepended("on",t)},addTransition:function(t){this.transitions.indexOf(t)<0&&(this.transitions.push(t),this.addTransitionLifecycleNames(t))},addTransitionLifecycleNames:function(t){this.lifecycle.onBefore[t]=r.prepended("onBefore",t),this.lifecycle.onAfter[t]=r.prepended("onAfter",t),this.lifecycle.on[t]=r.prepended("on",t)},mapTransition:function(t){var n=t.name,i=t.from,e=t.to;return this.addState(i),"function"!=typeof e&&this.addState(e),this.addTransition(n),this.map[i][n]=t,t},configureLifecycle:function(){return{onBefore:{transition:"onBeforeTransition"},onAfter:{transition:"onAfterTransition"},onEnter:{state:"onEnterState"},onLeave:{state:"onLeaveState"},on:{transition:"onTransition"}}},configureInitTransition:function(t){return"string"==typeof t?this.mapTransition(s({},this.defaults.init,{to:t,active:!0})):"object"==typeof t?this.mapTransition(s({},this.defaults.init,t,{active:!0})):(this.addState(this.defaults.init.from),this.defaults.init)},configureData:function(t){return"function"==typeof t?t:"object"==typeof t?function(){return t}:function(){return{}}},configureMethods:function(t){return t||{}},configurePlugins:function(t,n){t=t||[];var i,e,s;for(i=0,e=t.length;i<e;i++)s=t[i],"function"==typeof s&&(t[i]=s=s()),s.configure&&s.configure(this);return t},configureTransitions:function(t){var n,i,e,s,r,o=this.defaults.wildcard;for(i=0;i<t.length;i++)for(e=t[i],s=Array.isArray(e.from)?e.from:[e.from||o],r=e.to||o,n=0;n<s.length;n++)this.mapTransition({name:e.name,from:s[n],to:r})},transitionFor:function(t,n){var i=this.defaults.wildcard;return this.map[t][n]||this.map[i][n]},transitionsFor:function(t){var n=this.defaults.wildcard;return Object.keys(this.map[t]).concat(Object.keys(this.map[n]))},allStates:function(){return this.states},allTransitions:function(){return this.transitions}}),t.exports=e},function(t,n,i){function e(t,n){this.context=t,this.config=n,this.state=n.init.from,this.observers=[t]}var s=i(0),r=i(6),o=i(1),a=[null,[]];s(e.prototype,{init:function(t){if(s(this.context,this.config.data.apply(this.context,t)),o.hook(this,"init"),this.config.init.active)return this.fire(this.config.init.name,[])},is:function(t){return Array.isArray(t)?t.indexOf(this.state)>=0:this.state===t},isPending:function(){return this.pending},can:function(t){return!this.isPending()&&!!this.seek(t)},cannot:function(t){return!this.can(t)},allStates:function(){return this.config.allStates()},allTransitions:function(){return this.config.allTransitions()},transitions:function(){return this.config.transitionsFor(this.state)},seek:function(t,n){var i=this.config.defaults.wildcard,e=this.config.transitionFor(this.state,t),s=e&&e.to;return"function"==typeof s?s.apply(this.context,n):s===i?this.state:s},fire:function(t,n){return this.transit(t,this.state,this.seek(t,n),n)},transit:function(t,n,i,e){var s=this.config.lifecycle,r=this.config.options.observeUnchangedState||n!==i;return i?this.isPending()?this.context.onPendingTransition(t,n,i):(this.config.addState(i),this.beginTransit(),e.unshift({transition:t,from:n,to:i,fsm:this.context}),this.observeEvents([this.observersForEvent(s.onBefore.transition),this.observersForEvent(s.onBefore[t]),r?this.observersForEvent(s.onLeave.state):a,r?this.observersForEvent(s.onLeave[n]):a,this.observersForEvent(s.on.transition),r?["doTransit",[this]]:a,r?this.observersForEvent(s.onEnter.state):a,r?this.observersForEvent(s.onEnter[i]):a,r?this.observersForEvent(s.on[i]):a,this.observersForEvent(s.onAfter.transition),this.observersForEvent(s.onAfter[t]),this.observersForEvent(s.on[t])],e)):this.context.onInvalidTransition(t,n,i)},beginTransit:function(){this.pending=!0},endTransit:function(t){return this.pending=!1,t},failTransit:function(t){throw this.pending=!1,t},doTransit:function(t){this.state=t.to},observe:function(t){if(2===t.length){var n={};n[t[0]]=t[1],this.observers.push(n)}else this.observers.push(t[0])},observersForEvent:function(t){for(var n,i=0,e=this.observers.length,s=[];i<e;i++)n=this.observers[i],n[t]&&s.push(n);return[t,s,!0]},observeEvents:function(t,n,i,e){if(0===t.length)return this.endTransit(void 0===e||e);var s=t[0][0],r=t[0][1],a=t[0][2];if(n[0].event=s,s&&a&&s!==i&&o.hook(this,"lifecycle",n),0===r.length)return t.shift(),this.observeEvents(t,n,s,e);var f=r.shift(),c=f[s].apply(f,n);return c&&"function"==typeof c.then?c.then(this.observeEvents.bind(this,t,n,s)).catch(this.failTransit.bind(this)):!1===c?this.endTransit(!1):this.observeEvents(t,n,s,c)},onInvalidTransition:function(t,n,i){throw new r("transition is invalid in current state",t,n,i,this.state)},onPendingTransition:function(t,n,i){throw new r("transition is invalid while previous transition is still in progress",t,n,i,this.state)}}),t.exports=e},function(t,n,i){"use strict";function e(t){return r(this||{},t)}function s(){var t,n;"function"==typeof arguments[0]?(t=arguments[0],n=arguments[1]||{}):(t=function(){this._fsm.apply(this,arguments)},n=arguments[0]||{});var i=new u(n,e);return o(t.prototype,i),t.prototype._fsm.config=i,t}function r(t,n){return o(t,new u(n,e)),t._fsm(),t}function o(t,n){if("object"!=typeof t||Array.isArray(t))throw Error("StateMachine can only be applied to objects");c.build(t,n),Object.defineProperties(t,d),a(t,l),a(t,n.methods),n.allTransitions().forEach(function(n){t[f(n)]=function(){return this._fsm.fire(n,[].slice.call(arguments))}}),t._fsm=function(){this._fsm=new h(this,n),this._fsm.init(arguments)}}var a=i(0),f=i(2),c=i(1),u=i(3),h=i(4),l={is:function(t){return this._fsm.is(t)},can:function(t){return this._fsm.can(t)},cannot:function(t){return this._fsm.cannot(t)},observe:function(){return this._fsm.observe(arguments)},transitions:function(){return this._fsm.transitions()},allTransitions:function(){return this._fsm.allTransitions()},allStates:function(){return this._fsm.allStates()},onInvalidTransition:function(t,n,i){return this._fsm.onInvalidTransition(t,n,i)},onPendingTransition:function(t,n,i){return this._fsm.onPendingTransition(t,n,i)}},d={state:{configurable:!1,enumerable:!0,get:function(){return this._fsm.state},set:function(t){throw Error("use transitions to change state")}}};e.version="3.0.1",e.factory=s,e.apply=r,e.defaults={wildcard:"*",init:{name:"init",from:"none"}},t.exports=e},function(t,n,i){"use strict";t.exports=function(t,n,i,e,s){this.message=t,this.transition=n,this.from=i,this.to=e,this.current=s}}])});
\ No newline at end of file
const config = require('../config/index.js')
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
}
// 类型判断
const getType = function(o) {
let s = Object.prototype.toString.call(o)
return s.replace(/^\[object\s(.*)\]$/gi, ($0, $1) => {
return $1.toLowerCase();
})
}
//获取图片路径 param:图片名称带扩展名
const imgName = (imgNameWithExt = 'no.jpg') => {
return `${config.imgPath}${imgNameWithExt}`
}
//预览图片 param:t
const previewPic = (current, urls) => {
//图片预览
wx.previewImage({
current, // 当前显示图片的http链接
urls: urls || [current] // 需要预览的图片http链接列表
})
}
//api param:根路径后面的路由
const api = {
get: (url, query, notShowLoad) => {
if (!notShowLoad) {
wx.showLoading({
mask: true,
})
}
let sessionHead = {}
sessionHead['content-type'] = 'application/x-www-form-urlencoded'
sessionHead.token = wx.getStorageSync('user') ? wx.getStorageSync('user').token : ''
return new Promise((resolve, reject) => {
wx.request({
url: `${config.api}${url}`,
// data: Object.assign({}, { userId: wx.getStorageSync('user') ? wx.getStorageSync('user').userId : '' }, query),
data: query,
method: 'GET',
header: sessionHead,
success(res) {
if (res.statusCode == 200) {
if (res.data.success) {
resolve(res.data)
} else {
reject(res.data.message)
}
return
}
if (res.statusCode == 401) {
reject('请登录')
wx.removeStorageSync('listtip')
wx.redirectTo({
url: '/pages/welcome2/welcome2'
})
return
}
reject(res.data, '请求成功')
},
fail(res) {
console.error('1', res)
reject(res.data, '请求失败')
},
complete() {
if (!notShowLoad) {
wx.hideLoading()
}
}
})
})
},
post: (url, body, head, notShowLoad) => {
if (!notShowLoad) {
wx.showLoading({
mask: true,
})
}
let sessionHead = {
'content-type': 'application/x-www-form-urlencoded'
}
sessionHead.token = wx.getStorageSync('user') ? wx.getStorageSync('user').token : ''
if (head) {
sessionHead = Object.assign(sessionHead, head)
}
return new Promise((resolve, reject) => {
wx.request({
url: `${config.api}${url}`,
// data: Object.assign({}, { userId: wx.getStorageSync('user') ? wx.getStorageSync('user').userId : '' }, body),
data: body,
method: 'POST',
header: sessionHead,
success(res) {
console.log('1', res)
if (res.statusCode == 200) {
if (res.data.success) {
resolve(res.data)
} else {
reject(res.data.message)
}
return
}
if (res.statusCode == 401) {
reject('请登录')
wx.removeStorageSync('listtip')
wx.redirectTo({
url: '/pages/welcome2/welcome2'
})
return
}
reject(res.data, '请求成功')
},
fail(res) {
console.error('1', res)
reject(res.data, '请求失败')
},
complete() {
if (!notShowLoad) {
wx.hideLoading()
}
}
})
})
}
}
//api 无用户id param:根路径后面的路由
const apiPost = function(url, body, head) {
wx.showLoading({
mask: true,
})
let sessionHead = {
'content-type': 'application/x-www-form-urlencoded'
}
sessionHead.sessionid = wx.getStorageSync('user') ? wx.getStorageSync('user').sessionid : ''
if (head) {
sessionHead = Object.assign(sessionHead, head)
}
return new Promise((resolve, reject) => {
wx.request({
url: `${config.api}${url}`,
data: Object.assign({}, body),
method: 'POST',
header: sessionHead,
success(res) {
if (res.statusCode == 200) {
if (res.data.success) {
resolve(res.data)
} else {
if (/请登录/.test(res.data.message)) {
wx.redirectTo({
url: '/pages/welcome2/welcome2'
})
}
reject(res.data.message)
}
return
}
reject(res.data, '请求成功')
},
fail(res) {
reject(res.data, '请求失败')
},
complete() {
wx.hideLoading()
}
})
})
}
//获取用户权限
const getUserAuth = () => {
return new Promise((resolve, reject) => {
wx.getSetting({
success: (authsettings) => {
resolve(authsettings.authSetting)
},
fail: () => {
reject('获取用户权限失败')
}
})
})
}
//获取用户信息
const getUserInfo = () => {
return new Promise((resolve, reject) => {
getUserAuth()
.then(authsettings => {
console.log('授权信息', authsettings)
if (authsettings['scope.userInfo'] == undefined) {
wx.getUserInfo({
withCredentials: true,
lang: 'zh_CN',
success: (userinfo) => {
resolve(userinfo)
},
fail: () => {
reject('用户信息未授权')
}
})
} else if (authsettings['scope.userInfo'] == false) {
reject('用户信息未授权')
} else {
wx.getUserInfo({
withCredentials: true,
lang: 'zh_CN',
success: (userinfo) => {
resolve(userinfo)
},
fail: () => {
reject('用户信息获取失败')
}
})
}
})
.catch(err => {
reject(err)
})
})
}
//微信登录
const wxLogin = () => {
return new Promise((resolve, reject) => {
wx.checkSession({
success: function() {
resolve(wx.getStorageSync('loginCode'))
},
fail: function() {
wx.login({
success(res) {
if (res.code) {
wx.setStorageSync('loginCode', res.code)
resolve(res.code)
} else {
reject('获取用户登录态失败!')
}
},
fail() {
reject('调用登录态失败!')
}
});
}
})
})
}
//手动授权方法
const authAgainByUser = (msg) => {
wx.showModal({
title: '提示',
content: msg,
success(res) {
if (res.confirm) {
wx.openSetting()
}
}
})
}
//获取定位
const userLocation = () => {
return new Promise((resolve, reject) => {
getUserAuth()
.then(authsettings => {
if (authsettings['scope.userLocation'] == undefined) {
wx.getLocation({
type: 'gcj02',
success: (location) => {
resolve(location)
},
fail: () => {
reject('用户位置未授权')
}
})
} else if (authsettings['scope.userLocation'] == false) {
reject('用户位置未授权')
} else {
wx.getLocation({
type: 'gcj02',
success: (location) => {
resolve(location)
},
fail: () => {
reject('用户位置获取失败')
}
})
}
})
.catch(err => {
reject(err)
})
})
}
const msgTip = {
'没有该车': '该设备不存在!',
'timeout': '超时了,请重试!'
}
//错误提示 用于不常见错误定位 param:错误信息
const alertTip = (msg, cb) => {
msg = msg ? msg.toString() : 'timeout'
wx.showModal({
title: '提示',
content: msgTip[msg] ? msgTip[msg] : msg,
showCancel: false,
success() {
cb && cb()
}
})
}
//确认提示
const confirmTip = (msg, cb) => {
wx.showModal({
title: '提示',
content: msg,
success(res) {
if (res.confirm) {
cb && cb()
}
}
})
}
const wxscan = function() {
return new Promise((resolve, reject) => {
wx.scanCode({
onlyFromCamera: true,
success: function(res) {
resolve(res.result)
},
fail: function(res) {
reject('扫码失败,重试')
}
})
})
}
const mapApi = {
getRoad(data, notShowLoad) {
if (!notShowLoad) {
wx.showLoading({
mask: true,
})
}
return new Promise((resolve, reject) => {
wx.request({
method: 'GET',
url: 'http://apis.map.qq.com/ws/direction/v1/walking/',
data: Object.assign({}, data, {
key: config.key
}),
success(res) {
if (res.statusCode == 200) {
if (res.data.status == 0) {
let coors = res.data.result.routes[0].polyline
for (var i = 2; i < coors.length; i++) {
coors[i] = coors[i - 2] + coors[i] / 1000000
}
resolve(coors)
} else {
reject(res.data.message)
}
return
}
reject(res.data, '请求成功')
},
fail(res) {
reject(res, '请求失败')
},
complete() {
wx.hideLoading()
}
})
})
},
getAdress(data, notShowLoad) {
if (!notShowLoad) {
wx.showLoading({
mask: true,
})
}
return new Promise((resolve, reject) => {
wx.request({
method: 'GET',
url: 'https://apis.map.qq.com/ws/geocoder/v1/',
data: Object.assign({}, data, {
coord_type: 1,
key: config.key
}),
success(res) {
if (res.statusCode == 200) {
if (res.data.status == 0) {
resolve(res.data.result.address)
} else {
reject(res.data.message)
}
return
}
reject(res.data, '请求成功')
},
fail(res) {
reject(res, '请求失败')
},
complete() {
wx.hideLoading()
}
})
})
}
}
const getProtocol = (id) => {
function download(url) {
console.log(url)
let file = wx.getStorageSync('file')
if (!file) {
file = []
}
return new Promise((resolve, reject) => {
wx.showLoading({
mask: true,
})
wx.downloadFile({
url,
success: function(res) {
let filePath = res.tempFilePath;
file[+id] = filePath
wx.setStorageSync('file', file)
console.log('新文档', filePath)
wx.hideLoading()
wx.openDocument({
filePath: filePath,
success: function(res) {
resolve('打开文档成功')
},
fail(err) {
wx.hideLoading()
reject(err)
}
})
},
fail(err) {
console.error('2', err)
wx.hideLoading()
file[+id] = null
reject(err.errMsg)
}
})
})
}
return new Promise((resolve, reject) => {
// 协议文档
let file = wx.getStorageSync('file')
if (file && file[id]) {
wx.openDocument({
filePath: file[id],
success() {
console.log('存在文档', file[id])
resolve('打开文档成功')
},
fail(err) {
console.log(err)
api.get('agreement/getById', {
id
})
.then(({
data
}) => {
download(data.url, file).then(res => {
resolve(res)
})
.catch(err => {
wx.hideLoading()
reject(err)
})
})
.catch(err => {
wx.hideLoading()
reject(err)
})
}
})
} else {
api.get('agreement/getById', {
id
})
.then(({
data
}) => {
return download(data.url).then(res => {
resolve(res)
})
.catch(err => {
wx.hideLoading()
reject(err)
})
})
.catch(err => {
wx.hideLoading()
reject(err)
})
}
})
}
//上传图片
const uploadResource = function(r,t) {
wx.showLoading({
title: `上传${t||'图片'}中`,
mask: true,
})
// 数组型 资源
if (getType(r) === 'array') {
return Promise.all(r.map(item => {
return new Promise((resolve, reject) => {
wx.uploadFile({
url: 'https://zhizuxia.zhizukj.com/ydb/app/manage/file/upload.json',
filePath: item,
name: 'file',
success(res) {
resolve(JSON.parse(res.data).picUrl)
},
fail(err) {
reject('图片上传失败')
},
complete(res) {
wx.hideLoading()
}
})
})
}))
}else{
// 单个资源
return new Promise((resolve, reject) => {
wx.uploadFile({
url: 'https://zhizuxia.zhizukj.com/ydb/app/manage/file/upload.json',
filePath: r,
name: 'file',
success(res) {
resolve(JSON.parse(res.data).picUrl)
},
fail(err) {
reject('图片上传失败')
},
complete(res) {
wx.hideLoading()
}
})
})
}
}
module.exports = {
formatTime,
imgName,
api,
getUserInfo,
wxLogin,
alertTip,
msgTip,
authAgainByUser,
userLocation,
mapApi,
wxscan,
previewPic,
confirmTip,
uploadResource,
getProtocol
}
\ No newline at end of file
// pages/device_bind/device_bind.js
const { api, wxscan, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, getProtocol } = require('../../lib/util.js')
let timer=null
Page({
data: {
//img
imgTip: imgName('imgtip.png'),
imgScan:imgName('imgscan.png'),
modelScan:true,
frameNo: null,
userId:null,
rentType:0,//0团租 1个租
status:'normal',//normal 和 pedding
user:null,
agreeUserCar:true,
id:null//申请id
},
onLoad() {
let user = wx.getStorageSync('user')
let { userMapp } = user
if (!user) {
wx.redirectTo({
url: '/pages/welcome2/welcome2',
})
return
}
this.setData({
user,
rentType: userMapp.userType==1 ? 1 : 0,
userId: userMapp.id
})
},
onHide(){
clearInterval(timer)
},
onUnload(){
clearInterval(timer)
},
onShow() {
//团个租
this.getStatus(this.data.rentType)
},
scanImg(){
let This =this
if (!This.data.agreeUserCar){
alertTip('请同意租车协议')
return false
}
wxscan()
.then(frameNo=>{
This.setData({
frameNo
})
This.apiUseCar()
})
.catch(err=>{
alertTip(err)
})
},
apiUseCar(){
let This = this
if (!this.data.frameNo) {
alertTip('请输入车辆编码')
return false
}
if (!this.data.agreeUserCar) {
alertTip('请同意租车协议')
return false
}
let { frameNo, userId, rentType}=This.data
api.post('message/requestJoinCar', {
frameNo, userId, rentType
})
.then(res => {
console.log(frameNo, userId, rentType,res)
//等待。。
//团租
if (rentType==0){
This.getStatus()
timer = setInterval(() => {
This.getStatus()
}, 5000)
return
}
//个租 注册逻辑
})
.catch(err => {
console.error(err)
alertTip(err)
})
},
getStatus(userType){
let This=this
let msgType=[2,3]
console.log(userType)
api.get('message/getMessageInfo',{
userId:This.data.userId,
messageType: msgType[userType]//申请用车
},{},true)
.then(res=>{
console.log('getStatus',res)
let { state ,id } = res.data
if (!This.data.id){
This.setData({
id
})
}
switch(state){
//待审核
case 0:
This.setData({
status: 'pedding',//normal 和 pedding
})
if (!timer){
timer = setInterval(() => {
This.getStatus()
}, 5000)
}
break;
//审核通过去首页
case 1:
wx.redirectTo({
url: '/pages/user_index/user_index',
})
break;
//正常页面
default:
This.setData({
status: 'normal',//normal 和 pedding
})
clearInterval(timer)
}
})
.catch(err=>{
console.error(err)
})
},
backScan(){
this.setData({
modelScan: true
})
},
bindByHand(){
this.setData({
modelScan:false
})
},
deviceInput(e) {
this.setData({
frameNo: e.detail.value
})
},
giveUp() {
//放弃申请
let that = this
wx.showModal({
title: '提示',
content: '是否放弃申请',
success: function (res) {
if (res.confirm) {
let { frameNo, userId, id } = that.data
api.post('message/cancelJoinCar',{
id
}).then(res=>{
that.setData({
status: 'normal',
modelScan: true
})
clearInterval(timer)
}).catch(err=>{
alertTip(err)
})
}
}
})
},
//同意租车协议
hascheck(e){
this.setData({
agreeUserCar: !this.data.agreeUserCar
})
},
//进入租车协议
toProtocol(){
console.log(this.data.rentType)
getProtocol(3)
.then(res => {
console.log(res)
})
.catch(err => {
console.error(err)
alertTip(err.errMsg || err)
})
},
})
\ No newline at end of file
{
"navigationBarTitleText": "设备租赁"
}
\ No newline at end of file
<view class='con' wx:if='{{status=="normal"}}'>
<!--扫描 -->
<view class='con' wx:if='{{modelScan}}'>
<image src='{{imgScan}}' class='img-scan' bindtap='scanImg'></image>
<text class='title scan-title' bindtap='scanImg'>扫码用车</text>
<view class='insurance agree'>
<radio checked='{{agreeUserCar}}' catchtap='hascheck' color='#d7193c'></radio>
我同意智租科技
<text bindtap='toProtocol'> 《租车协议》</text>
</view>
<text class='scan' bindtap='bindByHand'>如果扫描失败,试试手动输入</text>
</view>
<!--手动输入 -->
<view class='con tip' wx:else>
<input placeholder='请输入二维码下方的编码' bindinput='deviceInput'></input>
<view class='insurance agree'>
<radio checked='{{agreeUserCar}}' catchtap='hascheck' color='#d7193c'></radio>
我同意智租科技
<text bindtap='toProtocol'>《租车协议》</text>
</view>
<button bindtap='apiUseCar' class='btn-bind'>开始用车</button>
<text class='scan' bindtap='backScan'>返回扫描添加</text>
</view>
</view>
<view class='con' wx:else>
<view class='wait-auto'>等待网点同意授权中...</view>
<view class='giveup'>
<text catchtap='giveUp'>放弃申请?</text>
</view>
</view>
\ No newline at end of file
/* pages/device_bind/device_bind.wxss */
page {
height: 100%;
}
.con {
display: flex;
flex-direction: column;
align-items: center;
background-color: #fff;
height: 100%;
}
.con.tip{
background-color: #f8f8f8;
width: 100%;
}
.img-scan {
margin-top: 106rpx;
width: 210rpx;
height: 210rpx;
}
.img-tip {
margin-top: 176rpx;
width: 480rpx;
height: 190rpx;
}
.title {
font-size: 21px;
line-height: 60rpx;
}
.scan-title {
margin-top: 40rpx;
}
.des {
color: #989898;
font-size: 13px;
line-height: 60rpx;
}
.tip-title{
margin-top: 60rpx;
}
.scan {
color: #d7193c;
box-sizing: border-box;
border: 2px solid #d7193c;
height: 64rpx;
margin-top: 50rpx;
padding: 0rpx 26rpx;
border-radius: 32rpx;
line-height: 60rpx;
font-size: 13px;
}
input{
box-sizing: border-box;
width: 100%;
padding: 0 30rpx;
line-height: 110rpx;
height: 110rpx;
background-color: #fff;
font-size: 14px;
margin-top: 12px;
}
.btn-bind{
background-color: #d7193c;
font-size: 17px;
width:695rpx;
height: 90rpx;
border-radius: 90rpx;
letter-spacing: 2px;
margin: 36rpx auto;
display: flex;
align-items: center;
justify-content: center;
}
.wait-auto{
color: #d7193c;
font-size: 50rpx;
margin: 60rpx 0;
}
.giveup{
color: #666666;
font-size: 30rpx;
display: flex;
justify-content: space-between;
padding: 0 80rpx;
}
.insurance {
padding: 20rpx 0;
}
.insurance text {
color: #d7193c;
}
\ No newline at end of file
const { api,alertTip ,imgName } = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
imgViplogo: imgName('viplogo.png'),
imgHeadshot: imgName('logo.png'),
imgMore: imgName('more.png'),
imgTip: imgName('tip.png'),
imgLogo: imgName('pointimg.png'),
nodePoint:{},//站点信息
userItemList: [{
msg: 0,
name: '站长列表',
icon: imgName('setting.png'),
page: '/pages/user_setting/user_setting'
}, {
msg: 0,
name: '退出登录',
icon: imgName('setting2.png'),
page: '1'
}]
},
onShow: function () {
let user=wx.getStorageSync('user').user
let {main}=user
let userItemList = [{
msg: 0,
name: '退出登录',
icon: imgName('setting2.png'),
page: '1'
}]
if (main){//主站长
userItemList = [{
msg: 0,
name: '站长列表',
icon: imgName('setting.png'),
page: '/pages/user_list/user_list'
}, {
msg: 0,
name: '退出登录',
icon: imgName('setting2.png'),
page: '1'
}]
}
this.setData({
user,
userItemList
})
this.getMyNodeInfo()
},
toDetailPage(e) {
let url = e.currentTarget.id
if (url === '1') {
//退出登录
this.loginOut()
return
}
wx.navigateTo({
url: e.currentTarget.id
})
},
//登出
loginOut() {
api.get('user/logout')
.then(res => {
wx.reLaunch({ url: '/pages/welcome2/welcome2' })
})
.catch(err => {
alertTip(err)
})
},
// 获取站点信息
getMyNodeInfo(){
api.get('user/myNodeInfo')
.then(res=>{
this.setData({
nodePoint:res.data
})
})
.catch(err=>{
console.log(err)
})
},
callphone(e){
wx.makePhoneCall({
phoneNumber: e.currentTarget.id
})
}
})
\ No newline at end of file
{"navigationBarTitleText": "我的网点"}
\ No newline at end of file
<view class='con'>
<view class='logo'>
<image src='{{nodePoint.nodePhoto?nodePoint.nodePhoto:imgLogo}}'></image>
<view class='item-dh'>{{nodePoint.nodeName}}</view>
</view>
<view>
<view class='point-des'>
<view class='item-dh'>
<text>地区:</text>
<text>{{nodePoint.province+' '+nodePoint.city+' '+nodePoint.area}}</text>
</view>
<view class='item-dh'>
<text>地址:</text>
<text>{{nodePoint.nodeAddress}}</text>
</view>
<view class='item-dh'>
<text>负责人:</text>
<text>{{nodePoint.mainUser}}</text>
</view>
<view class='item-dh' catchtap='callphone' id='{{nodePoint.innerPhone}}'>
<text>内部联系电话:</text>
<text>{{nodePoint.innerPhone}}</text>
</view>
<view class='item-dh' wx:if='{{nodePoint.parentName}}'>
<text>上级站点:</text>
<text>{{nodePoint.parentName}}</text>
</view>
</view>
</view>
<view class='i nav-item'>
<view class='layout item' wx:for="{{userItemList}}" wx:key='{{item.name}}' catchtap='toDetailPage' id='{{item.page}}'>
<view class='left'>
<image src='{{item.icon}}'></image>
<view>
<view>{{item.name}}</view>
</view>
</view>
<view class='right'>
<view class='msg-length' wx:if="{{item.msg!='0'}}">{{item.msg}}</view>
<image src='{{imgMore}}'></image>
</view>
</view>
</view>
</view>
\ No newline at end of file
page {
height: 100%;
}
.con {
height: 100%;
position: relative;
background-color: #f7f7f7;
font-size: 32rpx;
overflow: hidden;
}
.con .i {
background-color: #ffffff;
margin-bottom: 14rpx;
box-sizing: border-box;
padding: 0 28rpx;
}
.logo{
width: 100%;
height: 300rpx;
position: relative;
}
.logo image{
width: 100%;
height: 100%;
}
.logo view{
height: 80rpx;
line-height: 80rpx;
background-color:rgba(153, 153, 153, 0.6);
color: #fff;
position: absolute;
width: 100%;
left: 0;
bottom: 0;
}
.con .header {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.con .header .image {
width: 140rpx;
height: 140rpx;
border-radius: 50%;
overflow: hidden;
}
.con .header text {
padding-top: 28rpx;
}
.con .layout {
display: flex;
align-items: center;
justify-content: space-between;
}
.con .layout .left {
display: flex;
align-items: center;
}
.con .layout .left image {
width: 35rpx;
height: 35rpx;
margin-right: 36rpx;
}
.con .layout .right {
display: flex;
justify-content: flex-end;
align-items: center;
}
.con .layout .right image {
width: 22rpx;
height: 34rpx;
margin-left: 34rpx;
}
.con .vip {
height: 140rpx;
background-color: #ffffff;
}
.con .vip .layout {
height: 100%;
}
.con .vip .left .vip-title .des {
position: relative;
color: #999999;
font-size: 30rpx;
line-height: 60rpx;
}
.con .vip .left .vip-title .des .tip {
width: 70rpx;
height: 48rpx;
position: absolute;
top: -50rpx;
right: -36rpx;
}
.con .vip .right view {
width: 166rpx;
height: 64rpx;
line-height: 64rpx;
border-radius: 64rpx;
background-color: #d7193c;
text-align: center;
color: #ffffff;
letter-spacing: 12rpx;
}
.con .nav-item .item {
height: 110rpx;
margin-bottom: 2rpx;
position: relative;
}
.con .nav-item .item::after {
content: '';
width: 665rpx;
position: absolute;
right: -28rpx;
bottom: -2rpx;
border-bottom: 2rpx solid #f7f7f7;
}
.con .nav-item .msg-length {
width: 50rpx;
height: 34rpx;
background-color: #f43333;
font-size: 24rpx;
line-height: 34rpx;
border-radius: 17rpx;
text-align: center;
color: #ffffff;
}
.con .tab {
height: 110rpx;
width: 100%;
position: absolute;
bottom: 0;
left: 0;
background-color: #d7193c;
color: #fff;
line-height: 110rpx;
text-align: center;
}
.header-top{
display: flex;
height: 280rpx;
background-color: #fff;
justify-content: center;
margin-bottom: 20rpx;
align-items: stretch
}
.header{
flex: 0 0 200rpx;
}
.top-des{
display: flex;
flex-direction: column;
align-items:flex-start;
justify-content: center;
margin-bottom: 100rpx;
}
.item-dh{
padding: 0 30rpx;
line-height: 80rpx;
background-color: #fff;
border-bottom: 1px solid #eee;
display: flex;
}
.item-dh text:nth-of-type(1){
flex: 0 0 250rpx;
}
.point-des{
margin-bottom: 50rpx;
}
\ No newline at end of file
const qrcode = require('../../lib/qrcode.js')
Page({
/**
* 页面的初始数据
*/
data: {
carCode:''
},
onLoad: function (options) {
let size = this.setCanvasSize();//动态设置画布大小
qrcode.draw(options.vcu, 'qrcCanvas', size.w, size.h);
},
backList(){
wx.navigateBack()
},
//适配不同屏幕大小的canvas
setCanvasSize: function () {
var size = {};
try {
var res = wx.getSystemInfoSync();
var scale = 750 / 500;//不同屏幕下canvas的适配比例;设计稿是750宽
var width = res.windowWidth / scale;
var height = width;//canvas画布为正方形
size.w = width;
size.h = height;
} catch (e) {
// Do something when catch error
console.log("获取设备信息失败" + e);
}
return size;
},
})
\ No newline at end of file
{}
\ No newline at end of file
<canvas class='qrcode' catchtap='backList' canvas-id="qrcCanvas"/>
\ No newline at end of file
/* pages/test/test.wxss */
page{
height: 100%;
}
.qrcode{
width: 500rpx;
height: 500rpx;
position: absolute;
top: 50%;
left: 50%;
margin-top: -250rpx;
margin-left:-250rpx;
background:#f1f1f1;
}
\ No newline at end of file
const {
api,
alertTip,
getProtocol
} = require('../../lib/util.js')
var t = {}
Page({
data: {
inputAccount: null,
inputPassword: null,
inputPasswordAgain: null,
id: '', //用户id
inType: '2' //使用类型 0修改自身改密 1修改副账户密码 2新增用户
},
onLoad: function(query) {
this.setData({
inType: query.type,
id: query.id||''
})
},
onShow: function() {
},
numInput(e) {
this.setData({
[e.target.id]: e.detail.value
})
},
canBind(willTip) {
if (this.data.inType == 2) {
if (!this.data.inputAccount) {
willTip && alertTip('请输入账号!')
return false
}
}
if (!this.data.inputPassword) {
willTip && alertTip('请输入密码!')
return false
}
if (this.data.inputPasswordAgain != this.data.inputPassword) {
willTip && alertTip('两次输入的密码不一样!')
return false
}
return true
},
sureFormat() {
if (this.canBind(true)) {
let {
id,
inputAccount,
inputPassword
} = this.data
console.log(id,
inputAccount,
inputPassword)
switch (this.data.inType) {
case '0':
api.get('user/updatePwd', {
password: inputPassword
})
.then(res => {
alertTip('修改成功', () => {
wx.navigateBack()
})
})
.catch(err => {
alertTip(err)
})
break;
case '1':
api.get('user/updateUser', {
id,
password: inputPassword
})
.then(res => {
alertTip('修改成功', () => {
wx.navigateBack()
})
})
.catch(err => {
alertTip(err)
})
break;
case '2':
api.get('user/addUser', {
account: inputAccount,
password: inputPassword
})
.then(res => {
alertTip('增加成功', () => {
wx.navigateBack()
})
})
.catch(err => {
alertTip(err)
})
break;
}
}
}
})
\ No newline at end of file
{
"navigationBarTitleText": "用户注册"
}
\ No newline at end of file
<view class='con'>
<view class='form-box'>
<view class='phone list' hidden='{{inType!=2}}'>
<text class='form-tip'>账号</text>
<input type='text' id='inputAccount' placeholder='请输入账号' bindinput='numInput'></input>
</view>
<view class='phone-sure list'>
<text class='form-tip'>密码</text>
<input type='text' id='inputPassword' password placeholder='请输入密码' bindinput='numInput'></input>
</view>
<view class='phone-sure list'>
<text class='form-tip'>确认密码</text>
<input type='text' id='inputPasswordAgain' password placeholder='请再次输入密码' bindinput='numInput'></input>
</view>
</view>
<button bindtap='sureFormat'>确定</button>
</view>
\ No newline at end of file
page{
position: relative;
min-height: 100%;
padding-bottom: 50rpx;
background-color: #f8f8f8;
}
.con {
min-height: 100%;
padding: 14px 30rpx 0;
text-align: left;
}
.con text,.con view{
font-size: 28rpx;
}
.form-box {
width:750rpx;
margin-left: -30rpx;
background-color: #fff;
}
.form-tip{
flex-basis: 220rpx;
flex-shrink: 0;
}
.phone {
width: 100%;
}
.list {
height: 110rpx;
display: flex;
align-items: center;
padding: 0 30rpx;
border-bottom: 2rpx solid #f8f8f8;
}
.list input{
flex-grow: 1;
}
.msg {
color: #ffffff;
background-color: #2f2f2f;
border-radius: 62rpx;
padding: 18rpx 26rpx;
flex: 0 0 auto;
}
.msg.des{
color:#eee;
}
.insurance {
display: flex;
color: #7d7d7d;
}
.agree{
display: flex;
justify-content: center;
align-items: center;
}
.insurance text {
color: #d7193c;
}
.radio{
margin-right:10rpx;
}
button {
background-color: #d7193c;
border-radius: 90rpx;
letter-spacing: 4px;
margin: 36rpx auto;
}
.mode{
justify-content: flex-start;
}
.point{
flex: 1;
}
\ No newline at end of file
// pages/server_detail/server_detail.js
// pages/server_items/server_items.js
const { api, previewPic,confirmTip,formatTime, mapApi, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
orderNo:'--',
id:null,//订单编号
orderTime:'--',
receiveTime: '--',
completeTime: '--',
cancleTime: '--',
state: -1,
stateName: '--',
userPerson: '--',
vehicleModel: '--',
frameNo: '--',
vcuNo: '--',
pics: [],
comment: '--',
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.setData({
id:options.serverId
})
this.resetUi()
},
resetUi(){
let that=this
api.get('order/orderDetail', { id: that.data.id })
.then(res => {
let { orderNo, cancleTime, comment, completeTime, createAt, frameNo, id, manHourFee, nodeId, orderTime, pics, price, receiveTime, repairComment, repairUserId, state, userId, userName, userPhone, vcuNo, vehicleModel } = res.data
let stateName = ['已下单', '已接单', '已完成', '已评价', '已取消'][state]
let userPerson = userName + (userPhone && `(${userPhone})`)
orderTime = orderTime ? formatTime(new Date(orderTime)) : null
receiveTime = receiveTime ? formatTime(new Date(receiveTime)) : null
completeTime = completeTime ? formatTime(new Date(completeTime)) : null
cancleTime = cancleTime ? formatTime(new Date(cancleTime)) : null
pics = pics ? pics.split(',') : []
this.setData({
orderNo,
id,
orderTime,
receiveTime,
completeTime,
cancleTime,
state,
stateName,
userPerson,
vehicleModel,
frameNo,
vcuNo,
pics,
comment,
})
})
.catch(err => {
alertTip(err)
})
},
//接单
receiveOrder(){
let that = this
let id = that.data.id
if (!id) {
alertTip('数据不正常', () => {
wx.navigateBack()
})
}
confirmTip('您确认接单?',()=>{
api.get('order/receiveOrder', { id })
.then(res => {
console.log(res)
alertTip('接单成功', () => {
that.resetUi()
})
})
.catch(err => {
alertTip(err)
})
})
},
//处理订单
toItems(){
let id = this.data.id
if (!id) {
alertTip('数据不正常', () => {
wx.navigateBack()
})
}
confirmTip('您确认处理工单?', () => {
wx.navigateTo({
url: '/pages/server_items/server_items?id=' + id,
})
})
},
previewPic(e){
let { src,list} = e.currentTarget.dataset;
previewPic(src, list)
}
})
\ No newline at end of file
{
"navigationBarTitleText": "预约服务详情"
}
\ No newline at end of file
<view class='con'>
<scroll-view class='items' scroll-y>
<view class='title item'>
<text>服务单号:{{orderNo}}</text>
<text>{{stateName}}</text>
</view>
<view class='time item'>保修用户:{{userPerson}}</view>
<view class='time item' hidden='{{!orderTime}}'>预约时间:{{orderTime}}</view>
<view class='time item' hidden='{{!receiveTime}}'>接单时间:{{receiveTime}}</view>
<view class='time item' hidden='{{!completeTime}}'>完成时间:{{completeTime}}</view>
<view class='time item' hidden='{{!cancleTime}}'>取消时间:{{cancleTime}}</view>
<view class='time item'>车型:{{vehicleModel}}</view>
<view class='time item'>车架号:{{frameNo}}</view>
<view class='time item'>VCU:{{vcuNo}}</view>
<view class='car-des item' hidden='{{pics.length==0}}'>
<view>图片:</view>
<view class='des-body'>
<image src='{{item}}' catchtap='previewPic' data-src="{{item}}" data-list="{{pics}}" wx:for='{{pics}}' wx:key='{{index}}'></image>
</view>
</view>
<view class='problem item'>
<text>问题描述:</text>
<text>{{comment}}</text>
</view>
</scroll-view>
<view class='aciton' wx:if='{{state==0}}'>
<text catchtap='receiveOrder'>接单</text>
</view>
<view class='aciton' wx:if='{{state==1}}'>
<text catchtap='toItems'>处理</text>
</view>
</view>
\ No newline at end of file
/* pages/server_detail/server_detail.wxss */
page{
height: 100%;
}
.con{
height: 100%;
padding-bottom: 150rpx;
}
.item{
padding:30rpx 40rpx;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 2rpx solid #eee;
}
.items{
height: 100%;
overflow: hidden;
}
.time{
background-color: #ffffff;
}
.title{
background-color: #eee;
}
.title text:nth-of-type(2){
color: #d7193c;
}
.problem{
align-items: flex-start;
justify-content: flex-start;
}
.problem text:nth-of-type(1){
flex: 0 0 170rpx;
}
.problem text:nth-of-type(2){
flex: 1 0 300rpx;
}
.car-des{
justify-content: flex-start;
}
.car-des image{
width: 150rpx;
height: 150rpx;
margin-right: 20rpx;
}
.des-body{
flex: 1 0 auto;
}
.des-item{
display: flex;
padding: 10rpx 0;
}
.des-item text:nth-of-type(1){
flex: 0 0 120rpx;
}
.aciton{
position: absolute;
bottom: 0;
left: 0;
width: 100%;
box-sizing: border-box;
padding: 50rpx;
background-color: transparent;
display: flex;
justify-content: space-between;
align-items: center;
}
.aciton text{
padding: 20rpx 0;
text-align: center;
}
.aciton text:nth-of-type(1){
background-color: #d7193c;
color: #ffffff;
flex: 1 0 300rpx;
border-radius: 10rpx;
margin-right: 20rpx;
}
.aciton text:nth-of-type(2){
background-color: #ffffff;
color: #d7193c;
border: 1px solid #d7193c;
flex: 1 0 300rpx;
border-radius: 10rpx;
}
\ No newline at end of file
// pages/server_items/server_items.js
const { api, mapApi, formatTime, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
selectList:[],//选中类目的数组id
selectItems:[],//选中的内容数组
showList:[],//显示数组
originList: [],//原始数组
imgSearch:imgName('search.png'),
imgSelectrue: imgName('security_settings_unchecked.png'),
imgSelect: imgName('security_settings_unchecked_active.png'),
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.setData({
id: options.id
})
this.getRepairItemsList()
},
searchInput(e){
this.setShowList(e.detail.value)
},
searchComfirm(e){
this.setShowList(e.detail.value)
},
setShowList(value){
let newList = this.data.originList.map(item => {
let index = this.data.selectList.indexOf(item.id)
if (index == -1) {
item.check = false
} else {
item.check = true
}
return item
})
if (!value) {
this.setData({
showList: newList
})
return
}
let showList = newList.filter(item => {
return new RegExp(value).test(item.name)
})
this.setData({
showList
})
},
//选择单项
selectItem(e){
let id=e.currentTarget.id
let selectList = this.data.selectList
let index = selectList.indexOf(Number(id))
if (index==-1){
selectList.push(Number(id))
}else{
selectList.splice(index,1)
}
let selectItems = this.data.originList.filter(item=>{
return selectList.indexOf(Number(item.id))!=-1
})
this.setData({
selectList,
selectItems
})
this.setShowList()
},
//next 下一步
toNext(){
if (this.data.selectItems.length==0){
alertTip('未选择任何维修项目')
return
}
wx.navigateTo({
url: '/pages/server_sure/server_sure?id='+this.data.id,
})
},
//拿到维修项目
getRepairItemsList(){
api.get('order/repairItemsList')
.then(res=>{
let dataLists = res.items.map(item=>{
item.check=false
item.time = item.manHours+'工时'
item.fee ='¥'+item.materialFee
return item
})
this.setData({
showList: dataLists,
originList: dataLists
})
})
.catch(err=>{
alertTip(err)
})
}
})
\ No newline at end of file
{
"navigationBarTitleText": "选择维修项目",
"usingComponents": {
"wr-serach": "/components/search/search"
}
}
\ No newline at end of file
<view class='con'>
<view class='search'>
<wr-serach onchange='searchInput' onsearch='searchComfirm'></wr-serach>
</view>
<scroll-view scroll-y class='scroll'>
<view wx:for='{{showList}}' wx:key='{{item.id}}' class='server-item' id='{{item.id}}' catchtap='selectItem'>
<view class='hascheck'>
<image src='{{imgSelect}}' wx:if='{{item.check}}'></image>
<image src='{{imgSelectrue}}' wx:else></image>
</view>
<view class='item-title'>
<text>{{item.name}}</text>
<text class='label' wx:if='{{item.tip}}'>出保</text>
</view>
<view class='item-time'>
{{item.time}}
</view>
<view class='item-fee'>
{{item.fee}}
</view>
</view>
</scroll-view>
<view class='next'>
<text class='tip'>已选择{{selectList.length}}项</text>
<button catchtap='toNext'>下一步</button>
</view>
</view>
\ No newline at end of file
page,.con{
height: 100%;
overflow: hidden;
}
.con{
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: stretch;
}
.search{
flex: 0 0 auto;
padding: 20rpx 30rpx;
background-color: #eee;
}
.scroll{
flex: 1 0 200rpx;
overflow: hidden;
}
.next{
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 30rpx;
}
.next button{
background-color: #d7193c;
font-size: 32rpx;
width: 300rpx;
margin: 0
}
.tip{
color: #d7193c;
}
.server-item{
display: flex;
padding: 20rpx 30rpx;
justify-content: space-between;
}
.hascheck{
margin-right: 40rpx;
}
.hascheck image{
width: 40rpx;
height: 40rpx;
}
.item-title{
flex: 1 0 50rpx;
}
.label{
font-size: 24rpx;
line-height: 24rpx;
color: #fff;
background-color: #d7193c;
padding: 6rpx 20rpx;
border-radius: 30rpx;
margin-left: 10rpx;
}
.item-time{
flex: 0 0 130rpx;
}
.item-fee{
flex: 0 0 130rpx;
text-align: right;
}
\ No newline at end of file
// pages/server_sure/server_sure.js
const { api, formatTime, uploadResource,mapApi, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
prevPage:null,
totalTime:null,
repairComment:'',
totalMoney: null,
videos:'',//视频
pics: [],//图片
imgScan: imgName('imgscan.png'),
imgClose: imgName('close.png'),
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
let pages = getCurrentPages();
let prevPage = pages[pages.length - 2]; //上一个页面
let totalTime = prevPage.data.selectItems.reduce((total,item)=>{
return total+item.manHours
},0)
let totalMoney = prevPage.data.selectItems.reduce((total, item) => {
return total + item.materialFee
},0)
this.setData({
prevPage,
showList: prevPage.data.selectItems,
totalMoney,
items: prevPage.data.selectList.join(','),
totalTime,
id: prevPage.data.id
})
},
repairCommentInput(e){
let repairComment=e.detail.value
this.setData({
repairComment
})
},
//完成订单
completeOrder(){
let { id, items, repairComment, videos,pics}=this.data
let repairPics=pics.join(',').trim()
api.get('order/completeOrder',{
id, items, repairComment, videos, repairPics
})
.then(res=>{
alertTip('提交成功',()=>{
wx.switchTab({
url: '/pages/user_index/user_index'
});
})
})
.catch(err=>{
alertTip(err)
})
},
//选择图片
upimg: function () {
var that = this;
let hasImgLength = this.data.pics.length
if (hasImgLength < 3) {
wx.chooseImage({
count: 3 - hasImgLength, // 默认9
sizeType: ['original', 'compressed'],
success: function (res) {
uploadResource(res.tempFilePaths)
.then(picsRe=>{
let pics = that.data.pics.concat(picsRe)
that.setData({
pics
})
})
.catch(err=>{
alertTip('上传图片失败')
})
}
})
} else {
alertTip('最多上传三张图片')
}
},
//选择视频
upvideos: function () {
var that = this;
wx.chooseVideo({
sourceType: ['album', 'camera'],
maxDuration: 60,
success: function (res) {
that.setData({
videos: res.tempFilePath
})
uploadResource(res.tempFilePath,'视频')
.then(videos => {
that.setData({
videos
})
})
.catch(err => {
alertTip('上传视频失败')
})
}
})
},
//删除图片
deleteImg(e) {
let index = Number(e.currentTarget.id)
this.data.pics.splice(index, 1)
this.setData({
pics: this.data.pics
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
}
})
\ No newline at end of file
{}
\ No newline at end of file
<view class='con'>
<scroll-view scroll-y class='scroll'>
<view class='total-title'>选择项:</view>
<view class='total-item'>
<view wx:for='{{showList}}' wx:key='{{item.id}}' class='server-item' id='{{item.id}}'>
<view class='item-title'>
<text>{{item.name}}</text>
<text class='label' wx:if='{{item.tip}}'>出保</text>
</view>
<view class='item-time'>
{{item.time}}
</view>
<view class='item-fee'>
{{item.fee}}
</view>
</view>
</view>
<view class='total'>
<view class='total-title'>总计:</view>
<view class='total-other total-item'>
<view>
<text>工时:</text>
<text class='tip'>{{totalTime}}工时</text>
</view>
<view>
<text>材料费:</text>
<text class='tip'>¥{{totalMoney}}</text>
</view>
</view>
</view>
<view class='total'>
<view class='total-title'>维修评论:</view>
<view class='total-other total-item'>
<textarea placeholder='请输入维修评论' bindinput='repairCommentInput'></textarea>
</view>
</view>
<view class='total'>
<view class='total-title'>视频上传:</view>
<view class='total-other total-item upload' catchtap='upvideos'>
<image src='{{imgScan}}' hidden='{{videos}}'></image>
<text>{{videos?'视频已上传(点击替换)':''}}</text>
</view>
</view>
<view class='total'>
<view class='total-title'>图片上传:</view>
<view class='total-other total-item upload'>
<block wx:for="{{pics}}" wx:key="unique">
<view class='logoinfo'>
<image class='close' id='{{index}}' src='{{imgClose}}' catchtap='deleteImg'></image>
<image src='{{item}}'></image>
</view>
</block>
<image bindtap="upimg" src='{{imgScan}}'></image>
</view>
</view>
</scroll-view>
<view class='next'>
<button catchtap='completeOrder'>完成订单</button>
</view>
</view>
\ No newline at end of file
/* pages/server_sure/server_sure.wxss */
@import '../server_items/server_items.wxss'
.next{
text-align: center;
}
.next button{
margin: auto;
}
.total-title{
font-size: 36rpx;
font-weight: bold;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
padding:30rpx;
}
.total-item,server-item{
box-sizing: border-box;
padding-left: 170rpx;
padding-right: 30rpx;
line-height: 60rpx;
}
.total-other{
padding-left: 200rpx;
}
.tip{
color: #d7193c;
}
textarea{
border:1px solid #eee;
margin-top: 30rpx;
box-sizing: border-box;
width: 100%;
}
.upload{
padding-top: 50rpx;
padding-bottom: 50rpx;
display: flex;
}
.upload image{
width: 100rpx;
height: 100rpx;
vertical-align: middle;
margin-right:20rpx;
}
.upload image{
width: 100rpx;
height: 100rpx;
}
.logoinfo{
position: relative;
}
.upload image.close{
position: absolute;
top: 0;
right: 0;
width:50rpx;
height: 50rpx;
}
\ No newline at end of file
const config = require('../../config/index.js')
const { api, formatTime, mapApi, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
let orderState = ['已下单', '已接单', '已完成', '已完成', '已取消']
let serverTimer = null//数据轮询 订单列表
Page({
/**
* 页面的初始数据
*/
data: {
showList:[],//服务数组
messageNum:0,
imgSensitize: imgName('sensitize.png'),
imgHasalarm: imgName('hasalarm.png'),
page: 1,//当前页面
hasMorePage: false,//更多页面
},
markerTap() {
},
//消息
toMsgPage() {
wx.navigateTo({
url: '/pages/user_message/user_message',
})
},
//服务详情
toServerDetail(e){
let serverId=e.currentTarget.id
wx.navigateTo({
url: '/pages/server_detail/server_detail?serverId='+serverId,
})
},
onLoad: function () {
},
onHide: function () {
clearInterval(serverTimer)
},
onUnload() {
clearInterval(serverTimer)
},
onShow: function () {
let that=this
that.getOrderList()
serverTimer=setInterval(()=>{
that.getOrderList()
},5000)
},
getOrderList() {
//获取订单
let that=this
api.get('order/orderList',
{curPage: this.data.page,state:'0,1'}
,true)
.then(res => {
let showList = res.items.map(item => {
item.orderTime = formatTime(new Date(item.orderTime))
item.state = ['未接单', '已接单'][item.state]
item.pics = item.pics.split(',')[0] || imgName('logo.png')
return item
})
this.setData({
showList: that.data.page === 1 ? showList : that.data.showList.concat(showList),
hasMorePage: res.model.haveMore,
page: res.model.haveMore ? that.data.page + 1 : 1,
})
if (this.data.showList.length !== 0 && res.model.haveMore){
clearInterval(serverTimer)
}
})
.catch(err => {
alertTip(err)
})
}
})
\ No newline at end of file
{
"navigationBarTitleText": "智租保",
"enablePullDownRefresh": true
}
\ No newline at end of file
<!--pages/user_index/user_index.wxml-->
<view class='con'>
<view class='header' hidden='{{messageNum==0}}'>
<!-- <view class='item sensitize'>
<image src='{{imgSensitize}}'></image>
激活
</view> -->
<view class='item notify-num'>
<image src='{{imgHasalarm}}'></image>
通知
<text>{{messageNum}}</text>
</view>
</view>
<view class='notify' wx:if='{{showList.length==0}}'>
<text class='tip'>您暂无需要处理的事务</text>
</view>
<scroll-view wx:else class='server-list' scroll-y>
<view class='server-title'>
您有 <text>{{showList.length}}</text> 个待处理的预约服务
</view>
<view class='list-item' wx:for='{{showList}}' wx:key='{{item.id}}' id='{{item.id}}' catchtap='toServerDetail'>
<image src='{{item.pics}}'></image>
<view class='item-des item-text'>
<text>单号:{{item.orderNo}}</text>
<text>车型:{{item.vehicleModel}}</text>
<text>用户:{{item.userName}}</text>
<text>手机:{{item.userPhone}}</text>
</view>
<view class='item-state item-text'>
<text class='tip2'>{{item.state}}</text>
<text class='low-text'>{{item.orderTime}}</text>
</view>
</view>
<view class='btn' wx:if='{{hasMorePage}}'>
<button catchtap='getOrderList'>加载更多</button>
</view>
</scroll-view>
</view>
page{
height: 100%;
}
.con{
height: 100%;
display: flex;
flex-direction: column;
align-items: stretch;
}
.header{
height: 100rpx;
display: flex;
align-items: center;
justify-content: space-around;
border-bottom:2rpx solid #eeeeee;
}
.item{
width: 280rpx;
padding: 10rpx 30rpx;
display: flex;
align-items: center;
justify-content: center;
border: 2rpx solid #d7193c;
border-radius: 10rpx;
}
.item image{
width: 50rpx;
height: 50rpx;
padding-right: 20rpx;
}
.notify-num text{
color: #fff;
border-radius:25rpx;
padding: 4rpx 20rpx;
background-color: #d7193c;
margin-left: 10rpx;
line-height: 26rpx;
font-size: 24rpx;
}
.notify{
flex: 1 0 auto;
display: flex;
justify-content: center;
align-items: center;
}
.tip{
color: #d7193c;
font-size: 40rpx;
}
.server-list{
flex: 1 0 200rpx;
overflow: hidden;
}
.server-title{
border-bottom:2rpx solid #eeeeee;
padding: 0 30rpx;
font-weight: 700;
}
.server-title text{
color: #d7193c;
font-size: 40rpx;
line-height: 60rpx;
}
.list-item{
padding: 30rpx;
border-bottom:2rpx solid #eeeeee;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 28rpx;
}
.list-item image{
flex: 0 0 auto;
width: 80rpx;
height: 80rpx;
margin-right: 30rpx;
}
.item-text{
display: flex;
flex-direction: column;
justify-content: space-around;
align-self: stretch;
flex: 1 0 200rpx;
}
.item-state{
align-items: flex-end;
flex: 0 0 30rpx;
flex-wrap: wrap;
text-align: right;
white-space: pre-wrap;
}
.low-text{
color: #cccccc;
}
.tip2{
color: #d7193c;
}
.btn{
padding: 30rpx;
}
.btn button{
background-color: #d7193c;
}
\ No newline at end of file
const { api, mapApi, formatTime, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
userList:[]//用户列表
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
this.getUserList()
},
//获取所有的站长
getUserList(){
api.get('user/userList')
.then(res=>{
this.setData({
userList:res.items
})
})
.catch(err=>{
alertTip(err)
})
},
changeState(e){
let item=e.currentTarget.dataset.item
let that=this
api.get('user/changeState', { id:item.id,state:Math.abs(item.state-1)})
.then(res=>{
alertTip('修改成功',()=>{
that.getUserList()
})
})
.catch(err=>{
alertTip(err)
})
},
deleteUser(e) {
let item = e.currentTarget.dataset.item
let that = this
api.get('user/deleteUser', { id: item.id})
.then(res => {
alertTip('删除成功', () => {
that.getUserList()
})
})
.catch(err => {
alertTip(err)
})
},
updateUser(e) {
let item = e.currentTarget.dataset.item
let type1=1
//使用类型 0修改自身改密 1修改副账户密码 2新增用户
if(item.main){
type1 = 0
}
wx.navigateTo({
url: '/pages/register2/register2?type='+type1+'&id='+item.id,
})
},
addUser(){
wx.navigateTo({
url: '/pages/register2/register2?type=2',
})
}
})
\ No newline at end of file
{}
\ No newline at end of file
<view class='con'>
<view class='user-item' wx:for='{{userList}}' wx:key='{{item.id}}'>
<view class='user-name'>
{{item.account}}
</view>
<text class='label'>{{item.main?'主':'副'}}</text>
<view class='btn-group'>
<text class='btn' data-item='{{item}}' catchtap='changeState' hidden='{{item.main}}'>{{item.state?'已禁用':'已启用'}}</text>
<text class='btn' data-item='{{item}}' catchtap='deleteUser' hidden='{{item.main}}'>删除</text>
<text class='btn' data-item='{{item}}' catchtap='updateUser'>改密</text>
</view>
</view>
<button catchtap='addUser'>新增用户</button>
</view>
\ No newline at end of file
/* pages/user_list/user_list.wxss */
.con{
padding: 0 30rpx;
}
button{
margin: 50rpx;
background-color: #d7193c;
}
.user-item{
margin-bottom: 50rpx;
position: relative;
height: 200rpx;
border-radius: 10rpx;
box-shadow: 0px 4px 6px #eee;
text-align: center;
}
.label {
position: absolute;
right: 10rpx;
top:20rpx;
padding: 10rpx 20rpx;
background-color: #d7193c;
color: #fff;
border-radius:40rpx;
}
.user-name{
height: 100rpx;
font-weight: bold;
line-height: 100rpx;
}
.btn-group{
display: flex;
justify-content: space-around;
}
.btn{
padding: 20rpx 40rpx;
background-color: #eee;
border-radius: 6rpx;
}
\ No newline at end of file
const { api, mapApi, formatTime, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation} = require('../../lib/util.js')
let serverTimer=null
let orderState = ['已下单', '已接单', '已完成', '已评价', '已取消']
Page({
data: {
//标题数据
titleList:[
{
name:'全部'
},
{
name: '已下单'
},
{
name: '已接单'
},
{
name: '已完成'
},
{
name: '已取消'
}
],
state:-1,
showList:[],
imgNomes: imgName('nomes.png'),
page: 1,//当前页面
hasMorePage: false,//更多页面
searhValue:''
},
onLoad(){
// this.getOrderList()
},
onShow: function () {
this.getOrderList()
},
//搜索
apiSearch(e){
this.setData({
page:1,
searhValue:e.detail.value
})
this.getOrderList()
},
tabChange(e){
let index=e.detail.activeIndex
let stateArray=[-1,0,1,'2,3',4]
this.setData({
page:1,
state: stateArray[index]
})
this.getOrderList()
},
getOrderList(){
let that=this
let op = {
curPage: that.data.page,
state: that.data.state
}
if (this.data.searhValue != '') { op.name = this.data.searhValue}
api.get('order/orderList', op )
.then(res=>{
let showList = res.items.map(item=>{
item.orderTime = formatTime(new Date(item.orderTime))
item.state = orderState[item.state]
item.pics=item.pics.split(',')[0]||imgName('logo.png')
return item
})
this.setData({
showList: that.data.page === 1 ? showList : that.data.showList.concat(showList),
hasMorePage: res.model.haveMore,
page: res.model.haveMore ? that.data.page+1:1,
})
})
.catch(err=>{
alertTip(err)
})
},
//服务详情
toServerDetail(e) {
let serverId = e.currentTarget.id
// console.log(e)
wx.navigateTo({
url: '/pages/server_detail/server_detail?serverId=' + serverId,
})
},
})
\ No newline at end of file
{
"usingComponents": {
"navbar": "/components/navbar/navbar",
"wr-serach": "/components/search/search"
}
}
\ No newline at end of file
<view class='msg-read'>
<view class='search'>
<wr-serach onchange='apiSearch' placeholder='搜索预约单号/用户名/预约用户手机'></wr-serach>
</view>
<navbar titleList='{{titleList}}' ontabChange='tabChange'></navbar>
<scroll-view class='list-body' scroll-y>
<view wx:if='{{showList.length!=0}}'>
<view class='list-item' wx:for='{{showList}}' wx:key='{{item.serverNum}}' id='{{item.id}}' catchtap='toServerDetail'>
<image src='{{item.pics}}'></image>
<view class='item-des item-text'>
<text>单号:{{item.orderNo}}</text>
<text>车型:{{item.vehicleModel}}</text>
<text>用户:{{item.userName}}</text>
<text>手机:{{item.userPhone}}</text>
</view>
<view class='item-state item-text'>
<text class='tip2'>{{item.state}}</text>
<text class='low-text'>{{item.orderTime}}</text>
</view>
</view>
<view class='btn' wx:if='{{hasMorePage}}'>
<button catchtap='getOrderList'>加载更多</button>
</view>
</view>
<view wx:else class='no-list'>
<text class='tip2'>不存在任何订单</text>
</view>
</scroll-view>
</view>
\ No newline at end of file
page{
height: 100%;
}
.msg-read{
display: flex;
flex-direction: column;
height: 100%;
}
.list-body{
flex: 1 0 100rpx;
overflow: hidden;
}
.list-item{
padding: 30rpx;
border-bottom:2rpx solid #eeeeee;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 28rpx;
}
.list-item image{
flex: 0 0 auto;
width: 80rpx;
height: 80rpx;
margin-right: 30rpx;
}
.item-text{
display: flex;
flex-direction: column;
justify-content: space-around;
align-self: stretch;
flex: 0 0 200rpx;
}
.item-state{
align-items: flex-end;
flex-wrap: wrap;
text-align: right;
white-space: pre-wrap;
}
.low-text{
color: #cccccc;
}
.tip2{
color: #d7193c;
}
.no-list{
padding: 50rpx;
text-align: center;
}
.search{
padding: 20rpx 20rpx;
background-color: #eee;
}
.btn{
padding: 30rpx;
}
.btn button{
background-color: #d7193c;
}
\ No newline at end of file
const { api, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser } = require('../../lib/util.js')
Page({
data: {
title:'智租科技',
titleDes:'这是一段描述',
//图片
imgLogo: imgName('logo.png'),
imgPerson: imgName('sign_in_phone_white.png'),
imgLock: imgName('sign_in_password_white.png'),
user:null
},
onLoad: function () {
// wx.removeStorageSync('user')
},
onUnload(){},
onHide() {},
//登录
formSubmit(e){
if (!e.detail.value.account) {
alertTip('请输入账号!')
return false
}
if (!e.detail.value.password) {
alertTip('请输入密码!')
return false
}
let that=this
api.get('user/login',e.detail.value)
.then(res => {
let user=res.data
wx.setStorageSync('user', user)
wx.switchTab({
url: '/pages/user_index/user_index'
});
})
.catch(err => {
alertTip(err)
})
},
forgetPassword() {
// wx.navigateTo({
// url: '/pages/forgetpassword/forgetpassword',
// })
}
})
\ No newline at end of file
{
}
\ No newline at end of file
<view class='con'>
<image class='logo' src='{{imgLogo}}'></image>
<form class='from-login' bindsubmit="formSubmit" report-submit>
<view class='form-item'>
<label for='account'>
<image src='{{imgPerson}}'></image>
</label>
<input id='account' name='account' placeholder='请输入账号'></input>
</view>
<view class='form-item'>
<label for='password'>
<image src='{{imgLock}}'></image>
</label>
<input type='text' name='password' id='password' password placeholder='请输入密码'></input>
</view>
<button formType="submit">登录</button>
</form>
<!-- <view class='forget'>
<text catchtap='forgetPassword'>忘记密码?</text>
</view> -->
</view>
\ No newline at end of file
page {
height: 100%;
}
.con {
height: 100%;
text-align: center;
padding-top: 78rpx;
position: relative;
}
.con .logo {
width: 236rpx;
height: 236rpx;
}
.con .from-login {
display: block;
padding: 60rpx 62rpx 30rpx 62rpx;
}
.con .from-login .form-item {
box-sizing: border-box;
border: 4rpx solid #cccccc;
border-radius: 45rpx 45rpx;
background-color: #ffffff;
height: 90rpx;
line-height: 90rpx;
margin-bottom: 35rpx;
display: flex;
align-items: center;
justify-content: flex-start;
text-align: left;
font-size: 14px;
}
.con .from-login .form-item label {
width: 76rpx;
padding-left: 34rpx;
height: 42rpx;
line-height: 42rpx;
flex-grow: 0;
}
.con .from-login .form-item image {
width: 42rpx;
height: 42rpx;
margin-right: 34rpx;
}
.con .from-login .form-item input {
flex-grow: 1;
}
button {
margin-top: 82rpx;
background-color:#d7193c;
color:#fff;
font-size: 34rpx;
height: 90rpx;
border-radius: 45rpx;
letter-spacing: 4px;
}
.con .forget,.giveup{
color: #666666;
font-size: 30rpx;
display: flex;
justify-content: space-between;
padding: 0 80rpx;
}
.wait-auto{
color: #d7193c;
font-size: 50rpx;
margin: 60rpx 0;
}
.form-tip{
flex-basis: 220rpx;
flex-shrink: 0;
text-align: start;
}
.phone {
width: 100%;
}
.list {
height: 110rpx;
display: flex;
align-items: center;
padding: 0 30rpx;
border-bottom: 2rpx solid #f8f8f8;
}
.list input{
flex-grow: 1;
}
.radio-group{
flex: 1;
display: flex;
justify-content: space-between
}
.btn{
width: 80%;
}
.point{
flex: 1;
text-align: start;
}
.giveup2{
justify-content: flex-end;
}
\ No newline at end of file
{
"description": "项目配置文件。",
"setting": {
"urlCheck": true,
"es6": true,
"postcss": true,
"minified": true,
"newFeature": true
},
"compileType": "miniprogram",
"libVersion": "1.6.6",
"appid": "wx75c847665ef7211e",
"projectname": "%E6%99%BA%E7%A7%9F%E4%BF%9D",
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": []
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment