feat(rental): 新增我的柜子页面及相关功能

- 添加我的柜子页面路由和导航入口
- 实现用户租赁柜子列表展示功能
- 优化订单列表样式和商品信息展示
- 在用户信息中增加ab98User字段支持
- 统一订单获取接口参数格式
This commit is contained in:
dzq 2025-07-02 15:41:19 +08:00
parent 7ab5130cff
commit 32f90300c8
9 changed files with 53 additions and 86 deletions

View File

@ -163,6 +163,7 @@ export interface GetBalanceResponse {
useBalance: number
/** 借呗总额 */
balanceLimit: number
ab98User: ab98UserDTO;
}
export interface QyLoginDTO {

View File

@ -126,7 +126,7 @@ const handleSubmit = async () => {
const { code, data } = await submitApprovalApi(formData.value)
if (code === 0) {
orderStore.getOrders(wxStore.corpid, wxStore.openid, wxStore.qyUserId);
orderStore.getOrders(wxStore.corpid, wxStore.openid, wxStore.qyUserId, 0);
try {
await showConfirmDialog({

View File

@ -90,6 +90,12 @@ wxStore.refreshBalance();
<span>订单列表</span>
</div>
</van-col>
<van-col span="8">
<div class="custom-btn" @click="router.push('/rental-list')">
<van-icon name="orders-o" size="20px" />
<span>我的柜子</span>
</div>
</van-col>
<!-- <van-col span="6">
<div v-if="wxStore.isCabinetAdmin" class="custom-btn" @click="router.push('/manage/goods')">
<van-icon name="comment-o" size="20px" />
@ -115,7 +121,6 @@ wxStore.refreshBalance();
</div>
</van-col>
<van-col span="8"></van-col>
<van-col span="8"></van-col>
</van-row>
</div>
</template>

View File

@ -50,7 +50,7 @@ function backToHome() {
}
watch(() => orderId.value, async (newVal) => {
await orderStore.getOrders(wxStore.corpid, wxStore.openid, wxStore.qyUserId)
await orderStore.getOrders(wxStore.corpid, wxStore.openid, wxStore.qyUserId, 0)
currentOrder.value = orderStore.orders.find(o => o.orderId === newVal)
}, { immediate: true })
</script>

View File

@ -41,7 +41,7 @@ const getStatusText = (status: number) => {
<template>
<div class="order-list">
<!-- 状态切换标签页 -->
<van-tabs v-model:active="activeTab" @change="handleTabChange">
<van-tabs v-model:active="activeTab" @change="handleTabChange" style="margin-bottom: 8px;">
<van-tab title="未退还"></van-tab>
<van-tab title="已退还"></van-tab>
</van-tabs>
@ -72,7 +72,7 @@ const getStatusText = (status: number) => {
>
<template #icon>
<van-image
:src="goods.goodsInfo.coverImg"
:src="goods.goodsInfo?.coverImg"
width="80"
height="80"
class="product-image"
@ -80,7 +80,7 @@ const getStatusText = (status: number) => {
</template>
<div class="product-info">
<div class="product-name van-ellipsis">
{{ goods.goodsInfo.goodsName }}
{{ goods.goodsInfo?.goodsName }}
</div>
<div class="product-meta">
<span class="status">状态: {{ getStatusText(order.status) }}</span>
@ -109,7 +109,7 @@ const getStatusText = (status: number) => {
}
.order-item {
margin-bottom: 20px;
margin-bottom: 8px;
border: 1px solid #eee;
border-radius: 8px;
overflow: hidden;
@ -118,7 +118,7 @@ const getStatusText = (status: number) => {
.order-header {
display: flex;
justify-content: space-between;
padding: 10px 15px;
padding: 10px 15px 5px 15px;
background-color: #f5f5f5;
border-bottom: 1px solid #eee;
}
@ -130,7 +130,6 @@ const getStatusText = (status: number) => {
.goods-item {
display: flex;
padding: 10px 0;
border-bottom: 1px solid #f5f5f5;
}
goods-item:last-child {

View File

@ -97,7 +97,6 @@ async function handleOpenCabinet(item: OrderGoods) {
<template>
<div class="order-detail" v-if="order">
<h2>订单详情</h2>
<div class="order-info">
<p>订单号: {{ order.orderId }}</p>

View File

@ -1,24 +1,6 @@
<template>
<div v-if="showShopList" class="shop-list">
<div class="shop-prompt">
<van-cell title="请选择机柜地址:" center />
</div>
<van-row :gutter="[10, 10]" class="shop-row" justify="start">
<van-col v-for="shop in shopList" :key="shop.shopId" span="12" class="shop-col">
<div class="shop-item" @click="handleShopSelect(shop.shopId)">
<van-image :src="shop.coverImg || `${publicPath}product-image.png`" class="shop-cover-img" fit="cover" />
<div class="shop-info">
<van-icon name="shop-o" size="20" class="shop-icon" />
<div class="shop-name van-ellipsis">{{ shop.shopName }}</div>
</div>
</div>
</van-col>
<van-col v-if="shopList.length % 2 === 0" span="12" class="shop-col"></van-col>
</van-row>
</div>
<div v-else class="cabinet-container van-safe-area-bottom">
<div class="cabinet-container van-safe-area-bottom">
<div class="left-container">
<van-button icon="revoke" type="default" class="showShopListBtn" @click="handleBackToShopList">重选地址</van-button>
<van-sidebar v-model="activeCabinet" class="cabinet-sidebar" @change="onCabinetChange">
<van-sidebar-item v-for="cabinet in cabinetList" :key="cabinet.cabinetId" :title="cabinet.cabinetName" />
</van-sidebar>
@ -37,25 +19,18 @@
</template>
<div class="product-info">
<div class="goods-info">
<div v-if="locker.goodsName">
<div>
<div class="info-row">
<div class="locker-number">格口 {{ locker.cellNo }}</div>
<div class="goods-price">¥{{ (locker.price || 0).toFixed(2) }}</div>
</div>
<div class="goods-name">{{ locker.goodsName }}</div>
</div>
<div v-else>
<div class="info-row">
<div class="locker-number">格口 {{ locker.cellNo }}</div>
<div class="goods-price">¥0.00</div>
</div>
<div class="goods-name">空闲</div>
<div class="goods-name"></div>
</div>
</div>
<div class="button-group">
<van-button size="small" plain hairline :loading="openingLockerId === locker.lockerId"
@click="handleOpenLocker(locker)">
立即开启
开启格口
</van-button>
</div>
</div>
@ -74,9 +49,10 @@ import type { RentingCabinetDetailDTO, CabinetCellEntity } from '@/common/apis/c
import { useWxStore } from '@/pinia/stores/wx';
import { publicPath } from "@/common/utils/path";
import { showDialog, showToast } from 'vant';
import { useAb98UserStore } from '@/pinia/stores/ab98-user';
const wxStore = useWxStore();
const { userid: qyUserid, name: qyName, corpid } = storeToRefs(wxStore);
const { userid: userid, qyUserId: qyUserId, name: qyName, corpid, ab98User } = storeToRefs(wxStore);
const activeCabinet = ref(0)
const cabinetList = ref<CabinetItem[]>([])
@ -85,11 +61,6 @@ const openingLockerId = ref<number | null>(null)
const showBindGoodsPopup = ref(false)
const currentLocker = ref<LockerItem | null>(null)
const cabinetData = ref<RentingCabinetDetailDTO[]>([]);
//
const showShopList = ref(true);
const shopList = ref<ShopEntity[]>([]);
const shopId = ref<number>(0);
const selectedShop = ref<ShopEntity | null>(null);
let scrollListener: any[] = [];
interface CabinetItem {
@ -111,11 +82,12 @@ interface LockerItem {
}
//
const loadUserRentedCabinetDetail = async (selectedShopId?: number) => {
const targetShopId = selectedShopId || shopId.value;
if (!targetShopId || !corpid.value || !qyUserid.value) return;
const loadUserRentedCabinetDetail = async () => {
if (!ab98User.value || !ab98User.value.ab98UserId) {
return;
}
try {
const { data } = await getUserRentedCabinetListApi(corpid.value, Number(qyUserid.value));
const { data } = await getUserRentedCabinetListApi(corpid.value, ab98User.value.ab98UserId);
cabinetData.value = data || [];
cabinetList.value = cabinetData.value.map(cabinet => ({
cabinetId: cabinet.cabinetId,
@ -142,7 +114,7 @@ const updateLockerList = (cabinet: RentingCabinetDetailDTO) => {
status: cell.isRented ? 1 : 0,
statusClass: cell.isRented ? 'occupied' : 'available',
//
goodsName: '已租用商品',
goodsName: '',
price: cell.cellPrice,
coverImg: `${publicPath}img/product-image.svg`
}))
@ -162,7 +134,7 @@ const handleOpenLocker = async (locker: LockerItem) => {
//
await openCabinet(cabinetList.value[activeCabinet.value].cabinetId, locker.lockerNumber, {
cellId: locker.lockerId,
userid: qyUserid.value,
userid: userid.value,
isInternal: 2,
name: qyName.value,
mobile: '',
@ -177,40 +149,7 @@ const handleOpenLocker = async (locker: LockerItem) => {
//
const init = async () => {
if (showShopList.value) {
await getShopList();
} else if (shopId.value) {
await loadUserRentedCabinetDetail();
}
};
//
const getShopList = async () => {
try {
const res = await getShopListApi(wxStore.corpid, -1);
if (res?.code === 0 && res?.data?.length > 0) {
shopList.value = res.data;
}
} catch (error) {
console.error('获取商店列表失败:', error);
}
};
//
const handleShopSelect = (selectedShopId: number) => {
const shop = shopList.value.find(s => s.shopId === selectedShopId);
if (shop) {
selectedShop.value = shop;
shopId.value = selectedShopId;
}
showShopList.value = false;
loadUserRentedCabinetDetail(selectedShopId);
};
//
const handleBackToShopList = () => {
showShopList.value = true;
shopId.value = 0;
await loadUserRentedCabinetDetail();
};
onMounted(() => {

View File

@ -120,6 +120,9 @@ export const useWxStore = defineStore("wx", () => {
if (!userid.value) {
userid.value = balanceRes.data.userid;
}
if (!ab98User.value && balanceRes.data.ab98User) {
setAb98User(balanceRes.data.ab98User);
}
/* if (!corpid.value) {
corpid.value = balanceRes.data.corpid;
} */

View File

@ -73,6 +73,27 @@ export const routes: RouteRecordRaw[] = [
component: () => import('@/pages/order/index.vue'),
meta: {
title: '订单详情',
layout: {
navBar: {
showNavBar: true,
showLeftArrow: true
}
},
requiresAuth: true
}
},
{
path: '/rental-list',
name: 'RentalList',
component: () => import('@/pages/rental/index.vue'),
meta: {
title: '我的柜子',
layout: {
navBar: {
showNavBar: true,
showLeftArrow: true
}
},
requiresAuth: true
}
},