开发者中心 开发者中心
  • 简体中文
  • English
视频教程
敢为云网站
  • 6.0版本
  • 6.1 版本
视频教程
敢为云网站
  • 平台概述
  • 平台功能
  • 平台安装
  • 开发者指南
    • 协议插件开发
    • 扩展插件开发
    • 报警插件开发
    • 应用插件开发
      • 前端Web界面开发
      • 后端接口开发
        • 模板引擎
        • 基础开发
        • 内置特性
          • 读取配置
          • 事件总线
          • 定时作业
          • 数据转换对象(DTO)
          • 国际化语言
          • 基于公共外框使用说明
          • 各模块插件包处理
          • 基于自身外框使用说明
          • 后端使用说明
      • 插件打包和发布
    • Web可视化开发
    • 3D可视化开发
    • 桌面可视化开发
    • 小程序开发
  • 项目实战
  • 附录

内置特性

# 后端插件开发

# 读取配置

插件JSON配置名称不可更改,同时必须定义顶级根节点,建议以插件名作为顶级根节点,否则当加载多个插件,读取节点时,存在同名将会覆盖。比如读取如下根节点下Url值

底层暴露IIotConfiguration接口,将其通过构造函数注入使用,使用方式与IConfiguration接口等同

# 事件总线

引入事件总线设施从而降低代码耦合或削峰等,当前底层仅支持本地事件总线。

# 本地事件总线

所有事件总线定义以及订阅都放在IntegrationEvents目录

Events目录为事件定义,如下我们模拟定义添加用户后给用户发送邮件事件

EventHandlers目录为事件处理即订阅事件,实现ILocalEventHandler本地事件处理接口,其泛型类为对应要接收的事件

最后在Configure方法中通过底层暴露的本地事件总线接口,订阅当添加用户后,给用户发送邮件事件处理

# 全局订阅

首次加载时,立即全局订阅事件处理

# 局部订阅

我们也可以在具体某仓储接口实现中,按需局部订阅事件,比如当添加用户成功后才去订阅事件处理

紧接着在控制器构造函数中注入本地事件总线接口

最后,添加用户成功后,发布给用户发送邮件事件

# 跨库订阅

一般来讲,事件发布和订阅所属事件类型应为相同类型,但在插件化中存在事件发布和订阅处于不同库场景,此时事件发布和订阅类型不同,但属性一致,为避免代码耦合即解耦,底层设施额外扩展此使用场景。

场景假设:在插件库IoTCenter.Module.Test1发布触发发送用户邮件事件,而在IoTCenter.Module.Test2订阅用户发送邮件事件处理

如下截图:IoTCenter.Module.Test1类库中发布用户邮件事件

此类库中定义发布事件类,基础设施暴露EventName特性,通过EventName特性指定具体事件名称

如下截图:IoTCenter.Module.Test2类库中订阅用户邮件事件处理

此类库中同样使用EventName特性指定事件名称,与发布事件类型名称必须一致,同时在此特性上第二个参数必须显式标识为true

注:建议以插件名称简写作为事件名称前缀,否则,若存在同名事件名称将抛出异常

# 定时作业

利用https://github.com/atifaziz/NCrontab (opens new window)库实现计划作业表达式,包含秒级定义即支持6部分表达式定义(底层作业滚动周期为10s,所以自定义实现定时作业应>=10s)

# 使用示例

底层暴露IBackgroundTask接口,通过BackgroundTask特性配置Corn表达式

定时作业以单例形式注入

# 使用注意

在实际使用过程中,可能会出现定时任务仅运行一次或不运行情况,基于底层定时任务实现逻辑,列举如下三点使用注意事项

  1. 插件定时任务以【插件程序集名称+定时任务类名】作为计划名称,所以各插件中计划名称不可重复
  2. DoWorkAsync方法调用由底层根据滚动周期自动调用,切不可在其方法中再次使用While,否则会完全阻止其他任务调用
  3. DoWorkAsync方法建议尽可能使用异步方法,否则若业务逻辑耗时太长,会阻塞其他任务调用

# 数据转换对象(DTO)

对数据进行DTO,存在各式各样的包,基于此,底层统一规范使用AutoMapper来进行映射,关于AutoMapper这里不再做详细介绍,若不熟悉,请自行查阅相关资料并了解,为考虑到不同场景或简化等原因,底层提供多种映射使用方式

我们使用如下源目标和和映射目标作为示例演示

# 映射配置

底层暴露IAutoMapperConfig接口,创建映射配置类实现该接口,在此类中全局配置插件库中所有映射,配置类名称推荐以【插件名+ AutoMapperConfig】命名。

AutoMapper对于属性忽略映射,使用如下

.ForMember(d => d.Id, o => o.Ignore())

为进一步简化书写,底层额外扩展封装Ignore方法,使用如下

.Ignore(d => d.Id)

例如,如下所示,我们仅配置映射属性Name,但忽略映射Id

# 映射方式(一)

底层通过对外暴露IObjectMapping接口来进行对象映射,如下以构造函数注入使用

