3 Коміти 9ccb9e961b ... c6196fab63

Автор SHA1 Опис Дата
  王苗苗 c6196fab63 1.通过手机号返回大模型停水信息bug修改 2.新增查询客服接口 3.新增通过sessionId获取通话记录并关联创哥表的字段 4.更新通话记录,额外 1 тиждень тому
  王苗苗 9f94aa5d89 通话记录表新增sessionId 将曹永创和刘威余尚辉数据关联 1 тиждень тому
  王苗苗 96208de17b 新增tts相关接口测试 1 тиждень тому

+ 8 - 0
pom.xml

@@ -30,6 +30,7 @@
         <poi.version>4.1.2</poi.version>
         <velocity.version>2.3</velocity.version>
         <jwt.version>0.9.1</jwt.version>
+        <tts.version>3.7.1</tts.version>
     </properties>
 
     <!-- 依赖声明 -->
@@ -180,6 +181,13 @@
                 <version>${slibra.version}</version>
             </dependency>
 
+            <!-- 阿里云的tts -->
+            <dependency>
+                <groupId>com.aliyun</groupId>
+                <artifactId>aliyun-java-sdk-core</artifactId>
+                <version>${tts.version}</version>
+            </dependency>
+
         </dependencies>
     </dependencyManagement>
 

+ 180 - 0
slibra-admin/src/main/java/com/slibra/web/controller/business/FileTransJavaDemo.java

