6.6 消息

在我们系统研发过程中经常需要发送短信、邮件、站内信等,笔者在本文给大家介绍下如何使用Oinone的消息模块。

准备工作

如果通过我们工程脚手架工具生成的则已经引入了无需做更多的配置,如果不是则需要按以下步骤先配置依赖和增加启动模块

pamirs-demo-boot的pom文件中引入pamirs-message-core包依赖

<dependency>
  <groupId>pro.shushi.pamirs.core</groupId>
  <artifactId>pamirs-message-core</artifactId>
</dependency>

pamirs-demo-boot的application-dev.yml文件中增加配置pamirs.boot.modules增加message,即在启动应用中增加message模块

pamirs:
    boot:
    modules:
      - message

消息参数设置

发送邮件和短信需要设置对应的发送邮箱服务器和短信云,短信目前默认阿里云短信。我们通过代码示例来完成对应邮箱和短信的参数设置

Step1 增加pamirs-message-api依赖

pamirs-demo-core的pom文件中引入pamirs-message-api包依赖

<dependency>
  <groupId>pro.shushi.pamirs.core</groupId>
  <artifactId>pamirs-message-api</artifactId>
</dependency>

Step2 消息参数设置

请自行替换邮箱服务器和短信通道的账号信息

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

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.UpgradeDataInit;
import pro.shushi.pamirs.demo.api.DemoModule;
import pro.shushi.pamirs.message.enmu.EmailSendSecurityEnum;
import pro.shushi.pamirs.message.enmu.MessageEngineTypeEnum;
import pro.shushi.pamirs.message.enmu.SMSChannelEnum;
import pro.shushi.pamirs.message.model.EmailSenderSource;
import pro.shushi.pamirs.message.model.SmsChannelConfig;

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

@Component
public class DemoMessageInit implements InstallDataInit, UpgradeDataInit {

    private void initEmail(){
        EmailSenderSource emailSenderSource = new EmailSenderSource();
        emailSenderSource.setName("邮件发送服务");
        emailSenderSource.setType(MessageEngineTypeEnum.EMAIL_SEND);
        //优先级
        emailSenderSource.setSequence(10);
        //发送账号 FIXME 自行替换
        emailSenderSource.setSmtpUser("");
        //发送密码 FIXME 自行替换
        emailSenderSource.setSmtpPassword("");
        //发送服务器地址和端口
        emailSenderSource.setSmtpHost("smtp.exmail.qq.com");
        emailSenderSource.setSmtpPort(465);
        //" None: SMTP 对话用明文完成。" +
        //" TLS (STARTTLS): SMTP对话的开始时要求TLS 加密 (建议)" +
        //" SSL/TLS: SMTP对话通过专用端口用 SSL/TLS 加密 (默认是: 465)")
        emailSenderSource.setSmtpSecurity(EmailSendSecurityEnum.SSL);
        emailSenderSource.createOrUpdate();
    }

    private void initSms(){
        SmsChannelConfig smsChannelConfig = new SmsChannelConfig();
        smsChannelConfig.setType(MessageEngineTypeEnum.SMS_SEND);
        smsChannelConfig.setChannel(SMSChannelEnum.ALIYUN);
        //短信签名名称
        smsChannelConfig.setSignName("oinone");
        //阿里云账号信息  FIXME 自行替换
        smsChannelConfig.setAccessKeyId("");
        smsChannelConfig.setAccessKeySecret("");
        smsChannelConfig.setEndpoint("https://dysmsapi.aliyuncs.com");
        smsChannelConfig.setRegionId("cn-hangzhou");
        smsChannelConfig.setTimeZone("GMT");
        smsChannelConfig.setSignatureMethod("HMAC-SHA1");
        smsChannelConfig.setSignatureVersion("1.0");
        smsChannelConfig.setVersion("2017-05-25");
        smsChannelConfig.createOrUpdate();

        //初始化短信模版
        //目前支持阿里云短信通道:获取短信模板,如没有短信模板,需要先创建模板,并审核通过
        SmsTemplate smsTemplate = new SmsTemplate();
        smsTemplate.setName("通知短信");
        smsTemplate.setTemplateType(SMSTemplateTypeEnum.NOTIFY);
        smsTemplate.setTemplateCode("SMS_244595482");//从阿里云获取,自行提供 FIXME
        smsTemplate.setTemplateContent("尊敬的&{name},你的&{itemName}库存为&{quantity}");
        smsTemplate.setChannel(SMSChannelEnum.ALIYUN);
        smsTemplate.setStatus(SMSTemplateStatusEnum.SUCCESS);
        smsTemplate.createOrUpdate();
    }

