Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
dev
/
marubi-wish-list-mp
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
1283d91e
authored
2019-08-05 00:38:48 +0800
by
simon
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
版本提交
1 parent
c7d81d9a
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
1702 additions
and
106 deletions
gulpfile.js
src/app.json
src/component/tips-nearby-store-comp/tips-nearby-store-comp.js
src/component/tips-nearby-store-comp/tips-nearby-store-comp.scss
src/component/tips-nearby-store-comp/tips-nearby-store-comp.wxml
src/component/tips-prize-comp/tips-prize-comp.js
src/const/custom-data.js
src/http/api.js
src/pages/prize-detail/prize-detail.js
src/pages/prize-detail/prize-detail.json
src/pages/prize-detail/prize-detail.scss
src/pages/prize-detail/prize-detail.wxml
src/pages/user-table/user-table.js
src/pages/user-table/user-table.scss
src/pages/user-table/user-table.wxml
src/pages/wish/wish.js
src/utils/qrcode.js
gulpfile.js
View file @
1283d91
...
...
@@ -132,7 +132,7 @@ function sassCompile() {
}))
.
pipe
(
replace
(
'.scss'
,
'.wxss'
))
// .pipe(replace('%ASSETS_IMG%/', res))
.
pipe
(
replace
(
'../../image/oss/'
,
res
))
// 自定义图片地址
//
.pipe(replace('../../image/oss/', res)) // 自定义图片地址
.
pipe
(
replace
(
'src/assets/images'
,
res
))
// 雪碧图CSS RUL 中的图片路径
.
pipe
(
gulp
.
dest
(
paths
.
dist
.
baseDir
))
}
...
...
@@ -231,7 +231,7 @@ var watchHandler = function (type, file) {
var
tmp
=
file
.
replace
(
'src/'
,
'dist/'
)
del
([
tmp
]);
}
else
{
copyWXML
();
//
copyWXML();
wxmlImgRewrite
();
}
}
...
...
src/app.json
View file @
1283d91
...
...
@@ -22,5 +22,10 @@
"navigationBarBackgroundColor"
:
"#fff"
,
"navigationBarTitleText"
:
"心愿单"
,
"navigationBarTextStyle"
:
"black"
},
"permission"
:
{
"scope.userLocation"
:
{
"desc"
:
"你的位置信息将用显示附近门店"
}
}
}
...
...
src/component/tips-nearby-store-comp/tips-nearby-store-comp.js
View file @
1283d91
import
{
getBindtapData
,
}
from
'../../utils/util'
;
let
app
=
getApp
();
Component
({
properties
:
{
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText
:
{
type
:
String
,
value
:
'default value'
,
},
wishInfo
:
{
type
:
Object
,
value
:
{},
},
location
:
{
type
:
Object
,
value
:
{},
},
//是否选择模式
selectedMode
:
{
type
:
Boolean
,
value
:
false
}
},
data
:
{
// 这里是一些组件内部数据
someData
:
{}
someData
:
{},
searchMode
:
1
,
// 查询模式 1.根据位置自动查询 2.省市区查询
provinceId
:
""
,
cityId
:
""
,
districtId
:
""
,
provinceList
:
[],
cityList
:
[],
districtList
:
[],
provinceIndex
:
-
1
,
cityIndex
:
-
1
,
districtIndex
:
-
1
,
addressList
:
[],
total
:
0
,
curAddress
:
null
},
methods
:
{
/**
* 请求门店地址
*/
queryShop
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
let
{
location
,
wishInfo
,
provinceId
,
cityId
,
districtId
,
}
=
this
.
data
;
app
.
post
({
url
:
app
.
api
.
storeQuery
,
data
:
{
couponId
:
wishInfo
.
couponId
,
latitude
:
location
.
latitude
,
longitude
:
location
.
longitude
,
provinceId
:
provinceId
,
cityId
:
cityId
,
districtId
:
districtId
,
page
:
1
,
size
:
100
,
}
}).
then
((
result
)
=>
{
this
.
setData
({
addressList
:
result
.
list
,
total
:
result
.
total
})
resolve
();
})
});
},
/**
* 选择地址 item
*/
onSelectHandler
(
evt
)
{
let
item
=
getBindtapData
(
evt
);
let
index
=
getBindtapData
(
evt
,
"index"
);
let
addressList
=
this
.
data
.
addressList
;
addressList
.
forEach
((
element
,
idx
)
=>
{
element
.
selected
=
index
==
idx
;
});
this
.
setData
({
addressList
:
addressList
,
curAddress
:
item
})
},
/**
* 提交门店
*/
onSubmitHandler
(
evt
)
{
let
curAddress
=
this
.
data
.
curAddress
;
if
(
!
curAddress
)
{
wx
.
showToast
({
title
:
"请选择门店"
,
icon
:
'none'
});
return
;
}
let
wishInfo
=
this
.
properties
.
wishInfo
;
app
.
post
({
url
:
app
.
api
.
wishbillStoreAppoint
,
data
:
{
instanceCode
:
wishInfo
.
instanceCode
,
storeCode
:
curAddress
.
storeCode
,
storeName
:
curAddress
.
storeName
,
storeAddress
:
curAddress
.
storeAddress
,
latitude
:
curAddress
.
latitude
,
longitude
:
curAddress
.
longitude
}
}).
then
((
result
)
=>
{
this
.
triggerEvent
(
'evtcomp'
,
{
name
:
"_evt_submit_store_complete"
})
});
},
/**
* 显示位置
* @param {*} e
*/
onShowLocHandler
(
evt
)
{
let
item
=
getBindtapData
(
evt
);
wx
.
openLocation
({
latitude
:
item
.
latitude
,
// 纬度,范围为-90~90,负数表示南纬
longitude
:
item
.
longitude
,
// 经度,范围为-180~180,负数表示西经
scale
:
18
,
// 缩放比例
name
:
item
.
storeName
,
// 位置名
address
:
item
.
storeAddress
,
// 地址的详细说明
success
:
function
(
res
)
{
// success
}
})
},
// 转换成手动模式
onSearchHandModeHandler
()
{
this
.
setData
({
searchMode
:
2
});
},
// 转换为自动模式
onSearchAutoModeHandler
()
{
this
.
setData
({
searchMode
:
1
,
provinceId
:
""
,
cityId
:
""
,
districtId
:
""
,
})
},
getProvince
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
app
.
post
({
url
:
app
.
api
.
provinceQuery
}).
then
((
result
)
=>
{
this
.
setData
({
provinceList
:
result
})
console
.
log
(
"getProvince result:"
,
result
);
})
});
},
getCity
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
app
.
post
({
url
:
app
.
api
.
cityQuery
,
data
:
{
parentId
:
this
.
data
.
provinceId
}
}).
then
((
result
)
=>
{
console
.
log
(
"getCity result:"
,
result
);
})
});
},
getDistrict
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
app
.
post
({
url
:
app
.
api
.
districtQuery
,
data
:
{
parentId
:
this
.
data
.
cityId
}
}).
then
((
result
)
=>
{
console
.
log
(
"getDistrict result:"
,
result
);
})
});
},
bindPickerChangeProvince
(
e
)
{
let
index
=
e
.
detail
.
value
;
this
.
setData
({
provinceIndex
:
index
,
provinceId
:
this
.
data
.
provinceList
[
index
].
id
,
cityList
:
[],
districtList
:
[],
})
// 选市
this
.
getCity
()
},
bindPickerChangeCity
(
e
)
{
let
index
=
e
.
detail
.
value
;
this
.
setData
({
cityIndex
:
index
,
cityId
:
this
.
data
.
cityList
[
index
].
id
,
districtList
:
[],
})
this
.
getDistrict
();
},
bindPickerChangeDistrict
(
e
)
{
let
index
=
e
.
detail
.
value
;
this
.
setData
({
districtIndex
:
index
,
districtId
:
this
.
data
.
districtList
[
index
].
id
,
})
},
// 这里是一个自定义方法
customMethod
()
{
this
.
triggerEvent
(
'evtcomp'
,
{
...
...
@@ -23,5 +242,9 @@ Component({
name
:
"_evt_hide_mask"
});
}
},
//
ready
()
{
this
.
getProvince
();
}
})
...
...
src/component/tips-nearby-store-comp/tips-nearby-store-comp.scss
View file @
1283d91
...
...
@@ -53,6 +53,10 @@ $contentWidth:690px;
padding
:
0
20px
;
margin-right
:
10px
;
.val
{
@include
ellipsis
(
1
);
}
.icon
{
width
:
30px
;
height
:
17px
;
...
...
@@ -155,6 +159,11 @@ $contentWidth:690px;
margin
:
0
auto
;
@include
cb
();
}
.disable
{
background
:
transparent
;
background-color
:
#d2d2d2
;
}
}
}
...
...
src/component/tips-nearby-store-comp/tips-nearby-store-comp.wxml
View file @
1283d91
<view class="comp-item">
<view class="cont">
<!-- 导航 -->
<view wx:if="{{
1>10
}}" class="nav nav1">
<view wx:if="{{
searchMode == 1
}}" class="nav nav1">
<view class="place">
您当前所在城市:
<span class="city">深圳市</span>
</view>
<view
class="btn">切换城市
</view>
<view
bindtap="onSearchHandModeHandler" data-data="1" class="btn">手动选择
</view>
</view>
<view wx:else class="nav nav2">
<view class="area">
<view class="area-item">
省
<!-- 省 -->
<picker bindchange="bindPickerChangeProvince" value="{{provinceIndex}}" range="{{provinceList}}" range-key="name">
<view bindtap="getProvince" class="area-item">
<span class="val">
{{provinceList[provinceIndex].name ? provinceList[provinceIndex].name : '省'}}
</span>
<image class="icon" mode="widthFix" src="../../image/oss/icon/icon-drow-down.png" />
</view>
</picker>
<!-- 市 -->
<picker bindchange="bindPickerChangeCity" value="{{cityIndex}}" range="{{cityList}}" range-key="name">
<view class="area-item">
市
<span class="val">{{cityList[cityIndex].name ? cityList[cityIndex].name : '市'}}</span>
<image class="icon" mode="widthFix" src="../../image/oss/icon/icon-drow-down.png" />
</view>
</picker>
<!-- 区 -->
<picker bindchange="bindPickerChangeDistrict" value="{{districtIndex}}" range="{{districtList}}" range-key="name">
<view class="area-item">
区
<span class="val">
{{districtList[districtIndex].name ? districtList[districtIndex].name : '区'}}
</span>
<image class="icon" mode="widthFix" src="../../image/oss/icon/icon-drow-down.png" />
</view>
</picker>
</view>
<view
class="btn">切换城市
</view>
<view
bindtap="onSearchAutoModeHandler" data-data="2" class="btn">自动选择
</view>
</view>
<!-- 门店列表 -->
<scroll-view scroll-y="{{true}}" class="pos">
<view class="pos-item">
<view wx:if="{{1>10}}" class="check">
<image class="icon" mode="widthFix" src="../../image/oss/icon/icon-check.png" />
</view>
<view class="info">
<view class="tit">
<view class="name">坂田天虹店</view>
<view class="distance">距您1.2公里</view>
</view>
<view class="address">地址:安徽省安庆市大观区集贤南路43号八佰伴购物中心一楼</view>
</view>
<view class="loc">
<image class="icon" mode="widthFix" src="../../image/oss/icon/icon-loc.png" />
<view class="txt">导航</view>
</view>
</view>
<view class="pos-item">
<view class="check">
<image class="icon" mode="widthFix" src="../../image/oss/icon/icon-check.png" />
<view bindtap="onSelectHandler" data-data="{{item}}" data-index="{{index}}" wx:for="{{addressList}}" wx:key="{{index}}" class="pos-item">
<view wx:if="{{selectedMode}}" class="check">
<image wx:if="{{item.selected}}" class="icon" mode="widthFix" src="../../image/oss/icon/icon-check.png" />
</view>
<view class="info">
<view class="tit">
<view class="name">
坂田天虹店
</view>
<view class="distance">距您
1.2公里
</view>
<view class="name">
{{item.storeName}}
</view>
<view class="distance">距您
{{item.distance}}
</view>
</view>
<view class="address">
地址:安徽省安庆市大观区集贤南路43号八佰伴购物中心一楼
</view>
<view class="address">
{{item.storeAddress}}
</view>
</view>
<view class="loc">
<view
bindtap="onShowLocHandler" data-data="{{item}}"
class="loc">
<image class="icon" mode="widthFix" src="../../image/oss/icon/icon-loc.png" />
<view class="txt">导航</view>
</view>
</view>
</scroll-view>
<!-- 按钮 -->
<view wx:if="{{1>10}}" class="btn-wrap">
<view bindtap="onSelectHandler" class="store-btn">选择门店</view>
<view wx:if="{{selectedMode}}" class="btn-wrap">
<view wx:if="{{curAddress}}" bindtap="onSubmitHandler" class="store-btn">选择门店</view>
<view wx:else class="store-btn disable">选择门店</view>
</view>
</view>
</view>
...
...
src/component/tips-prize-comp/tips-prize-comp.js
View file @
1283d91
...
...
@@ -6,26 +6,10 @@ Component({
type
:
String
,
value
:
'default value'
,
},
eleList
:
{
type
:
Object
,
value
:
[],
},
eleVal
:
{
type
:
Number
,
value
:
0
,
},
wishBillInfo
:
{
type
:
Object
,
value
:
{},
},
wishInfo
:
{
type
:
Object
,
value
:
{},
},
wishList
:
{
type
:
Object
,
value
:
[],
},
// 1正常(有库存) 2无库存
status
:
{
type
:
Number
,
...
...
@@ -49,19 +33,51 @@ Component({
name
:
"_evt_hide_mask"
});
},
// 自提 要带上参数
/**
* 提交礼品领取方式
*/
queryWishbillAcceptTypeSubmit
(
acceptType
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
let
wishInfo
=
this
.
properties
.
wishInfo
;
app
.
post
({
url
:
app
.
api
.
wishbillAcceptTypeSubmit
,
data
:
{
instanceCode
:
wishInfo
.
instanceCode
,
acceptType
:
acceptType
}
}).
then
((
result
)
=>
{
resolve
(
result
)
})
});
},
// 自提
toSelfLiftHandler
()
{
this
.
queryWishbillAcceptTypeSubmit
(
2
).
then
((
result
)
=>
{
console
.
log
(
"prize-self-result:"
,
result
);
let
wishInfo
=
this
.
properties
.
wishInfo
;
let
query
=
Object
.
assign
(
wishInfo
,
result
);
console
.
log
(
"prize-self-query:"
,
query
);
this
.
hideMask
();
app
.
router
.
push
({
path
:
"prizeDetail"
,
query
:
this
.
properties
.
wishInfo
query
:
query
})
})
},
// 邮寄
toUserTableHandler
()
{
this
.
queryWishbillAcceptTypeSubmit
(
1
).
then
((
result
)
=>
{
console
.
log
(
"prize-table-result:"
,
result
);
let
wishInfo
=
this
.
properties
.
wishInfo
;
let
query
=
Object
.
assign
(
wishInfo
,
result
);
console
.
log
(
"prize-table-query:"
,
query
);
this
.
hideMask
();
app
.
router
.
push
({
path
:
"userTable"
,
query
:
query
})
})
},
...
...
src/const/custom-data.js
View file @
1283d91
...
...
@@ -169,6 +169,199 @@ let productMap = {
}
/**
* @my-wish
* 点击领取心愿单奖品
*/
let
wishbillGiftAccept
=
{
"status"
:
1
,
"order"
:
{
"acceptType"
:
0
,
"instanceCode"
:
"162951b667a746188c83491bd5601164"
,
"prizeName"
:
"丸美弹力蛋白眼精华素10g+10g"
,
"prizePic"
:
""
,
"commodityNo"
:
"11059001"
},
"coupon"
:
null
}
/**
* @my-wish
* 点击单个心愿单奖品
*/
let
curWish
=
{
accessStatus
:
1
,
commodityNo
:
"11059001"
,
conditionElasticValue
:
5480
,
coupon
:
null
,
elasticValue
:
10000
,
initialElasticValue
:
33
,
instanceCode
:
"162951b667a746188c83491bd5601164"
,
name
:
"丸美弹力蛋白眼精华素10g+10g"
,
order
:
{
acceptType
:
0
,
instanceCode
:
"162951b667a746188c83491bd5601164"
,
prizeName
:
"丸美弹力蛋白眼精华素10g+10g"
,
prizePic
:
""
,
commodityNo
:
"11059001"
},
point
:
{
left
:
558
,
top
:
437
},
price
:
"548"
,
prizeDefineCode
:
"P000000000000000000000000000001"
,
prizeName
:
"丸美弹力蛋白眼精华素10g+10g"
,
prizePic
:
""
,
progress
:
100
,
progressLeft
:
169.00000000000003
,
sence
:
1
,
status
:
1
,
storeRemain
:
99
,
tag
:
3
,
tips
:
{
type
:
"top-left"
,
point
:
{
fixLeft
:
-
188
,
fixTop
:
-
314
}
}
}
// 读取心愿单奖品
let
wishbillGiftQuery
=
{
"status"
:
1
,
"order"
:
{
"coupon"
:
{
"couponId"
:
"20839"
,
"couponCode"
:
"RLLW18Q1"
,
"rule"
:
"RLLW18Q1"
,
"startDate"
:
1564912960000
,
"endDate"
:
1567526399000
,
"type"
:
4
,
"name"
:
"眼部护理体验券-7月24日"
,
"state"
:
0
},
"acceptType"
:
2
,
"instanceCode"
:
"0924988c7fb0437b99c31b97bd1f1d6c"
,
"storeCode"
:
""
,
"storeName"
:
""
,
"storeAddress"
:
""
,
"latitude"
:
0.0
,
"longitude"
:
0.0
,
"prizeName"
:
"丸美巧克力青春丝滑眼乳霜25g"
,
"orderSn"
:
"MW20190804180237100003"
,
"commodityNo"
:
"11039003"
},
"coupon"
:
null
}
/**
* @tips-prize-comp
* 自提数据
*/
let
prizeLiftQuery
=
{
"coupon"
:
{
"couponId"
:
"20839"
,
"couponCode"
:
"RLLW18Q1"
,
"rule"
:
"RLLW18Q1"
,
"startDate"
:
1564912960000
,
"endDate"
:
1567526399000
,
"type"
:
4
,
"name"
:
"眼部护理体验券-7月24日"
,
"state"
:
0
},
"acceptType"
:
2
,
"instanceCode"
:
"0924988c7fb0437b99c31b97bd1f1d6c"
,
"storeCode"
:
""
,
"storeName"
:
""
,
"storeAddress"
:
""
,
"latitude"
:
0.0
,
"longitude"
:
0.0
,
"prizeName"
:
"丸美巧克力青春丝滑眼乳霜25g"
,
"orderSn"
:
"MW20190804180237100003"
,
"commodityNo"
:
"11039003"
}
/**
* @tips-prize-comp
* 邮寄提交返回数据
*/
let
prizeTableQuery
=
{
address
:
""
,
associateMobile
:
""
,
associateName
:
""
,
city
:
""
,
commodityNo
:
"11059001"
,
district
:
""
,
instanceCode
:
"162951b667a746188c83491bd5601164"
,
logisticsCompany
:
""
,
logisticsSn
:
""
,
memberCode
:
"654b8d70164e4c1e83e1503d44f325db"
,
orderSn
:
"MW20190804152353100001"
,
prizeName
:
"丸美弹力蛋白眼精华素10g+10g"
,
prizePic
:
""
,
province
:
""
,
}
/**
* @tips-prize-comp
* 邮寄提交返回数据 合并
*/
let
prizeTableQueryAssign
=
{
accessStatus
:
2
,
address
:
""
,
associateMobile
:
""
,
associateName
:
""
,
city
:
""
,
commodityNo
:
"11059001"
,
conditionElasticValue
:
5480
,
coupon
:
null
,
district
:
""
,
elasticValue
:
10000
,
initialElasticValue
:
33
,
instanceCode
:
"162951b667a746188c83491bd5601164"
,
logisticsCompany
:
""
,
logisticsSn
:
""
,
memberCode
:
"654b8d70164e4c1e83e1503d44f325db"
,
name
:
"丸美弹力蛋白眼精华素10g+10g"
,
order
:
{
acceptType
:
0
,
instanceCode
:
"162951b667a746188c83491bd5601164"
,
prizeName
:
"丸美弹力蛋白眼精华素10g+10g"
,
prizePic
:
""
,
commodityNo
:
"11059001"
},
orderSn
:
"MW20190804152353100001"
,
point
:
{
left
:
558
,
top
:
437
},
price
:
"548"
,
prizeDefineCode
:
"P000000000000000000000000000001"
,
prizeName
:
"丸美弹力蛋白眼精华素10g+10g"
,
prizePic
:
""
,
progress
:
100
,
progressLeft
:
169.00000000000003
,
province
:
""
,
sence
:
1
,
status
:
1
,
storeRemain
:
98
,
tag
:
3
,
tips
:
{
type
:
"top-left"
,
point
:
{
fixLeft
:
-
188
,
fixTop
:
-
314
},
},
}
module
.
exports
=
{
productMap
:
productMap
productMap
:
productMap
,
prizeTableQueryAssign
:
prizeTableQueryAssign
,
prizeLiftQuery
:
prizeLiftQuery
,
wishbillGiftQuery
:
wishbillGiftQuery
}
...
...
src/http/api.js
View file @
1283d91
...
...
@@ -22,5 +22,10 @@ module.exports = {
wishbillAcceptTypeSubmit
:
'/warubiEyeCreamApi/app/wishbill/accept/type/submit'
,
// post 提交礼品领取方式
wishbillAddressSubmit
:
'/warubiEyeCreamApi/app/wishbill/address/submit'
,
// post 提交邮寄地址
wishbillStoreAppoint
:
'/warubiEyeCreamApi/app/wishbill/store/appoint'
,
// post 预约自提门店
provinceQuery
:
'/warubiEyeCreamApi/app/store/province'
,
// post 省
cityQuery
:
'/warubiEyeCreamApi/app/store/city'
,
// post 市
districtQuery
:
'/warubiEyeCreamApi/app/store/district'
,
// post 区
wxacodeGet
:
'/warubiEyeCreamApi/app/qrcode/create'
,
//
}
...
...
src/pages/prize-detail/prize-detail.js
View file @
1283d91
import
{
getBindtapData
wishbillGiftQuery
}
from
'../../const/custom-data'
;
import
{
getBindtapData
,
pxToRpx
}
from
'../../utils/util'
;
import
Date
from
'../../utils/date'
;
import
QR
from
'../../utils/qrcode'
let
app
=
getApp
();
Page
({
data
:
{
userInfo
:
{},
used
:
false
,
//优惠券已使用,另外的样式
couponInfo
:
{
"couponId"
:
"20839"
,
"couponCode"
:
"RLLL1IHG"
,
"rule"
:
"RLLL1IHG"
,
"startDate"
:
1564479217000
,
"endDate"
:
1567094399000
,
"type"
:
4
,
"name"
:
"眼部护理体验券-7月24日"
,
"state"
:
0
,
"endDateStr"
:
"19-08-29"
}
wishInfo
:
{},
couponInfo
:
{},
nearbyStoreVisible
:
false
,
qrImagePath
:
""
,
location
:
{},
},
onShareAppMessage
()
{},
onLoad
(
options
)
{
let
couponInfo
=
options
;
// let wishInfo = options;
let
wishInfo
=
wishbillGiftQuery
.
order
;
let
couponInfo
=
wishInfo
.
coupon
;
// 设置起止时间
couponInfo
.
startDateStr
=
new
Date
(
couponInfo
.
startDate
).
toString
(
"yyyy.MM.dd"
);
couponInfo
.
endDateStr
=
new
Date
(
couponInfo
.
endDate
).
toString
(
"yyyy.MM.dd"
);
// 判断是否使用
// 自提券 使用状态(0=未使用 1=已过期,2=已使用)
let
used
=
couponInfo
.
state
!=
0
;
// used = true;
// 设置数据
this
.
setData
({
couponInfo
:
couponInfo
wishInfo
:
wishInfo
,
couponInfo
:
couponInfo
,
used
:
used
})
console
.
log
(
"couponInfo:"
,
couponInfo
);
this
.
initData
();
},
initData
()
{
...
...
@@ -35,11 +50,124 @@ Page({
this
.
setData
({
userInfo
:
app
.
globalData
.
userInfo
})
// 设置二维码
let
couponInfo
=
this
.
data
.
couponInfo
;
let
qrSize
=
this
.
setCanvasSize
(
300
);
console
.
log
(
"couponInfo:"
,
couponInfo
);
let
codeContent
=
couponInfo
.
couponCode
||
''
;
this
.
createQrCode
(
codeContent
,
'qrcanvas'
,
qrSize
.
w
,
qrSize
.
h
);
})
},
/**
* 请求门店地址
*/
queryShop
()
{
this
.
selectComponent
(
"#nearbyStoreComp"
).
queryShop
().
then
((
result
)
=>
{
this
.
setData
({
nearbyStoreVisible
:
true
})
})
},
// 查看可用门店
onNearbyStoreHandler
(
evt
)
{
console
.
log
(
"onNearbyStoreHandler couponInfo:"
,
this
.
data
.
couponInfo
);
this
.
wxLocation
();
},
// 使用微信位置
wxLocation
()
{
let
_this
=
this
;
wx
.
getLocation
({
type
:
'wgs84'
,
success
(
res
)
{
_this
.
setData
({
location
:
res
})
_this
.
queryShop
();
},
fail
(
err
)
{
wx
.
getSetting
({
success
:
(
res
)
=>
{
if
(
!
res
.
authSetting
[
'scope.userLocation'
])
{
// 未授权
wx
.
showModal
({
title
:
'提示'
,
content
:
'小程序请求访问地理位置'
,
confirmText
:
'前往授权'
,
success
(
res
)
{
if
(
res
.
confirm
)
{
wx
.
openSetting
({
complete
()
{
//设置完后重拉一遍位置,拉不到就算了
wx
.
getLocation
({
type
:
'wgs84'
,
// 默认为 wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标
success
:
function
(
res
)
{
_this
.
setData
({
location
:
res
})
_this
.
queryShop
();
},
fail
:
function
()
{
_this
.
queryShop
();
}
})
}
})
}
else
if
(
res
.
cancel
)
{
// 模态窗取消
_this
.
queryShop
();
}
}
})
}
}
})
}
})
},
createQrCode
(
content
,
canvasId
,
cavW
,
cavH
)
{
//调用插件中的draw方法,绘制二维码图片
QR
.
api
.
draw
(
content
,
canvasId
,
cavW
,
cavH
);
this
.
canvasToTempImage
(
canvasId
);
},
//获取临时缓存图片路径,存入data中
canvasToTempImage
(
canvasId
)
{
let
that
=
this
;
wx
.
canvasToTempFilePath
({
canvasId
,
// 这里canvasId即之前创建的canvas-id
success
:
function
(
res
)
{
let
tempFilePath
=
res
.
tempFilePath
;
console
.
log
(
tempFilePath
);
that
.
setData
({
// 如果采用mpvue,即 this.imagePath = tempFilePath
qrImagePath
:
tempFilePath
,
});
},
fail
:
function
(
res
)
{
console
.
log
(
res
);
}
});
},
//适配不同屏幕大小的canvas
setCanvasSize
(
sz
)
{
var
size
=
{};
try
{
var
res
=
wx
.
getSystemInfoSync
();
var
scale
=
750
/
sz
;
//不同屏幕下canvas的适配比例;设计稿是750宽
var
width
=
res
.
windowWidth
/
scale
;
var
height
=
width
;
//canvas画布为正方形
size
.
w
=
width
;
size
.
h
=
height
;
}
catch
(
e
)
{
// Do something when catch error
console
.
log
(
"获取设备信息失败"
+
e
);
}
return
size
;
},
hideMask
()
{
this
.
setData
({
nearbyStoreVisible
:
false
})
},
// 子组件事件
evtcomp
(
evt
)
{
...
...
@@ -50,6 +178,18 @@ Page({
switch
(
name
)
{
case
"_evt_hide"
:
this
.
hideMask
();
break
;
// 提交完毕
case
"_evt_submit_store_complete"
:
// 刷新状态
this
.
hideMask
();
wx
.
showModal
({
content
:
'预约成功'
,
showCancel
:
false
,
success
(
res
)
{}
});
break
;
default
:
...
...
src/pages/prize-detail/prize-detail.json
View file @
1283d91
{
"navigationBarTitleText"
:
"卡券详情"
,
"usingComponents"
:
{
"use-notice-comp"
:
"../../component/use-notice-comp/use-notice-comp"
"use-notice-comp"
:
"../../component/use-notice-comp/use-notice-comp"
,
"tips-nearby-store-comp"
:
"../../component/tips-nearby-store-comp/tips-nearby-store-comp"
,
"van-popup"
:
"../../ui/vant-weapp/popup/index"
}
}
...
...
src/pages/prize-detail/prize-detail.scss
View file @
1283d91
...
...
@@ -2,6 +2,7 @@
@import
'../../assets/scss/utils'
;
.page
{
position
:
relative
;
padding-bottom
:
$pageBottom
;
font-weight
:
300
;
...
...
@@ -82,8 +83,12 @@
.qrcode
{
width
:
300px
;
height
:
300px
;
background-color
:
wheat
;
margin
:
0
auto
;
image
{
width
:
300px
;
height
:
300px
;
}
}
// 数字码
...
...
@@ -215,14 +220,20 @@
// 已使用
.used
{
$alp
:
0
.3
;
.qrcode
{
opacity
:
$alp
;
}
.info
{
opacity
:
$alp
;
}
// .qrcode {
// opacity: $alp;
// }
// .info {
// opacity: $alp;
// }
// .code{
// opacity: $alp;
// }
}
...
...
src/pages/prize-detail/prize-detail.wxml
View file @
1283d91
<canvas style="width: 300rpx;height: 300rpx;visibility: hidden;position:absolute;" canvas-id="qrcanvas" />
<view class="page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
...
...
@@ -26,10 +27,14 @@
</view>
</view>
<!-- 二维码 -->
<view class="qrcode"></view>
<view class="qrcode">
<image class="image" mode="widthFix" src="{{qrImagePath}}" />
</view>
<view class="code">{{couponInfo.couponCode}}</view>
<!-- 预约自提按钮 -->
<view wx:if="{{1<10}}" bindtap="onNearbyStoreHandler" class="reservation-btn">预约自提门店</view>
<view wx:if="{{1<10}}" bindtap="onNearbyStoreHandler" class="reservation-btn">
预约自提门店
</view>
<!-- 预约成功 -->
<view wx:else class="reservation-complete">
<view class="tips">您已成功预约,请在有效期内前往领取</view>
...
...
@@ -57,3 +62,6 @@
</view>
</view>
</view>
<van-popup show="{{ nearbyStoreVisible }}" position="bottom" bind:click-overlay="hideMask">
<tips-nearby-store-comp id="nearbyStoreComp" bind:evtcomp="evtcomp" wish-info="{{wishInfo}}" location="{{location}}" selectedMode="{{true}}"></tips-nearby-store-comp>
</van-popup>
...
...
src/pages/user-table/user-table.js
View file @
1283d91
import
{
prizeTableQueryAssign
}
from
'../../const/custom-data'
;
import
{
getBindtapData
,
checkMobile
,
}
from
'../../utils/util'
;
let
app
=
getApp
();
Page
({
data
:
{
...
...
@@ -5,17 +14,122 @@ Page({
receiverName
:
""
,
receiverMobile
:
""
,
receiverAddress
:
""
,
addressStr
:
""
,
// 省市区合并地址
region
:
[],
regionStr
:
""
,
prize
:
{}
prize
:
{},
wishInfo
:
{}
},
onShareAppMessage
()
{},
onLoad
(
options
)
{},
onLoad
(
options
)
{
// let wishInfo = options;
let
wishInfo
=
prizeTableQueryAssign
;
console
.
log
(
"wishInfo:"
,
wishInfo
);
this
.
setData
({
wishInfo
:
wishInfo
})
if
(
wishInfo
.
associateMobile
)
{
// 如果初始化回显,则要设置 表单信息
// 显示省市区
this
.
setData
({
receiverName
:
wishInfo
.
associateName
,
receiverMobile
:
wishInfo
.
associateMobile
,
receiverAddress
:
wishInfo
.
address
,
regionStr
:
wishInfo
.
province
+
wishInfo
.
city
+
wishInfo
.
district
,
})
this
.
setStatus
(
1
);
}
else
{
this
.
setStatus
(
0
);
}
},
/**
* 提交表单
* @param {*} evt
*/
onSubmitHandler
(
evt
)
{},
onSubmitHandler
(
evt
)
{
let
wishInfo
=
this
.
data
.
wishInfo
;
let
{
receiverName
,
receiverMobile
,
receiverAddress
,
region
,
}
=
this
.
data
;
let
receiverProvince
=
region
[
0
];
let
receiverCity
=
region
[
1
];
let
receiverDistrict
=
region
[
2
];
let
tips
=
""
;
if
(
!
receiverName
)
{
tips
=
"请输入姓名"
;
this
.
showTips
(
tips
);
return
;
}
if
(
!
receiverMobile
)
{
tips
=
"请输入手机号码"
;
this
.
showTips
(
tips
);
return
;
}
if
(
!
checkMobile
(
receiverMobile
))
{
tips
=
"请输入正确的手机号"
;
this
.
showTips
(
tips
);
return
;
}
if
(
!
receiverProvince
||
!
receiverCity
||
!
receiverDistrict
)
{
tips
=
"请选择区域"
;
this
.
showTips
(
tips
);
return
;
}
if
(
!
receiverAddress
)
{
tips
=
"请填写地址"
;
this
.
showTips
(
tips
);
return
;
}
let
data
=
{
instanceCode
:
wishInfo
.
instanceCode
,
associateName
:
receiverName
,
associateMobile
:
receiverMobile
,
province
:
receiverProvince
,
city
:
receiverCity
,
district
:
receiverDistrict
,
address
:
receiverAddress
,
}
console
.
log
(
"data:"
,
data
);
app
.
post
({
url
:
app
.
api
.
wishbillAddressSubmit
,
data
:
data
}).
then
((
result
)
=>
{
this
.
setStatus
(
1
);
})
},
// 设置显示状态 0:填写 1:回显
setStatus
(
tableIndex
)
{
if
(
tableIndex
==
1
)
{
// 回显,拼接完整地址
this
.
refreshFullAddress
();
}
this
.
setData
({
tableIndex
:
tableIndex
})
},
/**
* 配置完整地址
*/
refreshFullAddress
()
{
let
{
receiverAddress
,
regionStr
,
}
=
this
.
data
;
let
addressStr
=
regionStr
+
receiverAddress
;
this
.
setData
({
addressStr
:
addressStr
})
},
/**
* 返回心愿单页面
* @param {*} evt
...
...
@@ -26,17 +140,39 @@ Page({
path
:
"wish"
})
},
bindNameInput
(
e
)
{
this
.
setData
({
receiverName
:
e
.
detail
.
value
})
},
bindPhoneInput
(
e
)
{
this
.
setData
({
receiverMobile
:
e
.
detail
.
value
})
},
bindAddressInput
(
e
)
{
this
.
setData
({
receiverAddress
:
e
.
detail
.
value
})
},
bindRegionChange
(
e
)
{
let
region
=
e
.
detail
.
value
;
let
regionStr
=
""
;
if
(
region
.
length
>
0
)
{
regionStr
=
region
.
join
(
"
,
"
);
regionStr
=
region
.
join
(
""
);
}
this
.
setData
({
region
,
regionStr
})
},
showTips
(
tips
)
{
wx
.
showToast
({
title
:
tips
,
icon
:
'none'
})
},
// 子组件事件
evtcomp
(
evt
)
{
let
{
...
...
src/pages/user-table/user-table.scss
View file @
1283d91
...
...
@@ -165,13 +165,24 @@ $iptHeight:80px;
align-items
:
center
;
width
:
140px
;
@extend
.bb
;
padding
:
0
20px
;
padding
:
0
12px
;
font-size
:
26px
;
.icon
{
width
:
15px
;
height
:
9px
;
margin-left
:
8px
;
}
.val
{
// @extend
@include
ellipsis
(
1
);
}
.holder
{
}
}
.line
{
...
...
src/pages/user-table/user-table.wxml
View file @
1283d91
...
...
@@ -14,9 +14,9 @@
<image mode="widthFix" src="../../image/oss/user-table/user-table-c1.png" />
</view>
<view class="display">
<image
class="prod" mode="aspectFit" src="../../image/prize/prize-1
.png" />
<image
wx:if="{{wishInfo.tag}}" class="prod" mode="aspectFit" src="../../image/prize/prize-{{wishInfo.tag}}
.png" />
</view>
<view class="name">
丸美弹力蛋白凝时紧致乳
</view>
<view class="name">
{{wishInfo.prizeName}}
</view>
</view>
<!-- 表单 -->
<view class="table">
...
...
@@ -28,28 +28,31 @@
<view class="form">
<view class="ipt">
<view class="label">姓名</view>
<input class="input" placeholder="请输入" />
<input
value="{{receiverName}}" bindinput="bindNameInput"
class="input" placeholder="请输入" />
</view>
<view class="ipt">
<view class="label">电话</view>
<input class="input" placeholder="请输入" />
<input
value="{{receiverMobile}}" bindinput="bindPhoneInput"
class="input" placeholder="请输入" />
</view>
<view class="ipt">
<view class="label">区域</view>
<picker class="form-detail-item-label" mode="region" bindchange="bindRegionChange" value="{{region}}">
<view class="input area">
<view class="area-item area-item2">
省
<span class="val">{{region[0]?region[0]:'省'}}</span>
<!-- <span wx:if="{{!region[0]}}" class="holder">省</span> -->
<image class="icon" mode="widthFix" src="../../image/oss/icon/icon-drow-down.png" />
</view>
<view class="line"></view>
<view class="area-item area-item2">
市
<span class="val">{{region[1]?region[1]:'市'}}</span>
<!-- <span wx:if="{{!region[1]}}" class="holder">市</span> -->
<image class="icon" mode="widthFix" src="../../image/oss/icon/icon-drow-down.png" />
</view>
<view class="line"></view>
<view class="area-item area-item2">
区
<span class="val">{{region[2]?region[2]:'区'}}</span>
<!-- <span wx:if="{{!region[2]}}" class="holder">区</span> -->
<image class="icon" mode="widthFix" src="../../image/oss/icon/icon-drow-down.png" />
</view>
</view>
...
...
@@ -57,7 +60,7 @@
</view>
<view class="ipt ipt2">
<view class="label">地址</view>
<textarea class="input textarea" placeholder="请输入"></textarea>
<textarea
value="{{receiverAddress}}" bindinput="bindAddressInput"
class="input textarea" placeholder="请输入"></textarea>
</view>
</view>
<view bindtap="onSubmitHandler" class="submit-btn">确认提交</view>
...
...
@@ -68,16 +71,16 @@
<view class="tips">*感谢您提交的地址,我们将尽快为您送出以上礼品</view>
<view class="form">
<view class="form-item">
<view class="label">
姓名
</view>
<view class="label">
{{wishInfo.associateName}}
</view>
<view class="val">林小美</view>
</view>
<view class="form-item">
<view class="label">电话</view>
<view class="val">
18812345678
</view>
<view class="val">
{{wishInfo.associateMobile}}
</view>
</view>
<view class="form-item">
<view class="label">地址</view>
<view class="val">
广州市天河区珠江新城花城大道路xx广州市天河区珠江新城花城大道路xx广州市天河区珠江新城花城大道路xx
</view>
<view class="val">
{{regionStr}}{{wishInfo.addressStr}}
</view>
</view>
</view>
<view bindtap="onWishHandler" class="submit-btn">返回首页</view>
...
...
src/pages/wish/wish.js
View file @
1283d91
...
...
@@ -16,7 +16,18 @@ Page({
wishInfo
:
{},
wishList
:
[],
helperInfo
:
{},
curWish
:
{},
// curWish: {},
curWish
:
{
"status"
:
1
,
"order"
:
{
"acceptType"
:
0
,
"instanceCode"
:
"162951b667a746188c83491bd5601164"
,
"prizeName"
:
"丸美弹力蛋白眼精华素10g+10g"
,
"prizePic"
:
""
,
"commodityNo"
:
"11059001"
},
"coupon"
:
null
},
status
:
1
,
// 1正常(有库存) 2无库存
},
onShareAppMessage
()
{},
...
...
@@ -38,28 +49,64 @@ Page({
onGetGiftHandler
(
evt
)
{
let
curData
=
getBindtapData
(
evt
);
console
.
log
(
"curData:"
,
curData
);
this
.
setData
({
curWish
:
curData
,
tipsPirzeVisible
:
true
,
})
return
;
app
.
poster
({
app
.
post
({
url
:
app
.
api
.
wishbillGiftAccept
,
data
:
curData
data
:
{
instanceCode
:
curData
.
instanceCode
}
}).
then
((
result
)
=>
{
// let curData
curData
=
Object
.
assign
(
curData
,
result
);
this
.
setData
({
curWish
:
curData
,
tipsPirzeVisible
:
true
,
status
:
curData
.
status
})
});
},
/**
* 查看我的奖品
* 点击领取
*/
onCheckGiftHandler
(
evt
)
{
let
curData
=
getBindtapData
(
evt
);
console
.
log
(
"curData:"
,
curData
);
// console.log("curData:", curData);
app
.
post
({
url
:
app
.
api
.
wishbillGiftQuery
,
data
:
{
instanceCode
:
curData
.
instanceCode
}
}).
then
((
result
)
=>
{
curData
=
Object
.
assign
(
curData
,
result
);
console
.
log
(
"curData 222:"
,
curData
);
this
.
setData
({
curWish
:
curData
,
status
:
curData
.
status
})
// 领取状态
// 领取类型:0=未提交;1=邮寄(填写邮寄信息);2=自提(填门店预约信息)
let
acceptType
=
curData
.
order
.
acceptType
;
console
.
log
(
"acceptType:"
,
acceptType
);
if
(
acceptType
==
0
)
{
// 未提交,显示领取选择
this
.
setData
({
tipsPirzeVisible
:
true
,
})
}
else
if
(
acceptType
==
1
)
{
// 已经选择邮寄
// 判断是否已经填写邮寄信息
app
.
router
.
push
({
path
:
"userTable"
})
}
else
if
(
acceptType
==
2
)
{
// 已经选择自提
app
.
router
.
push
({
path
:
"prizeDetail"
})
}
// 查看是否已经预约
})
},
// 显示规则页面
onShowRuleHandler
()
{
...
...
src/utils/qrcode.js
0 → 100755
View file @
1283d91
!
(
function
()
{
// alignment pattern
var
adelta
=
[
0
,
11
,
15
,
19
,
23
,
27
,
31
,
16
,
18
,
20
,
22
,
24
,
26
,
28
,
20
,
22
,
24
,
24
,
26
,
28
,
28
,
22
,
24
,
24
,
26
,
26
,
28
,
28
,
24
,
24
,
26
,
26
,
26
,
28
,
28
,
24
,
26
,
26
,
26
,
28
,
28
];
// version block
var
vpat
=
[
0xc94
,
0x5bc
,
0xa99
,
0x4d3
,
0xbf6
,
0x762
,
0x847
,
0x60d
,
0x928
,
0xb78
,
0x45d
,
0xa17
,
0x532
,
0x9a6
,
0x683
,
0x8c9
,
0x7ec
,
0xec4
,
0x1e1
,
0xfab
,
0x08e
,
0xc1a
,
0x33f
,
0xd75
,
0x250
,
0x9d5
,
0x6f0
,
0x8ba
,
0x79f
,
0xb0b
,
0x42e
,
0xa64
,
0x541
,
0xc69
];
// final format bits with mask: level << 3 | mask
var
fmtword
=
[
0x77c4
,
0x72f3
,
0x7daa
,
0x789d
,
0x662f
,
0x6318
,
0x6c41
,
0x6976
,
//L
0x5412
,
0x5125
,
0x5e7c
,
0x5b4b
,
0x45f9
,
0x40ce
,
0x4f97
,
0x4aa0
,
//M
0x355f
,
0x3068
,
0x3f31
,
0x3a06
,
0x24b4
,
0x2183
,
0x2eda
,
0x2bed
,
//Q
0x1689
,
0x13be
,
0x1ce7
,
0x19d0
,
0x0762
,
0x0255
,
0x0d0c
,
0x083b
//H
];
// 4 per version: number of blocks 1,2; data width; ecc width
var
eccblocks
=
[
1
,
0
,
19
,
7
,
1
,
0
,
16
,
10
,
1
,
0
,
13
,
13
,
1
,
0
,
9
,
17
,
1
,
0
,
34
,
10
,
1
,
0
,
28
,
16
,
1
,
0
,
22
,
22
,
1
,
0
,
16
,
28
,
1
,
0
,
55
,
15
,
1
,
0
,
44
,
26
,
2
,
0
,
17
,
18
,
2
,
0
,
13
,
22
,
1
,
0
,
80
,
20
,
2
,
0
,
32
,
18
,
2
,
0
,
24
,
26
,
4
,
0
,
9
,
16
,
1
,
0
,
108
,
26
,
2
,
0
,
43
,
24
,
2
,
2
,
15
,
18
,
2
,
2
,
11
,
22
,
2
,
0
,
68
,
18
,
4
,
0
,
27
,
16
,
4
,
0
,
19
,
24
,
4
,
0
,
15
,
28
,
2
,
0
,
78
,
20
,
4
,
0
,
31
,
18
,
2
,
4
,
14
,
18
,
4
,
1
,
13
,
26
,
2
,
0
,
97
,
24
,
2
,
2
,
38
,
22
,
4
,
2
,
18
,
22
,
4
,
2
,
14
,
26
,
2
,
0
,
116
,
30
,
3
,
2
,
36
,
22
,
4
,
4
,
16
,
20
,
4
,
4
,
12
,
24
,
2
,
2
,
68
,
18
,
4
,
1
,
43
,
26
,
6
,
2
,
19
,
24
,
6
,
2
,
15
,
28
,
4
,
0
,
81
,
20
,
1
,
4
,
50
,
30
,
4
,
4
,
22
,
28
,
3
,
8
,
12
,
24
,
2
,
2
,
92
,
24
,
6
,
2
,
36
,
22
,
4
,
6
,
20
,
26
,
7
,
4
,
14
,
28
,
4
,
0
,
107
,
26
,
8
,
1
,
37
,
22
,
8
,
4
,
20
,
24
,
12
,
4
,
11
,
22
,
3
,
1
,
115
,
30
,
4
,
5
,
40
,
24
,
11
,
5
,
16
,
20
,
11
,
5
,
12
,
24
,
5
,
1
,
87
,
22
,
5
,
5
,
41
,
24
,
5
,
7
,
24
,
30
,
11
,
7
,
12
,
24
,
5
,
1
,
98
,
24
,
7
,
3
,
45
,
28
,
15
,
2
,
19
,
24
,
3
,
13
,
15
,
30
,
1
,
5
,
107
,
28
,
10
,
1
,
46
,
28
,
1
,
15
,
22
,
28
,
2
,
17
,
14
,
28
,
5
,
1
,
120
,
30
,
9
,
4
,
43
,
26
,
17
,
1
,
22
,
28
,
2
,
19
,
14
,
28
,
3
,
4
,
113
,
28
,
3
,
11
,
44
,
26
,
17
,
4
,
21
,
26
,
9
,
16
,
13
,
26
,
3
,
5
,
107
,
28
,
3
,
13
,
41
,
26
,
15
,
5
,
24
,
30
,
15
,
10
,
15
,
28
,
4
,
4
,
116
,
28
,
17
,
0
,
42
,
26
,
17
,
6
,
22
,
28
,
19
,
6
,
16
,
30
,
2
,
7
,
111
,
28
,
17
,
0
,
46
,
28
,
7
,
16
,
24
,
30
,
34
,
0
,
13
,
24
,
4
,
5
,
121
,
30
,
4
,
14
,
47
,
28
,
11
,
14
,
24
,
30
,
16
,
14
,
15
,
30
,
6
,
4
,
117
,
30
,
6
,
14
,
45
,
28
,
11
,
16
,
24
,
30
,
30
,
2
,
16
,
30
,
8
,
4
,
106
,
26
,
8
,
13
,
47
,
28
,
7
,
22
,
24
,
30
,
22
,
13
,
15
,
30
,
10
,
2
,
114
,
28
,
19
,
4
,
46
,
28
,
28
,
6
,
22
,
28
,
33
,
4
,
16
,
30
,
8
,
4
,
122
,
30
,
22
,
3
,
45
,
28
,
8
,
26
,
23
,
30
,
12
,
28
,
15
,
30
,
3
,
10
,
117
,
30
,
3
,
23
,
45
,
28
,
4
,
31
,
24
,
30
,
11
,
31
,
15
,
30
,
7
,
7
,
116
,
30
,
21
,
7
,
45
,
28
,
1
,
37
,
23
,
30
,
19
,
26
,
15
,
30
,
5
,
10
,
115
,
30
,
19
,
10
,
47
,
28
,
15
,
25
,
24
,
30
,
23
,
25
,
15
,
30
,
13
,
3
,
115
,
30
,
2
,
29
,
46
,
28
,
42
,
1
,
24
,
30
,
23
,
28
,
15
,
30
,
17
,
0
,
115
,
30
,
10
,
23
,
46
,
28
,
10
,
35
,
24
,
30
,
19
,
35
,
15
,
30
,
17
,
1
,
115
,
30
,
14
,
21
,
46
,
28
,
29
,
19
,
24
,
30
,
11
,
46
,
15
,
30
,
13
,
6
,
115
,
30
,
14
,
23
,
46
,
28
,
44
,
7
,
24
,
30
,
59
,
1
,
16
,
30
,
12
,
7
,
121
,
30
,
12
,
26
,
47
,
28
,
39
,
14
,
24
,
30
,
22
,
41
,
15
,
30
,
6
,
14
,
121
,
30
,
6
,
34
,
47
,
28
,
46
,
10
,
24
,
30
,
2
,
64
,
15
,
30
,
17
,
4
,
122
,
30
,
29
,
14
,
46
,
28
,
49
,
10
,
24
,
30
,
24
,
46
,
15
,
30
,
4
,
18
,
122
,
30
,
13
,
32
,
46
,
28
,
48
,
14
,
24
,
30
,
42
,
32
,
15
,
30
,
20
,
4
,
117
,
30
,
40
,
7
,
47
,
28
,
43
,
22
,
24
,
30
,
10
,
67
,
15
,
30
,
19
,
6
,
118
,
30
,
18
,
31
,
47
,
28
,
34
,
34
,
24
,
30
,
20
,
61
,
15
,
30
];
// Galois field log table
var
glog
=
[
0xff
,
0x00
,
0x01
,
0x19
,
0x02
,
0x32
,
0x1a
,
0xc6
,
0x03
,
0xdf
,
0x33
,
0xee
,
0x1b
,
0x68
,
0xc7
,
0x4b
,
0x04
,
0x64
,
0xe0
,
0x0e
,
0x34
,
0x8d
,
0xef
,
0x81
,
0x1c
,
0xc1
,
0x69
,
0xf8
,
0xc8
,
0x08
,
0x4c
,
0x71
,
0x05
,
0x8a
,
0x65
,
0x2f
,
0xe1
,
0x24
,
0x0f
,
0x21
,
0x35
,
0x93
,
0x8e
,
0xda
,
0xf0
,
0x12
,
0x82
,
0x45
,
0x1d
,
0xb5
,
0xc2
,
0x7d
,
0x6a
,
0x27
,
0xf9
,
0xb9
,
0xc9
,
0x9a
,
0x09
,
0x78
,
0x4d
,
0xe4
,
0x72
,
0xa6
,
0x06
,
0xbf
,
0x8b
,
0x62
,
0x66
,
0xdd
,
0x30
,
0xfd
,
0xe2
,
0x98
,
0x25
,
0xb3
,
0x10
,
0x91
,
0x22
,
0x88
,
0x36
,
0xd0
,
0x94
,
0xce
,
0x8f
,
0x96
,
0xdb
,
0xbd
,
0xf1
,
0xd2
,
0x13
,
0x5c
,
0x83
,
0x38
,
0x46
,
0x40
,
0x1e
,
0x42
,
0xb6
,
0xa3
,
0xc3
,
0x48
,
0x7e
,
0x6e
,
0x6b
,
0x3a
,
0x28
,
0x54
,
0xfa
,
0x85
,
0xba
,
0x3d
,
0xca
,
0x5e
,
0x9b
,
0x9f
,
0x0a
,
0x15
,
0x79
,
0x2b
,
0x4e
,
0xd4
,
0xe5
,
0xac
,
0x73
,
0xf3
,
0xa7
,
0x57
,
0x07
,
0x70
,
0xc0
,
0xf7
,
0x8c
,
0x80
,
0x63
,
0x0d
,
0x67
,
0x4a
,
0xde
,
0xed
,
0x31
,
0xc5
,
0xfe
,
0x18
,
0xe3
,
0xa5
,
0x99
,
0x77
,
0x26
,
0xb8
,
0xb4
,
0x7c
,
0x11
,
0x44
,
0x92
,
0xd9
,
0x23
,
0x20
,
0x89
,
0x2e
,
0x37
,
0x3f
,
0xd1
,
0x5b
,
0x95
,
0xbc
,
0xcf
,
0xcd
,
0x90
,
0x87
,
0x97
,
0xb2
,
0xdc
,
0xfc
,
0xbe
,
0x61
,
0xf2
,
0x56
,
0xd3
,
0xab
,
0x14
,
0x2a
,
0x5d
,
0x9e
,
0x84
,
0x3c
,
0x39
,
0x53
,
0x47
,
0x6d
,
0x41
,
0xa2
,
0x1f
,
0x2d
,
0x43
,
0xd8
,
0xb7
,
0x7b
,
0xa4
,
0x76
,
0xc4
,
0x17
,
0x49
,
0xec
,
0x7f
,
0x0c
,
0x6f
,
0xf6
,
0x6c
,
0xa1
,
0x3b
,
0x52
,
0x29
,
0x9d
,
0x55
,
0xaa
,
0xfb
,
0x60
,
0x86
,
0xb1
,
0xbb
,
0xcc
,
0x3e
,
0x5a
,
0xcb
,
0x59
,
0x5f
,
0xb0
,
0x9c
,
0xa9
,
0xa0
,
0x51
,
0x0b
,
0xf5
,
0x16
,
0xeb
,
0x7a
,
0x75
,
0x2c
,
0xd7
,
0x4f
,
0xae
,
0xd5
,
0xe9
,
0xe6
,
0xe7
,
0xad
,
0xe8
,
0x74
,
0xd6
,
0xf4
,
0xea
,
0xa8
,
0x50
,
0x58
,
0xaf
];
// Galios field exponent table
var
gexp
=
[
0x01
,
0x02
,
0x04
,
0x08
,
0x10
,
0x20
,
0x40
,
0x80
,
0x1d
,
0x3a
,
0x74
,
0xe8
,
0xcd
,
0x87
,
0x13
,
0x26
,
0x4c
,
0x98
,
0x2d
,
0x5a
,
0xb4
,
0x75
,
0xea
,
0xc9
,
0x8f
,
0x03
,
0x06
,
0x0c
,
0x18
,
0x30
,
0x60
,
0xc0
,
0x9d
,
0x27
,
0x4e
,
0x9c
,
0x25
,
0x4a
,
0x94
,
0x35
,
0x6a
,
0xd4
,
0xb5
,
0x77
,
0xee
,
0xc1
,
0x9f
,
0x23
,
0x46
,
0x8c
,
0x05
,
0x0a
,
0x14
,
0x28
,
0x50
,
0xa0
,
0x5d
,
0xba
,
0x69
,
0xd2
,
0xb9
,
0x6f
,
0xde
,
0xa1
,
0x5f
,
0xbe
,
0x61
,
0xc2
,
0x99
,
0x2f
,
0x5e
,
0xbc
,
0x65
,
0xca
,
0x89
,
0x0f
,
0x1e
,
0x3c
,
0x78
,
0xf0
,
0xfd
,
0xe7
,
0xd3
,
0xbb
,
0x6b
,
0xd6
,
0xb1
,
0x7f
,
0xfe
,
0xe1
,
0xdf
,
0xa3
,
0x5b
,
0xb6
,
0x71
,
0xe2
,
0xd9
,
0xaf
,
0x43
,
0x86
,
0x11
,
0x22
,
0x44
,
0x88
,
0x0d
,
0x1a
,
0x34
,
0x68
,
0xd0
,
0xbd
,
0x67
,
0xce
,
0x81
,
0x1f
,
0x3e
,
0x7c
,
0xf8
,
0xed
,
0xc7
,
0x93
,
0x3b
,
0x76
,
0xec
,
0xc5
,
0x97
,
0x33
,
0x66
,
0xcc
,
0x85
,
0x17
,
0x2e
,
0x5c
,
0xb8
,
0x6d
,
0xda
,
0xa9
,
0x4f
,
0x9e
,
0x21
,
0x42
,
0x84
,
0x15
,
0x2a
,
0x54
,
0xa8
,
0x4d
,
0x9a
,
0x29
,
0x52
,
0xa4
,
0x55
,
0xaa
,
0x49
,
0x92
,
0x39
,
0x72
,
0xe4
,
0xd5
,
0xb7
,
0x73
,
0xe6
,
0xd1
,
0xbf
,
0x63
,
0xc6
,
0x91
,
0x3f
,
0x7e
,
0xfc
,
0xe5
,
0xd7
,
0xb3
,
0x7b
,
0xf6
,
0xf1
,
0xff
,
0xe3
,
0xdb
,
0xab
,
0x4b
,
0x96
,
0x31
,
0x62
,
0xc4
,
0x95
,
0x37
,
0x6e
,
0xdc
,
0xa5
,
0x57
,
0xae
,
0x41
,
0x82
,
0x19
,
0x32
,
0x64
,
0xc8
,
0x8d
,
0x07
,
0x0e
,
0x1c
,
0x38
,
0x70
,
0xe0
,
0xdd
,
0xa7
,
0x53
,
0xa6
,
0x51
,
0xa2
,
0x59
,
0xb2
,
0x79
,
0xf2
,
0xf9
,
0xef
,
0xc3
,
0x9b
,
0x2b
,
0x56
,
0xac
,
0x45
,
0x8a
,
0x09
,
0x12
,
0x24
,
0x48
,
0x90
,
0x3d
,
0x7a
,
0xf4
,
0xf5
,
0xf7
,
0xf3
,
0xfb
,
0xeb
,
0xcb
,
0x8b
,
0x0b
,
0x16
,
0x2c
,
0x58
,
0xb0
,
0x7d
,
0xfa
,
0xe9
,
0xcf
,
0x83
,
0x1b
,
0x36
,
0x6c
,
0xd8
,
0xad
,
0x47
,
0x8e
,
0x00
];
// Working buffers:
// data input and ecc append, image working buffer, fixed part of image, run lengths for badness
var
strinbuf
=
[],
eccbuf
=
[],
qrframe
=
[],
framask
=
[],
rlens
=
[];
// Control values - width is based on version, last 4 are from table.
var
version
,
width
,
neccblk1
,
neccblk2
,
datablkw
,
eccblkwid
;
var
ecclevel
=
2
;
// set bit to indicate cell in qrframe is immutable. symmetric around diagonal
function
setmask
(
x
,
y
)
{
var
bt
;
if
(
x
>
y
)
{
bt
=
x
;
x
=
y
;
y
=
bt
;
}
// y*y = 1+3+5...
bt
=
y
;
bt
*=
y
;
bt
+=
y
;
bt
>>=
1
;
bt
+=
x
;
framask
[
bt
]
=
1
;
}
// enter alignment pattern - black to qrframe, white to mask (later black frame merged to mask)
function
putalign
(
x
,
y
)
{
var
j
;
qrframe
[
x
+
width
*
y
]
=
1
;
for
(
j
=
-
2
;
j
<
2
;
j
++
)
{
qrframe
[(
x
+
j
)
+
width
*
(
y
-
2
)]
=
1
;
qrframe
[(
x
-
2
)
+
width
*
(
y
+
j
+
1
)]
=
1
;
qrframe
[(
x
+
2
)
+
width
*
(
y
+
j
)]
=
1
;
qrframe
[(
x
+
j
+
1
)
+
width
*
(
y
+
2
)]
=
1
;
}
for
(
j
=
0
;
j
<
2
;
j
++
)
{
setmask
(
x
-
1
,
y
+
j
);
setmask
(
x
+
1
,
y
-
j
);
setmask
(
x
-
j
,
y
-
1
);
setmask
(
x
+
j
,
y
+
1
);
}
}
//========================================================================
// Reed Solomon error correction
// exponentiation mod N
function
modnn
(
x
)
{
while
(
x
>=
255
)
{
x
-=
255
;
x
=
(
x
>>
8
)
+
(
x
&
255
);
}
return
x
;
}
var
genpoly
=
[];
// Calculate and append ECC data to data block. Block is in strinbuf, indexes to buffers given.
function
appendrs
(
data
,
dlen
,
ecbuf
,
eclen
)
{
var
i
,
j
,
fb
;
for
(
i
=
0
;
i
<
eclen
;
i
++
)
strinbuf
[
ecbuf
+
i
]
=
0
;
for
(
i
=
0
;
i
<
dlen
;
i
++
)
{
fb
=
glog
[
strinbuf
[
data
+
i
]
^
strinbuf
[
ecbuf
]];
if
(
fb
!=
255
)
/* fb term is non-zero */
for
(
j
=
1
;
j
<
eclen
;
j
++
)
strinbuf
[
ecbuf
+
j
-
1
]
=
strinbuf
[
ecbuf
+
j
]
^
gexp
[
modnn
(
fb
+
genpoly
[
eclen
-
j
])];
else
for
(
j
=
ecbuf
;
j
<
ecbuf
+
eclen
;
j
++
)
strinbuf
[
j
]
=
strinbuf
[
j
+
1
];
strinbuf
[
ecbuf
+
eclen
-
1
]
=
fb
==
255
?
0
:
gexp
[
modnn
(
fb
+
genpoly
[
0
])];
}
}
//========================================================================
// Frame data insert following the path rules
// check mask - since symmetrical use half.
function
ismasked
(
x
,
y
)
{
var
bt
;
if
(
x
>
y
)
{
bt
=
x
;
x
=
y
;
y
=
bt
;
}
bt
=
y
;
bt
+=
y
*
y
;
bt
>>=
1
;
bt
+=
x
;
return
framask
[
bt
];
}
//========================================================================
// Apply the selected mask out of the 8.
function
applymask
(
m
)
{
var
x
,
y
,
r3x
,
r3y
;
switch
(
m
)
{
case
0
:
for
(
y
=
0
;
y
<
width
;
y
++
)
for
(
x
=
0
;
x
<
width
;
x
++
)
if
(
!
((
x
+
y
)
&
1
)
&&
!
ismasked
(
x
,
y
))
qrframe
[
x
+
y
*
width
]
^=
1
;
break
;
case
1
:
for
(
y
=
0
;
y
<
width
;
y
++
)
for
(
x
=
0
;
x
<
width
;
x
++
)
if
(
!
(
y
&
1
)
&&
!
ismasked
(
x
,
y
))
qrframe
[
x
+
y
*
width
]
^=
1
;
break
;
case
2
:
for
(
y
=
0
;
y
<
width
;
y
++
)
for
(
r3x
=
0
,
x
=
0
;
x
<
width
;
x
++
,
r3x
++
)
{
if
(
r3x
==
3
)
r3x
=
0
;
if
(
!
r3x
&&
!
ismasked
(
x
,
y
))
qrframe
[
x
+
y
*
width
]
^=
1
;
}
break
;
case
3
:
for
(
r3y
=
0
,
y
=
0
;
y
<
width
;
y
++
,
r3y
++
)
{
if
(
r3y
==
3
)
r3y
=
0
;
for
(
r3x
=
r3y
,
x
=
0
;
x
<
width
;
x
++
,
r3x
++
)
{
if
(
r3x
==
3
)
r3x
=
0
;
if
(
!
r3x
&&
!
ismasked
(
x
,
y
))
qrframe
[
x
+
y
*
width
]
^=
1
;
}
}
break
;
case
4
:
for
(
y
=
0
;
y
<
width
;
y
++
)
for
(
r3x
=
0
,
r3y
=
((
y
>>
1
)
&
1
),
x
=
0
;
x
<
width
;
x
++
,
r3x
++
)
{
if
(
r3x
==
3
)
{
r3x
=
0
;
r3y
=
!
r3y
;
}
if
(
!
r3y
&&
!
ismasked
(
x
,
y
))
qrframe
[
x
+
y
*
width
]
^=
1
;
}
break
;
case
5
:
for
(
r3y
=
0
,
y
=
0
;
y
<
width
;
y
++
,
r3y
++
)
{
if
(
r3y
==
3
)
r3y
=
0
;
for
(
r3x
=
0
,
x
=
0
;
x
<
width
;
x
++
,
r3x
++
)
{
if
(
r3x
==
3
)
r3x
=
0
;
if
(
!
((
x
&
y
&
1
)
+
!
(
!
r3x
|
!
r3y
))
&&
!
ismasked
(
x
,
y
))
qrframe
[
x
+
y
*
width
]
^=
1
;
}
}
break
;
case
6
:
for
(
r3y
=
0
,
y
=
0
;
y
<
width
;
y
++
,
r3y
++
)
{
if
(
r3y
==
3
)
r3y
=
0
;
for
(
r3x
=
0
,
x
=
0
;
x
<
width
;
x
++
,
r3x
++
)
{
if
(
r3x
==
3
)
r3x
=
0
;
if
(
!
(((
x
&
y
&
1
)
+
(
r3x
&&
(
r3x
==
r3y
)))
&
1
)
&&
!
ismasked
(
x
,
y
))
qrframe
[
x
+
y
*
width
]
^=
1
;
}
}
break
;
case
7
:
for
(
r3y
=
0
,
y
=
0
;
y
<
width
;
y
++
,
r3y
++
)
{
if
(
r3y
==
3
)
r3y
=
0
;
for
(
r3x
=
0
,
x
=
0
;
x
<
width
;
x
++
,
r3x
++
)
{
if
(
r3x
==
3
)
r3x
=
0
;
if
(
!
(((
r3x
&&
(
r3x
==
r3y
))
+
((
x
+
y
)
&
1
))
&
1
)
&&
!
ismasked
(
x
,
y
))
qrframe
[
x
+
y
*
width
]
^=
1
;
}
}
break
;
}
return
;
}
// Badness coefficients.
var
N1
=
3
,
N2
=
3
,
N3
=
40
,
N4
=
10
;
// Using the table of the length of each run, calculate the amount of bad image
// - long runs or those that look like finders; called twice, once each for X and Y
function
badruns
(
length
)
{
var
i
;
var
runsbad
=
0
;
for
(
i
=
0
;
i
<=
length
;
i
++
)
if
(
rlens
[
i
]
>=
5
)
runsbad
+=
N1
+
rlens
[
i
]
-
5
;
// BwBBBwB as in finder
for
(
i
=
3
;
i
<
length
-
1
;
i
+=
2
)
if
(
rlens
[
i
-
2
]
==
rlens
[
i
+
2
]
&&
rlens
[
i
+
2
]
==
rlens
[
i
-
1
]
&&
rlens
[
i
-
1
]
==
rlens
[
i
+
1
]
&&
rlens
[
i
-
1
]
*
3
==
rlens
[
i
]
// white around the black pattern? Not part of spec
&&
(
rlens
[
i
-
3
]
==
0
// beginning
||
i
+
3
>
length
// end
||
rlens
[
i
-
3
]
*
3
>=
rlens
[
i
]
*
4
||
rlens
[
i
+
3
]
*
3
>=
rlens
[
i
]
*
4
)
)
runsbad
+=
N3
;
return
runsbad
;
}
// Calculate how bad the masked image is - blocks, imbalance, runs, or finders.
function
badcheck
()
{
var
x
,
y
,
h
,
b
,
b1
;
var
thisbad
=
0
;
var
bw
=
0
;
// blocks of same color.
for
(
y
=
0
;
y
<
width
-
1
;
y
++
)
for
(
x
=
0
;
x
<
width
-
1
;
x
++
)
if
((
qrframe
[
x
+
width
*
y
]
&&
qrframe
[(
x
+
1
)
+
width
*
y
]
&&
qrframe
[
x
+
width
*
(
y
+
1
)]
&&
qrframe
[(
x
+
1
)
+
width
*
(
y
+
1
)])
// all black
||
!
(
qrframe
[
x
+
width
*
y
]
||
qrframe
[(
x
+
1
)
+
width
*
y
]
||
qrframe
[
x
+
width
*
(
y
+
1
)]
||
qrframe
[(
x
+
1
)
+
width
*
(
y
+
1
)]))
// all white
thisbad
+=
N2
;
// X runs
for
(
y
=
0
;
y
<
width
;
y
++
)
{
rlens
[
0
]
=
0
;
for
(
h
=
b
=
x
=
0
;
x
<
width
;
x
++
)
{
if
((
b1
=
qrframe
[
x
+
width
*
y
])
==
b
)
rlens
[
h
]
++
;
else
rlens
[
++
h
]
=
1
;
b
=
b1
;
bw
+=
b
?
1
:
-
1
;
}
thisbad
+=
badruns
(
h
);
}
// black/white imbalance
if
(
bw
<
0
)
bw
=
-
bw
;
var
big
=
bw
;
var
count
=
0
;
big
+=
big
<<
2
;
big
<<=
1
;
while
(
big
>
width
*
width
)
big
-=
width
*
width
,
count
++
;
thisbad
+=
count
*
N4
;
// Y runs
for
(
x
=
0
;
x
<
width
;
x
++
)
{
rlens
[
0
]
=
0
;
for
(
h
=
b
=
y
=
0
;
y
<
width
;
y
++
)
{
if
((
b1
=
qrframe
[
x
+
width
*
y
])
==
b
)
rlens
[
h
]
++
;
else
rlens
[
++
h
]
=
1
;
b
=
b1
;
}
thisbad
+=
badruns
(
h
);
}
return
thisbad
;
}
function
genframe
(
instring
)
{
var
x
,
y
,
k
,
t
,
v
,
i
,
j
,
m
;
// find the smallest version that fits the string
t
=
instring
.
length
;
version
=
0
;
do
{
version
++
;
k
=
(
ecclevel
-
1
)
*
4
+
(
version
-
1
)
*
16
;
neccblk1
=
eccblocks
[
k
++
];
neccblk2
=
eccblocks
[
k
++
];
datablkw
=
eccblocks
[
k
++
];
eccblkwid
=
eccblocks
[
k
];
k
=
datablkw
*
(
neccblk1
+
neccblk2
)
+
neccblk2
-
3
+
(
version
<=
9
);
if
(
t
<=
k
)
break
;
}
while
(
version
<
40
);
// FIXME - insure that it fits insted of being truncated
width
=
17
+
4
*
version
;
// allocate, clear and setup data structures
v
=
datablkw
+
(
datablkw
+
eccblkwid
)
*
(
neccblk1
+
neccblk2
)
+
neccblk2
;
for
(
t
=
0
;
t
<
v
;
t
++
)
eccbuf
[
t
]
=
0
;
strinbuf
=
instring
.
slice
(
0
);
for
(
t
=
0
;
t
<
width
*
width
;
t
++
)
qrframe
[
t
]
=
0
;
for
(
t
=
0
;
t
<
(
width
*
(
width
+
1
)
+
1
)
/
2
;
t
++
)
framask
[
t
]
=
0
;
// insert finders - black to frame, white to mask
for
(
t
=
0
;
t
<
3
;
t
++
)
{
k
=
0
;
y
=
0
;
if
(
t
==
1
)
k
=
(
width
-
7
);
if
(
t
==
2
)
y
=
(
width
-
7
);
qrframe
[(
y
+
3
)
+
width
*
(
k
+
3
)]
=
1
;
for
(
x
=
0
;
x
<
6
;
x
++
)
{
qrframe
[(
y
+
x
)
+
width
*
k
]
=
1
;
qrframe
[
y
+
width
*
(
k
+
x
+
1
)]
=
1
;
qrframe
[(
y
+
6
)
+
width
*
(
k
+
x
)]
=
1
;
qrframe
[(
y
+
x
+
1
)
+
width
*
(
k
+
6
)]
=
1
;
}
for
(
x
=
1
;
x
<
5
;
x
++
)
{
setmask
(
y
+
x
,
k
+
1
);
setmask
(
y
+
1
,
k
+
x
+
1
);
setmask
(
y
+
5
,
k
+
x
);
setmask
(
y
+
x
+
1
,
k
+
5
);
}
for
(
x
=
2
;
x
<
4
;
x
++
)
{
qrframe
[(
y
+
x
)
+
width
*
(
k
+
2
)]
=
1
;
qrframe
[(
y
+
2
)
+
width
*
(
k
+
x
+
1
)]
=
1
;
qrframe
[(
y
+
4
)
+
width
*
(
k
+
x
)]
=
1
;
qrframe
[(
y
+
x
+
1
)
+
width
*
(
k
+
4
)]
=
1
;
}
}
// alignment blocks
if
(
version
>
1
)
{
t
=
adelta
[
version
];
y
=
width
-
7
;
for
(;
;)
{
x
=
width
-
7
;
while
(
x
>
t
-
3
)
{
putalign
(
x
,
y
);
if
(
x
<
t
)
break
;
x
-=
t
;
}
if
(
y
<=
t
+
9
)
break
;
y
-=
t
;
putalign
(
6
,
y
);
putalign
(
y
,
6
);
}
}
// single black
qrframe
[
8
+
width
*
(
width
-
8
)]
=
1
;
// timing gap - mask only
for
(
y
=
0
;
y
<
7
;
y
++
)
{
setmask
(
7
,
y
);
setmask
(
width
-
8
,
y
);
setmask
(
7
,
y
+
width
-
7
);
}
for
(
x
=
0
;
x
<
8
;
x
++
)
{
setmask
(
x
,
7
);
setmask
(
x
+
width
-
8
,
7
);
setmask
(
x
,
width
-
8
);
}
// reserve mask-format area
for
(
x
=
0
;
x
<
9
;
x
++
)
setmask
(
x
,
8
);
for
(
x
=
0
;
x
<
8
;
x
++
)
{
setmask
(
x
+
width
-
8
,
8
);
setmask
(
8
,
x
);
}
for
(
y
=
0
;
y
<
7
;
y
++
)
setmask
(
8
,
y
+
width
-
7
);
// timing row/col
for
(
x
=
0
;
x
<
width
-
14
;
x
++
)
if
(
x
&
1
)
{
setmask
(
8
+
x
,
6
);
setmask
(
6
,
8
+
x
);
}
else
{
qrframe
[(
8
+
x
)
+
width
*
6
]
=
1
;
qrframe
[
6
+
width
*
(
8
+
x
)]
=
1
;
}
// version block
if
(
version
>
6
)
{
t
=
vpat
[
version
-
7
];
k
=
17
;
for
(
x
=
0
;
x
<
6
;
x
++
)
for
(
y
=
0
;
y
<
3
;
y
++
,
k
--
)
if
(
1
&
(
k
>
11
?
version
>>
(
k
-
12
)
:
t
>>
k
))
{
qrframe
[(
5
-
x
)
+
width
*
(
2
-
y
+
width
-
11
)]
=
1
;
qrframe
[(
2
-
y
+
width
-
11
)
+
width
*
(
5
-
x
)]
=
1
;
}
else
{
setmask
(
5
-
x
,
2
-
y
+
width
-
11
);
setmask
(
2
-
y
+
width
-
11
,
5
-
x
);
}
}
// sync mask bits - only set above for white spaces, so add in black bits
for
(
y
=
0
;
y
<
width
;
y
++
)
for
(
x
=
0
;
x
<=
y
;
x
++
)
if
(
qrframe
[
x
+
width
*
y
])
setmask
(
x
,
y
);
// convert string to bitstream
// 8 bit data to QR-coded 8 bit data (numeric or alphanum, or kanji not supported)
v
=
strinbuf
.
length
;
// string to array
for
(
i
=
0
;
i
<
v
;
i
++
)
eccbuf
[
i
]
=
strinbuf
.
charCodeAt
(
i
);
strinbuf
=
eccbuf
.
slice
(
0
);
// calculate max string length
x
=
datablkw
*
(
neccblk1
+
neccblk2
)
+
neccblk2
;
if
(
v
>=
x
-
2
)
{
v
=
x
-
2
;
if
(
version
>
9
)
v
--
;
}
// shift and repack to insert length prefix
i
=
v
;
if
(
version
>
9
)
{
strinbuf
[
i
+
2
]
=
0
;
strinbuf
[
i
+
3
]
=
0
;
while
(
i
--
)
{
t
=
strinbuf
[
i
];
strinbuf
[
i
+
3
]
|=
255
&
(
t
<<
4
);
strinbuf
[
i
+
2
]
=
t
>>
4
;
}
strinbuf
[
2
]
|=
255
&
(
v
<<
4
);
strinbuf
[
1
]
=
v
>>
4
;
strinbuf
[
0
]
=
0x40
|
(
v
>>
12
);
}
else
{
strinbuf
[
i
+
1
]
=
0
;
strinbuf
[
i
+
2
]
=
0
;
while
(
i
--
)
{
t
=
strinbuf
[
i
];
strinbuf
[
i
+
2
]
|=
255
&
(
t
<<
4
);
strinbuf
[
i
+
1
]
=
t
>>
4
;
}
strinbuf
[
1
]
|=
255
&
(
v
<<
4
);
strinbuf
[
0
]
=
0x40
|
(
v
>>
4
);
}
// fill to end with pad pattern
i
=
v
+
3
-
(
version
<
10
);
while
(
i
<
x
)
{
strinbuf
[
i
++
]
=
0xec
;
// buffer has room if (i == x) break;
strinbuf
[
i
++
]
=
0x11
;
}
// calculate and append ECC
// calculate generator polynomial
genpoly
[
0
]
=
1
;
for
(
i
=
0
;
i
<
eccblkwid
;
i
++
)
{
genpoly
[
i
+
1
]
=
1
;
for
(
j
=
i
;
j
>
0
;
j
--
)
genpoly
[
j
]
=
genpoly
[
j
]
?
genpoly
[
j
-
1
]
^
gexp
[
modnn
(
glog
[
genpoly
[
j
]]
+
i
)]
:
genpoly
[
j
-
1
];
genpoly
[
0
]
=
gexp
[
modnn
(
glog
[
genpoly
[
0
]]
+
i
)];
}
for
(
i
=
0
;
i
<=
eccblkwid
;
i
++
)
genpoly
[
i
]
=
glog
[
genpoly
[
i
]];
// use logs for genpoly[] to save calc step
// append ecc to data buffer
k
=
x
;
y
=
0
;
for
(
i
=
0
;
i
<
neccblk1
;
i
++
)
{
appendrs
(
y
,
datablkw
,
k
,
eccblkwid
);
y
+=
datablkw
;
k
+=
eccblkwid
;
}
for
(
i
=
0
;
i
<
neccblk2
;
i
++
)
{
appendrs
(
y
,
datablkw
+
1
,
k
,
eccblkwid
);
y
+=
datablkw
+
1
;
k
+=
eccblkwid
;
}
// interleave blocks
y
=
0
;
for
(
i
=
0
;
i
<
datablkw
;
i
++
)
{
for
(
j
=
0
;
j
<
neccblk1
;
j
++
)
eccbuf
[
y
++
]
=
strinbuf
[
i
+
j
*
datablkw
];
for
(
j
=
0
;
j
<
neccblk2
;
j
++
)
eccbuf
[
y
++
]
=
strinbuf
[(
neccblk1
*
datablkw
)
+
i
+
(
j
*
(
datablkw
+
1
))];
}
for
(
j
=
0
;
j
<
neccblk2
;
j
++
)
eccbuf
[
y
++
]
=
strinbuf
[(
neccblk1
*
datablkw
)
+
i
+
(
j
*
(
datablkw
+
1
))];
for
(
i
=
0
;
i
<
eccblkwid
;
i
++
)
for
(
j
=
0
;
j
<
neccblk1
+
neccblk2
;
j
++
)
eccbuf
[
y
++
]
=
strinbuf
[
x
+
i
+
j
*
eccblkwid
];
strinbuf
=
eccbuf
;
// pack bits into frame avoiding masked area.
x
=
y
=
width
-
1
;
k
=
v
=
1
;
// up, minus
/* inteleaved data and ecc codes */
m
=
(
datablkw
+
eccblkwid
)
*
(
neccblk1
+
neccblk2
)
+
neccblk2
;
for
(
i
=
0
;
i
<
m
;
i
++
)
{
t
=
strinbuf
[
i
];
for
(
j
=
0
;
j
<
8
;
j
++
,
t
<<=
1
)
{
if
(
0x80
&
t
)
qrframe
[
x
+
width
*
y
]
=
1
;
do
{
// find next fill position
if
(
v
)
x
--
;
else
{
x
++
;
if
(
k
)
{
if
(
y
!=
0
)
y
--
;
else
{
x
-=
2
;
k
=
!
k
;
if
(
x
==
6
)
{
x
--
;
y
=
9
;
}
}
}
else
{
if
(
y
!=
width
-
1
)
y
++
;
else
{
x
-=
2
;
k
=
!
k
;
if
(
x
==
6
)
{
x
--
;
y
-=
8
;
}
}
}
}
v
=
!
v
;
}
while
(
ismasked
(
x
,
y
));
}
}
// save pre-mask copy of frame
strinbuf
=
qrframe
.
slice
(
0
);
t
=
0
;
// best
y
=
30000
;
// demerit
// for instead of while since in original arduino code
// if an early mask was "good enough" it wouldn't try for a better one
// since they get more complex and take longer.
for
(
k
=
0
;
k
<
8
;
k
++
)
{
applymask
(
k
);
// returns black-white imbalance
x
=
badcheck
();
if
(
x
<
y
)
{
// current mask better than previous best?
y
=
x
;
t
=
k
;
}
if
(
t
==
7
)
break
;
// don't increment i to a void redoing mask
qrframe
=
strinbuf
.
slice
(
0
);
// reset for next pass
}
if
(
t
!=
k
)
// redo best mask - none good enough, last wasn't t
applymask
(
t
);
// add in final mask/ecclevel bytes
y
=
fmtword
[
t
+
((
ecclevel
-
1
)
<<
3
)];
// low byte
for
(
k
=
0
;
k
<
8
;
k
++
,
y
>>=
1
)
if
(
y
&
1
)
{
qrframe
[(
width
-
1
-
k
)
+
width
*
8
]
=
1
;
if
(
k
<
6
)
qrframe
[
8
+
width
*
k
]
=
1
;
else
qrframe
[
8
+
width
*
(
k
+
1
)]
=
1
;
}
// high byte
for
(
k
=
0
;
k
<
7
;
k
++
,
y
>>=
1
)
if
(
y
&
1
)
{
qrframe
[
8
+
width
*
(
width
-
7
+
k
)]
=
1
;
if
(
k
)
qrframe
[(
6
-
k
)
+
width
*
8
]
=
1
;
else
qrframe
[
7
+
width
*
8
]
=
1
;
}
return
qrframe
;
}
var
_canvas
=
null
;
var
api
=
{
get
ecclevel
()
{
return
ecclevel
;
},
set
ecclevel
(
val
)
{
ecclevel
=
val
;
},
get
size
()
{
return
_size
;
},
set
size
(
val
)
{
_size
=
val
},
get
canvas
()
{
return
_canvas
;
},
set
canvas
(
el
)
{
_canvas
=
el
;
},
getFrame
:
function
(
string
)
{
return
genframe
(
string
);
},
//这里的utf16to8(str)是对Text中的字符串进行转码,让其支持中文
utf16to8
:
function
(
str
)
{
var
out
,
i
,
len
,
c
;
out
=
""
;
len
=
str
.
length
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
c
=
str
.
charCodeAt
(
i
);
if
((
c
>=
0x0001
)
&&
(
c
<=
0x007F
))
{
out
+=
str
.
charAt
(
i
);
}
else
if
(
c
>
0x07FF
)
{
out
+=
String
.
fromCharCode
(
0xE0
|
((
c
>>
12
)
&
0x0F
));
out
+=
String
.
fromCharCode
(
0x80
|
((
c
>>
6
)
&
0x3F
));
out
+=
String
.
fromCharCode
(
0x80
|
((
c
>>
0
)
&
0x3F
));
}
else
{
out
+=
String
.
fromCharCode
(
0xC0
|
((
c
>>
6
)
&
0x1F
));
out
+=
String
.
fromCharCode
(
0x80
|
((
c
>>
0
)
&
0x3F
));
}
}
return
out
;
},
/**
* 新增$this参数,传入组件的this,兼容在组件中生成
*/
draw
:
function
(
str
,
canvas
,
cavW
,
cavH
,
$this
,
ecc
)
{
var
that
=
this
;
ecclevel
=
ecc
||
ecclevel
;
canvas
=
canvas
||
_canvas
;
if
(
!
canvas
)
{
console
.
warn
(
'No canvas provided to draw QR code in!'
)
return
;
}
var
size
=
Math
.
min
(
cavW
,
cavH
);
str
=
that
.
utf16to8
(
str
);
//增加中文显示
var
frame
=
that
.
getFrame
(
str
),
// 组件中生成qrcode需要绑定this
ctx
=
wx
.
createCanvasContext
(
canvas
,
$this
),
px
=
Math
.
round
(
size
/
(
width
+
8
));
var
roundedSize
=
px
*
(
width
+
8
),
offset
=
Math
.
floor
((
size
-
roundedSize
)
/
2
);
size
=
roundedSize
;
//ctx.clearRect(0, 0, cavW, cavW);
ctx
.
setFillStyle
(
'#ffffff'
)
ctx
.
fillRect
(
0
,
0
,
cavW
,
cavW
);
ctx
.
setFillStyle
(
'#000000'
);
for
(
var
i
=
0
;
i
<
width
;
i
++
)
{
for
(
var
j
=
0
;
j
<
width
;
j
++
)
{
if
(
frame
[
j
*
width
+
i
])
{
ctx
.
fillRect
(
px
*
(
4
+
i
)
+
offset
,
px
*
(
4
+
j
)
+
offset
,
px
,
px
);
}
}
}
ctx
.
draw
();
}
}
module
.
exports
=
{
api
}
// exports.draw = api;
})();
\ No newline at end of file
Please
register
or
sign in
to post a comment