Commit 668c3b91 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/pay/pay",
"pages/user_index/user_index",
"pages/user_travel_path/user_travel_path",
"pages/server_point/server_point",
"pages/server_detail/server_detail",
"pages/server/server",
"pages/my/my",
"pages/device_bind/device_bind",
"pages/settting/setting",
"pages/path_detail/path_detail",
"pages/forgetpassword/forgetpassword",
"pages/user_device_message/user_device_message",
"pages/agreement_use/agreement_use",
"pages/user_car_loc/user_car_loc",
"pages/user_message/user_message",
"pages/qr_code/qr_code",
"pages/register2/register2",
"pages/point_detail/point_detail"
],
"window": {
"backgroundTextStyle": "dark",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTitleText": "智租侠",
"navigationBarTextStyle": "black"
},
"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: {
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: 'wx2adf345dae23b51b',
appSecret: '73abd12083691a26638f15f412b5030b',
api: 'https://zhizuxia.zhizukj.com/ydb/app/',
rapi: 'http://114.116.54.143:8081/repair/app/',//repair
version: 'v1.0.00',
imgPath: '/static/image/',
key: '3URBZ-FX6KD-H654D-H25M2-YVGJO-UAFXD'
},
pro: {
appid: 'wx2adf345dae23b51b',
appSecret: '73abd12083691a26638f15f412b5030b',
api: 'https://zhizuxia.zhizukj.com/ydb/app/',
rapi: 'http://114.116.54.143:8081/repair/app/',//repair
version: 'v1.0.00',
imgPath: '/static/image/',
key: 'G5DBZ-NH5KD-D3A4F-HK246-D7SJZ-H3BDB'
}
}
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
}
//获取图片路径 param:图片名称带扩展名
const imgName = (imgNameWithExt = 'no.jpg') => {
return `${config.imgPath}${imgNameWithExt}`
}
//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()
}
}
})
})
}
}
//mockApi
const mockApi = {
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,
// 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()
}
}
})
})
}
}
//api 站点相关api
const rapi = {
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.rapi}${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.rapi}${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()
}
}
})
})
}
}
//payApi
const payApi = {
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 && res.data.message =='SUCCESS') {
resolve(res.data.data)
} else {
reject(res.data.data)
}
return
}
if (res.statusCode == 401) {
reject('请登录')
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) {
if (res.statusCode == 200) {
if (res.data.success && res.data.message == 'SUCCESS') {
resolve(res.data.data)
} else {
reject(res.data.data)
}
return
}
if (res.statusCode == 401) {
reject('请登录')
wx.redirectTo({ url: '/pages/welcome2/welcome2' })
return
}
reject(res.data, '请求成功')
},
fail(res) {
console.error('1', res)
reject(res.data, '请求失败')
},
complete() {
if (!notShowLoad) {
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.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: () => {
console.log('用户位置未授权')
reject('用户位置未授权')
}
})
} else if (authsettings['scope.userLocation'] == false) {
console.log('用户拒绝过授权')
wx.showModal({
title: '提示',
content: '你拒绝了用户定位,请打开',
success(res){
wx.openSetting({
success: (res) => {
if (res.authSetting["scope.userLocation"]){
wx.getLocation({
type: 'gcj02',
success: (location) => {
resolve(location)
},
fail: () => {
reject('用户位置获取失败')
}
})
}
},
fail(err){
reject('用户没有授权')
}
})
}
})
} else {
wx.getLocation({
type: 'gcj02',
success: (location) => {
console.log('location')
resolve(location)
},
fail: () => {
console.log('用户位置获取失败')
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 wxscan = function () {
return new Promise((resolve, reject) => {
wx.scanCode({
onlyFromCamera: true,
success: function (res) { resolve(res.result) },
fail: function (res) { reject('扫码失败,重试') }
})
})
}
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)
})
}
})
}
module.exports = {
formatTime,
imgName,
api,
getUserInfo,
wxLogin,
alertTip,
msgTip,
authAgainByUser,
userLocation,
wxscan,
getProtocol,
payApi,
rapi,
mockApi
}
const { api, imgName, getUserInfo } = require('../../lib/util.js')
Page({
data: {
msg: 'agreement_use'
},
onLoad: function () {
console.log('agreement_use')
},
onShow: function () {
console.log('agreement_use show')
}
})
\ No newline at end of file
{}
\ No newline at end of file
<view>
{{msg}}
</view>
\ No newline at end of file
/**index.wxss**/
.userinfo {
display: flex;
flex-direction: column;
align-items: center;
}
.userinfo-avatar {
width: 128rpx;
height: 128rpx;
margin: 20rpx;
border-radius: 50%;
}
.userinfo-nickname {
color: #aaa;
}
.usermotto {
margin-top: 200px;
}
\ No newline at end of file
const { api,alertTip} = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
deviceId:null,
userList:[],
master:false
},
onLoad: function (query) {
this.setData({
deviceId:Number(query.id),
master:Number(query.master)==wx.getStorageSync('user').userId
})
this.getUsers(this.data.deviceId)
},
onPullDownRefresh: function () {
this.getUsers(this.data.deviceId)
},
getUsers(id){
let that=this
api.get('api/vehicle/vehicleBindingUser.json', { userVehicleId:id})
.then(res=>{
console.log(res.items)
that.setData({
userList: res.items.map(item => {
item.mobile = item.mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
return item
})
})
})
.catch(err=>{
console.error(err)
alertTip(err)
})
},
unbindUser(e) {
let that = this
let userId = Number(e.currentTarget.id)
wx.showModal({
title: '警告',
content: '确定解除该用户的绑定?',
success: function (res) {
if (res.confirm) {
api.post('api/vehicle/removeBinding.json', { userVehicleId: that.data.deviceId, removeUserId: userId })
.then(res => {
console.log(res)
that.getUsers(that.data.deviceId)
})
.catch(err => {
alertTip(err)
})
}
}
})
}
})
\ No newline at end of file
{
"enablePullDownRefresh": true,
"navigationBarTitleText": "用户列表"
}
\ No newline at end of file
<view class='con'>
<view wx:for='{{userList}}' class='user-item'>
<view>用户手机号:<text>{{item.mobile}}</text></view>
<view id='{{item.userId}}' catchtap='unbindUser' class='unbind' hidden='{{!master}}'>解绑</view>
</view>
</view>
page {
height: 100%;
background-color: #f7f7f7;
}
.user-item{
background-color: #ffffff;
margin: 20rpx 0;
height: 104rpx;
padding:0 30rpx;
display: flex;
align-items: center;
font-size: 32rpx;
justify-content: space-between;
}
.user-item text{
color: #a5a5a5;
}
.unbind{
width: 162rpx;
height: 56rpx;
color: #000000;
border-radius: 28rpx;
letter-spacing: 8rpx;
line-height: 56rpx;
text-align: center;
background-color: #d7193c;
}
\ No newline at end of file
// pages/device_bind/device_bind.js
const { api, wxscan, rapi, userLocation, 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
// 站点地图
markers: [],
longitude: 120.126593,
latitude: 30.342009,
},
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
})
this.getStatus(this.data.rentType)
},
onHide(){
clearInterval(timer)
},
onUnload(){
clearInterval(timer)
},
onShow() {
//团个租
// this.getStatus(this.data.rentType)
if (this.data.rentType==1){
this.getPointLists()
}
},
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 => {
//等待。。
//团租
// if (rentType==0){
alertTip(res.message)
This.getStatus(rentType)
timer = setInterval(() => {
This.getStatus(rentType)
}, 5000)
return
// }
//个租租车逻辑
})
.catch(err => {
alertTip(err)
console.error(err)
})
},
getStatus(userType){
let This=this
let msgType=[2,3]
api.get('message/getMessageInfo',{
userId:This.data.userId,
messageType: msgType[userType]//申请用车
},{},true)
.then(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(userType)
}, 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)
})
},
//进入个人页 退押金之类
toMy() {
wx.navigateTo({
url: '/pages/my/my',
})
},
//获取站点列表
getPointLists() {
let curPage =1
let that = this
userLocation()
.then(res => {
let { longitude: lng, latitude: lat } = res
that.setData({
longitude: lng,
latitude: lat,
})
rapi.get('userOrder/getNodeList', {
lng,
lat,
curPage
})
.then(({ items}) => {
let markers=[]
items.map(item => {
let oMarker = { iconPath: '/static/image/pointloc.png', width:25, height:25}
oMarker.latitude = item.nodeLat
oMarker.longitude = item.nodeLng
markers.push(oMarker)
return item
})
console.log(markers)
that.setData({
markers,
})
wx.createMapContext('myMap').includePoints({
padding: [10],
points: markers
})
})
.catch(err => {
console.log(err)
})
})
.catch(err => {
alertTip(err)
})
},
toServerPoint(){
wx.navigateTo({
url: '/pages/server_point/server_point',
})
}
})
\ No newline at end of file
{
"navigationBarTitleText": "车辆租赁"
}
\ No newline at end of file
<view class='con' wx:if='{{status=="normal"}}'>
<!--扫描 -->
<map id="myMap" catchtap='toServerPoint' wx:if='{{rentType}}' class='points' show-location longitude='{{longitude}}' latitude='{{latitude}}' markers='{{markers}}'></map>
<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>
<!-- <map id="myMap" catchtap='toServerPoint' wx:if='{{rentType}}' class='points' show-location longitude='{{longitude}}' latitude='{{latitude}}' markers='{{markers}}'></map> -->
<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 class='my' catchtap='toMy'>我的</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%;
width: 100%;
}
.con.tip{
background-color: #f8f8f8;
width: 100%;
}
.img-scan {
margin-top: 106rpx;
width: 210rpx;
height: 210rpx;
}
.my{
position: absolute;
bottom: 40rpx;
left: 0;
padding: 30rpx 50rpx 30rpx 30rpx;
color: #fff;
background-color: #d7193c;
border-radius: 0 50rpx 50rpx 0;
}
.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;
}
.points{
width: 100%;
height: 400rpx
}
\ No newline at end of file
const { api, alertTip } = require('../../lib/util.js')
var t = {}
Page({
data: {
inputPhone: null,
inputMeg: null,
inputPassword: null,
receiveMsg:'',
inputPasswordAgain: null,
msgLoading: false,
setTimeSec: 60,
limitSec: 60
},
onLoad: function (query) {
},
onShow: function () {
},
numInput(e) {
this.setData({
[e.target.id]: e.detail.value
})
},
getMsg() {
let _this = this
if (!/^1\d{10}/.test(this.data.inputPhone)) {
alertTip('请输入正确的手机号!')
return
}
_this.timer()
//请求验证码api
api.get('user/message', { mobile: Number(this.data.inputPhone) })
.then(res => {
this.setData({
receiveMsg: res.data
})
})
.catch(err => {
alertTip('获取验证码请求失败')
clearInterval(t)
_this.setData({
msgLoading: false
})
})
},
bindPhone() {
let This = this
//绑定手机号
if (This.canBind(true)) {
if (This.data.inputMeg != This.data.receiveMsg) {
alertTip('验证码不正确,修改失败!')
return
}
api.post('user/editPassBymobile', {
mobile: Number(This.data.inputPhone),
newPass: This.data.inputPassword
})
.then(res => {
console.log('成功', res)
wx.showLoading({
title: '修改密码成功',
})
wx.redirectTo({
url: '/pages/welcome2/welcome2',
})
})
.catch(err => {
alertTip(err)
})
}
},
canBind(willTip) {
if (!/^1\d{10}/.test(this.data.inputPhone)) {
willTip && alertTip('请输入正确的手机号!')
return false
}
if (!/\d{4}/i.test(this.data.inputMeg)) {
willTip && alertTip('请输入4位数字的验证码!')
return false
}
if (!/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,}$/.test(this.data.inputPassword)) {
willTip && alertTip('请输入6-12位包含数字和字母的密码!')
return false
}
if (this.data.inputPasswordAgain != this.data.inputPassword) {
willTip && alertTip('两次输入的密码不一样!')
return false
}
return true
},
// 重发验证码定时器
timer: function () {
var count = this.data.setTimeSec
var that = this
that.setData({
limitSec: count,
msgLoading: true
})
clearInterval(t)
t = setInterval(function () {
if (count != 0) {
count--
that.setData({
limitSec: count
})
} else {
clearInterval(t)
that.setData({
limitSec: count,
msgLoading: false
})
}
}, 1000)
}
})
\ No newline at end of file
{
"navigationBarTitleText": "忘记密码"
}
\ No newline at end of file
<view class='con'>
<view class='form-box'>
<view class='phone list'>
<text class='form-tip'>手机号码</text>
<input type='number' id='inputPhone' placeholder='填写手机号码' maxlength='11' bindinput='numInput'></input>
<text class='msg' wx:if='{{!msgLoading}}' bindtap='getMsg'>获取验证码</text>
<text class='msg des' wx:else>{{limitSec}}s</text>
</view>
<view class='phone-sure list'>
<text class='form-tip'>验证码</text>
<input type='number' id='inputMeg' placeholder='输入验证码' maxlength='8' bindinput='numInput'></input>
</view>
<view class='phone-sure list'>
<text class='form-tip'>新密码</text>
<input type='text' id='inputPassword' password placeholder='密码需是6-12字母和数字的组合' 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='bindPhone'>确认</button>
</view>
\ No newline at end of file
@import '../register2/register2.wxss'
\ No newline at end of file
const { api,payApi,alertTip ,imgName } = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
imgViplogo: imgName('viplogo.png'),
imgHeadshot: imgName('logo.png'),
imgMore: imgName('more.png'),
imgTip: imgName('tip.png'),
point1:'',
point2: '',
realName:null,
networkingStopTime: '0000-00-00',
networkingHasDay:null,
amount:0,//押金金额
person:1,//个租
vehicleName:null,
userItemList: [{
msg: 0,
name: '我的行程',
icon: imgName('journey.png'),
page: '/pages/user_travel_path/user_travel_path'
}, {
msg: 0,
name: '我的消息',
icon: imgName('message.png'),
page: '/pages/user_message/user_message'
}
// ,{
// msg: 0,
// name: '安防设置',
// icon: imgName('setting.png'),
// page: '/pages/user_setting/user_setting'
// }
, {
msg: 0,
name: '售后服务',
icon: imgName('server.png'),
page: '/pages/server_point/server_point'
}, {
msg: 0,
name: '其他',
icon: imgName('setting2.png'),
page: '/pages/settting/setting'
}]
},
onShow: function () {
let user = wx.getStorageSync('user').userMapp
let device = wx.getStorageSync('device')//可能不存在啊
if (!user) {
wx.redirectTo({
url: '/pages/welcome2/welcome2',
})
return
}
//获取站点
if(!this.data.point1){
api.get('user/getByUserId', { userId: user.id })
.then(({ data }) => {
this.setData({
point1: data.companyName,
point2: data.siteName,
})
})
.catch(err => {
console.error(err)
})
}
//个租
if (this.data.person==1){
this.updateDeposit()
}
this.setData({
realName:user.realName,
amount: user.depositAmount,//押金金额
person: user.userType,//个租
device,
})
//消息数量
// this.getFirstPage()
},
wxDepositRefund() {
// payApi.post('pay/wxRefund', {
// outRefundNo: '20180524194005033000337',
// outTradeNo: '20180524194005033000337'
// })
// .then(res => {
// alertTip('退款成功')
// console.log('退款', res)
// })
// .catch(err => {
// alertTip(err.err_code_des)
// console.error('退款', err)
// })
let that=this
payApi.post('pay/wxDepositRefund')
.then(res => {
alertTip('押金退款请求成功',()=>{
// that.updateDeposit()
wx.reLaunch({
url: '/pages/welcome2/welcome2',
})
})
})
.catch(err => {
alertTip(err.err_code_des || err.return_msg)
console.error('退款', err)
})
},
toDetailPage(e) {
let url = e.currentTarget.id
if(url==='') return
wx.navigateTo({
url: e.currentTarget.id
})
},
loginOut(){
api.get('api/user/logout.json')
.then(res => {
wx.reLaunch({ url: '/pages/welcome2/welcome2' })
})
.catch(err => {
alertTip(err)
})
},
//更新押金信息
updateDeposit(){
let that=this
//个人用户开始租车
let user = wx.getStorageSync('user')
// user.userMapp.depositAmount = 0
// wx.setStorageSync('user', user)
// this.setData({
// amount: 0
// })
setTimeout(()=>{
api.get('user/getByUserId', { userId: user.userMapp.id })
.then(res => {
user.userMapp.depositAmount = res.data.depositAmount
wx.setStorageSync('user', user)
that.setData({
amount: res.data.depositAmount
})
})
.catch(err => {
console.error(err)
})
},2500)
}
})
\ No newline at end of file
{"navigationBarTitleText": "个人中心"}
\ No newline at end of file
<view class='con'>
<view class='header-top'>
<view class='i header'>
<open-data class='image' type="userAvatarUrl"></open-data>
<!-- <image src='{{imgHeadshot}}'></image> -->
<text>{{realName}}</text>
</view>
<view class='top-des' wx:if='{{!person}}'>
<text>租赁商:{{point1}}</text>
<text>站点:{{point2}}</text>
</view>
</view>
<view class='i vip' hidden='{{!person}}'>
<view class='layout'>
<view class='left'>
押金金额:{{amount}}
</view>
<view class='right' catchtap='wxDepositRefund' wx:if='{{amount}}'>
<view>退押金</view>
</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 class='tab' catchtap='loginOut'>
切换账号
</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;
}
.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;
}
\ No newline at end of file
Component({
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
navList: {
type: Array,
value: [{
id: '1',
title: '标题',
icon: ''
}, {
id: '2',
title: '标题',
icon: ''
}],
}
},
data: {
// 这里是一些组件内部数据
activeId:null
},
attached(){
this.setData({
activeId:this.data.navList[0].id
})
},
methods: {
// 这里是一个自定义方法
_selectItem: function (e) {
if (this.data.activeId === e.target.dataset.act){
return
}
this.setData({
activeId:e.target.dataset.act
})
this.triggerEvent('change', { id: e.target.dataset.act})
}
}
})
\ No newline at end of file
{
"component": true
}
\ No newline at end of file
<!--pages/nav_bar/nav_bar.wxml-->
<view class='nav-box'>
<block wx:for="{{navList}}" wx:key="*this">
<view class='nav-item' bindtap='_selectItem' id='{{item.id}}' data-act='{{item.id}}'>
<image class='img-icon' src='{{item.icon}}' data-act='{{item.id}}'></image>
<text class='nav-title {{item.id==activeId?"active":""}}' data-act='{{item.id}}'>{{item.title}}</text>
</view>
</block>
</view>
/* pages/nav_bar/nav_bar.wxss */
.nav-box{
height: 10%;
display: flex;
justify-content: space-around;
text-align: center;
align-items: stretch;
border-top:2rpx solid #7A7A7A;
position:fixed;
bottom: 0;
left:0;
width: 100%;
background-color: #FAFAFA;
}
.img-icon{
width: 40rpx;
height: 40rpx;
padding: 10rpx 0;
}
.nav-item{
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
}
.nav-title{
font-size: 16px;
color: #353535;
}
.nav-title.active{
color: #1fb922;
}
\ No newline at end of file
const { api, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
polyline:[],
markers:[],
longitude: 120.126593,
latitude: 30.342009,
tripId:null
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (query) {
this.setData({
tripId:query.id
})
this.getTrack()
},
getTrack(){
let that = this
api.get('device/getTrack.json',{
id: this.data.tripId
})
.then(({items})=>{
let polyline = [{ points: [], color: '#d7193cFF', arrowLine: true, width: 3}]
items.map(item=>{
polyline[0].points.push({ latitude: item.lat, longitude: item.lng })
return item
})
this.setData({
polyline,
longitude: items[0].lng,
latitude: items[0].lat,
})
})
.catch(err=>{
console.log(err)
})
}
})
\ No newline at end of file
{"enablePullDownRefresh": true}
\ No newline at end of file
<map longitude='{{longitude}}' latitude='{{latitude}}' polyline='{{polyline}}'></map>
page{
height: 100%
}
map{
height: 100%;
width:100%
}
\ No newline at end of file
// pages/pay/pay.js
const { api, imgName, wxLogin, payApi, alertTip } = require('../../lib/util.js')
Page({
data: {
price:'--',
payType: 'rent',//deposit rent
success:true,//
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
let payType=options.type
this.setData({
payType,
})
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
onPullDownRefresh: function () {
if(this.data.success){
wx.stopPullDownRefresh()
}else{
//重新请求
}
},
payMoney(){
//租金
if (this.data.payType=='rent'){
this.payRent()
}else{
this.payDeposit()
}
},
payDeposit() {
// 原需要 订单号
// wxLogin()
// .then(code=>{
// payApi.get('pay/getOpenId.json',{
// code
// })
// .then(res=>{
// console.log('openid',res)
// let openId = res.openId
// wx.setStorageSync('openid', openId)
// payApi.post('pay/miniAppUnifiedOrder',{
// openId,
// outTradeNo: '20180524194005033000337'
// })
// .then(res => {
// console.log('miniAppUnifiedOrder', res)
// let { timeStamp, nonce_str: nonceStr, signType, prepay_id,paySign } = res
// //统一下单了
// wx.requestPayment({
// timeStamp,
// nonceStr,
// 'package': prepay_id,
// 'signType': 'MD5',
// paySign,
// 'success': function (res) {
// console.log(res)
// },
// 'fail': function (res) {
// console.error(res)
// }
// })
// })
// .catch(err => {
// alertTip(err.err_code_des)
// console.error(err)
// })
// })
// .catch(err=>{
// alertTip(err.remark)
// console.error('openid', err)
// })
// })
// .catch(err=>{
// console.log(err)
// })
wxLogin()
.then(code=>{
payApi.get('pay/getOpenId.json',{
code
})
.then(res=>{
console.log('openid',res)
let openId = res.openId
wx.setStorageSync('openid', openId)
payApi.post('pay/miniAppDepositOrder',{
openId
})
.then(res => {
console.log('miniAppUnifiedOrder', res)
let { timeStamp, nonce_str: nonceStr, signType, prepay_id,paySign } = res
//统一下单了
wx.requestPayment({
timeStamp,
nonceStr,
'package': prepay_id,
'signType': 'MD5',
paySign,
'success': function (res) {
alertTip('押金支付成功,开始租车',function(){
wx.navigateBack()
})
},
'fail': function (res) {
console.error(res)
}
})
})
.catch(err => {
alertTip(err.err_code_des || err.return_msg)
console.error(err)
})
})
.catch(err=>{
alertTip(err.remark)
console.error('openid', err)
})
})
.catch(err=>{
console.error(err)
})
},
payRent() {
// 租金
wxLogin()
.then(code=>{
payApi.get('pay/getOpenId.json',{
code
})
.then(res=>{
let openId = res.openId
wx.setStorageSync('openid', openId)
payApi.post('pay/miniAppUnifiedOrder',{
openId,
outTradeNo: '20180524194005033000337'
})
.then(res => {
console.log('miniAppUnifiedOrder', res)
let { timeStamp, nonce_str: nonceStr, signType, prepay_id,paySign } = res
//统一下单了
wx.requestPayment({
timeStamp,
nonceStr,
'package': prepay_id,
'signType': 'MD5',
paySign,
'success': function (res) {
alertTip('租金支付成功!', function () {
wx.navigateBack()
})
console.log(res)
},
'fail': function (res) {
console.error(res)
}
})
})
.catch(err => {
alertTip(err.err_code_des)
console.error(err)
})
})
.catch(err=>{
alertTip(err.remark)
console.error('openid', err)
})
})
.catch(err=>{
console.log(err)
})
}
})
\ No newline at end of file
{
"navigationBarTitleText": "押金支付",
"enablePullDownRefresh": true
}
\ No newline at end of file
<view class='con'>
<view wx:if='{{success}}'>
<view class='item'>
<text>支付类型:</text>
<text class='tip'>{{payType=='deposit'?"押金":"租金"}}</text>
</view>
<view wx:if='{{payType=="deposit"}}'>
<view class='item'>
<text>支付金额:</text>
<text class='tip'>¥{{price}}元</text>
</view>
<view class='item' wx:if='{{payType=="deposit"}}'>
<text>提示:</text>
<text class='tip2 tip'>押金可以在租车结束后退还。</text>
</view>
</view>
<!--租金 -->
<view wx:else>
<view class='item' wx:if='{{payType=="deposit"}}'>
<text>订单:</text>
<text class='tip2 tip'>押金可以在租车结束后退还。</text>
</view>
<view class='item'>
<text>支付金额:</text>
<text class='tip'>¥{{price}}元</text>
</view>
</view>
<!-- <button open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">授权登录</button> -->
<view class='btn'>
<button catchtap='payMoney'>付款</button>
<!-- <button catchtap='returnMoney'>退款</button> -->
</view>
</view>
<view wx:else class='tip'>
网络开小差了,请下拉刷新一下。
</view>
</view>
\ No newline at end of file
/* pages/pay/pay.wxss */
.page{
height: 100%;
flex-direction: column;
}
.con{
padding: 0 40rpx;
}
.tip{
display: flex;
justify-content: center;
align-items: center;
font-size: 40rpx;
color: #d7193c;
}
.item{
display: flex;
align-content: stretch;
height: 80rpx;
align-items: center;
border-bottom: 2rpx solid #eee;
}
.item text:nth-of-type(1){
flex: 0 0 180rpx;
}
.btn{
position: absolute;
bottom: 50rpx;
width: 90%;
}
button{
background-color: #d7193c;
}
.item-body{
display: flex;
height: 100%;
flex-direction: column;
justify-content: space-between
}
.tip2{
font-size: 32rpx;
}
\ No newline at end of file
// pages/point_detail/point_detail.js
const { api, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
pointId: null,
look: false,//false预约服务 true导航查看个租使用
// time: '0:0',//运营时间
locMap: {
latitude: 30.334546,
longitude: 120.121121,
markers: []
},
point:{},//站点
imgToloc: imgName('toloc.png'),
imgLoc: imgName('pointloc.png'),
imgToPoint: imgName('timeline_location.png'),
imgPhone: imgName('security_settings_telephone_active.png'),
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.setData({
look: options.look ? true : false
})
let point=wx.getStorageSync('point')
//获取站点信息
this.data.locMap.longitude=point.nodeLng
this.data.locMap.latitude = point.nodeLat
let pointMaker={
id: point.id,
latitude: point.nodeLat,
longitude: point.nodeLng,
iconPath:'/static/image/pointloc.png',
width:30,
height: 30
}
this.data.locMap.markers.push(pointMaker)
this.setData({
point,
locMap: this.data.locMap
})
},
onUnload: function () {
},
showMyLoc() {
if (!this.mapCtx) {
this.mapCtx = wx.createMapContext('carMap')
}
this.mapCtx.moveToLocation()
},
//站点
toPoint() {
let that = this
wx.openLocation({
latitude: Number(that.data.locMap.latitude),
longitude: Number(that.data.locMap.longitude),
scale: 28
})
},
//拨打电话
callPointPhone(e) {
wx.makePhoneCall({
phoneNumber: e.currentTarget.id
})
},
//需要服务
needServer(){
let hasCar=wx.getStorageSync('user').userMapp.isUseVehicle
if(hasCar){
wx.navigateTo({
url: `/pages/server/server?pointId=${this.data.pointId}`,
})
}else{
alertTip('你当前并没有使用车辆')
}
}
})
\ No newline at end of file
{
"usingComponents": {
"star-score": "/components/star/star"
}
}
\ No newline at end of file
<!--pages/point_detail/point_detail.wxml-->
<view class='con'>
<map id='carMap' scale='13' markers='{{locMap.markers}}' show-location bindmarkertap='markersTap' longitude='{{locMap.longitude}}' latitude='{{locMap.latitude}}'>
<cover-view class='map-controltap'>
<cover-image src='{{imgToPoint}}' catchtap='toPoint'></cover-image>
<cover-image src='{{imgToloc}}' catchtap='showMyLoc'></cover-image>
</cover-view>
</map>
<view class='map-des'>
<view class='point-box'>
<view class='point-left' id='{{point.id}}' catchtap='toPointDetail'>
<text>{{point.nodeName}}</text>
<!-- <star-score score='2.6'></star-score> -->
<view>
<image src='{{imgLoc}}'></image>
<text>{{point.city}}市{{point.area}}区{{point.nodeAddress}}</text>
</view>
</view>
<view class='point-right'>
<text class='tip' id='{{point.id}}' catchtap='toPointDetail'>{{point.distance}} km</text>
<view id='{{point.servicePhone}}' catchtap='callPointPhone'>
<image src='{{imgPhone}}'></image>
<text>拨打电话</text>
</view>
</view>
</view>
<!-- <view class='time'>运营时间:{{time}}</view> -->
<view class='server' hidden='{{look}}' catchtap='needServer'>预约服务</view>
</view>
</view>
\ No newline at end of file
/* pages/point_detail/point_detail.wxss */
page{
height: 100%;
}
.con{
height: 100%;
display: flex;
flex-direction: column;
align-items: stretch;
}
map{
flex: 1 0 auto;
width: 100%;
}
.map-controltap{
display: flex;
justify-content: space-between;
padding: 0 40rpx;
width: 100%;
position: absolute;
box-sizing: border-box;
bottom: 50rpx;
}
.map-controltap cover-image{
width: 50rpx;
height: 50rpx;
}
.time{
line-height: 80rpx;
font-size: 40rpx;
text-align: center;
}
.server{
line-height: 80rpx;
background-color: #d7193c;
color: #fff;
text-align: center;
}
.tip{
color: #d7193c;
}
.point-box{
display: flex;
justify-content: space-between;
align-items: stretch;
height: 140rpx;
padding: 20rpx 30rpx;
border-bottom: 1px solid #eee;
}
.point-left,.point-right{
display: flex;
flex-direction: column;
justify-content: space-between;
}
.point-left view,.point-right view{
display: flex;
}
.point-right{
align-items: flex-end;
}
.point-right .tip{
font-size: 40rpx;
}
.point-left{
flex:0 0 500rpx;
}
.time{
}
\ 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: {
inputPhone: null,
inputMeg: null,
receiveMsg:null,
inputPassword: null,
inputPasswordAgain: null,
inputName: null,
inputId: null,
msgLoading: false,
idPhoto:'',
// mode:false,//true 'group'
agree: true,
setTimeSec: 60,
limitSec: 60,
phoneNum: null,//输入的号码
// pointIndex:0,
// pointArray: ['厂1', '厂2', '厂23'],
sex:'1',
sexs:[
{ name: '0', value: '女' },
{ name: '1', value: '男', checked: 'true' },
]
},
onLoad: function (query) {
},
onShow: function () {
},
numInput(e) {
this.setData({
[e.target.id]: e.detail.value
})
},
getMsg() {
let inputPhone = this.data.inputPhone
let _this = this
if (!/^1\d{10}/.test(inputPhone)) {
alertTip('请输入正确的手机号!')
return
}
_this.timer()
//请求验证码api
api.get('user/message', { mobile: Number(this.data.inputPhone) })
.then(res => {
this.setData({
receiveMsg:res.data
})
})
.catch(err => {
alertTip('获取验证码请求失败')
clearInterval(t)
_this.setData({
msgLoading: false
})
})
},
hascheck(e) {
console.log(this.data.agree)
this.setData({
agree: !this.data.agree
})
},
toProtocol: function () {
getProtocol(1)
.then(res => {
console.log(res)
})
.catch(err => {
console.error(err)
alertTip(err.errMsg || err)
})
},
bindPhone() {
let This = this
//绑定手机号
if (This.canBind(true)) {
//个租
api.post('user/register', {
mobile: Number(This.data.inputPhone),
password: This.data.inputPassword,
sex: This.data.sex,
mobile: This.data.inputPhone,
idNumber: This.data.inputId,
realName: This.data.inputName,
idImg: This.data.idPhoto
})
.then(res => {
wx.showModal({
title: '提示',
content: res.message,
showCancel: false,
success: function (res) {
if (res.confirm) {
wx.reLaunch({
url: '/pages/welcome2/welcome2',
})
}
}
})
})
.catch(err => {
alertTip(err)
})
}
},
canBind(willTip) {
if (!/^1\d{10}/.test(this.data.inputPhone)) {
willTip && alertTip('请输入正确的手机号!')
return false
}
if (!/\d{4}/i.test(this.data.inputMeg)) {
willTip && alertTip('请输入4位数字的验证码!')
return false
}
if (this.data.inputMeg != this.data.receiveMsg) {
willTip && alertTip('验证码不正确!')
return false
}
if (!this.data.inputName) {
willTip && alertTip('请输入姓名!')
return false
}
if (!this.data.inputId) {
willTip && alertTip('请输入身份证号!')
return false
}
if (!this.data.idPhoto) {
willTip && alertTip('请上传身份证半身照!')
return false
}
if (!/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,}$/.test(this.data.inputPassword)) {
willTip && alertTip('请输入6-12位包含数字和字母的密码!')
return false
}
if (this.data.inputPasswordAgain != this.data.inputPassword) {
willTip && alertTip('两次输入的密码不一样!')
return false
}
if (!/\d{17}/i.test(this.data.inputId)) {
willTip && alertTip('请输入正确的身份证号!')
return false
}
if (!this.data.idPhoto) {
willTip && alertTip('请上传手持身份证半身照!')
return false
}
if (!this.data.agree) {
willTip && alertTip('请同意用户使用协议!')
return false
}
return true
},
// 重发验证码定时器
timer: function () {
var count = this.data.setTimeSec
var that = this
that.setData({
limitSec: count,
msgLoading: true
})
clearInterval(t)
t = setInterval(function () {
if (count != 0) {
count--
that.setData({
limitSec: count
})
} else {
clearInterval(t)
that.setData({
limitSec: count,
msgLoading: false
})
}
}, 1000)
},
//网点模式
beGroup(e){
this.setData({
mode:e.detail.value
})
},
//站点
pointChange(e){
this.setData({
pointIndex: e.detail.value
})
},
radioChange: function (e) {
this.setData({
sex: e.detail.value
})
},
uploadIdPhoto(){
let that = this
wx.chooseImage({
count: 1, // 默认9
sizeType: ['original'], // 可以指定是原图还是压缩图,默认二者都有
success: function (res) {
// 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
let tempFilePath = res.tempFilePaths[0]
console.log(tempFilePath)
wx.showLoading({
title: '上传中。。',
})
wx.uploadFile({
url: 'https://zhizuxia.zhizukj.com/ydb/app/manage/file/upload.json',
filePath: tempFilePath,
name: 'file',
success(res){
that.setData({
idPhoto: JSON.parse(res.data).picUrl
})
console.log(that.data.idPhoto)
},
fail(err){
alertTip('上传失败')
},
complete(res) {
wx.hideLoading()
}
})
}
})
}
})
\ No newline at end of file
{
"navigationBarTitleText": "用户注册"
}
\ No newline at end of file
<view class='con'>
<view class='form-box'>
<!-- <view class='mode list agree {{mode?"":"insurance"}}'>
<switch bindchange="beGroup" color='#ffd200'/> 我是团租用户
</view> -->
<view class='phone list'>
<text class='form-tip'>手机号码</text>
<input type='number' id='inputPhone' placeholder='填写手机号码' maxlength='11' bindinput='numInput'></input>
<text class='msg' wx:if='{{!msgLoading}}' bindtap='getMsg'>获取验证码</text>
<text class='msg des' wx:else>{{limitSec}}s</text>
</view>
<view class='phone-sure list'>
<text class='form-tip'>验证码</text>
<input type='number' id='inputMeg' placeholder='输入验证码' maxlength='8' bindinput='numInput'></input>
</view>
<view class='phone-sure list'>
<text class='form-tip'>性别</text>
<radio-group class="radio-group" bindchange="radioChange">
<label class="radio" wx:for="{{sexs}}">
<radio value="{{item.name}}" checked="{{item.checked}}" color='#d7193c'/>{{item.value}}
</label>
</radio-group>
</view>
<view class='phone-sure list'>
<text class='form-tip'>真实姓名</text>
<input id='inputName' placeholder='请输入身份证上姓名' bindinput='numInput'></input>
</view>
<view class='phone-sure list'>
<text class='form-tip'>身份证</text>
<input type='idcard' id='inputId' placeholder='请输入身份证' bindinput='numInput'></input>
</view>
<view class='phone-sure list' catchtap='uploadIdPhoto'>
<text class='form-tip'>半身照</text>
<input wx:if='{{!idPhoto}}' id='idPhoto' disabled placeholder='请上传手持身份证半身照'></input>
<view wx:else>已上传(点击修改)</view>
</view>
<view class='phone-sure list'>
<text class='form-tip'>密码</text>
<input type='text' id='inputPassword' password placeholder='密码需是6-12字母和数字的组合' 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 wx:if='{{mode}}'>
<view class='phone-sure list'>
<text class='form-tip'>所属站点</text>
<picker class='point' bindchange="pointChange" value="{{pointIndex}}" range="{{pointArray}}">
<view>{{pointArray[pointIndex]}}</view>
</picker>
</view>
</view>-->
</view>
<button bindtap='bindPhone'>注册</button>
<view class='insurance agree'>
<radio checked='{{agree}}' catchtap='hascheck' color='#d7193c'></radio >
我同意智租科技
<text bindtap='toProtocol'> 《用户服务协议》</text>
</view>
</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
const config = require('../../config/index.js')
const { api, rapi, mapApi, mockApi, imgName, getUserInfo, wxLogin, alertTip, wxscan, authAgainByUser, userLocation } = require('../../lib/util.js')
// user point device
let carTimer = null
Page({
/**
* 页面的初始数据
*/
data: {
tab: '',//tab是列表
//详情页数据
username:'',//用户名
userId:'',//用户id
userPhone: '',//手机号
comment:'',
user: null,
time: '',//时间
date: '',//日期
img_arr: [], //上传图片数组
pics:'',//图片线上路径数组
imgScan: imgName('imgscan.png'),
imgClose: imgName('close.png'),
imgLogo: imgName('logo.png'),
showList:[],//我的服务列表
page: 1,//当前页面
hasMorePage: false,//更多页面
},
onShow: function () {
},
//tab切换
tabCarMenu(e) {
let id = e.target.id
if (e.target.id === this.data.tab) return
let tab = this.data.tab === '' ? 'tab' : ''
//服务列表
if (tab == 'tab' && this.data.page == 1){
//当前页是第一页 获取第一页
this.getMyOrderList(1)
}
this.setData({
tab
})
},
onLoad: function () {
let {userMapp}=wx.getStorageSync('user')
let { model } = wx.getStorageSync('device')
this.setData({
username: userMapp.realName,//用户名
userPhone: userMapp.mobile,//手机号
cartype: model,//手机号
userId: userMapp.id
})
},
onUnload() {
wx.setStorageSync('carLists', this.data.carLists)
},
carTypeChange(e) {
},
numInput(e) {
this.setData({
[e.target.id]: e.detail.value
})
},
bindDateChange: function (e) {
this.setData({
date: e.detail.value
})
},
bindTimeChange: function (e) {
this.setData({
time: e.detail.value
})
},
//提交工单
submitServer(){
let { username, userPhone, comment, date, time, userId}=this.data
let { id: nodeId } = wx.getStorageSync('point')
// let { vcuNo, frameNo, model:vehicleModel } = wx.getStorageSync('device')
// 图片
if (!comment){
alertTip('请简单描述下问题')
return false
}
if (!time||!date) {
alertTip('选择预约时间')
return false
}
Promise.all(this.uploadIdPhoto())
.then(res=>{
let pics=res.join(',')||''
let orderTime = date.replace('-', '/') + " " + time + ":00"
rapi.get('userOrder/commitOrder',{
userId,
nodeId,
username,
userPhone,
comment,
vcuNo,
frameNo,
vehicleModel,
pics,
orderTime
})
})
.catch(err=>{
console.log(err)
})
},
//选择图片
upimg: function () {
var that = this;
let hasImgLength = this.data.img_arr.length
if (hasImgLength < 3) {
wx.chooseImage({
count: 3 - hasImgLength, // 默认9
sizeType: ['original', 'compressed'],
success: function (res) {
let img_arr= that.data.img_arr.concat(res.tempFilePaths)
that.setData({
img_arr
})
console.log(img_arr)
}
})
} else {
alertTip('最多上传三张图片')
}
},
//删除图片
deleteImg(e){
let index=Number(e.currentTarget.id)
this.data.img_arr.splice(index,1)
this.setData({
img_arr: this.data.img_arr
})
},
bindTextAreaBlur(e){
let comment=e.detail.value
this.setData({
comment
})
},
//上传图片
uploadIdPhoto() {
let that=this
if (that.data.img_arr.length==0){
return [Promise.resolve()]
}else{
wx.showLoading({
title: '上传图片中',
mask: true,
})
return that.data.img_arr.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()
}
})
})
})
}
},
//获取服务工单
getMyOrderList(page){
let curPage = page || this.data.page
let that = this
// rapi.get('userOrder/myOrderList',{
// userId: this.data.userId,
// curPage,
// }).then(res=>{
// console.log(res)
// let listArrays = res.items.map(item => { item.pics = item.pics.split(',')[0]; return item })
// //首页
// if (curPage == 1) {
// this.setData({
// showList: listArrays,
// page: curPage + 1,
// hasMorePage: res.model.haveMore
// })
// } else {
// let newArrays = that.data.pointLists.concat(listArrays)
// this.setData({
// showList: newPoints,
// page: curPage + 1,
// hasMorePage: res.model.haveMore
// })
// }
// }).catch(err=>{
// console.log(err)
// })
mockApi.get('http://result.eolinker.com/t2TvftRd7db394452f6fdee0541724f3fdde187fc6c117d?uri=repair/app/userOrder/myOrderList',{
userId: this.data.userId,
curPage,
}).then(res=>{
console.log(res)
let listArrays = res.items.map(item => {
item.pics = item.pics.split(',')[0]
let stateArray = ['已下单', '已接单', '已完成', '已完成','已取消']
item.state =stateArray[item.state]
item.orderTime = new Date(item.orderTime).toLocaleString()
return item
})
//首页
if (curPage == 1) {
this.setData({
showList: listArrays,
page: curPage + 1,
hasMorePage: res.model.haveMore
})
} else {
let newArrays = that.data.showList.concat(listArrays)
this.setData({
showList: newArrays,
page: curPage + 1,
hasMorePage: res.model.haveMore
})
}
}).catch(err=>{
console.log(err)
})
},
//获取服务详情
toServerDetail(e){
let serverId=e.currentTarget.id
wx.navigateTo({
url: `/pages/server_detail/server_detail?id=${serverId}`,
})
}
})
\ No newline at end of file
{
"navigationBarTitleText": "预约服务"
}
\ No newline at end of file
<!--pages/user_index/user_index.wxml-->
<view class='con'>
<view class='tab-header'>
<view class='main' catchtap='tabCarMenu'>
<view class='item {{tab===""? "active":""}}'>提交工单</view>
<view class='item {{tab==="tab"? "active":""}}' id='tab'>我的服务</view>
</view>
</view>
<view class='body-box {{tab}}'>
<view class='tab-map'>
<view>
<view class='phone list'>
<text>报修人:</text>
<input class='input-text' id='username' value='{{username}}' placeholder='请输入报修人姓名' bindinput='numInput'></input>
</view>
<view class='phone list'>
<text>联系电话:</text>
<input class='input-text' id='userPhone' value='{{userPhone}}' placeholder='请输入联系电话' bindinput='numInput'></input>
</view>
<view class='problem list'>
<text>问题描述:</text>
<textarea bindblur="bindTextAreaBlur" placeholder="请输入问题原因" />
</view>
<view class='phone list'>
<text>预约时间:</text>
<picker class='input-text point' mode="date" value="{{date}}" bindchange="bindDateChange">
<view>{{date?date:'选择日期'}}</view>
</picker>
<picker class='input-text point' mode="time" value="{{time}}" start="08:00" end="18:00" bindchange="bindTimeChange">
<view>{{time?time:'选择时间'}}</view>
</picker>
</view>
<view class='phone list'>
<text>上传图片:</text>
<view class='input-text' bindinput='numInput'>
<view class="big-logos">
<block wx:for="{{img_arr}}" 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>
</view>
</view>
<view class='option'>
<button catchtap='submitServer'>预约</button>
</view>
</view>
<view class='tab-detail'>
<scroll-view scroll-y class='device-list'>
<view wx:if='{{showList.length!=0}}'>
<view class='list-item' wx:for='{{showList}}' wx:key='{{item.id}}' id='{{item.id}}' catchtap='toServerDetail'>
<image src='{{item.pics||imgLogo}}'></image>
<view class='item-des item-text'>
<text>{{item.frameNo}}</text>
<text class='low-text'>{{item.vehicleModel}}</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='getMyOrderList'>加载更多</button>
</view>
</view>
<view wx:else class='no-list'>
<text class='tip2'>不存在任何工单</text>
</view>
</scroll-view>
</view>
</view>
</view>
\ No newline at end of file
page {
height: 100%;
overflow: hidden;
}
page .con {
height: 100%;
overflow: hidden;
position: relative;
}
page .con .tab-header {
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: stretch;
padding: 28rpx 28rpx 0 28rpx;
height: 103rpx;
color: #686868;
border-bottom: 2rpx solid #e9e9e9;
}
page .con .tab-header .person {
height: 100%;
width: 42rpx;
}
page .con .tab-header .main {
height: 100%;
flex: 1;
display: flex;
justify-content: space-between;
position: relative;
transform: translateY(2rpx);
}
page .con .tab-header .main .item {
font-size: 32rpx;
text-align: center;
flex: 1 0 auto;
border-bottom: 6rpx solid transparent;
}
page .con .tab-header .item.active {
color: #d7193c;
border-bottom-color: #d7193c;
}
page .con .body-box {
height: 1111rpx;
width: 200%;
box-sizing: border-box;
transform: translateX(0);
transition: all 0.2s;
display: flex;
}
page .con .body-box .tab-map {
width: 50%;
display: flex;
flex-direction: column;
/* justify-content: space-between; */
}
page .con .body-box .tab-detail {
width: 50%;
height: 100%;
box-sizing: border-box;
/* padding: 0 40rpx 50rpx; */
}
page .con .tab {
transform: translateX(-50%);
}
.phone {
width: 100%;
}
.list {
height: 110rpx;
display: flex;
align-items: center;
padding: 0 30rpx;
border-bottom: 2rpx solid #f8f8f8;
}
.list image{
width: 50rpx;
height: 50rpx;
}
.list text{
flex-basis: 160rpx;
flex-shrink: 0;
}
.list .input-text{
flex: 1;
}
.insurance{
color: #d7193c;
}
.option{
display: flex;
margin-top: 50rpx;
}
.option button{
background-color: #d7193c;
font-size: 32rpx;
flex-basis:500rpx;
color: #fff;
}
.list-title,.list-tr{
display: flex;
padding: 20rpx 30rpx;
width: 1310rpx;
border-bottom: 2px solid #f8f8f8;
align-items: center;
}
.list-title text,.list-tr .list-td{
flex:0 0 250rpx;
text-align: center;
word-break: break-all;
}
.list-tr{
border-bottom: 1px solid #f8f8f8;
}
.option2{
display: flex;
flex-direction: column;
}
.option2 text{
padding: 10rpx 20rpx;
background-color: #d7193c;
border-radius:10rpx;
}
.option2 text:nth-of-type(1){
margin-bottom: 20rpx;
}
.submit-sys{
position: fixed;
background-color: rgba(214, 25, 59, 0.7);
left: 50%;
bottom: 100rpx;
padding: 30rpx 50rpx 30rpx 10rpx;
border-top-right-radius: 46rpx;
border-bottom-right-radius: 46rpx;
}
.device-list{
width: 100%;
height: 100%;
overflow: scroll;
}
.fresh-car{
padding: 10rpx 20rpx;
background-color: #d7193c;
border-radius:10rpx;
text-align: center;
color: #fff;
}
button,.option2,.submit-sys{
color: #fff;
}
.big-logos{
display: flex;
}
.big-logos image{
width: 100rpx;
height: 100rpx;
margin-right:20rpx;
}
.logoinfo{
position: relative;
}
.big-logos image.close{
position: absolute;
top: 0;
right: 0;
width:50rpx;
height: 50rpx;
}
.problem textarea{
height: 100rpx;
}
.problem text{
align-self: flex-start;
}
.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;
}
.item-state{
align-items: flex-end;
flex: 0 0 300rpx;
flex-wrap: wrap;
text-align: right;
white-space: pre-wrap;
}
.low-text{
color: #cccccc;
}
.tip2{
color: #d7193c;
}
.no-list{
padding: 50rpx;
text-align: center;
}
.btn{
padding: 30rpx;
}
.btn button{
background-color: #d7193c;
}
\ No newline at end of file
// pages/server_detail/server_detail.js.
const { api, rapi, mapApi, mockApi, imgName, alertTip } = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
imgLogo: imgName('logo.png'),
order:{},
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
let id = options.id
console.log(id)
this.getMyOrderDetail(id)
},
onShow: function () {
},
getMyOrderDetail(id){
rapi.get('userOrder/myOrderDetail', {
id
}).then(res => {
let order = res.data
let stateArray = ['已下单', '已接单', '已完成', '已完成', '已取消']
order.state = stateArray[order.state]
order.pics = order.pics.split(',')
order.orderTime = new Date(order.orderTime).toLocaleString() || ''
order.receiveTime = new Date(order.receiveTime).toLocaleString() || ''
order.completeTime = new Date(order.completeTime).toLocaleString() || ''
this.setData({
order: res.data
})
}).catch(err => {
console.log(err)
})
},
// 预览问题图片
lookPic(e) {
let src = e.currentTarget.dataset.src;//获取data-src
let imgList = e.currentTarget.dataset.list;//获取data-list
//图片预览
wx.previewImage({
current: src, // 当前显示图片的http链接
urls: imgList // 需要预览的图片http链接列表
})
},
//取消订单
cancleOrder(){
rapi.get('userOrder/cancleOrder', {
userId: wx.getStorageSync('user').userMapp.id,
id:this.data.order.id
}).then(res => {
alertTip(res)
this.getMyOrderDetail(this.data.order.id)
}).catch(err => {
alertTip(err)
})
}
})
\ No newline at end of file
{}
\ No newline at end of file
<view class='con'>
<view class='item'>
<view class='item-title'>订单编号:</view>
<view class='item-body'>{{order.orderNo}}</view>
</view>
<view class='item'>
<view class='item-title'>订单状态:</view>
<view class='item-body tip'>{{order.state}}</view>
</view>
<view class='item'>
<view class='item-title'>服务站点:</view>
<view class='item-body'>{{order.nodeName}}</view>
</view>
<view class='item'>
<view class='item-title'>车型名称:</view>
<view class='item-body'>{{order.vehicleModel}}</view>
</view>
<view class='item'>
<view class='item-title'>车架号:</view>
<view class='item-body'>{{order.frameNo}}</view>
</view>
<view class='item'>
<view class='item-title'>中控号:</view>
<view class='item-body'>{{order.vcuNo}}</view>
</view>
<view class='item'>
<view class='item-title'>保修人:</view>
<view class='item-body'>{{order.userName}}</view>
</view>
<view class='item'>
<view class='item-title'>手机号:</view>
<view class='item-body'>{{order.userPhone}}</view>
</view>
<view class='item'>
<view class='item-title'>预约时间:</view>
<view class='item-body'>{{order.orderTime}}</view>
</view>
<view class='item' wx:if='{{order.state=="已完成"||order.state=="已接单"}}'>
<view class='item-title'>接单时间:</view>
<view class='item-body'>{{order.receiveTime}}</view>
</view>
<view class='item' wx:if='{{order.state=="已完成"}}'>
<view class='item-title'>完成时间:</view>
<view class='item-body'>{{order.completeTime}}</view>
</view>
<view class='item'>
<view class='item-title'>问题描述:</view>
<view class='item-body'>{{order.comment}}</view>
</view>
<view class='item'>
<view class='item-title'>服务描述:</view>
<view class='item-body'>{{order.repairComment||"没有描述"}}</view>
</view>
<view class='item'>
<view class='item-title'>图片:</view>
<view class='item-body img'>
<image wx:for='{{order.pics}}' data-src="{{item}}" data-list="{{order.pics}}" srcwx:key='{{item}}' src='{{item}}' catchtap='lookPic'></image>
</view>
</view>
<view class='item' wx:if='{{order.state=="已完成"}}'>
<view class='item-title'>收费:</view>
<view class='item-body'>
<view>总工时:{{order.manHoursFee}}小时</view>
<view>总费用:<text class='tip'>¥{{order.price}}</text>元</view>
</view>
</view>
<view class='item' wx:if='{{order.state=="已完成"}}'>
<view class='item-title'>计价细目:</view>
<view class='item-body'>
<view class='item' wx:for='{{order.itemList}}' wx:key='{{item.id}}'>
<view class='min-title'>{{item.itemName}}</view>
<view class='item-body'>
<view>工时:¥{{item.manHours}}小时</view>
<view>小计:<text class='tip'>¥{{item.materialFee}}</text>元</view>
</view>
</view>
</view>
</view>
<view class='btn' wx:if='{{order.state!="已完成"}}'>
<button catchtap='cancleOrder'>取消工单</button>
</view>
</view>
\ No newline at end of file
/* pages/server_detail/server_detail.wxss */
.con{
overflow: hidden;
}
.btn{
padding: 30rpx;
}
.btn button{
background-color: #d7193c;
}
.item{
padding: 30rpx;
display: flex;
border-bottom: 1px solid #eee;
}
.item-title{
flex: 0 0 150rpx;
text-align: right
}
.item-body{
flex: 0 0 550rpx;
flex-wrap: wrap;
padding-left: 40rpx;
}
.img image{
width: 60px;
height: 60px;
}
.tip{
color: #d7193c;
}
.min-title{
flex: 0 0 180rpx;
}
\ No newline at end of file
// pages/server_point/server_point.js
const { api, rapi,imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
first:true,
imgLoc: imgName('pointloc.png'),
imgPhone: imgName('security_settings_telephone_active.png'),
page: 1,//当前页面
hasMorePage: false,//更多页面
pointLists:[]//站点列表
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.getPointLists(1)
},
//获取站点列表
getPointLists(page){
let curPage = page || this.data.page
let that=this
userLocation()
.then(res=>{
let { longitude:lng, latitude:lat}=res
rapi.get('userOrder/getNodeList', {
lng,
lat,
curPage
})
.then(res => {
let listArrays = res.items.map(item => { item.distance=item.distance.toFixed(1); return item})
//首页
if (curPage==1){
this.setData({
pointLists:listArrays,
page: curPage + 1,
hasMorePage:res.model.haveMore
})
}else{
let newPoints = that.data.pointLists.concat(listArrays)
this.setData({
pointLists: newPoints,
page: curPage+1,
hasMorePage: res.model.haveMore
})
}
})
.catch(err => {
console.log(err)
})
})
.catch(err=>{
alertTip('你拒绝了地理定位,请打开后重试')
wx.navigateBack()
})
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
onReachBottom: function () {
console.log('到底了')
},
//分数改变
scoreChange(e){
console.log(e.detail)
},
//拨打电话
callPointPhone(e){
wx.makePhoneCall({
phoneNumber: e.currentTarget.id
})
},
//显示站点详细信息
toPointDetail(e){
let pointId=e.currentTarget.id
let index=e.currentTarget.dataset.index
wx.setStorageSync('point', this.data.pointLists[index])
//站点详情&look=false
wx.navigateTo({
url: `/pages/point_detail/point_detail`,
})
}
})
\ No newline at end of file
{
"navigationBarTitleText": "售后站点",
"usingComponents": {
"star-score": "/components/star/star"
}
}
\ No newline at end of file
<view class='con'>
<scroll-view class='item-body' scroll-y>
<view class='point-item' wx:for='{{pointLists}}' wx:key="{{item.id}}">
<view class='tip' wx:if='{{index==0}}'>距你最近的服务商:</view>
<view class='point-box'>
<view class='point-left' id='{{item.id}}' data-index='{{index}}' catchtap='toPointDetail'>
<text>{{item.nodeName}}</text>
<!-- <star-score score='2.6'></star-score> -->
<view>
<image src='{{imgLoc}}'></image>
<text>{{item.city}}市{{item.area}}区{{item.nodeAddress}}</text>
</view>
</view>
<view class='point-right'>
<text class='tip' id='{{item.id}}' data-index='{{index}}' catchtap='toPointDetail'>{{item.distance}} km</text>
<view id='{{item.servicePhone}}' catchtap='callPointPhone'>
<image src='{{imgPhone}}'></image>
<text>拨打电话</text>
</view>
</view>
</view>
</view>
<view class='btn' wx:if='{{hasMorePage}}'>
<button catchtap='getPointLists'>加载更多</button>
</view>
</scroll-view>
</view>
\ No newline at end of file
/* pages/server_point/server_point.wxss */
page{
font-size: 28rpx;
color: #000;
height: 100%;
}
.con{
height: 100%;
}
.item-body{
height: 100%;
overflow: hidden;
}
.tip{
padding: 20rpx 0;
}
.tip{
color: #d7193c;
}
.point-item{
padding: 20rpx;
border-bottom: 1px solid #eee;
}
.point-box{
display: flex;
justify-content: space-between;
align-items: stretch;
height: 130rpx;
}
.point-left,.point-right{
display: flex;
flex-direction: column;
justify-content: space-between;
}
.point-left view,.point-right view{
display: flex;
}
.point-right{
align-items: flex-end;
}
.point-right .tip{
font-size: 40rpx;
}
.point-left{
flex:0 0 500rpx;
}
.btn{
padding: 30rpx;
}
.btn button{
background-color: #d7193c;
}
\ No newline at end of file
const { api, alertTip, imgName, getProtocol } = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
imgMore: imgName('more.png'),
protocols: ['用车协议', '押金协议', '租车协议', '用户服务协议', '保险协议','智租协议'],
others: ['官网', '微信公众号', '微信公众号', '微信公众号']
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
readProtocol(e){
let id=e.currentTarget.id
console.log(id)
getProtocol(id)
.then(res=>{
console.log(res)
})
.catch(err=>{
console.error(err)
alertTip(err.errMsg||err)
})
},
loginOut(){
wx.redirectTo({
url: '/pages/welcome2/welcome2',
})
},
//详情页面
toDetail(){
let id = e.currentTarget.id
}
})
\ No newline at end of file
{}
\ No newline at end of file
<view class='con'>
<scroll-view class='scro' scroll-y>
<view class='i nav-item'>
<view class='layout'>
<view class='left sub-title'>
用户协议
</view>
</view>
<view class='layout item' wx:for='{{protocols}}' wx:key='{{index}}' id='{{index+1}}' catchtap='readProtocol'>
<view class='left'>
{{item}}
</view>
<view class='right'>
<image src='{{imgMore}}'></image>
</view>
</view>
</view>
<view class='i nav-item'>
<view class='layout'>
<view class='left sub-title'>
关于
</view>
</view>
<view class='layout item' wx:for='{{others}}' wx:key='{{index}}' id='{{index+1}}' catchtap='toDetail'>
<view class='left'>
{{item}}
</view>
<view class='right'>
<image src='{{imgMore}}'></image>
</view>
</view>
</view>
</scroll-view>
<view class='bom' catchtap='loginOut'>
退出登录
</view>
</view>
\ No newline at end of file
@import '../my/my.wxss'
.con{
height: 100%;
display: flex;
flex-direction: column;
align-items: stretch;
}
.bom{
background-color:#d7193c;
color:#fff;
line-height:110rpx;
text-align:center;
}
.scro{
height: 500rpx;
flex: 1 0 110rpx;
}
.tab{
flex: 0 0 110rpx,
}
.nav-item{
margin-top: 30rpx;
}
.sub-title{
font-size: 36rpx;
font-weight: bold;
line-height: 80rpx;
}
.item .left{
padding-left: 80rpx;
}
\ No newline at end of file
const { api, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
Page({
data: {
imgCheckOff: imgName('security_settings_unchecked.png'),
imgCheckOn: imgName('security_settings_unchecked_active.png'),
ignorealarmtimelen:0,
remindtimelength:0,
alarmSettings: [
{
id:0,
name: '无'
}, {
id:1,
name: '1分钟'
}, {
id:2,
name: '2分钟'
}, {
id:3,
name: '3分钟'
}, {
id: 4,
name: '4分钟'
}, {
id: 5,
name: '5分钟'
}],
/** alarmTimeSettings: [
{
id: 1,
name: '1分钟'
},
{
id: 3,
name: '3分钟'
},
{
id: 5,
name: '5分钟'
},
{
id: 10,
name: '10分钟'
},
{
id: 0,
name: '持续直到我处理报警提醒'
}
]*/
},
onLoad: function () {
},
onShow: function () {
this.getAlarmSetting()
},
getAlarmSetting() {
let that = this
api.post('api/user/userConfigInfo.json')
.then(res => {
let datamodel = res.data
that.setData({
ignorealarmtimelen: datamodel.ignorealarmtimelen,
remindtimelength: datamodel.remindtimelength
})
})
.catch(err => {
alertTip(err)
})
},
setSecure(e){
let that = this
let t = e.currentTarget
let data={}
data[t.dataset.type] = t.id
api.post('api/user/updateUserConfig.json', Object.assign({},data, { userid: wx.getStorageSync('user').userId }))
.then(res => {
that.getAlarmSetting()
})
.catch(err => {
alertTip(err)
})
}
})
\ No newline at end of file
<view class='con'>
<view class='set-box'>
<view class='setting-title'>
<view class='mode-title'>
<text>忽略相同类型提醒</text>
<view class='bar'></view>
</view>
<view class='mode-des'>收到车辆报警并选择忽略,一定时间内相同类型提醒不再提示。</view>
</view>
<view class='box-memu'>
<block wx:for='{{alarmSettings}}'>
<view class='box-item' id='{{item.id}}' data-type='ignorealarmtimelen' catchtap='setSecure'>
<text>{{item.name}}</text>
<view>
<image src='{{item.id==ignorealarmtimelen?imgCheckOn:imgCheckOff}}'></image>
</view>
</view>
</block>
</view>
</view>
</view>
\ No newline at end of file
page{
background-color: #f7f7f7;
}
.con{
border-top: 1px solid #ebebeb;
}
.set-box{
background-color: #ffffff;
}
.setting-title{
padding-left:50rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
height: 124rpx;
border-bottom: 1px solid #ebebeb;
}
.mode-title{
font-size: 34rpx;
line-height: 34rpx;
margin-bottom: 14rpx;
position: relative;
}
.bar{
position: absolute;
border-left: 3px solid #d7193c;
height: 34rpx;
top:0;
left: -23rpx;
}
.mode-des{
font-size: 22rpx;
line-height: 22rpx;
color: #afafaf;
}
.box-memu{
padding-left:50rpx;
}
.box-item{
border-bottom: 1px solid #ebebeb;
padding-right: 40rpx;
display: flex;
justify-content: space-between;
align-items: center;
height: 82rpx;
font-size: 32rpx;
}
.box-item image{
width: 44rpx;
height: 44rpx;
}
.box-item:last-child{
border-bottom: none;
}
const { api, mapApi, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
Page({
/**
* 页面的初始数据
*/
data: {
imgPerson: imgName('logo.png')
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
\ No newline at end of file
{}
\ No newline at end of file
<view>
<view class='set-box'>
<view class='logo'>
<image src='{{imgPerson}}'></image>
<view>
<text>188****8888{{userPhone}}</text>
<text class='low-des'>有效期:2019-05-30</text>
</view>
</view>
</view>
<view class='set-box'>
<view class='setting-title'>
<text class='bar'></text>
<text class='title'>服务费续期</text>
</view>
<view class='setting-item'>
<view class='box-item' data-remindermode='1'>
<view class='text-mode'>
1年
<text class='mode-main'>25</text> 元
</view>
<text class='buy-server'>续费</text>
</view>
<view class='box-item' data-remindermode='3'>
<view class='text-mode'>
2年
<text class='mode-main'>96</text> 元
</view>
<text class='buy-server'>续费</text>
</view>
</view>
</view>
<view class='set-box'>
<view class='setting-title'>
<text class='bar'></text>
<text class='title'>超级VIP</text>
<text class='title-des'>服务费-保险</text>
</view>
<view class='setting-item'>
<view class='box-item' data-remindermode='1'>
<view class='text-mode'>
1年
<text class='mode-main'>25</text> 元
</view>
<text class='buy-server'>续费</text>
</view>
<view class='box-item' data-remindermode='3'>
<view class='text-mode'>
2年
<text class='mode-main'>96</text> 元
</view>
<text class='buy-server'>续费</text>
</view>
</view>
</view>
</view>
\ No newline at end of file
page{
background-color: #f7f7f7;
border-top: 1px solid #ebebeb;
}
.set-box{
background-color: #ffffff;
margin-bottom: 14px;
}
.setting-title{
display: flex;
align-items: center;
height: 90rpx;
box-sizing: border-box;
font-size: 34rpx;
border-bottom: 1px solid #ebebeb;
}
.setting-title .bar{
display: inline-block;
height:34rpx;
border-left: 3px solid #d7193c;
margin: 0 26rpx 0 30rpx;
flex: 0 0 auto;
}
.setting-title .title{
flex: 0 0 auto;
}
.setting-item{
padding-left: 50rpx;
}
.box-item{
display: flex;
box-sizing: border-box;
align-items: center;
font-size: 28rpx;
padding: 20rpx 40rpx 20rpx 0;
border-bottom: 1px solid #ebebeb;
justify-content: space-between;
}
.setting-item .box-item:last-child{
border-bottom: none;
}
.more image:nth-of-type(1){
margin-right: 0;
}
.box-item image:nth-of-type(1).more-img{
width: 16rpx;
height: 30rpx;
}
.text-mode{
width: 468rpx;
font-size: 28rpx;
}
.mode-main{
font-size: 28rpx;
color: #f43333;
padding-bottom: 12rpx;
}
.buy-server{
padding: 14rpx 44rpx;
background-color: #d7193c;
color: #ffffff;
border-radius: 28rpx;
letter-spacing: 4px;
}
.title-des{
font-size: 28rpx;
color: #999999;
margin: 4rpx 0 0 7px;
}
.logo{
padding: 34rpx 28rpx;
display: flex;
align-items: center;
}
.logo image{
width: 112rpx;
height: 112rpx;
border-radius: 50%;
margin-right: 28rpx;
}
.logo text{
font-size: 36rpx;
}
text.low-des{
font-size: 26rpx;
color: #adadad;
margin-top: 18rpx;
}
.logo view{
display: flex;
flex-direction: column;
}
\ No newline at end of file
const { api, mapApi, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
Page({
data: {
markers:[],
longitude:0,
latitude: 0,
controls:[],
imgLogo: imgName('logo.png'),
imgToLoc: imgName('toloc.png'),
title: '展示车:震动报警',
time:'2018-05-09 18:08:44',
},
onLoad(){
this.mapCtx = wx.createMapContext('myMap')
let carLoc=wx.getStorageSync('carLocAlarm')
this.setData({
longitude: Number(carLoc.longitude),
latitude: Number(carLoc.latitude),
markers:[{
latitude: Number(carLoc.latitude),
longitude: Number(carLoc.longitude),
iconPath: imgName('loc.png'),
width:40,
height:46
}],
title: carLoc.content,
time: carLoc.msgTime
})
},
focusCar(e){
this.mapCtx.moveToLocation()
},
findCar(){
let that=this
wx.openLocation({
latitude: Number(that.data.latitude),
longitude: Number(that.data.longitude),
scale: 28
})
},
onUnload(){
wx.removeStorageSync('carLocAlarm')
}
})
\ No newline at end of file
{}
\ No newline at end of file
<map id="myMap" show-location scale='13' markers='{{markers}}' longitude='{{longitude}}' latitude='{{latitude}}'>
<cover-view class='des'>
<cover-image class='img-des' src='{{imgLogo}}'></cover-image>
<cover-view class='bar'></cover-view>
<cover-view class='content'>
<cover-view>{{title}}</cover-view>
<cover-view class='time'>{{time}}</cover-view>
</cover-view>
<cover-view class='toloc' catchtap='findCar'>导航</cover-view>
</cover-view>
<cover-image src='{{imgToLoc}}' class='loc' catchtap='focusCar'></cover-image>
</map>
\ No newline at end of file
page {
height: 100%;
}
map {
height: 100%;
width: 100%;
position: relative;
}
.des {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 86rpx;
display: flex;
align-items: center;
background-color: #fff;
padding: 27rpx 0;
}
.img-des {
width: 86rpx;
height: 86rpx;
margin: 0 26rpx;
}
.content {
padding: 0 28rpx;
height: 86rpx;
font-size: 32rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
flex: 1 0 auto;
}
.bar {
height: 86rpx;
width: 2px;
background-color: #dfdfdf;
}
.time {
font-size: 28rpx;
color: #a8a8a8;
}
.loc {
width: 80rpx;
height: 80rpx;
position: absolute;
right: 30rpx;
bottom: 168rpx;
}
.toloc {
line-height: 36rpx;
font-size: 32rpx;
padding: 20rpx 30rpx;
background-color: #d7193c;
border-radius: 38rpx;
margin-right: 26rpx;
}
const { api, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
const qrcode = require('../../lib/qrcode.js')
Page({
data: {
deviceList: [{
detailList:[{
name:'请尝试下拉刷新'
}]
}],
imgUserIcon: imgName('userdevice.png'),
imgUserBg: imgName('devicebg.png'),
imgCheck: imgName('security_settings_unchecked_active.png'),
imgPencil: imgName('pencil.png'),
imgAdd: imgName('add.png'),
imgFind: imgName('search.png'),
inputValue:'',
modify:false,
modifyValue:'',
deviceId:null,
carCode: '',//二维码
canvasHide: true,//二维码隐藏
},
onLoad: function () {
this.getCarList()
},
onShow: function () {
console.log('welcome show')
},
getCarList(data){
let that = this
api.get('api/vehicle/myVehicle.json', data ? data:{})
.then(res => {
console.log(res.items)
that.setData({
deviceList: res.items.map(item=>{
item.networkingStopTime=item.networkingStopTime.slice(0, 10)
return item
})
})
wx.stopPullDownRefresh()
})
.catch(err => {
wx.stopPullDownRefresh()
alertTip(err)
})
},
addCar(){
wx.navigateTo({
url: '/pages/device_bind/device_bind',
})
},
onPullDownRefresh(){
this.getCarList()
},
changeCar(e) {
let that=this
let id=e.currentTarget.id
api.get('api/vehicle/switchingVehicle.json', { id: Number(id)})
.then(res => {
that.getCarList()
})
.catch(err => {
alertTip(err)
})
},
formSubmit: function (e) {
this.getCarList({ search: e.detail.value})
this.setData({
inputValue:''
})
},
unbindCar(e){
let that = this
let id = e.currentTarget.id
wx.showModal({
title: '警告',
content: '确定解除该设备的绑定?',
success: function (res) {
if (res.confirm) {
api.post('api/vehicle/removeBinding.json', { userVehicleId: Number(id), removeUserId: Number(wx.getStorageSync('user').userId) })
.then(res => {
that.getCarList()
})
.catch(err => {
alertTip(err)
})
}
}
})
},
carBindUser(e){
console.log(e)
wx.navigateTo({
url: `/pages/carusers/carusers?id=${e.currentTarget.id}&master=${e.currentTarget.dataset.master}`,
})
},
modify(e){
let that=this
if (Number(e.currentTarget.dataset.master)==wx.getStorageSync('user').userId){
that.setData({
modify: true,
deviceId: Number(e.currentTarget.id)
})
}else{
alertTip('您不是主车主,无法修改')
}
},
apiModify(e){
let that=this
api.post('api/vehicle/modifyVehicleInfo.json', { name: e.detail.value, otherFeatures: '', id: that.data.deviceId })
.then(res => {
that.setData({
modify: false,
modifyValue:''
})
that.getCarList()
})
.catch(err => {
alertTip(err)
})
},
giveUp(){
let that=this
wx.showModal({
title: '提示',
content: '确定放弃修改车辆昵称?',
success(res){
if(res.confirm){
that.setData({
modify: false,
modifyValue: ''
})
}
}
})
},
showCode(e) {
wx.navigateTo({
url: `/pages/qr_code/qr_code?vcu=${e.currentTarget.id}`,
})
},
//适配不同屏幕大小的canvas
setCanvasSize: function () {
var size = {};
try {
var res = wx.getSystemInfoSync();
var scale = 750 / 460;//不同屏幕下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
{
"navigationBarTitleText": "我的设备",
"enablePullDownRefresh": true
}
\ No newline at end of file
<scroll-view class='con' wx:if='{{!modify}}' scroll-y>
<view class='search'>
<image class='search-icon' src='{{imgFind}}'></image>
<input name="search" class='search-car' confirm-type='search' placeholder="请输入车辆昵称" bindconfirm='formSubmit' value='{{inputValue}}' />
</view>
<block wx:for='{{deviceList}}'>
<view class='car-item'>
<view class='car-msg'>
<view class='msg-item'>
<view class='text-item' id='{{item.id}}' data-master='{{item.masterUser}}' catchtap='modify'>
<text>昵称:</text>
<text>{{item.name}} </text>
<image src='{{imgPencil}}' class='pencil'></image>
</view>
<view class='text-item'>
<text>设备号:</text>
<text>{{item.vcuNo}}</text>
</view>
<view class='text-item'>
<text>服务到期:</text>
<text class='high-light'>截止到{{item.networkingStopTime}}</text>
</view>
</view>
<view class='use-car'>
<image src='{{imgCheck}}' wx:if='{{item.use}}'></image>
</view>
</view>
<view class='car-change' wx:if='{{item.state}}'>
<text hidden='{{item.use}}' bindtap='changeCar' id='{{item.id}}'>使用</text>
<text catchtap='unbindCar' id='{{item.id}}'>解绑</text>
<text catchtap='carBindUser' id='{{item.id}}' data-master='{{item.masterUser}}'>用户列表</text>
<text catchtap='showCode' id='{{item.vcuNo}}'>二维码</text>
</view>
<view wx:else class='car-change'>
<text>等待授权</text>
</view>
</view>
</block>
</scroll-view>
<view wx:else class='con'>
<view class='search'>
<input name="search" class='search-car' placeholder="请输入要修改后的车辆昵称" bindconfirm='apiModify' value='{{modifyValue}}' />
</view>
<view class='addcar'>
<button type='primary' class='give-up' catchtap='giveUp'>放弃修改</button>
</view>
</view>
<view class='addcar' wx:if='{{!modify}}'>
<button bindtap='addCar'>
<image src='{{imgAdd}}'></image>
新增车辆</button>
</view>
\ No newline at end of file
page {
height: 100%;
overflow: hidden;
background-color: #f7f7f7;
position: relative;
}
.con {
box-sizing: border-box;
height: 100%;
padding-bottom: 84rpx;
}
.addcar{
position: absolute;
bottom:0;
left: 0;
width: 100%;
height: 140rpx;
background-color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
}
.addcar button{
background-color: #d7193c;
height: 84rpx;
width: 694rpx;
font-size: 34rpx;
line-height: 34rpx;
display: flex;
justify-content: center;
align-items: center;
}
.addcar image{
width: 36rpx;
height: 36rpx;
margin-right: 20rpx;
}
.search{
background-color: #ffffff;
padding-left: 30rpx;
height: 70rpx;
width: 694rpx;
display: flex;
align-items: center;
border-radius: 35rpx;
margin: 14rpx auto;
}
.search-icon{
margin-right: 20rpx;
width: 30rpx;
height: 30rpx;
}
.search-car{
font-size: 26rpx;
flex: 1 0 auto;
}
.car-item{
height: 294rpx;
background-color: #ffffff;
margin-bottom: 14rpx;
padding: 0 28rpx;
}
.car-msg{
height: 196rpx;
border-bottom: 2px dotted #cfcfcf;
display: flex;
justify-content: space-between;
}
.msg-item{
display: flex;
flex-direction: column;
justify-content: space-between;
height: 196rpx;
padding: 28rpx 0;
flex: 0 0 450rpx;
}
.use-car{
width: 57rpx;
padding: 28rpx 0;
}
.use-car image{
width: 57rpx;
height: 57rpx;
}
.pencil{
width: 28rpx;
height: 28rpx;
}
.text-item{
display: flex
}
.text-item text:nth-of-type(1){
flex: 0 0 170rpx;
font-size: 32rpx;
line-height: 32rpx;
}
.text-item text:nth-of-type(2){
flex: 1 0 auto;
font-size: 32rpx;
line-height: 32rpx;
color: #cfcfcf;
}
.text-item text:nth-of-type(2).high-light{
color: #ff3333;
}
.car-change{
display: flex;
height: 98rpx;
align-items: center;
justify-content: flex-end;
}
.car-change text{
border:1px solid #cccccc;
border-radius: 28rpx;
width: 160rpx;
height: 56rpx;
font-size: 26rpx;
line-height: 56rpx;
letter-spacing: 4rpx;
color: #cccccc;
text-align: center;
margin-right: 18rpx;
}
.car-change text:last-child{
margin-right: 0;
}
\ No newline at end of file
const jsbuffer=require('../../lib/jsbuffer.min.js')
const { api, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
Page({
data: {
msg: 'welcome',
imgDotBig: imgName('mesgDot1.png'),
imgDotSmall: imgName('mesgDot2.png'),
imgAlarmBattery: imgName('alarm_battery.png'),
imgAlarmMove: imgName('alarm_move.png'),
imgArrowUp:imgName('arrowup.png'),
imgArrowDown:imgName('arrowdown.png'),
alarmClass:'alarm-warn',
alarmMsg:[{
id:'1',
open:false,
date:{
month:'二月',
day:'27'
},
mileage:'0km',
alarmNum:'35次',
travelTimes:'10次',
detail:[{
time:'09:43',
type:'battery',
msg:'电池移除',
warn:true
}, {
time: '12:43',
type: 'battery',
msg:'电池接入',
warn: false
}, {
time: '13:53',
type: 'move',
msg:'车辆轻微震动',
warn: false
}, {
time: '14:53',
type: 'move',
msg: '车辆严重震动',
warn: true
}]
}]
},
onLoad: function () {
},
getImgSrc(type){
console.log(type)
},
openDetail(e){
let a =this.data.alarmMsg.map(item=>{
if(item.id==e.target.dataset.num){
item.open=!item.open
}
return item
})
this.setData({
alarmMsg:a
})
a=null;
},
onShow: function () {
// console.log('welcome show')
// let ab=new jsbuffer().from('2152e2ac','hex')
// ab.set(0,36)
// console.log(ab)
// let ba=new jsbuffer().read(ab.buffer)
// console.log(ba)
// console.log(ab.get(2))
// console.log(ab.get(1, 'HEX'))
}
})
\ No newline at end of file
<scroll-view class='con'>
<block wx:for='{{alarmMsg}}'>
<view class='date'>
<view class='date-total'>
<view class='total-side'>
<image src='{{imgDotBig}}'></image>
</view>
<view class='total-main'>
<view>
<text>{{item.date.day}}</text>
<text>{{item.date.month}}</text>
</view>
<view class='total-item'>
<view>
<text>{{item.mileage}}</text>
<text>里程</text>
</view>
<view>
<text>{{item.alarmNum}}</text>
<text>警告</text>
</view>
<view>
<text>{{item.travelTimes}}</text>
<text>行驶次数</text>
</view>
</view>
<view class='total-arrow'>
<image src='{{item.open?imgArrowUp:imgArrowDown}}' bindtap='openDetail' data-num='{{item.id}}'></image>
</view>
</view>
</view>
<view wx:if='{{item.open}}'>
<block wx:for='{{item.detail}}'>
<view class='date-detail'>
<view class='detail-side'>
<text>{{item.time}}</text>
<image src='{{imgDotSmall}}' data-type='item.type'></image>
</view>
<view class='detail-main'>
<view class='alarm {{ item.warn?alarmClass:""}}'>
<image src='{{item.type=="battery"?imgAlarmBattery:imgAlarmMove}}'></image>
<text>{{ item.msg}}</text>
</view>
<!-- <view class='detail-arrow'>
<image src='{{imgArrowUp}}'></image>
</view> -->
</view>
</view>
</block>
</view>
</view>
</block>
</scroll-view>
\ No newline at end of file
/**index.wxss**/
page{
height: 100%;
}
.con{
height: 100%;
background-color: #efeff0;
}
.date-total{
box-sizing: border-box;
height:112rpx;
display: flex;
}
.total-side {
flex-basis: 120rpx;
flex-grow: 0;
display: flex;
align-items: flex-end;
justify-content: flex-end;
padding-right: 10rpx;
}
.total-main{
background-color: #fff;
margin-bottom: 6rpx;
display: flex;
flex-grow: 1;
padding: 10rpx 20rpx;
justify-content: space-between;
}
.total-main>view:first-child{
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
border-right: 4rpx solid #000;
}
.total-main>view:first-child text:first-child{
font-size: 42rpx;
padding-right: 14rpx;
}
.total-main>view:first-child text:nth-of-type(2){
padding-right: 22rpx;
}
.total-item{
display: flex;
align-items: center;
justify-content: space-around;
flex-grow: 1;
}
.total-item>view{
display: flex;
flex-direction: column;
align-items: center;
}
.total-arrow,.detail-arrow{
display: flex;
align-items: center;
justify-content: center;
}
.total-arrow image,.detail-arrow image{
width: 36rpx;
height: 18rpx;
}
.total-side image{
width: 24rpx;
height: 72rpx;
}
.date-detail{
box-sizing: border-box;
height: 92rpx;
display: flex;
}
.detail-side{
flex-basis: 120rpx;
flex-grow: 0;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 14.7rpx;
}
.detail-side image{
width: 13rpx;
height: 92rpx;
}
.detail-main{
background-color: #fff;
margin: 14rpx 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.alarm image{
width: 38rpx;
height: 38rpx;
}
.detail-main{
padding: 0 20rpx 0 10rpx ;
flex-grow:1;
}
.alarm{
display: flex;
align-items: center;
font-size: 32rpx;
}
.alarm image{
padding-right: 24rpx;
}
.alarm-warn{
color: #e76955;
}
const config = require('../../config/index.js')
const { api, mapApi, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
let carTimer = null//数据轮询 车实时状态
let medicalTimer = null //体检 延时器
Page({
/**
* 页面的初始数据
*/
data: {
imgCarActionOpen: imgName('open.png'),
imgCarActionClose: imgName('close.png'),
imgPerson: imgName('person.png'),
imgKm: imgName('km.png'),
imgBattery: imgName('battery.png'),
imgFind: imgName('find.png'),
imgLoc: imgName('loc.png'),
imgLock: imgName('lock.png'),
imgToloc: imgName('toloc.png'),
imgMore: imgName('more.png'),
imgSpeed: imgName('speed.png'),
imgMedical: imgName('medical.png'),
user: null,//用户
person:1,//个租
device: null,//设备
timerDevice: null,
baseMsg: true,//基础数据获取是否正常
ui: {
message: null,//消息量
froNo: '--',//车架号
vcuNo: '--',//中控号
licensePlate: '--',//号牌
vehicleTypeName: '--',//车型名称
rentStartTime: '--',//起租时间
fee:'1.5',
deviceAdress: '--',//位置
last_communication_time: '--',//更新时间
lockState: 0,//锁
speed: '0',
estimatedMileage: '--',//预估里程
dumpEnergy: '--',//剩余电量
bluetoothAddress: null,
locMap: {
latitude: 30.334546,
longitude: 120.121121,
markers: [{
id:0,
latitude:0,
longitude:0,
iconPath: imgName('location_sucess.png'),
}]
},
},
location: null,
latitude: null,//维度
longitude: null,//经度
rent: 'false',//物联网到期
carDetail: false,//车辆详情
tab: '',
hasMedical: false,//是否体检
medicalNum: 0,//体检百分比
medicalScore: 80,//体检百分比
//详情页数据
details: [{
title: '网络信号',
icon: imgName('single.png'),
des1: '信号强度:--',
des2: '最后通信时间:--'
},
// {
// title: 'GPRS信号',
// icon: imgName('gprs.png'),
// des1: '经度:120.11536 纬度:30.33793',
// des2: '位置:浙江省杭州市拱墅区星桥路33号',
// tip: '当前定位正常,将车辆移至信号良好处,可增强通讯和定位。'
// },
{
title: '定位',
icon: imgName('locdes.png'),
des1: '经度:-- 纬度:--',
des2: '位置:--',
tip: ''
}, {
title: '卫星数量',
icon: imgName('satellite.png'),
des1: '可用卫星:--'
}],
},
markerTap() {
},
//消息
toMsgPage() {
wx.navigateTo({
url: '/pages/user_message/user_message',
})
},
//tab切换
tabCarMenu(e) {
let id = e.target.id
if (e.target.id === this.data.tab) return
let tab = this.data.tab === '' ? 'tab' : ''
this.setData({
tab
})
},
onLoad: function () {
let user = wx.getStorageSync('user').userMapp
if (!user){
wx.redirectTo({
url: '/pages/welcome2/welcome2',
})
return
}
this.setData({
user,
person: user.userType
})
this.apiGetCarMsg()
},
onHide: function () {
clearInterval(carTimer)
},
onUnload() {
clearInterval(carTimer)
},
onShow: function () {
let that = this
carTimer = setInterval(function () {
//获取车辆信息或者用户列表
that.getCarDetail()
}, 10000)
},
//获取硬件信息
getCarDetail() {
let { device, ui, details } = this.data
if (device && device.vcuNo) {
api.get('device/getDevInfo', {
vcuNo: device.vcuNo
}, true)
.then(res => {
let { data } = res
console.log('实时数据', data)
//实时数据
if (data.address) {
ui.deviceAdress = data.address//位置
}
if (data.last_update_time) {
ui.last_communication_time = data.last_update_time//更新时间
}
ui.estimatedMileage = data.km || '0'//预估里程
ui.lockState = data.lock_state == 'closed' ? 0 : 1//锁 1开锁状态
ui.dumpEnergy = data.power//剩余电量
ui.speed = data.speed//行驶速度
//地图内容
ui.locMap.latitude = Number(data.latitude)
ui.locMap.longitude = Number(data.longitude)
ui.locMap.markers[0].latitude = Number(data.latitude)
ui.locMap.markers[0].longitude = Number(data.longitude)
//详情内容
this.setCarDetail(data)
this.setData({
ui,
})
})
.catch(err => {
console.error(err)
})
}
},
getUserLoc() {
let This = this
userLocation()
.then(location => {
This.setData({
location
})
})
.catch(err => {
wx.showModal({
title: '提示',
showCancel: false,
content: '需要授权地理定位才能正常使用,点击确定去授权',
success(res) {
if (res.confirm) {
wx.openSetting({
complete() {
This.getUserLoc()
}
})
}
}
})
})
},
//请求一次 基础信息
apiGetCarMsg() {
let that = this
let user = this.data.user
let device = {}
api.get('user/getVcuByUserId', {
user_id: user.id
})
.then(res => {
let { data } = res
device.createDate = data.createDate
device.depositAmount = data.depositAmount
//获取车辆信息
api.get('vehicle/base/getVehicleBaseByFrameNo', {
frameNo: data.frameNo
})
.then(res => {
let carData = res.data
device = Object.assign(carData, device)
//获取车型
api.get('vehicle/model/getModelById', {
id: device.vehicleModelId
})
.then(res => {
let carData2 = res.data
device = Object.assign(carData2, device)
this.setData({
device,
baseMsg: true
})
wx.setStorageSync('device', device)
that.getCarDetail()
that.setUi()
})
.catch(err => {
that.setData({
baseMsg: false
})
console.error(err)
})
})
.catch(err => {
that.setData({
baseMsg: false
})
console.error(err)
})
})
.catch(err => {
that.setData({
baseMsg: false
})
if(/数据为空/.test(err)){
wx.reLaunch({
url: '/pages/welcome2/welcome2',
})
}
console.error(err)
})
},
//关锁
netCloseCar() {
let This = this
api.get('device/lockSwitch.json', { lockState: 0, userId:this.data.user.id })
.then(res => {
let ui=this.data.ui
ui.lockState=0
alertTip('锁车成功')
This.setData({
ui,
})
})
.catch(err => {
alertTip(err)
})
},
//开锁
netOpenCar() {
let This = this
api.get('device/lockSwitch.json', { lockState: 1, userId: this.data.user.id })
.then(res => {
let ui = this.data.ui
ui.lockState = 1
alertTip('开锁成功')
This.setData({
ui,
})
})
.catch(err => {
alertTip(err)
})
},
//寻车
netFindCar() {
api.get('device/findCar.json', { userId:this.data.user.id})
.then(res => {
alertTip('寻车成功')
})
.catch(err => {
alertTip(err)
})
},
//开关锁
apiActionDevice() {
if (this.data.ui.lockState) {//开
this.netCloseCar()
} else {
this.netOpenCar()
}
},
//我的
toMy() {
wx.navigateTo({
url: '/pages/my/my',
})
},
showMyLoc() {
if (!this.mapCtx) {
this.mapCtx = wx.createMapContext('carMap')
}
this.mapCtx.moveToLocation()
},
//车辆列表信息
setCarDetail(d) {
let details = this.data.details
details[0].des1 = `信号强度:${d.csq}`
details[0].des2 = `最后通信时间:${d.last_update_time}`
details[1].des1 = `经度:${d.longitude} 纬度:${d.latitude}`
details[1].des2 = `gps:${d.gps_effective==5?'有效':'无效'}`
details[1].des3 = `位置:${d.address}`
details[1].tip = `${d.gps_effective == 5 ? '' : '当前定位异常(以上数据为最后一次上报数据), 将车辆移至信号良好处, 可增强通讯和定位。'}`
details[2].des1 = `可用卫星:${d.number_satellite}`
this.setData({
details,
})
},
progressChange(e) {
console.log(e)
},
//体检
reMedical() {
this.changeBar()
},
changeBar() {
if (medicalTimer) {
console.log('medial')
return
}
this.setData({
hasMedical: false,//是否体检
medicalNum: 0
})
//请求体检内容
this.setData({
medicalNum: 100
})
let that = this
medicalTimer = setTimeout(() => {
that.setData({
hasMedical: true,//是否体检
medicalNum: 0,//体检百分比
})
medicalTimer = null
}, 3000)
},
//统一设置ui
setUi() {
let { user, device, ui } = this.data
//基础信息
if (user && device) {
ui.froNo = device.frameNo//车架号
ui.vcuNo = device.vcuNo//中控号
ui.vehicleTypeName = device.model//车型名称
ui.licensePlate = device.licensePlate//号牌
ui.rentStartTime = new Date(device.createDate).toLocaleString()//租车起始时间
}
//车辆信息
this.setData({
ui
})
},
//查看二维码
seeQrCode(e) {
let code = e.currentTarget.id
wx.navigateTo({
url: `/pages/qr_code/qr_code?vcu=${code}`,
})
},
//无数据返回登录
reLogin() {
wx.redirectTo({
url: '/pages/welcome2/welcome2',
})
}
})
\ No newline at end of file
{
}
\ No newline at end of file
<!--pages/user_index/user_index.wxml-->
<view class='con' wx:if='{{baseMsg}}'>
<view class='tab-header'>
<view class='person' catchtap='toMy'>
<image src='{{imgPerson}}'></image>
</view>
<view class='main' catchtap='tabCarMenu'>
<view class='item {{tab===""? "active":""}}'>车辆位置</view>
<view class='item {{tab==="tab"? "active":""}}' id='tab'>车辆详情</view>
</view>
<view class='person'></view>
</view>
<view class='body-box {{tab}}'>
<view class='tab-map'>
<map id='carMap' scale='13' markers='{{ui.locMap.markers}}' show-location bindmarkertap='markersTap' longitude='{{ui.locMap.longitude}}' latitude='{{ui.locMap.latitude}}'>
<cover-view class='map-alarm' catchtap='toMsgPage' hidden='{{ui.message}}'>
<cover-view>您有消息需要关注</cover-view>
<cover-image src='{{imgMore}}'></cover-image>
</cover-view>
<cover-view class='map-fee' catchtap='toMsgPage' wx:if='{{person}}'>
<cover-view>预估费用(仅供参考,以实际结算为准):{{ui.fee}}元</cover-view>
</cover-view>
<cover-view class='map-controltap'>
<cover-image src='{{imgFind}}' catchtap='netFindCar'></cover-image>
<cover-image src='{{imgToloc}}' catchtap='showMyLoc'></cover-image>
</cover-view>
</map>
<view class='map-des'>
<view class='loc'>{{ui.deviceAdress}}</view>
<view class='loc-des'>定位时间:{{ui.last_communication_time}}</view>
<view class='status'>
<view class='status-item'>
<image class='km' src='{{imgKm}}'></image>
<view>里程:{{ui.estimatedMileage}}</view>
</view>
<view class='status-item'>
<image class='battery' src='{{imgSpeed}}'></image>
<view>速度:{{ui.speed}}</view>
</view>
<view class='status-item'>
<image class='battery' src='{{imgBattery}}'></image>
<view>电量:{{ui.dumpEnergy}}</view>
</view>
</view>
<view class='btn-action'>
<view class='lock' bindtap='returnCar' wx:if='{{person==1}}'>
<text>还车</text>
</view>
<view class='lock' bindtap='apiActionDevice'>
<image src='{{imgLock}}'></image>
<text>{{ui.lockState?'我要锁车':'开锁用车'}}</text>
</view>
</view>
</view>
</view>
<scroll-view class='tab-detail' scroll-y>
<view class='device-msg item'>
<view>
<text>车型名称 :</text>
<text class='vname' id='{{ui.vehicleTypeName}}' catchtap='seeQrCode'>{{ui.vehicleTypeName}}(二维码)</text>
</view>
<view>
<text>车架号 :</text>
<text class='vname' id='{{ui.froNo}}' catchtap='seeQrCode'>{{ui.froNo}}(二维码)</text>
</view>
<view>
<text>中控号 :</text>
<text class='vname' id='{{ui.vcuNo}}' catchtap='seeQrCode'>{{ui.vcuNo}}(二维码)</text>
</view>
<view>
<text>车牌号 :</text>
<text class='vname' id='{{ui.licensePlate}}' catchtap='seeQrCode'>{{ui.licensePlate}}(二维码)</text>
</view>
<view>
<text>起租时间 :</text>
<text class='vname'>{{ui.rentStartTime}}</text>
</view>
</view>
<view class='item'>
<image class='icon' src='{{imgMedical}}'></image>
<view class='des'>
<view class='title'>
<text>体检情况</text>
<text class='medical-btn' catchtap='reMedical'>立即体检</text>
</view>
<view class='medical'>
<view wx:if="{{!hasMedical}}">
<progress class='progress' onchange='progressChange' percent="{{medicalNum}}" active show-info activeColor='#d7193c' />
</view>
<view wx:else>
<view>动力系统:</view>
<view>供电系统:</view>
<view>显示系统:</view>
<view>中控系统:</view>
<view>总分:</view>
</view>
</view>
<view class='notify' wx:if="{{hasMedical&&medicalScore<100}}">体检结果不佳,
<text catchtap='changeBar'> 我要保修。</text>
</view>
</view>
</view>
<view class='item' wx:for="{{details}}" wx:key='{{item.title}}'>
<image class='icon' src='{{item.icon}}'></image>
<view class='des'>
<view class='title'>{{item.title}}</view>
<view class='low-des'>
<view>{{item.des1}}</view>
<view>{{item.des2}}</view>
<view>{{item.des3}}</view>
</view>
<view class='notify'>{{item.tip}}</view>
</view>
</view>
</scroll-view>
</view>
</view>
<view wx:else class='con'>
<view class='msg-err'>
<text class='des'>网络问题,获取数据失败。</text>
<text class='bind' catchtap='apiGetCarMsg'>点击重新获取</text>
<text class='bind' catchtap='reLogin'>或者重新登录</text>
</view>
</view>
\ No newline at end of file
page {
height: 100%;
overflow: hidden;
}
page .con {
height: 100%;
overflow: hidden;
position: relative;
}
page .con .tab-header {
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: stretch;
padding: 0rpx 28rpx 0 28rpx;
height: 103rpx;
color: #686868;
border-bottom: 2rpx solid #e9e9e9;
}
page .con .tab-header .person {
height: 100%;
width: 42rpx;
padding-top: 28rpx;
}
page .con .tab-header image {
height: 42rpx;
width: 42rpx;
}
page .con .tab-header .main {
width: 318rpx;
height: 100%;
display: flex;
justify-content: space-between;
position: relative;
transform: translateY(2rpx);
}
page .con .tab-header .main .item {
font-size: 32rpx;
padding-top: 28rpx;
text-align: center;
border-bottom: 6rpx solid transparent;
}
page .con .tab-header .item.active {
color: #d7193c;
border-bottom-color: #d7193c;
}
page .con .body-box {
height: 1111rpx;
width: 200%;
box-sizing: border-box;
transform: translateX(0);
transition: all 0.2s;
display: flex;
}
page .con .body-box .tab-map {
width: 50%;
display: flex;
flex-direction: column;
/* justify-content: space-between; */
}
page .con .body-box .tab-map map {
width: 100%;
height: 690rpx;
position: relative;
}
page .con .body-box .tab-map map .map-alarm {
position: absolute;
top: 18rpx;
width: 700rpx;
box-sizing: border-box;
left: 25rpx;
height: 56rpx;
background-color: #494948;
color: #ffffff;
font-size: 26rpx;
border-radius: 56rpx;
padding: 0 36rpx;
margin: 0 auto;
}
.map-fee {
position: absolute;
top: 80rpx;
width: 700rpx;
color: #ffffff;
background-color: rgba(0, 0, 0,0.5);
box-sizing: border-box;
left: 25rpx;
height: 56rpx;
font-size: 26rpx;
border-radius: 56rpx;
padding: 0 36rpx;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
}
page .con .body-box .tab-map map .map-alarm cover-view {
line-height: 56rpx;
}
page .con .body-box .tab-map map .map-alarm cover-image {
width: 22rpx;
height: 34rpx;
position: absolute;
top: 11rpx;
right: 36rpx;
}
page .con .body-box .tab-map map .map-controltap {
position: absolute;
width: 100%;
box-sizing: border-box;
bottom: 24rpx;
padding: 0 26rpx;
}
page .con .body-box .tab-map map .map-controltap cover-image {
width: 80rpx;
height: 80rpx;
}
page .con .body-box .tab-map map .map-controltap cover-image:last-child {
position: absolute;
top: 0;
right: 26rpx;
}
page .con .body-box .tab-map .map-des {
height: 400rpx;
padding: 0 20rpx;
display: flex;
align-items: center;
flex-direction: column;
}
page .con .body-box .tab-map .map-des .loc {
font-size: 26rpx;
padding: 24rpx 0 0 0;
}
page .con .body-box .tab-map .map-des .loc-des {
color: #969696;
font-size: 24rpx;
padding: 14rpx 0;
}
page .con .body-box .tab-map .map-des .status {
width: 600rpx;
padding: 20rpx 0 30rpx;
height: 150rpx;
display: flex;
justify-content: space-between;
}
page .con .body-box .tab-map .map-des .status .status-item {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
font-size: 26rpx;
justify-content: space-between;
}
page .con .body-box .tab-map .map-des .status .status-item image {
width: 57rpx;
height: 57rpx;
}
page .con .body-box .tab-map .map-des .status .status-item image.battery {
width: 64rpx;
height: 40rpx;
margin-top: 8rpx;
}
page .con .body-box .tab-map .map-des .lock {
border-radius: 12rpx;
width: 100%;
height: 104rpx;
font-weight: bold;
background-color: #d7193c;
font-size: 42rpx;
display: flex;
align-items: center;
color: #ffffff;
justify-content: center;
}
page .con .body-box .tab-map .map-des .lock image {
width: 56rpx;
height: 56rpx;
margin-right: 16rpx;
}
page .con .body-box .tab-detail {
width: 50%;
height: 100%;
box-sizing: border-box;
padding: 0 40rpx 50rpx;
}
page .con .body-box .tab-detail .item {
padding: 38rpx 0;
border-bottom: 2rpx dashed #cccccc;
display: flex;
}
page .con .body-box .tab-detail .item .vname {
color: #cccccc;
}
page .con .body-box .tab-detail .item .des {
flex-grow: 1;
padding-left: 30rpx;
display: flex;
flex-direction: column;
align-items: flex-start;
}
page .con .body-box .tab-detail .item .des .title {
font-size: 38rpx;
line-height: 48rpx;
}
page .con .body-box .tab-detail .item .des .low-des {
font-size: 36rpx;
line-height: 40rpx;
padding-top: 26rpx;
color: #cccccc;
}
page .con .body-box .tab-detail .item .des .notify {
font-size: 30rpx;
padding-top: 22rpx;
color: #d7193c;
}
.notify text{
text-decoration: underline;
}
page .con .body-box .tab-detail .item .icon {
width: 50rpx;
height: 50rpx;
flex-grow: 0;
flex-shrink: 0;
}
page .con .tab {
transform: translateX(-50%);
}
.device-msg{
flex-direction: column;
}
.device-msg view{
display: flex;
line-height: 60rpx;
}
.device-msg text:nth-of-type(1){
flex: 0 0 200rpx;
}
.device-msg text:nth-of-type(2){
flex: 1 0 auto;
}
.medical{
flex: 1 0 auto;
padding-top: 26rpx;
}
.progress{
width: 580rpx;
}
.title{
align-self: stretch;
display: flex;
justify-content: space-between;
}
.medical-btn{
width: 166rpx;
height: 64rpx;
line-height: 64rpx;
border-radius: 64rpx;
background-color: #d7193c;
text-align: center;
color: #ffffff;
font-size: 32rpx;
}
.msg-err{
display: flex;
flex-direction: column;
align-items: center;
}
.bind{
color: #d7193c;
text-decoration: underline;
margin-top: 50rpx;
}
.btn-action{
display: flex;
width: 100%;
justify-content: space-between;
}
.btn-action view:nth-of-type(1){
flex: 1 0 50rpx;
margin-right: 20rpx;
}
.btn-action view:nth-of-type(2){
flex: 2 0 50rpx;
}
\ No newline at end of file
const { api, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser } = require('../../lib/util.js')
Page({
data: {
imgInbefore: imgName('insurancebefore.png'),
imgIn: imgName('insurancing.png'),
imgInafter: imgName('insuranced.png'),
imgInbg: imgName('inbg.png'),
insurances: [{
id: 'baoxian1hao',
company: '众安保险',
name: '齐世宝(送到抢险)',
minDes: '用车,防盗,理赔全程指导',
des: '用车,防盗,理赔全程指导',
tip: '丢车理赔',
imgSrc: 'aaa.png',
money: '68.0'.match(/(\d+)\.(\d*)?/)
}, {
id: 'baoxian2hao',
company: '中国平安',
name: '综合意外(送到抢险)',
minDes: '用车,防盗,理赔全程指导',
des: '用车,防盗,理赔全程指导,用车,防盗,理赔全程指导,用车',
tip: '',
imgSrc: 'bba.png',
money: '35.9'.match(/(\d+)\.(\d*)?/)
}]
},
onLoad: function () {
console.log('welcome')
},
onShow: function () {
console.log('welcome show')
let a='20.8'
console.log()
}
})
\ No newline at end of file
{}
\ No newline at end of file
<!--我的保险 -->
<view class='con'>
<view class='menu'>
<view class='in-title'>我的保单<view></view></view>
<view class='in-menu'>
<view class='in-item'>
<image src='{{imgInbefore}}'></image>
<text>待领取/审核</text>
</view>
<view class='in-item'>
<image src='{{imgIn}}'></image>
<text>保障中的</text>
</view>
<view class='in-item'>
<image src='{{imgInafter}}'></image>
<text>已过期</text>
</view>
</view>
</view>
<block wx:for='{{insurances}}'>
<view class='insu-item'>
<view class='insu-bg'>
<image src='{{imgInbg}}'></image>
<view class='insu-tip'>
<text>{{item.company}}</text>
<text>{{item.name}}</text>
</view>
<view class='s-label' wx:if="{{item.tip}}">{{item.tip}}</view>
</view>
<view class='insu-des'>
<text class='des'>{{item.des}}</text>
<text class='insu-mon'>
<text>{{item.money[1]}}</text><text>.{{item.money[2]}}</text><text>元</text>
</text>
</view>
</view>
</block>
</view>
\ No newline at end of file
.con{
background-color: #efeff0;
}
.menu{
margin-bottom:20rpx;
}
.in-title{
padding: 0 22rpx;
height: 62rpx;
border-bottom: 2rpx solid #bababa;
font-weight: bold;
line-height: 62rpx;
background-color: #ffffff;
}
.in-menu{
background-color:#fff;
display: flex;
justify-content: center;
}
.in-menu image{
width: 126rpx;
height: 126rpx;
}
.in-item{
height: 210rpx;
flex-basis: 204rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
line-height: 40rpx;
}
.insu-item{
height: 326rpx;
padding: 20rpx 40rpx;
background-color:#fff;
border-bottom: 2rpx solid #bababa;
}
.insu-bg{
position: relative;
}
.insu-tip{
position: absolute;
width: 420rpx;
height: 144rpx;
display: flex;
flex-direction: column;
background-color: rgba(0, 0, 0, 0.7);
top: 50%;
margin-top:-72rpx;
padding: 0 20rpx;
justify-content: space-around;
}
.insu-tip text:nth-of-type(1){
font-size: 16px;
color: #ff7500;
padding-top: 30rpx;
}
.insu-tip text:nth-of-type(2){
font-size: 20px;
color: #ffffff;
padding-bottom: 20rpx;
}
.s-label{
position: absolute;
top: 0;
right: -38rpx;
width: 136rpx;
height: 62rpx;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
background-color: #f87120;
}
.insu-bg image{
width: 100%;
height: 208rpx;
}
.insu-des{
/* padding-top: 30rpx; */
display: flex;
color: #888888;
justify-content: space-between;
}
.des{
flex-basis: 400rpx;
flex-grow: 0;
flex-shrink: 0;
}
.insu-mon text:nth-of-type(1){
color: #ff6d00;
font-size: 60rpx;
}
.insu-mon text:nth-of-type(2){
color: #ff6d00;
}
\ No newline at end of file
const { api, mapApi, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation} = require('../../lib/util.js')
Page({
data: {
alarMsgShowRead:0,
page: 1,//当前页面
hasMorePage: false,//更多页面
alarmMsg: [],//消息列表
imgDot: imgName('dot.png'),
imgMore: imgName('seemore.png'),
imgHasalarm: imgName('hasalarm.png'),
imgHasmes: imgName('hasmes.png'),
imgNoalarm: imgName('noalarm.png'),
imgNomes: imgName('nomes.png'),
},
onLoad: function () {
this.getMsgList(1)
},
//显示报警
showAlarm(){
},
//拉取消息列表
getMsgList(page,success){
let that = this
let curPage = page || this.data.page
let user = wx.getStorageSync('user').userMapp
let device = wx.getStorageSync('device')
api.get('alarmRecord/getList.json', { curPage, userId: user.id, frameNo: device.frameNo})
.then(res => {
console.log('getList', res)
let alarmMsg = res.items.map(item => {
// item.startPosition = String(item.startPosition).slice(0, 5)
// item.endPosition = String(item.endPosition).slice(0, 5)
// item.useTime = new Date(item.endDate - item.startDate).getSeconds() + 1
// item.startDate = new Date(item.startDate).toLocaleString()
// item.endDate = new Date(item.endDate).toLocaleString()
// item.useMileage = ((item.endMileage - item.startMileage) / 1000).toFixed(2)
return item
})
if (curPage == 1) {
this.setData({
alarmMsg,
page: curPage + 1,
hasMorePage: res.totalPage > curPage
})
} else {
let newArrays = that.data.alarmMsg.concat(alarmMsg)
this.setData({
alarmMsg: newArrays,
page: curPage + 1,
hasMorePage: res.totalPage > curPage
})
}
success && success()
})
.catch(err => {
alertTip(err)
})
},
onPullDownRefresh(){
this.getMsgList(1,()=>{
wx.stopPullDownRefresh()
})
}
})
\ No newline at end of file
{"enablePullDownRefresh":true,"navigationBarTitleText": "消息中心"}
\ No newline at end of file
<view class='msg-body' wx:if='{{alarmMsg.length!=0}}'>
<block wx:for='{{alarmMsg}}'>
<view class='msg-item' id='{{item.id}}' data-read='{{item.msgStatus}}' catchtap='showAlarm'>
<image class='alarm' src='{{imgNoalarm}}'></image>
<view class='msg-content'>
<view>{{item.title}}</view>
<view>
<text>{{item.content}}</text>
<text>{{item.msgTime}}</text>
</view>
</view>
<image src='{{imgMore}}' class='more'></image>
</view>
</block>
<view class='btn' wx:if='{{hasMorePage}}'>
<button catchtap='getMsgList'>加载更多</button>
</view>
</view>
<view wx:else class='des'>当前没有报警记录</view>
\ No newline at end of file
.des{
text-align: center;
font-size: 30rpx;
padding-top: 22rpx;
color: #d7193c;
}
\ No newline at end of file
const { api, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
Page({
data: {
imgHardOn: imgName('security_settings_on_active.png'),
imgHardOff: imgName('security_settings_on_black.png'),
imgStandardOn: imgName('security_settings_standard_active.png'),
imgStandardOff: imgName('security_settings_standard_black.png'),
imgOn: imgName('security_settings_off_active.png'),
imgOff: imgName('security_settings_off_black.png'),
imgWxOn: imgName('security_settings_wx_active.png'),
imgWxOff: imgName('security_settings_wx_black.png'),
imgPhoneOn: imgName('security_settings_telephone_active.png'),
imgPhoneOff: imgName('security_settings_telephone_black.png'),
checkOn: imgName('security_settings_unchecked_active.png'),
checkOff: imgName('security_settings_unchecked.png'),
imgMore: imgName('security_settings_more_white.png'),
imgMoreAction: imgName('chevrons_white.png'),
imgVoiceLow: imgName('voice.png'),
imgVoiceHign: imgName('voice2.png'),
settings:{
remindermode:1,
weixin:true,
phone:false
},
voiceNum: 50,
},
onLoad: function () {
console.log('welcome')
},
onShow: function () {
this.setData({
voiceNum: wx.getStorageSync('voiceNum')
})
this.getAlarmSetting()
},
getAlarmSetting(){
let that = this
api.post('api/user/userConfigInfo.json')
.then(res=>{
console.log(res)
let datamodel = res.data
if (!datamodel.telephonealarmnoti){
api.post('api/user/updateUserConfig.json', { userid: wx.getStorageSync('user').userId, telephonealarmnoti: true })
.then(res => {
that.getAlarmSetting()
})
.catch(err => {
alertTip(err)
})
}
that.setData({
settings: {
remindermode: datamodel.remindermode,
weixin: datamodel.wechatnotice,
phone: datamodel.telephonealarmnoti
}
})
})
.catch(err=>{
alertTip(err)
})
},
getWxAlarm(){
api.post('api/user/isFirstOpenWeChat.json')
.then(res=>{
console.log(res.data)
if(!res.data){
alertTip('未关注公众号')
}
})
.catch(err=>{
alertTip(err)
})
},
setSecure(e){
let This=this
api.post('api/user/updateUserConfig.json', {userid: wx.getStorageSync('user').userId,...e.currentTarget.dataset})
.then(res => {
This.getAlarmSetting()
})
.catch(err => {
alertTip(err)
})
},
//声音变化
voiceChange(e){
let that=this
api.post('api/vehicle/volume.json', { para: String(e.detail.value)})
.then(res => {
wx.setStorageSync('voiceNum', e.detail.value)
})
.catch(err => {
wx.setStorageSync('voiceNum', e.detail.value)
})
},
settingDetail(){
wx.navigateTo({
url: '/pages/user_alarm_detail_setting/user_alarm_detail_setting',
})
}
})
\ No newline at end of file
{}
\ No newline at end of file
<view>
<view class='set-box'>
<view class='setting-title'>
<text class='bar'></text>
<text class='title'>车辆状态提醒模式</text>
</view>
<view class='setting-item'>
<view class='box-item' catchtap='setSecure' data-remindermode='1'>
<image src='{{settings.remindermode==1||settings.remindermode==2?imgHardOn:imgHardOff}}'></image>
<view class='text-mode'>
<text class='mode-main'>警戒模式</text>
<text class='mode-des'>所有检测到的状态都会及时通知。</text>
</view>
<image src='{{settings.remindermode==1||settings.remindermode==2?checkOn:checkOff}}'></image>
</view>
<!-- <view class='box-item' catchtap='setSecure' data-remindermode='2'>
<image src='{{settings.remindermode==2?imgStandardOn:imgStandardOff}}'></image>
<view class='text-mode'>
<text class='mode-main'>标准模式</text>
<text class='mode-des'>仅检测到风险状态时提醒。</text>
</view>
<image src='{{settings.remindermode==2?checkOn:checkOff}}'></image>
</view> -->
<view class='box-item' catchtap='setSecure' data-remindermode='3'>
<image src='{{settings.remindermode==3?imgOn:imgOff}}'></image>
<view class='text-mode'>
<text class='mode-main'>关闭通知</text>
<text class='mode-des'>关闭通知后您将无法收到车辆报警信息,请慎重操作。</text>
</view>
<image src='{{settings.remindermode==3?checkOn:checkOff}}'></image>
</view>
<view class='box-item clear-bottom' catchtap='settingDetail'>
<image src='{{imgMore}}'></image>
<view class='text-mode'>
<text class='mode-main'>更多设置</text>
<text class='mode-des'>忽略相同的设置、提醒时长设置</text>
</view>
<view class='more'>
<image src='{{imgMoreAction}}' class='more-img'></image>
</view>
</view>
</view>
</view>
<view class='set-box'>
<view class='setting-title'>
<text class='bar'></text>
<text class='title'>报警通知设置</text>
<view class='test-alarm'>测试报警</view>
</view>
<view class='setting-item'>
<view class='box-item' catchtap='getWxAlarm'>
<image src='{{settings.weixin?imgWxOn:imgWxOff}}'></image>
<view class='text-mode'>
<text class='mode-main'>微信报警通知</text>
<text class='mode-des'>通过微信公众号(请关注微信公众号)</text>
</view>
<image src='{{settings.weixin?checkOn:checkOff}}'></image>
</view>
<view class='box-item'>
<image src='{{settings.phone?imgPhoneOn:imgPhoneOff}}'></image>
<view class='text-mode'>
<text class='mode-main'>电话报警通知</text>
<text class='mode-des'>通过来电发送报警通知,每月6次免费</text>
</view>
<image src='{{settings.phone?checkOn:checkOff}}'></image>
</view>
<view class='tip'>
<text>提示:车辆网服务到期的车辆不会推送报警信息</text>
</view>
</view>
</view>
<view class='set-box'>
<view class='setting-title'>
<text class='bar'></text>
<text class='title'>车辆音量设置</text>
</view>
<view class='setting-item'>
<view class='voice-item'>
<image src='{{imgVoiceLow}}'></image>
<slider class='voice' bindchange="voiceChange" activeColor='#ffd200' step="5" value='{{voiceNum}}'/>
<image src='{{imgVoiceHign}}'></image>
</view>
</view>
</view>
</view>
\ No newline at end of file
page{
background-color: #f7f7f7;
border-top: 1px solid #ebebeb;
}
.set-box{
background-color: #ffffff;
}
.setting-title{
display: flex;
align-items: center;
height: 90rpx;
box-sizing: border-box;
font-size: 34rpx;
border-bottom: 1px solid #ebebeb;
}
.setting-title .bar{
display: inline-block;
height:34rpx;
border-left: 3px solid #d7193c;
margin: 0 26rpx 0 30rpx;
flex: 0 0 auto;
}
.setting-title .title{
flex: 1 0 auto;
}
.setting-title .test-alarm{
padding: 13rpx 30rpx;
border: 2px solid #cccccc;
border-radius: 28rpx;
font-size: 24rpx;
line-height: 24rpx;
color: #cccccc;
margin-right: 28rpx;
flex: 0 0 auto;
}
.setting-item{
padding-left: 50rpx;
margin-bottom: 14px;
}
.box-item{
display: flex;
box-sizing: border-box;
align-items: center;
padding: 20rpx 40rpx 20rpx 0;
border-bottom: 1px solid #ebebeb;
}
.box-item image:nth-of-type(1){
width: 50rpx;
height: 50rpx;
flex:0 0 auto;
margin-right: 26rpx;
}
.box-item image:nth-of-type(2),.more{
width: 50rpx;
height: 50rpx;
flex:0 0 auto;
}
.more{
display: flex;
justify-content: center;
align-items: center;
}
.more image:nth-of-type(1){
margin-right: 0;
}
.box-item image:nth-of-type(1).more-img{
width: 16rpx;
height: 30rpx;
}
.text-mode{
flex: 1 0 auto;
display: flex;
width: 468rpx;
flex-direction: column;
justify-content: space-between;
}
.mode-main{
color: #000000;
font-size: 32rpx;
padding-bottom: 12rpx;
}
.mode-des{
font-size: 22rpx;
color:#999999;
}
.tip{
height: 62rpx;
color: #d7193c;
font-size: 22rpx;
line-height: 62rpx;
}
.clear-bottom{
border-bottom: none;
}
.voice-item{
display:flex;
box-sizing:border-box;
align-items:center;
padding:20rpx 40rpx 20rpx 0;
}
.voice-item image:nth-of-type(1){
width: 24rpx;
height: 40rpx;
flex: 0 0 auto;
}
.voice-item image:nth-of-type(2){
width: 50rpx;
height: 40rpx;
flex: 0 0 auto;
}
.voice{
flex: 1 0 auto;
}
\ No newline at end of file
const { api, mockApi, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser, userLocation } = require('../../lib/util.js')
let months={
'01': '一月',
'02': '二月',
'03':'三月',
'04': '四月',
'05': '五月',
'06': '六月',
'07': '七月',
'08': '八月',
'09': '九月',
'10': '十月',
'11': '十一月',
'12': '十二月',
}
Page({
data: {
msg: 'welcome',
er:imgName('erwei.png'),
imgHead: imgName('journey.jpg'),
imgLogo: imgName('logo.png'),
imgArrowUp: imgName('arrowup.png'),
imgArrowDown: imgName('arrowdown.png'),
imgLoction: imgName('showloc.png'),
imgRoad: imgName('showroad.png'),
imgAlarm: imgName('timeline_remind_black.png'),
detailList: [],
page: 1,//当前页面
hasMorePage: false,//更多页面
},
onLoad: function () {
// this.getTotalMileage()
// this.getDaysMileage()
this.getList(1)
},
onShow: function () {
},
//获取行程记录
getList(page){
let that = this
let curPage = page || this.data.page
let user = wx.getStorageSync('user').userMapp
let device = wx.getStorageSync('device')
api.get('tripRecord/getList.json', {
// mockApi.get('http://result.eolinker.com/t2TvftRd7db394452f6fdee0541724f3fdde187fc6c117d?uri=xingcehgn', {
userId: user.id,
frameNo: device.frameNo
})
.then(res => {
console.log('getList', res)
let detailList = res.data.map(item => {
item.startPosition = String(item.startPosition).slice(0, 5)
item.endPosition = String(item.endPosition).slice(0, 5)
item.useTime = new Date(item.endDate - item.startDate).getSeconds() + 1
item.startDate = new Date(item.startDate).toLocaleString()
item.endDate = new Date(item.endDate).toLocaleString()
item.useMileage = ((item.endMileage - item.startMileage) / 1000).toFixed(2)
return item
})
if (curPage == 1) {
this.setData({
detailList,
page: curPage + 1,
hasMorePage: res.totalPage > curPage
})
} else {
let newArrays = that.data.detailList.concat(detailList)
this.setData({
detailList: newArrays,
page: curPage + 1,
hasMorePage: res.totalPage > curPage
})
}
console.log(res.totalPage, curPage)
})
.catch(err => {
console.log(err)
})
},
//显示行程
getTrack(e){
let id=e.currentTarget.id
wx.navigateTo({
url: `/pages/path_detail/path_detail?id=${id}`,
})
}
})
\ No newline at end of file
{
"navigationBarTitleText": "行程记录"
}
\ No newline at end of file
<!-- <view class='travel-title'>
<image class='bg' src='{{imgHead}}'></image>
<image class='logo' src='{{imgLogo}}'></image>
<view class='mileage'>
<text>{{totalMileage}}km</text>
<text>总行驶里程</text>
</view>
</view> -->
<!-- <view class='day'>
<view>
<text>{{item.year}}年</text>
<text>{{item.month}}</text>
</view>
<view class='travel-day {{item.open?"active":""}}'>{{item.day}}</view>
<view catchtap='getHoursMileage' id='{{item.dateTime}}' class='{{item.open?"active":""}}'>
<text>里程:{{item.totalMileage}}km 时间:{{item.travelTime}}分钟</text>
<image src='{{item.open?imgArrowUp:imgArrowDown}}'></image>
</view>
</view> -->
<view class='bar-first' wx:if='{{detailList.length!=0}}'>
<block wx:for='{{detailList}}'>
<view class='min' wx:key='{{item.id}}' id='{{item.id}}' catchtap='getTrack'>
<view class='h-time'>
<view>{{item.startDate}}</view>
</view>
<view class='detail'>
<view class='detail-msg'>
<view class='detail-road'>
<text>{{item.startPosition}}</text>
<image src='{{imgRoad}}'></image>
<text>{{item.endPosition}}</text>
</view>
<view class='detail-mile'>
<text>{{item.useMileage}}km</text>
<text>{{item.useTime}}分钟</text>
<text>{{item.averageSpeed||"0.0"}}km/h</text>
</view>
</view>
<view class='detail-img' catchtap='showTrip' id='{{item.tripId}}'>
<image src='{{imgLoction}}'></image>
</view>
</view>
</view>
</block>
<view class='btn' wx:if='{{hasMorePage}}'>
<button catchtap='getList'>加载更多</button>
</view>
</view>
<view wx:else class='des'>当前没有行程记录</view>
\ No newline at end of file
page{
width: 100%;
}
.min{
/* height: 64rpx; */
display: flex;
align-items: center;
margin-top: 28rpx;
padding: 0 20rpx;
}
.day>view:nth-of-type(1),.min>view:nth-of-type(1){
width: 220rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.min>view:nth-of-type(1){
color: #cccccc;
}
.day>view:nth-of-type(2),.min>view:nth-of-type(2){
height: 64rpx;
background-color: #f7f7f7;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20rpx;
position: relative;
font-size: 24rpx;
border-radius: 6rpx;
flex: 1 0 auto;
}
.min>view:nth-of-type(2){
height: 91rpx;
}
.day>view:nth-of-type(3).active,.day>view:nth-of-type(2).active{
border: none;
background-color: #d7193c;
}
.day>view:nth-of-type(3).active::before{
border-right: 14rpx solid #d7193c;
}
.day>view:nth-of-type(3)::before,.min>view:nth-of-type(2)::before{
content: '';
position:absolute;
left:-12rpx;
border-right: 14rpx solid #f7f7f7;
border-left: 0;
border-top: 12rpx solid transparent;
border-bottom: 12rpx solid transparent;
}
.day>view:nth-of-type(3) image{
width: 25rpx;
height: 16rpx;
}
.min>view:nth-of-type(2){
box-sizing: border-box;
}
.detail-msg{
height: 100%;
display: flex;
flex: 1 0 auto;
flex-direction: column;
justify-content: space-around;
}
.detail-mile text{
color: #ababab;
}
.detail-road{
text-align: center;
}
.detail-road image{
width: 32rpx;
height: 17rpx;
margin: 0 30rpx;
}
.detail-img{
margin-left: 30rpx;
}
.detail-img image{
width: 49rpx;
height: 49rpx;
}
.detail-mile{
display: flex;
justify-content: space-between;
}
.alarm view text{
padding-left: 32rpx;
}
.btn{
padding: 30rpx;
}
.btn button{
background-color: #d7193c;
}
.des{
text-align: center;
font-size: 30rpx;
padding-top: 22rpx;
color: #d7193c;
}
\ No newline at end of file
const { api, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser } = require('../../lib/util.js')
Page({
data: {
title:'智租科技',
titleDes:'这是一段描述',
//图片
img_logo: imgName('logo.png'),
icon: imgName('icon.png')
},
onLoad: function () {
this.readyLogin()
console.log('welcome')
},
onShow: function () {
console.log('welcome show')
},
readyLogin(){
var _this=this
//登录
wxLogin()
.then(code => {
wx.request({
url: api('user/loginCode'),
data: { code },
success: function (res) {
if (res.statusCode != 200) {
alertTip('loginCode请求失败')
return
}
if(res.data.ok){
console.log('openid', res.data.data.openid)
}else{
alertTip(res.data.msg)
}
// _this.readyUserInfo()
},
fail: function (res) {
alertTip('loginCode请求失败:服务器异常')
}
})
})
.catch(err => {
alertTip(err)
})
},
//param:authAgain 手动授权
readyUserInfo(authAgain){
//获取用户信息
getUserInfo()
.then(userinfo => {
// console.log('用户信息', userinfo)
wx.setStorageSync('userinfo', userinfo)
//校验用户是否存在,上传用户信息,获取用户在逗哈状态
wx.request({
url: api('user/login'),
data: { userinfo },
method: 'POST',
success: function (res) {
if (res.statusCode != 200) {
alertTip('login请求失败')
return
}
console.log('欢迎',res)
if(!res.data.ok){
alertTip(res.data.msg)
return
}
//判断有没有注册 绑定手机号
let userData=res.data.data
//存储userid
wx.setStorageSync('userId', userData.userId)
if(userData.register==false){
wx.showModal({
title: '',
content: '检测到您的账号还未绑定手机号,请绑定手机号',
confirmText:'绑定手机',
success(res) {
if(res.confirm){
wx.redirectTo({
url: '/pages/register/register?userId=' + userData.userId,
})
}
}
})
return
}
// 判断绑定产品没有
if (userData.hasBindDevice){
wx.redirectTo({
url: '/pages/user_index/user_index',
})
return
}else{
wx.redirectTo({
url: '/pages/device_bind/device_bind',
})
return
}
},
fail: function (res) {
alertTip('login请求失败:请检查网络')
}
})
})
.catch(err => {
console.log('用户信息错误', err)
authAgain && authAgain('需要授权用户信息才能正常使用,点击确定去授权')
})
},
auth(){
this.readyUserInfo(authAgainByUser)
},
test(e){
console.log(e.detail)
}
})
\ No newline at end of file
{}
\ No newline at end of file
<view class='container'>
<scroll-view class='read' scroll-y>
<image class='logo' src='{{img_logo}}'></image>
<view class='tle'>
<view>{{title}}</view>
<view>{{titleDes}}</view>
</view>
<view class='des'>
</view>
</scroll-view>
<view class='login' bindtap='auth'>登录</view>
</view>
\ No newline at end of file
page{
height: 100%;
}
.container{
height: 100%;
background-color: #ffffff;
padding: 0 30rpx;
}
.read{
height: 400rpx;
text-align: center;
}
.logo{
width: 168rpx;
height: 153rpx;
margin-top: 80rpx;
}
.tle{
margin-top: 8rpx;
}
.tle view{
margin-top: 28rpx;
}
.des{
}
.login{
margin-top: 60rpx;
background-color: #1aad19;
width: 100%;
padding: 30rpx 0;
border-radius: 12rpx;
font-size: 18px;
color: #ffffff;
text-align: center
}
\ No newline at end of file
const { api, imgName, getUserInfo, wxLogin, alertTip, authAgainByUser } = require('../../lib/util.js')
let timer=null
Page({
data: {
title:'智租科技',
titleDes:'这是一段描述',
//图片
imgLogo: imgName('logo.png'),
imgPerson: imgName('sign_in_phone_white.png'),
imgLock: imgName('sign_in_password_white.png'),
userTypes: [
{ value: 0, name: '公司用户' },
{ value: 1, name: '个人用户' }
],
companyArray:['未获取'],
companyIndex: 0,
pointArray: ['未获取'],
pointIndex: 0,
id:null,//数据id
userType:null,
dataError:true,
user:null,
hasCar:null,//用车
login:true,//true login 页面 false 登录成功
status: 'normal'//normal正常 auth审核中 authFail审核驳回
},
onLoad: function () {
// wx.removeStorageSync('user')
},
onUnload(){clearInterval(timer)},
onHide() { clearInterval(timer)},
//登录
formSubmit(e){
if (!/^1\d{10}/.test(e.detail.value.mobile)) {
alertTip('请输入正确的手机号!')
return false
}
// if (!/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,}$/.test(e.detail.value.password)) {
// alertTip('请输入6-12位包含数字和字母的密码!')
// return false
// }
if (!e.detail.value.password) {
alertTip('请输入密码!')
return false
}
let that=this
api.get('user/pass/logon',e.detail.value)
.then(res => {
console.log(res)
let {userMapp}=res.data
wx.setStorageSync('user', res.data)
that.setData({
login: false,
user: userMapp,
hasCar: userMapp.isUseVehicle
})
//个租
if (userMapp.userType == 1 && that.data.hasCar == 1){
//有使用的车辆 跳到用车
wx.redirectTo({
url: '/pages/user_index/user_index',
})
return
}
//无车团个租判断
switch (userMapp.siteAuditState){
case 1:
//已提交审核 中。。
that.setData({
status:'auth'
})
clearInterval(timer)
timer = setInterval(() => {
that.getStatus()
}, 5000)
break;
case 2:
//审核 过。。
//存储用户类型,以这个为准
let user = wx.getStorageSync('user')
user.userMapp.userType = 0
wx.setStorageSync('user', user)
if (that.data.hasCar==1){
//有使用的车辆 跳到用车
wx.redirectTo({
url: '/pages/user_index/user_index',
})
return
}else{
wx.redirectTo({
url: '/pages/device_bind/device_bind',
})
}
break;
case 3:
//审核 驳。。
that.setData({
status: 'authFail'
})
break;
default:
//正常 申请页面
that.setData({
status: 'normal'
})
}
/**data:{
token:'fef',
userMapp:{},
}*/
})
.catch(err => {
alertTip(err)
})
},
forgetPassword() {
wx.navigateTo({
url: '/pages/forgetpassword/forgetpassword',
})
},
register() {
wx.navigateTo({
url: '/pages/register2/register2',
})
},
giveUp(){
//放弃申请
let that = this
let { id } = that.data
if (!id) {
alertTip('请稍后重试')
return
}
wx.showModal({
title: '提示',
content: '是否放弃申请',
success: function (res) {
if (res.confirm) {
api.post('message/cancelJoin', {
id
}).then(res => {
that.setData({
status: 'normal'
})
clearInterval(timer)
}).catch(err => {
alertTip(err)
})
}
}
})
},
//用户选择
radioChange(e){
let userType=Number(e.detail.value)
this.setData({
userType
})
if (userType == 0 && this.data.companyArray[0] =='未获取'){
this.getCompany()
}
},
//租赁商变化
companyChange(e){
this.setData({
companyIndex: e.detail.value
})
let company = this.data.companyArray[this.data.companyIndex]
this.getPoints(company.id)
},
//站点变化
pointChange(e) {
this.setData({
pointIndex: e.detail.value
})
// let point = this.data.pointArray[this.data.pointIndex]
},
//获取租赁商
getCompany(){
let that =this
api.get('company/getByCompany')
.then(({ items }) => {
that.setData({
dataError: false,
companyArray: items
})
that.getPoints(items[0].id)
})
.catch(err => {
alertTip(err)
that.setData({
dataError:true
})
})
},
//获取站点
getPoints(companyId){
let that=this
api.get('site/getByCompanyId', { companyId})
.then(({ items }) => {
that.setData({
pointArray: items
})
})
.catch(err => {
alertTip(err)
that.setData({
dataError: true
})
})
},
// 提交申请
applyFor(){
if (this.data.pointArray.length==0) {
alertTip('该租赁商下不存在站点,请联系管理员')
return
}
let company = this.data.companyArray[this.data.companyIndex]
let point = this.data.pointArray[this.data.pointIndex]
let that=this
wx.showModal({
title: '提示',
content: `确定申请 ${company.companyName} 下站点:${point.companyName}`,
success: function (res) {
if (res.confirm) {
api.post('message/requestJoin',{
userId: that.data.user.id,
siteId: point.id,
companyId: company.id,
rentType:0
})
.then(res=>{
//申请成功
console.log(res)
that.setData({
status: 'auth'
})
//轮询状态
clearInterval(timer)
that.getStatus()
timer = setInterval(() => {
that.getStatus()
}, 5000)
})
.catch(err=>{
alertTip(err.message)
})
}
}
})
},
rentCar(e){
//个人用户开始租车
api.get('user/getByUserId',{userId:this.data.user.id})
.then(res=>{
console.log(res)
// 判断是否存在未完成订单
if (res.data.isNoPayMoney!=0){
// 付钱
wx.navigateTo({
url: '/pages/pay/pay?type=rent',
})
return
}
if (res.data.depositAmount == 0){
alertTip('租车前请先支付押金!',function(){
wx.navigateTo({
url: `/pages/pay/pay?type=deposite`,
})
})
return
}
let user = wx.getStorageSync('user')
user.userMapp.userType = 1
user.userMapp.depositAmount = res.data.depositAmount
wx.setStorageSync('user', user)
wx.navigateTo({
url: '/pages/device_bind/device_bind',
})
})
.catch(err=>{
console.error(err)
})
},
reApply(){
//重新申请
this.setData({
login: false,//true login 页面 false 登录成功
status: 'normal'//normal正常 auth审核中 authFail审核驳回
})
},
//登录页面
resetStatus(){
this.setData({
login: true,//true login 页面 false 登录成功
status: 'normal'//normal正常 auth审核中 authFail审核驳回
})
},
//获取审核状态
getStatus() {
let This = this
api.get('message/getMessageInfo', {
userId: This.data.user.id,
messageType: 7//用户申请加入站点
}, {}, true)
.then(res => {
let { state, id } = res.data
if (!This.data.id) {
This.setData({
id
})
}
switch (state) {
//待审核
case 0:
This.setData({
status: 'auth'
})
break;
//审核通过去首页
case 1:
clearInterval(timer)
//存储用户类型,以这个为准
let user = wx.getStorageSync('user')
user.userMapp.userType = 0
wx.setStorageSync('user', user)
wx.redirectTo({
url: '/pages/device_bind/device_bind',
})
break;
//审核驳回
case -1:
that.setData({
status: 'authFail'
})
clearInterval(timer)
break;
//正常页面
default:
This.setData({
status: 'normal',//normal 和 pedding
})
clearInterval(timer)
}
})
.catch(err => {
console.error(err)
})
},
//个租是否能租
personCanRent(){
return false
}
})
\ No newline at end of file
{
}
\ No newline at end of file
<!--登录和团个租站点选择 -->
<view class='con' wx:if='{{login}}'>
<image class='logo' src='{{imgLogo}}'></image>
<form class='from-login' bindsubmit="formSubmit" report-submit>
<view class='form-item'>
<label for='mobile'>
<image src='{{imgPerson}}'></image>
</label>
<input type='number' maxlength='11' id='mobile' name='mobile' 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='register'>立即注册</text>
<text catchtap='forgetPassword'>忘记密码?</text>
</view>
</view>
<view wx:else class='con'>
<image class='logo' src='{{imgLogo}}'></image>
<view wx:if='{{status=="normal"}}'>
<view class='phone-sure list'>
<text class='form-tip'>请选择:</text>
<radio-group class="radio-group" bindchange="radioChange">
<label class="radio" wx:for="{{userTypes}}" wx:key='{{item.name}}'>
<radio value="{{item.value}}" color='#d7193c' checked="{{userType===index}}"/>{{item.name}}
</label>
</radio-group>
</view>
<view wx:if='{{userType===0}}'>
<view wx:if='{{dataError}}'>
<view catchtap='getCompany'>获取站点信息失败,点击刷新</view>
</view>
<view wx:else>
<view class='phone-sure list'>
<text class='form-tip'>选择租赁商:</text>
<picker class='point' bindchange="companyChange" value="{{companyIndex}}" range-key='companyName' range="{{companyArray}}">
<view>{{companyArray[companyIndex].companyName}}</view>
</picker>
</view>
<view class='phone-sure list'>
<text class='form-tip'>选择站点:</text>
<picker class='point' bindchange="pointChange" value="{{pointIndex}}" range-key='companyName' range="{{pointArray}}">
<view>{{pointArray.length==0?'没有站点':pointArray[pointIndex].companyName}}</view>
</picker>
</view>
<button class='btn' catchtap='applyFor'>提交申请</button>
</view>
<!--提交完申请 进入一个提示页面 点击确定返回登录页面 该页面轮询 处理结果 -->
</view>
<view wx:if='{{userType===1}}'>
<button class='btn' catchtap='rentCar'>点击开始租车</button>
</view>
</view>
<view wx:if='{{status=="auth"}}'>
<view class='wait-auto'>等待站点同意授权中...</view>
<view class='giveup2 giveup'>
<text catchtap='giveUp'>放弃申请?</text>
</view>
</view>
<view wx:if='{{status=="authFail"}}'>
<view class='wait-auto'>您的申请被驳回了...</view>
<view class='giveup'>
<text catchtap='resetStatus'>返回登录</text>
<text catchtap='reApply'>重新申请?</text>
</view>
</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": false,
"es6": true,
"postcss": true,
"minified": true,
"newFeature": true
},
"compileType": "miniprogram",
"libVersion": "1.6.4",
"appid": "wx2adf345dae23b51b",
"projectname": "%E6%99%BA%E7%A7%9F%E4%BE%A0",
"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