深入浅出Activity工作流:从理论到实践,让业务流转自动化 - 指南

news/2026/1/25 12:15:50/文章来源:https://www.cnblogs.com/tlnshuju/p/19529147

深入浅出Activity工作流:从理论到实践,让业务流转自动化 - 指南

2026-01-25 12:15  tlnshuju  阅读(0)  评论(0)    收藏  举报

引言

在现代企业级应用开发中,复杂的业务流程无处不在,例如请假审批、订单处理、合同审核等。这些流程往往涉及多个环节、多个角色以及各种条件分支。如果将这些流程逻辑硬编码在业务代码中,会导致代码臃肿、难以维护,且流程的任何变更都需要开发人员修改代码并重新部署。

Activity工作流引擎​ 正是为了解决这一问题而生的。它允许我们将业务过程的描述(先做什么,后做什么,由谁做,条件是什么)与具体的业务代码分离开来,从而实现业务流程的自动化管理。

一、Activity工作流是什么?

Activity是一个轻量级、开源的工作流和业务流程管理(BPM)引擎。它的核心是 ​BPMN 2.0​ 标准。

  • 工作流引擎​:可以理解为一个"业务流程的控制器"。它根据预先定义好的流程规则,推动一个流程实例从开始节点一步步执行到结束节点。
  • BPMN 2.0​:是一种全球通用的流程建模符号标准。它使用一套标准的图形元素(如圆圈、矩形、菱形)来描绘业务流程,使得业务分析师和开发人员可以用同一种"语言"进行沟通。

简单来说,你用BPMN 2.0的图表来"画"出流程,Activity引擎则负责"执行"你画出的流程图。

二、核心概念与架构

在深入代码之前,我们先了解几个核心概念,并通过一张架构图来建立整体认知。

概念解释类比
ProcessEngine工作流引擎的核心,相当于整个系统的"大脑",所有服务都由它创建和管理。公司的总指挥部
RepositoryService负责管理流程定义(如部署一个BPMN图表文件)。仓库管理员
RuntimeService负责启动流程实例和管理运行中的流程。流程启动器与监控中心
TaskService负责管理流程中产生的"任务",例如查询任务、完成任务等。这是与用户交互最频繁的服务。任务分发与回收站
HistoryService负责查询历史流程实例信息,便于追踪和审计。档案馆
IdentityService负责管理用户和组(角色)。人力资源部

Activity系统架构简图

这张图清晰地展示了Activity内部的核心协作关系:通过RepositoryService部署流程定义,然后由RuntimeService创建流程实例,TaskService则负责推动实例中具体任务的生命周期。

三、一个生动的例子:请假流程

让我们通过一个简单的请假流程来感受Activity的魅力。

1. 流程设计

假设一个请假流程是:员工申请 -> 经理审批 -> 结束。
我们用BPMN图来设计它:

  • 开始事件​:流程的起点。
  • 用户任务​:需要人工参与的活动,这里是"员工申请"和"经理审批"。
  • 排他网关​:像一个路标,根据条件决定流程的走向。例如,审批"批准"则结束,"拒绝"则打回重填。
  • 结束事件​:流程的终点。

2. 代码实现

首先,我们需要创建流程引擎并部署流程定义:

// 1. 创建流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2. 获取RepositoryService,进行部署
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment().addClasspathResource("processes/leave-application.bpmn20.xml") // BPMN文件路径.name("请假流程部署").deploy(); // 执行部署
System.out.println("流程部署ID: " + deployment.getId());

部署成功后,启动一个具体的请假流程实例:

// 3. 获取RuntimeService,启动流程实例
RuntimeService runtimeService = processEngine.getRuntimeService();
// 使用流程定义的Key来启动,默认是最新版本
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leaveApplication");
System.out.println("流程实例ID: " + processInstance.getId());

流程启动后,查询并完成任务:

