gaoluyang
4 天以前 b3af444b89aa69ab3b012c97a6298cda321c8c19
汇星与博达-指标统计页面
已添加1个文件
已修改1个文件
506 ■■■■■ 文件已修改
src/views/salesManagement/indicatorStats/index.vue 246 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/strategyControl/index.vue 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/indicatorStats/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,246 @@
<template>
  <div class="app-container indicator-stats">
    <el-card class="box-card">
      <!-- KPI æ±‡æ€» -->
      <el-row :gutter="20" class="stats-row">
        <el-col :span="6">
          <div class="stat-card">
            <div class="stat-icon" style="background: #ecf5ff;">
              <el-icon :size="30" color="#409eff"><Document /></el-icon>
            </div>
            <div class="stat-content">
              <div class="stat-value">{{ indicatorKpis.orderCount.toLocaleString() }}</div>
              <div class="stat-label">订单数量</div>
            </div>
          </div>
        </el-col>
        <el-col :span="6">
          <div class="stat-card">
            <div class="stat-icon" style="background: #f0f9ff;">
              <el-icon :size="30" color="#67c23a"><Tickets /></el-icon>
            </div>
            <div class="stat-content">
              <div class="stat-value">Â¥{{ indicatorKpis.salesAmount.toLocaleString() }}</div>
              <div class="stat-label">销售额</div>
            </div>
          </div>
        </el-col>
        <el-col :span="6">
          <div class="stat-card">
            <div class="stat-icon" style="background: #fef0f0;">
              <el-icon :size="30" color="#e6a23c"><Van /></el-icon>
            </div>
            <div class="stat-content">
              <div class="stat-value">{{ indicatorKpis.shipmentRate }}%</div>
              <div class="stat-label">发货率</div>
            </div>
          </div>
        </el-col>
        <el-col :span="6">
          <div class="stat-card">
            <div class="stat-icon" style="background: #f4f4f5;">
              <el-icon :size="30" color="#f56c6c"><Wallet /></el-icon>
            </div>
            <div class="stat-content">
              <div class="stat-value">{{ indicatorKpis.collectionRate }}%</div>
              <div class="stat-label">回款率</div>
            </div>
          </div>
        </el-col>
      </el-row>
      <!-- ç»´åº¦ç­›é€‰ -->
      <el-row :gutter="20" class="search-row">
        <el-col :span="6">
          <el-select v-model="indicatorFilter.product" placeholder="产品" clearable>
            <el-option label="全部产品" value="" />
            <el-option label="P.O 42.5普通硅酸盐水泥" value="P.O 42.5普通硅酸盐水泥" />
            <el-option label="P.S 32.5矿渣硅酸盐水泥" value="P.S 32.5矿渣硅酸盐水泥" />
            <el-option label="P.C 32.5复合硅酸盐水泥" value="P.C 32.5复合硅酸盐水泥" />
          </el-select>
        </el-col>
        <el-col :span="6">
          <el-select v-model="indicatorFilter.customer" placeholder="客户" clearable>
            <el-option label="全部客户" value="" />
            <el-option label="华东建材集团" value="华东建材集团" />
            <el-option label="长江混凝土公司" value="长江混凝土公司" />
            <el-option label="浦江水泥制品厂" value="浦江水泥制品厂" />
          </el-select>
        </el-col>
        <el-col :span="6">
          <el-select v-model="indicatorFilter.region" placeholder="区域" clearable>
            <el-option label="全部区域" value="" />
            <el-option label="华东地区" value="华东地区" />
            <el-option label="华南地区" value="华南地区" />
            <el-option label="华北地区" value="华北地区" />
          </el-select>
        </el-col>
        <el-col :span="6">
          <el-date-picker v-model="indicatorFilter.dateRange" type="daterange" range-separator="至"
                          start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD" style="width: 100%" />
        </el-col>
        <el-col :span="24" style="text-align: right; margin-top: 10px;">
          <el-button type="primary" @click="applyIndicatorFilter">查询</el-button>
          <el-button @click="resetIndicatorFilter">重置</el-button>
          <el-button @click="exportIndicatorTable">导出报表</el-button>
          <el-button @click="exportIndicatorChart">导出图表</el-button>
        </el-col>
      </el-row>
      <!-- å›¾è¡¨åŒº -->
      <div class="chart-container">
        <div ref="indicatorChartRef" style="width: 100%; height: 360px;"></div>
      </div>
      <!-- ä¸šç»©ç»Ÿè®¡ï¼ˆå›¢é˜Ÿç»´åº¦ï¼Œæ— ä¸ªäººå§“名) -->
      <el-table :data="teamPerformanceList" border stripe style="margin-top: 20px;">
        <el-table-column prop="team" label="销售团队"/>
        <el-table-column prop="orderCount" label="订单数"/>
        <el-table-column prop="salesAmount" label="销售额">
          <template #default="scope">Â¥{{ scope.row.salesAmount.toLocaleString() }}</template>
        </el-table-column>
        <el-table-column prop="shipmentRate" label="发货率">
          <template #default="scope">{{ scope.row.shipmentRate }}%</template>
        </el-table-column>
        <el-table-column prop="collectionRate" label="回款率">
          <template #default="scope">{{ scope.row.collectionRate }}%</template>
        </el-table-column>
        <el-table-column prop="attainment" label="目标达成率">
          <template #default="scope">
            <el-tag :type="scope.row.attainment >= 100 ? 'success' : scope.row.attainment >= 80 ? 'warning' : 'danger'">
              {{ scope.row.attainment }}%
            </el-tag>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
  </div>
