346 lines
13 KiB
TypeScript
346 lines
13 KiB
TypeScript
// 财务看板页 — 忠于 H5 原型结构,内联 mock 数据
|
||
// TODO: 联调时替换 mock 数据为真实 API 调用
|
||
|
||
/** 目录板块定义 */
|
||
interface TocItem {
|
||
emoji: string
|
||
title: string
|
||
sectionId: string
|
||
}
|
||
|
||
/** 指标解释映射 */
|
||
const tipContents: Record<string, { title: string; content: string }> = {
|
||
occurrence: {
|
||
title: '发生额/正价',
|
||
content: '所有消费项目按标价计算的总金额,不扣除任何优惠。\n\n即"如果没有任何折扣,客户应付多少"。',
|
||
},
|
||
discount: {
|
||
title: '总优惠',
|
||
content: '包含会员折扣、赠送卡抵扣、团购差价等所有优惠金额。\n\n优惠越高,实际收入越低。',
|
||
},
|
||
confirmed: {
|
||
title: '成交/确认收入',
|
||
content: '发生额减去总优惠后的实际入账金额。\n\n成交收入 = 发生额 - 总优惠',
|
||
},
|
||
cashIn: {
|
||
title: '实收/现金流入',
|
||
content: '实际到账的现金,包含消费直接支付和储值充值。\n\n往期为已结算金额,本期为截至当前的发生额。',
|
||
},
|
||
cashOut: {
|
||
title: '现金支出',
|
||
content: '包含人工、房租、水电、进货等所有经营支出。',
|
||
},
|
||
balance: {
|
||
title: '现金结余',
|
||
content: '现金流入减去现金支出。\n\n现金结余 = 现金流入 - 现金支出',
|
||
},
|
||
rechargeActual: {
|
||
title: '储值卡充值实收',
|
||
content: '会员储值卡首充和续费的实际到账金额。\n\n不含赠送金额。',
|
||
},
|
||
firstCharge: {
|
||
title: '首充',
|
||
content: '新会员首次充值的金额。',
|
||
},
|
||
renewCharge: {
|
||
title: '续费',
|
||
content: '老会员续费充值的金额。',
|
||
},
|
||
consume: {
|
||
title: '消耗',
|
||
content: '会员使用储值卡消费的金额。',
|
||
},
|
||
cardBalance: {
|
||
title: '储值卡总余额',
|
||
content: '所有储值卡的剩余可用余额。',
|
||
},
|
||
allCardBalance: {
|
||
title: '全类别会员卡余额合计',
|
||
content: '储值卡 + 赠送卡(酒水卡、台费卡、抵用券)的总余额。\n\n仅供经营参考,非财务属性。',
|
||
},
|
||
}
|
||
|
||
Page({
|
||
data: {
|
||
pageState: 'normal' as 'loading' | 'empty' | 'normal',
|
||
|
||
/** 时间筛选 */
|
||
selectedTime: 'month',
|
||
timeOptions: [
|
||
{ value: 'month', text: '本月' },
|
||
{ value: 'lastMonth', text: '上月' },
|
||
{ value: 'week', text: '本周' },
|
||
{ value: 'lastWeek', text: '上周' },
|
||
{ value: 'quarter3', text: '前3个月 不含本月' },
|
||
{ value: 'quarter', text: '本季度' },
|
||
{ value: 'lastQuarter', text: '上季度' },
|
||
{ value: 'half6', text: '最近6个月不含本月' },
|
||
],
|
||
|
||
/** 区域筛选 */
|
||
selectedArea: 'all',
|
||
areaOptions: [
|
||
{ value: 'all', text: '全部区域' },
|
||
{ value: 'hall', text: '大厅' },
|
||
{ value: 'hallA', text: 'A区' },
|
||
{ value: 'hallB', text: 'B区' },
|
||
{ value: 'hallC', text: 'C区' },
|
||
{ value: 'mahjong', text: '麻将房' },
|
||
{ value: 'teamBuilding', text: '团建房' },
|
||
],
|
||
|
||
/** 环比开关 */
|
||
compareEnabled: false,
|
||
|
||
/** 目录导航 */
|
||
tocVisible: false,
|
||
tocItems: [
|
||
{ emoji: '📈', title: '经营一览', sectionId: 'section-overview' },
|
||
{ emoji: '💳', title: '预收资产', sectionId: 'section-recharge' },
|
||
{ emoji: '💰', title: '应计收入确认', sectionId: 'section-revenue' },
|
||
{ emoji: '🧾', title: '现金流入', sectionId: 'section-cashflow' },
|
||
{ emoji: '📤', title: '现金流出', sectionId: 'section-expense' },
|
||
{ emoji: '🎱', title: '助教分析', sectionId: 'section-coach' },
|
||
] as TocItem[],
|
||
currentSectionIndex: 0,
|
||
scrollIntoView: '',
|
||
|
||
/** 提示弹窗 */
|
||
tipVisible: false,
|
||
tipTitle: '',
|
||
tipContent: '',
|
||
|
||
/** 经营一览 */
|
||
overview: {
|
||
occurrence: '¥823,456',
|
||
occurrenceCompare: '12.5%',
|
||
discount: '-¥113,336',
|
||
discountCompare: '3.2%',
|
||
discountRate: '13.8%',
|
||
discountRateCompare: '1.5%',
|
||
confirmedRevenue: '¥710,120',
|
||
confirmedCompare: '8.7%',
|
||
cashIn: '¥698,500',
|
||
cashInCompare: '5.3%',
|
||
cashOut: '¥472,300',
|
||
cashOutCompare: '2.1%',
|
||
cashBalance: '¥226,200',
|
||
cashBalanceCompare: '15.2%',
|
||
balanceRate: '32.4%',
|
||
balanceRateCompare: '3.8%',
|
||
},
|
||
|
||
/** 预收资产 */
|
||
recharge: {
|
||
actualIncome: '¥352,800',
|
||
actualCompare: '18.5%',
|
||
firstCharge: '¥188,500',
|
||
firstChargeCompare: '12.3%',
|
||
renewCharge: '¥164,300',
|
||
renewChargeCompare: '8.7%',
|
||
consumed: '¥238,200',
|
||
consumedCompare: '5.2%',
|
||
cardBalance: '¥642,600',
|
||
cardBalanceCompare: '11.4%',
|
||
giftRows: [
|
||
{
|
||
label: '新增', total: '¥108,600', totalCompare: '9.8%',
|
||
wine: '¥43,200', wineCompare: '11.2%',
|
||
table: '¥54,100', tableCompare: '8.5%',
|
||
coupon: '¥11,300', couponCompare: '6.3%',
|
||
},
|
||
{
|
||
label: '消费', total: '¥75,800', totalCompare: '7.2%',
|
||
wine: '¥32,100', wineCompare: '8.1%',
|
||
table: '¥32,800', tableCompare: '6.5%',
|
||
coupon: '¥10,900', couponCompare: '5.8%',
|
||
},
|
||
{
|
||
label: '余额', total: '¥243,900', totalCompare: '4.5%',
|
||
wine: '¥118,500', wineCompare: '5.2%',
|
||
table: '¥109,200', tableCompare: '3.8%',
|
||
coupon: '¥16,200', couponCompare: '2.5%',
|
||
},
|
||
],
|
||
allCardBalance: '¥586,500',
|
||
allCardBalanceCompare: '6.2%',
|
||
},
|
||
|
||
/** 应计收入确认 */
|
||
revenue: {
|
||
structureRows: [
|
||
{ name: '开台与包厢', amount: '¥358,600', discount: '-¥45,200', booked: '¥313,400', bookedCompare: '9.2%' },
|
||
{ name: 'A区', amount: '¥118,200', discount: '-¥11,600', booked: '¥106,600', bookedCompare: '12.1%', isSub: true },
|
||
{ name: 'B区', amount: '¥95,800', discount: '-¥11,200', booked: '¥84,600', bookedCompare: '8.5%', isSub: true },
|
||
{ name: 'C区', amount: '¥72,600', discount: '-¥11,100', booked: '¥61,500', bookedCompare: '6.3%', isSub: true },
|
||
{ name: '团建区', amount: '¥48,200', discount: '-¥6,800', booked: '¥41,400', bookedCompare: '5.8%', isSub: true },
|
||
{ name: '麻将区', amount: '¥23,800', discount: '-¥4,500', booked: '¥19,300', bookedCompare: '-2.1%', isSub: true },
|
||
{ name: '助教', desc: '基础课', amount: '¥232,500', discount: '-', booked: '¥232,500', bookedCompare: '15.3%' },
|
||
{ name: '助教', desc: '激励课', amount: '¥112,800', discount: '-', booked: '¥112,800', bookedCompare: '8.2%' },
|
||
{ name: '食品酒水', amount: '¥119,556', discount: '-¥68,136', booked: '¥51,420', bookedCompare: '6.5%' },
|
||
],
|
||
priceItems: [
|
||
{ name: '开台消费', value: '¥358,600', compare: '9.2%' },
|
||
{ name: '酒水商品', value: '¥186,420', compare: '18.5%' },
|
||
{ name: '包厢费用', value: '¥165,636', compare: '12.1%' },
|
||
{ name: '助教服务', value: '¥112,800', compare: '15.3%' },
|
||
],
|
||
totalOccurrence: '¥823,456',
|
||
totalOccurrenceCompare: '12.5%',
|
||
discountItems: [
|
||
{ name: '会员折扣', value: '-¥45,200', compare: '3.1%' },
|
||
{ name: '赠送卡抵扣', value: '-¥42,016', compare: '2.5%' },
|
||
{ name: '团购差价', value: '-¥26,120', compare: '5.2%' },
|
||
],
|
||
confirmedTotal: '¥710,120',
|
||
confirmedTotalCompare: '8.7%',
|
||
channelItems: [
|
||
{ name: '储值卡结算冲销', value: '¥238,200', compare: '11.2%' },
|
||
{ name: '现金/线上支付', value: '¥345,800', compare: '7.8%' },
|
||
{ name: '团购核销确认收入', desc: '团购成交价', value: '¥126,120', compare: '5.3%' },
|
||
],
|
||
},
|
||
|
||
/** 现金流入 */
|
||
cashflow: {
|
||
consumeItems: [
|
||
{ name: '纸币现金', desc: '柜台现金收款', value: '¥85,600', compare: '12.3%', isDown: true },
|
||
{ name: '线上收款', desc: '微信/支付宝/刷卡 已扣除平台服务费', value: '¥260,200', compare: '8.5%', isDown: false },
|
||
{ name: '团购平台', desc: '美团/抖音回款 已扣除平台服务费', value: '¥126,120', compare: '15.2%', isDown: false },
|
||
],
|
||
rechargeItems: [
|
||
{ name: '会员充值到账', desc: '首充/续费实收', value: '¥352,800', compare: '18.5%' },
|
||
],
|
||
total: '¥824,720',
|
||
totalCompare: '10.2%',
|
||
},
|
||
|
||
/** 现金流出 */
|
||
expense: {
|
||
operationItems: [
|
||
{ name: '食品饮料', value: '¥108,200', compare: '4.5%', isDown: false },
|
||
{ name: '耗材', value: '¥21,850', compare: '2.1%', isDown: true },
|
||
{ name: '报销', value: '¥10,920', compare: '6.8%', isDown: false },
|
||
],
|
||
fixedItems: [
|
||
{ name: '房租', value: '¥125,000', compare: '持平', isFlat: true },
|
||
{ name: '水电', value: '¥24,200', compare: '3.2%', isFlat: false },
|
||
{ name: '物业', value: '¥11,500', compare: '持平', isFlat: true },
|
||
{ name: '人员工资', value: '¥112,000', compare: '持平', isFlat: true },
|
||
],
|
||
coachItems: [
|
||
{ name: '基础课分成', value: '¥116,250', compare: '8.2%', isDown: false },
|
||
{ name: '激励课分成', value: '¥23,840', compare: '5.6%', isDown: false },
|
||
{ name: '充值提成', value: '¥12,640', compare: '12.3%', isDown: false },
|
||
{ name: '额外奖金', value: '¥11,500', compare: '3.1%', isDown: true },
|
||
],
|
||
platformItems: [
|
||
{ name: '汇来米', value: '¥10,680', compare: '1.5%' },
|
||
{ name: '美团', value: '¥11,240', compare: '2.8%' },
|
||
{ name: '抖音', value: '¥10,580', compare: '3.5%' },
|
||
],
|
||
total: '¥600,400',
|
||
totalCompare: '2.1%',
|
||
},
|
||
|
||
/** 助教分析 */
|
||
coachAnalysis: {
|
||
basic: {
|
||
totalPay: '¥232,500',
|
||
totalPayCompare: '15.3%',
|
||
totalShare: '¥116,250',
|
||
totalShareCompare: '15.3%',
|
||
avgHourly: '¥25/h',
|
||
avgHourlyCompare: '4.2%',
|
||
rows: [
|
||
{ level: '初级', pay: '¥68,600', payCompare: '12.5%', share: '¥34,300', shareCompare: '12.5%', hourly: '¥20/h', hourlyCompare: '持平', hourlyFlat: true },
|
||
{ level: '中级', pay: '¥82,400', payCompare: '18.2%', share: '¥41,200', shareCompare: '18.2%', hourly: '¥25/h', hourlyCompare: '8.7%' },
|
||
{ level: '高级', pay: '¥57,800', payCompare: '14.6%', share: '¥28,900', shareCompare: '14.6%', hourly: '¥30/h', hourlyCompare: '持平', hourlyFlat: true },
|
||
{ level: '星级', pay: '¥23,700', payCompare: '3.2%', payDown: true, share: '¥11,850', shareCompare: '3.2%', shareDown: true, hourly: '¥35/h', hourlyCompare: '持平', hourlyFlat: true },
|
||
],
|
||
},
|
||
incentive: {
|
||
totalPay: '¥112,800',
|
||
totalPayCompare: '8.2%',
|
||
totalShare: '¥33,840',
|
||
totalShareCompare: '8.2%',
|
||
avgHourly: '¥15/h',
|
||
avgHourlyCompare: '2.1%',
|
||
},
|
||
},
|
||
},
|
||
|
||
onLoad() {
|
||
// mock 数据已内联,直接显示
|
||
},
|
||
|
||
onPullDownRefresh() {
|
||
setTimeout(() => wx.stopPullDownRefresh(), 500)
|
||
},
|
||
|
||
/** 看板 Tab 切换 */
|
||
onTabChange(e: WechatMiniprogram.TouchEvent) {
|
||
const tab = e.currentTarget.dataset.tab as string
|
||
if (tab === 'customer') {
|
||
wx.navigateTo({ url: '/pages/board-customer/board-customer' })
|
||
} else if (tab === 'coach') {
|
||
wx.navigateTo({ url: '/pages/board-coach/board-coach' })
|
||
}
|
||
},
|
||
|
||
/** 时间筛选变更 */
|
||
onTimeChange(e: WechatMiniprogram.CustomEvent<{ value: string }>) {
|
||
this.setData({ selectedTime: e.detail.value })
|
||
},
|
||
|
||
/** 区域筛选变更 */
|
||
onAreaChange(e: WechatMiniprogram.CustomEvent<{ value: string }>) {
|
||
this.setData({ selectedArea: e.detail.value })
|
||
},
|
||
|
||
/** 环比开关切换 */
|
||
toggleCompare() {
|
||
this.setData({ compareEnabled: !this.data.compareEnabled })
|
||
},
|
||
|
||
/** 目录导航开关 */
|
||
toggleToc() {
|
||
this.setData({ tocVisible: !this.data.tocVisible })
|
||
},
|
||
|
||
closeToc() {
|
||
this.setData({ tocVisible: false })
|
||
},
|
||
|
||
/** 目录项点击 → 滚动到对应板块 */
|
||
onTocItemTap(e: WechatMiniprogram.TouchEvent) {
|
||
const index = e.currentTarget.dataset.index as number
|
||
const sectionId = this.data.tocItems[index]?.sectionId
|
||
if (sectionId) {
|
||
this.setData({
|
||
tocVisible: false,
|
||
currentSectionIndex: index,
|
||
scrollIntoView: sectionId,
|
||
})
|
||
}
|
||
},
|
||
|
||
/** 帮助图标点击 → 弹出说明 */
|
||
onHelpTap(e: WechatMiniprogram.TouchEvent) {
|
||
const key = e.currentTarget.dataset.key as string
|
||
const tip = tipContents[key]
|
||
if (tip) {
|
||
this.setData({
|
||
tipVisible: true,
|
||
tipTitle: tip.title,
|
||
tipContent: tip.content,
|
||
})
|
||
}
|
||
},
|
||
|
||
/** 关闭提示弹窗 */
|
||
closeTip() {
|
||
this.setData({ tipVisible: false })
|
||
},
|
||
})
|