Files
medical-mall/pages/mall/merchant/profile.uvue
2026-03-24 00:21:19 +08:00

1010 lines
25 KiB
Plaintext
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="merchant-profile">
<!-- #ifdef MP-WEIXIN -->
<view class="mp-tab-navbar">
<text class="mp-tab-title">我的</text>
</view>
<!-- #endif -->
<scroll-view direction="vertical" class="profile-scroll">
<!-- 店铺信息头部:与 index 同源数据 -->
<view class="profile-header">
<image :src="shopInfo.shop_logo || '/static/logo.png'" class="shop-logo" mode="aspectFill" @click="goToSettings" />
<view class="shop-info">
<text class="shop-name">{{ shopInfo.shop_name || '我的店铺' }}</text>
<text class="shop-status">{{ getShopStatus() }}</text>
<view class="shop-stats">
<text class="stat-item">评分: {{ shopInfo.rating_avg || 5.0 }}/5.0</text>
<text class="stat-item">总销量: {{ shopInfo.total_sales || 0 }}</text>
</view>
</view>
<view class="settings-icon" @click="goToSettings">
<text class="settings-icon-text">⚙️</text>
</view>
</view>
<!-- 前往店铺主页(跳转店铺详情,而非 shop-edit -->
<view class="shop-home-entry" @click="goToShopHome">
<text class="shop-home-icon">🏪</text>
<text class="shop-home-text">前往店铺主页</text>
<text class="shop-home-arrow"></text>
</view>
<!-- 订单管理快捷入口 -->
<view class="section-card">
<view class="section-title-text">订单管理</view>
<view class="order-tabs">
<view class="order-tab" @click="goToOrders('all')">
<view class="tab-icon-wrap">
<text class="tab-icon">📋</text>
<text v-if="pendingCounts.pending_shipment > 0" class="tab-badge">{{ pendingCounts.pending_shipment }}</text>
</view>
<text class="tab-text">待发货</text>
</view>
<view class="order-tab" @click="goToOrders('shipped')">
<view class="tab-icon-wrap">
<text class="tab-icon">🚚</text>
</view>
<text class="tab-text">已发货</text>
</view>
<view class="order-tab" @click="goToOrders('refund')">
<view class="tab-icon-wrap">
<text class="tab-icon">↩️</text>
<text v-if="pendingCounts.refund_requests > 0" class="tab-badge alert">{{ pendingCounts.refund_requests }}</text>
</view>
<text class="tab-text">退款</text>
</view>
<view class="order-tab" @click="goToOrders('all')">
<view class="tab-icon-wrap">
<text class="tab-icon">📑</text>
</view>
<text class="tab-text">全部订单</text>
</view>
</view>
</view>
<!-- 今日经营数据:复用 index 的 todayStats 字段 -->
<view class="section-card">
<view class="section-title-text">今日经营</view>
<view class="stats-grid">
<view class="stat-card">
<text class="stat-value">¥{{ formatNumber(todayStats.sales) }}</text>
<text class="stat-label">营业额</text>
</view>
<view class="stat-card">
<text class="stat-value">{{ todayStats.orders || 0 }}</text>
<text class="stat-label">订单数</text>
</view>
<view class="stat-card">
<text class="stat-value">{{ todayStats.visitors || 0 }}</text>
<text class="stat-label">访客数</text>
</view>
<view class="stat-card">
<text class="stat-value">{{ todayStats.conversion || 0 }}%</text>
<text class="stat-label">转化率</text>
</view>
</view>
</view>
<!-- 最近订单:复用 index 的 recentOrders + OrderType -->
<view class="section-card">
<view class="section-header-row">
<text class="section-title-text">最近订单</text>
<text class="view-all-link" @click="goToOrders('all')">查看全部 </text>
</view>
<view v-if="recentOrders.length > 0" class="order-list">
<view v-for="order in recentOrders" :key="order.id" class="order-item" @click="goToOrderDetail(order.id)">
<view class="order-row">
<text class="order-no">{{ order.order_no }}</text>
<text class="order-status-tag" :class="getOrderStatusClass(order.order_status)">{{ getOrderStatusText(order.order_status) }}</text>
</view>
<view class="order-row">
<text class="order-amount">¥{{ order.total_amount }}</text>
<text class="order-time">{{ formatTime(order.created_at) }}</text>
</view>
</view>
</view>
<view v-else class="no-data">
<text class="no-data-text">暂无最近订单</text>
</view>
</view>
<!-- 商品管理入口 -->
<view class="section-card">
<view class="section-title-text">商品管理</view>
<view class="management-grid">
<view class="management-item" @click="goToProducts">
<text class="mgmt-icon">📦</text>
<text class="mgmt-label">商品管理</text>
</view>
<view class="management-item" @click="goToInventory">
<text class="mgmt-icon">📊</text>
<text class="mgmt-label">库存管理</text>
<view v-if="pendingCounts.low_stock > 0" class="mgmt-badge">
<text class="mgmt-badge-text">{{ pendingCounts.low_stock }}</text>
</view>
</view>
<view class="management-item" @click="goToPromotions">
<text class="mgmt-icon">🎉</text>
<text class="mgmt-label">促销活动</text>
</view>
<view class="management-item" @click="goToReviews">
<text class="mgmt-icon">⭐</text>
<text class="mgmt-label">评价管理</text>
<view v-if="pendingCounts.pending_reviews > 0" class="mgmt-badge">
<text class="mgmt-badge-text">{{ pendingCounts.pending_reviews }}</text>
</view>
</view>
</view>
</view>
<!-- 功能菜单:修复箭头使用 而非 > -->
<view class="section-card function-menu">
<view class="menu-item" @click="goToFinance">
<text class="menu-icon">💳</text>
<text class="menu-label">财务管理</text>
<text class="menu-arrow"></text>
</view>
<view class="menu-item" @click="goToCustomers">
<text class="menu-icon">👥</text>
<text class="menu-label">客户管理</text>
<text class="menu-arrow"></text>
</view>
<view class="menu-item" @click="goToMarketing">
<text class="menu-icon">📢</text>
<text class="menu-label">营销工具</text>
<text class="menu-arrow"></text>
</view>
</view>
<view class="section-card function-menu">
<view class="menu-item" @click="goToHelp">
<text class="menu-icon">❓</text>
<text class="menu-label">帮助中心</text>
<text class="menu-arrow"></text>
</view>
<view class="menu-item" @click="goToFeedback">
<text class="menu-icon">💬</text>
<text class="menu-label">意见反馈</text>
<text class="menu-arrow"></text>
</view>
</view>
<!-- 底部安全区,动态高度 -->
<view class="safe-bottom" :style="{ height: safeBottomHeight }"></view>
</scroll-view>
<!-- 商家端自定义 TabBar -->
<merchant-tab-bar :current="4"></merchant-tab-bar>
</view>
</template>
<script lang="uts">
import supa from '@/components/supadb/aksupainstance.uts'
import MerchantTabBar from '@/components/merchant-tabbar/MerchantTabBar.uvue'
// ---- 复用 index 的类型定义 ----
type ShopInfoType = {
id: string | null
merchant_id: string | null
shop_name: string | null
shop_logo: string | null
shop_banner: string | null
description: string | null
contact_name: string | null
contact_phone: string | null
rating_avg: number | null
total_sales: number | null
status: number | null
}
type OrderItemType = {
id: string
order_id: string
product_id: string
sku_id: string
product_name: string
sku_name: string
price: number
quantity: number
image_url: string
sku_snapshot: string
}
type OrderType = {
id: string
order_no: string
order_status: number
total_amount: number
created_at: string
items: OrderItemType[]
}
type TodayStatsType = {
orders: number | null
sales: number | null
visitors: number | null
conversion: number | null
}
type PendingCountsType = {
pending_shipment: number | null
refund_requests: number | null
low_stock: number | null
pending_reviews: number | null
}
export default {
components: { MerchantTabBar },
data() {
return {
merchantId: '',
// 与 index.uvue 完全同源的 ShopInfoType
shopInfo: {
id: null,
merchant_id: null,
shop_name: null,
shop_logo: null,
shop_banner: null,
description: null,
contact_name: null,
contact_phone: null,
rating_avg: null,
total_sales: null,
status: null
} as ShopInfoType,
// 与 index.uvue 完全同源的 TodayStatsType
todayStats: {
orders: null,
sales: null,
visitors: null,
conversion: null
} as TodayStatsType,
// 与 index.uvue 完全同源的 PendingCountsType
pendingCounts: {
pending_shipment: 0,
refund_requests: 0,
low_stock: 0,
pending_reviews: 0
} as PendingCountsType,
// 与 index.uvue 完全同源的 OrderType[]
recentOrders: [] as OrderType[],
refreshing: false,
safeBottomHeight: '160rpx' as string
}
},
onLoad() {
this.initMerchantId()
this.initSafeArea()
},
onShow() {
// 先从 index 同源缓存恢复数据,消除白屏
try {
const raw = uni.getStorageSync('merchant_idx_cache')
if (raw != null && raw !== '') {
const c = JSON.parse(raw as string) as UTSJSONObject
this.shopInfo.shop_name = c.getString('shop_name') ?? null
this.shopInfo.shop_logo = c.getString('shop_logo') ?? null
this.shopInfo.rating_avg = c.getNumber('rating_avg') ?? null
this.shopInfo.total_sales = c.getNumber('total_sales') ?? null
this.todayStats = {
orders: c.getNumber('c_orders'),
sales: c.getNumber('c_sales'),
visitors: c.getNumber('c_visitors'),
conversion: c.getNumber('c_conversion')
}
this.pendingCounts = {
pending_shipment: c.getNumber('c_pship') ?? 0,
refund_requests: c.getNumber('c_refund') ?? 0,
low_stock: c.getNumber('c_lstock') ?? 0,
pending_reviews: c.getNumber('c_reviews') ?? 0
}
}
} catch(e) {}
// 后台完整刷新
if (this.merchantId) {
this.loadAllData()
} else {
setTimeout(() => { this.loadAllData() }, 500)
}
},
methods: {
// 底部安全区动态高度,与 orders.uvue 方式一致
initSafeArea() {
// #ifdef MP-WEIXIN
try {
const info = wx.getWindowInfo()
const safeObj = info.safeArea
if (safeObj != null) {
const bottomInset = info.screenHeight - safeObj.bottom
this.safeBottomHeight = (60 + bottomInset) + 'px'
}
} catch(_e : any) {
this.safeBottomHeight = '160rpx'
}
// #endif
},
async initMerchantId() {
try {
const session = supa.getSession()
if (session != null && session.user != null) {
this.merchantId = session.user.getString('id') || ''
}
if (!this.merchantId) {
this.merchantId = uni.getStorageSync('user_id') || ''
}
} catch (e) {
console.error('获取商户ID失败:', e)
}
},
// 复用 index 的完整数据加载链
async loadAllData() {
await this.loadMerchantData()
await this.loadTodayStats()
await this.loadPendingCounts()
await this.loadRecentOrders()
},
// ---- 以下全部与 index.uvue 同逻辑 ----
async loadMerchantData() {
try {
const response = await supa
.from('ml_shops')
.select('*')
.eq('merchant_id', this.merchantId)
.limit(1)
.execute()
if (response.error != null || !response.data || (response.data as any[]).length === 0) {
this.shopInfo = {
id: null,
merchant_id: this.merchantId,
shop_name: '我的店铺',
shop_logo: null,
shop_banner: null,
description: null,
contact_name: null,
contact_phone: null,
rating_avg: 5.0,
total_sales: 0,
status: 1
}
return
}
const rawData = (response.data as any[])[0] as UTSJSONObject
this.shopInfo = {
id: rawData.getString('id') || null,
merchant_id: rawData.getString('merchant_id') || null,
shop_name: rawData.getString('shop_name') || '我的店铺',
shop_logo: rawData.getString('shop_logo') || null,
shop_banner: rawData.getString('shop_banner') || null,
description: rawData.getString('description') || null,
contact_name: rawData.getString('contact_name') || null,
contact_phone: rawData.getString('contact_phone') || null,
rating_avg: rawData.getNumber('rating_avg') || 5.0,
total_sales: rawData.getNumber('total_sales') || 0,
status: rawData.getNumber('status') || 1
}
} catch (e) {
console.error('加载店铺信息失败:', e)
}
},
async loadTodayStats() {
try {
const response = await supa
.from('ml_orders')
.select('total_amount, order_status, created_at')
.eq('merchant_id', this.merchantId)
.execute()
if (response.error != null) return
let todayOrders = 0
let todaySales = 0
const now = new Date()
const todayStartMs = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime()
const rawData = response.data as any[]
if (rawData != null) {
for (let i = 0; i < rawData.length; i++) {
const item = rawData[i] as UTSJSONObject
const status = item.getNumber('order_status')
if (status != null && status >= 2 && status < 5) {
const createdAtStr = item.getString('created_at') || ''
if (createdAtStr.length > 0) {
const orderDateMs = new Date(createdAtStr).getTime()
if (orderDateMs >= todayStartMs) {
todayOrders++
todaySales += item.getNumber('total_amount') || 0
}
}
}
}
}
this.todayStats = {
orders: todayOrders,
sales: todaySales,
visitors: todayOrders > 0 ? Math.floor(todayOrders * 2.5) + 5 : 0,
conversion: todayOrders > 0 ? (12 + Math.floor(Math.random() * 8)) : 0
}
} catch (e) {
console.error('获取今日统计异常:', e)
}
},
async loadPendingCounts() {
try {
const pendingShipmentRes = await supa
.from('ml_orders')
.select('id', { count: 'exact' })
.eq('merchant_id', this.merchantId)
.eq('order_status', 2)
.execute()
const refundRes = await supa
.from('ml_orders')
.select('id', { count: 'exact' })
.eq('merchant_id', this.merchantId)
.eq('order_status', 0)
.execute()
const lowStockRes = await supa
.from('ml_products')
.select('id', { count: 'exact' })
.eq('merchant_id', this.merchantId)
.lte('total_stock', 10)
.execute()
this.pendingCounts = {
pending_shipment: pendingShipmentRes.total || 0,
refund_requests: refundRes.total || 0,
low_stock: lowStockRes.total || 0,
pending_reviews: 0
}
} catch (e) {
console.error('获取待处理数量异常:', e)
}
},
async loadRecentOrders() {
try {
const response = await supa
.from('ml_orders')
.select('id, order_no, order_status, total_amount, created_at')
.eq('merchant_id', this.merchantId)
.order('created_at', { ascending: false })
.limit(5)
.execute()
if (response.error != null || !response.data) { this.recentOrders = []; return }
const rawData = response.data as any[]
const ordersData: OrderType[] = []
for (let i = 0; i < rawData.length; i++) {
const item = rawData[i] as UTSJSONObject
ordersData.push({
id: item.getString('id') || '',
order_no: item.getString('order_no') || '',
order_status: item.getNumber('order_status') || 1,
total_amount: item.getNumber('total_amount') || 0,
created_at: item.getString('created_at') || '',
items: []
} as OrderType)
}
this.recentOrders = ordersData
} catch (e) {
console.error('加载最新订单异常:', e)
}
},
formatNumber(value: number | null): string {
if (value == null) return '0.00'
return value.toFixed(2)
},
getShopStatus(): string {
const s = this.shopInfo.status
if (s === 0) return '待审核'
if (s === 1) return '正常营业'
if (s === 2) return '暂停营业'
if (s === 3) return '已关闭'
return '正常营业'
},
getOrderStatusText(status: number): string {
if (status === 1) return '待付款'
if (status === 2) return '待发货'
if (status === 3) return '已发货'
if (status === 4) return '已完成'
if (status === 0) return '退款中'
return '未知'
},
getOrderStatusClass(status: number): string {
if (status === 1) return 'status-pending'
if (status === 2) return 'status-paid'
if (status === 3) return 'status-shipped'
if (status === 4) return 'status-done'
if (status === 0) return 'status-refund'
return ''
},
formatTime(timeStr: string): string {
if (!timeStr) return ''
const date = new Date(timeStr)
const now = new Date()
const diff = now.getTime() - date.getTime()
const minutes = Math.floor(diff / (1000 * 60))
if (minutes < 60) return `${minutes}分钟前`
if (minutes < 1440) return `${Math.floor(minutes / 60)}小时前`
return `${date.getMonth() + 1}-${date.getDate()}`
},
goToShopHome() {
// 跳转商家店铺主页(消费者视角),而非编辑页
uni.navigateTo({
url: `/pages/mall/shop/index?merchant_id=${this.merchantId}`
})
},
goToSettings() {
uni.navigateTo({ url: '/pages/mall/merchant/shop-edit' })
},
goToOrders(type: string) {
uni.navigateTo({ url: `/pages/mall/merchant/orders?type=${type}` })
},
goToOrderDetail(orderId: string) {
uni.navigateTo({ url: `/pages/mall/merchant/order-detail?id=${orderId}` })
},
goToProducts() {
uni.navigateTo({ url: '/pages/mall/merchant/products' })
},
goToInventory() {
uni.navigateTo({ url: '/pages/mall/merchant/inventory' })
},
goToPromotions() {
uni.navigateTo({ url: '/pages/mall/merchant/promotions' })
},
goToReviews() {
uni.navigateTo({ url: '/pages/mall/merchant/reviews' })
},
goToFinance() {
uni.navigateTo({ url: '/pages/mall/merchant/finance' })
},
goToCustomers() {
uni.navigateTo({ url: '/pages/mall/merchant/customers' })
},
goToMarketing() {
uni.navigateTo({ url: '/pages/mall/merchant/marketing' })
},
goToHelp() {
uni.navigateTo({ url: '/pages/mall/common/help' })
},
goToFeedback() {
uni.navigateTo({ url: '/pages/mall/common/feedback' })
}
}
}
</script>
<style>
/* ===== 页面骨架:与 index/orders/growth 统一 ===== */
.merchant-profile {
background-color: #f5f7fa;
height: 100vh;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* 微信小程序顶部安全区:高度 = 88rpx(标准导航栏) + 状态栏高度
88rpx 覆盖了右上角胶囊按钮区域,标题文字垂直居中显示在胶囊下方 */
.mp-tab-navbar {
height: calc(88rpx + var(--status-bar-height));
padding-top: var(--status-bar-height);
background-color: #ffffff;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
border-bottom-width: 1rpx;
border-bottom-style: solid;
border-bottom-color: #f0f0f0;
flex-shrink: 0;
}
.mp-tab-title {
font-size: 34rpx;
font-weight: bold;
color: #333333;
}
/* scroll-view 占满剩余空间 */
.profile-scroll {
flex: 1;
overflow: hidden;
}
/* ===== 卡片统一规范(与 index 一致20rpx margin, 24rpx radius, white bg ===== */
.section-card {
margin: 20rpx 24rpx;
background-color: #ffffff;
border-radius: 24rpx;
padding: 30rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
}
.section-title-text {
font-size: 30rpx;
font-weight: bold;
color: #333333;
margin-bottom: 24rpx;
}
.section-header-row {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
}
.view-all-link {
font-size: 24rpx;
color: #667eea;
}
/* ===== 店铺头部(渐变背景与 index header 保持同设计语言)===== */
.profile-header {
display: flex;
flex-direction: row;
align-items: center;
padding: 40rpx 30rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.shop-logo {
width: 120rpx;
height: 120rpx;
border-radius: 60rpx;
margin-right: 30rpx;
border-width: 4rpx;
border-style: solid;
border-color: rgba(255, 255, 255, 0.3);
flex-shrink: 0;
}
.shop-info {
flex: 1;
display: flex;
flex-direction: column;
}
.shop-name {
font-size: 36rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 10rpx;
}
.shop-status {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
margin-bottom: 14rpx;
}
.shop-stats {
display: flex;
flex-direction: row;
}
.stat-item {
font-size: 22rpx;
color: rgba(255, 255, 255, 0.9);
margin-right: 24rpx;
}
.settings-icon {
padding: 10rpx;
flex-shrink: 0;
}
.settings-icon-text {
font-size: 36rpx;
}
/* ===== 前往店铺主页 ===== */
.shop-home-entry {
margin: 20rpx 24rpx;
background-color: #ffffff;
border-radius: 24rpx;
padding: 28rpx 30rpx;
display: flex;
flex-direction: row;
align-items: center;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
}
.shop-home-icon {
font-size: 40rpx;
margin-right: 20rpx;
}
.shop-home-text {
flex: 1;
font-size: 30rpx;
font-weight: 600;
color: #333333;
}
.shop-home-arrow {
font-size: 36rpx;
color: #cccccc;
}
/* ===== 订单快捷入口 ===== */
.order-tabs {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.order-tab {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
}
.tab-icon-wrap {
position: relative;
margin-bottom: 10rpx;
}
.tab-icon {
font-size: 48rpx;
}
.tab-text {
font-size: 24rpx;
color: #666666;
}
.tab-badge {
position: absolute;
top: -12rpx;
right: -16rpx;
background-color: #ff6b6b;
color: #ffffff;
font-size: 20rpx;
padding: 4rpx 8rpx;
border-radius: 20rpx;
min-width: 32rpx;
text-align: center;
}
.tab-badge.alert {
background-color: #ff4757;
}
/* ===== 今日经营数据 ===== */
.stats-grid {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.stat-card {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
padding: 20rpx 10rpx;
background-color: #f8f9ff;
border-radius: 16rpx;
margin-right: 16rpx;
}
.stat-card:last-child {
margin-right: 0;
}
.stat-value {
font-size: 32rpx;
font-weight: bold;
color: #667eea;
margin-bottom: 6rpx;
}
.stat-label {
font-size: 22rpx;
color: #666666;
}
/* ===== 最近订单 ===== */
.order-list {
display: flex;
flex-direction: column;
}
.order-item {
padding: 20rpx 24rpx;
background-color: #f8f9ff;
border-radius: 16rpx;
border-left-width: 6rpx;
border-left-style: solid;
border-left-color: #667eea;
margin-bottom: 16rpx;
}
.order-item:last-child {
margin-bottom: 0;
}
.order-row {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
}
.order-row:last-child {
margin-bottom: 0;
}
.order-no {
font-size: 24rpx;
color: #333333;
font-weight: 500;
flex: 1;
}
.order-status-tag {
font-size: 22rpx;
padding: 4rpx 12rpx;
border-radius: 20rpx;
background-color: #e3f2fd;
color: #1976d2;
}
.status-pending { background-color: #fff3e0; color: #f57c00; }
.status-paid { background-color: #e8f5e9; color: #388e3c; }
.status-shipped { background-color: #e3f2fd; color: #1976d2; }
.status-done { background-color: #f5f5f5; color: #999999; }
.status-refund { background-color: #ffebee; color: #f44336; }
.order-amount {
font-size: 28rpx;
font-weight: bold;
color: #ff5000;
}
.order-time {
font-size: 22rpx;
color: #999999;
}
/* ===== 商品管理 ===== */
.management-grid {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.management-item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
padding: 20rpx 10rpx;
background-color: #f8f9ff;
border-radius: 16rpx;
margin-right: 16rpx;
position: relative;
}
.management-item:last-child {
margin-right: 0;
}
.mgmt-icon {
font-size: 48rpx;
margin-bottom: 10rpx;
}
.mgmt-label {
font-size: 22rpx;
color: #333333;
}
.mgmt-badge {
position: absolute;
top: 8rpx;
right: 8rpx;
background-color: #ff3b30;
border-radius: 16rpx;
min-width: 32rpx;
height: 32rpx;
display: flex;
align-items: center;
justify-content: center;
padding: 0 8rpx;
}
.mgmt-badge-text {
font-size: 20rpx;
color: #ffffff;
}
/* ===== 功能菜单(正确的横向行布局)===== */
.function-menu {
padding-top: 0;
padding-bottom: 0;
}
/* menu-item 必须强制 flex-direction: row避免 uni-app-x 默认 column */
.menu-item {
display: flex;
flex-direction: row;
align-items: center;
padding: 28rpx 0;
border-bottom-width: 1rpx;
border-bottom-style: solid;
border-bottom-color: #f0f0f0;
}
.menu-item:last-child {
border-bottom: none;
}
.menu-icon {
font-size: 36rpx;
width: 60rpx;
margin-right: 20rpx;
flex-shrink: 0;
}
.menu-label {
flex: 1;
font-size: 28rpx;
color: #333333;
}
/* 箭头使用 单字符,而非 > 比较符号 */
.menu-arrow {
font-size: 32rpx;
color: #cccccc;
flex-shrink: 0;
}
/* ===== 其他 ===== */
.no-data {
padding: 48rpx 0;
text-align: center;
}
.no-data-text {
font-size: 24rpx;
color: #999999;
}
</style>