4.1.10 函数之触发与定时(改)

函数的触发和定时在很多场景中会用到,也是一个oinone的基础能力。比如我们的流程产品中在定义流程触发时就会让用户选择模型触发还是时间触发,就是用到了函数的触发与定时能力。

整体链路示意图(如下图4-1-10-1 所示),本文只讲trigger里的两类任务,一个是触发任务,一个是定时任务,异步任务放在4.1.11【函数之异步执行】一文中单独去介绍。

4.1.10 函数之触发与定时(改)

图4-1-10-1 整体链路示意图

一、触发任务TriggerTaskAction(举例)

触发任务的创建,使用pamirs-middleware-canal监听mysql的binlog事件,通过rocketmq发送变更数据消息,收到MQ消息后,创建TriggerAutoTask。

触发任务的执行,使用TBSchedule拉取触发任务后,执行相应函数。

注意:pamirs-middleware-canal监听的数据库表必须包含触发模型的数据库表。

Step1 下载canal中间件

下载pamirs-middleware-canal-deployer-3.0.1.zip,去.txt后缀为pamirs-middleware-canal-deployer-3.0.1.zip,解压文件如下:

4.1.10 函数之触发与定时(改)

图4-1-10-2 下载canal中间件

Step2 引入依赖pamirs-core-trigger模块

  1. pamirs-demo-api增加pamirs-trigger-api
<dependency>
        <groupId>pro.shushi.pamirs.core</groupId>
        <artifactId>pamirs-trigger-api</artifactId>
</dependency>

图4-1-10-3 pamirs-trigger-api依赖包

  1. DemoModule在模块依赖定义中增加@Module(dependencies={TriggerModule.MODULE_MODULE})
@Component
@Module(
        name = DemoModule.MODULE_NAME,
        displayName = "oinoneDemo工程",
        version = "1.0.0",
        dependencies = {ModuleConstants.MODULE_BASE, CommonModule.MODULE_MODULE, UserModule.MODULE_MODULE, TriggerModule.MODULE_MODULE}
)
@Module.module(DemoModule.MODULE_MODULE)
@Module.Advanced(selfBuilt = true, application = true)
@UxHomepage(PetShopProxy.MODEL_MODEL)
public class DemoModule implements PamirsModule {
    ……其他代码
}

图4-1-10-4 模块依赖中增加Trigger模块

  1. pamirs-demo-boot 增加pamirs-trigger-core和pamirs-trigger-bridge-tbschedule的依赖
<dependency>
        <groupId>pro.shushi.pamirs.core</groupId>
        <artifactId>pamirs-trigger-core</artifactId>
</dependency>
<dependency>
        <groupId>pro.shushi.pamirs.core</groupId>
        <artifactId>pamirs-trigger-bridge-tbschedule</artifactId>
</dependency>

图4-1-10-5 增加pamirs-trigger-core和pamirs-trigger-bridge-tbschedule的依赖

  1. 修改pamirs-demo-boot的applcation-dev.yml

    1. 修改pamris.event.enabled和pamris.event.schedule.enabled为true

    2. pamirs_boot_modules增加启动模块:trigger

pamirs: 
  event:
    enabled: true
    schedule:
      enabled: true
    rocket-mq:
      namesrv-addr: 127.0.0.1:9876
  boot:
    init: true
    sync: true
    modules:
      - base
      - common
      - sequence
      - resource
      - user
      - auth
      - message
      - international
      - business
      - trigger
      - demo_core

图4-1-10-6 启动模块中增加trigger模块

Step3 启动canal中间件

  1. canal的库表需要手工建
create schema canal_tsdb collate utf8mb4_bin

图4-1-10-7 canal的建库语句

