# ECharts Configurations / ECharts图表配置

> Extracted from SKILL.md v2.1.0 — ECharts CDN dependency and all chart configuration templates (doughnut, bar, line, plus table).

---

## ECharts CDN

```html
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script>
```

**Container CSS:**
```css
.echarts-chart { width: 100%; height: 360px; min-height: 300px; }
```

---

## Doughnut Chart (COMP-DOUGHNUT-01) — 投资阶段分布环形图

**9-stage colors (MUST follow exactly):**

| Stage | Color |
|-------|-------|
| 储备 | #3B82F6 |
| 初筛 | #60A5FA |
| 立项 | #10B981 |
| 尽调 | #34D399 |
| 评审 | #F59E0B |
| 签署 | #FBBF24 |
| 出资 | #8B5CF6 |
| 投后 | #6366F1 |
| 退出 | #EF4444 |

**HTML container:**
```html
<div id="chart-doughnut" class="echarts-chart" role="img" aria-label="投资阶段分布环形图"></div>
```

**ECharts config:**
```javascript
function initDoughnutChart() {
  var chartDom = document.getElementById('chart-doughnut');
  if (!chartDom) return null;
  var myChart = echarts.init(chartDom);

  var option = {
    tooltip: {
      trigger: 'item',
      formatter: function(params) {
        return params.name + ': ' + params.value + '个 (' + params.percent + '%)';
      }
    },
    legend: {
      orient: 'horizontal', bottom: 0, left: 'center',
      itemWidth: 12, itemHeight: 12,
      textStyle: { fontSize: 13 }, type: 'scroll'
    },
    series: [{
      name: '投资阶段分布', type: 'pie',
      radius: ['45%', '70%'], center: ['50%', '45%'],
      avoidLabelOverlap: false,
      itemStyle: { borderRadius: 4, borderColor: '#fff', borderWidth: 2 },
      label: { show: false, position: 'center' },
      emphasis: {
        label: { show: true, fontSize: 20, fontWeight: 'bold' },
        scaleSize: 8
      },
      labelLine: { show: false },
      animationType: 'scale', animationEasing: 'elasticOut', animationDuration: 1000,
      data: [
        { value: 23, name: '储备', itemStyle: { color: '#3B82F6' } },
        { value: 18, name: '初筛', itemStyle: { color: '#60A5FA' } },
        { value: 15, name: '立项', itemStyle: { color: '#10B981' } },
        { value: 12, name: '尽调', itemStyle: { color: '#34D399' } },
        { value: 9,  name: '评审', itemStyle: { color: '#F59E0B' } },
        { value: 7,  name: '签署', itemStyle: { color: '#FBBF24' } },
        { value: 5,  name: '出资', itemStyle: { color: '#8B5CF6' } },
        { value: 11, name: '投后', itemStyle: { color: '#6366F1' } },
        { value: 8,  name: '退出', itemStyle: { color: '#EF4444' } }
      ]
    }]
  };

  myChart.setOption(option);

  // Click → drill-down breadcrumb
  myChart.on('click', function(params) {
    if (params.name) {
      showDrilldownBreadcrumb(['全集团', params.name + '阶段']);
      refreshKPIValues();
    }
  });

  window.addEventListener('resize', function() { myChart.resize(); });
  return myChart;
}
```

---

## Bar Chart (COMP-BAR-V-01) — 子公司投资对比柱状图

**Features:** Horizontal bar, gradient #2563EB→#3B82F6, right-side value labels, clickable → triggers breadcrumbs.

**HTML container:**
```html
<div id="chart-bar" class="echarts-chart" role="img" aria-label="子公司投资对比柱状图"></div>
```

