Преглед изворни кода

AI工作流,销售端绑定声音

lk пре 2 недеља
родитељ
комит
47c724a225

+ 96 - 0
fs-company/src/main/java/com/fs/company/controller/company/CompanyAiWorkflowController.java

@@ -0,0 +1,96 @@
+package com.fs.company.controller.company;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.utils.ServletUtils;
+import com.fs.framework.security.LoginUser;
+import com.fs.framework.service.TokenService;
+import com.fs.his.domain.FsAiWorkflow;
+import com.fs.his.domain.FsAiWorkflowNode;
+import com.fs.his.service.IFsAiWorkflowService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 企业AI工作流Controller
+ *
+ * @author fs
+ * @date 2026-01-09
+ */
+@RestController
+@RequestMapping("/company/aiWorkflow")
+public class CompanyAiWorkflowController extends BaseController {
+
+    @Autowired
+    private IFsAiWorkflowService fsAiWorkflowService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 分页查询AI工作流列表
+     */
+    @GetMapping("/list")
+    public TableDataInfo list(FsAiWorkflow fsAiWorkflow) {
+        startPage();
+        List<FsAiWorkflow> list = fsAiWorkflowService.selectFsAiWorkflowList(fsAiWorkflow);
+        return getDataTable(list);
+    }
+
+    /**
+     * 根据企业用户ID获取工作流的关键节点
+     * 节点类型: start(开始), end(结束), ai_chat(AI对话)
+     */
+    @GetMapping("/nodes/{companyUserId}")
+    public R getWorkflowNodes(@PathVariable("companyUserId") Long companyUserId) {
+        // 定义要查询的节点类型
+        List<String> nodeTypes = Arrays.asList("start", "end", "ai_chat");
+        List<FsAiWorkflowNode> nodes = fsAiWorkflowService.selectWorkflowNodesByCompanyUserId(companyUserId, nodeTypes);
+        return R.ok().put("data", nodes);
+    }
+
+    /**
+     * 获取当前登录企业用户的工作流关键节点
+     * 节点类型: start(开始), end(结束), ai_chat(AI对话)
+     */
+    @GetMapping("/myNodes")
+    public R getMyWorkflowNodes() {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if (loginUser == null || loginUser.getUser() == null) {
+            return R.error("用户信息错误");
+        }
+        Long companyUserId = loginUser.getUser().getUserId();
+        List<String> nodeTypes = Arrays.asList("start", "end", "ai_chat");
+        List<FsAiWorkflowNode> nodes = fsAiWorkflowService.selectWorkflowNodesByCompanyUserId(companyUserId, nodeTypes);
+        return R.ok().put("data", nodes);
+    }
+
+    /**
+     * 更新节点的语音URL
+     * @param nodeId 节点ID
+     * @param voiceUrl 语音URL
+     */
+    @PutMapping("/node/voiceUrl")
+    public R updateNodeVoiceUrl(@RequestParam("nodeId") Long nodeId,
+                                @RequestParam("voiceUrl") String voiceUrl) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if (loginUser == null || loginUser.getUser() == null) {
+            return R.error("用户信息错误");
+        }
+        Long companyUserId = loginUser.getUser().getUserId();
+
+        int result = fsAiWorkflowService.updateNodeVoiceUrl(nodeId, voiceUrl, companyUserId);
+        if (result == -1) {
+            return R.error("节点不存在");
+        } else if (result == -2) {
+            return R.error("无权限修改该节点");
+        } else if (result > 0) {
+            return R.ok("更新成功");
+        }
+        return R.error("更新失败");
+    }
+}

+ 3 - 0
fs-service/src/main/java/com/fs/his/domain/FsAiWorkflow.java

@@ -41,4 +41,7 @@ public class FsAiWorkflow extends BaseEntity {
 
     /** 删除标志 0正常 1删除 */
     private Integer delFlag;
+
+    /** 企业用户ID */
+    private Long companyUserId;
 }

+ 5 - 0
fs-service/src/main/java/com/fs/his/mapper/FsAiWorkflowMapper.java

