# @jzliu-cli/bi-engine

jzliu-cli BI 引擎 - 基于 Vue 2.x 的现代化 BI 仪表板解决方案

## 📦 安装

```bash
# 使用 yarn 安装
yarn add @jzliu-cli/bi-engine

# 或使用 npm 安装
npm install @jzliu-cli/bi-engine
```

## 🚀 快速开始

### 1. 安装依赖

```bash
# 安装核心依赖
yarn add @jzliu-cli/bi-engine element-ui vue@^2.6.11 vuex@^3.6.2

# 或使用 npm
npm install @jzliu-cli/bi-engine element-ui vue@^2.6.11 vuex@^3.6.2
```

### 2. 基础配置

**main.js**:
```javascript
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import Vuex from 'vuex'

// 必需：使用 Element UI
Vue.use(ElementUI)

// 必需：使用 Vuex
Vue.use(Vuex)

new Vue({
  render: h => h(App),
}).$mount('#app')
```

### 3. 快速上手

**最简单的使用方式**:
```vue
<template>
  <div style="height: 100vh;">
    <bi-dashboard />
  </div>
</template>

<script>
import { BiDashboard } from '@jzliu-cli/bi-engine'

export default {
  components: { BiDashboard }
}
</script>
```

**使用内置数据**:
```vue
<template>
  <div style="height: 100vh;">
    <bi-dashboard 
      :widgets="widgets" 
      :layoutObj="layoutObj"
    />
  </div>
</template>

<script>
import bi, { BiDashboard } from '@jzliu-cli/bi-engine'

export default {
  components: { BiDashboard },
  data() {
    return {
      // 使用内置模拟数据
      widgets: bi.mockData.widgets,
      layoutObj: {
        layout: [],
        dashboardName: '我的仪表板'
      }
    }
  }
}
</script>
```

## 📚 API 文档

### 主要组件

#### BiDashboard
主仪表板组件，提供完整的仪表板设计器功能。

**Props:**
- `previewFlag` (Boolean): 预览模式开关
- `layoutObj` (Object): 仪表板布局配置对象
- `widgets` (Array): 外部传入的图表组件数据
- `enableTabSwitch` (Boolean): 是否启用 tab 切换功能，默认 true

**Events:**
- `@dashboard-updated`: 仪表板更新时触发
- `@chart-selected`: 图表选中时触发
- `@tab-change`: 组件面板 tab 切换时触发，参数为 `{ tabKey, tabLabel }`

#### chartRender
图表渲染组件，用于渲染单个图表。

**Props:**
- `chartData` (Object): 图表数据配置
- `styleConfig` (Object): 样式配置

**示例:**
```javascript
<chart-render 
  :chartData="chartData" 
  :styleConfig="styleConfig"
  @chart-click="handleChartClick"
/>
```

#### cTabs
自定义标签页组件，提供美观的标签页切换功能。

**Props:**
- `tabList` (Array): 标签页列表，格式：`[{ key: 'tab1', label: '标签1' }, { key: 'tab2', label: '标签2' }]`
- `value` (String|Number): 当前激活的标签页 key

**Events:**
- `@input`: 标签页切换时触发，参数为新的 tabKey
- `@change`: 标签页切换时触发，参数为新的 tabKey

**示例:**
```javascript
<c-tabs 
  :tabList="tabList" 
  v-model="activeTab"
  @change="handleTabChange"
/>
```

### 工具函数 (utils)

提供丰富的工具函数集合：

```javascript
import { utils } from '@jzliu-cli/bi-engine'

// 图表工具函数
utils.chartUtils.elResizeObverse(element, callback)
utils.chartUtils.getParamsRowsAndColumns(data)

// 数据处理工具函数
utils.dataUtils.calcDescartes(arrays)
utils.dataUtils.transferWhiteVal(value)
utils.dataUtils.mateMapping(data)

// 样式工具函数
utils.styleUtils.generateStyle(config)

// 验证工具函数
utils.validationUtils.validateChartData(data)
```

