[]
        
在线Demo 免费试用
(Showing Draft Content)

实战示例、调试运维与最佳实践

6.1 从零开发示例(ECharts Demo 落地版)

将第 2 章中的 ECharts Demo 重新整理为可执行步骤如下:

  1. wyn-visual-tools init 初始化工程。

  2. 安装 echarts@types/echarts

  3. 运行 wyn-visual-tools develop

  4. src/visual.ts 中导入并初始化 ECharts。

  5. 先渲染 mock chart,确认最小闭环跑通。

  6. capabilities.json 中增加 data binding。

  7. update() 中将 dataViews 映射为 ECharts 所需的 series / xAxis / yAxis 数据结构。

  8. onResize() 中做 resize。

  9. 增加属性并在 render() 中消费。

  10. 增加标题、交互与 action。

  11. onDestroy() 中销毁图表实例。

  12. 使用 wyn-visual-tools package 输出 .viz 并上传验证。

6.2 样式开发与动态样式

LESS 样式结构示例

@primary-color: #1890ff;
@border-color: #d9d9d9;
@text-color: #333333;
@background-color: #ffffff;

.dropdown-button {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  border: 1px solid @border-color;
  border-radius: 4px;
  background-color: @background-color;
  cursor: pointer;
  transition: all 0.3s ease;

  &:hover {
    border-color: @primary-color;
  }

  &.open {
    border-color: @primary-color;
    box-shadow: 0 0 0 2px fade(@primary-color, 20%);
  }
}

动态应用样式

private applyStyles(): void {
  const { textStyle, borderColor, backgroundColor, borderRadius } = this.properties;

  if (textStyle) {
    this.container.style.fontSize = textStyle.fontSize;
    this.container.style.fontFamily = textStyle.fontFamily;
    this.container.style.fontWeight = textStyle.fontWeight;
    this.container.style.color = textStyle.color;
  }

  this.dropdownButton.style.borderColor = borderColor || '#d9d9d9';
  this.dropdownButton.style.backgroundColor = backgroundColor || '#ffffff';
  this.dropdownButton.style.borderRadius = `${borderRadius || 4}px`;
}

6.3 构建、打包与发布运维

常用命令

npm run compile
npm run dev
npm run release
wyn-visual-tools package

发布前建议顺序

  1. 本地编译通过

  2. 在开发工具中完成联调

  3. 更新版本号

  4. 生产构建

  5. 运行 wyn-visual-tools package

  6. 上传到系统

  7. 在设计器中做最终验收

6.4 调试技巧与常见错误排查

控制台日志建议

console.log('[插件名称] 数据更新:', options.dataViews);
console.log('[插件名称] 属性变化:', options.properties);
console.log('[插件名称] 参数值:', options.watchedParameters);

常见调试场景

数据绑定问题

console.log('dataViews:', options.dataViews);
console.log('plain data:', options.dataViews[0]?.plain);
console.log('profile:', options.dataViews[0]?.plain?.profile);

属性配置问题

console.log('properties:', options.properties);
console.log('watchedParameters:', options.watchedParameters);

渲染问题

console.log('容器尺寸:', this.container.clientWidth, this.container.clientHeight);
console.log('数据:', this.data);
console.log('是否模拟数据:', this.isMock);

常见错误排查表

错误现象

可能原因

解决建议

插件不显示

构建失败

检查 webpack / package 输出

数据为空

数据绑定配置错误

检查 capabilities.jsonplain.profile

属性不生效

属性名称不匹配

检查 JSON 与 properties.xxx 一致性

参数不显示

缺少 type: interaction

在分类上增加 interaction

样式错乱

CSS 冲突

使用命名空间隔离

下拉框被遮挡

根节点挂载与层级不当

提高 z-index,挂到合适容器

选择状态不同步

SelectionManager 使用不完整

统一通过 select / clear / contains 管理

编译报错 Cannot find module

TS 配置或依赖不完整

检查 esModuleInteropresolveJsonModuleinclude

打包后文件过大

使用开发构建而非生产构建

npm run releasepackage

6.5 最佳实践

代码组织