@@ -15,6 +15,11 @@ public interface FsAiWorkflowMapper {
 
     List<FsAiWorkflow> selectFsAiWorkflowList(FsAiWorkflow fsAiWorkflow);
 
+    /**
+     * 根据企业用户ID查询工作流列表
+     */
+    List<FsAiWorkflow> selectFsAiWorkflowByCompanyUserId(Long companyUserId);
+
     int insertFsAiWorkflow(FsAiWorkflow fsAiWorkflow);
 
     int updateFsAiWorkflow(FsAiWorkflow fsAiWorkflow);

+ 8 - 0
fs-service/src/main/java/com/fs/his/mapper/FsAiWorkflowNodeMapper.java

@@ -1,6 +1,8 @@
 package com.fs.his.mapper;
 
 import com.fs.his.domain.FsAiWorkflowNode;
+import org.apache.ibatis.annotations.Param;
+
 import java.util.List;
 
 /**
@@ -15,6 +17,12 @@ public interface FsAiWorkflowNodeMapper {
 
     List<FsAiWorkflowNode> selectFsAiWorkflowNodeByWorkflowId(Long workflowId);
 
+    /**
+     * 根据工作流ID和节点类型列表查询节点
+     */
+    List<FsAiWorkflowNode> selectNodesByWorkflowIdAndTypes(@Param("workflowId") Long workflowId,
+                                                           @Param("nodeTypes") List<String> nodeTypes);
+
     int insertFsAiWorkflowNode(FsAiWorkflowNode node);
 
     int batchInsertFsAiWorkflowNode(List<FsAiWorkflowNode> nodes);

+ 18 - 0
fs-service/src/main/java/com/fs/his/service/IFsAiWorkflowService.java

@@ -1,6 +1,7 @@
 package com.fs.his.service;
 
 import com.fs.his.domain.FsAiWorkflow;
+import com.fs.his.domain.FsAiWorkflowNode;
 import com.fs.his.domain.FsAiWorkflowNodeType;
 import com.fs.his.param.FsAiWorkflowSaveParam;
 import com.fs.his.vo.FsAiWorkflowExportVO;
@@ -54,4 +55,21 @@ public interface IFsAiWorkflowService {
      * 导出工作流JSON(包含节点、连接顺序、节点类型)
      */
     FsAiWorkflowExportVO exportWorkflowJson(Long workflowId);
+
+    /**
+     * 根据企业用户ID查询工作流的指定类型节点
+     * @param companyUserId 企业用户ID
+     * @param nodeTypes 节点类型列表(如: start, end, ai_chat)
+     * @return 节点列表
+     */
+    List<FsAiWorkflowNode> selectWorkflowNodesByCompanyUserId(Long companyUserId, List<String> nodeTypes);
+
+    /**
+     * 更新节点的voiceUrl
+     * @param nodeId 节点ID
+     * @param voiceUrl 语音URL
+     * @param companyUserId 企业用户ID(用于校验归属)
+     * @return 1成功 0失败 -1节点不存在 -2无权限
+     */
+    int updateNodeVoiceUrl(Long nodeId, String voiceUrl, Long companyUserId);
 }

+ 46 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsAiWorkflowServiceImpl.java

@@ -253,4 +253,50 @@ public class FsAiWorkflowServiceImpl implements IFsAiWorkflowService {
             default: return "";
         }
     }