// 4. 获取TaskService,查询任务
TaskService taskService = processEngine.getTaskService();
// 假设当前用户是"zhangsan"
List tasks = taskService.createTaskQuery().taskAssignee("zhangsan").list();
for (Task task : tasks) {System.out.println("任务ID: " + task.getId());System.out.println("任务名称: " + task.getName());// 办理任务(填写请假单)Map variables = new HashMap<>();variables.put("leaveDays", 3); // 设置流程变量:请假3天variables.put("reason", "回家探亲");taskService.complete(task.getId(), variables); // 完成任务
}

经理审批任务:

// 经理登录系统,查询自己的待办任务
List managerTasks = taskService.createTaskQuery().taskAssignee("manager").list();
for (Task task : managerTasks) {// 经理审批,传递审批意见Map variables = new HashMap<>();variables.put("approval", "reject"); // 审批结果:拒绝taskService.complete(task.getId(), variables);
}

四、进阶特性:驾驭复杂业务流程

当业务变得复杂时,基础的单线流程就不够用了。Activity提供了强大的BPMN元素来应对。

1. 并行网关:处理并行任务

场景​:请假流程升级,需要员工直属经理和部门总监同时审批。

  • 并行网关​:所有外出连线上的任务会同时被创建,并且必须全部完成,流程才会继续向下执行。直属经理和总监可以同时审批,互不依赖。

2. 包含网关:处理条件并行

场景​:根据请假天数决定审批路径,3天以内只需直属经理审批,3-5天需要直属经理和HR审批,5天以上需要直属经理、HR和部门总监审批。

3. 子流程:实现流程模块化

场景​:经理审批通过后,如果请假天数超过5天,需要启动一个"HR备案"子流程。

  • 嵌入子流程​:将一部分流程逻辑封装起来,使主流程更清晰。子流程可以有自己独立的作用域和变量。

4. 边界事件:响应异常与超时

场景​:给经理审批任务加上一个"定时边界事件",如果48小时内未处理,则自动超时并通过邮件提醒经理。

边界事件详细说明:​

  • 当任务"经理审批"创建时,定时器开始计时(如48小时)
  • 如果在时间内完成任务,流程正常继续
  • 如果超时未完成,边界事件触发,执行"发送提醒邮件"
  • 邮件发送后,可以重新分配任务或提醒经理处理

五、与Spring Boot无缝集成

现代Java应用开发离不开Spring Boot。Activity与Spring Boot的集成非常简单。

1. 添加依赖

org.activitiactiviti-spring-boot-starter7.0.0.SR1

2. 配置数据源(application.yml)​

spring:datasource:url: jdbc:mysql://your-db-host:3306/activiti?useUnicode=trueusername: your-usernamepassword: your-passwordactiviti:# 自动部署:检查resources/processes下的流程文件check-process-definitions: truedatabase-schema-update: truehistory-level: audit

3. 在Service层中使用

集成后,Activity的各个Service(如RuntimeServiceTaskService)会作为Bean被Spring管理,可以直接@Autowired注入使用。