**ECharts config:**
```javascript
function initBarChart() {
  var chartDom = document.getElementById('chart-bar');
  if (!chartDom) return null;
  var myChart = echarts.init(chartDom);

  var option = {
    tooltip: {
      trigger: 'axis', axisPointer: { type: 'shadow' },
      formatter: function(params) { return params[0].name + '<br/>投资金额: ' + params[0].value + '亿'; }
    },
    legend: { show: false },
    grid: { left: '12%', right: '10%', top: '8%', bottom: '8%', containLabel: true },
    xAxis: {
      type: 'value', name: '亿元',
      axisLabel: { formatter: '{value}' },
      splitLine: { lineStyle: { color: '#E5E7EB', type: 'dashed' } }
    },
    yAxis: {
      type: 'category', data: ['子公司C', '子公司B', '子公司A'],
      axisLabel: { fontSize: 13 }, axisLine: { show: false }, axisTick: { show: false }
    },
    series: [{
      type: 'bar', barWidth: '50%',
      emphasis: { itemStyle: { shadowBlur: 10, shadowColor: 'rgba(0,0,0,0.2)' } },
      label: { show: true, position: 'right', fontWeight: 'bold', formatter: '{c}亿' },
      itemStyle: {
        borderRadius: [0, 4, 4, 0],
        color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
          { offset: 0, color: '#2563EB' }, { offset: 1, color: '#3B82F6' }
        ])
      },
      data: [
        { value: 28.3, name: '子公司C' },
        { value: 35.7, name: '子公司B' },
        { value: 45.2, name: '子公司A' }
      ]
    }]
  };

  myChart.setOption(option);

  myChart.on('click', function(params) {
    if (params.name) {
      updateBreadcrumbA(['集团', params.name]);
      showDrilldownBreadcrumb([params.name, '全部阶段']);
      refreshKPIValues();
    }
  });

  window.addEventListener('resize', function() { myChart.resize(); });
  return myChart;
}
```

---

## Line Chart (COMP-LINE-01) — 投资趋势折线图

