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

553 lines
14 KiB

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