@Service
@Transactional
public class LeaveApplicationService {@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;@Autowiredprivate HistoryService historyService;/*** 启动请假流程*/public ProcessInstance startLeaveProcess(LeaveRequest request) {Map variables = new HashMap<>();variables.put("employee", request.getEmployee());variables.put("days", request.getDays());variables.put("reason", request.getReason());variables.put("startDate", request.getStartDate());variables.put("endDate", request.getEndDate());// 启动流程实例,并设置初始变量ProcessInstance instance = runtimeService.startProcessInstanceByKey("leaveProcess",request.getId().toString(), // 业务键variables);return instance;}/*** 查询用户待办任务*/public List getTasksForUser(String userId) {return taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list();}/*** 完成任务*/public void completeTask(String taskId, Map variables) {if (variables != null && !variables.isEmpty()) {taskService.complete(taskId, variables);} else {taskService.complete(taskId);}}/*** 查询流程历史*/public List getProcessHistory(String businessKey) {return historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).orderByProcessInstanceStartTime().desc().list();}
}

4. RESTful API控制器

@RestController
@RequestMapping("/api/process")
public class ProcessController {@Autowiredprivate LeaveApplicationService leaveApplicationService;/*** 启动请假流程*/@PostMapping("/leave/start")public ResponseEntity startLeaveProcess(@RequestBody LeaveRequest request) {try {ProcessInstance instance = leaveApplicationService.startLeaveProcess(request);return ResponseEntity.ok(instance);} catch (Exception e) {return ResponseEntity.badRequest().body("启动流程失败: " + e.getMessage());}}/*** 获取用户待办任务*/@GetMapping("/tasks/{userId}")public ResponseEntity> getUserTasks(@PathVariable String userId) {List tasks = leaveApplicationService.getTasksForUser(userId);return ResponseEntity.ok(tasks);}/*** 完成任务*/@PostMapping("/tasks/{taskId}/complete")public ResponseEntity completeTask(@PathVariable String taskId,@RequestBody Map variables) {try {leaveApplicationService.completeTask(taskId, variables);return ResponseEntity.ok("任务完成成功");} catch (Exception e) {return ResponseEntity.badRequest().body("完成任务失败: " + e.getMessage());}}
}

六、精细控制:流程变量与监听器

流程变量

流程变量是贯穿流程实例生命周期的上下文数据,用于传递业务参数和控制流程走向。

/*** 流程变量管理示例*/
@Service
public class ProcessVariableService {@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;/*** 设置流程变量*/public void setProcessVariables(String executionId, Map variables) {runtimeService.setVariables(executionId, variables);}/*** 获取流程变量*/public Object getProcessVariable(String executionId, String variableName) {return runtimeService.getVariable(executionId, variableName);}/*** 设置任务局部变量*/public void setTaskLocalVariables(String taskId, Map variables) {taskService.setVariablesLocal(taskId, variables);}/*** 在完成任务时设置变量*/public void completeTaskWithVariables(String taskId, Map variables) {// 这些变量会在任务完成后成为流程变量taskService.complete(taskId, variables);}
}

监听器

监听器允许你在流程的特定点(如任务创建、任务完成、流程开始/结束)插入自定义逻辑。

执行监听器架构

1. 任务监听器

/*** 任务分配监听器 - 在任务创建时自动发送通知*/
@Component
public class TaskAssignmentListener implements TaskListener {@Autowiredprivate NotificationService notificationService;@Autowiredprivate UserService userService;@Overridepublic void notify(DelegateTask delegateTask) {String eventName = delegateTask.getEventName();String assignee = delegateTask.getAssignee();String taskName = delegateTask.getName();String processInstanceId = delegateTask.getProcessInstanceId();switch (eventName) {case "create":handleTaskCreate(delegateTask, assignee, taskName, processInstanceId);break;case "complete":handleTaskComplete(delegateTask, assignee, taskName, processInstanceId);break;case "assignment":handleTaskAssignment(delegateTask, assignee, taskName, processInstanceId);break;}}private void handleTaskCreate(DelegateTask delegateTask, String assignee,String taskName, String processInstanceId) {if (assignee != null) {// 发送通知String message = String.format("您有新的待办任务:%s (流程实例ID: %s)",taskName, processInstanceId);notificationService.sendNotification(assignee, message);// 记录日志System.out.println("任务创建通知已发送给: " + assignee);}}private void handleTaskComplete(DelegateTask delegateTask, String assignee,String taskName, String processInstanceId) {// 任务完成时的处理逻辑String completionMessage = String.format("任务已完成:%s (办理人: %s)",taskName, assignee);System.out.println(completionMessage);// 可以记录操作日志到数据库// auditService.logTaskCompletion(taskName, assignee, new Date());}private void handleTaskAssignment(DelegateTask delegateTask, String assignee,String taskName, String processInstanceId) {// 任务分配时的处理逻辑System.out.println("任务已分配给: " + assignee);}
}

2. 执行监听器

/*** 流程执行监听器 - 监听流程开始、结束等事件*/
@Component
public class ProcessExecutionListener implements ExecutionListener {@Autowiredprivate BusinessService businessService;@Autowiredprivate AuditService auditService;@Overridepublic void notify(DelegateExecution execution) {String eventName = execution.getEventName();String processInstanceId = execution.getProcessInstanceId();String activityId = execution.getCurrentActivityId();switch (eventName) {case "start":handleProcessStart(execution, processInstanceId);break;case "end":handleProcessEnd(execution, processInstanceId);break;case "take":handleTransition(execution, processInstanceId, activityId);break;}}private void handleProcessStart(DelegateExecution execution, String processInstanceId) {String businessKey = execution.getProcessInstanceBusinessKey();System.out.println("流程启动: " + processInstanceId + ", 业务键: " + businessKey);if (businessKey != null) {// 更新业务实体状态为"审批中"businessService.updateStatus(businessKey, "IN_PROGRESS");}// 记录流程启动审计日志auditService.logProcessStart(processInstanceId, businessKey, new Date());}private void handleProcessEnd(DelegateExecution execution, String processInstanceId) {String businessKey = execution.getProcessInstanceBusinessKey();String status = (String) execution.getVariable("finalStatus");System.out.println("流程结束: " + processInstanceId + ", 最终状态: " + status);if (businessKey != null) {// 更新业务实体状态businessService.updateStatus(businessKey, status != null ? status : "COMPLETED");}// 记录流程结束审计日志auditService.logProcessEnd(processInstanceId, businessKey, status, new Date());}private void handleTransition(DelegateExecution execution, String processInstanceId, String activityId) {// 记录流程流转日志System.out.println("流程流转至: " + activityId);auditService.logActivityTransition(processInstanceId, activityId, new Date());}
}

3. 在BPMN XML中配置监听器


3}]]>

七、完整示例:复杂请假流程实现

下面是一个完整的复杂请假流程实现,包含所有讨论的特性:

/*** 复杂请假流程服务*/
@Service
@Transactional
public class ComplexLeaveProcessService {@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;@Autowiredprivate HistoryService historyService;@Autowiredprivate RepositoryService repositoryService;@Autowiredprivate UserService userService;/*** 部署流程定义*/public Deployment deployProcess() {return repositoryService.createDeployment().addClasspathResource("processes/complex-leave-process.bpmn20.xml").name("复杂请假流程").deploy();}/*** 启动复杂请假流程*/public ProcessInstance startComplexLeaveProcess(ComplexLeaveRequest request) {// 确定审批人String manager = userService.findManagerByEmployee(request.getEmployeeId());String hr = userService.findHROfficer();String director = userService.findDepartmentDirector(request.getDepartmentId());Map variables = new HashMap<>();variables.put("applicant", request.getEmployeeId());variables.put("manager", manager);variables.put("hr", hr);variables.put("director", director);variables.put("days", request.getDays());variables.put("reason", request.getReason());variables.put("startDate", request.getStartDate());variables.put("endDate", request.getEndDate());variables.put("department", request.getDepartmentId());// 根据天数设置审批路径if (request.getDays() > 5) {variables.put("needDirectorApprove", true);} else if (request.getDays() > 3) {variables.put("needHRApprove", true);}return runtimeService.startProcessInstanceByKey("complexLeaveProcess",String.valueOf(request.getId()),variables);}/*** 获取用户的待办任务(包含任务详情)*/public List getTaskDetailsForUser(String userId) {List tasks = taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list();return tasks.stream().map(task -> {TaskDetailDTO detail = new TaskDetailDTO();detail.setTaskId(task.getId());detail.setTaskName(task.getName());detail.setCreateTime(task.getCreateTime());detail.setProcessInstanceId(task.getProcessInstanceId());// 获取流程变量Map variables = taskService.getVariables(task.getId());detail.setVariables(variables);// 获取业务信息String businessKey = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult().getBusinessKey();detail.setBusinessKey(businessKey);return detail;}).collect(Collectors.toList());}/*** 完成任务并传递变量*/public void completeTaskWithDecision(String taskId, String decision, String comment) {Map variables = new HashMap<>();variables.put("approvalResult", decision);variables.put("approvalComment", comment);variables.put("approvalTime", new Date());if ("reject".equals(decision)) {variables.put("finalStatus", "REJECTED");}taskService.complete(taskId, variables);// 如果是最后一个审批任务且被批准,更新最终状态if ("approve".equals(decision)) {checkAndUpdateFinalStatus(taskId);}}/*** 检查并更新最终状态*/private void checkAndUpdateFinalStatus(String completedTaskId) {Task completedTask = taskService.createTaskQuery().taskId(completedTaskId).singleResult();String processInstanceId = completedTask.getProcessInstanceId();// 检查是否还有未完成的审批任务long activeTaskCount = taskService.createTaskQuery().processInstanceId(processInstanceId).count();if (activeTaskCount == 0) {// 所有审批完成,更新最终状态为已批准runtimeService.setVariable(processInstanceId, "finalStatus", "APPROVED");}}/*** 查询流程历史记录*/public ProcessHistoryDTO getProcessHistory(String businessKey) {ProcessHistoryDTO history = new ProcessHistoryDTO();// 获取流程实例历史HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();history.setProcessInstance(processInstance);// 获取任务历史List taskHistory = historyService.createHistoricTaskInstanceQuery().processInstanceBusinessKey(businessKey).orderByHistoricTaskInstanceStartTime().asc().list();history.setTaskHistory(taskHistory);// 获取流程变量历史List variableHistory = historyService.createHistoricVariableInstanceQuery().processInstanceBusinessKey(businessKey).list();history.setVariableHistory(variableHistory);return history;}
}
/*** 请假请求DTO*/
@Data
class ComplexLeaveRequest {private Long id;private String employeeId;private String departmentId;private Integer days;private String reason;private Date startDate;private Date endDate;
}
/*** 任务详情DTO*/
@Data
class TaskDetailDTO {private String taskId;private String taskName;private Date createTime;private String processInstanceId;private String businessKey;private Map variables;
}
/*** 流程历史DTO*/
@Data
class ProcessHistoryDTO {private HistoricProcessInstance processInstance;private List taskHistory;private List variableHistory;
}

八、总结

Activity工作流引擎将抽象的流程定义转化为可执行的代码,是企业应用开发中处理复杂业务流程的强大工具。通过 ​BPMN 2.0标准图​ 与 ​清晰的API服务,它极大地提升了流程类应用的开发效率和可维护性。

核心价值