**Features:** Current year solid line (#2563EB, 2px) + last year dashed (#9CA3AF, 2px). 12 months. Area fill gradient. Bottom summary: 本月投资/环比/同比.

**HTML container:**
```html
<div id="chart-line" class="echarts-chart" role="img" aria-label="投资趋势折线图"></div>
```

**ECharts config:**
```javascript
function initLineChart() {
  var chartDom = document.getElementById('chart-line');
  if (!chartDom) return null;
  var myChart = echarts.init(chartDom);

  var option = {
    tooltip: {
      trigger: 'axis',
      formatter: function(params) {
        var result = params[0].axisValue + '<br/>';
        params.forEach(function(item) {
          result += item.marker + ' ' + item.seriesName + ': ' + item.value + '亿<br/>';
        });
        return result;
      }
    },
    legend: { data: ['当年', '去年'], bottom: 0, itemWidth: 20, itemHeight: 2 },
    grid: { left: '5%', right: '5%', top: '8%', bottom: '12%', containLabel: true },
    xAxis: {
      type: 'category', boundaryGap: false,
      data: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
      axisLabel: { fontSize: 12 },
      axisLine: { lineStyle: { color: '#E5E7EB' } }
    },
    yAxis: {
      type: 'value', name: '亿元',
      axisLabel: { formatter: '{value}' },
      splitLine: { lineStyle: { color: '#E5E7EB', type: 'dashed' } }
    },
    series: [
      {
        name: '当年', type: 'line',
        data: [8.2, 9.5, 7.8, 10.1, 8.9, 11.2, 9.6, 10.8, 8.5, 11.5, 9.2, 12.3],
        smooth: true, symbol: 'circle', symbolSize: 8,
        lineStyle: { width: 2.5, color: '#2563EB' },
        itemStyle: { color: '#2563EB', borderColor: '#fff', borderWidth: 2 },
        areaStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: 'rgba(37, 99, 235, 0.25)' },
            { offset: 1, color: 'rgba(37, 99, 235, 0.02)' }
          ])
        }
      },
      {
        name: '去年', type: 'line',
        data: [6.5, 7.2, 6.8, 8.5, 7.3, 9.1, 8.0, 8.9, 7.1, 9.5, 7.8, 10.1],
        smooth: true, symbol: 'circle', symbolSize: 6,
        lineStyle: { width: 2, color: '#9CA3AF', type: 'dashed' },
        itemStyle: { color: '#9CA3AF', borderColor: '#fff', borderWidth: 2 }
      }
    ]
  };

  myChart.setOption(option);

  myChart.on('click', function(params) {
    if (params.componentType === 'series') {
      showDrilldownBreadcrumb(['全集团', params.seriesName + '年·' + params.name]);
      refreshKPIValues();
    }
  });

  window.addEventListener('resize', function() { myChart.resize(); });
  return myChart;
}
```

---

## Table (COMP-TABLE-01) — 项目明细表格

7-column pure HTML table. 5-8 mock rows. Row-level "详情→" links.

```html
<table class="data-table" role="grid">
  <thead>
    <tr>
      <th>#</th><th>项目名称</th><th>公司</th><th>金额</th><th>阶段</th><th>行业</th><th>操作</th>
    </tr>
  </thead>
  <tbody>
    <tr data-row="1">
      <td>1</td><td>智能科技A轮</td><td>子公司A</td><td>2.5亿</td><td>评审</td><td>科技</td>
      <td><a class="row-detail-btn" href="detail.html?project=1">详情→</a></td>
    </tr>
    <tr data-row="2">
      <td>2</td><td>医疗健康B轮</td><td>子公司B</td><td>1.8亿</td><td>尽调</td><td>医疗</td>
      <td><a class="row-detail-btn" href="detail.html?project=2">详情→</a></td>
    </tr>
  </tbody>
</table>
```

---

## V12 Pattern 2: Ring Chart Single-Filter

Click a ring chart sector → isolate (zero out others); click again → restore all.

**State tracker:**
```javascript
var filteredCharts = { doughnut: null }; // null = no filter; 'stageName' = locked

function filterRingToSingleSlice(myChart, stageName) {
  var option = myChart.getOption();
  var data = option.series[0].data.slice();
  data.forEach(function(item) {
    if (item.name !== stageName) {
      item.value = 0;
      item.itemStyle = item.itemStyle || {};
      item.itemStyle.opacity = 0;
    }
  });
  myChart.setOption({ series: [{ data: data }] });
}
```

**Click handler (toggle):**
```javascript
myChart.on('click', function(params) {
  if (!params.name) return;
  if (filteredCharts.doughnut === params.name) {
    myChart.setOption({ series: [{ data: ORIGINAL_DATA.doughnut }] });
    filteredCharts.doughnut = null;
  } else {
    filterRingToSingleSlice(myChart, params.name);
    filteredCharts.doughnut = params.name;
  }
});
```

---

## V12 Pattern 5: Chart-to-Chart Linkage

Ring sector click → filter bar chart. Bar click → refresh all ring charts with company-specific data. Mutual refresh via `setOption()`.

**Ring → Bar linkage:**
```javascript
function onRingSectorClick(stageName) {
  var barChart = window.__cockpitCharts.bar;
  if (!barChart) return;
  var filteredData = COMPANY_DATA.filter(function(c) {
    return c.stages.indexOf(stageName) >= 0;
  }).map(function(c) { return { value: c.investment, name: c.name }; });
  barChart.setOption({
    yAxis: { data: filteredData.map(function(d) { return d.name; }) },
    series: [{ data: filteredData }]
  });
}
```

**Bar → Ring linkage:**
```javascript
function onBarClick(companyName) {
  var doughnutChart = window.__cockpitCharts.doughnut;
  if (!doughnutChart) return;
  var companyData = getCompanyStageDistribution(companyName);
  doughnutChart.setOption({ series: [{ data: companyData }] });
  var lineChart = window.__cockpitCharts.line;
  if (lineChart) {
    lineChart.setOption({
      series: [
        { data: getCompanyMonthlyData(companyName, 'current') },
        { data: getCompanyMonthlyData(companyName, 'last') }
      ]
    });
  }
}
```
