This commit is contained in:
老叶
2021-07-04 18:09:48 +08:00
parent 3f5d7eaea5
commit d35252dffc
130 changed files with 10133 additions and 1 deletions
+2
View File
@@ -0,0 +1,2 @@
project.config.json
project.private.config.json
+31 -1
View File
@@ -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 //登录
+155
View File
@@ -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 () {
// 新版本下载失败
})
}
})
+80
View File
@@ -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"
}
}
}
+2
View File
@@ -0,0 +1,2 @@
/**app.wxss**/
@import "commons/css/common.wxss";
+83
View File
@@ -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
}
+26
View File
@@ -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;}
+15
View File
@@ -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;}
+13
View File
@@ -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);}
+14
View File
@@ -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;}
+28
View File
@@ -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;}
+17
View File
@@ -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;}
+119
View File
@@ -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;}
+74
View File
@@ -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;}
+115
View File
@@ -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;}
+27
View File
@@ -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;}
+14
View File
@@ -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;}
+13
View File
@@ -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";
+79
View File
@@ -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;
}
+36
View File
@@ -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;
}
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1018 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 869 B

+15
View File
@@ -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
}
+153
View File
@@ -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
}
+418
View File
@@ -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-231998/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
+36
View File
@@ -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;
+353
View File
@@ -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
}
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+423
View File
@@ -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
+130
View File
@@ -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;
+729
View File
@@ -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;
+180
View File
@@ -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
}
+254
View File
@@ -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 }
+26
View File
@@ -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)
}
}
+311
View File
@@ -0,0 +1,311 @@
/**
* 使用方法:
* 1.脚本顶部引入 const app = getApp();
* 2.Utils.$router.push(name,params,type,openMode)
* -1params为传入参数和值,如果params有值,将存在本地存储中
* -2)如果type(默认为params)为query时,参数会拼接到url后面
* -3openMode 开发方式 默认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.链式调用successfailcomplete
* 例: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;
}
}
+143
View File
@@ -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
}
+201
View File
@@ -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
}
+300
View File
@@ -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
}
+76
View File
@@ -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('拒绝授权')
}
})
},
}
})
+6
View File
@@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"lcb-msg": "/components/msg/index"
}
}
+16
View File
@@ -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>
+1
View File
@@ -0,0 +1 @@
@import "../../commons/css/common.wxss";
+86
View File
@@ -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
})
});
}
},
}
})
+6
View File
@@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"lcb-msg": "/components/msg/index"
}
}
+14
View File
@@ -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>
+1
View File
@@ -0,0 +1 @@
@import "../../commons/css/common.wxss";
+23
View File
@@ -0,0 +1,23 @@
// pages/components/footer/footer.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
+4
View File
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
+8
View File
@@ -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>
+5
View File
@@ -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;}
+21
View File
@@ -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: {
}
})
+6
View File
@@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"xxk-msg": "/components/msg/index"
}
}
+6
View File
@@ -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>
+1
View File
@@ -0,0 +1 @@
@import "../../commons/css/common.wxss";
+37
View File
@@ -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: {
}
})
+4
View File
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
+13
View File
@@ -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>
+9
View File
@@ -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;
}
+70
View File
@@ -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
})
}
}
})
+4
View File
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
+45
View File
@@ -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>
+144
View File
@@ -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
}
}
+96
View File
@@ -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'
})
}
}
})
+6
View File
@@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"xhb-searchBar": "/components/searchBar/index"
}
}
+30
View File
@@ -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>
+24
View File
@@ -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;
}
+35
View File
@@ -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)
}
}
})
+4
View File
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
+13
View File
@@ -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>
+33
View File
@@ -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;
}
+250
View File
@@ -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%;
}
File diff suppressed because one or more lines are too long
+121
View File
@@ -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
}
}
+75
View File
@@ -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
}
},
});
+5
View File
@@ -0,0 +1,5 @@
{
"usingComponents": {
"ec-canvas": "../../../ecCanvas/components/ec-canvas/ec-canvas"
}
}
+5
View File
@@ -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>
+17
View File
@@ -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%;
}
+71
View File
@@ -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,
})
});
}
},
})
+6
View File
@@ -0,0 +1,6 @@
{
"navigationBarTitleText": "客户建卡",
"usingComponents": {
}
}
+74
View File
@@ -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>
+1
View File
@@ -0,0 +1 @@
/* pages/customer/addCard/index.wxss */
+91
View File
@@ -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,
})
},
})
+3
View File
@@ -0,0 +1,3 @@
{
"usingComponents": {}
}
+141
View File
@@ -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>
+48
View File
@@ -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%;
}
+374
View File
@@ -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()
},
})
+7
View File
@@ -0,0 +1,7 @@
{
"navigationBarTitleText": "客户",
"enablePullDownRefresh": true,
"usingComponents": {
}
}
+202
View File
@@ -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>

Some files were not shown because too many files have changed in this diff Show More