### 配置对象 (panelConfig)

仪表板面板配置：

```javascript
import { panelConfig } from '@jzliu-cli/bi-engine'

// 获取默认配置
const defaultConfig = panelConfig.getDefaultConfig()

// 获取图表类型配置
const chartTypes = panelConfig.getChartTypes()

// 获取样式配置
const styleConfig = panelConfig.getStyleConfig()
```

### 枚举数据 (enumData)

提供各种枚举数据：

```javascript
import { enumData } from '@jzliu-cli/bi-engine'

// 聚合器映射
console.log(enumData.aggregatorMap)

// 表格类型映射
console.log(enumData.tableTypeZnMap)

// 图表系列颜色
console.log(enumData.chartSeriesColors)

// 线条类型映射
console.log(enumData.lineTypeMap)
```

### 模拟数据 (mockData)

用于开发和测试的模拟数据：

```javascript
import { mockData } from '@jzliu-cli/bi-engine'

// 获取示例图表数据
const sampleChartData = mockData.getSampleChartData()

// 获取仪表板配置示例
const sampleDashboardConfig = mockData.getSampleDashboardConfig()
```

### Store 配置 (storeConfig)

Vuex store 配置，用于状态管理：

```javascript
import { storeConfig } from '@jzliu-cli/bi-engine'
import Vuex from 'vuex'

// 创建 store 实例
const store = new Vuex.Store(storeConfig)

// 在 Vue 应用中使用
new Vue({
  store,
  // ...
})


## 📊 图表类型支持

- **柱状图** (Column)
- **折线图** (Line)  
- **饼图** (Pie)
- **表格** (Table)
- **指标卡** (IndicatorCard)

## 🔧 开发配置

### 本地开发

```bash
# 克隆项目
git clone <repository-url>

# 安装依赖
yarn install

# 启动开发服务器
yarn build:watch

# 构建生产版本
yarn build
```

### 本地链接测试

```bash
# 在 biDashboard 目录中
yarn link

# 在测试项目中
yarn link "@jzliu-cli/bi-engine"
```

## 📋 依赖要求

### 必需依赖
- Vue: ^2.6.11
- Element UI: ^2.15.10
- Vuex: ^3.6.2
- @antv/g2plot: ^2.4.13

### 可选依赖
- lodash: ^4.17.21
- vue-grid-layout: ^2.3.12
- vuedraggable: ^2.24.3

## 🎯 使用示例

### 基础图表渲染

```vue
<template>
  <div class="chart-container">
    <chart-render 
      :chartData="chartData"
      :styleConfig="styleConfig"
    />
  </div>
</template>

<script>
import { chartRender } from '@jzliu-cli/bi-engine'

export default {
  components: { chartRender },
  data() {
    return {
      chartData: {
        type: 'Column',
        name: '销售数据',
        data: {
          meta: [
            { field: 'category', name: '类别' },
            { field: 'value', name: '数值' }
          ],
          data: [
            { category: 'A', value: 100 },
            { category: 'B', value: 200 },
            { category: 'C', value: 150 }
          ]
        },
        fields: [
          {
            label: '类别轴',
            type: 'dimension',
            chooseFields: [{ name: 'category' }]
          },
          {
            label: '值轴', 
            type: 'measure',
            chooseFields: [{ name: 'value' }]
          }
        ]
      },
      styleConfig: {
        commongConfig: {
          showTitle: true,
          backgroundColor: '#fff'
        }
      }
    }
  }
}
</script>
```

### 完整仪表板

```vue
<template>
  <div class="dashboard">
    <bi-dashboard 
      :config="dashboardConfig"
      @dashboard-updated="handleDashboardUpdate"
      @chart-selected="handleChartSelect"
    />
  </div>
</template>

<script>
import BiDashboard from '@jzliu-cli/bi-engine'

