<template>
	<view class="page">
		<view class="warpbox">
			<!-- 顶部筛选区域 -->
			<view class="header-section">
				<!-- 经营看板 -->
				<view class="page-title"></view>
				<view class="filter-box">
					<picker mode="date" fields="month" :value="selectedMonth" @change="onMonthChange">
						<view class="date-picker-trigger">
							<text class="date-text">{{ selectedMonthText }}</text>
							<u-icon name="arrow-down" size="14" color="#666"></u-icon>
						</view>
					</picker>
					<!-- 截图按钮 -->
					<!-- #ifdef H5 -->
					<view class="screenshot-btn" v-if="showScreenshotBtn" @click="saveScreenshot" :class="{ loading: screenshotLoading }">
						<u-icon name="photo" size="18" color="#409EFF"></u-icon>
						<text class="screenshot-text">截图</text>
					</view>
					<!-- #endif -->
				</view>
			</view>

			<!-- 6大核心KPI指标 -->
			<view class="kpi-section">
				<!-- 上方4个指标 - 按照me.vue样式排版 -->
				<view class="glass-card billing-card">
					<view class="billing-main" v-for="(kpi, index) in kpiListTop.slice(0, 2)" :key="index" >
						<view class="stat-content">
							<view class="label-row">
								<view class="stat-icon-small" :class="kpi.type">
									<u-icon :name="getKpiIconName(kpi.key)" :size="20" color="#fff"></u-icon>
								</view>
								<view class="card-label">{{ kpi.label }}</view>
							</view>
							<view class="billing-value">
								<text class="currency" v-if="kpi.isMoney">￥</text>
								<text class="value">{{ kpi.isMoney ? kpi.value.toString().replace(/[^\d\.]/g, '') : (kpi.isPercent ? kpi.value : kpi.value) }}</text>
								<text class="unit" v-if="kpi.isPercent">%</text>
								<text class="unit" v-if="!kpi.isMoney && !kpi.isPercent && kpi.unit">{{ kpi.unit }}</text>
							</view>
						</view>
					</view>
					<view class="billing-footer">
						<view class="count-item" v-for="(kpi, index) in kpiListTop.slice(2, 4)" :key="index" >
							<view class="count-icon" :class="kpi.type">
								<u-icon :name="getKpiIconName(kpi.key)" :size="20" color="#fff"></u-icon>
							</view>
							<text class="count-text">
								<text class="count-value">{{ kpi.value }}</text>
								<text class="count-unit">{{ kpi.unit }}</text>
							</text>
						</view>
					</view>
				</view>
				<!-- 下方3个指标（1x3布局） -->
				<view class="kpi-grid-bottom">
					<view class="kpi-card" v-for="(kpi, index) in kpiListBottom" :key="index" >
						<view class="kpi-header">
							<view class="kpi-icon-square" :class="kpi.type">
								<u-icon :name="getKpiIconName(kpi.key)" :size="16" color="#fff"></u-icon>
							</view>
							<text class="kpi-label">{{ kpi.label }}</text>
						</view>
						<view class="kpi-value-group">
							
							<text class="value"><text class="currency" v-if="kpi.isMoney">￥</text>{{ kpi.isMoney ? kpi.value.toString().replace(/[^\d\.]/g, '') : (kpi.isPercent ? kpi.value : kpi.value) }}</text>
							<text class="unit" v-if="kpi.isPercent">%</text>
							<text class="unit" v-if="!kpi.isMoney && !kpi.isPercent && kpi.unit">{{ kpi.unit }}</text>
						</view>
					</view>
				</view>
			</view>

			<!-- 会员资产全景 -->
			<view class="warpboxss member-section" v-if="memberStatistics.totalMembers > 0">
				<view class="warpboxs-small-title">
					<view><text class="warpboxs-small-title-line"></text>会员资产全景</view>
				</view>
				<view class="member-grid">
					<view class="member-stat-card blue-theme" @click="openMemberDetailModal('total')">
						<view class="icon-circle">
							<u-icon name="account" size="24" color="#409EFF"></u-icon>
						</view>
						<view class="stat-info">
							<view class="stat-label">总会员数</view>
							<view class="stat-value">{{ formatNumber(memberStatistics.totalMembers) }}</view>
						</view>
					</view>
					<view class="member-stat-card green-theme" @click="openMemberDetailModal('active')">
						<view class="icon-circle">
							<u-icon name="checkmark-circle" size="24" color="#67C23A"></u-icon>
						</view>
						<view class="stat-info">
							<view class="stat-label">活跃会员</view>
							<view class="stat-value">{{ formatNumber(memberStatistics.activeMembers) }}</view>
						</view>
					</view>
					<view class="member-stat-card orange-theme" @click="openMemberDetailModal('remaining')">
						<view class="icon-circle">
							<u-icon name="shopping-cart" size="24" color="#E6A23C"></u-icon>
						</view>
						<view class="stat-info">
							<view class="stat-label">剩余权益</view>
							<view class="stat-value mini">￥{{ formatMoney(memberStatistics.totalRemainingAmount) }}</view>
						</view>
					</view>
					<view class="member-stat-card red-theme" @click="openMemberDetailModal('sleep')">
						<view class="icon-circle">
							<u-icon name="info-circle" size="24" color="#F56C6C"></u-icon>
						</view>
						<view class="stat-info">
							<view class="stat-label">沉睡会员</view>
							<view class="stat-value">{{ formatNumber(memberStatistics.totalSleepMembers) }}</view>
						</view>
					</view>
				</view>
			</view>

			<!-- 会员结构洞察 -->
			<view class="warpboxss member-chart-section" v-if="memberTypeDistribution.length > 0">
				<view class="warpboxs-small-title">
					<view><text class="warpboxs-small-title-line"></text>会员结构洞察</view>
				</view>
				<view class="member-chart-container">
					<view class="member-type-chart-wrapper">
						<qiun-data-charts 
							type="pie"
							:opts="memberTypeChartOpts"
							:chartData="memberTypeChartData"
							:ontouch="true"
							:inScrollView="true"
							:pageScrollTop="pageScrollTop"
						/>
					</view>
					<view class="member-type-legend">
						<view class="legend-item" v-for="(item, index) in memberTypeDistribution" :key="index">
							<view class="legend-dot" :style="{ backgroundColor: getMemberTypeColor(index) }"></view>
							<text class="legend-name">{{ item.MemberType || '未知' }}</text>
							<text class="legend-value">{{ formatNumber(item.Count || 0) }}人</text>
						</view>
					</view>
				</view>
			</view>

			<!-- 会员价值分层 -->
			<view class="warpboxss member-category-section" v-if="memberStatistics.beautyMembers > 0 || memberStatistics.medicalMembers > 0 || memberStatistics.techMembers > 0">
				<view class="warpboxs-small-title">
					<view><text class="warpboxs-small-title-line"></text>会员价值分层</view>
				</view>
				<view class="member-category-container">
					<view class="member-category-chart-wrapper">
						<qiun-data-charts 
							type="radar"
							:opts="memberCategoryChartOpts"
							:chartData="memberCategoryChartData"
							:ontouch="true"
							:inScrollView="true"
							:pageScrollTop="pageScrollTop"
						/>
					</view>
					<view class="member-category-legend">
						<view class="legend-item">
							<view class="legend-color" style="background: #409EFF;"></view>
							<view class="legend-text">
								<view class="legend-name">生美会员</view>
								<view class="legend-value">{{ formatNumber(memberStatistics.beautyMembers) }}人</view>
							</view>
						</view>
						<view class="legend-item">
							<view class="legend-color" style="background: #F56C6C;"></view>
							<view class="legend-text">
								<view class="legend-name">医美会员</view>
								<view class="legend-value">{{ formatNumber(memberStatistics.medicalMembers) }}人</view>
							</view>
						</view>
						<view class="legend-item">
							<view class="legend-color" style="background: #67C23A;"></view>
							<view class="legend-text">
								<view class="legend-name">科技部会员</view>
								<view class="legend-value">{{ formatNumber(memberStatistics.techMembers) }}人</view>
							</view>
						</view>
					</view>
				</view>
			</view>

			<!-- 经营效能趋势 -->
			<view class="warpboxss trend-section" v-if="trendData.length > 0">
				<view class="warpboxs-small-title">
					<view><text class="warpboxs-small-title-line"></text>经营效能趋势</view>
					<view class="trend-controls">
						<view class="pill-switch">
							<view class="pill-item" :class="trendType === 'month' ? 'active' : ''" @click="switchTrendType('month')">月</view>
							<view class="pill-item" :class="trendType === 'day' ? 'active' : ''" @click="switchTrendType('day')">日</view>
							<view class="pill-item" :class="trendType === 'week' ? 'active' : ''" @click="switchTrendType('week')">周</view>
						</view>
					</view>
				</view>
				<view class="chart-wrapper">
					<qiun-data-charts 
						type="line"
						:opts="trendChartOpts"
						:chartData="trendChartData"
						:ontouch="true"
						:inScrollView="true"
						:pageScrollTop="pageScrollTop"
						background="rgba(255, 255, 255, 0.8)"
					/>
				</view>
				<view class="trend-legend-modern">
					<view class="legend-item">
						<view class="dot revenue"></view>
						<text>营收(成交额)</text>
					</view>
					<view class="legend-item">
						<view class="dot consume"></view>
						<text>消耗(服务产出)</text>
					</view>
				</view>
			</view>

			<!-- 门店卓越榜 -->
			<view class="warpboxss ranking-section" v-if="storeRanking.length > 0">
				<view class="warpboxs-small-title">
					<view><text class="warpboxs-small-title-line"></text>门店卓越榜</view>
				</view>
				<view class="rank-list-modern">
					<view class="rank-item" v-for="(item, index) in storeRanking.slice(0, 10)" :key="index" @click="handleStoreClick(item)">
						<view class="rank-idx" :class="index < 3 ? 'top-3' : ''">
							<image v-if="index === 0" src="/static/rank/no1.png" class="medal-icon"></image>
							<image v-else-if="index === 1" src="/static/rank/no2.png" class="medal-icon"></image>
							<image v-else-if="index === 2" src="/static/rank/no3.png" class="medal-icon"></image>
							<text v-else>{{ index + 1 }}</text>
						</view>
						<view class="rank-info">
							<view class="info-main">
								<text class="name">{{ item.StoreName || '未知门店' }}</text>
								<text class="value">￥{{ formatMoney(item.TotalPerformance) }}</text>
							</view>
							<view class="progress-bg">
								<view class="progress-bar" :style="{ width: (item.TotalPerformance / (storeRanking[0].TotalPerformance || 1) * 100) + '%' }"></view>
							</view>
						</view>
					</view>
				</view>
			</view>

			<!-- 核心员效贡献矩阵 -->
			<view class="warpboxss coach-section" v-if="coachRanking.length > 0">
				<view class="warpboxs-small-title">
					<view><text class="warpboxs-small-title-line"></text>核心员效贡献矩阵</view>
					<view class="type-tags">
						<view class="tag-item" :class="coachRankType === 'billing' ? 'active' : ''" @click="switchCoachRankType('billing')">开单</view>
						<view class="tag-item" :class="coachRankType === 'consume' ? 'active' : ''" @click="switchCoachRankType('consume')">消耗</view>
						<view class="tag-item" :class="coachRankType === 'refund' ? 'active' : ''" @click="switchCoachRankType('refund')">退卡</view>
					</view>
				</view>
				<view class="rank-list-modern">
					<view class="rank-item" v-for="(item, index) in coachRanking.slice(0, 10)" :key="index">
						<view class="rank-idx" :class="index === 0 ? 'rank-1' : (index === 1 ? 'rank-2' : (index === 2 ? 'rank-3' : ''))">
							<text>{{ index + 1 }}</text>
						</view>
						<view class="rank-avatar">
							<text>{{ item.HealthCoachName ? item.HealthCoachName.substring(0, 1) : '无' }}</text>
						</view>
						<view class="rank-info">
							<view class="info-main">
								<text class="name">{{ item.HealthCoachName || '未知' }}</text>
								<text class="value">￥{{ formatMoney(item.Amount) }}</text>
							</view>
							<view class="progress-bg">
								<view class="progress-bar green" :style="{ width: item.Percent + '%' }"></view>
							</view>
						</view>
					</view>
				</view>
			</view>
			
			<!-- 协同作战榜 -->
			<view class="warpboxss gold-triangle-section" v-if="goldTriangleRankings.length > 0">
				<view class="warpboxs-small-title">
					<view><text class="warpboxs-small-title-line"></text>协同作战榜</view>
				</view>
				<view class="rank-list-modern">
					<view class="rank-item" v-for="(item, index) in goldTriangleRankingTop10" :key="index">
						<view class="rank-idx" :class="index === 0 ? 'rank-1' : (index === 1 ? 'rank-2' : (index === 2 ? 'rank-3' : ''))">
							<text>{{ index + 1 }}</text>
						</view>
						<view class="rank-info">
							<view class="info-main">
								<text class="name">{{ item.GoldTriangleName || '未知' }}</text>
								<text class="value orange-value">￥{{ formatMoney(item.TotalPerformance) }}</text>
							</view>
							<view class="progress-bg">
								<view class="progress-bar orange" :style="{ width: (item.TotalPerformance / (goldTriangleRankingTop10[0].TotalPerformance || 1) * 100) + '%' }"></view>
							</view>
						</view>
					</view>
				</view>
			</view>

			<!-- 客户活跃度分析 -->
			<view class="warpboxss visit-frequency-section" v-if="customerVisitFrequencyData.length > 0">
				<view class="warpboxs-small-title">
					<view><text class="warpboxs-small-title-line"></text>客户活跃度分析</view>
				</view>
				<view class="chart-wrapper">
					<qiun-data-charts 
						type="column"
						:opts="visitFrequencyChartOpts"
						:chartData="visitFrequencyChartData"
						:ontouch="true"
						:inScrollView="true"
						:pageScrollTop="pageScrollTop"
					/>
				</view>
			</view>

			<!-- 热门服务品项TOP10 -->
			<view class="warpboxss item-section" v-if="consumeItemTop10.length > 0">
				<view class="warpboxs-small-title">
					<view><text class="warpboxs-small-title-line"></text>热门服务品项</view>
				</view>
				<view class="item-grid">
					<view class="item-card" v-for="(item, index) in consumeItemTop10" :key="index">
						<view class="item-rank-badge" :class="'rank-' + (index + 1)">{{ index + 1 }}</view>
						<view class="item-name">{{ item.ItemName || '未知品项' }}</view>
						<view class="item-val">￥{{ formatMoney(item.Amount) }}</view>
						<view class="item-process">
							<view class="bar" :style="{ width: item.Percent + '%' }"></view>
						</view>
					</view>
				</view>
			</view>

			<!-- 热销产品品项TOP10 -->
			<view class="warpboxss item-section" v-if="billingItemTop10.length > 0">
				<view class="warpboxs-small-title">
					<view><text class="warpboxs-small-title-line"></text>热销产品品项</view>
				</view>
				<view class="item-grid">
					<view class="item-card" v-for="(item, index) in billingItemTop10" :key="index">
						<view class="item-rank-badge" :class="'rank-' + (index + 1)">{{ index + 1 }}</view>
						<view class="item-name">{{ item.ItemName || '未知品项' }}</view>
						<view class="item-val">￥{{ formatMoney(item.Amount) }}</view>
						<view class="item-process">
							<view class="bar blue" :style="{ width: item.Percent + '%' }"></view>
						</view>
					</view>
				</view>
			</view>
			
			<!-- 客户获取转化链 -->
			<view class="warpboxss funnel-section" v-if="tkStatisticsData">
				<view class="warpboxs-small-title">
					<view><text class="warpboxs-small-title-line"></text>客户获取转化链</view>
				</view>
				<view class="chart-wrapper">
					<qiun-data-charts 
						type="funnel"
						:opts="funnelChartOpts"
						:chartData="funnelChartData"
						:ontouch="true"
						:inScrollView="true"
						:pageScrollTop="pageScrollTop"
					/>
				</view>
				<view class="funnel-stats">
					<view class="stat-mini">邀约率: <text class="stat-value">{{ formatPercent(getTkInviteRate()) }}%</text></view>
					<view class="stat-mini">到店率: <text class="stat-value">{{ formatPercent(getInviteStoreRate()) }}%</text></view>
				</view>
			</view>

			<!-- 底部安全区域 -->
			<view style="height: 150rpx;"></view>
		</view>
		
		<!-- 会员统计详情弹窗 -->
		<u-popup :show="showMemberDetailModal" @close="closeMemberDetailModal" mode="center" border-radius="20" :closeable="true">
			<view class="member-detail-modal">
				<view class="modal-title">{{ detailModalTitle }}</view>
				<view class="modal-content">
					<view class="detail-item" v-for="(item, index) in detailModalData" :key="index">
						<view class="detail-label">{{ item.label }}</view>
						<view class="detail-value">{{ item.value }}</view>
					</view>
				</view>
			</view>
		</u-popup>
	</view>
