diff --git a/public/img/product-image.png b/public/img/product-image.png new file mode 100644 index 0000000..e553a04 Binary files /dev/null and b/public/img/product-image.png differ diff --git a/public/img/product-image.svg b/public/img/product-image.svg new file mode 100644 index 0000000..f12a898 --- /dev/null +++ b/public/img/product-image.svg @@ -0,0 +1,6 @@ + + + 空闲 + \ No newline at end of file diff --git a/src/common/apis/approval/index.ts b/src/common/apis/approval/index.ts new file mode 100644 index 0000000..61938b5 --- /dev/null +++ b/src/common/apis/approval/index.ts @@ -0,0 +1,10 @@ +import { request } from '@/http/axios' +import { SubmitApprovalRequestData, SubmitApprovalResponseData } from './type' + +export const submitApprovalApi = (data: SubmitApprovalRequestData) => { + return request({ + url: 'approval/submit', + method: 'post', + data + }) +} \ No newline at end of file diff --git a/src/common/apis/approval/type.ts b/src/common/apis/approval/type.ts new file mode 100644 index 0000000..3d771b2 --- /dev/null +++ b/src/common/apis/approval/type.ts @@ -0,0 +1,11 @@ +export interface SubmitApprovalRequestData { + orderId: number + goodsId: number + returnQuantity: number + returnImages: string +} + +export type SubmitApprovalResponseData = ApiResponseMsgData<{ + approvalId: number + status: number +}> \ No newline at end of file diff --git a/src/layout/components/Tabbar.vue b/src/layout/components/Tabbar.vue index 1827445..9a4b34f 100644 --- a/src/layout/components/Tabbar.vue +++ b/src/layout/components/Tabbar.vue @@ -3,7 +3,7 @@ const router = useRouter() const tabbarItemList = computed(() => { const routes = router.getRoutes() - return routes.filter(route => route.meta.layout?.tabbar?.showTabbar && route.path !== '/cabinet') + return routes.filter(route => route.meta.layout?.tabbar?.showTabbar) .map(route => ({ title: route.meta.title, icon: route.meta.layout?.tabbar?.icon, @@ -22,15 +22,6 @@ const wxStore = useWxStoreOutside() placeholder safe-area-inset-bottom > - - 柜机管理 - +import { ref } from 'vue' +import { showConfirmDialog, showSuccessToast } from 'vant' +import { submitApprovalApi } from '@/common/apis/approval' +import type { SubmitApprovalRequestData } from '@/common/apis/approval/type' +import { useRouter } from 'vue-router' + +const router = useRouter() +const route = useRoute() + +const formData = ref({ + orderId: Number(route.query.orderId), + goodsId: Number(route.query.goodsId), + returnQuantity: 1, + returnImages: '' +}) + +const submitting = ref(false) +const fileList = ref>([]) + +const validateForm = () => { + if (!formData.value.orderId || isNaN(formData.value.orderId)) { + showConfirmDialog({ title: '错误', message: '订单ID参数错误' }) + return false + } + if (!formData.value.goodsId || isNaN(formData.value.goodsId)) { + showConfirmDialog({ title: '错误', message: '商品ID参数错误' }) + return false + } + if (formData.value.returnQuantity < 1) { + showConfirmDialog({ title: '提示', message: '退还数量至少为1' }) + return false + } + return true +} + +const handleSubmit = async () => { + if (!validateForm()) return + + submitting.value = true + try { + formData.value.returnImages = fileList.value.map(f => f.url).join(',') + + const { code } = await submitApprovalApi(formData.value) + + if (code === 0) { + showSuccessToast('提交成功') + router.push({ name: 'approval-result', query: { id: formData.value.orderId } }) + } + } catch (error) { + showConfirmDialog({ + title: '提交失败', + message: error instanceof Error ? error.message : '网络请求异常' + }) + } finally { + submitting.value = false + } +} + + + + + \ No newline at end of file diff --git a/src/pages/cabinet/index.vue b/src/pages/cabinet/index.vue index 894deb0..237f2a5 100644 --- a/src/pages/cabinet/index.vue +++ b/src/pages/cabinet/index.vue @@ -4,41 +4,50 @@ -
- - - - - - +
+
+ + 详情 + + + 立即开启 + +
+ + @@ -48,6 +57,7 @@ import { ref } from 'vue' import { getCabinetDetailApi, openCabinet } from '@/common/apis/cabinet' import type { CabinetDetailDTO } from '@/common/apis/cabinet/type' import { useWxStoreOutside } from '@/pinia/stores/wx' +import { publicPath } from "@/common/utils/path" const wxStore = useWxStoreOutside() @@ -167,94 +177,139 @@ loadCabinetDetail() } } -.locker-item { - width: 100%; - margin: 8px; - border-radius: 8px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); - transition: all 0.3s ease; - overflow: hidden; +.status-overlay { + display: flex; + align-items: center; + justify-content: center; - &:hover { - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); - } - - .locker-status { - position: relative; - border-radius: 4px; - overflow: hidden; - - .locker-image { - display: block; - } - - .status-overlay { - position: absolute; - width: 100%; - height: 50px; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(0, 0, 0, 0.4); - display: flex; - align-items: center; - justify-content: center; - - .status-text { - color: white; - font-size: 16px; - font-weight: 500; - } - } - } - - .locker-info { - padding: 8px; - - .locker-number { - font-size: 14px; - color: #666; - margin-bottom: 4px; - } - - .goods-info { - margin: 8px 0; - padding: 8px; - background: #f7f8fa; - border-radius: 4px; - - .goods-name { - font-size: 12px; - color: #333; - line-height: 1.4; - } - - .goods-price { - font-size: 14px; - color: #e95d5d; - font-weight: bold; - margin-top: 4px; - } - } - - .button-group { - display: flex; - gap: 8px; - margin-top: 12px; - - .detail-btn { - flex: 1; - background-color: #e95d5d; - border: none; - } - - :deep(.van-button--default) { - color: #e95d5d; - border-color: #e95d5d; - } - } + .status-text { + color: white; + font-size: 16px; + font-weight: 500; } } + +.locker-number { + font-size: 14px; + color: #666; + margin-bottom: 4px; +} + +.goods-info { + display: flex; + flex-direction: column; + gap: 8px; + width: 100%; + + .goods-name { + white-space: normal; + word-wrap: break-word; + font-size: 12px; + color: #666; + line-height: 1.2; + width: 70%; + } + + .goods-price { + font-size: 14px; + color: #e95d5d; + font-weight: bold; + margin-top: 4px; + } +} + +.button-group { + display: flex; + gap: 8px; + margin-top: 0; + + .detail-btn { + flex: 1; + background-color: #e95d5d; + border: none; + } + + :deep(.van-button--default) { + color: #e95d5d; + border-color: #e95d5d; + } +} + +.product-list { + flex: 1; + overflow-y: auto; + padding: 10px 16px 60px; + background: #ffffff; +} + +.product-item { + margin-bottom: 10px; + padding: min(2.667vw, 20px) 0; +} + +.product-info { + display: flex; + flex-direction: column; + justify-content: space-between; + height: 100px; + position: relative; + padding-left: 3px; +} + +.goods-name { + text-align: left; +} + +.button-group { + padding: 4px; +} + +.button-group .van-button { + font-size: 12px; + height: 24px; + line-height: 22px; +} + +:deep(.van-button) { + --van-button-mini-height: 24px; + --van-button-mini-padding: 0 8px; +} + +.locker-number { + font-size: 14px; + color: #333; + line-height: 1.4; + text-align: left; +} + +.goods-price { + font-size: 16px; + color: #e95d5d; + font-weight: bold; + text-align: left; +} + +.button-group { + display: flex; + gap: 8px; + margin-top: 12px; +} + +.detail-btn { + flex: 1; + background-color: #e95d5d; + border: none; +} + +:deep(.van-button--default) { + color: #e95d5d; + border-color: #e95d5d; +} + +.info-row { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; +} \ No newline at end of file diff --git a/src/pages/me/index.vue b/src/pages/me/index.vue index d16e6dd..6d8da21 100644 --- a/src/pages/me/index.vue +++ b/src/pages/me/index.vue @@ -74,6 +74,7 @@ const balance = computed(() => wxStore.balance) + diff --git a/src/pages/order/index.vue b/src/pages/order/index.vue index 12b3736..5a43bc5 100644 --- a/src/pages/order/index.vue +++ b/src/pages/order/index.vue @@ -1,10 +1,11 @@ @@ -62,15 +74,26 @@ onMounted(() => { />
-
- {{ item.goodsInfo.goodsName }} -
-
- ¥{{ item.goodsInfo.price.toFixed(2) }} +
+
+ {{ item.goodsInfo.goodsName }} +
+
+ ¥{{ item.orderGoods.price.toFixed(2) }} +

数量: {{ item.orderGoods.quantity }}

小计: ¥{{ (item.orderGoods.price * item.orderGoods.quantity).toFixed(2) }}

+ + 退还 +
@@ -121,9 +144,39 @@ goods-info { flex: 1; } +.product-name-price { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 8px; +} + +.product-name { + flex: 1; + margin-right: 10px; +} + +.product-price { + color: #ee0a24; + font-weight: 500; +} .not-found { padding: 40px; text-align: center; color: #999; } + +.refund-btn { + margin-left: auto; + color: #fff; + background: #ee0a24; + border-radius: 15px; + padding: 0 12px; +} + +.action-row { + display: flex; + gap: 8px; + align-items: center; +} \ No newline at end of file diff --git a/src/router/index.ts b/src/router/index.ts index a4b414e..77d785d 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -29,6 +29,11 @@ export const systemRoutes: RouteRecordRaw[] = [ /** 业务页面 */ export const routes: RouteRecordRaw[] = [ + { + path: '/approval/submit', + component: () => import('@/pages/approval/submit.vue'), + meta: { requiresAuth: true } + }, { path: '/order-success', name: 'OrderSuccess', @@ -64,11 +69,11 @@ export const routes: RouteRecordRaw[] = [ } }, { - path: "/", - component: () => import("@/pages/product/ProductList.vue"), - name: "ProductList", + path: '/cabinet', + component: () => import('@/pages/cabinet/index.vue'), + name: "Cabinet", meta: { - title: "商品列表", + title: '柜机管理', keepAlive: true, layout: { navBar: { @@ -76,18 +81,18 @@ export const routes: RouteRecordRaw[] = [ showLeftArrow: false }, tabbar: { - showTabbar: true, + showTabbar: false, icon: "home-o" } } } }, { - path: '/cabinet', - component: () => import('@/pages/cabinet/index.vue'), - name: "Cabinet", + path: "/", + component: () => import("@/pages/product/ProductList.vue"), + name: "ProductList", meta: { - title: '柜机管理', + title: "商品列表", keepAlive: true, layout: { navBar: { @@ -122,6 +127,11 @@ export const routes: RouteRecordRaw[] = [ ] /* export const routes: RouteRecordRaw[] = [ + { + path: '/approval/submit', + component: () => import('@/pages/approval/submit.vue'), + meta: { requiresAuth: true } + }, { path: '/order-success', name: 'OrderSuccess',