1
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
{
|
||||
"navigationBarTitleText": "看板",
|
||||
"navigationBarBackgroundColor": "#ffffff",
|
||||
"navigationBarTextStyle": "black",
|
||||
"enablePullDownRefresh": true,
|
||||
"usingComponents": {
|
||||
"metric-card": "/components/metric-card/metric-card",
|
||||
|
||||
@@ -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' })
|
||||
},
|
||||
})
|
||||
|
||||
@@ -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-1),MP 需要用 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
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user