推荐顺序:

  1. 属性声明

  2. 构造函数

  3. 生命周期方法

  4. 数据处理方法

  5. 渲染方法

  6. 事件处理方法

  7. 工具方法

性能优化

  • 用防抖处理高频更新

  • 缓存格式化结果

  • 批量 DOM 更新

  • 使用 requestAnimationFrame

示例:

private formatCache = new Map<string, string>();
private formatValue(value: number, format: string): string {
  const key = `${value}_${format}`;
  if (!this.formatCache.has(key)) {
    this.formatCache.set(key, this.host.formatService.format(format, value));
  }
  return this.formatCache.get(key)!;
}

资源清理

public onDestroy(): void {
  this.container.removeEventListener('click', this.handleClick);
  document.removeEventListener('click', this.globalClickHandler);

  if (this.debounceTimer) clearTimeout(this.debounceTimer);
  if (this.animationTimer) cancelAnimationFrame(this.animationTimer);

  if (this.chart) {
    this.chart.dispose();
    this.chart = null;
  }

  if (this.resizeObserver) {
    this.resizeObserver.disconnect();
  }

  this.formatCache.clear();
}

错误处理

private render(): void {
  try {
    this.host.eventService.renderStart();
    this.doRender();
    this.host.eventService.renderFinish();
  } catch (error) {
    console.error('[插件名称] 渲染错误:', error);
    this.host.eventService.renderError();
  }
}

6.6 FAQ / 常见问题

Q1:数据绑定后显示为空?

优先检查:

  • options.dataViews[0] 是否存在

  • plain / single / matrix 是否与 dataViewMappings 对应

  • profile 中的字段名是否与代码读取路径一致

Q2:如何支持多个字段绑定?

使用 conditions 限制数量,例如:

{
  "conditions": [
    {
      "label": { "max": 5 },
      "value": { "max": 5 }
    }
  ]
}

Q3:watchParameter 不显示参数列表?

确保:

{
  "type": "interaction",
  "watchParameter": {
    "roles": []
  }
}

Q4:属性默认值不生效?

  • 检查 capabilities.jsonname

  • 检查代码中读取的 properties.xxx

  • 两者必须一致

Q5:样式与其他插件冲突?

使用命名空间隔离:

.wyn-visual-dropdown {
  .dropdown-button {}
  .dropdown-list {}
}

Q6:点击事件不触发?

检查 stopPropagationpreventDefault 是否需要。

Q7:收费插件为什么不能激活?

  • 检查 Wyn 是否为试用版

  • 检查 .cvl 是否匹配当前大版本

  • 检查授权状态是否显示为绿色可导入

6.7 检查清单

新建插件检查清单

  • 创建标准目录结构

  • 配置 package.json

  • 配置 tsconfig.json

  • 配置 webpack.config.js

  • 准备 visual.d.ts

  • 创建 visual.json

  • 创建 capabilities.json

  • 创建 i18n 资源文件

  • 创建插件图标

  • 实现 Visual

发布前检查清单

  • 所有功能测试通过

  • 生产模式构建成功

  • 无控制台错误

  • 国际化文本完整

  • 属性配置正确

  • 数据绑定正常

  • 交互功能正常

  • 资源清理完整

  • 版本号已更新

  • .viz 文件打包成功

代码质量检查清单

  • TypeScript 类型完整

  • any 类型滥用

  • 错误处理完善

  • 资源清理完整

  • 性能优化到位

  • 命名规范统一

6.8 参考资源与附件说明

官方与技术参考

附件与截图保留说明

  1. 截图类资料

    • 已转写为入口说明、操作说明、界面说明或编辑器说明。

    • 对属性编辑器、Data Binding 面板、操作栏按钮等截图,本文均保留了其对应功能含义。

  2. 外部代码文件

    • visual.ts:ECharts Demo 数据处理代码来源

    • visual (1).ts:ECharts Demo 属性消费代码来源

    • 当前整合文档已提炼其文字信息,但未包含附件原始代码全文

  3. 压缩包附件

    • SimpleEcharts.zip:完整 Demo 工程来源

    • 当前目录未直接提供该 zip 实体文件,因此本文保留了其来源与用途说明