    @Override
    public boolean init(AppLifecycleCommand command, String version) {
        initEmail();
        initSms();
        return Boolean.TRUE;
    }

    @Override
    public boolean upgrade(AppLifecycleCommand command, String version, String existVersion) {
        initEmail();
        initSms();
        return Boolean.TRUE;
    }

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

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

消息发送举例

该例子以各种站内信、邮件、短信方式发送宠物商品库存记录信息为例,构建宠物商品库存信息发送服务并在宠物商品库存模型的表格页面创建发送入口

Step1 创建宠物商品库存信息发送服务接口

在Api工程新建PetItemInventoryMessageService接口,并定义发送站内信、邮件、短信的三个Function

package pro.shushi.pamirs.demo.api.service;

import pro.shushi.pamirs.demo.api.model.PetItemInventroy;
import pro.shushi.pamirs.meta.annotation.Fun;
import pro.shushi.pamirs.meta.annotation.Function;

@Fun(PetItemInventoryMessageService.FUN_NAMESPACE)
public interface PetItemInventoryMessageService {

    String FUN_NAMESPACE = "demo.PetItemInventoryMessageService";
    @Function
    void sendMail(PetItemInventroy data);
    @Function
    void sendEmail(PetItemInventroy data);
    @Function
    void sendSms(PetItemInventroy data);

}

Step2 发送站内信

在Core工程新建PetItemInventoryMessageService接口的实现类

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

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.demo.api.enumeration.DemoExpEnumerate;
import pro.shushi.pamirs.demo.api.model.PetItemInventroy;
import pro.shushi.pamirs.demo.api.service.PetItemInventoryMessageService;
import pro.shushi.pamirs.demo.core.session.DemoSession;
import pro.shushi.pamirs.message.engine.MessageEngine;
import pro.shushi.pamirs.message.engine.email.EmailSender;
import pro.shushi.pamirs.message.engine.message.MessageSender;
import pro.shushi.pamirs.message.engine.sms.SMSSender;
import pro.shushi.pamirs.message.enmu.MessageEngineTypeEnum;
import pro.shushi.pamirs.message.enmu.MessageGroupTypeEnum;
import pro.shushi.pamirs.message.enmu.MessageTypeEnum;
import pro.shushi.pamirs.message.enmu.SMSTemplateTypeEnum;
import pro.shushi.pamirs.message.model.PamirsMessage;
import pro.shushi.pamirs.message.model.SmsTemplate;
import pro.shushi.pamirs.message.tmodel.EmailPoster;
import pro.shushi.pamirs.message.tmodel.SystemMessage;
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.common.exception.PamirsException;
import pro.shushi.pamirs.meta.util.JsonUtils;
import pro.shushi.pamirs.user.api.model.PamirsUser;

import javax.mail.MessagingException;
import javax.mail.SendFailedException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Fun(PetItemInventoryMessageService.FUN_NAMESPACE)
@Slf4j
@Component
public class PetItemInventoryMessageServiceImpl implements PetItemInventoryMessageService {

    public static final String INVALID_ADDRESSES_CODE = "Invalid Addresses";
    public static final String INVALID_ADDRESSES_MSG = "非法的邮箱地址";
    public static final String CAN_NO_CONNECT_TO_SMTP_CODE = "Could not connect to SMTP";
    public static final String CAN_NO_CONNECT_TO_SMTP_MSG = "连接邮件服务失败";