</template>
<script>
import uCharts from '@qiun/ucharts'

// uCharts 图表工具类
const ChartUtil = {
	// 绘制折线图
	drawLineChart(vueInstance, canvasId, categories, series, options = {}) {
		if (!categories || categories.length === 0 || !series || series.length === 0) {
			return
		}
		
		const chartData = {
			categories: categories,
			series: series.map((s, index) => ({
				name: s.name || `系列${index + 1}`,
				data: s.data,
				color: s.color || ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'][index]
			}))
		}
		
		// 如果是趋势图表，添加x轴标签倾斜设置
		const isTrendChart = canvasId === 'trendChart'
		
		const opts = {
			type: 'line',
			fontSize: 10,
			dataLabel: false,
			dataPointShape: true,
			legend: {
				show: false
			},
			xAxis: {
				disableGrid: false,
				itemCount: categories.length > 12 ? 12 : categories.length,
				...(isTrendChart ? {
					rotateLabel: true,
					rotateAngle: 45,
					marginTop: 5
				} : {})
			},
			yAxis: {
				gridType: 'dash',
				dashLength: 2,
				format: (val) => {
					return val >= 10000 ? (val / 10000).toFixed(1) + '万' : val.toString()
				}
			},
			extra: {
				line: {
					type: 'curve',
					width: 2
				},
				tooltip: {
					showBox: true,
					showArrow: true,
					showCategory: true
				},
			}
		}
		
		const query = uni.createSelectorQuery().in(vueInstance)
		query.select(`#${canvasId}`).boundingClientRect((rect) => {
			if (!rect || !rect.width || !rect.height) {
				console.warn(`图表容器 ${canvasId} 尺寸获取失败`, rect)
				return
			}
			const ctx = uni.createCanvasContext(canvasId, vueInstance)
			const systemInfo = uni.getSystemInfoSync()
			const pixelRatio = systemInfo.pixelRatio || 1
			const chartWidth = Math.floor(uni.upx2px(rect.width) * pixelRatio) || options.width || 700
			const chartHeight = Math.floor(uni.upx2px(rect.height) * pixelRatio) || options.height || 400
			const chart = new uCharts({
				type: 'line',
				context: ctx,
				width: chartWidth,
				height: chartHeight,
				categories: chartData.categories,
				series: chartData.series,
				animation: true,
				background: 'none',
				color: chartData.series.map(s => s.color),
				padding: isTrendChart ? [20, 10,10, 10] : [20, 10, 0, 10],
				enableScroll: false,
				legend: opts.legend,
				xAxis: opts.xAxis,
				yAxis: opts.yAxis,
				extra: opts.extra
			})
		}).exec()
	},
	
	// 绘制柱状图
	drawColumnChart(vueInstance, canvasId, categories, series, options = {}) {
		if (!categories || categories.length === 0 || !series || series.length === 0) {
			return
		}
		
		const chartData = {
			categories: categories,
			series: series.map((s, index) => ({
				name: s.name || `系列${index + 1}`,
				data: s.data,
				color: s.color || ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'][index]
			}))
		}
		
		const opts = {
			type: 'column',
			fontSize: 10,
			dataLabel: true,
			legend: {
				show: false
			},
			xAxis: {
				disableGrid: false,
				itemCount: categories.length > 12 ? 12 : categories.length
			},
			yAxis: {
				gridType: 'dash',
				dashLength: 2,
				format: (val) => {
					return val >= 10000 ? (val / 10000).toFixed(1) + '万' : val.toString()
				}
			},
			extra: {
				column: {
					type: 'group',
					width: 0.6,
					activeBgColor: '#000000',
					activeBgOpacity: 0.08
				},
				tooltip: {
					showBox: true,
					showArrow: true,
					showCategory: true
				}
			}
		}
		
		const query = uni.createSelectorQuery().in(vueInstance)
		query.select(`#${canvasId}`).boundingClientRect((rect) => {
			if (!rect || !rect.width || !rect.height) {
				console.warn(`图表容器 ${canvasId} 尺寸获取失败`, rect)
				return
			}
			const ctx = uni.createCanvasContext(canvasId, vueInstance)
			const systemInfo = uni.getSystemInfoSync()
			const pixelRatio = systemInfo.pixelRatio || 1
			const chartWidth = Math.floor(uni.upx2px(rect.width) * pixelRatio) || options.width || 700
			const chartHeight = Math.floor(uni.upx2px(rect.height) * pixelRatio) || options.height || 400
			const chart = new uCharts({
				type: 'column',
				context: ctx,
				width: chartWidth,
				height: chartHeight,
				categories: chartData.categories,
				series: chartData.series,
				animation: true,
				background: 'none',
				color: chartData.series.map(s => s.color),
				padding: [20, 10, 0, 10],
				enableScroll: false,
				legend: opts.legend,
				xAxis: opts.xAxis,
				yAxis: opts.yAxis,
				extra: opts.extra
			})
		}).exec()
	},
	
	// 绘制饼图
	drawPieChart(vueInstance, canvasId, data, options = {}) {
		if (!data || data.length === 0) {
			return
		}
		
		const chartData = {
			series: [{
				data: data.map(item => ({
					name: item.name,
					value: item.value,
					color: item.color
				}))
			}]
		}
		
		const opts = {
			type: 'pie',
			fontSize: 10,
			dataLabel: true,
			legend: {
				show: false
			},
			extra: {
				pie: {
					activeOpacity: 0.5,
					activeRadius: 10,
					offsetAngle: 0,
					labelWidth: 15,
					border: true,
					borderWidth: 3,
					borderColor: '#FFFFFF',
					ringWidth: 30
				},
				tooltip: {
					showBox: true,
					showArrow: true
				}
			}
		}
		
		const query = uni.createSelectorQuery().in(vueInstance)
		query.select(`#${canvasId}`).boundingClientRect((rect) => {
			if (!rect || !rect.width || !rect.height) {
				console.warn(`图表容器 ${canvasId} 尺寸获取失败`, rect)
				return
			}
			const ctx = uni.createCanvasContext(canvasId, vueInstance)
			const systemInfo = uni.getSystemInfoSync()
			const pixelRatio = systemInfo.pixelRatio || 1
			const chartWidth = Math.floor(uni.upx2px(rect.width) * pixelRatio) || options.width || 400
			const chartHeight = Math.floor(uni.upx2px(rect.height) * pixelRatio) || options.height || 400
			const chart = new uCharts({
				type: 'pie',
				context: ctx,
				width: chartWidth,
				height: chartHeight,
				series: chartData.series,
				animation: true,
				background: 'none',
				color: chartData.series[0].data.map(d => d.color),
				padding: 0,
				enableScroll: false,
				legend: opts.legend,
				extra: opts.extra
			})
		}).exec()
	},
	
	// 绘制雷达图
	drawRadarChart(vueInstance, canvasId, indicators, data, options = {}) {
		if (!indicators || indicators.length === 0 || !data || data.length === 0) {
			return
		}
		
		const chartData = {
			categories: indicators.map(ind => ind.name),
			series: [{
				name: data.name || '数据',
				data: indicators.map(ind => {
					const indicatorName = ind.name
					return data.value.find(item => item.name === indicatorName)?.value || 0
				}),
				color: data.color || '#409EFF'
			}]
		}
		
		const opts = {
			type: 'radar',
			fontSize: 10,
			dataLabel: true,
			legend: {
				show: false
			},
			extra: {
				radar: {
					gridType: 'radar',
					gridCount: 4,
					opacity: 0.2,
					labelOffset: 10,
					gridColor: 'rgba(64, 158, 255, 0.2)',
					gridBorderColor: 'rgba(64, 158, 255, 0.3)'
				},
				tooltip: {
					showBox: true,
					showArrow: true
				}
			}
		}
		
		const query = uni.createSelectorQuery().in(vueInstance)
		query.select(`#${canvasId}`).boundingClientRect((rect) => {
			if (!rect || !rect.width || !rect.height) {
				console.warn(`图表容器 ${canvasId} 尺寸获取失败`, rect)
				return
			}
			const ctx = uni.createCanvasContext(canvasId, vueInstance)
			const systemInfo = uni.getSystemInfoSync()
			const pixelRatio = systemInfo.pixelRatio || 1
			const chartWidth = Math.floor(uni.upx2px(rect.width) * pixelRatio) || options.width || 400
			const chartHeight = Math.floor(uni.upx2px(rect.height) * pixelRatio) || options.height || 400
			const chart = new uCharts({
				type: 'radar',
				context: ctx,
				width: chartWidth,
				height: chartHeight,
				categories: chartData.categories,
				series: chartData.series,
				animation: true,
				background: 'none',
				color: [chartData.series[0].color],
				padding: [15, 15, 0, 15],
				enableScroll: false,
				legend: opts.legend,
				extra: opts.extra
			})
		}).exec()
	},
	
	// 绘制漏斗图
	drawFunnelChart(vueInstance, canvasId, data, options = {}) {
		if (!data || data.length === 0) {
			return
		}
		
		// uCharts 漏斗图数据格式：series 中的 data 应该是对象数组
		const sortedData = [...data].sort((a, b) => (b.value || 0) - (a.value || 0))
		
		const chartData = {
			series: [{
				data: sortedData.map(item => ({
					name: item.name || '',
					centerText: String(item.value || 0),
					value: Number(item.value) || 0
				}))
			}]
		}
		
		const opts = {
			type: 'funnel',
			fontSize: 10,
			dataLabel: true,
			padding: [15, 15, 0, 15],
			enableScroll: false,
			color: sortedData.map(item => item.color),
			extra: {
				funnel: {
					activeOpacity: 0.3,
					activeWidth: 10,
					border: true,
					borderWidth: 2,
					borderColor: '#FFFFFF',
					fillOpacity: 1,
					labelAlign: 'right'
				},
				tooltip: {
					showBox: true,
					showArrow: true
				}
			}
		}
		
		const query = uni.createSelectorQuery().in(vueInstance)
		query.select(`#${canvasId}`).boundingClientRect((rect) => {
			if (!rect || !rect.width || !rect.height) {
				console.warn(`图表容器 ${canvasId} 尺寸获取失败`, rect)
				return
			}
			const ctx = uni.createCanvasContext(canvasId, vueInstance)
			const systemInfo = uni.getSystemInfoSync()
			const pixelRatio = systemInfo.pixelRatio || 1
			const chartWidth = Math.floor(uni.upx2px(rect.width) * pixelRatio) || options.width || 700
			const chartHeight = Math.floor(uni.upx2px(rect.height) * pixelRatio) || options.height || 500
			const chart = new uCharts({
				type: 'funnel',
				context: ctx,
				width: chartWidth,
				height: chartHeight,
				series: chartData.series,
				animation: true,
				background: 'none',
				color: opts.color,
				padding: opts.padding,
				enableScroll: opts.enableScroll,
				extra: opts.extra
			})
		}).exec()
	}
}

