Files
rent/apps/miniapp/src/pages/seller/home.vue
T
2026-04-27 18:03:20 +08:00

503 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="page-merchant">
<!-- 未登录商家账号 -->
<view v-if="!sellerStore.isSellerLoggedIn()" class="login-tip">
<text class="tip-text">请先注册/登录商家账号</text>
<button class="login-btn" @tap="goSellerRegister">去注册/登录</button>
</view>
<!-- 已登录但未申请店铺 -->
<view v-else-if="!sellerStore.hasMerchant()" class="apply-section">
<view class="seller-info">
<text class="seller-name">{{ sellerStore.sellerInfo?.contactName }}</text>
<text class="seller-phone">{{ sellerStore.sellerInfo?.phone }}</text>
</view>
<text class="apply-title">创建店铺</text>
<text class="apply-desc">完成店铺信息填写提交审核后即可营业</text>
<button class="apply-btn" @tap="goCreateShop">创建店铺</button>
<button class="logout-btn" @tap="handleLogoutSeller">退出商家账号</button>
</view>
<!-- 已有店铺加载中 -->
<view v-else-if="!merchant" class="loading-section">
<text class="loading-text">加载中...</text>
</view>
<!-- 已有店铺 -->
<view v-else class="merchant-content">
<!-- 店铺信息 -->
<view class="shop-header">
<image class="shop-logo" :src="merchant.logo || '/static/default-avatar.png'" mode="aspectFill" />
<view class="shop-info">
<text class="shop-name">{{ merchant.shopName }}</text>
<view class="status-row">
<text :class="['shop-status', merchant.status]">{{ statusText }}</text>
<!-- 审核中状态显示提示 -->
<text v-if="merchant.status === 'pending'" class="status-tip">等待平台审核</text>
</view>
</view>
</view>
<!-- 审核拒绝原因 -->
<view v-if="merchant.status === 'rejected' && merchant.rejectReason" class="reject-section">
<view class="reject-header">
<text class="reject-icon">!</text>
<text class="reject-title">审核拒绝原因</text>
</view>
<text class="reject-reason">{{ merchant.rejectReason }}</text>
<text class="reject-tip">请修改店铺信息后重新提交审核</text>
</view>
<!-- 店铺信息卡片非审核中状态 -->
<view v-if="merchant.status !== 'pending'" class="shop-detail-card">
<view class="detail-item">
<text class="detail-label">联系电话</text>
<text class="detail-value">{{ merchant.phone }}</text>
</view>
<view class="detail-item" v-if="merchant.city">
<text class="detail-label">所在城市</text>
<text class="detail-value">{{ merchant.province }} {{ merchant.city }} {{ merchant.district }}</text>
</view>
<view class="detail-item" v-if="merchant.address">
<text class="detail-label">详细地址</text>
<text class="detail-value">{{ merchant.address }}</text>
</view>
</view>
<!-- 数据概览仅审核通过显示 -->
<view v-if="merchant.status === 'approved'" class="stat-grid">
<view class="stat-item">
<text class="stat-value">0</text>
<text class="stat-label">今日订单</text>
</view>
<view class="stat-item">
<text class="stat-value">0</text>
<text class="stat-label">在售房源</text>
</view>
<view class="stat-item">
<text class="stat-value">0</text>
<text class="stat-label">今日收入</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ merchant.rating }}</text>
<text class="stat-label">店铺评分</text>
</view>
</view>
<!-- 操作按钮 -->
<view class="action-section">
<!-- 审核通过/拒绝时可修改店铺 -->
<button
v-if="merchant.status === 'approved' || merchant.status === 'rejected'"
class="edit-btn"
@tap="goEditShop"
>
修改店铺信息
</button>
<!-- 审核中状态不可修改 -->
<view v-if="merchant.status === 'pending'" class="pending-tip">
<text class="pending-text">店铺信息审核中暂不可修改</text>
</view>
<!-- 冻结状态 -->
<view v-if="merchant.status === 'frozen'" class="frozen-tip">
<text class="frozen-text">店铺已被冻结请联系平台客服</text>
</view>
</view>
<!-- 功能菜单仅审核通过显示 -->
<view v-if="merchant.status === 'approved'" class="menu-section">
<view class="menu-group">
<view class="menu-item" @tap="navigateTo('/pages/seller/orders')">
<text class="menu-label">订单管理</text>
<text class="menu-arrow">></text>
</view>
<view class="menu-item" @tap="navigateTo('/pages/seller/rooms')">
<text class="menu-label">房源管理</text>
<text class="menu-arrow">></text>
</view>
<view class="menu-item" @tap="navigateTo('/pages/seller/room-calendar')">
<text class="menu-label">房量房价</text>
<text class="menu-arrow">></text>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';
import { useSellerStore } from '@/store/seller';
import { getMyMerchant } from '@/api/seller/merchant';
const sellerStore = useSellerStore();
const merchant = ref<any>(null);
const merchantStatus: Record<string, string> = {
pending: '审核中',
approved: '营业中',
rejected: '已拒绝',
frozen: '已冻结',
};
const statusText = computed(() => {
if (!merchant.value) return '';
return merchantStatus[merchant.value.status] || '';
});
onMounted(async () => {
if (sellerStore.isSellerLoggedIn() && sellerStore.hasMerchant()) {
try {
const res = await getMyMerchant();
merchant.value = res.data;
// 同步更新 sellerStore 中的状态
if (sellerStore.sellerInfo && res.data.status !== sellerStore.sellerInfo.merchantStatus) {
sellerStore.sellerInfo.merchantStatus = res.data.status;
uni.setStorageSync('sellerInfo', sellerStore.sellerInfo);
}
} catch { /* 获取店铺信息失败 */ }
}
});
function goSellerRegister() {
uni.navigateTo({ url: '/pages/seller/register' });
}
function goCreateShop() {
uni.navigateTo({ url: '/pages/seller/shop-create' });
}
function goEditShop() {
uni.navigateTo({ url: '/pages/seller/shop-edit' });
}
function handleLogoutSeller() {
uni.showModal({
title: '提示',
content: '确定退出商家账号?',
success: (res) => {
if (res.confirm) {
sellerStore.logoutSeller();
}
},
});
}
function navigateTo(url: string) {
uni.navigateTo({ url });
}
</script>
<style lang="scss" scoped>
.page-merchant {
min-height: 100vh;
background: #f5f5f5;
}
.login-tip {
display: flex;
flex-direction: column;
align-items: center;
padding: 200rpx 48rpx;
}
.tip-text {
font-size: 30rpx;
color: #999;
margin-bottom: 40rpx;
}
.login-btn {
background: #FF6B35;
color: #fff;
border-radius: 40rpx;
padding: 20rpx 80rpx;
font-size: 30rpx;
border: none;
}
.apply-section {
display: flex;
flex-direction: column;
align-items: center;
padding: 120rpx 48rpx;
}
.seller-info {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 48rpx;
}
.seller-name {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.seller-phone {
font-size: 28rpx;
color: #999;
margin-top: 8rpx;
}
.apply-title {
font-size: 40rpx;
font-weight: 700;
color: #333;
}
.apply-desc {
font-size: 28rpx;
color: #999;
margin: 16rpx 0 48rpx;
}
.apply-btn {
background: linear-gradient(135deg, #FF6B35, #ff8a5c);
color: #fff;
border-radius: 40rpx;
padding: 24rpx 80rpx;
font-size: 32rpx;
font-weight: 600;
border: none;
}
.logout-btn {
margin-top: 32rpx;
background: transparent;
color: #999;
border: 1rpx solid #ddd;
border-radius: 40rpx;
padding: 20rpx 60rpx;
font-size: 28rpx;
}
.shop-header {
display: flex;
align-items: center;
padding: 40rpx 24rpx;
background: linear-gradient(135deg, #FF6B35, #ff8a5c);
}
.shop-logo {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
border: 4rpx solid rgba(255, 255, 255, 0.5);
}
.shop-info {
margin-left: 24rpx;
display: flex;
flex-direction: column;
}
.shop-name {
font-size: 34rpx;
font-weight: 600;
color: #fff;
}
.status-row {
display: flex;
align-items: center;
margin-top: 8rpx;
}
.shop-status {
font-size: 24rpx;
padding: 4rpx 16rpx;
border-radius: 16rpx;
color: #fff;
&.approved { background: rgba(82, 196, 26, 0.8); }
&.pending { background: rgba(250, 173, 20, 0.8); }
&.rejected { background: rgba(255, 77, 79, 0.8); }
&.frozen { background: rgba(140, 140, 140, 0.8); }
}
.status-tip {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
margin-left: 12rpx;
}
.reject-section {
background: #fff2f0;
border: 1rpx solid #ffccc7;
border-radius: 16rpx;
margin: 24rpx;
padding: 24rpx;
}
.reject-header {
display: flex;
align-items: center;
margin-bottom: 16rpx;
}
.reject-icon {
width: 32rpx;
height: 32rpx;
background: #ff4d4f;
border-radius: 50%;
color: #fff;
font-size: 20rpx;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
}
.reject-title {
font-size: 28rpx;
font-weight: 600;
color: #ff4d4f;
margin-left: 12rpx;
}
.reject-reason {
font-size: 28rpx;
color: #333;
line-height: 1.6;
}
.reject-tip {
font-size: 24rpx;
color: #ff7875;
margin-top: 12rpx;
}
.shop-detail-card {
background: #fff;
border-radius: 16rpx;
margin: 24rpx;
padding: 24rpx;
}
.detail-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16rpx 0;
border-bottom: 1rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
}
.detail-label {
font-size: 28rpx;
color: #999;
}
.detail-value {
font-size: 28rpx;
color: #333;
}
.stat-grid {
display: flex;
background: #fff;
margin: 24rpx;
border-radius: 16rpx;
padding: 32rpx 0;
}
.stat-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
}
.stat-value {
font-size: 36rpx;
font-weight: 700;
color: #333;
}
.stat-label {
font-size: 24rpx;
color: #999;
margin-top: 8rpx;
}
.action-section {
padding: 0 24rpx;
margin-bottom: 24rpx;
}
.edit-btn {
width: 100%;
height: 88rpx;
background: #fff;
color: #FF6B35;
border: 2rpx solid #FF6B35;
border-radius: 44rpx;
font-size: 32rpx;
font-weight: 600;
}
.pending-tip, .frozen-tip {
background: #fff;
border-radius: 16rpx;
padding: 32rpx 24rpx;
text-align: center;
}
.pending-text {
font-size: 28rpx;
color: #faad14;
}
.frozen-text {
font-size: 28rpx;
color: #999;
}
.loading-section {
display: flex;
justify-content: center;
align-items: center;
padding: 200rpx 0;
}
.loading-text {
font-size: 28rpx;
color: #999;
}
.menu-section {
padding: 0 24rpx;
}
.menu-group {
background: #fff;
border-radius: 16rpx;
overflow: hidden;
}
.menu-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx 24rpx;
border-bottom: 1rpx solid #f5f5f5;
&:last-child { border-bottom: none; }
}
.menu-label {
font-size: 30rpx;
color: #333;
}
.menu-arrow {
font-size: 28rpx;
color: #ccc;
}
</style>