    @Override
    @Function
    public void sendMail(PetItemInventroy data) {
        //接收对象列表
        PamirsUser user = DemoSession.getUser();

        List<Long> userIds = new ArrayList<>();
        userIds.add(user.getId());

        String subject = "商品库存信息";
        String body = data.getItemName() + "_" + data.getQuantity();
        MessageSender mailSender = (MessageSender) MessageEngine.get(MessageEngineTypeEnum.MAIL_SEND).get(null);
        PamirsMessage message = new PamirsMessage()
                .setName(subject)
                .setSubject(subject)
                .setBody(body)
                .setMessageType(MessageTypeEnum.NOTIFICATION);

        List<PamirsMessage> messages = new ArrayList<>();
        messages.add(message);
        SystemMessage systemMessage = new SystemMessage();
        systemMessage.setPartners(userIds.stream().map(i -> (PamirsUser) new PamirsUser().setId(i)).collect(Collectors.toList()))
                .setType(MessageGroupTypeEnum.SYSTEM_MAIL)
                .setMessages(messages);
        try {
            mailSender.sendSystemMail(systemMessage);
        } catch (Exception e) {
            // TODO: 可增加失败业务处理
            throw PamirsException.construct(DemoExpEnumerate.SYSTEM_ERROR, e).appendMsg("站内信发送失败").errThrow();
        }
    }

    @Override
    @Function
    public void sendEmail(PetItemInventroy data) {
        //发送一个邮件
        List<String> receiveEmails = new ArrayList<>();
        receiveEmails.add("testhaha@shushi.pro");//收件人邮箱,自行替换 FIXME 
        EmailSender emailSender = null;
        EmailPoster emailPoster = null;

        emailSender = (EmailSender) MessageEngine.get(MessageEngineTypeEnum.EMAIL_SEND).get(null);

        String title = data.getItemName();//"邮件标题";
        String body = data.getItemName() + "_" + data.getQuantity();//"邮件内容";
        String sender = DemoSession.getUserName();//"发件人";
        String replyEmail = "回复邮箱";

        emailPoster = new EmailPoster().setSender(sender).setTitle(title).setBody(body).setReplyTo(replyEmail);

        EmailPoster finalEmailPoster = emailPoster;
        EmailSender finalEmailSender = emailSender;

        StringBuilder errorMessages = new StringBuilder();
        receiveEmails.stream().distinct().collect(Collectors.toList()).forEach(
                email -> {
                    try {
                        if (!finalEmailSender.send(finalEmailPoster.setSendTo(email))) {
                            log.error("发送邮件失败:emailPoster:{}", JsonUtils.toJSONString(finalEmailPoster));
                            String message = "发送邮件失败,错误信息:" + "系统异常" + ",邮箱:" + email + ";";
                            errorMessages.append(message);
                        }
                    } catch (Exception e) {
                        log.error("发送邮件失败:emailPoster:{},异常:{}", JsonUtils.toJSONString(finalEmailPoster), e);
                        String errorMsg = transferEmailThrowMessage(e);
                        String message = "发送邮件失败,错误信息:" + errorMsg + ",邮箱:" + email + ";";
                        errorMessages.append(message);
                    }
                }
        );

        if (StringUtils.isNotBlank(errorMessages.toString())) {
            // TODO: 可增加处理邮件发送失败的业务逻辑
        }
    }

    private String transferEmailThrowMessage(Exception e) {
        String errorMessage = e.getMessage();
        Throwable cause = e.getCause();
        if (cause != null) {
            if (cause instanceof SendFailedException) {
                String message = cause.getMessage();
                if (INVALID_ADDRESSES_CODE.equals(message)) {
                    errorMessage = INVALID_ADDRESSES_MSG;
                }
            } else if (cause instanceof MessagingException) {
                String message = cause.getMessage();
                if (StringUtils.isNotBlank(message) && message.contains(CAN_NO_CONNECT_TO_SMTP_CODE)) {
                    errorMessage = CAN_NO_CONNECT_TO_SMTP_MSG;
                }
            }
        }
        return errorMessage;
    }