CREATE TABLE IF NOT EXISTS `meta_snapshot` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL COMMENT '修改时间',
  `destination` varchar(128) DEFAULT NULL COMMENT '通道名称',
  `binlog_file` varchar(64) DEFAULT NULL COMMENT 'binlog文件名',
  `binlog_offest` bigint(20) DEFAULT NULL COMMENT 'binlog偏移量',
  `binlog_master_id` varchar(64) DEFAULT NULL COMMENT 'binlog节点id',
  `binlog_timestamp` bigint(20) DEFAULT NULL COMMENT 'binlog应用的时间戳',
  `data` longtext DEFAULT NULL COMMENT '表结构数据',
  `extra` text DEFAULT NULL COMMENT '额外的扩展信息',
  PRIMARY KEY (`id`),
  UNIQUE KEY binlog_file_offest(`destination`,`binlog_master_id`,`binlog_file`,`binlog_offest`),
  KEY `destination` (`destination`),
  KEY `destination_timestamp` (`destination`,`binlog_timestamp`),
  KEY `gmt_modified` (`gmt_modified`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='表结构记录表快照表';

CREATE TABLE IF NOT EXISTS `meta_history` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL COMMENT '修改时间',
  `destination` varchar(128) DEFAULT NULL COMMENT '通道名称',
  `binlog_file` varchar(64) DEFAULT NULL COMMENT 'binlog文件名',
  `binlog_offest` bigint(20) DEFAULT NULL COMMENT 'binlog偏移量',
  `binlog_master_id` varchar(64) DEFAULT NULL COMMENT 'binlog节点id',
  `binlog_timestamp` bigint(20) DEFAULT NULL COMMENT 'binlog应用的时间戳',
  `use_schema` varchar(1024) DEFAULT NULL COMMENT '执行sql时对应的schema',
  `sql_schema` varchar(1024) DEFAULT NULL COMMENT '对应的schema',
  `sql_table` varchar(1024) DEFAULT NULL COMMENT '对应的table',
  `sql_text` longtext DEFAULT NULL COMMENT '执行的sql',
  `sql_type` varchar(256) DEFAULT NULL COMMENT 'sql类型',
  `extra` text DEFAULT NULL COMMENT '额外的扩展信息',
  PRIMARY KEY (`id`),
  UNIQUE KEY binlog_file_offest(`destination`,`binlog_master_id`,`binlog_file`,`binlog_offest`),
  KEY `destination` (`destination`),
  KEY `destination_timestamp` (`destination`,`binlog_timestamp`),
  KEY `gmt_modified` (`gmt_modified`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='表结构变化明细表';

CREATE TABLE IF NOT EXISTS `canal_filter` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `destination` varchar(128) NOT NULL COMMENT '通道名称',
  `filter` text NOT NULL COMMENT '过滤表达式',
  `create_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `write_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY destination(`destination`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='通道过滤';

CREATE TABLE IF NOT EXISTS `canal_destination` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `destination` varchar(128) NOT NULL COMMENT '通道名称',
  `content` text NOT NULL COMMENT '通道配置内容',
  `create_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `write_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `destination` (`destination`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='通道配置'

图4-1-10-8 canal的建表语句

  1. 修改canal的启动配置

    1. canal_tsdb就是上面建库,用户名和密码换成本机的

    2. 配置filter: demo.demo_core_pet_talent,监听PetTalent模型数据变化,filter为canal第一次启动默认监听的表。如果数据库中canal_filter表有数据这个修改无效

    3. filter目前需要手工配置,在下个版本中已经去掉了手工配置,而且文中的canal中间件已经是2.2.2版本了,兼容当前教程的版本

pamirs:
  middleware:
    data-source:
      jdbc-url: jdbc:mysql://localhost:3306/canal_tsdb?useUnicode=true&characterEncoding=utf-8&verifyServerCertificate=false&useSSL=false&requireSSL=false
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: oinone
  canal:
    ip: 127.0.0.1
    port: 1111
    metricsPort: 1112
    zkClusters:
      - 127.0.0.1:2181
    destinations:
      - destinaion: pamirschangedata
        name: pamirschangedata
        desc: pamirschangedata
        slaveId: 1235
        filter: demo\.demo_core_pet_talent
        dbUserName: root
        dbPassword: oinone
        memoryStorageBufferSize: 65536
        topic: CHANGE_DATA_EVENT_TOPIC
        dynamicTopic: false
        dbs:
          - { address: 127.0.0.1, port: 3306 }
    tsdb:
      enable: true
      jdbcUrl: "jdbc:mysql://127.0.0.1:3306/canal_tsdb"
      userName: root
      password: oinone
    mq: rocketmq
    rocketmq:
      namesrv: 127.0.0.1:9876
      retryTimesWhenSendFailed: 5
dubbo:
  application:
    name: canal-server
    version: 1.0.0
  registry:
    address: zookeeper://127.0.0.1:2181
  protocol:
    name: dubbo
    port: 20881
  scan:
    base-packages: pro.shushi  
server:
  address: 0.0.0.0
  port: 10010
  sessionTimeout: 3600

图4-1-10-9 修改canal的启动配置

pamirs.canal相关配置说明

canal.ip: 运行时ip

canal.port: 运行时端口

canal.zkClusters: 连接zookeeper集群地址

canal.destinations: 运行时Canal的所有实例

canal.destinations.destinaion: Canal的单个实例配置值为所有实例唯一

canal.destinations.destinaion.id: 与canal.destinations.destinaion.slaveId配置一致

canal.destinations.destinaion.slaveId: 为Canal的实例ID

canal.destinations.destinaion.filter: 为Canal监听过滤正则

canal.destinations.destinaion.dbUserName: 为Canal监听的MySQL的用户名

canal.destinations.destinaion.dbPassword: 为Canal监听的MySQL的用户密码

canal.destinations.destinaion.topic: 为监听到数据后往RocketMQ的指定Topic发送消息

canal.destinations.destinaion.dbs: 为连接的MySQL实例的ip和端口,如果为主从配置且主从都开启了Binlog同步功能则可以配置两个地址

canal.destinations.destinaion.memoryStorageBufferSize与canal.destinations.destinaion.dynamicTopic为固定值不需要更改

canal.tsdb: 用来保存canal运行时的元数据,配置为canal_tsdb库相关的连接信息

  1. 启动canal中间件

    1. 进入canal中间件解压目录执行下面命令就可以启动

    2. --spring.config.location请配置绝对路径,换成自己本机的就可以

java -jar  pamirs-middleware-canal-deployer-3.0.1-SNAPSHOT.jar --spring.config.location=/Users/oinone/Documents/oinone/canel/pamirs-middleware-canal-deployer-3.0.1/canal-config/application-dev.yml --spring.profiles.active=dev

图4-1-10-10 启动canal中间件

Step4 新建触发任务

新建PetTalentTrigger类,当PetTalent模型的数据记录被新建时触发系统做一些事情

package pro.shushi.pamirs.demo.core.trigger;

import pro.shushi.pamirs.demo.api.model.PetTalent;
import pro.shushi.pamirs.meta.annotation.Fun;
import pro.shushi.pamirs.meta.annotation.Function;
import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.trigger.annotation.Trigger;
import pro.shushi.pamirs.trigger.enmu.TriggerConditionEnum;

@Fun(PetTalent.MODEL_MODEL)
@Slf4j
public class PetTalentTrigger {
    @Function
    @Trigger(displayName = "PetTalent创建时触发",name = "PetTalent#Trigger#onCreate",condition = TriggerConditionEnum.ON_CREATE)
    public PetTalent onCreate(PetTalent data){
        log.info(data.getName() + ",被创建");
        //可以增加逻辑
        return data;
    }
}

图4-1-10-11 新建触发任务

Step5 重启应用看效果

  1. 解决启动是dubbo报错

启动过程中会报如下错误,虽然不影响结果,但是还是要把它消灭掉。修改bootstarp.yml文件关闭SpringCloud的自动注册就好了

4.1.10 函数之触发与定时(改)

图4-1-10-12 解决启动是dubbo报错

spring:
  profiles:
    active: dev
  application:
    name: pamirs-demo
  cloud:
    service-registry:
        auto-registration:
        enabled: false
pamirs:
  default:
    environment-check: true
    tenant-check: true

---
spring:
  profiles: dev
  cloud:
    config:
      enabled: false
      uri: http://127.0.0.1:7001
      label: master
      profile: dev
    nacos:
      server-addr: http://127.0.0.1:8848
      discovery:
        enabled: false
        namespace:
        prefix: application
        file-extension: yml
      config:
        enabled: false
        namespace:
        prefix: application
        file-extension: yml

dubbo:
  application:
    name: pamirs-demo
    version: 1.0.0
  registry:
    address: zookeeper://127.0.0.1:2181
  protocol:
    name: dubbo
    port: -1
  #    serialization: pamirs
  scan:
    base-packages: pro.shushi
  cloud:
    subscribed-services:

---
spring:
  profiles: test
  cloud:
    config:
      enabled: false
      uri: http://127.0.0.1:7001
      label: master
      profile: test
    nacos:
      server-addr: http://127.0.0.1:8848
      discovery:
        enabled: false
        namespace:
        prefix: application
        file-extension: yml
      config:
        enabled: false
        namespace:
        prefix: application
        file-extension: yml

dubbo:
  application:
    name: pamirs-demo
    version: 1.0.0
  registry:
    address: zookeeper://127.0.0.1:2181
  protocol:
    name: dubbo
    port: -1
  #    serialization: pamirs
  scan:
    base-packages: pro.shushi
  cloud:
    subscribed-services:

图4-1-10-13 关闭SpringCloud的自动注册

  1. 再次重启查看效果

前端新增一个宠物达人,在后台Console搜索“被创建”,我们就看到对应由触发器打印出来的日志

4.1.10 函数之触发与定时(改)

图4-1-10-14 示例效果

4.1.10 函数之触发与定时(改)

图4-1-10-15 示例效果

Step6 修改canal的Topic

在分布式环境下可以通过修改canal的topic(canal.destinations.destinaion.topic)来个隔离多个应用的触发消息。

  1. 新建DemoNotifyTopicEdit利用Topic修改api,增加后缀【"_"+ DemoModule.MODULE_MODULE】

  2. canal的配置canal.destinations.destinaion.topic改为:CHANGE_DATA_EVENT_TOPIC_demo_core

  3. 小伙伴自行测试

package pro.shushi.pamirs.demo.core.mq;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.demo.api.DemoModule;
import pro.shushi.pamirs.framework.connectors.event.spi.NotifyTopicEditorApi;
import pro.shushi.pamirs.trigger.constant.NotifyConstant;

@Component
public class DemoNotifyTopicEdit  implements NotifyTopicEditorApi {
    @Override
    public String handlerTopic(String topic) {
        if(NotifyConstant.AUTO_TRIGGER_TOPIC.equals(topic)){
            return NotifyConstant.AUTO_TRIGGER_TOPIC +"_"+ DemoModule.MODULE_MODULE;
        }
        return topic;
    }
}

图4-1-10-16 修改canal的Topic

pamirs:
  middleware:
    data-source:
      jdbc-url: jdbc:mysql://localhost:3306/canal_tsdb?useUnicode=true&characterEncoding=utf-8&verifyServerCertificate=false&useSSL=false&requireSSL=false
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: oinone
  canal:
    ip: 127.0.0.1
    port: 1111
    metricsPort: 1112
    zkClusters:
      - 127.0.0.1:2181
    destinations:
      - destinaion: pamirschangedata
        name: pamirschangedata
        desc: pamirschangedata
        slaveId: 1235
        filter: demo\.demo_core_pet_talent
        dbUserName: root
        dbPassword: oinone
        memoryStorageBufferSize: 65536
        topic: CHANGE_DATA_EVENT_TOPIC_demo_core
        dynamicTopic: false
        dbs:
          - { address: 127.0.0.1, port: 3306 }
    tsdb:
      enable: true
      jdbcUrl: "jdbc:mysql://127.0.0.1:3306/canal_tsdb"
      userName: root
      password: oinone
    mq: rocketmq
    rocketmq:
      namesrv: 127.0.0.1:9876
      retryTimesWhenSendFailed: 5
dubbo:
  application:
    name: canal-server
    version: 1.0.0
  registry:
    address: zookeeper://127.0.0.1:2181
  protocol:
    name: dubbo
    port: 20881
  scan:
    base-packages: pro.shushi  
server:
  address: 0.0.0.0
  port: 10010
  sessionTimeout: 3600

图4-1-10-17 修改canal.destinations.destinaion.topic配置

二、定时任务

定时任务是一种非常常见的模式,这里就不介绍概念了,直接进入示例环节

Step1 新建PetTalentAutoTask实现ScheduleAction

注:

  1. getInterfaceName()需要跟taskAction.setExecuteNamespace定义保持一致,都是函数的命名空间

  2. taskAction.setExecuteFun("execute");跟执行函数名“execute”一致

  3. TaskType需配置为CYCLE_SCHEDULE_NO_TRANSACTION_TASK,把定时任务的schedule线程分开,要不然有一个时间长的任务会导致普通异步或触发任务全部延时

package pro.shushi.pamirs.demo.core.task;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.core.common.enmu.TimeUnitEnum;
import pro.shushi.pamirs.demo.api.model.PetTalent;
import pro.shushi.pamirs.meta.annotation.Fun;
import pro.shushi.pamirs.meta.annotation.Function;
import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.meta.domain.fun.FunctionDefinition;
import pro.shushi.pamirs.middleware.schedule.api.ScheduleAction;
import pro.shushi.pamirs.middleware.schedule.common.Result;
import pro.shushi.pamirs.middleware.schedule.domain.ScheduleItem;
import pro.shushi.pamirs.middleware.schedule.eunmeration.TaskType;
import pro.shushi.pamirs.trigger.enmu.TriggerTimeAnchorEnum;
import pro.shushi.pamirs.trigger.model.ScheduleTaskAction;
import pro.shushi.pamirs.trigger.service.ScheduleTaskActionService;

@Slf4j
@Component
@Fun(PetTalent.MODEL_MODEL)
public class PetTalentAutoTask implements ScheduleAction {

    @Autowired
    private ScheduleTaskActionService scheduleTaskActionService;

    public void initTask(){
        ScheduleTaskAction taskAction = new ScheduleTaskAction();
        taskAction.setDisplayName("定时任务测试"); //定时任务描述
        taskAction.setDescription("定时任务测试");
        taskAction.setTechnicalName(PetTalent.MODEL_MODEL+"#"+PetTalentAutoTask.class.getSimpleName()+"#"+"testAutoTask");       //设置定时任务技术名
        taskAction.setLimitExecuteNumber(-1);   //设置执行次数
        taskAction.setPeriodTimeValue(1);       //设置执行周期规则
        taskAction.setPeriodTimeUnit(TimeUnitEnum.MINUTE);
        taskAction.setPeriodTimeAnchor(TriggerTimeAnchorEnum.START);
        taskAction.setLimitRetryNumber(1);      //设置失败重试规则
        taskAction.setNextRetryTimeValue(1);
        taskAction.setNextRetryTimeUnit(TimeUnitEnum.MINUTE);
        taskAction.setExecuteNamespace(PetTalent.MODEL_MODEL);
        taskAction.setExecuteFun("execute");
        taskAction.setExecuteFunction(new FunctionDefinition().setTimeout(5000));
        taskAction.setTaskType(TaskType.CYCLE_SCHEDULE_NO_TRANSACTION_TASK.getValue()); //设置定时任务,执行任务类型
        taskAction.setContext(null);            //用户传递上下文参数
        taskAction.setActive(true);             //定时任务是否生效
        taskAction.setFirstExecuteTime(System.currentTimeMillis());
        scheduleTaskActionService.submit(taskAction);//初始化任务,幂等可重复执行
    }

    @Override
    public String getInterfaceName() {return PetTalent.MODEL_MODEL;}

    @Override
    @Function
    public Result<Void> execute(ScheduleItem item) {
        log.info("testAutoTask,上次执行时间"+item.getLastExecuteTime());
        return new Result<>();
    }
}

图4-1-10-18 新建PetTalentAutoTask实现ScheduleAction

Step2 修改DemoModuleBizInit,进行定时任务初始化

模块更新的时候调用
petTalentAutoTask.initTask(),initTask本身是幂等的所以多掉几次没有关系。在4.1.3【模块之生命周期】一文介绍过InstallDataInit、UpgradeDataInit、ReloadDataInit,您有兴趣可以去回顾下。

package pro.shushi.pamirs.demo.core.init;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.boot.common.api.command.AppLifecycleCommand;
import pro.shushi.pamirs.boot.common.api.init.InstallDataInit;
import pro.shushi.pamirs.boot.common.api.init.ReloadDataInit;
import pro.shushi.pamirs.boot.common.api.init.UpgradeDataInit;
import pro.shushi.pamirs.demo.api.DemoModule;
import pro.shushi.pamirs.demo.api.enumeration.DemoExpEnumerate;
import pro.shushi.pamirs.demo.core.task.PetTalentAutoTask;
import pro.shushi.pamirs.meta.common.exception.PamirsException;

import java.util.Collections;
import java.util.List;

@Component
public class DemoModuleBizInit implements InstallDataInit,
    UpgradeDataInit, ReloadDataInit {

    @Autowired
    private PetTalentAutoTask petTalentAutoTask;

    @Override
    public boolean upgrade(AppLifecycleCommand command, String version, 
                           String existVersion) {
        petTalentAutoTask.initTask(); //初始化petTalent的定时任务
        return Boolean.TRUE;
    }

    @Override
    public List<String> modules() {
        return Collections.singletonList(DemoModule.MODULE_MODULE);
    }

    @Override
    public int priority() {return 0;}
}

图4-1-10-19 修改DemoModuleBizInit,进行定时任务初始化

Step3 重启看效果

4.1.10 函数之触发与定时(改)

图4-1-10-20 示例效果

Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9285.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(0)
史, 昂的头像史, 昂数式管理员
上一篇 2024年5月23日 am8:53
下一篇 2024年5月23日 am8:55

相关推荐

  • 数据大屏

    1. 业务场景 数据大屏是利用相应的系统来分析数据,通过图形的形式为企业提供客观、直接的数据分析结果,让业务人员和企业决策者直观面对数据背后的信息,实时监测企业数据,给予更直观的决策场景体验,助力企业数字化运营升级。 2. 操作流程 1)进入数据可视化,进入数据大屏tab,维护分组信息; 2)在二级分组名称后点击“+”【添加数据大屏】,对数据大屏进行设计; 3)创建完成后可以【编辑】数据大屏; 4)数据大屏完善后,可以点击【发布】数据大屏,则数据大屏此时可以被显示器引用播放; 5)如果数据大屏有更新,则可以点击【更新发布】; 6)如果数据大屏数据不再可以公开使用,则需要通过【隐藏】功能将数据大屏的引用权限收起,但不影响已被使用的数据大屏; 7)隐藏后可以【取消隐藏】,数据大屏恢复隐藏前的状态和功能,可以被引用 。 3. 操作流程图解 3.1 创建分组 1)操作流程:创建分组 2)操作路径:数据可视化-数据大屏-创建分组 3)点击搜索框后的「+」创建一级分组,输入一级分组名称后,点击一级分组后的「+」创建二级分组,输入二级分组名称后,此时分组创建完成,可以在二级分组下创建数据大屏 3.2 编辑分组名称 1)操作流程:选择分组-编辑分组名称 2)操作路径:数据可视化-数据大屏-编辑分组名称 3)鼠标移动至需要修改的分组上,点击出现的「编辑图标」,可以修改分组名称,修改后分组名称实时更新 3.3 删除分组 1)操作流程:选择分组-删除分组 2)操作路径:数据可视化-数据大屏-删除分组 3)鼠标移动至需要删除的分组上,当分组下无报表时出现「删除图标」,可以点击图标后删除分组,删除一级分组时对应所有的二级分组也会被删除,删除后消失,只有分组下没有数据大屏的分组才能直接删除成功 3.4 创建数据大屏 1)操作流程:选择二级分组-创建数据大屏 2)操作路径:数据可视化-数据大屏-二级分组-创建数据大屏 3)鼠标移动至需要创建数据大屏的二级分组上,出现「+」,点击图标后=需要填写数据大屏标题 a数据大屏标题:最大支持20个字,支持汉字、数字、大小写字母、-;同个一级分组下不允许重复; 4)输入标题后进入设计页面 3.5 编辑数据大屏 1)操作流程:选择数据大屏-编辑数据大屏 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-编辑数据大屏 3)只能编辑未发布或者已发布但没有被隐藏的数据大屏,且存在三种编辑情况 a. 第一种:点击数据大屏标题后的编辑图标,仅能编辑数据大屏标题; b. 第二种:点击数据大屏中的数据大屏标题、备注后的编辑图标,可以直接编辑数据大屏标题; c. 第三种:点击【编辑】按钮,进入数据大屏设计页面,带出已有的组件内容,编辑时的规则与创建时一致,编辑后可以点击保存进行更新,如果未保存直接返回,则编辑无效; 4)编辑后实时生效,数据大屏信息保持展示最新效果 3.6 删除数据大屏 1)操作流程:选择数据大屏-删除数据大屏 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-删除数据大屏 3)未发布或者已发布但没有被隐藏的数据大屏,并且没被引用,才展示数据大屏菜单名称后的删除图标 4)删除后数据大屏消失 3.7 复制 1)操作流程:选择数据大屏-复制数据大屏 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-复制数据大屏 3)点击【复制】按钮,复制成功,名称为copy of 原数据大屏标题,展示在原数据大屏分组的最后一个 3.8 发布 1)操作流程:选择数据大屏-发布数据大屏 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-发布 3)选择单个未发布且没有被隐藏的数据大屏,点击【发布】按钮,数据大屏状态变为已发布,展示最近发布时间; 4)如果数据大屏发布后有更新内容,会展示的更新类型:更新数据大屏信息/更新数据大屏内容 3.9 查看最近一次发布的版本 1)操作流程:选择数据大屏-查看最近一次发布的版本 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-更新发布数据大屏 3)当数据大屏发布后有更新,在最近发布时间左侧展示【查看】,在最近发布时间下展示更新的类型,点击查看可以查看最近发布的版本 3.10 更新发布 1)操作流程:选择数据大屏-更新发布数据大屏 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-更新发布数据大屏 3)选择单个已发布且没有被隐藏的数据大屏,并且该数据大屏在上次发布后有所更新,可以点击【更新发布】按钮,将最新的数据大屏内容发布至业务系统,业务系统引用的数据大屏为最新内容; 4)如果更新了内容,但未点击更新发布,则展示的仍是上次发布的数据大屏 3.11 隐藏 1)操作流程:选择数据大屏-隐藏数据大屏 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-隐藏数据大屏 3)数据大屏默认不隐藏,点击数据大屏左侧的是否隐藏可以切换 a. 未发布的数据大屏,较隐藏前,不可以操作【发布】,可以【取消隐藏】; b. 已发布的数据大屏,较隐藏前,只能操作【导出图片、导出excel、取消隐藏】; 4)隐藏后的数据大屏不可以被用于展示在其他大屏上,但不影响已经被引用的数据 3.12 取消隐藏 1)操作流程:选择数据大屏-取消隐藏数据大屏 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-取消隐藏数据大屏 3)隐藏后的数据大屏可以取消隐藏,切换是否隐藏=否,取消隐藏后,数据大屏恢复隐藏前的状态和功能,可以被引用 3.13 查看引用 1)流程:选择图表-查看被哪些报表/数据大屏/页面引用 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-更多-查看引用 3)选择具体的数据大屏,查看当前数据大屏被引用的所有信息 3.14 不允许别人编辑 1)流程:选择数据大屏-不允许别人编辑 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-更多-不允许别人编辑 3)选择自己创建的数据大屏,对数据大屏是否允许其他人编辑进行设置;如果设置为不允许,则其他人无法编辑数据大屏 3.15 不允许别人引用 1)流程:选择图表-更多-不允许别人引用 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-更多-不允许别人引用 3)选择自己创建的数据大屏,对数据大屏是否允许他人引用进行设置;如果设置为不允许,则其他人无法选择到 3.16 导出图片 1)操作流程:选择数据大屏-导出图片 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-导出图片 3)选择数据大屏后,点击【导出图片】按钮可以将当前数据大屏导出为图片 3.17 导出EXCEL 1)操作流程:选择数据大屏-导出EXCEL 2)操作路径:数据可视化-数据大屏-二级分组-数据大屏-数据大屏导出EXCEL 3)选择数据大屏后,点击【导出EXCEL】按钮可以将当前数据大屏包含的图表导出为EXCEL 4. 数据大屏设计页面 4.1 缩放自适应 1)流程:创建数据大屏-进入数据大屏设计页面 2)操作路径:数据可视化-数据大屏-创建/编辑-设计页面 3)进入页面后,默认按照当前屏幕展示最适合的数据大屏尺寸,可以通过+、-进行自定义缩放,每次缩放10% 4.2 全屏 1)流程:创建数据大屏-进入数据大屏设计页面 2)操作路径:数据可视化-数据大屏-创建/编辑-设计页面 3)进入页面后,设置完成,可以【全屏】查看效果,按esc退出全屏 4.3 保存 1) 流程:创建数据大屏-进入数据大屏设计页面 2) 操作路径:数据可视化-数据大屏-创建/编辑-设计页面 3) 进入页面后,设置完成后进行保存,数据大屏保持最新内容 4.4 添加、编辑、删除组件 1)流程:创建数据大屏-进入数据大屏设计页面 2)操作路径:数据可视化-数据大屏-创建/编辑-设计页面 3)可以添加图表、文本、通用标题、倒计时、时间器、图片、轮播图、视频、边框等组件;图表组件中,一个图表只能添加一次,其他组件不限制数量; 4)所有组件添加后均可进行设置样式,有编辑权限的图表组件可以通过【编辑】图标直接进入图表设计页面; 5)添加后均可删除,删除后组件不再展示在数据大屏画布中,可以重新添加 4.5 数据大屏设置 1)操作流程:创建数据大屏-进入数据大屏设计页面 2)操作路径:数据可视化-数据大屏-创建/编辑-设计页面 3)设置数据大屏时可以设置屏幕的宽高、背景颜色、背景图片、主题 a. 宽高:根据数据大屏需要投放的屏幕大小进行设置; b. 背景颜色:当数据大屏无图片背景时可以调整背景颜色; c. 背景图片:支持为数据大屏上传一张图片作为背景; d. 主题模版:可任选其一,需要先选定模版后再进行设计,不然设计完后再修改模版,会清空已选组件。 4.6 图表组件设置 1)操作流程:创建数据大屏-进入数据大屏设计页面 2)操作路径:数据可视化-数据大屏-创建/编辑-设计页面 3)拖入图表组件,可与边框合为一体,可以设置图表的显示内容、边框信息、动画效果、刷新频率 a. 图表显示内容:展示标题、副标题、描述、标签、图例,一屏展示条数,原图表有的内容在设置展示后展示在数据大屏,原图表没有的内容设置展示后不生效; b. 边框信息:包括边框样式、背景颜色、边框线条颜色、展示边框标题、边框标题内容、边框标题颜色、边框标题字体大小; c. 动画效果:可以设置自动轮播,为是时可以设置结束后停顿时长、速度、切换形式; d. 刷新频率:设置图表获取数据的频率,自动刷新、刷新频率。 4.7 文本组件设置 1)操作流程:创建数据大屏-进入数据大屏设计页面 2)操作路径:数据可视化-数据大屏-创建/编辑-设计页面 3)拖入文本组件后,可以输入多行文本,可以设置内容、对齐方式、字体大小、字体加粗、字体颜色、背景颜色、边框样式、文字滚动、结束后停顿、速度 4)当文字滚动开启时,文字会按照一行展示,通过设置结束后停顿和速度来控制文字滚动的效果 4.8 通用标题组件设置…

    2024年6月20日
    1.0K00
  • 3.5.7.5 自定义动作

    动作是什么 动作(action)描述了终端用户的各种操作。这些操作可以涉及多个层面,包括但不限于: 页面间的跳转:用户可以通过动作从一个页面跳转到另一个页面。 业务交互:动作可以触发与后端服务的交互,例如提交表单、请求数据等。 界面操作:动作可以用于打开模态对话框、抽屉(侧边栏)等界面元素。 作用场景 Oinone 平台内置了一系列的基础动作,默认实现了常见的功能,如页面跳转、业务交互和界面操作等。这些内置动作旨在满足大多数标准应用场景的需求,简化开发过程,提高开发效率。以下是一些常见的内置动作示例: 页面跳转:允许用户在不同页面间导航。 业务交互:支持与后端服务的数据交互,如提交表单。 界面操作:提供动态返回上一页、校验表单、关闭弹窗等。 自定义动作的需求场景 尽管内置动作覆盖了许多常规需求,但在某些复杂或特定的业务场景中,可能需要更加个性化的处理。这些场景可能包括: 特殊的业务逻辑:需要执行不同于标准流程的特定业务操作。 个性化的用户界面:标准的 UI 组件无法满足特定的设计要求。 高级交互功能:需要实现复杂的用户交互和数据处理。 扩展和定制动作 为了满足这些特定需求,Oinone 平台支持通过继承和扩展来自定义动作。开发者可以通过以下步骤实现自定义动作: 继承基类:从平台提供的动作基类继承,这为自定义动作提供了基础框架和必要的接口。 实现业务逻辑:在继承的基础上,添加特定的业务逻辑实现。 自定义界面:根据需要调整或完全重写界面组件,以符合特定的UI设计。 集成测试:确保自定义动作在各种情况下的稳定性和性能。 最佳实践 明确需求:在进行扩展之前,清楚地定义业务需求和目标。 重用现有功能:尽可能利用平台的内置功能和组件。 保持一致性:确保自定义动作与平台的整体风格和标准保持一致。 充分测试:进行全面的测试,确保新动作的稳定性和可靠性。 案例分析 假设有一个场景,需要一个特殊的数据提交流程,该流程不仅包括标准的表单提交,还涉及复杂的数据验证和后续处理。在这种情况下,可以创建一个自定义动作,继承基础动作类并实现特定的业务逻辑和用户界面。 自定义动作 自定义跳转动作 示例工程目录 以下是需关注的工程目录示例,main.ts更新导入./action,action/index.ts更新导出./custom-viewactioin: 图3-5-7-24 自定义跳转动作工程目录示例 步骤 1: 创建自定义动作类 首先,您创建了一个名为 CustomViewAction 的类,这个类继承自 RouterViewActionWidget。这意味着自定义动作是基于路由视图动作的,这通常涉及页面跳转或导航。 import {ActionWidget, RouterViewActionWidget, SPI} from '@kunlun/dependencies'; import CustomViewActionVue from './CustomViewAction.vue'; @SPI.ClassFactory( ActionWidget.Token({ model: 'resource.ResourceCity', name: 'redirectCreatePage' }) ) export class CustomViewAction extends RouterViewActionWidget { public initialize(props) { super.initialize(props); this.setComponent(CustomViewActionVue); return this; } } 图3-5-7-24 自定义跳转动作组件(TS)代码示例 @SPI.ClassFactory: 这是一个装饰器,用于向平台注册这个新的动作。 ActionWidget.Token: 通过这个Token,指定了这个动作与特定模型 (resource.ResourceCity) 关联,并给这个动作命名 (redirectCreatePage). 步骤 2: 初始化和设置组件 在 initialize 方法中,调用了父类的初始化方法,并设置了自定义的 Vue 组件。 public initialize(props) { super.initialize(props); this.setComponent(CustomViewActionVue); return this; } 图3-5-7-24 初始化和设置组件 步骤 3: 定义 Vue 组件 在 CustomViewAction.vue 文件中,定义了自定义动作的视觉表示。 <template> <div class="view-action-wrapper"> 自定义挑战跳转动作 </div> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ inheritAttrs: false, name: 'ViewActionComponent' }) </script> <style lang="scss"> .view-action-wrapper { } </style> 图3-5-7-24 自定义跳转动作组件(Vue)代码示例 步骤 4: 效果如下 图3-5-7-24 自定义跳转动作效果示例 自定义服务器动作 示例工程目录 以下是需关注的工程目录示例,action/index.ts更新导出./custom-serveraction: 图3-5-7-24 自定义服务器动作工程目录示例 步骤 1: 创建自定义动作类 首先, 创建了一个名为 CustomServerAction 的类,这个类继承自 ServerActionWidget。这表明您的自定义动作主要关注服务器端的逻辑。 import {ActionWidget, ServerActionWidget, SPI, Widget} from '@kunlun/dependencies'; import CustomServerActionVue from './CustomServerAction.vue'; @SPI.ClassFactory( ActionWidget.Token({ model: 'resource.ResourceCity', name: 'delete' })…

    2024年5月23日
    98300
  • 第5章 Oinone的CDM

    2024年5月23日
    85500
  • 5.6 商业支撑之商品域

    一、基础介绍 当业务在线化后,用于内部管理的产品主数据,叠加一堆销售属性变成了商品被推倒了前台,成为导购链路中最最重要的信息载体。看似最基础和最简单的商品模块也有很多门道。主要集中在以下几个方面: 商品的属性如何管理、呈现、参与导购(类目、搜索的过滤条件) 如何解决固定不变的内部管理需求与基于销售特性长期变化的运营需求之间的矛盾 在多渠道情况渠道商品,如何映射到实际sku进行履约 二、模型介绍 图5-6-1 模型介绍 类目属性,解决“商品的属性如何管理、呈现、参与导购(类目、搜索的过滤条件)” 前后台类目设计,解决“如何解决固定不变的内部管理需求与基于销售特性长期变化的运营需求之间的矛盾” 销售Sku和库存Sku设计,解决“在多渠道情况渠道商品,如何映射到实际sku进行履约” 要把这些问题搞清楚,得先把名词统一下: 领域 名称 oinone的定义 说明 举例 平台运营视角 Spu Product –>Spu2.1.9 –> 3.0.0 SPU(Standard Product Unit):标准化产品单元。SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性 iPhone X可以确定一个产品 后台类目 后台类目(Category) 商品分类分级管理,以及规范该类目下公共属性可以分为普通属性、销售属性 比如类目:3c数码/手机销售属性:内存大小、颜色等普通属性:分辨率 前台类目 前台类目(FrontCategory) 平台导购类目 通过前台类目关联后台类目或后台类目属性,用于满足运营需求 大体上SPU处于最上层、Item属于下一级,而SKU属于最低一层。SPU是平台层面,Item是商家层面,SKU是商家的Item确定销售属性SPU非必须,在平台类交易中,平台方为了规范商家发布商品信息,进行统一运营时需要 商家销售视角 Item 渠道商品(Item) 简单来说是:SPU加上归属商家、以及商家自有的价格与描述 商家A的iPhone X Sku 销售Sku(SaleSku) SKU=Stock Keeping Unit(库存保有单位)。是对每一个产品和服务的唯一标示符,该系统的使用SKU的值根于数据管理,使公司能够跟踪系统,如仓库和零售商店或产品的库存情况。 iPhone X 64G 银色 则是一个SKU。 店铺类目 ShopCategory 商家店铺导购类目 在平台类电商,商家都会有自己独立的店铺主页,商家类目跟前台类目作用类似,只是局限影响范围为商家店铺内 销售SKU中会有一个InvSkuCode来关联InventorySku,比如:品牌上在不同渠道(淘宝、京东、自建电商)中会有不同的销售SKU,在从渠道同步销售SKU会根据外部code 商家管理视角 产品或库存Sku InventorySku 跟销售领域的sku的定义类似,但销售领域是为了规范购买行为,这里规范企业内部管理。 iPhone X 64G 银色 组合Sku InventorySkuComposition 空调有内外机组合而成,这就是一个组合sku 产品分类 ProductKind 企业内部管理划分 商品系列 ItemSeries 指互相关联或相似的产品,是按照一定的分类标准对企业生产经营的全部产品进行划分的结果。一个产品系列内往往包括多个产品项目。产品系列的划分标准有产品功能、消费上的连带性、面向的顾客群、分销渠道、价格范围等 存货类别 StorageKind 为了反映存货的组成内容,正确计算产品的生产成本以及销售成本,会计上必须对存货进行科学地分类,按存货的不同类别进行核算 表5-6-1 各领域名称说明

    2024年5月23日
    95500
  • 2.4.1 Oinone独特性之单体与分布式的灵活切换

    企业数字化转型需要处理分布式带来的复杂性和成本问题。尽管这些问题令人望而却步,但分布式架构对于大部分企业仍然是必须的选择。如果一个低代码平台缺乏分布式能力,那么它的性能就无法满足客户的要求。相比之下,Oinone平台通过对部署的创新(如图2-6所示),成功实现了分布式架构的支持,而且能够按照客户的业务发展需求,灵活选择不同的部署模式,同时节约企业成本,提升创新效率。这一创新是Oinone平台与其他低代码平台的重要区别,能够满足客户预期发展并兼顾成本效益。 图2-6 传统部署方式VS Oinone部署方式 实现原理 要实现灵活部署的特性,必须满足两个基本要求: 开发过程中不需要过多关注分布式技术,就像开发单体应用一样简单。代码在运行时应该能够根据模块是否在运行容器中,来决定路由走本地还是远程。这样可以大大减少研发人员的工作量和技术复杂度。 研发与部署要分离,即"开发单体应用一样开发分布式应用,而部署形式由后期决定"。为此,我们的工程结构支持多种启动模式,并逐一介绍了针对不同场景的工程结构类型(如下图2-7所示)。这样可以让客户在后期根据业务发展情况和需求,选择最适合的部署模式,从而达到灵活部署的目的。 图2-7 Oinone工程结构梳理 在整个工程结构上,我们秉承了Spring Boot的规范,不会改变大家的工程习惯。而Oinone的部署能力则可以让我们更灵活地应对各种情况。现在,我们来逐一介绍几种常规的工程结构以及它们适用的场景: 单模块工程结构(常规操作) a. 这是非常标准的Spring Boot工程,适用于简单的应用场景开发以及入门学习。 多模块工程结构(常规操作) a. 这是非常标准的多Spring Boot工程,可以实现分布式独立启动,适用于常规的分布式应用场景开发。 多模块工程结构-独立boot工程模式 a. 这种工程结构在多模块工程的基础上,通过独立的boot工程来支撑多部署方式。适用于中大型分布式应用场景开发。 b. 然而,随着工程越来越多,我们也会面临一些问题: ⅰ研发:环境准备非常困难,每个模块都要单独启动,研发调试跟踪困难。 ⅱ部署:分布式的高可靠性保证需要每个模块至少有两个部署节点,但在模块较多的情况下,起步成本非常高。同时,企业初期业务不稳定且规模较小,使用多模块工程的第二种模式会增加问题排查难度和成本。 c. 此时,Oinone的多模块工程下的独立boot工程模式部署就可以发挥其灵活性,让研发和业务起步阶段可以选择all-in-one模式,等到业务发展到一定规模的时候,只需要把线上部署模式切换成模块独立部署,而研发还可以保留all-in-one模式的优势。 d. 值得注意的是,分分合合的部署模式在传统互联网架构和低代码或无代码平台上都是有代价的,但是Oinone却可以灵活适配,只需要在boot工程的yml文件中写入需要加载的模块就可以解决。此处我们仅介绍多模块加载配置,选择性忽略其他无关配置,具体配置(如下图2-8所示)。 pamirs: boot: init: true sync: true modules: – base – resource – sequence – user – auth – web tenants: – pamirs 图2-8 Oinone yml配置图大型多场景工程结构-独立boot工程模式: a. 在多模块工程结构基础上的加强版,增加CDM层设计,让不同场景即保持数据统一,又保持逻辑独立。这种工程结构特别适用于大型企业软件开发,其中涉及到多个场景的情况,例如B端和C端的应用,或者跨不同业务线的应用,能够保证数据的一致性,同时也能够保持逻辑独立,避免不同场景间的代码冲突。 b. 这种工程结构是我们Oinone支撑“企业级软件生态”的核心,我们可以把场景A当作我们官方应用,场景B当作其他第三方伙伴应用。在这个工程结构下,我们的客户可以定制化开发自己的应用,同时我们也可以通过这种模式来支持我们的伙伴们进行开发,实现多方共赢。 c. 基于独立boot工程模式,我们同样对应多种部署模式应对不同情况,并统一管理所有伙伴应用。这种工程结构的优点是扩展性好,可以支持不同规模的应用,并且可以根据需要进行快速扩展或缩小规模,具有很高的灵活性。 基于标准产品的二开工程结构,是指基于标准产品进行二次开发,满足客户特定需求的工程结构。这种模式下,Oinone提供标准产品,客户可以根据自己的需求进行二次开发,实现定制化需求,同时可以利用我们的模块化开发特性,将每一个需求作为一个模块进行开发和管理。这种工程结构的优点是能够快速满足客户特定需求,同时也具有很好的可维护性和可扩展性,因为每个需求都是一个独立的模块,可以方便地进行维护和扩展。在下一篇“Oinone独特性之每一个需求都是一个模块”文章中有详细介绍。

    2024年5月23日
    1.2K00

Leave a Reply

登录后才能评论