Compare commits

...

270 Commits

Author SHA1 Message Date
GaoHao 14486e14d1 配置更新 2025-02-06 11:11:23 +08:00
GaoHao 3b1c7ea31f 下载页面优化 2025-02-06 09:34:02 +08:00
GaoHao be21975449 Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-02-05 14:01:21 +08:00
GaoHao 19f6cadae7 红包明细加载优化 2025-02-05 14:01:02 +08:00
YeMingfei666 9dbf88174e h5首页增加关闭h5访问通知 2025-02-05 13:32:07 +08:00
YeMingfei666 93f4aca944 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-23 14:58:03 +08:00
GaoHao 9a33f5ebb1 Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-22 18:27:18 +08:00
GaoHao 65a6cb04e9 任务页面优化 2025-01-22 18:27:04 +08:00
YeMingfei666 d522437135 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-22 14:23:31 +08:00
GaoHao ab588d4123 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-22 14:21:06 +08:00
GaoHao a1c95f7f1b 公告H5优化 2025-01-22 14:21:02 +08:00
duan 0c5e5798ea 修改首页列表布局,和h5红包显示 2025-01-22 13:56:05 +08:00
YeMingfei666 6f1149fae2 增加打包后去除console.log打印 2025-01-22 13:53:54 +08:00
GaoHao b4a7890f8a Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-22 13:44:58 +08:00
GaoHao 08b63c3a88 H5生成接口地址修改 2025-01-22 13:44:37 +08:00
YeMingfei666 8f0729606e Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-22 11:41:19 +08:00
YeMingfei666 91e8d66941 修复视频播放控制条兼容问题,修改部分代码逻辑,去除部分打印代码 2025-01-22 11:41:09 +08:00
YeMingfei666 1550bcd19c 剔除无用代码 2025-01-22 11:39:59 +08:00
GaoHao f8bd53596b 提现优化更新 2025-01-22 10:38:43 +08:00
YeMingfei666 fa809e7b0b Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-21 17:25:42 +08:00
YeMingfei666 896287e5cf 暂时使用原生进度条。自定义进度条调试中 2025-01-21 17:25:32 +08:00
GaoHao ef55dc901e 个人中心优化 2025-01-21 17:22:26 +08:00
YeMingfei666 1be09bf67a 修复视频不显示支付次数问题 2025-01-21 15:20:05 +08:00
GaoHao d1153659cb 名字更新 2025-01-21 14:44:46 +08:00
duan fffcdf483b 修改olode为onshow 2025-01-20 16:16:36 +08:00
duan f0e2797e8e 添加领取接口 2025-01-20 15:15:52 +08:00
GaoHao 46ac9db29d 广告回调修改 2025-01-20 15:09:04 +08:00
GaoHao 3fbca65f86 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-20 14:56:43 +08:00
GaoHao 3b472eac65 任务看广告优化 2025-01-20 14:55:07 +08:00
duan d7a8578b0a 领取接口 2025-01-20 14:52:51 +08:00
duan 2ba92103f9 弹窗判断 2025-01-20 14:32:54 +08:00
GaoHao a60986d0ca Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-20 14:13:51 +08:00
GaoHao 88cdceb780 实名认证页面优化 2025-01-20 14:13:35 +08:00
duan 6422392967 签到领取 2025-01-20 13:40:53 +08:00
duan fe79e54917 修改onShow 2025-01-20 11:46:15 +08:00
GaoHao ec8e849bf5 Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-20 11:44:30 +08:00
GaoHao d7626a24b8 处理版本更新tabbar隐藏问题 2025-01-20 11:44:14 +08:00
duan 6cc92c111f 修改状态 2025-01-20 11:43:26 +08:00
GaoHao 2d5c5d2ba9 Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-20 11:15:55 +08:00
GaoHao f67ff84af3 版本更新优化 2025-01-20 11:15:28 +08:00
GaoHao c72c0e9baf 版本更新优化 2025-01-20 11:13:45 +08:00
duan 0a25834082 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-20 10:55:58 +08:00
duan ec35f4bfb1 修改报错 2025-01-20 10:55:55 +08:00
GYJ 949403dd0d test 2025-01-20 10:50:06 +08:00
duan c05ee20821 优化审核代码 2025-01-20 10:48:44 +08:00
duan b5d902a99d 版本判断 2025-01-20 10:47:42 +08:00
duan ccf9625f41 版本 2025-01-20 10:47:01 +08:00
duan bb197f1236 版本号提交 2025-01-20 10:45:21 +08:00
duan 8674f1974d 判断版本号 2025-01-20 10:44:47 +08:00
duan 1674a62fec 提交判断版本号 2025-01-20 10:42:53 +08:00
duan 18549d562f 代码找回 2025-01-20 10:07:52 +08:00
duan 45316112b4 合并代码 2025-01-20 09:51:11 +08:00
duan a0d3c31ea5 ios判断设置 2025-01-20 09:30:58 +08:00
YeMingfei666 f29542844a 解决store/common报错问题 2025-01-18 10:02:03 +08:00
duan 54f26055cc 解決衝突 2025-01-18 09:57:55 +08:00
duan a62e47fe25 解決衝突 2025-01-18 09:55:10 +08:00
YeMingfei666 940740ce6d Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-18 09:53:07 +08:00
duan 940cf8c2e7 修改ios審核時候的視頻播放 2025-01-18 09:51:56 +08:00
GaoHao 8622676ebf 任务看完广告提示优化 2025-01-18 09:45:59 +08:00
YeMingfei666 3b776a3beb 修复ios选集换行问题 2025-01-17 18:28:29 +08:00
YeMingfei666 9651c9cb6f 修复h5默认值错误问题 2025-01-17 18:19:29 +08:00
GaoHao a299b8e846 任务观看广告优化 2025-01-17 18:19:11 +08:00
GaoHao 2058c4af58 规则弹窗优化 2025-01-17 18:04:39 +08:00
YeMingfei666 35909ae42c Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-17 17:56:57 +08:00
YeMingfei666 6c4a6ea804 修复ios视频兼容性问题,改为同h5播放形式 2025-01-17 17:36:09 +08:00
YeMingfei666 48154cf82f 修复选集弹窗ios偶发性不出现问题 2025-01-17 16:19:23 +08:00
GaoHao 575caba06d Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-17 14:28:43 +08:00
GaoHao 64d7d9a317 个人中心登录状态优化 2025-01-17 14:28:19 +08:00
duan 503f1d4594 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-17 10:17:26 +08:00
duan ae33f415b0 兑换 2025-01-17 10:17:22 +08:00
YeMingfei666 169b3ca31e Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-17 10:08:16 +08:00
YeMingfei666 8553c5f2b7 处理ios兼容性问题 2025-01-17 10:08:06 +08:00
GaoHao cd1bfa9ec1 Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-17 10:00:37 +08:00
GaoHao e8cb4f83ed 登录相关界面优化 2025-01-17 10:00:19 +08:00
gyq 699061f506 Merge branch 'test' of e.coding.net:g-cphe0354/duanju/new_app into gyq 2025-01-16 15:18:15 +08:00
gyq be4bf820b4 优化个人中心刷新数据 2025-01-16 15:18:10 +08:00
GaoHao 899680b0c5 提现优化 2025-01-16 15:14:18 +08:00
GaoHao 51f8f54a26 请求返回修改 2025-01-16 13:55:54 +08:00
GaoHao 1704cd2e7c 提现看广告优化 2025-01-16 13:33:28 +08:00
duan f92a3bbdf6 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-16 11:42:00 +08:00
duan 55449dd522 修改样式 2025-01-16 11:41:58 +08:00
GaoHao 432c9b3123 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-16 11:24:27 +08:00
GaoHao c1f3c9a937 提现页面优化 2025-01-16 11:24:24 +08:00
duan 886aa998cc 任务每月1每月2 2025-01-16 11:21:14 +08:00
duan 08e4f8ae6e 任务merit领取 2025-01-16 10:33:19 +08:00
duan 5de46a4020 合并代码 2025-01-16 09:51:44 +08:00
duan 0cee26f44a ios审核判断,抽奖没次数提示 2025-01-16 09:50:25 +08:00
gyq ff72d7b087 Merge branch 'test' of e.coding.net:g-cphe0354/duanju/new_app into gyq 2025-01-16 09:38:39 +08:00
gyq 679bc382dd 更新金币明细类型 2025-01-16 09:38:33 +08:00
GaoHao 76db18804b 广告apd修改,注册优化 2025-01-16 09:32:49 +08:00
GaoHao a0f899c3cd 广告加载失败触发提醒 2025-01-15 17:50:53 +08:00
duan d255512ade Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-15 17:24:32 +08:00
duan 9871bd625a 显示安卓任务观看视频列表 2025-01-15 17:24:13 +08:00
GaoHao ff791757a3 Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-15 16:36:53 +08:00
GaoHao 9bced08083 广告apdid更新 2025-01-15 16:34:23 +08:00
YeMingfei666 96631da8fc Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-15 15:42:55 +08:00
YeMingfei666 7eec5a36f6 优化h5推荐页面视频播放展示形式 2025-01-15 15:42:46 +08:00
YeMingfei666 c276c9431b 支付增加轮询,store/common判断是否展示红包代码修改 2025-01-15 15:24:06 +08:00
duan e5842b6429 兑换记录 2025-01-15 14:49:27 +08:00
YeMingfei666 c2bbfc2342 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-15 14:15:25 +08:00
YeMingfei666 bc8d132192 增加公共数据 2025-01-15 14:15:15 +08:00
wwz 1b0279655d Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into wwz 2025-01-15 13:44:11 +08:00
wwz a049ee6667 客服 2025-01-15 13:44:01 +08:00
GaoHao a3cc95b816 Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-15 13:32:28 +08:00
GaoHao 6a6df97cc0 实名认证优化 2025-01-15 13:32:07 +08:00
duan 24d076575b 奖品记录 2025-01-15 11:32:52 +08:00
YeMingfei666 da473035d8 视频播放优化 2025-01-15 11:14:48 +08:00
YeMingfei666 a0cde5643e 视频播放优化 2025-01-15 11:02:54 +08:00
YeMingfei666 d9ffddb436 增加视频播放结束后的处理,修复视频播放结束调用播放结束接口报错问题,视频播放增加稳定版和预发布版本 2025-01-15 10:57:46 +08:00
duan 9e30dbbc83 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into dwb 2025-01-15 10:16:04 +08:00
duan bbef4754c9 抽奖 2025-01-15 10:15:55 +08:00
GaoHao d883976066 Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-15 09:24:26 +08:00
GaoHao b9100b58bb 首页公告优化 2025-01-15 09:23:53 +08:00
YeMingfei666 946f514ff1 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-14 18:25:28 +08:00
YeMingfei666 b8082b3352 优化播放开始请求接口增加防抖 2025-01-14 18:25:09 +08:00
duan f5df6b17dd 修改报错 2025-01-14 18:10:40 +08:00
duan 6b38f122e0 提交报错 2025-01-14 18:08:25 +08:00
duan 383ffe5c31 ios判断,红包修改 2025-01-14 18:06:23 +08:00
GaoHao 8860b724ee Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-14 17:35:51 +08:00
GaoHao b674358871 提现返回优化 2025-01-14 17:35:34 +08:00
YeMingfei666 092b040b5f Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-14 17:20:29 +08:00
YeMingfei666 9d62cfb410 优化-增加选集弹窗将当前滚动到弹窗中间位置 2025-01-14 17:20:16 +08:00
GaoHao 2eed3ff844 任务优化 2025-01-14 14:14:46 +08:00
YeMingfei666 1167ff6513 修复转盘跳转问题,金币支付不出现支付宝确认弹窗 2025-01-14 14:09:44 +08:00
YeMingfei666 8a5658681c 首页修改强制更新时禁止tabbar切换 2025-01-14 11:47:12 +08:00
YeMingfei666 62e75846a6 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-14 11:43:53 +08:00
duan 6e153586c9 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-14 11:41:45 +08:00
duan b9c8f40061 Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-14 11:41:40 +08:00
GaoHao 485b306ef2 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-14 11:41:20 +08:00
duan 976a192437 是否是ios环境 2025-01-14 11:41:13 +08:00
YeMingfei666 c39a4d9840 修复支付后跳转抽奖token被清除问题 2025-01-14 11:41:11 +08:00
GaoHao 4f11dc4e06 注册、登录优化 2025-01-14 11:36:03 +08:00
GaoHao 041b04bc82 任务广告更新 2025-01-14 11:28:54 +08:00
GaoHao 33e99d91a5 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao 2025-01-14 11:23:11 +08:00
duan ac16bec455 删除vconsole 2025-01-14 11:22:45 +08:00
GaoHao 3cd8b44cc6 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao 2025-01-14 11:21:18 +08:00
GaoHao b0c828aba9 登录、注册接口修改 2025-01-14 11:20:56 +08:00
duan 05201cf26b 解决冲突 2025-01-14 11:15:13 +08:00
duan 6fb22d8f10 修改ios权限问题 2025-01-14 11:12:52 +08:00
YeMingfei666 8622f3c4de 修复视频播放返回按钮显示隐藏问题 2025-01-14 10:54:20 +08:00
YeMingfei666 acf20d8f71 增加视频播放开始和结束请求 2025-01-14 10:50:13 +08:00
GaoHao 8b6d39c620 依赖更新 2025-01-14 10:30:52 +08:00
GaoHao 2f41b94465 Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-14 10:27:47 +08:00
YeMingfei666 aeb81fd2e5 修复点赞接传参问题 2025-01-14 10:27:35 +08:00
GaoHao d6be7802c8 注册/修改手机号优化 2025-01-14 10:27:23 +08:00
YeMingfei666 c80b7ca975 Merge branch 'ymf' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-14 10:14:17 +08:00
YeMingfei666 66236012c9 修复我的喜欢跳转视频详情进去走的历史记录问题,公共配置全部放到store/common.js下 2025-01-14 10:13:05 +08:00
duan 1281fd5513 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-14 09:49:46 +08:00
duan a1e15f3c00 首页搜索,暂无数据时显示的页面 2025-01-14 09:49:43 +08:00
YeMingfei666 781783a665 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-14 09:46:59 +08:00
YeMingfei666 2969521d89 修复偶发性短剧详情视频页面未跳转到播放历史位置 2025-01-14 09:45:25 +08:00
gyq 52487cc3c1 优化用户中心下拉刷新更新数据 2025-01-14 09:36:56 +08:00
YeMingfei666 34e1b9ed1f 去除获取金币比例接口改为从公共数据common里获取 2025-01-14 09:24:51 +08:00
YeMingfei666 85708668b3 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-13 18:19:06 +08:00
YeMingfei666 3919dc507c 增加公共状态管理 2025-01-13 18:18:45 +08:00
GaoHao e38575f236 更新升级优化 2025-01-13 18:08:32 +08:00
GaoHao f48cb6579c 更新升级优化 2025-01-13 18:07:24 +08:00
GaoHao b693f772bb Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao 2025-01-13 18:04:25 +08:00
GaoHao 421592420c 首页/提现公告弹窗优化更新 2025-01-13 17:58:19 +08:00
YeMingfei666 f410719b46 增加支付跳转盘抽奖 2025-01-13 17:37:51 +08:00
GaoHao 35b88a5d29 版本升级优化 2025-01-13 17:03:19 +08:00
YeMingfei666 8029d157b6 增加转盘抽奖跳转 2025-01-13 16:56:37 +08:00
YeMingfei666 6a5a96558c 视频支付更新 2025-01-13 16:19:41 +08:00
gyq 4775d0d24d Merge branch 'test' of e.coding.net:g-cphe0354/duanju/new_app into gyq 2025-01-13 15:52:11 +08:00
gyq 89b2b6cb36 优化 2025-01-13 15:52:05 +08:00
YeMingfei666 3433ebb6aa 视频列表支付更新 2025-01-13 15:50:56 +08:00
YeMingfei666 2ef47931e5 代码合并 2025-01-13 15:32:04 +08:00
YeMingfei666 adf4fcfcfc 修复h5一进来是未解锁剧集时选集等信息不出现问题 2025-01-13 14:33:04 +08:00
GaoHao caa216fef0 接口错误提示优化 2025-01-13 14:18:43 +08:00
YeMingfei666 8728844446 增加支付 2025-01-13 13:57:50 +08:00
duan 97509d86d4 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-13 11:28:19 +08:00
duan ffac79fcdf 修改任务带签到字体 2025-01-13 11:28:15 +08:00
GaoHao b15ecf1349 分享、注册优化更新 2025-01-13 11:28:01 +08:00
GaoHao 4638a4a30d 下载优化 2025-01-13 11:14:17 +08:00
GaoHao 0dd632eaff 版本更新增加 2025-01-13 10:59:11 +08:00
YeMingfei666 36028936c7 视频列表组件代码更新 2025-01-13 10:52:47 +08:00
GaoHao 6e6299c341 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao 2025-01-13 09:34:04 +08:00
GaoHao 91b4d645ff 规则按钮优化 2025-01-13 09:28:26 +08:00
YeMingfei666 d28a1e2d09 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-10 18:25:27 +08:00
YeMingfei666 4a141878f2 视频播放列表更新,增加分享海报生成 2025-01-10 18:25:01 +08:00
YeMingfei666 df3bc23cfc 增加错误处理 2025-01-09 17:57:26 +08:00
duan c8589be5b4 搜素页面,提交代码 2025-01-09 17:53:29 +08:00
duan ac95858331 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into dwb 2025-01-09 17:50:15 +08:00
duan 0892fc7be9 首页跳转详情 2025-01-09 17:50:02 +08:00
YeMingfei666 9ac12b7627 请求500处理 2025-01-09 17:47:29 +08:00
gyq a667473da1 新增剧集跳转 2025-01-09 17:43:03 +08:00
gyq 993113b324 Merge branch 'test' of e.coding.net:g-cphe0354/duanju/new_app into gyq 2025-01-09 17:37:20 +08:00
gyq 6e37df577a 新增追剧跳转 2025-01-09 17:37:14 +08:00
YeMingfei666 c220e38a9c 代码合并 2025-01-09 17:30:12 +08:00
YeMingfei666 f6d386e793 增加推荐页面 2025-01-09 17:28:50 +08:00
GaoHao 381d801611 提现广告优化 2025-01-09 15:27:39 +08:00
GaoHao c686a02931 页面展示优化 2025-01-09 11:38:37 +08:00
GaoHao 31b37eb1db Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-09 09:51:32 +08:00
GaoHao 513c8f782d 认证相关更新 2025-01-09 09:51:08 +08:00
YeMingfei666 8572bebabb 增加视频播放页面 2025-01-09 09:28:23 +08:00
gyq b81a4ab5cd 优化手机显示效果 2025-01-09 09:24:48 +08:00
GaoHao 81d57343a2 Merge branch 'gaohao' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-08 19:56:58 +08:00
GaoHao 84c66e6529 实名相关更新 2025-01-08 19:56:39 +08:00
gyq f542287d32 新增动态获取version 2025-01-08 18:20:45 +08:00
GaoHao 7cbadc5638 下拉刷新更新 2025-01-08 16:18:20 +08:00
gyq e04685a9ff 隐藏关于我们 2025-01-08 15:35:08 +08:00
GaoHao c8dbc0f550 消息中心路径配置 2025-01-08 15:31:47 +08:00
GaoHao ca84e7d51e 个人中心页面路径配置 2025-01-08 15:30:20 +08:00
GaoHao b7248db2af Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao 2025-01-08 14:55:48 +08:00
GaoHao 074d8d3fbd Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao 2025-01-08 11:25:48 +08:00
GaoHao 3291a7573a 红包/app下载/分享新增优化 2025-01-08 11:25:33 +08:00
gyq baba7211a4 Merge branch 'test' of e.coding.net:g-cphe0354/duanju/new_app into gyq 2025-01-08 11:01:47 +08:00
gyq cef6f2be85 新增意见反馈、帮助中心 2025-01-08 11:01:34 +08:00
YeMingfei666 b6eb3b0d35 增加海报生成组件 2025-01-07 17:33:08 +08:00
YeMingfei666 66d0881429 导出分享链接前缀方法 2025-01-07 17:29:06 +08:00
YeMingfei666 79813d84d1 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-07 17:27:30 +08:00
YeMingfei666 f483a8ab99 修复401未跳转登录问题 2025-01-07 17:27:14 +08:00
YeMingfei666 b244bf94d7 增加短剧视频详情页面 2025-01-07 17:26:23 +08:00
YeMingfei666 7c978d7e85 增加视频列表组件-h5 2025-01-07 17:25:39 +08:00
YeMingfei666 2bacc63e85 增加短剧视频列表请求接口 2025-01-07 17:25:10 +08:00
YeMingfei666 552a43b4e5 增加部分图标 2025-01-07 17:24:32 +08:00
duan 62c768be02 更新代码 2025-01-07 17:10:57 +08:00
GaoHao 8692626dd1 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao 2025-01-07 15:28:53 +08:00
GaoHao 419f308802 提现优化更新 2025-01-07 15:28:42 +08:00
duan e41396774b Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into dwb 2025-01-07 11:04:20 +08:00
duan b881ff4e63 首页搜索 2025-01-07 11:04:11 +08:00
YeMingfei666 ae5b72a9e9 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-07 11:03:02 +08:00
YeMingfei666 b26713a0ac 视频详情页面代码更新 2025-01-07 11:02:52 +08:00
gyq 7b0fc90f8c Merge branch 'test' of e.coding.net:g-cphe0354/duanju/new_app into gyq 2025-01-07 11:02:46 +08:00
gyq 3d387be4eb 新增对接追剧数据 2025-01-07 11:02:41 +08:00
GaoHao f82c31084d 增加协议 2025-01-07 11:01:32 +08:00
GaoHao c47fe17bcf Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao 2025-01-07 10:54:59 +08:00
GaoHao ecb94ba348 优化 2025-01-07 10:54:46 +08:00
YeMingfei666 75088f78c8 增加视频详情页面,处理登录注册接口数据不一致兼容问题 2025-01-07 10:53:49 +08:00
GaoHao 6290e963e4 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao 2025-01-07 10:43:35 +08:00
GaoHao 0041cc0e15 优化 2025-01-07 10:42:53 +08:00
duan 07d3a3684e Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into dwb 2025-01-07 10:42:43 +08:00
gyq 425673707f Merge branch 'test' of e.coding.net:g-cphe0354/duanju/new_app into gyq 2025-01-07 10:41:21 +08:00
gyq c6df33859c 优化 2025-01-07 10:41:13 +08:00
YeMingfei666 11b83c267f Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-07 10:40:42 +08:00
YeMingfei666 81a7a71d24 请求封装处理 2025-01-07 10:40:32 +08:00
duan 57ff5d726e update .gitignore 2025-01-07 10:20:47 +08:00
GaoHao f7037c0643 update .gitignore 2025-01-07 10:19:21 +08:00
gyq 3d5da70277 update .gitignore 2025-01-07 10:17:18 +08:00
gyq 3b45fd92fc update .gitignore 2025-01-07 10:13:45 +08:00
YeMingfei666 24036aad58 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-07 10:09:18 +08:00
YeMingfei666 9a1c657b42 修复gitignore失效问题 2025-01-07 10:09:08 +08:00
YeMingfei666 cf2f291d13 更新gitignore 2025-01-07 10:04:43 +08:00
GaoHao a194af29cb Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao 2025-01-07 09:55:31 +08:00
GaoHao 5b19340974 代码优化 2025-01-07 09:54:54 +08:00
gyq eac369650a Merge branch 'test' of e.coding.net:g-cphe0354/duanju/new_app into gyq 2025-01-07 09:53:51 +08:00
gyq b3f2901e3b 新增全局颜色变量 2025-01-07 09:53:45 +08:00
YeMingfei666 d41df28edd Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into ymf 2025-01-07 09:06:33 +08:00
YeMingfei666 c78c4875c8 配置文件更新 2025-01-07 09:04:21 +08:00
YeMingfei666 4326e4ff70 配置文件更新 2025-01-07 09:03:58 +08:00
YeMingfei666 ff36d048b2 暂时去除加密解密方法,运行到app会报错 2025-01-07 09:03:16 +08:00
gyq 96c378c54c Merge branch 'test' of e.coding.net:g-cphe0354/duanju/new_app into gyq 2025-01-06 18:31:25 +08:00
gyq 9c117f9219 优化http 2025-01-06 18:30:09 +08:00
duan 0cdd737ca5 更新代码 2025-01-06 18:28:10 +08:00
gyq fb23d878de 优化 2025-01-06 18:27:42 +08:00
gyq 6b3451bcc2 Merge branch 'test' of e.coding.net:g-cphe0354/duanju/new_app into gyq 2025-01-06 18:03:43 +08:00
gyq cb330b20a9 修改为动态获取token 2025-01-06 18:03:33 +08:00
duan 4ccddee396 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into test 2025-01-06 17:55:28 +08:00
duan caea0aeb6c 更新代码 2025-01-06 17:55:26 +08:00
gyq 86f55b8bfd Merge branch 'test' of e.coding.net:g-cphe0354/duanju/new_app into gyq 2025-01-06 17:52:55 +08:00
gyq 0eadb01746 请求接口 2025-01-06 17:52:45 +08:00
GaoHao 723199e66f Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao 2025-01-06 17:46:36 +08:00
GaoHao f586e5410c 登录注册、个人信息增加 2025-01-06 17:44:45 +08:00
gyq f782216775 Merge branch 'test' of e.coding.net:g-cphe0354/duanju/new_app into gyq 2025-01-06 17:24:57 +08:00
gyq 59bdf9dd43 新增追剧和我的 2025-01-06 17:24:49 +08:00
duan 4ec188968d 更新代码 2025-01-06 17:24:15 +08:00
GaoHao 7cd1fe7a89 Merge branch 'test' of https://e.coding.net/g-cphe0354/duanju/new_app into gaohao 2025-01-06 14:41:28 +08:00
duan f016c3094d 添加判断iso和安卓 2025-01-06 14:28:52 +08:00
duan f28d2b8a3d Merge branch 'master' of https://e.coding.net/g-cphe0354/duanju/new_app into dwb 2025-01-06 14:14:44 +08:00
duan 22e6d8b1e8 添加底部导航栏 2025-01-06 14:13:50 +08:00
229 changed files with 23921 additions and 3991 deletions

2
.gitignore vendored
View File

@ -1,3 +1,3 @@
/node_modules/
/unpackage/
/unpackage/dist/
/uni_modules/

13
.hbuilderx/launch.json Normal file
View File

@ -0,0 +1,13 @@
{
"version" : "1.0",
"configurations" : [
{
"playground" : "custom",
"type" : "uni-app:app-android"
},
{
"playground" : "custom",
"type" : "uni-app:app-ios"
}
]
}

106
App.vue
View File

@ -1,18 +1,114 @@
<script>
export default {
onLaunch: function() {
console.log('App Launch')
console.log('App Launch ');
uni.setStorageSync('adRewardedNum',0)
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
console.log('App Hide');
}
}
};
</script>
<style lang="scss">
/*每个页面公共css */
@import "uview-plus/index.scss";
</style>
@import "@/commons/style/common.scss";
ul,
li {
list-style: none;
}
.show {
display: block;
}
.hidden {
display: none !important;
}
page,
view,
scroll-view,
swiper,
swiper-item,
match-media,
movable-area,
movable-view,
cover-view,
cover-image,
icon,
text,
rich-text,
progress,
button,
checkbox-group,
editor,
form,
input,
label,
picker,
picker-view,
radio-group,
slider,
switch,
textarea,
navigator,
audio,
camera,
image,
video,
live-player,
live-pusher,
map,
canvas,
web-view {
box-sizing: border-box;
padding: 0;
margin: 0;
text-decoration: none;
outline: none;
}
.initStyle {
padding: 20rpx;
background-color: #2a2a2a;
height: 100vh;
color: #fff;
}
.fc {
color: #f4f693;
}
.inputClass {
line-height: 80rpx;
}
.inputClass input {
background-color: #fff;
height: 80rpx;
padding: 10rpx;
color: #000;
}
.result {
position: absolute;
font-size: 100rpx;
left: 50%;
top: 800rpx;
transform: translateX(-50%);
}
.u-image {
background-color: transparent !important;
}
.u-status-bar {
height: var(--status-bar-height);
}
</style>

85
api/index/index.js Normal file
View File

@ -0,0 +1,85 @@
import http from '@/http/http.js'
// 获取弹窗信息
export const announcement = (data) => {
return http.request({
url: '/announcement',
data
})
}
// 获取公告
export const messageselectMessage = (data) => {
return http.request({
url: '/message/selectMessage',
data: {
page: 1,
limit: 5,
state: 1
}
})
}
// 获取推荐视频
export const courseselectCourse = (data) => {
return http.request({
url: '/course/selectCourse',
data
})
}
// 兑换
export const userPrizeExchangeexchange = (data) => {
return http.request({
url: '/userPrizeExchange/exchange',
data,
method:'post'
})
}
// 搜索
export const selectCourseTitles = (data) => {
return http.request({
url: '/course/selectCourseTitles',
data
})
}
// 抽奖列表
export const selectDiscSpinning = (data) => {
return http.request({
url: '/discSpinning/selectDiscSpinning',
data
})
}
// 抽奖
export const discSpinningdraw = (data) => {
return http.request({
url: '/discSpinning/draw',
data
})
}
export const selectUserMoney = (data) => {
return http.request({
url: '/moneyDetails/selectUserMoney',
data
})
}
export const drawCount = (data) => {
return http.request({
url: '/discSpinning/drawCount',
data
})
}
// 获取记录
export const selectDiscSpinningRecord = (data) => {
return http.request({
url: '/discSpinningRecord/selectDiscSpinningRecord',
data
})
}
// 兑换记录
export const userPrizeExchange = (data) => {
return http.request({
url: '/userPrizeExchange/page',
data
})
}

28
api/init.js Normal file
View File

@ -0,0 +1,28 @@
import http from '@/http/http.js'
export async function init() {
//热搜词
http.request({
url: 'common/type/249',
}).then(res => {
if (res.code == 0) {
uni.setStorageSync('moreSearch', res.data.value)
}
})
}
/**
*
*/
export const commonType = (num) => {
return http.request({
url: `/common/type/${num}`,
})
}
export function getCommonConfig(){
return http.request({
url:'common/getAppUseKv'
})
}

56
api/login/login.js Normal file
View File

@ -0,0 +1,56 @@
import http from '@/http/http.js'
/**
* 登录
*/
export const login = (data) => {
return http.request({
url: '/Login',
method: 'POST',
data: data
})
}
/**
* 发送验证码
*/
export const setSendMsg = (mobile,type) => {
return http.request({
url: '/Login/sendMsg/' + mobile + '/'+type
})
}
/**
* 注册
*/
export const register = (data) => {
return http.request({
url: '/Login/register',
method: 'POST',
data: data
})
}
/**
* 修改密码
*/
export const forgetPwd = (data) => {
return http.request({
url: '/Login/forgetPwd',
method: 'POST',
params: data
})
}
/**
* 绑定
*/
export const bind = (data) => {
return http.request({
url: '/Login/registerCode',
method: 'POST',
data: data
})
}

75
api/me/me.js Normal file
View File

@ -0,0 +1,75 @@
import http from '@/http/http.js'
/**
* 获取最近观看
*/
export const selectByUserId = (data) => {
return http.request({
url: '/courseCollect/selectByUserId',
data: data,
method: 'GET'
})
}
/**
* 获取客服微信
*/
export const commonType = (type) => {
return http.request({
url: `/common/type/${type}`,
method: 'GET'
})
}
/**
* 金币明细
*/
export const queryUserMoneyDetails = (data) => {
return http.request({
url: '/moneyDetails/queryUserMoneyDetails',
method: 'GET',
data: data
})
}
/**
* 意见反馈
*/
export const sendMessage = (data) => {
return http.request({
url: '/message/sendMessage',
method: 'POST',
data: data
})
}
/**
* 帮助中心
*/
export const selectHelpList = (data) => {
return http.request({
url: '/helpWord/selectHelpList',
method: 'GET',
data: data
})
}
/**
* 个人中心数据
*/
export const collectVideoSummary = () => {
return http.request({
url: '/courseCollect/collectVideoSummary',
method: 'GET'
})
}
/**
* 金币
*/
export const selectUserMoney = () => {
return http.request({
url: '/moneyDetails/selectUserMoney',
method: 'GET'
})
}

11
api/me/message.js Normal file
View File

@ -0,0 +1,11 @@
import http from '@/http/http.js'
/**
* 获取消息列表
*/
export const selectMessageByUserId = (data) => {
return http.request({
url: '/message/selectMessageByUserId',
data: data,
})
}

84
api/me/withdraw.js Normal file
View File

@ -0,0 +1,84 @@
import http from '@/http/http.js'
/**
* 获取提现金额
*/
export const selectUserMoney = (data) => {
return http.request({
url: '/moneyDetails/selectUserMoney',
})
}
/**
* 获取提现记录
*/
export const selectPayDetails = (data) => {
return http.request({
url: '/cash/selectPayDetails',
data: data
})
}
/**
* 红包明细记录
*/
export const queryUserMoneyDetails = (data) => {
return http.request({
url: '/moneyDetails/queryUserMoneyDetails',
data: data
})
}
/**
* 修改提现账号
*/
export const updateUser = (data) => {
return http.request({
url: '/user/updateUser',
params: data
})
}
/**
* 实名认证
*/
export const realNameAuth = (data) => {
return http.request({
url: '/user/realNameAuth/v2',
method: 'POST',
data: data
})
}
/**
* 获取看广告状态
*/
export const canCash = (data) => {
return http.request({
url: '/cash/canCash',
showLoading: false,
})
}
/**
* 广告状态修改
*/
export const state = (data) => {
return http.request({
url: '/ad/state',
data: data,
})
}
/**
* 广告状态修改
*/
export const withdraw = (data) => {
return http.request({
url: '/cash/withdraw',
data: data,
})
}

32
api/share/index.js Normal file
View File

@ -0,0 +1,32 @@
import http from '@/http/http.js'
/**
* 获取已邀请列表
*/
export const selectInviteByUserIdLists = (data) => {
return http.request({
url: '/invite/selectInviteByUserIdLists',
data: data,
})
}
/**
* 获取邀请战绩
*/
export const selectInviteMoney = (data) => {
return http.request({
url: '/invite/selectInviteMoney',
data: data,
})
}
/**
* 获取海报数据
*/
export const selectBannerList = (data) => {
return http.request({
url: '/banner/selectBannerList',
data: data,
})
}

49
api/task/index.js Normal file
View File

@ -0,0 +1,49 @@
import http from '@/http/http.js'
// 获取任务列表
export const selectTaskCenter = (data) => {
return http.request({
url: '/taskCenter/selectTaskCenter',
data,
showLoading:false
})
}
// 兑换列表
export const selectTaskCenterUserReward = (data) => {
return http.request({
url: '/taskCenterReward/selectTaskCenterUserReward',
data,
isreturm:true
})
}
// 获取签到
export const getUserSignData = (data) => {
return http.request({
url: 'userSignRecord/getUserSignData',
data,
showLoading:false
})
}
export const receiveGoods = (data) => {
return http.request({
url: 'taskCenter/receiveGoods',
data,
method: 'POST',
})
}
// 任务-签到
export const taskReceive = (data) => {
return http.request({
url: 'taskCenter/taskReceive',
data,
isreturm:true
})
}
// 任务列表
export const selectDiscSpinning = (data) => {
return http.request({
url: 'discSpinning/selectDiscSpinning',
data,
})
}

44
api/user/user.js Normal file
View File

@ -0,0 +1,44 @@
import http from '@/http/http.js'
/**
* 获取APP版本信息
*/
export const selectNewApp = (data) => {
return http.request({
url: '/user/selectNewApp',
data: data,
})
}
/**
* 获取用户信息
*/
export const selectUserById = (data) => {
return http.request({
url: '/user/selectUserById',
data: data
})
}
/**
* 修改用户信息
*/
export const updateUsers = (data) => {
return http.request({
url: '/user/updateUsers',
method: 'POST',
data: data,
})
}
/**
* 修改手机号
*/
export const updatePhone = (data) => {
return http.request({
url: '/user/updatePhone',
method: 'POST',
params: data
})
}

150
api/video/index.js Normal file
View File

@ -0,0 +1,150 @@
import http from '@/http/http.js'
//获取短剧视频详情
export function getVideoDetail(data) {
return http.request({
url: 'course/courseSets',
data: data
})
}
//追剧
export function zhuiju(data) {
return http.request({
url: 'courseCollect/insertCourseCollect',
method: 'POST',
data: {
classify: 1,
...data
}
})
}
//点赞
export function dianzan(data) {
return http.request({
url: 'courseCollect/insertCourseCollect',
method: 'POST',
data: {
classify: 2,
...data
}
})
}
//插入播放历史记录
export function insertHistory(data) {
return http.request({
url: 'courseCollect/insertCourseCollect',
method: 'POST',
data: {
classify: 3,
type: 1,
...data
}
})
}
//获取金币比例
export function getJinbiBili(data) {
return http.request({
url: 'common/type/914',
data
})
}
//获取推荐视频
export function tuijianVideo(data) {
const randomNum = 10 + Math.ceil(Math.random() * 20)
return http.request({
url: 'course/selectCourseDetailsList',
method: 'GET',
data: {
page: 1,
limit: 10,
randomNum: randomNum
}
})
}
//解锁10集视频
export function buyTenVideo(data) {
return http.request({
url: 'order/insertCourseOrders/limit10',
method: 'GET',
data: data
})
}
//解锁单集或者全部视频
export function buyVideo(data) {
return http.request({
url: 'order/insertCourseOrders',
method: 'GET',
data: data
})
}
//订单支付
export function payOrder(data) {
let payType = 'h5'
// #ifdef APP
payType = 'app'
// #endif
return http.request({
url: 'wuyou/payOrder/' + data.orderId + '?payType=' + payType,
method: 'GET'
})
}
//获取订单支付状态
export function getOrderInfo(data) {
return http.request({
url: 'wuyou/queryOrder/' + data.orderId,
method: 'GET'
})
}
//金币解锁
export function goldPay(data) {
return http.request({
url: 'order/payOrders',
method: 'POST',
data: {
...data,
header: {
'content-type': 'application/x-www-form-urlencoded'
}
}
})
}
//获取转盘抽奖次数
export function getDrawCount(data) {
return http.request({
url: 'discSpinning/drawCount',
method: 'GET',
data
})
}
//播放开始或者结束
export function playStatus(data) {
return http.request({
url: 'course/viewCourse',
method: 'GET',
data
})
}
// 获取支付次数提示
export function getPayTips(data){
return http.request({
url: 'course/getRedEnvelopeTips',
method: 'GET',
data
})
}

