hookehuyr

feat(订单): 重构订单模块,实现真实API对接

- 修改订单API接口,简化并适配后端接口
- 商品详情页增加卖家判断逻辑,隐藏不相关操作
- 订单列表页重构,对接真实数据并优化分页加载
- 实现订单评价功能,对接真实API
- 优化订单详情展示,显示更多真实数据
1 /* 1 /*
2 - * @Date: 2024-01-01 00:00:00 2 + * @Date: 2025-07-03 17:21:45
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-07-09 15:00:24 4 + * @LastEditTime: 2025-07-14 09:34:58
5 * @FilePath: /jgdl/src/api/orders.js 5 * @FilePath: /jgdl/src/api/orders.js
6 - * @Description: 车辆订单相关API接口 6 + * @Description: 文件描述
7 */ 7 */
8 -import { fn, fetch } from './fn'; 8 +import { fn, fetch } from '@/api/fn';
9 9
10 -// API 端点定义 10 +const Api = {
11 -const OrderApi = { 11 + GET_ORDER_LIST: '/srv/?a=order&t=list',
12 - // 获取我的订单列表 12 + GET_ORDER_DETAIL: '/srv/?a=order&t=detail',
13 - GET_MY_ORDERS: '/api/orders/my-orders', 13 + CREATE_ORDER: '/srv/?a=order&t=add',
14 - // 获取订单详情 14 + REVIEW_ORDER: '/srv/?a=order&t=review',
15 - GET_ORDER_DETAIL: '/api/orders/detail', 15 + DELETE_ORDER: '/srv/?a=order&t=del',
16 - // 删除订单 16 +}
17 - DELETE_ORDER: '/api/orders/delete',
18 - // 取消订单
19 - CANCEL_ORDER: '/api/orders/cancel',
20 - // 确认收货
21 - CONFIRM_ORDER: '/api/orders/confirm',
22 - // 提交评价
23 - SUBMIT_REVIEW: '/api/orders/review',
24 - // 申请退款
25 - REQUEST_REFUND: '/api/orders/refund',
26 -};
27 17
28 /** 18 /**
29 - * @description: 获取我的订单列表 19 + * @description: 获取订单列表
30 - * @param {Object} params 20 + * @param page 页码,从0开始
31 - * @param {string} params.type - 订单类型 'bought' | 'sold' 21 + * @param page_size 每页数量
32 - * @param {number} params.page - 页码 22 + * @param type 列表类型。buy=我买的,sell=我卖的
33 - * @param {number} params.limit - 每页数量 23 + * @param status 订单状态(3=待支付, 5=已完成, 7=已取消)
34 - * @param {string} params.status - 订单状态筛选(可选) 24 + * @returns data{ list[{ id, title, total_amount, status, create_time, payment_time, details{ id, vehicle_id, quantity, vehicle{} } }] }
35 - * @returns {Promise}
36 */ 25 */
37 -export const getMyOrdersAPI = (params) => { 26 +export const getOrderListAPI = (params) => fn(fetch.get(Api.GET_ORDER_LIST, params));
38 - // TODO: 替换为真实的API调用
39 - return fn(fetch.get(OrderApi.GET_MY_ORDERS, params));
40 -};
41 27
42 /** 28 /**
43 * @description: 获取订单详情 29 * @description: 获取订单详情
44 - * @param {Object} params 30 + * @param id 订单ID
45 - * @param {string} params.orderId - 订单ID 31 + * @returns data{ id, title, total_amount, status, create_time, payment_time, details{ id, vehicle_id, quantity, vehicle{ id, title, price, cover_image } } }
46 - * @returns {Promise}
47 */ 32 */
48 -export const getOrderDetailAPI = (params) => { 33 +export const getOrderDetailAPI = (params) => fn(fetch.get(Api.GET_ORDER_DETAIL, params));
49 - // TODO: 替换为真实的API调用
50 - return fn(fetch.get(OrderApi.GET_ORDER_DETAIL, params));
51 -};
52 34
53 /** 35 /**
54 - * @description: 删除订单 36 + * @description: 创建订单
55 - * @param {Object} params 37 + * @param vehicle_id 车辆ID
56 - * @param {string} params.orderId - 订单ID 38 + * @param total_amount 总价
57 - * @returns {Promise} 39 + * @returns data{ id }
58 - *
59 - * @example
60 - * // 使用示例:
61 - * try {
62 - * const response = await deleteOrderAPI({ orderId: 'ORDER_123' });
63 - * if (response.success) {
64 - * console.log('删除成功:', response.message);
65 - * }
66 - * } catch (error) {
67 - * console.error('删除失败:', error.message);
68 - * }
69 - *
70 - * @apiResponse
71 - * {
72 - * success: true,
73 - * message: '订单删除成功',
74 - * data: null
75 - * }
76 */ 40 */
77 -export const deleteOrderAPI = (params) => { 41 +export const createOrderAPI = (params) => fn(fetch.post(Api.CREATE_ORDER, params));
78 - // TODO: 替换为真实的API调用
79 - // 当集成真实API时,请确保:
80 - // 1. 处理网络错误和超时
81 - // 2. 验证用户权限(只能删除自己的订单)
82 - // 3. 检查订单状态(只有特定状态的订单才能删除)
83 - // 4. 返回统一的响应格式
84 - return fn(fetch.delete(OrderApi.DELETE_ORDER, params));
85 -};
86 42
87 /** 43 /**
88 - * @description: 取消订单 44 + * @description: 订单评价
89 - * @param {Object} params 45 + * @param detail_id 订单ID
90 - * @param {string} params.orderId - 订单ID 46 + * @param rating 评级(1到5分)
91 - * @param {string} params.reason - 取消原因(可选) 47 + * @param note 评价内容
92 - * @returns {Promise} 48 + * @returns data{}
93 */ 49 */
94 -export const cancelOrderAPI = (params) => { 50 +export const reviewOrderAPI = (params) => fn(fetch.post(Api.REVIEW_ORDER, params));
95 - // TODO: 替换为真实的API调用
96 - return fn(fetch.post(OrderApi.CANCEL_ORDER, params));
97 -};
98 51
99 /** 52 /**
100 - * @description: 确认收货/完成交易 53 + * @description: 删除订单
101 - * @param {Object} params 54 + * @param order_id 订单ID
102 - * @param {string} params.orderId - 订单ID 55 + * @returns data{}
103 - * @returns {Promise}
104 - */
105 -export const confirmOrderAPI = (params) => {
106 - // TODO: 替换为真实的API调用
107 - return fn(fetch.post(OrderApi.CONFIRM_ORDER, params));
108 -};
109 -
110 -/**
111 - * @description: 提交订单评价
112 - * @param {Object} params
113 - * @param {string} params.orderId - 订单ID
114 - * @param {number} params.rating - 评分 (1-5)
115 - * @param {string} params.comment - 评价内容
116 - * @param {Array} params.images - 评价图片(可选)
117 - * @returns {Promise}
118 - *
119 - * @example
120 - * // 使用示例:
121 - * try {
122 - * const response = await submitReviewAPI({
123 - * orderId: 'ORDER_123',
124 - * rating: 5,
125 - * comment: '车况很好,卖家服务态度也很棒!',
126 - * images: ['image1.jpg', 'image2.jpg'] // 可选
127 - * });
128 - * if (response.success) {
129 - * console.log('评价提交成功:', response.message);
130 - * }
131 - * } catch (error) {
132 - * console.error('评价提交失败:', error.message);
133 - * }
134 - *
135 - * @apiResponse
136 - * {
137 - * success: true,
138 - * message: '评价提交成功',
139 - * data: {
140 - * reviewId: 'REVIEW_123',
141 - * createdAt: '2024-01-01T12:00:00Z'
142 - * }
143 - * }
144 - */
145 -export const submitReviewAPI = (params) => {
146 - // TODO: 替换为真实的API调用
147 - // 当集成真实API时,请确保:
148 - // 1. 验证评分范围(1-5)
149 - // 2. 验证评价内容长度限制
150 - // 3. 处理图片上传(如果有)
151 - // 4. 检查订单状态(只有已完成的订单才能评价)
152 - // 5. 防止重复评价
153 - return fn(fetch.post(OrderApi.SUBMIT_REVIEW, params));
154 -};
155 -
156 -/**
157 - * @description: 申请退款
158 - * @param {Object} params
159 - * @param {string} params.orderId - 订单ID
160 - * @param {string} params.reason - 退款原因
161 - * @param {number} params.amount - 退款金额
162 - * @param {Array} params.evidence - 退款凭证(可选)
163 - * @returns {Promise}
164 */ 56 */
165 -export const requestRefundAPI = (params) => { 57 +export const deleteOrderAPI = (params) => fn(fetch.post(Api.DELETE_ORDER, params));
166 - // TODO: 替换为真实的API调用
167 - return fn(fetch.post(OrderApi.REQUEST_REFUND, params));
168 -};
169 -
170 -// 导出所有API
171 -export default {
172 - getMyOrdersAPI,
173 - getOrderDetailAPI,
174 - deleteOrderAPI,
175 - cancelOrderAPI,
176 - confirmOrderAPI,
177 - submitReviewAPI,
178 - requestRefundAPI,
179 -};
......
This diff is collapsed. Click to expand it.
1 <!-- 1 <!--
2 * @Date: 2022-09-19 14:11:06 2 * @Date: 2022-09-19 14:11:06
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-07-11 14:56:02 4 + * @LastEditTime: 2025-07-14 09:34:00
5 * @FilePath: /jgdl/src/pages/productDetail/index.vue 5 * @FilePath: /jgdl/src/pages/productDetail/index.vue
6 * @Description: 商品详情页 6 * @Description: 商品详情页
7 --> 7 -->
...@@ -136,7 +136,7 @@ ...@@ -136,7 +136,7 @@
136 </view> 136 </view>
137 137
138 <!-- 卖家信息 --> 138 <!-- 卖家信息 -->
139 - <view class="seller-info bg-white mt-2 p-4 mb-2"> 139 + <view v-if="!isCurrentUserSeller" class="seller-info bg-white mt-2 p-4 mb-2">
140 <text class="text-lg font-medium mb-3 block">卖家信息</text> 140 <text class="text-lg font-medium mb-3 block">卖家信息</text>
141 <view class="flex items-center justify-between"> 141 <view class="flex items-center justify-between">
142 <view class="flex items-center"> 142 <view class="flex items-center">
...@@ -167,7 +167,7 @@ ...@@ -167,7 +167,7 @@
167 </view> 167 </view>
168 168
169 <!-- 底部按钮 --> 169 <!-- 底部按钮 -->
170 - <view class="bottom-actions"> 170 + <view v-if="!isCurrentUserSeller" class="bottom-actions">
171 <nut-row :gutter="10"> 171 <nut-row :gutter="10">
172 <nut-col :span="12"> 172 <nut-col :span="12">
173 <nut-button @click="handleContactSeller" block type="default" shape="round" 173 <nut-button @click="handleContactSeller" block type="default" shape="round"
...@@ -245,17 +245,20 @@ ...@@ -245,17 +245,20 @@
245 </template> 245 </template>
246 246
247 <script setup> 247 <script setup>
248 -import { ref, onMounted } from 'vue' 248 +import { ref, onMounted, computed } from 'vue'
249 import Taro, { useShareAppMessage } from '@tarojs/taro' 249 import Taro, { useShareAppMessage } from '@tarojs/taro'
250 import { Share, Heart1, HeartFill, Message } from '@nutui/icons-vue-taro' 250 import { Share, Heart1, HeartFill, Message } from '@nutui/icons-vue-taro'
251 import payCard from '@/components/payCard.vue' 251 import payCard from '@/components/payCard.vue'
252 import { useFavorite } from '@/composables/useFavorite' 252 import { useFavorite } from '@/composables/useFavorite'
253 -import avatarImg from '@/assets/images/avatar.png' 253 +// import avatarImg from '@/assets/images/avatar.png'
254 import { getCurrentPageParam } from "@/utils/weapp" 254 import { getCurrentPageParam } from "@/utils/weapp"
255 import { checkPermission, PERMISSION_TYPES } from '@/utils/permission' 255 import { checkPermission, PERMISSION_TYPES } from '@/utils/permission'
256 // 导入接口 256 // 导入接口
257 import { getVehicleDetailAPI } from '@/api/car' 257 import { getVehicleDetailAPI } from '@/api/car'
258 +import { createOrderAPI } from '@/api/orders'
258 import { DEFAULT_COVER_IMG } from '@/utils/config' 259 import { DEFAULT_COVER_IMG } from '@/utils/config'
260 +// 导入用户 store
261 +import { useUserStore } from '@/stores/user'
259 262
260 // 默认头像 263 // 默认头像
261 const defaultAvatar = 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg' 264 const defaultAvatar = 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'
...@@ -288,14 +291,14 @@ const quickTags = ref([ ...@@ -288,14 +291,14 @@ const quickTags = ref([
288 ]) 291 ])
289 292
290 // 备用图片数组 293 // 备用图片数组
291 -const fallbackImages = ref([ 294 +// const fallbackImages = ref([
292 - avatarImg, 295 +// avatarImg,
293 - avatarImg, 296 +// avatarImg,
294 - avatarImg, 297 +// avatarImg,
295 - avatarImg, 298 +// avatarImg,
296 - avatarImg 299 +// avatarImg
297 -]) 300 +// ])
298 -const imageLoadErrors = ref(new Set()) 301 +// const imageLoadErrors = ref(new Set())
299 302
300 // 模拟商品数据 303 // 模拟商品数据
301 const product = ref({}) 304 const product = ref({})
...@@ -304,13 +307,23 @@ const product = ref({}) ...@@ -304,13 +307,23 @@ const product = ref({})
304 * 轮播图切换事件 307 * 轮播图切换事件
305 * @param {number} index - 当前图片索引 308 * @param {number} index - 当前图片索引
306 */ 309 */
307 -// const onSwiperChange = (index) => { 310 +const onSwiperChange = (index) => {
308 -// currentImageIndex.value = index 311 + currentImageIndex.value = index
309 -// } 312 +}
310 313
311 // 使用收藏功能composables 314 // 使用收藏功能composables
312 const { toggleFavorite } = useFavorite() 315 const { toggleFavorite } = useFavorite()
313 316
317 +// 使用用户 store
318 +const userStore = useUserStore()
319 +
320 +/**
321 + * 判断当前用户是否为卖家
322 + */
323 +const isCurrentUserSeller = computed(() => {
324 + return product.value.seller?.id && userStore.userInfo.id && product.value.seller.id === userStore.userInfo.id
325 +})
326 +
314 /** 327 /**
315 * 显示微信号弹框 328 * 显示微信号弹框
316 */ 329 */
...@@ -406,11 +419,21 @@ const handlePurchase = async () => { ...@@ -406,11 +419,21 @@ const handlePurchase = async () => {
406 * @param {number} payInfo.remain_time - 剩余时间 419 * @param {number} payInfo.remain_time - 剩余时间
407 * @param {number} payInfo.price - 价格 420 * @param {number} payInfo.price - 价格
408 */ 421 */
409 -const onPay = ({ id, remain_time, price }) => { 422 +const onPay = async ({ id, remain_time, price }) => {
423 + try {
424 + const { code, data } = await createOrderAPI({
425 + vehicle_id: id,
426 + total_amount: price
427 + })
428 + if (code) {
410 show_pay.value = true 429 show_pay.value = true
411 - payData.value.id = id 430 + payData.value.id = data.id
412 payData.value.price = price 431 payData.value.price = price
413 payData.value.remain_time = remain_time 432 payData.value.remain_time = remain_time
433 + }
434 + } catch (error) {
435 + console.error('创建订单失败:', error)
436 + }
414 } 437 }
415 438
416 /** 439 /**
...@@ -471,6 +494,9 @@ function filterEmptyValues(arr) { ...@@ -471,6 +494,9 @@ function filterEmptyValues(arr) {
471 } 494 }
472 495
473 onMounted(async () => { 496 onMounted(async () => {
497 + // 获取用户信息
498 + await userStore.fetchUserInfo()
499 +
474 // 获取商品详情 500 // 获取商品详情
475 let params = getCurrentPageParam(); 501 let params = getCurrentPageParam();
476 const { code, data } = await getVehicleDetailAPI({ id: params.id }) 502 const { code, data } = await getVehicleDetailAPI({ id: params.id })
......