export default {
  components: { BiDashboard },
  data() {
    return {
      dashboardConfig: {
        layout: [],
        dashboardName: '我的仪表板'
      }
    }
  },
  methods: {
    handleDashboardUpdate(newConfig) {
      console.log('仪表板已更新:', newConfig)
    },
    handleChartSelect(chartData) {
      console.log('图表已选中:', chartData)
    }
  }
}
</script>
```

## 🐛 问题排查

### 常见问题

1. **样式不生效**
   - 确保已导入 Element UI 样式
   - 检查样式隔离前缀是否正确

2. **图表不显示**
   - 检查数据格式是否正确
   - 确认字段映射配置

3. **组件未注册**
   - 确保已正确使用 `Vue.use(BiDashboard)`
   - 检查组件名称拼写

### 调试模式

```javascript
// 开启调试模式
Vue.use(BiDashboard, {
  debug: true,
  config: {
    // 自定义配置
  }
})
```

## 📄 许可证

MIT License

## 🤝 贡献

欢迎提交 Issue 和 Pull Request！

## 🔄 第三方项目集成示例

### 1. 基础项目配置

**main.js 配置**:
```javascript
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import Vuex from 'vuex'

// 使用 Element UI
Vue.use(ElementUI)

// 使用 Vuex (必需)
Vue.use(Vuex)

new Vue({
  render: h => h(App),
}).$mount('#app')
```

### 2. 完整仪表板使用

**编辑模式 - 支持拖拽设计**:
```vue
<template>
  <div id="app" style="min-width: 1366px;">
    <div style="height:100%;width:100%;">
      <bi-dashboard 
        :widgets="widgets" 
        :layoutObj="layoutObj" 
        @tab-change="handleTabChange" 
      />
    </div>
  </div>
</template>

<script>
import bi, { BiDashboard } from '@jzliu-cli/bi-engine'

export default {
  name: 'App',
  components: {
    BiDashboard,
  },
  data() {
    return {
      // 使用内置模拟数据
      widgets: bi.mockData.widgets,
      layoutObj: {
        "layout": [
          {
            "type": "Table",
            "defaultRows": 8,
            "dataSetId": "USER_BEHAVIOR_FACT",
            "dataSetName": "用户行为事实表",
            "name": "交叉表",
            "defaultCols": "whole",
            "className": "component-type-cross-table",
            "measures": [
              {
                "unitCode": "page_views",
                "unitName": "页面浏览量",
                "belongDimName": null
              }
            ],
            "dimensions": [
              {
                "unitCode": "user_id",
                "unitName": "用户ID",
                "belongDimName": "用户维度"
              }
            ]
          }
        ],
        "dashboardName": "我的仪表板"
      }
    }
  },
  methods: {
    handleTabChange(tabInfo) {
      console.log('Tab 切换:', tabInfo)
      // 这里可以根据 tab 切换重新加载数据
      // 例如：this.loadWidgetsByTab(tabInfo.tabKey)
    }
  }
}
</script>
```

**预览模式 - 只读展示**:
```vue
<template>
  <div id="app" style="min-width: 1366px;">
    <div style="height:100%;width:100%;">
      <Preview :widgets="widgets" :layoutObj="layoutObj" />
    </div>
  </div>
</template>

<script>
import bi, { Preview } from '@jzliu-cli/bi-engine'

export default {
  name: 'App',
  components: {
    Preview,
  },
  data() {
    return {
      widgets: bi.mockData.widgets,
      layoutObj: {
        // 仪表板布局配置
      }
    }
  }
}
</script>
```

### 3. 单独使用图表组件

**单个图表渲染**:
```vue
<template>
  <div>
    <chart-render :chartData="chartData"></chart-render>
  </div>
</template>

<script>
import BiDashboard, { chartRender, mockData, enumData } from '@jzliu-cli/bi-engine'