3
commons/color.js Normal file
View File

@ -0,0 +1,3 @@
export default{
main:'#ff7581'
}

View File

@ -1,23 +1,23 @@
//打包时修改env的值即可
const env='test' //test , production,local
const env='production' //test , production,local
export const encryptKey='1234567890123456' // http数据加解密的key
export const apiUrl='/czg/'
export const h5Config = {
production: 'https://dj-h5.hnsiyao.cn',
production: 'https://web.hnsiyao.cn',
test: 'https://web-api.hnsiyao.cn',
local: 'http://192.168.1.41:8100'
}
export const AppConfig = {
production: 'https://dj-api.hnsiyao.cn',
test: 'https://video-h5.hnsiyao.cn',
test: 'https://web-api.hnsiyao.cn',
local: 'http://192.168.1.41:8100'
}
function returnShareUrl(){
export function returnShareUrl(){
if(env==='test'){
return 'https://video-h5.hnsiyao.cn'
}

409
commons/style/common.scss Normal file
View File

@ -0,0 +1,409 @@
.u-relative,
.u-rela {
position: relative;
}
.u-absolute,
.u-abso {
position: absolute;
}
.u-fixed,.u-fix{
position: fixed;
}
.left-top{
left: 0;
top: 0;
}
.u-overflow-hide{
overflow: hidden;
}
// nvue不能用标签命名样式不能放在微信组件中否则微信开发工具会报警告无法使用标签名当做选择器
/* #ifndef APP-NVUE */
image {
display: inline-block;
}
// 在weex也即nvue中所有元素默认为border-box
view,
text {
box-sizing: border-box;
}
/* #endif */
.u-font-xs {
font-size: 22rpx;
}
.u-font-sm {
font-size: 26rpx;
}
.u-font-md {
font-size: 28rpx;
}
.u-font-lg {
font-size: 30rpx;
}
.u-font-xl {
font-size: 34rpx;
}
.u-flex {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
}
.u-flex-wrap {
flex-wrap: wrap;
}
.u-flex-nowrap {
flex-wrap: nowrap;
}
.u-col-center {
align-items: center;
}
.u-col-top {
align-items: flex-start;
}
.u-col-bottom {
align-items: flex-end;
}
.u-row-center {
justify-content: center;
}
.u-row-left {
justify-content: flex-start;
}
.u-row-right {
justify-content: flex-end;
}
.u-row-between {
justify-content: space-between;
}
.u-row-around {
justify-content: space-around;
}
.u-text-left {
text-align: left;
}
.u-text-center {
text-align: center;
}
.u-text-right {
text-align: right;
}
.u-flex-col {
/* #ifndef APP-NVUE */
display: flex!important;
/* #endif */
flex-direction: column!important;
}
// 定义flex等分
@for $i from 0 through 12 {
.u-flex-#{$i} {
flex: $i;
}
}
// 定义字体(px)单位小于20都为px单位字体
@for $i from 9 to 20 {
.u-font-#{$i} {
font-size: $i + px;
}
}
// 定义字体(rpx)单位大于或等于20的都为rpx单位字体
@for $i from 20 through 40 {
.u-font-#{$i} {
font-size: $i + rpx;
}
}
// 定义内外边距历遍1-80
@for $i from 0 through 80 {
// 只要双数和能被5除尽的数
@if $i % 2 == 0 or $i % 5 == 0 {
// 得出u-margin-30或者u-m-30
.u-margin-#{$i}, .u-m-#{$i} {
margin: $i + rpx!important;
}
// 得出u-padding-30或者u-p-30
.u-padding-#{$i}, .u-p-#{$i} {
padding: $i + rpx!important;
}
@each $short, $long in l left, t top, r right, b bottom {
// 缩写版结果如 u-m-l-30
// 定义外边距
.u-m-#{$short}-#{$i} {
margin-#{$long}: $i + rpx!important;
}
// 定义内边距
.u-p-#{$short}-#{$i} {
padding-#{$long}: $i + rpx!important;
}
// 完整版结果如u-margin-left-30
// 定义外边距
.u-margin-#{$long}-#{$i} {
margin-#{$long}: $i + rpx!important;
}
// 定义内边距
.u-padding-#{$long}-#{$i} {
padding-#{$long}: $i + rpx!important;
}
}
}
}
// 重置nvue的默认关于flex的样式
.u-reset-nvue {
flex-direction: row;
align-items: center;
}
/* start--文本行数限制--start */
.u-line-1 {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.u-line-2 {
-webkit-line-clamp: 2;
}
.u-line-3 {
-webkit-line-clamp: 3;
}
.u-line-4 {
-webkit-line-clamp: 4;
}
.u-line-5 {
-webkit-line-clamp: 5;
}
.u-line-2, .u-line-3, .u-line-4, .u-line-5 {
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box; // 弹性伸缩盒
-webkit-box-orient: vertical; // 设置伸缩盒子元素排列方式
}
/* end--文本行数限制--end */
/* start--不同颜色文字--start */
.color-333{
color: #333;
}
.color-666{
color: #666;
}
.color-999{
color: #999;
}
.color-red{
color: $my-red-color;
}
.color-main{
color:$my-main-color
}
/* end--不同颜色文字--end */
.tranistion{
transition: all .3s ease-in-out;
}
.tranistion-1{
transition: all .1s ease-in-out;
}
.tranistion-2{
transition: all .2s ease-in-out;
}
.font-bold{
font-weight: 700;
}
/* start--不同颜色背景--start */
.my-bg-main{
background-color:$my-main-color
}
/* end--不同颜色背景--end */
.safe-page{
padding-bottom: 60rpx!important;
}
::v-deep .uni-switch-input.uni-switch-input-checked{
border-color: $my-main-color;
background-color: $my-main-color;
}
.btn-circle{
border-radius: 200px;
}
.min-page{
/* #ifdef H5 */
min-height: calc(100vh - 44px);
/* #endif */
/* #ifndef H5 */
min-height: 100vh;
/* #endif */
}
.w-full{
width: 100%;
}
.gap-20{
gap: 20rpx;
}
.color-000{
color: #000;
}
.color-fff{
color: #fff;
}
.bg-fff{
background-color: #fff;
}
.bg-gray{
background-color: #F9F9F9;
}
.overflow-hide{
/* #ifdef H5 */
height: calc(100vh - 44px);
/* #endif */
/* #ifndef H5 */
height: 100vh;
/* #endif */
overflow: hidden;
}
.no-wrap{
white-space: nowrap;
}
.border-r-12{
border-radius: 12rpx;
}
.border-r-18{
border-radius: 18rpx;
}
.border-top{
border-top: 1px solid #E5E5E5;
}
.border-bottom{
border-bottom: 1px solid #E5E5E5;
}
.scale7{
transform: scale(0.7);
}
.page-gray {
min-height: calc(100vh);
/* #ifdef H5 */
min-height: calc(100vh - var(--window-top));
/* #endif */
display: flex;
flex-direction: column;
background: #F9F9F9;
}
.box-shadow{
box-shadow: 0 0 5px #eee;
}
.safe-bottom{
padding-bottom: env(safe-area-inset-bottom);
/* #ifdef H5 */
padding-bottom: 28rpx;
/* #endif */
}
.position-all{
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.fixed-top{
position: fixed;
/* #ifdef H5 */
top: 44px;
/* #endif */
/* #ifndef H5 */
top: 0;
/* #endif */
left: 0;
right: 0;
}
.lh30 {
line-height: 30px;
}
.default-box-padding{
padding: 32rpx 24rpx;
}
.icon-arrow-down-fill {
width: 16rpx;
height: 10rpx;
}
.zIndex-999{
z-index: 999;
}
.icon-default-size{
width: 28rpx;
height: 28rpx;
}
::v-deep.uni-easyinput__placeholder-class{
font-size: 28rpx!important;
}
.filter-gray{
filter: grayscale(1);
}
// .u-font-20{
// font-size: 10px;
// }
// .u-font-24{
// font-size: 12px;
// }
// .u-font-28{
// font-size: 14px;
// }
// .u-font-32{
// font-size: 16px;
// }
.line-th{
text-decoration: line-through;
}
//覆盖u-view-plus 颜色
.u-primary-light {
color: $my-main-color;
}
::v-deep .u-border{
border-width: 1px!important;
}
::v-deep .u-m-t-16 .u-textarea{
border-width: 1px!important;
}

View File

@ -0,0 +1,26 @@
<template>
<view class="container">
<up-empty :icon="props.icon" :text="props.text"></up-empty>
</view>
</template>
<script setup>
const props = defineProps({
icon: {
type: String,
default: '/static/default/none.png'
},
text: {
type: String,
default: '空空如也~'
}
});
</script>
<style scoped lang="scss">
.container {
width: 100%;
display: flex;
justify-content: center;
}
</style>

View File

@ -0,0 +1,207 @@
<template>
<view class="qrcode">
<up-qrcode :size="qrcodeData.size" :val="qrcodeData.val" @result="qrcodeResult"></up-qrcode>
</view>
<view class="poster-box" @click="hide">
<view class="bg-fff container" @click.stop>
<canvas canvas-id="myCanvas" class="myCanvas" id="myCanvas" style="width: 100%;flex: 1;"></canvas>
</view>
</view>
<up-popup :show="posterData.result?true:false" mode="center" width="700rpx" closeOnClickOverlay @close="reset">
<image :src="posterData.result" mode="widthFix"></image>
</up-popup>
</template>
<script setup>
import {
getElRect
} from '@/utils/util.js'
import {
ref,
onMounted,
getCurrentInstance,
reactive,
computed
} from 'vue'
let show = ref(false)
function reset(){
ctx.clearRect(0,0,posterData.width,posterData.height)
show.value=false
qrcodeData.val=''
qrcodeData.result=''
posterData.result=''
}
const qrcodeData = reactive({
val: '',
result: '',
size: 80
})
let posterData = reactive({
width: 0,
height: 0,
result: ''
})
const ctx = uni.createCanvasContext('myCanvas')
function qrcodeResult(e) {
console.log(e);
qrcodeData.result = e
console.log(posterData);
const gap = 10
show.value = true
ctx.setFillStyle('#fff')
ctx.fillRect(0, 0, posterData.width, posterData.height)
uni.downloadFile({
url: posterData.bigImg,
success(res) {
if (res.statusCode == 200) {
uni.getImageInfo({
src: res.tempFilePath,
success(imageInfo) {
console.log(imageInfo);
const bili = imageInfo.width / imageInfo.height
const width = posterData.width - gap * 2
console.log(width);
console.log(width / bili);
ctx.drawImage(res.tempFilePath, gap, gap, width, width / bili, 0, 0)
ctx.drawImage(e, posterData.width - qrcodeData.size - gap, posterData.height -
gap - qrcodeData.size, qrcodeData.size, qrcodeData.size)
ctx.setFillStyle('#000')
ctx.setFontSize(14);
ctx.fillText(posterData.title, gap, posterData.height - gap - 20)
ctx.setFillStyle('#999')
ctx.setFontSize(12);
ctx.fillText(posterData.tips, gap, posterData.height - gap)
ctx.draw()
setTimeout(() => {
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: posterData.width,
height: posterData.height,
destWidth: posterData.width,
destHeight: posterData.height,
canvasId: 'myCanvas',
quality: 1,
success: function(res) {
// H5tempFilePath base64
console.log(res.tempFilePath)
posterData.result = res.tempFilePath
}
})
}, 600)
}
})
} else {
uni.showToast({
title: '封面图下载失败'
})
}
console.log(res);
}
})
show.value = true
}
const props = defineProps({
bigImg: {
type: Object,
default: () => {
return {}
}
}
})
function make(data) {
uni.showLoading({
title: '二维码生成中……'
})
Object.assign(posterData, data)
qrcodeData.val = data.qrcode
return
}
onMounted(() => {
// #ifdef H5
getElRect('myCanvas').then(res => {
Object.assign(posterData, res)
})
// #endif
})
function hide() {
show.value = false
}
let canvasConfig = reactive({
width: '',
height: ''
})
const canvasStyle = computed(() => {
return {
width: '',
height: ''
}
})
defineExpose({
make
})
</script>
<style lang="scss" scoped>
.qrcode {
position: fixed;
top: -9999px;
left: -9999px;
opacity: 0;
}
.u-popup {
position: fixed !important;
}
::v-deep .u-popup {
position: fixed !important;
}
.poster-box {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 9999;
background-color: rgba(0, 0, 0, .5);
transform: translateY(-100%);
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
transition: all .3s ease-in-out;
padding: 30rpx;
.container {
width: 100%;
flex: 1;
}
&.show {
transform: translateY(0px);
}
}
</style>

View File

@ -0,0 +1,529 @@
<template>
<view class="item" @appear="appear" @disappear="disappear" @click.stop :style="{height:height+'px'}">
<video class="u-flex-1 video" :show-fullscreen-btn="false" @controlstoggle="controlstoggles" v-if="showVideo"
@timeupdate="timeupdate" @waiting="waiting()" object-fit="cover" @pause="onpause" @click="videoClick()"
@play="videoPlay('myVideo'+item.courseDetailsId,item.courseDetailsId)" :play-strategy="2"
:show-loading="true" codec="software" :muted="false" :show-center-play-btn="true" :loop="loop"
:enable-progress-gesture="false" :poster="item.titleImg" :ref="'myVideo'+item.courseDetailsId"
:autoplay="autoplay" @ended="ended" :id="'myVideo'+item.courseDetailsId" :src="item.videoUrl"></video>
<image class="poster" v-else @click="!item.videoUrl?popupShow('pay',item):''" :src="item.titleImg"
mode="aspectFill">
</image>
<view class="info" v-if="!isCommand" :style="infoStyle">
<text class="color-fff" v-if="item.courseDetailsName">{{item.courseDetailsName}}</text>
<view v-if="item.content" v-html="item.content"></view>
<view class="u-m-t-20 color-fff" @click="popupShow('show')">
<text class="color-fff">
{{item.courseDetailsName}}{{total}}选集 >
</text>
</view>
</view>
<view class="info" v-if="isCommand" :style="infoStyle">
<text class="color-fff" v-if="item.courseDetailsName">{{item.courseDetailsName}}</text>
<view v-if="item.content" v-html="item.content"></view>
<view class="u-m-t-20 color-fff" @click="toDetail">
<text class="color-fff">
查看更多续集 >
</text>
</view>
</view>
<view class="right" :style="rightStyle">
<view class="love u-flex u-flex-xy-center u-flex-col u-m-b-40 u-text-center" @click="dianzanClick">
<up-icon name="heart-fill" v-if="item.isGood==1" color="red" size="30"></up-icon>
<up-icon name="heart-fill" v-else color="#ffffff" size="30"></up-icon>
<text class="text color-fff u-font-24">{{item.goodNum<0?0:item.goodNum}}</text>
</view>
<view class="share u-m-b-40 u-flex u-flex-xy-center u-flex-col u-text-center" @click="share">
<image class="icon" src="@/static/images/share.png" mode=""></image>
<text class="text color-fff u-font-24">分享</text>
</view>
<view class="zhuiju u-m-b-40 u-flex u-flex-xy-center u-flex-col u-text-center" @click="zhuijuClick">
<image class="icon" v-if="isCollect" src="@/static/images/shuqian_s.png" mode=""></image>
<image class="icon" v-else src="@/static/images/shuqian.png" mode=""></image>
<text class="text color-fff u-font-24">{{isCollect?'已追':'追剧'}}</text>
</view>
</view>
</view>
</template>
<script setup>
import * as Api from '@/api/video/index.js'
import {
computed,
nextTick,
onMounted,
ref,
watch
} from 'vue'
let loop = ref(false)
// #ifdef APP
loop.value = true
// #endif
const props = defineProps({
height:{
type:Number,
default:0
},
item: {
type: Object,
defaulr: () => {
return {
videoUrl: ''
}
}
},
rightStyle: {
type: Object,
default: () => {
return {
}
}
},
infoStyle: {
type: Object,
default: () => {
return {
}
}
},
isCommand: {
type: Boolean,
default: false
},
instance: {
type: Object,
defaulr: () => {
return {
proxy: {}
}
}
},
current: {
//h5
type: Number,
default: 0
},
index: {
type: Number,
default: 0
},
nowIndex: {
//app
type: Number,
default: 0
},
total: {
type: Number,
default: 0
},
isCollect: {
type: [Number, Boolean],
default: 0
},
playSpeeds: {
type: Number,
default: 1
},
showControls: {
type: Boolean,
default: true
}
})
let autoplay = ref(props.item.videoUrl ? true : false)
const emits = defineEmits(['controlstoggles', 'disappear', 'appear', 'waiting', 'videoPlay', 'ended', 'dianzanClick',
'share', 'zhuijuClick', 'popupShow', 'itemMounted', 'toDetail', 'showInfo', 'playStatusChange'
])
function controlstoggles(e) {
emits('controlstoggles', e)
}
function toDetail() {
if (video) {
video.pause()
}
emits('toDetail')
}
function waiting() {
}
let isPlying = ref(false)
watch(() => isPlying.value, (newval) => {
console.log(newval);
emits('showInfo', newval)
})
//
let isFirstPlay = true
let isPlayFinish = false //
/**
* @param {type} = [start,end]
*/
function sendPlayStatus(type = 'start') {
emits('playStatusChange', {
courseId: props.item.courseId,
courseDetailsId: props.item.courseDetailsId,
type
})
// Api.playStatus({
// courseId:props.item.courseId,
// courseDetailsId:props.item.courseDetailsId,
// type
// })
}
function timeupdate(e) {
//loding
// #ifdef H5
uni.hideLoading()
// #endif
if (isPlayFinish) {
return
}
if (e.detail.currentTime > e.detail.duration * 0.9) {
if (!isFirstPlay) {
sendPlayStatus('end')
isPlayFinish = true
}
}
}
function videoPlay() {
if (isFirstPlay && !isPlayFinish) {
sendPlayStatus('start')
}
isFirstPlay = false
isPlying.value = true
// #ifdef H5
emits('controlstoggles', {
detail: {
show: false
}
})
// #endif
}
function onpause() {
isPlying.value = false
// #ifdef H5
emits('controlstoggles', {
detail: {
show: true
}
})
// #endif
}
function ended() {
sendPlayStatus('end')
}
function dianzanClick() {
emits('dianzanClick')
}
function share() {
emits('share')
}
function zhuijuClick() {
emits('zhuijuClick')
}
function popupShow(key) {
emits('popupShow', key)
}
function videoClick() {
console.log('videoClick');
if (video) {
if (isPlying.value) {
video.pause()
} else {
video.play()
}
}
}
let first = true
function appear() {
if (video) {
video.playbackRate(props.playSpeeds)
video.play()
}
emits('appear', first)
if (first) {
first = false
}
}
let video = null
function disappear() {
if (video) {
video.pause()
}
emits('disappear')
}
const showVideo = computed(() => {
// #ifdef H5
return props.current === props.index && props.item.videoUrl
// #endif
// #ifdef APP
return props.nowIndex === props.index && props.item.videoUrl
// #endif
})
onMounted(() => {
init()
emits('itemMounted', props.index)
})
function init() {
try {
if (props.item.videoUrl && showVideo.value) {
video = uni.createVideoContext('myVideo' + props.item.courseDetailsId)
video.playbackRate(props.playSpeeds)
video.play()
console.log('init play');
}
} catch (error) {
console.error('------')
//TODO handle the exception
}
}
watch(() => props.playSpeeds, (newval) => {
console.log('speed' + newval);
if (video) {
video.playbackRate(newval)
}
})
watch(() => showVideo.value, (newval) => {
console.log('showVideo change:' + newval);
if (newval) {
isFirstPlay = true
isPlayFinish = false
nextTick(() => {
init()
})
} else {
video = null
}
})
const infoStyle = computed(() => {
return {
transform: `translateX(${(!isPlying.value||!props.item.videoUrl)?0:'-110%'})`
}
})
const rightStyle = computed(() => {
return {
transform: `translateX(${(!isPlying.value||!props.item.videoUrl)?'0':60}px)`
}
})
</script>
<style lang="scss" scoped>
.item {
// flex: 1;
// height: 100%;
position: relative;
}
.box {
/* #ifdef H5 */
flex: 1;
/* #endif */
}
.u-flex-1 {
flex: 1;
width: 100%;
height: 100%;
}
.u-popup {
position: fixed !important;
}
::v-deep .u-popup {
position: fixed !important;
}
.video {
width: 750rpx;
flex: 1;
}
.poster {
/* #ifdef H5 */
position: absolute;
width: 100%;
height: 90%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* #endif */
/* #ifdef APP */
width: 750rpx;
flex: 1;
/* #endif */
}
.u-text-center {
text-align: center;
}
.u-flex-row {
flex-direction: row !important;
}
.info {
/* #ifdef H5 */
width: 80%;
/* #endif */
height: auto;
position: absolute !important;
bottom: 50px;
left: 10px;
color: #ffffff;
font-size: 15px;
z-index: 9999;
transition: transform .3s ease-in-out;
}
.u-flex-y-center {
align-items: center !important;
}
.swipers-items {
width: 750rpx;
flex: 1;
position: relative;
background-color: #000;
}
.right {
transition: transform .3s ease-in-out;
position: absolute !important;
right: 20rpx;
/* #ifdef H5 */
top: 50%;
transform: translateY(-50%);
/* #endif */
/* #ifdef APP */
top: 500px;
/* #endif */
z-index: 999;
color: #fff;
font-size: 24rpx;
.icon {
width: 60rpx;
height: 60rpx;
}
.share {
.text {
white-space: nowrap;
}
}
.zhuiju {}
}
.poster-popup {
position: fixed !important;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
z-index: 9999;
justify-content: center;
align-items: center;
}
.ji-list {
.ji-item {
width: 210rpx;
margin-bottom: 20rpx;
margin-right: 30rpx;
height: 88rpx;
font-size: 28rpx;
color: #333;
border-radius: 12rpx;
background-color: #F5F7FF;
position: relative;
&.active {
background-color: $my-main-color;
color: #fff;
}
.lock {
position: absolute;
border-radius: 0px 6px 0px 6px;
background-color: #ccc;
padding: 2rpx 4rpx;
top: 0;
right: 0;
}
.playing {
position: absolute;
width: 32rpx;
height: 24rpx;
bottom: 5px;
right: 7px;
}
}
}
.ji-item:nth-of-type(3n) {
margin-right: 0;
}
.hot {
width: 40rpx;
height: 40rpx;
}
.pay-list {
.pay-list-item {
flex-direction: row;
justify-content: center;
background-color: #F2F2F2;
padding: 24rpx;
border-radius: 20rpx;
margin-bottom: 40rpx;
}
}
.zhifubao {
width: 56rpx;
height: 56rpx;
}
</style>

View File

@ -0,0 +1,557 @@
<template>
<view class="item" @appear="appear" @disappear="disappear" @click.stop :style="{height:height+'px'}">
<video class="u-flex-1 video" :show-fullscreen-btn="false" @controlstoggle="controlstoggles" v-if="showVideo"
:controls="showControls" @timeupdate="timeupdate" @waiting="waiting()" object-fit="cover"
@pause="onpause" @click="videoClick()"
@play="videoPlay('myVideo'+item.courseDetailsId,item.courseDetailsId)" :play-strategy="2"
:show-loading="true" codec="software" :muted="false" :show-center-play-btn="true" :loop="loop"
:enable-progress-gesture="false" :poster="item.titleImg" :ref="'myVideo'+item.courseDetailsId"
:autoplay="autoplay" @ended="ended" :id="'myVideo'+item.courseDetailsId" :src="item.videoUrl"></video>
<image class="poster" v-else @click="!item.videoUrl?popupShow('pay',item):''" :src="item.titleImg"
mode="aspectFill">
</image>
<view class="info" v-if="!isCommand" :style="infoStyle">
<text class="color-fff" v-if="item.courseDetailsName">{{item.courseDetailsName}}</text>
<view v-if="item.content" v-html="item.content"></view>
<view class="u-m-t-20 color-fff" @click="popupShow('show')">
<text class="color-fff">
{{item.courseDetailsName}}{{total}}选集 >
</text>
</view>
</view>
<view class="info" v-if="isCommand" :style="infoStyle">
<text class="color-fff" v-if="item.courseDetailsName">{{item.courseDetailsName}}</text>
<view v-if="item.content" v-html="item.content"></view>
<view class="u-m-t-20 color-fff" @click="toDetail">
<text class="color-fff">
查看更多续集 >
</text>
</view>
</view>
<view class="right" :style="rightStyle">
<view class="love u-flex u-flex-xy-center u-flex-col u-m-b-40 u-text-center" @click="dianzanClick">
<up-icon name="heart-fill" v-if="item.isGood==1" color="red" size="30"></up-icon>
<up-icon name="heart-fill" v-else color="#ffffff" size="30"></up-icon>
<text class="text color-fff u-font-24">{{item.goodNum<0?0:item.goodNum}}</text>
</view>
<view class="share u-m-b-40 u-flex u-flex-xy-center u-flex-col u-text-center" @click="share">
<image class="icon" src="@/static/images/share.png" mode=""></image>
<text class="text color-fff u-font-24">分享</text>
</view>
<view class="zhuiju u-m-b-40 u-flex u-flex-xy-center u-flex-col u-text-center" @click="zhuijuClick">
<image class="icon" v-if="isCollect" src="@/static/images/shuqian_s.png" mode=""></image>
<image class="icon" v-else src="@/static/images/shuqian.png" mode=""></image>
<text class="text color-fff u-font-24">{{isCollect?'已追':'追剧'}}</text>
</view>
</view>
</view>
</template>
<script setup>
import * as Api from '@/api/video/index.js'
import {
computed,
nextTick,
onMounted,
ref,
watch
} from 'vue'
let loop=ref(false)
// #ifdef APP
loop.value=true
// #endif
const props = defineProps({
height:{
type:Number,
default:0
},
item: {
type: Object,
defaulr: () => {
return {
videoUrl: ''
}
}
},
rightStyle: {
type: Object,
default: () => {
return {
}
}
},
infoStyle: {
type: Object,
default: () => {
return {
}
}
},
isCommand: {
type: Boolean,
default: false
},
instance: {
type: Object,
defaulr: () => {
return {
proxy: {}
}
}
},
current: {
//h5
type: Number,
default: 0
},
index: {
type: Number,
default: 0
},
nowIndex: {
//app
type: Number,
default: 0
},
total: {
type: Number,
default: 0
},
isCollect: {
type: [Number, Boolean],
default: 0
},
playSpeeds: {
type: Number,
default: 1
},
showControls: {
type: Boolean,
default: true
}
})
let autoplay = ref(props.item.videoUrl ? true : false)
const emits = defineEmits(['controlstoggles', 'disappear', 'appear', 'waiting', 'videoPlay', 'ended', 'dianzanClick',
'share', 'zhuijuClick', 'popupShow', 'itemMounted', 'toDetail', 'showInfo', 'playStatusChange'
])
function controlstoggles(e) {
emits('controlstoggles', e)
}
function toDetail() {
if (video) {
video.pause()
}
emits('toDetail')
}
function waiting() {
}
let isPlying = ref(false)
watch(() => isPlying.value, (newval) => {
emits('showInfo', newval)
})
//
let isFirstPlay = true
let isPlayFinish = false //
/**
* @param {type} = [start,end]
*/
function sendPlayStatus(type = 'start') {
emits('playStatusChange', {
courseId: props.item.courseId,
courseDetailsId: props.item.courseDetailsId,
type
})
// Api.playStatus({
// courseId:props.item.courseId,
// courseDetailsId:props.item.courseDetailsId,
// type
// })
}
function timeupdate(e) {
//loding
// #ifdef H5
uni.hideLoading()
// #endif
if (isPlayFinish) {
return
}
if (e.detail.currentTime > e.detail.duration * 0.9) {
if (!isFirstPlay) {
sendPlayStatus('end')
isPlayFinish = true
}
}
}
function videoPlay() {
if (isFirstPlay && !isPlayFinish) {
sendPlayStatus('start')
}
isFirstPlay = false
isPlying.value = true
// #ifdef H5
emits('controlstoggles', {
detail: {
show: false
}
})
// #endif
}
function onpause() {
isPlying.value = false
// #ifdef H5
emits('controlstoggles', {
detail: {
show: true
}
})
// #endif
}
function ended() {
sendPlayStatus('end')
}
function dianzanClick() {
emits('dianzanClick')
}
function share() {
emits('share')
}
function zhuijuClick() {
emits('zhuijuClick')
}
function popupShow(key) {
emits('popupShow', key)
}
function videoClick() {
console.log('videoClick');
if (video) {
if (isPlying.value) {
video.pause()
} else {
video.play()
}
}
}
let first = true
let isAppear = false //
function appear() {
isAppear = true
if (video && props.index == props.nowIndex) {
video.playbackRate(props.playSpeeds)
video.play()
}
emits('appear', first)
if (first) {
first = false
}
}
let video = null
function disappear() {
console.log('disappear');
isAppear = false
if (video) {
video.pause()
}
emits('disappear')
}
const showVideo = computed(() => {
if (isAppear && props.item.videoUrl) {
return true
}
// #ifdef H5
return props.current === props.index && props.item.videoUrl
// #endif
// #ifdef APP
return props.nowIndex === props.index && props.item.videoUrl
// #endif
})
onMounted(() => {
init()
emits('itemMounted', props.index)
})
function init() {
console.log('init');
try {
if (props.item.videoUrl && showVideo.value) {
video = uni.createVideoContext('myVideo' + props.item.courseDetailsId)
video.playbackRate(props.playSpeeds)
if (props.index == props.nowIndex) {
video.play()
console.log('init play');
}
}
} catch (error) {
console.error('------')
//TODO handle the exception
}
}
watch(() => props.playSpeeds, (newval) => {
console.log('speed' + newval);
if (video) {
video.playbackRate(newval)
}
})
watch(() => showVideo.value, (newval) => {
console.log('showVideo change:' + newval);
if (newval) {
isFirstPlay = true
isPlayFinish = false
// #ifdef H5
nextTick(() => {
init()
})
// #endif
// #ifdef APP
init()
// #endif
} else {
video = null
}
})
// #ifdef APP
watch(() => props.nowIndex, (newval) => {
if (props.item.videoUrl && showVideo.value && props.index == props.nowIndex) {
init()
}
})
// #endif
const showControls=computed(()=>{
// #ifdef H5
return true
// #endif
// #ifdef APP
return props.index==props.nowIndex&&!isPlying.value
// #endif
})
const infoStyle = computed(() => {
return {
transform: `translateX(${(!isPlying.value||!props.item.videoUrl)?0:'-110%'})`
}
})
const rightStyle = computed(() => {
return {
transform: `translateX(${(!isPlying.value||!props.item.videoUrl)?'0':60}px)`
}
})
</script>
<style lang="scss" scoped>
.item {
flex: 1;
height: 100%;
position: relative;
}
.box {
/* #ifdef H5 */
flex: 1;
/* #endif */
}
.u-flex-1 {
flex: 1;
width: 100%;
height: 100%;
}
.u-popup {
position: fixed !important;
}
::v-deep .u-popup {
position: fixed !important;
}
.video {
width: 750rpx;
flex: 1;
}
.poster {
/* #ifdef H5 */
position: absolute;
width: 100%;
height: 90%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* #endif */
/* #ifdef APP */
width: 750rpx;
flex: 1;
/* #endif */
}
.u-text-center {
text-align: center;
}
.u-flex-row {
flex-direction: row !important;
}
.info {
/* #ifdef H5 */
width: 80%;
/* #endif */
height: auto;
position: absolute !important;
bottom: 50px;
left: 10px;
color: #ffffff;
font-size: 15px;
z-index: 9999;
transition: transform .3s ease-in-out;
}
.u-flex-y-center {
align-items: center !important;
}
.swipers-items {
width: 750rpx;
flex: 1;
position: relative;
background-color: #000;
}
.right {
transition: transform .3s ease-in-out;
position: absolute !important;
right: 20rpx;
/* #ifdef H5 */
top: 50%;
transform: translateY(-50%);
/* #endif */
/* #ifdef APP */
top: 500px;
/* #endif */
z-index: 999;
color: #fff;
font-size: 24rpx;
.icon {
width: 60rpx;
height: 60rpx;
}
.share {
.text {
white-space: nowrap;
}
}
.zhuiju {}
}
.poster-popup {
position: fixed !important;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
z-index: 9999;
justify-content: center;
align-items: center;
}
.ji-list {
.ji-item {
width: 210rpx;
margin-bottom: 20rpx;
margin-right: 30rpx;
height: 88rpx;
font-size: 28rpx;
color: #333;
border-radius: 12rpx;
background-color: #F5F7FF;
position: relative;
&.active {
background-color: $my-main-color;
color: #fff;
}
.lock {
position: absolute;
border-radius: 0px 6px 0px 6px;
background-color: #ccc;
padding: 2rpx 4rpx;
top: 0;
right: 0;
}
.playing {
position: absolute;
width: 32rpx;
height: 24rpx;
bottom: 5px;
right: 7px;
}
}
}
.ji-item:nth-of-type(3n) {
margin-right: 0;
}
.hot {
width: 40rpx;
height: 40rpx;
}
.pay-list {
.pay-list-item {
flex-direction: row;
justify-content: center;
background-color: #F2F2F2;
padding: 24rpx;
border-radius: 20rpx;
margin-bottom: 40rpx;
}
}
.zhifubao {
width: 56rpx;
height: 56rpx;
}
</style>

View File

