静态
@@ -0,0 +1,2 @@
|
||||
project.config.json
|
||||
project.private.config.json
|
||||
@@ -1,2 +1,32 @@
|
||||
# XiaoChengXu-LiCheBao
|
||||
# 狸车宝项目
|
||||
|
||||
## 账号密码
|
||||
|
||||
wx71095d4049de3ed1
|
||||
a80eb6ed68d7bae2d804fe507a4522f7
|
||||
|
||||
//好店云
|
||||
wx8edd43f384bc39c4
|
||||
|
||||
测试账号:18050017004,没验证码
|
||||
|
||||
测试账号
|
||||
账号:18050017004
|
||||
验证码:888888
|
||||
|
||||
|
||||
## 状态码规范
|
||||
|
||||
|
||||
参数 | 类型 | 描述
|
||||
------------ | ------------- | ------------
|
||||
200 | Number | 成功状态码,服务器正常处理
|
||||
401 | Number | 认证信息失败,也就是token(ukey)失败
|
||||
402 | Number | 授权解密数据失败
|
||||
400 | Number | 服务端错误(除了40x中规定的错误状态,其他错误统一返回400)
|
||||
|
||||
|
||||
## 页面访问路径
|
||||
|
||||
/pages/login/index //登录
|
||||
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
import log from './commons/js/utils/log'
|
||||
App({
|
||||
onLaunch: function () {
|
||||
let that = this;
|
||||
this.updateVersion()
|
||||
wx.getSystemInfo({
|
||||
success(res) {
|
||||
that.globalData.statusBarHeight = res.statusBarHeight;
|
||||
that.globalData.screenHeight = res.screenHeight;
|
||||
that.globalData.screenWidth = res.screenWidth;
|
||||
if (res.platform == "devtools") {
|
||||
that.globalData.platform = "android";
|
||||
} else {
|
||||
that.globalData.platform = res.platform
|
||||
}
|
||||
}
|
||||
})
|
||||
wx.onMemoryWarning(function () {
|
||||
let getPath = getCurrentPages()
|
||||
let currentPage = getPath[getPath.length - 1]
|
||||
wx.reportAnalytics('outofmemory', {
|
||||
pages: getPath, //获取所有页面
|
||||
url: currentPage.route, //当前页面url
|
||||
options: currentPage.options //如果要获取url中所带的参数可以查看options
|
||||
})
|
||||
that.printErrorClient('filteroutofmemory')
|
||||
wx.reportMonitor('0', 500)
|
||||
wx.reLaunch(currentPage.route)
|
||||
})
|
||||
},
|
||||
onHide: function () {
|
||||
if (wx.canIUse('offMemoryWarning')) {
|
||||
wx.offMemoryWarning()
|
||||
// this.printErrorClient('offmemory')
|
||||
} else {
|
||||
this.printErrorClient('offmemorylowversion')
|
||||
console.warn('当前微信版本' + wx.getSystemInfoSync().SDKVersion + '过低,无法使用该功能,请升级到最新微信版本后重试。')
|
||||
}
|
||||
},
|
||||
onPageNotFound(res) {
|
||||
this.printErrorClient('404notfound',['错误信息:'+JSON.stringify(res)])
|
||||
if (res.path == 'pages/detail/detail') {
|
||||
this.errorPageRedirect('/pages/index/index', '抱歉,该页面已迁移,请在搜索页查询...')
|
||||
|
||||
} else if (res.path == 'pages/card/card' || res.path == 'pages/mine/mine') {
|
||||
console.log(1)
|
||||
this.errorPageRedirect('/pages/mine/index')
|
||||
} else {
|
||||
this.errorPageRedirect('/pages/index/index', '抱歉,该页面无法访问,正在回到首页...')
|
||||
}
|
||||
},
|
||||
initNum: 0,
|
||||
globalData: {
|
||||
loginRuning: false,
|
||||
loginCollect: [],
|
||||
userInfo: '',
|
||||
location: '',
|
||||
ukey: "",
|
||||
statusBarHeight: 20,
|
||||
screenHeight: 0,
|
||||
screenWidth: 0,
|
||||
platform: '',
|
||||
|
||||
},
|
||||
|
||||
setStorage: function (key, data, callback = function () {}, reject = function () {}) {
|
||||
try {
|
||||
wx.setStorageSync(key, data);
|
||||
this.globalData[key] = data;
|
||||
// console.log(`Method:setStorage(success)`);
|
||||
callback(data)
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
},
|
||||
getStorageByKey: function (key) {
|
||||
var storage;
|
||||
if (!!this.globalData[key]) {
|
||||
return this.globalData[key];
|
||||
} else {
|
||||
try {
|
||||
const value = wx.getStorageSync(key)
|
||||
if (value) {
|
||||
storage = value;
|
||||
return storage;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("getStorageByKey-fail:" + key);
|
||||
}
|
||||
}
|
||||
return !!storage ? storage : "";
|
||||
},
|
||||
errorPageRedirect(URL, TITLE = '正在跳转,请稍候...') {
|
||||
wx.showToast({
|
||||
title: TITLE,
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
success: function () {
|
||||
setTimeout(function () {
|
||||
wx.reLaunch({
|
||||
url: URL
|
||||
})
|
||||
}, 2000)
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 打印客户端信息
|
||||
*/
|
||||
printErrorClient(MSGNAME, ER = []) {
|
||||
log.setFilterMsg(MSGNAME)
|
||||
let pages = getCurrentPages() //获取加载的页面
|
||||
if(pages.length>0){
|
||||
let currentPage = pages[pages.length - 1] //获取当前页面的对象
|
||||
log.warn('当前页面:' + currentPage.route)
|
||||
log.info('路径:' + JSON.stringify(pages))
|
||||
}else{
|
||||
log.warn('当前页面不在app.json列表里')
|
||||
}
|
||||
let systemInfo = wx.getSystemInfoSync()
|
||||
log.info('设备型号:' + systemInfo.model)
|
||||
log.info('微信版本号:' + systemInfo.version)
|
||||
log.info('操作系统及版本:' + systemInfo.system)
|
||||
log.info('客户端平台:' + systemInfo.platform)
|
||||
log.info('客户端基础库版本:' + systemInfo.SDKVersion)
|
||||
log.info('地理位置的系统开关:' + systemInfo.locationEnabled)
|
||||
log.info('客户端Ukey:' + wx.getStorageSync('ukey'))
|
||||
log.info('客户端Userinfo:' + JSON.stringify(wx.getStorageSync('userInfo')))
|
||||
for(let i =0;i<ER.length;i++){
|
||||
log.info(ER[i])
|
||||
}
|
||||
},
|
||||
updateVersion() {
|
||||
const updateManager = wx.getUpdateManager()
|
||||
updateManager.onCheckForUpdate(function (res) {
|
||||
// 请求完新版本信息的回调
|
||||
console.log(res.hasUpdate)
|
||||
})
|
||||
updateManager.onUpdateReady(function () {
|
||||
wx.showModal({
|
||||
title: '更新提示',
|
||||
content: '新版本已经准备好,是否重启应用?',
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
|
||||
updateManager.applyUpdate()
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
updateManager.onUpdateFailed(function () {
|
||||
// 新版本下载失败
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,80 @@
|
||||
{
|
||||
"pages": [
|
||||
"pages/order/index",
|
||||
"pages/customer/index",
|
||||
"pages/index/index",
|
||||
"pages/login/index",
|
||||
"pages/web-view/index",
|
||||
"pages/mine/index",
|
||||
"pages/customer/addCard/index",
|
||||
"pages/customer/detail/index",
|
||||
"pages/order/register/index",
|
||||
"pages/order/detail/index"
|
||||
],
|
||||
"echarts": [
|
||||
{
|
||||
"root": "ecCanvas",
|
||||
"pages": [
|
||||
"pages/index/index"
|
||||
]
|
||||
}
|
||||
],
|
||||
"window": {
|
||||
"backgroundTextStyle": "light",
|
||||
"navigationBarBackgroundColor": "#fff",
|
||||
"navigationBarTitleText": "狸车宝",
|
||||
"navigationBarTextStyle": "black"
|
||||
},
|
||||
"tabBar": {
|
||||
"color": "#999999",
|
||||
"selectedColor": "#000000",
|
||||
"borderStyle": "black",
|
||||
"backgroundColor": "#ffffff",
|
||||
"list": [
|
||||
{
|
||||
"pagePath": "pages/index/index",
|
||||
"iconPath": "commons/images/tab-home.png",
|
||||
"selectedIconPath": "commons/images/tab-home-ac.png",
|
||||
"badge": false,
|
||||
"text": "首页"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/customer/index",
|
||||
"iconPath": "commons/images/tab-customer.png",
|
||||
"selectedIconPath": "commons/images/tab-customer-ac.png",
|
||||
"badge": false,
|
||||
"text": "客户"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/order/index",
|
||||
"iconPath": "commons/images/tab-order.png",
|
||||
"selectedIconPath": "commons/images/tab-order-ac.png",
|
||||
"badge": false,
|
||||
"text": "订单"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/mine/index",
|
||||
"iconPath": "commons/images/tab-mine.png",
|
||||
"selectedIconPath": "commons/images/tab-mine-ac.png",
|
||||
"badge": false,
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sitemapLocation": "sitemap.json",
|
||||
"usingComponents": {
|
||||
"lcb-msg": "/components/msg/index",
|
||||
"lcb-auth": "/components/auth/index",
|
||||
"lcb-navBar": "/components/navBar/navBar",
|
||||
"lcb-footer": "/components/footer/footer",
|
||||
"lcb-listmore": "/components/listMore/index",
|
||||
"QYWXcontact": "plugin://contactPlugin/cell",
|
||||
"kefuSuccess": "/components/kefuSuccess/index"
|
||||
},
|
||||
"plugins": {
|
||||
"contactPlugin": {
|
||||
"version": "1.4.0",
|
||||
"provider": "wx104a1a20c3f81ec2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
@-webkit-keyframes zoomIn {
|
||||
0% {
|
||||
opacity:0;
|
||||
-webkit-transform:scale3d(.3, .3, .3);
|
||||
transform:scale3d(.3, .3, .3)
|
||||
}
|
||||
50% {
|
||||
opacity:1
|
||||
}
|
||||
}
|
||||
@keyframes zoomIn {
|
||||
0% {
|
||||
opacity:0;
|
||||
-webkit-transform:scale3d(.3, .3, .3);
|
||||
transform:scale3d(.3, .3, .3)
|
||||
}
|
||||
50% {
|
||||
opacity:1
|
||||
}
|
||||
}
|
||||
.zoomIn {
|
||||
-webkit-animation-name:zoomIn;
|
||||
animation-name:zoomIn
|
||||
}
|
||||
|
||||
@-webkit-keyframes zoomOut {
|
||||
0% {
|
||||
opacity:1
|
||||
}
|
||||
50% {
|
||||
opacity:0;
|
||||
-webkit-transform:scale3d(.3, .3, .3);
|
||||
transform:scale3d(.3, .3, .3)
|
||||
}
|
||||
to {
|
||||
opacity:0
|
||||
}
|
||||
}
|
||||
@keyframes zoomOut {
|
||||
0% {
|
||||
opacity:1
|
||||
}
|
||||
50% {
|
||||
opacity:0;
|
||||
-webkit-transform:scale3d(.3, .3, .3);
|
||||
transform:scale3d(.3, .3, .3)
|
||||
}
|
||||
to {
|
||||
opacity:0
|
||||
}
|
||||
}
|
||||
.zoomOut {
|
||||
-webkit-animation-name:zoomOut;
|
||||
animation-name:zoomOut
|
||||
}
|
||||
|
||||
|
||||
@-webkit-keyframes slideInDown {
|
||||
0% {
|
||||
-webkit-transform:translate3d(0, -100%, 0);
|
||||
transform:translate3d(0, -100%, 0);
|
||||
visibility:visible
|
||||
}
|
||||
to {
|
||||
-webkit-transform:translateZ(0);
|
||||
transform:translateZ(0)
|
||||
}
|
||||
}
|
||||
@keyframes slideInDown {
|
||||
0% {
|
||||
-webkit-transform:translate3d(0, -100%, 0);
|
||||
transform:translate3d(0, -100%, 0);
|
||||
visibility:visible
|
||||
}
|
||||
to {
|
||||
-webkit-transform:translateZ(0);
|
||||
transform:translateZ(0)
|
||||
}
|
||||
}
|
||||
.slideInDown {
|
||||
-webkit-animation-name:slideInDown;
|
||||
animation-name:slideInDown
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
.bg-fff{background-color:#fff;}
|
||||
.bg-f6{background-color:#f6f6f6;}
|
||||
.bg-f7{background-color:#f7f7f7;}
|
||||
.bg-f8{background-color:#f8f8f8;}
|
||||
.bg-e4{background-color:#e4e4e4;}
|
||||
.bg-ccc{background-color:#ccc;}
|
||||
.bg-666{background-color:#666;}
|
||||
.bg-333{background-color:#333;}
|
||||
.bg-36afa2{background-color:#36afa2;}
|
||||
.bg-f9394d{background-color:#f9394d;}
|
||||
|
||||
.bg-000-op30{background-color:rgba(0,0,0,.3);}
|
||||
.bg-000-op50{background-color:rgba(0,0,0,.5);}
|
||||
.bg-000-op60{background-color:rgba(0,0,0,.6);}
|
||||
.bg-000-op80{background-color:rgba(0,0,0,.8);}
|
||||
|
||||
.bg-fff-op20{background-color:rgba(255,255,255,.2);}
|
||||
.bg-fff-op50{background-color:rgba(255,255,255,.5);}
|
||||
.bg-fff-op80{background-color:rgba(255,255,255,.8);}
|
||||
.bg-fff-op90{background-color:rgba(255,255,255,.9);}
|
||||
.bg-000-gradual-30-60{background-image:linear-gradient(rgba(0,0,0,.3),rgba(0,0,0,.6));}
|
||||
|
||||
.bg-f3f6fc{background-color:#f3f6fc;}
|
||||
.bg-fffaeb{background-color:#fffaeb;}
|
||||
.bg-f1f9f8{background-color:#f1f9f8;}
|
||||
.bg-fff6f8{background-color:#fff6f8;}
|
||||
@@ -0,0 +1,15 @@
|
||||
.bds-2-96dda2{border:#96dda2 2rpx solid;box-sizing:border-box;}
|
||||
.bts-20-f8{border-top:#f8f8f8 20rpx solid;box-sizing:border-box;}
|
||||
.bts-20-f7{border-top:#f7f7f7 20rpx solid;box-sizing:border-box;}
|
||||
|
||||
.bts-1-eb{border-top:#ebebeb 1rpx solid;box-sizing:border-box;}
|
||||
.bls-1-eb{border-left:#ebebeb 1rpx solid; box-sizing:border-box;}
|
||||
.brs-1-eb{border-right:#ebebeb 1rpx solid; box-sizing:border-box;}
|
||||
.bbs-1-eb{border-bottom:#ebebeb 1rpx solid; box-sizing:border-box;}
|
||||
.bds-1-eb{border:#ebebeb 1rpx solid; box-sizing:border-box;}
|
||||
.btd-1-eb{border-top:#ebebeb 1rpx dashed;box-sizing:border-box;}
|
||||
|
||||
.bds-7dbeeb{border:#7dbeeb 1rpx solid;box-sizing:border-box;}
|
||||
.bds-2-36afa2{border:#36afa2 2rpx solid;box-sizing:border-box;}
|
||||
|
||||
.last-b-none:last-child{border-bottom:none;}
|
||||
@@ -0,0 +1,13 @@
|
||||
.btn-border-36afa2{background:none;border:none;}
|
||||
.btn-border-36afa2::after{border:#36afa2 2rpx solid;}
|
||||
.btn-border-36afa2[disabled]{background:#ddd !important;border:none !important;color:#bbb !important;}
|
||||
.btn-border-36afa2[disabled]::after{border:#ddd 2rpx solid !important;}
|
||||
.btn-36afa2{background: #36afa2;border:none;}
|
||||
.btn-36afa2::after{border:none;}
|
||||
.btn-36afa2-hover{background:#2fa195;}
|
||||
.btn-36afa2[disabled]{background:#ddd !important;border:none !important;color:#bbb !important;}
|
||||
.btn-999{background:#999;border:none;}
|
||||
.btn-999::after{border:none;}
|
||||
.btn-999-hover{background:#a7a6a6;}
|
||||
.btn-999[disabled]{background:#999 !important;border:none !important;}
|
||||
.btn-inset-shadow{box-shadow:inset 0rpx 0rpx 10rpx 5rpx rgba(0, 0, 0, .2);}
|
||||
@@ -0,0 +1,14 @@
|
||||
.color-fff{color:#fff;}
|
||||
.color-f8{color:#f8f8f8;}
|
||||
.color-e4e4e4{color:#e4e4e4;}
|
||||
.color-333{color:#333;}
|
||||
.color-666{color:#666;}
|
||||
.color-777{color:#777;}
|
||||
.color-888{color:#888;}
|
||||
.color-999{color:#999;}
|
||||
.color-aaa{color:#aaa;}
|
||||
.color-bbb{color:#bbb;}
|
||||
.color-ccc{color:#ccc;}
|
||||
.color-f9394d{color:#f9394d;}
|
||||
.color-36afa2{color:#36afa2;}
|
||||
.color-00c800{color:#00c800;}
|
||||
@@ -0,0 +1,28 @@
|
||||
.font-10{font-size:16rpx;}
|
||||
.font-16{font-size:16rpx;}
|
||||
.font-18{font-size:18rpx;}
|
||||
.font-20{font-size:20rpx;}
|
||||
.font-22{font-size:22rpx;}
|
||||
.font-24{font-size:24rpx;}
|
||||
.font-26{font-size:26rpx;}
|
||||
.font-28{font-size:28rpx;}
|
||||
.font-30{font-size:30rpx;}
|
||||
.font-32{font-size:32rpx;}
|
||||
.font-34{font-size:34rpx;}
|
||||
.font-36{font-size:36rpx;}
|
||||
.font-38{font-size:38rpx;}
|
||||
.font-40{font-size:40rpx;}
|
||||
.font-42{font-size:42rpx;}
|
||||
.font-44{font-size:44rpx;}
|
||||
.font-48{font-size:48rpx;}
|
||||
.font-50{font-size:50rpx;}
|
||||
.font-52{font-size:52rpx;}
|
||||
.font-54{font-size:54rpx;}
|
||||
.font-56{font-size:56rpx;}
|
||||
.font-60{font-size:60rpx;}
|
||||
.font-66{font-size:66rpx;}
|
||||
.font-72{font-size:72rpx;}
|
||||
.font-75{font-size:75rpx;}
|
||||
.font-80{font-size:80rpx;}
|
||||
.font-90{font-size:90rpx;}
|
||||
.font-120{font-size:120rpx;}
|
||||
@@ -0,0 +1,17 @@
|
||||
.img-24x24{width:32rpx;height:32rpx;box-sizing:border-box;}
|
||||
.img-45x45{width:45rpx;height:45rpx;box-sizing:border-box;}
|
||||
.img-50x50{width:50rpx;height:50rpx;box-sizing:border-box;}
|
||||
.img-55x55{width:55rpx;height:55rpx;box-sizing:border-box;}
|
||||
.img-55x65{width:55rpx;height:65rpx;box-sizing:border-box;}
|
||||
.img-60x60{width:60rpx;height:60rpx;box-sizing:border-box;}
|
||||
.img-65x65{width:65rpx;height:65rpx;box-sizing:border-box;}
|
||||
.img-72x72{width:72rpx;height:72rpx;box-sizing:border-box;}
|
||||
.img-80x80{width:80rpx;height:80rpx;box-sizing:border-box;}
|
||||
.img-100x100{width:100rpx;height:100rpx;box-sizing:border-box;}
|
||||
.img-120x120{width:120rpx;height:120rpx;box-sizing:border-box;}
|
||||
.img-140x140{width:140rpx;height:140rpx;box-sizing:border-box;}
|
||||
.img-160x160{width:160rpx;height:160rpx;box-sizing:border-box;}
|
||||
.img-250x250{width:250rpx;height:250rpx;box-sizing:border-box;}
|
||||
.img-750x250{width:750rpx;height:250rpx;box-sizing:border-box;}
|
||||
|
||||
.img-h-200{height:200rpx;box-sizing:border-box;}
|
||||
@@ -0,0 +1,119 @@
|
||||
.h-100vh{height:100vh;}
|
||||
.h-30vh{height:30vh;}
|
||||
.h-70vh{height:70vh;}
|
||||
.minh-100vh{min-height:100vh;box-sizing:border-box;}
|
||||
.h-90vh{height:90vh;}
|
||||
|
||||
/*layout float*/
|
||||
.fn-clear:before,.fn-clear:after{content:"";display:table;}
|
||||
.fn-clear:after{clear:both;}
|
||||
.fn-clear{zoom:1;}
|
||||
.fn-fl{float:left;}
|
||||
.fn-fr{float:right;}
|
||||
.fn-hide{display:none;}
|
||||
|
||||
/*layout display*/
|
||||
.block{display:block;}
|
||||
.inline-block{display:inline-block;}
|
||||
|
||||
.overflowhidden{overflow:hidden;}
|
||||
.overflowXhidden{overflow-x:hidden;}
|
||||
.overflow-initial{overflow:initial;}
|
||||
.opacity-0{opacity:0;}
|
||||
.opacity-50{opacity:.5;}
|
||||
.opacity-80{opacity:.8;}
|
||||
|
||||
/*line-clamp*/
|
||||
.line-clamp-2{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;}
|
||||
.line-clamp-3{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden;}
|
||||
|
||||
/*layout flex*/
|
||||
.fn-flex{display:flex;flex-flow:row;align-items:stretch;}
|
||||
.fn-flex-center{align-items:center;}
|
||||
.fn-flex-item{display:block;flex:1;}
|
||||
.fn-flex-item.flexsize2{flex:2;}
|
||||
.fn-flex-item.flexsize3{flex:3;}
|
||||
.fn-flex-item.flexsize4{flex:4;}
|
||||
.fn-flex-item.flexsize5{flex:5;}
|
||||
.fn-flex-item.flexsize6{flex:6;}
|
||||
.fn-flex-item.flexsize7{flex:7;}
|
||||
.fn-flex-item.flexsize8{flex:8;}
|
||||
.fn-flex-item.flexsize9{flex:9;}
|
||||
.fn-flex-itemfixed{flex:0 0 auto;}
|
||||
.fn-flex-between{justify-content: space-between;}/*两端对齐*/
|
||||
.fn-flex-wrap{flex-wrap:wrap}/*多行*/
|
||||
|
||||
.wp20{width:20%;box-sizing:border-box;}
|
||||
.wp25{width:25%;box-sizing:border-box;}
|
||||
.wp33{width:33%;box-sizing:border-box;}
|
||||
.wp40{width:40%;box-sizing:border-box;}
|
||||
.wp45{width:45%;box-sizing:border-box;}
|
||||
.wp50{width:50%;box-sizing:border-box;}
|
||||
.wp60{width:60%!important;box-sizing:border-box;}
|
||||
.wp65{width:65%!important;box-sizing:border-box;}
|
||||
.wp70{width:70%!important;box-sizing:border-box;}
|
||||
.wp80{width:80%!important;box-sizing:border-box;}
|
||||
.wp90{width:90%;box-sizing:border-box;}
|
||||
.wp100{width:100%;box-sizing:border-box;}
|
||||
.wp110{width:110%;box-sizing:border-box;}
|
||||
.box-x-scroll{overflow-x:auto;}
|
||||
|
||||
.img-top-cover{background-repeat:no-repeat;background-position:center top;background-size:100% auto;}
|
||||
.img-center-cover{background-repeat:no-repeat;background-position:center center;background-size:100% auto;}
|
||||
.img-middle-cover{background-repeat:no-repeat;background-position:center center;background-size:auto 100%;}
|
||||
.img-fill-cover{background-repeat:no-repeat;background-position:center center;background-size:100% 100%;}
|
||||
.img-center-middle-100{position:absolute;top:50%;left:50%;max-width:100%;max-height:100%;transform:translate(-50%,-50%);}
|
||||
.fiximg{max-width:100%;}
|
||||
|
||||
.box-shadow-darkGray{box-shadow:0 0 10rpx rgba(0,0,0,.15);}
|
||||
.box-shadow-lightGray{box-shadow:0 0 10rpx rgba(0,0,0,.08);}
|
||||
|
||||
/*layer*/
|
||||
.content-pop-cover{position:fixed;top:0;bottom:0;right:0;left:0;background:rgba(0,0,0,0.6);z-index:999; }
|
||||
.content-pop{position:fixed;top:50%;left:50%;width:84%;transform:translate(-50%,-50%);z-index:1002;}
|
||||
|
||||
/*layout position*/
|
||||
.relative{position:relative;}
|
||||
.absolute{position:absolute;}
|
||||
.fixed{position:fixed;z-index:1;}
|
||||
.top--6{top:-6rpx;}
|
||||
.top-0{top:0;}
|
||||
.bottom-0{bottom:0;}
|
||||
.bottom-120{bottom:120rpx;}
|
||||
.bottom--67{bottom:-67rpx;}
|
||||
.left-0{left:0;}
|
||||
.right-0{right:0;}
|
||||
.right--10{right:-10rpx;}
|
||||
.left-p50{left:50%;}
|
||||
.z-index-0{z-index:0;}
|
||||
.z-index-1{z-index:1;}
|
||||
.z-index-2{z-index:2;}
|
||||
.z-index-3{z-index:3;}
|
||||
.z-index-4{z-index:4;}
|
||||
.z-index-9999{z-index:9999;}
|
||||
.box-center-middle{top:50%;left:50%;transform:translate(-50%,-50%);}
|
||||
.box-middle{top:50%;transform:translate(0,-50%);}
|
||||
.box-center{left:50%;transform:translate(-50%,0);}
|
||||
|
||||
.container{min-height:calc(100vh - 110rpx);}
|
||||
|
||||
.icon-jiazai{display:inline-block;-webkit-animation:rotate linear 1.2s infinite;animation:rotate linear 1.2s infinite;}
|
||||
@-webkit-keyframes rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}
|
||||
|
||||
.line-height-11{line-height:1.1;}
|
||||
.line-height-12{line-height:1.2;}
|
||||
.line-height-13{line-height:1.3;}
|
||||
.line-height-14{line-height:1.4;}
|
||||
.line-height-15{line-height:1.5;}
|
||||
.line-height-16{line-height:1.6;}
|
||||
.line-height-17{line-height:1.7;}
|
||||
.line-height-18{line-height:1.8;}
|
||||
.line-height-19{line-height:1.9;}
|
||||
.line-height-20{line-height:2;}
|
||||
.rich-text-img{display:bolck;max-width:100% !important;height:auto !important;margin:40rpx 0 20rpx 0 !important;}
|
||||
|
||||
.height-100{height:100rpx;}
|
||||
.height-190{height:190rpx;}
|
||||
.height-240{height:240rpx;}
|
||||
.tabmenu{line-height:80rpx;}
|
||||
.tabmenu.active::before{display:block;position:absolute;bottom:0;left:50%;width:30rpx;height:4rpx;margin-left:-15rpx;content:"";background-color:#36afa2;}
|
||||
@@ -0,0 +1,74 @@
|
||||
.mt0{margin-top:0;}
|
||||
.mt1{margin-top:1rpx;}
|
||||
.mt2{margin-top:2rpx;}
|
||||
.mt5{margin-top:5rpx;}
|
||||
.mt7{margin-top:7rpx;}
|
||||
.mt8{margin-top:8rpx;}
|
||||
.mt9{margin-top:9rpx;}
|
||||
.mt10{margin-top:10rpx;}
|
||||
.mt15{margin-top:15rpx;}
|
||||
.mt20{margin-top:20rpx;}
|
||||
.mt25{margin-top:25rpx;}
|
||||
.mt30{margin-top:30rpx;}
|
||||
.mt40{margin-top:40rpx;}
|
||||
.mt50{margin-top:50rpx;}
|
||||
.mt60{margin-top:60rpx;}
|
||||
.mt68{margin-top:68rpx;}
|
||||
.mt75{margin-top:75rpx;}
|
||||
.mt80{margin-top:80rpx;}
|
||||
.mt90{margin-top:90rpx;}
|
||||
.mt110{margin-top:110rpx;}
|
||||
.mt120{margin-top:120rpx;}
|
||||
.mt150{margin-top:150rpx;}
|
||||
.mt190{margin-top:190rpx;}
|
||||
.ml-1{margin-left:-1rpx;}
|
||||
.ml5{margin-left:5rpx;}
|
||||
.ml10{margin-left:10rpx;}
|
||||
.ml15{margin-left:15rpx;}
|
||||
.ml20{margin-left:20rpx;}
|
||||
.ml25{margin-left:25rpx;}
|
||||
.ml30{margin-left:30rpx;}
|
||||
.ml35{margin-left:35rpx;}
|
||||
.ml40{margin-left:40rpx;}
|
||||
.ml45{margin-left:45rpx;}
|
||||
.ml50{margin-left:50rpx;}
|
||||
.ml60{margin-left:60rpx;}
|
||||
.ml70{margin-left:70rpx;}
|
||||
.ml80{margin-left:80rpx;}
|
||||
.ml110{margin-left:110rpx;}
|
||||
.ml140{margin-left:140rpx;}
|
||||
.ml150{margin-left:150rpx;}
|
||||
.ml160{margin-left:160rpx;}
|
||||
.ml180{margin-left:180rpx;}
|
||||
.ml200{margin-left:200rpx;}
|
||||
.mr-20{margin-right:-20rpx;}
|
||||
.mr-30{margin-right:-30rpx;}
|
||||
.mr5{margin-right:5rpx;}
|
||||
.mr10{margin-right:10rpx;}
|
||||
.mr11{margin-right:11rpx;}
|
||||
.mr15{margin-right:15rpx;}
|
||||
.mr18{margin-right:18rpx;}
|
||||
.mr20{margin-right:20rpx;}
|
||||
.mr25{margin-right:25rpx;}
|
||||
.mr28{margin-right:28rpx;}
|
||||
.mr30{margin-right:30rpx;}
|
||||
.mr35{margin-right:35rpx;}
|
||||
.mr40{margin-right:40rpx;}
|
||||
.mr50{margin-right:50rpx;}
|
||||
.mr60{margin-right:60rpx;}
|
||||
.mr70{margin-right:70rpx;}
|
||||
.mr150{margin-right:150rpx;}
|
||||
.mr160{margin-right:160rpx;}
|
||||
.mr170{margin-right:170rpx;}
|
||||
.mr180{margin-right:180rpx;}
|
||||
.mr190{margin-right:190rpx;}
|
||||
.mb10{margin-bottom:10rpx;}
|
||||
.mb15{margin-bottom:15rpx;}
|
||||
.mb20{margin-bottom:20rpx;}
|
||||
.mb25{margin-bottom:25rpx;}
|
||||
.mb30{margin-bottom:30rpx;}
|
||||
.mb40{margin-bottom:40rpx;}
|
||||
.mb60{margin-bottom:60rpx;}
|
||||
.mb100{margin-bottom:100rpx;}
|
||||
.mb120{margin-bottom:120rpx;}
|
||||
.mb200{margin-bottom:200rpx;}
|
||||
@@ -0,0 +1,115 @@
|
||||
.inner8{padding:8rpx;}
|
||||
.inner10{padding:10rpx;}
|
||||
.inner20{padding:20rpx;}
|
||||
.inner25{padding:25rpx;}
|
||||
.inner30{padding:30rpx;}
|
||||
.inner40{padding:40rpx;}
|
||||
.inner60{padding:60rpx;}
|
||||
|
||||
.pt0{padding-top:0;}
|
||||
.pt2{padding-top:2rpx;}
|
||||
.pt5{padding-top:5rpx}
|
||||
.pt8{padding-top:8rpx;}
|
||||
.pt10{padding-top:10rpx;}
|
||||
.pt15{padding-top:15rpx;}
|
||||
.pt20{padding-top:20rpx;}
|
||||
.pt25{padding-top:25rpx;}
|
||||
.pt30{padding-top:30rpx;}
|
||||
.pt35{padding-top:35rpx;}
|
||||
.pt40{padding-top:40rpx;}
|
||||
.pt45{padding-top:45rpx;}
|
||||
.pt50{padding-top:50rpx;}
|
||||
.pt55{padding-top:55rpx;}
|
||||
.pt60{padding-top:60rpx;}
|
||||
.pt70{padding-top:70rpx;}
|
||||
.pt80{padding-top:80rpx;}
|
||||
.pt90{padding-top:90rpx;}
|
||||
.pt100{padding-top:100rpx;}
|
||||
.pt125{padding-top:125rpx;}
|
||||
.pt140{padding-top:140rpx;}
|
||||
.pt160{padding-top:160rpx;}
|
||||
.pt180{padding-top:180rpx;}
|
||||
.pt200{padding-top:200rpx;}
|
||||
.pt400{padding-top:400rpx;}
|
||||
.pl0{padding-left:0;}
|
||||
.pl5{padding-left:5rpx;}
|
||||
.pl10{padding-left:10rpx;}
|
||||
.pl15{padding-left:15rpx;}
|
||||
.pl20{padding-left:20rpx;}
|
||||
.pl25{padding-left:25rpx;}
|
||||
.pl28{padding-left:28rpx;}
|
||||
.pl30{padding-left:30rpx;}
|
||||
.pl36{padding-left:36rpx;}
|
||||
.pl40{padding-left:40rpx;}
|
||||
.pl42{padding-left:42rpx;}
|
||||
.pl45{padding-left:45rpx;}
|
||||
.pl50{padding-left:50rpx;}
|
||||
.pl60{padding-left:60rpx;}
|
||||
.pl62{padding-left:62rpx;}
|
||||
.pl70{padding-left:70rpx;}
|
||||
.pl75{padding-left:75rpx;}
|
||||
.pl80{padding-left:80rpx;}
|
||||
.pl90{padding-left:90rpx;}
|
||||
.pl100{padding-left:100rpx;}
|
||||
.pl110{padding-left:110rpx;}
|
||||
.pl120{padding-left:120rpx;}
|
||||
.pl130{padding-left:130rpx;}
|
||||
.pl135{padding-left:135rpx;}
|
||||
.pl140{padding-left:140rpx;}
|
||||
.pl150{padding-left:150rpx;}
|
||||
.pl160{padding-left:160rpx;}
|
||||
.pl170{padding-left:170rpx;}
|
||||
.pl180{padding-left:180rpx;}
|
||||
.pl190{padding-left:190rpx;}
|
||||
.pl200{padding-left:200rpx;}
|
||||
.pl210{padding-left:210rpx;}
|
||||
.pl220{padding-left:220rpx;}
|
||||
.pl260{padding-left:260rpx;}
|
||||
.pl320{padding-left:320rpx;}
|
||||
.pr0{padding-right:0;}
|
||||
.pr5{padding-right:5rpx;}
|
||||
.pr10{padding-right:10rpx;}
|
||||
.pr15{padding-right:15rpx;}
|
||||
.pr20{padding-right:20rpx;}
|
||||
.pr25{padding-right:25rpx;}
|
||||
.pr28{padding-right:28rpx;}
|
||||
.pr30{padding-right:30rpx;}
|
||||
.pr38{padding-right:38rpx;}
|
||||
.pr40{padding-right:40rpx;}
|
||||
.pr42{padding-right:42rpx;}
|
||||
.pr45{padding-right:45rpx;}
|
||||
.pr50{padding-right:50rpx;}
|
||||
.pr60{padding-right:60rpx;}
|
||||
.pr62{padding-right:62rpx;}
|
||||
.pr64{padding-right:64rpx;}
|
||||
.pr80{padding-right:80rpx;}
|
||||
.pr90{padding-right:90rpx;}
|
||||
.pr100{padding-right:100rpx;}
|
||||
.pr110{padding-right:110rpx;}
|
||||
.pr120{padding-right:120rpx;}
|
||||
.pr130{padding-right:130rpx;}
|
||||
.pr150{padding-right:150rpx;}
|
||||
.pr160{padding-right:160rpx;}
|
||||
.pr180{padding-right:180rpx;}
|
||||
.pr200{padding-right:200rpx;}
|
||||
.pb0{padding-bottom:0;}
|
||||
.pb2{padding-bottom:2rpx;}
|
||||
.pb5{padding-bottom:5rpx;}
|
||||
.pb8{padding-bottom:8rpx;}
|
||||
.pb10{padding-bottom:10rpx;}
|
||||
.pb15{padding-bottom:15rpx;}
|
||||
.pb20{padding-bottom:20rpx;}
|
||||
.pb25{padding-bottom:25rpx;}
|
||||
.pb30{padding-bottom:30rpx;}
|
||||
.pb35{padding-bottom:40rpx;}
|
||||
.pb40{padding-bottom:40rpx;}
|
||||
.pb50{padding-bottom:50rpx;}
|
||||
.pb55{padding-bottom:55rpx;}
|
||||
.pb60{padding-bottom:60rpx;}
|
||||
.pb80{padding-bottom:80rpx;}
|
||||
.pb90{padding-bottom:90rpx;}
|
||||
.pb100{padding-bottom:100rpx;}
|
||||
.pb130{padding-bottom:130rpx;}
|
||||
.pb150{padding-bottom:150rpx;}
|
||||
.pb180{padding-bottom:180rpx;}
|
||||
.pb200{padding-bottom:200rpx;}
|
||||
@@ -0,0 +1,27 @@
|
||||
.ulib-r0{border-radius:0;}
|
||||
.ulib-rr0{border-top-right-radius:0;border-bottom-right-radius:0;}
|
||||
.ulib-r5{border-radius:5rpx;}
|
||||
.ulib-rt5{border-top-left-radius:5rpx;border-top-right-radius:5rpx;}
|
||||
.ulib-rb5{border-bottom-left-radius:5rpx;border-bottom-right-radius:5rpx;}
|
||||
.ulib-rl5{border-top-left-radius:5rpx;border-bottom-left-radius:5rpx;}
|
||||
.ulib-r10{border-radius:10rpx;}
|
||||
.ulib-rt10{border-top-left-radius:10rpx;border-top-right-radius:10rpx;}
|
||||
.ulib-rl10{border-top-left-radius:10rpx;border-bottom-left-radius:10rpx;}
|
||||
.ulib-rr10{border-top-right-radius:10rpx;border-bottom-right-radius:10rpx;}
|
||||
.ulib-rb10{border-bottom-left-radius:10rpx;border-bottom-right-radius:10rpx;}
|
||||
.ulib-r10-bl{border-bottom-left-radius:10rpx;}
|
||||
.ulib-r10-tr-bl{border-top-right-radius:10rpx;border-bottom-left-radius:10rpx;}
|
||||
.ulib-r15{border-radius:15rpx;}
|
||||
.ulib-r20{border-radius:20rpx;}
|
||||
.ulib-rt20{border-top-left-radius:20rpx;border-top-right-radius:20rpx;}
|
||||
.ulib-rb20{border-bottom-left-radius:20rpx;border-bottom-right-radius:20rpx;}
|
||||
.ulib-rl20{border-top-left-radius:20rpx;border-bottom-left-radius:20rpx;}
|
||||
.ulib-rt30{border-top-left-radius:30rpx;border-top-right-radius:30rpx;}
|
||||
.ulib-r750{border-radius:750rpx;}
|
||||
.ulib-rt750{border-top-left-radius:750rpx;border-top-right-radius:750rpx;}
|
||||
.ulib-rl750{border-top-left-radius:750rpx;border-bottom-left-radius:750rpx;}
|
||||
.ulib-rr750{border-top-right-radius:750rpx;border-bottom-right-radius:750rpx;}
|
||||
.ulib-rlt0{border-top-left-radius:0;}
|
||||
.ulib-rlt10{border-top-left-radius:10rpx;}
|
||||
.ulib-rlt0{border-top-left-radius:0;}
|
||||
.ulib-rlb10{border-bottom-left-radius:10rpx;}
|
||||
@@ -0,0 +1,14 @@
|
||||
.text-nowrap{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
||||
.text-nospace{line-height:1;}
|
||||
.text-left{text-align:left;}
|
||||
.text-center{text-align:center;}
|
||||
.text-right{text-align:right;}
|
||||
.text-underline{text-decoration:underline;}
|
||||
.text-through{text-decoration:line-through;}
|
||||
.text-middle{vertical-align:middle}
|
||||
.text-bold{font-weight:bold;}
|
||||
.text-break{word-break:break-all;word-wrap:break-word;white-space:pre-wrap;}
|
||||
.text-shadow{text-shadow:1rpx 3rpx 3rpx rgba(0,0,0,.8);}
|
||||
.text-spacing-10{letter-spacing:10rpx}
|
||||
.space-nowrap{white-space:nowrap;}
|
||||
.space-normal{white-space:normal;}
|
||||
@@ -0,0 +1,13 @@
|
||||
@import "thirdparty/iconfont.wxss";
|
||||
@import "base/background.wxss";
|
||||
@import "base/border.wxss";
|
||||
@import "base/button.wxss";
|
||||
@import "base/fontColor.wxss";
|
||||
@import "base/fontSize.wxss";
|
||||
@import "base/imgSize.wxss";
|
||||
@import "base/textRender.wxss";
|
||||
@import "base/layout.wxss";
|
||||
@import "base/margin.wxss";
|
||||
@import "base/padding.wxss";
|
||||
@import "base/radius.wxss";
|
||||
@import "base/animate.wxss";
|
||||
@@ -0,0 +1,79 @@
|
||||
.A-coupon-item {
|
||||
height: 155rpx;
|
||||
background-repeat:repeat-y;
|
||||
background-size:100% auto;
|
||||
border-top:#e6e6e6 2rpx solid;
|
||||
border-bottom:#e6e6e6 2rpx solid;
|
||||
}
|
||||
|
||||
.A-coupon-item-price{
|
||||
height:100%;
|
||||
width: 150rpx;
|
||||
border-right: 2rpx dashed #f1e5d9;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.A-coupon-item-price::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: -11rpx;
|
||||
top: -11rpx;
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
border-radius: 100%;
|
||||
background-color: #fff;
|
||||
border:#e6e6e6 2rpx solid;
|
||||
}
|
||||
.A-coupon-item-price::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: -11rpx;
|
||||
bottom: -11rpx;
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
border-radius: 100%;
|
||||
background-color: #fff;
|
||||
border:#e6e6e6 2rpx solid;
|
||||
}
|
||||
|
||||
.xhb-coupon{
|
||||
overflow: hidden;
|
||||
background-image: url('https://qs.haodian.cn/wechat_app/xiaohongbangV2/coupon/coupon-bg.png');
|
||||
background-size: 100% auto;
|
||||
background-repeat: repeat-y;
|
||||
}
|
||||
.xhb-coupon::before,.xhb-coupon::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
border-radius: 100%;
|
||||
border: 1px solid #e8e8e8;
|
||||
left: 457rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 100%;
|
||||
}
|
||||
.xhb-coupon::before{
|
||||
top: -9rpx;
|
||||
}
|
||||
.xhb-coupon::after{
|
||||
bottom: -9rpx;
|
||||
}
|
||||
.xhb-coupon-info{
|
||||
width: 467rpx;
|
||||
height: 168rpx;
|
||||
border-top: 1px solid #e8e8e8;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
border-right: 1px dashed #e8e8e8;
|
||||
}
|
||||
.xhb-coupon-opt{
|
||||
width: 223rpx;
|
||||
height: 168rpx;
|
||||
border-top: 1px solid #e8e8e8;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
}
|
||||
.xhb-coupon-opt .btn{
|
||||
width: 162rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
.coms-dialog-kf .pic-top{
|
||||
height: 172rpx;
|
||||
|
||||
background: url("http://qs.haodian.cn/wechat_app/xiaohongbangV2/kf_dialog_bg_2.png") no-repeat top center;
|
||||
background-size: 100% 100%;
|
||||
|
||||
}
|
||||
|
||||
.coms-dialog-kf{
|
||||
width:596rpx;
|
||||
background: #fff;
|
||||
padding: 0 0 50rpx 0;
|
||||
}
|
||||
.coms-dialog-kf .tit{
|
||||
color: #333333;
|
||||
font-size: 30rpx;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
line-height: 1.6;
|
||||
margin: 20rpx 0 0;
|
||||
}
|
||||
.coms-dialog-kf .tit text{
|
||||
display: block;
|
||||
}
|
||||
|
||||
.coms-dialog-kf .btn-concat{
|
||||
width: 328rpx;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
border-radius: 50rpx;
|
||||
background: #fe2643;
|
||||
font-size: 32rpx;
|
||||
color:#fff;
|
||||
padding: 0;
|
||||
margin: 30rpx auto 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 526 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1018 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 889 B |
|
After Width: | Height: | Size: 869 B |
@@ -0,0 +1,15 @@
|
||||
import config from 'config'
|
||||
import WxRouter from 'utils/router';
|
||||
import apiQuery from 'utils/apiQuery';
|
||||
import userManager from 'utils/user-manager'
|
||||
import utils from 'utils/util'
|
||||
import eventBus from 'lib/event'
|
||||
|
||||
module.exports = {
|
||||
$router:new WxRouter(),
|
||||
apiQuery,
|
||||
config,
|
||||
userManager,
|
||||
utils,
|
||||
eventBus
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
const env = "d";
|
||||
|
||||
const version = 1,
|
||||
|
||||
//好店云
|
||||
app_id = 'ebb6d3808b2fa324',
|
||||
key = '06c92b4b954d06dab7b91a8886c7a69b';
|
||||
|
||||
|
||||
//狸车宝
|
||||
// app_id = '1c156bb57cd6984a',
|
||||
// key = '71fd71173b776766a2ae1209d9a2c2ed';
|
||||
|
||||
|
||||
let api, baseUrl;
|
||||
|
||||
if (env == "d") {
|
||||
baseUrl = "https://hd-api-dev.xiaoyu.com/hd/";
|
||||
} else if (env == "t") {
|
||||
baseUrl = "https://api.test.haodian.cn/hd/";
|
||||
} else if (env == "p") {
|
||||
baseUrl = "https://api.haodian.cn/hd/";
|
||||
}
|
||||
api = {
|
||||
baseUrl: baseUrl,
|
||||
appUserUkey: "app/user/ukey", //登录/退出登录
|
||||
appUser: "app/user", //用户信息
|
||||
appUserTel: "app/user/tel", //编辑拨打电话
|
||||
appHomeIcon: "app/home/icon", //首页图标
|
||||
appBiz: "app/biz",//店铺列表
|
||||
appExchangeTab: "app/exchange/tab", //核销tab /接单宝tab二级
|
||||
appExchange: "app/exchange", //核销记录列表 //核销
|
||||
appReceiverTab: "app/receiver/tab", //接单宝tab
|
||||
appReceiver: "app/receiver",//接单宝列表 //接单宝详情 //接单宝编辑
|
||||
appReceiverTip: "app/receiver/tip",//接单宝温馨提示
|
||||
appOtherMcode: "app/other/mcode",//发送验证码
|
||||
appReceiverLogs: "app/receiver/logs", //接单宝小记
|
||||
appYx: 'app/yx', //接单宝获取订单手机号
|
||||
receiverOrders: 'app/receiver/orders', //接单宝-分配订单
|
||||
receiverCustomer: 'app/receiver/customer', //客户信息修改
|
||||
|
||||
appSythome: 'app/sythome', //私域通首页
|
||||
sytactivityMenu: 'app/sytactivity/menu', //推广活动菜单
|
||||
appSytactivity: 'app/sytactivity', //推广活动列表 //推广活动编辑
|
||||
sytactivityDetail: 'app/sytactivity/detail', //推广活动详情
|
||||
sytactivityAchievement: 'app/sytactivity/achievement', //活动业绩
|
||||
sytactivityAchievementData: 'app/sytactivity/achievement_data', //活动业绩-实时战报
|
||||
sytactivityAchievementKpi: 'app/sytactivity/achievement_kpi', //活动业绩-kpi数据
|
||||
appSytteam: 'app/sytteam', //团队管理 //团队管理-发起团队
|
||||
sytteamMenu: 'app/sytteam/menu', //团队管理-菜单
|
||||
sytteamLeader: 'app/sytteam/leader', //团队管理-任命团长
|
||||
sytteamZb_top: 'app/sytteam/zb_top', //今日战报-TOP3
|
||||
sytteamZb_menu: 'app/sytteam/zb_menu', //今日战报-菜单
|
||||
sytteamZb_list: 'app/sytteam/zb_list', //今日战报-列表
|
||||
achievement_detail: 'app/sytactivity/achievement_detail', //活动业绩-活动明细
|
||||
|
||||
bizTreasures: 'app/biz/treasures', //店铺订单宝/客多宝
|
||||
customerTab: 'app/customer/tab', //客多宝-tab
|
||||
appCustomer: 'app/customer', //客多宝-列表
|
||||
|
||||
customerField: 'app/customer/field', //客户_基础信息 /客户_新增/编辑
|
||||
customerDistribution: 'app/customer/distribution', //客户_分配
|
||||
customerInfo: 'app/customer/info', //客户_详情
|
||||
customerLogs: 'app/customer/logs', //客户_小记
|
||||
customerLog: 'app/customer/log', //客户_更新小记
|
||||
customerStatus: 'app/customer/status', //客户_列表状态
|
||||
customerSetting: 'app/customer/setting', //基础设置信息/基础设置
|
||||
customerDockingPeople: 'app/customer/docking_people', //对接人列表
|
||||
|
||||
dxtHome: 'app/dxt/home', //电销通首页
|
||||
|
||||
dxtEmployeesMenu: 'app/dxt/employees_menu', //员工管理_菜单
|
||||
dxtEmployees: 'app/dxt/employees', //员工管理_列表
|
||||
dxtEmployeesStatus: 'app/dxt/employees_status', //员工管理_修改状态
|
||||
dxtEmployeesInfo: 'app/dxt/employees_info', //员工管理_新增/修改信息 /员工管理_员工详情
|
||||
dxtMigration: 'app/dxt/migration', //员工管理_一键迁移
|
||||
dxtAnalysis: 'app/dxt/analysis', //数据分析
|
||||
dxtAnalysisChart: 'app/dxt/analysis_chart', //数据分析_趋势图
|
||||
dxtPhoneBill: 'app/dxt/phone_bill', //话费清单
|
||||
|
||||
dxtCustomerField: 'app/dxt/customer_field', //客户_基础信息 /作废,移到客多宝
|
||||
dxtCustomer: 'app/dxt/customer', //客户_新增/编辑/客户_列表 /作废,移到客多宝
|
||||
dxtCustomerUb: 'app/dxt/customer_ub', //客户_分配 /作废,移到客多宝
|
||||
dxtCustomerInfo: 'app/dxt/customer_info', //客户_详情 /作废,移到客多宝
|
||||
dxtCustomerLogs: 'app/dxt/customer_logs', //客户_小记 /作废,移到客多宝
|
||||
dxtCustomerLog: 'app/dxt/customer_log', //客户_更新小记 /作废,移到客多宝
|
||||
|
||||
appOrder: 'app/order', //订单保列表
|
||||
orderMenu: 'app/order/menu', //订单保顶部菜单
|
||||
orderDetail: 'app/order/detail', //订单保详情
|
||||
orderStatus: 'app/order/status', //同意/拒绝核销
|
||||
|
||||
orderAccountMenu: 'app/order/account_menu', //帐户余额_顶部菜单
|
||||
orderAccount: 'app/order/account', //帐户余额_列表
|
||||
|
||||
appXz: 'app/xz', //(新)接单宝获取订单手机号
|
||||
|
||||
}
|
||||
|
||||
//远程图片存储地址
|
||||
var imgUrl = 'https://qs.haodian.cn/wechat_app/lichebao/'
|
||||
|
||||
|
||||
/**
|
||||
* 默认头像
|
||||
*/
|
||||
// var defaultAvartar = imgUrl + 'default.png'
|
||||
var defaultAvartar = ''
|
||||
|
||||
/**
|
||||
* 滚动高度设置
|
||||
*/
|
||||
var elementScrollTop = '150'
|
||||
|
||||
/**
|
||||
* 提醒模板id
|
||||
*/
|
||||
var bookTmpId ='zT5wqntUU0ipSJY7Hlw4T4lKfWwTddn3tv8udUv-rdo'
|
||||
|
||||
/**
|
||||
* 开奖模板id
|
||||
*/
|
||||
var getLotteryTmpId = '5Lv1DATQLG23omDhIA8DS2ZBM6zU9prvt94BO7S9exc'
|
||||
|
||||
/**
|
||||
* 模板id
|
||||
*/
|
||||
var subscribeTmpId = {
|
||||
book: 'zT5wqntUU0ipSJY7Hlw4T4lKfWwTddn3tv8udUv-rdo',
|
||||
getlottery: '5Lv1DATQLG23omDhIA8DS2ZBM6zU9prvt94BO7S9exc'
|
||||
}
|
||||
|
||||
/**
|
||||
* 接口白名单
|
||||
*/
|
||||
var white401UrlList = {
|
||||
'app/home/qrcode':'app/home/qrcode'
|
||||
}
|
||||
|
||||
export default {
|
||||
env,
|
||||
api,
|
||||
key,
|
||||
version,
|
||||
app_id,
|
||||
imgUrl,
|
||||
defaultAvartar,
|
||||
elementScrollTop,
|
||||
bookTmpId,
|
||||
getLotteryTmpId,
|
||||
subscribeTmpId,
|
||||
white401UrlList
|
||||
}
|
||||
@@ -0,0 +1,418 @@
|
||||
/**
|
||||
* 表单验证
|
||||
*
|
||||
* @param {Object} rules 验证字段的规则
|
||||
* @param {Object} messages 验证字段的提示信息
|
||||
*
|
||||
*/
|
||||
class WxValidate {
|
||||
constructor(rules = {}, messages = {}) {
|
||||
Object.assign(this, {
|
||||
data: {},
|
||||
rules,
|
||||
messages,
|
||||
})
|
||||
this.__init()
|
||||
}
|
||||
|
||||
/**
|
||||
* __init
|
||||
*/
|
||||
__init() {
|
||||
this.__initMethods()
|
||||
this.__initDefaults()
|
||||
this.__initData()
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
__initData() {
|
||||
this.form = {}
|
||||
this.errorList = []
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化默认提示信息
|
||||
*/
|
||||
__initDefaults() {
|
||||
this.defaults = {
|
||||
messages: {
|
||||
required: '这是必填字段。',
|
||||
email: '请输入有效的电子邮件地址。',
|
||||
tel: '请输入11位的手机号码。',
|
||||
url: '请输入有效的网址。',
|
||||
date: '请输入有效的日期。',
|
||||
dateISO: '请输入有效的日期(ISO),例如:2009-06-23,1998/01/22。',
|
||||
number: '请输入有效的数字。',
|
||||
digits: '只能输入数字。',
|
||||
idcard: '请输入18位的有效身份证。',
|
||||
equalTo: this.formatTpl('输入值必须和 {0} 相同。'),
|
||||
contains: this.formatTpl('输入值必须包含 {0}。'),
|
||||
minlength: this.formatTpl('最少要输入 {0} 个字符。'),
|
||||
maxlength: this.formatTpl('最多可以输入 {0} 个字符。'),
|
||||
rangelength: this.formatTpl('请输入长度在 {0} 到 {1} 之间的字符。'),
|
||||
min: this.formatTpl('请输入不小于 {0} 的数值。'),
|
||||
max: this.formatTpl('请输入不大于 {0} 的数值。'),
|
||||
range: this.formatTpl('请输入范围在 {0} 到 {1} 之间的数值。'),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化默认验证方法
|
||||
*/
|
||||
__initMethods() {
|
||||
const that = this
|
||||
that.methods = {
|
||||
/**
|
||||
* 验证必填元素
|
||||
*/
|
||||
required(value, param) {
|
||||
if (!that.depend(param)) {
|
||||
return 'dependency-mismatch'
|
||||
} else if (typeof value === 'number') {
|
||||
value = value.toString()
|
||||
} else if (typeof value === 'boolean') {
|
||||
return !0
|
||||
}
|
||||
|
||||
return value.length > 0
|
||||
},
|
||||
/**
|
||||
* 验证电子邮箱格式
|
||||
*/
|
||||
email(value) {
|
||||
return that.optional(value) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(value)
|
||||
},
|
||||
/**
|
||||
* 验证手机格式
|
||||
*/
|
||||
tel(value) {
|
||||
return that.optional(value) || /^1[3456789]\d{9}$/.test(value)
|
||||
},
|
||||
/**
|
||||
* 验证URL格式
|
||||
*/
|
||||
url(value) {
|
||||
return that.optional(value) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(value)
|
||||
},
|
||||
/**
|
||||
* 验证日期格式
|
||||
*/
|
||||
date(value) {
|
||||
return that.optional(value) || !/Invalid|NaN/.test(new Date(value).toString())
|
||||
},
|
||||
/**
|
||||
* 验证ISO类型的日期格式
|
||||
*/
|
||||
dateISO(value) {
|
||||
return that.optional(value) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
|
||||
},
|
||||
/**
|
||||
* 验证十进制数字
|
||||
*/
|
||||
number(value) {
|
||||
return that.optional(value) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value)
|
||||
},
|
||||
/**
|
||||
* 验证整数
|
||||
*/
|
||||
digits(value) {
|
||||
return that.optional(value) || /^\d+$/.test(value)
|
||||
},
|
||||
/**
|
||||
* 验证身份证号码
|
||||
*/
|
||||
idcard(value) {
|
||||
return that.optional(value) || /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)
|
||||
},
|
||||
/**
|
||||
* 验证两个输入框的内容是否相同
|
||||
*/
|
||||
equalTo(value, param) {
|
||||
return that.optional(value) || value === that.data[param]
|
||||
},
|
||||
/**
|
||||
* 验证是否包含某个值
|
||||
*/
|
||||
contains(value, param) {
|
||||
return that.optional(value) || value.indexOf(param) >= 0
|
||||
},
|
||||
/**
|
||||
* 验证最小长度
|
||||
*/
|
||||
minlength(value, param) {
|
||||
return that.optional(value) || value.length >= param
|
||||
},
|
||||
/**
|
||||
* 验证最大长度
|
||||
*/
|
||||
maxlength(value, param) {
|
||||
return that.optional(value) || value.length <= param
|
||||
},
|
||||
/**
|
||||
* 验证一个长度范围[min, max]
|
||||
*/
|
||||
rangelength(value, param) {
|
||||
return that.optional(value) || (value.length >= param[0] && value.length <= param[1])
|
||||
},
|
||||
/**
|
||||
* 验证最小值
|
||||
*/
|
||||
min(value, param) {
|
||||
return that.optional(value) || value >= param
|
||||
},
|
||||
/**
|
||||
* 验证最大值
|
||||
*/
|
||||
max(value, param) {
|
||||
return that.optional(value) || value <= param
|
||||
},
|
||||
/**
|
||||
* 验证一个值范围[min, max]
|
||||
*/
|
||||
range(value, param) {
|
||||
return that.optional(value) || (value >= param[0] && value <= param[1])
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加自定义验证方法
|
||||
* @param {String} name 方法名
|
||||
* @param {Function} method 函数体,接收两个参数(value, param),value表示元素的值,param表示参数
|
||||
* @param {String} message 提示信息
|
||||
*/
|
||||
addMethod(name, method, message) {
|
||||
this.methods[name] = method
|
||||
this.defaults.messages[name] = message !== undefined ? message : this.defaults.messages[name]
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断验证方法是否存在
|
||||
*/
|
||||
isValidMethod(value) {
|
||||
let methods = []
|
||||
for (let method in this.methods) {
|
||||
if (method && typeof this.methods[method] === 'function') {
|
||||
methods.push(method)
|
||||
}
|
||||
}
|
||||
return methods.indexOf(value) !== -1
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化提示信息模板
|
||||
*/
|
||||
formatTpl(source, params) {
|
||||
const that = this
|
||||
if (arguments.length === 1) {
|
||||
return function() {
|
||||
let args = Array.from(arguments)
|
||||
args.unshift(source)
|
||||
return that.formatTpl.apply(this, args)
|
||||
}
|
||||
}
|
||||
if (params === undefined) {
|
||||
return source
|
||||
}
|
||||
if (arguments.length > 2 && params.constructor !== Array) {
|
||||
params = Array.from(arguments).slice(1)
|
||||
}
|
||||
if (params.constructor !== Array) {
|
||||
params = [params]
|
||||
}
|
||||
params.forEach(function(n, i) {
|
||||
source = source.replace(new RegExp("\\{" + i + "\\}", "g"), function() {
|
||||
return n
|
||||
})
|
||||
})
|
||||
return source
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断规则依赖是否存在
|
||||
*/
|
||||
depend(param) {
|
||||
switch (typeof param) {
|
||||
case 'boolean':
|
||||
param = param
|
||||
break
|
||||
case 'string':
|
||||
param = !!param.length
|
||||
break
|
||||
case 'function':
|
||||
param = param()
|
||||
default:
|
||||
param = !0
|
||||
}
|
||||
return param
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断输入值是否为空
|
||||
*/
|
||||
optional(value) {
|
||||
return !this.methods.required(value) && 'dependency-mismatch'
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义字段的提示信息
|
||||
* @param {String} param 字段名
|
||||
* @param {Object} rule 规则
|
||||
*/
|
||||
customMessage(param, rule) {
|
||||
const params = this.messages[param]
|
||||
const isObject = typeof params === 'object'
|
||||
if (params && isObject) return params[rule.method]
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个指定字段的提示信息
|
||||
* @param {String} param 字段名
|
||||
* @param {Object} rule 规则
|
||||
*/
|
||||
defaultMessage(param, rule) {
|
||||
let message = this.customMessage(param, rule) || this.defaults.messages[rule.method]
|
||||
let type = typeof message
|
||||
|
||||
if (type === 'undefined') {
|
||||
message = `Warning: No message defined for ${rule.method}.`
|
||||
} else if (type === 'function') {
|
||||
message = message.call(this, rule.parameters)
|
||||
}
|
||||
|
||||
return message
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存错误信息
|
||||
* @param {String} param 字段名
|
||||
* @param {Object} rule 规则
|
||||
* @param {String} value 元素的值
|
||||
*/
|
||||
formatTplAndAdd(param, rule, value) {
|
||||
let msg = this.defaultMessage(param, rule)
|
||||
|
||||
this.errorList.push({
|
||||
param: param,
|
||||
msg: msg,
|
||||
value: value,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证某个指定字段的规则
|
||||
* @param {String} param 字段名
|
||||
* @param {Object} rules 规则
|
||||
* @param {Object} data 需要验证的数据对象
|
||||
*/
|
||||
checkParam(param, rules, data) {
|
||||
|
||||
// 缓存数据对象
|
||||
this.data = data
|
||||
|
||||
// 缓存字段对应的值
|
||||
const value = data[param] !== null && data[param] !== undefined ? data[param] : ''
|
||||
|
||||
// 遍历某个指定字段的所有规则,依次验证规则,否则缓存错误信息
|
||||
for (let method in rules) {
|
||||
|
||||
// 判断验证方法是否存在
|
||||
if (this.isValidMethod(method)) {
|
||||
|
||||
// 缓存规则的属性及值
|
||||
const rule = {
|
||||
method: method,
|
||||
parameters: rules[method]
|
||||
}
|
||||
|
||||
// 调用验证方法
|
||||
const result = this.methods[method](value, rule.parameters)
|
||||
|
||||
// 若result返回值为dependency-mismatch,则说明该字段的值为空或非必填字段
|
||||
if (result === 'dependency-mismatch') {
|
||||
continue
|
||||
}
|
||||
|
||||
this.setValue(param, method, result, value)
|
||||
|
||||
// 判断是否通过验证,否则缓存错误信息,跳出循环
|
||||
if (!result) {
|
||||
this.formatTplAndAdd(param, rule, value)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置字段的默认验证值
|
||||
* @param {String} param 字段名
|
||||
*/
|
||||
setView(param) {
|
||||
this.form[param] = {
|
||||
$name: param,
|
||||
$valid: true,
|
||||
$invalid: false,
|
||||
$error: {},
|
||||
$success: {},
|
||||
$viewValue: ``,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置字段的验证值
|
||||
* @param {String} param 字段名
|
||||
* @param {String} method 字段的方法
|
||||
* @param {Boolean} result 是否通过验证
|
||||
* @param {String} value 字段的值
|
||||
*/
|
||||
setValue(param, method, result, value) {
|
||||
const params = this.form[param]
|
||||
params.$valid = result
|
||||
params.$invalid = !result
|
||||
params.$error[method] = !result
|
||||
params.$success[method] = result
|
||||
params.$viewValue = value
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证所有字段的规则,返回验证是否通过
|
||||
* @param {Object} data 需要验证数据对象
|
||||
*/
|
||||
checkForm(data) {
|
||||
this.__initData()
|
||||
|
||||
for (let param in this.rules) {
|
||||
this.setView(param)
|
||||
this.checkParam(param, this.rules[param], data)
|
||||
}
|
||||
|
||||
return this.valid()
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回验证是否通过
|
||||
*/
|
||||
valid() {
|
||||
return this.size() === 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回错误信息的个数
|
||||
*/
|
||||
size() {
|
||||
return this.errorList.length
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回所有错误信息
|
||||
*/
|
||||
validationErrors() {
|
||||
return this.errorList
|
||||
}
|
||||
}
|
||||
|
||||
export default WxValidate
|
||||
@@ -0,0 +1,36 @@
|
||||
var events = {};
|
||||
|
||||
function on(name, self, callback) {
|
||||
var tuple = [self, callback];
|
||||
var callbacks = events[name];
|
||||
if (Array.isArray(callbacks)) {
|
||||
callbacks.push(tuple);
|
||||
}
|
||||
else {
|
||||
events[name] = [tuple];
|
||||
}
|
||||
}
|
||||
|
||||
function remove(name, self) {
|
||||
var callbacks = events[name];
|
||||
if (Array.isArray(callbacks)) {
|
||||
events[name] = callbacks.filter((tuple) => {
|
||||
return tuple[0] != self;
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function emit(name, data) {
|
||||
var callbacks = events[name];
|
||||
if (Array.isArray(callbacks)) {
|
||||
callbacks.map((tuple) => {
|
||||
var self = tuple[0];
|
||||
var callback = tuple[1];
|
||||
callback.call(self, data);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
exports.on = on;
|
||||
exports.remove = remove;
|
||||
exports.emit = emit;
|
||||
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
||||
* Digest Algorithm, as defined in RFC 1321.
|
||||
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
|
||||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||||
* Distributed under the BSD License
|
||||
* See http://pajhome.org.uk/crypt/md5 for more info.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Configurable variables. You may need to tweak these to be compatible with
|
||||
* the server-side, but the defaults work in most cases.
|
||||
*/
|
||||
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
|
||||
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
|
||||
|
||||
/*
|
||||
* These are the functions you'll usually want to call
|
||||
* They take string arguments and return either hex or base-64 encoded strings
|
||||
*/
|
||||
function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
|
||||
function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
|
||||
function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
|
||||
function hex_hmac_md5(k, d) { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
|
||||
function b64_hmac_md5(k, d) { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
|
||||
function any_hmac_md5(k, d, e) { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
|
||||
|
||||
/*
|
||||
* Perform a simple self-test to see if the VM is working
|
||||
*/
|
||||
function md5_vm_test() {
|
||||
return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the MD5 of a raw string
|
||||
*/
|
||||
function rstr_md5(s) {
|
||||
return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the HMAC-MD5, of a key and some data (raw strings)
|
||||
*/
|
||||
function rstr_hmac_md5(key, data) {
|
||||
var bkey = rstr2binl(key);
|
||||
if (bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
|
||||
|
||||
var ipad = Array(16), opad = Array(16);
|
||||
for (var i = 0; i < 16; i++) {
|
||||
ipad[i] = bkey[i] ^ 0x36363636;
|
||||
opad[i] = bkey[i] ^ 0x5C5C5C5C;
|
||||
}
|
||||
|
||||
var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
|
||||
return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a raw string to a hex string
|
||||
*/
|
||||
function rstr2hex(input) {
|
||||
try { hexcase } catch (e) { hexcase = 0; }
|
||||
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||
var output = "";
|
||||
var x;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
x = input.charCodeAt(i);
|
||||
output += hex_tab.charAt((x >>> 4) & 0x0F)
|
||||
+ hex_tab.charAt(x & 0x0F);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a raw string to a base-64 string
|
||||
*/
|
||||
function rstr2b64(input) {
|
||||
try { b64pad } catch (e) { b64pad = ''; }
|
||||
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
var output = "";
|
||||
var len = input.length;
|
||||
for (var i = 0; i < len; i += 3) {
|
||||
var triplet = (input.charCodeAt(i) << 16)
|
||||
| (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0)
|
||||
| (i + 2 < len ? input.charCodeAt(i + 2) : 0);
|
||||
for (var j = 0; j < 4; j++) {
|
||||
if (i * 8 + j * 6 > input.length * 8) output += b64pad;
|
||||
else output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a raw string to an arbitrary string encoding
|
||||
*/
|
||||
function rstr2any(input, encoding) {
|
||||
var divisor = encoding.length;
|
||||
var i, j, q, x, quotient;
|
||||
|
||||
/* Convert to an array of 16-bit big-endian values, forming the dividend */
|
||||
var dividend = Array(Math.ceil(input.length / 2));
|
||||
for (i = 0; i < dividend.length; i++) {
|
||||
dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Repeatedly perform a long division. The binary array forms the dividend,
|
||||
* the length of the encoding is the divisor. Once computed, the quotient
|
||||
* forms the dividend for the next step. All remainders are stored for later
|
||||
* use.
|
||||
*/
|
||||
var full_length = Math.ceil(input.length * 8 /
|
||||
(Math.log(encoding.length) / Math.log(2)));
|
||||
var remainders = Array(full_length);
|
||||
for (j = 0; j < full_length; j++) {
|
||||
quotient = Array();
|
||||
x = 0;
|
||||
for (i = 0; i < dividend.length; i++) {
|
||||
x = (x << 16) + dividend[i];
|
||||
q = Math.floor(x / divisor);
|
||||
x -= q * divisor;
|
||||
if (quotient.length > 0 || q > 0)
|
||||
quotient[quotient.length] = q;
|
||||
}
|
||||
remainders[j] = x;
|
||||
dividend = quotient;
|
||||
}
|
||||
|
||||
/* Convert the remainders to the output string */
|
||||
var output = "";
|
||||
for (i = remainders.length - 1; i >= 0; i--)
|
||||
output += encoding.charAt(remainders[i]);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a string as utf-8.
|
||||
* For efficiency, this assumes the input is valid utf-16.
|
||||
*/
|
||||
function str2rstr_utf8(input) {
|
||||
var output = "";
|
||||
var i = -1;
|
||||
var x, y;
|
||||
|
||||
while (++i < input.length) {
|
||||
/* Decode utf-16 surrogate pairs */
|
||||
x = input.charCodeAt(i);
|
||||
y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
|
||||
if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
|
||||
x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Encode output as utf-8 */
|
||||
if (x <= 0x7F)
|
||||
output += String.fromCharCode(x);
|
||||
else if (x <= 0x7FF)
|
||||
output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F),
|
||||
0x80 | (x & 0x3F));
|
||||
else if (x <= 0xFFFF)
|
||||
output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
|
||||
0x80 | ((x >>> 6) & 0x3F),
|
||||
0x80 | (x & 0x3F));
|
||||
else if (x <= 0x1FFFFF)
|
||||
output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
|
||||
0x80 | ((x >>> 12) & 0x3F),
|
||||
0x80 | ((x >>> 6) & 0x3F),
|
||||
0x80 | (x & 0x3F));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a string as utf-16
|
||||
*/
|
||||
function str2rstr_utf16le(input) {
|
||||
var output = "";
|
||||
for (var i = 0; i < input.length; i++)
|
||||
output += String.fromCharCode(input.charCodeAt(i) & 0xFF,
|
||||
(input.charCodeAt(i) >>> 8) & 0xFF);
|
||||
return output;
|
||||
}
|
||||
|
||||
function str2rstr_utf16be(input) {
|
||||
var output = "";
|
||||
for (var i = 0; i < input.length; i++)
|
||||
output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
|
||||
input.charCodeAt(i) & 0xFF);
|
||||
return output;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a raw string to an array of little-endian words
|
||||
* Characters >255 have their high-byte silently ignored.
|
||||
*/
|
||||
function rstr2binl(input) {
|
||||
var output = Array(input.length >> 2);
|
||||
for (var i = 0; i < output.length; i++)
|
||||
output[i] = 0;
|
||||
for (var i = 0; i < input.length * 8; i += 8)
|
||||
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
|
||||
return output;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of little-endian words to a string
|
||||
*/
|
||||
function binl2rstr(input) {
|
||||
var output = "";
|
||||
for (var i = 0; i < input.length * 32; i += 8)
|
||||
output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
|
||||
return output;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the MD5 of an array of little-endian words, and a bit length.
|
||||
*/
|
||||
function binl_md5(x, len) {
|
||||
/* append padding */
|
||||
x[len >> 5] |= 0x80 << ((len) % 32);
|
||||
x[(((len + 64) >>> 9) << 4) + 14] = len;
|
||||
|
||||
var a = 1732584193;
|
||||
var b = -271733879;
|
||||
var c = -1732584194;
|
||||
var d = 271733878;
|
||||
|
||||
for (var i = 0; i < x.length; i += 16) {
|
||||
var olda = a;
|
||||
var oldb = b;
|
||||
var oldc = c;
|
||||
var oldd = d;
|
||||
|
||||
a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
|
||||
d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
|
||||
c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
|
||||
b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
|
||||
a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
|
||||
d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
|
||||
c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
|
||||
b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
|
||||
a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
|
||||
d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
|
||||
c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
|
||||
b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
|
||||
a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
|
||||
d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
|
||||
c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
|
||||
b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
|
||||
|
||||
a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
|
||||
d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
|
||||
c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
|
||||
b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
|
||||
a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
|
||||
d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
|
||||
c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
|
||||
b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
|
||||
a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
|
||||
d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
|
||||
c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
|
||||
b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
|
||||
a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
|
||||
d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
|
||||
c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
|
||||
b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
|
||||
|
||||
a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
|
||||
d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
|
||||
c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
|
||||
b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
|
||||
a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
|
||||
d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
|
||||
c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
|
||||
b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
|
||||
a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
|
||||
d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
|
||||
c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
|
||||
b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
|
||||
a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
|
||||
d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
|
||||
c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
|
||||
b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
|
||||
|
||||
a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
|
||||
d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
|
||||
c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
|
||||
b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
|
||||
a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
|
||||
d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
|
||||
c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
|
||||
b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
|
||||
a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
|
||||
d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
|
||||
c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
|
||||
b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
|
||||
a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
|
||||
d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
|
||||
c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
|
||||
b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
|
||||
|
||||
a = safe_add(a, olda);
|
||||
b = safe_add(b, oldb);
|
||||
c = safe_add(c, oldc);
|
||||
d = safe_add(d, oldd);
|
||||
}
|
||||
return Array(a, b, c, d);
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions implement the four basic operations the algorithm uses.
|
||||
*/
|
||||
function md5_cmn(q, a, b, x, s, t) {
|
||||
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
|
||||
}
|
||||
function md5_ff(a, b, c, d, x, s, t) {
|
||||
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
|
||||
}
|
||||
function md5_gg(a, b, c, d, x, s, t) {
|
||||
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
|
||||
}
|
||||
function md5_hh(a, b, c, d, x, s, t) {
|
||||
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
|
||||
}
|
||||
function md5_ii(a, b, c, d, x, s, t) {
|
||||
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
||||
* to work around bugs in some JS interpreters.
|
||||
*/
|
||||
function safe_add(x, y) {
|
||||
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
||||
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||||
return (msw << 16) | (lsw & 0xFFFF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bitwise rotate a 32-bit number to the left.
|
||||
*/
|
||||
function bit_rol(num, cnt) {
|
||||
return (num << cnt) | (num >>> (32 - cnt));
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
hex_md5,
|
||||
b64_md5
|
||||
}
|
||||
@@ -0,0 +1,423 @@
|
||||
//Core code comes from https://github.com/davidshimjs/qrcodejs
|
||||
|
||||
var QRCode;
|
||||
|
||||
(function () {
|
||||
/**
|
||||
* Get the type by string length
|
||||
*
|
||||
* @private
|
||||
* @param {String} sText
|
||||
* @param {Number} nCorrectLevel
|
||||
* @return {Number} type
|
||||
*/
|
||||
function _getTypeNumber(sText, nCorrectLevel) {
|
||||
var nType = 1;
|
||||
var length = _getUTF8Length(sText);
|
||||
|
||||
for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) {
|
||||
var nLimit = 0;
|
||||
|
||||
switch (nCorrectLevel) {
|
||||
case QRErrorCorrectLevel.L:
|
||||
nLimit = QRCodeLimitLength[i][0];
|
||||
break;
|
||||
case QRErrorCorrectLevel.M:
|
||||
nLimit = QRCodeLimitLength[i][1];
|
||||
break;
|
||||
case QRErrorCorrectLevel.Q:
|
||||
nLimit = QRCodeLimitLength[i][2];
|
||||
break;
|
||||
case QRErrorCorrectLevel.H:
|
||||
nLimit = QRCodeLimitLength[i][3];
|
||||
break;
|
||||
}
|
||||
|
||||
if (length <= nLimit) {
|
||||
break;
|
||||
} else {
|
||||
nType++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nType > QRCodeLimitLength.length) {
|
||||
throw new Error("Too long data");
|
||||
}
|
||||
|
||||
return nType;
|
||||
}
|
||||
|
||||
function _getUTF8Length(sText) {
|
||||
var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a');
|
||||
return replacedText.length + (replacedText.length != sText ? 3 : 0);
|
||||
}
|
||||
|
||||
function QR8bitByte(data) {
|
||||
this.mode = QRMode.MODE_8BIT_BYTE;
|
||||
this.data = data;
|
||||
this.parsedData = [];
|
||||
|
||||
// Added to support UTF-8 Characters
|
||||
for (var i = 0, l = this.data.length; i < l; i++) {
|
||||
var byteArray = [];
|
||||
var code = this.data.charCodeAt(i);
|
||||
|
||||
if (code > 0x10000) {
|
||||
byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18);
|
||||
byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12);
|
||||
byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6);
|
||||
byteArray[3] = 0x80 | (code & 0x3F);
|
||||
} else if (code > 0x800) {
|
||||
byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12);
|
||||
byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6);
|
||||
byteArray[2] = 0x80 | (code & 0x3F);
|
||||
} else if (code > 0x80) {
|
||||
byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6);
|
||||
byteArray[1] = 0x80 | (code & 0x3F);
|
||||
} else {
|
||||
byteArray[0] = code;
|
||||
}
|
||||
|
||||
this.parsedData.push(byteArray);
|
||||
}
|
||||
|
||||
this.parsedData = Array.prototype.concat.apply([], this.parsedData);
|
||||
|
||||
if (this.parsedData.length != this.data.length) {
|
||||
this.parsedData.unshift(191);
|
||||
this.parsedData.unshift(187);
|
||||
this.parsedData.unshift(239);
|
||||
}
|
||||
}
|
||||
|
||||
QR8bitByte.prototype = {
|
||||
getLength: function (buffer) {
|
||||
return this.parsedData.length;
|
||||
},
|
||||
write: function (buffer) {
|
||||
for (var i = 0, l = this.parsedData.length; i < l; i++) {
|
||||
buffer.put(this.parsedData[i], 8);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// QRCodeModel
|
||||
function QRCodeModel(typeNumber, errorCorrectLevel) {
|
||||
this.typeNumber = typeNumber;
|
||||
this.errorCorrectLevel = errorCorrectLevel;
|
||||
this.modules = null;
|
||||
this.moduleCount = 0;
|
||||
this.dataCache = null;
|
||||
this.dataList = [];
|
||||
}
|
||||
QRCodeModel.prototype = {
|
||||
addData: function (data) { var newData = new QR8bitByte(data); this.dataList.push(newData); this.dataCache = null; }, isDark: function (row, col) {
|
||||
if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) { throw new Error(row + "," + col); }
|
||||
return this.modules[row][col];
|
||||
}, getModuleCount: function () { return this.moduleCount; }, make: function () { this.makeImpl(false, this.getBestMaskPattern()); }, makeImpl: function (test, maskPattern) {
|
||||
this.moduleCount = this.typeNumber * 4 + 17; this.modules = new Array(this.moduleCount); for (var row = 0; row < this.moduleCount; row++) { this.modules[row] = new Array(this.moduleCount); for (var col = 0; col < this.moduleCount; col++) { this.modules[row][col] = null; } }
|
||||
this.setupPositionProbePattern(0, 0); this.setupPositionProbePattern(this.moduleCount - 7, 0); this.setupPositionProbePattern(0, this.moduleCount - 7); this.setupPositionAdjustPattern(); this.setupTimingPattern(); this.setupTypeInfo(test, maskPattern); if (this.typeNumber >= 7) { this.setupTypeNumber(test); }
|
||||
if (this.dataCache == null) { this.dataCache = QRCodeModel.createData(this.typeNumber, this.errorCorrectLevel, this.dataList); }
|
||||
this.mapData(this.dataCache, maskPattern);
|
||||
}, setupPositionProbePattern: function (row, col) { for (var r = -1; r <= 7; r++) { if (row + r <= -1 || this.moduleCount <= row + r) continue; for (var c = -1; c <= 7; c++) { if (col + c <= -1 || this.moduleCount <= col + c) continue; if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) { this.modules[row + r][col + c] = true; } else { this.modules[row + r][col + c] = false; } } } }, getBestMaskPattern: function () {
|
||||
var minLostPoint = 0; var pattern = 0; for (var i = 0; i < 8; i++) { this.makeImpl(true, i); var lostPoint = QRUtil.getLostPoint(this); if (i == 0 || minLostPoint > lostPoint) { minLostPoint = lostPoint; pattern = i; } }
|
||||
return pattern;
|
||||
}, createMovieClip: function (target_mc, instance_name, depth) {
|
||||
var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth); var cs = 1; this.make(); for (var row = 0; row < this.modules.length; row++) { var y = row * cs; for (var col = 0; col < this.modules[row].length; col++) { var x = col * cs; var dark = this.modules[row][col]; if (dark) { qr_mc.beginFill(0, 100); qr_mc.moveTo(x, y); qr_mc.lineTo(x + cs, y); qr_mc.lineTo(x + cs, y + cs); qr_mc.lineTo(x, y + cs); qr_mc.endFill(); } } }
|
||||
return qr_mc;
|
||||
}, setupTimingPattern: function () {
|
||||
for (var r = 8; r < this.moduleCount - 8; r++) {
|
||||
if (this.modules[r][6] != null) { continue; }
|
||||
this.modules[r][6] = (r % 2 == 0);
|
||||
}
|
||||
for (var c = 8; c < this.moduleCount - 8; c++) {
|
||||
if (this.modules[6][c] != null) { continue; }
|
||||
this.modules[6][c] = (c % 2 == 0);
|
||||
}
|
||||
}, setupPositionAdjustPattern: function () {
|
||||
var pos = QRUtil.getPatternPosition(this.typeNumber); for (var i = 0; i < pos.length; i++) {
|
||||
for (var j = 0; j < pos.length; j++) {
|
||||
var row = pos[i]; var col = pos[j]; if (this.modules[row][col] != null) { continue; }
|
||||
for (var r = -2; r <= 2; r++) { for (var c = -2; c <= 2; c++) { if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) { this.modules[row + r][col + c] = true; } else { this.modules[row + r][col + c] = false; } } }
|
||||
}
|
||||
}
|
||||
}, setupTypeNumber: function (test) {
|
||||
var bits = QRUtil.getBCHTypeNumber(this.typeNumber); for (var i = 0; i < 18; i++) { var mod = (!test && ((bits >> i) & 1) == 1); this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod; }
|
||||
for (var i = 0; i < 18; i++) { var mod = (!test && ((bits >> i) & 1) == 1); this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod; }
|
||||
}, setupTypeInfo: function (test, maskPattern) {
|
||||
var data = (this.errorCorrectLevel << 3) | maskPattern; var bits = QRUtil.getBCHTypeInfo(data); for (var i = 0; i < 15; i++) { var mod = (!test && ((bits >> i) & 1) == 1); if (i < 6) { this.modules[i][8] = mod; } else if (i < 8) { this.modules[i + 1][8] = mod; } else { this.modules[this.moduleCount - 15 + i][8] = mod; } }
|
||||
for (var i = 0; i < 15; i++) { var mod = (!test && ((bits >> i) & 1) == 1); if (i < 8) { this.modules[8][this.moduleCount - i - 1] = mod; } else if (i < 9) { this.modules[8][15 - i - 1 + 1] = mod; } else { this.modules[8][15 - i - 1] = mod; } }
|
||||
this.modules[this.moduleCount - 8][8] = (!test);
|
||||
}, mapData: function (data, maskPattern) {
|
||||
var inc = -1; var row = this.moduleCount - 1; var bitIndex = 7; var byteIndex = 0; for (var col = this.moduleCount - 1; col > 0; col -= 2) {
|
||||
if (col == 6) col--; while (true) {
|
||||
for (var c = 0; c < 2; c++) {
|
||||
if (this.modules[row][col - c] == null) {
|
||||
var dark = false; if (byteIndex < data.length) { dark = (((data[byteIndex] >>> bitIndex) & 1) == 1); }
|
||||
var mask = QRUtil.getMask(maskPattern, row, col - c); if (mask) { dark = !dark; }
|
||||
this.modules[row][col - c] = dark; bitIndex--; if (bitIndex == -1) { byteIndex++; bitIndex = 7; }
|
||||
}
|
||||
}
|
||||
row += inc; if (row < 0 || this.moduleCount <= row) { row -= inc; inc = -inc; break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
QRCodeModel.PAD0 = 0xEC;
|
||||
QRCodeModel.PAD1 = 0x11;
|
||||
QRCodeModel.createData = function (typeNumber, errorCorrectLevel, dataList) {
|
||||
var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); var buffer = new QRBitBuffer(); for (var i = 0; i < dataList.length; i++) { var data = dataList[i]; buffer.put(data.mode, 4); buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); data.write(buffer); }
|
||||
var totalDataCount = 0; for (var i = 0; i < rsBlocks.length; i++) { totalDataCount += rsBlocks[i].dataCount; }
|
||||
if (buffer.getLengthInBits() > totalDataCount * 8) {
|
||||
throw new Error("code length overflow. ("
|
||||
+ buffer.getLengthInBits()
|
||||
+ ">"
|
||||
+ totalDataCount * 8
|
||||
+ ")");
|
||||
}
|
||||
if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { buffer.put(0, 4); }
|
||||
while (buffer.getLengthInBits() % 8 != 0) { buffer.putBit(false); }
|
||||
while (true) {
|
||||
if (buffer.getLengthInBits() >= totalDataCount * 8) { break; }
|
||||
buffer.put(QRCodeModel.PAD0, 8); if (buffer.getLengthInBits() >= totalDataCount * 8) { break; }
|
||||
buffer.put(QRCodeModel.PAD1, 8);
|
||||
}
|
||||
return QRCodeModel.createBytes(buffer, rsBlocks);
|
||||
};
|
||||
QRCodeModel.createBytes = function (buffer, rsBlocks) {
|
||||
var offset = 0; var maxDcCount = 0; var maxEcCount = 0; var dcdata = new Array(rsBlocks.length); var ecdata = new Array(rsBlocks.length); for (var r = 0; r < rsBlocks.length; r++) {
|
||||
var dcCount = rsBlocks[r].dataCount; var ecCount = rsBlocks[r].totalCount - dcCount; maxDcCount = Math.max(maxDcCount, dcCount); maxEcCount = Math.max(maxEcCount, ecCount); dcdata[r] = new Array(dcCount); for (var i = 0; i < dcdata[r].length; i++) { dcdata[r][i] = 0xff & buffer.buffer[i + offset]; }
|
||||
offset += dcCount; var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1); var modPoly = rawPoly.mod(rsPoly); ecdata[r] = new Array(rsPoly.getLength() - 1); for (var i = 0; i < ecdata[r].length; i++) { var modIndex = i + modPoly.getLength() - ecdata[r].length; ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0; }
|
||||
}
|
||||
var totalCodeCount = 0; for (var i = 0; i < rsBlocks.length; i++) { totalCodeCount += rsBlocks[i].totalCount; }
|
||||
var data = new Array(totalCodeCount); var index = 0; for (var i = 0; i < maxDcCount; i++) { for (var r = 0; r < rsBlocks.length; r++) { if (i < dcdata[r].length) { data[index++] = dcdata[r][i]; } } }
|
||||
for (var i = 0; i < maxEcCount; i++) { for (var r = 0; r < rsBlocks.length; r++) { if (i < ecdata[r].length) { data[index++] = ecdata[r][i]; } } }
|
||||
return data;
|
||||
};
|
||||
var QRMode = { MODE_NUMBER: 1 << 0, MODE_ALPHA_NUM: 1 << 1, MODE_8BIT_BYTE: 1 << 2, MODE_KANJI: 1 << 3 };
|
||||
var QRErrorCorrectLevel = { L: 1, M: 0, Q: 3, H: 2 };
|
||||
var QRMaskPattern = { PATTERN000: 0, PATTERN001: 1, PATTERN010: 2, PATTERN011: 3, PATTERN100: 4, PATTERN101: 5, PATTERN110: 6, PATTERN111: 7 };
|
||||
var QRUtil = {
|
||||
PATTERN_POSITION_TABLE: [[], [6, 18], [6, 22], [6, 26], [6, 30], [6, 34], [6, 22, 38], [6, 24, 42], [6, 26, 46], [6, 28, 50], [6, 30, 54], [6, 32, 58], [6, 34, 62], [6, 26, 46, 66], [6, 26, 48, 70], [6, 26, 50, 74], [6, 30, 54, 78], [6, 30, 56, 82], [6, 30, 58, 86], [6, 34, 62, 90], [6, 28, 50, 72, 94], [6, 26, 50, 74, 98], [6, 30, 54, 78, 102], [6, 28, 54, 80, 106], [6, 32, 58, 84, 110], [6, 30, 58, 86, 114], [6, 34, 62, 90, 118], [6, 26, 50, 74, 98, 122], [6, 30, 54, 78, 102, 126], [6, 26, 52, 78, 104, 130], [6, 30, 56, 82, 108, 134], [6, 34, 60, 86, 112, 138], [6, 30, 58, 86, 114, 142], [6, 34, 62, 90, 118, 146], [6, 30, 54, 78, 102, 126, 150], [6, 24, 50, 76, 102, 128, 154], [6, 28, 54, 80, 106, 132, 158], [6, 32, 58, 84, 110, 136, 162], [6, 26, 54, 82, 110, 138, 166], [6, 30, 58, 86, 114, 142, 170]], G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0), G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0), G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1), getBCHTypeInfo: function (data) {
|
||||
var d = data << 10; while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) { d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15))); }
|
||||
return ((data << 10) | d) ^ QRUtil.G15_MASK;
|
||||
}, getBCHTypeNumber: function (data) {
|
||||
var d = data << 12; while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) { d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18))); }
|
||||
return (data << 12) | d;
|
||||
}, getBCHDigit: function (data) {
|
||||
var digit = 0; while (data != 0) { digit++; data >>>= 1; }
|
||||
return digit;
|
||||
}, getPatternPosition: function (typeNumber) { return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; }, getMask: function (maskPattern, i, j) { switch (maskPattern) { case QRMaskPattern.PATTERN000: return (i + j) % 2 == 0; case QRMaskPattern.PATTERN001: return i % 2 == 0; case QRMaskPattern.PATTERN010: return j % 3 == 0; case QRMaskPattern.PATTERN011: return (i + j) % 3 == 0; case QRMaskPattern.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0; case QRMaskPattern.PATTERN101: return (i * j) % 2 + (i * j) % 3 == 0; case QRMaskPattern.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 == 0; case QRMaskPattern.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 == 0; default: throw new Error("bad maskPattern:" + maskPattern); } }, getErrorCorrectPolynomial: function (errorCorrectLength) {
|
||||
var a = new QRPolynomial([1], 0); for (var i = 0; i < errorCorrectLength; i++) { a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0)); }
|
||||
return a;
|
||||
}, getLengthInBits: function (mode, type) { if (1 <= type && type < 10) { switch (mode) { case QRMode.MODE_NUMBER: return 10; case QRMode.MODE_ALPHA_NUM: return 9; case QRMode.MODE_8BIT_BYTE: return 8; case QRMode.MODE_KANJI: return 8; default: throw new Error("mode:" + mode); } } else if (type < 27) { switch (mode) { case QRMode.MODE_NUMBER: return 12; case QRMode.MODE_ALPHA_NUM: return 11; case QRMode.MODE_8BIT_BYTE: return 16; case QRMode.MODE_KANJI: return 10; default: throw new Error("mode:" + mode); } } else if (type < 41) { switch (mode) { case QRMode.MODE_NUMBER: return 14; case QRMode.MODE_ALPHA_NUM: return 13; case QRMode.MODE_8BIT_BYTE: return 16; case QRMode.MODE_KANJI: return 12; default: throw new Error("mode:" + mode); } } else { throw new Error("type:" + type); } }, getLostPoint: function (qrCode) {
|
||||
var moduleCount = qrCode.getModuleCount(); var lostPoint = 0; for (var row = 0; row < moduleCount; row++) {
|
||||
for (var col = 0; col < moduleCount; col++) {
|
||||
var sameCount = 0; var dark = qrCode.isDark(row, col); for (var r = -1; r <= 1; r++) {
|
||||
if (row + r < 0 || moduleCount <= row + r) { continue; }
|
||||
for (var c = -1; c <= 1; c++) {
|
||||
if (col + c < 0 || moduleCount <= col + c) { continue; }
|
||||
if (r == 0 && c == 0) { continue; }
|
||||
if (dark == qrCode.isDark(row + r, col + c)) { sameCount++; }
|
||||
}
|
||||
}
|
||||
if (sameCount > 5) { lostPoint += (3 + sameCount - 5); }
|
||||
}
|
||||
}
|
||||
for (var row = 0; row < moduleCount - 1; row++) { for (var col = 0; col < moduleCount - 1; col++) { var count = 0; if (qrCode.isDark(row, col)) count++; if (qrCode.isDark(row + 1, col)) count++; if (qrCode.isDark(row, col + 1)) count++; if (qrCode.isDark(row + 1, col + 1)) count++; if (count == 0 || count == 4) { lostPoint += 3; } } }
|
||||
for (var row = 0; row < moduleCount; row++) { for (var col = 0; col < moduleCount - 6; col++) { if (qrCode.isDark(row, col) && !qrCode.isDark(row, col + 1) && qrCode.isDark(row, col + 2) && qrCode.isDark(row, col + 3) && qrCode.isDark(row, col + 4) && !qrCode.isDark(row, col + 5) && qrCode.isDark(row, col + 6)) { lostPoint += 40; } } }
|
||||
for (var col = 0; col < moduleCount; col++) { for (var row = 0; row < moduleCount - 6; row++) { if (qrCode.isDark(row, col) && !qrCode.isDark(row + 1, col) && qrCode.isDark(row + 2, col) && qrCode.isDark(row + 3, col) && qrCode.isDark(row + 4, col) && !qrCode.isDark(row + 5, col) && qrCode.isDark(row + 6, col)) { lostPoint += 40; } } }
|
||||
var darkCount = 0; for (var col = 0; col < moduleCount; col++) { for (var row = 0; row < moduleCount; row++) { if (qrCode.isDark(row, col)) { darkCount++; } } }
|
||||
var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; lostPoint += ratio * 10; return lostPoint;
|
||||
}
|
||||
};
|
||||
var QRMath = {
|
||||
glog: function (n) {
|
||||
if (n < 1) { throw new Error("glog(" + n + ")"); }
|
||||
return QRMath.LOG_TABLE[n];
|
||||
}, gexp: function (n) {
|
||||
while (n < 0) { n += 255; }
|
||||
while (n >= 256) { n -= 255; }
|
||||
return QRMath.EXP_TABLE[n];
|
||||
}, EXP_TABLE: new Array(256), LOG_TABLE: new Array(256)
|
||||
}; for (var i = 0; i < 8; i++) { QRMath.EXP_TABLE[i] = 1 << i; }
|
||||
for (var i = 8; i < 256; i++) { QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8]; }
|
||||
for (var i = 0; i < 255; i++) { QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i; }
|
||||
function QRPolynomial(num, shift) {
|
||||
if (num.length == undefined) { throw new Error(num.length + "/" + shift); }
|
||||
var offset = 0; while (offset < num.length && num[offset] == 0) { offset++; }
|
||||
this.num = new Array(num.length - offset + shift); for (var i = 0; i < num.length - offset; i++) { this.num[i] = num[i + offset]; }
|
||||
}
|
||||
QRPolynomial.prototype = {
|
||||
get: function (index) { return this.num[index]; }, getLength: function () { return this.num.length; }, multiply: function (e) {
|
||||
var num = new Array(this.getLength() + e.getLength() - 1); for (var i = 0; i < this.getLength(); i++) { for (var j = 0; j < e.getLength(); j++) { num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j))); } }
|
||||
return new QRPolynomial(num, 0);
|
||||
}, mod: function (e) {
|
||||
if (this.getLength() - e.getLength() < 0) { return this; }
|
||||
var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0)); var num = new Array(this.getLength()); for (var i = 0; i < this.getLength(); i++) { num[i] = this.get(i); }
|
||||
for (var i = 0; i < e.getLength(); i++) { num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio); }
|
||||
return new QRPolynomial(num, 0).mod(e);
|
||||
}
|
||||
};
|
||||
function QRRSBlock(totalCount, dataCount) { this.totalCount = totalCount; this.dataCount = dataCount; }
|
||||
QRRSBlock.RS_BLOCK_TABLE = [[1, 26, 19], [1, 26, 16], [1, 26, 13], [1, 26, 9], [1, 44, 34], [1, 44, 28], [1, 44, 22], [1, 44, 16], [1, 70, 55], [1, 70, 44], [2, 35, 17], [2, 35, 13], [1, 100, 80], [2, 50, 32], [2, 50, 24], [4, 25, 9], [1, 134, 108], [2, 67, 43], [2, 33, 15, 2, 34, 16], [2, 33, 11, 2, 34, 12], [2, 86, 68], [4, 43, 27], [4, 43, 19], [4, 43, 15], [2, 98, 78], [4, 49, 31], [2, 32, 14, 4, 33, 15], [4, 39, 13, 1, 40, 14], [2, 121, 97], [2, 60, 38, 2, 61, 39], [4, 40, 18, 2, 41, 19], [4, 40, 14, 2, 41, 15], [2, 146, 116], [3, 58, 36, 2, 59, 37], [4, 36, 16, 4, 37, 17], [4, 36, 12, 4, 37, 13], [2, 86, 68, 2, 87, 69], [4, 69, 43, 1, 70, 44], [6, 43, 19, 2, 44, 20], [6, 43, 15, 2, 44, 16], [4, 101, 81], [1, 80, 50, 4, 81, 51], [4, 50, 22, 4, 51, 23], [3, 36, 12, 8, 37, 13], [2, 116, 92, 2, 117, 93], [6, 58, 36, 2, 59, 37], [4, 46, 20, 6, 47, 21], [7, 42, 14, 4, 43, 15], [4, 133, 107], [8, 59, 37, 1, 60, 38], [8, 44, 20, 4, 45, 21], [12, 33, 11, 4, 34, 12], [3, 145, 115, 1, 146, 116], [4, 64, 40, 5, 65, 41], [11, 36, 16, 5, 37, 17], [11, 36, 12, 5, 37, 13], [5, 109, 87, 1, 110, 88], [5, 65, 41, 5, 66, 42], [5, 54, 24, 7, 55, 25], [11, 36, 12], [5, 122, 98, 1, 123, 99], [7, 73, 45, 3, 74, 46], [15, 43, 19, 2, 44, 20], [3, 45, 15, 13, 46, 16], [1, 135, 107, 5, 136, 108], [10, 74, 46, 1, 75, 47], [1, 50, 22, 15, 51, 23], [2, 42, 14, 17, 43, 15], [5, 150, 120, 1, 151, 121], [9, 69, 43, 4, 70, 44], [17, 50, 22, 1, 51, 23], [2, 42, 14, 19, 43, 15], [3, 141, 113, 4, 142, 114], [3, 70, 44, 11, 71, 45], [17, 47, 21, 4, 48, 22], [9, 39, 13, 16, 40, 14], [3, 135, 107, 5, 136, 108], [3, 67, 41, 13, 68, 42], [15, 54, 24, 5, 55, 25], [15, 43, 15, 10, 44, 16], [4, 144, 116, 4, 145, 117], [17, 68, 42], [17, 50, 22, 6, 51, 23], [19, 46, 16, 6, 47, 17], [2, 139, 111, 7, 140, 112], [17, 74, 46], [7, 54, 24, 16, 55, 25], [34, 37, 13], [4, 151, 121, 5, 152, 122], [4, 75, 47, 14, 76, 48], [11, 54, 24, 14, 55, 25], [16, 45, 15, 14, 46, 16], [6, 147, 117, 4, 148, 118], [6, 73, 45, 14, 74, 46], [11, 54, 24, 16, 55, 25], [30, 46, 16, 2, 47, 17], [8, 132, 106, 4, 133, 107], [8, 75, 47, 13, 76, 48], [7, 54, 24, 22, 55, 25], [22, 45, 15, 13, 46, 16], [10, 142, 114, 2, 143, 115], [19, 74, 46, 4, 75, 47], [28, 50, 22, 6, 51, 23], [33, 46, 16, 4, 47, 17], [8, 152, 122, 4, 153, 123], [22, 73, 45, 3, 74, 46], [8, 53, 23, 26, 54, 24], [12, 45, 15, 28, 46, 16], [3, 147, 117, 10, 148, 118], [3, 73, 45, 23, 74, 46], [4, 54, 24, 31, 55, 25], [11, 45, 15, 31, 46, 16], [7, 146, 116, 7, 147, 117], [21, 73, 45, 7, 74, 46], [1, 53, 23, 37, 54, 24], [19, 45, 15, 26, 46, 16], [5, 145, 115, 10, 146, 116], [19, 75, 47, 10, 76, 48], [15, 54, 24, 25, 55, 25], [23, 45, 15, 25, 46, 16], [13, 145, 115, 3, 146, 116], [2, 74, 46, 29, 75, 47], [42, 54, 24, 1, 55, 25], [23, 45, 15, 28, 46, 16], [17, 145, 115], [10, 74, 46, 23, 75, 47], [10, 54, 24, 35, 55, 25], [19, 45, 15, 35, 46, 16], [17, 145, 115, 1, 146, 116], [14, 74, 46, 21, 75, 47], [29, 54, 24, 19, 55, 25], [11, 45, 15, 46, 46, 16], [13, 145, 115, 6, 146, 116], [14, 74, 46, 23, 75, 47], [44, 54, 24, 7, 55, 25], [59, 46, 16, 1, 47, 17], [12, 151, 121, 7, 152, 122], [12, 75, 47, 26, 76, 48], [39, 54, 24, 14, 55, 25], [22, 45, 15, 41, 46, 16], [6, 151, 121, 14, 152, 122], [6, 75, 47, 34, 76, 48], [46, 54, 24, 10, 55, 25], [2, 45, 15, 64, 46, 16], [17, 152, 122, 4, 153, 123], [29, 74, 46, 14, 75, 47], [49, 54, 24, 10, 55, 25], [24, 45, 15, 46, 46, 16], [4, 152, 122, 18, 153, 123], [13, 74, 46, 32, 75, 47], [48, 54, 24, 14, 55, 25], [42, 45, 15, 32, 46, 16], [20, 147, 117, 4, 148, 118], [40, 75, 47, 7, 76, 48], [43, 54, 24, 22, 55, 25], [10, 45, 15, 67, 46, 16], [19, 148, 118, 6, 149, 119], [18, 75, 47, 31, 76, 48], [34, 54, 24, 34, 55, 25], [20, 45, 15, 61, 46, 16]];
|
||||
QRRSBlock.getRSBlocks = function (typeNumber, errorCorrectLevel) {
|
||||
var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel); if (rsBlock == undefined) { throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel); }
|
||||
var length = rsBlock.length / 3; var list = []; for (var i = 0; i < length; i++) { var count = rsBlock[i * 3 + 0]; var totalCount = rsBlock[i * 3 + 1]; var dataCount = rsBlock[i * 3 + 2]; for (var j = 0; j < count; j++) { list.push(new QRRSBlock(totalCount, dataCount)); } }
|
||||
return list;
|
||||
};
|
||||
QRRSBlock.getRsBlockTable = function (typeNumber, errorCorrectLevel) { switch (errorCorrectLevel) { case QRErrorCorrectLevel.L: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; case QRErrorCorrectLevel.M: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; case QRErrorCorrectLevel.Q: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; case QRErrorCorrectLevel.H: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; default: return undefined; } };
|
||||
function QRBitBuffer() { this.buffer = []; this.length = 0; }
|
||||
QRBitBuffer.prototype = {
|
||||
get: function (index) { var bufIndex = Math.floor(index / 8); return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1; }, put: function (num, length) { for (var i = 0; i < length; i++) { this.putBit(((num >>> (length - i - 1)) & 1) == 1); } }, getLengthInBits: function () { return this.length; }, putBit: function (bit) {
|
||||
var bufIndex = Math.floor(this.length / 8); if (this.buffer.length <= bufIndex) { this.buffer.push(0); }
|
||||
if (bit) { this.buffer[bufIndex] |= (0x80 >>> (this.length % 8)); }
|
||||
this.length++;
|
||||
}
|
||||
};
|
||||
var QRCodeLimitLength = [[17, 14, 11, 7], [32, 26, 20, 14], [53, 42, 32, 24], [78, 62, 46, 34], [106, 84, 60, 44], [134, 106, 74, 58], [154, 122, 86, 64], [192, 152, 108, 84], [230, 180, 130, 98], [271, 213, 151, 119], [321, 251, 177, 137], [367, 287, 203, 155], [425, 331, 241, 177], [458, 362, 258, 194], [520, 412, 292, 220], [586, 450, 322, 250], [644, 504, 364, 280], [718, 560, 394, 310], [792, 624, 442, 338], [858, 666, 482, 382], [929, 711, 509, 403], [1003, 779, 565, 439], [1091, 857, 611, 461], [1171, 911, 661, 511], [1273, 997, 715, 535], [1367, 1059, 751, 593], [1465, 1125, 805, 625], [1528, 1190, 868, 658], [1628, 1264, 908, 698], [1732, 1370, 982, 742], [1840, 1452, 1030, 790], [1952, 1538, 1112, 842], [2068, 1628, 1168, 898], [2188, 1722, 1228, 958], [2303, 1809, 1283, 983], [2431, 1911, 1351, 1051], [2563, 1989, 1423, 1093], [2699, 2099, 1499, 1139], [2809, 2213, 1579, 1219], [2953, 2331, 1663, 1273]];
|
||||
|
||||
// QRCode object
|
||||
QRCode = function (canvasId, vOption) {
|
||||
this._htOption = {
|
||||
width: 256,
|
||||
height: 256,
|
||||
typeNumber: 4,
|
||||
colorDark: "#000000",
|
||||
colorLight: "#ffffff",
|
||||
correctLevel: QRErrorCorrectLevel.H
|
||||
};
|
||||
|
||||
if (typeof vOption === 'string') {
|
||||
vOption = {
|
||||
text: vOption
|
||||
};
|
||||
}
|
||||
|
||||
// Overwrites options
|
||||
if (vOption) {
|
||||
for (var i in vOption) {
|
||||
this._htOption[i] = vOption[i];
|
||||
}
|
||||
}
|
||||
|
||||
this._oQRCode = null;
|
||||
this.canvasId = canvasId
|
||||
|
||||
if (this._htOption.text && this.canvasId) {
|
||||
this.makeCode(this._htOption.text);
|
||||
}
|
||||
};
|
||||
|
||||
QRCode.prototype.makeCode = function (sText) {
|
||||
this._oQRCode = new QRCodeModel(_getTypeNumber(sText, this._htOption.correctLevel), this._htOption.correctLevel);
|
||||
this._oQRCode.addData(sText);
|
||||
this._oQRCode.make();
|
||||
this.makeImage();
|
||||
};
|
||||
|
||||
QRCode.prototype.makeImage = function () {
|
||||
var _oContext
|
||||
if (this._htOption.usingIn) {
|
||||
_oContext = wx.createCanvasContext(this.canvasId, this._htOption.usingIn)
|
||||
}
|
||||
else {
|
||||
_oContext = wx.createCanvasContext(this.canvasId)
|
||||
}
|
||||
var _htOption = this._htOption;
|
||||
var oQRCode = this._oQRCode
|
||||
|
||||
var nCount = oQRCode.getModuleCount();
|
||||
var nWidth = _htOption.width / nCount;
|
||||
var nHeight = _htOption.height / nCount;
|
||||
var nRoundedWidth = Math.round(nWidth);
|
||||
var nRoundedHeight = Math.round(nHeight);
|
||||
|
||||
if (_htOption.image && _htOption.image != '') {
|
||||
_oContext.drawImage(_htOption.image, 0, 0, _htOption.width, _htOption.height)
|
||||
}
|
||||
|
||||
for (var row = 0; row < nCount; row++) {
|
||||
for (var col = 0; col < nCount; col++) {
|
||||
var bIsDark = oQRCode.isDark(row, col);
|
||||
var nLeft = col * nWidth;
|
||||
var nTop = row * nHeight;
|
||||
_oContext.setStrokeStyle(bIsDark ? _htOption.colorDark : _htOption.colorLight)
|
||||
// _oContext.setStrokeStyle('yellow')
|
||||
_oContext.setLineWidth(1)
|
||||
_oContext.setFillStyle(bIsDark ? _htOption.colorDark : _htOption.colorLight)
|
||||
// _oContext.setFillStyle('red')
|
||||
// if (bIsDark) {
|
||||
_oContext.fillRect(nLeft, nTop, nWidth, nHeight);
|
||||
// }
|
||||
|
||||
// 안티 앨리어싱 방지 처리
|
||||
// if (bIsDark) {
|
||||
_oContext.strokeRect(
|
||||
Math.floor(nLeft) + 0.5,
|
||||
Math.floor(nTop) + 0.5,
|
||||
nRoundedWidth,
|
||||
nRoundedHeight
|
||||
);
|
||||
|
||||
_oContext.strokeRect(
|
||||
Math.ceil(nLeft) - 0.5,
|
||||
Math.ceil(nTop) - 0.5,
|
||||
nRoundedWidth,
|
||||
nRoundedHeight
|
||||
);
|
||||
// }
|
||||
// _oContext.fillRect(
|
||||
// Math.floor(nLeft) + 0.5,
|
||||
// Math.floor(nTop) + 0.5,
|
||||
// nRoundedWidth,
|
||||
// nRoundedHeight
|
||||
// );
|
||||
// _oContext.fillRect(
|
||||
// Math.ceil(nLeft) - 0.5,
|
||||
// Math.ceil(nTop) - 0.5,
|
||||
// nRoundedWidth,
|
||||
// nRoundedHeight
|
||||
// );
|
||||
// _oContext.clearRect(
|
||||
// Math.floor(nLeft) + 0.5,
|
||||
// Math.floor(nTop) + 0.5,
|
||||
// nRoundedWidth,
|
||||
// nRoundedHeight
|
||||
// );
|
||||
// _oContext.clearRect(
|
||||
// Math.ceil(nLeft) - 0.5,
|
||||
// Math.ceil(nTop) - 0.5,
|
||||
// nRoundedWidth,
|
||||
// nRoundedHeight
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
_oContext.draw()
|
||||
};
|
||||
|
||||
QRCode.prototype.exportImage = function (callback) {
|
||||
if (!callback) {
|
||||
return
|
||||
}
|
||||
wx.canvasToTempFilePath({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: this._htOption.width,
|
||||
height: this._htOption.height,
|
||||
destWidth: this._htOption.width,
|
||||
destHeight: this._htOption.height,
|
||||
canvasId: this.canvasId,
|
||||
success: function (res) {
|
||||
console.log(res.tempFilePath)
|
||||
callback(res.tempFilePath)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
QRCode.CorrectLevel = QRErrorCorrectLevel;
|
||||
})();
|
||||
|
||||
module.exports = QRCode
|
||||
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* https://github.com/caiya/wxTimer
|
||||
*/
|
||||
|
||||
var wxTimer = function(initObj) {
|
||||
initObj = initObj || {};
|
||||
this.leftTime = initObj.leftTime || 0; //开始时间
|
||||
this.interval = initObj.interval || 1; //间隔时间
|
||||
this.complete = initObj.complete; //结束任务
|
||||
this.intervalFn = initObj.intervalFn; //间隔任务
|
||||
this.name = initObj.name; //当前计时器在计时器数组对象中的名字
|
||||
|
||||
this.intervarID; //计时ID
|
||||
};
|
||||
|
||||
wxTimer.prototype = {
|
||||
dateformat: function(micro_second) {
|
||||
// 总秒数
|
||||
var second = Math.floor(micro_second);
|
||||
// 天数
|
||||
var day = Math.floor(second / 3600 / 24);
|
||||
|
||||
// 总小时
|
||||
var hr = Math.floor(second / 3600);
|
||||
// 小时位
|
||||
var hr2 = hr % 24;
|
||||
// 分钟位
|
||||
var min = Math.floor((second - hr * 3600) / 60);
|
||||
// 秒位
|
||||
var sec = second - hr * 3600 - min * 60; // equal to => var sec = second % 60;
|
||||
// 毫秒位,保留2位
|
||||
var micro_sec = Math.floor((micro_second % 1000) / 10);
|
||||
return hr2;
|
||||
},
|
||||
dateformat_hur: function(micro_second) {
|
||||
// 总秒数
|
||||
var second = Math.floor(micro_second);
|
||||
// 天数
|
||||
var day = Math.floor(second / 3600 / 24);
|
||||
|
||||
// 总小时
|
||||
var hr = Math.floor(second / 3600);
|
||||
// 小时位
|
||||
var hr2 = hr % 24;
|
||||
// 分钟位
|
||||
var min = Math.floor((second - hr * 3600) / 60);
|
||||
// 秒位
|
||||
var sec = second - hr * 3600 - min * 60; // equal to => var sec = second % 60;
|
||||
// 毫秒位,保留2位
|
||||
var micro_sec = Math.floor((micro_second % 1000) / 10);
|
||||
return min;
|
||||
},
|
||||
dateformat_tim: function(micro_second) {
|
||||
// 总秒数
|
||||
var second = Math.floor(micro_second);
|
||||
// 天数
|
||||
var day = Math.floor(second / 3600 / 24);
|
||||
|
||||
// 总小时
|
||||
var hr = Math.floor(second / 3600);
|
||||
// 小时位
|
||||
var hr2 = hr % 24;
|
||||
// 分钟位
|
||||
var min = Math.floor((second - hr * 3600) / 60);
|
||||
// 秒位
|
||||
var sec = second - hr * 3600 - min * 60; // equal to => var sec = second % 60;
|
||||
// 毫秒位,保留2位
|
||||
var micro_sec = Math.floor((micro_second % 1000) / 10);
|
||||
return sec;
|
||||
},
|
||||
dateformats: function(micro_second) {
|
||||
// 总秒数
|
||||
var second = Math.floor(micro_second);
|
||||
var day = Math.floor(second / 3600 / 24);
|
||||
// 总小时
|
||||
var hr = Math.floor(second / 3600);
|
||||
// 小时位
|
||||
var hr2 = hr % 24;
|
||||
// 分钟位
|
||||
var min = Math.floor((second - hr * 3600) / 60);
|
||||
// 秒位
|
||||
var sec = second - hr * 3600 - min * 60; // equal to => var sec = second % 60;
|
||||
// 毫秒位,保留2位
|
||||
var micro_sec = Math.floor((micro_second % 1000) / 10);
|
||||
return day;
|
||||
},
|
||||
//开始
|
||||
start: function(self) {
|
||||
var that = this;
|
||||
//开始倒计时
|
||||
var count = 0; //这个count在这里应该是表示s数,js中获得时间是ms,所以下面*1000都换成ms
|
||||
function begin() {
|
||||
var collageHour = that.dateformat(that.leftTime); //时
|
||||
var collageDay = that.dateformats(that.leftTime); //天
|
||||
var collageMin = that.dateformat_hur(that.leftTime); //分
|
||||
var collageTim = that.dateformat_tim(that.leftTime); //秒
|
||||
var tmpTimeStr = `${collageDay}天${collageHour}时${collageMin}分${collageTim}秒`;
|
||||
var wxTimerList = self.data.wxTimerList;
|
||||
|
||||
//更新计时器数组
|
||||
wxTimerList[that.name] = {
|
||||
wxTimer: tmpTimeStr
|
||||
};
|
||||
|
||||
self.setData({
|
||||
wxTimer: tmpTimeStr,
|
||||
wxTimerList: wxTimerList
|
||||
});
|
||||
//时间间隔执行函数
|
||||
if (0 == that.leftTime-- % that.interval && that.intervalFn) {
|
||||
that.intervalFn();
|
||||
}
|
||||
//结束执行函数
|
||||
if (that.leftTime <= 0) {
|
||||
if (that.complete) {
|
||||
that.complete();
|
||||
}
|
||||
that.stop();
|
||||
}
|
||||
}
|
||||
begin();
|
||||
this.intervarID = setInterval(begin, 1000);
|
||||
},
|
||||
//结束
|
||||
stop: function() {
|
||||
clearInterval(this.intervarID);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = wxTimer;
|
||||
@@ -0,0 +1,729 @@
|
||||
import Config from '../config';
|
||||
import { HttpNoUkeyRequest, HttpRequest, asyncLogin, app } from 'httpRequest';
|
||||
|
||||
let apiQuery = Object.assign({});
|
||||
// console.log(apiQuery)
|
||||
|
||||
apiQuery.asyncLogin = asyncLogin;
|
||||
|
||||
apiQuery.getUserInfo = function (params,isLoading=true) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(isLoading, Config.api.appUser, 2, params, "GET", function (res) {
|
||||
app.setStorage("userInfo", res.data);
|
||||
resolve(res.data);
|
||||
}, reject)
|
||||
})
|
||||
}
|
||||
|
||||
apiQuery.putUserInfo = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(true, Config.api.appUser, 2, params, "PUT", function (res) {
|
||||
console.log(res)
|
||||
app.setStorage("userInfo", res.data);
|
||||
resolve(res.data);
|
||||
}, reject)
|
||||
})
|
||||
}
|
||||
|
||||
//用户信息授权
|
||||
apiQuery.authUserInfo = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
wx.getSetting({
|
||||
success(res) {
|
||||
let userInfo = app.getStorageByKey("userInfo");
|
||||
console.log(res.authSetting)
|
||||
if (res.authSetting['scope.userInfo']) {
|
||||
if (!userInfo.nickname || !userInfo.headimg || (userInfo.headimg != JSON.parse(params.detail.rawData).avatarUrl)) {
|
||||
asyncLogin().then(res => {
|
||||
apiQuery.putUserInfo({
|
||||
encryptedData: params.detail.encryptedData,
|
||||
iv: params.detail.iv
|
||||
}).then(res => {
|
||||
//设置本地存储
|
||||
resolve(res)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
resolve(userInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//用户手机号码授权
|
||||
apiQuery.authUserPhone = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (params.detail.errMsg.indexOf("deny") === -1) {
|
||||
asyncLogin().then(res => {
|
||||
apiQuery.putUserInfo({
|
||||
encryptedData: params.detail.encryptedData,
|
||||
iv: params.detail.iv
|
||||
}).then(res => {
|
||||
//设置本地存储
|
||||
resolve(res)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
wx.showToast({
|
||||
title: '您拒绝授权,将无法进行更多操作!',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
reject();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
apiQuery.putLogin = function(params){
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpNoUkeyRequest(false, Config.api.appUserUkey, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送验证码
|
||||
*/
|
||||
apiQuery.getAppOtherMcode = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpNoUkeyRequest(false, Config.api.appOtherMcode, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
apiQuery.putLogout = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appUserUkey, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑拨打电话
|
||||
*/
|
||||
apiQuery.putAppUserTel = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appUserTel, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户信息//废弃
|
||||
*/
|
||||
apiQuery.getAppUser = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(true, Config.api.appUser, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页图标
|
||||
*/
|
||||
apiQuery.getAppHomeIcon = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appHomeIcon, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 店铺列表
|
||||
*/
|
||||
apiQuery.getAppBiz = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appBiz, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销记录列表
|
||||
*/
|
||||
apiQuery.getAppExchange = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appExchange, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销tab
|
||||
*/
|
||||
apiQuery.getAppExchangeTab = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appExchangeTab, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销
|
||||
*/
|
||||
apiQuery.putAppExchange = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appExchange, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 接单宝tab
|
||||
*/
|
||||
apiQuery.getAppReceiverTab = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appReceiverTab, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 接单宝列表
|
||||
*/
|
||||
apiQuery.getAppReceiverList = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appReceiver, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 接单宝详情
|
||||
*/
|
||||
apiQuery.getAppReceiverInfo = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(true, Config.api.appReceiver, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 接单宝编辑
|
||||
*/
|
||||
apiQuery.putAppReceiver = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appReceiver, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 接单宝温馨提示
|
||||
*/
|
||||
apiQuery.getAppReceiverTip = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appReceiverTip, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 接单宝小记
|
||||
*/
|
||||
apiQuery.getAppReceiverLogs = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appReceiverLogs, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 接单宝获取订单手机号
|
||||
*/
|
||||
apiQuery.getAppYx = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appYx, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权保存用户信息
|
||||
*/
|
||||
apiQuery.putAppUser = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appUser, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 私域通首页
|
||||
*/
|
||||
apiQuery.getAppSythome = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appSythome, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 推广活动菜单
|
||||
*/
|
||||
apiQuery.getSytactivityMenu = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.sytactivityMenu, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 推广活动列表
|
||||
*/
|
||||
apiQuery.getAppSytactivity = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appSytactivity, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 推广活动编辑
|
||||
*/
|
||||
apiQuery.putAppSytactivity = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appSytactivity, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 推广活动详情
|
||||
*/
|
||||
apiQuery.getSytactivityDetail = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.sytactivityDetail, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 活动业绩
|
||||
*/
|
||||
apiQuery.getSytactivityAchievement = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.sytactivityAchievement, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 活动业绩-实时战报
|
||||
*/
|
||||
apiQuery.getSytactivityAchievementData = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.sytactivityAchievementData, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 活动业绩-kpi数据
|
||||
*/
|
||||
apiQuery.getSytactivityAchievementKpi = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.sytactivityAchievementKpi, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 团队管理
|
||||
*/
|
||||
apiQuery.getAppSytteam = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appSytteam, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 团队管理-发起团队
|
||||
*/
|
||||
apiQuery.putAppSytteam = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appSytteam, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 团队管理-菜单
|
||||
*/
|
||||
apiQuery.getSytteamMenu = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.sytteamMenu, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 团队管理-任命团长
|
||||
*/
|
||||
apiQuery.putSytteamLeader = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.sytteamLeader, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 今日战报-TOP3
|
||||
*/
|
||||
apiQuery.getSytteamZb_top = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.sytteamZb_top, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 今日战报-菜单
|
||||
*/
|
||||
apiQuery.getSytteamZb_menu = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.sytteamZb_menu, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 今日战报-列表
|
||||
*/
|
||||
apiQuery.getSytteamZb_list = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.sytteamZb_list, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 店铺订单宝/客多宝
|
||||
*/
|
||||
apiQuery.getBizTreasures = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.bizTreasures, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 客多宝-tab
|
||||
*/
|
||||
apiQuery.getCustomerTab = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.customerTab, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 客多宝-列表
|
||||
*/
|
||||
apiQuery.getAppCustomer = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appCustomer, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 活动业绩-活动明细
|
||||
*/
|
||||
apiQuery.getAchievementDetail = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.achievement_detail, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 接单宝-分配订单
|
||||
*/
|
||||
apiQuery.putReceiverOrders = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.receiverOrders, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 电销通首页
|
||||
*/
|
||||
apiQuery.getDxtHome = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtHome, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户_基础信息 /作废,移到客多宝
|
||||
*/
|
||||
apiQuery.getDxtCustomerField = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtCustomerField, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户_新增/编辑 /作废,移到客多宝
|
||||
*/
|
||||
apiQuery.putDxtCustomer = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(true, Config.api.dxtCustomer, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 员工管理_菜单
|
||||
*/
|
||||
apiQuery.getDxtEmployeesMenu = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtEmployeesMenu, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 员工管理_列表
|
||||
*/
|
||||
apiQuery.getDxtEmployees = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtEmployees, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* //员工管理_修改状态
|
||||
*/
|
||||
apiQuery.putDxtEmployeesStatus = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtEmployeesStatus, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* //员工管理_新增/修改信息
|
||||
*/
|
||||
apiQuery.putDxtEmployeesInfo = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtEmployeesInfo, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* //员工管理_一键迁移
|
||||
*/
|
||||
apiQuery.putDxtMigration = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtMigration, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 对接人列表
|
||||
*/
|
||||
apiQuery.getCustomerDockingPeople = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.customerDockingPeople, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* //客户_分配 /作废,移到客多宝
|
||||
*/
|
||||
apiQuery.putDxtCustomerUb = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtCustomerUb, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* //客户_更新小记 /作废,移到客多宝
|
||||
*/
|
||||
apiQuery.putDxtCustomerLog = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtCustomerLog, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户_列表
|
||||
*/
|
||||
apiQuery.getDxtCustomerList = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtCustomer, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 员工管理_员工详情
|
||||
*/
|
||||
apiQuery.getDxtEmployeesInfo = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtEmployeesInfo, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户_详情 /作废,移到客多宝
|
||||
*/
|
||||
apiQuery.getDxtCustomerInfo = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtCustomerInfo, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户_小记 /作废,移到客多宝
|
||||
*/
|
||||
apiQuery.getDxtCustomerLogs = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtCustomerLogs, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 基础设置信息
|
||||
*/
|
||||
apiQuery.getCustomerSetting = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.customerSetting, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* //基础设置
|
||||
*/
|
||||
apiQuery.putCustomerSetting = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.customerSetting, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据分析
|
||||
*/
|
||||
apiQuery.getDxtAnalysis = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtAnalysis, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据分析_趋势图
|
||||
*/
|
||||
apiQuery.getDxtAnalysisChart = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtAnalysisChart, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 话费清单
|
||||
*/
|
||||
apiQuery.getDxtPhoneBill = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.dxtPhoneBill, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户_基础信息
|
||||
*/
|
||||
apiQuery.getCustomerField = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.customerField, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* //客户_新增/编辑
|
||||
*/
|
||||
apiQuery.putCustomerField = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.customerField, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* //客户_分配
|
||||
*/
|
||||
apiQuery.putCustomerDistribution = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.customerDistribution, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户_详情
|
||||
*/
|
||||
apiQuery.getCustomerInfo = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.customerInfo, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户_更新小记
|
||||
*/
|
||||
apiQuery.getCustomerLogs = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.customerLogs, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* //客户_新增/编辑
|
||||
*/
|
||||
apiQuery.putCustomerLog = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.customerLog, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户_列表状态
|
||||
*/
|
||||
apiQuery.getCustomerStatus = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.customerStatus, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
//客户信息修改
|
||||
apiQuery.putReceiverCustomer = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.receiverCustomer, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
//订单保列表
|
||||
apiQuery.getAppOrder = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appOrder, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
//订单保顶部菜单
|
||||
apiQuery.getOrderMenu = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.orderMenu, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
//订单保详情
|
||||
apiQuery.getOrderDetail = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.orderDetail, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
//同意核销
|
||||
apiQuery.putOrderStatusAgree = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.orderStatus, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
//拒绝核销
|
||||
apiQuery.putOrderStatusRefuse = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.orderStatus, 2, params, "PUT", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
//帐户余额_顶部菜单
|
||||
apiQuery.getOrderAccountMenu = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.orderAccountMenu, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
//帐户余额_列表
|
||||
apiQuery.getOrderAccount = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.orderAccount, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
//(新)接单宝获取订单手机号
|
||||
apiQuery.getAppXz = function (params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
HttpRequest(false, Config.api.appXz, 2, params, "GET", resolve, reject)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export default apiQuery;
|
||||
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* 绘制圆角矩形
|
||||
* @param {Object} context - canvas组件的绘图上下文
|
||||
* @param {Number} x - 矩形的x坐标
|
||||
* @param {Number} y - 矩形的y坐标
|
||||
* @param {Number} w - 矩形的宽度
|
||||
* @param {Number} h - 矩形的高度
|
||||
* @param {Number} r - 矩形的圆角半径
|
||||
* @param {String} [c = 'transparent'] - 矩形的填充色
|
||||
*/
|
||||
const roundRect = (context, x, y, w, h, r, c = 'transparent') => {
|
||||
if (w < 2 * r) {
|
||||
r = w / 2;
|
||||
}
|
||||
if (h < 2 * r) {
|
||||
r = h / 2;
|
||||
}
|
||||
|
||||
context.beginPath();
|
||||
context.fillStyle = c;
|
||||
|
||||
context.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
|
||||
context.moveTo(x + r, y);
|
||||
context.lineTo(x + w - r, y);
|
||||
context.lineTo(x + w, y + r);
|
||||
|
||||
context.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2);
|
||||
context.lineTo(x + w, y + h - r);
|
||||
context.lineTo(x + w - r, y + h);
|
||||
|
||||
context.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5);
|
||||
context.lineTo(x + r, y + h);
|
||||
context.lineTo(x, y + h - r);
|
||||
|
||||
context.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI);
|
||||
context.lineTo(x, y + r);
|
||||
context.lineTo(x + r, y);
|
||||
|
||||
context.fill();
|
||||
context.closePath();
|
||||
};
|
||||
|
||||
/**
|
||||
* 绘制圆角图片
|
||||
* @param {Object} context - canvas组件的绘图上下文
|
||||
* @param {Number} r - 圆角半径
|
||||
* @param {String} path - 图片地址
|
||||
* @param {Number} sx - 源图像的矩形选择框的左上角 x 坐标
|
||||
* @param {Number} sy - 源图像的矩形选择框的左上角 y 坐标
|
||||
* @param {Number} sWidth - 源图像的矩形选择框的宽度
|
||||
* @param {Number} sHeight - 源图像的矩形选择框的高度
|
||||
* @param {Number} dx - 图像的左上角在目标 canvas 上 x 轴的位置
|
||||
* @param {Number} dy - 图像的左上角在目标 canvas 上 y 轴的位置
|
||||
* @param {Number} dWidth - 在目标画布上绘制图像的宽度,允许对绘制的图像进行缩放
|
||||
* @param {Number} dHeight - 在目标画布上绘制图像的高度,允许对绘制的图像进行缩放
|
||||
* @param {String} c - 矩形的填充色
|
||||
*/
|
||||
const roundImage = (context, r, path, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, c) => {
|
||||
context.save();
|
||||
roundRect(context, dx, dy, dWidth, dHeight, r, c);
|
||||
context.fill();
|
||||
context.clip();
|
||||
context.drawImage(path, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
|
||||
context.restore();
|
||||
};
|
||||
|
||||
/**
|
||||
* 绘制圆形图片
|
||||
* @param {Object} context - canvas组件的绘图上下文
|
||||
* @param {String} path - 图片地址
|
||||
* @param {Number} x - 图片的x坐标
|
||||
* @param {Number} y - 图片的y坐标
|
||||
* @param {Number} r - 图片的半径
|
||||
*/
|
||||
const circleImage = (context, path, x, y, r) => {
|
||||
let d = 2 * r;
|
||||
let cx = x + r;
|
||||
let cy = y + r;
|
||||
|
||||
context.save();
|
||||
context.beginPath();
|
||||
context.arc(cx, cy, r, 0, 2 * Math.PI);
|
||||
context.fill();
|
||||
context.clip();
|
||||
context.drawImage(path, x, y, d, d);
|
||||
context.restore();
|
||||
};
|
||||
|
||||
/**
|
||||
* 多行文本溢出
|
||||
* @param {Object} context - canvas组件的绘图上下文
|
||||
* @param {String} text - 文本内容
|
||||
* @param {Number} maxWidth - 文本最大宽度
|
||||
* @param {Number} maxRow - 文本最多显示行数
|
||||
* @param {String} font - 字体样式
|
||||
* @param {String} color - 文本颜色
|
||||
* @param {Number} lineHeight - 文本行高
|
||||
* @param {Number} x - 文本的x坐标
|
||||
* @param {Number} y - 文本的y坐标
|
||||
* @param {String} align - 文本居左居右
|
||||
* @param {String} decoration - 文字装饰,支持 underline、 overline、 line-through
|
||||
*/
|
||||
const drawTextOverflow = (context, text, maxWidth, maxRow, font, color, lineHeight, x, y,align='left',decoration='') => {
|
||||
let arr = [];
|
||||
let temp = '';
|
||||
let row = [];
|
||||
|
||||
text = text.replace(/[\r\n]/g, ''); // 去除回车换行符
|
||||
arr = text.split('');
|
||||
|
||||
//context.font = font; // 注意:一定要先设置字号,否则会出现文本变形
|
||||
context.setFontSize(font);
|
||||
context.setFillStyle(color);
|
||||
context.setTextAlign(align);
|
||||
|
||||
if (context.measureText(text).width <= maxWidth) {
|
||||
row.push(text);
|
||||
} else {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
// 超出最大行数且字符有剩余,添加...
|
||||
if (row.length == maxRow && i < arr.length - 1) {
|
||||
row[row.length - 1] += '...';
|
||||
break;
|
||||
}
|
||||
|
||||
// 字符换行计算
|
||||
if (context.measureText(temp).width < maxWidth) {
|
||||
temp += arr[i];
|
||||
|
||||
// 遍历到最后一位字符
|
||||
if (i === arr.length - 1) {
|
||||
row.push(temp);
|
||||
}
|
||||
} else {
|
||||
i--; // 防止字符丢失
|
||||
row.push(temp);
|
||||
temp = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制文本
|
||||
for (let i = 0; i < row.length; i++) {
|
||||
context.fillText(row[i], x, y + i * lineHeight, maxWidth);
|
||||
}
|
||||
|
||||
let measuredWith = context.measureText(text).width
|
||||
if (decoration) {
|
||||
context.beginPath();
|
||||
|
||||
if (/\bunderline\b/.test(decoration)) {
|
||||
context.moveTo(x, y);
|
||||
context.lineTo(x + measuredWith, y);
|
||||
}
|
||||
|
||||
if (/\boverline\b/.test(decoration)) {
|
||||
context.moveTo(x, y - font);
|
||||
context.lineTo(x + measuredWith, y - font);
|
||||
}
|
||||
|
||||
if (/\bline-through\b/.test(decoration)) {
|
||||
context.moveTo(x, y - font / 3);
|
||||
context.lineTo(x + measuredWith, y - font / 3);
|
||||
}
|
||||
|
||||
context.closePath();
|
||||
context.strokeStyle = color;
|
||||
context.stroke();
|
||||
}
|
||||
|
||||
context.save()
|
||||
return row.length * lineHeight; // 返回文本高度
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
roundRect,
|
||||
roundImage,
|
||||
circleImage,
|
||||
drawTextOverflow
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
|
||||
import Config from '../config';
|
||||
import { toEncrypt, randomString } from 'stringEncrypt';
|
||||
let app = getApp();
|
||||
|
||||
function HttpNoUkeyRequest(loading, url, sessionChoose, params, method, callBack, reject) {
|
||||
if (loading == true) {
|
||||
wx.showLoading();
|
||||
}
|
||||
let paramSession = sessionChoose == 1 ? {
|
||||
'content-type': 'application/x-www-form-urlencoded'
|
||||
} : {
|
||||
'content-type': 'application/json'
|
||||
};
|
||||
var params = Object.prototype.toString.call(params) == "[object Object]" ? params : {};
|
||||
params["version"] = Config.version;
|
||||
params["nonce_str"] = randomString();
|
||||
params["app_id"] = Config.app_id;
|
||||
let serectParams = {
|
||||
...params,
|
||||
sign: toEncrypt(params)
|
||||
}
|
||||
|
||||
wx.request({
|
||||
url: Config.api.baseUrl + url,
|
||||
data: serectParams,
|
||||
dataType: "json",
|
||||
header: paramSession,
|
||||
method: method,
|
||||
success: function (res) {
|
||||
// console.log(res.data);
|
||||
if (loading == true) {
|
||||
wx.hideLoading(); //隐藏提示框
|
||||
}
|
||||
//token 存在 还返回408,这个时候就要强制
|
||||
if (res.data.code == 408) {
|
||||
if (getCurrentPages().pop().route != 'pages/login/index') {
|
||||
wx.clearStorage()
|
||||
wx.reLaunch({
|
||||
url: '/pages/login/index'
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (res.data.code == 200) {
|
||||
callBack(res.data);
|
||||
} else {
|
||||
app.printErrorClient('failrequest', ['api地址:' + url, '传入数据:' + JSON.stringify(serectParams), '响应数据:' + JSON.stringify(res.data)])
|
||||
reject(res.data);
|
||||
if (Config.white401UrlList[url] === url) {//接口白名单
|
||||
return
|
||||
}
|
||||
wx.showToast({
|
||||
title: res.data.msg,
|
||||
icon: "none"
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
fail: function (res) {
|
||||
console.warn("HttpRequst当中wx.request fail 执行了:调用失败")
|
||||
app.printErrorClient('failrequest', ['HttpRequst当中wx.request fail 执行了:调用失败', 'api地址:' + url, '传入数据:' + JSON.stringify(serectParams), '响应数据:' + JSON.stringify(res.data)])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function HttpRequest(loading, url, sessionChoose, params, method, callBack, reject) {
|
||||
let ukey = app.getStorageByKey("ukey");
|
||||
let requestUrl = Config.api.baseUrl;
|
||||
//判断ukey是否存在
|
||||
// 存在就继续执行
|
||||
if (!!ukey) {
|
||||
if (loading == true) {
|
||||
wx.showLoading();
|
||||
}
|
||||
let paramSession = sessionChoose == 1 ? {
|
||||
'content-type': 'application/x-www-form-urlencoded'
|
||||
} : {
|
||||
'content-type': 'application/json'
|
||||
};
|
||||
var params = Object.prototype.toString.call(params) == "[object Object]" ? params : {};
|
||||
params["ukey"] = ukey;
|
||||
params["version"] = Config.version;
|
||||
params["nonce_str"] = randomString();
|
||||
params["app_id"] = Config.app_id;
|
||||
let serectParams = {
|
||||
...params,
|
||||
sign: toEncrypt(params)
|
||||
}
|
||||
|
||||
wx.request({
|
||||
url: Config.api.baseUrl + url,
|
||||
data: serectParams,
|
||||
dataType: "json",
|
||||
header: paramSession,
|
||||
method: method,
|
||||
success: function (res) {
|
||||
// console.log(res.data);
|
||||
if (loading == true) {
|
||||
wx.hideLoading(); //隐藏提示框
|
||||
}
|
||||
//token 存在 还返回408,这个时候就要强制
|
||||
if (res.data.code == 408) {
|
||||
// asyncLogin(true).then((res) => {
|
||||
// console.log("asyncLogin().then-success")
|
||||
// HttpRequest(loading, url, sessionChoose, params, method, callBack, reject)
|
||||
// })
|
||||
//if (getCurrentPages().pop().route != 'pages/login/index'){
|
||||
wx.clearStorage()
|
||||
wx.reLaunch({
|
||||
url: '/pages/login/index'
|
||||
})
|
||||
//}
|
||||
} else{
|
||||
if (res.data.code==200){
|
||||
callBack(res.data);
|
||||
}else{
|
||||
app.printErrorClient('failrequest',['api地址:'+url,'传入数据:'+JSON.stringify(serectParams),'响应数据:'+JSON.stringify(res.data)])
|
||||
reject(res.data);
|
||||
if (Config.white401UrlList[url] === url) {//接口白名单
|
||||
return
|
||||
}
|
||||
wx.showToast({
|
||||
title: res.data.msg,
|
||||
icon: "none"
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
fail: function (res) {
|
||||
console.warn("HttpRequst当中wx.request fail 执行了:调用失败")
|
||||
app.printErrorClient('failrequest',['HttpRequst当中wx.request fail 执行了:调用失败','api地址:'+url,'传入数据:'+JSON.stringify(serectParams),'响应数据:'+JSON.stringify(res.data)])
|
||||
}
|
||||
})
|
||||
} else {
|
||||
//不存在(或者) 重走登录流程
|
||||
//第一个执行的时候 后面的都需要挂起来
|
||||
// asyncLogin().then((res) => {
|
||||
// console.log("asyncLogin().then-没有token")
|
||||
// HttpRequest(loading, url, sessionChoose, params, method, callBack, reject)
|
||||
// })
|
||||
//if (getCurrentPages().pop().route != 'pages/login/index') {
|
||||
wx.clearStorage()
|
||||
wx.reLaunch({
|
||||
url: '/pages/login/index'
|
||||
})
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
function asyncLogin(flag) {
|
||||
|
||||
return new Promise((reslove, reject) => {
|
||||
if (app.globalData.loginRuning) {
|
||||
//已经在执行了
|
||||
app.globalData.loginCollect.push(reslove);
|
||||
} else {
|
||||
app.globalData.loginRuning = true;
|
||||
work(reslove, reject, flag)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function _resloveRun() {
|
||||
app.globalData.loginCollect.forEach((reslove) => {
|
||||
reslove();
|
||||
// console.log("app.globalData.loginCollect.forEach")
|
||||
});
|
||||
// console.log("_resloveRun")
|
||||
app.globalData.loginRuning = false;
|
||||
app.globalData.loginCollect = [];
|
||||
}
|
||||
|
||||
|
||||
function work(reslove, reject, flag) {
|
||||
wx.checkSession({
|
||||
success: function () {
|
||||
|
||||
//同步获取token
|
||||
let ukey = app.getStorageByKey("ukey");
|
||||
console.log("asyncLogin(checkSession-success)-ukey:" + ukey)
|
||||
//为了安全验证 判断ukey是否有本地存储
|
||||
if (!ukey || (!!ukey && flag)) {
|
||||
wxLogin(reslove);
|
||||
} else {
|
||||
//重新走登录流程
|
||||
reslove(ukey);
|
||||
_resloveRun();
|
||||
}
|
||||
},
|
||||
fail: function () {
|
||||
//重新走登录流程
|
||||
wxLogin(reslove);
|
||||
}
|
||||
})
|
||||
}
|
||||
function wxLogin(reslove) {
|
||||
wx.login({
|
||||
success(res) {
|
||||
console.log("执行了wx.login-code:"+res.code)
|
||||
if (res.code) {
|
||||
let params = {
|
||||
code: res.code,
|
||||
app_id: Config.app_id,
|
||||
nonce_str: randomString()
|
||||
}
|
||||
let sendData={
|
||||
...params,
|
||||
sign: toEncrypt(params)
|
||||
}
|
||||
wx.request({
|
||||
url: Config.api.baseUrl + Config.api.appUserUkey,
|
||||
data: sendData,
|
||||
dataType: "json",
|
||||
header: {
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
method: "GET",
|
||||
success: function (res) {
|
||||
console.log("wx.login-ukey:"+res.data.data.ukey)
|
||||
if (res.data.code == 200) {
|
||||
app.globalData.ukey = res.data.data.ukey;
|
||||
app.setStorage("ukey", res.data.data.ukey, function () {
|
||||
reslove();
|
||||
_resloveRun();
|
||||
})
|
||||
}
|
||||
},
|
||||
fail: function (res) {
|
||||
console.warn("wxLogin当中wx.request fail 执行了:调用失败")
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.warn('登录失败!' + res.errMsg)
|
||||
}
|
||||
},
|
||||
fail: function () {
|
||||
console.warn("调用wx.login接口失败!")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
app.asyncLogin = asyncLogin;
|
||||
|
||||
|
||||
|
||||
export { HttpNoUkeyRequest, HttpRequest, asyncLogin, app }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
var log = wx.getRealtimeLogManager ? wx.getRealtimeLogManager() : null
|
||||
|
||||
module.exports = {
|
||||
info() {
|
||||
if (!log) return
|
||||
log.info.apply(log, arguments)
|
||||
},
|
||||
warn() {
|
||||
if (!log) return
|
||||
log.warn.apply(log, arguments)
|
||||
},
|
||||
error() {
|
||||
if (!log) return
|
||||
log.error.apply(log, arguments)
|
||||
},
|
||||
setFilterMsg(msg) { // 从基础库2.7.3开始支持
|
||||
if (!log || !log.setFilterMsg) return
|
||||
if (typeof msg !== 'string') return
|
||||
log.setFilterMsg(msg)
|
||||
},
|
||||
addFilterMsg(msg) { // 从基础库2.8.1开始支持
|
||||
if (!log || !log.addFilterMsg) return
|
||||
if (typeof msg !== 'string') return
|
||||
log.addFilterMsg(msg)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
/**
|
||||
* 使用方法:
|
||||
* 1.脚本顶部引入 const app = getApp();
|
||||
* 2.Utils.$router.push(name,params,type,openMode)
|
||||
* -1)params为传入参数和值,如果params有值,将存在本地存储中
|
||||
* -2)如果type(默认为params)为query时,参数会拼接到url后面
|
||||
* -3)openMode 开发方式 默认navigateTo
|
||||
* 3.Utils.$router.reLaunch(name,params,type)//打开到应用内的某个页面,可跳转到Tabbar页面
|
||||
* 4.Utils.$router.redirect(name,params,type)//打开到应用内的某个页面,不可重定向到Tabbar页面
|
||||
* 5.Utils.$router.switchTab(name)//跳转指定的tab页
|
||||
* 6.Utils.$router.back(deltah,params)//返回上n级页面
|
||||
* 7.Utils.$router.backHome(params)//返回到首页
|
||||
* 8.Utils.$router.webviewRedirect(name, params, openMode)//跳转到webview页面
|
||||
* 9.Utils.$router.openUrlScheme //传入url结构解析后跳转
|
||||
* 10.链式调用success,fail,complete,
|
||||
* 例:Util.$router.push("mine")
|
||||
.success(res => {
|
||||
console.log("success: ", res)
|
||||
})
|
||||
.fail(err => {
|
||||
console.log("fail: ", res)
|
||||
})
|
||||
.complete(_ => {
|
||||
console.log("complete")
|
||||
})
|
||||
*/
|
||||
|
||||
const symbol = {
|
||||
reLaunch: Symbol(),
|
||||
redirect: Symbol(),
|
||||
switchTab: Symbol(),
|
||||
}
|
||||
|
||||
export default class Router {
|
||||
|
||||
/**
|
||||
* constructor 🚀
|
||||
*/
|
||||
constructor() {
|
||||
// 当前页面携带的参数 (缓存在storage中)
|
||||
this.params = null
|
||||
|
||||
// 当前页面携带的参数 (在query中)
|
||||
this.query = null
|
||||
|
||||
this.callbacks = {}
|
||||
|
||||
this.success = function (onSuccess) {
|
||||
this.callbacks.onSuccess = onSuccess
|
||||
return this
|
||||
}
|
||||
this.fail = function (onFail) {
|
||||
this.callbacks.onFail = onFail
|
||||
return this
|
||||
}
|
||||
this.complete = function (onComplete) {
|
||||
this.callbacks.onComplete = onComplete
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
/******** Public ********/
|
||||
|
||||
/**
|
||||
* 保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面
|
||||
* @param name
|
||||
* @param params
|
||||
* @returns {*}
|
||||
*/
|
||||
push(name, params = null, type = 'params', openMode = 'navigateTo') {
|
||||
|
||||
// const page = isFullPath ? { url: name, name: name}:this.getPageFor(name)
|
||||
const page = {
|
||||
url: name,
|
||||
name: name
|
||||
}
|
||||
|
||||
if (!page) {
|
||||
throw Error(`!! Not found page ->:[${name}] !!`)
|
||||
return
|
||||
}
|
||||
|
||||
this.currentPage = page
|
||||
|
||||
if (params) {
|
||||
const key = `router-${page.name}-params`
|
||||
wx.setStorageSync(key, params)
|
||||
this.params = this._getParams(key)
|
||||
} else {
|
||||
this.params = null
|
||||
}
|
||||
|
||||
if (type === 'query') {
|
||||
this.params = {}
|
||||
page.url += "?"
|
||||
for (let key in params) {
|
||||
console.log("key: ", key)
|
||||
page.url += `${key}=${params[key]}&`
|
||||
this.params[key] = params[key]
|
||||
}
|
||||
page.url = page.url.slice(0, -1)
|
||||
console.log("this.params", this.params)
|
||||
}
|
||||
|
||||
const [, , obj] = Array.from(arguments)
|
||||
const that = this
|
||||
let f = wx.navigateTo
|
||||
if (obj && Object.is(obj.fn, symbol.reLaunch)) {
|
||||
f = wx.reLaunch
|
||||
}
|
||||
if (obj && Object.is(obj.fn, symbol.redirect)) {
|
||||
f = wx.redirectTo
|
||||
}
|
||||
if (obj && Object.is(obj.fn, symbol.switchTab)) {
|
||||
f = wx.switchTab
|
||||
}
|
||||
|
||||
if (openMode == 'reLaunch') {
|
||||
f = wx.reLaunch
|
||||
} else if (openMode == 'redirect') {
|
||||
f = wx.redirectTo
|
||||
} else if(openMode == 'switchTab') {
|
||||
f = wx.switchTab
|
||||
}
|
||||
|
||||
f({
|
||||
url: page.url,
|
||||
...that._getFunc()
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭所有页面,打开到应用内的某个页面 可传递参数 可跳转到Tabbar页面
|
||||
* @param name
|
||||
* @param params
|
||||
*/
|
||||
reLaunch(name, params = null, type = 'params') {
|
||||
return this.push(name, params, {
|
||||
fn: symbol.reLaunch
|
||||
}, type)
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭所有页面,打开到应用内的某个页面 可传递参数 不可重定向到Tabbar页面
|
||||
* @param name
|
||||
* @param params
|
||||
*/
|
||||
redirect(name, params = null, type = 'params') {
|
||||
return this.push(name, params, {
|
||||
fn: symbol.redirect
|
||||
}, type)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转指定的tab页
|
||||
* @param name
|
||||
* @returns {*}
|
||||
*/
|
||||
//xxk://switchTab/pages/card/index
|
||||
switchTab(name) {
|
||||
return this.push(name, null, {
|
||||
fn: symbol.switchTab
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭当前页面,返回上一页面或多级页面。 没有参数 代表返回上一页
|
||||
* @param delta
|
||||
* @param params
|
||||
*/
|
||||
back(delta = 1, params = null) {
|
||||
if (params) {
|
||||
const key = `router-${this._currentPage.name}-params`
|
||||
wx.setStorageSync(key, params)
|
||||
this.params = this._getParams(key)
|
||||
} else {
|
||||
this.params = null
|
||||
}
|
||||
wx.navigateBack({
|
||||
delta,
|
||||
...this._getFunc()
|
||||
})
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭所有页面返回到首页
|
||||
* @param params
|
||||
*/
|
||||
backHome(params = null) {
|
||||
// return this.back(Number.MAX_SAFE_INTEGER, params)
|
||||
return this.reLaunch('/pages/index/index')
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到webview页面
|
||||
* @param name
|
||||
* @param params
|
||||
*/
|
||||
|
||||
webviewRedirect(url = null, title = '', openMode = 'navigateTo') {
|
||||
return this.push('/pages/web-view/index', {
|
||||
title: title,
|
||||
url: encodeURIComponent(url)
|
||||
}, 'query', openMode)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到其他小程序
|
||||
* @param url
|
||||
*/
|
||||
//调整小程序数据格式,appId要先加到app.json中
|
||||
//'xxk://navigateToMiniPrograms??appId=wx636830278bc7b5f4@path=/pages/consultant?id=1@envVersion=release@extraData={"fromwhere":"aolai"}'
|
||||
navigateToMiniProgramRedirect(OBJ) {
|
||||
let search = OBJ.split('??')[1]
|
||||
let appId = this._getQueryString('appId',search)
|
||||
let path = this._getQueryString('path',search)
|
||||
let extraData = JSON.parse(this._getQueryString('extraData',search))
|
||||
let envVersion = this._getQueryString('envVersion',search) || 'release'
|
||||
|
||||
wx.navigateToMiniProgram({
|
||||
appId: appId,
|
||||
path: path,
|
||||
extraData: extraData,
|
||||
envVersion: envVersion
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 传入url结构解析后跳转
|
||||
* @param url
|
||||
*/
|
||||
|
||||
openUrlScheme(url = null, title = '', openMode = 'navigateTo') {
|
||||
if (url.indexOf('http') > -1) {
|
||||
this.webviewRedirect(url, title, openMode)
|
||||
}else if(url.indexOf('xhb://navigateToMiniProgram')>-1){
|
||||
this.navigateToMiniProgramRedirect(url)
|
||||
} else if (url.indexOf('xhb://switchTab')>-1) {
|
||||
this.switchTab(url.split('switchTab')[1])
|
||||
// } else if(url.indexOf('ixm://reLaunch')>-1) {
|
||||
// this.reLaunch(url.split('reLaunch')[1])
|
||||
// } else if(url.indexOf('ixm://redirectTo')>-1) {
|
||||
// this.redirect(url.split('redirectTo')[1])
|
||||
// } else if(url.indexOf('ixm://navigateTo')>-1){
|
||||
// this.push(url.split('navigateTo')[1])
|
||||
// } else if(url.indexOf('ixm://navigateBack')>-1){
|
||||
// this.back(url.split('navigateBack/')[1])
|
||||
} else {
|
||||
this.push(url)
|
||||
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******** Private ********/
|
||||
|
||||
|
||||
/**
|
||||
* 获取函数
|
||||
* @returns {{fail: fail, success: success, complete: complete}}
|
||||
* @private
|
||||
*/
|
||||
_getFunc() {
|
||||
let that = this
|
||||
return {
|
||||
success: function (res) {
|
||||
if (that.callbacks.onSuccess) that.callbacks.onSuccess(res)
|
||||
},
|
||||
fail: function (err) {
|
||||
if (that.callbacks.onFail) that.callbacks.onFail(err)
|
||||
},
|
||||
complete: function () {
|
||||
if (that.callbacks.onComplete) that.callbacks.onComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前跳转的页面的携带的参数
|
||||
* @param key
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
_getParams(key) {
|
||||
return wx.getStorageSync(key)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取url的query值
|
||||
* @param name
|
||||
* @private
|
||||
*/
|
||||
|
||||
_getQueryString = (name, url) => {
|
||||
if (url.indexOf(name) > -1) {
|
||||
var reg = new RegExp('(^|@)' + name + '=([^@]*)(@|$)', 'i');
|
||||
var r = url.match(reg)
|
||||
if (r != null) {
|
||||
return unescape(r[2]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* date:2019-10-17
|
||||
* author: lien
|
||||
* desc: import StringEncrypt from '文件路径'; StringEncrypt.toEncrypt(this.data.dd,'xmfish')
|
||||
*/
|
||||
import md5 from '../lib/md5'
|
||||
import Config from '../config'
|
||||
|
||||
/**
|
||||
* utf-8加密
|
||||
*/
|
||||
function encodeUtf8(text) {
|
||||
const code = encodeURIComponent(text);
|
||||
const bytes = [];
|
||||
for (var i = 0; i < code.length; i++) {
|
||||
const c = code.charAt(i);
|
||||
if (c === '%') {
|
||||
const hex = code.charAt(i + 1) + code.charAt(i + 2);
|
||||
const hexVal = parseInt(hex, 16);
|
||||
bytes.push(hexVal);
|
||||
i += 2;
|
||||
} else bytes.push(c.charCodeAt(0));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* utf-8解密
|
||||
*/
|
||||
function decodeUtf8(bytes) {
|
||||
var encoded = "";
|
||||
for (var i = 0; i < bytes.length; i++) {
|
||||
encoded += '%' + bytes[i].toString(16);
|
||||
}
|
||||
return decodeURIComponent(encoded);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成从minNum到maxNum的随机数
|
||||
*/
|
||||
function randomNum(minNum, maxNum) {
|
||||
switch (arguments.length) {
|
||||
case 1:
|
||||
return parseInt(Math.random() * minNum + 1, 10);
|
||||
break;
|
||||
case 2:
|
||||
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机加密串
|
||||
*/
|
||||
function randomString(len) {
|
||||
len = len || 32;
|
||||
let $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
|
||||
let maxPos = $chars.length;
|
||||
let pwd = '';
|
||||
let newLen = randomNum(10, len)
|
||||
|
||||
for (let i = 0; i < newLen; i++) {
|
||||
pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
|
||||
}
|
||||
return pwd;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据
|
||||
*/
|
||||
let getData = (DATA) => {
|
||||
return DATA
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除空值
|
||||
*/
|
||||
let delEmptyValue = (DATA) => {
|
||||
let data = getData(DATA)
|
||||
let newData = {}
|
||||
for (let i in data) {
|
||||
if (data[i] !== '' && Object.prototype.toString.call(data[i]) != "[object Array]" && Object.prototype.toString.call(data[i]) != "[object Object]") {
|
||||
newData[i] = data[i]
|
||||
}
|
||||
}
|
||||
return newData
|
||||
}
|
||||
|
||||
/**
|
||||
* 按ascii码从小到大排序
|
||||
*/
|
||||
let sortByAscii = (DATA) => {
|
||||
let obj = {
|
||||
...delEmptyValue(DATA)
|
||||
}
|
||||
let arr = new Array();
|
||||
let num = 0;
|
||||
for (let i in obj) {
|
||||
arr[num] = i;
|
||||
num++;
|
||||
}
|
||||
let sortArr = arr.sort();
|
||||
//let sortObj = {}; //完成排序值
|
||||
let str = ''; //自定义排序字符串
|
||||
for (let i in sortArr) {
|
||||
str += sortArr[i] + '=' + obj[sortArr[i]] + '&';
|
||||
//sortObj[sortArr[i]] = obj[sortArr[i]];
|
||||
}
|
||||
//去除两侧字符串
|
||||
let char = '&'
|
||||
str = str.replace(new RegExp('^\\' + char + '+|\\' + char + '+$', 'g'), '');
|
||||
|
||||
return str
|
||||
//return sortObj
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接字符串
|
||||
*/
|
||||
let combineUrl = (DATA) => {
|
||||
let data = sortByAscii(DATA)
|
||||
let str = data + '&key=' + Config.key
|
||||
// console.log("发送的字符串:"+str)
|
||||
return str
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密字符串
|
||||
*/
|
||||
let toEncrypt = (DATA) => {
|
||||
// let secretKey = randomString()
|
||||
let data = combineUrl(DATA)
|
||||
return md5.hex_md5(data);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
toEncrypt,
|
||||
randomString
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
// import config from '../config'
|
||||
import api from '../utils/apiQuery'
|
||||
const app = getApp()
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
function getAjaxUserInfo(){
|
||||
return new Promise(function (resolve, reject) {
|
||||
api.getUserInfo().then(res=>{
|
||||
resolve(res)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户是否授权用户信息
|
||||
*/
|
||||
function isAuthUserInfo() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
api.getUserInfo().then(res=>{
|
||||
resolve(Boolean(res && res.nickname && res.headimg))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户是否绑定手机
|
||||
*/
|
||||
function isBindMobile() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
api.getUserInfo().then(res=>{
|
||||
resolve(res && res.mobile)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否开卡
|
||||
*/
|
||||
function isOpenCard() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
api.getUserInfo().then(res=>{
|
||||
resolve(res && res.card_id)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得用户位置,返回一个promise,同时间只会跑一个
|
||||
* {
|
||||
* lat,
|
||||
* lng,
|
||||
* from_storage //true表示是从缓存里获得, false表示从设置里获得
|
||||
* }
|
||||
*/
|
||||
// function getUserLocation() {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// // const lat = wx.getStorageSync('u_lat');
|
||||
// // const lng = wx.getStorageSync('u_lng');
|
||||
// // if (lat && lng) {
|
||||
// // return resolve({
|
||||
// // lat,
|
||||
// // lng,
|
||||
// // from_storage: true,
|
||||
// // })
|
||||
// // } else {
|
||||
// const loading = wx.getStorageSync('loading_gps');
|
||||
// if (loading) {
|
||||
// setTimeout(() => {
|
||||
// return resolve(this.getUserLocation());
|
||||
// }, 30);
|
||||
// return;
|
||||
// }
|
||||
// wx.setStorageSync('loading_gps', 1)
|
||||
// wx.getSetting({
|
||||
// success(res) {
|
||||
// console.log("======获取用户地理位置=====")
|
||||
// console.log(res);
|
||||
// wx.getLocation({
|
||||
// type: 'gcj02',
|
||||
// success: function (res) {
|
||||
// var lat = res.latitude
|
||||
// var lng = res.longitude
|
||||
// wx.setStorageSync('u_lat', lat)
|
||||
// wx.setStorageSync('u_lng', lng)
|
||||
// wx.removeStorageSync('loading_gps')
|
||||
// return resolve({
|
||||
// lat,
|
||||
// lng,
|
||||
// from_storage: false,
|
||||
// })
|
||||
// },
|
||||
// fail: function (res) {
|
||||
// console.log("用户没有授权地理位置")
|
||||
// console.log(res);
|
||||
// wx.removeStorageSync('loading_gps')
|
||||
// wx.showModal({
|
||||
// title: '提示',
|
||||
// content: '请先授权地理位置权限',
|
||||
// showCancel: false,
|
||||
// success(res) {
|
||||
// if (res.confirm) {
|
||||
// console.log('用户点击确定')
|
||||
// wx.openSetting({
|
||||
// success(res) {
|
||||
// console.log(res.authSetting)
|
||||
|
||||
// }
|
||||
// })
|
||||
// } else if (res.cancel) {
|
||||
// console.log('用户点击取消')
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// return reject('用户没有授权地理位置')
|
||||
// }
|
||||
// })
|
||||
// },
|
||||
// })
|
||||
// // }
|
||||
// })
|
||||
// }
|
||||
|
||||
|
||||
const getUserLocation = function () {
|
||||
return new Promise(function (resolve, reject) {
|
||||
wx.getLocation({
|
||||
type: 'wgs84',
|
||||
success(res) {
|
||||
app.setStorage('u_lat', res.latitude)
|
||||
app.setStorage('u_lng', res.longitude)
|
||||
resolve({
|
||||
lat:res.latitude,
|
||||
lng:res.longitude,
|
||||
from_storage: false,
|
||||
});
|
||||
},
|
||||
fail(res) {
|
||||
app.printErrorClient('userLocationFail', ['错误信息:'+ JSON.stringify(res)])
|
||||
_ModelForGetLocationModel(resolve, reject);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function _ModelForGetLocationModel(resolve, reject) {
|
||||
wx.showModal({
|
||||
title: '',
|
||||
content: '检测到你未打开地理位置的权限,是否前往开启',
|
||||
confirmText: '前往开启',
|
||||
showCancel:false,
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
//成功的时候只执行一次(通过手动的时候就没执行了)
|
||||
wx.openSetting({
|
||||
success(res) {
|
||||
wx.authorize({
|
||||
scope: 'scope.userLocation',
|
||||
success() {
|
||||
// resolve("toggle");
|
||||
wx.getLocation({
|
||||
type: 'wgs84',
|
||||
success(res) {
|
||||
app.setStorage('u_lat', res.latitude)
|
||||
app.setStorage('u_lng', res.longitude)
|
||||
resolve({
|
||||
lat:res.latitude,
|
||||
lng:res.longitude,
|
||||
from_storage: false,
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
fail() {
|
||||
app.printErrorClient('userLocationFail',['错误信息:打开打开地理位置的权限,未设置'])
|
||||
_ModelForGetLocationModel(resolve, reject);
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
} else if (res.cancel) {
|
||||
app.printErrorClient('userLocationFail',['错误信息:用户点击取消'])
|
||||
reject()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
getAjaxUserInfo,
|
||||
isAuthUserInfo,
|
||||
isBindMobile,
|
||||
isOpenCard,
|
||||
getUserLocation
|
||||
// getLocation
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
import log from 'log.js'
|
||||
const app = getApp();
|
||||
|
||||
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(':')
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取时间戳
|
||||
* @param {*}
|
||||
*/
|
||||
const getTimestamp = () => {
|
||||
return new Date().getTime()
|
||||
}
|
||||
|
||||
|
||||
const formatNumber = n => {
|
||||
n = n.toString()
|
||||
return n[1] ? n : '0' + n
|
||||
}
|
||||
|
||||
const padding = (s, len) => {
|
||||
len = len - (s + '').length
|
||||
for (var i = 0; i < len; i++) {
|
||||
s = '0' + s
|
||||
}
|
||||
return s
|
||||
}
|
||||
var DEFAULT_PATTERN = 'yyyy-MM-dd'
|
||||
var SIGN_REGEXP = /([yMdhsm])(\1*)/g
|
||||
|
||||
const formatDate = {
|
||||
formatYYMMDD: function (time) {
|
||||
let date = new Date(time)
|
||||
return date.toLocaleDateString().replace(RegExp('/', 'g'), '-') + ' 00:00:00'
|
||||
},
|
||||
format: function (date, pattern) {
|
||||
pattern = pattern || DEFAULT_PATTERN
|
||||
return pattern.replace(SIGN_REGEXP, function ($0) {
|
||||
switch ($0.charAt(0)) {
|
||||
case 'y':
|
||||
return padding(date.getFullYear(), $0.length)
|
||||
case 'M':
|
||||
return padding(date.getMonth() + 1, $0.length)
|
||||
case 'd':
|
||||
return padding(date.getDate(), $0.length)
|
||||
case 'w':
|
||||
return date.getDay() + 1
|
||||
case 'h':
|
||||
return padding(date.getHours(), $0.length)
|
||||
case 'm':
|
||||
return padding(date.getMinutes(), $0.length)
|
||||
case 's':
|
||||
return padding(date.getSeconds(), $0.length)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const getNowTimeFormate = (TYPE) => {
|
||||
var date = ''
|
||||
switch (TYPE) {
|
||||
case 'DAY':
|
||||
date = formatDate.format(new Date())
|
||||
// return date.slice(0, 4)+'-'+date.slice(4, 6)+'-'+date.slice(6, 8)
|
||||
return date
|
||||
break;
|
||||
case 'MONTH':
|
||||
date = formatDate.format(new Date(), 'yyyyMM')
|
||||
return date.slice(0, 4) + '-' + date.slice(4, 6)
|
||||
break;
|
||||
case 'TIME':
|
||||
date = formatDate.format(new Date(), 'yyyyMMddhhmmss')
|
||||
return date.slice(0, 4) + '-' + date.slice(4, 6) + '-' + date.slice(6, 8) + ' ' + date.slice(8, 10) + ':' + date.slice(10, 12) + ':' + date.slice(12, 14)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开地图
|
||||
*/
|
||||
const openLocation = function (params) {
|
||||
wx.openLocation({
|
||||
latitude: params.latitude,
|
||||
longitude: params.longitude,
|
||||
name: params.name || '',
|
||||
address: params.address || '',
|
||||
scale: params.scale || 18
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 提示框
|
||||
*/
|
||||
const $toast = function (message, time = 1500) {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.showToast({
|
||||
title: message,
|
||||
icon: 'none',
|
||||
duration: time,
|
||||
success: function (res) {
|
||||
resolve(res)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 对话框
|
||||
*/
|
||||
const $modal = function (title, content, confirmText = '确定', cancelText = '取消') {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.showModal({
|
||||
title: title,
|
||||
content: content,
|
||||
confirmText: confirmText,
|
||||
cancelText: cancelText,
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
// 确认按钮点击
|
||||
resolve(true)
|
||||
} else if (res.cancel) {
|
||||
// 取消按钮点击
|
||||
resolve(false)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取状态栏高度
|
||||
*/
|
||||
const getStatusBarHeight = () => {
|
||||
let barHeight = ''
|
||||
wx.getSystemInfo({
|
||||
success: function (res) {
|
||||
barHeight = res.statusBarHeight
|
||||
}
|
||||
})
|
||||
return barHeight
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前路径
|
||||
*/
|
||||
|
||||
function getCurrentPath() {
|
||||
var pages = getCurrentPages() //获取加载的页面
|
||||
var currentPage = pages[pages.length - 1] //获取当前页面的对象
|
||||
return {
|
||||
pages: pages, //获取所有页面
|
||||
url: currentPage.route, //当前页面url
|
||||
options: currentPage.options //如果要获取url中所带的参数可以查看options
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取路由跳转过来的数据
|
||||
*/
|
||||
function getRouterData (URL) {
|
||||
return wx.getStorageSync('router-/' + URL + '-params')
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 防止多次重复点击 (函数节流)
|
||||
*/
|
||||
function throttle(fn, gapTime) {
|
||||
if (gapTime == null || gapTime == undefined) {
|
||||
gapTime = 1000
|
||||
}
|
||||
|
||||
let _lastTime = null
|
||||
|
||||
// 返回新的函数
|
||||
return (function (e) {
|
||||
console.log(this)
|
||||
let _nowTime = +new Date()
|
||||
if (_nowTime - _lastTime > gapTime || !_lastTime) {
|
||||
// fn.apply(this, arguments) //将this和参数传给原函数
|
||||
fn(this, e) //上方法不可行的解决办法 改变this和e
|
||||
_lastTime = _nowTime
|
||||
}
|
||||
})()
|
||||
}
|
||||
|
||||
/*函数防抖*/
|
||||
function debounce(fn, interval) {
|
||||
var timer;
|
||||
var gapTime = interval || 200;//间隔时间,如果interval不传,则默认200ms
|
||||
return function () {
|
||||
clearTimeout(timer);
|
||||
var context = this;
|
||||
var args = arguments;//保存此处的arguments,因为setTimeout是全局的,arguments不是防抖函数需要的。
|
||||
timer = setTimeout(function () {
|
||||
fn.call(context, args);
|
||||
}, gapTime);
|
||||
};
|
||||
}
|
||||
|
||||
//去掉前后空格
|
||||
function trim(s){
|
||||
return s.toString().replace(/(^\s*)|(\s*$)/g, "");
|
||||
}
|
||||
|
||||
//过滤所以空格
|
||||
function filterSpace(s) {
|
||||
return s.toString().replace(/\ +/g, "");
|
||||
}
|
||||
|
||||
|
||||
function getNumber(str) {
|
||||
return str.toString().match(/\d+(\.\d{0,2})?/)[0]
|
||||
}
|
||||
|
||||
function compareVersion(v1, v2) {
|
||||
v1 = v1.split('.')
|
||||
v2 = v2.split('.')
|
||||
const len = Math.max(v1.length, v2.length)
|
||||
|
||||
while (v1.length < len) {
|
||||
v1.push('0')
|
||||
}
|
||||
while (v2.length < len) {
|
||||
v2.push('0')
|
||||
}
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
const num1 = parseInt(v1[i])
|
||||
const num2 = parseInt(v2[i])
|
||||
|
||||
if (num1 > num2) {
|
||||
return 1
|
||||
} else if (num1 < num2) {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 内存报警
|
||||
* 报警后,使用reLaunch,并记录当前页面及页面栈
|
||||
*/
|
||||
function memoryWarning(){
|
||||
wx.onMemoryWarning(function () {
|
||||
let getPath = getCurrentPath()
|
||||
wx.reportAnalytics('outofmemory', getPath)
|
||||
wx.reportMonitor('0', 500)
|
||||
wx.reLaunch(getPath.url)
|
||||
app.printErrorClient('filteroutofmemory')
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消内存报警
|
||||
*/
|
||||
function offMemoryWarning(){
|
||||
if (wx.canIUse('offMemoryWarning')) {
|
||||
wx.offMemoryWarning()
|
||||
app.printErrorClient('offmemory')
|
||||
} else {
|
||||
app.printErrorClient('offmemorylowversion')
|
||||
log.warn('当前微信版本'+wx.getSystemInfoSync().SDKVersion+'过低,无法使用该功能,请升级到最新微信版本后重试。')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
log,
|
||||
formatTime,
|
||||
openLocation,
|
||||
$toast,
|
||||
$modal,
|
||||
getStatusBarHeight,
|
||||
getCurrentPath,
|
||||
getRouterData,
|
||||
throttle,
|
||||
debounce,
|
||||
getNowTimeFormate,
|
||||
getTimestamp,
|
||||
trim,
|
||||
filterSpace,
|
||||
getNumber,
|
||||
memoryWarning,
|
||||
offMemoryWarning,
|
||||
// printErrorClient
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import _ from '../../commons/js/commons'
|
||||
const app = getApp()
|
||||
Component({
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
properties: {
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的初始数据
|
||||
*/
|
||||
data: {
|
||||
code:'',
|
||||
isRunning:false,
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
attached: function () {
|
||||
wx.login({
|
||||
success: res => {
|
||||
this.setData({
|
||||
code: res.code,
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的方法列表
|
||||
*/
|
||||
methods: {
|
||||
//授权用户信息
|
||||
getUserProfile(){
|
||||
let that = this
|
||||
if(!!that.data.isRunning) return;
|
||||
that.setData({
|
||||
isRunning:true
|
||||
});
|
||||
wx.getUserProfile({
|
||||
desc:'获取你的昵称、头像、地区及性别',//不写不弹提示框
|
||||
success:function(res){
|
||||
|
||||
let params = {};
|
||||
params['code'] = that.data.code;
|
||||
params['userInfo'] = res.userInfo;
|
||||
that.setData({
|
||||
isShow: false,
|
||||
})
|
||||
_.apiQuery.putAppUser(params).then(res => {
|
||||
that.setData({
|
||||
isRunning:false
|
||||
});
|
||||
wx.showToast({
|
||||
title: '授权成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
});
|
||||
},
|
||||
fail:function(err){
|
||||
that.setData({
|
||||
isRunning:false
|
||||
});
|
||||
console.log('拒绝授权')
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"lcb-msg": "/components/msg/index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<!--
|
||||
用法
|
||||
<xxk-auth isShow="true" bind:onSuccess="authEvent"></xxk-auth>
|
||||
-->
|
||||
|
||||
|
||||
<lcb-msg isShow="{{isShow}}" isHasClose="{{true}}">
|
||||
<view slot="content" class="inner40 text-center">
|
||||
<view class='pt20 text-center'><i class="iconfont font-80 color-00c800 icon-weixin"></i></view>
|
||||
<view class='pt20 pb30 text-center font-28 color-666'>
|
||||
<view>授权您的公开信息(昵称和头像)</view>
|
||||
<view>便于查看预定信息哦~</view>
|
||||
</view>
|
||||
<button class='mt20 btn-36afa2 text-center font-32 color-fff ulib-r10' hover-class="btn-36afa2-hover" bindtap="getUserProfile">授权登录</button>
|
||||
</view>
|
||||
</lcb-msg>
|
||||
@@ -0,0 +1 @@
|
||||
@import "../../commons/css/common.wxss";
|
||||
@@ -0,0 +1,86 @@
|
||||
import _ from '../../commons/js/commons'
|
||||
const app = getApp()
|
||||
Component({
|
||||
properties: {
|
||||
isShow: {
|
||||
type:Boolean,
|
||||
value:false
|
||||
},
|
||||
},
|
||||
data: {
|
||||
mobileNumber: '',
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
attached: function () {
|
||||
let userInfo = app.getStorageByKey("userInfo");
|
||||
if (!!userInfo) {
|
||||
this.setData({
|
||||
userInfo: userInfo,
|
||||
mobileNumber: !!userInfo.tel ? userInfo.tel : userInfo.mobile,
|
||||
})
|
||||
} else {
|
||||
this.getUserInfo()
|
||||
}
|
||||
},
|
||||
detached: function () {
|
||||
// 在组件实例被从页面节点树移除时执行
|
||||
},
|
||||
},
|
||||
ready: function () {},
|
||||
methods: {
|
||||
onClose() {
|
||||
this.setData({
|
||||
isShow: false
|
||||
})
|
||||
},
|
||||
|
||||
// 输入
|
||||
inputTx(e) {
|
||||
this.setData({
|
||||
[e.currentTarget.dataset.key]: e.detail.value
|
||||
})
|
||||
},
|
||||
|
||||
//用户信息
|
||||
getUserInfo() {
|
||||
let params = {};
|
||||
params['biz_id'] = 0;
|
||||
_.apiQuery.getUserInfo(params, false).then(res => {
|
||||
this.setData({
|
||||
userInfo: res,
|
||||
mobileNumber: !!res.tel ? res.tel : res.mobile,
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
//保存手机号
|
||||
putAppUserTel() {
|
||||
if (!/^1[3456789]\d{9}$/.test(this.data.mobileNumber)) {
|
||||
wx.showToast({
|
||||
title: '请输入正确手机号',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
let params = {};
|
||||
params['tel'] = this.data.mobileNumber;
|
||||
_.apiQuery.putAppUserTel(params).then(res => {
|
||||
console.log(res)
|
||||
wx.showToast({
|
||||
title: '修改成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
|
||||
this.getUserInfo()
|
||||
|
||||
this.setData({
|
||||
isShow: false
|
||||
})
|
||||
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"lcb-msg": "/components/msg/index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<lcb-msg isShow="{{isShow}}">
|
||||
<view slot="content" class="inner40">
|
||||
<input class="bg-f7 wp100 pl30 pr30 font-42 ulib-r10" placeholder-class='color-ccc' style="height:90rpx;" maxlength='-1' type='number' placeholder='请输入您的手机号' bindinput='inputTx' data-key='mobileNumber' value="{{mobileNumber}}"></input>
|
||||
<view class="mt30 font-26 color-666">请务必将号码修改成当前使用的手机号,否则将无法接通。</view>
|
||||
<view class="mt40 fn-flex text-center font-32">
|
||||
<view class="fn-flex-item pr20">
|
||||
<view class="bds-1-eb pt20 pb20 ulib-r10" bindtap="onClose">取消</view>
|
||||
</view>
|
||||
<view class="fn-flex-item pl20">
|
||||
<view class="btn-36afa2 pt20 pb20 color-fff ulib-r10" bindtap="putAppUserTel">保存</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</lcb-msg>
|
||||
@@ -0,0 +1 @@
|
||||
@import "../../commons/css/common.wxss";
|
||||
@@ -0,0 +1,23 @@
|
||||
// pages/components/footer/footer.js
|
||||
Component({
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
properties: {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的初始数据
|
||||
*/
|
||||
data: {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的方法列表
|
||||
*/
|
||||
methods: {
|
||||
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<view class="footer text-center">
|
||||
<view>
|
||||
<text class="support-tx">Powered by</text>
|
||||
<image class='inline-block img-30-21' mode='aspectFit' src='https://qs.haodian.cn/wechat_app/common/hdy-logo-gray.png'></image>
|
||||
<text class="support-tx">好店云</text>
|
||||
</view>
|
||||
<!-- <view class="foot-del">189 6512 2277</view> -->
|
||||
</view>
|
||||
@@ -0,0 +1,5 @@
|
||||
.footer {padding:30rpx 0;text-align:center; grid-row-start:2;grid-row-end:3;}
|
||||
.img-30-21{width:30rpx;height:21rpx;vertical-align:middle}
|
||||
.support-tx{margin:0 8rpx;font-size:20rpx;color:#bbb;vertical-align:middle}
|
||||
.inline-block{display:inline-block}
|
||||
.foot-del{font-size:18rpx;color:#bbb;}
|
||||
@@ -0,0 +1,21 @@
|
||||
import _ from '../../commons/js/commons'
|
||||
const app = getApp()
|
||||
Component({
|
||||
properties: {
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
},
|
||||
data: {
|
||||
imgUrl: _.config.imgUrl,//静态图片路径
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
|
||||
},
|
||||
ready: function () {},
|
||||
methods: {
|
||||
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"xxk-msg": "/components/msg/index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<xxk-msg isShow="{{isShow}}" isBottomOpt="true">
|
||||
<view slot="content" class="inner30">
|
||||
<view class="pt20 font-30 line-height-17 color-666">已为您分配专属客服,并将她的联系方式通过服务通知放送给你,请在消息列表查看。</view>
|
||||
<image lazy-load="{{true}}" class="mt20 wp100" mode="widthFix" src="{{imgUrl}}common/notice.jpg" />
|
||||
</view>
|
||||
</xxk-msg>
|
||||
@@ -0,0 +1 @@
|
||||
@import "../../commons/css/common.wxss";
|
||||
@@ -0,0 +1,37 @@
|
||||
Component({
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
properties: {
|
||||
isNoData: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
isLoading: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
isEnd: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
noDataMsg: {
|
||||
type:String,
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的初始数据
|
||||
*/
|
||||
data: {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的方法列表
|
||||
*/
|
||||
methods: {
|
||||
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<view class="pt20 pb20 text-center color-ccc" hidden="{{!isLoading}}">
|
||||
<i class="iconfont icon-jiazai font-36 text-middle"></i>
|
||||
<view class="mt10 font-26 text-middle">请稍等...</view>
|
||||
</view>
|
||||
|
||||
<view class="pt20 pb20 text-center font-26 color-ccc" hidden="{{!isEnd}}">
|
||||
<text>我们是有底线的</text>
|
||||
</view>
|
||||
|
||||
<view class="text-center pt100 pb100" hidden="{{!isNoData}}">
|
||||
<view class="inline-block noData"></view>
|
||||
<view class="pt30 font-28 color-999">{{noDataMsg||'空空如也,这里什么也没有'}}</view>
|
||||
</view>
|
||||
@@ -0,0 +1,9 @@
|
||||
@import "../../commons/css/common.wxss";
|
||||
|
||||
.noData {
|
||||
width: 220rpx;
|
||||
height: 142rpx;
|
||||
background: url(https://qs.haodian.cn/wechat_app/haodianyun/none.png?v=200413) no-repeat;
|
||||
background-size:100% auto;
|
||||
background-position: top center;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import commonconstants from '../../commons/js/config'
|
||||
Component({
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
properties: {
|
||||
isShow: { //是否显示弹框
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
isHasClose: { //是否显示关闭按钮 取值:'','up','down'
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
isExtraOpt: { //是否增加底部操作
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
isBottomOpt: { //是否显示底部操作
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
isTransparent: { //是否背景透明
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
iconType: { //图标
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
title: { //标题
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
content: { //内容
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
closeWord: { //关闭按钮文字
|
||||
type: String,
|
||||
value: '我知道了'
|
||||
}
|
||||
},
|
||||
|
||||
options: {
|
||||
multipleSlots: true // 在组件定义时的选项中启用多slot支持
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的初始数据
|
||||
*/
|
||||
data: {
|
||||
successIcon:commonconstants.imgUrl+'/msg/icon-success.png',
|
||||
failIcon: commonconstants.imgUrl+'/msg/icon-fail.png'
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的方法列表
|
||||
*/
|
||||
methods: {
|
||||
close(){
|
||||
this.setData({
|
||||
isShow: false
|
||||
})
|
||||
this.triggerEvent('closeevent', {
|
||||
isClose: true
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<!-- "usingComponents": {
|
||||
"xhb-msg": "/components/msg/index"
|
||||
},
|
||||
<xhb-msg closeevent="closeevent"></xhb-msg>
|
||||
|
||||
关闭方法: closeevent
|
||||
|
||||
插槽:
|
||||
<view slot="content">这里是插入到组件slot中的内容</view>
|
||||
<view slot="opt">这里是插入到组件slot中的内容</view> -->
|
||||
<view class="XXK-msg" style="{{isShow?'display:block':'display:none'}}">
|
||||
<view class="msgBg" style="background-color: rgba(0, 0, 0, .6);"></view>
|
||||
<view class="msgMain {{isShow?'active':''}}" style="{{isTransparent?'background-color: transparent;':''}}">
|
||||
<block wx:if="{{isHasClose !=''}}">
|
||||
<view wx:if="{{isHasClose=='up'}}" class="close up">
|
||||
<text class="iconfont icon-guanbi1 color-fff" bindtap="close"></text>
|
||||
</view>
|
||||
<view wx:else class="close down" bindtap="close">
|
||||
</view>
|
||||
</block>
|
||||
<view class="hd">
|
||||
<block wx:if="{{iconType!=''}}">
|
||||
<view class="msgMain-icon">
|
||||
<image src="{{successIcon}}" wx:if="{{iconType=='success'}}" />
|
||||
<image src="{{failIcon}}" wx:if="{{iconType=='fail'}}" />
|
||||
</view>
|
||||
</block>
|
||||
<text class="msgMain-title" wx:if="{{title}}">{{title}}</text>
|
||||
<view class="msgMain-content" wx:if="{{content}}">
|
||||
<view>{{content}}</view>
|
||||
</view>
|
||||
<slot name="content"></slot>
|
||||
</view>
|
||||
<view class="bd" wx:if="{{isBottomOpt}}">
|
||||
<view class="msgMain-opt">
|
||||
<view class="msgMain-opt-item" wx:if="{{isExtraOpt}}">
|
||||
<slot name="opt"></slot>
|
||||
</view>
|
||||
<view class="msgMain-opt-item">
|
||||
<view class="color-fff msgMain-opt-close" bindtap="close">{{closeWord}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,144 @@
|
||||
@import "../../commons/css/common.wxss";
|
||||
.XXK-msg{
|
||||
|
||||
}
|
||||
.XXK-msg .msgBg{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 9998;
|
||||
}
|
||||
.XXK-msg .msgMain{
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
min-width: 560rpx;
|
||||
/* min-height: 456rpx; */
|
||||
z-index: 9999;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
.XXK-msg .msgMain.active{
|
||||
animation: card .5s linear 1;
|
||||
}
|
||||
.XXK-msg .msgMain .close{
|
||||
position: absolute;
|
||||
}
|
||||
.XXK-msg .msgMain .close.up{
|
||||
right: 40rpx;
|
||||
top: -80rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.XXK-msg .msgMain .close.up::before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 4rpx;
|
||||
height: 34rpx;
|
||||
background-color: #fff;
|
||||
left: 50%;
|
||||
top: 53rpx;
|
||||
}
|
||||
.XXK-msg .msgMain .close.up text{
|
||||
width: 53rpx;
|
||||
height: 53rpx;
|
||||
line-height: 53rpx;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
border-radius: 100%;
|
||||
border: 4rpx solid #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* .XXK-msg .msgMain .close.down{
|
||||
left: 50%;
|
||||
bottom: -140rpx;
|
||||
transform: translateX(-50%);
|
||||
font-size: 53rpx;
|
||||
} */
|
||||
.XXK-msg .msgMain .close.down{
|
||||
right: 20rpx;
|
||||
top: 20rpx;
|
||||
/* font-size: 30rpx; */
|
||||
width: 35rpx;
|
||||
height: 35rpx;
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjBAMAAADs965qAAAAG1BMVEUAAAAjGBUjGBUjGBUjGBUjGBUjGBUjGBUjGBUq0FsOAAAACXRSTlMAZlQITRE0SzF33gruAAAAh0lEQVQoz33S0Q1AMBDG8Uss4GzQiHfpBBoLsAEbGMHoHtr6N/lEX1x9v1Dn7FytXV06zIe5vRW9t+Rji4IvFluWd12AlQ2MGkYJyxUZBSGopCBYRTAQrCLYVBHMXwQriLW7b/av9Fn6Rj2Xnl6/UTsB4qpd1d6TwYhg+rdBMJ2c62O+dArvBxZYHZp91AHFAAAAAElFTkSuQmCC");
|
||||
}
|
||||
.XXK-msg .msgMain-title{
|
||||
display: block;
|
||||
padding: 25rpx 0 5rpx 0;
|
||||
text-align: center;
|
||||
font-weight:bold;
|
||||
font-size: 36rpx;
|
||||
color: #000;
|
||||
}
|
||||
.XXK-msg .msgMain-content{
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
padding: 0 39rpx 55rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.XXK-msg .msgMain .hd{
|
||||
border-top-left-radius:20rpx;border-top-right-radius:20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.XXK-msg .msgMain .bd{
|
||||
/* padding-bottom: 30rpx; */
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
border-bottom-left-radius:20rpx;border-bottom-right-radius:20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.XXK-msg .msgMain-opt{
|
||||
display: flex;
|
||||
}
|
||||
.msgMain-opt-item{
|
||||
position: relative;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
.msgMain-opt-item text{
|
||||
font-size: 32rpx;
|
||||
}
|
||||
.msgMain-opt-item+.msgMain-opt-item::before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 2rpx;
|
||||
height: 100%;
|
||||
background-color: #d5d6d8;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
.msgMain-opt-close{
|
||||
border-radius: 750rpx;
|
||||
margin-left: 100rpx;
|
||||
margin-right: 100rpx;
|
||||
font-size: 32rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
background-color:#36afa2;
|
||||
}
|
||||
|
||||
.msgMain-icon{
|
||||
margin-top: 80rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.msgMain-icon image{
|
||||
width: 75rpx;
|
||||
height: 75rpx;
|
||||
}
|
||||
@keyframes card{
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate(-50%,-50%) scale3d(.3, .3, .3);
|
||||
}
|
||||
50% {
|
||||
transform: translate(-50%,-50%) scale3d(1,1,1);
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import Utils from '../../commons/js/utils/util'
|
||||
Component({
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
properties: {
|
||||
titleText: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
txtColor: {
|
||||
type: String,
|
||||
value: 'transparent'
|
||||
},
|
||||
bgColor: {
|
||||
type: String,
|
||||
value: '#fe2643'
|
||||
},
|
||||
isShowBg: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
city:{
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
homeShowBar:{
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
homeShowTitle:{
|
||||
type: Boolean,
|
||||
value: false
|
||||
}
|
||||
},
|
||||
attached: function () {
|
||||
this.setNavSize()
|
||||
},
|
||||
data: {
|
||||
isShowRetBtn: false,
|
||||
isShowHomeBtn: false,
|
||||
homeInfo:{
|
||||
placeholder: '搜索城市好店、好评...',
|
||||
url: '/pages/search/index'
|
||||
}
|
||||
},
|
||||
pageLifetimes: {
|
||||
show: function () {
|
||||
let pages = getCurrentPages();
|
||||
if (pages.length == 1) {
|
||||
this.setData({
|
||||
isShowRetBtn: true
|
||||
})
|
||||
}
|
||||
if (Utils.getCurrentPath().url == 'pages/index/index') {
|
||||
this.setData({
|
||||
isShowHomeBtn: true
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 通过获取系统信息计算导航栏高度
|
||||
setNavSize: function () {
|
||||
var that = this,
|
||||
sysinfo = wx.getSystemInfoSync(),
|
||||
statusHeight = sysinfo.statusBarHeight,
|
||||
isiOS = sysinfo.system.indexOf('iOS') > -1,
|
||||
navHeight;
|
||||
if (!isiOS) {
|
||||
navHeight = 48;
|
||||
} else {
|
||||
navHeight = 44;
|
||||
}
|
||||
that.setData({
|
||||
status: statusHeight,
|
||||
navHeight: navHeight
|
||||
})
|
||||
},
|
||||
// 返回事件
|
||||
back: function () {
|
||||
wx.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
},
|
||||
home: function () {
|
||||
wx.switchTab({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"xhb-searchBar": "/components/searchBar/index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<view>
|
||||
<view class="fixed top-0 left-0 right-0 z-index-1" style="height: {{status + navHeight}}px;background-color:{{bgColor}}" wx:if="{{isShowBg}}"></view>
|
||||
<view class="fixed top-0 left-0 right-0 z-index-9999" style="height: {{status + navHeight}}px;">
|
||||
<view style='height: {{status}}px;'></view>
|
||||
<view class="relative" style='height:{{navHeight}}px;line-height:{{navHeight}}px;' wx:if="{{type=='home'}}">
|
||||
<view class="citySelect font-28 color-fff ml30" wx:if="{{city}}">{{city}}</view>
|
||||
<view class="searchBar absolute box-middle" wx:if="{{homeShowBar}}">
|
||||
<xhb-searchBar searchType="home" placeholder="{{homeInfo.placeholder}}" url="{{homeInfo.url}}"></xhb-searchBar>
|
||||
</view>
|
||||
<view class='navbarTitle absolute box-center-middle wp40 text-center text-nowrap text-bold' style="color:{{txtColor}};" wx:if="{{!homeShowBar}}">{{titleText}}</view>
|
||||
</view>
|
||||
<view class='relative' style='height:{{navHeight}}px;' wx:else>
|
||||
<view class="absolute left-0 box-middle" style="width:80px;height:32px;margin-left:7px;box-sizing:border-box;" wx:if="{{!isShowRetBtn}}">
|
||||
<view class="absolute left-0 box-middle pl15 pr15" bindtap='back'>
|
||||
<i class="xhb-icon mr10 icon-fanhui" style="font-size:22px;color:{{txtColor}};"></i>
|
||||
</view>
|
||||
<!-- <view class="absolute top-0 bottom-0 mt15 mb15 box-center bls-ddd" style="width:10rpx;"></view> -->
|
||||
<!-- <view class="absolute right-0 box-middle pl20 pr20" bindtap='home' wx:if="{{!isShowHomeBtn}}">
|
||||
<i class="xhb-icon icon-shouye1" style="font-size:22px;color:{{txtColor}}"></i>
|
||||
</view> -->
|
||||
</view>
|
||||
<view class="absolute left-0 box-middle" style="width:40px;height:32px;margin-left:7px;box-sizing:border-box;" wx:else>
|
||||
<view class="absolute box-center-middle" bindtap='home' wx:if="{{!isShowHomeBtn}}">
|
||||
<i class="xhb-icon icon-shouye1" style="font-size:22px;color:{{txtColor}}"></i>
|
||||
</view>
|
||||
</view>
|
||||
<view class='navbarTitle absolute box-center-middle wp40 text-center text-nowrap text-bold' style="color:{{txtColor}};">{{titleText}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,24 @@
|
||||
@import "../../commons/css/common.wxss";
|
||||
|
||||
.citySelect {
|
||||
padding-left: 12rpx;
|
||||
}
|
||||
|
||||
.citySelect::after {
|
||||
content: '';
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: 12rpx;
|
||||
display: inline-block;
|
||||
border-width: 7rpx;
|
||||
border-style: solid;
|
||||
border-color: #fff transparent transparent transparent;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.searchBar{
|
||||
left: 150rpx;
|
||||
width: 384rpx;
|
||||
}
|
||||
.navbarTitle{
|
||||
font-size: 32rpx;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// components/searchBar/index.js
|
||||
import _ from '../../commons/js/commons';
|
||||
Component({
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
properties: {
|
||||
searchType: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
value: '/pages/search/index'
|
||||
}
|
||||
},
|
||||
attached: function () {
|
||||
},
|
||||
data: {
|
||||
},
|
||||
pageLifetimes: {
|
||||
show: function () {
|
||||
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
goPage(e){
|
||||
_.$router.push(e.currentTarget.dataset.url)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<!-- components/searchBar/index.wxml -->
|
||||
<view class="homeSearch" wx:if="{{searchType=='home'}}" bindtap="goPage" data-url="{{url}}">
|
||||
<view>
|
||||
<text class="icon"></text>
|
||||
<text class="placeholder">{{placeholder}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view wx:else class="professionSearch" bindtap="goPage" data-url="{{url}}">
|
||||
<view>
|
||||
<text class="icon"></text>
|
||||
<text class="placeholder">{{placeholder}}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,33 @@
|
||||
/* components/searchBar/index.wxss */
|
||||
.homeSearch{
|
||||
width: 100%;
|
||||
border-radius: 100rpx;
|
||||
height: 55rpx;
|
||||
line-height: 55rpx;
|
||||
background-color: rgba(255,255,255,.6);
|
||||
text-align: center;
|
||||
}
|
||||
.homeSearch .icon{
|
||||
display: inline-block;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.homeSearch .placeholder{
|
||||
font-size: 26rpx;
|
||||
color: rgba(0,0,0,.6);
|
||||
}
|
||||
.professionSearch{
|
||||
width: 100%;
|
||||
border-radius: 100rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
background-color: rgba(255,255,255,1);
|
||||
text-align: center;
|
||||
}
|
||||
.homeSearch .icon{
|
||||
display: inline-block;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.professionSearch .placeholder{
|
||||
font-size: 26rpx;
|
||||
color: #a3a3a3;
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
import WxCanvas from './wx-canvas';
|
||||
import * as echarts from './echarts';
|
||||
|
||||
let ctx;
|
||||
|
||||
function compareVersion(v1, v2) {
|
||||
v1 = v1.split('.')
|
||||
v2 = v2.split('.')
|
||||
const len = Math.max(v1.length, v2.length)
|
||||
|
||||
while (v1.length < len) {
|
||||
v1.push('0')
|
||||
}
|
||||
while (v2.length < len) {
|
||||
v2.push('0')
|
||||
}
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
const num1 = parseInt(v1[i])
|
||||
const num2 = parseInt(v2[i])
|
||||
|
||||
if (num1 > num2) {
|
||||
return 1
|
||||
} else if (num1 < num2) {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
Component({
|
||||
properties: {
|
||||
canvasId: {
|
||||
type: String,
|
||||
value: 'ec-canvas'
|
||||
},
|
||||
|
||||
ec: {
|
||||
type: Object
|
||||
},
|
||||
|
||||
forceUseOldCanvas: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
}
|
||||
},
|
||||
|
||||
data: {
|
||||
isUseNewCanvas: false
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
// Disable prograssive because drawImage doesn't support DOM as parameter
|
||||
// See https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.drawImage.html
|
||||
echarts.registerPreprocessor(option => {
|
||||
if (option && option.series) {
|
||||
if (option.series.length > 0) {
|
||||
option.series.forEach(series => {
|
||||
series.progressive = 0;
|
||||
});
|
||||
}
|
||||
else if (typeof option.series === 'object') {
|
||||
option.series.progressive = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.data.ec) {
|
||||
console.warn('组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" '
|
||||
+ 'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.data.ec.lazyLoad) {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init: function (callback) {
|
||||
const version = wx.getSystemInfoSync().SDKVersion
|
||||
|
||||
const canUseNewCanvas = compareVersion(version, '2.9.0') >= 0;
|
||||
const forceUseOldCanvas = this.data.forceUseOldCanvas;
|
||||
const isUseNewCanvas = canUseNewCanvas && !forceUseOldCanvas;
|
||||
this.setData({ isUseNewCanvas });
|
||||
|
||||
if (forceUseOldCanvas && canUseNewCanvas) {
|
||||
console.warn('开发者强制使用旧canvas,建议关闭');
|
||||
}
|
||||
|
||||
if (isUseNewCanvas) {
|
||||
// console.log('微信基础库版本大于2.9.0,开始使用<canvas type="2d"/>');
|
||||
// 2.9.0 可以使用 <canvas type="2d"></canvas>
|
||||
this.initByNewWay(callback);
|
||||
} else {
|
||||
const isValid = compareVersion(version, '1.9.91') >= 0
|
||||
if (!isValid) {
|
||||
console.error('微信基础库版本过低,需大于等于 1.9.91。'
|
||||
+ '参见:https://github.com/ecomfe/echarts-for-weixin'
|
||||
+ '#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82');
|
||||
return;
|
||||
} else {
|
||||
console.warn('建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能');
|
||||
this.initByOldWay(callback);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
initByOldWay(callback) {
|
||||
// 1.9.91 <= version < 2.9.0:原来的方式初始化
|
||||
ctx = wx.createCanvasContext(this.data.canvasId, this);
|
||||
const canvas = new WxCanvas(ctx, this.data.canvasId, false);
|
||||
|
||||
echarts.setCanvasCreator(() => {
|
||||
return canvas;
|
||||
});
|
||||
// const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
|
||||
const canvasDpr = 1
|
||||
var query = wx.createSelectorQuery().in(this);
|
||||
query.select('.ec-canvas').boundingClientRect(res => {
|
||||
if (typeof callback === 'function') {
|
||||
this.chart = callback(canvas, res.width, res.height, canvasDpr);
|
||||
}
|
||||
else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
|
||||
this.chart = this.data.ec.onInit(canvas, res.width, res.height, canvasDpr);
|
||||
}
|
||||
else {
|
||||
this.triggerEvent('init', {
|
||||
canvas: canvas,
|
||||
width: res.width,
|
||||
height: res.height,
|
||||
canvasDpr: canvasDpr // 增加了dpr,可方便外面echarts.init
|
||||
});
|
||||
}
|
||||
}).exec();
|
||||
},
|
||||
|
||||
initByNewWay(callback) {
|
||||
// version >= 2.9.0:使用新的方式初始化
|
||||
const query = wx.createSelectorQuery().in(this)
|
||||
query
|
||||
.select('.ec-canvas')
|
||||
.fields({ node: true, size: true })
|
||||
.exec(res => {
|
||||
const canvasNode = res[0].node
|
||||
this.canvasNode = canvasNode
|
||||
|
||||
const canvasDpr = wx.getSystemInfoSync().pixelRatio
|
||||
const canvasWidth = res[0].width
|
||||
const canvasHeight = res[0].height
|
||||
|
||||
const ctx = canvasNode.getContext('2d')
|
||||
|
||||
const canvas = new WxCanvas(ctx, this.data.canvasId, true, canvasNode)
|
||||
echarts.setCanvasCreator(() => {
|
||||
return canvas
|
||||
})
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)
|
||||
} else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
|
||||
this.chart = this.data.ec.onInit(canvas, canvasWidth, canvasHeight, canvasDpr)
|
||||
} else {
|
||||
this.triggerEvent('init', {
|
||||
canvas: canvas,
|
||||
width: canvasWidth,
|
||||
height: canvasHeight,
|
||||
dpr: canvasDpr
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
canvasToTempFilePath(opt) {
|
||||
if (this.data.isUseNewCanvas) {
|
||||
// 新版
|
||||
const query = wx.createSelectorQuery().in(this)
|
||||
query
|
||||
.select('.ec-canvas')
|
||||
.fields({ node: true, size: true })
|
||||
.exec(res => {
|
||||
const canvasNode = res[0].node
|
||||
opt.canvas = canvasNode
|
||||
wx.canvasToTempFilePath(opt)
|
||||
})
|
||||
} else {
|
||||
// 旧的
|
||||
if (!opt.canvasId) {
|
||||
opt.canvasId = this.data.canvasId;
|
||||
}
|
||||
ctx.draw(true, () => {
|
||||
wx.canvasToTempFilePath(opt, this);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
touchStart(e) {
|
||||
if (this.chart && e.touches.length > 0) {
|
||||
var touch = e.touches[0];
|
||||
var handler = this.chart.getZr().handler;
|
||||
handler.dispatch('mousedown', {
|
||||
zrX: touch.x,
|
||||
zrY: touch.y
|
||||
});
|
||||
handler.dispatch('mousemove', {
|
||||
zrX: touch.x,
|
||||
zrY: touch.y
|
||||
});
|
||||
handler.processGesture(wrapTouch(e), 'start');
|
||||
}
|
||||
},
|
||||
|
||||
touchMove(e) {
|
||||
if (this.chart && e.touches.length > 0) {
|
||||
var touch = e.touches[0];
|
||||
var handler = this.chart.getZr().handler;
|
||||
handler.dispatch('mousemove', {
|
||||
zrX: touch.x,
|
||||
zrY: touch.y
|
||||
});
|
||||
handler.processGesture(wrapTouch(e), 'change');
|
||||
}
|
||||
},
|
||||
|
||||
touchEnd(e) {
|
||||
if (this.chart) {
|
||||
const touch = e.changedTouches ? e.changedTouches[0] : {};
|
||||
var handler = this.chart.getZr().handler;
|
||||
handler.dispatch('mouseup', {
|
||||
zrX: touch.x,
|
||||
zrY: touch.y
|
||||
});
|
||||
handler.dispatch('click', {
|
||||
zrX: touch.x,
|
||||
zrY: touch.y
|
||||
});
|
||||
handler.processGesture(wrapTouch(e), 'end');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function wrapTouch(event) {
|
||||
for (let i = 0; i < event.touches.length; ++i) {
|
||||
const touch = event.touches[i];
|
||||
touch.offsetX = touch.x;
|
||||
touch.offsetY = touch.y;
|
||||
}
|
||||
return event;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<!-- 新的:接口对其了H5 -->
|
||||
<canvas wx:if="{{isUseNewCanvas}}" type="2d" class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>
|
||||
<!-- 旧的 -->
|
||||
<canvas wx:else class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>
|
||||
@@ -0,0 +1,4 @@
|
||||
.ec-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
export default class WxCanvas {
|
||||
constructor(ctx, canvasId, isNew, canvasNode) {
|
||||
this.ctx = ctx;
|
||||
this.canvasId = canvasId;
|
||||
this.chart = null;
|
||||
this.isNew = isNew
|
||||
if (isNew) {
|
||||
this.canvasNode = canvasNode;
|
||||
}
|
||||
else {
|
||||
this._initStyle(ctx);
|
||||
}
|
||||
|
||||
// this._initCanvas(zrender, ctx);
|
||||
|
||||
this._initEvent();
|
||||
}
|
||||
|
||||
getContext(contextType) {
|
||||
if (contextType === '2d') {
|
||||
return this.ctx;
|
||||
}
|
||||
}
|
||||
|
||||
// canvasToTempFilePath(opt) {
|
||||
// if (!opt.canvasId) {
|
||||
// opt.canvasId = this.canvasId;
|
||||
// }
|
||||
// return wx.canvasToTempFilePath(opt, this);
|
||||
// }
|
||||
|
||||
setChart(chart) {
|
||||
this.chart = chart;
|
||||
}
|
||||
|
||||
attachEvent() {
|
||||
// noop
|
||||
}
|
||||
|
||||
detachEvent() {
|
||||
// noop
|
||||
}
|
||||
|
||||
_initCanvas(zrender, ctx) {
|
||||
zrender.util.getContext = function () {
|
||||
return ctx;
|
||||
};
|
||||
|
||||
zrender.util.$override('measureText', function (text, font) {
|
||||
ctx.font = font || '12px sans-serif';
|
||||
return ctx.measureText(text);
|
||||
});
|
||||
}
|
||||
|
||||
_initStyle(ctx) {
|
||||
var styles = ['fillStyle', 'strokeStyle', 'globalAlpha',
|
||||
'textAlign', 'textBaseAlign', 'shadow', 'lineWidth',
|
||||
'lineCap', 'lineJoin', 'lineDash', 'miterLimit', 'fontSize'];
|
||||
|
||||
styles.forEach(style => {
|
||||
Object.defineProperty(ctx, style, {
|
||||
set: value => {
|
||||
if (style !== 'fillStyle' && style !== 'strokeStyle'
|
||||
|| value !== 'none' && value !== null
|
||||
) {
|
||||
ctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ctx.createRadialGradient = () => {
|
||||
return ctx.createCircularGradient(arguments);
|
||||
};
|
||||
}
|
||||
|
||||
_initEvent() {
|
||||
this.event = {};
|
||||
const eventNames = [{
|
||||
wxName: 'touchStart',
|
||||
ecName: 'mousedown'
|
||||
}, {
|
||||
wxName: 'touchMove',
|
||||
ecName: 'mousemove'
|
||||
}, {
|
||||
wxName: 'touchEnd',
|
||||
ecName: 'mouseup'
|
||||
}, {
|
||||
wxName: 'touchEnd',
|
||||
ecName: 'click'
|
||||
}];
|
||||
|
||||
eventNames.forEach(name => {
|
||||
this.event[name.wxName] = e => {
|
||||
const touch = e.touches[0];
|
||||
this.chart.getZr().handler.dispatch(name.ecName, {
|
||||
zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
|
||||
zrY: name.wxName === 'tap' ? touch.clientY : touch.y
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
set width(w) {
|
||||
if (this.canvasNode) this.canvasNode.width = w
|
||||
}
|
||||
set height(h) {
|
||||
if (this.canvasNode) this.canvasNode.height = h
|
||||
}
|
||||
|
||||
get width() {
|
||||
if (this.canvasNode)
|
||||
return this.canvasNode.width
|
||||
return 0
|
||||
}
|
||||
get height() {
|
||||
if (this.canvasNode)
|
||||
return this.canvasNode.height
|
||||
return 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import * as echarts from '../../../ecCanvas/components/ec-canvas/echarts';
|
||||
|
||||
function initChart(canvas, width, height, dpr) {
|
||||
const chart = echarts.init(canvas, null, {
|
||||
width: width,
|
||||
height: height,
|
||||
devicePixelRatio: dpr // new
|
||||
});
|
||||
canvas.setChart(chart);
|
||||
|
||||
var option = {
|
||||
title: {
|
||||
text: '测试下面legend的红色区域不应被裁剪',
|
||||
left: 'center'
|
||||
},
|
||||
legend: {
|
||||
data: ['A', 'B', 'C'],
|
||||
top: 50,
|
||||
left: 'center',
|
||||
backgroundColor: 'red',
|
||||
z: 100
|
||||
},
|
||||
grid: {
|
||||
containLabel: true
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: 'axis'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
|
||||
// show: false
|
||||
},
|
||||
yAxis: {
|
||||
x: 'center',
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
type: 'dashed'
|
||||
}
|
||||
}
|
||||
// show: false
|
||||
},
|
||||
series: [{
|
||||
name: 'A',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: [18, 36, 65, 30, 78, 40, 33]
|
||||
}, {
|
||||
name: 'B',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: [12, 50, 51, 35, 70, 30, 20]
|
||||
}, {
|
||||
name: 'C',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: [10, 30, 31, 50, 40, 20, 10]
|
||||
}]
|
||||
};
|
||||
|
||||
chart.setOption(option);
|
||||
return chart;
|
||||
}
|
||||
|
||||
Page({
|
||||
|
||||
data: {
|
||||
ec: {
|
||||
onInit: initChart
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"ec-canvas": "../../../ecCanvas/components/ec-canvas/ec-canvas"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<!--index.wxml-->
|
||||
分包
|
||||
<view class="echarts-con">
|
||||
<ec-canvas id="mychart-dom-line" canvas-id="mychart-line" ec="{{ ec }}"></ec-canvas>
|
||||
</view>
|
||||
@@ -0,0 +1,17 @@
|
||||
.echarts-con {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
ec-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// pages/customer/addCard/index.js
|
||||
Page({
|
||||
data: {
|
||||
c_time:'',
|
||||
},
|
||||
//生命周期函数--监听页面加载
|
||||
onLoad: function (options) {
|
||||
|
||||
},
|
||||
|
||||
//输入
|
||||
inputTx(e) {
|
||||
this.setData({
|
||||
[e.currentTarget.dataset.key]: e.detail.value
|
||||
})
|
||||
},
|
||||
|
||||
putaddStaff() {
|
||||
let that = this
|
||||
if (that.data.uname == '' ) {
|
||||
wx.showToast({
|
||||
title: '请输入员工姓名',
|
||||
icon: 'none'
|
||||
})
|
||||
} else if (!/^1[3456789]\d{9}$/.test(that.data.mobile)){
|
||||
wx.showToast({
|
||||
title: '请输入正确的手机号',
|
||||
icon: 'none'
|
||||
})
|
||||
} else{
|
||||
that.setData({
|
||||
submitFlag: true,
|
||||
})
|
||||
|
||||
let params = {};
|
||||
params['id'] = this.data.id;
|
||||
params['uname'] = that.data.uname;
|
||||
params['mobile'] = that.data.mobile;
|
||||
params['role'] = that.data.role?1:0;
|
||||
_.apiQuery.putDxtEmployeesInfo(params).then(res => {
|
||||
wx.showModal({
|
||||
title: '添加成功',
|
||||
content: '',
|
||||
confirmText: "继续添加",
|
||||
confirmColor: "#1282e1",
|
||||
cancelText: "返回",
|
||||
cancelColor: "#000000",
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
that.setData({
|
||||
uname:'',
|
||||
mobile:'',
|
||||
role:false,
|
||||
submitFlag:false,
|
||||
})
|
||||
} else if (res.cancel) {
|
||||
wx.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}).catch(res=>{
|
||||
this.setData({
|
||||
submitFlag: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"navigationBarTitleText": "客户建卡",
|
||||
"usingComponents": {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<view class="container">
|
||||
<view class="inner30">
|
||||
<view class="pl40 pr40 pt10 pb10 relative ulib-r10 box-shadow-lightGray overflowhidden">
|
||||
<view class="relative bbs-1-eb last-b-none pl140 font-28">
|
||||
<view class="absolute left-0 box-middle">客户姓名</view>
|
||||
<view>
|
||||
<input class="wp100 height-100 text-right font-28" placeholder-class="color-ccc" type="text" placeholder="请输入客户姓名" bindinput='inputTx' data-key="uname" name='uname' value='{{uname}}' />
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb last-b-none pl140 font-28">
|
||||
<view class="absolute left-0 box-middle">手机号码</view>
|
||||
<view>
|
||||
<input class="wp100 height-100 text-right font-28" placeholder-class="color-ccc" type="number" placeholder="请输入客户手机号" bindinput='inputTx' data-key="mobile" name='mobile' value='{{mobile}}' />
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">品牌</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
<picker mode="date" value="{{c_time}}" bindchange="bindStartDateChange">
|
||||
<text class="color-ccc" wx:if="{{c_time == ''}}">请选择</text>
|
||||
<text wx:else>{{c_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">车型</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
<picker mode="date" value="{{c_time}}" bindchange="bindStartDateChange">
|
||||
<text class="color-ccc" wx:if="{{c_time == ''}}">请选择</text>
|
||||
<text wx:else>{{c_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">颜色</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
<picker mode="date" value="{{c_time}}" bindchange="bindStartDateChange">
|
||||
<text class="color-ccc" wx:if="{{c_time == ''}}">请选择</text>
|
||||
<text wx:else>{{c_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">备选车型</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
<picker mode="date" value="{{c_time}}" bindchange="bindStartDateChange">
|
||||
<text class="color-ccc" wx:if="{{c_time == ''}}">请选择</text>
|
||||
<text wx:else>{{c_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">预计购车时间</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
<picker mode="date" value="{{c_time}}" bindchange="bindStartDateChange">
|
||||
<text class="color-ccc" wx:if="{{c_time == ''}}">请选择</text>
|
||||
<text wx:else>{{c_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="mt60 pl60 pr60">
|
||||
<button class="wp100 btn-36afa2 pt10 pb10 text-center font-32 color-fff ulib-r750" hover-class="btn-36afa2-hover" disabled="{{submitFlag}}" bindtap="putaddStaff">确认建卡</button>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<lcb-footer></lcb-footer>
|
||||
@@ -0,0 +1 @@
|
||||
/* pages/customer/addCard/index.wxss */
|
||||
@@ -0,0 +1,91 @@
|
||||
Page({
|
||||
data: {
|
||||
tabid:1,
|
||||
tab:[
|
||||
{"id":0,"title":"详细信息"},
|
||||
{"id":1,"title":"跟进记录"},
|
||||
{"id":2,"title":"智能标签"}
|
||||
],
|
||||
statusid:0,
|
||||
status:[
|
||||
{
|
||||
"id":0,
|
||||
"title":"未见潜客",
|
||||
check:true,
|
||||
},
|
||||
{
|
||||
"id":1,
|
||||
"title":"到店潜客",
|
||||
check:false,
|
||||
},
|
||||
{
|
||||
"id":2,
|
||||
"title":"订单客户",
|
||||
},
|
||||
{
|
||||
"id":3,
|
||||
"title":"战败客户",
|
||||
},
|
||||
],
|
||||
isShowSelectStatus:false,
|
||||
step:[
|
||||
{
|
||||
id:0,
|
||||
time:'2020.6.18 21:00',
|
||||
content:'通过XX海报加入客户',
|
||||
},
|
||||
{
|
||||
id:1,
|
||||
time:'2020.6.18 21:00',
|
||||
content:'店员 康康 交易完成 获得佣金 370元',
|
||||
},
|
||||
{
|
||||
id:2,
|
||||
time:'2020.6.18 21:00',
|
||||
content:'变更状态为已处理短信+1(16)',
|
||||
},
|
||||
{
|
||||
id:3,
|
||||
time:'2020.6.18 21:00',
|
||||
content:'店长 jimmy 获取佣金130元 ',
|
||||
},
|
||||
],
|
||||
},
|
||||
onLoad(options) {
|
||||
},
|
||||
onshow() {
|
||||
|
||||
},
|
||||
//切换tab
|
||||
changeTab(e){
|
||||
this.setData({
|
||||
tabid: this.data.tab[e.currentTarget.dataset.index].id,
|
||||
})
|
||||
//this.searchSubmit()
|
||||
},
|
||||
|
||||
//单选
|
||||
radioPicker(e){
|
||||
if(e.currentTarget.dataset.id != this.data.statusid){
|
||||
this.setData({
|
||||
isSubmiting: false,
|
||||
statusid:e.currentTarget.dataset.id,
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
//显示变更状态
|
||||
showSelectStatus(){
|
||||
this.setData({
|
||||
isShowSelectStatus:true,
|
||||
})
|
||||
},
|
||||
|
||||
//确认变更状态
|
||||
hideSelectStatus(){
|
||||
this.setData({
|
||||
isShowSelectStatus:false,
|
||||
})
|
||||
},
|
||||
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<view class="container">
|
||||
<view class="inner40">
|
||||
<view class="inner40 relative ulib-r10 box-shadow-lightGray mb30 overflowhidden">
|
||||
<view class="absolute top-0 left-0 width-25 mt40 pt5 pb5 bg-36afa2 line-height-13 font-22 color-fff">潜客</view>
|
||||
<view class="relative pr180">
|
||||
<view class="font-32">
|
||||
<text>林先生</text>
|
||||
<text>(*382)</text>
|
||||
<text class="iconfont icon-xingxing ml10"></text>
|
||||
</view>
|
||||
<view class="text-nowrap">
|
||||
<text class="inline-block mr10 pt5 pb5 pl10 pr10 bg-666 font-18 color-fff ulib-r750">H级客户</text>
|
||||
<text class="inline-block mr10 pt5 pb5 pl10 pr10 bg-666 font-18 color-fff ulib-r750">H级客户</text>
|
||||
<text class="inline-block mr10 pt5 pb5 pl10 pr10 bg-666 font-18 color-fff ulib-r750">H级客户</text>
|
||||
<text class="inline-block mr10 pt5 pb5 pl10 pr10 bg-666 font-18 color-fff ulib-r750">H级客户</text>
|
||||
...
|
||||
</view>
|
||||
<view class="absolute right-0 box-middle">
|
||||
<view class="inline-block relative img-55x55 bg-333 font-28 color-fff mr30 ulib-r750" catchtap="showMessage" data-id="{{info.id}}">
|
||||
<i class="absolute box-center-middle iconfont icon-liuyan"></i>
|
||||
</view>
|
||||
<view class="inline-block relative img-55x55 bg-333 font-28 color-fff ulib-r750" catchtap="{{info.call_type == 'xz'?'callXz':'call'}}" data-id="{{info.id}}" data-type="{{info.type}}">
|
||||
<i class="absolute box-center-middle iconfont icon-dianhua"></i>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt25 fn-clear font-28">
|
||||
<view class="fn-fl">品牌车型</view>
|
||||
<view class="fn-fr wp60 text-nowrap text-right color-666">东风EX1</view>
|
||||
</view>
|
||||
<view class=mt25 fn-clear font-28">
|
||||
<view class="fn-fl">品牌车型</view>
|
||||
<view class="fn-fr wp60 text-nowrap text-right color-666">东风EX1</view>
|
||||
</view>
|
||||
<view class="mt25 fn-clear font-28">
|
||||
<view class="fn-fl">品牌车型</view>
|
||||
<view class="fn-fr wp60 text-nowrap text-right color-666">东风EX1</view>
|
||||
</view>
|
||||
<view class="mt25 fn-clear font-28">
|
||||
<view class="fn-fl">品牌车型</view>
|
||||
<view class="fn-fr wp60 text-nowrap text-right color-666">东风EX1</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="fn-flex font-32 color-666 text-center">
|
||||
<block wx:for='{{tab}}' wx:key='list'>
|
||||
<view class="fn-flex-item pl20 pr20 tabmenu2 {{tabid == item.id?'active color-36afa2':''}}" data-index="{{index}}" bindtap="changeTab">
|
||||
<view class="relative">{{item.title}}</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="mt30 pb150" wx:if="{{tabid == tab[0].id}}">
|
||||
<view class="font-22">
|
||||
<i class="iconfont icon-fenqi mr10"></i>
|
||||
<text>分期信息</text>
|
||||
</view>
|
||||
<view class="mt10">
|
||||
<view class="relative bbs-1-eb last-b-none pl140 font-28">
|
||||
<view class="absolute left-0 box-middle">客户姓名</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
哈哈哈
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb last-b-none pl140 font-28">
|
||||
<view class="absolute left-0 box-middle">手机号码</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
153*****7676
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">性别</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
男
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt30 pb150" wx:elif="{{tabid == tab[1].id}}">
|
||||
<view class="fn-flex text-center">
|
||||
<view class="fn-flex-item mr15 pt20 pb20 bg-f3f6fc ulib-r10">
|
||||
<view class="font-32">6</view>
|
||||
<view class="font-22">去电</view>
|
||||
</view>
|
||||
<view class="fn-flex-item ml15 mr15 pt20 pb20 bg-fffaeb ulib-r10">
|
||||
<view class="font-32">6</view>
|
||||
<view class="font-22">短信</view>
|
||||
</view>
|
||||
<view class="fn-flex-item ml15 mr15 pt20 pb20 bg-f1f9f8 ulib-r10">
|
||||
<view class="font-32">6</view>
|
||||
<view class="font-22">到店</view>
|
||||
</view>
|
||||
<view class="fn-flex-item ml15 pt20 pb20 bg-fff6f8 ulib-r10">
|
||||
<view class="font-32">6</view>
|
||||
<view class="font-22">试驾</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt40 font-22">
|
||||
<i class="iconfont icon-genzong mr10"></i>
|
||||
<text>用户跟踪</text>
|
||||
</view>
|
||||
<view class="orderDtail-log mt30 relative" wx:if="{{step.length>0}}">
|
||||
<block wx:for="{{step}}" wx:key="index">
|
||||
<view class="orderDtail-log-item pl40 relative">
|
||||
<view class="orderDtail-log-content">
|
||||
<view class="font-22 color-999">{{item.time}}</view>
|
||||
<view class="font-28 text-break">{{item.content}}</view>
|
||||
</view>
|
||||
<i class="absolute left-0 box-middle mt40 bg-fff line-height-11 font-22 color-999 iconfont icon-jiantou" wx:if="{{index+1 != step.length}}"></i>
|
||||
<text class="absolute orderDtail-log-dot"></text>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt30 pb150" wx:elif="{{tabid == tab[2].id}}">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="fixed left-0 bottom-0 right-0 bg-fff-op80 pl100 pr100 pt20 pb20">
|
||||
<button class="wp100 btn-36afa2 pt10 pb10 text-center font-32 color-fff ulib-r750" bindtap="showSelectStatus">变更状态</button>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<lcb-msg isShow="{{isShowSelectStatus}}">
|
||||
<view slot="content">
|
||||
<view class="mt50 font-36 text-center">修改状态</view>
|
||||
<scroll-view class="pb50" scroll-y="true" style="max-height:600rpx;">
|
||||
<view class="pl40 pr40 mt20 font-32">
|
||||
<block wx:for="{{status}}" wx:key='index'>
|
||||
<view class="relative mt20 inner30 bg-f6 ulib-r10" bindtap="radioPicker" data-id="{{item.id}}">
|
||||
<text>{{item.title}}</text>
|
||||
<i class="absolute right-0 box-middle mr30 iconfont {{statusid == item.id?'icon-danxuan_xuanzhong color-36afa2':'icon-danxuan'}}"></i>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="bts-1-eb text-center font-32 color-666">
|
||||
<view class="pt25 pb25 color-36afa2" bindtap="hideSelectStatus">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</lcb-msg>
|
||||
@@ -0,0 +1,48 @@
|
||||
.tabmenu2{display:inline-block;line-height:72rpx;}
|
||||
.tabmenu2.active view.relative{display:inline-block;}
|
||||
.tabmenu2.active view.relative::before{display:inline-block;position:absolute;bottom:0;left:50%;transform:translate(-50%,0);width:64rpx;height:4rpx;content:"";background-color:#36afa2;}
|
||||
|
||||
.width-25{width:25rpx;}
|
||||
|
||||
.orderDtail-log::before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 10rpx;
|
||||
bottom: 10rpx;
|
||||
background-color: #1a1a1a;
|
||||
width: 2rpx;
|
||||
left:10rpx;
|
||||
}
|
||||
.orderDtail-log-item{
|
||||
margin-top: 40rpx;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.orderDtail-log-item:first-child{
|
||||
margin-top: 0;
|
||||
}
|
||||
.orderDtail-log-dot{
|
||||
top: 8rpx;
|
||||
left:0;
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
border-radius: 100%;
|
||||
background-color: #fff;
|
||||
}
|
||||
.orderDtail-log-dot::before{
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
.orderDtail-log-dot::after{
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background-color: #1a1a1a;
|
||||
}
|
||||
.orderDtail-log-dot::before,.orderDtail-log-dot::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
border-radius: 100%;
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
import _ from '../../commons/js/commons'
|
||||
const app = getApp()
|
||||
Page({
|
||||
data: {
|
||||
list: [],
|
||||
searchInp:{
|
||||
value: '',
|
||||
focus: false,
|
||||
},
|
||||
sourcetabindex: -1,
|
||||
a_id: '',
|
||||
c_time:'',
|
||||
u_id:'',
|
||||
r_time: '',
|
||||
pageNo: 1,
|
||||
noData: false,
|
||||
end: false,
|
||||
load: true,
|
||||
loading: false,
|
||||
flag: 0,
|
||||
tab_list: [],
|
||||
tag_list: [],
|
||||
activityList: [],
|
||||
isShowScreen:false,
|
||||
isShowDropDown:false,
|
||||
form:'',
|
||||
isRefresh:false,
|
||||
status_pid:-2,
|
||||
status_id:'',
|
||||
tag_id:'',
|
||||
user_list: [],
|
||||
objUser_list: [],
|
||||
userindex:-1,
|
||||
serviceindex: -1,
|
||||
|
||||
isShowMessage:false,
|
||||
isShowSort:false,
|
||||
isClickSort:false,
|
||||
timeSlot:[
|
||||
{
|
||||
title:'今天',
|
||||
},
|
||||
{
|
||||
title:'昨天',
|
||||
},
|
||||
{
|
||||
title:'近七天',
|
||||
},
|
||||
{
|
||||
title:'近三十天',
|
||||
},
|
||||
],
|
||||
testDriveIndex:0,
|
||||
testDrive:[
|
||||
{
|
||||
title:'全部',
|
||||
},
|
||||
{
|
||||
title:'是',
|
||||
},
|
||||
{
|
||||
title:'否',
|
||||
},
|
||||
],
|
||||
timeSlotIndex:0,
|
||||
},
|
||||
onLoad: function (options) {
|
||||
for (let key in options) {
|
||||
this.setData({
|
||||
[key]: options[key]
|
||||
})
|
||||
}
|
||||
this.getCustomerTab()
|
||||
},
|
||||
|
||||
//切换tab
|
||||
changeTab(e){
|
||||
this.setData({
|
||||
status_pid: this.data.tab[e.currentTarget.dataset.index].id,
|
||||
})
|
||||
this.searchSubmit()
|
||||
},
|
||||
|
||||
//拨打客户电话Yx
|
||||
call(e) {
|
||||
let params = {};
|
||||
params['id'] = e.currentTarget.dataset.id;
|
||||
params['type'] = e.currentTarget.dataset.type;
|
||||
_.apiQuery.getAppYx(params).then(res=>{
|
||||
if(!!res.data.service_msg){
|
||||
this.setData({
|
||||
isShowNote:true,
|
||||
notemsg:res.data.service_msg,
|
||||
})
|
||||
}else{
|
||||
wx.makePhoneCall({
|
||||
phoneNumber: res.data.mobile,
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
//拨打客户电话Xz
|
||||
callXz(e) {
|
||||
let params = {};
|
||||
params['id'] = e.currentTarget.dataset.id;
|
||||
params['type'] = e.currentTarget.dataset.type;
|
||||
_.apiQuery.getAppXz(params).then(res=>{
|
||||
if(!!res.data.service_msg){
|
||||
this.setData({
|
||||
isShowNote:true,
|
||||
notemsg:res.data.service_msg,
|
||||
})
|
||||
}else{
|
||||
wx.makePhoneCall({
|
||||
phoneNumber: res.data.mobile,
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
//提交搜索
|
||||
searchSubmit(){
|
||||
this.setData({
|
||||
list: [],
|
||||
pageNo: 1,
|
||||
noData: false,
|
||||
end: false,
|
||||
load: true,
|
||||
loading: false,
|
||||
flag: this.data.flag + 1
|
||||
})
|
||||
this.getAppCustomer()
|
||||
},
|
||||
|
||||
//客多宝-tab
|
||||
getCustomerTab() {
|
||||
let params = {};
|
||||
params['biz_id'] = !!this.data.bizid?this.data.bizid:'0';
|
||||
_.apiQuery.getCustomerTab(params).then(res => {
|
||||
this.setData({
|
||||
tab_list:res.data.tab_list,
|
||||
tag_list:res.data.tag_list,
|
||||
})
|
||||
|
||||
if(!!this.data.type){
|
||||
let tab_list = res.data.tab_list
|
||||
tab_list.forEach((item, index)=>{
|
||||
if(item.value == this.data.type){
|
||||
this.setData({
|
||||
sourcetabindex:index,
|
||||
})
|
||||
}
|
||||
});
|
||||
}else{
|
||||
this.setData({
|
||||
type:res.data.tab_list[0].value,
|
||||
sourcetabindex:0,
|
||||
})
|
||||
}
|
||||
|
||||
this.getCustomerStatus()
|
||||
|
||||
if(this.data.sourcetabindex>-1&&this.data.tab_list[this.data.sourcetabindex].value==2){
|
||||
this.getAppSytactivity()
|
||||
}
|
||||
|
||||
wx.stopPullDownRefresh()
|
||||
});
|
||||
},
|
||||
|
||||
//活动列表
|
||||
getAppSytactivity() {
|
||||
let params = {};
|
||||
params['page'] = 1;
|
||||
params['size'] = 50;
|
||||
params['type'] = 0;
|
||||
if(!!this.data.bizid){
|
||||
params['biz_id'] = this.data.bizid;
|
||||
}
|
||||
_.apiQuery.getAppSytactivity(params).then(res => {
|
||||
this.setData({
|
||||
activityList: res.data.list,
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
//客多宝列表
|
||||
getAppCustomer() {
|
||||
this.setData({
|
||||
load: false,
|
||||
loading: true,
|
||||
})
|
||||
let params = {};
|
||||
if(this.data.isRefresh){
|
||||
params['page'] = 1;
|
||||
params['size'] = (this.data.pageNo - 1)*10;
|
||||
}else{
|
||||
params['page'] = this.data.pageNo;
|
||||
params['size'] = 10;
|
||||
}
|
||||
params['biz_id'] = !!this.data.bizid?this.data.bizid:'0';
|
||||
|
||||
params['type'] = this.data.type;
|
||||
if(this.data.searchInp.value != ''){
|
||||
params['keyword'] = this.data.searchInp.value;
|
||||
}
|
||||
if(this.data.a_id != ''){
|
||||
params['a_id'] = this.data.a_id;
|
||||
}
|
||||
if(this.data.c_time != ''){
|
||||
params['c_time'] = this.data.c_time;
|
||||
}
|
||||
if(this.data.u_id != ''){
|
||||
params['ubid'] = this.data.u_id;
|
||||
}
|
||||
if(this.data.r_time != ''){
|
||||
params['r_time'] = this.data.r_time;
|
||||
}
|
||||
if(this.data.status_pid != -2){
|
||||
params['status_pid'] = this.data.status_pid;
|
||||
}
|
||||
if(this.data.status_id != ''){
|
||||
params['status_id'] = this.data.status_id;
|
||||
}
|
||||
if(this.data.tag_id != ''){
|
||||
params['tag_id'] = this.data.tag_id;
|
||||
}
|
||||
_.apiQuery.getAppCustomer(params).then(res => {
|
||||
console.log(res)
|
||||
this.setData({
|
||||
flag: this.data.flag - 1
|
||||
})
|
||||
if (!this.data.flag) {
|
||||
if(this.data.isRefresh){
|
||||
this.setData({
|
||||
total: res.data.total,
|
||||
list: res.data.list,
|
||||
load: true,
|
||||
loading: false,
|
||||
isRefresh: false,
|
||||
})
|
||||
}else{
|
||||
this.setData({
|
||||
total: res.data.total,
|
||||
pageNo: this.data.pageNo + 1,
|
||||
list: this.data.list.concat(res.data.list),
|
||||
load: true,
|
||||
loading: false,
|
||||
})
|
||||
}
|
||||
if (res.data.total == 0) {
|
||||
this.setData({
|
||||
noData: true
|
||||
})
|
||||
} else if (this.data.list.length == res.data.total) {
|
||||
this.setData({
|
||||
end: true
|
||||
})
|
||||
}
|
||||
}
|
||||
wx.stopPullDownRefresh()
|
||||
});
|
||||
},
|
||||
bindEndDateChange: function(e) {
|
||||
this.setData({
|
||||
r_time: e.detail.value
|
||||
})
|
||||
this.searchSubmit()
|
||||
},
|
||||
|
||||
//状态tab
|
||||
getCustomerStatus(){
|
||||
let params = {};
|
||||
params['type'] = this.data.type;
|
||||
_.apiQuery.getCustomerStatus(params).then(res=>{
|
||||
|
||||
this.setData({
|
||||
if_ub:res.data.rolevel,
|
||||
tab:res.data.list,
|
||||
status_pid: this.data.status_pid == -2?res.data.list[0].id:this.data.status_pid
|
||||
})
|
||||
|
||||
this.searchSubmit()
|
||||
})
|
||||
},
|
||||
|
||||
//选择标签
|
||||
changeTag(e){
|
||||
this.setData({
|
||||
tag_id: e.currentTarget.dataset.id,
|
||||
})
|
||||
this.searchSubmit()
|
||||
},
|
||||
|
||||
bindUserPicker(e) {
|
||||
this.setData({
|
||||
userindex: e.detail.value
|
||||
})
|
||||
},
|
||||
|
||||
//隐藏高级搜索
|
||||
hidesearch() {
|
||||
this.setData({
|
||||
isShowSort: false
|
||||
})
|
||||
},
|
||||
|
||||
//显示高级搜索
|
||||
showSort(){
|
||||
this.setData({
|
||||
isClickSort: true,
|
||||
isShowSort: !this.data.isShowSort
|
||||
})
|
||||
},
|
||||
|
||||
//单选
|
||||
radioPicker(e){
|
||||
if(e.currentTarget.dataset.type == 'timeSlot'){
|
||||
this.setData({
|
||||
timeSlotIndex:e.currentTarget.dataset.index,
|
||||
})
|
||||
} else if(e.currentTarget.dataset.type == 'testDrive'){
|
||||
this.setData({
|
||||
testDriveIndex:e.currentTarget.dataset.index,
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
//显示短信弹框
|
||||
showMessage(e){
|
||||
this.setData({
|
||||
messageId:e.currentTarget.dataset.id,
|
||||
isShowMessage:true,
|
||||
})
|
||||
},
|
||||
|
||||
//关闭短信弹框
|
||||
hideMessage(e){
|
||||
this.setData({
|
||||
isShowMessage:false,
|
||||
})
|
||||
},
|
||||
|
||||
//推送链接
|
||||
pushLink(e){
|
||||
if(e.currentTarget.dataset.url){
|
||||
_.$router.openUrlScheme(e.currentTarget.dataset.url)
|
||||
}
|
||||
},
|
||||
|
||||
//页面相关事件处理函数--监听用户下拉动作
|
||||
onPullDownRefresh: function () {
|
||||
this.setData({
|
||||
list: [],
|
||||
pageNo: 1,
|
||||
noData: false,
|
||||
end: false,
|
||||
load: true,
|
||||
loading: false,
|
||||
flag: this.data.flag + 1
|
||||
})
|
||||
this.getAppCustomer()
|
||||
},
|
||||
|
||||
//页面上拉触底事件的处理函数
|
||||
onReachBottom: function () {
|
||||
if (this.data.noData || this.data.end||!this.data.load) return;
|
||||
this.setData({
|
||||
flag: this.data.flag + 1
|
||||
})
|
||||
this.getAppCustomer()
|
||||
},
|
||||
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"navigationBarTitleText": "客户",
|
||||
"enablePullDownRefresh": true,
|
||||
"usingComponents": {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
<view class="container">
|
||||
|
||||
<view>
|
||||
<view style="padding-top:110rpx"></view>
|
||||
<view class="fixed top-0 left-0 right-0 bg-fff z-index-1">
|
||||
<view class="mt5 fn-flex font-32 color-666 text-center" wx:if="{{tab.length<5}}">
|
||||
<block wx:for='{{tab}}' wx:key='list'>
|
||||
<view class="fn-flex-item pl20 pr20 tabmenu2 {{status_pid == item.id?'active color-36afa2':''}}" data-index="{{index}}" bindtap="changeTab">
|
||||
<view class="relative">{{item.title}}</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<scroll-view class="mt5 font-28 color-666 text-center space-nowrap" scroll-x="true" wx:else>
|
||||
<block wx:for='{{tab}}' wx:key='list'>
|
||||
<view class="pl20 pr20 tabmenu2 {{status_pid == item.id?'active color-36afa2':''}}" data-index="{{index}}" bindtap="changeTab" >
|
||||
<view class="relative">{{item.title}}</view>
|
||||
</view>
|
||||
</block>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="pl40 pb15 fn-clear">
|
||||
<view class="fn-fl">
|
||||
<text class="text-middle">共<text class="color-f9394d">{{total}}</text>条</text>
|
||||
<picker class="inline-block text-middle bg-f6 ml20 pt5 pb5 pl15 pr15 ulib-r750 font-22" mode="date" value="{{r_time}}" bindchange="bindEndDateChange">
|
||||
<text class="color-666" wx:if="{{r_time == ''}}">建卡日期</text>
|
||||
<text wx:else>{{r_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="fn-fr pr180 relative">
|
||||
<text bindtap="showSort" class="inner5 iconfont icon-gaojisousuo ml10"></text>
|
||||
<view bindtap="pushLink" data-url="/pages/customer/addCard/index" class="absolute right-0 box-middle pt5 pb5 pl10 pr30 space-nowrap bg-333 font-22 color-fff ulib-rl750"><i class="iconfont mr5 icon-jia"></i>客户建卡</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="mt10 pl30 pr30">
|
||||
|
||||
<block wx:for='{{list}}' wx:key='index'>
|
||||
<view class="inner40 relative ulib-r10 box-shadow-lightGray mb30 overflowhidden" bindtap="pushLink" data-url="{{item.url}}">
|
||||
<view class="relative pr180">
|
||||
<view class="font-32">
|
||||
<text>{{item.cust_name}}</text>
|
||||
<text>(*382)</text>
|
||||
<text class="iconfont icon-xingxing ml10"></text>
|
||||
</view>
|
||||
<view class="text-nowrap">
|
||||
<text class="inline-block mr10 pt5 pb5 pl10 pr10 bg-666 font-18 color-fff ulib-r750">H级客户</text>
|
||||
<text class="inline-block mr10 pt5 pb5 pl10 pr10 bg-666 font-18 color-fff ulib-r750">H级客户</text>
|
||||
<text class="inline-block mr10 pt5 pb5 pl10 pr10 bg-666 font-18 color-fff ulib-r750">H级客户</text>
|
||||
<text class="inline-block mr10 pt5 pb5 pl10 pr10 bg-666 font-18 color-fff ulib-r750">H级客户</text>
|
||||
...
|
||||
</view>
|
||||
<view class="absolute right-0 box-middle">
|
||||
<view class="inline-block relative img-55x55 bg-333 font-28 color-fff mr30 ulib-r750" catchtap="showMessage" data-id="{{item.id}}">
|
||||
<i class="absolute box-center-middle iconfont icon-liuyan"></i>
|
||||
</view>
|
||||
<view class="inline-block relative img-55x55 bg-333 font-28 color-fff ulib-r750" wx:if="{{item.disabled == 0}}" catchtap="{{item.call_type == 'xz'?'callXz':'call'}}" data-id="{{item.id}}" data-type="{{item.type}}">
|
||||
<i class="absolute box-center-middle iconfont icon-dianhua"></i>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt25 fn-clear font-28">
|
||||
<view class="fn-fl">品牌车型</view>
|
||||
<view class="fn-fr wp60 text-nowrap text-right color-666">东风EX1</view>
|
||||
</view>
|
||||
<view class="mt25 fn-clear font-28">
|
||||
<view class="fn-fl">品牌车型</view>
|
||||
<view class="fn-fr wp60 text-nowrap text-right color-666">东风EX1</view>
|
||||
</view>
|
||||
<view class="mt25 fn-clear font-28">
|
||||
<view class="fn-fl">品牌车型</view>
|
||||
<view class="fn-fr wp60 text-nowrap text-right color-666">东风EX1</view>
|
||||
</view>
|
||||
<view class="mt25 fn-clear font-28">
|
||||
<view class="fn-fl">品牌车型</view>
|
||||
<view class="fn-fr wp60 text-nowrap text-right color-666">东风EX1</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<lcb-listmore isLoading='{{loading}}' isEnd='{{end}}' isNoData='{{noData}}'></lcb-listmore>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<lcb-footer></lcb-footer>
|
||||
|
||||
<lcb-msg isShow="{{isShowMessage}}">
|
||||
<view slot="content">
|
||||
<view class="inner40">
|
||||
<textarea class="wp100 inner20 bds-1-eb font-28 ulib-r10" placeholder-class="color-ccc" maxlength='100' placeholder="请输入短信内容" bindinput='inputTx' data-key="uname" name='uname' value='{{uname}}' />
|
||||
</view>
|
||||
<view class="fn-flex bts-1-eb text-center font-32 color-666">
|
||||
<view class="fn-flex-item pt25 pb25" bindtap="hideMessage">取消</view>
|
||||
<view class="fn-flex-item bls-1-eb pt25 pb25 color-36afa2" bindtap="hideMessage">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</lcb-msg>
|
||||
|
||||
<view class="search-sort {{!isClickSort?'fn-hide':''}} {{!isShowSort?'sortout':'sortin'}} bg-fff fixed top-0 bottom-0 z-index-2 ulib-rl20 overflowhidden">
|
||||
<scroll-view class="wp100" scroll-y="true" style="height:100%">
|
||||
<view class="inner30">
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">建卡开始时间</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
<picker mode="date" value="{{c_time}}" bindchange="bindStartDateChange">
|
||||
<text class="color-ccc" wx:if="{{c_time == ''}}">请选择</text>
|
||||
<text wx:else>{{c_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">建卡结束时间</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
<picker mode="date" value="{{c_time}}" bindchange="bindStartDateChange">
|
||||
<text class="color-ccc" wx:if="{{c_time == ''}}">请选择</text>
|
||||
<text wx:else>{{c_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pt30 pb30 last-b-none">
|
||||
<view class="font-22">常用时间段</view>
|
||||
<view class="fn-clear">
|
||||
<block wx:for="{{timeSlot}}" wx:key='index'>
|
||||
<view class="inline-block radio-btn mt20 mr20 pt15 pb15 pl25 pr25 ulib-r10 font-28 {{timeSlotIndex == index?'bg-333 color-fff':'bg-f8'}}" bindtap="radioPicker" data-type="timeSlot" data-index="{{index}}">
|
||||
{{item.title}}
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pt30 pb30 last-b-none">
|
||||
<view class="font-22">是否试驾</view>
|
||||
<view class="fn-clear">
|
||||
<block wx:for="{{testDrive}}" wx:key='index'>
|
||||
<view class="inline-block radio-btn mt20 mr20 pt15 pb15 pl25 pr25 ulib-r10 font-28 {{testDriveIndex == index?'bg-333 color-fff':'bg-f8'}}" bindtap="radioPicker" data-type="testDrive" data-index="{{index}}">
|
||||
{{item.title}}
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">意向等级</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
<picker mode="date" value="{{c_time}}" bindchange="bindStartDateChange">
|
||||
<text class="color-ccc" wx:if="{{c_time == ''}}">请选择</text>
|
||||
<text wx:else>{{c_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">意向车名</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
<picker mode="date" value="{{c_time}}" bindchange="bindStartDateChange">
|
||||
<text class="color-ccc" wx:if="{{c_time == ''}}">请选择</text>
|
||||
<text wx:else>{{c_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">车型级别</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
<picker mode="date" value="{{c_time}}" bindchange="bindStartDateChange">
|
||||
<text class="color-ccc" wx:if="{{c_time == ''}}">请选择</text>
|
||||
<text wx:else>{{c_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">客户来源</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
<picker mode="date" value="{{c_time}}" bindchange="bindStartDateChange">
|
||||
<text class="color-ccc" wx:if="{{c_time == ''}}">请选择</text>
|
||||
<text wx:else>{{c_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative bbs-1-eb pl190 last-b-none">
|
||||
<view class="absolute left-0 box-middle font-28">到店次数</view>
|
||||
<view class="pt30 pb30 text-right font-28 color-666">
|
||||
<picker mode="date" value="{{c_time}}" bindchange="bindStartDateChange">
|
||||
<text class="color-ccc" wx:if="{{c_time == ''}}">请选择</text>
|
||||
<text wx:else>{{c_time}}</text>
|
||||
<i class="iconfont ml10 icon-gengduo"></i>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pt50 pb100"></view>
|
||||
</scroll-view>
|
||||
<view class="absolute left-0 bottom-0 right-0 fn-flex pt20 pb20 pl60 pr60 bg-fff-op90 text-center">
|
||||
<view class="fn-flex-item mr20 pt15 pb15 bds-2-36afa2 font-32 color-36afa2 ulib-r750" bindtap="resetsearch">重置</view>
|
||||
<view class="fn-flex-item ml20 pt15 pb15 bg-36afa2 font-32 color-fff ulib-r750" bindtap="hidesearch">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="search-bg fixed left-0 right-0 top-0 bottom-0" hidden="{{!isShowSort}}" style="background-color:rgba(0,0,0,.5);" bindtap="hidesearch"></view>
|
||||