@@ -0,0 +1,180 @@
+package com.slibra.web.controller.business;
+
+import com.alibaba.fastjson.JSONObject;
+import com.aliyuncs.CommonRequest;
+import com.aliyuncs.CommonResponse;
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.http.MethodType;
+import com.aliyuncs.profile.DefaultProfile;
+public class FileTransJavaDemo {
+    // 地域ID,常量,固定值。
+    public static final String REGIONID = "cn-shanghai";
+    public static final String ENDPOINTNAME = "cn-shanghai";
+    public static final String PRODUCT = "nls-filetrans";
+    public static final String DOMAIN = "filetrans.cn-shanghai.aliyuncs.com";
+    public static final String API_VERSION = "2018-08-17";  // 中国站版本
+    // public static final String API_VERSION = "2019-08-23";  // 国际站版本
+    public static final String POST_REQUEST_ACTION = "SubmitTask";
+    public static final String GET_REQUEST_ACTION = "GetTaskResult";
+    // 请求参数
+    public static final String KEY_APP_KEY = "appkey";
+    public static final String KEY_FILE_LINK = "file_link";
+    public static final String KEY_VERSION = "version";
+    public static final String KEY_ENABLE_WORDS = "enable_words";
+    // 响应参数
+    public static final String KEY_TASK = "Task";
+    public static final String KEY_TASK_ID = "TaskId";
+    public static final String KEY_STATUS_TEXT = "StatusText";
+    public static final String KEY_RESULT = "Result";
+    // 状态值
+    public static final String STATUS_SUCCESS = "SUCCESS";
+    private static final String STATUS_RUNNING = "RUNNING";
+    private static final String STATUS_QUEUEING = "QUEUEING";
+    // 阿里云鉴权client
+    IAcsClient client;
+    public FileTransJavaDemo(String accessKeyId, String accessKeySecret) {
+        // 设置endpoint
+        try {
+            DefaultProfile.addEndpoint(ENDPOINTNAME, REGIONID, PRODUCT, DOMAIN);
+        } catch (ClientException e) {
+            e.printStackTrace();
+        }
+        // 创建DefaultAcsClient实例并初始化
+        DefaultProfile profile = DefaultProfile.getProfile(REGIONID, accessKeyId, accessKeySecret);
+        this.client = new DefaultAcsClient(profile);
+    }
+    public String submitFileTransRequest(String appKey, String fileLink) {
+        /**
+         * 1. 创建CommonRequest,设置请求参数。
+         */
+        CommonRequest postRequest = new CommonRequest();
+        // 设置域名
+        postRequest.setDomain(DOMAIN);
+        // 设置API的版本号,格式为YYYY-MM-DD。
+        postRequest.setVersion(API_VERSION);
+        // 设置action
+        postRequest.setAction(POST_REQUEST_ACTION);
+        // 设置产品名称
+        postRequest.setProduct(PRODUCT);
+        /**
+         * 2. 设置录音文件识别请求参数,以JSON字符串的格式设置到请求Body中。
+         */
+        JSONObject taskObject = new JSONObject();
+        // 设置appkey
+        taskObject.put(KEY_APP_KEY, appKey);
+        // 设置音频文件访问链接
+        taskObject.put(KEY_FILE_LINK, fileLink);
+        // 新接入请使用4.0版本,已接入(默认2.0)如需维持现状,请注释掉该参数设置。
+        taskObject.put(KEY_VERSION, "4.0");
+        // 设置是否输出词信息,默认为false,开启时需要设置version为4.0及以上。
+        taskObject.put(KEY_ENABLE_WORDS, true);
+        String task = taskObject.toJSONString();
+        System.out.println(task);
+        // 设置以上JSON字符串为Body参数。
+        postRequest.putBodyParameter(KEY_TASK, task);
+        // 设置为POST方式的请求。
+        postRequest.setMethod(MethodType.POST);
+        // postRequest.setHttpContentType(FormatType.JSON);    //当aliyun-java-sdk-core 版本为4.6.0及以上时,请取消该行注释
+        /**
+         * 3. 提交录音文件识别请求,获取录音文件识别请求任务的ID,以供识别结果查询使用。
+         */
+        String taskId = null;
+        try {
+            CommonResponse postResponse = client.getCommonResponse(postRequest);
+            System.err.println("提交录音文件识别请求的响应:" + postResponse.getData());
+            if (postResponse.getHttpStatus() == 200) {
+                JSONObject result = JSONObject.parseObject(postResponse.getData());
+                String statusText = result.getString(KEY_STATUS_TEXT);
+                if (STATUS_SUCCESS.equals(statusText)) {
+                    taskId = result.getString(KEY_TASK_ID);
+                }
+            }
+        } catch (ClientException e) {
+            e.printStackTrace();
+        }
+        return taskId;
+    }
+    public String getFileTransResult(String taskId) {
+        /**
+         * 1. 创建CommonRequest,设置任务ID。
+         */
+        CommonRequest getRequest = new CommonRequest();
+        // 设置域名
+        getRequest.setDomain(DOMAIN);
+        // 设置API版本
+        getRequest.setVersion(API_VERSION);
+        // 设置action
+        getRequest.setAction(GET_REQUEST_ACTION);
+        // 设置产品名称
+        getRequest.setProduct(PRODUCT);
+        // 设置任务ID为查询参数
+        getRequest.putQueryParameter(KEY_TASK_ID, taskId);
+        // 设置为GET方式的请求
+        getRequest.setMethod(MethodType.GET);
+        /**
+         * 2. 提交录音文件识别结果查询请求
+         * 以轮询的方式进行识别结果的查询,直到服务端返回的状态描述为“SUCCESS”或错误描述,则结束轮询。
+         */
+        String result = null;
+        while (true) {
+            try {
+                CommonResponse getResponse = client.getCommonResponse(getRequest);
+                System.err.println("识别查询结果:" + getResponse.getData());
+                if (getResponse.getHttpStatus() != 200) {
+                    break;
+                }
+                JSONObject rootObj = JSONObject.parseObject(getResponse.getData());
+                String statusText = rootObj.getString(KEY_STATUS_TEXT);
+                if (STATUS_RUNNING.equals(statusText) || STATUS_QUEUEING.equals(statusText)) {
+                    // 继续轮询,注意设置轮询时间间隔。
+                    Thread.sleep(10000);
+                }
+                else {
+                    // 状态信息为成功,返回识别结果;状态信息为异常,返回空。
+                    if (STATUS_SUCCESS.equals(statusText)) {
+                        result = rootObj.getString(KEY_RESULT);
+                        // 状态信息为成功,但没有识别结果,则可能是由于文件里全是静音、噪音等导致识别为空。
+                        if(result == null) {
+                            result = "";
+                        }
+                    }
+                    break;
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return result;
+    }
+    public static void main(String args[]) throws Exception {
+        //从环境变量获取配置的值
+        /*final String accessKeyId = System.getenv().get("ALIYUN_AK_ID");
+        final String accessKeySecret = System.getenv().get("ALIYUN_AK_SECRET");
+        final String appKey = System.getenv().get("NLS_APP_KEY");*/
+        final String accessKeyId = "LTAI5tQ2HmiHCygZkt5BYrYR";
+        final String accessKeySecret = "KhmxTd14SUcXafpFk5yofA43FoeM99";
+        final String appKey = "OKt6jogp6fRjHQVp";
+        String fileLink = "https://gw.alipayobjects.com/os/bmw-prod/0574ee2e-f494-45a5-820f-63aee583045a.wav";
+//        String fileLink = "https://www.w3school.com.cn/i/audio/song.mp3";
+        FileTransJavaDemo demo = new FileTransJavaDemo(accessKeyId, accessKeySecret);
+        // 第一步:提交录音文件识别请求,获取任务ID用于后续的识别结果轮询。
+        String taskId = demo.submitFileTransRequest(appKey, fileLink);
+        if (taskId != null) {
+            System.out.println("录音文件识别请求成功,task_id: " + taskId);
+        }
+        else {
+            System.out.println("录音文件识别请求失败!");
+            return;
+        }
+        // 第二步:根据任务ID轮询识别结果。
+        String result = demo.getFileTransResult(taskId);
+        if (result != null) {
+            System.out.println("录音文件识别结果查询成功:" + result);
+        }
+        else {
+            System.out.println("录音文件识别结果查询失败!");
+        }
+    }
+}

+ 22 - 0
slibra-admin/src/main/java/com/slibra/web/controller/business/TCallRecordController.java

@@ -1,7 +1,11 @@
 package com.slibra.web.controller.business;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import javax.servlet.http.HttpServletResponse;
+
+import com.slibra.common.core.domain.R;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -103,4 +107,22 @@ public class TCallRecordController extends BaseController
     {
         return toAjax(tCallRecordService.deleteTCallRecordByIds(ids));
     }
+
+
+    //2024年11月18日10:44:02  新增接口,通过sessionId返回对应的通话记录信息,并且关联曹永创的contents[当前通话记录]字段
+    @GetMapping(value = "/getCallBySessionId")
+    public R<TCallRecord> getCallBySessionId(String sessionId)
+    {
+        return R.ok(tCallRecordService.getCallBySessionId(sessionId));
+    }
+
+    /**
+     * 获取客服列表接口【只返回用户的ID和姓名】
+     * @return
+     */
+    @GetMapping(value = "/getAgentList")
+    public R<List<HashMap<String, Object>>> getAgentList()
+    {
+        return R.ok(tCallRecordService.getAgentList());
+    }
 }

+ 5 - 0
slibra-admin/src/main/resources/application.yml

@@ -240,3 +240,8 @@ big-model:
 
 log:
   logPath: /home/intelligent-voice/logs
+
+#tts配置
+ALIYUN_AK_ID: LTAI5tQ2HmiHCygZkt5BYrYR
+ALIYUN_AK_SECRET: KhmxTd14SUcXafpFk5yofA43FoeM99
+NLS_APP_KEY: OKt6jogp6fRjHQVp

+ 8 - 0
slibra-system/src/main/java/com/slibra/business/domain/TCallRecord.java

@@ -28,6 +28,10 @@ public class TCallRecord extends BaseEntity
     /** 主键 */
     private Long id;
 
+    /** sessionId */
+    @Excel(name = "sessionId")
+    private String sessionId;
+
     /** 呼入分类(0白名单 1AI服务 2传统服务) */
     @Excel(name = "呼入分类", readConverterExp = "0=白名单,1=AI服务,2=传统服务")
     private Long type;
@@ -92,4 +96,8 @@ public class TCallRecord extends BaseEntity
     @Excel(name = "乐观锁")
     private Long revision;
 
+
+    //2024年11月18日10:45:25 新增的返回的字段[当前通话记录]
+    private String currentCallRecords;
+
 }

+ 9 - 0
slibra-system/src/main/java/com/slibra/business/mapper/TCallRecordMapper.java

@@ -1,6 +1,9 @@
 package com.slibra.business.mapper;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+
 import com.slibra.business.domain.TCallRecord;
 
 /**
@@ -58,4 +61,10 @@ public interface TCallRecordMapper
      * @return 结果
      */
     public int deleteTCallRecordByIds(Long[] ids);
+
+    String getBusinessTypeBySessionId(String sessionId);
+
+    String getContentsBySessionId(String sessionId);
+
+    List<HashMap<String, Object>> getAgentList();
 }

