[English](./README.md) | 简体中文

# @ray-js/common-charts

面向 **涂鸦 Ray** 小程序的图表组件，底层通过 RJS 插件使用 **ECharts**。熟悉 ECharts 的 `option` 即可快速接入。

## 目录

- [环境要求](#环境要求)
- [安装](#安装)
- [使用](#使用)
- [进阶使用](#advanced-usage-zh)
- [常见问题](#常见问题)

## 环境要求

| 项目                   | 说明                                                                                                                         |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Peer 依赖**          | [`@ray-js/ray`](https://www.npmjs.com/package/@ray-js/ray) `^1.4.9`（与业务工程中的 Ray 版本保持一致）。                     |
| **底层组件**           | 依赖 [`@tuya-miniapp/common-charts`](https://github.com/Tuya-Community/tuya-miniapp-materials?path=materials/CommonCharts)。 |
| **可选：完整 ECharts** | 使用 `usingPlugin` 时需在工程中安装 `echarts` 并配置 RJS 插件（见 [进阶使用](#advanced-usage-zh)）。                         |

## 安装

```bash
npm install @ray-js/common-charts
# 或
yarn add @ray-js/common-charts
```

## 使用

默认导出为 **`CommonCharts`**。HTML 型 tooltip（`renderMode: 'html'`）可在字符串 `formatter` 里用普通字符串拼接实现，与常规 ECharts 一致；本包另提供可选的 **`html()`** 辅助函数，需要时再 `import`（见 [tooltip（HTML）](#tooltip-html)）。完整属性类型见 [`src/props.ts`](./src/props.ts)。

### 基础用法

```jsx
import CommonCharts from '@ray-js/common-charts';

<CommonCharts
  unit="℃"
  option={{
    backgroundColor: '#fff',
    xAxis: {
      type: 'category',
      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
    },
    yAxis: { type: 'value' },
    tooltip: {},
    series: [
      {
        name: '测试样例',
        data: [150, 230, 224, 218, 135, 147, 260],
        type: 'line',
      },
    ],
  }}
/>;
```

### 自定义类名

```jsx
<CommonCharts
  option={{ backgroundColor: 'transparent', ...lineOption } as EChartsOption}
  customClass={styles['my-chart']}
/>
```

### `notMerge` — 关闭默认合并（v0.0.4+）

需要**完全自控** ECharts `option` 时开启；开启后组件**不再**对传入的 `option` 做合并或改写。

> **注意：** 经过 JS → RJS 时无法传递真实的 `function`，深度定制会更吃力，请按需开启。

```jsx
<CommonCharts option={完整的EChartsOption} notMerge />
```

也可通过 `opts` 传入初始化相关配置（例如其中的 `notMerge`），见 [ECharts `opts`](#echarts-opts)。

### 主题

内置：`dark`、`light`。

```jsx
<CommonCharts theme="dark" />
```

### ECharts 的 `opts` 能力

<a id="echarts-opts"></a>

透传底层图表初始化选项（如合并策略）。

```jsx
<CommonCharts
  opts={{ notMerge: true }}
  option={updatedOption as EChartsOption}
  customStyle={{
    width: '100%',
    height: '300px',
  }}
/>
```

### 全屏

`supportFullScreen` 控制是否支持全屏展示。**未实现**阻止底层默认滑动，可在业务侧用 `ty.onWindowResize` 等做横竖屏或布局适配。

```jsx
<CommonCharts supportFullScreen />
```

### 错误提示

```jsx
<CommonCharts option={{} as EChartsOption} errMsg={Strings.getLang('errorMsg')} />
```

### Loading 文案

```jsx
<CommonCharts loadingText="Loading..." />
```

### `unit` 单位

使用默认 tooltip 行为时，可通过 `unit` 快速带上单位。

```jsx
<CommonCharts unit="米" />
```

### tooltip（HTML）（v0.1.3）

<a id="tooltip-html"></a>

设置 `renderMode: 'html'`，在字符串 `formatter` 中返回 HTML 即可。下面示例使用了本包提供的可选 **`html()`** 辅助函数；也可全部改为手写字符串（见 [进阶使用](#advanced-usage-zh)）。

```jsx
import CommonCharts, { html } from '@ray-js/common-charts';

<CommonCharts
  option={{
    ...lineChartOption,
    tooltip: {
      formatter: `function (params) {
        var text = _.reduce(params, function (acc, cur, idx) {
          return acc + ${html(
            'div',
            { style: { fontSize: '10px' } },
            "cur.marker + cur.seriesName + ':' + cur.value"
          )}
        }, '');
        return ${html(
          'div',
          {
            style: {
              color: 'red',
              fontSize: '10px',
              textAlign: 'center',
            },
          },
          'dayjs(Date.now()).format("YYYY-MM-DD HH:mm:ss")'
        )} + text;
      }`,
      renderMode: 'html',
      confine: true,
    },
  }}
/>;
```

### ECharts 事件（v0.0.3+）

```jsx
<CommonCharts
  on={{
    click(e) {
      console.log(e);
    },
  }}
/>
```

### `getEchartsProxy`（v0.0.3+）

在 JS 侧拿到的是 RJS 实例的**代理**，详见 [常见问题](#常见问题)。

```jsx
<CommonCharts
  getEchartsProxy={instance => {
    instance.showLoading();
  }}
/>
```

### `onLoad` / `onRender`（v0.1.2+）

以**字符串**形式编写在图表上下文中执行的函数（仅 ES5，规则同 [进阶使用](#advanced-usage-zh)）。

- **`onLoad`**：首次 `setOption` 之后执行。
- **`onRender`**：每次 `setOption` 之后执行。

```jsx
<CommonCharts
  onLoad={`
    function () {
      console.log('首次 setOption 后');
      myChart.group = 'chart';
      Echarts.connect('chart');
    }
  `}
  onRender={`
    function () {
      console.log('每次 setOption 后');
    }
  `}
/>
```

### 聚焦 / 失焦（v0.1.5）

```jsx
<CommonCharts
  option={lineOption as EChartsOption}
  blurAutoHideTooltip
  customStyle={{
    width: '100%',
    height: '300px',
    outline: isFocus ? '1px solid black' : 'none',
  }}
  onBlur={() => {
    console.log('onblur');
    setIsFocus(false);
  }}
  onFocus={() => {
    console.log('onfocus');
    setIsFocus(true);
  }}
/>
```

### 按需引入 ECharts 插件（v0.1.8）

```jsx
<CommonCharts
  option={{
    xAxis: {
      type: 'category',
      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
    },
    yAxis: { type: 'value' },
    series: [
      {
        data: [20, 80, 110, 150, 200, 320, 400],
        type: 'line',
        smooth: true,
      },
    ],
    visualMap: {
      show: false,
      type: 'piecewise',
      dimension: 1,
      pieces: [
        { gt: 0, lte: 100, color: '#1F65AE' },
        { gt: 100, lte: 300, color: '#40B243' },
        { gt: 300, color: '#FFD27F' },
      ],
    },
  }}
  usingPlugin
  usingPluginList={['rjs://echarts/lib/component/visualMap/installVisualMapPiecewise.js']}
/>
```

<a id="advanced-usage-zh"></a>

## 进阶使用

_自 v0.1.0 起支持。_

### 以字符串形式传入「函数」

JS ↔ RJS 无法传递真实函数，需传入 **字符串**，内容为 **ES5 函数体**。

- 不支持箭头函数。
- 仅支持 ES5 语法。
- HTML 片段可直接字符串拼接；**`html()`** 仅为本包提供的可选辅助，非必须。

**字符串执行时可用的内置变量：**

| 变量       | 说明                                |
| :--------- | :---------------------------------- |
| `_`        | [lodash](https://www.lodashjs.com/) |
| `myChart`  | ECharts 实例                        |
| `option`   | 当前 `option`                       |
| `Echarts`  | ECharts 类                          |
| `dayjs`    | dayjs                               |
| `unit`     | 传入的 `unit`                       |
| `theme`    | 传入的 `theme`                      |
| 自定义扩展 | 通过 `injectVars` 注入              |

```ts
// 自行拼接 HTML
{
  tooltip: {
    formatter: `function (params) {
      var text = _.reduce(params, function (acc, cur, idx) {
        var lineText = cur.marker + cur.seriesName + ": " + cur.value;
        return acc + "<div style='font-size: 10px'>" + lineText + "</div>";
      }, "");
      return "<div style='color: red;font-size: 10px;text-align: center'>" +
        dayjs(Date.now()).format("YYYY-MM-DD HH:mm:ss") + "</div>" + text;
    }`,
  },
}
```

```ts
// 可选：使用 html() 的写法（需 import html）
{
  tooltip: {
    formatter: `function (params) {
        var text = _.reduce(params, function (acc, cur, idx) {
          return acc + ${html(
            'div',
            { style: { fontSize: '10px' } },
            "cur.marker + cur.seriesName + ':' + cur.value"
          )}
        }, '');
        return ${html(
          'div',
          {
            style: {
              color: 'red',
              fontSize: '10px',
              textAlign: 'center',
            },
          },
          'dayjs(Date.now()).format("YYYY-MM-DD HH:mm:ss")'
        )} + text;
      }`,
  },
}
```

### `usingPlugin` — 使用增强能力

1. **安装 echarts**（在启用插件的工程里）：

   ```bash
   npm install echarts
   ```

2. **组件上开启：**

   ```jsx
   <CommonCharts usingPlugin />
   ```

3. **在 `global.config.ts` 中配置 `usingPlugins`**，插件 ID 以官方列表为准，详见 [插件文档](https://developer.tuya.com/cn/miniapp/develop/miniapp/framework/plugin/intro)。

   `package.json`（示例：与工具链默认插件集对齐时多为 **5.4.2**）：

   ```json
   {
     "echarts": "5.4.2"
   }
   ```

   ```ts
   {
     "usingPlugins": ["rjs://echarts"]
   }
   ```

4. **`usingPluginList`（v0.1.8+）** — 与步骤 3 类似；若未传或传空数组，会加载**全量** ECharts 插件，包体积显著增大。按需列出 RJS 入口可减小体积。

   组件默认插件集对应 **ECharts 5.4.2**，按需加载时建议版本一致。若必须使用更高版本能力，可将 **`echarts/core`** 一并列入 `usingPluginList`，以**整体替换**组件内置插件版本。

   示例：仅需 **visualMap（分段型）**：

   ```ts
   {
     "usingPlugins": ["rjs://echarts/lib/component/visualMap/installVisualMapPiecewise.js"]
   }
   ```

   ```tsx
   <CommonCharts
     option={/* ... */}
     usingPlugin
     usingPluginList={['rjs://echarts/lib/component/visualMap/installVisualMapPiecewise.js']}
   />
   ```

## 常见问题

1. **`option` 里写 function 不生效**  
   JS → RJS 只传数据，函数会被丢弃。请使用**字符串函数体**（v0.1.0+），见 [进阶使用](#advanced-usage-zh)。

2. **监听图表事件时，回调里部分字段为 `null`**  
   ECharts 回调对象可能存在循环引用或 getter，无法完整序列化；桥接层会先做一次安全处理再传到 JS。

3. **`getEchartsProxy` 里调方法没有返回值**  
   真实实例在 RJS 中，JS 侧为用于触发调用与事件的代理，跨线程无法带回同步返回值。

4. **只想用合并能力，自己用 RJS 画 ECharts 可以吗？**  
   可以。使用 `import { autoInject } from '@tuya-miniapp/common-charts/lib/core/inject.js'`。渲染仍依赖小程序 [插件系统](https://developer.tuya.com/cn/miniapp/develop/miniapp/framework/plugin/intro)。

5. **不想用合并，完全自定义 `option`**  
   v0.0.4+ 使用 `notMerge`。同样受限于 props 不能传真实 `function`，请按需开启。

6. **官网示例在小程序里不生效**  
   先确认是否使用 HTML 模式 tooltip、以及是否在 `option` 里写了无法跨桥传递的 `function`；处理方式见问题 1。