作者 Rico

初始化溯泉公众号

要显示太多修改。

为保证性能只显示 18 of 18+ 个文件。

<script>
import Vue from 'vue';
import { mapMutations, mapActions, mapState } from 'vuex';
import Wechat from './common/wechat/wechat';
import store from '@/common/store';
export default {
methods: {
//应用初始化,获取模板,获取页面路由,获取用户信息,保存用户Token并返回初始进入页面
...mapActions(['getAppInit', 'getTemplate', 'getRoutes', 'getUserInfo', 'setTokenAndBack']),
// 获取系统栏高度
async setAppInfo() {
let that = this;
let platform = '';
return new Promise((resolve, reject) => {
uni.getSystemInfo({
success: function(e) {
Vue.prototype.StatusBar = e.statusBarHeight;
// #ifdef H5
Vue.prototype.CustomBar = e.statusBarHeight + 45;
if (that.$wxsdk.isWechat()) {
platform = 'wxOfficialAccount';
} else {
platform = 'H5';
}
// #endif
// #ifdef APP-PLUS
platform = 'App';
if (e.platform == 'android') {
uni.setStorageSync('isAndroid', true);
Vue.prototype.CustomBar = e.statusBarHeight + 50;
} else {
Vue.prototype.CustomBar = e.statusBarHeight + 45;
uni.setStorageSync('isAndroid', false);
}
// #endif
// #ifdef MP-WEIXIN
platform = 'wxMiniProgram';
new Wechat().getWxMiniProgramSessionKey();
let custom = wx.getMenuButtonBoundingClientRect();
Vue.prototype.Custom = custom;
Vue.prototype.CustomBar = custom.bottom + custom.top - e.statusBarHeight;
// #endif
uni.setStorageSync('platform', platform);
resolve(platform);
}
});
});
},
// 自动登录
async autoLogin(data) {
let initData = data;
var wechat = new Wechat();
if (initData.wechat.autologin && !uni.getStorageSync('token')) {
// #ifdef H5
uni.setStorageSync('appid', initData.wechat.appid);
let token = await wechat.login();
this.setTokenAndBack(token);
// #endif
// #ifdef MP-WEIXIN
wechat.login();
// #endif
}
}
},
onLaunch: async function(options) {
if (options.query.mode === 'save') {
//截图模式
uni.setStorageSync('screenShot', true);
uni.setStorageSync('shop_id', options.query.shop_id);
}
// #ifdef MP-WEIXIN
if(options.scene !== 1154) {
var wechat = new Wechat();
wechat.checkMiniProgramUpdate();
}
// #endif
await this.setAppInfo();
await this.getTemplate(options);
let init = await this.getAppInit(options);
await this.autoLogin(init.data);
await this.getRoutes();
},
onShow: function() {
this.$store.commit('CART_NUM');
},
onHide: function() {}
};
</script>
<style lang="scss">
@import 'static/colorui/main.css';
@import 'static/colorui/icon.css';
@import 'static/font/shopro-icon.css';
// 其他scss集成在uni.scss,(变量,class,minix)
uni-radio:not([disabled]) .uni-radio-input:hover,
uni-checkbox:not([disabled]) .uni-checkbox-input:hover {
border-color: #ccc !important;
}
page {
-webkit-overflow-scrolling: touch; //ios滑动不流畅
height: 100%;
background: #f6f6f6;
width: 100%;
font-size: 30upx;
font-family: NotoSansHans-Bold;
word-break: break-all; //英文文本不换行
color: #333;
}
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
display: none;
}
</style>
... ...
不能预览此文件类型
不能预览此文件类型
/**
* Wechat v1.0.2
* @description shopro-wechat 1.0.2 wehcat全局分享组件
* @Author llidongtony
* @Date 2020-05-18
* @Email lidongtony@qq.com
*/
import store from '@/common/store'
import api from '@/common/request/index'
import Router from '@/common/router'
// #ifdef H5
import wxsdk from '@/common/wechat/sdk'
// #endif
export default {
data() {
return {
//设置默认的分享参数
shareInfo: {
title: '', //分享标题
path: '', //转发链接 小程序转发只有页面链接和参数,其他全部带域名
imageUrl: '', //分享图片
copyLink: '' //复制链接地址 复制的链接都是WAP版链接地址
}
}
},
onLoad(options) {
let that = this;
//为每个页面设置分享信息
that.setShareInfo();
//直接进入页面
if (options.page) {
let page = decodeURIComponent(options.page);
uni.navigateTo({
url: page
})
}
//用户进入识别判断流程
// 1.解析进入信息
if (options.scene) {
let scene = decodeURIComponent(options.scene);
options.url = this.getQueryValue('url', scene);
options.share_id = this.getQueryValue('share_id', scene);
}
// 2.保存推荐人信息
if (options.share_id) {
uni.setStorageSync('share_id', options.share_id);
if (options.url) {
let url = options.url;
uni.setStorageSync('url', url);
}
store.dispatch('getUserInfo'); //实时触发获取用户信息,添加推广记录
}
// 3.识别分享后跳转路径 如果当前页面是首页才自动跳转 此处为了兼容小程序分享朋友圈时无脑跳转分享路径的情况,防止二次跳转落地页
if (options.url && getCurrentPages()[0].route == 'pages/index/index') {
let url = options.url;
uni.setStorageSync('url', url);
if (url.indexOf('-') > -1) {
url = url.split('-');
switch (url[0]) {
case 'goods': //跳转商品
this.$Router.push({
path: '/pages/goods/detail/index',
query: {
id: url[1]
}
});
break;
case 'groupon':
this.$Router.push({
path: '/pages/activity/groupon/detail',
query: {
id: url[1]
}
});
break;
// ... 后续跳转活动判断
}
}
}
},
methods: {
setShareInfo(scene = {
title: '', //自定义分享标题
image: '', //自定义分享图片
query: {} //自定义分享参数
}) {
let that = this;
uni.getStorage({
key: 'shareInfo',
success(e) {
var defaultShareInfo = e.data;
var platform = uni.getStorageSync('platform');
var domain = uni.getStorageSync('sysInfo')['domain'];
if (domain === '' || defaultShareInfo.title === '' || defaultShareInfo.image === '') {
throw '请在商城配置中设置商城域名或分享信息'
}
//设置自定义分享标题
if (scene.title != '') {
that.shareInfo.title = scene.title;
} else {
that.shareInfo.title = defaultShareInfo.title;
}
//设置分享图片
if (scene.image != '') {
that.shareInfo.imageUrl = scene.image;
} else {
that.shareInfo.imageUrl = defaultShareInfo.image;
}
//判断用户登录 携带用户信息
let userInfo = store.state.user.userInfo;
if (userInfo && userInfo.id) {
scene.query.share_id = userInfo.id
}
//构造query参数链接
that.shareInfo.path = ''
let urlQuery = that.setPathQuery(scene.query);
// #ifdef MP-WEIXIN
that.shareInfo.path = 'pages/index/index' + urlQuery;
that.shareInfo.copyLink = domain + urlQuery;
// #endif
// #ifndef MP-WEIXIN
that.shareInfo.path = domain + urlQuery;
that.shareInfo.copyLink = domain + urlQuery;
// #endif
//微信网页 使用jssdk分享 此处针对没有交互就进行任意页面分享转发的微信公众号用户,需针对每个页面url路径都进行注册
// #ifdef H5
if (platform === 'wxOfficialAccount') {
wxsdk.share(that.shareInfo);
}
// #endif
}
})
},
// 全局自定义url字符串拼接的方法
setPathQuery(query) {
var url = this.shareInfo.path;
if (JSON.stringify(query) != '{}') {
let queryArr = [];
for (const key in query) {
if (query.hasOwnProperty(key)) {
if (key === 'url') {
queryArr.push(`${key}=${encodeURIComponent(query[key])}`)
} else {
queryArr.push(`${key}=${query[key]}`)
}
}
}
if (url.indexOf('?') !== -1) {
url = `${url}&${queryArr.join('&')}`
} else {
url = `${url}?${queryArr.join('&')}`
}
}
return url;
},
getQueryValue(queryName, scene) {
var query = decodeURI(scene);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == queryName) {
return pair[1];
}
}
return false;
}
},
// #ifdef MP-WEIXIN
onShareAppMessage(res) {
let that = this;
return {
title: that.shareInfo.title,
path: that.shareInfo.path,
imageUrl: that.shareInfo.imageUrl,
success(res) {
uni.showToast({
title: '分享成功'
})
},
fail(res) {
uni.showToast({
title: '分享失败',
icon: 'none'
})
},
complete() {}
}
},
onShareTimeline(res) {
let that = this;
let query = '';
//携带当前页面资源ID参数
let currentPage = getCurrentPages()[getCurrentPages().length - 1];
let options = currentPage.options;
if(JSON.stringify(options) != '{}' && options.id) {
query += `id=${options.id}`;
}
let shareInfoUrl = that.shareInfo.path.split('?');
if(shareInfoUrl.length > 1) {
if(query !== '') {
query += '&';
}
query += shareInfoUrl[1];
}
return {
title: that.shareInfo.title,
query: query,
imageUrl: that.shareInfo.imageUrl,
success(res) {
uni.showToast({
title: '分享成功'
})
},
fail(res) {
uni.showToast({
title: '分享失败',
icon: 'none'
})
},
complete() {}
}
}
// #endif
}
... ...
/// null = 未请求,1 = 已允许,0 = 拒绝|受限, 2 = 系统未开启
var isIOS
function album() {
var result = 0;
var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
var authStatus = PHPhotoLibrary.authorizationStatus();
if (authStatus === 0) {
result = null;
} else if (authStatus == 3) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(PHPhotoLibrary);
return result;
}
function camera() {
var result = 0;
var AVCaptureDevice = plus.ios.import("AVCaptureDevice");
var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');
if (authStatus === 0) {
result = null;
} else if (authStatus == 3) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(AVCaptureDevice);
return result;
}
function location() {
var result = 0;
var cllocationManger = plus.ios.import("CLLocationManager");
var enable = cllocationManger.locationServicesEnabled();
var status = cllocationManger.authorizationStatus();
if (!enable) {
result = 2;
} else if (status === 0) {
result = null;
} else if (status === 3 || status === 4) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(cllocationManger);
return result;
}
function push() {
var result = 0;
var UIApplication = plus.ios.import("UIApplication");
var app = UIApplication.sharedApplication();
var enabledTypes = 0;
if (app.currentUserNotificationSettings) {
var settings = app.currentUserNotificationSettings();
enabledTypes = settings.plusGetAttribute("types");
if (enabledTypes == 0) {
result = 0;
console.log("推送权限没有开启");
} else {
result = 1;
console.log("已经开启推送功能!")
}
plus.ios.deleteObject(settings);
} else {
enabledTypes = app.enabledRemoteNotificationTypes();
if (enabledTypes == 0) {
result = 3;
console.log("推送权限没有开启!");
} else {
result = 4;
console.log("已经开启推送功能!")
}
}
plus.ios.deleteObject(app);
plus.ios.deleteObject(UIApplication);
return result;
}
function contact() {
var result = 0;
var CNContactStore = plus.ios.import("CNContactStore");
var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
if (cnAuthStatus === 0) {
result = null;
} else if (cnAuthStatus == 3) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(CNContactStore);
return result;
}
function record() {
var result = null;
var avaudiosession = plus.ios.import("AVAudioSession");
var avaudio = avaudiosession.sharedInstance();
var status = avaudio.recordPermission();
console.log("permissionStatus:" + status);
if (status === 1970168948) {
result = null;
} else if (status === 1735552628) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(avaudiosession);
return result;
}
function calendar() {
var result = null;
var EKEventStore = plus.ios.import("EKEventStore");
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
if (ekAuthStatus == 3) {
result = 1;
console.log("日历权限已经开启");
} else {
console.log("日历权限没有开启");
}
plus.ios.deleteObject(EKEventStore);
return result;
}
function memo() {
var result = null;
var EKEventStore = plus.ios.import("EKEventStore");
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
if (ekAuthStatus == 3) {
result = 1;
console.log("备忘录权限已经开启");
} else {
console.log("备忘录权限没有开启");
}
plus.ios.deleteObject(EKEventStore);
return result;
}
function requestIOS(permissionID) {
return new Promise((resolve, reject) => {
switch (permissionID) {
case "push":
resolve(push());
break;
case "location":
resolve(location());
break;
case "record":
resolve(record());
break;
case "camera":
resolve(camera());
break;
case "album":
resolve(album());
break;
case "contact":
resolve(contact());
break;
case "calendar":
resolve(calendar());
break;
case "memo":
resolve(memo());
break;
default:
resolve(0);
break;
}
});
}
function requestAndroid(permissionID) {
return new Promise((resolve, reject) => {
plus.android.requestPermissions(
[permissionID],
function(resultObj) {
var result = 0;
for (var i = 0; i < resultObj.granted.length; i++) {
var grantedPermission = resultObj.granted[i];
console.log('已获取的权限:' + grantedPermission);
result = 1
}
for (var i = 0; i < resultObj.deniedPresent.length; i++) {
var deniedPresentPermission = resultObj.deniedPresent[i];
console.log('拒绝本次申请的权限:' + deniedPresentPermission);
result = 0
}
for (var i = 0; i < resultObj.deniedAlways.length; i++) {
var deniedAlwaysPermission = resultObj.deniedAlways[i];
console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
result = -1
}
resolve(result);
},
function(error) {
console.log('result error: ' + error.message)
resolve({
code: error.code,
message: error.message
});
}
);
});
}
function gotoAppPermissionSetting() {
if (permission.isIOS) {
var UIApplication = plus.ios.import("UIApplication");
var application2 = UIApplication.sharedApplication();
var NSURL2 = plus.ios.import("NSURL");
var setting2 = NSURL2.URLWithString("app-settings:");
application2.openURL(setting2);
plus.ios.deleteObject(setting2);
plus.ios.deleteObject(NSURL2);
plus.ios.deleteObject(application2);
} else {
var Intent = plus.android.importClass("android.content.Intent");
var Settings = plus.android.importClass("android.provider.Settings");
var Uri = plus.android.importClass("android.net.Uri");
var mainActivity = plus.android.runtimeMainActivity();
var intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
intent.setData(uri);
mainActivity.startActivity(intent);
}
}
const permission = {
get isIOS(){
return typeof isIOS === 'boolean' ? isIOS : (isIOS = uni.getSystemInfoSync().platform === 'ios')
},
requestIOS: requestIOS,
requestAndroid: requestAndroid,
gotoAppSetting: gotoAppPermissionSetting
}
module.exports = permission
... ...
import Request from './request'
import apiList from './shopro'
import store from '@/common/store/index.js'
export default function api(url, data = {}) {
const request = new Request();
let api = getApiObj(url);
request.interceptor.request((config, cancel) => { /* 请求之前拦截器 */
if (api.auth) {
let token = uni.getStorageSync('token');
if (!token) {
store.commit('LOGIN_TIP', true)
store.commit('OUT_LOGIN');
throw('暂未登录,已阻止此次API请求~');
}
}
if (uni.getStorageSync('token')) {
config.header.token = uni.getStorageSync('token');
}
return config
});
request.interceptor.response((response) => { /* 请求之后拦截器 */
if (response.data.code === 0) { // 服务端返回的状态码不等于200,则reject()
uni.showToast({
title: response.data.msg || '请求出错,稍后重试',
icon: 'none',
duration: 1000,
mask: true
});
}
if (response.data.code === 401) { // 服务端返回的状态码不等于200,则reject()
uni.removeStorageSync('token');
store.commit('LOGIN_TIP', true)
}
// if (response.config.custom.verification) { // 演示自定义参数的作用
// return response.data
// }
return response
}, (response) => { // 预留可以日志上报
return response
})
return request.request({
url: api.url,
data,
method: api.method
})
}
function getApiObj(url) {
let apiArray = url.split(".");
let api = apiList;
apiArray.forEach(v => {
api = api[v];
});
return api;
}
... ...
import {
API_URL
} from '@/env'
export default class Request {
config = {
baseUrl: API_URL,
header: {
'content-type': 'application/json',
'platform': uni.getStorageSync('platform'),
},
method: 'GET',
dataType: 'json',
// #ifndef MP-ALIPAY || APP-PLUS
responseType: 'text',
// #endif
custom: {},
// #ifdef MP-ALIPAY
timeout: 30000,
// #endif
// #ifdef APP-PLUS
sslVerify: false
// #endif
}
static posUrl(url) { /* 判断url是否为绝对路径 */
return /(http|https):\/\/([\w.]+\/?)\S*/.test(url)
}
static addQueryString(params) {
let paramsData = ''
Object.keys(params).forEach(function(key) {
paramsData += key + '=' + encodeURIComponent(params[key]) + '&'
})
return paramsData.substring(0, paramsData.length - 1)
}
/**
* @property {Function} request 请求拦截器
* @property {Function} response 响应拦截器
* @type {{request: Request.interceptor.request, response: Request.interceptor.response}}
*/
interceptor = {
/**
* @param {Request~requestCallback} cb - 请求之前拦截,接收一个函数(config, cancel)=> {return config}。第一个参数为全局config,第二个参数为函数,调用则取消本次请求。
*/
request: (cb) => {
if (cb) {
this.requestBeforeFun = cb
}
},
/**
* @param {Request~responseCallback} cb 响应拦截器,对响应数据做点什么
* @param {Request~responseErrCallback} ecb 响应拦截器,对响应错误做点什么
*/
response: (cb, ecb) => {
if (cb && ecb) {
this.requestComFun = cb
this.requestComFail = ecb
}
}
}
requestBeforeFun(config) {
return config
}
requestComFun(response) {
return response
}
requestComFail(response) {
return response
}
/**
* 自定义验证器,如果返回true 则进入响应拦截器的响应成功函数(resolve),否则进入响应拦截器的响应错误函数(reject)
* @param { Number } statusCode - 请求响应体statusCode(只读)
* @return { Boolean } 如果为true,则 resolve, 否则 reject
*/
validateStatus(statusCode) {
return statusCode === 200
}
/**
* @Function
* @param {Request~setConfigCallback} f - 设置全局默认配置
*/
setConfig(f) {
this.config = f(this.config)
}
/**
* @Function
* @param {Object} options - 请求配置项
* @prop {String} options.url - 请求路径
* @prop {Object} options.data - 请求参数
* @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
* @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
* @prop {Object} [options.header = config.header] - 请求header
* @prop {Object} [options.method = config.method] - 请求方法
* @returns {Promise<unknown>}
*/
async request(options = {}) {
options.baseUrl = this.config.baseUrl
options.dataType = options.dataType || this.config.dataType
// #ifndef MP-ALIPAY || APP-PLUS
options.responseType = options.responseType || this.config.responseType
// #endif
// #ifdef MP-ALIPAY
options.timeout = options.timeout || this.config.timeout
// #endif
options.url = options.url || ''
options.data = options.data || {}
options.params = options.params || {}
options.header = options.header || this.config.header
options.method = options.method || this.config.method
options.custom = { ...this.config.custom,
...(options.custom || {})
}
// #ifdef APP-PLUS
options.sslVerify = options.sslVerify === undefined ? this.config.sslVerify : options.sslVerify
// #endif
// uni.showToast({
// icon: "loading",
// image: "/static/imgs//logo/logo.gif"
// })
return new Promise((resolve, reject) => {
let next = true
let handleRe = {}
options.complete = (response) => {
response.config = handleRe
if (this.validateStatus(response.statusCode)) { // 成功
response = this.requestComFun(response)
resolve(response.data)
} else if (401 === response.statusCode) {
response = this.requestComFun(response)
resolve(response.data)
} else if (500 === response.statusCode) {
resolve(response.data)
} else {
response = this.requestComFail(response)
reject(response)
}
}
const cancel = (t = 'handle cancel', config = options) => {
const err = {
errMsg: t,
config: config
}
reject(err)
next = false
}
handleRe = { ...this.requestBeforeFun(options, cancel)
}
const _config = { ...handleRe
}
if (!next) return
delete _config.custom
let mergeUrl = Request.posUrl(_config.url) ? _config.url : (_config.baseUrl + _config.url)
if (JSON.stringify(_config.params) !== '{}') {
const paramsH = Request.addQueryString(_config.params);
mergeUrl += mergeUrl.indexOf('?') === -1 ? `?${paramsH}` : `&${paramsH}`
}
_config.url = mergeUrl
uni.request(_config)
})
}
get(url, options = {}) {
return this.request({
url,
method: 'GET',
...options
})
}
post(url, data, options = {}) {
return this.request({
url,
data,
method: 'POST',
...options
})
}
upload(url, {
// #ifdef APP-PLUS
files,
// #endif
// #ifdef MP-ALIPAY
fileType,
// #endif
filePath,
name,
header,
formData,
custom
}) {
return new Promise((resolve, reject) => {
let next = true
let handleRe = {}
const globalHeader = { ...this.config.header
}
delete globalHeader['content-type']
const pubConfig = {
baseUrl: this.config.baseUrl,
url,
// #ifdef APP-PLUS
files,
// #endif
// #ifdef MP-ALIPAY
fileType,
// #endif
filePath,
method: 'UPLOAD',
name,
header: header || globalHeader,
formData,
custom: { ...this.config.custom,
...(custom || {})
},
complete: (response) => {
response.config = handleRe
if (response.statusCode === 200) { // 成功
response = this.requestComFun(response)
resolve(response)
} else {
response = this.requestComFail(response)
reject(response)
}
}
}
const cancel = (t = 'handle cancel', config = pubConfig) => {
const err = {
errMsg: t,
config: config
}
reject(err)
next = false
}
handleRe = { ...this.requestBeforeFun(pubConfig, cancel)
}
const _config = { ...handleRe
}
if (!next) return
delete _config.custom
_config.url = Request.posUrl(_config.url) ? _config.url : (_config.baseUrl + _config.url)
uni.uploadFile(_config)
})
}
}
/**
* setConfig回调
* @return {Object} - 返回操作后的config
* @callback Request~setConfigCallback
* @param {Object} config - 全局默认config
*/
/**
* 请求拦截器回调
* @return {Object} - 返回操作后的config
* @callback Request~requestCallback
* @param {Object} config - 全局config
* @param {Function} [cancel] - 取消请求钩子,调用会取消本次请求
*/
/**
* 响应拦截器回调
* @return {Object} - 返回操作后的response
* @callback Request~responseCallback
* @param {Object} response - 请求结果 response
*/
/**
* 响应错误拦截器回调
* @return {Object} - 返回操作后的response
* @callback Request~responseErrCallback
* @param {Object} response - 请求结果 response
*/
... ...
/**
* 接口列表文件
*/
export default {
/** 初始化 ↓ **/
init: {
url: 'index/init',
auth: false,
method: 'GET',
// desc: '初始化数据',
},
/** 上传图片 ↓ **/
upload: {
url: 'index/upload',
auth: true,
method: 'POST',
// desc: '上传',
},
/** 上传Base64图片 ↓ **/
uploadBase64: {
url: 'index/uploadBase64',
auth: false,
method: 'POST',
// desc: '上传Base64位图片',
},
/** 消息订阅模板 ↓ **/
messageIds: {
url: 'notification/template',
auth: true,
method: 'GET',
// desc: '订阅消息模板ids',
},
/** 模板信息 ↓ **/
template: {
url: 'index/template',
auth: false,
method: 'GET',
// desc: '模板信息',
},
/** 自定义模板页面 ↓ **/
custom: {
url: 'index/custom',
auth: false,
method: 'GET',
// desc: '自定义模板页面',
},
/** 直播 ↓ **/
live: {
url: 'live',
auth: false,
method: 'GET',
// desc: '直播列表',
},
/** 微信Jssdk ↓ **/
wechat: {
jssdk: {
url: 'wechat/jssdk',
auth: false,
method: 'POST',
// desc: '微信Jssdk',
},
},
/** 签到 ↓ **/
user_sign: {
index: {
url: 'user_sign/index',
auth: true,
method: 'GET',
// desc: '签到记录',
},
sign: {
url: 'user_sign/sign',
auth: true,
method: 'POST',
// desc: '签到',
}
},
/** 同步路由 ↓ **/
dev: {
asyncLink: {
url: 'index/asyncLink',
auth: false,
method: 'POST',
// desc: '路由表',
},
asyncDecorateScreenShot: {
url: 'index/asyncDecorateScreenShot',
auth: false,
method: 'POST',
// desc: '更新店铺装修截图',
},
asyncBannerBgColor: {
url: 'index/asyncBannerBgColor',
auth: false,
method: 'POST',
// desc: '路由表',
},
debug: {
url: 'index/debugLog',
auth: false,
method: 'POST',
}
},
/** 富文本 ↓ **/
richtext: {
url: 'index/richtext',
auth: false,
method: 'GET',
// desc: '富文本数据',
},
/** 三级分类 ↓ **/
category: {
url: 'category',
auth: false,
method: 'GET',
// desc: '三级分类',
},
/** 二级分类 ↓ **/
categoryGoods: {
url: 'category/goods',
auth: false,
method: 'GET',
// desc: '点餐用',
},
/** 积分商城 ↓ **/
score: {
list: {
url: 'score_goods_sku_price/index',
auth: false,
method: 'GET',
// desc: '积分商品列表',
},
detail: {
url: 'score_goods_sku_price/detail',
auth: false,
method: 'GET',
// desc: '积分详情',
},
},
/** 商户 ↓ **/
store: {
list: {
url: 'store/index',
auth: true,
method: 'GET',
// desc: '商户列表,不需要storeId',
},
info: {
url: 'store.store/index',
auth: true,
method: 'GET',
// desc: '商户信息',
},
order: {
url: 'store.order/index',
auth: true,
method: 'GET',
// desc: '商户订单',
},
orderDetail: {
url: 'store.order/detail',
auth: true,
method: 'GET',
// desc: '订单详情',
},
orderSend: {
url: 'store.order/send',
auth: true,
method: 'POST',
// desc: '订单发货',
},
orderConfirm: {
url: 'store.order/confirm',
auth: true,
method: 'POST',
// desc: '核销订单',
},
},
/** 商品评论 ↓ **/
goods_comment: {
list: {
url: 'goods_comment/index',
auth: false,
method: 'GET',
// desc: '商品评论列表',
},
type: {
url: 'goods_comment/type',
auth: false,
method: 'GET',
// desc: '商品评论分类',
},
},
/** 商品 ↓ **/
goods: {
lists: {
url: 'goods/lists',
auth: false,
method: 'GET',
// desc: '商品列表',
},
seckillList: {
url: 'goods/seckillList',
auth: false,
method: 'GET',
// desc: '秒杀列表',
},
activity: {
url: 'goods/activity',
auth: false,
method: 'GET',
// desc: '活动商品',
},
myGroupon: {
url: 'activity_groupon/myGroupon',
auth: true,
method: 'GET',
// desc: '我的拼团',
},
grouponDetail: {
url: 'activity_groupon/detail',
auth: true,
method: 'GET',
// desc: '拼团详情',
},
grouponItem: {
url: 'activity_groupon/index',
auth: false,
method: 'GET',
// desc: '拼购列表',
},
grouponList: {
url: 'goods/grouponList',
auth: false,
method: 'GET',
// desc: '拼团商品列表',
},
detail: {
url: 'goods/detail',
auth: false,
method: 'GET',
// desc: '商品详情',
},
favorite: {
url: 'goods/favorite',
auth: true,
method: 'POST',
// desc: '商品收藏',
},
favoriteList: {
url: 'goods/favoriteList',
auth: true,
method: 'GET',
// desc: '商品收藏列表',
},
viewList: {
url: 'goods/viewList',
auth: true,
method: 'GET',
// desc: '足迹列表',
},
viewDelete: {
url: 'goods/viewDelete',
auth: true,
method: 'POST',
// desc: '删除足迹',
},
storeAddress: {
url: 'goods/store',
auth: true,
method: 'GET',
// desc: '商品支持的自提点',
},
},
/** 用户 ↓ **/
user: {
info: {
url: 'user',
auth: true,
method: 'GET',
// desc: '用户信息',
},
profile: {
url: 'user/profile',
auth: true,
method: 'POST',
// desc: '修改用户信息',
},
changemobile: {
url: 'user/changemobile',
auth: true,
method: 'POST',
// desc: '修改手机号',
},
changepwd: {
url: 'user/changepwd',
auth: true,
method: 'POST',
// desc: '修改密码',
},
resetpwd: {
url: 'user/resetpwd',
auth: false,
method: 'POST',
// desc: '重置密码',
},
mobileLogin: {
url: 'user/mobileLogin',
auth: false,
method: 'POST',
// desc: '手机验证码登录',
},
accountLogin: {
url: 'user/accountLogin',
auth: false,
method: 'POST',
// desc: '账号密码登录',
},
getWxMiniProgramSessionKey: {
url: 'user/getWxMiniProgramSessionKey',
auth: false,
method: 'POST',
// desc: '获取用户session_key',
},
wxMiniProgramLogin: {
url: 'user/wxMiniProgramLogin',
auth: false,
method: 'POST',
// desc: '微信小程序登录',
},
wxOpenPlatformLogin: {
url: 'user/wxOpenPlatformLogin',
auth: false,
method: 'POST',
// desc: '微信APP登录',
},
register: {
url: 'user/register',
auth: false,
method: 'POST',
// desc: '用户注册',
},
forgot: {
url: 'user/forgot',
auth: false,
method: 'POST',
// desc: '忘记密码',
},
},
/** 分享 ↓ **/
share: {
add: {
url: 'share/add',
auth: false,
method: 'POST',
// desc: '添加分享记录',
}
},
/** 位置 ↓ **/
address: {
area: {
url: 'address/area',
auth: false,
method: 'GET',
// desc: '省市区',
},
list: {
url: 'address',
auth: true,
method: 'GET',
// desc: '地址列表',
},
edit: {
url: 'address/edit',
auth: true,
method: 'POST',
// desc: '修改地址',
},
defaults: {
url: 'address/defaults',
auth: true,
method: 'GET',
// desc: '默认地址',
},
info: {
url: 'address/info',
auth: true,
method: 'GET',
// desc: '地址详情',
},
del: {
url: 'address/del',
auth: true,
method: 'POST',
// desc: '删除',
},
},
/** 短信 ↓ **/
sms: {
send: {
url: 'sms/send',
auth: false,
method: 'POST',
// desc: '发送短信',
},
},
/** 常见问题 ↓ **/
faq: {
list: {
url: 'faq',
auth: false,
method: 'GET',
// desc: '常见问题列表',
},
},
/** 意见反馈 ↓ **/
feedback: {
type: {
url: 'feedback/type',
auth: true,
method: 'GET',
// desc: '意见反馈类型',
},
add: {
url: 'feedback/add',
auth: true,
method: 'POST',
// desc: '提交意见',
},
},
/** 购物车 ↓ **/
cart: {
index: {
url: 'cart',
auth: true,
method: 'POST',
// desc: '购物车商品列表',
},
add: {
url: 'cart/add',
auth: true,
method: 'POST',
// desc: '添加购物车',
},
edit: {
url: 'cart/edit',
auth: true,
method: 'POST',
// desc: '编辑购物车',
},
},
/** 订单 ↓ **/
order: {
index: {
url: 'order/index',
auth: true,
method: 'GET',
// desc: '订单列表',
},
pre: {
url: 'order/pre',
auth: true,
method: 'POST',
// desc: '预备提交订单',
},
createOrder: {
url: 'order/createOrder',
auth: true,
method: 'POST',
// desc: '提交订单',
},
detail: {
url: 'order/detail',
auth: true,
method: 'GET',
// desc: '订单详情',
},
itemDetail: {
url: 'order/itemDetail',
auth: true,
method: 'GET',
// desc: '订单商品详情',
},
confirm: {
url: 'order/confirm',
auth: true,
method: 'POST',
// desc: '确认收货',
},
refund: {
url: 'order/refund',
auth: true,
method: 'POST',
// desc: '申请退款',
},
cancel: {
url: 'order/cancel',
auth: true,
method: 'POST',
// desc: '取消订单',
},
statusNum: {
url: 'order/statusNum',
auth: true,
method: 'GET',
// desc: '订单dot',
},
comment: {
url: 'order/comment',
auth: true,
method: 'POST',
// desc: '评价商品',
},
coupons: {
url: 'order/coupons',
auth: true,
method: 'POST',
// desc: '商品可用优惠券',
},
aftersale: {
url: 'order_aftersale/aftersale',
auth: true,
method: 'POST',
// desc: '申请售后',
},
aftersaleList: {
url: 'order_aftersale/index',
auth: true,
method: 'GET',
// desc: '售后列表',
},
aftersaleDetail: {
url: 'order_aftersale/detail',
auth: true,
method: 'GET',
// desc: '售后列表详情',
},
deleteOrder: {
url: 'order/delete',
auth: true,
method: 'POST',
// desc: '删除订单',
},
deleteAftersaleOrder: {
url: 'order_aftersale/delete',
auth: true,
method: 'POST',
// desc: '删除售后订单',
},
cancelAftersaleOrder: {
url: 'order_aftersale/cancel',
auth: true,
method: 'POST',
// desc: '取消售后订单',
},
expressList: {
url: 'order_express/index',
auth: true,
method: 'GET',
// desc: '包裹列表',
},
expressDetail: {
url: 'order_express/detail',
auth: true,
method: 'GET',
// desc: '包裹详情',
},
itemDetail: {
url: 'order/itemDetail',
auth: true,
method: 'GET',
// desc: '订单商品详情',
}
},
/** 支付 ↓ **/
pay: {
prepay: {
url: 'pay/prepay',
auth: true,
method: 'POST',
// desc: '发起支付',
},
},
/** 提现 ↓ **/
user_wallet_apply: {
apply: {
url: 'user_wallet_apply/apply',
auth: true,
method: 'POST',
// desc: '申请提现',
},
rule: {
url: 'user_wallet_apply/rule',
auth: true,
method: 'GET',
// desc: '体现规则',
}
},
/** 钱包明细 ↓ **/
user_wallet_log: {
url: 'user_wallet_log',
auth: true,
method: 'GET',
// desc: '钱包明细',
},
/** 银行卡 ↓ **/
user_bank: {
info: {
url: 'user_bank/info',
auth: true,
method: 'GET',
// desc: '银行卡信息',
},
edit: {
url: 'user_bank/edit',
auth: true,
method: 'POST',
// desc: '编辑银行卡信息',
}
},
/** 评论 ↓ **/
comment: {
submit: {
url: 'comment/submit',
auth: true,
method: 'POST',
// desc: '提交评论',
},
list: {
url: 'comment/list',
auth: true,
method: 'GET',
// desc: '评论列表',
}
},
/** 优惠券 ↓ **/
coupons: {
list: {
url: 'coupons',
auth: true,
method: 'GET',
// desc: '个人中心优惠券列表',
},
lists: {
url: 'coupons/lists',
auth: false,
method: 'GET',
// desc: '首页优惠券',
},
get: {
url: 'coupons/get',
auth: true,
method: 'GET',
// desc: '领取',
},
detail: {
url: 'coupons/detail',
auth: true,
method: 'GET',
// desc: '购物券详情',
},
goods: {
url: 'coupons/goods',
auth: true,
method: 'GET',
// desc: '适用商品',
}
},
};
... ...
import Vue from 'vue'
import Router from 'uni-simple-router'
import store from '@/common/store'
Vue.use(Router)
//初始化
const router = new Router({
APP: {
animation: {
animationType: 'pop-in',
animationDuration: 300
}
},
encodeURI: false,
routes: ROUTES //路由表
});
//全局路由前置守卫
router.beforeEach((to, from, next) => {
// 有两个个判断条件,一个是token,还有一个路由元信息
let userInfo = Boolean(uni.getStorageSync('userInfo'));
// 权限控制
if (to.meta && to.meta.auth && !userInfo) {
store.commit('LOGIN_TIP', true)
} else {
next()
}
})
// 全局路由后置守卫
router.afterEach((to, from) => {})
export default router;
... ...
/**
* ShoproPay v1.0.0
* @Class ShoproPay
* @description shopro-pay 1.0.0 统一支付
* @Author llidongtony
* @Date 2020-04-09
* @Email lidongtony@qq.com
*/
import api from '@/common/request/index'
import store from '@/common/store'
import tools from '@/common/utils/tools'
// #ifdef H5
import wxsdk from '@/common/wechat/sdk'
import Wechat from '@/common/wechat/wechat'
// #endif
import Router from '@/common/router';
export default class ShoproPay {
// wxOfficialAccount wxMiniProgram App H5
// wechat 公众号JSSDK支付 小程序支付 微信开放平台支付 H5网页支付
// alipay 复制网址 复制网址 支付宝开放平台支付 直接跳转链接
// wallet v v v v
constructor(payment, order) {
this.payment = payment;
this.order = order;
this.platform = uni.getStorageSync('platform');
let payMehod = this.getPayMethod();
payMehod();
}
getPayMethod() {
var payMethod = {
'wxOfficialAccount': {
'wechat': () => {
this.wxOfficialAccountPay()
},
'alipay': () => {
this.copyPayLink()
},
'wallet': () => {
this.walletPay()
}
},
'wxMiniProgram': {
'wechat': () => {
this.wxMiniProgramPay()
},
'alipay': () => {
this.copyPayLink()
},
'wallet': () => {
this.walletPay()
}
},
'App': {
'wechat': () => {
this.wechatPay()
},
'alipay': () => {
this.aliPay()
},
'wallet': () => {
this.walletPay()
},
},
'H5': {
'wechat': () => {
this.wechatWapPay()
},
'alipay': () => {
this.goToPayLink()
},
'wallet': () => {
this.walletPay()
},
},
}
return payMethod[this.platform][this.payment];
}
prepay() {
let that = this;
uni.showLoading({
title: '支付中',
mask: true
});
return new Promise((resolve, reject) => {
let that = this;
let params = {
order_sn: that.order.order_sn,
payment: that.payment
}
if (uni.getStorageSync('openid')) {
params.openid = uni.getStorageSync('openid');
}
api('pay.prepay', params).then(res => {
if (res.code === 1) {
if (res.data === 'no_openid') {
uni.showModal({
title: '微信支付',
content: '点击确定后请再次使用微信支付',
success: function(res) {
if (res.confirm) {
//静默获取openid
let wechat = new Wechat();
wechat.wxOfficialAccountBaseLogin();
} else if (res.cancel) {
console.log('用户点击取消');
}
},
fail: (err) => {
uni.hideLoading();
}
});
} else {
uni.hideLoading();
resolve(res);
}
} else {
uni.hideLoading();
uni.showToast({
title: res.msg,
icon: 'none'
})
}
})
});
}
async wxOfficialAccountPay() {
let that = this;
let result = await this.prepay();
wxsdk.wxpay(result.data.pay_data, (res) => {
if (res.errMsg == "chooseWXPay:ok") {
Router.replace({
path: '/pages/order/payment/result',
query: {
orderSn: that.order.order_sn,
type: that.payment,
pay: 1
}
});
} else if (res.errMsg === 'chooseWXPay:cancel') {
//取消支付
} else {
Router.replace({
path: '/pages/order/payment/result',
query: {
orderSn: that.order.order_sn,
type: that.payment,
pay: 0
}
});
}
});
}
//
async wechatWapPay() {
let that = this;
let result = await this.prepay();
if (result.code === 1) {
var url = result.data.pay_data.match(/url\=\'(\S*)\'/);
let reg = new RegExp('&amp;', 'g') //g代表全部
let newUrl = url[1].replace(reg, '&');
let domain = uni.getStorageSync('sysInfo').domain; //域名需要https
let params = encodeURIComponent(
`${domain}/pages/order/payment/result?orderSn=${that.order.order_sn}&type=${that.payment}&pay=1`)
window.location.href = newUrl + '&redirect_url=' + params;
}
}
async wxMiniProgramPay() {
let that = this;
let result = await this.prepay();
let payData = result.data.pay_data;
uni.requestPayment({
provider: 'wxpay',
timeStamp: payData.timeStamp,
nonceStr: payData.nonceStr,
package: payData.package,
signType: payData.signType,
paySign: payData.paySign,
success: function(res) {
Router.replace({
path: '/pages/order/payment/result',
query: {
orderSn: that.order.order_sn,
type: that.payment,
pay: 1
}
});
},
fail: function(err) {
if (err.errMsg !== "requestPayment:fail cancel") {
Router.replace({
path: '/pages/order/payment/result',
query: {
orderSn: that.order.order_sn,
type: that.payment,
pay: 0
}
});
}
}
});
}
async walletPay() {
let that = this;
let result = await this.prepay();
if (result.code === 1) {
Router.replace({
path: '/pages/order/payment/result',
query: {
orderSn: that.order.order_sn,
type: that.payment,
pay: 1
}
});
}
}
async copyPayLink() {
let that = this;
let result = await this.prepay();
if (result.code === 1) {
//引入showModal 点击确认 复制链接;
uni.showModal({
title: '支付宝支付',
content: '复制链接到外部浏览器',
confirmText: '复制链接',
success: (res) => {
if (res.confirm) {
uni.setClipboardData({
data: result.data.pay_data,
success: function(data) {
//#ifdef H5
tools.toast('已复制到剪切板');
//#endif
},
fail: function(err) {},
complete: function(res) {}
});
} else if (res.cancel) {
}
}
})
}
}
async goToPayLink() {
let that = this;
let result = await this.prepay();
if (result.code === 1) {
window.location = result.data.pay_data;
}
}
async aliPay() {
let that = this;
let result = await this.prepay();
if (result.code === 1) {
uni.requestPayment({
provider: 'alipay',
orderInfo: result.data.pay_data, //支付宝订单数据
success: function(res) {
Router.replace({
path: '/pages/order/payment/result',
query: {
orderSn: that.order.order_sn,
type: that.payment,
pay: 1
}
});
},
fail: function(err) {
if (err.errMsg !== "requestPayment:fail cancel") {
Router.replace({
path: '/pages/order/payment/result',
query: {
orderSn: that.order.order_sn,
type: that.payment,
pay: 0
}
});
}
}
});
}
}
async wechatPay() {
let that = this;
let result = await this.prepay();
if (result.code === 1) {
uni.requestPayment({
provider: 'wxpay',
orderInfo: JSON.parse(result.data.pay_data), //微信订单数据(官方说是string。实测为object)
success: function(res) {
Router.replace({
path: '/pages/order/payment/result',
query: {
orderSn: that.order.order_sn,
type: that.payment,
pay: 1
}
});
},
fail: function(err) {
if (err.errMsg !== "requestPayment:fail cancel") {
Router.replace({
path: '/pages/order/payment/result',
query: {
orderSn: that.order.order_sn,
type: that.payment,
pay: 0
}
});
}
}
});
}
}
}
... ...
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import init from './modules/init.js'
import user from './modules/user.js'
import cart from './modules/cart.js'
import theme from './modules/theme.js'
const store = new Vuex.Store({
modules: {
init,
user,
cart,
theme
}
})
export default store
... ...
// 购物车模块
import http from '@/common/request/index'
import store from '@/common/store'
import {
CART_LIST,
CART_NUM
} from '../types.js'
const state = {
cartList: [],
allSelected: false,
cartNum: uni.getStorageSync('cartNum') ? uni.getStorageSync('cartNum') : 0, //购物车,涉及到刷新数据丢失,所以存了本地,
}
const actions = {
// 购物车数据(查)
getCartList({
commit,
state
}) {
return new Promise((resolve, reject) => {
http('cart.index').then(res => {
let cartData = res.data;
cartData.map(item => {
item.checked = true;
})
uni.setStorageSync('cartNum', cartData.length);
commit('CART_LIST', cartData);
commit('checkCartList');
commit('CART_NUM');
}).catch(e => {
reject(e)
})
})
},
// 添加到购物车(增)
addCartGoods({
commit
}, data) {
return new Promise((resolve, reject) => {
http('cart.add', {
goods_list: data.list,
from: data.from
}).then(res => {
store.dispatch('getCartList');
resolve(res)
}).catch(e => {
reject(e)
})
})
},
// 修改购物车商品数量(改)|| 删除购物车商品(删)
changeCartList({
commit,
state,
dispatch
}, param) {
return new Promise((resolve, reject) => {
http('cart.edit', {
cart_list: param.ids,
value: param.goodsNum || null,
act: param.art
}).then(res => {
if (param.art === 'delete' && res.code === 1) {
store.dispatch('getCartList');
}
resolve(res)
commit('checkCartList');
}).catch(e => {
reject(e)
})
})
},
}
const mutations = {
// cart数据获取变动。
[CART_LIST](state, data) {
state.cartList = data
},
// cart数量角标更新。
[CART_NUM](state, data) {
let cartNum = uni.getStorageSync('cartNum') ? uni.getStorageSync('cartNum') : 0;
state.cartNum = cartNum
},
// 切换全选。
changeAllSellect(state) {
state.allSelected = !state.allSelected;
},
// 全选设置
getAllSellectCartList(state, flag) {
state.cartList.map(item => {
item.checked = flag
})
},
// 单选设置
selectItem(
state, {
index,
flag
}) {
state.cartList[index].checked = !flag;
store.commit('checkCartList')
},
// 全选检测
checkCartList(state) {
let all = true;
state.cartList.map(item => {
if (!item.checked) {
all = false
}
})
state.allSelected = all;
}
}
const getters = {
// 购物车数量和总价
totalCount: state => {
let totalNum = 0;
let totalPrice = 0;
state.cartList.filter(item => {
if (item.checked) {
totalNum += 1;
totalPrice += item.goods_num * item.sku_price.price;
}
})
return {
totalNum,
totalPrice
}
},
// 外卖购物车数量和总价
takeoutTotalCount: state => {
let totalNum = 0;
let totalPrice = 0;
state.cartList.forEach(item => {
totalNum += item.goods_num;
totalPrice += item.goods_num * item.sku_price.price;
})
return {
totalNum,
totalPrice
}
},
// 是否选择了商品
isSel: state => {
let isSel = false;
state.cartList.map(item => {
if (item.checked) {
isSel = true
}
})
return isSel
}
}
export default {
state,
mutations,
actions,
getters
}
... ...
// 初始化数据模块
import api from '@/common/request/index'
import store from '@/common/store'
import Router from '@/common/router';
import {
INIT_DATA,
PAGE_ROUTES,
CART_NUM,
TEMPLATE_DATA
} from '../types.js'
const state = {
initData: {},
routes: [],
addons: uni.getStorageSync('addons') ? uni.getStorageSync('addons') : [], //插件列表
templateData: uni.getStorageSync('templateData') ? uni.getStorageSync('templateData') : {},
hasTemplate:true//是否有初始化数据
}
const actions = {
getAppInit({
commit
}, options) {
uni.setStorageSync('mode', 'product');
return new Promise((resolve, reject) => {
api('init').then(res => {
commit('INIT_DATA', res.data);
uni.setStorageSync('sysInfo', res.data.info);
uni.setStorageSync('shareInfo', res.data.share);
uni.setStorageSync('addons', res.data.addons)
resolve(res)
}).catch(e => {
reject(e)
})
})
},
// 同步前端路由
getRoutes({
commit
}) {
return new Promise((resolve, reject) => {
api('dev.asyncLink', {
data: ROUTES
}).then(res => {
commit('PAGE_ROUTES', res.data);
resolve(res)
}).catch(e => {
reject(e)
})
})
},
// 模板信息
getTemplate({
commit
}, options = {}) {
var params = {};
return new Promise((resolve, reject) => {
//请求预览商城模板
if (options.query && options.query.shop_id) {
params.shop_id = options.query.shop_id;
}
if (options.query && options.query.custom_id) {
Router.replace({
path: '/pages/index/view',
query: {
id: options.query.custom_id,
}
});
}
api('template', params).then(res => {
uni.setStorageSync('templateData', res.data);
commit('TEMPLATE_DATA', res.data);
if(res.code == 0){
commit('hasTemplate', false);
}
resolve(res)
}).catch(e => {
reject(e)
})
})
},
}
const mutations = {
[PAGE_ROUTES](state, data) {
state.routes = data
},
[INIT_DATA](state, data) {
state.initData = data
},
[TEMPLATE_DATA](state, data) {
state.templateData = data
},
hasTemplate(state, data) {
state.hasTemplate = data
},
// 弹窗一次的话,关闭的时候删除数据。
delPopup(state, path) {
uni.removeStorageSync('templateData');
let templateData = state.templateData
templateData.popup[0].content.list.forEach(item => {
if (item.page.includes(path)) {
let index = item.page.indexOf(path);
item.page.splice(index, 1)
}
})
uni.setStorageSync('templateData', templateData);
state.templateData = templateData;
}
}
const getters = {
}
export default {
state,
mutations,
actions,
getters
}
... ...
// 初始化数据模块
import http from '@/common/request/index'
let barTheme = {
'normal-theme': {
color: '#000000',
background: '#f6f6f6'
},
'dark-theme': {
color: '#ffffff',
background: '#000000'
},
'red-theme': {
color: '#8e5a54',
background: '#f9e5ee'
},
'yellow-theme': {
color: '#8c6031',
background: '#f6e1c9'
},
'green-theme': {
color: '#5d6021',
background: '#e3eabb'
},
'cyan-theme': {
color: '#417036',
background: '#d1e9cd'
},
'blue-theme': {
color: '#2e6167',
background: '#bbe4e3'
}
}
import {
SET_THEME
} from '../types.js'
const state = {
themeKey: uni.getStorageSync('themeKey') ? uni.getStorageSync('themeKey') : 'red-theme',
}
const actions = {}
const mutations = {
[SET_THEME](state, data) {
state.themeKey = data;
uni.setStorageSync('themeKey', data);
let fcolor = data == 'dark-theme' ? '#ffffff' : '#000000'; //标题字体色
let item = barTheme[data];
let tcolor = item.color;
let bcolor = item.background; //背景色。
uni.setNavigationBarColor({
frontColor: fcolor,
backgroundColor: bcolor
});
uni.setTabBarStyle({
color: tcolor, //底部默认字色
backgroundColor: bcolor, //底部背景色。
})
},
}
const getters = {
}
export default {
state,
mutations,
actions,
getters
}
... ...
// 用户数据模块
import api from '@/common/request/index'
import store from '@/common/store'
import router from '@/common/router.js'
import tools from '@/common/utils/tools'
import {
USER_INFO,
LOGIN_TIP,
ORDER_NUMBER,
MESSAGE_IDS,
OUT_LOGIN,
// #ifdef MP-WEIXIN
FORCE_OAUTH,
// #endif
} from '../types.js'
const state = {
userInfo: uni.getStorageSync('userInfo') ? uni.getStorageSync('userInfo') : {},
showLoginTip: false,
orderNum: {},
// #ifdef MP-WEIXIN
forceOauth: false,
// #endif
messageIds: {}, //小程序订阅消息模板ids
}
const actions = {
//设置token并返回上次页面
setTokenAndBack({
commit
}, token) {
uni.setStorageSync('token', token);
store.dispatch('getUserInfo');
let fromLogin = uni.getStorageSync('fromLogin');
if (fromLogin) {
tools.routerTo(fromLogin.path, fromLogin.query, true);
uni.removeStorageSync('fromLogin')
} else {
//默认跳转首页S
router.replaceAll('/pages/index/index')
}
},
// 获取用户信息
getUserInfo({
commit
}) {
return new Promise((resolve, reject) => {
api('user.info').then(res => {
store.dispatch('getCartList')
commit('LOGIN_TIP', false);
commit('USER_INFO', res.data);
uni.setStorageSync('userInfo', res.data);
store.dispatch('getOrderNum');
//添加推广记录
let share_id = uni.getStorageSync('share_id');
let url = uni.getStorageSync('url');
let shareParams = {};
// if(share_id && res.data.id >share_id) {
if (share_id) {
shareParams.share_id = share_id;
shareParams.url = url;
api('share.add', shareParams).then(res => {
if (res.code === 1) {
uni.removeStorageSync('share_id');
uni.removeStorageSync('url');
}
})
}
resolve(res)
}).catch(e => {
reject(e)
})
})
},
// 订单信息
getOrderNum({
commit
}) {
return new Promise((resolve, reject) => {
api('order.statusNum').then(res => {
commit('ORDER_NUMBER', res.data);
resolve(res)
}).catch(e => {
reject(e)
})
})
},
// 获取订阅消息模板ids;
getMessageIds({
commit
}, type) {
return new Promise((resolve, reject) => {
api('messageIds').then(res => {
commit('MESSAGE_IDS', res.data);
let typeName = []; //模板键
let obj = res.data; //模板对象
let arr = []; //模板ids
switch (type) {
case 'result': //支付成功后
typeName = ['order_sended']
break;
case 'grouponResult': //拼团支付成功后
typeName = ['groupon_success', 'groupon_fail', 'order_sended']
break;
case 'aftersale': //点击售后
typeName = ['refund_agree', 'aftersale_change', 'wallet_change']
break;
case 'wallet': //提现提醒
typeName = ['score_change', 'wallet_apply', 'wallet_change']
break;
case 'store': //门店新订单通知
typeName = ['store_order_new']
break;
default:
typeName = []
break;
}
typeName.forEach(item => {
obj[item] && arr.push(obj[item])
})
arr.length && uni.requestSubscribeMessage({
tmplIds: arr,
success: (res) => {
console.log(res);
},
fail: (err) => {
console.log(err);
}
});
resolve(res)
}).catch(e => {
reject(e)
})
})
},
}
const mutations = {
// 小程序订阅消息模板ids
[MESSAGE_IDS](state, data) {
state.messageIds = data
},
[USER_INFO](state, data) {
state.userInfo = data
},
[LOGIN_TIP](state, data) {
state.showLoginTip = data
},
[ORDER_NUMBER](state, data) {
state.orderNum = data
},
// #ifdef MP-WEIXIN
[FORCE_OAUTH](state, data) {
state.forceOauth = data
data ? uni.hideTabBar() : uni.showTabBar();
},
// #endif
[OUT_LOGIN](state, data) {
uni.removeStorageSync('token');
uni.removeStorageSync('userInfo');
uni.removeStorageSync('cartNum');
store.commit('USER_INFO', {});
store.commit('CART_LIST', []);
store.commit('CART_NUM');
store.commit('ORDER_NUMBER', {});
},
}
const getters = {
}
export default {
state,
mutations,
actions,
getters
}
... ...
export const INIT_DATA = 'INIT_DATA' //初始化数据
export const PAGE_ROUTES = 'PAGE_ROUTES'//路由表
export const TEMPLATE_DATA = 'TEMPLATE_DATA'//模板信息
export const SET_THEME = 'SET_THEME' //更改主题
export const USER_INFO = 'USER_INFO' //用户信息
export const ORDER_NUMBER = 'ORDER_NUMBER' //订单数量
export const OUT_LOGIN = 'OUT_LOGIN' //退出登录
export const CART_LIST = 'CART_LIST' //购物车商品
export const CART_NUM = 'CART_NUM' //购物车商品数
export const LOGIN_TIP = 'LOGIN_TIP' //登录提示
// #ifdef MP-WEIXIN
export const FORCE_OAUTH = 'FORCE_OAUTH' // 小程序强制登录弹窗
// #endif
export const MESSAGE_IDS = 'MESSAGE_IDS' // 小程序订阅消息模板ids
... ...
/**
* 获取单个字符的utf8编码
* unicode BMP平面约65535个字符
* @param {num} code
* return {array}
*/
function unicodeFormat8(code) {
// 1 byte
var c0, c1, c2;
if (code < 128) {
return [code];
// 2 bytes
} else if (code < 2048) {
c0 = 192 + (code >> 6);
c1 = 128 + (code & 63);
return [c0, c1];
// 3 bytes
} else {
c0 = 224 + (code >> 12);
c1 = 128 + (code >> 6 & 63);
c2 = 128 + (code & 63);
return [c0, c1, c2];
}
}
/**
* 获取字符串的utf8编码字节串
* @param {string} string
* @return {array}
*/
function getUTF8Bytes(string) {
var utf8codes = [];
for (var i = 0; i < string.length; i++) {
var code = string.charCodeAt(i);
var utf8 = unicodeFormat8(code);
for (var j = 0; j < utf8.length; j++) {
utf8codes.push(utf8[j]);
}
}
return utf8codes;
}
/**
* 二维码算法实现
* @param {string} data 要编码的信息字符串
* @param {num} errorCorrectLevel 纠错等级
*/
export default function QRCodeAlg(data, errorCorrectLevel) {
this.typeNumber = -1; //版本
this.errorCorrectLevel = errorCorrectLevel;
this.modules = null; //二维矩阵,存放最终结果
this.moduleCount = 0; //矩阵大小
this.dataCache = null; //数据缓存
this.rsBlocks = null; //版本数据信息
this.totalDataCount = -1; //可使用的数据量
this.data = data;
this.utf8bytes = getUTF8Bytes(data);
this.make();
}
QRCodeAlg.prototype = {
constructor: QRCodeAlg,
/**
* 获取二维码矩阵大小
* @return {num} 矩阵大小
*/
getModuleCount: function () {
return this.moduleCount;
},
/**
* 编码
*/
make: function () {
this.getRightType();
this.dataCache = this.createData();
this.createQrcode();
},
/**
* 设置二位矩阵功能图形
* @param {bool} test 表示是否在寻找最好掩膜阶段
* @param {num} maskPattern 掩膜的版本
*/
makeImpl: function (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);
}
this.setupPositionProbePattern(0, 0);
this.setupPositionProbePattern(this.moduleCount - 7, 0);
this.setupPositionProbePattern(0, this.moduleCount - 7);
this.setupPositionAdjustPattern();
this.setupTimingPattern();
this.setupTypeInfo(true, maskPattern);
if (this.typeNumber >= 7) {
this.setupTypeNumber(true);
}
this.mapData(this.dataCache, maskPattern);
},
/**
* 设置二维码的位置探测图形
* @param {num} row 探测图形的中心横坐标
* @param {num} col 探测图形的中心纵坐标
*/
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;
}
}
}
},
/**
* 创建二维码
* @return {[type]} [description]
*/
createQrcode: function () {
var minLostPoint = 0;
var pattern = 0;
var bestModules = null;
for (var i = 0; i < 8; i++) {
this.makeImpl(i);
var lostPoint = QRUtil.getLostPoint(this);
if (i == 0 || minLostPoint > lostPoint) {
minLostPoint = lostPoint;
pattern = i;
bestModules = this.modules;
}
}
this.modules = bestModules;
this.setupTypeInfo(false, pattern);
if (this.typeNumber >= 7) {
this.setupTypeNumber(false);
}
},
/**
* 设置定位图形
* @return {[type]} [description]
*/
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);
if (this.modules[6][r] != null) {
continue;
}
this.modules[6][r] = (r % 2 == 0);
}
},
/**
* 设置矫正图形
* @return {[type]} [description]
*/
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;
}
}
}
}
}
},
/**
* 设置版本信息(7以上版本才有)
* @param {bool} test 是否处于判断最佳掩膜阶段
* @return {[type]} [description]
*/
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;
this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
}
},
/**
* 设置格式信息(纠错等级和掩膜版本)
* @param {bool} test
* @param {num} maskPattern 掩膜版本
* @return {}
*/
setupTypeInfo: function (test, maskPattern) {
var data = (QRErrorCorrectLevel[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
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);
},
/**
* 数据编码
* @return {[type]} [description]
*/
createData: function () {
var buffer = new QRBitBuffer();
var lengthBits = this.typeNumber > 9 ? 16 : 8;
buffer.put(4, 4); //添加模式
buffer.put(this.utf8bytes.length, lengthBits);
for (var i = 0, l = this.utf8bytes.length; i < l; i++) {
buffer.put(this.utf8bytes[i], 8);
}
if (buffer.length + 4 <= this.totalDataCount * 8) {
buffer.put(0, 4);
}
// padding
while (buffer.length % 8 != 0) {
buffer.putBit(false);
}
// padding
while (true) {
if (buffer.length >= this.totalDataCount * 8) {
break;
}
buffer.put(QRCodeAlg.PAD0, 8);
if (buffer.length >= this.totalDataCount * 8) {
break;
}
buffer.put(QRCodeAlg.PAD1, 8);
}
return this.createBytes(buffer);
},
/**
* 纠错码编码
* @param {buffer} buffer 数据编码
* @return {[type]}
*/
createBytes: function (buffer) {
var offset = 0;
var maxDcCount = 0;
var maxEcCount = 0;
var length = this.rsBlock.length / 3;
var rsBlocks = new Array();
for (var i = 0; i < length; i++) {
var count = this.rsBlock[i * 3 + 0];
var totalCount = this.rsBlock[i * 3 + 1];
var dataCount = this.rsBlock[i * 3 + 2];
for (var j = 0; j < count; j++) {
rsBlocks.push([dataCount, totalCount]);
}
}
var dcdata = new Array(rsBlocks.length);
var ecdata = new Array(rsBlocks.length);
for (var r = 0; r < rsBlocks.length; r++) {
var dcCount = rsBlocks[r][0];
var ecCount = rsBlocks[r][1] - 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 data = new Array(this.totalDataCount);
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;
},
/**
* 布置模块,构建最终信息
* @param {} data
* @param {} maskPattern
* @return {}
*/
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;
}
}
}
}
};
/**
* 填充字段
*/
QRCodeAlg.PAD0 = 0xEC;
QRCodeAlg.PAD1 = 0x11;
//---------------------------------------------------------------------
// 纠错等级对应的编码
//---------------------------------------------------------------------
var QRErrorCorrectLevel = [1, 0, 3, 2];
//---------------------------------------------------------------------
// 掩膜版本
//---------------------------------------------------------------------
var QRMaskPattern = {
PATTERN000: 0,
PATTERN001: 1,
PATTERN010: 2,
PATTERN011: 3,
PATTERN100: 4,
PATTERN101: 5,
PATTERN110: 6,
PATTERN111: 7
};
//---------------------------------------------------------------------
// 工具类
//---------------------------------------------------------------------
var QRUtil = {
/*
每个版本矫正图形的位置
*/
PATTERN_POSITION_TABLE: [
[],
[6, 18],
[6, 22],
[6, 26],
[6, 30],
[6, 34],
[6, 22, 38],
[6, 24, 42],
[6, 26, 46],
[6, 28, 50],
[6, 30, 54],
[6, 32, 58],
[6, 34, 62],
[6, 26, 46, 66],
[6, 26, 48, 70],
[6, 26, 50, 74],
[6, 30, 54, 78],
[6, 30, 56, 82],
[6, 30, 58, 86],
[6, 34, 62, 90],
[6, 28, 50, 72, 94],
[6, 26, 50, 74, 98],
[6, 30, 54, 78, 102],
[6, 28, 54, 80, 106],
[6, 32, 58, 84, 110],
[6, 30, 58, 86, 114],
[6, 34, 62, 90, 118],
[6, 26, 50, 74, 98, 122],
[6, 30, 54, 78, 102, 126],
[6, 26, 52, 78, 104, 130],
[6, 30, 56, 82, 108, 134],
[6, 34, 60, 86, 112, 138],
[6, 30, 58, 86, 114, 142],
[6, 34, 62, 90, 118, 146],
[6, 30, 54, 78, 102, 126, 150],
[6, 24, 50, 76, 102, 128, 154],
[6, 28, 54, 80, 106, 132, 158],
[6, 32, 58, 84, 110, 136, 162],
[6, 26, 54, 82, 110, 138, 166],
[6, 30, 58, 86, 114, 142, 170]
],
G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
/*
BCH编码格式信息
*/
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;
},
/*
BCH编码版本信息
*/
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;
},
/*
获取BCH位信息
*/
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);
}
},
/*
获取RS的纠错多项式
*/
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;
},
/*
获取评价
*/
getLostPoint: function (qrCode) {
var moduleCount = qrCode.getModuleCount(),
lostPoint = 0,
darkCount = 0;
for (var row = 0; row < moduleCount; row++) {
var sameCount = 0;
var head = qrCode.modules[row][0];
for (var col = 0; col < moduleCount; col++) {
var current = qrCode.modules[row][col];
//level 3 评价
if (col < moduleCount - 6) {
if (current && !qrCode.modules[row][col + 1] && qrCode.modules[row][col + 2] && qrCode.modules[row][col + 3] && qrCode.modules[row][col + 4] && !qrCode.modules[row][col + 5] && qrCode.modules[row][col + 6]) {
if (col < moduleCount - 10) {
if (qrCode.modules[row][col + 7] && qrCode.modules[row][col + 8] && qrCode.modules[row][col + 9] && qrCode.modules[row][col + 10]) {
lostPoint += 40;
}
} else if (col > 3) {
if (qrCode.modules[row][col - 1] && qrCode.modules[row][col - 2] && qrCode.modules[row][col - 3] && qrCode.modules[row][col - 4]) {
lostPoint += 40;
}
}
}
}
//level 2 评价
if ((row < moduleCount - 1) && (col < moduleCount - 1)) {
var count = 0;
if (current) count++;
if (qrCode.modules[row + 1][col]) count++;
if (qrCode.modules[row][col + 1]) count++;
if (qrCode.modules[row + 1][col + 1]) count++;
if (count == 0 || count == 4) {
lostPoint += 3;
}
}
//level 1 评价
if (head ^ current) {
sameCount++;
} else {
head = current;
if (sameCount >= 5) {
lostPoint += (3 + sameCount - 5);
}
sameCount = 1;
}
//level 4 评价
if (current) {
darkCount++;
}
}
}
for (var col = 0; col < moduleCount; col++) {
var sameCount = 0;
var head = qrCode.modules[0][col];
for (var row = 0; row < moduleCount; row++) {
var current = qrCode.modules[row][col];
//level 3 评价
if (row < moduleCount - 6) {
if (current && !qrCode.modules[row + 1][col] && qrCode.modules[row + 2][col] && qrCode.modules[row + 3][col] && qrCode.modules[row + 4][col] && !qrCode.modules[row + 5][col] && qrCode.modules[row + 6][col]) {
if (row < moduleCount - 10) {
if (qrCode.modules[row + 7][col] && qrCode.modules[row + 8][col] && qrCode.modules[row + 9][col] && qrCode.modules[row + 10][col]) {
lostPoint += 40;
}
} else if (row > 3) {
if (qrCode.modules[row - 1][col] && qrCode.modules[row - 2][col] && qrCode.modules[row - 3][col] && qrCode.modules[row - 4][col]) {
lostPoint += 40;
}
}
}
}
//level 1 评价
if (head ^ current) {
sameCount++;
} else {
head = current;
if (sameCount >= 5) {
lostPoint += (3 + sameCount - 5);
}
sameCount = 1;
}
}
}
// LEVEL4
var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
lostPoint += ratio * 10;
return lostPoint;
}
};
//---------------------------------------------------------------------
// QRMath使用的数学工具
//---------------------------------------------------------------------
var QRMath = {
/*
将n转化为a^m
*/
glog: function (n) {
if (n < 1) {
throw new Error("glog(" + n + ")");
}
return QRMath.LOG_TABLE[n];
},
/*
将a^m转化为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 多项式
//---------------------------------------------------------------------
/**
* 多项式类
* @param {Array} num 系数
* @param {num} shift a^shift
*/
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;
},
/**
* 多项式乘法
* @param {QRPolynomial} e 被乘多项式
* @return {[type]} [description]
*/
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);
},
/**
* 多项式模运算
* @param {QRPolynomial} e 模多项式
* @return {}
*/
mod: function (e) {
var tl = this.getLength(),
el = e.getLength();
if (tl - el < 0) {
return this;
}
var num = new Array(tl);
for (var i = 0; i < tl; i++) {
num[i] = this.get(i);
}
while (num.length >= el) {
var ratio = QRMath.glog(num[0]) - QRMath.glog(e.get(0));
for (var i = 0; i < e.getLength(); i++) {
num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
}
while (num[0] == 0) {
num.shift();
}
}
return new QRPolynomial(num, 0);
}
};
//---------------------------------------------------------------------
// RS_BLOCK_TABLE
//---------------------------------------------------------------------
/*
二维码各个版本信息[块数, 每块中的数据块数, 每块中的信息块数]
*/
var 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]
];
/**
* 根据数据获取对应版本
* @return {[type]} [description]
*/
QRCodeAlg.prototype.getRightType = function () {
for (var typeNumber = 1; typeNumber < 41; typeNumber++) {
var rsBlock = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + this.errorCorrectLevel];
if (rsBlock == undefined) {
throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + this.errorCorrectLevel);
}
var length = rsBlock.length / 3;
var totalDataCount = 0;
for (var i = 0; i < length; i++) {
var count = rsBlock[i * 3 + 0];
var dataCount = rsBlock[i * 3 + 2];
totalDataCount += dataCount * count;
}
var lengthBytes = typeNumber > 9 ? 2 : 1;
if (this.utf8bytes.length + lengthBytes < totalDataCount || typeNumber == 40) {
this.typeNumber = typeNumber;
this.rsBlock = rsBlock;
this.totalDataCount = totalDataCount;
break;
}
}
};
//---------------------------------------------------------------------
// 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);
},
put: function (num, length) {
for (var i = 0; i < length; i++) {
this.putBit(((num >>> (length - i - 1)) & 1));
}
},
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++;
}
};
\ No newline at end of file
... ...
import _app from './app.js';
import QRCodeAlg from './QRCodeAlg.js';
import { base64ToPath } from './image-tools.js';
const ShreUserPosterBackgroundKey = 'ShrePosterBackground_'; // 背景图片缓存名称前缀
const idKey = 'QSSHAREPOSTER_IDKEY'; //drawArray自动生成的idkey
var isMp = false;
// #ifdef MP
isMp = true;
// #endif
var nbgScale = 1;
// export default
function getSharePoster(obj) {
return new Promise(async (resolve, reject) => {
try {
const result1 = await returnPromise(obj);
resolve(result1);
} catch (e) {
//TODO handle the exception
try {
if(obj.bgScale) {
obj.bgScale = Number(obj.bgScale) - 0.1
}else{
nbgScale = nbgScale - 0.1
}
console.log('------------清除缓存后, 开始第二次尝试------------');
const result2 = await returnPromise(obj);
resolve(result2);
} catch (e) {
//TODO handle the exception
reject(e);
}
}
})
}
function returnPromise(obj) {
let {
type,
formData,
background,
posterCanvasId,
backgroundImage,
reserve,
textArray,
drawArray,
qrCodeArray,
imagesArray,
setCanvasWH,
setCanvasToTempFilePath,
setDraw,
bgScale,
Context,
_this,
delayTimeScale,
drawDelayTime
} = obj;
return new Promise(async (rs, rj) => {
try {
_app.showLoading('正在准备海报数据');
if (!Context) {
_app.log('没有画布对象,创建画布对象');
Context = uni.createCanvasContext(posterCanvasId, (_this || null));
}
let bgObj;
if (background && background.width && background.height) {
bgObj = background;
} else {
bgObj = await getShreUserPosterBackground({
backgroundImage,
type,
formData
});
}
bgScale = bgScale || nbgScale;
bgObj.width = bgObj.width * bgScale;
bgObj.height = bgObj.height * bgScale;
_app.log('获取背景图信息对象成功:' + JSON.stringify(bgObj));
const params = {
bgObj,
type,
bgScale,
getBgObj: function() {
return params.bgObj;
},
setBgObj: function(newBgObj){
const n = {...params.bgObj, ...newBgObj};
params.bgObj = n;
bgObj = n;
}
};
if (imagesArray) {
if (typeof(imagesArray) == 'function')
imagesArray = imagesArray(params);
_app.showLoading('正在生成需绘制图片的临时路径');
_app.log('准备设置图片');
imagesArray = await setImage(imagesArray);
_app.hideLoading();
}
if (textArray) {
if (typeof(textArray) == 'function')
textArray = textArray(params);
textArray = setText(Context, textArray);
}
if (qrCodeArray) {
if (typeof(qrCodeArray) == 'function')
qrCodeArray = qrCodeArray(params);
_app.showLoading('正在生成需绘制图片的临时路径');
for (let i = 0; i < qrCodeArray.length; i++) {
_app.log(i);
if (qrCodeArray[i].image)
qrCodeArray[i].image = await _app.downloadFile_PromiseFc(qrCodeArray[i].image);
}
_app.hideLoading();
}
if (drawArray) {
if (typeof(drawArray) == 'function') {
drawArray = drawArray(params);
}
if (_app.isPromise(drawArray)) {
drawArray = await drawArray;
}
if (_app.isArray(drawArray) && drawArray.length > 0) {
let hasAllInfoCallback = false;
for (let i = 0; i < drawArray.length; i++) {
const drawArrayItem = drawArray[i];
if (_app.isFn(drawArrayItem.allInfoCallback) && !hasAllInfoCallback) hasAllInfoCallback = true;
drawArrayItem[idKey] = i;
let newData;
switch (drawArrayItem.type) {
case 'image':
newData = await setImage(drawArrayItem);
break;
case 'text':
newData = setText(Context, drawArrayItem);
break;
case 'qrcode':
if (drawArrayItem.image)
newData = {
image: await _app.downloadFile_PromiseFc(drawArrayItem.image)
};
break;
case 'custom':
break;
case 'fillrect':
break;
case 'strokeRect':
break;
case 'roundStrokeRect':
break;
case 'roundFillRect':
break;
default:
_app.log('未识别的类型');
break;
}
if (newData && _app.isObject(newData)) {
drawArray[i] = { ...drawArrayItem,
...newData
}
};
}
if (hasAllInfoCallback) {
_app.log('----------------hasAllInfoCallback----------------');
const drawArray_copy = [...drawArray];
drawArray_copy.sort((a, b) => {
const a_serialNum = !_app.isUndef(a.serialNum) && !_app.isNull(a.serialNum) ? Number(a.serialNum) : Number.NEGATIVE_INFINITY;
const b_serialNum = !_app.isUndef(b.serialNum) && !_app.isNull(b.serialNum) ? Number(b.serialNum) : Number.NEGATIVE_INFINITY;
return a_serialNum - b_serialNum;
})
_app.log('开始for循环');
for (let i = 0; i < drawArray_copy.length; i++) {
const item = { ...drawArray_copy[i]
};
if (_app.isFn(item.allInfoCallback)) {
let newData = item.allInfoCallback({
drawArray
});
if (_app.isPromise(newData)) newData = await newData;
const item_idKey = item[idKey];
if (!_app.isUndef(item_idKey)) {
drawArray[item[idKey]] = { ...item,
...newData
};
} else {
console.log('程序错误 找不到idKey!!! ...这不应该啊');
}
}
}
_app.log('for循环结束');
}
}
}
console.log('params:' + JSON.stringify(params))
if (setCanvasWH && typeof(setCanvasWH) == 'function') {
await new Promise((resolve, reject)=>{
setCanvasWH(params);
setTimeout(()=>{
resolve();
}, 50)
})
}
const poster = await drawShareImage({
Context,
type,
posterCanvasId,
reserve,
drawArray,
textArray,
imagesArray,
bgObj,
qrCodeArray,
setCanvasToTempFilePath,
setDraw,
bgScale,
_this,
delayTimeScale,
drawDelayTime
});
_app.hideLoading();
rs({
bgObj,
poster,
type
});
} catch (e) {
//TODO handle the exception
rj(e);
}
});
}
function drawShareImage(obj) { //绘制海报方法
let {
Context,
type,
posterCanvasId,
reserve,
bgObj,
drawArray,
textArray,
qrCodeArray,
imagesArray,
setCanvasToTempFilePath,
setDraw,
bgScale,
_this,
delayTimeScale,
drawDelayTime
} = obj;
const params = {
Context,
bgObj,
type,
bgScale
};
delayTimeScale = delayTimeScale !== undefined ? delayTimeScale : 15;
drawDelayTime = drawDelayTime !== undefined ? drawDelayTime : 100;
return new Promise((rs, rj) => {
try {
_app.showLoading('正在绘制海报');
_app.log('背景对象:' + JSON.stringify(bgObj));
if (bgObj && bgObj.path) {
_app.log('背景有图片路径');
Context.drawImage(bgObj.path, 0, 0, bgObj.width, bgObj.height);
} else {
_app.log('背景没有图片路径');
if (bgObj.backgroundColor) {
_app.log('背景有背景颜色:' + bgObj.backgroundColor);
Context.setFillStyle(bgObj.backgroundColor);
Context.fillRect(0, 0, bgObj.width, bgObj.height);
} else {
_app.log('背景没有背景颜色');
}
}
_app.showLoading('绘制图片');
if (imagesArray && imagesArray.length > 0)
drawImage(Context, imagesArray);
_app.showLoading('绘制自定义内容');
if (setDraw && typeof(setDraw) == 'function') setDraw(params);
_app.showLoading('绘制文本');
if (textArray && textArray.length > 0)
drawText(Context, textArray, bgObj);
_app.showLoading('绘制二维码');
if (qrCodeArray && qrCodeArray.length > 0) {
for (let i = 0; i < qrCodeArray.length; i++) {
drawQrCode(Context, qrCodeArray[i]);
}
}
_app.showLoading('绘制可控层级序列');
if (drawArray && drawArray.length > 0) {
for (let i = 0; i < drawArray.length; i++) {
const drawArrayItem = drawArray[i];
_app.log('绘制可控层级序列, drawArrayItem:' + JSON.stringify(drawArrayItem));
switch (drawArrayItem.type) {
case 'image':
_app.log('绘制可控层级序列, 绘制图片');
drawImage(Context, drawArrayItem);
break;
case 'text':
_app.log('绘制可控层级序列, 绘制文本');
drawText(Context, drawArrayItem, bgObj);
break;
case 'qrcode':
_app.log('绘制可控层级序列, 绘制二维码');
drawQrCode(Context, drawArrayItem);
break;
case 'custom':
_app.log('绘制可控层级序列, 绘制自定义内容');
if (drawArrayItem.setDraw && typeof drawArrayItem.setDraw === 'function')
drawArrayItem.setDraw(Context);
break;drawRoundStrokeRect, drawStrokeRect
case 'fillRect':
_app.log('绘制可控层级序列, 绘制填充直角矩形');
drawFillRect(Context, drawArrayItem);
break;
case 'strokeRect':
_app.log('绘制可控层级序列, 绘制线条直角矩形');
drawStrokeRect(Context, drawArrayItem);
break;
case 'roundStrokeRect':
_app.log('绘制可控层级序列, 绘制线条圆角矩形');
drawRoundStrokeRect(Context, drawArrayItem);
break;
case 'roundFillRect':
_app.log('绘制可控层级序列, 绘制填充圆角矩形');
drawRoundFillRect(Context, drawArrayItem);
break;
default:
_app.log('未识别的类型');
break;
}
}
}
_app.showLoading('绘制中')
setTimeout(() => {
_app.log('准备执行draw方法')
_app.log('Context:' + Context);
const fn = function(){
_app.showLoading('正在输出图片');
let setObj = setCanvasToTempFilePath || {};
if (setObj && typeof(setObj) == 'function')
setObj = setCanvasToTempFilePath(bgObj, type);
let canvasToTempFilePathFn;
const data = {
x: 0,
y: 0,
width: Number(bgObj.width),
height: Number(bgObj.height),
destWidth: Number(bgObj.width), // 若H5使用这里请不要乘以二
destHeight: Number(bgObj.height), // 若H5使用这里请不要乘以二
quality: .8,
fileType: 'jpg',
...setObj
};
console.log('canvasToTempFilePath的data对象:' + JSON.stringify(data));
canvasToTempFilePathFn = function() {
const toTempFilePathObj = { //输出为图片
...data,
canvasId: posterCanvasId,
success(res) {
_app.hideLoading();
rs(res);
},
fail(err) {
_app.hideLoading();
console.log('输出图片失败');
_app.log('输出图片失败:' + JSON.stringify(err));
rj('输出图片失败:' + JSON.stringify(err))
}
}
uni.canvasToTempFilePath(toTempFilePathObj, _this || null);
}
let delayTime = 0;
if (qrCodeArray) {
qrCodeArray.forEach(item => {
if (item.text) {
delayTime += Number(item.text.length);
}
})
}
if (imagesArray) {
imagesArray.forEach(() => {
delayTime += delayTimeScale;
})
}
if (textArray) {
textArray.forEach(() => {
delayTime += delayTimeScale;
})
}
if (drawArray) {
drawArray.forEach(item => {
switch (item.type) {
case 'text':
if (item.text) {
delayTime += item.text.length;
}
break;
default:
delayTime += delayTimeScale;
break;
}
})
}
_app.log('延时系数:' + delayTimeScale);
_app.log('总计延时:' + delayTime);
setTimeout(canvasToTempFilePathFn, delayTime);
}
Context.draw((typeof(reserve) == 'boolean' ? reserve : false), fn);
}, drawDelayTime);
} catch (e) {
//TODO handle the exception
_app.hideLoading();
rj(e);
}
});
}
// export
function drawFillRect(Context, drawArrayItem = {}) { //填充矩形
_app.log('进入绘制填充直角矩形方法, drawArrayItem:' + JSON.stringify(drawArrayItem));
Context.setFillStyle(drawArrayItem.backgroundColor || 'black');
Context.setGlobalAlpha(drawArrayItem.alpha || 1);
Context.fillRect(drawArrayItem.dx || 0, drawArrayItem.dy || 0, drawArrayItem.width || 0, drawArrayItem.height || 0);
Context.setGlobalAlpha(1);
}
// export
function drawStrokeRect(Context, drawArrayItem = {}) { //线条矩形
Context.setStrokeStyle(drawArrayItem.color||'black');
Context.setLineWidth(drawArrayItem.lineWidth || 1);
Context.strokeRect(drawArrayItem.dx, drawArrayItem.dy, drawArrayItem.width, drawArrayItem.height);
}
// export
function drawRoundStrokeRect(Context, drawArrayItem = {}) {
let { dx, dy, width, height, r, lineWidth, color } = drawArrayItem;
r = r || width * .1;
if (width < 2 * r) {
r = width / 2;
}
if (width < 2 * r) {
r = width / 2;
}
Context.beginPath();
Context.moveTo(dx + r, dy);
Context.arcTo(dx + width, dy, dx + width, dy + height, r);
Context.arcTo(dx + width, dy + height, dx, dy + height, r);
Context.arcTo(dx, dy + height, dx, dy, r);
Context.arcTo(dx, dy, dx + width, dy, r);
Context.closePath();
Context.setLineWidth(lineWidth || 1);
Context.setStrokeStyle(color || 'black');
Context.stroke();
}
// export
function drawRoundFillRect(Context, drawArrayItem = {}) {
let { dx, dy, width, height, r, backgroundColor } = drawArrayItem;
r = r || width * .1;
if (width < 2 * r) {
r = width / 2;
}
if (width < 2 * r) {
r = width / 2;
}
Context.beginPath();
Context.moveTo(dx + r, dy);
Context.arcTo(dx + width, dy, dx + width, dy + height, r);
Context.arcTo(dx + width, dy + height, dx, dy + height, r);
Context.arcTo(dx, dy + height, dx, dy, r);
Context.arcTo(dx, dy, dx + width, dy, r);
Context.closePath();
Context.setFillStyle(backgroundColor);
Context.fill();
}
// export
function setText(Context, texts) { // 设置文本数据
_app.log('进入设置文字方法, texts:' + JSON.stringify(texts));
if (texts && _app.isArray(texts)) {
_app.log('texts是数组');
if (texts.length > 0) {
for (let i = 0; i < texts.length; i++) {
_app.log('字符串信息-初始化之前:' + JSON.stringify(texts[i]));
texts[i] = setTextFn(Context, texts[i]);
}
}
} else {
_app.log('texts是对象');
texts = setTextFn(Context, texts);
}
_app.log('返回texts:' + JSON.stringify(texts));
return texts;
}
function setTextFn(Context, textItem) {
_app.log('进入设置文字方法, textItem:' + JSON.stringify(textItem));
if (_app.isNotNull_string(textItem.text)) {
textItem.text = String(textItem.text);
textItem.alpha = textItem.alpha !== undefined ? Number(textItem.alpha) : 1;
textItem.color = textItem.color || 'black';
textItem.size = textItem.size !== undefined ? Number(textItem.size) : 10;
textItem.textAlign = textItem.textAlign || 'left';
textItem.textBaseline = textItem.textBaseline || 'middle';
textItem.dx = Number(textItem.dx) || 0;
textItem.dy = Number(textItem.dy) || 0;
textItem.size = Math.ceil(Number(textItem.size));
_app.log('字符串信息-初始化默认值后:' + JSON.stringify(textItem));
const textLength = countTextLength(Context, {
text: textItem.text,
size: textItem.size
});
_app.log('字符串信息-初始化时的文本长度:' + textLength);
let infoCallBackObj = {};
if (textItem.infoCallBack && typeof(textItem.infoCallBack) === 'function') {
infoCallBackObj = textItem.infoCallBack(textLength);
}
textItem = {
...textItem,
textLength,
...infoCallBackObj
}
_app.log('字符串信息-infoCallBack后:' + JSON.stringify(textItem));
}
return textItem;
}
function countTextLength(Context, obj) {
_app.log('计算文字长度, obj:' + JSON.stringify(obj));
const {
text,
size
} = obj;
Context.setFontSize(size);
let textLength;
try{
textLength = Context.measureText(text); // 官方文档说 App端自定义组件编译模式暂时不可用measureText方法
}catch(e){
//TODO handle the exception
textLength = {};
}
textLength = {};
_app.log('measureText计算文字长度, textLength:' + JSON.stringify(textLength));
textLength = textLength && textLength.width ? textLength.width : 0;
if (!textLength) {
let l = 0;
for (let j = 0; j < text.length; j++) {
let t = text.substr(j, 1);
const countL = countStrLength(t);
_app.log('计算文字宽度系数:' + countL);
l += countL;
}
_app.log('文字宽度总系数:' + l);
textLength = l * size;
}
return textLength;
}
//计算字符长度系数
function countStrLength(t) {
let l;
if (/a/.test(t)) {
l = 0.552734375
} else if (/b/.test(t)) {
l = 0.638671875
} else if (/c/.test(t)) {
l = 0.50146484375
} else if (/d/.test(t)) {
l = 0.6396484375
} else if (/e/.test(t)) {
l = 0.5673828125
} else if (/f/.test(t)) {
l = 0.3466796875
} else if (/g/.test(t)) {
l = 0.6396484375
} else if (/h/.test(t)) {
l = 0.61572265625
} else if (/i/.test(t)) {
l = 0.26611328125
} else if (/j/.test(t)) {
l = 0.26708984375
} else if (/k/.test(t)) {
l = 0.54443359375
} else if (/l/.test(t)) {
l = 0.26611328125
} else if (/m/.test(t)) {
l = 0.93701171875
} else if (/n/.test(t)) {
l = 0.6162109375
} else if (/o/.test(t)) {
l = 0.6357421875
} else if (/p/.test(t)) {
l = 0.638671875
} else if (/q/.test(t)) {
l = 0.6396484375
} else if (/r/.test(t)) {
l = 0.3818359375
} else if (/s/.test(t)) {
l = 0.462890625
} else if (/t/.test(t)) {
l = 0.37255859375
} else if (/u/.test(t)) {
l = 0.6162109375
} else if (/v/.test(t)) {
l = 0.52490234375
} else if (/w/.test(t)) {
l = 0.78955078125
} else if (/x/.test(t)) {
l = 0.5068359375
} else if (/y/.test(t)) {
l = 0.529296875
} else if (/z/.test(t)) {
l = 0.49169921875
} else if (/A/.test(t)) {
l = 0.70361328125
} else if (/B/.test(t)) {
l = 0.62744140625
} else if (/C/.test(t)) {
l = 0.6689453125
} else if (/D/.test(t)) {
l = 0.76171875
} else if (/E/.test(t)) {
l = 0.5498046875
} else if (/F/.test(t)) {
l = 0.53125
} else if (/G/.test(t)) {
l = 0.74365234375
} else if (/H/.test(t)) {
l = 0.7734375
} else if (/I/.test(t)) {
l = 0.2939453125
} else if (/J/.test(t)) {
l = 0.39599609375
} else if (/K/.test(t)) {
l = 0.634765625
} else if (/L/.test(t)) {
l = 0.51318359375
} else if (/M/.test(t)) {
l = 0.97705078125
} else if (/N/.test(t)) {
l = 0.81298828125
} else if (/O/.test(t)) {
l = 0.81494140625
} else if (/P/.test(t)) {
l = 0.61181640625
} else if (/Q/.test(t)) {
l = 0.81494140625
} else if (/R/.test(t)) {
l = 0.65283203125
} else if (/S/.test(t)) {
l = 0.5771484375
} else if (/T/.test(t)) {
l = 0.5732421875
} else if (/U/.test(t)) {
l = 0.74658203125
} else if (/V/.test(t)) {
l = 0.67626953125
} else if (/W/.test(t)) {
l = 1.017578125
} else if (/X/.test(t)) {
l = 0.64501953125
} else if (/Y/.test(t)) {
l = 0.603515625
} else if (/Z/.test(t)) {
l = 0.6201171875
} else if (/[0-9]/.test(t)) {
l = 0.58642578125
} else if (/[\u4e00-\u9fa5]/.test(t)) {
l = 1
} else if (/ /.test(t)) {
l = 0.2958984375
} else if (/\`/.test(t)) {
l = 0.294921875
} else if (/\~/.test(t)) {
l = 0.74169921875
} else if (/\!/.test(t)) {
l = 0.3125
} else if (/\@/.test(t)) {
l = 1.03125
} else if (/\#/.test(t)) {
l = 0.63818359375
} else if (/\$/.test(t)) {
l = 0.58642578125
} else if (/\%/.test(t)) {
l = 0.8896484375
} else if (/\^/.test(t)) {
l = 0.74169921875
} else if (/\&/.test(t)) {
l = 0.8701171875
} else if (/\*/.test(t)) {
l = 0.455078125
} else if (/\(/.test(t)) {
l = 0.333984375
} else if (/\)/.test(t)) {
l = 0.333984375
} else if (/\_/.test(t)) {
l = 0.4482421875
} else if (/\-/.test(t)) {
l = 0.4326171875
} else if (/\+/.test(t)) {
l = 0.74169921875
} else if (/\=/.test(t)) {
l = 0.74169921875
} else if (/\|/.test(t)) {
l = 0.26904296875
} else if (/\\/.test(t)) {
l = 0.416015625
} else if (/\[/.test(t)) {
l = 0.333984375
} else if (/\]/.test(t)) {
l = 0.333984375
} else if (/\;/.test(t)) {
l = 0.24072265625
} else if (/\'/.test(t)) {
l = 0.25634765625
} else if (/\,/.test(t)) {
l = 0.24072265625
} else if (/\./.test(t)) {
l = 0.24072265625
} else if (/\//.test(t)) {
l = 0.42724609375
} else if (/\{/.test(t)) {
l = 0.333984375
} else if (/\}/.test(t)) {
l = 0.333984375
} else if (/\:/.test(t)) {
l = 0.24072265625
} else if (/\"/.test(t)) {
l = 0.435546875
} else if (/\</.test(t)) {
l = 0.74169921875
} else if (/\>/.test(t)) {
l = 0.74169921875
} else if (/\?/.test(t)) {
l = 0.48291015625
} else {
l = 1
}
return l;
}
// export
function setImage(images) { // 设置图片数据
_app.log('进入设置图片数据方法');
return new Promise(async (resolve, rejcet) => {
try {
if (images && _app.isArray(images)) {
_app.log('images是一个数组');
for (let i = 0; i < images.length; i++) {
_app.log('设置图片数据循环中:' + i);
images[i] = await setImageFn(images[i]);
}
} else {
_app.log('images是一个对象');
images = await setImageFn(images);
}
resolve(images);
} catch (e) {
//TODO handle the exception
rejcet(e);
}
})
}
function base64ToPathFn(path) {
var reg = /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s]*?)\s*$/i;
if(!reg.test(path)){
return Promise.resolve(path);
}
return base64ToPath(path);
}
function setImageFn(image) {
return new Promise(async (resolve, reject) => {
if (image.url) {
image.url = (await base64ToPathFn(image.url));
let imgUrl = image.url;
imgUrl = await _app.downloadFile_PromiseFc(imgUrl);
image.url = imgUrl;
const hasinfoCallBack = image.infoCallBack && typeof(image.infoCallBack) === 'function';
let imageInfo = {};
imageInfo = await _app.getImageInfo_PromiseFc(imgUrl);
if (hasinfoCallBack) {
image = {
...image,
...image.infoCallBack(imageInfo)
};
}
image.dx = Number(image.dx) || 0;
image.dy = Number(image.dy) || 0;
image.dWidth = Number(image.dWidth || imageInfo.width);
image.dHeight = Number(image.dHeight || imageInfo.height);
image = {
...image,
imageInfo
}
}
resolve(image);
})
}
// export
function drawText(Context, textArray, bgObj) { // 先遍历换行再绘制
if (!_app.isArray(textArray)) {
_app.log('遍历文本方法, 不是数组');
textArray = [textArray];
} else {
_app.log('遍历文本方法, 是数组');
}
_app.log('遍历文本方法, textArray:' + JSON.stringify(textArray));
const newArr = [];
if (textArray && textArray.length > 0) {
for (let j = 0; j < textArray.length; j++) {
const textItem = textArray[j];
if (textItem.text && textItem.lineFeed) {
let lineNum = -1,
maxWidth = bgObj.width,
lineHeight = textItem.size,
dx = textItem.dx;
if (_app.isObject(textItem.lineFeed)) {
const lineFeed = textItem.lineFeed;
lineNum = (lineFeed.lineNum !== undefined && typeof(lineFeed.lineNum) === 'number') && lineFeed.lineNum >= 0 ?
lineFeed.lineNum : lineNum;
maxWidth = (lineFeed.maxWidth !== undefined && typeof(lineFeed.maxWidth) === 'number') ? lineFeed.maxWidth :
maxWidth;
lineHeight = (lineFeed.lineHeight !== undefined && typeof(lineFeed.lineHeight) === 'number') ? lineFeed.lineHeight :
lineHeight;
dx = (lineFeed.dx !== undefined && typeof(lineFeed.dx) === 'number') ? lineFeed.dx : dx;
}
const chr = (textItem.text).split("");
let temp = "";
const row = [];
//循环出几行文字组成数组
for (let a = 0, len = chr.length; a < len; a++) {
if (countTextLength(Context, {
text: temp,
size: textItem.size
}) <= maxWidth && countTextLength(Context, {
text: (temp + chr[a]),
size: textItem.size
}) <= maxWidth) {
temp += chr[a];
if (a == (chr.length - 1)) {
row.push(temp);
}
} else {
row.push(temp);
temp = chr[a];
}
}
_app.log('循环出的文本数组:' + JSON.stringify(row));
//只显示几行 变量间距lineHeight 变量行数lineNum
let allNum = (lineNum >= 0 && lineNum < row.length) ? lineNum : row.length;
for (let i = 0; i < allNum; i++) {
let str = row[i];
if (i == (allNum - 1) && allNum < row.length) {
str = str.substring(0, str.length - 1) + '...';
}
const obj = { ...textItem,
text: str,
dx: i === 0 ? textItem.dx : (dx >= 0 ? dx : textItem.dx),
dy: textItem.dy + (i * lineHeight),
textLength: countTextLength(Context, {
text: str,
size: textItem.size
})
};
_app.log('重新组成的文本对象:' + JSON.stringify(obj));
newArr.push(obj);
}
} else {
newArr.push(textItem);
}
}
}
_app.log('绘制文本新数组:' + JSON.stringify(newArr));
drawTexts(Context, newArr);
}
function setFont(textItem = {}) {
if (textItem.font && typeof(textItem.font) === 'string') {
_app.log(textItem.font)
return textItem.font;
} else {
let fontStyle = 'normal';
let fontVariant = 'normal';
let fontWeight = 'normal';
let fontSize = textItem.size || 10;
let fontFamily = 'sans-serif';
fontSize = Math.ceil(Number(fontSize));
if (textItem.fontStyle && typeof(textItem.fontStyle) === 'string')
fontStyle = textItem.fontStyle.trim();
if (textItem.fontVariant && typeof(textItem.fontVariant) === 'string')
fontVariant = textItem.fontVariant.trim();
if (textItem.fontWeight && (typeof(textItem.fontWeight) === 'string' || typeof(textItem.fontWeight) === 'number'))
fontWeight = textItem.fontWeight.trim();
if (textItem.fontFamily && typeof(textItem.fontFamily) === 'string')
fontFamily = textItem.fontFamily.trim();
return fontStyle + ' ' +
fontVariant + ' ' +
fontWeight + ' ' +
fontSize + 'px' + ' ' +
fontFamily;
}
}
function drawTexts(Context, texts) { // 绘制文本
_app.log('准备绘制文本方法, texts:' + JSON.stringify(texts));
if (texts && _app.isArray(texts)) {
_app.log('准备绘制文本方法, 是数组');
if (texts.length > 0) {
for (let i = 0; i < texts.length; i++) {
drawTextFn(Context, texts[i]);
}
}
} else {
_app.log('准备绘制文本方法, 不是数组');
drawTextFn(Context, texts);
}
}
function drawTextFn(Context, textItem) {
_app.log('进入绘制文本方法, textItem:' + JSON.stringify(textItem));
if (textItem && _app.isObject(textItem) && textItem.text) {
Context.font = setFont(textItem);
Context.setFillStyle(textItem.color);
Context.setGlobalAlpha(textItem.alpha);
Context.setTextAlign(textItem.textAlign);
Context.setTextBaseline(textItem.textBaseline);
Context.fillText(textItem.text, textItem.dx, textItem.dy);
if (textItem.lineThrough && _app.isObject(textItem.lineThrough)) {
_app.log('有删除线');
let lineThrough = textItem.lineThrough;
lineThrough.alpha = lineThrough.alpha !== undefined ? lineThrough.alpha : textItem.alpha;
lineThrough.style = lineThrough.style || textItem.color;
lineThrough.width = lineThrough.width !== undefined ? lineThrough.width : textItem.size / 10;
lineThrough.cap = lineThrough.cap !== undefined ? lineThrough.cap : 'butt';
_app.log('删除线对象:' + JSON.stringify(lineThrough));
Context.setGlobalAlpha(lineThrough.alpha);
Context.setStrokeStyle(lineThrough.style);
Context.setLineWidth(lineThrough.width);
Context.setLineCap(lineThrough.cap);
let mx, my;
switch (textItem.textAlign) {
case 'left':
mx = textItem.dx;
break;
case 'center':
mx = textItem.dx - (textItem.textLength) / 2;
break;
default:
mx = textItem.dx - (textItem.textLength);
break;
}
switch (textItem.textBaseline) {
case 'top':
my = textItem.dy + (textItem.size * .5);
break;
case 'middle':
my = textItem.dy;
break;
default:
my = textItem.dy - (textItem.size * .5);
break;
}
Context.beginPath();
Context.moveTo(mx, my);
Context.lineTo(mx + textItem.textLength, my);
Context.stroke();
Context.closePath();
_app.log('删除线完毕');
}
Context.setGlobalAlpha(1);
Context.font = '10px sans-serif';
}
}
// export
function drawImage(Context, images) { // 绘制图片
_app.log('判断图片数据类型:' + JSON.stringify(images))
if (images && _app.isArray(images)) {
if (images.length > 0) {
for (let i = 0; i < images.length; i++) {
readyDrawImageFn(Context, images[i]);
}
}
} else {
readyDrawImageFn(Context, images);
}
}
function readyDrawImageFn(Context, img) {
_app.log('判断绘制图片形状, img:' + JSON.stringify(img));
if (img.url) {
if (img.circleSet) {
drawCircleImage(Context, img);
} else if (img.roundRectSet) {
drawRoundRectImage(Context, img);
} else {
drawImageFn(Context, img);
}
}
}
function drawImageFn(Context, img) {
_app.log('进入绘制默认图片方法, img:' + JSON.stringify(img));
if (img.url) {
const hasAlpha = !_app.isUndef(img.alpha);
img.alpha = Number(!_app.isUndef(img.alpha) ? img.alpha : 1);
Context.setGlobalAlpha(img.alpha);
_app.log('绘制默认图片方法, 有url');
if (img.dWidth && img.dHeight && img.sx && img.sy && img.sWidth && img.sHeight) {
_app.log('绘制默认图片方法, 绘制第一种方案');
Context.drawImage(img.url,
Number(img.sx) || false, Number(img.sy) || false,
Number(img.sWidth) || false, Number(img.sHeight) || false,
Number(img.dx || 0), Number(img.dy || 0),
Number(img.dWidth) || false, Number(img.dHeight) || false,);
} else if (img.dWidth && img.dHeight) {
_app.log('绘制默认图片方法, 绘制第二种方案');
Context.drawImage(img.url, Number(img.dx || 0), Number(img.dy || 0),
Number(img.dWidth) || false, Number(img.dHeight) || false);
} else {
_app.log('绘制默认图片方法, 绘制第三种方案');
Context.drawImage(img.url, Number(img.dx || 0), Number(img.dy || 0));
}
if (hasAlpha) {
Context.setGlobalAlpha(1);
}
}
_app.log('绘制默认图片方法, 绘制完毕');
}
function drawCircleImage(Context, obj) {
_app.log('进入绘制圆形图片方法, obj:' + JSON.stringify(obj));
let {
dx,
dy,
dWidth,
dHeight,
circleSet,
imageInfo
} = obj;
let x, y, r;
if (typeof circleSet === 'object') {
x = circleSet.x;
y = circleSet.y;
r = circleSet.r;
}
if (!r) {
let d;
d = dWidth > dHeight ? dHeight : dWidth;
r = d / 2;
}
x = x ? dx + x : (dx || 0) + r;
y = y ? dy + y : (dy || 0) + r;
Context.save();
Context.beginPath();
Context.arc(x, y, r, 0, 2 * Math.PI, false);
Context.closePath();
Context.setGlobalAlpha(0);
Context.fillStyle = '#FFFFFF';
Context.fill();
Context.setGlobalAlpha(1);
Context.clip();
drawImageFn(Context, obj);
_app.log('默认图片绘制完毕');
Context.restore();
}
function drawRoundRectImage(Context, obj) { // 绘制矩形
_app.log('进入绘制矩形图片方法, obj:' + JSON.stringify(obj));
Context.save();
let {
dx,
dy,
dWidth,
dHeight,
roundRectSet,
imageInfo
} = obj;
let r;
if (typeof roundRectSet === 'object') {
r = roundRectSet.r;
}
r = r || dWidth * .1;
if (dWidth < 2 * r) {
r = dWidth / 2;
}
if (dHeight < 2 * r) {
r = dHeight / 2;
}
Context.beginPath();
Context.moveTo(dx + r, dy);
Context.arcTo(dx + dWidth, dy, dx + dWidth, dy + dHeight, r);
Context.arcTo(dx + dWidth, dy + dHeight, dx, dy + dHeight, r);
Context.arcTo(dx, dy + dHeight, dx, dy, r);
Context.arcTo(dx, dy, dx + dWidth, dy, r);
Context.closePath();
Context.setGlobalAlpha(0);
Context.fillStyle = '#FFFFFF';
Context.fill();
Context.setGlobalAlpha(1);
Context.clip();
drawImageFn(Context, obj);
Context.restore();
_app.log('进入绘制矩形图片方法, 绘制完毕');
}
// export
function drawQrCode(Context, qrCodeObj) { //生成二维码方法, 参考了 诗小柒 的二维码生成器代码
_app.log('进入绘制二维码方法')
_app.showLoading('正在生成二维码');
let qrcodeAlgObjCache = [];
let options = {
text: String(qrCodeObj.text || '') || '', // 生成内容
size: Number(qrCodeObj.size || 0) || 200, // 二维码大小
background: String(qrCodeObj.background || '') || '#ffffff', // 背景色
foreground: String(qrCodeObj.foreground || '') || '#000000', // 前景色
pdground: String(qrCodeObj.pdground || '') || '#000000', // 定位角点颜色
correctLevel: Number(qrCodeObj.correctLevel || 0) || 3, // 容错级别
image: String(qrCodeObj.image || '') || '', // 二维码图标
imageSize: Number(qrCodeObj.imageSize || 0) || 40, // 二维码图标大小
dx: Number(qrCodeObj.dx || 0) || 0, // x轴距离
dy: Number(qrCodeObj.dy || 0) || 0 // y轴距离
}
let qrCodeAlg = null;
let d = 0;
for (var i = 0, l = qrcodeAlgObjCache.length; i < l; i++) {
d = i;
if (qrcodeAlgObjCache[i].text == options.text && qrcodeAlgObjCache[i].text.correctLevel == options.correctLevel) {
qrCodeAlg = qrcodeAlgObjCache[i].obj;
break;
}
}
if (d == l) {
qrCodeAlg = new QRCodeAlg(options.text, options.correctLevel);
qrcodeAlgObjCache.push({
text: options.text,
correctLevel: options.correctLevel,
obj: qrCodeAlg
});
}
let getForeGround = function(config) {
let options = config.options;
if (options.pdground && (
(config.row > 1 && config.row < 5 && config.col > 1 && config.col < 5) ||
(config.row > (config.count - 6) && config.row < (config.count - 2) && config.col > 1 && config.col < 5) ||
(config.row > 1 && config.row < 5 && config.col > (config.count - 6) && config.col < (config.count - 2))
)) {
return options.pdground;
}
return options.foreground;
}
let count = qrCodeAlg.getModuleCount();
let ratioSize = options.size;
let ratioImgSize = options.imageSize;
//计算每个点的长宽
let tileW = (ratioSize / count).toPrecision(4);
let tileH = (ratioSize / count).toPrecision(4);
//绘制
for (let row = 0; row < count; row++) {
for (let col = 0; col < count; col++) {
let w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));
let h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW));
let foreground = getForeGround({
row: row,
col: col,
count: count,
options: options
});
Context.setFillStyle(qrCodeAlg.modules[row][col] ? foreground : options.background);
Context.fillRect(options.dx + Math.round(col * tileW), options.dy + Math.round(row * tileH), w, h);
}
}
if (options.image) {
let x = options.dx + Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
let y = options.dy + Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
drawRoundedRect(Context, x, y, ratioImgSize, ratioImgSize, 2, 6, true, true)
Context.drawImage(options.image, x, y, ratioImgSize, ratioImgSize);
// 画圆角矩形
function drawRoundedRect(ctxi, x, y, width, height, r, lineWidth, fill, stroke) {
ctxi.setLineWidth(lineWidth);
ctxi.setFillStyle(options.background);
ctxi.setStrokeStyle(options.background);
ctxi.beginPath(); // draw top and top right corner
ctxi.moveTo(x + r, y);
ctxi.arcTo(x + width, y, x + width, y + r, r); // draw right side and bottom right corner
ctxi.arcTo(x + width, y + height, x + width - r, y + height, r); // draw bottom and bottom left corner
ctxi.arcTo(x, y + height, x, y + height - r, r); // draw left and top left corner
ctxi.arcTo(x, y, x + r, y, r);
ctxi.closePath();
if (fill) {
ctxi.fill();
}
if (stroke) {
ctxi.stroke();
}
}
}
_app.log('进入绘制二维码方法完毕')
_app.hideLoading();
}
function getShreUserPosterBackground(objs) { //检查背景图是否存在于本地, 若存在直接返回, 否则调用getShreUserPosterBackgroundFc方法
let {
backgroundImage,
type
} = objs;
return new Promise(async (resolve, reject) => {
try {
_app.showLoading('正在获取海报背景图');
const savedFilePath = await getShreUserPosterBackgroundFc(objs)
_app.hideLoading();
resolve(savedFilePath);
} catch (e) {
_app.hideLoading();
_app.showToast('获取分享用户背景图失败:' + JSON.stringify(e));
_app.log(JSON.stringify(e));
reject(e);
}
})
}
function getPosterStorage(type) {
return _app.getStorageSync(getStorageKey(type));
}
function removePosterStorage(type) {
const ShreUserPosterBackgroundKey = getStorageKey(type);
const pbg = _app.getStorageSync(ShreUserPosterBackgroundKey);
if (pbg && pbg.path) {
_app.removeStorageSync(ShreUserPosterBackgroundKey);
}
}
function setPosterStorage(type, data) {
_app.setStorage(getStorageKey(type), data);
}
function getStorageKey(type) {
return ShreUserPosterBackgroundKey + (type || 'default');
}
function getShreUserPosterBackgroundFc(objs, upimage) { //下载并保存背景图方法
let {
backgroundImage,
type
} = objs;
_app.log('获取分享背景图, 尝试清空本地数据');
return new Promise(async (resolve, reject) => {
try {
_app.showLoading('正在下载海报背景图');
_app.log('没有从后端获取的背景图片路径, 尝试从后端获取背景图片路径');
let image = backgroundImage?backgroundImage:(await _app.getPosterUrl(objs));
image = (await base64ToPathFn(image));
_app.log('尝试下载并保存背景图:' + image);
const savedFilePath = await _app.downLoadAndSaveFile_PromiseFc(image);
if (savedFilePath) {
_app.log('下载并保存背景图成功:' + savedFilePath);
const imageObj = await _app.getImageInfo_PromiseFc(savedFilePath);
_app.log('获取图片信息成功');
const returnObj = {
path: savedFilePath,
width: imageObj.width,
height: imageObj.height,
name: _app.fileNameInPath(image)
}
_app.log('拼接背景图信息对象成功:' + JSON.stringify(returnObj));
// #ifndef H5
setPosterStorage(type, { ...returnObj
});
// #endif
_app.hideLoading();
_app.log('返回背景图信息对象');
resolve({ ...returnObj
});
} else {
_app.hideLoading();
reject('not find savedFilePath');
}
} catch (e) {
//TODO handle the exception
reject(e);
}
});
}
module.exports = {
getSharePoster,
setText,
setImage,
drawText,
drawImage,
drawQrCode,
drawFillRect,
drawStrokeRect,
drawRoundStrokeRect,
drawRoundFillRect
}
... ...