微信小程序页面迁移校验之前 P5任务处理之前
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"navigationBarTitleText": "助教看板",
|
||||
"enablePullDownRefresh": true,
|
||||
"usingComponents": {
|
||||
"filter-dropdown": "/components/filter-dropdown/filter-dropdown",
|
||||
"ai-float-button": "/components/ai-float-button/ai-float-button",
|
||||
"board-tab-bar": "/components/board-tab-bar/board-tab-bar",
|
||||
"t-loading": "tdesign-miniprogram/loading/loading",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-empty": "tdesign-miniprogram/empty/empty",
|
||||
"t-tag": "tdesign-miniprogram/tag/tag"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
// 助教看板页 — 排序×技能×时间三重筛选,4 种维度卡片
|
||||
// TODO: 联调时替换 mock 数据为真实 API 调用
|
||||
export {}
|
||||
|
||||
/** 排序维度 → 卡片模板映射 */
|
||||
type DimType = 'perf' | 'salary' | 'sv' | 'task'
|
||||
|
||||
const SORT_TO_DIM: Record<string, DimType> = {
|
||||
perf_desc: 'perf',
|
||||
perf_asc: 'perf',
|
||||
salary_desc: 'salary',
|
||||
salary_asc: 'salary',
|
||||
sv_desc: 'sv',
|
||||
task_desc: 'task',
|
||||
}
|
||||
|
||||
const SORT_OPTIONS = [
|
||||
{ value: 'perf_desc', text: '定档业绩最高' },
|
||||
{ value: 'perf_asc', text: '定档业绩最低' },
|
||||
{ value: 'salary_desc', text: '工资最高' },
|
||||
{ value: 'salary_asc', text: '工资最低' },
|
||||
{ value: 'sv_desc', text: '客源储值最高' },
|
||||
{ value: 'task_desc', text: '任务完成最多' },
|
||||
]
|
||||
|
||||
const SKILL_OPTIONS = [
|
||||
{ value: 'all', text: '不限' },
|
||||
{ value: 'chinese', text: '🎱 中式/追分' },
|
||||
{ value: 'snooker', text: '斯诺克' },
|
||||
{ value: 'mahjong', text: '🀄 麻将/棋牌' },
|
||||
{ value: 'karaoke', text: '🎤 团建/K歌' },
|
||||
]
|
||||
|
||||
const TIME_OPTIONS = [
|
||||
{ value: 'month', text: '本月' },
|
||||
{ value: 'quarter', text: '本季度' },
|
||||
{ value: 'last_month', text: '上月' },
|
||||
{ value: 'last_3m', text: '前3个月(不含本月)' },
|
||||
{ value: 'last_quarter', text: '上季度' },
|
||||
{ value: 'last_6m', text: '最近6个月(不含本月,不支持客源储值最高)' },
|
||||
]
|
||||
|
||||
/** 等级 → 样式类映射 */
|
||||
const LEVEL_CLASS: Record<string, string> = {
|
||||
'星级': 'level--star',
|
||||
'高级': 'level--high',
|
||||
'中级': 'level--mid',
|
||||
'初级': 'level--low',
|
||||
}
|
||||
|
||||
/** 技能 → 样式类映射 */
|
||||
const SKILL_CLASS: Record<string, string> = {
|
||||
'🎱': 'skill--chinese',
|
||||
'斯': 'skill--snooker',
|
||||
'🀄': 'skill--mahjong',
|
||||
'🎤': 'skill--karaoke',
|
||||
}
|
||||
|
||||
interface CoachItem {
|
||||
id: string
|
||||
name: string
|
||||
initial: string
|
||||
avatarGradient: string
|
||||
level: string
|
||||
levelClass: string
|
||||
skills: Array<{ text: string; cls: string }>
|
||||
topCustomers: string[]
|
||||
// 定档业绩维度
|
||||
perfHours: string
|
||||
perfHoursBefore?: string
|
||||
perfGap?: string
|
||||
perfReached: boolean
|
||||
// 工资维度
|
||||
salary: string
|
||||
salaryPerfHours: string
|
||||
salaryPerfBefore?: string
|
||||
// 客源储值维度
|
||||
svAmount: string
|
||||
svCustomerCount: string
|
||||
svConsume: string
|
||||
// 任务维度
|
||||
taskRecall: string
|
||||
taskCallback: string
|
||||
}
|
||||
|
||||
/** Mock 数据(忠于 H5 原型 6 位助教) */
|
||||
const MOCK_COACHES: CoachItem[] = [
|
||||
{
|
||||
id: 'c1', name: '小燕', initial: '小',
|
||||
avatarGradient: 'avatar--blue',
|
||||
level: '星级', levelClass: LEVEL_CLASS['星级'],
|
||||
skills: [{ text: '🎱', cls: SKILL_CLASS['🎱'] }],
|
||||
topCustomers: ['💖 王先生', '💖 李女士', '💛 赵总'],
|
||||
perfHours: '86.2h', perfHoursBefore: '92.0h', perfGap: '距升档 13.8h', perfReached: false,
|
||||
salary: '¥12,680', salaryPerfHours: '86.2h', salaryPerfBefore: '92.0h',
|
||||
svAmount: '¥45,200', svCustomerCount: '18', svConsume: '¥8,600',
|
||||
taskRecall: '18', taskCallback: '14',
|
||||
},
|
||||
{
|
||||
id: 'c2', name: '泡芙', initial: '泡',
|
||||
avatarGradient: 'avatar--green',
|
||||
level: '高级', levelClass: LEVEL_CLASS['高级'],
|
||||
skills: [{ text: '斯', cls: SKILL_CLASS['斯'] }],
|
||||
topCustomers: ['💖 陈先生', '💛 刘女士', '💛 黄总'],
|
||||
perfHours: '72.5h', perfHoursBefore: '78.0h', perfGap: '距升档 7.5h', perfReached: false,
|
||||
salary: '¥10,200', salaryPerfHours: '72.5h', salaryPerfBefore: '78.0h',
|
||||
svAmount: '¥38,600', svCustomerCount: '15', svConsume: '¥6,200',
|
||||
taskRecall: '15', taskCallback: '13',
|
||||
},
|
||||
{
|
||||
id: 'c3', name: 'Amy', initial: 'A',
|
||||
avatarGradient: 'avatar--pink',
|
||||
level: '星级', levelClass: LEVEL_CLASS['星级'],
|
||||
skills: [{ text: '🎱', cls: SKILL_CLASS['🎱'] }, { text: '斯', cls: SKILL_CLASS['斯'] }],
|
||||
topCustomers: ['💖 张先生', '💛 周女士', '💛 吴总'],
|
||||
perfHours: '68.0h', perfHoursBefore: '72.5h', perfGap: '距升档 32.0h', perfReached: false,
|
||||
salary: '¥9,800', salaryPerfHours: '68.0h', salaryPerfBefore: '72.5h',
|
||||
svAmount: '¥32,100', svCustomerCount: '14', svConsume: '¥5,800',
|
||||
taskRecall: '12', taskCallback: '13',
|
||||
},
|
||||
{
|
||||
id: 'c4', name: 'Mia', initial: 'M',
|
||||
avatarGradient: 'avatar--amber',
|
||||
level: '中级', levelClass: LEVEL_CLASS['中级'],
|
||||
skills: [{ text: '🀄', cls: SKILL_CLASS['🀄'] }],
|
||||
topCustomers: ['💛 赵先生', '💛 吴女士', '💛 孙总'],
|
||||
perfHours: '55.0h', perfGap: '距升档 5.0h', perfReached: false,
|
||||
salary: '¥7,500', salaryPerfHours: '55.0h',
|
||||
svAmount: '¥28,500', svCustomerCount: '12', svConsume: '¥4,100',
|
||||
taskRecall: '10', taskCallback: '10',
|
||||
},
|
||||
{
|
||||
id: 'c5', name: '糖糖', initial: '糖',
|
||||
avatarGradient: 'avatar--purple',
|
||||
level: '初级', levelClass: LEVEL_CLASS['初级'],
|
||||
skills: [{ text: '🎱', cls: SKILL_CLASS['🎱'] }],
|
||||
topCustomers: ['💛 钱先生', '💛 孙女士', '💛 周总'],
|
||||
perfHours: '42.0h', perfHoursBefore: '45.0h', perfReached: true,
|
||||
salary: '¥6,200', salaryPerfHours: '42.0h', salaryPerfBefore: '45.0h',
|
||||
svAmount: '¥22,000', svCustomerCount: '10', svConsume: '¥3,500',
|
||||
taskRecall: '8', taskCallback: '10',
|
||||
},
|
||||
{
|
||||
id: 'c6', name: '露露', initial: '露',
|
||||
avatarGradient: 'avatar--cyan',
|
||||
level: '中级', levelClass: LEVEL_CLASS['中级'],
|
||||
skills: [{ text: '🎤', cls: SKILL_CLASS['🎤'] }],
|
||||
topCustomers: ['💛 郑先生', '💛 冯女士', '💛 陈总'],
|
||||
perfHours: '38.0h', perfGap: '距升档 22.0h', perfReached: false,
|
||||
salary: '¥5,100', salaryPerfHours: '38.0h',
|
||||
svAmount: '¥18,300', svCustomerCount: '9', svConsume: '¥2,800',
|
||||
taskRecall: '6', taskCallback: '9',
|
||||
},
|
||||
]
|
||||
|
||||
Page({
|
||||
data: {
|
||||
pageState: 'loading' as 'loading' | 'empty' | 'normal',
|
||||
activeTab: 'coach' as 'finance' | 'customer' | 'coach',
|
||||
|
||||
selectedSort: 'perf_desc',
|
||||
sortOptions: SORT_OPTIONS,
|
||||
selectedSkill: 'all',
|
||||
skillOptions: SKILL_OPTIONS,
|
||||
selectedTime: 'month',
|
||||
timeOptions: TIME_OPTIONS,
|
||||
|
||||
/** 当前维度类型,控制卡片模板 */
|
||||
dimType: 'perf' as DimType,
|
||||
|
||||
coaches: [] as CoachItem[],
|
||||
allCoaches: [] as CoachItem[],
|
||||
|
||||
/** 筛选栏可见性(滚动隐藏/显示) */
|
||||
filterBarVisible: true,
|
||||
},
|
||||
|
||||
_lastScrollTop: 0,
|
||||
_scrollAcc: 0,
|
||||
_scrollDir: null as 'up' | 'down' | null,
|
||||
|
||||
onLoad() {
|
||||
this.loadData()
|
||||
},
|
||||
|
||||
onPullDownRefresh() {
|
||||
this.loadData()
|
||||
setTimeout(() => wx.stopPullDownRefresh(), 500)
|
||||
},
|
||||
|
||||
/** 滚动隐藏/显示筛选栏 */
|
||||
onPageScroll(e: { scrollTop: number }) {
|
||||
const y = e.scrollTop
|
||||
const delta = y - this._lastScrollTop
|
||||
this._lastScrollTop = y
|
||||
|
||||
if (y <= 8) {
|
||||
if (!this.data.filterBarVisible) this.setData({ filterBarVisible: true })
|
||||
this._scrollAcc = 0
|
||||
this._scrollDir = null
|
||||
return
|
||||
}
|
||||
|
||||
if (Math.abs(delta) <= 2) return
|
||||
const dir = delta > 0 ? 'down' : 'up'
|
||||
if (dir !== this._scrollDir) {
|
||||
this._scrollDir = dir
|
||||
this._scrollAcc = 0
|
||||
}
|
||||
this._scrollAcc += Math.abs(delta)
|
||||
|
||||
const threshold = dir === 'up' ? 12 : 24
|
||||
if (this._scrollAcc < threshold) return
|
||||
|
||||
const visible = dir === 'up'
|
||||
if (this.data.filterBarVisible !== visible) {
|
||||
this.setData({ filterBarVisible: visible })
|
||||
}
|
||||
this._scrollAcc = 0
|
||||
},
|
||||
|
||||
loadData() {
|
||||
this.setData({ pageState: 'loading' })
|
||||
setTimeout(() => {
|
||||
const data = MOCK_COACHES
|
||||
if (!data || data.length === 0) {
|
||||
this.setData({ pageState: 'empty' })
|
||||
return
|
||||
}
|
||||
this.setData({ allCoaches: data, coaches: data, pageState: 'normal' })
|
||||
}, 400)
|
||||
},
|
||||
|
||||
onTabChange(e: WechatMiniprogram.TouchEvent) {
|
||||
const tab = e.currentTarget.dataset.tab as string
|
||||
if (tab === 'finance') {
|
||||
wx.switchTab({ url: '/pages/board-finance/board-finance' })
|
||||
} else if (tab === 'customer') {
|
||||
wx.navigateTo({ url: '/pages/board-customer/board-customer' })
|
||||
}
|
||||
},
|
||||
|
||||
onSortChange(e: WechatMiniprogram.CustomEvent<{ value: string }>) {
|
||||
const val = e.detail.value
|
||||
this.setData({
|
||||
selectedSort: val,
|
||||
dimType: SORT_TO_DIM[val] || 'perf',
|
||||
})
|
||||
},
|
||||
|
||||
onSkillChange(e: WechatMiniprogram.CustomEvent<{ value: string }>) {
|
||||
this.setData({ selectedSkill: e.detail.value })
|
||||
},
|
||||
|
||||
onTimeChange(e: WechatMiniprogram.CustomEvent<{ value: string }>) {
|
||||
this.setData({ selectedTime: e.detail.value })
|
||||
},
|
||||
|
||||
onCoachTap(e: WechatMiniprogram.TouchEvent) {
|
||||
const id = e.currentTarget.dataset.id as string
|
||||
wx.navigateTo({ url: '/pages/coach-detail/coach-detail?id=' + id })
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,153 @@
|
||||
<!-- 助教看板页 — 忠于 H5 原型结构 -->
|
||||
|
||||
<!-- 加载态 -->
|
||||
<view class="page-loading" wx:if="{{pageState === 'loading'}}">
|
||||
<t-loading theme="circular" size="70rpx" text="加载中..." />
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="page-empty" wx:elif="{{pageState === 'empty'}}">
|
||||
<t-empty description="暂无助教数据" />
|
||||
</view>
|
||||
|
||||
<!-- 正常态 -->
|
||||
<block wx:else>
|
||||
<!-- 顶部看板 Tab -->
|
||||
<view class="board-tabs">
|
||||
<view class="board-tab" data-tab="finance" bindtap="onTabChange">
|
||||
<text>财务</text>
|
||||
</view>
|
||||
<view class="board-tab" data-tab="customer" bindtap="onTabChange">
|
||||
<text>客户</text>
|
||||
</view>
|
||||
<view class="board-tab board-tab--active" data-tab="coach">
|
||||
<text>助教</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 筛选区域 -->
|
||||
<view class="filter-bar {{filterBarVisible ? '' : 'filter-bar--hidden'}}">
|
||||
<view class="filter-bar-inner">
|
||||
<view class="filter-item filter-item--wide">
|
||||
<filter-dropdown
|
||||
label="定档业绩最高"
|
||||
options="{{sortOptions}}"
|
||||
value="{{selectedSort}}"
|
||||
bind:change="onSortChange"
|
||||
/>
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<filter-dropdown
|
||||
label="不限"
|
||||
options="{{skillOptions}}"
|
||||
value="{{selectedSkill}}"
|
||||
bind:change="onSkillChange"
|
||||
/>
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<filter-dropdown
|
||||
label="本月"
|
||||
options="{{timeOptions}}"
|
||||
value="{{selectedTime}}"
|
||||
bind:change="onTimeChange"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 助教列表 -->
|
||||
<view class="coach-list">
|
||||
<view
|
||||
class="coach-card"
|
||||
wx:for="{{coaches}}"
|
||||
wx:key="id"
|
||||
data-id="{{item.id}}"
|
||||
bindtap="onCoachTap"
|
||||
>
|
||||
<view class="card-row">
|
||||
<!-- 头像 -->
|
||||
<view class="card-avatar {{item.avatarGradient}}">
|
||||
<text class="avatar-text">{{item.initial}}</text>
|
||||
</view>
|
||||
|
||||
<!-- 信息区 -->
|
||||
<view class="card-info">
|
||||
<!-- 第一行:姓名 + 等级 + 技能 + 右侧指标 -->
|
||||
<view class="card-name-row">
|
||||
<text class="card-name">{{item.name}}</text>
|
||||
<text class="level-tag {{item.levelClass}}">{{item.level}}</text>
|
||||
<text
|
||||
class="skill-tag {{skill.cls}}"
|
||||
wx:for="{{item.skills}}"
|
||||
wx:for-item="skill"
|
||||
wx:key="text"
|
||||
>{{skill.text}}</text>
|
||||
|
||||
<!-- 定档业绩维度 -->
|
||||
<view class="card-right" wx:if="{{dimType === 'perf'}}">
|
||||
<text class="right-text">定档 <text class="right-highlight">{{item.perfHours}}</text></text>
|
||||
<text class="right-sub" wx:if="{{item.perfHoursBefore}}">折前 <text class="right-sub-val">{{item.perfHoursBefore}}</text></text>
|
||||
</view>
|
||||
|
||||
<!-- 工资维度 -->
|
||||
<view class="card-right" wx:elif="{{dimType === 'salary'}}">
|
||||
<text class="salary-tag">预估</text>
|
||||
<text class="salary-amount">{{item.salary}}</text>
|
||||
</view>
|
||||
|
||||
<!-- 客源储值维度 -->
|
||||
<view class="card-right" wx:elif="{{dimType === 'sv'}}">
|
||||
<text class="right-sub">储值</text>
|
||||
<text class="salary-amount">{{item.svAmount}}</text>
|
||||
</view>
|
||||
|
||||
<!-- 任务维度 -->
|
||||
<view class="card-right" wx:elif="{{dimType === 'task'}}">
|
||||
<text class="right-text">召回 <text class="right-highlight">{{item.taskRecall}}</text></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 第二行:客户列表 + 右侧补充 -->
|
||||
<view class="card-bottom-row">
|
||||
<view class="customer-list">
|
||||
<block wx:for="{{item.topCustomers}}" wx:for-item="cust" wx:for-index="custIdx" wx:key="*this">
|
||||
<text class="customer-item" wx:if="{{dimType !== 'sv' || custIdx < 2}}">{{cust}}</text>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!-- 定档业绩:距升档/已达标 -->
|
||||
<text class="bottom-right bottom-right--warning" wx:if="{{dimType === 'perf' && !item.perfReached}}">{{item.perfGap}}</text>
|
||||
<text class="bottom-right bottom-right--success" wx:elif="{{dimType === 'perf' && item.perfReached}}">✅ 已达标</text>
|
||||
|
||||
<!-- 工资:定档/折前 -->
|
||||
<view class="bottom-right-group" wx:elif="{{dimType === 'salary'}}">
|
||||
<text class="bottom-perf">定档 <text class="bottom-perf-val">{{item.salaryPerfHours}}</text></text>
|
||||
<text class="bottom-sub" wx:if="{{item.salaryPerfBefore}}">折前 <text class="bottom-sub-val">{{item.salaryPerfBefore}}</text></text>
|
||||
</view>
|
||||
|
||||
<!-- 客源储值:客户数 | 消耗 -->
|
||||
<view class="bottom-right-group" wx:elif="{{dimType === 'sv'}}">
|
||||
<text class="bottom-sub">客户 <text class="bottom-perf-val">{{item.svCustomerCount}}</text>人</text>
|
||||
<text class="bottom-divider">|</text>
|
||||
<text class="bottom-sub">消耗 <text class="bottom-perf-val">{{item.svConsume}}</text></text>
|
||||
</view>
|
||||
|
||||
<!-- 任务:回访数 -->
|
||||
<text class="bottom-sub" wx:elif="{{dimType === 'task'}}">回访 <text class="bottom-perf-val">{{item.taskCallback}}</text></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部安全区(为自定义导航栏留空间) -->
|
||||
<view class="safe-bottom"></view>
|
||||
</block>
|
||||
|
||||
<!-- 自定义底部导航栏 -->
|
||||
<board-tab-bar active="board" />
|
||||
|
||||
<!-- AI 悬浮按钮 — 在导航栏上方 -->
|
||||
<ai-float-button bottom="{{220}}" />
|
||||
|
||||
<dev-fab />
|
||||
@@ -0,0 +1,330 @@
|
||||
/* 助教看板页 — H5 px × 2 × 0.875 精确转换 */
|
||||
|
||||
/* ===== 三态 ===== */
|
||||
.page-loading,
|
||||
.page-empty {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 60vh;
|
||||
}
|
||||
|
||||
/* ===== 看板 Tab py-3=12px→22rpx, text-sm=14px→26rpx(视觉校准+2) ===== */
|
||||
.board-tabs {
|
||||
display: flex;
|
||||
background: #ffffff;
|
||||
border-bottom: 2rpx solid #eeeeee;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.board-tab {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 24rpx 0;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #8b8b8b;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.board-tab--active {
|
||||
color: #0052d9;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* w-24px→42rpx, h-3px→5rpx(H5 实际渲染偏细) */
|
||||
.board-tab--active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 42rpx;
|
||||
height: 5rpx;
|
||||
background: linear-gradient(90deg, #0052d9, #5b9cf8);
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
/* ===== 筛选区域 px-4=16px→28rpx, py-2=8px→14rpx ===== */
|
||||
.filter-bar {
|
||||
background: #f3f3f3;
|
||||
padding: 14rpx 28rpx;
|
||||
position: sticky;
|
||||
top: 70rpx;
|
||||
z-index: 15;
|
||||
border-bottom: 2rpx solid #eeeeee;
|
||||
transition: transform 220ms ease, opacity 220ms ease;
|
||||
}
|
||||
|
||||
.filter-bar--hidden {
|
||||
opacity: 0;
|
||||
transform: translateY(-110%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* p-1.5=6px→10rpx, gap-2=8px→14rpx, rounded-lg=8px→14rpx */
|
||||
.filter-bar-inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 14rpx;
|
||||
padding: 10rpx;
|
||||
border: 2rpx solid #eeeeee;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.filter-item--wide {
|
||||
flex: 1.8;
|
||||
}
|
||||
|
||||
/* ===== 助教列表 p-4=16px→28rpx, space-y-3=12px→20rpx ===== */
|
||||
.coach-list {
|
||||
padding: 24rpx 28rpx;
|
||||
}
|
||||
|
||||
/* ===== 助教卡片 p-4=16px→28rpx, rounded-2xl=16px→28rpx ===== */
|
||||
.coach-card {
|
||||
background: #ffffff;
|
||||
border-radius: 28rpx;
|
||||
padding: 30rpx 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.coach-card:active {
|
||||
opacity: 0.96;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* gap-3=12px→20rpx(视觉校准紧凑) */
|
||||
.card-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
/* ===== 头像 w-11 h-11=44px→78rpx, text-base=16px→28rpx ===== */
|
||||
.card-avatar {
|
||||
width: 78rpx;
|
||||
height: 78rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.avatar-text {
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 头像渐变色(忠于 H5 原型 6 种) */
|
||||
.avatar--blue { background: linear-gradient(135deg, #60a5fa, #6366f1); }
|
||||
.avatar--green { background: linear-gradient(135deg, #4ade80, #10b981); }
|
||||
.avatar--pink { background: linear-gradient(135deg, #f472b6, #f43f5e); }
|
||||
.avatar--amber { background: linear-gradient(135deg, #fbbf24, #f97316); }
|
||||
.avatar--purple { background: linear-gradient(135deg, #a78bfa, #8b5cf6); }
|
||||
.avatar--cyan { background: linear-gradient(135deg, #22d3ee, #14b8a6); }
|
||||
|
||||
/* ===== 信息区 ===== */
|
||||
.card-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* gap-1.5=6px→10rpx */
|
||||
.card-name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
/* text-base=16px→28rpx */
|
||||
.card-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #242424;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ===== 等级标签 px-1.5=6px→10rpx, py-0.5=2px→4rpx, text-xs=12px→22rpx ===== */
|
||||
.level-tag {
|
||||
padding: 4rpx 10rpx;
|
||||
font-size: 22rpx;
|
||||
border-radius: 6rpx;
|
||||
flex-shrink: 0;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.level--star {
|
||||
background: linear-gradient(to right, #fbbf24, #f97316);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.level--high {
|
||||
background: linear-gradient(to right, #a78bfa, #8b5cf6);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.level--mid {
|
||||
background: linear-gradient(to right, #60a5fa, #6366f1);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.level--low {
|
||||
background: linear-gradient(to right, #9ca3af, #6b7280);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* ===== 技能标签 ===== */
|
||||
.skill-tag {
|
||||
padding: 4rpx 10rpx;
|
||||
font-size: 22rpx;
|
||||
border-radius: 6rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.skill--chinese { background: rgba(0, 82, 217, 0.1); color: #0052d9; }
|
||||
.skill--snooker { background: rgba(0, 168, 112, 0.1); color: #00a870; }
|
||||
.skill--mahjong { background: rgba(237, 123, 47, 0.1); color: #ed7b2f; }
|
||||
.skill--karaoke { background: rgba(227, 77, 89, 0.1); color: #e34d59; }
|
||||
|
||||
/* ===== 卡片右侧指标(ml-auto 推到右边) ===== */
|
||||
.card-right {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
flex-shrink: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* text-xs=12px→22rpx — "定档"标签文字,普通粗细 */
|
||||
.right-text {
|
||||
font-size: 22rpx;
|
||||
color: #8b8b8b;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* text-sm=14px→24rpx — 数值加粗 */
|
||||
.right-highlight {
|
||||
font-size: 24rpx;
|
||||
font-weight: 700;
|
||||
color: #0052d9;
|
||||
}
|
||||
|
||||
/* "折前"更淡更细 */
|
||||
.right-sub {
|
||||
font-size: 20rpx;
|
||||
color: #c5c5c5;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.right-sub-val {
|
||||
color: #8b8b8b;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* 工资维度 */
|
||||
.salary-tag {
|
||||
padding: 4rpx 10rpx;
|
||||
background: rgba(237, 123, 47, 0.1);
|
||||
color: #ed7b2f;
|
||||
font-size: 22rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
|
||||
/* text-lg=18px→32rpx — 储值维度缩小避免挤压客户列表 */
|
||||
.salary-amount {
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
color: #242424;
|
||||
}
|
||||
|
||||
/* ===== 第二行 mt-1.5=6px→12rpx, text-xs=12px→22rpx ===== */
|
||||
.card-bottom-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
||||
/* gap-2=8px→12rpx */
|
||||
.customer-list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.customer-item {
|
||||
font-size: 22rpx;
|
||||
color: #a6a6a6;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bottom-right {
|
||||
font-size: 22rpx;
|
||||
font-weight: 500;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.bottom-right--warning {
|
||||
color: #ed7b2f;
|
||||
}
|
||||
|
||||
.bottom-right--success {
|
||||
color: #00a870;
|
||||
}
|
||||
|
||||
.bottom-right-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.bottom-perf {
|
||||
font-size: 22rpx;
|
||||
color: #4b4b4b;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.bottom-perf-val {
|
||||
font-weight: 700;
|
||||
color: #4b4b4b;
|
||||
}
|
||||
|
||||
.bottom-sub {
|
||||
font-size: 22rpx;
|
||||
color: #8b8b8b;
|
||||
}
|
||||
|
||||
.bottom-sub-val {
|
||||
color: #8b8b8b;
|
||||
}
|
||||
|
||||
.bottom-divider {
|
||||
font-size: 22rpx;
|
||||
color: #c5c5c5;
|
||||
}
|
||||
|
||||
/* ===== 底部安全区(自定义导航栏高度 100rpx + safe-area) ===== */
|
||||
.safe-bottom {
|
||||
height: 200rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
Reference in New Issue
Block a user