  1. 可维护性高​:流程逻辑与业务代码解耦。当业务流程发生变化时(例如,增加一个总监审批环节),通常只需要修改BPMN图并重新部署,无需修改Java代码。
  2. 可视化与可追溯性​:BPMN图使业务流程一目了然。HistoryService 可以让你轻松查看任何一个流程实例的完整执行路径。
  3. 提高开发效率​:开发人员更专注于每个节点的具体业务实现,而复杂的流程流转、持久化、事务管理等都由引擎自动处理。
  4. 灵活性​:支持动态调整流程、任务跳转、委托等高级功能,能够适应复杂的业务场景。
  5. 强大的生态与集成​:与Spring家族无缝集成,并提供了REST API,便于前后端分离架构。

适用场景

  • 审批流系统​:请假、报销、采购等审批流程
  • 订单处理​:电商订单的状态流转和处理
  • 工单系统​:客户服务请求的分配和处理
  • 合同管理​:合同起草、审批、签订的全生命周期管理

从简单的线性审批到包含并行网关、子流程、边界事件的复杂场景,Activity都能游刃有余。通过与 ​Spring Boot 的集成,可以快速搭建企业级应用。而流程变量监听器等高级功能,则为实现精细化的业务控制提供了可能。

希望本篇完整的指南能帮助你系统性地掌握Activity,并将其成功应用到你的项目中,最终实现业务流程的自动化与智能化管理。


扩展学习方向​:

  • 探索Activity Modeler进行可视化流程设计
  • 学习Activiti的REST API,构建前后端分离的工作流平台
  • 研究历史数据的高效查询与清理策略
  • 了解流程实例的迁移和版本管理策略
  • 探索与规则引擎(Drools)的集成实现动态路由

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1214316.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何搭建公司网站?网站建设公司搭建网站有哪些步骤呀?

作为一名经历过网站建设诸多挑战的过来人&#xff0c;我将结合自身经验与行业常见流程&#xff0c;系统梳理公司网站建设的步骤与注意事项&#xff0c;帮助大家厘清实际需求&#xff0c;减少不必要的弯路。 一、明确需求与目标&#xff08;核心起点&#xff09; 1、确定网站类型…

Python 使用 subprocess 检测 Linux 用户是否存在,不存在则自动创建

一、背景说明 在 Linux 服务器自动化运维、初始化脚本或容器环境中&#xff0c;经常需要判断某个系统用户是否存在&#xff1a; 如果存在&#xff1a;直接使用如果不存在&#xff1a;自动创建用户 本文介绍如何使用 Python 的 subprocess 模块&#xff0c;调用系统命令 id 和…

全网最全10个AI论文软件,专科生轻松搞定毕业论文!

全网最全10个AI论文软件&#xff0c;专科生轻松搞定毕业论文&#xff01; AI 工具让论文写作不再难 对于专科生来说&#xff0c;撰写毕业论文往往是一个令人头疼的任务。从选题到开题&#xff0c;再到撰写和降重&#xff0c;每一个环节都可能让人感到压力山大。而随着 AI 技术…

超详细版Batocera游戏整合包配置步骤(新手友好)

以下是对您提供的博文《超详细版 Batocera 游戏整合包配置技术解析》的 深度润色与工程化重构版本 。本次优化严格遵循您的全部要求: ✅ 彻底去除AI痕迹(无模板化句式、无空洞总结、无机械连接词) ✅ 摒弃“引言/概述/核心特性/原理解析/实战指南/总结”等刻板结构 ✅ …

Qwen-Image-Edit-2511保姆级教程:从下载到出图全流程

Qwen-Image-Edit-2511保姆级教程&#xff1a;从下载到出图全流程 你是不是也遇到过这些情况&#xff1a;想把商品图里的背景换成纯白&#xff0c;结果边缘发灰&#xff1b;想给海报加一句中文标语&#xff0c;字体却和原图不搭&#xff1b;想让两张人物照片风格统一&#xff0…

深度剖析usb_burning_tool支持设备类型与兼容性

以下是对您提供的博文内容进行 深度润色与结构重构后的专业级技术文章 。整体遵循“去AI化、强人设、重实战、轻模板”的原则,摒弃所有刻板标题与套路化表达,以一位深耕嵌入式烧录领域十年的工程师口吻娓娓道来——有经验、有踩坑、有思辨、有温度,同时确保技术细节精准、…

2026山东优秀的污水提升器实力厂家

一、 核心结论 在2026年的市场环境下,地下室改造、商业空间升级及环保标准提升,共同驱动了污水提升器市场的专业化与精细化发展。为帮助山东及全国用户精准选型,本报告建立了一套涵盖产品技术、市场表现、服务能力、…

零基础也能用!YOLOv9官方镜像保姆级教程,快速实现图像识别

零基础也能用&#xff01;YOLOv9官方镜像保姆级教程&#xff0c;快速实现图像识别 你是不是也遇到过这样的情况&#xff1a;刚下载完一个目标检测镜像&#xff0c;打开终端却卡在“conda activate”命令上&#xff1f;或者复制粘贴了一堆训练命令&#xff0c;结果报错说Module…

为什么Qwen3-14B能省事?128k长文单卡推理部署解析

为什么Qwen3-14B能省事&#xff1f;128k长文单卡推理部署解析 1. 它不是“小模型”&#xff0c;而是“刚刚好”的大模型守门员 很多人看到“14B”就下意识划走——觉得参数不够大、性能不够强、跑不起来新任务。但Qwen3-14B恰恰打破了这个惯性认知&#xff1a;它不是在参数规…

Qwen3-4B-Instruct-2507企业部署:高可用架构设计案例

Qwen3-4B-Instruct-2507企业部署&#xff1a;高可用架构设计案例 1. 为什么需要企业级部署方案&#xff1f; 你可能已经试过在单卡上跑通 Qwen3-4B-Instruct-2507——输入几行提示词&#xff0c;模型秒回一段逻辑清晰、语言自然的文本&#xff0c;体验确实流畅。但当它真正走…

直播带货新玩法:用Live Avatar做AI代言人

直播带货新玩法&#xff1a;用Live Avatar做AI代言人 数字人技术正从实验室快速走向直播间。当传统直播依赖真人出镜、固定时段、高人力成本时&#xff0c;一种更灵活、可复用、全天候在线的AI代言人正在改变电商内容生产方式。Live Avatar——由阿里联合高校开源的数字人模型…

2026年成都打印纸市场:实力厂商价格对比与选型全攻略

随着2026年的到来,四川成都的企业采购者们正面临新的挑战与选择:在竞争日益激烈的办公用品市场中,如何筛选出技术扎实、效果可视的打印纸实力厂商?面对市场上林林总总的品牌与服务商,不同规模和发展阶段的企业应如…

2026年国内知名的测水流量计工厂电话,一体式电磁流量计/超声波液位计/醇类流量计/威力巴流量计,测水流量计产品推荐榜

在工业自动化与环保监测领域,测水流量计作为核心计量设备,其精度与稳定性直接影响生产效率与资源管理。近年来,随着国家对水资源保护的重视及工业4.0的推进,市场对高质量测水流量计的需求持续攀升。然而,行业内部…

pwn入门(一)

moectf2025 目录syslockxdulakerezpivotezprotectionfmt_thardpivot迁移到bss段输出puts@gotret2libcexpshellboxNo way to leakelf相关结构延迟绑定_dl_fixupret2dlresolveexpcall_it syslock import ctypes from pwn…

阅读文献的方法

阅读文献的方法Posted on 2026-01-25 12:07 steve.z 阅读(0) 评论(0) 收藏 举报阅读文献的方法 一、一篇文献一般会包含的几部分title - 标题 abs - 导言 intro - 介绍 method - 你提出的算法 exp - 实验 conclus…

2025年AI超级员工使用体验排行榜,AI超级员工/AI企业员工供应商排行榜单

智能营销新纪元:企业数字化转型的关键利器 随着人工智能技术的快速发展,AI超级员工正成为企业数字化转型的重要推动力。据最新市场调研数据显示,2025年全球AI超级员工市场规模预计将达到千亿级别,越来越多的企业开…

机械行业CKEDITOR导入CAD图纸如何PHP自动转存?

广州软件公司技术负责人&#xff1a;Word粘贴与多格式文档导入功能开发实录 一、需求分析与技术规划 作为技术负责人&#xff0c;我主导了客户需求的技术可行性评估与方案规划。核心需求包括&#xff1a; 富文本粘贴功能&#xff1a;支持Word/微信公众号内容粘贴&#xff0c…

2026年市面上评价高的层板货架订做厂家口碑推荐榜,仓库货架/重型货架/自动化立体库货架,层板货架厂商口碑排行榜

行业背景:层板货架市场如何选型? 随着制造业、物流业及电商行业的快速发展,层板货架作为仓储系统的核心设备,其选型需求正从“标准化”向“定制化”“智能化”加速转型。据第三方调研机构统计,2025年国内层板货架…

2026年初国内AI获客系统服务商竞争力深度解析

一、 核心结论 在存量竞争与增量探索并存的2026年,AI获客已成为企业实现增长破局的必备“利器”。本报告旨在拨开市场迷雾,通过一套严谨的四维评估框架——技术能力、市场表现、客户成功、生态建设,对国内主流AI获客…

我不想在核心代码中维护一个只会被使用一次的复杂模板机制,为了方便开发者快速开发、定制或贡献自己的模板,为前端单独抽出一个仓库和文档!

开源项目地址:https://gitee.com/teanary/teanary_template 项目地址:https://teanary.com/zh_CN/index.html 这是一个独立的模板仓库,包含了 Teanary 电商系统的所有前端视图模板文件。这个仓库的目的是方便开发者快…