+
+    @Override
+    public List<FsAiWorkflowNode> selectWorkflowNodesByCompanyUserId(Long companyUserId, List<String> nodeTypes) {
+        // 根据企业用户ID查询工作流
+        List<FsAiWorkflow> workflows = fsAiWorkflowMapper.selectFsAiWorkflowByCompanyUserId(companyUserId);
+        if (workflows == null || workflows.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        // 收集所有工作流的指定类型节点
+        List<FsAiWorkflowNode> result = new ArrayList<>();
+        for (FsAiWorkflow workflow : workflows) {
+            List<FsAiWorkflowNode> nodes = fsAiWorkflowNodeMapper.selectNodesByWorkflowIdAndTypes(
+                    workflow.getWorkflowId(), nodeTypes);
+            if (nodes != null) {
+                result.addAll(nodes);
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public int updateNodeVoiceUrl(Long nodeId, String voiceUrl, Long companyUserId) {
+        // 1. 查询节点是否存在
+        FsAiWorkflowNode node = fsAiWorkflowNodeMapper.selectFsAiWorkflowNodeById(nodeId);
+        if (node == null) {
+            return -1; // 节点不存在
+        }
+
+        // 2. 查询节点所属的工作流
+        FsAiWorkflow workflow = fsAiWorkflowMapper.selectFsAiWorkflowById(node.getWorkflowId());
+        if (workflow == null) {
+            return -1; // 工作流不存在
+        }
+
+        // 3. 校验工作流是否属于该企业用户
+        if (workflow.getCompanyUserId() == null || !workflow.getCompanyUserId().equals(companyUserId)) {
+            return -2; // 无权限
+        }
+
+        // 4. 更新voiceUrl
+        FsAiWorkflowNode updateNode = new FsAiWorkflowNode();
+        updateNode.setNodeId(nodeId);
+        updateNode.setVoiceUrl(voiceUrl);
+        return fsAiWorkflowNodeMapper.updateFsAiWorkflowNode(updateNode);
+    }
 }

+ 11 - 1
fs-service/src/main/resources/mapper/his/FsAiWorkflowMapper.xml

@@ -16,11 +16,12 @@
         <result property="updateTime" column="update_time"/>
         <result property="remark" column="remark"/>
         <result property="delFlag" column="del_flag"/>
+        <result property="companyUserId" column="company_user_id"/>
     </resultMap>
 
     <sql id="selectFsAiWorkflowVo">
         select workflow_id, workflow_name, workflow_desc, workflow_type, status, version,
-               canvas_data, create_by, create_time, update_by, update_time, remark, del_flag
+               canvas_data, create_by, create_time, update_by, update_time, remark, del_flag, company_user_id
         from fs_ai_workflow
     </sql>
 
@@ -33,6 +34,7 @@
             </if>
             <if test="workflowType != null">and workflow_type = #{workflowType}</if>
             <if test="status != null">and status = #{status}</if>
+            <if test="companyUserId != null">and company_user_id = #{companyUserId}</if>
         </where>
         order by create_time desc
     </select>
@@ -42,6 +44,12 @@
         where workflow_id = #{workflowId} and del_flag = 0
     </select>
 
+    <select id="selectFsAiWorkflowByCompanyUserId" parameterType="Long" resultMap="FsAiWorkflowResult">
+        <include refid="selectFsAiWorkflowVo"/>
+        where company_user_id = #{companyUserId} and del_flag = 0 and status = 1
+        order by create_time desc
+    </select>
+
     <insert id="insertFsAiWorkflow" parameterType="FsAiWorkflow" useGeneratedKeys="true" keyProperty="workflowId">
         insert into fs_ai_workflow
         <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -54,6 +62,7 @@
             <if test="createBy != null">create_by,</if>
             <if test="createTime != null">create_time,</if>
             <if test="remark != null">remark,</if>
+            <if test="companyUserId != null">company_user_id,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="workflowName != null and workflowName != ''">#{workflowName},</if>
@@ -65,6 +74,7 @@
             <if test="createBy != null">#{createBy},</if>
             <if test="createTime != null">#{createTime},</if>
             <if test="remark != null">#{remark},</if>
+            <if test="companyUserId != null">#{companyUserId},</if>
         </trim>
     </insert>
 

+ 12 - 0
fs-service/src/main/resources/mapper/his/FsAiWorkflowNodeMapper.xml

@@ -18,6 +18,7 @@
         <result property="sortOrder" column="sort_order"/>
         <result property="createTime" column="create_time"/>
         <result property="updateTime" column="update_time"/>
+        <result property="voiceUrl" column="voice_url"/>
     </resultMap>
 
     <select id="selectFsAiWorkflowNodeById" parameterType="Long" resultMap="FsAiWorkflowNodeResult">
@@ -28,6 +29,16 @@
         select * from fs_ai_workflow_node where workflow_id = #{workflowId} order by sort_order
     </select>
 
+    <select id="selectNodesByWorkflowIdAndTypes" resultMap="FsAiWorkflowNodeResult">
+        select * from fs_ai_workflow_node
+        where workflow_id = #{workflowId}
+        and node_type in
+        <foreach collection="nodeTypes" item="nodeType" open="(" separator="," close=")">
+            #{nodeType}
+        </foreach>
+        order by sort_order
+    </select>
+
     <insert id="insertFsAiWorkflowNode" parameterType="FsAiWorkflowNode" useGeneratedKeys="true" keyProperty="nodeId">
         insert into fs_ai_workflow_node (workflow_id, node_key, node_name, node_type, node_icon, node_color,
             pos_x, pos_y, width, height, node_config, sort_order, create_time)
@@ -58,6 +69,7 @@
             <if test="height != null">height = #{height},</if>
             <if test="nodeConfig != null">node_config = #{nodeConfig},</if>
             <if test="sortOrder != null">sort_order = #{sortOrder},</if>
+            <if test="voiceUrl != null">voice_url = #{voiceUrl},</if>
             update_time = now(),
         </trim>
         where node_id = #{nodeId}