232 Commits
Author SHA1 Message Date
芋道源码 b5fc0068b1 !6 文章详情页面:新增调用增加浏览量接口
Merge pull request !6 from puhui999/master
2023-10-21 14:27:43 +00:00
puhui999 85af097207 文章详情页面:新增调用增加浏览量接口 2023-10-20 23:11:23 +08:00
YunaiV 24c3709c95 修复微信小程序的一键登录 2023-10-19 21:49:41 +08:00
YunaiV 0b3882256e Merge remote-tracking branch 'origin/master' 2023-10-19 21:21:45 +08:00
YunaiV e99f8d485c 调整微信公众号登录的实现 2023-10-19 21:21:39 +08:00
芋道源码 1aa198fd85 !5 APP增加终端Header[terminal]
Merge pull request !5 from 疯狂的世界/master
2023-10-16 13:41:57 +00:00
owen 2aeebb3245 Merge remote-tracking branch 'origin/master' 2023-10-16 15:14:30 +08:00
owen cc94ee7aff 1. APP增加终端Header[terminal]
2. 订单、会员注册记录来源终端
2023-10-16 15:06:58 +08:00
YunaiV 86b92e6f2a 同步最新 README.md 功能列表 2023-10-13 18:49:17 +08:00
YunaiV f41874765a 全局:修复部分接口强制登录的问题 2023-10-07 22:54:08 +08:00
YunaiV 8d1cb7c4de 拼团:修复部分字段读取不对的问题 2023-10-07 22:48:39 +08:00
YunaiV 52b8033e2d promotion:基本完善完砍价逻辑 2023-10-06 10:18:05 +08:00
YunaiV 7e55249b79 使用动态 token,去除全局写死 2023-10-06 02:10:56 +08:00
YunaiV c36415fcda trade:砍价记录的详情 50% 2023-10-06 02:06:45 +08:00
YunaiV 7ce062229f trade:完善砍价的下单流程 2023-10-05 23:24:14 +08:00
YunaiV ae95b0def7 Merge remote-tracking branch 'origin/master' 2023-10-05 17:22:45 +08:00
YunaiV cab431c25e trade:完善砍价的界面 2023-10-05 17:22:38 +08:00
芋道源码 563533ba19 !4 交易:核销
Merge pull request !4 from 疯狂的世界/master
2023-10-04 09:35:43 +00:00
owen 42e9129f8a 交易:核销 2023-10-04 09:11:49 +08:00
芋道源码 6a6f022eac !3 完善优惠券功能
Merge pull request !3 from 疯狂的世界/master
2023-10-03 10:45:57 +00:00
owen 6f2d9f1014 Merge remote-tracking branch 'origin/master' 2023-10-03 00:00:12 +08:00
YunaiV 7be4e398f3 trade:新增是否自提的配置项 2023-10-02 21:19:19 +08:00
owen d5592cbd48 Merge remote-tracking branch 'origin/master' 2023-10-01 15:29:43 +08:00
owen 1256956825 签到:签到后增加用户积分、经验 2023-10-01 09:53:53 +08:00
YunaiV d3c114325b wallet:接入支付收银台 2023-09-30 22:07:57 +08:00
owen 40ae9ca1c4 Merge remote-tracking branch 'origin/master' 2023-09-30 22:07:12 +08:00
owen 1ff0b665b6 优惠券:重构是否领取检查方式 2023-09-30 22:05:02 +08:00
YunaiV 06f7bd5f68 wallet:接入佣金提现 2023-09-30 21:02:13 +08:00
YunaiV 03ceb0bcf3 wallet:接入钱包充值 2023-09-30 18:54:26 +08:00
YunaiV 5981432ff7 Merge remote-tracking branch 'origin/master' 2023-09-29 13:34:47 +08:00
YunaiV e513fff4c0 aftersale:调整售后理由的接口 2023-09-29 13:34:41 +08:00
owen 78da791d4c 优惠券:完善优惠券领取接口 2023-09-26 23:20:56 +08:00
owen 810f311a13 优惠券:完善优惠券匹配接口 2023-09-26 22:46:06 +08:00
owen 1f7824b0d7 优惠券:完善APP优惠券查询接口 2023-09-26 20:44:17 +08:00
芋道源码 2bf4f1fa56 !2 分销:Review代码修改
Merge pull request !2 from 疯狂的世界/master
2023-09-25 00:37:49 +00:00
owen 52f8e217f3 评论:修正好评率,舍弃小数 2023-09-24 23:26:57 +08:00
owen 380b47e371 分销:修正分享海报 2023-09-24 23:18:50 +08:00
owen 5d319b3f37 分销:重命名提现类型字段 2023-09-24 22:32:11 +08:00
owen b076f61c58 分销:根据商品,计算推广员可以得到的佣金 2023-09-24 22:27:23 +08:00
owen 7b35a39618 分销:Review代码修改 2023-09-24 20:28:43 +08:00
芋道源码 f9253f9e56 !1 trade: 分销业务 - 提现申请
Merge pull request !1 from 疯狂的世界/master
2023-09-24 01:50:17 +00:00
YunaiV 681535e94b 增加 vipPrice 的返回 2023-09-24 00:45:48 +08:00
owen fc50e78bec 分佣: 提现记录 2023-09-22 18:35:41 +08:00
owen d07f823326 分佣: 提现 2023-09-22 18:06:11 +08:00
owen 787d115e5a 分佣:提现银行卡列表 2023-09-22 15:42:12 +08:00
owen 4f219f2551 分佣:提现银行卡列表 2023-09-22 15:38:40 +08:00
owen a91b09a5fc system: uniapp增加字典数据查询接口 2023-09-22 15:11:03 +08:00
owen a2f0aa31fd trade: 分销业务 - 提现申请 2023-09-21 23:56:33 +08:00
YunaiV 1e01a404ba 修复 msg 错误提示 2023-09-11 16:30:12 +08:00
YunaiV b34a1ec397 完善 README 文档 2023-09-11 16:02:57 +08:00
YunaiV f26acabda2 完善 README 文档 2023-09-11 16:00:57 +08:00
YunaiV ca316b10ae 完善 README 文档 2023-09-11 16:00:02 +08:00
YunaiV 6ea3a8aa69 初始化 README 信息 2023-09-11 12:53:42 +08:00
YunaiV 7e7248ef97 登录:完善微信公众号的登录逻辑 2023-09-11 10:01:24 +08:00
YunaiV 4e40a69f61 登录:初步微信公众号的实现静默登录 2023-09-11 09:15:35 +08:00
YunaiV 99a6ff2d77 登录:初步实现微信公众号登录 2023-09-10 22:46:53 +08:00
YunaiV e8573f42bb 登录:微信一键登录 2023-09-10 19:57:10 +08:00
YunaiV 0bd831fe35 登录:修复登录完后,不会进行跳转,在微信小程序的情况 2023-09-10 18:37:22 +08:00
YunaiV 54c6e483a4 登录:微信小程序,静默登录 2023-09-10 18:01:21 +08:00
YunaiV 3c7db828db 登录:接入验证码登录 2023-09-09 22:45:58 +08:00
YunaiV b71fed3782 分佣:商品详情,展示分佣 2023-09-09 22:34:22 +08:00
YunaiV 31970ceda9 分佣:商品详情,展示分佣 2023-09-09 22:27:39 +08:00
YunaiV ad4eb04f49 分佣:商品详情增加绑定用户 2023-09-09 22:19:12 +08:00
YunaiV 15b7e3d94c 分佣:绑定 user 2023-09-09 21:06:25 +08:00
YunaiV e9019e9d39 分佣:spreadList 改成 posterUrls 2023-09-09 19:52:17 +08:00
YunaiV 81c8285016 分佣:调整分销状态的读取 2023-09-09 19:35:08 +08:00
YunaiV 50fcef07ee 分佣:user_cash 迁移 2023-09-07 00:15:00 +08:00
YunaiV 34d222dc36 分佣:user_spread_code 迁移 2023-09-06 22:41:17 +08:00
YunaiV 25538f7a82 promotionGood 组件没用到,先删除掉。 2023-09-06 00:05:46 +08:00
YunaiV 27321bda16 分佣:promoter-list 迁移 2023-09-05 23:49:24 +08:00
YunaiV b15fb02ecf 分佣:commission-rank 迁移 2023-09-05 21:36:10 +08:00
YunaiV 5b8b91356f 分佣:promoter-rank 迁移 2023-09-05 00:11:57 +08:00
YunaiV 17ae7587cb 分佣:promoter-order 迁移 2023-09-04 22:47:41 +08:00
YunaiV c8db068547 分佣:user_spread_money 迁移 2023-09-04 21:00:33 +08:00
YunaiV 9acaf3c27c 分佣:user_spread_user 迁移 2023-09-03 21:21:54 +08:00
YunaiV 32e108ca2f 调整 CRMEB 字样 2023-08-31 19:21:22 +08:00
YunaiV e45372d4b6 购物车:接入修改数量 API,剩余所有 2023-08-30 19:14:46 +08:00
YunaiV 6bdbebe2a0 购物车:接入修改数量 API(全选、不选) 2023-08-30 08:46:15 +08:00
YunaiV 92cb6252ae 购物车:接入修改数量 API 2023-08-29 23:58:33 +08:00
YunaiV f579101f7c 购物车:接入购物车列表 API 2023-08-29 23:28:17 +08:00
YunaiV 31f8897d6e 会员钱包:接入钱包明细 2023-08-29 00:32:07 +08:00
YunaiV 182cb8efdb 会员钱包:接入钱包明细 2023-08-28 22:36:36 +08:00
YunaiV 85f91fa570 会员等级:接入 api 2023-08-28 21:03:42 +08:00
YunaiV 02ce643f57 登录界面:账号密码登录 2023-08-28 19:58:22 +08:00
YunaiV 84e9e44b22 积分的实现 2023-08-21 23:58:13 +08:00
YunaiV a7f96df500 签到记录列表的实现 2023-08-21 21:57:32 +08:00
YunaiV 09496a038b 签到的信息界面 2023-08-21 21:45:48 +08:00
YunaiV 3ec70daafc 清理下 login 相关无用的代码 2023-08-19 23:40:59 +08:00
YunaiV 475a681300 接入密码找回功能 2023-08-19 23:12:19 +08:00
YunaiV 592827bc3d 修改手机的接入 2023-08-19 19:24:24 +08:00
YunaiV ea89482012 【个人信息的修改】
1、完成接入
2023-08-19 17:47:46 +08:00
YunaiV 5e4a9f8cc2 【个人中心】
1、完成个人信息的接入
2023-08-19 17:00:08 +08:00
YunaiV e42f376bc2 【个人中心】
1、完成订单中心的接入
2023-08-19 16:04:25 +08:00
YunaiV 330e508900 【个人中心】
1、进入自己实现的店铺装修
2023-08-19 15:40:30 +08:00
YunaiV e452f7cb19 【订单】
1、接入退款流程
2023-08-18 19:59:47 +08:00
YunaiV a4846939dd 【退款】
1、退款详情
2、退货界面
2023-08-18 19:14:39 +08:00
YunaiV 40883fda3b 【退款】
1、订单详情界面,移除和退款状态相关的字段
2、增加 users/user_return_detail 退款详情界面
2023-08-17 23:14:41 +08:00
YunaiV 7d512ef9a6 【退款】
1、发起退款界面 90%
2023-08-17 22:33:51 +08:00
YunaiV e629285b51 【退款】
1、发起退款界面 50%
2023-08-17 20:31:56 +08:00
YunaiV 0bc8344505 【退款】
1、接入退款列表
2023-08-17 13:34:47 +08:00
YunaiV c83c98b598 【订单】
1、接入物流进度
2023-08-16 23:29:55 +08:00
YunaiV 5a25680bf7 【首页】
1、接入装修
2、分享配置调整
2023-08-16 22:43:54 +08:00
YunaiV 83d81031e3 【订单详情】
1、实现评论的文件上传
2023-08-13 22:02:12 +08:00
YunaiV c7323c1900 【订单详情】
1、订单评价的接入
2023-08-13 21:44:29 +08:00
YunaiV cf73be8270 【订单详情】
1、接入确认收货接口
2023-08-13 20:26:58 +08:00
YunaiV d68b24445a 【订单详情】
1、接入物流的单号展示
2023-08-13 20:13:00 +08:00
YunaiV 1279ba6b5d 【收银台】
1. 接入 mock 支付
2. 接入提交支付后,直接成功的返回
2023-08-13 17:30:20 +08:00
YunaiV 04ccd6d704 【收银台】
1. 清理多余的支付代码
2023-08-13 16:35:18 +08:00
YunaiV 644b458969 【收银台】
1. 完成微信小程序的支付
2023-07-08 12:43:29 +08:00
YunaiV 2afae4f007 【订单支付结果页】
1. 增加后端支付渠道的配置
2023-07-06 23:16:33 +08:00
YunaiV 6316405712 【订单支付结果页】
1. 接入微信公众号 MP 支付
2023-07-06 19:10:53 +08:00
YunaiV bff8bd8dd0 【订单支付结果页】
1. 和支付结果的回调打通
2023-07-04 23:42:48 +08:00
YunaiV a7e784555d 【订单支付结果页】
1. 实现功能
2023-07-04 22:40:58 +08:00
YunaiV 965d6683bf 【支付页】
1. 初步接入 pc、wap 支付
2. 清理多余的变量
2023-07-04 20:31:21 +08:00
YunaiV be43aaafd8 【订单详情】
1. 配送信息
2023-07-02 12:54:57 +08:00
YunaiV 00ed94c762 【订单详情】
1. 取消订单
2. 删除订单
2023-07-02 00:15:10 +08:00
YunaiV 2aef6a4fe5 【订单详情】
1. 字段的展示
2. 各状态下的操作按钮
2023-07-01 21:47:34 +08:00
YunaiV 62644ddb56 【订单详情】
1. 移除冗余的支付
2. 接入后端的订单详情 API 接口
2023-07-01 21:02:15 +08:00
YunaiV 6a1b442c3c 【订单列表】
1. 基本实现主体功能
2023-07-01 18:21:24 +08:00
YunaiV d175b3dd26 【订单确认】
1. 接入支付页
2023-07-01 00:19:38 +08:00
YunaiV 224e4f4772 【收银台】
1. 从 crmeb php 项目迁移
2023-07-01 00:05:01 +08:00
YunaiV 8d6d8a25fd 【订单确认】
1. 去除无用的支付逻辑
2. 去除 textarea 的状态
2023-06-30 23:04:05 +08:00
YunaiV 1a8c321ca7 【订单确认】
1. 接入价格信息
2. 调整 address 的获取
2023-06-30 22:44:36 +08:00
YunaiV fe955e9fb1 【订单确认】
1. 接入订单商品列表
2023-06-29 23:32:16 +08:00
YunaiV 3ae38b6626 【订单确认】
1. 将 coupon 接入优惠劵列表
2023-06-29 20:19:40 +08:00
YunaiV 3d4400f198 【订单确认】
1. 将 coupon 优惠劵的变量、方法先整理一下
2023-06-29 00:37:30 +08:00
YunaiV ec0e0ee234 【门店自提列表】
1. 功能实现
2023-06-29 00:24:30 +08:00
YunaiV 39873a9e3c 【商品评论列表】
1. 功能实现
2023-06-28 00:25:26 +08:00
YunaiV afad547b14 【home 组件】
1. 功能实现
2023-06-27 22:43:47 +08:00
YunaiV b1da35a040 【文章详情】
1. 功能实现
2023-06-27 22:19:08 +08:00
YunaiV dcae130b4a 【WebView 界面】
1. 整理代码
2023-06-27 00:36:49 +08:00
YunaiV 828505c2dd 删除无用页面 2023-06-27 00:16:57 +08:00
YunaiV 8e2d28d27a 【App 页面】
1. 整理代码
2023-06-27 00:06:02 +08:00
YunaiV 72385f8ed8 【文章列表】
1. 功能实现
2023-06-26 23:47:06 +08:00
YunaiV c23e1922a3 【确认页,选择地址】
1. 功能实现
2023-06-26 20:52:27 +08:00
YunaiV e08f65b4cb 【收货地址添加】
1. 功能实现
2023-06-26 20:06:29 +08:00
YunaiV 6442fc5c11 删除无用页面 2023-06-25 22:27:09 +08:00
YunaiV 21461991ac 【我的收货地址】
1. 接入列表、删除、默认的逻辑
2023-06-25 22:10:27 +08:00
YunaiV e58e910951 【首页】
1. 接入优惠劵的逻辑
2023-06-25 21:01:34 +08:00
YunaiV 4c0704b5cd 【首页】
1. 清理多余的变量、方法
2. 清理 MP 消息模版的获取,貌似暂时没用到
2023-06-25 20:48:13 +08:00
YunaiV 87bd79b8ee 【我的优惠劵】
1. 实现功能
2023-06-25 20:28:37 +08:00
YunaiV 576d0874ad 【优惠劵领取】
1. 实现功能
2023-06-25 17:43:59 +08:00
YunaiV a08e05ea8b 【商品推荐】
1. 实现功能
2023-06-25 16:48:23 +08:00
YunaiV 202ee764ba 删除无用页面 2023-06-25 12:33:20 +08:00
YunaiV 0d723b1f28 【我的收藏】
1. 实现功能
2023-06-25 12:26:24 +08:00
YunaiV 10ee3965df 删除无用页面 2023-06-25 11:46:26 +08:00
YunaiV 13769114d2 【商品列表】
1. 实现完成
2023-06-25 11:20:41 +08:00
YunaiV 335146ed94 【商品分类】
1. 实现完成
2023-06-23 23:53:53 +08:00
YunaiV 0a575e92d0 【首页】
1. 接入商品推荐
2023-06-23 23:37:28 +08:00
YunaiV 7f0870a34a 【商品搜索】
1. 实现完成
2023-06-23 22:52:45 +08:00
YunaiV 3746fe27bb 【商品热门推荐】
1. 实现完成
2023-06-23 01:25:37 +08:00
YunaiV edabd0c29f 商品的图片轮播、视频播放 2023-06-23 00:43:02 +08:00
YunaiV 5d9be29f04 删除 components/couponWindow 暂时没用到 2023-06-23 00:39:54 +08:00
YunaiV 8718927bb1 【砍价详细】
1. 移除后端的 action,而是前端计算,和后端解耦
2023-06-23 00:26:28 +08:00
YunaiV e67fdf510c Merge remote-tracking branch 'origin/master' 2023-06-22 23:05:54 +08:00
YunaiV 4dd71968a5 【砍价记录列表】
1. 基本对接完成
2023-06-22 23:05:48 +08:00
YunaiV e763dce12b 删除暂时用不到的界面 2023-06-22 00:20:47 +08:00
YunaiV 4aed2a78e0 【砍价详情】
1. 基本对接完成
2023-06-21 23:45:45 +08:00
YunaiV 9199f20de0 【砍价详情】
1. 增加拼团记录的调用(部分)
2023-06-21 00:30:15 +08:00
YunaiV 220b21b6b6 【砍价详情】
1. 接入拼团活动的详情接口
2023-06-20 21:18:32 +08:00
YunaiV 725a37eae5 【砍价详情】
1. 清理无用变量
2023-06-19 23:53:34 +08:00
YunaiV f256bb904d 【砍价活动列表】
1. 全部接入
2023-06-19 23:35:19 +08:00
YunaiV b88b260ac2 【首页】
1. 砍价活动组件
2023-06-19 20:36:58 +08:00
YunaiV 7f976681e4 【秒杀活动列表】 2023-06-18 21:24:11 +08:00
YunaiV cf23ffbbfe 优化限购、库存的返回结果 2023-06-18 20:15:41 +08:00
YunaiV a89d014836 【首页】
1. 秒杀活动组件
2023-06-18 02:01:24 +08:00
YunaiV 987e90f80a 【首页】
1. 拼团活动组件
2023-06-18 00:36:22 +08:00
YunaiV 70fe080f57 【拼团活动列表】
1. 接入 banner 活动页
2023-06-17 00:48:00 +08:00
YunaiV b8e61cf7a0 【拼团活动列表】
1. 接入拼团列表
2023-06-16 22:43:16 +08:00
YunaiV 96db421a2a 【拼团状态详情】
1. 接入拼团记录、活动、商品信息等
2023-06-16 19:44:57 +08:00
YunaiV 31ead800b1 【拼团商品详情】
1. 整理变量
2023-06-15 20:54:32 +08:00
YunaiV 31c96a5c76 【拼团商品详情】
1. 接入分销、分享的逻辑
2023-06-15 20:40:34 +08:00
YunaiV 868901739c 【拼团商品详情】
1. 接入 SKU 选择
2023-06-15 20:26:03 +08:00
YunaiV 04350dc5c2 【拼团商品详情】
1. 初步增加商品详情的加载
2023-06-14 21:21:01 +08:00
YunaiV cb01b3d6c1 【拼团商品详情】
1. 初步增加活动详情的加载
2023-06-14 00:16:34 +08:00
YunaiV 6fcb8196c3 【秒杀商品详情】
1. 完成秒杀详情
2023-06-11 23:18:54 +08:00
YunaiV 4e756482ce 【秒杀商品详情】
1. 接入滚动逻辑
2023-06-11 23:06:35 +08:00
YunaiV 0ceb18b823 【秒杀商品详情】
1. 接入分销
2023-06-11 22:59:10 +08:00
YunaiV ddf9aa6d8a 【秒杀商品详情】
1. 接入收藏
2023-06-11 22:21:35 +08:00
YunaiV 02aa4756fd 【秒杀商品详情】
1. 接入评价
2023-06-11 22:18:47 +08:00
YunaiV 80c5617d52 【秒杀商品详情】
1. 接入下单流程
2023-06-11 22:11:30 +08:00
YunaiV 7bc30ba3eb 【秒杀商品详情】
1. 完整接入 SKU 选择
2023-06-11 18:37:40 +08:00
YunaiV 07b9521a63 【秒杀商品详情】
1. 简单接入 SKU 选择
2023-06-11 00:14:28 +08:00
YunaiV eab00bf2a6 【秒杀商品详情】
1. 接入秒杀状态
2023-06-10 23:18:33 +08:00
YunaiV 9e74d2a704 【秒杀商品详情】
1. 整理下整体界面
2023-06-10 22:00:41 +08:00
YunaiV 992321be2a 【商品详情】
1. 接入商品推荐
2023-06-10 17:51:02 +08:00
YunaiV b6fd22c8fb 【商品详情】
1. 接入营销活动列表
2023-06-10 14:47:22 +08:00
YunaiV d89f64f80f 【商品详情】
1. 接入优惠劵逻辑
2023-06-10 09:57:20 +08:00
YunaiV 33311ae19c 【商品详情】
1. 接入评论逻辑
2023-06-10 00:17:07 +08:00
YunaiV 8fbdec3738 【商品详情】
1. 接入收藏逻辑
2023-06-09 20:43:37 +08:00
YunaiV e68d39c99c 【订单详情】
1. 清理无用的 systemStore 门店信息
2. 清理公众号的 authorize 组件
2023-06-09 00:30:10 +08:00
YunaiV 6320bb3453 【订单详情】
1. 梳理分销、分享相关的逻辑,把方法放到一起
2023-06-09 00:18:44 +08:00
YunaiV 83a6955778 【订单详情】
1. 将商品相关的方法挪到最前面
2023-06-08 21:55:18 +08:00
YunaiV 8b2291d8b4 【订单详情】
1. 处理 nav + scroll 相关的变量和方法
2023-06-08 01:08:13 +08:00
YunaiV 16b6a37074 【订单详情】
1. 修复微信小程序的兼容性,主要 productWindow 子组件不允许修改 props 的问题
2023-06-08 00:06:16 +08:00
YunaiV ed2ea5876c 【订单详情】
1. onLoad 的注释补全
2. onReady 的注释补全
2023-06-07 23:07:57 +08:00
YunaiV dcbe6241f0 【订单详情】
1. 购物车数量、添加
2. 提交订单
2023-06-07 20:23:44 +08:00
YunaiV c9f3f7f6ff 【订单详情】
1. 梳理 html 和 data 属性,标记哪些是 TODO
2023-06-06 23:47:32 +08:00
YunaiV 9fca18b350 【订单详情】
1. 简化 sku 选择的逻辑,默认选择有库存,否则第一个 sku
2023-06-06 23:18:13 +08:00
YunaiV c8fdda0bb0 【订单详情】
1. 接入 sku 的选择
2023-06-06 22:47:43 +08:00
YunaiV 4e465b7e72 【订单详情】
1. 初步接入详情 API 接口
2023-06-06 19:12:07 +08:00
YunaiV 4a9c829d6f 订单、售后相关的订单标记 2023-06-05 00:03:30 +08:00
stivepeim 8ccaa633ff update install info 2023-04-06 18:26:56 +08:00
stivepeim ce1472d09c 规整演示数据 管理端 admin / 123456 移动端 18292417675 / crmeb@123456 2023-03-15 18:02:30 +08:00
stivepeim e93170f25a 修改pom缺省version节点 2022-03-30 16:36:18 +08:00
hejinfu1026 f1c8338981 增加安装查询 2022-01-26 10:42:05 +08:00
hejinfu1026 6397287238 修改y移动端图片上传配置api 2022-01-14 17:50:32 +08:00
hejinfu1026 fc25cdfa02 移动端提前缓存城市数据,避免编辑地址时等待请求 2022-01-14 09:50:15 +08:00
hejinfu1026 f4e2327095 12.31移动端开源代码更新 2021-12-31 15:52:11 +08:00
hejinfu1026 955ea2fdee 修复一些缺陷,更换tabbar素材 2021-11-15 10:16:11 +08:00
stivepeim c42aab28a1 全新UI视觉体验,移动端API优化降低重复调用,提高并发6倍,修复N多Bug 2021-06-11 17:41:16 +08:00
stivepeim 39c4716fc1 修复全量sql 修复配置文件
修复公众号授权问题
2021-05-17 16:41:39 +08:00
stivepeim ddf354921b 修复公众号授权10003的问题! 2021-05-15 17:26:02 +08:00
stivepeim 96cbe9d7e3 小程序授权登录回复正常 2021-05-07 18:31:36 +08:00
stivepeim df945fc609 修复 小程序授权登录后跳转问题 2021-05-06 14:47:32 +08:00
stivepeim 829babf74a 修复routine.js 文件 2021-05-06 14:05:24 +08:00
stivepeim 95031bc483 修复 getUserProfile 2021-05-06 10:04:18 +08:00
stivepeim 5e6d4b5a77 1:运行Java程序后访问localhost:8080 自动跳转doc.html
2:修复默认运费配置数据,确定订单下单正确
3:小程序超包问题
2021-04-26 18:40:42 +08:00
stivepeim bd5e8f1aea 修复内容
1. 会员等级背景图去掉校验
	2. 当查询不到会员等级是,按无会员等级展示
	3. 删除商城首页冗余配置在index中的引用
	4. 换绑推广人时,计算上一个推广人的推广人数
	5. pc后台清除推广人时,更新推广人数量
	6. 保证砍价金额最小为0.01
	7. 修复商品删除时购物车关联删除
	8. 删除商品问题修复
	9. 运费模板——指定包邮,包邮数量类型修改
	10. 签到错误修复
	11. 修复我的优惠券只查询20条的问题
	12. 文章列表修复
	13. 拼团商品详情页数据统计显示问题修复
	14. PC后台,账户详情,持有优惠券列表修复
	15. 支付查询参数修复
	16. 修复过期优惠券可以重复领取
	17. 订单邮费切换地址重复计算修复
	18. 判断是否在指定包邮区域内 必须满足件数 + 金额 才能包邮
	19. 支付页面,切换tab,金额计算问题修复
	20. 物流模板新增、编辑——修复
	21. 去除线下邮费的影响
	22. 订单运费计算重写
	23. 下单页面到店自提合计金额不应该计算商品邮费
	24. 新人券领取后,部分使用时间为空——修复
2021-03-19 18:26:43 +08:00
guaishoudemao d4f2aae8f9 更新代码 2021-02-06 17:25:18 +08:00
stivepeim f3c1bcb6c5 H5首页 样式修复 2021-01-20 15:54:45 +08:00
stivepeim 621819b067 ## v1.3.1 更新列表
1. 【修复】申请退款后积分等操作可能出现错误的问题
	2. 【修复】拼团支付可能出现支付错误的问题
	3. 【修复】退款申请后的订单流程优化和积分赠送的问题
	4. 【修复】回收站中的商品无法恢复的问题
	5. 【修复】一号通短信查询记录不完整的问题
	6. 【修复】用户管理批量加分组,标签的问题
	7. 【修复】积分日志搜索显示有误的问题
	8. 【修复】手动发送优惠券可能会出错的问题
	9. 【修复】核销订单创建在某种条件下会出错的问题
	10. 【修复】移动端商品详情,购物车等样式兼容问题
	11. 【修复】业务流程性的优化
2021-01-19 10:16:45 +08:00
stivepeim a6f622572a update sql and version Info 2020-12-23 17:21:20 +08:00
stivepeim 3c0b73f100 圣诞快乐
# v1.3 更新列表
    1. 【新增】砍价
	2. 【新增】拼团
	3. 【新增】一号通
	4. 【修复】商品sku 编辑时出现商品属性对应错误的问题
	5. 【修复】商品推广海报生成二维码可能会出错的问题【小程序调试中】
	6. 【修复】微信公众号和小程序头像可能获取不到的问题
	7. 【修复】下单时可能会出错的问题
	8. 【修复】pc管理端用户访问量
	9. 【修复】微信退款
	10. 【修复】管理端订单状态可能出现不正确的情况
	11. 【修复】WEB管理端-菜单色调,短信API更新,首页用户访问量,系统设置tab是自动选择下一及表单
	12. 【修复】系统设置出现更新不正确的问题
2020-12-23 15:56:45 +08:00
stivepeim 9b39c27876 更新Note
1. 修复购物车,订单和退单后后置任务正确执行
	2. 修复佣金记录金额和详情
	3. 修复管理端 移动应用界面下订单管理数据统计不准确的问题
	4. 修复短信API升级-后台使用一号通
	5. 修复用户管理相关问题
	6. 修复核销点核销后核销地址不准确
	7. 修复资源同步云服务的问题
新增功能
	1. 秒杀
		a. 秒杀时段配置
		b. 秒杀商品维护
	2. 财务管理
		a. 申请提现
		b. 财务记录
			i. 充值记录
			ii. 资金监控
		c. 佣金记录
	3. 普通商品显示该商品正在参加的活动信息[秒杀]
2020-11-05 16:21:06 +08:00
张乐 6fe074baaa 移动端代码优化 2020-09-15 18:42:06 +08:00
张乐 1d816d6b06 bug修复 2020-09-15 18:24:23 +08:00
张乐 8c67e73d43 v1.1
1、提货点
2、客服(腾讯云智服)
3、接口权限控制
4、复制第三方商品可配置
4、优化附件上传配置
5、手机端核销订单
6、手机端订单统计、订单管理
7、短信优化
8、订阅消息全自动化
2020-09-15 16:13:25 +08:00
张乐 6685425ae0 资金明细优化 2020-08-26 18:02:40 +08:00
张乐 6a7437f068 bug修复 2020-08-17 18:32:53 +08:00
张乐 deabefd64f 紧急修复了一些bug 2020-08-17 15:28:28 +08:00
张乐 d1682fba15 我们发布啦 2020-08-13 16:12:57 +08:00
958 changed files with 56699 additions and 92889 deletions

No files matched your search

-31
View File
@@ -1,31 +0,0 @@
# 版本号
SHOPRO_VERSION=v2.4.0
# 后端接口 - 正式环境(通过 process.env.NODE_ENV 非 development)
SHOPRO_BASE_URL=http://api-dashboard.yudao.iocoder.cn
# 后端接口 - 测试环境(通过 process.env.NODE_ENV = development)
SHOPRO_DEV_BASE_URL=http://127.0.0.1:48080
### SHOPRO_DEV_BASE_URL = http://yunai.natapp1.cc
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
SHOPRO_UPLOAD_TYPE=server
# 后端接口前缀(一般不建议调整)
SHOPRO_API_PATH=/app-api
# 后端 websocket 接口前缀
SHOPRO_WEBSOCKET_PATH=/infra/ws
# 开发环境运行端口
SHOPRO_DEV_PORT=3000
# 客户端静态资源地址 空=默认使用服务端指定的CDN资源地址前缀 | local=本地 | http(s)://xxx.xxx=自定义静态资源地址前缀
SHOPRO_STATIC_URL=http://test.yudao.iocoder.cn
### SHOPRO_STATIC_URL = https://file.sheepjs.com
# 是否开启直播 1 开启直播 | 0 关闭直播 (小程序官方后台未审核开通直播权限时请勿开启)
SHOPRO_MPLIVE_ON=0
# 租户ID 默认 1
SHOPRO_TENANT_ID=1
+24 -11
View File
@@ -1,11 +1,24 @@
unpackage/*
node_modules/*
.idea/*
deploy.sh
.hbuilderx/
.vscode/
**/.DS_Store
yarn.lock
package-lock.json
*.keystore
pnpm-lock.yaml
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
build.sh
.idea
unpackage
+20
View File
@@ -0,0 +1,20 @@
{ // 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" : "remote"
},
"h5" :
{
"launchtype" : "remote"
},
"mp-weixin" :
{
"launchtype" : "remote"
},
"type" : "uniCloud"
}
]
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

-6
View File
@@ -1,6 +0,0 @@
/unpackage/*
/node_modules/**
/uni_modules/**
/public/*
**/*.svg
**/*.sh
-10
View File
@@ -1,10 +0,0 @@
{
"printWidth": 100,
"semi": true,
"vueIndentScriptAndStyle": true,
"singleQuote": true,
"trailingComma": "all",
"proseWrap": "never",
"htmlWhitespaceSensitivity": "strict",
"endOfLine": "auto"
}
+187 -32
View File
@@ -1,39 +1,194 @@
<script setup>
import { onLaunch, onShow, onError } from '@dcloudio/uni-app';
import { ShoproInit } from './sheep';
<script>
import { HTTP_REQUEST_URL } from './config/app';
import Auth from './libs/wechat.js';
import Routine from './libs/routine.js';
export default {
globalData: {
spid: 0,
code: 0,
isLogin: false,
userInfo: {},
MyMenus: [],
windowHeight: 0,
id: 0
},
onLaunch: function(option) {
let that = this;
// 获得全局的 window 高度
// #ifdef H5
uni.getSystemInfo({
success: function(res) {
// 首页没有title获取的整个页面的高度,里面的页面有原生标题要减掉就是视口的高度
// 状态栏是动态的可以拿到 标题栏是固定写死的是44px
let height = res.windowHeight - res.statusBarHeight - 44
// #ifdef H5
that.globalData.windowHeight = res.windowHeight + 'px'
// #endif
}
});
// #endif
onLaunch(() => {
// 隐藏原生导航栏 使用自定义底部导航
uni.hideTabBar();
// 获取导航高度;
uni.getSystemInfo({
success: function(res) {
that.globalData.navHeight = res.statusBarHeight * (750 / res.windowWidth) + 91;
}
});
// #ifdef MP
let menuButtonInfo = uni.getMenuButtonBoundingClientRect();
that.globalData.navH = menuButtonInfo.top * 2 + menuButtonInfo.height / 2;
// #endif
// 加载Shopro底层依赖
ShoproInit();
});
// #ifdef MP
if (HTTP_REQUEST_URL === '') {
console.error(
"请配置根目录下的config.js文件中的 'HTTP_REQUEST_URL'\n\n请修改开发者工具中【详情】->【AppID】改为自己的Appid\n\n请前往后台【小程序】->【小程序配置】填写自己的 appId and AppSecret"
);
return false;
}
// TODO 芋艿: 分销
if (option.query.hasOwnProperty('scene')) {
switch(option.scene){
case 1047: // 扫描小程序码
case 1048: // 长按图片识别小程序码
case 1049: // 手机相册选取小程序码
case 1001: // 直接进入小程序
let value = this.$util.getUrlParams(decodeURIComponent(option.query.scene));
let values = value.split(',');
if(values.length === 2){
let v1 = values[0].split(":");
if (v1[0] === 'pid') {
that.globalData.spid = v1[1];
} else{
that.globalData.id = v1[1];
}
let v2 = values[1].split(":");
if (v2[0] === 'pid') {
that.globalData.spid = v2[1];
}else{
that.globalData.id = v2[1];
}
}else{
that.globalData.spid = values[0].split(":")[1];
}
break;
}
}
// #endif
onError((err) => {
console.log('AppOnError:', err);
});
// #ifdef H5
// 静默登录的情况一:微信公众号
let snsapiBase = 'snsapi_base';
let urlData = location.pathname + location.search;
if (!that.$store.getters.isLogin && Auth.isWeixin()) {
const { code, state } = option.query;
if (code && code !== uni.getStorageSync('snsapiCode')
&& location.pathname.indexOf('/pages/users/wechat_login/index') === -1) {
// 存储静默授权code
uni.setStorageSync('snsapiCode', code);
Auth.auth(code, state, that.$Cache.get('spread')).then(res => {
// TODO 芋艿:snRouter 的作用是啥
uni.setStorageSync('snRouter', decodeURIComponent(decodeURIComponent(option.query.back_url)));
// 跳转回去
location.replace(decodeURIComponent(decodeURIComponent(option.query.back_url)));
}).catch(error => {
this.$Cache.set('snsapiKey', code);
// TODO 芋艿:为什么没有 snsapiKey 就反复认证???没看懂
// if (!this.$Cache.has('snsapiKey')) {
// if (location.pathname.indexOf('/pages/users/wechat_login/index') === -1) {
// Auth.oAuth(snsapiBase, option.query.back_url);
// }
// }
});
} else {
if (!this.$Cache.has('snsapiKey')) {
if (location.pathname.indexOf('/pages/users/wechat_login/index') === -1) {
Auth.oAuth(snsapiBase, urlData);
}
}
}
} else {
if (option.query.back_url) {
location.replace(uni.getStorageSync('snRouter'));
}
}
// #endif
onShow((options) => {
// #ifdef APP-PLUS
// 获取urlSchemes参数
const args = plus.runtime.arguments;
if (args) {
}
// 获取剪贴板
uni.getClipboardData({
success: (res) => { },
});
// #endif
// #ifdef MP-WEIXIN
// 确认收货回调结果
console.log(options,'options');
// #endif
});
// #ifdef MP
// 静默登录的情况二:微信小程序
if (!this.$store.getters.isLogin) {
let spread = that.globalData.spid ? that.globalData.spid : 0;
Routine.getCode().then(code => {
Routine.authUserInfo(code, spread)
.then(res => {})
}).catch(res => {
uni.hideLoading();
});
}
// #endif
},
async mounted() {
// 读取用户的基本信息
if (this.$store.getters.isLogin && !this.$Cache.get('USER_INFO')) {
await this.$store.dispatch('USERINFO');
}
},
onShow: function() {
// #ifdef H5
uni.getSystemInfo({
success(e) {
// TODO 芋艿:这样是否合理???
/* 窗口宽度大于420px且不在PC页面且不在移动设备时跳转至 PC.html 页面 */
if (e.windowWidth > 420 && !window.top.isPC && !/iOS|Android/i.test(e.system)) {
// window.location.pathname = 'https://java.crmeb.net/';
/* 若你的项目未设置根目录(默认为 / 时),则使用下方代码 */
window.location.pathname = '/static/html/pc.html';
}
}
})
// #endif
}
}
</script>
<style>
@import url("@/plugin/animate/animate.min.css");
@import 'static/css/base.css';
@import 'static/iconfont/iconfont.css';
@import 'static/css/guildford.css';
@import 'static/css/style.scss';
<style lang="scss">
@import '@/sheep/scss/index.scss';
/* 条件编译,仅在H5平台生效 */
// #ifdef H5
body::-webkit-scrollbar,
html::-webkit-scrollbar {
display: none;
}
// #endif
view {
box-sizing: border-box;
}
.bg-color-red {
background-color: #E93323 !important;
}
.syspadding {
padding-top: var(--status-bar-height);
}
.flex {
display: flex;
}
.uni-scroll-view::-webkit-scrollbar {
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
display: none
}
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
</style>
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2022 lidongtony
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.
+5 -6
View File
@@ -23,18 +23,18 @@
![功能图](/.image/common/mall-feature.png)
* 基于 uni-app + Vue3 开发,支持微信小程序、微信公众号、H5 移动端,未来会支持支付宝小程序、抖音小程序等
* 基于 uniapp 开发,支持微信小程序、微信公众号、H5 移动端,未来会支持支付宝小程序、抖音小程序等
* 支持 SaaS 多租户,可满足商品、订单、支付、会员、优惠券、秒杀、拼团、砍价、分销、积分等多种经营需求
## 🔥 后端架构
支持 Spring Boot、Spring Cloud 两种架构:
① Spring Boot 单体架构:<https://doc.iocoder.cn>
① Spring Boot 单体架构:<https://github.com/YunaiV/ruoyi-vue-pro>
![架构图](/.image/common/ruoyi-vue-pro-architecture.png)
② Spring Cloud 微服务架构:<https://cloud.iocoder.cn>
② Spring Cloud 微服务架构:<https://github.com/YunaiV/yudao-cloud>
![架构图](/.image/common/yudao-cloud-architecture.png)
@@ -42,9 +42,9 @@
![移动端预览](/.image/common/mall-preview.png)
## 🐶 管理端预览
_前端基于 crmeb uniapp 经过授权重构,优化代码实现_
![店铺装修](/.image/mall/店铺装修.png)
## 🐶 管理端预览
![会员详情](/.image/mall/会员详情.png)
@@ -53,4 +53,3 @@
![订单详情](/.image/mall/订单详情.png)
![营销中心](/.image/mall/营销中心.png)
-3
View File
@@ -1,3 +0,0 @@
{
"prompt" : "template"
}
+143
View File
@@ -0,0 +1,143 @@
import request from "@/utils/request.js";
/**
*
* 所有活动接口 包括:拼团,砍价,秒杀
*
*/
/**
* 拼团列表
*
*/
export function getCombinationList(data) {
return request.get('combination/list', data,{noAuth:true});
}
/**
* 拼团 开团
*/
export function getCombinationPink(id) {
return request.get("combination/pink/" + id);
}
/**
* 拼团 取消开团
*/
export function postCombinationRemove(data) {
return request.post("combination/remove",data);
}
/**
* 砍价列表
*/
export function getBargainList(data) {
return request.get("bargain/list", data,{noAuth:true});
}
/**
*
* 砍价列表(已参与)
* @param object data
*/
export function getBargainUserList(data){
return request.get('bargain/record',data);
}
/**
*
* 取消砍价
* @param int bargainId
*/
export function bargainUserCancel(bargainId){
return request.post('bargain/user/cancel', { bargainId: bargainId})
}
/**
* 砍价产品详情
*/
export function getBargainDetail(id) {
return request.get("bargain/detail/" + id);
}
/**
* 用户砍价信息,注意自己的活动和别人的活动的区别
*/
export function getBargainUser(data) {
return request.get("bargain/user", data);
}
/**
* 砍价开启
*/
export function postBargainStart(bargainId) {
return request.post("bargain/start", { bargainId: bargainId});
}
/**
* 砍价 帮助好友砍价
*/
export function postBargainHelp(data) {
return request.post("bargain/help", data);
}
/**
* 砍价 砍掉金额
*/
export function postBargainHelpPrice(data) {
return request.post("bargain/help/price", data);
}
/**
* 砍价 砍价帮
*/
export function postBargainHelpList(params,data) {
return request.get("bargain/help/list?limit="+params.limit+"&page="+params.page, data,{});
}
/**
* 砍价海报
* @param object data
*
*/
export function getBargainPoster(data){
return request.post('bargain/poster',data)
}
/**
* 拼团海报
* @param object data
*
*/
export function getCombinationPoster(data){
return request.post('combination/poster',data)
}
/**
* 砍价取消
*/
export function getBargainUserCancel(data) {
return request.post("/bargain/user/cancel", data);
}
/**
* 获取秒杀小程序二维码
*/
export function seckillCode(id,data) {
return request.get("seckill/code/"+id,data);
}
/**
* 获取拼团小程序二维码
*/
export function scombinationCode(id) {
return request.get("combination/code/"+id);
}
/**
* 首页砍价产品列表
*/
export function bargainHeaderApi(){
return request.get('bargain/header');
}
+164
View File
@@ -0,0 +1,164 @@
import request from "@/utils/request.js";
/**
* 公共接口 ,优惠券接口 , 行业此讯 , 手机号码注册
*
*/
/**
* 获取主页数据 无需授权
*
*/
export function getIndexData()
{
return request.get("index",{},{ noAuth : true});
}
/**
* 获取登录授权login
*
*/
export function getLogo()
{
return request.get('wechat/getLogo', {}, { noAuth : true});
}
/**
* 保存form_id
* @param string formId
*/
export function setFormId(formId) {
return request.post("wechat/set_form_id", { formId: formId});
}
/**
* 领取优惠券
* @param int couponId
*
*/
export function setCouponReceive(couponId){
return request.post('coupon/receive', { couponId: couponId});
}
/**
* 优惠券列表
* @param object data
*/
export function getCoupons(data){
return request.get('coupons',data,{noAuth:true})
}
/**
* 手机号+验证码登录接口
* @param object data
*/
export function loginMobile(data){
return request.post('login/mobile',data,{noAuth:true})
}
/**
* 获取短信KEY
* @param object phone
*/
export function verifyCode(){
return request.get('verify_code', {},{noAuth:true})
}
/**
* 验证码发送
* @param object phone
*/
export function registerVerify(phone){
return request.post('sendCode', { phone: phone },{noAuth:true},1)
}
/**
* 手机号注册
* @param object data
*
*/
export function phoneRegister(data){
return request.post('register',data,{noAuth:true});
}
/**
* 手机号修改密码
* @param object data
*
*/
export function phoneRegisterReset(data){
return request.post('register/reset',data,{noAuth:true})
}
/**
* 手机号+密码登录
* @param object data
*
*/
export function phoneLogin(data){
return request.post('login',data,{noAuth:true})
}
/**
* 切换H5登录
* @param object data
*/
// #ifdef MP
export function switchH5Login(){
return request.post('switch_h5', { 'from':'routine'});
}
// #endif
/*
* h5切换公众号登录
* */
// #ifdef H5
export function switchH5Login() {
return request.post("switch_h5", { 'from': "wechat" });
}
// #endif
/**
* 换绑手机号
*
*/
export function bindingPhone(data){
return request.post('update/binding',data);
}
/**
* 换绑手机号校验
*
*/
export function bindingVerify(data){
return request.post('update/binding/verify',data);
}
/**
* 退出登錄
*
*/
export function logout(){
return request.get('logout');
}
/**
* 获取订阅消息id
*/
export function getTemlIds(data)
{
return request.get('wechat/program/my/temp/list', data , { noAuth:true});
}
/**
* 获取小程序直播列表
*/
export function getLiveList(page,limit) {
return request.get('wechat/live', { page, limit}, { noAuth: true });
}
/**
* 获取小程序二维码
*/
export function getQrcode(data) {
return request.post('qrcode/get',data,{ noAuth: true });
}
+33
View File
@@ -0,0 +1,33 @@
import request from "@/utils/request.js";
// 获得用户收件地址
export function getAddress(id) {
return request.get('app-api/member/address/get', {
id
});
}
// 获得默认的用户收件地址
export function getDefaultUserAddress() {
return request.get('app-api/member/address/get-default', {});
}
// 获得用户收件地址列表
export function getAddressList() {
return request.get('app-api/member/address/list', {});
}
// 创建用户收件地址
export function createAddress(data) {
return request.post('app-api/member/address/create', data);
}
// 更新用户收件地址
export function updateAddress(data) {
return request.put('app-api/member/address/update', data);
}
// 删除用户收件地址
export function deleteAddress(id) {
return request.delete('app-api/member/address/delete?id=' + id, {});
}
+67
View File
@@ -0,0 +1,67 @@
import request from "@/utils/request.js";
// 发送手机验证码
export function sendSmsCode(mobile, scene) {
return request.post('app-api/member/auth/send-sms-code', {
mobile,
scene
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 校验手机验证码
export function validateSmsCode(mobile, scene, code) {
return request.post('app-api/member/auth/validate-sms-code', {
mobile,
scene,
code
});
}
// 登出系统
export function logout() {
return request.post('app-api/member/auth/logout');
}
// 使用手机 + 密码登录
export function login(data) {
return request.post('app-api/member/auth/login', data, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 使用手机 + 验证码登录
export function smsLogin(data) {
return request.post('app-api/member/auth/sms-login', data, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 社交快捷登录
export function socialLogin(type, code, state) {
return request.post('app-api/member/auth/social-login', {
type,
code,
state
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 微信小程序的一键登录登录
export function weixinMiniAppLogin(phoneCode, loginCode) {
return request.post('app-api/member/auth/weixin-mini-app-login', {
phoneCode,
loginCode
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 创建微信 JS SDK 初始化所需的签名
export function createWeixinMpJsapiSignature(url) {
return request.post("app-api/member/auth/create-weixin-jsapi-signature?url=" + url, {}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+11
View File
@@ -0,0 +1,11 @@
import request from "@/utils/request.js";
// 获得会员等级列表
export function getLevelList() {
return request.get('app-api/member/level/list');
}
// 获得会员经验记录分页
export function getExperienceRecordPage() {
return request.get('app-api/member/experience-record/page');
}
+6
View File
@@ -0,0 +1,6 @@
import request from "@/utils/request.js";
// 获得用户积分记录分页
export function getPointRecordPage() {
return request.get('app-api/member/point/record/page');
}
+21
View File
@@ -0,0 +1,21 @@
import request from "@/utils/request.js";
// 获得签到规则列表
export function getSignInConfigList() {
return request.get('app-api/member/sign-in/config/list');
}
// 获得个人签到统计
export function getSignInRecordSummary() {
return request.get('app-api/member/sign-in/record/get-summary')
}
// 签到
export function createSignInRecord() {
return request.post('app-api/member/sign-in/record/create')
}
// 获得签到记录分页
export function getSignRecordPage() {
return request.get('app-api/member/sign-in/record/page');
}
+28
View File
@@ -0,0 +1,28 @@
import request from "@/utils/request.js";
// 获得基本信息
export function getUserInfo() {
return request.get('app-api/member/user/get');
}
// 修改基本信息
export function updateUser(data) {
return request.put('app-api/member/user/update', data);
}
// 修改用户手机
export function updateUserMobile(data) {
return request.put('app-api/member/user/update-mobile', data);
}
// 修改用户密码
export function updateUserPassword(data) {
return request.put('app-api/member/user/update-password', data);
}
// 重置密码
export function resetUserPassword(data) {
return request.put('app-api/member/user/reset-password', data, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+247
View File
@@ -0,0 +1,247 @@
import request from "@/utils/request.js";
/**
* 获取购物车列表
* @param numType boolean true 购物车数量,false=购物车产品数量
*/
export function getCartCounts(numType,type) {
return request.get("cart/count?numType=" + numType + "&type=" + type);
}
/**
* 获取购物车列表
*
*/
export function getCartList(data) {
return request.get("cart/list", data);
}
/**
* 修改购物车数量
* @param int cartId 购物车id
* @param int number 修改数量
*/
export function changeCartNum(cartId, number) {
return request.post("cart/num", {
id: cartId,
number: number
}, {}, 1);
}
/**
* 清除购物车
* @param object ids join(',') 切割成字符串
*/
export function cartDel(ids) {
if (typeof ids === 'object')
ids = ids.join(',');
return request.post('cart/delete', {
ids: ids
}, {}, 1);
}
/**
* 购物车重选提交
*
*/
export function getResetCart(data) {
return request.post('cart/resetcart', data);
}
/**
* 订单列表
* @param object data
*/
export function getOrderList(data) {
return request.get('order/list', data);
}
/**
* 订单产品信息
* @param string unique
*/
export function orderProduct(data) {
return request.post('order/product', data);
}
/**
* 订单评价
* @param object data
*
*/
export function orderComment(data) {
return request.post('order/comment', data);
}
/**
* 订单支付
* @param object data
*/
export function orderPay(data) {
return request.post('order/pay', data);
}
/**
* 订单统计数据
*/
export function orderData() {
return request.get('order/data')
}
/**
* 订单取消
* @param string id
*
*/
export function orderCancel(id) {
return request.post('order/cancel', {
id: id
}, {}, 1);
}
/**
* 删除已完成订单
* @param string uni
*
*/
export function orderDel(uni) {
return request.post('order/del', {
id: uni
}, {}, 1);
}
/**
* 订单详情
* @param string uni
*/
export function getOrderDetail(uni) {
return request.get('order/detail/' + uni);
}
/**
* 再次下单
* @param string uni
*
*/
export function orderAgain(uni) {
return request.post('order/again', {
orderNo: uni
});
}
/**
* 订单收货
* @param string uni
*
*/
export function orderTake(uni) {
return request.post('order/take', {
id: uni
}, {}, 1);
}
/**
* 订单查询物流信息
* @returns {*}
*/
export function express(uni) {
return request.get("order/express/" + uni);
}
/**
* 获取退款理由
*
*/
export function ordeRefundReason() {
return request.get('order/refund/reason');
}
/**
* 订单退款审核
* @param object data
*/
export function orderRefundVerify(data) {
return request.post('order/refund', data);
}
/**
* 订单确认获取订单详细信息
* @param string cartId
*/
export function orderConfirm(cartId, isNew, addAgain,secKill,combination,bargain) {
return request.post('order/confirm', {
cartIds: cartId,
isNew: isNew,
addAgain: addAgain,
secKill: secKill,
combination:combination,
bargain:bargain
});
}
/**
* 获取当前金额能使用的优惠券
* @param string price
*
*/
export function getCouponsOrderPrice(preOrderNo) {
return request.get(`coupons/order/${preOrderNo}`)
}
/**
* 订单创建
* @param string key
* @param object data
*
*/
export function orderCreate(data) {
return request.post('order/create', data);
}
/**
* 计算订单金额
* @param key
* @param data
* @returns {*}
*/
export function postOrderComputed(data) {
return request.post("order/computed/price", data);
}
/**
* 微信订单支付
* @param object data
*/
export function wechatOrderPay(data) {
return request.post('pay/payment', data);
}
/**
* 微信查询支付结果
* @param object data
*/
export function wechatQueryPayResult(data) {
return request.get('pay/queryPayResult?orderNo=' + data);
}
/**
* 申请退款商品详情
* @param object data
*/
export function applyRefund(orderId) {
return request.get(`order/apply/refund/${orderId}`);
}
/**
* 预下单
* @param object data
*/
export function preOrderApi(data) {
return request.post(`order/pre/order`, data);
}
/**
* 加载预下单
* @param object preOrderNo
*/
export function loadPreOrderApi(preOrderNo) {
return request.get(`order/load/pre/${preOrderNo}`);
}
+8
View File
@@ -0,0 +1,8 @@
import request from "@/utils/request.js";
// 获得指定应用的开启的支付渠道编码列表
export function getEnableChannelCodeList(appId) {
return request.get("app-api/pay/channel/get-enable-code-list", {
appId
});
}
+11
View File
@@ -0,0 +1,11 @@
import request from "@/utils/request.js";
export function getOrder(id) {
return request.get("app-api/pay/order/get", {
id
});
}
export function submitOrder(data) {
return request.post("app-api/pay/order/submit", data);
}
+21
View File
@@ -0,0 +1,21 @@
import request from "@/utils/request.js";
// 获取钱包
export function getPayWallet() {
return request.get("app-api/pay/wallet/get");
}
// 获得钱包流水分页
export function getWalletTransactionPage(data) {
return request.get("app-api/pay/wallet-transaction/page", data);
}
// 获得钱包充值套餐列表
export function getWalletRechargePackageList() {
return request.get("app-api/pay/wallet-recharge-package/list");
}
// 创建钱包充值记录(发起充值)
export function createWalletRecharge(data) {
return request.post("app-api/pay/wallet-recharge/create", data);
}
+8
View File
@@ -0,0 +1,8 @@
import request from "@/utils/request.js";
// 查询分类列表
export function getCategoryList() {
return request.get('app-api/product/category/list', {}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+27
View File
@@ -0,0 +1,27 @@
import request from "@/utils/request.js";
// 获得商品的评价统计
export function getCommentStatistics(spuId) {
return request.get('app-api/product/comment/statistics', {
spuId
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得最近的 n 条商品评价
export function getCommentList(spuId, count) {
return request.get('app-api/product/comment/list', {
spuId,
count
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得商品评价分页
export function getCommentPage(data) {
return request.get('app-api/product/comment/page', data, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+46
View File
@@ -0,0 +1,46 @@
import request from "@/utils/request.js";
// 检查是否收藏过商品
export function isFavoriteExists(spuId) {
return request.get('app-api/product/favorite/exits', {
spuId
});
}
// 获得商品收藏数量
export function getFavoriteCount() {
return request.get('app-api/product/favorite/get-count');
}
// 添加商品收藏
export function createFavorite(spuId) {
return request.post('app-api/product/favorite/create', {
spuId
});
}
// 添加多个商品收藏
export function createFavoriteList(spuIds) {
return request.post('app-api/product/favorite/create-list', {
spuIds
});
}
// 取消商品收藏
export function deleteFavorite(spuId) {
return request.delete('app-api/product/favorite/delete', {
spuId
});
}
// 获得商品收藏分页
export function getFavoritePage(data) {
return request.get('app-api/product/favorite/page', data);
}
// 取消多个商品收藏
export function deleteFavoriteList(spuIds) {
return request.delete('app-api/product/favorite/delete-list', {
spuIds
});
}
+24
View File
@@ -0,0 +1,24 @@
import request from "@/utils/request.js";
// 获得商品 SPU 列表
export function getSpuList(recommendType) {
return request.get('app-api/product/spu/list', {
recommendType
});
}
// 获得商品 SPU 分页
export function getSpuPage(data) {
return request.get('app-api/product/spu/page', data, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 查询商品
export function getSpuDetail(id) {
return request.get('app-api/product/spu/get-detail', {
id
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+19
View File
@@ -0,0 +1,19 @@
import request from "@/utils/request.js";
// 获得单个商品,近期参与的每个活动
export function getActivityListBySpuId(spuId) {
return request.get("app-api/promotion/activity/list-by-spu-id", {
spuId
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得多个商品,近期参与的每个活动
export function getActivityListBySpuIds(spuIds) {
return request.get("app-api/promotion/activity/list-by-spu-ids", {
spuIds
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+38
View File
@@ -0,0 +1,38 @@
import request from "@/utils/request.js";
// 获得文章分类列表
export function getArticleCategoryList() {
return request.get("app-api/promotion/article-category/list", {}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得文章列表
export function getArticleList(data) {
return request.get("app-api/promotion/article/list", data, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得文章分页
export function getArticlePage(data) {
return request.get("app-api/promotion/article/page", data, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得文章
export function getArticle(id) {
return request.get("app-api/promotion/article/get", {
id
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 增加文章浏览量
export function addArticleBrowseCount(id) {
return request.put("app-api/promotion/article/add-browse-count?id=" + id, {}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+7
View File
@@ -0,0 +1,7 @@
import request from "@/utils/request.js";
export function getBannerList(position) {
return request.get("app-api/promotion/banner/list", {
position
});
}
+75
View File
@@ -0,0 +1,75 @@
import request from "@/utils/request.js";
// 获得砍价活动列表
export function getBargainActivityList(count) {
return request.get("app-api/promotion/bargain-activity/list", {
count
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得砍价活动详情
export function getBargainActivityDetail(id) {
return request.get("app-api/promotion/bargain-activity/get-detail", {
id
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得砍价活动分页
export function getBargainActivityPage(count) {
return request.get("app-api/promotion/bargain-activity/page", {
count
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得砍价记录的概要信息
export function getBargainRecordSummary() {
return request.get("app-api/promotion/bargain-record/get-summary", {}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得砍价记录的分页
export function getBargainRecordPage(data) {
return request.get("app-api/promotion/bargain-record/page", data, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得砍价活动详情
export function getBargainRecordDetail(id, activityId) {
return request.get("app-api/promotion/bargain-record/get-detail", {
id: id > 0 ? id : undefined,
activityId: activityId > 0 ? activityId : undefined
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 创建砍价记录(参与拼团活动)
export function createBargainRecord(activityId) {
return request.post("app-api/promotion/bargain-record/create", {
activityId
});
}
// 创建砍价助力(给拼团记录砍一刀)
export function createBargainHelp(recordId) {
return request.post("app-api/promotion/bargain-help/create", {
recordId: recordId
});
}
// 获得砍价助力列表
export function getBargainHelpList(recordId) {
return request.get("app-api/promotion/bargain-help/list", {
recordId: recordId
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+53
View File
@@ -0,0 +1,53 @@
import request from "@/utils/request.js";
// 获得拼团活动列表
export function getCombinationActivityList(count) {
return request.get("app-api/promotion/combination-activity/list", {
count
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得拼团活动分页
export function getCombinationActivityPage(data) {
return request.get("app-api/promotion/combination-activity/page", data, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得拼团活动明细
export function getCombinationActivity(id) {
return request.get("app-api/promotion/combination-activity/get-detail", {
id
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得最近 n 条拼团记录(团长发起的)
export function getHeadCombinationRecordList(activityId, status, count) {
return request.get("app-api/promotion/combination-record/get-head-list", {
activityId,
status,
count
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得拼团记录明细
export function getCombinationRecordDetail(id) {
return request.get("app-api/promotion/combination-record/get-detail", {
id
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得拼团记录的概要信息
export function getCombinationRecordSummary() {
return request.get("app-api/promotion/combination-record/get-summary", {}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+37
View File
@@ -0,0 +1,37 @@
import request from "@/utils/request.js";
// 领取优惠券
export function takeCoupon(templateId) {
return request.post("app-api/promotion/coupon/take", {
templateId
});
}
// 获得匹配指定商品的优惠劵列表
export function getMatchCouponList(data) {
return request.get("app-api/promotion/coupon/match-list", data);
}
// 获得用户优惠劵列表
export function getCouponPage(data) {
return request.get("app-api/promotion/coupon/page", data);
}
// 获得优惠劵模板分页
export function getCouponTemplatePage(data) {
return request.get("app-api/promotion/coupon-template/page", data, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得优惠劵模板列表
export function getCouponTemplateList(data) {
return request.get("app-api/promotion/coupon-template/list", data, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得未使用的优惠劵数量
export function getUnusedCouponCount() {
return request.get("app-api/promotion/coupon/get-unused-count");
}
+9
View File
@@ -0,0 +1,9 @@
import request from "@/utils/request.js";
export function getDecorateComponentListByPage(page) {
return request.get("app-api/promotion/decorate/list", {
page
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+31
View File
@@ -0,0 +1,31 @@
import request from "@/utils/request.js";
// 获得秒杀时间段列表
export function getSeckillConfigList() {
return request.get("app-api/promotion/seckill-config/list", {}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得当前秒杀活动
export function getNowSeckillActivity() {
return request.get("app-api/promotion/seckill-activity/get-now", {}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得秒杀活动分页
export function getSeckillActivityPage(data) {
return request.get("app-api/promotion/seckill-activity/page", data, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
// 获得秒杀活动明细
export function getSeckillActivity(id) {
return request.get("app-api/promotion/seckill-activity/get-detail", {
id
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+116
View File
@@ -0,0 +1,116 @@
import request from "@/utils/request.js";
import wechat from "@/libs/wechat.js";
import {
toLogin,
checkLogin
} from '../libs/login';
/**
* 获取微信公众号js配置
* @returns {*}
*/
export function getWechatConfig() {
return request.get("wechat/config",{ url: encodeURIComponent(wechat.signLink()) },{ noAuth: true });
}
/**
* 获取微信sdk配置
* @returns {*}
*/
export function wechatAuth(code, spread) {
var reg=/^[0-9]+.?[0-9]*$/; //判断字符串是否为数字 ,判断正整数用/^[1-9]+[0-9]*]*$/
spread = reg.test(spread) ? spread : 0;
return request.get(
"wechat/authorize/login?code=" + code + "&spread_spid=" + spread, {},
{ noAuth: true }
);
}
/**
* 获取登录授权login
*
*/
export function getLogo()
{
// wechat/get_logo
return request.get('wechat/getLogo', {}, { noAuth : true});
}
/**
* 小程序用户登录
* @param data object 小程序用户登录信息
*/
export function login(code,data) {
return request.post("wechat/authorize/program/login?code="+code, data, { noAuth : true });
}
/**
* 分享
* @returns {*}
*/
export function getShare() {
return request.get("share", {}, { noAuth: true });
}
/**
* 获取关注海报
* @returns {*}
*/
export function follow() {
return request.get("wechat/follow", {}, { noAuth: true });
}
/**
* 获取图片base64
* @retins {*}
* */
export function imageBase64(image) {
return request.post("qrcode/base64",image,{ noAuth: true },1);
}
/**
* 自动复制口令功能
* @returns {*}
*/
export function copyWords() {
return request.get("copy_words", {}, { noAuth: true });
}
/**
* 首页 获取客服地址
* @returns {*}
*/
export function kefuConfig() {
return request.get("config", {}, { noAuth: true });
}
/**
* 微信(公众号,小程序)绑定手机号
* @param {Object} data
*/
export function getUserPhone(data){
return request.post('wechat/register/binding/phone',data,{noAuth : true});
}
/**
* APP微信登录
* @param {Object} data
*/
export function appAuth(data) {
return request.post("wechat/authorize/app/login", data, { noAuth : true });
}
/**
* 苹果登录
* @param {Object} data
*/
export function appleLogin(data) {
return request.post("ios/login", data, { noAuth : true });
}
/**
* 苹果绑定手机号
* @param {Object} data
*/
export function iosBinding(data) {
return request.post("ios/binding/phone", data, { noAuth : true });
}
+191
View File
@@ -0,0 +1,191 @@
import request from "@/utils/request.js";
/**
* 获取产品详情
* @param int id
*
*/
export function getProductDetail(id, type) {
return request.get('product/detail/' + id + '?type=' + type, {}, {
noAuth: true
});
}
/**
* 产品分享二维码 推广员
* @param int id
*/
// #ifndef MP
export function getProductCode(id) {
return request.get('product/code/' + id, {});
}
// #endif
// #ifdef MP
export function getProductCode(id) {
return request.get('product/code/' + id, {
user_type: 'routine'
});
}
// #endif
/**
* 添加收藏
* @param int id
* @param string category product=普通产品,product_seckill=秒杀产品
*/
export function collectAdd(id, category) {
return request.post('collect/add', {
id: id,
'category': category === undefined ? 'product' : category
});
}
/**
* 取消收藏产品
* @param int id
*/
export function collectDel(proId) {
return request.post(`collect/cancel/${proId}`);
}
/**
* 删除收藏产品
* @param string id
*/
export function collectDelete(ids) {
return request.post(`collect/delete`,ids);
}
/**
* 购车添加
*
*/
export function postCartAdd(data) {
return request.post('cart/save', data, {});
}
/**
* 获取分类列表
*
*/
export function getCategoryList() {
return request.get('category', {}, {
noAuth: true
});
}
/**
* 获取产品列表
* @param object data
*/
export function getProductslist(data) {
return request.get('products', data, {
noAuth: true
});
}
/**
* 获取推荐产品
*
*/
export function getProductHot(page, limit) {
return request.get("product/hot", {
page: page === undefined ? 1 : page,
limit: limit === undefined ? 4 : limit
}, {
noAuth: true
});
}
/**
* 批量收藏
*
* @param object id 产品编号 join(',') 切割成字符串
* @param string category
*/
export function collectAll(id, category) {
return request.post('collect/all', {
id: id,
category: category === undefined ? 'product' : category
});
}
/**
* 首页产品的轮播图和产品信息
* @param int type
*
*/
export function getGroomList(type, data) {
return request.get('index/product/' + type, data, {
noAuth: true
});
}
/**
* 获取收藏列表
* @param object data
*/
export function getCollectUserList(data) {
return request.get('collect/user', data)
}
/**
* 获取产品评论
* @param int id
* @param object data
*
*/
export function getReplyList(id, data) {
return request.get('reply/list/' + id, data,{
noAuth: true
})
}
/**
* 产品评价数量和好评度
* @param int id
*/
export function getReplyConfig(id) {
return request.get('reply/config/' + id,{},{
noAuth: true
});
}
/**
* 获取搜索关键字获取
*
*/
export function getSearchKeyword() {
return request.get('search/keyword', {}, {
noAuth: true
});
}
/**
* 门店列表
* @returns {*}
*/
export function storeListApi(data) {
return request.post("store/list", data, {}, 1);
}
/**
* 优品推荐
* @param object data
*/
export function getProductGood() {
return request.get('product/good');
}
/**
* 详情页产品评论
* @param int id
* @param object data
*
*/
export function getReplyProduct(id) {
return request.get('reply/product/' + id, {
noAuth: true
})
}
+8
View File
@@ -0,0 +1,8 @@
import request from "@/utils/request.js";
// 获得地区树
export function getAreaTree() {
return request.get("app-api/system/area/tree", {}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+6
View File
@@ -0,0 +1,6 @@
import request from "@/utils/request.js";
// 根据字典类型查询字典数据信息
export function getDicts(dictType) {
return request.get('app-api/system/dict-data/type?type=' + dictType);
}
+27
View File
@@ -0,0 +1,27 @@
import request from "@/utils/request.js";
export function getAfterSale(id) {
return request.get("app-api/trade/after-sale/get", {
id
});
}
export function getApplyingAfterSaleCount() {
return request.get("app-api/trade/after-sale/get-applying-count");
}
export function getAfterSalePage(data) {
return request.get("app-api/trade/after-sale/page", data);
}
export function createAfterSale(data) {
return request.post("app-api/trade/after-sale/create", data);
}
export function cancelAfterSale(id) {
return request.delete("app-api/trade/after-sale/cancel?id=" + id);
}
export function deliveryAfterSale(data) {
return request.put("app-api/trade/after-sale/delivery", data);
}
+62
View File
@@ -0,0 +1,62 @@
import request from "@/utils/request.js";
// 获得个人分销信息
export function getBrokerageUser() {
return request.get('app-api/trade/brokerage-user/get');
}
// 获得个人分销信息
export function bindBrokerageUser(bindUserId) {
return request.put('app-api/trade/brokerage-user/bind', {
bindUserId
});
}
// 获得个人分销统计
export function getBrokerageUserSummary() {
return request.get('app-api/trade/brokerage-user/get-summary');
}
// 获得下级分销统计分页
export function getBrokerageUserChildSummaryPage(data) {
return request.get('app-api/trade/brokerage-user/child-summary-page', data);
}
// 获得分销用户排行分页(基于用户量)
export function getBrokerageUserRankPageByUserCount(data) {
return request.get('app-api/trade/brokerage-user/rank-page-by-user-count', data);
}
// 获得分销用户排行(基于佣金)
export function getBrokerageUserRankByPrice(data) {
return request.get('app-api/trade/brokerage-user/get-rank-by-price', data);
}
// 获得分销用户排行分页(基于佣金)
export function getBrokerageUserRankPageByPrice(data) {
return request.get('app-api/trade/brokerage-user/rank-page-by-price', data);
}
// 获得分销提现分页记录
export function getBrokerageWithdrawPage(data) {
return request.get('app-api/trade/brokerage-withdraw/page', data);
}
// 创建分销提现
export function createBrokerageWithdraw(data) {
return request.post('app-api/trade/brokerage-withdraw/create', data);
}
// 获得分销记录分页
export function getBrokerageRecordPage(data) {
return request.get('app-api/trade/brokerage-record/page', data);
}
// 获得商品的分销金额
export function getProductBrokeragePrice(spuId) {
return request.get('app-api/trade/brokerage-record/get-product-brokerage-price', {
spuId
}, {
noAuth: true // TODO 芋艿:后续要做调整
});
}
+33
View File
@@ -0,0 +1,33 @@
import request from "@/utils/request.js";
export function addCart(data) {
return request.post("app-api/trade/cart/add", data);
}
export function updateCartCount(data) {
return request.put("app-api/trade/cart/update-count", data);
}
export function updateCartSelected(data) {
return request.put("app-api/trade/cart/update-selected", data);
}
export function resetCart(data) {
return request.put("app-api/trade/cart/reset", data);
}
export function getCartCount() {
return request.get("app-api/trade/cart/get-count");
}
export function getCartCountMap() {
return request.get("app-api/trade/cart/get-count-map");
}
export function getCartList() {
return request.get("app-api/trade/cart/list");
}
export function deleteCart(ids) {
return request.delete("app-api/trade/cart/delete?ids=" + ids.join(','));
}
+6
View File
@@ -0,0 +1,6 @@
import request from "@/utils/request.js";
// 获得交易配置
export function getTradeConfig() {
return request.get("app-api/trade/config/get");
}
+23
View File
@@ -0,0 +1,23 @@
import request from "@/utils/request.js";
// 获得配送配置
export function getDeliveryConfig() {
return request.get("app-api/trade/delivery/config/get", {});
}
// 获得自提门店列表
export function getDeliveryPickUpStoreList(data) {
return request.get("app-api/trade/delivery/pick-up-store/list", data);
}
// 获得自提门店
export function getDeliveryPickUpStore(id) {
return request.get("app-api/trade/delivery/pick-up-store/get", {
id
});
}
// 获得快递公司列表
export function getDeliveryExpressList() {
return request.get("app-api/trade/delivery/express/list");
}
+61
View File
@@ -0,0 +1,61 @@
import request from "@/utils/request.js";
export function settlementOrder(data) {
const data2 = {
...data,
}
// 解决 SpringMVC 接受 List<Item> 参数的问题
delete data2.items
for (let i = 0; i < data.items.length; i++) {
data2['items[' + i + '].skuId'] = data.items[i].skuId;
data2['items[' + i + '].count'] = data.items[i].count;
data2['items[' + i + '].cartId'] = data.items[i].cartId;
}
return request.get("app-api/trade/order/settlement", data2);
}
export function createOrder(data) {
return request.post("app-api/trade/order/create", data);
}
export function getOrderDetail(id) {
return request.get("app-api/trade/order/get-detail", {
id
});
}
export function getOrderCount() {
return request.get("app-api/trade/order/get-count");
}
export function getOrderPage(data) {
return request.get("app-api/trade/order/page", data);
}
export function receiveOrder(id) {
return request.put("app-api/trade/order/receive?id=" + id, {});
}
export function cancelOrder(id) {
return request.delete("app-api/trade/order/cancel?id=" + id, {});
}
export function deleteOrder(id) {
return request.delete("app-api/trade/order/delete?id=" + id, {});
}
export function getOrderItem(id) {
return request.get("app-api/trade/order/item/get", {
id
});
}
export function createOrderItemComment(data) {
return request.post("app-api/trade/order/item/create-comment", data);
}
export function getOrderExpressTrackList(id) {
return request.get("app-api/trade/order/get-express-track-list", {
id
});
}
+396
View File
@@ -0,0 +1,396 @@
import request from "@/utils/request.js";
/**
* 获取用户信息
*/
export function getUserInfo(){
return request.get('user');
}
/**
* 设置用户分享
*/
export function userShare(){
return request.post('user/share');
}
/**
* h5用户登录
* @param data object 用户账号密码
*/
export function loginH5(data) {
return request.post("login", data, { noAuth : true });
}
/**
* h5用户手机号登录
* @param data object 用户手机号 也只能
*/
export function loginMobile(data) {
return request.post("login/mobile", data, { noAuth : true });
}
/**
* 验证码key
*/
export function getCodeApi() {
return request.get("verify_code", {}, { noAuth: true });
}
/**
* h5用户发送验证码
* @param data object 用户手机号
*/
export function registerVerify(phone){
return request.post('sendCode', { phone: phone },{noAuth:true},1)
}
/**
* h5用户手机号注册
* @param data object 用户手机号 验证码 密码
*/
export function register(data) {
return request.post("register", data, { noAuth : true });
}
/**
* 用户手机号修改密码
* @param data object 用户手机号 验证码 密码
*/
export function registerReset(data) {
return request.post("register/reset", data, { noAuth: true });
}
/**
* 获取用户中心菜单
*
*/
export function getMenuList() {
return request.get("menu/user");
}
/*
* 签到用户信息
* */
export function postSignUser(sign) {
return request.post("user/sign/user", sign);
}
/**
* 获取签到配置
*
*/
export function getSignConfig(){
return request.get('user/sign/config')
}
/**
* 获取签到列表
* @param object data
*/
export function getSignList(data){
return request.get('user/sign/list',data);
}
/**
* 用户签到
*/
export function setSignIntegral(){
return request.get('user/sign/integral')
}
/**
* 签到列表(年月)
* @param object data
*
*/
export function getSignMonthList(data){
return request.get('user/sign/month',data)
}
/**
* 活动状态
*
*/
export function userActivity(){
return request.get('user/activity');
}
/*
* 余额明细(types|2=全部,1=支出,2=收入)
* */
export function getCommissionInfo(data) {
return request.get("spread/commission/detail", data);
}
/*
* 提现记录 getCountApi
* */
export function getRecordApi(q) {
return request.get("extract/record", q);
}
/*
* 提现总金额
* */
export function getCountApi() {
return request.get("extract/totalMoney");
}
/*
* 积分记录
* */
export function getIntegralList(q) {
return request.get("integral/list", q);
}
/**
* 获取分销海报图片
*
*/
export function spreadBanner(data){
return request.get('user/spread/banner',data);
}
/**
*
* 获取推广用户一级和二级
* @param object data
*/
export function spreadPeople(data){
return request.get('spread/people',data);
}
/**
*
* 推广佣金/提现总和
* @param int type
*/
export function spreadCount(type){
return request.get('spread/count/'+type);
}
/*
* 推广数据 当前佣金 提现总金额
* */
export function getSpreadInfo() {
return request.get("commission");
}
/**
*
* 推广订单
* @param object data
*/
export function spreadOrder(data){
return request.get('spread/order',data);
}
/*
* 获取推广人排行
* */
export function getRankList(q) {
return request.get("rank", q);
}
/*
* 获取佣金排名
* */
export function getBrokerageRank(q) {
return request.get("brokerage_rank", q);
}
/**
* 提现申请
* @param object data
*/
export function extractCash(data){
return request.post('extract/cash',data)
}
/**
* 会员等级列表
*
*/
export function userLevelGrade(){
return request.get('user/level/grade');
}
/**
* 获取某个等级任务
* @param int id 任务id
*/
export function userLevelTask(id){
return request.get('user/level/task/'+id);
}
/**
* 检查用户是否可以成为会员
*
*/
export function userLevelDetection(){
return request.get('user/level/detection');
}
/**
* 获取单个地址
* @param int id
*/
export function getAddressDetail(id){
return request.get('address/detail/'+id);
}
/**
* 修改用户信息
* @param object
*/
export function userEdit(data){
return request.post('user/edit',data);
}
/*
* 退出登录
* */
export function getLogout() {
return request.get("logout");
}
/**
* 小程序充值
*
*/
export function rechargeRoutine(data){
return request.post('recharge/routine',data)
}
/*
* 公众号充值
* */
export function rechargeWechat(data) {
return request.post("recharge/wechat", data);
}
/*
* app微信充值
* */
export function appWechat(data) {
return request.post("recharge/wechat/app", data);
}
/*
* 余额充值
* */
export function transferIn(data) {
return request.post("recharge/transferIn", data,{},1);
}
/**
* 获取默认地址
*
*/
export function getAddressDefault(){
return request.get('address/default');
}
/**
* 充值金额选择
*/
export function getRechargeApi() {
return request.get("recharge/index");
}
/**
* 登录记录
*/
export function setVisit(data)
{
return request.post('user/set_visit', {...data}, { noAuth:true});
}
/**
* 客服列表
*/
export function serviceList() {
return request.get("user/service/lst");
}
/**
* 客服详情
*/
export function getChatRecord(to_uid, data) {
return request.get("user/service/record/" + to_uid, data);
}
/**
* 静默绑定推广人
* @param {Object} puid
*/
export function spread(puid)
{
return request.get("user/bindSpread?spreadPid="+ puid);
}
/**
* 当前用户在佣金排行第几名
*
*/
export function brokerageRankNumber(data)
{
return request.get("user/brokerageRankNumber",data);
}
/**
* 会员等级经验值;
*
*/
export function getlevelInfo()
{
return request.get("user/level/grade");
}
/**
* 经验值明细;
*
*/
export function getlevelExpList(data)
{
return request.get("user/expList",data);
}
/**
* 经验值明细;
*
*/
export function getuserDalance()
{
return request.get("user/balance");
}
/**
* 账单记录;
*
*/
export function getBillList(data)
{
return request.get("recharge/bill/record",data);
}
/*
* 积分中心详情
* */
export function postIntegralUser() {
return request.get("integral/user");
}
/*
* 立即提现 冻结期、冻结佣金、可提现佣金、最低可提现金额
* */
export function extractUser() {
return request.get("extract/user");
}
/*
* 推广人统计页 推广人数(一级+二级)、一级人数、二级人数
* */
export function spreadPeoCount() {
return request.get("spread/people/count");
}
+145
View File
@@ -0,0 +1,145 @@
<template>
<view>
<view class='Popup' v-if='isShowAuth'>
<image :src='logoUrl'></image>
<view class='title'>授权提醒</view>
<view class='tip'>请授权头像等信息,以便为您提供更好的服务</view>
<view class='bottom flex'>
<view class='item' @click='close'>随便逛逛</view>
<!-- #ifdef APP-PLUS -->
<button class='item grant' @click="setUserInfo">去授权</button>
<!-- #endif -->
<!-- #ifdef MP -->
<button class='item grant' type="primary" open-type="getUserInfo" lang="zh_CN" @getuserinfo="setUserInfo">去授权</button>
<!-- #endif -->
</view>
</view>
<view class='mask' v-if='isShowAuth' @click='close'></view>
</view>
</template>
<script>
const app = getApp();
import Cache from '../utils/cache';
import { getLogo } from '../api/public';
import { LOGO_URL } from '../config/cache';
import { mapGetters } from 'vuex';
import Routine from '../libs/routine';
export default {
name:'Authorize',
props:{
isAuto:{
type:Boolean,
default:true
},
isGoIndex:{
type:Boolean,
default:true
},
isShowAuth:{
type:Boolean,
default:false
}
},
data(){
return {
logoUrl:''
}
},
computed:mapGetters(['isLogin','userInfo']),
watch:{
isLogin(n){
n === true && this.$emit('onLoadFun',this.userInfo);
}
},
created() {
this.getLogoUrl();
this.setAuthStatus();
},
methods:{
setAuthStatus(){
Routine.authorize().then(res=>{
if(res.islogin === false)
this.setUserInfo();
else
this.$emit('onLoadFun',this.userInfo);
}).catch(res=>{
if (this.isAuto)
this.$emit('authColse',true);
})
},
getUserInfo(code){
Routine.getUserInfo().then(res=>{
let userInfo = res.userInfo
userInfo.code = code;
userInfo.spread_spid = app.globalData.spid;//获取推广人ID
userInfo.spread_code = app.globalData.code;//获取推广人分享二维码ID
userInfo.avatar = userInfo.userInfo.avatarUrl;
userInfo.city = userInfo.userInfo.city;
userInfo.country = userInfo.userInfo.country;
userInfo.nickName = userInfo.userInfo.nickName;
userInfo.province = userInfo.userInfo.province;
userInfo.sex = userInfo.userInfo.gender;
Routine.authUserInfo(code,userInfo).then(res=>{
uni.hideLoading();
this.$emit('authColse',false);
this.$emit('onLoadFun',this.userInfo);
}).catch(res=>{
uni.hideLoading();
uni.showToast({
title:res.message,
icon:'none',
duration:2000
});
})
}).catch(res =>{
uni.hideLoading();
})
},
setUserInfo(){
uni.showLoading({title:'正在登录中'});
Routine.getCode().then(code=>{
this.getUserInfo(code);
}).catch(res=>{
uni.hideLoading();
})
},
getLogoUrl(){
let that = this;
if (Cache.has(LOGO_URL)) {
this.logoUrl = Cache.get(LOGO_URL);
return;
}
getLogo().then(res=>{
that.logoUrl = res.data.logoUrl
Cache.set(LOGO_URL,that.logoUrl);
})
},
close(){
let pages = getCurrentPages(), currPage = pages[pages.length - 1];
if(this.isGoIndex){
uni.switchTab({url:'/pages/index/index'});
} else {
this.$emit('authColse',false);
}
// if (currPage && currPage.isShowAuth != undefined){
// currPage.isShowAuth = true;
// }
},
}
}
</script>
<style scoped lang='scss'>
.Popup{width:500rpx;background-color:#fff;position:fixed;top:50%;left:50%;margin-left:-250rpx;transform:translateY(-50%);z-index:320;}
.Popup image{width:150rpx;height:150rpx;margin:-67rpx auto 0 auto;display:block;border: 8rpx solid #fff;border-radius: 50%}
.Popup .title{font-size:28rpx;color:#000;text-align:center;margin-top: 30rpx}
.Popup .tip{font-size:22rpx;color:#555;padding:0 24rpx;margin-top:25rpx;}
.Popup .bottom .item{width:50%;height:80rpx;background-color:#eeeeee;text-align:center;line-height:80rpx;font-size:24rpx;color:#666;margin-top:54rpx;}
.Popup .bottom .item.on{width: 100%}
.flex{display:flex;}
.Popup .bottom .item.grant{font-size:28rpx;color:#fff;font-weight:bold;background-color:$theme-color;border-radius:0;padding:0;}
.mask{position:fixed;top:0;right:0;left:0;bottom:0;background-color:rgba(0,0,0,0.65);z-index:310;}
</style>
+57
View File
@@ -0,0 +1,57 @@
<template>
<view>
<view class="Loads acea-row row-center-wrapper" v-if="loading && !loaded" style="margin-top: .2rem;">
<view v-if="loading">
<view class="iconfont icon-jiazai loading acea-row row-center-wrapper"></view>
正在加载中
</view>
<view v-else>
上拉加载更多
</view>
</view>
</view>
</template>
<script>
export default {
name: "Loading",
props: {
loaded: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: false
}
}
};
</script>
<style>
.Loads {
height: 80upx;
font-size: 25upx;
color: #000;
}
.Loads .iconfont {
font-size: 30upx;
margin-right: 10upx;
height: 32upx;
line-height: 32upx;
}
/*加载动画*/
@keyframes load {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.loadingpic {
animation: load 3s linear 1s infinite;
}
.loading {
animation: load linear 1s infinite;
}
</style>
+189
View File
@@ -0,0 +1,189 @@
<template>
<view>
<view class="address-window" :class="address.address ? 'on' : ''">
<view class='title'>选择地址<text class='iconfont icon-guanbi' @tap='close'></text></view>
<view class='list'>
<view class='item acea-row row-between-wrapper' :class='active === index?"font-color":""'
v-for="(item,index) in addressList" @tap='tapAddress(index,item.id)' :key='index'>
<text class='iconfont icon-ditu' :class='active===index?"font-color":""' />
<view class='address'>
<view class='name' :class='active==index?"font-color":""'>
{{ item.name }}
<text class='phone'>{{ item.mobile }}</text>
</view>
<view class='line1'>{{ item.areaName }} {{ item.detailAddress }}</view>
</view>
<text class='iconfont icon-complete' :class='active === index?"font-color":""' />
</view>
</view>
<!-- 无地址 -->
<view class='pictrue' v-if="!is_loading && !addressList.length">
<image src='../../static/images/noAddress.png'></image>
</view>
<view class='addressBnt bg-color' @tap='goAddressPages'>选择其地址</view>
</view>
<view class='mask' catchtouchmove="true" :hidden='!address.address' @tap='close' />
</view>
</template>
<script>
import * as AddressApi from '@/api/member/address.js';
export default {
props: {
pagesUrl: {
type: String,
default: '',
},
address: {
type: Object,
default: function() {
return {
address: true, // 是否打开
addressId: 0,
};
}
},
isLog: {
type: Boolean,
default: false,
}
},
data() {
return {
active: 0, // 激活的 addressList 下标
is_loading: true,
addressList: []
};
},
methods: {
/**
* 选中某个地址
*/
tapAddress: function(e, addressid) {
this.active = e;
for (let i = 0; i < this.addressList.length; i++) {
if (this.addressList[i].id === addressid) {
this.$emit('OnChangeAddress', this.addressList[i]);
break
}
}
},
close: function() {
this.$emit('changeClose');
},
goAddressPages: function() {
this.$emit('changeClose');
uni.navigateTo({
url: this.pagesUrl
});
},
getAddressList: function() {
AddressApi.getAddressList().then(res => {
const addressList = res.data;
this.$set(this, 'addressList', addressList);
this.is_loading = false;
// 处理默认选中项
if (!this.address.addressId) {
return;
}
let defaultAddress = {};
for (let i = 0; i < addressList.length; i++) {
if (addressList[i].id === this.address.addressId) {
this.active = i;
defaultAddress = this.addressList[i];
}
}
})
}
}
}
</script>
<style scoped lang="scss">
.address-window {
background-color: #fff;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
z-index: 101;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
}
.address-window.on {
transform: translate3d(0, 0, 0);
}
.address-window .title {
font-size: 32rpx;
font-weight: bold;
text-align: center;
height: 123rpx;
line-height: 123rpx;
position: relative;
}
.address-window .title .iconfont {
position: absolute;
right: 30rpx;
color: #8a8a8a;
font-size: 35rpx;
}
.address-window .list .item {
margin-left: 30rpx;
padding-right: 30rpx;
border-bottom: 1px solid #eee;
height: 129rpx;
font-size: 25rpx;
color: #333;
}
.address-window .list .item .iconfont {
font-size: 37rpx;
color: #2c2c2c;
}
.address-window .list .item .iconfont.icon-complete {
font-size: 30rpx;
color: #fff;
}
.address-window .list .item .address {
width: 560rpx;
}
.address-window .list .item .address .name {
font-size: 28rpx;
font-weight: bold;
color: #282828;
margin-bottom: 4rpx;
}
.address-window .list .item .address .name .phone {
margin-left: 18rpx;
}
.address-window .addressBnt {
font-size: 30rpx;
font-weight: bold;
color: #fff;
width: 690rpx;
height: 86rpx;
border-radius: 43rpx;
text-align: center;
line-height: 86rpx;
margin: 85rpx auto;
}
.address-window .pictrue {
width: 414rpx;
height: 336rpx;
margin: 0 auto;
}
.address-window .pictrue image {
width: 100%;
height: 100%;
}
</style>
@@ -1,20 +1,13 @@
<template>
<view class="time" :style="justifyLeft">
<text class="" v-if="tipText">{{ tipText }}</text>
<text class="styleAll p6" v-if="isDay === true"
:style="{background:bgColor.bgColor,color:bgColor.Color}">{{ day }}{{bgColor.isDay?'天':''}}</text>
<text class="timeTxt" v-if="dayText"
:style="{width:bgColor.timeTxtwidth,color:bgColor.bgColor}">{{ dayText }}</text>
<text class="styleAll" :class='isCol?"timeCol":""'
:style="{background:bgColor.bgColor,color:bgColor.Color,width:bgColor.width}">{{ hour }}</text>
<text class="timeTxt" v-if="hourText" :class='isCol?"whit":""'
:style="{width:bgColor.timeTxtwidth,color:bgColor.bgColor}">{{ hourText }}</text>
<text class="styleAll" :class='isCol?"timeCol":""'
:style="{background:bgColor.bgColor,color:bgColor.Color,width:bgColor.width}">{{ minute }}</text>
<text class="timeTxt" v-if="minuteText" :class='isCol?"whit":""'
:style="{width:bgColor.timeTxtwidth,color:bgColor.bgColor}">{{ minuteText }}</text>
<text class="styleAll" :class='isCol?"timeCol":""'
:style="{background:bgColor.bgColor,color:bgColor.Color,width:bgColor.width}">{{ second }}</text>
<text class="styleAll p6" v-if="isDay === true" :style="{background:bgColor.bgColor,color:bgColor.Color}">{{ day }}{{bgColor.isDay?'天':''}}</text>
<text class="timeTxt" v-if="dayText" :style="{width:bgColor.timeTxtwidth,color:bgColor.bgColor}">{{ dayText }}</text>
<text class="styleAll" :class='isCol?"timeCol":""' :style="{background:bgColor.bgColor,color:bgColor.Color,width:bgColor.width}">{{ hour }}</text>
<text class="timeTxt" v-if="hourText" :class='isCol?"whit":""' :style="{width:bgColor.timeTxtwidth,color:bgColor.bgColor}">{{ hourText }}</text>
<text class="styleAll" :class='isCol?"timeCol":""' :style="{background:bgColor.bgColor,color:bgColor.Color,width:bgColor.width}">{{ minute }}</text>
<text class="timeTxt" v-if="minuteText" :class='isCol?"whit":""' :style="{width:bgColor.timeTxtwidth,color:bgColor.bgColor}">{{ minuteText }}</text>
<text class="styleAll" :class='isCol?"timeCol":""' :style="{background:bgColor.bgColor,color:bgColor.Color,width:bgColor.width}">{{ second }}</text>
<text class="timeTxt" v-if="secondText">{{ secondText }}</text>
</view>
</template>
@@ -124,11 +117,10 @@
</script>
<style scoped>
.p6 {
.p6{
padding: 0 8rpx;
}
.styleAll {
.styleAll{
/* color: #fff; */
font-size: 24rpx;
height: 36rpx;
@@ -137,19 +129,16 @@
text-align: center;
/* padding: 0 6rpx; */
}
.timeTxt {
text-align: center;
/* width: 16rpx; */
height: 36rpx;
line-height: 36rpx;
display: inline-block;
.timeTxt{
text-align: center;
/* width: 16rpx; */
height: 36rpx;
line-height: 36rpx;
display: inline-block;
}
.whit {
.whit{
color: #fff !important;
}
.time {
display: flex;
justify-content: center;
@@ -170,4 +159,4 @@
font-size: 24rpx; */
color: #E93323;
}
</style>
</style>
+247
View File
@@ -0,0 +1,247 @@
<template>
<view>
<view class='coupon-list-window' :class='coupon.coupon === true?"on":""'>
<view v-if="!orderShow" class="nav acea-row row-around">
<view :class="['acea-row', 'row-middle', type === 1 ? 'on' : '']" @click="setType(1)">通用券</view>
<view :class="['acea-row', 'row-middle', type === 2 ? 'on' : '']" @click="setType(2)">商品券</view>
<view :class="['acea-row', 'row-middle', type === 3 ? 'on' : '']" @click="setType(3)">品类券</view>
</view>
<view class='coupon-list' :style="{'margin-top':!orderShow?'0':'50rpx'}">
<block v-if="coupon.list.length">
<view class='item acea-row row-center-wrapper' v-for="(item,index) in coupon.list"
@click="getCouponUser(index, item.id)" :key='index'>
<!-- 金额 -->
<view class='money acea-row row-column row-center-wrapper' :class='item.canTake ? "" : "moneyGray"'>
<view>¥
<text v-if="item.discountType === 1" class='num'>{{ fen2yuan(item.discountPrice) }}</text>
<text v-else class='num'>{{ (item.discountPercent / 10.0).toFixed(1) }} 折</text>
</view>
<view class="pic-num">满 {{ fen2yuan(item.usePrice) }} 元可用</view>
</view>
<view class='text'>
<!-- 类型 -->
<view class='condition line2'>
<span class='line-title' :class='item.isUse?"gray":""' v-if='type === 1'>通用</span>
<span class='line-title' :class='item.isUse?"gray":""'
v-else-if='type === 3'>品类</span>
<span class='line-title' :class='item.isUse?"gray":""' v-else>商品</span>
<span>{{item.name}}</span>
</view>
<!-- 领取类型 -->
<view class='data acea-row row-between-wrapper'>
<view v-if="item.validityType > 1">领取后 {{ item.fixedEndTerm }} 天内可用</view>
<view v-else>
{{ formatDate(item.validStartTime) + " - " + formatDate(item.validEndTime) }}
</view>
<view class='bnt bg-color' v-if="item.canTake">{{coupon.statusTile || '立即领取'}}</view>
<view class='bnt gray' v-else>{{item.use_title || '已领取'}}</view>
</view>
</view>
</view>
</block>
<!-- 无优惠券 -->
<view class='pictrue' v-else>
<image src='../../static/images/noCoupon.png'></image>
</view>
</view>
</view>
<view class='mask' catchtouchmove="true" :hidden='!coupon.coupon' @click='close'></view>
</view>
</template>
<script>
import * as Util from '@/utils/util.js';
import dayjs from "@/plugin/dayjs/dayjs.min.js";
import * as CouponApi from '@/api/promotion/coupon.js';
export default {
props: {
openType: {
type: Number, // 打开状态 0=领取优惠券, 1=使用优惠券
default: 0,
},
coupon: {
type: Object,
default: function() {
return {};
}
},
orderShow: {
type: String, // 下单页面使用优惠券组件不展示 tab 切换页
default: function() {
return '';
}
}
},
data() {
return {
type: 1 // 使用类型
};
},
methods: {
close: function() {
this.type = 1
this.$emit('ChangCouponsClose');
},
/**
* 选择优惠劵
*/
getCouponUser: function(index, id) {
// 领取优惠劵时,如果已经领取,则直接跳过
let list = this.coupon.list;
switch (this.openType) {
case 0: // 领取优惠券
if (!list[index].canTake) {
return;
}
CouponApi.takeCoupon(id).then(res => {
this.$util.Tips({
title: "领取成功"
});
this.$emit('ChangCoupons', list[index]);
})
break;
case 1: // 使用优惠劵
// TODO 芋艿:需要额外把不可用优惠劵的样式做了;
if (list[index].match === false) {
alert('该优惠劵无法使用,原因:' + list[index].description);
return;
}
this.$emit('ChangCoupons', index);
break;
}
},
setType: function(type) {
this.type = type;
this.$emit('tabCouponType', type);
},
fen2yuan(price) {
return Util.fen2yuan(price)
},
formatDate: function(date) {
return dayjs(date).format("YYYY-MM-DD");
}
}
}
</script>
<style scoped lang="scss">
.coupon-list-window {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background-color: #f5f5f5;
border-radius: 16rpx 16rpx 0 0;
z-index: 555;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
}
.coupon-list-window.on {
transform: translate3d(0, 0, 0);
}
.coupon-list-window .title {
height: 124rpx;
width: 100%;
text-align: center;
line-height: 124rpx;
font-size: 32rpx;
font-weight: bold;
position: relative;
}
.coupon-list-window .title .iconfont {
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
font-size: 35rpx;
color: #8a8a8a;
font-weight: normal;
}
.coupon-list-window .coupon-list {
margin: 0 0 30rpx 0;
height: 823rpx;
overflow: auto;
padding-top: 30rpx;
}
.coupon-list-window .pictrue {
width: 414rpx;
height: 336rpx;
margin: 208rpx auto;
}
.coupon-list-window .pictrue image {
width: 100%;
height: 100%;
}
.pic-num {
color: #fff;
font-size: 24rpx;
}
.line-title {
width: 90rpx;
padding: 0 10rpx;
box-sizing: border-box;
background: rgba(255, 247, 247, 1);
border: 1px solid rgba(232, 51, 35, 1);
opacity: 1;
border-radius: 20rpx;
font-size: 20rpx;
color: #E83323;
margin-right: 12rpx;
}
.line-title.gray {
border-color: #BBB;
color: #bbb;
background-color: #F5F5F5;
}
.nav {
// position: absolute;
// top: 0;
// left: 0;
width: 100%;
height: 96rpx;
border-bottom: 2rpx solid #F5F5F5;
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
background-color: #FFFFFF;
font-size: 30rpx;
color: #999999;
}
.nav .acea-row {
border-top: 5rpx solid transparent;
border-bottom: 5rpx solid transparent;
}
.nav .acea-row.on {
border-bottom-color: #E93323;
color: #282828;
}
.nav .acea-row:only-child {
border-bottom-color: transparent;
}
.occupy {
height: 106rpx;
}
.coupon-list .item {
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.06);
}
.coupon-list .item .money {
font-weight: normal;
}
</style>
+167
View File
@@ -0,0 +1,167 @@
<template>
<view>
<view class='coupon-window' :class='window==true?"on":""'>
<view class='couponWinList'>
<view class='item acea-row row-between-wrapper' v-for="(item,index) in couponList" :key="index">
<view class='money font-color'>¥<text class='num'>{{ item.money?Number(item.money):'' }}</text></view>
<view class='text'>
<view class='name'>购物买{{item.minPrice}}减{{item.money}}</view>
<view v-if="item.day>0">领取后{{item.day}}天内可用</view>
<view v-else>{{item.useStartTimeStr&&item.useEndTimeStr ? item.useStartTimeStr+'~'+item.useEndTimeStr : ''}}</view>
</view>
</view>
</view>
<view class='lid'>
<navigator hover-class='none' url='/pages/users/user_get_coupon/index' class='bnt font-color'>立即领取</navigator>
<view class='iconfont icon-guanbi3' @click="close"></view>
</view>
</view>
<view class='mask' catchtouchmove="true" :hidden="window==false"></view>
</view>
</template>
<script>
export default {
props: {
window: {
type: Boolean,
default: false,
},
couponList: {
type: Array,
default: function() {
return []
},
}
},
methods: {
close:function(){
this.$emit('onColse');
}
}
}
</script>
<style scoped lang="scss">
.mask{
z-index: 999;
}
.coupon-window {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnYAAAKJCAMAAAABTpQHAAADAFBMVEUAAADsY0H3UUrdOyD3UjL4UjruSzH8vRrkOSb5UUr5UEr/ihHzMxP+4qP1NBX5UEr3NxT3YD/ZJgr+7Xn5UUryMBH1MxL5U0r5NxT8xCT8OhX/6UH7ORb5UUr3U0b+ljj8Ohf7Ohf5UUv5ORLLHgX/6EL5Ukr5UUv9Oxb9jxD5OBb5UEr996/+96v4UEzDHwb5UUv5UUr5UUr/6UL/6kH/q0H69Kz9Ohb8xiD/njD+oh/5UUv8uiP8747+PRf+PBf/0H/4nSH9jxH89a35UUr+w4v1Xzb/u1j8uiL8sib5UUv/6kH+zVv/2pX5UEr8vSP/oAr9yUL8uCT38qf5oR/qLhr1gRX+0KT+57T3hhv6lh3/6kHnOyn/wWvpJAv9963wfRT+5q78xh72igztIwX5iBf8uB/+v3npMyP3TUX4UEnvPjLyRDrqNSbrNynxQjftOi32S0P1SkHzRjz0SD7rNif5UUvwQTXvPTDwQDTtOSv1SUDqNCTsOCrtPC7uPC/4Tkf0Rz3////yQznsOCnvT0X+PRj+PSb+PRr8tbP9Pyj93Nv1WVH1rar95OP/QBvwe3T62Nf+Oxf4X1n8ysj9fx3uRTr+9vX6RDL9NxX9sUL/9/b7oJ37QS34Rjj+Yyb7qiLtIwT5bmj+bSr/lQv6iIXrSDz+7u35sa72Vz/829r7sib3Rzz+Th790tH+dy34xML1gXz+v0X+Rhz8yxj7qqf5h4P+oUz7kEL9aDX8viT97ez+RCn8v739rTH+hRn6k5D+sE/+nj7+nif5e3f+ykj+kDH+NiP+VyHtJxT7jSX+LhT+igz+u1j+pzz7cjz9gC/8qin+xZDua2P6hUHylpH+wGf+uEP+WzH2ubbtW1L6e0D8yy71byX1MBH8vg7/3p3/0Xf+TSz0oZ33ZkH8iDP4OiL82SH+3oT0c23+z17/8a/+sG390kz/8cL+65XxiIL+p1360Qb9voP+tnj95Gz/5aj9yJrzZV3+rgT/15D93k7vWCnwaRr84gjxUTGJMH7QAAAAaHRSTlMABPoHISsNyhHx5sk/yZTaTxgYDHl6XjdryrBthrRR/sqjlzEiYVzP18+9kIVYRy2+qp83JslB4tLJyYVoGvfuyUDdbGb+/smvfmxRysnFxf7KnCr83G/+yYxWRv3Jq6WgzPKz67/b4QYS7fUAADl2SURBVHja7Jy9btpQGIaPwUbYQvwEgxECmpgIo/AjYCCDFRhgYmCJuqZLp14Al3DkAcmSN2exImYLCe6gUiMqpIitW7eOvYIuPbRV2qgJx8QYbHweBUWK8qOEh/d872cCIDwhlGCEeqE04OWK2GrmG0NJisViHIsYPcIiOPRhSRo28s2WWJH5QalQF5hECBAIVqASTL00kMVmQ4pxI9twManRFOVBqS4kKEAg/EuQFgoDuZWXuJGDcFK+JQ8KAh0E7uO6DQj7gaKFEi/mJXa0Z1gpL/IlgXZPAF73rgHBYRJIt1bDRrSNn9xeD9doIf0S4LAg6WpJQHCMsFCSmw6km00JWakpl4QwOAzJWq/tntw9LhL1gbhlvo2fv42f+8ydwDXEQX3v0deu+izqrvYyT4SEvjjc4/j2aOezNzzsUOzvL/moWu8K+IurnsP1iS7IeUzCbe/Ho1WPbjkBl5cLNHCaZLtXA76D6jn1UKOYUqVhK+LG/73HMbb4Sdb9ZhuVEkMBp0j2qm3MgUOdu3LdY5e2Ax2Kxhi3YU7DmPe/JxgnLUqLdc+R3GtXsQ96Op6OF0/A8UHVqu0dznF1HnOq7tIPvNf47/10FHwRLs/XQ2Cn1KrY0boYPctl0pGTY+y5u1oa0SUxhjNhvOlofLQDY+PzzXZsRVt7bsfE3cXeVbWKkykYz5YvstFcOuKivfYOqdVs7sgpYdC0HHJ4P15QFP9F2Bj9ZeqGn4FvKlxzIOxAgtq7Gla6s0tN75YvztbeAQ8SOgliZlsbuyNK4PPsBnXWb5bNG2O8wfpmvX/YiEA2z9tT77pavcLdZ7kO1ODCMLuna++8N99RdDEep/Gl6jWBxwyQcr4Eqce8vku0sXdaFEmnLVbThdlB3mUiYeAtgkw8ncnlIthH4LbVgu6jg9XXcM0+/Qrp3lk4WVIQaWdOVpOJMe+eZnMZj8Udsi6Ti2ZPs2kaP+ReWT62C5XYiICIVQpbNdxk9V0bYIl0kHbq6s1kMjF1DXmX8Vap+GXd2Wm5o3dOUyf4OTcJ8DB8IzAiPBJo8Iz1KlEFeCJdqC/N6Zdbw0DWQa17cQ68xNq66EW5YyygpnXO8IGHu1wWrIsk5p7drdSDAE8PRR2eIrJuPjdn32cPiyWyTtXTwEtQxXgqmr2cm8bK0CCE2TD+Mm315cBL9P1aIKyVjH4C99e1dJoULyFcGrfT208f700dQlW/AZ4iGMlEs2VlYRjTqTlH3kUBlpdmD4YfjggYhpuPW8rS3FyGEOr6x++3b1ZLfZ117711xAIQQWWio82N6WS1MjUIlYyVpvX//pyRydFqkZgsAHtkIdT06ezLwwLqGlS1uzjwGMFUuQuhPjeM1WxqQh120gALhQKPOGer3draJtOXUIcPD3NzrkNk4F0KeI7ztypcezd9+PTp2xIiUpSlSzfEOVtwFRuZF+lAzYTLpba27nMEeJD0V1WB2nJ1O/v+7dsKhTY8C1p5ev81RZyze9oy4JWk1sMd/MXXDPAkN8g7RdEWq/vZbLFUIdQstfEkoHninE1iPA1eQ+gS/uEuCrxJ8OZX3un6/ZfZvaYj7eIAT7hPeutOGPbDYHvoMkSo2ntvLeye8FZfZ5wyWdz/mCyhksV3ikKeXIbYGYF8YfuCwZShqn698drm5F/O32vKulcsoWHqyuUJ7jeu+PwK/+7hKgzYkpNs98aTZeIv6TvkHUJb6kqnuHmq6EsjggNI/RDYDk8+tfMJqTtNhQpST9m8LxZa5OKXY7AtAfiMyHtdVZF1MLUh6AYk6BxGGvjsJffOU6e6qmy4RsGIJOj2ACsywF/ELy5emuuCJbIu2RvD0jH+w/X2z39I8KS67hWOP/hLmx0coUV2dHsn4L968YR6Y0Q4CI068ClBsqQ7JFLfX0Peb0JkpDs0HO+zhQpIyGRh4gJY2U/tghYDHwiuICB6/yqYNegWkc5FBFp+EI9I5zqOXzwinSs5bvESZKZzKwHxWMtFuEKkczGBitdeTczano79QHA17NHt8ag+94Hwk73zjWmrCsO4bGNsKpnTRUMWIdGoISbGqSSAmAARgTiCELMNzJJtZno5tF2BRrIPuONN9qG5tilpSRPaDwRpiyNBNBQUwp8B4wMZUyDDQDBAcBlO1BEQdJ98z3vuvS3/WpAlXBZ+m3Bpby/YPnve93nP6aZ5Hn93d/2NYmGIPUL22BUciX3sUSHydbLHruH1R2Mn6NE3PiN77CI+e2P3h9r9e0li93H42C7fnPLaXlO3Kzmym7fjHThB9tilnNit6xYRe/V1N3P42K4cpjz3CtljV/PK7nvHxcEXyB67nhe0tGxx8EBkZJh/3jZ2b1HikeBxzUyPIyILTxWcO1cQe2jjUd1elHhkOKGNId7BtFMFHz8RD5x7KmLP6h59tmF4+x9aKDkEqrsYj6THF0Sud8ae1T1inDj0/8ZnaYVpBx6K8PYfKMzOT0hISnqCEZ9+MXbP6h4ydqI9/o/hHT318cVzBYUvHnwYBTYlOysmJiYvM4ELLz3+1P6VutRYgDWbzW7ysPGrl6w1AwQIo5ZuCSAh6DM3Eo5P9Eny9aXGbqIRXtjqatmTF+vqbqZfLEhJO7ptwzuQkp8bg+SdTJAN79yB4FmdxtbCOkTAg4d+81r6CCpnLbUkBHaXKHkI4ofL+wjgcXWE+zlCyK7WB/dzrfWJQB8euuGokWiEI1ub4Z0aANUNdHbm5menpG1Td/vTsnMTY2KiGOB4SVx3HwcavGMa27XeLTJ86ETiOngIKmctobwLNeTiZzhQGVwhkvog8K5VMFn5QmhbUhXmUIQM6safUCvsO7aFYcc5EN3NuJ/b2to+yc0v3L/NGsvMLgp0h8Sg4QXp7ujzRFv0uUSkgx1vpK4OcS0uEoJaETATROKHbpFhVXVnFjcDCeBWfhrUmp8Grq0hnj+6WXtiquu6daN5EnR3IStlm+3d0ZQsMLu8vJMn84INT66zr2ktS9itzDlE4Fsd6d5IXZK4CfpIAAnN7pKOACLQXV5e7l+pu0ZxE/hIADu/0BXix4sbBIOxg12QEOOVL4hWeHyT21IKWIGtnpicnLhx40ZbbsrRbbZ2ILuovJOpOdHRqXmK4aHuDkGBJVqD6cOH2rMKJrcEXLt2zQlfOq9xxsqBa5JVBPAGvLcdPoUwJtSvm+oFo4kb32+CIBhkvyMcnxie4LaNC3VGEHTskeZSuKKNV3IdHF4hmmFThfbZurqu3u8mJtvuTc9O32uLAtlt2+1y81KjgTNnUmNU3cXHF2iuwPIuydVHvhWBGQMlALyG7fj6BmHCCteOx3jvbUGwiiuxEhW7D9PBZThZT1GCxagM1J1znBKGB2j5NkATu8/GCLrxn3KgRI408EekyWKxNImAo94CWEGYZrPFch9+Qu3wfPgR3msf1N1kBfbG1NSDqdl7bZ9kb7PIHlRll5MafSY6D3WXhP3de0RrdKArkVJ9JXvNvZfhJnCREREYF4KgeGYlHntFwCYIIYwJL9tXIgDl2MNJRnaI0cTqFSookSkXAjThd1gPbOtCYiknWuJIZLjJCaiu54/myXu/L00/WHow2vBJyjYjRUQaFNkElF1mZs6ZMycV3aV3dWlNd26eJWiFMC4CY8wzvhCEMSy5Qeh5MbYIDJsICEAlyg9xoAECpQTo5nnCiGaHpdEhAKz/aqr0CoKqO5cYCofAMYSPLine truncated
background-repeat: no-repeat;
background-size: 100% 100%;
width: 630rpx;
height: 649rpx;
position: fixed;
top: 20%;
z-index: 1000;
left: 50%;
margin-left: -305rpx;
transform: translate3d(0, -200%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
}
.coupon-window.on {
transform: translate3d(0, 0, 0);
}
.coupon-window .couponWinList {
width: 480rpx;
margin: 157rpx 0 0 60rpx;
height: 415rpx;
overflow: auto;
}
.coupon-window .couponWinList .item {
width: 100%;
height: 120rpx;
background-color: #fff;
position: relative;
margin-bottom: 17rpx;
}
.coupon-window .couponWinList .item::after {
content: '';
position: absolute;
width: 18rpx;
height: 18rpx;
border-radius: 50%;
background-color: #f2443a;
left: 25.5%;
bottom: 0;
margin-bottom: -9rpx;
}
.coupon-window .couponWinList .item::before {
content: '';
position: absolute;
width: 18rpx;
height: 18rpx;
border-radius: 50%;
background-color: #f2443a;
left: 25.5%;
top: 0;
margin-top: -9rpx;
}
.coupon-window .couponWinList .item .money {
width: 130rpx;
border-right: 1px dashed #ddd;
height: 100%;
text-align: center;
line-height: 120rpx;
font-size: 26rpx;
font-weight: bold;
}
.coupon-window .couponWinList .item .money .num {
font-size: 40rpx;
}
.coupon-window .couponWinList .item .text {
width: 349rpx;
font-size: 22rpx;
color: #999;
padding: 0 29rpx;
box-sizing: border-box;
}
.coupon-window .couponWinList .item .text .name {
font-size: 26rpx;
color: #282828;
font-weight: bold;
margin-bottom: 9rpx;
}
.coupon-window .lid {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAj0AAADgCAMAAADfcCfrAAAA1VBMVEUAAADuOi7uOi77TUr6TUn7Tkr8Tkv6TEj7Tkr7Tkr7Tkr7Tkv7Tkr6TUn7Tkv7Tkr8Tkv7TUn7Tkr6TUj7Tkv8Tkv7Tkr7Tkr7TUn6TUj7Tkv7Tkr7Tkv7TUn6TUn7Tkr7T0v8T0v6S0b8T0v7Tkr7Tkv7Tkr4SkT8T0v8T0v8TkvuOi7uOi7uOy7uOi7uOy7uOi7yQDf5S0X0QzrvPDD6TUn1RT7xPzT4SUP3SEHvOy75TEf2R0DzQjjwPjP7Tkr3SUL1RDz2Rj/wPTL7T0v6TEj8T0z0OnFeAAAAMXRSTlMA9otDM86SA7lo+6BeVeWHLQepdxLr3bI8I8CYcE9J8B32DdXGjHwoY4EW6WL80q+xIV6CCQAABS1JREFUeNrs2tlyokAYhuGugkZ2kH1HZFFznmNPmL7/SxqjyRCTTAUzE9PA91zDW3//dEMAvsomAF+xitqAkZgA3Gibaz47Iay2ohUBGGujyBW7IOzEd/QHAvCplXigbEDYM9oKawLwd1tDM9kVwgZlmGGLho/ZbqKytwi7Zmr6hgBcL8mpyT5C2Hu1ZHgE4LLpdOehM6qeoaAcBS3eZu/4bDCingFFQQvm5VLNBjfVMxRk4GN+cbZFS9kIhH0u0PY7AguxFg6NysYhbBw/zERcSc/dKurkio1H+vGq5FBsCczTys7Csr8N6W+j1ppiYwjNzDpyh3K+q55hCFk57hRnwiuspuq/hvRfFThZhJexadvoad0P7lLPQKXpHufYJK3szDH7wX3rGVSNpO+Q0IR4xUEu+xMO6jkrk1bHFOLfSlS0y2HFUz1nVZPuRexCvIqNNqn6Ez7rOVOplgl43eDLJrdkv3/CeT0XpmwZWIZ4sMkPodlfTKWes4pqroCLoR8TG28mzqTqufATSYnwq8ddrcW9lJT9WxOs58KU0dBdbArXqdX+Lsjxrp7mEM6yb+JFSpqUxzsixx9QUqczbHza/8du9q1sHj81i3ou1ECWsiLGh9m/eBAUaXw3M6rnVUQKIrrV2jZcrbnxnJpfPUNEqWuI+PvsM6u4yCQ5UI8c4KaeFz51rL0QYyl6Z2vn3GTDaz0vzMaxlMLGLCLrnaBYDvWP/OG2nmEWhZKrRwscRus40g9aYvZHbnFfz+uM0k4X7LnfOD5F40ohNY/8m049f1RB40idXtizesh/sAW9S0MuD6g51TNQTSprrasX4maaB5u3E/TM0kJq8rQLL6Se18qgCbW2UwzB5jslbxfle7edbjJzrOdKZdLEObWU6fkpJo/8pPVDLAq5nh0kR25qf/LFvEYel6AM6kZ2tNTqMsUoBDGOvS35Blsv3omRYOiKa0lamNDAVx9nbBn1fEgtzaCmiRyeskpby+pcV1EU3TBy4Zl4RXhWGMYpDyVzXcuy0jR1nFBuaBCU1ePSLLgeQD0wHuoBjqAeQD0wAuoBjqAeQD0wAuoBjqAeQD3wE8gv+M0uHRMxDARBADtMqeKxC/NHZQo71/wWEgaxZQ/2cMLcsGUP9hCwhyL2YA8BeyhiD/Zwwvxgyx7sIWAPRezBHgL2UMQe7CFgD0XswR4C9lDEHvbmD1v2YA8BeyhiD/YQsIci9mAPAXsoMi9s2YM9BOyhiD3YwwlzwZY92EPAHorYgz0E7KGIPdhDwB6KzANb9nzs0sEJAkAQBLBtSRQFQUHtvydbGPZz80hqCPYQsIci9mAPAXsoYg/2cMJ8Ycse7CFgD0XsYW/usGUP9hCwhyL2YA8BeyhiD/YQsIci9mAPJ8wHtuzBHgL2UMQe7OGEucKWPdhDwB6K2IM9BOyhiD3YQ8AeitiDPQTsoci8YMse7CFgD0XswR4C9lDEHuzhhLnAlj3YQ8AeitiDPQTsoYg92EPAHorYgz0E7KGIPdjDCfOALXuwh4A9FLEHewjYQxF7sIeAPRSxh715w5Y92EPAHorYgz0E7KGIPdjDCfODLXuwh4A9FLGHvbnBlj3YQ8AeitiDPQTsoYg92EPAHorYgz0E7KHIPOHffh3jAAREURR9RKJSiIaCQqP4Y6j//hdGxALMbzT3rOHmJS+KekA9+IN2B4JkDgTpcCDGNDsQc2hlfBBjizRlB8pVqZW0nfwulNrzE4+0ptMq4DvLdaNXu3VDDXyWxl63C8Kz+KuXmMKNAAAAAElFTkSuQmCC');
background-repeat: no-repeat;
background-size: 100% 100%;
width: 573rpx;
height: 224rpx;
position: fixed;
left: 50%;
top: 20%;
margin: 424rpx 0 0 -296rpx;
}
.coupon-window .lid .bnt {
font-size: 29rpx;
width: 440rpx;
height: 80rpx;
border-radius: 40rpx;
background-color: #f9f1d3;
text-align: center;
line-height: 80rpx;
font-weight: bold;
margin: 98rpx auto 0 auto;
}
.coupon-window .lid .iconfont {
color: #fff;
font-size: 60rpx;
text-align: center;
margin-top: 87rpx;
}
</style>
+260
View File
@@ -0,0 +1,260 @@
<template>
<view>
<view class="upload">
<block v-for="(upload,index) in uploads" :key="index">
<view class="uplode-file">
<image v-if="types == 'image'" class="uploade-img" :src="upload" :data-src="upload" @tap="previewImage"></image>
<image v-if="types == 'image'" class="clear-one-icon" :src="clearIcon" @tap="delImage(index)"></image>
<video v-if="types == 'video'" class="uploade-img" :src="upload" controls>
<cover-image v-if="types == 'video'" class="clear-one-icon" :src="clearIcon" @tap="delImage(index)"></cover-image>
</video>
</view>
</block>
<view class="uploader-input-box" v-if="uploads.length < uploadCount">
<view class="uploader-input" @tap="chooseUploads"></view>
</view>
</view>
<button type="primary" v-if="types == 'image'" @tap="upload">上传</button>
</view>
</template>
<script>
export default{
props: {
types: {
type: String,
default: 'image'
},
dataList: {
type: Array,
default: function() {
return []
}
},
clearIcon: {
type: String,
default: 'http://img1.imgtn.bdimg.com/it/u=451604666,2295832001&fm=26&gp=0.jpg'
},
uploadUrl: {
type: String,
default: ''
},
deleteUrl: {
type: String,
default: ''
},
uploadCount: {
type: Number,
default: 1
},
//上传图片大小 默认3M
upload_max: {
type: Number,
default: 3
}
},
data(){
return {
//上传的图片地址
uploadImages: [],
//展示的图片地址
uploads: [],
// 超出限制数组
exceeded_list: [],
}
},
watch:{
dataList() {
this.uploads = this.dataList
}
},
methods:{
previewImage (e) {
var current = e.target.dataset.src
uni.previewImage({
current: current,
urls: this.dataList
})
},
chooseUploads(){
switch (this.types){
case 'image':
uni.chooseImage({
count: this.uploadCount - this.uploads.length, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], //从相册选择
success: (res) => {
for(let i = 0; i< res.tempFiles.length; i++){
if(Math.ceil(res.tempFiles[i].size / 1024) < this.upload_max * 1024){
this.uploads.push(res.tempFiles[i].path)
this.uploadImages.push(res.tempFiles[i].path)
}else {
this.exceeded_list.push(i === 0 ? 1 : i + 1);
uni.showModal({
title: '提示',
content: `第${[...new Set(this.exceeded_list)].join(',')}张图片超出限制${this.upload_max}MB,已过滤`
});
}
}
},
fail: (err) => {
uni.showModal({
content: JSON.stringify(err)
});
}
});
break;
case 'video' :
uni.chooseVideo({
sourceType: ['camera', 'album'],
success: (res) => {
if(Math.ceil(res.size / 1024) < this.upload_max * 1024){
this.uploads.push(res.tempFilePath)
uni.uploadFile({
url: this.uploadUrl, //仅为示例,非真实的接口地址
filePath: res.tempFilePath,
name: 'file',
//请求参数
formData: {
'user': 'test'
},
success: (uploadFileRes) => {
this.$emit('successVideo',uploadFileRes)
}
});
}else {
uni.showModal({
title: '提示',
content: `第${[...new Set(this.exceeded_list)].join(',')}张视频超出限制${this.upload_max}MB,已过滤`
});
}
},
fail: (err) => {
uni.showModal({
content: JSON.stringify(err)
});
}
});
break;
}
},
delImage(index){
if(this.uploads[index].substring(0,4) !== 'http'){
this.uploads.splice(index,1)
return;
};
if(!this.deleteUrl) {
uni.showModal({
content: '请填写删除接口'
});
return;
};
uni.request({
url: this.deleteUrl,
method: 'DELETE',
data: {
image: this.dataList[index]
},
success: res => {
this.uploads.splice(index,1)
},
});
},
upload(){
if(!this.uploadUrl) {
uni.showModal({
content: '请填写上传接口'
});
return;
};
for (let i of this.uploadImages) {
uni.uploadFile({
url: this.uploadUrl, //仅为示例,非真实的接口地址
filePath: i,
name: 'file',
//请求参数
formData: {
'user': 'test'
},
success: (uploadFileRes) => {
this.$emit('successImage',uploadFileRes)
}
});
}
}
}
}
</script>
<style scoped>
.upload {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.uplode-file {
margin: 10upx;
width: 210upx;
height: 210upx;
position: relative;
}
.uploade-img {
display: block;
width: 210upx;
height: 210upx;
}
.clear-one{
position: absolute;
top: -10rpx;
right: 0;
}
.clear-one-icon{
position: absolute;
width: 20px;
height: 20px;
top: 0;
right: 0;
z-index: 9;
}
.uploader-input-box {
position: relative;
margin:10upx;
width: 208upx;
height: 208upx;
border: 2upx solid #D9D9D9;
}
.uploader-input-box:before,
.uploader-input-box:after {
content: " ";
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
background-color: #D9D9D9;
}
.uploader-input-box:before {
width: 4upx;
height: 79upx;
}
.uploader-input-box:after {
width: 79upx;
height: 4upx;
}
.uploader-input-box:active {
border-color: #999999;
}
.uploader-input-box:active:before,
.uploader-input-box:active:after {
background-color: #999999;
}
.uploader-input {
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
}
</style>
+40
View File
@@ -0,0 +1,40 @@
### easy-upload 组件
使用方法
```js
<easy-upload
:dataList="imageList" uploadUrl="http://localhost:3000/upload" :types="category"
deleteUrl='http://localhost:3000/upload' :uploadCount="6"
@successImage="successImage" @successVideo="successvideo"
></easy-upload>
//先引入组件
import easyUpload from '@/components/easy-upload/easy-upload.vue'
//注册组件
components:{
easyUpload
}
//使用 easycom 可以直接使用
```
| 参数 | 类型 | 是否必填 | 参数描述
| ---- | ---- | ---- | ----
| types | String | 否 | 上传类型 image/video
| dataList | Array | 否 | 图片/视频数据展示
| clearIcon | String | 否 | 删除图标(可以换成自己本地图片)
| uploadUrl | String | 否 | 上传的接口
| deleteUrl | String | 否 | 删除的接口
| uploadCount | Number | 否 | 上传图片最大个数(默认为一张)
| upload_max | Number | 否 | 上传大小(默认为3M)
| upload_max | Number | 否 | 上传大小(默认为3M)
| upload_max | Number | 否 | 上传大小(默认为3M)
| 事件 | 是否必填 | 参数描述
| ---- | ---- | ----
| successImage | 否 | 上传图片成功事件
| successVideo | 否 | 上传视频成功回调
示例项目中有服务端代码 (node.js)
+37
View File
@@ -0,0 +1,37 @@
<template>
<view class="empty-box">
<image src="../static/images/empty-box.png"></image>
<view class="txt">{{title}}</view>
</view>
</template>
<script>
export default{
props: {
title: {
type: String,
default: '暂无记录',
},
},
}
</script>
<style lang="scss">
.empty-box{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-top: 200rpx;
padding-bottom: 60rpx;
image{
width: 414rpx;
height: 240rpx;
}
.txt{
font-size: 26rpx;
color: #999;
}
}
</style>
+140
View File
@@ -0,0 +1,140 @@
<template>
<view class='goodList'>
<block v-for="(item,index) in bastList" :key="index">
<view @click="goDetail(item)" class='item acea-row row-between-wrapper' hover-class="none">
<view class='pictrue'>
<image :src='item.picUrl'></image>
<span class="pictrue_log pictrue_log_class" v-if="item.activityList && item.activityList[0] && item.activityList[0].type === 1">秒杀</span>
<span class="pictrue_log pictrue_log_class" v-if="item.activityList && item.activityList[0] && item.activityList[0].type === 2">砍价</span>
<span class="pictrue_log pictrue_log_class" v-if="item.activityList && item.activityList[0] && item.activityList[0].type === 3">拼团</span>
</view>
<view class='underline'>
<view class='text'>
<view class='line1'>{{ item.name }}</view>
<view class='money font-color'>¥<text class='num'>{{ fen2yuan(item.price) }}</text></view>
<view class='vip-money acea-row row-middle' v-if="item.vipPrice > 0">¥{{ fen2yuan(item.price - item.vipPrice) }}
<image src='../../static/images/vip.png'></image><text class='num'>已售{{ item.salesCount }}{{item.unitName}}</text>
</view>
<view class='vip-money acea-row row-middle' v-else><text class='num'>已售{{ item.salesCount }}{{item.unitName}}</text></view>
</view>
</view>
<view class='iconfont icon-gouwuche cart-color acea-row row-center-wrapper'></view>
</view>
</block>
</view>
</template>
<script>
import {mapGetters} from "vuex";
import { goShopDetail } from '@/libs/order.js'
import * as Util from '@/utils/util.js';
export default {
computed: mapGetters(['uid']),
props: {
status: {
type: Number,
default: 0,
},
bastList: {
type: Array,
default: function() {
return [];
}
}
},
methods: {
goDetail(item) {
goShopDetail(item,this.uid).then(() =>{
uni.navigateTo({
url:`/pages/goods_details/index?id=${item.id}`
})
})
},
fen2yuan(price) {
return Util.fen2yuan(price)
}
}
}
</script>
<style scoped lang='scss'>
.goodList .item {
position: relative;
padding-left: 30rpx;
}
.goodList .item .pictrue {
width: 180rpx;
height: 180rpx;
position: relative;
}
.goodList .item .pictrue image {
width: 100%;
height: 100%;
border-radius: 6rpx;
}
.goodList .item .pictrue .numPic {
position: absolute;
left: 7rpx;
top: 7rpx;
width: 50rpx;
height: 50rpx;
border-radius: 50%;
}
.goodList .item .underline {
padding: 30rpx 30rpx 30rpx 0;
border-bottom: 1px solid #f5f5f5;
}
.goodList .item:nth-last-child(1) .underline {
border-bottom: 0;
}
.goodList .item .text {
font-size: 30rpx;
color: #222;
width: 489rpx;
}
.goodList .item .text .money {
font-size: 26rpx;
font-weight: bold;
margin-top: 50rpx;
}
.goodList .item .text .money .num {
font-size: 34rpx;
}
.goodList .item .text .vip-money {
font-size: 24rpx;
color: #282828;
font-weight: bold;
margin-top: 15rpx;
}
.goodList .item .text .vip-money image {
width: 46rpx;
height: 21rpx;
margin: 0 22rpx 0 5rpx;
}
.goodList .item .text .vip-money .num {
font-size: 22rpx;
color: #aaa;
font-weight: normal;
margin: -2rpx 0 0 0;
}
.goodList .item .iconfont {
position: absolute;
right: 30rpx;
width: 50rpx;
height: 50rpx;
border-radius: 50%;
font-size: 30rpx;
bottom: 38rpx;
}
</style>
+107
View File
@@ -0,0 +1,107 @@
<template>
<view style="touch-action: none;">
<view class="home" style="position:fixed;" :style="{ top: top + 'px'}" id="right-nav" @touchmove.stop.prevent="setTouchMove">
<view class="homeCon bg-color-red" :class="homeActive === true ? 'on' : ''" v-if="homeActive">
<navigator hover-class='none' url='/pages/index/index' open-type='switchTab'
class='iconfont icon-shouye-xianxing' />
<navigator hover-class='none' url='/pages/order_addcart/order_addcart' open-type='switchTab'
class='iconfont icon-caigou-xianxing' />
<navigator hover-class='none' url='/pages/user/index' open-type='switchTab'
class='iconfont icon-yonghu1' />
</view>
<view @click="open" class="pictrueBox">
<view class="pictrue">
<image :src="homeActive === true ? '/static/images/close.gif' : '/static/images/open.gif'" class="image" />
</view>
</view>
</view>
</view>
</template>
<script>
import {
mapGetters
} from "vuex";
export default {
name: "Home",
props: {},
data: function() {
return {
top: "500"
};
},
computed: mapGetters(["homeActive"]),
methods: {
setTouchMove(e) {
if (e.touches[0].clientY < 545 && e.touches[0].clientY > 66) {
this.top = e.touches[0].clientY
}
},
open: function() {
this.homeActive ?
this.$store.commit("CLOSE_HOME") :
this.$store.commit("OPEN_HOME");
}
}
};
</script>
<style scoped>
.pictrueBox {
width: 130rpx;
height: 120rpx;
}
/*返回主页按钮*/
.home {
position: fixed;
color: white;
text-align: center;
z-index: 9999;
right: 15rpx;
display: flex;
}
.home .homeCon {
border-radius: 50rpx;
opacity: 0;
height: 0;
color: $theme-color;
width: 0;
}
.home .homeCon.on {
opacity: 1;
animation: bounceInRight 0.5s cubic-bezier(0.215, 0.610, 0.355, 1.000);
width: 300rpx;
height: 86rpx;
margin-bottom: 20rpx;
display: flex;
justify-content: center;
align-items: center;
background: #f44939 !important;
}
.home .homeCon .iconfont {
font-size: 48rpx;
color: #fff;
display: inline-block;
margin: 0 auto;
}
.home .pictrue {
width: 86rpx;
height: 86rpx;
border-radius: 50%;
margin: 0 auto;
}
.home .pictrue .image {
width: 100%;
height: 100%;
border-radius: 50%;
transform: rotate(90deg);
ms-transform: rotate(90deg);
moz-transform: rotate(90deg);
webkit-transform: rotate(90deg);
o-transform: rotate(90deg);
}
</style>
+814
View File
@@ -0,0 +1,814 @@
<!--
parser 主模块组件
github:https://github.com/jin-yufeng/Parser
docs:https://jin-yufeng.github.io/Parser
插件市场:https://ext.dcloud.net.cn/plugin?id=805
author:JinYufeng
update:2020/04/14
-->
<template>
<view>
<slot v-if="!nodes.length" />
<!--#ifdef APP-PLUS-NVUE-->
<web-view id="top" ref="web" :src="src" :style="'margin-top:-2px;height:'+height+'px'" @onPostMessage="_message" />
<!--#endif-->
<!--#ifndef APP-PLUS-NVUE-->
<view id="top" :style="showAm+(selectable?';user-select:text;-webkit-user-select:text':'')" :animation="scaleAm" @tap="_tap"
@touchstart="_touchstart" @touchmove="_touchmove">
<!--#ifdef H5-->
<div :id="'rtf'+uid"></div>
<!--#endif-->
<!--#ifndef H5-->
<trees :nodes="nodes" :lazy-load="lazyLoad" :loadVideo="loadVideo" />
<image v-for="(item, index) in imgs" v-bind:key="index" :id="index" :src="item" hidden @load="_load" />
<!--#endif-->
</view>
<!--#endif-->
</view>
</template>
<script>
// #ifndef H5 || APP-PLUS-NVUE
import trees from './libs/trees';
var cache = {},
// #ifdef MP-WEIXIN || MP-TOUTIAO
fs = uni.getFileSystemManager ? uni.getFileSystemManager() : null,
// #endif
Parser = require('./libs/MpHtmlParser.js');
var document; // document 补丁包 https://jin-yufeng.github.io/Parser/#/instructions?id=document
// 计算 cache 的 key
function hash(str) {
for (var i = str.length, val = 5381; i--;)
val += (val << 5) + str.charCodeAt(i);
return val;
}
// #endif
// #ifdef H5 || APP-PLUS-NVUE
var rpx = uni.getSystemInfoSync().screenWidth / 750,
cfg = require('./libs/config.js');
// #endif
// #ifdef APP-PLUS-NVUE
var dom = weex.requireModule('dom');
// #endif
export default {
name: 'parser',
data() {
return {
// #ifdef APP-PLUS
loadVideo: false,
// #endif
// #ifdef H5
uid: this._uid,
// #endif
// #ifdef APP-PLUS-NVUE
src: '',
height: 1,
// #endif
// #ifndef APP-PLUS-NVUE
scaleAm: '',
showAm: '',
imgs: [],
// #endif
nodes: []
}
},
// #ifndef H5 || APP-PLUS-NVUE
components: {
trees
},
// #endif
props: {
'html': null,
// #ifndef MP-ALIPAY
'autopause': {
type: Boolean,
default: true
},
// #endif
'autosetTitle': {
type: Boolean,
default: true
},
// #ifndef H5 || APP-PLUS-NVUE
'compress': Number,
'useCache': Boolean,
'xml': Boolean,
// #endif
'domain': String,
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
'gestureZoom': Boolean,
// #endif
// #ifdef MP-WEIXIN || MP-QQ || H5 || APP-PLUS
'lazyLoad': Boolean,
// #endif
'selectable': Boolean,
'tagStyle': Object,
'showWithAnimation': Boolean,
'useAnchor': Boolean
},
watch: {
html(html) {
this.setContent(html);
}
},
mounted() {
// 图片数组
this.imgList = [];
this.imgList.each = function(f) {
for (var i = 0, len = this.length; i < len; i++)
this.setItem(i, f(this[i], i, this));
}
this.imgList.setItem = function(i, src) {
if (i == void 0 || !src) return;
// #ifndef MP-ALIPAY || APP-PLUS
// 去重
if (src.indexOf('http') == 0 && this.includes(src)) {
var newSrc = '';
for (var j = 0, c; c = src[j]; j++) {
if (c == '/' && src[j - 1] != '/' && src[j + 1] != '/') break;
newSrc += Math.random() > 0.5 ? c.toUpperCase() : c;
}
newSrc += src.substr(j);
return this[i] = newSrc;
}
// #endif
this[i] = src;
// 暂存 data src
if (src.includes('data:image')) {
var filePath, info = src.match(/data:image\/(\S+?);(\S+?),(.+)/);
if (!info) return;
// #ifdef MP-WEIXIN || MP-TOUTIAO
filePath = `${wx.env.USER_DATA_PATH}/${Date.now()}.${info[1]}`;
fs && fs.writeFile({
filePath,
data: info[3],
encoding: info[2],
success: () => this[i] = filePath
})
// #endif
// #ifdef APP-PLUS
filePath = `_doc/parser_tmp/${Date.now()}.${info[1]}`;
var bitmap = new plus.nativeObj.Bitmap();
bitmap.loadBase64Data(src, () => {
bitmap.save(filePath, {}, () => {
bitmap.clear()
this[i] = filePath;
})
})
// #endif
}
}
if (this.html) this.setContent(this.html);
},
beforeDestroy() {
// #ifdef H5
if (this._observer) this._observer.disconnect();
// #endif
this.imgList.each(src => {
// #ifdef APP-PLUS
if (src && src.includes('_doc')) {
plus.io.resolveLocalFileSystemURL(src, entry => {
entry.remove();
});
}
// #endif
// #ifdef MP-WEIXIN || MP-TOUTIAO
if (src && src.includes(uni.env.USER_DATA_PATH))
fs && fs.unlink({
filePath: src
})
// #endif
})
clearInterval(this._timer);
},
methods: {
// #ifdef H5 || APP-PLUS-NVUE
_Dom2Str(nodes) {
var str = '';
for (var node of nodes) {
if (node.type == 'text')
str += node.text;
else {
str += ('<' + node.name);
for (var attr in node.attrs || {})
str += (' ' + attr + '="' + node.attrs[attr] + '"');
if (!node.children || !node.children.length) str += '>';
else str += ('>' + this._Dom2Str(node.children) + '</' + node.name + '>');
}
}
return str;
},
_handleHtml(html, append) {
if (typeof html != 'string') html = this._Dom2Str(html.nodes || html);
// 处理 rpx
if (html.includes('rpx'))
html = html.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * rpx + 'px');
if (!append) {
// 处理 tag-style 和 userAgentStyles
var style = '<style>@keyframes show{0%{opacity:0}100%{opacity:1}}';
for (var item in cfg.userAgentStyles)
style += `${item}{${cfg.userAgentStyles[item]}}`;
for (item in this.tagStyle)
style += `${item}{${this.tagStyle[item]}}`;
style += '</style>';
html = style + html;
}
return html;
},
// #endif
setContent(html, append) {
// #ifdef APP-PLUS-NVUE
if (!html) {
this.src = '';
this.height = 1;
return;
}
if (append) return;
plus.io.resolveLocalFileSystemURL('_doc', entry => {
entry.getDirectory('parser_tmp', {
create: true
}, entry => {
var fileName = Date.now() + '.html';
entry.getFile(fileName, {
create: true
}, entry => {
entry.createWriter(writer => {
writer.onwriteend = () => {
this.nodes = [1];
this.src = '_doc/parser_tmp/' + fileName;
this.$nextTick(function() {
entry.remove();
})
}
html =
'<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1' +
(this.selectable ? '' : ',user-scalable=no') +
'"><script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></' +
'script><base href="' + this.domain + '">' + this._handleHtml(html) +
'<script>"use strict";function post(t){uni.postMessage({data:t})}' +
(this.showWithAnimation ? 'document.body.style.animation="show .5s",' : '') +
'document.addEventListener("UniAppJSBridgeReady",function(){post({action:"load",text:document.body.innerText});var t=document.getElementsByTagName("title");t.length&&post({action:"getTitle",title:t[0].innerText});for(var e,o=document.getElementsByTagName("img"),n=[],i=0,r=0;e=o[i];i++)e.onerror=function(){post({action:"error",source:"img",target:this})},e.hasAttribute("ignore")||"A"==e.parentElement.nodeName||(e.i=r++,n.push(e.src),e.onclick=function(){post({action:"preview",img:{i:this.i,src:this.src}})});post({action:"getImgList",imgList:n});for(var a,s=document.getElementsByTagName("a"),c=0;a=s[c];c++)a.onclick=function(){var t,e=this.getAttribute("href");if("#"==e[0]){var r=document.getElementById(e.substr(1));r&&(t=r.offsetTop)}return post({action:"linkpress",href:e,offset:t}),!1};;for(var u,m=document.getElementsByTagName("video"),d=0;u=m[d];d++)u.style.maxWidth="100%",u.onerror=function(){post({action:"error",source:"video",target:this})}' +
(this.autopause ? ',u.onplay=function(){for(var t,e=0;t=m[e];e++)t!=this&&t.pause()}' : '') +
';for(var g,l=document.getElementsByTagName("audio"),p=0;g=l[p];p++)g.onerror=function(){post({action:"error",source:"audio",target:this})};window.onload=function(){post({action:"ready",height:document.body.scrollHeight})}});</' +
'script>';
writer.write(html);
});
})
})
})
// #endif
// #ifdef H5
if (!html) {
if (this.rtf && !append) this.rtf.parentNode.removeChild(this.rtf);
return;
}
var div = document.createElement('div');
if (!append) {
if (this.rtf) this.rtf.parentNode.removeChild(this.rtf);
this.rtf = div;
} else {
if (!this.rtf) this.rtf = div;
else this.rtf.appendChild(div);
}
div.innerHTML = this._handleHtml(html, append);
for (var styles = this.rtf.getElementsByTagName('style'), i = 0, style; style = styles[i++];) {
style.innerHTML = style.innerHTML.replace(/body/g, '#rtf' + this._uid);
style.setAttribute('scoped', 'true');
}
// 懒加载
if (!this._observer && this.lazyLoad && IntersectionObserver) {
this._observer = new IntersectionObserver(changes => {
for (let item, i = 0; item = changes[i++];) {
if (item.isIntersecting) {
item.target.src = item.target.getAttribute('data-src');
item.target.removeAttribute('data-src');
this._observer.unobserve(item.target);
}
}
}, {
rootMargin: '900px 0px 900px 0px'
})
}
var _ts = this;
// 获取标题
var title = this.rtf.getElementsByTagName('title');
if (title.length && this.autosetTitle)
uni.setNavigationBarTitle({
title: title[0].innerText
})
// 图片处理
this.imgList.length = 0;
var imgs = this.rtf.getElementsByTagName('img');
for (let i = 0, j = 0, img; img = imgs[i]; i++) {
img.style.maxWidth = '100%';
var src = img.getAttribute('src');
if (this.domain && src) {
if (src[0] == '/') {
if (src[1] == '/')
img.src = (this.domain.includes('://') ? this.domain.split('://')[0] : '') + ':' + src;
else img.src = this.domain + src;
} else if (!src.includes('://')) img.src = this.domain + '/' + src;
}
if (!img.hasAttribute('ignore') && img.parentElement.nodeName != 'A') {
img.i = j++;
_ts.imgList.push(img.src || img.getAttribute('data-src'));
img.onclick = function() {
var preview = true;
this.ignore = () => preview = false;
_ts.$emit('imgtap', this);
if (preview) {
uni.previewImage({
current: this.i,
urls: _ts.imgList
});
}
}
}
img.onerror = function() {
_ts.$emit('error', {
source: 'img',
target: this
});
}
if (_ts.lazyLoad && this._observer && img.src && img.i != 0) {
img.setAttribute('data-src', img.src);
img.removeAttribute('src');
this._observer.observe(img);
}
}
// 链接处理
var links = this.rtf.getElementsByTagName('a');
for (var link of links) {
link.onclick = function() {
var jump = true,
href = this.getAttribute('href');
_ts.$emit('linkpress', {
href,
ignore: () => jump = false
});
if (jump && href) {
if (href[0] == '#') {
if (_ts.useAnchor) {
_ts.navigateTo({
id: href.substr(1)
})
}
} else if (href.indexOf('http') == 0 || href.indexOf('//') == 0)
return true;
else {
uni.navigateTo({
url: href
})
}
}
return false;
}
}
// 视频处理
var videos = this.rtf.getElementsByTagName('video');
_ts.videoContexts = videos;
for (let video, i = 0; video = videos[i++];) {
video.style.maxWidth = '100%';
video.onerror = function() {
_ts.$emit('error', {
source: 'video',
target: this
});
}
video.onplay = function() {
if (_ts.autopause)
for (let item, i = 0; item = _ts.videoContexts[i++];)
if (item != this) item.pause();
}
}
// 音频处理
var audios = this.rtf.getElementsByTagName('audios');
for (var audio of audios)
audio.onerror = function() {
_ts.$emit('error', {
source: 'audio',
target: this
});
}
this.document = this.rtf;
if (!append) document.getElementById('rtf' + this._uid).appendChild(this.rtf);
this.$nextTick(() => {
this.nodes = [1];
this.$emit('load');
})
setTimeout(() => this.showAm = '', 500);
// #endif
// #ifndef H5 || APP-PLUS-NVUE
var nodes;
if (!html)
return this.nodes = [];
else if (typeof html == 'string') {
let parser = new Parser(html, this);
// 缓存读取
if (this.useCache) {
var hashVal = hash(html);
if (cache[hashVal])
nodes = cache[hashVal];
else {
nodes = parser.parse();
cache[hashVal] = nodes;
}
} else nodes = parser.parse();
this.$emit('parse', nodes);
} else if (Object.prototype.toString.call(html) == '[object Array]') {
// 非本插件产生的 array 需要进行一些转换
if (html.length && html[0].PoweredBy != 'Parser') {
let parser = new Parser(html, this);
(function f(ns) {
for (var i = 0, n; n = ns[i]; i++) {
if (n.type == 'text') continue;
n.attrs = n.attrs || {};
for (var item in n.attrs)
if (typeof n.attrs[item] != 'string') n.attrs[item] = n.attrs[item].toString();
parser.matchAttr(n, parser);
if (n.children && n.children.length) {
parser.STACK.push(n);
f(n.children);
parser.popNode(parser.STACK.pop());
} else n.children = void 0;
}
})(html);
}
nodes = html;
} else if (typeof html == 'object' && html.nodes) {
nodes = html.nodes;
console.warn('错误的 html 类型:object 类型已废弃');
} else
return console.warn('错误的 html 类型:' + typeof html);
// #ifdef APP-PLUS
this.loadVideo = false;
// #endif
if (document) this.document = new document(this.nodes, 'nodes', this);
if (append) this.nodes = this.nodes.concat(nodes);
else this.nodes = nodes;
if (nodes.length && nodes[0].title && this.autosetTitle)
uni.setNavigationBarTitle({
title: nodes[0].title
})
this.$nextTick(() => {
this.imgList.length = 0;
this.videoContexts = [];
// #ifdef MP-TOUTIAO
setTimeout(() => {
// #endif
var f = (cs) => {
for (let i = 0, c; c = cs[i++];) {
if (c.$options.name == 'trees') {
for (var j = c.nodes.length, item; item = c.nodes[--j];) {
if (item.c) continue;
if (item.name == 'img') {
this.imgList.setItem(item.attrs.i, item.attrs.src);
// #ifndef MP-ALIPAY
if (!c.observer && !c.imgLoad && item.attrs.i != '0') {
if (this.lazyLoad && uni.createIntersectionObserver) {
c.observer = uni.createIntersectionObserver(c);
c.observer.relativeToViewport({
top: 900,
bottom: 900
}).observe('._img', () => {
c.imgLoad = true;
c.observer.disconnect();
})
} else
c.imgLoad = true;
}
// #endif
}
// #ifndef MP-ALIPAY
else if (item.name == 'video') {
var ctx = uni.createVideoContext(item.attrs.id, c);
ctx.id = item.attrs.id;
this.videoContexts.push(ctx);
}
// #endif
// #ifdef MP-BAIDU || MP-ALIPAY || APP-PLUS
if (item.attrs && item.attrs.id) {
this.anchors = this.anchors || [];
this.anchors.push({
id: item.attrs.id,
node: c
})
}
// #endif
}
}
if (c.$children.length)
f(c.$children)
}
}
f(this.$children);
// #ifdef MP-TOUTIAO
}, 200)
this.$emit('load');
// #endif
// #ifdef APP-PLUS
setTimeout(() => {
this.loadVideo = true;
}, 3000);
// #endif
})
// #endif
// #ifndef APP-PLUS-NVUE
var height;
clearInterval(this._timer);
this._timer = setInterval(() => {
// #ifdef H5
var res = [this.rtf.getBoundingClientRect()];
// #endif
// #ifndef H5
// #ifdef APP-PLUS
uni.createSelectorQuery().in(this)
// #endif
// #ifndef APP-PLUS
this.createSelectorQuery()
// #endif
.select('#top').boundingClientRect().exec(res => {
// #endif
this.width = res[0].width;
if (res[0].height == height) {
this.$emit('ready', res[0])
clearInterval(this._timer);
}
height = res[0].height;
// #ifndef H5
});
// #endif
}, 350)
if (this.showWithAnimation && !append) this.showAm = 'animation:show .5s';
// #endif
},
getText(ns = this.nodes) {
// #ifdef APP-PLUS-NVUE
return this._text;
// #endif
// #ifdef H5
return this.rtf.innerText;
// #endif
// #ifndef H5 || APP-PLUS-NVUE
var txt = '';
for (var i = 0, n; n = ns[i++];) {
if (n.type == 'text') txt += n.text.replace(/&nbsp;/g, '\u00A0').replace(/&lt;/g, '<').replace(/&gt;/g, '>')
.replace(/&amp;/g, '&');
else if (n.type == 'br') txt += '\n';
else {
// 块级标签前后加换行
var block = n.name == 'p' || n.name == 'div' || n.name == 'tr' || n.name == 'li' || (n.name[0] == 'h' && n.name[1] >
'0' && n.name[1] < '7');
if (block && txt && txt[txt.length - 1] != '\n') txt += '\n';
if (n.children) txt += this.getText(n.children);
if (block && txt[txt.length - 1] != '\n') txt += '\n';
else if (n.name == 'td' || n.name == 'th') txt += '\t';
}
}
return txt;
// #endif
},
navigateTo(obj) {
if (!this.useAnchor)
return obj.fail && obj.fail({
errMsg: 'Anchor is disabled'
})
// #ifdef APP-PLUS-NVUE
if (!obj.id)
dom.scrollToElement(this.$refs.web);
else
this.$refs.web.evalJs('var pos=document.getElementById("' + obj.id +
'");if(pos)post({action:"linkpress",href:"#",offset:pos.offsetTop})');
return obj.success && obj.success({
errMsg: 'pageScrollTo:ok'
});
// #endif
// #ifdef H5
if (!obj.id) {
window.scrollTo(0, this.rtf.offsetTop);
return obj.success && obj.success({
errMsg: 'pageScrollTo:ok'
});
}
var target = document.getElementById(obj.id);
if (!target) return obj.fail && obj.fail({
errMsg: 'Label not found'
});
obj.scrollTop = this.rtf.offsetTop + target.offsetTop;
uni.pageScrollTo(obj);
// #endif
// #ifndef H5
var Scroll = (selector, component) => {
uni.createSelectorQuery().in(component ? component : this).select(selector).boundingClientRect().selectViewport()
.scrollOffset()
.exec(res => {
if (!res || !res[0])
return obj.fail && obj.fail({
errMsg: 'Label not found'
});
obj.scrollTop = res[1].scrollTop + res[0].top;
uni.pageScrollTo(obj);
})
}
if (!obj.id) Scroll('#top');
else {
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
Scroll('#top >>> #' + obj.id + ', #top >>> .' + obj.id);
// #endif
// #ifdef MP-BAIDU || MP-ALIPAY || APP-PLUS
for (var anchor of this.anchors)
if (anchor.id == obj.id)
Scroll('#' + obj.id + ', .' + obj.id, anchor.node);
// #endif
}
// #endif
},
getVideoContext(id) {
// #ifndef APP-PLUS-NVUE
if (!id) return this.videoContexts;
else
for (var i = this.videoContexts.length; i--;)
if (this.videoContexts[i].id == id) return this.videoContexts[i];
// #endif
},
// 预加载
preLoad(html, num) {
// #ifdef H5 || APP-PLUS-NVUE
if (html.constructor == Array)
html = this._Dom2Str(html);
var script = "var contain=document.createElement('div');contain.innerHTML='" + html.replace(/'/g, "\\'") +
"';for(var imgs=contain.querySelectorAll('img'),i=imgs.length-1;i>=" + num +
";i--)imgs[i].removeAttribute('src');";
// #endif
// #ifdef APP-PLUS-NVUE
this.$refs.web.evalJs(script);
// #endif
// #ifdef H5
eval(script);
// #endif
// #ifndef H5 || APP-PLUS-NVUE
if (typeof html == 'string') {
var id = hash(html);
html = new Parser(html, this).parse();
cache[id] = html;
}
var wait = [];
(function f(ns) {
for (var i = 0, n; n = ns[i++];) {
if (n.name == 'img' && n.attrs.src && !wait.includes(n.attrs.src))
wait.push(n.attrs.src);
f(n.children || []);
}
})(html);
if (num) wait = wait.slice(0, num);
this._wait = (this._wait || []).concat(wait);
if (!this.imgs) this.imgs = this._wait.splice(0, 15);
else if (this.imgs.length < 15)
this.imgs = this.imgs.concat(this._wait.splice(0, 15 - this.imgs.length));
// #endif
},
// #ifdef APP-PLUS-NVUE
_message(e) {
// 接收 web-view 消息
var data = e.detail.data[0];
if (data.action == 'load') {
this.$emit('load');
this._text = data.text;
} else if (data.action == 'getTitle') {
if (this.autosetTitle)
uni.setNavigationBarTitle({
title: data.title
})
} else if (data.action == 'getImgList') {
this.imgList.length = 0;
for (var i = data.imgList.length; i--;)
this.imgList.setItem(i, data.imgList[i]);
} else if (data.action == 'preview') {
var preview = true;
data.img.ignore = () => preview = false;
this.$emit('imgtap', data.img);
if (preview)
uni.previewImage({
current: data.img.i,
urls: this.imgList
})
} else if (data.action == 'linkpress') {
var jump = true,
href = data.href;
this.$emit('linkpress', {
href,
ignore: () => jump = false
})
if (jump && href) {
if (href[0] == '#') {
if (this.useAnchor)
dom.scrollToElement(this.$refs.web, {
offset: data.offset
})
} else if (href.includes('://'))
plus.runtime.openWeb(href);
else
uni.navigateTo({
url: href
})
}
} else if (data.action == 'error')
this.$emit('error', {
source: data.source,
target: data.target
})
else if (data.action == 'ready') {
this.height = data.height;
this.$nextTick(() => {
uni.createSelectorQuery().in(this).select('#top').boundingClientRect().exec(res => {
this.rect = res[0];
this.$emit('ready', res[0]);
})
})
}
},
// #endif
// #ifndef APP-PLUS-NVUE
// #ifndef H5
_load(e) {
if (this._wait.length)
this.$set(this.imgs, e.target.id, this._wait.shift());
},
// #endif
_tap(e) {
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
if (this.gestureZoom && e.timeStamp - this._lastT < 300) {
var initY = e.touches[0].pageY - e.currentTarget.offsetTop;
if (this._zoom) {
this._scaleAm.translateX(0).scale(1).step();
uni.pageScrollTo({
scrollTop: (initY + this._initY) / 2 - e.touches[0].clientY,
duration: 400
})
} else {
var initX = e.touches[0].pageX - e.currentTarget.offsetLeft;
this._initY = initY;
this._scaleAm = uni.createAnimation({
transformOrigin: `${initX}px ${this._initY}px 0`,
timingFunction: 'ease-in-out'
});
// #ifdef MP-TOUTIAO
this._scaleAm.opacity(1);
// #endif
this._scaleAm.scale(2).step();
this._tMax = initX / 2;
this._tMin = (initX - this.width) / 2;
this._tX = 0;
}
this._zoom = !this._zoom;
this.scaleAm = this._scaleAm.export();
}
this._lastT = e.timeStamp;
// #endif
},
_touchstart(e) {
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
if (e.touches.length == 1)
this._initX = this._lastX = e.touches[0].pageX;
// #endif
},
_touchmove(e) {
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
var diff = e.touches[0].pageX - this._lastX;
if (this._zoom && e.touches.length == 1 && Math.abs(diff) > 20) {
this._lastX = e.touches[0].pageX;
if ((this._tX <= this._tMin && diff < 0) || (this._tX >= this._tMax && diff > 0))
return;
this._tX += (diff * Math.abs(this._lastX - this._initX) * 0.05);
if (this._tX < this._tMin) this._tX = this._tMin;
if (this._tX > this._tMax) this._tX = this._tMax;
this._scaleAm.translateX(this._tX).step();
this.scaleAm = this._scaleAm.export();
}
// #endif
}
// #endif
}
}
</script>
<style>
@keyframes show {
0% {
opacity: 0
}
100% {
opacity: 1;
}
}
/* #ifdef MP-WEIXIN */
:host {
display: block;
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
/* #endif */
</style>
+102
View File
@@ -0,0 +1,102 @@
/*
解析和匹配 Css 的选择器
github:https://github.com/jin-yufeng/Parser
docs:https://jin-yufeng.github.io/Parser
author:JinYufeng
update:2020/03/15
*/
var cfg = require('./config.js');
class CssHandler {
constructor(tagStyle) {
var styles = Object.assign({}, cfg.userAgentStyles);
for (var item in tagStyle)
styles[item] = (styles[item] ? styles[item] + ';' : '') + tagStyle[item];
this.styles = styles;
}
getStyle = data => this.styles = new CssParser(data, this.styles).parse();
match(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;
class CssParser {
constructor(data, init) {
this.data = data;
this.floor = 0;
this.i = 0;
this.list = [];
this.res = init;
this.state = this.Space;
}
parse() {
for (var c; c = this.data[this.i]; this.i++)
this.state(c);
return this.res;
}
section = () => this.data.substring(this.start, this.i);
isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
// 状态机
Space(c) {
if (c == '.' || c == '#' || this.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;
}
Comment() {
this.i = this.data.indexOf('*/', this.i) + 1;
if (!this.i) this.i = this.data.length;
this.state = this.Space;
}
Ignore(c) {
if (c == '{') this.floor++;
else if (c == '}' && !--this.floor) this.state = this.Space;
}
Name(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 (!this.isLetter(c) && (c < '0' || c > '9') && c != '-' && c != '_')
this.state = this.Ignore;
}
NameSpace(c) {
if (c == '{') this.Content();
else if (c == ',') this.Comma();
else if (!cfg.blankChar[c]) this.state = this.Ignore;
}
Comma() {
while (cfg.blankChar[this.data[++this.i]]);
if (this.data[this.i] == '{') this.Content();
else {
this.start = this.i--;
this.state = this.Name;
}
}
Content() {
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;
}
}
+577
View File
@@ -0,0 +1,577 @@
/*
将 html 解析为适用于小程序 rich-text 的 DOM 结构
github:https://github.com/jin-yufeng/Parser
docs:https://jin-yufeng.github.io/Parser
author:JinYufeng
update:2020/04/13
*/
var cfg = require('./config.js'),
blankChar = cfg.blankChar,
CssHandler = require('./CssHandler.js'),
{
screenWidth,
system
} = wx.getSystemInfoSync();
// #ifdef MP-BAIDU || MP-ALIPAY || MP-TOUTIAO
var entities = {
lt: '<',
gt: '>',
amp: '&',
quot: '"',
apos: "'",
nbsp: '\xA0',
ensp: '\u2002',
emsp: '\u2003',
ndash: '–',
mdash: '—',
middot: '·',
lsquo: '‘',
rsquo: '’',
ldquo: '“',
rdquo: '”',
bull: '•',
hellip: '…',
permil: '‰',
copy: '©',
reg: '®',
trade: '™',
times: '×',
divide: '÷',
cent: '¢',
pound: '£',
yen: '¥',
euro: '€',
sect: '§'
};
// #endif
var emoji; // emoji 补丁包 https://jin-yufeng.github.io/Parser/#/instructions?id=emoji
class MpHtmlParser {
constructor(data, options = {}) {
this.attrs = {};
this.compress = options.compress;
this.CssHandler = new CssHandler(options.tagStyle, screenWidth);
this.data = data;
this.domain = options.domain;
this.DOM = [];
this.i = this.start = this.audioNum = this.imgNum = this.videoNum = 0;
this.protocol = this.domain && this.domain.includes('://') ? this.domain.split('://')[0] : '';
this.state = this.Text;
this.STACK = [];
this.useAnchor = options.useAnchor;
this.xml = options.xml;
}
parse() {
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());
// #ifdef MP-BAIDU || MP-TOUTIAO
// 将顶层标签的一些样式提取出来给 rich-text
(function f(ns) {
for (var i = ns.length, n; n = ns[--i];) {
if (n.type == 'text') continue;
if (!n.c) {
var style = n.attrs.style;
if (style) {
var j, k, res;
if ((j = style.indexOf('display')) != -1)
res = style.substring(j, (k = style.indexOf(';', j)) == -1 ? style.length : k);
if ((j = style.indexOf('float')) != -1)
res += ';' + style.substring(j, (k = style.indexOf(';', j)) == -1 ? style.length : k);
n.attrs.contain = res;
}
} else f(n.children);
}
})(this.DOM);
// #endif
if (this.DOM.length) {
this.DOM[0].PoweredBy = 'Parser';
if (this.title) this.DOM[0].title = this.title;
}
return this.DOM;
}
// 设置属性
setAttr() {
var name = this.getName(this.attrName);
if (cfg.trustAttrs[name]) {
if (!this.attrVal) {
if (cfg.boolAttrs[name]) this.attrs[name] = 'T';
} else if (name == 'src') this.attrs[name] = this.getUrl(this.attrVal.replace(/&amp;/g, '&'));
else this.attrs[name] = this.attrVal;
}
this.attrVal = '';
while (blankChar[this.data[this.i]]) this.i++;
if (this.isClose()) this.setNode();
else {
this.start = this.i;
this.state = this.AttrName;
}
}
// 设置文本节点
setText() {
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 tmp = [];
for (let i = text.length, c; c = text[--i];)
if (!blankChar[c] || (!blankChar[tmp[0]] && (c = ' '))) tmp.unshift(c);
text = tmp.join('');
if (text == ' ') return;
}
// 处理实体
var siblings = this.siblings(),
i = -1,
j, en;
while (1) {
if ((i = text.indexOf('&', i + 1)) == -1) break;
if ((j = text.indexOf(';', i + 2)) == -1) break;
if (text[i + 1] == '#') {
en = parseInt((text[i + 2] == 'x' ? '0' : '') + text.substring(i + 2, j));
if (!isNaN(en)) text = text.substr(0, i) + String.fromCharCode(en) + text.substring(j + 1);
} else {
en = text.substring(i + 1, j);
// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
if (en == 'nbsp') text = text.substr(0, i) + '\xA0' + text.substr(j + 1); // 解决 &nbsp; 失效
else if (en != 'lt' && en != 'gt' && en != 'amp' && en != 'ensp' && en != 'emsp' && en != 'quot' && en != 'apos') {
i && siblings.push({
type: 'text',
text: text.substr(0, i)
})
siblings.push({
type: 'text',
text: `&${en};`,
en: 1
})
text = text.substr(j + 1);
i = -1;
}
// #endif
// #ifdef MP-BAIDU || MP-ALIPAY || MP-TOUTIAO
if (entities[en]) text = text.substr(0, i) + entities[en] + text.substr(j + 1);
// #endif
}
}
text && siblings.push({
type: 'text',
text
})
}
// 设置元素节点
setNode() {
var node = {
name: this.tagName.toLowerCase(),
attrs: this.attrs
},
close = cfg.selfClosingTags[node.name] || (this.xml && this.data[this.i] == '/');
this.attrs = {};
if (!cfg.ignoreTags[node.name]) {
this.matchAttr(node);
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.STACK[this.STACK.length - 1],
attrs = node.attrs;
if (parent && attrs.src)
if (parent.name == 'video' || parent.name == 'audio')
parent.attrs.source.push(attrs.src);
else {
var i, media = attrs.media;
if (parent.name == 'picture' && !parent.attrs.src && !(attrs.src.indexOf('.webp') && system.includes('iOS')) &&
(!media || (media.includes('px') &&
(((i = media.indexOf('min-width')) != -1 && (i = media.indexOf(':', i + 8)) != -1 && screenWidth > parseInt(
media.substr(i + 1))) ||
((i = media.indexOf('max-width')) != -1 && (i = media.indexOf(':', i + 8)) != -1 && screenWidth < parseInt(
media.substr(i + 1)))))))
parent.attrs.src = 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;
}
// 移除标签
remove(node) {
var name = node.name,
j = this.i;
while (1) {
if ((this.i = this.data.indexOf('</', this.i + 1)) == -1) {
if (name == 'pre' || name == 'svg') this.i = j;
else this.i = this.data.length;
return;
}
this.start = (this.i += 2);
while (!blankChar[this.data[this.i]] && !this.isClose()) this.i++;
if (this.getName(this.section()) == name) {
// 代码块高亮
if (name == 'pre') {
this.data = this.data.substr(0, j + 1) + cfg.highlight(this.data.substring(j + 1, this.i - 5), node.attrs) +
this.data.substr(this.i - 5);
return this.i = j;
} else if (name == 'style')
this.CssHandler.getStyle(this.data.substring(j + 1, this.i - 7));
else if (name == 'title')
this.title = this.data.substring(j + 1, this.i - 7);
if ((this.i = this.data.indexOf('>', this.i)) == -1) this.i = this.data.length;
// 处理 svg
if (name == 'svg') {
var src = this.data.substring(j, this.i + 1);
if (!node.attrs.xmlns) src = ' xmlns="http://www.w3.org/2000/svg"' + src;
var i = j;
while (this.data[j] != '<') j--;
src = this.data.substring(j, i) + src;
var parent = this.STACK[this.STACK.length - 1];
if (node.attrs.width == '100%' && parent && (parent.attrs.style || '').includes('inline'))
parent.attrs.style = 'width:300px;max-width:100%;' + parent.attrs.style;
this.siblings().push({
name: 'img',
attrs: {
src: 'data:image/svg+xml;utf8,' + src.replace(/#/g, '%23'),
ignore: 'T'
}
})
}
return;
}
}
}
// 处理属性
matchAttr(node) {
var attrs = node.attrs,
style = this.CssHandler.match(node.name, attrs, node) + (attrs.style || ''),
styleObj = {};
if (attrs.id) {
if (this.compress & 1) attrs.id = void 0;
else if (this.useAnchor) this.bubble();
}
if ((this.compress & 2) && attrs.class) attrs.class = void 0;
switch (node.name) {
case 'img':
if (attrs['data-src']) {
attrs.src = attrs.src || attrs['data-src'];
attrs['data-src'] = void 0;
}
if (attrs.src && !attrs.ignore) {
if (this.bubble()) attrs.i = (this.imgNum++).toString();
else attrs.ignore = 'T';
}
break;
case 'a':
case 'ad':
// #ifdef APP-PLUS
case 'iframe':
case 'embed':
// #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 'video':
case 'audio':
if (!attrs.id) attrs.id = node.name + (++this[`${node.name}Num`]);
else this[`${node.name}Num`]++;
if (node.name == 'video') {
if (attrs.width) {
style = `width:${parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px')};${style}`;
attrs.width = void 0;
}
if (attrs.height) {
style = `height:${parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px')};${style}`;
attrs.height = void 0;
}
if (this.videoNum > 3) node.lazyLoad = true;
}
attrs.source = [];
if (attrs.src) attrs.source.push(attrs.src);
if (!attrs.controls && !attrs.autoplay)
console.warn(`存在没有 controls 属性的 ${node.name} 标签,可能导致无法播放`, node);
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.c = void 0;
break;
}
}
if (attrs.align) {
styleObj['text-align'] = attrs.align;
attrs.align = void 0;
}
// 压缩 style
var styles = style.replace(/&quot;/g, '"').replace(/&amp;/g, '&').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.includes('-webkit') || value.includes('-moz') || value.includes('-ms') || value.includes('-o') || value
.includes(
'safe'))
style += `;${key}:${value}`;
else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import'))
styleObj[key] = value;
}
if (node.name == 'img' && parseInt(styleObj.width || attrs.width) > screenWidth)
styleObj.height = 'auto';
for (var key in styleObj) {
var value = styleObj[key];
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($) * screenWidth / 750 + 'px');
else if (key == 'white-space' && value.includes('pre'))
this.pre = node.pre = true;
style += `;${key}:${value}`;
}
style = style.substr(1);
if (style) attrs.style = style;
}
// 节点出栈处理
popNode(node) {
// 空白符处理
if (node.pre) {
node.pre = this.pre = void 0;
for (let i = this.STACK.length; i--;)
if (this.STACK[i].pre)
this.pre = true;
}
if (node.name == 'head' || (cfg.filter && cfg.filter(node, this) == false))
return this.siblings().pop();
var attrs = node.attrs;
// 替换一些标签名
if (node.name == 'picture') {
node.name = 'img';
if (!attrs.src && (node.children[0] || '').name == 'img')
attrs.src = node.children[0].attrs.src;
if (attrs.src && !attrs.ignore)
attrs.i = (this.imgNum++).toString();
return node.children = void 0;
}
if (cfg.blockTags[node.name]) node.name = 'div';
else if (!cfg.trustTags[node.name]) node.name = 'span';
// 处理列表
if (node.c) {
if (node.name == 'ul') {
var floor = 1;
for (let i = this.STACK.length; i--;)
if (this.STACK[i].name == 'ul') floor++;
if (floor != 1)
for (let i = node.children.length; i--;)
node.children[i].floor = floor;
} else if (node.name == 'ol') {
for (let i = 0, num = 1, child; child = node.children[i++];)
if (child.name == 'li') {
child.type = 'ol';
child.num = ((num, type) => {
if (type == 'a') return String.fromCharCode(97 + (num - 1) % 26);
if (type == 'A') return String.fromCharCode(65 + (num - 1) % 26);
if (type == 'i' || type == 'I') {
num = (num - 1) % 99 + 1;
var one = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'],
ten = ['X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'],
res = (ten[Math.floor(num / 10) - 1] || '') + (one[num % 10 - 1] || '');
if (type == 'i') return res.toLowerCase();
return res;
}
return num;
})(num++, attrs.type) + '.';
}
}
}
// 处理表格的边框
if (node.name == 'table') {
var padding = attrs.cellpadding,
spacing = attrs.cellspacing,
border = attrs.border;
if (node.c) {
this.bubble();
if (!padding) padding = 2;
if (!spacing) spacing = 2;
}
if (border) attrs.style = `border:${border}px solid gray;${attrs.style || ''}`;
if (spacing) attrs.style = `border-spacing:${spacing}px;${attrs.style || ''}`;
if (border || padding)
(function f(ns) {
for (var i = 0, n; n = ns[i]; i++) {
if (n.name == 'th' || n.name == 'td') {
if (border) n.attrs.style = `border:${border}px solid gray;${n.attrs.style}`;
if (padding) n.attrs.style = `padding:${padding}px;${n.attrs.style}`;
} else f(n.children || []);
}
})(node.children)
}
this.CssHandler.pop && this.CssHandler.pop(node);
// 自动压缩
if (node.name == 'div' && !Object.keys(attrs).length) {
var siblings = this.siblings();
if (node.children.length == 1 && node.children[0].name == 'div')
siblings[siblings.length - 1] = node.children[0];
}
}
// 工具函数
bubble() {
for (var i = this.STACK.length, item; item = this.STACK[--i];) {
if (cfg.richOnlyTags[item.name]) {
if (item.name == 'table' && !Object.hasOwnProperty.call(item, 'c')) item.c = 1;
return false;
}
item.c = 1;
}
return true;
}
getName = val => this.xml ? val : val.toLowerCase();
getUrl(url) {
if (url[0] == '/') {
if (url[1] == '/') url = this.protocol + ':' + 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;
}
isClose = () => this.data[this.i] == '>' || (this.data[this.i] == '/' && this.data[this.i + 1] == '>');
section = () => this.data.substring(this.start, this.i);
siblings = () => this.STACK.length ? this.STACK[this.STACK.length - 1].children : this.DOM;
// 状态机
Text(c) {
if (c == '<') {
var next = this.data[this.i + 1],
isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
if (isLetter(next)) {
this.setText();
this.start = this.i + 1;
this.state = this.TagName;
} else if (next == '/') {
this.setText();
if (isLetter(this.data[++this.i + 1])) {
this.start = this.i + 1;
this.state = this.EndTag;
} else
this.Comment();
} else if (next == '!') {
this.setText();
this.Comment();
}
}
}
Comment() {
var key;
if (this.data.substring(this.i + 2, this.i + 4) == '--') key = '-->';
else if (this.data.substring(this.i + 2, this.i + 9) == '[CDATA[') key = ']]>';
else key = '>';
if ((this.i = this.data.indexOf(key, this.i + 2)) == -1) this.i = this.data.length;
else this.i += key.length - 1;
this.start = this.i + 1;
this.state = this.Text;
}
TagName(c) {
if (blankChar[c]) {
this.tagName = this.section();
while (blankChar[this.data[this.i]]) this.i++;
if (this.isClose()) this.setNode();
else {
this.start = this.i;
this.state = this.AttrName;
}
} else if (this.isClose()) {
this.tagName = this.section();
this.setNode();
}
}
AttrName(c) {
var blank = blankChar[c];
if (blank) {
this.attrName = this.section();
c = this.data[this.i];
}
if (c == '=') {
if (!blank) this.attrName = this.section();
while (blankChar[this.data[++this.i]]);
this.start = this.i--;
this.state = this.AttrValue;
} else if (blank) this.setAttr();
else if (this.isClose()) {
this.attrName = this.section();
this.setAttr();
}
}
AttrValue(c) {
if (c == '"' || c == "'") {
this.start++;
if ((this.i = this.data.indexOf(c, this.i + 1)) == -1) return this.i = this.data.length;
this.attrVal = this.section();
this.i++;
} else {
for (; !blankChar[this.data[this.i]] && !this.isClose(); this.i++);
this.attrVal = this.section();
}
this.setAttr();
}
EndTag(c) {
if (blankChar[c] || c == '>' || c == '/') {
var name = this.getName(this.section());
for (var i = this.STACK.length; i--;)
if (this.STACK[i].name == name) break;
if (i != -1) {
var node;
while ((node = this.STACK.pop()).name != name);
this.popNode(node);
} else if (name == 'p' || name == 'br')
this.siblings().push({
name,
attrs: {}
});
this.i = this.data.indexOf('>', this.i);
this.start = this.i + 1;
if (this.i == -1) this.i = this.data.length;
else this.state = this.Text;
}
}
}
module.exports = MpHtmlParser;
+80
View File
@@ -0,0 +1,80 @@
/* 配置文件 */
// #ifdef MP-WEIXIN
const canIUse = wx.canIUse('editor'); // 高基础库标识,用于兼容
// #endif
module.exports = {
// 过滤器函数
filter: null,
// 代码高亮函数
highlight: null,
// 文本处理函数
onText: null,
blankChar: makeMap(' ,\xA0,\t,\r,\n,\f'),
// 块级标签,将被转为 div
blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,section' + (
// #ifdef MP-WEIXIN
canIUse ? '' :
// #endif
',pre')),
// 将被移除的标签
ignoreTags: makeMap(
'area,base,basefont,canvas,command,frame,input,isindex,keygen,link,map,meta,param,script,source,style,svg,textarea,title,track,use,wbr'
// #ifdef MP-WEIXIN
+ (canIUse ? ',rp' : '')
// #endif
// #ifndef APP-PLUS
+ ',embed,iframe'
// #endif
),
// 只能被 rich-text 显示的标签
richOnlyTags: makeMap('a,colgroup,fieldset,legend,picture,table'
// #ifdef MP-WEIXIN
+ (canIUse ? ',bdi,bdo,caption,rt,ruby' : '')
// #endif
),
// 自闭合的标签
selfClosingTags: makeMap(
'area,base,basefont,br,col,circle,ellipse,embed,frame,hr,img,input,isindex,keygen,line,link,meta,param,path,polygon,rect,source,track,use,wbr'
),
// 信任的属性
trustAttrs: makeMap(
'align,alt,app-id,author,autoplay,border,cellpadding,cellspacing,class,color,colspan,controls,data-src,dir,face,height,href,id,ignore,loop,media,muted,name,path,poster,rowspan,size,span,src,start,style,type,unit-id,width,xmlns'
),
// bool 型的属性
boolAttrs: makeMap('autoplay,controls,ignore,loop,muted'),
// 信任的标签
trustTags: makeMap(
'a,abbr,ad,audio,b,blockquote,br,code,col,colgroup,dd,del,dl,dt,div,em,fieldset,h1,h2,h3,h4,h5,h6,hr,i,img,ins,label,legend,li,ol,p,q,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video'
// #ifdef MP-WEIXIN
+ (canIUse ? ',bdi,bdo,caption,pre,rt,ruby' : '')
// #endif
// #ifdef APP-PLUS
+ ',embed,iframe'
// #endif
),
// 默认的标签样式
userAgentStyles: {
address: 'font-style:italic',
big: 'display:inline;font-size:1.2em',
blockquote: 'background-color:#f6f6f6;border-left:3px solid #dbdbdb;color:#6c6c6c;padding:5px 0 5px 10px',
caption: 'display:table-caption;text-align:center',
center: 'text-align:center',
cite: 'font-style:italic',
dd: 'margin-left:40px',
img: 'max-width:100%',
mark: 'background-color:yellow',
picture: 'max-width:100%',
pre: 'font-family:monospace;white-space:pre;overflow:scroll',
s: 'text-decoration:line-through',
small: 'display:inline;font-size:0.8em',
u: 'text-decoration:underline'
}
}
function makeMap(str) {
var map = {},
list = str.split(',');
for (var i = list.length; i--;)
map[list[i]] = true;
return map;
}
+35
View File
@@ -0,0 +1,35 @@
var inlineTags = {
abbr: 1,
b: 1,
big: 1,
code: 1,
del: 1,
em: 1,
i: 1,
ins: 1,
label: 1,
q: 1,
small: 1,
span: 1,
strong: 1
}
export default {
// 从顶层标签的样式中取出一些给 rich-text
getStyle: function(style) {
if (style) {
var i, j, res = '';
if ((i = style.indexOf('display')) != -1)
res = style.substring(i, (j = style.indexOf(';', i)) == -1 ? style.length : j);
if ((i = style.indexOf('float')) != -1)
res += ';' + style.substring(i, (j = style.indexOf(';', i)) == -1 ? style.length : j);
return res;
}
},
getNode: function(item) {
return [item];
},
// 是否通过 rich-text 显示
useRichText: function(item) {
return !item.c && !inlineTags[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1;
}
}
+44
View File
@@ -0,0 +1,44 @@
var inlineTags = {
abbr: 1,
b: 1,
big: 1,
code: 1,
del: 1,
em: 1,
i: 1,
ins: 1,
label: 1,
q: 1,
small: 1,
span: 1,
strong: 1
}
module.exports = {
// 从顶层标签的样式中取出一些给 rich-text
getStyle: function(style) {
if (style) {
var i, j, res = '';
if ((i = style.indexOf('display')) != -1)
res = style.substring(i, (j = style.indexOf(';', i)) == -1 ? style.length : j);
if ((i = style.indexOf('float')) != -1)
res += ';' + style.substring(i, (j = style.indexOf(';', i)) == -1 ? style.length : j);
return res;
}
},
// 处理懒加载
getNode: function(item, imgLoad) {
if (!imgLoad && item.attrs.i != '0') {
var img = {
name: 'img',
attrs: JSON.parse(JSON.stringify(item.attrs))
}
delete img.attrs.src;
img.attrs.style += ';width:20px;height:20px';
return [img];
} else return [item];
},
// 是否通过 rich-text 显示
useRichText: function(item) {
return !item.c && !inlineTags[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1;
}
}
+476
View File
@@ -0,0 +1,476 @@
<!--
trees 递归显示组件
github:https://github.com/jin-yufeng/Parser
docs:https://jin-yufeng.github.io/Parser
插件市场:https://ext.dcloud.net.cn/plugin?id=805
author:JinYufeng
update:2020/04/13
-->
<template>
<view class="interlayer">
<block v-for="(n, index) in nodes" v-bind:key="index">
<!--图片-->
<!--#ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY || APP-PLUS-->
<rich-text v-if="n.name=='img'" :id="n.attrs.id" class="_img" :style="''+handler.getStyle(n.attrs.style)" :nodes="handler.getNode(n,!lazyLoad||imgLoad)"
:data-attrs="n.attrs" @tap="imgtap" @longpress="imglongtap" />
<!--#endif-->
<!--#ifdef MP-BAIDU || MP-TOUTIAO-->
<rich-text v-if="n.name=='img'" :id="n.attrs.id" class="_img" :style="n.attrs.contain" :nodes='[n]' :data-attrs="n.attrs"
@tap="imgtap" @longpress="imglongtap" />
<!--#endif-->
<!--文本-->
<!--#ifdef MP-WEIXIN || MP-QQ || APP-PLUS-->
<rich-text v-else-if="n.decode" class="_entity" :nodes="[n]"></rich-text>
<!--#endif-->
<text v-else-if="n.type=='text'" decode>{{n.text}}</text>
<text v-else-if="n.name=='br'">\n</text>
<!--视频-->
<view v-else-if="n.name=='video'">
<view v-if="(!loadVideo||n.lazyLoad)&&!(controls[n.attrs.id]&&controls[n.attrs.id].play)" :id="n.attrs.id" :class="'_video '+(n.attrs.class||'')"
:style="n.attrs.style" @tap="_loadVideo" />
<video v-else :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :autoplay="n.attrs.autoplay||(controls[n.attrs.id]&&controls[n.attrs.id].play)"
:controls="n.attrs.controls" :loop="n.attrs.loop" :muted="n.attrs.muted" :poster="n.attrs.poster" :src="n.attrs.source[(controls[n.attrs.id]&&controls[n.attrs.id].index)||0]"
:unit-id="n.attrs['unit-id']" :data-id="n.attrs.id" data-from="video" data-source="source" @error="error" @play="play" />
</view>
<!--音频-->
<audio v-else-if="n.name=='audio'" :class="n.attrs.class" :style="n.attrs.style" :author="n.attrs.author" :autoplay="n.attrs.autoplay"
:controls="n.attrs.controls" :loop="n.attrs.loop" :name="n.attrs.name" :poster="n.attrs.poster" :src="n.attrs.source[(controls[n.attrs.id]&&controls[n.attrs.id].index)||0]"
:data-id="n.attrs.id" data-from="audio" data-source="source" @error="error" @play="play" />
<!--链接-->
<view v-else-if="n.name=='a'" :class="'_a '+(n.attrs.class||'')" hover-class="_hover" :style="n.attrs.style"
:data-attrs="n.attrs" @tap="linkpress">
<trees class="_span" :nodes="n.children" />
</view>
<!--广告(按需打开注释)-->
<!--#ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO-->
<!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :unit-id="n.attrs['unit-id']"
data-from="ad" @error="error" />-->
<!--#endif-->
<!--#ifdef MP-BAIDU-->
<!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :appid="n.attrs.appid"
:apid="n.attrs.apid" :type="n.attrs.type" data-from="ad" @error="error" />-->
<!--#endif-->
<!--#ifdef APP-PLUS-->
<!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :adpid="n.attrs.adpid"
data-from="ad" @error="error" />-->
<!--#endif-->
<!--列表-->
<view v-else-if="n.name=='li'" :id="n.attrs.id" :class="n.attrs.class" :style="(n.attrs.style||'')+';display:flex'">
<view v-if="n.type=='ol'" class="_ol-bef">{{n.num}}</view>
<view v-else class="_ul-bef">
<view v-if="n.floor%3==0" class="_ul-p1">█</view>
<view v-else-if="n.floor%3==2" class="_ul-p2" />
<view v-else class="_ul-p1" style="border-radius:50%">█</view>
</view>
<!--#ifdef MP-ALIPAY-->
<view class="_li">
<trees :nodes="n.children" />
</view>
<!--#endif-->
<!--#ifndef MP-ALIPAY-->
<trees class="_li" :nodes="n.children" :lazyLoad="lazyLoad" :loadVideo="loadVideo" />
<!--#endif-->
</view>
<!--表格-->
<view v-else-if="n.name=='table'&&n.c" :id="n.attrs.id" :class="n.attrs.class" :style="(n.attrs.style||'')+';display:table'">
<view v-for="(tbody, i) in n.children" v-bind:key="i" :class="tbody.attrs.class" :style="(tbody.attrs.style||'')+(tbody.name[0]=='t'?';display:table-'+(tbody.name=='tr'?'row':'row-group'):'')">
<view v-for="(tr, j) in tbody.children" v-bind:key="j" :class="tr.attrs.class" :style="(tr.attrs.style||'')+(tr.name[0]=='t'?';display:table-'+(tr.name=='tr'?'row':'cell'):'')">
<trees v-if="tr.name=='td'" :nodes="tr.children" :lazyLoad="lazyLoad" :loadVideo="loadVideo" />
<block v-else>
<!--#ifdef MP-ALIPAY-->
<view v-for="(td, k) in tr.children" v-bind:key="k" :class="td.attrs.class" :style="(td.attrs.style||'')+(td.name[0]=='t'?';display:table-'+(td.name=='tr'?'row':'cell'):'')">
<trees :nodes="td.children" />
</view>
<!--#endif-->
<!--#ifndef MP-ALIPAY-->
<trees v-for="(td, k) in tr.children" v-bind:key="k" :class="td.attrs.class" :style="(td.attrs.style||'')+(td.name[0]=='t'?';display:table-'+(td.name=='tr'?'row':'cell'):'')"
:nodes="td.children" :lazyLoad="lazyLoad" :loadVideo="loadVideo" />
<!--#endif-->
</block>
</view>
</view>
</view>
<!--#ifdef APP-PLUS-->
<iframe v-else-if="n.name=='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen" :frameborder="n.attrs.frameborder"
:width="n.attrs.width" :height="n.attrs.height" :src="n.attrs.src" />
<embed v-else-if="n.name=='embed'" :style="n.attrs.style" :width="n.attrs.width" :height="n.attrs.height" :src="n.attrs.src" />
<!--#endif-->
<!--富文本-->
<!--#ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY || APP-PLUS-->
<rich-text v-else-if="handler.useRichText(n)" :id="n.attrs.id" :class="'_p __'+n.name" :nodes="[n]" />
<!--#endif-->
<!--#ifdef MP-BAIDU || MP-TOUTIAO-->
<rich-text v-else-if="!(n.c||n.continue)" :id="n.attrs.id" :class="_p" :style="n.attrs.contain" :nodes="[n]" />
<!--#endif-->
<!--#ifdef MP-ALIPAY-->
<view v-else :id="n.attrs.id" :class="'_'+n.name+' '+(n.attrs.class||'')" :style="n.attrs.style">
<trees :nodes="n.children" />
</view>
<!--#endif-->
<!--#ifndef MP-ALIPAY-->
<trees v-else :class="(n.attrs.id||'')+' _'+n.name+' '+(n.attrs.class||'')" :style="n.attrs.style" :nodes="n.children"
:lazyLoad="lazyLoad" :loadVideo="loadVideo" />
<!--#endif-->
</block>
</view>
</template>
<script module="handler" lang="wxs" src="./handler.wxs"></script>
<script module="handler" lang="sjs" src="./handler.sjs"></script>
<script>
global.Parser = {};
import trees from './trees'
export default {
components: {
trees
},
name: 'trees',
data() {
return {
controls: {},
// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
imgLoad: false,
// #endif
// #ifndef APP-PLUS
loadVideo: true
// #endif
}
},
props: {
nodes: Array,
// #ifdef MP-WEIXIN || MP-QQ || H5 || APP-PLUS
lazyLoad: Boolean,
// #endif
// #ifdef APP-PLUS
loadVideo: Boolean
// #endif
},
mounted() {
// 获取顶层组件
this.top = this.$parent;
while (this.top.$options.name != 'parser') {
if (this.top.top) {
this.top = this.top.top;
break;
}
this.top = this.top.$parent;
}
},
// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
beforeDestroy() {
if (this.observer)
this.observer.disconnect();
},
// #endif
methods: {
// #ifndef MP-ALIPAY
play(e) {
if (this.top.videoContexts.length > 1 && this.top.autopause)
for (var i = this.top.videoContexts.length; i--;)
if (this.top.videoContexts[i].id != e.currentTarget.dataset.id)
this.top.videoContexts[i].pause();
},
// #endif
imgtap(e) {
var attrs = e.currentTarget.dataset.attrs;
if (!attrs.ignore) {
var preview = true, data = {
id: e.target.id,
src: attrs.src,
ignore: () => preview = false
};
global.Parser.onImgtap && global.Parser.onImgtap(data);
this.top.$emit('imgtap', data);
if (preview) {
var urls = this.top.imgList,
current = urls[attrs.i] ? parseInt(attrs.i) : (urls = [attrs.src], 0);
uni.previewImage({
current,
urls
})
}
}
},
imglongtap(e) {
var attrs = e.item.dataset.attrs;
if (!attrs.ignore)
this.top.$emit('imglongtap', {
id: e.target.id,
src: attrs.src
})
},
linkpress(e) {
var jump = true,
attrs = e.currentTarget.dataset.attrs;
attrs.ignore = () => jump = false;
global.Parser.onLinkpress && global.Parser.onLinkpress(attrs);
this.top.$emit('linkpress', attrs);
if (jump) {
// #ifdef MP
if (attrs['app-id']) {
return uni.navigateToMiniProgram({
appId: attrs['app-id'],
path: attrs.path
})
}
// #endif
if (attrs.href) {
if (attrs.href[0] == '#') {
if (this.top.useAnchor)
this.top.navigateTo({
id: attrs.href.substring(1)
})
} else if (attrs.href.indexOf('http') == 0 || attrs.href.indexOf('//') == 0) {
// #ifdef APP-PLUS
plus.runtime.openWeb(attrs.href);
// #endif
// #ifndef APP-PLUS
uni.setClipboardData({
data: attrs.href,
success: () =>
uni.showToast({
title: '链接已复制'
})
})
// #endif
} else
uni.navigateTo({
url: attrs.href
})
}
}
},
error(e) {
var context, target = e.currentTarget,
source = target.dataset.from;
if (source == 'video' || source == 'audio') {
// 加载其他 source
var index = this.controls[target.id] ? this.controls[target.id].index + 1 : 1;
if (index < target.dataset.source.length)
this.$set(this.controls, target.id + '.index', index);
if (source == 'video') context = uni.createVideoContext(target.id, this);
}
this.top && this.top.$emit('error', {
source,
target,
errMsg: e.detail.errMsg,
errCode: e.detail.errCode,
context
});
},
_loadVideo(e) {
this.$set(this.controls, e.currentTarget.id, {
play: true,
index: 0
})
}
}
}
</script>
<style>
/* 在这里引入自定义样式 */
/* 链接和图片效果 */
._a {
display: inline;
color: #366092;
word-break: break-all;
padding: 1.5px 0 1.5px 0;
}
._hover {
opacity: 0.7;
text-decoration: underline;
}
._img {
display: inline-block;
text-indent: 0;
}
/* #ifdef MP-WEIXIN */
:host {
display: inline;
}
/* #endif */
/* #ifdef MP */
.interlayer {
align-content: inherit;
align-items: inherit;
display: inherit;
flex-direction: inherit;
flex-wrap: inherit;
justify-content: inherit;
width: 100%;
white-space: inherit;
}
/* #endif */
._b,
._strong {
font-weight: bold;
}
._blockquote,
._div,
._p,
._ol,
._ul,
._li {
display: block;
}
._code {
font-family: monospace;
}
._del {
text-decoration: line-through;
}
._em,
._i {
font-style: italic;
}
._h1 {
font-size: 2em;
}
._h2 {
font-size: 1.5em;
}
._h3 {
font-size: 1.17em;
}
._h5 {
font-size: 0.83em;
}
._h6 {
font-size: 0.67em;
}
._h1,
._h2,
._h3,
._h4,
._h5,
._h6 {
display: block;
font-weight: bold;
}
._ins {
text-decoration: underline;
}
._li {
flex: 1;
width: 0;
}
._ol-bef {
margin-right: 5px;
text-align: right;
width: 36px;
}
._ul-bef {
line-height: normal;
margin: 0 12px 0 23px;
}
._ol-bef,
._ul_bef {
flex: none;
user-select: none;
}
._ul-p1 {
display: inline-block;
height: 0.3em;
line-height: 0.3em;
overflow: hidden;
width: 0.3em;
}
._ul-p2 {
border: 0.05em solid black;
border-radius: 50%;
display: inline-block;
height: 0.23em;
width: 0.23em;
}
._q::before {
content: '"';
}
._q::after {
content: '"';
}
._sub {
font-size: smaller;
vertical-align: sub;
}
._sup {
font-size: smaller;
vertical-align: super;
}
/* #ifndef MP-WEIXIN */
._abbr,
._b,
._code,
._del,
._em,
._i,
._ins,
._label,
._q,
._span,
._strong,
._sub,
._sup {
display: inline;
}
/* #endif */
/* #ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY */
.__bdo,
.__bdi,
.__ruby,
.__rt,
._entity {
display: inline-block;
}
/* #endif */
._video {
background-color: black;
display: inline-block;
height: 225px;
position: relative;
width: 300px;
}
._video::after {
border-color: transparent transparent transparent white;
border-style: solid;
border-width: 15px 0 15px 30px;
content: '';
left: 50%;
margin: -15px 0 0 -15px;
position: absolute;
top: 50%;
}
</style>
+272
View File
@@ -0,0 +1,272 @@
<template>
<view v-if="isUp">
<view class="mobile-bg" v-if="isShow" @click="close"></view>
<view class="mobile-mask animated" :class="{slideInUp:isUp}" :style="{position:isPos?'fixed':'static'}">
<view class="input-item">
<input type="text" v-model="account" placeholder="输入手机号" />
</view>
<view class="input-item">
<input type="text" v-model="codeNum" placeholder="输入验证码" />
<button class="code" :disabled="disabled" @click="code">{{text}}</button>
</view>
<view class="sub_btn" @click="loginBtn">{{(!userInfo.phone && isLogin) || (userInfo.phone && isLogin)?'立即绑定':'立即登录'}}</view>
</view>
</view>
</template>
<script>
const app = getApp();
import sendVerifyCode from "@/mixins/SendVerifyCode";
import {mapGetters} from "vuex";
import * as AuthApi from "@/api/member/auth";
import * as UserApi from "@/api/member/user";
import * as BrokerageAPI from '@/api/trade/brokerage.js'
import { iosBinding } from '@/api/public';
const BACK_URL = "login_back_url";
export default {
name: 'login_mobile',
computed: mapGetters(['userInfo','isLogin']),
props: {
isUp: {
type: Boolean,
default: false,
},
authKey: {
type: String,
default: '',
},
socialCode: {
type: String,
default: '',
},
socialState: {
type: String,
default: '',
},
isShow: {
type: Boolean,
default: true
},
isPos: {
type: Boolean,
default: true
},
appleShow: {
type: String,
default: ''
},
platform: {
type: String,
default: '',
}
},
data() {
return {
account: '',
codeNum: '',
isApp: 0
}
},
mixins: [sendVerifyCode],
methods: {
// 获取验证码
async code() {
if (!this.account) {
return this.$util.Tips({
title: '请填写手机号码'
});
}
if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(this.account)) {
return this.$util.Tips({
title: '请输入正确的手机号码'
});
}
await AuthApi.sendSmsCode(this.account, 1)
.then(res => {
this.$util.Tips({title:res.message});
this.sendCode();
})
.catch(err => {
return this.$util.Tips({
title: err
});
});
},
close() {
this.$emit('close', false)
},
// 登录
loginBtn() {
if (!this.account) {
return this.$util.Tips({
title: '请填写手机号码'
});
}
if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(this.account)) {
return this.$util.Tips({
title: '请输入正确的手机号码'
});
}
if (!this.codeNum) return this.$util.Tips({
title: '请填写验证码'
});
if (!/^[\w\d]+$/i.test(this.codeNum)) {
return this.$util.Tips({
title: '请输入正确的验证码'
});
}
uni.showLoading({
title: !this.userInfo.phone && this.isLogin?'正在绑定中':'正在登录中'
});
if (!this.userInfo.phone && this.isLogin) {
// TODO 芋艿:不晓得它要搞啥哈???
iosBinding({
captcha: this.codeNum,
phone: this.account
}).then(res => {
this.$util.Tips({
title: '绑定手机号成功',
icon: 'success'
}, {
tab: 3
})
this.isApp = 1;
this.getUserInfo();
}).catch(error => {
uni.hideLoading()
this.$util.Tips({
title: error
})
})
} else {
AuthApi.smsLogin({
mobile: this.account,
code: this.codeNum,
socialType: 31,
socialCode: this.socialCode,
socialState: this.socialState
}).then(res => {
// TODO 芋艿:refreshToken 机制
let data = res.data;
this.$store.commit("LOGIN", {
'token': res.data.accessToken
});
this.getUserInfo(data);
this.bindBrokerUser();
}).catch(error => {
uni.hideLoading()
this.$util.Tips({
title: error
})
})
}
},
/**
* 获取个人用户信息
*/
getUserInfo: function(data) {
this.$store.commit("SETUID", data.userId);
this.$store.commit("OPENID", data.openid);
UserApi.getUserInfo().then(res => {
uni.hideLoading();
this.$store.commit("UPDATE_USERINFO", res.data);
// 调回登录前页面
// #ifdef MP
this.$util.Tips({
title: '登录成功',
icon: 'success'
}, {
tab: 3
})
this.close()
// #endif
// #ifdef H5
this.$emit('wechatPhone', true)
// #endif
});
},
bindBrokerUser() {
const spread = this.$Cache.get("spread");
if (spread > 0) {
BrokerageAPI.bindBrokerageUser(spread)
}
}
}
}
</script>
<style lang="stylus" scoped>
.mobile-bg {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
}
.isPos {
position: static;
}
.mobile-mask {
z-index: 20;
// position: fixed;
left: 0;
bottom: 0;
width: 100%;
padding: 67rpx 30rpx;
background: #fff;
.input-item {
display: flex;
justify-content: space-between;
width: 100%;
height: 86rpx;
margin-bottom: 38rpx;
input {
flex: 1;
display: block;
height: 100%;
padding-left: 40rpx;
border-radius: 43rpx;
border: 1px solid #DCDCDC;
}
.code {
display: flex;
align-items: center;
justify-content: center;
width: 220rpx;
height: 86rpx;
margin-left: 30rpx;
background: rgba(233, 51, 35, 0.05);
font-size: 28rpx;
color: $theme-color;
border-radius: 43rpx;
&[disabled] {
background: rgba(0, 0, 0, 0.05);
color: #999;
}
}
}
.sub_btn {
width: 690rpx;
height: 86rpx;
line-height: 86rpx;
margin-top: 60rpx;
background: #E93323;
border-radius: 43rpx;
color: #fff;
font-size: 28rpx;
text-align: center;
}
}
.animated {
animation-duration: .4s
}
</style>
+160
View File
@@ -0,0 +1,160 @@
<template>
<view v-if="isPhoneBox">
<view class="mobile-bg" @click="close"></view>
<view class="mobile-mask animated" :class="{slideInUp:isUp}">
<view class="info-box">
<image :src="logoUrl"></image>
<view class="title">获取授权</view>
<view class="txt">获取微信的手机号授权</view>
</view>
<button class="sub_btn" open-type="getPhoneNumber" @getphonenumber="getphonenumber">获取微信手机号</button>
</view>
</view>
</template>
<script>
const app = getApp();
import Routine from '@/libs/routine';
import {
loginMobile,
registerVerify,
getCodeApi,
getUserInfo
} from "@/api/user";
import { getLogo, getUserPhone } from '@/api/public';
export default{
name:'routine_phone',
props:{
isPhoneBox:{
type:Boolean,
default:false,
},
logoUrl:{
type:String,
default:'',
},
authKey:{
type:String,
default:'',
}
},
data(){
return {
keyCode:'',
account:'',
codeNum:'',
isStatus:false
}
},
mounted() {
},
methods:{
// #ifdef MP
// 小程序获取手机号码
getphonenumber(e){
uni.showLoading({ title: '加载中' });
Routine.getCode()
.then(code => {
this.getUserPhoneNumber(e.detail.encryptedData, e.detail.iv, code);
})
.catch(error => {
uni.hideLoading();
});
},
// 小程序获取手机号码回调
getUserPhoneNumber(encryptedData, iv, code) {
getUserPhone({
encryptedData: encryptedData,
iv: iv,
code: code,
key:this.authKey,
type: 'routine'
})
.then(res => {
this.$store.commit('LOGIN', {
token: res.data.token
});
this.$store.commit("SETUID", res.data.uid);
this.getUserInfo();
})
.catch(res => {
uni.hideLoading();
this.$util.Tips({
title: res
});
});
},
/**
* 获取个人用户信息
*/
getUserInfo: function() {
let that = this;
getUserInfo().then(res => {
uni.hideLoading();
that.userInfo = res.data
that.$store.commit("UPDATE_USERINFO", res.data);
that.isStatus = true
this.close()
});
},
// #endif
close(){
this.$emit('close',{isStatus:this.isStatus})
}
}
}
</script>
<style lang="scss">
.mobile-bg{
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
}
.mobile-mask {
z-index: 20;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
padding: 67rpx 30rpx;
background: #fff;
.info-box{
display:flex;
flex-direction: column;
align-items: center;
justify-content: center;
image{
width: 150rpx;
height: 150rpx;
border-radius: 10rpx;
}
.title{
margin-top: 30rpx;
margin-bottom: 20rpx;
font-size: 36rpx;
}
.txt{
font-size: 30rpx;
color: #868686;
}
}
.sub_btn{
width: 690rpx;
height: 86rpx;
line-height: 86rpx;
margin-top: 60rpx;
background: $theme-color;
border-radius: 43rpx;
color: #fff;
font-size: 28rpx;
text-align: center;
}
}
.animated{
animation-duration:.4s
}
</style>
+406
View File
@@ -0,0 +1,406 @@
.mpvue-calendar {
margin:auto;
width: 100%;
min-width:350px;
background: #fff;
user-select:none;
position: relative;
}
.calendar-tools{
height:40px;
font-size: 20px;
line-height: 40px;
color:#5e7a88;
box-shadow: 0px 4px 8px rgba(25, 47, 89, 0.1);
margin-bottom: 20px;
border-top: 1px solid rgba(200, 200, 200, .1);
}
.calendar-tools span{
cursor: pointer;
}
.calendar-prev{
width: 14.28571429%;
float:left;
text-align: center;
}
.calendar-prev img, .calendar-next img{
width: 34px;
height: 34px;
}
.calendar-info{
font-size:16px;
line-height: 1.3;
text-align: center;
width: 220px;
margin: 0 auto;
}
.calendar-info>div.mc-month{
margin:auto;
height:24px;
width:100px;
text-align: center;
color:#5e7a88;
overflow: hidden;
position: relative;
}
.calendar-info>div.mc-month .mc-month-inner{
position: absolute;
left:0;
top:0;
height:480px;
}
.month-transition{
transition:top .5s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.calendar-info .mc-month-text{
display:block;
font-size:28px;
height:40px;
width:200px;
overflow:hidden;
text-align:center;
}
.calendar-info>div.mc-month .mc-month-inner>span{
display: block;
font-size: 14px;
height:24px;
line-height:24px;
width:100px;
overflow: hidden;
text-align: center;
}
.calendar-info>div.mc-year{
font-size:10px;
line-height: 1;
color:#999;
}
.calendar-next{
width: 14.28571429%;
float:right;
text-align: center;
}
.mpvue-calendar table {
clear: both;
width: 100%;
margin-bottom:10px;
border-collapse: collapse;
color: #444444;
}
.mpvue-calendar td {
margin:2px !important;
padding: 4px;
width: 14.28571429%;
box-sizing: border-box;
text-align: center;
vertical-align: middle;
font-size:14px;
cursor: pointer;
position: relative;
vertical-align: top;
}
.mpvue-calendar td.mc-week{
font-size:10px;
pointer-events:none !important;
cursor: default !important;
}
.mpvue-calendar td.disabled {
color: #ccc;
}
.mpvue-calendar td.disabled div{
color: #ccc;
}
.mpvue-calendar td span{
display:block;
height:100%;
width:100%;
margin:0px auto;
border-radius:50%;
position: relative;
z-index: 3;
}
.mpvue-calendar td:not(.disabled) span.mc-date-red{
color:#ea6151;
}
.mc-today{
color: #3b75fb;
}
.mpvue-calendar td.selected span{
background-color: #3b75fb;
color: #fff;
border-radius: 50%;
}
.mpvue-calendar td .mc-text{
box-sizing: border-box;
height: 0.7em;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
position: absolute;
bottom: 0px;
left: 0;
right: 0;
text-align: center;
font-size: 0.7em;
line-height: 0.7em;
z-index: 4;
}
.mpvue-calendar td .isGregorianFestival,
.mpvue-calendar td .isTerm,
.mpvue-calendar td .isLunarFestival{
color:#ea6151;
}
.mpvue-calendar td.selected span.mc-date-red{
background-color: #3b75fb;
color: #fff;
}
.selected .mc-text {
color: #fff !important;
}
.mpvue-calendar .lunarStyle .mc-text{
overflow: visible;
bottom: 20%;
}
.mpvue-calendar thead td {
text-transform: uppercase;
height:30px;
vertical-align: middle;
}
.mc-head {
margin-bottom: 10px;
}
.mc-head div {
overflow: hidden;
}
.mc-head-box div {
flex:1;
text-align: center;
font-size: 18px;
}
.mc-head-box {
display: flex;
flex-direction: row;
justify-content: center;
align-content: space-between
}
.mc-body {
padding-bottom: 20px;
}
.mc-body tr {
display: flex;
flex-direction: row;
justify-content: center;
align-content: space-between;
}
.mc-dot {
width: 8px;
height: 8px;
background-color: #ea6151;
border-radius: 50%;
position: absolute;
bottom: -4px;
left: 50%;
margin-left: -4px;
z-index: 5;
}
.remark-text {
box-sizing: border-box;
height: 0.7em;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
position: absolute;
bottom: 0px;
left: 0;
right: 0;
text-align: center;
font-size: 0.7em;
line-height: 0.7em;
z-index: 5;
}
.slot-element{
line-height: normal;
position: absolute;
z-index: 5;
}
.mpvue-calendar-change{
position: absolute;
left:0px;
top:42px;
right:0px;
bottom:0px;
background:#fff;
display: flex;
justify-content: center;
align-items: center;
flex-wrap:wrap;
overflow: auto;
transition:all .5s cubic-bezier(0.075, 0.82, 0.165, 1);
opacity: 0;
pointer-events: none;
transform: translateY(-10px);
z-index: 9;
}
.mpvue-calendar-change.show{
opacity: 1;
pointer-events: auto;
transform: translateY(0px);
}
.mpvue-calendar-change span{
margin:4px 2%;
display: inline-block;
line-height: 30px;
border-radius: 20px;
text-align:center;
color:#999;
width: 20%;
float: left;
text-align: center;
border-radius: 40px;
box-sizing: border-box;
margin-bottom: 4%;
cursor: pointer;
}
.mpvue-calendar-change span.active{
background-color: #587dff;
box-shadow: 2px 2px 2px rgba(88, 125, 255, 0.7);
color:#fff;
}
.mpvue-calendar-change .calendar-week-switch-months{
height: 100%;
}
.mpvue-calendar-change .calendar-week-switch-months span {
margin-bottom: 10px;
margin-top: 0px;
}
.calendar-years, .calendar-months{
height: 50%;
width: 100%;
padding: 10px;
box-sizing: border-box;
position: relative;
}
.calendar-years:after {
content: '';
display: block;
width: 86%;
height: 1px;
background-color: #eee;
position: absolute;
bottom: 2%;
left: 7%;
}
/*range background*/
.mc-range-mode .selected .mc-range-bg{
content: '';
display: block;
width: 150%;
height: 100%;
background-color: #01a1ed;
position: relative;
top: -100%;
left: 50%;
}
.mpvue-calendar .mc-range-mode .selected .calendar-date{
background-color: transparent;
}
.mpvue-calendar .mc-range-mode .mc-range-row-last .calendar-date, .mpvue-calendar .mc-range-mode .mc-range-row-first .calendar-date{
border-radius: 4px;
background-color: #01a1ed;
}
.mpvue-calendar .mc-range-mode .mc-range-month-first.selected .calendar-date, .mpvue-calendar .mc-range-mode .mc-range-month-last.selected .calendar-date{
background-color: #01a1ed;
border-radius: 4px;
}
.mc-range-mode .mc-range-month-last .mc-range-bg{
background-color: transparent;
border-radius: 4px;
}
.mc-range-mode .mc-range-end .mc-range-bg, .mc-range-mode .mc-range-row-last .mc-range-bg{
display: none;
}
.mc-range-row-first.mc-range-end .mc-range-bg{
display: block;
margin-left: -50%;
width: 50%;
border-radius: 4px;
}
.mpvue-calendar .mc-range-row-first.mc-range-end.month-first-date .mc-range-bg{
margin-left: 0px;
}
.mc-range-row-last.mc-range-begin .mc-range-bg{
display: block;
width: 50%;
border-radius: 4px;
}
.mpvue-calendar .mc-range-mode .selected.mc-range-second-to-last span{
background-color: #01a1ed;
border-radius: 4px;
}
.mc-range-begin.mc-range-second-to-last{
background-color: #01a1ed;
border-radius: 4px;
}
.mpvue-calendar .mc-range-mode .mc-range-end span.calendar-date, .mpvue-calendar .mc-range-mode .mc-range-begin span.calendar-date{
background-color: #3b75fb;
color: #fff;
border-radius: 50%;
}
.mpvue-calendar .mc-range-mode .month-last-date.mc-range-begin .mc-range-bg{
display: block;
width: 50%;
border-radius: 4px;
}
.mpvue-calendar .mc-range-mode .month-first-date.mc-range-end .mc-range-bg{
display: block;
width: 50%;
border-radius: 4px;
left: 0px;
}
.calendar-wrapper .mpvue-calendar .mc-range-mode .mc-range-select-one div.mc-range-bg{
display: none;
}
.mc-range-mode .mc-range-second-to-last .mc-range-bg{
border-radius: 0px 25% 25% 0px;
}
.mc-today-element .calendar-date{
background-color: rgba(25, 47, 89, 0.1);
border-radius: 4px;
}
/*week switch*/
.mpvue-calendar .mc-range-mode.week-switch .month-last-date.mc-range-begin .mc-range-bg{
width: 150%;
border-radius: 0px 20% 20% 0px;
}
.mpvue-calendar .mc-range-mode.week-switch .mc-range-month-last .mc-range-bg{
background-color: #01a1ed;
border-radius: 0px 20% 20% 0px;
}
/*month range*/
.mpvue-calendar .month-range-mode{
border-bottom: 1px solid #f2f2f2;
position: relative;
}
.mpvue-calendar .mc-month-range-mode-head{
box-shadow: 0 4px 8px rgba(25,47,89,.1);
padding: 8px 0px;
position: sticky;
top: 0px;
background-color: #fff;
z-index: 9;
}
.month-range-mode .month-rang-head {
text-align: left;
margin: 10px 0px;
padding-left: 10px;
}
.month-range-mode .mc-last-month, .month-range-mode .mc-next-month{
opacity: 0 !important;
}
.month-text-background{
position: absolute;
font-size: 140px;
width: 100%;
height: 100%;
text-align: center;
line-height: 2.4;
}
+524
View File
@@ -0,0 +1,524 @@
/**
* @1900-2100区间内的公历、农历互转
* @charset UTF-8
* @Author Jea杨(JJonline@JJonline.Cn)
* @Time 2014-7-21
* @Time 2016-8-13 Fixed 2033hex、Attribution Annals
* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug
* @Version 1.0.2
* @公历转农历:calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
* @农历转公历:calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
*/
var calendar = {
/**
* 农历1900-2100的润大小信息表
* @Array Of Property
* @return Hex
*/
lunarInfo:[0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,//1900-1909
0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,//1910-1919
0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,//1920-1929
0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,//1930-1939
0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,//1940-1949
0x06ca0,0x0b550,0x15355,0x04da0,0x0a5b0,0x14573,0x052b0,0x0a9a8,0x0e950,0x06aa0,//1950-1959
0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,//1960-1969
0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b6a0,0x195a6,//1970-1979
0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,//1980-1989
0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,//1990-1999
0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,//2000-2009
0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,//2010-2019
0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,//2020-2029
0x05aa0,0x076a3,0x096d0,0x04afb,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,//2030-2039
0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0,//2040-2049
/**Add By JJonline@JJonline.Cn**/
0x14b63,0x09370,0x049f8,0x04970,0x064b0,0x168a6,0x0ea50, 0x06b20,0x1a6c4,0x0aae0,//2050-2059
0x0a2e0,0x0d2e3,0x0c960,0x0d557,0x0d4a0,0x0da50,0x05d55,0x056a0,0x0a6d0,0x055d4,//2060-2069
0x052d0,0x0a9b8,0x0a950,0x0b4a0,0x0b6a6,0x0ad50,0x055a0,0x0aba4,0x0a5b0,0x052b0,//2070-2079
0x0b273,0x06930,0x07337,0x06aa0,0x0ad50,0x14b55,0x04b60,0x0a570,0x054e4,0x0d160,//2080-2089
0x0e968,0x0d520,0x0daa0,0x16aa6,0x056d0,0x04ae0,0x0a9d4,0x0a2d0,0x0d150,0x0f252,//2090-2099
0x0d520],//2100
/**
* 公历每个月份的天数普通表
* @Array Of Property
* @return Number
*/
solarMonth:[31,28,31,30,31,30,31,31,30,31,30,31],
/**
* 天干地支之天干速查表
* @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
* @return Cn string
*/
Gan:["\u7532","\u4e59","\u4e19","\u4e01","\u620a","\u5df1","\u5e9a","\u8f9b","\u58ec","\u7678"],
/**
* 天干地支之地支速查表
* @Array Of Property
* @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
* @return Cn string
*/
Zhi:["\u5b50","\u4e11","\u5bc5","\u536f","\u8fb0","\u5df3","\u5348","\u672a","\u7533","\u9149","\u620c","\u4ea5"],
/**
* 天干地支之地支速查表<=>生肖
* @Array Of Property
* @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
* @return Cn string
*/
Animals:["\u9f20","\u725b","\u864e","\u5154","\u9f99","\u86c7","\u9a6c","\u7f8a","\u7334","\u9e21","\u72d7","\u732a"],
/**
* 24节气速查表
* @Array Of Property
* @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"]
* @return Cn string
*/
solarTerm:["\u5c0f\u5bd2","\u5927\u5bd2","\u7acb\u6625","\u96e8\u6c34","\u60ca\u86f0","\u6625\u5206","\u6e05\u660e","\u8c37\u96e8","\u7acb\u590f","\u5c0f\u6ee1","\u8292\u79cd","\u590f\u81f3","\u5c0f\u6691","\u5927\u6691","\u7acb\u79cb","\u5904\u6691","\u767d\u9732","\u79cb\u5206","\u5bd2\u9732","\u971c\u964d","\u7acb\u51ac","\u5c0f\u96ea","\u5927\u96ea","\u51ac\u81f3"],
/**
* 1900-2100各年的24节气日期速查表
* @Array Of Property
* @return 0x string For splice
*/
sTermInfo:['9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e','97bcf97c3598082c95f8c965cc920f',
'97bd0b06bdb0722c965ce1cfcc920f','b027097bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e',
'97bcf97c359801ec95f8c965cc920f','97bd0b06bdb0722c965ce1cfcc920f','b027097bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e','97bcf97c359801ec95f8c965cc920f','97bd0b06bdb0722c965ce1cfcc920f',
'b027097bd097c36b0b6fc9274c91aa','9778397bd19801ec9210c965cc920e','97b6b97bd19801ec95f8c965cc920f',
'97bd09801d98082c95f8e1cfcc920f','97bd097bd097c36b0b6fc9210c8dc2','9778397bd197c36c9210c9274c91aa',
'97b6b97bd19801ec95f8c965cc920e','97bd09801d98082c95f8e1cfcc920f','97bd097bd097c36b0b6fc9210c8dc2',
'9778397bd097c36c9210c9274c91aa','97b6b97bd19801ec95f8c965cc920e','97bcf97c3598082c95f8e1cfcc920f',
'97bd097bd097c36b0b6fc9210c8dc2','9778397bd097c36c9210c9274c91aa','97b6b97bd19801ec9210c965cc920e',
'97bcf97c3598082c95f8c965cc920f','97bd097bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e','97bcf97c3598082c95f8c965cc920f','97bd097bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e','97bcf97c359801ec95f8c965cc920f',
'97bd097bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e',
'97bcf97c359801ec95f8c965cc920f','97bd097bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e','97bcf97c359801ec95f8c965cc920f','97bd097bd07f595b0b6fc920fb0722',
'9778397bd097c36b0b6fc9210c8dc2','9778397bd19801ec9210c9274c920e','97b6b97bd19801ec95f8c965cc920f',
'97bd07f5307f595b0b0bc920fb0722','7f0e397bd097c36b0b6fc9210c8dc2','9778397bd097c36c9210c9274c920e',
'97b6b97bd19801ec95f8c965cc920f','97bd07f5307f595b0b0bc920fb0722','7f0e397bd097c36b0b6fc9210c8dc2',
'9778397bd097c36c9210c9274c91aa','97b6b97bd19801ec9210c965cc920e','97bd07f1487f595b0b0bc920fb0722',
'7f0e397bd097c36b0b6fc9210c8dc2','9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e',
'97bcf7f1487f595b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e','97bcf7f1487f595b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e','97bcf7f1487f531b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e',
'97bcf7f1487f531b0b0bb0b6fb0722','7f0e397bd07f595b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c9274c920e','97bcf7f0e47f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722',
'9778397bd097c36b0b6fc9210c91aa','97b6b97bd197c36c9210c9274c920e','97bcf7f0e47f531b0b0bb0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722','9778397bd097c36b0b6fc9210c8dc2','9778397bd097c36c9210c9274c920e',
'97b6b7f0e47f531b0723b0b6fb0722','7f0e37f5307f595b0b0bc920fb0722','7f0e397bd097c36b0b6fc9210c8dc2',
'9778397bd097c36b0b70c9274c91aa','97b6b7f0e47f531b0723b0b6fb0721','7f0e37f1487f595b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc9210c8dc2','9778397bd097c36b0b6fc9274c91aa','97b6b7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f595b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa',
'97b6b7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa','97b6b7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa','97b6b7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722','9778397bd097c36b0b6fc9274c91aa',
'97b6b7f0e47f531b0723b0787b0721','7f0e27f0e47f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722',
'9778397bd097c36b0b6fc9210c91aa','97b6b7f0e47f149b0723b0787b0721','7f0e27f0e47f531b0723b0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722','9778397bd097c36b0b6fc9210c8dc2','977837f0e37f149b0723b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722','7f0e37f5307f595b0b0bc920fb0722','7f0e397bd097c35b0b6fc9210c8dc2',
'977837f0e37f14998082b0787b0721','7f07e7f0e47f531b0723b0b6fb0721','7f0e37f1487f595b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc9210c8dc2','977837f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722','977837f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722',
'977837f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722','977837f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722','977837f0e37f14998082b0787b06bd',
'7f07e7f0e47f149b0723b0787b0721','7f0e27f0e47f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722',
'977837f0e37f14998082b0723b06bd','7f07e7f0e37f149b0723b0787b0721','7f0e27f0e47f531b0723b0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722','977837f0e37f14898082b0723b02d5','7ec967f0e37f14998082b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722','7f0e37f1487f595b0b0bb0b6fb0722','7f0e37f0e37f14898082b0723b02d5',
'7ec967f0e37f14998082b0787b0721','7f07e7f0e47f531b0723b0b6fb0722','7f0e37f1487f531b0b0bb0b6fb0722',
'7f0e37f0e37f14898082b0723b02d5','7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721',
'7f0e37f1487f531b0b0bb0b6fb0722','7f0e37f0e37f14898082b072297c35','7ec967f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722','7f0e37f0e37f14898082b072297c35',
'7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e37f0e366aa89801eb072297c35','7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f149b0723b0787b0721',
'7f0e27f1487f531b0b0bb0b6fb0722','7f0e37f0e366aa89801eb072297c35','7ec967f0e37f14998082b0723b06bd',
'7f07e7f0e47f149b0723b0787b0721','7f0e27f0e47f531b0723b0b6fb0722','7f0e37f0e366aa89801eb072297c35',
'7ec967f0e37f14998082b0723b06bd','7f07e7f0e37f14998083b0787b0721','7f0e27f0e47f531b0723b0b6fb0722',
'7f0e37f0e366aa89801eb072297c35','7ec967f0e37f14898082b0723b02d5','7f07e7f0e37f14998082b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722','7f0e36665b66aa89801e9808297c35','665f67f0e37f14898082b0723b02d5',
'7ec967f0e37f14998082b0787b0721','7f07e7f0e47f531b0723b0b6fb0722','7f0e36665b66a449801e9808297c35',
'665f67f0e37f14898082b0723b02d5','7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721',
'7f0e36665b66a449801e9808297c35','665f67f0e37f14898082b072297c35','7ec967f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721','7f0e26665b66a449801e9808297c35','665f67f0e37f1489801eb072297c35',
'7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722'],
/**
* 数字转中文速查表
* @Array Of Property
* @trans ['日','一','二','三','四','五','六','七','八','九','十']
* @return Cn string
*/
nStr1:["\u65e5","\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u4e03","\u516b","\u4e5d","\u5341"],
/**
* 日期转农历称呼速查表
* @Array Of Property
* @trans ['初','十','廿','卅']
* @return Cn string
*/
nStr2:["\u521d","\u5341","\u5eff","\u5345"],
/**
* 月份转农历称呼速查表
* @Array Of Property
* @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊']
* @return Cn string
*/
nStr3:["\u6b63","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u4e03","\u516b","\u4e5d","\u5341","\u51ac","\u814a"],
/**
* 返回农历y年一整年的总天数
* @param lunar Year
* @return Number
* @eg:var count = calendar.lYearDays(1987) ;//count=387
*/
lYearDays:function(y) {
var i, sum = 348;
for(i=0x8000; i>0x8; i>>=1) { sum += (calendar.lunarInfo[y-1900] & i)? 1: 0; }
return(sum+calendar.leapDays(y));
},
/**
* 返回农历y年闰月是哪个月;若y年没有闰月 则返回0
* @param lunar Year
* @return Number (0-12)
* @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
*/
leapMonth:function(y) { //闰字编码 \u95f0
return(calendar.lunarInfo[y-1900] & 0xf);
},
/**
* 返回农历y年闰月的天数 若该年没有闰月则返回0
* @param lunar Year
* @return Number (0、29、30)
* @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
*/
leapDays:function(y) {
if(calendar.leapMonth(y)) {
return((calendar.lunarInfo[y-1900] & 0x10000)? 30: 29);
}
return(0);
},
/**
* 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法
* @param lunar Year
* @return Number (-1、29、30)
* @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
*/
monthDays:function(y,m) {
if(m>12 || m<1) {return -1}//月份参数从1至12,参数错误返回-1
return( (calendar.lunarInfo[y-1900] & (0x10000>>m))? 30: 29 );
},
/**
* 返回公历(!)y年m月的天数
* @param solar Year
* @return Number (-1、28、29、30、31)
* @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
*/
solarDays:function(y,m) {
if(m>12 || m<1) {return -1} //若参数错误 返回-1
var ms = m-1;
if(ms==1) { //2月份的闰平规律测算后确认返回28或29
return(((y%4 == 0) && (y%100 != 0) || (y%400 == 0))? 29: 28);
}else {
return(calendar.solarMonth[ms]);
}
},
/**
* 农历年份转换为干支纪年
* @param lYear 农历年的年份数
* @return Cn string
*/
toGanZhiYear:function(lYear) {
var ganKey = (lYear - 3) % 10;
var zhiKey = (lYear - 3) % 12;
if(ganKey == 0) ganKey = 10;//如果余数为0则为最后一个天干
if(zhiKey == 0) zhiKey = 12;//如果余数为0则为最后一个地支
return calendar.Gan[ganKey-1] + calendar.Zhi[zhiKey-1];
},
/**
* 公历月、日判断所属星座
* @param cMonth [description]
* @param cDay [description]
* @return Cn string
*/
toAstro:function(cMonth,cDay) {
var s = "\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf";
var arr = [20,19,21,21,21,22,23,23,23,23,22,22];
return s.substr(cMonth*2 - (cDay < arr[cMonth-1] ? 2 : 0),2) + "\u5ea7";//座
},
/**
* 传入offset偏移量返回干支
* @param offset 相对甲子的偏移量
* @return Cn string
*/
toGanZhi:function(offset) {
return calendar.Gan[offset%10] + calendar.Zhi[offset%12];
},
/**
* 传入公历(!)y年获得该年第n个节气的公历日期
* @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起
* @return day Number
* @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
*/
getTerm:function(y,n) {
if(y<1900 || y>2100) {return -1;}
if(n<1 || n>24) {return -1;}
var _table = calendar.sTermInfo[y-1900];
var _info = [
parseInt('0x'+_table.substr(0,5)).toString() ,
parseInt('0x'+_table.substr(5,5)).toString(),
parseInt('0x'+_table.substr(10,5)).toString(),
parseInt('0x'+_table.substr(15,5)).toString(),
parseInt('0x'+_table.substr(20,5)).toString(),
parseInt('0x'+_table.substr(25,5)).toString()
];
var _calday = [
_info[0].substr(0,1),
_info[0].substr(1,2),
_info[0].substr(3,1),
_info[0].substr(4,2),
_info[1].substr(0,1),
_info[1].substr(1,2),
_info[1].substr(3,1),
_info[1].substr(4,2),
_info[2].substr(0,1),
_info[2].substr(1,2),
_info[2].substr(3,1),
_info[2].substr(4,2),
_info[3].substr(0,1),
_info[3].substr(1,2),
_info[3].substr(3,1),
_info[3].substr(4,2),
_info[4].substr(0,1),
_info[4].substr(1,2),
_info[4].substr(3,1),
_info[4].substr(4,2),
_info[5].substr(0,1),
_info[5].substr(1,2),
_info[5].substr(3,1),
_info[5].substr(4,2),
];
return parseInt(_calday[n-1]);
},
/**
* 传入农历数字月份返回汉语通俗表示法
* @param lunar month
* @return Cn string
* @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
*/
toChinaMonth:function(m) { // 月 => \u6708
if(m>12 || m<1) {return -1} //若参数错误 返回-1
var s = calendar.nStr3[m-1];
s+= "\u6708";//加上月字
return s;
},
/**
* 传入农历日期数字返回汉字表示法
* @param lunar day
* @return Cn string
* @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
*/
toChinaDay:function(d){ //日 => \u65e5
var s;
switch (d) {
case 10:
s = '\u521d\u5341'; break;
case 20:
s = '\u4e8c\u5341'; break;
break;
case 30:
s = '\u4e09\u5341'; break;
break;
default :
s = calendar.nStr2[Math.floor(d/10)];
s += calendar.nStr1[d%10];
}
return(s);
},
/**
* 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春”
* @param y year
* @return Cn string
* @eg:var animal = calendar.getAnimal(1987) ;//animal='兔'
*/
getAnimal: function(y) {
return calendar.Animals[(y - 4) % 12]
},
/**
* 传入阳历年月日获得详细的公历、农历object信息 <=>JSON
* @param y solar year
* @param m solar month
* @param d solar day
* @return JSON object
* @eg:console.log(calendar.solar2lunar(1987,11,01));
*/
solar2lunar:function (y,m,d) { //参数区间1900.1.31~2100.12.31
if(y<1900 || y>2100) {return -1;}//年份限定、上限
if(y==1900&&m==1&&d<31) {return -1;}//下限
if(!y) { //未传参 获得当天
var objDate = new Date();
}else {
var objDate = new Date(y,parseInt(m)-1,d)
}
var i, leap=0, temp=0;
//修正ymd参数
var y = objDate.getFullYear(),m = objDate.getMonth()+1,d = objDate.getDate();
var offset = (Date.UTC(objDate.getFullYear(),objDate.getMonth(),objDate.getDate()) - Date.UTC(1900,0,31))/86400000;
for(i=1900; i<2101 && offset>0; i++) { temp=calendar.lYearDays(i); offset-=temp; }
if(offset<0) { offset+=temp; i--; }
//是否今天
var isTodayObj = new Date(),isToday=false;
if(isTodayObj.getFullYear()==y && isTodayObj.getMonth()+1==m && isTodayObj.getDate()==d) {
isToday = true;
}
//星期几
var nWeek = objDate.getDay(),cWeek = calendar.nStr1[nWeek];
if(nWeek==0) {nWeek =7;}//数字表示周几顺应天朝周一开始的惯例
//农历年
var year = i;
var leap = calendar.leapMonth(i); //闰哪个月
var isLeap = false;
//效验闰月
for(i=1; i<13 && offset>0; i++) {
//闰月
if(leap>0 && i==(leap+1) && isLeap==false){
--i;
isLeap = true; temp = calendar.leapDays(year); //计算农历闰月天数
}
else{
temp = calendar.monthDays(year, i);//计算农历普通月天数
}
//解除闰月
if(isLeap==true && i==(leap+1)) { isLeap = false; }
offset -= temp;
}
if(offset==0 && leap>0 && i==leap+1)
if(isLeap){
isLeap = false;
}else{
isLeap = true; --i;
}
if(offset<0){ offset += temp; --i; }
//农历月
var month = i;
//农历日
var day = offset + 1;
//天干地支处理
var sm = m-1;
var gzY = calendar.toGanZhiYear(year);
//月柱 1900年1月小寒以前为 丙子月(60进制12)
var firstNode = calendar.getTerm(year,(m*2-1));//返回当月「节」为几日开始
var secondNode = calendar.getTerm(year,(m*2));//返回当月「节」为几日开始
//依据12节气修正干支月
var gzM = calendar.toGanZhi((y-1900)*12+m+11);
if(d>=firstNode) {
gzM = calendar.toGanZhi((y-1900)*12+m+12);
}
//传入的日期的节气与否
var isTerm = false;
var Term = null;
if(firstNode==d) {
isTerm = true;
Term = calendar.solarTerm[m*2-2];
}
if(secondNode==d) {
isTerm = true;
Term = calendar.solarTerm[m*2-1];
}
//日柱 当月一日与 1900/1/1 相差天数
var dayCyclical = Date.UTC(y,sm,1,0,0,0,0)/86400000+25567+10;
var gzD = calendar.toGanZhi(dayCyclical+d-1);
//该日期所属的星座
var astro = calendar.toAstro(m,d);
return {'lYear':year,'lMonth':month,'lDay':day,'Animal':calendar.getAnimal(year),'IMonthCn':(isLeap?"\u95f0":'')+calendar.toChinaMonth(month),'IDayCn':calendar.toChinaDay(day),'cYear':y,'cMonth':m,'cDay':d,'gzYear':gzY,'gzMonth':gzM,'gzDay':gzD,'isToday':isToday,'isLeap':isLeap,'nWeek':nWeek,'ncWeek':"\u661f\u671f"+cWeek,'isTerm':isTerm,'Term':Term,'astro':astro};
},
/**
* 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON
* @param y lunar year
* @param m lunar month
* @param d lunar day
* @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可]
* @return JSON object
* @eg:console.log(calendar.lunar2solar(1987,9,10));
*/
lunar2solar:function(y,m,d,isLeapMonth) { //参数区间1900.1.31~2100.12.1
var isLeapMonth = !!isLeapMonth;
var leapOffset = 0;
var leapMonth = calendar.leapMonth(y);
var leapDay = calendar.leapDays(y);
if(isLeapMonth&&(leapMonth!=m)) {return -1;}//传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
if(y==2100&&m==12&&d>1 || y==1900&&m==1&&d<31) {return -1;}//超出了最大极限值
var day = calendar.monthDays(y,m);
var _day = day;
//bugFix 2016-9-25
//if month is leap, _day use leapDays method
if(isLeapMonth) {
_day = calendar.leapDays(y,m);
}
if(y < 1900 || y > 2100 || d > _day) {return -1;}//参数合法性效验
//计算农历的时间差
var offset = 0;
for(var i=1900;i<y;i++) {
offset+=calendar.lYearDays(i);
}
var leap = 0,isAdd= false;
for(var i=1;i<m;i++) {
leap = calendar.leapMonth(y);
if(!isAdd) {//处理闰月
if(leap<=i && leap>0) {
offset+=calendar.leapDays(y);isAdd = true;
}
}
offset+=calendar.monthDays(y,i);
}
//转换闰月农历 需补充该年闰月的前一个月的时差
if(isLeapMonth) {offset+=day;}
//1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
var stmap = Date.UTC(1900,1,30,0,0,0);
var calObj = new Date((offset+d-31)*86400000+stmap);
var cY = calObj.getUTCFullYear();
var cM = calObj.getUTCMonth()+1;
var cD = calObj.getUTCDate();
return calendar.solar2lunar(cY,cM,cD);
}
};
export default calendar
+15
View File
@@ -0,0 +1,15 @@
@font-face {font-family: "iconfont";
src: url('data:font/truetype;charset=utf-8;base64,d09GRgABAAAAAASEAAsAAAAABuwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFY7d0f0Y21hcAAAAYAAAABTAAABhmJUzs9nbHlmAAAB1AAAALcAAADIzC0F5mhlYWQAAAKMAAAALwAAADYS7IZUaGhlYQAAArwAAAAcAAAAJAfeA4RobXR4AAAC2AAAAAwAAAAMDAAAAGxvY2EAAALkAAAACAAAAAgANgBkbWF4cAAAAuwAAAAfAAAAIAEOACluYW1lAAADDAAAAUUAAAJtPlT+fXBvc3QAAARUAAAALQAAAEOUPjuMeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2BkYWCcwMDKwMHUyXSGgYGhH0IzvmYwYuRgYGBiYGVmwAoC0lxTGByeMj5jYm7438AQw9zA0AAUZgTJAQDdSgvleJztkMERgDAIBPdIzMOxEB8W5MvuTRsRMHbhzSwHR/IBWIDiHE4FXYjQ6akyL6yZ13zT3IXd6jYGfO6S75q7xT81fm1Z9zlZXOsl+j5BD35IDU4AeJwVzUEOwUAYBeD/mfxTEso/mkEJoYluqgtajUjYsHEOSytncROJK/QErjNMd+8lL+8jEP3eqq8uNCPiokK1L4t1ihzVCSPMEekAep3mQCh4tpVm95JWz2QGj3iyiN3LZMJBODU49IMuDxk32YifuI89X4+xqwcsHUtEjfVVWt1p5MvWNs9RY4RowNLrJ7Tq8ZKNN7wmvMp8jBc7PDpW3RPfPrISV5ss4QEO9pxcdrix/gMMIyHOAHicY2BkYGAAYmNBZtV4fpuvDNwsDCBw/dlCBQT9fzMLA3MKkMvBwAQSBQDyNAlAAHicY2BkYGBu+N/AEMPCAAJAkpEBFTADAEcJAmwEAAAABAAAAAQAAAAAAAAAADYAZHicY2BkYGBgZpBlANEMDExAzAWEDAz/wXwGAAuHATgAeJxlj01OwzAQhV/6B6QSqqhgh+QFYgEo/RGrblhUavdddN+mTpsqiSPHrdQDcB6OwAk4AtyAO/BIJ5s2lsffvHljTwDc4Acejt8t95E9XDI7cg0XuBeuU38QbpBfhJto41W4Rf1N2MczpsJtdGF5g9e4YvaEd2EPHXwI13CNT+E69S/hBvlbuIk7/Aq30PHqwj7mXle4jUcv9sdWL5xeqeVBxaHJIpM5v4KZXu+Sha3S6pxrW8QmU4OgX0lTnWlb3VPs10PnIhVZk6oJqzpJjMqt2erQBRvn8lGvF4kehCblWGP+tsYCjnEFhSUOjDFCGGSIyujoO1Vm9K+xQ8Jee1Y9zed0WxTU/3OFAQL0z1xTurLSeTpPgT1fG1J1dCtuy56UNJFezUkSskJe1rZUQuoBNmVXjhF6XNGJPyhnSP8ACVpuyAAAAHicY2BigAAuBuyAmZGJkZmRhYEnKzMxryS/tDgjMS+dC8qpzC9lYAAAiPIJlAAAAA==');
}
.iconfont {
font-family:"iconfont" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-arrow-right:before { content: "\e602"; }
.icon-arrow-left:before { content: "\e501"; }
File diff suppressed because it is too large. Load diff
+394
View File
@@ -0,0 +1,394 @@
.mpvue-calendar {
margin:auto;
width: 100%;
min-width:300rpx;
background: #fff;
user-select:none;
position: relative;
}
.calendar-tools{
height:40px;
font-size: 20px;
line-height: 40px;
color:#5e7a88;
box-shadow: 0rpx 4rpx 8rpx rgba(25, 47, 89, 0.1);
margin-bottom: 30rpx;
border-top: 1px solid rgba(200, 200, 200, .1);
}
.calendar-prev{
width: 14.28571429%;
float:left;
text-align: center;
}
.calendar-prev img, .calendar-next img{
width: 34rpx;
height: 34rpx;
}
.calendar-info{
padding-top: 3px;
font-size:16px;
line-height: 1.3;
text-align: center;
width: 220rpx;
margin: 0 auto;
}
.calendar-info>div.mc-month{
margin:auto;
height:40rpx;
width:100px;
text-align: center;
color:#5e7a88;
overflow: hidden;
position: relative;
}
.calendar-info>div.mc-month .mc-month-inner{
position: absolute;
left:0;
top:0;
height:480rpx;
}
.month-transition{
transition:top .5s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.calendar-info .mc-month-text{
display:block;
font-size:28rpx;
height:40rpx;
width:200rpx;
overflow:hidden;
text-align:center;
}
.calendar-info>div.mc-month .mc-month-inner>span{
display: block;
font-size: 14px;
height:20px;
width:100px;
overflow: hidden;
text-align: center;
}
.calendar-info>div.mc-year{
font-size:10px;
line-height: 1;
color:#999;
}
.calendar-next{
width: 14.28571429%;
float:right;
text-align: center;
}
.mpvue-calendar table {
clear: both;
width: 100%;
margin-bottom:10px;
border-collapse: collapse;
color: #444444;
}
.mpvue-calendar td {
margin:2px !important;
padding:0px 0;
width: 14.28571429%;
height:88rpx;
text-align: center;
vertical-align: middle;
font-size:14px;
line-height: 125%;
cursor: pointer;
position: relative;
vertical-align: top;
}
.mpvue-calendar td.mc-week{
font-size:10px;
pointer-events:none !important;
cursor: default !important;
}
.mpvue-calendar td.disabled {
color: #ccc;
}
.mpvue-calendar td.disabled div{
color: #ccc;
}
.mpvue-calendar td span{
display:block;
height:76rpx;
width:76rpx;
font-size: 28rpx;
line-height:76rpx;
margin:0px auto;
position: relative;
z-index: 3;
}
.mpvue-calendar td:not(.disabled) span.mc-date-red{
color:#ea6151;
}
.mc-today{
color: #3b75fb;
}
.mpvue-calendar td.selected span{
background-color: #3b75fb;
color: #fff;
border-radius:50%;
}
.mpvue-calendar td .mc-text{
position: absolute;
top:28px;
left:0;
right:0;
text-align: center;
padding:2px;
font-size:20rpx;
line-height: 1.2;
color:#444;
z-index: 4;
}
.mpvue-calendar td .isGregorianFestival,
.mpvue-calendar td .isTerm,
.mpvue-calendar td .isLunarFestival{
color:#ea6151;
}
.mpvue-calendar td.selected span.mc-date-red{
background-color: #3b75fb;
color: #fff;
}
.selected .mc-text {
color: #fff !important;
}
.mpvue-calendar .lunarStyle span{
width: 80rpx;
height: 80rpx;
line-height:54rpx;
}
.mpvue-calendar .lunarStyle .mc-text{
top: 44rpx;
}
.mpvue-calendar thead td {
text-transform: uppercase;
height:30px;
vertical-align: middle;
}
.mc-head {
margin-bottom: 20rpx;
}
.mc-head div {
overflow: hidden;
}
.mc-head-box div {
flex:1;
text-align: center;
}
.mc-head-box {
display: flex;
flex-direction: row;
justify-content: center;
align-content: space-between
}
.mc-head-box div {
font-size: 28rpx;
}
.mc-body tr {
display: flex;
flex-direction: row;
justify-content: center;
align-content: space-between
}
.mc-dot {
width: 10rpx;
height: 10rpx;
background-color: #ea6151;
border-radius: 50%;
margin: 0 auto;
margin-top: 5rpx;
position: absolute;
bottom: -5rpx;
left: 50%;
margin-left: -5rpx;
z-index: 5;
}
.remark-text {
padding-left: 8rpx;
padding-right: 8rpx;
box-sizing: border-box;
height: 34rpx;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.slot-element{
line-height: normal;
position: absolute;
z-index: 5;
}
.mpvue-calendar-change{
position: absolute;
left:0rpx;
top:85rpx;
right:0rpx;
bottom:0rpx;
background:#fff;
display: flex;
justify-content: center;
align-items: center;
flex-wrap:wrap;
overflow: auto;
transition:all .5s cubic-bezier(0.075, 0.82, 0.165, 1);
opacity: 0;
pointer-events: none;
transform: translateY(-10px);
z-index: 9;
}
.mpvue-calendar-change.show{
opacity: 1;
pointer-events: auto;
transform: translateY(0px);
}
.mpvue-calendar-change span{
margin:4px 2%;
display: inline-block;
line-height: 30px;
border-radius: 20px;
text-align:center;
color:#999;
width: 20%;
float: left;
text-align: center;
border-radius: 40px;
box-sizing: border-box;
margin-bottom: 4%;
}
.mpvue-calendar-change span.active{
background-color: #587dff;
box-shadow: 2px 2px 2px rgba(88, 125, 255, 0.7);
color:#fff;
}
.mpvue-calendar-change .calendar-week-switch-months{
height: 100%;
padding: 10rpx 20rpx;
}
.mpvue-calendar-change .calendar-week-switch-months span {
margin-bottom: 20rpx;
margin-top: 0px;
font-size: 26rpx;
line-height: 40rpx;
}
.calendar-years, .calendar-months{
height: 50%;
width: 100%;
padding: 10px;
box-sizing: border-box;
position: relative;
}
.calendar-years:after {
content: '';
display: block;
width: 86%;
height: 1rpx;
background-color: #eee;
position: absolute;
bottom: 2%;
left: 7%;
}
/*range background*/
.mc-range-mode .selected .mc-range-bg{
content: '';
display: block;
width: 110rpx;
height: 80rpx;
background-color: #01a1ed;
position: absolute;
top: 0rpx;
left: 50%;
}
.mpvue-calendar .mc-range-mode .selected .calendar-date{
background-color: transparent;
}
.mpvue-calendar .mc-range-mode .mc-range-row-last span.calendar-date, .mpvue-calendar .mc-range-mode .mc-range-row-first span.calendar-date{
border-radius: 6rpx;
background-color: #01a1ed;
}
.mpvue-calendar .mc-range-mode .mc-range-month-first.selected .calendar-date, .mpvue-calendar .mc-range-mode .mc-range-month-last.selected .calendar-date{
border-radius: 6rpx;
background-color: #01a1ed;
}
.mc-range-mode .mc-range-month-last .mc-range-bg{
background-color: transparent;
border-radius: 6rpx;
}
.mc-range-mode .mc-range-end .mc-range-bg, .mc-range-mode .mc-range-row-last .mc-range-bg{
display: none;
}
.mpvue-calendar .mc-range-mode .mc-range-end span.calendar-date, .mpvue-calendar .mc-range-mode .mc-range-begin span.calendar-date{
background-color: #3b75fb;
color: #fff;
border-radius: 50%;
}
.mc-range-mode .mc-range-row-first.mc-range-end .mc-range-bg{
display: block;
border-radius: 6rpx;
width: 40rpx;
left: 5px;
}
.mpvue-calendar .mc-range-row-first.mc-range-end.month-first-date .mc-range-bg{
margin-left: 0px;
}
.mc-range-mode .mc-range-row-last.mc-range-begin .mc-range-bg{
display: block;
border-radius: 4rpx;
width: 40rpx;
right: 10px;
}
.mpvue-calendar .mc-range-mode .month-last-date.mc-range-begin .mc-range-bg{
display: block;
width: 40rpx;
border-radius: 6rpx;
}
.mpvue-calendar .mc-range-mode .month-first-date.mc-range-end .mc-range-bg{
display: block;
width: 40rpx;
border-radius: 6rpx;
left: 10rpx;
}
.mpvue-calendar .mc-range-mode .mc-range-select-one div.mc-range-bg{
display: none !important;
}
.mc-body .mc-today-element .calendar-date{
background-color: rgba(25, 47, 89, 0.1);
border-radius: 6rpx;
}
/*week switch*/
.mpvue-calendar .mc-range-mode.week-switch .month-last-date.mc-range-begin .mc-range-bg{
width: 130%;
border-radius: 0px 20% 20% 0px;
}
.mpvue-calendar .mc-range-mode.week-switch .mc-range-month-last .mc-range-bg{
background-color: #01a1ed;
border-radius: 0px 20% 20% 0px;
}
/*month range*/
.mpvue-calendar .month-range-mode{
border-bottom: 1px solid #f2f2f2;
position: relative;
}
.mpvue-calendar .mc-month-range-mode-head{
box-shadow: 0 4px 8px rgba(25,47,89,.1);
padding: 15rpx 0rpx;
position: sticky;
top: 0px;
background-color: #fff;
z-index: 9;
}
.month-range-mode .month-rang-head {
text-align: left;
margin: 20rpx 0px;
padding-left: 40rpx;
font-size: 28rpx;
}
.month-range-mode .mc-last-month, .month-range-mode .mc-next-month{
opacity: 0 !important;
}
.month-text-background{
position: absolute;
font-size: 140px;
width: 100%;
height: 100%;
text-align: center;
line-height: 2.4;
}
+160
View File
@@ -0,0 +1,160 @@
<template>
<view class="number-box">
<block v-for="(myIndex, index) in indexArr" :key="index">
<swiper class="swiper" vertical="true" :current="myIndex" circular="true"
v-bind:style="{color:color,width:myIndex == 10 ? '14rpx' : myIndex == 1 ? '22rpx' : width+'rpx',height:height+'rpx',lineHeight:fontSize+'rpx',fontSize:fontSize+'rpx',fontWeight: fontWeight}">
<swiper-item>
<view class="swiper-item">0</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">1</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">2</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">3</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">4</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">5</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">6</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">7</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">8</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">9</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">.</view>
</swiper-item>
</swiper>
</block>
</view>
</template>
<script>
export default {
props: {
num: [String, Number],
color: {
type: String,
default: '#000000'
},
width: {
type: String,
default: '30'
},
height: {
type: String,
default: '30'
},
fontSize: {
type: String,
default: '30'
},
fontWeight: {
type: [String, Number],
default: 500
}
},
data() {
return {
indexArr: []
};
},
created() {
let {
num
} = this;
let arr = new Array(num.toString().length);
arr.fill(0);
this.indexArr = arr;
},
watch: {
num: function(val, oldVal) {
// 处理新老数据长度不一样的情况
let arr = Array.prototype.slice.apply(this.indexArr);
let newLen = val.toString().length;
let oldLen = oldVal.toString().length;
if (newLen > oldLen) {
for (let i = 0; i < newLen - oldLen; i++) {
arr.push(0);
}
this.indexArr = arr;
}
if (newLen < oldLen) {
for (let i = 0; i < oldLen - newLen; i++) {
arr.pop();
}
this.indexArr = arr;
}
this.numChange(val);
}
},
mounted() {
//定时器作用:app显示数字滚动
this._time = setTimeout(() => {
this.numChange(this.num);
clearTimeout(this._time);
}, 50);
},
methods: {
/**
* 数字改变
* @value 数字
*/
numChange(num) {
this.$nextTick(() => {
let {
indexArr
} = this;
let copyIndexArr = Array.prototype.slice.apply(indexArr);
let _num = num.toString();
for (let i = 0; i < _num.length; i++) {
if (_num[i] === '.') {
copyIndexArr[i] = 10;
} else {
copyIndexArr[i] = Number(_num[i]);
}
}
this.indexArr = copyIndexArr;
})
}
}
};
</script>
<style lang="scss">
.number-box {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.swiper {
position: relative;
// line-height: 30upx;
// width: 30upx;
// height: 30upx;
// font-size: 30upx;
// background: red;
}
.swiper:after {
content: '';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
</style>
+136
View File
@@ -0,0 +1,136 @@
<template>
<view class="orderGoods borRadius14">
<view class='total'>共{{ totalNmu }}件商品</view>
<view class='goodWrapper pad30'>
<view class='item acea-row row-between-wrapper' v-for="(item,index) in cartInfo" :key="index"
@click="jumpCon(item.spuId)">
<view class='pictrue'>
<image :src='item.picUrl' />
</view>
<view class='text'>
<view class='acea-row row-between-wrapper'>
<view class='name line1'>{{ item.spuName }}</view>
<view class='num'>x {{ item.count }}</view>
</view>
<view class='attr line1'>
<text v-for="(property, propertyIndex) in item.properties" :key="propertyIndex" style="padding-right: 10rpx;">
{{ property.valueName }} 
</text>
</view>
<view class='money font-color'>¥{{ fen2yuan(item.price) }}</view>
<!-- 售后状态 -->
<!-- TODO 芋艿:这样式不太合理;应该顺着向右对齐 -->
<view class="evaluate" style="right: 60px;" v-if="afterSale" @click.stop="afterSaleTap(item)">
{{
item.afterSaleStatus === 0 ? '申请退款' :
item.afterSaleStatus === 10 ? '退款中' : '退款成功'
}}
</view>
<!-- 评价状态 -->
<view class='evaluate' v-if='item.commentStatus === false && evaluate === 2' @click.stop="evaluateTap(item)">评价</view>
<view class='evaluate' v-else-if="item.replyStatus === true">已评价</view>
</view>
</view>
</view>
</view>
</template>
<script>
import * as Util from '@/utils/util.js';
export default {
props: {
evaluate: {
type: Number,
default: 0, // 是否开启评价功能 0 - 不开启;2 - 开启
},
afterSale: { // 是否开启售后功能
type: Boolean,
default: false,
},
cartInfo: {
type: Array,
default: function() {
return [];
}
},
orderId: {
type: String,
default: '',
},
jump: {
type: Boolean,
default: false,
},
productType: {
type: Number,
default: function() {
return 0;
}
}
},
data() {
return {
totalNmu: 0 // 商品数量
};
},
watch: {
cartInfo: function(nVal, oVal) {
let num = 0
nVal.forEach((item, index) => {
num += item.count
})
this.totalNmu = num
}
},
methods: {
evaluateTap(item) {
uni.navigateTo({
url: "/pages/users/goods_comment_con/index?orderItemId=" + item.id
})
},
afterSaleTap(item) {
if (item.afterSaleStatus === 0) {
uni.navigateTo({
url: "/pages/users/goods_return/index?orderId=" + item.orderId + '&orderItemId=' + item.id
})
return;
}
uni.navigateTo({
url: "/pages/users/user_return_detail/index?id=" + item.afterSaleId
})
},
jumpCon: function(id) {
let type = this.productType === 0 ?'normal':'video'
if (this.jump) {
uni.navigateTo({
url: `/pages/goods_details/index?id=${id}&type=${type}`
})
}
},
fen2yuan(price) {
return Util.fen2yuan(price)
},
}
}
</script>
<style scoped lang="scss">
.orderGoods {
background-color: #fff;
margin-top: 15rpx;
}
.orderGoods .total {
width: 100%;
height: 86rpx;
padding: 0 24rpx;
border-bottom: 2rpx solid #f0f0f0;
font-size: 30rpx;
color: #282828;
line-height: 86rpx;
box-sizing: border-box;
}
.pictrue image {
background: #f4f4f4;
}
</style>
+314
View File
@@ -0,0 +1,314 @@
<template>
<view>
<view class="payment" :class="pay_close ? 'on' : ''">
<view class="title acea-row row-center-wrapper">
选择付款方式<text class="iconfont icon-guanbi" @click='close'></text>
</view>
<view class="item acea-row row-between-wrapper" @click='goPay(item.number || 0 , item.value)'
v-for="(item,index) in payMode" :key="index">
<view class="left acea-row row-between-wrapper">
<view class="iconfont" :class="item.icon"></view>
<view class="text">
<view class="name">{{item.name}}</view>
<view class="info" v-if="item.number">
{{item.title}} <span class="money">¥{{ item.number }}</span>
</view>
<view class="info" v-else>{{item.title}}</view>
</view>
</view>
<view class="iconfont icon-xiangyou"></view>
</view>
</view>
<view class="mask" @click='close' v-if="pay_close"></view>
</view>
</template>
<script>
import {
orderPay,
wechatOrderPay,
wechatQueryPayResult
} from '@/api/order.js';
import {
mapGetters
} from "vuex";
export default {
props: {
payMode: {
type: Array,
default: function() {
return [];
}
},
pay_close: {
type: Boolean,
default: false,
},
order_id: {
type: String,
default: ''
},
totalPrice: {
type: String,
default: '0'
}
},
data() {
return {
};
},
computed: mapGetters(['systemPlatform']),
methods: {
close: function() {
this.$emit('onChangeFun', {
action: 'payClose'
});
},
goPay: function(number, paytype) {
let that = this;
let goPages = '/pages/order_pay_status/index?order_id=' + that.order_id;
if (!that.order_id) return that.$util.Tips({
title: '请选择要支付的订单'
});
if (paytype == 'yue' && parseFloat(number) < parseFloat(that.totalPrice)) return that.$util.Tips({
title: '余额不足!'
});
uni.showLoading({
title: '支付中'
});
wechatOrderPay({
orderNo: that.order_id,
// #ifdef MP
payChannel: 'routine',
// #endif
// #ifdef H5
payChannel: that.$wechat.isWeixin() ? 'public' : 'weixinh5',
// #endif
payType: paytype
}).then(res => {
let jsConfig = res.data.jsConfig;
that.order_id = res.data.orderNo;
switch (res.data.payType) {
case 'weixin':
// #ifdef MP
uni.requestPayment({
timeStamp: jsConfig.timeStamp,
nonceStr: jsConfig.nonceStr,
package: jsConfig.packages,
signType: jsConfig.signType,
paySign: jsConfig.paySign,
success: function(ress) {
uni.hideLoading();
wechatQueryPayResult(that.order_id).then(res => {
uni.hideLoading();
return that.$util.Tips({
title: "支付成功",
icon: 'success'
}, () => {
that.$emit('onChangeFun', {
action: 'pay_complete'
});
});
}).cache(err => {
uni.hideLoading();
return that.$util.Tips({
title: err
});
})
},
fail: function(e) {
uni.hideLoading();
return that.$util.Tips({
title: '取消支付'
}, () => {
that.$emit('onChangeFun', {
action: 'pay_fail'
});
});
},
complete: function(e) {
uni.hideLoading();
if (e.errMsg == 'requestPayment:cancel') return that.$util
.Tips({
title: '取消支付'
}, () => {
that.$emit('onChangeFun', {
action: 'pay_fail'
});
});
},
})
// #endif
// #ifdef H5
let datas = {
timestamp: jsConfig.timeStamp,
nonceStr: jsConfig.nonceStr,
package: jsConfig.packages,
signType: jsConfig.signType,
paySign: jsConfig.paySign
};
that.$wechat.pay(datas).then(res => {
if (res.errMsg == 'chooseWXPay:cancel') {
uni.hideLoading();
return that.$util.Tips({
title: '支付失败'
});
} else {
wechatQueryPayResult(that.order_id).then(res => {
uni.hideLoading();
return that.$util.Tips({
title: "支付成功",
icon: 'success'
}, () => {
that.$emit('onChangeFun', {
action: 'pay_complete'
});
});
}).cache(err => {
uni.hideLoading();
return that.$util.Tips({
title: err
});
})
}
}).cache(errW => {
uni.hideLoading();
return that.$util.Tips({
title: errW
});
})
// #endif
break;
case 'yue':
uni.hideLoading();
return that.$util.Tips({
title: '余额支付成功',
icon: 'success'
}, () => {
that.$emit('onChangeFun', {
action: 'pay_complete'
});
});
break;
case 'weixinh5':
uni.hideLoading();
location.replace(jsConfig.mwebUrl + '&redirect_url=' + window.location.protocol +
'//' + window.location.host + goPages + '&status=1');
return that.$util.Tips({
title: "支付中",
icon: 'success'
}, () => {
that.$emit('onChangeFun', {
action: 'pay_complete'
});
});
break;
}
}).catch(err => {
uni.hideLoading();
return that.$util.Tips({
title: err
}, () => {
that.$emit('onChangeFun', {
action: 'pay_fail'
});
});
})
}
}
}
</script>
<style scoped lang="scss">
.payment {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
border-radius: 16rpx 16rpx 0 0;
background-color: #fff;
padding-bottom: 60rpx;
z-index: 99;
transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
transform: translate3d(0, 100%, 0);
}
.payment.on {
transform: translate3d(0, 0, 0);
}
.payment .title {
text-align: center;
height: 123rpx;
font-size: 32rpx;
color: #282828;
font-weight: bold;
padding-right: 30rpx;
margin-left: 30rpx;
position: relative;
border-bottom: 1rpx solid #eee;
}
.payment .title .iconfont {
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
font-size: 43rpx;
color: #8a8a8a;
font-weight: normal;
}
.payment .item {
border-bottom: 1rpx solid #eee;
height: 130rpx;
margin-left: 30rpx;
padding-right: 30rpx;
}
.payment .item .left {
width: 610rpx;
}
.payment .item .left .text {
width: 540rpx;
}
.payment .item .left .text .name {
font-size: 32rpx;
color: #282828;
}
.payment .item .left .text .info {
font-size: 24rpx;
color: #999;
}
.payment .item .left .text .info .money {
color: #ff9900;
}
.payment .item .left .iconfont {
font-size: 45rpx;
color: #09bb07;
}
.payment .item .left .iconfont.icon-zhifubao {
color: #00aaea;
}
.payment .item .left .iconfont.icon-yuezhifu {
color: #ff9900;
}
.payment .item .left .iconfont.icon-yuezhifu1 {
color: #eb6623;
}
.payment .item .iconfont {
font-size: 0.3rpx;
color: #999;
}
</style>
+151
View File
@@ -0,0 +1,151 @@
<template>
<view class='product-bg'>
<swiper :indicator-dots="indicatorDots" indicator-active-color="#e93323" :autoplay="autoplay"
:circular="circular" :interval="interval" :duration="duration" @change="change">
<!-- 视频 -->
<swiper-item v-if="videoline">
<view class="item">
<view v-show="!controls" style="width:100%;height:100% ">
<video id="myVideo" :src='videoline' objectFit="cover" controls style="width:100%;height:100% "
show-center-play-btn show-mute-btn="true" auto-pause-if-navigate :custom-cache="false"
:enable-progress-gesture="false" :poster="imgUrls[0]" @pause="videoPause"></video>
</view>
<view class="poster" v-show="controls">
<image class="image" :src="imgUrls[0]"></image>
</view>
<view class="stop" v-show="controls" @tap="bindPause">
<image class="image" src="../../static/images/stop.png"></image>
</view>
</view>
</swiper-item>
<!-- 图片 -->
<block v-for="(item,index) in imgUrls" :key='index'>
<swiper-item>
<image :src="item" class="slide-image" />
</swiper-item>
</block>
</swiper>
</view>
</template>
<script>
export default {
props: {
imgUrls: {
type: Array,
default: function() {
return [];
}
},
videoline: {
type: String,
value: ""
}
},
data() {
return {
indicatorDots: true,
circular: true,
autoplay: true,
interval: 3000,
duration: 500,
currents: "1",
controls: true,
isPlay:true,
videoContext:''
};
},
mounted() {
if (this.videoline) {
this.imgUrls.shift()
}
},
methods: {
videoPause(e){
},
bindPause: function() {
this.videoContext.play();
this.$set(this, 'controls', false)
this.autoplay = false
},
change: function(e) {
this.$set(this, 'currents', e.detail.current + 1);
}
}
}
</script>
<style scoped lang="scss">
.product-bg {
width: 100%;
height: 750rpx;
position: relative;
}
.product-bg swiper {
width: 100%;
height: 100%;
position: relative;
}
.product-bg .slide-image {
width: 100%;
height: 100%;
}
.product-bg .pages {
position: absolute;
background-color: #fff;
height: 34rpx;
padding: 0 10rpx;
border-radius: 3rpx;
right: 30rpx;
bottom: 30rpx;
line-height: 34rpx;
font-size: 24rpx;
color: #050505;
}
#myVideo {
width: 100%;
height: 100%
}
.product-bg .item {
position: relative;
width: 100%;
height: 100%;
}
.product-bg .item .poster {
position: absolute;
top: 0;
left: 0;
height: 750rpx;
width: 100%;
z-index: 9;
}
.product-bg .item .poster .image {
width: 100%;
height: 100%;
}
.product-bg .item .stop {
position: absolute;
top: 50%;
left: 50%;
width: 136rpx;
height: 136rpx;
margin-top: -68rpx;
margin-left: -68rpx;
z-index: 9;
}
.product-bg .item .stop .image {
width: 100%;
height: 100%;
}
</style>
+350
View File
@@ -0,0 +1,350 @@
<template>
<view>
<view class="product-window"
:class="(attr.cartAttr === true ? 'on' : '') + ' ' + (iSbnt ? 'join':'') + ' ' + (iScart ? 'joinCart':'')">
<view class="textpic acea-row row-between-wrapper">
<view class="pictrue">
<image :src="attr.productSelect.picUrl"></image>
</view>
<view class="text">
<view class="line1">
{{ attr.productSelect.spuName }}
</view>
<view class="money font-color">
¥<text class="num">{{ fen2yuan(attr.productSelect.price) }}</text>
<text class="stock" v-if='isShow'>库存: {{ attr.productSelect.stock }}</text>
<text class='stock' v-if="attr.productSelect.limitCount > 0">限购: {{ attr.productSelect.limitCount }}</text>
</view>
</view>
<view class="iconfont icon-guanbi" @click="close"></view>
</view>
<view class="rollTop">
<!-- 属性 key + value 列表 -->
<view class="productWinList">
<view class="item" v-for="(property, propertyIndex) in attr.properties" :key="propertyIndex">
<view class="title">{{ property.name }}</view>
<view class="listn acea-row row-middle">
<view class="itemn" :class="property.index === value.name ? 'on' : ''"
v-for="(value, valueIndex) in property.values" :key="valueIndex"
@click="clickProperty(propertyIndex, valueIndex)">
{{ value.name }}
</view>
</view>
</view>
</view>
<view class="cart acea-row row-between-wrapper">
<view class="title">数量</view>
<view class="carnum acea-row row-left">
<view class="item reduce" :class="attr.productSelect.cart_num <= 1 ? 'on' : ''"
@click="CartNumDes">
-
</view>
<view class='item num'>
<input type="number" v-model="attr.productSelect.cart_num"
data-name="productSelect.cart_num"
@input="bindCode(attr.productSelect.cart_num)" />
</view>
<view v-if="iSplus" class="item plus" :class="attr.productSelect.cart_num >= attr.productSelect.stock ? 'on' : ''" @click="CartNumAdd">
+
</view>
<view v-else class='item plus'
:class='(attr.productSelect.cart_num >= attr.productSelect.stock)
|| (attr.productSelect.cart_num >= attr.productSelect.limitCount)
? "on":""'
@click='CartNumAdd'>+</view>
</view>
</view>
</view>
<!-- TODO 芋艿:拼团 -->
<view class="joinBnt bg-color" v-if="iSbnt && attr.productSelect.stock > 0"
@click="goCat">我要参团</view>
<view class="joinBnt on"
v-else-if="iSbnt && attr.productSelect.stock <= 0">已售罄</view>
<!-- TODO 芋艿:购物车 -->
<view class="joinBnt bg-color" v-if="iScart && attr.productSelect.stock"
@click="goCat">确定</view>
<view class="joinBnt on"
v-else-if="(iScart && !attr.productSelect.stock)">已售罄</view>
</view>
<view class="mask" @touchmove.prevent :hidden="attr.cartAttr === false" @click="close"></view>
</view>
</template>
<script>
import * as Util from '@/utils/util.js';
export default {
props: {
attr: {
type: Object,
default: () => {}
},
isShow: { // 是否展示库存
type: Number,
value: 0
},
iSbnt: { // 是否拼团商品
type: Number,
value: 0
},
iSplus: { // 是否允许 + - 操作
type: Number,
value: 0
},
iScart: { // 是否来自购物车界面
type: Number,
value: 0
}
},
data() {
return {};
},
mounted() {},
methods: {
goCat: function() {
this.$emit('goCat');
},
/**
* 购物车手动输入数量
*/
bindCode: function(e) {
// TODO 芋艿:【优化】方法名的处理;是否可去掉这个事件,统一处理
this.$emit('iptCartNum', this.attr.productSelect.cart_num);
},
close: function() {
this.$emit('close');
},
CartNumDes: function() {
// TODO 芋艿:【优化】方法名的处理;是否可去掉这个事件,统一处理
this.$emit('ChangeCartNum', false);
},
CartNumAdd: function() {
// TODO 芋艿:【优化】方法名的处理;是否可去掉这个事件,统一处理
this.$emit('ChangeCartNum', true);
},
/**
* 选中某个规格属性
*
* @param propertyIndex properties 的下标
* @param valueIndex values 的下标
*/
clickProperty: function(propertyIndex, valueIndex) {
this.$set(this.attr.properties[propertyIndex], 'index', this.attr.properties[propertyIndex].values[valueIndex].name);
let newSkuKey = this.getCheckedValueNames().join(",");
// TODO 芋艿:【优化】修改下 ChangeAttr 名字,改成 selectSku 更合适
this.$emit("ChangeAttr", newSkuKey, propertyIndex, valueIndex);
},
/**
* 获取被选中属性值的数组
*
* @returns {*[]} 例如说,['红色', '大']
*/
getCheckedValueNames: function() {
let properties = this.attr.properties;
let valueNames = [];
for (let i = 0; i < properties.length; i++) {
for (let j = 0; j < properties[i].values.length; j++) {
if (properties[i].index === properties[i].values[j].name) {
valueNames.push(properties[i].values[j].name);
}
}
}
return valueNames;
},
fen2yuan(price) {
return Util.fen2yuan(price)
}
}
}
</script>
<style scoped lang="scss">
.product-window {
position: fixed;
bottom: 0;
width: 100%;
left: 0;
background-color: #fff;
z-index: 77;
border-radius: 16rpx 16rpx 0 0;
padding-bottom: 140rpx;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
}
.product-window.on {
transform: translate3d(0, 0, 0);
}
.product-window.join {
padding-bottom: 30rpx;
}
.product-window.joinCart {
padding-bottom: 30rpx;
z-index: 999;
}
.product-window .textpic {
padding: 0 130rpx 0 30rpx;
margin-top: 29rpx;
position: relative;
}
.product-window .textpic .pictrue {
width: 150rpx;
height: 150rpx;
}
.product-window .textpic .pictrue image {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
.product-window .textpic .text {
width: 410rpx;
font-size: 32rpx;
color: #333333;
}
.product-window .textpic .text .money {
font-size: 24rpx;
margin-top: 40rpx;
}
.product-window .textpic .text .money .num {
font-size: 36rpx;
}
.product-window .textpic .text .money .stock {
color: #999;
margin-left: 18rpx;
}
.product-window .textpic .iconfont {
position: absolute;
right: 30rpx;
top: -5rpx;
font-size: 35rpx;
color: #8a8a8a;
}
.product-window .rollTop {
max-height: 500rpx;
overflow: auto;
margin-top: 36rpx;
}
.product-window .productWinList .item~.item {
margin-top: 36rpx;
}
.product-window .productWinList .item .title {
font-size: 30rpx;
color: #999;
padding: 0 30rpx;
}
.product-window .productWinList .item .listn {
padding: 0 30rpx 0 16rpx;
}
.product-window .productWinList .item .listn .itemn {
border: 1px solid #F2F2F2;
font-size: 26rpx;
color: #282828;
padding: 7rpx 33rpx;
border-radius: 40rpx;
margin: 20rpx 0 0 14rpx;
background-color: #F2F2F2;
}
.product-window .productWinList .item .listn .itemn.on {
color: $theme-color;
background: rgba(255, 244, 243, 1);
border-color: $theme-color;
}
.product-window .productWinList .item .listn .itemn.limit {
color: #999;
text-decoration: line-through;
}
.product-window .cart {
margin-top: 36rpx;
padding: 0 30rpx;
}
.product-window .cart .title {
font-size: 30rpx;
color: #999;
}
.product-window .cart .carnum {
height: 54rpx;
margin-top: 24rpx;
}
.product-window .cart .carnum view {
// border: 1px solid #a4a4a4;
width: 84rpx;
text-align: center;
height: 100%;
line-height: 54rpx;
color: #282828;
font-size: 45rpx;
}
.product-window .cart .carnum .reduce {
border-right: 0;
border-radius: 6rpx 0 0 6rpx;
line-height: 48rpx;
}
.product-window .cart .carnum .reduce.on {
// border-color: #e3e3e3;
color: #DEDEDE;
font-size: 44rpx;
}
.product-window .cart .carnum .plus {
border-left: 0;
border-radius: 0 6rpx 6rpx 0;
line-height: 46rpx;
}
.product-window .cart .carnum .plus.on {
border-color: #e3e3e3;
color: #dedede;
}
.product-window .cart .carnum .num {
background: rgba(242, 242, 242, 1);
color: #282828;
font-size: 28rpx;
border-radius: 12rpx;
line-height: 29px;
height: 54rpx;
input {
display: -webkit-inline-box;
}
}
.product-window .joinBnt {
font-size: 30rpx;
width: 620rpx;
height: 86rpx;
border-radius: 50rpx;
text-align: center;
line-height: 86rpx;
color: #fff;
margin: 21rpx auto 0 auto;
}
.product-window .joinBnt.on {
background-color: #bbb;
color: #fff;
}
</style>
+115
View File
@@ -0,0 +1,115 @@
<template>
<view class='recommend'>
<view class='title acea-row row-center-wrapper'>
<text class='iconfont icon-zhuangshixian'></text>
<text class='name'>热门推荐</text>
<text class='iconfont icon-zhuangshixian lefticon'></text>
</view>
<view class='recommendList acea-row row-between-wrapper'>
<view class='item' v-for="(item,index) in hostProduct" :key="index" hover-class='none' @tap="goDetail(item)">
<view class='pictrue'>
<image :src='item.picUrl'></image>
<span class="pictrue_log_big pictrue_log_class" v-if="item.activityList && item.activityList[0] && item.activityList[0].type === 1">秒杀</span>
<span class="pictrue_log_big pictrue_log_class" v-if="item.activityList && item.activityList[0] && item.activityList[0].type === 2">砍价</span>
<span class="pictrue_log_big pictrue_log_class" v-if="item.activityList && item.activityList[0] && item.activityList[0].type === 3">拼团</span>
</view>
<view class='name line1'>{{ item.name }}</view>
<view class='money font-color'>¥<text class='num'>{{ fen2yuan(item.price) }}</text></view>
</view>
</view>
</view>
</template>
<script>
import { mapGetters } from "vuex";
import { goShopDetail } from '@/libs/order.js'
import * as Util from '@/utils/util.js';
export default {
computed: mapGetters(['uid']),
props: {
hostProduct: {
type: Array,
default: function() {
return [];
}
}
},
methods: {
goDetail(item){
goShopDetail(item,this.uid).then(() => {
uni.navigateTo({
url:`/pages/goods_details/index?id=${item.id}`
})
})
},
fen2yuan(price) {
return Util.fen2yuan(price)
}
}
}
</script>
<style scoped lang="scss">
.recommend {
background-color: #fff;
}
.recommend .title {
height: 135rpx;
line-height: 135rpx;
font-size: 28rpx;
color: #282828;
}
.recommend .title .name {
margin: 0 28rpx;
}
.recommend .title .iconfont {
font-size: 170rpx;
color: #454545;
}
.recommend .title .iconfont.lefticon {
transform: rotate(180deg);
}
.recommend .recommendList {
padding: 0 30rpx;
/* #ifdef H5 */
padding-bottom: 50rpx;
/* #endif */
}
.recommend .recommendList .item {
width: 335rpx;
margin-bottom: 30rpx;
}
.recommend .recommendList .item .pictrue {
position: relative;
width: 100%;
height: 335rpx;
}
.recommend .recommendList .item .pictrue image {
width: 100%;
height: 100%;
border-radius: 14rpx;
}
.recommend .recommendList .item .name {
font-size: 28rpx;
color: #282828;
margin-top: 20rpx;
}
.recommend .recommendList .item .money {
font-size: 20rpx;
margin-top: 8rpx;
font-weight: 600;
}
.recommend .recommendList .item .money .num {
font-size: 28rpx;
}
</style>
+43
View File
@@ -0,0 +1,43 @@
<template>
<view v-if="shareInfoStatus" class="poster-first">
<view class="mask-share">
<image src="/static/images/share-info.png" @click="shareInfoClose" @touchmove.stop.prevent="false" />
</view>
</view>
</template>
<script>
export default {
props: {
shareInfoStatus: {
type: Boolean,
default:false,
}
},
data: function() {
return {};
},
mounted: function() {},
methods: {
shareInfoClose: function() {
this.$emit("setShareInfoStatus");
}
}
};
</script>
<style scoped lang="scss">
.poster-first {
overscroll-behavior: contain;
}
.mask-share {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 99;
}
.mask-share image {
width: 100%;
height:100%;
}
</style>
+75
View File
@@ -0,0 +1,75 @@
<template>
<view class='sharing-packets' :class='!enabled ? "on":""'>
<view class='iconfont icon-guanbi' @click="closeShare"></view>
<view class='line'></view>
<view class='sharing-con' @click='goShare'>
<image src='../../static/images/red-packets.png'></image>
<view class='text font-color'>
<view>会员分享返</view>
<view class='money' v-if="sharePacket.brokerageMinPrice && sharePacket.brokerageMaxPrice">
<text class='label'>¥</text>{{ fen2yuan(sharePacket.brokerageMinPrice) }}~{{ fen2yuan(sharePacket.brokerageMaxPrice) }}
</view>
<view class='money' v-else-if="sharePacket.brokerageMinPrice">
<text class='label'>¥</text>{{ fen2yuan(sharePacket.brokerageMinPrice) }}
</view>
<view class='money' v-else-if="sharePacket.brokerageMaxPrice">
<text class='label'>¥</text>{{ fen2yuan(sharePacket.brokerageMaxPrice) }}
</view>
<view class='tip'>下单即返佣金</view>
<view class='shareBut'>立即分享</view>
</view>
</view>
</view>
</template>
<script>
import * as Util from '@/utils/util.js';
export default {
props: {
sharePacket: {
type: Object,
default: function() {
return {
enabled: true,
brokerageMinPrice: undefined,
brokerageMaxPrice: undefined,
}
}
}
},
data() {
return {
};
},
computed: {
enabled() {
return this.sharePacket.enabled && (this.sharePacket.brokerageMinPrice || this.sharePacket.brokerageMaxPrice)
}
},
methods: {
closeShare:function(){
this.$emit('closeChange');
},
goShare:function(){
this.$emit('listenerActionSheet');
},
fen2yuan(price) {
return Util.fen2yuan(price)
}
}
}
</script>
<style scoped lang="scss">
.sharing-packets{position:fixed;left:30rpx;bottom:200rpx;z-index:5;transition:all 0.3s ease-in-out 0s;opacity:1;transform: scale(1);}
.sharing-packets.on{transform: scale(0);opacity:0;}
.sharing-packets .iconfont{width:44rpx;height:44rpx;border-radius:50%;text-align:center;line-height:44rpx;background-color:#999;font-size:20rpx;color:#fff;margin:0 auto;box-sizing:border-box;padding-left:1px;}
.sharing-packets .line{width:2rpx;height:40rpx;background-color:#999;margin:0 auto;}
.sharing-packets .sharing-con{width:187rpx;height:210rpx;position:relative;}
.sharing-packets .sharing-con image{width:100%;height:100%;}
.sharing-packets .sharing-con .text{position:absolute;top:30rpx;font-size:20rpx;width:100%;text-align:center;}
.sharing-packets .sharing-con .text .money{font-size:32rpx;font-weight:bold;margin-top:5rpx;white-space: nowrap}
.sharing-packets .sharing-con .text .money .label{font-size:20rpx;}
.sharing-packets .sharing-con .text .tip{font-size:18rpx;color:#999;margin-top:5rpx;}
.sharing-packets .sharing-con .text .shareBut{font-size:22rpx;color:#fff;margin-top:18rpx;height:50rpx;line-height:50rpx;}
</style>
+52
View File
@@ -0,0 +1,52 @@
<template>
<view class='swiper'>
<swiper :autoplay="autoplay" :circular="circular" :interval="interval" :duration="duration" @change="swiperChange">
<block v-for="(item,index) in imgUrls" :key="index">
<swiper-item>
<navigator :url="item.link" style='width:100%;height:100%;' hover-class='none'><image :src="item.img" class="slide-image"/></navigator>
</swiper-item>
</block>
</swiper>
<view class="dots acea-row">
<view class="dot" :class="index == currentSwiper ? 'active' : ''" v-for="(item,index) in imgUrls" :key="index"></view>
</view>
</view>
</template>
<script>
export default {
props: {
imgUrls: {
type: Array,
default: function(){
return [];
}
}
},
data() {
return {
circular: true,
autoplay: true,
interval: 3000,
duration: 500,
currentSwiper: 0
};
},
methods: {
swiperChange: function (e) {
this.currentSwiper = e.detail.current
}
}
}
</script>
<style scoped lang="scss">
.swiper{width:100%;height:282rpx;position:relative;}
.swiper swiper{width:100%;height:100%;position:relative;}
.swiper swiper .slide-image{width:100%;height:100%;}
.swiper .dots{position:absolute;right:40rpx;bottom:20rpx;}
.swiper .dots .dot{width:12rpx;height:12rpx;border:2rpx solid #fff;border-radius:50%;margin-right:15rpx;}
.swiper .dots .dot.active{border-color:$theme-color;background-color:$theme-color;}
</style>
+165
View File
@@ -0,0 +1,165 @@
<template>
<canvas v-if="canvasId" :id="canvasId" :canvasId="canvasId" :style="{'width':cWidth*pixelRatio+'px','height':cHeight*pixelRatio+'px', 'transform': 'scale('+(1/pixelRatio)+')','margin-left':-cWidth*(pixelRatio-1)/2+'px','margin-top':-cHeight*(pixelRatio-1)/2+'px'}"
@touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" @error="error">
</canvas>
</template>
<script>
import uCharts from './u-charts.js';
var canvases = {};
export default {
props: {
chartType: {
required: true,
type: String,
default: 'column'
},
opts: {
required: true,
type: Object,
default () {
return null;
},
},
canvasId: {
type: String,
default: 'u-canvas',
},
cWidth: {
default: 375,
},
cHeight: {
default: 250,
},
pixelRatio: {
type: Number,
default: 1,
},
},
mounted() {
this.init();
},
methods: {
init() {
switch (this.chartType) {
case 'column':
this.initColumnChart();
break;
case 'line':
this.initLineChart();
break;
default:
break;
}
},
initColumnChart() {
canvases[this.canvasId] = new uCharts({
$this: this,
canvasId: this.canvasId,
type: 'column',
legend: true,
fontSize: 11,
background: '#FFFFFF',
pixelRatio: this.pixelRatio,
animation: true,
categories: this.opts.categories,
series: this.opts.series,
enableScroll: true,
xAxis: {
disableGrid: true,
itemCount: 4,
scrollShow: true
},
yAxis: {
//disabled:true
},
dataLabel: true,
width: this.cWidth * this.pixelRatio,
height: this.cHeight * this.pixelRatio,
extra: {
column: {
type: 'group',
}
}
});
},
initLineChart() {
canvases[this.canvasId] = new uCharts({
$this: this,
canvasId: this.canvasId,
type: 'line',
fontSize: 11,
legend: true,
dataLabel: false,
dataPointShape: true,
background: '#FFFFFF',
pixelRatio: this.pixelRatio,
categories: this.opts.categories,
series: this.opts.series,
animation: true,
enableScroll: true,
xAxis: {
type: 'grid',
gridColor: '#CCCCCC',
gridType: 'dash',
dashLength: 8,
itemCount: 4,
scrollShow: true
},
yAxis: {
gridType: 'dash',
gridColor: '#CCCCCC',
dashLength: 8,
splitNumber: 5,
min: 10,
max: 180,
format: (val) => {
return val.toFixed(0) + '元'
}
},
width: this.cWidth * this.pixelRatio,
height: this.cHeight * this.pixelRatio,
extra: {
line: {
type: 'straight'
}
}
});
},
// 这里仅作为示例传入两个参数,cid为canvas-id,newdata为更新的数据,需要更多参数请自行修改
changeData(cid,newdata) {
canvases[cid].updateData({
series: newdata.series,
categories: newdata.categories
});
},
touchStart(e) {
canvases[this.canvasId].showToolTip(e, {
format: function(item, category) {
return category + ' ' + item.name + ':' + item.data
}
});
canvases[this.canvasId].scrollStart(e);
},
touchMove(e) {
canvases[this.canvasId].scroll(e);
},
touchEnd(e) {
canvases[this.canvasId].scrollEnd(e);
},
error(e) {
console.log(e)
}
},
};
</script>
<style scoped>
.charts {
width: 100%;
height: 100%;
flex: 1;
background-color: #FFFFFF;
}
</style>
File diff suppressed because it is too large. Load diff
+1
View File
@@ -0,0 +1 @@
'use strict';var config={yAxisWidth:15,yAxisSplit:5,xAxisHeight:15,xAxisLineHeight:15,legendHeight:15,yAxisTitleWidth:15,padding:[10,10,10,10],pixelRatio:1,rotate:!1,columePadding:3,fontSize:13,dataPointShape:["circle","circle","circle","circle"],colors:["#1890ff","#2fc25b","#facc14","#f04864","#8543e0","#90ed7d"],pieChartLinePadding:15,pieChartTextPadding:5,xAxisTextPadding:3,titleColor:"#333333",titleFontSize:20,subtitleColor:"#999999",subtitleFontSize:15,toolTipPadding:3,toolTipBackground:"#000000",toolTipOpacity:.7,toolTipLineHeight:20,radarLabelTextMargin:15,gaugeLabelTextMargin:15};let assign=function(e,...t){function i(e,t){for(let a in t)e[a]=e[a]&&"[object Object]"===e[a].toString()?i(e[a],t[a]):e[a]=t[a];return e}if(null==e)throw new TypeError("Cannot convert undefined or null to object");return!t||0>=t.length?e:(t.forEach(t=>{e=i(e,t)}),e)};var util={toFixed:function(e,t){return t=t||2,this.isFloat(e)&&(e=e.toFixed(t)),e},isFloat:function(e){return 0!=e%1},approximatelyEqual:function(e,t){return 1e-10>Math.abs(e-t)},isSameSign:function(e,t){var i=Math.abs;return i(e)===e&&i(t)===t||i(e)!==e&&i(t)!==t},isSameXCoordinateArea:function(e,t){return this.isSameSign(e.x,t.x)},isCollision:function(e,t){e.end={},e.end.x=e.start.x+e.width,e.end.y=e.start.y-e.height,t.end={},t.end.x=t.start.x+t.width,t.end.y=t.start.y-t.height;var i=t.start.x>e.end.x||t.end.x<e.start.x||t.end.y>e.start.y||t.start.y<e.end.y;return!i}};function getH5Offset(t){return t.mp={changedTouches:[]},t.mp.changedTouches.push({x:t.offsetX,y:t.offsetY}),t}function hexToRgb(e,t){var i=/^#?([a-f\d])([a-f\d])([a-f\d])$/i,a=e.replace(i,function(e,t,i,a){return t+t+i+i+a+a}),o=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(a),n=parseInt(o[1],16),l=parseInt(o[2],16),r=parseInt(o[3],16);return"rgba("+n+","+l+","+r+","+t+")"}function findRange(e,t,i){if(isNaN(e))throw new Error("[uCharts] unvalid series data!");i=i||10,t=t?t:"upper";for(var a=1;1>i;)i*=10,a*=10;for(e="upper"===t?Math.ceil(e*a):Math.floor(e*a);0!=e%i;)"upper"===t?e++:e--;return e/a}function calCandleMA(e,t,i,a){let o=[];for(let n,l=0;l<e.length;l++){n={data:[],name:t[l],color:i[l]};for(let t=0,i=a.length;t<i;t++){if(t<e[l]){n.data.push(null);continue}let i=0;for(let o=0;o<e[l];o++)i+=a[t-o][1];n.data.push(+(i/e[l]).toFixed(3))}o.push(n)}return o}function calValidDistance(e,t,i,a,o){var n=o.width-o.area[1]-o.area[3],l=i.eachSpacing*(o.chartData.xAxisData.xAxisPoints.length-1),r=t;return 0<=t?(r=0,e.event.trigger("scrollLeft")):Math.abs(t)>=l-n&&(r=n-l,e.event.trigger("scrollRight")),r}function isInAngleRange(e,t,i){function a(e){for(;0>e;)e+=2*o;for(;e>2*o;)e-=2*o;return e}var o=Math.PI;return e=a(e),t=a(t),i=a(i),t>i&&(i+=2*o,e<t&&(e+=2*o)),e>=t&&e<=i}function calRotateTranslate(e,t,i){var a=e,o=i-t,n=a+(i-o-a)/1.4142135623730951;n*=-1;return{transX:n,transY:(i-o)*(1.4142135623730951-1)-(i-o-a)/1.4142135623730951}}function createCurveControlPoints(e,t){function i(e,t){return!!(e[t-1]&&e[t+1])&&(e[t].y>=l(e[t-1].y,e[t+1].y)||e[t].y<=n(e[t-1].y,e[t+1].y))}function o(e,t){return!!(e[t-1]&&e[t+1])&&(e[t].x>=l(e[t-1].x,e[t+1].x)||e[t].x<=n(e[t-1].x,e[t+1].x))}var n=Math.min,l=Math.max,r=.2,a=.2,s=null,d=null,h=null,x=null;if(1>t?(s=e[0].x+(e[1].x-e[0].x)*r,d=e[0].y+(e[1].y-e[0].y)*r):(s=e[t].x+(e[t+1].x-e[t-1].x)*r,d=e[t].y+(e[t+1].y-e[t-1].y)*r),t>e.length-3){var c=e.length-1;h=e[c].x-(e[c].x-e[c-1].x)*a,x=e[c].y-(e[c].y-e[c-1].y)*a}else h=e[t+1].x-(e[t+2].x-e[t].x)*a,x=e[t+1].y-(e[t+2].y-e[t].y)*a;return i(e,t+1)&&(x=e[t+1].y),i(e,t)&&(d=e[t].y),o(e,t+1)&&(h=e[t+1].x),o(e,t)&&(s=e[t].x),(d>=l(e[t].y,e[t+1].y)||d<=n(e[t].y,e[t+1].y))&&(d=e[t].y),(x>=l(e[t].y,e[t+1].y)||x<=n(e[t].y,e[t+1].y))&&(x=e[t+1].y),(s>=l(e[t].x,e[t+1].x)||s<=n(e[t].x,e[t+1].x))&&(s=e[t].x),(h>=l(e[t].x,e[t+1].x)||h<=n(e[t].x,e[t+1].x))&&(h=e[t+1].x),{ctrA:{x:s,y:d},ctrB:{x:h,y:x}}}function convertCoordinateOrigin(e,t,i){return{x:i.x+e,y:i.y-t}}function avoidCollision(e,t){if(t)for(;util.isCollision(e,t);)0<e.start.x?e.start.y--:0>e.start.x?e.start.y++:0<e.start.y?e.start.y++:e.start.y--;return e}function fillSeries(e,t,i){var a=0;return e.map(function(e){if(e.color||(e.color=i.colors[a],a=(a+1)%i.colors.length),e.index||(e.index=0),e.type||(e.type=t.type),"undefined"==typeof e.show&&(e.show=!0),e.type||(e.type=t.type),e.pointShape||(e.pointShape="circle"),!e.legendShape)switch(e.type){case"line":e.legendShape="line";break;case"column":e.legendShape="rect";break;case"area":e.legendShape="triangle";break;default:e.legendShape="circle";}return e})}function getDataRange(e,t){var i=0,a=t-e;return i=1e4<=a?1e3:1e3<=a?100:100<=a?10:10<=a?5:1<=a?1:.1<=a?.1:.01<=a?.01:.001<=a?.001:1e-4<=a?1e-4:1e-5<=a?1e-5:1e-6,{minRange:findRange(e,"lower",i),maxRange:findRange(t,"upper",i)}}function measureText(e){var t=1<arguments.length&&arguments[1]!==void 0?arguments[1]:config.fontSize;e=e+"";var e=e.split(""),a=0;for(let t,o=0;o<e.length;o++)t=e[o],a+=/[a-zA-Z]/.test(t)?7:/[0-9]/.test(t)?5.5:/\./.test(t)?2.7:/-/.test(t)?3.25:Line truncated
@@ -0,0 +1,152 @@
<template>
<view class="uni-calendar-item__weeks-box" :class="{
'uni-calendar-item--disable':weeks.disable,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) ,
'uni-calendar-item--multiple': weeks.multiple
}"
@click="choiceDate(weeks)">
<view class="uni-calendar-item__weeks-box-item">
<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
<text class="uni-calendar-item__weeks-box-text" :class="{
'uni-calendar-item--isDay-text': weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--disable':weeks.disable,
}">{{weeks.date}}</text>
<text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{
'uni-calendar-item--isDay-text':weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--multiple': weeks.multiple,
}">今天</text>
<text v-if="lunar&&!weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text" :class="{
'uni-calendar-item--isDay-text':weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--disable':weeks.disable,
}">{{weeks.isDay?'今天': (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text>
<text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{
'uni-calendar-item--extra':weeks.extraInfo.info,
'uni-calendar-item--isDay-text':weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--disable':weeks.disable,
}">{{weeks.extraInfo.info}}</text>
</view>
</view>
</template>
<script>
export default {
props: {
weeks: {
type: Object,
default () {
return {}
}
},
calendar: {
type: Object,
default: () => {
return {}
}
},
selected: {
type: Array,
default: () => {
return []
}
},
lunar: {
type: Boolean,
default: false
}
},
methods: {
choiceDate(weeks) {
this.$emit('change', weeks)
}
}
}
</script>
<style lang="scss" scoped>
.uni-calendar-item__weeks-box {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
}
.uni-calendar-item__weeks-box-text {
font-size: $uni-font-size-base;
color: $uni-text-color;
}
.uni-calendar-item__weeks-lunar-text {
font-size: $uni-font-size-sm;
color: $uni-text-color;
}
.uni-calendar-item__weeks-box-item {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
width: 100rpx;
height: 100rpx;
}
.uni-calendar-item__weeks-box-circle {
position: absolute;
top: 5px;
right: 5px;
width: 8px;
height: 8px;
border-radius: 8px;
background-color: $uni-color-error;
}
.uni-calendar-item--disable {
background-color: rgba(249, 249, 249, $uni-opacity-disabled);
color: $uni-text-color-disable;
}
.uni-calendar-item--isDay-text {
color: $uni-color-primary;
}
.uni-calendar-item--isDay {
background-color: $uni-color-primary;
opacity: 0.8;
color: #fff;
}
.uni-calendar-item--extra {
color: $uni-color-error;
opacity: 0.8;
}
.uni-calendar-item--checked {
background-color: $uni-color-primary;
color: #fff;
opacity: 0.8;
}
.uni-calendar-item--multiple {
background-color: $uni-color-primary;
color: #fff;
opacity: 0.8;
}
</style>
+434
View File
@@ -0,0 +1,434 @@
<template>
<view class="uni-calendar" @touchmove.stop.prevent="clean">
<view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}" @click="clean"></view>
<view v-if="insert || show" class="uni-calendar__content" :class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow}">
<view v-if="!insert" class="uni-calendar__header uni-calendar--fixed-top">
<view class="uni-calendar__header-btn-box" @click="close">
<text class="uni-calendar__header-text uni-calendar--fixed-width">取消</text>
</view>
<view class="uni-calendar__header-btn-box" @click="confirm">
<text class="uni-calendar__header-text uni-calendar--fixed-width">确定</text>
</view>
</view>
<view class="uni-calendar__header">
<view class="uni-calendar__header-btn-box" @click="pre">
<view class="uni-calendar__header-btn uni-calendar--left"></view>
</view>
<text class="uni-calendar__header-text">{{ (nowDate.year||'') +'年'+( nowDate.month||'') +'月'}}</text>
<view class="uni-calendar__header-btn-box" @click="next">
<view class="uni-calendar__header-btn uni-calendar--right"></view>
</view>
<text class="uni-calendar__backtoday" @click="backtoday">回到今天</text>
</view>
<view class="uni-calendar__box">
<view v-if="showMonth" class="uni-calendar__box-bg">
<text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
</view>
<view class="uni-calendar__weeks">
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">日</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">一</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">二</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">三</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">四</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">五</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">六</text>
</view>
</view>
<view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
<view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
<uni-calendar-item :weeks="weeks" :calendar="calendar" :selected="selected" :lunar="lunar" @change="choiceDate"></uni-calendar-item>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import Calendar from './util.js';
import uniCalendarItem from './uni-calendar-item.vue'
export default {
components: {
uniCalendarItem
},
props: {
/**
* 当前日期
*/
date: {
type: String,
default: ''
},
/**
* 打点日期
*/
selected: {
type: Array,
default () {
return []
}
},
/**
* 是否开启阴历日期
*/
lunar: {
type: Boolean,
default: false
},
/**
* 开始时间
*/
startDate: {
type: String,
default: ''
},
/**
* 结束时间
*/
endDate: {
type: String,
default: ''
},
/**
* 范围
*/
range: {
type: Boolean,
default: false
},
/**
* 插入
*/
insert: {
type: Boolean,
default: true
},
/**
* 是否显示月份背景
*/
showMonth: {
type: Boolean,
default: true
}
},
data() {
return {
show: false,
weeks: [],
calendar: {},
nowDate: '',
aniMaskShow: false
}
},
watch: {
selected(newVal) {
this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
this.weeks = this.cale.weeks
}
},
created() {
// 获取日历方法实例
this.cale = new Calendar({
date: this.date,
selected: this.selected,
startDate: this.startDate,
endDate: this.endDate,
range: this.range,
})
this.init(this.cale.date.fullDate)
},
methods: {
// 取消穿透
clean() {},
init(date) {
this.weeks = this.cale.weeks
this.nowDate = this.calendar = this.cale.getInfo(date)
},
open() {
this.show = true
this.$nextTick(() => {
setTimeout(()=>{
this.aniMaskShow = true
},50)
})
},
close() {
this.aniMaskShow = false
this.$nextTick(() => {
setTimeout(() => {
this.show = false
}, 300)
})
},
confirm() {
this.setEmit('confirm')
this.close()
},
change() {
if (!this.insert) return
this.setEmit('change')
},
monthSwitch() {
let {
year,
month
} = this.nowDate
this.$emit('monthSwitch', {
year,
month: Number(month)
})
},
setEmit(name) {
let {
year,
month,
date,
fullDate,
lunar,
extraInfo
} = this.calendar
this.$emit(name, {
range: this.cale.multipleStatus,
year,
month,
date,
fulldate: fullDate,
lunar,
extraInfo: extraInfo || {}
})
},
choiceDate(weeks) {
if (weeks.disable) return
this.calendar = weeks
// 设置多选
this.cale.setMultiple(this.calendar.fullDate)
this.weeks = this.cale.weeks
this.change()
},
backtoday() {
this.cale.setDate(this.date)
this.weeks = this.cale.weeks
this.nowDate = this.calendar = this.cale.getInfo(this.date)
this.change()
},
pre() {
const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate
this.setDate(preDate)
this.monthSwitch()
},
next() {
const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
this.setDate(nextDate)
this.monthSwitch()
},
setDate(date) {
this.cale.setDate(date)
this.weeks = this.cale.weeks
this.nowDate = this.cale.getInfo(date)
}
}
}
</script>
<style lang="scss" scoped>
.uni-calendar {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
}
.uni-calendar__mask {
position: fixed;
bottom: 0;
top: 0;
left: 0;
right: 0;
background-color: $uni-bg-color-mask;
transition-property: opacity;
transition-duration: 0.3s;
opacity: 0;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.uni-calendar--mask-show {
opacity: 1
}
.uni-calendar--fixed {
position: fixed;
bottom: 0;
left: 0;
right: 0;
transition-property: transform;
transition-duration: 0.3s;
transform: translateY(460px);
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.uni-calendar--ani-show {
transform: translateY(0);
}
.uni-calendar__content {
background-color: #fff;
}
.uni-calendar__header {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
height: 50px;
border-bottom-color: $uni-border-color;
border-bottom-style: solid;
border-bottom-width: 1px;
}
.uni-calendar--fixed-top {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
border-top-color: $uni-border-color;
border-top-style: solid;
border-top-width: 1px;
}
.uni-calendar--fixed-width {
width: 50px;
// padding: 0 15px;
}
.uni-calendar__backtoday {
position: absolute;
right: 0;
top: 25rpx;
padding: 0 5px;
padding-left: 10px;
height: 25px;
line-height: 25px;
font-size: 12px;
border-top-left-radius: 25px;
border-bottom-left-radius: 25px;
color: $uni-text-color;
background-color: $uni-bg-color-hover;
}
.uni-calendar__header-text {
text-align: center;
width: 100px;
font-size: $uni-font-size-base;
color: $uni-text-color;
}
.uni-calendar__header-btn-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
}
.uni-calendar__header-btn {
width: 10px;
height: 10px;
border-left-color: $uni-text-color-placeholder;
border-left-style: solid;
border-left-width: 2px;
border-top-color: $uni-color-subtitle;
border-top-style: solid;
border-top-width: 2px;
}
.uni-calendar--left {
transform: rotate(-45deg);
}
.uni-calendar--right {
transform: rotate(135deg);
}
.uni-calendar__weeks {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.uni-calendar__weeks-item {
flex: 1;
}
.uni-calendar__weeks-day {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
height: 45px;
border-bottom-color: #F5F5F5;
border-bottom-style: solid;
border-bottom-width: 1px;
}
.uni-calendar__weeks-day-text {
font-size: 14px;
}
.uni-calendar__box {
position: relative;
}
.uni-calendar__box-bg {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.uni-calendar__box-bg-text {
font-size: 200px;
font-weight: bold;
color: $uni-text-color-grey;
opacity: 0.1;
text-align: center;
/* #ifndef APP-NVUE */
line-height: 1;
/* #endif */
}
</style>
@@ -1,14 +1,15 @@
import CALENDAR from './calendar.js'
class Calendar {
constructor({
date,
selected,
startDate,
endDate,
range,
// multipleStatus
range
} = {}) {
// 当前日期
this.date = this.getDate(new Date()) // 当前初入日期
this.date = this.getDate(date) // 当前初入日期
// 打点信息
this.selected = selected || [];
// 范围开始
@@ -17,48 +18,15 @@ class Calendar {
this.endDate = endDate
this.range = range
// 多选状态
this.cleanMultipleStatus()
// 每周日期
this.weeks = {}
// this._getWeek(this.date.fullDate)
// this.multipleStatus = multipleStatus
this.lastHover = false
}
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this.selectDate = this.getDate(date)
this._getWeek(this.selectDate.fullDate)
}
/**
* 清理多选状态
*/
cleanMultipleStatus() {
this.multipleStatus = {
before: '',
after: '',
data: []
}
}
// 每周日期
this.weeks = {}
/**
* 重置开始日期
*/
resetSatrtDate(startDate) {
// 范围开始
this.startDate = startDate
}
/**
* 重置结束日期
*/
resetEndDate(endDate) {
// 范围结束
this.endDate = endDate
this._getWeek(this.date.fullDate)
}
/**
@@ -110,6 +78,7 @@ class Calendar {
dateArr.push({
date: beforeDate,
month: full.month - 1,
lunar: this.getlunar(full.year, full.month - 1, beforeDate),
disable: true
})
}
@@ -139,16 +108,15 @@ class Calendar {
let disableBefore = true
let disableAfter = true
if (this.startDate) {
// let dateCompBefore = this.dateCompare(this.startDate, fullDate)
// disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
disableBefore = this.dateCompare(this.startDate, nowDate)
let dateCompBefore = this.dateCompare(this.startDate, fullDate)
disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
}
if (this.endDate) {
// let dateCompAfter = this.dateCompare(fullDate, this.endDate)
// disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
disableAfter = this.dateCompare(nowDate, this.endDate)
let dateCompAfter = this.dateCompare(fullDate, this.endDate)
disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
}
let multiples = this.multipleStatus.data
let checked = false
let multiplesStatus = -1
@@ -162,17 +130,16 @@ class Calendar {
checked = true
}
}
let data = {
fullDate: nowDate,
year: full.year,
date: i,
multiple: this.range ? checked : false,
beforeMultiple: this.isLogicBefore(nowDate, this.multipleStatus.before, this.multipleStatus.after),
afterMultiple: this.isLogicAfter(nowDate, this.multipleStatus.before, this.multipleStatus.after),
month: full.month,
disable: !(disableBefore && disableAfter),
isDay,
userChecked: false
lunar: this.getlunar(full.year, full.month, i),
disable: !disableBefore || !disableAfter,
isDay
}
if (info) {
data.extraInfo = info
@@ -191,12 +158,19 @@ class Calendar {
dateArr.push({
date: i,
month: Number(full.month) + 1,
lunar: this.getlunar(full.year, Number(full.month) + 1, i),
disable: true
})
}
return dateArr
}
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this._getWeek(date)
}
/**
* 获取当前日期详情
* @param {Object} date
@@ -239,25 +213,6 @@ class Calendar {
}
}
/**
* 比较真实起始日期
*/
isLogicBefore(currentDay, before, after) {
let logicBefore = before
if (before && after) {
logicBefore = this.dateCompare(before, after) ? before : after
}
return this.dateEqual(logicBefore, currentDay)
}
isLogicAfter(currentDay, before, after) {
let logicAfter = after
if (before && after) {
logicAfter = this.dateCompare(before, after) ? after : before
}
return this.dateEqual(logicAfter, currentDay)
}
/**
* 获取日期范围内所有日期
@@ -280,6 +235,19 @@ class Calendar {
}
return arr
}
/**
* 计算阴历日期显示
*/
getlunar(year, month, date) {
return CALENDAR.solar2lunar(year, month, date)
}
/**
* 设置打点
*/
setSelectInfo(data, value) {
this.selected = value
this._getWeek(data)
}
/**
* 获取多选状态
@@ -291,72 +259,21 @@ class Calendar {
} = this.multipleStatus
if (!this.range) return
if (before && after) {
if (!this.lastHover) {
this.lastHover = true
return
}
this.multipleStatus.before = fullDate
this.multipleStatus.before = ''
this.multipleStatus.after = ''
this.multipleStatus.data = []
this.multipleStatus.fulldate = ''
this.lastHover = false
this._getWeek(fullDate)
} else {
if (!before) {
this.multipleStatus.before = fullDate
this.lastHover = false
} else {
this.multipleStatus.after = fullDate
if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
.after);
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
} else {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus
.before);
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
}
this.lastHover = true
}
}
this._getWeek(fullDate)
}
/**
* 鼠标 hover 更新多选状态
*/
setHoverMultiple(fullDate) {
let {
before,
after
} = this.multipleStatus
if (!this.range) return
if (this.lastHover) return
if (!before) {
this.multipleStatus.before = fullDate
} else {
this.multipleStatus.after = fullDate
if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
} else {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
}
}
this._getWeek(fullDate)
}
/**
* 更新默认值多选状态
*/
setDefaultMultiple(before, after) {
this.multipleStatus.before = before
this.multipleStatus.after = after
if (before && after) {
if (this.dateCompare(before, after)) {
this.multipleStatus.data = this.geDateAll(before, after);
this._getWeek(after)
} else {
this.multipleStatus.data = this.geDateAll(after, before);
this._getWeek(before)
this._getWeek(fullDate)
}
}
}
+156
View File
@@ -0,0 +1,156 @@
<template>
<view class="evaluateWtapper" v-if="reply.length > 0">
<view class="evaluateItem" v-for="(item, index) in reply" :key="index">
<view class="pic-text acea-row">
<view class="pictrue">
<image :src="item.userAvatar"></image>
</view>
<view class="content">
<view>
<view class="acea-row row-between">
<view class="acea-row">
<view class="name line1">{{ item.userNickname }}</view>
<view class="start" :class="'star' + item.scores"></view>
</view>
<view class="time">{{ formatDate(item.createTime) }}</view>
</view>
<view class="sku">规格:
<text v-for="(property, propertyIndex) in item.skuProperties" :key="propertyIndex" style="padding-right: 2px">
{{ property.valueName }}
</text>
</view>
</view>
<view class="evaluate-infor">{{ item.content }}</view>
<view class="imgList acea-row" v-if="item.picUrls && item.picUrls.length > 0">
<view class="pictrue" v-for="(picUrl, indexn) in item.picUrls" :key="indexn">
<image :src="picUrl" class="image" @click='getpreviewImage(index, indexn)'></image>
</view>
</view>
<view class="reply" v-if="item.replyContent">
<text class="font-color">店小二</text>:{{ item.replyContent }}
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import dayjs from "@/plugin/dayjs/dayjs.min.js";
export default {
props: {
reply: {
type: Array,
default: []
}
},
data: function() {
return {};
},
methods: {
getpreviewImage: function(indexw, indexn) {
uni.previewImage({
urls: this.reply[indexw].picUrls,
current: this.reply[indexw].picUrls[indexn]
});
},
formatDate: function(date) {
return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
}
}
}
</script>
<style scoped lang='scss'>
.evaluateWtapper .evaluateItem {
background-color: #fff;
padding: 24rpx;
border-bottom-left-radius: 14rpx;
border-bottom-right-radius: 14rpx;
}
.evaluateWtapper .evaluateItem~.evaluateItem {
border-top: 1rpx solid #f5f5f5;
}
.evaluateWtapper .evaluateItem .pic-text {
font-size: 26rpx;
color: #282828;
.content{
width: 84%;
margin-left: 20rpx;
}
}
.evaluateWtapper .evaluateItem .pic-text .pictrue {
width: 62rpx;
height: 62rpx;
}
.evaluateWtapper .evaluateItem .pic-text .pictrue image {
width: 100%;
height: 100%;
border-radius: 50%;
}
.evaluateWtapper .evaluateItem .pic-text .name {
max-width: 450rpx;
}
.evaluateWtapper .evaluateItem .time {
font-size: 24rpx;
color: #999999;
}
.sku{
font-size: 24rpx;
color: #999999;
margin: 10rpx 0;
}
.evaluateWtapper .evaluateItem .evaluate-infor {
font-size: 28rpx;
color: #333;
margin-bottom: 14rpx;
}
.evaluateWtapper .evaluateItem .imgList {/*
padding: 0 24rpx;
margin-top: 16rpx; */
}
.evaluateWtapper .evaluateItem .imgList .pictrue {
width: 102rpx;
height: 102rpx;
margin-right: 14rpx;
border-radius: 14rpx;
margin-bottom: 16rpx;
/* margin: 0 0 15rpx 15rpx; */
}
.evaluateWtapper .evaluateItem .imgList .pictrue image {
width: 100%;
height: 100%;
background-color: #f7f7f7;
border-radius: 14rpx;
}
.evaluateWtapper .evaluateItem .reply {
font-size: 26rpx;
color: #454545;
background-color: #f7f7f7;
border-radius: 14rpx;
margin: 20rpx 30rpx 0 0rpx;
padding: 20rpx;
position: relative;
}
.evaluateWtapper .evaluateItem .reply::before {
content: "";
width: 0;
height: 0;
border-left: 20rpx solid transparent;
border-right: 20rpx solid transparent;
border-bottom: 30rpx solid #f7f7f7;
position: absolute;
top: -14rpx;
left: 40rpx;
}
</style>
+10
View File
@@ -0,0 +1,10 @@
/*!
* vConsole v3.3.4 (https://github.com/Tencent/vConsole)
*
* Tencent is pleased to support the open source community by making vConsole available.
* Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("VConsole",[],t):"object"==typeof exports?exports.VConsole=t():e.VConsole=t()}(window,function(){return function(e){var t={};function o(n){if(t[n])return t[n].exports;var r=t[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,o),r.l=!0,r.exports}return o.m=e,o.c=t,o.d=function(e,t,n){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)o.d(n,r,function(t){return e[t]}.bind(null,r));return n},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=6)}([function(e,t,o){var n,r,i;r=[t],void 0===(i="function"==typeof(n=function(e){"use strict";function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(e){return"[object Number]"==Object.prototype.toString.call(e)}function n(e){return"[object String]"==Object.prototype.toString.call(e)}function r(e){return"[object Array]"==Object.prototype.toString.call(e)}function i(e){return"[object Boolean]"==Object.prototype.toString.call(e)}function a(e){return void 0===e}function l(e){return null===e}function c(e){return"[object Symbol]"==Object.prototype.toString.call(e)}function s(e){return!("[object Object]"!=Object.prototype.toString.call(e)&&(o(e)||n(e)||i(e)||r(e)||l(e)||d(e)||a(e)||c(e)))}function d(e){return"[object Function]"==Object.prototype.toString.call(e)}function u(e){var t=Object.prototype.toString.call(e);return"[object global]"==t||"[object Window]"==t||"[object DOMWindow]"==t}function v(e){if(!s(e)&&!r(e))return[];if(r(e)){var t=[];return e.forEach(function(e,o){t.push(o)}),t}return Object.getOwnPropertyNames(e).sort()}Object.defineProperty(e,"__esModule",{value:!0}),e.getDate=function(e){var t=e>0?new Date(e):new Date,o=t.getDate()<10?"0"+t.getDate():t.getDate(),n=t.getMonth()<9?"0"+(t.getMonth()+1):t.getMonth()+1,r=t.getFullYear(),i=t.getHours()<10?"0"+t.getHours():t.getHours(),a=t.getMinutes()<10?"0"+t.getMinutes():t.getMinutes(),l=t.getSeconds()<10?"0"+t.getSeconds():t.getSeconds(),c=t.getMilliseconds()<10?"0"+t.getMilliseconds():t.getMilliseconds();return c<100&&(c="0"+c),{time:+t,year:r,month:n,day:o,hour:i,minute:a,second:l,millisecond:c}},e.isNumber=o,e.isString=n,e.isArray=r,e.isBoolean=i,e.isUndefined=a,e.isNull=l,e.isSymbol=c,e.isObject=s,e.isFunction=d,e.isElement=function(e){return"object"===("undefined"==typeof HTMLElement?"undefined":t(HTMLElement))?e instanceof HTMLElement:e&&"object"===t(e)&&null!==e&&1===e.nodeType&&"string"==typeof e.nodeName},e.isWindow=u,e.isPlainObject=function(e){var o,n=Object.prototype.hasOwnProperty;if(!e||"object"!==t(e)||e.nodeType||u(e))return!1;try{if(e.constructor&&!n.call(e,"constructor")&&!n.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(e){return!1}for(o in e);return void 0===o||n.call(e,o)},e.htmlEncode=function(e){return document.createElement("a").appendChild(document.createTextNode(e)).parentNode.innerHTML},e.JSONStringify=function(e){if(!s(e)&&!r(e))return JSON.stringify(e);var t="{",o="}";r(e)&&(t="[",o="]");for(var n=t,i=v(e),a=0;a<i.length;a++){var l=i[a],u=e[l];try{r(e)||(s(l)||r(l)||c(l)?n+=Object.prototype.toString.call(l):n+=l,n+=": "),r(u)?n+="Array["+u.length+"]":s(u)||c(u)||d(u)?n+=Object.prototype.toString.call(u):n+=JSON.stringify(u),a<i.length-1&&(n+=", ")}catch(e){continue}}return n+=o},e.getObjAllKeys=v,e.getObjName=function(e){return Object.prototype.toString.call(e).replace("[object ","").replace("]","")},e.setStorage=function(e,t){window.localStorage&&(e="vConsole_"+e,localStorage.setItem(e,t))},e.getStorage=function(e){if(window.localStorage)return e="vConsole_"+e,localStorage.getItem(e)}})?n.apply(t,r):n)||(e.exports=i)},function(e,t,o){var n,r,i;r=[t,o(0),o(10)],void 0===(i="function"==typeof(n=function(o,n,r){"use strict";var i;Object.defineProperty(o,"__esModule",{value:!0}),o.default=void 0,r=(i=r)&&i.__esModule?i:{default:i};var a={one:function(e,t){try{return(t||document).querySelector(e)||void 0}catch(e){return}},all:function(e,t){try{var o=(t||document).querySelectorAll(e);return Array.from(o)}catch(e){return[]}},addClass:function(e,t){if(e){(0,n.isArray)(e)||(e=[e]);for(var o=0;o<e.length;o++){var r=(e[o].className||"").split(" ");r.indexOf(t)>-1||(r.push(t),e[o].className=r.join(" "))}}},removeClaLine truncated
+29
View File
@@ -0,0 +1,29 @@
let domain = 'http://apif.java.crmeb.net'
// let domain = 'http://127.0.0.1:48080'
module.exports = {
// 请求域名 格式: https://您的域名
// #ifdef MP
HTTP_REQUEST_URL: domain,
// #endif
// #ifdef H5
//H5接口是浏览器地址
// HTTP_REQUEST_URL: window.location.protocol+"//"+window.location.host,
// http://api.java.crmeb.net:20001
HTTP_REQUEST_URL: domain,
// #endif
HEADER:{
'content-type': 'application/json'
},
HEADERPARAMS:{
'content-type': 'application/x-www-form-urlencoded'
},
// 回话密钥名称 请勿修改此配置
TOKENNAME: 'Authori-zation',
// 缓存时间 0 永久
EXPIRE:0,
//分页最多显示条数
LIMIT: 10
};
+34
View File
@@ -0,0 +1,34 @@
module.exports = {
//token
LOGIN_STATUS: 'LOGIN_STATUS_TOKEN',
// uid
UID:'UID',
// openid
OPENID: 'OPENID',
//用户信息
USER_INFO: 'USER_INFO',
//token 过期时间
EXPIRES_TIME: 'EXPIRES_TIME',
//微信授权
WX_AUTH: 'WX_AUTH',
//微信授权状态
STATE_KEY: 'wx_authorize_state',
//登录回调地址
BACK_URL: 'login_back_url',
// 小程序授权状态
STATE_R_KEY: 'roution_authorize_state',
//logo Url
LOGO_URL: 'LOGO_URL',
//模板缓存
// SUBSCRIBE_MESSAGE: 'SUBSCRIBE_MESSAGE',
TIPS_KEY: 'TIPS_KEY',
SPREAD: 'spread',
//缓存经度
CACHE_LONGITUDE: 'LONGITUDE',
//缓存纬度
CACHE_LATITUDE: 'LATITUDE',
//app手机信息
PLATFORM: 'systemPlatform'
}
+8
View File
@@ -0,0 +1,8 @@
module.exports = {
// Socket链接 暂不做配置
WSS_SERVER_URL:'',
// Socket调试模式
SERVER_DEBUG:true,
// 心跳间隔
PINGINTERVAL:3000
}
-17
View File
@@ -1,17 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
/>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>
File diff suppressed because it is too large. Load diff
-9
View File
@@ -1,9 +0,0 @@
{
"compilerOptions": {
"jsx": "preserve",
"baseUrl": ".",
"paths": {
"@/*": ["./*"]
}
}
}
+22
View File
@@ -0,0 +1,22 @@
import { appAuth } from '../api/public';
class Apps{
/**
* 授权登录获取token
* @param {Object} code
*/
authApp(code) {
return new Promise((resolve, reject) => {
appAuth(code,{'spread_spid': 0})
.then(({
data
}) => {
resolve(data);
Cache.set(WX_AUTH, code);
Cache.clear(STATE_KEY);
})
.catch(reject);
});
}
}
export default new Apps();
+62
View File
@@ -0,0 +1,62 @@
import $store from "@/store";
import { VUE_APP_WS_URL } from "@/utils/index.js";
const Socket = function() {
this.ws = new WebSocket(wss(VUE_APP_WS_URL));
this.ws.onopen = this.onOpen.bind(this);
this.ws.onerror = this.onError.bind(this);
this.ws.onmessage = this.onMessage.bind(this);
this.ws.onclose = this.onClose.bind(this);
};
function wss(wsSocketUrl) {
let ishttps = document.location.protocol == 'https:';
if (ishttps) {
return wsSocketUrl.replace('ws:', 'wss:');
} else {
return wsSocketUrl.replace('wss:', 'ws:');
}
}
Socket.prototype = {
vm(vm) {
this.vm = vm;
},
close() {
clearInterval(this.timer);
this.ws.close();
},
onOpen: function() {
console.log("ws open");
this.init();
this.send({
type: "login",
data: $store.state.app.token
});
this.vm.$emit("socket_open");
},
init: function() {
var that = this;
this.timer = setInterval(function() {
that.send({ type: "ping" });
}, 10000);
},
send: function(data) {
return this.ws.send(JSON.stringify(data));
},
onMessage: function(res) {
const { type, data = {} } = JSON.parse(res.data);
this.vm.$emit(type, data);
},
onClose: function() {
clearInterval(this.timer);
},
onError: function(e) {
console.log(e);
this.vm.$emit("socket_error", e);
}
};
Socket.prototype.constructor = Socket;
export default Socket;
+84
View File
@@ -0,0 +1,84 @@
import store from "../store";
import Cache from '../utils/cache';
import { Debounce } from '@/utils/validate.js'
// #ifdef H5
import { isWeixin } from "../utils";
import auth from './wechat';
// #endif
import { LOGIN_STATUS, USER_INFO, EXPIRES_TIME, STATE_R_KEY, BACK_URL} from './../config/cache';
function prePage(){
let pages = getCurrentPages();
let prePage = pages[pages.length - 1];
return prePage.route;
}
export const toLogin = Debounce(_toLogin,800)
export function _toLogin(push, pathLogin) {
store.commit("LOGOUT");
let path = prePage();
let login_back_url = Cache.get(BACK_URL);
// #ifdef H5
// path = location.href;
path = location.pathname + location.search;
// #endif
if(!pathLogin){
pathLogin = '/page/users/login/index'
Cache.set('login_back_url',path);
}
// #ifdef H5
if (isWeixin()) {
let urlData = location.pathname + location.search
if (!Cache.has('snsapiKey')) {
auth.oAuth('snsapi_base', urlData);
} else {
if (['/pages/user/index'].indexOf(login_back_url) === -1) {
uni.navigateTo({
url: '/pages/users/wechat_login/index'
})
}
}
} else {
if (['/pages/user/index'].indexOf(login_back_url) === -1) {
uni.navigateTo({
url: '/pages/users/login/index'
})
}
}
// #endif
if (['pages/user/index','/pages/user/index'].indexOf(login_back_url) === -1) {
// #ifdef MP
uni.navigateTo({
url: '/pages/users/wechat_login/index'
})
// #endif
}
}
export function checkLogin()
{
let token = Cache.get(LOGIN_STATUS);
let expiresTime = Cache.get(EXPIRES_TIME);
let newTime = Math.round(new Date() / 1000);
if (expiresTime < newTime || !token){
Cache.clear(LOGIN_STATUS);
Cache.clear(EXPIRES_TIME);
Cache.clear(USER_INFO);
Cache.clear(STATE_R_KEY);
return false;
}else{
store.commit('UPDATE_LOGIN',token);
let userInfo = Cache.get(USER_INFO,true);
if(userInfo){
store.commit('UPDATE_USERINFO',userInfo);
}
return true;
}
}
+49
View File
@@ -0,0 +1,49 @@
import {
preOrderApi
} from '@/api/order.js';
import util from 'utils/util'
// TODO 芋艿:需要调整位置
/**
* 去商品详情
*/
export function goShopDetail(item, uid) {
return new Promise(resolve => {
const activityH5 = item.activityList && item.activityList[0] ? item.activityList[0] : null;
if (activityH5 && activityH5.type === 1) {
uni.navigateTo({
url: `/pages/activity/goods_seckill_details/index?id=${activityH5.id}`
})
} else if (activityH5 && activityH5.type === 2) {
uni.navigateTo({
url: `/pages/activity/goods_bargain_details/index?id=${activityH5.id}&startBargainUid=${uid}`
})
} else if (activityH5 && activityH5.type === 3) {
uni.navigateTo({
url: `/pages/activity/goods_combination_details/index?id=${activityH5.id}`
})
} else {
resolve(item);
}
});
}
/**
* 活动商品、普通商品、购物车、再次购买预下单
*/
export function getPreOrder(preOrderType, orderDetails) {
return new Promise((resolve, reject) => {
preOrderApi({
"preOrderType": preOrderType,
"orderDetails": orderDetails
}).then(res => {
uni.navigateTo({
url: '/pages/users/order_confirm/index?preOrderNo=' + res.data.preOrderNo
});
}).catch(err => {
return util.Tips({
title: err
});
})
});
}
Loaded 100 of 958 files, more files were not shown because too many files have changed in this diff. Show more