export default {
	data() {
		return {
			loading: false,
			screenshotLoading: false, // 截图加载状态
			showScreenshotBtn: true, // 是否显示截图按钮
			selectedMonth: '',
			trendType: 'day', // month/day/week
			coachRankType: 'billing', // billing/consume/refund
			pageScrollTop: 0, // 页面滚动位置
			
			// 会员详情弹窗
			showMemberDetailModal: false,
			detailModalType: '', // total/active/remaining/sleep
			
			// 核心KPI数据
			kpiData: {},
			
			// 会员统计数据
			memberStatistics: {
				totalMembers: 0,
				newMembers: 0,
				newMembersLastMonth: 0,
				active_0_3: 0,
				active_4_59: 0,
				activeMembers: 0,
				activeRate: 0,
				activeRate30: 0,
				totalRemainingAmount: 0,
				avgRemainingAmount: 0,
				topRemainingMemberId: '',
				topRemainingMemberName: '',
				topRemainingAmount: 0,
				topBillingMemberId: '',
				topBillingMemberName: '',
				topBillingAmount: 0,
				topConsumeMemberId: '',
				topConsumeMemberName: '',
				topConsumeAmount: 0,
				totalSleepMembers: 0,
				sleep_60_89: 0,
				sleep_90_179: 0,
				sleep_180_359: 0,
				sleep_360_plus: 0,
				beautyMembers: 0,
				medicalMembers: 0,
				techMembers: 0,
				educationMembers: 0
			},
			memberTypeDistribution: [], // 会员类型分布
			customerVisitFrequencyData: [], // 客户到店频次数据
			
			// 趋势数据
			trendData: [],
			
			// 排行榜数据
			storeRanking: [],
			coachRankings: {
				billing: [],
				consume: [],
				refund: []
			},
			goldTriangleRankings: [],
			
			// 品项数据
			consumeItemTop10: [],
			billingItemTop10: [],
			
			// 拓客漏斗数据
			tkStatisticsData: null,
			
			// 会员类型分布图表数据
			memberTypeChartData: {},
			memberTypeChartOpts: {
				color: ["#F56C6C", "#67C23A", "#409EFF", "#E6A23C"],
				padding: [15, 15, 0, 15],
				dataLabel: false,
				legend: {
					show: false
				},
				extra: {
					pie: {
						activeOpacity: 0.5,
						activeRadius: 10,
						offsetAngle: 0,
						labelWidth: 15,
						border: true,
						borderWidth: 3,
						borderColor: '#FFFFFF',
						ringWidth: 30
					},
					tooltip: {
						showBox: true,
						showArrow: true,
						format: (item) => {
							return item.name + ': ' + (item.data || 0) + '人'
						}
					}
				}
			},
			// 会员价值分层图表数据
			memberCategoryChartData: {},
			memberCategoryChartOpts: {
				color: ["#409EFF"],
				padding: [0, 0, 0, 0],
				dataLabel: false,
				legend: {
					show: false
				},
				extra: {
					radar: {
						gridType: 'radar',
						gridCount: 4,
						opacity: 0.2,
						labelOffset: 0,
						gridColor: 'rgba(64, 158, 255, 0.2)',
						gridBorderColor: 'rgba(64, 158, 255, 0.3)'
					},
					tooltip: {
						showBox: true,
						showArrow: true,
						format: (item) => {
							return item.name + ': ' + (item.data || 0) + '人'
						}
					}
				}
			},
			// 经营效能趋势图表数据
			trendChartData: {},
			trendChartOpts: {
				color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4", "#ea7ccc"],
				padding: [15, 10, 0, 15],
				enableScroll: true,
				dataLabel: false,
				dataPointShape: true,
				legend: {},
				xAxis: {
					disableGrid: true,
					scrollShow: true,
					itemCount: 4
				},
				yAxis: {
					gridType: "dash",
					dashLength: 2,
					format: (val) => {
						return val >= 10000 ? (val / 10000).toFixed(1) + '万' : val.toString()
					}
				},
				extra: {
					line: {
						type: "straight",
						width: 2,
						activeType: "hollow"
					},
					tooltip: {
						showBox: true,
						showArrow: true,
						showCategory: true,
						format: (item, category) => {
							const val = item.data >= 10000 ? (item.data / 10000).toFixed(1) + '万' : item.data.toString()
							return category + '\n' + item.name + ': ' + val
						}
					}
				}
			},
			// 客户活跃度分析图表数据
			visitFrequencyChartData: {},
			visitFrequencyChartOpts: {
				color: ["#409EFF"],
				padding: [20, 10, 0, 10],
				dataLabel: true,
				legend: {
					show: false
				},
				xAxis: {
					disableGrid: false,
					itemCount: 8
				},
				yAxis: {
					gridType: 'dash',
					dashLength: 2,
					format: (val) => {
						return val >= 10000 ? (val / 10000).toFixed(1) + '万' : val.toString()
					}
				},
				extra: {
					column: {
						type: 'group',
						width: 20,
						activeBgColor: '#000000',
						activeBgOpacity: 0.08
					},
					tooltip: {
						showBox: true,
						showArrow: true,
						showCategory: true,
						format: (item, category) => {
							return category + '\n' + item.name + ': ' + (item.data || 0) + '人'
						}
					}
				}
			},
			// 客户获取转化链图表数据
			funnelChartData: {},
			funnelChartOpts: {
				color: ["#409EFF", "#67C23A", "#E6A23C", "#F56C6C"],
				padding: [15, 15, 0, 15],
				dataLabel: true,
				extra: {
					funnel: {
						activeOpacity: 0.3,
						activeWidth: 10,
						border: true,
						borderWidth: 2,
						borderColor: '#FFFFFF',
						fillOpacity: 1,
						labelAlign: 'right'
					},
					tooltip: {
						showBox: true,
						showArrow: true,
						format: (item) => {
							return item.name + ': ' + (item.data || 0)
						}
					}
				}
			}
		}
	},
	computed: {
		selectedMonthText() {
			if (!this.selectedMonth) return '请选择月份'
			const date = new Date(this.selectedMonth)
			return `${date.getFullYear()}年${String(date.getMonth() + 1).padStart(2, '0')}月`
		},
		// 6大核心KPI列表
		kpiList() {
			const d = this.kpiData || {}
			const tkCount = (this.tkStatisticsData && this.tkStatisticsData.TkCount) ? this.tkStatisticsData.TkCount : 0
			return [
				{
					tooltip: '本月现金业绩，不包含退款业绩',
					key: 'billing',
					label: '开单金额',
					value: this.formatMoney(d.TotalBillingAmount),
					raw: d.TotalBillingAmount || 0,
					type: 'green',
					isMoney: true
				},
				{
					tooltip: '实际退卡金额',
					key: 'refund',
					label: '退卡',
					value: this.formatMoney(d.TotalRefundAmount),
					raw: d.TotalRefundAmount || 0,
					type: 'red',
					isMoney: true
				},
				{
					tooltip: '',
					key: 'tk',
					label: '人头数',
					value: tkCount,
					raw: tkCount,
					type: 'light-blue',
					isPercent: false,
					unit: '人头'
				},
				{
					tooltip: '',
					key: 'visit',
					label: '人次数',
					value: 0,
					raw: 0,
					type: 'purple',
					isPercent: false,
					unit: '人次'
				},
				{
					tooltip: '',
					key: 'consume',
					label: '消耗金额',
					value: this.formatMoney(d.TotalConsumeAmount),
					raw: d.TotalConsumeAmount || 0,
					type: 'light-blue',
					isMoney: true
				},
				{
					tooltip: '',
					key: 'manual',
					label: '手工费',
					value: this.formatMoney(0),
					raw: 0,
					type: 'orange',
					isMoney: true
				},
				{
					tooltip: '',
					key: 'item',
					label: '项目数',
					value: 0,
					raw: 0,
					type: 'pink',
					isPercent: false
				}
			]
		},
		// 上方4个KPI（2x2布局）
		kpiListTop() {
			return this.kpiList.slice(0, 4)
		},
		// 下方3个KPI（1x3布局）
		kpiListBottom() {
			return this.kpiList.slice(4, 7)
		},
		// 健康师排行榜当前类型
		coachRanking() {
			const list = this.coachRankings[this.coachRankType] || []
			const max = list.length > 0 ? Math.max(...list.map(i => (i.Amount || 1)), 1) : 100
			return list.map(item => ({
				...item,
				Percent: Math.min(100, Math.round((item.Amount / max) * 100))
			})).slice(0, 10)
		},
		// 金三角排行榜Top10
		goldTriangleRankingTop10() {
			if (!this.goldTriangleRankings || this.goldTriangleRankings.length === 0) {
				return []
			}
			return [...this.goldTriangleRankings]
				.sort((a, b) => (b.F_TotalPerformance || b.TotalPerformance || 0) - (a.F_TotalPerformance || a.TotalPerformance || 0))
				.slice(0, 10)
				.map(item => ({
					GoldTriangleName: item.F_GoldTriangleName || item.GoldTriangleName || '未知',
					TotalPerformance: item.F_TotalPerformance || item.TotalPerformance || 0
				}))
		},
		// 详情弹窗标题
		detailModalTitle() {
			const titleMap = {
				total: '总会员数',
				active: '活跃会员',
				remaining: '剩余权益',
				sleep: '沉睡会员'
			}
			return titleMap[this.detailModalType] || '会员'
		},
		// 详情弹窗数据
		detailModalData() {
			const ms = this.memberStatistics
			const dataMap = {
				total: [
					{ label: '总会员数', value: this.formatNumber(ms.totalMembers) },
					{ label: '本月新增', value: this.formatNumber(ms.newMembers) },
					...(ms.newMembersLastMonth > 0 ? [{ label: '上月新增', value: this.formatNumber(ms.newMembersLastMonth) }] : [])
				],
				active: [
					{ label: '活跃会员总数', value: this.formatNumber(ms.activeMembers) },
					{ label: '活跃(≤3天)', value: this.formatNumber(ms.active_0_3) },
					{ label: '常到店(4-59天)', value: this.formatNumber(ms.active_4_59) },
					{ label: '60天活跃率', value: ms.activeRate + '%' },
					{ label: '30天活跃率', value: ms.activeRate30 + '%' }
				],
				remaining: [
					{ label: '总剩余权益', value: '￥' + this.formatMoney(ms.totalRemainingAmount) },
					{ label: '人均剩余权益', value: this.formatMoney(ms.avgRemainingAmount) + '元' },
					...(ms.topRemainingAmount > 0 ? [{ label: '最高剩余权益', value: (ms.topRemainingMemberName || '无') + ' ￥' + this.formatMoney(ms.topRemainingAmount) }] : []),
					...(ms.topBillingAmount > 0 ? [{ label: '本月开单最高', value: (ms.topBillingMemberName || '无') + ' ￥' + this.formatMoney(ms.topBillingAmount) }] : []),
					...(ms.topConsumeAmount > 0 ? [{ label: '本月消耗最高', value: (ms.topConsumeMemberName || '无') + ' ￥' + this.formatMoney(ms.topConsumeAmount) }] : [])
				],
				sleep: [
					{ label: '沉睡会员总数', value: this.formatNumber(ms.totalSleepMembers) },
					{ label: '60-89天', value: this.formatNumber(ms.sleep_60_89) },
					{ label: '90-179天', value: this.formatNumber(ms.sleep_90_179) },
					{ label: '180-359天', value: this.formatNumber(ms.sleep_180_359) },
					{ label: '360天+', value: this.formatNumber(ms.sleep_360_plus) }
				]
			}
			return dataMap[this.detailModalType] || []
		}
	},
	onLoad() {
		// 默认选择当前月份
		const now = new Date()
		this.selectedMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`
		this.search()
	},
	// 组件挂载时调用（作为组件使用时）
	mounted() {
		// this.init()
	},
	onPullDownRefresh() {
		this.search().finally(() => {
			uni.stopPullDownRefresh()
		})
	},
	onPageScroll(e) {
		this.pageScrollTop = e.scrollTop || 0
	},
	methods: {
		// 初始化方法（供父组件调用）
		init() {
			// 默认选择当前月份
			const now = new Date()
			this.selectedMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`
			this.search()
		},
		// 月份选择变化
		onMonthChange(e) {
			this.selectedMonth = e.detail.value
			this.search()
		},
		// 切换趋势类型
		switchTrendType(type) {
			this.trendType = type
			this.search()
		},
		// 切换健康师排行类型
		switchCoachRankType(type) {
			this.coachRankType = type
		},
		// 主搜索方法
		async search() {
			try {
				this.loading = true
				
				// 格式化月份
				const statisticsMonth = this.selectedMonth.replace(/-/, '')
				const year = parseInt(this.selectedMonth.substring(0, 4))
				const month = parseInt(this.selectedMonth.substring(5, 7))
				const startDate = new Date(year, month - 1, 1)
				const endDate = new Date(year, month, 0, 23, 59, 59)
				
				const startTime = this.formatDateTime(startDate)
				const endTime = this.formatDateTime(endDate)
				
				// 并行加载所有数据
				await Promise.all([
					this.loadKPIs({ startTime, endTime }),
					this.loadTrends({ statisticsMonth, trendType: this.trendType }),
					this.loadTkFunnel({ startTime, endTime }),
					this.loadRankings({ statisticsMonth, startTime, endTime }),
					this.loadInsights({ startTime, endTime }),
					this.loadMemberStatistics({ statisticsMonth })
				])
				
			} catch (error) {
				console.error('加载数据失败:', error)
				uni.showToast({
					title: '网络错误，请重试',
					icon: 'none'
				})
			} finally {
				this.loading = false
			}
		},
		// 加载KPI数据
		async loadKPIs(p) {
			try {
				const res = await this.API.getBusinessStatistics({
					startTime: p.startTime,
					endTime: p.endTime,
					storeIds: []
				})
				
				if (res.code === 200 && res.data) {
					const data = res.data
					this.kpiData = {
						TotalBillingAmount: data.TotalBillingAmount || 0,
						TotalConsumeAmount: data.TotalConsumeAmount || 0,
						CompletedBillingAmount: (data.TotalBillingAmount || 0) - (data.TotalRefundAmount || 0),
						BillingCompletionRate: data.BillingCompletionRate || 0,
						TargetBillingAmount: data.TargetBillingAmount || 0,
						TotalRefundAmount: data.TotalRefundAmount || 0
					}
				}
			} catch (error) {
				console.error('加载KPI数据失败:', error)
			}
		},
		// 加载趋势数据
		async loadTrends(p) {
			try {
				// 根据趋势类型构建参数
				let params = {}
				if (p.trendType === 'month') {
					// 最近12个月
					const startMonth = this.getMonthsAgo(11, p.statisticsMonth)
					params = {
						startMonth: startMonth,
						endMonth: p.statisticsMonth,
						periodType: 'month',
						storeIds: []
					}
				} else if (p.trendType === 'day') {
					// 本月按天
					const dateRange = this.getMonthDateRange(p.statisticsMonth)
					params = {
						startMonth: dateRange.startDate,
						endMonth: dateRange.endDate,
						periodType: 'day',
						storeIds: []
					}
				} else if (p.trendType === 'week') {
					// 最近4周
					const dateRange = this.getMonthDateRange(p.statisticsMonth)
					const weekStart = this.getDaysAgo(27, dateRange.startDate)
					params = {
						startMonth: weekStart,
						endMonth: dateRange.endDate,
						periodType: 'week',
						storeIds: []
					}
				}
				
				const res = await this.API.getStorePerformanceTrend(params)
				
				if (res.code === 200 && res.data) {
					let data = res.data.Data || res.data || []
					if (res.data.Success) {
						data = res.data.Data || []
					}
					
					// 处理趋势数据
					const allData = []
					if (Array.isArray(data)) {
						data.forEach(store => {
							if (store && store.Data && Array.isArray(store.Data)) {
								store.Data.forEach(item => {
									if (item && item.Month) {
										allData.push({
											Date: item.Month,
											BillingAmount: parseFloat(item.TotalPerformance || 0),
											ConsumeAmount: parseFloat(item.ConsumeAmount || 0)
										})
									}
								})
							}
						})
					}
					
					// 按日期分组汇总
					const grouped = {}
					allData.forEach(item => {
						if (!grouped[item.Date]) {
							grouped[item.Date] = { Date: item.Date, BillingAmount: 0, ConsumeAmount: 0 }
						}
						grouped[item.Date].BillingAmount += item.BillingAmount
						grouped[item.Date].ConsumeAmount += item.ConsumeAmount
					})
					
					this.trendData = Object.values(grouped).sort((a, b) => a.Date.localeCompare(b.Date))
					
					// 渲染图表
					this.$nextTick(() => {
						this.drawTrendChart()
					})
				}
			} catch (error) {
				console.error('加载趋势数据失败:', error)
			}
		},
		// 加载拓客漏斗数据
		async loadTkFunnel(p) {
			try {
				const res = await this.API.getTkStatistics({
					startTime: p.startTime,
					endTime: p.endTime,
					storeId: []
				})
				
				if (res.code === 200 && res.data) {
					this.tkStatisticsData = res.data
					// 绘制漏斗图
					this.$nextTick(() => {
						this.drawFunnelChart()
					})
				}
			} catch (error) {
				console.error('加载拓客漏斗数据失败:', error)
			}
		},
		// 加载排行榜数据
		async loadRankings(p) {
			try {
				const [store, bill, cons, refu, gold] = await Promise.all([
					this.API.getStorePerformanceRanking({
						statisticsMonth: p.statisticsMonth,
						topCount: 10
					}),
					this.API.getHealthCoachBillingRanking({
						startTime: p.startTime,
						endTime: p.endTime,
						storeIds: []
					}),
					this.API.getHealthCoachConsumeRanking({
						startTime: p.startTime,
						endTime: p.endTime,
						storeIds: []
					}),
					this.API.getHealthCoachRefundRanking({
						startTime: p.startTime,
						endTime: p.endTime,
						storeIds: []
					}),
					this.API.getGoldTrianglePerformanceRanking({
						statisticsMonth: p.statisticsMonth,
						topCount: 10
					})
				])
				
				// 处理门店排行榜
				if (store.code === 200 && store.data) {
					let storeData = store.data.Data || store.data || []
					if (store.data.Success) {
						storeData = store.data.Data || []
					}
					this.storeRanking = storeData.map(item => ({
						StoreId: item.StoreId,
						StoreName: item.StoreName,
						TotalPerformance: item.TotalPerformance || 0
					}))
				}
				
				// 处理健康师排行榜
				this.coachRankings.billing = this.parseCoachRanking(bill, 'BillingPerformance')
				this.coachRankings.consume = this.parseCoachRanking(cons, 'ConsumePerformance')
				this.coachRankings.refund = this.parseCoachRanking(refu, 'RefundPerformance')
				
				// 处理金三角排行榜
				if (gold.code === 200 && gold.data) {
					let goldData = gold.data.Data || gold.data || []
					if (gold.data.Success) {
						goldData = gold.data.Data || []
					}
					this.goldTriangleRankings = goldData.map(item => ({
						F_GoldTriangleName: item.GoldTriangleName,
						F_TotalPerformance: item.TotalPerformance || 0
					}))
				}
			} catch (error) {
				console.error('加载排行榜数据失败:', error)
			}
		},
		// 解析健康师排行榜数据
		parseCoachRanking(res, performanceKey) {
			if (res.code === 200 && res.data) {
				let data = res.data.Data || res.data || []
				if (res.data.Success) {
					data = res.data.Data || []
				}
				return data.map(i => ({
					HealthCoachName: i.HealthCoachName || i.Name || '未知',
					Amount: i[performanceKey] || i.Performance || 0
				}))
			}
			return []
		},
		// 加载洞察数据（到店频次、品项统计）
		async loadInsights(p) {
			try {
				const [freq, item] = await Promise.all([
					this.API.getCustomerVisitFrequency({
						startTime: p.startTime,
						endTime: p.endTime,
						storeIds: []
					}),
					this.API.getItemStatistics({
						startTime: p.startTime,
						endTime: p.endTime,
						storeIds: []
					})
				])
				
				// 处理客户到店频次数据
				if (freq.code === 200 && freq.data) {
					const raw = Array.isArray(freq.data) ? freq.data : (freq.data.Data || [])
					this.customerVisitFrequencyData = raw.map(item => ({
						VisitCount: item.VisitCount || 0,
						CustomerCount: item.CustomerCount || 0
					}))
					
					// 渲染到店频次图表
					this.$nextTick(() => {
						this.drawVisitFrequencyChart()
					})
				}
				
				// 处理品项统计数据
				if (item.code === 200 && item.data) {
					const raw = Array.isArray(item.data) ? item.data : (item.data.Data || [])
					
					// 消耗品项TOP10
					const consumeMax = raw.length ? Math.max(...raw.map(i => (i.ConsumeAmount || 0)), 1) : 100
					this.consumeItemTop10 = raw
						.filter(i => (i.ConsumeAmount || 0) > 0)
						.sort((a, b) => (b.ConsumeAmount || 0) - (a.ConsumeAmount || 0))
						.slice(0, 10)
						.map(i => ({
							ItemName: i.ItemName || '未知品项',
							Amount: i.ConsumeAmount || 0,
							Percent: Math.round(((i.ConsumeAmount || 0) / consumeMax) * 100)
						}))
					
					// 开单品项TOP10
					const billingMax = raw.length ? Math.max(...raw.map(i => (i.BillingAmount || 0)), 1) : 100
					this.billingItemTop10 = raw
						.filter(i => (i.BillingAmount || 0) > 0)
						.sort((a, b) => (b.BillingAmount || 0) - (a.BillingAmount || 0))
						.slice(0, 10)
						.map(i => ({
							ItemName: i.ItemName || '未知品项',
							Amount: i.BillingAmount || 0,
							Percent: Math.round(((i.BillingAmount || 0) / billingMax) * 100)
						}))
				}
			} catch (error) {
				console.error('加载洞察数据失败:', error)
			}
		},
		// 加载会员统计数据
		async loadMemberStatistics(p) {
			try {
				const res = await this.API.getDashboardData({
					statisticsMonth: p.statisticsMonth
				})
				
				if (res.code === 200 && res.data) {
					let data = null
					if (res.data.Success && res.data.Data) {
						data = res.data.Data
					} else if (res.data) {
						data = res.data
					}
					
					if (data && data.MemberStatistics) {
						const ms = data.MemberStatistics
						const active_0_3 = ms.ActiveMembers0_3 || 0
						const active_4_59 = ms.ActiveMembers4_59 || 0
						const totalMembers = ms.TotalMembers || 0
						const active30 = ms.ActiveMembers || 0
						const active60 = active_0_3 + active_4_59
						const activeRate60 = totalMembers > 0 ? Math.round((active60 / totalMembers) * 10000) / 100 : 0
						const activeRate30 = totalMembers > 0 ? Math.round((active30 / totalMembers) * 10000) / 100 : 0
						
						this.memberStatistics = {
							totalMembers,
							newMembers: ms.NewMembersThisMonth || 0,
							newMembersLastMonth: ms.NewMembersLastMonth || 0,
							active_0_3,
							active_4_59,
							activeMembers: active60,
							activeRate: activeRate60,
							activeRate30,
							totalRemainingAmount: ms.TotalRemainingAmount || 0,
							avgRemainingAmount: ms.AvgRemainingAmount || 0,
							topRemainingMemberId: ms.TopRemainingMemberId || '',
							topRemainingMemberName: ms.TopRemainingMemberName || '',
							topRemainingAmount: ms.TopRemainingAmount || 0,
							topBillingMemberId: ms.TopBillingMemberId || '',
							topBillingMemberName: ms.TopBillingMemberName || '',
							topBillingAmount: ms.TopBillingAmount || 0,
							topConsumeMemberId: ms.TopConsumeMemberId || '',
							topConsumeMemberName: ms.TopConsumeMemberName || '',
							topConsumeAmount: ms.TopConsumeAmount || 0,
							totalSleepMembers: ms.TotalSleepMembers || 0,
							sleep_60_89: ms.SleepMembers60_89 || 0,
							sleep_90_179: ms.SleepMembers90_179 || 0,
							sleep_180_359: ms.SleepMembers180_359 || 0,
							sleep_360_plus: ms.SleepMembers360Plus || 0,
							beautyMembers: ms.BeautyMembers || 0,
							medicalMembers: ms.MedicalMembers || 0,
							techMembers: ms.TechMembers || 0,
							educationMembers: ms.EducationMembers || 0
						}
						this.memberTypeDistribution = ms.MemberTypeDistribution || []
						
						// 等待DOM更新后渲染图表
						this.$nextTick(() => {
							this.drawMemberTypeChart()
							this.drawMemberCategoryChart()
						})
					}
				}
			} catch (error) {
				console.error('加载会员统计数据失败:', error)
			}
		},
		// 格式化趋势日期
		formatTrendDate(dateStr) {
			if (!dateStr) return ''
			// 如果是YYYYMM格式
			if (dateStr.length === 6) {
				const year = dateStr.substring(0, 4)
				const month = dateStr.substring(4, 6)
				return `${year}-${month}`
			}
			// 如果是YYYY-MM-DD格式
			if (dateStr.length === 10) {
				return dateStr
			}
			return dateStr
		},
		// 处理KPI点击
		handleKpiClick(kpi) {
			// KPI穿透功能，可以后续实现
			uni.showToast({
				title: kpi.label ,
				icon: 'none'
			})
		},
		// 处理门店点击
		handleStoreClick(store) {
			// 门店详情功能
			uni.showToast({
				title: store.StoreName,
				icon: 'none'
			})
		},
		// 获取KPI图标名称（使用uview图标）
		getKpiIconName(key) {
			const iconMap = {
				billing: 'grid',
				consume: 'star',
				net: 'red-packet',
				target: 'red-packet',
				tk: 'account',
				refund: 'warning',
				visit: 'account',
				manual: 'star',
				item: 'grid'
			}
			return iconMap[key] || 'chart'
		},
		// 获取KPI图标颜色
		getKpiIconColor(type) {
			const colorMap = {
				primary: '#1976d2',
				success: '#388e3c',
				warning: '#f57c00',
				info: '#7b1fa2',
				error: '#d32f2f'
			}
			return colorMap[type] || '#1976d2'
		},
		// 获取KPI颜色
		getKpiColor(type) {
			const colorMap = {
				primary: '#409EFF',
				success: '#67C23A',
				warning: '#E6A23C',
				info: '#909399',
				error: '#F56C6C',
				danger: '#F56C6C'
			}
			return colorMap[type] || '#409EFF'
		},
		// 格式化数字
		formatNumber(num) {
			if (num === null || num === undefined) return '0'
			if (typeof num === 'string') num = parseFloat(num)
			if (isNaN(num)) return '0'
			if (num >= 10000) {
				return (num / 10000).toFixed(2) + '万'
			}
			return num.toLocaleString()
		},
		// 格式化金额
		formatMoney(amount) {
			if (amount === null || amount === undefined) return '0.00'
			if (typeof amount === 'string') amount = parseFloat(amount)
			if (isNaN(amount)) return '0.00'
			if (amount >= 10000) {
				return (amount / 10000).toFixed(2) + '万'
			}
			return amount.toFixed(2)
		},
		// 格式化百分比
		formatPercent(percent) {
			return Math.round(percent * 100) / 100
		},
		// 获取邀约率
		getTkInviteRate() {
			if (!this.tkStatisticsData || !this.tkStatisticsData.TkCount) return 0
			return (this.tkStatisticsData.YaoyCount || 0) / this.tkStatisticsData.TkCount * 100
		},
		// 获取到店率
		getInviteStoreRate() {
			if (!this.tkStatisticsData || !this.tkStatisticsData.YaoyCount) return 0
			return (this.tkStatisticsData.DdCount || 0) / this.tkStatisticsData.YaoyCount * 100
		},
		// 格式化日期时间
		formatDateTime(date) {
			const year = date.getFullYear()
			const month = String(date.getMonth() + 1).padStart(2, '0')
			const day = String(date.getDate()).padStart(2, '0')
			const hours = String(date.getHours()).padStart(2, '0')
			const minutes = String(date.getMinutes()).padStart(2, '0')
			const seconds = String(date.getSeconds()).padStart(2, '0')
			return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
		},
		// 获取月份日期范围
		getMonthDateRange(monthStr) {
			const year = parseInt(monthStr.substring(0, 4))
			const month = parseInt(monthStr.substring(4, 6))
			const startDate = new Date(year, month - 1, 1)
			const endDate = new Date(year, month, 0, 23, 59, 59)
			return {
				startDate: this.formatDateTime(startDate).split(' ')[0],
				endDate: this.formatDateTime(endDate).split(' ')[0]
			}
		},
		// 获取N个月前的月份（YYYYMM格式）
		getMonthsAgo(n, monthStr) {
			const year = parseInt(monthStr.substring(0, 4))
			const month = parseInt(monthStr.substring(4, 6))
			const date = new Date(year, month - 1 - n, 1)
			return `${date.getFullYear()}${String(date.getMonth() + 1).padStart(2, '0')}`
		},
		// 获取N天前的日期（YYYY-MM-DD格式）
		getDaysAgo(n, dateStr) {
			const date = new Date(dateStr)
			date.setDate(date.getDate() - n)
			return date.toISOString().split('T')[0]
		},
		// 初始化图表
		initChart() {
			// uCharts 不需要初始化，图表会在数据加载后自动绘制
		},
		// 保存截图
		async saveScreenshot() {
			// 隐藏截图按钮
			this.showScreenshotBtn = false
			// 显示加载提示
			uni.showLoading({
				title: '截图中'
			})
			this.screenshotLoading = true
			try {
				// 根据平台选择不同的截图方式
				// #ifdef H5
				await this.saveScreenshotH5()
				// #endif
				
				// #ifdef MP-WEIXIN
				await this.saveScreenshotMiniProgram()
				// #endif
				
				// #ifndef H5 || MP-WEIXIN
				// 其他平台的兜底处理
				await this.saveScreenshotFallback()
				// #endif
			} catch (error) {
				console.error('截图生成失败:', error)
				uni.showToast({
					title: '截图生成失败: ' + (error.message || '未知错误'),
					icon: 'none',
					duration: 3000
				})
			} finally {
				this.screenshotLoading = false
				// 隐藏加载提示
				uni.hideLoading()
				// 恢复显示截图按钮
				this.showScreenshotBtn = true
			}
		},
		// H5平台截图
		async saveScreenshotH5() {
			try {
				// 动态导入html2canvas
				const html2canvas = await import('html2canvas')
				
				// 获取要截图的容器
				let element = document.querySelector('.warpbox')
				if (!element) {
					element = document.querySelector('.page')
				}
				if (!element) {
					throw new Error('未找到要截图的内容')
				}
				
				// 等待页面完全渲染
				await new Promise(resolve => setTimeout(resolve, 1000))
				
				// 滚动到页面顶部确保所有内容可见
				window.scrollTo(0, 0)
				await new Promise(resolve => setTimeout(resolve, 500))
				
				// 临时修改背景色为白色，确保截图效果
				const originalBg = element.style.background
				element.style.background = '#ffffff'
				
				// 等待样式生效
				await new Promise(resolve => setTimeout(resolve, 200))
				
				// 配置截图选项
				const options = {
					allowTaint: true,
					useCORS: true,
					scale: 2.0,
					backgroundColor: '#ffffff',
					logging: false,
					imageTimeout: 30000,
					scrollX: 0,
					scrollY: 0,
					onclone: function(clonedDoc) {
						clonedDoc.body.style.backgroundColor = '#ffffff'
						clonedDoc.documentElement.style.backgroundColor = '#ffffff'
					}
				}
				
				// 生成截图
				let canvas
				try {
					canvas = await html2canvas.default(element, options)
				} catch (firstError) {
					console.warn('第一次截图失败，尝试备选方案:', firstError)
					const fallbackOptions = {
						allowTaint: true,
						useCORS: true,
						scale: 2.0,
						backgroundColor: '#ffffff',
						logging: false,
						imageTimeout: 30000
					}
					canvas = await html2canvas.default(element, fallbackOptions)
				}
				
				// 转换为DataURL
				const dataUrl = canvas.toDataURL('image/png', 1.0)
				
				// 创建下载链接
				const link = document.createElement('a')
				const fileName = `集团驾驶舱_${this.selectedMonth}_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.png`
				link.download = fileName
				link.href = dataUrl
				
				// 触发下载
				document.body.appendChild(link)
				link.click()
				document.body.removeChild(link)
				
				// 恢复原始背景色
				element.style.background = originalBg
				
				uni.showToast({
					title: '截图保存成功',
					icon: 'success',
					duration: 2000
				})
			} catch (error) {
				console.error('H5截图失败:', error)
				throw error
			}
		},
		// 微信小程序截图
		async saveScreenshotMiniProgram() {
			try {
				// 获取系统信息
				const systemInfo = uni.getSystemInfoSync()
				
				// 使用页面截图API
				uni.canvasToTempFilePath({
					canvasId: 'screenshot-canvas',
					success: (res) => {
						// 保存到相册
						uni.saveImageToPhotosAlbum({
							filePath: res.tempFilePath,
							success: () => {
								uni.showToast({
									title: '截图已保存到相册',
									icon: 'success',
									duration: 2000
								})
							},
							fail: (err) => {
								console.error('保存到相册失败:', err)
								// 如果用户拒绝授权，提供预览
								uni.previewImage({
									urls: [res.tempFilePath],
									current: res.tempFilePath
								})
							}
						})
					},
					fail: (err) => {
						console.error('导出图片失败:', err)
						throw new Error('导出图片失败')
					}
				}, this)
			} catch (error) {
				console.error('小程序截图失败:', error)
				throw error
			}
		},
		// 兜底截图方案
		async saveScreenshotFallback() {
			await new Promise(resolve => setTimeout(resolve, 2000))
			uni.showToast({
				title: '截图功能暂不支持当前平台',
				icon: 'none',
				duration: 2000
			})
		},
		// 绘制趋势图表
		drawTrendChart() {
			if (!this.trendData || this.trendData.length === 0) {
				this.trendChartData = {}
				return
			}
			
			// 格式化日期
			const categories = this.trendData.map(item => {
				const date = item.Date
				if (!date) return ''
				
				if (this.trendType === 'month') {
					if (date.length === 6) {
						return date.substring(0, 4) + '-' + date.substring(4, 6)
					}
				} else if (this.trendType === 'day') {
					if (date.length >= 10) {
						return date.substring(5, 10) // MM-DD
					}
				} else if (this.trendType === 'week') {
					if (date.includes('-W')) {
						return date.replace('-W', ' 第') + '周'
					}
				}
				return date
			})
			
			const series = [
				{
					name: '成交额',
					data: this.trendData.map(item => parseFloat((parseFloat(item.BillingAmount || 0)).toFixed(2)))
				},
				{
					name: '服务产出',
					data: this.trendData.map(item => parseFloat((parseFloat(item.ConsumeAmount || 0)).toFixed(2)))
				}
			]
			
			// 更新图表数据
			this.trendChartData = {
				categories: categories,
				series: series
			}
		},
		// 绘制会员类型分布饼图
		drawMemberTypeChart() {
			if (!this.memberTypeDistribution || this.memberTypeDistribution.length === 0) {
				this.memberTypeChartData = {}
				return
			}
			
			const colors = ['#F56C6C', '#67C23A', '#409EFF', '#E6A23C']
			const data = this.memberTypeDistribution.map((item, index) => ({
				name: item.MemberType || '未知',
				value: item.Count || 0,
				color: colors[index % colors.length]
			}))
			
			// 更新图表数据
			this.memberTypeChartData = {
				series: [{
					data: data
				}]
			}
		},
		// 绘制会员价值分层雷达图
		drawMemberCategoryChart() {
			if (!this.memberStatistics) {
				this.memberCategoryChartData = {}
				return
			}
			
			const beautyMembers = this.memberStatistics.beautyMembers || 0
			const medicalMembers = this.memberStatistics.medicalMembers || 0
			const techMembers = this.memberStatistics.techMembers || 0
			
			const categories = ['生美会员', '医美会员', '科技部会员']
			const series = [{
				name: '会员分布',
				data: [beautyMembers, medicalMembers, techMembers]
			}]
			
			// 更新图表数据
			this.memberCategoryChartData = {
				categories: categories,
				series: series
			}
		},
		// 绘制客户活跃度分析图表
		drawVisitFrequencyChart() {
			if (!this.customerVisitFrequencyData || this.customerVisitFrequencyData.length === 0) {
				this.visitFrequencyChartData = {}
				return
			}
			
			// 排序数据（按到店次数）
			const sortedData = [...this.customerVisitFrequencyData]
				.sort((a, b) => (a.VisitCount || 0) - (b.VisitCount || 0))
				.slice(0, 8)
			
			if (sortedData.length === 0) {
				this.visitFrequencyChartData = {}
				return
			}
			
			const categories = sortedData.map(item => (item.VisitCount || 0) + '次')
			const series = [{
				name: '客户数',
				data: sortedData.map(item => item.CustomerCount || 0)
			}]
			
			// 更新图表数据
			this.visitFrequencyChartData = {
				categories: categories,
				series: series
			}
		},
		// 获取会员类型颜色
		getMemberTypeColor(index) {
			const colors = ['#F56C6C', '#67C23A', '#409EFF', '#E6A23C']
			return colors[index % colors.length]
		},
		// 绘制漏斗图
		drawFunnelChart() {
			if (!this.tkStatisticsData) {
				this.funnelChartData = {}
				return
			}
			
			const d = this.tkStatisticsData
			const funnelData = [
				{ value: d.TkCount || 0, name: '获客', color: '#409EFF' },
				{ value: d.YaoyCount || 0, name: '邀约', color: '#67C23A' },
				{ value: d.DdCount || 0, name: '到店', color: '#E6A23C' },
				{ value: d.XfCount || 0, name: '成交', color: '#F56C6C' }
			]
			
			// 更新图表数据
			this.funnelChartData = {
				series: [{
					data: funnelData.map(item => ({
						name: item.name,
						value: item.value,
						color: item.color
					}))
				}]
			}
		},
		// 打开会员详情弹窗
		openMemberDetailModal(type) {
			this.detailModalType = type
			this.showMemberDetailModal = true
		},
		// 关闭会员详情弹窗
		closeMemberDetailModal() {
			this.showMemberDetailModal = false
			this.detailModalType = ''
		}
	}
}
</script>

