diff --git a/App.vue b/App.vue index f112766b2fe467674ada5b877819c78ec56423c7..9967daa3a0adf48e6c5e25c0153247178c99f8fe 100644 --- a/App.vue +++ b/App.vue @@ -1,57 +1,57 @@ - - - diff --git a/common/appInit.js b/common/appInit.js index a3d285a963c1c18265e6a8754ac89911474dad72..9af4be22e51b70b1b9c9a164f9c60c7c1f52f850 100644 --- a/common/appInit.js +++ b/common/appInit.js @@ -1,457 +1,457 @@ -import uniStarterConfig from '@/uni-starter.config.js'; -import store from '@/store' -//应用初始化页 -// #ifdef APP-PLUS -import checkUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update'; -import callCheckVersion from '@/uni_modules/uni-upgrade-center-app/utils/call-check-version'; -import interceptorChooseImage from '@/uni_modules/json-interceptor-chooseImage/js_sdk/main.js'; -// #endif -const db = uniCloud.database() -export default async function() { - let loginConfig = uniStarterConfig.router.login - //清除有配置但设备环境不支持的登录项 - // #ifdef APP-PLUS - await new Promise((callBack) => { - plus.oauth.getServices(oauthServices => { - loginConfig = loginConfig.filter(item => { - if (["univerify", "weixin", "apple"].includes(item)) { - let index = oauthServices.findIndex(e => e.id == item) - if (index == -1) { - return false - } else { - return oauthServices[index].nativeClient - } - } else { - return true - } - }) - if (loginConfig.includes('univerify')) { //一键登录 功能预登录 - uni.preLogin({ - provider: 'univerify', - complete: e => { - console.log(e); - } - }) - } - callBack() - }, err => { - console.error('获取服务供应商失败:' + JSON.stringify(err)); - }) - }) - // #endif - - //非app移除:一键登录、苹果登录;h5移除微信登录,如果你做微信公众号登录需要将此行移除 - // #ifndef APP-PLUS - loginConfig = loginConfig.filter(item => { - return ![ - 'univerify', - 'apple', - // #ifdef H5 - 'weixin' - // #endif - ].includes(item) - }) - // #endif - - uniStarterConfig.router.login = loginConfig - - // uniStarterConfig挂载到getApp().globalData.config - setTimeout(() => { - getApp({ - allowDefault: true - }).globalData.config = uniStarterConfig; - }, 1) - - - // 初始化appVersion(仅app生效) - initAppVersion(); - - // #ifdef APP-PLUS - // 实现,路由拦截。当应用无访问摄像头/相册权限,引导跳到设置界面 - interceptorChooseImage() - // #endif - - - //clientDB的错误提示 - function onDBError({ - code, // 错误码详见https://uniapp.dcloud.net.cn/uniCloud/clientdb?id=returnvalue - message - }) { - console.log('onDBError', { - code, - message - }); - // 处理错误 - console.error(code, message); - if ([ - 'TOKEN_INVALID_INVALID_CLIENTID', - 'TOKEN_INVALID', - 'TOKEN_INVALID_TOKEN_EXPIRED', - 'TOKEN_INVALID_WRONG_TOKEN', - 'TOKEN_INVALID_ANONYMOUS_USER', - - ].includes(code)) { - uni.navigateTo({ - url: '/pages/ucenter/login-page/index/index' - }) - } - } - // 绑定clientDB错误事件 - db.on('error', onDBError) - - // 解绑clientDB错误事件 - //db.off('error', onDBError) - db.on('refreshToken', function({ - token, - tokenExpired - }) { - console.log('监听到clientDB的refreshToken', { - token, - tokenExpired - }); - store.commit('user/login', { - token, - tokenExpired - }) - }) - - const Debug = false; - //拦截器封装callFunction - let callFunctionOption; - uniCloud.addInterceptor('callFunction', { - async invoke(option) { - // #ifdef APP-PLUS - // 判断如果是执行登录(无论是哪种登录方式),就记录用户的相关设备id - if (option.name == 'uni-id-cf' && - (option.data.action == 'register' || option.data.action.slice(0, 5) == 'login') - ) { - let oaid = await new Promise((callBack, fail) => { - if (uni.getSystemInfoSync().platform == "android") { - plus.device.getOAID({ - success: function(e) { - callBack(e.oaid) - // console.log('getOAID success: '+JSON.stringify(e)); - }, - fail: function(e) { - callBack() - console.log('getOAID failed: ' + JSON.stringify(e)); - } - }); - } else { - callBack() - } - }) - - let imei = await new Promise((callBack, fail) => { - if (uni.getSystemInfoSync().platform == "android") { - plus.device.getInfo({ - success: function(e) { - callBack(e.imei) - // console.log('getOAID success: '+JSON.stringify(e)); - }, - fail: function(e) { - callBack() - console.log('getOAID failed: ' + JSON.stringify(e)); - } - }); - } else { - callBack() - } - }) - - let push_clientid = '', - idfa = plus.storage.getItem('idfa') || ''; //idfa有需要的用户在应用首次启动时自己获取存储到storage中 - - try { - push_clientid = plus.push.getClientInfo().clientid - } catch (e) { - uni.showModal({ - content: '获取推送标识失败。如果你的应用不需要推送功能,请注释掉本代码块', - showCancel: false, - confirmText: "好的" - }); - console.log(e) - } - - let deviceInfo = { - push_clientid, // 获取匿名设备标识符 - imei, - oaid, - idfa - } - console.log("重新登录/注册,获取设备id", deviceInfo); - option.data.deviceInfo = deviceInfo - - // #ifndef H5 - //注册可能不仅仅走register接口,还有登录并注册的接口 - option.data.inviteCode = await new Promise((callBack) => { - uni.getClipboardData({ - success: function(res) { - if (res.data.slice(0, 18) == 'uniInvitationCode:') { - let uniInvitationCode = res.data.slice(18, 38) - console.log('当前用户是其他用户推荐下载的,推荐者的code是:' + - uniInvitationCode); - // uni.showModal({ - // content: '当前用户是其他用户推荐下载的,推荐者的code是:'+uniInvitationCode, - // showCancel: false - // }); - callBack(uniInvitationCode) - //当前用户是其他用户推荐下载的。这里登记他的推荐者id 为当前用户的myInviteCode。判断如果是注册 - } else { - callBack(false) - } - }, - fail() { - callBack(false) - } - }); - }) - // #endif - } - // #endif - // console.log(JSON.stringify(option)); - callFunctionOption = option - }, - complete(e) { - // console.log(JSON.stringify(e)); - }, - fail(e) { // 失败回调拦截 - if (Debug) { - uni.showModal({ - content: JSON.stringify(e), - showCancel: false - }); - console.error(e); - } else { - uni.showModal({ - content: "系统错误请稍后再试!", - showCancel: false, - confirmText: "知道了" - }); - } - //如果执行错误,检查是否断网 - uni.getNetworkType({ - complete: res => { - // console.log(res); - if (res.networkType == 'none') { - uni.showToast({ - title: '手机网络异常', - icon: 'none' - }); - console.log('手机网络异常'); - let callBack = res => { - console.log(res); - if (res.isConnected) { - uni.showToast({ - title: '恢复联网自动重新执行', - icon: 'none' - }); - console.log(res.networkType, "恢复联网自动重新执行"); - uni.offNetworkStatusChange(e => { - console.log("移除监听成功", e); - }) - //恢复联网自动重新执行 - uniCloud.callFunction(callFunctionOption) - uni.offNetworkStatusChange(callBack); - } - } - uni.onNetworkStatusChange(callBack); - } - } - }); - }, - success: (e) => { - // console.log(e); - const { - token, - tokenExpired - } = e.result - if (token && tokenExpired) { - store.commit('user/login', { - token, - tokenExpired - }) - } - switch (e.result.code) { - case 403: - uni.navigateTo({ - url: "/pages/ucenter/login-page/index/index" - }) - break; - case 30203: - uni.navigateTo({ - url: "/pages/ucenter/login-page/index/index" - }) - break; - case 50101: - uni.showToast({ - title: e.result.msg, - icon: 'none', - duration: 2000 - }); - break; - default: - console.log('code的值是:' + e.result.code, '可以在上面添加case,自动处理响应体'); - break; - } - - switch (e.result.errCode) { - case 'uni-id-token-not-exist': - uni.showToast({ - title: '登录信息失效', - icon: 'none' - }); - uni.navigateTo({ - url: "/pages/ucenter/login-page/index/index" - }) - break; - default: - break; - } - } - }) - - //自定义路由拦截 - const { - "router": { - needLogin, - visitor, - login - } - } = uniStarterConfig //需要登录的页面 - - let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"]; - list.forEach(item => { //用遍历的方式分别为,uni.navigateTo,uni.redirectTo,uni.reLaunch,uni.switchTab这4个路由方法添加拦截器 - uni.addInterceptor(item, { - invoke(e) { // 调用前拦截 - //获取用户的token - const token = uni.getStorageSync('uni_id_token'), - //token是否已失效 - tokenExpired = uni.getStorageSync('uni_id_token_expired') < Date.now(), - //获取要跳转的页面路径(url去掉"?"和"?"后的参数) - url = e.url.split('?')[0]; - //获取要前往的页面路径(即url去掉"?"和"?"后的参数) - const pages = getCurrentPages(); - if (!pages.length) { - console.log("首页启动调用了"); - return e - } - const fromUrl = pages[pages.length - 1].route; - - let inLoginPage = fromUrl.split('/')[2] == 'login-page' - - //控制登录优先级 - if ( //判断当前窗口是否为登录页面,如果是则不重定向路由 - url == '/pages/ucenter/login-page/index/index' && - !inLoginPage - ) { - //一键登录(univerify)、账号(username)、验证码登录(短信smsCode) - if (login[0] == 'username') { - e.url = "/pages/ucenter/login-page/pwd-login/pwd-login" - } else { - if (e.url == url) { - e.url += '?' - } //添加参数之前判断是否带了`?`号如果没有就补上,因为当开发场景本身有参数的情况下是已经带了`?`号 - e.url += "type=" + login[0] - } - } else { - //拦截强制登录页面 - let pass = true - //pattern - if (needLogin) { - pass = needLogin.every((item) => { - if (typeof(item) == 'object' && item.pattern) { - return !item.pattern.test(url) - } - return url != item - }) - // console.log({pass}) - } - if (visitor) { - pass = visitor.some((item) => { - if (typeof(item) == 'object' && item.pattern) { - return item.pattern.test(url) - } - return url == item - }) - // console.log({pass}) - } - - if (!pass && (token == '' || tokenExpired)) { - uni.showToast({ - title: '请先登录', - icon: 'none' - }) - uni.navigateTo({ - url: "/pages/ucenter/login-page/index/index" - }) - return false - } - } - return e - }, - fail(err) { // 失败回调拦截 - console.log(err); - if (Debug) { - console.log(err); - uni.showModal({ - content: JSON.stringify(err), - showCancel: false - }); - } - } - }) - }) - - // #ifdef APP-PLUS - // 监听并提示设备网络状态变化 - uni.onNetworkStatusChange(res => { - console.log(res.isConnected); - console.log(res.networkType); - if (res.networkType != 'none') { - uni.showToast({ - title: '当前网络类型:' + res.networkType, - icon: 'none', - duration: 3000 - }) - } else { - uni.showToast({ - title: '网络类型:' + res.networkType, - icon: 'none', - duration: 3000 - }) - } - }); - // #endif - -} -/** - * // 初始化appVersion - */ -function initAppVersion() { - // #ifdef APP-PLUS - let appid = plus.runtime.appid; - plus.runtime.getProperty(appid, (wgtInfo) => { - let appVersion = plus.runtime; - let currentVersion = appVersion.versionCode > wgtInfo.versionCode ? appVersion : wgtInfo; - getApp({ - allowDefault: true - }).appVersion = { - ...currentVersion, - appid, - hasNew: false - } - // 检查更新小红点 - callCheckVersion().then(res => { - // console.log('检查是否有可以更新的版本', res); - if (res.result.code > 0) { - // 有新版本 - getApp({ - allowDefault: true - }).appVersion.hasNew = true; - } - }) - }); - // 检查更新 - // #endif -} +import uniStarterConfig from '@/uni-starter.config.js'; +import store from '@/store' +//应用初始化页 +// #ifdef APP-PLUS +import checkUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update'; +import callCheckVersion from '@/uni_modules/uni-upgrade-center-app/utils/call-check-version'; +import interceptorChooseImage from '@/uni_modules/json-interceptor-chooseImage/js_sdk/main.js'; +// #endif +const db = uniCloud.database() +export default async function() { + let loginConfig = uniStarterConfig.router.login + //清除有配置但设备环境不支持的登录项 + // #ifdef APP-PLUS + await new Promise((callBack) => { + plus.oauth.getServices(oauthServices => { + loginConfig = loginConfig.filter(item => { + if (["univerify", "weixin", "apple"].includes(item)) { + let index = oauthServices.findIndex(e => e.id == item) + if (index == -1) { + return false + } else { + return oauthServices[index].nativeClient + } + } else { + return true + } + }) + if (loginConfig.includes('univerify')) { //一键登录 功能预登录 + uni.preLogin({ + provider: 'univerify', + complete: e => { + console.log(e); + } + }) + } + callBack() + }, err => { + console.error('获取服务供应商失败:' + JSON.stringify(err)); + }) + }) + // #endif + + //非app移除:一键登录、苹果登录;h5移除微信登录,如果你做微信公众号登录需要将此行移除 + // #ifndef APP-PLUS + loginConfig = loginConfig.filter(item => { + return ![ + 'univerify', + 'apple', + // #ifdef H5 + 'weixin' + // #endif + ].includes(item) + }) + // #endif + + uniStarterConfig.router.login = loginConfig + + // uniStarterConfig挂载到getApp().globalData.config + setTimeout(() => { + getApp({ + allowDefault: true + }).globalData.config = uniStarterConfig; + }, 1) + + + // 初始化appVersion(仅app生效) + initAppVersion(); + + // #ifdef APP-PLUS + // 实现,路由拦截。当应用无访问摄像头/相册权限,引导跳到设置界面 + interceptorChooseImage() + // #endif + + + //clientDB的错误提示 + function onDBError({ + code, // 错误码详见https://uniapp.dcloud.net.cn/uniCloud/clientdb?id=returnvalue + message + }) { + console.log('onDBError', { + code, + message + }); + // 处理错误 + console.error(code, message); + if ([ + 'TOKEN_INVALID_INVALID_CLIENTID', + 'TOKEN_INVALID', + 'TOKEN_INVALID_TOKEN_EXPIRED', + 'TOKEN_INVALID_WRONG_TOKEN', + 'TOKEN_INVALID_ANONYMOUS_USER', + + ].includes(code)) { + uni.navigateTo({ + url: '/pages/ucenter/login-page/index/index' + }) + } + } + // 绑定clientDB错误事件 + db.on('error', onDBError) + + // 解绑clientDB错误事件 + //db.off('error', onDBError) + db.on('refreshToken', function({ + token, + tokenExpired + }) { + console.log('监听到clientDB的refreshToken', { + token, + tokenExpired + }); + store.commit('user/login', { + token, + tokenExpired + }) + }) + + const Debug = false; + //拦截器封装callFunction + let callFunctionOption; + uniCloud.addInterceptor('callFunction', { + async invoke(option) { + // #ifdef APP-PLUS + // 判断如果是执行登录(无论是哪种登录方式),就记录用户的相关设备id + if (option.name == 'uni-id-cf' && + (option.data.action == 'register' || option.data.action.slice(0, 5) == 'login') + ) { + let oaid = await new Promise((callBack, fail) => { + if (uni.getSystemInfoSync().platform == "android") { + plus.device.getOAID({ + success: function(e) { + callBack(e.oaid) + // console.log('getOAID success: '+JSON.stringify(e)); + }, + fail: function(e) { + callBack() + console.log('getOAID failed: ' + JSON.stringify(e)); + } + }); + } else { + callBack() + } + }) + + let imei = await new Promise((callBack, fail) => { + if (uni.getSystemInfoSync().platform == "android") { + plus.device.getInfo({ + success: function(e) { + callBack(e.imei) + // console.log('getOAID success: '+JSON.stringify(e)); + }, + fail: function(e) { + callBack() + console.log('getOAID failed: ' + JSON.stringify(e)); + } + }); + } else { + callBack() + } + }) + + let push_clientid = '', + idfa = plus.storage.getItem('idfa') || ''; //idfa有需要的用户在应用首次启动时自己获取存储到storage中 + + try { + push_clientid = plus.push.getClientInfo().clientid + } catch (e) { + uni.showModal({ + content: '获取推送标识失败。如果你的应用不需要推送功能,请注释掉本代码块', + showCancel: false, + confirmText: "好的" + }); + console.log(e) + } + + let deviceInfo = { + push_clientid, // 获取匿名设备标识符 + imei, + oaid, + idfa + } + console.log("重新登录/注册,获取设备id", deviceInfo); + option.data.deviceInfo = deviceInfo + + // #ifndef H5 + //注册可能不仅仅走register接口,还有登录并注册的接口 + option.data.inviteCode = await new Promise((callBack) => { + uni.getClipboardData({ + success: function(res) { + if (res.data.slice(0, 18) == 'uniInvitationCode:') { + let uniInvitationCode = res.data.slice(18, 38) + console.log('当前用户是其他用户推荐下载的,推荐者的code是:' + + uniInvitationCode); + // uni.showModal({ + // content: '当前用户是其他用户推荐下载的,推荐者的code是:'+uniInvitationCode, + // showCancel: false + // }); + callBack(uniInvitationCode) + //当前用户是其他用户推荐下载的。这里登记他的推荐者id 为当前用户的myInviteCode。判断如果是注册 + } else { + callBack(false) + } + }, + fail() { + callBack(false) + } + }); + }) + // #endif + } + // #endif + // console.log(JSON.stringify(option)); + callFunctionOption = option + }, + complete(e) { + // console.log(JSON.stringify(e)); + }, + fail(e) { // 失败回调拦截 + if (Debug) { + uni.showModal({ + content: JSON.stringify(e), + showCancel: false + }); + console.error(e); + } else { + uni.showModal({ + content: "系统错误请稍后再试!", + showCancel: false, + confirmText: "知道了" + }); + } + //如果执行错误,检查是否断网 + uni.getNetworkType({ + complete: res => { + // console.log(res); + if (res.networkType == 'none') { + uni.showToast({ + title: '手机网络异常', + icon: 'none' + }); + console.log('手机网络异常'); + let callBack = res => { + console.log(res); + if (res.isConnected) { + uni.showToast({ + title: '恢复联网自动重新执行', + icon: 'none' + }); + console.log(res.networkType, "恢复联网自动重新执行"); + uni.offNetworkStatusChange(e => { + console.log("移除监听成功", e); + }) + //恢复联网自动重新执行 + uniCloud.callFunction(callFunctionOption) + uni.offNetworkStatusChange(callBack); + } + } + uni.onNetworkStatusChange(callBack); + } + } + }); + }, + success: (e) => { + // console.log(e); + const { + token, + tokenExpired + } = e.result + if (token && tokenExpired) { + store.commit('user/login', { + token, + tokenExpired + }) + } + switch (e.result.code) { + case 403: + uni.navigateTo({ + url: "/pages/ucenter/login-page/index/index" + }) + break; + case 30203: + uni.navigateTo({ + url: "/pages/ucenter/login-page/index/index" + }) + break; + case 50101: + uni.showToast({ + title: e.result.msg, + icon: 'none', + duration: 2000 + }); + break; + default: + console.log('code的值是:' + e.result.code, '可以在上面添加case,自动处理响应体'); + break; + } + + switch (e.result.errCode) { + case 'uni-id-token-not-exist': + uni.showToast({ + title: '登录信息失效', + icon: 'none' + }); + uni.navigateTo({ + url: "/pages/ucenter/login-page/index/index" + }) + break; + default: + break; + } + } + }) + + //自定义路由拦截 + const { + "router": { + needLogin, + visitor, + login + } + } = uniStarterConfig //需要登录的页面 + + let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"]; + list.forEach(item => { //用遍历的方式分别为,uni.navigateTo,uni.redirectTo,uni.reLaunch,uni.switchTab这4个路由方法添加拦截器 + uni.addInterceptor(item, { + invoke(e) { // 调用前拦截 + //获取用户的token + const token = uni.getStorageSync('uni_id_token'), + //token是否已失效 + tokenExpired = uni.getStorageSync('uni_id_token_expired') < Date.now(), + //获取要跳转的页面路径(url去掉"?"和"?"后的参数) + url = e.url.split('?')[0]; + //获取要前往的页面路径(即url去掉"?"和"?"后的参数) + const pages = getCurrentPages(); + if (!pages.length) { + console.log("首页启动调用了"); + return e + } + const fromUrl = pages[pages.length - 1].route; + + let inLoginPage = fromUrl.split('/')[2] == 'login-page' + + //控制登录优先级 + if ( //判断当前窗口是否为登录页面,如果是则不重定向路由 + url == '/pages/ucenter/login-page/index/index' && + !inLoginPage + ) { + //一键登录(univerify)、账号(username)、验证码登录(短信smsCode) + if (login[0] == 'username') { + e.url = "/pages/ucenter/login-page/pwd-login/pwd-login" + } else { + if (e.url == url) { + e.url += '?' + } //添加参数之前判断是否带了`?`号如果没有就补上,因为当开发场景本身有参数的情况下是已经带了`?`号 + e.url += "type=" + login[0] + } + } else { + //拦截强制登录页面 + let pass = true + //pattern + if (needLogin) { + pass = needLogin.every((item) => { + if (typeof(item) == 'object' && item.pattern) { + return !item.pattern.test(url) + } + return url != item + }) + // console.log({pass}) + } + if (visitor) { + pass = visitor.some((item) => { + if (typeof(item) == 'object' && item.pattern) { + return item.pattern.test(url) + } + return url == item + }) + // console.log({pass}) + } + + if (!pass && (token == '' || tokenExpired)) { + uni.showToast({ + title: '请先登录', + icon: 'none' + }) + uni.navigateTo({ + url: "/pages/ucenter/login-page/index/index" + }) + return false + } + } + return e + }, + fail(err) { // 失败回调拦截 + console.log(err); + if (Debug) { + console.log(err); + uni.showModal({ + content: JSON.stringify(err), + showCancel: false + }); + } + } + }) + }) + + // #ifdef APP-PLUS + // 监听并提示设备网络状态变化 + uni.onNetworkStatusChange(res => { + console.log(res.isConnected); + console.log(res.networkType); + if (res.networkType != 'none') { + uni.showToast({ + title: '当前网络类型:' + res.networkType, + icon: 'none', + duration: 3000 + }) + } else { + uni.showToast({ + title: '网络类型:' + res.networkType, + icon: 'none', + duration: 3000 + }) + } + }); + // #endif + +} +/** + * // 初始化appVersion + */ +function initAppVersion() { + // #ifdef APP-PLUS + let appid = plus.runtime.appid; + plus.runtime.getProperty(appid, (wgtInfo) => { + let appVersion = plus.runtime; + let currentVersion = appVersion.versionCode > wgtInfo.versionCode ? appVersion : wgtInfo; + getApp({ + allowDefault: true + }).appVersion = { + ...currentVersion, + appid, + hasNew: false + } + // 检查更新小红点 + callCheckVersion().then(res => { + // console.log('检查是否有可以更新的版本', res); + if (res.result.code > 0) { + // 有新版本 + getApp({ + allowDefault: true + }).appVersion.hasNew = true; + } + }) + }); + // 检查更新 + // #endif +} diff --git a/components/Sansnn-uQRCode/Sansnn-uQRCode.vue b/components/Sansnn-uQRCode/Sansnn-uQRCode.vue index 0433faee91742247dc38a4363bb74f5775d04eb4..4a51a3776fd3dd3f6e810cd42d8040e52d0b7914 100644 --- a/components/Sansnn-uQRCode/Sansnn-uQRCode.vue +++ b/components/Sansnn-uQRCode/Sansnn-uQRCode.vue @@ -1,198 +1,198 @@ - - - diff --git a/components/Sansnn-uQRCode/uqrcode.js b/components/Sansnn-uQRCode/uqrcode.js index 311ce1dfacd7052ea3459aa1b142ac5fd65f02d9..0ba3d2bb19bb5bce5fcdb1bce4e43755b21ed140 100644 --- a/components/Sansnn-uQRCode/uqrcode.js +++ b/components/Sansnn-uQRCode/uqrcode.js @@ -1,1438 +1,1438 @@ -//--------------------------------------------------------------------- -// github https://github.com/Sansnn/uQRCode -//--------------------------------------------------------------------- - -let uQRCode = {}; - -(function() { - //--------------------------------------------------------------------- - // QRCode for JavaScript - // - // Copyright (c) 2009 Kazuhiko Arase - // - // URL: http://www.d-project.com/ - // - // Licensed under the MIT license: - // http://www.opensource.org/licenses/mit-license.php - // - // The word "QR Code" is registered trademark of - // DENSO WAVE INCORPORATED - // http://www.denso-wave.com/qrcode/faqpatent-e.html - // - //--------------------------------------------------------------------- - - //--------------------------------------------------------------------- - // QR8bitByte - //--------------------------------------------------------------------- - - function QR8bitByte(data) { - this.mode = QRMode.MODE_8BIT_BYTE; - this.data = data; - } - - QR8bitByte.prototype = { - - getLength: function(buffer) { - return this.data.length; - }, - - write: function(buffer) { - for (var i = 0; i < this.data.length; i++) { - // not JIS ... - buffer.put(this.data.charCodeAt(i), 8); - } - } - }; - - //--------------------------------------------------------------------- - // QRCode - //--------------------------------------------------------------------- - - function QRCode(typeNumber, errorCorrectLevel) { - this.typeNumber = typeNumber; - this.errorCorrectLevel = errorCorrectLevel; - this.modules = null; - this.moduleCount = 0; - this.dataCache = null; - this.dataList = new Array(); - } - - QRCode.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() { - // Calculate automatically typeNumber if provided is < 1 - if (this.typeNumber < 1) { - var typeNumber = 1; - for (typeNumber = 1; typeNumber < 40; typeNumber++) { - var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel); - - var buffer = new QRBitBuffer(); - var totalDataCount = 0; - for (var i = 0; i < rsBlocks.length; i++) { - totalDataCount += rsBlocks[i].dataCount; - } - - for (var i = 0; i < this.dataList.length; i++) { - var data = this.dataList[i]; - buffer.put(data.mode, 4); - buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); - data.write(buffer); - } - if (buffer.getLengthInBits() <= totalDataCount * 8) - break; - } - this.typeNumber = typeNumber; - } - 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; //(col + row) % 3; - } - } - - 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 = QRCode.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); - - // vertical - 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; - } - } - - // horizontal - 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; - } - } - - // fixed module - 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; - } - } - } - - } - - }; - - QRCode.PAD0 = 0xEC; - QRCode.PAD1 = 0x11; - - QRCode.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); - } - - // calc num max data. - 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 + - ")"); - } - - // end code - if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { - buffer.put(0, 4); - } - - // padding - while (buffer.getLengthInBits() % 8 != 0) { - buffer.putBit(false); - } - - // padding - while (true) { - - if (buffer.getLengthInBits() >= totalDataCount * 8) { - break; - } - buffer.put(QRCode.PAD0, 8); - - if (buffer.getLengthInBits() >= totalDataCount * 8) { - break; - } - buffer.put(QRCode.PAD1, 8); - } - - return QRCode.createBytes(buffer, rsBlocks); - } - - QRCode.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; - - } - - //--------------------------------------------------------------------- - // QRMode - //--------------------------------------------------------------------- - - var QRMode = { - MODE_NUMBER: 1 << 0, - MODE_ALPHA_NUM: 1 << 1, - MODE_8BIT_BYTE: 1 << 2, - MODE_KANJI: 1 << 3 - }; - - //--------------------------------------------------------------------- - // QRErrorCorrectLevel - //--------------------------------------------------------------------- - - var QRErrorCorrectLevel = { - L: 1, - M: 0, - Q: 3, - H: 2 - }; - - //--------------------------------------------------------------------- - // QRMaskPattern - //--------------------------------------------------------------------- - - var QRMaskPattern = { - PATTERN000: 0, - PATTERN001: 1, - PATTERN010: 2, - PATTERN011: 3, - PATTERN100: 4, - PATTERN101: 5, - PATTERN110: 6, - PATTERN111: 7 - }; - - //--------------------------------------------------------------------- - // QRUtil - //--------------------------------------------------------------------- - - 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) { - - // 1 - 9 - - 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) { - - // 10 - 26 - - 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) { - - // 27 - 40 - - 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; - - // LEVEL1 - - 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); - } - } - } - - // LEVEL2 - - 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; - } - } - } - - // LEVEL3 - - 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; - } - } - } - - // LEVEL4 - - 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; - } - - }; - - - //--------------------------------------------------------------------- - // QRMath - //--------------------------------------------------------------------- - - 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; - } - - //--------------------------------------------------------------------- - // QRPolynomial - //--------------------------------------------------------------------- - - 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); - } - - // recursive call - return new QRPolynomial(num, 0).mod(e); - } - }; - - //--------------------------------------------------------------------- - // QRRSBlock - //--------------------------------------------------------------------- - - function QRRSBlock(totalCount, dataCount) { - this.totalCount = totalCount; - this.dataCount = dataCount; - } - - QRRSBlock.RS_BLOCK_TABLE = [ - - // L - // M - // Q - // H - - // 1 - [1, 26, 19], - [1, 26, 16], - [1, 26, 13], - [1, 26, 9], - - // 2 - [1, 44, 34], - [1, 44, 28], - [1, 44, 22], - [1, 44, 16], - - // 3 - [1, 70, 55], - [1, 70, 44], - [2, 35, 17], - [2, 35, 13], - - // 4 - [1, 100, 80], - [2, 50, 32], - [2, 50, 24], - [4, 25, 9], - - // 5 - [1, 134, 108], - [2, 67, 43], - [2, 33, 15, 2, 34, 16], - [2, 33, 11, 2, 34, 12], - - // 6 - [2, 86, 68], - [4, 43, 27], - [4, 43, 19], - [4, 43, 15], - - // 7 - [2, 98, 78], - [4, 49, 31], - [2, 32, 14, 4, 33, 15], - [4, 39, 13, 1, 40, 14], - - // 8 - [2, 121, 97], - [2, 60, 38, 2, 61, 39], - [4, 40, 18, 2, 41, 19], - [4, 40, 14, 2, 41, 15], - - // 9 - [2, 146, 116], - [3, 58, 36, 2, 59, 37], - [4, 36, 16, 4, 37, 17], - [4, 36, 12, 4, 37, 13], - - // 10 - [2, 86, 68, 2, 87, 69], - [4, 69, 43, 1, 70, 44], - [6, 43, 19, 2, 44, 20], - [6, 43, 15, 2, 44, 16], - - // 11 - [4, 101, 81], - [1, 80, 50, 4, 81, 51], - [4, 50, 22, 4, 51, 23], - [3, 36, 12, 8, 37, 13], - - // 12 - [2, 116, 92, 2, 117, 93], - [6, 58, 36, 2, 59, 37], - [4, 46, 20, 6, 47, 21], - [7, 42, 14, 4, 43, 15], - - // 13 - [4, 133, 107], - [8, 59, 37, 1, 60, 38], - [8, 44, 20, 4, 45, 21], - [12, 33, 11, 4, 34, 12], - - // 14 - [3, 145, 115, 1, 146, 116], - [4, 64, 40, 5, 65, 41], - [11, 36, 16, 5, 37, 17], - [11, 36, 12, 5, 37, 13], - - // 15 - [5, 109, 87, 1, 110, 88], - [5, 65, 41, 5, 66, 42], - [5, 54, 24, 7, 55, 25], - [11, 36, 12], - - // 16 - [5, 122, 98, 1, 123, 99], - [7, 73, 45, 3, 74, 46], - [15, 43, 19, 2, 44, 20], - [3, 45, 15, 13, 46, 16], - - // 17 - [1, 135, 107, 5, 136, 108], - [10, 74, 46, 1, 75, 47], - [1, 50, 22, 15, 51, 23], - [2, 42, 14, 17, 43, 15], - - // 18 - [5, 150, 120, 1, 151, 121], - [9, 69, 43, 4, 70, 44], - [17, 50, 22, 1, 51, 23], - [2, 42, 14, 19, 43, 15], - - // 19 - [3, 141, 113, 4, 142, 114], - [3, 70, 44, 11, 71, 45], - [17, 47, 21, 4, 48, 22], - [9, 39, 13, 16, 40, 14], - - // 20 - [3, 135, 107, 5, 136, 108], - [3, 67, 41, 13, 68, 42], - [15, 54, 24, 5, 55, 25], - [15, 43, 15, 10, 44, 16], - - // 21 - [4, 144, 116, 4, 145, 117], - [17, 68, 42], - [17, 50, 22, 6, 51, 23], - [19, 46, 16, 6, 47, 17], - - // 22 - [2, 139, 111, 7, 140, 112], - [17, 74, 46], - [7, 54, 24, 16, 55, 25], - [34, 37, 13], - - // 23 - [4, 151, 121, 5, 152, 122], - [4, 75, 47, 14, 76, 48], - [11, 54, 24, 14, 55, 25], - [16, 45, 15, 14, 46, 16], - - // 24 - [6, 147, 117, 4, 148, 118], - [6, 73, 45, 14, 74, 46], - [11, 54, 24, 16, 55, 25], - [30, 46, 16, 2, 47, 17], - - // 25 - [8, 132, 106, 4, 133, 107], - [8, 75, 47, 13, 76, 48], - [7, 54, 24, 22, 55, 25], - [22, 45, 15, 13, 46, 16], - - // 26 - [10, 142, 114, 2, 143, 115], - [19, 74, 46, 4, 75, 47], - [28, 50, 22, 6, 51, 23], - [33, 46, 16, 4, 47, 17], - - // 27 - [8, 152, 122, 4, 153, 123], - [22, 73, 45, 3, 74, 46], - [8, 53, 23, 26, 54, 24], - [12, 45, 15, 28, 46, 16], - - // 28 - [3, 147, 117, 10, 148, 118], - [3, 73, 45, 23, 74, 46], - [4, 54, 24, 31, 55, 25], - [11, 45, 15, 31, 46, 16], - - // 29 - [7, 146, 116, 7, 147, 117], - [21, 73, 45, 7, 74, 46], - [1, 53, 23, 37, 54, 24], - [19, 45, 15, 26, 46, 16], - - // 30 - [5, 145, 115, 10, 146, 116], - [19, 75, 47, 10, 76, 48], - [15, 54, 24, 25, 55, 25], - [23, 45, 15, 25, 46, 16], - - // 31 - [13, 145, 115, 3, 146, 116], - [2, 74, 46, 29, 75, 47], - [42, 54, 24, 1, 55, 25], - [23, 45, 15, 28, 46, 16], - - // 32 - [17, 145, 115], - [10, 74, 46, 23, 75, 47], - [10, 54, 24, 35, 55, 25], - [19, 45, 15, 35, 46, 16], - - // 33 - [17, 145, 115, 1, 146, 116], - [14, 74, 46, 21, 75, 47], - [29, 54, 24, 19, 55, 25], - [11, 45, 15, 46, 46, 16], - - // 34 - [13, 145, 115, 6, 146, 116], - [14, 74, 46, 23, 75, 47], - [44, 54, 24, 7, 55, 25], - [59, 46, 16, 1, 47, 17], - - // 35 - [12, 151, 121, 7, 152, 122], - [12, 75, 47, 26, 76, 48], - [39, 54, 24, 14, 55, 25], - [22, 45, 15, 41, 46, 16], - - // 36 - [6, 151, 121, 14, 152, 122], - [6, 75, 47, 34, 76, 48], - [46, 54, 24, 10, 55, 25], - [2, 45, 15, 64, 46, 16], - - // 37 - [17, 152, 122, 4, 153, 123], - [29, 74, 46, 14, 75, 47], - [49, 54, 24, 10, 55, 25], - [24, 45, 15, 46, 46, 16], - - // 38 - [4, 152, 122, 18, 153, 123], - [13, 74, 46, 32, 75, 47], - [48, 54, 24, 14, 55, 25], - [42, 45, 15, 32, 46, 16], - - // 39 - [20, 147, 117, 4, 148, 118], - [40, 75, 47, 7, 76, 48], - [43, 54, 24, 22, 55, 25], - [10, 45, 15, 67, 46, 16], - - // 40 - [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 = new Array(); - - 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; - } - } - - //--------------------------------------------------------------------- - // QRBitBuffer - //--------------------------------------------------------------------- - - function QRBitBuffer() { - this.buffer = new Array(); - 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++; - } - }; - - //--------------------------------------------------------------------- - // Support Chinese - //--------------------------------------------------------------------- - function utf16To8(text) { - var result = ''; - var c; - for (var i = 0; i < text.length; i++) { - c = text.charCodeAt(i); - if (c >= 0x0001 && c <= 0x007F) { - result += text.charAt(i); - } else if (c > 0x07FF) { - result += String.fromCharCode(0xE0 | c >> 12 & 0x0F); - result += String.fromCharCode(0x80 | c >> 6 & 0x3F); - result += String.fromCharCode(0x80 | c >> 0 & 0x3F); - } else { - result += String.fromCharCode(0xC0 | c >> 6 & 0x1F); - result += String.fromCharCode(0x80 | c >> 0 & 0x3F); - } - } - return result; - } - - uQRCode = { - - errorCorrectLevel: QRErrorCorrectLevel, - - defaults: { - size: 354, - margin: 0, - backgroundColor: '#ffffff', - foregroundColor: '#000000', - fileType: 'png', // 'jpg', 'png' - errorCorrectLevel: QRErrorCorrectLevel.H, - typeNumber: -1 - }, - - make: function(options) { - return new Promise((reslove, reject) => { - var defaultOptions = { - canvasId: options.canvasId, - componentInstance: options.componentInstance, - text: options.text, - size: this.defaults.size, - margin: this.defaults.margin, - backgroundColor: this.defaults.backgroundColor, - foregroundColor: this.defaults.foregroundColor, - fileType: this.defaults.fileType, - errorCorrectLevel: this.defaults.errorCorrectLevel, - typeNumber: this.defaults.typeNumber - }; - if (options) { - for (var i in options) { - defaultOptions[i] = options[i]; - } - } - options = defaultOptions; - if (!options.canvasId) { - console.error('uQRCode: Please set canvasId!'); - return; - } - - function createCanvas() { - var qrcode = new QRCode(options.typeNumber, options.errorCorrectLevel); - qrcode.addData(utf16To8(options.text)); - qrcode.make(); - - var ctx = uni.createCanvasContext(options.canvasId, options.componentInstance); - ctx.setFillStyle(options.backgroundColor); - ctx.fillRect(0, 0, options.size, options.size); - - var tileW = (options.size - options.margin * 2) / qrcode.getModuleCount(); - var tileH = tileW; - - for (var row = 0; row < qrcode.getModuleCount(); row++) { - for (var col = 0; col < qrcode.getModuleCount(); col++) { - var style = qrcode.isDark(row, col) ? options.foregroundColor : options.backgroundColor; - ctx.setFillStyle(style); - var x = Math.round(col * tileW) + options.margin; - var y = Math.round(row * tileH) + options.margin; - var w = Math.ceil((col + 1) * tileW) - Math.floor(col * tileW); - var h = Math.ceil((row + 1) * tileW) - Math.floor(row * tileW); - ctx.fillRect(x, y, w, h); - } - } - - setTimeout(function() { - ctx.draw(false, (function() { - setTimeout(function() { - uni.canvasToTempFilePath({ - canvasId: options.canvasId, - fileType: options.fileType, - width: options.size, - height: options.size, - destWidth: options.size, - destHeight: options.size, - success: function(res) { - let resData; // 将统一为base64格式 - let tempFilePath = res.tempFilePath; // H5为base64,其他为相对路径 - - // #ifdef H5 - resData = tempFilePath; - options.success && options.success(resData); - reslove(resData); - // #endif - - // #ifdef APP-PLUS - const path = plus.io.convertLocalFileSystemURL(tempFilePath) // 绝对路径 - let fileReader = new plus.io.FileReader(); - fileReader.readAsDataURL(path); - fileReader.onloadend = res => { - resData = res.target.result; - options.success && options.success(resData); - reslove(resData); - }; - // #endif - - // #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO - uni.getFileSystemManager().readFile({ - filePath: tempFilePath, - encoding: 'base64', - success: res => { - resData = 'data:image/png;base64,' + res.data; - options.success && options.success(resData); - reslove(resData); - } - }) - // #endif - - // #ifndef H5 || APP-PLUS || MP-WEIXIN || MP-QQ || MP-TOUTIAO - if (plus) { - const path = plus.io.convertLocalFileSystemURL(tempFilePath) // 绝对路径 - let fileReader = new plus.io.FileReader(); - fileReader.readAsDataURL(path); - fileReader.onloadend = res => { - resData = res.target.result; - options.success && options.success(resData); - reslove(resData); - }; - } else { - uni.request({ - url: tempFilePath, - method: 'GET', - responseType: 'arraybuffer', - success: res => { - resData = `data:image/png;base64,${uni.arrayBufferToBase64(res.data)}`; // 把arraybuffer转成base64 - options.success && options.success(resData); - reslove(resData); - } - }) - } - // #endif - }, - fail: function(error) { - options.fail && options.fail(error); - reject(error); - }, - complete: function(res) { - options.complete && options.complete(res); - } - }, options.componentInstance); - }, options.text.length + 100); - })()); - }, 150); - } - - createCanvas(); - }); - } - } - -})() - +//--------------------------------------------------------------------- +// github https://github.com/Sansnn/uQRCode +//--------------------------------------------------------------------- + +let uQRCode = {}; + +(function() { + //--------------------------------------------------------------------- + // QRCode for JavaScript + // + // Copyright (c) 2009 Kazuhiko Arase + // + // URL: http://www.d-project.com/ + // + // Licensed under the MIT license: + // http://www.opensource.org/licenses/mit-license.php + // + // The word "QR Code" is registered trademark of + // DENSO WAVE INCORPORATED + // http://www.denso-wave.com/qrcode/faqpatent-e.html + // + //--------------------------------------------------------------------- + + //--------------------------------------------------------------------- + // QR8bitByte + //--------------------------------------------------------------------- + + function QR8bitByte(data) { + this.mode = QRMode.MODE_8BIT_BYTE; + this.data = data; + } + + QR8bitByte.prototype = { + + getLength: function(buffer) { + return this.data.length; + }, + + write: function(buffer) { + for (var i = 0; i < this.data.length; i++) { + // not JIS ... + buffer.put(this.data.charCodeAt(i), 8); + } + } + }; + + //--------------------------------------------------------------------- + // QRCode + //--------------------------------------------------------------------- + + function QRCode(typeNumber, errorCorrectLevel) { + this.typeNumber = typeNumber; + this.errorCorrectLevel = errorCorrectLevel; + this.modules = null; + this.moduleCount = 0; + this.dataCache = null; + this.dataList = new Array(); + } + + QRCode.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() { + // Calculate automatically typeNumber if provided is < 1 + if (this.typeNumber < 1) { + var typeNumber = 1; + for (typeNumber = 1; typeNumber < 40; typeNumber++) { + var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel); + + var buffer = new QRBitBuffer(); + var totalDataCount = 0; + for (var i = 0; i < rsBlocks.length; i++) { + totalDataCount += rsBlocks[i].dataCount; + } + + for (var i = 0; i < this.dataList.length; i++) { + var data = this.dataList[i]; + buffer.put(data.mode, 4); + buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); + data.write(buffer); + } + if (buffer.getLengthInBits() <= totalDataCount * 8) + break; + } + this.typeNumber = typeNumber; + } + 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; //(col + row) % 3; + } + } + + 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 = QRCode.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); + + // vertical + 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; + } + } + + // horizontal + 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; + } + } + + // fixed module + 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; + } + } + } + + } + + }; + + QRCode.PAD0 = 0xEC; + QRCode.PAD1 = 0x11; + + QRCode.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); + } + + // calc num max data. + 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 + + ")"); + } + + // end code + if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { + buffer.put(0, 4); + } + + // padding + while (buffer.getLengthInBits() % 8 != 0) { + buffer.putBit(false); + } + + // padding + while (true) { + + if (buffer.getLengthInBits() >= totalDataCount * 8) { + break; + } + buffer.put(QRCode.PAD0, 8); + + if (buffer.getLengthInBits() >= totalDataCount * 8) { + break; + } + buffer.put(QRCode.PAD1, 8); + } + + return QRCode.createBytes(buffer, rsBlocks); + } + + QRCode.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; + + } + + //--------------------------------------------------------------------- + // QRMode + //--------------------------------------------------------------------- + + var QRMode = { + MODE_NUMBER: 1 << 0, + MODE_ALPHA_NUM: 1 << 1, + MODE_8BIT_BYTE: 1 << 2, + MODE_KANJI: 1 << 3 + }; + + //--------------------------------------------------------------------- + // QRErrorCorrectLevel + //--------------------------------------------------------------------- + + var QRErrorCorrectLevel = { + L: 1, + M: 0, + Q: 3, + H: 2 + }; + + //--------------------------------------------------------------------- + // QRMaskPattern + //--------------------------------------------------------------------- + + var QRMaskPattern = { + PATTERN000: 0, + PATTERN001: 1, + PATTERN010: 2, + PATTERN011: 3, + PATTERN100: 4, + PATTERN101: 5, + PATTERN110: 6, + PATTERN111: 7 + }; + + //--------------------------------------------------------------------- + // QRUtil + //--------------------------------------------------------------------- + + 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) { + + // 1 - 9 + + 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) { + + // 10 - 26 + + 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) { + + // 27 - 40 + + 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; + + // LEVEL1 + + 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); + } + } + } + + // LEVEL2 + + 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; + } + } + } + + // LEVEL3 + + 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; + } + } + } + + // LEVEL4 + + 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; + } + + }; + + + //--------------------------------------------------------------------- + // QRMath + //--------------------------------------------------------------------- + + 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; + } + + //--------------------------------------------------------------------- + // QRPolynomial + //--------------------------------------------------------------------- + + 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); + } + + // recursive call + return new QRPolynomial(num, 0).mod(e); + } + }; + + //--------------------------------------------------------------------- + // QRRSBlock + //--------------------------------------------------------------------- + + function QRRSBlock(totalCount, dataCount) { + this.totalCount = totalCount; + this.dataCount = dataCount; + } + + QRRSBlock.RS_BLOCK_TABLE = [ + + // L + // M + // Q + // H + + // 1 + [1, 26, 19], + [1, 26, 16], + [1, 26, 13], + [1, 26, 9], + + // 2 + [1, 44, 34], + [1, 44, 28], + [1, 44, 22], + [1, 44, 16], + + // 3 + [1, 70, 55], + [1, 70, 44], + [2, 35, 17], + [2, 35, 13], + + // 4 + [1, 100, 80], + [2, 50, 32], + [2, 50, 24], + [4, 25, 9], + + // 5 + [1, 134, 108], + [2, 67, 43], + [2, 33, 15, 2, 34, 16], + [2, 33, 11, 2, 34, 12], + + // 6 + [2, 86, 68], + [4, 43, 27], + [4, 43, 19], + [4, 43, 15], + + // 7 + [2, 98, 78], + [4, 49, 31], + [2, 32, 14, 4, 33, 15], + [4, 39, 13, 1, 40, 14], + + // 8 + [2, 121, 97], + [2, 60, 38, 2, 61, 39], + [4, 40, 18, 2, 41, 19], + [4, 40, 14, 2, 41, 15], + + // 9 + [2, 146, 116], + [3, 58, 36, 2, 59, 37], + [4, 36, 16, 4, 37, 17], + [4, 36, 12, 4, 37, 13], + + // 10 + [2, 86, 68, 2, 87, 69], + [4, 69, 43, 1, 70, 44], + [6, 43, 19, 2, 44, 20], + [6, 43, 15, 2, 44, 16], + + // 11 + [4, 101, 81], + [1, 80, 50, 4, 81, 51], + [4, 50, 22, 4, 51, 23], + [3, 36, 12, 8, 37, 13], + + // 12 + [2, 116, 92, 2, 117, 93], + [6, 58, 36, 2, 59, 37], + [4, 46, 20, 6, 47, 21], + [7, 42, 14, 4, 43, 15], + + // 13 + [4, 133, 107], + [8, 59, 37, 1, 60, 38], + [8, 44, 20, 4, 45, 21], + [12, 33, 11, 4, 34, 12], + + // 14 + [3, 145, 115, 1, 146, 116], + [4, 64, 40, 5, 65, 41], + [11, 36, 16, 5, 37, 17], + [11, 36, 12, 5, 37, 13], + + // 15 + [5, 109, 87, 1, 110, 88], + [5, 65, 41, 5, 66, 42], + [5, 54, 24, 7, 55, 25], + [11, 36, 12], + + // 16 + [5, 122, 98, 1, 123, 99], + [7, 73, 45, 3, 74, 46], + [15, 43, 19, 2, 44, 20], + [3, 45, 15, 13, 46, 16], + + // 17 + [1, 135, 107, 5, 136, 108], + [10, 74, 46, 1, 75, 47], + [1, 50, 22, 15, 51, 23], + [2, 42, 14, 17, 43, 15], + + // 18 + [5, 150, 120, 1, 151, 121], + [9, 69, 43, 4, 70, 44], + [17, 50, 22, 1, 51, 23], + [2, 42, 14, 19, 43, 15], + + // 19 + [3, 141, 113, 4, 142, 114], + [3, 70, 44, 11, 71, 45], + [17, 47, 21, 4, 48, 22], + [9, 39, 13, 16, 40, 14], + + // 20 + [3, 135, 107, 5, 136, 108], + [3, 67, 41, 13, 68, 42], + [15, 54, 24, 5, 55, 25], + [15, 43, 15, 10, 44, 16], + + // 21 + [4, 144, 116, 4, 145, 117], + [17, 68, 42], + [17, 50, 22, 6, 51, 23], + [19, 46, 16, 6, 47, 17], + + // 22 + [2, 139, 111, 7, 140, 112], + [17, 74, 46], + [7, 54, 24, 16, 55, 25], + [34, 37, 13], + + // 23 + [4, 151, 121, 5, 152, 122], + [4, 75, 47, 14, 76, 48], + [11, 54, 24, 14, 55, 25], + [16, 45, 15, 14, 46, 16], + + // 24 + [6, 147, 117, 4, 148, 118], + [6, 73, 45, 14, 74, 46], + [11, 54, 24, 16, 55, 25], + [30, 46, 16, 2, 47, 17], + + // 25 + [8, 132, 106, 4, 133, 107], + [8, 75, 47, 13, 76, 48], + [7, 54, 24, 22, 55, 25], + [22, 45, 15, 13, 46, 16], + + // 26 + [10, 142, 114, 2, 143, 115], + [19, 74, 46, 4, 75, 47], + [28, 50, 22, 6, 51, 23], + [33, 46, 16, 4, 47, 17], + + // 27 + [8, 152, 122, 4, 153, 123], + [22, 73, 45, 3, 74, 46], + [8, 53, 23, 26, 54, 24], + [12, 45, 15, 28, 46, 16], + + // 28 + [3, 147, 117, 10, 148, 118], + [3, 73, 45, 23, 74, 46], + [4, 54, 24, 31, 55, 25], + [11, 45, 15, 31, 46, 16], + + // 29 + [7, 146, 116, 7, 147, 117], + [21, 73, 45, 7, 74, 46], + [1, 53, 23, 37, 54, 24], + [19, 45, 15, 26, 46, 16], + + // 30 + [5, 145, 115, 10, 146, 116], + [19, 75, 47, 10, 76, 48], + [15, 54, 24, 25, 55, 25], + [23, 45, 15, 25, 46, 16], + + // 31 + [13, 145, 115, 3, 146, 116], + [2, 74, 46, 29, 75, 47], + [42, 54, 24, 1, 55, 25], + [23, 45, 15, 28, 46, 16], + + // 32 + [17, 145, 115], + [10, 74, 46, 23, 75, 47], + [10, 54, 24, 35, 55, 25], + [19, 45, 15, 35, 46, 16], + + // 33 + [17, 145, 115, 1, 146, 116], + [14, 74, 46, 21, 75, 47], + [29, 54, 24, 19, 55, 25], + [11, 45, 15, 46, 46, 16], + + // 34 + [13, 145, 115, 6, 146, 116], + [14, 74, 46, 23, 75, 47], + [44, 54, 24, 7, 55, 25], + [59, 46, 16, 1, 47, 17], + + // 35 + [12, 151, 121, 7, 152, 122], + [12, 75, 47, 26, 76, 48], + [39, 54, 24, 14, 55, 25], + [22, 45, 15, 41, 46, 16], + + // 36 + [6, 151, 121, 14, 152, 122], + [6, 75, 47, 34, 76, 48], + [46, 54, 24, 10, 55, 25], + [2, 45, 15, 64, 46, 16], + + // 37 + [17, 152, 122, 4, 153, 123], + [29, 74, 46, 14, 75, 47], + [49, 54, 24, 10, 55, 25], + [24, 45, 15, 46, 46, 16], + + // 38 + [4, 152, 122, 18, 153, 123], + [13, 74, 46, 32, 75, 47], + [48, 54, 24, 14, 55, 25], + [42, 45, 15, 32, 46, 16], + + // 39 + [20, 147, 117, 4, 148, 118], + [40, 75, 47, 7, 76, 48], + [43, 54, 24, 22, 55, 25], + [10, 45, 15, 67, 46, 16], + + // 40 + [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 = new Array(); + + 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; + } + } + + //--------------------------------------------------------------------- + // QRBitBuffer + //--------------------------------------------------------------------- + + function QRBitBuffer() { + this.buffer = new Array(); + 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++; + } + }; + + //--------------------------------------------------------------------- + // Support Chinese + //--------------------------------------------------------------------- + function utf16To8(text) { + var result = ''; + var c; + for (var i = 0; i < text.length; i++) { + c = text.charCodeAt(i); + if (c >= 0x0001 && c <= 0x007F) { + result += text.charAt(i); + } else if (c > 0x07FF) { + result += String.fromCharCode(0xE0 | c >> 12 & 0x0F); + result += String.fromCharCode(0x80 | c >> 6 & 0x3F); + result += String.fromCharCode(0x80 | c >> 0 & 0x3F); + } else { + result += String.fromCharCode(0xC0 | c >> 6 & 0x1F); + result += String.fromCharCode(0x80 | c >> 0 & 0x3F); + } + } + return result; + } + + uQRCode = { + + errorCorrectLevel: QRErrorCorrectLevel, + + defaults: { + size: 354, + margin: 0, + backgroundColor: '#ffffff', + foregroundColor: '#000000', + fileType: 'png', // 'jpg', 'png' + errorCorrectLevel: QRErrorCorrectLevel.H, + typeNumber: -1 + }, + + make: function(options) { + return new Promise((reslove, reject) => { + var defaultOptions = { + canvasId: options.canvasId, + componentInstance: options.componentInstance, + text: options.text, + size: this.defaults.size, + margin: this.defaults.margin, + backgroundColor: this.defaults.backgroundColor, + foregroundColor: this.defaults.foregroundColor, + fileType: this.defaults.fileType, + errorCorrectLevel: this.defaults.errorCorrectLevel, + typeNumber: this.defaults.typeNumber + }; + if (options) { + for (var i in options) { + defaultOptions[i] = options[i]; + } + } + options = defaultOptions; + if (!options.canvasId) { + console.error('uQRCode: Please set canvasId!'); + return; + } + + function createCanvas() { + var qrcode = new QRCode(options.typeNumber, options.errorCorrectLevel); + qrcode.addData(utf16To8(options.text)); + qrcode.make(); + + var ctx = uni.createCanvasContext(options.canvasId, options.componentInstance); + ctx.setFillStyle(options.backgroundColor); + ctx.fillRect(0, 0, options.size, options.size); + + var tileW = (options.size - options.margin * 2) / qrcode.getModuleCount(); + var tileH = tileW; + + for (var row = 0; row < qrcode.getModuleCount(); row++) { + for (var col = 0; col < qrcode.getModuleCount(); col++) { + var style = qrcode.isDark(row, col) ? options.foregroundColor : options.backgroundColor; + ctx.setFillStyle(style); + var x = Math.round(col * tileW) + options.margin; + var y = Math.round(row * tileH) + options.margin; + var w = Math.ceil((col + 1) * tileW) - Math.floor(col * tileW); + var h = Math.ceil((row + 1) * tileW) - Math.floor(row * tileW); + ctx.fillRect(x, y, w, h); + } + } + + setTimeout(function() { + ctx.draw(false, (function() { + setTimeout(function() { + uni.canvasToTempFilePath({ + canvasId: options.canvasId, + fileType: options.fileType, + width: options.size, + height: options.size, + destWidth: options.size, + destHeight: options.size, + success: function(res) { + let resData; // 将统一为base64格式 + let tempFilePath = res.tempFilePath; // H5为base64,其他为相对路径 + + // #ifdef H5 + resData = tempFilePath; + options.success && options.success(resData); + reslove(resData); + // #endif + + // #ifdef APP-PLUS + const path = plus.io.convertLocalFileSystemURL(tempFilePath) // 绝对路径 + let fileReader = new plus.io.FileReader(); + fileReader.readAsDataURL(path); + fileReader.onloadend = res => { + resData = res.target.result; + options.success && options.success(resData); + reslove(resData); + }; + // #endif + + // #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO + uni.getFileSystemManager().readFile({ + filePath: tempFilePath, + encoding: 'base64', + success: res => { + resData = 'data:image/png;base64,' + res.data; + options.success && options.success(resData); + reslove(resData); + } + }) + // #endif + + // #ifndef H5 || APP-PLUS || MP-WEIXIN || MP-QQ || MP-TOUTIAO + if (plus) { + const path = plus.io.convertLocalFileSystemURL(tempFilePath) // 绝对路径 + let fileReader = new plus.io.FileReader(); + fileReader.readAsDataURL(path); + fileReader.onloadend = res => { + resData = res.target.result; + options.success && options.success(resData); + reslove(resData); + }; + } else { + uni.request({ + url: tempFilePath, + method: 'GET', + responseType: 'arraybuffer', + success: res => { + resData = `data:image/png;base64,${uni.arrayBufferToBase64(res.data)}`; // 把arraybuffer转成base64 + options.success && options.success(resData); + reslove(resData); + } + }) + } + // #endif + }, + fail: function(error) { + options.fail && options.fail(error); + reject(error); + }, + complete: function(res) { + options.complete && options.complete(res); + } + }, options.componentInstance); + }, options.text.length + 100); + })()); + }, 150); + } + + createCanvas(); + }); + } + } + +})() + export default uQRCode diff --git a/components/cloud-image/cloud-image.vue b/components/cloud-image/cloud-image.vue index 3f2815937d591835950b9bb99e159a952bb0eedd..b211f1a2ed02122472da80664c1d77e4c4a72214 100644 --- a/components/cloud-image/cloud-image.vue +++ b/components/cloud-image/cloud-image.vue @@ -1,14 +1,14 @@ -