@ -0,0 +1,662 @@
<template>
<view class="item" @appear="appear" @disappear="disappear" @click.stop :style="{height:height+'px'}" :key="index">
<!-- :controls="showControls" -->
<video class=" video" :show-fullscreen-btn="false" @controlstoggle="controlstoggles" v-if="showVideo"
play-btn-position="bottom" :show-center-play-btn="true" :show-play-btn="true" @click.stop="videoClick()"
@loadedmetadata="loadedmetadata" @timeupdate="timeupdate" @waiting="waiting()" object-fit="cover"
@loadeddata="waiting()" @pause="onpause"
@play="videoPlay('myVideo'+item.courseDetailsId,item.courseDetailsId)" :play-strategy="2"
:show-loading="true" codec="software" :muted="false" :loop="loop" :enable-progress-gesture="false"
:poster="item.titleImg" :ref="'myVideo'+item.courseDetailsId" :autoplay="autoplay" @ended="ended"
:id="'myVideo'+item.courseDetailsId" :src="item.videoUrl"></video>
<image class="poster" v-else @click.stop="posterClick" :src="item.titleImg" mode="aspectFill">
</image>
<!-- #ifdef APP -->
<view class="control-play-cover" v-if="showControls&&isIos" @click="playCoverClick()">
</view>
<!-- #endif -->
<!-- <view class="progress" v-if="showVideo&&!isPlying" @click.stop>
<progress-vue @touchstart="progressScroll" @touchend="progressScrollEnd"></progress-vue>
</view> -->
<!-- <view class="play-icon" v-if="showVideo&&!isPlying" @click.stop="playIconClick()" :style="playStyle">
<image class="icon" src="@/static/images/play.png" mode=""></image>
</view> -->
<view class="info" v-if="!isCommand" :style="infoStyle">
<text class="color-fff" v-if="item.courseDetailsName">{{item.courseDetailsName}}</text>
<view v-if="item.content" v-html="item.content"></view>
<view class="u-m-t-20 color-fff" @click.stop="popupShow('show')">
<text class="color-fff">
{{item.courseDetailsName}}{{total}}选集 >
</text>
</view>
</view>
<view class="info" v-if="isCommand" :style="infoStyle">
<text class="color-fff" v-if="item.courseDetailsName">{{item.courseDetailsName}}</text>
<view v-if="item.content" v-html="item.content"></view>
<view class="u-m-t-20 color-fff" @click.stop="toDetail">
<text class="color-fff">
查看更多续集 >
</text>
</view>
</view>
<view class="right" :style="rightStyle">
<view class="love u-flex u-flex-xy-center u-flex-col u-m-b-40 u-text-center" @click="dianzanClick">
<up-icon name="heart-fill" v-if="item.isGood==1" color="red" size="30"></up-icon>
<up-icon name="heart-fill" v-else color="#ffffff" size="30"></up-icon>
<text class="text color-fff u-font-24">{{item.goodNum<0?0:item.goodNum}}</text>
</view>
<view class="share u-m-b-40 u-flex u-flex-xy-center u-flex-col u-text-center" @click="share">
<image class="icon" src="@/static/images/share.png" mode=""></image>
<text class="text color-fff u-font-24">分享</text>
</view>
<view class="zhuiju u-m-b-40 u-flex u-flex-xy-center u-flex-col u-text-center" @click="zhuijuClick">
<image class="icon" v-if="isCollect" src="@/static/images/shuqian_s.png" mode=""></image>
<image class="icon" v-else src="@/static/images/shuqian.png" mode=""></image>
<text class="text color-fff u-font-24">{{isCollect?'已追':'追剧'}}</text>
</view>
</view>
</view>
</template>
<script setup>
import * as Api from '@/api/video/index.js'
// #ifdef APP
const domModule = uni.requireNativePlugin('dom')
// #endif
import progressVue from './progress.vue'
import {
computed,
nextTick,
onMounted,
ref,
watch
} from 'vue'
let loop = ref(false)
// #ifdef APP
loop.value = true
// #endif
const props = defineProps({
isIos:{
type: Boolean,
default: false
},
isAndriod: {
type: Boolean,
default: false
},
height: {
type: Number,
default: 0
},
item: {
type: Object,
defaulr: () => {
return {
videoUrl: ''
}
}
},
rightStyle: {
type: Object,
default: () => {
return {
}
}
},
infoStyle: {
type: Object,
default: () => {
return {
}
}
},
isTabbar: {
type: Boolean,
default: false
},
isCommand: {
type: Boolean,
default: false
},
instance: {
type: Object,
defaulr: () => {
return {
proxy: {}
}
}
},
current: {
//h5
type: Number,
default: 0
},
index: {
type: Number,
default: 0
},
nowIndex: {
//app
type: Number,
default: 0
},
total: {
type: Number,
default: 0
},
isCollect: {
type: [Number, Boolean],
default: 0
},
playSpeeds: {
type: Number,
default: 1
},
showAndriod: {
type: Boolean,
default: false
}
})
let isWaiting = ref(true)
function waiting() {
console.log('waiting');
isWaiting.value = true
}
let showControls = ref(props.showAndriod?false:true)
let playPercent = ref(0)
let autoplay = ref(props.item.videoUrl ? true : false)
const emits = defineEmits(['controlstoggles', 'disappear', 'appear', 'waiting', 'videoPlay', 'ended', 'dianzanClick',
'share', 'zhuijuClick', 'popupShow', 'itemMounted', 'toDetail', 'playStatusChange', 'progressScroll',
'progressScrollEnd'
])
function progressScroll(e) {
emits('progressScroll')
}
function progressScrollEnd(e) {
emits('progressScrollEnd')
}
function posterClick() {
if (!props.item.videoUrl) {
popupShow('pay', props.item)
}
}
function controlstoggles(e) {
showControls.value = e.detail.show
emits('controlstoggles', e)
}
function toDetail() {
if (video) {
video.pause()
}
emits('toDetail')
}
let videoIsLoadedmetadata = ref(false)
function loadedmetadata() {
console.log('loadedmetadata');
videoIsLoadedmetadata.value = true
}
let isPlying = ref(false)
//
let isFirstPlay = true
let isPlayFinish = false //
/**
* @param {type} = [start,end]
*/
function sendPlayStatus(type = 'start') {
emits('playStatusChange', {
courseId: props.item.courseId,
courseDetailsId: props.item.courseDetailsId,
type
})
// Api.playStatus({
// courseId:props.item.courseId,
// courseDetailsId:props.item.courseDetailsId,
// type
// })
}
function timeupdate(e) {
playPercent.value = e.detail.currentTime * 100 / e.detail.duration
//loding
uni.hideLoading()
if (isPlayFinish) {
return
}
if (e.detail.currentTime > e.detail.duration * 0.9) {
if (!isFirstPlay) {
sendPlayStatus('end')
isPlayFinish = true
}
}
}
let videoBar = null
let watingTimer = null
function videoPlay() {
if (isFirstPlay && !isPlayFinish) {
sendPlayStatus('start')
}
isFirstPlay = false
isPlying.value = true
clearTimeout(watingTimer)
watingTimer = setTimeout(() => {
isWaiting.value = false
}, 1000)
// showControls.value = false
// #ifdef H5
videoBar = videoBar ? videoBar : document.querySelector('.uni-video-bar');
videoBar.style.cssText = 'display:none;';
// #endif
// #ifdef APP
if (!props.showAndriod) {}
// #endif
}
function onpause() {
isPlying.value = false
// showControls.value = true
// #ifdef H5
videoBar = videoBar ? videoBar : document.querySelector('.uni-video-bar');
videoBar.style.cssText = '';
// #endif
}
function ended() {
sendPlayStatus('end')
}
function dianzanClick() {
emits('dianzanClick')
}
function share() {
emits('share')
}
function zhuijuClick() {
emits('zhuijuClick')
}
function popupShow(key) {
emits('popupShow', key)
}
function playCoverClick() {
console.log('playCoverClick');
if (video) {
if (isPlying.value) {
video.pause()
} else {
video.play()
}
}
}
function playIconClick(){
if (video) {
if (isPlying.value) {
video.pause()
} else {
video.play()
}
}
}
function videoClick() {
console.log('videoClick');
// #ifdef APP
// ios
if (isPlying.value&&showControls.value) {
return
}
// #endif
if (video) {
if (isPlying.value) {
video.pause()
} else {
video.play()
}
}
}
let first = true
function appear() {
if (video) {
video.playbackRate(props.playSpeeds)
video.play()
}
emits('appear', first)
if (first) {
first = false
}
}
let video = null
function disappear(e) {
emits('disappear', e)
if (video) {
video.pause()
}
}
const showVideo = computed(() => {
if (props.isAndriod) {
return (props.nowIndex === props.index && props.item.videoUrl) ? true : false
} else {
return props.current === props.index && props.item.videoUrl
}
})
onMounted(() => {
init()
emits('itemMounted', props.index)
})
function init() {
try {
if (props.item.videoUrl && showVideo.value) {
video = uni.createVideoContext('myVideo' + props.item.courseDetailsId)
video.playbackRate(props.playSpeeds)
video.play()
}
} catch (error) {
console.error('------')
//TODO handle the exception
}
}
watch(() => props.playSpeeds, (newval) => {
console.log('speed' + newval);
if (video) {
video.playbackRate(newval)
}
})
watch(() => showVideo.value, (newval) => {
if (newval) {
isFirstPlay = true
isPlayFinish = false
nextTick(() => {
init()
})
} else {
video = null
}
})
const customStyle = computed(() => {
// #ifdef H5
return {
bottom: props.isTabbar ? '50px' : '0'
}
// #endif
// #ifndef H5
return {}
// #endif
})
const playStyle = computed(() => {
if (isPlying.value) {
return {
bottom: '0'
}
}
return {
bottom: props.isTabbar ? (50 + 44 + 'px') : '44px'
}
})
const infoStyle = computed(() => {
// #ifdef H5
return {
transform: `translateX(${(!isPlying.value||!props.item.videoUrl)?0:'-750rpx'})`
}
// #endif
return {
transform: `translateX(${(showControls.value||!props.item.videoUrl)?0:'-750rpx'})`
}
// return {
// transform: `translateX(${(!isPlying.value||!props.item.videoUrl)?0:'-750rpx'})`
// }
})
const rightStyle = computed(() => {
// #ifdef H5
return {
transform: `translateX(${(!isPlying.value||!props.item.videoUrl)?'0':60}px)`
}
// #endif
return {
transform: `translateX(${(showControls.value||!props.item.videoUrl)?'0':60}px)`
}
})
</script>
<style lang="scss" scoped>
.item {
// flex: 1;
// height: 100%;
position: relative;
}
/* 假设控制条的类名为 uni-video-controls */
.uni-video-controls {
transition: none !important;
-webkit-transition: none !important;
}
.box {
/* #ifdef H5 */
flex: 1;
/* #endif */
}
.u-flex-1 {
flex: 1;
width: 100%;
height: 100%;
}
.u-popup {
position: fixed !important;
}
::v-deep .u-popup {
position: fixed !important;
}
.video {
width: 750rpx;
flex: 1;
}
.poster {
/* #ifdef H5 */
position: absolute;
width: 100%;
height: 90%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* #endif */
/* #ifdef APP */
width: 750rpx;
flex: 1;
/* #endif */
}
.u-text-center {
text-align: center;
}
.u-flex-row {
flex-direction: row !important;
}
.info {
/* #ifdef H5 */
width: 80%;
/* #endif */
height: auto;
position: absolute !important;
bottom: 50px;
left: 10px;
color: #ffffff;
font-size: 15px;
z-index: 9999;
transition: transform .3s ease-in-out;
}
.u-flex-y-center {
align-items: center !important;
}
.swipers-items {
width: 750rpx;
flex: 1;
position: relative;
background-color: #000;
}
.right {
transition: transform .3s ease-in-out;
position: absolute !important;
right: 20rpx;
/* #ifdef H5 */
top: 50%;
transform: translateY(-50%);
/* #endif */
/* #ifdef APP */
bottom: 100px;
/* #endif */
z-index: 999;
color: #fff;
font-size: 24rpx;
.icon {
width: 60rpx;
height: 60rpx;
}
.share {
.text {
white-space: nowrap;
}
}
.zhuiju {}
}
.poster-popup {
position: fixed !important;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
z-index: 9999;
justify-content: center;
align-items: center;
}
.play-icon {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
justify-content: center;
align-items: center;
$icon-size: 80rpx;
.icon {
width: $icon-size;
height: $icon-size;
}
}
.hot {
width: 40rpx;
height: 40rpx;
}
.pay-list {
.pay-list-item {
flex-direction: row;
justify-content: center;
background-color: #F2F2F2;
padding: 24rpx;
border-radius: 20rpx;
margin-bottom: 40rpx;
}
}
.progress {
padding: 20rpx;
position: absolute;
bottom: 20rpx;
left: 0;
right: 0;
z-index: 1;
}
.zhifubao {
width: 56rpx;
height: 56rpx;
}
.control-play-cover {
position: absolute;
left: 10px;
bottom: 0;
width: 38px;
height: 44px;
// background-color: red;
background-color: transparent;
z-index: 1;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
<template>
<view class="progress-box">
<view class="line" :style="{width:percent+'px'}">
</view>
<view class="block" @touchstart="progressTouchStart" @touchmove="progressTouchMove"
:style="{transform:'translateX('+percent+'px)'}"
@touchend="progressTouchEnd"></view>
</view>
</template>
<script setup>
import {
ref
} from 'vue';
const props=defineProps({
})
let percent=ref(50)
//
let progressIsTouch = false
let start = 0
function progressTouchStart(e) {
console.log(e);
start = e.touches[0].clientX
progressIsTouch = true
}
function progressTouchMove(e) {
console.log(e);
const step = 1;
playPercent.value += step
}
function progressTouchEnd(e) {
console.log(e);
progressIsTouch = false
}
</script>
<style lang="scss" scoped>
.progress-box {
border-radius: 20px;
height: 5px;
margin: 4px 0;
background-color: rgba(255, 255, 255, .6);
box-shadow: 0 0 1px #eee;
flex-direction: row;
overflow: visible;
.line {
background-color: #fff;
border-radius: 20px;
overflow: visible;
}
$block-size: 8px;
.block {
top: -1px;
left: 0;
position: absolute;
z-index: 2;
width: $block-size;
height: $block-size;
background-color: #fff;
border-radius: 50%;
box-shadow: 0 0 1px #eee;
}
}
</style>

163
components/pop-ling-qu.vue Normal file
View File

@ -0,0 +1,163 @@
<template>
<view>
<u-popup v-model="show" mode="center" @close="close">
<view class="bg">
<view class="title">恭喜您获得</view>
<view class="goods">
<template v-if="result&&result.type==3">
<view class="u-flex u-col-center u-row-center">
<image style="height: 100px;" :src="result.img" mode="heightFix"></image>
</view>
<view class="u-flex u-row-center u-m-t-30">
<view class="type">{{result.name}}</view>
</view>
</template>
<template v-if="result&&result.type==2">
<view class="u-flex color-money u-col-center u-row-center">
<view class="money">{{result.number}}</view>
<view class="font-bold " style="margin-top: 20rpx;font-size: 36rpx;"></view>
</view>
<view class="u-flex u-m-t-24 u-row-center">
<view class="type">现金红包</view>
</view>
</template>
</view>
<view class="u-flex close u-row-center">
<u-icon name="close-circle" :size="54" @click="close" color="#fff"></u-icon>
</view>
</view>
</u-popup>
</view>
</template>
<script>
export default {
data() {
return {
show: false,
result: ''
}
},
methods: {
open(data) {
console.log(data);
this.result = data
this.show = true
},
close() {
console.log('抽奖弹窗关闭');
this.show = false
if(!this.result){
return
}
const {
orderId,
id
} = this.result
this.$Request.postJson('/app/discSpinning/receive', this.result).then(res => {
this.result = ''
console.log(res)
if (res.code == 0) {
console.log('抽奖领取成功');
const key=res.data==0?'isBindAliPay':undefined
this.$emit('close',key)
if(key&&key=='isBindAliPay'){
uni.navigateTo({
url:'/me/yaoqing/zhifubao-tixain'
})
}
} else {
}
})
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .u-mode-center-box {
background-color: transparent;
}
.color-money {
color: #E42F00;
}
.money {
font-weight: 700;
font-size: 96rpx;
letter-spacing: 2px;
}
.bg {
width: 628rpx;
height: 770rpx;
margin-right: 10rpx;
background-color: transparent;
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
background-image: url("~static/images/zhuanpan/gift.png");
position: relative;
@media (-webkit-min-device-pixel-ratio: 2),
(min-device-pixel-ratio: 2) {
background-image: url("~static/images/zhuanpan/gift@2x.png");
}
.title {
position: absolute;
top: 218rpx;
text-align: center;
left: 0;
right: 0;
font-weight: 700;
font-size: 60rpx;
color: #AF6920;
letter-spacing: 4rpx;
}
.goods {
position: absolute;
top: 336rpx;
text-align: center;
left: 0;
right: 0;
text-align: center;
}
.type {
padding: 6rpx 28rpx;
border-radius: 100rpx;
background: #E25B41;
font-size: 28rpx;
color: #fff;
font-weight: bold;
}
.close{
position: absolute;
bottom: 0;
left: 0;
right: 0;
}
.btn-box {
position: absolute;
top: 574rpx;
left: 0;
right: 0;
.btn {
padding: 10rpx 60rpx 10rpx 64rpx;
text-align: center;
font-weight: bold;
font-size: 44rpx;
color: #AF6920;
letter-spacing: 2px;
}
}
}
</style>

View File

@ -0,0 +1,241 @@
const isWeex = typeof WXEnvironment !== 'undefined';
const isWeexIOS = isWeex && /ios/i.test(WXEnvironment.platform);
const isWeexAndroid = isWeex && !isWeexIOS;
import GLmethod from '../context-webgl/GLmethod';
const GCanvasModule =
(typeof weex !== 'undefined' && weex.requireModule) ? (weex.requireModule('gcanvas')) :
(typeof __weex_require__ !== 'undefined') ? (__weex_require__('@weex-module/gcanvas')) : {};
let isDebugging = false;
let isComboDisabled = false;
const logCommand = (function () {
const methodQuery = [];
Object.keys(GLmethod).forEach(key => {
methodQuery[GLmethod[key]] = key;
})
const queryMethod = (id) => {
return methodQuery[parseInt(id)] || 'NotFoundMethod';
}
const logCommand = (id, cmds) => {
const mId = cmds.split(',')[0];
const mName = queryMethod(mId);
console.log(`=== callNative - componentId:${id}; method: ${mName}; cmds: ${cmds}`);
}
return logCommand;
})();
function joinArray(arr, sep) {
let res = '';
for (let i = 0; i < arr.length; i++) {
if (i !== 0) {
res += sep;
}
res += arr[i];
}
return res;
}
const commandsCache = {}
const GBridge = {
callEnable: (ref, configArray) => {
commandsCache[ref] = [];
return GCanvasModule.enable({
componentId: ref,
config: configArray
});
},
callEnableDebug: () => {
isDebugging = true;
},
callEnableDisableCombo: () => {
isComboDisabled = true;
},
callSetContextType: function (componentId, context_type) {
GCanvasModule.setContextType(context_type, componentId);
},
callReset: function(id){
GCanvasModule.resetComponent && canvasModule.resetComponent(componentId);
},
render: isWeexIOS ? function (componentId) {
return GCanvasModule.extendCallNative({
contextId: componentId,
type: 0x60000001
});
} : function (componentId) {
return callGCanvasLinkNative(componentId, 0x60000001, 'render');
},
render2d: isWeexIOS ? function (componentId, commands, callback) {
if (isDebugging) {
console.log('>>> >>> render2d ===');
console.log('>>> commands: ' + commands);
}
GCanvasModule.render([commands, callback?true:false], componentId, callback);
} : function (componentId, commands,callback) {
if (isDebugging) {
console.log('>>> >>> render2d ===');
console.log('>>> commands: ' + commands);
}
callGCanvasLinkNative(componentId, 0x20000001, commands);
if(callback){
callback();
}
},
callExtendCallNative: isWeexIOS ? function (componentId, cmdArgs) {
throw 'should not be here anymore ' + cmdArgs;
} : function (componentId, cmdArgs) {
throw 'should not be here anymore ' + cmdArgs;
},
flushNative: isWeexIOS ? function (componentId) {
const cmdArgs = joinArray(commandsCache[componentId], ';');
commandsCache[componentId] = [];
if (isDebugging) {
console.log('>>> >>> flush native ===');
console.log('>>> commands: ' + cmdArgs);
}
const result = GCanvasModule.extendCallNative({
"contextId": componentId,
"type": 0x60000000,
"args": cmdArgs
});
const res = result && result.result;
if (isDebugging) {
console.log('>>> result: ' + res);
}
return res;
} : function (componentId) {
const cmdArgs = joinArray(commandsCache[componentId], ';');
commandsCache[componentId] = [];
if (isDebugging) {
console.log('>>> >>> flush native ===');
console.log('>>> commands: ' + cmdArgs);
}
const result = callGCanvasLinkNative(componentId, 0x60000000, cmdArgs);
if (isDebugging) {
console.log('>>> result: ' + result);
}
return result;
},
callNative: function (componentId, cmdArgs, cache) {
if (isDebugging) {
logCommand(componentId, cmdArgs);
}
commandsCache[componentId].push(cmdArgs);
if (!cache || isComboDisabled) {
return GBridge.flushNative(componentId);
} else {
return undefined;
}
},
texImage2D(componentId, ...args) {
if (isWeexIOS) {
if (args.length === 6) {
const [target, level, internalformat, format, type, image] = args;
GBridge.callNative(
componentId,
GLmethod.texImage2D + ',' + 6 + ',' + target + ',' + level + ',' + internalformat + ',' + format + ',' + type + ',' + image.src
)
} else if (args.length === 9) {
const [target, level, internalformat, width, height, border, format, type, image] = args;
GBridge.callNative(
componentId,
GLmethod.texImage2D + ',' + 9 + ',' + target + ',' + level + ',' + internalformat + ',' + width + ',' + height + ',' + border + ',' +
+ format + ',' + type + ',' + (image ? image.src : 0)
)
}
} else if (isWeexAndroid) {
if (args.length === 6) {
const [target, level, internalformat, format, type, image] = args;
GCanvasModule.texImage2D(componentId, target, level, internalformat, format, type, image.src);
} else if (args.length === 9) {
const [target, level, internalformat, width, height, border, format, type, image] = args;
GCanvasModule.texImage2D(componentId, target, level, internalformat, width, height, border, format, type, (image ? image.src : 0));
}
}
},
texSubImage2D(componentId, target, level, xoffset, yoffset, format, type, image) {
if (isWeexIOS) {
if (arguments.length === 8) {
GBridge.callNative(
componentId,
GLmethod.texSubImage2D + ',' + 6 + ',' + target + ',' + level + ',' + xoffset + ',' + yoffset, + ',' + format + ',' + type + ',' + image.src
)
}
} else if (isWeexAndroid) {
GCanvasModule.texSubImage2D(componentId, target, level, xoffset, yoffset, format, type, image.src);
}
},
bindImageTexture(componentId, src, imageId) {
GCanvasModule.bindImageTexture([src, imageId], componentId);
},
perloadImage([url, id], callback) {
GCanvasModule.preLoadImage([url, id], function (image) {
image.url = url;
image.id = id;
callback(image);
});
},
measureText(text, fontStyle, componentId) {
return GCanvasModule.measureText([text, fontStyle], componentId);
},
getImageData (componentId, x, y, w, h, callback) {
GCanvasModule.getImageData([x, y,w,h],componentId,callback);
},
putImageData (componentId, data, x, y, w, h, callback) {
GCanvasModule.putImageData([x, y,w,h,data],componentId,callback);
},
toTempFilePath(componentId, x, y, width, height, destWidth, destHeight, fileType, quality, callback){
GCanvasModule.toTempFilePath([x, y, width,height, destWidth, destHeight, fileType, quality], componentId, callback);
}
}
export default GBridge;

View File

@ -0,0 +1,18 @@
class FillStyleLinearGradient {
constructor(x0, y0, x1, y1) {
this._start_pos = { _x: x0, _y: y0 };
this._end_pos = { _x: x1, _y: y1 };
this._stop_count = 0;
this._stops = [0, 0, 0, 0, 0];
}
addColorStop = function (pos, color) {
if (this._stop_count < 5 && 0.0 <= pos && pos <= 1.0) {
this._stops[this._stop_count] = { _pos: pos, _color: color };
this._stop_count++;
}
}
}
export default FillStyleLinearGradient;

View File

@ -0,0 +1,8 @@
class FillStylePattern {
constructor(img, pattern) {
this._style = pattern;
this._img = img;
}
}
export default FillStylePattern;

View File

@ -0,0 +1,17 @@
class FillStyleRadialGradient {
constructor(x0, y0, r0, x1, y1, r1) {
this._start_pos = { _x: x0, _y: y0, _r: r0 };
this._end_pos = { _x: x1, _y: y1, _r: r1 };
this._stop_count = 0;
this._stops = [0, 0, 0, 0, 0];
}
addColorStop(pos, color) {
if (this._stop_count < 5 && 0.0 <= pos && pos <= 1.0) {
this._stops[this._stop_count] = { _pos: pos, _color: color };
this._stop_count++;
}
}
}
export default FillStyleRadialGradient;

View File

@ -0,0 +1,666 @@
import FillStylePattern from './FillStylePattern';
import FillStyleLinearGradient from './FillStyleLinearGradient';
import FillStyleRadialGradient from './FillStyleRadialGradient';
import GImage from '../env/image.js';
import {
ArrayBufferToBase64,
Base64ToUint8ClampedArray
} from '../env/tool.js';
export default class CanvasRenderingContext2D {
_drawCommands = '';
_globalAlpha = 1.0;
_fillStyle = 'rgb(0,0,0)';
_strokeStyle = 'rgb(0,0,0)';
_lineWidth = 1;
_lineCap = 'butt';
_lineJoin = 'miter';
_miterLimit = 10;
_globalCompositeOperation = 'source-over';
_textAlign = 'start';
_textBaseline = 'alphabetic';
_font = '10px sans-serif';
_savedGlobalAlpha = [];
timer = null;
componentId = null;
_notCommitDrawImageCache = [];
_needRedrawImageCache = [];
_redrawCommands = '';
_autoSaveContext = true;
// _imageMap = new GHashMap();
// _textureMap = new GHashMap();
constructor() {
this.className = 'CanvasRenderingContext2D';
//this.save()
}
setFillStyle(value) {
this.fillStyle = value;
}
set fillStyle(value) {
this._fillStyle = value;
if (typeof(value) == 'string') {
this._drawCommands = this._drawCommands.concat("F" + value + ";");
} else if (value instanceof FillStylePattern) {
const image = value._img;
if (!image.complete) {
image.onload = () => {
var index = this._needRedrawImageCache.indexOf(image);
if (index > -1) {
this._needRedrawImageCache.splice(index, 1);
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
this._redrawflush(true);
}
}
this._notCommitDrawImageCache.push(image);
} else {
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
}
//CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
this._drawCommands = this._drawCommands.concat("G" + image._id + "," + value._style + ";");
} else if (value instanceof FillStyleLinearGradient) {
var command = "D" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," +
value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," +
value._stop_count;
for (var i = 0; i < value._stop_count; ++i) {
command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
}
this._drawCommands = this._drawCommands.concat(command + ";");
} else if (value instanceof FillStyleRadialGradient) {
var command = "H" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," + value._start_pos._r
.toFixed(2) + "," +
value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," + value._end_pos._r.toFixed(2) + "," +
value._stop_count;
for (var i = 0; i < value._stop_count; ++i) {
command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
}
this._drawCommands = this._drawCommands.concat(command + ";");
}
}
get fillStyle() {
return this._fillStyle;
}
get globalAlpha() {
return this._globalAlpha;
}
setGlobalAlpha(value) {
this.globalAlpha = value;
}
set globalAlpha(value) {
this._globalAlpha = value;
this._drawCommands = this._drawCommands.concat("a" + value.toFixed(2) + ";");
}
get strokeStyle() {
return this._strokeStyle;
}
setStrokeStyle(value) {
this.strokeStyle = value;
}
set strokeStyle(value) {
this._strokeStyle = value;
if (typeof(value) == 'string') {
this._drawCommands = this._drawCommands.concat("S" + value + ";");
} else if (value instanceof FillStylePattern) {
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
this._drawCommands = this._drawCommands.concat("G" + image._id + "," + value._style + ";");
} else if (value instanceof FillStyleLinearGradient) {
var command = "D" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," +
value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," +
value._stop_count;
for (var i = 0; i < value._stop_count; ++i) {
command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
}
this._drawCommands = this._drawCommands.concat(command + ";");
} else if (value instanceof FillStyleRadialGradient) {
var command = "H" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," + value._start_pos._r
.toFixed(2) + "," +
value._end_pos._x.toFixed(2) + "," + value._end_pos._y + ",".toFixed(2) + value._end_pos._r.toFixed(2) + "," +
value._stop_count;
for (var i = 0; i < value._stop_count; ++i) {
command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
}
this._drawCommands = this._drawCommands.concat(command + ";");
}
}
get lineWidth() {
return this._lineWidth;
}
setLineWidth(value) {
this.lineWidth = value;
}
set lineWidth(value) {
this._lineWidth = value;
this._drawCommands = this._drawCommands.concat("W" + value + ";");
}
get lineCap() {
return this._lineCap;
}
setLineCap(value) {
this.lineCap = value;
}
set lineCap(value) {
this._lineCap = value;
this._drawCommands = this._drawCommands.concat("C" + value + ";");
}
get lineJoin() {
return this._lineJoin;
}
setLineJoin(value) {
this.lineJoin = value
}
set lineJoin(value) {
this._lineJoin = value;
this._drawCommands = this._drawCommands.concat("J" + value + ";");
}
get miterLimit() {
return this._miterLimit;
}
setMiterLimit(value) {
this.miterLimit = value
}
set miterLimit(value) {
this._miterLimit = value;
this._drawCommands = this._drawCommands.concat("M" + value + ";");
}
get globalCompositeOperation() {
return this._globalCompositeOperation;
}
set globalCompositeOperation(value) {
this._globalCompositeOperation = value;
let mode = 0;
switch (value) {
case "source-over":
mode = 0;
break;
case "source-atop":
mode = 5;
break;
case "source-in":
mode = 0;
break;
case "source-out":
mode = 2;
break;
case "destination-over":
mode = 4;
break;
case "destination-atop":
mode = 4;
break;
case "destination-in":
mode = 4;
break;
case "destination-out":
mode = 3;
break;
case "lighter":
mode = 1;
break;
case "copy":
mode = 2;
break;
case "xor":
mode = 6;
break;
default:
mode = 0;
}
this._drawCommands = this._drawCommands.concat("B" + mode + ";");
}
get textAlign() {
return this._textAlign;
}
setTextAlign(value) {
this.textAlign = value
}
set textAlign(value) {
this._textAlign = value;
let Align = 0;
switch (value) {
case "start":
Align = 0;
break;
case "end":
Align = 1;
break;
case "left":
Align = 2;
break;
case "center":
Align = 3;
break;
case "right":
Align = 4;
break;
default:
Align = 0;
}
this._drawCommands = this._drawCommands.concat("A" + Align + ";");
}
get textBaseline() {
return this._textBaseline;
}
setTextBaseline(value) {
this.textBaseline = value
}
set textBaseline(value) {
this._textBaseline = value;
let baseline = 0;
switch (value) {
case "alphabetic":
baseline = 0;
break;
case "middle":
baseline = 1;
break;
case "top":
baseline = 2;
break;
case "hanging":
baseline = 3;
break;
case "bottom":
baseline = 4;
break;
case "ideographic":
baseline = 5;
break;
default:
baseline = 0;
break;
}
this._drawCommands = this._drawCommands.concat("E" + baseline + ";");
}
get font() {
return this._font;
}
setFontSize(size) {
var str = this._font;
var strs = str.trim().split(/\s+/);
for (var i = 0; i < strs.length; i++) {
var values = ["normal", "italic", "oblique", "normal", "small-caps", "normal", "bold",
"bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900",
"normal", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed",
"semi-expanded", "expanded", "extra-expanded", "ultra-expanded"
];
if (-1 == values.indexOf(strs[i].trim())) {
if (typeof size === 'string') {
strs[i] = size;
} else if (typeof size === 'number') {
strs[i] = String(size) + 'px';
}
break;
}
}
this.font = strs.join(" ");
}
set font(value) {
this._font = value;
this._drawCommands = this._drawCommands.concat("j" + value + ";");
}
setTransform(a, b, c, d, tx, ty) {
this._drawCommands = this._drawCommands.concat("t" +
(a === 1 ? "1" : a.toFixed(2)) + "," +
(b === 0 ? "0" : b.toFixed(2)) + "," +
(c === 0 ? "0" : c.toFixed(2)) + "," +
(d === 1 ? "1" : d.toFixed(2)) + "," + tx.toFixed(2) + "," + ty.toFixed(2) + ";");
}
transform(a, b, c, d, tx, ty) {
this._drawCommands = this._drawCommands.concat("f" +
(a === 1 ? "1" : a.toFixed(2)) + "," +
(b === 0 ? "0" : b.toFixed(2)) + "," +
(c === 0 ? "0" : c.toFixed(2)) + "," +
(d === 1 ? "1" : d.toFixed(2)) + "," + tx + "," + ty + ";");
}
resetTransform() {
this._drawCommands = this._drawCommands.concat("m;");
}
scale(a, d) {
this._drawCommands = this._drawCommands.concat("k" + a.toFixed(2) + "," +
d.toFixed(2) + ";");
}
rotate(angle) {
this._drawCommands = this._drawCommands
.concat("r" + angle.toFixed(6) + ";");
}
translate(tx, ty) {
this._drawCommands = this._drawCommands.concat("l" + tx.toFixed(2) + "," + ty.toFixed(2) + ";");
}
save() {
this._savedGlobalAlpha.push(this._globalAlpha);
this._drawCommands = this._drawCommands.concat("v;");
}
restore() {
this._drawCommands = this._drawCommands.concat("e;");
this._globalAlpha = this._savedGlobalAlpha.pop();
}
createPattern(img, pattern) {
if (typeof img === 'string') {
var imgObj = new GImage();
imgObj.src = img;
img = imgObj;
}
return new FillStylePattern(img, pattern);
}
createLinearGradient(x0, y0, x1, y1) {
return new FillStyleLinearGradient(x0, y0, x1, y1);
}
createRadialGradient = function(x0, y0, r0, x1, y1, r1) {
return new FillStyleRadialGradient(x0, y0, r0, x1, y1, r1);
};
createCircularGradient = function(x0, y0, r0) {
return new FillStyleRadialGradient(x0, y0, 0, x0, y0, r0);
};
strokeRect(x, y, w, h) {
this._drawCommands = this._drawCommands.concat("s" + x + "," + y + "," + w + "," + h + ";");
}
clearRect(x, y, w, h) {
this._drawCommands = this._drawCommands.concat("c" + x + "," + y + "," + w +
"," + h + ";");
}
clip() {
this._drawCommands = this._drawCommands.concat("p;");
}
resetClip() {
this._drawCommands = this._drawCommands.concat("q;");
}
closePath() {
this._drawCommands = this._drawCommands.concat("o;");
}
moveTo(x, y) {
this._drawCommands = this._drawCommands.concat("g" + x.toFixed(2) + "," + y.toFixed(2) + ";");
}
lineTo(x, y) {
this._drawCommands = this._drawCommands.concat("i" + x.toFixed(2) + "," + y.toFixed(2) + ";");
}
quadraticCurveTo = function(cpx, cpy, x, y) {
this._drawCommands = this._drawCommands.concat("u" + cpx + "," + cpy + "," + x + "," + y + ";");
}
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, ) {
this._drawCommands = this._drawCommands.concat(
"z" + cp1x.toFixed(2) + "," + cp1y.toFixed(2) + "," + cp2x.toFixed(2) + "," + cp2y.toFixed(2) + "," +
x.toFixed(2) + "," + y.toFixed(2) + ";");
}
arcTo(x1, y1, x2, y2, radius) {
this._drawCommands = this._drawCommands.concat("h" + x1 + "," + y1 + "," + x2 + "," + y2 + "," + radius + ";");
}
beginPath() {
this._drawCommands = this._drawCommands.concat("b;");
}
fillRect(x, y, w, h) {
this._drawCommands = this._drawCommands.concat("n" + x + "," + y + "," + w +
"," + h + ";");
}
rect(x, y, w, h) {
this._drawCommands = this._drawCommands.concat("w" + x + "," + y + "," + w + "," + h + ";");
}
fill() {
this._drawCommands = this._drawCommands.concat("L;");
}
stroke(path) {
this._drawCommands = this._drawCommands.concat("x;");
}
arc(x, y, radius, startAngle, endAngle, anticlockwise) {
let ianticlockwise = 0;
if (anticlockwise) {
ianticlockwise = 1;
}
this._drawCommands = this._drawCommands.concat(
"y" + x.toFixed(2) + "," + y.toFixed(2) + "," +
radius.toFixed(2) + "," + startAngle + "," + endAngle + "," + ianticlockwise +
";"
);
}
fillText(text, x, y) {
let tmptext = text.replace(/!/g, "!!");
tmptext = tmptext.replace(/,/g, "!,");
tmptext = tmptext.replace(/;/g, "!;");
this._drawCommands = this._drawCommands.concat("T" + tmptext + "," + x + "," + y + ",0.0;");
}
strokeText = function(text, x, y) {
let tmptext = text.replace(/!/g, "!!");
tmptext = tmptext.replace(/,/g, "!,");
tmptext = tmptext.replace(/;/g, "!;");
this._drawCommands = this._drawCommands.concat("U" + tmptext + "," + x + "," + y + ",0.0;");
}
measureText(text) {
return CanvasRenderingContext2D.GBridge.measureText(text, this.font, this.componentId);
}
isPointInPath = function(x, y) {
throw new Error('GCanvas not supported yet');
}
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) {
if (typeof image === 'string') {
var imgObj = new GImage();
imgObj.src = image;
image = imgObj;
}
if (image instanceof GImage) {
if (!image.complete) {
imgObj.onload = () => {
var index = this._needRedrawImageCache.indexOf(image);
if (index > -1) {
this._needRedrawImageCache.splice(index, 1);
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
this._redrawflush(true);
}
}
this._notCommitDrawImageCache.push(image);
} else {
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
}
var srcArgs = [image, sx, sy, sw, sh, dx, dy, dw, dh];
var args = [];
for (var arg in srcArgs) {
if (typeof(srcArgs[arg]) != 'undefined') {
args.push(srcArgs[arg]);
}
}
this.__drawImage.apply(this, args);
//this.__drawImage(image,sx, sy, sw, sh, dx, dy, dw, dh);
}
}
__drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) {
const numArgs = arguments.length;
function drawImageCommands() {
if (numArgs === 3) {
const x = parseFloat(sx) || 0.0;
const y = parseFloat(sy) || 0.0;
return ("d" + image._id + ",0,0," +
image.width + "," + image.height + "," +
x + "," + y + "," + image.width + "," + image.height + ";");
} else if (numArgs === 5) {
const x = parseFloat(sx) || 0.0;
const y = parseFloat(sy) || 0.0;
const width = parseInt(sw) || image.width;
const height = parseInt(sh) || image.height;
return ("d" + image._id + ",0,0," +
image.width + "," + image.height + "," +
x + "," + y + "," + width + "," + height + ";");
} else if (numArgs === 9) {
sx = parseFloat(sx) || 0.0;
sy = parseFloat(sy) || 0.0;
sw = parseInt(sw) || image.width;
sh = parseInt(sh) || image.height;
dx = parseFloat(dx) || 0.0;
dy = parseFloat(dy) || 0.0;
dw = parseInt(dw) || image.width;
dh = parseInt(dh) || image.height;
return ("d" + image._id + "," +
sx + "," + sy + "," + sw + "," + sh + "," +
dx + "," + dy + "," + dw + "," + dh + ";");
}
}
this._drawCommands += drawImageCommands();
}
_flush(reserve, callback) {
const commands = this._drawCommands;
this._drawCommands = '';
CanvasRenderingContext2D.GBridge.render2d(this.componentId, commands, callback);
this._needRender = false;
}
_redrawflush(reserve, callback) {
const commands = this._redrawCommands;
CanvasRenderingContext2D.GBridge.render2d(this.componentId, commands, callback);
if (this._needRedrawImageCache.length == 0) {
this._redrawCommands = '';
}
}
draw(reserve, callback) {
if (!reserve) {
this._globalAlpha = this._savedGlobalAlpha.pop();
this._savedGlobalAlpha.push(this._globalAlpha);
this._redrawCommands = this._drawCommands;
this._needRedrawImageCache = this._notCommitDrawImageCache;
if (this._autoSaveContext) {
this._drawCommands = ("v;" + this._drawCommands);
this._autoSaveContext = false;
} else {
this._drawCommands = ("e;X;v;" + this._drawCommands);
}
} else {
this._needRedrawImageCache = this._needRedrawImageCache.concat(this._notCommitDrawImageCache);
this._redrawCommands += this._drawCommands;
if (this._autoSaveContext) {
this._drawCommands = ("v;" + this._drawCommands);
this._autoSaveContext = false;
}
}
this._notCommitDrawImageCache = [];
if (this._flush) {
this._flush(reserve, callback);
}
}
getImageData(x, y, w, h, callback) {
CanvasRenderingContext2D.GBridge.getImageData(this.componentId, x, y, w, h, function(res) {
res.data = Base64ToUint8ClampedArray(res.data);
if (typeof(callback) == 'function') {
callback(res);
}
});
}
putImageData(data, x, y, w, h, callback) {
if (data instanceof Uint8ClampedArray) {
data = ArrayBufferToBase64(data);
CanvasRenderingContext2D.GBridge.putImageData(this.componentId, data, x, y, w, h, function(res) {
if (typeof(callback) == 'function') {
callback(res);
}
});
}
}
toTempFilePath(x, y, width, height, destWidth, destHeight, fileType, quality, callback) {
CanvasRenderingContext2D.GBridge.toTempFilePath(this.componentId, x, y, width, height, destWidth, destHeight,
fileType, quality,
function(res) {
if (typeof(callback) == 'function') {
callback(res);
}
});
}
}

View File

@ -0,0 +1,11 @@
export default class WebGLActiveInfo {
className = 'WebGLActiveInfo';
constructor({
type, name, size
}) {
this.type = type;
this.name = name;
this.size = size;
}
}

View File

@ -0,0 +1,21 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLBuffer';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLBuffer {
className = name;
constructor(id) {
this.id = id;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

View File

@ -0,0 +1,21 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLFrameBuffer';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLFramebuffer {
className = name;
constructor(id) {
this.id = id;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

View File

@ -0,0 +1,298 @@
export default {
"DEPTH_BUFFER_BIT": 256,
"STENCIL_BUFFER_BIT": 1024,
"COLOR_BUFFER_BIT": 16384,
"POINTS": 0,
"LINES": 1,
"LINE_LOOP": 2,
"LINE_STRIP": 3,
"TRIANGLES": 4,
"TRIANGLE_STRIP": 5,
"TRIANGLE_FAN": 6,
"ZERO": 0,
"ONE": 1,
"SRC_COLOR": 768,
"ONE_MINUS_SRC_COLOR": 769,
"SRC_ALPHA": 770,
"ONE_MINUS_SRC_ALPHA": 771,
"DST_ALPHA": 772,
"ONE_MINUS_DST_ALPHA": 773,
"DST_COLOR": 774,
"ONE_MINUS_DST_COLOR": 775,
"SRC_ALPHA_SATURATE": 776,
"FUNC_ADD": 32774,
"BLEND_EQUATION": 32777,
"BLEND_EQUATION_RGB": 32777,
"BLEND_EQUATION_ALPHA": 34877,
"FUNC_SUBTRACT": 32778,
"FUNC_REVERSE_SUBTRACT": 32779,
"BLEND_DST_RGB": 32968,
"BLEND_SRC_RGB": 32969,
"BLEND_DST_ALPHA": 32970,
"BLEND_SRC_ALPHA": 32971,
"CONSTANT_COLOR": 32769,
"ONE_MINUS_CONSTANT_COLOR": 32770,
"CONSTANT_ALPHA": 32771,
"ONE_MINUS_CONSTANT_ALPHA": 32772,
"BLEND_COLOR": 32773,
"ARRAY_BUFFER": 34962,
"ELEMENT_ARRAY_BUFFER": 34963,
"ARRAY_BUFFER_BINDING": 34964,
"ELEMENT_ARRAY_BUFFER_BINDING": 34965,
"STREAM_DRAW": 35040,
"STATIC_DRAW": 35044,
"DYNAMIC_DRAW": 35048,
"BUFFER_SIZE": 34660,
"BUFFER_USAGE": 34661,
"CURRENT_VERTEX_ATTRIB": 34342,
"FRONT": 1028,
"BACK": 1029,
"FRONT_AND_BACK": 1032,
"TEXTURE_2D": 3553,
"CULL_FACE": 2884,
"BLEND": 3042,
"DITHER": 3024,
"STENCIL_TEST": 2960,
"DEPTH_TEST": 2929,
"SCISSOR_TEST": 3089,
"POLYGON_OFFSET_FILL": 32823,
"SAMPLE_ALPHA_TO_COVERAGE": 32926,
"SAMPLE_COVERAGE": 32928,
"NO_ERROR": 0,
"INVALID_ENUM": 1280,
"INVALID_VALUE": 1281,
"INVALID_OPERATION": 1282,
"OUT_OF_MEMORY": 1285,
"CW": 2304,
"CCW": 2305,
"LINE_WIDTH": 2849,
"ALIASED_POINT_SIZE_RANGE": 33901,
"ALIASED_LINE_WIDTH_RANGE": 33902,
"CULL_FACE_MODE": 2885,
"FRONT_FACE": 2886,
"DEPTH_RANGE": 2928,
"DEPTH_WRITEMASK": 2930,
"DEPTH_CLEAR_VALUE": 2931,
"DEPTH_FUNC": 2932,
"STENCIL_CLEAR_VALUE": 2961,
"STENCIL_FUNC": 2962,
"STENCIL_FAIL": 2964,
"STENCIL_PASS_DEPTH_FAIL": 2965,
"STENCIL_PASS_DEPTH_PASS": 2966,
"STENCIL_REF": 2967,
"STENCIL_VALUE_MASK": 2963,
"STENCIL_WRITEMASK": 2968,
"STENCIL_BACK_FUNC": 34816,
"STENCIL_BACK_FAIL": 34817,
"STENCIL_BACK_PASS_DEPTH_FAIL": 34818,
"STENCIL_BACK_PASS_DEPTH_PASS": 34819,
"STENCIL_BACK_REF": 36003,
"STENCIL_BACK_VALUE_MASK": 36004,
"STENCIL_BACK_WRITEMASK": 36005,
"VIEWPORT": 2978,
"SCISSOR_BOX": 3088,
"COLOR_CLEAR_VALUE": 3106,
"COLOR_WRITEMASK": 3107,
"UNPACK_ALIGNMENT": 3317,
"PACK_ALIGNMENT": 3333,
"MAX_TEXTURE_SIZE": 3379,
"MAX_VIEWPORT_DIMS": 3386,
"SUBPIXEL_BITS": 3408,
"RED_BITS": 3410,
"GREEN_BITS": 3411,
"BLUE_BITS": 3412,
"ALPHA_BITS": 3413,
"DEPTH_BITS": 3414,
"STENCIL_BITS": 3415,
"POLYGON_OFFSET_UNITS": 10752,
"POLYGON_OFFSET_FACTOR": 32824,
"TEXTURE_BINDING_2D": 32873,
"SAMPLE_BUFFERS": 32936,
"SAMPLES": 32937,
"SAMPLE_COVERAGE_VALUE": 32938,
"SAMPLE_COVERAGE_INVERT": 32939,
"COMPRESSED_TEXTURE_FORMATS": 34467,
"DONT_CARE": 4352,
"FASTEST": 4353,
"NICEST": 4354,
"GENERATE_MIPMAP_HINT": 33170,
"BYTE": 5120,
"UNSIGNED_BYTE": 5121,
"SHORT": 5122,
"UNSIGNED_SHORT": 5123,
"INT": 5124,
"UNSIGNED_INT": 5125,
"FLOAT": 5126,
"DEPTH_COMPONENT": 6402,
"ALPHA": 6406,
"RGB": 6407,
"RGBA": 6408,
"LUMINANCE": 6409,
"LUMINANCE_ALPHA": 6410,
"UNSIGNED_SHORT_4_4_4_4": 32819,
"UNSIGNED_SHORT_5_5_5_1": 32820,
"UNSIGNED_SHORT_5_6_5": 33635,
"FRAGMENT_SHADER": 35632,
"VERTEX_SHADER": 35633,
"MAX_VERTEX_ATTRIBS": 34921,
"MAX_VERTEX_UNIFORM_VECTORS": 36347,
"MAX_VARYING_VECTORS": 36348,
"MAX_COMBINED_TEXTURE_IMAGE_UNITS": 35661,
"MAX_VERTEX_TEXTURE_IMAGE_UNITS": 35660,
"MAX_TEXTURE_IMAGE_UNITS": 34930,
"MAX_FRAGMENT_UNIFORM_VECTORS": 36349,
"SHADER_TYPE": 35663,
"DELETE_STATUS": 35712,
"LINK_STATUS": 35714,
"VALIDATE_STATUS": 35715,
"ATTACHED_SHADERS": 35717,
"ACTIVE_UNIFORMS": 35718,
"ACTIVE_ATTRIBUTES": 35721,
"SHADING_LANGUAGE_VERSION": 35724,
"CURRENT_PROGRAM": 35725,
"NEVER": 512,
"LESS": 513,
"EQUAL": 514,
"LEQUAL": 515,
"GREATER": 516,
"NOTEQUAL": 517,
"GEQUAL": 518,
"ALWAYS": 519,
"KEEP": 7680,
"REPLACE": 7681,
"INCR": 7682,
"DECR": 7683,
"INVERT": 5386,
"INCR_WRAP": 34055,
"DECR_WRAP": 34056,
"VENDOR": 7936,
"RENDERER": 7937,
"VERSION": 7938,
"NEAREST": 9728,
"LINEAR": 9729,
"NEAREST_MIPMAP_NEAREST": 9984,
"LINEAR_MIPMAP_NEAREST": 9985,
"NEAREST_MIPMAP_LINEAR": 9986,
"LINEAR_MIPMAP_LINEAR": 9987,
"TEXTURE_MAG_FILTER": 10240,
"TEXTURE_MIN_FILTER": 10241,
"TEXTURE_WRAP_S": 10242,
"TEXTURE_WRAP_T": 10243,
"TEXTURE": 5890,
"TEXTURE_CUBE_MAP": 34067,
"TEXTURE_BINDING_CUBE_MAP": 34068,
"TEXTURE_CUBE_MAP_POSITIVE_X": 34069,
"TEXTURE_CUBE_MAP_NEGATIVE_X": 34070,
"TEXTURE_CUBE_MAP_POSITIVE_Y": 34071,
"TEXTURE_CUBE_MAP_NEGATIVE_Y": 34072,
"TEXTURE_CUBE_MAP_POSITIVE_Z": 34073,
"TEXTURE_CUBE_MAP_NEGATIVE_Z": 34074,
"MAX_CUBE_MAP_TEXTURE_SIZE": 34076,
"TEXTURE0": 33984,
"TEXTURE1": 33985,
"TEXTURE2": 33986,
"TEXTURE3": 33987,
"TEXTURE4": 33988,
"TEXTURE5": 33989,
"TEXTURE6": 33990,
"TEXTURE7": 33991,
"TEXTURE8": 33992,
"TEXTURE9": 33993,
"TEXTURE10": 33994,
"TEXTURE11": 33995,
"TEXTURE12": 33996,
"TEXTURE13": 33997,
"TEXTURE14": 33998,
"TEXTURE15": 33999,
"TEXTURE16": 34000,
"TEXTURE17": 34001,
"TEXTURE18": 34002,
"TEXTURE19": 34003,
"TEXTURE20": 34004,
"TEXTURE21": 34005,
"TEXTURE22": 34006,
"TEXTURE23": 34007,
"TEXTURE24": 34008,
"TEXTURE25": 34009,
"TEXTURE26": 34010,
"TEXTURE27": 34011,
"TEXTURE28": 34012,
"TEXTURE29": 34013,
"TEXTURE30": 34014,
"TEXTURE31": 34015,
"ACTIVE_TEXTURE": 34016,
"REPEAT": 10497,
"CLAMP_TO_EDGE": 33071,
"MIRRORED_REPEAT": 33648,
"FLOAT_VEC2": 35664,
"FLOAT_VEC3": 35665,
"FLOAT_VEC4": 35666,
"INT_VEC2": 35667,
"INT_VEC3": 35668,
"INT_VEC4": 35669,
"BOOL": 35670,
"BOOL_VEC2": 35671,
"BOOL_VEC3": 35672,
"BOOL_VEC4": 35673,
"FLOAT_MAT2": 35674,
"FLOAT_MAT3": 35675,
"FLOAT_MAT4": 35676,
"SAMPLER_2D": 35678,
"SAMPLER_CUBE": 35680,
"VERTEX_ATTRIB_ARRAY_ENABLED": 34338,
"VERTEX_ATTRIB_ARRAY_SIZE": 34339,
"VERTEX_ATTRIB_ARRAY_STRIDE": 34340,
"VERTEX_ATTRIB_ARRAY_TYPE": 34341,
"VERTEX_ATTRIB_ARRAY_NORMALIZED": 34922,
"VERTEX_ATTRIB_ARRAY_POINTER": 34373,
"VERTEX_ATTRIB_ARRAY_BUFFER_BINDING": 34975,
"IMPLEMENTATION_COLOR_READ_TYPE": 35738,
"IMPLEMENTATION_COLOR_READ_FORMAT": 35739,
"COMPILE_STATUS": 35713,
"LOW_FLOAT": 36336,
"MEDIUM_FLOAT": 36337,
"HIGH_FLOAT": 36338,
"LOW_INT": 36339,
"MEDIUM_INT": 36340,
"HIGH_INT": 36341,
"FRAMEBUFFER": 36160,
"RENDERBUFFER": 36161,
"RGBA4": 32854,
"RGB5_A1": 32855,
"RGB565": 36194,
"DEPTH_COMPONENT16": 33189,
"STENCIL_INDEX8": 36168,
"DEPTH_STENCIL": 34041,
"RENDERBUFFER_WIDTH": 36162,
"RENDERBUFFER_HEIGHT": 36163,
"RENDERBUFFER_INTERNAL_FORMAT": 36164,
"RENDERBUFFER_RED_SIZE": 36176,
"RENDERBUFFER_GREEN_SIZE": 36177,
"RENDERBUFFER_BLUE_SIZE": 36178,
"RENDERBUFFER_ALPHA_SIZE": 36179,
"RENDERBUFFER_DEPTH_SIZE": 36180,
"RENDERBUFFER_STENCIL_SIZE": 36181,
"FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE": 36048,
"FRAMEBUFFER_ATTACHMENT_OBJECT_NAME": 36049,
"FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL": 36050,
"FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE": 36051,
"COLOR_ATTACHMENT0": 36064,
"DEPTH_ATTACHMENT": 36096,
"STENCIL_ATTACHMENT": 36128,
"DEPTH_STENCIL_ATTACHMENT": 33306,
"NONE": 0,
"FRAMEBUFFER_COMPLETE": 36053,
"FRAMEBUFFER_INCOMPLETE_ATTACHMENT": 36054,
"FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT": 36055,
"FRAMEBUFFER_INCOMPLETE_DIMENSIONS": 36057,
"FRAMEBUFFER_UNSUPPORTED": 36061,
"FRAMEBUFFER_BINDING": 36006,
"RENDERBUFFER_BINDING": 36007,
"MAX_RENDERBUFFER_SIZE": 34024,
"INVALID_FRAMEBUFFER_OPERATION": 1286,
"UNPACK_FLIP_Y_WEBGL": 37440,
"UNPACK_PREMULTIPLY_ALPHA_WEBGL": 37441,
"CONTEXT_LOST_WEBGL": 37442,
"UNPACK_COLORSPACE_CONVERSION_WEBGL": 37443,
"BROWSER_DEFAULT_WEBGL": 37444
};

View File

@ -0,0 +1,142 @@
let i = 1;
const GLmethod = {};
GLmethod.activeTexture = i++; //1
GLmethod.attachShader = i++;
GLmethod.bindAttribLocation = i++;
GLmethod.bindBuffer = i++;
GLmethod.bindFramebuffer = i++;
GLmethod.bindRenderbuffer = i++;
GLmethod.bindTexture = i++;
GLmethod.blendColor = i++;
GLmethod.blendEquation = i++;
GLmethod.blendEquationSeparate = i++; //10
GLmethod.blendFunc = i++;
GLmethod.blendFuncSeparate = i++;
GLmethod.bufferData = i++;
GLmethod.bufferSubData = i++;
GLmethod.checkFramebufferStatus = i++;
GLmethod.clear = i++;
GLmethod.clearColor = i++;
GLmethod.clearDepth = i++;
GLmethod.clearStencil = i++;
GLmethod.colorMask = i++; //20
GLmethod.compileShader = i++;
GLmethod.compressedTexImage2D = i++;
GLmethod.compressedTexSubImage2D = i++;
GLmethod.copyTexImage2D = i++;
GLmethod.copyTexSubImage2D = i++;
GLmethod.createBuffer = i++;
GLmethod.createFramebuffer = i++;
GLmethod.createProgram = i++;
GLmethod.createRenderbuffer = i++;
GLmethod.createShader = i++; //30
GLmethod.createTexture = i++;
GLmethod.cullFace = i++;
GLmethod.deleteBuffer = i++;
GLmethod.deleteFramebuffer = i++;
GLmethod.deleteProgram = i++;
GLmethod.deleteRenderbuffer = i++;
GLmethod.deleteShader = i++;
GLmethod.deleteTexture = i++;
GLmethod.depthFunc = i++;
GLmethod.depthMask = i++; //40
GLmethod.depthRange = i++;
GLmethod.detachShader = i++;
GLmethod.disable = i++;
GLmethod.disableVertexAttribArray = i++;
GLmethod.drawArrays = i++;
GLmethod.drawArraysInstancedANGLE = i++;
GLmethod.drawElements = i++;
GLmethod.drawElementsInstancedANGLE = i++;
GLmethod.enable = i++;
GLmethod.enableVertexAttribArray = i++; //50
GLmethod.flush = i++;
GLmethod.framebufferRenderbuffer = i++;
GLmethod.framebufferTexture2D = i++;
GLmethod.frontFace = i++;
GLmethod.generateMipmap = i++;
GLmethod.getActiveAttrib = i++;
GLmethod.getActiveUniform = i++;
GLmethod.getAttachedShaders = i++;
GLmethod.getAttribLocation = i++;
GLmethod.getBufferParameter = i++; //60
GLmethod.getContextAttributes = i++;
GLmethod.getError = i++;
GLmethod.getExtension = i++;
GLmethod.getFramebufferAttachmentParameter = i++;
GLmethod.getParameter = i++;
GLmethod.getProgramInfoLog = i++;
GLmethod.getProgramParameter = i++;
GLmethod.getRenderbufferParameter = i++;
GLmethod.getShaderInfoLog = i++;
GLmethod.getShaderParameter = i++; //70
GLmethod.getShaderPrecisionFormat = i++;
GLmethod.getShaderSource = i++;
GLmethod.getSupportedExtensions = i++;
GLmethod.getTexParameter = i++;
GLmethod.getUniform = i++;
GLmethod.getUniformLocation = i++;
GLmethod.getVertexAttrib = i++;
GLmethod.getVertexAttribOffset = i++;
GLmethod.isBuffer = i++;
GLmethod.isContextLost = i++; //80
GLmethod.isEnabled = i++;
GLmethod.isFramebuffer = i++;
GLmethod.isProgram = i++;
GLmethod.isRenderbuffer = i++;
GLmethod.isShader = i++;
GLmethod.isTexture = i++;
GLmethod.lineWidth = i++;
GLmethod.linkProgram = i++;
GLmethod.pixelStorei = i++;
GLmethod.polygonOffset = i++; //90
GLmethod.readPixels = i++;
GLmethod.renderbufferStorage = i++;
GLmethod.sampleCoverage = i++;
GLmethod.scissor = i++;
GLmethod.shaderSource = i++;
GLmethod.stencilFunc = i++;
GLmethod.stencilFuncSeparate = i++;
GLmethod.stencilMask = i++;
GLmethod.stencilMaskSeparate = i++;
GLmethod.stencilOp = i++; //100
GLmethod.stencilOpSeparate = i++;
GLmethod.texImage2D = i++;
GLmethod.texParameterf = i++;
GLmethod.texParameteri = i++;
GLmethod.texSubImage2D = i++;
GLmethod.uniform1f = i++;
GLmethod.uniform1fv = i++;
GLmethod.uniform1i = i++;
GLmethod.uniform1iv = i++;
GLmethod.uniform2f = i++; //110
GLmethod.uniform2fv = i++;
GLmethod.uniform2i = i++;
GLmethod.uniform2iv = i++;
GLmethod.uniform3f = i++;
GLmethod.uniform3fv = i++;
GLmethod.uniform3i = i++;
GLmethod.uniform3iv = i++;
GLmethod.uniform4f = i++;
GLmethod.uniform4fv = i++;
GLmethod.uniform4i = i++; //120
GLmethod.uniform4iv = i++;
GLmethod.uniformMatrix2fv = i++;
GLmethod.uniformMatrix3fv = i++;
GLmethod.uniformMatrix4fv = i++;
GLmethod.useProgram = i++;
GLmethod.validateProgram = i++;
GLmethod.vertexAttrib1f = i++; //new
GLmethod.vertexAttrib2f = i++; //new
GLmethod.vertexAttrib3f = i++; //new
GLmethod.vertexAttrib4f = i++; //new //130
GLmethod.vertexAttrib1fv = i++; //new
GLmethod.vertexAttrib2fv = i++; //new
GLmethod.vertexAttrib3fv = i++; //new
GLmethod.vertexAttrib4fv = i++; //new
GLmethod.vertexAttribPointer = i++;
GLmethod.viewport = i++;
export default GLmethod;

View File

@ -0,0 +1,23 @@
const GLtype = {};
[
"GLbitfield",
"GLboolean",
"GLbyte",
"GLclampf",
"GLenum",
"GLfloat",
"GLint",
"GLintptr",
"GLsizei",
"GLsizeiptr",
"GLshort",
"GLubyte",
"GLuint",
"GLushort"
].sort().map((typeName, i) => GLtype[typeName] = 1 >> (i + 1));
export default GLtype;

View File

@ -0,0 +1,21 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLProgram';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLProgram {
className = name;
constructor(id) {
this.id = id;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

View File

@ -0,0 +1,21 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLRenderBuffer';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLRenderbuffer {
className = name;
constructor(id) {
this.id = id;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLShader';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLShader {
className = name;
constructor(id, type) {
this.id = id;
this.type = type;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

View File

@ -0,0 +1,11 @@
export default class WebGLShaderPrecisionFormat {
className = 'WebGLShaderPrecisionFormat';
constructor({
rangeMin, rangeMax, precision
}) {
this.rangeMin = rangeMin;
this.rangeMax = rangeMax;
this.precision = precision;
}
}

View File

@ -0,0 +1,22 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLTexture';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLTexture {
className = name;
constructor(id, type) {
this.id = id;
this.type = type;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

View File

@ -0,0 +1,22 @@
import {getTransferedObjectUUID} from './classUtils';
const name = 'WebGLUniformLocation';
function uuid(id) {
return getTransferedObjectUUID(name, id);
}
export default class WebGLUniformLocation {
className = name;
constructor(id, type) {
this.id = id;
this.type = type;
}
static uuid = uuid;
uuid() {
return uuid(this.id);
}
}

View File

@ -0,0 +1,3 @@
export function getTransferedObjectUUID(name, id) {
return `${name.toLowerCase()}-${id}`;
}

74
gcanvas/env/canvas.js vendored Normal file
View File

@ -0,0 +1,74 @@
import GContext2D from '../context-2d/RenderingContext';
import GContextWebGL from '../context-webgl/RenderingContext';
export default class GCanvas {
// static GBridge = null;
id = null;
_needRender = true;
constructor(id, { disableAutoSwap }) {
this.id = id;
this._disableAutoSwap = disableAutoSwap;
if (disableAutoSwap) {
this._swapBuffers = () => {
GCanvas.GBridge.render(this.id);
}
}
}
getContext(type) {
let context = null;
if (type.match(/webgl/i)) {
context = new GContextWebGL(this);
context.componentId = this.id;
if (!this._disableAutoSwap) {
const render = () => {
if (this._needRender) {
GCanvas.GBridge.render(this.id);
this._needRender = false;
}
}
setInterval(render, 16);
}
GCanvas.GBridge.callSetContextType(this.id, 1); // 0 for 2d; 1 for webgl
} else if (type.match(/2d/i)) {
context = new GContext2D(this);
context.componentId = this.id;
// const render = ( callback ) => {
//
// const commands = context._drawCommands;
// context._drawCommands = '';
//
// GCanvas.GBridge.render2d(this.id, commands, callback);
// this._needRender = false;
// }
// //draw方法触发
// context._flush = render;
// //setInterval(render, 16);
GCanvas.GBridge.callSetContextType(this.id, 0);
} else {
throw new Error('not supported context ' + type);
}
return context;
}
reset() {
GCanvas.GBridge.callReset(this.id);
}
}

96
gcanvas/env/image.js vendored Normal file
View File

@ -0,0 +1,96 @@
let incId = 1;
const noop = function () { };
class GImage {
static GBridge = null;
constructor() {
this._id = incId++;
this._width = 0;
this._height = 0;
this._src = undefined;
this._onload = noop;
this._onerror = noop;
this.complete = false;
}
get width() {
return this._width;
}
set width(v) {
this._width = v;
}
get height() {
return this._height;
}
set height(v) {
this._height = v;
}
get src() {
return this._src;
}
set src(v) {
if (v.startsWith('//')) {
v = 'http:' + v;
}
this._src = v;
GImage.GBridge.perloadImage([this._src, this._id], (data) => {
if (typeof data === 'string') {
data = JSON.parse(data);
}
if (data.error) {
var evt = { type: 'error', target: this };
this.onerror(evt);
} else {
this.complete = true;
this.width = typeof data.width === 'number' ? data.width : 0;
this.height = typeof data.height === 'number' ? data.height : 0;
var evt = { type: 'load', target: this };
this.onload(evt);
}
});
}
addEventListener(name, listener) {
if (name === 'load') {
this.onload = listener;
} else if (name === 'error') {
this.onerror = listener;
}
}
removeEventListener(name, listener) {
if (name === 'load') {
this.onload = noop;
} else if (name === 'error') {
this.onerror = noop;
}
}
get onload() {
return this._onload;
}
set onload(v) {
this._onload = v;
}
get onerror() {
return this._onerror;
}
set onerror(v) {
this._onerror = v;
}
}
export default GImage;

24
gcanvas/env/tool.js vendored Normal file
View File

@ -0,0 +1,24 @@
export function ArrayBufferToBase64 (buffer) {
var binary = '';
var bytes = new Uint8ClampedArray(buffer);
for (var len = bytes.byteLength, i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
export function Base64ToUint8ClampedArray(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = atob(base64);
const outputArray = new Uint8ClampedArray(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}

39
gcanvas/index.js Normal file
View File

@ -0,0 +1,39 @@
import GCanvas from './env/canvas';
import GImage from './env/image';
import GWebGLRenderingContext from './context-webgl/RenderingContext';
import GContext2D from './context-2d/RenderingContext';
import GBridgeWeex from './bridge/bridge-weex';
export let Image = GImage;
export let WeexBridge = GBridgeWeex;
export function enable(el, { bridge, debug, disableAutoSwap, disableComboCommands } = {}) {
const GBridge = GImage.GBridge = GCanvas.GBridge = GWebGLRenderingContext.GBridge = GContext2D.GBridge = bridge;
GBridge.callEnable(el.ref, [
0, // renderMode: 0--RENDERMODE_WHEN_DIRTY, 1--RENDERMODE_CONTINUOUSLY
-1, // hybridLayerType: 0--LAYER_TYPE_NONE 1--LAYER_TYPE_SOFTWARE 2--LAYER_TYPE_HARDWARE
false, // supportScroll
false, // newCanvasMode
1, // compatible
'white',// clearColor
false // sameLevel: newCanvasMode = true && true => GCanvasView and Webview is same level
]);
if (debug === true) {
GBridge.callEnableDebug();
}
if (disableComboCommands) {
GBridge.callEnableDisableCombo();
}
var canvas = new GCanvas(el.ref, { disableAutoSwap });
canvas.width = el.style.width;
canvas.height = el.style.height;
return canvas;
};

View File

@ -1,177 +1,250 @@
// 导入全局属性
import {
sm4DecryptByResData
} from '@/utils/encryptUtil.js'
import infoBox from "@/utils/infoBox.js"
import { reject } from 'lodash';
import config from '@/commons/config.js'
} from "@/utils/encryptUtil.js";
import infoBox from "@/utils/infoBox.js";
import {
reject
} from "lodash";
import config from "@/commons/config.js";
// 测试服
let baseUrl = config.baseApiUrl
const loadingShowTime = 200
function getHeader(){
const headerObject={}
headerObject["token"] = uni.getStorageSync('token')
return headerObject
let baseUrl = config.baseApiUrl + "app";
const loadingShowTime = 200;
function getHeader(data) {
const header = data ? data.header : {}
const headerObject = {
...header
};
headerObject["token"] = uni.getStorageSync("token");
return headerObject;
}
// 通用处理逻辑
function commonsProcess(showLoading, httpReqCallback) {
// 通用处理逻辑
function commonsProcess(showLoading, httpReqCallback, isreturm) {
// 判断是否请求完成(用作 是否loading
// 包括: 'ing', 'ingLoading', 'finish'
let reqState = 'ing'
let reqState = "ing";
// 是否已经提示的错误信息
let isShowErrorToast = false
let isShowErrorToast = false;
// 请求完成, 需要处理的动作
let reqFinishFunc = () => {
if (reqState == 'ingLoading') { // 关闭loading弹层
infoBox.hideLoading()
if (reqState == "ingLoading") {
// 关闭loading弹层
infoBox.hideLoading();
}
reqState = 'finish' // 请求完毕
}
// 明确显示loading
reqState = "finish"; // 请求完毕
};
// 明确显示loading
if (showLoading) {
// xx ms内响应完成不提示loading
setTimeout(() => {
if (reqState == 'ing') {
reqState = 'ingLoading'
infoBox.showLoading()
if (reqState == "ing") {
reqState = "ingLoading";
infoBox.showLoading();
}
}, loadingShowTime)
}, loadingShowTime);
}
return httpReqCallback().then((httpData) => {
reqFinishFunc(); // 请求完毕的动作
// 从http响应数据中解构响应数据 [ 响应码、 bodyData ]
let {
statusCode,
data
} = httpData
// 避免混淆重新命名
let bodyData = data
if (statusCode == 500) {
isShowErrorToast = true
return Promise.reject(bodyData) // 跳转到catch函数
}
if (statusCode == 401) {
// 提示信息
isShowErrorToast = true
return Promise.reject(bodyData) // 跳转到catch函数
}
// http响应码不正确
if (statusCode != 200 && statusCode != 204 && statusCode != 201) {
isShowErrorToast = true
data.message=data.message=='Bad credentials'?'用户名或密码错误':data.message
infoBox.showToast(data.message || '服务器异常')
return Promise.reject(bodyData) // 跳转到catch函数
}
return httpReqCallback()
.then((httpData) => {
// 加密数据
if (!bodyData.data && bodyData.encryptData) {
reqFinishFunc(); // 请求完毕的动作
// 从http响应数据中解构响应数据 [ 响应码、 bodyData ]
let {
statusCode,
data
} = httpData;
// 避免混淆重新命名
let bodyData = data;
if (isreturm) {
return Promise.resolve(bodyData);
}
if (statusCode == 500) {
isShowErrorToast = true;
return Promise.reject(bodyData); // 跳转到catch函数
}
return Promise.resolve({
bizData: sm4DecryptByResData(bodyData.encryptData),
code: bodyData.code
})
}
if (statusCode == 401) {
// 提示信息
isShowErrorToast = true;
return Promise.reject(bodyData); // 跳转到catch函数
}
// http响应码不正确
if (statusCode != 200 && statusCode != 204 && statusCode != 201) {
isShowErrorToast = true;
infoBox.showToast(data.message || "服务器异常");
return Promise.reject(bodyData); // 跳转到catch函数
}
if (bodyData.code == 401) {
// 提示信息
isShowErrorToast = true;
return Promise.reject(bodyData); // 跳转到catch函数
}
if (bodyData.code == 500) {
// 提示信息
isShowErrorToast = true;
return Promise.reject(bodyData); // 跳转到catch函数
}
if (bodyData.code != 0) {
infoBox.showToast(data.message);
return;
}
// 加密数据
if (!bodyData.data && bodyData.encryptData) {
return Promise.resolve({
bizData: sm4DecryptByResData(bodyData.encryptData),
code: bodyData.code,
});
}
let result=null;
if(bodyData.hasOwnProperty('data')){
result=bodyData.data
}
else if(bodyData.hasOwnProperty('page')){
result=bodyData.page
}
else{
result=bodyData
}
// 构造请求成功的响应数据
return Promise.resolve(result);
})
.catch((res) => {
// 构造请求成功的响应数据
return Promise.resolve(bodyData)
if (res.status == 404) {
infoBox.showToast("接口404").then(() => {});
reject();
return;
}
}).catch(res => {
if(res.status==401){
infoBox.showErrorToast(res.message||'请登录').then(() => {
uni.redirectTo({url: '/pages/login/index'})
reject()
})
}
if(res.status==500){
infoBox.showErrorToast(res.message||'服务器异常').then(() => {
})
}
reqFinishFunc(); // 请求完毕的动作
if (res.code == 401) {
uni.redirectTo({
url: "/pages/login/login",
});
reject();
}
if (res.code != 0&&res.code != 401) {
infoBox.showToast(res.msg).then(() => {});
reject();
}
if (res.code == 500) {
infoBox.showToast(res.msg || "服务器异常").then(() => {});
reject();
}
reqFinishFunc(); // 请求完毕的动作
// 如果没有提示错误, 那么此处提示 异常。
if (!isShowErrorToast) {
infoBox.showErrorToast(`请求网络异常`)
}
return Promise.reject(res)
}).finally(() => { // finally 是 then结束后再执行, 此处不适用。 需要在请求完成后立马调用: reqFinishFunc()
});
// 如果没有提示错误, 那么此处提示 异常。
if (!isShowErrorToast) {
infoBox.showToast(`请求网络异常`);
}
return Promise.reject(res);
})
.finally(() => {
// finally 是 then结束后再执行, 此处不适用。 需要在请求完成后立马调用: reqFinishFunc()
});
}
// 默认 显示loading(控制 xxs 内 不提示loading )
function req(uri, data, method = "GET", showLoading = true, extParams = {}) {
return commonsProcess(showLoading, () => {
return uni.request(
Object.assign({
url: baseUrl + uri,
data: data,
method: method,
header: getHeader()
}, extParams)
)
})
url: baseUrl + uri,
data: data,
method: method,
header: getHeader(data),
},
extParams
)
);
});
}
// 默认 显示loading(控制 xxs 内 不提示loading )
function request(args) {
const {
let {
url,
data,
params,
method = "GET",
showLoading = true,
extParams = {}
extParams = {},
isreturm = false
} = args
if (params) {
let result = ''
Object.keys(params).forEach((key) => {
if (!Object.is(params[key], undefined) && !Object.is(params[key], null) && !Object.is(JSON
.stringify(params[key]), '{}')) {
result += encodeURIComponent(key) + '=' + encodeURIComponent(params[key]) + "&"
}
})
url = url + '?' + (result.slice(0, result.length - 1))
params = null
}
let headerObject = {}
return commonsProcess(showLoading, () => {
return uni.request(
Object.assign({
url: baseUrl + url,
data: params||data,
url: slash(baseUrl, url),
data: params || data,
method: method,
header: getHeader()
header: getHeader(data)
}, extParams)
)
})
}, isreturm)
}
// 处理/
function slash(baseUrl, url) {
let u = "";
if (baseUrl[baseUrl.length - 1] == "/") {
u += baseUrl;
} else {
u = u + baseUrl + "/";
}
if (url[0] == "/") {
u = u + url.slice(1);
} else {
u = u + url;
}
return u;
}
// 上传
function upload(uri, data, file, showLoading = true, extParams = {}) {
// 放置token
let headerObject = {}
let headerObject = {};
return commonsProcess(showLoading, () => {
return uni.uploadFile(
Object.assign({
url: baseUrl + uri,
formData: data,
name: "file",
filePath: file.path||file.url,
header: getHeader()
}, extParams)
).then((httpData) => {
// uni.upload 返回bodyData 的是 string类型。 需要解析。
httpData.data = JSON.parse(httpData.data)
return Promise.resolve(httpData)
}).catch(err=>{
uni.hideLoading()
infoBox.showErrorToast(`上传失败`)
})
})
return uni
.uploadFile(
Object.assign({
url: baseUrl + uri,
formData: data,
name: "file",
filePath: file.path || file.url,
header: getHeader(data),
},
extParams
)
)
.then((httpData) => {
// uni.upload 返回bodyData 的是 string类型。 需要解析。
httpData.data = JSON.parse(httpData.data);
return Promise.resolve(httpData);
})
.catch((err) => {
uni.hideLoading();
infoBox.showToast(`上传失败`);
});
});
}
export default {
req: req,
request,
upload: upload
}
upload: upload,
};

18
main.js
View File

@ -1,6 +1,12 @@
import App from './App'
import uviewPlus from 'uview-plus'
import * as Pinia from "pinia";
import {
createUnistorage
} from "pinia-plugin-unistorage";
import {
useCommonStore
} from '@/store/common.js'
// #ifndef VUE3
import Vue from 'vue'
import './uni.promisify.adaptor'
@ -11,16 +17,22 @@ const app = new Vue({
})
app.$mount()
// #endif
// #ifdef VUE3
import {
createSSRApp
} from 'vue'
export function createApp() {
const app = createSSRApp(App)
const store = Pinia.createPinia();
store.use(createUnistorage());
app.use(uviewPlus)
app.use(store)
const $common = useCommonStore()
$common.init()
return {
app
app,
Pinia
}
}
// #endif

View File

@ -1,9 +1,9 @@
{
"name" : "duanju-app-v3",
"name" : "斯耀短剧",
"appid" : "__UNI__E0B05B1",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"versionName" : "1.2.5",
"versionCode" : 125,
"transformPx" : false,
/* 5+App */
"app-plus" : {
@ -20,7 +20,8 @@
"modules" : {
"Camera" : {},
"Push" : {},
"VideoPlayer" : {}
"VideoPlayer" : {},
"Canvas" : "nvue canvas" //使Canvas
},
/* */
"distribute" : {
@ -54,7 +55,8 @@
"NSPhotoLibraryUsageDescription" : "获取您的相册读取权限,目的是为了在我的资料页面使用相册读取功能,修改上传头像",
"NSCameraUsageDescription" : "获取您的摄像头权限,目的是为了在我的资料页面使用摄像头功能,修改上传头像"
},
"urltypes" : "com.hnsiyao.duanju"
"urltypes" : "com.hnsiyao.duanju",
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {
@ -62,7 +64,7 @@
"unipush" : {}
},
"ad" : {
"gdt" : {}
"ks" : {}
}
},
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ],

287
package-lock.json generated
View File

@ -1,70 +1,295 @@
{
"name": "new_app",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"clipboard": "^2.0.11",
"dayjs": "^1.11.13",
"uview-plus": "^3.3.61"
"lockfileVersion": 1,
"dependencies": {
"@babel/runtime": {
"version": "7.26.0",
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.26.0.tgz",
"integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
"requires": {
"regenerator-runtime": "^0.14.0"
}
},
"node_modules/clipboard": {
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
"clipboard": {
"version": "2.0.11",
"resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
"integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
"license": "MIT",
"dependencies": {
"requires": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"node_modules/dayjs": {
"concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmmirror.com/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"requires": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^2.2.2",
"typedarray": "^0.0.6"
}
},
"copy-text-to-clipboard": {
"version": "3.2.0",
"resolved": "https://registry.npmmirror.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz",
"integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q=="
},
"core-js": {
"version": "3.40.0",
"resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.40.0.tgz",
"integrity": "sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ=="
},
"core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-5.1.0.tgz",
"integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==",
"requires": {
"lru-cache": "^4.0.1",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
},
"dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
"license": "MIT"
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
},
"node_modules/delegate": {
"delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
"license": "MIT"
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
},
"node_modules/good-listener": {
"gm-crypto": {
"version": "0.1.12",
"resolved": "https://registry.npmmirror.com/gm-crypto/-/gm-crypto-0.1.12.tgz",
"integrity": "sha512-ercd9ionBqxR+/FCXICr0eo+jzC8BvSK0j9L7/eB0uwbyjgeMPTdBNrcQTqIuRXOtOAKSGsTNvtLYFnIxNEoFg==",
"requires": {
"buffer": "^5.7.0",
"jsbn": "^1.1.0",
"to-arraybuffer": "^1.0.1"
}
},
"good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
"license": "MIT",
"dependencies": {
"requires": {
"delegate": "^3.1.2"
}
},
"node_modules/select": {
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lru-cache": {
"version": "4.1.5",
"resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-4.1.5.tgz",
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
"requires": {
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
}
},
"mutation-observer": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/mutation-observer/-/mutation-observer-1.0.3.tgz",
"integrity": "sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA=="
},
"os-shim": {
"version": "0.1.3",
"resolved": "https://registry.npmmirror.com/os-shim/-/os-shim-0.1.3.tgz",
"integrity": "sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A=="
},
"node_modules/pinia-plugin-unistorage": {
"version": "0.1.2",
"resolved": "https://registry.npmmirror.com/pinia-plugin-unistorage/-/pinia-plugin-unistorage-0.1.2.tgz",
"integrity": "sha512-WXit2cGnm5rG6CDTcLSLehNWhyJS/Yq7WEeeXAapZbCnqoPJxlszqg7rT8S+OP47az0h5nlajGo+LuyMxUQ2uw==",
"dev": true,
"license": "MIT"
},
"node_modules/pre-commit": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/pre-commit/-/pre-commit-1.2.2.tgz",
"integrity": "sha512-qokTiqxD6GjODy5ETAIgzsRgnBWWQHQH2ghy86PU7mIn/wuWeTwF3otyNQZxWBwVn8XNr8Tdzj/QfUXpH+gRZA==",
"requires": {
"cross-spawn": "^5.0.1",
"spawn-sync": "^1.0.15",
"which": "1.2.x"
}
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="
},
"readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"select": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
"integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==",
"license": "MIT"
"integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
},
"node_modules/tiny-emitter": {
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-1.2.0.tgz",
"integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
"requires": {
"shebang-regex": "^1.0.0"
}
},
"shebang-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-1.0.0.tgz",
"integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="
},
"spawn-sync": {
"version": "1.0.15",
"resolved": "https://registry.npmmirror.com/spawn-sync/-/spawn-sync-1.0.15.tgz",
"integrity": "sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw==",
"requires": {
"concat-stream": "^1.4.7",
"os-shim": "^0.1.2"
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
},
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
"license": "MIT"
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
},
"node_modules/uview-plus": {
"to-arraybuffer": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
"integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA=="
},
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmmirror.com/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"uview-plus": {
"version": "3.3.61",
"resolved": "https://registry.npmmirror.com/uview-plus/-/uview-plus-3.3.61.tgz",
"integrity": "sha512-1IdZMYd7KuByW+bfBseEuSaKcYB6F4q8bGqAru1UDKIkRVTxkPlqvsTE8Q0+I0+jk6q1ov1KbGFDuyXxVzXcCg==",
"dependencies": {
"requires": {
"clipboard": "^2.0.11",
"dayjs": "^1.11.3"
},
"engines": {
"HBuilderX": "^3.1.0"
}
},
"vconsole": {
"version": "3.15.1",
"resolved": "https://registry.npmmirror.com/vconsole/-/vconsole-3.15.1.tgz",
"integrity": "sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==",
"requires": {
"@babel/runtime": "^7.17.2",
"copy-text-to-clipboard": "^3.0.1",
"core-js": "^3.11.0",
"mutation-observer": "^1.0.3"
}
},
"which": {
"version": "1.2.14",
"resolved": "https://registry.npmmirror.com/which/-/which-1.2.14.tgz",
"integrity": "sha512-16uPglFkRPzgiUXYMi1Jf8Z5EzN1iB4V0ZtMXcHZnwsBtQhhHeCqoWw7tsUY42hJGNDWtUsVLTjakIa5BgAxCw==",
"requires": {
"isexe": "^2.0.0"
}
},
"yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmmirror.com/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
}
}
}