    @Override
    @Function
    public void sendSms(PetItemInventroy data) {
        StringBuilder errorMessages = new StringBuilder();

        List<String> receivePhoneNumbers = new ArrayList<>();
        receivePhoneNumbers.add("13777899044");//接收手机号,自行提供 FIXME 

        //目前支持阿里云短信通道:获取短信模板,如没有短信模板,需要先创建模板,并审核通过
        //如以下示例
        SmsTemplate smsTemplate = new SmsTemplate().setTemplateType(SMSTemplateTypeEnum.NOTIFY).setTemplateCode("SMS_246455054").queryOne();//从阿里云获取

        // 占位符处理
        Map<String, String> vars = new HashMap<>();
        vars.put("name", DemoSession.getUserName());
        vars.put("itemName", data.getItemName());
        vars.put("quantity", data.getQuantity().toString());

        SMSSender smsSender = (SMSSender) MessageEngine.get(MessageEngineTypeEnum.SMS_SEND).get(null);
        receivePhoneNumbers.stream().distinct().forEach(it -> {
            try {
                if (!smsSender.smsSend(smsTemplate, it, vars)) {
                    String message = "发送短信失败,错误信息:" + "系统异常" + ",手机号:" + it + ";";
                    errorMessages.append(message);
                }
            } catch (Exception e) {
                String message = "发送短信失败,错误信息:" + e.getMessage() + ",手机号:" + it + ";";
                errorMessages.append(message);
            }
        });
        if (StringUtils.isNotBlank(errorMessages.toString())) {
            // TODO: 可增加失败业务处理
        }
    }
}

Step3 为宠物商品库存模型的表格页面新增发送入口

把以下代码复制到PetItemInventroyAction类中

@Autowired
private PetItemInventoryMessageService petItemInventoryMessageService;
@Action(displayName = "发送站内信",bindingType = ViewTypeEnum.TABLE,contextType = ActionContextTypeEnum.SINGLE)
public PetItemInventroy sendMail(PetItemInventroy data) {
    petItemInventoryMessageService.sendMail(data);
    return data;
}

/**
 * 发送邮件
 */
@Action(displayName = "发送邮件",bindingType = ViewTypeEnum.TABLE,contextType = ActionContextTypeEnum.SINGLE)
public PetItemInventroy sendEmail(PetItemInventroy data){
    petItemInventoryMessageService.sendEmail(data);
    return data;
}

/**
 * 发送短息
 */
@Action(displayName = "发送短信",bindingType = ViewTypeEnum.TABLE,contextType = ActionContextTypeEnum.SINGLE)
public PetItemInventroy sendSms(PetItemInventroy data){
    petItemInventoryMessageService.sendSms(data);
    return data;
}

Step4 重启看效果

请分别点击发送邮件、发送短信、发送站内信测试效果,自行测试效果

image.png

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

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

Like (0)
史, 昂's avatar史, 昂数式管理员
Previous 2024年5月23日
Next 2024年5月23日

相关推荐

  • 流程设计

    1.流程设计 进入流程设计页之后可以进行流程名称、流程说明的编辑,可以进行流程设计,流程参数配置,保存和发布。 1.1 流程配置 点击进入流程配置页面,若需要配置一些参数供流程使用,可在此添加和删除。删除流程参数时,若该参数已在流程中被使用则无法删除。参数支持文本、数值、日期、布尔四种类型。 1.2 保存 点击后流程设计进行存档,流程设计不完整也支持保存,下次进入流程设计回到保存的页面。 1.3 发布 第一次发布时右上角发布显示文字为发布流程,后续发布按钮显示文字为更新发布。发布后流程才会按照设计触发,首次发布和更新发布的逻辑一致,若流程中有未解决的错误则无法发布不成功,发布成功后页面跳转到显示全部流程的页面,流程状态为已启用、已更新。

    2024年6月20日
    1.4K00
  • 开发者

    1.开发者 1.1 Webhook 通过webhook流程节点可以向第三方系统发送请求。 1.1.1 请求方式 支持GET、POST两种请求方式。 1.1.2 URL 在Webhook URL中填写发送请求的HTTP地址。 1.1.3 Headers&Body Headers的value支持通过表达式配置变量 Body的数据类型支持KEY_VALUE和APPLICATION_JSON两种。