<style lang="scss" scoped>
.page {
	min-height: 100vh;
	background: linear-gradient(135deg, #e8f5e9 0%, #b2dfdb 100%);
	padding-bottom: 40rpx;
	font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", Arial, sans-serif;
}

.warpbox {
	padding: 0 30rpx;
	padding-top: 20rpx;
}

/* 顶部区域 */
.header-section {
	margin-bottom: 20rpx;
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 0 10rpx;
	
	.page-title {
		font-size: 36rpx;
		font-weight: bold;
		color: #1f2937;
	}
	
	.filter-box {
		display: flex;
		align-items: center;
		gap: 12rpx;
		
		.date-picker-trigger {
			display: flex;
			align-items: center;
			background: rgba(255, 255, 255, 0.6);
			backdrop-filter: blur(10px);
			padding: 8rpx 16rpx;
			border-radius: 30rpx;
			border: 1px solid rgba(255, 255, 255, 0.8);
			
			.date-text {
				font-size: 24rpx;
				color: #333;
				margin-right: 6rpx;
			}
		}
		
		.refresh-btn {
			padding: 6rpx;
			&.loading {
				animation: rotate 1s linear infinite;
			}
		}
		
		.screenshot-btn {
			display: flex;
			align-items: center;
			gap: 8rpx;
			padding: 8rpx 16rpx;
			background: rgba(64, 158, 255, 0.1);
			border-radius: 20rpx;
			transition: all 0.3s;
			
			&:active {
				background: rgba(64, 158, 255, 0.2);
				transform: scale(0.95);
			}
			
			&.loading {
				opacity: 0.6;
			}
			
			.screenshot-text {
				font-size: 24rpx;
				color: #409EFF;
			}
		}
	}
}

/* 卡片容器通用样式 - 玻璃拟态 */
.warpboxss {
	background: rgba(255, 255, 255, 0.8);
	backdrop-filter: blur(20px) saturate(180%);
	-webkit-backdrop-filter: blur(20px) saturate(180%);
	padding: 20rpx;
	border-radius: 20rpx;
	box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(255, 255, 255, 0.8) inset;
	margin-bottom: 20rpx;
	transition: all 0.3s ease;
	
	&:active {
		transform: scale(0.99);
	}
}

.warpboxs-small-title {
	display: flex;
	justify-content: space-between;
	align-items: center;
	font-size: 28rpx;
	font-weight: 600;
	color: #1f2937;
	margin-bottom: 16rpx;
	
	view:first-child {
		display: flex;
		align-items: center;
	}

	.warpboxs-small-title-line {
		background: linear-gradient(180deg, #43a047 0%, #66bb6a 100%);
		height: 26rpx;
		width: 10rpx;
		margin-right: 12rpx;
		border-radius: 18rpx;
		box-shadow:
			0 2rpx 8rpx rgba(67, 160, 71, 0.4),
			0 0 12rpx rgba(67, 160, 71, 0.3),
			inset 0 1rpx 2rpx rgba(255, 255, 255, 0.3);
	}
}

/* KPI 核心指标 */
.kpi-section {
	margin-bottom: 20rpx;
}

/* 上方4个指标 - 按照me.vue样式 */
.billing-card {
	width: 100%;
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: 24rpx;
	background: rgba(255, 255, 255, 0.7);
	backdrop-filter: blur(20px) saturate(180%);
	-webkit-backdrop-filter: blur(20px) saturate(180%);
	border-radius: 24rpx;
	box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(255, 255, 255, 0.8) inset;
	margin-bottom: 16rpx;
	box-sizing: border-box;
}

.billing-main {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: center;
	flex: 1;
	width: 100%;
	padding: 0 8rpx;
	margin-bottom: 30rpx;

}

.billing-card .stat-content {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	width: 100%;
	gap: 10rpx;
}

.billing-card .label-row {
	display: flex;
	align-items: center;
	justify-content: flex-start;
	width: 100%;
	gap: 8rpx;
}

.billing-card .card-label {
	font-size: 24rpx;
	font-weight: 500;
	color: #666;
}

.billing-card .stat-icon-small {
	width: 48rpx;
	height: 48rpx;
	border-radius: 12rpx;
	margin-right: 8rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	
	&.green { background: #4caf50; }
	&.red { background: #f44336; }
	&.light-blue { background: #42a5f5; }
	&.purple { background: #9c27b0; }
	&.orange { background: #ff9800; }
	&.pink { background: #e91e63; }
}

.billing-value {
	font-size: 38rpx;
	font-weight: bold;
	color: #1f2937;
	line-height: 1.1;
	text-align: center;
	width: 100%;
	padding: 0 30rpx;
	box-sizing: border-box;
	display: flex;
	align-items: baseline;
	justify-content: center;
	
	.currency {
		font-size: 24rpx;
		margin-right: 4rpx;
	}
	
	.value {
		font-size: 38rpx;
	}
	
	.unit {
		font-size: 24rpx;
		color: #666;
		margin-left: 4rpx;
	}
}

.billing-footer {
	display: flex;
	justify-content: space-around;
	width: 100%;
	padding-top: 30rpx;
	border-top: 1px solid rgba(0, 0, 0, 0.05);
	margin-top: auto;
}

.count-item {
	display: flex;
	align-items: center;
	gap: 8rpx;
}

.count-icon {
	width: 36rpx;
	height: 36rpx;
	border-radius: 8rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	
	&.green { background: #4caf50; }
	&.red { background: #f44336; }
	&.light-blue { background: #42a5f5; }
	&.purple { background: #9c27b0; }
	&.orange { background: #ff9800; }
	&.pink { background: #e91e63; }
}

.count-text {
	font-size: 26rpx;
	color: #666666;
	line-height: 1.5;
	display: flex;
	align-items: baseline;
	
	.count-value {
		font-size: 26rpx;
		font-weight: 500;
	}
	
	.count-unit {
		font-size: 24rpx;
		margin-left: 4rpx;
	}
}

.kpi-grid-bottom {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 16rpx;
}

.kpi-card {
	background: rgba(255, 255, 255, 0.8);
	backdrop-filter: blur(20px) saturate(180%);
	-webkit-backdrop-filter: blur(20px) saturate(180%);
	border-radius: 24rpx;
	padding:24rpx;
	// height: 200rpx;
	display: flex;
	flex-direction: column;
	justify-content: center;
	box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(255, 255, 255, 0.8) inset;
	
	.kpi-header {
		display: flex;
		align-items: center;
		margin-bottom: 16rpx;
		
		.kpi-icon-square {
			width: 50rpx;
			height: 50rpx;
			border-radius: 10rpx;
			display: flex;
			align-items: center;
			justify-content: center;
			margin-right: 12rpx;
			flex-shrink: 0;
			
			&.green { background: #4caf50; }
			&.red { background: #f44336; }
			&.light-blue { background: #42a5f5; }
			&.purple { background: #9c27b0; }
			&.orange { background: #ff9800; }
			&.pink { background: #e91e63; }
		}
		
		.kpi-label {
			font-size: 24rpx;
			color: #666;
		}
	}
	
	.kpi-value-group {
		display: flex;
		align-items: baseline;
		
		.currency { 
			font-size: 24rpx; 
			color: #333; 
			margin-right: 4rpx; 
		}
		.value { 
			font-size: 36rpx; 
			font-weight: bold; 
			color: #333; 
			letter-spacing: -1rpx; 
			flex: 1;
			text-align: center;
		}
		.unit { 
			font-size: 24rpx; 
			color: #666; 
			margin-left: 4rpx; 
		}
	}
}

/* 会员数据 */
.member-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 16rpx;
}

.member-stat-card {
	background: #fff;
	padding: 18rpx;
	border-radius: 14rpx;
	display: flex;
	align-items: flex-start;
	box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.03);
	
	.icon-circle {
		width: 56rpx;
		height: 56rpx;
		border-radius: 50%;
		display: flex;
		align-items: center;
		justify-content: center;
		margin-right: 16rpx;
		flex-shrink: 0;
	}
	
	&.blue-theme .icon-circle { background: rgba(64, 158, 255, 0.1); }
	&.green-theme .icon-circle { background: rgba(103, 194, 58, 0.1); }
	&.orange-theme .icon-circle { background: rgba(230, 162, 60, 0.1); }
	&.red-theme .icon-circle { background: rgba(245, 108, 108, 0.1); }
	
	.stat-info {
		flex: 1;
		.stat-label { font-size: 22rpx; color: #666; margin-bottom: 6rpx; }
		.stat-value { font-size: 28rpx; font-weight: bold; color: #333; margin-bottom: 6rpx; }
		.stat-value.mini { font-size: 24rpx; }
		.stat-sub { font-size: 18rpx; color: #999; line-height: 1.4; }
	}
}

/* 趋势图表 */
.trend-controls {
	.pill-switch {
		display: flex;
		background: #f5f5f5;
		border-radius: 26rpx;
		padding: 3rpx;
		
		.pill-item {
			padding: 5rpx 18rpx;
			font-size: 22rpx;
			color: #666;
			border-radius: 24rpx;
			transition: all 0.3s;
			
			&.active {
				background: #fff;
				color: #43a047;
				box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
				font-weight: 500;
			}
		}
	}
}

.chart-wrapper {
	width: 100%;
	height: 400rpx;
	position: relative;
}

.trend-chart-canvas,
.visit-frequency-chart-canvas,
.funnel-chart-canvas {
	width: 100%;
	height: 100%;
}

.trend-legend-modern {
	display: flex;
	justify-content: center;
	margin-top: 16rpx;
	
	.legend-item {
		display: flex;
		align-items: center;
		margin: 0 20rpx;
		font-size: 22rpx;
		color: #666;
		
		.dot {
			width: 10rpx;
			height: 10rpx;
			border-radius: 50%;
			margin-right: 6rpx;
			
			&.revenue { background: #43a047; }
			&.consume { background: #409EFF; }
		}
	}
}

/* 排行榜通用 */
.type-tags {
	display: flex;
	.tag-item {
		padding: 5rpx 16rpx;
		font-size: 20rpx;
		margin-left: 10rpx;
		border-radius: 18rpx;
		background: #f0f0f0;
		color: #666;
		
		&.active {
			background: #e8f5e9;
			color: #43a047;
		}
	}
}

.rank-list-modern {
	.rank-item {
		display: flex;
		align-items: center;
		padding: 18rpx 0;
		
		.rank-idx {
			width: 50rpx;
			font-size: 26rpx;
			font-weight: bold;
			color: #999;
			text-align: center;
			margin-right: 16rpx;
			
			&.rank-1 { 
				color: #FFD700; 
				font-size: 30rpx; 
				text-shadow: 0 2rpx 4rpx rgba(255, 215, 0, 0.3);
			}
			
			&.rank-2 { 
				color: #C0C0C0; 
				font-size: 30rpx; 
				text-shadow: 0 2rpx 4rpx rgba(192, 192, 192, 0.3);
			}
			
			&.rank-3 { 
				color: #CD7F32; 
				font-size: 30rpx; 
				text-shadow: 0 2rpx 4rpx rgba(205, 127, 50, 0.3);
			}
			
			&.top-3 { color: #43a047; font-size: 30rpx; }
			
			.medal-icon { width: 40rpx; height: 40rpx; }
		}
		
		.rank-avatar {
			width: 56rpx;
			height: 56rpx;
			background: #e8f5e9;
			border-radius: 50%;
			display: flex;
			align-items: center;
			justify-content: center;
			margin-right: 16rpx;
			color: #43a047;
			font-weight: bold;
			font-size: 24rpx;
		}
		
		.rank-info {
			flex: 1;
			
			.info-main {
				display: flex;
				justify-content: space-between;
				align-items: center;
				margin-bottom: 10rpx;
				
				.name { font-size: 26rpx; font-weight: 500; color: #333; }
				.value { font-size: 26rpx; font-weight: bold; color: #43a047; }
				.value.orange-value { color: #ff9800; }
			}
			
			.progress-bg {
				height: 6rpx;
				background: #f5f5f5;
				border-radius: 3rpx;
				overflow: hidden;
				
				.progress-bar {
					height: 100%;
					background: linear-gradient(90deg, #66bb6a 0%, #43a047 100%);
					border-radius: 3rpx;
					
					&.green { background: linear-gradient(90deg, #66bb6a 0%, #43a047 100%); }
					&.orange { background: linear-gradient(90deg, #ffb74d 0%, #ff9800 100%); }
				}
			}
		}
	}
}

/* 热门品项 */
.item-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 16rpx;
	
	.item-card {
		background: #fff;
		border-radius: 12rpx;
		padding: 16rpx;
		position: relative;
		overflow: hidden;
		
		.item-rank-badge {
			position: absolute;
			top: 0;
			left: 0;
			padding: 3rpx 10rpx;
			background: #f0f0f0;
			color: #999;
			font-size: 18rpx;
			border-bottom-right-radius: 12rpx;
			
			&.rank-1 { background: #ffe0b2; color: #ef6c00; }
			&.rank-2 { background: #e0f2f1; color: #00897b; }
			&.rank-3 { background: #e3f2fd; color: #1e88e5; }
		}
		
		.item-name { font-size: 24rpx; color: #333; margin-top: 20rpx; margin-bottom: 6rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 500; }
		.item-val { font-size: 24rpx; color: #43a047; font-weight: bold; margin-bottom: 10rpx; }
		.item-process { width: 100%; height: 4rpx; background: #f0f0f0; border-radius: 2rpx; .bar { height: 100%; background: #43a047; border-radius: 2rpx; } }
	}
}

/* 转化漏斗 */
.funnel-section {
	.chart-wrapper {
		width: 100%;
		height: 400rpx;
		margin-bottom: 16rpx;
	}
	
	.funnel-chart-canvas {
		width: 100%;
		height: 100%;
	}
	
	.funnel-stats {
		display: flex;
		justify-content: space-around;
		padding: 16rpx 0;
		
		.stat-mini {
			font-size: 22rpx;
			color: #666;
			
			.stat-value {
				color: #43a047;
				font-weight: 600;
				margin-left: 6rpx;
			}
		}
	}
}

@keyframes rotate {
	from { transform: rotate(0deg); }
	to { transform: rotate(360deg); }
}

/* 会员结构洞察 */
.member-chart-container {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.member-type-chart-wrapper {
	width: 100%;
	height: 480rpx;
	margin-bottom: 16rpx;
}

.member-type-chart-canvas {
	width: 100%;
	height: 100%;
}

.member-type-legend {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 16rpx;
	padding: 16rpx;
	// background: #f5f5f5;
	border-radius: 12rpx;
	width: 100%;
}

.member-type-legend .legend-item {
	display: flex;
	align-items: center;
	gap: 6rpx;
	padding: 6rpx 12rpx;
	background: #fff;
	border-radius: 8rpx;
}

.member-type-legend .legend-dot {
	width: 20rpx;
	height: 20rpx;
	border-radius: 50%;
}

.member-type-legend .legend-name {
	font-size: 22rpx;
	color: #666;
	margin-right: 6rpx;
}

.member-type-legend .legend-value {
	font-size: 22rpx;
	color: #333;
	font-weight: bold;
}

/* 会员价值分层 */
.member-category-container {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.member-category-chart-wrapper {
	width: 100%;
	height: 480rpx;
	margin-bottom: 16rpx;
}

.member-category-chart-canvas {
	width: 100%;
	height: 100%;
}

.member-category-legend {
	display: flex;
	flex-direction: row;
	gap: 12rpx;
	padding: 16rpx;
	// background: #f5f5f5;
	border-radius: 12rpx;
	width: 100%;
}

.member-category-legend .legend-item {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 8rpx;
	padding: 10rpx;
	background: #fff;
	border-radius: 8rpx;
	flex: 1;
}

.member-category-legend .legend-color {
	width: 28rpx;
	height: 28rpx;
	border-radius: 4rpx;
	flex-shrink: 0;
}

.member-category-legend .legend-text {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
}

.member-category-legend .legend-name {
	font-size: 22rpx;
	color: #666;
	margin-bottom: 3rpx;
}

.member-category-legend .legend-value {
	font-size: 24rpx;
	color: #333;
	font-weight: bold;
}

/* 客户活跃度分析 */
.visit-frequency-section {
	.chart-wrapper {
		width: 100%;
		height: 400rpx;
	}
	
	.visit-frequency-chart-canvas {
		width: 100%;
		height: 100%;
	}
}

/* 热销产品品项 */
.item-process .bar.blue {
	background: #409EFF;
}

/* 会员统计卡片点击提示 */
.stat-hint {
	font-size: 18rpx;
	color: #999;
	margin-top: 4rpx;
}

.member-stat-card {
	cursor: pointer;
	transition: all 0.3s ease;
	
	&:active {
		transform: scale(0.98);
		opacity: 0.9;
	}
}

/* 会员详情弹窗 */
.member-detail-modal {
	width: 600rpx;
	max-height: 80vh;
	background: #fff;
	border-radius: 20rpx;
	overflow: hidden;
	
	.modal-title {
		font-size: 32rpx;
		font-weight: bold;
		color: #333;
		text-align: center;
		padding: 30rpx 20rpx 20rpx;
		border-bottom: 1px solid #f0f0f0;
	}
	
	.modal-content {
		padding: 20rpx;
		max-height: 60vh;
		overflow-y: auto;
		
		.detail-item {
			display: flex;
			justify-content: space-between;
			align-items: center;
			padding: 20rpx 0;
			border-bottom: 1px solid #f5f5f5;
			
			&:last-child {
				border-bottom: none;
			}
			
			.detail-label {
				font-size: 26rpx;
				color: #666;
				flex: 1;
			}
			
			.detail-value {
				font-size: 26rpx;
				color: #333;
				font-weight: 500;
				text-align: right;
				flex: 1;
			}
		}
	}
}
</style>
