- doctor-login submitLogin 增加「请输入密码」前置校验, 与 getCode 一致,避免空密码误触发登录请求 - 配合后端 service_user 空密码回退 PC 医生/药师密码校验
165 lines
7.8 KiB
Vue
165 lines
7.8 KiB
Vue
<template>
|
|
<business-page-layout title="业务工作台" :show-tabbar="true" :tab-index="0">
|
|
<view class="workspace-container">
|
|
|
|
<!-- 极简顶部英雄区 (保持原风格) -->
|
|
<view class="hero-section">
|
|
<view class="brand-info-wrap">
|
|
<view class="brand-text">
|
|
<view class="badge"><text class="badge-text">业务工作台</text></view>
|
|
<text class="store-name">{{ displayName }}</text>
|
|
<text class="store-sub">今日业务进度更新</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 核心资产看板 (优化布局与数值层级) -->
|
|
<view class="dashboard-wrapper">
|
|
<view class="dashboard-card">
|
|
<view class="stat-item">
|
|
<text class="stat-label">门店 (录/通)</text>
|
|
<view class="stat-value-group">
|
|
<text class="stat-value">{{ stats.storeCount || 0 }}</text>
|
|
<text class="stat-slash">/</text>
|
|
<text class="stat-value-highlight">{{ stats.storeApprovedCount || 0 }}</text>
|
|
</view>
|
|
</view>
|
|
<view class="stat-item">
|
|
<text class="stat-label">医生 (录/通)</text>
|
|
<view class="stat-value-group">
|
|
<text class="stat-value">{{ stats.doctorCount || 0 }}</text>
|
|
<text class="stat-slash">/</text>
|
|
<text class="stat-value-highlight">{{ stats.doctorApprovedCount || 0 }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 多彩微拟物双列卡片区 -->
|
|
<view class="content-wrapper">
|
|
<view v-for="section in sections" :key="section.key" class="section-panel">
|
|
<view class="panel-header">
|
|
<text class="panel-title">{{ section.title }}</text>
|
|
</view>
|
|
|
|
<view class="service-grid">
|
|
<view
|
|
v-for="item in section.items"
|
|
:key="item.key"
|
|
class="service-card"
|
|
hover-class="service-card-hover"
|
|
@click="go(item)"
|
|
>
|
|
<view class="service-icon-box" :style="{ background: item.theme.bg }">
|
|
<u-icon :name="item.icon" size="38" :color="item.theme.color"></u-icon>
|
|
</view>
|
|
<view class="service-info">
|
|
<text class="service-name">{{ item.label }}</text>
|
|
<text class="service-desc">{{ item.desc || '快捷进入' }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
</view>
|
|
</business-page-layout>
|
|
</template>
|
|
|
|
<script>
|
|
// ... (脚本逻辑保持不变)
|
|
import BusinessPageLayout from '@/subPackages/sub_salesperson/components/business-page-layout.vue'
|
|
import { getSalespersonInputStats } from '@/api/salesperson.js'
|
|
import { navigateToInputForm } from '@/subPackages/sub_salesperson/common/inputNavigation.js'
|
|
|
|
export default {
|
|
components: { BusinessPageLayout },
|
|
data() {
|
|
return {
|
|
displayName: '',
|
|
stats: { storeCount: 0, storeApprovedCount: 0, doctorCount: 0, doctorApprovedCount: 0 },
|
|
themes: {
|
|
store: { bg: 'linear-gradient(135deg, #ECFEFF, #CFFAFE)', color: '#06B6D4' },
|
|
doctor: { bg: 'linear-gradient(135deg, #FFFBEB, #FEF3C7)', color: '#D97706' }
|
|
}
|
|
}
|
|
},
|
|
// ... (computed 及 methods 保持原样)
|
|
computed: {
|
|
sections() {
|
|
return [
|
|
{ key: 'input', title: '信息录入', items: [
|
|
{ key: 'store-form', label: '门店录入', desc: '新增线下门店', path: '/subPackages/sub_salesperson/store-input/form', inputType: 'store', isForm: true, icon: 'plus-square-fill', theme: this.themes.store },
|
|
{ key: 'doctor-form', label: '医生录入', desc: '新增合作医生', path: '/subPackages/sub_salesperson/doctor-input/form', inputType: 'doctor', isForm: true, icon: 'plus-circle-fill', theme: this.themes.doctor },
|
|
]},
|
|
{ key: 'list', title: '档案管理', items: [
|
|
{ key: 'my-store', label: '我的诊所', desc: '查看所属正式诊所', path: '/subPackages/sub_platform_admin/store/index', icon: 'home', theme: this.themes.store },
|
|
{ key: 'store-list', label: '门店列表', desc: '查看已录门店', path: '/subPackages/sub_salesperson/store-input/index', icon: 'home-fill', theme: this.themes.store },
|
|
{ key: 'doctor-list', label: '医生列表', desc: '查看已录医生', path: '/subPackages/sub_salesperson/doctor-input/index', icon: 'account-fill', theme: this.themes.doctor },
|
|
]}
|
|
]
|
|
}
|
|
},
|
|
onShow() {
|
|
const user = uni.getStorageSync('salesperson_user') || {}
|
|
this.displayName = user.nick_name || '业务员'
|
|
this.fetchDashboardData()
|
|
},
|
|
methods: {
|
|
async fetchDashboardData() {
|
|
try {
|
|
const wrap = await getSalespersonInputStats()
|
|
if (!wrap || !wrap.ok) return
|
|
const data = wrap.data || {}
|
|
this.stats = {
|
|
storeCount: data.store_count || 0,
|
|
storeApprovedCount: data.store_approved_count || 0,
|
|
doctorCount: data.doctor_count || 0,
|
|
doctorApprovedCount: data.doctor_approved_count || 0,
|
|
}
|
|
} catch (e) { console.error('获取统计数据失败', e) }
|
|
},
|
|
go(item) {
|
|
uni.vibrateShort(); // 增加轻微触感反馈
|
|
if (item.isForm && item.inputType) {
|
|
navigateToInputForm(item.path, item.inputType)
|
|
return
|
|
}
|
|
uni.navigateTo({ url: item.path })
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
/* 保持你的容器风格 */
|
|
.workspace-container { padding-bottom: 80rpx; background-color: #F4F6F8; min-height: 100vh; }
|
|
.hero-section { background: linear-gradient(135deg, #6acdbb 0%, #4db6a8 100%); padding: 40rpx 40rpx 80rpx; border-bottom-left-radius: 48rpx; border-bottom-right-radius: 48rpx; box-shadow: 0 4rpx 20rpx rgba(77, 182, 168, 0.2); }
|
|
.brand-text { flex: 1; }
|
|
.badge { display: inline-flex; background: rgba(255, 255, 255, 0.15); padding: 6rpx 20rpx; border-radius: 30rpx; margin-bottom: 20rpx; border: 1px solid rgba(255, 255, 255, 0.2); }
|
|
.badge-text { font-size: 22rpx; color: #fff; }
|
|
.store-name { font-size: 42rpx; font-weight: 600; color: #fff; }
|
|
.store-sub { font-size: 26rpx; color: rgba(255, 255, 255, 0.85); }
|
|
|
|
/* 看板区域优化 */
|
|
.dashboard-wrapper { margin: -40rpx 30rpx 30rpx; }
|
|
.dashboard-card { background: #fff; border-radius: 32rpx; padding: 40rpx 30rpx; display: grid; grid-template-columns: repeat(2, 1fr); gap: 20rpx; box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.05); }
|
|
.stat-item { display: flex; flex-direction: column; align-items: center; }
|
|
.stat-label { font-size: 22rpx; color: #94A3B8; margin-bottom: 12rpx; }
|
|
.stat-value-group { display: flex; align-items: baseline; }
|
|
.stat-value { font-size: 42rpx; font-weight: 700; color: #1E293B; }
|
|
.stat-slash { font-size: 32rpx; color: #CBD5E1; margin: 0 8rpx; }
|
|
.stat-value-highlight { font-size: 42rpx; font-weight: 700; color: #059669; }
|
|
|
|
/* 业务卡片区保持原样 */
|
|
.content-wrapper { position: relative; z-index: 10; }
|
|
.section-panel { margin: 0 30rpx 30rpx; }
|
|
.panel-title { font-size: 34rpx; font-weight: 700; color: #1E293B; margin-bottom: 24rpx; display: block; padding-left: 10rpx;}
|
|
.service-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20rpx; }
|
|
.service-card { background: #FFFFFF; border-radius: 28rpx; padding: 30rpx 24rpx; display: flex; align-items: center; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.02); }
|
|
.service-card-hover { transform: translateY(-2rpx); }
|
|
.service-icon-box { width: 76rpx; height: 76rpx; border-radius: 22rpx; display: flex; align-items: center; justify-content: center; margin-right: 20rpx; flex-shrink: 0; box-shadow: inset 0 2rpx 4rpx rgba(255, 255, 255, 0.5); }
|
|
.service-info { display: flex; flex-direction: column; flex: 1; overflow: hidden; }
|
|
.service-name { font-size: 28rpx; font-weight: 600; color: #1E293B; line-height: 1.2; }
|
|
.service-desc { font-size: 20rpx; color: #94A3B8; margin-top: 4rpx; line-height: 1.2; }
|
|
</style> |