export default {
  name: 'ChartComponent',
  components: { chartRender },
  data() {
    return {
      // 使用内置模拟数据
      chartData: mockData.pieWidgets
    }
  }
}
</script>
```

### 4. 动态数据加载

**根据 tab 切换动态加载数据**:
```vue
<template>
  <div>
    <bi-dashboard 
      :widgets="widgets" 
      :layoutObj="layoutObj"
      @tab-change="handleTabChange"
    />
  </div>
</template>

<script>
import bi, { BiDashboard } from '@jzliu-cli/bi-engine'

export default {
  components: { BiDashboard },
  data() {
    return {
      widgets: [],
      layoutObj: {
        layout: [],
        dashboardName: '动态仪表板'
      },
      currentTab: 'all'
    }
  },
  methods: {
    async handleTabChange(tabInfo) {
      console.log('Tab 切换:', tabInfo)
      this.currentTab = tabInfo.tabKey
      
      // 根据 tab 切换重新调用接口获取数据
      await this.loadWidgets(tabInfo.tabKey)
    },
    
    async loadWidgets(tabKey) {
      try {
        // 调用你的接口获取对应 tab 的 widgets 数据
        const response = await this.$http.get(`/api/widgets?tab=${tabKey}`)
        this.widgets = response.data
      } catch (error) {
        console.error('加载 widgets 失败:', error)
        // 失败时使用默认数据
        this.widgets = bi.mockData.widgets
      }
    }
  },
  
  async created() {
    // 初始化加载数据
    await this.loadWidgets('all')
  }
}
</script>
```

### 5. 使用内置工具和配置

**使用工具函数和配置**:
```javascript
import bi, { 
  chartRender, 
  mockData, 
  enumData, 
  utils, 
  panelConfig 
} from '@jzliu-cli/bi-engine'

// 使用模拟数据
const sampleData = mockData.widgets

// 使用枚举数据
const chartTypes = enumData.chartTypeMap

// 使用工具函数
const processedData = utils.dataUtils.calcDescartes(data)

// 使用配置
const defaultConfig = panelConfig.getDefaultConfig()
```

## 🎯 常见使用场景

### 场景1: 仪表板设计器
适用于需要拖拽设计仪表板的场景，用户可以：
- 从组件面板拖拽图表到画布
- 配置图表样式和数据
- 实时预览效果
- 保存和加载仪表板配置

### 场景2: 仪表板预览
适用于只读展示的场景，用户可以：
- 查看已设计的仪表板
- 交互式浏览图表
- 响应式适配不同屏幕

### 场景3: 单个图表展示
适用于只需要展示单个图表的场景：
- 在现有页面中嵌入图表
- 使用内置的图表类型
- 自定义图表样式

### 场景4: 动态数据仪表板
适用于需要根据用户操作动态加载数据的场景：
- 根据 tab 切换加载不同数据
- 实时更新图表内容
- 支持数据筛选和查询

## 📋 数据格式说明

### widgets 数据格式
```javascript
const widgets = [
  {
    type: 'Column',           // 图表类型
    name: '柱状图',           // 图表名称
    className: 'component-type-column', // CSS 类名
    defaultImg: 'http://example.com/img.png', // 默认图片
    measures: [               // 度量字段
      {
        unitCode: 'sales',
        unitName: '销售额',
        belongDimName: null
      }
    ],
    dimensions: [             // 维度字段
      {
        unitCode: 'category',
        unitName: '类别',
        belongDimName: '商品维度'
      }
    ]
  }
]
```

### layoutObj 数据格式
```javascript
const layoutObj = {
  layout: [                   // 布局配置
    {
      type: 'Column',
      x: 0, y: 0, w: 6, h: 4, // 网格位置和大小
      i: 'unique-id',         // 唯一标识
      // ... 其他图表配置
    }
  ],
  dashboardName: '仪表板名称'
}
```

## 📞 支持

如有问题，请联系：
- 邮箱: support@jzliu-cli.com
- 文档: [在线文档](https://docs.jzliu-cli.com/bi-engine)

---