</template>
<script setup>
import { ref, reactive, onMounted, nextTick } from 'vue'
import { Document, Van, Tickets, Wallet } from '@element-plus/icons-vue'
import * as echarts from 'echarts'
const indicatorKpis = reactive({
  orderCount: 1280,
  salesAmount: 9650000,
  shipmentRate: 89.2,
  collectionRate: 76.4
})
const indicatorFilter = reactive({
  product: '',
  customer: '',
  region: '',
  dateRange: []
})
const indicatorChartRef = ref(null)
let indicatorChart = null
const teamPerformanceList = ref([
  { team: '华东大区', orderCount: 320, salesAmount: 2850000, shipmentRate: 90, collectionRate: 80, attainment: 105 },
  { team: '华北大区', orderCount: 280, salesAmount: 2150000, shipmentRate: 86, collectionRate: 73, attainment: 92 },
  { team: '华南大区', orderCount: 210, salesAmount: 1850000, shipmentRate: 88, collectionRate: 70, attainment: 78 },
  { team: '西南大区', orderCount: 180, salesAmount: 1500000, shipmentRate: 83, collectionRate: 68, attainment: 74 }
])
const initIndicatorChart = () => {
  if (!indicatorChartRef.value) return
  if (indicatorChart) indicatorChart.dispose()
  indicatorChart = echarts.init(indicatorChartRef.value)
  const option = {
    title: { text: '多维度销售指标趋势', left: 'center' },
    tooltip: { trigger: 'axis' },
    legend: { data: ['订单数', '销售额', '发货率', '回款率'], top: 30 },
    grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
    xAxis: { type: 'category', data: ['2024-12', '2025-01', '2025-02', '2025-03', '2025-04', '2025-05'] },
    yAxis: [
      { type: 'value', name: '数量/金额', axisLabel: { formatter: '{value}' } },
      { type: 'value', name: '比例(%)', min: 0, max: 100, axisLabel: { formatter: '{value}%' } }
    ],
    series: [
      { name: '订单数', type: 'bar', data: [180, 220, 210, 260, 205, 225], itemStyle: { color: '#409eff' } },
      { name: '销售额', type: 'bar', data: [820, 950, 910, 1080, 980, 1020], itemStyle: { color: '#67c23a' } },
      { name: '发货率', type: 'line', yAxisIndex: 1, data: [86, 89, 88, 91, 87, 90], itemStyle: { color: '#e6a23c' } },
      { name: '回款率', type: 'line', yAxisIndex: 1, data: [72, 76, 74, 79, 75, 78], itemStyle: { color: '#f56c6c' } }
    ]
  }
  indicatorChart.setOption(option)
}
const applyIndicatorFilter = () => {
  const random = (base, delta) => {
    const v = base + Math.round((Math.random() - 0.5) * delta)
    return v < 0 ? 0 : v
  }
  indicatorKpis.orderCount = random(1280, 120)
  indicatorKpis.salesAmount = random(9650000, 350000)
  indicatorKpis.shipmentRate = (85 + Math.random() * 10).toFixed(1) * 1
  indicatorKpis.collectionRate = (70 + Math.random() * 12).toFixed(1) * 1
  setTimeout(() => initIndicatorChart(), 200)
}
const resetIndicatorFilter = () => {
  indicatorFilter.product = ''
  indicatorFilter.customer = ''
  indicatorFilter.region = ''
  indicatorFilter.dateRange = []
  applyIndicatorFilter()
}
const exportIndicatorTable = () => {
  const header = ['销售团队', '订单数', '销售额', '发货率(%)', '回款率(%)', '目标达成率(%)']
  const rows = teamPerformanceList.value.map(r => [
    r.team,
    r.orderCount,
    r.salesAmount,
    r.shipmentRate,
    r.collectionRate,
    r.attainment
  ])
  const csv = [header, ...rows].map(r => r.join(',')).join('\n')
  const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = '指标统计-团队业绩.csv'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  URL.revokeObjectURL(url)
}
const exportIndicatorChart = () => {
  if (!indicatorChart) return
  const url = indicatorChart.getDataURL({ type: 'png', pixelRatio: 2, backgroundColor: '#fff' })
  const link = document.createElement('a')
  link.href = url
  link.download = '指标统计-图表.png'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}
