feat(router): 恢复管理员路由守卫检查

feat(api): 为余额查询接口添加corpid参数

refactor(product): 优化商品获取逻辑并移除URL参数依赖

feat(product): 添加机柜地址选择功能并重构商品列表页面

fix(wx): 修复余额获取逻辑并启用相关用户信息更新
This commit is contained in:
dzq 2025-06-10 17:13:06 +08:00
parent e23719854e
commit 195749ad6e
6 changed files with 150 additions and 41 deletions

View File

@ -59,11 +59,11 @@ export function openCabinetApi(orderId: number, orderGoodsId: number, data: Open
}
/** 获取用户余额接口 */
export function getBalanceApi(openid: string) {
export function getBalanceApi(corpid: string, openid: string) {
return request<ApiResponseData<GetBalanceResponse>>({
url: "payment/getBalance",
method: "get",
params: { openid }
params: { corpid, openid }
})
}
export function getBalanceByQyUserid(corpid: string, userid: string) {

View File

@ -11,6 +11,8 @@ import Detail from "./components/detail.vue"
import { useRoute } from 'vue-router'
import { useWxStore } from "@/pinia/stores/wx"
import { bindQyUserApi } from "@/common/apis/ab98"
import { getShopListApi } from "@/common/apis/shop"
import { ShopEntity } from "@/common/apis/shop/type"
const router = useRouter()
const route = useRoute()
@ -33,6 +35,11 @@ const headerHeight = ref(150)
//
let scrollListener: any[] = []
//
const showShopList = ref(true);
const shopList = ref<ShopEntity[]>([]);
const shopId = ref<number>(0);
//
const showDetailPopup = ref(false)
// ID
@ -51,6 +58,18 @@ const idNum = ref('');
const showAb98BindPopup = ref(false);
//
function handleShopSelect(selectedShopId: number) {
shopId.value = selectedShopId;
showShopList.value = false;
productStore.getGoods(selectedShopId);
cartStore.clearCart();
}
function handleBackToShopList() {
showShopList.value = true;
shopId.value = 0;
cartStore.clearCart();
}
function handleCategoryClick(index: number) {
activeCategory.value = index
}
@ -105,7 +124,7 @@ function getCartItemCount(cellId: number) {
function filterProductsByName(products: Product[], query: string) {
if (!query) return products
return products.filter(p =>
return products.filter(p =>
p.name.toLowerCase().includes(query.toLowerCase())
)
}
@ -117,7 +136,15 @@ const currentProducts = computed(() => {
//
onMounted(() => {
productStore.getGoods();
if (showShopList.value) {
getShopListApi(wxStore.corpid).then((res) => {
if (res?.code === 0 && res?.data?.length > 0) {
shopList.value = res.data;
}
});
} else {
productStore.getGoods(shopId.value);
}
scrollListener.push(scrollContainer.value?.addEventListener("scroll", throttledScroll))
// scrollListener.push(scrollContainer.value?.addEventListener("scroll", throttledUpdate))
})
@ -137,14 +164,22 @@ function handleCheckout() {
//
watch(() => route.path, (newPath) => {
if (newPath === '/') {
productStore.getGoods()
if (showShopList.value) {
getShopListApi(wxStore.corpid).then((res) => {
if (res?.code === 0 && res?.data?.length > 0) {
shopList.value = res.data;
}
});
} else {
productStore.getGoods(shopId.value);
}
}
});
}, { immediate: true });
let showAb98BindPopupOnce = false;
watch(openid, async () => {
if (openid.value && corpidLogin.value && !ab98User.value
&& !showAb98BindPopup.value && !showAb98BindPopupOnce) {
if (openid.value && corpidLogin.value && !ab98User.value
&& !showAb98BindPopup.value && !showAb98BindPopupOnce) {
//
showAb98BindPopup.value = true;
showAb98BindPopupOnce = true;
@ -174,24 +209,49 @@ async function handleAb98Bind() {
</script>
<template>
<div class="shop">
<div v-if="showShopList" class="shop-list">
<div class="shop-header" :style="{ height: `${headerHeight}px` }">
<van-image :src="`${publicPath}cover.png`" class="shop-cover" fit="cover" />
</div>
<div class="shop-prompt">
<van-cell title="请选择机柜地址:" center />
</div>
<van-row :gutter="[10, 10]" class="shop-row" justify="start">
<van-col span="12" class="shop-col">
<div class="shop-item" @click="handleShopSelect(0)">
<div class="shop-info">
<van-icon name="home-o" size="20" class="shop-icon" />
<div class="shop-name van-ellipsis">全部</div>
</div>
</div>
</van-col>
<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-if="!showShopList" class="shop">
<div class="shop-header" :style="{ height: `${headerHeight}px` }">
<van-image :src="`${publicPath}cover.png`" class="shop-cover" fit="cover" />
</div>
<div class="product-container">
<!-- 左侧分类导航 -->
<van-sidebar v-model="activeCategory" class="category-nav" @change="handleCategoryClick">
<van-sidebar-item v-for="label in labels" :key="label.id" :title="label.name" />
</van-sidebar>
<div>
<van-button icon="revoke" type="default" class="showShopListBtn" @click="showShopList = true">重选地址</van-button>
<van-sidebar v-model="activeCategory" class="category-nav" @change="handleCategoryClick">
<van-sidebar-item v-for="label in labels" :key="label.id" :title="label.name" />
</van-sidebar>
</div>
<!-- 右侧商品列表 -->
<div ref="scrollContainer" class="product-list">
<van-search
v-model="searchQuery"
placeholder="搜索商品名称"
shape="round"
class="search-box"
/>
<van-search v-model="searchQuery" placeholder="搜索商品名称" shape="round" class="search-box" />
<div class="category-section">
<van-cell v-for="product in currentProducts" :key="product.id" class="product-item">
<template #icon>
@ -222,7 +282,8 @@ async function handleAb98Bind() {
<div class="cart-actions">
<van-button v-if="getCartItemCount(product.cellId)" size="mini" icon="minus"
@click.stop="handleRemoveFromCart(product)" />
<span v-if="getCartItemCount(product.cellId)" class="cart-count">{{ getCartItemCount(product.cellId) }}</span>
<span v-if="getCartItemCount(product.cellId)" class="cart-count">{{ getCartItemCount(product.cellId)
}}</span>
<van-button size="mini" type="primary" class="add-cart-btn" icon="plus"
:disabled="product.stock === 0" @click.stop="handleAddToCart(product)" :style="{
opacity: product.stock === 0 ? 0.6 : 1,
@ -260,18 +321,9 @@ async function handleAb98Bind() {
<div style="text-align: center; font-size: 16px; font-weight: bold; margin-bottom: 16px;">请绑定汇邦云账号</div>
<van-form @submit="handleAb98Bind">
<van-cell-group inset>
<van-field
v-model="name"
label="姓名"
placeholder="请输入真实姓名"
:rules="[{ required: true, message: '请填写姓名' }]"
/>
<van-field
v-model="idNum"
label="身份证号"
placeholder="请输入身份证号码"
:rules="[{ required: true, message: '请填写身份证号' }]"
/>
<van-field v-model="name" label="姓名" placeholder="请输入真实姓名" :rules="[{ required: true, message: '请填写姓名' }]" />
<van-field v-model="idNum" label="身份证号" placeholder="请输入身份证号码"
:rules="[{ required: true, message: '请填写身份证号' }]" />
</van-cell-group>
<div style="margin: 16px;">
<van-button block type="primary" native-type="submit">
@ -305,6 +357,12 @@ async function handleAb98Bind() {
flex-shrink: 0;
}
.showShopListBtn {
width: 100%;
padding: 0;
border: 0;
}
.product-list {
flex: 1;
overflow-y: auto;
@ -505,4 +563,54 @@ async function handleAb98Bind() {
text-align: center;
}
}
.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 {
font-size: 14px;
color: #333;
font-weight: 500;
margin: 2px 0 4px 2px;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
}
}
</style>

View File

@ -234,12 +234,12 @@ async function handleSubmit() {
<van-icon v-if="selectedPayment === 'wechat'" name="success" class="check-icon" />
</van-cell>
<van-cell v-if="corpidLogin"
<van-cell v-if="balance && balance > 0"
:class="['payment-option', { selected: selectedPayment === 'balance', disabled: balance < totalPrice }]"
@click="selectedPayment = 'balance'">
<van-icon name="balance-o" class="method-icon" />
<span class="method-label">
余额支付
借呗支付
<span class="balance-amount">当前¥{{ balance.toFixed(2) }}</span>
</span>
<div class="empty"></div>

View File

@ -21,14 +21,15 @@ export const useProductStore = defineStore("product", () => {
const shopId = ref<number|null>(null);
const getGoods = async (shopId_?: number) => {
if (shopId_) {
if (shopId_ && shopId_ > 0) {
shopId.value = shopId_;
} else {
const urlParams = new URLSearchParams(window.location.search);
shopId.value = null;
/* const urlParams = new URLSearchParams(window.location.search);
const shopIdParams = urlParams.get('shopId') || undefined;
if (shopIdParams) {
shopId.value = Number(shopIdParams);
}
} */
}
try {

View File

@ -108,17 +108,17 @@ export const useWxStore = defineStore("wx", () => {
balanceRes = await getBalanceByQyUserid(corpid.value, userid.value);
} else {
corpid.value = "wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw";
// balanceRes = await getBalanceApi(openid.value)
balanceRes = await getBalanceApi(corpid.value, openid.value)
}
console.log('获取余额成功:', balanceRes)
if (balanceRes && balanceRes.code == 0) {
balance.value = balanceRes.data.balance;
useBalance.value = balanceRes.data.useBalance;
balanceLimit.value = balanceRes.data.balanceLimit;
/* if (!userid.value) {
if (!userid.value) {
userid.value = balanceRes.data.userid;
}
if (!corpid.value) {
/* if (!corpid.value) {
corpid.value = balanceRes.data.corpid;
} */
}

View File

@ -25,10 +25,10 @@ export function registerNavigationGuard(router: Router) {
if (corpid) {
return true;
}
/* const isAdmin = urlParams.get('isAdmin') || undefined;
const isAdmin = urlParams.get('isAdmin') || undefined;
if (isAdmin) {
return true;
} */
}
// useAb98UserStore位置不能放在外面否则会导致路由守卫无法正常工作
const ab98UserStore = useAb98UserStore();