Commit a28664c7 authored by chenhao's avatar chenhao

Merge branch 'developer' of http://172.16.10.76/moa/amos-boot-biz into developer

parents 2828b1ad 49f3d7e2
......@@ -7,6 +7,7 @@
rs.mrid,
rs.`name`,
rs.parent_mrid,
rs.risk_level_mrid,
IFNULL(rs.rpn, 0) rpn,
IFNULL(rs.rpni, 0) rpni
FROM `asf_fire_risk_source` rs
......
package com.yeejoin.amos.boot.module.jcs.api.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author litw
* @date 2021-11-26.
*/
@Data
public class AlertCallCommandDto {
@ApiModelProperty(value = "名称")
String name;
@ApiModelProperty(value = "职务")
String duty;
}
......@@ -113,4 +113,7 @@ public class AlertCalledDto extends BaseDto{
private String systemSource;
@ApiModelProperty(value = "系统来源code")
private String systemSourceCode;
@ApiModelProperty(value = "处置记录url")
private String recordUrl;
}
package com.yeejoin.amos.boot.module.jcs.api.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* @author ltw
* @date 2021-11-25.
*/
@Data
public class AlertCalledMobDto {
@ApiModelProperty(value = "力量调派")
List<AlertCalledPowerInfoDto> alertCalledPowerInfoDtoList;
@ApiModelProperty(value = "指挥力量")
List<AlertCallCommandDto> alertCallCommandDtoList;
@ApiModelProperty(value = "年度")
String year;
@ApiModelProperty(value = "灾害单位")
String unit;
@ApiModelProperty(value = "详细地址")
String address;
@ApiModelProperty(value = "警情类型")
String alertType;
@ApiModelProperty(value = "来源类型")
String sourceType;
@ApiModelProperty(value = "报警人姓名")
String reportName;
@ApiModelProperty(value = "联系电话")
String conectPhone;
@ApiModelProperty(value = "接警时间")
String callTime;
@ApiModelProperty(value = "出动时间")
String toTime;
@ApiModelProperty(value = "到场时间")
String arriveTime;
@ApiModelProperty(value = "控制时间")
String controlTime;
@ApiModelProperty(value = "结束时间")
String endTime;
}
package com.yeejoin.amos.boot.module.jcs.api.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author litw
* @date 2021-11-25.
*/
@Data
public class AlertCalledPowerInfoDto {
@ApiModelProperty(value = "队站")
String station;
@ApiModelProperty(value = "到场时间")
String arriveTime;
@ApiModelProperty(value = "车辆名称")
String carName;
@ApiModelProperty(value = "参战人数")
String personNum;
@ApiModelProperty(value = "水")
String water;
@ApiModelProperty(value = "泡沫")
String foam;
@ApiModelProperty(value = "干粉")
String dryPowder;
@ApiModelProperty(value = "其他")
String other;
@ApiModelProperty(value = "第一次出动调派车辆数量")
String disatchNum;
}
......@@ -64,4 +64,13 @@ public class AlertCalledZhDto {
@ApiModelProperty(value = "警情修改时间")
private Date updateTime;
@ApiModelProperty(value = "处置记录url")
private String recordUrl;
/**
* 警情状态
*/
@ApiModelProperty(value = "警情状态")
private Boolean alertStatus;
}
package com.yeejoin.amos.boot.module.jcs.api.dto;
import com.yeejoin.amos.component.rule.Label;
import com.yeejoin.amos.component.rule.RuleFact;
import lombok.Data;
import java.io.Serializable;
import java.util.Map;
/**
* @ProjectName: EquipManageRoot
* @Package: com.yeejoin.equipmanage.common.vo
* @ClassName: ConfirmAlamVo
* @Author: Jianqiang Gao
* @Description: ConfirmAlamVo
* @Date: 2021/9/16 11:31
* @Version: 1.0
*/
@Data
@RuleFact(value = "确警消息",project = "消息规则")
public class IotSystemAlarmRo implements Serializable {
private static final long serialVersionUID = -8807644006700780121L;
@Label(value = "物联警情id")
private Long id;
@Label(value = "联系人")
private String contactUser;
@Label(value = "联系人电话")
private String contactPhone;
@Label(value = "事发单位")
private String unitInvolvedId;
@Label(value = "事发单位名称")
private String unitInvolvedName;
@Label(value = "建筑经度")
private Double longitude;
@Label(value = "建筑纬度")
private Double latitude;
@Label(value = "地址")
private String address;
@Label(value = "火灾地址")
private String fireLocation;
@Label(value = "楼经度")
private Double floorLongitude;
@Label(value = "楼纬度")
private Double floorLatitude;
@Label(value = "发送到web标识")
private Boolean isSendWeb;
@Label("关联id")
private String relationId;
@Label("消息类型")
private String msgType;
@Label(value = "终端标识")
private String terminal;
@Label(value = "类别")
private Integer category;
@Label(value = "扩展参数")
private Map<String, String> extras;
}
\ No newline at end of file
......@@ -104,7 +104,8 @@ public class AlertCalled extends BaseEntity {
@ApiModelProperty(value = "备注信息")
private String remark;
@ApiModelProperty(value = "处置记录url")
private String recordUrl;
......
......@@ -2,10 +2,10 @@ package com.yeejoin.amos.boot.module.jcs.api.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yeejoin.amos.boot.module.jcs.api.dto.AlertSubmittedDto;
import com.yeejoin.amos.boot.module.jcs.api.dto.AlertSubmittedZHDto;
import com.yeejoin.amos.boot.module.jcs.api.entity.AlertSubmitted;
import com.yeejoin.amos.boot.module.jcs.api.dto.AlertSubmittedExtDto;
import com.yeejoin.amos.boot.module.jcs.api.dto.AlertSubmittedSMSDto;
import com.yeejoin.amos.boot.module.jcs.api.dto.AlertSubmittedZHDto;
import com.yeejoin.amos.boot.module.jcs.api.entity.AlertSubmitted;
import org.apache.ibatis.annotations.Param;
import java.util.List;
......@@ -57,4 +57,9 @@ public interface AlertSubmittedMapper extends BaseMapper<AlertSubmitted> {
Map<String, Integer> getUseNum(@Param("id") Long id);
List<Map<String, Object>> getFirst(@Param("alertId") Long alertId);
List<Map<String, Object>> getOther(@Param("alertId") Long alertId);
}
......@@ -16,8 +16,6 @@ import java.util.List;
*/
public interface IVoiceRecordFileService {
void publishRecord(VoiceRecordFileDto model);
Page<VoiceRecordFileDto> queryRecordListByQueryDto(Page<VoiceRecordFileDto> page, String telEndTimeStr, String telEndTimeStr1, String fileType, String caller, String called, String sortParam, String sortRule);
VoiceRecordFileDto getRecordById(Long sequenceNbr);
......@@ -27,4 +25,6 @@ public interface IVoiceRecordFileService {
List<FusionDto> getCarList(Boolean hasFusion);
List<FusionDto> getSinglePawnList(Boolean hasFusion);
List <VoiceRecordFileDto> listByAlertId(Long alertId);
}
......@@ -34,6 +34,8 @@
a.address ,
a.coordinate_x longitude,
a.coordinate_y latitude,
a.record_url,
a.alert_status,
CASE a.response_level_code
WHEN '1164' THEN '紧急出动'
WHEN '1165' THEN '紧急集结'
......
......@@ -131,6 +131,40 @@
a.alert_called_id = ${id}
</select>
<select id="getFirst" resultType="Map">
SELECT distinct
a.rec_date recDate ,
b.company_name companyName,
c.resources_name carName,
c.resources_num carNum,
c.resources_id id
FROM
jc_power_transfer a
LEFT JOIN jc_power_transfer_company b ON a.sequence_nbr = b.power_transfer_id
LEFT JOIN jc_power_transfer_company_resources c ON c.power_transfer_company_id = b.sequence_nbr
where a.sequence_nbr = (select sequence_nbr from jc_power_transfer where alert_called_id
= #{alertId}
order by rec_date asc limit 1)
</select>
<select id="getOther" resultType="Map">
SELECT distinct
a.rec_date recDate ,
b.company_name companyName,
c.resources_name carName,
c.resources_num carNum,
c.resources_id id
FROM
jc_power_transfer a
LEFT JOIN jc_power_transfer_company b ON a.sequence_nbr = b.power_transfer_id
LEFT JOIN jc_power_transfer_company_resources c ON c.power_transfer_company_id = b.sequence_nbr
where a.sequence_nbr = (select sequence_nbr from jc_power_transfer where alert_called_id
= #{alertId}
order by rec_date asc limit 1,100)
</select>
......
......@@ -16,6 +16,9 @@ public class CheckReportDangerDto implements Serializable {
String companyName;
@ApiModelProperty(value = "隐患id")
String id;
@ApiModelProperty(value = "隐患id")
String dangerId;
@ApiModelProperty(value = "存在问题")
......
......@@ -3,7 +3,6 @@ package com.yeejoin.amos.boot.module.command.biz.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
......@@ -19,7 +18,6 @@ import com.yeejoin.amos.boot.module.command.api.dto.CarTaskDto;
import com.yeejoin.amos.boot.module.command.api.dto.SeismometeorologyDto;
import com.yeejoin.amos.boot.module.command.biz.service.impl.RemoteSecurityService;
import com.yeejoin.amos.boot.module.common.api.dto.*;
import com.yeejoin.amos.boot.module.common.api.dto.FireBrigadeResourceDto;
import com.yeejoin.amos.boot.module.common.api.entity.FireTeam;
import com.yeejoin.amos.boot.module.common.api.feign.EquipFeignClient;
import com.yeejoin.amos.boot.module.common.api.feign.IotFeignClient;
......@@ -49,15 +47,13 @@ import com.yeejoin.amos.boot.module.jcs.api.service.*;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.enumeration.UserType;
import org.typroject.tyboot.core.foundation.exception.BaseException;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.foundation.utils.DateUtil;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.restful.doc.TycloudOperation;
......@@ -74,7 +70,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* *指挥资源Api
......
......@@ -175,6 +175,7 @@ public class ContingencyPlanController extends AbstractBaseController {
}
}
@TycloudOperation(ApiLevel = UserType.AGENCY)
@ApiOperation(value = "启动")
@RequestMapping(value = "/start", method = RequestMethod.POST)
public ResponseModel start(@RequestBody ContingencyPlanParamVo vo) {
......@@ -196,6 +197,7 @@ public class ContingencyPlanController extends AbstractBaseController {
return CommonResponseUtil2.success(result);
}
@TycloudOperation(ApiLevel = UserType.AGENCY)
@ApiOperation(value = "装备确景")
@RequestMapping(value = "/scene", method = RequestMethod.GET)
public ResponseModel scene(@ApiParam(value = "装备Id", required = true) String equipmentId,
......@@ -208,6 +210,7 @@ public class ContingencyPlanController extends AbstractBaseController {
}
}
@TycloudOperation(ApiLevel = UserType.AGENCY)
@ApiOperation(value = "预案启动记录分页列表")
@RequestMapping(value = "/record/page", method = RequestMethod.GET)
public ResponseModel recordList(
......@@ -229,6 +232,7 @@ public class ContingencyPlanController extends AbstractBaseController {
return CommonResponseUtil2.success(contingencyPlanService.recordListByPage(page, planId, planName, classifyId, startTimeLeft, startTimeRight, executionType, planPattern));
}
@TycloudOperation(ApiLevel = UserType.AGENCY)
@ApiOperation(value = "第一次查看预案记录")
@RequestMapping(value = "/frist/getRecord/{batchNo}", method = RequestMethod.GET)
public ResponseModel firstGetRecord( @PathVariable(value = "batchNo") String batchNo) {
......@@ -236,6 +240,7 @@ public class ContingencyPlanController extends AbstractBaseController {
return CommonResponseUtil2.success(map);
}
@TycloudOperation(ApiLevel = UserType.AGENCY)
@ApiOperation(value = "查看预案记录列表")
@RequestMapping(value = "/getRecordList/{batchNo}", method = RequestMethod.GET)
public ResponseModel getRecordList( @PathVariable(value = "batchNo") String batchNo) {
......
......@@ -20,6 +20,31 @@
<artifactId>amos-boot-module-common-biz</artifactId>
<version>${amos-biz-boot.version}</version>
</dependency>
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.6.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>poi-ooxml</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
<exclusion>
<artifactId>poi-ooxml-schemas</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
<exclusion>
<artifactId>poi</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc</artifactId>
<version>4.9.0</version>
</dependency>
</dependencies>
</project>
......@@ -9,6 +9,7 @@ import com.yeejoin.amos.boot.biz.common.controller.BaseController;
import com.yeejoin.amos.boot.biz.common.service.impl.DataDictionaryServiceImpl;
import com.yeejoin.amos.boot.biz.common.utils.DateUtils;
import com.yeejoin.amos.boot.biz.common.utils.NameUtils;
import com.yeejoin.amos.boot.module.jcs.api.dto.AlertCalledFormDto;
import com.yeejoin.amos.boot.module.jcs.api.dto.AlertCalledObjsDto;
import com.yeejoin.amos.boot.module.jcs.api.dto.AlertCalledRo;
import com.yeejoin.amos.boot.module.jcs.api.dto.AlertSubmittedDto;
......@@ -39,6 +40,9 @@ import org.typroject.tyboot.core.restful.doc.TycloudOperation;
import org.typroject.tyboot.core.restful.utils.ResponseHelper;
import org.typroject.tyboot.core.restful.utils.ResponseModel;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -258,6 +262,29 @@ public class AlertSubmittedController extends BaseController {
return ResponseHelper.buildResponse(schedulingContent);
}
/**
* 获取警情续报内容
*
* @return 返回结果
*/
@TycloudOperation(ApiLevel = UserType.AGENCY)
@RequestMapping(value = "/alert_submitted/ddd", method = RequestMethod.GET)
@ApiOperation(httpMethod = "GET", value = "获取警情续报内容和模板", notes = "获取警情续报内容和模板")
public ResponseModel<Object> getAlertSubmittedContentDD() {
try {
AlertCalledFormDto alertCalledFormDto = (AlertCalledFormDto)alertCalledService.selectAlertCalledByIdNoRedis(1455815417061728258L);
alertSubmittedService.generateMob(alertCalledFormDto.getAlertCalled());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
return ResponseHelper.buildResponse(null);
}
private String getTaskInformation(String content, Map<String, String> definitions) {
int size = definitions.size();
String[] keys = definitions.keySet().toArray(new String[size]);
......
package com.yeejoin.amos.boot.module.jcs.biz.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.controller.BaseController;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.module.jcs.api.dto.VoiceRecordFileDto;
import com.yeejoin.amos.boot.module.jcs.api.entity.VoiceRecordFile;
import com.yeejoin.amos.boot.module.jcs.biz.service.impl.AlertCalledServiceImpl;
import com.yeejoin.amos.boot.module.jcs.biz.service.impl.VoiceRecordFileServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.typroject.tyboot.core.foundation.enumeration.UserType;
......@@ -20,7 +17,6 @@ import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseHelper;
import org.typroject.tyboot.core.restful.utils.ResponseModel;
import java.util.ArrayList;
import java.util.List;
/**
......@@ -35,7 +31,7 @@ import java.util.List;
public class VoiceRecordFileController extends BaseController {
@Autowired
VoiceRecordFileServiceImpl voiceRecordFileServiceImpl;
VoiceRecordFileServiceImpl voiceRecordFileService;
@Autowired
AlertCalledServiceImpl iAlertCalledService;
......@@ -49,18 +45,7 @@ public class VoiceRecordFileController extends BaseController {
@ApiOperation(httpMethod = "GET",value = "根据警情id 查找通话记录信息", notes = "根据警情id 查找通话记录信息")
@GetMapping(value = "/list/alert/{alertId}")
public ResponseModel<List<VoiceRecordFileDto>> selectForListByAlertId(@PathVariable Long alertId) {
LambdaQueryWrapper<VoiceRecordFile> queryWrapper = new LambdaQueryWrapper<VoiceRecordFile>();
queryWrapper.eq(VoiceRecordFile::getAlertId, alertId).orderByDesc(VoiceRecordFile::getRecDate);
List<VoiceRecordFile> list = voiceRecordFileServiceImpl.list(queryWrapper);
List<VoiceRecordFileDto> dtoList = new ArrayList<VoiceRecordFileDto>(list.size());
list.stream().forEach(voiceRecord -> {
// 创建新的对象实例
VoiceRecordFileDto target = new VoiceRecordFileDto();
// 把原对象数据拷贝到新对象
BeanUtils.copyProperties(voiceRecord, target);
dtoList.add(target);
});
return ResponseHelper.buildResponse(dtoList);
return ResponseHelper.buildResponse(voiceRecordFileService.listByAlertId(alertId));
}
/**
......@@ -73,7 +58,7 @@ public class VoiceRecordFileController extends BaseController {
@GetMapping(value = "/{sequenceNbr}")
public ResponseModel<VoiceRecordFileDto> getRecordById(@PathVariable Long sequenceNbr) {
VoiceRecordFileDto record = voiceRecordFileServiceImpl.getRecordById(sequenceNbr);
VoiceRecordFileDto record = voiceRecordFileService.getRecordById(sequenceNbr);
return ResponseHelper.buildResponse(record);
}
......@@ -85,13 +70,22 @@ public class VoiceRecordFileController extends BaseController {
@TycloudOperation(ApiLevel = UserType.AGENCY)
@PostMapping(value = "/saveRecord")
@ApiOperation(httpMethod = "POST", value = "新增通话记录附件", notes = "新增通话记录附件")
public ResponseModel<Boolean> saveRecord(@RequestBody VoiceRecordFileDto model) {
public ResponseModel<VoiceRecordFileDto> saveRecord(@RequestBody VoiceRecordFileDto model) {
if (ValidationUtil.isEmpty(model.getCaller())
|| ValidationUtil.isEmpty(model.getCalled())){
throw new BadRequest("参数校验失败.");
}
voiceRecordFileServiceImpl.publishRecord(model);
return ResponseHelper.buildResponse(true);
return ResponseHelper.buildResponse(voiceRecordFileService.saveRecord(model));
}
@TycloudOperation(ApiLevel = UserType.AGENCY)
@RequestMapping(value = "/{sequenceNbr}", method = RequestMethod.PUT)
@ApiOperation(httpMethod = "PUT", value = "更新通话记录附件", notes = "更新通话记录附件")
public ResponseModel<VoiceRecordFileDto> updateRecord(
@RequestBody VoiceRecordFileDto model,
@PathVariable(value = "sequenceNbr") Long sequenceNbr) {
model.setSequenceNbr(sequenceNbr);
return ResponseHelper.buildResponse(voiceRecordFileService.updateRecord(model));
}
@TycloudOperation(ApiLevel = UserType.AGENCY)
......@@ -117,7 +111,7 @@ public class VoiceRecordFileController extends BaseController {
sortParam = "call_time";
sortRule = "desc";
}
Page<VoiceRecordFileDto> pageBean = voiceRecordFileServiceImpl.queryRecordListByQueryDto(page,
Page<VoiceRecordFileDto> pageBean = voiceRecordFileService.queryRecordListByQueryDto(page,
model.getTelStartTimeStr(),model.getTelEndTimeStr(),model.getFileType(),model.getCaller(),
model.getCalled(),sortParam,sortRule);
Page<VoiceRecordFileDto> result = new Page<VoiceRecordFileDto>(pageNum,pageSize);
......
......@@ -2,6 +2,7 @@ package com.yeejoin.amos.boot.module.jcs.biz.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.module.common.api.feign.EquipFeignClient;
import com.yeejoin.amos.boot.module.jcs.api.dto.FusionDto;
......@@ -24,6 +25,7 @@ import org.springframework.util.Assert;
import org.typroject.tyboot.component.emq.EmqKeeper;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.DataNotFound;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -77,28 +79,25 @@ public class VoiceRecordFileServiceImpl extends BaseService<VoiceRecordFileDto,
return this.queryForList("", false);
}
@Override
public void publishRecord(final VoiceRecordFileDto model) {
public VoiceRecordFileDto saveRecord(final VoiceRecordFileDto model) {
Map<String, String> dMap = fusionService.getCallRecordByNumber(model.getCaller(), model.getCalled());
// 保存到日志表中
VoiceRecordLog log = new VoiceRecordLog();
VoiceRecordFile voiceRecordFile = new VoiceRecordFile();
BeanUtils.copyProperties(model, voiceRecordFile);
log.setAlertId(model.getAlertId());
String cid = dMap.get("cid");
Assert.notNull(cid, "CID不能为空");
Map<String, String> callRecord = fusionService.getCallRecordByCID(cid);
voiceRecordFile.setConnectId(cid);
model.setConnectId(cid);
log.setConnectId(cid);
log.setIsDeal(false);
log.setDealTimes(0);
if (!ValidationUtil.isEmpty(callRecord)){
voiceRecordFile.setFilePath(String.format("/%s/%s", callRecord.get("subPath"), callRecord.get("recordName").replace("wav", "mp3")));
if (!ValidationUtil.isEmpty(callRecord)) {
model.setFilePath(String.format("/%s/%s", callRecord.get("subPath"), callRecord.get("recordName").replace("wav", "mp3")));
logger.info(String.format("音频地址:【%s】", String.format("/%s/%s", callRecord.get("subPath"), callRecord.get("recordName"))));
} else { // 无录音地址记录日志
iVoiceRecordLogServiceImpl.save(log);
}
save(voiceRecordFile);
return this.createWithModel(model);
}
@Override
......@@ -118,9 +117,7 @@ public class VoiceRecordFileServiceImpl extends BaseService<VoiceRecordFileDto,
@Override
public VoiceRecordFileDto getRecordById(Long sequenceNbr) {
VoiceRecordFileDto record = baseMapper.getRecordById(sequenceNbr);
Map<String, String> callRecord = fusionService.getCallRecordByCID(record.getConnectId());
record.setFilePath(String.format("/%s/%s", callRecord.get("subPath"), callRecord.get("recordName")));
return record;
return buildFilePath(record);
}
@Override
......@@ -169,6 +166,31 @@ public class VoiceRecordFileServiceImpl extends BaseService<VoiceRecordFileDto,
return fusionDtos;
}
@Override
public List<VoiceRecordFileDto> listByAlertId(Long alertId) {
LambdaQueryWrapper<VoiceRecordFile> queryWrapper = new LambdaQueryWrapper<VoiceRecordFile>();
queryWrapper.eq(VoiceRecordFile::getAlertId, alertId).orderByDesc(VoiceRecordFile::getRecDate);
List<VoiceRecordFile> list = voiceRecordFileServiceImpl.list(queryWrapper);
List<VoiceRecordFileDto> dtoList = new ArrayList<>();
list.stream().forEach(voiceRecord -> {
// 创建新的对象实例
VoiceRecordFileDto target = new VoiceRecordFileDto();
// 把原对象数据拷贝到新对象
BeanUtils.copyProperties(voiceRecord, target);
buildFilePath(target);
dtoList.add(target);
});
return dtoList;
}
public VoiceRecordFileDto updateRecord(VoiceRecordFileDto model) {
VoiceRecordFileDto oldModel = this.queryBySeq(model.getSequenceNbr());
if (ValidationUtil.isEmpty(oldModel))
throw new DataNotFound("找不到指定的数据.");
oldModel.setAlertId(model.getAlertId());
return this.updateWithModel(oldModel);
}
/**
* 获取在线用户的employeeID集合
*
......@@ -176,7 +198,7 @@ public class VoiceRecordFileServiceImpl extends BaseService<VoiceRecordFileDto,
*/
private List<String> getAllOnlineUser(Boolean hasFusion) {
List<String> employeeIDs = new ArrayList<>();
if (hasFusion){
if (hasFusion) {
JSONObject jsonObject = fusionService.getAllOnlineUser();
if (!ValidationUtil.isEmpty(jsonObject)) {
JSONArray onlines = jsonObject.getJSONArray("Onlines");
......@@ -189,12 +211,12 @@ public class VoiceRecordFileServiceImpl extends BaseService<VoiceRecordFileDto,
return employeeIDs;
}
private FusionDto buildFusionDtoAndId(FusionDto fusionDto, List<String> employeeIDs, Boolean hasFusion, Map map){
private FusionDto buildFusionDtoAndId(FusionDto fusionDto, List<String> employeeIDs, Boolean hasFusion, Map map) {
List carPropertyList = (List) map.get("carPropertyList");
carPropertyList.forEach(carProperty -> {
Map carPropertyMap = (Map) carProperty;
Object nameKey = carPropertyMap.get("nameKey");
if (hasFusion && PropertyEnum.GIS.getValue().equals(nameKey)){
if (hasFusion && PropertyEnum.GIS.getValue().equals(nameKey)) {
fusionDto.setId(String.valueOf(carPropertyMap.get("value")));
} else if (!hasFusion && PropertyEnum.VIDEO.getValue().equals(nameKey)) {
fusionDto.setId(String.valueOf(carPropertyMap.get("value")));
......@@ -213,4 +235,10 @@ public class VoiceRecordFileServiceImpl extends BaseService<VoiceRecordFileDto,
}
return fusionDto;
}
private VoiceRecordFileDto buildFilePath(VoiceRecordFileDto record) {
Map<String, String> callRecord = fusionService.getCallRecordByCID(record.getConnectId());
record.setFilePath(String.format("/%s/%s", callRecord.get("subPath"), callRecord.get("recordName")));
return record;
}
}
\ No newline at end of file
......@@ -95,7 +95,7 @@ public class CheckReportController extends BaseController {
@TycloudOperation(ApiLevel = UserType.AGENCY)
@ApiOperation(value = "获取检查报告文档", notes = "获取检查报告文档")
@GetMapping(value = "/docx/{id}")
public ResponseModel getCheckReportDocx(HttpServletResponse response, @PathVariable(name = "id") String reportId) throws Exception {
return ResponseHelper.buildResponse(iCheckReportService.getCheckReportDocx(response, reportId));
public void getCheckReportDocx(HttpServletResponse response, @PathVariable(name = "id") String reportId) throws Exception {
iCheckReportService.getCheckReportDocx(response, reportId);
}
}
......@@ -231,8 +231,8 @@ public class CheckReportServiceImpl extends BaseService<CheckReportDto, CheckRep
// 复查已整改隐患
List<CheckReportDangerDto> reviewReformedList = result.get("reviewReformedList");
Set<String> reviewDangerIdSet = Sets.newHashSet();
reviewDangerIdSet.addAll(Lists.transform(reviewDangerList, CheckReportDangerDto::getDangerId));
reviewDangerIdSet.addAll(Lists.transform(reviewReformedList, CheckReportDangerDto::getDangerId));
reviewDangerIdSet.addAll(Lists.transform(reviewDangerList, CheckReportDangerDto::getId));
reviewDangerIdSet.addAll(Lists.transform(reviewReformedList, CheckReportDangerDto::getId));
// 保存本次复查隐患id
checkReport.setReviewDangerIds(Joiner.on(",").join(reviewDangerIdSet));
// List<CheckReportDangerDto> reviewReformingList = result.get("reviewReformingList");
......@@ -290,7 +290,8 @@ public class CheckReportServiceImpl extends BaseService<CheckReportDto, CheckRep
}
@Override
public Object getCheckReportDocx(HttpServletResponse response, String reportId) throws ParseException, UnsupportedEncodingException {
public void getCheckReportDocx(HttpServletResponse response, String reportId) throws ParseException,
UnsupportedEncodingException {
CheckReportDto report = this.getDetailById(reportId);
report.setReportDate(getCheckReportDateStr(report));
report.setNowDate(DateUtils.dateFormat(new Date(), DateUtils.CHN_DATE_PATTERN));
......@@ -305,7 +306,7 @@ public class CheckReportServiceImpl extends BaseService<CheckReportDto, CheckRep
configureBuilder.setElMode(ELMode.SPEL_MODE).bind("checkDangerList", checkDangerTablePolicy).bind("reviewDangerList", reviewDangerTablePolicy).build();
XWPFTemplate template = XWPFTemplate.compile(checkReportTemplatePath, configureBuilder.build()).render(report);
response.setContentType("application/msword");
response.setHeader("Content-disposition",
response.setHeader("Content-Disposition",
"attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
OutputStream out = null;
BufferedOutputStream bos = null;
......@@ -328,7 +329,6 @@ public class CheckReportServiceImpl extends BaseService<CheckReportDto, CheckRep
}
}
}
return null;
}
private String getCheckReportDateStr(CheckReportDto checkReportDto) throws ParseException {
......@@ -394,23 +394,24 @@ public class CheckReportServiceImpl extends BaseService<CheckReportDto, CheckRep
report.getCompanyName(), report.getDangerName(), report.getDangerStateName(), report.getCompanyId());
checkDangerList.add(rowRenderData);
}));
generateTableData(table, checkDangerList);
// companyId字段在RowRenderData中下标(0开始,companyName:1,dangerName:2,dangerStateName:3,companyId:4)
generateTableData(table, checkDangerList, 4);
}
}
public static void generateTableData(XWPFTable table, List<RowRenderData> dangerList) {
public static void generateTableData(XWPFTable table, List<RowRenderData> dangerList, int bizIndex) {
if (!ValidationUtil.isEmpty(dangerList)) {
// 表格渲染和列表数据下标相反,需要翻转一下列表
List<RowRenderData> reverseList = Lists.reverse(dangerList);
table.removeRow(dangerListDataStartRow);
int lastRow = dangerListDataStartRow;
String sameCompanyId =
dangerList.get(0).getCellDatas().get(4).getRenderData().getText();
dangerList.get(0).getCellDatas().get(bizIndex).getRenderData().getText();
List<Map<String, Integer>> mergeRowMapList = Lists.newArrayList();
// 循环插入行
int listLength = dangerList.size();
for (int i = 0; i < listLength; i++) {
String companyId = dangerList.get(i).getCellDatas().get(4).getRenderData().getText();
String companyId = dangerList.get(i).getCellDatas().get(bizIndex).getRenderData().getText();
reverseList.get(i).getCellDatas().get(0).getRenderData().setText(String.valueOf(listLength - i));
reverseList.get(i).getCellDatas().forEach(cellRenderData -> {
Style style = new Style();
......@@ -419,10 +420,12 @@ public class CheckReportServiceImpl extends BaseService<CheckReportDto, CheckRep
cellRenderData.getRenderData().setStyle(style);
});
XWPFTableRow insertNewTableRow = table.insertNewTableRow(dangerListDataStartRow);
IntStream.range(0, 4).forEach(j -> insertNewTableRow.createCell());
// 生成表格字段个数 (不包含companyId字段)
int cellLength = reverseList.get(i).getCellDatas().size() - 1;
IntStream.range(0, cellLength).forEach(j -> insertNewTableRow.createCell());
if (!sameCompanyId.equals(companyId)) {
sameCompanyId = dangerList.get(i).getCellDatas().get(4).getRenderData().getText();
sameCompanyId = dangerList.get(i).getCellDatas().get(bizIndex).getRenderData().getText();
Map<String, Integer> mergeRowMap = Maps.newHashMap();
mergeRowMap.put("fromRow", lastRow);
mergeRowMap.put("toRow", i + dangerListDataStartRow - 1);
......@@ -464,7 +467,8 @@ public class CheckReportServiceImpl extends BaseService<CheckReportDto, CheckRep
report.getRemark(), report.getCompanyId());
reviewDangerList.add(rowRenderData);
}));
generateTableData(table, reviewDangerList);
// companyId字段在RowRenderData中下标(0开始,companyName:1,dangerName:2,dangerStateName:3,remark:4,companyId:5)
generateTableData(table, reviewDangerList, 5);
}
}
......
......@@ -38,5 +38,5 @@ public interface ICheckReportService {
* @param reportId
* @return
*/
Object getCheckReportDocx(HttpServletResponse response, String reportId) throws Exception;
void getCheckReportDocx(HttpServletResponse response, String reportId) throws Exception;
}
......@@ -2298,5 +2298,17 @@
</sql>
</changeSet> -->
<changeSet author="litw" id="2021-11-29-1">
<preConditions onFail="MARK_RAN">
<not>
<columnExists tableName="jc_alert_called" columnName="record_url"/>
</not>
</preConditions>
<comment>update data jc_alert_called</comment>
<sql>
ALTER TABLE jc_alert_called ADD record_url varchar(200) null COMMENT '处置记录URL';
</sql>
</changeSet>
</databaseChangeLog>
......@@ -627,6 +627,7 @@
LEFT JOIN p_input_item pii ON pii.id = ppii.input_item_id
WHERE prp.point_id = #{pointId}
AND prp.route_id =#{routeId}
AND NOT FIND_IN_SET(prpi.point_input_item_id,prp.exclude_items)
ORDER BY
prpi.order_no
......
......@@ -71,8 +71,10 @@
p_point_inputitem pi
LEFT JOIN p_input_item ii ON ii.id = pi.input_item_id
LEFT JOIN p_point_classify pc ON FIND_IN_SET(pc.id, pi.classify_ids) > 0
LEFT JOIN p_route_point prp ON prp.point_id = pi.point_id
WHERE
pi.point_id = #{pointId}
AND NOT FIND_IN_SET(pi.id,prp.exclude_items)
ORDER BY
pi.order_no
</select>
......@@ -1088,27 +1090,21 @@
<select id="queryItemList4RoutePoint" parameterType="long" resultType="map">
SELECT
pii.id itemId
, pii.name
, pii.picture_json photo
, pii.basis_json basis
, pii.check_method method
, pii.item_type type
, pii.level
, pii.risk_desc
, pii.input_classify
ppi.id itemId,
pii.name,
pii.picture_json photo,
pii.basis_json basis,
pii.check_method method,
pii.item_type type,
pii.level,
pii.risk_desc,
pii.input_classify
FROM
p_input_item pii
p_point_inputitem ppi
LEFT JOIN p_input_item pii ON pii.id = ppi.input_item_id
WHERE
pii.id IN (
SELECT
DISTINCT ppi.input_item_id
FROM
p_point_inputitem ppi
WHERE
ppi.point_id = #{pointId}
AND ppi.classify_ids = #{classifyId}
)
ppi.point_id = #{pointId}
AND ppi.classify_ids = #{classifyId}
</select>
<select id="getPointRefItem" parameterType="list" resultType="map">
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>amos-boot-utils</artifactId>
<groupId>com.amosframework.boot</groupId>
<version>1.0.0</version>
</parent>
<artifactId>amos-boot-utils-speech</artifactId>
<dependencies>
<dependency>
<groupId>com.amosframework.boot</groupId>
<artifactId>amos-boot-core</artifactId>
<version>${amos-biz-boot.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>3.7.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.nls</groupId>
<artifactId>nls-sdk-transcriber</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
package com.yeejoin.amos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpeechApplication {
public static void main(String[] args) {
SpringApplication.run(SpeechApplication.class, args);
}
}
\ No newline at end of file
package com.yeejoin.amos.speech;
import com.alibaba.nls.client.AccessToken;
import com.alibaba.nls.client.protocol.NlsClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
/**
* 阿里云nlsClient语音识别客户端
* 应用全局创建一个NlsClient实例,默认服务地址为阿里云线上服务地址,默认值:wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1
*/
public class AppNslClient {
private static final Logger logger = LoggerFactory.getLogger(AppNslClientToken.class);
private volatile static NlsClient nlsClient;
private AppNslClient() {
}
public static NlsClient instance() {
if (nlsClient == null) {
synchronized (NlsClient.class) {
if (nlsClient == null) {
logger.warn("AppNslClient语音识别客户端为空,开始创建...");
nlsClient = new NlsClient(AppNslClientToken.instance().getToken());
return nlsClient;
}
}
}
//设置访问token
nlsClient.setToken(AppNslClientToken.instance().getToken());
return nlsClient;
}
}
/**
* AppNslClientToken
*/
class AppNslClientToken {
private static final Logger logger = LoggerFactory.getLogger(AppNslClientToken.class);
private volatile static AccessToken accessToken;
private static long getTokenTime;
private AppNslClientToken() {
}
public static AccessToken instance() {
if (accessToken == null) {
synchronized (NlsClient.class) {
if (accessToken == null) {
logger.warn("token为空,开始获取token...");
accessToken = getAccessToken();
getTokenTime = System.currentTimeMillis();
}
}
}
//token过期自更新
if (getTokenTime + accessToken.getExpireTime() <= System.currentTimeMillis()) {
logger.warn("token已过期,开始重新获取...");
accessToken = getAccessToken();
getTokenTime = System.currentTimeMillis();
} else {
long time = getTokenTime + accessToken.getExpireTime() - System.currentTimeMillis();
logger.warn("token过期还剩:" + "(" + time / (1000 * 60 * 60 * 24) + "天)");
}
return accessToken;
}
/**
* 获取访问Token,包含token和过期时间(2021-11-30测试Token过期时间为18天)
* 集成项目中,token放到缓存中,避免多次获取可能导致已进行的任务token失效
*
* @return token 访问token
*/
private static AccessToken getAccessToken() {
AccessToken accessToken = new AccessToken(SpeechConfig.AccessKeId, SpeechConfig.AccessKeySecret);
try {
accessToken.apply();
logger.warn("获取到最新的token: " + accessToken.getToken() + ", 过期时间: " + accessToken.getExpireTime() + "(" + accessToken.getExpireTime() / (1000 * 60 * 60 * 24) + "天)");
return accessToken;
} catch (IOException e) {
logger.error("获取语音识别客户端token失败!原因:" + e.getMessage());
throw new RuntimeException("获取语音识别客户端token失败!原因:" + e.getMessage());
}
}
}
package com.yeejoin.amos.speech;
import okhttp3.*;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* okHttp客户端
*/
public class AppOkHttpClient {
static OkHttpClient client = new OkHttpClient
.Builder()
.connectTimeout(20, TimeUnit.SECONDS)
.readTimeout(120, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.build();
/**
* okHttp post提交文件请求
*
* @param url 请求地址
* @param headers 请求头
* @param speechFile 待识别文件
* @param callback 识别回调函数
*/
public static void sendPostFile(String url, HashMap<String, String> headers, File speechFile, Callback callback) {
RequestBody body = RequestBody.create(MediaType.parse("application/octet-stream"), speechFile);
Headers.Builder hb = new Headers.Builder();
if (headers != null && !headers.isEmpty()) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
hb.add(entry.getKey(), entry.getValue());
}
}
Request request = new Request.Builder()
.url(url)
.headers(hb.build())
.post(body)
.build();
client.newCall(request).enqueue(callback);
}
}
\ No newline at end of file
package com.yeejoin.amos.speech;
/**
* 阿里云语音识别
* <p>
* 试用版
* <p>
* 自2020年03月01日起,免费试用版规则调整为如下内容:
* 试用版不计费,如有变化,请关注官网通知。
* 一句话识别、实时语音识别、语音合成每自然日内支持2个并发调用,每自然日用量不限,免费试用期限为三个月。
* 录音文件识别每自然日识别时长不超过2小时,免费试用期限为三个月。
* 长文本语音合成和录音文件识别极速版均不支持试用版,如需使用请开通商用版本。
* <p>
* 商用版
* <p>
* 2019年06月10日零时后自动调整为如上新规计费方式。
* 对于录音文件识别,若您需要超过2个小时或更长的接口使用时长,请开通商用版。
* 开通商用版默认为后付费方式。购买预付费资源包后,自动变更为预付费方式,并优先使用资源包内资源进行抵扣,当预付费资源包内资源使用完后,会再次变更为后付费方式。
* 商用版按每自然日使用量计费,无免费额度,不使用则不产生费用。北京时间每日24时,系统将自动对当日用量进行全量计算并计费,账单生成将稍有延迟。
* 开通商用版后,不建议再次降配为试用版。商用版降配试用版后,可用并发数将置为0,服务将无法继续使用。
*/
public class SpeechConfig {
/**
* 测试信息,可在阿里云上配置
*/
public static final String AccessKeId = "LTAI5t7mGN6dYoCwMdKiLTgt";
public static final String AccessKeySecret = "0LYdEnvKzQxBg0lpIahDp5rzB2r4Dp";
public static final String AppKey = "EG5fJBBIqkNMj6bM";
}
package com.yeejoin.amos.speech;
import okhttp3.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.HashMap;
/**
* 不支持免费用户测试
* 录音文件识别极速版(支持提交音频文件识别,文件大小,文件时长有限制)
* <p>
* 音频格式:支持AAC/MP3/OPUS/WAV格式编码的音频。
* 使用限制:支持100 MB以内且不超过2小时的音频文件的识别。
*
* @see SpeechRecognizer
* 时长超过2小时的文件请使用录音文件识别普通版
*
* <p>
* 模型类型:8000(电话)/16000(非电话)。
* <p>
* 同步返回识别结果
*/
public class SpeechFlashRecognizer {
private static final Logger logger = LoggerFactory.getLogger(SpeechFlashRecognizer.class);
//音频文件
private final File speechFile;
//音频格式
private final String format;
//音频采样率
private final int sampleRate;
//识别回调函数
private final Callback callback;
public SpeechFlashRecognizer(File speechFile, int sampleRate, Callback callback) {
if (speechFile == null || !speechFile.exists() || !speechFile.isFile()) {
throw new IllegalArgumentException("待识别的文件存在异常");
}
if (sampleRate == 0) {
throw new IllegalArgumentException("音频采样率不能为0");
}
String[] split = speechFile.getName().split("\\.");
if (split.length != 0) {
this.format = split[split.length - 1];
} else {
throw new IllegalArgumentException("音频文件格式提取失败");
}
this.speechFile = speechFile;
this.sampleRate = sampleRate;
this.callback = callback;
}
/**
* 设置HTTPS REST POST请求
* 1.使用http协议
* 2.语音识别服务域名:nls-gateway.cn-shanghai.aliyuncs.com
* 3.语音识别接口请求路径:/stream/v1/FlashRecognizer
* 4.设置必须请求参数:appkey、token、format、sample_rate
* 5.Content-Type 类型必须为 application/octet-stream
*/
public void process() {
String request = "https://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/FlashRecognizer";
request = request + "?appkey=" + SpeechConfig.AppKey;
request = request + "&token=" + AppNslClientToken.instance().getToken();
request = request + "&format=" + format;
request = request + "&sample_rate=" + sampleRate;
logger.info("Request: " + request);
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/octet-stream");
AppOkHttpClient.sendPostFile(request, headers, this.speechFile, this.callback);
}
}
package com.yeejoin.amos.speech;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
/**
* 不支持提交文件
* 录音文件识别普通版(提供外网访问的音频文件地址)
* <p>
* 识别的文件需要提交基于HTTP可访问的URL地址,可以通过URL访问,不支持提交本地文件
* 上传的录音文件URL的访问权限需要设置为公开,URL中只能使用域名不能使用IP地址、不可包含空格
*
* @see SpeechFlashRecognizer
* (内网考虑使用录音文件识别极速版,极速版可以提交文件识别,但极速版不提供试用)
* <p>
* 支持单轨/双轨的.wav、.mp3、.m4a、.wma、.aac、.ogg、.amr、.flac格式录音文件识别
* 文件大小需控制在512 MB以下
* 免费用户每日可识别不超过2小时时长的录音文件
* 提交录音文件识别请求后,免费用户的识别任务在24小时内完成并返回识别文本; 付费用户的识别任务在6小时内完成并返回识别文本。识别结果在服务端可保存72小时
*/
@Deprecated
public class SpeechRecognizer {
// 地域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 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;
private static final Logger logger = LoggerFactory.getLogger(SpeechRecognizer.class);
public SpeechRecognizer() {
// 设置endpoint
try {
DefaultProfile.addEndpoint(ENDPOINTNAME, REGIONID, PRODUCT, DOMAIN);
} catch (ClientException e) {
e.printStackTrace();
}
// 创建DefaultAcsClient实例并初始化
DefaultProfile profile = DefaultProfile.getProfile(REGIONID, SpeechConfig.AccessKeId, SpeechConfig.AccessKeySecret);
this.client = new DefaultAcsClient(profile);
}
/**
* 提交录音文件地址
*/
public String submitFileTransRequest(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, SpeechConfig.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();
logger.info(task);
// 设置以上JSON字符串为Body参数。
postRequest.putBodyParameter(KEY_TASK, task);
// 设置为POST方式的请求。
postRequest.setMethod(MethodType.POST);
/**
* 3. 提交录音文件识别请求,获取录音文件识别请求任务的ID,以供识别结果查询使用。
*/
String taskId = null;
try {
CommonResponse postResponse = client.getCommonResponse(postRequest);
logger.warn("提交录音文件识别请求的响应:" + 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;
}
/**
* 根据任务ID轮询识别结果
*/
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);
logger.warn("识别查询结果:" + 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)) {
// 继续轮询,注意设置轮询时间间隔。
TimeUnit.SECONDS.sleep(3);
} else {
// 状态信息为成功,返回识别结果;状态信息为异常,返回空。
if (STATUS_SUCCESS.equals(statusText)) {
result = rootObj.getString(KEY_RESULT);
// 状态信息为成功,但没有识别结果,则可能是由于文件里全是静音、噪音等导致识别为空。
if (result == null) {
result = "";
}
}
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
}
package com.yeejoin.amos.speech;
import com.alibaba.nls.client.protocol.InputFormatEnum;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriberListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.TimeUnit;
/**
* 实时语音识别
* <p>
* 支持的输入格式:PCM(无压缩的PCM或WAV文件)、16 bit采样位数、单声道(mono)。
* 支持的音频采样率:8000 Hz和16000 Hz。
*/
public class SpeechTranscriber {
private static final Logger logger = LoggerFactory.getLogger(SpeechTranscriber.class);
//语音识别文件
private final File speechFile;
//识别回调函数
private final SpeechTranscriberListener listener;
public SpeechTranscriber(File speechFile, SpeechTranscriberListener listener) {
if (speechFile != null && speechFile.exists() && speechFile.isFile()) {
this.speechFile = speechFile;
this.listener = listener;
} else {
throw new IllegalArgumentException("待识别的文件存在异常");
}
}
/**
* 开始语音识别
*/
public void process() {
com.alibaba.nls.client.protocol.asr.SpeechTranscriber transcriber = null;
try {
//创建实例、建立连接。
transcriber = new com.alibaba.nls.client.protocol.asr.SpeechTranscriber(AppNslClient.instance(), listener);
transcriber.setAppKey(SpeechConfig.AppKey);
//输入音频编码方式。
transcriber.setFormat(InputFormatEnum.PCM);
//输入音频采样率。
transcriber.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
//是否返回中间识别结果。
transcriber.setEnableIntermediateResult(true);
//是否生成并返回标点符号。
transcriber.setEnablePunctuation(true);
//是否将返回结果规整化,比如将一百返回为100。
transcriber.setEnableITN(false);
//设置vad断句参数。默认值:800ms,有效值:200ms~2000ms。
//transcriber.addCustomedParam("max_sentence_silence", 600);
//设置是否语义断句。
//transcriber.addCustomedParam("enable_semantic_sentence_detection",false);
//设置是否开启顺滑。
//transcriber.addCustomedParam("disfluency",true);
//设置是否开启词模式。
//transcriber.addCustomedParam("enable_words",true);
//设置vad噪音阈值参数,参数取值为-1~+1,如-0.9、-0.8、0.2、0.9。
//取值越趋于-1,判定为语音的概率越大,亦即有可能更多噪声被当成语音被误识别。
//取值越趋于+1,判定为噪音的越多,亦即有可能更多语音段被当成噪音被拒绝识别。
//该参数属高级参数,调整需慎重和重点测试。
//transcriber.addCustomedParam("speech_noise_threshold",0.3);
//设置训练后的定制语言模型id。
//transcriber.addCustomedParam("customization_id","你的定制语言模型id");
//设置训练后的定制热词id。
//transcriber.addCustomedParam("vocabulary_id","你的定制热词id");
//设置是否忽略单句超时。
transcriber.addCustomedParam("enable_ignore_sentence_timeout", false);
//vad断句开启后处理。
//transcriber.addCustomedParam("enable_vad_unify_post",false);
//此方法将以上参数设置序列化为JSON发送给服务端,并等待服务端确认。
transcriber.start();
FileInputStream fis = new FileInputStream(speechFile);
byte[] b = new byte[3200];
int len;
while ((len = fis.read(b)) > 0) {
logger.info("send data pack length: " + len);
transcriber.send(b, len);
//本案例用读取本地文件的形式模拟实时获取语音流并发送的,因为读取速度较快,这里需要设置sleep,如果实时获取语音则无需设置sleep
TimeUnit.MILLISECONDS.sleep(1000);
}
//通知服务端语音数据发送完毕,等待服务端处理完成。
long now = System.currentTimeMillis();
logger.info("ASR wait for complete");
transcriber.stop();
logger.info("ASR latency : " + (System.currentTimeMillis() - now) + " ms");
} catch (Exception e) {
logger.error(e.getMessage());
} finally {
if (null != transcriber) {
transcriber.close();
}
}
}
}
package com.yejoin.amos;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriberListener;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriberResponse;
import com.yeejoin.amos.speech.SpeechFlashRecognizer;
import com.yeejoin.amos.speech.SpeechRecognizer;
import com.yeejoin.amos.speech.SpeechTranscriber;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
public class SpeechApplicationTests {
private static final Logger logger = LoggerFactory.getLogger(SpeechApplicationTests.class);
/**
* 实时语音识别使用示例(提交文件流,免费可测试)
*/
@Test
void testSpeechTranscriber() {
//本案例使用本地文件模拟发送实时流数据。您在实际使用时,可以实时采集或接收语音流并发送到ASR服务端。
String fileLink = "https://gw.alipayobjects.com/os/bmw-prod/0574ee2e-f494-45a5-820f-63aee583045a.wav";
//将上面fileLink文件下载到本地后,替换filepath为本地地址测试
String filepath = "D:\\ffmpeg-4.4-full_build-shared\\bin\\out.pcm";
SpeechTranscriber transcriber = new SpeechTranscriber(new File(filepath), new SpeechTranscriberListener() {
/**
* 语音识别过程中返回的结果。仅当setEnableIntermediateResult为true时,才会返回该消息。
*/
@Override
public void onTranscriptionResultChange(SpeechTranscriberResponse response) {
logger.warn("语音识别过程中返回的结果");
logger.warn("task_id: " + response.getTaskId() +
", name: " + response.getName() +
//状态码“20000000”表示正常识别。
", status: " + response.getStatus() +
//句子编号,从1开始递增。
", index: " + response.getTransSentenceIndex() +
//当前的识别结果。
", result: " + response.getTransSentenceText() +
//当前已处理的音频时长,单位为毫秒。
", time: " + response.getTransSentenceTime());
}
/**
* 服务端准备好了进行识别
*/
@Override
public void onTranscriberStart(SpeechTranscriberResponse response) {
logger.warn("服务端准备好了进行识别");
logger.warn("task_id: " + response.getTaskId()
+ ", name: " + response.getName()
+ ", status: " + response.getStatus());
}
/**
* 服务端检测到了一句话的开始
*/
@Override
public void onSentenceBegin(SpeechTranscriberResponse response) {
logger.warn("服务端检测到了一句话的开始");
logger.warn("task_id: " + response.getTaskId()
+ ", name: " + response.getName()
+ ", status: " + response.getStatus());
}
/**
* 服务端检测到了一句话的结束
* 识别出一句话。服务端会智能断句,当识别到一句话结束时会返回此消息。
*/
@Override
public void onSentenceEnd(SpeechTranscriberResponse response) {
logger.warn("服务端检测到了一句话的结束");
logger.warn("task_id: " + response.getTaskId() +
", name: " + response.getName() +
//状态码“20000000”表示正常识别。
", status: " + response.getStatus() +
//句子编号,从1开始递增。
", index: " + response.getTransSentenceIndex() +
//当前的识别结果。
", result: " + response.getTransSentenceText() +
//置信度
", confidence: " + response.getConfidence() +
//开始时间
", begin_time: " + response.getSentenceBeginTime() +
//当前已处理的音频时长,单位为毫秒。
", time: " + response.getTransSentenceTime());
}
/**
* 识别结束后返回的最终结果
*/
@Override
public void onTranscriptionComplete(SpeechTranscriberResponse response) {
logger.warn("识别结束后返回的最终结果");
logger.warn("task_id: " + response.getTaskId()
+ ", name: " + response.getName()
+ ", status: " + response.getStatus()
+ ",result:" + response.getTransSentenceText());
}
/**
* 失败处理
*/
@Override
public void onFail(SpeechTranscriberResponse response) {
logger.error("失败处理");
logger.error("task_id: " + response.getTaskId()
+ ", status: " + response.getStatus()
+ ", status_text: " + response.getStatusText());
}
});
transcriber.process();
}
/**
* 语音文件识别极速版使用示例(提交文件,收费无法测试)
*/
@Test
void testSpeechFlashRecognizer() {
//String fileName = SpeechRecognizerRestfulDemo.class.getClassLoader().getResource("./nls-sample-16k.wav").getPath();
// 重要:此处用一个本地文件来模拟发送实时流数据,实际使用时,您可以从某处实时采集或接收语音流并发送到ASR服务端。
String fileName = "D:\\ffmpeg-4.4-full_build-shared\\bin\\test.mp3";
String format = "mp3";
int sampleRate = 16000;
SpeechFlashRecognizer speechFlashRecognizer = new SpeechFlashRecognizer(new File(fileName), sampleRate, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
logger.error("语音识别失败,原因:" + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
assert response.body() != null;
logger.warn("语音识别结果:" + response.body().string());
}
});
speechFlashRecognizer.process();
}
/**
* 语音文件识别普通版使用示例(提交文件地址,免费可测试)
*/
@Test
void testSpeechRecognizer() {
String fileLink = "https://gw.alipayobjects.com/os/bmw-prod/0574ee2e-f494-45a5-820f-63aee583045a.wav";
SpeechRecognizer speechRecognizer = new SpeechRecognizer();
// 第一步:提交录音文件识别请求,获取任务ID用于后续的识别结果轮询。
String taskId = speechRecognizer.submitFileTransRequest(fileLink);
if (taskId != null) {
logger.info("录音文件识别请求成功,task_id: " + taskId);
} else {
logger.error("录音文件识别请求失败!");
return;
}
// 第二步:根据任务ID轮询识别结果。
String result = speechRecognizer.getFileTransResult(taskId);
if (result != null) {
logger.info("录音文件识别结果查询成功:" + result);
} else {
logger.error("录音文件识别结果查询失败!");
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>amos-biz-boot</artifactId>
<groupId>com.amosframework.boot</groupId>
<version>1.0.0</version>
</parent>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>amos-biz-boot</artifactId>
<groupId>com.amosframework.boot</groupId>
<version>1.0.0</version>
</parent>
<artifactId>amos-boot-utils</artifactId>
<packaging>pom</packaging>
<artifactId>amos-boot-utils</artifactId>
<packaging>pom</packaging>
<dependencies>
</dependencies>
<dependencies>
</dependencies>
<modules>
<module>amos-boot-utils-jpush</module>
<module>amos-boot-utils-video</module>
</modules>
<modules>
<module>amos-boot-utils-jpush</module>
<module>amos-boot-utils-video</module>
<module>amos-boot-utils-speech</module>
</modules>
</project>
\ No newline at end of file
......@@ -283,6 +283,11 @@
<name>Snapshots</name>
<url>http://172.16.1.6:8081/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<modules>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment