Files
Neo-ZQYY/apps/miniprogram - 副本/miniprogram/pages/board-customer/board-customer.wxml

302 lines
13 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 客户看板页 — 忠于 H5 原型8 维度卡片模板 -->
<!-- 加载态 -->
<view class="page-loading" wx:if="{{pageState === 'loading'}}">
<t-loading theme="circular" size="70rpx" text="加载中..." />
</view>
<!-- 空状态 -->
<view class="page-empty" wx:elif="{{pageState === 'empty'}}">
<t-empty description="暂无客户数据" />
</view>
<!-- 正常态 -->
<block wx:else>
<!-- 顶部看板 Tab -->
<view class="board-tabs">
<view class="board-tab" data-tab="finance" bindtap="onTabChange">
<text>财务</text>
</view>
<view class="board-tab board-tab--active" data-tab="customer">
<text>客户</text>
</view>
<view class="board-tab" data-tab="coach" bindtap="onTabChange">
<text>助教</text>
</view>
</view>
<!-- 筛选区域 -->
<view class="filter-bar {{filterBarVisible ? '' : 'filter-bar--hidden'}}">
<view class="filter-bar-inner">
<view class="filter-item filter-item--wide">
<filter-dropdown
label="最应召回"
options="{{dimensionOptions}}"
value="{{selectedDimension}}"
bind:change="onDimensionChange"
/>
</view>
<view class="filter-item">
<filter-dropdown
label="全部"
options="{{projectOptions}}"
value="{{selectedProject}}"
bind:change="onProjectChange"
/>
</view>
</view>
</view>
<!-- 列表头部 -->
<view class="list-header">
<view class="list-header-left">
<text class="list-header-title">客户列表</text>
<text class="list-header-sub">· 前100名</text>
</view>
<text class="list-header-count">共{{totalCount}}名客户</text>
</view>
<!-- 客户列表 -->
<view class="customer-list">
<view
class="customer-card"
wx:for="{{customers}}"
wx:key="id"
data-id="{{item.id}}"
bindtap="onCustomerTap"
>
<!-- ===== 卡片头部:头像 + 姓名 + 右侧指标 ===== -->
<view class="card-header">
<view class="card-avatar {{item.avatarCls}}">
<text class="avatar-text">{{item.initial}}</text>
</view>
<text class="card-name" wx:if="{{dimType !== 'freq60'}}">{{item.name}}</text>
<!-- 最频繁:姓名 + 下方小字垂直排列 -->
<view class="card-name-group" wx:if="{{dimType === 'freq60'}}">
<text class="card-name">{{item.name}}</text>
<view class="card-name-sub">
<text class="mid-text" style="white-space: nowrap;">平均间隔 <text class="mid-primary">{{item.avgInterval}}</text></text>
<text class="mid-text" style="margin-left: 16rpx; white-space: nowrap;">60天消费 <text class="mid-dark">{{item.spend60d}}</text></text>
</view>
</view>
<view class="card-header-spacer"></view>
<!-- 最应召回:理想/已过/超期 -->
<view class="header-metrics" wx:if="{{dimType === 'recall'}}">
<text class="metric-gray">理想 <text class="metric-dark">{{item.idealDays}}天</text></text>
<text class="metric-gray">已过 <text class="metric-error">{{item.elapsedDays}}天</text></text>
<view class="overdue-tag {{item.overdueDays > 7 ? 'overdue-tag--danger' : 'overdue-tag--warn'}}">
<text>超期 {{item.overdueDays}}天</text>
</view>
</view>
<!-- 最大消费潜力:频率/客单/余额标签 -->
<view class="header-metrics" wx:elif="{{dimType === 'potential'}}">
<view class="potential-tag potential-tag--{{tag.theme}}" wx:for="{{item.potentialTags}}" wx:for-item="tag" wx:key="text">
<text>{{tag.text}}</text>
</view>
</view>
<!-- 最高余额:最近到店/理想 -->
<view class="header-metrics" wx:elif="{{dimType === 'balance'}}">
<text class="metric-gray">最近到店 <text class="metric-dark">{{item.lastVisit}}</text></text>
<text class="metric-gray">理想 <text class="metric-dark">{{item.idealDays}}天</text></text>
</view>
<!-- 最近充值:最近到店/理想 -->
<view class="header-metrics" wx:elif="{{dimType === 'recharge'}}">
<text class="metric-gray">最近到店 <text class="metric-dark">{{item.lastVisit}}</text></text>
<text class="metric-gray">理想 <text class="metric-dark">{{item.idealDays}}天</text></text>
</view>
<!-- 最频繁近60天右上角大字到店次数 -->
<view class="header-metrics header-metrics--freq" wx:elif="{{dimType === 'freq60'}}">
<view class="freq-big-num">
<text class="freq-big-val">{{item.visits60d}}</text>
<text class="freq-big-unit">次</text>
</view>
<text class="freq-big-label">60天到店</text>
</view>
<!-- 最专一近60天右上角 ❤️ 助教名 + 关系指数 -->
<view class="header-metrics header-metrics--loyal" wx:elif="{{dimType === 'loyal'}}">
<heart-icon score="{{item.topCoachHeart}}" />
<text class="loyal-top-name">{{item.topCoachName}}</text>
<text class="loyal-top-score">{{item.topCoachScore}}</text>
</view>
<!-- 最高消费近60天高消费标签 -->
<view class="header-metrics" wx:elif="{{dimType === 'spend60'}}">
<view class="potential-tag potential-tag--warning" wx:if="{{item.highSpendTag}}">
<text>高消费</text>
</view>
</view>
<!-- 最近到店:右上角大字 X天前到店 -->
<view class="header-metrics header-metrics--recent" wx:elif="{{dimType === 'recent'}}">
<view class="recent-big-num">
<text class="recent-big-val">{{item.daysAgo}}</text>
<text class="recent-big-unit">天前到店</text>
</view>
</view>
</view>
<!-- ===== 卡片中间行:维度特定数据 ===== -->
<!-- 最应召回30天到店 / 余额 / 召回指数 -->
<view class="card-mid-row" wx:if="{{dimType === 'recall'}}">
<text class="mid-text">30天到店 <text class="mid-dark">{{item.visits30d}}次</text></text>
<text class="mid-text mid-ml">余额 <text class="mid-dark">{{item.balance}}</text></text>
<text class="mid-text mid-right">召回指数 <text class="mid-primary-bold">{{item.recallIndex}}</text></text>
</view>
<!-- 最大消费潜力4 列网格30天消费用橙色大字和最高余额的余额值一致 -->
<view class="card-grid card-grid--4" wx:elif="{{dimType === 'potential'}}">
<view class="grid-cell">
<text class="grid-label">30天消费</text>
<text class="grid-val grid-val--warning grid-val--lg">{{item.spend30d}}</text>
</view>
<view class="grid-cell">
<text class="grid-label">月均到店</text>
<text class="grid-val">{{item.avgVisits}}</text>
</view>
<view class="grid-cell">
<text class="grid-label">余额</text>
<text class="grid-val grid-val--success">{{item.balance}}</text>
</view>
<view class="grid-cell">
<text class="grid-label">次均消费</text>
<text class="grid-val">{{item.avgSpend}}</text>
</view>
</view>
<!-- 最高余额3 列网格 -->
<view class="card-grid card-grid--3" wx:elif="{{dimType === 'balance'}}">
<view class="grid-cell">
<text class="grid-label">余额</text>
<text class="grid-val grid-val--warning grid-val--lg">{{item.balance}}</text>
</view>
<view class="grid-cell">
<text class="grid-label">月均消耗</text>
<text class="grid-val">{{item.monthlyConsume}}</text>
</view>
<view class="grid-cell">
<text class="grid-label">可用</text>
<text class="grid-val grid-val--success">{{item.availableMonths}}</text>
</view>
</view>
<!-- 最近充值4 列网格 -->
<view class="card-grid card-grid--4" wx:elif="{{dimType === 'recharge'}}">
<view class="grid-cell">
<text class="grid-label">最后充值</text>
<text class="grid-val">{{item.lastRecharge}}</text>
</view>
<view class="grid-cell">
<text class="grid-label">充值</text>
<text class="grid-val grid-val--success">{{item.rechargeAmount}}</text>
</view>
<view class="grid-cell">
<text class="grid-label">60天充值</text>
<text class="grid-val">{{item.recharges60d}}</text>
</view>
<view class="grid-cell">
<text class="grid-label">当前余额</text>
<text class="grid-val grid-val--warning">{{item.currentBalance}}</text>
</view>
</view>
<!-- 最高消费近60天3 列网格 -->
<view class="card-grid card-grid--3" wx:elif="{{dimType === 'spend60'}}">
<view class="grid-cell">
<text class="grid-label">近60天消费</text>
<text class="grid-val grid-val--warning grid-val--lg">{{item.spend60d}}</text>
</view>
<view class="grid-cell">
<text class="grid-label">到店次数</text>
<text class="grid-val">{{item.visits60d}}</text>
</view>
<view class="grid-cell">
<text class="grid-label">次均消费</text>
<text class="grid-val">{{item.avgSpend}}</text>
</view>
</view>
<!-- 最频繁近60天无中间行数据已在头部 -->
<!-- 最频繁迷你柱状图8 周) -->
<view class="mini-chart" wx:if="{{dimType === 'freq60'}}">
<view class="mini-chart-header">
<text class="mini-chart-label">8周前</text>
<text class="mini-chart-label">本周</text>
</view>
<view class="mini-chart-bars">
<view class="mini-bar-col" wx:for="{{item.weeklyVisits}}" wx:for-item="wv" wx:for-index="wIdx" wx:key="wIdx">
<view class="mini-bar" style="height:{{wv.pct}}%;opacity:{{0.2 + wv.pct * 0.006}}"></view>
</view>
</view>
<view class="mini-chart-nums">
<text class="mini-chart-num {{wIdx === item.weeklyVisits.length - 1 ? 'mini-chart-num--active' : ''}}" wx:for="{{item.weeklyVisits}}" wx:for-item="wv" wx:for-index="wIdx" wx:key="wIdx">{{wv.val}}</text>
</view>
</view>
<!-- 最专一近60天助教服务明细表 -->
<view class="loyal-table" wx:elif="{{dimType === 'loyal'}}">
<!-- 表头 -->
<view class="loyal-row loyal-row--header">
<text class="loyal-col loyal-col--name">助教</text>
<text class="loyal-col">次均时长</text>
<text class="loyal-col">服务次数</text>
<text class="loyal-col">助教消费</text>
<text class="loyal-col">关系指数</text>
</view>
<!-- 数据行 -->
<view class="loyal-row" wx:for="{{item.coachDetails}}" wx:for-item="cd" wx:key="name">
<view class="loyal-col loyal-col--name">
<heart-icon score="{{cd.heartScore}}" />
<text class="loyal-coach-name {{cd.cls}}">{{cd.name}}</text>
<text class="assistant-badge assistant-badge--follow" wx:if="{{cd.badge === '跟'}}">跟</text>
<text class="assistant-badge assistant-badge--drop" wx:elif="{{cd.badge === '弃'}}">弃</text>
</view>
<text class="loyal-col loyal-val">{{cd.avgDuration}}</text>
<text class="loyal-col loyal-val">{{cd.serviceCount}}</text>
<text class="loyal-col loyal-val">{{cd.coachSpend}}</text>
<text class="loyal-col {{cd.relationIdx >= 8 ? 'loyal-val--primary' : 'loyal-val--gray'}}">{{cd.relationIdx}}</text>
</view>
</view>
<!-- 最近到店:理想间隔 / 60天到店 / 次均消费 -->
<view class="card-mid-row" wx:elif="{{dimType === 'recent'}}">
<text class="mid-text">理想间隔 <text class="mid-dark">{{item.idealDays}}天</text></text>
<text class="mid-text mid-ml">60天到店 <text class="mid-dark">{{item.visits60d}}天</text></text>
<text class="mid-text mid-ml">次均消费 <text class="mid-dark">{{item.avgSpend}}</text></text>
</view>
<!-- ===== 卡片底部:助教行(最专一维度不显示,因为助教信息在表格中) ===== -->
<view class="card-assistant-row" wx:if="{{item.assistants && item.assistants.length > 0 && dimType !== 'loyal'}}">
<text class="assistant-label">助教:</text>
<block wx:for="{{item.assistants}}" wx:for-item="ast" wx:for-index="astIdx" wx:key="name">
<text class="assistant-sep" wx:if="{{astIdx > 0}}">|</text>
<view class="assistant-tag">
<heart-icon score="{{ast.heartScore}}" />
<text class="assistant-name {{ast.cls}}">{{ast.name}}</text>
<text class="assistant-badge assistant-badge--follow" wx:if="{{ast.badge === '跟'}}">跟</text>
<text class="assistant-badge assistant-badge--drop" wx:elif="{{ast.badge === '弃'}}">弃</text>
</view>
</block>
</view>
</view>
</view>
<!-- 底部安全区 -->
<view class="safe-bottom"></view>
</block>
<!-- 自定义底部导航栏 -->
<board-tab-bar active="board" />
<!-- AI 悬浮按钮 -->
<ai-float-button bottom="{{220}}" />
<dev-fab />