+ 7 - 0
slibra-system/src/main/java/com/slibra/business/service/ITCallRecordService.java

@@ -1,6 +1,9 @@
 package com.slibra.business.service;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+
 import com.slibra.business.domain.TCallRecord;
 
 /**
@@ -58,4 +61,8 @@ public interface ITCallRecordService
      * @return 结果
      */
     public int deleteTCallRecordById(Long id);
+
+    TCallRecord getCallBySessionId(String sessionId);
+
+    List<HashMap<String, Object>> getAgentList();
 }

+ 6 - 1
slibra-system/src/main/java/com/slibra/business/service/impl/FrontServiceImpl.java

@@ -75,9 +75,14 @@ public class FrontServiceImpl implements IFrontService {
         if(BusinessEnum.AiChatReqEnum.water_info.getCode().equals(method)){
 //            return this.cutOffWaterMapper.getCutOffWaterByUserPhone(phone);
             //通过手机号获取对应的小区的名字,一个手机号只能查询到一个
+            //2024年11月18日10:21:42 因为TUserInfo存储的主要是户号相关信息,所以一个手机号是可以对应多条记录的
             List<TUserInfo> tUserInfos = this.userInfoMapper.selectTUserInfoList(TUserInfo.builder().phone(phone).build());
             if(!CollectionUtils.isEmpty(tUserInfos)){
-                return this.cutOffWaterMapper.getCutOffWaterByNeighbourhoodName(tUserInfos.get(0).getNeighbourhoodName());
+                List<TCutOffWater> cutOffWaters = new ArrayList<>();
+                for (TUserInfo tUserInfo : tUserInfos) {
+                    cutOffWaters.addAll(this.cutOffWaterMapper.getCutOffWaterByNeighbourhoodName(tUserInfo.getNeighbourhoodName()));
+                }
+                return cutOffWaters;
             }
         }
         //基于用户输入的小区信息,查询停水信息

+ 41 - 0
slibra-system/src/main/java/com/slibra/business/service/impl/TCallRecordServiceImpl.java

@@ -1,12 +1,22 @@
 package com.slibra.business.service.impl;
 
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+
+import com.slibra.common.exception.ServiceException;
 import com.slibra.common.utils.DateUtils;
+import com.slibra.common.utils.SecurityUtils;
+import com.slibra.common.utils.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.slibra.business.mapper.TCallRecordMapper;
 import com.slibra.business.domain.TCallRecord;
 import com.slibra.business.service.ITCallRecordService;
+import org.springframework.util.CollectionUtils;
 
 /**
  * 通话记录Service业务层处理
@@ -17,6 +27,7 @@ import com.slibra.business.service.ITCallRecordService;
 @Service
 public class TCallRecordServiceImpl implements ITCallRecordService 
 {
+    private static final Logger log = LoggerFactory.getLogger(TCallRecordServiceImpl.class);
     @Autowired
     private TCallRecordMapper tCallRecordMapper;
 
@@ -67,6 +78,19 @@ public class TCallRecordServiceImpl implements ITCallRecordService
     public int updateTCallRecord(TCallRecord tCallRecord)
     {
         tCallRecord.setUpdateTime(DateUtils.getNowDate());
+        //2024年11月18日10:23:18 由于前端不方便穿ID和name,这里由后台来操作
+        try {
+            tCallRecord.setUserId(SecurityUtils.getUserId());
+            tCallRecord.setUserName(SecurityUtils.getUsername());
+        } catch (Exception e) {
+            log.error("××××××跟新通话记录的时候,获取用户信息失败!");
+        }
+        //额外再查询曹永创的botrecords表,通过session获取intent,更新【业务类型】字段
+        String sessionId = tCallRecord.getSessionId();
+        if(StringUtils.isBlank(sessionId))
+            log.error("更新通话记录的时候,由于获取不到sessionId,导致无法更新曹永创的字段bussinessType【业务类型】");
+        else
+            tCallRecord.setBussinessType(this.tCallRecordMapper.getBusinessTypeBySessionId(sessionId));
         return tCallRecordMapper.updateTCallRecord(tCallRecord);
     }
 
@@ -93,4 +117,21 @@ public class TCallRecordServiceImpl implements ITCallRecordService
     {
         return tCallRecordMapper.deleteTCallRecordById(id);
     }
+
+    @Override
+    public TCallRecord getCallBySessionId(String sessionId) {
+        if(StringUtils.isBlank(sessionId))
+            throw new ServiceException("请输入sessionId");
+        List<TCallRecord> tCallRecords = this.tCallRecordMapper.selectTCallRecordList(TCallRecord.builder().sessionId(sessionId).build());
+        if(!CollectionUtils.isEmpty(tCallRecords)){
+            TCallRecord tCallRecord = tCallRecords.get(0);
+            tCallRecord.setCurrentCallRecords(this.tCallRecordMapper.getContentsBySessionId(sessionId));//[当前通话记录]
+        }
+        return null;
+    }
+
+    @Override
+    public List<HashMap<String, Object>> getAgentList() {
+        return this.tCallRecordMapper.getAgentList();
+    }
 }

+ 41 - 4
slibra-system/src/main/resources/mapper/business/TCallRecordMapper.xml

@@ -3,9 +3,10 @@
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.slibra.business.mapper.TCallRecordMapper">
-    
+
     <resultMap type="TCallRecord" id="TCallRecordResult">
         <result property="id"    column="id"    />
+        <result property="sessionId"    column="session_id"    />
         <result property="type"    column="type"    />
         <result property="userId"    column="user_id"    />
         <result property="userName"    column="user_name"    />
@@ -30,7 +31,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 
     <sql id="selectTCallRecordVo">
-        select id, type, user_id, user_name, service_category, time_begin, time_end, times, category, status, phone, bussiness_type, url, remark, has_parsed, parsed_voice_content, del_flag, revision, create_by, create_time, update_by, update_time from t_call_record
+        select id, session_id, type, user_id, user_name, service_category, time_begin, time_end, times, category, status, phone, bussiness_type, url, remark, has_parsed, parsed_voice_content, del_flag, revision, create_by, create_time, update_by, update_time from t_call_record
     </sql>
 
 
@@ -38,10 +39,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectTCallRecordVo"/>
         where id = #{id} and del_flag = 0
     </select>
-        
+
     <insert id="insertTCallRecord" parameterType="TCallRecord" useGeneratedKeys="true" keyProperty="id">
         insert into t_call_record
         <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="sessionId != null">session_id,</if>
             <if test="type != null">type,</if>
             <if test="userId != null">user_id,</if>
             <if test="userName != null">user_name,</if>
@@ -65,6 +67,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="updateTime != null">update_time,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="sessionId != null">#{sessionId},</if>
             <if test="type != null">#{type},</if>
             <if test="userId != null">#{userId},</if>
             <if test="userName != null">#{userName},</if>
@@ -92,6 +95,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <update id="updateTCallRecord" parameterType="TCallRecord">
         update t_call_record
         <trim prefix="SET" suffixOverrides=",">
+            <if test="sessionId != null">session_id = #{sessionId},</if>
             <if test="type != null">type = #{type},</if>
             <if test="userId != null">user_id = #{userId},</if>
             <if test="userName != null">user_name = #{userName},</if>
@@ -118,7 +122,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         where id = #{id}
     </update>
 
-    
+
 
     <delete id="deleteTCallRecordById" parameterType="Long">
         update t_call_record set del_flag = 2,revision = revision + 1 where del_flag = 0 and id = #{id}
@@ -136,6 +140,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectTCallRecordVo"/>
         <where>
             1 = 1
+            <if test="sessionId != null  and sessionId != ''"> and session_id = #{sessionId}</if>
             <if test="type != null "> and type = #{type}</if>
             <if test="userId != null "> and user_id = #{userId}</if>
             <if test="userName != null  and userName != ''"> and user_name like concat('%', #{userName}, '%')</if>
@@ -153,4 +158,36 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
         and del_flag = 0 order by id desc
     </select>
+
+
+    <select id="getBusinessTypeBySessionId" resultType="string">
+        SELECT
+            intent
+        FROM
+            botrecords
+        WHERE
+            `session` = #{sessionId}
+            LIMIT 1
+    </select>
+
+    <select id="getContentsBySessionId" resultType="string">
+        SELECT
+            contents
+        FROM
+            botrecords
+        WHERE
+            `session` = #{sessionId}
+            LIMIT 1
+    </select>
+
+    <select id="getAgentList" resultType="java.util.HashMap">
+        SELECT
+            user_id id,
+            user_name `name`
+        FROM
+            sys_user
+        WHERE
+            agent_num IS NOT NULL
+          AND agent_num != ''
+    </select>
 </mapper>