1
This commit is contained in:
@@ -1,17 +1,109 @@
|
||||
import { mockCustomers, mockCustomerDetail } from '../../utils/mock-data'
|
||||
import type { CustomerDetail, ConsumptionRecord } from '../../utils/mock-data'
|
||||
import { sortByTimestamp } from '../../utils/sort'
|
||||
import type { CustomerDetail } from '../../utils/mock-data'
|
||||
|
||||
/** 消费记录(三种样式) */
|
||||
interface ConsumptionRecordV2 {
|
||||
id: string
|
||||
type: 'table' | 'shop' | 'recharge'
|
||||
date: string
|
||||
// 台桌结账
|
||||
tableName?: string
|
||||
startTime?: string
|
||||
endTime?: string
|
||||
duration?: string
|
||||
tableFee?: number
|
||||
tableOrigPrice?: number
|
||||
// 助教
|
||||
coaches?: {
|
||||
name: string
|
||||
level: string
|
||||
levelColor: string
|
||||
courseType: string
|
||||
hours: string
|
||||
perfHours?: string
|
||||
fee: number
|
||||
}[]
|
||||
// 食品酒水
|
||||
foodAmount?: number
|
||||
foodOrigPrice?: number
|
||||
// 总金额
|
||||
totalAmount?: number
|
||||
totalOrigPrice?: number
|
||||
// 充值
|
||||
payMethod?: string
|
||||
rechargeAmount?: number
|
||||
}
|
||||
|
||||
/** mock 消费记录(三种样式) */
|
||||
const mockConsumptionRecords: ConsumptionRecordV2[] = [
|
||||
{
|
||||
id: 'r1',
|
||||
type: 'table',
|
||||
date: '2026-02-05',
|
||||
tableName: 'A12号台',
|
||||
startTime: '21:30',
|
||||
endTime: '00:50',
|
||||
duration: '3h20min',
|
||||
tableFee: 180,
|
||||
tableOrigPrice: 240,
|
||||
coaches: [
|
||||
{ name: '小燕', level: '高级', levelColor: 'pink', courseType: '基础课', hours: '2.5h', fee: 200 },
|
||||
{ name: 'Lucy', level: '初级', levelColor: 'green', courseType: '激励课', hours: '0.5h', perfHours: '1h', fee: 50 },
|
||||
],
|
||||
foodAmount: 210,
|
||||
foodOrigPrice: 260,
|
||||
totalAmount: 640,
|
||||
totalOrigPrice: 750,
|
||||
},
|
||||
{
|
||||
id: 'r2',
|
||||
type: 'table',
|
||||
date: '2026-02-01',
|
||||
tableName: '888号台',
|
||||
startTime: '14:00',
|
||||
endTime: '16:00',
|
||||
duration: '2h00min',
|
||||
tableFee: 120,
|
||||
coaches: [
|
||||
{ name: '泡芙', level: '中级', levelColor: 'purple', courseType: '激励课', hours: '1.5h', perfHours: '2h', fee: 100 },
|
||||
],
|
||||
totalAmount: 220,
|
||||
},
|
||||
{
|
||||
id: 'r3',
|
||||
type: 'shop',
|
||||
date: '2026-01-28',
|
||||
coaches: [
|
||||
{ name: '小燕', level: '高级', levelColor: 'pink', courseType: '基础课', hours: '1h', fee: 100 },
|
||||
],
|
||||
foodAmount: 180,
|
||||
totalAmount: 280,
|
||||
},
|
||||
{
|
||||
id: 'r4',
|
||||
type: 'recharge',
|
||||
date: '2026-01-20',
|
||||
payMethod: '微信支付',
|
||||
rechargeAmount: 5000,
|
||||
},
|
||||
]
|
||||
|
||||
Page({
|
||||
data: {
|
||||
/** 页面状态 */
|
||||
pageState: 'loading' as 'loading' | 'empty' | 'normal',
|
||||
pageState: 'loading' as 'loading' | 'empty' | 'error' | 'normal',
|
||||
/** 客户 ID */
|
||||
customerId: '',
|
||||
/** 客户详情 */
|
||||
detail: null as CustomerDetail | null,
|
||||
/** 排序后的消费记录 */
|
||||
sortedRecords: [] as ConsumptionRecord[],
|
||||
/** 消费记录(三种样式) */
|
||||
consumptionRecords: [] as ConsumptionRecordV2[],
|
||||
/** 是否正在加载更多 */
|
||||
loadingMore: false,
|
||||
/** 是否还有更多记录 */
|
||||
hasMoreRecords: true,
|
||||
/** 备注弹窗 */
|
||||
noteModalVisible: false,
|
||||
/** AI 洞察 */
|
||||
aiInsight: {
|
||||
summary: '高价值 VIP 客户,月均到店 4-5 次,偏好夜场中式台球,近期对斯诺克产生兴趣。社交属性强,常带固定球搭子,有拉新能力。储值余额充足,对促销活动响应积极。',
|
||||
@@ -23,13 +115,13 @@ Page({
|
||||
},
|
||||
/** 维客线索 */
|
||||
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: '小燕' },
|
||||
{ category: '客户\n基础', categoryColor: 'primary', text: '🎂 生日 3月15日 · VIP会员 · 注册2年', source: '系统' },
|
||||
{ category: '消费\n习惯', categoryColor: 'success', text: '🌙 常来夜场 · 月均4-5次', source: '系统' },
|
||||
{ category: '消费\n习惯', categoryColor: 'success', text: '💰 高客单价', source: '系统', detail: '近60天场均消费 ¥420,高于门店均值 ¥180;偏好夜场时段,酒水附加消费占比 35%' },
|
||||
{ category: '玩法\n偏好', categoryColor: 'purple', text: '🎱 偏爱中式 · 斯诺克进阶中', source: '系统' },
|
||||
{ category: '促销\n接受', categoryColor: 'warning', text: '🍷 爱点酒水套餐 · 对储值活动敏感', source: '系统', detail: '最近3次到店均点了酒水套餐;上次 ¥5000 储值活动当天即充值,对满赠类活动响应率高' },
|
||||
{ category: '社交\n关系', categoryColor: 'pink', text: '👥 常带朋友 · 固定球搭子2人', source: '系统', detail: '近60天 80% 的到店为多人局,常与「李哥」「阿杰」同行;曾介绍2位新客办卡' },
|
||||
{ category: '重要\n反馈', categoryColor: 'error', text: '⚠️ 上次提到想练斯诺克走位,对球桌维护质量比较在意,建议优先安排VIP房', source: '小燕' },
|
||||
],
|
||||
/** Banner 统计 */
|
||||
bannerStats: {
|
||||
@@ -110,24 +202,42 @@ Page({
|
||||
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
|
||||
try {
|
||||
// TODO: 替换为真实 API 调用
|
||||
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
|
||||
if (!detail) {
|
||||
this.setData({ pageState: 'empty' })
|
||||
return
|
||||
}
|
||||
|
||||
this.setData({
|
||||
pageState: 'normal',
|
||||
detail,
|
||||
consumptionRecords: mockConsumptionRecords,
|
||||
hasMoreRecords: false,
|
||||
})
|
||||
} catch {
|
||||
this.setData({ pageState: 'error' })
|
||||
}
|
||||
}, 500)
|
||||
},
|
||||
|
||||
const sorted = sortByTimestamp(detail.consumptionRecords || [], 'date') as ConsumptionRecord[]
|
||||
this.setData({
|
||||
pageState: 'normal',
|
||||
detail,
|
||||
sortedRecords: sorted,
|
||||
})
|
||||
/** 重试 */
|
||||
onRetry() {
|
||||
this.loadData(this.data.customerId)
|
||||
},
|
||||
|
||||
/** 触底加载更多消费记录 */
|
||||
onReachBottom() {
|
||||
if (this.data.loadingMore || !this.data.hasMoreRecords) return
|
||||
this.setData({ loadingMore: true })
|
||||
// TODO: 真实 API 分页加载
|
||||
setTimeout(() => {
|
||||
this.setData({ loadingMore: false, hasMoreRecords: false })
|
||||
}, 500)
|
||||
},
|
||||
|
||||
@@ -142,7 +252,21 @@ Page({
|
||||
|
||||
/** 添加备注 */
|
||||
onAddNote() {
|
||||
wx.showToast({ title: '备注功能开发中', icon: 'none' })
|
||||
this.setData({ noteModalVisible: true })
|
||||
},
|
||||
|
||||
/** 备注确认 */
|
||||
onNoteConfirm(e: WechatMiniprogram.CustomEvent) {
|
||||
this.setData({ noteModalVisible: false })
|
||||
const { content } = e.detail || {}
|
||||
if (content) {
|
||||
wx.showToast({ title: '备注已保存', icon: 'success' })
|
||||
}
|
||||
},
|
||||
|
||||
/** 备注取消 */
|
||||
onNoteCancel() {
|
||||
this.setData({ noteModalVisible: false })
|
||||
},
|
||||
|
||||
/** 查看服务记录 */
|
||||
|
||||
Reference in New Issue
Block a user