This commit is contained in:
Neo
2026-03-15 10:15:02 +08:00
parent 2dd217522c
commit 72bb11b34f
916 changed files with 65306 additions and 16102803 deletions

View File

@@ -1,5 +1,7 @@
{
"navigationBarTitleText": "看板",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"enablePullDownRefresh": true,
"usingComponents": {
"metric-card": "/components/metric-card/metric-card",

View File

@@ -1,6 +1,8 @@
// 财务看板页 — 忠于 H5 原型结构,内联 mock 数据
// TODO: 联调时替换 mock 数据为真实 API 调用
import { getRandomAiColor } from '../../utils/ai-color'
/** 目录板块定义 */
interface TocItem {
emoji: string
@@ -62,10 +64,14 @@ const tipContents: Record<string, { title: string; content: string }> = {
Page({
data: {
pageState: 'normal' as 'loading' | 'empty' | 'normal',
pageState: 'normal' as 'loading' | 'empty' | 'error' | 'normal',
/** AI 配色 */
aiColorClass: '',
/** 时间筛选 */
selectedTime: 'month',
selectedTimeText: '本月',
timeOptions: [
{ value: 'month', text: '本月' },
{ value: 'lastMonth', text: '上月' },
@@ -79,6 +85,7 @@ Page({
/** 区域筛选 */
selectedArea: 'all',
selectedAreaText: '全部区域',
areaOptions: [
{ value: 'all', text: '全部区域' },
{ value: 'hall', text: '大厅' },
@@ -103,7 +110,12 @@ Page({
{ emoji: '🎱', title: '助教分析', sectionId: 'section-coach' },
] as TocItem[],
currentSectionIndex: 0,
scrollIntoView: '',
/** P1: 吸顶板块头H5: scaleX 从左滑入,同时筛选按钮 opacity 淡出) */
stickyHeaderVisible: false,
stickyHeaderEmoji: '',
stickyHeaderTitle: '',
stickyHeaderDesc: '',
/** 提示弹窗 */
tipVisible: false,
@@ -169,15 +181,15 @@ Page({
/** 应计收入确认 */
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%' },
{ id: 'table', name: '开台与包厢', amount: '¥358,600', discount: '-¥45,200', booked: '¥313,400', bookedCompare: '9.2%' },
{ id: 'area-a', name: 'A区', amount: '¥118,200', discount: '-¥11,600', booked: '¥106,600', bookedCompare: '12.1%', isSub: true },
{ id: 'area-b', name: 'B区', amount: '¥95,800', discount: '-¥11,200', booked: '¥84,600', bookedCompare: '8.5%', isSub: true },
{ id: 'area-c', name: 'C区', amount: '¥72,600', discount: '-¥11,100', booked: '¥61,500', bookedCompare: '6.3%', isSub: true },
{ id: 'team', name: '团建区', amount: '¥48,200', discount: '-¥6,800', booked: '¥41,400', bookedCompare: '5.8%', isSub: true },
{ id: 'mahjong', name: '麻将区', amount: '¥23,800', discount: '-¥4,500', booked: '¥19,300', bookedCompare: '-2.1%', isSub: true },
{ id: 'coach-basic', name: '助教', desc: '基础课', amount: '¥232,500', discount: '-', booked: '¥232,500', bookedCompare: '15.3%' },
{ id: 'coach-incentive', name: '助教', desc: '激励课', amount: '¥112,800', discount: '-', booked: '¥112,800', bookedCompare: '8.2%' },
{ id: 'food', name: '食品酒水', amount: '¥119,556', discount: '-¥68,136', booked: '¥51,420', bookedCompare: '6.5%' },
],
priceItems: [
{ name: '开台消费', value: '¥358,600', compare: '9.2%' },
@@ -188,9 +200,10 @@ Page({
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%' },
{ name: '团购优惠', value: '-¥56,200', compare: '5.2%' },
{ name: '手动调整 + 大客户优惠', value: '-¥34,800', compare: '3.1%' },
{ name: '赠送卡抵扣', desc: '台桌卡+酒水卡+抵用券', value: '-¥22,336', compare: '8.6%' },
{ name: '其他优惠', desc: '免单+抹零', value: '-¥0', compare: '' },
],
confirmedTotal: '¥710,120',
confirmedTotalCompare: '8.7%',
@@ -266,12 +279,120 @@ Page({
totalShareCompare: '8.2%',
avgHourly: '¥15/h',
avgHourlyCompare: '2.1%',
rows: [
{ level: '初级', pay: '¥32,400', payCompare: '6.8%', share: '¥9,720', shareCompare: '6.8%', hourly: '¥12/h', hourlyCompare: '持平', hourlyFlat: true },
{ level: '中级', pay: '¥38,600', payCompare: '10.5%', share: '¥11,580', shareCompare: '10.5%', hourly: '¥15/h', hourlyCompare: '5.2%' },
{ level: '高级', pay: '¥28,200', payCompare: '7.3%', share: '¥8,460', shareCompare: '7.3%', hourly: '¥18/h', hourlyCompare: '持平', hourlyFlat: true },
{ level: '星级', pay: '¥13,600', payCompare: '2.1%', payDown: true, share: '¥4,080', shareCompare: '2.1%', shareDown: true, hourly: '¥22/h', hourlyCompare: '持平', hourlyFlat: true },
],
},
},
},
onLoad() {
// mock 数据已内联,直接显示
// P5: AI 配色
const aiColor = getRandomAiColor()
this.setData({ aiColorClass: aiColor.className })
},
onShow() {
// 同步 custom-tab-bar 选中态
const tabBar = this.getTabBar?.()
if (tabBar) tabBar.setData({ active: 'board' })
// TODO: 联调时在此刷新看板数据
},
onReady() {
// P1: 缓存各 section 的 top 位置
this._cacheSectionPositions()
},
/** P1/P2: 页面滚动监听(节流 100ms— 匹配 H5 原型行为 */
/* CHANGE 2026-03-13 | intent: H5 原型下滑→显示吸顶头+隐藏筛选按钮,上滑→隐藏吸顶头+恢复筛选按钮;不再使用独立的 filterBarHidden 状态 */
onPageScroll(e: { scrollTop: number }) {
const now = Date.now()
if (now - this._lastScrollTime < 100) return
this._lastScrollTime = now
const scrollTop = e.scrollTop
const isScrollingDown = scrollTop > this._lastScrollTop
this._lastScrollTop = scrollTop
// P1: 吸顶板块头 — 与 H5 updateStickyHeader 逻辑对齐
if (this._sectionTops.length === 0) return
// 偏移量tabs(~78rpx) + filter-bar(~70rpx) 约 148rpx ≈ 93px取 100 作为阈值
const offset = 100
let currentIdx = 0
for (let i = this._sectionTops.length - 1; i >= 0; i--) {
if (scrollTop + offset >= this._sectionTops[i]) {
currentIdx = i
break
}
}
// H5: scrollY < 80 时隐藏吸顶头
if (scrollTop < 80) {
if (this.data.stickyHeaderVisible) {
this.setData({ stickyHeaderVisible: false })
}
return
}
const toc = this.data.tocItems[currentIdx]
if (isScrollingDown && !this.data.stickyHeaderVisible) {
// H5: 下滑且吸顶头未显示 → 显示吸顶头(筛选按钮通过 CSS opacity 自动淡出)
this.setData({
stickyHeaderVisible: true,
stickyHeaderEmoji: toc?.emoji || '',
stickyHeaderTitle: toc?.title || '',
stickyHeaderDesc: toc ? (this._getSectionDesc(currentIdx) || '') : '',
currentSectionIndex: currentIdx,
})
} else if (!isScrollingDown && this.data.stickyHeaderVisible) {
// H5: 上滑且吸顶头显示 → 隐藏吸顶头(筛选按钮通过 CSS opacity 自动恢复)
this.setData({ stickyHeaderVisible: false })
} else if (this.data.stickyHeaderVisible && currentIdx !== this.data.currentSectionIndex) {
// H5: 吸顶头显示时板块切换 → 更新内容
this.setData({
stickyHeaderEmoji: toc?.emoji || '',
stickyHeaderTitle: toc?.title || '',
stickyHeaderDesc: toc ? (this._getSectionDesc(currentIdx) || '') : '',
currentSectionIndex: currentIdx,
})
}
},
/** 缓存 section 位置(私有) */
_sectionTops: [] as number[],
_lastScrollTop: 0,
_lastScrollTime: 0,
/** H5 原型吸顶头包含板块描述,从 data-section-desc 映射 */
_sectionDescs: [
'快速了解收入与现金流的整体健康度',
'会员卡充值与余额 掌握资金沉淀',
'从发生额到入账收入的全流程',
'实际到账的资金来源明细',
'清晰呈现各类开销与结构',
'全部助教服务收入与分成的平均值',
] as string[],
_getSectionDesc(index: number): string {
return this._sectionDescs[index] || ''
},
_cacheSectionPositions() {
const sectionIds = this.data.tocItems.map(item => item.sectionId)
const query = wx.createSelectorQuery().in(this)
sectionIds.forEach(id => {
query.select(`#${id}`).boundingClientRect()
})
query.exec((results: Array<WechatMiniprogram.BoundingClientRectCallbackResult | null>) => {
if (!results) return
this._sectionTops = results.map(r => (r ? r.top : 0))
})
},
onPullDownRefresh() {
@@ -290,12 +411,24 @@ Page({
/** 时间筛选变更 */
onTimeChange(e: WechatMiniprogram.CustomEvent<{ value: string }>) {
this.setData({ selectedTime: e.detail.value })
const value = e.detail.value
const option = this.data.timeOptions.find(o => o.value === value)
this.setData({
selectedTime: value,
selectedTimeText: option?.text || '本月',
})
},
/** 区域筛选变更 */
onAreaChange(e: WechatMiniprogram.CustomEvent<{ value: string }>) {
this.setData({ selectedArea: e.detail.value })
const value = e.detail.value
const option = this.data.areaOptions.find(o => o.value === value)
this.setData({
selectedArea: value,
selectedAreaText: option?.text || '全部区域',
})
// P3: 区域变更后重新缓存 section 位置(预收资产可能隐藏/显示)
setTimeout(() => this._cacheSectionPositions(), 300)
},
/** 环比开关切换 */
@@ -312,7 +445,7 @@ Page({
this.setData({ tocVisible: false })
},
/** 目录项点击 → 滚动到对应板块 */
/** 目录项点击 → 滚动到对应板块P0: 使用 pageScrollTo 替代 scrollIntoView */
onTocItemTap(e: WechatMiniprogram.TouchEvent) {
const index = e.currentTarget.dataset.index as number
const sectionId = this.data.tocItems[index]?.sectionId
@@ -320,8 +453,18 @@ Page({
this.setData({
tocVisible: false,
currentSectionIndex: index,
scrollIntoView: sectionId,
})
wx.createSelectorQuery().in(this)
.select(`#${sectionId}`)
.boundingClientRect((rect) => {
if (rect) {
wx.pageScrollTo({
scrollTop: rect.top + (this._lastScrollTop || 0) - 140,
duration: 300,
})
}
})
.exec()
}
},
@@ -342,4 +485,9 @@ Page({
closeTip() {
this.setData({ tipVisible: false })
},
/** P4: 错误态重试 */
onRetry() {
this.setData({ pageState: 'normal' })
},
})

View File

@@ -10,6 +10,14 @@
<t-empty description="暂无财务数据" />
</view>
<!-- 错误态 -->
<view class="page-error" wx:elif="{{pageState === 'error'}}">
<t-empty description="加载失败" />
<view class="retry-btn" bindtap="onRetry">
<text class="retry-btn-text">点击重试</text>
</view>
</view>
<!-- 正常态 -->
<block wx:else>
<!-- 顶部看板 Tab 导航 -->
@@ -26,15 +34,16 @@
</view>
<!-- 筛选区域 -->
<!-- CHANGE 2026-03-13 | intent: H5 原型筛选按钮与吸顶板块头共存于同一容器,通过 opacity/scaleX 动画切换;目录按钮始终可见,只有筛选按钮和环比开关淡出 -->
<view class="filter-bar">
<view class="filter-bar-inner">
<!-- 目录按钮 -->
<!-- 目录按钮(始终可见,不受吸顶头影响) -->
<view class="toc-btn" bindtap="toggleToc">
<t-icon name="view-list" size="40rpx" color="#ffffff" />
</view>
<!-- 时间筛选 -->
<view class="filter-item">
<!-- 时间筛选(吸顶头显示时淡出) -->
<view class="filter-item {{stickyHeaderVisible ? 'filter-item--hidden' : ''}}">
<filter-dropdown
label="本月"
options="{{timeOptions}}"
@@ -43,8 +52,8 @@
/>
</view>
<!-- 区域筛选 -->
<view class="filter-item">
<!-- 区域筛选(吸顶头显示时淡出) -->
<view class="filter-item {{stickyHeaderVisible ? 'filter-item--hidden' : ''}}">
<filter-dropdown
label="全部区域"
options="{{areaOptions}}"
@@ -53,7 +62,7 @@
/>
</view>
<!-- 环比开关 -->
<!-- 环比开关(始终可见,不受吸顶头影响) -->
<view class="compare-switch" bindtap="toggleCompare">
<text class="compare-label">环比</text>
<view class="compare-toggle {{compareEnabled ? 'compare-toggle--active' : ''}}">
@@ -61,15 +70,23 @@
</view>
</view>
</view>
<!-- 吸顶板块头(滚动到非首屏时从左滑入,覆盖在筛选按钮上方) -->
<view class="sticky-section-header {{stickyHeaderVisible ? 'sticky-section-header--show' : ''}}">
<text class="sticky-header-emoji">{{stickyHeaderEmoji}}</text>
<view class="sticky-header-content">
<text class="sticky-header-title">{{stickyHeaderTitle}}</text>
<text class="sticky-header-desc">{{stickyHeaderDesc}}</text>
</view>
<view class="sticky-header-tags">
<text class="sticky-header-tag" wx:if="{{selectedTimeText !== '本月'}}">{{selectedTimeText}}</text>
<text class="sticky-header-tag" wx:if="{{selectedAreaText !== '全部区域'}}">{{selectedAreaText}}</text>
</view>
</view>
</view>
<!-- 滚动内容区 -->
<scroll-view
class="board-content"
scroll-y
scroll-into-view="{{scrollIntoView}}"
scroll-with-animation
>
<!-- 内容区(页面自然滚动) -->
<view class="board-content">
<!-- ===== 板块 1: 经营一览(深色) ===== -->
<view id="section-overview" class="card-section section-dark">
@@ -184,31 +201,52 @@
</view>
<!-- AI 洞察 -->
<!-- CHANGE 2026-03-12 | intent: H5 原型使用 SVG 机器人图标,不可用 emoji 替代;规范要求内联 SVG 导出为文件用 image 引用 -->
<view class="ai-insight-section">
<view class="ai-insight-header">
<view class="ai-insight-icon">🤖</view>
<view class="ai-insight-icon">
<image src="/assets/icons/ai-robot.svg" mode="aspectFit" class="ai-insight-icon-img" />
</view>
<text class="ai-insight-title">AI 智能洞察</text>
</view>
<view class="ai-insight-body">
<text class="ai-insight-line"><text class="ai-insight-dim">优惠率Top</text>团购(5.2%) / 大客户(3.1%) / 赠送卡(2.5%)</text>
<text class="ai-insight-line"><text class="ai-insight-dim">差异最大:</text>酒水(+18%) / 台桌(-5%) / 包厢(+12%)</text>
<text class="ai-insight-line"><text class="ai-insight-dim">建议关注:</text>充值高但消耗低,会员活跃度需提升</text>
<!-- CHANGE 2026-03-12 | intent: H5 原型第三行"充值高但消耗低"有 underline 样式 -->
<text class="ai-insight-line"><text class="ai-insight-dim">建议关注:</text><text class="ai-insight-underline">充值高但消耗低</text>,会员活跃度需提升</text>
</view>
</view>
</view>
<!-- ===== 板块 2: 预收资产 ===== -->
<view id="section-recharge" class="card-section">
<!-- ===== 板块 2: 预收资产(仅"全部区域"时显示) ===== -->
<view id="section-recharge" class="card-section" wx:if="{{selectedArea === 'all'}}">
<view class="card-header-light">
<text class="card-header-emoji">💳</text>
<view class="card-header-text">
<text class="card-header-title-light">预收资产</text>
<text class="card-header-desc-light">会员卡充值与余额 掌握资金沉淀</text>
<text class="card-header-desc-light">会员卡充值与余额 掌握资金沉淀 辅助会员运营策略定制</text>
</view>
</view>
<!-- 储值卡统计 -->
<view class="section-body">
<!-- 全类别会员卡余额合计 -->
<!-- CHANGE 2026-03-13 | intent: H5 中 label 和 help-icon 在同一行flex items-center mb-1MP 需要用 view 包裹实现同行布局 -->
<view class="total-balance-row">
<view class="total-balance-left">
<view class="total-balance-label">
<text>全类别会员卡余额合计</text>
<view class="help-icon-dark" data-key="allCardBalance" bindtap="onHelpTap">?</view>
</view>
<text class="total-balance-note">仅经营参考,非财务属性</text>
</view>
<view class="total-balance-right">
<text class="total-balance-value">{{recharge.allCardBalance}}</text>
<view class="compare-row-inline" wx:if="{{compareEnabled}}">
<text class="compare-text-up-sm">↑{{recharge.allCardBalanceCompare}}</text>
</view>
</view>
</view>
<text class="card-section-title">储值卡统计</text>
<view class="table-bordered">
<!-- 行1储值卡充值实收 -->
@@ -273,7 +311,7 @@
</view>
<!-- 赠送卡统计详情 -->
<text class="card-section-title" style="margin-top: 28rpx;">赠送卡统计详情</text>
<text class="card-section-title" style="margin-top: 35rpx;">赠送卡统计详情</text>
<view class="table-bordered">
<!-- 表头 -->
<view class="gift-table-header">
@@ -282,51 +320,44 @@
<text class="gift-col">台费卡</text>
<text class="gift-col">抵用券</text>
</view>
<!-- 新增行 -->
<view class="gift-table-row" wx:for="{{recharge.giftRows}}" wx:key="label">
<!-- 数据行(新增/消费/余额) -->
<view class="gift-table-row {{compareEnabled ? 'gift-table-row--compare' : ''}}" wx:for="{{recharge.giftRows}}" wx:key="label">
<!-- 左列:标题 + 环比 / 总金额 -->
<view class="gift-col gift-col--name">
<text class="gift-row-label">{{item.label}}</text>
<text class="gift-row-total">{{item.total}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<text class="compare-text-up-xs">↑{{item.totalCompare}}</text>
<view class="gift-label-line">
<text class="gift-row-label">{{item.label}}</text>
<text class="compare-text-up-xs" wx:if="{{compareEnabled}}">↑{{item.totalCompare}}</text>
</view>
<text class="gift-row-total">{{item.total}}</text>
</view>
<!-- 酒水卡 -->
<view class="gift-col">
<text class="gift-col-val">{{item.wine}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<view class="gift-label-line" wx:if="{{compareEnabled}}">
<text class="compare-text-up-xs">↑{{item.wineCompare}}</text>
</view>
</view>
<!-- 台费卡 -->
<view class="gift-col">
<text class="gift-col-val">{{item.table}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<view class="gift-label-line" wx:if="{{compareEnabled}}">
<text class="compare-text-up-xs">↑{{item.tableCompare}}</text>
</view>
</view>
<!-- 抵用券 -->
<view class="gift-col">
<text class="gift-col-val">{{item.coupon}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<view class="gift-label-line" wx:if="{{compareEnabled}}">
<text class="compare-text-up-xs">↑{{item.couponCompare}}</text>
</view>
</view>
</view>
</view>
<!-- 全类别会员卡余额合计 -->
<view class="total-balance-row">
<view class="total-balance-left">
<text class="total-balance-label">全类别会员卡余额合计</text>
<view class="help-icon-dark" data-key="allCardBalance" bindtap="onHelpTap">?</view>
<text class="total-balance-note">仅经营参考,非财务属性</text>
</view>
<view class="total-balance-right">
<text class="total-balance-value">{{recharge.allCardBalance}}</text>
<view class="compare-row-inline" wx:if="{{compareEnabled}}">
<text class="compare-text-up-sm">↑{{recharge.allCardBalanceCompare}}</text>
</view>
</view>
</view>
</view>
<!-- 底部锯齿(模拟 H5 card-section::after -->
<view class="card-tear"></view>
</view>
<!-- ===== 板块 3: 应计收入确认 ===== -->
@@ -354,7 +385,7 @@
<text class="rev-col">入账</text>
</view>
<!-- 数据行 -->
<block wx:for="{{revenue.structureRows}}" wx:key="name">
<block wx:for="{{revenue.structureRows}}" wx:key="id">
<view class="rev-table-row {{item.isSub ? 'rev-table-row--sub' : ''}}">
<view class="rev-col rev-col--name">
<text class="{{item.isSub ? 'rev-name-sub' : 'rev-name'}}">{{item.name}}</text>
@@ -364,7 +395,7 @@
<text class="rev-col rev-val {{item.discount !== '-' ? 'rev-val--red' : 'rev-val--muted'}}">{{item.discount}}</text>
<view class="rev-col">
<text class="rev-val {{item.isSub ? '' : 'rev-val--bold'}}">{{item.booked}}</text>
<view class="compare-row" wx:if="{{compareEnabled && item.bookedCompare}}">
<view class="compare-row-inline" wx:if="{{compareEnabled && item.bookedCompare}}">
<text class="compare-text-up-xs">↑{{item.bookedCompare}}</text>
</view>
</view>
@@ -373,7 +404,8 @@
</view>
<!-- 收入确认(损益链) -->
<view class="sub-title-row" style="margin-top: 28rpx;">
<!-- CHANGE 2026-03-13 | intent: H5 收入结构外层 mb-5=20px→36rpx(87.5%取偶),损益链与收入结构之间的间距 -->
<view class="sub-title-row" style="margin-top: 36rpx;">
<text class="sub-title-text">收入确认</text>
<text class="sub-title-desc">从正价到收款方式的损益链</text>
</view>
@@ -414,10 +446,13 @@
</view>
<view class="flow-detail-list">
<view class="flow-detail-item" wx:for="{{revenue.discountItems}}" wx:key="name">
<text class="flow-detail-name">{{item.name}}</text>
<view class="flow-detail-name-group">
<text class="flow-detail-name">{{item.name}}</text>
<text class="flow-detail-name-desc" wx:if="{{item.desc}}">{{item.desc}}</text>
</view>
<view class="flow-detail-right">
<text class="flow-detail-val flow-detail-val--red">{{item.value}}</text>
<view class="compare-row-inline" wx:if="{{compareEnabled}}">
<text class="flow-detail-val {{item.value === '-¥0' ? 'flow-detail-val--muted' : 'flow-detail-val--red'}}">{{item.value}}</text>
<view class="compare-row-inline" wx:if="{{compareEnabled && item.compare}}">
<text class="compare-text-down-xs">↓{{item.compare}}</text>
</view>
</view>
@@ -426,8 +461,9 @@
<!-- 成交收入 -->
<view class="flow-total-row flow-total-row--accent">
<view class="flow-total-left">
<text class="flow-total-label">成交收入</text>
<text class="flow-total-desc">发生额 - 优惠</text>
<text class="flow-total-label">成交/确认收入</text>
<text class="flow-total-desc">发生额扣除以上优惠抵扣后的金额</text>
<text class="flow-total-desc">此金额收款渠道分布如下</text>
</view>
<view class="flow-total-right">
<text class="flow-total-value">{{revenue.confirmedTotal}}</text>
@@ -456,6 +492,8 @@
</view>
</view>
</view>
<!-- 底部锯齿(模拟 H5 card-section::after -->
<view class="card-tear"></view>
</view>
<!-- ===== 板块 4: 现金流入 ===== -->
@@ -487,7 +525,8 @@
</view>
<!-- 充值收入 -->
<text class="flow-group-label" style="margin-top: 20rpx;">充值收入</text>
<!-- CHANGE 2026-03-13 | intent: H5 mt-3=12px→22rpx(87.5%取偶) -->
<text class="flow-group-label" style="margin-top: 22rpx;">充值收入</text>
<view class="flow-item-list">
<view class="flow-item" wx:for="{{cashflow.rechargeItems}}" wx:key="name">
<view class="flow-item-left">
@@ -514,6 +553,8 @@
</view>
</view>
</view>
<!-- 底部锯齿(模拟 H5 card-section::after -->
<view class="card-tear"></view>
</view>
<!-- ===== 板块 5: 现金流出 ===== -->
@@ -587,6 +628,8 @@
</view>
</view>
</view>
<!-- 底部锯齿(模拟 H5 card-section::after -->
<view class="card-tear"></view>
</view>
<!-- ===== 板块 6: 助教分析 ===== -->
@@ -595,7 +638,7 @@
<text class="card-header-emoji">🎱</text>
<view class="card-header-text">
<text class="card-header-title-light">助教分析</text>
<text class="card-header-desc-light">全部助教服务收入与分成的平均值</text>
<text class="card-header-desc-light">全部助教服务收入与分成的平均值,用以评估球房分成效益</text>
</view>
</view>
@@ -614,41 +657,41 @@
<text class="coach-fin-col coach-fin-col--name coach-fin-bold">合计</text>
<view class="coach-fin-col">
<text class="coach-fin-bold">{{coachAnalysis.basic.totalPay}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<view class="compare-row-inline" wx:if="{{compareEnabled}}">
<text class="compare-text-up-xs">↑{{coachAnalysis.basic.totalPayCompare}}</text>
</view>
</view>
<view class="coach-fin-col">
<text class="coach-fin-bold">{{coachAnalysis.basic.totalShare}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<view class="compare-row-inline" wx:if="{{compareEnabled}}">
<text class="compare-text-up-xs">↑{{coachAnalysis.basic.totalShareCompare}}</text>
</view>
</view>
<view class="coach-fin-col">
<text class="coach-fin-val-sm">{{coachAnalysis.basic.avgHourly}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<view class="compare-row-inline" wx:if="{{compareEnabled}}">
<text class="compare-text-up-xs">↑{{coachAnalysis.basic.avgHourlyCompare}}</text>
</view>
</view>
</view>
<!-- 明细行 -->
<view class="coach-fin-row" wx:for="{{coachAnalysis.basic.rows}}" wx:key="level">
<view class="coach-fin-row coach-fin-row--detail" wx:for="{{coachAnalysis.basic.rows}}" wx:key="level">
<text class="coach-fin-col coach-fin-col--name">{{item.level}}</text>
<view class="coach-fin-col">
<text class="coach-fin-val">{{item.pay}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<view class="compare-row-inline" wx:if="{{compareEnabled}}">
<text class="{{item.payDown ? 'compare-text-down-xs' : 'compare-text-up-xs'}}">{{item.payDown ? '↓' : '↑'}}{{item.payCompare}}</text>
</view>
</view>
<view class="coach-fin-col">
<text class="coach-fin-val">{{item.share}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<view class="compare-row-inline" wx:if="{{compareEnabled}}">
<text class="{{item.shareDown ? 'compare-text-down-xs' : 'compare-text-up-xs'}}">{{item.shareDown ? '↓' : '↑'}}{{item.shareCompare}}</text>
</view>
</view>
<view class="coach-fin-col">
<text class="coach-fin-val-sm">{{item.hourly}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<view class="compare-row-inline" wx:if="{{compareEnabled}}">
<text class="{{item.hourlyFlat ? 'compare-text-flat-xs' : 'compare-text-up-xs'}}">{{item.hourlyFlat ? '' : '↑'}}{{item.hourlyCompare}}</text>
</view>
</view>
@@ -664,34 +707,36 @@
<text class="coach-fin-col">球房抽成</text>
<text class="coach-fin-col">小时平均</text>
</view>
<view class="coach-fin-row">
<view class="coach-fin-row coach-fin-row--incentive-total">
<text class="coach-fin-col coach-fin-col--name coach-fin-bold">合计</text>
<view class="coach-fin-col">
<text class="coach-fin-bold">{{coachAnalysis.incentive.totalPay}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<view class="compare-row-inline" wx:if="{{compareEnabled}}">
<text class="compare-text-up-xs">↑{{coachAnalysis.incentive.totalPayCompare}}</text>
</view>
</view>
<view class="coach-fin-col">
<text class="coach-fin-bold">{{coachAnalysis.incentive.totalShare}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<view class="compare-row-inline" wx:if="{{compareEnabled}}">
<text class="compare-text-up-xs">↑{{coachAnalysis.incentive.totalShareCompare}}</text>
</view>
</view>
<view class="coach-fin-col">
<text class="coach-fin-val-sm">{{coachAnalysis.incentive.avgHourly}}</text>
<view class="compare-row" wx:if="{{compareEnabled}}">
<view class="compare-row-inline" wx:if="{{compareEnabled}}">
<text class="compare-text-up-xs">↑{{coachAnalysis.incentive.avgHourlyCompare}}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 底部锯齿(模拟 H5 card-section::after -->
<view class="card-tear"></view>
</view>
<!-- 底部安全区 -->
<view class="safe-bottom"></view>
</scroll-view>
</view>
<!-- ===== 目录导航遮罩 ===== -->
<view class="toc-overlay" wx:if="{{tocVisible}}" catchtap="closeToc"></view>
@@ -731,4 +776,4 @@
<!-- AI 悬浮按钮 -->
<ai-float-button bottom="{{200}}" />
<dev-fab />
<dev-fab wx:if="{{false}}" />

File diff suppressed because it is too large Load Diff