Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0961aa610b | ||
|
|
545d4259c4 | ||
|
|
1ffa754dbe | ||
|
|
96d86f237d | ||
|
|
8e64ecebd1 | ||
|
|
98f912f113 | ||
|
|
732aa7686c | ||
|
|
b2e40e7011 | ||
|
|
d7a18f9c01 | ||
|
|
c5307513cc | ||
|
|
a5d073e798 | ||
|
|
9639c2f270 | ||
|
|
cf6b26e565 | ||
|
|
9171275d3d | ||
|
|
2a2ce2eff6 | ||
|
|
b6635a5d5c | ||
|
|
da4cd2238e | ||
|
|
fb3120d818 | ||
|
|
5f496038c5 | ||
|
|
146f9ddc88 | ||
|
|
6abad0df4d | ||
|
|
47ac7d1fbc | ||
|
|
25e4686e30 | ||
|
|
b476305e30 | ||
|
|
518c898882 | ||
|
|
09dc98db16 | ||
|
|
ea98ba45ca | ||
|
|
2e572639b0 | ||
|
|
4a0ea9b43c | ||
|
|
6d762c5367 | ||
|
|
2349faa1bc | ||
|
|
4cdb595a2a | ||
|
|
5552236952 | ||
|
|
d2f516e1ae | ||
|
|
cb39246850 | ||
|
|
18484f7ee8 | ||
|
|
2ca7f48131 | ||
|
|
f491e87d6a | ||
|
|
6f8e82e6cf | ||
|
|
6c95891476 | ||
|
|
76e7ed8f25 | ||
|
|
f6b2eb6925 | ||
|
|
c23e7ac3d0 | ||
|
|
ca1926a732 | ||
|
|
a1995c88e8 | ||
|
|
27260f4a75 | ||
|
|
0c5ef4a085 | ||
|
|
3dad154ca0 | ||
|
|
e727974806 | ||
|
|
ab709267be | ||
|
|
51cd8908ec | ||
|
|
56182dfbe9 | ||
|
|
6b6fa0c257 | ||
|
|
ff6769001d | ||
|
|
9df0194aeb | ||
|
|
b741a1d148 | ||
|
|
f03fcf1373 | ||
|
|
5a66e71809 | ||
|
|
e93322959e | ||
|
|
4a8a92f323 | ||
|
|
ba56d9843f | ||
|
|
eb3d0ff6b0 | ||
|
|
aa571f25f9 | ||
|
|
49e8b9f5c3 | ||
|
|
6af76a20f3 | ||
|
|
55131bf0c3 | ||
|
|
f3c7387650 | ||
|
|
b2d030f96b | ||
|
|
97711bad3e | ||
|
|
29584a108b | ||
|
|
1432ec5996 | ||
|
|
9521d4b557 | ||
|
|
27af994667 | ||
|
|
dbc192faa7 | ||
|
|
5f8ed35521 | ||
|
|
b42c151585 | ||
|
|
3e2749672e | ||
|
|
07098527ff | ||
|
|
cb29c2c0aa | ||
|
|
4be2b441f5 | ||
|
|
2cd4095035 | ||
|
|
80b2bb6f5e | ||
|
|
9b6d1a9a97 | ||
|
|
735dc8c373 | ||
|
|
fdca229a77 | ||
|
|
fd8f9a6857 | ||
|
|
9f5f4816d3 | ||
|
|
089e0197cd | ||
|
|
81cd02bbee | ||
|
|
1cfd974fed | ||
|
|
82a82a4bed | ||
|
|
75e7e58b8d | ||
|
|
b6dd2ae1eb | ||
|
|
85441704cb | ||
|
|
089191e95d | ||
|
|
9f33e44db0 | ||
|
|
ed3d370de2 | ||
|
|
36289d526c | ||
|
|
7268659193 | ||
|
|
b1d6e1d687 | ||
|
|
89e86b84fe | ||
|
|
77574e099a | ||
|
|
5e6adced12 | ||
|
|
4fef5c5f0e | ||
|
|
1bff364d38 | ||
|
|
abf1235916 | ||
|
|
2c4ad9f78a | ||
|
|
75c5203c90 | ||
|
|
a514de68b3 | ||
|
|
522591c486 | ||
|
|
263eb74695 | ||
|
|
53920d2efa | ||
|
|
a0f85bf157 | ||
|
|
adc521022f | ||
|
|
356193aab5 | ||
|
|
07d167c624 | ||
|
|
01ee048a22 | ||
|
|
512d87c6f2 | ||
|
|
af0643ce93 | ||
|
|
9d333085cb | ||
|
|
d37b848307 | ||
|
|
28faf73c62 | ||
|
|
f10c9ec16c | ||
|
|
ef3a82ee14 | ||
|
|
47f4295316 | ||
|
|
8a6ec1cb02 | ||
|
|
edf158ec2c | ||
|
|
f4adfde90b | ||
|
|
283449fc3d | ||
|
|
e66e1c6eac | ||
|
|
ea8ea9e744 | ||
|
|
c8a95ef3ec | ||
|
|
bf75dc2768 | ||
|
|
0575bd56b0 | ||
|
|
8154108fe9 | ||
|
|
7f1504214c | ||
|
|
c6b55dc90b | ||
|
|
ed7258b577 | ||
|
|
6c0ba7d585 | ||
|
|
154a706af4 | ||
|
|
fc396021c6 | ||
|
|
532503b65b | ||
|
|
b22cdae4fe | ||
|
|
42bcab7f28 | ||
|
|
4db992d3fa | ||
|
|
e9a91b84fc | ||
|
|
e13eedc2c2 | ||
|
|
be5db900a0 | ||
|
|
34274cbaa8 | ||
|
|
438897b9d3 | ||
|
|
58af434a90 | ||
|
|
83daf7f7c2 | ||
|
|
35c75338ee | ||
|
|
19d3cb33e2 | ||
|
|
5feab41b3d | ||
|
|
51ba185e81 | ||
|
|
92b9820f20 | ||
|
|
cc9f31f8c3 | ||
|
|
374ccf43fd | ||
|
|
fd83bcf02a | ||
|
|
b093f99ab5 | ||
|
|
e53cb63ce4 | ||
|
|
a9a522880d | ||
|
|
e7ba7a82e3 | ||
|
|
7a3f98e5fc | ||
|
|
a9739208f8 | ||
|
|
bb1da04177 | ||
|
|
15ce250c1b | ||
|
|
f7ec1badf7 | ||
|
|
2b5a06174f | ||
|
|
1fc3537bf4 | ||
|
|
e126981628 | ||
|
|
2eb1a1bf41 | ||
|
|
3099c8c491 | ||
|
|
1aa944e18c | ||
|
|
e635b91bb5 | ||
|
|
c7ea2f97ac | ||
|
|
965b97dae7 | ||
|
|
c78a849c96 | ||
|
|
a2dec947a2 | ||
|
|
aaad12c50e | ||
|
|
44052b22c3 | ||
|
|
196a1b2235 | ||
|
|
1bc75b2ff5 | ||
|
|
b98f848be1 | ||
|
|
ce81110bb3 | ||
|
|
c9434b9ec9 | ||
|
|
d1681ec2d5 | ||
|
|
eae8f3c174 | ||
|
|
7f5970d741 | ||
|
|
ececc6f67c | ||
|
|
77306a54e7 | ||
|
|
bd07762a10 | ||
|
|
1b385d728a | ||
|
|
8b73d488ca | ||
|
|
59c6613102 | ||
|
|
9add242540 | ||
|
|
d97cc41f42 | ||
|
|
dfe19ca710 | ||
|
|
d716bc4619 | ||
|
|
0b9e8a39aa | ||
|
|
20f937a4ed | ||
|
|
a2b0942d88 | ||
|
|
f67e6a7f54 | ||
|
|
3d7f63868f | ||
|
|
8977504147 | ||
|
|
0b9d7a8808 | ||
|
|
1879a0b464 | ||
|
|
f4cc8def91 | ||
|
|
2e423e9748 | ||
|
|
9fc054a301 | ||
|
|
2ea027a6e0 | ||
|
|
508bd9cbd7 | ||
|
|
d221f277a1 | ||
|
|
e289c10270 | ||
|
|
4c6a8077aa | ||
|
|
c8feb58a46 | ||
|
|
a95a04085b | ||
|
|
7baec78c02 | ||
|
|
9399a3e223 | ||
|
|
39440c1e67 | ||
|
|
b630d26d4b | ||
|
|
72628f7e1c | ||
|
|
d9efd4e2e6 | ||
|
|
166030e3b8 | ||
|
|
a4a8548b5a | ||
|
|
9c03966e12 | ||
|
|
793252e4aa | ||
|
|
760dad0436 | ||
|
|
3355f5e853 | ||
|
|
6550441bc9 | ||
|
|
561529b01e | ||
|
|
4d92eaf5f9 | ||
|
|
950acf5275 | ||
|
|
f00a8052ea | ||
|
|
c3b1ff4b92 | ||
|
|
6b8a4fec29 | ||
|
|
2dfe61503f | ||
|
|
521553e2f5 | ||
|
|
f46bfc6ee1 | ||
|
|
03512800b2 | ||
|
|
ccd033b15a | ||
|
|
dabefbe21c | ||
|
|
8963ebc6af | ||
|
|
004294ae7c | ||
|
|
8815972188 | ||
|
|
ae3cef3e19 | ||
|
|
68d2fc4c24 | ||
|
|
c3f3c44e63 | ||
|
|
97802232a2 | ||
|
|
73dbe70305 | ||
|
|
a816582206 | ||
|
|
d2c4b9efc9 | ||
|
|
13986f3943 | ||
|
|
b7c38be5b3 | ||
|
|
d7eb74968a | ||
|
|
ddc54679fb | ||
|
|
7226eb8eb0 | ||
|
|
a0deb30075 | ||
|
|
e8cc7cb6c0 | ||
|
|
f6fefe3aef | ||
|
|
bfdb7bd00e | ||
|
|
d1162d8552 | ||
|
|
19ebbecb0c | ||
|
|
e4ca6b4e68 | ||
|
|
f478606ae4 | ||
|
|
b10f8d3181 | ||
|
|
71b9a502f3 | ||
|
|
d51ebca23b | ||
|
|
fb4220b46e | ||
|
|
d815fd5e3f | ||
|
|
c0105cc0fe | ||
|
|
a0e9ceb945 | ||
|
|
12332f0f30 | ||
|
|
eea2ad446f | ||
|
|
fe76f2fc90 | ||
|
|
87a6b962e7 | ||
|
|
829bea3861 |
No files matched your search
@@ -1,21 +1,31 @@
|
||||
# 版本号
|
||||
SHOPRO_VERSION = v1.8.3
|
||||
SHOPRO_VERSION=v2.3.0
|
||||
|
||||
# 后端接口 - 正式环境(通过 process.env.NODE_ENV = development)
|
||||
SHOPRO_BASE_URL = http://api-dashboard.yudao.iocoder.cn
|
||||
# 后端接口 - 正式环境(通过 process.env.NODE_ENV 非 development)
|
||||
SHOPRO_BASE_URL=http://api-dashboard.yudao.iocoder.cn
|
||||
|
||||
# 后端接口 - 测试环境(通过 process.env.NODE_ENV 非 development)
|
||||
SHOPRO_DEV_BASE_URL = http://127.0.0.1:48080
|
||||
# 后端接口 - 测试环境(通过 process.env.NODE_ENV = development)
|
||||
SHOPRO_DEV_BASE_URL=http://127.0.0.1:48080
|
||||
### SHOPRO_DEV_BASE_URL = http://yunai.natapp1.cc
|
||||
|
||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
|
||||
SHOPRO_UPLOAD_TYPE=server
|
||||
|
||||
# 后端接口前缀(一般不建议调整)
|
||||
SHOPRO_API_PATH = /app-api
|
||||
SHOPRO_API_PATH=/app-api
|
||||
|
||||
# 后端 websocket 接口前缀
|
||||
SHOPRO_WEBSOCKET_PATH=/infra/ws
|
||||
|
||||
# 开发环境运行端口
|
||||
SHOPRO_DEV_PORT = 3000
|
||||
SHOPRO_DEV_PORT=3000
|
||||
|
||||
# 客户端静态资源地址 空=默认使用服务端指定的CDN资源地址前缀 | local=本地 | http(s)://xxx.xxx=自定义静态资源地址前缀
|
||||
SHOPRO_STATIC_URL = https://file.sheepjs.com
|
||||
SHOPRO_STATIC_URL=http://test.yudao.iocoder.cn
|
||||
### SHOPRO_STATIC_URL = https://file.sheepjs.com
|
||||
|
||||
# 是否开启直播 1 开启直播 | 0 关闭直播 (小程序官方后台未审核开通直播权限时请勿开启)
|
||||
SHOPRO_MPLIVE_ON = 0
|
||||
SHOPRO_MPLIVE_ON=0
|
||||
|
||||
# 租户ID 默认 1
|
||||
SHOPRO_TENANT_ID=1
|
||||
@@ -5,7 +5,6 @@ deploy.sh
|
||||
.hbuilderx/
|
||||
.vscode/
|
||||
**/.DS_Store
|
||||
.env
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
*.keystore
|
||||
|
||||
+8
-8
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "芋道商城",
|
||||
"appid": "__UNI__082C0BA",
|
||||
"appid": "__UNI__460BC4C",
|
||||
"description": "基于 uni-app + Vue3 技术驱动的在线商城系统,内含诸多功能与丰富的活动,期待您的使用和反馈。",
|
||||
"versionName": "1.8.3",
|
||||
"versionCode": 183,
|
||||
"versionName": "2.1.0",
|
||||
"versionCode": "183",
|
||||
"transformPx": false,
|
||||
"app-plus": {
|
||||
"usingComponents": true,
|
||||
@@ -57,7 +57,6 @@
|
||||
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
|
||||
"<uses-permission android:name=\"android.permission.SEND_SMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
|
||||
@@ -185,11 +184,12 @@
|
||||
"versionCode": 100
|
||||
},
|
||||
"mp-weixin": {
|
||||
"appid": "wx63c280fe3248a3e7",
|
||||
"appid": "wx66186af0759f47c9",
|
||||
"setting": {
|
||||
"urlCheck": false,
|
||||
"minified": true,
|
||||
"postcss": true
|
||||
"postcss": false,
|
||||
"es6": false
|
||||
},
|
||||
"optimization": {
|
||||
"subPackages": true
|
||||
@@ -217,8 +217,8 @@
|
||||
"h5": {
|
||||
"template": "index.html",
|
||||
"router": {
|
||||
"mode": "hash",
|
||||
"base": "./"
|
||||
"mode": "history",
|
||||
"base": "/"
|
||||
},
|
||||
"sdkConfigs": {
|
||||
"maps": {}
|
||||
|
||||
+2
-3
@@ -2,7 +2,7 @@
|
||||
"id": "shopro",
|
||||
"name": "shopro",
|
||||
"displayName": "芋道商城",
|
||||
"version": "1.0.1",
|
||||
"version": "2.3.0",
|
||||
"description": "芋道商城,一套代码,同时发行到iOS、Android、H5、微信小程序多个平台,请使用手机扫码快速体验强大功能",
|
||||
"scripts": {
|
||||
"prettier": "prettier --write \"{pages,sheep}/**/*.{js,json,tsx,css,less,scss,vue,html,md}\""
|
||||
@@ -88,13 +88,12 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@hyoga/uni-socket.io": "^1.0.1",
|
||||
"dayjs": "^1.11.7",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"luch-request": "^3.0.8",
|
||||
"pinia": "^2.0.33",
|
||||
"pinia-plugin-persist-uni": "^1.2.0",
|
||||
"qs-canvas": "^1.0.11",
|
||||
"weixin-js-sdk": "^1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
+35
-23
@@ -120,6 +120,17 @@
|
||||
"group": "商品"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "point",
|
||||
"style": {
|
||||
"navigationBarTitleText": "积分商品"
|
||||
},
|
||||
"meta": {
|
||||
"sync": true,
|
||||
"title": "积分商品",
|
||||
"group": "商品"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "list",
|
||||
"style": {
|
||||
@@ -307,6 +318,18 @@
|
||||
"title": "编辑地址"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "goods_details_store/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "自提门店"
|
||||
},
|
||||
"meta": {
|
||||
"auth": true,
|
||||
"sync": true,
|
||||
"title": "地址管理",
|
||||
"group": "用户中心"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "wallet/money",
|
||||
"style": {
|
||||
@@ -630,28 +653,17 @@
|
||||
"group": "营销活动"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "bargain/list",
|
||||
"style": {
|
||||
"navigationBarTitleText": "砍价列表"
|
||||
},
|
||||
"meta": {
|
||||
"sync": true,
|
||||
"title": "砍价列表",
|
||||
"group": "营销活动"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "bargain/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "砍价详情"
|
||||
},
|
||||
"meta": {
|
||||
"sync": true,
|
||||
"title": "砍价详情",
|
||||
"group": "营销活动"
|
||||
}
|
||||
}
|
||||
{
|
||||
"path": "point/list",
|
||||
"style": {
|
||||
"navigationBarTitleText": "积分商城"
|
||||
},
|
||||
"meta": {
|
||||
"sync": true,
|
||||
"title": "积分商城",
|
||||
"group": "营销活动"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -674,4 +686,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,920 +0,0 @@
|
||||
<!-- 砍价详情 -->
|
||||
<template>
|
||||
<!-- TODO @科举:按照项目的代码风格,调整下这个界面 -->
|
||||
<!-- TODO @科举:挪到 bargain/detail.vue 里 -->
|
||||
<!-- TODO @科举:尽量都迁移完;依赖数据的部分,通过直接在 state 写死状态,不用后端返回,跑通整个界面;不追求 100% 对,但是至少自己观感是 ok 的 -->
|
||||
<s-layout title='砍价详情'>
|
||||
<view class='bargain'>
|
||||
<!-- :class="startBargainUid !== userInfo.uid ? 'on' : ''" -->
|
||||
<view class="header">
|
||||
<navigator url="/pages/activity/bargainingList" hover-class="none">
|
||||
<view class="back" style='width: 234rpx;
|
||||
height: 54rpx;
|
||||
background: linear-gradient(233deg,#ffd169,#fe960f);
|
||||
opacity: 1;
|
||||
border-radius: 0 26rpx 26rpx 0;
|
||||
line-height: 54rpx;
|
||||
text-align: center;
|
||||
color: #6e3f00;
|
||||
font-size: 25rpx;'>
|
||||
<text class="iconfont icon-xiangzuo"></text> 返回砍价列表
|
||||
</view>
|
||||
</navigator>
|
||||
</view>
|
||||
<view class="pad30" style="padding-bottom: 30rpx;">
|
||||
<view class='wrapper'>
|
||||
<view class='pictxt acea-row row-between' @tap="goProduct"
|
||||
style='display:flex;box-sizing: border-box;'>
|
||||
<view class='pictrue'>
|
||||
<image :src='state.bargainInfo.picUrl' />
|
||||
</view>
|
||||
<view class='text acea-row row-column-around' style='margin-left: 10rpx;'>
|
||||
<view class='line1'>{{ state.bargainInfo.name }}</view>
|
||||
<view class="surplus">最低价:¥{{ fen2yuan(state.bargainInfo.bargainMinPrice) }}</view>
|
||||
<view class="surplus">剩余:{{ state.bargainInfo.stock }} {{state.bargainInfo.unitName}}</view>
|
||||
<view class='money font-color-red' style='color:red'>
|
||||
当前: ¥ <text class='num'>{{ fen2yuan(state.buyPrice) }}</text>
|
||||
</view>
|
||||
<view class="acea-row" style='display:flex'
|
||||
v-if="state.bargainInfo.endTime > new Date().getTime() && state.bargainInfo.stock > 0">
|
||||
<s-count-down :tipText="' '" :bgColor="state.bgColor" :dayText="':'" :hourText="':'"
|
||||
:minuteText="':'" :secondText="' '" :datatime="state.bargainInfo.endTime / 1000"
|
||||
:isDay="true" />
|
||||
<text style="font-size: 22rpx;margin-left: 4rpx;line-height: 36rpx;">后结束</text>
|
||||
</view>
|
||||
<view v-else-if="state.bargainInfo.endTime <= new Date().getTime()">
|
||||
<view style="font-size: 22rpx;" @tap='currentBargainUser'>已结束</view>
|
||||
</view>
|
||||
<view v-else-if="state.bargainInfo.stock <= 0">
|
||||
<view style="font-size: 22rpx;" @tap='currentBargainUser'>已售罄</view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="iconfont icon-jiantou iconfonts"></text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 砍价记录 -->
|
||||
<view class='title font-color acea-row row-center-wrapper'>
|
||||
<view class='pictrue'>
|
||||
<!-- TODO 芋艿:暂时不支持砍价功能,后续换到 cdn 加载图片 -->
|
||||
<!-- <image src='../static/zuo2.png'></image>-->
|
||||
</view>
|
||||
<view class="tits">
|
||||
<view class='titleCon'>砍价记录</view>
|
||||
<view class="line"></view>
|
||||
</view>
|
||||
<view class='pictrue on'>
|
||||
<!-- TODO 芋艿:暂时不支持砍价功能,后续换到 cdn 加载图片 -->
|
||||
<!-- <image src='../static/you2.png'></image>-->
|
||||
</view>
|
||||
</view>
|
||||
<view class='bargainGang borRadius14'>
|
||||
<view class='list' v-if="state.bargainUserHelpList.length > 0">
|
||||
<block v-for="(item, index) in state.bargainUserHelpList" :key='index'
|
||||
v-if="index < 3 || !state.couponsHidden">
|
||||
<view class='item acea-row row-between-wrapper'>
|
||||
<view class='pictxt acea-row row-between-wrapper'>
|
||||
<view class='pictrue'>
|
||||
<image :src='item.avatar' />
|
||||
</view>
|
||||
<view class='text'>
|
||||
<view class='name line1'>{{item.nickname}}</view>
|
||||
<view class='line1'>{{ formatDate(item.createTime) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class='money'>
|
||||
已砍 <text class="font-color-red">{{ fen2yuan(item.reducePrice) }}</text>元
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</block>
|
||||
<view class="open acea-row row-center-wrapper" @click="openTap"
|
||||
v-if="state.bargainUserHelpList.length > 3">
|
||||
{{state.couponsHidden?'展开更多':'关闭展开'}}
|
||||
<text class="iconfont" :class='state.couponsHidden ? "icon-xiangxia":"icon-xiangshang"' />
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="state.bargainUserHelpList.length === 0" class="contentNo">
|
||||
<text class="iconfont icon-xiaolian mr8"></text>
|
||||
暂无助力记录
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import BargainApi from '@/sheep/api/promotion/bargain'
|
||||
|
||||
const state = reactive({
|
||||
id: '',
|
||||
buyPrice: '',
|
||||
bargainInfo: {},
|
||||
bgColor: {
|
||||
'bgColor': '#333333',
|
||||
'Color': '#fff',
|
||||
'width': '44rpx',
|
||||
'timeTxtwidth': '16rpx',
|
||||
'isDay': true
|
||||
},
|
||||
bargainUserHelpList: [],
|
||||
couponsHidden: true,
|
||||
});
|
||||
|
||||
|
||||
async function getBargainDetails() {
|
||||
let {
|
||||
data,
|
||||
code
|
||||
} = await BargainApi.getBargainActivityDetail({
|
||||
id: state.id
|
||||
})
|
||||
if (code == 0) {
|
||||
state.bargainInfo = data;
|
||||
state.buyPrice = state.bargainInfo.bargainFirstPrice;
|
||||
}
|
||||
|
||||
}
|
||||
onLoad(function(options) {
|
||||
if (options.hasOwnProperty('id')) {
|
||||
options.id ? state.id = options.id : state.id = ''
|
||||
}
|
||||
getBargainDetails()
|
||||
})
|
||||
// 工具函数
|
||||
function fen2yuan(price) {
|
||||
return (price / 100.0).toFixed(2)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: red !important;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.userEvaluation {
|
||||
i {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.go {
|
||||
color: #E93323;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
margin-top: 26rpx;
|
||||
|
||||
.iconfont {
|
||||
font-size: 11px
|
||||
}
|
||||
}
|
||||
|
||||
.poster-pop {
|
||||
width: 594rpx;
|
||||
height: 850rpx;
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 999;
|
||||
top: 50%;
|
||||
margin-top: -466rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.close {
|
||||
text-align: center;
|
||||
margin-top: 55rpx;
|
||||
color: #fff;
|
||||
font-size: 52rpx;
|
||||
}
|
||||
|
||||
.save-poster {
|
||||
background-color: #df2d0a;
|
||||
font-size: :22rpx;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
height: 76rpx;
|
||||
line-height: 76rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.keep {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
font-size: 25rpx;
|
||||
margin-top: 25rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.canvas {
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.font_hui {
|
||||
color: #CCCCCC !important;
|
||||
}
|
||||
|
||||
.bg_qian {
|
||||
background-color: #F5F5F5 !important;
|
||||
}
|
||||
|
||||
.font-color-red {
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.huiBtn {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
width: 630rpx;
|
||||
height: 80rpx;
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
margin: 0 auto;
|
||||
background-color: #CCCCCC;
|
||||
box-shadow: 0 7rpx 0 #AAAAAA;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
.huifont {
|
||||
color: #CCCCCC;
|
||||
}
|
||||
|
||||
.buyBox {
|
||||
margin-top: 40rpx;
|
||||
|
||||
.on {
|
||||
width: 300rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 32rpx;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
}
|
||||
|
||||
.buyNow {
|
||||
background: linear-gradient(180deg, #FF8831 0%, #F11B09 100%);
|
||||
box-shadow: 0 7rpx 0 #C11100;
|
||||
}
|
||||
|
||||
.buyMore {
|
||||
background: linear-gradient(180deg, #FFCA52 0%, #FE960F 100%);
|
||||
box-shadow: 0 7rpx 0 #D87A00;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.mr8 {
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.contentNo {
|
||||
width: 100%;
|
||||
padding: 50rpx 15rpx;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
color: #AAAAAA;
|
||||
}
|
||||
|
||||
.generate-posters {
|
||||
width: 100%;
|
||||
height: 170rpx;
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 388;
|
||||
transform: translate3d(0, 100%, 0);
|
||||
transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
|
||||
border-top: 1rpx solid #eee;
|
||||
}
|
||||
|
||||
.generate-posters.on {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
.generate-posters .item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.generate-posters .item .iconfont {
|
||||
font-size: 80rpx;
|
||||
color: #5eae72;
|
||||
}
|
||||
|
||||
.generate-posters .item .iconfont.icon-haibao {
|
||||
color: #5391f1;
|
||||
}
|
||||
|
||||
.bargain .bargainGang {
|
||||
background-color: #fff;
|
||||
|
||||
.list {
|
||||
padding: 50rpx 30rpx 0 30rpx;
|
||||
}
|
||||
|
||||
.open {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.helpNo {
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
color: #AAAAAA;
|
||||
}
|
||||
}
|
||||
|
||||
.bargain .bargainGang .open .iconfont {
|
||||
font-size: 25rpx;
|
||||
margin: 5rpx 0 0 10rpx;
|
||||
}
|
||||
|
||||
.bargain .icon-xiangzuo {
|
||||
font-size: 24rpx;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.bargain .header {
|
||||
/* TODO 芋艿:此处原来采用base64 但是过长编辑到小程序卡死 目前采用网络地址 需解决 */
|
||||
background-image: url('https://huizhizao-1314830814.cos.ap-shanghai.myqcloud.com/huizhizao-1314830814/7e9bea1e8bbcd8a7a865a7703d65a1d0b25ec33a4b8d443698ff2e6eccf1300f.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
width: 100%;
|
||||
height: 340rpx;
|
||||
margin: 0 auto;
|
||||
padding-top: 20rpx;
|
||||
|
||||
.back {
|
||||
width: 235rpx;
|
||||
height: 54rpx;
|
||||
background: linear-gradient(233deg, #FFD169 0%, #FE960F 100%);
|
||||
opacity: 1;
|
||||
border-radius: 0px 27rpx 27rpx 0px;
|
||||
line-height: 54rpx;
|
||||
text-align: center;
|
||||
color: #6E3F00;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.bargain .header .pictxt {
|
||||
margin: 330rpx auto 0 auto;
|
||||
font-size: 26rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.bargain .header .pictxt .pictrue {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
|
||||
.bargain .header .pictxt .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid #fff;
|
||||
}
|
||||
|
||||
.bargain .header .pictxt .text {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.bargain .header .pictxt .text text {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.bargain .header .time {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAbgAAACmCAMAAACfv2reAAAAk1BMVEUAAAD/nSL/oCj/oCj/nSH/nSH/oCj/mhr/mhr/oCj/oCj/oCj/nSH/niT/mhr/mhr/oCj/mhr/oCj/oCj/mhr/niP/oCj/oCj/mhr/////oCj/mhr/nyT/w3f/rkf/rEL/pjT/tlr/xXv/uF3//vz/vmv/wXP/vWr/79r/1aD/05r/wXL/nB//5MH/+/X/t1r/5MP28hXaAAAAGXRSTlMABvndiVtUVPjkOC8Dk+DarKyQC+QH86amYv5b+wAAA6JJREFUeNrs3Nlu4kAQheEyGOywBkImcR8Sh7Avycz7P920G8l3MYtccko63wXc969GXuiS20XJ6ygF1SQdvyaRiL5kDKrZOBFtgxjID7tVRjVZ7Q45EA9EV4z5ntVqttqfEIuqBKevjGr3dUIiiqIZ9hkp2GMWiZ4Ocv5Oqljl6IieCQ4ZqThgInpG2GWkYoeR6EnBX0olK6SiB8hICSAlhjOE4YxiOKMYziiGM4rhjGI4o5TCIWA4PQhqzzcPGE4PMA9q3m0fAcPpKdfYk3o47z1gOD3Ae+A8qUfuLby/C4bTA5zXOPekHktvu11v12uG0wOc13jpybWi7ku75X6yOR43bwHD6QHegmK13U/+tF+6kZS6bVfls8RweoDPkqvS7pZ/lXTVNpvNkTtOW7nj/Gq7avFACrG7YOlt196W4fQA5zVeeu6CWLyu81rT3lP1VWWBV5WKgEVQeVX51Bu2nNcViR7890Of93EKVO7j+iFYJJ1iv/XlEj450QZ8BHJJv9hzHXn0n1M+q2ze9c8qpz7Zo7T9Z4+vdZoHyJV6Pllbin0XMVzzrg/37JO1xHl8kfoLAHIt5zHcb8FwRjGcUQxnFMMZdU84HrNq3jdSxXBjHmzUssPo9nA8Sty8Aya3h+Ph/caFw/s3h+O4jMbtMXtWDCcJTv8yqqQ/oKYMx5FQDSpHQumGGww5hK1e32EI23BwTziOPWzYOBFRDydRZ8JBo/VJR5NOJHeGI1MYziiGM4rhjGI4oxjOKIYziuGMYjijGM4ohjOK4YxiOKMYziiGM4rhjGI4oxjOKIYziuH+s0cHJAAAAACC/r9uR6AXnBI3JW5K3JS4KXFT4qbETYmbEjclbkrclLgpcVPipsRNiZsSNyVuStyUuClxU+KmxE2JmxI3JW5K3JS4KXFT4qbETYmbEjclbkrclLgpcVPipsRNiZsSNyVuStyUuClxU+KmxE2JmxI3JW5K3JS4KXFT4qbETYmbEjclbkrclLgpcVPipsRNiZsSNyVuStyUuClxtUdHJwzDUAxFZTs2xInBxLQf2n/QvrTQGSLQ+ZAGuKIcTpTDiXI4UQ4nyuFEOZwohxPlcKIcTpTDiXI4UQ4nyuFEOZwohxPlcKIcThQD3jEJJmSRzCixHSakkyyYsRdMyCA5UWPzAZNxZJIVaY/bXU7G8Q32AhpDvvqCPd7qIzM0hI0mZsPtHDQp48RPKzQZpeEv1Vky7fFymTXh9gGY1gZJcqJI8QAAAABJRU5ErkJggg==');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
width: 440rpx;
|
||||
height: 166rpx;
|
||||
margin: 0 auto;
|
||||
|
||||
font-size: 22rpx;
|
||||
text-align: center;
|
||||
padding-top: 11rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.bargain .header .time .red {
|
||||
color: #fc4141;
|
||||
}
|
||||
|
||||
.bargain .header .people {
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 20rpx;
|
||||
position: absolute;
|
||||
width: 85%;
|
||||
/* #ifdef MP */
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
top: 40rpx;
|
||||
/* #endif */
|
||||
/* #ifdef H5 */
|
||||
top: 58rpx;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.bargain .header .time text {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.bargain {
|
||||
.wrapper {
|
||||
margin-top: -100rpx;
|
||||
|
||||
.pictxt {
|
||||
width: 100%;
|
||||
height: 260rpx;
|
||||
background-color: #FFF5E6;
|
||||
padding: 20rpx;
|
||||
border-radius: 14rpx;
|
||||
}
|
||||
|
||||
.surplus {
|
||||
color: #999999;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background-image: url('../static/zhuangshi.png');
|
||||
background-size: 100% 100%;
|
||||
background-color: #fff;
|
||||
border-bottom-left-radius: 14rpx;
|
||||
border-bottom-right-radius: 14rpx;
|
||||
padding: 40rpx 0 70rpx 0;
|
||||
|
||||
.money {
|
||||
color: #333333;
|
||||
font-size: 36rpx;
|
||||
|
||||
.price {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.bargain .wrapper,
|
||||
{
|
||||
// background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAArIAAAF8CAYAAAAzc1jZAAAco0lEQVR4Xu3dW4zc513H4feddWynQU1FY69zKvZuysENPqx7SFFRU4JEi+ACCVUUiQsuqYQ4VIWCchEuoAIFqRdI5QrlgkNLqQpSJA5VSWkKqKK7DkKuqIQ3RnUTe40CJRSSNDt/ZEeF1LGTmdnffuP1PLntzPf3n2fm4tMoTnrzFwECBAgQIECAAIEdKNB34DN7ZAIECBAgQIAAAQJNyPoRECBAgAABAgQI7EgBIbsjvzYPTYAAAQIECBAgIGT9BggQIECAAAECBHakgJDdkV+bhyZAgAABAgQIEBCyfgMECBAgQIAAAQI7TuD8iaX3C9kd97V5YAIECBAgQIDA/AoMrfWNlUO/2frog0J2fn8HPjkBAgQIECBAYEcJDHfdtWfj5vHvt9Z//OKDC9kd9fV5WAIECBAgQIDAfApsHN73bW3vax8eenvnNwWE7Hz+FnxqAgQIECBAgMCOETj73be/ftdr9vx57/0tL35oIbtjvkIPSoAAAQIECBCYP4GzR26/Y/euvX819PY9l396ITt/vwefmAABAgQIECCwIwS+evdtd+7ac+MjrbXlKz2wkN0RX6OHJECAAAECBAjMl8CTxw4eHC0sfKa1tnS1Ty5k5+s34dMSIECAAAECBK55gSdOLL1h1Prne2t3vtzDCtlr/qv0gAQIECBAgACB+RG4+Ae7dr9m76NX+mdiL1cQsvPzu/BJCRAgQIAAAQLXtMC5I4s39Rtu+uvW+lsneVAhO4mS1xAgQIAAAQIECGyrwNDaro2V5Ydbbz806SEhO6mU1xEgQIAAAQIECGybwMbK0u8Nvf/0NAeE7DRaXkuAAAECBAgQIFAusHFi6UND6x+edljITivm9QQIECBAgAABAmUCF1aWfmTc2p+13kfTjgrZacW8ngABAgQIECBAoERg49jSG4eF/sXW2mtnGRSys6h5DwECBAgQIECAwJYETh1uu/fduPz3Q2srsw4J2VnlvI8AAQIECBAgQGBmgfPHlx9so/aBmQdaa0J2K3reS4AAAQIECBAgMLXAuZWD9/Q++nxrfWHqN7/oDUJ2K3reS4AAAQIECBAgMJXA0FrfWFn+Yuuz/yMF3zwoZKei92ICBAgQIECAAIGtCFw4tvST44X+B1vZELIVejYIECBAgAABAgSmEji/svx3rbe3T/Wmq7zY35GtULRBgAABAgQIECAwscCFo0vfubkwvre30duH3t7cW7974je/6IVCdhY17yFAgAABAgQIECgTePL4gX297b2v99G9rbd7W+vfNcm4kJ1EyWsIECBAgAABAgRiAufvPrTYb2jfP4zakdZGR/owvHPo/XWXP4CQjX0lDhEgQIAAAQIECMwiMLQ2unD0O44Ou0b39WF039CHt7bWv13IzqLpPQQIECBAgAABAq+qwLkTB98mZF/Vr8BxAgQIECBAgACBWQX6V+6448Y7z579n1kHvI8AAQIECBAgQIDAqyHQz60sf3bh61/70X1f/renX40HcJMAAQIECBAgQIDALAL9/InloQ3DF/ozT//g/i9d+K9ZRryHAAECBAgQIECAQFrghZC9+NcwPNqfefqHxWz6K3CPAAECBAgQIEBgFoH/D9kXavbT+1fX39Nb25xlzHsIECBAgAABAgQIpAQuC9mLf2N2+MiBtfVfSD2AOwQIECBAgAABAgRmEXhJyF4cGY0337fv5JmPzTLoPQQIECBAgAABAgQSAlcM2TYMX1/4xvjNt/zTmX9OPIQbBAgQIECAAAECBKYVuHLIttb6MPzDqbX173tXa89PO+r1BAgQIECAAAECBLZb4Kohe/HwMLRfP7B2+v7tfgj7BAgQIECAAAECBKYVeNmQbW3Y3BwPP3Dbycc/N+2w1xMgQIAAAQIECBDYToFXCNlLf1/2y//5tfWjb/yX9ux2PohtAgQIECBAgAABAtMITBCyl/4ZgwcW19Z/bZphryVAgAABAgQIECCwnQKThWxr3xi15+/Zt/qva9v5MLYJECBAgAABAgQITCowache/INfq59bO/229/qvfk1q63UECBAgQIAAAQLbKDBxyF56hvHw/sWT6x/dxucxTYAAAQIECBAgQGAigelCdhj+/blnn7vrzlNnn5po3YsIECBAgAABAgQIbJPAdCH7wr9b9ncOrJ3+2W16HrMECBAgQIAAAQIEJhKYOmR7a8+P2ub33rLqP187kbAXESBAgAABAgQIbIvADCE7fGW82T504LH1P9yWJzJKgAABAgQIECBAYAKBiUK2D+2r42H8yfG4f+LWf1z/297aMMG2lxAgQIAAAQIECBDYNoGXCdnhfBvaJ/swfHzfyccfFa/b9h0YJkCAAAECBAgQmEHgW0N2aBeGNv5UH/on/ubk+iP+nbEziHoLAQIECBAgQIBARKCfX1l6amjtU70PH9+/+vhnuv/gQQTeEQIECBAgQIAAga0J9FOH2+43fak9t7UZ7yZAgAABAgQIECCQFejZc64RIECAAAECBAgQqBEQsjWOVggQIECAAAECBMICQjYM7hwBAgQIECBAgECNgJCtcbRCgAABAgQIECAQFhCyYXDnCBAgQIAAAQIEagSEbI2jFQIECBAgQIAAgbCAkA2DO0eAAAECBAgQIFAjIGRrHK0QIECAAAECBAiEBYRsGNw5AgQIECBAgACBGgEhW+NohQABAgQIECBAICwgZMPgzhEgQIAAAQIECNQICNkaRysECBAgQIAAAQJhASEbBneOAAECBAgQIECgRkDI1jhaIUCAAAECBAgQCAsI2TC4cwQIECBAgAABAjUCQrbG0QoBAgQIECBAgEBYQMiGwZ0jQIAAAQIECBCoERCyNY5WCBAgQIAAAQIEwgJCNgzuHAECBAgQIECAQI2AkK1xtEKAAAECBAgQIBAWELJhcOcIECBAgAABAgRqBIRsjaMVAgQIECBAgACBsICQDYM7R4AAAQIECBAgUCMgZGscrRAgQIAAAQIECIQFhGwY3DkCBAgQIECAAIEaASFb42iFAAECBAgQIEAgLCBkw+DOESBAgAABAgQI1AgI2RpHKwQIECBAgAABAmEBIRsGd44AAQIECBAgQKBGQMjWOFohQIAAAQIECBAICwjZMLhzBAgQIECAAAECNQJCtsbRCgECBAgQIECAQFhAyIbBnSNAgAABAgQIEKgRELI1jlYIECBAgAABAgTCAkI2DO4cAQIECBAgQIBAjYCQrXG0QoAAAQIECBAgEBYQsmFw5wgQIECAAAECBGoEhGyNoxUCBAgQIECAAIGwgJANgztHgAABAgQIECBQIyBkaxytECBAgAABAgQIhAWEbBjcOQIECBAgQIAAgRoBIVvjaIUAAQIECBAgQCAsIGTD4M4RIECAAAECBAjUCAjZGkcrBAgQIECAAAECYQEhGwZ3jgABAgQIECBAoEZAyNY4WiFAgAABAgQIEAgLCNkwuHMECBAgQIAAAQI1AkK2xtEKAQIECBAgQIBAWEDIhsGdI0CAAAECBAgQqBEQsjWOVggQIECAAAECBMICQjYM7hwBAgQIECBAgECNgJCtcbRCgAABAgQIECAQFhCyYXDnCBAgQIAAAQIEagSEbI2jFQIECBAgQIAAgbCAkA2DO0eAAAECBAgQIFAjIGRrHK0QIECAAAECBAiEBYRsGNw5AgQIECBAgACBGgEhW+NohQABAgQIECBAICwgZMPgzhEgQIAAAQIECNQICNkaRysECBAgQIAAAQJhASEbBneOAAECBAgQIECgRkDI1jhaIUCAAAECBAgQCAsI2TC4cwQIECBAgAABAjUCQrbG0QoBAgQIECBAgEBYQMiGwZ0jQIAAAQIECBCoERCyNY5WCBAgQIAAAQIEwgJCNgzuHAECBAgQIECAQI2AkK1xtEKAAAECBAgQIBAWELJhcOcIECBAgAABAgRqBIRsjaMVAgQIECBAgACBsICQDYM7R4AAAQIECBAgUCMgZGscrRAgQIAAAQIECIQFhGwY3DkCBAgQIECAAIEaASFb42iFAAECBAgQIEAgLCBkw+DOESBAgAABAgQI1AgI2RpHKwQIECBAgAABAmEBIRsGd44AAQIECBAgQKBGQMjWOFohQIAAAQIECBAICwjZMLhzBAgQIECAAAECNQJCtsbRCgECBAgQIECAQFhAyIbBnSNAgAABAgQIEKgRELI1jlYIECBAgAABAgTCAkI2DO4cAQIECBAgQIBAjYCQrXG0QoAAAQIECBAgEBYQsmFw5wgQIECAAAECBGoEhGyNoxUCBAgQIECAAIGwgJANgztHgAABAgQIECBQIyBkaxytECBAgAABAgQIhAWEbBjcOQIECBAgQIAAgRoBIVvjaIUAAQIECBAgQCAsIGTD4M4RIECAAAECBAjUCAjZGkcrBAgQIECAAAECYQEhGwZ3jgABAgQIECBAoEZAyNY4WiFAgAABAgQIEAgLCNkwuHMECBAgQIAAAQI1AkK2xtEKAQIECBAgQIBAWEDIhsGdI0CAAAECBAgQqBEQsjWOVggQIECAAAECBMICQjYM7hwBAgQIECBAgECNgJCtcbRCgAABAgQIECAQFhCyYXDnCBAgQIAAAQIEagSEbI2jFQIECBAgQIAAgbCAkA2DO0eAAAECBAgQIFAjIGRrHK0QIECAAAECBAiEBYRsGNw5AgQIECBAgACBGgEhW+NohQABAgQIECBAICwgZMPgzhEgQIAAAQIECNQICNkaRysECBAgQIAAAQJhASEbBneOAAECBAgQIECgRkDI1jhaIUCAAAECBAgQCAsI2TC4cwQIECBAgAABAjUCQrbG0QoBAgQIECBAgEBYQMiGwZ0jQIAAAQIECBCoERCyNY5WCBAgQIAAAQIEwgJCNgzuHAECBAgQIECAQI2AkK1xtEKAAALine truncated
|
||||
// babackground-repeat: no-repeat;
|
||||
// background-size: 100% 100%;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
padding: 0 24rpx 10rpx 24rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.bargain .pictxt .pictrue {
|
||||
width: 220rpx;
|
||||
height: 220rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bargain .pictxt .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
|
||||
.bargain .pictxt .text {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
|
||||
.line1 {
|
||||
width: 324rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.bargain .pictxt .text .money {
|
||||
font-weight: bold;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.bargain .pictxt .text .money .num {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
.bargain .pictxt .text .successNum {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.bargain .cu-progress {
|
||||
overflow: hidden;
|
||||
height: 12rpx;
|
||||
background-color: #FDEAE8;
|
||||
width: 560rpx;
|
||||
height: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
margin: 20rpx auto;
|
||||
}
|
||||
|
||||
.bargain .cu-progress .bg-red {
|
||||
width: 0;
|
||||
height: 100%;
|
||||
transition: width 0.6s ease;
|
||||
border-radius: 20rpx;
|
||||
background-image: linear-gradient(to right, #ffa363 0%, #e93323 100%);
|
||||
}
|
||||
|
||||
.bargain .money {
|
||||
// font-size: 22rpx;
|
||||
// color: #999;
|
||||
// margin-top: 40rpx;
|
||||
|
||||
}
|
||||
|
||||
.bargain .bargainSuccess {
|
||||
font-size: 26rpx;
|
||||
color: #333333;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
image {
|
||||
width: 48rpx;
|
||||
height: 62rpx;
|
||||
margin-right: 18rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.bargain .bargainSuccess .iconfont {
|
||||
font-size: 45rpx;
|
||||
color: #54c762;
|
||||
padding-right: 18rpx;
|
||||
vertical-align: -5rpx;
|
||||
}
|
||||
|
||||
.bargain .bargainBnt {
|
||||
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
width: 630rpx;
|
||||
height: 80rpx;
|
||||
background-image: url('../static/btn.png');
|
||||
background-size: 100% 100%;
|
||||
// border-radius: 40rpx;
|
||||
// background: linear-gradient(180deg, #FF8831 0%, #F11B09 100%);
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.bargain .bargainBnt.on {
|
||||
border: 2rpx solid red;
|
||||
color: red;
|
||||
background-image: linear-gradient(to right, #fff 0%, #fff 100%);
|
||||
width: 596rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
|
||||
.bargain .bargainBnt.grey {
|
||||
color: #fff;
|
||||
background-image: linear-gradient(to right, #bbbbbb 0%, #bbbbbb 100%);
|
||||
}
|
||||
|
||||
.bargain .tip {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
margin-top: 20rpx;
|
||||
margin-bottom: 50rpx;
|
||||
}
|
||||
|
||||
.bargain .lock,
|
||||
.bargain .bargainGang .lock,
|
||||
.bargain .goodsDetails .lock {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAiQAAABCCAYAAABnwc0eAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQyIDc5LjE2MDkyNCwgMjAxNy8wNy8xMy0wMTowNjozOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo4YmQzMTQ1Ny01MGY2LWFmNDMtYmY4Yi1kNWRjZTMxZDg5MTUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6M0RCMkU3QUEzQzBCMTFFOUI2N0VEOEJBMDUwMTU2ODMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6M0RCMkU3QTkzQzBCMTFFOUI2N0VEOEJBMDUwMTU2ODMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTggKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NDRmMWQxNmItZTIxMC1lYzQwLWJmODYtYzE4OWRiYzNmOGYyIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjhiZDMxNDU3LTUwZjYtYWY0My1iZjhiLWQ1ZGNlMzFkODkxNSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoRfwVwAAAlWSURBVHja7J3NqhxFHEer+uOaGL2ECG5U1IBgEkgeQBcqLiLJ3hcIJAs34k7XZhkRFBSSjbs8QCCLEF3oA0iuBjfBr+xcRWPCzHSXVdVVM9XV1X1nrvbC6XPg78ztnuqBDh5+9THV8sfTL4qIk7ou6HpH18vu2D1dN3Vd1fVj3ODE9z8LANhO7p55KXUYTwDAf+qJLHi/o+szXXd0va/rVV1PuDrhjplzX+g6zO0HmCR4AgBG8UQRNL6h6+19vsQEmIu6XnGJZ8Z9B5iUZPAEAIziCT9C8skajUPe0nWF+w4wKfAEAIzmCRNITrmUsiSXUhzJM3G0yMWxsrBl3ptj5pzjkmsLANsPngCAUT1hAolZcJL7o77hoaz5sPm4dBc1x/yFZNPmAvcfYBLgCQAY1RMmkJz1jXddw/0wn3m6sN95lvsPMAnwBACM6gnz6eM+yZSr4ZN9KZthmOPcf4BJgCcAYFRP2Pjih082RbeZ5Rt8KQD8f8ETADCmJ8zPfu8dyuSr4YmdFyqx+8ZcZE8q+3f9txQPvinF7Lc8vsYvui3/AgDbD54AgFE9YWLMzXhoZffNSmRH9DGpT8vcvjfHEtwq6fkATIEBT+TWFXgCAE+kPZG5PJHZ932eMIHkWi5l62zTuNBvciebvDnWxrS5ylAswCToeuIp7YbMeML5QheeAMATnTyRNYMb1hculKQ8YY7u6fqydcoEERtGitX7rDO8YtrsKf4BAKZA1xNGMCL0hAsmeAIATyzzRNEKI8u/E56wMaVSyuwrf6t1AV+251M271fcFs1e9KJWqAZgCiQ9kQeeyPAEAJ6IPGFnWZwbvCPyMukJG0jmSplnTZzT9blxh23khmCtcHIXSsy5JsmcF+75FHNEAzAJOp7wjpBOML4TgycA8IT3RB6FEf8+4QkbSB7XVhbmwHu6TjcNy0Yy0lVzgTOi2eL1kf9y1xYAtpykJ/JyFUZk6Xs+eAIATzSe8F5YzraUfmq34wk/ZaMvUtsDz35w7IelaELh6NLn9tpfXNu2ALD9dDzhHRF2YDLjiWfwBACeaHsib+eKVJ6QKhbF9dfMf5Uwq+LtOb863n5Oine/444DTJ3rrztPqKUamvfSeeJb7hEAnhAuSLgsoYLXbp7oLIkX+c4qf/gn4Zjr2Vd+ugcAIliU5js0uAEAIjLnCd9ZaY1vdEdNu4Ek2xHtRBI0wjkA4EUT6aE7qgoAdFzCAKG63hgOJGWrbQs8AwBWNNFIKgDAkCeiXJLyRpFONOF8sBL9CQUAJklWivb4K6kEABKeaEWHYU+k15D4xuHurmQRAFiKZqfd48ERANDnCRm4YmDZWTHc8xFRIqEXBAAi3mmxbRuCCQD4PCHXn13pX0PiBbP6KR8AgAskO5Fj6LAAQF/HJbX8Q24SSIIwIpENAIR9lbLxgu/9KOZtACDOE37K5j8ZIRHNOhIcAwAtLxT988H0XQDAeyLZoVk7kBRrNwaAqYqmFMs9BQAANgkkYpNAstwTTUULUrAPABhP5M1rPJvL7C4AdPJEMK0rNwkkMncNfBgBAOjxBJsnAsB+nhBirbWoiUCSid7JYcliEgCIRCNcB2ZoC0YAmKYnQj+ED+NcP5D0NUA0ACBWo6dSJgIJAIAmy4LnWwXPsulxRTqQqCjRmFc6PgCwMk0kF//z34xbAwBRpvCucH6wf2drBJK4B0QKAYCOHxJuCB8vDgAg4pFUMZgruoFEqf5V8+zYCgChGPxwrBQ80wYAunnC548wP8i0KIpkoFGp+WDmhwEgDB110/NRKpjmBQCIYoPNFMEPZdS6W8fXVXQ1L6CanwEDwMoH4WtLQngCAHyeCBazqmVCSXqi6BVN61iwsBUAQFWid1c0PAEAcZ6In62X8ERihGThhmEFC9QAoL/nk9qHRLGhIgAMdFz89O5agcRcwA+rtJaQ0PMBAO+JRb8P8AQA2I7LonusNXWzbyBZpLeDrrm3ABCJhrXvALBOx2UNN3QDSTVvN26FEYZiAcA4YZ7wAQ/hBIBEngi3jd9ohKQjGv87YqZsACD0hEi7AgDAemKR6LT0d1gGAklqnIWeDwCEgSR2BJ4AgMgT4YarAzs6F/0XiNzCr24AIBVI4gf9MlACANYTs64jBvotiTUkM5F+jDiWAQDviXm3p2LmiGt6LQAQ5wmRyBLrbIyWWtQKABCLpveZV9weABDtGZfObMtaP/udMQQLAGuIhlFUABjquMxFZ55mYCR1YMomSjO4BgBCT/if8fmn/eIKAOjkieTwSDqQ3D3zUuvAiY+ebxop/7vh9oXiz9s23//MjQfYUpL/z3/4XKvTs+rx4AkAPBF6IprL9U8Il902WeeiH/9+0g6zmNWx/tXWXNy9rM8BAPK5fP+knbYxhScAoNcTKzc0vnCe+Ph+xxNhINnR9ZmuO41gomoWu97R9YWuw9xqgEnS9UQVBRM8AYAnvCe8G+JckfBEETS+oett+5fZf772G5nIcFMTE2Au6npF1zu6Ztx3gElJJvDEfLVepHaLR/AEAJ4IPVHP+55n0/GEHyH5ZNl4eQEdSqqFSzOLeAvYt3Rd4b4DTIrIE84LoScqPAGAJwJPVC5P+Eyh5r15wgSSUy6liFYgqcMLNOI5kmcil8sVspdcWwDYfhKeWKw84V8VngDAEwGqilxR2VCS8oQJJBd05f6o+VD9V925QP1XJQ5lmTha5PYzsmlzgfsPMAkSnqhWjhDNa/1wgScA8ETgicUqT1hfVDZjpDxhAslZ33hXnzQfevC11GLRoUQ1ZcRjjnnMZ54u7Hee5f4DTIIeT6imx1NrT/xZiwe3MzwBgCcCT2RBntBh5M/+PGEWtR73SaZ0wyezXzPxx1c7g99qPqvbHH9Y1fwTAGw/PZ7I8AQA7OOJ9fKEtYmZxzEpZVN0m1kwBwQAWwyeAIAxPWFa3TuUHVgWv/yLtgDw/wFPAMConjCB5GZ58N7LrZKeD8AUwBMAMKonTCC5lktZHaCxaXOVoViASYAnAGBUT5hAsqfrywNcwLTZ48GeAJMATwDAqJ6wK08qpd7XL7c2aHxbl2kjaoVqAKYAngCAMT1hA8lcKfOsiXO6PjfuGGhYuyRzXrjnU8wRDcAkwBMAMKYnbCB5XFtZmAPv6Tqt61NdP5lr63qo6wd37Ixotnh95K/o2gLAloMnAGBMT/wjwAC10O4qfVDGDQAAAABJRU5ErkJggg==');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
width: 548rpx;
|
||||
height: 66rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: -43rpx;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.bargain .title {
|
||||
font-size: 40rpx;
|
||||
font-weight: 600;
|
||||
// height: 80rpx;
|
||||
// margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.bargain .title .pictrue {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
}
|
||||
|
||||
.bargain .title .pictrue.on,
|
||||
.bargain .title .pictrue.on {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.bargain .title .pictrue image,
|
||||
.bargain .title .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.bargain .title .tits {
|
||||
margin: 50rpx 15rpx 40rpx 15rpx;
|
||||
}
|
||||
|
||||
.bargain .title .titleCon {
|
||||
margin: 0 10rpx -14rpx 10rpx;
|
||||
color: #fff;
|
||||
border: 16rpx solid linear-gradient(0deg, #FFD136 0%, rgba(255, 213, 72, 0.12) 100%);
|
||||
;
|
||||
}
|
||||
|
||||
.bargain .title .line {
|
||||
// width: 216rpx;
|
||||
height: 16rpx;
|
||||
background: linear-gradient(0deg, #FFD136 0%, rgba(255, 213, 72, 0.12) 100%);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.bargain .bargainGang .list .item {
|
||||
padding-bottom: 50rpx;
|
||||
}
|
||||
|
||||
.bargain .bargainGang .list .item .pictxt {
|
||||
|
||||
// width: 310rpx;
|
||||
.num {
|
||||
width: 28rpx;
|
||||
height: 36rpx;
|
||||
|
||||
// image{
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// }
|
||||
}
|
||||
|
||||
.num1 {
|
||||
background-image: url(../static/n1.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.num2 {
|
||||
background-image: url(../static/n2.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.num3 {
|
||||
background-image: url(../static/n3.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.bargain .bargainGang .list .item .pictxt .pictrue {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
margin-right: 14rpx;
|
||||
}
|
||||
|
||||
.bargain .bargainGang .list .item .pictxt .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.bargain .bargainGang .list .item .pictxt .text {
|
||||
width: 225rpx;
|
||||
font-size: 20rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.bargain .bargainGang .list .item .pictxt .text .name {
|
||||
font-size: 25rpx;
|
||||
color: #333333;
|
||||
margin-bottom: 7rpx;
|
||||
}
|
||||
|
||||
.bargain .bargainGang .list .item .money {
|
||||
font-size: 25rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.bargain .bargainGang .list .item .money .iconfont {
|
||||
font-size: 35rpx;
|
||||
vertical-align: middle;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.bargain .bargainGang .load {
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.bargain .goodsDetails {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
//margin: 13rpx auto 0 auto;
|
||||
}
|
||||
|
||||
.bargain .goodsDetails~.goodsDetails {
|
||||
margin-bottom: 50rpx;
|
||||
}
|
||||
|
||||
.bargain .goodsDetails .conter {
|
||||
// margin-top: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bargain .goodsDetails .conter image {
|
||||
width: 100% !important;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.bargain .bargainTip {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 500rpx;
|
||||
height: 469rpx;
|
||||
margin-left: -246rpx;
|
||||
z-index: 111;
|
||||
border-radius: 14rpx;
|
||||
background-color: #fff;
|
||||
transition: all 0.3s ease-in-out 0s;
|
||||
opacity: 0;
|
||||
transform: scale(0);
|
||||
padding-bottom: 60rpx;
|
||||
margin-top: -330rpx;
|
||||
background: linear-gradient(180deg, #FFFFFF 0%, #FFEEEB 100%);
|
||||
|
||||
.cu-progress {
|
||||
width: 410rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.t1 {
|
||||
text-align: center;
|
||||
color: #666666;
|
||||
font-size: 24rpx;
|
||||
margin: 20rpx 0 54rpx 0;
|
||||
}
|
||||
|
||||
.bubbleBox {
|
||||
width: 410rpx;
|
||||
margin: 16rpx auto;
|
||||
|
||||
.bubble {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
text {
|
||||
display: inline-block;
|
||||
font-size: 22rpx;
|
||||
padding: 2rpx 8rpx;
|
||||
border-radius: 30rpx;
|
||||
background-color: #E93323;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
text::before {
|
||||
content: '';
|
||||
width: 0;
|
||||
height: 32rpx;
|
||||
border: 14rpx solid;
|
||||
position: absolute;
|
||||
bottom: -54rpx;
|
||||
left: 14rpx;
|
||||
border-color: #E93323 transparent transparent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.bargain .bargainTip.on {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.bargain .bargainTip .pictrue {
|
||||
width: 500rpx;
|
||||
height: 200rpx;
|
||||
margin-top: -118rpx;
|
||||
}
|
||||
|
||||
.bargain .bargainTip .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.bargain .bargainTip .cutOff {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
margin: 12rpx 0 0rpx 0;
|
||||
font-weight: 600;
|
||||
|
||||
text {
|
||||
font-weight: 600;
|
||||
font-size: 44rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.bargain .bargainTip .cutOff.on {
|
||||
margin-top: 26rpx;
|
||||
}
|
||||
|
||||
.bargain .bargainTip .help {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
|
||||
.bargain .bargainTip .tipBnt {
|
||||
font-size: 32rpx;
|
||||
color: #fff;
|
||||
width: 360rpx;
|
||||
height: 82rpx;
|
||||
border-radius: 41rpx;
|
||||
background-image: linear-gradient(to right, #f67a38 0%, #f11b09 100%);
|
||||
text-align: center;
|
||||
line-height: 82rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.bargain_view {
|
||||
width: 180rpx;
|
||||
height: 48rpx;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
opacity: 1;
|
||||
border-radius: 0 0 6rpx 6rpx;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
font-size: 22rpx;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 48rpx;
|
||||
}
|
||||
|
||||
.iconfonts {
|
||||
font-size: 22rpx !important;
|
||||
line-height: 220rpx;
|
||||
}
|
||||
|
||||
.wxParse-div {
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.bargain .mask {
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.share-box {
|
||||
z-index: 1000;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,370 +0,0 @@
|
||||
<template>
|
||||
<!-- TODO @科举:参考 groupon/list.vue 和 seckill/list.vue 界面,调整下头部,就是从 5 到 11 行的 -->
|
||||
<s-layout navbar="inner" title='砍价列表'>
|
||||
<view style='background-color: red;height:100vh;'>
|
||||
<view class='bargain-list'>
|
||||
<!-- #ifdef H5 -->
|
||||
<view class='iconfont icon-xiangzuo' @tap='goBack' :style="'top:'+ (state.navH/2) +'rpx'"
|
||||
v-if="state.returnShow">
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 砍价记录的概要 -->
|
||||
<view class='header'>
|
||||
<view class="pic">
|
||||
<view class='swipers'>
|
||||
<swiper indicator-dots="true" autoplay="true" interval="2500" duration="500" vertical="true"
|
||||
circular="true">
|
||||
<block v-for="(item,index) in state.bargainSuccessList" :key='index'>
|
||||
<swiper-item>
|
||||
<view class="acea-row row-middle" style='display:flex'>
|
||||
<image :src="item.avatar" class="mr9"></image>
|
||||
<view class='mr9 nickName'>{{ item.nickname }}</view>
|
||||
<text class='mr9'>拿了</text>
|
||||
<view class='line1'>{{ item.activityName }}</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</block>
|
||||
</swiper>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tit">已有{{ state.bargainTotal }}人砍成功</view>
|
||||
</view>
|
||||
|
||||
<!-- 砍价活动列表 -->
|
||||
<view class='list'>
|
||||
<block v-for="(item,index) in state.bargainList" :key="index">
|
||||
<view style='display:flex' class='item acea-row row-between-wrapper'
|
||||
@tap="openSubscribe('/pages/activity/bargain/detail?id='+ item.id)">
|
||||
<view class='pictrue'>
|
||||
<image :src='item.picUrl'></image>
|
||||
</view>
|
||||
<view class='text acea-row row-column-around'>
|
||||
<view class='name line2'>{{ item.name }}</view>
|
||||
<view class="acea-row" style="margin-bottom: 14rpx;display:flex">
|
||||
<s-count-down :tipText="' '" :bgColor="state.bgColor" :dayText="':'" :hourText="':'"
|
||||
:minuteText="':'" :secondText="' '" :datatime="item.endTime / 1000"
|
||||
:isDay="true" />
|
||||
<text class="txt">后结束</text>
|
||||
</view>
|
||||
<view v-if="item.stock === 0">
|
||||
<view style="font-size: 22rpx;"
|
||||
@tap="openSubscribe('/pages/activity/goods_bargain_details/index?id='+ item.id +'&startBargainUid='+ uid)">
|
||||
已售罄</view>
|
||||
</view>
|
||||
<view class='money font-color'>最低: ¥<text
|
||||
class='price'>{{ fen2yuan(item.bargainMinPrice) }}</text></view>
|
||||
</view>
|
||||
<view v-if="item.stock > 0" class='cutBnt bg-color'>参与砍价</view>
|
||||
<view v-if="item.stock === 0" class='cutBnt bg-color-hui'>已售罄</view>
|
||||
</view>
|
||||
</block>
|
||||
<view class='loadingicon acea-row row-center-wrapper' v-if='state.bargainList.length > 0'
|
||||
style='text-align: center;'>
|
||||
<text class='loading iconfont icon-jiazai' :hidden='!loading'></text>{{state.loadTitle}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive
|
||||
} from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
onLoad,
|
||||
onReachBottom
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
fen2yuan
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import BargainApi from '@/sheep/api/promotion/bargain'
|
||||
const state = reactive({
|
||||
navH: '',
|
||||
returnShow: true,
|
||||
|
||||
// ========== 砍价记录概要的相关变量 ==========
|
||||
bargainTotal: 0,
|
||||
bargainSuccessList: [],
|
||||
|
||||
// ========== 砍价活动的相关变量 ==========
|
||||
bargainList: [],
|
||||
page: 1,
|
||||
limit: 10,
|
||||
loading: false,
|
||||
loadend: false,
|
||||
bgColor: {
|
||||
'bgColor': '#E93323',
|
||||
'Color': '#fff',
|
||||
'width': '44rpx',
|
||||
'timeTxtwidth': '16rpx',
|
||||
'isDay': true
|
||||
},
|
||||
loadTitle: '加载更多',
|
||||
});
|
||||
|
||||
async function getBargainHeader() {
|
||||
let {
|
||||
code,
|
||||
data
|
||||
} = await BargainApi.getBargainRecordSummary()
|
||||
if (code == 0) {
|
||||
state.bargainTotal = data.successUserCount;
|
||||
state.bargainSuccessList = data.successList;
|
||||
} else {
|
||||
state.$util.Tips({
|
||||
title: data
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function getBargainList() {
|
||||
// TODO @科举:loading 和 loadTitle 改成现在这个项目的风格,包括组件使用 uni-load-more
|
||||
if (state.loadend || state.loading) {
|
||||
return;
|
||||
}
|
||||
state.loading = true;
|
||||
state.loadTitle = '';
|
||||
let {
|
||||
data,
|
||||
code
|
||||
} = await BargainApi.getBargainActivityPage({
|
||||
pageNo: state.page,
|
||||
pageSize: state.limit
|
||||
})
|
||||
if (code == 0) {
|
||||
const list = data.list;
|
||||
const bargainList = _.concat(state.bargainList, list);
|
||||
const loadend = list.length < state.limit;
|
||||
state.loadend = loadend;
|
||||
state.loading = false;
|
||||
state.loadTitle = loadend ? '已全部加载' : '加载更多';
|
||||
// this.$set(this, 'bargainList', bargainList);
|
||||
state.bargainList = data.list
|
||||
// this.$set(this, 'page', this.page + 1);
|
||||
state.page = state.page + 1;
|
||||
|
||||
} else {
|
||||
state.loading = false;
|
||||
state.loadTitle = '加载更多';
|
||||
}
|
||||
}
|
||||
|
||||
function openSubscribe(e) {
|
||||
console.log('跳转')
|
||||
console.log(e)
|
||||
// TODO @科举:参考 pages/pay/result.vue 页面的 subscribeMessage 方法,写订阅逻辑。
|
||||
sheep.$router.go(e)
|
||||
return;
|
||||
let page = e;
|
||||
// #ifndef MP
|
||||
uni.navigateTo({
|
||||
url: page
|
||||
});
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
uni.showLoading({
|
||||
title: '正在加载',
|
||||
})
|
||||
openBargainSubscribe().then(res => {
|
||||
uni.hideLoading();
|
||||
|
||||
}).catch((err) => {
|
||||
uni.hideLoading();
|
||||
});
|
||||
// #endif
|
||||
}
|
||||
|
||||
onLoad(function() {
|
||||
getBargainHeader();
|
||||
getBargainList();
|
||||
})
|
||||
|
||||
onReachBottom(() => {
|
||||
getBargainList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
page,
|
||||
.page-app {
|
||||
background-color: #e93323 !important;
|
||||
}
|
||||
|
||||
.font-color {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.mr9 {
|
||||
margin-right: 9rpx;
|
||||
}
|
||||
|
||||
.swipers {
|
||||
height: 100%;
|
||||
width: 76%;
|
||||
margin: auto;
|
||||
overflow: hidden;
|
||||
font-size: 22rpx;
|
||||
color: #fff;
|
||||
|
||||
image {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
swiper {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.line1 {
|
||||
width: 195rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.bargain-list .icon-xiangzuo {
|
||||
font-size: 40rpx;
|
||||
color: #fff;
|
||||
position: fixed;
|
||||
left: 30rpx;
|
||||
z-index: 99;
|
||||
transform: translateY(-20%);
|
||||
height: 100%
|
||||
}
|
||||
|
||||
.bargain-list .header {
|
||||
/* TODO 芋艿:此处原来采用base64 但是过长编辑到小程序卡死 目前采用网络地址 需解决 */
|
||||
background-image: url('https://huizhizao-1314830814.cos.ap-shanghai.myqcloud.com/huizhizao-1314830814/bdc8a9210710b83bcd88a14703f440fc7091792706b5cb71b54361488a547298.png');
|
||||
babackground-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
width: 750rpx;
|
||||
height: 420rpx;
|
||||
|
||||
.acea-row {
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
left: 50rpx;
|
||||
|
||||
.nickName {
|
||||
width: 65rpx;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.pic {
|
||||
width: 478rpx;
|
||||
height: 50rpx;
|
||||
margin: 0 auto;
|
||||
/* TODO 芋艿:此处原来是本地地址小程序不支持,需改为线上 */
|
||||
background-image: url('https://huizhizao-1314830814.cos.ap-shanghai.myqcloud.com/huizhizao-1314830814/d111ac53e1390618f22fcc03e415bcd584b3f409ae52421aef95c2ab9b02aa30.png');
|
||||
babackground-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.tit {
|
||||
color: #FFFFFF;
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
margin-top: 304rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.bargain-list .list {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.bargain-list .list .item {
|
||||
position: relative;
|
||||
height: 250rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 14rpx;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 30rpx 25rpx;
|
||||
}
|
||||
|
||||
.bargain-list .list .item .pictrue {
|
||||
width: 190rpx;
|
||||
height: 190rpx;
|
||||
}
|
||||
|
||||
.bargain-list .list .item .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 14rpx;
|
||||
}
|
||||
|
||||
.bargain-list .list .item .text {
|
||||
width: 432rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
|
||||
.txt {
|
||||
font-size: 22rpx;
|
||||
margin-left: 4rpx;
|
||||
color: #666666;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.bargain-list .list .item .text .name {
|
||||
width: 100%;
|
||||
height: 68rpx;
|
||||
line-height: 36rpx;
|
||||
font-size: 28rpx;
|
||||
margin-bottom: 26rpx;
|
||||
}
|
||||
|
||||
.bargain-list .list .item .text .num {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.bargain-list .list .item .text .num .iconfont {
|
||||
font-size: 35rpx;
|
||||
margin-right: 7rpx;
|
||||
}
|
||||
|
||||
.bargain-list .list .item .text .money {
|
||||
font-size: 24rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.bargain-list .list .item .text .money .price {
|
||||
font-size: 38rpx;
|
||||
}
|
||||
|
||||
.bargain-list .list .item .cutBnt {
|
||||
position: absolute;
|
||||
width: 162rpx;
|
||||
height: 52rpx;
|
||||
border-radius: 50rpx;
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 52rpx;
|
||||
right: 24rpx;
|
||||
bottom: 30rpx;
|
||||
background: linear-gradient(90deg, #FF7931 0%, #E93323 100%);
|
||||
}
|
||||
|
||||
.bargain-list .list .item .cutBnt .iconfont {
|
||||
margin-right: 8rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.bargain-list .list .load {
|
||||
font-size: 24rpx;
|
||||
height: 85rpx;
|
||||
text-align: center;
|
||||
line-height: 85rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,11 @@
|
||||
<!-- 拼团订单的详情 -->
|
||||
<template>
|
||||
<s-layout title="拼团详情" class="detail-wrap" :navbar="state.data && !state.loading ? 'inner': 'normal'" :onShareAppMessage="shareInfo">
|
||||
<s-layout
|
||||
title="拼团详情"
|
||||
class="detail-wrap"
|
||||
:navbar="state.data && !state.loading ? 'inner' : 'normal'"
|
||||
:onShareAppMessage="shareInfo"
|
||||
>
|
||||
<view v-if="state.loading"></view>
|
||||
<view v-if="state.data && !state.loading">
|
||||
<!-- 团长信息 + 活动信息 -->
|
||||
@@ -22,7 +27,7 @@
|
||||
priceColor="#E1212B"
|
||||
@tap="
|
||||
sheep.$router.go('/pages/goods/groupon', {
|
||||
id: state.data.headRecord.activityId
|
||||
id: state.data.headRecord.activityId,
|
||||
})
|
||||
"
|
||||
:style="[{ top: Number(statusBarHeight + 108) + 'rpx' }]"
|
||||
@@ -71,7 +76,9 @@
|
||||
</view>
|
||||
<view class="countdown-title ss-flex" v-else>
|
||||
还差
|
||||
<view class="num">{{ state.data.headRecord.userSize - state.data.headRecord.userCount }}人</view>
|
||||
<view class="num"
|
||||
>{{ state.data.headRecord.userSize - state.data.headRecord.userCount }}人</view
|
||||
>
|
||||
拼团成功
|
||||
<view class="ss-flex countdown-time">
|
||||
<view class="countdown-h ss-flex ss-row-center">{{ endTime.h }}</view>
|
||||
@@ -109,7 +116,11 @@
|
||||
</view>
|
||||
</view>
|
||||
<!-- 还有几个坑位 -->
|
||||
<view class="default-avatar ss-m-r-24 ss-m-b-20" v-for="item in state.remainNumber" :key="item">
|
||||
<view
|
||||
class="default-avatar ss-m-r-24 ss-m-b-20"
|
||||
v-for="item in state.remainNumber"
|
||||
:key="item"
|
||||
>
|
||||
<image
|
||||
:src="sheep.$url.static('/static/img/shop/avatar/unknown.png')"
|
||||
class="avatar-img"
|
||||
@@ -154,11 +165,7 @@
|
||||
</view>
|
||||
<view v-else class="ss-flex ss-row-center">
|
||||
<view v-if="state.data.orderId">
|
||||
<button
|
||||
class="ss-reset-button join-btn"
|
||||
:disabled="endTime.ms <= 0"
|
||||
@tap="onShare"
|
||||
>
|
||||
<button class="ss-reset-button join-btn" :disabled="endTime.ms <= 0" @tap="onShare">
|
||||
邀请好友来拼团
|
||||
</button>
|
||||
</view>
|
||||
@@ -174,11 +181,11 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- TODO 芋艿:这里暂时没接入 -->
|
||||
<view v-if="state.data.goods">
|
||||
<view v-if="!isEmpty(state.goodsInfo)">
|
||||
<!-- 规格与数量弹框 -->
|
||||
<s-select-groupon-sku
|
||||
:show="state.showSelectSku"
|
||||
:goodsInfo="state.data.goods"
|
||||
:goodsInfo="state.goodsInfo"
|
||||
:grouponAction="state.grouponAction"
|
||||
:grouponNum="state.grouponNum"
|
||||
@buy="onBuy"
|
||||
@@ -186,6 +193,7 @@
|
||||
@close="state.showSelectSku = false"
|
||||
/>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<s-empty v-if="!state.data && !state.loading" icon="/static/goods-empty.png" />
|
||||
@@ -196,25 +204,28 @@
|
||||
import { computed, reactive } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { useDurationTime } from '@/sheep/hooks/useGoods';
|
||||
import { fen2yuan, useDurationTime } from '@/sheep/hooks/useGoods';
|
||||
import { showShareModal } from '@/sheep/hooks/useModal';
|
||||
import { isEmpty } from 'lodash';
|
||||
import CombinationApi from "@/sheep/api/promotion/combination";
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import CombinationApi from '@/sheep/api/promotion/combination';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
|
||||
const headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const state = reactive({
|
||||
data: {}, // 拼团详情
|
||||
loading: true,
|
||||
grouponAction: 'create',
|
||||
showSelectSku: false,
|
||||
grouponNum: 0,
|
||||
number: 0,
|
||||
activity: {},
|
||||
goodsId: 0, // 商品ID
|
||||
goodsInfo: {}, // 商品信息
|
||||
showSelectSku: false, // 显示规格弹框
|
||||
selectedSkuPrice: {}, // 选中的规格价格
|
||||
activity: {}, // 团购活动
|
||||
grouponId: 0, // 团购ID
|
||||
grouponNum: 0, // 团购人数
|
||||
grouponAction: 'create', // 团购操作
|
||||
combinationHeadId: null, // 拼团团长编号
|
||||
loading: true,
|
||||
});
|
||||
|
||||
// todo 芋艿:分享要再接下
|
||||
const shareInfo = computed(() => {
|
||||
if (isEmpty(state.data)) return {};
|
||||
return sheep.$platform.share.getShareInfo(
|
||||
@@ -224,15 +235,14 @@
|
||||
desc: state.data.goods?.subtitle,
|
||||
params: {
|
||||
page: '5',
|
||||
query: state.data.id,
|
||||
query: state.data.headRecord.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'groupon', // 邀请拼团海报
|
||||
title: state.data.headRecord.spuName, // 商品标题
|
||||
image: sheep.$url.cdn(state.data.headRecord.picUrl), // 商品主图
|
||||
price: state.data.goods?.price, // 商品价格
|
||||
original_price: state.data.goods?.original_price, // 商品原价
|
||||
price: fen2yuan(state.data.headRecord.combinationPrice), // 商品价格
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -244,33 +254,33 @@
|
||||
});
|
||||
}
|
||||
|
||||
// 去开团 TODO 芋艿:这里没接入
|
||||
// 去开团
|
||||
function onCreateGroupon() {
|
||||
state.grouponAction = 'create';
|
||||
state.grouponId = 0;
|
||||
state.showSelectSku = true;
|
||||
}
|
||||
|
||||
// 规格变更 TODO 芋艿:这里没接入
|
||||
// 规格变更
|
||||
function onSkuChange(e) {
|
||||
state.selectedSkuPrice = e;
|
||||
}
|
||||
|
||||
// 立即参团 TODO 芋艿:这里没接入
|
||||
// 立即参团
|
||||
function onJoinGroupon() {
|
||||
state.grouponAction = 'join';
|
||||
state.grouponId = state.data.activityId;
|
||||
state.combinationHeadId = state.data.id;
|
||||
state.grouponNum = state.data.num;
|
||||
state.grouponId = state.data.headRecord.activityId;
|
||||
state.combinationHeadId = state.data.headRecord.id;
|
||||
state.grouponNum = state.data.headRecord.userSize;
|
||||
state.showSelectSku = true;
|
||||
}
|
||||
|
||||
// 立即购买 TODO 芋艿:这里没接入
|
||||
// 立即购买
|
||||
function onBuy(sku) {
|
||||
sheep.$router.go('/pages/order/confirm', {
|
||||
data: JSON.stringify({
|
||||
order_type: 'goods',
|
||||
combinationActivityId: state.data.activity.id,
|
||||
combinationActivityId: state.activity.id,
|
||||
combinationHeadId: state.combinationHeadId,
|
||||
items: [
|
||||
{
|
||||
@@ -295,8 +305,29 @@
|
||||
state.remainNumber = remainNumber > 0 ? remainNumber : 0;
|
||||
|
||||
// 获取活动信息
|
||||
const { data: activity } = await CombinationApi.getCombinationActivity(data.headRecord.activityId);
|
||||
const { data: activity } = await CombinationApi.getCombinationActivity(
|
||||
data.headRecord.activityId,
|
||||
);
|
||||
state.activity = activity;
|
||||
state.grouponNum = activity.userSize;
|
||||
// 加载商品信息
|
||||
const { data: spu } = await SpuApi.getSpuDetail(activity.spuId);
|
||||
state.goodsId = spu.id;
|
||||
// 默认显示最低价
|
||||
activity.products.forEach((product) => {
|
||||
spu.price = Math.min(spu.price, product.combinationPrice); // 设置 SPU 的最低价格
|
||||
});
|
||||
state.goodsInfo = spu;
|
||||
// 价格、库存使用活动的
|
||||
spu.skus.forEach((sku) => {
|
||||
const product = activity.products.find((product) => product.skuId === sku.id);
|
||||
if (product) {
|
||||
sku.price = product.combinationPrice;
|
||||
} else {
|
||||
// 找不到可能是没配置,则不能发起秒杀
|
||||
sku.stock = 0;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
state.data = null;
|
||||
}
|
||||
@@ -316,8 +347,7 @@
|
||||
.recharge-box {
|
||||
position: relative;
|
||||
margin-bottom: 120rpx;
|
||||
background: v-bind(headerBg) center/750rpx 100%
|
||||
no-repeat,
|
||||
background: v-bind(headerBg) center/750rpx 100% no-repeat,
|
||||
linear-gradient(115deg, #f44739 0%, #ff6600 100%);
|
||||
border-radius: 0 0 5% 5%;
|
||||
height: 100rpx;
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
</view>
|
||||
<view class="border-bottom">
|
||||
<s-goods-item
|
||||
:img="record.picUrl"
|
||||
:title="record.spuName"
|
||||
:price="record.combinationPrice"
|
||||
:img="record.picUrl"
|
||||
:title="record.spuName"
|
||||
:price="record.combinationPrice"
|
||||
>
|
||||
<template #groupon>
|
||||
<view class="ss-flex">
|
||||
@@ -67,8 +67,8 @@
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash';
|
||||
import {formatOrderColor} from "@/sheep/hooks/useGoods";
|
||||
import _ from 'lodash-es';
|
||||
import { formatOrderColor } from '@/sheep/hooks/useGoods';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
import CombinationApi from '@/sheep/api/promotion/combination';
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list)
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<view class="type-text ss-flex ss-row-center">满减:</view>
|
||||
<view class="ss-flex-1">
|
||||
<view class="tip-content" v-for="item in state.activityInfo.rules" :key="item">
|
||||
{{ formatRewardActivityRule(state.activityInfo, item) }}
|
||||
{{ item.description }}
|
||||
</view>
|
||||
</view>
|
||||
<image class="activity-left-image" src="/static/activity-left.png" />
|
||||
@@ -63,10 +63,11 @@
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import RewardActivityApi from '@/sheep/api/promotion/rewardActivity';
|
||||
import { formatRewardActivityRule } from '@/sheep/hooks/useGoods';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
import { appendSettlementProduct } from '@/sheep/hooks/useGoods';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
|
||||
const state = reactive({
|
||||
activityId: 0, // 获得编号
|
||||
@@ -118,11 +119,18 @@
|
||||
const { code, data } = await SpuApi.getSpuPage({
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
...params
|
||||
...params,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
// 拼接结算信息(营销)
|
||||
await OrderApi.getSettlementProduct(data.list.map((item) => item.id).join(',')).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
return;
|
||||
}
|
||||
appendSettlementProduct(data.list, res.data);
|
||||
});
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<!-- 积分商城:商品列表 -->
|
||||
<template>
|
||||
<s-layout title="积分商城" navbar="normal" :leftWidth="0" :rightWidth="0">
|
||||
<scroll-view
|
||||
class="scroll-box"
|
||||
:style="{ height: pageHeight + 'rpx' }"
|
||||
scroll-y="true"
|
||||
:scroll-with-animation="false"
|
||||
:enable-back-to-top="true"
|
||||
>
|
||||
<s-point-card ref="sPointCardRef" class="ss-p-x-20 ss-m-t-20"/>
|
||||
<s-empty
|
||||
v-if="activityTotal === 0"
|
||||
icon="/static/goods-empty.png"
|
||||
text="暂无积分商品"
|
||||
></s-empty>
|
||||
<uni-load-more
|
||||
v-if="activityTotal > 0"
|
||||
:status="loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
</scroll-view>
|
||||
</s-layout>
|
||||
</template>
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import PointApi from '@/sheep/api/promotion/point';
|
||||
import SLayout from '@/sheep/components/s-layout/s-layout.vue';
|
||||
|
||||
// 计算页面高度
|
||||
const { safeAreaInsets, safeArea } = sheep.$platform.device;
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const pageHeight =
|
||||
(safeArea.height + safeAreaInsets.bottom) * 2 + statusBarHeight - sheep.$platform.navbar - 350;
|
||||
|
||||
const sPointCardRef = ref();
|
||||
// 查询活动列表
|
||||
const activityPageParams = reactive({
|
||||
pageNo: 1, // 页码
|
||||
pageSize: 5, // 每页数量
|
||||
});
|
||||
|
||||
const activityTotal = ref(0); // 活动总数
|
||||
const activityCount = ref(0); // 已加载活动数量
|
||||
const loadStatus = ref(''); // 页面加载状态
|
||||
async function getActivityList() {
|
||||
loadStatus.value = 'loading';
|
||||
const { data } = await PointApi.getPointActivityPage(activityPageParams);
|
||||
await sPointCardRef.value.concatActivity(data.list);
|
||||
activityCount.value = sPointCardRef.value.getActivityCount();
|
||||
activityTotal.value = data.total;
|
||||
|
||||
loadStatus.value = activityCount.value < activityTotal.value ? 'more' : 'noMore';
|
||||
}
|
||||
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus !== 'noMore') {
|
||||
activityPageParams.pageNo += 1;
|
||||
getActivityList();
|
||||
}
|
||||
}
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
onLoad(() => {
|
||||
getActivityList();
|
||||
});
|
||||
</script>
|
||||
+137
-61
@@ -3,13 +3,20 @@
|
||||
<s-layout navbar="inner" :bgStyle="{ color: 'rgb(245,28,19)' }">
|
||||
<!--顶部背景图-->
|
||||
<view
|
||||
class="page-bg"
|
||||
:style="[{ marginTop: '-' + Number(statusBarHeight + 88) + 'rpx' }]"
|
||||
class="page-bg"
|
||||
:style="[{ marginTop: '-' + Number(statusBarHeight + 88) + 'rpx' }]"
|
||||
></view>
|
||||
<!-- 时间段轮播图 -->
|
||||
<view class="header" v-if="activeTimeConfig?.sliderPicUrls?.length > 0">
|
||||
<swiper indicator-dots="true" autoplay="true" :circular="true" interval="3000" duration="1500"
|
||||
indicator-color="rgba(255,255,255,0.6)" indicator-active-color="#fff">
|
||||
<swiper
|
||||
indicator-dots="true"
|
||||
autoplay="true"
|
||||
:circular="true"
|
||||
interval="3000"
|
||||
duration="1500"
|
||||
indicator-color="rgba(255,255,255,0.6)"
|
||||
indicator-active-color="#fff"
|
||||
>
|
||||
<block v-for="(picUrl, index) in activeTimeConfig.sliderPicUrls" :key="index">
|
||||
<swiper-item class="borRadius14">
|
||||
<image :src="picUrl" class="slide-image borRadius14" lazy-load />
|
||||
@@ -22,17 +29,28 @@
|
||||
<!-- 左侧图标 -->
|
||||
<view class="time-icon">
|
||||
<!-- TODO 芋艿:图片统一维护 -->
|
||||
<image class="ss-w-100 ss-h-100" src="http://mall.yudao.iocoder.cn/static/images/priceTag.png" />
|
||||
<image
|
||||
class="ss-w-100 ss-h-100"
|
||||
src="http://mall.yudao.iocoder.cn/static/images/priceTag.png"
|
||||
/>
|
||||
</view>
|
||||
<scroll-view class="time-list" :scroll-into-view="activeTimeElId" scroll-x scroll-with-animation>
|
||||
<view v-for="(config, index) in timeConfigList" :key="index"
|
||||
:class="['item', { active: activeTimeIndex === index}]"
|
||||
:id="`timeItem${index}`"
|
||||
@tap="handleChangeTimeConfig(index)">
|
||||
<scroll-view
|
||||
class="time-list"
|
||||
:scroll-into-view="activeTimeElId"
|
||||
scroll-x
|
||||
scroll-with-animation
|
||||
>
|
||||
<view
|
||||
v-for="(config, index) in timeConfigList"
|
||||
:key="index"
|
||||
:class="['item', { active: activeTimeIndex === index }]"
|
||||
:id="`timeItem${index}`"
|
||||
@tap="handleChangeTimeConfig(index, config.id)"
|
||||
>
|
||||
<!-- 活动起始时间 -->
|
||||
<view class="time">{{ config.startTime }}</view>
|
||||
<!-- 活动状态 -->
|
||||
<view class="status">{{ config.status }}</view>
|
||||
<view class="status">{{ config?.status }}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
@@ -42,7 +60,10 @@
|
||||
<!-- 活动倒计时 -->
|
||||
<view class="content-header ss-flex-col ss-col-center ss-row-center">
|
||||
<view class="content-header-box ss-flex ss-row-center">
|
||||
<view class="countdown-box ss-flex" v-if="activeTimeConfig?.status === TimeStatusEnum.STARTED">
|
||||
<view
|
||||
class="countdown-box ss-flex"
|
||||
v-if="activeTimeConfig?.status === TimeStatusEnum.STARTED"
|
||||
>
|
||||
<view class="countdown-title ss-m-r-12">距结束</view>
|
||||
<view class="ss-flex countdown-time">
|
||||
<view class="ss-flex countdown-h">{{ countDown.h }}</view>
|
||||
@@ -70,19 +91,44 @@
|
||||
:data="{ ...activity, price: activity.seckillPrice }"
|
||||
:goodsFields="goodsFields"
|
||||
:seckillTag="true"
|
||||
@click="sheep.$router.go('/pages/goods/seckill', { id: activity.id })"
|
||||
>
|
||||
<!-- 抢购进度 -->
|
||||
<template #activity>
|
||||
<view class="limit">限量 <text class="ss-m-l-5">{{ activity.stock}} {{activity.unitName}}</text></view>
|
||||
<view class="limit">
|
||||
限量
|
||||
<text class="ss-m-l-5">{{ activity.stock }} {{ activity.unitName }}</text>
|
||||
</view>
|
||||
<su-progress :percentage="activity.percent" strokeWidth="10" textInside isAnimate />
|
||||
</template>
|
||||
<!-- 抢购按钮 -->
|
||||
<template #cart>
|
||||
<button :class="['ss-reset-button cart-btn', { disabled: activeTimeConfig.status === TimeStatusEnum.END }]">
|
||||
<span v-if="activeTimeConfig?.status === TimeStatusEnum.WAIT_START">未开始</span>
|
||||
<span v-else-if="activeTimeConfig?.status === TimeStatusEnum.STARTED">马上抢</span>
|
||||
<span v-else>已结束</span>
|
||||
<button
|
||||
:class="[
|
||||
'ss-reset-button cart-btn',
|
||||
{ disabled: activeTimeConfig?.status === TimeStatusEnum.END },
|
||||
]"
|
||||
v-if="activeTimeConfig?.status === TimeStatusEnum.WAIT_START"
|
||||
>
|
||||
<span>未开始</span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'ss-reset-button cart-btn',
|
||||
{ disabled: activeTimeConfig?.status === TimeStatusEnum.END },
|
||||
]"
|
||||
@click="sheep.$router.go('/pages/goods/seckill', { id: activity.id })"
|
||||
v-else-if="activeTimeConfig?.status === TimeStatusEnum.STARTED"
|
||||
>
|
||||
<span>马上抢</span>
|
||||
</button>
|
||||
<button
|
||||
:class="[
|
||||
'ss-reset-button cart-btn',
|
||||
{ disabled: activeTimeConfig?.status === TimeStatusEnum.END },
|
||||
]"
|
||||
v-else
|
||||
>
|
||||
<span>已结束</span>
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-column>
|
||||
@@ -100,40 +146,51 @@
|
||||
</s-layout>
|
||||
</template>
|
||||
<script setup>
|
||||
import {reactive, computed, ref, nextTick} from 'vue';
|
||||
import { reactive, computed, ref, nextTick } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import { useDurationTime } from '@/sheep/hooks/useGoods';
|
||||
import SeckillApi from "@/sheep/api/promotion/seckill";
|
||||
import dayjs from "dayjs";
|
||||
import {TimeStatusEnum} from "@/sheep/util/const";
|
||||
import SeckillApi from '@/sheep/api/promotion/seckill';
|
||||
import dayjs from 'dayjs';
|
||||
import { TimeStatusEnum } from '@/sheep/util/const';
|
||||
|
||||
// 计算页面高度
|
||||
const { safeAreaInsets, safeArea } = sheep.$platform.device;
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const pageHeight = (safeArea.height + safeAreaInsets.bottom) * 2 + statusBarHeight - sheep.$platform.navbar - 350;
|
||||
const pageHeight =
|
||||
(safeArea.height + safeAreaInsets.bottom) * 2 + statusBarHeight - sheep.$platform.navbar - 350;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/goods/seckill-header.png');
|
||||
|
||||
// 商品控件显示的字段(不显示库存、销量。改为显示自定义的进度条)
|
||||
const goodsFields = {
|
||||
name: { show: true },
|
||||
introduction: { show: true },
|
||||
price: { show: true },
|
||||
marketPrice: { show: true },
|
||||
name: {
|
||||
show: true,
|
||||
},
|
||||
introduction: {
|
||||
show: true,
|
||||
},
|
||||
price: {
|
||||
show: true,
|
||||
},
|
||||
marketPrice: {
|
||||
show: true,
|
||||
},
|
||||
};
|
||||
|
||||
//#region 时间段
|
||||
// 时间段列表
|
||||
const timeConfigList = ref([])
|
||||
const timeConfigList = ref([]);
|
||||
// 查询时间段
|
||||
const getSeckillConfigList = async () => {
|
||||
const { data } = await SeckillApi.getSeckillConfigList()
|
||||
const { data } = await SeckillApi.getSeckillConfigList();
|
||||
const now = dayjs();
|
||||
const today = now.format('YYYY-MM-DD')
|
||||
const today = now.format('YYYY-MM-DD');
|
||||
const select = ref([]);
|
||||
// 判断时间段的状态
|
||||
data.forEach((config, index) => {
|
||||
const startTime = dayjs(`${today} ${config.startTime}`)
|
||||
const endTime = dayjs(`${today} ${config.endTime}`)
|
||||
const startTime = dayjs(`${today} ${config.startTime}`);
|
||||
const endTime = dayjs(`${today} ${config.endTime}`);
|
||||
select.value[index] = config.id;
|
||||
if (now.isBefore(startTime)) {
|
||||
config.status = TimeStatusEnum.WAIT_START;
|
||||
} else if (now.isAfter(endTime)) {
|
||||
@@ -142,35 +199,36 @@
|
||||
config.status = TimeStatusEnum.STARTED;
|
||||
activeTimeIndex.value = index;
|
||||
}
|
||||
})
|
||||
timeConfigList.value = data
|
||||
});
|
||||
timeConfigList.value = data;
|
||||
// 默认选中进行中的活动
|
||||
handleChangeTimeConfig(activeTimeIndex.value);
|
||||
handleChangeTimeConfig(activeTimeIndex.value, select.value[activeTimeIndex.value]);
|
||||
// 滚动到进行中的时间段
|
||||
scrollToTimeConfig(activeTimeIndex.value)
|
||||
}
|
||||
scrollToTimeConfig(activeTimeIndex.value);
|
||||
};
|
||||
|
||||
// 滚动到指定时间段
|
||||
const activeTimeElId = ref('') // 当前选中的时间段的元素ID
|
||||
const activeTimeElId = ref(''); // 当前选中的时间段的元素ID
|
||||
const scrollToTimeConfig = (index) => {
|
||||
nextTick(() => activeTimeElId.value = `timeItem${index}`)
|
||||
}
|
||||
nextTick(() => (activeTimeElId.value = `timeItem${index}`));
|
||||
};
|
||||
|
||||
// 切换时间段
|
||||
const activeTimeIndex = ref(0) // 当前选中的时间段的索引
|
||||
const activeTimeConfig = computed(() => timeConfigList.value[activeTimeIndex.value]) // 当前选中的时间段
|
||||
const handleChangeTimeConfig = (index) => {
|
||||
activeTimeIndex.value = index
|
||||
const activeTimeIndex = ref(0); // 当前选中的时间段的索引
|
||||
const activeTimeConfig = computed(() => timeConfigList.value[activeTimeIndex.value]); // 当前选中的时间段
|
||||
const handleChangeTimeConfig = (index, id) => {
|
||||
activeTimeIndex.value = index;
|
||||
|
||||
// 查询活动列表
|
||||
activityPageParams.pageNo = 1
|
||||
activityList.value = []
|
||||
activityPageParams.pageNo = 1;
|
||||
activityPageParams.configId = id;
|
||||
activityList.value = [];
|
||||
getActivityList();
|
||||
}
|
||||
};
|
||||
|
||||
// 倒计时
|
||||
const countDown = computed(() => {
|
||||
const endTime = activeTimeConfig.value?.endTime
|
||||
const endTime = activeTimeConfig.value?.endTime;
|
||||
if (endTime) {
|
||||
return useDurationTime(`${dayjs().format('YYYY-MM-DD')} ${endTime}`);
|
||||
}
|
||||
@@ -182,20 +240,22 @@
|
||||
|
||||
// 查询活动列表
|
||||
const activityPageParams = reactive({
|
||||
id: 0, // 时间段 ID
|
||||
configId: 0, // 时间段 ID
|
||||
pageNo: 1, // 页码
|
||||
pageSize: 5, // 每页数量
|
||||
})
|
||||
const activityTotal = ref(0) // 活动总数
|
||||
const activityList = ref([]) // 活动列表
|
||||
const loadStatus = ref('') // 页面加载状态
|
||||
});
|
||||
const activityTotal = ref(0); // 活动总数
|
||||
const activityList = ref([]); // 活动列表
|
||||
const loadStatus = ref(''); // 页面加载状态
|
||||
async function getActivityList() {
|
||||
loadStatus.value = 'loading';
|
||||
const { data } = await SeckillApi.getSeckillActivityPage(activityPageParams)
|
||||
data.list.forEach(activity => {
|
||||
const { data } = await SeckillApi.getSeckillActivityPage(activityPageParams);
|
||||
data.list.forEach((activity) => {
|
||||
// 计算抢购进度
|
||||
activity.percent = parseInt(100 * (activity.totalStock - activity.stock) / activity.totalStock);
|
||||
})
|
||||
activity.percent = parseInt(
|
||||
(100 * (activity.totalStock - activity.stock)) / activity.totalStock,
|
||||
);
|
||||
});
|
||||
activityList.value = activityList.value.concat(...data.list);
|
||||
activityTotal.value = data.total;
|
||||
|
||||
@@ -205,7 +265,7 @@
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (loadStatus.value !== 'noMore') {
|
||||
activityPageParams.pageNo += 1
|
||||
activityPageParams.pageNo += 1;
|
||||
getActivityList();
|
||||
}
|
||||
}
|
||||
@@ -216,7 +276,7 @@
|
||||
|
||||
// 页面初始化
|
||||
onLoad(async () => {
|
||||
await getSeckillConfigList()
|
||||
await getSeckillConfigList();
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@@ -235,7 +295,8 @@
|
||||
margin: -276rpx auto 0 auto;
|
||||
border-radius: 14rpx;
|
||||
overflow: hidden;
|
||||
swiper{
|
||||
|
||||
swiper {
|
||||
height: 330rpx !important;
|
||||
border-radius: 14rpx;
|
||||
overflow: hidden;
|
||||
@@ -246,7 +307,8 @@
|
||||
height: 100%;
|
||||
border-radius: 14rpx;
|
||||
overflow: hidden;
|
||||
img{
|
||||
|
||||
img {
|
||||
border-radius: 14rpx;
|
||||
}
|
||||
}
|
||||
@@ -257,10 +319,12 @@
|
||||
width: 75rpx;
|
||||
height: 70rpx;
|
||||
}
|
||||
|
||||
// 时间段列表
|
||||
.time-list {
|
||||
width: 596rpx;
|
||||
white-space: nowrap;
|
||||
|
||||
// 时间段
|
||||
.item {
|
||||
display: inline-block;
|
||||
@@ -270,17 +334,20 @@
|
||||
box-sizing: border-box;
|
||||
margin-right: 30rpx;
|
||||
width: 130rpx;
|
||||
|
||||
// 开始时间
|
||||
.time {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
// 选中的时间段
|
||||
&.active {
|
||||
.time {
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
// 状态
|
||||
.status {
|
||||
height: 30rpx;
|
||||
@@ -301,6 +368,7 @@
|
||||
margin: 0 20rpx 0 20rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
|
||||
.content-header {
|
||||
width: 100%;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
@@ -312,6 +380,7 @@
|
||||
height: 64rpx;
|
||||
background: rgba($color: #fff, $alpha: 0.66);
|
||||
border-radius: 32px;
|
||||
|
||||
// 场次倒计时内容
|
||||
.countdown-title {
|
||||
font-size: 28rpx;
|
||||
@@ -319,10 +388,12 @@
|
||||
color: #333333;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
|
||||
// 场次倒计时
|
||||
.countdown-time {
|
||||
font-size: 28rpx;
|
||||
color: rgba(#ed3c30, 0.23);
|
||||
|
||||
// 场次倒计时:小时部分
|
||||
.countdown-h {
|
||||
font-size: 24rpx;
|
||||
@@ -334,6 +405,7 @@
|
||||
background: rgba(#ed3c30, 0.23);
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
|
||||
// 场次倒计时:分钟、秒
|
||||
.countdown-num {
|
||||
font-size: 24rpx;
|
||||
@@ -348,12 +420,15 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 活动列表
|
||||
.scroll-box {
|
||||
height: 900rpx;
|
||||
|
||||
// 活动
|
||||
.goods-box {
|
||||
position: relative;
|
||||
|
||||
// 抢购按钮
|
||||
.cart-btn {
|
||||
position: absolute;
|
||||
@@ -373,6 +448,7 @@
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
// 秒杀限量商品数
|
||||
.limit {
|
||||
font-size: 22rpx;
|
||||
|
||||
+2
-2
@@ -62,7 +62,7 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 签到说明 TODO @科举:这里改成【已累计签到】 -->
|
||||
<!-- 签到说明 TODO @芋艿:【签到】这里改成【已累计签到】;改版,接入 sheepjs -->
|
||||
<view class="bg-white ss-m-t-16 ss-p-t-30 ss-p-b-60 ss-p-x-40">
|
||||
<view class="activity-title ss-m-b-30">签到说明</view>
|
||||
<view class="activity-des">1、已累计签到{{state.signInfo.totalDay}}天</view>
|
||||
@@ -110,7 +110,7 @@
|
||||
signInfo: {}, // 签到信息
|
||||
|
||||
signConfigList: [], // 签到配置列表
|
||||
maxDay: 0, // 最大的签到天数
|
||||
maxDay: 0, // 最大的签到天数
|
||||
|
||||
showModel: false, // 签到弹框
|
||||
signResult: {}, // 签到结果
|
||||
|
||||
@@ -1,23 +1,15 @@
|
||||
<template>
|
||||
<view class="goods ss-flex">
|
||||
<image class="image" :src="sheep.$url.cdn(goodsData.image)" mode="aspectFill"> </image>
|
||||
<view class="ss-flex-1">
|
||||
<view class="title ss-line-2">
|
||||
{{ goodsData.title }}
|
||||
</view>
|
||||
<view v-if="goodsData.subtitle" class="subtitle ss-line-1">
|
||||
{{ goodsData.subtitle }}
|
||||
</view>
|
||||
<view class="price ss-m-t-8">
|
||||
¥{{ isArray(goodsData.price) ? goodsData.price[0] : goodsData.price }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<s-goods-item
|
||||
:title="goodsData.spuName"
|
||||
:img="goodsData.picUrl"
|
||||
:price="goodsData.price"
|
||||
:skuText="goodsData.introduction"
|
||||
priceColor="#FF3000"
|
||||
:titleWidth="400"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { isArray } from 'lodash';
|
||||
|
||||
const props = defineProps({
|
||||
goodsData: {
|
||||
@@ -27,37 +19,3 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.goods {
|
||||
background: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
|
||||
.image {
|
||||
width: 116rpx;
|
||||
height: 116rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
height: 64rpx;
|
||||
line-height: 32rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #ff3000;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<view class="send-wrap ss-flex">
|
||||
<view class="left ss-flex ss-flex-1">
|
||||
<uni-easyinput
|
||||
class="ss-flex-1 ss-p-l-22"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
v-model="message"
|
||||
placeholder="请输入你要咨询的问题"
|
||||
></uni-easyinput>
|
||||
</view>
|
||||
<text class="sicon-basic bq" @tap.stop="onTools('emoji')"></text>
|
||||
<text
|
||||
v-if="!message"
|
||||
class="sicon-edit"
|
||||
:class="{ 'is-active': toolsMode === 'tools' }"
|
||||
@tap.stop="onTools('tools')"
|
||||
></text>
|
||||
<button v-if="message" class="ss-reset-button send-btn" @tap="sendMessage">
|
||||
发送
|
||||
</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
/**
|
||||
* 消息发送组件
|
||||
*/
|
||||
const props = defineProps({
|
||||
// 消息
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
// 工具模式
|
||||
toolsMode: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(['update:modelValue', 'onTools', 'sendMessage']);
|
||||
const message = computed({
|
||||
get() {
|
||||
return props.modelValue;
|
||||
},
|
||||
set(newValue) {
|
||||
emits(`update:modelValue`, newValue);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 打开工具菜单
|
||||
function onTools(mode) {
|
||||
emits('onTools', mode);
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
function sendMessage() {
|
||||
emits('sendMessage');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.send-wrap {
|
||||
padding: 18rpx 20rpx;
|
||||
background: #fff;
|
||||
|
||||
.left {
|
||||
height: 64rpx;
|
||||
border-radius: 32rpx;
|
||||
background: var(--ui-BG-1);
|
||||
}
|
||||
|
||||
.bq {
|
||||
font-size: 50rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.sicon-edit {
|
||||
font-size: 50rpx;
|
||||
margin-left: 10rpx;
|
||||
transform: rotate(0deg);
|
||||
transition: all linear 0.2s;
|
||||
|
||||
&.is-active {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
|
||||
.send-btn {
|
||||
width: 100rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 30rpx;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
font-size: 26rpx;
|
||||
color: #fff;
|
||||
margin-left: 11rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<!-- 聊天虚拟列表 -->
|
||||
<z-paging ref="pagingRef" v-model="messageList" use-chat-record-mode use-virtual-list
|
||||
cell-height-mode="dynamic" default-page-size="20" :auto-clean-list-when-reload="false"
|
||||
safe-area-inset-bottom bottom-bg-color="#f8f8f8" :back-to-top-style="backToTopStyle"
|
||||
:auto-show-back-to-top="showNewMessageTip" @backToTopClick="onBackToTopClick"
|
||||
@scrolltoupper="onScrollToUpper" @query="queryList">
|
||||
<template #top>
|
||||
<!-- 撑一下顶部导航 -->
|
||||
<view :style="{ height: sys_navBar + 'px' }"></view>
|
||||
</template>
|
||||
<!-- style="transform: scaleY(-1)"必须写,否则会导致列表倒置!!! -->
|
||||
<!-- 注意不要直接在chat-item组件标签上设置style,因为在微信小程序中是无效的,请包一层view -->
|
||||
<template #cell="{item,index}">
|
||||
<view style="transform: scaleY(-1)">
|
||||
<!-- 消息渲染 -->
|
||||
<MessageListItem :message="item" :message-index="index" :message-list="messageList"></MessageListItem>
|
||||
</view>
|
||||
</template>
|
||||
<!-- 底部聊天输入框 -->
|
||||
<template #bottom>
|
||||
<slot name="bottom"></slot>
|
||||
</template>
|
||||
<!-- 查看最新消息 -->
|
||||
<template #backToTop>
|
||||
<text>有新消息</text>
|
||||
</template>
|
||||
</z-paging>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import MessageListItem from '@/pages/chat/components/messageListItem.vue';
|
||||
import { reactive, ref } from 'vue';
|
||||
import KeFuApi from '@/sheep/api/promotion/kefu';
|
||||
import { isEmpty } from '@/sheep/helper/utils';
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const sys_navBar = sheep.$platform.navbar;
|
||||
const messageList = ref([]); // 消息列表
|
||||
const showNewMessageTip = ref(false); // 显示有新消息提示
|
||||
const backToTopStyle = reactive({
|
||||
'width': '100px',
|
||||
'background-color': '#fff',
|
||||
'border-radius': '30px',
|
||||
'box-shadow': '0 2px 4px rgba(0, 0, 0, 0.1)',
|
||||
'display': 'flex',
|
||||
'justifyContent': 'center',
|
||||
'alignItems': 'center',
|
||||
}); // 返回顶部样式
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
const pagingRef = ref(null); // 虚拟列表
|
||||
const queryList = async (pageNo, pageSize) => {
|
||||
// 组件加载时会自动触发此方法,因此默认页面加载时会自动触发,无需手动调用
|
||||
// 这里的pageNo和pageSize会自动计算好,直接传给服务器即可
|
||||
queryParams.pageNo = pageNo;
|
||||
queryParams.pageSize = pageSize;
|
||||
await getMessageList();
|
||||
};
|
||||
// 获得消息分页列表
|
||||
const getMessageList = async () => {
|
||||
const { data } = await KeFuApi.getKefuMessagePage(queryParams);
|
||||
if (isEmpty(data.list)) {
|
||||
return;
|
||||
}
|
||||
pagingRef.value.completeByTotal(data.list, data.total);
|
||||
};
|
||||
/** 刷新消息列表 */
|
||||
const refreshMessageList = (message = undefined) => {
|
||||
if (message !== undefined) {
|
||||
showNewMessageTip.value = true;
|
||||
// 追加数据
|
||||
pagingRef.value.addChatRecordData([message], false);
|
||||
return;
|
||||
}
|
||||
pagingRef.value.reload();
|
||||
};
|
||||
/** 滚动到最新消息 */
|
||||
const onBackToTopClick = (event) => {
|
||||
event(false); // 禁用默认操作
|
||||
pagingRef.value.scrollToBottom();
|
||||
};
|
||||
/** 监听滚动到底部事件(因为 scroll 翻转了顶就是底) */
|
||||
const onScrollToUpper = () => {
|
||||
// 若已是第一页则不做处理
|
||||
if (queryParams.pageNo === 1) {
|
||||
return;
|
||||
}
|
||||
showNewMessageTip.value = false;
|
||||
};
|
||||
defineExpose({ getMessageList, refreshMessageList });
|
||||
</script>
|
||||
@@ -0,0 +1,301 @@
|
||||
<template>
|
||||
<view class="chat-box">
|
||||
<!-- 消息渲染 -->
|
||||
<view class="message-item ss-flex-col scroll-item">
|
||||
<view class="ss-flex ss-row-center ss-col-center">
|
||||
<!-- 日期 -->
|
||||
<view
|
||||
v-if="
|
||||
message.contentType !== KeFuMessageContentTypeEnum.SYSTEM &&
|
||||
showTime(message, messageIndex)
|
||||
"
|
||||
class="date-message"
|
||||
>
|
||||
{{ formatDate(message.createTime) }}
|
||||
</view>
|
||||
<!-- 系统消息 -->
|
||||
<view
|
||||
v-if="message.contentType === KeFuMessageContentTypeEnum.SYSTEM"
|
||||
class="system-message"
|
||||
>
|
||||
{{ message.content }}
|
||||
</view>
|
||||
</view>
|
||||
<!-- 消息体渲染管理员消息和用户消息并左右展示 -->
|
||||
<view
|
||||
v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM"
|
||||
class="ss-flex ss-col-top"
|
||||
:class="[
|
||||
message.senderType === UserTypeEnum.ADMIN
|
||||
? `ss-row-left`
|
||||
: message.senderType === UserTypeEnum.MEMBER
|
||||
? `ss-row-right`
|
||||
: '',
|
||||
]"
|
||||
>
|
||||
<!-- 客服头像 -->
|
||||
<image
|
||||
v-show="message.senderType === UserTypeEnum.ADMIN"
|
||||
class="chat-avatar ss-m-r-24"
|
||||
:src="
|
||||
sheep.$url.cdn(message.senderAvatar) ||
|
||||
sheep.$url.static('/static/img/shop/chat/default.png')
|
||||
"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<!-- 内容 -->
|
||||
<template v-if="message.contentType === KeFuMessageContentTypeEnum.TEXT">
|
||||
<view class="message-box" :class="{ admin: message.senderType === UserTypeEnum.ADMIN }">
|
||||
<mp-html :content="replaceEmoji(message.content)" />
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="message.contentType === KeFuMessageContentTypeEnum.IMAGE">
|
||||
<view
|
||||
class="message-box"
|
||||
:class="{ admin: message.senderType === UserTypeEnum.ADMIN }"
|
||||
:style="{ width: '200rpx' }"
|
||||
>
|
||||
<su-image
|
||||
class="message-img"
|
||||
isPreview
|
||||
:previewList="[sheep.$url.cdn(message.content)]"
|
||||
:current="0"
|
||||
:src="sheep.$url.cdn(message.content)"
|
||||
:height="200"
|
||||
:width="200"
|
||||
mode="aspectFill"
|
||||
></su-image>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="message.contentType === KeFuMessageContentTypeEnum.PRODUCT">
|
||||
<GoodsItem
|
||||
:goodsData="getMessageContent(message)"
|
||||
@tap="sheep.$router.go('/pages/goods/index', { id: getMessageContent(message).spuId })"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="message.contentType === KeFuMessageContentTypeEnum.ORDER">
|
||||
<OrderItem
|
||||
:orderData="getMessageContent(message)"
|
||||
@tap="sheep.$router.go('/pages/order/detail', { id: getMessageContent(message).id })"
|
||||
/>
|
||||
</template>
|
||||
<!-- user头像 -->
|
||||
<image
|
||||
v-if="message.senderType === UserTypeEnum.MEMBER"
|
||||
class="chat-avatar ss-m-l-24"
|
||||
:src="
|
||||
sheep.$url.cdn(message.senderAvatar) ||
|
||||
sheep.$url.static('/static/img/shop/chat/default.png')
|
||||
"
|
||||
mode="aspectFill"
|
||||
>
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, unref } from 'vue';
|
||||
import dayjs from 'dayjs';
|
||||
import { KeFuMessageContentTypeEnum, UserTypeEnum } from '@/pages/chat/util/constants';
|
||||
import { emojiList } from '@/pages/chat/util/emoji';
|
||||
import sheep from '@/sheep';
|
||||
import { formatDate } from '@/sheep/util';
|
||||
import GoodsItem from '@/pages/chat/components/goods.vue';
|
||||
import OrderItem from '@/pages/chat/components/order.vue';
|
||||
|
||||
const props = defineProps({
|
||||
// 消息
|
||||
message: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 消息索引
|
||||
messageIndex: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
// 消息列表
|
||||
messageList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
const getMessageContent = computed(() => (item) => JSON.parse(item.content)); // 解析消息内容
|
||||
|
||||
//======================= 工具 =======================
|
||||
|
||||
const showTime = computed(() => (item, index) => {
|
||||
if (unref(props.messageList)[index + 1]) {
|
||||
let dateString = dayjs(unref(props.messageList)[index + 1].createTime).fromNow();
|
||||
return dateString !== dayjs(unref(item).createTime).fromNow();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// 处理表情
|
||||
function replaceEmoji(data) {
|
||||
let newData = data;
|
||||
if (typeof newData !== 'object') {
|
||||
let reg = /\[(.+?)]/g; // [] 中括号
|
||||
let zhEmojiName = newData.match(reg);
|
||||
if (zhEmojiName) {
|
||||
zhEmojiName.forEach((item) => {
|
||||
let emojiFile = selEmojiFile(item);
|
||||
newData = newData.replace(
|
||||
item,
|
||||
`<img class="chat-img" style="width: 24px;height: 24px;margin: 0 3px;" src="${sheep.$url.cdn(
|
||||
'/static/img/chat/emoji/' + emojiFile,
|
||||
)}"/>`,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
return newData;
|
||||
}
|
||||
|
||||
function selEmojiFile(name) {
|
||||
for (let index in emojiList) {
|
||||
if (emojiList[index].name === name) {
|
||||
return emojiList[index].file;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.message-item {
|
||||
margin-bottom: 33rpx;
|
||||
}
|
||||
|
||||
.date-message,
|
||||
.system-message {
|
||||
width: fit-content;
|
||||
border-radius: 12rpx;
|
||||
padding: 8rpx 16rpx;
|
||||
margin-bottom: 16rpx;
|
||||
background-color: var(--ui-BG-3);
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.chat-avatar {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.send-status {
|
||||
color: #333;
|
||||
height: 80rpx;
|
||||
margin-right: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.loading {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
-webkit-animation: rotating 2s linear infinite;
|
||||
animation: rotating 2s linear infinite;
|
||||
|
||||
@-webkit-keyframes rotating {
|
||||
0% {
|
||||
transform: rotateZ(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotating {
|
||||
0% {
|
||||
transform: rotateZ(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.warning {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
color: #ff3000;
|
||||
}
|
||||
}
|
||||
|
||||
.message-box {
|
||||
max-width: 50%;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
padding: 20rpx;
|
||||
border-radius: 10rpx;
|
||||
color: #fff;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
|
||||
&.admin {
|
||||
background: #fff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
:deep() {
|
||||
.imgred {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.imgred,
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep() {
|
||||
.goods,
|
||||
.order {
|
||||
max-width: 500rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.message-img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
|
||||
.template-wrap {
|
||||
// width: 100%;
|
||||
padding: 20rpx 24rpx;
|
||||
background: #fff;
|
||||
border-radius: 10rpx;
|
||||
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 29rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
font-size: 24rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.error-img {
|
||||
width: 400rpx;
|
||||
height: 400rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,49 +1,36 @@
|
||||
<template>
|
||||
<view class="order">
|
||||
<view class="top ss-flex ss-row-between">
|
||||
<span>{{ orderData.order_sn }}</span>
|
||||
<span>{{ orderData.create_time.split(' ')[1] }}</span>
|
||||
<view class="bg-white order-list-card-box ss-r-10 ss-m-t-14 ss-m-20"
|
||||
:key="orderData.id">
|
||||
<view class="order-card-header ss-flex ss-col-center ss-row-between ss-p-x-20">
|
||||
<view class="order-no">订单号:{{ orderData.no }}</view>
|
||||
<view class="order-state ss-font-26" :class="formatOrderColor(orderData)">
|
||||
{{ formatOrderStatus(orderData) }}
|
||||
</view>
|
||||
</view>
|
||||
<template v-if="from != 'msg'">
|
||||
<view class="bottom ss-flex" v-for="item in orderData.items" :key="item">
|
||||
<image class="image" :src="sheep.$url.cdn(item.goods_image)" mode="aspectFill"> </image>
|
||||
<view class="ss-flex-1">
|
||||
<view class="title ss-line-2">
|
||||
{{ item.goods_title }}
|
||||
</view>
|
||||
<view v-if="item.goods_num" class="num ss-m-b-10"> 数量:{{ item.goods_num }} </view>
|
||||
<view class="ss-flex ss-row-between ss-m-t-8">
|
||||
<span class="price">¥{{ item.goods_price }}</span>
|
||||
<span class="status">{{ orderData.status_text }}</span>
|
||||
</view>
|
||||
<view class="border-bottom" v-for="item in orderData.items" :key="item.id">
|
||||
<s-goods-item
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
/>
|
||||
</view>
|
||||
<view class="pay-box ss-m-t-30 ss-flex ss-row-right ss-p-r-20">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="discounts-title pay-color">共 {{ orderData.productCount }} 件商品,总金额:</view>
|
||||
<view class="discounts-money pay-color">
|
||||
¥{{ fen2yuan(orderData.payPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="bottom ss-flex" v-for="item in [orderData.items[0]]" :key="item">
|
||||
<image class="image" :src="sheep.$url.cdn(item.goods_image)" mode="aspectFill"> </image>
|
||||
<view class="ss-flex-1">
|
||||
<view class="title title-1 ss-line-1">
|
||||
{{ item.goods_title }}
|
||||
</view>
|
||||
<view class="order-total ss-flex ss-row-between ss-m-t-8">
|
||||
<span>共{{ orderData.items.length }}件商品</span>
|
||||
<span>合计 ¥{{ orderData.pay_fee }}</span>
|
||||
</view>
|
||||
<view class="ss-flex ss-row-right ss-m-t-8">
|
||||
<span class="status">{{ orderData.status_text }}</span>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { fen2yuan, formatOrderColor, formatOrderStatus } from '@/sheep/hooks/useGoods';
|
||||
|
||||
const props = defineProps({
|
||||
from: String,
|
||||
orderData: {
|
||||
type: Object,
|
||||
default: {},
|
||||
@@ -52,71 +39,76 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order {
|
||||
background: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
.order-list-card-box {
|
||||
.order-card-header {
|
||||
height: 80rpx;
|
||||
|
||||
.top {
|
||||
line-height: 40rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #999;
|
||||
border-bottom: 1px solid rgba(223, 223, 223, 0.5);
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.image {
|
||||
flex-shrink: 0;
|
||||
width: 116rpx;
|
||||
height: 116rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
height: 64rpx;
|
||||
line-height: 32rpx;
|
||||
.order-no {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
&.title-1 {
|
||||
height: 32rpx;
|
||||
width: 300rpx;
|
||||
.order-state {}
|
||||
}
|
||||
.pay-box {
|
||||
.discounts-title {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.discounts-money {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.pay-color {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
.order-card-footer {
|
||||
height: 100rpx;
|
||||
|
||||
.more-item-box {
|
||||
padding: 20rpx;
|
||||
|
||||
.more-item {
|
||||
height: 60rpx;
|
||||
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.num {
|
||||
.more-btn {
|
||||
color: $dark-9;
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.price {
|
||||
.content {
|
||||
width: 154rpx;
|
||||
color: #333333;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #ff3000;
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.order-total {
|
||||
line-height: 28rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
.warning-color {
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.danger-color {
|
||||
color: #ff3000;
|
||||
}
|
||||
|
||||
.success-color {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.info-color {
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
@@ -14,11 +14,11 @@
|
||||
<view
|
||||
class="item"
|
||||
v-for="item in state.pagination.data"
|
||||
:key="item"
|
||||
:key="item.id"
|
||||
@tap="emits('select', { type: mode, data: item })"
|
||||
>
|
||||
<template v-if="mode == 'goods'">
|
||||
<GoodsItem :goodsData="item.goods" />
|
||||
<GoodsItem :goodsData="item" />
|
||||
</template>
|
||||
<template v-if="mode == 'order'">
|
||||
<OrderItem :orderData="item" />
|
||||
@@ -32,8 +32,7 @@
|
||||
|
||||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import GoodsItem from './goods.vue';
|
||||
import OrderItem from './order.vue';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
@@ -83,7 +82,7 @@
|
||||
page,
|
||||
list_rows,
|
||||
});
|
||||
let orderList = _.concat(state.pagination.data, res.data.data);
|
||||
let orderList = _.concat(state.pagination.data, res.data.list);
|
||||
state.pagination = {
|
||||
...res.data,
|
||||
data: orderList,
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<su-popup
|
||||
:show="showTools"
|
||||
@close="handleClose"
|
||||
>
|
||||
<view class="ss-modal-box ss-flex-col">
|
||||
<slot></slot>
|
||||
<view class="content ss-flex ss-flex-1">
|
||||
<template v-if="toolsMode === 'emoji'">
|
||||
<swiper
|
||||
class="emoji-swiper"
|
||||
:indicator-dots="true"
|
||||
circular
|
||||
indicator-active-color="#7063D2"
|
||||
indicator-color="rgba(235, 231, 255, 1)"
|
||||
:autoplay="false"
|
||||
:interval="3000"
|
||||
:duration="1000"
|
||||
>
|
||||
<swiper-item v-for="emoji in emojiPage" :key="emoji">
|
||||
<view class="ss-flex ss-flex-wrap">
|
||||
<image
|
||||
v-for="item in emoji" :key="item"
|
||||
class="emoji-img"
|
||||
:src="sheep.$url.cdn(`/static/img/chat/emoji/${item.file}`)"
|
||||
@tap="onEmoji(item)"
|
||||
>
|
||||
</image>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="image">
|
||||
<s-uploader
|
||||
file-mediatype="image"
|
||||
:imageStyles="{ width: 50, height: 50, border: false }"
|
||||
@select="imageSelect({ type: 'image', data: $event })"
|
||||
>
|
||||
<image
|
||||
class="icon"
|
||||
:src="sheep.$url.static('/static/img/shop/chat/image.png')"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
</s-uploader>
|
||||
<view>图片</view>
|
||||
</view>
|
||||
<view class="goods" @tap="onShowSelect('goods')">
|
||||
<image
|
||||
class="icon"
|
||||
:src="sheep.$url.static('/static/img/shop/chat/goods.png')"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view>商品</view>
|
||||
</view>
|
||||
<view class="order" @tap="onShowSelect('order')">
|
||||
<image
|
||||
class="icon"
|
||||
:src="sheep.$url.static('/static/img/shop/chat/order.png')"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view>订单</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</su-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
/**
|
||||
* 聊天工具
|
||||
*/
|
||||
import { emojiPage } from '@/pages/chat/util/emoji';
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const props = defineProps({
|
||||
// 工具模式
|
||||
toolsMode: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
// 控制工具菜单弹出
|
||||
showTools: {
|
||||
type: Boolean,
|
||||
default: () => false,
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(['onEmoji', 'imageSelect', 'onShowSelect', 'close']);
|
||||
|
||||
// 关闭弹出工具菜单
|
||||
function handleClose() {
|
||||
emits('close');
|
||||
}
|
||||
|
||||
// 选择表情
|
||||
function onEmoji(emoji) {
|
||||
emits('onEmoji', emoji);
|
||||
}
|
||||
|
||||
// 选择图片
|
||||
function imageSelect(val) {
|
||||
emits('imageSelect', val);
|
||||
}
|
||||
|
||||
// 选择商品或订单
|
||||
function onShowSelect(mode) {
|
||||
emits('onShowSelect', mode);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
width: 100%;
|
||||
align-content: space-around;
|
||||
border-top: 1px solid #dfdfdf;
|
||||
padding: 20rpx 0 0;
|
||||
|
||||
.emoji-swiper {
|
||||
width: 100%;
|
||||
height: 280rpx;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.emoji-img {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
display: inline-block;
|
||||
margin: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.image,
|
||||
.goods,
|
||||
.order {
|
||||
width: 33.3%;
|
||||
height: 280rpx;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.icon {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
margin-bottom: 21rpx;
|
||||
}
|
||||
}
|
||||
|
||||
:deep() {
|
||||
.uni-file-picker__container {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.file-picker__box {
|
||||
display: none;
|
||||
|
||||
&:last-of-type {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+97
-780
@@ -1,278 +1,19 @@
|
||||
<template>
|
||||
<s-layout class="chat-wrap" title="客服" navbar="inner">
|
||||
<div class="status">
|
||||
{{ socketState.isConnect ? customerServiceInfo.title : '网络已断开,请检查网络后刷新重试' }}
|
||||
</div>
|
||||
<s-layout class="chat-wrap" :title="!isReconnecting ? '连接客服成功' : '会话重连中'" navbar="inner">
|
||||
<!-- 覆盖头部导航栏背景颜色 -->
|
||||
<div class="page-bg" :style="{ height: sys_navBar + 'px' }"></div>
|
||||
<view class="chat-box" :style="{ height: pageHeight + 'px' }">
|
||||
<scroll-view
|
||||
:style="{ height: pageHeight + 'px' }"
|
||||
scroll-y="true"
|
||||
:scroll-with-animation="false"
|
||||
:enable-back-to-top="true"
|
||||
:scroll-into-view="chat.scrollInto"
|
||||
>
|
||||
<button
|
||||
class="loadmore-btn ss-reset-button"
|
||||
v-if="
|
||||
chatList.length &&
|
||||
chatHistoryPagination.lastPage > 1 &&
|
||||
loadingMap[chatHistoryPagination.loadStatus].title
|
||||
"
|
||||
@click="onLoadMore"
|
||||
>
|
||||
{{ loadingMap[chatHistoryPagination.loadStatus].title }}
|
||||
<i
|
||||
class="loadmore-icon sa-m-l-6"
|
||||
:class="loadingMap[chatHistoryPagination.loadStatus].icon"
|
||||
></i>
|
||||
</button>
|
||||
<view class="message-item ss-flex-col" v-for="(item, index) in chatList" :key="index">
|
||||
<view class="ss-flex ss-row-center ss-col-center">
|
||||
<!-- 日期 -->
|
||||
<view v-if="item.from !== 'system' && showTime(item, index)" class="date-message">
|
||||
{{ formatTime(item.date) }}
|
||||
</view>
|
||||
<!-- 系统消息 -->
|
||||
<view v-if="item.from === 'system'" class="system-message">
|
||||
{{ item.content.text }}
|
||||
</view>
|
||||
</view>
|
||||
<!-- 常见问题 -->
|
||||
<view v-if="item.mode === 'template' && item.content.list.length" class="template-wrap">
|
||||
<view class="title">猜你想问</view>
|
||||
<view
|
||||
class="item"
|
||||
v-for="(item, index) in item.content.list"
|
||||
:key="index"
|
||||
@click="onTemplateList(item)"
|
||||
>
|
||||
* {{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
v-if="
|
||||
(item.from === 'customer_service' && item.mode !== 'template') ||
|
||||
item.from === 'customer'
|
||||
"
|
||||
class="ss-flex ss-col-top"
|
||||
:class="[
|
||||
item.from === 'customer_service'
|
||||
? `ss-row-left`
|
||||
: item.from === 'customer'
|
||||
? `ss-row-right`
|
||||
: '',
|
||||
]"
|
||||
>
|
||||
<!-- 客服头像 -->
|
||||
<image
|
||||
v-show="item.from === 'customer_service'"
|
||||
class="chat-avatar ss-m-r-24"
|
||||
:src="
|
||||
sheep.$url.cdn(item?.sender?.avatar) ||
|
||||
sheep.$url.static('/static/img/shop/chat/default.png')
|
||||
"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
|
||||
<!-- 发送状态 -->
|
||||
<span
|
||||
v-if="
|
||||
item.from === 'customer' &&
|
||||
index == chatData.chatList.length - 1 &&
|
||||
chatData.isSendSucces !== 0
|
||||
"
|
||||
class="send-status"
|
||||
>
|
||||
<image
|
||||
v-if="chatData.isSendSucces == -1"
|
||||
class="loading"
|
||||
:src="sheep.$url.static('/static/img/shop/chat/loading.png')"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<!-- <image
|
||||
v-if="chatData.isSendSucces == 1"
|
||||
class="warning"
|
||||
:src="sheep.$url.static('/static/img/shop/chat/warning.png')"
|
||||
mode="aspectFill"
|
||||
@click="onAgainSendMessage(item)"
|
||||
></image> -->
|
||||
</span>
|
||||
|
||||
<!-- 内容 -->
|
||||
<template v-if="item.mode === 'text'">
|
||||
<view class="message-box" :class="[item.from]">
|
||||
<div
|
||||
class="message-text ss-flex ss-flex-wrap"
|
||||
@click="onRichtext"
|
||||
v-html="replaceEmoji(item.content.text)"
|
||||
></div>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.mode === 'image'">
|
||||
<view class="message-box" :class="[item.from]" :style="{ width: '200rpx' }">
|
||||
<su-image
|
||||
class="message-img"
|
||||
isPreview
|
||||
:previewList="[sheep.$url.cdn(item.content.url)]"
|
||||
:current="0"
|
||||
:src="sheep.$url.cdn(item.content.url)"
|
||||
:height="200"
|
||||
:width="200"
|
||||
mode="aspectFill"
|
||||
></su-image>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.mode === 'goods'">
|
||||
<GoodsItem
|
||||
:goodsData="item.content.item"
|
||||
@tap="
|
||||
sheep.$router.go('/pages/goods/index', {
|
||||
id: item.content.item.id,
|
||||
})
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="item.mode === 'order'">
|
||||
<OrderItem
|
||||
from="msg"
|
||||
:orderData="item.content.item"
|
||||
@tap="
|
||||
sheep.$router.go('/pages/order/detail', {
|
||||
id: item.content.item.id,
|
||||
})
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<!-- user头像 -->
|
||||
<image
|
||||
v-show="item.from === 'customer'"
|
||||
class="chat-avatar ss-m-l-24"
|
||||
:src="sheep.$url.cdn(customerUserInfo.avatar)"
|
||||
mode="aspectFill"
|
||||
>
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
<view id="scrollBottom"></view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<su-fixed bottom>
|
||||
<view class="send-wrap ss-flex">
|
||||
<view class="left ss-flex ss-flex-1">
|
||||
<uni-easyinput
|
||||
class="ss-flex-1 ss-p-l-22"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
v-model="chat.msg"
|
||||
placeholder="请输入你要咨询的问题"
|
||||
></uni-easyinput>
|
||||
</view>
|
||||
<text class="sicon-basic bq" @tap.stop="onTools('emoji')"></text>
|
||||
<text
|
||||
v-if="!chat.msg"
|
||||
class="sicon-edit"
|
||||
:class="{ 'is-active': chat.toolsMode == 'tools' }"
|
||||
@tap.stop="onTools('tools')"
|
||||
></text>
|
||||
<button v-if="chat.msg" class="ss-reset-button send-btn" @tap="onSendMessage">
|
||||
发送
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
<su-popup
|
||||
:show="chat.showTools"
|
||||
@close="
|
||||
chat.showTools = false;
|
||||
chat.toolsMode = '';
|
||||
"
|
||||
>
|
||||
<view class="ss-modal-box ss-flex-col">
|
||||
<view class="send-wrap ss-flex">
|
||||
<view class="left ss-flex ss-flex-1">
|
||||
<uni-easyinput
|
||||
class="ss-flex-1 ss-p-l-22"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
v-model="chat.msg"
|
||||
placeholder="请输入你要咨询的问题"
|
||||
></uni-easyinput>
|
||||
</view>
|
||||
<text class="sicon-basic bq" @tap.stop="onTools('emoji')"></text>
|
||||
<text></text>
|
||||
<text
|
||||
v-if="!chat.msg"
|
||||
class="sicon-edit"
|
||||
:class="{ 'is-active': chat.toolsMode == 'tools' }"
|
||||
@tap.stop="onTools('tools')"
|
||||
></text>
|
||||
<button v-if="chat.msg" class="ss-reset-button send-btn" @tap="onSendMessage">
|
||||
发送
|
||||
</button>
|
||||
</view>
|
||||
<view class="content ss-flex ss-flex-1">
|
||||
<template v-if="chat.toolsMode == 'emoji'">
|
||||
<swiper
|
||||
class="emoji-swiper"
|
||||
:indicator-dots="true"
|
||||
circular
|
||||
indicator-active-color="#7063D2"
|
||||
indicator-color="rgba(235, 231, 255, 1)"
|
||||
:autoplay="false"
|
||||
:interval="3000"
|
||||
:duration="1000"
|
||||
>
|
||||
<swiper-item v-for="emoji in emojiPage" :key="emoji">
|
||||
<view class="ss-flex ss-flex-wrap">
|
||||
<template v-for="item in emoji" :key="item">
|
||||
<image
|
||||
class="emoji-img"
|
||||
:src="sheep.$url.cdn(`/static/img/chat/emoji/${item.file}`)"
|
||||
@tap="onEmoji(item)"
|
||||
>
|
||||
</image>
|
||||
</template>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="image">
|
||||
<s-uploader
|
||||
file-mediatype="image"
|
||||
:imageStyles="{ width: 50, height: 50, border: false }"
|
||||
@select="onSelect({ type: 'image', data: $event })"
|
||||
>
|
||||
<image
|
||||
class="icon"
|
||||
:src="sheep.$url.static('/static/img/shop/chat/image.png')"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
</s-uploader>
|
||||
<view>图片</view>
|
||||
</view>
|
||||
<view class="goods" @tap="onShowSelect('goods')">
|
||||
<image
|
||||
class="icon"
|
||||
:src="sheep.$url.static('/static/img/shop/chat/goods.png')"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view>商品</view>
|
||||
</view>
|
||||
<view class="order" @tap="onShowSelect('order')">
|
||||
<image
|
||||
class="icon"
|
||||
:src="sheep.$url.static('/static/img/shop/chat/order.png')"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view>订单</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</su-popup>
|
||||
|
||||
<!-- 聊天区域 -->
|
||||
<MessageList ref="messageListRef">
|
||||
<template #bottom>
|
||||
<message-input v-model="chat.msg" @on-tools="onTools" @send-message="onSendMessage"></message-input>
|
||||
</template>
|
||||
</MessageList>
|
||||
<!-- 聊天工具 -->
|
||||
<tools-popup :show-tools="chat.showTools" :tools-mode="chat.toolsMode" @close="handleToolsClose"
|
||||
@on-emoji="onEmoji" @image-select="onSelect" @on-show-select="onShowSelect">
|
||||
<message-input v-model="chat.msg" @on-tools="onTools" @send-message="onSendMessage"></message-input>
|
||||
</tools-popup>
|
||||
<!-- 商品订单选择 -->
|
||||
<SelectPopup
|
||||
:mode="chat.selectMode"
|
||||
:show="chat.showSelect"
|
||||
@@ -283,99 +24,61 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import MessageList from '@/pages/chat/components/messageList.vue';
|
||||
import { reactive, ref, toRefs } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { computed, reactive, toRefs } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { emojiList, emojiPage } from './emoji.js';
|
||||
import SelectPopup from './components/select-popup.vue';
|
||||
import GoodsItem from './components/goods.vue';
|
||||
import OrderItem from './components/order.vue';
|
||||
import { useChatWebSocket } from './socket';
|
||||
|
||||
const {
|
||||
socketInit,
|
||||
state: chatData,
|
||||
socketSendMsg,
|
||||
formatChatInput,
|
||||
socketHistoryList,
|
||||
onDrop,
|
||||
onPaste,
|
||||
getFocus,
|
||||
// upload,
|
||||
getUserToken,
|
||||
// socketTest,
|
||||
showTime,
|
||||
formatTime,
|
||||
} = useChatWebSocket();
|
||||
const chatList = toRefs(chatData).chatList;
|
||||
const customerServiceInfo = toRefs(chatData).customerServerInfo;
|
||||
const chatHistoryPagination = toRefs(chatData).chatHistoryPagination;
|
||||
const customerUserInfo = toRefs(chatData).customerUserInfo;
|
||||
const socketState = toRefs(chatData).socketState;
|
||||
import ToolsPopup from '@/pages/chat/components/toolsPopup.vue';
|
||||
import MessageInput from '@/pages/chat/components/messageInput.vue';
|
||||
import SelectPopup from '@/pages/chat/components/select-popup.vue';
|
||||
import { KeFuMessageContentTypeEnum, WebSocketMessageTypeConstants } from '@/pages/chat/util/constants';
|
||||
import FileApi from '@/sheep/api/infra/file';
|
||||
import KeFuApi from '@/sheep/api/promotion/kefu';
|
||||
import { useWebSocket } from '@/sheep/hooks/useWebSocket';
|
||||
|
||||
const sys_navBar = sheep.$platform.navbar;
|
||||
const chatConfig = computed(() => sheep.$store('app').chat);
|
||||
|
||||
const { screenHeight, safeAreaInsets, safeArea, screenWidth } = sheep.$platform.device;
|
||||
const pageHeight = safeArea.height - 44 - 35 - 50;
|
||||
|
||||
const chatStatus = {
|
||||
online: {
|
||||
text: '在线',
|
||||
colorVariate: '#46c55f',
|
||||
},
|
||||
offline: {
|
||||
text: '离线',
|
||||
colorVariate: '#b5b5b5',
|
||||
},
|
||||
busy: {
|
||||
text: '忙碌',
|
||||
colorVariate: '#ff0e1b',
|
||||
},
|
||||
};
|
||||
|
||||
// 加载更多
|
||||
const loadingMap = {
|
||||
loadmore: {
|
||||
title: '查看更多',
|
||||
icon: 'el-icon-d-arrow-left',
|
||||
},
|
||||
nomore: {
|
||||
title: '没有更多了',
|
||||
icon: '',
|
||||
},
|
||||
loading: {
|
||||
title: '加载中... ',
|
||||
icon: 'el-icon-loading',
|
||||
},
|
||||
};
|
||||
const onLoadMore = () => {
|
||||
chatHistoryPagination.value.page < chatHistoryPagination.value.lastPage && socketHistoryList();
|
||||
};
|
||||
|
||||
const chat = reactive({
|
||||
msg: '',
|
||||
scrollInto: '',
|
||||
|
||||
showTools: false,
|
||||
toolsMode: '',
|
||||
|
||||
showSelect: false,
|
||||
selectMode: '',
|
||||
chatStyle: {
|
||||
mode: 'inner',
|
||||
color: '#F8270F',
|
||||
type: 'color',
|
||||
alwaysShow: 1,
|
||||
src: '',
|
||||
list: {},
|
||||
},
|
||||
});
|
||||
|
||||
// 发送消息
|
||||
async function onSendMessage() {
|
||||
if (!chat.msg) return;
|
||||
try {
|
||||
const data = {
|
||||
contentType: KeFuMessageContentTypeEnum.TEXT,
|
||||
content: chat.msg,
|
||||
};
|
||||
await KeFuApi.sendKefuMessage(data);
|
||||
await messageListRef.value.refreshMessageList();
|
||||
chat.msg = '';
|
||||
} finally {
|
||||
chat.showTools = false;
|
||||
}
|
||||
}
|
||||
|
||||
const messageListRef = ref();
|
||||
|
||||
//======================= 聊天工具相关 start =======================
|
||||
|
||||
function handleToolsClose() {
|
||||
chat.showTools = false;
|
||||
chat.toolsMode = '';
|
||||
}
|
||||
|
||||
function onEmoji(item) {
|
||||
chat.msg += item.name;
|
||||
}
|
||||
|
||||
// 点击工具栏开关
|
||||
function onTools(mode) {
|
||||
if (!socketState.value.isConnect) {
|
||||
sheep.$helper.toast(socketState.value.tip || '您已掉线!请返回重试');
|
||||
if (isReconnecting.value) {
|
||||
sheep.$helper.toast('您已掉线!请返回重试');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -395,205 +98,77 @@
|
||||
}
|
||||
|
||||
async function onSelect({ type, data }) {
|
||||
let msg = '';
|
||||
let msg;
|
||||
switch (type) {
|
||||
case 'image':
|
||||
const { path, fullurl } = await sheep.$api.app.upload(data.tempFiles[0].path, 'default');
|
||||
const res = await FileApi.uploadFile(data.tempFiles[0].path);
|
||||
msg = {
|
||||
from: 'customer',
|
||||
mode: 'image',
|
||||
date: new Date().getTime(),
|
||||
content: {
|
||||
url: fullurl,
|
||||
path: path,
|
||||
},
|
||||
contentType: KeFuMessageContentTypeEnum.IMAGE,
|
||||
content: res.data,
|
||||
};
|
||||
break;
|
||||
case 'goods':
|
||||
msg = {
|
||||
from: 'customer',
|
||||
mode: 'goods',
|
||||
date: new Date().getTime(),
|
||||
content: {
|
||||
item: {
|
||||
id: data.goods.id,
|
||||
title: data.goods.title,
|
||||
image: data.goods.image,
|
||||
price: data.goods.price,
|
||||
stock: data.goods.stock,
|
||||
},
|
||||
},
|
||||
contentType: KeFuMessageContentTypeEnum.PRODUCT,
|
||||
content: JSON.stringify(data),
|
||||
};
|
||||
break;
|
||||
case 'order':
|
||||
msg = {
|
||||
from: 'customer',
|
||||
mode: 'order',
|
||||
date: new Date().getTime(),
|
||||
content: {
|
||||
item: {
|
||||
id: data.id,
|
||||
order_sn: data.order_sn,
|
||||
create_time: data.create_time,
|
||||
pay_fee: data.pay_fee,
|
||||
items: data.items.filter((item) => ({
|
||||
goods_id: item.goods_id,
|
||||
goods_title: item.goods_title,
|
||||
goods_image: item.goods_image,
|
||||
goods_price: item.goods_price,
|
||||
})),
|
||||
status_text: data.status_text,
|
||||
},
|
||||
},
|
||||
contentType: KeFuMessageContentTypeEnum.ORDER,
|
||||
content: JSON.stringify(data),
|
||||
};
|
||||
break;
|
||||
}
|
||||
if (msg) {
|
||||
socketSendMsg(msg, () => {
|
||||
scrollBottom();
|
||||
});
|
||||
// 发送消息
|
||||
// scrollBottom();
|
||||
await KeFuApi.sendKefuMessage(msg);
|
||||
await messageListRef.value.refreshMessageList();
|
||||
chat.showTools = false;
|
||||
chat.showSelect = false;
|
||||
chat.selectMode = '';
|
||||
}
|
||||
}
|
||||
|
||||
function onAgainSendMessage(item) {
|
||||
if (!socketState.value.isConnect) {
|
||||
sheep.$helper.toast(socketState.value.tip || '您已掉线!请返回重试');
|
||||
return;
|
||||
}
|
||||
if (!item) return;
|
||||
const data = {
|
||||
from: 'customer',
|
||||
mode: 'text',
|
||||
date: new Date().getTime(),
|
||||
content: item.content,
|
||||
};
|
||||
socketSendMsg(data, () => {
|
||||
scrollBottom();
|
||||
});
|
||||
}
|
||||
|
||||
function onSendMessage() {
|
||||
if (!socketState.value.isConnect) {
|
||||
sheep.$helper.toast(socketState.value.tip || '您已掉线!请返回重试');
|
||||
return;
|
||||
}
|
||||
if (!chat.msg) return;
|
||||
const data = {
|
||||
from: 'customer',
|
||||
mode: 'text',
|
||||
date: new Date().getTime(),
|
||||
content: {
|
||||
text: chat.msg,
|
||||
},
|
||||
};
|
||||
socketSendMsg(data, () => {
|
||||
scrollBottom();
|
||||
});
|
||||
chat.showTools = false;
|
||||
// scrollBottom();
|
||||
setTimeout(() => {
|
||||
chat.msg = '';
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// 点击猜你想问
|
||||
function onTemplateList(e) {
|
||||
if (!socketState.value.isConnect) {
|
||||
sheep.$helper.toast(socketState.value.tip || '您已掉线!请返回重试');
|
||||
return;
|
||||
}
|
||||
const data = {
|
||||
from: 'customer',
|
||||
mode: 'text',
|
||||
date: new Date().getTime(),
|
||||
content: {
|
||||
text: e.title,
|
||||
},
|
||||
customData: {
|
||||
question_id: e.id,
|
||||
},
|
||||
};
|
||||
socketSendMsg(data, () => {
|
||||
scrollBottom();
|
||||
});
|
||||
// scrollBottom();
|
||||
}
|
||||
|
||||
function onEmoji(item) {
|
||||
chat.msg += item.name;
|
||||
}
|
||||
|
||||
function selEmojiFile(name) {
|
||||
for (let index in emojiList) {
|
||||
if (emojiList[index].name === name) {
|
||||
return emojiList[index].file;
|
||||
//======================= 聊天工具相关 end =======================
|
||||
const { options } = useWebSocket({
|
||||
// 连接成功
|
||||
onConnected: async () => {
|
||||
},
|
||||
// 收到消息
|
||||
onMessage: async (data) => {
|
||||
const type = data.type;
|
||||
if (!type) {
|
||||
console.error('未知的消息类型:' + data.value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function replaceEmoji(data) {
|
||||
let newData = data;
|
||||
if (typeof newData !== 'object') {
|
||||
let reg = /\[(.+?)\]/g; // [] 中括号
|
||||
let zhEmojiName = newData.match(reg);
|
||||
if (zhEmojiName) {
|
||||
zhEmojiName.forEach((item) => {
|
||||
let emojiFile = selEmojiFile(item);
|
||||
newData = newData.replace(
|
||||
item,
|
||||
`<img class="chat-img" style="width: 24px;height: 24px;margin: 0 3px;" src="${sheep.$url.cdn(
|
||||
'/static/img/chat/emoji/' + emojiFile,
|
||||
)}"/>`,
|
||||
);
|
||||
});
|
||||
// 2.2 消息类型:KEFU_MESSAGE_TYPE
|
||||
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_TYPE) {
|
||||
// 刷新消息列表
|
||||
await messageListRef.value.refreshMessageList(JSON.parse(data.content));
|
||||
return;
|
||||
}
|
||||
}
|
||||
return newData;
|
||||
}
|
||||
|
||||
function scrollBottom() {
|
||||
let timeout = null;
|
||||
chat.scrollInto = '';
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => {
|
||||
chat.scrollInto = 'scrollBottom';
|
||||
}, 100);
|
||||
}
|
||||
|
||||
onLoad(async () => {
|
||||
const { error } = await getUserToken();
|
||||
if (error === 0) {
|
||||
socketInit(chatConfig.value, () => {
|
||||
scrollBottom();
|
||||
});
|
||||
} else {
|
||||
socketState.value.isConnect = false;
|
||||
}
|
||||
// 2.3 消息类型:KEFU_MESSAGE_ADMIN_READ
|
||||
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_ADMIN_READ) {
|
||||
console.log('管理员已读消息');
|
||||
}
|
||||
},
|
||||
});
|
||||
const isReconnecting = toRefs(options).isReconnecting; // 重连状态
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-bg {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
background-size: 750rpx 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
<style scoped lang="scss">
|
||||
.chat-wrap {
|
||||
// :deep() {
|
||||
// .ui-navbar-box {
|
||||
// background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
// }
|
||||
// }
|
||||
|
||||
.page-bg {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: var(--ui-BG-Main);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.status {
|
||||
position: relative;
|
||||
@@ -608,263 +183,5 @@
|
||||
font-weight: 400;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.chat-box {
|
||||
padding: 0 20rpx 0;
|
||||
|
||||
.loadmore-btn {
|
||||
width: 98%;
|
||||
height: 40px;
|
||||
font-size: 12px;
|
||||
color: #8c8c8c;
|
||||
|
||||
.loadmore-icon {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
.message-item {
|
||||
margin-bottom: 33rpx;
|
||||
}
|
||||
|
||||
.date-message,
|
||||
.system-message {
|
||||
width: fit-content;
|
||||
border-radius: 12rpx;
|
||||
padding: 8rpx 16rpx;
|
||||
margin-bottom: 16rpx;
|
||||
background-color: var(--ui-BG-3);
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.chat-avatar {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.send-status {
|
||||
color: #333;
|
||||
height: 80rpx;
|
||||
margin-right: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.loading {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
-webkit-animation: rotating 2s linear infinite;
|
||||
animation: rotating 2s linear infinite;
|
||||
|
||||
@-webkit-keyframes rotating {
|
||||
0% {
|
||||
transform: rotateZ(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotating {
|
||||
0% {
|
||||
transform: rotateZ(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.warning {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
color: #ff3000;
|
||||
}
|
||||
}
|
||||
|
||||
.message-box {
|
||||
max-width: 50%;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
// max-width: 500rpx;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
padding: 20rpx;
|
||||
border-radius: 10rpx;
|
||||
color: #fff;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
|
||||
&.customer_service {
|
||||
background: #fff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
:deep() {
|
||||
.imgred {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.imgred,
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep() {
|
||||
.goods,
|
||||
.order {
|
||||
max-width: 500rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.message-img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
|
||||
.template-wrap {
|
||||
// width: 100%;
|
||||
padding: 20rpx 24rpx;
|
||||
background: #fff;
|
||||
border-radius: 10rpx;
|
||||
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 29rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
font-size: 24rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.error-img {
|
||||
width: 400rpx;
|
||||
height: 400rpx;
|
||||
}
|
||||
|
||||
#scrollBottom {
|
||||
height: 120rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.send-wrap {
|
||||
padding: 18rpx 20rpx;
|
||||
background: #fff;
|
||||
|
||||
.left {
|
||||
height: 64rpx;
|
||||
border-radius: 32rpx;
|
||||
background: var(--ui-BG-1);
|
||||
}
|
||||
|
||||
.bq {
|
||||
font-size: 50rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.sicon-edit {
|
||||
font-size: 50rpx;
|
||||
margin-left: 10rpx;
|
||||
transform: rotate(0deg);
|
||||
transition: all linear 0.2s;
|
||||
|
||||
&.is-active {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
|
||||
.send-btn {
|
||||
width: 100rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 30rpx;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
font-size: 26rpx;
|
||||
color: #fff;
|
||||
margin-left: 11rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
align-content: space-around;
|
||||
border-top: 1px solid #dfdfdf;
|
||||
padding: 20rpx 0 0;
|
||||
|
||||
.emoji-swiper {
|
||||
width: 100%;
|
||||
height: 280rpx;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.emoji-img {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
display: inline-block;
|
||||
margin: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.image,
|
||||
.goods,
|
||||
.order {
|
||||
width: 33.3%;
|
||||
height: 280rpx;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.icon {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
margin-bottom: 21rpx;
|
||||
}
|
||||
}
|
||||
|
||||
:deep() {
|
||||
.uni-file-picker__container {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.file-picker__box {
|
||||
display: none;
|
||||
|
||||
&:last-of-type {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.chat-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 0 3px;
|
||||
}
|
||||
.full-img {
|
||||
object-fit: cover;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,821 +0,0 @@
|
||||
import { reactive, ref, unref } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
// import chat from '@/sheep/api/chat';
|
||||
import dayjs from 'dayjs';
|
||||
import io from '@hyoga/uni-socket.io';
|
||||
|
||||
export function useChatWebSocket(socketConfig) {
|
||||
let SocketIo = null;
|
||||
|
||||
// chat状态数据
|
||||
const state = reactive({
|
||||
chatDotNum: 0, //总状态红点
|
||||
chatList: [], //会话信息
|
||||
customerUserInfo: {}, //用户信息
|
||||
customerServerInfo: {
|
||||
//客服信息
|
||||
title: '连接中...',
|
||||
state: 'connecting',
|
||||
avatar: null,
|
||||
nickname: '',
|
||||
},
|
||||
socketState: {
|
||||
isConnect: true, //是否连接成功
|
||||
isConnecting: false, //重连中,不允许新的socket开启。
|
||||
tip: '',
|
||||
},
|
||||
chatHistoryPagination: {
|
||||
page: 0, //当前页
|
||||
list_rows: 10, //每页条数
|
||||
last_id: 0, //最后条ID
|
||||
lastPage: 0, //总共多少页
|
||||
loadStatus: 'loadmore', //loadmore-加载前的状态,loading-加载中的状态,nomore-没有更多的状态
|
||||
},
|
||||
templateChatList: [], //猜你想问
|
||||
|
||||
chatConfig: {}, // 配置信息
|
||||
|
||||
isSendSucces: -1, // 是否发送成功 -1=发送中|0=发送成功|1发送失败
|
||||
});
|
||||
|
||||
/**
|
||||
* 连接初始化
|
||||
* @param {Object} config - 配置信息
|
||||
* @param {Function} callBack -回调函数,有新消息接入,保持底部
|
||||
*/
|
||||
const socketInit = (config, callBack) => {
|
||||
state.chatConfig = config;
|
||||
if (SocketIo && SocketIo.connected) return; // 如果socket已经连接,返回false
|
||||
if (state.socketState.isConnecting) return; // 重连中,返回false
|
||||
|
||||
// 启动初始化
|
||||
SocketIo = io(config.chat_domain, {
|
||||
reconnection: true, // 默认 true 是否断线重连
|
||||
reconnectionAttempts: 5, // 默认无限次 断线尝试次数
|
||||
reconnectionDelay: 1000, // 默认 1000,进行下一次重连的间隔。
|
||||
reconnectionDelayMax: 5000, // 默认 5000, 重新连接等待的最长时间 默认 5000
|
||||
randomizationFactor: 0.5, // 默认 0.5 [0-1],随机重连延迟时间
|
||||
timeout: 20000, // 默认 20s
|
||||
transports: ['websocket', 'polling'], // websocket | polling,
|
||||
...config,
|
||||
});
|
||||
|
||||
// 监听连接
|
||||
SocketIo.on('connect', async (res) => {
|
||||
socketReset(callBack);
|
||||
// socket连接
|
||||
// 用户登录
|
||||
// 顾客登录
|
||||
console.log('socket:connect');
|
||||
});
|
||||
// 监听消息
|
||||
SocketIo.on('message', (res) => {
|
||||
if (res.error === 0) {
|
||||
const { message, sender } = res.data;
|
||||
state.chatList.push(formatMessage(res.data.message));
|
||||
|
||||
// 告诉父级页面
|
||||
// window.parent.postMessage({
|
||||
// chatDotNum: ++state.chatDotNum
|
||||
// })
|
||||
callBack && callBack();
|
||||
}
|
||||
});
|
||||
// 监听客服接入成功
|
||||
SocketIo.on('customer_service_access', (res) => {
|
||||
if (res.error === 0) {
|
||||
editCustomerServerInfo({
|
||||
title: res.data.customer_service.name,
|
||||
state: 'online',
|
||||
avatar: res.data.customer_service.avatar,
|
||||
});
|
||||
state.chatList.push(formatMessage(res.data.message));
|
||||
// callBack && callBack()
|
||||
}
|
||||
});
|
||||
// 监听排队等待
|
||||
SocketIo.on('waiting_queue', (res) => {
|
||||
if (res.error === 0) {
|
||||
editCustomerServerInfo({
|
||||
title: res.data.title,
|
||||
state: 'waiting',
|
||||
avatar: '',
|
||||
});
|
||||
// callBack && callBack()
|
||||
}
|
||||
});
|
||||
// 监听没有客服在线
|
||||
SocketIo.on('no_customer_service', (res) => {
|
||||
if (res.error === 0) {
|
||||
editCustomerServerInfo({
|
||||
title: '暂无客服在线...',
|
||||
state: 'waiting',
|
||||
avatar: '',
|
||||
});
|
||||
}
|
||||
state.chatList.push(formatMessage(res.data.message));
|
||||
// callBack && callBack()
|
||||
});
|
||||
// 监听客服上线
|
||||
SocketIo.on('customer_service_online', (res) => {
|
||||
if (res.error === 0) {
|
||||
editCustomerServerInfo({
|
||||
title: res.data.customer_service.name,
|
||||
state: 'online',
|
||||
avatar: res.data.customer_service.avatar,
|
||||
});
|
||||
}
|
||||
});
|
||||
// 监听客服下线
|
||||
SocketIo.on('customer_service_offline', (res) => {
|
||||
if (res.error === 0) {
|
||||
editCustomerServerInfo({
|
||||
title: res.data.customer_service.name,
|
||||
state: 'offline',
|
||||
avatar: res.data.customer_service.avatar,
|
||||
});
|
||||
}
|
||||
});
|
||||
// 监听客服忙碌
|
||||
SocketIo.on('customer_service_busy', (res) => {
|
||||
if (res.error === 0) {
|
||||
editCustomerServerInfo({
|
||||
title: res.data.customer_service.name,
|
||||
state: 'busy',
|
||||
avatar: res.data.customer_service.avatar,
|
||||
});
|
||||
}
|
||||
});
|
||||
// 监听客服断开链接
|
||||
SocketIo.on('customer_service_break', (res) => {
|
||||
if (res.error === 0) {
|
||||
editCustomerServerInfo({
|
||||
title: '客服服务结束',
|
||||
state: 'offline',
|
||||
avatar: '',
|
||||
});
|
||||
state.socketState.isConnect = false;
|
||||
state.socketState.tip = '当前服务已结束';
|
||||
}
|
||||
state.chatList.push(formatMessage(res.data.message));
|
||||
// callBack && callBack()
|
||||
});
|
||||
// 监听自定义错误 custom_error
|
||||
SocketIo.on('custom_error', (error) => {
|
||||
editCustomerServerInfo({
|
||||
title: error.msg,
|
||||
state: 'offline',
|
||||
avatar: '',
|
||||
});
|
||||
console.log('custom_error:', error);
|
||||
});
|
||||
// 监听错误 error
|
||||
SocketIo.on('error', (error) => {
|
||||
console.log('error:', error);
|
||||
});
|
||||
// 重连失败 connect_error
|
||||
SocketIo.on('connect_error', (error) => {
|
||||
console.log('connect_error');
|
||||
});
|
||||
// 连接上,但无反应 connect_timeout
|
||||
SocketIo.on('connect_timeout', (error) => {
|
||||
console.log(error, 'connect_timeout');
|
||||
});
|
||||
// 服务进程销毁 disconnect
|
||||
SocketIo.on('disconnect', (error) => {
|
||||
console.log(error, 'disconnect');
|
||||
});
|
||||
// 服务重启重连上reconnect
|
||||
SocketIo.on('reconnect', (error) => {
|
||||
console.log(error, 'reconnect');
|
||||
});
|
||||
// 开始重连reconnect_attempt
|
||||
SocketIo.on('reconnect_attempt', (error) => {
|
||||
state.socketState.isConnect = false;
|
||||
state.socketState.isConnecting = true;
|
||||
editCustomerServerInfo({
|
||||
title: `重连中,第${error}次尝试...`,
|
||||
state: 'waiting',
|
||||
avatar: '',
|
||||
});
|
||||
console.log(error, 'reconnect_attempt');
|
||||
});
|
||||
// 重新连接中reconnecting
|
||||
SocketIo.on('reconnecting', (error) => {
|
||||
console.log(error, 'reconnecting');
|
||||
});
|
||||
// 重新连接错误reconnect_error
|
||||
SocketIo.on('reconnect_error', (error) => {
|
||||
console.log('reconnect_error');
|
||||
});
|
||||
// 重新连接失败reconnect_failed
|
||||
SocketIo.on('reconnect_failed', (error) => {
|
||||
state.socketState.isConnecting = false;
|
||||
editCustomerServerInfo({
|
||||
title: `重连失败,请刷新重试~`,
|
||||
state: 'waiting',
|
||||
avatar: '',
|
||||
});
|
||||
console.log(error, 'reconnect_failed');
|
||||
|
||||
// setTimeout(() => {
|
||||
state.isSendSucces = 1;
|
||||
// }, 500)
|
||||
});
|
||||
};
|
||||
|
||||
// 重置socket
|
||||
const socketReset = (callBack) => {
|
||||
state.chatList = [];
|
||||
state.chatHistoryList = [];
|
||||
state.chatHistoryPagination = {
|
||||
page: 0,
|
||||
per_page: 10,
|
||||
last_id: 0,
|
||||
totalPage: 0,
|
||||
};
|
||||
socketConnection(callBack); // 连接
|
||||
};
|
||||
|
||||
// 退出连接
|
||||
const socketClose = () => {
|
||||
SocketIo.emit('customer_logout', {}, (res) => {
|
||||
console.log('socket:退出', res);
|
||||
});
|
||||
};
|
||||
|
||||
// 测试事件
|
||||
const socketTest = () => {
|
||||
SocketIo.emit('test', {}, (res) => {
|
||||
console.log('test:test', res);
|
||||
});
|
||||
};
|
||||
|
||||
// 发送消息
|
||||
const socketSendMsg = (data, sendMsgCallBack) => {
|
||||
state.isSendSucces = -1;
|
||||
state.chatList.push(data);
|
||||
sendMsgCallBack && sendMsgCallBack();
|
||||
SocketIo.emit(
|
||||
'message',
|
||||
{
|
||||
message: formatInput(data),
|
||||
...data.customData,
|
||||
},
|
||||
(res) => {
|
||||
// setTimeout(() => {
|
||||
state.isSendSucces = res.error;
|
||||
// }, 500)
|
||||
|
||||
// console.log(res, 'socket:send');
|
||||
// sendMsgCallBack && sendMsgCallBack()
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
// 连接socket,存入sessionId
|
||||
const socketConnection = (callBack) => {
|
||||
SocketIo.emit(
|
||||
'connection',
|
||||
{
|
||||
auth: 'user',
|
||||
token: uni.getStorageSync('socketUserToken') || '',
|
||||
session_id: uni.getStorageSync('socketSessionId') || '',
|
||||
},
|
||||
(res) => {
|
||||
if (res.error === 0) {
|
||||
socketCustomerLogin(callBack);
|
||||
uni.setStorageSync('socketSessionId', res.data.session_id);
|
||||
// uni.getStorageSync('socketUserToken') && socketLogin(uni.getStorageSync(
|
||||
// 'socketUserToken')) // 如果有用户token,绑定
|
||||
state.customerUserInfo = res.data.chat_user;
|
||||
state.socketState.isConnect = true;
|
||||
} else {
|
||||
editCustomerServerInfo({
|
||||
title: `服务器异常!`,
|
||||
state: 'waiting',
|
||||
avatar: '',
|
||||
});
|
||||
state.socketState.isConnect = false;
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
// 用户id,获取token
|
||||
const getUserToken = async (id) => {
|
||||
const res = await chat.unifiedToken();
|
||||
if (res.error === 0) {
|
||||
uni.setStorageSync('socketUserToken', res.data.token);
|
||||
// SocketIo && SocketIo.connected && socketLogin(res.data.token)
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
// 用户登录
|
||||
const socketLogin = (token) => {
|
||||
SocketIo.emit(
|
||||
'login',
|
||||
{
|
||||
token: token,
|
||||
},
|
||||
(res) => {
|
||||
console.log(res, 'socket:login');
|
||||
state.customerUserInfo = res.data.chat_user;
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
// 顾客登录
|
||||
const socketCustomerLogin = (callBack) => {
|
||||
SocketIo.emit(
|
||||
'customer_login',
|
||||
{
|
||||
room_id: state.chatConfig.room_id,
|
||||
},
|
||||
(res) => {
|
||||
state.templateChatList = res.data.questions.length ? res.data.questions : [];
|
||||
state.chatList.push({
|
||||
from: 'customer_service', // 用户customer右 | 顾客customer_service左 | 系统system中间
|
||||
mode: 'template', // goods,order,image,text,system
|
||||
date: new Date().getTime(), //时间
|
||||
content: {
|
||||
//内容
|
||||
list: state.templateChatList,
|
||||
},
|
||||
});
|
||||
res.error === 0 && socketHistoryList(callBack);
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
// 获取历史消息
|
||||
const socketHistoryList = (historyCallBack) => {
|
||||
state.chatHistoryPagination.loadStatus = 'loading';
|
||||
state.chatHistoryPagination.page += 1;
|
||||
SocketIo.emit('messages', state.chatHistoryPagination, (res) => {
|
||||
if (res.error === 0) {
|
||||
state.chatHistoryPagination.total = res.data.messages.total;
|
||||
state.chatHistoryPagination.lastPage = res.data.messages.last_page;
|
||||
state.chatHistoryPagination.page = res.data.messages.current_page;
|
||||
res.data.messages.data.forEach((item) => {
|
||||
item.message_type && state.chatList.unshift(formatMessage(item));
|
||||
});
|
||||
state.chatHistoryPagination.loadStatus =
|
||||
state.chatHistoryPagination.page < state.chatHistoryPagination.lastPage
|
||||
? 'loadmore'
|
||||
: 'nomore';
|
||||
if (state.chatHistoryPagination.last_id == 0) {
|
||||
state.chatHistoryPagination.last_id = res.data.messages.data.length
|
||||
? res.data.messages.data[0].id
|
||||
: 0;
|
||||
}
|
||||
state.chatHistoryPagination.page === 1 && historyCallBack && historyCallBack();
|
||||
}
|
||||
|
||||
// 历史记录之后,猜你想问
|
||||
// state.chatList.push({
|
||||
// from: 'customer_service', // 用户customer右 | 顾客customer_service左 | 系统system中间
|
||||
// mode: 'template', // goods,order,image,text,system
|
||||
// date: new Date().getTime(), //时间
|
||||
// content: { //内容
|
||||
// list: state.templateChatList
|
||||
// }
|
||||
// })
|
||||
});
|
||||
};
|
||||
|
||||
// 修改客服信息
|
||||
const editCustomerServerInfo = (data) => {
|
||||
state.customerServerInfo = {
|
||||
...state.customerServerInfo,
|
||||
...data,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* ================
|
||||
* 工具函数 ↓
|
||||
* ===============
|
||||
*/
|
||||
|
||||
/**
|
||||
* 是否显示时间
|
||||
* @param {*} item - 数据
|
||||
* @param {*} index - 索引
|
||||
*/
|
||||
const showTime = (item, index) => {
|
||||
if (unref(state.chatList)[index + 1]) {
|
||||
let dateString = dayjs(unref(state.chatList)[index + 1].date).fromNow();
|
||||
if (dateString === dayjs(unref(item).date).fromNow()) {
|
||||
return false;
|
||||
} else {
|
||||
dateString = dayjs(unref(item).date).fromNow();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* 格式化时间
|
||||
* @param {*} time - 时间戳
|
||||
*/
|
||||
const formatTime = (time) => {
|
||||
let diffTime = new Date().getTime() - time;
|
||||
if (diffTime > 28 * 24 * 60 * 1000) {
|
||||
return dayjs(time).format('MM/DD HH:mm');
|
||||
}
|
||||
if (diffTime > 360 * 28 * 24 * 60 * 1000) {
|
||||
return dayjs(time).format('YYYY/MM/DD HH:mm');
|
||||
}
|
||||
return dayjs(time).fromNow();
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取焦点
|
||||
* @param {*} virtualNode - 节点信息 ref
|
||||
*/
|
||||
const getFocus = (virtualNode) => {
|
||||
if (window.getSelection) {
|
||||
let chatInput = unref(virtualNode);
|
||||
chatInput.focus();
|
||||
let range = window.getSelection();
|
||||
range.selectAllChildren(chatInput);
|
||||
range.collapseToEnd();
|
||||
} else if (document.selection) {
|
||||
let range = document.selection.createRange();
|
||||
range.moveToElementText(chatInput);
|
||||
range.collapse(false);
|
||||
range.select();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
* @param {Blob} file -文件数据流
|
||||
* @return {path,fullPath}
|
||||
*/
|
||||
|
||||
const upload = (name, file) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let data = new FormData();
|
||||
data.append('file', file, name);
|
||||
data.append('group', 'chat');
|
||||
ajax({
|
||||
url: '/upload',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
data,
|
||||
success: function (res) {
|
||||
resolve(res);
|
||||
},
|
||||
error: function (err) {
|
||||
reject(err);
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 粘贴到输入框
|
||||
* @param {*} e - 粘贴内容
|
||||
* @param {*} uploadHttp - 上传图片地址
|
||||
*/
|
||||
const onPaste = async (e) => {
|
||||
let paste = e.clipboardData || window.clipboardData;
|
||||
let filesArr = Array.from(paste.files);
|
||||
filesArr.forEach(async (child) => {
|
||||
if (child && child.type.includes('image')) {
|
||||
e.preventDefault(); //阻止默认
|
||||
let file = child;
|
||||
const img = await readImg(file);
|
||||
const blob = await compressImg(img, file.type);
|
||||
const { data } = await upload(file.name, blob);
|
||||
let image = `<img class="full-url" src='${data.fullurl}'>`;
|
||||
document.execCommand('insertHTML', false, image);
|
||||
} else {
|
||||
document.execCommand('insertHTML', false, paste.getData('text'));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 拖拽到输入框
|
||||
* @param {*} e - 粘贴内容
|
||||
* @param {*} uploadHttp - 上传图片地址
|
||||
*/
|
||||
const onDrop = async (e) => {
|
||||
e.preventDefault(); //阻止默认
|
||||
let filesArr = Array.from(e.dataTransfer.files);
|
||||
filesArr.forEach(async (child) => {
|
||||
if (child && child.type.includes('image')) {
|
||||
let file = child;
|
||||
const img = await readImg(file);
|
||||
const blob = await compressImg(img, file.type);
|
||||
const { data } = await upload(file.name, blob);
|
||||
let image = `<img class="full-url" src='${data.fullurl}' >`;
|
||||
document.execCommand('insertHTML', false, image);
|
||||
} else {
|
||||
ElMessage({
|
||||
message: '禁止拖拽非图片资源',
|
||||
type: 'warning',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 解析富文本输入框内容
|
||||
* @param {*} virtualNode -节点信息
|
||||
* @param {Function} formatInputCallBack - cb 回调
|
||||
*/
|
||||
const formatChatInput = (virtualNode, formatInputCallBack) => {
|
||||
let res = '';
|
||||
let elemArr = Array.from(virtualNode.childNodes);
|
||||
elemArr.forEach((child, index) => {
|
||||
if (child.nodeName === '#text') {
|
||||
//如果为文本节点
|
||||
res += child.nodeValue;
|
||||
if (
|
||||
//文本节点的后面是图片,并且不是emoji,分开发送。输入框中的图片和文本表情分开。
|
||||
elemArr[index + 1] &&
|
||||
elemArr[index + 1].nodeName === 'IMG' &&
|
||||
elemArr[index + 1] &&
|
||||
elemArr[index + 1].name !== 'emoji'
|
||||
) {
|
||||
const data = {
|
||||
from: 'customer',
|
||||
mode: 'text',
|
||||
date: new Date().getTime(),
|
||||
content: {
|
||||
text: filterXSS(res),
|
||||
},
|
||||
};
|
||||
formatInputCallBack && formatInputCallBack(data);
|
||||
res = '';
|
||||
}
|
||||
} else if (child.nodeName === 'BR') {
|
||||
res += '<br/>';
|
||||
} else if (child.nodeName === 'IMG') {
|
||||
// 有emjio 和 一般图片
|
||||
// 图片解析后直接发送,不跟文字表情一组
|
||||
if (child.name !== 'emoji') {
|
||||
let srcReg = /src=[\'\']?([^\'\']*)[\'\']?/i;
|
||||
let src = child.outerHTML.match(srcReg);
|
||||
const data = {
|
||||
from: 'customer',
|
||||
mode: 'image',
|
||||
date: new Date().getTime(),
|
||||
content: {
|
||||
url: src[1],
|
||||
path: src[1].replace(/http:\/\/[^\/]*/, ''),
|
||||
},
|
||||
};
|
||||
formatInputCallBack && formatInputCallBack(data);
|
||||
} else {
|
||||
// 非表情图片跟文字一起发送
|
||||
res += child.outerHTML;
|
||||
}
|
||||
} else if (child.nodeName === 'DIV') {
|
||||
res += `<div style='width:200px; white-space: nowrap;'>${child.outerHTML}</div>`;
|
||||
}
|
||||
});
|
||||
if (res) {
|
||||
const data = {
|
||||
from: 'customer',
|
||||
mode: 'text',
|
||||
date: new Date().getTime(),
|
||||
content: {
|
||||
text: filterXSS(res),
|
||||
},
|
||||
};
|
||||
formatInputCallBack && formatInputCallBack(data);
|
||||
}
|
||||
unref(virtualNode).innerHTML = '';
|
||||
};
|
||||
|
||||
/**
|
||||
* 状态回调
|
||||
* @param {*} res -接口返回数据
|
||||
*/
|
||||
const callBackNotice = (res) => {
|
||||
ElNotification({
|
||||
title: 'socket',
|
||||
message: res.msg,
|
||||
showClose: true,
|
||||
type: res.error === 0 ? 'success' : 'warning',
|
||||
duration: 1200,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 格式化发送信息
|
||||
* @param {Object} message
|
||||
* @returns obj - 消息对象
|
||||
*/
|
||||
const formatInput = (message) => {
|
||||
let obj = {};
|
||||
switch (message.mode) {
|
||||
case 'text':
|
||||
obj = {
|
||||
message_type: 'text',
|
||||
message: message.content.text,
|
||||
};
|
||||
break;
|
||||
case 'image':
|
||||
obj = {
|
||||
message_type: 'image',
|
||||
message: message.content.path,
|
||||
};
|
||||
break;
|
||||
case 'goods':
|
||||
obj = {
|
||||
message_type: 'goods',
|
||||
message: message.content.item,
|
||||
};
|
||||
break;
|
||||
case 'order':
|
||||
obj = {
|
||||
message_type: 'order',
|
||||
message: message.content.item,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
/**
|
||||
* 格式化接收信息
|
||||
* @param {*} message
|
||||
* @returns obj - 消息对象
|
||||
*/
|
||||
const formatMessage = (message) => {
|
||||
let obj = {};
|
||||
switch (message.message_type) {
|
||||
case 'system':
|
||||
obj = {
|
||||
from: 'system', // 用户customer左 | 顾客customer_service右 | 系统system中间
|
||||
mode: 'system', // goods,order,image,text,system
|
||||
date: message.create_time * 1000, //时间
|
||||
content: {
|
||||
//内容
|
||||
text: message.message,
|
||||
},
|
||||
};
|
||||
break;
|
||||
case 'text':
|
||||
obj = {
|
||||
from: message.sender_identify,
|
||||
mode: message.message_type,
|
||||
date: message.create_time * 1000, //时间
|
||||
sender: message.sender,
|
||||
content: {
|
||||
text: message.message,
|
||||
messageId: message.id,
|
||||
},
|
||||
};
|
||||
break;
|
||||
case 'image':
|
||||
obj = {
|
||||
from: message.sender_identify,
|
||||
mode: message.message_type,
|
||||
date: message.create_time * 1000, //时间
|
||||
sender: message.sender,
|
||||
content: {
|
||||
url: sheep.$url.cdn(message.message),
|
||||
messageId: message.id,
|
||||
},
|
||||
};
|
||||
break;
|
||||
case 'goods':
|
||||
obj = {
|
||||
from: message.sender_identify,
|
||||
mode: message.message_type,
|
||||
date: message.create_time * 1000, //时间
|
||||
sender: message.sender,
|
||||
content: {
|
||||
item: message.message,
|
||||
messageId: message.id,
|
||||
},
|
||||
};
|
||||
break;
|
||||
case 'order':
|
||||
obj = {
|
||||
from: message.sender_identify,
|
||||
mode: message.message_type,
|
||||
date: message.create_time * 1000, //时间
|
||||
sender: message.sender,
|
||||
content: {
|
||||
item: message.message,
|
||||
messageId: message.id,
|
||||
},
|
||||
};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* file 转换为 img
|
||||
* @param {*} file - file 文件
|
||||
* @returns img - img标签
|
||||
*/
|
||||
const readImg = (file) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
img.src = e.target.result;
|
||||
};
|
||||
reader.onerror = function (e) {
|
||||
reject(e);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
img.onload = function () {
|
||||
resolve(img);
|
||||
};
|
||||
img.onerror = function (e) {
|
||||
reject(e);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 压缩图片
|
||||
*@param img -被压缩的img对象
|
||||
* @param type -压缩后转换的文件类型
|
||||
* @param mx -触发压缩的图片最大宽度限制
|
||||
* @param mh -触发压缩的图片最大高度限制
|
||||
* @returns blob - 文件流
|
||||
*/
|
||||
const compressImg = (img, type = 'image/jpeg', mx = 1000, mh = 1000, quality = 1) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const canvas = document.createElement('canvas');
|
||||
const context = canvas.getContext('2d');
|
||||
const { width: originWidth, height: originHeight } = img;
|
||||
// 最大尺寸限制
|
||||
const maxWidth = mx;
|
||||
const maxHeight = mh;
|
||||
// 目标尺寸
|
||||
let targetWidth = originWidth;
|
||||
let targetHeight = originHeight;
|
||||
if (originWidth > maxWidth || originHeight > maxHeight) {
|
||||
if (originWidth / originHeight > 1) {
|
||||
// 宽图片
|
||||
targetWidth = maxWidth;
|
||||
targetHeight = Math.round(maxWidth * (originHeight / originWidth));
|
||||
} else {
|
||||
// 高图片
|
||||
targetHeight = maxHeight;
|
||||
targetWidth = Math.round(maxHeight * (originWidth / originHeight));
|
||||
}
|
||||
}
|
||||
canvas.width = targetWidth;
|
||||
canvas.height = targetHeight;
|
||||
context.clearRect(0, 0, targetWidth, targetHeight);
|
||||
// 图片绘制
|
||||
context.drawImage(img, 0, 0, targetWidth, targetHeight);
|
||||
canvas.toBlob(
|
||||
function (blob) {
|
||||
resolve(blob);
|
||||
},
|
||||
type,
|
||||
quality,
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
compressImg,
|
||||
readImg,
|
||||
formatMessage,
|
||||
formatInput,
|
||||
callBackNotice,
|
||||
|
||||
socketInit,
|
||||
socketSendMsg,
|
||||
socketClose,
|
||||
socketHistoryList,
|
||||
|
||||
getFocus,
|
||||
formatChatInput,
|
||||
onDrop,
|
||||
onPaste,
|
||||
upload,
|
||||
|
||||
getUserToken,
|
||||
|
||||
state,
|
||||
|
||||
socketTest,
|
||||
|
||||
showTime,
|
||||
formatTime,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
export const KeFuMessageContentTypeEnum = {
|
||||
TEXT: 1, // 文本消息
|
||||
IMAGE: 2, // 图片消息
|
||||
VOICE: 3, // 语音消息
|
||||
VIDEO: 4, // 视频消息
|
||||
SYSTEM: 5, // 系统消息
|
||||
// ========== 商城特殊消息 ==========
|
||||
PRODUCT: 10,// 商品消息
|
||||
ORDER: 11,// 订单消息"
|
||||
};
|
||||
export const UserTypeEnum = {
|
||||
MEMBER: 1, // 会员 面向 c 端,普通用户
|
||||
ADMIN: 2, // 管理员 面向 b 端,管理后台
|
||||
};
|
||||
// Promotion 的 WebSocket 消息类型枚举类
|
||||
export const WebSocketMessageTypeConstants = {
|
||||
KEFU_MESSAGE_TYPE: 'kefu_message_type', // 客服消息类型
|
||||
KEFU_MESSAGE_ADMIN_READ: 'kefu_message_read_status_change' // 客服消息管理员已读
|
||||
}
|
||||
File renamed without changes.
@@ -16,7 +16,7 @@
|
||||
/>
|
||||
</button>
|
||||
</view>
|
||||
<view class="ss-flex" @tap="sheep.$router.go('/pages/user/wallet/commission')">
|
||||
<view class="ss-flex" @tap="sheep.$router.go('/pages/commission/wallet')">
|
||||
<view class="header-title ss-m-r-4">查看明细</view>
|
||||
<text class="cicon-play-arrow" />
|
||||
</view>
|
||||
|
||||
@@ -61,21 +61,21 @@
|
||||
title: '钱包余额',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
icon: '/static/img/shop/pay/bank.png',
|
||||
title: '银行卡转账',
|
||||
value: '2',
|
||||
},
|
||||
{
|
||||
icon: '/static/img/shop/pay/wechat.png',
|
||||
title: '微信零钱',
|
||||
value: '2',
|
||||
value: '3',
|
||||
},
|
||||
{
|
||||
icon: '/static/img/shop/pay/alipay.png',
|
||||
title: '支付宝账户',
|
||||
value: '3',
|
||||
},
|
||||
{
|
||||
icon: '/static/img/shop/pay/bank.png',
|
||||
title: '银行卡转账',
|
||||
value: '4',
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
function onChange(e) {
|
||||
|
||||
@@ -1,74 +1,90 @@
|
||||
<!-- 分销首页:明细列表 -->
|
||||
<template>
|
||||
<view class="distribution-log-wrap">
|
||||
<view class="header-box">
|
||||
<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title2.png')" />
|
||||
<view class="ss-flex header-title">
|
||||
<view class="title">实时动态</view>
|
||||
<text class="cicon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" @scrolltolower="loadmore" class="scroll-box log-scroll"
|
||||
scroll-with-animation="true">
|
||||
<view v-if="state.pagination.list">
|
||||
<view class="log-item-box ss-flex ss-row-between" v-for="item in state.pagination.list" :key="item.id">
|
||||
<view class="log-item-wrap">
|
||||
<view class="log-item ss-flex ss-ellipsis-1 ss-col-center">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<image class="log-img" :src="sheep.$url.static('/static/img/shop/avatar/notice.png')" mode="aspectFill" />
|
||||
</view>
|
||||
<view class="log-text ss-ellipsis-1">
|
||||
<view class="distribution-log-wrap">
|
||||
<view class="header-box">
|
||||
<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title2.png')" />
|
||||
<view class="ss-flex header-title">
|
||||
<view class="title">实时动态</view>
|
||||
<text class="cicon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view
|
||||
scroll-y="true"
|
||||
@scrolltolower="loadmore"
|
||||
class="scroll-box log-scroll"
|
||||
scroll-with-animation="true"
|
||||
>
|
||||
<view v-if="state.pagination.list">
|
||||
<view
|
||||
class="log-item-box ss-flex ss-row-between"
|
||||
v-for="item in state.pagination.list"
|
||||
:key="item.id"
|
||||
>
|
||||
<view class="log-item-wrap">
|
||||
<view class="log-item ss-flex ss-ellipsis-1 ss-col-center">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<image
|
||||
class="log-img"
|
||||
:src="sheep.$url.static('/static/img/shop/avatar/notice.png')"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</view>
|
||||
<view class="log-text ss-ellipsis-1">
|
||||
{{ item.title }} {{ fen2yuan(item.price) }} 元
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="log-time">{{ dayjs(item.createTime).fromNow() }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="log-time">{{ dayjs(item.createTime).fromNow() }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" color="#333333"
|
||||
@tap="loadmore" />
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- 加载更多 -->
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
color="#333333"
|
||||
@tap="loadmore"
|
||||
/>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import dayjs from 'dayjs';
|
||||
import sheep from '@/sheep';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash-es';
|
||||
import dayjs from 'dayjs';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
import { fen2yuan } from '../../../sheep/hooks/useGoods';
|
||||
|
||||
const state = reactive({
|
||||
loadStatus: '',
|
||||
pagination: {
|
||||
const state = reactive({
|
||||
loadStatus: '',
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 1,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
async function getLog() {
|
||||
async function getLog() {
|
||||
state.loadStatus = 'loading';
|
||||
const { code, data } = await BrokerageApi.getBrokerageRecordPage({
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize
|
||||
});
|
||||
pageSize: state.pagination.pageSize,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
}
|
||||
|
||||
getLog();
|
||||
getLog();
|
||||
|
||||
// 加载更多
|
||||
function loadmore() {
|
||||
// 加载更多
|
||||
function loadmore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
@@ -78,88 +94,88 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.distribution-log-wrap {
|
||||
width: 690rpx;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
z-index: 3;
|
||||
position: relative;
|
||||
.distribution-log-wrap {
|
||||
width: 690rpx;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
z-index: 3;
|
||||
position: relative;
|
||||
|
||||
.header-box {
|
||||
width: 690rpx;
|
||||
height: 76rpx;
|
||||
position: relative;
|
||||
.header-box {
|
||||
width: 690rpx;
|
||||
height: 76rpx;
|
||||
position: relative;
|
||||
|
||||
.header-bg {
|
||||
width: 690rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
.header-bg {
|
||||
width: 690rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
position: absolute;
|
||||
left: 20rpx;
|
||||
top: 24rpx;
|
||||
}
|
||||
.header-title {
|
||||
position: absolute;
|
||||
left: 20rpx;
|
||||
top: 24rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
|
||||
.cicon-forward {
|
||||
font-size: 30rpx;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
}
|
||||
.cicon-forward {
|
||||
font-size: 30rpx;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.log-scroll {
|
||||
height: 600rpx;
|
||||
background: #fdfae9;
|
||||
padding: 10rpx 20rpx 0;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12rpx 12rpx;
|
||||
.log-scroll {
|
||||
height: 600rpx;
|
||||
background: #fdfae9;
|
||||
padding: 10rpx 20rpx 0;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12rpx 12rpx;
|
||||
|
||||
.log-item-box {
|
||||
margin-bottom: 20rpx;
|
||||
.log-item-box {
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.log-time {
|
||||
// margin-left: 30rpx;
|
||||
text-align: right;
|
||||
font-size: 24rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 400;
|
||||
color: #c4c4c4;
|
||||
}
|
||||
}
|
||||
.log-time {
|
||||
// margin-left: 30rpx;
|
||||
text-align: right;
|
||||
font-size: 24rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 400;
|
||||
color: #c4c4c4;
|
||||
}
|
||||
}
|
||||
|
||||
.loadmore-wrap {
|
||||
// line-height: 80rpx;
|
||||
}
|
||||
.loadmore-wrap {
|
||||
// line-height: 80rpx;
|
||||
}
|
||||
|
||||
.log-item {
|
||||
// background: rgba(#ffffff, 0.2);
|
||||
border-radius: 24rpx;
|
||||
padding: 6rpx 20rpx 6rpx 12rpx;
|
||||
.log-item {
|
||||
// background: rgba(#ffffff, 0.2);
|
||||
border-radius: 24rpx;
|
||||
padding: 6rpx 20rpx 6rpx 12rpx;
|
||||
|
||||
.log-img {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.log-img {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.log-text {
|
||||
max-width: 480rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.log-text {
|
||||
max-width: 480rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,138 +1,145 @@
|
||||
<!-- 分销:商菜单栏 -->
|
||||
<template>
|
||||
<view class="menu-box ss-flex-col">
|
||||
<view class="header-box">
|
||||
<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title1.png')" />
|
||||
<view class="ss-flex header-title">
|
||||
<view class="title">功能专区</view>
|
||||
<text class="cicon-forward"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="menu-list ss-flex ss-flex-wrap">
|
||||
<view v-for="(item, index) in state.menuList" :key="index" class="item-box ss-flex-col ss-col-center"
|
||||
@tap="sheep.$router.go(item.path)">
|
||||
<image class="menu-icon ss-m-b-10" :src="sheep.$url.static(item.img)" mode="aspectFill"></image>
|
||||
<view>{{ item.title }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="menu-box ss-flex-col">
|
||||
<view class="header-box">
|
||||
<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title1.png')" />
|
||||
<view class="ss-flex header-title">
|
||||
<view class="title">功能专区</view>
|
||||
<text class="cicon-forward"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="menu-list ss-flex ss-flex-wrap">
|
||||
<view
|
||||
v-for="(item, index) in state.menuList"
|
||||
:key="index"
|
||||
class="item-box ss-flex-col ss-col-center"
|
||||
@tap="sheep.$router.go(item.path)"
|
||||
>
|
||||
<image
|
||||
class="menu-icon ss-m-b-10"
|
||||
:src="sheep.$url.static(item.img)"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view>{{ item.title }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { reactive } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { reactive } from 'vue';
|
||||
|
||||
const state = reactive({
|
||||
menuList: [{
|
||||
img: '/static/img/shop/commission/commission_icon1.png',
|
||||
title: '我的团队',
|
||||
path: '/pages/commission/team',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon2.png',
|
||||
title: '佣金明细',
|
||||
path: '/pages/commission/wallet',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon3.png',
|
||||
title: '分销订单',
|
||||
path: '/pages/commission/order',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon4.png',
|
||||
title: '推广商品',
|
||||
path: '/pages/commission/goods',
|
||||
},
|
||||
// {
|
||||
// img: '/static/img/shop/commission/commission_icon5.png',
|
||||
// title: '我的资料',
|
||||
// path: '/pages/commission/apply',
|
||||
// isAgentFrom: true,
|
||||
// },
|
||||
// todo @芋艿:邀请海报需要登录后的个人数据
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon7.png',
|
||||
title: '邀请海报',
|
||||
path: 'action:showShareModal',
|
||||
},
|
||||
// TODO @芋艿:缺少 icon
|
||||
const state = reactive({
|
||||
menuList: [
|
||||
{
|
||||
// img: '/static/img/shop/commission/commission_icon7.png',
|
||||
title: '推广排行',
|
||||
path: '/pages/commission/promoter',
|
||||
},
|
||||
img: '/static/img/shop/commission/commission_icon1.png',
|
||||
title: '我的团队',
|
||||
path: '/pages/commission/team',
|
||||
},
|
||||
{
|
||||
// img: '/static/img/shop/commission/commission_icon7.png',
|
||||
title: '佣金排行',
|
||||
path: '/pages/commission/commission-ranking',
|
||||
}
|
||||
],
|
||||
});
|
||||
img: '/static/img/shop/commission/commission_icon2.png',
|
||||
title: '佣金明细',
|
||||
path: '/pages/commission/wallet',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon3.png',
|
||||
title: '分销订单',
|
||||
path: '/pages/commission/order',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon4.png',
|
||||
title: '推广商品',
|
||||
path: '/pages/commission/goods',
|
||||
},
|
||||
// {
|
||||
// img: '/static/img/shop/commission/commission_icon5.png',
|
||||
// title: '我的资料',
|
||||
// path: '/pages/commission/apply',
|
||||
// isAgentFrom: true,
|
||||
// },
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon7.png',
|
||||
title: '邀请海报',
|
||||
path: 'action:showShareModal',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon8.png',
|
||||
title: '推广排行',
|
||||
path: '/pages/commission/promoter',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon9.png',
|
||||
title: '佣金排行',
|
||||
path: '/pages/commission/commission-ranking',
|
||||
},
|
||||
],
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.menu-box {
|
||||
margin: 0 auto;
|
||||
width: 690rpx;
|
||||
margin-bottom: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
z-index: 3;
|
||||
position: relative;
|
||||
}
|
||||
.menu-box {
|
||||
margin: 0 auto;
|
||||
width: 690rpx;
|
||||
margin-bottom: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
z-index: 3;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header-box {
|
||||
width: 690rpx;
|
||||
height: 76rpx;
|
||||
position: relative;
|
||||
.header-box {
|
||||
width: 690rpx;
|
||||
height: 76rpx;
|
||||
position: relative;
|
||||
|
||||
.header-bg {
|
||||
width: 690rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
.header-bg {
|
||||
width: 690rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
position: absolute;
|
||||
left: 20rpx;
|
||||
top: 24rpx;
|
||||
}
|
||||
.header-title {
|
||||
position: absolute;
|
||||
left: 20rpx;
|
||||
top: 24rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
|
||||
.cicon-forward {
|
||||
font-size: 30rpx;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
}
|
||||
.cicon-forward {
|
||||
font-size: 30rpx;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-list {
|
||||
padding: 50rpx 0 10rpx 0;
|
||||
background: #fdfae9;
|
||||
border-radius: 0 0 12rpx 12rpx;
|
||||
}
|
||||
.menu-list {
|
||||
padding: 50rpx 0 10rpx 0;
|
||||
background: #fdfae9;
|
||||
border-radius: 0 0 12rpx 12rpx;
|
||||
}
|
||||
|
||||
.item-box {
|
||||
width: 25%;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
.item-box {
|
||||
width: 25%;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
width: 68rpx;
|
||||
height: 68rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.menu-icon {
|
||||
width: 68rpx;
|
||||
height: 68rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.menu-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
.menu-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
@@ -14,12 +14,18 @@
|
||||
>
|
||||
<template #rightBottom>
|
||||
<view class="ss-flex ss-row-between">
|
||||
<view class="commission-num" v-if="item.brokerageMinPrice === undefined">预计佣金:计算中</view>
|
||||
<view class="commission-num" v-else-if="item.brokerageMinPrice === item.brokerageMaxPrice">
|
||||
<view class="commission-num" v-if="item.brokerageMinPrice === undefined"
|
||||
>预计佣金:计算中</view
|
||||
>
|
||||
<view
|
||||
class="commission-num"
|
||||
v-else-if="item.brokerageMinPrice === item.brokerageMaxPrice"
|
||||
>
|
||||
预计佣金:{{ fen2yuan(item.brokerageMinPrice) }}
|
||||
</view>
|
||||
<view class="commission-num" v-else>
|
||||
预计佣金:{{ fen2yuan(item.brokerageMinPrice) }} ~ {{ fen2yuan(item.brokerageMaxPrice) }}
|
||||
预计佣金:{{ fen2yuan(item.brokerageMinPrice) }} ~
|
||||
{{ fen2yuan(item.brokerageMaxPrice) }}
|
||||
</view>
|
||||
<button
|
||||
class="ss-reset-button share-btn ui-BG-Main-Gradient"
|
||||
@@ -53,7 +59,7 @@
|
||||
import $share from '@/sheep/platform/share';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import { showShareModal } from '@/sheep/hooks/useModal';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
@@ -70,7 +76,7 @@
|
||||
shareInfo: {},
|
||||
});
|
||||
|
||||
// TODO 芋艿:分享的接入
|
||||
// TODO @puhui999:【分享】接入
|
||||
function onShareGoods(goodsInfo) {
|
||||
state.shareInfo = $share.getShareInfo(
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- 分销中心 -->
|
||||
<template>
|
||||
<s-layout navbar="inner" class="index-wrap" title="分销中心" :bgStyle="bgStyle" onShareAppMessage>
|
||||
<s-layout navbar="inner" class="index-wrap" title="分销中心" :bgStyle="bgStyle" :onShareAppMessage="shareInfo">
|
||||
<!-- 分销商信息 -->
|
||||
<commission-info />
|
||||
<!-- 账户信息 -->
|
||||
@@ -16,14 +16,23 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import commissionInfo from './components/commission-info.vue';
|
||||
import accountInfo from './components/account-info.vue';
|
||||
import commissionLog from './components/commission-log.vue';
|
||||
import commissionMenu from './components/commission-menu.vue';
|
||||
import commissionAuth from './components/commission-auth.vue';
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const state = reactive({});
|
||||
const shareInfo = computed(() => {
|
||||
return sheep.$platform.share.getShareInfo({
|
||||
params: {
|
||||
page: '6',
|
||||
},
|
||||
}, {
|
||||
type: 'user',
|
||||
});
|
||||
});
|
||||
|
||||
const bgStyle = {
|
||||
color: '#F7D598',
|
||||
@@ -34,4 +43,4 @@
|
||||
:deep(.page-main) {
|
||||
background-size: 100% 100% !important;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -41,10 +41,7 @@
|
||||
<view class="no-box ss-flex ss-col-center ss-row-between">
|
||||
<text class="order-code">订单编号:{{ item.bizId }}</text>
|
||||
<text class="order-state">
|
||||
{{
|
||||
item.status === 0 ? '待结算'
|
||||
: item.status === 1 ? '已结算' : '已取消'
|
||||
}}
|
||||
{{ item.status === 0 ? '待结算' : item.status === 1 ? '已结算' : '已取消' }}
|
||||
( 佣金 {{ fen2yuan(item.price) }} 元 )
|
||||
</text>
|
||||
</view>
|
||||
@@ -77,7 +74,7 @@
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import { onPageScroll } from '@dcloudio/uni-app';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
|
||||
@@ -1,8 +1,29 @@
|
||||
<!-- 页面 TODO 芋艿:该页面的实现代码需要优化,包括 js 和 css,以及相关的样式设计 -->
|
||||
<template>
|
||||
<s-layout title="我的团队" :class="state.scrollTop ? 'team-wrap' : ''" navbar="inner">
|
||||
<view
|
||||
class="header-box"
|
||||
:style="[
|
||||
{
|
||||
marginTop: '-' + Number(statusBarHeight + 88) + 'rpx',
|
||||
paddingTop: Number(statusBarHeight + 108) + 'rpx',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<!-- 推广数据总览 -->
|
||||
<view class="team-data-box ss-flex ss-col-center ss-row-between" style="width: 100%">
|
||||
<view class="data-card" style="width: 100%">
|
||||
<view class="total-item" style="width: 100%">
|
||||
<view class="item-title" style="text-align: center">推广人数</view>
|
||||
<view class="total-num" style="text-align: center">
|
||||
{{ state.summary.firstBrokerageUserCount + state.summary.secondBrokerageUserCount || 0 }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="promoter-list">
|
||||
<view
|
||||
<!--<view
|
||||
class="promoterHeader bg-color"
|
||||
style="backgroundcolor: #e93323 !important; height: 218rpx; color: #fff"
|
||||
>
|
||||
@@ -21,9 +42,9 @@
|
||||
</view>
|
||||
<view class="iconfont icon-tuandui" />
|
||||
</view>
|
||||
</view>
|
||||
<view style="padding: 0 30rpx">
|
||||
<view class="nav acea-row row-around l1">
|
||||
</view>-->
|
||||
<view style="padding: 0 20rpx">
|
||||
<view class="nav acea-row row-around l1" style="margin-top:20rpx;">
|
||||
<view :class="state.level == 1 ? 'item on' : 'item'" @click="setType(1)">
|
||||
一级({{ state.summary.firstBrokerageUserCount || 0 }})
|
||||
</view>
|
||||
@@ -152,7 +173,7 @@
|
||||
</view>
|
||||
</block>
|
||||
<block v-if="state.pagination.list.length === 0">
|
||||
<view style="text-align: center">暂无推广人数</view>
|
||||
<view style="text-align: center;margin-top:30rpx;">暂无推广人数</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
@@ -235,7 +256,7 @@
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import { onPageScroll } from '@dcloudio/uni-app';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
|
||||
@@ -456,7 +477,7 @@
|
||||
.promoter-list .nav .item.on {
|
||||
border-bottom: 5rpx solid;
|
||||
// $theme-color
|
||||
color: red;
|
||||
color: var(--ui-BG-Main);
|
||||
// $theme-color
|
||||
}
|
||||
|
||||
|
||||
+411
-363
@@ -1,196 +1,243 @@
|
||||
<!-- 分销 - 佣金明细 -->
|
||||
<template>
|
||||
<s-layout class="wallet-wrap" title="佣金">
|
||||
<!-- 钱包卡片 -->
|
||||
<view class="header-box ss-flex ss-row-center ss-col-center">
|
||||
<view class="card-box ui-BG-Main ui-Shadow-Main">
|
||||
<view class="card-head ss-flex ss-col-center">
|
||||
<view class="card-title ss-m-r-10">当前佣金(元)</view>
|
||||
<view @tap="state.showMoney = !state.showMoney" class="ss-eye-icon"
|
||||
:class="state.showMoney ? 'cicon-eye' : 'cicon-eye-off'" />
|
||||
</view>
|
||||
<view class="ss-flex ss-row-between ss-col-center ss-m-t-30">
|
||||
<view class="money-num">{{ state.showMoney ? fen2yuan(state.summary.withdrawPrice || 0) : '*****' }}</view>
|
||||
<view class="ss-flex">
|
||||
<view class="ss-m-r-20">
|
||||
<button class="ss-reset-button withdraw-btn" @tap="sheep.$router.go('/pages/commission/withdraw')">
|
||||
提现
|
||||
</button>
|
||||
</view>
|
||||
<button class="ss-reset-button balance-btn ss-m-l-20" @tap="state.showModal = true">
|
||||
转余额
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<s-layout class="wallet-wrap" title="佣金">
|
||||
<!-- 钱包卡片 -->
|
||||
<view class="header-box ss-flex ss-row-center ss-col-center">
|
||||
<view class="card-box ui-BG-Main ui-Shadow-Main">
|
||||
<view class="card-head ss-flex ss-col-center">
|
||||
<view class="card-title ss-m-r-10">当前佣金(元)</view>
|
||||
<view
|
||||
@tap="state.showMoney = !state.showMoney"
|
||||
class="ss-eye-icon"
|
||||
:class="state.showMoney ? 'cicon-eye' : 'cicon-eye-off'"
|
||||
/>
|
||||
</view>
|
||||
<view class="ss-flex ss-row-between ss-col-center ss-m-t-30">
|
||||
<view class="money-num">{{
|
||||
state.showMoney ? fen2yuan(state.summary.withdrawPrice || 0) : '*****'
|
||||
}}</view>
|
||||
<view class="ss-flex">
|
||||
<view class="ss-m-r-20">
|
||||
<button
|
||||
class="ss-reset-button withdraw-btn"
|
||||
@tap="sheep.$router.go('/pages/commission/withdraw')"
|
||||
>
|
||||
提现
|
||||
</button>
|
||||
</view>
|
||||
<button class="ss-reset-button balance-btn ss-m-l-20" @tap="state.showModal = true">
|
||||
转余额
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="ss-flex">
|
||||
<view class="loading-money">
|
||||
<view class="loading-money-title">冻结佣金</view>
|
||||
<view class="loading-money-num">
|
||||
<view class="ss-flex">
|
||||
<view class="loading-money">
|
||||
<view class="loading-money-title">冻结佣金</view>
|
||||
<view class="loading-money-num">
|
||||
{{ state.showMoney ? fen2yuan(state.summary.frozenPrice || 0) : '*****' }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="loading-money ss-m-l-100">
|
||||
<view class="loading-money-title">可提现佣金</view>
|
||||
<view class="loading-money-num">
|
||||
</view>
|
||||
<view class="loading-money ss-m-l-100">
|
||||
<view class="loading-money-title">可提现佣金</view>
|
||||
<view class="loading-money-num">
|
||||
{{ state.showMoney ? fen2yuan(state.summary.brokeragePrice || 0) : '*****' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<su-sticky>
|
||||
<!-- 统计 -->
|
||||
<view class="filter-box ss-p-x-30 ss-flex ss-col-center ss-row-between">
|
||||
<uni-datetime-picker v-model="state.date" type="daterange" @change="onChangeTime" :end="state.today">
|
||||
<button class="ss-reset-button date-btn">
|
||||
<text>{{ dateFilterText }}</text>
|
||||
<text class="cicon-drop-down ss-seldate-icon" />
|
||||
</button>
|
||||
</uni-datetime-picker>
|
||||
<su-sticky>
|
||||
<!-- 统计 -->
|
||||
<view class="filter-box ss-p-x-30 ss-flex ss-col-center ss-row-between">
|
||||
<uni-datetime-picker
|
||||
v-model="state.date"
|
||||
type="daterange"
|
||||
@change="onChangeTime"
|
||||
:end="state.today"
|
||||
>
|
||||
<button class="ss-reset-button date-btn">
|
||||
<text>{{ dateFilterText }}</text>
|
||||
<text class="cicon-drop-down ss-seldate-icon" />
|
||||
</button>
|
||||
</uni-datetime-picker>
|
||||
|
||||
<view class="total-box">
|
||||
<view class="total-box">
|
||||
<!-- TODO 芋艿:这里暂时不考虑做 -->
|
||||
<!-- <view class="ss-m-b-10">总收入¥{{ state.pagination.income.toFixed(2) }}</view> -->
|
||||
<!-- <view>总支出¥{{ (-state.pagination.expense).toFixed(2) }}</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<su-tabs :list="tabMaps" @change="onChangeTab" :scrollable="false" :current="state.currentTab" />
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据"></s-empty>
|
||||
<!-- <view class="ss-m-b-10">总收入¥{{ state.pagination.income.toFixed(2) }}</view> -->
|
||||
<!-- <view>总支出¥{{ (-state.pagination.expense).toFixed(2) }}</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<su-tabs
|
||||
:list="tabMaps"
|
||||
@change="onChangeTab"
|
||||
:scrollable="false"
|
||||
:current="state.currentTab"
|
||||
/>
|
||||
</su-sticky>
|
||||
<s-empty
|
||||
v-if="state.pagination.total === 0"
|
||||
icon="/static/data-empty.png"
|
||||
text="暂无数据"
|
||||
></s-empty>
|
||||
|
||||
<!-- 转余额弹框 -->
|
||||
<su-popup :show="state.showModal" type="bottom" round="20" @close="state.showModal = false" showClose>
|
||||
<view class="ss-p-x-20 ss-p-y-30">
|
||||
<view class="model-title ss-m-b-30 ss-m-l-20">转余额</view>
|
||||
<view class="model-subtitle ss-m-b-100 ss-m-l-20">将您的佣金转到余额中继续消费</view>
|
||||
<view class="input-box ss-flex ss-col-center border-bottom ss-m-b-70 ss-m-x-20">
|
||||
<view class="unit">¥</view>
|
||||
<uni-easyinput :inputBorder="false" class="ss-flex-1 ss-p-l-10" v-model="state.price" type="number"
|
||||
placeholder="请输入金额" />
|
||||
</view>
|
||||
<button class="ss-reset-button model-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onConfirm">
|
||||
确定
|
||||
</button>
|
||||
</view>
|
||||
</su-popup>
|
||||
<su-popup
|
||||
:show="state.showModal"
|
||||
type="bottom"
|
||||
round="20"
|
||||
@close="state.showModal = false"
|
||||
showClose
|
||||
>
|
||||
<view class="ss-p-x-20 ss-p-y-30">
|
||||
<view class="model-title ss-m-b-30 ss-m-l-20">转余额</view>
|
||||
<view class="model-subtitle ss-m-b-100 ss-m-l-20">将您的佣金转到余额中继续消费</view>
|
||||
<view class="input-box ss-flex ss-col-center border-bottom ss-m-b-70 ss-m-x-20">
|
||||
<view class="unit">¥</view>
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
class="ss-flex-1 ss-p-l-10"
|
||||
v-model="state.price"
|
||||
type="number"
|
||||
placeholder="请输入金额"
|
||||
/>
|
||||
</view>
|
||||
<button
|
||||
class="ss-reset-button model-btn ui-BG-Main-Gradient ui-Shadow-Main"
|
||||
@tap="onConfirm"
|
||||
>
|
||||
确定
|
||||
</button>
|
||||
</view>
|
||||
</su-popup>
|
||||
|
||||
<!-- 钱包记录 -->
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view class="wallet-list ss-flex border-bottom" v-for="item in state.pagination.list" :key="item.id">
|
||||
<view class="list-content">
|
||||
<view class="title-box ss-flex ss-row-between ss-m-b-20">
|
||||
<text class="title ss-line-1">{{ item.title }}</text>
|
||||
<view class="money">
|
||||
<text v-if="item.price >= 0" class="add">+{{ fen2yuan(item.price) }}</text>
|
||||
<text v-else class="minus">{{ fen2yuan(item.price) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="time">{{ sheep.$helper.timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 钱包记录 -->
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view
|
||||
class="wallet-list ss-flex border-bottom"
|
||||
v-for="item in state.pagination.list"
|
||||
:key="item.id"
|
||||
>
|
||||
<view class="list-content">
|
||||
<view class="title-box ss-flex ss-row-between ss-m-b-20">
|
||||
<text class="title ss-line-1">{{ item.title }}</text>
|
||||
<view class="money">
|
||||
<text v-if="item.price >= 0" class="add">+{{ fen2yuan(item.price) }}</text>
|
||||
<text v-else class="minus">{{ fen2yuan(item.price) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="time">{{
|
||||
sheep.$helper.timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss')
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- <u-gap></u-gap> -->
|
||||
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
|
||||
<!-- <u-gap></u-gap> -->
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}" />
|
||||
</s-layout>
|
||||
}"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import dayjs from 'dayjs';
|
||||
import _ from 'lodash';
|
||||
import { computed, reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import dayjs from 'dayjs';
|
||||
import _ from 'lodash-es';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
const headerBg = sheep.$url.css('/static/img/shop/user/wallet_card_bg.png');
|
||||
const headerBg = sheep.$url.css('/static/img/shop/user/wallet_card_bg.png');
|
||||
|
||||
const state = reactive({
|
||||
const state = reactive({
|
||||
showMoney: false,
|
||||
summary: {}, // 分销信息
|
||||
|
||||
today: '',
|
||||
date: [],
|
||||
currentTab: 0,
|
||||
pagination: {
|
||||
currentTab: 0,
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 1,
|
||||
},
|
||||
loadStatus: '',
|
||||
loadStatus: '',
|
||||
|
||||
price: undefined,
|
||||
showModal: false,
|
||||
});
|
||||
showModal: false,
|
||||
});
|
||||
|
||||
const tabMaps = [{
|
||||
name: '分佣',
|
||||
value: '1', // BrokerageRecordBizTypeEnum.ORDER
|
||||
},
|
||||
{
|
||||
name: '提现',
|
||||
value: '2', // BrokerageRecordBizTypeEnum.WITHDRAW
|
||||
}
|
||||
];
|
||||
const tabMaps = [
|
||||
{
|
||||
name: '分佣',
|
||||
value: '1', // BrokerageRecordBizTypeEnum.ORDER
|
||||
},
|
||||
{
|
||||
name: '提现',
|
||||
value: '2', // BrokerageRecordBizTypeEnum.WITHDRAW
|
||||
},
|
||||
];
|
||||
|
||||
const dateFilterText = computed(() => {
|
||||
if (state.date[0] === state.date[1]) {
|
||||
return state.date[0];
|
||||
} else {
|
||||
return state.date.join('~');
|
||||
}
|
||||
});
|
||||
const dateFilterText = computed(() => {
|
||||
if (state.date[0] === state.date[1]) {
|
||||
return state.date[0];
|
||||
} else {
|
||||
return state.date.join('~');
|
||||
}
|
||||
});
|
||||
|
||||
async function getLogList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { code, data } = await BrokerageApi.getBrokerageRecordPage({
|
||||
pageSize: state.pagination.pageSize,
|
||||
pageNo: state.pagination.pageNo,
|
||||
async function getLogList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { code, data } = await BrokerageApi.getBrokerageRecordPage({
|
||||
pageSize: state.pagination.pageSize,
|
||||
pageNo: state.pagination.pageNo,
|
||||
bizType: tabMaps[state.currentTab].value,
|
||||
'createTime[0]': state.date[0] + ' 00:00:00',
|
||||
'createTime[1]': state.date[1] + ' 23:59:59',
|
||||
});
|
||||
if (code !== 0) {
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
}
|
||||
|
||||
function onChangeTab(e) {
|
||||
resetPagination(state.pagination);
|
||||
state.currentTab = e.index;
|
||||
getLogList();
|
||||
}
|
||||
|
||||
function onChangeTime(e) {
|
||||
state.date[0] = e[0];
|
||||
state.date[1] = e[e.length - 1];
|
||||
function onChangeTab(e) {
|
||||
resetPagination(state.pagination);
|
||||
getLogList();
|
||||
}
|
||||
state.currentTab = e.index;
|
||||
getLogList();
|
||||
}
|
||||
|
||||
// 确认操作(转账到余额)
|
||||
async function onConfirm() {
|
||||
if (state.price <= 0) {
|
||||
sheep.$helper.toast('请输入正确的金额');
|
||||
return;
|
||||
}
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认把您的佣金转入到余额钱包中?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
function onChangeTime(e) {
|
||||
state.date[0] = e[0];
|
||||
state.date[1] = e[e.length - 1];
|
||||
resetPagination(state.pagination);
|
||||
getLogList();
|
||||
}
|
||||
|
||||
// 确认操作(转账到余额)
|
||||
async function onConfirm() {
|
||||
if (state.price <= 0) {
|
||||
sheep.$helper.toast('请输入正确的金额');
|
||||
return;
|
||||
}
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认把您的佣金转入到余额钱包中?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const { code } = await BrokerageApi.createBrokerageWithdraw({
|
||||
type: 1, // 钱包
|
||||
price: state.price * 100,
|
||||
@@ -199,272 +246,273 @@
|
||||
state.showModal = false;
|
||||
await getAgentInfo();
|
||||
onChangeTab({
|
||||
index: 1
|
||||
index: 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function getAgentInfo() {
|
||||
const { code, data } = await BrokerageApi.getBrokerageUserSummary();
|
||||
async function getAgentInfo() {
|
||||
const { code, data } = await BrokerageApi.getBrokerageUserSummary();
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.summary = data;
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
state.today = dayjs().format('YYYY-MM-DD');
|
||||
state.date = [state.today, state.today];
|
||||
if (options.type === 2) { // 切换到“提现” tab 下
|
||||
onLoad(async (options) => {
|
||||
state.today = dayjs().format('YYYY-MM-DD');
|
||||
state.date = [state.today, state.today];
|
||||
if (options.type === 2) {
|
||||
// 切换到“提现” tab 下
|
||||
state.currentTab = 1;
|
||||
}
|
||||
getLogList();
|
||||
getAgentInfo();
|
||||
});
|
||||
getLogList();
|
||||
getAgentInfo();
|
||||
});
|
||||
|
||||
onReachBottom(() => {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
onReachBottom(() => {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getLogList();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 钱包
|
||||
.header-box {
|
||||
background-color: $white;
|
||||
padding: 30rpx;
|
||||
// 钱包
|
||||
.header-box {
|
||||
background-color: $white;
|
||||
padding: 30rpx;
|
||||
|
||||
.card-box {
|
||||
width: 100%;
|
||||
min-height: 300rpx;
|
||||
padding: 40rpx;
|
||||
background-size: 100% 100%;
|
||||
border-radius: 30rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
.card-box {
|
||||
width: 100%;
|
||||
min-height: 300rpx;
|
||||
padding: 40rpx;
|
||||
background-size: 100% 100%;
|
||||
border-radius: 30rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: v-bind(headerBg) no-repeat;
|
||||
pointer-events: none;
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: v-bind(headerBg) no-repeat;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.card-head {
|
||||
color: $white;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.card-head {
|
||||
color: $white;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.ss-eye-icon {
|
||||
font-size: 40rpx;
|
||||
color: $white;
|
||||
}
|
||||
.ss-eye-icon {
|
||||
font-size: 40rpx;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.money-num {
|
||||
font-size: 40rpx;
|
||||
line-height: normal;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
.money-num {
|
||||
font-size: 40rpx;
|
||||
line-height: normal;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.reduce-num {
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
color: $white;
|
||||
}
|
||||
.reduce-num {
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.withdraw-btn {
|
||||
width: 120rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 30px;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
background-color: $white;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
.withdraw-btn {
|
||||
width: 120rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 30px;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
background-color: $white;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.balance-btn {
|
||||
width: 120rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 30px;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
border: 1px solid $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
.balance-btn {
|
||||
width: 120rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 30px;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
border: 1px solid $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading-money {
|
||||
margin-top: 56rpx;
|
||||
.loading-money {
|
||||
margin-top: 56rpx;
|
||||
|
||||
.loading-money-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: normal;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
.loading-money-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: normal;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.loading-money-num {
|
||||
font-size: 30rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 500;
|
||||
color: #fefefe;
|
||||
}
|
||||
}
|
||||
.loading-money-num {
|
||||
font-size: 30rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 500;
|
||||
color: #fefefe;
|
||||
}
|
||||
}
|
||||
|
||||
// 筛选
|
||||
// 筛选
|
||||
|
||||
.filter-box {
|
||||
height: 120rpx;
|
||||
padding: 0 30rpx;
|
||||
background-color: $bg-page;
|
||||
.filter-box {
|
||||
height: 120rpx;
|
||||
padding: 0 30rpx;
|
||||
background-color: $bg-page;
|
||||
|
||||
.total-box {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: $dark-9;
|
||||
}
|
||||
.total-box {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: $dark-9;
|
||||
}
|
||||
|
||||
.date-btn {
|
||||
background-color: $white;
|
||||
line-height: 54rpx;
|
||||
border-radius: 27rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: $dark-6;
|
||||
.date-btn {
|
||||
background-color: $white;
|
||||
line-height: 54rpx;
|
||||
border-radius: 27rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: $dark-6;
|
||||
|
||||
.ss-seldate-icon {
|
||||
font-size: 50rpx;
|
||||
color: $dark-9;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ss-seldate-icon {
|
||||
font-size: 50rpx;
|
||||
color: $dark-9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tab
|
||||
.wallet-tab-card {
|
||||
.tab-item {
|
||||
height: 80rpx;
|
||||
position: relative;
|
||||
// tab
|
||||
.wallet-tab-card {
|
||||
.tab-item {
|
||||
height: 80rpx;
|
||||
position: relative;
|
||||
|
||||
.tab-title {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.tab-title {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.cur-tab-title {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
.cur-tab-title {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
.tab-line {
|
||||
width: 60rpx;
|
||||
height: 6rpx;
|
||||
border-radius: 6rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 2rpx;
|
||||
background-color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
}
|
||||
.tab-line {
|
||||
width: 60rpx;
|
||||
height: 6rpx;
|
||||
border-radius: 6rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 2rpx;
|
||||
background-color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 钱包记录
|
||||
.wallet-list {
|
||||
padding: 30rpx;
|
||||
background-color: #ffff;
|
||||
// 钱包记录
|
||||
.wallet-list {
|
||||
padding: 30rpx;
|
||||
background-color: #ffff;
|
||||
|
||||
.head-img {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
background: $gray-c;
|
||||
}
|
||||
.head-img {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
background: $gray-c;
|
||||
}
|
||||
|
||||
.list-content {
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
flex: 1;
|
||||
.list-content {
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
flex: 1;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: $dark-3;
|
||||
width: 400rpx;
|
||||
}
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: $dark-3;
|
||||
width: 400rpx;
|
||||
}
|
||||
|
||||
.time {
|
||||
color: $gray-c;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
.time {
|
||||
color: $gray-c;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.money {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
font-family: OPPOSANS;
|
||||
.money {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
font-family: OPPOSANS;
|
||||
|
||||
.add {
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
.add {
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.minus {
|
||||
color: $dark-3;
|
||||
}
|
||||
}
|
||||
}
|
||||
.minus {
|
||||
color: $dark-3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.model-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
.model-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.model-subtitle {
|
||||
font-size: 26rpx;
|
||||
color: #c2c7cf;
|
||||
}
|
||||
.model-subtitle {
|
||||
font-size: 26rpx;
|
||||
color: #c2c7cf;
|
||||
}
|
||||
|
||||
.model-btn {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: normal;
|
||||
}
|
||||
.model-btn {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.input-box {
|
||||
height: 100rpx;
|
||||
.input-box {
|
||||
height: 100rpx;
|
||||
|
||||
.unit {
|
||||
font-size: 48rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
}
|
||||
.unit {
|
||||
font-size: 48rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.uni-easyinput__placeholder-class {
|
||||
font-size: 30rpx;
|
||||
height: 40rpx;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.uni-easyinput__placeholder-class {
|
||||
font-size: 30rpx;
|
||||
height: 40rpx;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -15,7 +15,10 @@
|
||||
<view class="num-title">可提现金额(元)</view>
|
||||
<view class="wallet-num">{{ fen2yuan(state.brokerageInfo.brokeragePrice) }}</view>
|
||||
</view>
|
||||
<button class="ss-reset-button log-btn" @tap="sheep.$router.go('/pages/commission/wallet', { type: 2 })">
|
||||
<button
|
||||
class="ss-reset-button log-btn"
|
||||
@tap="sheep.$router.go('/pages/commission/wallet', { type: 2 })"
|
||||
>
|
||||
提现记录
|
||||
</button>
|
||||
</view>
|
||||
@@ -26,9 +29,9 @@
|
||||
<view class="bank-list ss-flex ss-col-center" @tap="onAccountSelect(true)">
|
||||
<view v-if="!state.accountInfo.type" class="empty-text">请选择提现方式</view>
|
||||
<view v-if="state.accountInfo.type === '1'" class="empty-text">钱包余额</view>
|
||||
<view v-if="state.accountInfo.type === '2'" class="empty-text">微信零钱</view>
|
||||
<view v-if="state.accountInfo.type === '3'" class="empty-text">支付宝账户</view>
|
||||
<view v-if="state.accountInfo.type === '4'" class="empty-text">银行卡转账</view>
|
||||
<view v-if="state.accountInfo.type === '2'" class="empty-text">银行卡转账</view>
|
||||
<view v-if="state.accountInfo.type === '3'" class="empty-text">微信零钱</view>
|
||||
<view v-if="state.accountInfo.type === '4'" class="empty-text">支付宝账户</view>
|
||||
<text class="cicon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
@@ -61,10 +64,10 @@
|
||||
/>
|
||||
</view>
|
||||
<!-- 收款码 -->
|
||||
<view class="card-title" v-show="['2', '3'].includes(state.accountInfo.type)">收款码</view>
|
||||
<view class="card-title" v-show="['3', '4'].includes(state.accountInfo.type)">收款码</view>
|
||||
<view
|
||||
class="input-box ss-flex ss-col-center"
|
||||
v-show="['2', '3'].includes(state.accountInfo.type)"
|
||||
v-show="['3', '4'].includes(state.accountInfo.type)"
|
||||
>
|
||||
<view class="unit" />
|
||||
<view class="upload-img">
|
||||
@@ -78,10 +81,10 @@
|
||||
</view>
|
||||
</view>
|
||||
<!-- 持卡人姓名 -->
|
||||
<view class="card-title" v-show="state.accountInfo.type === '4'">持卡人</view>
|
||||
<view class="card-title" v-show="state.accountInfo.type === '2'">持卡人</view>
|
||||
<view
|
||||
class="input-box ss-flex ss-col-center border-bottom"
|
||||
v-show="state.accountInfo.type === '4'"
|
||||
v-show="state.accountInfo.type === '2'"
|
||||
>
|
||||
<view class="unit" />
|
||||
<uni-easyinput
|
||||
@@ -92,24 +95,35 @@
|
||||
/>
|
||||
</view>
|
||||
<!-- 提现银行 -->
|
||||
<view class="card-title" v-show="state.accountInfo.type === '4'">提现银行</view>
|
||||
<view class="card-title" v-show="state.accountInfo.type === '2'">提现银行</view>
|
||||
<view
|
||||
class="input-box ss-flex ss-col-center border-bottom"
|
||||
v-show="state.accountInfo.type === '4'"
|
||||
v-show="state.accountInfo.type === '2'"
|
||||
>
|
||||
<view class="unit" />
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
class="ss-flex-1 ss-p-l-10"
|
||||
v-model="state.accountInfo.bankName"
|
||||
placeholder="请输入提现银行"
|
||||
/>
|
||||
<!--银行改为下拉选择-->
|
||||
<picker
|
||||
@change="bankChange"
|
||||
:value="state.bankListSelectedIndex"
|
||||
:range="state.bankList"
|
||||
range-key="label"
|
||||
style="width: 100%"
|
||||
>
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
:value="state.accountInfo.bankName"
|
||||
placeholder="请选择银行"
|
||||
suffixIcon="right"
|
||||
disabled
|
||||
:styles="{ disableColor: '#fff', borderColor: '#fff', color: '#333!important' }"
|
||||
/>
|
||||
</picker>
|
||||
</view>
|
||||
<!-- 开户地址 -->
|
||||
<view class="card-title" v-show="state.accountInfo.type === '4'">开户地址</view>
|
||||
<view class="card-title" v-show="state.accountInfo.type === '2'">开户地址</view>
|
||||
<view
|
||||
class="input-box ss-flex ss-col-center border-bottom"
|
||||
v-show="state.accountInfo.type === '4'"
|
||||
v-show="state.accountInfo.type === '2'"
|
||||
>
|
||||
<view class="unit" />
|
||||
<uni-easyinput
|
||||
@@ -152,6 +166,7 @@
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import TradeConfigApi from '@/sheep/api/trade/config';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
import DictApi from '@/sheep/api/system/dict';
|
||||
|
||||
const headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
@@ -176,6 +191,8 @@
|
||||
frozenDays: 0, // 冻结天数
|
||||
minPrice: 0, // 最低提现金额
|
||||
withdrawTypes: [], // 提现方式
|
||||
bankList: [], // 银行字典数据
|
||||
bankListSelectedIndex: '', // 选中银行 bankList 的 index
|
||||
});
|
||||
|
||||
// 打开提现方式的弹窗
|
||||
@@ -186,7 +203,7 @@
|
||||
// 提交提现
|
||||
const onConfirm = async () => {
|
||||
// 参数校验
|
||||
debugger;
|
||||
//debugger;
|
||||
if (
|
||||
!state.accountInfo.price ||
|
||||
state.accountInfo.price > state.brokerageInfo.price ||
|
||||
@@ -215,12 +232,12 @@
|
||||
confirmText: '查看记录',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
sheep.$router.go('/pages/commission/wallet', { type: 2 })
|
||||
sheep.$router.go('/pages/commission/wallet', { type: 2 });
|
||||
return;
|
||||
}
|
||||
getBrokerageUser();
|
||||
state.accountInfo = {};
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -245,10 +262,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 获取提现银行配置字典
|
||||
async function getDictDataListByType() {
|
||||
let { code, data } = await DictApi.getDictDataListByType('brokerage_bank_name');
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
if (data && data.length > 0) {
|
||||
state.bankList = data;
|
||||
}
|
||||
}
|
||||
|
||||
// 银行选择
|
||||
function bankChange(e) {
|
||||
const value = e.detail.value;
|
||||
state.bankListSelectedIndex = value;
|
||||
state.accountInfo.bankName = state.bankList[value].label;
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
getWithdrawRules();
|
||||
getBrokerageUser()
|
||||
})
|
||||
getBrokerageUser();
|
||||
getDictDataListByType(); //获取银行字典数据
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
+23
-11
@@ -16,13 +16,16 @@
|
||||
<view class="title ss-m-t-50 ss-m-b-20 ss-m-x-20">{{ state.coupon.name }}</view>
|
||||
<view class="subtitle ss-m-b-50">
|
||||
满 {{ fen2yuan(state.coupon.usePrice) }} 元,
|
||||
{{ state.coupon.discountType === 1
|
||||
? '减 ' + fen2yuan(state.coupon.discountPrice) + ' 元'
|
||||
: '打 ' + state.coupon.discountPercent / 10.0 + ' 折' }}
|
||||
{{
|
||||
state.coupon.discountType === 1
|
||||
? '减 ' + fen2yuan(state.coupon.discountPrice) + ' 元'
|
||||
: '打 ' + state.coupon.discountPercent / 10.0 + ' 折'
|
||||
}}
|
||||
</view>
|
||||
<button
|
||||
class="ss-reset-button ss-m-b-30"
|
||||
:class="state.coupon.canTake || state.coupon.status === 1
|
||||
:class="
|
||||
state.coupon.canTake || state.coupon.status === 1
|
||||
? 'use-btn' // 优惠劵模版(可领取)、优惠劵(可使用)
|
||||
: 'disable-btn'
|
||||
"
|
||||
@@ -31,7 +34,13 @@
|
||||
>
|
||||
<text v-if="state.id > 0">{{ state.coupon.canTake ? '立即领取' : '已领取' }}</text>
|
||||
<text v-else>
|
||||
{{ state.coupon.status === 1 ? '立即使用' : state.coupon.status === 2 ? '已使用' : '已过期' }}
|
||||
{{
|
||||
state.coupon.status === 1
|
||||
? '可使用'
|
||||
: state.coupon.status === 2
|
||||
? '已使用'
|
||||
: '已过期'
|
||||
}}
|
||||
</text>
|
||||
</button>
|
||||
<view class="time ss-m-y-30" v-if="state.coupon.validityType === 2">
|
||||
@@ -48,7 +57,6 @@
|
||||
<view>优惠券类型</view>
|
||||
<view>{{ state.coupon.discountType === 1 ? '满减券' : '折扣券' }}</view>
|
||||
</view>
|
||||
<!-- TODO 芋艿:可优化,增加优惠劵的描述 -->
|
||||
<uni-collapse>
|
||||
<uni-collapse-item title="优惠券说明" v-if="state.coupon.description">
|
||||
<view class="content ss-p-b-20">
|
||||
@@ -140,7 +148,7 @@
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
@@ -176,7 +184,7 @@
|
||||
const { code, data } = await SpuApi.getSpuPage({
|
||||
categoryId: state.categoryId,
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize
|
||||
pageSize: state.pagination.pageSize,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
@@ -197,7 +205,9 @@
|
||||
|
||||
// 获得分类列表
|
||||
async function getCategoryList() {
|
||||
const { data, code } = await CategoryApi.getCategoryListByIds(state.coupon.productScopeValues.join(','));
|
||||
const { data, code } = await CategoryApi.getCategoryListByIds(
|
||||
state.coupon.productScopeValues.join(','),
|
||||
);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
@@ -225,8 +235,10 @@
|
||||
|
||||
// 加载优惠劵信息
|
||||
async function getCouponContent() {
|
||||
const { code, data } = state.id > 0 ? await CouponApi.getCouponTemplate(state.id)
|
||||
: await CouponApi.getCoupon(state.couponId);
|
||||
const { code, data } =
|
||||
state.id > 0
|
||||
? await CouponApi.getCouponTemplate(state.id)
|
||||
: await CouponApi.getCoupon(state.couponId);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
+16
-12
@@ -45,7 +45,7 @@
|
||||
<template #default>
|
||||
<button
|
||||
class="ss-reset-button card-btn ss-flex ss-row-center ss-col-center"
|
||||
:class=" item.status !== 1 ? 'disabled-btn': ''"
|
||||
:class="item.status !== 1 ? 'disabled-btn' : ''"
|
||||
:disabled="item.status !== 1"
|
||||
@click.stop="sheep.$router.go('/pages/coupon/detail', { couponId: item.id })"
|
||||
>
|
||||
@@ -56,9 +56,14 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}" @tap="loadMore" />
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
@@ -66,7 +71,7 @@
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
|
||||
@@ -78,7 +83,7 @@
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 5
|
||||
pageSize: 5,
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
@@ -102,13 +107,12 @@
|
||||
},
|
||||
];
|
||||
|
||||
// TODO yunai:
|
||||
function onTabsChange(e) {
|
||||
state.currentTab = e.index;
|
||||
state.type = e.value;
|
||||
resetPagination(state.pagination)
|
||||
resetPagination(state.pagination);
|
||||
if (state.currentTab === 0) {
|
||||
getData();
|
||||
getData();
|
||||
} else {
|
||||
getCoupon();
|
||||
}
|
||||
@@ -135,7 +139,7 @@
|
||||
const { data, code } = await CouponApi.getCouponPage({
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
status: state.type
|
||||
status: state.type,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
@@ -177,13 +181,13 @@
|
||||
// 领劵中心
|
||||
if (Option.type === 'all' || !Option.type) {
|
||||
getData();
|
||||
// 我的优惠劵
|
||||
// 我的优惠劵
|
||||
} else {
|
||||
Option.type === 'geted'
|
||||
? (state.currentTab = 1)
|
||||
: Option.type === 'used'
|
||||
? (state.currentTab = 2)
|
||||
: (state.currentTab = 3);
|
||||
? (state.currentTab = 2)
|
||||
: (state.currentTab = 3);
|
||||
state.type = state.currentTab;
|
||||
getCoupon();
|
||||
}
|
||||
|
||||
+142
-97
@@ -1,89 +1,130 @@
|
||||
<!-- 评价 -->
|
||||
<template>
|
||||
<s-layout title="评价">
|
||||
<view>
|
||||
<view v-for="(item, index) in state.orderInfo.items" :key="item.id">
|
||||
<view>
|
||||
<view class="commont-from-wrap">
|
||||
<!-- 评价商品 -->
|
||||
<s-goods-item
|
||||
<s-layout title="评价">
|
||||
<view>
|
||||
<view v-for="(item, index) in state.orderInfo.items" :key="item.id">
|
||||
<view>
|
||||
<view class="commont-from-wrap">
|
||||
<!-- 评价商品 -->
|
||||
<s-goods-item
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.payPrice"
|
||||
:price="item.payPrice"
|
||||
:num="item.count"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<!-- 评分 -->
|
||||
<view class="star-box ss-flex ss-col-center">
|
||||
<view class="star-title ss-m-r-40">商品质量</view>
|
||||
<uni-rate v-model="state.commentList[index].descriptionScores" />
|
||||
</view>
|
||||
<view class="star-box ss-flex ss-col-center">
|
||||
<view class="star-title ss-m-r-40">服务态度</view>
|
||||
<uni-rate v-model="state.commentList[index].benefitScores" />
|
||||
</view>
|
||||
<!-- 评价 -->
|
||||
<view class="area-box">
|
||||
<uni-easyinput :inputBorder="false" type="textarea" maxlength="120" autoHeight
|
||||
v-model="state.commentList[index].content"
|
||||
placeholder="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~" />
|
||||
<!-- TODO 芋艿:文件上传 -->
|
||||
<view class="img-box">
|
||||
<s-uploader v-model:url="state.commentList[index].images" fileMediatype="image"
|
||||
limit="9" mode="grid" :imageStyles="{ width: '168rpx', height: '168rpx' }" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- TODO 芋艿:是否匿名 -->
|
||||
|
||||
<su-fixed bottom placeholder>
|
||||
<view class="foot_box ss-flex ss-row-center ss-col-center">
|
||||
<button class="ss-reset-button post-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onSubmit">
|
||||
发布
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
<view class="form-item">
|
||||
<!-- 评分 -->
|
||||
<view class="star-box ss-flex ss-col-center">
|
||||
<view class="star-title ss-m-r-40">商品质量</view>
|
||||
<uni-rate v-model="state.commentList[index].descriptionScores" />
|
||||
</view>
|
||||
<view class="star-box ss-flex ss-col-center">
|
||||
<view class="star-title ss-m-r-40">服务态度</view>
|
||||
<uni-rate v-model="state.commentList[index].benefitScores" />
|
||||
</view>
|
||||
<!-- 评价 -->
|
||||
<view class="area-box">
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
type="textarea"
|
||||
maxlength="120"
|
||||
autoHeight
|
||||
v-model="state.commentList[index].content"
|
||||
placeholder="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~"
|
||||
/>
|
||||
<view class="img-box">
|
||||
<s-uploader
|
||||
v-model:url="state.commentList[index].images"
|
||||
fileMediatype="image"
|
||||
limit="9"
|
||||
mode="grid"
|
||||
:imageStyles="{ width: '168rpx', height: '168rpx' }"
|
||||
@success="(payload) => uploadSuccess(payload, index)"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="checkbox-container">
|
||||
<checkbox-group @change="(event) => toggleAnonymous(index, event)">
|
||||
<label>
|
||||
<checkbox value="anonymousChecked" />
|
||||
匿名评论
|
||||
</label>
|
||||
</checkbox-group>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<su-fixed bottom placeholder>
|
||||
<view class="foot_box ss-flex ss-row-center ss-col-center">
|
||||
<button class="ss-reset-button post-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onSubmit">
|
||||
发布
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
|
||||
const state = reactive({
|
||||
orderInfo: {},
|
||||
commentList: [],
|
||||
id: null
|
||||
});
|
||||
const state = reactive({
|
||||
orderInfo: {},
|
||||
commentList: [],
|
||||
id: null,
|
||||
});
|
||||
|
||||
async function onSubmit() {
|
||||
/**
|
||||
* 切换是否匿名
|
||||
*
|
||||
* @param commentIndex 当前评论下标
|
||||
* @param event 复选框事件
|
||||
*/
|
||||
function toggleAnonymous(commentIndex, event) {
|
||||
state.commentList[commentIndex].anonymous = event.detail.value[0] === 'anonymousChecked';
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布评论
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function onSubmit() {
|
||||
// 顺序提交评论
|
||||
for (const comment of state.commentList) {
|
||||
await OrderApi.createOrderItemComment(comment);
|
||||
}
|
||||
// 都评论好,返回
|
||||
sheep.$router.back();
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
/**
|
||||
* 图片添加到表单
|
||||
*
|
||||
* @param payload 上传成功后的回调数据
|
||||
* @param commentIndex 当前评论的下标
|
||||
*/
|
||||
function uploadSuccess(payload, commentIndex) {
|
||||
state.commentList[commentIndex].picUrls = state.commentList[commentIndex].images;
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (!options.id) {
|
||||
sheep.$helper.toast(`缺少订单信息,请检查`);
|
||||
return
|
||||
return;
|
||||
}
|
||||
state.id = options.id;
|
||||
state.id = options.id;
|
||||
|
||||
const { code, data } = await OrderApi.getOrder(state.id);
|
||||
const { code, data } = await OrderApi.getOrderDetail(state.id);
|
||||
if (code !== 0) {
|
||||
sheep.$helper.toast('无待评价订单');
|
||||
return
|
||||
return;
|
||||
}
|
||||
// 处理评论
|
||||
data.items.forEach((item) => {
|
||||
@@ -93,53 +134,57 @@
|
||||
descriptionScores: 5,
|
||||
benefitScores: 5,
|
||||
content: '',
|
||||
picUrls: []
|
||||
picUrls: [],
|
||||
});
|
||||
});
|
||||
state.orderInfo = data;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 评价商品
|
||||
.goods-card {
|
||||
margin: 10rpx 0;
|
||||
padding: 20rpx;
|
||||
background: #fff;
|
||||
}
|
||||
// 评价商品
|
||||
.goods-card {
|
||||
margin: 10rpx 0;
|
||||
padding: 20rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
// 评论,选择图片
|
||||
.form-item {
|
||||
background: #fff;
|
||||
// 评论,选择图片
|
||||
.form-item {
|
||||
background: #fff;
|
||||
|
||||
.star-box {
|
||||
height: 100rpx;
|
||||
padding: 0 25rpx;
|
||||
}
|
||||
.star-box {
|
||||
height: 100rpx;
|
||||
padding: 0 25rpx;
|
||||
}
|
||||
|
||||
.star-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
.star-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.area-box {
|
||||
width: 690rpx;
|
||||
min-height: 306rpx;
|
||||
background: rgba(249, 250, 251, 1);
|
||||
border-radius: 20rpx;
|
||||
padding: 28rpx;
|
||||
margin: auto;
|
||||
.area-box {
|
||||
width: 690rpx;
|
||||
min-height: 306rpx;
|
||||
background: rgba(249, 250, 251, 1);
|
||||
border-radius: 20rpx;
|
||||
padding: 28rpx;
|
||||
margin: auto;
|
||||
|
||||
.img-box {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
.img-box {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.post-btn {
|
||||
width: 690rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
color: rgba(#fff, 0.9);
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
</style>
|
||||
.checkbox-container {
|
||||
padding: 10rpx;
|
||||
}
|
||||
|
||||
.post-btn {
|
||||
width: 690rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
color: rgba(#fff, 0.9);
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- 商品评论的分页 -->
|
||||
<template>
|
||||
<s-layout title="全部评价">
|
||||
<s-layout title="全部评论">
|
||||
<su-tabs
|
||||
:list="state.type"
|
||||
:scrollable="false"
|
||||
@@ -16,6 +16,7 @@
|
||||
<s-empty v-if="state.pagination.total === 0" text="暂无数据" icon="/static/data-empty.png" />
|
||||
<!-- 下拉 -->
|
||||
<uni-load-more
|
||||
icon-type="auto"
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
@@ -30,7 +31,7 @@
|
||||
import CommentApi from '@/sheep/api/product/comment';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import commentItem from '../components/detail/comment-item.vue';
|
||||
|
||||
const state = reactive({
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<su-fixed bottom placeholder :val="44">
|
||||
<view>
|
||||
<view v-for="activity in props.activityList" :key="activity.id">
|
||||
<!-- TODO 芋艿:拼团 -->
|
||||
<view
|
||||
class="activity-box ss-p-x-38 ss-flex ss-row-between ss-col-center"
|
||||
:class="activity.type === 1 ? 'seckill-box' : 'groupon-box'"
|
||||
@@ -14,7 +13,6 @@
|
||||
:src="sheep.$url.static('/static/img/shop/goods/seckill-icon.png')"
|
||||
class="activity-icon"
|
||||
/>
|
||||
<!-- TODO 芋艿:拼团 -->
|
||||
<image
|
||||
v-else-if="activity.type === 3"
|
||||
:src="sheep.$url.static('/static/img/shop/goods/groupon-icon.png')"
|
||||
@@ -33,7 +31,6 @@
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
|
||||
// TODO 芋艿:这里要迁移下;
|
||||
const seckillBg = sheep.$url.css('/static/img/shop/goods/seckill-tip-bg.png');
|
||||
const grouponBg = sheep.$url.css('/static/img/shop/goods/groupon-tip-bg.png');
|
||||
|
||||
|
||||
+55
-37
@@ -7,12 +7,16 @@
|
||||
<detailSkeleton v-if="state.skeletonLoading" />
|
||||
<!-- 下架/售罄提醒 -->
|
||||
<s-empty
|
||||
v-else-if="state.goodsInfo === null || state.activity.status !== 0 || state.activity.endTime < new Date().getTime()"
|
||||
text="活动不存在或已结束"
|
||||
icon="/static/soldout-empty.png"
|
||||
showAction
|
||||
actionText="返回上一页"
|
||||
@clickAction="sheep.$router.back()"
|
||||
v-else-if="
|
||||
state.goodsInfo === null ||
|
||||
state.activity.status !== 0 ||
|
||||
state.activity.endTime < new Date().getTime()
|
||||
"
|
||||
text="活动不存在或已结束"
|
||||
icon="/static/soldout-empty.png"
|
||||
showAction
|
||||
actionText="返回上一页"
|
||||
@clickAction="sheep.$router.back()"
|
||||
/>
|
||||
<block v-else>
|
||||
<view class="detail-swiper-selector">
|
||||
@@ -47,13 +51,10 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="ss-flex ss-row-between">
|
||||
<view
|
||||
class="origin-price ss-flex ss-col-center"
|
||||
v-if="state.goodsInfo.price"
|
||||
>
|
||||
<view class="origin-price ss-flex ss-col-center" v-if="state.goodsInfo.price">
|
||||
单买价:
|
||||
<view class="origin-price-text">
|
||||
{{ fen2yuan(state.goodsInfo.price) }}
|
||||
{{ fen2yuan(state.goodsInfo.marketPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -79,7 +80,7 @@
|
||||
<!-- 功能卡片 -->
|
||||
<view class="detail-cell-card detail-card ss-flex-col">
|
||||
<!-- 规格 -->
|
||||
<detail-cell-sku :sku="state.selectedSkuPrice" @tap="state.showSelectSku = true" />
|
||||
<detail-cell-sku :sku="state.selectedSku" @tap="state.showSelectSku = true" />
|
||||
</view>
|
||||
|
||||
<!-- 参团列表 -->
|
||||
@@ -103,7 +104,6 @@
|
||||
<detail-content-card class="detail-content-selector" :content="state.goodsInfo.description" />
|
||||
|
||||
<!-- 商品tabbar -->
|
||||
<!-- TODO: 已售罄、预热 判断 设计-->
|
||||
<detail-tabbar v-model="state.goodsInfo">
|
||||
<view class="buy-box ss-flex ss-col-center ss-p-r-20">
|
||||
<button
|
||||
@@ -123,7 +123,14 @@
|
||||
"
|
||||
:disabled="state.goodsInfo.stock === 0 || state.activity.status !== 0"
|
||||
>
|
||||
<view class="btn-price">{{ fen2yuan(state.activity.price || state.goodsInfo.price) }}</view>
|
||||
<view class="btn-price">{{
|
||||
fen2yuan(
|
||||
state.selectedSku.price * state.selectedSku.count ||
|
||||
state.activity.price * state.selectedSku.count ||
|
||||
state.goodsInfo.price * state.selectedSku.count ||
|
||||
state.goodsInfo.price,
|
||||
)
|
||||
}}</view>
|
||||
<view v-if="state.activity.startTime > new Date().getTime()">未开始</view>
|
||||
<view v-else-if="state.activity.endTime <= new Date().getTime()">已结束</view>
|
||||
<view v-else>
|
||||
@@ -141,7 +148,7 @@
|
||||
import { reactive, computed } from 'vue';
|
||||
import { onLoad, onPageScroll } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import detailNavbar from './components/detail/detail-navbar.vue';
|
||||
import detailCellSku from './components/detail/detail-cell-sku.vue';
|
||||
import detailTabbar from './components/detail/detail-tabbar.vue';
|
||||
@@ -149,29 +156,27 @@
|
||||
import detailCommentCard from './components/detail/detail-comment-card.vue';
|
||||
import detailContentCard from './components/detail/detail-content-card.vue';
|
||||
import grouponCardList from './components/groupon/groupon-card-list.vue';
|
||||
import {useDurationTime, formatGoodsSwiper, fen2yuan} from '@/sheep/hooks/useGoods';
|
||||
import CombinationApi from "@/sheep/api/promotion/combination";
|
||||
import SpuApi from "@/sheep/api/product/spu";
|
||||
import { useDurationTime, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import CombinationApi from '@/sheep/api/promotion/combination';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
|
||||
const headerBg = sheep.$url.css('/static/img/shop/goods/groupon-bg.png');
|
||||
const btnBg = sheep.$url.css('/static/img/shop/goods/groupon-btn.png');
|
||||
const disabledBtnBg = sheep.$url.css(
|
||||
'/static/img/shop/goods/activity-btn-disabled.png',
|
||||
);
|
||||
const disabledBtnBg = sheep.$url.css('/static/img/shop/goods/activity-btn-disabled.png');
|
||||
const grouponBg = sheep.$url.css('/static/img/shop/goods/groupon-tip-bg.png');
|
||||
|
||||
onPageScroll(() => {});
|
||||
const state = reactive({
|
||||
skeletonLoading: true, // 骨架屏
|
||||
goodsId: 0, // 商品ID
|
||||
goodsInfo: {}, // 商品信息
|
||||
goodsSwiper: [], // 商品轮播图
|
||||
showSelectSku: false, // 显示规格弹框
|
||||
selectedSkuPrice: {}, // 选中的规格价格
|
||||
activity: {}, // 团购活动
|
||||
grouponId: 0, // 团购ID
|
||||
grouponNum: 0, // 团购人数
|
||||
grouponAction: 'create', // 团购操作
|
||||
skeletonLoading: true, // 骨架屏
|
||||
goodsId: 0, // 商品ID
|
||||
goodsInfo: {}, // 商品信息
|
||||
goodsSwiper: [], // 商品轮播图
|
||||
showSelectSku: false, // 显示规格弹框
|
||||
selectedSku: {}, // 选中的规格属性
|
||||
activity: {}, // 团购活动
|
||||
grouponId: 0, // 团购ID
|
||||
grouponNum: 0, // 团购人数
|
||||
grouponAction: 'create', // 团购操作
|
||||
combinationHeadId: null, // 拼团团长编号
|
||||
});
|
||||
|
||||
@@ -182,7 +187,7 @@
|
||||
|
||||
// 规格变更
|
||||
function onSkuChange(e) {
|
||||
state.selectedSkuPrice = e;
|
||||
state.selectedSku = e;
|
||||
}
|
||||
|
||||
function onSkuClose() {
|
||||
@@ -198,6 +203,7 @@
|
||||
|
||||
/**
|
||||
* 去参团
|
||||
*
|
||||
* @param record 团长的团购记录
|
||||
*/
|
||||
function onJoinGroupon(record) {
|
||||
@@ -226,7 +232,6 @@
|
||||
}
|
||||
|
||||
// 分享信息
|
||||
// TODO @芋艿:分享的接入
|
||||
const shareInfo = computed(() => {
|
||||
if (isEmpty(state.activity)) return {};
|
||||
return sheep.$platform.share.getShareInfo(
|
||||
@@ -261,9 +266,23 @@
|
||||
// 加载商品信息
|
||||
const { data: spu } = await SpuApi.getSpuDetail(activity.spuId);
|
||||
state.goodsId = spu.id;
|
||||
activity.products.forEach(product => {
|
||||
spu.price = Math.min(spu.price, product.combinationPrice); // 设置 SPU 的最低价格
|
||||
|
||||
// 默认显示最低价
|
||||
spu.price = activity.products.reduce((min, product) => {
|
||||
return Math.min(min, product.combinationPrice || Infinity);
|
||||
}, Infinity);
|
||||
|
||||
// 价格、库存使用活动的
|
||||
spu.skus.forEach((sku) => {
|
||||
const product = activity.products.find((product) => product.skuId === sku.id);
|
||||
if (product) {
|
||||
sku.price = product.combinationPrice;
|
||||
} else {
|
||||
// 找不到可能是没配置,则不能发起秒杀
|
||||
sku.stock = 0;
|
||||
}
|
||||
});
|
||||
|
||||
// 关闭骨架屏
|
||||
state.skeletonLoading = false;
|
||||
if (code === 0) {
|
||||
@@ -475,8 +494,7 @@
|
||||
}
|
||||
|
||||
.groupon-box {
|
||||
background: v-bind(grouponBg)
|
||||
no-repeat;
|
||||
background: v-bind(grouponBg) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
|
||||
+590
-334
@@ -1,182 +1,303 @@
|
||||
<template>
|
||||
<view>
|
||||
<s-layout :onShareAppMessage="shareInfo" navbar="goods">
|
||||
<!-- 标题栏 -->
|
||||
<detailNavbar />
|
||||
<view>
|
||||
<s-layout :onShareAppMessage="shareInfo" navbar="goods">
|
||||
<!-- 标题栏 -->
|
||||
<detailNavbar />
|
||||
|
||||
<!-- 骨架屏 -->
|
||||
<detailSkeleton v-if="state.skeletonLoading" />
|
||||
<!-- 下架/售罄提醒 -->
|
||||
<s-empty v-else-if="state.goodsInfo === null" text="商品不存在或已下架" icon="/static/soldout-empty.png" showAction
|
||||
actionText="再逛逛" actionUrl="/pages/goods/list" />
|
||||
<block v-else>
|
||||
<view class="detail-swiper-selector">
|
||||
<!-- 商品轮播图 -->
|
||||
<su-swiper class="ss-m-b-14" isPreview :list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
|
||||
otStyle="tag" imageMode="widthFix" dotCur="bg-mask-40" :seizeHeight="750" />
|
||||
<!-- 骨架屏 -->
|
||||
<detailSkeleton v-if="state.skeletonLoading" />
|
||||
<!-- 下架/售罄提醒 -->
|
||||
<s-empty
|
||||
v-else-if="state.goodsInfo === null"
|
||||
text="商品不存在或已下架"
|
||||
icon="/static/soldout-empty.png"
|
||||
showAction
|
||||
actionText="再逛逛"
|
||||
actionUrl="/pages/goods/list"
|
||||
/>
|
||||
<block v-else>
|
||||
<view class="detail-swiper-selector">
|
||||
<!-- 商品轮播图 -->
|
||||
<su-swiper
|
||||
class="ss-m-b-14"
|
||||
isPreview
|
||||
:list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
|
||||
otStyle="tag"
|
||||
imageMode="widthFix"
|
||||
dotCur="bg-mask-40"
|
||||
:seizeHeight="750"
|
||||
/>
|
||||
<!-- 限时折扣/会员价的优惠信息 -->
|
||||
<view
|
||||
class="discount"
|
||||
v-if="
|
||||
state.settlementSku && state.settlementSku.id && state.settlementSku.promotionPrice
|
||||
"
|
||||
>
|
||||
<image class="disImg" :src="sheep.$url.static('/static/img/shop/goods/dis.png')" />
|
||||
<view class="discountCont">
|
||||
<view class="disContT">
|
||||
<view class="disContT1">
|
||||
<view class="disContT1P">
|
||||
¥{{ fen2yuan(state.settlementSku.promotionPrice) }}
|
||||
</view>
|
||||
<view class="disContT1End">
|
||||
直降¥
|
||||
{{ fen2yuan(state.settlementSku.price - state.settlementSku.promotionPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="disContT2" v-if="state.settlementSku.promotionType === 4">
|
||||
限时折扣
|
||||
</view>
|
||||
<view class="disContT2" v-else-if="state.settlementSku.promotionType === 6">
|
||||
会员折扣
|
||||
</view>
|
||||
</view>
|
||||
<view class="disContB">
|
||||
<view class="disContB1">
|
||||
价格:¥{{ fen2yuan(state.settlementSku.price) }} 丨 剩余:
|
||||
{{ state.settlementSku.stock }}
|
||||
</view>
|
||||
<view class="disContB2" v-if="state.settlementSku.promotionEndTime > 0">
|
||||
距结束仅剩
|
||||
<countDown
|
||||
:tipText="' '"
|
||||
:bgColor="bgColor"
|
||||
:dayText="':'"
|
||||
:hourText="':'"
|
||||
:minuteText="':'"
|
||||
:secondText="' '"
|
||||
:datatime="state.settlementSku.promotionEndTime / 1000"
|
||||
:isDay="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 价格+标题 -->
|
||||
<view class="title-card detail-card ss-p-y-30 ss-p-x-20">
|
||||
<!-- 没有限时折扣/会员价的优惠信息时,展示的价格信息 -->
|
||||
<view
|
||||
class="ss-flex ss-row-between ss-col-center ss-m-b-26"
|
||||
v-if="!state.settlementSku.promotionPrice"
|
||||
>
|
||||
<view class="price-box ss-flex ss-col-bottom">
|
||||
<view class="price-text ss-m-r-16">
|
||||
{{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
|
||||
</view>
|
||||
<view class="origin-price-text" v-if="state.goodsInfo.marketPrice > 0">
|
||||
{{ fen2yuan(state.selectedSku.marketPrice || state.goodsInfo.marketPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="sales-text">
|
||||
{{ formatSales('exact', state.goodsInfo.salesCount) }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="discounts-box ss-flex ss-row-between ss-m-b-28">
|
||||
<!-- 查看优惠劵的描述 -->
|
||||
<view
|
||||
class="tag ss-m-r-10"
|
||||
v-for="coupon in state.couponInfo.slice(0, 1)"
|
||||
:key="coupon.id"
|
||||
@tap="onOpenActivity"
|
||||
>
|
||||
[劵]满{{ fen2yuanSimple(coupon.usePrice) }}元{{
|
||||
coupon.discountType === 1
|
||||
? '减' + fen2yuanSimple(coupon.discountPrice) + '元'
|
||||
: '打' + formatDiscountPercent(coupon.discountPercent) + '折'
|
||||
}}
|
||||
</view>
|
||||
<!-- 查看满减送的描述 -->
|
||||
<div class="tag-content">
|
||||
<view class="tag-box ss-flex">
|
||||
<!-- 最多打印 3 条,所以需要扣除优惠劵已打印的 -->
|
||||
<view
|
||||
v-for="item in getRewardActivityRuleItemDescriptions(
|
||||
state.rewardActivity,
|
||||
).slice(0, 3 - state.couponInfo.slice(0, 1).length)"
|
||||
:key="item"
|
||||
class="tag ss-m-r-10"
|
||||
@tap="onOpenActivity"
|
||||
>
|
||||
<text>{{ item }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</div>
|
||||
<!-- 领取优惠劵的按钮 -->
|
||||
<view
|
||||
class="get-coupon-box ss-flex ss-col-center ss-m-l-20"
|
||||
@tap="onOpenActivity"
|
||||
v-if="state.couponInfo.length"
|
||||
>
|
||||
<view class="discounts-title ss-m-r-8">领券</view>
|
||||
<text class="cicon-forward"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="title-text ss-line-2 ss-m-b-6">{{ state.goodsInfo.name }}</view>
|
||||
<view class="subtitle-text ss-line-1">{{ state.goodsInfo.introduction }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 价格+标题 -->
|
||||
<view class="title-card detail-card ss-p-y-40 ss-p-x-20">
|
||||
<view class="ss-flex ss-row-between ss-col-center ss-m-b-26">
|
||||
<view class="price-box ss-flex ss-col-bottom">
|
||||
<view class="price-text ss-m-r-16">
|
||||
{{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
|
||||
</view>
|
||||
<view class="origin-price-text" v-if="state.goodsInfo.marketPrice > 0">
|
||||
{{ fen2yuan(state.selectedSku.marketPrice || state.goodsInfo.marketPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="sales-text">
|
||||
{{ formatSales('exact', state.goodsInfo.salesCount) }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="discounts-box ss-flex ss-row-between ss-m-b-28">
|
||||
<!-- 满减送/限时折扣活动的提示 -->
|
||||
<div class="tag-content">
|
||||
<view class="tag-box ss-flex">
|
||||
<view class="tag ss-m-r-10" v-for="promos in state.activityInfo"
|
||||
:key="promos.id" @tap="onActivity">
|
||||
{{ promos.name }}
|
||||
</view>
|
||||
</view>
|
||||
</div>
|
||||
<!-- 功能卡片 -->
|
||||
<view class="detail-cell-card detail-card ss-flex-col">
|
||||
<detail-cell-sku
|
||||
v-model="state.selectedSku.goods_sku_text"
|
||||
:sku="state.selectedSku"
|
||||
@tap="state.showSelectSku = true"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 优惠劵 -->
|
||||
<view class="get-coupon-box ss-flex ss-col-center ss-m-l-20" @tap="state.showModel = true"
|
||||
v-if="state.couponInfo.length">
|
||||
<view class="discounts-title ss-m-r-8">领券</view>
|
||||
<text class="cicon-forward"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="title-text ss-line-2 ss-m-b-6">{{ state.goodsInfo.name }}</view>
|
||||
<view class="subtitle-text ss-line-1">{{ state.goodsInfo.introduction }}</view>
|
||||
</view>
|
||||
<!-- 规格与数量弹框 -->
|
||||
<s-select-sku
|
||||
:goodsInfo="state.goodsInfo"
|
||||
:show="state.showSelectSku"
|
||||
@addCart="onAddCart"
|
||||
@buy="onBuy"
|
||||
@change="onSkuChange"
|
||||
@close="state.showSelectSku = false"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 功能卡片 -->
|
||||
<view class="detail-cell-card detail-card ss-flex-col">
|
||||
<detail-cell-sku v-model="state.selectedSku.goods_sku_text" :sku="state.selectedSku"
|
||||
@tap="state.showSelectSku = true" />
|
||||
</view>
|
||||
<!-- 评价 -->
|
||||
<detail-comment-card class="detail-comment-selector" :goodsId="state.goodsId" />
|
||||
<!-- 详情 -->
|
||||
<detail-content-card
|
||||
class="detail-content-selector"
|
||||
:content="state.goodsInfo.description"
|
||||
/>
|
||||
|
||||
<!-- 规格与数量弹框 -->
|
||||
<s-select-sku :goodsInfo="state.goodsInfo" :show="state.showSelectSku" @addCart="onAddCart"
|
||||
@buy="onBuy" @change="onSkuChange" @close="state.showSelectSku = false" />
|
||||
</view>
|
||||
<!-- 活动跳转:拼团/秒杀/砍价活动 -->
|
||||
<detail-activity-tip
|
||||
v-if="state.activityList.length > 0"
|
||||
:activity-list="state.activityList"
|
||||
/>
|
||||
|
||||
<!-- 评价 -->
|
||||
<detail-comment-card class="detail-comment-selector" :goodsId="state.goodsId" />
|
||||
<!-- 详情 -->
|
||||
<detail-content-card class="detail-content-selector" :content="state.goodsInfo.description" />
|
||||
<!-- 详情 tabbar -->
|
||||
<detail-tabbar v-model="state.goodsInfo">
|
||||
<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-if="state.goodsInfo.stock > 0">
|
||||
<button
|
||||
class="ss-reset-button add-btn ui-Shadow-Main"
|
||||
@tap="state.showSelectSku = true"
|
||||
>
|
||||
加入购物车
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button buy-btn ui-Shadow-Main"
|
||||
@tap="state.showSelectSku = true"
|
||||
>
|
||||
立即购买
|
||||
</button>
|
||||
</view>
|
||||
<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-else>
|
||||
<button class="ss-reset-button disabled-btn" disabled> 已售罄 </button>
|
||||
</view>
|
||||
</detail-tabbar>
|
||||
|
||||
<!-- 活动跳转:拼团/秒杀/砍价活动 -->
|
||||
<detail-activity-tip v-if="state.activityList.length > 0" :activity-list="state.activityList" />
|
||||
|
||||
<!-- 详情 tabbar -->
|
||||
<detail-tabbar v-model="state.goodsInfo">
|
||||
<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-if="state.goodsInfo.stock > 0">
|
||||
<button class="ss-reset-button add-btn ui-Shadow-Main" @tap="state.showSelectSku = true">
|
||||
加入购物车
|
||||
</button>
|
||||
<button class="ss-reset-button buy-btn ui-Shadow-Main" @tap="state.showSelectSku = true">
|
||||
立即购买
|
||||
</button>
|
||||
</view>
|
||||
<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-else>
|
||||
<button class="ss-reset-button disabled-btn" disabled> 已售罄 </button>
|
||||
</view>
|
||||
</detail-tabbar>
|
||||
|
||||
<!-- 优惠劵弹窗 -->
|
||||
<s-coupon-get v-model="state.couponInfo" :show="state.showModel" @close="state.showModel = false"
|
||||
@get="onGet" />
|
||||
|
||||
<!-- 满减送/限时折扣活动弹窗 -->
|
||||
<s-activity-pop v-model="state.activityInfo" :show="state.showActivityModel"
|
||||
@close="state.showActivityModel = false" />
|
||||
</block>
|
||||
</s-layout>
|
||||
</view>
|
||||
<!-- 满减送/限时折扣活动弹窗 -->
|
||||
<s-activity-pop
|
||||
v-model="state"
|
||||
:show="state.showActivityModel"
|
||||
@close="state.showActivityModel = false"
|
||||
@get="onTakeCoupon"
|
||||
/>
|
||||
</block>
|
||||
</s-layout>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
computed
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad,
|
||||
onPageScroll
|
||||
} from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import ActivityApi from '@/sheep/api/promotion/activity';
|
||||
import { reactive, computed, ref, toRaw } from 'vue';
|
||||
import { onLoad, onPageScroll } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import ActivityApi from '@/sheep/api/promotion/activity';
|
||||
import FavoriteApi from '@/sheep/api/product/favorite';
|
||||
import { formatSales, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import detailNavbar from './components/detail/detail-navbar.vue';
|
||||
import detailCellSku from './components/detail/detail-cell-sku.vue';
|
||||
import detailTabbar from './components/detail/detail-tabbar.vue';
|
||||
import detailSkeleton from './components/detail/detail-skeleton.vue';
|
||||
import detailCommentCard from './components/detail/detail-comment-card.vue';
|
||||
import detailContentCard from './components/detail/detail-content-card.vue';
|
||||
import detailActivityTip from './components/detail/detail-activity-tip.vue';
|
||||
import { isEmpty } from 'lodash';
|
||||
import RewardActivityApi from '@/sheep/api/promotion/rewardActivity';
|
||||
import {
|
||||
formatSales,
|
||||
formatGoodsSwiper,
|
||||
fen2yuan,
|
||||
fen2yuanSimple,
|
||||
formatDiscountPercent,
|
||||
getRewardActivityRuleItemDescriptions,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import detailNavbar from './components/detail/detail-navbar.vue';
|
||||
import detailCellSku from './components/detail/detail-cell-sku.vue';
|
||||
import detailTabbar from './components/detail/detail-tabbar.vue';
|
||||
import detailSkeleton from './components/detail/detail-skeleton.vue';
|
||||
import detailCommentCard from './components/detail/detail-comment-card.vue';
|
||||
import detailContentCard from './components/detail/detail-content-card.vue';
|
||||
import detailActivityTip from './components/detail/detail-activity-tip.vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
|
||||
onPageScroll(() => {});
|
||||
onPageScroll(() => {});
|
||||
import countDown from '@/sheep/components/countDown/index.vue';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import activity from '@/sheep/api/promotion/activity';
|
||||
|
||||
const state = reactive({
|
||||
goodsId: 0,
|
||||
skeletonLoading: true, // SPU 加载中
|
||||
goodsInfo: {}, // SPU 信息
|
||||
showSelectSku: false, // 是否展示 SKU 选择弹窗
|
||||
selectedSku: {}, // 选中的 SKU
|
||||
showModel: false, // 是否展示 Coupon 优惠劵的弹窗
|
||||
couponInfo: [], // 可领取的 Coupon 优惠劵的列表
|
||||
showActivityModel: false, // 【满减送/限时折扣】是否展示 Activity 营销活动的弹窗
|
||||
activityInfo: [], // 【满减送/限时折扣】可参与的 Activity 营销活动的列表
|
||||
activityList: [], // 【秒杀/拼团/砍价】可参与的 Activity 营销活动的列表
|
||||
});
|
||||
const bgColor = {
|
||||
bgColor: '#E93323',
|
||||
Color: '#fff',
|
||||
width: '44rpx',
|
||||
timeTxtwidth: '16rpx',
|
||||
isDay: true,
|
||||
};
|
||||
const isLogin = computed(() => sheep.$store('user').isLogin);
|
||||
const state = reactive({
|
||||
goodsId: 0,
|
||||
skeletonLoading: true, // SPU 加载中
|
||||
goodsInfo: {}, // SPU 信息
|
||||
showSelectSku: false, // 是否展示 SKU 选择弹窗
|
||||
selectedSku: {}, // 选中的 SKU
|
||||
settlementSku: {}, // 结算的 SKU:由于 selectedSku 不进行默认选中,所以初始使用结算价格最低的 SKU 作为基础展示
|
||||
showModel: false, // 是否展示 Coupon 优惠劵的弹窗
|
||||
couponInfo: [], // 可领取的 Coupon 优惠劵的列表
|
||||
showActivityModel: false, // 【满减送/限时折扣】是否展示 Activity 营销活动的弹窗
|
||||
rewardActivity: {}, // 【满减送】活动
|
||||
activityList: [], // 【秒杀/拼团/砍价】可参与的 Activity 营销活动的列表
|
||||
});
|
||||
|
||||
// 规格变更
|
||||
function onSkuChange(e) {
|
||||
state.selectedSku = e;
|
||||
}
|
||||
// 规格变更
|
||||
function onSkuChange(e) {
|
||||
state.selectedSku = e;
|
||||
state.settlementSku = e;
|
||||
}
|
||||
|
||||
// 添加购物车
|
||||
function onAddCart(e) {
|
||||
// 添加购物车
|
||||
function onAddCart(e) {
|
||||
if (!e.id) {
|
||||
sheep.$helper.toast('请选择商品规格');
|
||||
return;
|
||||
}
|
||||
sheep.$store('cart').add(e);
|
||||
}
|
||||
sheep.$store('cart').add(e);
|
||||
}
|
||||
|
||||
// 立即购买
|
||||
function onBuy(e) {
|
||||
if (!state.selectedSku.id) {
|
||||
// 立即购买
|
||||
function onBuy(e) {
|
||||
if (!e.id) {
|
||||
sheep.$helper.toast('请选择商品规格');
|
||||
return;
|
||||
}
|
||||
sheep.$router.go('/pages/order/confirm', {
|
||||
data: JSON.stringify({
|
||||
items: [{
|
||||
skuId: e.id,
|
||||
count: e.goods_num
|
||||
}],
|
||||
// TODO 芋艿:后续清理掉这 2 参数
|
||||
deliveryType: 1,
|
||||
pointStatus: false,
|
||||
items: [
|
||||
{
|
||||
skuId: e.id,
|
||||
count: e.goods_num,
|
||||
categoryId: state.goodsInfo.categoryId,
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 营销活动
|
||||
function onActivity() {
|
||||
state.showActivityModel = true;
|
||||
}
|
||||
// 打开营销弹窗
|
||||
function onOpenActivity() {
|
||||
state.showActivityModel = true;
|
||||
}
|
||||
|
||||
// 立即领取
|
||||
async function onGet(id) {
|
||||
// 立即领取优惠劵
|
||||
async function onTakeCoupon(id) {
|
||||
const { code } = await CouponApi.takeCoupon(id);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
@@ -187,28 +308,29 @@
|
||||
setTimeout(() => {
|
||||
getCoupon();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 芋艿:待测试
|
||||
const shareInfo = computed(() => {
|
||||
if (isEmpty(state.goodsInfo)) return {};
|
||||
return sheep.$platform.share.getShareInfo({
|
||||
title: state.goodsInfo.name,
|
||||
image: sheep.$url.cdn(state.goodsInfo.image),
|
||||
desc: state.goodsInfo.subtitle,
|
||||
params: {
|
||||
page: '2',
|
||||
query: state.goodsInfo.id,
|
||||
},
|
||||
}, {
|
||||
type: 'goods', // 商品海报
|
||||
title: state.goodsInfo.name, // 商品标题
|
||||
// image: sheep.$url.cdn(state.goodsInfo.image), // 商品主图
|
||||
image: sheep.$url.cdn(state.goodsInfo.picUrl), // 商品主图
|
||||
price: fen2yuan(state.goodsInfo.price), // 商品价格
|
||||
original_price: fen2yuan(state.goodsInfo.maretPrice), // 商品原价
|
||||
}, );
|
||||
});
|
||||
const shareInfo = computed(() => {
|
||||
if (isEmpty(state.goodsInfo)) return {};
|
||||
return sheep.$platform.share.getShareInfo(
|
||||
{
|
||||
title: state.goodsInfo.name,
|
||||
image: sheep.$url.cdn(state.goodsInfo.picUrl),
|
||||
desc: state.goodsInfo.introduction,
|
||||
params: {
|
||||
page: '2',
|
||||
query: state.goodsInfo.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'goods', // 商品海报
|
||||
title: state.goodsInfo.name, // 商品名称
|
||||
image: sheep.$url.cdn(state.goodsInfo.picUrl), // 商品主图
|
||||
price: fen2yuan(state.goodsInfo.price), // 商品价格
|
||||
original_price: fen2yuan(state.goodsInfo.marketPrice), // 商品原价
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
async function getCoupon() {
|
||||
const { code, data } = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
|
||||
@@ -217,197 +339,331 @@
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
// 非法参数
|
||||
if (!options.id) {
|
||||
state.goodsInfo = null;
|
||||
return;
|
||||
}
|
||||
state.goodsId = options.id;
|
||||
// 1. 加载商品信息
|
||||
SpuApi.getSpuDetail(state.goodsId).then((res) => {
|
||||
// 未找到商品
|
||||
if (res.code !== 0 || !res.data) {
|
||||
state.goodsInfo = null;
|
||||
return;
|
||||
}
|
||||
// 加载到商品
|
||||
state.skeletonLoading = false;
|
||||
state.goodsInfo = res.data;
|
||||
async function getSettlementByIds(ids) {
|
||||
let { data, code } = await OrderApi.getSettlementProduct(ids);
|
||||
if (code !== 0 || data.length !== 1) {
|
||||
return;
|
||||
}
|
||||
data = data[0];
|
||||
|
||||
// 加载是否收藏
|
||||
FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
|
||||
if (res.code !== 0) {
|
||||
return;
|
||||
// 补充 SKU 的价格信息
|
||||
state.goodsInfo.skus.forEach((sku) => {
|
||||
data.skus.forEach((item) => {
|
||||
if (sku.id === item.id) {
|
||||
sku.promotionType = item.promotionType;
|
||||
sku.promotionPrice = item.promotionPrice;
|
||||
sku.promotionId = item.promotionId;
|
||||
sku.promotionEndTime = item.promotionEndTime;
|
||||
}
|
||||
state.goodsInfo.favorite = res.data;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 2. 加载优惠劵信息
|
||||
// 选择有 promotionPrice 且最小的
|
||||
state.settlementSku = state.goodsInfo.skus
|
||||
.filter((sku) => sku.stock > 0 && sku.promotionPrice > 0)
|
||||
.reduce((prev, curr) => (prev.promotionPrice < curr.promotionPrice ? prev : curr));
|
||||
|
||||
// 设置满减送活动
|
||||
if (data.rewardActivity) {
|
||||
state.rewardActivity = data.rewardActivity;
|
||||
//获取活动时间
|
||||
getActivityTime(state.rewardActivity.id);
|
||||
}
|
||||
}
|
||||
|
||||
//获取活动时间
|
||||
async function getActivityTime(id) {
|
||||
const { code, data } = await RewardActivityApi.getRewardActivity(id);
|
||||
if (code === 0) {
|
||||
// console.log('获取到的活动 数据', data)
|
||||
state.rewardActivity.startTime = data.startTime;
|
||||
state.rewardActivity.endTime = data.endTime;
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
// 非法参数
|
||||
if (!options.id) {
|
||||
state.goodsInfo = null;
|
||||
return;
|
||||
}
|
||||
state.goodsId = options.id;
|
||||
// 1. 加载商品信息
|
||||
SpuApi.getSpuDetail(state.goodsId).then((res) => {
|
||||
// 未找到商品
|
||||
if (res.code !== 0 || !res.data) {
|
||||
state.goodsInfo = null;
|
||||
return;
|
||||
}
|
||||
// 加载到商品
|
||||
state.skeletonLoading = false;
|
||||
state.goodsInfo = res.data;
|
||||
// 加载是否收藏
|
||||
if (isLogin.value) {
|
||||
FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
|
||||
if (res.code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.goodsInfo.favorite = res.data;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 加载优惠劵信息
|
||||
getCoupon();
|
||||
|
||||
// 3. 加载营销活动信息
|
||||
ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
return;
|
||||
}
|
||||
res.data.forEach(activity => {
|
||||
if ([1, 2, 3].includes(activity.type)) { // 情况一:拼团/秒杀/砍价
|
||||
state.activityList.push(activity);
|
||||
} else if (activity.type === 5) { // 情况二:满减送
|
||||
state.activityInfo.push(activity);
|
||||
} else { // 情况三:限时折扣 TODO 芋艿
|
||||
console.log('待实现!优先级不高');
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
// 3. 加载营销活动信息
|
||||
ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.activityList = res.data;
|
||||
});
|
||||
//获取结算信息
|
||||
getSettlementByIds(state.goodsId);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.detail-card {
|
||||
background-color: #ffff;
|
||||
margin: 14rpx 20rpx;
|
||||
border-radius: 10rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.detail-card {
|
||||
background-color: #ffff;
|
||||
margin: 14rpx 20rpx;
|
||||
border-radius: 10rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// 价格标题卡片
|
||||
.title-card {
|
||||
.price-box {
|
||||
.price-text {
|
||||
font-size: 42rpx;
|
||||
font-weight: 500;
|
||||
color: #ff3000;
|
||||
line-height: 30rpx;
|
||||
font-family: OPPOSANS;
|
||||
// 价格标题卡片
|
||||
.title-card {
|
||||
.price-box {
|
||||
.price-text {
|
||||
font-size: 42rpx;
|
||||
font-weight: 500;
|
||||
color: #ff3000;
|
||||
line-height: 30rpx;
|
||||
font-family: OPPOSANS;
|
||||
|
||||
&::before {
|
||||
content: '¥';
|
||||
font-size: 30rpx;
|
||||
}
|
||||
}
|
||||
&::before {
|
||||
content: '¥';
|
||||
font-size: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.origin-price-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
text-decoration: line-through;
|
||||
color: $gray-c;
|
||||
font-family: OPPOSANS;
|
||||
.origin-price-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
text-decoration: line-through;
|
||||
color: $gray-c;
|
||||
font-family: OPPOSANS;
|
||||
|
||||
&::before {
|
||||
content: '¥';
|
||||
}
|
||||
}
|
||||
}
|
||||
&::before {
|
||||
content: '¥';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sales-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: $gray-c;
|
||||
}
|
||||
.sales-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: $gray-c;
|
||||
}
|
||||
|
||||
.discounts-box {
|
||||
.tag-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.discounts-box {
|
||||
.tag-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tag-box {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.tag-box {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.tag {
|
||||
flex-shrink: 0;
|
||||
padding: 4rpx 10rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
border-radius: 4rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
background: var(--ui-BG-Main-tag);
|
||||
}
|
||||
.tag {
|
||||
flex-shrink: 0;
|
||||
padding: 4rpx 10rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
border-radius: 4rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
background: var(--ui-BG-Main-tag);
|
||||
}
|
||||
|
||||
.discounts-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: var(--ui-BG-Main);
|
||||
line-height: normal;
|
||||
}
|
||||
.discounts-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: var(--ui-BG-Main);
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.cicon-forward {
|
||||
color: var(--ui-BG-Main);
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
.cicon-forward {
|
||||
color: var(--ui-BG-Main);
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
.title-text {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
|
||||
.subtitle-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
color: $dark-9;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
}
|
||||
.subtitle-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
color: $dark-9;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// 购买
|
||||
.buy-box {
|
||||
.add-btn {
|
||||
width: 214rpx;
|
||||
height: 72rpx;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
border-radius: 40rpx 0 0 40rpx;
|
||||
background-color: var(--ui-BG-Main-light);
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
// 购买
|
||||
.buy-box {
|
||||
.add-btn {
|
||||
width: 214rpx;
|
||||
height: 72rpx;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
border-radius: 40rpx 0 0 40rpx;
|
||||
background-color: var(--ui-BG-Main-light);
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.buy-btn {
|
||||
width: 214rpx;
|
||||
height: 72rpx;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
.buy-btn {
|
||||
width: 214rpx;
|
||||
height: 72rpx;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
|
||||
border-radius: 0 40rpx 40rpx 0;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
color: $white;
|
||||
}
|
||||
border-radius: 0 40rpx 40rpx 0;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.disabled-btn {
|
||||
width: 428rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 40rpx;
|
||||
background: #999999;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
.disabled-btn {
|
||||
width: 428rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 40rpx;
|
||||
background: #999999;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
.model-box {
|
||||
height: 60vh;
|
||||
.model-box {
|
||||
height: 60vh;
|
||||
|
||||
.model-content {
|
||||
height: 56vh;
|
||||
}
|
||||
.model-content {
|
||||
height: 56vh;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.subtitle {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
// 限时折扣
|
||||
.discount {
|
||||
width: 750rpx;
|
||||
height: 100rpx;
|
||||
// background-color: red;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.disImg {
|
||||
width: 750rpx;
|
||||
height: 100rpx;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.discountCont {
|
||||
width: 680rpx;
|
||||
height: 90rpx;
|
||||
margin: 10rpx auto 0 auto;
|
||||
// background-color: gold;
|
||||
}
|
||||
|
||||
.disContT {
|
||||
width: 680rpx;
|
||||
height: 50rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.disContT1 {
|
||||
width: 400rpx;
|
||||
height: 50rpx;
|
||||
// background-color: green;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.disContT2 {
|
||||
width: 200rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
// background-color: gold;
|
||||
font-size: 30rpx;
|
||||
text-align: end;
|
||||
color: white;
|
||||
font-weight: bolder;
|
||||
font-style: oblique 20deg;
|
||||
letter-spacing: 0.1rem;
|
||||
}
|
||||
|
||||
.disContT1P {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.disContT1End {
|
||||
// width: 180rpx;
|
||||
padding: 0 10rpx;
|
||||
height: 30rpx;
|
||||
line-height: 28rpx;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
background-color: white;
|
||||
color: #ff3000;
|
||||
font-size: 23rpx;
|
||||
border-radius: 20rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.disContB {
|
||||
width: 680rpx;
|
||||
height: 40rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 20rpx;
|
||||
color: white;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.disContB1 {
|
||||
width: 300rpx;
|
||||
height: 40rpx;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.disContB2 {
|
||||
width: 300rpx;
|
||||
height: 40rpx;
|
||||
line-height: 40rpx;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
+308
-263
@@ -1,362 +1,407 @@
|
||||
<template>
|
||||
<s-layout navbar="normal" :leftWidth="0" :rightWidth="0" tools="search" :defaultSearch="state.keyword"
|
||||
@search="onSearch">
|
||||
<!-- 筛选 -->
|
||||
<su-sticky bgColor="#fff">
|
||||
<view class="ss-flex">
|
||||
<view class="ss-flex-1">
|
||||
<su-tabs :list="state.tabList" :scrollable="false" @change="onTabsChange"
|
||||
:current="state.currentTab" />
|
||||
</view>
|
||||
<view class="list-icon" @tap="state.iconStatus = !state.iconStatus">
|
||||
<text v-if="state.iconStatus" class="sicon-goods-list" />
|
||||
<text v-else class="sicon-goods-card" />
|
||||
</view>
|
||||
</view>
|
||||
</su-sticky>
|
||||
<s-layout
|
||||
navbar="normal"
|
||||
:leftWidth="0"
|
||||
:rightWidth="0"
|
||||
tools="search"
|
||||
:defaultSearch="state.keyword"
|
||||
@search="onSearch"
|
||||
>
|
||||
<!-- 筛选 -->
|
||||
<su-sticky bgColor="#fff">
|
||||
<view class="ss-flex">
|
||||
<view class="ss-flex-1">
|
||||
<su-tabs
|
||||
:list="state.tabList"
|
||||
:scrollable="false"
|
||||
@change="onTabsChange"
|
||||
:current="state.currentTab"
|
||||
/>
|
||||
</view>
|
||||
<view class="list-icon" @tap="state.iconStatus = !state.iconStatus">
|
||||
<text v-if="state.iconStatus" class="sicon-goods-list" />
|
||||
<text v-else class="sicon-goods-card" />
|
||||
</view>
|
||||
</view>
|
||||
</su-sticky>
|
||||
|
||||
<!-- 弹窗 -->
|
||||
<su-popup :show="state.showFilter" type="top" round="10" :space="sys_navBar + 38" backgroundColor="#F6F6F6"
|
||||
:zIndex="10" @close="state.showFilter = false">
|
||||
<view class="filter-list-box">
|
||||
<view class="filter-item" v-for="(item, index) in state.tabList[state.currentTab].list"
|
||||
:key="item.value" :class="[{ 'filter-item-active': index === state.curFilter }]"
|
||||
@tap="onFilterItem(index)">
|
||||
{{ item.label }}
|
||||
</view>
|
||||
</view>
|
||||
</su-popup>
|
||||
<!-- 弹窗 -->
|
||||
<su-popup
|
||||
:show="state.showFilter"
|
||||
type="top"
|
||||
round="10"
|
||||
:space="sys_navBar + 38"
|
||||
backgroundColor="#F6F6F6"
|
||||
:zIndex="10"
|
||||
@close="state.showFilter = false"
|
||||
>
|
||||
<view class="filter-list-box">
|
||||
<view
|
||||
class="filter-item"
|
||||
v-for="(item, index) in state.tabList[state.currentTab].list"
|
||||
:key="item.value"
|
||||
:class="[{ 'filter-item-active': index === state.curFilter }]"
|
||||
@tap="onFilterItem(index)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</view>
|
||||
</view>
|
||||
</su-popup>
|
||||
|
||||
<!-- 情况一:单列布局 -->
|
||||
<view v-if="state.iconStatus && state.pagination.total > 0" class="goods-list ss-m-t-20">
|
||||
<view class="ss-p-l-20 ss-p-r-20 ss-m-b-20" v-for="item in state.pagination.list" :key="item.id">
|
||||
<s-goods-column
|
||||
<view v-if="state.iconStatus && state.pagination.total > 0" class="goods-list ss-m-t-20">
|
||||
<view
|
||||
class="ss-p-l-20 ss-p-r-20 ss-m-b-20"
|
||||
v-for="item in state.pagination.list"
|
||||
:key="item.id"
|
||||
>
|
||||
<s-goods-column
|
||||
class=""
|
||||
size="lg"
|
||||
:data="item"
|
||||
:topRadius="10"
|
||||
:bottomRadius="10"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 情况二:双列布局 -->
|
||||
<view v-if="!state.iconStatus && state.pagination.total > 0"
|
||||
class="ss-flex ss-flex-wrap ss-p-x-20 ss-m-t-20 ss-col-top">
|
||||
<view class="goods-list-box">
|
||||
<view class="left-list" v-for="item in state.leftGoodsList" :key="item.id">
|
||||
<s-goods-column
|
||||
<view
|
||||
v-if="!state.iconStatus && state.pagination.total > 0"
|
||||
class="ss-flex ss-flex-wrap ss-p-x-20 ss-m-t-20 ss-col-top"
|
||||
>
|
||||
<view class="goods-list-box">
|
||||
<view class="left-list" v-for="item in state.leftGoodsList" :key="item.id">
|
||||
<s-goods-column
|
||||
class="goods-md-box"
|
||||
size="md"
|
||||
:data="item"
|
||||
:topRadius="10"
|
||||
:bottomRadius="10"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
@getHeight="mountMasonry($event, 'left')"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
@getHeight="mountMasonry($event, 'left')"
|
||||
>
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" />
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-list-box">
|
||||
<view class="right-list" v-for="item in state.rightGoodsList" :key="item.id">
|
||||
<s-goods-column
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" />
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-list-box">
|
||||
<view class="right-list" v-for="item in state.rightGoodsList" :key="item.id">
|
||||
<s-goods-column
|
||||
class="goods-md-box"
|
||||
size="md"
|
||||
:topRadius="10"
|
||||
:bottomRadius="10"
|
||||
:data="item"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
@getHeight="mountMasonry($event, 'right')"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
@getHeight="mountMasonry($event, 'right')"
|
||||
>
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" />
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" />
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}" @tap="loadMore" />
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/soldout-empty.png" text="暂无商品" />
|
||||
</s-layout>
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/soldout-empty.png" text="暂无商品" />
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash-es';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import { appendSettlementProduct } from '@/sheep/hooks/useGoods';
|
||||
|
||||
const sys_navBar = sheep.$platform.navbar;
|
||||
const emits = defineEmits(['close', 'change']);
|
||||
const sys_navBar = sheep.$platform.navbar;
|
||||
const emits = defineEmits(['close', 'change']);
|
||||
|
||||
const state = reactive({
|
||||
pagination: {
|
||||
list: [],
|
||||
const state = reactive({
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 6,
|
||||
},
|
||||
currentSort: undefined,
|
||||
currentOrder: undefined,
|
||||
currentTab: 0, // 当前选中的 tab
|
||||
curFilter: 0, // 当前选中的 list 筛选项
|
||||
showFilter: false,
|
||||
iconStatus: false, // true - 单列布局;false - 双列布局
|
||||
pageSize: 6,
|
||||
},
|
||||
currentSort: undefined,
|
||||
currentOrder: undefined,
|
||||
currentTab: 0, // 当前选中的 tab
|
||||
curFilter: 0, // 当前选中的 list 筛选项
|
||||
showFilter: false,
|
||||
iconStatus: false, // true - 单列布局;false - 双列布局
|
||||
keyword: '',
|
||||
categoryId: 0,
|
||||
tabList: [{
|
||||
name: '综合推荐',
|
||||
list: [{
|
||||
label: '综合推荐'
|
||||
},
|
||||
{
|
||||
label: '价格升序',
|
||||
sort: 'price',
|
||||
order: true,
|
||||
},
|
||||
{
|
||||
label: '价格降序',
|
||||
sort: 'price',
|
||||
order: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '销量',
|
||||
sort: 'salesCount',
|
||||
order: false
|
||||
},
|
||||
{
|
||||
name: '新品优先',
|
||||
value: 'createTime',
|
||||
order: false
|
||||
},
|
||||
],
|
||||
loadStatus: '',
|
||||
leftGoodsList: [], // 双列布局 - 左侧商品
|
||||
rightGoodsList: [], // 双列布局 - 右侧商品
|
||||
});
|
||||
tabList: [
|
||||
{
|
||||
name: '综合推荐',
|
||||
list: [
|
||||
{
|
||||
label: '综合推荐',
|
||||
},
|
||||
{
|
||||
label: '价格升序',
|
||||
sort: 'price',
|
||||
order: true,
|
||||
},
|
||||
{
|
||||
label: '价格降序',
|
||||
sort: 'price',
|
||||
order: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '销量',
|
||||
sort: 'salesCount',
|
||||
order: false,
|
||||
},
|
||||
{
|
||||
name: '新品优先',
|
||||
value: 'createTime',
|
||||
order: false,
|
||||
},
|
||||
],
|
||||
loadStatus: '',
|
||||
leftGoodsList: [], // 双列布局 - 左侧商品
|
||||
rightGoodsList: [], // 双列布局 - 右侧商品
|
||||
});
|
||||
|
||||
// 加载瀑布流
|
||||
let count = 0;
|
||||
let leftHeight = 0;
|
||||
let rightHeight = 0;
|
||||
// 加载瀑布流
|
||||
let count = 0;
|
||||
let leftHeight = 0;
|
||||
let rightHeight = 0;
|
||||
|
||||
// 处理双列布局 leftGoodsList + rightGoodsList
|
||||
function mountMasonry(height = 0, where = 'left') {
|
||||
if (!state.pagination.list[count]) {
|
||||
function mountMasonry(height = 0, where = 'left') {
|
||||
if (!state.pagination.list[count]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (where === 'left') {
|
||||
leftHeight += height;
|
||||
} else {
|
||||
rightHeight += height;
|
||||
}
|
||||
if (leftHeight <= rightHeight) {
|
||||
state.leftGoodsList.push(state.pagination.list[count]);
|
||||
} else {
|
||||
state.rightGoodsList.push(state.pagination.list[count]);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (where === 'left') {
|
||||
leftHeight += height;
|
||||
} else {
|
||||
rightHeight += height;
|
||||
}
|
||||
if (leftHeight <= rightHeight) {
|
||||
state.leftGoodsList.push(state.pagination.list[count]);
|
||||
} else {
|
||||
state.rightGoodsList.push(state.pagination.list[count]);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
// 清空列表
|
||||
function emptyList() {
|
||||
function emptyList() {
|
||||
resetPagination(state.pagination);
|
||||
state.leftGoodsList = [];
|
||||
state.rightGoodsList = [];
|
||||
count = 0;
|
||||
leftHeight = 0;
|
||||
rightHeight = 0;
|
||||
}
|
||||
state.rightGoodsList = [];
|
||||
count = 0;
|
||||
leftHeight = 0;
|
||||
rightHeight = 0;
|
||||
}
|
||||
|
||||
// 搜索
|
||||
function onSearch(e) {
|
||||
state.keyword = e;
|
||||
emptyList();
|
||||
getList(state.currentSort, state.currentOrder);
|
||||
}
|
||||
// 搜索
|
||||
function onSearch(e) {
|
||||
state.keyword = e;
|
||||
emptyList();
|
||||
getList(state.currentSort, state.currentOrder);
|
||||
}
|
||||
|
||||
// 点击
|
||||
function onTabsChange(e) {
|
||||
// 点击
|
||||
function onTabsChange(e) {
|
||||
// 如果点击的是【综合推荐】,则直接展开或者收起筛选项
|
||||
if (state.tabList[e.index].list) {
|
||||
state.currentTab = e.index;
|
||||
state.showFilter = !state.showFilter;
|
||||
return;
|
||||
}
|
||||
if (state.tabList[e.index].list) {
|
||||
state.currentTab = e.index;
|
||||
state.showFilter = !state.showFilter;
|
||||
return;
|
||||
}
|
||||
state.showFilter = false;
|
||||
|
||||
// 如果点击的是【销量】或者【新品优先】,则直接切换 tab
|
||||
if (e.index === state.currentTab) {
|
||||
return;
|
||||
}
|
||||
if (e.index === state.currentTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.currentTab = e.index;
|
||||
state.currentSort = e.sort;
|
||||
state.currentOrder = e.order;
|
||||
emptyList();
|
||||
getList(e.sort, e.order);
|
||||
}
|
||||
emptyList();
|
||||
getList(e.sort, e.order);
|
||||
}
|
||||
|
||||
// 点击 tab 的 list 筛选项
|
||||
const onFilterItem = (val) => {
|
||||
// 点击 tab 的 list 筛选项
|
||||
const onFilterItem = (val) => {
|
||||
// 如果点击的是当前的筛选项,则直接收起筛选项,不要加载数据
|
||||
// 这里选择 tabList[0] 的原因,是目前只有它有 list
|
||||
if (state.currentSort === state.tabList[0].list[val].sort
|
||||
&& state.currentOrder === state.tabList[0].list[val].order) {
|
||||
state.showFilter = false;
|
||||
return;
|
||||
}
|
||||
if (
|
||||
state.currentSort === state.tabList[0].list[val].sort &&
|
||||
state.currentOrder === state.tabList[0].list[val].order
|
||||
) {
|
||||
state.showFilter = false;
|
||||
return;
|
||||
}
|
||||
state.showFilter = false;
|
||||
|
||||
// 设置筛选条件
|
||||
state.curFilter = val;
|
||||
state.tabList[0].name = state.tabList[0].list[val].label;
|
||||
state.currentSort = state.tabList[0].list[val].sort;
|
||||
state.currentOrder = state.tabList[0].list[val].order;
|
||||
// 清空 + 加载数据
|
||||
state.curFilter = val;
|
||||
state.tabList[0].name = state.tabList[0].list[val].label;
|
||||
state.currentSort = state.tabList[0].list[val].sort;
|
||||
state.currentOrder = state.tabList[0].list[val].order;
|
||||
// 清空 + 加载数据
|
||||
emptyList();
|
||||
getList();
|
||||
}
|
||||
getList();
|
||||
};
|
||||
|
||||
async function getList() {
|
||||
state.loadStatus = 'loading';
|
||||
const { code, data } = await SpuApi.getSpuPage({
|
||||
async function getList() {
|
||||
state.loadStatus = 'loading';
|
||||
const { code, data } = await SpuApi.getSpuPage({
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
sortField: state.currentSort,
|
||||
sortAsc: state.currentOrder,
|
||||
categoryId: state.categoryId,
|
||||
keyword: state.keyword,
|
||||
});
|
||||
sortField: state.currentSort,
|
||||
sortAsc: state.currentOrder,
|
||||
categoryId: state.categoryId,
|
||||
keyword: state.keyword,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list)
|
||||
// 拼接结算信息(营销)
|
||||
await OrderApi.getSettlementProduct(data.list.map((item) => item.id).join(',')).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
return;
|
||||
}
|
||||
appendSettlementProduct(data.list, res.data);
|
||||
});
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
mountMasonry();
|
||||
}
|
||||
}
|
||||
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getList(state.currentSort, state.currentOrder);
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
state.categoryId = options.categoryId;
|
||||
state.keyword = options.keyword;
|
||||
getList(state.currentSort, state.currentOrder);
|
||||
});
|
||||
onLoad((options) => {
|
||||
state.categoryId = options.categoryId;
|
||||
state.keyword = options.keyword;
|
||||
getList(state.currentSort, state.currentOrder);
|
||||
});
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.goods-list-box {
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
.goods-list-box {
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.left-list {
|
||||
margin-right: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.left-list {
|
||||
margin-right: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.right-list {
|
||||
margin-left: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
.right-list {
|
||||
margin-left: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-box {
|
||||
&:nth-last-of-type(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.goods-box {
|
||||
&:nth-last-of-type(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
&:nth-child(2n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
&:nth-child(2n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.list-icon {
|
||||
width: 80rpx;
|
||||
.list-icon {
|
||||
width: 80rpx;
|
||||
|
||||
.sicon-goods-card {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
.sicon-goods-card {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
|
||||
.sicon-goods-list {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
}
|
||||
.sicon-goods-list {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-card {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
.goods-card {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.list-filter-tabs {
|
||||
background-color: #fff;
|
||||
}
|
||||
.list-filter-tabs {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.filter-list-box {
|
||||
padding: 28rpx 52rpx;
|
||||
.filter-list-box {
|
||||
padding: 28rpx 52rpx;
|
||||
|
||||
.filter-item {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
margin-bottom: 24rpx;
|
||||
.filter-item {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-item-active {
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
.filter-item-active {
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
height: 50px;
|
||||
position: relative;
|
||||
z-index: 11;
|
||||
.tab-item {
|
||||
height: 50px;
|
||||
position: relative;
|
||||
z-index: 11;
|
||||
|
||||
.tab-title {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.tab-title {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.cur-tab-title {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
.cur-tab-title {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
.tab-line {
|
||||
width: 60rpx;
|
||||
height: 6rpx;
|
||||
border-radius: 6rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 10rpx;
|
||||
background-color: var(--ui-BG-Main);
|
||||
z-index: 12;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.tab-line {
|
||||
width: 60rpx;
|
||||
height: 6rpx;
|
||||
border-radius: 6rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 10rpx;
|
||||
background-color: var(--ui-BG-Main);
|
||||
z-index: 12;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,480 @@
|
||||
<!-- 秒杀商品详情 -->
|
||||
<template>
|
||||
<s-layout :onShareAppMessage="shareInfo" navbar="goods">
|
||||
<!-- 标题栏 -->
|
||||
<detailNavbar />
|
||||
<!-- 骨架屏 -->
|
||||
<detailSkeleton v-if="state.skeletonLoading" />
|
||||
<!-- 下架/售罄提醒 -->
|
||||
<s-empty
|
||||
v-else-if="state.goodsInfo === null || state.goodsInfo.activity_type !== PromotionActivityTypeEnum.POINT.type"
|
||||
text="活动不存在或已结束"
|
||||
icon="/static/soldout-empty.png"
|
||||
showAction
|
||||
actionText="再逛逛"
|
||||
actionUrl="/pages/goods/list"
|
||||
/>
|
||||
<block v-else>
|
||||
<view class="detail-swiper-selector">
|
||||
<!-- 商品图轮播 -->
|
||||
<su-swiper
|
||||
class="ss-m-b-14"
|
||||
isPreview
|
||||
:list="state.goodsSwiper"
|
||||
dotStyle="tag"
|
||||
imageMode="widthFix"
|
||||
dotCur="bg-mask-40"
|
||||
:seizeHeight="750"
|
||||
/>
|
||||
|
||||
<!-- 价格+标题 -->
|
||||
<view class="title-card detail-card ss-p-y-40 ss-p-x-20">
|
||||
<view class="ss-flex ss-row-between ss-col-center ss-m-b-18">
|
||||
<view class="price-box ss-flex ss-col-bottom">
|
||||
<image
|
||||
:src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
|
||||
class="point-img"
|
||||
></image>
|
||||
<text class="point-text ss-m-r-16">
|
||||
{{ getShowPrice.point }}
|
||||
{{ !getShowPrice.price || getShowPrice.price === 0 ? '' : `+¥${getShowPrice.price}` }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="sales-text">
|
||||
{{ formatExchange(state.goodsInfo.sales_show_type, state.goodsInfo.sales) }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="origin-price-text ss-m-b-60" v-if="state.goodsInfo.marketPrice">
|
||||
原价:¥{{ fen2yuan(state.selectedSku.marketPrice || state.goodsInfo.marketPrice) }}
|
||||
</view>
|
||||
<view class="title-text ss-line-2 ss-m-b-6">{{ state.goodsInfo.name || '' }}</view>
|
||||
<view class="subtitle-text ss-line-1">{{ state.goodsInfo.introduction }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 功能卡片 -->
|
||||
<view class="detail-cell-card detail-card ss-flex-col">
|
||||
<detail-cell-sku :sku="state.selectedSku" @tap="state.showSelectSku = true" />
|
||||
</view>
|
||||
<!-- 规格与数量弹框 -->
|
||||
<s-select-seckill-sku
|
||||
v-model="state.goodsInfo"
|
||||
:show="state.showSelectSku"
|
||||
:single-limit-count="activity.singleLimitCount"
|
||||
@buy="onBuy"
|
||||
@change="onSkuChange"
|
||||
@close="state.showSelectSku = false"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 评价 -->
|
||||
<detail-comment-card class="detail-comment-selector" :goodsId="state.goodsInfo.id" />
|
||||
<!-- 详情 -->
|
||||
<detail-content-card class="detail-content-selector" :content="state.goodsInfo.description" />
|
||||
|
||||
<!-- 详情tabbar -->
|
||||
<detail-tabbar v-model="state.goodsInfo">
|
||||
<view class="buy-box ss-flex ss-col-center ss-p-r-20">
|
||||
<button
|
||||
class="ss-reset-button origin-price-btn ss-flex-col"
|
||||
v-if="state.goodsInfo.marketPrice"
|
||||
@tap="sheep.$router.go('/pages/goods/index', { id: state.goodsInfo.id })"
|
||||
>
|
||||
<view>
|
||||
<view class="btn-price">{{ fen2yuan(state.goodsInfo.marketPrice) }}</view>
|
||||
<view>原价购买</view>
|
||||
</view>
|
||||
</button>
|
||||
<button
|
||||
class="ss-reset-button btn-box ss-flex-col"
|
||||
@tap="state.showSelectSku = true"
|
||||
:class="
|
||||
state.goodsInfo.stock != 0
|
||||
? 'check-btn-box'
|
||||
: 'disabled-btn-box'
|
||||
"
|
||||
:disabled="state.goodsInfo.stock === 0"
|
||||
>
|
||||
<view class="price-box ss-flex">
|
||||
<image
|
||||
:src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
|
||||
style="width: 36rpx;height: 36rpx;margin: 0 4rpx;"
|
||||
></image>
|
||||
<text class="point-text ss-m-r-16">
|
||||
{{ getShowPrice.point }}
|
||||
{{ !getShowPrice.price || getShowPrice.price === 0 ? '' : `+¥${getShowPrice.price}` }}
|
||||
</text>
|
||||
</view>
|
||||
<view v-if="state.goodsInfo.stock === 0">已售罄</view>
|
||||
<view v-else>立即兑换</view>
|
||||
</button>
|
||||
</view>
|
||||
</detail-tabbar>
|
||||
</block>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, reactive, ref, unref } from 'vue';
|
||||
import { onLoad, onPageScroll } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import { fen2yuan, formatExchange, formatGoodsSwiper } from '@/sheep/hooks/useGoods';
|
||||
import detailNavbar from './components/detail/detail-navbar.vue';
|
||||
import detailCellSku from './components/detail/detail-cell-sku.vue';
|
||||
import detailTabbar from './components/detail/detail-tabbar.vue';
|
||||
import detailSkeleton from './components/detail/detail-skeleton.vue';
|
||||
import detailCommentCard from './components/detail/detail-comment-card.vue';
|
||||
import detailContentCard from './components/detail/detail-content-card.vue';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
import { PromotionActivityTypeEnum } from '@/sheep/util/const';
|
||||
import PointApi from '@/sheep/api/promotion/point';
|
||||
|
||||
const headerBg = sheep.$url.css('/static/img/shop/goods/score-bg.png');
|
||||
const btnBg = sheep.$url.css('/static/img/shop/goods/seckill-btn.png');
|
||||
const disabledBtnBg = sheep.$url.css('/static/img/shop/goods/activity-btn-disabled.png');
|
||||
const seckillBg = sheep.$url.css('/static/img/shop/goods/seckill-tip-bg.png');
|
||||
const grouponBg = sheep.$url.css('/static/img/shop/goods/groupon-tip-bg.png');
|
||||
|
||||
onPageScroll(() => {
|
||||
});
|
||||
const state = reactive({
|
||||
skeletonLoading: true,
|
||||
goodsInfo: {},
|
||||
showSelectSku: false,
|
||||
goodsSwiper: [],
|
||||
selectedSku: {},
|
||||
showModel: false,
|
||||
total: 0,
|
||||
price: '',
|
||||
});
|
||||
|
||||
// 规格变更
|
||||
function onSkuChange(e) {
|
||||
state.selectedSku = e;
|
||||
}
|
||||
|
||||
// 立即购买
|
||||
function onBuy(sku) {
|
||||
sheep.$router.go('/pages/order/confirm', {
|
||||
data: JSON.stringify({
|
||||
order_type: 'goods',
|
||||
buy_type: 'point',
|
||||
pointActivityId: activity.value.id,
|
||||
items: [
|
||||
{
|
||||
skuId: sku.id,
|
||||
count: sku.count,
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
// 分享信息
|
||||
// TODO puhui999: 下次 fix
|
||||
const shareInfo = computed(() => {
|
||||
if (isEmpty(unref(activity))) return {};
|
||||
return sheep.$platform.share.getShareInfo(
|
||||
{
|
||||
title: activity.value.name,
|
||||
image: sheep.$url.cdn(state.goodsInfo.picUrl),
|
||||
params: {
|
||||
page: '4',
|
||||
query: activity.value.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'goods', // 商品海报
|
||||
title: activity.value.name, // 商品标题
|
||||
image: sheep.$url.cdn(state.goodsInfo.picUrl), // 商品主图
|
||||
price: state.goodsInfo.price, // 商品价格
|
||||
marketPrice: state.goodsInfo.marketPrice, // 商品原价
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
const activity = ref();
|
||||
|
||||
const getShowPrice = computed(() => {
|
||||
if (!isEmpty(state.selectedSku)) {
|
||||
const sku = state.selectedSku;
|
||||
return {
|
||||
point: sku.point,
|
||||
price: !sku.pointPrice ? '' : fen2yuan(sku.pointPrice),
|
||||
};
|
||||
}
|
||||
return {
|
||||
point: activity.value.point,
|
||||
price: !activity.value.price ? '' : fen2yuan(activity.value.price),
|
||||
};
|
||||
});
|
||||
|
||||
const getShowPriceText = computed(() => {
|
||||
let priceText = `¥${fen2yuan(state.goodsInfo.price)}`;
|
||||
if (!isEmpty(state.selectedSku)) {
|
||||
const sku = state.selectedSku;
|
||||
priceText = `${sku.point}${!sku.pointPrice ? '' : `+¥${fen2yuan(sku.pointPrice)}`}`;
|
||||
}
|
||||
return priceText;
|
||||
});
|
||||
|
||||
// 查询活动
|
||||
const getActivity = async (id) => {
|
||||
const { data } = await PointApi.getPointActivity(id);
|
||||
activity.value = data;
|
||||
// 查询商品
|
||||
await getSpu(data.spuId);
|
||||
};
|
||||
|
||||
// 查询商品
|
||||
const getSpu = async (id) => {
|
||||
const { data } = await SpuApi.getSpuDetail(id);
|
||||
data.activity_type = PromotionActivityTypeEnum.POINT.type;
|
||||
state.goodsInfo = data;
|
||||
state.goodsInfo.stock = Math.min(data.stock, activity.value.stock);
|
||||
// 处理轮播图
|
||||
state.goodsSwiper = formatGoodsSwiper(state.goodsInfo.sliderPicUrls);
|
||||
|
||||
// 价格、库存使用活动的
|
||||
data.skus.forEach((sku) => {
|
||||
const product = activity.value.products.find((product) => product.skuId === sku.id);
|
||||
if (product) {
|
||||
sku.point = product.point;
|
||||
sku.pointPrice = product.price;
|
||||
sku.stock = Math.min(sku.stock, product.stock);
|
||||
// 设置限购数量
|
||||
sku.limitCount = product.count;
|
||||
} else {
|
||||
// 找不到可能是没配置
|
||||
sku.stock = 0;
|
||||
}
|
||||
});
|
||||
|
||||
state.skeletonLoading = false;
|
||||
};
|
||||
|
||||
onLoad((options) => {
|
||||
// 非法参数
|
||||
if (!options.id) {
|
||||
state.goodsInfo = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// 查询活动
|
||||
getActivity(options.id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.disabled-btn-box[disabled] {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
background-color: $white;
|
||||
margin: 14rpx 20rpx;
|
||||
border-radius: 10rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// 价格标题卡片
|
||||
.title-card {
|
||||
width: 710rpx;
|
||||
box-sizing: border-box;
|
||||
background-size: 100% 100%;
|
||||
border-radius: 10rpx;
|
||||
background-image: v-bind(headerBg);
|
||||
background-repeat: no-repeat;
|
||||
|
||||
.price-box {
|
||||
.point-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.point-text {
|
||||
font-size: 42rpx;
|
||||
font-weight: 500;
|
||||
color: #ff3000;
|
||||
line-height: 36rpx;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.price-text {
|
||||
font-size: 42rpx;
|
||||
font-weight: 500;
|
||||
color: #ff3000;
|
||||
line-height: 36rpx;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
}
|
||||
|
||||
.origin-price-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
text-decoration: line-through;
|
||||
color: $gray-c;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.sales-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: $gray-c;
|
||||
}
|
||||
|
||||
.discounts-box {
|
||||
.discounts-tag {
|
||||
padding: 4rpx 10rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
border-radius: 4rpx;
|
||||
color: var(--ui-BG-Main);
|
||||
// background: rgba(#2aae67, 0.05);
|
||||
background: var(--ui-BG-Main-tag);
|
||||
}
|
||||
|
||||
.discounts-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: var(--ui-BG-Main);
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.cicon-forward {
|
||||
color: var(--ui-BG-Main);
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
|
||||
.subtitle-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
color: $dark-9;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// 购买
|
||||
.buy-box {
|
||||
.check-btn-box {
|
||||
width: 248rpx;
|
||||
height: 80rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
margin-left: -36rpx;
|
||||
background-image: v-bind(btnBg);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
color: #ffffff;
|
||||
line-height: normal;
|
||||
border-radius: 0px 40rpx 40rpx 0px;
|
||||
}
|
||||
|
||||
.disabled-btn-box {
|
||||
width: 248rpx;
|
||||
height: 80rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
margin-left: -36rpx;
|
||||
background-image: v-bind(disabledBtnBg);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
color: #999999;
|
||||
line-height: normal;
|
||||
border-radius: 0px 40rpx 40rpx 0px;
|
||||
}
|
||||
|
||||
.btn-price {
|
||||
font-family: OPPOSANS;
|
||||
|
||||
&::before {
|
||||
content: '¥';
|
||||
}
|
||||
}
|
||||
|
||||
.origin-price-btn {
|
||||
width: 236rpx;
|
||||
height: 80rpx;
|
||||
background: rgba(#ff5651, 0.1);
|
||||
color: #ff6000;
|
||||
border-radius: 40rpx 0px 0px 40rpx;
|
||||
line-height: normal;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
|
||||
.no-original {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.btn-title {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//秒杀卡片
|
||||
.seckill-box {
|
||||
background: v-bind(seckillBg) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.groupon-box {
|
||||
background: v-bind(grouponBg) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
//活动卡片
|
||||
.activity-box {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
.activity-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 42rpx;
|
||||
|
||||
.activity-icon {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.activity-go {
|
||||
width: 70rpx;
|
||||
height: 32rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
font-weight: 500;
|
||||
color: #ff6000;
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.model-box {
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+45
-36
@@ -7,7 +7,9 @@
|
||||
<detailSkeleton v-if="state.skeletonLoading" />
|
||||
<!-- 下架/售罄提醒 -->
|
||||
<s-empty
|
||||
v-else-if="state.goodsInfo === null || state.goodsInfo.activity_type !== 'seckill'"
|
||||
v-else-if="
|
||||
state.goodsInfo === null || state.goodsInfo.activity_type !== 'seckill' || endTime.ms <= 0
|
||||
"
|
||||
text="活动不存在或已结束"
|
||||
icon="/static/soldout-empty.png"
|
||||
showAction
|
||||
@@ -63,16 +65,13 @@
|
||||
<detail-progress :percent="state.percent" />
|
||||
</view>
|
||||
|
||||
<view class="title-text ss-line-2 ss-m-b-6">{{ state.goodsInfo?.name }}</view>
|
||||
<view class="title-text ss-line-2 ss-m-b-6">{{ state.goodsInfo.name || '' }}</view>
|
||||
<view class="subtitle-text ss-line-1">{{ state.goodsInfo.introduction }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 功能卡片 -->
|
||||
<view class="detail-cell-card detail-card ss-flex-col">
|
||||
<detail-cell-sku
|
||||
:sku="state.selectedSku"
|
||||
@tap="state.showSelectSku = true"
|
||||
/>
|
||||
<detail-cell-sku :sku="state.selectedSku" @tap="state.showSelectSku = true" />
|
||||
</view>
|
||||
<!-- 规格与数量弹框 -->
|
||||
<s-select-seckill-sku
|
||||
@@ -107,7 +106,9 @@
|
||||
<button v-else class="ss-reset-button origin-price-btn ss-flex-col">
|
||||
<view
|
||||
class="no-original"
|
||||
:class="state.goodsInfo.stock === 0 || timeStatusEnum !== TimeStatusEnum.STARTED ? '' : ''"
|
||||
:class="
|
||||
state.goodsInfo.stock === 0 || timeStatusEnum !== TimeStatusEnum.STARTED ? '' : ''
|
||||
"
|
||||
>
|
||||
秒杀价
|
||||
</view>
|
||||
@@ -136,11 +137,11 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {reactive, computed, ref} from 'vue';
|
||||
import { reactive, computed, ref, unref } from 'vue';
|
||||
import { onLoad, onPageScroll } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import {isEmpty, min} from 'lodash';
|
||||
import {useDurationTime, formatGoodsSwiper, fen2yuan} from '@/sheep/hooks/useGoods';
|
||||
import { isEmpty, min } from 'lodash-es';
|
||||
import { useDurationTime, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import detailNavbar from './components/detail/detail-navbar.vue';
|
||||
import detailCellSku from './components/detail/detail-cell-sku.vue';
|
||||
import detailTabbar from './components/detail/detail-tabbar.vue';
|
||||
@@ -148,15 +149,13 @@
|
||||
import detailCommentCard from './components/detail/detail-comment-card.vue';
|
||||
import detailContentCard from './components/detail/detail-content-card.vue';
|
||||
import detailProgress from './components/detail/detail-progress.vue';
|
||||
import SeckillApi from "@/sheep/api/promotion/seckill";
|
||||
import SpuApi from "@/sheep/api/product/spu";
|
||||
import {getTimeStatusEnum, TimeStatusEnum} from "@/sheep/util/const";
|
||||
import SeckillApi from '@/sheep/api/promotion/seckill';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
import { getTimeStatusEnum, TimeStatusEnum } from '@/sheep/util/const';
|
||||
|
||||
const headerBg = sheep.$url.css('/static/img/shop/goods/seckill-bg.png');
|
||||
const btnBg = sheep.$url.css('/static/img/shop/goods/seckill-btn.png');
|
||||
const disabledBtnBg = sheep.$url.css(
|
||||
'/static/img/shop/goods/activity-btn-disabled.png',
|
||||
);
|
||||
const disabledBtnBg = sheep.$url.css('/static/img/shop/goods/activity-btn-disabled.png');
|
||||
const seckillBg = sheep.$url.css('/static/img/shop/goods/seckill-tip-bg.png');
|
||||
const grouponBg = sheep.$url.css('/static/img/shop/goods/groupon-tip-bg.png');
|
||||
|
||||
@@ -199,9 +198,9 @@
|
||||
});
|
||||
}
|
||||
|
||||
// 分享信息 TODO 芋艿:待接入
|
||||
// 分享信息
|
||||
const shareInfo = computed(() => {
|
||||
if (isEmpty(activity)) return {};
|
||||
if (isEmpty(unref(activity))) return {};
|
||||
return sheep.$platform.share.getShareInfo(
|
||||
{
|
||||
title: activity.value.name,
|
||||
@@ -221,36 +220,41 @@
|
||||
);
|
||||
});
|
||||
|
||||
const activity = ref()
|
||||
const timeStatusEnum = ref('')
|
||||
const activity = ref();
|
||||
const timeStatusEnum = ref('');
|
||||
|
||||
// 查询活动
|
||||
const getActivity = async (id) => {
|
||||
const { data } = await SeckillApi.getSeckillActivity(id)
|
||||
activity.value = data
|
||||
timeStatusEnum.value = getTimeStatusEnum(activity.startTime, activity.endTime)
|
||||
|
||||
const { data } = await SeckillApi.getSeckillActivity(id);
|
||||
activity.value = data;
|
||||
timeStatusEnum.value = getTimeStatusEnum(activity.value.startTime, activity.value.endTime);
|
||||
state.percent = 100 - (data.stock / data.totalStock) * 100;
|
||||
// 查询商品
|
||||
await getSpu(data.spuId)
|
||||
}
|
||||
await getSpu(data.spuId);
|
||||
};
|
||||
|
||||
// 查询商品
|
||||
const getSpu = async (id) => {
|
||||
const { data } = await SpuApi.getSpuDetail(id)
|
||||
// 模拟
|
||||
data.activity_type = 'seckill'
|
||||
state.goodsInfo = data
|
||||
const { data } = await SpuApi.getSpuDetail(id);
|
||||
data.activity_type = 'seckill';
|
||||
state.goodsInfo = data;
|
||||
// 处理轮播图
|
||||
state.goodsSwiper = formatGoodsSwiper(state.goodsInfo.sliderPicUrls);
|
||||
|
||||
// 默认显示最低价
|
||||
state.goodsInfo.price = min([state.goodsInfo.price, ...activity.value.products.map(spu => spu.seckillPrice)])
|
||||
state.goodsInfo.price = min([
|
||||
state.goodsInfo.price,
|
||||
...activity.value.products.map((spu) => spu.seckillPrice),
|
||||
]);
|
||||
|
||||
// 价格、库存使用活动的
|
||||
data.skus.forEach(sku => {
|
||||
const product = activity.value.products.find(product => product.skuId === sku.id);
|
||||
data.skus.forEach((sku) => {
|
||||
const product = activity.value.products.find((product) => product.skuId === sku.id);
|
||||
if (product) {
|
||||
sku.price = product.seckillPrice;
|
||||
sku.stock = Math.min(sku.stock, product.stock);
|
||||
} else { // 找不到可能是没配置,则不能发起秒杀
|
||||
} else {
|
||||
// 找不到可能是没配置,则不能发起秒杀
|
||||
sku.stock = 0;
|
||||
}
|
||||
// 设置限购数量
|
||||
@@ -264,7 +268,7 @@
|
||||
});
|
||||
|
||||
state.skeletonLoading = false;
|
||||
}
|
||||
};
|
||||
|
||||
onLoad((options) => {
|
||||
// 非法参数
|
||||
@@ -274,7 +278,7 @@
|
||||
}
|
||||
|
||||
// 查询活动
|
||||
getActivity(options.id)
|
||||
getActivity(options.id);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -282,6 +286,7 @@
|
||||
.disabled-btn-box[disabled] {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
background-color: $white;
|
||||
margin: 14rpx 20rpx;
|
||||
@@ -372,6 +377,7 @@
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
|
||||
.countdown-h {
|
||||
font-size: 24rpx;
|
||||
font-family: OPPOSANS;
|
||||
@@ -382,6 +388,7 @@
|
||||
background: rgba(#000000, 0.1);
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
|
||||
.countdown-num {
|
||||
font-size: 24rpx;
|
||||
font-family: OPPOSANS;
|
||||
@@ -465,6 +472,7 @@
|
||||
line-height: normal;
|
||||
border-radius: 0px 40rpx 40rpx 0px;
|
||||
}
|
||||
|
||||
.btn-price {
|
||||
font-family: OPPOSANS;
|
||||
|
||||
@@ -482,6 +490,7 @@
|
||||
line-height: normal;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
|
||||
.no-original {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
+10
-18
@@ -28,12 +28,11 @@
|
||||
style="transform: scale(0.8)" @tap.stop="onSelectSingle(item.id)" />
|
||||
</label>
|
||||
<s-goods-item :title="item.spu.name" :img="item.spu.picUrl || item.goods.image"
|
||||
:price="item.sku.price/100"
|
||||
:price="item.sku.price"
|
||||
:skuText="item.sku.properties.length>1? item.sku.properties.reduce((items2,items)=>items2.valueName+' '+items.valueName):item.sku.properties[0].valueName"
|
||||
priceColor="#FF3000" :titleWidth="400">
|
||||
<template v-if="!state.editMode" v-slot:tool>
|
||||
<su-number-box :min="0" :max="item.sku.stock" :step="1" v-model="item.count"
|
||||
@change="onNumberChange($event, item)"></su-number-box>
|
||||
<su-number-box :min="0" :max="item.sku.stock" :step="1" v-model="item.count" @change="onNumberChange($event, item)" />
|
||||
</template>
|
||||
</s-goods-item>
|
||||
</view>
|
||||
@@ -50,7 +49,7 @@
|
||||
</label>
|
||||
<text>合计:</text>
|
||||
<view class="text-price price-text">
|
||||
{{ state.totalPriceSelected }}
|
||||
{{ fen2yuan(state.totalPriceSelected) }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="footer-right">
|
||||
@@ -72,11 +71,8 @@
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import {
|
||||
computed,
|
||||
reactive,
|
||||
unref
|
||||
} from 'vue';
|
||||
import { computed, reactive } from 'vue';
|
||||
import { fen2yuan } from '../../sheep/hooks/useGoods';
|
||||
|
||||
const sys_navBar = sheep.$platform.navbar;
|
||||
const cart = sheep.$store('cart');
|
||||
@@ -89,12 +85,13 @@
|
||||
isAllSelected: computed(() => cart.isAllSelected),
|
||||
totalPriceSelected: computed(() => cart.totalPriceSelected),
|
||||
});
|
||||
|
||||
// 单选选中
|
||||
function onSelectSingle(id) {
|
||||
console.log('单选')
|
||||
cart.selectSingle(id);
|
||||
}
|
||||
// 全选
|
||||
|
||||
// 全选
|
||||
function onSelectAll() {
|
||||
cart.selectAll(!state.isAllSelected);
|
||||
}
|
||||
@@ -105,12 +102,12 @@
|
||||
let goods_list = [];
|
||||
state.selectedList = state.list.filter((item) => state.selectedIds.includes(item.id));
|
||||
state.selectedList.map((item) => {
|
||||
console.log(item, '便利');
|
||||
// 此处前端做出修改
|
||||
items.push({
|
||||
skuId: item.sku.id,
|
||||
count: item.count,
|
||||
cartId: item.id,
|
||||
categoryId: item.spu.categoryId
|
||||
})
|
||||
goods_list.push({
|
||||
// goods_id: item.goods_id,
|
||||
@@ -128,12 +125,7 @@
|
||||
}
|
||||
sheep.$router.go('/pages/order/confirm', {
|
||||
data: JSON.stringify({
|
||||
// order_type: 'goods',
|
||||
// goods_list,
|
||||
items,
|
||||
// from: 'cart',
|
||||
deliveryType: 1,
|
||||
pointStatus: false,
|
||||
items
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { computed, reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import { handleTree } from '@/sheep/util';
|
||||
|
||||
const state = reactive({
|
||||
@@ -131,12 +131,13 @@
|
||||
getGoodsList();
|
||||
}
|
||||
|
||||
onLoad(async () => {
|
||||
onLoad(async (params) => {
|
||||
await getList();
|
||||
// 如果是 first 风格,需要加载商品分页
|
||||
if (state.style === 'first_one' || state.style === 'first_two') {
|
||||
onMenu(0);
|
||||
}
|
||||
|
||||
// 首页点击分类的处理:查找满足条件的分类
|
||||
const foundCategory = state.categoryList.find(category => category.id === params.id);
|
||||
// 如果找到则调用 onMenu 自动勾选相应分类,否则调用 onMenu(0) 勾选第一个分类
|
||||
onMenu(foundCategory ? state.categoryList.indexOf(foundCategory) : 0);
|
||||
});
|
||||
|
||||
onReachBottom(() => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<template>
|
||||
<view v-if="template">
|
||||
<s-layout title="首页" navbar="custom" tabbar="/pages/index/index" :bgStyle="template.page"
|
||||
:navbarStyle="template.style?.navbar" onShareAppMessage>
|
||||
:navbarStyle="template.navigationBar" onShareAppMessage>
|
||||
<s-block v-for="(item, index) in template.components" :key="index" :styles="item.property.style">
|
||||
<s-block-item :type="item.id" :data="item.property" :styles="item.property.style" />
|
||||
</s-block>
|
||||
@@ -53,6 +53,7 @@
|
||||
// 小程序识别二维码
|
||||
if (options.scene) {
|
||||
const sceneParams = decodeURIComponent(options.scene).split('=');
|
||||
console.log("sceneParams=>",sceneParams);
|
||||
options[sceneParams[0]] = sceneParams[1];
|
||||
}
|
||||
// #endif
|
||||
|
||||
@@ -14,19 +14,20 @@
|
||||
new URLSearchParams(location.search).forEach((value, key) => {
|
||||
options[key] = value;
|
||||
});
|
||||
// 执行登录 or 绑定,注意需要 await 绑定
|
||||
const event = options.event;
|
||||
const code = options.code;
|
||||
const state = options.state;
|
||||
if (event === 'login') { // 场景一:登录
|
||||
const res = await sheep.$platform.useProvider().login(code, state);
|
||||
await sheep.$platform.useProvider().login(code, state);
|
||||
} else if (event === 'bind') { // 场景二:绑定
|
||||
sheep.$platform.useProvider().bind(code, state);
|
||||
await sheep.$platform.useProvider().bind(code, state);
|
||||
}
|
||||
|
||||
// 检测 H5 登录回调
|
||||
let returnUrl = uni.getStorageSync('returnUrl');
|
||||
if (returnUrl) {
|
||||
uni.removeStorage('returnUrl');
|
||||
uni.removeStorage({key:'returnUrl'});
|
||||
location.replace(returnUrl);
|
||||
} else {
|
||||
uni.switchTab({
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
tabbar="/pages/index/user"
|
||||
navbar="custom"
|
||||
:bgStyle="template.page"
|
||||
:navbarStyle="template.style?.navbar"
|
||||
:navbarStyle="template.navigationBar"
|
||||
onShareAppMessage
|
||||
>
|
||||
<s-block v-for="(item, index) in template.components" :key="index" :styles="item.property.style">
|
||||
|
||||
@@ -0,0 +1,278 @@
|
||||
<!-- 下单界面,收货地址 or 自提门店的选择组件 -->
|
||||
<template>
|
||||
<view class="allAddress" :style="state.isPickUp ? '' : 'padding-top:10rpx;'">
|
||||
<view class="nav flex flex-wrap">
|
||||
<view
|
||||
class="item font-color"
|
||||
:class="state.deliveryType === 1 ? 'on' : 'on2'"
|
||||
@tap="switchDeliveryType(1)"
|
||||
v-if="state.isPickUp"
|
||||
/>
|
||||
<view
|
||||
class="item font-color"
|
||||
:class="state.deliveryType === 2 ? 'on' : 'on2'"
|
||||
@tap="switchDeliveryType(2)"
|
||||
v-if="state.isPickUp"
|
||||
/>
|
||||
</view>
|
||||
<!-- 情况一:收货地址的选择 -->
|
||||
<view
|
||||
class="address flex flex-wrap flex-center ss-row-between"
|
||||
@tap="onSelectAddress"
|
||||
v-if="state.deliveryType === 1"
|
||||
:style="state.isPickUp ? '' : 'border-top-left-radius: 14rpx;border-top-right-radius: 14rpx;'"
|
||||
>
|
||||
<view class="addressCon" v-if="state.addressInfo.name">
|
||||
<view class="name"
|
||||
>{{ state.addressInfo.name }}
|
||||
<text class="phone">{{ state.addressInfo.mobile }}</text>
|
||||
</view>
|
||||
<view class="flex flex-wrap">
|
||||
<text class="default font-color" v-if="state.addressInfo.defaultStatus">[默认]</text>
|
||||
<text class="line2"
|
||||
>{{ state.addressInfo.areaName }} {{ state.addressInfo.detailAddress }}</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
<view class="addressCon" v-else>
|
||||
<view class="setaddress">设置收货地址</view>
|
||||
</view>
|
||||
<view class="iconfont">
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 情况二:门店的选择 -->
|
||||
<view class="address flex flex-wrap flex-center ss-row-between" v-else @tap="onSelectAddress">
|
||||
<view class="addressCon" v-if="state.pickUpInfo.name">
|
||||
<view class="name"
|
||||
>{{ state.pickUpInfo.name }}
|
||||
<text class="phone">{{ state.pickUpInfo.phone }}</text>
|
||||
</view>
|
||||
<view class="line1">
|
||||
{{ state.pickUpInfo.areaName }}{{ ', ' + state.pickUpInfo.detailAddress }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="addressCon" v-else>
|
||||
<view class="setaddress">选择自提门店</view>
|
||||
</view>
|
||||
<view class="iconfont">
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="line">
|
||||
<image :src="sheep.$url.static('/static/images/line.png', 'local')" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(['update:modelValue']);
|
||||
|
||||
// computed 解决父子组件双向数据同步
|
||||
const state = computed({
|
||||
get() {
|
||||
return new Proxy(props.modelValue, {
|
||||
set(obj, name, val) {
|
||||
emits('update:modelValue', {
|
||||
...obj,
|
||||
[name]: val,
|
||||
});
|
||||
return true;
|
||||
},
|
||||
});
|
||||
},
|
||||
set(val) {
|
||||
emits('update:modelValue', val);
|
||||
},
|
||||
});
|
||||
|
||||
// 选择地址
|
||||
function onSelectAddress() {
|
||||
let emitName = 'SELECT_ADDRESS';
|
||||
let addressPage = '/pages/user/address/list?type=select';
|
||||
if (state.value.deliveryType === 2) {
|
||||
emitName = 'SELECT_PICK_UP_INFO';
|
||||
addressPage = '/pages/user/goods_details_store/index';
|
||||
}
|
||||
uni.$once(emitName, (e) => {
|
||||
changeConsignee(e.addressInfo);
|
||||
});
|
||||
sheep.$router.go(addressPage);
|
||||
}
|
||||
|
||||
// 更改收货人地址&计算订单信息
|
||||
async function changeConsignee(addressInfo = {}) {
|
||||
if (!isEmpty(addressInfo)) {
|
||||
if (state.value.deliveryType === 1) {
|
||||
state.value.addressInfo = addressInfo;
|
||||
}
|
||||
if (state.value.deliveryType === 2) {
|
||||
state.value.pickUpInfo = addressInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 收货方式切换
|
||||
const switchDeliveryType = (type) => {
|
||||
state.value.deliveryType = type;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.allAddress .font-color {
|
||||
color: #e93323 !important;
|
||||
}
|
||||
.line2 {
|
||||
width: 504rpx;
|
||||
}
|
||||
.textR {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 100%;
|
||||
height: 3rpx;
|
||||
}
|
||||
|
||||
.line image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.address {
|
||||
padding: 28rpx;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.address .addressCon {
|
||||
width: 596rpx;
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.address .addressCon .name {
|
||||
font-size: 30rpx;
|
||||
color: #282828;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.address .addressCon .name .phone {
|
||||
margin-left: 50rpx;
|
||||
}
|
||||
|
||||
.address .addressCon .default {
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.address .addressCon .setaddress {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.address .iconfont {
|
||||
font-size: 35rpx;
|
||||
color: #707070;
|
||||
}
|
||||
|
||||
.allAddress {
|
||||
width: 100%;
|
||||
background: linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
|
||||
// background-image: linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
|
||||
// background-image: -webkit-linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
|
||||
// background-image: -moz-linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
|
||||
//padding: 100rpx 30rpx 0 30rpx;
|
||||
padding-top: 100rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav {
|
||||
width: 690rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.allAddress .nav .item {
|
||||
width: 334rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav .item.on {
|
||||
position: relative;
|
||||
width: 230rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav .item.on::before {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
content: '快递配送';
|
||||
font-size: 28rpx;
|
||||
display: block;
|
||||
height: 0;
|
||||
width: 336rpx;
|
||||
border-width: 0 20rpx 80rpx 0;
|
||||
border-style: none solid solid;
|
||||
border-color: transparent transparent #fff;
|
||||
z-index: 2;
|
||||
border-radius: 14rpx 36rpx 0 0;
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav .item:nth-of-type(2).on::before {
|
||||
content: '到店自提';
|
||||
border-width: 0 0 80rpx 20rpx;
|
||||
border-radius: 36rpx 14rpx 0 0;
|
||||
}
|
||||
|
||||
.allAddress .nav .item.on2 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.allAddress .nav .item.on2::before {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
content: '到店自提';
|
||||
font-size: 28rpx;
|
||||
display: block;
|
||||
height: 0;
|
||||
width: 401rpx;
|
||||
border-width: 0 0 60rpx 60rpx;
|
||||
border-style: none solid solid;
|
||||
border-color: transparent transparent #f7c1bd;
|
||||
border-radius: 36rpx 14rpx 0 0;
|
||||
text-align: center;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav .item:nth-of-type(1).on2::before {
|
||||
content: '快递配送';
|
||||
border-width: 0 60rpx 60rpx 0;
|
||||
border-radius: 14rpx 36rpx 0 0;
|
||||
}
|
||||
|
||||
.allAddress .address {
|
||||
width: 690rpx;
|
||||
max-height: 180rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.allAddress .line {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
@@ -98,11 +98,7 @@
|
||||
</view>
|
||||
<view class="modal-content content_box">
|
||||
<radio-group @change="onChange">
|
||||
<label
|
||||
class="radio ss-flex ss-col-center"
|
||||
v-for="item in state.reasonList"
|
||||
:key="item"
|
||||
>
|
||||
<label class="radio ss-flex ss-col-center" v-for="item in state.reasonList" :key="item">
|
||||
<view class="ss-flex-1 ss-p-20">{{ item }}</view>
|
||||
<radio
|
||||
:value="item"
|
||||
@@ -130,6 +126,7 @@
|
||||
import TradeConfigApi from '@/sheep/api/trade/config';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
import { WxaSubscribeTemplate } from '@/sheep/util/const';
|
||||
|
||||
const form = ref(null);
|
||||
const state = reactive({
|
||||
@@ -152,9 +149,9 @@
|
||||
],
|
||||
reasonList: [], // 可选的申请原因数组
|
||||
showModal: false, // 是否显示申请原因弹窗
|
||||
currentValue: '' // 当前选择的售后原因
|
||||
currentValue: '', // 当前选择的售后原因
|
||||
});
|
||||
const formData = reactive({
|
||||
let formData = reactive({
|
||||
way: '',
|
||||
applyReason: '',
|
||||
applyDescription: '',
|
||||
@@ -164,9 +161,6 @@
|
||||
|
||||
// 提交表单
|
||||
async function submit() {
|
||||
// #ifdef MP
|
||||
sheep.$platform.useProvider('wechat').subscribeMessage('order_aftersale_change');
|
||||
// #endif
|
||||
let data = {
|
||||
orderItemId: state.itemId,
|
||||
refundPrice: state.item.payPrice,
|
||||
@@ -177,7 +171,7 @@
|
||||
uni.showToast({
|
||||
title: '申请成功',
|
||||
});
|
||||
sheep.$router.go('/pages/order/aftersale/list');
|
||||
sheep.$router.redirect('/pages/order/aftersale/list');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +208,7 @@
|
||||
state.itemId = parseInt(options.itemId);
|
||||
|
||||
// 读取订单信息
|
||||
const { code, data } = await OrderApi.getOrder(state.orderId);
|
||||
const { code, data } = await OrderApi.getOrderDetail(state.orderId);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
+286
-249
@@ -1,156 +1,193 @@
|
||||
<!-- 售后详情 -->
|
||||
<template>
|
||||
<s-layout title="售后详情" :navbar="!isEmpty(state.info) && state.loading ? 'inner' : 'normal'">
|
||||
<view class="content_box" v-if="!isEmpty(state.info) && state.loading">
|
||||
<!-- 步骤条 -->
|
||||
<view class="steps-box ss-flex" :style="[
|
||||
<s-layout title="售后详情" :navbar="!isEmpty(state.info) && state.loading ? 'inner' : 'normal'">
|
||||
<view class="content_box" v-if="!isEmpty(state.info) && state.loading">
|
||||
<!-- 步骤条 -->
|
||||
<view
|
||||
class="steps-box ss-flex"
|
||||
:style="[
|
||||
{
|
||||
marginTop: '-' + Number(statusBarHeight + 88) + 'rpx',
|
||||
paddingTop: Number(statusBarHeight + 88) + 'rpx',
|
||||
},
|
||||
]">
|
||||
<view class="ss-flex">
|
||||
<view class="steps-item" v-for="(item, index) in state.list" :key="index">
|
||||
<view class="ss-flex">
|
||||
<text class="sicon-circleclose"
|
||||
v-if="state.list.length - 1 === index && [61, 62, 63].includes(state.info.status)" />
|
||||
<text class="sicon-circlecheck" v-else
|
||||
:class="state.active >= index ? 'activity-color' : 'info-color'" />
|
||||
]"
|
||||
>
|
||||
<view class="ss-flex">
|
||||
<view class="steps-item" v-for="(item, index) in state.list" :key="index">
|
||||
<view class="ss-flex">
|
||||
<text
|
||||
class="sicon-circleclose"
|
||||
v-if="state.list.length - 1 === index && [61, 62, 63].includes(state.info.status)"
|
||||
/>
|
||||
<text
|
||||
class="sicon-circlecheck"
|
||||
v-else
|
||||
:class="state.active >= index ? 'activity-color' : 'info-color'"
|
||||
/>
|
||||
|
||||
<view v-if="state.list.length - 1 !== index" class="line"
|
||||
:class="state.active >= index ? 'activity-bg' : 'info-bg'" />
|
||||
</view>
|
||||
<view class="steps-item-title" :class="state.active >= index ? 'activity-color' : 'info-color'">
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
v-if="state.list.length - 1 !== index"
|
||||
class="line"
|
||||
:class="state.active >= index ? 'activity-bg' : 'info-bg'"
|
||||
/>
|
||||
</view>
|
||||
<view
|
||||
class="steps-item-title"
|
||||
:class="state.active >= index ? 'activity-color' : 'info-color'"
|
||||
>
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 服务状态 -->
|
||||
<view class="status-box ss-flex ss-col-center ss-row-between ss-m-x-20"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/log', { id: state.id })">
|
||||
<view class="">
|
||||
<view class="status-text">
|
||||
<!-- 服务状态 -->
|
||||
<view
|
||||
class="status-box ss-flex ss-col-center ss-row-between ss-m-x-20"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/log', { id: state.id })"
|
||||
>
|
||||
<view class="">
|
||||
<view class="status-text">
|
||||
{{ formatAfterSaleStatusDescription(state.info) }}
|
||||
</view>
|
||||
<view class="status-time">
|
||||
<view class="status-time">
|
||||
{{ sheep.$helper.timeFormat(state.info.updateTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</view>
|
||||
</view>
|
||||
<text class="ss-iconfont _icon-forward" style="color: #666" />
|
||||
</view>
|
||||
</view>
|
||||
<text class="ss-iconfont _icon-forward" style="color: #666" />
|
||||
</view>
|
||||
|
||||
<!-- 退款金额 -->
|
||||
<view class="aftersale-money ss-flex ss-col-center ss-row-between">
|
||||
<view class="aftersale-money--title">退款总额</view>
|
||||
<view class="aftersale-money--num">¥{{ fen2yuan(state.info.refundPrice) }}</view>
|
||||
</view>
|
||||
<!-- 服务商品 -->
|
||||
<view class="order-shop">
|
||||
<s-goods-item
|
||||
:img=" state.info.picUrl"
|
||||
:title=" state.info.spuName"
|
||||
:titleWidth="480"
|
||||
<!-- 退款金额 -->
|
||||
<view class="aftersale-money ss-flex ss-col-center ss-row-between">
|
||||
<view class="aftersale-money--title">退款总额</view>
|
||||
<view class="aftersale-money--num">¥{{ fen2yuan(state.info.refundPrice) }}</view>
|
||||
</view>
|
||||
<!-- 服务商品 -->
|
||||
<view class="order-shop">
|
||||
<s-goods-item
|
||||
:img="state.info.picUrl"
|
||||
:title="state.info.spuName"
|
||||
:titleWidth="480"
|
||||
:skuText="state.info.properties.map((property) => property.valueName).join(' ')"
|
||||
:num=" state.info.count"
|
||||
:num="state.info.count"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 服务内容 -->
|
||||
<view class="aftersale-content">
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">服务单号:</view>
|
||||
<view class="item-content ss-m-r-16">{{ state.info.no }}</view>
|
||||
<button class="ss-reset-button copy-btn" @tap="onCopy">复制</button>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">申请时间:</view>
|
||||
<view class="item-content">
|
||||
{{ sheep.$helper.timeFormat(state.info.createTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">售后类型:</view>
|
||||
<view class="item-content">{{ state.info.way === 10 ? '仅退款' : '退款退货' }}</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">申请原因:</view>
|
||||
<view class="item-content">{{ state.info.applyReason }}</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">相关描述:</view>
|
||||
<view class="item-content">{{ state.info.applyDescription }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 服务内容 -->
|
||||
<view class="aftersale-content">
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">服务单号:</view>
|
||||
<view class="item-content ss-m-r-16">{{ state.info.no }}</view>
|
||||
<button class="ss-reset-button copy-btn" @tap="onCopy">复制</button>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">申请时间:</view>
|
||||
<view class="item-content">
|
||||
{{ sheep.$helper.timeFormat(state.info.createTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">售后类型:</view>
|
||||
<view class="item-content">{{ state.info.way === 10 ? '仅退款' : '退款退货' }}</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">申请原因:</view>
|
||||
<view class="item-content">{{ state.info.applyReason }}</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">相关描述:</view>
|
||||
<view class="item-content">{{ state.info.applyDescription }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作区 -->
|
||||
<s-empty v-if="isEmpty(state.info) && state.loading" icon="/static/order-empty.png" text="暂无该订单售后详情" />
|
||||
<su-fixed bottom placeholder bg="bg-white" v-if="!isEmpty(state.info)">
|
||||
<view class="foot_box">
|
||||
<button class="ss-reset-button btn" v-if="state.info.buttons?.includes('cancel')"
|
||||
@tap="onApply(state.info.id)">
|
||||
<s-empty
|
||||
v-if="isEmpty(state.info) && state.loading"
|
||||
icon="/static/order-empty.png"
|
||||
text="暂无该订单售后详情"
|
||||
/>
|
||||
<su-fixed bottom placeholder bg="bg-white" v-if="!isEmpty(state.info)">
|
||||
<view class="foot_box">
|
||||
<button
|
||||
class="ss-reset-button btn"
|
||||
v-if="state.info.buttons?.includes('cancel')"
|
||||
@tap="onApply(state.info.id)"
|
||||
>
|
||||
取消申请
|
||||
</button>
|
||||
<button class="ss-reset-button btn" v-if="state.info.buttons?.includes('delivery')"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/return-delivery', { id: state.info.id })">
|
||||
<button
|
||||
class="ss-reset-button btn"
|
||||
v-if="state.info.buttons?.includes('delivery')"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/return-delivery', { id: state.info.id })"
|
||||
>
|
||||
填写退货
|
||||
</button>
|
||||
<button class="ss-reset-button contcat-btn btn" @tap="sheep.$router.go('/pages/chat/index')">
|
||||
<button
|
||||
class="ss-reset-button contcat-btn btn"
|
||||
@tap="sheep.$router.go('/pages/chat/index')"
|
||||
>
|
||||
联系客服
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { fen2yuan, formatAfterSaleStatusDescription, handleAfterSaleButtons } from '@/sheep/hooks/useGoods';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatAfterSaleStatusDescription,
|
||||
handleAfterSaleButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
|
||||
const state = reactive({
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
|
||||
const state = reactive({
|
||||
id: 0, // 售后编号
|
||||
info: {}, // 收货信息
|
||||
loading: false,
|
||||
loading: false,
|
||||
active: 0, // 在 list 的激活位置
|
||||
list: [{
|
||||
title: '提交申请',
|
||||
}, {
|
||||
title: '处理中',
|
||||
}, {
|
||||
title: '完成'
|
||||
}], // 时间轴
|
||||
});
|
||||
list: [
|
||||
{
|
||||
title: '提交申请',
|
||||
},
|
||||
{
|
||||
title: '处理中',
|
||||
},
|
||||
{
|
||||
title: '完成',
|
||||
},
|
||||
], // 时间轴
|
||||
});
|
||||
|
||||
function onApply(id) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消此申请吗?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
function onApply(id) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消此申请吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await AfterSaleApi.cancelAfterSale(id);
|
||||
if (code === 0) {
|
||||
await getDetail(id);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 复制
|
||||
const onCopy = () => {
|
||||
sheep.$helper.copyText(state.info.no);
|
||||
};
|
||||
sheep.$helper.copyText(state.info.no);
|
||||
};
|
||||
|
||||
async function getDetail(id) {
|
||||
async function getDetail(id) {
|
||||
state.loading = true;
|
||||
const { code, data } = await AfterSaleApi.getAfterSale(id);
|
||||
if (code !== 0) {
|
||||
@@ -170,173 +207,173 @@
|
||||
} else if ([61, 62, 63].includes(state.info.status)) {
|
||||
state.active = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
onLoad((options) => {
|
||||
if (!options.id) {
|
||||
sheep.$helper.toast(`缺少订单信息,请检查`);
|
||||
return
|
||||
return;
|
||||
}
|
||||
state.id = options.id;
|
||||
getDetail(options.id);
|
||||
});
|
||||
state.id = options.id;
|
||||
getDetail(options.id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 步骤条
|
||||
.steps-box {
|
||||
width: 100%;
|
||||
height: 190rpx;
|
||||
background: v-bind(headerBg) no-repeat,
|
||||
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
background-size: 750rpx 100%;
|
||||
padding-left: 72rpx;
|
||||
// 步骤条
|
||||
.steps-box {
|
||||
width: 100%;
|
||||
height: 190rpx;
|
||||
background: v-bind(headerBg) no-repeat,
|
||||
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
background-size: 750rpx 100%;
|
||||
padding-left: 72rpx;
|
||||
|
||||
.steps-item {
|
||||
.sicon-circleclose {
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
}
|
||||
.steps-item {
|
||||
.sicon-circleclose {
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sicon-circlecheck {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.sicon-circlecheck {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.steps-item-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
margin-top: 16rpx;
|
||||
margin-left: -36rpx;
|
||||
width: 100rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.steps-item-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
margin-top: 16rpx;
|
||||
margin-left: -36rpx;
|
||||
width: 100rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.activity-color {
|
||||
color: #fff;
|
||||
}
|
||||
.activity-color {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.info-color {
|
||||
color: rgba(#fff, 0.4);
|
||||
}
|
||||
.info-color {
|
||||
color: rgba(#fff, 0.4);
|
||||
}
|
||||
|
||||
.activity-bg {
|
||||
background: #fff;
|
||||
}
|
||||
.activity-bg {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.info-bg {
|
||||
background: rgba(#fff, 0.4);
|
||||
}
|
||||
.info-bg {
|
||||
background: rgba(#fff, 0.4);
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 270rpx;
|
||||
height: 4rpx;
|
||||
}
|
||||
.line {
|
||||
width: 270rpx;
|
||||
height: 4rpx;
|
||||
}
|
||||
|
||||
// 服务状态
|
||||
.status-box {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx 20rpx 0px 0px;
|
||||
padding: 20rpx;
|
||||
margin-top: -20rpx;
|
||||
// 服务状态
|
||||
.status-box {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx 20rpx 0px 0px;
|
||||
padding: 20rpx;
|
||||
margin-top: -20rpx;
|
||||
|
||||
.status-text {
|
||||
font-size: 28rpx;
|
||||
.status-text {
|
||||
font-size: 28rpx;
|
||||
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.status-time {
|
||||
font-size: 24rpx;
|
||||
.status-time {
|
||||
font-size: 24rpx;
|
||||
|
||||
font-weight: 400;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
}
|
||||
}
|
||||
font-weight: 400;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 退款金额
|
||||
.aftersale-money {
|
||||
background-color: #fff;
|
||||
height: 98rpx;
|
||||
padding: 0 20rpx;
|
||||
margin: 20rpx;
|
||||
// 退款金额
|
||||
.aftersale-money {
|
||||
background-color: #fff;
|
||||
height: 98rpx;
|
||||
padding: 0 20rpx;
|
||||
margin: 20rpx;
|
||||
|
||||
.aftersale-money--title {
|
||||
font-size: 28rpx;
|
||||
.aftersale-money--title {
|
||||
font-size: 28rpx;
|
||||
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
|
||||
.aftersale-money--num {
|
||||
font-size: 28rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 500;
|
||||
color: #ff3000;
|
||||
}
|
||||
}
|
||||
.aftersale-money--num {
|
||||
font-size: 28rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 500;
|
||||
color: #ff3000;
|
||||
}
|
||||
}
|
||||
|
||||
// order-shop
|
||||
.order-shop {
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
}
|
||||
// order-shop
|
||||
.order-shop {
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
}
|
||||
|
||||
// 服务内容
|
||||
.aftersale-content {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
margin: 0 20rpx;
|
||||
// 服务内容
|
||||
.aftersale-content {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
margin: 0 20rpx;
|
||||
|
||||
.aftersale-item {
|
||||
height: 60rpx;
|
||||
.aftersale-item {
|
||||
height: 60rpx;
|
||||
|
||||
.copy-btn {
|
||||
background: #eeeeee;
|
||||
color: #333;
|
||||
border-radius: 20rpx;
|
||||
width: 75rpx;
|
||||
height: 40rpx;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
.copy-btn {
|
||||
background: #eeeeee;
|
||||
color: #333;
|
||||
border-radius: 20rpx;
|
||||
width: 75rpx;
|
||||
height: 40rpx;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.item-title {
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item-content {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部功能
|
||||
.foot_box {
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
// 底部功能
|
||||
.foot_box {
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
|
||||
.btn {
|
||||
width: 160rpx;
|
||||
line-height: 60rpx;
|
||||
background: rgba(238, 238, 238, 1);
|
||||
border-radius: 30rpx;
|
||||
padding: 0;
|
||||
margin-right: 20rpx;
|
||||
font-size: 26rpx;
|
||||
.btn {
|
||||
width: 160rpx;
|
||||
line-height: 60rpx;
|
||||
background: rgba(238, 238, 238, 1);
|
||||
border-radius: 30rpx;
|
||||
padding: 0;
|
||||
margin-right: 20rpx;
|
||||
font-size: 26rpx;
|
||||
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+162
-145
@@ -1,193 +1,210 @@
|
||||
<!-- 售后列表 -->
|
||||
<template>
|
||||
<s-layout title="售后列表">
|
||||
<!-- tab -->
|
||||
<su-sticky bgColor="#fff">
|
||||
<su-tabs :list="tabMaps" :scrollable="false" @change="onTabsChange" :current="state.currentTab" />
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据" />
|
||||
<!-- 列表 -->
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view class="list-box ss-m-y-20" v-for="order in state.pagination.list" :key="order.id"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/detail', { id: order.id })">
|
||||
<view class="order-head ss-flex ss-col-center ss-row-between">
|
||||
<text class="no">服务单号:{{ order.no }}</text>
|
||||
<text class="state">{{ formatAfterSaleStatus(order) }}</text>
|
||||
</view>
|
||||
<s-goods-item
|
||||
<s-layout title="售后列表">
|
||||
<!-- tab -->
|
||||
<su-sticky bgColor="#fff">
|
||||
<su-tabs
|
||||
:list="tabMaps"
|
||||
:scrollable="false"
|
||||
@change="onTabsChange"
|
||||
:current="state.currentTab"
|
||||
/>
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据" />
|
||||
<!-- 列表 -->
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view
|
||||
class="list-box ss-m-y-20"
|
||||
v-for="order in state.pagination.list"
|
||||
:key="order.id"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/detail', { id: order.id })"
|
||||
>
|
||||
<view class="order-head ss-flex ss-col-center ss-row-between">
|
||||
<text class="no">服务单号:{{ order.no }}</text>
|
||||
<text class="state">{{ formatAfterSaleStatus(order) }}</text>
|
||||
</view>
|
||||
<s-goods-item
|
||||
:img="order.picUrl"
|
||||
:title="order.spuName"
|
||||
:skuText="order.properties.map((property) => property.valueName).join(' ')"
|
||||
:skuText="order.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="order.refundPrice"
|
||||
/>
|
||||
<view class="apply-box ss-flex ss-col-center ss-row-between border-bottom ss-p-x-20">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="title ss-m-r-20">{{ order.way === 10 ? '仅退款' : '退款退货' }}</view>
|
||||
<view class="value">{{ formatAfterSaleStatusDescription(order) }}</view>
|
||||
</view>
|
||||
<text class="_icon-forward"></text>
|
||||
</view>
|
||||
<view class="tool-btn-box ss-flex ss-col-center ss-row-right ss-p-r-20">
|
||||
<view class="apply-box ss-flex ss-col-center ss-row-between border-bottom ss-p-x-20">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="title ss-m-r-20">{{ order.way === 10 ? '仅退款' : '退款退货' }}</view>
|
||||
<view class="value">{{ formatAfterSaleStatusDescription(order) }}</view>
|
||||
</view>
|
||||
<text class="_icon-forward"></text>
|
||||
</view>
|
||||
<view class="tool-btn-box ss-flex ss-col-center ss-row-right ss-p-r-20">
|
||||
<!-- TODO 功能缺失:填写退货信息 -->
|
||||
<view>
|
||||
<button class="ss-reset-button tool-btn" @tap.stop="onApply(order.id)"
|
||||
v-if="order?.buttons.includes('cancel')">取消申请</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
|
||||
<view>
|
||||
<button
|
||||
class="ss-reset-button tool-btn"
|
||||
@tap.stop="onApply(order.id)"
|
||||
v-if="order?.buttons.includes('cancel')"
|
||||
>取消申请</button
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}" @tap="loadMore" />
|
||||
</s-layout>
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import { formatAfterSaleStatus, formatAfterSaleStatusDescription, handleAfterSaleButtons } from '@/sheep/hooks/useGoods';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash-es';
|
||||
import {
|
||||
formatAfterSaleStatus,
|
||||
formatAfterSaleStatusDescription,
|
||||
handleAfterSaleButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
const paginationNull = {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
};
|
||||
|
||||
const state = reactive({
|
||||
currentTab: 0,
|
||||
showApply: false,
|
||||
pagination: {
|
||||
const state = reactive({
|
||||
currentTab: 0,
|
||||
showApply: false,
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
pageSize: 10,
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
|
||||
// TODO 芋艿:优化点,增加筛选
|
||||
const tabMaps = [{
|
||||
name: '全部',
|
||||
value: 'all',
|
||||
},
|
||||
// {
|
||||
// name: '申请中',
|
||||
// value: 'nooper',
|
||||
// },
|
||||
// {
|
||||
// name: '处理中',
|
||||
// value: 'ing',
|
||||
// },
|
||||
// {
|
||||
// name: '已完成',
|
||||
// value: 'completed',
|
||||
// },
|
||||
// {
|
||||
// name: '已拒绝',
|
||||
// value: 'refuse',
|
||||
// },
|
||||
];
|
||||
const tabMaps = [
|
||||
{
|
||||
name: '全部',
|
||||
value: 'all',
|
||||
},
|
||||
// {
|
||||
// name: '申请中',
|
||||
// value: 'nooper',
|
||||
// },
|
||||
// {
|
||||
// name: '处理中',
|
||||
// value: 'ing',
|
||||
// },
|
||||
// {
|
||||
// name: '已完成',
|
||||
// value: 'completed',
|
||||
// },
|
||||
// {
|
||||
// name: '已拒绝',
|
||||
// value: 'refuse',
|
||||
// },
|
||||
];
|
||||
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
state.pagination = paginationNull
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
resetPagination(state.pagination);
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 获取售后列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { data, code } = await AfterSaleApi.getAfterSalePage({
|
||||
// type: tabMaps[state.currentTab].value,
|
||||
// 获取售后列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { data, code } = await AfterSaleApi.getAfterSalePage({
|
||||
// type: tabMaps[state.currentTab].value,
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
});
|
||||
if (code !== 0) {
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
data.list.forEach(order => handleAfterSaleButtons(order));
|
||||
}
|
||||
data.list.forEach((order) => handleAfterSaleButtons(order));
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
}
|
||||
|
||||
function onApply(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消此申请吗?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
function onApply(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消此申请吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const { code } = await AfterSaleApi.cancelAfterSale(orderId);
|
||||
if (code === 0) {
|
||||
state.pagination = paginationNull
|
||||
resetPagination(state.pagination);
|
||||
await getOrderList();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getOrderList();
|
||||
}
|
||||
}
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list-box {
|
||||
background-color: #fff;
|
||||
.list-box {
|
||||
background-color: #fff;
|
||||
|
||||
.order-head {
|
||||
padding: 0 25rpx;
|
||||
height: 77rpx;
|
||||
}
|
||||
.order-head {
|
||||
padding: 0 25rpx;
|
||||
height: 77rpx;
|
||||
}
|
||||
|
||||
.apply-box {
|
||||
height: 82rpx;
|
||||
.apply-box {
|
||||
height: 82rpx;
|
||||
|
||||
.title {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.title {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 22rpx;
|
||||
color: $dark-6;
|
||||
}
|
||||
}
|
||||
.value {
|
||||
font-size: 22rpx;
|
||||
color: $dark-6;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-btn-box {
|
||||
height: 100rpx;
|
||||
.tool-btn-box {
|
||||
height: 100rpx;
|
||||
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
border-radius: 30rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
border-radius: 30rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -6,14 +6,15 @@
|
||||
<view class='list borRadius14'>
|
||||
<view class='item acea-row row-between-wrapper' style="display: flex;align-items: center;">
|
||||
<view>物流公司</view>
|
||||
<picker mode='selector' class='num' @change="bindPickerChange" :value="state.expressIndex"
|
||||
:range="state.expresses" range-key="name">
|
||||
<view class="picker acea-row row-between-wrapper">
|
||||
<view class='reason'>{{ state.expresses[state.expressIndex].name }}</view>
|
||||
<!-- TODO 芋艿:这里样式有问题,少了 > 按钮 -->
|
||||
<text class='iconfont icon-jiantou' />
|
||||
</view>
|
||||
</picker>
|
||||
<view v-if="state.expresses.length>0" style="flex:1">
|
||||
<picker mode='selector' class='num' @change="bindPickerChange" :value="state.expressIndex"
|
||||
:range="state.expresses" range-key="name">
|
||||
<view class="picker acea-row row-between-wrapper" style="display: flex;justify-content: space-between;">
|
||||
<view class='reason'>{{ state.expresses[state.expressIndex].name }}</view>
|
||||
<text class='iconfont _icon-forward' />
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class='item textarea acea-row row-between' style="display: flex;align-items: center;">
|
||||
<view>物流单号</view>
|
||||
|
||||
+178
-65
@@ -1,13 +1,7 @@
|
||||
<template>
|
||||
<s-layout title="确认订单">
|
||||
<!-- TODO:这个判断先删除 v-if="state.orderInfo.need_address === 1" -->
|
||||
<view class="bg-white address-box ss-m-b-14 ss-r-b-10" @tap="onSelectAddress">
|
||||
<s-address-item :item="state.addressInfo" :hasBorderBottom="false">
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</s-address-item>
|
||||
</view>
|
||||
<!-- 头部地址选择【配送地址】【自提地址】 -->
|
||||
<AddressSelection v-model="addressState" />
|
||||
|
||||
<!-- 商品信息 -->
|
||||
<view class="order-card-box ss-m-b-14">
|
||||
@@ -46,26 +40,89 @@
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- TODO 芋艿:接入积分 -->
|
||||
<view
|
||||
v-if="state.orderPayload.pointActivityId"
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderPayload.order_type === 'score'"
|
||||
>
|
||||
<view class="item-title">扣除积分</view>
|
||||
<view class="item-title">兑换积分</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<image
|
||||
:src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
|
||||
class="score-img"
|
||||
/>
|
||||
<text class="item-value ss-m-r-24">{{ state.orderInfo.score_amount }}</text>
|
||||
<text class="item-value ss-m-r-24">
|
||||
{{ state.orderInfo.usePoint }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between">
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.type === 0 || state.orderPayload.pointActivityId"
|
||||
>
|
||||
<view class="item-title">积分抵扣</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
{{ state.pointStatus || state.orderPayload.pointActivityId ? '剩余积分' : '当前积分' }}
|
||||
<image
|
||||
:src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
|
||||
class="score-img"
|
||||
/>
|
||||
<text class="item-value ss-m-r-24">
|
||||
{{
|
||||
state.pointStatus || state.orderPayload.pointActivityId
|
||||
? state.orderInfo.totalPoint - state.orderInfo.usePoint
|
||||
: state.orderInfo.totalPoint || 0
|
||||
}}
|
||||
</text>
|
||||
<checkbox-group @change="changeIntegral" v-if="!state.orderPayload.pointActivityId">
|
||||
<checkbox
|
||||
:checked="state.pointStatus"
|
||||
:disabled="!state.orderInfo.totalPoint || state.orderInfo.totalPoint <= 0"
|
||||
/>
|
||||
</checkbox-group>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 快递配置时,信息的展示 -->
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="addressState.deliveryType === 1"
|
||||
>
|
||||
<view class="item-title">运费</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value ss-m-r-24">
|
||||
<text class="item-value ss-m-r-24" v-if="state.orderInfo.price.deliveryPrice > 0">
|
||||
+¥{{ fen2yuan(state.orderInfo.price.deliveryPrice) }}
|
||||
</text>
|
||||
<view class="item-value ss-m-r-24" v-else>免运费</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 门店自提时,需要填写姓名和手机号 -->
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="addressState.deliveryType === 2"
|
||||
>
|
||||
<view class="item-title">联系人</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="请填写您的联系姓名"
|
||||
v-model="addressState.receiverName"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="addressState.deliveryType === 2"
|
||||
>
|
||||
<view class="item-title">联系电话</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="请填写您的联系电话"
|
||||
v-model="addressState.receiverMobile"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 优惠劵:只有 type = 0 普通订单(非拼团、秒杀、砍价),才可以使用优惠劵 -->
|
||||
@@ -80,11 +137,17 @@
|
||||
</text>
|
||||
<text
|
||||
class="item-value"
|
||||
:class="state.couponInfo.length > 0 ? 'text-red' : 'text-disabled'"
|
||||
:class="
|
||||
state.couponInfo.filter((coupon) => coupon.match).length > 0
|
||||
? 'text-red'
|
||||
: 'text-disabled'
|
||||
"
|
||||
v-else
|
||||
>
|
||||
{{
|
||||
state.couponInfo.length > 0 ? state.couponInfo.length + ' 张可用' : '暂无可用优惠券'
|
||||
state.couponInfo.filter((coupon) => coupon.match).length > 0
|
||||
? state.couponInfo.filter((coupon) => coupon.match).length + ' 张可用'
|
||||
: '暂无可用优惠券'
|
||||
}}
|
||||
</text>
|
||||
<text class="_icon-forward item-icon" />
|
||||
@@ -95,21 +158,31 @@
|
||||
v-if="state.orderInfo.price.discountPrice > 0"
|
||||
>
|
||||
<view class="item-title">活动优惠</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<!-- @tap="state.showDiscount = true" TODO 芋艿:后续要把优惠信息打进去 -->
|
||||
<view class="ss-flex ss-col-center" @tap="state.showDiscount = true">
|
||||
<text class="item-value text-red">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.discountPrice) }}
|
||||
</text>
|
||||
<text class="_icon-forward item-icon" />
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.price.vipPrice > 0"
|
||||
>
|
||||
<view class="item-title">会员优惠</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value text-red">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.vipPrice) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="total-box-footer ss-font-28 ss-flex ss-row-right ss-col-center ss-m-r-28">
|
||||
<view class="total-num ss-m-r-20">
|
||||
共{{ state.orderInfo.items.reduce((acc, item) => acc + item.count, 0) }}件
|
||||
</view>
|
||||
<view>合计:</view>
|
||||
<view class="total-num text-red"> ¥{{ fen2yuan(state.orderInfo.price.payPrice) }} </view>
|
||||
<view class="total-num text-red"> ¥{{ fen2yuan(state.orderInfo.price.payPrice) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -121,7 +194,7 @@
|
||||
@close="state.showCoupon = false"
|
||||
/>
|
||||
|
||||
<!-- 满额折扣弹框 TODO 芋艿:后续要把优惠信息打进去 -->
|
||||
<!-- 满额折扣弹框 TODO @puhui999:【折扣】后续要把优惠信息打进去 -->
|
||||
<s-discount-list
|
||||
v-model="state.orderInfo"
|
||||
:show="state.showDiscount"
|
||||
@@ -148,12 +221,12 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import AddressSelection from '@/pages/order/addressSelection.vue';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import TradeConfigApi from '@/sheep/api/trade/config';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
|
||||
const state = reactive({
|
||||
@@ -162,41 +235,62 @@
|
||||
items: [], // 商品项列表
|
||||
price: {}, // 价格信息
|
||||
},
|
||||
addressInfo: {}, // 选择的收货地址
|
||||
showCoupon: false, // 是否展示优惠劵
|
||||
couponInfo: [], // 优惠劵列表
|
||||
showDiscount: false, // 是否展示营销活动
|
||||
// ========== 积分 ==========
|
||||
pointStatus: false, //是否使用积分
|
||||
});
|
||||
|
||||
// 选择地址
|
||||
function onSelectAddress() {
|
||||
uni.$once('SELECT_ADDRESS', (e) => {
|
||||
changeConsignee(e.addressInfo);
|
||||
});
|
||||
sheep.$router.go('/pages/user/address/list');
|
||||
}
|
||||
const addressState = ref({
|
||||
addressInfo: {}, // 选择的收货地址
|
||||
deliveryType: 1, // 收货方式:1-快递配送,2-门店自提
|
||||
isPickUp: true, // 门店自提是否开启
|
||||
pickUpInfo: {}, // 选择的自提门店信息
|
||||
receiverName: '', // 收件人名称
|
||||
receiverMobile: '', // 收件人手机
|
||||
});
|
||||
|
||||
// 更改收货人地址&计算订单信息
|
||||
async function changeConsignee(addressInfo = {}) {
|
||||
if (!isEmpty(addressInfo)) {
|
||||
state.addressInfo = addressInfo;
|
||||
}
|
||||
// ========== 积分 ==========
|
||||
/**
|
||||
* 使用积分抵扣
|
||||
*/
|
||||
const changeIntegral = async () => {
|
||||
state.pointStatus = !state.pointStatus;
|
||||
await getOrderInfo();
|
||||
}
|
||||
};
|
||||
|
||||
// 选择优惠券
|
||||
async function onSelectCoupon(couponId) {
|
||||
state.orderPayload.couponId = couponId || 0;
|
||||
state.orderPayload.couponId = couponId;
|
||||
await getOrderInfo();
|
||||
state.showCoupon = false;
|
||||
}
|
||||
|
||||
// 提交订单
|
||||
function onConfirm() {
|
||||
if (!state.addressInfo.id) {
|
||||
if (addressState.value.deliveryType === 1 && !addressState.value.addressInfo.id) {
|
||||
sheep.$helper.toast('请选择收货地址');
|
||||
return;
|
||||
}
|
||||
if (addressState.value.deliveryType === 2) {
|
||||
if (!addressState.value.pickUpInfo.id) {
|
||||
sheep.$helper.toast('请选择自提门店地址');
|
||||
return;
|
||||
}
|
||||
if (addressState.value.receiverName === '' || addressState.value.receiverMobile === '') {
|
||||
sheep.$helper.toast('请填写联系人或联系人电话');
|
||||
return;
|
||||
}
|
||||
if (!/^[\u4e00-\u9fa5\w]{2,16}$/.test(addressState.value.receiverName)) {
|
||||
sheep.$helper.toast('请填写您的真实姓名');
|
||||
return;
|
||||
}
|
||||
if (!/^1(3|4|5|7|8|9|6)\d{9}$/.test(addressState.value.receiverMobile)) {
|
||||
sheep.$helper.toast('请填写正确的手机号');
|
||||
return;
|
||||
}
|
||||
}
|
||||
submitOrder();
|
||||
}
|
||||
|
||||
@@ -205,12 +299,17 @@
|
||||
const { code, data } = await OrderApi.createOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
addressId: state.addressInfo.id,
|
||||
deliveryType: 1, // TODO 芋艿:需要支持【门店自提】
|
||||
pointStatus: false, // TODO 芋艿:需要支持【积分选择】
|
||||
remark: state.orderPayload.remark,
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
addressId: addressState.value.addressInfo.id, // 收件地址编号
|
||||
pickUpStoreId: addressState.value.pickUpInfo.id, //自提门店编号
|
||||
receiverName: addressState.value.receiverName, // 选择门店自提时,该字段为联系人名
|
||||
receiverMobile: addressState.value.receiverMobile, // 选择门店自提时,该字段为联系人手机
|
||||
pointStatus: state.pointStatus,
|
||||
combinationActivityId: state.orderPayload.combinationActivityId,
|
||||
combinationHeadId: state.orderPayload.combinationHeadId,
|
||||
seckillActivityId: state.orderPayload.seckillActivityId
|
||||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
pointActivityId: state.orderPayload.pointActivityId,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
@@ -219,10 +318,17 @@
|
||||
if (state.orderPayload.items[0].cartId > 0) {
|
||||
sheep.$store('cart').getList();
|
||||
}
|
||||
|
||||
// 跳转到支付页面
|
||||
sheep.$router.redirect('/pages/pay/index', {
|
||||
id: data.payOrderId,
|
||||
});
|
||||
if (data.payOrderId && data.payOrderId > 0) {
|
||||
sheep.$router.redirect('/pages/pay/index', {
|
||||
id: data.payOrderId,
|
||||
});
|
||||
} else {
|
||||
sheep.$router.redirect('/pages/order/detail', {
|
||||
id: data.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 检查库存 & 计算订单价格
|
||||
@@ -231,33 +337,25 @@
|
||||
const { data, code } = await OrderApi.settlementOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
addressId: state.addressInfo.id,
|
||||
deliveryType: 1, // TODO 芋艿:需要支持【门店自提】
|
||||
pointStatus: false, // TODO 芋艿:需要支持【积分选择】
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
addressId: addressState.value.addressInfo.id, // 收件地址编号
|
||||
pickUpStoreId: addressState.value.pickUpInfo.id, //自提门店编号
|
||||
receiverName: addressState.value.receiverName, // 选择门店自提时,该字段为联系人名
|
||||
receiverMobile: addressState.value.receiverMobile, // 选择门店自提时,该字段为联系人手机
|
||||
pointStatus: state.pointStatus,
|
||||
combinationActivityId: state.orderPayload.combinationActivityId,
|
||||
combinationHeadId: state.orderPayload.combinationHeadId,
|
||||
seckillActivityId: state.orderPayload.seckillActivityId
|
||||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
pointActivityId: state.orderPayload.pointActivityId,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.orderInfo = data;
|
||||
state.couponInfo = data.coupons || [];
|
||||
// 设置收货地址
|
||||
if (state.orderInfo.address) {
|
||||
state.addressInfo = state.orderInfo.address;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取可用优惠券
|
||||
async function getCoupons() {
|
||||
const { code, data } = await CouponApi.getMatchCouponList(
|
||||
state.orderInfo.price.payPrice,
|
||||
state.orderInfo.items.map((item) => item.spuId),
|
||||
state.orderPayload.items.map((item) => item.skuId),
|
||||
state.orderPayload.items.map((item) => item.categoryId),
|
||||
);
|
||||
if (code === 0) {
|
||||
state.couponInfo = data;
|
||||
addressState.value.addressInfo = state.orderInfo.address;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +366,22 @@
|
||||
}
|
||||
state.orderPayload = JSON.parse(options.data);
|
||||
await getOrderInfo();
|
||||
await getCoupons();
|
||||
// 获取交易配置
|
||||
const { data, code } = await TradeConfigApi.getTradeConfig();
|
||||
if (code === 0) {
|
||||
addressState.value.isPickUp = data.deliveryPickUpEnabled;
|
||||
}
|
||||
});
|
||||
|
||||
// 使用 watch 监听地址和配送方式的变化
|
||||
watch(addressState, async (newAddress, oldAddress) => {
|
||||
// 如果收货地址或配送方式有变化,则重新计算价格
|
||||
if (
|
||||
newAddress.addressInfo.id !== oldAddress.addressInfo.id ||
|
||||
newAddress.deliveryType !== oldAddress.deliveryType
|
||||
) {
|
||||
await getOrderInfo();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
+70
-23
@@ -45,9 +45,9 @@
|
||||
</image>
|
||||
<view class="ss-font-30">{{ formatOrderStatus(state.orderInfo) }}</view>
|
||||
</view>
|
||||
<view class="ss-font-26 ss-m-x-20 ss-m-b-70">{{
|
||||
formatOrderStatusDescription(state.orderInfo)
|
||||
}}</view>
|
||||
<view class="ss-font-26 ss-m-x-20 ss-m-b-70">
|
||||
{{ formatOrderStatusDescription(state.orderInfo) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收货地址 -->
|
||||
@@ -67,11 +67,11 @@
|
||||
class="detail-goods"
|
||||
:style="[{ marginTop: state.orderInfo.receiverAreaId > 0 ? '0' : '-40rpx' }]"
|
||||
>
|
||||
<!-- 订单信息 TODO 芋艿: -->
|
||||
<!-- 订单信 -->
|
||||
<view class="order-list" v-for="item in state.orderInfo.items" :key="item.goods_id">
|
||||
<view class="order-card">
|
||||
<s-goods-item
|
||||
@tap="onGoodsDetail(item.skuId)"
|
||||
@tap="onGoodsDetail(item.spuId)"
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
@@ -126,6 +126,13 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 自提核销 -->
|
||||
<PickUpVerify
|
||||
:order-info="state.orderInfo"
|
||||
:systemStore="systemStore"
|
||||
ref="pickUpVerifyRef"
|
||||
></PickUpVerify>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="notice-box">
|
||||
<view class="notice-box__content">
|
||||
@@ -167,11 +174,22 @@
|
||||
<text class="title">运费</text>
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.deliveryPrice) }}</text>
|
||||
</view>
|
||||
<!-- TODO 芋艿:优惠劵抵扣、积分抵扣 -->
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.couponPrice > 0">
|
||||
<text class="title">优惠劵金额</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.couponPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.pointPrice > 0">
|
||||
<text class="title">积分抵扣</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.pointPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.discountPrice > 0">
|
||||
<text class="title">优惠金额</text>
|
||||
<text class="title">活动优惠</text>
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.discountPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.vipPrice > 0">
|
||||
<text class="title">会员优惠</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.vipPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item all-rpice-item ss-flex ss-m-t-20">
|
||||
<text class="title">{{ state.orderInfo.payStatus ? '已付款' : '需付款' }}</text>
|
||||
<text class="detail all-price">¥{{ fen2yuan(state.orderInfo.payPrice) }}</text>
|
||||
@@ -203,13 +221,12 @@
|
||||
>
|
||||
继续支付
|
||||
</button>
|
||||
<!-- TODO 芋艿:拼团接入 -->
|
||||
<button
|
||||
class="ss-reset-button cancel-btn"
|
||||
v-if="state.orderInfo.buttons?.includes('combination')"
|
||||
@tap="
|
||||
sheep.$router.go('/pages/activity/groupon/detail', {
|
||||
id: state.orderInfo.ext.groupon_id,
|
||||
id: state.orderInfo.combinationRecordId,
|
||||
})
|
||||
"
|
||||
>
|
||||
@@ -243,9 +260,9 @@
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatOrderStatus,
|
||||
@@ -253,6 +270,8 @@
|
||||
handleOrderButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import DeliveryApi from '@/sheep/api/trade/delivery';
|
||||
import PickUpVerify from '@/pages/order/pickUpVerify.vue';
|
||||
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
|
||||
@@ -263,9 +282,12 @@
|
||||
comeinType: '', // 进入订单详情的来源类型
|
||||
});
|
||||
|
||||
// ========== 门店自提(核销) ==========
|
||||
const systemStore = ref({}); // 门店信息
|
||||
|
||||
// 复制
|
||||
const onCopy = () => {
|
||||
sheep.$helper.copyText(state.orderInfo.sn);
|
||||
sheep.$helper.copyText(state.orderInfo.no);
|
||||
};
|
||||
|
||||
// 去支付
|
||||
@@ -306,7 +328,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
// 确认收货 TODO 芋艿:待测试
|
||||
// 确认收货
|
||||
async function onConfirm(orderId, ignore = false) {
|
||||
// 需开启确认收货组件
|
||||
// todo: 芋艿:待接入微信
|
||||
@@ -323,11 +345,20 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(orderId);
|
||||
if (code === 0) {
|
||||
await getOrderDetail(orderId);
|
||||
}
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认收货吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(orderId);
|
||||
if (code === 0) {
|
||||
await getOrderDetail(orderId);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
@@ -359,34 +390,50 @@
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// 评价
|
||||
function onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/add', {
|
||||
id
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
const pickUpVerifyRef = ref();
|
||||
|
||||
async function getOrderDetail(id) {
|
||||
// 对详情数据进行适配
|
||||
let res;
|
||||
if (state.comeinType === 'wechat') {
|
||||
// TODO 芋艿:微信场景下
|
||||
res = await OrderApi.getOrder(id, {
|
||||
res = await OrderApi.getOrderDetail(id, {
|
||||
merchant_trade_no: state.merchantTradeNo,
|
||||
});
|
||||
} else {
|
||||
res = await OrderApi.getOrder(id);
|
||||
res = await OrderApi.getOrderDetail(id);
|
||||
}
|
||||
if (res.code === 0) {
|
||||
state.orderInfo = res.data;
|
||||
handleOrderButtons(state.orderInfo);
|
||||
// 配送方式:门店自提
|
||||
if (res.data.pickUpStoreId) {
|
||||
const { data } = await DeliveryApi.getDeliveryPickUpStore(res.data.pickUpStoreId);
|
||||
systemStore.value = data || {};
|
||||
}
|
||||
if (state.orderInfo.deliveryType === 2 && state.orderInfo.payStatus) {
|
||||
pickUpVerifyRef.value && pickUpVerifyRef.value.markCode(res.data.pickUpVerifyCode);
|
||||
}
|
||||
} else {
|
||||
sheep.$router.back();
|
||||
}
|
||||
}
|
||||
|
||||
onShow(async () => {
|
||||
//onShow中获取订单列表,保证跳转后页面为最新状态
|
||||
await getOrderDetail(state.orderInfo.id);
|
||||
})
|
||||
|
||||
onLoad(async (options) => {
|
||||
let id = 0;
|
||||
if (options.id) {
|
||||
@@ -397,7 +444,7 @@
|
||||
if (state.comeinType === 'wechat') {
|
||||
state.merchantTradeNo = options.merchant_trade_no;
|
||||
}
|
||||
await getOrderDetail(id);
|
||||
state.orderInfo.id = id
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
+10
-10
@@ -12,11 +12,11 @@
|
||||
</swiper>
|
||||
</uni-swiper-dot>
|
||||
<view class="log-card-msg">
|
||||
<!-- TODO 芋艿:优化点:展示状态 -->
|
||||
<!-- <view class="ss-flex ss-m-b-8">-->
|
||||
<!-- <view>物流状态:</view>-->
|
||||
<!-- <view class="warning-color">{{ state.info.status_text }}</view>-->
|
||||
<!-- </view>-->
|
||||
<!-- TODO 芋艿:【物流】优化点:展示状态 -->
|
||||
<!-- <view class="ss-flex ss-m-b-8">-->
|
||||
<!-- <view>物流状态:</view>-->
|
||||
<!-- <view class="warning-color">{{ state.info.status_text }}</view>-->
|
||||
<!-- </view>-->
|
||||
<view class="ss-m-b-8">快递单号:{{ state.info.logisticsNo }}</view>
|
||||
<view>快递公司:{{ state.info.logisticsName }}</view>
|
||||
</view>
|
||||
@@ -34,10 +34,10 @@
|
||||
<view v-if="state.tracks.length - 1 !== index" class="line" />
|
||||
</view>
|
||||
<view class="log-content-msg">
|
||||
<!-- TODO 芋艿:优化点:展示状态 -->
|
||||
<!-- <view class="log-msg-title ss-m-b-20">-->
|
||||
<!-- {{ item.status_text }}-->
|
||||
<!-- </view>-->
|
||||
<!-- TODO 芋艿:【物流】优化点:展示状态 -->
|
||||
<!-- <view class="log-msg-title ss-m-b-20">-->
|
||||
<!-- {{ item.status_text }}-->
|
||||
<!-- </view>-->
|
||||
<view class="log-msg-desc ss-m-b-16">{{ item.content }}</view>
|
||||
<view class="log-msg-date ss-m-b-40">
|
||||
{{ sheep.$helper.timeFormat(item.time, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
@@ -78,7 +78,7 @@
|
||||
}
|
||||
|
||||
async function getOrderDetail(id) {
|
||||
const { data } = await OrderApi.getOrder(id)
|
||||
const { data } = await OrderApi.getOrderDetail(id);
|
||||
state.info = data;
|
||||
}
|
||||
|
||||
|
||||
+416
-371
@@ -1,249 +1,293 @@
|
||||
<!-- 订单列表 -->
|
||||
<template>
|
||||
<s-layout title="我的订单">
|
||||
<su-sticky bgColor="#fff">
|
||||
<su-tabs :list="tabMaps" :scrollable="false" @change="onTabsChange" :current="state.currentTab" />
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/order-empty.png" text="暂无订单" />
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view class="bg-white order-list-card-box ss-r-10 ss-m-t-14 ss-m-20" v-for="order in state.pagination.list"
|
||||
:key="order.id" @tap="onOrderDetail(order.id)">
|
||||
<view class="order-card-header ss-flex ss-col-center ss-row-between ss-p-x-20">
|
||||
<view class="order-no">订单号:{{ order.no }}</view>
|
||||
<view class="order-state ss-font-26" :class="formatOrderColor(order)">
|
||||
<s-layout title="我的订单">
|
||||
<su-sticky bgColor="#fff">
|
||||
<su-tabs
|
||||
:list="tabMaps"
|
||||
:scrollable="false"
|
||||
@change="onTabsChange"
|
||||
:current="state.currentTab"
|
||||
/>
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/order-empty.png" text="暂无订单" />
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view
|
||||
class="bg-white order-list-card-box ss-r-10 ss-m-t-14 ss-m-20"
|
||||
v-for="order in state.pagination.list"
|
||||
:key="order.id"
|
||||
@tap="onOrderDetail(order.id)"
|
||||
>
|
||||
<view class="order-card-header ss-flex ss-col-center ss-row-between ss-p-x-20">
|
||||
<view class="order-no">订单号:{{ order.no }}</view>
|
||||
<view class="order-state ss-font-26" :class="formatOrderColor(order)">
|
||||
{{ formatOrderStatus(order) }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="border-bottom" v-for="item in order.items" :key="item.id">
|
||||
<s-goods-item
|
||||
</view>
|
||||
<view class="border-bottom" v-for="item in order.items" :key="item.id">
|
||||
<s-goods-item
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
/>
|
||||
</view>
|
||||
<view class="pay-box ss-m-t-30 ss-flex ss-row-right ss-p-r-20">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="discounts-title pay-color">共 {{ order.productCount }} 件商品,总金额:</view>
|
||||
<view class="discounts-money pay-color">
|
||||
¥{{ fen2yuan(order.payPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-card-footer ss-flex ss-col-center ss-p-x-20"
|
||||
:class="order.buttons.length > 3 ? 'ss-row-between' : 'ss-row-right'">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<button v-if="order.buttons.includes('combination')" class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderGroupon(order)">
|
||||
</view>
|
||||
<view class="pay-box ss-m-t-30 ss-flex ss-row-right ss-p-r-20">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="discounts-title pay-color"
|
||||
>共 {{ order.productCount }} 件商品,总金额:</view
|
||||
>
|
||||
<view class="discounts-money pay-color"> ¥{{ fen2yuan(order.payPrice) }} </view>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-card-footer ss-flex ss-col-center ss-p-x-20"
|
||||
:class="order.buttons.length > 3 ? 'ss-row-between' : 'ss-row-right'"
|
||||
>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<button
|
||||
v-if="order.buttons.includes('combination')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderGroupon(order)"
|
||||
>
|
||||
拼团详情
|
||||
</button>
|
||||
<button v-if="order.buttons.length === 0" class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderDetail(order.id)">
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.length === 0"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderDetail(order.id)"
|
||||
>
|
||||
查看详情
|
||||
</button>
|
||||
<button v-if="order.buttons.includes('confirm')" class="tool-btn ss-reset-button"
|
||||
@tap.stop="onConfirm(order)">
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('confirm')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onConfirm(order)"
|
||||
>
|
||||
确认收货
|
||||
</button>
|
||||
<button v-if="order.buttons.includes('express')" class="tool-btn ss-reset-button"
|
||||
@tap.stop="onExpress(order.id)">
|
||||
查看物流
|
||||
</button>
|
||||
<button v-if="order.buttons.includes('cancel')" class="tool-btn ss-reset-button"
|
||||
@tap.stop="onCancel(order.id)">
|
||||
取消订单
|
||||
</button>
|
||||
<button v-if="order.buttons.includes('comment')" class="tool-btn ss-reset-button"
|
||||
@tap.stop="onComment(order.id)">
|
||||
评价
|
||||
</button>
|
||||
<button v-if="order.buttons.includes('delete')" class="delete-btn ss-reset-button"
|
||||
@tap.stop="onDelete(order.id)">
|
||||
删除订单
|
||||
</button>
|
||||
<button v-if="order.buttons.includes('pay')" class="tool-btn ss-reset-button ui-BG-Main-Gradient"
|
||||
@tap.stop="onPay(order.payOrderId)">
|
||||
继续支付
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('express')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onExpress(order.id)"
|
||||
>
|
||||
查看物流
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('cancel')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onCancel(order.id)"
|
||||
>
|
||||
取消订单
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('comment')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onComment(order.id)"
|
||||
>
|
||||
评价
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('delete')"
|
||||
class="delete-btn ss-reset-button"
|
||||
@tap.stop="onDelete(order.id)"
|
||||
>
|
||||
删除订单
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('pay')"
|
||||
class="tool-btn ss-reset-button ui-BG-Main-Gradient"
|
||||
@tap.stop="onPay(order.payOrderId)"
|
||||
>
|
||||
继续支付
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
|
||||
<!-- 加载更多 -->
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}" @tap="loadMore" />
|
||||
</s-layout>
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatOrderColor, formatOrderStatus, handleOrderButtons,
|
||||
formatOrderColor,
|
||||
formatOrderStatus,
|
||||
handleOrderButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
isEmpty
|
||||
} from 'lodash';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash-es';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
const paginationNull = {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 5,
|
||||
};
|
||||
|
||||
// 数据
|
||||
const state = reactive({
|
||||
currentTab: 0, // 选中的 tabMaps 下标
|
||||
pagination: {
|
||||
// 数据
|
||||
const state = reactive({
|
||||
currentTab: 0, // 选中的 tabMaps 下标
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 5,
|
||||
},
|
||||
loadStatus: ''
|
||||
});
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
|
||||
const tabMaps = [{
|
||||
name: '全部'
|
||||
},
|
||||
{
|
||||
name: '待付款',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: '待发货',
|
||||
value: 10,
|
||||
},
|
||||
{
|
||||
name: '待收货',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: '待评价',
|
||||
value: 30,
|
||||
},
|
||||
];
|
||||
const tabMaps = [
|
||||
{
|
||||
name: '全部',
|
||||
},
|
||||
{
|
||||
name: '待付款',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: '待发货',
|
||||
value: 10,
|
||||
},
|
||||
{
|
||||
name: '待收货',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: '待评价',
|
||||
value: 30,
|
||||
},
|
||||
];
|
||||
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
if (state.currentTab === e.index) {
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
if (state.currentTab === e.index) {
|
||||
return;
|
||||
}
|
||||
// 重头加载代码
|
||||
state.pagination = paginationNull;
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
resetPagination(state.pagination);
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 订单详情
|
||||
function onOrderDetail(id) {
|
||||
sheep.$router.go('/pages/order/detail', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 分享拼团 TODO 芋艿:待测试
|
||||
function onOrderGroupon(order) {
|
||||
sheep.$router.go('/pages/activity/groupon/detail', {
|
||||
id: order.ext.groupon_id,
|
||||
});
|
||||
}
|
||||
|
||||
// 继续支付
|
||||
function onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 评价
|
||||
function onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/add', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 确认收货 TODO 芋艿:待测试
|
||||
async function onConfirm(order, ignore = false) {
|
||||
// 需开启确认收货组件
|
||||
// todo: 芋艿:需要后续接入微信收货组件
|
||||
// 1.怎么检测是否开启了发货组件功能?如果没有开启的话就不能在这里return出去
|
||||
// 2.如果开启了走mpConfirm方法,需要在App.vue的show方法中拿到确认收货结果
|
||||
let isOpenBusinessView = true;
|
||||
if (
|
||||
sheep.$platform.name === 'WechatMiniProgram' &&
|
||||
!isEmpty(order.wechat_extra_data) &&
|
||||
isOpenBusinessView &&
|
||||
!ignore
|
||||
) {
|
||||
mpConfirm(order);
|
||||
return;
|
||||
}
|
||||
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(order.id);
|
||||
if (code === 0) {
|
||||
state.pagination = paginationNull;
|
||||
await getOrderList();
|
||||
}
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 小程序确认收货组件 TODO 芋艿:后续再接入
|
||||
function mpConfirm(order) {
|
||||
if (!wx.openBusinessView) {
|
||||
sheep.$helper.toast(`请升级微信版本`);
|
||||
return;
|
||||
}
|
||||
wx.openBusinessView({
|
||||
businessType: 'weappOrderConfirm',
|
||||
extraData: {
|
||||
merchant_id: '1481069012',
|
||||
merchant_trade_no: order.wechat_extra_data.merchant_trade_no,
|
||||
transaction_id: order.wechat_extra_data.transaction_id,
|
||||
},
|
||||
success(response) {
|
||||
console.log('success:', response);
|
||||
if (response.errMsg === 'openBusinessView:ok') {
|
||||
if (response.extraData.status === 'success') {
|
||||
onConfirm(order, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
fail(error) {
|
||||
console.log('error:', error);
|
||||
},
|
||||
complete(result) {
|
||||
console.log('result:', result);
|
||||
},
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
|
||||
// 查看物流
|
||||
async function onExpress(id) {
|
||||
sheep.$router.go('/pages/order/express/log', {
|
||||
// 订单详情
|
||||
function onOrderDetail(id) {
|
||||
sheep.$router.go('/pages/order/detail', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 取消订单
|
||||
async function onCancel(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
// 跳转拼团记录的详情
|
||||
function onOrderGroupon(order) {
|
||||
sheep.$router.go('/pages/activity/groupon/detail', {
|
||||
id: order.combinationRecordId,
|
||||
});
|
||||
}
|
||||
|
||||
// 继续支付
|
||||
function onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 评价
|
||||
function onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/add', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 确认收货 TODO 芋艿:待测试
|
||||
async function onConfirm(order, ignore = false) {
|
||||
// 需开启确认收货组件
|
||||
// todo: 芋艿:需要后续接入微信收货组件
|
||||
// 1.怎么检测是否开启了发货组件功能?如果没有开启的话就不能在这里return出去
|
||||
// 2.如果开启了走mpConfirm方法,需要在App.vue的show方法中拿到确认收货结果
|
||||
let isOpenBusinessView = true;
|
||||
if (
|
||||
sheep.$platform.name === 'WechatMiniProgram' &&
|
||||
!isEmpty(order.wechat_extra_data) &&
|
||||
isOpenBusinessView &&
|
||||
!ignore
|
||||
) {
|
||||
mpConfirm(order);
|
||||
return;
|
||||
}
|
||||
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认收货吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(order.id);
|
||||
if (code === 0) {
|
||||
resetPagination(state.pagination);
|
||||
await getOrderList();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 小程序确认收货组件 TODO 芋艿:后续再接入
|
||||
function mpConfirm(order) {
|
||||
if (!wx.openBusinessView) {
|
||||
sheep.$helper.toast(`请升级微信版本`);
|
||||
return;
|
||||
}
|
||||
wx.openBusinessView({
|
||||
businessType: 'weappOrderConfirm',
|
||||
extraData: {
|
||||
merchant_id: '1481069012',
|
||||
merchant_trade_no: order.wechat_extra_data.merchant_trade_no,
|
||||
transaction_id: order.wechat_extra_data.transaction_id,
|
||||
},
|
||||
success(response) {
|
||||
console.log('success:', response);
|
||||
if (response.errMsg === 'openBusinessView:ok') {
|
||||
if (response.extraData.status === 'success') {
|
||||
onConfirm(order, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
fail(error) {
|
||||
console.log('error:', error);
|
||||
},
|
||||
complete(result) {
|
||||
console.log('result:', result);
|
||||
},
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
|
||||
// 查看物流
|
||||
async function onExpress(id) {
|
||||
sheep.$router.go('/pages/order/express/log', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 取消订单
|
||||
async function onCancel(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await OrderApi.cancelOrder(orderId);
|
||||
if (code === 0) {
|
||||
// 修改数据的状态
|
||||
@@ -252,208 +296,209 @@
|
||||
orderInfo.status = 40;
|
||||
handleOrderButtons(orderInfo);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 删除订单
|
||||
function onDelete(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要删除订单吗?',
|
||||
success: async function(res) {
|
||||
if (res.confirm) {
|
||||
const { code } = await OrderApi.deleteOrder(orderId);
|
||||
if (code === 0) {
|
||||
// 删除订单
|
||||
function onDelete(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要删除订单吗?',
|
||||
success: async function (res) {
|
||||
if (res.confirm) {
|
||||
const { code } = await OrderApi.deleteOrder(orderId);
|
||||
if (code === 0) {
|
||||
// 删除数据
|
||||
let index = state.pagination.list.findIndex((order) => order.id === orderId);
|
||||
state.pagination.list.splice(index, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
let index = state.pagination.list.findIndex((order) => order.id === orderId);
|
||||
state.pagination.list.splice(index, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 获取订单列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { code, data } = await OrderApi.getOrderPage({
|
||||
// 获取订单列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { code, data } = await OrderApi.getOrderPage({
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
status: tabMaps[state.currentTab].value,
|
||||
commentStatus: tabMaps[state.currentTab].value === 30 ? false : null
|
||||
});
|
||||
commentStatus: tabMaps[state.currentTab].value === 30 ? false : null,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
data.list.forEach(order => handleOrderButtons(order));
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list)
|
||||
data.list.forEach((order) => handleOrderButtons(order));
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return
|
||||
}
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
|
||||
// 下拉刷新
|
||||
onPullDownRefresh(() => {
|
||||
state.pagination = paginationNull;
|
||||
getOrderList();
|
||||
setTimeout(function() {
|
||||
uni.stopPullDownRefresh();
|
||||
}, 800);
|
||||
});
|
||||
// 下拉刷新
|
||||
onPullDownRefresh(() => {
|
||||
resetPagination(state.pagination);
|
||||
getOrderList();
|
||||
setTimeout(function () {
|
||||
uni.stopPullDownRefresh();
|
||||
}, 800);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
font-size: 26rpx;
|
||||
border-radius: 30rpx;
|
||||
margin-right: 10rpx;
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
font-size: 26rpx;
|
||||
border-radius: 30rpx;
|
||||
margin-right: 10rpx;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
width: 160rpx;
|
||||
height: 56rpx;
|
||||
color: #ff3000;
|
||||
background: #fee;
|
||||
border-radius: 28rpx;
|
||||
font-size: 26rpx;
|
||||
margin-right: 10rpx;
|
||||
line-height: normal;
|
||||
.delete-btn {
|
||||
width: 160rpx;
|
||||
height: 56rpx;
|
||||
color: #ff3000;
|
||||
background: #fee;
|
||||
border-radius: 28rpx;
|
||||
font-size: 26rpx;
|
||||
margin-right: 10rpx;
|
||||
line-height: normal;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.apply-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
border: 2rpx solid #dcdcdc;
|
||||
line-height: normal;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
.apply-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
border: 2rpx solid #dcdcdc;
|
||||
line-height: normal;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.swiper-box {
|
||||
flex: 1;
|
||||
.swiper-box {
|
||||
flex: 1;
|
||||
|
||||
.swiper-item {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.swiper-item {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.order-list-card-box {
|
||||
.order-card-header {
|
||||
height: 80rpx;
|
||||
.order-list-card-box {
|
||||
.order-card-header {
|
||||
height: 80rpx;
|
||||
|
||||
.order-no {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
.order-no {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.order-state {}
|
||||
}
|
||||
.order-state {
|
||||
}
|
||||
}
|
||||
|
||||
.pay-box {
|
||||
.discounts-title {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999999;
|
||||
}
|
||||
.pay-box {
|
||||
.discounts-title {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.discounts-money {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
.discounts-money {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.pay-color {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
.pay-color {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.order-card-footer {
|
||||
height: 100rpx;
|
||||
.order-card-footer {
|
||||
height: 100rpx;
|
||||
|
||||
.more-item-box {
|
||||
padding: 20rpx;
|
||||
.more-item-box {
|
||||
padding: 20rpx;
|
||||
|
||||
.more-item {
|
||||
height: 60rpx;
|
||||
.more-item {
|
||||
height: 60rpx;
|
||||
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.more-btn {
|
||||
color: $dark-9;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.more-btn {
|
||||
color: $dark-9;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 154rpx;
|
||||
color: #333333;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
width: 154rpx;
|
||||
color: #333333;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.uni-tooltip-popup) {
|
||||
background: var(--ui-BG);
|
||||
}
|
||||
:deep(.uni-tooltip-popup) {
|
||||
background: var(--ui-BG);
|
||||
}
|
||||
|
||||
.warning-color {
|
||||
color: #faad14;
|
||||
}
|
||||
.warning-color {
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.danger-color {
|
||||
color: #ff3000;
|
||||
}
|
||||
.danger-color {
|
||||
color: #ff3000;
|
||||
}
|
||||
|
||||
.success-color {
|
||||
color: #52c41a;
|
||||
}
|
||||
.success-color {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.info-color {
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
.info-color {
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,260 @@
|
||||
<template>
|
||||
<view class='order-details'>
|
||||
<!-- 自提商品核销 -->
|
||||
<view v-if="orderInfo.deliveryType === 2 && orderInfo.payStatus" class="writeOff borRadius14">
|
||||
<view class="title">核销信息</view>
|
||||
<view class="grayBg flex-center">
|
||||
<view class="pictrue">
|
||||
<image
|
||||
v-if="!!painterImageUrl"
|
||||
:src="painterImageUrl"
|
||||
:style="{width: `${state.qrcodeSize}px`, height: `${state.qrcodeSize}px`}"
|
||||
:show-menu-by-longpress="true"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="gear">
|
||||
<image :src="sheep.$url.static('/static/images/writeOff.png', 'local')"></image>
|
||||
</view>
|
||||
<view class="num">{{ orderInfo.pickUpVerifyCode }}</view>
|
||||
<view class="rules">
|
||||
<!-- TODO puhui999: 需要后端放回:使用 receiveTime 即可 -->
|
||||
<view class="item">
|
||||
<view class="rulesTitle flex flex-wrap align-center">
|
||||
核销时间
|
||||
</view>
|
||||
<view class="info">
|
||||
每日:
|
||||
<text class="time">2020-2-+52</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="rulesTitle flex flex-wrap align-center">
|
||||
<text class="iconfont icon-shuoming1"></text>
|
||||
使用说明
|
||||
</view>
|
||||
<view class="info">可将二维码出示给店员扫描或提供数字核销码</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="orderInfo.deliveryType === 2" class="map flex flex-wrap align-center ss-row-between borRadius14">
|
||||
<view>自提地址信息</view>
|
||||
<view class="place cart-color flex flex-wrap flex-center" @tap="showMaoLocation">
|
||||
查看位置
|
||||
</view>
|
||||
</view>
|
||||
<!-- 海报画板:默认隐藏只用来生成海报。生成方式为主动调用 -->
|
||||
<l-painter
|
||||
v-if="showPainter"
|
||||
isCanvasToTempFilePath
|
||||
pathType="url"
|
||||
@success="setPainterImageUrl"
|
||||
hidden
|
||||
ref="painterRef"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
orderInfo: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
systemStore:{
|
||||
type: Object,
|
||||
default() {},
|
||||
}
|
||||
});
|
||||
const state = reactive({
|
||||
qrcodeSize: 145
|
||||
})
|
||||
|
||||
/**
|
||||
* 打开地图
|
||||
*/
|
||||
const showMaoLocation = () => {
|
||||
console.log(props.systemStore);
|
||||
if (!props.systemStore.latitude || !props.systemStore.longitude) {
|
||||
sheep.$helper.toast('缺少经纬度信息无法查看地图!');
|
||||
return
|
||||
}
|
||||
uni.openLocation({
|
||||
latitude: props.systemStore.latitude,
|
||||
longitude: props.systemStore.longitude,
|
||||
scale: 8,
|
||||
name: props.systemStore.name,
|
||||
address: props.systemStore.areaName + props.systemStore.detailAddress,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 拨打电话
|
||||
*/
|
||||
const makePhone = () => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: props.systemStore.phone
|
||||
})
|
||||
}
|
||||
|
||||
const painterRef = ref(); // 海报画板
|
||||
const painterImageUrl = ref(); // 海报 url
|
||||
const showPainter = ref(true)
|
||||
// 渲染海报
|
||||
const renderPoster = async (poster) => {
|
||||
await painterRef.value.render(poster);
|
||||
};
|
||||
// 获得生成的图片
|
||||
const setPainterImageUrl = (path) => {
|
||||
painterImageUrl.value = path;
|
||||
showPainter.value = false
|
||||
};
|
||||
/**
|
||||
* 生成核销二维码
|
||||
*/
|
||||
const markCode = (text) => {
|
||||
renderPoster({
|
||||
css: {
|
||||
width: `${state.qrcodeSize}px`,
|
||||
height: `${state.qrcodeSize}px`
|
||||
},
|
||||
views:[
|
||||
{
|
||||
type: 'qrcode',
|
||||
text: text,
|
||||
css: {
|
||||
width: `${state.qrcodeSize}px`,
|
||||
height: `${state.qrcodeSize}px`
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
defineExpose({
|
||||
markCode
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.borRadius14 {
|
||||
border-radius: 14rpx !important;
|
||||
}
|
||||
.cart-color {
|
||||
color: #E93323 !important;
|
||||
border: 1px solid #E93323 !important
|
||||
}
|
||||
.order-details{
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
}
|
||||
.order-details .writeOff {
|
||||
background-color: #fff;
|
||||
margin-top: 15rpx;
|
||||
padding-bottom: 50rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .title {
|
||||
font-size: 30rpx;
|
||||
color: #282828;
|
||||
height: 87rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
padding: 0 24rpx;
|
||||
line-height: 87rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .grayBg {
|
||||
background-color: #f2f5f7;
|
||||
width: 590rpx;
|
||||
height: 384rpx;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
margin: 50rpx auto 0 auto;
|
||||
padding-top: 55rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .grayBg .pictrue {
|
||||
width: 290rpx;
|
||||
height: 290rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .grayBg .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.order-details .writeOff .gear {
|
||||
width: 590rpx;
|
||||
height: 30rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.order-details .writeOff .gear image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.order-details .writeOff .num {
|
||||
background-color: #f0c34c;
|
||||
width: 590rpx;
|
||||
height: 84rpx;
|
||||
color: #282828;
|
||||
font-size: 48rpx;
|
||||
margin: 0 auto;
|
||||
border-radius: 0 0 20rpx 20rpx;
|
||||
text-align: center;
|
||||
padding-top: 4rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules {
|
||||
margin: 46rpx 30rpx 0 30rpx;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
padding-top: 10rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item .rulesTitle {
|
||||
font-size: 28rpx;
|
||||
color: #282828;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item .rulesTitle .iconfont {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
margin-right: 8rpx;
|
||||
margin-top: 5rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item .info {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
margin-top: 7rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item .info .time {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.order-details .map {
|
||||
height: 86rpx;
|
||||
font-size: 30rpx;
|
||||
color: #282828;
|
||||
line-height: 86rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
margin-top: 15rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.order-details .map .place {
|
||||
font-size: 26rpx;
|
||||
width: 176rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
line-height: 50rpx;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
+31
-14
@@ -81,7 +81,7 @@
|
||||
import { fen2yuan, useDurationTime } from '@/sheep/hooks/useGoods';
|
||||
import PayOrderApi from '@/sheep/api/pay/order';
|
||||
import PayChannelApi from '@/sheep/api/pay/channel';
|
||||
import { getPayMethods } from '@/sheep/platform/pay';
|
||||
import { getPayMethods, goPayResult } from '@/sheep/platform/pay';
|
||||
|
||||
const userWallet = computed(() => sheep.$store('user').userWallet);
|
||||
|
||||
@@ -135,12 +135,22 @@
|
||||
|
||||
// 状态转换:payOrder.status => payStatus
|
||||
function checkPayStatus() {
|
||||
if (state.orderInfo.status === 10
|
||||
|| state.orderInfo.status === 20 ) { // 支付成功
|
||||
if (state.orderInfo.status === 10 || state.orderInfo.status === 20) {
|
||||
// 支付成功
|
||||
state.payStatus = 2;
|
||||
// 跳转回支付成功页
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '订单已支付',
|
||||
showCancel: false,
|
||||
success: function () {
|
||||
goPayResult(state.orderInfo.id, state.orderType);
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (state.orderInfo.status === 30) { // 支付关闭
|
||||
if (state.orderInfo.status === 30) {
|
||||
// 支付关闭
|
||||
state.payStatus = -1;
|
||||
return;
|
||||
}
|
||||
@@ -155,31 +165,39 @@
|
||||
// 设置支付订单信息
|
||||
async function setOrder(id) {
|
||||
// 获得支付订单信息
|
||||
const { data, code } = await PayOrderApi.getOrder(id);
|
||||
const { data, code } = await PayOrderApi.getOrder(id, true);
|
||||
if (code !== 0 || !data) {
|
||||
state.payStatus = -2;
|
||||
return;
|
||||
}
|
||||
state.orderInfo = data;
|
||||
// 获得支付方式
|
||||
await setPayMethods();
|
||||
// 设置支付状态
|
||||
checkPayStatus();
|
||||
// 获得支付方式
|
||||
await setPayMethods();
|
||||
}
|
||||
|
||||
// 获得支付方式
|
||||
async function setPayMethods() {
|
||||
const { data, code } = await PayChannelApi.getEnableChannelCodeList(state.orderInfo.appId)
|
||||
const { data, code } = await PayChannelApi.getEnableChannelCodeList(state.orderInfo.appId);
|
||||
if (code !== 0) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
state.payMethods = getPayMethods(data)
|
||||
state.payMethods = getPayMethods(data);
|
||||
state.payMethods.find((item) => {
|
||||
if (item.value && !item.disabled) {
|
||||
state.payment = item.value;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
if (sheep.$platform.name === 'WechatOfficialAccount'
|
||||
&& sheep.$platform.os === 'ios'
|
||||
&& !sheep.$platform.landingPage.includes('pages/pay/index')) {
|
||||
if (
|
||||
sheep.$platform.name === 'WechatOfficialAccount' &&
|
||||
sheep.$platform.os === 'ios' &&
|
||||
!sheep.$platform.landingPage.includes('pages/pay/index')
|
||||
) {
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
@@ -208,7 +226,6 @@
|
||||
position: relative;
|
||||
padding: 60rpx 20rpx 40rpx;
|
||||
|
||||
|
||||
.money-text {
|
||||
color: $red;
|
||||
font-size: 46rpx;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<view class="title">充值金额</view>
|
||||
<view class="num" :class="item.refundStatus === 10 ? 'danger-color' : 'success-color'">
|
||||
{{ fen2yuan(item.payPrice) }} 元
|
||||
<text v-if="item.bonusPrice > 0">(赠送 {{ fen2yuan(item.bonusPrice)}} 元)</text>
|
||||
<text v-if="item.bonusPrice > 0">(赠送 {{ fen2yuan(item.bonusPrice) }} 元)</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="status-box item ss-flex ss-col-center ss-row-between">
|
||||
@@ -30,7 +30,9 @@
|
||||
</view>
|
||||
<view class="time-box item ss-flex ss-col-center ss-row-between">
|
||||
<text class="item-title">充值时间</text>
|
||||
<view class="time"> {{ sheep.$helper.timeFormat(item.payTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
|
||||
<view class="time">
|
||||
{{ sheep.$helper.timeFormat(item.payTime, 'yyyy-mm-dd hh:MM:ss') }}</view
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -53,7 +55,7 @@
|
||||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import PayWalletApi from '@/sheep/api/pay/wallet';
|
||||
import sheep from '@/sheep';
|
||||
import { fen2yuan } from '../../sheep/hooks/useGoods';
|
||||
|
||||
+201
-200
@@ -1,259 +1,260 @@
|
||||
<!-- 充值界面 -->
|
||||
<template>
|
||||
<s-layout title="充值" class="withdraw-wrap" navbar="inner">
|
||||
<view class="wallet-num-box ss-flex ss-col-center ss-row-between" :style="[
|
||||
<s-layout title="充值" class="withdraw-wrap" navbar="inner">
|
||||
<view class="wallet-num-box ss-flex ss-col-center ss-row-between" :style="[
|
||||
{
|
||||
marginTop: '-' + Number(statusBarHeight + 88) + 'rpx',
|
||||
paddingTop: Number(statusBarHeight + 108) + 'rpx',
|
||||
},
|
||||
]">
|
||||
<view class="">
|
||||
<view class="num-title">当前余额(元)</view>
|
||||
<view class="wallet-num">{{ fen2yuan(userWallet.balance) }}</view>
|
||||
</view>
|
||||
<button class="ss-reset-button log-btn" @tap="sheep.$router.go('/pages/pay/recharge-log')">
|
||||
<view class="">
|
||||
<view class="num-title">当前余额(元)</view>
|
||||
<view class="wallet-num">{{ fen2yuan(userWallet.balance) }}</view>
|
||||
</view>
|
||||
<button class="ss-reset-button log-btn" @tap="sheep.$router.go('/pages/pay/recharge-log')">
|
||||
充值记录
|
||||
</button>
|
||||
</view>
|
||||
<view class="recharge-box">
|
||||
<view class="recharge-card-box">
|
||||
<view class="input-label ss-m-b-50">充值金额</view>
|
||||
<view class="input-box ss-flex border-bottom ss-p-b-20">
|
||||
<view class="unit">¥</view>
|
||||
<uni-easyinput v-model="state.recharge_money" type="digit" placeholder="请输入充值金额"
|
||||
</view>
|
||||
<view class="recharge-box">
|
||||
<view class="recharge-card-box">
|
||||
<view class="input-label ss-m-b-50">充值金额</view>
|
||||
<view class="input-box ss-flex border-bottom ss-p-b-20">
|
||||
<view class="unit">¥</view>
|
||||
<uni-easyinput v-model="state.recharge_money" type="digit" placeholder="请输入充值金额"
|
||||
:inputBorder="false" />
|
||||
</view>
|
||||
<view class="face-value-box ss-flex ss-flex-wrap ss-m-y-40">
|
||||
<button class="ss-reset-button face-value-btn" v-for="item in state.packageList" :key="item.money"
|
||||
:class="[{ 'btn-active': state.recharge_money === fen2yuan(item.payPrice) }]"
|
||||
@tap="onCard(item.payPrice)">
|
||||
<text class="face-value-title">{{ fen2yuan(item.payPrice) }}</text>
|
||||
<view v-if="item.bonusPrice" class="face-value-tag">
|
||||
送 {{ fen2yuan(item.bonusPrice) }} 元
|
||||
</view>
|
||||
<view class="face-value-box ss-flex ss-flex-wrap ss-m-y-40">
|
||||
<button class="ss-reset-button face-value-btn" v-for="item in state.packageList" :key="item.money"
|
||||
:class="[{ 'btn-active': state.recharge_money === fen2yuan(item.payPrice) }]"
|
||||
@tap="onCard(item.payPrice)">
|
||||
<text class="face-value-title">{{ fen2yuan(item.payPrice) }}</text>
|
||||
<view v-if="item.bonusPrice" class="face-value-tag">
|
||||
送 {{ fen2yuan(item.bonusPrice) }} 元
|
||||
</view>
|
||||
</button>
|
||||
</view>
|
||||
<button class="ss-reset-button save-btn ui-BG-Main-Gradient ss-m-t-60 ui-Shadow-Main" @tap="onConfirm">
|
||||
确认充值
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</s-layout>
|
||||
</button>
|
||||
</view>
|
||||
<button class="ss-reset-button save-btn ui-BG-Main-Gradient ss-m-t-60 ui-Shadow-Main" @tap="onConfirm">
|
||||
确认充值
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, reactive } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { computed, reactive } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import PayWalletApi from '@/sheep/api/pay/wallet';
|
||||
import { WxaSubscribeTemplate } from '@/sheep/util/const';
|
||||
|
||||
const userWallet = computed(() => sheep.$store('user').userWallet);
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
|
||||
const userWallet = computed(() => sheep.$store('user').userWallet);
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
|
||||
|
||||
const state = reactive({
|
||||
recharge_money: '', // 输入的充值金额
|
||||
const state = reactive({
|
||||
recharge_money: '', // 输入的充值金额
|
||||
packageList: [],
|
||||
});
|
||||
});
|
||||
|
||||
// 点击卡片,选择充值金额
|
||||
function onCard(e) {
|
||||
state.recharge_money = fen2yuan(e);
|
||||
}
|
||||
// 点击卡片,选择充值金额
|
||||
function onCard(e) {
|
||||
state.recharge_money = fen2yuan(e);
|
||||
}
|
||||
|
||||
// 获得钱包充值套餐列表
|
||||
async function getRechargeTabs() {
|
||||
async function getRechargeTabs() {
|
||||
const { code, data } = await PayWalletApi.getWalletRechargePackageList();
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.packageList = data;
|
||||
}
|
||||
}
|
||||
|
||||
// 发起支付
|
||||
async function onConfirm() {
|
||||
const { code, data } = await PayWalletApi.createWalletRecharge({
|
||||
packageId: state.packageList.find((item) => fen2yuan(item.payPrice) === state.recharge_money)?.id,
|
||||
payPrice: state.recharge_money * 100
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
async function onConfirm() {
|
||||
const { code, data } = await PayWalletApi.createWalletRecharge({
|
||||
packageId: state.packageList.find((item) => fen2yuan(item.payPrice) === state.recharge_money)?.id,
|
||||
payPrice: state.recharge_money * 100,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
// #ifdef MP
|
||||
sheep.$platform.useProvider('wechat').subscribeMessage('money_change');
|
||||
sheep.$platform.useProvider('wechat').subscribeMessage(WxaSubscribeTemplate.PAY_WALLET_RECHARGER_SUCCESS);
|
||||
// #endif
|
||||
sheep.$router.go('/pages/pay/index', {
|
||||
id: data.payOrderId,
|
||||
orderType: 'recharge'
|
||||
orderType: 'recharge',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(() => {
|
||||
getRechargeTabs();
|
||||
});
|
||||
onLoad(() => {
|
||||
getRechargeTabs();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
.uni-input-input {
|
||||
font-family: OPPOSANS !important;
|
||||
}
|
||||
}
|
||||
:deep() {
|
||||
.uni-input-input {
|
||||
font-family: OPPOSANS !important;
|
||||
}
|
||||
}
|
||||
|
||||
.wallet-num-box {
|
||||
padding: 0 40rpx 80rpx;
|
||||
background: var(--ui-BG-Main) v-bind(headerBg) center/750rpx 100% no-repeat;
|
||||
border-radius: 0 0 5% 5%;
|
||||
.wallet-num-box {
|
||||
padding: 0 40rpx 80rpx;
|
||||
background: var(--ui-BG-Main) v-bind(headerBg) center/750rpx 100% no-repeat;
|
||||
border-radius: 0 0 5% 5%;
|
||||
|
||||
.num-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.num-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.wallet-num {
|
||||
font-size: 60rpx;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
.wallet-num {
|
||||
font-size: 60rpx;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.log-btn {
|
||||
width: 170rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border: 1rpx solid $white;
|
||||
border-radius: 30rpx;
|
||||
padding: 0;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
.log-btn {
|
||||
width: 170rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border: 1rpx solid $white;
|
||||
border-radius: 30rpx;
|
||||
padding: 0;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
.recharge-box {
|
||||
position: relative;
|
||||
padding: 0 30rpx;
|
||||
margin-top: -60rpx;
|
||||
}
|
||||
.recharge-box {
|
||||
position: relative;
|
||||
padding: 0 30rpx;
|
||||
margin-top: -60rpx;
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
width: 620rpx;
|
||||
height: 86rpx;
|
||||
border-radius: 44rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.save-btn {
|
||||
width: 620rpx;
|
||||
height: 86rpx;
|
||||
border-radius: 44rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.recharge-card-box {
|
||||
width: 690rpx;
|
||||
background: var(--ui-BG);
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
.recharge-card-box {
|
||||
width: 690rpx;
|
||||
background: var(--ui-BG);
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.input-label {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
.input-label {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.unit {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 48rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
.unit {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 48rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.uni-easyinput__placeholder-class {
|
||||
font-size: 30rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.uni-easyinput__placeholder-class {
|
||||
font-size: 30rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:deep(.uni-easyinput__content-input) {
|
||||
font-size: 48rpx;
|
||||
}
|
||||
:deep(.uni-easyinput__content-input) {
|
||||
font-size: 48rpx;
|
||||
}
|
||||
|
||||
.face-value-btn {
|
||||
width: 200rpx;
|
||||
height: 144rpx;
|
||||
border: 1px solid var(--ui-BG-Main);
|
||||
border-radius: 10rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-bottom: 15rpx;
|
||||
margin-right: 15rpx;
|
||||
.face-value-btn {
|
||||
width: 200rpx;
|
||||
height: 144rpx;
|
||||
border: 1px solid var(--ui-BG-Main);
|
||||
border-radius: 10rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-bottom: 15rpx;
|
||||
margin-right: 15rpx;
|
||||
|
||||
&:nth-of-type(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
&:nth-of-type(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.face-value-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 500;
|
||||
color: var(--ui-BG-Main);
|
||||
font-family: OPPOSANS;
|
||||
.face-value-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 500;
|
||||
color: var(--ui-BG-Main);
|
||||
font-family: OPPOSANS;
|
||||
|
||||
&::after {
|
||||
content: '元';
|
||||
font-size: 24rpx;
|
||||
margin-left: 6rpx;
|
||||
}
|
||||
}
|
||||
&::after {
|
||||
content: '元';
|
||||
font-size: 24rpx;
|
||||
margin-left: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.face-value-tag {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
height: 40rpx;
|
||||
line-height: 40rpx;
|
||||
background: var(--ui-BG-Main);
|
||||
opacity: 0.8;
|
||||
border-radius: 10rpx 0 20rpx 0;
|
||||
top: 0;
|
||||
left: -2rpx;
|
||||
padding: 0 16rpx;
|
||||
font-size: 22rpx;
|
||||
color: $white;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
.face-value-tag {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
height: 40rpx;
|
||||
line-height: 40rpx;
|
||||
background: var(--ui-BG-Main);
|
||||
opacity: 0.8;
|
||||
border-radius: 10rpx 0 20rpx 0;
|
||||
top: 0;
|
||||
left: -2rpx;
|
||||
padding: 0 16rpx;
|
||||
font-size: 22rpx;
|
||||
color: $white;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--ui-BG-Main);
|
||||
opacity: 0.1;
|
||||
z-index: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
&::before {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--ui-BG-Main);
|
||||
opacity: 0.1;
|
||||
z-index: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-active {
|
||||
z-index: 1;
|
||||
.btn-active {
|
||||
z-index: 1;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
background: var(--ui-BG-Main);
|
||||
opacity: 1;
|
||||
}
|
||||
&::before {
|
||||
content: '';
|
||||
background: var(--ui-BG-Main);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.face-value-title {
|
||||
color: $white;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
.face-value-title {
|
||||
color: $white;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.face-value-tag {
|
||||
background: $white;
|
||||
color: var(--ui-BG-Main);
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.face-value-tag {
|
||||
background: $white;
|
||||
color: var(--ui-BG-Main);
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+48
-15
@@ -39,7 +39,6 @@
|
||||
<button class="check-btn ss-reset-button" v-if="payResult === 'success'" @tap="onOrder">
|
||||
查看订单
|
||||
</button>
|
||||
<!-- TODO 芋艿:拼团接入 -->
|
||||
<button
|
||||
class="check-btn ss-reset-button"
|
||||
v-if="payResult === 'success' && state.tradeOrder.type === 3"
|
||||
@@ -49,9 +48,11 @@
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- TODO 芋艿:订阅 -->
|
||||
<!-- #ifdef MP -->
|
||||
<view class="subscribe-box ss-flex ss-m-t-44">
|
||||
<view
|
||||
class="subscribe-box ss-flex ss-m-t-44"
|
||||
v-if="showSubscribeBtn && state.orderType === 'goods'"
|
||||
>
|
||||
<image class="subscribe-img" :src="sheep.$url.static('/static/img/shop/order/cargo.png')" />
|
||||
<view class="subscribe-title ss-m-r-48 ss-m-l-16">获取实时发货信息与订单状态</view>
|
||||
<view class="subscribe-start" @tap="subscribeMessage">立即订阅</view>
|
||||
@@ -63,12 +64,13 @@
|
||||
|
||||
<script setup>
|
||||
import { onLoad, onHide, onShow } from '@dcloudio/uni-app';
|
||||
import { reactive, computed } from 'vue';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { reactive, computed, ref } from 'vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import sheep from '@/sheep';
|
||||
import PayOrderApi from '@/sheep/api/pay/order';
|
||||
import { fen2yuan } from '../../sheep/hooks/useGoods';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import { WxaSubscribeTemplate } from '@/sheep/util/const';
|
||||
|
||||
const state = reactive({
|
||||
id: 0, // 支付单号
|
||||
@@ -111,11 +113,23 @@
|
||||
// 非待支付,可能是已支付,可能是已退款
|
||||
state.result = 'paid';
|
||||
// #ifdef MP
|
||||
subscribeMessage();
|
||||
uni.showModal({
|
||||
title: '支付结果',
|
||||
showCancel: false, // 不要取消按钮
|
||||
content: '支付成功',
|
||||
success: () => {
|
||||
// 订阅只能由用户主动触发,只能包一层 showModal 诱导用户点击
|
||||
autoSubscribeMessage();
|
||||
},
|
||||
});
|
||||
|
||||
// #endif
|
||||
// 特殊:获得商品订单信息
|
||||
if (state.orderType === 'goods') {
|
||||
const { data, code } = await OrderApi.getOrder(state.orderInfo.merchantOrderId);
|
||||
const { data, code } = await OrderApi.getOrderDetail(
|
||||
state.orderInfo.merchantOrderId,
|
||||
true,
|
||||
);
|
||||
if (code === 0) {
|
||||
state.tradeOrder = data;
|
||||
}
|
||||
@@ -136,7 +150,6 @@
|
||||
}
|
||||
|
||||
function onOrder() {
|
||||
// TODO 芋艿:待测试
|
||||
if (state.orderType === 'recharge') {
|
||||
sheep.$router.redirect('/pages/pay/recharge-log');
|
||||
} else {
|
||||
@@ -144,15 +157,35 @@
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 芋艿:待测试
|
||||
// #ifdef MP
|
||||
const showSubscribeBtn = ref(false); // 默认隐藏
|
||||
const SUBSCRIBE_BTN_STATUS_STORAGE_KEY = 'subscribe_btn_status';
|
||||
function subscribeMessage() {
|
||||
let event = ['order_dispatched'];
|
||||
if (state.tradeOrder.type === 3) {
|
||||
event.push('groupon_finish');
|
||||
event.push('groupon_fail');
|
||||
if (state.orderType !== 'goods') {
|
||||
return;
|
||||
}
|
||||
sheep.$platform.useProvider('wechat').subscribeMessage(event);
|
||||
const event = [WxaSubscribeTemplate.TRADE_ORDER_DELIVERY];
|
||||
if (state.tradeOrder.type === 3) {
|
||||
event.push(WxaSubscribeTemplate.PROMOTION_COMBINATION_SUCCESS);
|
||||
}
|
||||
sheep.$platform.useProvider('wechat').subscribeMessage(event, () => {
|
||||
// 订阅后记录一下订阅状态
|
||||
uni.removeStorageSync(SUBSCRIBE_BTN_STATUS_STORAGE_KEY);
|
||||
uni.setStorageSync(SUBSCRIBE_BTN_STATUS_STORAGE_KEY, '已订阅');
|
||||
// 隐藏订阅按钮
|
||||
showSubscribeBtn.value = false;
|
||||
});
|
||||
}
|
||||
async function autoSubscribeMessage() {
|
||||
// 1. 校验是否手动订阅过
|
||||
const subscribeBtnStatus = uni.getStorageSync(SUBSCRIBE_BTN_STATUS_STORAGE_KEY);
|
||||
if (!subscribeBtnStatus) {
|
||||
showSubscribeBtn.value = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 订阅消息
|
||||
subscribeMessage();
|
||||
}
|
||||
// #endif
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
}
|
||||
}
|
||||
onLoad(() => {
|
||||
// TODO 芋艿:目前简单做,使用营销文章,作为 faq
|
||||
// TODO 芋艿:【文章】目前简单做,使用营销文章,作为 faq
|
||||
if (true) {
|
||||
sheep.$router.go('/pages/public/richtext', {
|
||||
title: '常见问题',
|
||||
|
||||
+230
-176
@@ -1,78 +1,118 @@
|
||||
<!-- 收货地址的新增/编辑 -->
|
||||
<template>
|
||||
<s-layout :title="state.model.id ? '编辑地址' : '新增地址'">
|
||||
<uni-forms ref="addressFormRef" v-model="state.model" :rules="rules" validateTrigger="bind"
|
||||
labelWidth="160" labelAlign="left" border :labelStyle="{ fontWeight: 'bold' }">
|
||||
<view class="bg-white form-box ss-p-x-30">
|
||||
<uni-forms-item name="name" label="收货人" class="form-item">
|
||||
<uni-easyinput v-model="state.model.name" placeholder="请填写收货人姓名" :inputBorder="false"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal" />
|
||||
</uni-forms-item>
|
||||
<s-layout :title="state.model.id ? '编辑地址' : '新增地址'">
|
||||
<uni-forms
|
||||
ref="addressFormRef"
|
||||
v-model="state.model"
|
||||
:rules="rules"
|
||||
validateTrigger="bind"
|
||||
labelWidth="160"
|
||||
labelAlign="left"
|
||||
border
|
||||
:labelStyle="{ fontWeight: 'bold' }"
|
||||
>
|
||||
<view class="bg-white form-box ss-p-x-30">
|
||||
<uni-forms-item name="name" label="收货人" class="form-item">
|
||||
<uni-easyinput
|
||||
v-model="state.model.name"
|
||||
placeholder="请填写收货人姓名"
|
||||
:inputBorder="false"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
|
||||
/>
|
||||
</uni-forms-item>
|
||||
|
||||
<uni-forms-item name="mobile" label="手机号" class="form-item">
|
||||
<uni-easyinput v-model="state.model.mobile" type="number" placeholder="请输入手机号" :inputBorder="false"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal">
|
||||
</uni-easyinput>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item name="areaName" label="省市区" @tap="state.showRegion = true" class="form-item">
|
||||
<uni-easyinput v-model="state.model.areaName" disabled :inputBorder="false"
|
||||
:styles="{ disableColor: '#fff', color: '#333' }"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
|
||||
placeholder="请选择省市区">
|
||||
<template v-slot:right>
|
||||
<uni-icons type="right" />
|
||||
</template>
|
||||
</uni-easyinput>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item name="detailAddress" label="详细地址" :formItemStyle="{ alignItems: 'flex-start' }"
|
||||
:labelStyle="{ lineHeight: '5em' }" class="textarea-item">
|
||||
<uni-easyinput :inputBorder="false" type="textarea" v-model="state.model.detailAddress"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
|
||||
placeholder="请输入详细地址" clearable />
|
||||
</uni-forms-item>
|
||||
</view>
|
||||
<view class="ss-m-y-20 bg-white ss-p-x-30 ss-flex ss-row-between ss-col-center default-box">
|
||||
<view class="default-box-title"> 设为默认地址 </view>
|
||||
<su-switch style="transform: scale(0.8)" v-model="state.model.defaultStatus" />
|
||||
</view>
|
||||
</uni-forms>
|
||||
<su-fixed bottom :opacity="false" bg="" placeholder :noFixed="false" :index="10">
|
||||
<view class="footer-box ss-flex-col ss-row-between ss-p-20">
|
||||
<view class="ss-m-b-20">
|
||||
<uni-forms-item name="mobile" label="手机号" class="form-item">
|
||||
<uni-easyinput
|
||||
v-model="state.model.mobile"
|
||||
type="number"
|
||||
placeholder="请输入手机号"
|
||||
:inputBorder="false"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
|
||||
>
|
||||
</uni-easyinput>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item
|
||||
name="areaName"
|
||||
label="省市区"
|
||||
@tap="state.showRegion = true"
|
||||
class="form-item"
|
||||
>
|
||||
<uni-easyinput
|
||||
v-model="state.model.areaName"
|
||||
disabled
|
||||
:inputBorder="false"
|
||||
:styles="{ disableColor: '#fff', color: '#333' }"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
|
||||
placeholder="请选择省市区"
|
||||
>
|
||||
<template v-slot:right>
|
||||
<uni-icons type="right" />
|
||||
</template>
|
||||
</uni-easyinput>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item
|
||||
name="detailAddress"
|
||||
label="详细地址"
|
||||
:formItemStyle="{ alignItems: 'flex-start' }"
|
||||
:labelStyle="{ lineHeight: '5em' }"
|
||||
class="textarea-item"
|
||||
>
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
type="textarea"
|
||||
v-model="state.model.detailAddress"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
|
||||
placeholder="请输入详细地址"
|
||||
clearable
|
||||
/>
|
||||
</uni-forms-item>
|
||||
</view>
|
||||
<view class="ss-m-y-20 bg-white ss-p-x-30 ss-flex ss-row-between ss-col-center default-box">
|
||||
<view class="default-box-title"> 设为默认地址 </view>
|
||||
<su-switch style="transform: scale(0.8)" v-model="state.model.defaultStatus" />
|
||||
</view>
|
||||
</uni-forms>
|
||||
<su-fixed bottom :opacity="false" bg="" placeholder :noFixed="false" :index="10">
|
||||
<view class="footer-box ss-flex-col ss-row-between ss-p-20">
|
||||
<view class="ss-m-b-20">
|
||||
<button class="ss-reset-button save-btn ui-Shadow-Main" @tap="onSave">保存</button>
|
||||
</view>
|
||||
<button v-if="state.model.id" class="ss-reset-button cancel-btn" @tap="onDelete">
|
||||
删除
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
<button v-if="state.model.id" class="ss-reset-button cancel-btn" @tap="onDelete">
|
||||
删除
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
|
||||
<!-- 省市区弹窗 -->
|
||||
<su-region-picker :show="state.showRegion" @cancel="state.showRegion = false" @confirm="onRegionConfirm" />
|
||||
</s-layout>
|
||||
<!-- 省市区弹窗 -->
|
||||
<su-region-picker
|
||||
:show="state.showRegion"
|
||||
@cancel="state.showRegion = false"
|
||||
@confirm="onRegionConfirm"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, unref } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import _ from 'lodash';
|
||||
import { mobile } from '@/sheep/validate/form';
|
||||
import { ref, reactive, unref } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import _ from 'lodash-es';
|
||||
import { mobile } from '@/sheep/validate/form';
|
||||
import AreaApi from '@/sheep/api/system/area';
|
||||
import AddressApi from '@/sheep/api/member/address';
|
||||
|
||||
const addressFormRef = ref(null);
|
||||
const state = reactive({
|
||||
showRegion: false,
|
||||
model: {
|
||||
name: '',
|
||||
mobile: '',
|
||||
const addressFormRef = ref(null);
|
||||
const state = reactive({
|
||||
showRegion: false,
|
||||
model: {
|
||||
name: '',
|
||||
mobile: '',
|
||||
detailAddress: '',
|
||||
defaultStatus: false,
|
||||
defaultStatus: false,
|
||||
areaName: '',
|
||||
},
|
||||
},
|
||||
rules: {},
|
||||
});
|
||||
});
|
||||
|
||||
const rules = {
|
||||
name: {
|
||||
@@ -85,167 +125,181 @@
|
||||
},
|
||||
mobile,
|
||||
detailAddress: {
|
||||
rules: [{
|
||||
required: true,
|
||||
errorMessage: '请输入详细地址',
|
||||
}]
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
errorMessage: '请输入详细地址',
|
||||
},
|
||||
],
|
||||
},
|
||||
areaName: {
|
||||
rules: [{
|
||||
required: true,
|
||||
errorMessage: '请选择您的位置'
|
||||
}]
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
errorMessage: '请选择您的位置',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
// 确认选择地区
|
||||
const onRegionConfirm = (e) => {
|
||||
state.model.areaName = `${e.province_name} ${e.city_name} ${e.district_name}`
|
||||
const onRegionConfirm = (e) => {
|
||||
state.model.areaName = `${e.province_name} ${e.city_name} ${e.district_name}`;
|
||||
state.model.areaId = e.district_id;
|
||||
state.showRegion = false;
|
||||
};
|
||||
state.showRegion = false;
|
||||
};
|
||||
|
||||
// 获得地区数据
|
||||
const getAreaData = () => {
|
||||
if (_.isEmpty(uni.getStorageSync('areaData'))) {
|
||||
const getAreaData = () => {
|
||||
if (_.isEmpty(uni.getStorageSync('areaData'))) {
|
||||
AreaApi.getAreaTree().then((res) => {
|
||||
if (res.code === 0) {
|
||||
uni.setStorageSync('areaData', res.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// 保存收货地址
|
||||
const onSave = async () => {
|
||||
const onSave = async () => {
|
||||
// 参数校验
|
||||
const validate = await unref(addressFormRef)
|
||||
.validate()
|
||||
.catch((error) => {
|
||||
console.log('error: ', error);
|
||||
});
|
||||
if (!validate) {
|
||||
const validate = await unref(addressFormRef)
|
||||
.validate()
|
||||
.catch((error) => {
|
||||
console.log('error: ', error);
|
||||
});
|
||||
if (!validate) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 提交请求
|
||||
const formData = {
|
||||
...state.model
|
||||
...state.model,
|
||||
};
|
||||
const { code } =
|
||||
state.model.id > 0
|
||||
? await AddressApi.updateAddress(formData)
|
||||
: await AddressApi.createAddress(formData);
|
||||
if (code === 0) {
|
||||
sheep.$router.back();
|
||||
}
|
||||
const {code } = state.model.id > 0 ? await AddressApi.updateAddress(formData)
|
||||
: await AddressApi.createAddress(formData);
|
||||
if (code === 0) {
|
||||
sheep.$router.back();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// 删除收货地址
|
||||
const onDelete = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认删除此收货地址吗?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const onDelete = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认删除此收货地址吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await AddressApi.deleteAddress(state.model.id);
|
||||
if (code === 0) {
|
||||
sheep.$router.back();
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
onLoad(async (options) => {
|
||||
onLoad(async (options) => {
|
||||
// 获得地区数据
|
||||
getAreaData();
|
||||
getAreaData();
|
||||
// 情况一:基于 id 获得收件地址
|
||||
if (options.id) {
|
||||
let { code, data} = await AddressApi.getAddress(options.id);
|
||||
if (options.id) {
|
||||
let { code, data } = await AddressApi.getAddress(options.id);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.model = data;
|
||||
}
|
||||
// 情况二:微信导入 TODO 芋艿:待接入
|
||||
if (options.data) {
|
||||
let data = JSON.parse(options.data);
|
||||
const areaData = uni.getStorageSync('areaData');
|
||||
let provinceArr = areaData.filter(item => item.name == data.province_name);
|
||||
data.province_id = provinceArr[0].id;
|
||||
let provinceArr2 = provinceArr[0].children.filter(item => item.name == data.city_name);
|
||||
data.city_id = provinceArr2[0].id;
|
||||
let provinceArr3 = provinceArr2[0].children.filter(item => item.name == data.district_name);
|
||||
data.district_id = provinceArr3[0].id;
|
||||
state.model = {
|
||||
...state.model,
|
||||
...data,
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
// 情况二:微信导入
|
||||
if (options.data) {
|
||||
let data = JSON.parse(options.data);
|
||||
const areaData = uni.getStorageSync('areaData');
|
||||
const findAreaByName = (areas, name) => areas.find((item) => item.name === name);
|
||||
|
||||
let provinceObj = findAreaByName(areaData, data.province_name);
|
||||
let cityObj = provinceObj ? findAreaByName(provinceObj.children, data.city_name) : undefined;
|
||||
let districtObj = cityObj ? findAreaByName(cityObj.children, data.district_name) : undefined;
|
||||
let areaId = (districtObj || cityObj || provinceObj).id;
|
||||
|
||||
state.model = {
|
||||
...state.model,
|
||||
areaId,
|
||||
areaName: [data.province_name, data.city_name, data.district_name]
|
||||
.filter(Boolean)
|
||||
.join(' '),
|
||||
defaultStatus: false,
|
||||
detailAddress: data.address,
|
||||
mobile: data.mobile,
|
||||
name: data.consignee,
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
.uni-forms-item__label .label-text {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
:deep() {
|
||||
.uni-forms-item__label .label-text {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
|
||||
.uni-easyinput__content-input {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
.uni-easyinput__content-input {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
|
||||
.uni-easyinput__content-textarea {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
margin-top: 8rpx !important;
|
||||
}
|
||||
.uni-easyinput__content-textarea {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
margin-top: 8rpx !important;
|
||||
}
|
||||
|
||||
.uni-icons {
|
||||
font-size: 40rpx !important;
|
||||
}
|
||||
.uni-icons {
|
||||
font-size: 40rpx !important;
|
||||
}
|
||||
|
||||
.is-textarea-icon {
|
||||
margin-top: 22rpx;
|
||||
}
|
||||
.is-textarea-icon {
|
||||
margin-top: 22rpx;
|
||||
}
|
||||
|
||||
.is-disabled {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
.is-disabled {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.default-box {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
height: 100rpx;
|
||||
.default-box {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
height: 100rpx;
|
||||
|
||||
.default-box-title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
.default-box-title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-box {
|
||||
.save-btn {
|
||||
width: 710rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
color: $white;
|
||||
}
|
||||
.footer-box {
|
||||
.save-btn {
|
||||
width: 710rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
width: 710rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: var(--ui-BG);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.cancel-btn {
|
||||
width: 710rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: var(--ui-BG);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+147
-125
@@ -1,143 +1,165 @@
|
||||
<!-- 收件地址列表 -->
|
||||
<template>
|
||||
<s-layout title="收货地址" :bgStyle="{ color: '#FFF' }">
|
||||
<view v-if="state.list.length">
|
||||
<s-address-item hasBorderBottom v-for="item in state.list" :key="item.id" :item="item"
|
||||
@tap="onSelect(item)" />
|
||||
</view>
|
||||
<s-layout title="收货地址" :bgStyle="{ color: '#FFF' }">
|
||||
<view v-if="state.list.length">
|
||||
<s-address-item
|
||||
hasBorderBottom
|
||||
v-for="item in state.list"
|
||||
:key="item.id"
|
||||
:item="item"
|
||||
@tap="onSelect(item)"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<su-fixed bottom placeholder>
|
||||
<view class="footer-box ss-flex ss-row-between ss-p-20">
|
||||
<!-- 微信小程序和微信H5 -->
|
||||
<button v-if="['WechatMiniProgram', 'WechatOfficialAccount'].includes(sheep.$platform.name)"
|
||||
@tap="importWechatAddress"
|
||||
class="border ss-reset-button sync-wxaddress ss-m-20 ss-flex ss-row-center ss-col-center">
|
||||
<text class="cicon-weixin ss-p-r-10" style="color: #09bb07; font-size: 40rpx"></text>
|
||||
导入微信地址
|
||||
</button>
|
||||
<button class="add-btn ss-reset-button ui-Shadow-Main"
|
||||
@tap="sheep.$router.go('/pages/user/address/edit')">
|
||||
新增收货地址
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
<s-empty v-if="state.list.length === 0 && !state.loading" text="暂无收货地址" icon="/static/data-empty.png" />
|
||||
</s-layout>
|
||||
<su-fixed bottom placeholder>
|
||||
<view class="footer-box ss-flex ss-row-between ss-p-20">
|
||||
<!-- 微信小程序和微信H5 -->
|
||||
<button
|
||||
v-if="['WechatMiniProgram', 'WechatOfficialAccount'].includes(sheep.$platform.name)"
|
||||
@tap="importWechatAddress"
|
||||
class="border ss-reset-button sync-wxaddress ss-m-20 ss-flex ss-row-center ss-col-center"
|
||||
>
|
||||
<text class="cicon-weixin ss-p-r-10" style="color: #09bb07; font-size: 40rpx"></text>
|
||||
导入微信地址
|
||||
</button>
|
||||
<button
|
||||
class="add-btn ss-reset-button ui-Shadow-Main"
|
||||
@tap="sheep.$router.go('/pages/user/address/edit')"
|
||||
>
|
||||
新增收货地址
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
<s-empty
|
||||
v-if="state.list.length === 0 && !state.loading"
|
||||
text="暂无收货地址"
|
||||
icon="/static/data-empty.png"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, onBeforeMount } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { onBeforeMount, reactive } from 'vue';
|
||||
import { onShow, onLoad } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import AreaApi from '@/sheep/api/system/area';
|
||||
import AddressApi from '@/sheep/api/member/address';
|
||||
|
||||
const state = reactive({
|
||||
list: [], // 地址列表
|
||||
loading: true,
|
||||
});
|
||||
const state = reactive({
|
||||
list: [], // 地址列表
|
||||
loading: true,
|
||||
openType: '', // 页面打开类型
|
||||
});
|
||||
|
||||
// 选择收货地址
|
||||
const onSelect = (addressInfo) => {
|
||||
uni.$emit('SELECT_ADDRESS', {
|
||||
addressInfo,
|
||||
});
|
||||
sheep.$router.back();
|
||||
};
|
||||
// 选择收货地址
|
||||
const onSelect = (addressInfo) => {
|
||||
if (state.openType !== 'select'){ // 不作为选择组件时阻断操作
|
||||
return
|
||||
}
|
||||
uni.$emit('SELECT_ADDRESS', {
|
||||
addressInfo,
|
||||
});
|
||||
sheep.$router.back();
|
||||
};
|
||||
|
||||
// 导入微信地址
|
||||
// TODO 芋艿:未测试
|
||||
function importWechatAddress() {
|
||||
let wechatAddress = {};
|
||||
// #ifdef MP
|
||||
uni.chooseAddress({
|
||||
success: (res) => {
|
||||
wechatAddress = {
|
||||
consignee: res.userName,
|
||||
mobile: res.telNumber,
|
||||
province_name: res.provinceName,
|
||||
city_name: res.cityName,
|
||||
district_name: res.countyName,
|
||||
address: res.detailInfo,
|
||||
region: '',
|
||||
is_default: false,
|
||||
};
|
||||
if (!isEmpty(wechatAddress)) {
|
||||
sheep.$router.go('/pages/user/address/edit', {
|
||||
data: JSON.stringify(wechatAddress),
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('%cuni.chooseAddress,调用失败', 'color:green;background:yellow');
|
||||
},
|
||||
});
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
sheep.$platform.useProvider('wechat').jssdk.openAddress({
|
||||
success: (res) => {
|
||||
wechatAddress = {
|
||||
consignee: res.userName,
|
||||
mobile: res.telNumber,
|
||||
province_name: res.provinceName,
|
||||
city_name: res.cityName,
|
||||
district_name: res.countryName,
|
||||
address: res.detailInfo,
|
||||
region: '',
|
||||
is_default: false,
|
||||
};
|
||||
if (!isEmpty(wechatAddress)) {
|
||||
sheep.$router.go('/pages/user/address/edit', {
|
||||
data: JSON.stringify(wechatAddress),
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
// #endif
|
||||
}
|
||||
// 导入微信地址
|
||||
function importWechatAddress() {
|
||||
let wechatAddress = {};
|
||||
// #ifdef MP
|
||||
uni.chooseAddress({
|
||||
success: (res) => {
|
||||
wechatAddress = {
|
||||
consignee: res.userName,
|
||||
mobile: res.telNumber,
|
||||
province_name: res.provinceName,
|
||||
city_name: res.cityName,
|
||||
district_name: res.countyName,
|
||||
address: res.detailInfo,
|
||||
region: '',
|
||||
is_default: false,
|
||||
};
|
||||
if (!isEmpty(wechatAddress)) {
|
||||
sheep.$router.go('/pages/user/address/edit', {
|
||||
data: JSON.stringify(wechatAddress),
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('%cuni.chooseAddress,调用失败', 'color:green;background:yellow');
|
||||
},
|
||||
});
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
sheep.$platform.useProvider('wechat').jssdk.openAddress({
|
||||
success: (res) => {
|
||||
wechatAddress = {
|
||||
consignee: res.userName,
|
||||
mobile: res.telNumber,
|
||||
province_name: res.provinceName,
|
||||
city_name: res.cityName,
|
||||
district_name: res.countryName,
|
||||
address: res.detailInfo,
|
||||
region: '',
|
||||
is_default: false,
|
||||
};
|
||||
if (!isEmpty(wechatAddress)) {
|
||||
sheep.$router.go('/pages/user/address/edit', {
|
||||
data: JSON.stringify(wechatAddress),
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
// #endif
|
||||
}
|
||||
|
||||
onShow(async () => {
|
||||
state.list = (await AddressApi.getAddressList()).data;
|
||||
state.loading = false;
|
||||
});
|
||||
onLoad((option) => {
|
||||
if (option.type) {
|
||||
state.openType = option.type;
|
||||
}
|
||||
});
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (!!uni.getStorageSync('areaData')) {
|
||||
return;
|
||||
}
|
||||
// 提前加载省市区数据
|
||||
onShow(async () => {
|
||||
state.list = (await AddressApi.getAddressList()).data;
|
||||
state.loading = false;
|
||||
});
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (!!uni.getStorageSync('areaData')) {
|
||||
return;
|
||||
}
|
||||
// 提前加载省市区数据
|
||||
AreaApi.getAreaTree().then((res) => {
|
||||
if (res.code === 0) {
|
||||
uni.setStorageSync('areaData', res.data);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (res.code === 0) {
|
||||
uni.setStorageSync('areaData', res.data);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.footer-box {
|
||||
.add-btn {
|
||||
flex: 1;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
border-radius: 80rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
line-height: 80rpx;
|
||||
color: $white;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.footer-box {
|
||||
.add-btn {
|
||||
flex: 1;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
border-radius: 80rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
line-height: 80rpx;
|
||||
color: $white;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.sync-wxaddress {
|
||||
flex: 1;
|
||||
line-height: 80rpx;
|
||||
background: $white;
|
||||
border-radius: 80rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: $dark-6;
|
||||
margin-right: 18rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.sync-wxaddress {
|
||||
flex: 1;
|
||||
line-height: 80rpx;
|
||||
background: $white;
|
||||
border-radius: 80rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: $dark-6;
|
||||
margin-right: 18rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -5,7 +5,8 @@
|
||||
<!-- 头部 -->
|
||||
<view class="cart-header ss-flex ss-col-center ss-row-between ss-p-x-30">
|
||||
<view class="header-left ss-flex ss-col-center ss-font-26">
|
||||
共 <text class="goods-number ui-TC-Main ss-flex">{{ state.pagination.total }}</text> 件商品
|
||||
共
|
||||
<text class="goods-number ui-TC-Main ss-flex">{{ state.pagination.total }}</text> 件商品
|
||||
</view>
|
||||
<view class="header-right">
|
||||
<button
|
||||
@@ -77,7 +78,8 @@
|
||||
<view class="footer-right">
|
||||
<button
|
||||
class="ss-reset-button ui-BG-Main-Gradient pay-btn ss-font-28 ui-Shadow-Main"
|
||||
@tap="onCancel">
|
||||
@tap="onCancel"
|
||||
>
|
||||
取消收藏
|
||||
</button>
|
||||
</view>
|
||||
@@ -100,7 +102,7 @@
|
||||
import sheep from '@/sheep';
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import FavoriteApi from '@/sheep/api/product/favorite';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
@@ -129,7 +131,7 @@
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list)
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
@@ -174,7 +176,7 @@
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getData();
|
||||
|
||||
@@ -81,11 +81,13 @@
|
||||
</view>
|
||||
<view class="footer-right ss-flex">
|
||||
<button
|
||||
:class="['ss-reset-button pay-btn ss-font-28 ',
|
||||
{
|
||||
'ui-BG-Main-Gradient': state.selectedSpuIdList.length > 0,
|
||||
'ui-Shadow-Main': state.selectedSpuIdList.length > 0
|
||||
}]"
|
||||
:class="[
|
||||
'ss-reset-button pay-btn ss-font-28 ',
|
||||
{
|
||||
'ui-BG-Main-Gradient': state.selectedSpuIdList.length > 0,
|
||||
'ui-Shadow-Main': state.selectedSpuIdList.length > 0,
|
||||
},
|
||||
]"
|
||||
@tap="onDelete"
|
||||
>
|
||||
删除足迹
|
||||
@@ -120,9 +122,9 @@
|
||||
import sheep from '@/sheep';
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import _ from 'lodash';
|
||||
import SpuHistoryApi from "@/sheep/api/product/history";
|
||||
import {cloneDeep} from "@/sheep/helper/utils";
|
||||
import _ from 'lodash-es';
|
||||
import SpuHistoryApi from '@/sheep/api/product/history';
|
||||
import { cloneDeep } from '@/sheep/helper/utils';
|
||||
|
||||
const sys_navBar = sheep.$platform.navbar;
|
||||
const pagination = {
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
<template>
|
||||
<s-layout title="选择自提门店" :bgStyle="{ color: '#FFF' }">
|
||||
<view class="storeBox" ref="container">
|
||||
<view
|
||||
class="storeBox-box"
|
||||
v-for="(item, index) in state.storeList"
|
||||
:key="index"
|
||||
@tap="checked(item)"
|
||||
>
|
||||
<view class="store-img">
|
||||
<image :src="item.logo" class="img" />
|
||||
</view>
|
||||
<view class="store-cent-left">
|
||||
<view class="store-name">{{ item.name }}</view>
|
||||
<view class="store-address line1">
|
||||
{{ item.areaName }}{{ ', ' + item.detailAddress }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="row-right ss-flex-col ss-col-center">
|
||||
<view>
|
||||
<!-- #ifdef H5 -->
|
||||
<a class="store-phone" :href="'tel:' + item.phone">
|
||||
<view class="iconfont">
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</a>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP -->
|
||||
<view class="store-phone" @click="call(item.phone)">
|
||||
<view class="iconfont">
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view class="store-distance ss-flex ss-row-center" @tap.stop="showMaoLocation(item)">
|
||||
<text class="addressTxt" v-if="item.distance">
|
||||
距离{{ item.distance.toFixed(2) }}千米
|
||||
</text>
|
||||
<text class="addressTxt" v-else>查看地图</text>
|
||||
<view class="iconfont">
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import DeliveryApi from '@/sheep/api/trade/delivery';
|
||||
import { onMounted, reactive } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const LONGITUDE = 'user_longitude';
|
||||
const LATITUDE = 'user_latitude';
|
||||
const state = reactive({
|
||||
loaded: false,
|
||||
loading: false,
|
||||
storeList: [],
|
||||
system_store: {},
|
||||
locationShow: false,
|
||||
user_latitude: 0,
|
||||
user_longitude: 0,
|
||||
});
|
||||
|
||||
const call = (phone) => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: phone,
|
||||
});
|
||||
};
|
||||
const selfLocation = () => {
|
||||
// #ifdef H5
|
||||
const jsWxSdk = sheep.$platform.useProvider('wechat').jsWxSdk;
|
||||
if (jsWxSdk.isWechat()) {
|
||||
jsWxSdk.getLocation((res) => {
|
||||
state.user_latitude = res.latitude;
|
||||
state.user_longitude = res.longitude;
|
||||
uni.setStorageSync(LATITUDE, res.latitude);
|
||||
uni.setStorageSync(LONGITUDE, res.longitude);
|
||||
getList();
|
||||
});
|
||||
} else {
|
||||
// #endif
|
||||
uni.getLocation({
|
||||
type: 'gcj02',
|
||||
success: (res) => {
|
||||
try {
|
||||
state.user_latitude = res.latitude;
|
||||
state.user_longitude = res.longitude;
|
||||
uni.setStorageSync(LATITUDE, res.latitude);
|
||||
uni.setStorageSync(LONGITUDE, res.longitude);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
getList();
|
||||
},
|
||||
complete: () => {
|
||||
getList();
|
||||
},
|
||||
});
|
||||
// #ifdef H5
|
||||
}
|
||||
// #endif
|
||||
};
|
||||
const showMaoLocation = (e) => {
|
||||
// #ifdef H5
|
||||
const jsWxSdk = sheep.$platform.useProvider('wechat').jsWxSdk;
|
||||
if (jsWxSdk.isWechat()) {
|
||||
jsWxSdk.openLocation({
|
||||
latitude: Number(e.latitude),
|
||||
longitude: Number(e.longitude),
|
||||
name: e.name,
|
||||
address: `${e.areaName}-${e.detailAddress}`,
|
||||
});
|
||||
} else {
|
||||
// #endif
|
||||
uni.openLocation({
|
||||
latitude: Number(e.latitude),
|
||||
longitude: Number(e.longitude),
|
||||
name: e.name,
|
||||
address: `${e.areaName}-${e.detailAddress}`,
|
||||
success: function () {
|
||||
console.log('success');
|
||||
},
|
||||
});
|
||||
// #ifdef H5
|
||||
}
|
||||
// #endif
|
||||
};
|
||||
|
||||
/**
|
||||
* 选中门店
|
||||
*/
|
||||
const checked = (addressInfo) => {
|
||||
uni.$emit('SELECT_PICK_UP_INFO', {
|
||||
addressInfo,
|
||||
});
|
||||
sheep.$router.back();
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取门店列表数据
|
||||
*/
|
||||
const getList = async () => {
|
||||
if (state.loading || state.loaded) {
|
||||
return;
|
||||
}
|
||||
state.loading = true;
|
||||
const { data, code } = await DeliveryApi.getDeliveryPickUpStoreList({
|
||||
latitude: state.user_latitude,
|
||||
longitude: state.user_longitude,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.loading = false;
|
||||
state.storeList = data;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (state.user_latitude && state.user_longitude) {
|
||||
getList();
|
||||
} else {
|
||||
selfLocation();
|
||||
getList();
|
||||
}
|
||||
});
|
||||
onLoad(() => {
|
||||
try {
|
||||
state.user_latitude = uni.getStorageSync(LATITUDE);
|
||||
state.user_longitude = uni.getStorageSync(LONGITUDE);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.line1 {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.geoPage {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.storeBox {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.storeBox-box {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 23rpx 0;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.store-cent {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.store-cent-left {
|
||||
//width: 45%;
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.store-img {
|
||||
flex: 1;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 6rpx;
|
||||
margin-right: 22rpx;
|
||||
}
|
||||
|
||||
.store-img .img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.store-name {
|
||||
color: #282828;
|
||||
font-size: 30rpx;
|
||||
margin-bottom: 22rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.store-address {
|
||||
color: #666666;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.store-phone {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
text-align: center;
|
||||
line-height: 48rpx;
|
||||
background-color: #e83323;
|
||||
margin-bottom: 22rpx;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.store-distance {
|
||||
font-size: 22rpx;
|
||||
color: #e83323;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-size: 20rpx;
|
||||
}
|
||||
|
||||
.row-right {
|
||||
flex: 2;
|
||||
//display: flex;
|
||||
//flex-direction: column;
|
||||
//align-items: flex-end;
|
||||
//width: 33.5%;
|
||||
}
|
||||
</style>
|
||||
+8
-9
@@ -26,7 +26,8 @@
|
||||
<button
|
||||
class="ss-reset-button avatar-action-btn"
|
||||
open-type="chooseAvatar"
|
||||
@chooseavatar="onChooseAvatar">
|
||||
@chooseavatar="onChooseAvatar"
|
||||
>
|
||||
修改
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
@@ -154,10 +155,7 @@
|
||||
</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="info ss-flex ss-col-center" v-if="state.thirdInfo">
|
||||
<image
|
||||
class="avatar ss-m-r-20"
|
||||
:src="sheep.$url.cdn(state.thirdInfo.avatar)"
|
||||
/>
|
||||
<image class="avatar ss-m-r-20" :src="sheep.$url.cdn(state.thirdInfo.avatar)" />
|
||||
<text class="name">{{ state.thirdInfo.nickname }}</text>
|
||||
</view>
|
||||
<view class="bind-box ss-m-l-20">
|
||||
@@ -185,7 +183,7 @@
|
||||
<script setup>
|
||||
import { computed, reactive, onBeforeMount } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { clone } from 'lodash';
|
||||
import { clone } from 'lodash-es';
|
||||
import { showAuthModal } from '@/sheep/hooks/useModal';
|
||||
import FileApi from '@/sheep/api/infra/file';
|
||||
import UserApi from '@/sheep/api/member/user';
|
||||
@@ -198,14 +196,15 @@
|
||||
|
||||
const placeholderStyle = 'color:#BBBBBB;font-size:28rpx;line-height:normal';
|
||||
|
||||
const sexRadioMap = [{
|
||||
const sexRadioMap = [
|
||||
{
|
||||
name: '男',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
name: '女',
|
||||
value: '2',
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
const userInfo = computed(() => sheep.$store('user').userInfo);
|
||||
@@ -279,7 +278,7 @@
|
||||
|
||||
// 保存信息
|
||||
async function onSubmit() {
|
||||
const { code } = await UserApi.updateUser({
|
||||
const { code } = await UserApi.updateUser({
|
||||
avatar: state.model.avatar,
|
||||
nickname: state.model.nickname,
|
||||
sex: state.model.sex,
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
/>
|
||||
</view>
|
||||
<view class="ss-flex ss-row-between ss-col-center ss-m-t-64">
|
||||
<view class="money-num">{{ state.showMoney ? fen2yuan(userWallet.balance) : '*****' }}</view>
|
||||
<view class="money-num">{{
|
||||
state.showMoney ? fen2yuan(userWallet.balance) : '*****'
|
||||
}}</view>
|
||||
<button class="ss-reset-button topup-btn" @tap="sheep.$router.go('/pages/pay/recharge')">
|
||||
充值
|
||||
</button>
|
||||
@@ -24,7 +26,12 @@
|
||||
<su-sticky>
|
||||
<!-- 统计 -->
|
||||
<view class="filter-box ss-p-x-30 ss-flex ss-col-center ss-row-between">
|
||||
<uni-datetime-picker v-model="state.data" type="daterange" @change="onChangeTime" :end="state.today">
|
||||
<uni-datetime-picker
|
||||
v-model="state.data"
|
||||
type="daterange"
|
||||
@change="onChangeTime"
|
||||
:end="state.today"
|
||||
>
|
||||
<button class="ss-reset-button date-btn">
|
||||
<text>{{ dateFilterText }}</text>
|
||||
<text class="cicon-drop-down ss-seldate-icon"></text>
|
||||
@@ -82,7 +89,7 @@
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import dayjs from 'dayjs';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import PayWalletApi from '@/sheep/api/pay/wallet';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
@@ -98,7 +105,7 @@
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 8
|
||||
pageSize: 8,
|
||||
},
|
||||
summary: {
|
||||
totalIncome: 0,
|
||||
@@ -155,7 +162,7 @@
|
||||
// 获得钱包统计
|
||||
async function getSummary() {
|
||||
const { data, code } = await PayWalletApi.getWalletTransactionSummary({
|
||||
'createTime': [state.date[0] + ' 00:00:00', state.date[1] + ' 23:59:59'],
|
||||
createTime: [state.date[0] + ' 00:00:00', state.date[1] + ' 23:59:59'],
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
@@ -226,8 +233,7 @@
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: v-bind(headerBg)
|
||||
no-repeat;
|
||||
background: v-bind(headerBg) no-repeat;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
+19
-14
@@ -24,19 +24,24 @@
|
||||
<su-sticky :customNavHeight="sys_navBar">
|
||||
<!-- 统计 -->
|
||||
<view class="filter-box ss-p-x-30 ss-flex ss-col-center ss-row-between">
|
||||
<uni-datetime-picker v-model="state.date" type="daterange" @change="onChangeTime" :end="state.today">
|
||||
<button class="ss-reset-button date-btn">
|
||||
<text>{{ dateFilterText }}</text>
|
||||
<text class="cicon-drop-down ss-seldate-icon"></text>
|
||||
</button>
|
||||
</uni-datetime-picker>
|
||||
<uni-datetime-picker
|
||||
v-model="state.date"
|
||||
type="daterange"
|
||||
@change="onChangeTime"
|
||||
:end="state.today"
|
||||
>
|
||||
<button class="ss-reset-button date-btn">
|
||||
<text>{{ dateFilterText }}</text>
|
||||
<text class="cicon-drop-down ss-seldate-icon"></text>
|
||||
</button>
|
||||
</uni-datetime-picker>
|
||||
|
||||
<!-- TODO 芋艿:优化 -->
|
||||
<!-- <view class="total-box">-->
|
||||
<!-- <view class="ss-m-b-10">总收入¥{{ state.pagination.income }}</view>-->
|
||||
<!-- <view>总支出¥{{ -state.pagination.expense }}</view>-->
|
||||
<!-- </view>-->
|
||||
</view>
|
||||
<!-- TODO 芋艿:【钱包】可优化 -->
|
||||
<!-- <view class="total-box">-->
|
||||
<!-- <view class="ss-m-b-10">总收入¥{{ state.pagination.income }}</view>-->
|
||||
<!-- <view>总支出¥{{ -state.pagination.expense }}</view>-->
|
||||
<!-- </view>-->
|
||||
</view>
|
||||
<su-tabs
|
||||
:list="tabMaps"
|
||||
@change="onChange"
|
||||
@@ -83,7 +88,7 @@
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { computed, reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import dayjs from 'dayjs';
|
||||
import PointApi from '@/sheep/api/member/point';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
@@ -274,4 +279,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
+24
-3
@@ -1,4 +1,5 @@
|
||||
import { baseUrl, apiPath } from '@/sheep/config';
|
||||
import { baseUrl, apiPath, tenantId } from '@/sheep/config';
|
||||
import request from '@/sheep/request';
|
||||
|
||||
const FileApi = {
|
||||
// 上传文件
|
||||
@@ -15,8 +16,8 @@ const FileApi = {
|
||||
name: 'file',
|
||||
header: {
|
||||
// Accept: 'text/json',
|
||||
Accept : '*/*',
|
||||
'tenant-id' :'1',
|
||||
Accept: '*/*',
|
||||
'tenant-id': tenantId,
|
||||
// Authorization: 'Bearer test247',
|
||||
},
|
||||
success: (uploadFileRes) => {
|
||||
@@ -40,6 +41,26 @@ const FileApi = {
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// 获取文件预签名地址
|
||||
getFilePresignedUrl: (path) => {
|
||||
return request({
|
||||
url: '/infra/file/presigned-url',
|
||||
method: 'GET',
|
||||
params: {
|
||||
path,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 创建文件
|
||||
createFile: (data) => {
|
||||
return request({
|
||||
url: '/infra/file/create', // 请求的 URL
|
||||
method: 'POST', // 请求方法
|
||||
data: data, // 要发送的数据
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default FileApi;
|
||||
@@ -49,6 +49,28 @@ const SocialApi = {
|
||||
},
|
||||
});
|
||||
},
|
||||
// 获取订阅消息模板列表
|
||||
getSubscribeTemplateList: () =>
|
||||
request({
|
||||
url: '/member/social-user/get-subscribe-template-list',
|
||||
method: 'GET',
|
||||
custom: {
|
||||
showError: false,
|
||||
showLoading: false,
|
||||
},
|
||||
}),
|
||||
// 获取微信小程序码
|
||||
getWxaQrcode: async (path, query) => {
|
||||
return await request({
|
||||
url: '/member/social-user/wxa-qrcode',
|
||||
method: 'POST',
|
||||
data: {
|
||||
scene: query,
|
||||
path,
|
||||
checkPath: false, // TODO 开发环境暂不检查 path 是否存在
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default SocialApi;
|
||||
@@ -1,14 +0,0 @@
|
||||
import request from '@/sheep/request';
|
||||
|
||||
// TODO 芋艿:暂不支持 socket 聊天
|
||||
export default {
|
||||
// 获取聊天token
|
||||
unifiedToken: () =>
|
||||
request({
|
||||
url: 'unifiedToken',
|
||||
custom: {
|
||||
showError: false,
|
||||
showLoading: false,
|
||||
},
|
||||
}),
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
const files = import.meta.globEager('./*.js');
|
||||
const files = import.meta.glob('./*.js', { eager: true });
|
||||
let api = {};
|
||||
Object.keys(files).forEach((key) => {
|
||||
api = {
|
||||
|
||||
@@ -1,32 +1,6 @@
|
||||
import request from '@/sheep/request';
|
||||
import { baseUrl, apiPath } from '@/sheep/config';
|
||||
|
||||
export default {
|
||||
// 微信相关
|
||||
wechat: {
|
||||
// 小程序订阅消息
|
||||
subscribeTemplate: (params) =>
|
||||
request({
|
||||
url: 'third/wechat/subscribeTemplate',
|
||||
method: 'GET',
|
||||
params: {
|
||||
platform: 'miniProgram',
|
||||
},
|
||||
custom: {
|
||||
showError: false,
|
||||
showLoading: false,
|
||||
},
|
||||
}),
|
||||
|
||||
// 获取微信小程序码
|
||||
getWxacode: (path) =>
|
||||
`${baseUrl}${apiPath}third/wechat/wxacode?platform=miniProgram&payload=${encodeURIComponent(
|
||||
JSON.stringify({
|
||||
path,
|
||||
}),
|
||||
)}`,
|
||||
},
|
||||
|
||||
// 苹果相关
|
||||
apple: {
|
||||
// 第三方登录
|
||||
|
||||
@@ -2,11 +2,11 @@ import request from '@/sheep/request';
|
||||
|
||||
const PayOrderApi = {
|
||||
// 获得支付订单
|
||||
getOrder: (id) => {
|
||||
getOrder: (id, sync) => {
|
||||
return request({
|
||||
url: '/pay/order/get',
|
||||
method: 'GET',
|
||||
params: { id }
|
||||
params: { id, sync },
|
||||
});
|
||||
},
|
||||
// 提交支付订单
|
||||
@@ -14,9 +14,9 @@ const PayOrderApi = {
|
||||
return request({
|
||||
url: '/pay/order/submit',
|
||||
method: 'POST',
|
||||
data
|
||||
data,
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default PayOrderApi;
|
||||
@@ -13,6 +13,18 @@ const SpuApi = {
|
||||
},
|
||||
});
|
||||
},
|
||||
// 获得商品结算信息
|
||||
getSettlementProduct: (spuIds) => {
|
||||
return request({
|
||||
url: '/trade/order/settlement-product',
|
||||
method: 'GET',
|
||||
params: { spuIds },
|
||||
custom: {
|
||||
showLoading: false,
|
||||
showError: false,
|
||||
},
|
||||
});
|
||||
},
|
||||
// 获得商品 SPU 分页
|
||||
getSpuPage: (params) => {
|
||||
return request({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import request from '@/sheep/request';
|
||||
|
||||
const ActivityApi = {
|
||||
// 获得单个商品,近期参与的每个活动
|
||||
// 获得单个商品,进行中的拼团、秒杀、砍价活动信息
|
||||
getActivityListBySpuId: (spuId) => {
|
||||
return request({
|
||||
url: '/promotion/activity/list-by-spu-id',
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import request from '@/sheep/request';
|
||||
|
||||
const BargainApi = {
|
||||
// 获得砍价记录的概要信息
|
||||
getBargainRecordSummary: () => {
|
||||
return request({
|
||||
url: '/promotion/bargain-record/get-summary',
|
||||
method: 'GET',
|
||||
});
|
||||
},
|
||||
// 获得砍价活动分页
|
||||
getBargainActivityPage: () => {
|
||||
return request({
|
||||
url: '/promotion/bargain-activity/page',
|
||||
method: 'GET',
|
||||
});
|
||||
},
|
||||
// 获得砍价活动详情
|
||||
getBargainActivityDetail(params) {
|
||||
return request({
|
||||
url: '/promotion/bargain-activity/get-detail',
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default BargainApi;
|
||||
@@ -2,15 +2,6 @@ import request from '@/sheep/request';
|
||||
|
||||
// 拼团 API
|
||||
const CombinationApi = {
|
||||
// 获得拼团活动列表
|
||||
getCombinationActivityList: (count) => {
|
||||
return request({
|
||||
url: '/promotion/combination-activity/list',
|
||||
method: 'GET',
|
||||
params: { count },
|
||||
});
|
||||
},
|
||||
|
||||
// 获得拼团活动分页
|
||||
getCombinationActivityPage: (params) => {
|
||||
return request({
|
||||
@@ -31,6 +22,17 @@ const CombinationApi = {
|
||||
});
|
||||
},
|
||||
|
||||
// 获得拼团活动列表,基于活动编号数组
|
||||
getCombinationActivityListByIds: (ids) => {
|
||||
return request({
|
||||
url: '/promotion/combination-activity/list-by-ids',
|
||||
method: 'GET',
|
||||
params: {
|
||||
ids,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 获得最近 n 条拼团记录(团长发起的)
|
||||
getHeadCombinationRecordList: (activityId, status, count) => {
|
||||
return request({
|
||||
@@ -47,9 +49,9 @@ const CombinationApi = {
|
||||
// 获得我的拼团记录分页
|
||||
getCombinationRecordPage: (params) => {
|
||||
return request({
|
||||
url: "/promotion/combination-record/page",
|
||||
url: '/promotion/combination-record/page',
|
||||
method: 'GET',
|
||||
params
|
||||
params,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -79,23 +79,6 @@ const CouponApi = {
|
||||
},
|
||||
});
|
||||
},
|
||||
// 获得匹配指定商品的优惠劵列表
|
||||
getMatchCouponList: (price, spuIds, skuIds, categoryIds) => {
|
||||
return request({
|
||||
url: '/promotion/coupon/match-list',
|
||||
method: 'GET',
|
||||
params: {
|
||||
price,
|
||||
spuIds: spuIds.join(','),
|
||||
skuIds: skuIds.join(','),
|
||||
categoryIds: categoryIds.join(','),
|
||||
},
|
||||
custom: {
|
||||
showError: false,
|
||||
showLoading: false, // 避免影响 settlementOrder 结算的结果
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default CouponApi;
|
||||
@@ -0,0 +1,31 @@
|
||||
import request from '@/sheep/request';
|
||||
|
||||
const KeFuApi = {
|
||||
sendKefuMessage: (data) => {
|
||||
return request({
|
||||
url: '/promotion/kefu-message/send',
|
||||
method: 'POST',
|
||||
data,
|
||||
custom: {
|
||||
auth: true,
|
||||
showLoading: true,
|
||||
loadingMsg: '发送中',
|
||||
showSuccess: true,
|
||||
successMsg: '发送成功',
|
||||
},
|
||||
});
|
||||
},
|
||||
getKefuMessagePage: (params) => {
|
||||
return request({
|
||||
url: '/promotion/kefu-message/page',
|
||||
method: 'GET',
|
||||
params,
|
||||
custom: {
|
||||
auth: true,
|
||||
showLoading: false,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default KeFuApi;
|
||||
@@ -0,0 +1,30 @@
|
||||
import request from '@/sheep/request';
|
||||
|
||||
const PointApi = {
|
||||
// 获得积分商城活动分页
|
||||
getPointActivityPage: (params) => {
|
||||
return request({ url: 'promotion/point-activity/page', method: 'GET', params });
|
||||
},
|
||||
|
||||
// 获得积分商城活动列表,基于活动编号数组
|
||||
getPointActivityListByIds: (ids) => {
|
||||
return request({
|
||||
url: '/promotion/point-activity/list-by-ids',
|
||||
method: 'GET',
|
||||
params: {
|
||||
ids,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 获得积分商城活动明细
|
||||
getPointActivity: (id) => {
|
||||
return request({
|
||||
url: 'promotion/point-activity/get-detail',
|
||||
method: 'GET',
|
||||
params: { id },
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default PointApi;
|
||||
@@ -1,4 +1,4 @@
|
||||
import request from "@/sheep/request";
|
||||
import request from '@/sheep/request';
|
||||
|
||||
const SeckillApi = {
|
||||
// 获得秒杀时间段列表
|
||||
@@ -16,6 +16,17 @@ const SeckillApi = {
|
||||
return request({ url: 'promotion/seckill-activity/page', method: 'GET', params });
|
||||
},
|
||||
|
||||
// 获得秒杀活动列表,基于活动编号数组
|
||||
getSeckillActivityListByIds: (ids) => {
|
||||
return request({
|
||||
url: '/promotion/seckill-activity/list-by-ids',
|
||||
method: 'GET',
|
||||
params: {
|
||||
ids,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 获得秒杀活动明细
|
||||
* @param {number} id 秒杀活动编号
|
||||
@@ -25,9 +36,9 @@ const SeckillApi = {
|
||||
return request({
|
||||
url: 'promotion/seckill-activity/get-detail',
|
||||
method: 'GET',
|
||||
params: { id }
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default SeckillApi;
|
||||
@@ -0,0 +1,16 @@
|
||||
import request from '@/sheep/request';
|
||||
|
||||
const DictApi = {
|
||||
// 根据字典类型查询字典数据信息
|
||||
getDictDataListByType: (type) => {
|
||||
return request({
|
||||
url: `/system/dict-data/type`,
|
||||
method: 'GET',
|
||||
params: {
|
||||
type,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default DictApi;
|
||||
@@ -1,6 +1,14 @@
|
||||
import request from '@/sheep/request';
|
||||
|
||||
const BrokerageApi = {
|
||||
// 绑定分销用户
|
||||
bindBrokerageUser: (data)=>{
|
||||
return request({
|
||||
url: '/trade/brokerage-user/bind',
|
||||
method: 'PUT',
|
||||
data
|
||||
});
|
||||
},
|
||||
// 获得个人分销信息
|
||||
getBrokerageUser: () => {
|
||||
return request({
|
||||
@@ -16,12 +24,12 @@ const BrokerageApi = {
|
||||
});
|
||||
},
|
||||
// 获得分销记录分页
|
||||
getBrokerageRecordPage: (params) => {
|
||||
getBrokerageRecordPage: params => {
|
||||
if (params.status === undefined) {
|
||||
delete params.status
|
||||
}
|
||||
const queryString = Object.keys(params)
|
||||
.map((key) => encodeURIComponent(key) + '=' + params[key])
|
||||
.map(key => encodeURIComponent(key) + '=' + params[key])
|
||||
.join('&');
|
||||
return request({
|
||||
url: `/trade/brokerage-record/page?${queryString}`,
|
||||
@@ -29,7 +37,7 @@ const BrokerageApi = {
|
||||
});
|
||||
},
|
||||
// 创建分销提现
|
||||
createBrokerageWithdraw: (data) => {
|
||||
createBrokerageWithdraw: data => {
|
||||
return request({
|
||||
url: '/trade/brokerage-withdraw/create',
|
||||
method: 'POST',
|
||||
@@ -37,17 +45,15 @@ const BrokerageApi = {
|
||||
});
|
||||
},
|
||||
// 获得商品的分销金额
|
||||
getProductBrokeragePrice: (spuId) => {
|
||||
getProductBrokeragePrice: spuId => {
|
||||
return request({
|
||||
url: '/trade/brokerage-record/get-product-brokerage-price',
|
||||
method: 'GET',
|
||||
params: {
|
||||
spuId
|
||||
}
|
||||
params: { spuId }
|
||||
});
|
||||
},
|
||||
// 获得分销用户排行(基于佣金)
|
||||
getRankByPrice: (params) => {
|
||||
getRankByPrice: params => {
|
||||
const queryString = `times=${params.times[0]}×=${params.times[1]}`;
|
||||
return request({
|
||||
url: `/trade/brokerage-user/get-rank-by-price?${queryString}`,
|
||||
@@ -55,9 +61,9 @@ const BrokerageApi = {
|
||||
});
|
||||
},
|
||||
// 获得分销用户排行分页(基于佣金)
|
||||
getBrokerageUserChildSummaryPageByPrice: (params) => {
|
||||
getBrokerageUserChildSummaryPageByPrice: params => {
|
||||
const queryString = Object.keys(params)
|
||||
.map((key) => encodeURIComponent(key) + '=' + params[key])
|
||||
.map(key => encodeURIComponent(key) + '=' + params[key])
|
||||
.join('&');
|
||||
return request({
|
||||
url: `/trade/brokerage-user/rank-page-by-price?${queryString}`,
|
||||
@@ -65,9 +71,9 @@ const BrokerageApi = {
|
||||
});
|
||||
},
|
||||
// 获得分销用户排行分页(基于用户量)
|
||||
getBrokerageUserRankPageByUserCount: (params) => {
|
||||
getBrokerageUserRankPageByUserCount: params => {
|
||||
const queryString = Object.keys(params)
|
||||
.map((key) => encodeURIComponent(key) + '=' + params[key])
|
||||
.map(key => encodeURIComponent(key) + '=' + params[key])
|
||||
.join('&');
|
||||
return request({
|
||||
url: `/trade/brokerage-user/rank-page-by-user-count?${queryString}`,
|
||||
@@ -75,7 +81,7 @@ const BrokerageApi = {
|
||||
});
|
||||
},
|
||||
// 获得下级分销统计分页
|
||||
getBrokerageUserChildSummaryPage: (params) => {
|
||||
getBrokerageUserChildSummaryPage: params => {
|
||||
return request({
|
||||
url: '/trade/brokerage-user/child-summary-page',
|
||||
method: 'GET',
|
||||
|
||||
@@ -7,7 +7,25 @@ const DeliveryApi = {
|
||||
url: `/trade/delivery/express/list`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
},
|
||||
// 获得自提门店列表
|
||||
getDeliveryPickUpStoreList: (params) => {
|
||||
return request({
|
||||
url: `/trade/delivery/pick-up-store/list`,
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
},
|
||||
// 获得自提门店
|
||||
getDeliveryPickUpStore: (id) => {
|
||||
return request({
|
||||
url: `/trade/delivery/pick-up-store/get`,
|
||||
method: 'GET',
|
||||
params: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default DeliveryApi;
|
||||
@@ -1,4 +1,5 @@
|
||||
import request from '@/sheep/request';
|
||||
import { isEmpty } from '@/sheep/helper/utils';
|
||||
|
||||
const OrderApi = {
|
||||
// 计算订单信息
|
||||
@@ -13,7 +14,16 @@ const OrderApi = {
|
||||
if (!(data.addressId > 0)) {
|
||||
delete data2.addressId;
|
||||
}
|
||||
if (!(data.combinationActivityId) > 0) {
|
||||
if (!(data.pickUpStoreId > 0)) {
|
||||
delete data2.pickUpStoreId;
|
||||
}
|
||||
if (isEmpty(data.receiverName)) {
|
||||
delete data2.receiverName;
|
||||
}
|
||||
if (isEmpty(data.receiverMobile)) {
|
||||
delete data2.receiverMobile;
|
||||
}
|
||||
if (!(data.combinationActivityId > 0)) {
|
||||
delete data2.combinationActivityId;
|
||||
}
|
||||
if (!(data.combinationHeadId > 0)) {
|
||||
@@ -22,6 +32,9 @@ const OrderApi = {
|
||||
if (!(data.seckillActivityId > 0)) {
|
||||
delete data2.seckillActivityId;
|
||||
}
|
||||
if (!(data.pointActivityId > 0)) {
|
||||
delete data2.pointActivityId;
|
||||
}
|
||||
// 解决 SpringMVC 接受 List<Item> 参数的问题
|
||||
delete data2.items;
|
||||
for (let i = 0; i < data.items.length; i++) {
|
||||
@@ -43,6 +56,18 @@ const OrderApi = {
|
||||
},
|
||||
});
|
||||
},
|
||||
// 获得商品结算信息
|
||||
getSettlementProduct: (spuIds) => {
|
||||
return request({
|
||||
url: '/trade/order/settlement-product',
|
||||
method: 'GET',
|
||||
params: { spuIds },
|
||||
custom: {
|
||||
showLoading: false,
|
||||
showError: false,
|
||||
},
|
||||
});
|
||||
},
|
||||
// 创建订单
|
||||
createOrder: (data) => {
|
||||
return request({
|
||||
@@ -51,13 +76,14 @@ const OrderApi = {
|
||||
data,
|
||||
});
|
||||
},
|
||||
// 获得订单
|
||||
getOrder: (id) => {
|
||||
// 获得订单详细:sync 是可选参数
|
||||
getOrderDetail: (id, sync) => {
|
||||
return request({
|
||||
url: `/trade/order/get-detail`,
|
||||
method: 'GET',
|
||||
params: {
|
||||
id,
|
||||
sync,
|
||||
},
|
||||
custom: {
|
||||
showLoading: false,
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
<!-- TODO 霖:是不是怎么复用 s-count-down 组件 -->
|
||||
<template>
|
||||
<view class="time" :style="justifyLeft">
|
||||
<text class="" v-if="tipText">{{ tipText }}</text>
|
||||
<text
|
||||
class="styleAll p6"
|
||||
v-if="isDay === true"
|
||||
:style="{ background: bgColor.bgColor, color: bgColor.Color }"
|
||||
>{{ day }}{{ bgColor.isDay ? '天' : '' }}</text
|
||||
>
|
||||
<text
|
||||
class="timeTxt"
|
||||
v-if="dayText"
|
||||
:style="{ width: bgColor.timeTxtwidth, color: bgColor.bgColor }"
|
||||
>{{ dayText }}</text
|
||||
>
|
||||
<text
|
||||
class="styleAll"
|
||||
:class="isCol ? 'timeCol' : ''"
|
||||
:style="{ background: bgColor.bgColor, color: bgColor.Color, width: bgColor.width }"
|
||||
>{{ hour }}</text
|
||||
>
|
||||
<text
|
||||
class="timeTxt"
|
||||
v-if="hourText"
|
||||
:class="isCol ? 'whit' : ''"
|
||||
:style="{ width: bgColor.timeTxtwidth, color: bgColor.bgColor }"
|
||||
>{{ hourText }}</text
|
||||
>
|
||||
<text
|
||||
class="styleAll"
|
||||
:class="isCol ? 'timeCol' : ''"
|
||||
:style="{ background: bgColor.bgColor, color: bgColor.Color, width: bgColor.width }"
|
||||
>{{ minute }}</text
|
||||
>
|
||||
<text
|
||||
class="timeTxt"
|
||||
v-if="minuteText"
|
||||
:class="isCol ? 'whit' : ''"
|
||||
:style="{ width: bgColor.timeTxtwidth, color: bgColor.bgColor }"
|
||||
>{{ minuteText }}</text
|
||||
>
|
||||
<text
|
||||
class="styleAll"
|
||||
:class="isCol ? 'timeCol' : ''"
|
||||
:style="{ background: bgColor.bgColor, color: bgColor.Color, width: bgColor.width }"
|
||||
>{{ second }}</text
|
||||
>
|
||||
<text class="timeTxt" v-if="secondText">{{ secondText }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'countDown',
|
||||
props: {
|
||||
justifyLeft: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
//距离开始提示文字
|
||||
tipText: {
|
||||
type: String,
|
||||
default: '倒计时',
|
||||
},
|
||||
dayText: {
|
||||
type: String,
|
||||
default: '天',
|
||||
},
|
||||
hourText: {
|
||||
type: String,
|
||||
default: '时',
|
||||
},
|
||||
minuteText: {
|
||||
type: String,
|
||||
default: '分',
|
||||
},
|
||||
secondText: {
|
||||
type: String,
|
||||
default: '秒',
|
||||
},
|
||||
datatime: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
isDay: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isCol: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
bgColor: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
day: '00',
|
||||
hour: '00',
|
||||
minute: '00',
|
||||
second: '00',
|
||||
};
|
||||
},
|
||||
created: function () {
|
||||
this.show_time();
|
||||
},
|
||||
mounted: function () {},
|
||||
methods: {
|
||||
show_time: function () {
|
||||
let that = this;
|
||||
|
||||
function runTime() {
|
||||
//时间函数
|
||||
let intDiff = that.datatime - Date.parse(new Date()) / 1000; //获取数据中的时间戳的时间差;
|
||||
let day = 0,
|
||||
hour = 0,
|
||||
minute = 0,
|
||||
second = 0;
|
||||
if (intDiff > 0) {
|
||||
//转换时间
|
||||
if (that.isDay === true) {
|
||||
day = Math.floor(intDiff / (60 * 60 * 24));
|
||||
} else {
|
||||
day = 0;
|
||||
}
|
||||
hour = Math.floor(intDiff / (60 * 60)) - day * 24;
|
||||
minute = Math.floor(intDiff / 60) - day * 24 * 60 - hour * 60;
|
||||
second = Math.floor(intDiff) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60;
|
||||
if (hour <= 9) hour = '0' + hour;
|
||||
if (minute <= 9) minute = '0' + minute;
|
||||
if (second <= 9) second = '0' + second;
|
||||
that.day = day;
|
||||
that.hour = hour;
|
||||
that.minute = minute;
|
||||
that.second = second;
|
||||
} else {
|
||||
that.day = '00';
|
||||
that.hour = '00';
|
||||
that.minute = '00';
|
||||
that.second = '00';
|
||||
}
|
||||
}
|
||||
runTime();
|
||||
setInterval(runTime, 1000);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.p6 {
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
.styleAll {
|
||||
/* color: #fff; */
|
||||
font-size: 24rpx;
|
||||
height: 36rpx;
|
||||
line-height: 36rpx;
|
||||
border-radius: 6rpx;
|
||||
text-align: center;
|
||||
/* padding: 0 6rpx; */
|
||||
}
|
||||
.timeTxt {
|
||||
text-align: center;
|
||||
/* width: 16rpx; */
|
||||
height: 36rpx;
|
||||
line-height: 36rpx;
|
||||
display: inline-block;
|
||||
}
|
||||
.whit {
|
||||
color: #fff !important;
|
||||
}
|
||||
.time {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: #fc4141;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.timeCol {
|
||||
/* width: 40rpx;
|
||||
height: 40rpx;
|
||||
line-height: 40rpx;
|
||||
text-align:center;
|
||||
border-radius: 6px;
|
||||
background: #fff;
|
||||
font-size: 24rpx; */
|
||||
color: #e93323;
|
||||
}
|
||||
</style>
|
||||
@@ -2,34 +2,81 @@
|
||||
<template>
|
||||
<su-popup :show="show" type="bottom" round="20" @close="emits('close')" showClose>
|
||||
<view class="model-box">
|
||||
<view class="title ss-m-t-16 ss-m-l-20 ss-flex">营销活动</view>
|
||||
<view class="title ss-m-t-16 ss-m-l-20 ss-flex">优惠</view>
|
||||
<view v-if="state.rewardActivity && state.rewardActivity.id > 0">
|
||||
<view class="titleLi">促销</view>
|
||||
<scroll-view
|
||||
class="model-content"
|
||||
scroll-y
|
||||
:scroll-with-animation="false"
|
||||
:enable-back-to-top="true"
|
||||
>
|
||||
<view
|
||||
class="actBox"
|
||||
v-for="(item, index) in getRewardActivityRuleGroupDescriptions(state.rewardActivity)"
|
||||
:key="index"
|
||||
>
|
||||
<view
|
||||
class="boxCont ss-flex ss-col-top ss-m-b-40"
|
||||
@tap="onGoodsList(state.rewardActivity)"
|
||||
>
|
||||
<view class="model-content-tag ss-flex ss-row-center">{{ item.name }}</view>
|
||||
<view class="model-content-title">
|
||||
<view class="contBu">
|
||||
{{ item.values.join(';') }}
|
||||
</view>
|
||||
<view class="ss-m-b-24 cotBu-txt">
|
||||
{{ sheep.$helper.timeFormat(state.rewardActivity.startTime, 'yyyy.mm.dd') }}
|
||||
-
|
||||
{{ sheep.$helper.timeFormat(state.rewardActivity.endTime, 'yyyy.mm.dd') }}
|
||||
</view>
|
||||
</view>
|
||||
<text class="cicon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="titleLi">可领优惠券</view>
|
||||
<scroll-view
|
||||
class="model-content ss-m-t-50"
|
||||
class="model-content"
|
||||
scroll-y
|
||||
:scroll-with-animation="false"
|
||||
:enable-back-to-top="true"
|
||||
v-if="state.couponInfo.length"
|
||||
>
|
||||
<view v-for="item in state.activityInfo" :key="item.id">
|
||||
<view class="ss-flex ss-col-top ss-m-b-40" @tap="onGoodsList(item)">
|
||||
<view class="model-content-tag ss-flex ss-row-center">满减</view>
|
||||
<view class="ss-m-l-20 model-content-title ss-flex-1">
|
||||
<view class="ss-m-b-24" v-for="rule in state.activityMap[item.id]?.rules" :key="rule">
|
||||
{{ formatRewardActivityRule(state.activityMap[item.id], rule) }}
|
||||
<view class="actBox" v-for="item in state.couponInfo" :key="item.id">
|
||||
<view class="boxCont ss-flex ss-col-top ss-m-b-40">
|
||||
<view class="model-content-tag2">
|
||||
<view class="usePrice"> ¥{{ fen2yuan(item.discountPrice) }} </view>
|
||||
<view class="impose"> 满¥{{ fen2yuan(item.usePrice) }}可用 </view>
|
||||
</view>
|
||||
<view class="model-content-title2">
|
||||
<view class="contBu">
|
||||
{{ item.name }}
|
||||
</view>
|
||||
<view class="ss-m-b-24 cotBu-txt">
|
||||
{{
|
||||
item.validityType == 1
|
||||
? sheep.$helper.timeFormat(item.validStartTime, 'yyyy.mm.dd') -
|
||||
sheep.$helper.timeFormat(item.validEndTime, 'yyyy.mm.dd')
|
||||
: '领取后' + item.fixedStartTerm + '-' + item.fixedEndTerm + '天可用'
|
||||
}}
|
||||
</view>
|
||||
</view>
|
||||
<text class="cicon-forward" />
|
||||
<view class="coupon" @click.stop="getBuy(item.id)" v-if="item.canTake"> 立即领取 </view>
|
||||
<view class="coupon2" v-else> 已领取 </view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="nullBox" v-else> 暂无可领优惠券 </view>
|
||||
</view>
|
||||
</su-popup>
|
||||
</template>
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import RewardActivityApi from '@/sheep/api/promotion/rewardActivity';
|
||||
import { formatRewardActivityRule } from '@/sheep/hooks/useGoods';
|
||||
|
||||
import { getRewardActivityRuleGroupDescriptions } from '@/sheep/hooks/useGoods';
|
||||
import { computed, reactive, watch, ref } from 'vue';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
@@ -42,26 +89,14 @@
|
||||
});
|
||||
const emits = defineEmits(['close']);
|
||||
const state = reactive({
|
||||
activityInfo: computed(() => props.modelValue),
|
||||
activityMap: {}
|
||||
rewardActivity: computed(() => props.modelValue.rewardActivity),
|
||||
couponInfo: computed(() => props.modelValue.couponInfo),
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.show,
|
||||
() => {
|
||||
// 展示的情况下,加载每个活动的详细信息
|
||||
if (props.show) {
|
||||
state.activityInfo?.forEach(activity => {
|
||||
RewardActivityApi.getRewardActivity(activity.id).then(res => {
|
||||
if (res.code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.activityMap[activity.id] = res.data;
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
// 领取优惠劵
|
||||
const getBuy = (id) => {
|
||||
emits('get', id);
|
||||
};
|
||||
|
||||
function onGoodsList(e) {
|
||||
sheep.$router.go('/pages/activity/index', {
|
||||
@@ -72,34 +107,149 @@
|
||||
<style lang="scss" scoped>
|
||||
.model-box {
|
||||
height: 60vh;
|
||||
|
||||
.title {
|
||||
justify-content: center;
|
||||
font-size: 36rpx;
|
||||
height: 80rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.model-content {
|
||||
height: fit-content;
|
||||
max-height: 380rpx;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.model-content-tag {
|
||||
background: rgba(#ff6911, 0.1);
|
||||
font-size: 24rpx;
|
||||
// background: rgba(#ff6911, 0.1);
|
||||
font-size: 35rpx;
|
||||
font-weight: 500;
|
||||
color: #ff6911;
|
||||
line-height: 42rpx;
|
||||
width: 68rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 5rpx;
|
||||
line-height: 150rpx;
|
||||
width: 200rpx;
|
||||
height: 150rpx;
|
||||
text-align: center;
|
||||
|
||||
// border-radius: 5rpx;
|
||||
}
|
||||
|
||||
.model-content-title {
|
||||
width: 450rpx;
|
||||
height: 150rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cicon-forward {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
// 新增的
|
||||
.titleLi {
|
||||
margin: 10rpx 0 10rpx 20rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.actBox {
|
||||
width: 700rpx;
|
||||
height: 150rpx;
|
||||
background-color: #fff2f2;
|
||||
margin: 10rpx auto;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.boxCont {
|
||||
width: 700rpx;
|
||||
height: 150rpx;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.contBu {
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
overflow: hidden;
|
||||
font-size: 30rpx;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
-o-text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.cotBu-txt {
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
font-size: 25rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.model-content-tag2 {
|
||||
font-size: 35rpx;
|
||||
font-weight: 500;
|
||||
color: #ff6911;
|
||||
width: 200rpx;
|
||||
height: 150rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.usePrice {
|
||||
width: 200rpx;
|
||||
height: 90rpx;
|
||||
line-height: 100rpx;
|
||||
// background-color: red;
|
||||
}
|
||||
|
||||
.impose {
|
||||
width: 200rpx;
|
||||
height: 50rpx;
|
||||
// line-height: 75rpx;
|
||||
font-size: 23rpx;
|
||||
// background-color: gold;
|
||||
}
|
||||
|
||||
.model-content-title2 {
|
||||
width: 330rpx;
|
||||
height: 150rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.coupon {
|
||||
width: 150rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
background-color: rgb(255, 68, 68);
|
||||
color: white;
|
||||
border-radius: 30rpx;
|
||||
text-align: center;
|
||||
font-size: 25rpx;
|
||||
}
|
||||
|
||||
.coupon2 {
|
||||
width: 150rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
background-color: rgb(203, 192, 191);
|
||||
color: white;
|
||||
border-radius: 30rpx;
|
||||
text-align: center;
|
||||
font-size: 25rpx;
|
||||
}
|
||||
.nullBox {
|
||||
width: 100%;
|
||||
height: 300rpx;
|
||||
font-size: 25rpx;
|
||||
line-height: 300rpx;
|
||||
text-align: center;
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
@@ -18,9 +18,7 @@
|
||||
<view class="address-text">
|
||||
{{ props.item.detailAddress }}
|
||||
</view>
|
||||
<view class="person-text">
|
||||
{{ props.item.name }} {{ props.item.mobile }}
|
||||
</view>
|
||||
<view class="person-text"> {{ props.item.name }} {{ props.item.mobile }} </view>
|
||||
</view>
|
||||
<view v-else>
|
||||
<view class="address-text ss-m-b-10">请选择收货地址</view>
|
||||
@@ -47,7 +45,7 @@
|
||||
* @slot - 默认插槽
|
||||
*/
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
|
||||
@@ -10,7 +10,11 @@
|
||||
/>
|
||||
|
||||
<!-- 2. 短信登录 smsLogin -->
|
||||
<sms-login v-if="authType === 'smsLogin'" :agreeStatus="state.protocol" @onConfirm="onConfirm" />
|
||||
<sms-login
|
||||
v-if="authType === 'smsLogin'"
|
||||
:agreeStatus="state.protocol"
|
||||
@onConfirm="onConfirm"
|
||||
/>
|
||||
|
||||
<!-- 3. 忘记密码 resetPassword-->
|
||||
<reset-password v-if="authType === 'resetPassword'" />
|
||||
@@ -32,7 +36,11 @@
|
||||
<!-- 7.1 微信小程序的快捷登录 -->
|
||||
<view v-if="sheep.$platform.name === 'WechatMiniProgram'" class="ss-flex register-box">
|
||||
<view class="register-title">还没有账号?</view>
|
||||
<button class="ss-reset-button login-btn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
|
||||
<button
|
||||
class="ss-reset-button login-btn"
|
||||
open-type="getPhoneNumber"
|
||||
@getphonenumber="getPhoneNumber"
|
||||
>
|
||||
快捷登录
|
||||
</button>
|
||||
<view class="circle" />
|
||||
@@ -81,17 +89,13 @@
|
||||
/>
|
||||
<view class="agreement-text ss-flex ss-col-center ss-m-l-8">
|
||||
我已阅读并遵守
|
||||
<view class="tcp-text" @tap.stop="onProtocol('用户协议')">
|
||||
《用户协议》
|
||||
</view>
|
||||
<view class="tcp-text" @tap.stop="onProtocol('用户协议')"> 《用户协议》 </view>
|
||||
<view class="agreement-text">与</view>
|
||||
<view class="tcp-text" @tap.stop="onProtocol('隐私协议')">
|
||||
《隐私协议》
|
||||
</view>
|
||||
<view class="tcp-text" @tap.stop="onProtocol('隐私协议')"> 《隐私协议》 </view>
|
||||
</view>
|
||||
</label>
|
||||
</view>
|
||||
<view class="safe-box"/>
|
||||
<view class="safe-box" />
|
||||
</view>
|
||||
</su-popup>
|
||||
</template>
|
||||
@@ -107,8 +111,6 @@
|
||||
import mpAuthorization from './components/mp-authorization.vue';
|
||||
import { closeAuthModal, showAuthModal } from '@/sheep/hooks/useModal';
|
||||
|
||||
const appInfo = computed(() => sheep.$store('app').info);
|
||||
|
||||
const modalStore = sheep.$store('modal');
|
||||
// 授权弹窗类型
|
||||
const authType = computed(() => modalStore.auth);
|
||||
@@ -152,7 +154,13 @@
|
||||
}
|
||||
const loginRes = await sheep.$platform.useProvider(provider).login();
|
||||
if (loginRes) {
|
||||
const userInfo = await sheep.$store('user').getInfo();
|
||||
closeAuthModal();
|
||||
// 如果用户已经有头像和昵称,不需要再次授权
|
||||
if (userInfo.avatar && userInfo.nickname) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 触发小程序授权信息弹框
|
||||
// #ifdef MP-WEIXIN
|
||||
showAuthModal('mpAuthorization');
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<!-- 基础组件:列表导航 -->
|
||||
<s-menu-list v-if="type === 'MenuList'" :data="data" />
|
||||
<!-- 基础组件:宫格导航 -->
|
||||
<s-menu-grid v-if="type === 'MenuGrid'" :data="data" />
|
||||
<s-menu-grid v-if="type === 'MenuGrid'" :data="data" :styles="styles" />
|
||||
<!-- 基础组件:弹窗广告 -->
|
||||
<s-popup-image v-if="type === 'Popover'" :data="data" />
|
||||
<!-- 基础组件:悬浮按钮 -->
|
||||
@@ -39,6 +39,8 @@
|
||||
<s-groupon-block v-if="type === 'PromotionCombination'" :data="data" :styles="styles" />
|
||||
<!-- 营销组件:秒杀 -->
|
||||
<s-seckill-block v-if="type === 'PromotionSeckill'" :data="data" :styles="styles" />
|
||||
<!-- 营销组件:积分商城 -->
|
||||
<s-point-block v-if="type === 'PromotionPoint'" :data="data" :styles="styles" />
|
||||
<!-- 营销组件:小程序直播(暂时没有这个功能) -->
|
||||
<s-live-block v-if="type === 'MpLive'" :data="data" :styles="styles" />
|
||||
<!-- 营销组件:优惠券 -->
|
||||
@@ -47,13 +49,13 @@
|
||||
<s-richtext-block v-if="type === 'PromotionArticle'" :data="data" :styles="styles" />
|
||||
|
||||
<!-- 用户组件:用户卡片 -->
|
||||
<s-user-card v-if="type === 'UserCard'" />
|
||||
<s-user-card v-if="type === 'UserCard'" :data="data" :styles="styles" />
|
||||
<!-- 用户组件:用户订单 -->
|
||||
<s-order-card v-if="type === 'UserOrder'" :data="data" />
|
||||
<s-order-card v-if="type === 'UserOrder'" :data="data" :styles="styles" />
|
||||
<!-- 用户组件:用户资产 -->
|
||||
<s-wallet-card v-if="type === 'UserWallet'" />
|
||||
<s-wallet-card v-if="type === 'UserWallet'" :data="data" :styles="styles" />
|
||||
<!-- 用户组件:用户卡券 -->
|
||||
<s-coupon-card v-if="type === 'UserCoupon'" />
|
||||
<s-coupon-card v-if="type === 'UserCoupon'" :data="data" :styles="styles" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,152 +1,176 @@
|
||||
<!-- 装修营销组件:优惠券 -->
|
||||
<template>
|
||||
<scroll-view class="scroll-box" scroll-x scroll-anchoring>
|
||||
<view class="coupon-box ss-flex">
|
||||
<view
|
||||
class="coupon-item"
|
||||
:style="[couponBg, { marginLeft: `${data.space}px` }]"
|
||||
v-for="(item, index) in couponList"
|
||||
:key="index"
|
||||
>
|
||||
<su-coupon
|
||||
:size="SIZE_LIST[columns - 1]"
|
||||
:textColor="data.textColor"
|
||||
background=""
|
||||
:couponId="item.id"
|
||||
:title="item.name"
|
||||
:type="formatCouponDiscountType(item)"
|
||||
:value="formatCouponDiscountValue(item)"
|
||||
:sellBy="formatValidityType(item)"
|
||||
>
|
||||
<template v-slot:btn>
|
||||
<!-- 两列时,领取按钮坚排 -->
|
||||
<button
|
||||
v-if="columns === 2"
|
||||
@click.stop="onGetCoupon(item.id)"
|
||||
class="ss-reset-button card-btn vertical"
|
||||
:style="[btnStyles]"
|
||||
>
|
||||
<view class="btn-text">立即领取</view>
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
class="ss-reset-button card-btn"
|
||||
:style="[btnStyles]"
|
||||
@click.stop="onGetCoupon(item.id)"
|
||||
>
|
||||
立即领取
|
||||
</button>
|
||||
</template>
|
||||
</su-coupon>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<scroll-view class="scroll-box" scroll-x scroll-anchoring :style="[bgStyle, { marginLeft: `${data.space}px` }]">
|
||||
<view class="coupon-box ss-flex" :style="couponList.length === 2 ? couponBoxStyleTwo : couponBoxStyleNormal">
|
||||
<view class="coupon-item" :style="[couponBg, { marginLeft: `${data.space}px` }]"
|
||||
v-for="(item, index) in couponList" :key="index">
|
||||
<su-coupon :size="SIZE_LIST[columns - 1]" :textColor="data.textColor" background="" :couponId="item.id"
|
||||
:title="item.name" :type="formatCouponDiscountType(item)" :value="formatCouponDiscountValue(item)"
|
||||
:sellBy="formatValidityType(item)">
|
||||
<template v-slot:btn>
|
||||
<!-- 两列时,领取按钮坚排 -->
|
||||
<button v-if="columns === 2" @click.stop="onGetCoupon(item.id)"
|
||||
class="ss-reset-button card-btn vertical" :style="[btnStyles]">
|
||||
<view class="btn-text">立即领取</view>
|
||||
</button>
|
||||
<button v-else class="ss-reset-button card-btn" :style="[btnStyles]"
|
||||
@click.stop="onGetCoupon(item.id)">
|
||||
立即领取
|
||||
</button>
|
||||
</template>
|
||||
</su-coupon>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { CouponTemplateValidityTypeEnum, PromotionDiscountTypeEnum } from "@/sheep/util/const";
|
||||
import { floatToFixed2, formatDate } from "@/sheep/util";
|
||||
import sheep from '@/sheep';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import {
|
||||
ref,
|
||||
onMounted,
|
||||
computed
|
||||
} from 'vue';
|
||||
import {
|
||||
CouponTemplateValidityTypeEnum,
|
||||
PromotionDiscountTypeEnum
|
||||
} from "@/sheep/util/const";
|
||||
import {
|
||||
floatToFixed2,
|
||||
formatDate
|
||||
} from "@/sheep/util";
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
const { columns, button } = props.data;
|
||||
const SIZE_LIST = ['lg', 'md', 'xs']
|
||||
const couponBg = {
|
||||
background: `url(${sheep.$url.cdn(props.data.bgImg)}) no-repeat top center / 100% 100%`,
|
||||
};
|
||||
const btnStyles = {
|
||||
background: button.bgColor,
|
||||
color: button.color,
|
||||
};
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
const {
|
||||
columns,
|
||||
button
|
||||
} = props.data;
|
||||
const SIZE_LIST = ['lg', 'md', 'xs']
|
||||
const couponBg = {
|
||||
background: `url(${sheep.$url.cdn(props.data.bgImg)}) no-repeat top center / 100% 100%`,
|
||||
};
|
||||
const btnStyles = {
|
||||
background: button.bgColor,
|
||||
color: button.color,
|
||||
};
|
||||
// 两列优惠券时的排版方式
|
||||
const couponBoxStyleNormal = {
|
||||
'display': 'flex',
|
||||
'justify-content': 'space-between'
|
||||
};
|
||||
// 非两列优惠券时的排版方式
|
||||
const couponBoxStyleTwo = {
|
||||
'display': 'flex',
|
||||
'justify-content': 'space-around'
|
||||
};
|
||||
// 设置背景样式
|
||||
const bgStyle = computed(() => {
|
||||
// 直接从 props.styles 解构
|
||||
const {
|
||||
bgType,
|
||||
bgImg,
|
||||
bgColor
|
||||
} = props.styles;
|
||||
|
||||
// 格式化【折扣类型】
|
||||
const formatCouponDiscountType = (coupon) => {
|
||||
if(coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
|
||||
return 'reduce'
|
||||
}
|
||||
if(coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
|
||||
return 'percent'
|
||||
}
|
||||
return `未知【${coupon.discountType}】`
|
||||
}
|
||||
// 根据 bgType 返回相应的样式
|
||||
return {
|
||||
background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
|
||||
};
|
||||
});
|
||||
// 格式化【折扣类型】
|
||||
const formatCouponDiscountType = (coupon) => {
|
||||
if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
|
||||
return 'reduce'
|
||||
}
|
||||
if (coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
|
||||
return 'percent'
|
||||
}
|
||||
return `未知【${coupon.discountType}】`
|
||||
}
|
||||
|
||||
// 格式化【折扣】
|
||||
const formatCouponDiscountValue = (coupon) => {
|
||||
if(coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
|
||||
return floatToFixed2(coupon.discountPrice)
|
||||
}
|
||||
if(coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
|
||||
return coupon.discountPercent
|
||||
}
|
||||
return `未知【${coupon.discountType}】`
|
||||
}
|
||||
// 格式化【折扣】
|
||||
const formatCouponDiscountValue = (coupon) => {
|
||||
if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
|
||||
return floatToFixed2(coupon.discountPrice)
|
||||
}
|
||||
if (coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
|
||||
return coupon.discountPercent
|
||||
}
|
||||
return `未知【${coupon.discountType}】`
|
||||
}
|
||||
|
||||
// 格式化【有效期限】
|
||||
const formatValidityType = (row) => {
|
||||
if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) {
|
||||
return `${formatDate(row.validStartTime)} 至 ${formatDate(row.validEndTime)}`
|
||||
}
|
||||
if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
|
||||
return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`
|
||||
}
|
||||
return '未知【' + row.validityType + '】'
|
||||
}
|
||||
// 格式化【有效期限】
|
||||
const formatValidityType = (row) => {
|
||||
if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) {
|
||||
return `${formatDate(row.validStartTime)} 至 ${formatDate(row.validEndTime)}`
|
||||
}
|
||||
if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
|
||||
return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`
|
||||
}
|
||||
return '未知【' + row.validityType + '】'
|
||||
}
|
||||
|
||||
const couponList = ref([]);
|
||||
// 立即领取优惠券
|
||||
async function onGetCoupon(id) {
|
||||
const { error, msg } = await CouponApi.takeCoupon(id);
|
||||
if (error === 0) {
|
||||
uni.showToast({
|
||||
title: msg,
|
||||
icon: 'none',
|
||||
});
|
||||
return
|
||||
}
|
||||
await getCouponTemplateList()
|
||||
}
|
||||
const getCouponTemplateList = async () => {
|
||||
const { data } = await CouponApi.getCouponTemplateListByIds(props.data.couponIds.join(','));
|
||||
couponList.value = data;
|
||||
}
|
||||
onMounted(() => {
|
||||
getCouponTemplateList()
|
||||
});
|
||||
const couponList = ref([]);
|
||||
// 立即领取优惠券
|
||||
async function onGetCoupon(id) {
|
||||
const {
|
||||
error,
|
||||
msg
|
||||
} = await CouponApi.takeCoupon(id);
|
||||
if (error === 0) {
|
||||
uni.showToast({
|
||||
title: msg,
|
||||
icon: 'none',
|
||||
});
|
||||
return
|
||||
}
|
||||
await getCouponTemplateList()
|
||||
}
|
||||
const getCouponTemplateList = async () => {
|
||||
const {
|
||||
data
|
||||
} = await CouponApi.getCouponTemplateListByIds(props.data.couponIds.join(','));
|
||||
couponList.value = data;
|
||||
}
|
||||
onMounted(() => {
|
||||
getCouponTemplateList()
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 50rpx;
|
||||
&.vertical {
|
||||
width: 50rpx;
|
||||
height: 140rpx;
|
||||
margin: auto 20rpx auto 0;
|
||||
.card-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 50rpx;
|
||||
|
||||
.btn-text {
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
}
|
||||
}
|
||||
.coupon-item {
|
||||
&:nth-of-type(1) {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
&.vertical {
|
||||
width: 50rpx;
|
||||
height: 140rpx;
|
||||
margin: auto 20rpx auto 0;
|
||||
|
||||
.btn-text {
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.coupon-item {
|
||||
&:nth-of-type(1) {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- 装修用户组件:用户卡券 -->
|
||||
<template>
|
||||
<view class="ss-coupon-menu-wrap ss-flex ss-col-center">
|
||||
<view class="ss-coupon-menu-wrap ss-flex ss-col-center" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
|
||||
<view class="menu-item ss-flex-col ss-row-center ss-col-center" v-for="item in props.list" :key="item.title"
|
||||
@tap="sheep.$router.go(item.path, { type: item.type })"
|
||||
:class="item.type === 'all' ? 'menu-wallet' : 'ss-flex-1'">
|
||||
@@ -15,6 +15,7 @@
|
||||
* 装修组件 - 优惠券菜单
|
||||
*/
|
||||
import sheep from '@/sheep';
|
||||
import { computed } from 'vue';
|
||||
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
@@ -52,6 +53,28 @@
|
||||
];
|
||||
},
|
||||
},
|
||||
// 装修数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 装修样式
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
// 设置背景样式
|
||||
const bgStyle = computed(() => {
|
||||
// 直接从 props.styles 解构
|
||||
const { bgType, bgImg, bgColor } = props.styles;
|
||||
|
||||
// 根据 bgType 返回相应的样式
|
||||
return {
|
||||
background: bgType === 'img'
|
||||
? `url(${bgImg}) no-repeat top center / 100% 100%`
|
||||
: bgColor
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -37,30 +37,22 @@
|
||||
<view class="ss-flex ss-row-between ss-m-t-16">
|
||||
<view
|
||||
class="sellby-text"
|
||||
:class=" isDisable ? 'disabled-color' : 'subtitle-color'"
|
||||
:class="isDisable ? 'disabled-color' : 'subtitle-color'"
|
||||
v-if="data.validityType === 2"
|
||||
>
|
||||
有效期:领取后 {{ data.fixedEndTerm }} 天内可用
|
||||
</view>
|
||||
<view
|
||||
class="sellby-text"
|
||||
:class=" isDisable ? 'disabled-color' : 'subtitle-color'"
|
||||
v-else
|
||||
>
|
||||
<view class="sellby-text" :class="isDisable ? 'disabled-color' : 'subtitle-color'" v-else>
|
||||
有效期: {{ sheep.$helper.timeFormat(data.validStartTime, 'yyyy-mm-dd') }} 至
|
||||
{{ sheep.$helper.timeFormat(data.validEndTime, 'yyyy-mm-dd') }}
|
||||
</view>
|
||||
<view
|
||||
class="value-enough"
|
||||
:class="isDisable ? 'disabled-color' : 'subtitle-color'"
|
||||
>
|
||||
<view class="value-enough" :class="isDisable ? 'disabled-color' : 'subtitle-color'">
|
||||
满 {{ fen2yuan(data.usePrice) }} 可用
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- TODO 芋艿:可优化,增加优惠劵的描述 -->
|
||||
<view class="desc ss-flex ss-row-between">
|
||||
<view>
|
||||
<view class="desc-title">{{ data.description }}</view>
|
||||
@@ -76,17 +68,15 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, reactive } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import { fen2yuan } from '../../hooks/useGoods';
|
||||
import sheep from '../../index';
|
||||
|
||||
const state = reactive({});
|
||||
|
||||
const isDisable = computed(() => {
|
||||
if (props.type === 'coupon') {
|
||||
return false;
|
||||
}
|
||||
return props.data.status !== 1;
|
||||
return props.disabled;
|
||||
});
|
||||
|
||||
// 接受参数
|
||||
@@ -202,4 +192,4 @@
|
||||
.price-text {
|
||||
color: #ff0000;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -16,8 +16,12 @@
|
||||
:scroll-with-animation="false"
|
||||
:enable-back-to-top="true"
|
||||
>
|
||||
<!--可使用的优惠券区域-->
|
||||
<view class="subtitle ss-m-l-20">可使用优惠券</view>
|
||||
<view v-for="(item, index) in state.couponInfo" :key="index">
|
||||
<view
|
||||
v-for="(item, index) in state.couponInfo.filter((coupon) => coupon.match)"
|
||||
:key="index"
|
||||
>
|
||||
<s-coupon-list :data="item" type="user" :disabled="false">
|
||||
<template #default>
|
||||
<label class="ss-flex ss-col-center" @tap="radioChange(item.id)">
|
||||
@@ -31,19 +35,18 @@
|
||||
</template>
|
||||
</s-coupon-list>
|
||||
</view>
|
||||
<!-- TODO 芋艿:未来接口需要支持下
|
||||
<!--不可使用的优惠券区域-->
|
||||
<view class="subtitle ss-m-t-40 ss-m-l-20">不可使用优惠券</view>
|
||||
<view v-for="item in state.couponInfo.cannot_use" :key="item.id">
|
||||
<view v-for="item in state.couponInfo.filter((coupon) => !coupon.match)" :key="item.id">
|
||||
<s-coupon-list :data="item" type="user" :disabled="true">
|
||||
<template v-slot:reason>
|
||||
<view class="ss-flex ss-m-t-24">
|
||||
<view class="reason-title"> 不可用原因:</view>
|
||||
<view class="reason-desc">{{ item.cannot_use_msg }}</view>
|
||||
<view class="reason-desc">{{ item.mismatchReason || '未达到使用门槛' }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</s-coupon-list>
|
||||
</view>
|
||||
-->
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="modal-footer ss-flex">
|
||||
@@ -55,7 +58,8 @@
|
||||
import { computed, reactive } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: { // 优惠劵列表
|
||||
modelValue: {
|
||||
// 优惠劵列表
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
@@ -69,13 +73,13 @@
|
||||
|
||||
const state = reactive({
|
||||
couponInfo: computed(() => props.modelValue), // 优惠劵列表
|
||||
couponId: 0, // 选中的优惠劵编号
|
||||
couponId: undefined, // 选中的优惠劵编号
|
||||
});
|
||||
|
||||
// 选中优惠劵
|
||||
function radioChange(couponId) {
|
||||
if (state.couponId === couponId) {
|
||||
state.couponId = 0;
|
||||
state.couponId = undefined;
|
||||
} else {
|
||||
state.couponId = couponId;
|
||||
}
|
||||
@@ -84,7 +88,7 @@
|
||||
// 确认优惠劵
|
||||
const onConfirm = () => {
|
||||
emits('confirm', state.couponId);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
@@ -96,25 +100,30 @@
|
||||
.model-box {
|
||||
height: 60vh;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
height: 80rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.model-content {
|
||||
height: 54vh;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
width: 100%;
|
||||
height: 120rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 710rpx;
|
||||
margin-left: 20rpx;
|
||||
@@ -123,12 +132,14 @@
|
||||
border-radius: 40rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.reason-title {
|
||||
font-weight: 600;
|
||||
font-size: 20rpx;
|
||||
line-height: 26rpx;
|
||||
color: #ff0003;
|
||||
}
|
||||
|
||||
.reason-desc {
|
||||
font-weight: 600;
|
||||
font-size: 20rpx;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<!-- 顶部导航栏 - 单元格 -->
|
||||
<template>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<!-- 类型一: 文字 -->
|
||||
<view
|
||||
v-if="data.type === 'text'"
|
||||
class="nav-title inline"
|
||||
@@ -7,15 +9,17 @@
|
||||
>
|
||||
{{ data.text }}
|
||||
</view>
|
||||
<!-- 类型二: 图片 -->
|
||||
<view
|
||||
v-if="data.type === 'image'"
|
||||
:style="[{ width: width }]"
|
||||
class="menu-icon-wrap ss-flex ss-row-center ss-col-center"
|
||||
@tap="sheep.$router.go(data.url)"
|
||||
>
|
||||
<image class="nav-image" :src="sheep.$url.cdn(data.src)" mode="aspectFit"></image>
|
||||
<image class="nav-image" :src="sheep.$url.cdn(data.imgUrl)" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="ss-flex-1" v-if="data.type == 'search'" :style="[{ width: width }]">
|
||||
<!-- 类型三: 搜索框 -->
|
||||
<view class="ss-flex-1" v-if="data.type === 'search'" :style="[{ width: width }]">
|
||||
<s-search-block
|
||||
:placeholder="data.placeholder || '搜索关键字'"
|
||||
:radius="data.borderRadius"
|
||||
|
||||
Loaded 100 of 214 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user