敢为人鲜小程序前端代码仓库
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.

540 lines
14 KiB

4 weeks ago
4 weeks ago
4 weeks ago
  1. <template>
  2. <view class="page">
  3. <!-- 导航栏 -->
  4. <navbar title="订单详情 " leftClick @leftClick="navigateBack" bgColor="#019245"
  5. color="#fff" />
  6. <!-- 店铺信息 -->
  7. <view class="shop-info">
  8. <view class="shop-header">
  9. <image class="shop-logo" :src="teamLeader.spotImage" mode="aspectFill"></image>
  10. <view class="shop-name-container">
  11. <text class="shop-name"> {{ teamLeader.spotName }} </text>
  12. <view class="shop-address">
  13. <view style="padding-top: 7rpx;">
  14. <!-- 需要置顶 -->
  15. <uv-icon name="map-fill" color="#019245" size="28rpx"></uv-icon>
  16. </view>
  17. <text class="address-text">{{ teamLeader.area }} {{ teamLeader.address }}</text>
  18. </view>
  19. <view class="shop-phone">
  20. <view style="padding-top: 7rpx;">
  21. <!-- 需要置顶 -->
  22. <uv-icon name="phone-fill" color="#019245" size="28rpx"></uv-icon>
  23. </view>
  24. <text class="phone-text">{{teamLeader.phone}}</text>
  25. </view>
  26. </view>
  27. </view>
  28. </view>
  29. <view class="order-status">
  30. <!-- 商品列表 -->
  31. <view class="food-list">
  32. <view class="food-item" v-for="(food, index) in showedFoods" :key="food.id">
  33. <image class="food-image" :src="food.goods.image" mode="aspectFill" />
  34. <view class="food-info">
  35. <text class="food-name">{{food.goods.title}}</text>
  36. <view class="food-sold">
  37. <uv-icon name="bag" size="28rpx"></uv-icon>
  38. <text>已售出 {{ food.goods.sales }}</text>
  39. </view>
  40. <text class="food-price"> <text style="font-size: 20rpx;"></text> {{food.goods.price}}</text>
  41. <text class="food-count">×{{food.num}}</text>
  42. </view>
  43. </view>
  44. <view class="expand-more" @tap="showAllFoods = !showAllFoods" v-if="orderDetail.goodsList.length > 3">
  45. <text>{{showAllFoods ? '收起' : '展开'}} ({{orderDetail.goodsList.length}})</text>
  46. <uv-icon :name="showAllFoods ? 'arrow-up' : 'arrow-down'" size="28rpx"></uv-icon>
  47. </view>
  48. </view>
  49. <!-- 订单信息 -->
  50. <view class="order-info">
  51. <view class="info-item">
  52. <text class="info-label">合计:</text>
  53. <text class="info-value price">{{ orderDetail.priceAll }}</text>
  54. </view>
  55. <view class="info-item" v-if="this.orderDetail.status != '-1'" >
  56. <text class="info-label">创建时间:</text>
  57. <text class="info-value">{{ orderDetail.createTime }}</text>
  58. </view>
  59. <view class="info-item" v-if="this.orderDetail.status != '-1'">
  60. <text class="info-label">订单编号:</text>
  61. <text class="info-value">{{orderDetail.id}}</text>
  62. </view>
  63. </view>
  64. </view>
  65. <view class="discount-info-container">
  66. <!-- 优惠信息 -->
  67. <view class="discount-info" @click="gotoCoupon">
  68. <view class="discount-header">
  69. <text>优惠</text>
  70. </view>
  71. <view class="discount-item">
  72. <view class="discount-left">
  73. <image src="@/static/image/券.webp" mode="aspectFill" class="coupon-icon" />
  74. <view>新用户立减</view>
  75. </view>
  76. <text class="discount-amount">-{{ orderDetail.pricePreferential || 0 }}</text>
  77. </view>
  78. </view>
  79. <!-- 备注 -->
  80. <view class="remark-section">
  81. <view class="remark-header">
  82. <text>备注</text>
  83. </view>
  84. <view class="remark-content">
  85. <input v-if="orderDetail.status_dictText === '待支付'" type="text" v-model="orderDetail.remark"
  86. placeholder="请输入您要备注的内容" placeholder-style="font-size: 28rpx" />
  87. <text v-else>{{orderDetail.remark || '无备注信息'}}</text>
  88. </view>
  89. </view>
  90. </view>
  91. <!-- 支付方式 -->
  92. <uv-radio-group v-model="payMethod" v-if="orderDetail.status_dictText === '待支付'">
  93. <view class="payment-methods">
  94. <view class="payment-item">
  95. <uv-icon name="weixin-circle-fill" size="70rpx" color="#019245" />
  96. <text class="payment-name">微信支付</text>
  97. <uv-radio activeColor="#019245" size="40rpx" name="weixin" />
  98. </view>
  99. <view class="payment-item">
  100. <uv-icon name="red-packet" size="70rpx" color="#019245" />
  101. <text class="payment-name">账户余额<text class="balance-text">(余额: {{ userInfo.balance }})</text></text>
  102. <uv-radio activeColor="#019245" size="40rpx" name="account" />
  103. </view>
  104. </view>
  105. </uv-radio-group>
  106. <!-- 底部支付栏 -->
  107. <view class="bottom-bar">
  108. <view class="total-section">
  109. <text class="total-label">{{ orderDetail.goodsList.length || 0 }}<text style="color: black;">合计</text> </text>
  110. <text class="total-price">{{ orderDetail.pricePay || cartPay }}</text>
  111. </view>
  112. <view class="pay-button" @tap="handlePay" v-if="orderStatus === '待支付'">立即下单</view>
  113. <view class="pay-button" @tap="handlePay" v-if="orderStatus === '已送达'">立即取餐</view>
  114. </view>
  115. </view>
  116. </template>
  117. <script>
  118. import navbar from '@/components/base/navbar.vue'
  119. import { mapState } from 'vuex'
  120. import Cart from '../../pages/index/cart.vue'
  121. export default {
  122. components: {
  123. navbar
  124. },
  125. data() {
  126. return {
  127. id: '',
  128. payMethod: 'weixin',
  129. showAllFoods: false,
  130. orderStatus: '',
  131. orderDetail: { },
  132. cartDiscount: 0
  133. }
  134. },
  135. computed: {
  136. ...mapState(['cartData']),
  137. // statusText() {
  138. // const statusMap = {
  139. // 'pending': '等待支付',
  140. // 'processing': '正在出餐',
  141. // 'shipping': '正在配送中',
  142. // 'delivered': '已送达,等待取餐',
  143. // 'completed': '订单已完成',
  144. // 'canceled': '订单已取消'
  145. // }
  146. // return statusMap[this.orderDetail.status] || '等待支付'
  147. // },
  148. showedFoods() {
  149. return this.showAllFoods ? this.orderDetail.goodsList : this.orderDetail.goodsList.slice(0, 3)
  150. },
  151. teamLeader() {
  152. return this.orderDetail.teamLeader
  153. },
  154. cartPay() {
  155. return this.orderDetail.priceAll - this.cartDiscount
  156. },
  157. },
  158. onLoad(options) {
  159. // 如果是购物车调过来的结账页面
  160. if (options.status === 'cart') {
  161. this.showCartData()
  162. // 独一无二代表购物车的状态
  163. this.orderStatus = '-1'
  164. }
  165. else if (options.id) {
  166. this.getOrderDetail(options.id)
  167. this.orderStatus = options.status
  168. }
  169. },
  170. methods: {
  171. // 返回上一页
  172. navigateBack() {
  173. uni.navigateBack()
  174. },
  175. // 如果是购物车结账页面
  176. showCartData() {
  177. this.$api('queryMyLeader', {}, res => {
  178. if (res.code === 200) {
  179. this.orderDetail.teamLeader =
  180. {
  181. ...res.result
  182. }
  183. }
  184. })
  185. console.log('cartData', this.cartData);
  186. this.orderDetail.goodsList = this.cartData.sendData
  187. this.orderDetail.priceAll = this.cartData.priceAll
  188. },
  189. // 获取订单详情
  190. getOrderDetail(id) {
  191. this.id = id
  192. this.$api('queryMemberOrderList', {
  193. id: this.id
  194. }, res => {
  195. if (res.code === 200) {
  196. this.orderDetail = res.result.records[0]
  197. }
  198. })
  199. },
  200. // 处理支付
  201. handlePay() {
  202. uni.showLoading({
  203. title: '支付处理中...'
  204. })
  205. // 模拟支付过程
  206. setTimeout(() => {
  207. uni.hideLoading()
  208. uni.showToast({
  209. title: '支付成功',
  210. icon: 'success',
  211. duration: 2000
  212. })
  213. // 支付成功后,跳转回订单列表页面,并刷新
  214. setTimeout(() => {
  215. this.navigateBack()
  216. // 页面栈中的order页面需要刷新
  217. const pages = getCurrentPages()
  218. const prevPage = pages[pages.length - 2]
  219. if (prevPage && prevPage.route.includes('order')) {
  220. // 更新上一页的数据
  221. prevPage.$vm.loadMockOrders()
  222. prevPage.$vm.filterOrdersByStatus(1) // 切换到待出餐Tab
  223. prevPage.$vm.current = 1 // 更新Tab索引
  224. }
  225. }, 1000)
  226. }, 2000)
  227. },
  228. // 去优惠页面
  229. gotoCoupon() {
  230. this.$utils.navigateTo({
  231. url: '/pages_order/mine/coupon?isUseinOrder=true'
  232. })
  233. }
  234. }
  235. }
  236. </script>
  237. <style lang="scss" scoped>
  238. .page {
  239. background-color: #f5f5f5;
  240. min-height: 100vh;
  241. padding-bottom: 120rpx;
  242. }
  243. .status-bar {
  244. background-color: #019245;
  245. padding: 30rpx;
  246. color: #fff;
  247. font-size: 32rpx;
  248. font-weight: 500;
  249. }
  250. .shop-info {
  251. background-color: #fff;
  252. margin: 20rpx;
  253. border-radius: 16rpx;
  254. padding: 20rpx;
  255. .shop-header {
  256. display: flex;
  257. align-items: center;
  258. // background-color: red;
  259. .shop-logo {
  260. width: 150rpx;
  261. height: 150rpx;
  262. // border-radius: 10rpx;
  263. margin-right: 20rpx;
  264. }
  265. .shop-name-container {
  266. flex: 1;
  267. .shop-name {
  268. font-size: 30rpx;
  269. font-weight: 500;
  270. margin-bottom: 10rpx;
  271. display: block;
  272. }
  273. .shop-address, .shop-phone {
  274. display: flex;
  275. align-items: start;
  276. font-size: 24rpx;
  277. color: $uni-color-third;
  278. margin-top: 8rpx;
  279. .address-text, .phone-text {
  280. margin-left: 8rpx;
  281. width: 80%;
  282. white-space: wrap;
  283. // overflow: hidden;
  284. // text-overflow: ellipsis;
  285. }
  286. }
  287. .shop-address-top{
  288. display: flex;
  289. align-items: start;
  290. background-color: red;
  291. // gap: 10rpx;
  292. }
  293. }
  294. }
  295. }
  296. .order-status{
  297. background-color: #fff;
  298. margin: 20rpx;
  299. border-radius: 16rpx;
  300. padding: 20rpx;
  301. .food-list {
  302. // gap: 20rpx;
  303. // background-color: #019245;
  304. .food-item {
  305. display: flex;
  306. margin-bottom: 20rpx;
  307. // background-color: red;
  308. .food-image {
  309. width: 120rpx;
  310. height: 120rpx;
  311. // border-radius: 10rpx;
  312. margin-right: 20rpx;
  313. }
  314. .food-info {
  315. flex: 1;
  316. display: flex;
  317. flex-direction: column;
  318. justify-content: space-between;
  319. position: relative;
  320. .food-name {
  321. font-size: 28rpx;
  322. font-weight: 500;
  323. }
  324. .food-sold {
  325. display: flex;
  326. align-items: center;
  327. font-size: 24rpx;
  328. color: $uni-color-third;
  329. }
  330. .food-price {
  331. font-size: 28rpx;
  332. color: #f00;
  333. }
  334. .food-count {
  335. color: black;
  336. position: absolute;
  337. bottom: 50%;
  338. right: 0;
  339. }
  340. }
  341. }
  342. .expand-more {
  343. display: flex;
  344. align-items: center;
  345. justify-content: center;
  346. padding: 20rpx 0 0;
  347. font-size: 24rpx;
  348. color: $uni-color-third;
  349. }
  350. }
  351. .order-info {
  352. padding-top: 20rpx;
  353. .info-item {
  354. display: flex;
  355. justify-content: space-between;
  356. margin-bottom: 15rpx;
  357. font-size: 26rpx;
  358. .info-label {
  359. color: black;
  360. }
  361. .info-value {
  362. color: #333;
  363. &.price {
  364. color: #f00;
  365. font-weight: 500;
  366. }
  367. }
  368. }
  369. }
  370. }
  371. .discount-info-container {
  372. background-color: #fff;
  373. margin: 20rpx;
  374. border-radius: 16rpx;
  375. padding: 20rpx;
  376. display: flex;
  377. flex-direction: column;
  378. gap: 40rpx;
  379. }
  380. .discount-info {
  381. display: flex;
  382. align-items: center;
  383. justify-content: space-between;
  384. .discount-header {
  385. font-size: 28rpx;
  386. }
  387. .discount-item {
  388. display: flex;
  389. justify-content: space-between;
  390. align-items: center;
  391. gap: 20rpx;
  392. .discount-left {
  393. display: flex;
  394. align-items: center;
  395. gap: 10rpx;
  396. .coupon-icon {
  397. width: 36rpx;
  398. height: 36rpx;
  399. margin-top: 6rpx;
  400. }
  401. }
  402. .discount-amount {
  403. color: #f00;
  404. font-weight: 500;
  405. }
  406. }
  407. }
  408. .remark-section {
  409. display: flex;
  410. // flex-direction: column;
  411. gap: 40rpx;
  412. // background-color: red;
  413. align-items: center;
  414. .remark-header {
  415. font-size: 28rpx;
  416. // font-weight: 500;
  417. }
  418. .remark-content {
  419. font-size: 26rpx;
  420. color: black;
  421. min-height: 60rpx;
  422. display: flex;
  423. align-items: center;
  424. }
  425. }
  426. .payment-methods {
  427. background-color: #fff;
  428. width: 100%;
  429. margin: 20rpx;
  430. border-radius: 16rpx;
  431. padding: 20rpx;
  432. display: flex;
  433. flex-direction: column;
  434. gap: 20rpx;
  435. .payment-item {
  436. display: flex;
  437. align-items: center;
  438. padding: 20rpx 0;
  439. border-bottom: 1rpx solid #f5f5f5;
  440. &:last-child {
  441. border-bottom: none;
  442. }
  443. .payment-name {
  444. flex: 1;
  445. margin-left: 20rpx;
  446. font-size: 28rpx;
  447. .balance-text {
  448. font-size: 24rpx;
  449. color: $uni-color-third;
  450. margin-left: 10rpx;
  451. }
  452. }
  453. }
  454. }
  455. .bottom-bar {
  456. position: fixed;
  457. bottom: 0;
  458. left: 0;
  459. right: 0;
  460. height: 100rpx;
  461. background-color: #fff;
  462. display: flex;
  463. align-items: center;
  464. padding: 0 30rpx;
  465. box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
  466. .total-section {
  467. flex: 1;
  468. .total-label {
  469. font-size: 26rpx;
  470. color: $uni-color-third;
  471. }
  472. .total-price {
  473. font-size: 32rpx;
  474. color: #f00;
  475. margin-left: 10rpx;
  476. }
  477. }
  478. .pay-button {
  479. width: 240rpx;
  480. height: 80rpx;
  481. background-color: #019245;
  482. color: #fff;
  483. font-size: 30rpx;
  484. display: flex;
  485. align-items: center;
  486. justify-content: center;
  487. border-radius: 40rpx;
  488. }
  489. }
  490. </style>