Activiti 工作流大致了解
一、什么是 Activiti
简而言之,就是系统的流程图,如:请假审批流程、账单审批流程等。
二、mysql与pom配置
mysql要使用jdbc:mysql://localhost:3306/activiti?autoReconnect=true
pom文件要添加关键依赖
<!--activiti核心依赖-->
<dependency><groupId>org.activiti</groupId><artifactId>activiti-engine</artifactId><version>7.1.0.M6</version>
</dependency>
<!--mysql驱动包-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.23</version>
</dependency>
<!--mybatis-->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.5</version>
</dependency>
三、Activiti流程引擎通过 activiti.cfg.xml 进行核心配置
在 resources 目录下创建 activiti.cfg.xml 文件:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 默认方式下,bean的id必须是processEngineConfiguration --><bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"><!-- 配置数据源 & 为对 & 的转义 --><property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/activiti01?characterEncoding=utf8&nullCatalogMeansCurrent=true"/><property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/><property name="jdbcUsername" value="root"/><property name="jdbcPassword" value="你的mysql密码"/><!-- activiti 数据库表生成策略 --><!--自动更新数据库结构true:适用开发环境,默认值。activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建false:适用生产环境。activiti在启动时,对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)--><property name="databaseSchemaUpdate" value="true"/></bean>
</beans>
四、通过流程引擎建立数据表
创建 ProcessEngine 流程引擎实例和数据表
@Testpublic void getProcessEngine() {
// 使用activiti提供的工具类ProcessEngines,
// 调用 getDefaultProcessEngine 会默认读取resource下的activiti.cfg.xml文件,
// 并创建 Activiti 流程引擎 和 创建数据库表ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();System.out.println(processEngine);}
此时自动生成25张表
- ACT_GE_* : GE 表示 general 。通用数据,各种情况都使用的数据 ,如存放资源文件(图片,规则等)。
- ACT_HI_xxx : HI 表示history。就是这些表包含着历史的相关数据,如结束的流程实例(变量,任务等)。
- ACT_RE_xxx : RE 表示repository。带此前缀的表包含的是静态信息,如,流程定义,流程的资源(图片,规则
等)。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 - ACT_RU_xxx : RU 表示 runtime。这是运行时的表存储着流程变量,用户任务,变量,职责(job)等运行时的
数据。Activiti只存储实例执行期间的运行时数据,当流程实例结束时,将删除这些记录。 - ACT_EVT_* :EVT表示event,流程引擎的通用事件日志记录表。
| 表分类 | 表名 | 说明 |
|---|---|---|
| 通用数据 | ||
| act_ge_bytearray | 二进制数据表(流程图) | |
| act_ge_property | 属性数据表,存储整个流程引擎级别的数据,初始化表结构时,会插入版本号信息等 | |
| 通用数据 | ||
| act_hi_actinst | 历史节点表 | |
| act_hi_attachment | 历史附件表 | |
| act_hi_comment | 历史意见表 | |
| act_hi_detail | 历史详情表,提供历史变量的查询 | |
| act_hi_identitylink | 历史流程人员表,主要存储任务节点与参与者的相关信息 | |
| act_hi_procinst | 历史流程实例表 | |
| act_hi_taskinst | 历史任务实例表 | |
| act_hi_varinst | 历史变量表 | |
| 流程定义表 | ||
| act_re_deployment | 部署信息表 | |
| act_re_model | 流程设计模型表 | |
| act_re_procdef | 流程定义数据表 | |
| 流程运行数据表 | ||
| act_ru_deadletter_job | 作业死亡信息表,如果作业失败超过重试次数,则写入到此表 | |
| act_ru_event_subscr | throwEvent、catchEvent时间监听信息表 | |
| act_ru_execution | 运行时流程执行实例表 | |
| act_ru_identitylink | 运行时流程人员表,主要存储任务节点与参与者的相关信息 | |
| act_ru_integration | 运行时积分表 | |
| act_ru_job | 定时异步任务数据表 | |
| act_ru_suspended_job | 运行时作业暂停表, 比如流程中有一个定时任务,如果把这个任务停止工作了,这个任务写入到此表中 | |
| act_ru_task | 运行时任务节点表 | |
| act_ru_timer_job | 运行时定时器作业表 | |
| act_ru_variable | 运行时流程变量数据表 | |
| 其他表 | ||
| act_procdef_info | 流程定义的动态变更信息 | |
| act_evt_log | 流程引擎的通用事件日志记录表 |
五、Activiti7 的Servcie核心接口
Activiti不需要我们去创建一系列的建Entity 、 DAO、Service、Controller,有现成接口直接调用
Service 管理接口说明:
| Service接口 | 说明 |
|---|---|
| RuntimeService | 运行时 Service,可以处理所有正在运行状态的流程实例和任务等 |
| RepositoryService | 流程仓库 Service,主要用于管理流程仓库,比如流程定义的控制管理(部署、删除、挂起、激活…) |
| DynamicBpmnService | RepositoryService可以用来部署流程定义(使用xml形式定义好的),一旦部署到Activiti(解析后保存到DB),那么流程定义就不会再变了,除了修改xml定义文件内容;而DynamicBpmnService就允许我们在程序运行过程中去修改流程定义,例如:修改流程定义中的分配角色、优先级、流程流转的条件等等 |
| TaskService | 任务 Service,用于管理和查询任务,例如:签收、办理等 |
| HistoryService | 历史 Service,可以查询所有历史数据,例如:流程实例信息、参与者信息、完成时间… |
| ManagementService | 引擎管理Service,和具体业务无关,主要用于对Activiti流程引擎的管理和维护。 |
核心 Service 接口实例获取方式如下:
// 会在首次调用时初始化并构建一个流程引擎,此后始终返回相同的流程引擎。
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 引擎管理类
ManagementService managementService = processEngine.getManagementService();
// 动态修改流程管理类
DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();
// 流程运行管理类
RuntimeService runtimeService = processEngine.getRuntimeService();
// 流程仓库管理类
RepositoryService repositoryService = processEngine.getRepositoryService();
// 任务管理类
TaskService taskService = processEngine.getTaskService();
// 历史管理类
HistoryService historyService = processEngine.getHistoryService();
六、Activiti7 流程实操
6.1 idea安装插件
Activiti BPMN visualizer

6.2 绘制流程定义模型
1.在 /resources 目录下创建 processes 目录,用于存放流程图
2.创建名为 leave 的文件

3.在 leave.bpmn.xml 空白处右键,打开编辑页面

建立如下流程:

其中设置流程中的name和assignee:


然后导出png图片:
右键空白处:

生成leave.png:

6.3 部署流程定义
将上面在设计器中定义的流程部署到activiti数据库中,就是流程定义部署。
通过调用activiti的api将流程定义的 .bpm 和 png 两个文件一个一个添加部署到activiti中
/*** 部署流程:* 1. act_re_deployment 流程部署表,每执行一次部署,会插入一条记录,同样的流程多次部署不同的流程部署ID* 2. act_re_procdef 生成流程定义信息,同样的流程多次部署不同的流程定义ID与版本号version* 3. act_ge_bytearray 流程资源表,插入资源数据,当前插入两条记录(.bpmn和.png资源)*/@Testpublic void deployByFile() {// 1. 实例化流程引擎实例ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 2. 获取流程定义和部署对象相关的ServiceRepositoryService repositoryService = processEngine.getRepositoryService();// 3. 创建部署对象进行流程的部署,定义一个流程的名字,把 .bpmn 和 .png 部署到数据库中Deployment deployment = repositoryService.createDeployment().name("请假申请流程").addClasspathResource("processes/leave.bpmn20.xml").addClasspathResource("processes/leave.png").deploy();// 4. 输出部署信息System.out.println("部署ID:" + deployment.getId() );System.out.println("部署名称:" + deployment.getName() );}
执行两次并不会发生冲突,act_re_deployment 流程部署表只是ID不同,act_re_procdef 流程定义数据表ID和版本version都不同

6.4 查询流程定义
主要针对去查询act_re_procdef表的东西,可以根据key去找,或者根据流程定义ID去找
/*** 查询部署的流程定义数据 ACT_RE_PROCDEF*/@Testpublic void getProcessDefinitionList() {// 1. 实例化流程引擎实例ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 2. 获取 RepositoryServiceRepositoryService repositoryService = processEngine.getRepositoryService();// 3. 获取 ProcessDefinitionQueryProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();Set<String> set = new HashSet<String>();set.add("leaveProcess:1:4");set.add("leaveProcess:2:2504");// List<ProcessDefinition> definitionList = query.processDefinitionKey("leaveProcess") // 根据key去找List<ProcessDefinition> definitionList = query.processDefinitionIds(set) // 根据流程定义ID去找.orderByProcessDefinitionVersion() // 按版本号排序.desc() // 降序.list();for (ProcessDefinition pd : definitionList) {System.out.println("流程部署ID:" + pd.getDeploymentId());System.out.println("流程定义ID:" + pd.getId());System.out.println("流程定义Key:" + pd.getKey());System.out.println("流程定义名称:" + pd.getName());System.out.println("流程定义版本号:" + pd.getVersion());}}
查询结果如下:

6.5 启动流程(发起申请)
类似 java类 与 java实例对象 一样。发起一个申请就类似 new 了一个对象。
/*** 启动流程(发起申请)*/@Testpublic void startProcessInstance() {// 1. 实例化ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 2. 获取 RuntimeServiceRuntimeService runtimeService = processEngine.getRuntimeService();// 开启流程实例 (流程设计图唯一标识key) 按照 key 启动会去找版本最新的执行ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leaveProcess");System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());System.out.println("流程实例id:" + processInstance.getId());}

其中涉及的表有:
- act_hi_actinst 流程实例执行的节点历史信息
- act_hi_identitylink 流程的参与用户历史信息
- act_hi_procinst 流程实例历史信息
- act_hi_taskinst 流程实例的任务历史信息
- act_ru_execution 流程运行中执行信息
- act_ru_identitylink 流程运行中参与用户信息
- act_ru_task 流程运行中任务信息
6.6 查询办理人待办任务与完成任务
启动流程实例后,用户查询自己当前的待办任务,然后执行后续操作
/*** 查询指定人员的待办任务*/@Testpublic void taskListByAssignee() {// 1. 实例化流程引擎实例ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 2. 获取 TaskServiceTaskService taskService = processEngine.getTaskService();// 3. 根据流程唯一标识 key 和 任务办理人 查询任务List<Task> list = taskService.createTaskQuery().processDefinitionKey("leaveProcess") // 根据 Key.taskAssignee("领导")// 查询 领导 的任务.list();for (Task task : list) {System.out.println("流程实例id:" + task.getProcessInstanceId());System.out.println("任务id:" + task.getId());System.out.println("任务名称:" + task.getName());System.out.println("任务办理人:" + task.getAssignee());}}

以上只是查询,查询后需要执行后续操作
/*** 完成待办任务*/@Testpublic void completeTask() {// 1. 实例化流程引擎实例ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 2. 获取 TaskServiceTaskService taskService = processEngine.getTaskService();// 3. 查询代办任务Task task = taskService.createTaskQuery().processDefinitionKey("leaveProcess") // 流程 Key.taskAssignee("领导") // 查询 领导 的任务
// .taskAssignee("总经理").singleResult(); // 目前只有一条任务,则可以只获取一条// 4. 完成任务(任务id)taskService.complete(task.getId());}
执行上述代码后 act_ru_task 表里的 name 那一列从领导审批变成了总经理审批
上面代码更换注释,执行总经理审批,act_ru_task 删除刚刚执行的一行数据。
6.7 查询流程实例历史节点信息
通过 HistoryService 历史数据对象来获取 HistoricActivityInstanceQuery 历史节点查询对象
/*** 查看流程办理历史信息*/@Testpublic void historyInfo(){// 1. 实例化流程引擎实例ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 2. 获取 HistoryServiceHistoryService historyService = processEngine.getHistoryService();// 3. 获取节点历史记录查询对象 ACT_HI_ACTINST 表HistoricActivityInstanceQuery query = historyService.createHistoricActivityInstanceQuery();List<HistoricActivityInstance> list = query.processInstanceId("5001").orderByHistoricActivityInstanceStartTime() // 根据开始时间排序 asc 升序.asc().list();for (HistoricActivityInstance hi : list) {System.out.print("流程定义ID: " + hi.getProcessDefinitionId());System.out.print(",流程实例ID: " + hi.getProcessInstanceId());System.out.print(",节点ID: " + hi.getActivityId());System.out.print(",节点名称: " + hi.getActivityName());System.out.print(",任务办理人:" + hi.getAssignee());System.out.print(",开始时间:" + hi.getStartTime());System.out.println("结束时间:" + hi.getEndTime());}}
“5001“从act_hi_procinst查找
相关文章:
Activiti 工作流大致了解
一、什么是 Activiti 简而言之,就是系统的流程图,如:请假审批流程、账单审批流程等。 二、mysql与pom配置 mysql要使用jdbc:mysql://localhost:3306/activiti?autoReconnecttrue pom文件要添加关键依赖 <!--activiti核心依赖--> &…...
速盾:高防 CDN,网站安全的有力保障
在当今数字化时代,网站安全已成为企业和个人关注的焦点。随着网络攻击手段的不断升级,传统的安全防护措施已经难以满足需求。而高防 CDN(Content Delivery Network,内容分发网络)的出现,为网站安全提供了有…...
宝塔搭建nextcould 30docker搭建onlyoffic8.0
宝塔搭建nextcould 宝塔搭建nextcould可以参考这两个博文 我搭建的是30版本的nextcould,服务组件用的是下面这些,步骤是一样的,只是版本不一样而已 nginx 1.24.0 建议选择nginx,apache没成功。 MySQL 8.0以上都可以 php 8.2.…...
【源码+文档+调试讲解】交通信息管理系统
摘 要 智能交通信息管理系统是一种基于计算机技术的软件系统,旨在提高交通管理的效率和服务质量。通过该系统可以实现智能交通管理的全面管理和优化。智能交通信息管理系统具备集成管理功能。它能够整合智能交通管理的各个业务环节,包括个人中心、用户管…...
小阿轩yx-案例:Ansible剧本文件实践
小阿轩yx-案例:Ansible剧本文件实践 Playbook 介绍 什么是 playbook playbook 顾名思义,即剧本,现实生活中演员按照剧本表演在 ansible 中,由被控计算机表演,进行安装,部署应用,提供对外的服…...
【ShuQiHere】深入理解微架构(Microarchitecture):LC-3 的底层实现 ️
【ShuQiHere】🖥️ 微架构(Microarchitecture) 是计算机体系结构中的重要概念,它定义了如何将 指令集架构(Instruction Set Architecture, ISA) 转化为实际硬件。通过微架构,我们可以理解计算机…...
Ubuntu24.04.1系统下VideoMamba环境配置
文章目录 前言第一步:基本的环境创建第二步:causal-conv1d和mamba_ssm库的安装第三步:安装requirements.txt 前言 VideoMamba环境的配置折磨了我三天,由于Mamba对Cuda的版本有要求,因此配置环境的时候Cuda版本以及各种…...
c++第十二章续(队列结构类模拟)
队列类 设计类,需要开发公有接口和私有实现 Queue类接口 公有接口: 默认初始化,和可以用显式初始化覆盖默认值 Queue类的实现 如何表示队列数据: 一种方法是使用new动态分配一个数组,它包含所需的元素数。不过&…...
数据集-目标检测系列-豹子 猎豹 检测数据集 leopard>> DataBall
数据集-目标检测系列-豹子 猎豹 检测数据集 leopard>> DataBall 数据集-目标检测系列-豹子 猎豹 检测数据集 leopard 数据量:5k 想要进一步了解,请联系。 DataBall 助力快速掌握数据集的信息和使用方式,会员享有 百种数据集&#x…...
基于ESP8266—AT指令连接阿里云+MQTT透传数据(3)
MQTT_RX设备为接收(订阅)数据的Topic,使用ESP8266通过AT指令实现。 首先需要串口通信软件,如 SSCOM、PuTTY、SecureCRT 等串口调试工具,功能丰富,支持常见的串口调试功能,用于发送AT指令。 以下是ESP8266通过AT指令连接阿里云MQTT服务的步骤: 1、初始化WiFi 发送下面…...
redis的数据结构,内存处理,缓存问题
redisObject redis任意数据的key和value都会被封装为一个RedisObject,也叫redis对象: 这就redis的头信息,占有16个字节 redis中有两个热门数据结构 1.SkipList,跳表,首先是链表,和普通链表有以下差异&am…...
机器学习模型评估与选择
前言 承接上篇讲述了机器学习有哪些常见的模型算法,以及使用的场景,本篇将继续讲述如何选择模型和评估模型。几个概念了解一下: 经验误差:模型在训练集上的误差称之为经验误差;过拟合:模型在训练集上表现…...
Web认识 -- 第一课
文章目录 前言一、HTML是什么?二、了解Web1. 基本概念2.Web标准3. Web构成1.前端1. HTML2.CSS3. javaScript4.常见浏览器介绍 2.Web标签构成1.结构标准2.表现标准 -- css3. 行为标准 -- javaScript 总结 前言 这里是我们进入前端学习的开端,在本次更新之后我会陆续…...
Recaptcha2 图像识别 API 对接说明
Recaptcha2 图像识别 API 对接说明 本文将介绍一种 Recaptcha2 图像识别2 API 对接说明,它可以通过用户输入识别的内容和 Recaptcha2验证码图像,最后返回需要点击的小图像的坐标,完成验证。 接下来介绍下 Recaptcha2 图像识别 API 的对接说…...
6种MySQL高可用方案对比分析
大家好,我是 V 哥,关于 MySQL 高可用方案,在面试中频频出现,有同学在字节面试就遇到过,主要考察你在高可用项目中是如何应用的,V 哥整理了6种方案,供你参考。 MySQL的高可用方案有多种…...
FastAPI: websocket的用法及举例
1. Websocket 1.1 Websocket介绍 WebSocket 是一种在单个TCP连接上进行全双工通信的协议,允许客户端和服务器之间相互发送数据,而不需要像传统的HTTP请求-响应模型那样频繁建立和断开连接。 全双工通信(Full-Duplex Communication)是一种通信模式&#…...
JavaSE——面向对象2:方法的调用机制、传参机制、方法递归、方法重载、可变参数、作用域
目录 一、成员方法 (一)方法的快速入门 (二)方法的调用机制(重要) (三)方法的定义 (四)注意事项和使用细节 1.访问修饰符(作用是控制方法的使用范围) 2.返回的数据类型 3.方法名 4.形参列表 5.方法体 6.方法调用细节说明 (五)传参机制 1.基本数据类型的传参机制 …...
Vue+Flask
App.vue 首先要安装 npm install axios<template><div><h1>{{ message }}</h1><input v-model"name" placeholder"Enter your name" /><input v-model"age" placeholder"Enter your age" /><…...
深入剖析 Android Lifecycle:构建高效稳定的应用
在 Android 开发中,管理应用组件的生命周期是至关重要的。正确处理生命周期事件可以确保应用的性能、稳定性和用户体验。Android Framework 提供了一系列的机制来管理应用组件的生命周期,而android.arch.lifecycle库则为我们提供了更简洁、更灵活的方式来…...
ElasticSearch分词器、相关性详解与聚合查询实战
目录 1. ES分词器详解 1.1 基本概念 1.2 分词发生时期 1.3 分词器的组成 切词器:Tokenizer 词项过滤器:Token Filter 字符过滤器:Character Filter 1.4 倒排索引的数据结构 2. 相关性详解 2.1 什么是相关性(Relevance&am…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)
Name:3ddown Serial:FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名:Axure 序列号:8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...
