最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot整合Activiti的項目中實現(xiàn)抄送功能

 更新時間:2026年01月09日 08:32:17   作者:hhzz  
本文主要介紹了SpringBoot整合Activiti的項目中實現(xiàn)抄送功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

1、實現(xiàn)思路

在Activiti工作流中,抄送功能通常不是直接提供的,但可以通過擴展來實現(xiàn)。抄送功能可以理解為將某個任務的信息發(fā)送給相關人員,而不需要他們直接處理任務。在Spring Boot整合Activiti的項目中,我們可以通過以下方式實現(xiàn)抄送功能:

  1. 自定義抄送表:記錄抄送的任務、抄送給誰、抄送時間等信息。
  2. 在任務創(chuàng)建或完成時觸發(fā)抄送邏輯,將任務信息插入抄送表。
  3. 提供接口供用戶查看自己被抄送的任務。

在Spring Boot項目中整合Activiti工作流的抄送功能,可以通過以下方案實現(xiàn):

2、在Spring Boot中集成Activiti

pom.xml中添加Activiti依賴:

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter</artifactId>
    <version>7.1.0.M6</version>
</dependency>

2.1、設計抄送表

創(chuàng)建抄送表,表結(jié)構(gòu)如下:

CREATE TABLE `act_cc_task` (
  `id` varchar(64) NOT NULL COMMENT '主鍵',
  `task_id` varchar(64) DEFAULT NULL COMMENT '任務ID',
  `proc_inst_id` varchar(64) DEFAULT NULL COMMENT '流程實例ID',
  `proc_def_id` varchar(64) DEFAULT NULL COMMENT '流程定義ID',
  `title` varchar(255) DEFAULT NULL COMMENT '抄送標題',
  `content` text COMMENT '抄送內(nèi)容',
  `from_user_id` varchar(64) DEFAULT NULL COMMENT '發(fā)起人',
  `to_user_ids` text COMMENT '接收人(多個用逗號分隔)',
  `status` int(1) DEFAULT '0' COMMENT '狀態(tài)(0:未讀,1:已讀)',
  `create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',
  `read_time` datetime DEFAULT NULL COMMENT '讀取時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2.2、抄送實體類

@Data
@TableName("act_cc_task")
public class CcTask {
    @TableId(type = IdType.ASSIGN_ID)
    private String id;
    private String taskId;
    private String procInstId;
    private String procDefId;
    private String title;
    private String content;
    private String fromUserId;
    private String toUserIds;  // 多個用戶用逗號分隔
    private Integer status;
    private Date createTime;
    private Date readTime;
    
    @TableField(exist = false)
    private List<String> toUserList;  // 接收人列表
}

2.3、實現(xiàn)抄送服務

創(chuàng)建一個抄送服務,用于處理抄送邏輯。例如,在任務完成時,將任務抄送給指定人員。

服務接口:

public interface CcTaskService {
    
    /**
     * 創(chuàng)建抄送任務
     */
    void createCcTask(String taskId, List<String> toUserIds, 
                     String title, String content);
    
    /**
     * 獲取用戶的抄送列表
     */
    PageInfo<CcTask> getUserCcTasks(String userId, Integer pageNum, 
                                   Integer pageSize, Integer status);
    
    /**
     * 標記為已讀
     */
    void markAsRead(String ccTaskId, String userId);
    
    /**
     * 批量抄送
     */
    void batchCcTask(List<String> taskIds, List<String> toUserIds, 
                    String reason);
}

服務實現(xiàn):

在任務完成時觸發(fā)抄送,可以在任務完成事件監(jiān)聽器中觸發(fā)抄送。例如,創(chuàng)建一個任務監(jiān)聽器

@Service
@Slf4j
public class CcTaskServiceImpl implements CcTaskService {
    
    @Autowired
    private CcTaskMapper ccTaskMapper;
    
    @Autowired
    private TaskService taskService;
    
    @Autowired
    private RuntimeService runtimeService;
    
    @Override
    @Transactional
    public void createCcTask(String taskId, List<String> toUserIds, 
                           String title, String content) {
        
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .singleResult();
        
        if (task == null) {
            throw new BusinessException("任務不存在");
        }
        
        // 獲取當前登錄用戶
        String currentUserId = SecurityUtils.getCurrentUserId();
        
        CcTask ccTask = new CcTask();
        ccTask.setId(IdUtil.fastSimpleUUID());
        ccTask.setTaskId(taskId);
        ccTask.setProcInstId(task.getProcessInstanceId());
        ccTask.setProcDefId(task.getProcessDefinitionId());
        ccTask.setTitle(title);
        ccTask.setContent(content);
        ccTask.setFromUserId(currentUserId);
        ccTask.setToUserIds(StringUtils.join(toUserIds, ","));
        ccTask.setStatus(0);
        ccTask.setCreateTime(new Date());
        
        ccTaskMapper.insert(ccTask);
        
        // 發(fā)送通知(可集成消息推送)
        sendNotification(ccTask);
    }
    
    /**
     * 使用監(jiān)聽器自動抄送
     */
    @Component
    public static class TaskCcListener implements TaskListener {
        
        @Autowired
        private CcTaskService ccTaskService;
        
        @Override
        public void notify(DelegateTask delegateTask) {
            String eventName = delegateTask.getEventName();
            
            // 在任務創(chuàng)建時自動抄送
            if ("create".equals(eventName)) {
                Object ccUsers = delegateTask.getVariable("ccUsers");
                if (ccUsers != null) {
                    List<String> userIds = (List<String>) ccUsers;
                    if (!CollectionUtils.isEmpty(userIds)) {
                        String taskName = delegateTask.getName();
                        String content = String.format("任務【%s】需要您知曉", taskName);
                        
                        ccTaskService.createCcTask(
                            delegateTask.getId(),
                            userIds,
                            taskName,
                            content
                        );
                    }
                }
            }
        }
    }
}

然后在流程定義中,在任務完成事件上綁定這個監(jiān)聽器??梢栽贐PMN文件中配置,也可以通過代碼配置。

控制器層:

@RestController
@RequestMapping("/api/cc")
@Api(tags = "抄送管理")
public class CcTaskController {
    
    @Autowired
    private CcTaskService ccTaskService;
    
    @PostMapping("/create")
    @ApiOperation("創(chuàng)建抄送")
    public Result createCcTask(@RequestBody CcTaskCreateDTO dto) {
        ccTaskService.createCcTask(
            dto.getTaskId(),
            dto.getToUserIds(),
            dto.getTitle(),
            dto.getContent()
        );
        return Result.success();
    }
    
    @GetMapping("/list")
    @ApiOperation("獲取抄送列表")
    public Result<PageInfo<CcTask>> getCcList(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam(required = false) Integer status) {
        
        String userId = SecurityUtils.getCurrentUserId();
        PageInfo<CcTask> result = ccTaskService.getUserCcTasks(
            userId, pageNum, pageSize, status
        );
        return Result.success(result);
    }
    
    @PostMapping("/read/{id}")
    @ApiOperation("標記已讀")
    public Result markAsRead(@PathVariable String id) {
        String userId = SecurityUtils.getCurrentUserId();
        ccTaskService.markAsRead(id, userId);
        return Result.success();
    }
}

3、前端集成

3.1、抄送組件

<template>
  <div class="cc-task-container">
    <!-- 抄送按鈕 -->
    <el-button type="text" @click="showCcDialog">
      <i class="el-icon-s-promotion"></i> 抄送
    </el-button>
    
    <!-- 抄送對話框 -->
    <el-dialog title="任務抄送" :visible.sync="ccDialogVisible">
      <el-form :model="ccForm">
        <el-form-item label="接收人">
          <el-select 
            v-model="ccForm.userIds" 
            multiple 
            filterable
            placeholder="請選擇接收人">
            <el-option
              v-for="user in userList"
              :key="user.id"
              :label="user.name"
              :value="user.id">
            </el-option>
          </el-select>
        </el-form-item>
        
        <el-form-item label="抄送說明">
          <el-input
            type="textarea"
            v-model="ccForm.content"
            placeholder="請輸入抄送說明"
            rows="4">
          </el-input>
        </el-form-item>
      </el-form>
      
      <div slot="footer">
        <el-button @click="ccDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitCc">確定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
export default {
  props: {
    taskId: String,
    taskName: String
  },
  data() {
    return {
      ccDialogVisible: false,
      userList: [],
      ccForm: {
        userIds: [],
        content: ''
      }
    }
  },
  methods: {
    showCcDialog() {
      this.ccDialogVisible = true
      this.loadUserList()
    },
    
    async loadUserList() {
      const res = await this.$api.user.getUserList()
      this.userList = res.data
    },
    
    async submitCc() {
      const params = {
        taskId: this.taskId,
        toUserIds: this.ccForm.userIds,
        title: `任務【${this.taskName}】抄送`,
        content: this.ccForm.content
      }
      
      await this.$api.cc.create(params)
      this.$message.success('抄送成功')
      this.ccDialogVisible = false
      this.$emit('cc-success')
    }
  }
}
</script>

3.2、抄送列表頁面

<template>
  <div class="cc-task-list">
    <el-tabs v-model="activeStatus" @tab-click="handleTabClick">
      <el-tab-pane label="未讀" name="0"></el-tab-pane>
      <el-tab-pane label="已讀" name="1"></el-tab-pane>
      <el-tab-pane label="全部" name=""></el-tab-pane>
    </el-tabs>
    
    <el-table :data="ccList" v-loading="loading">
      <el-table-column prop="title" label="標題" width="200">
        <template slot-scope="{row}">
          <span :class="{'unread': row.status === 0}">
            {{ row.title }}
          </span>
        </template>
      </el-table-column>
      
      <el-table-column prop="content" label="內(nèi)容"></el-table-column>
      
      <el-table-column prop="fromUserName" label="發(fā)起人" width="100">
      </el-table-column>
      
      <el-table-column prop="createTime" label="時間" width="180">
        <template slot-scope="{row}">
          {{ formatDate(row.createTime) }}
        </template>
      </el-table-column>
      
      <el-table-column label="操作" width="120">
        <template slot-scope="{row}">
          <el-button 
            v-if="row.status === 0"
            type="text" 
            @click="markAsRead(row.id)">
            標記已讀
          </el-button>
          <el-button 
            type="text" 
            @click="viewProcess(row.procInstId)">
            查看流程
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="pagination.pageNum"
      :page-sizes="[10, 20, 50, 100]"
      :page-size="pagination.pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="pagination.total">
    </el-pagination>
  </div>
</template>

前端可以調(diào)用上述接口展示抄送列表,并允許用戶標記已讀。

注意事項

  • 抄送功能可以根據(jù)實際需求進行擴展,例如增加抄送類型(任務創(chuàng)建時抄送、任務完成時抄送等)。
  • 抄送人員可以從任務變量、流程變量、固定配置或者從用戶選擇中獲取。
  • 抄送任務可能不需要處理,但需要記錄,因此抄送表的設計可以根據(jù)業(yè)務需求調(diào)整。

4、高級功能擴展

4.1、郵件通知集成

@Component
public class EmailCcNotifier {
    
    @Autowired
    private JavaMailSender mailSender;
    
    @Value("${spring.mail.username}")
    private String from;
    
    public void sendCcNotification(CcTask ccTask, User user) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(user.getEmail());
        message.setSubject("工作流抄送通知:" + ccTask.getTitle());
        message.setText(buildEmailContent(ccTask));
        
        mailSender.send(message);
    }
    
    private String buildEmailContent(CcTask ccTask) {
        return String.format(
            "您收到一條工作流抄送:\n" +
            "標題:%s\n" +
            "內(nèi)容:%s\n" +
            "發(fā)起人:%s\n" +
            "時間:%s\n" +
            "請登錄系統(tǒng)查看詳情。",
            ccTask.getTitle(),
            ccTask.getContent(),
            ccTask.getFromUserId(),
            DateUtil.formatDateTime(ccTask.getCreateTime())
        );
    }
}

4.2、消息推送集成(WebSocket)

@ServerEndpoint("/websocket/cc")
@Component
public class CcWebSocket {
    
    private static Map<String, Session> sessions = new ConcurrentHashMap<>();
    
    @OnOpen
    public void onOpen(Session session) {
        String userId = getUserIdFromSession(session);
        sessions.put(userId, session);
    }
    
    /**
     * 向指定用戶推送抄送消息
     */
    public static void sendCcMessage(String userId, CcTask ccTask) {
        Session session = sessions.get(userId);
        if (session != null && session.isOpen()) {
            try {
                String message = JSON.toJSONString(
                    Map.of("type", "cc", "data", ccTask)
                );
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                log.error("發(fā)送WebSocket消息失敗", e);
            }
        }
    }
}

4.3、 抄送規(guī)則配置

@Component
public class CcRuleEngine {
    
    /**
     * 根據(jù)規(guī)則自動抄送
     * 規(guī)則示例:
     * 1. 特定節(jié)點自動抄送
     * 2. 金額大于閾值抄送
     * 3. 特定部門任務抄送
     */
    public List<String> getCcUsersByRule(
            String processDefinitionId, 
            String taskDefinitionKey,
            Map<String, Object> variables) {
        
        List<String> userIds = new ArrayList<>();
        
        // 示例:根據(jù)任務節(jié)點配置抄送
        if ("approve".equals(taskDefinitionKey)) {
            // 審批節(jié)點抄送給部門經(jīng)理
            String deptId = (String) variables.get("deptId");
            userIds.addAll(getDeptManagers(deptId));
        }
        
        // 示例:根據(jù)金額閾值抄送
        Double amount = (Double) variables.get("amount");
        if (amount != null && amount > 10000) {
            userIds.addAll(getFinanceUsers());
        }
        
        return userIds.stream().distinct().collect(Collectors.toList());
    }
}

4.4、 應用配置文件

# application.yml
activiti:
  cc:
    enabled: true
    # 是否啟用郵件通知
    email-notify: true
    # 是否啟用站內(nèi)信
    message-notify: true
    # 默認抄送人(角色)
    default-cc-roles: ROLE_DEPT_MANAGER,ROLE_ADMIN

4.5、 流程定義中的抄送配置

<!-- 在BPMN文件中添加抄送配置 -->
<userTask id="approveTask" name="審批任務">
  <extensionElements>
    <activiti:taskListener event="create" 
      class="com.xxx.listener.AutoCcTaskListener"/>
    <activiti:formProperty id="ccUsers" 
      name="抄送人" type="users"/>
  </extensionElements>
</userTask>

5、總結(jié)

抄送功能的實現(xiàn)要點:

  • 數(shù)據(jù)持久化:設計抄送表記錄抄送信息
  • 業(yè)務邏輯:提供抄送CRUD服務
  • 流程集成:通過監(jiān)聽器自動觸發(fā)抄送
  • 用戶通知:集成多種通知方式(站內(nèi)信、郵件、推送)
  • 權(quán)限控制:確保用戶只能操作自己的抄送記錄
  • 配置靈活:支持規(guī)則引擎和動態(tài)配置

這種實現(xiàn)方式既保持了工作流引擎的純凈性,又通過擴展實現(xiàn)了業(yè)務需要的抄送功能。

到此這篇關于SpringBoot整合Activiti的項目中實現(xiàn)抄送功能的文章就介紹到這了,更多相關SpringBoot Activiti抄送內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • WebUploader+SpringMVC實現(xiàn)文件上傳功能

    WebUploader+SpringMVC實現(xiàn)文件上傳功能

    WebUploader是由Baidu團隊開發(fā)的一個簡單的以HTML5為主,F(xiàn)LASH為輔的現(xiàn)代文件上傳組件。這篇文章主要介紹了WebUploader+SpringMVC實現(xiàn)文件上傳功能,需要的朋友可以參考下
    2017-06-06
  • SpringCloud Config使用本地倉庫及map注入

    SpringCloud Config使用本地倉庫及map注入

    這篇文章主要介紹了SpringCloud Config使用本地倉庫及map注入,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • 使用BigDecimal進行精確運算(實現(xiàn)加減乘除運算)

    使用BigDecimal進行精確運算(實現(xiàn)加減乘除運算)

    這篇文章主要介紹了如何使用BigDecimal進行精確運算,最后提供了一個工具類,該工具類提供加,減,乘,除運算
    2013-11-11
  • java防盜鏈在報表中的應用實例(推薦)

    java防盜鏈在報表中的應用實例(推薦)

    下面小編就為大家?guī)硪黄猨ava防盜鏈在報表中的應用實例(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • 淺談JVM之類的加載鏈接和初始化

    淺談JVM之類的加載鏈接和初始化

    有了java class文件之后,為了讓class文件轉(zhuǎn)換成為JVM可以真正運行的結(jié)構(gòu),需要經(jīng)歷加載,鏈接和初始化的過程。這三個過程是怎么工作的呢?在本文中你將會找到答案。
    2021-06-06
  • 基于Spring Security前后端分離的權(quán)限控制系統(tǒng)問題

    基于Spring Security前后端分離的權(quán)限控制系統(tǒng)問題

    本文給大家分享基于Spring Security前后端分離的權(quán)限控制系統(tǒng)問題,需要了解權(quán)限如何加載,權(quán)限匹配規(guī)則和登錄的實現(xiàn)代碼,對Spring Security權(quán)限控制系統(tǒng)相關知識感興趣的朋友一起看看吧
    2021-06-06
  • SpringMVC一步到位精通攔截器

    SpringMVC一步到位精通攔截器

    攔截器(Interceptor)是一種動態(tài)攔截方法調(diào)用的機制,在SpringMVC中動態(tài)攔截控制器方法的執(zhí)行。本文將詳細講講SpringMVC中攔截器的概念及入門案例,感興趣的可以嘗試一下
    2022-12-12
  • Reactor 多任務并發(fā)執(zhí)行且結(jié)果按順序返回第一個

    Reactor 多任務并發(fā)執(zhí)行且結(jié)果按順序返回第一個

    這篇文章主要介紹了Reactor 多任務并發(fā)執(zhí)行且結(jié)果按順序返回第一個,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下
    2022-09-09
  • 淺談Java8 判空新寫法

    淺談Java8 判空新寫法

    在開發(fā)過程中很多時候會遇到判空校驗,如果不做判空校驗則會產(chǎn)生NullPointerException異常,本文就來介紹一下Java8 判空新寫法,感興趣的可以了解一下
    2021-09-09
  • Java class文件格式之數(shù)據(jù)類型(二)_動力節(jié)點Java學院整理

    Java class文件格式之數(shù)據(jù)類型(二)_動力節(jié)點Java學院整理

    這篇文章主要介紹了Java class文件格式之數(shù)據(jù)類型(二)的相關資料,需要的朋友可以參考下
    2017-06-06

最新評論

美姑县| 运城市| 绍兴市| 灌云县| 凤庆县| 嘉义县| 本溪市| 图们市| 陆良县| 石渠县| 保山市| 离岛区| 元江| 滨州市| 沙洋县| 祁东县| 宜都市| 平昌县| 分宜县| 江都市| 紫阳县| 仲巴县| 武冈市| 辽宁省| 泸定县| 大城县| 什邡市| 临沂市| 桦甸市| 平远县| 辽中县| 余江县| 开阳县| 刚察县| 安庆市| 金沙县| 班戈县| 平罗县| 阜康市| 塘沽区| 长汀县|