onMounted(() => {
  nextTick(() => initIndicatorChart())
})
</script>
<style scoped>
.indicator-stats {
  padding: 0;
}
.box-card { border: none; box-shadow: none; }
.search-row { margin-bottom: 20px; }
.stats-row { margin-bottom: 24px; }
.stat-card { display: flex; align-items: center; padding: 20px; background: #fff; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); }
.stat-icon { width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; border-radius: 8px; margin-right: 16px; }
.stat-content { flex: 1; }
.stat-value { font-size: 28px; font-weight: bold; color: #303133; margin-bottom: 4px; }
.stat-label { font-size: 14px; color: #909399; }
.chart-container { margin: 20px 0; padding: 20px; background: #fff; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); }
</style>
src/views/salesManagement/strategyControl/index.vue
@@ -474,6 +474,124 @@
          />
        </el-card>
      </el-tab-pane>
      <!-- æŒ‡æ ‡ç»Ÿè®¡ï¼ˆå¤šç»´åº¦é”€å”®åˆ†æžï¼‰ -->
      <el-tab-pane label="指标统计" name="indicatorStats">
        <el-card class="box-card">
          <!-- KPI æ±‡æ€» -->
          <el-row :gutter="20" class="stats-row">
            <el-col :span="6">
              <div class="stat-card">
                <div class="stat-icon" style="background: #ecf5ff;">
                  <el-icon :size="30" color="#409eff"><Document /></el-icon>
                </div>
                <div class="stat-content">
                  <div class="stat-value">{{ indicatorKpis.orderCount.toLocaleString() }}</div>
                  <div class="stat-label">订单数量</div>
                </div>
              </div>
            </el-col>
            <el-col :span="6">
              <div class="stat-card">
                <div class="stat-icon" style="background: #f0f9ff;">
                  <el-icon :size="30" color="#67c23a"><Tickets /></el-icon>
                </div>
                <div class="stat-content">
                  <div class="stat-value">Â¥{{ indicatorKpis.salesAmount.toLocaleString() }}</div>
                  <div class="stat-label">销售额</div>
                </div>
              </div>
            </el-col>
            <el-col :span="6">
              <div class="stat-card">
                <div class="stat-icon" style="background: #fef0f0;">
                  <el-icon :size="30" color="#e6a23c"><Van /></el-icon>
                </div>
                <div class="stat-content">
                  <div class="stat-value">{{ indicatorKpis.shipmentRate }}%</div>
                  <div class="stat-label">发货率</div>
                </div>
              </div>
            </el-col>
            <el-col :span="6">
              <div class="stat-card">
                <div class="stat-icon" style="background: #f4f4f5;">
                  <el-icon :size="30" color="#f56c6c"><Wallet /></el-icon>
                </div>
                <div class="stat-content">
                  <div class="stat-value">{{ indicatorKpis.collectionRate }}%</div>
                  <div class="stat-label">回款率</div>
                </div>
              </div>
            </el-col>
          </el-row>
          <!-- ç»´åº¦ç­›é€‰ -->
          <el-row :gutter="20" class="search-row">
            <el-col :span="6">
              <el-select v-model="indicatorFilter.product" placeholder="产品" clearable>
                <el-option label="全部产品" value="" />
                <el-option label="P.O 42.5普通硅酸盐水泥" value="P.O 42.5普通硅酸盐水泥" />
                <el-option label="P.S 32.5矿渣硅酸盐水泥" value="P.S 32.5矿渣硅酸盐水泥" />
                <el-option label="P.C 32.5复合硅酸盐水泥" value="P.C 32.5复合硅酸盐水泥" />
              </el-select>
            </el-col>
            <el-col :span="6">
              <el-select v-model="indicatorFilter.customer" placeholder="客户" clearable>
                <el-option label="全部客户" value="" />
                <el-option label="华东建材集团" value="华东建材集团" />
                <el-option label="长江混凝土公司" value="长江混凝土公司" />
                <el-option label="浦江水泥制品厂" value="浦江水泥制品厂" />
              </el-select>
            </el-col>
            <el-col :span="6">
              <el-select v-model="indicatorFilter.region" placeholder="区域" clearable>
                <el-option label="全部区域" value="" />
                <el-option label="华东地区" value="华东地区" />
                <el-option label="华南地区" value="华南地区" />
                <el-option label="华北地区" value="华北地区" />
              </el-select>
            </el-col>
            <el-col :span="6">
              <el-date-picker v-model="indicatorFilter.dateRange" type="daterange" range-separator="至"
                              start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD" style="width: 100%" />
            </el-col>
            <el-col :span="24" style="text-align: right; margin-top: 10px;">
              <el-button type="primary" @click="applyIndicatorFilter">查询</el-button>
              <el-button @click="resetIndicatorFilter">重置</el-button>
              <el-button @click="exportIndicatorTable">导出报表</el-button>
              <el-button @click="exportIndicatorChart">导出图表</el-button>
            </el-col>
          </el-row>
          <!-- å›¾è¡¨åŒº -->
          <div class="chart-container">
            <div ref="indicatorChartRef" style="width: 100%; height: 360px;"></div>
          </div>
          <!-- ä¸šç»©ç»Ÿè®¡ï¼ˆå›¢é˜Ÿç»´åº¦ï¼Œæ— ä¸ªäººå§“名) -->
          <el-table :data="teamPerformanceList" border stripe style="margin-top: 20px;">
            <el-table-column prop="team" label="销售团队" width="140" />
            <el-table-column prop="orderCount" label="订单数" width="100" />
            <el-table-column prop="salesAmount" label="销售额" width="140">
              <template #default="scope">Â¥{{ scope.row.salesAmount.toLocaleString() }}</template>
            </el-table-column>
            <el-table-column prop="shipmentRate" label="发货率" width="100">
              <template #default="scope">{{ scope.row.shipmentRate }}%</template>
            </el-table-column>
            <el-table-column prop="collectionRate" label="回款率" width="100">
              <template #default="scope">{{ scope.row.collectionRate }}%</template>
            </el-table-column>
            <el-table-column prop="attainment" label="目标达成率" width="120">
              <template #default="scope">
                <el-tag :type="scope.row.attainment >= 100 ? 'success' : scope.row.attainment >= 80 ? 'warning' : 'danger'">
                  {{ scope.row.attainment }}%
                </el-tag>
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </el-tab-pane>
    </el-tabs>
    <!-- ä»·æ ¼ç­–略对话框 -->
@@ -482,7 +600,7 @@
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="策略类型" prop="strategyType">
              <el-select v-model="priceStrategyForm.strategyType" placeholder="请选择策略类型" style="width: 100%;">
              <el-select v-model="priceStrategyForm.strategyType" placeholder="请选择策略类型" style="width: 100%;" :disabled="priceStrategyDialogMode === 'view'">
                <el-option label="专属价格" value="专属价格"></el-option>
                <el-option label="阶梯报价" value="阶梯报价"></el-option>
                <el-option label="促销折扣" value="促销折扣"></el-option>
@@ -491,7 +609,7 @@
          </el-col>
          <el-col :span="12">
            <el-form-item label="客户名称" prop="customerName">
              <el-select v-model="priceStrategyForm.customerName" placeholder="请选择客户" style="width: 100%;">
              <el-select v-model="priceStrategyForm.customerName" placeholder="请选择客户" style="width: 100%;" :disabled="priceStrategyDialogMode === 'view'">
                <el-option label="华东建材集团" value="华东建材集团"></el-option>
                <el-option label="长江混凝土公司" value="长江混凝土公司"></el-option>
                <el-option label="浦江水泥制品厂" value="浦江水泥制品厂"></el-option>
@@ -502,7 +620,7 @@
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="产品名称" prop="productName">
              <el-select v-model="priceStrategyForm.productName" placeholder="请选择产品" style="width: 100%;">
              <el-select v-model="priceStrategyForm.productName" placeholder="请选择产品" style="width: 100%;" :disabled="priceStrategyDialogMode === 'view'">
                <el-option label="P.O 42.5普通硅酸盐水泥" value="P.O 42.5普通硅酸盐水泥"></el-option>
                <el-option label="P.S 32.5矿渣硅酸盐水泥" value="P.S 32.5矿渣硅酸盐水泥"></el-option>
                <el-option label="P.C 32.5复合硅酸盐水泥" value="P.C 32.5复合硅酸盐水泥"></el-option>
@@ -511,19 +629,19 @@
          </el-col>
          <el-col :span="12">
            <el-form-item label="规格型号" prop="specification">
              <el-input v-model="priceStrategyForm.specification" placeholder="请输入规格型号" />
              <el-input v-model="priceStrategyForm.specification" placeholder="请输入规格型号" :disabled="priceStrategyDialogMode === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="基础价格(元/吨)" prop="basePrice">
              <el-input-number v-model="priceStrategyForm.basePrice" :min="0" :precision="2" style="width: 100%;" />
              <el-input-number v-model="priceStrategyForm.basePrice" :min="0" :precision="2" style="width: 100%;" :disabled="priceStrategyDialogMode === 'view'" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="策略价格" prop="strategyPrice">
              <el-input v-model="priceStrategyForm.strategyPrice" placeholder="如: Â¥350/吨 æˆ– 9折" />
              <el-input v-model="priceStrategyForm.strategyPrice" placeholder="如: Â¥350/吨 æˆ– 9折" :disabled="priceStrategyDialogMode === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -536,6 +654,7 @@
                placeholder="选择生效日期"
                style="width: 100%"
                value-format="YYYY-MM-DD"
                :disabled="priceStrategyDialogMode === 'view'"
              />
            </el-form-item>
          </el-col>
@@ -547,17 +666,18 @@
                placeholder="选择失效日期"
                style="width: 100%"
                value-format="YYYY-MM-DD"
                :disabled="priceStrategyDialogMode === 'view'"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="策略说明" prop="description">
          <el-input type="textarea" v-model="priceStrategyForm.description" :rows="3" placeholder="请输入策略说明" />
          <el-input type="textarea" v-model="priceStrategyForm.description" :rows="3" placeholder="请输入策略说明" :disabled="priceStrategyDialogMode === 'view'" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="priceStrategyDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleSavePriceStrategy">保存</el-button>
        <el-button @click="priceStrategyDialogVisible = false">{{ priceStrategyDialogMode === 'view' ? '关闭' : '取消' }}</el-button>
        <el-button v-if="priceStrategyDialogMode !== 'view'" type="primary" @click="handleSavePriceStrategy">保存</el-button>
      </template>
    </el-dialog>
  </div>
@@ -648,6 +768,7 @@
const priceStrategyDialogVisible = ref(false)
const priceStrategyDialogTitle = ref('新增价格策略')
const priceStrategyDialogMode = ref('add') // add | edit | view
const priceStrategyForm = reactive({
  strategyType: '',
  customerName: '',
@@ -849,16 +970,21 @@
const handleAddPriceStrategy = () => {
  priceStrategyDialogTitle.value = '新增价格策略'
  resetPriceStrategyForm()
  priceStrategyDialogMode.value = 'add'
  priceStrategyDialogVisible.value = true
}
const handleViewPriceStrategy = (row) => {
  ElMessage.info('查看策略详情: ' + row.strategyNo)
  priceStrategyDialogTitle.value = '查看价格策略'
  Object.assign(priceStrategyForm, row)
  priceStrategyDialogMode.value = 'view'
  priceStrategyDialogVisible.value = true
}
const handleEditPriceStrategy = (row) => {
  priceStrategyDialogTitle.value = '编辑价格策略'
  Object.assign(priceStrategyForm, row)
  priceStrategyDialogMode.value = 'edit'
  priceStrategyDialogVisible.value = true
}
@@ -868,6 +994,12 @@
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    // æœ¬åœ°å‡æ•°æ®åˆ é™¤ï¼šä»Žåˆ—表中移除并更新总数
    const index = priceStrategyList.value.findIndex(item => item.id === row.id)
    if (index > -1) {
      priceStrategyList.value.splice(index, 1)
      if (pricePagination.total > 0) pricePagination.total -= 1
    }
    ElMessage.success('删除成功')
  })
}
@@ -1176,6 +1308,112 @@
  profitPagination.pageSize = val.limit
}
// ========== æŒ‡æ ‡ç»Ÿè®¡ï¼ˆå¤šç»´åº¦åˆ†æžï¼‰ ==========
const indicatorKpis = reactive({
  orderCount: 1280,
  salesAmount: 9650000,
  shipmentRate: 89.2,
  collectionRate: 76.4
})
const indicatorFilter = reactive({
  product: '',
  customer: '',
  region: '',
  dateRange: []
})
const indicatorChartRef = ref(null)
let indicatorChart = null
const teamPerformanceList = ref([
  { team: '华东团队A', orderCount: 320, salesAmount: 2850000, shipmentRate: 90, collectionRate: 80, attainment: 105 },
  { team: '华北团队B', orderCount: 280, salesAmount: 2150000, shipmentRate: 86, collectionRate: 73, attainment: 92 },
  { team: '华南团队C', orderCount: 210, salesAmount: 1850000, shipmentRate: 88, collectionRate: 70, attainment: 78 },
  { team: '西南团队D', orderCount: 180, salesAmount: 1500000, shipmentRate: 83, collectionRate: 68, attainment: 74 }
])
const initIndicatorChart = () => {
  if (!indicatorChartRef.value) return
  if (indicatorChart) indicatorChart.dispose()
  indicatorChart = echarts.init(indicatorChartRef.value)
  const option = {
    title: { text: '多维度销售指标趋势', left: 'center' },
    tooltip: { trigger: 'axis' },
    legend: { data: ['订单数', '销售额', '发货率', '回款率'], top: 30 },
    grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
    xAxis: { type: 'category', data: ['2024-12', '2025-01', '2025-02', '2025-03', '2025-04', '2025-05'] },
    yAxis: [
      { type: 'value', name: '数量/金额', axisLabel: { formatter: '{value}' } },
      { type: 'value', name: '比例(%)', min: 0, max: 100, axisLabel: { formatter: '{value}%' } }
    ],
    series: [
      { name: '订单数', type: 'bar', data: [180, 220, 210, 260, 205, 225], itemStyle: { color: '#409eff' } },
      { name: '销售额', type: 'bar', data: [820, 950, 910, 1080, 980, 1020], itemStyle: { color: '#67c23a' } },
      { name: '发货率', type: 'line', yAxisIndex: 1, data: [86, 89, 88, 91, 87, 90], itemStyle: { color: '#e6a23c' } },
      { name: '回款率', type: 'line', yAxisIndex: 1, data: [72, 76, 74, 79, 75, 78], itemStyle: { color: '#f56c6c' } }
    ]
  }
  indicatorChart.setOption(option)
}
const applyIndicatorFilter = () => {
  // ä½¿ç”¨å‡æ•°æ®æ¨¡æ‹ŸæŸ¥è¯¢ï¼Œåˆ·æ–°KPI和图表
  // ä»…演示:随机微调以体现筛选效果
  const random = (base, delta) => {
    const v = base + Math.round((Math.random() - 0.5) * delta)
    return v < 0 ? 0 : v
  }
  indicatorKpis.orderCount = random(1280, 120)
  indicatorKpis.salesAmount = random(9650000, 350000)
  indicatorKpis.shipmentRate = (85 + Math.random() * 10).toFixed(1) * 1
  indicatorKpis.collectionRate = (70 + Math.random() * 12).toFixed(1) * 1
  setTimeout(() => initIndicatorChart(), 200)
}
const resetIndicatorFilter = () => {
  indicatorFilter.product = ''
  indicatorFilter.customer = ''
  indicatorFilter.region = ''
  indicatorFilter.dateRange = []
  applyIndicatorFilter()
}
const exportIndicatorTable = () => {
  // å¯¼å‡ºå›¢é˜Ÿä¸šç»©ä¸ºCSV(假导出)
  const header = ['销售团队', '订单数', '销售额', '发货率(%)', '回款率(%)', '目标达成率(%)']
  const rows = teamPerformanceList.value.map(r => [
    r.team,
    r.orderCount,
    r.salesAmount,
    r.shipmentRate,
    r.collectionRate,
    r.attainment
  ])
  const csv = [header, ...rows].map(r => r.join(',')).join('\n')
  const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = '指标统计-团队业绩.csv'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  URL.revokeObjectURL(url)
}
const exportIndicatorChart = () => {
  if (!indicatorChart) return
  const url = indicatorChart.getDataURL({ type: 'png', pixelRatio: 2, backgroundColor: '#fff' })
  const link = document.createElement('a')
  link.href = url
  link.download = '指标统计-图表.png'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}
// ç”Ÿå‘½å‘¨æœŸ
onMounted(() => {
  // ç»„件挂载后不立即初始化图表,等待用户切换到对应标签页
@@ -1188,6 +1426,8 @@
      initPriceChart()
    } else if (newVal === 'profitAnalysis') {
      initProfitChart()
    } else if (newVal === 'indicatorStats') {
      initIndicatorChart()
    }
  })
})