调用接口中的Map方法完成从源目标到映射目标的数据映射,此方式乃AutoMapper内置映射使用方式

同样,我们通过Postman来模拟验证测试下

# 映射方式(二)

上述为AutoMapper框架默认映射方式,但底层额外基于object提供了扩展方法,更加方便简洁化,所以我们不再通过IObjectMapping接口进行映射

比如上述通过源对象CreateUserDTO映射到目标对象UserTest,导入命名空间【IoTCenterCore.AutoMapper】,然后调用MapTo扩展方法,我们可修改为如下

调用MapToList方法将映射源集合映射到目标集合

# 国际化语言

# 前端使用说明

# 翻译包说明

我们以设备列表为例,各个插件翻译包统一存储在en-US和zh-CN目录下中的Front目录,其命名规则为插件名.页面名(如:ganwei-iotcenter-equip-lists.equipListsIot.json)

Json文件配置示例:(ganwei-iotcenter-equip-lists.equipListsIot.json),前端约定命名格式:

以常规组件为前缀key,内部根据页面自行定义,统一为驼峰命名,

示例:(输入框)

{
    “input”:{
    “inputSearchEquip”:”搜索设备名称”
    }
}

# 基于公共外框使用说明

在登录界面进行切换(需下载最新登录包)

若不启用国际语言切换,可在外框中config.json配置

# 各模块插件包处理

以设备列表(ganwei-base-equip-lists)为例,在App.vue中:

import moduleObserve from 'gw-base-utils/moduleObserve'

mixins: [moduleObserve],

Index.js入口文件使用

import i18n from 'gw-base-utils/i18n.js'

页面使用:设备列表为例子,其他一样使用方式

# 基于自身外框使用说明

# 外框修改

  1. 在外框jumpIframePro中引入

  1. 外框main.js中引入中英文

import i18n from 'gw-base-utils/i18n.js'

基于自身登录页面(Login.vue)配置说明:

import changeLanguage from 'gw-base-utils-plus/changeLanguage'
mixins: [changeLanguage],
this.showLangSelect = data.showLangSelect;
    if (!this.showLangSelect) {
        window.localStorage.languageType = 'zh-CN'
    }
await this.initLanguage();

<el-select	v-if="showLangSelect"	v-model="languageSelected" @change="langChange" class="languageSelect">
    <template slot="prefix">
        <i class="iconfont icon-gw-icon-diqiu"></i>
    </template>
    <el-option	v-for="(item,index)	in langOptions" :label="item.name" :value="item.value" :key="index">
    </el-option>
</el-select>

样式参考:login.scss

/deep/ .languageSelect {
    position: fixed;
    right: 30px;
    top: 30px;
    width: 150px;

    .el-input {
        width: 150px;
    }
    .el-input__prefix {
        display: flex;
        justify-content: center;
        align-items: center;
    }
}

# 各模块插件包处理

以设备列表(ganwei-base-equip-lists)为例,在App.vue中:

import moduleObserve from 'gw-base-utils/moduleObserve'
mixins: [moduleObserve],

Index.js入口文件使用

import i18n from 'gw-base-utils/i18n.js'

页面使用:以设备列表为例,其他一样使用方式

# APi请求处理

let languageType = window.localStorage.languageType
if (languageType && languageType !== 'zh-CN') {
    config.url = config.url + config.url.includes('?') ? '&' : '?' + 'culture=' + languageType
}

# 后端使用说明

# 公共翻译和插件翻译

公共翻译和插件翻译

前端页面内容和相关操作等提示都由后台统一返回,我们将翻译分为公共翻译和插件翻译两部分。如下截图插件作为国际化插件入口,其Localization目录作为全局国际化公共翻译

zh-CN文件:公共中文翻译

en-US文件:公共英文翻译

指定插件国际化翻译目录如下:

# zh-CN目录

  1. Back:后台插件中文翻译

  2. Front:前端UI中文翻译

# en-US目录

  1. Back:后台插件英文翻译

  2. Front:前端UI英文翻译

注1:前端文件命名约定【前端插件名.子菜单名.json】

注2:后台插件命名约定【插件名.json】

# 使用示例

我们以如下截图设备列表中文翻译为例,作进一步详细说明

  1. 前端UI

  1. 后端响应

翻译模板json数组内容:

msgid “填写翻译键” msgstr “填写翻译值”

使用.NET Core框架所提供【IStringLocalizer<T>】构造函数注入,进行翻译。

private readonly IStringLocalizer<T> _stringLocalizer;

# 公共翻译内容

建议翻译键以【common_】作为前缀,其他单词通过下划线隔开

若需响应参数不正确或参数为空或不能为空等,对应公共翻译键如_stringLocalizer["common_parameter_is_incorrect"]

# 插件翻译内容

建议翻译键以【插件名简称_】作为前缀,其他单词通过下划线隔开

比如翻译设备不存在,_stringLocalizer["equip_config_device_not_exist"]

上次更新: 3/23/2023, 3:15:49 PM

← 基础开发 插件打包和发布→

目录
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式