普兆健康管家前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

646 lines
16 KiB

5 months ago
  1. <template>
  2. <view class="page__view">
  3. <navbar title="订单详情" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="#FFFFFF" />
  4. <view class="main">
  5. <view class="flex address" v-if="addressData">
  6. <addressView :data="addressData" :showIcon="true" :enableCopy="true"></addressView>
  7. </view>
  8. <template v-if="orderData">
  9. <view class="card detail">
  10. <view class="flex card-top">
  11. <view class="title">订单详情</view>
  12. <view :class="['flex', 'status', `status-${orderData.status}`]">{{ statusDesc }}</view>
  13. </view>
  14. <view class="card-main">
  15. <view class="flex product" v-for="item in orderData.productList" :key="item.id">
  16. <image class="img" :src="item.url" mode="scaleToFill"></image>
  17. <view class="info">
  18. <view class="row">{{ item.name }}</view>
  19. <view class="flex row">
  20. <view class="row-label">产品类型</view>
  21. <view class="row-content">{{ item.type }}</view>
  22. </view>
  23. <view class="flex row">
  24. <view class="row-label">产品内容</view>
  25. <view class="row-content">{{ item.content }}</view>
  26. </view>
  27. <view class="flex price">
  28. <text class="price-label">价格</text>
  29. <text class="price-unit">¥</text><text class="price-value">{{ item.price.toFixed(2) }}</text>
  30. </view>
  31. </view>
  32. </view>
  33. </view>
  34. <view class="flex row card-bottom">
  35. <view class="row-label">总价格</view>
  36. <view class="flex row-content price">¥<text class="price-value">{{ orderData.amount.toFixed(2) }}</text></view>
  37. </view>
  38. </view>
  39. <view v-if="orderData.status == 5" class="card service">
  40. <view class="flex card-top">
  41. <view class="title">售后信息</view>
  42. </view>
  43. <view class="card-main">
  44. <uv-steps
  45. current="0"
  46. direction="column"
  47. dot
  48. activeColor="#10A934"
  49. inactiveColor="#C6C6C6"
  50. >
  51. <uv-steps-item
  52. v-for="(item, index) in orderData.serviceRecords"
  53. :key="item.id"
  54. >
  55. <template #title>
  56. <view class="flex step-header">
  57. <view :class="['step-title', index == 0 ? 'highlight' : '']">{{ item.title }}</view>
  58. <view class="step-time">{{ item.createTime }}</view>
  59. </view>
  60. </template>
  61. <template #desc>
  62. <view class="step-desc">{{ item.desc }}</view>
  63. </template>
  64. </uv-steps-item>
  65. </uv-steps>
  66. </view>
  67. </view>
  68. <view class="card info">
  69. <view class="flex card-top">
  70. <view class="title">订单信息</view>
  71. </view>
  72. <view class="card-main">
  73. <view class="flex row">
  74. <view class="row-label">订单编号</view>
  75. <view class="row-content">{{ orderData.number }}</view>
  76. </view>
  77. <view class="flex row">
  78. <view class="row-label">下单时间</view>
  79. <view class="row-content">{{ $dayjs(orderData.createTime).format('YYYY-MM-DD HH:mm') }}</view>
  80. </view>
  81. </view>
  82. </view>
  83. </template>
  84. <view class="notice">
  85. <view class="notice-header">下单须知</view>
  86. <view class="notice-content">
  87. <!-- todo: 替换配置项key -->
  88. <uv-parse :content="configList['config_agreement']"></uv-parse>
  89. </view>
  90. </view>
  91. </view>
  92. <view class="flex bottom" v-if="orderData && [0,1,2,3,4].includes(orderData.status)">
  93. <button plain class="flex flex-column btn btn-service" open-type="contact">
  94. <image class="btn-service-icon" src="@/pages_order/static/order/icon-service.png" mode="widthFix"></image>
  95. <view>联系客服</view>
  96. </button>
  97. <view class="flex cols">
  98. <!-- 待支付 -->
  99. <template v-if="orderData.status == 0">
  100. <view class="flex col price">
  101. <view class="price-label">合计</view>
  102. <text class="price-unit">¥</text><text class="price-value">{{ orderData.amount.toFixed(2) }}</text>
  103. </view>
  104. <button class="flex col btn btn-primary" @click="onPay">立即支付</button>
  105. </template>
  106. <!-- 待发货 -->
  107. <template v-else-if="orderData.status == 1">
  108. <button class="flex col btn" @click="onApplyService">申请售后</button>
  109. </template>
  110. <!-- 待收货 -->
  111. <template v-else-if="orderData.status == 2">
  112. <button class="flex col btn" @click="onApplyService">申请售后</button>
  113. <button class="flex col btn btn-primary" @click="onConfirmReceipt">确认收货</button>
  114. </template>
  115. <!-- 待评价 -->
  116. <template v-else-if="orderData.status == 3">
  117. <button class="flex col btn" @click="onApplyService">申请售后</button>
  118. <button class="flex col btn btn-primary" @click="onComment">立即评价</button>
  119. </template>
  120. <!-- 已完成 -->
  121. <template v-else-if="orderData.status == 4">
  122. <button class="flex col btn" @click="onApplyService">申请售后</button>
  123. </template>
  124. </view>
  125. </view>
  126. <payPopup ref="payPopup"></payPopup>
  127. <serviceSelectPopup ref="serviceSelectPopup"></serviceSelectPopup>
  128. </view>
  129. </template>
  130. <script>
  131. import addressView from '@/pages_order/address/addressView.vue'
  132. import payPopup from '@/pages_order/order/payPopup.vue'
  133. import serviceSelectPopup from '@/pages_order/service/serviceSelectPopup.vue'
  134. const STATUS_AND_DESC_MAPPING = {
  135. 0: '待支付',
  136. 1: '待发货',
  137. 2: '待收货',
  138. 3: '待评价',
  139. 4: '已完成',
  140. 5: '售后',
  141. }
  142. export default {
  143. components: {
  144. addressView,
  145. payPopup,
  146. serviceSelectPopup,
  147. },
  148. data() {
  149. return {
  150. id: null,
  151. addressData: null,
  152. orderData: null,
  153. }
  154. },
  155. computed: {
  156. statusDesc() {
  157. return STATUS_AND_DESC_MAPPING[this.orderData?.status]
  158. },
  159. },
  160. onShow() {
  161. console.log('onShow')
  162. if (!this.id) {
  163. return
  164. }
  165. this.fetchOrderDetail()
  166. },
  167. onLoad(arg) {
  168. console.log('onLoad')
  169. this.id = arg.id
  170. this.fetchOrderDetail()
  171. },
  172. methods: {
  173. async fetchOrderDetail() {
  174. console.log('fetch data')
  175. // todo: fetch data by id
  176. this.addressData = {
  177. id: '001',
  178. name: '郑文锦',
  179. phone: '18108341643',
  180. area: ['海南省', '海口市', '秀英区'],
  181. address: '秀英街道5单元183室',
  182. // id: '006',
  183. // name: '何炜',
  184. // phone: '18108341643',
  185. // area: ['新疆维吾尔自治区', '乌鲁木齐市', '沙依巴克区'],
  186. // address: '新疆维吾尔自治区乌鲁木齐市沙依巴克区仓房沟片区街道4单元50室',
  187. }
  188. this.orderData = {
  189. id: '001',
  190. url: '/pages_order/static/index/recommend-pic.png',
  191. title: '月度装定制营养包',
  192. amount: 688,
  193. productList: [
  194. {
  195. id: '0011',
  196. url: '/pages_order/static/index/medicine-1.png',
  197. name: '月度装定制营养包',
  198. type: '保健品',
  199. content: '控糖精华萃 x30颗、膳食纤维 ×30颗',
  200. price: 688.00,
  201. count: 1,
  202. countDesc: '1月装',
  203. customized: true,
  204. },
  205. {
  206. id: '0012',
  207. url: '/pages_order/static/index/medicine-2.png',
  208. name: '月度装定制营养包',
  209. type: '保健品',
  210. content: '控糖精华萃 x30颗、膳食纤维 ×30颗',
  211. price: 688.00,
  212. count: 1,
  213. countDesc: '1月装',
  214. free: true,
  215. },
  216. {
  217. id: '0013',
  218. url: '/pages_order/static/index/medicine-3.png',
  219. name: '月度装定制营养包',
  220. type: '保健品',
  221. content: '控糖精华萃 x30颗、膳食纤维 ×30颗',
  222. price: 688.00,
  223. count: 1,
  224. countDesc: '1月装',
  225. free: true,
  226. },
  227. ],
  228. serviceRecords: [
  229. {
  230. id: '003',
  231. title: '退款成功',
  232. desc: '平台已为您退款,具体到账时间请查询支付账户',
  233. createTime: '2025-04-20 12:00',
  234. },
  235. {
  236. id: '002',
  237. title: '等待审核',
  238. desc: '您的服务单已申请成功,待售后审核',
  239. createTime: '2025-04-20 12:00',
  240. },
  241. {
  242. id: '001',
  243. title: '提交申请',
  244. desc: '包装破损',
  245. createTime: '2025-04-20 12:00',
  246. },
  247. ],
  248. userName: '周小艺',
  249. phone: '15558661691',
  250. number: 'BH872381728321983929',
  251. createTime: '2025-04-28 08:14',
  252. status: 5,
  253. }
  254. console.log('addressData', this.addressData)
  255. console.log('orderData', this.orderData)
  256. },
  257. onPay() {
  258. const {
  259. id,
  260. title,
  261. amount
  262. } = this.orderData
  263. const obj = {
  264. title,
  265. orderId: id,
  266. amount,
  267. }
  268. this.$refs.payPopup.open(obj)
  269. },
  270. onConfirmReceipt() {
  271. // todo: fetch confirm
  272. this.fetchOrderDetail()
  273. },
  274. onComment() {
  275. this.$utils.navigateTo(`/pages_order/comment/commentWrite?id=${this.orderData.id}`)
  276. },
  277. onApplyService() {
  278. const {
  279. id,
  280. productList,
  281. } = this.orderData
  282. const obj = {
  283. id,
  284. productList,
  285. }
  286. this.$refs.serviceSelectPopup.open(obj)
  287. },
  288. },
  289. }
  290. </script>
  291. <style scoped lang="scss">
  292. .page__view {
  293. width: 100vw;
  294. min-height: 100vh;
  295. background-color: $uni-bg-color;
  296. position: relative;
  297. /deep/ .nav-bar__view {
  298. position: fixed;
  299. top: 0;
  300. left: 0;
  301. }
  302. }
  303. .main {
  304. padding: calc(var(--status-bar-height) + 144rpx) 32rpx 224rpx 32rpx;
  305. }
  306. .address {
  307. padding: 24rpx 32rpx;
  308. background: #FFFFFF;
  309. border-radius: 24rpx;
  310. justify-content: flex-start;
  311. }
  312. .card {
  313. margin-top: 40rpx;
  314. padding: 32rpx;
  315. background: #FAFAFF;
  316. border: 2rpx solid #FFFFFF;
  317. border-radius: 32rpx;
  318. &-top {
  319. margin-bottom: 32rpx;
  320. justify-content: space-between;
  321. .title {
  322. font-family: PingFang SC;
  323. font-weight: 500;
  324. font-size: 36rpx;
  325. line-height: 1.4;
  326. color: #252545;
  327. }
  328. .status {
  329. display: inline-flex;
  330. min-width: 120rpx;
  331. padding: 6rpx 0;
  332. box-sizing: border-box;
  333. font-family: PingFang SC;
  334. font-weight: 400;
  335. font-size: 24rpx;
  336. line-height: 1.4;
  337. color: #252545;
  338. background: #F3F3F3;
  339. border-radius: 12rpx;
  340. &-0 {
  341. color: #FF860E;
  342. background: #FFF4E9;
  343. }
  344. &-1 {
  345. color: #2799E0;
  346. background: #EEF7FD;
  347. }
  348. &-2 {
  349. color: #7D27E0;
  350. background: #F5EEFD;
  351. }
  352. &-5 {
  353. color: #E53C29;
  354. background: #FDE7E5;
  355. }
  356. }
  357. }
  358. .row {
  359. justify-content: space-between;
  360. font-family: PingFang SC;
  361. font-weight: 400;
  362. font-size: 28rpx;
  363. line-height: 1.4;
  364. &-label {
  365. flex: none;
  366. color: #8B8B8B;
  367. }
  368. &-content {
  369. color: #393939;
  370. }
  371. }
  372. &.detail {
  373. .product {
  374. margin-bottom: 32rpx;
  375. column-gap: 24rpx;
  376. .img {
  377. flex: none;
  378. width: 120rpx;
  379. height: 120rpx;
  380. }
  381. .info {
  382. flex: 1;
  383. padding: 24rpx 32rpx;
  384. background: #FFFFFF;
  385. border-radius: 32rpx;
  386. .row {
  387. margin-bottom: 16rpx;
  388. justify-content: flex-start;
  389. column-gap: 4rpx;
  390. }
  391. .price {
  392. justify-content: flex-start;
  393. column-gap: 8rpx;
  394. font-family: PingFang SC;
  395. font-weight: 500;
  396. line-height: 1.4;
  397. &-label {
  398. font-weight: 400;
  399. font-size: 26rpx;
  400. color: #8B8B8B;
  401. }
  402. &-unit {
  403. font-size: 24rpx;
  404. color: #7451DE;
  405. }
  406. &-value {
  407. font-size: 32rpx;
  408. color: #7451DE;
  409. }
  410. }
  411. }
  412. }
  413. .card-bottom {
  414. .price {
  415. column-gap: 8rpx;
  416. font-family: PingFang SC;
  417. font-weight: 500;
  418. font-size: 24rpx;
  419. line-height: 1.4;
  420. color: #7451DE;
  421. &-value {
  422. font-size: 32rpx;
  423. }
  424. }
  425. }
  426. }
  427. &.info {
  428. .row + .row {
  429. margin-top: 32rpx;
  430. }
  431. }
  432. &.service {
  433. .step {
  434. &-header {
  435. justify-content: flex-start;
  436. column-gap: 24rpx;
  437. padding-left: 24rpx;
  438. }
  439. &-title {
  440. font-family: PingFang SC;
  441. font-weight: 400;
  442. font-size: 30rpx;
  443. line-height: 1.4;
  444. color: #000000;
  445. &.highlight {
  446. font-weight: 500;
  447. color: #10A934;
  448. }
  449. }
  450. &-time {
  451. font-family: PingFang SC;
  452. font-weight: 400;
  453. font-size: 24rpx;
  454. line-height: 1.4;
  455. color: #8B8B8B;
  456. }
  457. &-desc {
  458. padding: 16rpx 0 16rpx 24rpx;
  459. font-family: PingFang SC;
  460. font-weight: 400;
  461. font-size: 24rpx;
  462. line-height: 1.4;
  463. color: #777777;
  464. }
  465. }
  466. }
  467. }
  468. .notice {
  469. margin-top: 40rpx;
  470. font-family: PingFang SC;
  471. font-weight: 400;
  472. &-header {
  473. font-size: 28rpx;
  474. line-height: 1.4;
  475. color: #393939;
  476. }
  477. &-content {
  478. margin-top: 24rpx;
  479. font-size: 24rpx;
  480. line-height: 1.4;
  481. color: #BABABA;
  482. }
  483. }
  484. .bottom {
  485. position: fixed;
  486. left: 0;
  487. bottom: 0;
  488. z-index: 2;
  489. column-gap: 32rpx;
  490. width: 100vw;
  491. height: 200rpx;
  492. padding: 24rpx 40rpx;
  493. background: #FFFFFF;
  494. box-sizing: border-box;
  495. .btn {
  496. background: transparent;
  497. border: none;
  498. &-service {
  499. flex: none;
  500. row-gap: 4rpx;
  501. font-family: PingFang SC;
  502. font-weight: 400;
  503. font-size: 22rpx;
  504. line-height: 1.1;
  505. color: #999999;
  506. &-icon {
  507. width: 52rpx;
  508. height: auto;
  509. }
  510. }
  511. }
  512. .cols {
  513. flex: 1;
  514. column-gap: 32rpx;
  515. .col {
  516. flex: 1;
  517. }
  518. .btn {
  519. padding: 14rpx 0;
  520. box-sizing: border-box;
  521. font-family: PingFang SC;
  522. font-weight: 500;
  523. font-size: 36rpx;
  524. line-height: 1.4;
  525. color: #252545;
  526. border: 2rpx solid #252545;
  527. border-radius: 41rpx;
  528. &-primary {
  529. padding: 16rpx 0;
  530. color: #FFFFFF;
  531. background-image: linear-gradient(to right, #4B348F, #845CFA);
  532. border: none;
  533. }
  534. }
  535. .price {
  536. column-gap: 8rpx;
  537. font-family: PingFang SC;
  538. font-weight: 400;
  539. font-size: 24rpx;
  540. line-height: 1.4;
  541. &-label {
  542. color: #626262;
  543. }
  544. &-unit,
  545. &-value {
  546. font-weight: 500;
  547. color: #7451DE;
  548. .highlight {
  549. font-size: 40rpx;
  550. }
  551. }
  552. &-value {
  553. font-size: 40rpx;
  554. }
  555. }
  556. }
  557. }
  558. </style>