commit d9e2784c1b47acae6a9c4baaa30b5c12bfebf5d3
Author: RIceWqy <1840169763@qq.com>
Date: Thu Dec 14 21:15:04 2023 +0800
init
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f19d0a8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/node_modules/*
+/unpackage/*
+!/unpackage/res/*
+/.idea/*
\ No newline at end of file
diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json
new file mode 100644
index 0000000..81f13f4
--- /dev/null
+++ b/.hbuilderx/launch.json
@@ -0,0 +1,16 @@
+{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+ // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+ "version": "0.0",
+ "configurations": [{
+ "default" :
+ {
+ "launchtype" : "local"
+ },
+ "mp-weixin" :
+ {
+ "launchtype" : "local"
+ },
+ "type" : "uniCloud"
+ }
+ ]
+}
diff --git a/App.vue b/App.vue
new file mode 100644
index 0000000..8af619b
--- /dev/null
+++ b/App.vue
@@ -0,0 +1,15 @@
+
+
+
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..68bc927
--- /dev/null
+++ b/README.md
@@ -0,0 +1,236 @@
+
+
+vue3版本正式发布,持续更新中
+
+### :sparkles: 开源不易,给个star吧~ 问题反馈交流:648050824
+
+
+
+[官方地址: https://www.shopro.top](https://www.shopro.top)
+
+[插件地址: https://ext.dcloud.net.cn/plugin?id=10180](https://ext.dcloud.net.cn/plugin?id=10180)
+
+[vue2码云仓库: https://gitee.com/itmonkey-cn/shopro.git](https://gitee.com/itmonkey-cn/shopro.git)
+
+[vue3码云仓库: https://gitee.com/sheepjs/shopro-uniapp](https://gitee.com/sheepjs/shopro-uniapp)
+
+[github仓库:https://github.com/ITmonkey-cn/shopro.git](https://github.com/ITmonkey-cn/shopro.git)
+
+
+# 部分页面展示
+
+
+# Shopro使用说明
+
+1. 首次安装需要 npm i 加载相关依赖
+
+2. 基于uni-app,需要下载hbuilderX进行编译
+
+3. manifest.json中配置相关信息
+
+
+
+# Shopro演示站
+
+|  |  |  |
+|------------------------------------------------- | ---------------------------------------- | ---------------------------------- |
+| 微信小程序 | H5二维码 | 安卓apk (普通浏览器扫描) |
+
+
+
+
+# 更新日志
+## 更新vue3版本
+vue3版本正式上线!将持续更新+开源,欢迎下载使用,望点赞+收藏~
+
+[官方地址: https://www.shopro.top](https://www.shopro.top)
+
+[插件地址: https://ext.dcloud.net.cn/plugin?id=10180](https://ext.dcloud.net.cn/plugin?id=10180)
+
+[vue2码云仓库: https://gitee.com/itmonkey-cn/shopro.git](https://gitee.com/itmonkey-cn/shopro.git)
+
+[vue3码云仓库: https://gitee.com/sheepjs/shopro-uniapp](https://gitee.com/sheepjs/shopro-uniapp)
+
+[github仓库:https://github.com/ITmonkey-cn/shopro.git](https://github.com/ITmonkey-cn/shopro.git)
+
+## V1.4.0(2023-02-24)
+1. 修复积分记录上拉加载更多
+2. 修复小程序分类左侧数据过多,滚动问题
+3. 修复门店申请,选择地区,没有区级单位
+4. 修复日志取值
+5. 修复登录流程、优化自提时间不能选择当前时间之前
+6. 修复支付支持 v3
+7. 修复隐私协议框跳转问题
+8. 修复导航栏、状态栏
+9. 修复小程序上传报错
+10. 修复小程序消息通知偶发订阅报错问题
+11. 修复服务商拉起失败问题
+12. 修复扫码核销、核销总码
+13. 优化app登录\微信小程序登录
+
+## V1.3.8(2022-01-08)
+1. 新增商品购买输入数量
+2. 新增商品评价内容过滤
+3. 新增充值到余额
+4. 新增消费送积分
+5. 修复首页拼团组件标题取值错误问题
+6. 修复物流列表真机样式错乱问题
+7. 修复某些ios机型优惠券不显示
+8. 修复自定义底部导航分享后,返回首页底部导航不显示问题
+9. 修复商品评论图片预览问题
+
+## V1.3.7(2021-10-18)
+1. 新增 商品订单申请开具发票功能
+2. 修复 用户协议,隐私协议,门店申请协议,自提协议等富文本跳转
+3. 修复 小程序端弹窗图片,非https协议无法保存的问题
+4. 修复 用户信息页面刷新时数据丢失问题
+5. 修复 用户信息页面修改密码点击无效问题
+6. 修复 客服页面刷新,切换为默认客服问题
+7. 修复 客服中,商品和订单,多次打开时列表内容重复问题
+8. 修复 登录、注册、找回密码,获取验证码按钮未显示问题
+9. 修复 轮播图组件参数
+10. 优化 小程序端自提商品二维码不稳定问题
+11. 优化 商家中心,订单金额的统计规则
+12. 优化 钱包提现规则
+13. 优化 商品列表搜索内容,存入搜索历史记录
+14. 优化 商品详情优惠券 显示已领取状态
+
+
+## V1.3.6(2021-8-30)
+1. 优化 小程序性能问题,更换router底层依赖版本,精简店铺装修组件
+2. 修复 登录卡片隐藏后,需要点击两次才能调起的问题
+3. 修复 微信小程序,进入直播内容页面,跳转商品详情后,无法返回上一级的问题
+4. 修复搜索页跳转商品列表,商品卡片偶尔重复问题
+5. 修复门店中心的订单详情,下单时间NaN问题
+6. 修复微信小程序真机测试时,自提商品核销码生成不稳定的问题
+7. 修复微信小程序,登录错误,显示The given payload报错的问题。
+8. 修复ios部分机型,首页装修优惠券背景空白问题
+9. 重构 入口文件和shopro启动流程
+10. 重构 vuex相关代码,拆分精简数据。
+11. 优化 优惠券相关逻辑和样式
+12. 修复 门店禁用后,前台还展示的问题
+13. 优化 购物车逻辑
+14. 优化 瀑布流排版不稳定(左右排列错误)
+15. 优化 日历无法快速切换年份
+16. 优化 选择商品规格组件
+17. 优化 分享海报
+
+## V1.3.2(2021-6-30)
+1. 修复秒杀卡片百分比改为件数,统一百分比计算
+2. 修复门店地址信息过长会被遮盖
+3. 修复苹果6s小程序端,分销中心弹窗不出来
+4. 修复门店订单详情,单笔商品数量过多,底部发货按钮顶起
+5. 修复商品卡片,添加添加购物车库存无限制问题
+6. 修复小程序端秒杀卡片,跳转详情问题
+7. 优化小程序端,确认订单优惠金额样式异常问题
+8. 优化海报,首页banner裁剪方式
+9. 优化地址定位问题,改为选择位置
+10. 优化确认订单,配送自提点的默认手机号问题
+11. 优化购物车失效商品拦截,
+12. 优化确认订单配送商品无经纬度等错误异常
+13. 优化门店申请,位置选择
+14. 优化瀑布流左右偶发不均问题
+
+
+## V1.3.1(2021-6-17)
+1. 优化自提点协议勾选检测。
+2. 修复无自提门店,选择自提方式报错
+3. 修复商品规格滑动问题
+4. 修复一级分类,快速购买,持续loading问题
+5. 修复分销中心分享链接,无法复制问题
+6. 修复确认订单商品计数问题
+7. 优化app端底部安全区域问题
+8. 新增app端苹果登录
+9. 更多细节体验优化,可扫码体验~
+
+## V1.3.0(2021-6-8)
+1. 重构所有页面,重新设计了样式,全面使用uview替换color-ui,感谢uview团队!
+2. 优化页面加载速度,重写初始化流程,兼容H5的hash模式与history模式
+3. 重写登录注册模块,自动登录注册、绑定/解绑 第三方授权登录信息,更新微信小程序最新的getUserProfile接口
+4. 重构分享逻辑,分享信息使用状态管理,解决重复冗余加载,使用spm参数构造,支持添加自定义参数,精确的分享链路追踪(分享人、分享方式、页面、分享平台、受邀请人平台)解决了因小程序码参数苏的位数限制导致无法支持长页面和大用户ID被截断的问题。(之前的海报和分享卡片将作废)
+5. 添加多提现方式(包含支付宝、微信企业付款、银行卡)
+6. 重写海报模块
+7. 更新了路由拦截和请求拦截器。
+8. 重构App权限请求和加载速度
+9. 默认使用原生底部导航,可修改代码实现自定义底部导航和后端对接
+10. 更多重构细节体验优化,可扫码体验~
+
+
+## V1.2.0(2021-1-12)
+1. 新增官方客服
+2. 新增分销中心,搭配后台强大的分销功能
+3. 新增全局静态资源的服务地址
+4. 新增uView UI 部分组件(特别鸣谢)
+5. 优化IOS APP的网络权限验证流程
+6. 优化海报的头像位置,适应小屏机型
+7. 优化多选项卡切换的数据抖动问题
+8. 优化H5微信支付的回调逻辑
+7. 修复IOS App的webview内核,防止被Appstore审核被拒
+8. 更多细节优化,可扫码体验~
+## 更新功能部分截图
+
+
+
+## V1.1.2(2020-10-15)
+1. 新增:分享到朋友圈
+2. 优化:商品详情页体验
+3. 优化:分类页体验
+4. 修复:商品购买计数器相关bug
+5. 修复:小程序分享后空白页(适配新规则)
+6. 修复:小程序自动更新版本报错
+7. 其他:相关优化,问题修复。
+
+
+## V1.0.7(2020-09-29)
+1. 新增:多配送方式(到店自提、商家配送、自动发货)和对应详情列表页面
+2. 新增:用户商家中心,门店切换,输码扫码核销,门店信息查看,发货,交易信息统计。
+3. 新增:物流信息,对接快递鸟物流查询,多包裹列表。
+4. 新增:商品售后,完善商品售后流程,服务单详情,售后进度查询和通知。
+5. 新增:全局优惠券,优化优惠券领取使用相关。
+6. 新增:部分页面下拉刷新,优化体验
+7. 新增:第三方客服,跟进购物闭环。
+8. 新增:微信,公众号地址导入。
+9. 新增:多分类灵活配置,支持立即购买(类外卖)
+10. 新增:app端,隐私协议相关。
+11. 优化:海报升级体验
+12. 优化: 富文本相关
+14. 优化:小程序登录提示
+15. 优化:首页推荐商品加载更多
+16. 修复:低版本tabbar首次不渲染。
+17. 修复:iphonX底部安全区域问题。
+18. 修复:直播列表瀑布流排序问题
+## 更新功能部分截图
+
+
+
+
+## V1.0.6(2020-07-16)
+1. 新增:底部导航购物车角标
+2. 新增:单规格商品选择
+3. 新增: 分享海报权限控制,必须得登录
+4. 修复:自定义底部导航,带参报错
+5. 修复:拼团商品数量选择限制
+6. 修复:头部搜索为空查询。
+7. 优化:我的拼团下拉刷新
+8. 优化:商品下架,详情提醒
+9. 以及后台相关修改优化。
+
+
+## V1.0.5(2020-07-10)
+1. 新增:自定义底部导航。后台返回底部导航数据,跳转任意页面,如果没有默认使用原生导航。
+2. 新增:悬浮工具按钮。后台控制按钮显示页面, 工具按钮可以是弹窗,也可跳转页面。
+3. 新增: 广告弹窗。后台控制弹窗显示页面,单次或者多次。
+4. 新增:小程序分包。优化了不能开发模式不能预览,相应速度。
+5. 新增: easycom组件引入。减少繁琐的组件引入(控制台提示的分包建议并不合理,可以忽略)
+6. 修复:支付宝部分退款问题
+7. 修复:小程序用户登录,无感登录支付
+8. 修复:商品分类优化
+9. 修复:小程序端授权登录session_key时效问题
+10. 优化部分UI界面性能体验,更多后台新增功能可去官网体验~
+
+## V1.0.4(2020-06-09)
+1.首次开源发布
+
+
+
+
diff --git a/androidPrivacy.json b/androidPrivacy.json
new file mode 100644
index 0000000..a78485c
--- /dev/null
+++ b/androidPrivacy.json
@@ -0,0 +1,3 @@
+{
+ "prompt" : "none"
+}
diff --git a/components/shopro-auth-modal/shopro-auth-modal.vue b/components/shopro-auth-modal/shopro-auth-modal.vue
new file mode 100644
index 0000000..8499167
--- /dev/null
+++ b/components/shopro-auth-modal/shopro-auth-modal.vue
@@ -0,0 +1,992 @@
+
+
+
+
+
+
+
+
+ 账号登录
+
+ 短信登录
+
+
+ 如果未设置过密码,请点击忘记密码
+
+
+
+ 账号
+
+
+
+
+ {{ form["accountLogin"].error.account || "" }}
+
+
+
+
+ 密码
+
+
+
+
+ {{ form["accountLogin"].error.password || "" }}
+
+
+
+
+
+
+
+
+
+
+ 账号登录
+
+
+ 短信登录
+
+
+ 未注册手机号请先点击下方立即注册
+
+
+
+ 手机号
+
+
+
+ {{ form["smsLogin"].error.mobile || "" }}
+
+
+
+ 验证码
+
+
+
+ {{ form["smsLogin"].error.code || "" }}
+
+
+
+
+
+
+
+ 注册
+ 请使用本人手机号完成注册
+
+
+
+ 手机号
+
+
+
+ {{ form["register"].error.mobile || "" }}
+
+
+
+ 密码
+
+
+ {{ form["register"].error.password || "" }}
+
+
+
+ 验证码
+
+
+
+ {{ form["register"].error.code || "" }}
+
+
+
+
+
+
+
+ 忘记密码
+ 为了您的账号安全,修改密码前请先进行安全验证
+
+
+
+ 手机号
+
+
+
+ {{ form["forgotPwd"].error.mobile || "" }}
+
+
+
+
+ 验证码
+
+
+ {{ form["forgotPwd"].error.code || "" }}
+
+
+
+
+ 密码
+
+
+
+ {{ form["forgotPwd"].error.password || "" }}
+
+
+
+
+
+
+
+ 绑定手机号
+ 为了您的账号安全,请绑定手机号
+
+
+
+ 手机号
+
+
+
+ {{ form["bindMobile"].error.mobile || "" }}
+
+
+
+ 验证码
+
+
+
+ {{ form["bindMobile"].error.code || "" }}
+
+
+
+
+
+
+ 修改密码
+
+
+
+
+ 旧密码
+
+
+
+ {{ form["changePwd"].error.oldPassword || "" }}
+
+
+
+
+ 新密码
+
+
+
+ {{ form["changePwd"].error.newPassword || "" }}
+
+
+
+
+ 确认密码
+
+
+
+ {{ form["changePwd"].error.reNewPassword || "" }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 我已阅读并遵守
+
+
+ 《用户协议》
+
+ 与
+
+ 《隐私协议》
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/shopro-canvas/shopro-canvas.vue b/components/shopro-canvas/shopro-canvas.vue
new file mode 100644
index 0000000..004e139
--- /dev/null
+++ b/components/shopro-canvas/shopro-canvas.vue
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/shopro-coupon/shopro-coupon.vue b/components/shopro-coupon/shopro-coupon.vue
new file mode 100644
index 0000000..16b3ed9
--- /dev/null
+++ b/components/shopro-coupon/shopro-coupon.vue
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+ ¥
+ {{ couponData.amount }}
+ {{ couponData.name }}
+
+ 满{{ couponData.enough }}元可用
+
+ 有效期:{{ $u.timeFormat(couponData.usetime.start, 'yyyy-mm-dd') }} 至 {{ $u.timeFormat(couponData.usetime.end, 'yyyy-mm-dd') }}
+
+
+
+
+
+
+
+ 仅剩{{ stock }}张
+
+
+
+
+
+
+
+
+
diff --git a/components/shopro-empty/shopro-empty.vue b/components/shopro-empty/shopro-empty.vue
new file mode 100644
index 0000000..7ceb170
--- /dev/null
+++ b/components/shopro-empty/shopro-empty.vue
@@ -0,0 +1,77 @@
+
+
+
+ {{ tipText }}
+
+
+
+
+
+
+
+
+
diff --git a/components/shopro-float-btn/shopro-float-btn.vue b/components/shopro-float-btn/shopro-float-btn.vue
new file mode 100644
index 0000000..dc50a2e
--- /dev/null
+++ b/components/shopro-float-btn/shopro-float-btn.vue
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/shopro-goods-card/shopro-goods-card.vue b/components/shopro-goods-card/shopro-goods-card.vue
new file mode 100644
index 0000000..2aa27ca
--- /dev/null
+++ b/components/shopro-goods-card/shopro-goods-card.vue
@@ -0,0 +1,348 @@
+
+
+
+
+
+
+
+
+
+ {{ typeMap[type].text }}
+
+ {{ title }}
+
+ {{ subtitle }}
+
+ {{ item }}
+
+
+
+
+
+
+ {{ price }}
+ ¥{{ originPrice }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/shopro-live-card/shopro-live-card.vue b/components/shopro-live-card/shopro-live-card.vue
new file mode 100644
index 0000000..3ea10b3
--- /dev/null
+++ b/components/shopro-live-card/shopro-live-card.vue
@@ -0,0 +1,361 @@
+
+
+
+
+
+
+
+
+ {{ liveStatus[liveState].title }}
+
+ {{ detail.name }}
+
+
+
+
+ {{ detail.anchor_name }}
+
+
+
+
+
+
+ ¥{{ goods.price }}
+
+ {{ liveGoodsList.length }}+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ liveStatus[liveState].title }}
+
+ {{ detail.name }}
+
+
+
+
+
+
+
+
diff --git a/components/shopro-mini-card/shopro-mini-card.vue b/components/shopro-mini-card/shopro-mini-card.vue
new file mode 100644
index 0000000..ab6ba0b
--- /dev/null
+++ b/components/shopro-mini-card/shopro-mini-card.vue
@@ -0,0 +1,130 @@
+
+
+
+
+
+ {{ title }}
+ {{ subtitle }}
+
+
+
+ {{ price }}
+ {{ originPrice }}
+
+
+
+
+
+
+
+
+
diff --git a/components/shopro-navbar/shopro-navbar.vue b/components/shopro-navbar/shopro-navbar.vue
new file mode 100644
index 0000000..faa863c
--- /dev/null
+++ b/components/shopro-navbar/shopro-navbar.vue
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+ {{ backText || '' }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/shopro-notice-modal/shopro-notice-modal.vue b/components/shopro-notice-modal/shopro-notice-modal.vue
new file mode 100644
index 0000000..5fc954e
--- /dev/null
+++ b/components/shopro-notice-modal/shopro-notice-modal.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
diff --git a/components/shopro-share/shopro-share.vue b/components/shopro-share/shopro-share.vue
new file mode 100644
index 0000000..c451b25
--- /dev/null
+++ b/components/shopro-share/shopro-share.vue
@@ -0,0 +1,571 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 微信好友
+
+
+
+
+ 生成海报
+
+
+
+
+ 复制链接
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/shopro-sku/shopro-sku.vue b/components/shopro-sku/shopro-sku.vue
new file mode 100644
index 0000000..14044c9
--- /dev/null
+++ b/components/shopro-sku/shopro-sku.vue
@@ -0,0 +1,589 @@
+
+
+
+
+
+
+
+
+
+
+ {{ goodsInfo.title }}
+
+
+ {{ currentSkuPrice.price_text || goodsInfo.price }}
+
+
+ ¥{{ currentSkuPrice.groupon_price || (goodsInfo.activity_type === 'groupon' ? goodsInfo.groupon_price : goodsInfo.price) }}
+
+ ¥{{ currentSkuPrice.price || goodsInfo.price }}
+
+ 库存{{ currentSkuPrice.stock || goodsInfo.stock }}件
+
+
+
+
+
+
+
+ {{ s.name }}
+
+
+
+
+
+
+
+ 购买数量
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/shopro-tabbar/shopro-tabbar.vue b/components/shopro-tabbar/shopro-tabbar.vue
new file mode 100644
index 0000000..9998f08
--- /dev/null
+++ b/components/shopro-tabbar/shopro-tabbar.vue
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+ {{ cartNum }}
+
+
+
+ {{ tab.name }}
+
+
+
+
+
+
+
+
+
diff --git a/env.js b/env.js
new file mode 100644
index 0000000..8bb7f8f
--- /dev/null
+++ b/env.js
@@ -0,0 +1,18 @@
+/**
+ * Shopro全局配置文件 v1.4.0
+ */
+
+// 接口根域名 https://demo.shopro.top
+export const BASE_URL = 'https://demo.shopro.top'
+
+// 接口路径
+export const API_URL = `${BASE_URL}/addons/shopro/`
+
+// 全局网络图片地址变量,css背景图片地址变量在uni.scss中定义
+export const IMG_URL = 'https://file.shopro.top'
+
+//高德地图开发者Web服务key,逆坐标解析必须
+export const MAP_KEY = '2658492***4a9ac5839753dc'
+
+//后台是否开通直播权限,根据情况在manifest.json中引入直播插件,并在pages.json中打开直播页面
+export const HAS_LIVE = false
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..3a3e9a8
--- /dev/null
+++ b/main.js
@@ -0,0 +1,33 @@
+import Vue from "vue";
+import App from "./App";
+import {
+ router,
+ RouterMount
+} from "@/shopro/router";
+import store from "@/shopro/store";
+import uView from "uview-ui";
+import shopro from "@/shopro";
+
+
+async function bootstrap() {
+ App.mpType = "app";
+ //引入路由
+ Vue.use(router);
+ // 引入全局uView
+ Vue.use(uView);
+ // 加载shopro
+ Vue.use(shopro);
+
+ const app = new Vue({
+ store,
+ ...App
+ });
+ // #ifdef H5
+ RouterMount(app, router, "#app");
+ // #endif
+ // #ifndef H5
+ app.$mount();
+ // #endif
+}
+
+bootstrap();
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..6d0a852
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,233 @@
+{
+ "name" : "Shopro商城",
+ "appid" : "__UNI_*****06",
+ "description" : "Shopro商城",
+ "versionName" : "1.4.0",
+ "versionCode" : 140,
+ "transformPx" : false,
+ "app-plus" : {
+ "optimization" : {
+ "subPackages" : true
+ },
+ "runmode" : "liberate",
+ "safearea" : {
+ "background" : "#fff",
+ "bottom" : {
+ "offset" : "auto"
+ }
+ },
+ "splashscreen" : {
+ "alwaysShowBeforeRender" : true,
+ "waiting" : true,
+ "autoclose" : true,
+ "delay" : 200
+ },
+ "usingComponents" : true,
+ "nvueCompiler" : "uni-app",
+ "compilerVersion" : 3,
+ "modules" : {
+ "Geolocation" : {},
+ "Maps" : {},
+ "OAuth" : {},
+ "Payment" : {},
+ "Share" : {},
+ "VideoPlayer" : {}
+ },
+ "distribute" : {
+ "android" : {
+ "permissions" : [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "abiFilters" : [ "armeabi-v7a", "arm64-v8a" ]
+ },
+ "ios" : {
+ "capabilities" : {
+ "entitlements" : {
+ "com.apple.developer.associated-domains" : [ "applinks:m.*****.top" ]
+ }
+ },
+ "privacyDescription" : {
+ "NSLocationAlwaysAndWhenInUseUsageDescription" : "需要同意获取您的位置信息才能展示附近信息",
+ "NSLocationAlwaysUsageDescription" : "需要同意获取您的位置信息才能展示附近信息",
+ "NSLocationWhenInUseUsageDescription" : "需要同意获取您的位置信息才能展示附近信息",
+ "NSPhotoLibraryAddUsageDescription" : "需要同意访问您的相册才能保存图片",
+ "NSPhotoLibraryUsageDescription" : "需要同意访问您的相册才能选取图片",
+ "NSCameraUsageDescription" : "需要同意访问您的摄像头才能拍摄照片",
+ "NSUserTrackingUsageDescription" : "请放心,开启权限不会获取您在其他站点的隐私信息,该权限仅用于标识设备并保障服务安全与提升浏览体验"
+ }
+ },
+ "sdkConfigs" : {
+ "ad" : {},
+ "payment" : {
+ "alipay" : {
+ "__platform__" : [ "ios", "android" ]
+ },
+ "weixin" : {
+ "__platform__" : [ "ios", "android" ],
+ "appid" : "wx522b*****ae",
+ "UniversalLinks" : "https://m.*****.top/uni-universallinks/__U*****"
+ }
+ },
+ "geolocation" : {
+ "amap" : {
+ "__platform__" : [ "android" ],
+ "appkey_ios" : "949f86b55f*****de010206494",
+ "appkey_android" : "0d51d7*****ebf2bcbe264dac409"
+ }
+ },
+ "maps" : {
+ "amap" : {
+ "appkey_ios" : "949f86b55f*****de010206494",
+ "appkey_android" : "0d51d7a*****f2bcbe264dac409"
+ }
+ },
+ "oauth" : {
+ "weixin" : {
+ "appid" : "wx522b*****319ae",
+ "appsecret" : "531b39d953f9*****e83c7238fb4dc",
+ "UniversalLinks" : "https://m.*****.top/uni-universallinks/__UNI__EB95F06"
+ },
+ "apple" : {}
+ },
+ "share" : {
+ "weixin" : {
+ "appid" : "wx522*****319ae",
+ "UniversalLinks" : "https://m.*****.top/uni-universallinks/__UNI__EB95F06"
+ }
+ },
+ "push" : {}
+ },
+ "icons" : {
+ "android" : {
+ "hdpi" : "",
+ "xhdpi" : "",
+ "xxhdpi" : "",
+ "xxxhdpi" : ""
+ },
+ "ios" : {
+ "appstore" : "",
+ "ipad" : {
+ "app" : "",
+ "app@2x" : "",
+ "notification" : "",
+ "notification@2x" : "",
+ "proapp@2x" : "",
+ "settings" : "",
+ "settings@2x" : "",
+ "spotlight" : "",
+ "spotlight@2x" : ""
+ },
+ "iphone" : {
+ "app@2x" : "",
+ "app@3x" : "",
+ "notification@2x" : "",
+ "notification@3x" : "",
+ "settings@2x" : "",
+ "settings@3x" : "",
+ "spotlight@2x" : "",
+ "spotlight@3x" : ""
+ }
+ }
+ },
+ "splashscreen" : {
+ "useOriginalMsgbox" : false
+ }
+ },
+ "kernel" : {
+ "ios" : "WKWebview"
+ }
+ },
+ "quickapp" : {},
+ "mp-weixin" : {
+ "appid" : "wx3*****67dd0",
+ "setting" : {
+ "urlCheck" : false,
+ "es6" : true, //消除大多数样式警告
+ "minified" : true,
+ "postcss" : true,
+ "checkSiteMap" : false // 关闭页面索引检测
+ },
+ "optimization" : {
+ "subPackages" : true
+ },
+ "plugins" : {},
+ //这段代码,需要放到plugins中。
+ //只有后台开通小程序直播功能权限,才可以打开,不然报错,程序无法运行。
+ // "live-player-plugin": {
+ // "version": "1.3.2", // 注意填写该直播组件最新版本号,微信开发者工具调试时可获取最新版本号
+ // "provider": "wx2b03c6e691cd7370" // 必须填该直播组件appid,该示例值即为直播组件appid
+ // }
+ "usingComponents" : true,
+ "permission" : {
+ "scope.userLocation" : {
+ "desc" : "计算附近商家位置"
+ }
+ },
+ "requiredPrivateInfos" : [ "getLocation", "chooseLocation", "chooseAddress" ]
+ },
+ "mp-alipay" : {
+ "usingComponents" : true,
+ "component2" : true
+ },
+ "mp-qq" : {
+ "appid" : ""
+ },
+ "mp-baidu" : {
+ "usingComponents" : true,
+ "appid" : ""
+ },
+ "mp-toutiao" : {
+ "usingComponents" : true,
+ "appid" : ""
+ },
+ "h5" : {
+ "template" : "template.h5.html",
+ "router" : {
+ "mode" : "history",
+ "base" : ""
+ },
+ "optimization" : {
+ "treeShaking" : {
+ "enable" : true
+ }
+ },
+ "title" : "Shopro商城",
+ "devServer" : {
+ "https" : false,
+ "port" : ""
+ },
+ "sdkConfigs" : {
+ "maps" : {
+ "qqmap" : {
+ "key" : "4NRBZ-CM*****-ARYXH-DCFH3"
+ }
+ }
+ },
+ "domain" : "*****"
+ },
+ "_spaceID" : "f0536a*****8350-2aa7c3e11334"
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..3238a99
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,138 @@
+{
+ "name": "shopro-plus",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "shopro-plus",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "jweixin-module": "^1.6.0",
+ "uni-read-pages": "^1.0.5",
+ "uni-simple-router": "^2.0.6",
+ "vconsole": "^3.7.0"
+ },
+ "devDependencies": {}
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.23.6",
+ "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.23.6.tgz",
+ "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==",
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/copy-text-to-clipboard": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmmirror.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz",
+ "integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/core-js": {
+ "version": "3.34.0",
+ "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.34.0.tgz",
+ "integrity": "sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag==",
+ "hasInstallScript": true
+ },
+ "node_modules/jweixin-module": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmmirror.com/jweixin-module/-/jweixin-module-1.6.0.tgz",
+ "integrity": "sha512-dGk9cf+ipipHmtzYmKZs5B2toX+p4hLyllGLF6xuC8t+B05oYxd8fYoaRz0T30U2n3RUv8a4iwvjhA+OcYz52w=="
+ },
+ "node_modules/mutation-observer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmmirror.com/mutation-observer/-/mutation-observer-1.0.3.tgz",
+ "integrity": "sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA=="
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
+ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
+ },
+ "node_modules/uni-read-pages": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmmirror.com/uni-read-pages/-/uni-read-pages-1.0.5.tgz",
+ "integrity": "sha512-GkrrZ0LX0vn9R5k6RKEi0Ez3Q3e2vUpjXQ8Z6/K/d28KudI9ajqgt8WEjQFlG5EPm1K6uTArN8LlqmZTEixDUA==",
+ "hasInstallScript": true
+ },
+ "node_modules/uni-simple-router": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmmirror.com/uni-simple-router/-/uni-simple-router-2.0.7.tgz",
+ "integrity": "sha512-8FKv5dw7Eoonm0gkO8udprrxzin0fNUI0+AvIphFkFRH5ZmP5ZWJ2pvnWzb2NiiqQSECTSU5VSB7HhvOSwD5eA=="
+ },
+ "node_modules/vconsole": {
+ "version": "3.15.1",
+ "resolved": "https://registry.npmmirror.com/vconsole/-/vconsole-3.15.1.tgz",
+ "integrity": "sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==",
+ "dependencies": {
+ "@babel/runtime": "^7.17.2",
+ "copy-text-to-clipboard": "^3.0.1",
+ "core-js": "^3.11.0",
+ "mutation-observer": "^1.0.3"
+ }
+ }
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.23.6",
+ "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.23.6.tgz",
+ "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==",
+ "requires": {
+ "regenerator-runtime": "^0.14.0"
+ }
+ },
+ "copy-text-to-clipboard": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmmirror.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz",
+ "integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q=="
+ },
+ "core-js": {
+ "version": "3.34.0",
+ "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.34.0.tgz",
+ "integrity": "sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag=="
+ },
+ "jweixin-module": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmmirror.com/jweixin-module/-/jweixin-module-1.6.0.tgz",
+ "integrity": "sha512-dGk9cf+ipipHmtzYmKZs5B2toX+p4hLyllGLF6xuC8t+B05oYxd8fYoaRz0T30U2n3RUv8a4iwvjhA+OcYz52w=="
+ },
+ "mutation-observer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmmirror.com/mutation-observer/-/mutation-observer-1.0.3.tgz",
+ "integrity": "sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA=="
+ },
+ "regenerator-runtime": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
+ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
+ },
+ "uni-read-pages": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmmirror.com/uni-read-pages/-/uni-read-pages-1.0.5.tgz",
+ "integrity": "sha512-GkrrZ0LX0vn9R5k6RKEi0Ez3Q3e2vUpjXQ8Z6/K/d28KudI9ajqgt8WEjQFlG5EPm1K6uTArN8LlqmZTEixDUA=="
+ },
+ "uni-simple-router": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmmirror.com/uni-simple-router/-/uni-simple-router-2.0.7.tgz",
+ "integrity": "sha512-8FKv5dw7Eoonm0gkO8udprrxzin0fNUI0+AvIphFkFRH5ZmP5ZWJ2pvnWzb2NiiqQSECTSU5VSB7HhvOSwD5eA=="
+ },
+ "vconsole": {
+ "version": "3.15.1",
+ "resolved": "https://registry.npmmirror.com/vconsole/-/vconsole-3.15.1.tgz",
+ "integrity": "sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==",
+ "requires": {
+ "@babel/runtime": "^7.17.2",
+ "copy-text-to-clipboard": "^3.0.1",
+ "core-js": "^3.11.0",
+ "mutation-observer": "^1.0.3"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..752b733
--- /dev/null
+++ b/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "shopro-plus",
+ "version": "1.0.0",
+ "main": "main.js",
+ "scripts": {
+ "test": ""
+ },
+ "repository": {
+ "type": "git",
+ "url": ""
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "homepage": "",
+ "dependencies": {
+ "jweixin-module": "^1.6.0",
+ "uni-read-pages": "^1.0.5",
+ "uni-simple-router": "^2.0.6",
+ "vconsole": "^3.7.0"
+ },
+ "description": "",
+ "devDependencies": {}
+}
diff --git a/pages.json b/pages.json
new file mode 100644
index 0000000..42d88fb
--- /dev/null
+++ b/pages.json
@@ -0,0 +1,921 @@
+{
+ "easycom": {
+ "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue",
+ "^shopro-(.*)": "@/components/shopro-$1/shopro-$1.vue"
+ },
+
+ "pages": [{
+ "path": "pages/index/index",
+ "aliasPath": "/", //对于h5端你必须在首页加上aliasPath并设置为/
+ "style": {
+ "navigationBarTitleText": "首页",
+ "navigationBarTextStyle": "white",
+ "enablePullDownRefresh": true,
+ "navigationStyle": "custom",
+ "mp-alipay": {
+ "transparentTitle": "always",
+ "titlePenetrate": "YES",
+ "allowsBounceVertical": "NO"
+ }
+ },
+ "meta": {
+ "auth": false, //需要登录
+ "async": true, //是否同步
+ "title": "首页", //标题
+ "group": "商城" //分组
+ }
+ },
+ {
+ "path": "pages/index/category",
+ "style": {
+ "navigationBarTitleText": "分类"
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "分类",
+ "group": "商城"
+ }
+ },
+ {
+ "path": "pages/index/cart",
+ "style": {
+ "navigationBarTitleText": "购物车"
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "购物车",
+ "group": "商城"
+ }
+ },
+ {
+ "path": "pages/index/user",
+ "style": {
+ "navigationBarTitleText": "我的",
+ "navigationStyle": "custom",
+ "navigationBarTextStyle": "white",
+ "enablePullDownRefresh": true
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "我的",
+ "group": "商城"
+ }
+ },
+ {
+ "path": "pages/index/view",
+ "name": "view",
+ "style": {
+ "navigationBarTitleText": "",
+ "enablePullDownRefresh": true
+
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "自定义页面",
+ "group": "商城"
+ }
+ }
+ ],
+ "subPackages": [{
+ "root": "pages/activity",
+ "pages": [{
+ "path": "sign/index",
+ "style": {
+ "navigationBarTitleText": "签到中心"
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "签到中心",
+ "group": "应用"
+ }
+ },
+ {
+ "path": "seckill/list",
+ "style": {
+ "navigationBarTitleText": "限时秒杀",
+ "enablePullDownRefresh": true
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "限时秒杀",
+ "group": "秒杀"
+ }
+ },
+ {
+ "path": "groupon/list",
+ "style": {
+ "navigationBarTitleText": "今日必拼",
+ "enablePullDownRefresh": true
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "今日必拼",
+ "group": "拼团"
+ }
+ },
+ {
+ "path": "groupon/detail",
+ "style": {
+ "navigationBarTitleText": "拼团详情",
+ "enablePullDownRefresh": true
+ },
+ "meta": {
+ "auth": false,
+ "async": false,
+ "title": "拼团详情",
+ "group": "拼团"
+ }
+ },
+ {
+ "path": "groupon/my-groupon",
+ "style": {
+ "navigationBarTitleText": "我的拼团",
+ "enablePullDownRefresh": true
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "我的拼团",
+ "group": "拼团"
+ }
+ },
+ {
+ "path": "discounts/list",
+ "style": {
+ "navigationBarTitleText": "优惠活动商品"
+ },
+ "meta": {
+ "auth": false,
+ "async": false,
+ "title": "优惠活动商品",
+ "group": "活动"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/app",
+ "pages": [
+ // {
+ // "path": "live/list",
+ // "style": {
+ // "navigationBarTitleText": "直播列表"
+ // },
+ // "meta": {
+ // "auth": false,
+ // "async": false,
+ // "title": "直播列表",
+ // "group": "直播"
+ // }
+ // },
+ {
+ "path": "score/list",
+ "style": {
+ "navigationBarTitleText": "积分商品"
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "积分商品",
+ "group": "积分"
+ }
+ },
+ {
+ "path": "coupon/list",
+ "style": {
+ "navigationBarTitleText": "优惠券中心",
+ "navigationStyle": "custom"
+
+
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "优惠券中心",
+ "group": "优惠券"
+ }
+ }, {
+ "path": "coupon/detail",
+ "style": {
+ "navigationBarTitleText": "优惠券详情",
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "优惠券详情",
+ "group": "优惠券"
+ }
+ },
+ {
+ "path": "merchant/index",
+ "style": {
+ "navigationBarTitleText": "门店中心",
+ "navigationStyle": "custom",
+ "enablePullDownRefresh": true,
+ "navigationBarTextStyle": "white"
+
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "门店中心",
+ "group": "门店"
+ }
+ },
+ {
+ "path": "merchant/apply",
+ "style": {
+ "navigationBarTitleText": "门店入驻",
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "门店入驻",
+ "group": "门店"
+ }
+ },
+ {
+ "path": "merchant/detail",
+ "style": {
+ "navigationBarTitleText": "订单详情"
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "订单详情",
+ "group": "订单"
+ }
+ },
+ {
+ "path": "merchant/info",
+ "style": {
+ "navigationBarTitleText": "门店详情"
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "门店详情",
+ "group": "门店"
+ }
+ },
+ {
+ "path": "merchant/list",
+ "style": {
+ "navigationBarTitleText": "我的门店"
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "我的门店",
+ "group": "门店"
+ }
+ },
+ {
+ "path": "commission/index",
+ "style": {
+ "navigationBarTitleText": "分销中心",
+ "enablePullDownRefresh": true,
+ "navigationStyle": "custom",
+ "navigationBarTextStyle": "white"
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "分销中心",
+ "group": "分销"
+ }
+ },
+ {
+ "path": "commission/team",
+ "style": {
+ "navigationBarTitleText": "我的团队",
+ "navigationStyle": "custom",
+ "navigationBarTextStyle": "white"
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "我的团队",
+ "group": "分销"
+ }
+ },
+ {
+ "path": "commission/commission-log",
+ "style": {
+ "navigationBarTitleText": "佣金明细",
+ "enablePullDownRefresh": true
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "佣金明细",
+ "group": "分销"
+ }
+ },
+ {
+ "path": "commission/order",
+ "style": {
+ "navigationBarTitleText": "分销订单",
+ "navigationStyle": "custom",
+ "navigationBarTextStyle": "white",
+ "enablePullDownRefresh": true
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "分销订单",
+ "group": "分销"
+ }
+ },
+ {
+ "path": "commission/goods",
+ "style": {
+ "navigationBarTitleText": "推广商品"
+
+
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "推广商品",
+ "group": "分销"
+ }
+ },
+ {
+ "path": "commission/apply",
+ "style": {
+ "navigationBarTitleText": "申请分销商",
+ "navigationStyle": "custom",
+ "navigationBarTextStyle": "white"
+
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "申请分销商",
+ "group": "分销"
+ }
+ },
+ {
+ "path": "commission/rankings",
+ "style": {
+ "navigationBarTitleText": "分销排行",
+ "navigationStyle": "custom",
+ "navigationBarTextStyle": "white"
+
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "分销排行",
+ "group": "分销"
+ }
+ },
+ {
+ "path": "commission/share-log",
+ "style": {
+ "navigationBarTitleText": "分享记录",
+ "navigationStyle": "custom",
+ "navigationBarTextStyle": "white",
+ "enablePullDownRefresh": true
+
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "分享记录",
+ "group": "分销"
+ }
+ }
+
+ ]
+ },
+ {
+ "root": "pages/goods",
+ "pages": [{
+ "path": "list",
+ "style": {
+ "navigationBarTitleText": "商品列表",
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "商品列表",
+ "group": "商品"
+ }
+ },
+ {
+ "path": "detail",
+ "style": {
+ "navigationBarTitleText": "商品详情",
+ "navigationStyle": "custom"
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "商品详情",
+ "group": "商品"
+ }
+ },
+ {
+ "path": "comment/add-comment",
+ "style": {
+ "navigationBarTitleText": "评价"
+ },
+ "meta": {
+ "auth": false,
+ "async": false,
+ "title": "评价",
+ "group": "商品"
+ }
+ },
+ {
+ "path": "comment/comment-list",
+ "style": {
+ "navigationBarTitleText": "评价列表"
+ },
+ "meta": {
+ "auth": false,
+ "async": false,
+ "title": "评价列表",
+ "group": "商品"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/order",
+ "pages": [{
+ "path": "confirm",
+ "style": {
+ "navigationBarTitleText": "确认订单"
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "确认订单",
+ "group": "订单"
+ }
+ },
+ {
+ "path": "payment/method",
+ "style": {
+ "navigationBarTitleText": "收银台"
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "收银台",
+ "group": "订单"
+ }
+ },
+ {
+ "path": "payment/result",
+ "style": {
+ "navigationBarTitleText": "支付结果"
+ },
+ "meta": {
+ "auth": false,
+ "async": false,
+ "title": "支付结果",
+ "group": "订单"
+ }
+ },
+ {
+ "path": "list",
+ "style": {
+ "navigationBarTitleText": "订单列表"
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "订单列表",
+ "group": "订单"
+ }
+ },
+ {
+ "path": "detail",
+ "style": {
+ "navigationBarTitleText": "订单详情"
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "订单详情",
+ "group": "订单"
+ }
+ },
+ {
+ "path": "after-sale/detail",
+ "style": {
+ "navigationBarTitleText": "售后详情"
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "售后详情",
+ "group": "订单"
+ }
+ },
+ {
+ "path": "after-sale/list",
+ "style": {
+ "navigationBarTitleText": "售后列表"
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "售后列表",
+ "group": "订单"
+ }
+ },
+ {
+ "path": "after-sale/log",
+ "style": {
+ "navigationBarTitleText": "售后记录"
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "售后记录",
+ "group": "订单"
+ }
+ },
+ {
+ "path": "after-sale/refund",
+ "style": {
+ "navigationBarTitleText": "申请售后"
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "申请售后",
+ "group": "订单"
+ }
+ },
+ {
+ "path": "express/distribution-detail",
+ "style": {
+ "navigationBarTitleText": "配送详情"
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "配送详情",
+ "group": "订单"
+ }
+ },
+ {
+ "path": "express/express-detail",
+ "style": {
+ "navigationBarTitleText": "物流详情"
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "物流详情",
+ "group": "订单"
+ }
+ },
+ {
+ "path": "express/express-list",
+ "style": {
+ "navigationBarTitleText": "包裹列表"
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "包裹列表",
+ "group": "订单"
+ }
+ },
+
+ {
+ "path": "express/store-address",
+ "style": {
+ "navigationBarTitleText": "选择自提点",
+ "navigationStyle": "custom",
+ "navigationBarTextStyle": "white"
+
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "选择自提点",
+ "group": "订单"
+ }
+ }
+
+ ]
+ },
+ {
+ "root": "pages/public",
+ "pages": [{
+ "path": "faq",
+ "style": {
+ "navigationBarTitleText": "常见问题"
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "常见问题",
+ "group": "通用"
+ }
+ },
+ {
+ "path": "feedback",
+ "style": {
+ "navigationBarTitleText": "问题反馈"
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "问题反馈",
+ "group": "通用"
+ }
+ },
+ {
+ "path": "chat/index",
+ "style": {
+ "navigationBarTitleText": "客服",
+ "navigationStyle": "custom",
+ "navigationBarTextStyle": "white"
+
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "客服",
+ "group": "通用"
+ }
+ },
+ {
+ "path": "search",
+ "style": {
+ "navigationBarTitleText": "搜索"
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "搜索",
+ "group": "通用"
+ }
+ },
+ {
+ "path": "richtext",
+ "style": {
+ "navigationBarTitleText": ""
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "富文本",
+ "group": "通用"
+ }
+ },
+ {
+ "path": "webview",
+ "style": {
+ "navigationBarTitleText": ""
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "外链",
+ "group": "通用"
+ }
+ },
+ {
+ "path": "404",
+ "name": "404",
+ "style": {
+ "navigationBarTitleText": "页面不存在"
+ }
+ },
+ {
+ "path": "loading",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom",
+ "enablePullDownRefresh": false
+ }
+
+ }
+ ]
+ },
+ {
+ "root": "pages/user",
+ "pages": [{
+ "path": "info",
+ "style": {
+ "navigationBarTitleText": "个人信息"
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "个人信息",
+ "group": "用户"
+ }
+ },
+ {
+ "path": "set",
+ "style": {
+ "navigationBarTitleText": "系统设置"
+ },
+ "meta": {
+ "auth": false,
+ "async": true,
+ "title": "系统设置",
+ "group": "通用"
+ }
+ },
+ {
+ "path": "view-log",
+ "style": {
+ "navigationBarTitleText": "浏览足迹"
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "浏览足迹",
+ "group": "用户"
+ }
+ },
+ {
+ "path": "wallet/index",
+ "style": {
+ "navigationBarTitleText": "我的钱包"
+
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "钱包",
+ "group": "用户"
+ }
+ },
+ {
+ "path": "wallet/withdraw",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom"
+
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "提现",
+ "group": "用户"
+ }
+ },
+ {
+ "path": "wallet/withdraw-log",
+ "style": {
+ "navigationBarTitleText": "提现记录"
+
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "提现记录",
+ "group": "用户"
+ }
+ },
+ {
+ "path": "wallet/top-up",
+ "style": {
+ "navigationBarTitleText": "充值",
+ "navigationStyle": "custom"
+
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "充值",
+ "group": "用户"
+ }
+ },
+ {
+ "path": "wallet/top-up-log",
+ "style": {
+ "navigationBarTitleText": "充值记录"
+
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "充值记录",
+ "group": "用户"
+ }
+ },
+ {
+ "path": "wallet/score-balance",
+ "style": {
+ "navigationBarTitleText": "积分余额",
+ "navigationStyle": "custom"
+
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "积分余额",
+ "group": "积分"
+ }
+ },
+ {
+ "path": "address/list",
+ "style": {
+ "navigationBarTitleText": "收货地址"
+
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "收货地址",
+ "group": "用户"
+ }
+ },
+ {
+ "path": "address/edit",
+ "style": {
+ "navigationBarTitleText": ""
+
+ },
+ "meta": {
+ "auth": true,
+ "async": false,
+ "title": "修改地址",
+ "group": "用户"
+ }
+ },
+ {
+ "path": "favorite",
+ "style": {
+ "navigationBarTitleText": "我的收藏"
+ },
+ "meta": {
+ "auth": true,
+ "async": true,
+ "title": "我的收藏",
+ "group": "用户"
+ }
+ }
+ ]
+ }
+ ],
+ "preloadRule": {
+ "pages/index/index": {
+ "network": "all",
+ "packages": ["pages/activity", "pages/user", "pages/goods", "pages/app", "pages/public",
+ "pages/order"
+ ]
+ }
+ },
+ "globalStyle": {
+ "navigationBarTextStyle": "black",
+ "navigationBarTitleText": "shopro-plus",
+ "navigationBarBackgroundColor": "#FFFFFF",
+ "backgroundColor": "#FFFFFF"
+ },
+ "tabBar": {
+ "color": "#333",
+ "selectedColor": "#a8700d",
+ "backgroundColor": "#ffffff",
+ "borderStyle": "black",
+ "list": [{
+ "pagePath": "pages/index/index",
+ "text": "首页",
+ "iconPath": "static/images/tabbar/tabbar_home.png",
+ "selectedIconPath": "/static/images/tabbar/tabbar_home1.png"
+ },
+ {
+ "pagePath": "pages/index/category",
+ "text": "分类",
+ "iconPath": "static/images/tabbar/tabbar_category.png",
+ "selectedIconPath": "/static/images/tabbar/tabbar_category1.png"
+ },
+ {
+ "pagePath": "pages/index/cart",
+ "text": "购物车",
+ "iconPath": "static/images/tabbar/tabbar_cart.png",
+ "selectedIconPath": "/static/images/tabbar/tabbar_cart1.png"
+ },
+ {
+ "pagePath": "pages/index/user",
+ "text": "我的",
+ "iconPath": "static/images/tabbar/tabbar_personal.png",
+ "selectedIconPath": "/static/images/tabbar/tabbar_personal1.png"
+ }
+ ]
+ }
+}
diff --git a/pages/activity/discounts/list.vue b/pages/activity/discounts/list.vue
new file mode 100644
index 0000000..b2d2163
--- /dev/null
+++ b/pages/activity/discounts/list.vue
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
+
+ {{ timeRule.title }}
+
+
+
+ {{ activityInfo.title }}
+ {{ tag }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/activity/groupon/detail.vue b/pages/activity/groupon/detail.vue
new file mode 100644
index 0000000..9e42faa
--- /dev/null
+++ b/pages/activity/groupon/detail.vue
@@ -0,0 +1,371 @@
+
+
+
+
+
+
+
+
+
+
+
+ 已拼{{ grouponDetail.goods.sales }}件
+
+ {{ grouponDetail.num || 0 }}人团
+
+
+
+
+
+
+
+
+
+
+
+
+ 恭喜您~拼团成功!
+
+
+
+ 对不起~您来晚了,该团已满
+
+
+
+
+
+
+
+ {{ grouponDetail.my ? '对不起~拼团已过期!已全额退款' : '对不起~拼团已过期!您来晚了~' }}
+
+
+
+
+
+
+
+
+
+ 对不起~拼团活动已结束!您来晚了~
+
+
+
+
+ 待成团,还差
+ {{ grouponDetail.num - grouponDetail.current_num }}
+ 人拼团成功
+
+
+ 倒计时
+
+ {{ time.h || '00' }}
+ :
+ {{ time.m || '00' }}
+ :
+ {{ time.s || '00' }}
+
+
+
+
+
+
+
+
+ 团长
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 玩法
+
+ {{ activity.richtext_title || '开团/参团·邀请好友·人满发货(不满退款' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/activity/groupon/list.vue b/pages/activity/groupon/list.vue
new file mode 100644
index 0000000..c02bb36
--- /dev/null
+++ b/pages/activity/groupon/list.vue
@@ -0,0 +1,246 @@
+
+
+
+
+ 爆款推荐
+ 省钱省心限时拼
+
+
+
+
+
+
+
+
+
+ 拼团
+ {{ item.title }}
+
+ {{ item.subtitle }}
+
+
+
+
+
+ 已拼{{ item.sales }}件
+
+ {{ item.activity.rules.team_num || 0 }}人团
+
+
+
+
+ {{ item.groupon_price }}
+ {{ item.original_price }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/activity/groupon/my-groupon.vue b/pages/activity/groupon/my-groupon.vue
new file mode 100644
index 0000000..d11fcbf
--- /dev/null
+++ b/pages/activity/groupon/my-groupon.vue
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+ {{ nav.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 已拼{{ groupon.goods.sales }}件
+
+ {{ groupon.groupon.num || 0 }}人团
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/activity/seckill/list.vue b/pages/activity/seckill/list.vue
new file mode 100644
index 0000000..4e58205
--- /dev/null
+++ b/pages/activity/seckill/list.vue
@@ -0,0 +1,248 @@
+
+
+
+
+
+
+ {{ tab.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 秒杀
+ {{ item.title }}
+
+ {{ item.subtitle }}
+
+
+
+
+ 已售出{{ item.sales }}件
+
+
+
+
+ {{ item.price }}
+ {{ item.original_price }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/activity/sign/index.vue b/pages/activity/sign/index.vue
new file mode 100644
index 0000000..bdced6e
--- /dev/null
+++ b/pages/activity/sign/index.vue
@@ -0,0 +1,361 @@
+
+
+
+
+
+
+ 每日签到
+
+ 已连续签到
+ {{ cuntinueDays }}
+ 天
+
+
+
+
+
+
+
+
+ {{ cur_year || '--' }} 年 {{ cur_month || '--' }} 月
+
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+ {{ item.day }}
+
+
+
+ {{ item.day }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 已连续打卡
+ {{ cuntinueDays }}
+ 天
+
+
+
+ 签到成功
+ 恭喜您获得{{ score || '0' }}积分
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/commission/apply.vue b/pages/app/commission/apply.vue
new file mode 100644
index 0000000..9da398c
--- /dev/null
+++ b/pages/app/commission/apply.vue
@@ -0,0 +1,269 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 我已阅读并遵守
+ {{ protocol.name }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/commission/commission-log.vue b/pages/app/commission/commission-log.vue
new file mode 100644
index 0000000..52c49a9
--- /dev/null
+++ b/pages/app/commission/commission-log.vue
@@ -0,0 +1,393 @@
+
+
+
+
+
+
+
+ 总收益(元)
+
+
+ {{ showMoney ? agentInfo.total_income || '0.00' : '***' }}
+
+
+ 待入账佣金
+ {{ showMoney ? agentInfo.delay_money || '0.00' : '***' }}
+
+
+ 可提现佣金
+ {{ showMoney ? userInfo.money || '0.00' : '***' }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ stateMap[stateCurrent] }}¥{{ totalMoney || '0.00' }}
+
+
+
+
+
+ {{ state.name }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.buyer.nickname }}
+ {{ $u.timeFormat(item.createtime, 'yyyy.mm.dd') }}
+
+
+
+ {{ item.status < 0 ? '-' : '+' }} {{ item.commission }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/commission/goods.vue b/pages/app/commission/goods.vue
new file mode 100644
index 0000000..d76f9d9
--- /dev/null
+++ b/pages/app/commission/goods.vue
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+ {{ item.title }}
+ {{ item.subtitle }}
+
+ ¥{{ item.price }}
+ ¥{{ item.original_price }}
+
+ 预计佣金:¥{{ item.commission_money }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/commission/index.vue b/pages/app/commission/index.vue
new file mode 100644
index 0000000..bf12aa9
--- /dev/null
+++ b/pages/app/commission/index.vue
@@ -0,0 +1,855 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ userInfo.nickname }}
+
+
+
+ {{ commissionLv.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 总收益
+ {{ showMoney ? commissionWallet.total_income || '0.00' : '***' }}
+
+
+ 待入账佣金
+ {{ showMoney ? commissionWallet.delay_money || '0.00' : '***' }}
+
+
+ 我的消费
+ {{ showMoney ? userInfo.total_consume || '0.00' : '***' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.remark }}
+
+
+ {{ $u.timeFrom(item.createtime) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ authNotice.title }}
+ {{ authNotice.detail }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+ {{ item.subtitle }}
+
+
+
+
+
+
+
+ * 购买指定商品即可成为分销商
+
+
+
+
+
+
+
+
+
+ 满足以下消费金额
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ userInfo.total_consume }}
+
+
+
+ {{ moneyTermNum }}
+
+
+
+
+
+
+ * 满足指定消费金额即可成为分销商
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/commission/order.vue b/pages/app/commission/order.vue
new file mode 100644
index 0000000..b7d332b
--- /dev/null
+++ b/pages/app/commission/order.vue
@@ -0,0 +1,497 @@
+
+
+
+
+
+
+
+
+
+
+
+ 团队订单数量(单)
+ {{ agentInfo.child_order_count || 0 }}
+
+
+
+ 一级订单
+ {{ agentInfo.child_order_count_1 || 0 }}
+
+
+ 二级订单
+ {{ agentInfo.child_order_count_2 || 0 }}
+
+
+
+
+
+ 团队订单金额(元)
+ {{ agentInfo.child_order_money || '0.00' }}
+
+
+
+ 一级订单
+ {{ agentInfo.child_order_money_1 || '0.00' }}
+
+
+ 二级订单
+ {{ agentInfo.child_order_money_2 || '0.00' }}
+
+
+
+
+
+
+
+
+ 直推分销订单数量(单)
+ {{ agentInfo.order_count }}
+
+
+ 直推分销订单金额(元)
+ {{ agentInfo.order_money }}
+
+
+
+
+
+
+
+
+
+ {{ stateMap[stateCurrent] }}¥{{ amount || '0.00' }}
+
+
+
+
+
+ {{ state.name }}
+
+
+
+
+
+
+
+
+
+
+
+ 订单编号:{{ item.order.order_sn }}
+ {{ item.order.status_name }}
+
+
+
+ 下单人:
+
+ {{ item.buyer.nickname }}
+
+ {{ $u.timeFormat(item.order.createtime, ' yyyy.mm.dd hh:MM ') }}
+
+
+
+
+ {{ corder.order_item.goods_title }}
+ 数量: {{ corder.order_item.goods_num }};{{ corder.order_item.goods_sku_text || '' }}
+
+
+ {{ corder.amount }}
+ {{ corder.commission_order_status_text }}
+
+
+ 佣金
+ {{ corder.reward.commission }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/commission/rankings.vue b/pages/app/commission/rankings.vue
new file mode 100644
index 0000000..809cf85
--- /dev/null
+++ b/pages/app/commission/rankings.vue
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+ {{ item.user ? item.user.nickname : '当前用户已注销' }}
+ {{ $u.timeFormat(item.createtime, 'yyyy年mm月dd日') }}
+
+
+
+ {{ item.total_income }}
+ 累计收益
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/commission/share-log.vue b/pages/app/commission/share-log.vue
new file mode 100644
index 0000000..14b8e24
--- /dev/null
+++ b/pages/app/commission/share-log.vue
@@ -0,0 +1,255 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ tab.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.user.nickname }}
+
+
+
+ {{ item.msg }}
+
+
+ {{ $u.timeFormat(item.createtime, 'yyyy年mm月dd日 hh:MM') }}
+ 来自{{ typeObj[item.type] }}分享
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/commission/team.vue b/pages/app/commission/team.vue
new file mode 100644
index 0000000..42b71d2
--- /dev/null
+++ b/pages/app/commission/team.vue
@@ -0,0 +1,344 @@
+
+
+
+
+
+
+
+
+ 推荐人:
+
+ {{ referrerInfo.nickname }}
+
+
+
+
+
+
+ 团队总人数(人)
+ {{ userInfo.child_user_count || 0 }}
+
+
+
+ 一级成员
+ {{ userInfo.child_user_count_1 || 0 }}
+
+
+ 二级成员
+ {{ userInfo.child_user_count_2 || 0 }}
+
+
+
+
+
+ 团队分销商人数(人)
+ {{ agentInfo.child_agent_count || 0 }}
+
+
+
+ 一级分销商
+ {{ agentInfo.child_agent_count_1 || 0 }}
+
+
+ 二级分销商
+ {{ agentInfo.child_agent_count_2 || 0 }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ children.nickname }}
+
+
+ {{ children.agent ? children.agent.level.name : '' }}
+
+
+ {{ $u.timeFormat(children.createtime, 'yyyy年mm月dd日') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/components/sh-collapse-item.vue b/pages/app/components/sh-collapse-item.vue
new file mode 100644
index 0000000..64eb503
--- /dev/null
+++ b/pages/app/components/sh-collapse-item.vue
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+ {{ name }}
+
+
+ {{ level.name }}
+
+
+
+ {{ $u.timeFormat(dateTime, 'yyyy年mm月dd日') }}
+ 下级成员:{{ childNum }}人
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/coupon/detail.vue b/pages/app/coupon/detail.vue
new file mode 100644
index 0000000..314fe52
--- /dev/null
+++ b/pages/app/coupon/detail.vue
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ couponDetail.amount || '0.00' }}元优惠券
+ 满{{ couponDetail.enough || '0.00' }}元可用
+
+
+ 有效期:{{ $u.timeFormat(couponDetail.usetime.start, 'yyyy-mm-dd') }} 至 {{ $u.timeFormat(couponDetail.usetime.end, 'yyyy-mm-dd') }}
+
+
+
+
+
+ 优惠券说明
+ {{ couponDetail.description || '暂无说明~' }}
+
+
+
+
+
+
+ 适用商品
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/coupon/list.vue b/pages/app/coupon/list.vue
new file mode 100644
index 0000000..7147024
--- /dev/null
+++ b/pages/app/coupon/list.vue
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+ {{ nav.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/live/list.vue b/pages/app/live/list.vue
new file mode 100644
index 0000000..3ee250e
--- /dev/null
+++ b/pages/app/live/list.vue
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+ {{ tab.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/merchant/apply.vue b/pages/app/merchant/apply.vue
new file mode 100644
index 0000000..b4416c5
--- /dev/null
+++ b/pages/app/merchant/apply.vue
@@ -0,0 +1,598 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 勾选代表同意《申请协议》
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 确定
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ authNotice.title }}
+ {{ authNotice.detail || '' }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/merchant/detail.vue b/pages/app/merchant/detail.vue
new file mode 100644
index 0000000..efe07e6
--- /dev/null
+++ b/pages/app/merchant/detail.vue
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
+
+
+ 数量:{{ item.goods_num || 0 }};
+ {{ item.goods_sku_text ? item.goods_sku_text : '' }}
+
+
+
+
+ ¥{{ item.goods_price || 0 }}
+
+
+
+
+
+ 预留电话:
+ {{ item.ext_arr.dispatch_phone }}
+
+
+ 到店/自提时间:
+ 配送时间:
+ {{ item.ext_arr.dispatch_date || '' }}
+
+
+
+
+
+ 订单信息
+
+
+ 订单状态:
+ {{ orderDetail.status_name }}
+
+
+ 订单编号:
+ {{ orderDetail.order_sn }}
+
+
+ 下单时间:
+ {{ orderDetail.paytime }}
+
+
+ 备注:
+ {{ orderDetail.remark }}
+
+
+ 配送地址:
+
+ {{ orderDetail.province_name || '' }}{{ orderDetail.city_name || '' }}{{ orderDetail.area_name || '' }}{{ orderDetail.address || '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/merchant/index.vue b/pages/app/merchant/index.vue
new file mode 100644
index 0000000..1078028
--- /dev/null
+++ b/pages/app/merchant/index.vue
@@ -0,0 +1,618 @@
+
+
+
+
+
+
+
+
+
+
+ {{ storeDetail.name }}
+
+
+
+ {{ storeDetail.province_name || '' }}{{ storeDetail.city_name || '' }}{{ storeDetail.area_name || '' }}{{ storeDetail.address || '' }}
+
+
+
+
+
+
+
+
+
+
+
+ 输码核销
+
+
+ 输码
+
+
+
+
+
+
+ 扫码核销
+
+
+ 扫码
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 订单量(单):{{ orderInfo.total_num || 0 }}
+ 交易额(元):{{ orderInfo.total_money || 0 }}
+
+
+
+
+
+
+ 订单编号:{{ order.order_sn }}
+ {{ order.status_name }}
+
+
+
+
+
+ 数量:{{ item.goods_num || 0 }};
+ {{ item.goods_sku_text ? item.goods_sku_text : '' }}
+
+
+
+
+ ¥{{ item.goods_price || 0 }}
+
+
+
+
+
+
+
+ 优惠:
+ {{ reduceAdd(order.item, 'discount_fee') }}
+
+
+ 实付款:
+ {{ reduceAdd(order.item, 'pay_price') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 输码核销
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/merchant/info.vue b/pages/app/merchant/info.vue
new file mode 100644
index 0000000..bafb536
--- /dev/null
+++ b/pages/app/merchant/info.vue
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+ 营业星期:
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/merchant/list.vue b/pages/app/merchant/list.vue
new file mode 100644
index 0000000..c7cef81
--- /dev/null
+++ b/pages/app/merchant/list.vue
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/app/score/list.vue b/pages/app/score/list.vue
new file mode 100644
index 0000000..7742af8
--- /dev/null
+++ b/pages/app/score/list.vue
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+ {{ leftGoods.price }}
+
+ 已兑换{{ leftGoods.sales }}件
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/comment/add-comment.vue b/pages/goods/comment/add-comment.vue
new file mode 100644
index 0000000..77bad49
--- /dev/null
+++ b/pages/goods/comment/add-comment.vue
@@ -0,0 +1,210 @@
+
+
+
+
+
+
+
+
+ 数量:{{ goodsDetail.goods_num || 0 }};
+ {{ goodsDetail.goods_sku_text ? goodsDetail.goods_sku_text : '' }}
+
+
+
+
+ ¥{{ goodsDetail.goods_price || 0 }}
+
+
+
+
+
+
+
+
+ {{ starTip }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/comment/comment-list.vue b/pages/goods/comment/comment-list.vue
new file mode 100644
index 0000000..306277c
--- /dev/null
+++ b/pages/goods/comment/comment-list.vue
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/components/sh-activity.vue b/pages/goods/components/sh-activity.vue
new file mode 100644
index 0000000..3530cb8
--- /dev/null
+++ b/pages/goods/components/sh-activity.vue
@@ -0,0 +1,157 @@
+
+
+
+ 优惠
+
+
+
+ {{ item.title }}
+ {{ tag }}
+
+
+
+
+
+
+
+
+
+ {{ activityMap[activityType].title }}
+
+
+
+
+ {{ activityMap[activityType].title }}
+
+ {{ tag }}
+
+
+
+
+
+ 共有{{ activityMap[activityType].num }}件商品参加此活动
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/components/sh-comment.vue b/pages/goods/components/sh-comment.vue
new file mode 100644
index 0000000..0a7381c
--- /dev/null
+++ b/pages/goods/components/sh-comment.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
diff --git a/pages/goods/components/sh-coupon.vue b/pages/goods/components/sh-coupon.vue
new file mode 100644
index 0000000..4cad267
--- /dev/null
+++ b/pages/goods/components/sh-coupon.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/components/sh-filter.vue b/pages/goods/components/sh-filter.vue
new file mode 100644
index 0000000..feced9a
--- /dev/null
+++ b/pages/goods/components/sh-filter.vue
@@ -0,0 +1,168 @@
+
+
+
+
+
+ 综合推荐
+ 扩展自定义排序
+
+
+
+ {{ defaultOrder === 1 ? '自定义' : '综合推荐' }}
+
+
+
+
+
+ 销量
+
+
+
+
+ 价格
+
+
+
+
+
+
+
+
+ 新品优先
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/components/sh-groupon.vue b/pages/goods/components/sh-groupon.vue
new file mode 100644
index 0000000..013d332
--- /dev/null
+++ b/pages/goods/components/sh-groupon.vue
@@ -0,0 +1,220 @@
+
+
+
+
+ 已有{{ grouponData.sales }}人参与活动
+
+
+
+
+
+ {{ g.leader.user_nickname }}
+
+
+
+
+ 还差
+ {{ g.num - g.current_num }}人
+ 成团
+
+ 剩余时间{{ g.time.h }}:{{ g.time.m }}:{{ g.time.s }}
+
+
+
+
+
+
+
+
+
+ 正在拼团
+
+
+
+
+
+ {{ g.leader.user_nickname }}
+
+
+
+
+ 还差
+ {{ g.num - g.current_num }}人
+ 成团
+
+ 剩余时间{{ g.time.h }}:{{ g.time.m }}:{{ g.time.s }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/components/sh-price-card.vue b/pages/goods/components/sh-price-card.vue
new file mode 100644
index 0000000..cfc77fd
--- /dev/null
+++ b/pages/goods/components/sh-price-card.vue
@@ -0,0 +1,377 @@
+
+
+
+
+
+ ¥
+ {{ detail.price }}
+ 优惠价
+
+
+
+ 原价:¥{{ detail.original_price }}
+
+ 已售:{{ detail.sales }}件
+
+
+
+
+
+
+
+
+ {{ detail.price }}
+
+
+
+ 价值:¥{{ detail.original_price }}
+
+ 已兑换:{{ detail.sales }}件
+
+
+
+
+
+
+
+ ¥
+ {{ detail.activity_type === 'groupon' ? detail.groupon_price : detail.price }}
+ {{ detail.activity.rules.team_num }}人团
+
+
+
+ 原价:¥{{ detail.original_price }}
+
+ 已拼:{{ detail.sales }}件
+
+
+ 距开始
+ 距结束
+ {{ activityRules.countDownTime.h || '00' }} : {{ activityRules.countDownTime.m || '00' }} : {{ activityRules.countDownTime.s || '00' }}
+
+ 活动已结束
+
+
+
+
+
+
+
+ ¥
+ {{ detail.price }}
+ 秒杀价
+
+
+ 距开始
+ 距结束
+ {{ activityRules.countDownTime.h || '00' }} : {{ activityRules.countDownTime.m || '00' }} : {{ activityRules.countDownTime.s || '00' }}
+
+ 活动已结束
+
+
+
+ 原价:¥{{ detail.original_price }}
+
+ 已售:{{ detail.sales }}件
+
+
+
+
+
+
+ 仅剩{{ detail.stock }}件
+ 已售罄
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/components/sh-serve.vue b/pages/goods/components/sh-serve.vue
new file mode 100644
index 0000000..df936c7
--- /dev/null
+++ b/pages/goods/components/sh-serve.vue
@@ -0,0 +1,140 @@
+
+
+
+
+ 服务
+
+
+
+
+ {{ serve.name }}
+
+
+
+
+
+
+
+
+
+ 服务保障
+
+
+
+
+ {{ serve.name }}
+
+ {{ serve.description }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/detail.vue b/pages/goods/detail.vue
new file mode 100644
index 0000000..db7280d
--- /dev/null
+++ b/pages/goods/detail.vue
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ goodsInfo.title }}
+ {{ goodsInfo.subtitle }}
+
+
+
+
+
+
+
+
+
+ 规格
+ {{ currentSkuText || '请选择规格' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 玩法
+ {{ goodsInfo.activity.richtext_title || '开团/参团·邀请好友·人满发货(不满退款' }}
+
+
+
+
+
+
+
+
+ {{ tab.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t.title }}
+ {{ t.content }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/goods/list.vue b/pages/goods/list.vue
new file mode 100644
index 0000000..fee57a4
--- /dev/null
+++ b/pages/goods/list.vue
@@ -0,0 +1,224 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/cart.vue b/pages/index/cart.vue
new file mode 100644
index 0000000..fed6e4e
--- /dev/null
+++ b/pages/index/cart.vue
@@ -0,0 +1,371 @@
+
+
+
+
+
+
+
+ 共
+ {{ cartList.length }}
+ 件商品
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 活动商品,仅支持单独购买
+
+
+
+
+ {{ g.sku_price && g.sku_price.goods_sku_text ? g.sku_price.goods_sku_text : '' }}
+
+
+
+
+ ¥{{ g.sku_price ? g.sku_price.price : 0 }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/category.vue b/pages/index/category.vue
new file mode 100644
index 0000000..019790d
--- /dev/null
+++ b/pages/index/category.vue
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/category/one-catgory.vue b/pages/index/category/one-catgory.vue
new file mode 100644
index 0000000..d37c0fd
--- /dev/null
+++ b/pages/index/category/one-catgory.vue
@@ -0,0 +1,265 @@
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ goods.title }}
+ {{ goods.price }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/category/takeout-catgory.vue b/pages/index/category/takeout-catgory.vue
new file mode 100644
index 0000000..e19b6f6
--- /dev/null
+++ b/pages/index/category/takeout-catgory.vue
@@ -0,0 +1,603 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/category/three-catgory.vue b/pages/index/category/three-catgory.vue
new file mode 100644
index 0000000..e3bad78
--- /dev/null
+++ b/pages/index/category/three-catgory.vue
@@ -0,0 +1,209 @@
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ list.name }}
+
+ 查看更多
+
+
+
+
+
+
+ {{ mlist.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/category/two-catgory.vue b/pages/index/category/two-catgory.vue
new file mode 100644
index 0000000..a891e72
--- /dev/null
+++ b/pages/index/category/two-catgory.vue
@@ -0,0 +1,213 @@
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+ {{ categoryData[listId].name }}
+
+
+
+
+
+
+ {{ list.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-adv.vue b/pages/index/components/sh-adv.vue
new file mode 100644
index 0000000..7791323
--- /dev/null
+++ b/pages/index/components/sh-adv.vue
@@ -0,0 +1,174 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-banner.vue b/pages/index/components/sh-banner.vue
new file mode 100644
index 0000000..bcaa8ac
--- /dev/null
+++ b/pages/index/components/sh-banner.vue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-category-tabs.vue b/pages/index/components/sh-category-tabs.vue
new file mode 100644
index 0000000..b1e29d0
--- /dev/null
+++ b/pages/index/components/sh-category-tabs.vue
@@ -0,0 +1,348 @@
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+ {{ item.description }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-cell.vue b/pages/index/components/sh-cell.vue
new file mode 100644
index 0000000..2b5c431
--- /dev/null
+++ b/pages/index/components/sh-cell.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-coupon.vue b/pages/index/components/sh-coupon.vue
new file mode 100644
index 0000000..430b276
--- /dev/null
+++ b/pages/index/components/sh-coupon.vue
@@ -0,0 +1,276 @@
+
+
+
+
+ 领券专区
+
+ 查看更多
+
+
+
+
+
+
+
+
+
+ {{ item.amount }}
+ 满{{ item.enough }}元可用
+ 仅剩{{ item.stock }}张
+
+
+
+
+
+
+
+
+
+
+
+ ¥
+ {{ item.amount }}
+ {{ item.name }}
+
+ 满{{ item.enough }}元可用
+
+ 有效期:{{ $u.timeFormat(item.usetime.start, 'yyyy-mm-dd') }} 至 {{ $u.timeFormat(item.usetime.end, 'yyyy-mm-dd') }}
+
+
+
+
+ 仅剩{{ item.stock }}张
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-goods-card.vue b/pages/index/components/sh-goods-card.vue
new file mode 100644
index 0000000..ad71ce6
--- /dev/null
+++ b/pages/index/components/sh-goods-card.vue
@@ -0,0 +1,356 @@
+
+
+
+
+
+
+
+ {{ typeMap[type].text }}
+ {{ title }}
+
+ {{ subtitle }}
+
+
+
+ {{ item }}
+
+
+
+
+ {{ price }}
+ {{ originPrice }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-grid-swiper.vue b/pages/index/components/sh-grid-swiper.vue
new file mode 100644
index 0000000..ab20d97
--- /dev/null
+++ b/pages/index/components/sh-grid-swiper.vue
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-grid.vue b/pages/index/components/sh-grid.vue
new file mode 100644
index 0000000..3e245c0
--- /dev/null
+++ b/pages/index/components/sh-grid.vue
@@ -0,0 +1,60 @@
+
+
+
+
+ {{ menu.name }}
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-groupon.vue b/pages/index/components/sh-groupon.vue
new file mode 100644
index 0000000..2744d39
--- /dev/null
+++ b/pages/index/components/sh-groupon.vue
@@ -0,0 +1,319 @@
+
+
+
+
+
+
+ {{ detail.name }}
+
+
+ 更多拼团
+
+
+
+
+
+
+
+
+
+
+ {{ mgoods.title }}
+ {{ mgoods.groupon_price }}
+
+
+ {{ mgoods.sales }}人正在拼
+
+ ¥{{ mgoods.original_price }}
+
+
+
+
+
+
+
+
+
+
+ 拼团
+ {{ item.title }}
+
+ {{ item.subtitle }}
+
+
+
+
+
+ 已拼{{ item.sales }}件
+
+ {{ item.activity.rules.team_num || 0 }}人团
+
+
+
+
+ {{ item.groupon_price }}
+ {{ item.original_price }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-hot-goods.vue b/pages/index/components/sh-hot-goods.vue
new file mode 100644
index 0000000..f323be6
--- /dev/null
+++ b/pages/index/components/sh-hot-goods.vue
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-live.vue b/pages/index/components/sh-live.vue
new file mode 100644
index 0000000..b3871d2
--- /dev/null
+++ b/pages/index/components/sh-live.vue
@@ -0,0 +1,108 @@
+
+
+
+ {{ detail.name }}
+
+ 更多直播
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-order-card.vue b/pages/index/components/sh-order-card.vue
new file mode 100644
index 0000000..da40d8a
--- /dev/null
+++ b/pages/index/components/sh-order-card.vue
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
+ {{ order.title }}
+ {{ orderNum[order.type] }}
+
+
+
+
+
+ 退换货
+
+
+
+
+
+
+
+
+ 全部订单
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-richtext.vue b/pages/index/components/sh-richtext.vue
new file mode 100644
index 0000000..4c5364f
--- /dev/null
+++ b/pages/index/components/sh-richtext.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-search.vue b/pages/index/components/sh-search.vue
new file mode 100644
index 0000000..e11a3df
--- /dev/null
+++ b/pages/index/components/sh-search.vue
@@ -0,0 +1,46 @@
+
+
+
+
+ 搜索
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-seckill.vue b/pages/index/components/sh-seckill.vue
new file mode 100644
index 0000000..f168a0a
--- /dev/null
+++ b/pages/index/components/sh-seckill.vue
@@ -0,0 +1,300 @@
+
+
+
+
+
+
+ {{ detail.name }}
+
+
+
+ 更多抢购
+
+
+
+
+
+
+
+
+
+
+ {{ mgoods.title }}
+
+ {{ mgoods.price }}
+ ¥{{ mgoods.original_price }}
+
+
+
+
+
+
+
+
+
+
+
+ 秒杀
+ {{ item.title }}
+
+ {{ item.subtitle }}
+
+
+
+
+
+ 已售出{{ item.sales }}件
+
+
+
+
+ {{ item.price }}
+ {{ item.original_price }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-title-card.vue b/pages/index/components/sh-title-card.vue
new file mode 100644
index 0000000..0c98db6
--- /dev/null
+++ b/pages/index/components/sh-title-card.vue
@@ -0,0 +1,64 @@
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
diff --git a/pages/index/components/sh-wallet.vue b/pages/index/components/sh-wallet.vue
new file mode 100644
index 0000000..fc1b39f
--- /dev/null
+++ b/pages/index/components/sh-wallet.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
+ {{ userInfo.money || '0' }}
+ 账户余额
+
+
+ {{ userInfo.score || '0' }}
+ 积分
+
+
+ {{ userOtherData.coupons_num || '0' }}
+ 优惠券
+
+
+
+
+
+ 我的钱包
+
+
+
+
+
+
+
diff --git a/pages/index/index.vue b/pages/index/index.vue
new file mode 100644
index 0000000..728ead7
--- /dev/null
+++ b/pages/index/index.vue
@@ -0,0 +1,215 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/index/home-head.vue b/pages/index/index/home-head.vue
new file mode 100644
index 0000000..825aba2
--- /dev/null
+++ b/pages/index/index/home-head.vue
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+
+
+
+
+ {{ navTitle || '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/index/privacy-modal.vue b/pages/index/index/privacy-modal.vue
new file mode 100644
index 0000000..0f510b3
--- /dev/null
+++ b/pages/index/index/privacy-modal.vue
@@ -0,0 +1,155 @@
+
+
+
+
+ 用户隐私协议概况
+
+ 感谢您使用{{
+ initShop.name
+ }},我们非常重视您的个人信息和隐私保护,在您使用服务前,请仔细阅读
+ 《{{ initShop.name }}隐私协议》
+ ,我们将会严格按照经您同意的各项条款使用您的个人信息,以便为您提供更好的服务。
+
+ 如您同意此条款,请点击“同意”并开始使用我们的产品和服务,我们将尽全力保护您的个人信息安全。
+
+
+
+
+
+
+
+
diff --git a/pages/index/user.vue b/pages/index/user.vue
new file mode 100644
index 0000000..e18f843
--- /dev/null
+++ b/pages/index/user.vue
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ initShop.copyright[0] }}
+ {{ initShop.copyright[1] }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/user/userinfo-card.vue b/pages/index/user/userinfo-card.vue
new file mode 100644
index 0000000..f7ea73c
--- /dev/null
+++ b/pages/index/user/userinfo-card.vue
@@ -0,0 +1,342 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ userInfo.nickname || '请登录~' }}
+
+
+
+
+
+
+ {{ userInfo.group.name }}
+
+
+
+
+
+
+
+
+
+
+ 点击绑定手机号,确保账户安全
+
+
+
+
+
+
+ 提示
+ 更新微信信息?
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/view.vue b/pages/index/view.vue
new file mode 100644
index 0000000..a3b9b72
--- /dev/null
+++ b/pages/index/view.vue
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/after-sale/detail.vue b/pages/order/after-sale/detail.vue
new file mode 100644
index 0000000..8d70d33
--- /dev/null
+++ b/pages/order/after-sale/detail.vue
@@ -0,0 +1,329 @@
+
+
+
+
+
+
+
+
+
+
+ {{ aftersaleDetail.aftersale_status_desc }}
+ {{ aftersaleDetail.updatetime }}
+
+
+
+
+
+
+ 退款总额
+ ¥{{ aftersaleDetail.refund_fee }}
+ 未退款
+
+
+
+
+
+
+ 数量:{{ aftersaleDetail.goods_num || 0 }};
+ {{ aftersaleDetail.goods_sku_text ? aftersaleDetail.goods_sku_text : '' }}
+
+
+
+
+ ¥{{ aftersaleDetail.goods_price || 0 }}
+
+
+
+
+
+
+
+
+
+ 服务单号:
+ {{ aftersaleDetail.aftersale_sn }}
+
+
+
+ 申请时间:
+ {{ aftersaleDetail.createtime }}
+
+
+ 售后类型:
+ {{ aftersaleDetail.type_text }}
+
+
+ 申请原因:
+ {{ aftersaleLog[aftersaleLog.length - 1].reason }}
+
+
+ 相关描述:
+ {{ aftersaleLog[aftersaleLog.length - 1].content }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/after-sale/list.vue b/pages/order/after-sale/list.vue
new file mode 100644
index 0000000..9c1ce52
--- /dev/null
+++ b/pages/order/after-sale/list.vue
@@ -0,0 +1,329 @@
+
+
+
+
+
+
+
+ {{ nav.title }}
+
+
+
+
+
+
+
+
+
+ 服务单号:{{ order.aftersale_sn }}
+
+ {{ order.aftersale_status_text }}
+
+
+
+
+
+
+ 数量:{{ order.goods_num || 0 }};
+ {{ order.goods_sku_text ? order.goods_sku_text : '' }}
+
+
+
+
+ ¥{{ order.goods_price || 0 }}
+
+
+
+
+
+
+
+
+ {{ order.aftersale_status_text }}
+ {{ order.aftersale_status_desc }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/after-sale/log.vue b/pages/order/after-sale/log.vue
new file mode 100644
index 0000000..91a1361
--- /dev/null
+++ b/pages/order/after-sale/log.vue
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+ {{ log.reason }}
+
+
+
+
+ {{ $u.timeFormat(log.createtime, 'yyyy-mm-dd hh:MM') }}
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/after-sale/refund.vue b/pages/order/after-sale/refund.vue
new file mode 100644
index 0000000..04bdbfe
--- /dev/null
+++ b/pages/order/after-sale/refund.vue
@@ -0,0 +1,432 @@
+
+
+
+
+
+
+
+
+ 数量:{{ orderItemDetail.goods_num || 0 }};
+ {{ orderItemDetail.goods_sku_text ? orderItemDetail.goods_sku_text : '' }}
+
+
+
+
+ ¥{{ orderItemDetail.goods_price || 0 }}
+
+
+
+
+
+
+
+
+ 请选择售后类型
+
+ {{ item.title }}
+
+
+
+
+
+ 选择申请原因
+
+ {{ refundCause }}
+ 请选择申请原因~
+
+
+
+
+
+
+ 联系方式
+
+
+
+
+
+ 相关描述
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ refundList.title }}
+
+
+
+
+ {{ item.val }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/components/sh-select-coupon.vue b/pages/order/components/sh-select-coupon.vue
new file mode 100644
index 0000000..63977ad
--- /dev/null
+++ b/pages/order/components/sh-select-coupon.vue
@@ -0,0 +1,116 @@
+
+
+
+ 优惠券
+
+ {{ title }}
+ 暂无优惠券
+
+
+
+
+
+
+ 选择优惠券
+
+
+
+ 不使用优惠券
+
+
+
+ {{ radio.name }}:{{ `满${radio.enough}减${radio.amount}` }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/confirm.vue b/pages/order/confirm.vue
new file mode 100644
index 0000000..dc14bd5
--- /dev/null
+++ b/pages/order/confirm.vue
@@ -0,0 +1,2059 @@
+
+
+
+
+
+
+
+ 请选择收货地址
+
+
+
+
+
+ {{ addressData.consignee }}
+ {{ addressData.phone }}
+ 默认
+
+
+
+ {{ addressData.province_name }}{{ addressData.city_name
+ }}{{ addressData.area_name }}{{ addressData.address }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ g.detail.current_sku_price &&
+ g.detail.current_sku_price.goods_sku_text
+ ? g.detail.current_sku_price.goods_sku_text
+ : ""
+ }}
+
+
+
+
+
+
+ {{ g.detail.current_sku_price.score }}积分+
+ ¥{{ g.detail.current_sku_price.price }}
+
+ x{{ g.goods_num }}
+
+
+
+
+
+
+
+ 配送方式
+
+ {{ getCurGoodsExpress(g) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 积分
+ -{{ orderPre.score_amount || 0 }}积分
+
+
+
+ 商品金额
+
+ ¥{{ orderPre.goods_amount || "0.00" }}
+
+
+
+
+
+
+
+
+ 活动优惠
+
+ -¥{{ orderPre.activity_discount_money || "0.00" }}
+
+
+
+
+
+ {{ item.activity_title }}
+
+ -¥{{ item.activity_discount_money || "0.00" }}
+
+
+
+
+
+
+
+
+ 运费
+ 活动减¥ {{ orderPre.dispatch_discount_money }}
+
+
+ -¥{{ orderPre.dispatch_amount }}
+ ¥{{
+ Number(orderPre.dispatch_amount) -
+ Number(orderPre.dispatch_discount_money) || "0.00"
+ }}
+
+
+
+
+
+ 申请发票
+
+ {{ selectedInvoice }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 个人
+
+
+
+ 企/事业单位
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ nav.title }}
+
+
+
+
+
+
+
+ 请选择收货地址
+
+
+
+
+
+
+
+ 默认
+ {{ addressData.province_name }}{{ addressData.city_name
+ }}{{ addressData.area_name }}{{ addressData.address }}
+
+
+
+
+
+ 物流快递
+
+
+
+
+ {{ addressData.consignee }}
+ {{ addressData.phone }}
+
+
+
+
+
+
+
+
+ 开启定位服务
+ 为你推荐更精准的位置信息噢~
+
+
+
+
+
+
+ 最近
+ {{
+ storeInfo ? storeInfo.name : "暂无自提点"
+ }}
+
+
+
+
+ 距您{{ storeInfo ? storeInfo.distance_text : 0 }}
+
+
+
+
+ 到店时间
+
+ {{ checkTime[checkDayCur].title
+ }}{{
+ checkTime[checkDayCur].timeRange[checkTimeCur]
+ }}
+
+
+
+
+
+ 预留电话
+
+
+
+
+
+
+
+
+ 同意并接受
+ 《到店自提服务协议》
+
+
+
+
+
+
+
+
+
+ 默认
+ {{ addressData.province_name }}{{ addressData.city_name
+ }}{{ addressData.area_name }}{{ addressData.address }}
+
+
+
+
+
+ 商家配送
+
+
+
+
+ 配送时间
+
+ {{ checkTime[checkDayCur].title
+ }}{{ checkTime[checkDayCur].timeRange[checkTimeCur] }}
+
+
+
+
+
+ 预留电话
+
+
+
+
+
+
+
+
+
+
+
+ 订单支付完成后,请在订单详情页查看发货信息
+
+
+ 自动发货
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 选择{{ checkType }}时间
+
+
+
+ {{ day.title }}
+
+
+
+
+
+ {{ time }}
+
+
+ 请选择其它日期
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/detail.vue b/pages/order/detail.vue
new file mode 100644
index 0000000..5983d0d
--- /dev/null
+++ b/pages/order/detail.vue
@@ -0,0 +1,742 @@
+
+
+
+
+
+
+
+ {{ orderDetail.status_desc }}
+
+
+
+
+
+
+
+ {{ orderDetail.consignee }}
+ {{ orderDetail.phone }}
+
+ {{ orderDetail.province_name }}{{ orderDetail.city_name }}{{ orderDetail.area_name }}{{ orderDetail.address }}
+
+
+
+
+
+
+
+
+
+
+ 数量:{{ order.goods_num || 0 }};
+ {{ order.goods_sku_text ? order.goods_sku_text : '' }}
+
+
+
+
+ ¥{{ order.goods_price || 0 }}
+
+
+
+
+
+
+
+
+ 配送:
+ {{ expressType[order.dispatch_type] }}
+
+
+
+ 详情
+
+
+
+
+
+
+
+ 退款原因:
+ {{ order.refund_msg }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 订单编号:
+ {{ orderDetail.order_sn }}
+
+
+
+ 下单时间:
+ {{ orderDetail.createtime }}
+
+
+ 支付方式:
+ {{ payType[orderDetail.pay_type] }}
+
+
+ 支付时间:
+ {{ orderDetail.paytime }}
+
+
+
+
+
+
+ 商品总额
+ ¥{{ orderDetail.goods_amount }}
+
+
+ 运费
+ ¥{{ orderDetail.dispatch_amount }}
+
+
+ 优惠金额
+ -¥{{ orderDetail.discount_fee }}
+
+
+ 积分
+ -{{ orderDetail.score_fee }}积分
+
+
+ {{ orderDetail.status <= 0 ? '需付款' : '实付款' }}:
+ ¥{{ orderDetail.total_fee }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/express/distribution-detail.vue b/pages/order/express/distribution-detail.vue
new file mode 100644
index 0000000..7262446
--- /dev/null
+++ b/pages/order/express/distribution-detail.vue
@@ -0,0 +1,407 @@
+
+
+
+
+
+
+
+
+
+
+ 数量:{{ itemDetail.goods_num || 0 }};
+ {{ itemDetail.goods_sku_text ? itemDetail.goods_sku_text : '' }}
+
+
+
+
+ ¥{{ itemDetail.goods_price || 0 }}
+
+
+
+
+
+
+
+
+
+ 总核销码
+
+ 核销码
+
+
+ {{ code.code }}
+ {{ code.status_name }}
+
+
+
+
+ 为保障您的权益,未到店消费前请不要将提货码提供给商家
+
+
+
+
+
+
+ {{ storeInfo.name }}
+
+
+
+ {{ storeInfo.province_name || '' }}{{ storeInfo.city_name || '' }}{{ storeInfo.area_name || '' }}{{ storeInfo.address || '' }}
+
+ 营业时间:{{ storeInfo.openhours || '' }}
+
+
+
+ 到这去
+
+
+
+
+
+
+ 配送信息
+ 配送地址:{{ itemDetail.order.city_name || '' }}{{ itemDetail.order.area_name || '' }}{{ itemDetail.order.address || '' }}
+ 配送时间:{{ itemDetail.ext_arr.dispatch_date || '' }}
+
+
+
+
+ 发货信息
+
+ {{ item.name }}:{{ item.value }}
+
+ {{ itemDetail.ext_arr.autosend_content }}
+ 暂未发货~
+
+
+
+
+
+
+
+ 核销码:{{ qrcode }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/express/express-detail.vue b/pages/order/express/express-detail.vue
new file mode 100644
index 0000000..75bf2d3
--- /dev/null
+++ b/pages/order/express/express-detail.vue
@@ -0,0 +1,217 @@
+
+
+
+
+
+
+
+
+
+ {{ goodsList.length || 0 }}件商品
+
+ {{ firstGoods.status_name || '' }}
+
+
+
+ {{ expressDetail.express_name || '' }}
+ {{ expressDetail.express_no || '' }}
+
+
+
+
+
+
+
+
+
+ {{ log.changedate.split(' ')[0]}}
+ {{ log.changedate.split(' ')[1] }}
+
+
+
+ {{ log.status_name }}
+ {{ log.content }}
+
+
+ 暂无物流信息~
+
+
+
+
+
+
+
+
diff --git a/pages/order/express/express-list.vue b/pages/order/express/express-list.vue
new file mode 100644
index 0000000..98876e2
--- /dev/null
+++ b/pages/order/express/express-list.vue
@@ -0,0 +1,114 @@
+
+
+
+ {{ expressList.length }}个包裹已发出
+
+
+ {{ express.log[0].status_name }}
+ {{ express.express_name }}:{{ express.express_no }}
+
+
+ {{ express.log[0].content }}
+
+
+
+ 共{{ express.item.length }}件商品
+
+
+
+
+
+
+
+
diff --git a/pages/order/express/store-address.vue b/pages/order/express/store-address.vue
new file mode 100644
index 0000000..c6ebc77
--- /dev/null
+++ b/pages/order/express/store-address.vue
@@ -0,0 +1,351 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ address.name }}
+
+
+
+
+ {{ address.openhours }}
+
+
+ {{ weekMap[week] }}、
+
+
+
+
+
+ {{ address.province_name }}{{ address.city_name }}{{ address.area_name }}{{ address.address }}
+
+
+
+
+ {{ address.phone }}
+
+
+
+
+ {{ address.distance_text || 0 }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/list.vue b/pages/order/list.vue
new file mode 100644
index 0000000..5c1523f
--- /dev/null
+++ b/pages/order/list.vue
@@ -0,0 +1,407 @@
+
+
+
+
+
+
+ {{ nav.title }}
+
+
+
+
+
+
+
+
+
+
+ 订单编号:{{ order.order_sn }}
+ {{ order.status_name }}
+
+
+
+
+
+
+ 数量:{{ goods.goods_num || 0 }};
+ {{ goods.goods_sku_text ? goods.goods_sku_text : '' }}
+
+
+
+
+ ¥{{ goods.goods_price || 0 }}
+
+
+
+
+
+
+
+
+ 优惠:
+ ¥
+ {{ order.discount_fee }} ,运费:
+ ¥
+ {{ order.dispatch_amount }} ,{{ order.status <= 0 ? '需付款' : '实付款' }}:
+ {{ order.total_fee }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/payment/method.vue b/pages/order/payment/method.vue
new file mode 100644
index 0000000..e8f5fe2
--- /dev/null
+++ b/pages/order/payment/method.vue
@@ -0,0 +1,255 @@
+
+
+
+
+ {{ timeText }}
+ {{ orderDetail.total_fee }}
+
+
+
+
+
+
+
+
+ 微信支付
+
+
+
+
+
+
+
+ 支付宝支付
+
+
+
+
+
+
+
+ ApplePay
+
+
+
+
+
+
+
+ 余额支付
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/order/payment/result.vue b/pages/order/payment/result.vue
new file mode 100644
index 0000000..0e128b3
--- /dev/null
+++ b/pages/order/payment/result.vue
@@ -0,0 +1,287 @@
+
+
+
+
+
+
+
+
+ {{ payText[payState] }}
+ ¥{{ orderDetail.total_fee }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ payText[payState] }}
+ ¥{{ orderDetail.total_fee }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/404.vue b/pages/public/404.vue
new file mode 100644
index 0000000..67a5cee
--- /dev/null
+++ b/pages/public/404.vue
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/pages/public/chat/index.vue b/pages/public/chat/index.vue
new file mode 100644
index 0000000..f51291d
--- /dev/null
+++ b/pages/public/chat/index.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/chat/shopro/chat.js b/pages/public/chat/shopro/chat.js
new file mode 100644
index 0000000..679ea22
--- /dev/null
+++ b/pages/public/chat/shopro/chat.js
@@ -0,0 +1,161 @@
+/**
+ * shopro
+ * 聊天配置,socket服务相关,心跳检测和重连
+ */
+
+/**
+ * socket
+ * @param {Object} config - 初始化配置对象
+ * @param {Number} wait = [10000] - 心跳频率
+ */
+
+import {
+ BASE_URL
+} from '@/env.js'
+
+const service = BASE_URL.split('://')[1].split(':')[0];
+
+export default class Socket {
+ constructor(initData, callback) {
+ let {
+ ping,
+ is_ssl,
+ gateway_port,
+ ssl_type
+ } = initData;
+
+ let url = `${is_ssl?'wss':'ws'}://${service}:${gateway_port}/`
+ if (is_ssl && ssl_type === 'reverse_proxy') {
+ url = `wss://${service}/websocket/`
+ }
+ this.config = {
+ url: url,
+ session_id: uni.getStorageSync('chatSessionId'),
+ token: uni.getStorageSync('token'),
+ identify: 'user'
+ };
+ this.callback = callback; //onmsg回调
+ this.timeoutObj = null; //心跳检测定时器对象
+ this.lockReconnect = false; //检测次数锁
+ this.isClose = false; //链接断开
+ this.timer = null; // 检测定时器
+ this.limit = 0; //检测次数,默认最大12
+ this.timout = ping;
+ uni.setStorageSync('isSocketOpen', false)
+ this.init()
+ }
+
+ // 初始化
+ async init() {
+ await this.connect();
+ }
+
+ // 连接
+ async connect() {
+ if (!uni.getStorageSync('isSocketOpen')) {
+ let [error, res] = await uni.connectSocket({
+ url: `${this.config.url}?identify=${this.config.identify}&token=${this.config.token}&session_id=${this.config.session_id}`
+ });
+ if (res.errMsg === 'connectSocket:ok') {
+ this.initEventHandle();
+ }
+ }
+ }
+
+ // 发送消息
+ async send(msg = "") {
+ if (uni.getStorageSync('isSocketOpen')) {
+ let [error, res] = await uni.sendSocketMessage({
+ data: msg
+ });
+ return Promise.resolve(res);
+ }
+ }
+
+ // 监听消息
+ onMsg() {
+ uni.onSocketMessage(res => {
+ if (res.code === 1 && res.type === 'init') {
+ this.config.session_id = res.data.session_id;
+ }
+ this.callback(res)
+ });
+ }
+
+ // 关闭连接
+ close() {
+ uni.closeSocket();
+ uni.removeStorage({
+ key: 'isSocketOpen',
+ success: (res) => {
+ console.log('移除isSocketOpensuccess');
+ }
+ });
+ clearTimeout(this.timer);
+ clearTimeout(this.timeoutObj);
+ }
+
+ //心跳检测
+ start() {
+ clearTimeout(this.timeoutObj);
+ this.timeoutObj = setTimeout(() => {
+ let obj = {
+ type: 'ping'
+ };
+ let objStr = JSON.stringify(obj)
+ uni.sendSocketMessage({
+ data: objStr,
+ });
+ this.start()
+ }, this.timout)
+ }
+
+ // 监听事件集
+ initEventHandle() {
+ // 监听打开
+ uni.onSocketOpen(res => {
+ uni.setStorageSync('isSocketOpen', true)
+ console.log('连接成功!');
+ this.lockReconnect = true;
+ this.isClose = false;
+ this.start()
+ });
+
+ // 监听消息
+ this.onMsg()
+
+ // 监听错误
+ uni.onSocketError(err => {
+ console.log('连接错误', err);
+ uni.closeSocket();
+ });
+
+ // 监听关闭
+ uni.onSocketClose(res => {
+ console.log('关闭链接');
+ this.isClose = true;
+ if (uni.getStorageSync('isSocketOpen')) {
+ this.lockReconnect = false
+ this.reconnect()
+ }
+
+
+ });
+ }
+
+ // 重连
+ reconnect() {
+ if (this.lockReconnect) return;
+ clearTimeout(this.timer)
+ if (this.limit < 12) {
+ this.timer = setTimeout(() => {
+ console.log('重连中', this.limit);
+ this.init();
+ this.reconnect()
+ }, 5000);
+ this.limit += 1
+ }
+ }
+
+
+}
diff --git a/pages/public/chat/shopro/chat.scss b/pages/public/chat/shopro/chat.scss
new file mode 100644
index 0000000..47aaec8
--- /dev/null
+++ b/pages/public/chat/shopro/chat.scss
@@ -0,0 +1,185 @@
+.bg-gradual-purple {
+ background-image: linear-gradient(45deg, #9000ff, #5e00ff);
+ color: #ffffff;
+}
+
+.bg-white {
+ background-color: #ffffff;
+ color: #666666;
+}
+
+.round {
+ border-radius: 5000upx;
+}
+
+/* ==================
+ 聊天
+ ==================== */
+.cu-avatar {
+ font-variant: small-caps;
+ margin: 0;
+ padding: 0;
+ display: inline-flex;
+ text-align: center;
+ justify-content: center;
+ align-items: center;
+ background-color: #ccc;
+ color: #ffffff;
+ white-space: nowrap;
+ position: relative;
+ width: 64upx;
+ height: 64upx;
+ background-size: cover;
+ background-position: center;
+ vertical-align: middle;
+ font-size: 1.5em;
+}
+
+.cu-bar {
+ display: flex;
+ position: relative;
+ align-items: center;
+ min-height: 100upx;
+ justify-content: space-between;
+ background-color: #fff;
+}
+
+.cu-bar .action {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ justify-content: center;
+ max-width: 100%;
+}
+
+.cu-bar.foot {
+ position: fixed;
+ width: 100%;
+ bottom: 0;
+ z-index: 1024;
+ box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-chat {
+ display: flex;
+ flex-direction: column;
+}
+
+.cu-chat .cu-item {
+ display: flex;
+ padding: 30upx 30upx 70upx;
+ position: relative;
+}
+
+.cu-chat .cu-item > .cu-avatar {
+ width: 80upx;
+ height: 80upx;
+}
+
+.cu-chat .cu-item > .main {
+ max-width: calc(100% - 260upx);
+ margin: 0 40upx;
+ display: flex;
+ align-items: center;
+}
+
+.cu-chat .cu-item > image {
+ height: 320upx;
+}
+
+.cu-chat .cu-item > .main .content {
+ padding: 20upx;
+ border-radius: 6upx;
+ display: inline-flex;
+ max-width: 100%;
+ align-items: center;
+ font-size: 30upx;
+ position: relative;
+ min-height: 80upx;
+ line-height: 40upx;
+ text-align: left;
+}
+
+.cu-chat .cu-item > .main .content:not([class*='bg-']) {
+ background-color: #ffffff;
+ color: #333333;
+}
+
+.cu-chat .cu-item .date {
+ position: absolute;
+ font-size: 24upx;
+ color: #8799a3;
+ width: calc(100% - 320upx);
+ bottom: 20upx;
+ left: 160upx;
+}
+
+.cu-chat .cu-item .action {
+ padding: 0 30upx;
+ display: flex;
+ align-items: center;
+}
+
+.cu-chat .cu-item > .main .content::after {
+ content: '';
+ top: 27upx;
+ transform: rotate(45deg);
+ position: absolute;
+ z-index: 100;
+ display: inline-block;
+ overflow: hidden;
+ width: 24upx;
+ height: 24upx;
+ left: -12upx;
+ right: initial;
+ background-color: inherit;
+}
+
+.cu-chat .cu-item.self > .main .content::after {
+ left: auto;
+ right: -12upx;
+}
+
+.cu-chat .cu-item > .main .content::before {
+ content: '';
+ top: 30upx;
+ transform: rotate(45deg);
+ position: absolute;
+ z-index: -1;
+ display: inline-block;
+ overflow: hidden;
+ width: 24upx;
+ height: 24upx;
+ left: -12upx;
+ right: initial;
+ background-color: inherit;
+ filter: blur(5upx);
+ opacity: 0.3;
+}
+
+.cu-chat .cu-item > .main .content:not([class*='bg-'])::before {
+ background-color: #333333;
+ opacity: 0.1;
+}
+
+.cu-chat .cu-item.self > .main .content::before {
+ left: auto;
+ right: -12upx;
+}
+
+.cu-chat .cu-item.self {
+ justify-content: flex-end;
+ text-align: right;
+}
+
+.cu-chat .cu-info {
+ display: inline-block;
+ margin: 20upx auto;
+ font-size: 24upx;
+ padding: 8upx 12upx;
+ background-color: rgba(0, 0, 0, 0.2);
+ border-radius: 6upx;
+ color: #ffffff;
+ max-width: 400upx;
+ line-height: 1.4;
+}
diff --git a/pages/public/chat/shopro/index.vue b/pages/public/chat/shopro/index.vue
new file mode 100644
index 0000000..090d517
--- /dev/null
+++ b/pages/public/chat/shopro/index.vue
@@ -0,0 +1,1115 @@
+
+
+
+
+
+
+ {{ navTitle.split(',')[0] }}
+
+
+ 在线
+
+
+
+ 离线
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ chat.msg }}
+ {{ $u.timeFrom(chat.date) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 订单号:{{ chat.msg.order_sn }}
+
+
+
+ {{ chat.msg.title }}
+
+
+ {{ chat.msg.price }}
+ {{ chat.msg.status_name }}
+
+
+
+
+
+
+
+
+
+
+ {{ chat.msg.title }}
+
+ {{ chat.msg.price }}
+
+
+
+
+
+
+
+
+
+
+
+ 猜你想问
+ * {{ item.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/chat/wm/config.js b/pages/public/chat/wm/config.js
new file mode 100644
index 0000000..2689e76
--- /dev/null
+++ b/pages/public/chat/wm/config.js
@@ -0,0 +1,131 @@
+import {
+ BASE_URL
+} from '@/env.js'
+const expression = [{
+ 'title': '[zy]',
+ 'src': '/emoji/1.png'
+ }, {
+ 'title': '[zm]',
+ 'src': '/emoji/2.png'
+ }, {
+ 'title': '[jy]',
+ 'src': '/emoji/3.png'
+ },
+ {
+ 'title': '[jyb]',
+ 'src': '/emoji/4.png'
+ }, {
+ 'title': '[bx]',
+ 'src': '/emoji/5.png'
+ }, {
+ 'title': '[kzn]',
+ 'src': '/emoji/6.png'
+ },
+ {
+ 'title': '[gg]',
+ 'src': '/emoji/7.png'
+ }, {
+ 'title': '[ll]',
+ 'src': '/emoji/8.png'
+ }, {
+ 'title': '[jyll]',
+ 'src': '/emoji/9.png'
+ },
+ {
+ 'title': '[o]',
+ 'src': '/emoji/10.png'
+ }, {
+ 'title': '[yz]',
+ 'src': '/emoji/11.png'
+ }, {
+ 'title': '[wx]',
+ 'src': '/emoji/12.png'
+ },
+ {
+ 'title': '[zyb]',
+ 'src': '/emoji/13.png'
+ }, {
+ 'title': '[tp]',
+ 'src': '/emoji/14.png'
+ }, {
+ 'title': '[wxb]',
+ 'src': '/emoji/15.png'
+ },
+ {
+ 'title': '[zyc]',
+ 'src': '/emoji/16.png'
+ }, {
+ 'title': '[llb]',
+ 'src': '/emoji/17.png'
+ }, {
+ 'title': '[xm]',
+ 'src': '/emoji/18.png'
+ },
+ {
+ 'title': '[qz]',
+ 'src': '/emoji/19.png'
+ }, {
+ 'title': '[zmb]',
+ 'src': '/emoji/20.png'
+ }, {
+ 'title': '[kx]',
+ 'src': '/emoji/21.png'
+ },
+ {
+ 'title': '[mm]',
+ 'src': '/emoji/22.png'
+ }, {
+ 'title': '[bz]',
+ 'src': '/emoji/23.png'
+ }, {
+ 'title': '[bkx]',
+ 'src': '/emoji/24.png'
+ },
+ {
+ 'title': '[mg]',
+ 'src': '/emoji/25.png'
+ }, {
+ 'title': '[pz]',
+ 'src': '/emoji/26.png'
+ }, {
+ 'title': '[pzb]',
+ 'src': '/emoji/27.png'
+ },
+ {
+ 'title': '[wxc]',
+ 'src': '/emoji/28.png'
+ }, {
+ 'title': '[jyc]',
+ 'src': '/emoji/29.png'
+ }, {
+ 'title': '[jyd]',
+ 'src': '/emoji/30.png'
+ },
+ {
+ 'title': '[dm]',
+ 'src': '/emoji/31.png'
+ }, {
+ 'title': '[tpb]',
+ 'src': '/emoji/32.png'
+ }, {
+ 'title': '[tpc]',
+ 'src': '/emoji/33.png'
+ },
+ {
+ 'title': '[tpd]',
+ 'src': '/emoji/34.png'
+ }, {
+ 'title': '[ly]',
+ 'src': '/emoji/35.png'
+ }, {
+ 'title': '[zyd]',
+ 'src': '/emoji/36.png'
+ },
+];
+
+let service = BASE_URL.split('://')[1].split(':')[0];
+export default {
+ baseURL: service, // dev.7wpp.com 启动workerman服务的域名,无需填写协议和端口
+ https_switch: false, // 是否启用https协议(默认关,正式版必开,且需要参考文档创建wss服务)
+ expression
+}
diff --git a/pages/public/chat/wm/index.vue b/pages/public/chat/wm/index.vue
new file mode 100644
index 0000000..08137cb
--- /dev/null
+++ b/pages/public/chat/wm/index.vue
@@ -0,0 +1,1622 @@
+
+
+
+
+
+ {{ errorTips }}
+
+ {{ config.announcement }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.datetime }}
+
+
+
+ {{ message.message }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ message.message.subject }}
+ {{message.message.note}}
+
+
+ {{ message.message.price }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{selectModelType[selectModel]}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 没有更多记录了...
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/faq.vue b/pages/public/faq.vue
new file mode 100644
index 0000000..c003ba8
--- /dev/null
+++ b/pages/public/faq.vue
@@ -0,0 +1,65 @@
+
+
+
+
+ {{ item.content }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/feedback.vue b/pages/public/feedback.vue
new file mode 100644
index 0000000..20ce1c8
--- /dev/null
+++ b/pages/public/feedback.vue
@@ -0,0 +1,218 @@
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/loading.vue b/pages/public/loading.vue
new file mode 100644
index 0000000..bfea71a
--- /dev/null
+++ b/pages/public/loading.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
diff --git a/pages/public/richtext.vue b/pages/public/richtext.vue
new file mode 100644
index 0000000..c184d3f
--- /dev/null
+++ b/pages/public/richtext.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/search.vue b/pages/public/search.vue
new file mode 100644
index 0000000..35b1651
--- /dev/null
+++ b/pages/public/search.vue
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+ 搜索历史
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/public/webview.vue b/pages/public/webview.vue
new file mode 100644
index 0000000..8970e79
--- /dev/null
+++ b/pages/public/webview.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
diff --git a/pages/user/address/edit.vue b/pages/user/address/edit.vue
new file mode 100644
index 0000000..59949a8
--- /dev/null
+++ b/pages/user/address/edit.vue
@@ -0,0 +1,344 @@
+
+
+
+
+
+
+
+
+ {{ chooseAddress }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 设为默认地址
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/address/list.vue b/pages/user/address/list.vue
new file mode 100644
index 0000000..9dc6832
--- /dev/null
+++ b/pages/user/address/list.vue
@@ -0,0 +1,166 @@
+
+
+
+
+
+ {{ address.consignee }}
+ {{ address.phone }}
+ 默认
+
+ {{ address.province_name }}{{ address.city_name }}{{ address.area_name }}{{ address.address }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/favorite.vue b/pages/user/favorite.vue
new file mode 100644
index 0000000..38a31e1
--- /dev/null
+++ b/pages/user/favorite.vue
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+ 共
+ {{ total }}
+ 件商品
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/info.vue b/pages/user/info.vue
new file mode 100644
index 0000000..068f041
--- /dev/null
+++ b/pages/user/info.vue
@@ -0,0 +1,473 @@
+
+
+
+
+ 基本信息
+
+
+
+ 头像
+
+
+
+
+
+
+ 昵称
+
+
+
+
+
+
+ 生日
+
+ {{ userData.birthday || "请选择生日~" }}
+
+
+
+
+
+ 地址管理
+
+
+
+
+
+
+ 修改密码
+
+
+
+
+
+
+ 手机号
+
+ {{ userInfo.mobile || "暂未绑定手机号" }}
+
+
+
+
+
+
+
+ 第三方账号绑定
+
+
+
+
+
+ 微信小程序
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 微信公众号
+
+
+
+
+ {{ thirdOauthInfo.nickname }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 微信
+
+
+
+
+ {{ thirdOauthInfo.nickname }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/set.vue b/pages/user/set.vue
new file mode 100644
index 0000000..ad2ce87
--- /dev/null
+++ b/pages/user/set.vue
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+ {{ initShop.name }}
+
+
+
+
+
+ 占用缓存
+
+ {{ storageSize }}
+
+
+
+
+ 当前版本
+
+ {{ initShop.version }}
+
+
+
+
+ 意见反馈
+
+
+
+ 关于我们
+
+
+
+ 隐私协议
+
+
+
+
+ 注销账号
+
+
+
+
+
+
+
+ {{ initShop.copyright[0] }}
+ {{ initShop.copyright[1] }}
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/view-log.vue b/pages/user/view-log.vue
new file mode 100644
index 0000000..f204077
--- /dev/null
+++ b/pages/user/view-log.vue
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/wallet/index.vue b/pages/user/wallet/index.vue
new file mode 100644
index 0000000..7097c19
--- /dev/null
+++ b/pages/user/wallet/index.vue
@@ -0,0 +1,345 @@
+
+
+
+
+
+
+
+ 可提现金额(元)
+
+
+ {{ showMoney ? userInfo.money || '0.00' : '*****' }}
+
+
+
+
+
+
+
+
+ 收入¥{{ incomeMoney || '0.00' }} 支出¥{{ expendMoney || '0.00' }}
+
+
+
+
+ {{ state.name }}
+
+
+
+
+
+
+
+
+
+
+ {{ item.type_name }}{{ item.title ? '-' + item.title : '' }}
+
+ +{{ item.wallet }}
+ {{ item.wallet }}
+
+
+ {{ $u.timeFormat(item.createtime, 'yyyy-mm-dd hh:MM') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/wallet/score-balance.vue b/pages/user/wallet/score-balance.vue
new file mode 100644
index 0000000..a7862d2
--- /dev/null
+++ b/pages/user/wallet/score-balance.vue
@@ -0,0 +1,175 @@
+
+
+
+
+
+
+ {{ userInfo.score || 0 }}
+ 当前积分
+
+
+
+ 全部
+ 收入
+ 支出
+
+
+
+
+
+
+ {{ log.type_name }}
+ {{ $u.timeFormat(log.createtime) }}
+
+ {{ log.wallet }}
+ {{ log.wallet }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/wallet/top-up-log.vue b/pages/user/wallet/top-up-log.vue
new file mode 100644
index 0000000..c1db236
--- /dev/null
+++ b/pages/user/wallet/top-up-log.vue
@@ -0,0 +1,127 @@
+
+
+
+
+
+ {{item.pay_type_text}}充值
+ {{ item.total_fee }} 元
+
+
+ 充值单号
+
+ {{item.order_sn}}
+
+
+ 充值时间
+
+ {{$u.timeFormat(item.createtime, 'yyyy.mm.dd hh:MM:ss')}}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/wallet/top-up.vue b/pages/user/wallet/top-up.vue
new file mode 100644
index 0000000..ed14eb7
--- /dev/null
+++ b/pages/user/wallet/top-up.vue
@@ -0,0 +1,284 @@
+
+
+
+
+
+
+
+
+ 账户余额(元)
+ {{ userInfo.money || '0.00' }}
+
+
+
+
+
+
+ 充值金额
+
+ ¥
+
+
+
+
+ 快捷充值
+
+
+
+ {{item.money}}
+
+
+
+
+
+
+
+
+
+
+ 充值说明
+ 1.充值为在线支付,即时到账,不支持退款;
+
+ 2.充值后金额会自动进入您的余额账户,请注意查收。
+
+
+
+
+
+
+
+
diff --git a/pages/user/wallet/withdraw-log.vue b/pages/user/wallet/withdraw-log.vue
new file mode 100644
index 0000000..b00726f
--- /dev/null
+++ b/pages/user/wallet/withdraw-log.vue
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+ 提现至{{ item.apply_type_text }}
+ {{ item.money }} 元
+
+
+ 申请状态
+ {{ item.status_text }}
+
+
+ 账户信息
+ {{ item.apply_info | applyInfoFilter }}
+
+
+ 提现单号
+ {{ item.apply_sn }}
+
+
+ 手续费
+ {{ item.charge_money }} 元
+
+
+ 申请时间
+ {{ $u.timeFormat(item.createtime, 'yyyy.mm.dd hh:MM:ss') }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/user/wallet/withdraw.vue b/pages/user/wallet/withdraw.vue
new file mode 100644
index 0000000..b012398
--- /dev/null
+++ b/pages/user/wallet/withdraw.vue
@@ -0,0 +1,537 @@
+
+
+
+
+
+
+
+
+ 可提现金额(元)
+ {{ userInfo.money || '0.00' }}
+
+
+
+
+
+
+ 提现金额
+
+ ¥
+
+
+
+ 提现至
+
+ 请选择提现方式
+
+
+ {{ withdrawList[withdrawType].title }}
+
+
+
+
+
+
+
+
+
+ {{ !withdrawInfo ? '暂无微信授权信息' : `${withdrawInfo.bank_name || ''} [${withdrawInfo.card_no || ''}] ${withdrawInfo.real_name || ''}` }}
+
+
+
+
+
+ {{
+ !withdrawInfo
+ ? `暂无${withdrawList[withdrawType].title}信息`
+ : `${withdrawInfo.bank_name || ''} [${withdrawInfo.card_no || ''}] ${withdrawInfo.real_name || ''}`
+ }}
+
+
+
+
+
+
+
+
+
+ 提现说明
+ 1.单次最低提现 {{ ruleInfo.min }} 元,最高提现 {{ ruleInfo.max }} 元;
+
+ 2.每日最多可提现次数: {{ ruleInfo.perday_num ? ruleInfo.perday_num : '不限' }};每日最多提现金额(元):
+ {{ ruleInfo.perday_amount ? ruleInfo.perday_amount : '不限' }};
+
+ 3.每笔收取提现手续费 {{ ruleInfo.service_fee }}%;
+ 4.提现结果请查收对应渠道服务通知;
+ 5.如有疑问请及时联系客服。
+
+
+
+
+ 选择提现方式
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formTitle }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/shopro/apple/index.js b/shopro/apple/index.js
new file mode 100644
index 0000000..b69849c
--- /dev/null
+++ b/shopro/apple/index.js
@@ -0,0 +1,76 @@
+/**
+ * Apple v1.0.0
+ * @Class Apple
+ * @description shopro-apple 1.0.0 apple第三方登录组件
+ * @Author lidongtony
+ * @Date 2020-02-19
+ * @Email lidongtony@qq.com
+ */
+import api from '@/shopro/request/index';
+
+export default {
+ eventMap(event) {
+ let map = '';
+ switch (event) {
+ case 'login':
+ map = '登录中...';
+ break;
+ case 'refresh':
+ map = '更新中...';
+ break;
+ case 'bind':
+ map = '绑定中...';
+ break;
+ }
+ return map;
+ },
+
+ // #ifdef APP-PLUS
+ // 微信开放平台登录
+ appleIdOauth(event = 'login') {
+ let that = this;
+ return new Promise((resolve, reject) => {
+ uni.login({
+ provider: 'apple',
+ success: function(loginRes) {
+ if (loginRes.errMsg === "login:ok") {
+ // 登录成功
+ uni.getUserInfo({
+ provider: 'apple',
+ success(res) {
+ if(res.errMsg === 'getUserInfo:ok') {
+ let userInfo = res.userInfo;
+ api('user.appleIdOauth', {
+ userInfo,
+ event
+ }, that.eventMap(event)).then(res => {
+ if (res.code === 1) {
+ resolve(res.data.token);
+ } else {
+ resolve(false);
+ }
+ });
+ }
+ // 获取用户信息成功
+ }
+ })
+
+
+ }
+ },
+ fail: function(res) {
+ uni.showToast({
+ title: '请稍后再试'
+ });
+ resolve(false);
+ api('common.debug', {
+ info: res
+ })
+ },
+ complete: function(res) {
+ }
+ });
+ });
+ },
+ // #endif
+}
diff --git a/shopro/index.js b/shopro/index.js
new file mode 100644
index 0000000..9340350
--- /dev/null
+++ b/shopro/index.js
@@ -0,0 +1,60 @@
+// 挂载变量
+import {
+ BASE_URL,
+ API_URL,
+ IMG_URL
+} from '../env.js';
+import store from '@/shopro/store';
+import http from '@/shopro/request';
+import platform from '@/shopro/platform';
+import tools from '@/shopro/utils/tools'
+// mixin混入
+import mixin from '@/shopro/mixins';
+// #ifdef H5
+// uni方法重写, h5的粘贴板的设置,获取。图片视频的保存
+import wxsdk from '@/shopro/wechat/sdk'
+import VConsole from 'vconsole'
+import '@/shopro/utils/sdk-h5.js'
+// #endif
+
+import wechat from '@/shopro/wechat/wechat';
+
+const install = Vue => {
+ Vue.prototype.$BASE_URL = BASE_URL;
+ Vue.prototype.$API_URL = API_URL;
+ Vue.prototype.$IMG_URL = IMG_URL;
+ // 挂载请求
+ Vue.prototype.$http = http;
+ // 平台判断
+ Vue.prototype.$platform = platform;
+ // 挂载工具函数
+ Vue.prototype.$tools = tools;
+ Vue.mixin(mixin);
+
+ // #ifdef H5
+ // 微信H5,sdk挂载
+ Vue.prototype.$wxsdk = wxsdk;
+ // 调试微信jssdk
+ process.env.NODE_ENV === 'development' && new VConsole()
+ // #endif
+}
+
+export async function init(options) {
+ // #ifdef H5
+ platform.entry();
+ // #endif
+ // #ifdef MP-WEIXIN
+ // 检测小程序更新(如果从朋友圈场景进入则无此API)
+ options.scene !== 1154 && wechat.checkMiniProgramUpdate();
+ // #endif
+ await store.dispatch("appInit", options); // 加载商城基本信息
+ await store.dispatch("getTemplate", options); // 加载模板数据
+ // #ifdef MP-WEIXIN
+ await store.dispatch('getMessageIds'); //获取模板消息
+ // #endif
+ process.env.NODE_ENV === 'development' && store.dispatch("syncPages");
+}
+
+export default {
+ install
+}
diff --git a/shopro/mixins/index.js b/shopro/mixins/index.js
new file mode 100644
index 0000000..46ce5e5
--- /dev/null
+++ b/shopro/mixins/index.js
@@ -0,0 +1,121 @@
+/**
+ * MixinIndex v1.0.0
+ * @description shopro-mixin-index 1.0.0 shopro全局入口组件
+ * @Author lidongtony
+ * @Date 2021-04-18
+ * @Email lidongtony@qq.com
+ */
+
+import store from '@/shopro/store'
+import share from '@/shopro/share'
+import http from '@/shopro/request'
+import $platform from '@/shopro/platform'
+import {
+ router
+} from '@/shopro/router'
+export default {
+ onLoad(options) {
+ let that = this;
+ // 后端拼接的具体page页面 直接进入 (如订阅消息场景下直接跳转)
+ // #ifdef MP
+ if (options?.scene) {
+ let scene = decodeURIComponent(options.scene);
+ let sceneObj = scene.split('=');
+ options[sceneObj[0]] = sceneObj[1];
+ }
+ // #endif
+ if (options?.page) {
+ router.replace({
+ path: decodeURIComponent(options.page)
+ })
+ }
+ if (options?.custom_id) {
+ router.replace({
+ path: '/pages/index/view',
+ query: {
+ id: options.custom_id
+ }
+ })
+ }
+ if (options?.spm) {
+ let shareParams = share.getShareQuery(options.spm);
+ // 保存推荐信息
+ if (shareParams.shareUserId) {
+ if (store.getters.isLogin) {
+ http('common.shareAdd', {
+ spm: options.spm
+ });
+ } else {
+ uni.setStorageSync('spm', options.spm);
+ }
+ }
+ // 跳转分享路径
+ let page = {};
+ if (shareParams.page) {
+ page.path = shareParams.page;
+ }
+ if (shareParams.pageId) {
+ page.query = {
+ id: shareParams.pageId
+ }
+ }
+ if (page.path) {
+ router.replace(page);
+ }
+ }
+ },
+ // #ifdef MP-WEIXIN
+ onShareAppMessage(res) {
+ let that = this;
+ // uni.$emit('ON_WX_SHARE')
+ let shareInfo = store.getters.shareInfo;
+ return {
+ title: shareInfo.title,
+ path: shareInfo.path,
+ imageUrl: shareInfo.image,
+ success(res) {
+ uni.showToast({
+ title: '分享成功'
+ })
+
+ },
+ fail(res) {
+ uni.showToast({
+ title: '分享失败',
+ icon: 'none'
+ })
+ },
+ complete() {}
+ }
+ },
+ onShareTimeline(res) {
+ let that = this;
+ let shareInfo = store.getters.shareInfo;
+ let query = shareInfo.query;
+ //携带当前页面资源ID参数
+ let currentPage = getCurrentPages()[getCurrentPages().length - 1];
+ let options = currentPage.options;
+ if (JSON.stringify(options) != '{}' && options.id) {
+ query += `&id=${options.id}`;
+ }
+
+ return {
+ title: shareInfo.title,
+ query: query,
+ imageUrl: shareInfo.image,
+ success(res) {
+ uni.showToast({
+ title: '分享成功'
+ })
+ },
+ fail(res) {
+ uni.showToast({
+ title: '分享失败',
+ icon: 'none'
+ })
+ },
+ complete() {}
+ }
+ }
+ // #endif
+}
diff --git a/shopro/pay/index.js b/shopro/pay/index.js
new file mode 100644
index 0000000..91111e6
--- /dev/null
+++ b/shopro/pay/index.js
@@ -0,0 +1,275 @@
+import $http from '@/shopro/request/index'
+// #ifdef H5
+import wxsdk from '@/shopro/wechat/sdk'
+// #endif
+import wechat from '@/shopro/wechat/wechat'
+import {
+ router as $Router
+} from '@/shopro/router/index.js'
+import store from '@/shopro/store';
+import $platform from '@/shopro/platform';
+
+/**
+ * 支付
+ *
+ * @param {String} payment = ['wechat','alipay','wallet'] - 支付方式
+ * @param {Object} order = {} - 订单详情
+ * @param {String} orderType = ['goods','recharge'] - 订单类型
+ */
+
+export default class ShoproPay {
+
+
+ // wxOfficialAccount wxMiniProgram App H5
+ // wechat 公众号JSSDK支付 小程序支付 微信开放平台支付 H5网页支付
+ // alipay 复制网址 复制网址 支付宝开放平台支付 直接跳转链接
+ // wallet v v v v
+
+
+ constructor(payment, order, orderType) {
+ this.payment = payment;
+ this.order = order;
+ this.orderType = orderType;
+ this.platform = $platform.get();
+ 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;
+ return new Promise((resolve, reject) => {
+ let that = this;
+
+ let domain = store.getters.initShop.domain;
+ let return_url = `${domain}pages/order/payment/result?orderId=***&type=${that.payment}&payState=success&orderType=${that.orderType}`
+ console.log(return_url, 'return_url');
+ let params = {
+ order_sn: that.order.order_sn,
+ payment: that.payment,
+ return_url: return_url
+ }
+ if (uni.getStorageSync('openid')) {
+ params.openid = uni.getStorageSync('openid');
+ }
+ $http('money.prepay', params, '支付中').then(res => {
+ if (res.code === 1) {
+ res.data === 'no_openid' ?
+ uni.showModal({
+ title: '微信支付',
+ content: '请先绑定微信再使用微信支付',
+ success: function(res) {
+ if (res.confirm) {
+ wechat.bind();
+ }
+ },
+ }) :
+ resolve(res);
+
+ }
+ })
+ });
+ }
+
+
+ // 微信H5支付
+ async wxOfficialAccountPay() {
+ let that = this;
+ let result = await this.prepay();
+ wxsdk.wxpay(result.data.pay_data, (res) => {
+ if (res.err_msg == "get_brand_wcpay_request:ok") {
+ that.payResult('success')
+ } else {
+ that.payResult('fail')
+ }
+ });
+ }
+
+ //浏览器微信支付
+ async wechatWapPay() {
+ let that = this;
+ let result = await this.prepay();
+ if (result.code === 1) {
+ let newUrl = '';
+ if (result.data.pay_data && result.data.pay_data.h5_url != undefined) {
+ console.log('v3');
+ newUrl = result.data.pay_data.h5_url;
+ } else {
+ console.log('v2');
+ var url = result.data.pay_data.match(/url\=\'(\S*)\'/);
+ let reg = new RegExp('&', 'g') //g代表全部
+ newUrl = url[1].replace(reg, '&');
+ }
+
+ let domain = store.getters.initShop.domain; //域名需要https
+ let params = encodeURIComponent(
+ `${domain}pages/order/payment/result?orderId=${that.order.id}&type=${that.payment}&orderType=${that.orderType}`
+ )
+ window.location.href = newUrl + '&redirect_url=' + params;
+ }
+ }
+
+ // 微信小程序支付
+ async wxMiniProgramPay() {
+ let that = this;
+ let result = await this.prepay();
+ uni.requestPayment({
+ provider: 'wxpay',
+ ...result.data.pay_data,
+ success: res => {
+ that.payResult('success')
+ },
+ fail: err => {
+ console.log('支付取消或者失败:', err);
+ err.errMsg !== "requestPayment:fail cancel" && that.payResult('fail')
+ }
+ });
+ }
+
+ // 余额支付
+ async walletPay() {
+ let that = this;
+ let result = await this.prepay();
+ result.code === 1 && that.payResult('success')
+ }
+
+ // 支付宝复制链接支付
+ 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) {
+ that.$u.toast('已复制到剪切板');
+ }
+ });
+ }
+ }
+ })
+ }
+ }
+
+ // 支付链接
+ 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: res => {
+ that.payResult('success')
+ },
+ fail: err => {
+ console.log('支付取消或者失败:', err);
+ err.errMsg !== "requestPayment:fail cancel" && that.payResult('fail')
+ }
+ });
+ }
+ }
+
+ // 微信支付
+ 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: res => {
+ that.payResult('success')
+ },
+ fail: err => {
+ err.errMsg !== "requestPayment:fail cancel" && that.payResult('fail')
+ console.log('支付取消或者失败:', err);
+ }
+ });
+ }
+ }
+
+
+ // 支付结果跳转,success:成功,fail:失败
+ payResult(resultType) {
+ const that = this;
+ $Router.replace({
+ path: '/pages/order/payment/result',
+ query: {
+ orderId: that.order.id,
+ type: that.payment, //重新支付的时候使用
+ payState: resultType,
+ orderType: that.orderType
+ }
+ });
+ }
+
+}
diff --git a/shopro/permission/app.js b/shopro/permission/app.js
new file mode 100644
index 0000000..f456834
--- /dev/null
+++ b/shopro/permission/app.js
@@ -0,0 +1,284 @@
+/**
+ * 本模块封装了Android、iOS的应用权限判断、打开应用权限设置界面、以及位置系统服务是否开启
+ * @description 安卓相关权限,需要先在manifest.json中勾选
+ * @param {String} scopeValue - 权限种类
+ *
+ */
+
+// 只写了当前项目用到的权限,其他用到的自己加下
+const PERMISSION_MAP = {
+ 'userLocation': {
+ tip: '地理位置',
+ androidPermissionID: ['android.permission.ACCESS_FINE_LOCATION'],
+
+ },
+ 'writePhotosAlbum': {
+ tip: '保存到相册',
+ androidPermissionID: ['android.permission.WRITE_EXTERNAL_STORAGE'],
+
+ },
+ 'camera': {
+ tip: '摄像头',
+ androidPermissionID: ['android.permission.CAMERA'],
+
+ }
+
+}
+
+
+// 判断平台
+let isIos = (plus.os.name == "iOS")
+
+export default class AppAuth {
+ constructor(scopeValue) {
+ this.scopeValue = scopeValue
+ }
+
+ //权限检测
+ async checkAuth() {
+ const that = this
+ let result = false
+ switch (this.scopeValue) {
+ case 'userLocation': //定位权限
+ result = isIos ? that.iosLocationAuth : await that.androidAuth()
+ break;
+ case 'writePhotosAlbum': //相册权限
+ result = isIos ? that.iosPhotoAuth : await that.androidAuth()
+ break;
+ case 'camera': //摄像头权限
+ result = isIos ? that.iosCameraAuth : await that.androidAuth()
+ break;
+ default:
+ result = false
+ break;
+ }
+ return Promise.resolve(result)
+ }
+
+ // Android权限查询
+ androidAuth() {
+ const that = this;
+ let permissionID = PERMISSION_MAP[this.scopeValue].androidPermissionID;
+ return new Promise((resolve, reject) => {
+ plus.android.requestPermissions(
+ [...permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
+ function(resultObj) {
+ let 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);
+ // 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
+ if (result !== 1) {
+ that.gotoAppSetting()
+ }
+ },
+ function(error) {
+ console.log('申请权限错误:' + error.code + " = " + error.message);
+ resolve({
+ code: error.code,
+ message: error.message
+ });
+ }
+ );
+ });
+ }
+
+ // 跳转到**应用**的权限页面
+ gotoAppSetting() {
+ uni.showModal({
+ title: '设置权限',
+ content: `当前功能需要${PERMISSION_MAP[this.scopeValue].tip}权限,是否去设置?`,
+ confirmText: '设置',
+ success: res => {
+ if (res.confirm) {
+ if (isIos) {
+ let UIApplication = plus.ios.import("UIApplication");
+ let application2 = UIApplication.sharedApplication();
+ let NSURL2 = plus.ios.import("NSURL");
+ let setting2 = NSURL2.URLWithString("app-settings:");
+ application2.openURL(setting2);
+ plus.ios.deleteObject(setting2);
+ plus.ios.deleteObject(NSURL2);
+ plus.ios.deleteObject(application2);
+ } else {
+ let Intent = plus.android.importClass("android.content.Intent");
+ let Settings = plus.android.importClass("android.provider.Settings");
+ let Uri = plus.android.importClass("android.net.Uri");
+ let mainActivity = plus.android.runtimeMainActivity();
+ let intent = new Intent();
+ intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ let uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
+ intent.setData(uri);
+ mainActivity.startActivity(intent);
+ }
+ }
+ },
+ fail: err => {
+ console.log(`%cuni.showModal失败:`, 'color:green;background:yellow');
+ }
+ })
+ }
+
+
+
+ // 定位是否开启
+ iosLocationAuth() {
+ let result = 0;
+ let cllocationManger = plus.ios.import("CLLocationManager");
+ let enable = cllocationManger.locationServicesEnabled();
+ let 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;
+ }
+
+ // 判断推送权限是否开启
+ iosPushAuth() {
+ let result = false;
+ let UIApplication = plus.ios.import("UIApplication");
+ let app = UIApplication.sharedApplication();
+ let enabledTypes = 0;
+ if (app.currentUserNotificationSettings) {
+ let settings = app.currentUserNotificationSettings();
+ enabledTypes = settings.plusGetAttribute("types");
+ console.log("enabledTypes1:" + enabledTypes);
+ if (enabledTypes == 0) {
+ console.log("推送权限没有开启");
+ } else {
+ result = true;
+ console.log("已经开启推送功能!")
+ }
+ plus.ios.deleteObject(settings);
+ } else {
+ enabledTypes = app.enabledRemoteNotificationTypes();
+ if (enabledTypes == 0) {
+ console.log("推送权限没有开启!");
+ } else {
+ result = true;
+ console.log("已经开启推送功能!")
+ }
+ console.log("enabledTypes2:" + enabledTypes);
+ }
+ plus.ios.deleteObject(app);
+ plus.ios.deleteObject(UIApplication);
+ return result;
+ }
+
+
+
+ // 判断麦克风权限是否开启
+ iosRecordAuth() {
+ let result = false;
+ let avaudiosession = plus.ios.import("AVAudioSession");
+ let avaudio = avaudiosession.sharedInstance();
+ let permissionStatus = avaudio.recordPermission();
+ console.log("permissionStatus:" + permissionStatus);
+ if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {
+ console.log("麦克风权限没有开启");
+ } else {
+ result = true;
+ console.log("麦克风权限已经开启");
+ }
+ plus.ios.deleteObject(avaudiosession);
+ return result;
+ }
+
+ // 判断相机权限是否开启
+ iosCameraAuth() {
+ let result = false;
+ let AVCaptureDevice = plus.ios.import("AVCaptureDevice");
+ let authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');
+ console.log("authStatus:" + authStatus);
+ if (authStatus == 3) {
+ result = true;
+ console.log("相机权限已经开启");
+ } else {
+ console.log("相机权限没有开启");
+ }
+ plus.ios.deleteObject(AVCaptureDevice);
+ return result;
+ }
+
+ // 判断相册权限是否开启
+ iosPhotoAuth() {
+ let result = false;
+ let PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
+ let authStatus = PHPhotoLibrary.authorizationStatus();
+ console.log("authStatus:" + authStatus);
+ if (authStatus == 3) {
+ result = true;
+ console.log("相册权限已经开启");
+ } else {
+ console.log("相册权限没有开启");
+ }
+ plus.ios.deleteObject(PHPhotoLibrary);
+ return result;
+ }
+
+ // 判断通讯录权限是否开启
+ iosContactAuth() {
+ let result = false;
+ let CNContactStore = plus.ios.import("CNContactStore");
+ let cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
+ if (cnAuthStatus == 3) {
+ result = true;
+ console.log("通讯录权限已经开启");
+ } else {
+ console.log("通讯录权限没有开启");
+ }
+ plus.ios.deleteObject(CNContactStore);
+ return result;
+ }
+
+ // 判断日历权限是否开启
+ iosCalendarAuth() {
+ let result = false;
+ let EKEventStore = plus.ios.import("EKEventStore");
+ let ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
+ if (ekAuthStatus == 3) {
+ result = true;
+ console.log("日历权限已经开启");
+ } else {
+ console.log("日历权限没有开启");
+ }
+ plus.ios.deleteObject(EKEventStore);
+ return result;
+ }
+
+ // 判断备忘录权限是否开启
+ iosMemoAuth() {
+ let result = false;
+ let EKEventStore = plus.ios.import("EKEventStore");
+ let ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
+ if (ekAuthStatus == 3) {
+ result = true;
+ console.log("备忘录权限已经开启");
+ } else {
+ console.log("备忘录权限没有开启");
+ }
+ plus.ios.deleteObject(EKEventStore);
+ return result;
+ }
+
+}
diff --git a/shopro/permission/h5.js b/shopro/permission/h5.js
new file mode 100644
index 0000000..8de0ed8
--- /dev/null
+++ b/shopro/permission/h5.js
@@ -0,0 +1,37 @@
+/**
+ * H5相关权限
+ * @description 相关权限校验,调用在wechat/sdk.js
+ * @param {String} scopeValue - 权限种类
+ *
+ */
+
+const TIPS_MAP = {
+ 'userInfo': '用户信息',
+ 'userLocation': '地理位置',
+ 'address': '通信地址',
+ 'record': '录音功能',
+ 'writePhotosAlbum': '保存到相册',
+ 'message': '订阅消息'
+}
+export default class H5Auth {
+
+ constructor(scopeValue) {
+ this.scopeValue = scopeValue
+ }
+
+ // 检测当前请求权限是否可用。
+ checkAuth() {
+ const that = this;
+ return new Promise((resolve, reject) => {
+ switch (that.scopeValue) {
+ case 'writePhotosAlbum' || 'camera':
+ resolve(1)
+ break;
+ default:
+ resolve(1)
+ break;
+ }
+ })
+ }
+
+}
diff --git a/shopro/permission/index.js b/shopro/permission/index.js
new file mode 100644
index 0000000..e42e929
--- /dev/null
+++ b/shopro/permission/index.js
@@ -0,0 +1,37 @@
+/**
+ * 权限入口文件
+ * @param {String} authType -权限种类
+ */
+// #ifdef MP
+import MpAuth from './mp.js' //微信小程序
+// #endif
+
+// #ifdef H5
+import H5Auth from './h5.js' //H5相关
+// #endif
+
+// #ifdef APP-VUE
+import AppAuth from './app.js' //APP相关
+// #endif
+
+export default class Auth {
+
+ constructor(authType) {
+ this.authType = authType
+ }
+
+ async check() {
+ let state = 0
+ // #ifdef MP
+ state = await new MpAuth(this.authType).checkAuth()
+ // #endif
+ // #ifdef H5
+ state = await new H5Auth(this.authType).checkAuth()
+ // #endif
+ // #ifdef APP-VUE
+ state = await new AppAuth(this.authType).checkAuth()
+ // #endif
+ return Promise.resolve(state)
+ }
+
+}
diff --git a/shopro/permission/mp.js b/shopro/permission/mp.js
new file mode 100644
index 0000000..709483e
--- /dev/null
+++ b/shopro/permission/mp.js
@@ -0,0 +1,88 @@
+/**
+ * 小程序相关权限
+ * @param {String} scopeValue - 权限种类,isMessage为订阅消息设置,默认false
+ *
+ */
+
+const TIPS_MAP = {
+ 'userInfo': '用户信息',
+ 'userLocation': '地理位置', //需要在manifest中配置permission。
+ 'address': '通信地址',
+ 'userLocationBackground': '后台定位',
+ 'record': '录音功能',
+ 'writePhotosAlbum': '保存到相册',
+ 'camera': '摄像头',
+ 'invoice': '获取发票',
+ 'invoiceTitle': '发票抬头',
+ 'werun': '微信步数',
+ 'message': '订阅消息'
+}
+
+export default class MpAuth {
+
+ constructor(scopeValue) {
+ this.scopeValue = scopeValue
+ this.isMessage = scopeValue === 'message' ? true : false
+ }
+
+ // 检测当前请求权限是否可用。
+ checkAuth() {
+ const that = this;
+ return new Promise((resolve, reject) => {
+ uni.getSetting({
+ withSubscriptions: that.isMessage, //是否获取用户订阅消息的订阅状态
+ success: res => {
+ if (!that.isMessage) { // 非订阅消息
+ if (!res.authSetting[
+ `scope.${this.scopeValue}`]) { //用户未请求过此权限,后者用户拒绝了此权限
+ uni.authorize({ //如果没请求过,会弹窗询问。同意过,直接success。此前拒绝,直接fai
+ scope: `scope.${this.scopeValue}`,
+ success: res => { //用户同意
+ console.log(
+ `%c用户同意${TIPS_MAP[this.scopeValue]}权限1`,
+ 'color:green;background:yellow');
+ resolve(1)
+ },
+ fail: err => { //用户拒绝
+ console.log(
+ `%c用户拒绝${TIPS_MAP[this.scopeValue]}权限`,
+ 'color:green;background:yellow');
+ resolve(0)
+ that.setAuth()
+ }
+ })
+ } else { //用户同意授权此权限,直接调用接口
+ console.log(`%c用户同意${TIPS_MAP[this.scopeValue]}权限2`,
+ 'color:green;background:yellow');
+ resolve(1)
+ }
+ } else { //订阅消息 TODO
+
+ }
+ },
+ fail: err => {
+ console.log(`%cuni.getSetting失败:`, 'color:green;background:yellow');
+ console.log(err);
+ }
+ })
+ })
+
+
+ }
+
+ // 引导用户开启权限
+ setAuth() {
+ uni.showModal({
+ title: '设置权限',
+ content: `当前功能需要${TIPS_MAP[this.scopeValue]}权限,是否开启?`,
+ confirmText: '立即授权',
+ success: res => {
+ res.confirm && uni.openSetting()
+ },
+ fail: err => {
+ console.log(`%cuni.showModal失败:`, 'color:green;background:yellow');
+ }
+ })
+ }
+
+}
diff --git a/shopro/platform/index.js b/shopro/platform/index.js
new file mode 100644
index 0000000..a1c967c
--- /dev/null
+++ b/shopro/platform/index.js
@@ -0,0 +1,81 @@
+/**
+ * Platform v1.0.0
+ * @Class Platform
+ * @description shopro-platform 1.0.0 全平台兼容
+ * @Author lidongtony
+ * @Date 2021-04-07
+ * @Email lidongtony@qq.com
+ */
+
+// #ifdef H5
+// 微信H5
+import wxsdk from '@/shopro/wechat/sdk';
+import {
+ router
+} from '@/shopro/router';
+// #endif
+export default {
+
+ // 获取当前运行平台
+ get() {
+ let platform = '';
+ // #ifdef H5
+ wxsdk.isWechat() ? (platform = 'wxOfficialAccount') : (platform = 'H5');
+ // #endif
+ // #ifdef APP-PLUS
+ platform = 'App';
+ // #endif
+ // #ifdef MP-WEIXIN
+ platform = 'wxMiniProgram';
+ // #endif
+ // #ifdef MP-ALIPAY
+ platform = 'alipayMiniProgram';
+ // #endif
+ if (platform !== '') {
+ uni.setStorageSync('platform', platform);
+ } else {
+ uni.showToast({
+ title: '暂不支持该平台',
+ icon: 'none'
+ });
+ }
+ return platform;
+ },
+ set(platform) {
+ uni.setStorageSync('platform', platform);
+ return platform;
+ },
+
+ // 检测当前运行机型
+ device() {
+ return uni.getSystemInfoSync().platform;
+ },
+
+ // 获取前端真实主机
+ host() {
+ let host = location.origin;
+ let basePath = router.$route.options.base;
+ let mode = router.$route.options.mode;
+ host += basePath;
+ if (mode === 'hash') {
+ host += '#/';
+ }
+ return host;
+ },
+
+ // 处理wechat jssdk 签名网址(针对IOS微信浏览器做优化)
+ entry() {
+ let that = this;
+ var entryUrl = location.href;
+ if (this.device() === 'ios') {
+ if (typeof(location.entryUrl) !== 'undefined') {
+ entryUrl = location.entryUrl;
+ } else {
+ location.entryUrl = entryUrl;
+ }
+ }
+ return entryUrl;
+ },
+
+
+}
diff --git a/shopro/poster/QS-SharePoster/QRCodeAlg.js b/shopro/poster/QS-SharePoster/QRCodeAlg.js
new file mode 100644
index 0000000..e69a0e5
--- /dev/null
+++ b/shopro/poster/QS-SharePoster/QRCodeAlg.js
@@ -0,0 +1,1009 @@
+ /**
+ * 获取单个字符的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
diff --git a/shopro/poster/QS-SharePoster/QS-SharePoster.js b/shopro/poster/QS-SharePoster/QS-SharePoster.js
new file mode 100644
index 0000000..4324631
--- /dev/null
+++ b/shopro/poster/QS-SharePoster/QS-SharePoster.js
@@ -0,0 +1,1589 @@
+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 nbgScale = 1;
+// export default
+function getSharePoster(obj) {
+ let {
+ type,
+ formData,
+ background,
+ posterCanvasId,
+ backgroundImage,
+ reserve,
+ textArray,
+ drawArray,
+ qrCodeArray,
+ imagesArray,
+ setCanvasWH,
+ setCanvasToTempFilePath,
+ canvas2image,
+ setDraw,
+ bgScale,
+ Context,
+ _this,
+ delayTimeScale,
+ drawDelayTime,
+ draw
+ } = obj;
+ return new Promise(async (rs, rj) => {
+ try {
+ 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.log('准备设置图片');
+ imagesArray = await setImage(imagesArray);
+ }
+ if (textArray) {
+ if (typeof(textArray) == 'function')
+ textArray = textArray(params);
+ textArray = setText(Context, textArray);
+
+ }
+ if (qrCodeArray) {
+ if (typeof(qrCodeArray) == 'function')
+ qrCodeArray = qrCodeArray(params);
+ 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);
+ }
+ }
+ 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;
+ const addDrawArray = [];
+ 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;
+ let addDraw = false;
+ switch (drawArrayItem.type) {
+ case 'image':
+ newData = await setImage(drawArrayItem);
+ break;
+ case 'text':
+ newData = setText(Context, drawArrayItem, params.bgObj);
+ // if (_app.isArray(setTextResult)) {
+ // addDraw = true;
+ // addDrawArray.push({
+ // index: i,
+ // items: setTextResult
+ // });
+ // } else {
+ // newData = setTextResult;
+ // }
+ 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 (!addDraw && newData && _app.isObject(newData)) {
+ drawArray[i] = {
+ ...drawArrayItem,
+ ...newData
+ }
+ };
+ }
+
+ // if (addDrawArray.length) {
+ // for (let i = 0; i < addDrawArray.length; i++) {
+ // const item = addDrawArray[i];
+ // const index = drawArray.findIndex(ite => ite[idKey] == item.index);
+ // if (-1 != index) {
+ // item.items.forEach((ite, index) => {
+ // ite[idKey] = drawArray.length + index;
+ // ite.allInfoCallback = null;
+ // });
+ // drawArray.splice(index, 1, ...item.items)
+ // }
+ // }
+ // }
+ _app.log('AllInfoCallback之前', JSON.stringify(drawArray));
+
+ // 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]
+ };
+ const item_idKey = item[idKey];
+ _app.log('item_idKey', item_idKey);
+ const ind = drawArray.findIndex(it => it[idKey] == item_idKey);
+ _app.log('ind', ind);
+ if (-1 == ind) break;
+ if (_app.isFn(item.allInfoCallback)) {
+ let newData = item.allInfoCallback({
+ drawArray
+ });
+ _app.log('newData', JSON.stringify(newData));
+ if (_app.isPromise(newData)) newData = await newData;
+
+ if (drawArray[ind].type === 'text' && newData.size) {
+ const textLength = countTextLength(Context, {
+ text: newData.text || drawArray[ind].text,
+ size: newData.size
+ });
+ newData.textLength = textLength;
+ }
+ drawArray[ind] = {
+ ...item,
+ ...newData
+ };
+ }
+ _app.log('drawArray[ind]', JSON.stringify(drawArray[ind]));
+ if (drawArray[ind].type === 'text') {
+ const setLineFeedResult = setLineFeed(Context, drawArray[ind], params.bgObj);
+ if (_app.isArray(setLineFeedResult)) {
+ setLineFeedResult.forEach((ite, index) => {
+ ite[idKey] = drawArray.length + index;
+ ite.allInfoCallback = null;
+ })
+ drawArray.splice(ind, 1, ...setLineFeedResult);
+ } else {
+ drawArray.splice(ind, 1, setLineFeedResult);
+ }
+ }
+
+ }
+ _app.log('for循环结束');
+ _app.log('allInfocallback结束', JSON.stringify(drawArray));
+ // }
+ }
+ }
+ drawArray.sort((a, b) => {
+ const a_zIndex = !_app.isUndef(a.zIndex) && !_app.isNull(a
+ .zIndex) ? Number(a.zIndex) : Number.NEGATIVE_INFINITY;
+ const b_zIndex = !_app.isUndef(b.zIndex) && !_app.isNull(b
+ .zIndex) ? Number(b.zIndex) : Number.NEGATIVE_INFINITY;
+ return a_zIndex - b_zIndex;
+ });
+ _app.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,
+ canvas2image,
+ draw
+ });
+ rs({
+ bgObj,
+ poster,
+ type
+ });
+ } catch (e) {
+ //TODO handle the exception
+ _app.hideLoading();
+ rj(e);
+ }
+ });
+}
+
+function drawShareImage(obj) { //绘制海报方法
+ let {
+ Context,
+ type,
+ posterCanvasId,
+ reserve,
+ bgObj,
+ drawArray,
+ textArray,
+ qrCodeArray,
+ imagesArray,
+ setCanvasToTempFilePath,
+ setDraw,
+ bgScale,
+ _this,
+ delayTimeScale,
+ drawDelayTime,
+ canvas2image,
+ draw
+ } = obj;
+ const params = {
+ Context,
+ bgObj,
+ type,
+ bgScale
+ };
+ delayTimeScale = delayTimeScale !== undefined ? delayTimeScale : 15;
+ drawDelayTime = drawDelayTime !== undefined ? drawDelayTime : 100;
+ return new Promise(async (rs, rj) => {
+ try {
+ _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('背景没有背景颜色');
+ }
+ }
+
+ if (imagesArray && imagesArray.length > 0)
+ drawImage(Context, imagesArray);
+
+ if (setDraw && typeof(setDraw) == 'function') setDraw(params);
+
+ if (textArray && textArray.length > 0)
+ drawText(Context, textArray, bgObj);
+
+ if (qrCodeArray && qrCodeArray.length > 0) {
+ for (let i = 0; i < qrCodeArray.length; i++) {
+ drawQrCode(Context, qrCodeArray[i]);
+ }
+ }
+
+ 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;
+ }
+ }
+ }
+ setTimeout(() => {
+ _app.log('准备执行draw方法')
+ _app.log('Context:' + Context);
+ if (draw === false) {
+ _app.log('draw属性为false,请自行调用canvas实例的draw方法');
+ rs();
+ return;
+ }
+ const fn = function() {
+ let setObj = setCanvasToTempFilePath || {};
+ if (setObj && typeof(setObj) == 'function')
+ setObj = setCanvasToTempFilePath(bgObj, type);
+ let canvasToTempFilePathFn;
+ const dpr = uni.getSystemInfoSync().pixelRatio;
+ const data = {
+ // 注释的设置使用uni自己的默认值更为稳定
+ // x: 0,
+ // y: 0,
+ // width: Number(bgObj.width),
+ // height: Number(bgObj.height),
+ // destWidth: Number(bgObj.width) * dpr,
+ // destHeight: Number(bgObj.height) * dpr,
+ quality: .8,
+ fileType: 'jpg',
+ ...setObj,
+ canvasId: posterCanvasId,
+ };
+ if (canvas2image === false) {
+ return rs({
+ setCanvasToTempFilePath: data
+ });
+ }
+ _app.log('canvasToTempFilePath的data对象:' + JSON.stringify(data));
+ canvasToTempFilePathFn = function() {
+ const toTempFilePathObj = { //输出为图片
+ ...data,
+ success(res) {
+ rs({
+ ...res,
+ setCanvasToTempFilePath: data
+ });
+ },
+ fail(err) {
+ _app.hideLoading();
+ _app.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;
+ case 'qrcode':
+ if (item.text) {
+ delayTime += item.text.length * 2;
+ }
+ 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.arc(dx + r, dy + r, r, 1 * Math.PI, 1.5 * Math.PI);
+ Context.lineTo(dx + width - r, dy);
+ Context.arc(dx + width - r, dy + r, r, 1.5 * Math.PI, 0);
+ Context.lineTo(dx + width, dy + height - r);
+ Context.arc(dx + width - r, dy + height - r, r, 0, .5 * Math.PI);
+ Context.lineTo(dx + r, dy + height);
+ Context.arc(dx + r, dy + height - r, r, .5 * Math.PI, 1 * Math.PI);
+ Context.lineTo(dx, 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.arc(dx + r, dy + r, r, 1 * Math.PI, 1.5 * Math.PI);
+ Context.lineTo(dx + width - r, dy);
+ Context.arc(dx + width - r, dy + r, r, 1.5 * Math.PI, 0);
+ Context.lineTo(dx + width, dy + height - r);
+ Context.arc(dx + width - r, dy + height - r, r, 0, .5 * Math.PI);
+ Context.lineTo(dx + r, dy + height);
+ Context.arc(dx + r, dy + height - r, r, .5 * Math.PI, 1 * Math.PI);
+ Context.lineTo(dx, dy + r);
+ Context.closePath();
+ Context.setFillStyle(backgroundColor);
+ Context.fill();
+}
+
+// export
+function setText(Context, texts, bgObj) { // 设置文本数据
+ _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], bgObj);
+ }
+ }
+ } else {
+ _app.log('texts是对象');
+ texts = setTextFn(Context, texts, bgObj);
+ _app.log('返回texts:' + JSON.stringify(texts));
+ return texts;
+ }
+}
+
+function setTextFn(Context, textItem, bgObj) {
+ _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));
+ let 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);
+ }
+
+ if (infoCallBackObj.size)
+ textLength = countTextLength(Context, {
+ text: textItem.text,
+ size: textItem.size
+ });
+ textItem = {
+ ...textItem,
+ ...infoCallBackObj,
+ textLength,
+ }
+ _app.log('字符串信息-infoCallBack后:' + JSON.stringify(textItem));
+ }
+ return textItem;
+}
+
+function setLineFeed(Context, textItem, bgObj) {
+ if (textItem.text && textItem.lineFeed) {
+ _app.log('设置换行')
+ 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;
+ }
+ _app.lineFeedTags.forEach(i => {
+ textItem.text = textItem.text.split(i).join(_app.tagetLineFeedTag);
+ })
+ const chr = (textItem.text).split("");
+ let temp = "";
+ const row = [];
+ //循环出几行文字组成数组
+ for (let a = 0, len = chr.length; a < len; a++) {
+ if (chr[a] === _app.tagetLineFeedTag) {
+ row.push(temp);
+ temp = chr[++a];
+ continue;
+ }
+ 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];
+ if (a == chr.length - 1) row.push(chr[a]);
+ }
+ }
+ _app.log('循环出的文本数组:' + JSON.stringify(row));
+ //只显示几行 变量间距lineHeight 变量行数lineNum
+ let allNum = (lineNum >= 0 && lineNum < row.length) ? lineNum : row.length;
+ const newArr = [];
+ for (let i = 0; i < allNum; i++) {
+ let str = row[i];
+ if (i == (allNum - 1) && allNum < row.length && row.length > 1) {
+ if (countTextLength(Context, {
+ text: str,
+ size: textItem.size
+ }) > (maxWidth - textItem.size) * .9) {
+ 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);
+ }
+ _app.log('newArr: -----', JSON.stringify(newArr))
+ const result = newArr.length > 1 ? newArr : newArr[0];
+ return result
+ }
+ 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 = {};
+ }
+ _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.48291015625
+ } else {
+ l = 1
+ }
+ return l;
+}
+
+// export
+function setImage(images) { // 设置图片数据
+ _app.log('进入设置图片数据方法');
+ return new Promise(async (resolve, reject) => {
+ 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) {
+ _app.hideLoading()
+ //TODO handle the exception
+ reject(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) => {
+ try {
+ if (image.url) {
+ image.url = (await base64ToPathFn(image.url));
+ let imgUrl = image.url;
+ const oldImgUrl = imgUrl;
+ imgUrl = await _app.downloadFile_PromiseFc(imgUrl);
+ image.url = imgUrl;
+ const hasinfoCallBack = image.infoCallBack && typeof(image.infoCallBack) === 'function';
+ let imageInfo = {};
+ imageInfo = await _app.getImageInfo_PromiseFc(oldImgUrl);
+ 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);
+ } catch (e) {
+ _app.hideLoading();
+ reject(e)
+ //TODO handle the exception
+ }
+
+ })
+}
+
+// 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 = textArray;
+ // 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];
+ // if (a == chr.length - 1) row.push(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);
+ }
+ }
+}
+
+const drawImageModes = {
+ scaleToFill(Context, img) {
+ _app.log('准备绘制mode为scaleToFill的图片')
+ Context.drawImage(img.url, Number(img.dx || 0), Number(img.dy || 0),
+ Number(img.dWidth) || false, Number(img.dHeight) || false);
+ _app.log('mode为scaleToFill的图片绘制完毕')
+ },
+ aspectFit(Context, img) {
+ _app.log('准备绘制mode为aspectFit的图片')
+ const {
+ imageInfo,
+ dWidth,
+ dHeight
+ } = img;
+ const {
+ height,
+ width
+ } = imageInfo;
+ let drawWidth = dWidth;
+ let drawHeight = height / width * drawWidth;
+ if (drawHeight < dHeight) {
+ const diffHeight = (Number(dHeight) - Number(drawHeight)) / Number(dHeight) * height;
+ img.dy = Number(img.dy) + diffHeight / 2;
+ } else {
+ drawHeight = dHeight;
+ drawWidth = width / height * drawHeight;
+ const diffWidth = (Number(dWidth) - Number(drawWidth)) / Number(dWidth) * width;
+ img.dx = Number(img.dx) + diffWidth / 2;
+ }
+ Context.drawImage(img.url, 0, 0, width, height, img.dx, img.dy, drawWidth, drawHeight);
+ _app.log('mode为aspectFit的图片绘制完毕')
+ },
+ aspectFill(Context, img) {
+ const dpr = uni.getSystemInfoSync().pixelRatio;
+ _app.log('准备绘制mode为aspectFill的图片')
+ const {
+ imageInfo,
+ dWidth,
+ dHeight
+ } = img;
+ const {
+ height,
+ width
+ } = imageInfo;
+ let sx = 0,
+ sy = 0,
+ sWidth = (width),
+ sHeight = (height);
+ let drawWidth = dWidth;
+ let drawHeight = height / width * drawWidth;
+ if (drawHeight < dHeight) {
+ _app.log('绘制高度 小于 预定高度')
+ drawHeight = dHeight;
+ drawWidth = width / height * drawHeight;
+ const diffWidth = ((Number(drawWidth) - Number(dWidth)) / Number(drawWidth)) * width;
+ sx = diffWidth / 2;
+ sWidth = width - diffWidth;
+ } else {
+ const diffHeight = ((Number(drawHeight) - Number(dHeight)) / Number(drawHeight)) * height;
+ sy = diffHeight / 2;
+ sHeight = (height - diffHeight);
+ }
+ _app.log(
+ `aspectFill 最终绘制: sx: ${sx}, sy: ${sy}, sWidth: ${sWidth}, sHeight: ${sHeight}, dx: ${img.dx}, dy: ${img.dy}, dWidth: ${dWidth}, dHeight: ${dHeight}`
+ )
+ Context.drawImage(img.url, sx, sy, sWidth, sHeight, img.dx, img.dy, dWidth, dHeight);
+ _app.log('mode为aspectFill的图片绘制完毕')
+ }
+}
+
+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.dHeight === undefined) img.dHeight = img.imageInfo.height;
+ if (img.dWidth === undefined) img.dWidth = img.imageInfo.width;
+ const fn = drawImageModes[img.mode];
+ if (fn) {
+ fn(Context, img);
+ } else {
+ 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.arc(dx + r, dy + r, r, 1 * Math.PI, 1.5 * Math.PI);
+ Context.lineTo(dx + dWidth - r, dy);
+ Context.arc(dx + dWidth - r, dy + r, r, 1.5 * Math.PI, 0);
+ Context.lineTo(dx + dWidth, dy + dHeight - r);
+ Context.arc(dx + dWidth - r, dy + dHeight - r, r, 0, .5 * Math.PI);
+ Context.lineTo(dx + r, dy + dHeight);
+ Context.arc(dx + r, dy + dHeight - r, r, .5 * Math.PI, 1 * Math.PI);
+ Context.lineTo(dx, dy + r);
+
+ // 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('进入绘制二维码方法')
+ 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('进入绘制二维码方法完毕')
+}
+
+
+function getShreUserPosterBackground(objs) { //检查背景图是否存在于本地, 若存在直接返回, 否则调用getShreUserPosterBackgroundFc方法
+ let {
+ backgroundImage,
+ type
+ } = objs;
+ return new Promise(async (resolve, reject) => {
+ try {
+ const savedFilePath = await getShreUserPosterBackgroundFc(objs)
+ 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.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(image);
+ _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.log('返回背景图信息对象');
+ resolve({
+ ...returnObj
+ });
+ } else {
+ reject('not find savedFilePath');
+ }
+ } catch (e) {
+
+ //TODO handle the exception
+ _app.hideLoading();
+ reject(e);
+ }
+ });
+}
+
+
+module.exports = {
+ getShreUserPosterBackground,
+ getSharePoster,
+ setText,
+ setImage,
+ drawText,
+ drawImage,
+ drawQrCode,
+ drawFillRect,
+ drawStrokeRect,
+ drawRoundStrokeRect,
+ drawRoundFillRect
+}
diff --git a/shopro/poster/QS-SharePoster/app.js b/shopro/poster/QS-SharePoster/app.js
new file mode 100644
index 0000000..1dda932
--- /dev/null
+++ b/shopro/poster/QS-SharePoster/app.js
@@ -0,0 +1,566 @@
+let log = console.log; // 如果在项目的APP.vue文件中的onlaunch中设置 console.log = ()=> {} 则在此也不会有打印信息
+log = ()=>{}; // 打开注释则该插件不会打印任何信息
+let _app = {
+ lineFeedTags: ['
', '
', '\r\n', '\n\t', '\r', '\n'], //换行符识别列表
+ tagetLineFeedTag: `❤`, //将lineFeedTags列表中的字符串替换为该字符, 代表换行符, 只要找一个特殊符号就行,必须是单字符单字符单字符!
+ //交互控制
+ log(t) {
+ // log(t);
+ }, // 打印控制,
+ showLoading(msg, ifmask) {
+ uni.showLoading({
+ title: msg,
+ mask: ifmask || false
+ })
+ },
+ hideLoading() {
+ uni.hideLoading();
+ },
+ showToast(msg, icon) {
+ uni.showToast({
+ title: msg,
+ icon: icon || 'none'
+ })
+ },
+ getPosterUrl(objs) { // 后端获取背景图的url路径方法
+ let {
+ backgroundImage,
+ type,
+ formData
+ } = objs;
+ return new Promise((rs, rj) => {
+ let image;
+ if (backgroundImage) {
+ image = backgroundImage;
+ } else {
+ switch (type) { //根据type获取背景图, 一般要改成request获取
+ case 1:
+ image = '';
+ break;
+ default:
+ image = '';
+ break;
+ }
+ }
+ if (image) {
+ rs(image); // resolve图片的路径
+ } else {
+ rj('背景图片路径不存在');
+ }
+ })
+ },
+
+
+
+
+
+
+ //下面一般不用动他
+ shareTypeListSheetArray: {
+ array: [0, 1, 2, 3, 4, 5]
+ }, // 分享类型 0-图文链接 1-纯文字 2-纯图片 3-音乐 4-视频 5-小程序
+ isArray(arg) {
+ return Object.prototype.toString.call(arg) === '[object Array]';
+ },
+ isObject(arg) {
+ return Object.prototype.toString.call(arg) === '[object Object]';
+ },
+ isPromise(obj) {
+ return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
+ },
+ isNull(arg) {
+ return arg === null;
+ },
+ isUndefined(arg) {
+ return arg === undefined;
+ },
+ isUndef(arg) {
+ return arg === undefined;
+ },
+ isNotNull_string(arg) {
+ return arg !== null && arg !== undefined && arg !== '';
+ },
+ isFn(fn) {
+ return fn && typeof fn === 'function';
+ },
+ getStorage(key, scb, fcb) {
+ uni.getStorage({
+ key,
+ success: function(res) {
+ if (res.data && res.data != "") {
+ if (scb) scb(res.data);
+ } else {
+ if (fcb) fcb();
+ }
+ },
+ fail: function() {
+ if (fcb) fcb();
+ }
+ })
+ },
+ setStorage(key, data) {
+ log('设置缓存')
+ log('key:' + key)
+ log('data:' + JSON.stringify(data));
+ uni.setStorage({
+ key,
+ data
+ })
+ },
+ setStorageSync(key, data) {
+ uni.setStorageSync(key, data);
+ },
+ getStorageSync(key) {
+ return uni.getStorageSync(key);
+ },
+ clearStorageSync() {
+ uni.clearStorageSync();
+ },
+ removeStorageSync(key) {
+ uni.removeStorageSync(key);
+ },
+ getImageInfo(url, cb, fcb) {
+ url = checkMPUrl(url);
+ uni.getImageInfo({
+ src: url,
+ success(res) {
+ if (cb && typeof(cb) == 'function') cb(res);
+ },
+ fail(err) {
+ if (fcb && typeof(fcb) == 'function') fcb(err);
+ }
+ })
+ },
+ downloadFile(url, cb) {
+ url = checkMPUrl(url);
+ uni.downloadFile({
+ url,
+ success(res) {
+ if (cb && typeof(cb) == 'function') cb(res);
+ }
+ })
+ },
+ downloadFile_PromiseFc(url) {
+ return new Promise((rs, rj) => {
+ if (url.substring(0, 4) !== 'http') {
+ rs(url);
+ } else {
+ url = checkMPUrl(url);
+ log('url:' + url);
+ uni.downloadFile({
+ url,
+ success(res) {
+ if (res && res.tempFilePath)
+ rs(res.tempFilePath);
+ else
+ rj('not find tempFilePath');
+ },
+ fail(err) {
+ rj(err);
+ }
+ })
+ }
+ });
+ },
+ saveFile(url) {
+ uni.saveFile({
+ tempFilePath: url,
+ success(res) {
+ log('保存成功:' + JSON.stringify(res))
+ }
+ })
+ },
+ downLoadAndSaveFile_PromiseFc(url) {
+ return new Promise((rs, rj) => {
+ log('准备下载并保存图片:' + url);
+ if (url.substring(0, 4) === 'http') {
+ url = checkMPUrl(url);
+ uni.downloadFile({
+ url,
+ success(d_res) {
+ log('下载背景图成功:' + JSON.stringify(d_res));
+ if (d_res && d_res.tempFilePath) {
+
+ // #ifdef H5
+ rs(d_res.tempFilePath);
+ // #endif
+
+ // #ifndef H5
+ uni.saveFile({
+ tempFilePath: d_res.tempFilePath,
+ success(s_res) {
+ log('保存背景图成功:' + JSON.stringify(s_res));
+ if (s_res && s_res.savedFilePath)
+ rs(s_res.savedFilePath);
+ else
+ rs(d_res.tempFilePath);
+ },
+ fail(err) {
+ rs(d_res.tempFilePath);
+ }
+ })
+ // #endif
+
+ } else {
+ rj('not find tempFilePath');
+ }
+ },
+ fail(err) {
+ rj(err);
+ }
+ })
+ } else {
+ rs(url);
+ }
+ })
+ },
+ checkFile_PromiseFc(url) {
+ return new Promise((rs, rj) => {
+ uni.getSavedFileList({
+ success(res) {
+ let d = res.fileList;
+ let index = d.findIndex(item => {
+ return item.filePath === url;
+ })
+ rs(index);
+ },
+ fail(err) {
+ rj(err);
+ }
+ })
+ });
+ },
+ removeSavedFile(path) {
+ uni.getSavedFileList({
+ success(res) {
+ let d = res.fileList;
+ let index = d.findIndex(item => {
+ return item.filePath === path;
+ });
+ if (index >= 0)
+ uni.removeSavedFile({
+ filePath: path
+ })
+ }
+ })
+ },
+ fileNameInPath(path) {
+ let s = path.split("/");
+ return s[s.length - 1];
+ },
+ getImageInfo_PromiseFc(imgPath) {
+ return new Promise((rs, rj) => {
+ log('准备获取图片信息:' + imgPath);
+ imgPath = checkMPUrl(imgPath);
+ uni.getImageInfo({
+ src: imgPath,
+ success: res => {
+ log('获取图片信息成功:' + JSON.stringify(res));
+ rs(res);
+ },
+ fail: err => {
+ log('获取图片信息失败:' + JSON.stringify(err));
+ rj(err)
+ }
+ })
+ });
+ },
+ previewImage(urls) {
+ if (typeof(urls) == 'string')
+ urls = [urls];
+ uni.previewImage({
+ urls,
+ })
+ },
+ actionSheet(obj, cb) {
+ let sheetArray = [];
+ for (let i = 0; i < obj.array.length; i++) {
+ switch (obj.array[i]) {
+ case 'sinaweibo':
+ sheetArray[i] = '新浪微博';
+ break;
+ case 'qq':
+ sheetArray[i] = 'QQ';
+ break;
+ case 'weixin':
+ sheetArray[i] = '微信';
+ break;
+ case 'WXSceneSession':
+ sheetArray[i] = '微信好友';
+ break;
+ case 'WXSenceTimeline':
+ sheetArray[i] = '微信朋友圈';
+ break;
+ case 'WXSceneFavorite':
+ sheetArray[i] = '微信收藏';
+ break;
+ case 0:
+ sheetArray[i] = '图文链接';
+ break;
+ case 1:
+ sheetArray[i] = '纯文字';
+ break;
+ case 2:
+ sheetArray[i] = '纯图片';
+ break;
+ case 3:
+ sheetArray[i] = '音乐';
+ break;
+ case 4:
+ sheetArray[i] = '视频';
+ break;
+ case 5:
+ sheetArray[i] = '小程序';
+ break;
+ default:
+ break;
+ }
+ }
+ this.showActionSheet(sheetArray, cb);
+ },
+ showActionSheet(sheetArray, cb) {
+ uni.showActionSheet({
+ itemList: sheetArray,
+ success: (e) => {
+ if (cb && typeof(cb) == 'function') cb(e.tapIndex);
+ }
+ })
+ },
+ getProvider(type, cb, sheet) {
+ let _this = this;
+ uni.getProvider({
+ service: type,
+ success: function(res) {
+ if (sheet) {
+ let obj = {};
+ obj.array = res.provider;
+ _this.actionSheet(obj, function(index) {
+ if (cb && typeof(cb) == "function") cb(res.provider[index]);
+ });
+ } else {
+ if (type == 'payment') {
+ let providers = res.provider;
+ let payTypeArray = [];
+ for (let i = 0; i < providers.length; i++) {
+ if (providers[i] == 'wxpay') {
+ payTypeArray[i] = {
+ name: '微信支付',
+ value: providers[i],
+ img: '/static/image/wei.png'
+ };
+ } else if (providers[i] == 'alipay') {
+ payTypeArray[i] = {
+ name: "支付宝支付",
+ value: providers[i],
+ img: '/static/image/ali.png'
+ };
+ }
+ }
+ if (cb && typeof(cb) == "function") cb(payTypeArray);
+ } else {
+ if (cb && typeof(cb) == "function") cb(res);
+ }
+ }
+ },
+ })
+ },
+ // #ifdef APP-PLUS
+ getShare(providerName, WXScene, shareType, title, summary, href, imageUrl, miniProgramObj, mediaUrl, scb,
+ fcb) { //miniProgram: {path: '', type: 0, webUrl: ''}
+ let _this = this;
+ if (typeof(shareType) == 'number' && !isNaN(shareType) && shareType >= 0) {
+ _this.readyShare(providerName, WXScene, shareType, title, summary, href, imageUrl, miniProgramObj,
+ mediaUrl, scb,
+ fcb);
+ } else {
+ _this.actionSheet(_this.shareTypeListSheetArray, function(index) {
+ _this.readyShare(providerName, WXScene, _this.shareTypeListSheetArray.array[index], title,
+ summary, href,
+ imageUrl, miniProgramObj, mediaUrl, scb, fcb);
+ });
+ }
+ },
+ readyShare(providerName, WXScene, shareType, title, summary, href, imageUrl, miniProgramObj, mediaUrl, scb,
+ fcb) {
+ let _this = this;
+ let shareObjData = {};
+ switch (shareType) {
+ case 0:
+ shareObjData = {
+ href: href,
+ summary: summary,
+ imageUrl: imageUrl
+ };
+ break;
+ case 1:
+ shareObjData = {
+ summary: summary,
+ href: href
+ };
+ break;
+ case 2:
+ shareObjData = {
+ imageUrl: imageUrl
+ };
+ break;
+ case 3:
+ if (mediaUrl) {
+ _this.showToast('暂不支持此分享类型');
+ return;
+ };
+ shareObjData = {
+ mediaUrl: mediaUrl
+ };
+ break;
+ case 4:
+ if (mediaUrl) {
+ _this.showToast('暂不支持此分享类型');
+ return;
+ };
+ shareObjData = {
+ mediaUrl: mediaUrl
+ };
+ break;
+ case 5:
+ shareObjData = {
+ miniProgram: {
+ ...miniProgramObj,
+ id: miniProgramId,
+ type: miniProgramShareType
+ },
+ imageUrl: imageUrl
+ };
+ providerName = 'weixin';
+ break;
+ default:
+ _this.showToast('分享参数-shareType错误');
+ return;
+ break;
+ }
+ shareObjData.title = title;
+ _this.share(providerName, WXScene, shareType, shareObjData, function(res) {
+ if (scb && typeof(scb) == 'function') scb(res);
+ }, function(err) {
+ if (fcb && typeof(fcb) == 'function') fcb(err);
+ });
+ },
+ share(providerName, WXScene, shareType, data, scb, fcb) {
+ let _this = this;
+ let shareObj = {
+ provider: '',
+ success: Function,
+ fail: Function
+ };
+ if (providerName && providerName != '') {
+ shareObj.provider = providerName;
+ if (providerName == 'weixin') {
+ _this.readyShareWXScene(WXScene, function(Scene) {
+ shareObj.scene = Scene;
+ _this.doingShare(shareObj, shareType, data, scb, fcb);
+ });
+ } else {
+ _this.doingShare(shareObj, shareType, data, scb, fcb);
+ }
+ } else {
+ _this.getProvider('share', function(name) {
+ shareObj.provider = name;
+ if (name == 'weixin') {
+ _this.readyShareWXScene(WXScene, function(Scene) {
+ shareObj.scene = Scene;
+ _this.doingShare(shareObj, shareType, data, scb, fcb);
+ });
+ } else {
+ _this.doingShare(shareObj, shareType, data, scb, fcb);
+ }
+ }, true);
+ }
+ },
+ readyShareWXScene(WXScene, cb) {
+ let _this = this;
+ let WXScenetypelist = {
+ array: ['WXSceneSession', 'WXSenceTimeline', 'WXSceneFavorite']
+ };
+ if (WXScene && WXScene != "") {
+ if (cb && typeof(cb) == 'function') cb(WXScene);
+ } else {
+ _this.actionSheet(WXScenetypelist, function(index) {
+ if (cb && typeof(cb) == 'function') cb(WXScenetypelist.array[index]);
+ });
+ }
+ },
+ doingShare(shareObj, shareType, data, scb, fcb) {
+ shareObj.type = shareType;
+ if (data && data.title) shareObj.title = data.title;
+ switch (shareType) {
+ case 0: //图文链接
+ shareObj.href = data.href;
+ shareObj.summary = data.summary;
+ shareObj.imageUrl = data.imageUrl;
+ break;
+ case 1: //纯文字
+ shareObj.summary = data.summary;
+ shareObj.href = data.href;
+ break;
+ case 2: //纯图片
+ shareObj.imageUrl = data.imageUrl;
+ break;
+ case 3: //音乐
+ if (!data.mediaUrl) {
+ _this.showToast('暂不支持此分享类型');
+ return;
+ };
+ shareObj.mediaUrl = data.mediaUrl;
+ break;
+ case 4: //视频
+ if (!data.mediaUrl) {
+ _this.showToast('暂不支持此分享类型');
+ return;
+ };
+ shareObj.mediaUrl = data.mediaUrl;
+ break;
+ case 5: //小程序
+ if (miniProgramId == '') {
+ uni.showToast('未设置小程序ID, 请使用其他方式分享');
+ return;
+ }
+ let mp = {
+ id: miniProgramId
+ };
+ mp.path = data.miniProgram.path;
+ mp.type = data.miniProgram.type;
+ if (data.miniProgram.webUrl) mp.webUrl = data.miniProgram.webUrl;
+ shareObj.miniProgram = mp;
+ shareObj.imageUrl = data.imageUrl;
+ break;
+ default:
+ appJS.showToast('分享参数-shareType错误');
+ break;
+ }
+ shareObj.success = function(res) {
+ if (scb && typeof(scb) == 'function') scb(res);
+ }
+ shareObj.fail = function(err) {
+ if (fcb && typeof(fcb) == 'function') fcb(err);
+ }
+ log(JSON.stringify(shareObj));
+ uni.share(shareObj);
+ },
+ // #endif
+}
+
+function checkMPUrl(url) {
+ // #ifdef MP
+ if (
+ url.substring(0, 4) === 'http' &&
+ url.substring(0, 5) !== 'https' &&
+ url.substring(0, 12) !== 'http://store' &&
+ url.substring(0, 10) !== 'http://tmp' &&
+ url.substring(0, 10) !== 'http://usr'
+ ) {
+ url = 'https' + url.substring(4, url.length);
+ }
+ // #endif
+ return url;
+}
+
+module.exports = _app;
diff --git a/shopro/poster/QS-SharePoster/image-tools.js b/shopro/poster/QS-SharePoster/image-tools.js
new file mode 100644
index 0000000..b5f2a3c
--- /dev/null
+++ b/shopro/poster/QS-SharePoster/image-tools.js
@@ -0,0 +1,147 @@
+function getLocalFilePath(path) {
+ if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
+ return path
+ }
+ if (path.indexOf('file://') === 0) {
+ return path
+ }
+ if (path.indexOf('/storage/emulated/0/') === 0) {
+ return path
+ }
+ if (path.indexOf('/') === 0) {
+ var localFilePath = plus.io.convertAbsoluteFileSystem(path)
+ if (localFilePath !== path) {
+ return localFilePath
+ } else {
+ path = path.substr(1)
+ }
+ }
+ return '_www/' + path
+}
+
+export function pathToBase64(path) {
+ return new Promise(function(resolve, reject) {
+ if (typeof window === 'object' && 'document' in window) {
+ if (typeof FileReader === 'function') {
+ var xhr = new XMLHttpRequest()
+ xhr.open('GET', path, true)
+ xhr.responseType = 'blob'
+ xhr.onload = function() {
+ if (this.status === 200) {
+ let fileReader = new FileReader()
+ fileReader.onload = function(e) {
+ resolve(e.target.result)
+ }
+ fileReader.onerror = reject
+ fileReader.readAsDataURL(this.response)
+ }
+ }
+ xhr.onerror = reject
+ xhr.send()
+ return
+ }
+ var canvas = document.createElement('canvas')
+ var c2x = canvas.getContext('2d')
+ var img = new Image
+ img.onload = function() {
+ canvas.width = img.width
+ canvas.height = img.height
+ c2x.drawImage(img, 0, 0)
+ resolve(canvas.toDataURL())
+ canvas.height = canvas.width = 0
+ }
+ img.onerror = reject
+ img.src = path
+ return
+ }
+ if (typeof plus === 'object') {
+ plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
+ entry.file(function(file) {
+ var fileReader = new plus.io.FileReader()
+ fileReader.onload = function(data) {
+ resolve(data.target.result)
+ }
+ fileReader.onerror = function(error) {
+ reject(error)
+ }
+ fileReader.readAsDataURL(file)
+ }, function(error) {
+ reject(error)
+ })
+ }, function(error) {
+ reject(error)
+ })
+ return
+ }
+ if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
+ wx.getFileSystemManager().readFile({
+ filePath: path,
+ encoding: 'base64',
+ success: function(res) {
+ resolve('data:image/png;base64,' + res.data)
+ },
+ fail: function(error) {
+ reject(error)
+ }
+ })
+ return
+ }
+ reject(new Error('not support'))
+ })
+}
+
+export function base64ToPath(base64) {
+ return new Promise(function(resolve, reject) {
+ if (typeof window === 'object' && 'document' in window) {
+ base64 = base64.split(',')
+ var type = base64[0].match(/:(.*?);/)[1]
+ var str = atob(base64[1])
+ var n = str.length
+ var array = new Uint8Array(n)
+ while (n--) {
+ array[n] = str.charCodeAt(n)
+ }
+ return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
+ }
+ var extName = base64.match(/data\:\S+\/(\S+);/)
+ if (extName) {
+ extName = extName[1]
+ } else {
+ reject(new Error('base64 error'))
+ }
+ var fileName = Date.now() + '.' + extName
+ if (typeof plus === 'object') {
+ var bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
+ bitmap.loadBase64Data(base64, function() {
+ var filePath = '_doc/uniapp_temp/' + fileName
+ bitmap.save(filePath, {}, function() {
+ bitmap.clear()
+ resolve(filePath)
+ }, function(error) {
+ bitmap.clear()
+ reject(error)
+ })
+ }, function(error) {
+ bitmap.clear()
+ reject(error)
+ })
+ return
+ }
+ if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
+ var filePath = wx.env.USER_DATA_PATH + '/' + fileName
+ wx.getFileSystemManager().writeFile({
+ filePath: filePath,
+ data: base64.replace(/^data:\S+\/\S+;base64,/, ''),
+ encoding: 'base64',
+ success: function() {
+ resolve(filePath)
+ },
+ fail: function(error) {
+ reject(error)
+ }
+ })
+ return
+ }
+ reject(new Error('not support'))
+ })
+}
\ No newline at end of file
diff --git a/shopro/poster/tools.js b/shopro/poster/tools.js
new file mode 100644
index 0000000..d3c3193
--- /dev/null
+++ b/shopro/poster/tools.js
@@ -0,0 +1,193 @@
+export default {
+ async checkImgHttp(imgPath, type) {
+ let res = await this.getImageInfo_PromiseFc(imgPath)
+ let newPath = '';
+ if (!res) {
+ uni.hideLoading()
+ switch (type) {
+ case 'avatar':
+ console.log('%cerr:海报头像图片错误: ' + imgPath, 'color:green;background:yellow');
+ break;
+ case 'bgImage':
+ console.log('%cerr:海报背景图片错误: ' + imgPath, 'color:green;background:yellow');
+ break;
+ case 'wxCode':
+ console.log('%cerr:海报微信二维码图片错误: ' + imgPath, 'color:green;background:yellow');
+ break;
+ case 'goodsImage':
+ console.log('%cerr:海报商品图片错误: ' + imgPath, 'color:green;background:yellow');
+ break;
+ default:
+ break;
+ }
+ } else {
+ let pathArr = imgPath.split('://');
+ // #ifdef H5
+ let ishttps = 'https:' == window.location.protocol ? true : false;
+ ishttps ? (pathArr[0] = 'https') : (pathArr[0] = 'http');
+ // #endif
+ // #ifdef MP-WEIXIN
+ pathArr[0] = 'https'
+ // #endif
+ newPath = pathArr.join('://');
+ }
+
+ return newPath;
+ },
+ // 检测图片是否可用
+ getImageInfo_PromiseFc(imgPath) {
+ return new Promise((rs, rj) => {
+ imgPath = this.checkMPUrl(imgPath);
+ uni.getImageInfo({
+ src: imgPath,
+ success: res => {
+ rs(1);
+ },
+ fail: err => {
+ console.log(err)
+ rs(0);
+ }
+ })
+ });
+ },
+ // 微信头像
+ checkMPUrl(url) {
+ // #ifdef MP
+ if (
+ url.substring(0, 4) === 'http' &&
+ url.substring(0, 5) !== 'https' &&
+ url.substring(0, 12) !== 'http://store' &&
+ url.substring(0, 10) !== 'http://tmp' &&
+ url.substring(0, 10) !== 'http://usr'
+ ) {
+ url = 'https' + url.substring(4, url.length);
+ }
+ // #endif
+ return url;
+ },
+
+
+
+
+ /**
+ * 相对比例
+ * @param {Object} bgObj - 背景图片数据对象
+ * @param {Number} num - 需要计算的绘制模块数值
+ */
+ getScale(bgObj, num = 0) {
+ return Number(bgObj.width * (num / bgObj.width).toFixed(2))
+ },
+
+
+
+ /**
+ * 绘制序列
+ * @param {Object} bgObj - 背景图片数据对象
+ * @param {Array} drawArr - 绘制元素数组对象
+ */
+ initDrawArray(bgObj, drawArr) {
+ const that = this;
+ let arr = []
+ drawArr.forEach(item => {
+ switch (item.type) {
+ case 'text':
+ arr.push({
+ type: 'text',
+ text: item.text, //文本
+ size: that.getScale(bgObj, item.size) || 50, //大小
+ color: item.color || 'black', //颜色
+ alpha: item.alpha || 1, //透明度
+ textAlign: item.textAlign || 'left', //文字x对齐方式: 'left'、'middle'、'right'
+ textBaseline: item.textBaseline ||
+ 'middle', //文字y对齐方式: 'top'、'bottom'、'middle'、'normal'
+ dx: that.getScale(bgObj, item.dx) || 0, //文字x轴位置
+ dy: that.getScale(bgObj, item.dy + item.size) || 0, //文字y轴位置
+ [item.lineFeed ? 'lineFeed' : '']: { //设置换行
+ maxWidth: item.lineFeed?.maxWidth && that.getScale(bgObj, item.lineFeed
+ .maxWidth) || bgObj
+ .width, //最大宽度
+ lineHeight: item.lineFeed?.lineHeight && that.getScale(bgObj, item
+ .lineFeed.lineHeight) || 50, //行高
+ lineNum: item.lineFeed?.lineNum || -1, // 最多行数,小于0为无限
+ dx: item.lineFeed?.dx || -1, //非第一行文字位置,小于0为默认位置
+ },
+ infoCallBack: (textLength) => { //回调函数,返回文本信息
+ if (item.isBgCenter) {
+ return {
+ dx: (bgObj.width - textLength) / 2,
+ }
+ }
+ return {}
+ },
+ [item.lineThrough ? 'lineThrough' : '']: { // 设置删除线,默认为字体样式
+ width: item.lineThrough?.width || item.size / 10,
+ style: item.lineThrough?.style || item.color,
+ alpha: item.lineThrough?.alpha || 1,
+ cap: item.lineThrough?.cap || 'butt',
+ },
+ fontStyle: item.fontStyle || 'normal', // 设置字体,跟随系统默认
+ fontVariant: item.fontVariant || 'normal',
+ fontWeight: item.fontWeight || 'normal',
+ fontFamily: item.fontFamily || 'sans-serif',
+ })
+ break;
+ case 'qrcode':
+ arr.push({
+ type: 'qrcode',
+ text: String(item.text || '') || '', // 生成内容
+ size: Number(that.getScale(bgObj, item.size) || 0) || 200, // 二维码大小
+ background: String(item.background || '') || '#ffffff', // 背景色
+ foreground: String(item.foreground || '') || '#000000', // 前景色
+ correctLevel: Number(item.correctLevel || 0) || 3, // 容错级别
+ image: String(item.image || '') || '', // 二维码图标
+ imageSize: Number(that.getScale(bgObj, item.imageSize) || 0) || 40, // 二维码图标大小
+ dx: item.isBgCenter ? (bgObj.width - item.size) / 2 : Number(that.getScale(
+ bgObj, item.dx) || 0) || 0,
+ dy: Number(that.getScale(bgObj, item.dy) || 0) || 0, // y轴距离
+
+ })
+ break;
+ case 'image':
+ arr.push({
+ type: 'image',
+ url: this.checkImgHttp(item.url, item.name), // 网络图片路径
+ dWidth: Number(that.getScale(bgObj, item.dWidth) || 0) || 100, //绘制图像的宽度,允许缩放
+ dHeight: Number(that.getScale(bgObj, item.dHeight) || 0) || 100, //绘制图像的高度,允许缩放
+ sWidth: Number(that.getScale(bgObj, item.sWidth) || 0) || 100, //绘制图像的宽度,允许缩放
+ sHeight: Number(that.getScale(bgObj, item.sHeight) || 0) || 100, //绘制图像的高度,允许缩放
+ dx: Number(that.getScale(bgObj, item.dx) || 0) || 0, // x轴距离
+ dy: Number(that.getScale(bgObj, item.dy) || 0) || 0, // y轴距离
+ sx: Number(that.getScale(bgObj, item.sx) || 0) || 0,
+ sy: Number(that.getScale(bgObj, item.sy) || 0) || 0,
+ [item.circleSet ? 'circleSet' : '']: { //圆形设置
+ r: Number(item.circleSet?.r && that.getScale(bgObj, item.circleSet
+ .r) || 0),
+ x: Number(item.circleSet?.x && that.getScale(bgObj, item.circleSet
+ .x) || 0),
+ y: Number(item.circleSet?.y && that.getScale(bgObj, item.circleSet
+ .y) || 0),
+ },
+ [item.roundRectSet ? 'roundRectSet' : '']: { //圆角设置
+ r: Number(item.roundRectSet?.r && that.getScale(bgObj, item
+ .roundRectSet.r) || 0),
+ },
+ infoCallBack: (imgInfo) => { //回调函数,返回图片信息
+ if (item.isBgCenter) {
+ return {
+ dx: (bgObj.width - item.dWidth) / 2,
+ }
+ }
+ },
+ })
+ break;
+ default:
+ _app.log('暂无次类型');
+ break;
+ }
+ })
+ return arr
+ }
+
+
+
+}
diff --git a/shopro/request/apis.js b/shopro/request/apis.js
new file mode 100644
index 0000000..952e016
--- /dev/null
+++ b/shopro/request/apis.js
@@ -0,0 +1,779 @@
+/**
+ * 接口列表文件
+ */
+export default {
+
+ /** 公共 ↓ **/
+ common: {
+ init: {
+ url: "index/init",
+ auth: false,
+ method: "GET",
+ // desc: '初始化数据'
+ },
+ chat: {
+ url: "chat.index/init",
+ auth: false,
+ method: "GET",
+ // desc: '初始化聊天配置',
+ },
+ upload: {
+ url: "index/upload",
+ auth: true,
+ method: "POST",
+ // desc: '上传图片',
+ },
+ 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: '直播列表',
+ },
+ wxJssdk: {
+ url: "wechat/jssdk",
+ auth: false,
+ method: "POST",
+ // desc: '微信Jssdk',
+ },
+ syncPages: {
+ url: "index/asyncPages",
+ auth: false,
+ method: "POST",
+ // desc: '路由表 DEV开发模式下有效'
+ },
+ debug: {
+ url: "index/debugLog",
+ auth: false,
+ method: "POST",
+ // desc: '上传DEBUG信息',
+ },
+ richText: {
+ url: "index/richtext",
+ auth: false,
+ method: "GET",
+ // desc: '富文本数据',
+ },
+ shareAdd: {
+ url: "share/add",
+ auth: false,
+ method: "POST",
+ // desc: '添加分享记录',
+ },
+ smsSend: {
+ url: "sms/send",
+ auth: false,
+ method: "POST",
+ // desc: '发送短信',
+ },
+ },
+
+ /** 分类 ↓ **/
+ category: {
+ info: {
+ url: "category/detail",
+ auth: false,
+ method: "GET",
+ // desc: '分类类别',
+ },
+ detail: {
+ url: "category",
+ auth: false,
+ method: "GET",
+ // desc: '分类详情',
+ },
+ list: {
+ url: "category/list",
+ 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: '核销订单',
+ },
+ apply: {
+ url: "store.apply/apply",
+ auth: true,
+ method: "POST",
+ // desc: '申请门店',
+ },
+ shopInfo: {
+ url: "store.apply/info",
+ auth: true,
+ method: "POST",
+ // 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: false,
+ 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: '商品收藏',
+ },
+
+ storeAddress: {
+ url: "goods/store",
+ auth: true,
+ method: "GET",
+ // desc: '商品支持的自提点',
+ },
+ scoreList: {
+ url: "score_goods_sku_price/index",
+ auth: false,
+ method: "GET",
+ // desc: '积分商品列表',
+ },
+ scoreDetail: {
+ url: "score_goods_sku_price/detail",
+ auth: false,
+ method: "GET",
+ // desc: '积分详情',
+ },
+ commentList: {
+ url: "goods_comment/index",
+ auth: false,
+ method: "GET",
+ // desc: '商品评论列表',
+ },
+ commentType: {
+ url: "goods_comment/type",
+ auth: false,
+ method: "GET",
+ // desc: '商品评论分类',
+ },
+ },
+
+ /** 用户 ↓ **/
+ user: {
+
+ accountLogin: {
+ url: "user/accountLogin",
+ auth: false,
+ method: "POST",
+ // desc: '账号密码登录',
+ },
+
+ smsLogin: {
+ url: "user/smsLogin",
+ auth: false,
+ method: "POST",
+ // desc: '短信登录',
+ },
+
+ register: {
+ url: "user/register",
+ auth: false,
+ method: "POST",
+ // desc: '注册',
+ },
+
+ forgotPwd: {
+ url: "user/forgotPwd",
+ auth: false,
+ method: "POST",
+ // desc: '重置密码',
+ },
+
+ bindMobile: {
+ url: "user/bindMobile",
+ auth: true,
+ method: "POST",
+ // desc: '修改手机号',
+ },
+
+ changePwd: {
+ url: "user/changePwd",
+ auth: true,
+ method: "POST",
+ // desc: '修改密码',
+ },
+
+ info: {
+ url: "user",
+ auth: true,
+ method: "GET",
+ // desc: '用户信息'
+ },
+
+ profile: {
+ url: "user/profile",
+ auth: true,
+ method: "POST",
+ // desc: '修改用户信息'
+ },
+ logout: {
+ url: "user/logout",
+ auth: true,
+ method: "POST",
+ // desc: '退出登录'
+ },
+ delete: {
+ url: "user/delete",
+ auth: true,
+ method: "POST",
+ // desc: '注销账号'
+ },
+
+ getWxMiniProgramSessionKey: {
+ url: "user/getWxMiniProgramSessionKey",
+ auth: false,
+ method: "POST",
+ // desc: '获取用户session_key',
+ },
+
+ wxMiniProgramOauth: {
+ url: "user/wxMiniProgramOauth",
+ auth: false,
+ method: "POST",
+ // desc: '微信小程序登录',
+ },
+
+ wxOpenPlatformOauth: {
+ url: "user/wxOpenPlatformOauth",
+ auth: false,
+ method: "POST",
+ // desc: '微信APP登录',
+ },
+
+ thirdOauthInfo: {
+ url: "user/thirdOauthInfo",
+ auth: true,
+ method: "GET",
+ // desc: '第三方绑定信息',
+ },
+ unbindThirdOauth: {
+ url: "user/unbindThirdOauth",
+ auth: true,
+ method: "POST",
+ // desc: '解绑信息',
+ },
+
+ signList: {
+ url: "user_sign/index",
+ auth: true,
+ method: "GET",
+ // desc: '签到记录',
+ },
+ sign: {
+ url: "user_sign/sign",
+ auth: true,
+ method: "POST",
+ // desc: '签到',
+ },
+ messageIds: {
+ url: "notification/template",
+ auth: false,
+ method: "GET",
+ // desc: '订阅消息模板ids',
+ },
+ 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: '删除足迹'
+ },
+ userData: {
+ url: "user/userData",
+ auth: true,
+ method: "GET",
+ // desc: '用户其他信息',
+ },
+ appleIdOauth: {
+ url: "user/appleIdOauth",
+ auth: false,
+ method: "POST",
+ // desc: 'appleId授权',
+ }
+ },
+
+ /** 位置 ↓ **/
+ 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: '删除',
+ },
+ },
+
+ /** 常见问题 ↓ **/
+ other: {
+ faqList: {
+ url: "faq",
+ auth: false,
+ method: "GET",
+ // desc: '常见问题列表',
+ },
+ feedbackType: {
+ url: "feedback/type",
+ auth: true,
+ method: "GET",
+ // desc: '意见反馈类型',
+ },
+ feedbackAdd: {
+ url: "feedback/add",
+ auth: true,
+ method: "POST",
+ // desc: '提交意见',
+ },
+ commentAdd: {
+ url: "comment/submit",
+ auth: true,
+ method: "POST",
+ // desc: '提交评论',
+ },
+ commentList: {
+ url: "comment/list",
+ auth: true,
+ method: "GET",
+ // 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: '确认收货',
+ },
+ cancel: {
+ url: "order/cancel",
+ auth: true,
+ method: "POST",
+ // desc: '取消订单',
+ },
+ 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: '订单商品详情',
+ }
+ },
+
+ /** 支付金钱 ↓ **/
+ money: {
+ prepay: {
+ url: "pay/prepay",
+ auth: true,
+ method: "POST",
+ // desc: '发起支付',
+ },
+ walletApply: {
+ url: "user_wallet_apply/apply",
+ auth: true,
+ method: "POST",
+ // desc: '申请提现'
+ },
+ walletRule: {
+ url: "user_wallet_apply/rule",
+ auth: true,
+ method: "GET",
+ // desc: '提现规则'
+ },
+ walletLog: {
+ url: "user_wallet_log",
+ auth: true,
+ method: "GET",
+ // desc: '钱包,积分明细'
+ },
+ bankInfo: {
+ url: "user_bank/info",
+ auth: true,
+ method: "GET",
+ // desc: '银行卡信息'
+ },
+ bankEdit: {
+ url: "user_bank/edit",
+ auth: true,
+ method: "POST",
+ // desc: '编辑银行卡信息'
+ },
+ withdrawLog: {
+ url: "user_wallet_apply/index",
+ auth: true,
+ method: "GET",
+ // desc: '提现记录'
+ },
+ recharge: {
+ url: "trade_order/recharge",
+ auth: true,
+ method: "POST",
+ // desc: '充值'
+ },
+ rechargeLog: {
+ url: "trade_order/index",
+ auth: true,
+ method: "GET",
+ // desc: '充值记录'
+ },
+ rechargeDetail: {
+ url: "trade_order/detail",
+ auth: true,
+ method: "GET",
+ // desc: '充值订单详情'
+ }
+ },
+
+ /** 优惠券 ↓ **/
+ coupons: {
+ list: {
+ url: "coupons",
+ auth: false,
+ method: "GET",
+ // desc: '个人中心优惠券列表',
+ },
+ templateList: {
+ 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: false,
+ method: "GET",
+ // desc: '适用商品',
+ }
+ },
+
+ /** 分销 ↓ **/
+ commission: {
+ auth: {
+ url: "commission.agent/info",
+ auth: true,
+ method: "GET",
+ // desc: '分销身份鉴权',
+ },
+ log: {
+ url: "commission.log/index",
+ auth: true,
+ method: "GET",
+ // desc: '分销动态',
+ },
+ goods: {
+ url: "commission.goods/index",
+ auth: true,
+ method: "GET",
+ // desc: '分销商品',
+ },
+ ranking: {
+ url: "commission.agent/ranking",
+ auth: true,
+ method: "GET",
+ // desc: '分销商排行榜',
+ },
+ form: {
+ url: "commission.agent/agentForm",
+ auth: true,
+ method: "GET",
+ // desc: '申请成为分销商表单',
+ },
+ apply: {
+ url: "commission.agent/applyForm",
+ auth: true,
+ method: "POST",
+ // desc: '申请成为分销商',
+ },
+ team: {
+ url: "commission.agent/team",
+ auth: true,
+ method: "GET",
+ // desc: '我的团队',
+ },
+ share: {
+ url: "share/index",
+ auth: true,
+ method: "GET",
+ // desc: '分享记录',
+ },
+ orderLog: {
+ url: "commission.order/index",
+ auth: true,
+ method: "GET",
+ // desc: '分销订单',
+ },
+ rewardLog: {
+ url: "commission.reward/index",
+ auth: true,
+ method: "GET",
+ // desc: '佣金记录',
+ },
+ lv: {
+ url: "commission.agent/level",
+ auth: true,
+ method: "GET",
+ // desc: '佣金记录',
+ }
+ }
+
+
+};
diff --git a/shopro/request/index.js b/shopro/request/index.js
new file mode 100644
index 0000000..3d9b71a
--- /dev/null
+++ b/shopro/request/index.js
@@ -0,0 +1,73 @@
+import Request from './request'
+import apiList from './apis.js'
+import store from '@/shopro/store/index.js'
+
+const shoproRequest = new Request();
+export default function http(
+ url,
+ data = {},
+ toastBefore = '', // 请求前加载提示
+ toastAfter = true, // 请求后错误提示
+) {
+ let api = getApiPath(url);
+ /* 请求之前拦截器 */
+ shoproRequest.interceptor.request((config, cancel) => {
+ let token = uni.getStorageSync('token');
+ if (api.auth && !token) {
+ store.dispatch('showAuthModal');
+ uni.hideLoading()
+ throw (`暂未登录,已阻止此次API请求: '${api.url}'`);
+ }
+ token && shoproRequest.setConfig(config => {
+ config.header.token = token
+ })
+ if (toastBefore !== '') {
+ uni.showLoading({
+ title: toastBefore,
+ mask: true
+ });
+ }
+ return config
+ });
+
+ /* 请求之后拦截器 */
+ shoproRequest.interceptor.response((response) => {
+ uni.hideLoading();
+ if (response.code === 0) {
+ if (toastAfter) {
+ uni.showToast({
+ title: response.msg || '请求出错,稍后重试',
+ icon: 'none',
+ duration: 1000,
+ mask: true
+ });
+ }
+
+ }
+
+ // token过期注销
+ if (response.code === 401) {
+ store.dispatch('logout');
+ store.dispatch('showAuthModal');
+ throw (`登录已过期或注销,已阻止此次API请求: '${api.url}'`);
+ }
+ return response
+ })
+
+ return shoproRequest.request({
+ url: api.url,
+ data,
+ method: api.method
+ })
+
+}
+
+// 组装接口路径
+function getApiPath(url) {
+ let apiArray = url.split(".");
+ let api = apiList;
+ apiArray.forEach(v => {
+ api = api[v];
+ });
+ return api;
+}
diff --git a/shopro/request/request.js b/shopro/request/request.js
new file mode 100644
index 0000000..e784e1d
--- /dev/null
+++ b/shopro/request/request.js
@@ -0,0 +1,133 @@
+/**
+ * Request:请求封装
+ * @property {Object} config = 私有属性,默认值
+ * @property {Function} isUrl = 私有方法,url是否完整
+ * @property {Function} requestBefore = 私有方法,请求前
+ * @property {Function} requestAfter = 私有方法,请求后
+ */
+import {
+ API_URL
+} from '@/env'
+import platform from '@/shopro/platform/index';
+export default class Request {
+ constructor() {
+ // 默认配置
+ this.config = {
+ baseUrl: API_URL,
+ header: {
+ 'content-type': 'application/json',
+ 'platform': platform.get()
+ },
+ url: '',
+ data: {},
+ params: {},
+ method: 'GET',
+ dataType: 'json',
+ // #ifndef MP-ALIPAY || APP-PLUS
+ responseType: 'text',
+ // #endif
+ custom: {},
+ // #ifdef APP-PLUS
+ sslVerify: false
+ // #endif
+ }
+
+ /* 拦截器 */
+ this.interceptor = {
+ request: cb => {
+ if (cb) {
+ this.requestBefore = cb
+ } else {
+ this.requestBefore = request => request
+ }
+ },
+ response: (cb) => {
+ if (cb) {
+ this.requestAfter = cb
+ } else {
+ this.requestAfter = response => response
+ }
+ }
+ }
+ }
+
+ /* 判断url是否完整 */
+ static isUrl(url) {
+ return /(http|https):\/\/([\w.]+\/?)\S*/.test(url)
+ }
+
+ static addQueryString(params) {
+ let paramsData = ''
+ Object.keys(params).forEach(key => {
+ paramsData += key + '=' + encodeURIComponent(params[key]) + '&'
+ })
+ return paramsData.substring(0, paramsData.length - 1)
+ }
+
+ /* 请求前 */
+ static requestBefore(config) {
+ return config
+ }
+
+ /* 请求后 */
+ static requestAfter(response) {
+ return response
+ }
+
+ /*设置全局配置*/
+ setConfig(func) {
+ return func(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}
+ */
+ async request(options = {}) {
+ options = {
+ ...options,
+ ...this.config,
+ ...this.requestBefore(options)
+ }
+ return new Promise((resolve, reject) => {
+ let mergeUrl = Request.isUrl(options.url) ? options.url : (options.baseUrl + options.url)
+ if (JSON.stringify(options.params) !== '{}') {
+ let query = Request.addQueryString(options.params);
+ mergeUrl += mergeUrl.indexOf('?') === -1 ? `?${query}` : `&${query}`
+ }
+ options.url = mergeUrl
+ options.success = res => {
+ resolve(this.requestAfter(res.data))
+ }
+ options.fail = err => {
+ reject(this.requestAfter(err))
+ }
+ uni.request(options)
+ })
+ }
+
+ get(url, options = {}) {
+ return this.request({
+ url,
+ method: 'GET',
+ ...options
+ })
+ }
+
+ post(url, data, options = {}) {
+ return this.request({
+ url,
+ data,
+ method: 'POST',
+ ...options
+ })
+ }
+
+}
diff --git a/shopro/router/index.js b/shopro/router/index.js
new file mode 100644
index 0000000..8f9d7fe
--- /dev/null
+++ b/shopro/router/index.js
@@ -0,0 +1,70 @@
+// 路由
+import {
+ RouterMount,
+ createRouter
+} from './uni-simple-router.js'
+import store from '@/shopro/store'
+const router = createRouter({
+ platform: process.env.VUE_APP_PLATFORM,
+ applet: {
+ animationDuration: 0 //默认 300ms
+ },
+ routerErrorEach: ({
+ type,
+ msg
+ }) => {
+ switch (type) {
+ case 3: // APP退出应用
+ // #ifdef APP-PLUS
+ router.$lockStatus = false;
+ uni.showModal({
+ title: '提示',
+ content: '您确定要退出应用吗?',
+ success: function(res) {
+ if (res.confirm) {
+ plus.runtime.quit();
+ }
+ }
+ });
+ // #endif
+ break;
+ case 2:
+ case 0:
+ router.$lockStatus = false;
+ break;
+ default:
+ break;
+ }
+
+ },
+ // 通配符,非定义页面,跳转404
+ routes: [...ROUTES,
+ {
+ path: '*',
+ redirect: (to) => {
+ return {
+ name: '404'
+ }
+ }
+ },
+ ]
+});
+
+//全局路由前置守卫
+router.beforeEach((to, from, next) => {
+ // 权限控制登录
+ if (to.meta && to.meta.auth && !store.getters.isLogin) {
+ store.dispatch('showAuthModal');
+ next(false);
+ } else if (store.getters.initRecharge.enable !== '1' && to.path === '/pages/user/wallet/top-up') {
+ // 充值入口控制
+ next(false);
+ } else {
+ next()
+ }
+});
+
+export {
+ router,
+ RouterMount
+}
diff --git a/shopro/router/uni-simple-router.js b/shopro/router/uni-simple-router.js
new file mode 100644
index 0000000..a68ff67
--- /dev/null
+++ b/shopro/router/uni-simple-router.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Router=t():e.Router=t()}(self,(function(){return e={779:(e,t,r)=>{var o=r(173);e.exports=function e(t,r,n){return o(r)||(n=r||n,r=[]),n=n||{},t instanceof RegExp?function(e,t){var r=e.source.match(/\((?!\?)/g);if(r)for(var o=0;o{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},844:function(e,t,r){"use strict";var o=this&&this.__assign||function(){return(o=Object.assign||function(e){for(var t,r=1,o=arguments.length;r0?t.vueEachArray[r](e,o,(function(){n&&n()})):t.myEachHook(e,o,(function(a){!1===a?n(!1):t.vueEachArray[r](e,o,(function(e){n(a)}))}),t.router,!0)}},t}(Array);t.MyArray=n,t.proxyEachHook=function(e,t){for(var r=["beforeHooks","afterHooks"],o=0;o0)return!1;window.location.reload()}),0)}else e.mount[0].app.$mount(),e.mount=[]}},814:function(e,t){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,r=1,o=arguments.length;r{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getEnterPath=void 0,t.getEnterPath=function(e,t){switch(t.options.platform){case"mp-alipay":case"mp-weixin":case"mp-toutiao":case"mp-qq":return e.$options.mpInstance.route;case"mp-baidu":return e.$options.mpInstance.is||e.$options.mpInstance.pageinstance.route}return e.$options.mpInstance.route}},282:function(e,t,r){"use strict";var o=this&&this.__assign||function(){return(o=Object.assign||function(e){for(var t,r=1,o=arguments.length;r{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.createRouteMap=void 0;var o=r(883),n=r(789);t.createRouteMap=function(e,t){var r={finallyPathList:[],finallyPathMap:Object.create(null),aliasPathMap:Object.create(null),pathMap:Object.create(null),vueRouteMap:Object.create(null),nameMap:Object.create(null)};return t.forEach((function(t){var a=n.getRoutePath(t,e),i=a.finallyPath,u=a.aliasPath,l=a.path;if(null==l)throw new Error("请提供一个完整的路由对象,包括以绝对路径开始的 ‘path’ 字符串 "+JSON.stringify(t));if(i instanceof Array&&!e.options.h5.vueRouterDev&&"h5"===e.options.platform)throw new Error("非 vueRouterDev 模式下,route.alias 目前无法提供数组类型! "+JSON.stringify(t));var p=i,c=u;"h5"!==e.options.platform&&0!==p.indexOf("/")&&"*"!==l&&o.warn("当前路由对象下,route:"+JSON.stringify(t)+" 是否缺少了前缀 ‘/’",e,!0),r.finallyPathMap[p]||(r.finallyPathMap[p]=t,r.aliasPathMap[c]=t,r.pathMap[l]=t,r.finallyPathList.push(p),null!=t.name&&(r.nameMap[t.name]=t))})),r}},662:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.registerEachHooks=t.registerRouterHooks=t.registerHook=void 0;var o=r(366),n=r(169);function a(e,t){e[0]=t}t.registerHook=a,t.registerRouterHooks=function(e,t){return a(e.routerBeforeHooks,(function(e,r,o){t.routerBeforeEach(e,r,o)})),a(e.routerAfterHooks,(function(e,r){t.routerAfterEach(e,r)})),a(e.routerErrorHooks,(function(e,r){t.routerErrorEach(e,r)})),e},t.registerEachHooks=function(e,t,r){a(e.lifeCycle[t],(function(e,a,i,u,l){l?n.onTriggerEachHook(e,a,u,o.hookToggle[t],i):r(e,a,i)}))}},460:function(e,t,r){"use strict";var o=this&&this.__assign||function(){return(o=Object.assign||function(e){for(var t,r=1,o=arguments.length;r0)return P}if(""!==u)return h(t);throw new Error(r+" 路径无法在路由表中找到!检查跳转路径及路由表")},t.getDataType=v,t.copyData=function(e){return JSON.parse(JSON.stringify(e))},t.getUniCachePage=function(e){var t=getCurrentPages();if(null==e)return t;if(0===t.length)return t;var r=t.reverse()[e];return null==r?[]:r},t.urlToJson=function(e){var t={},r=e.split("?"),o=r[0],n=r[1];if(null!=n)for(var a=0,i=n.split("&");a3},t.baseClone=y,t.deepClone=g,t.lockDetectWarn=function(e,t,r,o,n){if("afterHooks"===n)o();else{var a=e.options.detectBeforeLock;a&&a(e,t,r),e.$lockStatus?e.options.routerErrorEach({type:2,msg:"当前页面正在处于跳转状态,请稍后再进行跳转...."},e):o()}},t.replaceHook=function(e,t,r,o){var n=t.$options,a=e[r][o],u={};if("[object Array]"===v(a)&&(u={beforeCreate:[],created:[],beforeMount:[],mounted:[],beforeDestroy:[],destroyed:[]}),null!=a){for(var l=i.proxyVueSortHookName[o],p=function(r){var p=l[r],c=n[p];if("[object Array]"===v(c)){if(1===c.length&&c.toString().includes("UNI-SIMPLE-ROUTER"))return"continue";var s={options:[],hook:Function},f=c.splice(c.length-1,1,(function(){for(var e=[],t=0;t0?u[p]=[s]:a[p]=[s]}},c=0;c0&&a.push(u)}},t.callHook=d,t.resetPageHook=function(e,t){var r=t.trim().match(/^(\/?[^\?\s]+)(\?[\s\S]*$)?$/);if(null==r)throw new Error("还原hook失败。请检查 【"+t+"】 路径是否正确。");t=r[1];var o="appletsProxyHook";"app-plus"===e.options.platform&&(o="appProxyHook");for(var n=[],a=0,i=Object.entries(e[o]);a{"use strict";function r(e,t,r,o){if(void 0===o&&(o=!1),!o){var n="[object Object]"===t.toString();if(!1===t)return!1;if(n&&!1===t[e])return!1}return console[e](r),!0}Object.defineProperty(t,"__esModule",{value:!0}),t.warnLock=t.log=t.warn=t.err=t.isLog=void 0,t.isLog=r,t.err=function(e,t,o){r("error",t.options.debugger,e,o)},t.warn=function(e,t,o){r("warn",t.options.debugger,e,o)},t.log=function(e,t,o){r("log",t.options.debugger,e,o)},t.warnLock=function(e){console.warn(e)}},607:function(e,t,r){"use strict";var o=this&&this.__createBinding||(Object.create?function(e,t,r,o){void 0===o&&(o=r),Object.defineProperty(e,o,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,o){void 0===o&&(o=r),e[o]=t[r]}),n=this&&this.__exportStar||function(e,t){for(var r in e)"default"===r||Object.prototype.hasOwnProperty.call(t,r)||o(t,e,r)};Object.defineProperty(t,"__esModule",{value:!0}),t.createRouter=t.RouterMount=t.runtimeQuit=void 0,n(r(366),t),n(r(309),t);var a=r(814);Object.defineProperty(t,"runtimeQuit",{enumerable:!0,get:function(){return a.runtimeQuit}});var i=r(963);Object.defineProperty(t,"RouterMount",{enumerable:!0,get:function(){return i.RouterMount}}),Object.defineProperty(t,"createRouter",{enumerable:!0,get:function(){return i.createRouter}})},366:(e,t)=>{"use strict";var r,o,n;Object.defineProperty(t,"__esModule",{value:!0}),t.rewriteMethodToggle=t.navtypeToggle=t.hookToggle=void 0,(n=t.hookToggle||(t.hookToggle={})).beforeHooks="beforeEach",n.afterHooks="afterEach",n.enterHooks="beforeEnter",(o=t.navtypeToggle||(t.navtypeToggle={})).push="navigateTo",o.replace="redirectTo",o.replaceAll="reLaunch",o.pushTab="switchTab",o.back="navigateBack",(r=t.rewriteMethodToggle||(t.rewriteMethodToggle={})).navigateTo="push",r.navigate="push",r.redirectTo="replace",r.reLaunch="replaceAll",r.switchTab="pushTab",r.navigateBack="back"},309:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0})},169:function(e,t,r){"use strict";var o=this&&this.__rest||function(e,t){var r={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var n=0;for(o=Object.getOwnPropertySymbols(e);n0){var u=void 0;switch("h5"===e.options.platform?u=i.$options.beforeRouteLeave:null!=i.$vm&&(u=i.$vm.$options.beforeRouteLeave),n.getDataType(u)){case"[object Array]":a=(a=u[0]).bind(i);break;case"[object Function]":a=u.bind(i.$vm)}}return p(a,t,r,e,o)}function p(e,t,r,o,n,a){void 0===a&&(a=!0),null!=e&&e instanceof Function?!0===a?e(t,r,n,o,!1):(e(t,r,(function(){}),o,!1),n()):n()}function c(e,t,r,o,a,i){var u=n.forMatNextToFrom(e,t,r),l=u.matTo,p=u.matFrom;"h5"===e.options.platform?s(a,0,i,e,l,p,o):s(a.slice(0,4),0,(function(){i((function(){s(a.slice(4),0,n.voidFun,e,l,p,o)}))}),e,l,p,o)}function s(e,r,i,l,p,c,f){var h=n.routesForMapRoute(l,p.path,["finallyPathMap","pathMap"]);if(e.length-1{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.proxyPageHook=t.createFullPath=t.createToFrom=void 0;var o=r(789),n=r(890),a=r(99);t.createToFrom=function(e,t){var r=o.getUniCachePage(0);return"[object Array]"===o.getDataType(r)?o.deepClone(e):n.createRoute(t)},t.createFullPath=function(e,t){if(null==e.fullPath){var r=a.stringifyQuery(e.query);e.fullPath=e.path+r}null==t.fullPath&&(r=a.stringifyQuery(t.query),t.fullPath=t.path+r)},t.proxyPageHook=function(e,t,r,n){o.replaceHook(t,e,r,n)}},99:function(e,t,r){"use strict";var o=this&&this.__assign||function(){return(o=Object.assign||function(e){for(var t,r=1,o=arguments.length;r{[propName: string]: any;}",t):e[r]=u}else{if(!n.assertDeepObject(o))return e;var l=JSON.stringify(o);e[r]={query:l}}return e},t.parseQuery=function(e,t){var r=t.options.parseQuery;if(r)e=r(n.copyData(e)),"[object Object]"!==n.getDataType(e)&&i.warn("请按格式返回参数: parseQuery?:(jsonQuery:{[propName: string]: any;})=>{[propName: string]: any;}",t);else if(Reflect.get(e,"query")){var o=Reflect.get(e,"query");if("string"==typeof o)try{o=JSON.parse(o)}catch(e){i.warn("尝试解析深度对象失败,按原样输出。"+e,t)}if("object"==typeof o)return n.deepDecodeQuery(o)}return e},t.stringifyQuery=function(e){var t=e?Object.keys(e).map((function(t){var r=e[t];if(void 0===r)return"";if(null===r)return c(t);if(Array.isArray(r)){var o=[];return r.forEach((function(e){void 0!==e&&(null===e?o.push(c(t)):o.push(c(t)+"="+c(e)))})),o.join("&")}return c(t)+"="+c(r)})).filter((function(e){return e.length>0})).join("&"):null;return t?"?"+t:""}},314:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.rewriteMethod=void 0;var o=r(366),n=r(789),a=r(883),i=r(809),u=["navigateTo","redirectTo","reLaunch","switchTab","navigateBack"];t.rewriteMethod=function(e){!1===e.options.keepUniOriginNav&&u.forEach((function(t){var r=uni[t];uni[t]=function(u,l,p,c){void 0===l&&(l=!1),l?i.uniOriginJump(e,r,t,u,p,c):("app-plus"===e.options.platform&&0===Object.keys(e.appMain).length&&(e.appMain={NAVTYPE:t,path:u.url}),function(e,t,r){if("app-plus"===r.options.platform){var i=null;e&&(i=e.openType),null!=i&&"appLaunch"===i&&(t="reLaunch")}if("reLaunch"===t&&'{"url":"/"}'===JSON.stringify(e)&&(a.warn("uni-app 原生方法:reLaunch({url:'/'}) 默认被重写啦!你可以使用 this.$Router.replaceAll() 或者 uni.reLaunch({url:'/?xxx=xxx'})",r,!0),t="navigateBack",e={from:"backbutton"}),"navigateBack"===t){var u=1;null==e&&(e={delta:1}),"[object Number]"===n.getDataType(e.delta)&&(u=e.delta),r.back(u,e)}else{var l=o.rewriteMethodToggle[t],p=e.url;if(!p.startsWith("/")){var c=n.resolveAbsolutePath(p,r);p=c,e.url=c}if("switchTab"===t){var s=n.routesForMapRoute(r,p,["pathMap","finallyPathList"]),f=n.getRoutePath(s,r).finallyPath;if("[object Array]"===n.getDataType(f)&&a.warn("uni-app 原生方法跳转路径为:"+p+"。此路为是tab页面时,不允许设置 alias 为数组的情况,并且不能为动态路由!当然你可以通过通配符*解决!",r,!0),"*"===f&&a.warn("uni-app 原生方法跳转路径为:"+p+"。在路由表中找不到相关路由表!当然你可以通过通配符*解决!",r,!0),"h5"===r.options.platform){var h=e.success;e.success=function(){for(var t=[],r=0;r0&&Reflect.has(t,"index")){var r=n.getUniCachePage(0);if(0===Object.keys(r).length)return!1;var o=r,a=o.$options.onTabItemTap;if(a)for(var i=0;i0&&n[n.length-1])||6!==a[0]&&2!==a[0])){i=0;continue}if(3===a[0]&&(!n||a[1]>n[0]&&a[1] state.cartList,
+ checkCart: state => state.checkCart,
+ allSelected: state => state.allSelected,
+ cartNum: state => state.cartNum,
+ // 购物车数量和总价
+ totalCount: state => {
+ let totalNum = 0;
+ let totalPrice = 0;
+ state.cartList.filter(item => {
+ if (item.checked) {
+ totalNum += 1;
+ totalPrice += item.goods_num * (item.sku_price ? item.sku_price.price : 0);
+ }
+ })
+ return {
+ totalNum,
+ totalPrice
+ }
+ },
+
+ // 是否选择了商品
+ isSel: state => {
+ let isSel = false;
+ state.cartList.map(item => {
+ if (item.checked) {
+ isSel = true
+ }
+ })
+ return isSel
+ },
+
+ // 活动商品唯一选中可以结算
+ isActivityPay() {
+ let num = 0
+ let activityNum = 0
+ state.cartList.map(item => {
+ if (item.checked) {
+ num += 1
+ if (item.cart_type === 'activity') {
+ activityNum += 1
+ }
+ }
+ })
+ if ((num === 1 && activityNum === 1) || activityNum === 0) {
+ return true
+ }
+ return false
+ }
+
+}
+
+
+const mutations = {
+ // cart数据获取变动。
+ CART_LIST(state, payload) {
+ state.cartList = payload;
+ let cartListNumber = payload.length;
+ if (Number(cartListNumber)) {
+ uni.setTabBarBadge({
+ index: 2,
+ text: String(cartListNumber)
+ })
+ } else {
+ uni.removeTabBarBadge({
+ index: 2
+ })
+ }
+ state.cartNum = cartListNumber;
+ },
+
+ // 切换全选。
+ changeAllSellect(state) {
+ state.allSelected = !state.allSelected;
+ },
+ // 全选设置
+ getAllSellectCartList(state, flag) {
+ state.cartList.map(item => {
+ item.checked = flag
+ })
+ },
+ // 全选检测
+ checkCartList(state) {
+ let all = true;
+ state.cartList.map(item => {
+ if (!item.checked) {
+ all = false
+ }
+ })
+ state.allSelected = all;
+ },
+ // 是否购物车数据检测
+ getCheckCart(state) {
+ let obj = {};
+ state.cartList.map(item => {
+ obj[item.goods_id] = {
+ num: item.goods_num,
+ cartOrderId: item.id
+ };
+ });
+ state.checkCart = obj;
+ },
+}
+
+const actions = {
+ // 购物车数据(查)
+ getCartList({
+ commit
+ }) {
+ return new Promise((resolve, reject) => {
+ http('cart.index').then(res => {
+ if (res.code === 1) {
+ let cartData = res.data;
+ cartData.length && cartData.map(item => {
+ item.checked = true;
+ })
+ commit('CART_LIST', cartData);
+ commit('checkCartList');
+ commit('getCheckCart')
+ }
+
+ }).catch(e => {
+ reject(e)
+ })
+ })
+ },
+ // 添加到购物车(增)
+ addCartGoods({
+ dispatch
+ }, data) {
+ return new Promise((resolve, reject) => {
+ http('cart.add', {
+ goods_list: data.list,
+ from: data.from
+ }).then(res => {
+ res.code === 1 && dispatch('getCartList');
+ resolve(res)
+ }).catch(e => {
+ reject(e)
+ })
+ })
+ },
+ // 修改购物车商品数量(改)|| 删除购物车商品(删)
+ changeCartList({
+ commit,
+ 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) {
+ dispatch('getCartList');
+ }
+ commit('checkCartList');
+ resolve(res)
+ }).catch(e => {
+ reject(e)
+ })
+ })
+ },
+}
+
+export default {
+ state,
+ mutations,
+ actions,
+ getters
+}
diff --git a/shopro/store/modules/shopro.js b/shopro/store/modules/shopro.js
new file mode 100644
index 0000000..d6c0b83
--- /dev/null
+++ b/shopro/store/modules/shopro.js
@@ -0,0 +1,146 @@
+import http from '@/shopro/request/index'
+import share from '@/shopro/share';
+
+const state = {
+ shop: {}, // 商城信息
+ wechat: {}, // 微信配置
+ share: {}, // 分享配置
+ payment: {}, // 支付配置
+ addons: [], // 插件配置
+ chat: uni.getStorageSync("chat") || {}, // 客服配置
+ store: {}, // 商城信息
+ tabbarData: [], //自定义底部导航数据
+ recharge: uni.getStorageSync("recharge") || {}, //充值配置
+
+ homeTemplate: [], // 首页模板数据
+ userTemplate: [], // 个人中心模板数据
+ floatData: {}, // 悬浮按钮数据
+ popupData: {}, // 弹窗数据
+ hasTemplate: true, //是否有模板数据
+ shareInfo: {} // 默认分享数据
+}
+const getters = {
+ initShop: state => state.shop,
+ initStore: state => state.store,
+ initShare: state => state.share,
+ initPayment: state => state.payment,
+ initAddons: state => state.addons,
+ initChat: state => state.chat,
+ initWechat: state => state.wechat,
+ initRecharge: state => state.recharge,
+
+ hasTemplate: state => state.hasTemplate,
+ homeTemplate: state => state.homeTemplate,
+ userTemplate: state => state.userTemplate,
+ floatData: state => state.floatData,
+ popupData: state => state.popupData,
+ tabbarData: state => state.tabbarData,
+
+ shareInfo: state => state.shareInfo
+}
+
+
+const actions = {
+ // 初始化数据
+ async appInit({
+ commit,
+ dispatch
+ }, options) {
+ const result = await http('common.init');
+ if (result.code === 1) {
+ commit('CONFIG', result.data);
+ if (!options?.query?.token) {
+ dispatch('autoLogin');
+ }
+ return result.data;
+ }
+ return false;
+ },
+
+ // 获取模板数据
+ async getTemplate({
+ commit
+ }, options) {
+ let shop_id = 0;
+ // #ifdef H5
+ if (options?.query.shop_id) {
+ shop_id = options.query.shop_id;
+ }
+ // #endif
+
+ // #ifdef MP
+ if (options?.query.scene) {
+ let scene = decodeURIComponent(options?.query.scene);
+ let sceneObj = scene.split('=');
+ if (sceneObj[0] === 'shop_id') {
+ shop_id = sceneObj[1]
+ }
+ }
+ // #endif
+ const result = await http('common.template', shop_id ? {
+ shop_id
+ } : {});
+ if (result.code === 1) {
+ commit("hasTemplate", true);
+ commit('TEMPLATE', result.data);
+ return result.data;
+ } else {
+ commit("hasTemplate", false);
+ return false;
+ }
+ },
+
+ // 同步路由到后端
+ syncPages({
+ commit
+ }) {
+ http('common.syncPages', {
+ data: ROUTES,
+ })
+ },
+}
+
+
+const mutations = {
+ CONFIG(state, payload) {
+ Object.keys(payload).forEach(k => {
+ state[k] = payload[k];
+ if (k === 'chat') {
+ uni.setStorageSync("chat", payload[k]);
+ }
+ if (k === 'recharge') {
+ uni.setStorageSync("recharge", payload[k])
+ }
+ })
+ },
+
+ TEMPLATE(state, data) {
+ state.template = data;
+ state.homeTemplate = data.home
+ state.userTemplate = data.user
+ state.floatData = data['float-button']?. [0]?.content
+ state.popupData = data?.popup?. [0]?.content
+ state.tabbarData = data?.tabbar?. [0]?.content
+ },
+
+ hasTemplate(state, data) {
+ state.hasTemplate = data
+ },
+ // 弹窗一次的话,关闭的时候删除数据。
+ delPopup(state, index) {
+ let popupData = state.popupData;
+ popupData.list.splice(index, 1)
+ state.template = popupData;
+ },
+ shareInfo(state, shareInfo) {
+ state.shareInfo = shareInfo;
+ }
+}
+
+
+export default {
+ state,
+ mutations,
+ actions,
+ getters
+}
diff --git a/shopro/store/modules/user.js b/shopro/store/modules/user.js
new file mode 100644
index 0000000..833d099
--- /dev/null
+++ b/shopro/store/modules/user.js
@@ -0,0 +1,241 @@
+// 用户数据模块
+import http from '@/shopro/request/index'
+import store from '@/shopro/store'
+import tools from '@/shopro/utils/tools'
+import wechat from '@/shopro/wechat/wechat'
+import share from '@/shopro/share'
+
+const state = {
+ token: uni.getStorageSync("token") || "",
+ isLogin: uni.getStorageSync("isLogin") || false, // 是否登陆
+ userInfo: uni.getStorageSync("userInfo") || {}, // 用户信息
+ agentInfo: {}, //分销商信息
+ userData: {}, //用户其他相关信息
+ subscribeMessageIdsMap: [], //小程序订阅消息模板ids
+ authType: '' // smsLogin:手机号登录注册, accountLogin:密码登录, forgotPwd:忘记密码, changePwd:修改密码, bindMobile:绑定手机号
+}
+
+const getters = {
+ token: state => state.token,
+ isLogin: state => state.isLogin,
+ userInfo: state => state.userInfo,
+ agentInfo: state => state.agentInfo,
+ userOtherData: state => state.userData,
+ authType: state => state.authType,
+ subscribeMessageIdsMap: state => state.subscribeMessageIdsMap
+}
+
+const actions = {
+ // 获取用户信息
+ getUserInfo({
+ commit,
+ dispatch,
+ getters,
+ state
+ }, token = '') {
+ return new Promise((resolve, reject) => {
+ token && uni.setStorageSync('token', token);
+ http('user.info').then(res => {
+ if (res.code === 1) {
+ let lastLoginStatus = getters.isLogin;
+ commit('userInfo', res.data);
+ commit('isLogin', true);
+ dispatch('showAuthModal', '');
+ !lastLoginStatus && share.setShareInfo();
+ // 存在分享信息 添加分享记录
+ let spm = uni.getStorageSync('spm');
+ if (spm) {
+ http('common.shareAdd', {
+ spm: spm
+ });
+ uni.removeStorageSync('spm');
+ }
+ resolve(res.data)
+ }
+
+ }).then(() => {
+ // 只有在登录的时候请求购物车信息,订单信息,获取登录信息之后。
+ token && dispatch('getCartList');
+ token && dispatch('getUserData');
+ })
+ .catch(e => {
+ reject(e)
+ })
+ })
+ },
+ // 用户其他相关信息
+ getUserData({
+ commit
+ }) {
+ return new Promise((resolve, reject) => {
+ http('user.userData').then(res => {
+ commit('USER_DATA', res.data);
+ resolve(res)
+ }).catch(e => {
+ reject(e)
+ })
+ })
+ },
+
+ // 获取分销商身份信息
+ getAgent({
+ commit
+ }) {
+ return new Promise((resolve, reject) => {
+ http('commission.auth').then(res => {
+ if (res.code === 1) {
+ commit('AGENT_INFO', res.data.data);
+ }
+ resolve(res)
+ }).catch(e => {
+ reject(e)
+ });
+ })
+ },
+
+
+ // 自动登录
+ async autoLogin({
+ getters,
+ dispatch
+ }) {
+ if (getters.initWechat?.autologin && !getters.isLogin) { // 微信开启自动登录 并且当前未登录,进入自动登录流程
+ let token = '';
+
+ // #ifdef H5
+ wechat.login();
+ // #endif
+
+ // #ifdef MP-WEIXIN
+ token = await wechat.getWxMiniProgramSessionKey(true)
+ // #endif
+
+ token && await dispatch('getUserInfo', token);
+ } else if (getters.isLogin) { // 已经登录,直接获取用户信息
+ await dispatch('getUserInfo');
+ }
+ share.setShareInfo();
+ // 初始化小程序session_key
+ // #ifdef MP-WEIXIN
+ if (!getters.initWechat?.autologin) {
+ await wechat.getWxMiniProgramSessionKey(false);
+ }
+ // #endif
+ },
+
+ // 登录弹窗控制
+ showAuthModal({
+ commit
+ }, type = 'accountLogin') {
+ commit('AUTH_TYPE', type);
+ },
+
+ // 退出登录
+ logout({
+ commit,
+ dispatch
+ }) {
+ uni.getStorageSync('token') && http('user.logout');
+ commit('token', "");
+ uni.removeStorageSync('chatSessionId');
+ commit('isLogin', false);
+ commit('userInfo', {});
+ commit('CART_LIST', []);
+ commit('USER_DATA', {});
+ // 重置全局分享信息
+ share.setShareInfo();
+ },
+
+ // 获取订阅消息模板ids;
+ getMessageIds({
+ commit,
+ state
+ }) {
+ http('user.messageIds').then(res => {
+ commit('formatMessage', res.data)
+ Promise.resolve(res.data)
+ }).catch(e => {
+ Promise.reject(e)
+ })
+
+ },
+}
+
+const mutations = {
+ token(state, payload) {
+ state.token = payload;
+ uni.setStorageSync("token", payload);
+ },
+ // 登录态
+ isLogin(state, data) {
+ state.isLogin = data;
+ uni.setStorageSync('isLogin', data);
+ },
+ // 用户信息
+ userInfo(state, data) {
+ state.userInfo = data;
+ uni.setStorageSync("userInfo", data);
+ },
+ // 分销商信息
+ AGENT_INFO(state, data) {
+ state.agentInfo = data;
+ },
+ // 小程序订阅消息模板ids
+ MESSAGE_IDS(state, data) {
+ state.subscribeMessageIds = data;
+ },
+ USER_DATA(state, data) {
+ state.userData = data;
+ },
+ AUTH_TYPE(state, data) {
+ data ? uni.hideTabBar() : uni.showTabBar();
+ state.authType = data;
+ },
+
+ // 订阅消息
+ subscribeMessage(state, type) {
+ let arr = state.subscribeMessageIdsMap[type];
+ arr.length && uni.requestSubscribeMessage({
+ tmplIds: arr,
+ success: (res) => {
+ console.log(res);
+ },
+ fail: (err) => {
+ console.log(err);
+ }
+
+ });
+ },
+
+ // 解析订阅消息数据
+ formatMessage(state, messageIdsObj) {
+ // 各场景下用到的订阅模板
+ let typeMap = {
+ 'result': ['order_sended', 'wallet_change'], //支付成功
+ 'grouponResult': ['groupon_success', 'groupon_fail', 'order_sended'], //拼团支付成功后
+ 'aftersale': ['refund_agree', 'aftersale_change', 'wallet_change'], //点击售后
+ 'wallet': ['score_change', 'wallet_apply', 'wallet_change'], //提现提醒
+ 'store': ['store_order_new'], //门店新订单通知
+ 'storeApply': ['store_apply'] //门店申请通知
+ }
+ let idsMap = {}
+ Object.keys(typeMap).forEach(key => {
+ idsMap[key] = []
+ typeMap[key].forEach(item => {
+ if (messageIdsObj[item]) {
+ idsMap[key].push(messageIdsObj[item])
+ }
+ })
+ })
+ state.subscribeMessageIdsMap = idsMap
+ },
+}
+
+
+
+export default {
+ state,
+ mutations,
+ actions,
+ getters
+}
diff --git a/shopro/utils/sdk-h5.js b/shopro/utils/sdk-h5.js
new file mode 100644
index 0000000..9c2bcf9
--- /dev/null
+++ b/shopro/utils/sdk-h5.js
@@ -0,0 +1,585 @@
+//#ifdef H5
+/**
+ * 设置剪切板
+uni.setClipboardData({ data:'文字', success:function(data){}, fail:function(err){}, complete:function(res){} })
+
+获取剪贴板
+uni.getClipboardData({success:function(data){}, fail:function(err){}, complete:function(res){} })
+
+保存图片到系统相册
+uni.saveImageToPhotosAlbum({ filePath: res.tempFilePaths[0], success: function () { console.log('save success'); } })
+
+保存视频到系统相册
+uni.saveVideoToPhotosAlbum({ filePath: res.tempFilePath, success: function () { console.log('save success'); } });
+ * **/
+! function(t, e) {
+ try {
+ window.ClipboardJS = e();
+ } catch (e) {};
+ "object" == typeof exports && "object" == typeof module ? module.exports = e() : "function" == typeof define && define
+ .amd ? define([], e) : "object" == typeof exports ? exports.ClipboardJS = e() : t.ClipboardJS = e()
+}(this, function() {
+ return function(n) {
+ var o = {};
+
+ function r(t) {
+ if (o[t]) return o[t].exports;
+ var e = o[t] = {
+ i: t,
+ l: !1,
+ exports: {}
+ };
+ return n[t].call(e.exports, e, e.exports, r), e.l = !0, e.exports
+ }
+ return r.m = n, r.c = o, r.d = function(t, e, n) {
+ r.o(t, e) || Object.defineProperty(t, e, {
+ enumerable: !0,
+ get: n
+ })
+ }, r.r = function(t) {
+ "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, {
+ value: "Module"
+ }), Object.defineProperty(t, "__esModule", {
+ value: !0
+ })
+ }, r.t = function(e, t) {
+ if (1 & t && (e = r(e)), 8 & t) return e;
+ if (4 & t && "object" == typeof e && e && e.__esModule) return e;
+ var n = Object.create(null);
+ if (r.r(n), Object.defineProperty(n, "default", {
+ enumerable: !0,
+ value: e
+ }), 2 & t && "string" != typeof e)
+ for (var o in e) r.d(n, o, function(t) {
+ return e[t]
+ }.bind(null, o));
+ return n
+ }, r.n = function(t) {
+ var e = t && t.__esModule ? function() {
+ return t.default
+ } : function() {
+ return t
+ };
+ return r.d(e, "a", e), e
+ }, r.o = function(t, e) {
+ return Object.prototype.hasOwnProperty.call(t, e)
+ }, r.p = "", r(r.s = 0)
+ }([function(t, e, n) {
+ "use strict";
+ var r = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) {
+ return typeof t
+ } : function(t) {
+ return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" :
+ typeof t
+ },
+ i = function() {
+ function o(t, e) {
+ for (var n = 0; n < e.length; n++) {
+ var o = e[n];
+ o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(
+ t, o.key, o)
+ }
+ }
+ return function(t, e, n) {
+ return e && o(t.prototype, e), n && o(t, n), t
+ }
+ }(),
+ a = o(n(1)),
+ c = o(n(3)),
+ u = o(n(4));
+
+ function o(t) {
+ return t && t.__esModule ? t : {
+ default: t
+ }
+ }
+ var l = function(t) {
+ function o(t, e) {
+ ! function(t, e) {
+ if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function")
+ }(this, o);
+ var n = function(t, e) {
+ if (!t) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+ return !e || "object" != typeof e && "function" != typeof e ? t : e
+ }(this, (o.__proto__ || Object.getPrototypeOf(o)).call(this));
+ return n.resolveOptions(e), n.listenClick(t), n
+ }
+ return function(t, e) {
+ if ("function" != typeof e && null !== e) throw new TypeError(
+ "Super expression must either be null or a function, not " + typeof e);
+ t.prototype = Object.create(e && e.prototype, {
+ constructor: {
+ value: t,
+ enumerable: !1,
+ writable: !0,
+ configurable: !0
+ }
+ }), e && (Object.setPrototypeOf ? Object.setPrototypeOf(t, e) : t.__proto__ = e)
+ }(o, c.default), i(o, [{
+ key: "resolveOptions",
+ value: function() {
+ var t = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : {};
+ this.action = "function" == typeof t.action ? t.action : this.defaultAction, this.target = "function" ==
+ typeof t.target ? t.target : this.defaultTarget, this.text = "function" == typeof t.text ? t.text : this
+ .defaultText, this.container = "object" === r(t.container) ? t.container : document.body
+ }
+ }, {
+ key: "listenClick",
+ value: function(t) {
+ var e = this;
+ this.listener = (0, u.default)(t, "click", function(t) {
+ return e.onClick(t)
+ })
+ }
+ }, {
+ key: "onClick",
+ value: function(t) {
+ var e = t.delegateTarget || t.currentTarget;
+ this.clipboardAction && (this.clipboardAction = null), this.clipboardAction = new a.default({
+ action: this.action(e),
+ target: this.target(e),
+ text: this.text(e),
+ container: this.container,
+ trigger: e,
+ emitter: this
+ })
+ }
+ }, {
+ key: "defaultAction",
+ value: function(t) {
+ return s("action", t) || 'copy'
+ }
+ }, {
+ key: "defaultTarget",
+ value: function(t) {
+ var e = s("target", t);
+ if (e) {
+ return document.querySelector(e)
+ }
+ }
+ }, {
+ key: "defaultText",
+ value: function(t) {
+ return s("text", t) || this.text
+ }
+ }, {
+ key: "destroy",
+ value: function() {
+ this.listener.destroy(), this.clipboardAction && (this.clipboardAction.destroy(), this.clipboardAction =
+ null)
+ }
+ }], [{
+ key: "isSupported",
+ value: function() {
+ var t = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : ["copy", "cut"],
+ e = "string" == typeof t ? [t] : t,
+ n = !!document.queryCommandSupported;
+ return e.forEach(function(t) {
+ n = n && !!document.queryCommandSupported(t)
+ }), n
+ }
+ }]), o
+ }();
+
+ function s(t, e) {
+ var n = "data-clipboard-" + t;
+ let isFun = e && typeof e.hasAttribute === 'function';
+ if (isFun && e.hasAttribute(n)) {
+ return e.getAttribute(n)
+ }
+ }
+ t.exports = l
+ }, function(t, e, n) {
+ "use strict";
+ var o, r = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) {
+ return typeof t
+ } : function(t) {
+ return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" :
+ typeof t
+ },
+ i = function() {
+ function o(t, e) {
+ for (var n = 0; n < e.length; n++) {
+ var o = e[n];
+ o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(
+ t, o.key, o)
+ }
+ }
+ return function(t, e, n) {
+ return e && o(t.prototype, e), n && o(t, n), t
+ }
+ }(),
+ a = n(2),
+ c = (o = a) && o.__esModule ? o : {
+ default: o
+ };
+ var u = function() {
+ function e(t) {
+ ! function(t, e) {
+ if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function")
+ }(this, e), this.resolveOptions(t), this.initSelection()
+ }
+ return i(e, [{
+ key: "resolveOptions",
+ value: function() {
+ var t = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : {};
+ this.action = t.action, this.container = t.container, this.emitter = t.emitter, this.target = t.target,
+ this.text = t.text, this.trigger = t.trigger, this.selectedText = ""
+ }
+ }, {
+ key: "initSelection",
+ value: function() {
+ this.text ? this.selectFake() : this.target && this.selectTarget()
+ }
+ }, {
+ key: "selectFake",
+ value: function() {
+ var t = this,
+ e = "rtl" == document.documentElement.getAttribute("dir");
+ this.removeFake(), this.fakeHandlerCallback = function() {
+ return t.removeFake()
+ }, this.fakeHandler = this.container.addEventListener("click", this.fakeHandlerCallback) || !0, this.fakeElem =
+ document.createElement("textarea"), this.fakeElem.style.fontSize = "12pt", this.fakeElem.style.border =
+ "0", this.fakeElem.style.padding = "0", this.fakeElem.style.margin = "0", this.fakeElem.style.position =
+ "absolute", this.fakeElem.style[e ? "right" : "left"] = "-9999px";
+ var n = window.pageYOffset || document.documentElement.scrollTop;
+ this.fakeElem.style.top = n + "px", this.fakeElem.setAttribute("readonly", ""), this.fakeElem.value =
+ this.text, this.container.appendChild(this.fakeElem), this.selectedText = (0, c.default)(this.fakeElem),
+ this.copyText()
+ }
+ }, {
+ key: "removeFake",
+ value: function() {
+ this.fakeHandler && (this.container.removeEventListener("click", this.fakeHandlerCallback), this.fakeHandler =
+ null, this.fakeHandlerCallback = null), this.fakeElem && (this.container.removeChild(this.fakeElem),
+ this.fakeElem = null)
+ }
+ }, {
+ key: "selectTarget",
+ value: function() {
+ this.selectedText = (0, c.default)(this.target), this.copyText()
+ }
+ }, {
+ key: "copyText",
+ value: function() {
+ var e = void 0;
+ try {
+ e = document.execCommand(this.action)
+ } catch (t) {
+ e = !1
+ }
+ this.handleResult(e)
+ }
+ }, {
+ key: "handleResult",
+ value: function(t) {
+ this.emitter.emit(t ? "success" : "error", {
+ action: this.action,
+ text: this.selectedText,
+ trigger: this.trigger,
+ clearSelection: this.clearSelection.bind(this)
+ })
+ }
+ }, {
+ key: "clearSelection",
+ value: function() {
+ this.trigger && this.trigger.focus(), window.getSelection().removeAllRanges()
+ }
+ }, {
+ key: "destroy",
+ value: function() {
+ this.removeFake()
+ }
+ }, {
+ key: "action",
+ set: function() {
+ var t = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : "copy";
+ if (this._action = t, "copy" !== this._action && "cut" !== this._action) throw new Error(
+ 'Invalid "action" value, use either "copy" or "cut"')
+ },
+ get: function() {
+ return this._action
+ }
+ }, {
+ key: "target",
+ set: function(t) {
+ if (void 0 !== t) {
+ if (!t || "object" !== (void 0 === t ? "undefined" : r(t)) || 1 !== t.nodeType) throw new Error(
+ 'Invalid "target" value, use a valid Element');
+ if ("copy" === this.action && t.hasAttribute("disabled")) throw new Error(
+ 'Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');
+ if ("cut" === this.action && (t.hasAttribute("readonly") || t.hasAttribute("disabled"))) throw new Error(
+ 'Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes'
+ );
+ this._target = t
+ }
+ },
+ get: function() {
+ return this._target
+ }
+ }]), e
+ }();
+ t.exports = u
+ }, function(t, e) {
+ t.exports = function(t) {
+ var e;
+ if ("SELECT" === t.nodeName) t.focus(), e = t.value;
+ else if ("INPUT" === t.nodeName || "TEXTAREA" === t.nodeName) {
+ var n = t.hasAttribute("readonly");
+ n || t.setAttribute("readonly", ""), t.select(), t.setSelectionRange(0, t.value.length), n || t.removeAttribute(
+ "readonly"), e = t.value
+ } else {
+ t.hasAttribute("contenteditable") && t.focus();
+ var o = window.getSelection(),
+ r = document.createRange();
+ r.selectNodeContents(t), o.removeAllRanges(), o.addRange(r), e = o.toString()
+ }
+ return e
+ }
+ }, function(t, e) {
+ function n() {}
+ n.prototype = {
+ on: function(t, e, n) {
+ var o = this.e || (this.e = {});
+ return (o[t] || (o[t] = [])).push({
+ fn: e,
+ ctx: n
+ }), this
+ },
+ once: function(t, e, n) {
+ var o = this;
+
+ function r() {
+ o.off(t, r), e.apply(n, arguments)
+ }
+ return r._ = e, this.on(t, r, n)
+ },
+ emit: function(t) {
+ for (var e = [].slice.call(arguments, 1), n = ((this.e || (this.e = {}))[t] || []).slice(), o = 0, r = n.length; o <
+ r; o++) n[o].fn.apply(n[o].ctx, e);
+ return this
+ },
+ off: function(t, e) {
+ var n = this.e || (this.e = {}),
+ o = n[t],
+ r = [];
+ if (o && e)
+ for (var i = 0, a = o.length; i < a; i++) o[i].fn !== e && o[i].fn._ !== e && r.push(o[i]);
+ return r.length ? n[t] = r : delete n[t], this
+ }
+ }, t.exports = n
+ }, function(t, e, n) {
+ var d = n(5),
+ h = n(6);
+ t.exports = function(t, e, n) {
+ if (!t && !e && !n) throw new Error("Missing required arguments");
+ if (!d.string(e)) throw new TypeError("Second argument must be a String");
+ if (!d.fn(n)) throw new TypeError("Third argument must be a Function");
+ if (d.node(t)) return s = e, f = n, (l = t).addEventListener(s, f), {
+ destroy: function() {
+ l.removeEventListener(s, f)
+ }
+ };
+ if (d.nodeList(t)) return a = t, c = e, u = n, Array.prototype.forEach.call(a, function(t) {
+ t.addEventListener(c, u)
+ }), {
+ destroy: function() {
+ Array.prototype.forEach.call(a, function(t) {
+ t.removeEventListener(c, u)
+ })
+ }
+ };
+ if (d.string(t)) return o = t, r = e, i = n, h(document.body, o, r, i);
+ throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList");
+ var o, r, i, a, c, u, l, s, f
+ }
+ }, function(t, n) {
+ n.node = function(t) {
+ return void 0 !== t && t instanceof HTMLElement && 1 === t.nodeType
+ }, n.nodeList = function(t) {
+ var e = Object.prototype.toString.call(t);
+ return void 0 !== t && ("[object NodeList]" === e || "[object HTMLCollection]" === e) && "length" in t && (0 ===
+ t.length || n.node(t[0]))
+ }, n.string = function(t) {
+ return "string" == typeof t || t instanceof String
+ }, n.fn = function(t) {
+ return "[object Function]" === Object.prototype.toString.call(t)
+ }
+ }, function(t, e, n) {
+ var a = n(7);
+
+ function i(t, e, n, o, r) {
+ var i = function(e, n, t, o) {
+ return function(t) {
+ t.delegateTarget = a(t.target, n), t.delegateTarget && o.call(e, t)
+ }
+ }.apply(this, arguments);
+ return t.addEventListener(n, i, r), {
+ destroy: function() {
+ t.removeEventListener(n, i, r)
+ }
+ }
+ }
+ t.exports = function(t, e, n, o, r) {
+ return "function" == typeof t.addEventListener ? i.apply(null, arguments) : "function" == typeof n ? i.bind(
+ null, document).apply(null, arguments) : ("string" == typeof t && (t = document.querySelectorAll(t)), Array.prototype
+ .map.call(t, function(t) {
+ return i(t, e, n, o, r)
+ }))
+ }
+ }, function(t, e) {
+ if ("undefined" != typeof Element && !Element.prototype.matches) {
+ var n = Element.prototype;
+ n.matches = n.matchesSelector || n.mozMatchesSelector || n.msMatchesSelector || n.oMatchesSelector || n.webkitMatchesSelector
+ }
+ t.exports = function(t, e) {
+ for (; t && 9 !== t.nodeType;) {
+ if ("function" == typeof t.matches && t.matches(e)) return t;
+ t = t.parentNode
+ }
+ }
+ }])
+});
+let Types = {
+ isFunction: function(obj) {
+ var type = Object.prototype.toString.call(obj)
+ return type == '[object Function]'
+ },
+ isObject: function(obj) {
+ var type = Object.prototype.toString.call(obj)
+ return type == '[object Object]'
+ },
+ isString: function(obj) {
+ var type = Object.prototype.toString.call(obj)
+ return type == '[object String]'
+ }
+}
+uni.setClipboardData = function(options) {
+ let emptyFun = function() {}
+ let config = {
+ data: null,
+ event: null,
+ success: emptyFun,
+ fail: emptyFun,
+ complete: emptyFun
+ }
+ if (options && Types.isObject(options)) {
+ config = Object.assign({}, config, options)
+ }
+ if (options && Types.isString(options)) {
+ config = Object.assign({}, config, {
+ data: options
+ })
+ }
+ let data = config.data
+ let success = config.success || emptyFun
+ let fail = config.fail || emptyFun
+ let complete = config.complete || emptyFun
+ let e = config.event || window.event || {}
+ let cb = new ClipboardJS('.null', {
+ text: () => data
+ })
+ cb.on('success', function(res) {
+ window.__clipboard__ = data;
+ success && Types.isFunction(success) && success({
+ data: res.text
+ })
+ complete && Types.isFunction(complete) && complete()
+ cb.off('error')
+ cb.off('success')
+ cb.destroy()
+ })
+ cb.on('error', function(err) {
+ fail && Types.isFunction(fail) && fail(err)
+ complete && Types.isFunction(complete) && complete()
+ cb.off('error')
+ cb.off('success')
+ cb.destroy()
+ })
+ cb.onClick(e)
+};
+uni.getClipboardData = function(options) {
+ let emptyFun = function() {}
+ let config = {
+ data: null,
+ event: null,
+ success: emptyFun,
+ fail: emptyFun,
+ complete: emptyFun
+ }
+ if (options && Types.isObject(options)) {
+ config = Object.assign({}, config, options)
+ }
+ let success = config.success || emptyFun
+ let fail = config.fail || emptyFun
+ let complete = config.complete || emptyFun
+ if (window.__clipboard__ !== undefined) {
+ success && Types.isFunction(success) && success({
+ data: window.__clipboard__
+ })
+ } else {
+ fail && Types.isFunction(fail) && fail({
+ data: null
+ })
+ }
+ complete && Types.isFunction(complete) && complete()
+};
+
+function fileDownLoad(data) {
+ var linkElement = document.createElement('a')
+ linkElement.setAttribute('href', data.blob)
+ linkElement.setAttribute('downLoad', data.name)
+ linkElement.click()
+}
+uni.saveImageToPhotosAlbum = uni.saveVideoToPhotosAlbum = function(options) {
+ let emptyFun = function() {}
+ let config = {
+ filePath: null,
+ success: emptyFun,
+ fail: emptyFun,
+ complete: emptyFun
+ }
+ if (options && Types.isObject(options)) {
+ config = Object.assign({}, config, options)
+ }
+ if (options && Types.isString(options)) {
+ config = Object.assign({}, config, {
+ filePath: options
+ })
+ }
+ let filePath = config.filePath
+ let success = config.success || emptyFun
+ let fail = config.fail || emptyFun
+ let complete = config.complete || emptyFun
+ if (!filePath) {
+ fail && Types.isFunction(fail) && fail({
+ msg: 'no File'
+ })
+ complete && Types.isFunction(complete) && complete()
+ return
+ }
+ let names = filePath.split('/')
+ let name = names[names.length - 1]
+ uni.downloadFile({
+ url: filePath,
+ success: function(res) {
+ let tempFilePath = res.tempFilePath
+ fileDownLoad({
+ name: name,
+ blob: tempFilePath
+ })
+ success && Types.isFunction(success) && success({
+ filePath: filePath
+ })
+ },
+ fail: function(err) {
+ fail && Types.isFunction(fail) && fail({
+ msg: err
+ })
+ },
+ complete: function() {
+ complete && Types.isFunction(complete) && complete()
+ }
+ })
+}
+//#endif
diff --git a/shopro/utils/tools.js b/shopro/utils/tools.js
new file mode 100644
index 0000000..d5a8de4
--- /dev/null
+++ b/shopro/utils/tools.js
@@ -0,0 +1,140 @@
+import {
+ API_URL
+} from '@/env'
+import {
+ router
+} from '@/shopro/router'
+export default {
+
+ /**
+ * 跳转再封装,主要是为了兼容外链。
+ * @param {String} path - 跳转路径
+ * @param {isTabbar} isTabbar - 是否是底部导航
+ */
+ routerTo(path, isTabbar) {
+ if (path) {
+ // 是否跳转外部链接
+ if (~path.indexOf('http') || ~path.indexOf('www')) {
+ // #ifdef H5
+ window.location = path;
+ // #endif
+ // #ifndef H5
+ router.push({
+ path: '/pages/public/webview',
+ query: {
+ 'webviewPath': path
+ }
+ })
+ // #endif
+ return false
+ }
+ if (isTabbar) {
+ router.replaceAll(path)
+ } else {
+ path.includes('/pages/index') && !path.includes('/pages/index/view') ? router.replaceAll(path) : router
+ .push(path)
+ }
+
+ } else {
+ console.log(`%cerr:没有填写跳转路径`, 'color:green;background:yellow');
+ }
+ },
+ /**
+ * 图片处理-预览图片
+ * @param {Array} urls - 图片列表
+ * @param {Number} current - 首个预览下标
+ */
+ previewImage(urls = [], current = 0) {
+ uni.previewImage({
+ urls: urls,
+ current: current,
+ indicator: 'default',
+ loop: true,
+ fail(err) {
+ console.log('previewImage出错', urls, err)
+ },
+ })
+ },
+
+ /**
+ * 数据分组
+ * @param {Array} oArr - 原数组列表
+ * @param {Number} length - 单个数组长度
+ * @return {Array} arr - 分组后的新数组
+ */
+ splitData(oArr = [], length = 1) {
+ let arr = [];
+ let minArr = [];
+ oArr.forEach(c => {
+ if (minArr.length === length) {
+ minArr = [];
+ }
+ if (minArr.length === 0) {
+ arr.push(minArr);
+ }
+ minArr.push(c);
+ });
+
+ return arr;
+ },
+
+ /**
+ * 剩余时间格式化
+ * @param {Number} t - 剩余多少秒
+ * @return {Object} format - 格式后的天时分秒对象
+ */
+ format(t) {
+ let format = {
+ d: '00',
+ h: '00',
+ m: '00',
+ s: '00'
+ };
+ if (t > 0) {
+ let d = Math.floor(t / 86400);
+ let h = Math.floor((t / 3600) % 24);
+ let m = Math.floor((t / 60) % 60);
+ let s = Math.floor(t % 60);
+ format.d = d < 10 ? '0' + d : d;
+ format.h = h < 10 ? '0' + h : h;
+ format.m = m < 10 ? '0' + m : m;
+ format.s = s < 10 ? '0' + s : s;
+ }
+ return format;
+ },
+
+ /**
+ * 打电话
+ * @param {String} phoneNumber - 数字字符串
+ */
+ callPhone(phoneNumber = '') {
+ let num = phoneNumber.toString()
+ uni.makePhoneCall({
+ phoneNumber: num,
+ fail(err) {
+ console.log('makePhoneCall出错', err)
+ },
+ });
+ },
+
+ /**
+ * 微信头像
+ * @param {String} url -图片地址
+ */
+ checkMPUrl(url) {
+ // #ifdef MP
+ if (
+ url.substring(0, 4) === 'http' &&
+ url.substring(0, 5) !== 'https' &&
+ url.substring(0, 12) !== 'http://store' &&
+ url.substring(0, 10) !== 'http://tmp' &&
+ url.substring(0, 10) !== 'http://usr'
+ ) {
+ url = 'https' + url.substring(4, url.length);
+ }
+ // #endif
+ return url;
+ },
+
+
+}
diff --git a/shopro/validate/form.js b/shopro/validate/form.js
new file mode 100644
index 0000000..0568d3d
--- /dev/null
+++ b/shopro/validate/form.js
@@ -0,0 +1,112 @@
+/**
+ * Validate v1.0.0 通用验证
+ */
+import test from '@/uview-ui/libs/function/test.js'
+export default {
+
+ // 手机号
+ mobile: [{
+ required: true,
+ message: '请输入手机号',
+ trigger: ['change', 'blur']
+ },
+ {
+ validator: (rule, value, callback) => {
+ return test.mobile(value);
+ },
+ message: '手机号码格式不正确',
+ trigger: ['change', 'blur']
+ }
+ ],
+ // 账户
+ account: [{
+ required: true,
+ min: 5,
+ message: '请输入账号',
+ trigger: ['change', 'blur']
+ }],
+
+ // 短信验证码
+ code: [{
+ required: true,
+ min: 4,
+ message: '请输入验证码',
+ trigger: ['change', 'blur']
+ }],
+
+ // 密码
+ password: [{
+ required: true,
+ message: '请输入密码',
+ trigger: ['change', 'blur']
+ },
+ {
+ pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]+\S{5,12}$/,
+ message: '需同时含有字母和数字,长度在6-12之间',
+ trigger: ['change', 'blur']
+ }
+ ],
+
+ // 真实姓名
+ realName: [{
+ required: true,
+ message: '请输入持卡人姓名',
+ trigger: ['change', 'blur']
+ },
+ {
+ validator: (rule, value, callback) => {
+ return test.chinese(value);
+ },
+ message: '请输入汉字',
+ trigger: ['change', 'blur']
+ }
+ ],
+
+ // 开户行
+ bankName: [{
+ required: true,
+ message: '请输入开户行',
+ trigger: ['change', 'blur']
+ },
+ {
+ validator: (rule, value, callback) => {
+ return test.chinese(value);
+ },
+ message: '请输入汉字',
+ trigger: ['change', 'blur']
+ }
+ ],
+
+ // 银行卡号
+ bankCode: [{
+ required: true,
+ message: '请输入银行卡号',
+ trigger: ['change', 'blur']
+ },
+ {
+ validator: (rule, value, callback) => {
+ return test.number(value);
+ },
+ message: '请输入正确账号',
+ trigger: ['change', 'blur']
+ }
+ ],
+
+ // 支付宝账号
+ alipayAccount: [{
+ required: true,
+ message: '请输入支付账号',
+ trigger: ['change', 'blur']
+ },
+ {
+ validator: (rule, value, callback) => {
+ let isRange = test.rangeLength(value, [6, 30]);
+ let isAsterisk = test.contains(value, '*');
+
+ return isRange && !isAsterisk;
+ },
+ message: '请输入正确账号',
+ trigger: ['change', 'blur']
+ }
+ ],
+}
diff --git a/shopro/wechat/sdk.js b/shopro/wechat/sdk.js
new file mode 100644
index 0000000..8ddbe79
--- /dev/null
+++ b/shopro/wechat/sdk.js
@@ -0,0 +1,182 @@
+var jweixin = require("jweixin-module");
+import http from "@/shopro/request/index";
+import $platform from "@/shopro/platform";
+export default {
+ //判断是否在微信中
+ isWechat() {
+ var ua = window.navigator.userAgent.toLowerCase();
+ if (ua.match(/micromessenger/i) == "micromessenger") {
+ return true;
+ } else {
+ return false;
+ }
+ },
+ // 鉴权页面
+ initJssdk(callback) {
+ http("common.wxJssdk", {
+ uri: encodeURIComponent($platform.entry())
+ }).then(res => {
+ jweixin.config({
+ debug: res.data.debug,
+ appId: res.data.appId,
+ timestamp: res.data.timestamp,
+ nonceStr: res.data.nonceStr,
+ signature: res.data.signature,
+ jsApiList: res.data.jsApiList,
+ openTagList: res.data.openTagList
+ });
+ if (callback) {
+ callback(res.data);
+ }
+ });
+ },
+
+ //在需要定位页面调用
+ getLocation(callback) {
+ this.isWechat() && this.initJssdk(function(res) {
+ jweixin.ready(function() {
+ jweixin.getLocation({
+ type: "gcj02", // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
+ success: function(res) {
+ callback(res);
+ },
+ fail: function(res) {
+ console.log("%c微信H5sdk,getLocation失败:",
+ "color:green;background:yellow");
+ },
+ });
+ });
+ });
+ },
+
+ //获取微信收货地址
+ openAddress(callback) {
+ this.isWechat() && this.initJssdk(function(res) {
+ jweixin.ready(function() {
+ jweixin.openAddress({
+ success: function(res) {
+ callback(res);
+ },
+ fail: function(err) {
+ console.log("%c微信H5sdk,openAddress失败:",
+ "color:green;background:yellow");
+ },
+ complete: function(msg) {}
+ });
+ });
+ });
+ },
+
+ // 微信扫码
+ scanQRCode(callback) {
+ this.isWechat() && this.initJssdk(function(res) {
+ jweixin.ready(function() {
+ jweixin.scanQRCode({
+ needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
+ scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
+ success: function(res) {
+ callback(res);
+ },
+ fail: function(res) {
+ console.log("%c微信H5sdk,scanQRCode失败:",
+ "color:green;background:yellow");
+ },
+ });
+ });
+ });
+ },
+
+ // 微信分享
+ share(data, callback) {
+ this.isWechat() && this.initJssdk(function(res) {
+ jweixin.ready(function() {
+ var shareData = {
+ title: data.title,
+ desc: data.desc,
+ link: data.path,
+ imgUrl: data.image,
+ success: function(res) {
+ callback(res);
+ // 分享后的一些操作,比如分享统计等等
+ },
+ cancel: function(res) {}
+ };
+
+ jweixin.updateAppMessageShareData(shareData); //新版接口
+ //分享到朋友圈接口
+ // jweixin.updateTimelineShareData(shareData);
+
+
+ });
+ });
+
+ },
+
+
+ // 打开坐标位置
+ openLocation(data, callback) { //打开位置
+ this.isWechat() && this.initJssdk(function(res) {
+ jweixin.ready(function() {
+ jweixin.openLocation({ //根据传入的坐标打开地图
+ latitude: data.latitude,
+ longitude: data.longitude
+ });
+ });
+ });
+ },
+ // 选择图片
+ chooseImage(callback) { //选择图片
+ this.isWechat() && this.initJssdk(function(res) {
+ jweixin.ready(function() {
+ jweixin.chooseImage({
+ count: 1,
+ sizeType: ["compressed"],
+ sourceType: ["album"],
+ success: function(rs) {
+ callback(rs);
+ }
+ });
+ });
+ });
+ },
+
+ //微信支付
+ wxpay(data, callback) {
+ let that = this;
+ this.isWechat() && this.initJssdk(function(res) {
+ jweixin.ready(function() {
+
+ WeixinJSBridge.invoke('getBrandWCPayRequest', {
+ "appId": data.appId, //公众号ID,由商户传入
+ "timeStamp": data.timeStamp, //时间戳,自1970年以来的秒数
+ "nonceStr": data.nonceStr, //随机串
+ "package": data.package,
+ "signType": data.signType, //微信签名方式:
+ "paySign": data.paySign,
+ },
+ function(res) {
+ callback(res)
+ });
+
+ // jweixin.chooseWXPay({
+ // timestamp: data.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
+ // nonceStr: data.nonceStr, // 支付签名随机串,不长于 32 位
+ // package: data.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
+ // signType: data.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
+ // paySign: data.paySign, // 支付签名
+ // success: function(res) {
+ // callback(res);
+ // },
+ // fail: function(res) {
+ // console.log("%c微信H5sdk,chooseWXPay失败:",
+ // "color:green;background:yellow");
+ // callback(res);
+ // },
+ // cancel: function(res) {
+
+ // },
+ // });
+ });
+ });
+ }
+};
diff --git a/shopro/wechat/wechat.js b/shopro/wechat/wechat.js
new file mode 100644
index 0000000..d0d6e9f
--- /dev/null
+++ b/shopro/wechat/wechat.js
@@ -0,0 +1,239 @@
+/**
+ * Wechat v1.2.1
+ * @Class Wechat
+ * @description shopro-wechat 1.2.1 wehcat第三方登录组件
+ * @Author lidongtony
+ * @Date 2022-12-12
+ * @Email lidongtony@qq.com
+ */
+import api from "@/shopro/request/index";
+import $platform from "@/shopro/platform";
+import store from "@/shopro/store";
+import {
+ API_URL
+} from "@/env";
+
+export default {
+ eventMap(event) {
+ let map = "";
+ switch (event) {
+ case "login":
+ map = "登录中...";
+ break;
+ case "refresh":
+ map = "更新中...";
+ break;
+ case "bind":
+ map = "绑定中...";
+ break;
+ }
+ return map;
+ },
+
+ async login(payload) {
+ let token = "";
+ // #ifdef MP-WEIXIN
+ token = await this.wxMiniProgramOauth("login", payload);
+ return token;
+ // #endif
+ // #ifdef H5
+ this.wxOfficialAccountOauth("login");
+ // #endif
+ // #ifdef APP-PLUS
+ token = await this.wxOpenPlatformOauth("login");
+ return token;
+ // #endif
+ },
+ async refresh() {
+ let token = "";
+ // #ifdef MP-WEIXIN
+ token = await this.wxMiniProgramOauth("refresh");
+ return token;
+ // #endif
+ // #ifdef H5
+ this.wxOfficialAccountOauth("refresh");
+ // #endif
+ // #ifdef APP-PLUS
+ token = await this.wxOpenPlatformOauth("refresh");
+ return token;
+ // #endif
+ },
+ async bind(payload) {
+ let token = "";
+ // #ifdef MP-WEIXIN
+ token = await this.wxMiniProgramOauth("bind", payload);
+ return token;
+ // #endif
+ // #ifdef H5
+ this.wxOfficialAccountOauth("bind");
+ // #endif
+ // #ifdef APP-PLUS
+ token = await this.wxOpenPlatformOauth("bind");
+ return token;
+ // #endif
+ },
+
+ // #ifdef H5
+ // 微信公众号网页登录&刷新头像昵称&绑定
+ wxOfficialAccountOauth(event = "login") {
+ if ($platform.get() !== "wxOfficialAccount") {
+ uni.showToast({
+ title: "请在微信浏览器中打开",
+ icon: "none"
+ });
+ throw false;
+ }
+ let host = $platform.host();
+ let payloadObject = {
+ host: host,
+ event,
+ token: (event !== "login" && store.getters.isLogin) ? uni.getStorageSync("token") : ""
+ };
+ let payload = encodeURIComponent(JSON.stringify(payloadObject));
+ let redirect_uri = encodeURIComponent(`${API_URL}user/wxOfficialAccountOauth?payload=${payload}`);
+ let oauthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + store.getters.initWechat.appid +
+ `&redirect_uri=${redirect_uri}&response_type=code&scope=snsapi_userinfo&state=1`;
+ uni.setStorageSync("lastPage", window.location.href);
+ window.location = oauthUrl;
+ },
+
+ // 微信公众号网页静默登录:临时登录获取OpenId 不入库不绑定用户
+ wxOfficialAccountBaseLogin() {
+ let state = encodeURIComponent(window.location.href);
+ window.location = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + store.getters.initWechat
+ .appid +
+ `&redirect_uri=${API_URL}user/wxOfficialAccountBaseLogin&response_type=code&scope=snsapi_base&state=${state}`;
+ throw "stop";
+ },
+ // #endif
+
+ // #ifdef APP-PLUS
+ // 微信开放平台登录
+ async wxOpenPlatformOauth(event = "login") {
+ let that = this;
+ const loginResult = await uni.login({
+ provider: 'weixin',
+ onlyAuthorize: true,
+ });
+ if (loginRes.errMsg !== 'login:ok') {
+ uni.showToast({
+ title: loginRes.errMsg,
+ icon: 'none',
+ });
+ return Promise.reject('');
+ }
+ const authResult = loginRes.authResult;
+ const res = await api("user.wxOpenPlatformOauth", {
+ authResult,
+ event
+ }, that.eventMap(event));
+ if (res.code === 1) {
+ return Promise.resolve(res.data.token);
+ } else {
+ uni.showToast({
+ title: res.msg,
+ icon: 'none',
+ });
+ }
+ return Promis.reject('');
+ },
+ // #endif
+
+ // #ifdef MP-WEIXIN
+ // 微信小程序静默登录
+ async getWxMiniProgramSessionKey(autoLogin = true) {
+ const loginResult = await uni.login();
+ if (loginResult[1].errMsg !== 'login:ok') {
+ uni.showToast({
+ title: loginResult[1].errMsg,
+ icon: "none"
+ });
+ return Promise.reject(loginResult[1].errMsg);
+ }
+
+ const res = await api("user.getWxMiniProgramSessionKey", {
+ code: loginResult[1].code,
+ autoLogin: autoLogin
+ });
+ if (res.code === 1) {
+ uni.setStorageSync("session_id", res
+ .data.session_id);
+ if (autoLogin) {
+ if (res.data.token) {
+ return Promise.resolve(res.data.token);
+ } else {
+ return Promise.resolve('');
+ }
+ }
+ return Promise.resolve(res.data.session_id);
+ } else {
+ return Promise.reject(res.msg);
+ }
+
+ },
+
+ // 微信小程序获取用户手机号登录
+ async wxMiniProgramOauth(event = "login", payload) {
+ let that = this;
+ uni.showLoading({
+ title: that.eventMap(event)
+ });
+ if (payload.detail.errMsg !== 'getPhoneNumber:ok') {
+ uni.showToast({
+ title: payload.detail.errMsg,
+ icon: "none"
+ });
+ return Promise.reject(payload.detail.errMsg);
+ }
+
+ const res = await api("user.wxMiniProgramOauth", {
+ event,
+ code: payload.detail.code,
+ iv: payload.detail.iv,
+ encryptedData: payload.detail.encryptedData,
+ session_id: uni.getStorageSync("session_id"),
+ });
+
+ if (res.code === 1) {
+ return Promise.resolve(res.data.token);
+ } else {
+ uni.removeStorageSync("session_id");
+ that.getWxMiniProgramSessionKey(false);
+ return Promise.resolve(false);
+ }
+ },
+
+ // 小程序更新
+ checkMiniProgramUpdate() {
+ if (uni.canIUse("getUpdateManager")) {
+ const updateManager = uni.getUpdateManager();
+ updateManager.onCheckForUpdate(function (res) {
+ // 请求完新版本信息的回调
+ if (res.hasUpdate) {
+ updateManager.onUpdateReady(function () {
+ uni.showModal({
+ title: "更新提示",
+ content: "新版本已经准备好,是否重启应用?",
+ success: function (res) {
+ if (res.confirm) {
+ // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
+ updateManager.applyUpdate();
+ }
+ }
+ });
+ });
+ updateManager.onUpdateFailed(function () {
+ // 新的版本下载失败
+ uni.showModal({
+ title: "已经有新版本了哟~",
+ content: "新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~"
+ });
+ });
+ }
+ });
+ }
+ },
+ // #endif
+
+
+};
diff --git a/static/common/js/touch-emulator.js b/static/common/js/touch-emulator.js
new file mode 100644
index 0000000..9632413
--- /dev/null
+++ b/static/common/js/touch-emulator.js
@@ -0,0 +1,363 @@
+(function(window, document, exportName, undefined) {
+ "use strict";
+
+ var isMultiTouch = false;
+ var multiTouchStartPos;
+ var eventTarget;
+ var touchElements = {};
+
+ // polyfills
+ if(!document.createTouch) {
+ document.createTouch = function(view, target, identifier, pageX, pageY, screenX, screenY, clientX, clientY) {
+ // auto set
+ if(clientX == undefined || clientY == undefined) {
+ clientX = pageX - window.pageXOffset;
+ clientY = pageY - window.pageYOffset;
+ }
+
+ return new Touch(target, identifier, {
+ pageX: pageX,
+ pageY: pageY,
+ screenX: screenX,
+ screenY: screenY,
+ clientX: clientX,
+ clientY: clientY
+ });
+ };
+ }
+
+ if(!document.createTouchList) {
+ document.createTouchList = function() {
+ var touchList = new TouchList();
+ for (var i = 0; i < arguments.length; i++) {
+ touchList[i] = arguments[i];
+ }
+ touchList.length = arguments.length;
+ return touchList;
+ };
+ }
+
+ /**
+ * create an touch point
+ * @constructor
+ * @param target
+ * @param identifier
+ * @param pos
+ * @param deltaX
+ * @param deltaY
+ * @returns {Object} touchPoint
+ */
+ function Touch(target, identifier, pos, deltaX, deltaY) {
+ deltaX = deltaX || 0;
+ deltaY = deltaY || 0;
+
+ this.identifier = identifier;
+ this.target = target;
+ this.clientX = pos.clientX + deltaX;
+ this.clientY = pos.clientY + deltaY;
+ this.screenX = pos.screenX + deltaX;
+ this.screenY = pos.screenY + deltaY;
+ this.pageX = pos.pageX + deltaX;
+ this.pageY = pos.pageY + deltaY;
+ }
+
+ /**
+ * create empty touchlist with the methods
+ * @constructor
+ * @returns touchList
+ */
+ function TouchList() {
+ var touchList = [];
+
+ touchList.item = function(index) {
+ return this[index] || null;
+ };
+
+ // specified by Mozilla
+ touchList.identifiedTouch = function(id) {
+ return this[id + 1] || null;
+ };
+
+ return touchList;
+ }
+
+
+ /**
+ * Simple trick to fake touch event support
+ * this is enough for most libraries like Modernizr and Hammer
+ */
+ function fakeTouchSupport() {
+ var objs = [window, document.documentElement];
+ var props = ['ontouchstart', 'ontouchmove', 'ontouchcancel', 'ontouchend'];
+
+ for(var o=0; o 2; // pointer events
+ }
+
+ /**
+ * disable mouseevents on the page
+ * @param ev
+ */
+ function preventMouseEvents(ev) {
+ // 注释启用默认事件
+ // ev.preventDefault();
+ // ev.stopPropagation();
+ }
+
+ /**
+ * only trigger touches when the left mousebutton has been pressed
+ * @param touchType
+ * @returns {Function}
+ */
+ function onMouse(touchType) {
+ return function(ev) {
+ // prevent mouse events
+ preventMouseEvents(ev);
+
+ if (ev.which !== 1) {
+ return;
+ }
+
+ // The EventTarget on which the touch point started when it was first placed on the surface,
+ // even if the touch point has since moved outside the interactive area of that element.
+ // also, when the target doesnt exist anymore, we update it
+ if (ev.type == 'mousedown' || !eventTarget || (eventTarget && !eventTarget.dispatchEvent)) {
+ eventTarget = ev.target;
+ }
+
+ // shiftKey has been lost, so trigger a touchend
+ if (isMultiTouch && !ev.shiftKey) {
+ triggerTouch('touchend', ev);
+ isMultiTouch = false;
+ }
+
+ triggerTouch(touchType, ev);
+
+ // we're entering the multi-touch mode!
+ if (!isMultiTouch && ev.shiftKey) {
+ isMultiTouch = true;
+ multiTouchStartPos = {
+ pageX: ev.pageX,
+ pageY: ev.pageY,
+ clientX: ev.clientX,
+ clientY: ev.clientY,
+ screenX: ev.screenX,
+ screenY: ev.screenY
+ };
+ triggerTouch('touchstart', ev);
+ }
+
+ // reset
+ if (ev.type == 'mouseup') {
+ multiTouchStartPos = null;
+ isMultiTouch = false;
+ eventTarget = null;
+ }
+ }
+ }
+
+ /**
+ * trigger a touch event
+ * @param eventName
+ * @param mouseEv
+ */
+ function triggerTouch(eventName, mouseEv) {
+ var touchEvent = document.createEvent('Event');
+ touchEvent.initEvent(eventName, true, true);
+
+ touchEvent.altKey = mouseEv.altKey;
+ touchEvent.ctrlKey = mouseEv.ctrlKey;
+ touchEvent.metaKey = mouseEv.metaKey;
+ touchEvent.shiftKey = mouseEv.shiftKey;
+
+ touchEvent.touches = getActiveTouches(mouseEv, eventName);
+ touchEvent.targetTouches = getActiveTouches(mouseEv, eventName);
+ touchEvent.changedTouches = getChangedTouches(mouseEv, eventName);
+
+ eventTarget.dispatchEvent(touchEvent);
+ }
+
+ /**
+ * create a touchList based on the mouse event
+ * @param mouseEv
+ * @returns {TouchList}
+ */
+ function createTouchList(mouseEv) {
+ var touchList = new TouchList();
+
+ if (isMultiTouch) {
+ var f = TouchEmulator.multiTouchOffset;
+ var deltaX = multiTouchStartPos.pageX - mouseEv.pageX;
+ var deltaY = multiTouchStartPos.pageY - mouseEv.pageY;
+
+ touchList.push(new Touch(eventTarget, 1, multiTouchStartPos, (deltaX*-1) - f, (deltaY*-1) + f));
+ touchList.push(new Touch(eventTarget, 2, multiTouchStartPos, deltaX+f, deltaY-f));
+ } else {
+ touchList.push(new Touch(eventTarget, 1, mouseEv, 0, 0));
+ }
+
+ return touchList;
+ }
+
+ /**
+ * receive all active touches
+ * @param mouseEv
+ * @returns {TouchList}
+ */
+ function getActiveTouches(mouseEv, eventName) {
+ // empty list
+ if (mouseEv.type == 'mouseup') {
+ return new TouchList();
+ }
+
+ var touchList = createTouchList(mouseEv);
+ if(isMultiTouch && mouseEv.type != 'mouseup' && eventName == 'touchend') {
+ touchList.splice(1, 1);
+ }
+ return touchList;
+ }
+
+ /**
+ * receive a filtered set of touches with only the changed pointers
+ * @param mouseEv
+ * @param eventName
+ * @returns {TouchList}
+ */
+ function getChangedTouches(mouseEv, eventName) {
+ var touchList = createTouchList(mouseEv);
+
+ // we only want to return the added/removed item on multitouch
+ // which is the second pointer, so remove the first pointer from the touchList
+ //
+ // but when the mouseEv.type is mouseup, we want to send all touches because then
+ // no new input will be possible
+ if(isMultiTouch && mouseEv.type != 'mouseup' &&
+ (eventName == 'touchstart' || eventName == 'touchend')) {
+ touchList.splice(0, 1);
+ }
+
+ return touchList;
+ }
+
+ /**
+ * show the touchpoints on the screen
+ */
+ function showTouches(ev) {
+ var touch, i, el, styles;
+
+ // first all visible touches
+ for(i = 0; i < ev.touches.length; i++) {
+ touch = ev.touches[i];
+ el = touchElements[touch.identifier];
+ if(!el) {
+ el = touchElements[touch.identifier] = document.createElement("div");
+ document.body.appendChild(el);
+ }
+
+ styles = TouchEmulator.template(touch);
+ for(var prop in styles) {
+ el.style[prop] = styles[prop];
+ }
+ }
+
+ // remove all ended touches
+ if(ev.type == 'touchend' || ev.type == 'touchcancel') {
+ for(i = 0; i < ev.changedTouches.length; i++) {
+ touch = ev.changedTouches[i];
+ el = touchElements[touch.identifier];
+ if(el) {
+ el.parentNode.removeChild(el);
+ delete touchElements[touch.identifier];
+ }
+ }
+ }
+ }
+
+ /**
+ * TouchEmulator initializer
+ */
+ function TouchEmulator() {
+ if (hasTouchSupport()) {
+ return;
+ }
+
+ fakeTouchSupport();
+
+ window.addEventListener("mousedown", onMouse('touchstart'), true);
+ window.addEventListener("mousemove", onMouse('touchmove'), true);
+ window.addEventListener("mouseup", onMouse('touchend'), true);
+
+ window.addEventListener("mouseenter", preventMouseEvents, true);
+ window.addEventListener("mouseleave", preventMouseEvents, true);
+ window.addEventListener("mouseout", preventMouseEvents, true);
+ window.addEventListener("mouseover", preventMouseEvents, true);
+
+ // it uses itself!
+ window.addEventListener("touchstart", showTouches, true);
+ window.addEventListener("touchmove", showTouches, true);
+ window.addEventListener("touchend", showTouches, true);
+ window.addEventListener("touchcancel", showTouches, true);
+ }
+
+ // start distance when entering the multitouch mode
+ TouchEmulator.multiTouchOffset = 75;
+
+ /**
+ * css template for the touch rendering
+ * @param touch
+ * @returns object
+ */
+ TouchEmulator.template = function(touch) {
+ var size = 0;
+ var transform = 'translate('+ (touch.clientX-(size/2)) +'px, '+ (touch.clientY-(size/2)) +'px)';
+ return {
+ position: 'fixed',
+ left: 0,
+ top: 0,
+ background: '#fff',
+ border: 'solid 1px #999',
+ opacity: .6,
+ borderRadius: '100%',
+ height: size + 'px',
+ width: size + 'px',
+ padding: 0,
+ margin: 0,
+ display: 'block',
+ overflow: 'hidden',
+ pointerEvents: 'none',
+ webkitUserSelect: 'none',
+ mozUserSelect: 'none',
+ userSelect: 'none',
+ webkitTransform: transform,
+ mozTransform: transform,
+ transform: transform,
+ zIndex: 100
+ }
+ };
+
+ // export
+ if (typeof define == "function" && define.amd) {
+ define(function() {
+ return TouchEmulator;
+ });
+ } else if (typeof module != "undefined" && module.exports) {
+ module.exports = TouchEmulator;
+ } else {
+ window[exportName] = TouchEmulator;
+ }
+})(window, document, "TouchEmulator");
\ No newline at end of file
diff --git a/static/font/OPPOSANS-M-subfont.ttf b/static/font/OPPOSANS-M-subfont.ttf
new file mode 100644
index 0000000..88ff835
Binary files /dev/null and b/static/font/OPPOSANS-M-subfont.ttf differ
diff --git a/static/font/shopro-icon.css b/static/font/shopro-icon.css
new file mode 100644
index 0000000..a133a5b
--- /dev/null
+++ b/static/font/shopro-icon.css
@@ -0,0 +1,106 @@
+@font-face {
+ font-family: "iconfont";
+ /* Project id 1678323 */
+ src:
+ url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAABHoAAsAAAAAIoQAABGbAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACGJAqySKh8ATYCJANgCzIABCAFhGcHgi8bwxwzo7aTtDJH9l8l8ATGqyFHKHipGkWzKMLL/ysqKsPKOcPIvI7DN7dnUfNyxMWZa8cirvC1oZQQT3bR1+vuwfbMrgcnMgIzgKEQKTynF5IRlII/mjlkX9prquJakykTw2L7lDFTKWWqWLzgHRlk9KS1de1TUCfrcqRhALfVCBPa3nzZQEeZYMUoMfIRbEwwCjPQC73GK7mICK4qzaPP53unepd0dBcYiCwnKUkylQAEBeSRtH1NevsT2i4bKCkwCf5vrrTJXgFpSigMWpGZ5OAnszA5nM0R5QhJVaHqq1CbEpCrPFfA5ytMdXWF8BVKV5lqWchNI5VuHcxVHcrD++E7t3e14ekss9Sv6sBX4V4QwNLfWGry1O1j1tywlAybYRCDBR55ZcNaJVjZ8seETBV8h8s9p0FOUAB1TJ0BjsuPLz8YmA8KRyOua9aqFcn+Mn6s0Hube53pj+zNrgKOrQAH0EDvijlUuPE3fYPeUrN+hQ2vgc7a0/MzmZP5mc0ifaTsyt5leT5mJV+db81350e/jn6saDbJYOx279qJVKGzvvbu9P8rPKipqmsoEeAihFgKFClTYfDwUWhiiYgD4oLcIYB01lISZBzXo4ZM1qOKTDHq71SD0QA1YJRAHTACUB8MF9SCIaARGCFoO6iE0fZgFEB7gFEEXQdGGfQdGBXQHOthIB+zHh7kC9fDh3w1Q4FuBUOD7gYjBj2K9UjwdR0nsmQUyEvDgJTO0R/sgvkzYfYlYsJZyQoXZ8JxjbLBO2qOy9T4pCa4RIBDMsSLputhMYUwR4uWK9r5ysGvc3mKojiqSrFFJAVHFaM2sXq8sEddG9vPtmljhFVr6SWDPOtKaHc4AZFHbFgZ3D5MfDcdHJLfsI8QP6pk8OCJJc9EYWRkd3WFcWNerMoX+Rujb42/N/ntqLcznu+NNDkMmaOLvj9HlYLgFrGhRIoczrs/5v2M61zhpVCiaqwFYpuCtk37dGcz36QbM1/Mvaa0QAzRcTPNwQHAAJlMvqMxIPkv3O9tuu8DpQYBbjeiCDZrYbin3bjTDWiD2qV7R9v0uz1Qtzepjdv79ApArRp1KFoNP51lO9IrahUHRl2rKS26rbi9fDoFak8/ohb9/WNg1Ccfih376Zn0t1qr3kcl/SF0tEcs4wFQGYK+3e5SmyoJpfTddG1QT78L/SOFtEiPiJ/NXPoW9b+YVhKLfDFV9eoDuztP96VzhRLlBOGCvZ0dyU53YsuO/IDGhPsi7VxuDp5ms+meQT2TOhrJBmMSLpOPnd5dviigVMsCpyyZ7RUIYhE/BLFAVjcBqiW1SE3VombhI477ZLHrmqw5kIsw5dAgDG4kW4Xno+4MR67WlMhTDCmYoor+FF0OdUWFaviqGlQdVyvZWr1MSpZBK45BkpZKiKZO/W6p/3Bt/9v+hbVk1jRakb9E47vU7UiLIiMIVN/Xw/D38Yd1JQ9saCcKrqoyJ9uF1AfGI+2hfn/j7dgr9HDQgieBEU1f1PDzr6q8litNZIFa0WtQUDXm1nEAI6sAXLr6u1ey9hBZ+wWXCgCPHUFfdhiluPoAB1ZVrayL5o4inOQ4FWT1+wC3cjK7FOMRFIcb4/ur2jyylY2qV/l9ApBRiKc9OAtAGbE6CpfJSIP1O6ytXlZ7+TwpbgHiRIXE25X6xQtHlKWL5e2SIsqtLCyN2mjgoElEP+20h2nvPOMmQ/npopoAg0Zfxhn2zKB8hzukweQZv+/5QFo/6nnQhMZ/8vZH0YegwyP99y/DdM2S+zKoZufdaOVVFO2wvO5Y9Um3W6NT3Kw9HdRzlc3GLZK3eCyKPxRBy/Im1PzbcenSFtj649IlzbjpV1jm/3hW3+yt8IzUW45Lotxh8lIx7tB0kXQZd5Ss2FR9MM/wrsy8S0iMzNBpTs+tEB+7KqJNZakokwTPn+hRJrFRZYkY97WZxEyGaiS9lEnU2ALHEunCiCxVTqQTKYdOESbhkWU6GydYmS1nUibXLz6SdaiRoAyvpR4XiHxsmxEM5J+GSJ/D31PIeEJgCSHGbBIYjo/RCTauUAxHggTPxiWBIdyAb/yUXZnCZpU8adWndOFaH9EsUKfs7APKbre3zRihKj8yV0e66C/hv0VJa2+jqScIydiYL1JpkxRxflMpyAXJfM76Rn1KO4R1Nsdy4bPoKyEC5078HvSebOPUJY2NlEyBZJVzlKJ4kmTyKxn6x2UX3B2tRszlWkLZJG5zBTabiPpDTUA63JfANzpBsOrBVA+/gT+cVMs4G0F+BAIqfS9TTnnc+zmvYfOZmfjVBoChhqwu4SIUJFVTRbI+uZ7ymMqEBwOrXCEdyqV4vWT+K1rGv1pcJg3Fh7/cNA9VTXZlZQDHk2+QrDlxSEq29YpaVMtlI0CJbC6Hyz66WlNsC613szKwORwYQIHSKj09XuarG2F0J+9jyUh8q2PDmBw3Fcw3SgDJIu9NzvH6OI/Y6/Ylvgjcxcwi5xYDzm9FBssyTQJSGKhyCZ7hb1APq5uDHbpMQ6TbVDDg/gNjOCI9ppHswGos4cUDqZgXQrnhzylQWfpVNDzqzytXT+D6YMemUGNBgbIzn5Qcb3kiwBehNRXkd2BoNy9d+fvutV1eXXUJ/YBLJr/p1Qc+yhWgFTq7p9ENQYEizQfOSyUmmuzNzbGfMPeItOiMmVdwgatFcydOzEW13AtII7090Vyu1ud2yntqwipDlEVq/hr1X+e1OI/wg5bdExPfc+pxC+TVOuP5JGsS1LJSVgBgZ7unFjKVYvY86X72fqldpn2i6jxyXrYsp/8gqywRNAjVLCBAA7xXvEAQLzwgrMHxAqHyrQkxMLhzNog9wMDZO8N69eJu9ylsCkZhg+eWNSIGWM/q02UyhufDJKMRGUfexII5/GHOAs4wn4PdbLC4IJM7C1SD8FHExAX0QVaYhhmwJKa+ISju7hSi+V5ghWHGRFu5R/Kc9dX9/HVXWBNX+lUHKMctevwlK2Gt4UjZLv+SG79VWsO6J+SChhS5C2zqmzb2gHHEOap1on7Wgk8yZ4UyLN9X7GRb0U1jbv62/ANKqbSIJz4vN6W2Apf/Da5TSiBBTkjSQsKhO8mHTKFKRdKPXAyqGK0GUTqmNWdCorbEOyPRn49JGWPa90UkrpmfU/T4GDYF8vfyRlPjVc9AzJ6OyLKI0tKIssjPSHPwiNLIss8ujzHt5eJskUYjyhZfWNI6uEgjzr5Al7JUNgIxFgyuWIpYs5cuNoODwOC9lO1b73LfArAuHKjFqmNiqrFa65BCekPXYtYui0irHz/+Azlu5kci0ezGAYdONhcE7s9fMN5Uzdhzam44w+77ymdBDeZGivXAgfbyxrjKLZDmDV0eaXFlC43BIHmwHbwfvHvqzfFTCWfIxbVhPZgi+QyVIO8eYh3d5evK1nVthHLgwKis7nJ/QNSpZLqabkDeIroPOlhP1wmVfL5SaKDrnp15CDoXrL4+wVavrtN1jFIhX6nke0/Vw7rT3UNKAbXo0I1ShgZWM0pVQ0fTZESicOMNV8Olp/ej0dD0QLCcojKpI8h5ROW87YhThvPJXc4ZVMQdoWYI43iCWOH+0xFIlBxvlSQpRTpCZTaVA4zekYzcqldXyVGXjh9VwPZXXlVlsY8c/r3OPdc8nJGxbXN6eku5BNNqMckINAIMQUCeiJez0hgfrhWlE7S4FFTlgf1KNi7LqayGPRqj0k+WbPACKLlBBn5mWomfspHt8H3EEDLqYj5FdvVGkS5bBETOADMgjIVBGeDp5Ttjbbq9Ml1rSC011Kr/tFwlviNCrvNpYZ000LlyShgW1b+8iFFhgKvFsrikU9LLtkFQtVuEo987eoCezwnyNy7KuIR/drkV6APEsI8tAuS/l7e12cNg0XdpMbhiiNO9ygcsHmCvSCWkOgan4UO04NIGw3K+HrL47D6xirHPdMM5MvqbOlLG6JYzO9KdulIcNefhsiVl3XFWDGJ/cArgO8upRuMiDCN2zB5yzcN5bq/O/jm2enVeV0/VJb/Zi8Ujd9HFSbd2zmDlkRTc6wJWlZt5glTTtnpLtfKnwm4FPY+wLA8jnJwfWpmNJ+CI/z3vgBLw+5czAoKp0rAi0c/rdINELpl3fdNJ8m+ZGyj9LWloIPqQPN25qneYsWSs6/nh4LeO/CDOhrOdJM9fvJJ7TibVudkhwOvPBxZHv4ohf355J1PoNWHupqALzzYfidw9rtd1qniOEtF1OCbrHDKqxyR5paLZ6fFwrEeWGsEgmXs8kCfZFFCS6b+uM1m/Ir+loJvM/OHoY/abgt868YPEB151kjkgX/VG0l/iuDq9/6KuTCAFkniqd/7GEjEQuGx1bHzUXnKp3f+CRH6cNCQ7oYlRR7+TkqSWJroWuxZ4HQ9Lx7J1vsU+d20Lgo/3uh+vju4mtBNqAusC40vlefQmep303pyVdWil13OXokg9Fl4Zprf/GFDLkoVLzCtnpXl5gTyXhR7FRFlgwwDtXuxUc5jSDR5wTQ9wcnOSphQ7zCBmy07Tt2+nZj+1r4CBP4/7zncs+rbGvmn0q3xgqx+qGA4aTEa+4jgFZIGcGeec8VMf4hw8LYXN076TzEeDAPzTo9aLYz7Ztmqt0nMrY0lbCE0qUNC9gMIEGZTOzACZcEcr1dCprU5jxZ6I7x9XBFkekePrLl4cBJng4IULkQUBz9keOWK4zYcPwwTEP29WVHGE/dR4SXBJuoFRhdZxEzXWNM9j4TP8ir1nQterxhmCljAa6QbZcVbUolVoPamJXGhFWbVatVnDV7F/1YpxIut+1NPIzCPKRNIxgr2xxiGe3M2nx83Jj4lymYlcL5O1upvQUnbFB/xkPwt3QeD3Z/Z4tuTtUpuimdvqtkgfKpuC2yIt73zIWfTCDUWOMZ2ut9EZ7BfiGWW/9ET5Bx+LZfqj6Ru//UkzUnL02J8tgqjun741Ns5LNTJ4/eQkjTTBtYRLs/SNmnLPRkvr4GyDje53VzupXfLBvxaWvyUrV626Kqvy2OTHJnvkAUsQ49Re3xUngO3IgiiFUwXdU032Hfz11TaKi/K+tKC2bXY27Qa0isShH/DsKdy+fK06BBcItCS9TZi8IiRfy1LoVIWQsuZ8NmbB7+dYxqmjTXNsW20TvHKXNkaApH/HDhQtbF09JvH0JP9biOIobyw9f3NN8cK4wkNP8ekEdUlFlTBL7NnJG9tMEDHWfLV8bnAwGMwOjv6R5uAHg6Pg35X2UcMuLqC64F/O2eb8G8brg04Yzb7D6X0IS31Z46D5QJ/UiEzev0I93s9rn+uANkzAsgV7oJfOV3uVxOsx6zuWLKcS9UE42wfQHfDCj6j79++HRlo6OItOkifsl6YiItarH1D+FTgWOy/d+FxcHv2bX/vzIP7TuAoU1PyvGHlzmwhDYMOfM0OI8LuqjyRID9TbscfNPx9yYWFpUzdNRQXW7gBb/RE1n6tkr7OV/z7s9QdSeLRCGp+OohnZEzkEDEQuPmOQpZcp5w+o20IOMQWgqwM7JFRcQooSt5Gm4oloRr5BDrEcuVT8hywLpHhpAV1bPsmBIJB8eM8xtCbCQfJwD0H5WDivxFNwKSqeB337O9PWwIBL4zTpjZolinjk7JivGtcHcWx54uwIQupromRu0G+V32n6oR2zJRyAgM5rSrhl3G+7lhCLIWqa1M/vEEDhiRE4pnjKHalGyOAG/DlTJUNc0wyryooU3s4Nilk7iEfwIzhKHcNNtSRBbCZbuC3+5gggfDf61iQwE+b0s5taxdX6xdvHs0Fj3FUrzp6mRIsZI4644okvhY3sNxVKUUpSlkrVatVrFBWXlNaC/6Ax8kNhq/dotDBqgqLwgHfeVAbtdnsEKRUnLrQSCncoYjF9b/0IhSHreyStQm2Nqt97YaSCg7ktD09JEzSq9Il5zmomlx2UBn6qvfP5CB00HvBBe/KoEnJVnpwhiZOlco+pRg1K/qb2NihLuP4ICIoOVtJPRAMZ9WpuActCyl6EcVxzIH0ID50B') format('woff2')
+}
+
+.iconfont {
+ font-family: "iconfont" !important;
+ font-size: 16px;
+ font-style: normal;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-zhifubao:before {
+ content: "\e60a";
+}
+
+.icon-yinhangqia:before {
+ content: "\e767";
+}
+
+.icon-zixun:before {
+ content: "\e771";
+}
+
+.icon-icon-test:before {
+ content: "\e6e7";
+}
+
+.icon-qrcode:before {
+ content: "\eb64";
+}
+
+.icon-xiala:before {
+ content: "\e608";
+}
+
+.icon-youjiantou-tianchong:before {
+ content: "\e73d";
+}
+
+.icon-yuandianxiao:before {
+ content: "\e757";
+}
+
+.icon-biaoqing:before {
+ content: "\e620";
+}
+
+.icon-tianjia:before {
+ content: "\e61f";
+}
+
+.icon-icon-test1:before {
+ content: "\e605";
+}
+
+.icon-21shuru:before {
+ content: "\e615";
+}
+
+.icon-fire:before {
+ content: "\e629";
+}
+
+.icon-zizhutuiguang:before {
+ content: "\e604";
+}
+
+.icon-quanping:before {
+ content: "\e66a";
+}
+
+.icon-yishixiao:before {
+ content: "\e6d9";
+}
+
+.icon-tuihuo1:before {
+ content: "\e601";
+}
+
+.icon-tuikuan1:before {
+ content: "\e600";
+}
+
+.icon-tuihuo:before {
+ content: "\e602";
+}
+
+.icon-huanhuo:before {
+ content: "\e603";
+}
+
+.icon-dingwei:before {
+ content: "\e86a";
+}
+
+.icon-add-fill:before {
+ content: "\e777";
+}
+
+.icon-reduce-fill:before {
+ content: "\e788";
+}
diff --git a/static/images/empty_network.png b/static/images/empty_network.png
new file mode 100644
index 0000000..da7b9fe
Binary files /dev/null and b/static/images/empty_network.png differ
diff --git a/static/images/tabbar/tabbar_cart.png b/static/images/tabbar/tabbar_cart.png
new file mode 100644
index 0000000..ae1f141
Binary files /dev/null and b/static/images/tabbar/tabbar_cart.png differ
diff --git a/static/images/tabbar/tabbar_cart1.png b/static/images/tabbar/tabbar_cart1.png
new file mode 100644
index 0000000..b192d85
Binary files /dev/null and b/static/images/tabbar/tabbar_cart1.png differ
diff --git a/static/images/tabbar/tabbar_category.png b/static/images/tabbar/tabbar_category.png
new file mode 100644
index 0000000..7ac5a72
Binary files /dev/null and b/static/images/tabbar/tabbar_category.png differ
diff --git a/static/images/tabbar/tabbar_category1.png b/static/images/tabbar/tabbar_category1.png
new file mode 100644
index 0000000..2d94ce4
Binary files /dev/null and b/static/images/tabbar/tabbar_category1.png differ
diff --git a/static/images/tabbar/tabbar_home.png b/static/images/tabbar/tabbar_home.png
new file mode 100644
index 0000000..bc83b14
Binary files /dev/null and b/static/images/tabbar/tabbar_home.png differ
diff --git a/static/images/tabbar/tabbar_home1.png b/static/images/tabbar/tabbar_home1.png
new file mode 100644
index 0000000..3b5e39c
Binary files /dev/null and b/static/images/tabbar/tabbar_home1.png differ
diff --git a/static/images/tabbar/tabbar_personal.png b/static/images/tabbar/tabbar_personal.png
new file mode 100644
index 0000000..933f32e
Binary files /dev/null and b/static/images/tabbar/tabbar_personal.png differ
diff --git a/static/images/tabbar/tabbar_personal1.png b/static/images/tabbar/tabbar_personal1.png
new file mode 100644
index 0000000..57c0e70
Binary files /dev/null and b/static/images/tabbar/tabbar_personal1.png differ
diff --git a/static/style/colorui.css b/static/style/colorui.css
new file mode 100644
index 0000000..513e1e9
--- /dev/null
+++ b/static/style/colorui.css
@@ -0,0 +1,3924 @@
+/*
+ ColorUi for uniApp v2.1.6 | by 文晓港 2019-05-31 10:44:24
+ 仅供学习交流,如作它用所承受的法律责任一概与作者无关
+
+ *使用ColorUi开发扩展与插件时,请注明基于ColorUi开发
+
+ (QQ交流群:240787041)
+*/
+
+/* ==================
+ 初始化
+ ==================== */
+body {
+ background-color: #f1f1f1;
+ font-size: 28upx;
+ color: #333333;
+ font-family: Helvetica Neue, Helvetica, sans-serif;
+}
+
+view,
+scroll-view,
+swiper,
+button,
+input,
+textarea,
+label,
+navigator,
+image {
+ box-sizing: border-box;
+}
+
+.round {
+ border-radius: 5000upx;
+}
+
+.radius {
+ border-radius: 6upx;
+}
+
+/* ==================
+ 图片
+ ==================== */
+
+image {
+ max-width: 100%;
+ display: inline-block;
+ position: relative;
+ z-index: 0;
+}
+
+image.loading::before {
+ content: "";
+ background-color: #f5f5f5;
+ display: block;
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ z-index: -2;
+}
+
+image.loading::after {
+ content: "\e7f1";
+ font-family: "cuIcon";
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 32upx;
+ height: 32upx;
+ line-height: 32upx;
+ right: 0;
+ bottom: 0;
+ z-index: -1;
+ font-size: 32upx;
+ margin: auto;
+ color: #ccc;
+ -webkit-animation: cuIcon-spin 2s infinite linear;
+ animation: cuIcon-spin 2s infinite linear;
+ display: block;
+}
+
+.response {
+ width: 100%;
+}
+
+/* ==================
+ 开关
+ ==================== */
+
+switch,
+checkbox,
+radio {
+ position: relative;
+}
+
+switch::after,
+switch::before {
+ font-family: "cuIcon";
+ content: "\e645";
+ position: absolute;
+ color: #ffffff !important;
+ top: 0%;
+ left: 0upx;
+ font-size: 26upx;
+ line-height: 26px;
+ width: 50%;
+ text-align: center;
+ pointer-events: none;
+ transform: scale(0, 0);
+ transition: all 0.3s ease-in-out 0s;
+ z-index: 9;
+ bottom: 0;
+ height: 26px;
+ margin: auto;
+}
+
+switch::before {
+ content: "\e646";
+ right: 0;
+ transform: scale(1, 1);
+ left: auto;
+}
+
+switch[checked]::after,
+switch.checked::after {
+ transform: scale(1, 1);
+}
+
+switch[checked]::before,
+switch.checked::before {
+ transform: scale(0, 0);
+}
+
+/* #ifndef MP-ALIPAY */
+radio::before,
+checkbox::before {
+ font-family: "cuIcon";
+ content: "\e645";
+ position: absolute;
+ color: #ffffff !important;
+ top: 50%;
+ margin-top: -8px;
+ right: 5px;
+ font-size: 32upx;
+ line-height: 16px;
+ pointer-events: none;
+ transform: scale(1, 1);
+ transition: all 0.3s ease-in-out 0s;
+ z-index: 9;
+}
+
+radio .wx-radio-input,
+checkbox .wx-checkbox-input,
+radio .uni-radio-input,
+checkbox .uni-checkbox-input {
+ margin: 0;
+ width: 24px;
+ height: 24px;
+}
+
+checkbox.round .wx-checkbox-input,
+checkbox.round .uni-checkbox-input {
+ border-radius: 100upx;
+}
+
+/* #endif */
+
+switch[checked]::before {
+ transform: scale(0, 0);
+}
+
+switch .wx-switch-input,
+switch .uni-switch-input {
+ border: none;
+ padding: 0 24px;
+ width: 48px;
+ height: 26px;
+ margin: 0;
+ border-radius: 100upx;
+}
+
+switch .wx-switch-input:not([class*="bg-"]),
+switch .uni-switch-input:not([class*="bg-"]) {
+ background: #8799a3 !important;
+}
+
+switch .wx-switch-input::after,
+switch .uni-switch-input::after {
+ margin: auto;
+ width: 26px;
+ height: 26px;
+ border-radius: 100upx;
+ left: 0upx;
+ top: 0upx;
+ bottom: 0upx;
+ position: absolute;
+ transform: scale(0.9, 0.9);
+ transition: all 0.1s ease-in-out 0s;
+}
+
+switch .wx-switch-input.wx-switch-input-checked::after,
+switch .uni-switch-input.uni-switch-input-checked::after {
+ margin: auto;
+ left: 22px;
+ box-shadow: none;
+ transform: scale(0.9, 0.9);
+}
+
+radio-group {
+ display: inline-block;
+}
+
+
+
+switch.radius .wx-switch-input::after,
+switch.radius .wx-switch-input,
+switch.radius .wx-switch-input::before,
+switch.radius .uni-switch-input::after,
+switch.radius .uni-switch-input,
+switch.radius .uni-switch-input::before {
+ border-radius: 10upx;
+}
+
+.uni-checkbox-input:hover {
+ border-color: #d1d1d1 !important;
+}
+
+switch .wx-switch-input::before,
+radio.radio::before,
+checkbox .wx-checkbox-input::before,
+radio .wx-radio-input::before,
+switch .uni-switch-input::before,
+radio.radio::before,
+checkbox .uni-checkbox-input::before,
+radio .uni-radio-input::before {
+ display: none;
+}
+
+radio.radio[checked]::after,
+radio.radio .uni-radio-input-checked::after {
+ content: "";
+ background-color: transparent;
+ display: block;
+ position: absolute;
+ width: 8px;
+ height: 8px;
+ z-index: 999;
+ top: 0upx;
+ left: 0upx;
+ right: 0;
+ bottom: 0;
+ margin: auto;
+ border-radius: 200upx;
+ /* #ifndef MP */
+ border: 7px solid #ffffff !important;
+ /* #endif */
+
+ /* #ifdef MP */
+ border: 8px solid #ffffff !important;
+ /* #endif */
+}
+
+.switch-sex::after {
+ content: "\e71c";
+}
+
+.switch-sex::before {
+ content: "\e71a";
+}
+
+.switch-sex .wx-switch-input,
+.switch-sex .uni-switch-input {
+ background: #e54d42 !important;
+ border-color: #e54d42 !important;
+}
+
+.switch-sex[checked] .wx-switch-input,
+.switch-sex.checked .uni-switch-input {
+ background: #0081ff !important;
+ border-color: #0081ff !important;
+}
+
+switch.red[checked] .wx-switch-input.wx-switch-input-checked,
+checkbox.red[checked] .wx-checkbox-input,
+radio.red[checked] .wx-radio-input,
+switch.red.checked .uni-switch-input.uni-switch-input-checked,
+checkbox.red.checked .uni-checkbox-input,
+radio.red.checked .uni-radio-input {
+ background-color: #e54d42 !important;
+ border-color: #e54d42 !important;
+ color: #ffffff !important;
+}
+
+switch.orange[checked] .wx-switch-input,
+checkbox.orange[checked] .wx-checkbox-input,
+radio.orange[checked] .wx-radio-input,
+switch.orange.checked .uni-switch-input,
+checkbox.orange.checked .uni-checkbox-input,
+radio.orange.checked .uni-radio-input {
+ background-color: #f37b1d !important;
+ border-color: #f37b1d !important;
+ color: #ffffff !important;
+}
+
+switch.yellow[checked] .wx-switch-input,
+checkbox.yellow[checked] .wx-checkbox-input,
+radio.yellow[checked] .wx-radio-input,
+switch.yellow.checked .uni-switch-input,
+checkbox.yellow.checked .uni-checkbox-input,
+radio.yellow.checked .uni-radio-input {
+ background-color: #fbbd08 !important;
+ border-color: #fbbd08 !important;
+ color: #333333 !important;
+}
+
+switch.olive[checked] .wx-switch-input,
+checkbox.olive[checked] .wx-checkbox-input,
+radio.olive[checked] .wx-radio-input,
+switch.olive.checked .uni-switch-input,
+checkbox.olive.checked .uni-checkbox-input,
+radio.olive.checked .uni-radio-input {
+ background-color: #8dc63f !important;
+ border-color: #8dc63f !important;
+ color: #ffffff !important;
+}
+
+switch.green[checked] .wx-switch-input,
+switch[checked] .wx-switch-input,
+checkbox.green[checked] .wx-checkbox-input,
+checkbox[checked] .wx-checkbox-input,
+radio.green[checked] .wx-radio-input,
+radio[checked] .wx-radio-input,
+switch.green.checked .uni-switch-input,
+switch.checked .uni-switch-input,
+checkbox.green.checked .uni-checkbox-input,
+checkbox.checked .uni-checkbox-input,
+radio.green.checked .uni-radio-input,
+radio.checked .uni-radio-input {
+ background-color: #39b54a !important;
+ border-color: #39b54a !important;
+ color: #ffffff !important;
+ border-color: #39B54A !important;
+}
+
+switch.cyan[checked] .wx-switch-input,
+checkbox.cyan[checked] .wx-checkbox-input,
+radio.cyan[checked] .wx-radio-input,
+switch.cyan.checked .uni-switch-input,
+checkbox.cyan.checked .uni-checkbox-input,
+radio.cyan.checked .uni-radio-input {
+ background-color: #1cbbb4 !important;
+ border-color: #1cbbb4 !important;
+ color: #ffffff !important;
+}
+
+switch.blue[checked] .wx-switch-input,
+checkbox.blue[checked] .wx-checkbox-input,
+radio.blue[checked] .wx-radio-input,
+switch.blue.checked .uni-switch-input,
+checkbox.blue.checked .uni-checkbox-input,
+radio.blue.checked .uni-radio-input {
+ background-color: #0081ff !important;
+ border-color: #0081ff !important;
+ color: #ffffff !important;
+}
+
+switch.purple[checked] .wx-switch-input,
+checkbox.purple[checked] .wx-checkbox-input,
+radio.purple[checked] .wx-radio-input,
+switch.purple.checked .uni-switch-input,
+checkbox.purple.checked .uni-checkbox-input,
+radio.purple.checked .uni-radio-input {
+ background-color: #6739b6 !important;
+ border-color: #6739b6 !important;
+ color: #ffffff !important;
+}
+
+switch.mauve[checked] .wx-switch-input,
+checkbox.mauve[checked] .wx-checkbox-input,
+radio.mauve[checked] .wx-radio-input,
+switch.mauve.checked .uni-switch-input,
+checkbox.mauve.checked .uni-checkbox-input,
+radio.mauve.checked .uni-radio-input {
+ background-color: #9c26b0 !important;
+ border-color: #9c26b0 !important;
+ color: #ffffff !important;
+}
+
+switch.pink[checked] .wx-switch-input,
+checkbox.pink[checked] .wx-checkbox-input,
+radio.pink[checked] .wx-radio-input,
+switch.pink.checked .uni-switch-input,
+checkbox.pink.checked .uni-checkbox-input,
+radio.pink.checked .uni-radio-input {
+ background-color: #e03997 !important;
+ border-color: #e03997 !important;
+ color: #ffffff !important;
+}
+
+switch.brown[checked] .wx-switch-input,
+checkbox.brown[checked] .wx-checkbox-input,
+radio.brown[checked] .wx-radio-input,
+switch.brown.checked .uni-switch-input,
+checkbox.brown.checked .uni-checkbox-input,
+radio.brown.checked .uni-radio-input {
+ background-color: #a5673f !important;
+ border-color: #a5673f !important;
+ color: #ffffff !important;
+}
+
+switch.grey[checked] .wx-switch-input,
+checkbox.grey[checked] .wx-checkbox-input,
+radio.grey[checked] .wx-radio-input,
+switch.grey.checked .uni-switch-input,
+checkbox.grey.checked .uni-checkbox-input,
+radio.grey.checked .uni-radio-input {
+ background-color: #8799a3 !important;
+ border-color: #8799a3 !important;
+ color: #ffffff !important;
+}
+
+switch.gray[checked] .wx-switch-input,
+checkbox.gray[checked] .wx-checkbox-input,
+radio.gray[checked] .wx-radio-input,
+switch.gray.checked .uni-switch-input,
+checkbox.gray.checked .uni-checkbox-input,
+radio.gray.checked .uni-radio-input {
+ background-color: #f0f0f0 !important;
+ border-color: #f0f0f0 !important;
+ color: #333333 !important;
+}
+
+switch.black[checked] .wx-switch-input,
+checkbox.black[checked] .wx-checkbox-input,
+radio.black[checked] .wx-radio-input,
+switch.black.checked .uni-switch-input,
+checkbox.black.checked .uni-checkbox-input,
+radio.black.checked .uni-radio-input {
+ background-color: #333333 !important;
+ border-color: #333333 !important;
+ color: #ffffff !important;
+}
+
+switch.white[checked] .wx-switch-input,
+checkbox.white[checked] .wx-checkbox-input,
+radio.white[checked] .wx-radio-input,
+switch.white.checked .uni-switch-input,
+checkbox.white.checked .uni-checkbox-input,
+radio.white.checked .uni-radio-input {
+ background-color: #ffffff !important;
+ border-color: #ffffff !important;
+ color: #333333 !important;
+}
+
+/* ==================
+ 边框
+ ==================== */
+
+/* -- 实线 -- */
+
+.solid,
+.solid-top,
+.solid-right,
+.solid-bottom,
+.solid-left,
+.solids,
+.solids-top,
+.solids-right,
+.solids-bottom,
+.solids-left,
+.dashed,
+.dashed-top,
+.dashed-right,
+.dashed-bottom,
+.dashed-left {
+ position: relative;
+}
+
+.solid::after,
+.solid-top::after,
+.solid-right::after,
+.solid-bottom::after,
+.solid-left::after,
+.solids::after,
+.solids-top::after,
+.solids-right::after,
+.solids-bottom::after,
+.solids-left::after,
+.dashed::after,
+.dashed-top::after,
+.dashed-right::after,
+.dashed-bottom::after,
+.dashed-left::after {
+ content: " ";
+ width: 200%;
+ height: 200%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border-radius: inherit;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ pointer-events: none;
+ box-sizing: border-box;
+}
+
+.solid::after {
+ border: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-top::after {
+ border-top: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-right::after {
+ border-right: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-bottom::after {
+ border-bottom: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-left::after {
+ border-left: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solids::after {
+ border: 8upx solid #eee;
+}
+
+.solids-top::after {
+ border-top: 8upx solid #eee;
+}
+
+.solids-right::after {
+ border-right: 8upx solid #eee;
+}
+
+.solids-bottom::after {
+ border-bottom: 8upx solid #eee;
+}
+
+.solids-left::after {
+ border-left: 8upx solid #eee;
+}
+
+/* -- 虚线 -- */
+
+.dashed::after {
+ border: 1upx dashed #ddd;
+}
+
+.dashed-top::after {
+ border-top: 1upx dashed #ddd;
+}
+
+.dashed-right::after {
+ border-right: 1upx dashed #ddd;
+}
+
+.dashed-bottom::after {
+ border-bottom: 1upx dashed #ddd;
+}
+
+.dashed-left::after {
+ border-left: 1upx dashed #ddd;
+}
+
+/* -- 阴影 -- */
+
+.shadow[class*='white'] {
+ --ShadowSize: 0 1upx 6upx;
+}
+
+.shadow-lg {
+ --ShadowSize: 0upx 40upx 100upx 0upx;
+}
+
+.shadow-warp {
+ position: relative;
+ box-shadow: 0 0 10upx rgba(0, 0, 0, 0.1);
+}
+
+.shadow-warp:before,
+.shadow-warp:after {
+ position: absolute;
+ content: "";
+ top: 20upx;
+ bottom: 30upx;
+ left: 20upx;
+ width: 50%;
+ box-shadow: 0 30upx 20upx rgba(0, 0, 0, 0.2);
+ transform: rotate(-3deg);
+ z-index: -1;
+}
+
+.shadow-warp:after {
+ right: 20upx;
+ left: auto;
+ transform: rotate(3deg);
+}
+
+.shadow-blur {
+ position: relative;
+}
+
+.shadow-blur::before {
+ content: "";
+ display: block;
+ background: inherit;
+ filter: blur(10upx);
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 10upx;
+ left: 10upx;
+ z-index: -1;
+ opacity: 0.4;
+ transform-origin: 0 0;
+ border-radius: inherit;
+ transform: scale(1, 1);
+}
+
+/* ==================
+ 按钮
+ ==================== */
+
+.cu-btn {
+ position: relative;
+ border: 0upx;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ box-sizing: border-box;
+ padding: 0 30upx;
+ font-size: 28upx;
+ height: 64upx;
+ line-height: 1;
+ text-align: center;
+ text-decoration: none;
+ overflow: visible;
+ margin-left: initial;
+ transform: translate(0upx, 0upx);
+ margin-right: initial;
+}
+
+.cu-btn::after {
+ display: none;
+}
+
+.cu-btn:not([class*="bg-"]) {
+ background-color: #f0f0f0;
+}
+
+.cu-btn[class*="line"] {
+ background-color: transparent;
+}
+
+.cu-btn[class*="line"]::after {
+ content: " ";
+ display: block;
+ width: 200%;
+ height: 200%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border: 1upx solid currentColor;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ box-sizing: border-box;
+ border-radius: 12upx;
+ z-index: 1;
+ pointer-events: none;
+}
+
+.cu-btn.round[class*="line"]::after {
+ border-radius: 1000upx;
+}
+
+.cu-btn[class*="lines"]::after {
+ border: 6upx solid currentColor;
+}
+
+.cu-btn[class*="bg-"]::after {
+ display: none;
+}
+
+.cu-btn.sm {
+ padding: 0 20upx;
+ font-size: 20upx;
+ height: 48upx;
+}
+
+.cu-btn.lg {
+ padding: 0 40upx;
+ font-size: 32upx;
+ height: 80upx;
+}
+
+.cu-btn.cuIcon.sm {
+ width: 48upx;
+ height: 48upx;
+}
+
+.cu-btn.cuIcon {
+ width: 64upx;
+ height: 64upx;
+ border-radius: 500upx;
+ padding: 0;
+}
+
+button.cuIcon.lg {
+ width: 80upx;
+ height: 80upx;
+}
+
+.cu-btn.shadow-blur::before {
+ top: 4upx;
+ left: 4upx;
+ filter: blur(6upx);
+ opacity: 0.6;
+}
+
+.cu-btn.button-hover {
+ transform: translate(1upx, 1upx);
+}
+
+.block {
+ display: block;
+}
+
+.cu-btn.block {
+ display: flex;
+}
+
+.cu-btn[disabled] {
+ opacity: 0.6;
+ color: #ffffff;
+}
+
+/* ==================
+ 徽章
+ ==================== */
+
+.cu-tag {
+ font-size: 24upx;
+ vertical-align: middle;
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ box-sizing: border-box;
+ padding: 0upx 16upx;
+ height: 48upx;
+ font-family: Helvetica Neue, Helvetica, sans-serif;
+ white-space: nowrap;
+}
+
+.cu-tag:not([class*="bg"]):not([class*="line"]) {
+ background-color: #f1f1f1;
+}
+
+.cu-tag[class*="line-"]::after {
+ content: " ";
+ width: 200%;
+ height: 200%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border: 1upx solid currentColor;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ box-sizing: border-box;
+ border-radius: inherit;
+ z-index: 1;
+ pointer-events: none;
+}
+
+.cu-tag.radius[class*="line"]::after {
+ border-radius: 12upx;
+}
+
+.cu-tag.round[class*="line"]::after {
+ border-radius: 1000upx;
+}
+
+.cu-tag[class*="line-"]::after {
+ border-radius: 0;
+}
+
+.cu-tag+.cu-tag {
+ margin-left: 10upx;
+}
+
+.cu-tag.sm {
+ font-size: 20upx;
+ padding: 0upx 12upx;
+ height: 32upx;
+}
+
+.cu-capsule {
+ display: inline-flex;
+ vertical-align: middle;
+}
+
+.cu-capsule+.cu-capsule {
+ margin-left: 10upx;
+}
+
+.cu-capsule .cu-tag {
+ margin: 0;
+}
+
+.cu-capsule .cu-tag[class*="line-"]:last-child::after {
+ border-left: 0upx solid transparent;
+}
+
+.cu-capsule .cu-tag[class*="line-"]:first-child::after {
+ border-right: 0upx solid transparent;
+}
+
+.cu-capsule.radius .cu-tag:first-child {
+ border-top-left-radius: 6upx;
+ border-bottom-left-radius: 6upx;
+}
+
+.cu-capsule.radius .cu-tag:last-child::after,
+.cu-capsule.radius .cu-tag[class*="line-"] {
+ border-top-right-radius: 12upx;
+ border-bottom-right-radius: 12upx;
+}
+
+.cu-capsule.round .cu-tag:first-child {
+ border-top-left-radius: 200upx;
+ border-bottom-left-radius: 200upx;
+ text-indent: 4upx;
+}
+
+.cu-capsule.round .cu-tag:last-child::after,
+.cu-capsule.round .cu-tag:last-child {
+ border-top-right-radius: 200upx;
+ border-bottom-right-radius: 200upx;
+ text-indent: -4upx;
+}
+
+.cu-tag.badge {
+ border-radius: 200upx;
+ position: absolute;
+ top: -10upx;
+ right: -10upx;
+ font-size: 20upx;
+ padding: 0upx 10upx;
+ height: 28upx;
+ color: #ffffff;
+}
+
+.cu-tag.badge:not([class*="bg-"]) {
+ background-color: #dd514c;
+}
+
+.cu-tag:empty:not([class*="cuIcon-"]) {
+ padding: 0upx;
+ width: 16upx;
+ height: 16upx;
+ top: -4upx;
+ right: -4upx;
+}
+
+.cu-tag[class*="cuIcon-"] {
+ width: 32upx;
+ height: 32upx;
+ top: -4upx;
+ right: -4upx;
+}
+
+/* ==================
+ 头像
+ ==================== */
+
+.cu-avatar {
+ font-variant: small-caps;
+ margin: 0;
+ padding: 0;
+ display: inline-flex;
+ text-align: center;
+ justify-content: center;
+ align-items: center;
+ background-color: #ccc;
+ color: #ffffff;
+ white-space: nowrap;
+ position: relative;
+ width: 64upx;
+ height: 64upx;
+ background-size: cover;
+ background-position: center;
+ vertical-align: middle;
+ font-size: 1.5em;
+}
+
+.cu-avatar.sm {
+ width: 48upx;
+ height: 48upx;
+ font-size: 1em;
+}
+
+.cu-avatar.lg {
+ width: 96upx;
+ height: 96upx;
+ font-size: 2em;
+}
+
+.cu-avatar.xl {
+ width: 128upx;
+ height: 128upx;
+ font-size: 2.5em;
+}
+
+.cu-avatar .avatar-text {
+ font-size: 0.4em;
+}
+
+.cu-avatar-group {
+ direction: rtl;
+ unicode-bidi: bidi-override;
+ padding: 0 10upx 0 40upx;
+ display: inline-block;
+}
+
+.cu-avatar-group .cu-avatar {
+ margin-left: -30upx;
+ border: 4upx solid #f1f1f1;
+ vertical-align: middle;
+}
+
+.cu-avatar-group .cu-avatar.sm {
+ margin-left: -20upx;
+ border: 1upx solid #f1f1f1;
+}
+
+/* ==================
+ 进度条
+ ==================== */
+
+.cu-progress {
+ overflow: hidden;
+ height: 28upx;
+ background-color: #ebeef5;
+ display: inline-flex;
+ align-items: center;
+ width: 100%;
+}
+
+.cu-progress+view,
+.cu-progress+text {
+ line-height: 1;
+}
+
+.cu-progress.xs {
+ height: 10upx;
+}
+
+.cu-progress.sm {
+ height: 20upx;
+}
+
+.cu-progress view {
+ width: 0;
+ height: 100%;
+ align-items: center;
+ display: flex;
+ justify-items: flex-end;
+ justify-content: space-around;
+ font-size: 20upx;
+ color: #ffffff;
+ transition: width 0.6s ease;
+}
+
+.cu-progress text {
+ align-items: center;
+ display: flex;
+ font-size: 20upx;
+ color: #333333;
+ text-indent: 10upx;
+}
+
+.cu-progress.text-progress {
+ padding-right: 60upx;
+}
+
+.cu-progress.striped view {
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-size: 72upx 72upx;
+}
+
+.cu-progress.active view {
+ animation: progress-stripes 2s linear infinite;
+}
+
+@keyframes progress-stripes {
+ from {
+ background-position: 72upx 0;
+ }
+
+ to {
+ background-position: 0 0;
+ }
+}
+
+/* ==================
+ 加载
+ ==================== */
+
+.cu-load {
+ display: block;
+ line-height: 3em;
+ text-align: center;
+}
+
+.cu-load::before {
+ font-family: "cuIcon";
+ display: inline-block;
+ margin-right: 6upx;
+}
+
+.cu-loda.loadmore::before {
+ content: "加载更多";
+}
+
+.cu-load.loading::before {
+ content: "\e67a";
+ animation: cuIcon-spin 2s infinite linear;
+}
+
+.cu-load.loading::after {
+ content: "加载中...";
+}
+
+.cu-load.nomore::before {
+ content: "\e64a";
+}
+
+.cu-load.nomore::after {
+ content: "没有更多了";
+}
+
+.cu-load.erro::before {
+ content: "\e658";
+}
+
+.cu-load.erro::after {
+ content: "加载失败";
+}
+
+.cu-load.load-cuIcon::before {
+ font-size: 32upx;
+}
+
+.cu-load.load-cuIcon::after {
+ display: none;
+}
+
+.cu-load.load-cuIcon.over {
+ display: none;
+}
+
+.cu-load.load-modal {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 140upx;
+ left: 0;
+ margin: auto;
+ width: 260upx;
+ height: 260upx;
+ background-color: #ffffff;
+ border-radius: 10upx;
+ box-shadow: 0 0 0upx 2000upx rgba(0, 0, 0, 0.5);
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ justify-content: center;
+ font-size: 28upx;
+ z-index: 9999;
+ line-height: 2.4em;
+}
+
+.cu-load.load-modal [class*="cuIcon-"] {
+ font-size: 60upx;
+}
+
+.cu-load.load-modal image {
+ width: 70upx;
+ height: 70upx;
+}
+
+.cu-load.load-modal::after {
+ content: "";
+ position: absolute;
+ background-color: #ffffff;
+ border-radius: 50%;
+ width: 200upx;
+ height: 200upx;
+ font-size: 10px;
+ border-top: 6upx solid rgba(0, 0, 0, 0.05);
+ border-right: 6upx solid rgba(0, 0, 0, 0.05);
+ border-bottom: 6upx solid rgba(0, 0, 0, 0.05);
+ border-left: 6upx solid #f37b1d;
+ animation: cuIcon-spin 1s infinite linear;
+ z-index: -1;
+}
+
+.load-progress {
+ pointer-events: none;
+ top: 0;
+ position: fixed;
+ width: 100%;
+ left: 0;
+ z-index: 2000;
+}
+
+.load-progress.hide {
+ display: none;
+}
+
+.load-progress .load-progress-bar {
+ position: relative;
+ width: 100%;
+ height: 4upx;
+ overflow: hidden;
+ transition: all 200ms ease 0s;
+}
+
+.load-progress .load-progress-spinner {
+ position: absolute;
+ top: 10upx;
+ right: 10upx;
+ z-index: 2000;
+ display: block;
+}
+
+.load-progress .load-progress-spinner::after {
+ content: "";
+ display: block;
+ width: 24upx;
+ height: 24upx;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ border: solid 4upx transparent;
+ border-top-color: inherit;
+ border-left-color: inherit;
+ border-radius: 50%;
+ -webkit-animation: load-progress-spinner 0.4s linear infinite;
+ animation: load-progress-spinner 0.4s linear infinite;
+}
+
+@-webkit-keyframes load-progress-spinner {
+ 0% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ }
+
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes load-progress-spinner {
+ 0% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ }
+
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+/* ==================
+ 列表
+ ==================== */
+.grayscale {
+ filter: grayscale(1);
+}
+
+.cu-list+.cu-list {
+ margin-top: 30upx
+}
+
+.cu-list>.cu-item {
+ transition: all .6s ease-in-out 0s;
+ transform: translateX(0upx)
+}
+
+.cu-list>.cu-item.move-cur {
+ transform: translateX(-260upx)
+}
+
+.cu-list>.cu-item .move {
+ position: absolute;
+ right: 0;
+ display: flex;
+ width: 260upx;
+ height: 100%;
+ transform: translateX(100%)
+}
+
+.cu-list>.cu-item .move view {
+ display: flex;
+ flex: 1;
+ justify-content: center;
+ align-items: center
+}
+
+.cu-list.menu-avatar {
+ overflow: hidden;
+}
+
+.cu-list.menu-avatar>.cu-item {
+ position: relative;
+ display: flex;
+ padding-right: 10upx;
+ height: 140upx;
+ background-color: #ffffff;
+ justify-content: flex-end;
+ align-items: center
+}
+
+.cu-list.menu-avatar>.cu-item>.cu-avatar {
+ position: absolute;
+ left: 30upx
+}
+
+.cu-list.menu-avatar>.cu-item .flex .text-cut {
+ max-width: 510upx
+}
+
+.cu-list.menu-avatar>.cu-item .content {
+ position: absolute;
+ left: 146upx;
+ width: calc(100% - 96upx - 60upx - 120upx - 20upx);
+ line-height: 1.6em;
+}
+
+.cu-list.menu-avatar>.cu-item .content.flex-sub {
+ width: calc(100% - 96upx - 60upx - 20upx);
+}
+
+.cu-list.menu-avatar>.cu-item .content>view:first-child {
+ font-size: 30upx;
+ display: flex;
+ align-items: center
+}
+
+.cu-list.menu-avatar>.cu-item .content .cu-tag.sm {
+ display: inline-block;
+ margin-left: 10upx;
+ height: 28upx;
+ font-size: 16upx;
+ line-height: 32upx
+}
+
+.cu-list.menu-avatar>.cu-item .action {
+ width: 100upx;
+ text-align: center
+}
+
+.cu-list.menu-avatar>.cu-item .action view+view {
+ margin-top: 10upx
+}
+
+.cu-list.menu-avatar.comment>.cu-item .content {
+ position: relative;
+ left: 0;
+ width: auto;
+ flex: 1;
+}
+
+.cu-list.menu-avatar.comment>.cu-item {
+ padding: 30upx 30upx 30upx 120upx;
+ height: auto
+}
+
+.cu-list.menu-avatar.comment .cu-avatar {
+ align-self: flex-start
+}
+
+.cu-list.menu>.cu-item {
+ position: relative;
+ display: flex;
+ padding: 0 30upx;
+ min-height: 100upx;
+ background-color: #ffffff;
+ justify-content: space-between;
+ align-items: center
+}
+
+.cu-list.menu>.cu-item:last-child:after {
+ border: none
+}
+
+.cu-list.menu-avatar>.cu-item:after,
+.cu-list.menu>.cu-item:after {
+ position: absolute;
+ top: 0;
+ left: 0;
+ box-sizing: border-box;
+ width: 200%;
+ height: 200%;
+ border-bottom: 1upx solid #ddd;
+ border-radius: inherit;
+ content: " ";
+ transform: scale(.5);
+ transform-origin: 0 0;
+ pointer-events: none
+}
+
+.cu-list.menu>.cu-item.grayscale {
+ background-color: #f5f5f5
+}
+
+.cu-list.menu>.cu-item.cur {
+ background-color: #fcf7e9
+}
+
+.cu-list.menu>.cu-item.arrow {
+ padding-right: 90upx
+}
+
+.cu-list.menu>.cu-item.arrow:before {
+ position: absolute;
+ top: 0;
+ right: 30upx;
+ bottom: 0;
+ display: block;
+ margin: auto;
+ width: 30upx;
+ height: 30upx;
+ color: #8799a3;
+ content: "\e6a3";
+ text-align: center;
+ font-size: 34upx;
+ font-family: cuIcon;
+ line-height: 30upx
+}
+
+.cu-list.menu>.cu-item button.content {
+ padding: 0;
+ background-color: transparent;
+ justify-content: flex-start
+}
+
+.cu-list.menu>.cu-item button.content:after {
+ display: none
+}
+
+.cu-list.menu>.cu-item .cu-avatar-group .cu-avatar {
+ border-color: #ffffff
+}
+
+.cu-list.menu>.cu-item .content>view:first-child {
+ display: flex;
+ align-items: center
+}
+
+.cu-list.menu>.cu-item .content>text[class*=cuIcon] {
+ display: inline-block;
+ margin-right: 10upx;
+ width: 1.6em;
+ text-align: center
+}
+
+.cu-list.menu>.cu-item .content>image {
+ display: inline-block;
+ margin-right: 10upx;
+ width: 1.6em;
+ height: 1.6em;
+ vertical-align: middle
+}
+
+.cu-list.menu>.cu-item .content {
+ font-size: 30upx;
+ line-height: 1.6em;
+ flex: 1
+}
+
+.cu-list.menu>.cu-item .content .cu-tag.sm {
+ display: inline-block;
+ margin-left: 10upx;
+ height: 28upx;
+ font-size: 16upx;
+ line-height: 32upx
+}
+
+.cu-list.menu>.cu-item .action .cu-tag:empty {
+ right: 10upx
+}
+
+.cu-list.menu {
+ display: block;
+ overflow: hidden
+}
+
+.cu-list.menu.sm-border>.cu-item:after {
+ left: 30upx;
+ width: calc(200% - 120upx)
+}
+
+.cu-list.grid>.cu-item {
+ position: relative;
+ display: flex;
+ padding: 20upx 0 30upx;
+ transition-duration: 0s;
+ flex-direction: column
+}
+
+.cu-list.grid>.cu-item:after {
+ position: absolute;
+ top: 0;
+ left: 0;
+ box-sizing: border-box;
+ width: 200%;
+ height: 200%;
+ border-right: 1px solid rgba(0, 0, 0, .1);
+ border-bottom: 1px solid rgba(0, 0, 0, .1);
+ border-radius: inherit;
+ content: " ";
+ transform: scale(.5);
+ transform-origin: 0 0;
+ pointer-events: none
+}
+
+.cu-list.grid>.cu-item text {
+ display: block;
+ margin-top: 10upx;
+ color: #888;
+ font-size: 26upx;
+ line-height: 40upx
+}
+
+.cu-list.grid>.cu-item [class*=cuIcon] {
+ position: relative;
+ display: block;
+ margin-top: 20upx;
+ width: 100%;
+ font-size: 48upx
+}
+
+.cu-list.grid>.cu-item .cu-tag {
+ right: auto;
+ left: 50%;
+ margin-left: 20upx
+}
+
+.cu-list.grid {
+ background-color: #ffffff;
+ text-align: center
+}
+
+.cu-list.grid.no-border>.cu-item {
+ padding-top: 10upx;
+ padding-bottom: 20upx
+}
+
+.cu-list.grid.no-border>.cu-item:after {
+ border: none
+}
+
+.cu-list.grid.no-border {
+ padding: 20upx 10upx
+}
+
+.cu-list.grid.col-3>.cu-item:nth-child(3n):after,
+.cu-list.grid.col-4>.cu-item:nth-child(4n):after,
+.cu-list.grid.col-5>.cu-item:nth-child(5n):after {
+ border-right-width: 0
+}
+
+.cu-list.card-menu {
+ overflow: hidden;
+ margin-right: 30upx;
+ margin-left: 30upx;
+ border-radius: 20upx
+}
+
+
+/* ==================
+ 操作条
+ ==================== */
+
+.cu-bar {
+ display: flex;
+ position: relative;
+ align-items: center;
+ min-height: 100upx;
+ justify-content: space-between;
+}
+
+.cu-bar .action {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ justify-content: center;
+ max-width: 100%;
+}
+
+.cu-bar .action.border-title {
+ position: relative;
+ top: -10upx;
+}
+
+.cu-bar .action.border-title text[class*="bg-"]:last-child {
+ position: absolute;
+ bottom: -0.5rem;
+ min-width: 2rem;
+ height: 6upx;
+ left: 0;
+}
+
+.cu-bar .action.sub-title {
+ position: relative;
+ top: -0.2rem;
+}
+
+.cu-bar .action.sub-title text {
+ position: relative;
+ z-index: 1;
+}
+
+.cu-bar .action.sub-title text[class*="bg-"]:last-child {
+ position: absolute;
+ display: inline-block;
+ bottom: -0.2rem;
+ border-radius: 6upx;
+ width: 100%;
+ height: 0.6rem;
+ left: 0.6rem;
+ opacity: 0.3;
+ z-index: 0;
+}
+
+.cu-bar .action.sub-title text[class*="text-"]:last-child {
+ position: absolute;
+ display: inline-block;
+ bottom: -0.7rem;
+ left: 0.5rem;
+ opacity: 0.2;
+ z-index: 0;
+ text-align: right;
+ font-weight: 900;
+ font-size: 36upx;
+}
+
+.cu-bar.justify-center .action.border-title text:last-child,
+.cu-bar.justify-center .action.sub-title text:last-child {
+ left: 0;
+ right: 0;
+ margin: auto;
+ text-align: center;
+}
+
+.cu-bar .action:first-child {
+ margin-left: 30upx;
+ font-size: 30upx;
+}
+
+.cu-bar .action text.text-cut {
+ text-align: left;
+ width: 100%;
+}
+
+.cu-bar .cu-avatar:first-child {
+ margin-left: 20upx;
+}
+
+.cu-bar .action:first-child>text[class*="cuIcon-"] {
+ margin-left: -0.3em;
+ margin-right: 0.3em;
+}
+
+.cu-bar .action:last-child {
+ margin-right: 30upx;
+}
+
+.cu-bar .action>text[class*="cuIcon-"],
+.cu-bar .action>view[class*="cuIcon-"] {
+ font-size: 36upx;
+}
+
+.cu-bar .action>text[class*="cuIcon-"]+text[class*="cuIcon-"] {
+ margin-left: 0.5em;
+}
+
+.cu-bar .content {
+ position: absolute;
+ text-align: center;
+ width: calc(100% - 340upx);
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: 0;
+ margin: auto;
+ height: 60upx;
+ font-size: 32upx;
+ line-height: 60upx;
+ cursor: none;
+ pointer-events: none;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+.cu-bar.ios .content {
+ bottom: 7px;
+ height: 30px;
+ font-size: 32upx;
+ line-height: 30px;
+}
+
+.cu-bar.btn-group {
+ justify-content: space-around;
+}
+
+.cu-bar.btn-group button {
+ padding: 20upx 32upx;
+}
+
+.cu-bar.btn-group button {
+ flex: 1;
+ margin: 0 20upx;
+ max-width: 50%;
+}
+
+.cu-bar .search-form {
+ background-color: #f5f5f5;
+ line-height: 64upx;
+ height: 64upx;
+ font-size: 24upx;
+ color: #333333;
+ flex: 1;
+ display: flex;
+ align-items: center;
+ margin: 0 30upx;
+}
+
+.cu-bar .search-form+.action {
+ margin-right: 30upx;
+}
+
+.cu-bar .search-form input {
+ flex: 1;
+ padding-right: 30upx;
+ height: 64upx;
+ line-height: 64upx;
+ font-size: 26upx;
+ background-color: transparent;
+}
+
+.cu-bar .search-form [class*="cuIcon-"] {
+ margin: 0 0.5em 0 0.8em;
+}
+
+.cu-bar .search-form [class*="cuIcon-"]::before {
+ top: 0upx;
+}
+
+.cu-bar.fixed,
+.nav.fixed {
+ position: fixed;
+ width: 100%;
+ top: 0;
+ z-index: 1024;
+ box-shadow: 0 1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.foot {
+ position: fixed;
+ width: 100%;
+ bottom: 0;
+ z-index: 1024;
+ box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.tabbar {
+ padding: 0;
+ height: calc(100upx + env(safe-area-inset-bottom) / 2);
+ padding-bottom: calc(env(safe-area-inset-bottom) / 2);
+}
+
+.cu-tabbar-height {
+ min-height: 100upx;
+ height: calc(100upx + env(safe-area-inset-bottom) / 2);
+}
+
+.cu-bar.tabbar.shadow {
+ box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.tabbar .action {
+ font-size: 22upx;
+ position: relative;
+ flex: 1;
+ text-align: center;
+ padding: 0;
+ display: block;
+ height: auto;
+ line-height: 1;
+ margin: 0;
+ background-color: inherit;
+ overflow: initial;
+}
+
+.cu-bar.tabbar.shop .action {
+ width: 140upx;
+ flex: initial;
+}
+
+.cu-bar.tabbar .action.add-action {
+ position: relative;
+ z-index: 2;
+ padding-top: 50upx;
+}
+
+.cu-bar.tabbar .action.add-action [class*="cuIcon-"] {
+ position: absolute;
+ width: 70upx;
+ z-index: 2;
+ height: 70upx;
+ border-radius: 50%;
+ line-height: 70upx;
+ font-size: 50upx;
+ top: -35upx;
+ left: 0;
+ right: 0;
+ margin: auto;
+ padding: 0;
+}
+
+.cu-bar.tabbar .action.add-action::after {
+ content: "";
+ position: absolute;
+ width: 100upx;
+ height: 100upx;
+ top: -50upx;
+ left: 0;
+ right: 0;
+ margin: auto;
+ box-shadow: 0 -3upx 8upx rgba(0, 0, 0, 0.08);
+ border-radius: 50upx;
+ background-color: inherit;
+ z-index: 0;
+}
+
+.cu-bar.tabbar .action.add-action::before {
+ content: "";
+ position: absolute;
+ width: 100upx;
+ height: 30upx;
+ bottom: 30upx;
+ left: 0;
+ right: 0;
+ margin: auto;
+ background-color: inherit;
+ z-index: 1;
+}
+
+.cu-bar.tabbar .btn-group {
+ flex: 1;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+ padding: 0 10upx;
+}
+
+.cu-bar.tabbar button.action::after {
+ border: 0;
+}
+
+.cu-bar.tabbar .action [class*="cuIcon-"] {
+ width: 100upx;
+ position: relative;
+ display: block;
+ height: auto;
+ margin: 0 auto 10upx;
+ text-align: center;
+ font-size: 40upx;
+}
+
+.cu-bar.tabbar .action .cuIcon-cu-image {
+ margin: 0 auto;
+}
+
+.cu-bar.tabbar .action .cuIcon-cu-image image {
+ width: 50upx;
+ height: 50upx;
+ display: inline-block;
+}
+
+.cu-bar.tabbar .submit {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+ text-align: center;
+ position: relative;
+ flex: 2;
+ align-self: stretch;
+}
+
+.cu-bar.tabbar .submit:last-child {
+ flex: 2.6;
+}
+
+.cu-bar.tabbar .submit+.submit {
+ flex: 2;
+}
+
+.cu-bar.tabbar.border .action::before {
+ content: " ";
+ width: 200%;
+ height: 200%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ border-right: 1upx solid rgba(0, 0, 0, 0.1);
+ z-index: 3;
+}
+
+.cu-bar.tabbar.border .action:last-child:before {
+ display: none;
+}
+
+.cu-bar.input {
+ padding-right: 20upx;
+ background-color: #ffffff;
+}
+
+.cu-bar.input input {
+ overflow: initial;
+ line-height: 64upx;
+ height: 64upx;
+ min-height: 64upx;
+ flex: 1;
+ font-size: 30upx;
+ margin: 0 20upx;
+}
+
+.cu-bar.input .action {
+ margin-left: 20upx;
+}
+
+.cu-bar.input .action [class*="cuIcon-"] {
+ font-size: 48upx;
+}
+
+.cu-bar.input input+.action {
+ margin-right: 20upx;
+ margin-left: 0upx;
+}
+
+.cu-bar.input .action:first-child [class*="cuIcon-"] {
+ margin-left: 0upx;
+}
+
+.cu-custom {
+ display: block;
+ position: relative;
+}
+
+.cu-custom .cu-bar .content {
+ width: calc(100% - 440upx);
+}
+
+/* #ifdef MP-ALIPAY */
+.cu-custom .cu-bar .action .cuIcon-back {
+ opacity: 0;
+}
+
+/* #endif */
+
+.cu-custom .cu-bar .content image {
+ height: 60upx;
+ width: 240upx;
+}
+
+.cu-custom .cu-bar {
+ min-height: 0px;
+ /* #ifdef MP-WEIXIN */
+ padding-right: 220upx;
+ /* #endif */
+ /* #ifdef MP-ALIPAY */
+ padding-right: 150upx;
+ /* #endif */
+ box-shadow: 0upx 0upx 0upx;
+ z-index: 9999;
+}
+
+.cu-custom .cu-bar .border-custom {
+ position: relative;
+ background: rgba(0, 0, 0, 0.15);
+ border-radius: 1000upx;
+ height: 30px;
+}
+
+.cu-custom .cu-bar .border-custom::after {
+ content: " ";
+ width: 200%;
+ height: 200%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border-radius: inherit;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ pointer-events: none;
+ box-sizing: border-box;
+ border: 1upx solid #ffffff;
+ opacity: 0.5;
+}
+
+.cu-custom .cu-bar .border-custom::before {
+ content: " ";
+ width: 1upx;
+ height: 110%;
+ position: absolute;
+ top: 22.5%;
+ left: 0;
+ right: 0;
+ margin: auto;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ pointer-events: none;
+ box-sizing: border-box;
+ opacity: 0.6;
+ background-color: #ffffff;
+}
+
+.cu-custom .cu-bar .border-custom text {
+ display: block;
+ flex: 1;
+ margin: auto !important;
+ text-align: center;
+ font-size: 34upx;
+}
+
+/* ==================
+ 导航栏
+ ==================== */
+
+.nav {
+ white-space: nowrap;
+}
+
+::-webkit-scrollbar {
+ display: none;
+}
+
+.nav .cu-item {
+ height: 90upx;
+ display: inline-block;
+ line-height: 90upx;
+ margin: 0 10upx;
+ padding: 0 20upx;
+}
+
+.nav .cu-item.cur {
+ border-bottom: 4upx solid;
+}
+
+/* ==================
+ 时间轴
+ ==================== */
+
+.cu-timeline {
+ display: block;
+ background-color: #ffffff;
+}
+
+.cu-timeline .cu-time {
+ width: 120upx;
+ text-align: center;
+ padding: 20upx 0;
+ font-size: 26upx;
+ color: #888;
+ display: block;
+}
+
+.cu-timeline>.cu-item {
+ padding: 30upx 30upx 30upx 120upx;
+ position: relative;
+ display: block;
+ z-index: 0;
+}
+
+.cu-timeline>.cu-item:not([class*="text-"]) {
+ color: #ccc;
+}
+
+.cu-timeline>.cu-item::after {
+ content: "";
+ display: block;
+ position: absolute;
+ width: 1upx;
+ background-color: #ddd;
+ left: 60upx;
+ height: 100%;
+ top: 0;
+ z-index: 8;
+}
+
+.cu-timeline>.cu-item::before {
+ font-family: "cuIcon";
+ display: block;
+ position: absolute;
+ top: 36upx;
+ z-index: 9;
+ background-color: #ffffff;
+ width: 50upx;
+ height: 50upx;
+ text-align: center;
+ border: none;
+ line-height: 50upx;
+ left: 36upx;
+}
+
+.cu-timeline>.cu-item:not([class*="cuIcon-"])::before {
+ content: "\e763";
+}
+
+.cu-timeline>.cu-item[class*="cuIcon-"]::before {
+ background-color: #ffffff;
+ width: 50upx;
+ height: 50upx;
+ text-align: center;
+ border: none;
+ line-height: 50upx;
+ left: 36upx;
+}
+
+.cu-timeline>.cu-item>.content {
+ padding: 30upx;
+ border-radius: 6upx;
+ display: block;
+ line-height: 1.6;
+}
+
+.cu-timeline>.cu-item>.content:not([class*="bg-"]) {
+ background-color: #f1f1f1;
+ color: #333333;
+}
+
+.cu-timeline>.cu-item>.content+.content {
+ margin-top: 20upx;
+}
+
+/* ==================
+ 聊天
+ ==================== */
+
+.cu-chat {
+ display: flex;
+ flex-direction: column;
+}
+
+.cu-chat .cu-item {
+ display: flex;
+ padding: 30upx 30upx 70upx;
+ position: relative;
+}
+
+.cu-chat .cu-item>.cu-avatar {
+ width: 80upx;
+ height: 80upx;
+}
+
+.cu-chat .cu-item>.main {
+ max-width: calc(100% - 260upx);
+ margin: 0 40upx;
+ display: flex;
+ align-items: center;
+}
+
+.cu-chat .cu-item>image {
+ height: 320upx;
+}
+
+.cu-chat .cu-item>.main .content {
+ padding: 20upx;
+ border-radius: 6upx;
+ display: inline-flex;
+ max-width: 100%;
+ align-items: center;
+ font-size: 30upx;
+ position: relative;
+ min-height: 80upx;
+ line-height: 40upx;
+ text-align: left;
+}
+
+.cu-chat .cu-item>.main .content:not([class*="bg-"]) {
+ background-color: #ffffff;
+ color: #333333;
+}
+
+.cu-chat .cu-item .date {
+ position: absolute;
+ font-size: 24upx;
+ color: #8799a3;
+ width: calc(100% - 320upx);
+ bottom: 20upx;
+ left: 160upx;
+}
+
+.cu-chat .cu-item .action {
+ padding: 0 30upx;
+ display: flex;
+ align-items: center;
+}
+
+.cu-chat .cu-item>.main .content::after {
+ content: "";
+ top: 27upx;
+ transform: rotate(45deg);
+ position: absolute;
+ z-index: 100;
+ display: inline-block;
+ overflow: hidden;
+ width: 24upx;
+ height: 24upx;
+ left: -12upx;
+ right: initial;
+ background-color: inherit;
+}
+
+.cu-chat .cu-item.self>.main .content::after {
+ left: auto;
+ right: -12upx;
+}
+
+.cu-chat .cu-item>.main .content::before {
+ content: "";
+ top: 30upx;
+ transform: rotate(45deg);
+ position: absolute;
+ z-index: -1;
+ display: inline-block;
+ overflow: hidden;
+ width: 24upx;
+ height: 24upx;
+ left: -12upx;
+ right: initial;
+ background-color: inherit;
+ filter: blur(5upx);
+ opacity: 0.3;
+}
+
+.cu-chat .cu-item>.main .content:not([class*="bg-"])::before {
+ background-color: #333333;
+ opacity: 0.1;
+}
+
+.cu-chat .cu-item.self>.main .content::before {
+ left: auto;
+ right: -12upx;
+}
+
+.cu-chat .cu-item.self {
+ justify-content: flex-end;
+ text-align: right;
+}
+
+.cu-chat .cu-info {
+ display: inline-block;
+ margin: 20upx auto;
+ font-size: 24upx;
+ padding: 8upx 12upx;
+ background-color: rgba(0, 0, 0, 0.2);
+ border-radius: 6upx;
+ color: #ffffff;
+ max-width: 400upx;
+ line-height: 1.4;
+}
+
+/* ==================
+ 卡片
+ ==================== */
+
+.cu-card {
+ display: block;
+ overflow: hidden;
+}
+
+.cu-card>.cu-item {
+ display: block;
+ background-color: #ffffff;
+ overflow: hidden;
+ border-radius: 10upx;
+ margin: 30upx;
+}
+
+.cu-card>.cu-item.shadow-blur {
+ overflow: initial;
+}
+
+.cu-card.no-card>.cu-item {
+ margin: 0upx;
+ border-radius: 0upx;
+}
+
+.cu-card .grid.grid-square {
+ margin-bottom: -20upx;
+}
+
+.cu-card.case .image {
+ position: relative;
+}
+
+.cu-card.case .image image {
+ width: 100%;
+}
+
+.cu-card.case .image .cu-tag {
+ position: absolute;
+ right: 0;
+ top: 0;
+}
+
+.cu-card.case .image .cu-bar {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ background-color: transparent;
+ padding: 0upx 30upx;
+}
+
+.cu-card.case.no-card .image {
+ margin: 30upx 30upx 0;
+ overflow: hidden;
+ border-radius: 10upx;
+}
+
+.cu-card.dynamic {
+ display: block;
+}
+
+.cu-card.dynamic>.cu-item {
+ display: block;
+ background-color: #ffffff;
+ overflow: hidden;
+}
+
+.cu-card.dynamic>.cu-item>.text-content {
+ padding: 0 30upx 0;
+ max-height: 6.4em;
+ overflow: hidden;
+ font-size: 30upx;
+ margin-bottom: 20upx;
+}
+
+.cu-card.dynamic>.cu-item .square-img {
+ width: 100%;
+ height: 200upx;
+ border-radius: 6upx;
+}
+
+.cu-card.dynamic>.cu-item .only-img {
+ width: 100%;
+ height: 320upx;
+ border-radius: 6upx;
+}
+
+/* card.dynamic>.cu-item .comment {
+ padding: 20upx;
+ background-color: #f1f1f1;
+ margin: 0 30upx 30upx;
+ border-radius: 6upx;
+} */
+
+.cu-card.article {
+ display: block;
+}
+
+.cu-card.article>.cu-item {
+ padding-bottom: 30upx;
+}
+
+.cu-card.article>.cu-item .title {
+ font-size: 30upx;
+ font-weight: 900;
+ color: #333333;
+ line-height: 100upx;
+ padding: 0 30upx;
+}
+
+.cu-card.article>.cu-item .content {
+ display: flex;
+ padding: 0 30upx;
+}
+
+.cu-card.article>.cu-item .content>image {
+ width: 240upx;
+ height: 6.4em;
+ margin-right: 20upx;
+ border-radius: 6upx;
+}
+
+.cu-card.article>.cu-item .content .desc {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+}
+
+.cu-card.article>.cu-item .content .text-content {
+ font-size: 28upx;
+ color: #888;
+ height: 4.8em;
+ overflow: hidden;
+}
+
+/* ==================
+ 表单
+ ==================== */
+
+.cu-form-group {
+ background-color: #ffffff;
+ padding: 1upx 30upx;
+ display: flex;
+ align-items: center;
+ min-height: 100upx;
+ justify-content: space-between;
+}
+
+.cu-form-group+.cu-form-group {
+ border-top: 1upx solid #eee;
+}
+
+.cu-form-group .title {
+ text-align: justify;
+ padding-right: 30upx;
+ font-size: 30upx;
+ position: relative;
+ height: 60upx;
+ line-height: 60upx;
+}
+
+.cu-form-group input {
+ flex: 1;
+ font-size: 30upx;
+ color: #555;
+ padding-right: 20upx;
+}
+
+.cu-form-group>text[class*="cuIcon-"] {
+ font-size: 36upx;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+.cu-form-group textarea {
+ margin: 32upx 0 30upx;
+ height: 4.6em;
+ width: 100%;
+ line-height: 1.2em;
+ flex: 1;
+ font-size: 28upx;
+ padding: 0;
+}
+
+.cu-form-group.align-start .title {
+ height: 1em;
+ margin-top: 32upx;
+ line-height: 1em;
+}
+
+.cu-form-group picker {
+ flex: 1;
+ padding-right: 40upx;
+ overflow: hidden;
+ position: relative;
+}
+
+.cu-form-group picker .picker {
+ line-height: 100upx;
+ font-size: 28upx;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ width: 100%;
+ text-align: right;
+}
+
+.cu-form-group picker::after {
+ font-family: cuIcon;
+ display: block;
+ content: "\e6a3";
+ position: absolute;
+ font-size: 34upx;
+ color: #8799a3;
+ line-height: 100upx;
+ width: 60upx;
+ text-align: center;
+ top: 0;
+ bottom: 0;
+ right: -20upx;
+ margin: auto;
+}
+
+.cu-form-group textarea[disabled],
+.cu-form-group textarea[disabled] .placeholder {
+ color: transparent;
+}
+
+/* ==================
+ 模态窗口
+ ==================== */
+
+.cu-modal {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1110;
+ opacity: 0;
+ outline: 0;
+ text-align: center;
+ -ms-transform: scale(1.185);
+ transform: scale(1.185);
+ backface-visibility: hidden;
+ perspective: 2000upx;
+ background: rgba(0, 0, 0, 0.6);
+ transition: all 0.3s ease-in-out 0s;
+ pointer-events: none;
+}
+
+.cu-modal::before {
+ content: "\200B";
+ display: inline-block;
+ height: 100%;
+ vertical-align: middle;
+}
+
+.cu-modal.show {
+ opacity: 1;
+ transition-duration: 0.3s;
+ -ms-transform: scale(1);
+ transform: scale(1);
+ overflow-x: hidden;
+ overflow-y: auto;
+ pointer-events: auto;
+}
+
+.cu-dialog {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+ margin-left: auto;
+ margin-right: auto;
+ width: 680upx;
+ max-width: 100%;
+ background-color: #f8f8f8;
+ border-radius: 10upx;
+ overflow: hidden;
+}
+
+.cu-modal.bottom-modal::before {
+ vertical-align: bottom;
+}
+
+.cu-modal.bottom-modal .cu-dialog {
+ width: 100%;
+ border-radius: 0;
+}
+
+.cu-modal.bottom-modal {
+ margin-bottom: -1000upx;
+}
+
+.cu-modal.bottom-modal.show {
+ margin-bottom: 0;
+}
+
+.cu-modal.drawer-modal {
+ transform: scale(1);
+ display: flex;
+}
+
+.cu-modal.drawer-modal .cu-dialog {
+ height: 100%;
+ min-width: 200upx;
+ border-radius: 0;
+ margin: initial;
+ transition-duration: 0.3s;
+}
+
+.cu-modal.drawer-modal.justify-start .cu-dialog {
+ transform: translateX(-100%);
+}
+
+.cu-modal.drawer-modal.justify-end .cu-dialog {
+ transform: translateX(100%);
+}
+
+.cu-modal.drawer-modal.show .cu-dialog {
+ transform: translateX(0%);
+}
+
+.cu-modal .cu-dialog>.cu-bar:first-child .action {
+ min-width: 100rpx;
+ margin-right: 0;
+ min-height: 100rpx;
+}
+
+/* ==================
+ 轮播
+ ==================== */
+swiper .a-swiper-dot {
+ display: inline-block;
+ width: 16upx;
+ height: 16upx;
+ background: rgba(0, 0, 0, .3);
+ border-radius: 50%;
+ vertical-align: middle;
+}
+
+swiper[class*="-dot"] .wx-swiper-dots,
+swiper[class*="-dot"] .a-swiper-dots,
+swiper[class*="-dot"] .uni-swiper-dots {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ justify-content: center;
+}
+
+swiper.square-dot .wx-swiper-dot,
+swiper.square-dot .a-swiper-dot,
+swiper.square-dot .uni-swiper-dot {
+ background-color: #ffffff;
+ opacity: 0.4;
+ width: 10upx;
+ height: 10upx;
+ border-radius: 20upx;
+ margin: 0 8upx !important;
+}
+
+swiper.square-dot .wx-swiper-dot.wx-swiper-dot-active,
+swiper.square-dot .a-swiper-dot.a-swiper-dot-active,
+swiper.square-dot .uni-swiper-dot.uni-swiper-dot-active {
+ opacity: 1;
+ width: 30upx;
+}
+
+swiper.round-dot .wx-swiper-dot,
+swiper.round-dot .a-swiper-dot,
+swiper.round-dot .uni-swiper-dot {
+ width: 10upx;
+ height: 10upx;
+ position: relative;
+ margin: 4upx 8upx !important;
+}
+
+swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active::after,
+swiper.round-dot .a-swiper-dot.a-swiper-dot-active::after,
+swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active::after {
+ content: "";
+ position: absolute;
+ width: 10upx;
+ height: 10upx;
+ top: 0upx;
+ left: 0upx;
+ right: 0;
+ bottom: 0;
+ margin: auto;
+ background-color: #ffffff;
+ border-radius: 20upx;
+}
+
+swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active,
+swiper.round-dot .a-swiper-dot.a-swiper-dot-active,
+swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active {
+ width: 18upx;
+ height: 18upx;
+}
+
+.screen-swiper {
+ min-height: 375upx;
+}
+
+.screen-swiper image,
+.screen-swiper video,
+.swiper-item image,
+.swiper-item video {
+ width: 100%;
+ display: block;
+ height: 100%;
+ margin: 0;
+ pointer-events: none;
+}
+
+.card-swiper {
+ height: 420upx !important;
+}
+
+.card-swiper swiper-item {
+ width: 610upx !important;
+ left: 70upx;
+ box-sizing: border-box;
+ padding: 40upx 0upx 70upx;
+ overflow: initial;
+}
+
+.card-swiper swiper-item .swiper-item {
+ width: 100%;
+ display: block;
+ height: 100%;
+ border-radius: 10upx;
+ transform: scale(0.9);
+ transition: all 0.2s ease-in 0s;
+ overflow: hidden;
+}
+
+.card-swiper swiper-item.cur .swiper-item {
+ transform: none;
+ transition: all 0.2s ease-in 0s;
+}
+
+
+.tower-swiper {
+ height: 420upx;
+ position: relative;
+ max-width: 750upx;
+ overflow: hidden;
+}
+
+.tower-swiper .tower-item {
+ position: absolute;
+ width: 300upx;
+ height: 380upx;
+ top: 0;
+ bottom: 0;
+ left: 50%;
+ margin: auto;
+ transition: all 0.2s ease-in 0s;
+ opacity: 1;
+}
+
+.tower-swiper .tower-item.none {
+ opacity: 0;
+}
+
+.tower-swiper .tower-item .swiper-item {
+ width: 100%;
+ height: 100%;
+ border-radius: 6upx;
+ overflow: hidden;
+}
+
+/* ==================
+ 步骤条
+ ==================== */
+
+.cu-steps {
+ display: flex;
+}
+
+scroll-view.cu-steps {
+ display: block;
+ white-space: nowrap;
+}
+
+scroll-view.cu-steps .cu-item {
+ display: inline-block;
+}
+
+.cu-steps .cu-item {
+ flex: 1;
+ text-align: center;
+ position: relative;
+ min-width: 100upx;
+}
+
+.cu-steps .cu-item:not([class*="text-"]) {
+ color: #8799a3;
+}
+
+.cu-steps .cu-item [class*="cuIcon-"],
+.cu-steps .cu-item .num {
+ display: block;
+ font-size: 40upx;
+ line-height: 80upx;
+}
+
+.cu-steps .cu-item::before,
+.cu-steps .cu-item::after,
+.cu-steps.steps-arrow .cu-item::before,
+.cu-steps.steps-arrow .cu-item::after {
+ content: "";
+ display: block;
+ position: absolute;
+ height: 0px;
+ width: calc(100% - 80upx);
+ border-bottom: 1px solid #ccc;
+ left: calc(0px - (100% - 80upx) / 2);
+ top: 40upx;
+ z-index: 0;
+}
+
+.cu-steps.steps-arrow .cu-item::before,
+.cu-steps.steps-arrow .cu-item::after {
+ content: "\e6a3";
+ font-family: 'cuIcon';
+ height: 30upx;
+ border-bottom-width: 0px;
+ line-height: 30upx;
+ top: 0;
+ bottom: 0;
+ margin: auto;
+ color: #ccc;
+}
+
+.cu-steps.steps-bottom .cu-item::before,
+.cu-steps.steps-bottom .cu-item::after {
+ bottom: 40upx;
+ top: initial;
+}
+
+.cu-steps .cu-item::after {
+ border-bottom: 1px solid currentColor;
+ width: 0px;
+ transition: all 0.3s ease-in-out 0s;
+}
+
+.cu-steps .cu-item[class*="text-"]::after {
+ width: calc(100% - 80upx);
+ color: currentColor;
+}
+
+.cu-steps .cu-item:first-child::before,
+.cu-steps .cu-item:first-child::after {
+ display: none;
+}
+
+.cu-steps .cu-item .num {
+ width: 40upx;
+ height: 40upx;
+ border-radius: 50%;
+ line-height: 40upx;
+ margin: 20upx auto;
+ font-size: 24upx;
+ border: 1px solid currentColor;
+ position: relative;
+ overflow: hidden;
+}
+
+.cu-steps .cu-item[class*="text-"] .num {
+ background-color: currentColor;
+}
+
+.cu-steps .cu-item .num::before,
+.cu-steps .cu-item .num::after {
+ content: attr(data-index);
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ margin: auto;
+ transition: all 0.3s ease-in-out 0s;
+ transform: translateY(0upx);
+}
+
+.cu-steps .cu-item[class*="text-"] .num::before {
+ transform: translateY(-40upx);
+ color: #ffffff;
+}
+
+.cu-steps .cu-item .num::after {
+ transform: translateY(40upx);
+ color: #ffffff;
+ transition: all 0.3s ease-in-out 0s;
+}
+
+.cu-steps .cu-item[class*="text-"] .num::after {
+ content: "\e645";
+ font-family: 'cuIcon';
+ color: #ffffff;
+ transform: translateY(0upx);
+}
+
+.cu-steps .cu-item[class*="text-"] .num.err::after {
+ content: "\e646";
+}
+
+/* ==================
+ 布局
+ ==================== */
+
+/* -- flex弹性布局 -- */
+
+.flex {
+ display: flex;
+}
+
+.basis-xs {
+ flex-basis: 20%;
+}
+
+.basis-sm {
+ flex-basis: 40%;
+}
+
+.basis-df {
+ flex-basis: 50%;
+}
+
+.basis-lg {
+ flex-basis: 60%;
+}
+
+.basis-xl {
+ flex-basis: 80%;
+}
+
+.flex-sub {
+ flex: 1;
+}
+
+.flex-twice {
+ flex: 2;
+}
+
+.flex-treble {
+ flex: 3;
+}
+
+.flex-direction {
+ flex-direction: column;
+}
+
+.flex-wrap {
+ flex-wrap: wrap;
+}
+
+.align-start {
+ align-items: flex-start;
+}
+
+.align-end {
+ align-items: flex-end;
+}
+
+.align-center {
+ align-items: center;
+}
+
+.align-stretch {
+ align-items: stretch;
+}
+
+.self-start {
+ align-self: flex-start;
+}
+
+.self-center {
+ align-self: flex-center;
+}
+
+.self-end {
+ align-self: flex-end;
+}
+
+.self-stretch {
+ align-self: stretch;
+}
+
+.align-stretch {
+ align-items: stretch;
+}
+
+.justify-start {
+ justify-content: flex-start;
+}
+
+.justify-end {
+ justify-content: flex-end;
+}
+
+.justify-center {
+ justify-content: center;
+}
+
+.justify-between {
+ justify-content: space-between;
+}
+
+.justify-around {
+ justify-content: space-around;
+}
+
+/* grid布局 */
+
+.grid {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.grid.grid-square {
+ overflow: hidden;
+}
+
+.grid.grid-square .cu-tag {
+ position: absolute;
+ right: 0;
+ top: 0;
+ border-bottom-left-radius: 6upx;
+ padding: 6upx 12upx;
+ height: auto;
+ background-color: rgba(0, 0, 0, 0.5);
+}
+
+.grid.grid-square>view>text[class*="cuIcon-"] {
+ font-size: 52upx;
+ position: absolute;
+ color: #8799a3;
+ margin: auto;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+}
+
+.grid.grid-square>view {
+ margin-right: 20upx;
+ margin-bottom: 20upx;
+ border-radius: 6upx;
+ position: relative;
+ overflow: hidden;
+}
+
+.grid.grid-square>view.bg-img image {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+}
+
+.grid.col-1.grid-square>view {
+ padding-bottom: 100%;
+ height: 0;
+ margin-right: 0;
+}
+
+.grid.col-2.grid-square>view {
+ padding-bottom: calc((100% - 20upx)/2);
+ height: 0;
+ width: calc((100% - 20upx)/2);
+}
+
+.grid.col-3.grid-square>view {
+ padding-bottom: calc((100% - 40upx)/3);
+ height: 0;
+ width: calc((100% - 40upx)/3);
+}
+
+.grid.col-4.grid-square>view {
+ padding-bottom: calc((100% - 60upx)/4);
+ height: 0;
+ width: calc((100% - 60upx)/4);
+}
+
+.grid.col-5.grid-square>view {
+ padding-bottom: calc((100% - 80upx)/5);
+ height: 0;
+ width: calc((100% - 80upx)/5);
+}
+
+.grid.col-2.grid-square>view:nth-child(2n),
+.grid.col-3.grid-square>view:nth-child(3n),
+.grid.col-4.grid-square>view:nth-child(4n),
+.grid.col-5.grid-square>view:nth-child(5n) {
+ margin-right: 0;
+}
+
+.grid.col-1>view {
+ width: 100%;
+}
+
+.grid.col-2>view {
+ width: 50%;
+}
+
+.grid.col-3>view {
+ width: 33.33%;
+}
+
+.grid.col-4>view {
+ width: 25%;
+}
+
+.grid.col-5>view {
+ width: 20%;
+}
+
+/* -- 内外边距 -- */
+
+.margin-0 {
+ margin: 0;
+}
+
+.margin-xs {
+ margin: 10upx;
+}
+
+.margin-sm {
+ margin: 20upx;
+}
+
+.margin {
+ margin: 30upx;
+}
+
+.margin-lg {
+ margin: 40upx;
+}
+
+.margin-xl {
+ margin: 50upx;
+}
+
+.margin-top-xs {
+ margin-top: 10upx;
+}
+
+.margin-top-sm {
+ margin-top: 20upx;
+}
+
+.margin-top {
+ margin-top: 30upx;
+}
+
+.margin-top-lg {
+ margin-top: 40upx;
+}
+
+.margin-top-xl {
+ margin-top: 50upx;
+}
+
+.margin-right-xs {
+ margin-right: 10upx;
+}
+
+.margin-right-sm {
+ margin-right: 20upx;
+}
+
+.margin-right {
+ margin-right: 30upx;
+}
+
+.margin-right-lg {
+ margin-right: 40upx;
+}
+
+.margin-right-xl {
+ margin-right: 50upx;
+}
+
+.margin-bottom-xs {
+ margin-bottom: 10upx;
+}
+
+.margin-bottom-sm {
+ margin-bottom: 20upx;
+}
+
+.margin-bottom {
+ margin-bottom: 30upx;
+}
+
+.margin-bottom-lg {
+ margin-bottom: 40upx;
+}
+
+.margin-bottom-xl {
+ margin-bottom: 50upx;
+}
+
+.margin-left-xs {
+ margin-left: 10upx;
+}
+
+.margin-left-sm {
+ margin-left: 20upx;
+}
+
+.margin-left {
+ margin-left: 30upx;
+}
+
+.margin-left-lg {
+ margin-left: 40upx;
+}
+
+.margin-left-xl {
+ margin-left: 50upx;
+}
+
+.margin-lr-xs {
+ margin-left: 10upx;
+ margin-right: 10upx;
+}
+
+.margin-lr-sm {
+ margin-left: 20upx;
+ margin-right: 20upx;
+}
+
+.margin-lr {
+ margin-left: 30upx;
+ margin-right: 30upx;
+}
+
+.margin-lr-lg {
+ margin-left: 40upx;
+ margin-right: 40upx;
+}
+
+.margin-lr-xl {
+ margin-left: 50upx;
+ margin-right: 50upx;
+}
+
+.margin-tb-xs {
+ margin-top: 10upx;
+ margin-bottom: 10upx;
+}
+
+.margin-tb-sm {
+ margin-top: 20upx;
+ margin-bottom: 20upx;
+}
+
+.margin-tb {
+ margin-top: 30upx;
+ margin-bottom: 30upx;
+}
+
+.margin-tb-lg {
+ margin-top: 40upx;
+ margin-bottom: 40upx;
+}
+
+.margin-tb-xl {
+ margin-top: 50upx;
+ margin-bottom: 50upx;
+}
+
+.padding-0 {
+ padding: 0;
+}
+
+.padding-xs {
+ padding: 10upx;
+}
+
+.padding-sm {
+ padding: 20upx;
+}
+
+.padding {
+ padding: 30upx;
+}
+
+.padding-lg {
+ padding: 40upx;
+}
+
+.padding-xl {
+ padding: 50upx;
+}
+
+.padding-top-xs {
+ padding-top: 10upx;
+}
+
+.padding-top-sm {
+ padding-top: 20upx;
+}
+
+.padding-top {
+ padding-top: 30upx;
+}
+
+.padding-top-lg {
+ padding-top: 40upx;
+}
+
+.padding-top-xl {
+ padding-top: 50upx;
+}
+
+.padding-right-xs {
+ padding-right: 10upx;
+}
+
+.padding-right-sm {
+ padding-right: 20upx;
+}
+
+.padding-right {
+ padding-right: 30upx;
+}
+
+.padding-right-lg {
+ padding-right: 40upx;
+}
+
+.padding-right-xl {
+ padding-right: 50upx;
+}
+
+.padding-bottom-xs {
+ padding-bottom: 10upx;
+}
+
+.padding-bottom-sm {
+ padding-bottom: 20upx;
+}
+
+.padding-bottom {
+ padding-bottom: 30upx;
+}
+
+.padding-bottom-lg {
+ padding-bottom: 40upx;
+}
+
+.padding-bottom-xl {
+ padding-bottom: 50upx;
+}
+
+.padding-left-xs {
+ padding-left: 10upx;
+}
+
+.padding-left-sm {
+ padding-left: 20upx;
+}
+
+.padding-left {
+ padding-left: 30upx;
+}
+
+.padding-left-lg {
+ padding-left: 40upx;
+}
+
+.padding-left-xl {
+ padding-left: 50upx;
+}
+
+.padding-lr-xs {
+ padding-left: 10upx;
+ padding-right: 10upx;
+}
+
+.padding-lr-sm {
+ padding-left: 20upx;
+ padding-right: 20upx;
+}
+
+.padding-lr {
+ padding-left: 30upx;
+ padding-right: 30upx;
+}
+
+.padding-lr-lg {
+ padding-left: 40upx;
+ padding-right: 40upx;
+}
+
+.padding-lr-xl {
+ padding-left: 50upx;
+ padding-right: 50upx;
+}
+
+.padding-tb-xs {
+ padding-top: 10upx;
+ padding-bottom: 10upx;
+}
+
+.padding-tb-sm {
+ padding-top: 20upx;
+ padding-bottom: 20upx;
+}
+
+.padding-tb {
+ padding-top: 30upx;
+ padding-bottom: 30upx;
+}
+
+.padding-tb-lg {
+ padding-top: 40upx;
+ padding-bottom: 40upx;
+}
+
+.padding-tb-xl {
+ padding-top: 50upx;
+ padding-bottom: 50upx;
+}
+
+/* -- 浮动 -- */
+
+.cf::after,
+.cf::before {
+ content: " ";
+ display: table;
+}
+
+.cf::after {
+ clear: both;
+}
+
+.fl {
+ float: left;
+}
+
+.fr {
+ float: right;
+}
+
+/* ==================
+ 背景
+ ==================== */
+
+.line-red::after,
+.lines-red::after {
+ border-color: #FF0000;
+}
+
+.line-orange::after,
+.lines-orange::after {
+ border-color: #f37b1d;
+}
+
+.line-yellow::after,
+.lines-yellow::after {
+ border-color: #fbbd08;
+}
+
+.line-olive::after,
+.lines-olive::after {
+ border-color: #8dc63f;
+}
+
+.line-green::after,
+.lines-green::after {
+ border-color: #39b54a;
+}
+
+.line-cyan::after,
+.lines-cyan::after {
+ border-color: #1cbbb4;
+}
+
+.line-blue::after,
+.lines-blue::after {
+ border-color: #0081ff;
+}
+
+.line-purple::after,
+.lines-purple::after {
+ border-color: #6739b6;
+}
+
+.line-mauve::after,
+.lines-mauve::after {
+ border-color: #9c26b0;
+}
+
+.line-pink::after,
+.lines-pink::after {
+ border-color: #e03997;
+}
+
+.line-brown::after,
+.lines-brown::after {
+ border-color: #a5673f;
+}
+
+.line-grey::after,
+.lines-grey::after {
+ border-color: #8799a3;
+}
+
+.line-gray::after,
+.lines-gray::after {
+ border-color: #aaaaaa;
+}
+
+.line-black::after,
+.lines-black::after {
+ border-color: #333333;
+}
+
+.line-white::after,
+.lines-white::after {
+ border-color: #ffffff;
+}
+
+.bg-red {
+ background-color: #FF0000;
+ color: #ffffff;
+}
+
+.bg-orange {
+ background-color: #f37b1d;
+ color: #ffffff;
+}
+
+.bg-yellow {
+ background-color: #fbbd08;
+ color: #333333;
+}
+
+.bg-olive {
+ background-color: #8dc63f;
+ color: #ffffff;
+}
+
+.bg-green {
+ background-color: #39b54a;
+ color: #ffffff;
+}
+
+.bg-cyan {
+ background-color: #1cbbb4;
+ color: #ffffff;
+}
+
+.bg-blue {
+ background-color: #0081ff;
+ color: #ffffff;
+}
+
+.bg-purple {
+ background-color: #6739b6;
+ color: #ffffff;
+}
+
+.bg-mauve {
+ background-color: #9c26b0;
+ color: #ffffff;
+}
+
+.bg-pink {
+ background-color: #e03997;
+ color: #ffffff;
+}
+
+.bg-brown {
+ background-color: #a5673f;
+ color: #ffffff;
+}
+
+.bg-grey {
+ background-color: #8799a3;
+ color: #ffffff;
+}
+
+.bg-gray {
+ background-color: #f0f0f0;
+ color: #333333;
+}
+
+.bg-black {
+ background-color: #333333;
+ color: #ffffff;
+}
+
+.bg-white {
+ background-color: #ffffff;
+ color: #666666;
+}
+
+.bg-shadeTop {
+ background-image: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0.01));
+ color: #ffffff;
+}
+
+.bg-shadeBottom {
+ background-image: linear-gradient(rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 1));
+ color: #ffffff;
+}
+
+.bg-red.light {
+ color: #FF0000;
+ background-color: #fadbd9;
+}
+
+.bg-orange.light {
+ color: #f37b1d;
+ background-color: #fde6d2;
+}
+
+.bg-yellow.light {
+ color: #fbbd08;
+ background-color: #fef2ced2;
+}
+
+.bg-olive.light {
+ color: #8dc63f;
+ background-color: #e8f4d9;
+}
+
+.bg-green.light {
+ color: #39b54a;
+ background-color: #d7f0dbff;
+}
+
+.bg-cyan.light {
+ color: #1cbbb4;
+ background-color: #d2f1f0;
+}
+
+.bg-blue.light {
+ color: #0081ff;
+ background-color: #cce6ff;
+}
+
+.bg-purple.light {
+ color: #6739b6;
+ background-color: #e1d7f0;
+}
+
+.bg-mauve.light {
+ color: #9c26b0;
+ background-color: #ebd4ef;
+}
+
+.bg-pink.light {
+ color: #e03997;
+ background-color: #f9d7ea;
+}
+
+.bg-brown.light {
+ color: #a5673f;
+ background-color: #ede1d9;
+}
+
+.bg-grey.light {
+ color: #8799a3;
+ background-color: #e7ebed;
+}
+
+.bg-gradual-red {
+ background-image: linear-gradient(45deg, #f43f3b, #ec008c);
+ color: #ffffff;
+}
+
+.bg-gradual-orange {
+ background-image: linear-gradient(45deg, #ff9700, #ed1c24);
+ color: #ffffff;
+}
+
+.bg-gradual-green {
+ background-image: linear-gradient(45deg, #39b54a, #8dc63f);
+ color: #ffffff;
+}
+
+.bg-gradual-purple {
+ background-image: linear-gradient(45deg, #9000ff, #5e00ff);
+ color: #ffffff;
+}
+
+.bg-gradual-pink {
+ background-image: linear-gradient(45deg, #ec008c, #6739b6);
+ color: #ffffff;
+}
+
+.bg-gradual-blue {
+ background-image: linear-gradient(45deg, #0081ff, #1cbbb4);
+ color: #ffffff;
+}
+
+.shadow[class*="-red"] {
+ box-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
+}
+
+.shadow[class*="-orange"] {
+ box-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
+}
+
+.shadow[class*="-yellow"] {
+ box-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
+}
+
+.shadow[class*="-olive"] {
+ box-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
+}
+
+.shadow[class*="-green"] {
+ box-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
+}
+
+.shadow[class*="-cyan"] {
+ box-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
+}
+
+.shadow[class*="-blue"] {
+ box-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
+}
+
+.shadow[class*="-purple"] {
+ box-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
+}
+
+.shadow[class*="-mauve"] {
+ box-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
+}
+
+.shadow[class*="-pink"] {
+ box-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
+}
+
+.shadow[class*="-brown"] {
+ box-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
+}
+
+.shadow[class*="-grey"] {
+ box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.shadow[class*="-gray"] {
+ box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.shadow[class*="-black"] {
+ box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.shadow[class*="-white"] {
+ box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.text-shadow[class*="-red"] {
+ text-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
+}
+
+.text-shadow[class*="-orange"] {
+ text-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
+}
+
+.text-shadow[class*="-yellow"] {
+ text-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
+}
+
+.text-shadow[class*="-olive"] {
+ text-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
+}
+
+.text-shadow[class*="-green"] {
+ text-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
+}
+
+.text-shadow[class*="-cyan"] {
+ text-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
+}
+
+.text-shadow[class*="-blue"] {
+ text-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
+}
+
+.text-shadow[class*="-purple"] {
+ text-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
+}
+
+.text-shadow[class*="-mauve"] {
+ text-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
+}
+
+.text-shadow[class*="-pink"] {
+ text-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
+}
+
+.text-shadow[class*="-brown"] {
+ text-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
+}
+
+.text-shadow[class*="-grey"] {
+ text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.text-shadow[class*="-gray"] {
+ text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.text-shadow[class*="-black"] {
+ text-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.bg-img {
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+.bg-mask {
+ background-color: #333333;
+ position: relative;
+}
+
+.bg-mask::after {
+ content: "";
+ border-radius: inherit;
+ width: 100%;
+ height: 100%;
+ display: block;
+ background-color: rgba(0, 0, 0, 0.4);
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: 0;
+}
+
+.bg-mask view,
+.bg-mask cover-view {
+ z-index: 5;
+ position: relative;
+}
+
+.bg-video {
+ position: relative;
+}
+
+.bg-video video {
+ display: block;
+ height: 100%;
+ width: 100%;
+ -o-object-fit: cover;
+ object-fit: cover;
+ position: absolute;
+ top: 0;
+ z-index: 0;
+ pointer-events: none;
+}
+
+/* ==================
+ 文本
+ ==================== */
+
+.text-xs {
+ font-size: 20upx;
+}
+
+.text-sm {
+ font-size: 24upx;
+}
+
+.text-df {
+ font-size: 28upx;
+}
+
+.text-lg {
+ font-size: 32upx;
+}
+
+.text-xl {
+ font-size: 36upx;
+}
+
+.text-xxl {
+ font-size: 44upx;
+}
+
+.text-sl {
+ font-size: 80upx;
+}
+
+.text-xsl {
+ font-size: 120upx;
+}
+
+.text-Abc {
+ text-transform: Capitalize;
+}
+
+.text-ABC {
+ text-transform: Uppercase;
+}
+
+.text-abc {
+ text-transform: Lowercase;
+}
+
+.text-price::before {
+ content: "¥";
+ font-size: 80%;
+ margin-right: 4upx;
+}
+
+.text-cut {
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+.text-bold {
+ font-weight: bold;
+}
+
+.text-center {
+ text-align: center;
+}
+
+.text-content {
+ line-height: 1.6;
+}
+
+.text-left {
+ text-align: left;
+}
+
+.text-right {
+ text-align: right;
+}
+
+.text-red,
+.line-red,
+.lines-red {
+ color: #FF0000;
+}
+
+.text-orange,
+.line-orange,
+.lines-orange {
+ color: #f37b1d;
+}
+
+.text-yellow,
+.line-yellow,
+.lines-yellow {
+ color: #fbbd08;
+}
+
+.text-olive,
+.line-olive,
+.lines-olive {
+ color: #8dc63f;
+}
+
+.text-green,
+.line-green,
+.lines-green {
+ color: #39b54a;
+}
+
+.text-cyan,
+.line-cyan,
+.lines-cyan {
+ color: #1cbbb4;
+}
+
+.text-blue,
+.line-blue,
+.lines-blue {
+ color: #0081ff;
+}
+
+.text-purple,
+.line-purple,
+.lines-purple {
+ color: #6739b6;
+}
+
+.text-mauve,
+.line-mauve,
+.lines-mauve {
+ color: #9c26b0;
+}
+
+.text-pink,
+.line-pink,
+.lines-pink {
+ color: #e03997;
+}
+
+.text-brown,
+.line-brown,
+.lines-brown {
+ color: #a5673f;
+}
+
+.text-grey,
+.line-grey,
+.lines-grey {
+ color: #8799a3;
+}
+
+.text-gray,
+.line-gray,
+.lines-gray {
+ color: #aaaaaa;
+}
+
+.text-black,
+.line-black,
+.lines-black {
+ color: #333333;
+}
+
+.text-white,
+.line-white,
+.lines-white {
+ color: #ffffff;
+}
diff --git a/static/style/index.scss b/static/style/index.scss
new file mode 100644
index 0000000..486ce44
--- /dev/null
+++ b/static/style/index.scss
@@ -0,0 +1,30 @@
+@import 'uview-ui/index.scss';
+@import 'static/style/colorui.css';
+@import 'static/font/shopro-icon.css';
+@import 'uview-ui/iconfont.css';
+
+/* 字体文件 */
+@font-face {
+ font-family: OPPOSANS;
+ src: url('~@/static/font/OPPOSANS-M-subfont.ttf');
+}
+.font-OPPOSANS {
+ font-family: OPPOSANS;
+}
+page {
+ -webkit-overflow-scrolling: touch; // ios滑动不流畅
+ height: 100%;
+ background: #f6f6f6;
+ width: 100%;
+ font-size: 30rpx;
+ font-family: OPPOSANS;
+ word-break: break-all; //英文文本不换行
+ white-space: normal;
+ color: $u-main-color;
+}
+::-webkit-scrollbar {
+ width: 0;
+ height: 0;
+ color: transparent;
+ display: none;
+}
diff --git a/template.h5.html b/template.h5.html
new file mode 100644
index 0000000..aa53041
--- /dev/null
+++ b/template.h5.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+ <%= htmlWebpackPlugin.options.title %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni.scss b/uni.scss
new file mode 100644
index 0000000..12fdd98
--- /dev/null
+++ b/uni.scss
@@ -0,0 +1,7 @@
+/**
+ * 下方引入的为uView UI的集成样式文件,为scss预处理器,其中包含了一些"u-"开头的自定义变量
+ * 使用的时候,请将下面的一行复制到您的uniapp项目根目录的uni.scss中即可
+ * uView自定义的css类名和scss变量,均以"u-"开头,不会造成冲突,请放心使用
+ */
+@import 'uview-ui/theme.scss';
+$IMG_URL: 'http://file.shopro.top'; //css中背景图片变量。js图片变量在env.js
diff --git a/uview-ui/LICENSE b/uview-ui/LICENSE
new file mode 100644
index 0000000..8e39ead
--- /dev/null
+++ b/uview-ui/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 www.uviewui.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/uview-ui/README.md b/uview-ui/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/uview-ui/components/u-calendar/u-calendar.vue b/uview-ui/components/u-calendar/u-calendar.vue
new file mode 100644
index 0000000..77870e5
--- /dev/null
+++ b/uview-ui/components/u-calendar/u-calendar.vue
@@ -0,0 +1,667 @@
+
+
+
+
+
+
+
+ {{ showTitle }}
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+ {{ startText }}
+
+
+ {{ endText }}
+
+
+ {{ month }}
+
+
+
+ {{ mode == 'date' ? activeDate : startDate }}
+ 至{{ endDate }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-checkbox-group/u-checkbox-group.vue b/uview-ui/components/u-checkbox-group/u-checkbox-group.vue
new file mode 100644
index 0000000..2848e4f
--- /dev/null
+++ b/uview-ui/components/u-checkbox-group/u-checkbox-group.vue
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-checkbox/u-checkbox.vue b/uview-ui/components/u-checkbox/u-checkbox.vue
new file mode 100644
index 0000000..9414461
--- /dev/null
+++ b/uview-ui/components/u-checkbox/u-checkbox.vue
@@ -0,0 +1,284 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-collapse-item/u-collapse-item.vue b/uview-ui/components/u-collapse-item/u-collapse-item.vue
new file mode 100644
index 0000000..3b66bfa
--- /dev/null
+++ b/uview-ui/components/u-collapse-item/u-collapse-item.vue
@@ -0,0 +1,204 @@
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-collapse/u-collapse.vue b/uview-ui/components/u-collapse/u-collapse.vue
new file mode 100644
index 0000000..8572957
--- /dev/null
+++ b/uview-ui/components/u-collapse/u-collapse.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-column-notice/u-column-notice.vue b/uview-ui/components/u-column-notice/u-column-notice.vue
new file mode 100644
index 0000000..dd8bd31
--- /dev/null
+++ b/uview-ui/components/u-column-notice/u-column-notice.vue
@@ -0,0 +1,237 @@
+
+
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-count-down/u-count-down.vue b/uview-ui/components/u-count-down/u-count-down.vue
new file mode 100644
index 0000000..7285d67
--- /dev/null
+++ b/uview-ui/components/u-count-down/u-count-down.vue
@@ -0,0 +1,318 @@
+
+
+
+
+ {{ d }}
+
+
+
+ {{ separator == 'colon' ? ':' : '天' }}
+
+
+
+ {{ h }}
+
+
+
+ {{ separator == 'colon' ? ':' : '时' }}
+
+
+
+ {{ i }}
+
+
+
+ {{ separator == 'colon' ? ':' : '分' }}
+
+
+
+ {{ s }}
+
+
+
+ 秒
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-dropdown-item/u-dropdown-item.vue b/uview-ui/components/u-dropdown-item/u-dropdown-item.vue
new file mode 100644
index 0000000..d251f08
--- /dev/null
+++ b/uview-ui/components/u-dropdown-item/u-dropdown-item.vue
@@ -0,0 +1,150 @@
+
+ {}" @tap.stop.prevent="() => {}">
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-dropdown/u-dropdown.vue b/uview-ui/components/u-dropdown/u-dropdown.vue
new file mode 100644
index 0000000..87efbe3
--- /dev/null
+++ b/uview-ui/components/u-dropdown/u-dropdown.vue
@@ -0,0 +1,320 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-empty/u-empty.vue b/uview-ui/components/u-empty/u-empty.vue
new file mode 100644
index 0000000..2c77b24
--- /dev/null
+++ b/uview-ui/components/u-empty/u-empty.vue
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-form-item/u-form-item.vue b/uview-ui/components/u-form-item/u-form-item.vue
new file mode 100644
index 0000000..d6b8c8b
--- /dev/null
+++ b/uview-ui/components/u-form-item/u-form-item.vue
@@ -0,0 +1,431 @@
+
+
+
+
+
+
+
+
+ *
+
+
+
+
+ {{label}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{validateMessage}}
+
+
+
+
+
+
diff --git a/uview-ui/components/u-form/u-form.vue b/uview-ui/components/u-form/u-form.vue
new file mode 100644
index 0000000..bdbafaf
--- /dev/null
+++ b/uview-ui/components/u-form/u-form.vue
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-icon/u-icon.vue b/uview-ui/components/u-icon/u-icon.vue
new file mode 100644
index 0000000..db1b019
--- /dev/null
+++ b/uview-ui/components/u-icon/u-icon.vue
@@ -0,0 +1,336 @@
+
+
+
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-input/u-input.vue b/uview-ui/components/u-input/u-input.vue
new file mode 100644
index 0000000..8c6399d
--- /dev/null
+++ b/uview-ui/components/u-input/u-input.vue
@@ -0,0 +1,390 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-line-progress/u-line-progress.vue b/uview-ui/components/u-line-progress/u-line-progress.vue
new file mode 100644
index 0000000..06f9ad4
--- /dev/null
+++ b/uview-ui/components/u-line-progress/u-line-progress.vue
@@ -0,0 +1,148 @@
+
+
+
+
+
+ {{percent + '%'}}
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-line/u-line.vue b/uview-ui/components/u-line/u-line.vue
new file mode 100644
index 0000000..c56fbc3
--- /dev/null
+++ b/uview-ui/components/u-line/u-line.vue
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-loadmore/u-loadmore.vue b/uview-ui/components/u-loadmore/u-loadmore.vue
new file mode 100644
index 0000000..2667155
--- /dev/null
+++ b/uview-ui/components/u-loadmore/u-loadmore.vue
@@ -0,0 +1,232 @@
+
+
+
+
+
+
+
+
+
+ {{
+ showText
+ }}
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-mask/u-mask.vue b/uview-ui/components/u-mask/u-mask.vue
new file mode 100644
index 0000000..e70a2ac
--- /dev/null
+++ b/uview-ui/components/u-mask/u-mask.vue
@@ -0,0 +1,133 @@
+
+ {}"
+ :class="{
+ 'u-mask-zoom': zoom,
+ 'u-mask-show': show
+ }"
+ >
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-modal/u-modal.vue b/uview-ui/components/u-modal/u-modal.vue
new file mode 100644
index 0000000..df61852
--- /dev/null
+++ b/uview-ui/components/u-modal/u-modal.vue
@@ -0,0 +1,297 @@
+
+
+
+
+ {{ title }}
+
+
+ {{ content }}
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-no-network/u-no-network.vue b/uview-ui/components/u-no-network/u-no-network.vue
new file mode 100644
index 0000000..86acc1c
--- /dev/null
+++ b/uview-ui/components/u-no-network/u-no-network.vue
@@ -0,0 +1,231 @@
+
+ {}">
+
+
+ {{ tips }}
+
+
+
+ 请检查网络,或前往
+ 设置
+
+
+ 重试
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-notice-bar/u-notice-bar.vue b/uview-ui/components/u-notice-bar/u-notice-bar.vue
new file mode 100644
index 0000000..41a6cc4
--- /dev/null
+++ b/uview-ui/components/u-notice-bar/u-notice-bar.vue
@@ -0,0 +1,272 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-number-box/u-number-box.vue b/uview-ui/components/u-number-box/u-number-box.vue
new file mode 100644
index 0000000..ec66d4b
--- /dev/null
+++ b/uview-ui/components/u-number-box/u-number-box.vue
@@ -0,0 +1,386 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uview-ui/components/u-parse/libs/CssHandler.js b/uview-ui/components/u-parse/libs/CssHandler.js
new file mode 100644
index 0000000..75c6015
--- /dev/null
+++ b/uview-ui/components/u-parse/libs/CssHandler.js
@@ -0,0 +1,100 @@
+const cfg = require('./config.js'),
+ isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+
+function CssHandler(tagStyle) {
+ var styles = Object.assign(Object.create(null), cfg.userAgentStyles);
+ for (var item in tagStyle)
+ styles[item] = (styles[item] ? styles[item] + ';' : '') + tagStyle[item];
+ this.styles = styles;
+}
+CssHandler.prototype.getStyle = function(data) {
+ this.styles = new parser(data, this.styles).parse();
+}
+CssHandler.prototype.match = function(name, attrs) {
+ var tmp, matched = (tmp = this.styles[name]) ? tmp + ';' : '';
+ if (attrs.class) {
+ var items = attrs.class.split(' ');
+ for (var i = 0, item; item = items[i]; i++)
+ if (tmp = this.styles['.' + item])
+ matched += tmp + ';';
+ }
+ if (tmp = this.styles['#' + attrs.id])
+ matched += tmp + ';';
+ return matched;
+}
+module.exports = CssHandler;
+
+function parser(data, init) {
+ this.data = data;
+ this.floor = 0;
+ this.i = 0;
+ this.list = [];
+ this.res = init;
+ this.state = this.Space;
+}
+parser.prototype.parse = function() {
+ for (var c; c = this.data[this.i]; this.i++)
+ this.state(c);
+ return this.res;
+}
+parser.prototype.section = function() {
+ return this.data.substring(this.start, this.i);
+}
+// 状态机
+parser.prototype.Space = function(c) {
+ if (c == '.' || c == '#' || isLetter(c)) {
+ this.start = this.i;
+ this.state = this.Name;
+ } else if (c == '/' && this.data[this.i + 1] == '*')
+ this.Comment();
+ else if (!cfg.blankChar[c] && c != ';')
+ this.state = this.Ignore;
+}
+parser.prototype.Comment = function() {
+ this.i = this.data.indexOf('*/', this.i) + 1;
+ if (!this.i) this.i = this.data.length;
+ this.state = this.Space;
+}
+parser.prototype.Ignore = function(c) {
+ if (c == '{') this.floor++;
+ else if (c == '}' && !--this.floor) {
+ this.list = [];
+ this.state = this.Space;
+ }
+}
+parser.prototype.Name = function(c) {
+ if (cfg.blankChar[c]) {
+ this.list.push(this.section());
+ this.state = this.NameSpace;
+ } else if (c == '{') {
+ this.list.push(this.section());
+ this.Content();
+ } else if (c == ',') {
+ this.list.push(this.section());
+ this.Comma();
+ } else if (!isLetter(c) && (c < '0' || c > '9') && c != '-' && c != '_')
+ this.state = this.Ignore;
+}
+parser.prototype.NameSpace = function(c) {
+ if (c == '{') this.Content();
+ else if (c == ',') this.Comma();
+ else if (!cfg.blankChar[c]) this.state = this.Ignore;
+}
+parser.prototype.Comma = function() {
+ while (cfg.blankChar[this.data[++this.i]]);
+ if (this.data[this.i] == '{') this.Content();
+ else {
+ this.start = this.i--;
+ this.state = this.Name;
+ }
+}
+parser.prototype.Content = function() {
+ this.start = ++this.i;
+ if ((this.i = this.data.indexOf('}', this.i)) == -1) this.i = this.data.length;
+ var content = this.section();
+ for (var i = 0, item; item = this.list[i++];)
+ if (this.res[item]) this.res[item] += ';' + content;
+ else this.res[item] = content;
+ this.list = [];
+ this.state = this.Space;
+}
diff --git a/uview-ui/components/u-parse/libs/MpHtmlParser.js b/uview-ui/components/u-parse/libs/MpHtmlParser.js
new file mode 100644
index 0000000..aeb0fc3
--- /dev/null
+++ b/uview-ui/components/u-parse/libs/MpHtmlParser.js
@@ -0,0 +1,580 @@
+/**
+ * html 解析器
+ * @tutorial https://github.com/jin-yufeng/Parser
+ * @version 20201029
+ * @author JinYufeng
+ * @listens MIT
+ */
+const cfg = require('./config.js'),
+ blankChar = cfg.blankChar,
+ CssHandler = require('./CssHandler.js'),
+ windowWidth = uni.getSystemInfoSync().windowWidth;
+var emoji;
+
+function MpHtmlParser(data, options = {}) {
+ this.attrs = {};
+ this.CssHandler = new CssHandler(options.tagStyle, windowWidth);
+ this.data = data;
+ this.domain = options.domain;
+ this.DOM = [];
+ this.i = this.start = this.audioNum = this.imgNum = this.videoNum = 0;
+ options.prot = (this.domain || '').includes('://') ? this.domain.split('://')[0] : 'http';
+ this.options = options;
+ this.state = this.Text;
+ this.STACK = [];
+ // 工具函数
+ this.bubble = () => {
+ for (var i = this.STACK.length, item; item = this.STACK[--i];) {
+ if (cfg.richOnlyTags[item.name]) return false;
+ item.c = 1;
+ }
+ return true;
+ }
+ this.decode = (val, amp) => {
+ var i = -1,
+ j, en;
+ while (1) {
+ if ((i = val.indexOf('&', i + 1)) == -1) break;
+ if ((j = val.indexOf(';', i + 2)) == -1) break;
+ if (val[i + 1] == '#') {
+ en = parseInt((val[i + 2] == 'x' ? '0' : '') + val.substring(i + 2, j));
+ if (!isNaN(en)) val = val.substr(0, i) + String.fromCharCode(en) + val.substr(j + 1);
+ } else {
+ en = val.substring(i + 1, j);
+ if (cfg.entities[en] || en == amp)
+ val = val.substr(0, i) + (cfg.entities[en] || '&') + val.substr(j + 1);
+ }
+ }
+ return val;
+ }
+ this.getUrl = url => {
+ if (url[0] == '/') {
+ if (url[1] == '/') url = this.options.prot + ':' + url;
+ else if (this.domain) url = this.domain + url;
+ } else if (this.domain && url.indexOf('data:') != 0 && !url.includes('://'))
+ url = this.domain + '/' + url;
+ return url;
+ }
+ this.isClose = () => this.data[this.i] == '>' || (this.data[this.i] == '/' && this.data[this.i + 1] == '>');
+ this.section = () => this.data.substring(this.start, this.i);
+ this.parent = () => this.STACK[this.STACK.length - 1];
+ this.siblings = () => this.STACK.length ? this.parent().children : this.DOM;
+}
+MpHtmlParser.prototype.parse = function() {
+ if (emoji) this.data = emoji.parseEmoji(this.data);
+ for (var c; c = this.data[this.i]; this.i++)
+ this.state(c);
+ if (this.state == this.Text) this.setText();
+ while (this.STACK.length) this.popNode(this.STACK.pop());
+ return this.DOM;
+}
+// 设置属性
+MpHtmlParser.prototype.setAttr = function() {
+ var name = this.attrName.toLowerCase(),
+ val = this.attrVal;
+ if (cfg.boolAttrs[name]) this.attrs[name] = 'T';
+ else if (val) {
+ if (name == 'src' || (name == 'data-src' && !this.attrs.src)) this.attrs.src = this.getUrl(this.decode(val, 'amp'));
+ else if (name == 'href' || name == 'style') this.attrs[name] = this.decode(val, 'amp');
+ else if (name.substr(0, 5) != 'data-') this.attrs[name] = val;
+ }
+ this.attrVal = '';
+ while (blankChar[this.data[this.i]]) this.i++;
+ if (this.isClose()) this.setNode();
+ else {
+ this.start = this.i;
+ this.state = this.AttrName;
+ }
+}
+// 设置文本节点
+MpHtmlParser.prototype.setText = function() {
+ var back, text = this.section();
+ if (!text) return;
+ text = (cfg.onText && cfg.onText(text, () => back = true)) || text;
+ if (back) {
+ this.data = this.data.substr(0, this.start) + text + this.data.substr(this.i);
+ let j = this.start + text.length;
+ for (this.i = this.start; this.i < j; this.i++) this.state(this.data[this.i]);
+ return;
+ }
+ if (!this.pre) {
+ // 合并空白符
+ var flag, tmp = [];
+ for (let i = text.length, c; c = text[--i];)
+ if (!blankChar[c]) {
+ tmp.unshift(c);
+ if (!flag) flag = 1;
+ } else {
+ if (tmp[0] != ' ') tmp.unshift(' ');
+ if (c == '\n' && flag == void 0) flag = 0;
+ }
+ if (flag == 0) return;
+ text = tmp.join('');
+ }
+ this.siblings().push({
+ type: 'text',
+ text: this.decode(text)
+ });
+}
+// 设置元素节点
+MpHtmlParser.prototype.setNode = function() {
+ var node = {
+ name: this.tagName.toLowerCase(),
+ attrs: this.attrs
+ },
+ close = cfg.selfClosingTags[node.name];
+ if (this.options.nodes.length) node.type = 'node';
+ this.attrs = {};
+ if (!cfg.ignoreTags[node.name]) {
+ // 处理属性
+ var attrs = node.attrs,
+ style = this.CssHandler.match(node.name, attrs, node) + (attrs.style || ''),
+ styleObj = {};
+ if (attrs.id) {
+ if (this.options.compress & 1) attrs.id = void 0;
+ else if (this.options.useAnchor) this.bubble();
+ }
+ if ((this.options.compress & 2) && attrs.class) attrs.class = void 0;
+ switch (node.name) {
+ case 'a':
+ case 'ad': // #ifdef APP-PLUS
+ case 'iframe':
+ // #endif
+ this.bubble();
+ break;
+ case 'font':
+ if (attrs.color) {
+ styleObj['color'] = attrs.color;
+ attrs.color = void 0;
+ }
+ if (attrs.face) {
+ styleObj['font-family'] = attrs.face;
+ attrs.face = void 0;
+ }
+ if (attrs.size) {
+ var size = parseInt(attrs.size);
+ if (size < 1) size = 1;
+ else if (size > 7) size = 7;
+ var map = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'];
+ styleObj['font-size'] = map[size - 1];
+ attrs.size = void 0;
+ }
+ break;
+ case 'embed':
+ // #ifndef APP-PLUS
+ var src = node.attrs.src || '',
+ type = node.attrs.type || '';
+ if (type.includes('video') || src.includes('.mp4') || src.includes('.3gp') || src.includes('.m3u8'))
+ node.name = 'video';
+ else if (type.includes('audio') || src.includes('.m4a') || src.includes('.wav') || src.includes('.mp3') || src.includes(
+ '.aac'))
+ node.name = 'audio';
+ else break;
+ if (node.attrs.autostart)
+ node.attrs.autoplay = 'T';
+ node.attrs.controls = 'T';
+ // #endif
+ // #ifdef APP-PLUS
+ this.bubble();
+ break;
+ // #endif
+ case 'video':
+ case 'audio':
+ if (!attrs.id) attrs.id = node.name + (++this[`${node.name}Num`]);
+ else this[`${node.name}Num`]++;
+ if (node.name == 'video') {
+ if (this.videoNum > 3)
+ node.lazyLoad = 1;
+ if (attrs.width) {
+ styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px');
+ attrs.width = void 0;
+ }
+ if (attrs.height) {
+ styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px');
+ attrs.height = void 0;
+ }
+ }
+ if (!attrs.controls && !attrs.autoplay) attrs.controls = 'T';
+ attrs.source = [];
+ if (attrs.src) {
+ attrs.source.push(attrs.src);
+ attrs.src = void 0;
+ }
+ this.bubble();
+ break;
+ case 'td':
+ case 'th':
+ if (attrs.colspan || attrs.rowspan)
+ for (var k = this.STACK.length, item; item = this.STACK[--k];)
+ if (item.name == 'table') {
+ item.flag = 1;
+ break;
+ }
+ }
+ if (attrs.align) {
+ if (node.name == 'table') {
+ if (attrs.align == 'center') styleObj['margin-inline-start'] = styleObj['margin-inline-end'] = 'auto';
+ else styleObj['float'] = attrs.align;
+ } else styleObj['text-align'] = attrs.align;
+ attrs.align = void 0;
+ }
+ // 压缩 style
+ var styles = style.split(';');
+ style = '';
+ for (var i = 0, len = styles.length; i < len; i++) {
+ var info = styles[i].split(':');
+ if (info.length < 2) continue;
+ let key = info[0].trim().toLowerCase(),
+ value = info.slice(1).join(':').trim();
+ if (value[0] == '-' || value.includes('safe'))
+ style += `;${key}:${value}`;
+ else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import'))
+ styleObj[key] = value;
+ }
+ if (node.name == 'img') {
+ if (attrs.src && !attrs.ignore) {
+ if (this.bubble())
+ attrs.i = (this.imgNum++).toString();
+ else attrs.ignore = 'T';
+ }
+ if (attrs.ignore) {
+ style += ';-webkit-touch-callout:none';
+ styleObj['max-width'] = '100%';
+ }
+ var width;
+ if (styleObj.width) width = styleObj.width;
+ else if (attrs.width) width = attrs.width.includes('%') ? attrs.width : parseFloat(attrs.width) + 'px';
+ if (width) {
+ styleObj.width = width;
+ attrs.width = '100%';
+ if (parseInt(width) > windowWidth) {
+ styleObj.height = '';
+ if (attrs.height) attrs.height = void 0;
+ }
+ }
+ if (styleObj.height) {
+ attrs.height = styleObj.height;
+ styleObj.height = '';
+ } else if (attrs.height && !attrs.height.includes('%'))
+ attrs.height = parseFloat(attrs.height) + 'px';
+ }
+ for (var key in styleObj) {
+ var value = styleObj[key];
+ if (!value) continue;
+ if (key.includes('flex') || key == 'order' || key == 'self-align') node.c = 1;
+ // 填充链接
+ if (value.includes('url')) {
+ var j = value.indexOf('(');
+ if (j++ != -1) {
+ while (value[j] == '"' || value[j] == "'" || blankChar[value[j]]) j++;
+ value = value.substr(0, j) + this.getUrl(value.substr(j));
+ }
+ }
+ // 转换 rpx
+ else if (value.includes('rpx'))
+ value = value.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * windowWidth / 750 + 'px');
+ else if (key == 'white-space' && value.includes('pre') && !close)
+ this.pre = node.pre = true;
+ style += `;${key}:${value}`;
+ }
+ style = style.substr(1);
+ if (style) attrs.style = style;
+ if (!close) {
+ node.children = [];
+ if (node.name == 'pre' && cfg.highlight) {
+ this.remove(node);
+ this.pre = node.pre = true;
+ }
+ this.siblings().push(node);
+ this.STACK.push(node);
+ } else if (!cfg.filter || cfg.filter(node, this) != false)
+ this.siblings().push(node);
+ } else {
+ if (!close) this.remove(node);
+ else if (node.name == 'source') {
+ var parent = this.parent();
+ if (parent && (parent.name == 'video' || parent.name == 'audio') && node.attrs.src)
+ parent.attrs.source.push(node.attrs.src);
+ } else if (node.name == 'base' && !this.domain) this.domain = node.attrs.href;
+ }
+ if (this.data[this.i] == '/') this.i++;
+ this.start = this.i + 1;
+ this.state = this.Text;
+}
+// 移除标签
+MpHtmlParser.prototype.remove = function(node) {
+ var name = node.name,
+ j = this.i;
+ // 处理 svg
+ var handleSvg = () => {
+ var src = this.data.substring(j, this.i + 1);
+ node.attrs.xmlns = 'http://www.w3.org/2000/svg';
+ for (var key in node.attrs) {
+ if (key == 'viewbox') src = ` viewBox="${node.attrs.viewbox}"` + src;
+ else if (key != 'style') src = ` ${key}="${node.attrs[key]}"` + src;
+ }
+ src = '