    2024年6月20日
    2.0K00
  • 2.4 Oinone的三大独特性

    Oinone在技术方面通过整合互联网架构和低代码技术,实现了三个独特的关键创新点(如图2-5所示): 独立模块化的个性化定制:每个需求都可以被视为一个独立的模块,从而实现个性化定制,提高软件生产效率。此外,这些独立模块也不会影响产品的迭代和升级,为客户带来无忧的体验。 灵活的部署方式:单体部署和分布式部署的灵活切换,为企业业务的发展提供了便利,同时适用于不同规模的公司,有助于有效地节约企业成本,提升创新效率,并让互联网技术更加亲民。 低代码和无代码的结合:低无一体为不同的IT组织和业务用户提供了有效的协同工作方式,能够快速部署安全、可扩展的应用程序和解决方案,帮助企业/组织更好地管理业务流程并不断优化。 图2-5 Oinone的三大独特性

    2024年5月23日
    2.0K00
  • 3.3.8 字段类型之基础与复合

    模型字段是描述实体的特征属性,本文介绍重点介绍字段的基础类型与复合类型 使用@Field注解来描述模型的字段。如果未配置字段类型,系统会根据Java代码的字段声明类型来自动获取业务类型。建议配置displayName属性来描述字段在前端的显示名称。可以使用defaultValue配置字段的默认值。 一、安装与更新 使用@Field.field来配置字段的不可变更编码。字段一旦安装,无法在对该字段编码值进行修改,之后的字段配置更新会依据该编码进行查找并更新;如果仍然修改该注解的配置值,则系统会将该字段识别为新字段,存储模型会创建新的数据库表字段,而原字段将会rename为废弃字段。 二、字段类型 类型系统由基本类型、复合(组件)类型、引用类型和关系类型四种类型系统构成。通过类型系统描述应用程序、数据库和前端视觉视图如何进行交互,数据及数据间关系如何处理的协议。其中引用类型和关系类型介绍详见3.3.9【字段类型之关系与引用】一文,字段命名规范参见3.3.1【构建第一个Model】一文,这里不再赘述。 基本类型 业务类型 Java类型 数据库类型 规则说明 BINARY ByteByte[] TINYINTBLOB 二进制类型,不推荐使用 INTEGER ShortIntegerLongBigInteger smallintintbigintdecimal(size,0) 整数, 包括整数(10-11位有效数字)、长整数(19-20位有效数字)和大整数(超过19位)。【数据库规则】:默认使用int;如果size小于6则使用smallint;如果size超过6则使用int;如果size超过10位数字,即大于11(包含符号位),则使用长整数bigint;如果size超过19位数字,即大于20(包含符号位),则使用大数decimal。若未配置size,则按Java类型推测。【前端交互规则】:整数使用Number类型,长整数和大整数前后端协议使用字符串类型。 FLOAT FloatDoubleBigDecimal float(M,D)double(M,D)decimal(M,D) 浮点数,?包括单精度浮点数(7-8位有效数字)、双精度浮点数(15-16位有效数字)和大数(超过15位)。【数据库规则】:默认使用单精度浮点数float;如果size超过7位数字,即大于等于8,则使用双精度浮点数double;如果size超过15位数字,即大于等于16,则使用大数decimal。若未配置size,则按Java类型推测。【前端交互规则】:单精度浮点数float和双精度浮点数double使用Number类型(因为都使用IEEE754协议64位进行存储),大数前后端协议使用字符串类型。 BOOLEAN Boolean tinyint(1) 布尔类型,值为1,true(真)或0,false(假) ENUM Enum 与数据字典指定基本类型一致 【前端交互规则】:可选项从ModelField的options字段获取,options字段值为字段指定数据字典子集的JSON序列化字符串。前后端传递的是可选项的name,数据库存储使用可选项的value。multi属性为true,则使用多选控件;multi属性为false,则使用单元控件 STRING String varchar(size) 字符串,size为长度限制默认值参考,前端可以view中覆盖该配置 TEXT String text 多行文本,编辑态组件为多行文本框,长度限制为配置项size值 HTML String text 富文本编辑器 DATETIME java.util.Datejava.sql.Timestamp datetime(fraction)timestamp(fraction) 日期时间类型【数据库规则】:日期和时间的组合,时间格式为?YYYY-MM-DD HH:MM:SS[.fraction],默认精确到秒,在默认的秒精确度上,可以带小数,最多带6位小数,即可以精确到?microseconds (6 digits) precision。可以通过设置fraction来设置精确小数位数,最终存储在字段的decimal属性上。【前端交互规则】:前端默认使用日期时间控件,根据日期时间类型格式化格式format格式化日期时间 YEAR java.util.Date year 年份类型日期类型【数据库规则】:默认“YYYY”格式表示的日期值【前端交互规则】:前端默认使用年份控件,根据日期类型格式化格式format格式化日期 DATE java.util.Datejava.sql.Date datedate 日期类型【数据库规则】:默认“YYYY-MM-DD”格式表示的日期值【前端交互规则】:前端默认使用日期控件,根据日期类型格式化格式format格式化日期 TIME java.util.Datejava.sql.Time time(fraction)time(fraction) 时间类型【数据库规则】:默认“HH:MM:SS”格式表示的时间值【前端交互规则】:前端默认使用时间控件,根据日期类型格式化格式format格式化日期 表3-3-8-1 字段基本类型 复合类型 业务类型 Java类型 数据库类型 规则说明 MONEY BigDecimal decimal(M,D) 金额,前端使用金额控件,可以使用currency设置币种字段 表3-3-8-2 字段复合类型 不可变更字段 使用immutable属性来描述该字段前后端都无法进行更新操作,系统会忽略不可变更字段的更新操作。 自动生成编码的字段 详见3.3.5【模型编码生成器】一文。 字段的序列化与反序列化 使用@Field注解的serialize属性来配置非字符串类型属性的序列化与反序列化方式,最终会以序列化后的字符串持久化到存储中。 详见3.3.7【字段之序列化方式】一文 前端默认配置 可以使用@Field注解中的以下属性来配置前端的默认视觉与交互规则,也可以在前端设置覆盖以下配置。 @Field(required),是否必填 @Field(invisible),是否不可见 @Field(priority),字段优先级,列表的列使用该属性进行排序 更多前端默认视图配置详见:3.5.4【Ux注解详解】一文,如:readonly是否只读等。 举例 回顾我们前面学习例子 现有PetShop代码如下 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.core.common.enmu.DataStatusEnum; import pro.shushi.pamirs.demo.api.enumeration.PetShopOptionEnum; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; import java.sql.Time; import java.util.List; @Model.model(PetShop.MODEL_MODEL) @Model(displayName = 宠物店铺,summary=宠物店铺,labelFields ={shopName} ) @Model.Code(sequence = DATE_ORDERLY_SEQ,prefix = P,size=6,step=1,initial = 10000,format = yyyyMMdd) public class PetShop extends AbstractDemoIdModel { public static final String MODEL_MODEL=demo.PetShop; @Field(displayName = 店铺编码) private String code; @Field(displayName = 店铺编码2) @Field.Sequence(sequence = DATE_ORDERLY_SEQ,prefix = C,size=6,step=1,initial = 10000,format = yyyyMMdd) private String codeTwo; @Field(displayName = 店铺名称,required = true) private String shopName; @Field(displayName = 开店时间,required = true) private Time openTime; @Field(displayName = 闭店时间,required = true) private Time closeTime; @Field(displayName =…

    2024年5月23日
    1.6K00
  • 4.2.1 组件之生命周期

    组件生命周期的意义所在:比如动态创建了「视图、字段」,等它们初始化完成或者发生了修改后要执行业务逻辑,这个时候只能去自定义当前字段或者视图,体验极差,平台应该提供一些列的生命周期,允许其他人调用生命周期的api去执行对应的逻辑。 一、实现原理 图4-2-1-1 实现原理 当用户通过内部API去监听某个生命周期的时候,内部会动态的去创建该生命周期,每个生命周期都有「唯一标识」,内部会根据「唯一标识」去创建对应的「Effect」,Effect会根据生命周期的「唯一标识」实例化一个「lifeCycle」,「lifeCycle」创建完成后,会被存放到「Heart」中,「Heart」是整个生命周期的心脏,当心脏每次跳动的时候(生命周期被监听触发)都会触发对应的生命周期 二、生命周期API API 描述 返回值 View LifeCycle onViewBeforeCreated 视图创建前 ViewWidget onViewCreated 视图创建后 ViewWidget onViewBeforeMount 视图挂载前 ViewWidget onViewMounted 视图挂载后 ViewWidget onViewBeforeUpdate 视图数据发生修改前 ViewWidget onViewUpdated 视图数据修改后 ViewWidget onViewBeforeUnmount 视图销毁前 ViewWidget onViewUnmounted 视图销毁 ViewWidget onViewSubmit 提交数据 ViewWidget onViewSubmitStart 数据开始提交 ViewWidget onViewSubmitSuccess 数据提交成功 ViewWidget onViewSubmitFailed 数据提交失败 ViewWidget onViewSubmitEnd 数据提交结束 ViewWidget onViewValidateStart 视图字段校验 ViewWidget onViewValidateSuccess 校验成功 ViewWidget onViewValidateFailed 校验失败 ViewWidget onViewValidateEnd 校验结束 ViewWidget Field LifeCycle onFieldBeforeCreated 字段创建前 FieldWidget onFieldCreated 字段创建后 FieldWidget onFieldBeforeMount 字段挂载前 FieldWidget onFieldMounted 字段挂载后 FieldWidget onFieldBeforeUpdate 字段数据发生修改前 FieldWidget onFieldUpdated 字段数据修改后 FieldWidget onFieldBeforeUnmount 字段销毁前 FieldWidget onFieldUnmounted 字段销毁 FieldWidget onFieldFocus 字段聚焦 FieldWidget onFieldChange 字段的值发生了变化 FieldWidget onFieldBlur 字段失焦 FieldWidget onFieldValidateStart 字段开始校验 FieldWidget onFieldValidateSuccess 校验成功 FieldWidget onFieldValidateFailed 校验失败 FieldWidget onFieldValidateEnd 校验结束 FieldWidget 表4-2-1-1 生命周期API 上面列出的分别是「视图、字段」的生命周期,目前Action的生命周期还没有,后续再补充。 三、第一个View组件生命周期的监听(举例) Step1 新建registryLifeCycle.ts 新建registryLifeCycle.ts,监听宠物达人的列表页。’宠物达人table_demo_core’为视图名,您需要找后端配合 import { onViewCreated } from '@kunlun/dependencies' function registryLifeCycle(){ onViewCreated('宠物达人table_demo_core', (viewWidget) => { console.log('宠物达人table_demo_core'); console.log(viewWidget); }); } export {registryLifeCycle} 图4-2-1-2 新建registryLifeCycle.ts Step2 修改main.ts 全局注册lifeCycle import { registryLifeCycle } from './registryLifeCycle'; registryLifeCycle(); 图4-2-1-3 修改main.ts Step3 看效果 图4-2-1-4 示例效果 四、第一个Filed组件生命周期的监听(举例) Step1 修改registryLifeCycle.ts 通过onFieldValueChange增加宠物达人搜索视图的name(达人)字段的值变化进行监听。 宠物达人search:name 代表 视图名:字段名 import { onViewCreated , onFieldValueChange} from '@kunlun/dependencies' function registryLifeCycle(){ onViewCreated('宠物达人table_demo_core', (viewWidget) => { console.log('宠物达人table_demo_core'); console.log(viewWidget); }); onFieldValueChange('宠物达人search:name', (filedWidget) => { console.log('宠物达人search:name');…

    Oinone 7天入门到精通 2024年5月23日
    1.2K00

Leave a Reply

Please Login to Comment