View File

@ -1,12 +1,26 @@
{
"id": "mosowe-rotary-table-compatible",
"name": "抽奖转盘非固定图片可自定义传入奖项列表v2 v3兼容",
"displayName": "抽奖转盘非固定图片可自定义传入奖项列表v2 v3兼容",
"version": "1.0.0",
"description": "抽奖转盘非固定图片可自定义传入奖项列表v2 v3兼容",
"keywords": [
"抽奖",
"转盘",
"转盘抽奖",
"轮盘抽奖"
],
"dcloudext": {
"category": [
"前端组件",
"通用组件"
]
},
"dependencies": {
"clipboard": "^2.0.11",
"dayjs": "^1.11.13",
"gm-crypto": "^0.1.8",
"jsbn": "^1.1.0",
"lodash": "^4.17.21",
"pre-commit": "^1.2.2",
"to-arraybuffer": "^1.0.1",
"uview-plus": "^3.3.61"
"uview-plus": "^3.3.62"
},
"devDependencies": {
"pinia-plugin-unistorage": "^0.1.2"
}
}

View File

@ -12,15 +12,258 @@
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app"
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
}, {
"path": "pages/video/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/video/detail",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/task/index",
"style": {
"navigationBarTitleText": "任务大厅",
"navigationStyle": "custom"
}
}, {
"path": "pages/chasingDrama/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enablePullDownRefresh": true
}
}, {
"path": "pages/watching_history/watching_history",
"style": {
"enablePullDownRefresh": true
}
}, {
"path": "pages/me/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enablePullDownRefresh": true
}
}, {
"path": "pages/me/contact",
"style": {
"navigationBarTitleText": "联系客服"
}
}, {
"path": "pages/me/gold_record",
"style": {
"navigationBarTitleText": "金币明细",
"enablePullDownRefresh": true
}
}, {
"path": "pages/me/feedback",
"style": {
"navigationBarTitleText": "意见反馈"
}
}, {
"path": "pages/me/help_center",
"style": {
"navigationBarTitleText": "帮助中心"
}
}, {
"path": "pages/me/setting",
"style": {
"navigationBarTitleText": "设置"
}
}, {
"path": "pages/me/help_center_detail",
"style": {
"navigationBarTitleText": ""
}
}, {
"path": "pages/login/login",
"style": {
"navigationBarTitleText": "登录",
"navigationStyle": "custom"
}
}, {
"path": "pages/login/register",
"style": {
"navigationBarTitleText": "注册",
"navigationStyle": "custom"
}
}, {
"path": "pages/login/bind",
"style": {
"navigationBarTitleText": "修改手机号"
}
}, {
"path": "pages/login/registerApp",
"style": {
"navigationBarTitleText": "注册",
"navigationStyle": "custom"
}
}, {
"path": "pages/login/forgetPwd",
"style": {
"navigationBarTitleText": "忘记密码",
"navigationStyle": "custom"
}
}, {
"path": "pages/login/download",
"style": {
"navigationBarTitleText": "下载"
}
}, {
"path": "pages/me/userInfo",
"style": {
"navigationBarTitleText": "个人资料"
}
}, {
"path": "pages/me/privacy",
"style": {
"navigationBarTitleText": "隐私协议"
}
}, {
"path": "pages/me/agreement",
"style": {
"navigationBarTitleText": "服务协议"
}
}, {
"path": "pages/me/message",
"style": {
"navigationBarTitleText": "消息中心"
}
}, {
"path": "pages/me/withdraw/index",
"style": {
"navigationBarTitleText": "申请提现",
"navigationStyle": "custom"
}
}, {
"path": "pages/me/withdraw/realName",
"style": {
"navigationBarTitleText": "实名认证"
}
}, {
"path": "pages/index/prizeDraw/kevy-luckydraw",
"style": {
"navigationBarTitleText": "大转盘抽奖"
}
}, {
"path": "pages/me/withdraw/alipay",
"style": {
"navigationBarTitleText": "提现账号"
}
}, {
"path": "pages/me/withdraw/moneyList",
"style": {
"navigationBarTitleText": "红包明细"
}
}, {
"path": "pages/share/index",
"style": {
"navigationBarTitleText": "分享"
}
},
{
"path": "pages/index/search/index",
"style": {
"navigationBarTitleText": "搜索"
}
},
{
"path": "pages/task/prizeList",
"style": {
"navigationBarTitleText": "任务"
}
},
{
"path": "pages/task/receiveMember",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/pays/pays",
"style": {
"navigationBarTitleText": ""
}
},
{
"path" : "pages/index/prizeDraw/LotteryRecords",
"style" :
{
"navigationBarTitleText" : "我的奖励"
}
},
{
"path" : "pages/index/prizeDraw/duihuan",
"style" :
{
"navigationBarTitleText" : "兑换"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarTitleText": "",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"uniIdRouter": {}
"tabBar": {
"color": "#333333",
"selectedColor": "#FF7581",
"backgroundColor": "#FFFFFF",
"borderStyle": "black",
"list": [{
"pagePath": "pages/index/index",
"iconPath": "static/tabbar/index.png",
"selectedIconPath": "static/tabbar/index_2.png",
"text": "小剧场"
}, {
"pagePath": "pages/video/index",
"iconPath": "static/tabbar/learn.png",
"selectedIconPath": "static/tabbar/learn_2.png",
"text": "推荐"
},
{
"pagePath": "pages/task/index",
"iconPath": "static/tabbar/task.png",
"selectedIconPath": "static/tabbar/task_2.png",
"text": "任务"
},
{
"pagePath": "pages/chasingDrama/index",
"iconPath": "static/tabbar/zhuiju.png",
"selectedIconPath": "static/tabbar/zhuiju_2.png",
"text": "追剧"
},
{
"pagePath": "pages/me/index",
"iconPath": "static/tabbar/me.png",
"selectedIconPath": "static/tabbar/me_2.png",
"text": "我的"
}
]
},
"uniIdRouter": {},
"condition" : { //
"current": 0, //(list )
"list": [
{
"name": "", //
"path": "", //
"query": "" //onLoad
}
]
}
}

View File

@ -0,0 +1,172 @@
<template>
<view class="container">
<view class="u-status-bar"></view>
<view class="list-wrap">
<view class="title-wrap">
<view class="title">最近观看</view>
<navigator class="more" url="/pages/watching_history/watching_history?type=3">更多</navigator>
</view>
<view class="list">
<view
class="item"
v-for="item in data.list1"
:key="item.id"
@click="linkTo(`/pages/video/detail?courseId=${item.courseId}&courseDetailsId=${item.courseDetailsId}`)"
>
<view class="cover">
<image class="img" :src="item.titleImg" mode="aspectFill"></image>
<view class="num">{{ item.courseDetailsName }}</view>
</view>
<view class="intro-wrap">
<view class="name">{{ item.title }}</view>
<view class="t">{{ item.courseLabel }}</view>
</view>
</view>
</view>
<emprty-card v-if="!data.list1.length" />
</view>
<view class="list-wrap">
<view class="title-wrap">
<view class="title">我的追剧</view>
<navigator class="more" url="/pages/watching_history/watching_history?type=1">更多</navigator>
</view>
<view class="list">
<view
class="item"
v-for="item in data.list2"
:key="item.id"
@click="linkTo(`/pages/video/detail?courseId=${item.courseId}&courseDetailsId=${item.courseDetailsId}`)"
>
<div class="item-content">
<view class="cover">
<image class="img" :src="item.titleImg" mode="aspectFill"></image>
<view class="num">{{ item.courseDetailsName }}</view>
</view>
<view class="intro-wrap">
<view class="name">{{ item.title }}</view>
<view class="t">{{ item.courseLabel }}</view>
</view>
</div>
</view>
</view>
<emprty-card v-if="!data.list2.length" />
</view>
</view>
</template>
<script setup>
import { reactive } from 'vue';
import { selectByUserId } from '@/api/me/me.js';
import { onLoad, onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app';
import { linkTo } from '@/utils/app.js';
//
async function selectByUserIdAjax() {
try {
const res1 = await selectByUserId({ page: 1, limit: 6, classify: 3 });
const res2 = await selectByUserId({ page: 1, limit: 6, classify: 1 });
data.list1 = res1.records;
data.list2 = res2.records;
} catch (error) {
console.log(error);
}
setTimeout(() => {
uni.stopPullDownRefresh();
}, 500);
}
const data = reactive({
list1: [], //
list2: [] //
});
//
onReachBottom(() => {});
//
onPullDownRefresh(() => {
selectByUserIdAjax();
});
//
onLoad(() => {
selectByUserIdAjax();
});
</script>
<style lang="scss">
page {
background: #f5f7ff;
}
</style>
<style scoped lang="scss">
.container {
color: #333;
font-size: 28upx;
}
.list-wrap {
margin-bottom: 40upx;
.title-wrap {
display: flex;
justify-content: space-between;
align-items: center;
padding: 28upx;
.title {
font-weight: bold;
font-size: 32upx;
}
.more {
color: #999;
}
}
.list {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(auto, 1fr);
grid-column-gap: 28upx;
grid-row-gap: 28upx;
padding: 0 28upx;
.item {
width: 100%;
overflow: hidden;
background-color: #fff;
border-radius: 20upx;
.cover {
height: 200upx;
position: relative;
.img {
width: 100%;
height: 100%;
}
.num {
padding: 4upx 16upx;
border-radius: 8upx;
background: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(5px);
position: absolute;
right: 8upx;
bottom: 8upx;
color: #fff;
font-size: 24upx;
}
}
.intro-wrap {
padding: 20upx;
.name {
width: 180upx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 32upx;
font-weight: bold;
}
.t {
color: #999;
font-size: 24upx;
margin-top: 8upx;
}
}
}
}
}
</style>

View File

@ -0,0 +1,62 @@
<template>
<view class="contentlist">
<view class="liststyle" v-for="item in props.list" :key="item.courseId" @tap="seVideo(item)">
<image :src="item.titleImg" style="width: 188rpx;height: 247rpx;border-radius:21rpx 21rpx 21rpx 21rpx"
mode=""></image>
<view style="color: #333333;">
{{item.title.slice(0,6)}}
</view>
<view style="color: #999999;">
{{item.courseLabel}}
</view>
</view>
</view>
</template>
<script setup>
import {
returnIsSafari
} from '@/utils/app.js'
const props = defineProps({
list: {
type: Array,
default: []
},
})
function seVideo(item) {
uni.navigateTo({
url: "/pages/video/detail?courseId=" + item.courseId + "&courseDetailsId=" + item.courseDetailsId
})
}
</script>
<style scoped lang="scss">
.contentlist {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
margin-top: 10rpx;
padding: 0 26rpx;
.liststyle {
border-radius: 21rpx 21rpx 21rpx 21rpx;
width: 30%;
margin-top: 20rpx;
text-align: center;
>view {
font-weight: 400;
font-size: 25rpx;
text-align: left;
margin-left: 10rpx;
}
}
// .liststyle:last-child {
// margin-right: auto;
// margin-left: 6rpx;
// }
}
</style>

View File

@ -1,14 +1,402 @@
<template>
<view class="indexStyle">
<image src="@/static/index/indexbh.png" mode="">
</image>
<view class="indexStyleTwo">
<image src="@/static/logo.png" mode=""></image>
<!-- <view @tap="moreVideo">
<image src="@/static/sosuo.png" style="height: 34rpx;width: 34rpx;" mode=""></image>
点击搜索更多好剧
</view> -->
</view>
<template v-if="datas.isExamine">
<view class="gongao">
<view class="gongaoicon">
公告
</view>
<swiper :autoplay="true" :vertical="true" :interval="4000" :circular="true" :indicator-dots="false"
class="swiperstyle">
<swiper-item v-for="(item, index) in datas.noticeList" :key="index">
<view style="height: 80rpx;line-height: 80rpx;">{{ item.title }}</view>
</swiper-item>
</swiper>
</view>
</template>
</view>
<view class="navTop">
<view :class="datas.active == 1 ? 'navTop-active' : ''" @tap="getrecomVideo('', 1)">
最新
</view>
<view :class="datas.active == 2 ? 'navTop-active' : ''" @tap="getrecomVideo('1', 2)">
排行
</view>
<view :class="datas.active == 3 ? 'navTop-active' : ''" @tap="getrecomVideo('2', 3)">
最热
</view>
<view :class="datas.active == 4 ? 'navTop-active' : ''" @tap="getrecomVideo('1', 4)">
剧情
</view>
<view :class="datas.active == 5 ? 'navTop-active' : ''" @tap="getrecomVideo('2', 5)">
飙升
</view>
</view>
<contentlist :list='datas.list'></contentlist>
<image v-if="datas.isExamine" @click="goMsg()" src="@/static/index/red-pack-new.gif"
style="width: 200rpx;height: 200rpx;position: fixed;right: 10rpx;bottom: 180rpx;" mode=""></image>
<up-modal :show="datas.version.show" :confirm-text="datas.version.confirmText"
:showCancelButton="datas.version.cancelText!=''" @cancel="cancelUpdateVersion" @confirm='confirmUpdateVersion'
:title="datas.version.title" :title-style="{ fontWeight: '700' }" confirm-color="rgb(255, 117, 129)">
<view class="" style="padding-top: 30rpx;text-align: left;">
<scroll-view scroll-y="true" style="max-height: 50vh;">
<!-- <rich-text style="color:#666" :nodes="datas.version.content"></rich-text> -->
<view style="text-align: justify;font-size: 18px;color: #666;" v-html="datas.version.content"></view>
</scroll-view>
</view>
</up-modal>
<!-- h5关闭通知 -->
<!-- #ifdef H5 -->
<up-modal :show="datas.stopShow"
cancel-text="知道了"
show-cancel-button
confirm-text="去下载" title="重要通知"
@cancel="stopCancel"
:title="datas.rule_title" :title-style="{fontWeight:'700'}" @confirm="stopConfirm"
confirm-color="rgb(255, 117, 129)">
<view class="color-red u-text-left">
<text>2025年2月8日将关闭网页访问请及时下载最新APP</text>
</view>
</up-modal>
<!-- #endif -->
</template>
<script setup>
import http from '@/http/http.js'
http.request({
url:'app/common/getAppUseKv'
}).then(res=>{
console.log(res);
import {
reactive,
nextTick
} from 'vue';
import {
announcement,
messageselectMessage,
courseselectCourse
} from '@/api/index/index.js'
import {
onLoad,
onReady,
onReachBottom,
onShow
} from '@dcloudio/uni-app'
import contentlist from './components/contentlist.vue'
import {
selectNewApp
} from '@/api/user/user.js';
import config from '@/commons/config.js';
import {
linkTo
} from '@/utils/app.js';
import {
useCommonStore
} from '@/store/common.js'
const $common = useCommonStore()
onShow(() => {
// console.log('cash:' + uni.getStorageSync('userInfo').userId + "" + new Date().getTime(), 'debug')
// ios
$common.init()
// #ifdef H5
datas.isExamine = $common.isIosExamine
// #endif
// let sysInfo = uni.getSystemInfoSync()
// let isIos = sysInfo.platform == 'ios'
// if (isIos) {
// datas.setindexdata = $common.setversion
// console.log(datas.setindexdata,'seaeasdas')
// }
})
let datas = reactive({
noticeList: [], //
active: 1, //
list: [], //
page: 1, //
stopShow:true,//h5
ruleShow: false,
rule_title: '', //
rule_content: '', //
ruleIndex: 0,
ruleList: [],
version: {
show: false,
title: "",
content: "",
confirmText: "",
cancelText: "",
downloadLink: ""
},
setindexdata: false
})
onLoad(() => {
versionUpdate()
getMsg()
getrecomVideo()
})
onReady(() => {
if (!uni.getStorageSync('ruleShow')) {
announcement({
type: 0
}).then(res => {
if (res) {
datas.ruleShow = true
datas.ruleList = res
ruleInit()
}
})
}
})
onReachBottom(() => {
++datas.page
getrecomVideo()
})
function stopConfirm(){
datas.stopShow=false
uni.navigateTo({
url:'/pages/login/download'
})
}
function stopCancel(){
datas.stopShow=false
}
function versionUpdate() {
//#ifdef APP-PLUS
plus.screen.lockOrientation('portrait-primary'); //
//
plus.runtime.getProperty(plus.runtime.appid, widgetInfo => {
//
selectNewApp().then(async res => {
res = res[0];
console.log(uni.getSystemInfoSync().platform == 'ios', 1101)
let version;
if (uni.getSystemInfoSync().platform == 'android') {
version = res.version
}
if (uni.getSystemInfoSync().platform == 'ios') {
version = res.iosVersion
}
let isVersion = await $common.setversion(widgetInfo.version, version)
datas.isExamine = $common.isIosExamine
console.log(isVersion, '')
if (isVersion == 1) {
datas.version.downloadLink = res.androidWgtUrl;
datas.version.show = true;
datas.version.title = "发现新版本";
datas.version.content = res.des;
uni.hideTabBar()
if (res.method == "true") {
datas.version.confirmText = "立即更新"
} else {
datas.version.confirmText = "立即更新"
datas.version.cancelText = "下次更新"
}
}
});
});
//#endif
}
function cancelUpdateVersion() {
uni.showTabBar()
datas.version.show = false
}
function confirmUpdateVersion() {
// plus.runtime.openURL(config.baseUrl + '/pages/login/appEq')
linkTo('/pages/login/download')
return
uni.showLoading({
title: '下载中...',
mask: true
});
if (uni.getSystemInfoSync().platform == 'android') {
uni.downloadFile({
url: datas.version.downloadLink,
success: downloadResult => {
console.log(downloadResult)
if (downloadResult.statusCode === 200) {
plus.runtime.install(
downloadResult.tempFilePath, {
force: false
},
d => {
console.log('install success...');
plus.runtime
.restart();
},
e => {
console.log(e)
console.error('install fail...');
}
);
}
}
});
}
if (uni.getSystemInfoSync().platform == 'ios') {
plus.runtime.openURL(datas.version.downloadLink, function(res) {});
}
}
function ruleInit() {
datas.rule_title = datas.ruleList[datas.ruleIndex].title
datas.rule_content = datas.ruleList[datas.ruleIndex].content
}
/**
* 规则确认
*/
function ruleConfirm() {
datas.ruleShow = false
datas.ruleIndex++
if (datas.ruleIndex >= datas.ruleList.length) {
datas.ruleIndex = 0
uni.setStorageSync('ruleShow', true)
return
}
setTimeout(res => {
ruleInit()
datas.ruleShow = true
}, 300)
}
//
function goMsg(url) {
uni.navigateTo({
url: '/pages/index/prizeDraw/kevy-luckydraw'
});
}
//
function moreVideo() {
uni.navigateTo({
url: '/pages/index/search/index'
});
}
//
async function getMsg() {
let res = await messageselectMessage()
datas.noticeList = res.list
}
//
async function getrecomVideo(sort, active = 1) {
datas.active = active
if (sort) {
datas.page = 1
}
let res = await courseselectCourse({
page: datas.page,
limit: 12,
sort: sort,
classifyId: ''
})
if (datas.page == 1) {
datas.list = res.list
} else {
datas.list = [...datas.list, ...res.list]
}
}
</script>
<style>
</style>
<style lang="scss" scoped>
.indexStyle {
height: 555rpx;
position: relative;
>image {
width: 100%;
height: 555rpx;
position: absolute;
}
.indexStyleTwo {
display: flex;
align-items: center;
justify-content: space-between;
padding: 88rpx 25rpx;
>image {
width: 187rpx;
height: 50rpx;
}
>view {
z-index: 50;
width: 236rpx;
line-height: 43rpx;
background: rgba(255, 255, 255, 0.29);
border-radius: 7rpx 7rpx 7rpx 7rpx;
font-weight: 400;
font-size: 21rpx;
color: rgba(255, 255, 255, 0.85);
display: flex;
align-items: center;
}
}
.gongao {
position: absolute;
bottom: 75rpx;
left: 70rpx;
border-radius: 21rpx 21rpx 21rpx 21rpx;
width: 611rpx;
height: 78rpx;
background-color: rgba(255, 255, 255, .65);
display: flex;
align-items: center;
padding: 12rpx;
box-sizing: border-box;
.gongaoicon {
color: #ffffff;
width: 98rpx;
height: 50rpx;
line-height: 50rpx;
text-align: center;
font-size: 25rpx;
background-image: url('../../static/index/gonggaobg.png');
background-size: 98rpx 50rpx;
}
.swiperstyle {
height: 78rpx;
width: 80%;
}
}
}
.navTop-active {
color: #cb5d68;
}
.navTop {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20rpx;
>view {
background-color: #f0f0f0;
margin-left: 20rpx;
padding: 6rpx 20rpx
}
}
</style>

View File

@ -0,0 +1,181 @@
<template>
<view class="gift-bg"></view>
<view class="list">
<view class="tab">
<view class="tab_item" :class="{ active: item.type == datas.tabIndex }" @click="tabClickczgw(item)"
v-for="(item, index) in datas.tab" :key="index">{{ item.label }}</view>
</view>
<view class="item" v-for="(item, index) in datas.list" :key="index">
<view class="color-666 u-font-24">{{datas.tabIndex==1?'中奖时间':'兑换时间'}} {{item.createTime}}</view>
<view class="u-m-t-24 u-flex u-row-between">
<view class="u-flex-1 u-flex u-col-top">
<u-image width="128rpx" height="128rpx" src="@/static/index/redPack.png"></u-image>
<view class="u-m-l-16">
<view v-if="datas.tabIndex == 1">{{item.name}}</view>
<view v-else>{{item.prizeName}}</view>
<view v-if="datas.tabIndex == 1" class="color-999 u-font-24 u-m-t-16">×{{item.number}}</view>
</view>
</view>
<view class="" v-if="datas.tabIndex==1&&!item.targetId&&item.type==3">
<view class="btn-circle duihuan" @click="toDuiHuan(item)">立即兑换</view>
</view>
</view>
</view>
<view class="empty" v-if="!datas.list.length">
<u-empty text="暂无记录" src="/static/icon-empty.svg"></u-empty>
</view>
</view>
</template>
<script setup>
import {
reactive
} from 'vue';
import {
onReachBottom,
onShow
} from '@dcloudio/uni-app'
import {
selectDiscSpinningRecord,
userPrizeExchange
} from '@/api/index/index.js'
let datas = reactive({
list: [],
tab: [{
label: '抽奖记录',
type: 1
},
{
label: '兑换记录',
type: 2
}
],
tabIndex: 1,
page: 1
})
onShow(() => {
getList();
})
onReachBottom(() => {
++datas.page
getList();
})
async function getList() {
let res = '';
if (datas.tabIndex == 1) {
res = await selectDiscSpinningRecord({
page: datas.page,
limit: 10,
source: 1
})
} else {
res = await userPrizeExchange({
page: datas.page,
limit: 10,
source: 1
})
}
if (datas.tabIndex == 1) {
if (datas.page == 1) {
datas.list = res.records;
} else {
if (res.records.length) {
datas.list.push(...datas.list, res.records)
}
}
} else {
if (datas.page == 1) {
datas.list = res.list;
} else {
if (res.records.length) {
datas.list.push(...datas.list, res.list)
}
}
// datas.total = res.page.totalCount;
}
}
function tabClickczgw(item) {
datas.list = [];
datas.tabIndex = item.type;
datas.page = 1
getList();
}
//
function toDuiHuan(item) {
uni.navigateTo({
url: `/pages/index/prizeDraw/duihuan?id=${item.id}`
})
}
</script>
<style lang="scss" scoped>
.gift-bg {
position: relative;
width: 100%;
height: 524rpx;
background: url('@/static/index/giftbg.png') no-repeat center center/cover;
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
.duihuan {
background: linear-gradient(87deg, #ed8087 0%, #eca2aa 100%);
font-size: 24rpx;
color: #fff;
padding: 8rpx 16rpx;
text-align: center;
&.finish {
background: #e5e5e5;
color: #999;
}
}
.empty {
margin-top: 140rpx;
}
.list {
margin: 0 20rpx;
position: relative;
z-index: 2;
margin-top: -148rpx;
border-radius: 18rpx 18rpx 18rpx 18rpx;
overflow: hidden;
background-color: #fff;
.tab {
display: flex;
.tab_item {
height: 80rpx;
line-height: 80rpx;
width: 50%;
text-align: center;
font-size: 32rpx;
color: #333;
}
.active {
background-color: #eca2aa;
color: #fff;
}
}
.item {
padding: 32rpx 24rpx;
border-bottom: 1rpx solid #e5e5e5;
}
}
</style>

View File

@ -0,0 +1,110 @@
<template>
<view class="min-page bg-gray u-font-28">
<view class="block bg-fff border-r-18 default-box-padding">
<view>
<view>中奖用户手机号</view>
<view class="border u-m-t-24 u-p-l-24" style="margin-bottom: 20rpx;">
<u-input v-model="datas.query.phone" type="number" maxlength="11"
placeholder="请输入中奖用户手机号"></u-input>
</view>
<view>收货地址</view>
<view class="border u-m-t-24 u-p-l-24" style="margin-bottom: 20rpx;">
<u-input v-model="datas.query.address" type="text" placeholder="请输入收货地址"></u-input>
</view>
<view>备注</view>
<view class="border u-m-t-24 u-p-l-24">
<u-input v-model="datas.query.remark" type="text" placeholder="请输入备注"></u-input>
</view>
</view>
<view class="u-m-t-48">
<view>兑换事项</view>
<view class="u-m-t-16 color-999">
请认真核实兑换账号一但兑换成功后不予退换
</view>
</view>
</view>
<view class="u-flex u-row-center">
<view class="btn-circle duihuan" @click="exchange">确认兑换</view>
</view>
</view>
</template>
<script setup>
import {
reactive
} from 'vue'
import {
onLoad
} from '@dcloudio/uni-app'
import {
userPrizeExchangeexchange
} from '@/api/index/index.js'
let datas = reactive({
query: {
foreignId: null,
foreignType: 'spinning',
phone: "",
address: "",
remark: "",
}
})
onLoad(options => {
if (options.id) {
datas.query.foreignId = options.id
}
if (options.foreignType) {
datas.query.foreignType = options.foreignType
}
})
async function exchange() {
let url = ""
if (!datas.query.phone) {
uni.showToast({
title: '请输入中奖用户手机号',
icon: 'none'
});
return;
}
if (!datas.query.address) {
uni.showToast({
title: '请输入中奖用户地址',
icon: 'none'
});
return;
}
let res = await userPrizeExchangeexchange(datas.query)
uni.showToast({
title: '兑换成功',
icon: 'none'
});
setTimeout(() => {
uni.navigateBack()
}, 1200)
}
</script>
<style lang="scss" scoped>
.border {
border: 1px solid #999999;
border-radius: 12rpx 12rpx 12rpx 12rpx;
}
.duihuan {
background: #ED838A;
width: 556rpx;
padding: 18rpx 0;
text-align: center;
font-size: 32rpx;
font-weight: bold;
color: #fff;
margin-top: 84rpx;
}
.min-page {
padding: 32rpx 20rpx;
}
</style>

View File

@ -0,0 +1,545 @@
<template>
<view class="content">
<view class="t-bg" style="">
<image class="t-wan" src="./luck/wenan.png"></image>
<image class="t-wan-lp" src="./luck/hengfu.png"></image>
<view class="t-choujiang t-flex-row">
<l-dialer :prizeList="list" @click="onClick" @done="onDone" ref="dialer" />
</view>
</view>
<!-- 规则部分 -->
<view class="t-bottom">
<view class="t-luck-wrapper">
<view class="t-jh t-flex-row">
剩余免费抽奖{{luckDrawTimes}}
</view>
<!-- <view class="t-fuhuo-text t-flex-row">{{freeNumDay}}</view> -->
<view class="t-fh-fs t-flex-row-sb">
<view class="t-flex-row" @tap='goUrl("/pages/me/withdraw/index")' hover-class="t-click-class">红包
&nbsp;{{totalMoney}}</view>
<button open-type="share" @tap='goUrl("/pages/index/prizeDraw/LotteryRecords")'
class="t-share t-flex-row t-plain-btn" hover-class="t-click-class">我的奖品</button>
</view>
<view class="t-line"></view>
<view class="t-r-title t-flex-row">活动规则</view>
<view class="t-rule">
<text>1.抽奖细则每日前{{ freeNumDay }}次付款均可获得抽奖机会</text>
<text>2.奖励说明红包奖励将自动发放到红包余额已绑定银行卡账号将会自动发起提现其余奖品则需联系客服领取</text>
</view>
</view>
</view>
<!-- 抽奖结束弹窗 -->
<kevy-mask :show="isShowAwd" @click="toConfirmAwd">
<view class="t-full t-flex-row">
<view class="t-tk-modal">
<view class="t-tk-bg t-bg-full">
<!-- <view v-if="drawIdx!=null && drawIdx == 0" class="t-xxcy t-flex-col-s">
<image src="./luck/xiexiecanyu.png"></image>
<view class="t-xxcy-ts t-flex-row">再努力努力肯定就会中哦~</view>
</view> -->
<view class="t-tk-zj t-flex-col-s">
<image class="t-tk-zj-tip" src="./luck/wenzi.png"></image>
<view class="t-tk-zj-desc t-flex-col">
<image class="t-zj-jp" :src="selectData.img" mode="aspectFit"></image>
<view class="t-zj-jp-desc">
{{selectData.name}}&nbsp;&nbsp;{{selectData.number}}
</view>
</view>
</view>
</view>
<view @click="toConfirmAwd" class="t-tk-btn t-bg-full">
确定
</view>
</view>
</view>
</kevy-mask>
</view>
</template>
<script>
import {
drawCount,
selectUserMoney,
selectDiscSpinning,
discSpinningdraw
} from '@/api/index/index.js';
var animation = uni.createAnimation({
duration: 4000,
timingFunction: 'ease-out'
});
import kevyMask from './kevy-mask.vue';
export default {
components: {
kevyMask,
},
data() {
return {
totalMoney: 0, //
rotate: 0, //-
turning: false, //
luckDrawTimes: 0, //55
isShowAwd: false, //
drawIdx: null, //5340
//
freeNumDay: 0,
list: [],
selectData: "",
source: 1
}
},
onLoad(opt) {
if (opt.source) {
this.source = opt.source
}
this.getRedPack();
this.getCount();
this.getPrizeList();
},
methods: {
goUrl(url) {
uni.navigateTo({
url
})
},
onDone(index) {
this.selectData.img = this.list[index].img
this.isShowAwd = true
},
async onClick() {
if (this.luckDrawTimes) {
const res = await discSpinningdraw({
source: this.source
});
let indexs = -1
this.list.forEach((ele, index) => {
if (ele.id == res.discSpinningId) {
indexs = index
this.selectData = res
}
})
//
this.$refs.dialer.run(indexs)
} else {
uni.showToast({
title: '暂无抽奖次数',
icon:'none'
})
}
},
//
async getCount() {
const res = await drawCount({
source: this.source
});
this.luckDrawTimes = res.count || 0;
this.freeNumDay = res.sum || 0;
},
//
async getRedPack() {
const res = await selectUserMoney();
this.totalMoney = res.amount;
},
//
async getPrizeList() {
const res = await selectDiscSpinning({
source: this.source
});
res.records.forEach(res => {
res.img = res.url
})
this.list = res.records
},
/**
* 确认奖品按钮点击事件
*/
toConfirmAwd() {
//
this.isShowAwd = false;
this.getRedPack();
this.getCount();
}
}
}
</script>
<style scoped>
.content {
width: 100%;
box-sizing: border-box;
}
.t-bg {
background-image: url('./luck/DZP_BJ.png');
width: 100%;
box-sizing: border-box;
background-size: 100% 100%;
background-repeat: no-repeat;
position: relative;
overflow-x: hidden;
height: 1200rpx;
padding-top: 345rpx;
/* margin-top: 40rpx; */
}
.t-overlay {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 9999;
background: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
transition: all 0.5s;
}
.t-wan {
position: absolute;
width: 100%;
height: 283rpx;
top: 12rpx;
left: 0;
z-index: 1;
}
.t-wan-lp {
position: absolute;
width: 370rpx;
height: 130rpx;
top: 223rpx;
z-index: 0;
left: calc(50% - 185rpx);
}
.t-choujiang {
width: 630rpx;
height: 630rpx;
background-size: 100% 100%;
background-repeat: no-repeat;
margin: 0rpx auto;
position: relative;
background-image: url('./luck/BJ.png')
}
.t-zp {
width: 577rpx;
height: 577rpx;
background-size: 100% 100%;
background-repeat: no-repeat;
transform-origin: 0% 100%;
}
.t-start {
width: 146rpx;
height: 171rpx;
position: absolute;
z-index: 1;
}
.t-jh {
width: 456rpx;
height: 120rpx;
margin: 0 auto;
background-size: 100% 100%;
background-repeat: no-repeat;
font-size: 40rpx;
color: #980100;
background-image: url('./luck/anniu.png')
}
.t-fuhuo-text {
font-size: 30rpx;
color: #980100;
width: 100%;
height: 42rpx;
margin-top: 14rpx;
}
.t-fh-fs {
width: 580rpx;
height: 100rpx;
margin: 20rpx auto 0rpx;
}
.t-fh-fs view {
width: 250rpx;
height: 100rpx;
background-image: linear-gradient(180deg, #DF0236 0%, #DD0227 100%);
border-radius: 10rpx;
font-size: 30rpx;
color: #FFFFFF;
}
.t-share {
width: 250rpx;
height: 100rpx;
background-image: linear-gradient(180deg, #DF0236 0%, #DD0227 100%);
border-radius: 10rpx;
font-size: 30rpx;
color: #FFFFFF;
}
.t-bottom {
position: relative;
width: 100%;
box-sizing: border-box;
opacity: 0.99;
background: #FDC469;
}
.t-luck-wrapper {
position: relative;
box-sizing: border-box;
top: -219rpx;
}
.t-line {
width: 580rpx;
height: 1rpx;
margin: 50rpx auto 0rpx;
background: #980100;
}
.t-r-title {
font-size: 28rpx;
color: #980100;
height: 40rpx;
width: 100%;
margin: 30rpx auto 0rpx;
width: 585rpx;
}
.t-rule {
margin: 10rpx auto 0rpx;
width: 585rpx;
}
.t-rule text {
font-size: 28rpx;
color: #980100;
text-align: justify;
display: block;
}
.t-wrapper {
width: 100%;
height: 100%;
position: relative;
top: 0rpx;
}
.t-video-con {
width: 100%;
height: 422rpx;
background: #fff;
position: relative;
}
.t-video {
width: 100%;
height: 100%;
}
.t-close {
position: absolute;
top: 0rpx;
right: 0rpx;
width: 34rpx;
height: 34rpx;
padding: 30rpx;
z-index: 9999;
}
.t-nocice {
position: fixed;
left: 0rpx;
top: 0rpx;
z-index: 999;
width: 100%;
height: 40rpx !important;
box-sizing: border-box;
font-size: 30rpx;
}
.t-tk-modal {
width: 632rpx;
height: 588rpx;
position: relative;
box-sizing: border-box;
}
.t-tk-bg {
width: 100%;
height: 528rpx;
background-size: 100% 100%;
background-image: url('./luck/tankuang.png')
}
.t-tk-btn {
width: 336rpx;
height: 120rpx;
position: absolute;
bottom: 0rpx;
left: calc(50% - 168rpx);
font-size: 40rpx;
color: #980100;
line-height: 120rpx;
text-align: center;
background-size: 100% 100%;
background-image: url('./luck/xiaoanniu.png')
}
.t-flex-row {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.t-flex-row-sa {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
}
.t-flex-row-sb {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.t-flex-row-s {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.t-flex-row-s-s {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
}
.t-flex-row-s-e {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-end;
}
.t-flex-row-e {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
line-height: 60rpx;
}
.t-flex-col {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.t-flex-col-sa {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
.t-flex-col-sb {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.t-flex-col-s {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
.t-flex-col-s-s {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
}
.t-flex-col-s-e {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-end;
}
.t-flex-col-e {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
}
.t-xxcy image {
width: 400rpx;
height: 148rpx;
margin-top: 139rpx;
}
.t-xxcy-ts {
width: 510rpx;
height: 100rpx;
background: #FEF2CD;
border-radius: 20rpx;
font-size: 30rpx;
color: #D93637;
margin-top: 43rpx;
}
.t-tk-zj {}
.t-tk-zj-tip {
width: 347rpx;
height: 106rpx;
margin-top: 44rpx;
}
.t-tk-zj-desc {
width: 474rpx;
height: 281rpx;
background: #FEF2CD;
border-radius: 20rpx;
margin-top: 2rpx;
}
.t-zj-jp {
width: 264rpx;
height: 157rpx;
}
.t-zj-jp-desc {
font-size: 36rpx;
color: #D93637;
text-align: center;
width: 420rpx;
}
.t-click-class {
opacity: 0.7;
}
</style>

View File

@ -0,0 +1,355 @@
<template>
<view class="content">
<view class="t-mask"
:style="{opacity:show?'1':'0','z-index':zIndex,'left':show?'0rpx':'200%','transition-duration':duration?(duration+'s'):'0.3s'}"
@click.stop="maskClick" @mousemove.stop>
<view :class="['t-wrap',aniType,{'show':show}]">
<view :style="[contentStyle]" @click.stop>
<slot></slot>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "KevyMask",
props: {
/**
* 是否显示
*/
show: {
type: Boolean,
default: false
},
/**
* 是否开启点击遮罩关闭
*/
maskClose: {
type: Boolean,
default: true
},
/**
* 层级
*/
zIndex: {
type: Number,
default: 10
},
/**
* 动画时长单位秒
*/
duration: {
type: [String, Number],
default: 0.3
},
/**
* 嵌入内容css类名
*/
contentStyle: {
type: Object,
default: () => {}
},
/**
* 动画类型13fadeInAndScaleUpslideFromRightslideFromBottomnewspaperfallsideAndFallflipH3dflipV3dsign3dsuperScaleslit3drotateFromBottom3drotateFromLeft3d
*/
aniType: {
type: String,
default: 'fadeInAndScaleUp'
},
},
data() {
return {
isRm:false
}
},
created() {
},
methods: {
//
maskClick() {
if (this.maskClose) {
this.$emit("click");
}
}
}
}
</script>
<style lang="scss" scoped>
.content {
width: 100%;
box-sizing: border-box;
height: 0rpx;
overflow: hidden;
.t-mask {
position: fixed;
top: 0rpx;
left: 0rpx;
background: rgba(0, 0, 0, 0.6);
margin: 0rpx;
padding: 0rpx;
transition-property: opacity;
transition-timing-function: ease-in;
-webkit-perspective: 1300rpx;
perspective: 1300rpx;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
.t-wrap {
min-width: 100vw;
min-height: 100vh;
overflow: hidden;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
//fadeInAndScaleUp
&.fadeInAndScaleUp {
-webkit-transform: scale(0.7);
transform: scale(0.7);
opacity: 0;
-webkit-transition: all 0.3s;
transition: all 0.3s;
&.show {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1;
}
}
//slideFromRight
&.slideFromRight {
-webkit-transform: translateX(20%);
transform: translateX(20%);
opacity: 0;
-webkit-transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
&.show {
-webkit-transform: translateX(0);
transform: translateX(0);
opacity: 1;
}
}
//slideFromBottom
&.slideFromBottom {
-webkit-transform: translateY(20%);
transform: translateY(20%);
opacity: 0;
-webkit-transition: all 0.3s;
transition: all 0.3s;
&.show {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
}
//newspaper
&.newspaper {
-webkit-transform: scale(0) rotate(720deg);
transform: scale(0) rotate(720deg);
opacity: 0;
-webkit-transition: all 0.5s;
transition: all 0.5s;
&.show {
-webkit-transform: scale(1) rotate(0deg);
transform: scale(1) rotate(0deg);
opacity: 1;
}
}
//fall
&.fall {
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: translateZ(600px) rotateX(20deg);
transform: translateZ(600px) rotateX(20deg);
opacity: 0;
&.show {
-webkit-transition: all 0.3s ease-in;
transition: all 0.3s ease-in;
-webkit-transform: translateZ(0px) rotateX(0deg);
transform: translateZ(0px) rotateX(0deg);
opacity: 1;
}
}
//sideAndFall
&.sideAndFall {
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: translate(30%) translateZ(600px) rotate(10deg);
transform: translate(30%) translateZ(600px) rotate(10deg);
opacity: 0;
&.show {
-webkit-transition: all 0.3s ease-in;
transition: all 0.3s ease-in;
-webkit-transform: translate(0%) translateZ(0) rotate(0deg);
transform: translate(0%) translateZ(0) rotate(0deg);
opacity: 1;
}
}
//flipH3d
&.flipH3d {
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: rotateY(-70deg);
transform: rotateY(-70deg);
-webkit-transition: all 0.3s;
transition: all 0.3s;
opacity: 0;
&.show {
-webkit-transform: rotateY(0deg);
transform: rotateY(0deg);
opacity: 1;
}
}
//flipV3d
&.flipV3d {
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: rotateX(-70deg);
transform: rotateX(-70deg);
-webkit-transition: all 0.3s;
transition: all 0.3s;
opacity: 0;
&.show {
-webkit-transform: rotateX(0deg);
transform: rotateX(0deg);
opacity: 1;
}
}
//sign3d
&.sign3d {
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: rotateX(-60deg);
transform: rotateX(-60deg);
-webkit-transform-origin: 50% 0;
transform-origin: 50% 0;
opacity: 0;
-webkit-transition: all 0.3s;
transition: all 0.3s;
&.show {
-webkit-transform: rotateX(0deg);
transform: rotateX(0deg);
opacity: 1;
}
}
//superScale
&.superScale {
-webkit-transform: scale(2);
transform: scale(2);
opacity: 0;
-webkit-transition: all 0.3s;
transition: all 0.3s;
&.show {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1;
}
}
//slit3d
&.slit3d {
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: translateZ(-3000px) rotateY(90deg);
transform: translateZ(-3000px) rotateY(90deg);
opacity: 0;
&.show {
-webkit-animation: slit .7s forwards ease-out;
animation: slit .7s forwards ease-out;
}
}
@-webkit-keyframes slit {
50% {
-webkit-transform: translateZ(-250px) rotateY(89deg);
opacity: .5;
-webkit-animation-timing-function: ease-out;
}
100% {
-webkit-transform: translateZ(0) rotateY(0deg);
opacity: 1;
}
}
@keyframes slit {
50% {
transform: translateZ(-250px) rotateY(89deg);
opacity: 1;
animation-timing-function: ease-in;
}
100% {
transform: translateZ(0) rotateY(0deg);
opacity: 1;
}
}
//rotateFromBottom3d
&.rotateFromBottom3d {
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: translateY(100%) rotateX(90deg);
transform: translateY(100%) rotateX(90deg);
-webkit-transform-origin: 0 100%;
transform-origin: 0 100%;
opacity: 0;
-webkit-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
&.show {
-webkit-transform: translateY(0%) rotateX(0deg);
transform: translateY(0%) rotateX(0deg);
opacity: 1;
}
}
//rotateFromLeft3d
&.rotateFromLeft3d {
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: translateZ(100px) translateX(-30%) rotateY(90deg);
transform: translateZ(100px) translateX(-30%) rotateY(90deg);
-webkit-transform-origin: 0 100%;
transform-origin: 0 100%;
opacity: 0;
-webkit-transition: all 0.3s;
transition: all 0.3s;
&.show {
-webkit-transform: translateZ(0px) translateX(0%) rotateY(0deg);
transform: translateZ(0px) translateX(0%) rotateY(0deg);
opacity: 1;
}
}
}
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,174 @@
<template>
<view>
<u-sticky :enable="true">
<view class="search-box">
<u-search bg-color="#f2f2f2" style="width: 100%;" placeholder="搜索更多资源" :show-action="true"
:animation="true" action-text="取消" v-model="datas.keyword" @custom="goBack()"
@search="doSearch()"></u-search>
</view>
</u-sticky>
</view>
<view class="search-keyword" v-if="datas.isSearch">
<view class="keyword-block" v-if="datas.hotKeywordList.length != 0">
<view class="keyword-list-header">
<view>热搜</view>
</view>
<view class="keyword">
<view v-for="(keyword, index) in datas.hotKeywordList" @tap="doSearchs(keyword)" :key="index">
{{ keyword }}
</view>
</view>
</view>
</view>
<view class="search-list" v-else>
<view class="search-list-box">
<videoList @success="posterSuccess" :list="datas.keywordList" />
</view>
</view>
<view style="display: flex;flex-direction: column;align-items: center;" v-if="!datas.isSearch&&datas.keywordList.length==0">
<image src="/static/index/none.png" style="width: 341rpx;height: 341rpx;" mode=""></image>
<text style=";">暂无数据</text>
</view>
</template>
<script setup>
import {
selectCourseTitles
} from '@/api/index/index.js'
import videoList from './videoList.vue'
import {
reactive
} from 'vue';
import {
onShow,
onReachBottom
} from '@dcloudio/uni-app'
let datas = reactive({
hotKeywordList: [], //
keywordList: [], //
keyword: "", //
page: 1,
isSearch: true,
})
onShow(() => {
getList()
})
function posterSuccess() {
}
function getList() {
if (uni.getStorageSync('moreSearch')) {
datas.hotKeywordList = (uni.getStorageSync('moreSearch')).split(',')
} else {
datas.hotKeywordList = []
}
}
onReachBottom(() => {
++datas.page
doSearch()
})
function doSearchs(keyWord) {
datas.keyword = keyWord
doSearch()
}
//
async function doSearch() {
datas.isSearch = false
let res = await selectCourseTitles({
title: datas.keyword,
limit: 20,
page: datas.page,
})
if (datas.page == 1) {
datas.keywordList = res.list
} else {
datas.keywordList = [...datas.keywordList, ...res.list]
}
}
//
function goBack() {
uni.navigateBack()
}
</script>
<style scoped lang="scss">
.search-box {
width: 100%;
/* background-color: rgb(242, 242, 242); */
padding: 15upx 2.5%;
display: flex;
justify-content: space-between;
// position: sticky;
// top: 0;
background-color: #ffffff;
}
.search-keyword {
width: 100%;
}
.keyword-block {
padding: 10rpx 0;
}
.keyword {
width: 94%;
padding: 3px 3%;
display: flex;
flex-flow: wrap;
justify-content: flex-start;
>view {
display: flex;
justify-content: center;
align-items: center;
border-radius: 60upx;
padding: 0 20upx;
margin: 10upx 20upx 10upx 0;
height: 60upx;
font-size: 28upx;
// background-color: rgb(242, 242, 242);
background: #E6EBFF;
color: #6b6b6b;
}
}
.keyword-block .keyword-list-header {
width: 94%;
padding: 10rpx 3%;
font-size: 27rpx;
color: #333;
display: flex;
justify-content: space-between;
}
.keyword-block .keyword-list-header image {
width: 40rpx;
height: 40rpx;
}
.search-list {
width: 100%;
margin-top: 20rpx;
display: flex;
align-items: center;
justify-content: center;
.search-list-box {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
width: 686rpx;
height: 100%;
}
}
</style>

View File

@ -0,0 +1,227 @@
<!-- 瀑布流 -->
<template>
<view class="list ">
<view class="list-box ">
<!-- 左边数据 -->
<view class="list-box-ite">
<view @click="clickItem(item)" class="list-box-ite-item" v-for="(item, index) in datas.arrListLeft"
:key="index">
<view class="list-box-ite-item-img">
<u-lazy-load border-radius="24rpx 24rpx 0 0" :image="item.titleImg"></u-lazy-load>
<view class="list-box-ite-item-img-t" v-if="item.over == 1">
{{ item.courseDetailsCount ? item.courseDetailsCount : 0 }}
</view>
<view class="list-box-ite-item-img-t" v-else>
更新至{{ item.courseDetailsCount ? item.courseDetailsCount : 0 }}
</view>
</view>
<view class="list-box-ite-item-txt">
<view class="list-box-ite-item-txt-t">
{{ item.title }}
</view>
<view class="list-box-ite-item-txt-l" v-if="item.courseLabel">
{{ item.courseLabel }}
</view>
</view>
</view>
</view>
<!-- 右边数据 -->
<view class="list-box-ite">
<view @click="clickItem(item)" class="list-box-ite-item" v-for="(item, index) in datas.arrListRight"
:key="index">
<view class="list-box-ite-item-img">
<u-lazy-load border-radius="24rpx 24rpx 0 0" :image="item.titleImg"></u-lazy-load>
<view class="list-box-ite-item-img-t" v-if="item.over == 1">
{{ item.courseDetailsCount ? item.courseDetailsCount : 0 }}
</view>
<view class="list-box-ite-item-img-t" v-else>
更新至{{ item.courseDetailsCount ? item.courseDetailsCount : 0 }}
</view>
</view>
<view class="list-box-ite-item-txt">
<view class="list-box-ite-item-txt-t">
{{ item.title }}
</view>
<view class="list-box-ite-item-txt-l" v-if="item.courseLabel">
{{ item.courseLabel }}
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import {
reactive,
watch
} from "vue";
import {
onShow,
onReachBottom
} from '@dcloudio/uni-app'
const props = defineProps({
list: {
type: Array,
default: []
},
})
let datas = reactive({
arrListLeft: [], //
arrListRight: [], //
})
onShow(() => {
spliceArrayListr()
})
watch(() => props.list, () => {
spliceArrayListr()
})
function clickItem(item) {
uni.navigateTo({
url: "/pages/video/detail?courseId=" + item.courseId + "&courseDetailsId=" + item.courseDetailsId
})
}
function spliceArrayListr() {
datas.arrListRight = []
datas.arrListLeft = []
props.list.map((item, index) => {
if (index % 2 === 0) {
datas.arrListLeft.push(item)
} else {
datas.arrListRight.push(item)
}
})
}
</script>
<style lang="scss">
.list {
width: 100%;
height: auto;
display: flex;
align-items: center;
justify-content: center;
.list-box {
width: 686rpx;
height: 100%;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.list-box-ite {
width: calc((100% - 20rpx) / 2);
height: auto;
}
.list-box-ite-item {
width: 100%;
height: auto;
margin-bottom: 20rpx;
.list-box-ite-item-img {
width: 100%;
border-radius: 24rpx 24rpx 0 0;
min-height: 300rpx;
position: relative;
image {
width: 100%;
min-height: 300rpx;
border-radius: 24rpx 24rpx 0 0;
}
.list-box-ite-item-img-t {
position: absolute;
bottom: 10rpx;
right: 0;
max-width: 80%;
border-radius: 10rpx;
background-color: rgba(51, 51, 51, 0.7);
color: #FFFFFF;
font-size: 22rpx;
padding: 10rpx;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.list-box-ite-item-txt {
padding: 10rpx 20rpx;
background-color: #ffffff;
border-radius: 0 0 24rpx 24rpx;
}
.list-box-ite-item-txt-t {
color: #333333;
font-size: 30rpx;
font-weight: bold;
}
.list-box-ite-item-txt-l {
color: #999999;
font-size: 22rpx;
margin-top: 10rpx;
}
}
.list-box-item {
width: calc((100% - 20rpx) / 2);
// height: 100%;
min-height: 320rpx;
border-radius: 24rpx;
background-color: #ffffff;
margin-bottom: 20rpx;
}
.list-box-item-img {
width: 100%;
height: 200rpx;
border-radius: 24rpx 24rpx 0 0;
image {
width: 100%;
height: 200rpx;
border-radius: 24rpx 24rpx 0 0;
}
}
.list-box-item-txt {
width: 100%;
// height: 120rpx;
padding: 20rpx 0;
border-radius: 0 0 24rpx 24rpx;
}
.list-box-item-txt-t {
width: 100%;
padding: 0 20rpx;
color: #333333;
font-size: 30rpx;
font-weight: bold;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.list-box-item-txt-l {
color: #999999;
font-size: 22rpx;
margin-top: 10rpx;
padding: 0 20rpx;
}
}
</style>

200
pages/login/bind.vue Normal file
View File

@ -0,0 +1,200 @@
<template>
<view class="container">
<view class="cu-form-group" >
<view class="title">手机号</view>
<input type="number" :value="data.mobile" placeholder="请输入手机号" maxlength="11" data-key="mobile"
@input="inputChange" />
</view>
<view class="cu-form-group" >
<text class="title">验证码</text>
<input type="number" :value="data.code" placeholder="请输入验证码" maxlength="6" data-key="code" @input="inputChange"
@confirm="toLogin" />
<button class="send-msg" @click="sendMsg" :disabled="data.sendIng">{{ data.sendTime }}</button>
</view>
<button class="confirm-btn" @click="toLogin">立即绑定</button>
</view>
</template>
<script setup>
import { reactive } from 'vue';
import { onLoad} from '@dcloudio/uni-app'
import { setSendMsg, bind} from '@/api/login/login.js';
import { updatePhone } from '@/api/user/user.js';
let data = reactive({
mobile: '',
code: '',
loginIng: false,
sendIng: false,
sendTime: '获取验证码',
count: 60,
type: '',
})
onLoad((option) => {
if (option.type) {
data.type = option.type
}
})
function inputChange(e) {
const key = e.currentTarget.dataset.key;
data[key] = e.detail.value;
}
function countDown() {
const {
count
} = data;
if (count === 1) {
data.count = 60;
data.sendIng = false;
data.sendTime = '获取验证码'
} else {
data.count = count - 1;
data.sendIng = true;
data.sendTime = count - 1 + '秒后重新获取';
setTimeout(countDown.bind(this), 1000);
}
}
async function sendMsg() {
const { mobile } = data;
if (!data.mobile) {
uni.showToast({ title: '请输入手机号', icon: 'none', })
} else if (mobile.length !== 11) {
uni.showToast({ title: '请输入正确的手机号', icon: 'none', })
} else {
uni.showLoading({
title: '正在发送验证码...'
})
let res = await setSendMsg(data.mobile,'gzg')
uni.hideLoading();
console.log(res)
if (res.code == 0) {
data.sendIng = true;
uni.showToast({ title: '验证码发送成功请注意查收', icon: 'none', })
countDown();
} else {
uni.showModal({
showCancel: false,
title: '短信发送失败',
content: res.msg ? res.msg : '请一分钟后再获取验证码'
});
}
}
}
async function toLogin() {
const {
mobile,
code
} = data;
if (!data.mobile) {
uni.showToast({ title: '请输入手机号', icon: 'none', })
} else if (data.mobile.length !== 11) {
uni.showToast({ title: '请输入正确的手机号', icon: 'none', })
} else if (!data.code) {
uni.showToast({ title: '请输入验证码', icon: 'none', })
} else {
uni.showLoading({ title: '正在绑定中...' })
let res = await updatePhone({
phone: mobile,
// wxId: openId,
// userId: userId,
// inviterCode: invitation,
// avatar: openidheadimgurl,
// userName: openidnickname,
msg: code
})
uni.hideLoading();
uni.setStorageSync('token', res.token)
uni.setStorageSync('userInfo', res.user)
uni.showToast({ title: '绑定成功', icon: 'none', })
setTimeout(function() {
uni.navigateBack()
}, 1000)
}
}
</script>
<style lang='scss' scoped>
page {
background: #ffffff;
}
.container {
padding-top: 32rpx;
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
background: #ffffff;
}
.cu-form-group{
background-color: #ffffff;
padding: 1rpx 30rpx;
display: flex;
align-items: center;
min-height: 80rpx;
justify-content: space-between;
margin: 30rpx;
border: 2rpx solid whitesmoke;
margin-bottom: 40rpx;
border-radius: 60rpx
}
.title{
text-align: justify;
padding-right: 30rpx;
font-size: 30rpx;
position: relative;
height: 60rpx;
line-height: 60rpx;
flex-shrink: 0;
}
uni-input{
flex: 1;
font-size: 15px;
color: #555;
padding-right: 10px;
}
.send-msg {
border-radius: 30px;
color: white;
height: 30px;
font-size: 14px;
line-height: 30px;
background: #ff7581;
padding: 0 30rpx;
border: none;
&:after {
border: none;
}
}
.confirm-btn {
width: 300px;
height: 42px;
line-height: 42px;
border-radius: 30px;
margin-top: 70px;
background: #ff7581;
color: #ffffff;
font-size: 16px;
margin: 0 auto;
&:after {
border: none;
}
}
</style>

113
pages/login/download.vue Normal file
View File

@ -0,0 +1,113 @@
<template>
<view class="containers">
<div class="bg" style="background: url('/static/download/appeq_bg.png') no-repeat center bottom / cover;"></div>
<view class="content">
<image class="logo" src="/static/download/appLogo.png"></image>
<view style="font-size: 40rpx;margin-top: 22rpx;color: #FFFFFF;font-weight: bold;">{{data.confirmBtn}}</view>
<view style="font-size: 28rpx;margin-top: 16rpx;color: #FFFFFF;font-weight: bold;">海量电子榨菜 免费又过瘾</view>
<button class="confirm-btn" @click="download">点击下载{{data.confirmBtn}}</button>
</view>
<!-- #ifdef H5 -->
<div v-if="data.isWeixin" style="width: 100%;height: 100%;position: absolute;top: 0;background: url('/static/download/open_guide.png') no-repeat center bottom / cover;"></div>
<!-- #endif -->
</view>
</template>
<script setup>
import { reactive } from 'vue';
import { onLoad} from '@dcloudio/uni-app'
import { commonType } from '@/api/init.js';
let data = reactive({
openShare: false,
openShares: false,
confirmBtn: '斯耀短剧APP',
isWeixin: false,
})
onLoad(() => {
// #ifdef H5
let u = window.navigator.userAgent;
if ( uni.getSystemInfoSync().platform == 'ios') {
data.confirmBtn = "顺享短剧APP"
}
if ( u.toLowerCase().indexOf('micromessenger') !== -1) {
data.isWeixin = true
}
// #endif
})
function download() {
console.log(uni.getSystemInfoSync().platform == 'android')
if (uni.getSystemInfoSync().platform == 'android') {
commonType(49).then(res => {
if (res && res.value) {
// #ifndef H5
plus.runtime.openURL(res.value, function(res) {});
// #endif
// #ifdef H5
window.location.href = res.value;
// #endif
}
});
} else {
// #ifndef H5
plus.runtime.openURL('https://apps.apple.com/cn/app/%E9%A1%BA%E4%BA%AB%E7%9F%AD%E5%89%A7/id6740074541', function(res) {});
// #endif
// #ifdef H5
window.location.href = 'https://apps.apple.com/cn/app/%E9%A1%BA%E4%BA%AB%E7%9F%AD%E5%89%A7/id6740074541';
// #endif
}
}
</script>
<style lang="scss" scoped>
uni-page-body{
width: 100%;
height: 100%;
}
.containers {
width: 100%;
height: 100%;
.bg{
width: 100%;
height: 85%;
position: absolute;
}
.content{
position: relative;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.logo{
width: 124rpx;
height: 124rpx;
margin-top: -920rpx;
border-radius: 20rpx;
}
}
}
.confirm-btn {
width: 416rpx;
height: 90rpx;
line-height: 90rpx;
background: #FD5775;
color: #fff;
font-size: 32rpx;
font-weight: bold;
font-size: 32rpx;
color: #FFFFFF;
position: absolute;
left: 0;
right: 0;
bottom: 70rpx;
margin: auto;
}
</style>

295
pages/login/forgetPwd.vue Normal file
View File

@ -0,0 +1,295 @@
<template>
<view class="container">
<view class="bg" >
<image src="../../static/default/i_bg.png" style="width: 100%;height:100%" mode="aspectFill"></image>
</view>
<view class="wrapper u-relative" style="padding-top: 48rpx;box-sizing: border-box;">
<view class="nav" style="width: 100%;height: 96rpx;"></view>
<view class="input-content">
<view style="font-size: 58rpx;font-weight: bold;color: #333;margin-bottom: 48rpx;">重置密码</view>
<view class="cu-form-group">
<view class="title">手机号</view>
<view class="input" style="padding-left: 20rpx;">
<input class="input" type="number" :value="data.mobile" placeholder="请输入手机号" maxlength="11" data-key="mobile"
@input="inputChange" />
</view>
</view>
<view class="cu-form-group">
<text class="title">验证码</text>
<view class="input flex" style="padding-left: 20rpx;padding-right: 20rpx;">
<input type="number" :value="data.code" placeholder="请输入验证码" maxlength="6" data-key="code"
@input="inputChange" @confirm="reset" />
<button class="send-msg" @click="sendMsg" :disabled="data.sending">{{ data.sendTime }}</button>
</view>
</view>
<view class="cu-form-group">
<text class="title">设置密码</text>
<view class="input" style="padding-left: 20rpx;">
<input class="input" type="password" :value="data.password" placeholder="请设置新密码" placeholder-class="input-empty"
maxlength="20" minlength="6" data-key="password" @input="inputChange" @confirm="reset" />
</view>
</view>
<button class="confirm-btn" @click="reset">立即重置</button>
</view>
</view>
</view>
</template>
<script setup>
import { reactive } from 'vue';
import { onLoad} from '@dcloudio/uni-app'
import {setSendMsg,forgetPwd} from '@/api/login/login.js';
let data = reactive({
code: '',
mobile: '',
password: '',
sending: false,
sendTime: '获取验证码',
count: 60,
})
/**
* 发送验证码
*/
async function sendMsg() {
if (!data.mobile) {
uni.showToast({
title: '请输入手机号',
icon: 'none',
duration: 1000
})
} else if (data.mobile.length !== 11) {
uni.showToast({
title: '请输入正确的手机号',
icon: 'none',
duration: 1000
})
} else {
uni.showLoading({
title: '正在发送验证码...'
})
let res = await setSendMsg(data.mobile,'forget')
uni.hideLoading();
uni.hideToast();
if( res ){
data.sending = true;
uni.showToast({
title: '验证码发送成功请注意查收',
icon: 'none',
})
countDown();
} else {
uni.showModal({
showCancel: false,
title: '短信发送失败',
content: '请一分钟后再获取验证码'
});
}
}
}
/**
* 验证码倒计时
*/
function countDown() {
if (data.count === 1) {
data.count = 60;
data.sending = false;
data.sendTime = '获取验证码';
} else {
data.count = data.count - 1;
data.sending = true;
data.sendTime = data.count - 1 + '秒后重新获取';
setTimeout(countDown.bind(this), 1000);
}
}
/**
* 获取手机号/验证码/密码
* @param {Object} e
*/
function inputChange(e) {
const key = e.currentTarget.dataset.key;
data[key] = e.detail.value;
}
/**
* 注册
*/
async function reset() {
if (!data.mobile) {
uni.showToast({
title: '请输入手机号',
icon: 'none',
duration: 1000
})
} else if (!data.code) {
uni.showToast({
title: '请输入验证码',
icon: 'none',
duration: 1000
})
} else if (!data.password) {
uni.showToast({
title: '请输入密码',
icon: 'none',
duration: 1000
})
} else {
data.loginIng = true;
uni.showLoading({
title: '正在修改密码中...'
})
let res = await forgetPwd({
pwd: data.password,
phone: data.mobile,
msg: data.code,
})
uni.hideLoading();
uni.showToast({
title: '密码找回成功',
icon: 'none'
});
setTimeout(function() {
uni.navigateTo({
url: '/pages/login/login'
});
}, 1000)
}
}
</script>
<style lang="scss" >
page {
background: #ffffff;
}
*{
box-sizing: border-box;
}
.bg{
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
top: 0;
}
.wrapper{
position: relative;
padding-top: 48rpx;
box-sizing: border-box;
}
.footerView {
display: flex;
justify-content: center;
align-items: center;
font-weight: 400;
font-size: 24rpx;
color: #333333;
// position: absolute;
// left: 0;
// right: 0;
// bottom: 78rpx;
}
.cuIcon::before{
width: 30rpx;
height: 30rpx;
margin-right: 12rpx;
}
.cuIcon-round::before {
content: "\e6d7";
}
.cuIcon-radiobox:before {
content: "\e75b";
color: #37A6FF;
}
.send-msg {
line-height: initial;
font-weight: 400;
font-size: 28rpx;
color: #EC6F48;
border: none;
background-color: transparent;
margin: 0;
padding: 0;
}
.send-msg::after{
border: none;
background-color: transparent;
}
.container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
background: #ffffff;
box-sizing: border-box;
}
.wrapper {
min-height: 100vh;
position: relative;
z-index: 90;
}
.input-content {
padding: 0 56rpx;
}
.cu-form-group{
display: flex;
flex-direction: column;
align-items: flex-start;
margin-bottom: 48rpx;
background-color: transparent;
padding: 0;
.title{
margin-bottom: 32rpx;
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
.input{
width: 100%;
// height: 84rpx;
// line-height: 84rpx;
background-color: #fff;
align-items: center;
// padding: 22rpx 32rpx 22rpx 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
input{
height: 84rpx!important;
}
v-deep .uni-input-input{
height: 84rpx!important;
}
}
}
.confirm-btn {
width: 100%;
height: 100rpx;
text-align: center;
line-height: 100rpx;
border-radius: 16rpx;
margin-top: 40rpx;
background: #EC6F48;
font-size: 32rpx;
color: #FFFFFF;
&:after {
border: none;
}
}
</style>

259
pages/login/login.vue Normal file
View File

@ -0,0 +1,259 @@
<template>
<view class="container">
<view class="bg" >
<image src="../../static/default/i_bg.png" style="width: 100%;height:100%" mode="aspectFill"></image>
</view>
<view class="wrapper">
<view class="nav" style="width: 100%;height: 96rpx;"></view>
<view class="input-content">
<view style="font-size: 58rpx;font-weight: bold;color: #333;margin-bottom: 48rpx;">登录</view>
<view class="cu-form-group">
<view class="title">手机号</view>
<view class="input" style="padding-left: 20rpx;">
<input class="input" type="number" :value="data.mobile" placeholder="请输入手机号" maxlength="11" data-key="mobile"
@input="inputChange" />
</view>
</view>
<view class="cu-form-group">
<text class="title">密码</text>
<view class="input flex" style="padding-left: 20rpx;padding-right: 20rpx;">
<input class="input" type="password" :value="data.password" placeholder="请输入密码" placeholder-class="input-empty"
maxlength="20" minlength="6" data-key="password" @input="inputChange" @confirm="toLogin" />
<text class="send-msg" @click="linkTo('/pages/login/forgetPwd')" style="flex-shrink: 0;">忘记密码</text>
</view>
</view>
<button class="confirm-btn" @click="toLogin">登录</button>
<view style="margin-top: 32px;text-align: center">
<view>
没有账号
<text style="color: #ff7581" @click="linkTo('/pages/login/register')">立即注册</text>
</view>
</view>
</view>
<view class="footerView">
<u-checkbox-group>
<u-checkbox v-model="data.checked" label-size='24upx' shape="circle" @change="radioChange"></u-checkbox>
</u-checkbox-group>
<view>同意</view>
<!-- 协议地址 -->
<view @click="linkTo('/pages/me/privacy')">隐私政策</view>
<view @click="linkTo('/pages/me/agreement')">用户服务协议</view>
</view>
<u-toast ref="uToast" />
</view>
</view>
</template>
<script setup>
import { reactive } from 'vue';
import { onLoad} from '@dcloudio/uni-app'
import { login } from '@/api/login/login.js';
import { linkTo } from '@/utils/app.js';
let data = reactive({
mobile: '',
password: '',
checked: false
})
onLoad(() => {
})
/**
* 获取手机号/密码
*/
function inputChange (e) {
const key = e.currentTarget.dataset.key;
data[key] = e.detail.value;
}
/**
* 同意协议
*/
function radioChange (e) {
data.checked = e
}
/**
* 登录
*/
async function toLogin () {
if (!data.checked) {
uni.showToast({
title: '请阅读并同意《隐私政策》和《用户服务协议》',
icon: 'none',
})
return;
}
const { mobile, password } = data;
if (!mobile) {
uni.showToast({
title: '请输入手机号',
icon: 'none',
})
} else if (mobile.length != 11) {
uni.showToast({
title: '请输入正确的手机号',
icon: 'none',
})
} else if (!password) {
uni.showToast({
title: '请输入密码',
icon: 'none',
})
} else {
uni.showLoading({
title: '正在登录中...',
})
let res = await login({
password: password,
phone: mobile
})
console.log(res)
uni.setStorageSync('token', res.token)
uni.setStorageSync('userInfo', res.user)
// uni.setStorageSync('userId', res.user.userId)
// uni.setStorageSync('userName', res.user.userName)
// uni.setStorageSync('avatar', res.user.avatar ? res.user.avatar : '../../static/default/avatar.png')
// uni.setStorageSync('phone', res.user.phone)
// uni.setStorageSync('invitationCode', res.user.invitationCode)
// uni.setStorageSync('sex', res.user.sex)
// uni.setStorageSync('userId', res.user.userId)
//
// if (res.user.qdCode) {
// uni.setStorageSync('qdCode', res.user.qdCode)
// }
uni.hideLoading();
uni.showToast({
title: '登录成功',
icon: 'none'
})
uni.reLaunch({
url:'/pages/index/index'
})
}
}
</script>
<style lang="scss" scoped>
page {
background: #ffffff;
}
.container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
background: #ffffff;
box-sizing: border-box;
}
.bg{
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
top: 0;
}
.wrapper{
position: relative;
padding-top: 48rpx;
box-sizing: border-box;
}
.footerView {
display: flex;
justify-content: center;
align-items: center;
font-weight: 400;
font-size: 24rpx;
color: #333333;
margin-top: 50rpx;
}
.send-msg {
line-height: initial;
font-weight: 400;
font-size: 28rpx;
color: #EC6F48;
border: none;
background-color: transparent;
}
.send-msg::after{
border: none;
background-color: transparent;
}
.wrapper {
min-height: 100vh;
position: relative;
z-index: 90;
}
*{
box-sizing: border-box;
}
.input-content {
padding: 0 56rpx;
}
.cu-form-group{
width: 100%;
display: flex;
flex-direction: column;
align-items: flex-start;
margin-bottom: 48rpx;
background-color: transparent;
padding: 0;
}
.cu-form-group .title{
width: 100%;
margin-bottom: 32rpx;
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
.cu-form-group .input{
width: 100%!important;
// height: 84rpx;
// line-height: 84rpx;
background-color: #fff;
align-items: center;
// padding: 22rpx 32rpx 22rpx 24rpx!important;
input{
height: 84rpx!important;
}
v-deep .uni-input-input{
height: 84rpx!important;
}
}
.flex{
display: flex;
}
.confirm-btn {
width: 100%;
height: 100rpx;
text-align: center;
line-height: 100rpx;
border-radius: 16rpx;
margin-top: 40rpx;
background: #EC6F48;
font-size: 32rpx;
color: #FFFFFF;
&:after {
border: none;
}
}
</style>

404
pages/login/register.vue Normal file
View File

@ -0,0 +1,404 @@
<template>
<view class="container">
<view class="bg" >
<image src="../../static/default/i_bg.png" style="width: 100%;height:100%" mode="aspectFill"></image>
</view>
<view class="wrapper u-relative" style="padding-top: 48rpx;box-sizing: border-box;">
<view class="nav" style="width: 100%;height: 96rpx;"></view>
<view class="input-content">
<view style="font-size: 58rpx;font-weight: bold;color: #333;margin-bottom: 48rpx;">注册</view>
<view class="cu-form-group">
<view class="title">手机号</view>
<view class="input" style="padding-left: 20rpx;">
<input class="input" type="number" :value="data.mobile" placeholder="请输入手机号" maxlength="11" data-key="mobile"
@input="inputChange" />
</view>
</view>
<view class="cu-form-group">
<text class="title">验证码</text>
<view class="input flex" style="padding-left: 20rpx;padding-right: 20rpx;">
<input type="number" :value="data.code" placeholder="请输入验证码" maxlength="6" data-key="code"
@input="inputChange" @confirm="toRegister" />
<button class="send-msg" @click="sendMsg" :disabled="data.sending">{{ data.sendTime }}</button>
</view>
</view>
<view class="cu-form-group">
<text class="title">设置密码</text>
<view class="input" style="padding-left: 20rpx;">
<input class="input" type="password" :value="data.password" placeholder="请设置新密码" placeholder-class="input-empty"
maxlength="20" minlength="6" data-key="password" @input="inputChange" @confirm="toRegister" />
</view>
</view>
<button class="confirm-btn" @click="toRegister">注册</button>
<button class="confirm-btn" @click="toLogin">登录</button>
</view>
<view class="footerView">
<u-checkbox-group>
<u-checkbox v-model="data.checked" label-size='24upx' shape="circle" @change="radioChange"></u-checkbox>
</u-checkbox-group>
<view>注册即同意</view>
<!-- 协议地址 -->
<view @click="linkTo('/pages/me/privacy')" style="color: #37A6FF;">隐私政策</view>
<view @click="linkTo('/pages/me/agreement')" style="color: #37A6FF;">用户服务协议</view>
</view>
</view>
</view>
</template>
<script setup>
import { reactive } from 'vue';
import { onLoad} from '@dcloudio/uni-app'
import {setSendMsg,register} from '@/api/login/login.js';
import {commonType} from '@/api/init.js';
import { linkTo } from '@/utils/app.js';
let data = reactive({
code: '',
mobile: '',
password: '',
sending: false,
sendTime: '获取验证码',
count: 60,
relation: "",
invitation: '',
isregisterCode: '',
qdCodeion: '', //
checked: false,
})
onLoad(async ( options ) => {
if (uni.getStorageSync('qdCodeion')) { data.qdCodeion = uni.getStorageSync('qdCodeion') }
if (options.qdCode) { data.qdCodeion = options.qdCode }
if (options.invitation ) { data.invitation = options.invitation }
let res = await commonType(3)
data.isregisterCode = res.value
})
/**
* 发送验证码
*/
async function sendMsg () {
if (!data.mobile) {
uni.showToast({
title: '请输入手机号',
icon: 'none',
})
} else if (data.mobile.length !== 11) {
uni.showToast({
title: '请输入正确的手机号',
icon: 'none',
})
} else {
uni.showLoading({
title: '正在发送验证码...'
})
let res = await setSendMsg(data.mobile,'login')
uni.hideLoading();
uni.hideToast();
if( res ){
data.sending = true;
uni.showToast({
title: '验证码发送成功请注意查收',
icon: 'none',
duration: 1000
})
countDown();
} else {
uni.showModal({
showCancel: false,
title: '短信发送失败',
content: '请一分钟后再获取验证码'
});
}
}
}
/**
* 验证码倒计时
*/
function countDown() {
console.log(data.count)
if (data.count === 1) {
data.count = 60;
data.sending = false;
data.sendTime = '获取验证码';
} else {
data.count = data.count - 1;
data.sending = true;
data.sendTime = data.count - 1 + '秒后重新获取';
setTimeout(countDown.bind(this), 1000);
}
}
/**
* 获取注册值
* @param {Object} e
*/
function inputChange(e) {
const key = e.currentTarget.dataset.key;
data[key] = e.detail.value;
}
/**
* 是否同意协议
* @param {Object} e
*/
function radioChange(e) {
data.checked = e
}
/**
* 登录
*/
function toLogin() {
uni.reLaunch({
url: '/pages/login/login'
});
}
/**
* 注册
*/
async function toRegister() {
const {
mobile,
password,
code,
checked,
invitation,
isregisterCode,
qdCodeion
} = data;
if (!mobile) {
uni.showToast({
title: '请输入账号',
icon: 'none',
duration: 1000
})
return
}
if (!code) {
uni.showToast({
title: '请输入验证码',
icon: 'none',
duration: 1000
})
return
}
if (!password) {
uni.showToast({
title: '请设置密码',
icon: 'none',
duration: 1000
})
return
}
if (password.length < 6) {
uni.showToast({
title: '密码位数必须大于六位',
icon: 'none',
duration: 1000
})
return
}
if (invitation.length == 0 && isregisterCode == '是') {
uni.showToast({
title: '请输入邀请码',
icon: 'none',
duration: 1000
})
return
}
if (!checked) {
uni.showToast({
title: '请先同意《隐私政策》和《用户协议》',
icon: 'none',
duration: 1000
})
return
}
data.logining = true;
uni.showLoading({
title: '注册中...'
})
let platform = ''
// #ifdef APP
platform = 'app'
// #endif
// #ifdef H5
platform = 'h5'
// #endif
let res = await register({
password: password,
phone: mobile,
msg: code,
inviterCode: invitation,
platform: platform,
qdCode: qdCodeion,
})
if (res.code === 0) {
uni.setStorageSync('token', res.token)
uni.setStorageSync('userInfo', res.user)
uni.showToast({
title: '注册成功',
icon: 'none'
})
setTimeout(function() {
uni.switchTab({
url: '/pages/index/index'
});
}, 1000)
} else {
uni.showModal({
showCancel: false,
title: '注册失败',
content: res.msg
});
}
uni.hideLoading();
}
</script>
<style lang="scss" scoped>
page {
background: #ffffff;
}
*{
box-sizing: border-box;
}
.bg{
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
top: 0;
}
.wrapper{
position: relative;
padding-top: 48rpx;
box-sizing: border-box;
}
.flex{
display: flex;
}
.footerView {
display: flex;
justify-content: center;
align-items: center;
font-weight: 400;
font-size: 24rpx;
color: #333333;
margin-top: 50rpx;
}
.cuIcon::before{
width: 30rpx;
height: 30rpx;
margin-right: 12rpx;
}
.cuIcon-round::before {
content: "\e6d7";
}
.cuIcon-radiobox:before {
content: "\e75b";
color: #37A6FF;
}
.send-msg {
line-height: initial;
font-weight: 400;
font-size: 28rpx;
color: #EC6F48;
border: none;
background-color: transparent;
margin: 0;
padding: 0;
}
.send-msg::after{
border: none;
background-color: transparent;
}
.container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
background: #ffffff;
box-sizing: border-box;
}
.wrapper {
min-height: 100vh;
position: relative;
z-index: 90;
}
.input-content {
padding: 0 56rpx;
}
.cu-form-group{
display: flex;
flex-direction: column;
align-items: flex-start;
margin-bottom: 48rpx;
background-color: transparent;
padding: 0;
.title{
margin-bottom: 32rpx;
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
.input{
width: 100%;
// height: 84rpx;
// line-height: 84rpx;
background-color: #fff;
align-items: center;
// padding: 22rpx 32rpx 22rpx 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
input{
height: 84rpx!important;
}
v-deep .uni-input-input{
height: 84rpx!important;
}
}
}
.confirm-btn {
width: 100%;
height: 100rpx;
text-align: center;
line-height: 100rpx;
border-radius: 16rpx;
margin-top: 40rpx;
background: #EC6F48;
font-size: 32rpx;
color: #FFFFFF;
&:after {
border: none;
}
}
</style>

401
pages/login/registerApp.vue Normal file
View File

@ -0,0 +1,401 @@
<template>
<view class="container">
<view class="bg" >
<image src="../../static/default/i_bg.png" style="width: 100%;height:100%" mode="aspectFill"></image>
</view>
<view class="wrapper u-relative" style="padding-top: 48rpx;box-sizing: border-box;">
<view class="input-content">
<view style="font-size: 58rpx;font-weight: bold;color: #333;margin-bottom: 48rpx;">注册</view>
<view class="cu-form-group" >
<view class="title">手机号</view>
<input class="input" type="number" :value="mobile" placeholder="请输入手机号" maxlength="11" data-key="mobile"
@input="inputChange" />
</view>
<view class="cu-form-group" >
<text class="title">验证码</text>
<view class="input flex">
<input type="number" :value="code" placeholder="请输入验证码" maxlength="6" data-key="code"
@input="inputChange" @confirm="toLogin" />
<button class="send-msg" @click="sendMsg" :disabled="sending">{{ sendTime }}</button>
</view>
</view>
<view class="cu-form-group" >
<text class="title">设置密码</text>
<input class="input" type="password" :value="password" placeholder="请设置新密码" placeholder-class="input-empty"
maxlength="20" minlength="6" data-key="password" @input="inputChange" @confirm="toLogin" />
</view>
<!-- <view class="cu-form-group"
style="border: 2upx solid whitesmoke;margin-bottom: 20px;border-radius: 30px">
<text class="title">邀请码</text>
<input type="text" v-if="registerCode == ''" :value="invitation" placeholder="请填写邀请码"
data-key="invitation" maxlength="20" @input="inputChange" @confirm="toLogin" />
<input type="text" v-if="registerCode == ''" :value="invitation" placeholder="请填写邀请码(选填)"
data-key="invitation" maxlength="20" @input="inputChange" @confirm="toLogin" />
</view> -->
<button class="confirm-btn" @click="toRegister">注册</button>
<button class="confirm-btn" @click="toLogin">登录</button>
</view>
<view class="footerView">
<u-checkbox-group>
<u-checkbox v-model="checked" label-size='24upx' shape="circle" @change="radioChange"></u-checkbox>
</u-checkbox-group>
<view>同意</view>
<!-- 协议地址 -->
<navigator url="/me/setting/mimi" open-type="navigate" style="color: #37A6FF;">隐私政策</navigator>
<navigator url="/me/setting/xieyi" open-type="navigate" style="color: #37A6FF;">用户协议</navigator>
</view>
</view>
</view>
</template>
<script setup>
import { reactive } from 'vue';
import { onLoad} from '@dcloudio/uni-app'
import http from '@/http/http.js';
let data = reactive({
code: '',
mobile: '',
password: '',
sending: false,
sendTime: '获取验证码',
count: 60,
relation: "",
invitation: '',
registerCode: '',
qdCodeion: '', //
checked: false,
})
onLoad(( options ) => {
let relation = e.invitation
if (relation) {
this.relation = relation;
this.invitation = relation;
}
if (e.qdCode) {
this.qdCodeion = e.qdCode
}
http.request({
url:'app/common/type/3',
}).then(res => {
if (res.code == 0) {
this.registerCode = res.data.value
}
});
})
/**
* 是否同意协议
* @param {Object} e
*/
function radioChange(e) {
this.checked = e
}
function showMa() {
//
this.$Request.getT('/common/type/88').then(res => {
if (res.code == 0) {
this.invitation = res.data.value;
}
});
}
function sendMsg() {
const {
mobile
} = this;
if (!mobile) {
uni.showToast({
title: '请输入手机号',
icon: 'none',
duration: 1000
})
} else if (mobile.length !== 11) {
uni.showToast({
title: '请输入正确的手机号',
icon: 'none',
duration: 1000
})
} else {
uni.showLoading({
title: '正在发送验证码...'
})
http.request({
url:'app/Login/sendMsg/' + mobile + '/login',
}).then(res => {
if (res.code === 0) {
this.sending = true;
uni.showToast({
title: '验证码发送成功请注意查收',
icon: 'none',
duration: 1000
})
this.countDown();
} else {
uni.showModal({
showCancel: false,
title: '短信发送失败',
content: res.msg ? res.msg : '请一分钟后再获取验证码'
});
}
uni.hideLoading();
})
}
}
function countDown() {
const {
count
} = this;
if (count === 1) {
this.count = 60;
this.sending = false;
this.sendTime = '获取验证码';
} else {
this.count = count - 1;
this.sending = true;
this.sendTime = count - 1 + '秒后重新获取';
setTimeout(this.countDown.bind(this), 1000);
}
}
function inputChange(e) {
const key = e.currentTarget.dataset.key;
this[key] = e.detail.value;
}
function toLogin() {
console.log("123");
uni.reLaunch({
url: '/pages/login/login'
});
}
function toRegister() {
const {
mobile,
password,
code,
checked,
invitation,
registerCode,
qdCodeion
} = this;
if (!mobile) {
uni.showToast({
title: '请输入账号',
icon: 'none',
duration: 1000
})
return
}
if (!code) {
uni.showToast({
title: '请输入验证码',
icon: 'none',
duration: 1000
})
return
}
if (!password) {
uni.showToast({
title: '请设置密码',
icon: 'none',
duration: 1000
})
return
}
if (password.length < 6) {
uni.showToast({
title: '密码位数必须大于六位',
icon: 'none',
duration: 1000
})
return
}
if (invitation.length == 0 && registerCode == '是') {
uni.showToast({
title: '请输入邀请码',
icon: 'none',
duration: 1000
})
return
}
if (!checked) {
uni.showToast({
title: '请先同意《隐私政策》和《用户协议》',
icon: 'none',
duration: 1000
})
return
}
this.logining = true;
uni.showLoading({
title: '注册中...'
})
let platform = ''
// #ifdef APP
platform = 'app'
// #endif
// #ifdef H5
platform = 'h5'
// #endif
http.request({
url: 'app/Login/registerCode?password=' + password + '&phone=' + mobile + '&msg=' + code +
'&inviterCode=' + invitation + '&platform=' + platform + '&qdCode=' + qdCodeion,
method: 'post'
}).then(res => {
if (res.code === 0) {
// this.$queue.remove('invitation');
uni.setStorageSync('token', res.token)
uni.setStorageSync('userId', res.user.userId)
uni.setStorageSync('phone', res.user.phone)
uni.setStorageSync('invitationCode', res.user.invitationCode)
//
if (res.user.qdCode) {
uni.setStorageSync('qdCode', res.user.qdCode)
}
uni.showToast({
title: '注册成功',
icon: 'none'
})
setTimeout(function() {
uni.navigateTo({
url: '/pages/login/appEq'
})
}, 1000)
} else {
uni.hideLoading();
uni.showModal({
showCancel: false,
title: '注册失败',
content: res.msg
});
}
});
}
</script>
<style lang="scss" scoped>
page {
background: #fff;
}
*{
box-sizing: border-box;
}
.flex{
display: flex;
}
.bg{
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
top: 0;
}
.wrapper{
position: relative;
padding-top: 48rpx;
box-sizing: border-box;
}
.footerView {
display: flex;
justify-content: center;
align-items: center;
font-weight: 400;
font-size: 24rpx;
color: #333333;
// position: absolute;
// left: 0;
// right: 0;
// bottom: 178rpx;
.cuIcon::before{
width: 30rpx;
height: 30rpx;
margin-right: 12rpx;
}
.cuIcon-round::before {
content: "\e6d7";
}
.cuIcon-radiobox:before {
content: "\e75b";
color: #37A6FF;
}
}
.send-msg {
line-height: initial;
font-weight: 400;
font-size: 28rpx;
color: #EC6F48;
border: none;
background-color: transparent!important;
}
.send-msg::after{
border: none;
background-color: transparent;
}
.container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
background: #fff;
}
.wrapper {
position: relative;
z-index: 90;
min-height: 100vh;
}
.input-content {
padding: 0 56rpx;
.cu-form-group{
display: flex;
flex-direction: column;
align-items: flex-start;
margin-bottom: 48rpx;
background-color: transparent;
padding: 0;
.title{
margin-bottom: 32rpx;
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
.input{
width: 100%;
height: 84rpx;
line-height: 84rpx;
background-color: #fff;
align-items: center;
padding: 22rpx 32rpx 22rpx 24rpx;
}
}
}
.confirm-btn {
width: 100%;
height: 100rpx;
text-align: center;
line-height: 100rpx;
border-radius: 16rpx;
margin-top: 40rpx;
background: #EC6F48;
font-size: 32rpx;
color: #FFFFFF;
&:after {
border: none;
}
}
</style>

65
pages/me/agreement.vue Normal file
View File

@ -0,0 +1,65 @@
<template>
<view style="line-height: 26px;padding: 32upx;" class="home1 ">
<view style="font-size: 28upx;" v-html="data.content"></view>
<view class="btn-box u-flex u-row-center" v-if="!isLogin">
<view class="btn cancel" @click="cancel">拒绝</view>
<view class="btn" @click="back">同意</view>
</view>
</view>
</template>
<script setup>
import { reactive } from 'vue';
import { onLoad } from '@dcloudio/uni-app'
import {commonType} from '@/api/init.js';
let data = reactive({
content: '',
isLogin:false
})
onLoad(() => {
getGuize()
data.isLogin=uni.getStorageSync('token')?true:false
})
async function getGuize() {
let res = await commonType(154)
data.content = res.value
}
function cancel(){
// #ifdef H5
uni.navigateBack()
// #endif
// #ifdef APP
plus.runtime.quit();
// #endif
}
function back(){
uni.navigateBack()
}
</script>
<style scoped>
.btn {
width: 100%;
height: 42px;
line-height: 42px;
border-radius: 30px;
background: #ff7581;
color: #ffffff;
text-align: center;
}
.btn-box{
gap: 20px;
padding: 30rpx 130rpx;
}
.cancel{
background-color: #eee;
color: #999;
}
page{
/* background: #1c1b20; */
}
</style>

View File

@ -0,0 +1,249 @@
## 1.9.72023-08-02
本次更新:
- 调整 `draw-before` 为自定义函数,且该函数为必备函数,转盘能否启动,将根据该函数中调用 `callback` 时传递的 `Boolean` 进行判断
## 1.9.6.22023-07-28
本次更新:
- 更新示例项目
## 1.9.6.12023-07-28
本次更新:
- 修复参数文档排版问题
## 1.9.62023-07-28
本次更新:
- 新增`drawStartBefore`钩子,请看说明文档
## 1.9.52023-07-12
本次更新:
- 优化 `duration` 参数的变更需要刷新才能生效的开发体验
- 新增 `duration``ringCount` 设置不合理时的 `console` 提醒
## 1.9.42023-07-06
本次更新:
- 修复某些情况文字无法换行的问题
- 参数`strMaxLen`设置为`0`时不限制文字长度
## 1.9.32023-06-12
本次更新:
- 新增 `selfTime` 参数,查看文档说明
- 示例项目分离 `uni-popup` 用例为独立页面进行展示
## 1.9.22023-05-22
本次更新:
- 新增 `renderDelay` 参数,请查看文档
- 示例项目新增 `ui-popup` 组件的用例,使用 `uni-popup` 包裹转盘时,请前往 `uni-popup` 组件文档关注平台兼容性问题
## 1.9.12023-03-07
本次更新:
- 新增 `selfRotaty` 自转参数视觉效果上存在细微瑕疵欢迎PR
## 1.8.332022-07-04
本次更新:
- 统一奖品图片下载方式
## 1.8.322022-06-20
本次更新:
- 调整平台兼容性(因 HBX 存在 bug导致平台兼容性的更新多次失败近几次的更新都可以忽略
## 1.8.312022-06-20
本次更新:
- 无意义的更新,请忽略
## 1.8.302022-06-20
本次更新:
- 调整平台兼容性
## 1.8.292022-06-19
本次更新:
- 调整平台兼容信息
## 1.8.282022-06-19
本次更新:
- 修复单个尺寸过大的 canvas 在 H5/APP-vue iOS/Safari 中存在可能无法绘制成功的问题
## 1.8.272022-06-01
本次更新:
- 优化示例项目
## 1.8.262022-06-01
本次更新:
- 修复奖品图片裁切为圆形时在安卓机器不显示的问题
## 1.8.252022-05-31
本次更新:
- 修复部分安卓下载图片得到.unknown格式文件的问题
## 1.8.242022-05-09
本地缓存:
- 优化示例项目
## 1.8.232022-05-09
本地缓存:
- 优化清除文件缓存的方法
## 1.8.222022-05-09
本次更新:
- 调整计算转盘绘制的方式
## 1.8.212022-05-08
本次更新:
- 调整示例项目中本地图片的引入方式
## 1.8.202022-04-29
本次更新:
- 修复转盘在某个临界点可以出现多次触发的问题
## 1.8.192022-04-27
本次更新:
- 奖品文字的绘制由先前的两行变成多行,根据设定的每行文字的长度分段绘制
## 1.8.182022-04-25
本次更新:
- 减少小程序平台的 delay
## 1.8.172022-03-23
本次更新:
- 新增配置项 `imgCircled` 奖品图片是否裁切为圆形,默认不裁切
## 1.8.162022-03-04
本次更新:
- 示例项目新增绘制时长的计算,方便开发时定位绘制慢的问题
## 1.8.152022-03-02
本次更新:
- 优化一处错误提示信息的展现方式
## 1.8.142021-11-29
本次更新:
- 示例项目中新增开放自定义权重最大值,没有自定义则取权重数组中的最大值
- 更新文档
## 1.8.132021-11-03
本次更新:
- 注释 `1.8.12` 版本中调试时的代码
## 1.8.122021-11-03
本次更新:
- 修复一些老机型不支持 `flex` 导致布局错乱的问题
## 1.8.112021-10-29
本次更新:
- 优化示例项目中模拟接口访问的速度
## 1.8.102021-10-19
本次更新:
- 优化组件代码
- 更新示例项目
## 1.8.92021-09-28
本次更新:
- 移除内置的 `奖品准备中...` 提示
## 1.8.82021-09-27
本次更新:
- 修复 `1.8.6` 引起的非微信小程序平台绘制异常的问题
## 1.8.72021-09-23
本次更新:
- 优化项目中使用到的图片大小
## 1.8.62021-09-23
本次更新:
- 修复小程序平台在绘制 `base64` 格式的图片时无法在真机模式下正常显示的问题
## 1.8.52021-09-13
本次更新:
- 修复一个已知问题
## 1.8.42021-09-12
本次更新:
- 调整 `strFontColor``strFontColors`,现在可以设置每个区块的文字颜色,详见文档说明
## 1.8.32021-09-12
本次更新:
- 修复因 `1.8.0` 改动引起的文字方向、无奖品图时绘制异常的问题
- 新增 `imgDrawed` 是否绘制奖品图片的配置项 ,默认为 `true`
## 1.8.22021-09-10
本次更新:
**不兼容旧版本的更新**
- 移除配置项 `strKey` 字段
- 调整 `prizeList` 结构
## 1.8.12021-09-06
本次更新:
- 修复 `hbx3.1.22` 在小程序平台处理 `id-name` 存在解析错误的问题
## 1.8.02021-09-06
本次更新:
**该版本更新涉及破坏性的变更,请重新查看 `API - Props` 的部分**
- `px` 全面调整为 `rpx` 单位,多个`Props` 的参数相应调整,请查看文档
- 新增 `pixelRatio` 参数,该参数为设计稿的设备像素比基准值,默认为 `2` 倍素
## 1.7.182021-09-05
本次更新:
- 修复一个已知问题
## 1.7.172021-08-23
本次更新:
- 更新示例项目
## 1.7.162021-08-14
本次更新:
- 更新示例项目
## 1.7.152021-08-03
本次更新:
- 新增文字竖向展示的功能,详见文档说明
## 1.7.132021-08-02
本次更新:
- 更新文档
## 1.7.122021-07-30
本次更新:
- 修复示例项目的已知问题
- 现已提供Almost-Lottery抽奖转盘的uniCloud云端一体页面模板
- 现已提供Almost-Lottery抽奖转盘云端一体页面配套的Admin配置中心
## 1.7.112021-07-22
本次更新:
- 修复部分安卓手机文字大小异常的问题
- 字段 `strHeightMultiple` 更换为 `strLineHeight`
## 1.7.102021-07-12
本次更新:
- 修复奖品名称 `name` 为空字符串时无法成功绘制转盘的问题
- 新增 `prizeNameDrawed` 是否绘制奖品名称的配置项,现在可以仅展示奖品图片了
## 1.7.92021-07-09
本次更新:
- 优化组件内部代码
- 修复奖品图片已然是 `base64` 格式时导致转盘绘制失败的问题
- 文档新增QQ群号让沟通更便捷
## 1.7.82021-07-08
本次更新:
- 调整 `Canvas` 默认宽高为 `280`
## 1.7.72021-07-08
本次更新:
- 新增多个配置项,满足更多自定义需求
- 优化多行文本情况下非中文字符的字节处理
- 修复偶发的第一条数据文本不居中显示的问题
## 1.7.62021-07-02
本次更新:
- 调整 `imageWidth``imageHeight` 字段为 `imgWidth``imgHeight`
- 更新示例项目
## 1.7.52021-07-01
本次更新:
- 新增配置项 `imgMarginStr` 奖品图片距离奖品文字的距离
## 1.7.42021-06-28
本次更新:
- 新增轮盘旋转或指针旋转配置项
- 转盘内置的外环图片以及按钮图片统一调整为 `image` 展示
- 更新相关文档说明
## 1.7.32021-06-16
本次更新:
- 优化错误提示
- 优化示例项目
- 优化文档说明
## 1.7.22021-06-11
本次更新:
- 新增 `canvasId` 参数配置项,多画板情况下需要配置不同的 `canvasId`
- 优化多画板情况下的缓存功能
- 优化示例项目
- 修改文档说明
## 1.7.12021-06-10
本次更新:
- 优化示例项目中的注释
## 1.7.02021-06-04
本次更新:
- 修复 `1.6.1` 引起的多行奖品文字行高异常的问题
- 新增配置转盘外环和抽奖按钮图片的功能,详见文档说明
- 更新示例项目,新增抽奖次数等业务有关的逻辑供参考
## 1.6.12021-05-28
本次更新:
- 修复小程序平台画板模糊的问题
## 1.6.02021-05-28
本次更新:
- 新增奖品区块是否开启描边的配置项,默认不开启
- 调整画板缓存为默认不开启
- 优化代码
- 优化文档说明
- 更新示例项目并修改部分注释
## 1.5.132021-05-22
本次更新:
- 优化文档说明
- 更新示例项目
## 1.5.122021-05-22
本次更新:
- 新增配置项 `strokeColor` 奖品区块边框颜色
- 更新文档说明
## 1.5.112021-05-19
本次更新:
- 新增`strMarginOutside`参数,用于设置奖品文字距离边缘的距离
- 修复奖品文字在某些情况下不是居中显示的问题
## 1.5.102021-05-19
本次更新:
- 修复示例项目中权重值相同时的取值逻辑
## 1.5.92021-05-14
本次更新:
- 调整代码,优化小程序端的展示
## 1.5.82021-05-12
本次更新:
- 文档增加预警提示:不再维护非 `uni_modules` 模式下的版本
## 1.5.72021-05-12
本次更新:
- 修复小程序平台奖品名称不清晰的问题
## 1.5.62021-03-18
本次更新:
- 适配 uni_modules 插件模式

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,85 @@
{
"id": "almost-lottery",
"displayName": "Almost-Lottery抽奖转盘",
"version": "1.9.7",
"description": "【荣获2021插件大赛三等奖】提供奇数、缓存等众多配置项更有抽奖概率、抽奖次数、付费抽奖等功能内置于示例项目中完美支持APP、各平台小程序、H5、PC同时提供 uniCloud 云端版本",
"keywords": [
"转盘",
"抽奖",
"转盘抽奖",
"大转盘",
"大转盘抽奖"
],
"repository": "https://github.com/ialmost/almost-components_uniapp",
"engines": {
"HBuilderX": "^3.7.11"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "",
"type": "component-vue"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "n"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y",
"钉钉": "y",
"快手": "y",
"飞书": "y",
"京东": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "n"
}
}
}
}
}

View File

@ -0,0 +1,174 @@
# almost-lottery
*使用 Canvas 绘制的抽奖转盘,提供奇数、缓存等众多配置项,更有抽奖概率、抽奖次数、付费抽奖等功能内置于示例项目中*
> <br />
>
> 如果用着还行,请支持一下
> - 前往 [GitHub](https://github.com/ialmost/almost-components_uniapp) 给个 Star
> - 前往 [UniApp](https://ext.dcloud.net.cn/plugin?id=1030) 给个五星
> - 使用中遇到问题时,可以添加 **QQ群 20441313**
>
> <br />
## 基于 uniCloud 开发的云端 Almost-Lottery 抽奖转盘,欢迎尝试体验
- [Almost-Lottery抽奖转盘的云端一体页面](https://ext.dcloud.net.cn/plugin?id=5763)
- [Almost-Lottery抽奖转盘的配置中心](https://ext.dcloud.net.cn/plugin?id=5762)
## 高能预警
- 本插件仅支持 `uni_modules` 模式,强烈推荐使用该模式,**非 `uni_modules` 模式不再维护**
- 在使用本插件之前,强烈建议使用 `HBuilderX` 导入示例项目验证可用性并参照修改
## 功能概要
- [x] 可配置奖品文字 **支持横向/竖向展示**
- [x] 可配置每个奖品区块的背景颜色
- [x] 可配置每个奖品区块的奖品文字颜色
- [x] 可配置奖品区块是否开启描边以及边框的颜色,默认不开启
- [x] 可配置转盘外环和抽奖按钮图
- [x] 可配置每个奖品区块的奖品图片,**当图片是网络地址时小程序端需要配置白名单H5端需要允许跨域奖品文字为竖向时不支持展示奖品图片**
- [x] 奖品列表支持奇数,**奇数时需尽量能被 `360` 除尽**
- [x] 可配置内圈与外圈的间距
- [x] 可配置轮盘旋转或指针旋转
- [x] 可配置画板是否缓存,默认不开启
- [x] 更多配置请查看API说明
## 示例项目附加功能
- [x] 中奖概率,**强烈推荐中奖概率应由后端控制**
- [x] 抽奖次数
- [x] 付费抽奖
## 注意事项
- 编译到小程序端时请务必勾选ES6转ES5
- `@reset-index="prizeIndex = -1"` 必须默认写入到 `template` 中,不可删除
- 每个奖品区块的奖品图片尺寸不宜过大,图片越大,绘制的过程越慢,尽量将图片尺寸控制在 `100*100` 以内,且图片大小控制在 `40KB` 以内
- 关于中奖概率的配置,请下载示例项目,参照 `pages/index/index.vue` 中的代码进行配置
- 组件本身不涉及任何业务逻辑,与业务相关的代码建议都放在 `pages/index/index.vue`
## 代码演示
#### 基础用法
```
// template
// @reset-index="prizeIndex = -1" 必须默认写入到 template 中,不可删除
<almost-lottery
:prizeList="prizeList"
:prizeIndex="prizeIndex"
@reset-index="prizeIndex = -1"
@draw-before="handleDrawBefore"
@draw-start="handleDrawStart"
@draw-end="handleDrawEnd"
@finish="handleDrawFinish"
v-if="prizeList.length"
/>
// script
import AlmostLottery from '@/uni_modules/almost-lottery/components/almost-lottery/almost-lottery.vue'
export default {
components: {
AlmostLottery
},
data () {
return {
// 以下是奖品配置数据
// 奖品数据
prizeList: [],
// 中奖下标
prizeIndex: -1
}
},
methods: {
// 本次抽奖开始之前
handleDrawStart (callback) {
// 这里需要处理你抽奖之前的逻辑
// 请查看示例项目中的代码
// 必须调用 callback 并传递一个布尔值,布尔值为 true 时,转盘才会开始旋转
let flag = true
callback(flag)
},
// 本次抽奖开始
handleDrawStart () {
// 这里需要处理你的抽奖逻辑,并得出中奖物品的 prizeIndex
// 请查看示例项目中的代码
},
// 本次抽奖结束
handleDrawEnd () {
// 完成抽奖后,这里处理你拿到结果后的逻辑
// 请查看示例项目中的代码
},
// 抽奖转盘绘制完成
handleDrawFinish (res) {
// 抽奖转盘准备就绪后,这里处理你的逻辑
// 请查看示例项目中的代码
// console.log('抽奖转盘绘制完成', res)
}
}
}
```
## API
#### Props
参数 | 说明 | 类型 | 默认值
:---|:---|:---|:---
pixelRatio | 移动端设计稿的像素比基准值,**涉及到 `rpx` 的适配问题** | *`Number`* | `2`
canvasId | Canvas的标识**多画板情况下需要配置不同的标识** | *`String`* | `'almostLottery'`
renderDelay | 转盘的渲染延时,**转盘被包裹在 uni-popup 组件内且开启了动画,请设置成最少 300** | *`Number`* | `0`
lotterySize | 抽奖转盘的整体尺寸,单位 `rpx` | *`Number`* | `600`
actionSize | 抽奖按钮的尺寸,单位 `rpx` | *`Number`* | `200`
canvasMarginOutside | Canvas边缘距离转盘边缘的距离单位`rpx` | *`Number`* | `90`
prizeIndex | 获奖奖品在奖品列表中的序号,**每次抽奖结束后会自动重置为 `-1`** | *`Number`* | `-1`
prizeList | 奖品列表,支持奇数(尽量能被 `360` 除尽),**为奇数时需要重设 `colors` 参数** | *`Array`* | -
lotteryBg | 转盘外环图片 | `String` | `默认内置的本地图片`
actionBg | 抽奖按钮图片 | `String` | `默认内置的本地图片`
colors | 奖品区块对应的背景颜色,默认 2 个颜色相互交替,**也可以对每个区块设置不同颜色** | *`Array`* | `['#FFFFFF', '#FFBF05']`
prizeNameDrawed | 是否绘制奖品名称 | *`Boolean`* | `true`
stroked | 是否开启奖品区块描边 | *`Boolean`* | `false`
strDirection | 奖品名称展示方向,可选值 `'horizontal'` => 横向 `'vertical'` => 竖向 | *`String`* | `'horizontal'`
strokeColor | 奖品区块边框颜色 | *`String`* | `'#FFBF05'`
rotateType | 旋转的类型,可选值 `'roulette'` => 轮盘旋转 `'pointer'` => 指针旋转 | *`String`* | `'roulette'`
selfRotaty | 是否开启自转,开启后`duration`和`ringCount`参数不生效 | *`Boolean`* | `false`
selfTime | 开启自转时,最少转多少毫秒 | *`Number`* | `1000`
duration | 转盘旋转的动画时长,单位:秒 | *`Number`* | `8`
ringCount | 旋转的圈数 | *`Number`* | `8`
pointerPosition | 点击抽奖按钮指针的位置,可选值 `'edge'` => 指向边界 `'middle'` => 指向中间 | *`String`* | `'edge'`
strFontColors | 奖品文字颜色,默认 2 个颜色相互交替,**也可以对每个区块的文字设置不同颜色,或仅设置一个颜色** | *`Array`* | `['#FFBF05', '#FFFFFF']`
strFontSize | 奖品名称的字号,单位 `rpx` | *`Number`* | `24`
strLineHeight | 奖品名称多行情况下的行高 | *`Number`* | `1.2`
strMaxLen | 奖品名称长度限制,为`0`时不限制,**文字竖向时不生效** | *`Number`* | `12`
strLineLen | 奖品名称在多行情况下第一行文字的长度,**文字竖向时不生效** | *`Number`* | `6`
strMarginOutside | 奖品文字相对轮盘边缘的距离,单位 `rpx` | *`Number`* | `strFontSize 的一半`
imgMarginStr | 奖品图片相对奖品文字的距离,单位 `rpx` | *`Number`* | `60`
imgWidth | 奖品图片的宽度,单位 `rpx` | *`Number`* | `50`
imgHeight | 奖品图片的高度,单位 `rpx` | *`Number`* | `50`
imgDrawed | 是否绘制奖品图片,默认绘制 | *`Boolean`* | `true`
imgCircled | 奖品图片是否裁切为圆形,默认不裁切 | *`Boolean`* | `false`
successMsg | 转盘绘制成功的提示 | *`String`* | `'奖品准备就绪,快来参与抽奖吧'`
failMsg | 转盘绘制失败的提示 | *`String`* | `'奖品仍在准备中,请稍后再来...'`
canvasCached | 是否开启缓存,避免在数据不变的情况下重复绘制,建议在生产环境中开启 | *`Boolean`* | `false`
#### Events
事件名 | 说明 | 回调参数
:---|:---|:---|:---
@reset-index | 每次抽奖结束后重置获奖的序号为 `-1`**该事件必须默认写入到 `template` 中,不可删除** | -
@draw-before | 转盘旋转之前触发,**该事件必须默认写入到 `template` 中,不可删除** | `callback(Boolean)`
@draw-start | 转盘旋转开始时触发 | -
@draw-end | 转盘旋转结束时触发 | -
@finish | Canvas转盘绘制完成时触发 | `{ ok: 绘制是否成功, data: 转盘的图片, msg: 绘制结果的提示 }`
#### prizeList 数据结构
*请按如下数据字段对你的奖品列表数据结构进行调整*
键名 | 说明 | 类型
:---|:---|:---
prizeId | 奖品对应 `ID` | *`Number`*
prizeName | 奖品名称 | *`String`*
prizeStock | 奖品库存 | *`Number`*
prizeWeight | 奖品权重 | *`Number`*
prizeImage | 奖品图片地址,网络图片仅支持`http`和`https`协议 | *`String`*

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,298 @@
/**
* 存储 localStorage 数据
* @param {String} name - 缓存数据的标识
* @param {any} content - 缓存的数据内容
*/
export const setStore = (name, content) => {
if (!name) return
if (typeof content !== 'string') {
content = JSON.stringify(content)
}
uni.setStorageSync(name, content)
}
/**
* 获取 localStorage 数据
* @param {String} name - 缓存数据的标识
*/
export const getStore = (name) => {
if (!name) return
return uni.getStorageSync(name)
}
/**
* 清除 localStorage 数据
* @param {String} name - 缓存数据的标识
*/
export const clearStore = (name) => {
if (name) {
uni.removeStorageSync(name)
} else {
console.log('清理本地全部缓存')
uni.clearStorageSync()
}
}
/**
* 绘制圆形
* @param {String} ctx - 图片网络地址
* @param {String} img - 图片地址
* @param {String} x - x 轴偏移量
* @param {String} y - y 轴偏移量
* @param {String} w -
* @param {String} h -
*/
export const circleImg = (ctx, img, x, y, w, h) => {
let r = Math.floor(w/2)
let cx = x + r
let cy = y + r
ctx.save()
ctx.beginPath()
ctx.arc(cx, cy, r, 0, Math.PI * 2)
ctx.fill()
ctx.clip()
ctx.drawImage(img, x, y, w, h)
ctx.restore()
}
/**
* 计算文本的长度
* @param {String} text - 文本内容
*/
export const clacTextLen = (text) => {
if (!text) return { byteLen: 0, realLen: 0 }
text += ''
let clacLen = 0
for (let i = 0; i < text.length; i++) {
if ((text.charCodeAt(i) < 0) || (text.charCodeAt(i) > 255)) {
clacLen += 2
} else {
clacLen += 1
}
}
// console.log(`当前文本 ${text} 的长度为 ${clacLen / 2}`)
return {
byteLen: clacLen,
realLen: clacLen / 2
}
}
/**
* 下载文件并返回临时路径
* @return {String} 临时路径
* @param {String} fileUrl - 网络地址
*/
export const downloadFile = (fileUrl) => {
return new Promise((resolve) => {
uni.downloadFile({
url: fileUrl,
success: (res) => {
resolve({
ok: true,
data: res.errMsg,
tempFilePath: res.tempFilePath
})
},
fail: (err) => {
resolve({
ok: false,
data: err.errMsg,
msg: '图片下载失败'
})
}
})
})
}
/**
* 清理应用已缓存的文件
*/
export const clearCacheFile = () => {
// #ifndef H5
uni.getSavedFileList({
success: (res) => {
let fileList = res.fileList
if (fileList.length) {
for (let i = 0; i < fileList.length; i++) {
uni.removeSavedFile({
filePath: fileList[i].filePath,
complete: () => {
console.log('清除缓存已完成')
}
})
}
}
},
fail: (err) => {
console.log('getSavedFileList Fail')
}
})
// #endif
}
// 图像转换工具可用于图像和base64的转换
// https://ext.dcloud.net.cn/plugin?id=123
const getLocalFilePath = (path) => {
if (
path.indexOf('_www') === 0 ||
path.indexOf('_doc') === 0 ||
path.indexOf('_documents') === 0 ||
path.indexOf('_downloads') === 0
) return path
if (path.indexOf('/storage/emulated/0/') === 0) return path
if (path.indexOf('/storage/sdcard0/') === 0) return path
if (path.indexOf('/var/mobile/') === 0) return path
if (path.indexOf('file://') === 0) return path
if (path.indexOf('/') === 0) {
// ios 无法获取本地路径
let localFilePath = plus.os.name === 'iOS' ? path : plus.io.convertLocalFileSystemURL(path)
if (localFilePath !== path) {
return localFilePath
} else {
path = path.substring(1)
}
}
return '_www/' + path
}
export const pathToBase64 = (path) => {
return new Promise((resolve, reject) => {
if (typeof window === 'object' && 'document' in window) {
if (typeof FileReader === 'function') {
let xhr = new XMLHttpRequest()
xhr.open('GET', path, true)
xhr.responseType = 'blob'
xhr.onload = function() {
if (this.status === 200) {
let fileReader = new FileReader()
fileReader.onload = function(e) {
resolve(e.target.result)
}
fileReader.onerror = reject
fileReader.readAsDataURL(this.response)
}
}
xhr.onerror = reject
xhr.send()
return
}
let canvas = document.createElement('canvas')
let c2x = canvas.getContext('2d')
let img = new Image
img.onload = function() {
canvas.width = img.width
canvas.height = img.height
c2x.drawImage(img, 0, 0)
resolve(canvas.toDataURL())
canvas.height = canvas.width = 0
}
img.onerror = reject
img.src = path
return
}
if (typeof plus === 'object') {
let tempPath = getLocalFilePath(path)
plus.io.resolveLocalFileSystemURL(tempPath, (entry) => {
entry.file((file) => {
let fileReader = new plus.io.FileReader()
fileReader.onload = function(data) {
resolve(data.target.result)
}
fileReader.onerror = function(error) {
console.log(error)
reject(error)
}
fileReader.readAsDataURL(file)
}, (error) => {
reject(error)
})
}, (error) => {
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
wx.getFileSystemManager().readFile({
filePath: path,
encoding: 'base64',
success: (res) => {
resolve('data:image/png;base64,' + res.data)
},
fail: (error) => {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
export const base64ToPath = (base64) => {
return new Promise((resolve, reject) => {
if (typeof window === 'object' && 'document' in window) {
base64 = base64.split(',')
let type = base64[0].match(/:(.*?);/)[1]
let str = atob(base64[1])
let n = str.length
let array = new Uint8Array(n)
while (n--) {
array[n] = str.charCodeAt(n)
}
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], {
type: type
})))
}
let extName = base64.match(/data\:\S+\/(\S+);/)
if (extName) {
extName = extName[1]
} else {
reject(new Error('base64 error'))
}
let fileName = Date.now() + '.' + extName
if (typeof plus === 'object') {
let bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
bitmap.loadBase64Data(base64, () => {
let filePath = '_doc/uniapp_temp/' + fileName
bitmap.save(filePath, {}, () => {
bitmap.clear()
resolve(filePath)
}, (error) => {
bitmap.clear()
reject(error)
})
}, (error) => {
bitmap.clear()
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
let filePath = wx.env.USER_DATA_PATH + '/' + fileName
wx.getFileSystemManager().writeFile({
filePath: filePath,
data: base64.replace(/^data:\S+\/\S+;base64,/, ''),
encoding: 'base64',
success: () => {
resolve(filePath)
},
fail: (error) => {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}

118
pages/me/contact.vue Normal file
View File

@ -0,0 +1,118 @@
<template>
<view class="container">
<view v-if="info.value == 4">
<web-view :src="info.url"></web-view>
</view>
<view class="" v-else>
<view class="card" v-if="info.value == 1">
<view class="title">
<view class="t1">添加客服微信咨询</view>
<view class="t2">{{ info.wx }}</view>
</view>
<view class="content">
<image class="img" :src="info.qrcode" mode="widthFix" @click="checkQrcode"></image>
</view>
</view>
<view class="card" v-if="info.value == 2">
<view class="title">
<view class="t1">添加客服微信咨询</view>
<view class="t2">{{ info.wx }}</view>
</view>
<view class="content">
<image class="img" :src="info.qrcode" mode="widthFix" @click="checkQrcode"></image>
</view>
</view>
</view>
</view>
</template>
<script setup>
import {
ref,
reactive
} from 'vue';
import {
onLoad
} from '@dcloudio/uni-app';
import {
commonType
} from '@/api/me/me.js';
const info = ref({});
async function commonTypeAjax() {
try {
const Ttype = await commonType(202);
// " 1 2 3 4 ",
info.value.value = Ttype.value
switch (info.value.value) {
case '1':
const res1 = await commonType(205);
const res2 = await commonType(207);
info.value.wx = res2.value;
info.value.qrcode = res1.value;
break;
case '2':
console.log('wu')
break;
case '3':
uni.makePhoneCall({
phoneNumber: uni.getStorageSync('kefuPhone') //
});
break;
case '4':
info.value.url = uni.getStorageSync('kefuPhone')
break;
}
} catch (error) {
console.log(error);
}
}
//
function checkQrcode() {
uni.previewImage({
urls: [info.value.qrcode]
});
}
onLoad(() => {
commonTypeAjax();
});
</script>
<style scoped lang="scss">
page {
background: #f5f5f5;
}
.container {
padding: 28upx;
}
.card {
padding: 28upx;
border-radius: 20upx;
background-color: #fff;
.title {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
.t1 {
color: #555;
}
}
.content {
display: flex;
justify-content: center;
padding-top: 28upx;
.img {
width: 100%;
display: block;
}
}
}
</style>

124
pages/me/feedback.vue Normal file
View File

@ -0,0 +1,124 @@
<template>
<view class="container">
<view class="card">
<view class="title-wrap">
<view class="title">问题和意见</view>
<view class="right" @click="showSheet = true">快速键入</view>
</view>
<view class="ipt-wrap">
<up-textarea v-model="form.content" placeholder="请详细描述你的问题和意见..." count></up-textarea>
</view>
</view>
<view class="card">
<view class="title-wrap">
<view class="title">QQ/邮箱</view>
</view>
<view class="ipt-wrap">
<up-input v-model="form.contact" placeholder="方便我们联系你 " count></up-input>
</view>
</view>
<view class="btn">
<up-button color="#ff7581" :loading="loaing" loading-text="提交中..." @click="confirmHandle">提交</up-button>
</view>
<up-action-sheet
:actions="list"
:show="showSheet"
cancelText="取消"
closeOnClickAction
closeOnClickOverlay
@close="showSheet = false"
@select="selectSheet"
></up-action-sheet>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { sendMessage } from '@/api/me/me.js';
const list = ref([
{
name: '界面显示错乱'
},
{
name: '启动缓慢,卡出翔了'
},
{
name: 'UI无法直视丑哭了'
},
{
name: '偶发性崩溃'
}
]);
const showSheet = ref(false);
const loaing = ref(false);
const form = reactive({
content: '',
contact: ''
});
function selectSheet(e) {
if (!form.content.length) {
form.content = e.name;
} else {
form.content += `${e.name}`;
}
}
//
async function confirmHandle() {
try {
if (!form.content) {
uni.showToast({
title: '请输入内容',
icon: 'none'
});
return;
}
if (!form.contact) {
uni.showToast({
title: '请输入联系方式',
icon: 'none'
});
return;
}
loaing.value = true;
await sendMessage({
content: JSON.stringify({ score: 5, ...form }),
state: 2,
title: form.contact
});
uni.showToast({
title: '提交成功',
icon: 'none',
mask: true
});
setTimeout(() => {
uni.navigateBack();
}, 1000);
} catch (error) {
console.log(error);
}
loaing.value = false;
}
</script>
<style scoped lang="scss">
.container {
padding: 0 20upx;
font-size: 28upx;
}
.card {
margin-bottom: 28upx;
.title-wrap {
padding: 28upx 0;
color: #999;
display: flex;
justify-content: space-between;
}
}
.btn {
padding: 28upx 0;
}
</style>

104
pages/me/gold_record.vue Normal file
View File

@ -0,0 +1,104 @@
<template>
<view class="container">
<view class="list">
<view class="item" v-for="item in listData.list" :key="item.id">
<view class="row">类型{{ item.title }}</view>
<view class="row">内容{{ item.content }}</view>
<view class="row">时间{{ item.createTime }}</view>
<view class="btm">
<text class="add" v-if="item.type == 1">+{{ item.money }}</text>
<text class="sub" v-if="item.type == 2">-{{ item.money }}</text>
</view>
</view>
</view>
<emprty-card v-if="!listData.list.length && listData.status == 'nomore'" />
<up-loadmore :status="listData.status" />
</view>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
import { queryUserMoneyDetails } from '@/api/me/me.js';
const listData = reactive({
list: [],
page: 1,
size: 10,
status: 'loading'
});
onReachBottom(() => {
listData.page++;
getList();
});
async function getList() {
try {
const res = await queryUserMoneyDetails({
page: listData.page,
limit: listData.size,
moneyType: 2,
viewType: 2
});
if (listData.page == 1) {
listData.list = res.records;
} else {
listData.list.push(...res.records);
}
if (res.currPage >= res.totalPage) {
listData.status = 'nomore';
}
} catch (error) {
console.log(error);
}
setTimeout(() => {
uni.stopPullDownRefresh();
}, 500);
}
//
onPullDownRefresh(() => {
listData.page = 1;
listData.status = 'loading';
getList();
});
onLoad((e) => {
getList();
});
</script>
<style>
page {
background: #f5f5f5;
}
</style>
<style scoped lang="scss">
.container {
padding: 28upx;
}
.list {
.item {
padding: 28upx;
border-radius: 20upx;
margin-bottom: 28upx;
background: #fff;
.row {
margin-bottom: 4px;
font-size: 28upx;
}
.btm {
display: flex;
justify-content: flex-end;
font-weight: bold;
.add {
color: rgb(253, 100, 22);
}
.sub {
color: #5aaf2e;
}
}
}
}
</style>

88
pages/me/help_center.vue Normal file
View File

@ -0,0 +1,88 @@
<template>
<view class="container">
<up-collapse accordion>
<up-collapse-item :title="item.helpClassifyName" :name="item.helpClassifyId" v-for="item in list" :key="item.helpClassifyId">
<view class="row-wrap">
<view class="u-collapse-content row" v-for="val in item.helpWordList" :key="val.helpWordId" @click="toHelpDetal(val)">
{{ val.helpWordTitle }}
</view>
</view>
</up-collapse-item>
</up-collapse>
<view class="footer-wrap">
<view class="footer">
<view class="item" @click="linkTo('/pages/me/contact')">
<up-icon name="email" size="24" />
联系客服
</view>
<view class="item" @click="linkTo('/pages/me/feedback')">
<up-icon name="edit-pen" size="24" />
意见反馈
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { selectHelpList } from '@/api/me/me.js';
import { linkTo } from '@/utils/app.js';
//
const list = ref([]);
async function selectHelpListAjax() {
try {
const res = await selectHelpList({ types: 1 });
list.value = res;
} catch (error) {
console.log(error);
}
}
function toHelpDetal(item) {
uni.setStorageSync('helpDetail', item);
linkTo('/pages/me/help_center_detail');
}
onLoad(() => {
selectHelpListAjax();
});
</script>
<style scoped lang="scss">
.footer-wrap {
padding: 28upx;
width: 100%;
position: fixed;
bottom: 0;
left: 0;
z-index: 99;
.footer {
background-color: #f5f5f5;
height: 108upx;
display: flex;
border-radius: 20upx;
.item {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
position: relative;
&:first-child {
&::after {
content: '';
height: 20upx;
border-right: 1upx solid #999;
position: absolute;
right: 0;
top: 50%;
margin-top: -10upx;
}
}
}
}
}
</style>

View File

@ -0,0 +1,27 @@
<template>
<view class="container">
<rich-text :nodes="content.helpWordContent"></rich-text>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const content = ref('');
onLoad(() => {
content.value = uni.getStorageSync('helpDetail');
const regex = new RegExp('img', 'gi');
content.value.helpWordContent = content.value.helpWordContent.replace(regex, `img style="width:100%;"`);
uni.setNavigationBarTitle({
title: content.value.helpWordTitle
});
});
</script>
<style scoped lang="scss">
.container {
padding: 28upx;
}
</style>

397
pages/me/index.vue Normal file
View File

@ -0,0 +1,397 @@
<template>
<view class="container">
<view class="u-status-bar"></view>
<view class="top-bg"></view>
<view class="content">
<view class="user-info">
<view class="logo-wrap">
<view class="logo">
<image class="img" src="/static/logo.png" mode="widthFix"></image>
</view>
<view class="quick-menu">
<image class="icon" src="/static/me/logo_btn1.png" mode="aspectFit" @click="linkTo('/pages/share/index', true)"></image>
<image class="icon" src="/static/me/logo_btn2.png" mode="aspectFit" @click="linkTo('/pages/me/message', true)"></image>
<image class="icon" src="/static/me/logo_btn3.png" mode="aspectFit" @click="linkTo('/pages/me/contact', true)"></image>
</view>
</view>
<view class="top" @click="linkTo(userInfo.phone?'/pages/me/userInfo':'/pages/login/login')">
<image class="avatar" :src="userInfo.avatar || '/static/default_avatar.png'" mode="aspectFill"></image>
<view class="info-wrap">
<view class="name">{{ userInfo.phone || '请登录' }}</view>
</view>
</view>
<view class="btm">
<navigator class="item" hover-class="none" url="/pages/watching_history/watching_history?type=2">
<view class="title">我的喜欢</view>
<view class="num">{{ likeData.likeCount }}</view>
</navigator>
<navigator class="item" hover-class="none" url="/pages/watching_history/watching_history?type=1">
<view class="title">我的追剧</view>
<view class="num">{{ likeData.collectCount }}</view>
</navigator>
<view class="item" v-if="$common.isIosExamine" @click="linkTo('/pages/me/withdraw/index',true)">
<view class="title">我的红包</view>
<view class="num">{{ amount || 0 }}</view>
</view>
</view>
</view>
<view class="card-wrap">
<view class="gold-wrap">
<view class="left">
<image class="icon" src="/static/me/gold_icon.png" mode="aspectFit"></image>
<view class="num">{{ gold }}</view>
</view>
<div @click="linkTo('/pages/me/gold_record', true)">
<view class="btn">金币明细</view>
</div>
</view>
<div class="title-wrap" @click="linkTo('/pages/watching_history/watching_history?type=3', true)">
<view class="a">
<view class="t">观看历史</view>
<up-icon name="arrow-right"></up-icon>
</view>
</div>
<view class="history-list">
<view
class="item"
v-for="item in recordThree"
:key="item.id"
@click="linkTo(`/pages/video/detail?courseId=${item.courseId}&courseDetailsId=${item.courseDetailsId}`)"
>
<image class="cover" :src="item.titleImg" mode="aspectFill"></image>
<view class="name">{{ item.title }}</view>
<view class="t">看到{{ item.courseDetailsName }}</view>
</view>
</view>
<view class="empty" style="padding-bottom: 20px" v-if="!recordThree.length">
<emprty-card></emprty-card>
</view>
</view>
<view class="card-wrap">
<view class="menu-list">
<view class="item" @click="toTask">
<image class="icon" src="/static/me/menu_icon1.png" mode="aspectFit"></image>
<view class="name">任务中心</view>
</view>
<view class="item" @click="linkTo('/pages/me/setting')">
<image class="icon" src="/static/me/menu_icon2.png" mode="aspectFit"></image>
<view class="name">设置中心</view>
</view>
<view class="item" @click="linkTo('/pages/me/feedback', true)">
<image class="icon" src="/static/me/menu_icon3.png" mode="aspectFit"></image>
<view class="name">意见反馈</view>
</view>
<view class="item" @click="linkTo('/pages/me/help_center')">
<image class="icon" src="/static/me/menu_icon4.png" mode="aspectFit"></image>
<view class="name">帮助中心</view>
</view>
<view class="item" @click="linkTo('/pages/login/download')">
<image class="icon" src="/static/me/menu_icon5.png" mode="aspectFit"></image>
<view class="name">检查更新</view>
</view>
<view class="item" @click="linkTo('/pages/me/agreement')">
<image class="icon" src="/static/me/menu_icon6.png" mode="aspectFit"></image>
<view class="name">用户协议</view>
</view>
<!-- <view class="item">
<image class="icon" src="/static/me/menu_icon7.png" mode="aspectFit"></image>
<view class="name">关于我们</view>
</view> -->
<view class="item" @click="linkTo('/pages/me/privacy')">
<image class="icon" src="/static/me/menu_icon8.png" mode="aspectFit"></image>
<view class="name">隐私政策</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { onLoad,onShow, onPullDownRefresh } from '@dcloudio/uni-app';
import { selectByUserId, collectVideoSummary, selectUserMoney } from '@/api/me/me.js';
import { linkTo } from '@/utils/app.js';
import {
useCommonStore
} from '@/store/common.js'
const $common = useCommonStore()
const userInfo = ref({});
//
const recordThree = ref([]);
onShow(()=>{
// ios
$common.init()
})
async function selectByUserIdAjax() {
try {
const res = await selectByUserId({ page: 1, limit: 3, classify: 3 });
recordThree.value = res.records;
} catch (error) {
console.log(error);
}
}
//
const likeData = reactive({
likeCount: 0,
collectCount: 0
});
async function collectVideoSummaryAjax() {
try {
const res = await collectVideoSummary();
likeData.likeCount = res.likeCount;
likeData.collectCount = res.collectCount;
} catch (error) {
console.log(error);
}
}
//
const gold = ref(0);
const amount = ref(0);
async function selectUserMoneyAjax() {
try {
const res = await selectUserMoney();
gold.value = res.money;
amount.value = res.amount;
} catch (error) {
console.log(error);
}
}
//
function toTask() {
uni.switchTab({
url: '/pages/task/index'
});
}
onPullDownRefresh(async () => {
await selectByUserIdAjax();
await collectVideoSummaryAjax();
await selectUserMoneyAjax();
userInfo.value = uni.getStorageSync('userInfo');
setTimeout(() => {
uni.stopPullDownRefresh();
}, 500);
});
onShow(() => {
if(uni.getStorageSync('token')){
selectByUserIdAjax();
collectVideoSummaryAjax();
selectUserMoneyAjax();
userInfo.value = uni.getStorageSync('userInfo');
}
});
</script>
<style>
page {
background: #f5f7ff;
}
</style>
<style scoped lang="scss">
$bgColor: #f5f7ff;
.container {
font-size: 28upx;
color: #333;
}
.top-bg {
width: 100%;
height: 50%;
position: fixed;
top: 0;
left: 0;
background: linear-gradient(90deg, #ffe5ea 0, #e4f5fb 49%, #fff0ee);
&::after {
content: '';
height: 50%;
width: 100%;
background: linear-gradient(to bottom, transparent, $bgColor);
position: absolute;
bottom: 0;
left: 0;
}
}
.content {
padding: 28upx;
position: relative;
.user-info {
.logo-wrap {
display: flex;
align-items: center;
justify-content: space-between;
.logo {
width: 160upx;
.img {
width: 100%;
display: block;
}
}
.quick-menu {
display: flex;
gap: 20upx;
.icon {
$size: 60upx;
width: $size;
height: $size;
}
}
}
.top {
display: flex;
align-items: center;
padding-top: 40upx;
.avatar {
$size: 94upx;
width: $size;
height: $size;
border-radius: 50%;
margin-right: 12upx;
}
.info-wrap {
flex: 1;
display: flex;
flex-direction: column;
font-size: 32upx;
}
}
.btm {
display: flex;
padding: 40upx 0;
.item {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.title {
font-size: 28upx;
}
.num {
font-weight: bold;
display: flex;
justify-content: center;
}
}
}
}
}
.card-wrap {
background: #fff;
border-radius: 16upx;
overflow: hidden;
margin-bottom: 28upx;
.gold-wrap {
background: #f2b5b5;
display: flex;
justify-content: space-between;
padding: 20upx 28upx;
position: relative;
// &::after {
// $size: 40upx;
// content: '';
// width: $size;
// height: $size;
// border-radius: 8upx;
// transform: rotate(45deg);
// position: absolute;
// left: 50%;
// margin-left: $size * 0.5 * -1;
// bottom: $size * 0.3 * -1;
// background: inherit;
// }
.left {
display: flex;
align-items: center;
.icon {
$size: 52upx;
width: $size;
height: $size;
margin-right: 20upx;
}
.num {
color: #fff;
font-size: 32upx;
}
}
.btn {
color: #977641;
background: linear-gradient(90deg, #fee7bc 0%, #fdcc89 100%);
width: 144upx;
height: 56upx;
border-radius: 56upx;
display: flex;
align-items: center;
justify-content: center;
font-size: 24upx;
}
}
.title-wrap {
padding: 28upx;
.a {
display: flex;
align-items: center;
justify-content: space-between;
.t {
font-size: 28upx;
}
}
}
.history-list {
padding: 0 28upx 28upx;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 1fr;
grid-column-gap: 28upx;
grid-row-gap: 28upx;
.item {
.cover {
width: 100%;
height: 280upx;
border-radius: 20upx;
}
.name {
font-size: 28upx;
width: 160upx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.t {
color: #999;
font-size: 24upx;
}
}
}
.menu-list {
display: flex;
flex-wrap: wrap;
padding: 28upx 0 0;
.item {
flex: 0 0 25%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-bottom: 32upx;
.icon {
$size: 56upx;
width: $size;
height: $size;
}
.name {
font-size: 24upx;
margin-top: 8upx;
color: #333;
}
}
}
}
</style>

99
pages/me/message.vue Normal file
View File

@ -0,0 +1,99 @@
<!-- 消息中心 -->
<template>
<view class="container">
<view v-if="data.msgList.length" class="list" v-for="(item,index) in data.msgList"
:key='index'>
<image class="icon" src="@/static/me/message.png" mode="aspectFit"></image>
<view class="item-right">
<view class="top">
<view class="title">{{item.title}}</view>
<view class="text-gray">{{item.createAt}}</view>
</view>
<view class="text-gray">{{item.content}}</view>
</view>
</view>
<emprty-card v-if="!data.msgList.length" />
</view>
</template>
<script setup>
import { reactive } from 'vue';
import { onLoad,onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
import { selectMessageByUserId } from '@/api/me/message.js';
let data = reactive({
page: 1,
limit: 10,
msgList: []
})
onLoad(() => {
getMsg()
})
async function getMsg() {
uni.showLoading({
title: '加载中'
})
let params = {
page: data.page,
limit: data.limit,
state: 5
}
let res = await selectMessageByUserId(params)
uni.hideLoading()
uni.stopPullDownRefresh();
if (data.page == 1) {
data.msgList = res.list
uni.stopPullDownRefresh();
return
}
data.msgList = [...data.msgList, ...res.list]
}
onReachBottom(() => {
data.page = data.page + 1;
getMsg()
})
onPullDownRefresh(() => {
data.page = 1;
data.msgList = []
getMsg()
})
</script>
<style lang="scss" scoped>
page {
background-color: white;
}
.container{
padding: 0 30rpx;
}
.list{
display: flex;
padding: 20rpx 0;
border-bottom: 1rpx solid #e4e7ed;
.icon{
width: 85rpx;
height: 85rpx;
}
.item-right{
width: 100%;
display: flex;
flex-direction: column;
margin-left: 30rpx;
font-size: 28rpx;
color: #333;
.top{
display: flex;
justify-content: space-between;
.title{
font-size: 32rpx;
font-weight: bold;
color: #333;
}
}
}
}
</style>

68
pages/me/privacy.vue Normal file
View File

@ -0,0 +1,68 @@
<template>
<view style="font-size: 14px;line-height: 26px;padding: 32upx;" class="home1 ">
<view style="font-size: 28upx;" v-html="data.content"></view>
<view class="btn-box u-flex u-row-center" v-if="!isLogin">
<view class="btn cancel" @click="cancel">拒绝</view>
<view class="btn" @click="back">同意</view>
</view>
</view>
</template>
<script setup>
import { reactive } from 'vue';
import { onLoad } from '@dcloudio/uni-app'
import {commonType} from '@/api/init.js';
let data = reactive({
content: '',
isLogin:false
})
onLoad(() => {
getGuize()
data.isLogin=uni.getStorageSync('token')?true:false
})
async function getGuize() {
let res = await commonType(155)
data.content = res.value
}
function cancel(){
// #ifdef H5
uni.navigateBack()
// #endif
// #ifdef APP
plus.runtime.quit();
// #endif
}
function back(){
uni.navigateBack()
}
</script>
<style scoped>
.btn {
width: 100%;
height: 42px;
line-height: 42px;
border-radius: 30px;
background: #ff7581;
color: #ffffff;
text-align: center;
}
.btn-box{
gap: 20px;
padding: 30rpx 130rpx;
}
.cancel{
background-color: #eee;
color: #999;
}
page{
/* background: #1c1b20; */
}
</style>

94
pages/me/setting.vue Normal file
View File

@ -0,0 +1,94 @@
<template>
<view class="container">
<view class="list">
<view class="item" @click="linkTo('/pages/login/bind',true)">
<view class="title">修改手机号</view>
<up-icon name="arrow-right" />
</view>
<view class="item" @click="linkTo('/pages/me/help_center')">
<view class="title">帮助中心</view>
<up-icon name="arrow-right" />
</view>
<view class="item" @click="linkTo('/pages/me/feedback',true)">
<view class="title">意见反馈</view>
<up-icon name="arrow-right" />
</view>
<view class="item" @click="linkTo('/pages/me/agreement')">
<view class="title">用户协议</view>
<up-icon name="arrow-right" />
</view>
<view class="item" @click="linkTo('/pages/me/privacy')">
<view class="title">隐私协议</view>
<up-icon name="arrow-right" />
</view>
<view class="item" @click="logout" v-if="token">
<view class="title">退出登录</view>
<up-icon name="arrow-right" />
</view>
</view>
<view class="version">{{ version }}</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { linkTo } from '@/utils/app.js';
import { onLoad } from '@dcloudio/uni-app';
const version = ref('');
const token = ref('');
// 退
function logout() {
uni.showModal({
title: '注意',
content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
uni.clearStorageSync();
uni.reLaunch({
url: '/pages/login/login'
});
}
}
});
}
onLoad(() => {
token.value = uni.getStorageSync('token');
const systemInfo = uni.getSystemInfoSync();
//#ifdef APP-PLUS
version.value = systemInfo.appWgtVersion;
//#endif
// #ifdef H5
version.value = systemInfo.appVersion;
// #endif
});
</script>
<style scoped lang="scss">
.container {
font-size: 28upx;
color: #555;
}
.list {
padding-bottom: 120upx;
.item {
padding: 32upx 28upx;
border-bottom: 1upx solid #efefef;
display: flex;
align-items: center;
justify-content: space-between;
}
}
.version {
width: 100%;
height: 120upx;
display: flex;
justify-content: center;
position: fixed;
bottom: 0;
left: 0;
color: #999;
}
</style>

174
pages/me/userInfo.vue Normal file
View File

@ -0,0 +1,174 @@
<template>
<view class="container">
<up-cell-group>
<up-cell title="头像">
<template #value>
<image :src="data.userInfo.avatar?data.userInfo.avatar:'../../static/default/avatar.png'" mode="aspectFill" @click="uploadImg"
style="width: 111rpx;height: 111rpx;border-radius: 50%;"></image>
</template>
</up-cell>
<up-cell title="用户名">
<template #value>
<input v-model="data.userInfo.userName" align="right" placeholder="请输入用户名" />
</template>
</up-cell>
<!-- <up-cell title="手机">
<template #value>
<input v-model="data.userInfo.phone" align="right" placeholder="请输入联系电话" />
</template>
</up-cell> -->
</up-cell-group>
<view class="save" @click="save">保存</view>
</view>
</template>
<script setup>
import { reactive } from 'vue';
import { onShow} from '@dcloudio/uni-app'
import config from '@/commons/config.js';
import { selectUserById, updateUsers } from '@/api/user/user.js';
let data = reactive({
userInfo: {
avatar: '',
userName: '',
phone: '',
}
})
onShow(() => {
getUserInfo()
})
/**
* 获取个人信息
*/
async function getUserInfo () {
let res = await selectUserById()
data.userInfo = res
}
/**
* 上传头像
*/
function uploadImg () {
var url = null;
uni.showActionSheet({
// itemList
itemList: ["查看头像", "从相册选择图片"],
success(e) {
var index = e.tapIndex
console.log(index)
if (index === 0) {
//
//
console.log()
let url = data.userInfo.avatar||'../../static/default/avatar.png';
let arr = []
arr.push(url)
uni.previewImage({
//
urls: arr
})
} else if (index === 1) {
uni.chooseImage({
count: 1, //9
sizeType: ['original', 'compressed'], //
sourceType: ['album'], //
success: function(res) {
uni.showLoading({
title: '上传中...'
});
uni.uploadFile({
url: config.baseApiUrl + 'alioss/upload',
filePath: res.tempFilePaths[0],
name: 'file',
success: uploadFileRes => {
url = JSON.parse(uploadFileRes.data);
console.log(url)
data.userInfo.avatar = url.data
uni.hideLoading();
}
});
}
});
}
}
})
}
/**
* 保存
*/
function save () {
if (!data.userInfo.userName) {
uni.showToast({
title: "用户名不能为空",
icon: "none"
})
return
}
// if (!data.userInfo.phone) {
// uni.showToast({
// title: "",
// icon: "none"
// })
// return
// }
// if (checkPhone(data.userInfo.phone) == false) {
// uni.showToast({
// title: "",
// icon: "none"
// })
// return
// }
uni.showModal({
title: '温馨提示',
content: '确定保存信息',
confirmColor: '#ff7581',
success: async e => {
if (e.confirm) {
let res = await updateUsers({
userName: data.userInfo.userName,
avatar: data.userInfo.avatar,
// phone: data.userInfo.phone,
})
uni.showToast({
title: '保存成功',
icon: "none"
})
let userInfo = uni.getStorageSync('userInfo');
userInfo.userName = data.userInfo.userName
userInfo.avatar = data.userInfo.avatar
// userInfo.phone = data.userInfo.phone
uni.setStorageSync('userInfo', userInfo);
setTimeout(function() {
uni.navigateBack()
}, 1000)
}
}
});
}
function checkPhone(phone) {
return /^1[3456789]\d{9}$/.test(phone);
}
</script>
<style style="sass" scoped>
.save{
color: #FFFFFF;
background: #ff7581;
text-align: center;
width: 234px;
height: 41px;
font-size: 14px;
line-height: 41px;
margin: 0 auto;
border-radius: 20px;
margin-top: 78px;
}
</style>

View File

@ -0,0 +1,128 @@
<template>
<view class="containerView">
<up-cell-group :border="false">
<up-cell title="收款人姓名">
<template #right-icon> <up-input border="none" v-model="data.zhiFuBaoName" placeholder="请输入支付宝收款人姓名"></up-input> </template>
</up-cell>
<up-cell title="支付宝账号">
<template #right-icon> <up-input border="none" v-model="data.zhiFuBao" placeholder="请输入要绑定的支付宝手机号"></up-input> </template>
</up-cell>
</up-cell-group>
<button class="confirm-btn" @click="toLogin"
:disabled="data.logining">绑定账户</button>
<view style="font-size: 24upx;color: #999999;padding: 0 15rpx;margin-top: 32rpx;margin-bottom: 10rpx;">请正确填写收款人的支付宝账户和真实的收款人姓名</view>
<view style="font-size: 24upx;color: #999999;padding: 0 15rpx">否则将无法正常收款请须知</view>
</view>
</template>
<script setup>
import { reactive, nextTick, ref } from 'vue';
import { onReady,onLoad,onShow } from '@dcloudio/uni-app'
import { updateUser } from '@/api/me/withdraw.js';
import { commonType } from '@/api/init.js';
let data = reactive({
zhiFuBao: null,
zhiFuBaoName: null,
logining: false
})
onLoad(() => {
data.zhiFuBao = uni.getStorageSync('userInfo').zhiFuBao;
data.zhiFuBaoName = uni.getStorageSync('userInfo').zhiFuBaoName;
})
function inputChange(e) {
const key = e.currentTarget.dataset.key;
data[key] = e.detail.value;
}
async function toLogin() {
if (!data.zhiFuBaoName) {
uni.showToast({
title: '请设置收款人姓名',
icon: 'none'
})
} else if (!data.zhiFuBao) {
uni.showToast({
title: '请设置收款人支付宝账号',
icon: 'none'
})
} else {
data.logining = true
let res = await updateUser({
zhiFuBao: data.zhiFuBao,
certName: data.zhiFuBaoName,
})
if( res) {
data.logining = false
let userInfo = uni.getStorageSync('userInfo')
userInfo.zhiFuBao = data.zhiFuBao
userInfo.zhiFuBaoName = data.zhiFuBaoName
uni.setStorageSync('userInfo', userInfo)
uni.showToast({
title: '修改成功',
icon: 'none',
complete() {
setTimeout(function() {
uni.navigateBack();
}, 1000)
}
})
}
}
}
</script>
<style lang='scss'>
page {
background: #FFFFFF;
}
.containerView {
padding:30rpx;
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
background: #ffffff;
}
.confirm-btn1 {
width: 300px;
height: 42px;
line-height: 42px;
border-radius: 30px;
margin-top: 70upx;
/* background: whitesmoke; */
background: #ff7581;
color: #FFFFFF;
font-size: 32rpx;
&:after {
border: none;
}
}
.confirm-btn {
width: 300px;
height: 42px;
line-height: 42px;
border-radius: 30px;
margin-top: 70upx;
background: #ff7581;
color: #ffffff;
font-size: 32rpx;
border: none;
&:after {
border: none;
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More