微信小程序页面迁移校验之前 P5任务处理之前
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"navigationBarTitleText": "客户详情",
|
||||
"usingComponents": {
|
||||
"heart-icon": "/components/heart-icon/heart-icon",
|
||||
"star-rating": "/components/star-rating/star-rating",
|
||||
"ai-float-button": "/components/ai-float-button/ai-float-button",
|
||||
"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,161 @@
|
||||
import { mockCustomers, mockCustomerDetail } from '../../utils/mock-data'
|
||||
import type { CustomerDetail, ConsumptionRecord } from '../../utils/mock-data'
|
||||
import { sortByTimestamp } from '../../utils/sort'
|
||||
|
||||
Page({
|
||||
data: {
|
||||
/** 页面状态 */
|
||||
pageState: 'loading' as 'loading' | 'empty' | 'normal',
|
||||
/** 客户 ID */
|
||||
customerId: '',
|
||||
/** 客户详情 */
|
||||
detail: null as CustomerDetail | null,
|
||||
/** 排序后的消费记录 */
|
||||
sortedRecords: [] as ConsumptionRecord[],
|
||||
/** AI 洞察 */
|
||||
aiInsight: {
|
||||
summary: '高价值 VIP 客户,月均到店 4-5 次,偏好夜场中式台球,近期对斯诺克产生兴趣。社交属性强,常带固定球搭子,有拉新能力。储值余额充足,对促销活动响应积极。',
|
||||
strategies: [
|
||||
{ color: 'green', text: '最后到店距今 12 天,超出理想间隔 7 天,建议尽快安排助教主动联系召回' },
|
||||
{ color: 'amber', text: '客户提到想练斯诺克走位,可推荐斯诺克专项课程包,结合储值优惠提升客单价' },
|
||||
{ color: 'pink', text: '社交属性强,可邀请参加门店球友赛事活动,带动球搭子到店消费' },
|
||||
],
|
||||
},
|
||||
/** 维客线索 */
|
||||
clues: [
|
||||
{ category: '客户基础', categoryColor: 'primary', text: '🎂 生日 3月15日 · VIP会员 · 注册2年', source: '系统' },
|
||||
{ category: '消费习惯', categoryColor: 'success', text: '🌙 常来夜场 · 月均4-5次', source: '系统' },
|
||||
{ category: '消费习惯', categoryColor: 'success', text: '💰 高客单价', source: '系统', detail: '近60天场均消费 ¥420,高于门店均值 ¥180;偏好夜场时段,酒水附加消费占比 35%' },
|
||||
{ category: '玩法偏好', categoryColor: 'purple', text: '🎱 偏爱中式 · 斯诺克进阶中', source: '系统' },
|
||||
{ category: '促销接受', categoryColor: 'warning', text: '🍷 爱点酒水套餐 · 对储值活动敏感', source: '系统', detail: '最近3次到店均点了酒水套餐;上次 ¥5000 储值活动当天即充值,对满赠类活动响应率高' },
|
||||
{ category: '社交关系', categoryColor: 'pink', text: '👥 常带朋友 · 固定球搭子2人', source: '系统', detail: '近60天 80% 的到店为多人局,常与「李哥」「阿杰」同行;曾介绍2位新客办卡' },
|
||||
{ category: '重要反馈', categoryColor: 'error', text: '⚠️ 上次提到想练斯诺克走位,对球桌维护质量比较在意,建议优先安排VIP房', source: '小燕' },
|
||||
],
|
||||
/** Banner 统计 */
|
||||
bannerStats: {
|
||||
balance: '¥8,600',
|
||||
spend60d: '¥2,800',
|
||||
idealInterval: '7天',
|
||||
daysSinceVisit: '12天',
|
||||
},
|
||||
/** 助教任务 */
|
||||
coachTasks: [
|
||||
{
|
||||
name: '小燕',
|
||||
level: '高级助教',
|
||||
levelColor: 'pink',
|
||||
taskType: '高优先召回',
|
||||
taskColor: 'red',
|
||||
lastService: '02-20 21:30 · 2.5h',
|
||||
bgClass: 'coach-card-red',
|
||||
metrics: [
|
||||
{ label: '近60天次数', value: '18次', color: 'primary' },
|
||||
{ label: '总时长', value: '17h', color: '' },
|
||||
{ label: '次均时长', value: '0.9h', color: 'warning' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '泡芙',
|
||||
level: '中级助教',
|
||||
levelColor: 'purple',
|
||||
taskType: '关系构建',
|
||||
taskColor: 'pink',
|
||||
lastService: '02-15 14:00 · 1.5h',
|
||||
bgClass: 'coach-card-pink',
|
||||
metrics: [
|
||||
{ label: '近60天次数', value: '12次', color: 'primary' },
|
||||
{ label: '总时长', value: '11h', color: '' },
|
||||
{ label: '次均时长', value: '0.9h', color: 'warning' },
|
||||
],
|
||||
},
|
||||
],
|
||||
/** 最喜欢的助教 */
|
||||
favoriteCoaches: [
|
||||
{
|
||||
name: '小燕',
|
||||
emoji: '❤️',
|
||||
relationIndex: '0.92',
|
||||
indexColor: 'success',
|
||||
bgClass: 'fav-card-pink',
|
||||
stats: [
|
||||
{ label: '基础', value: '12h', color: 'primary' },
|
||||
{ label: '激励', value: '5h', color: 'warning' },
|
||||
{ label: '上课', value: '18次', color: '' },
|
||||
{ label: '充值', value: '¥5,000', color: 'success' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '泡芙',
|
||||
emoji: '💛',
|
||||
relationIndex: '0.78',
|
||||
indexColor: 'warning',
|
||||
bgClass: 'fav-card-amber',
|
||||
stats: [
|
||||
{ label: '基础', value: '8h', color: 'primary' },
|
||||
{ label: '激励', value: '3h', color: 'warning' },
|
||||
{ label: '上课', value: '12次', color: '' },
|
||||
{ label: '充值', value: '¥3,000', color: 'success' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
const id = options?.id || ''
|
||||
this.setData({ customerId: id })
|
||||
this.loadData(id)
|
||||
},
|
||||
|
||||
loadData(id: string) {
|
||||
this.setData({ pageState: 'loading' })
|
||||
|
||||
setTimeout(() => {
|
||||
// TODO: 替换为真实 API 调用
|
||||
// 先从 mockCustomers 查找基本信息,再用 mockCustomerDetail 补充
|
||||
const customer = mockCustomers.find((c) => c.id === id)
|
||||
const detail = customer
|
||||
? { ...mockCustomerDetail, id: customer.id, name: customer.name, heartScore: customer.heartScore, tags: customer.tags }
|
||||
: mockCustomerDetail
|
||||
|
||||
if (!detail) {
|
||||
this.setData({ pageState: 'empty' })
|
||||
return
|
||||
}
|
||||
|
||||
const sorted = sortByTimestamp(detail.consumptionRecords || [], 'date') as ConsumptionRecord[]
|
||||
this.setData({
|
||||
pageState: 'normal',
|
||||
detail,
|
||||
sortedRecords: sorted,
|
||||
})
|
||||
}, 500)
|
||||
},
|
||||
|
||||
/** 发起对话 */
|
||||
onStartChat() {
|
||||
const id = this.data.customerId || this.data.detail?.id || ''
|
||||
wx.navigateTo({
|
||||
url: `/pages/chat/chat?customerId=${id}`,
|
||||
fail: () => wx.showToast({ title: '页面跳转失败', icon: 'none' }),
|
||||
})
|
||||
},
|
||||
|
||||
/** 添加备注 */
|
||||
onAddNote() {
|
||||
wx.showToast({ title: '备注功能开发中', icon: 'none' })
|
||||
},
|
||||
|
||||
/** 查看服务记录 */
|
||||
onViewServiceRecords() {
|
||||
const id = this.data.customerId || this.data.detail?.id || ''
|
||||
wx.navigateTo({
|
||||
url: `/pages/customer-service-records/customer-service-records?customerId=${id}`,
|
||||
fail: () => wx.showToast({ title: '页面跳转失败', icon: 'none' }),
|
||||
})
|
||||
},
|
||||
|
||||
/** 返回 */
|
||||
onBack() {
|
||||
wx.navigateBack()
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,215 @@
|
||||
<!-- 加载态 -->
|
||||
<view class="page-loading" wx:if="{{pageState === 'loading'}}">
|
||||
<t-loading theme="circular" size="80rpx" text="加载中..." />
|
||||
</view>
|
||||
|
||||
<!-- 空态 -->
|
||||
<view class="page-empty" wx:elif="{{pageState === 'empty'}}">
|
||||
<t-icon name="info-circle" size="120rpx" color="#c5c5c5" />
|
||||
<text class="empty-text">未找到客户信息</text>
|
||||
</view>
|
||||
|
||||
<!-- 正常态 -->
|
||||
<block wx:elif="{{pageState === 'normal'}}">
|
||||
<!-- Banner 区域 -->
|
||||
<view class="banner-area">
|
||||
<view class="banner-bg"></view>
|
||||
<view class="banner-overlay">
|
||||
<!-- 导航栏 -->
|
||||
<view class="banner-nav">
|
||||
<view class="nav-back" bindtap="onBack">
|
||||
<t-icon name="chevron-left" size="48rpx" color="#ffffff" />
|
||||
</view>
|
||||
<text class="nav-title">客户详情</text>
|
||||
<view class="nav-placeholder"></view>
|
||||
</view>
|
||||
|
||||
<!-- 客户基本信息 -->
|
||||
<view class="customer-header">
|
||||
<view class="avatar-box">
|
||||
<text class="avatar-text">{{detail.name[0] || '?'}}</text>
|
||||
</view>
|
||||
<view class="info-right">
|
||||
<view class="name-row">
|
||||
<text class="customer-name">{{detail.name}}</text>
|
||||
<t-tag wx:for="{{detail.tags}}" wx:key="*this"
|
||||
variant="light" size="small" theme="warning"
|
||||
class="customer-tag">{{item}}</t-tag>
|
||||
</view>
|
||||
<view class="sub-info">
|
||||
<text class="phone">{{detail.phone}}</text>
|
||||
<text class="member-id">VIP20231215</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Banner 统计指标 -->
|
||||
<view class="banner-stats">
|
||||
<view class="stat-item stat-border">
|
||||
<text class="stat-value stat-green">{{bannerStats.balance}}</text>
|
||||
<text class="stat-label">储值余额</text>
|
||||
</view>
|
||||
<view class="stat-item stat-border">
|
||||
<text class="stat-value">{{bannerStats.spend60d}}</text>
|
||||
<text class="stat-label">60天消费</text>
|
||||
</view>
|
||||
<view class="stat-item stat-border">
|
||||
<text class="stat-value">{{bannerStats.idealInterval}}</text>
|
||||
<text class="stat-label">理想间隔</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-value stat-amber">{{bannerStats.daysSinceVisit}}</text>
|
||||
<text class="stat-label">距今到店</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 主体内容 -->
|
||||
<view class="main-content">
|
||||
<!-- AI 智能洞察 -->
|
||||
<view class="ai-insight-card">
|
||||
<view class="ai-insight-header">
|
||||
<text class="ai-icon-emoji">🤖</text>
|
||||
<text class="ai-insight-label">AI 智能洞察</text>
|
||||
</view>
|
||||
<text class="ai-insight-summary">{{aiInsight.summary}}</text>
|
||||
<view class="ai-strategy-box">
|
||||
<text class="strategy-title">📋 当前推荐策略</text>
|
||||
<view class="strategy-list">
|
||||
<view class="strategy-item" wx:for="{{aiInsight.strategies}}" wx:key="index">
|
||||
<view class="strategy-dot dot-{{item.color}}"></view>
|
||||
<text class="strategy-text">{{item.text}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 维客线索 -->
|
||||
<view class="card">
|
||||
<view class="card-header">
|
||||
<text class="section-title title-green">维客线索</text>
|
||||
<view class="ai-badge-box">
|
||||
<text class="ai-badge-emoji">🤖</text>
|
||||
<text class="ai-badge-text">AI智能洞察</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="clue-list">
|
||||
<view class="clue-item {{item.detail ? 'clue-with-detail' : ''}}" wx:for="{{clues}}" wx:key="index">
|
||||
<view class="clue-main">
|
||||
<view class="clue-category clue-cat-{{item.categoryColor}}">
|
||||
<text>{{item.category}}</text>
|
||||
</view>
|
||||
<view class="clue-content">
|
||||
<text class="clue-text">{{item.text}}</text>
|
||||
<text class="clue-source">By:{{item.source}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="clue-detail" wx:if="{{item.detail}}">{{item.detail}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 助教任务 -->
|
||||
<view class="card">
|
||||
<view class="card-header">
|
||||
<text class="section-title title-blue">助教任务</text>
|
||||
<text class="header-hint">当前进行中</text>
|
||||
</view>
|
||||
<view class="coach-task-list">
|
||||
<view class="coach-task-card {{item.bgClass}}" wx:for="{{coachTasks}}" wx:key="index">
|
||||
<view class="coach-task-top">
|
||||
<view class="coach-name-row">
|
||||
<text class="coach-name">{{item.name}}</text>
|
||||
<text class="coach-level level-{{item.levelColor}}">{{item.level}}</text>
|
||||
</view>
|
||||
<text class="coach-task-type type-{{item.taskColor}}">{{item.taskType}}</text>
|
||||
</view>
|
||||
<text class="coach-last-service">上次服务:{{item.lastService}}</text>
|
||||
<view class="coach-metrics">
|
||||
<view class="coach-metric" wx:for="{{item.metrics}}" wx:for-item="m" wx:key="label">
|
||||
<text class="metric-label">{{m.label}}</text>
|
||||
<text class="metric-value {{m.color ? 'text-' + m.color : ''}}">{{m.value}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 最喜欢的助教 -->
|
||||
<view class="card">
|
||||
<view class="card-header">
|
||||
<text class="section-title title-pink">最喜欢的助教</text>
|
||||
<text class="header-hint">近60天</text>
|
||||
</view>
|
||||
<view class="fav-coach-list">
|
||||
<view class="fav-coach-card {{item.bgClass}}" wx:for="{{favoriteCoaches}}" wx:key="index">
|
||||
<view class="fav-coach-top">
|
||||
<view class="fav-coach-name">
|
||||
<text class="fav-emoji">{{item.emoji}}</text>
|
||||
<text class="fav-name">{{item.name}}</text>
|
||||
</view>
|
||||
<view class="fav-index">
|
||||
<text class="fav-index-label">关系指数</text>
|
||||
<text class="fav-index-value text-{{item.indexColor}}">{{item.relationIndex}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="fav-period">近60天</text>
|
||||
<view class="fav-stats">
|
||||
<view class="fav-stat" wx:for="{{item.stats}}" wx:for-item="s" wx:key="label">
|
||||
<text class="fav-stat-label">{{s.label}}</text>
|
||||
<text class="fav-stat-value {{s.color ? 'text-' + s.color : ''}}">{{s.value}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 消费记录 -->
|
||||
<view class="card">
|
||||
<view class="card-header" bindtap="onViewServiceRecords">
|
||||
<text class="section-title title-orange">消费记录</text>
|
||||
<t-icon name="chevron-right" size="40rpx" color="#a6a6a6" />
|
||||
</view>
|
||||
<view class="record-list" wx:if="{{sortedRecords.length > 0}}">
|
||||
<view class="record-item" wx:for="{{sortedRecords}}" wx:key="id">
|
||||
<view class="record-header">
|
||||
<view class="record-project">
|
||||
<view class="record-dot"></view>
|
||||
<text class="record-project-name">{{item.project}}</text>
|
||||
</view>
|
||||
<text class="record-date">{{item.date}}</text>
|
||||
</view>
|
||||
<view class="record-body">
|
||||
<view class="record-info">
|
||||
<text class="record-coach" wx:if="{{item.coachName !== '-'}}">助教:{{item.coachName}}</text>
|
||||
<text class="record-duration" wx:if="{{item.duration > 0}}">{{item.duration}}分钟</text>
|
||||
</view>
|
||||
<text class="record-amount">¥{{item.amount}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="record-empty" wx:else>
|
||||
<t-icon name="info-circle" size="80rpx" color="#dcdcdc" />
|
||||
<text class="empty-hint">暂无消费记录</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部操作栏 -->
|
||||
<view class="bottom-bar safe-area-bottom">
|
||||
<view class="btn-chat" bindtap="onStartChat">
|
||||
<t-icon name="chat" size="40rpx" color="#ffffff" />
|
||||
<text>问问助手</text>
|
||||
</view>
|
||||
<view class="btn-note" bindtap="onAddNote">
|
||||
<t-icon name="edit-1" size="40rpx" color="#242424" />
|
||||
<text>备注</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- AI 悬浮按钮 -->
|
||||
<ai-float-button bottom="{{200}}" customerId="{{detail.id}}" />
|
||||
</block>
|
||||
|
||||
<dev-fab />
|
||||
@@ -0,0 +1,680 @@
|
||||
/* 加载态 & 空态 */
|
||||
.page-loading,
|
||||
.page-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 60vh;
|
||||
gap: 24rpx;
|
||||
}
|
||||
.empty-text {
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
color: var(--color-gray-6, #a6a6a6);
|
||||
}
|
||||
|
||||
/* ========== Banner ========== */
|
||||
.banner-area {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.banner-bg {
|
||||
width: 100%;
|
||||
height: 480rpx;
|
||||
background: linear-gradient(135deg, #1a1a2e, #c9a84c);
|
||||
display: block;
|
||||
}
|
||||
.banner-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.banner-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 88rpx;
|
||||
padding: 0 32rpx;
|
||||
}
|
||||
.nav-back {
|
||||
padding: 8rpx;
|
||||
}
|
||||
.nav-title {
|
||||
font-size: var(--font-base, 32rpx);
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
}
|
||||
.nav-placeholder {
|
||||
width: 64rpx;
|
||||
}
|
||||
|
||||
/* 客户头部信息 */
|
||||
.customer-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 32rpx;
|
||||
padding: 16rpx 40rpx 24rpx;
|
||||
}
|
||||
.avatar-box {
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
border-radius: 32rpx;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
backdrop-filter: blur(8px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.avatar-text {
|
||||
font-size: 48rpx;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
}
|
||||
.info-right {
|
||||
flex: 1;
|
||||
}
|
||||
.name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
margin-bottom: 16rpx;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.customer-name {
|
||||
font-size: var(--font-xl, 40rpx);
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
}
|
||||
.customer-tag {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.sub-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 32rpx;
|
||||
}
|
||||
.phone,
|
||||
.member-id {
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
/* Banner 统计 */
|
||||
.banner-stats {
|
||||
margin: 0 40rpx;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: var(--radius-lg, 24rpx);
|
||||
backdrop-filter: blur(8px);
|
||||
display: flex;
|
||||
}
|
||||
.stat-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 24rpx 0;
|
||||
}
|
||||
.stat-border {
|
||||
border-right: 1rpx solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.stat-value {
|
||||
display: block;
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
}
|
||||
.stat-green {
|
||||
color: #6ee7b7;
|
||||
}
|
||||
.stat-amber {
|
||||
color: #fcd34d;
|
||||
}
|
||||
.stat-label {
|
||||
display: block;
|
||||
font-size: var(--font-xs, 24rpx);
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
/* ========== 主体内容 ========== */
|
||||
.main-content {
|
||||
padding: 32rpx;
|
||||
padding-bottom: 200rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 32rpx;
|
||||
}
|
||||
|
||||
/* ========== AI 智能洞察卡片 ========== */
|
||||
.ai-insight-card {
|
||||
border-radius: var(--radius-xl, 32rpx);
|
||||
overflow: hidden;
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
padding: 40rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
.ai-insight-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
.ai-icon-small {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: var(--radius-md, 16rpx);
|
||||
padding: 8rpx;
|
||||
}
|
||||
.ai-icon-emoji {
|
||||
font-size: 40rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
.ai-insight-label {
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
font-weight: 500;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
.ai-insight-summary {
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
line-height: 1.7;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
.ai-strategy-box {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: var(--radius-lg, 24rpx);
|
||||
padding: 24rpx;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
.strategy-title {
|
||||
font-size: var(--font-xs, 24rpx);
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
margin-bottom: 16rpx;
|
||||
display: block;
|
||||
}
|
||||
.strategy-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12rpx;
|
||||
}
|
||||
.strategy-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 16rpx;
|
||||
}
|
||||
.strategy-dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 50%;
|
||||
margin-top: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.dot-green {
|
||||
background: #6ee7b7;
|
||||
}
|
||||
.dot-amber {
|
||||
background: #fcd34d;
|
||||
}
|
||||
.dot-pink {
|
||||
background: #f9a8d4;
|
||||
}
|
||||
.strategy-text {
|
||||
font-size: var(--font-xs, 24rpx);
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* ========== 通用卡片 ========== */
|
||||
.card {
|
||||
background: #ffffff;
|
||||
border-radius: var(--radius-xl, 32rpx);
|
||||
padding: 40rpx;
|
||||
box-shadow: var(--shadow-lg, 0 8rpx 32rpx rgba(0, 0, 0, 0.06));
|
||||
}
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
.section-title {
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
font-weight: 600;
|
||||
color: var(--color-gray-13, #242424);
|
||||
position: relative;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
.section-title::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 6rpx;
|
||||
height: 28rpx;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
.title-green::before {
|
||||
background: linear-gradient(180deg, #00a870, #4cd964);
|
||||
}
|
||||
.title-blue::before {
|
||||
background: linear-gradient(180deg, #0052d9, #5b9cf8);
|
||||
}
|
||||
.title-orange::before {
|
||||
background: linear-gradient(180deg, #ed7b2f, #ffc107);
|
||||
}
|
||||
.title-pink::before {
|
||||
background: linear-gradient(180deg, #e851a4, #f5a0c0);
|
||||
}
|
||||
.header-hint {
|
||||
font-size: var(--font-xs, 24rpx);
|
||||
color: var(--color-gray-6, #a6a6a6);
|
||||
}
|
||||
|
||||
/* AI 徽章 */
|
||||
.ai-badge-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
background: var(--color-primary-light, #ecf2fe);
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 100rpx;
|
||||
}
|
||||
.ai-badge-emoji {
|
||||
font-size: 24rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
.ai-badge-text {
|
||||
font-size: 22rpx;
|
||||
color: var(--color-primary, #0052d9);
|
||||
}
|
||||
|
||||
/* ========== 维客线索 ========== */
|
||||
.clue-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
}
|
||||
.clue-item {
|
||||
background: #fafafa;
|
||||
border-radius: var(--radius-lg, 24rpx);
|
||||
border: 1rpx solid var(--color-gray-3, #e7e7e7);
|
||||
padding: 24rpx;
|
||||
}
|
||||
.clue-main {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 24rpx;
|
||||
}
|
||||
.clue-category {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8rpx;
|
||||
font-size: 22rpx;
|
||||
font-weight: 500;
|
||||
flex-shrink: 0;
|
||||
line-height: 1.3;
|
||||
text-align: center;
|
||||
}
|
||||
.clue-cat-primary {
|
||||
background: rgba(0, 82, 217, 0.1);
|
||||
color: var(--color-primary, #0052d9);
|
||||
}
|
||||
.clue-cat-success {
|
||||
background: rgba(0, 168, 112, 0.1);
|
||||
color: var(--color-success, #00a870);
|
||||
}
|
||||
.clue-cat-purple {
|
||||
background: rgba(124, 58, 237, 0.1);
|
||||
color: #7c3aed;
|
||||
}
|
||||
.clue-cat-warning {
|
||||
background: rgba(237, 123, 47, 0.1);
|
||||
color: var(--color-warning, #ed7b2f);
|
||||
}
|
||||
.clue-cat-pink {
|
||||
background: rgba(236, 72, 153, 0.1);
|
||||
color: #ec4899;
|
||||
}
|
||||
.clue-cat-error {
|
||||
background: rgba(227, 77, 89, 0.1);
|
||||
color: var(--color-error, #e34d59);
|
||||
}
|
||||
.clue-content {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
min-height: 80rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.clue-text {
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
color: var(--color-gray-13, #242424);
|
||||
line-height: 1.5;
|
||||
}
|
||||
.clue-source {
|
||||
font-size: 22rpx;
|
||||
color: var(--color-gray-6, #a6a6a6);
|
||||
align-self: flex-end;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
.clue-detail {
|
||||
font-size: var(--font-xs, 24rpx);
|
||||
color: var(--color-gray-7, #8b8b8b);
|
||||
line-height: 1.6;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
/* ========== 助教任务 ========== */
|
||||
.coach-task-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
.coach-task-card {
|
||||
border-radius: var(--radius-lg, 24rpx);
|
||||
padding: 24rpx;
|
||||
}
|
||||
.coach-card-red {
|
||||
background: linear-gradient(135deg, rgba(254, 226, 226, 0.8), rgba(255, 228, 230, 0.6));
|
||||
border: 1rpx solid rgba(252, 165, 165, 0.6);
|
||||
}
|
||||
.coach-card-pink {
|
||||
background: linear-gradient(135deg, rgba(252, 231, 243, 0.8), rgba(250, 232, 255, 0.6));
|
||||
border: 1rpx solid rgba(249, 168, 212, 0.6);
|
||||
}
|
||||
.coach-task-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.coach-name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
.coach-name {
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
font-weight: 600;
|
||||
color: var(--color-gray-13, #242424);
|
||||
}
|
||||
.coach-level {
|
||||
font-size: 22rpx;
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 100rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
.level-pink {
|
||||
background: #fce7f3;
|
||||
color: #be185d;
|
||||
}
|
||||
.level-purple {
|
||||
background: #f3e8ff;
|
||||
color: #7c3aed;
|
||||
}
|
||||
.coach-task-type {
|
||||
font-size: 22rpx;
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 100rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
.type-red {
|
||||
background: #fee2e2;
|
||||
color: #b91c1c;
|
||||
}
|
||||
.type-pink {
|
||||
background: #fce7f3;
|
||||
color: #be185d;
|
||||
}
|
||||
.coach-last-service {
|
||||
font-size: var(--font-xs, 24rpx);
|
||||
color: var(--color-gray-7, #8b8b8b);
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.coach-metrics {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
.coach-metric {
|
||||
flex: 1;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border-radius: var(--radius-md, 16rpx);
|
||||
padding: 12rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
.metric-label {
|
||||
display: block;
|
||||
font-size: 20rpx;
|
||||
color: var(--color-gray-6, #a6a6a6);
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
.metric-value {
|
||||
display: block;
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
font-weight: 700;
|
||||
color: var(--color-gray-13, #242424);
|
||||
}
|
||||
|
||||
/* ========== 最喜欢的助教 ========== */
|
||||
.fav-coach-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
.fav-coach-card {
|
||||
border-radius: var(--radius-lg, 24rpx);
|
||||
padding: 32rpx;
|
||||
}
|
||||
.fav-card-pink {
|
||||
background: linear-gradient(135deg, rgba(252, 231, 243, 0.8), rgba(255, 228, 230, 0.6));
|
||||
border: 1rpx solid rgba(249, 168, 212, 0.6);
|
||||
}
|
||||
.fav-card-amber {
|
||||
background: linear-gradient(135deg, rgba(254, 243, 199, 0.8), rgba(254, 249, 195, 0.6));
|
||||
border: 1rpx solid rgba(252, 211, 77, 0.6);
|
||||
}
|
||||
.fav-coach-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.fav-coach-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
}
|
||||
.fav-emoji {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
.fav-name {
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
font-weight: 600;
|
||||
color: var(--color-gray-13, #242424);
|
||||
}
|
||||
.fav-index {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
.fav-index-label {
|
||||
font-size: var(--font-xs, 24rpx);
|
||||
color: var(--color-gray-7, #8b8b8b);
|
||||
}
|
||||
.fav-index-value {
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
.fav-period {
|
||||
font-size: var(--font-xs, 24rpx);
|
||||
color: var(--color-gray-7, #8b8b8b);
|
||||
margin-bottom: 12rpx;
|
||||
padding-left: 4rpx;
|
||||
}
|
||||
.fav-stats {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
.fav-stat {
|
||||
flex: 1;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border-radius: var(--radius-md, 16rpx);
|
||||
padding: 16rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
.fav-stat-label {
|
||||
display: block;
|
||||
font-size: var(--font-xs, 24rpx);
|
||||
color: var(--color-gray-7, #8b8b8b);
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
.fav-stat-value {
|
||||
display: block;
|
||||
font-size: var(--font-base, 32rpx);
|
||||
font-weight: 700;
|
||||
color: var(--color-gray-13, #242424);
|
||||
}
|
||||
|
||||
/* ========== 消费记录 ========== */
|
||||
.record-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
.record-item {
|
||||
background: #fafafa;
|
||||
border-radius: var(--radius-lg, 24rpx);
|
||||
border: 1rpx solid var(--color-gray-3, #e7e7e7);
|
||||
overflow: hidden;
|
||||
}
|
||||
.record-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 24rpx;
|
||||
background: linear-gradient(90deg, #eff6ff, #eef2ff);
|
||||
border-bottom: 1rpx solid rgba(219, 234, 254, 0.5);
|
||||
}
|
||||
.record-project {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
.record-dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 50%;
|
||||
background: var(--color-primary, #0052d9);
|
||||
}
|
||||
.record-project-name {
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
font-weight: 600;
|
||||
color: var(--color-primary, #0052d9);
|
||||
}
|
||||
.record-date {
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
color: var(--color-gray-8, #777777);
|
||||
}
|
||||
.record-body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 24rpx;
|
||||
}
|
||||
.record-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24rpx;
|
||||
}
|
||||
.record-coach {
|
||||
font-size: var(--font-xs, 24rpx);
|
||||
color: var(--color-gray-8, #777777);
|
||||
}
|
||||
.record-duration {
|
||||
font-size: var(--font-xs, 24rpx);
|
||||
color: var(--color-gray-6, #a6a6a6);
|
||||
}
|
||||
.record-amount {
|
||||
font-size: var(--font-base, 32rpx);
|
||||
font-weight: 700;
|
||||
color: var(--color-gray-13, #242424);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.record-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 48rpx 0;
|
||||
gap: 16rpx;
|
||||
}
|
||||
.empty-hint {
|
||||
font-size: var(--font-sm, 28rpx);
|
||||
color: var(--color-gray-5, #c5c5c5);
|
||||
}
|
||||
|
||||
/* ========== 底部操作栏 ========== */
|
||||
.bottom-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 128rpx;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(20px);
|
||||
border-top: 1rpx solid var(--color-gray-2, #eeeeee);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24rpx;
|
||||
padding: 0 32rpx;
|
||||
z-index: 100;
|
||||
}
|
||||
.btn-chat {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
background: linear-gradient(135deg, #0052d9, #3b82f6);
|
||||
color: #ffffff;
|
||||
font-weight: 500;
|
||||
border-radius: var(--radius-lg, 24rpx);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
font-size: var(--font-base, 32rpx);
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 82, 217, 0.3);
|
||||
}
|
||||
.btn-note {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
background: var(--color-gray-1, #f3f3f3);
|
||||
color: var(--color-gray-13, #242424);
|
||||
font-weight: 500;
|
||||
border-radius: var(--radius-lg, 24rpx);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
font-size: var(--font-base, 32rpx);
|
||||
}
|
||||
|
||||
/* ========== 颜色工具类 ========== */
|
||||
.text-primary {
|
||||
color: var(--color-primary, #0052d9) !important;
|
||||
}
|
||||
.text-success {
|
||||
color: var(--color-success, #00a870) !important;
|
||||
}
|
||||
.text-warning {
|
||||
color: var(--color-warning, #ed7b2f) !important;
|
||||
}
|
||||
.text-error {
|
||||
color: var(--color-error, #e34d59) !important;
|
||||
}
|
||||
Reference in New Issue
Block a user