feat(机柜页面): 增加商店选择功能并优化机柜展示
- 在机柜页面添加商店列表选择功能,用户需先选择商店才能查看对应机柜 - 修改getCabinetDetailApi和getShopListApi接口,支持传入shopId和mode参数 - 添加返回商店列表按钮,优化页面交互流程 - 实现滚动时头部高度动态调整效果 - 新增相关样式和状态管理逻辑
This commit is contained in:
parent
87574aebf6
commit
2132e0e1e5
|
@ -3,10 +3,13 @@ import type { CabinetDetailResponse } from './type'
|
||||||
import { OpenCabinetApiData } from '../shop/type'
|
import { OpenCabinetApiData } from '../shop/type'
|
||||||
|
|
||||||
/** 获取智能柜详情接口 */
|
/** 获取智能柜详情接口 */
|
||||||
export function getCabinetDetailApi() {
|
export function getCabinetDetailApi(shopId: number) {
|
||||||
return request<CabinetDetailResponse>({
|
return request<CabinetDetailResponse>({
|
||||||
url: 'cabinet/detail',
|
url: 'cabinet/detail',
|
||||||
method: 'get'
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
shopId
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,10 +74,16 @@ export function getBalanceByQyUserid(corpid: string, userid: string) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getShopListApi(corpid: string) {
|
export function getShopListApi(corpid: string, mode?: number) {
|
||||||
|
const params: any = {
|
||||||
|
corpid
|
||||||
|
};
|
||||||
|
if (typeof mode !== 'undefined') {
|
||||||
|
params.mode = mode;
|
||||||
|
}
|
||||||
return request<ApiResponseData<ShopEntity[]>>({
|
return request<ApiResponseData<ShopEntity[]>>({
|
||||||
url: "shop/list",
|
url: "shop/list",
|
||||||
method: "get",
|
method: "get",
|
||||||
params: { corpid }
|
params
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -1,16 +1,36 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="cabinet-container van-safe-area-bottom">
|
<div v-if="showShopList" class="shop-list">
|
||||||
<van-sidebar v-model="activeCabinet" class="cabinet-sidebar" @change="onCabinetChange">
|
<div class="shop-prompt">
|
||||||
<van-sidebar-item v-for="cabinet in cabinetList" :key="cabinet.cabinetId" :title="cabinet.cabinetName" />
|
<van-cell title="请选择机柜地址:" center />
|
||||||
</van-sidebar>
|
</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)">
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="product-list">
|
<div class="product-list">
|
||||||
<van-cell v-for="locker in lockerList" :key="locker.lockerId" class="product-item">
|
<van-cell v-for="locker in lockerList" :key="locker.lockerId" class="product-item">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<div class="image-container">
|
<div class="image-container">
|
||||||
<van-image width="80" height="80"
|
<van-image width="80" height="80"
|
||||||
:src="locker.coverImg ? locker.coverImg : `${publicPath}` + 'img/product-image.svg'" fit="cover"
|
:src="locker.coverImg ? locker.coverImg : `${publicPath}` + 'img/product-image.svg'"
|
||||||
radius="4" class="product-image" :style="{ filter: locker.stock === 0 ? 'grayscale(100%)' : 'none' }">
|
fit="cover" radius="4" class="product-image"
|
||||||
|
:style="{ filter: locker.stock === 0 ? 'grayscale(100%)' : 'none' }">
|
||||||
</van-image>
|
</van-image>
|
||||||
<div v-if="locker.stock >= 0" class="stock-overlay">
|
<div v-if="locker.stock >= 0" class="stock-overlay">
|
||||||
库存: {{ locker.stock }}
|
库存: {{ locker.stock }}
|
||||||
|
@ -50,11 +70,14 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { throttle } from 'lodash-es';
|
||||||
import { getCabinetDetailApi, openCabinet } from '@/common/apis/cabinet'
|
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
|
||||||
import type { CabinetDetailDTO } from '@/common/apis/cabinet/type'
|
import { getShopListApi } from '@/common/apis/shop';
|
||||||
import { useWxStore, useWxStoreOutside } from '@/pinia/stores/wx'
|
import { ShopEntity } from '@/common/apis/shop/type';
|
||||||
import { publicPath } from "@/common/utils/path"
|
import { getCabinetDetailApi, openCabinet } from '@/common/apis/cabinet';
|
||||||
|
import type { CabinetDetailDTO } from '@/common/apis/cabinet/type';
|
||||||
|
import { useWxStore, useWxStoreOutside } from '@/pinia/stores/wx';
|
||||||
|
import { publicPath } from "@/common/utils/path";
|
||||||
|
|
||||||
const wxStore = useWxStore();
|
const wxStore = useWxStore();
|
||||||
const { userid: qyUserid, name: qyName } = storeToRefs(wxStore);
|
const { userid: qyUserid, name: qyName } = storeToRefs(wxStore);
|
||||||
|
@ -64,6 +87,13 @@ const cabinetList = ref<CabinetItem[]>([])
|
||||||
const lockerList = ref<LockerItem[]>([])
|
const lockerList = ref<LockerItem[]>([])
|
||||||
const openingLockerId = ref<number | null>(null)
|
const openingLockerId = ref<number | null>(null)
|
||||||
const cabinetData = ref<CabinetDetailDTO[]>([]);
|
const cabinetData = ref<CabinetDetailDTO[]>([]);
|
||||||
|
const scrollContainer = ref<HTMLElement>();
|
||||||
|
// 机柜地址选择相关状态
|
||||||
|
const showShopList = ref(true);
|
||||||
|
const shopList = ref<ShopEntity[]>([]);
|
||||||
|
const shopId = ref<number>(0);
|
||||||
|
const headerHeight = ref(150);
|
||||||
|
let scrollListener: any[] = [];
|
||||||
|
|
||||||
interface CabinetItem {
|
interface CabinetItem {
|
||||||
cabinetId: number
|
cabinetId: number
|
||||||
|
@ -83,10 +113,12 @@ interface LockerItem {
|
||||||
coverImg?: string
|
coverImg?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取柜机列表
|
// 获取机柜列表
|
||||||
const loadCabinetDetail = async () => {
|
const loadCabinetDetail = async (selectedShopId?: number) => {
|
||||||
|
const targetShopId = selectedShopId || shopId.value;
|
||||||
|
if (!targetShopId) return;
|
||||||
try {
|
try {
|
||||||
const { data } = await getCabinetDetailApi();
|
const { data } = await getCabinetDetailApi(targetShopId);
|
||||||
cabinetData.value = data;
|
cabinetData.value = data;
|
||||||
cabinetList.value = data.map(cabinet => ({
|
cabinetList.value = data.map(cabinet => ({
|
||||||
cabinetId: cabinet.cabinetId,
|
cabinetId: cabinet.cabinetId,
|
||||||
|
@ -149,7 +181,56 @@ const handleOpenLocker = async (locker: LockerItem) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadCabinetDetail()
|
// 初始化方法
|
||||||
|
const init = async () => {
|
||||||
|
if (showShopList.value) {
|
||||||
|
await getShopList();
|
||||||
|
} else if (shopId.value) {
|
||||||
|
await loadCabinetDetail();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取商店列表
|
||||||
|
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) => {
|
||||||
|
shopId.value = selectedShopId;
|
||||||
|
showShopList.value = false;
|
||||||
|
loadCabinetDetail(selectedShopId);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 返回商店列表
|
||||||
|
const handleBackToShopList = () => {
|
||||||
|
showShopList.value = true;
|
||||||
|
shopId.value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听滚动事件调整头部高度
|
||||||
|
const throttledScroll = throttle(() => {
|
||||||
|
if (!scrollContainer.value) return;
|
||||||
|
const scrollTop = scrollContainer.value.scrollTop;
|
||||||
|
headerHeight.value = Math.max(150 - scrollTop * 0.5, 60);
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
init();
|
||||||
|
scrollListener.push(window.addEventListener('scroll', throttledScroll));
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
scrollListener.forEach(listener => window.removeEventListener('scroll', listener));
|
||||||
|
scrollListener = [];
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -176,6 +257,81 @@ loadCabinetDetail()
|
||||||
height: calc(100vh - var(--van-tabbar-height));
|
height: calc(100vh - var(--van-tabbar-height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 机柜选择相关样式 */
|
||||||
|
.shop {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-header {
|
||||||
|
overflow: hidden;
|
||||||
|
transition: height 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-cover {
|
||||||
|
width: 100%;
|
||||||
|
transform: translateY(calc((150px - var(--header-height)) / 2));
|
||||||
|
scale: calc(1 + (150 - var(--header-height)) / 150);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-list {
|
||||||
|
.shop-prompt {
|
||||||
|
margin: 8px;
|
||||||
|
height: 44px !important;
|
||||||
|
background: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-row {
|
||||||
|
margin: 8px 0;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-col {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-item {
|
||||||
|
height: 60px !important;
|
||||||
|
padding: 12px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||||
|
transition: transform 0.2s;
|
||||||
|
|
||||||
|
.shop-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: start;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-name {
|
||||||
|
white-space: normal;
|
||||||
|
word-break: break-word;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
margin: 2px 0 4px 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.showShopListBtn {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.cabinet-sidebar {
|
.cabinet-sidebar {
|
||||||
width: 120px;
|
width: 120px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
Loading…
Reference in New Issue