Commit 3c49197fc5b47858d025957f879cd058af3f8deb
1 parent
e9257718
1.报站语音合成代码合并(lggj)
2.设备管理权限控制 3.站点加入公司分公司加权限控制 4.视频播放调整(多sim情况处理)
Showing
22 changed files
with
1038 additions
and
49 deletions
pom.xml
| @@ -433,7 +433,25 @@ | @@ -433,7 +433,25 @@ | ||
| 433 | <artifactId>kotlin-stdlib</artifactId> | 433 | <artifactId>kotlin-stdlib</artifactId> |
| 434 | <version>1.3.72</version> | 434 | <version>1.3.72</version> |
| 435 | </dependency> | 435 | </dependency> |
| 436 | - </dependencies> | 436 | + |
| 437 | + <dependency> | ||
| 438 | + <groupId>com.squareup.okhttp3</groupId> | ||
| 439 | + <artifactId>okhttp</artifactId> | ||
| 440 | + <version>4.10.0</version> | ||
| 441 | + </dependency> | ||
| 442 | + | ||
| 443 | + <dependency> | ||
| 444 | + <groupId>org.java-websocket</groupId> | ||
| 445 | + <artifactId>Java-WebSocket</artifactId> | ||
| 446 | + <version>1.5.3</version> | ||
| 447 | + </dependency> | ||
| 448 | + | ||
| 449 | + <dependency> | ||
| 450 | + <groupId>org.bytedeco</groupId> | ||
| 451 | + <artifactId>javacv-platform</artifactId> | ||
| 452 | + <version>1.5.11</version> | ||
| 453 | + </dependency> | ||
| 454 | + </dependencies> | ||
| 437 | 455 | ||
| 438 | <dependencyManagement> | 456 | <dependencyManagement> |
| 439 | <dependencies> | 457 | <dependencies> |
src/main/java/com/bsth/controller/gps/GpsController.java
| 1 | package com.bsth.controller.gps; | 1 | package com.bsth.controller.gps; |
| 2 | 2 | ||
| 3 | +import com.bsth.common.Constants; | ||
| 3 | import com.bsth.data.BasicData; | 4 | import com.bsth.data.BasicData; |
| 4 | import com.bsth.data.gpsdata_v2.GpsRealData; | 5 | import com.bsth.data.gpsdata_v2.GpsRealData; |
| 5 | import com.bsth.data.gpsdata_v2.entity.GpsEntity; | 6 | import com.bsth.data.gpsdata_v2.entity.GpsEntity; |
| @@ -7,13 +8,16 @@ import com.bsth.data.gpsdata_v2.handlers.overspeed.GpsOverspeed; | @@ -7,13 +8,16 @@ import com.bsth.data.gpsdata_v2.handlers.overspeed.GpsOverspeed; | ||
| 7 | import com.bsth.data.gpsdata_v2.handlers.overspeed.OverspeedProcess; | 8 | import com.bsth.data.gpsdata_v2.handlers.overspeed.OverspeedProcess; |
| 8 | import com.bsth.data.schedule.e_state_check.ScheduleStationCodeChecker; | 9 | import com.bsth.data.schedule.e_state_check.ScheduleStationCodeChecker; |
| 9 | import com.bsth.data.schedule.e_state_check.entity.SCodeInfo; | 10 | import com.bsth.data.schedule.e_state_check.entity.SCodeInfo; |
| 11 | +import com.bsth.entity.sys.CompanyAuthority; | ||
| 10 | import com.bsth.service.gps.GpsService; | 12 | import com.bsth.service.gps.GpsService; |
| 11 | import com.bsth.service.gps.entity.GpsSpeed; | 13 | import com.bsth.service.gps.entity.GpsSpeed; |
| 12 | import com.google.common.base.Splitter; | 14 | import com.google.common.base.Splitter; |
| 13 | import org.springframework.beans.factory.annotation.Autowired; | 15 | import org.springframework.beans.factory.annotation.Autowired; |
| 14 | import org.springframework.web.bind.annotation.*; | 16 | import org.springframework.web.bind.annotation.*; |
| 15 | 17 | ||
| 18 | +import javax.servlet.http.HttpServletRequest; | ||
| 16 | import javax.servlet.http.HttpServletResponse; | 19 | import javax.servlet.http.HttpServletResponse; |
| 20 | +import javax.servlet.http.HttpSession; | ||
| 17 | import java.text.ParseException; | 21 | import java.text.ParseException; |
| 18 | import java.util.ArrayList; | 22 | import java.util.ArrayList; |
| 19 | import java.util.HashMap; | 23 | import java.util.HashMap; |
| @@ -38,10 +42,11 @@ public class GpsController { | @@ -38,10 +42,11 @@ public class GpsController { | ||
| 38 | @RequestParam(defaultValue = "0") int page, | 42 | @RequestParam(defaultValue = "0") int page, |
| 39 | @RequestParam(defaultValue = "15") int size, | 43 | @RequestParam(defaultValue = "15") int size, |
| 40 | @RequestParam(defaultValue = "timestamp") String order, | 44 | @RequestParam(defaultValue = "timestamp") String order, |
| 41 | - @RequestParam(defaultValue = "DESC") String direction) { | 45 | + @RequestParam(defaultValue = "DESC") String direction, HttpServletRequest request) { |
| 42 | 46 | ||
| 43 | - | ||
| 44 | - return gpsService.search(map, page, size, order, direction); | 47 | + HttpSession session = request.getSession(); |
| 48 | + List<CompanyAuthority> cmyAuths = (List<CompanyAuthority>) session.getAttribute(Constants.COMPANY_AUTHORITYS); | ||
| 49 | + return gpsService.search(map, page, size, order, direction, cmyAuths); | ||
| 45 | } | 50 | } |
| 46 | 51 | ||
| 47 | @RequestMapping(value = "/real/line/{lineCode}") | 52 | @RequestMapping(value = "/real/line/{lineCode}") |
src/main/java/com/bsth/data/BasicData.java
| @@ -14,6 +14,7 @@ import java.util.Set; | @@ -14,6 +14,7 @@ import java.util.Set; | ||
| 14 | 14 | ||
| 15 | import com.bsth.entity.*; | 15 | import com.bsth.entity.*; |
| 16 | import com.bsth.repository.*; | 16 | import com.bsth.repository.*; |
| 17 | +import com.bsth.util.db.DBUtils_MS; | ||
| 17 | import org.apache.commons.lang3.StringUtils; | 18 | import org.apache.commons.lang3.StringUtils; |
| 18 | import org.slf4j.Logger; | 19 | import org.slf4j.Logger; |
| 19 | import org.slf4j.LoggerFactory; | 20 | import org.slf4j.LoggerFactory; |
| @@ -62,6 +63,9 @@ public class BasicData { | @@ -62,6 +63,9 @@ public class BasicData { | ||
| 62 | //车辆自编号和sim号对照 (K:车辆自编号 V: sim号) | 63 | //车辆自编号和sim号对照 (K:车辆自编号 V: sim号) |
| 63 | public static Map<String, String> nbbm2SimMap; | 64 | public static Map<String, String> nbbm2SimMap; |
| 64 | 65 | ||
| 66 | + //车辆自编号和sim号对照 (K:车辆自编号 V: sim号) | ||
| 67 | + public static Map<String, String> nbbm2Sim2Map; | ||
| 68 | + | ||
| 65 | //站点编码和名称对照,包括停车场 (K: lineCode_updown_stationCode ,V:站点名称) | 69 | //站点编码和名称对照,包括停车场 (K: lineCode_updown_stationCode ,V:站点名称) |
| 66 | public static Map<String, String> stationCode2NameMap; | 70 | public static Map<String, String> stationCode2NameMap; |
| 67 | 71 | ||
| @@ -105,6 +109,8 @@ public class BasicData { | @@ -105,6 +109,8 @@ public class BasicData { | ||
| 105 | // 线路编码_日期 等级 | 109 | // 线路编码_日期 等级 |
| 106 | public static Map<String, String> lineDate2Level; | 110 | public static Map<String, String> lineDate2Level; |
| 107 | 111 | ||
| 112 | + private static JdbcTemplate msJdbcTemplate = new JdbcTemplate(DBUtils_MS.getDataSource()); | ||
| 113 | + | ||
| 108 | static Logger logger = LoggerFactory.getLogger(BasicData.class); | 114 | static Logger logger = LoggerFactory.getLogger(BasicData.class); |
| 109 | 115 | ||
| 110 | public static String getStationNameByCode(String code, String prefix){ | 116 | public static String getStationNameByCode(String code, String prefix){ |
| @@ -238,8 +244,10 @@ public class BasicData { | @@ -238,8 +244,10 @@ public class BasicData { | ||
| 238 | Map<String, String> nbbmCompanyPlate = new HashMap<>(); | 244 | Map<String, String> nbbmCompanyPlate = new HashMap<>(); |
| 239 | // 车辆自编号和sim对照 | 245 | // 车辆自编号和sim对照 |
| 240 | Map<String, String> nbbm2Sim = new HashMap<>(); | 246 | Map<String, String> nbbm2Sim = new HashMap<>(); |
| 247 | + Map<String, String> nbbm2Sim2 = new HashMap<>(); | ||
| 241 | 248 | ||
| 242 | Iterator<Cars> carIterator = carsRepository.findAll().iterator(); | 249 | Iterator<Cars> carIterator = carsRepository.findAll().iterator(); |
| 250 | + List<Map<String, Object>> maps = msJdbcTemplate.queryForList("SELECT in_code, sim, relation_sim FROM bsth_c_device_sim_mapping"); | ||
| 243 | Cars car; | 251 | Cars car; |
| 244 | while (carIterator.hasNext()) { | 252 | while (carIterator.hasNext()) { |
| 245 | car = carIterator.next(); | 253 | car = carIterator.next(); |
| @@ -247,7 +255,11 @@ public class BasicData { | @@ -247,7 +255,11 @@ public class BasicData { | ||
| 247 | nbbm2CompanyCode.put(car.getInsideCode(), car.getBusinessCode()); | 255 | nbbm2CompanyCode.put(car.getInsideCode(), car.getBusinessCode()); |
| 248 | nbbm2FgsCompanyCode.put(car.getInsideCode(), car.getBrancheCompanyCode() + "_" + car.getBusinessCode() ); | 256 | nbbm2FgsCompanyCode.put(car.getInsideCode(), car.getBrancheCompanyCode() + "_" + car.getBusinessCode() ); |
| 249 | nbbmCompanyPlate.put(car.getInsideCode(), car.getCarPlate()); | 257 | nbbmCompanyPlate.put(car.getInsideCode(), car.getCarPlate()); |
| 250 | - nbbm2Sim.put(car.getInsideCode(), car.getSim()); | 258 | + } |
| 259 | + for (Map<String, Object> map : maps) { | ||
| 260 | + String inCode = (String) map.get("in_code"), sim = (String) map.get("sim"), sim2 = (String) map.get("relation_sim"); | ||
| 261 | + nbbm2Sim.put(inCode, sim); | ||
| 262 | + nbbm2Sim2.put(inCode, sim2); | ||
| 251 | } | 263 | } |
| 252 | 264 | ||
| 253 | deviceId2NbbmMap = deviceId2Nbbm; | 265 | deviceId2NbbmMap = deviceId2Nbbm; |
| @@ -255,6 +267,7 @@ public class BasicData { | @@ -255,6 +267,7 @@ public class BasicData { | ||
| 255 | nbbm2FgsCompanyCodeMap = nbbm2FgsCompanyCode; | 267 | nbbm2FgsCompanyCodeMap = nbbm2FgsCompanyCode; |
| 256 | nbbmCompanyPlateMap = nbbmCompanyPlate; | 268 | nbbmCompanyPlateMap = nbbmCompanyPlate; |
| 257 | nbbm2SimMap = nbbm2Sim; | 269 | nbbm2SimMap = nbbm2Sim; |
| 270 | + nbbm2Sim2Map = nbbm2Sim2; | ||
| 258 | } | 271 | } |
| 259 | 272 | ||
| 260 | /** | 273 | /** |
src/main/java/com/bsth/data/gpsdata_v2/entity/GpsEntity.java
| @@ -129,6 +129,11 @@ public class GpsEntity implements Cloneable{ | @@ -129,6 +129,11 @@ public class GpsEntity implements Cloneable{ | ||
| 129 | private String sim; | 129 | private String sim; |
| 130 | 130 | ||
| 131 | /** | 131 | /** |
| 132 | + * sim号 拓华有两套设备 | ||
| 133 | + */ | ||
| 134 | + private String sim2; | ||
| 135 | + | ||
| 136 | + /** | ||
| 132 | * 当前乘客数 | 137 | * 当前乘客数 |
| 133 | */ | 138 | */ |
| 134 | private int passengerNum; | 139 | private int passengerNum; |
| @@ -450,6 +455,14 @@ public class GpsEntity implements Cloneable{ | @@ -450,6 +455,14 @@ public class GpsEntity implements Cloneable{ | ||
| 450 | this.sim = sim; | 455 | this.sim = sim; |
| 451 | } | 456 | } |
| 452 | 457 | ||
| 458 | + public String getSim2() { | ||
| 459 | + return sim2; | ||
| 460 | + } | ||
| 461 | + | ||
| 462 | + public void setSim2(String sim2) { | ||
| 463 | + this.sim2 = sim2; | ||
| 464 | + } | ||
| 465 | + | ||
| 453 | public int getPassengerNum() { | 466 | public int getPassengerNum() { |
| 454 | return passengerNum; | 467 | return passengerNum; |
| 455 | } | 468 | } |
src/main/java/com/bsth/data/gpsdata_v2/load/GatewayHttpLoader.java
| @@ -71,7 +71,7 @@ public class GatewayHttpLoader implements ApplicationContextAware, InitializingB | @@ -71,7 +71,7 @@ public class GatewayHttpLoader implements ApplicationContextAware, InitializingB | ||
| 71 | list = GpsDataUtils.clearInvalid(list); | 71 | list = GpsDataUtils.clearInvalid(list); |
| 72 | 72 | ||
| 73 | List<GpsEntity> ups = new ArrayList<>(); | 73 | List<GpsEntity> ups = new ArrayList<>(); |
| 74 | - String nbbm, sim; | 74 | + String nbbm, sim, sim2; |
| 75 | for (GpsEntity gps : list) { | 75 | for (GpsEntity gps : list) { |
| 76 | if (StringUtils.isBlank(gps.getDeviceId())) | 76 | if (StringUtils.isBlank(gps.getDeviceId())) |
| 77 | continue; | 77 | continue; |
| @@ -82,7 +82,9 @@ public class GatewayHttpLoader implements ApplicationContextAware, InitializingB | @@ -82,7 +82,9 @@ public class GatewayHttpLoader implements ApplicationContextAware, InitializingB | ||
| 82 | nbbm = BasicData.deviceId2NbbmMap.get(gps.getDeviceId()); | 82 | nbbm = BasicData.deviceId2NbbmMap.get(gps.getDeviceId()); |
| 83 | if (!StringUtils.isBlank(nbbm)) { | 83 | if (!StringUtils.isBlank(nbbm)) { |
| 84 | sim = BasicData.nbbm2SimMap.get(nbbm); | 84 | sim = BasicData.nbbm2SimMap.get(nbbm); |
| 85 | + sim2 = BasicData.nbbm2Sim2Map.get(nbbm); | ||
| 85 | gps.setSim(sim); | 86 | gps.setSim(sim); |
| 87 | + gps.setSim2(sim2); | ||
| 86 | } | 88 | } |
| 87 | gps.setNbbm(nbbm); | 89 | gps.setNbbm(nbbm); |
| 88 | ups.add(gps); | 90 | ups.add(gps); |
src/main/java/com/bsth/data/schedule/DayOfSchedule.java
| @@ -366,6 +366,9 @@ public class DayOfSchedule { | @@ -366,6 +366,9 @@ public class DayOfSchedule { | ||
| 366 | sch.setScheduleDateStr(fmtyyyyMMdd.print(sch.getScheduleDate().getTime())); | 366 | sch.setScheduleDateStr(fmtyyyyMMdd.print(sch.getScheduleDate().getTime())); |
| 367 | sch.setRealExecDate(sch.getScheduleDateStr()); | 367 | sch.setRealExecDate(sch.getScheduleDateStr()); |
| 368 | sch.setCreateDate(d); | 368 | sch.setCreateDate(d); |
| 369 | + if (sch.getStatus() == null) { | ||
| 370 | + sch.setStatus(0); | ||
| 371 | + } | ||
| 369 | 372 | ||
| 370 | if (StringUtils.isEmpty(sch.getFcsj())) | 373 | if (StringUtils.isEmpty(sch.getFcsj())) |
| 371 | sch.setFcsj("00:00"); | 374 | sch.setFcsj("00:00"); |
src/main/java/com/bsth/entity/Station.java
| @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
| 5 | import org.geolatte.geom.Point; | 5 | import org.geolatte.geom.Point; |
| 6 | import org.hibernate.annotations.DynamicInsert; | 6 | import org.hibernate.annotations.DynamicInsert; |
| 7 | import org.hibernate.annotations.DynamicUpdate; | 7 | import org.hibernate.annotations.DynamicUpdate; |
| 8 | +import org.hibernate.annotations.Formula; | ||
| 8 | 9 | ||
| 9 | import javax.persistence.*; | 10 | import javax.persistence.*; |
| 10 | import java.util.Date; | 11 | import java.util.Date; |
| @@ -130,6 +131,20 @@ public class Station { | @@ -130,6 +131,20 @@ public class Station { | ||
| 130 | 131 | ||
| 131 | private String standardStationCode; | 132 | private String standardStationCode; |
| 132 | 133 | ||
| 134 | + private String company; | ||
| 135 | + | ||
| 136 | + @Transient | ||
| 137 | + private String companyName; | ||
| 138 | + | ||
| 139 | + private String brancheCompany; | ||
| 140 | + | ||
| 141 | + @Transient | ||
| 142 | + private String brancheCompanyName; | ||
| 143 | + | ||
| 144 | + /** 组合公司分公司编码 */ | ||
| 145 | + @Formula(" concat(company, '_', branche_company) ") | ||
| 146 | + private String cgsbm; | ||
| 147 | + | ||
| 133 | public Integer getId() { | 148 | public Integer getId() { |
| 134 | return id; | 149 | return id; |
| 135 | } | 150 | } |
| @@ -321,4 +336,44 @@ public class Station { | @@ -321,4 +336,44 @@ public class Station { | ||
| 321 | public void setStandardStationCode(String standardStationCode) { | 336 | public void setStandardStationCode(String standardStationCode) { |
| 322 | this.standardStationCode = standardStationCode; | 337 | this.standardStationCode = standardStationCode; |
| 323 | } | 338 | } |
| 339 | + | ||
| 340 | + public String getCompany() { | ||
| 341 | + return company; | ||
| 342 | + } | ||
| 343 | + | ||
| 344 | + public void setCompany(String company) { | ||
| 345 | + this.company = company; | ||
| 346 | + } | ||
| 347 | + | ||
| 348 | + public String getCompanyName() { | ||
| 349 | + return companyName; | ||
| 350 | + } | ||
| 351 | + | ||
| 352 | + public void setCompanyName(String companyName) { | ||
| 353 | + this.companyName = companyName; | ||
| 354 | + } | ||
| 355 | + | ||
| 356 | + public String getBrancheCompany() { | ||
| 357 | + return brancheCompany; | ||
| 358 | + } | ||
| 359 | + | ||
| 360 | + public void setBrancheCompany(String brancheCompany) { | ||
| 361 | + this.brancheCompany = brancheCompany; | ||
| 362 | + } | ||
| 363 | + | ||
| 364 | + public String getBrancheCompanyName() { | ||
| 365 | + return brancheCompanyName; | ||
| 366 | + } | ||
| 367 | + | ||
| 368 | + public void setBrancheCompanyName(String brancheCompanyName) { | ||
| 369 | + this.brancheCompanyName = brancheCompanyName; | ||
| 370 | + } | ||
| 371 | + | ||
| 372 | + public String getCgsbm() { | ||
| 373 | + return cgsbm; | ||
| 374 | + } | ||
| 375 | + | ||
| 376 | + public void setCgsbm(String cgsbm) { | ||
| 377 | + this.cgsbm = cgsbm; | ||
| 378 | + } | ||
| 324 | } | 379 | } |
src/main/java/com/bsth/entity/realcontrol/ScheduleRealInfo.java
| @@ -137,7 +137,7 @@ public class ScheduleRealInfo { | @@ -137,7 +137,7 @@ public class ScheduleRealInfo { | ||
| 137 | private Long zdsjActualTime; | 137 | private Long zdsjActualTime; |
| 138 | 138 | ||
| 139 | /**班次状态 0 未执行 1 正在执行 2 已执行 -1 已烂班 */ | 139 | /**班次状态 0 未执行 1 正在执行 2 已执行 -1 已烂班 */ |
| 140 | - private int status; | 140 | + private Integer status; |
| 141 | 141 | ||
| 142 | private String adjustExps; | 142 | private String adjustExps; |
| 143 | 143 | ||
| @@ -617,11 +617,11 @@ public class ScheduleRealInfo { | @@ -617,11 +617,11 @@ public class ScheduleRealInfo { | ||
| 617 | this.zdsjActualTime = zdsjActualTime; | 617 | this.zdsjActualTime = zdsjActualTime; |
| 618 | } | 618 | } |
| 619 | 619 | ||
| 620 | - public int getStatus() { | 620 | + public Integer getStatus() { |
| 621 | return status; | 621 | return status; |
| 622 | } | 622 | } |
| 623 | 623 | ||
| 624 | - public void setStatus(int status) { | 624 | + public void setStatus(Integer status) { |
| 625 | this.status = status; | 625 | this.status = status; |
| 626 | } | 626 | } |
| 627 | 627 |
src/main/java/com/bsth/entity/speech/SpeechRequest.java
0 → 100644
| 1 | +package com.bsth.entity.speech; | ||
| 2 | + | ||
| 3 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
| 4 | + | ||
| 5 | +import java.util.HashMap; | ||
| 6 | +import java.util.Map; | ||
| 7 | + | ||
| 8 | +public class SpeechRequest { | ||
| 9 | + | ||
| 10 | + /** | ||
| 11 | + * 包含appid | ||
| 12 | + */ | ||
| 13 | + private Map<String, Object> common = new HashMap<>(); | ||
| 14 | + | ||
| 15 | + /** | ||
| 16 | + * 音频合成参数 | ||
| 17 | + */ | ||
| 18 | + private Map<String, Object> business = new HashMap<>(); | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 数据、状态参数 | ||
| 22 | + */ | ||
| 23 | + private Map<String, Object> data = new HashMap<>(); | ||
| 24 | + | ||
| 25 | + @JsonIgnore | ||
| 26 | + private boolean completed = false; | ||
| 27 | + | ||
| 28 | + public Map<String, Object> getCommon() { | ||
| 29 | + return common; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + public void setCommon(Map<String, Object> common) { | ||
| 33 | + this.common = common; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + public Map<String, Object> getBusiness() { | ||
| 37 | + return business; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + public void setBusiness(Map<String, Object> business) { | ||
| 41 | + this.business = business; | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + public Map<String, Object> getData() { | ||
| 45 | + return data; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + public void setData(Map<String, Object> data) { | ||
| 49 | + this.data = data; | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + public boolean isCompleted() { | ||
| 53 | + return completed; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + public void setCompleted(boolean completed) { | ||
| 57 | + this.completed = completed; | ||
| 58 | + } | ||
| 59 | +} |
src/main/java/com/bsth/entity/speech/SpeechResponse.java
0 → 100644
| 1 | +package com.bsth.entity.speech; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 讯飞在线语音合成返回json | ||
| 5 | + */ | ||
| 6 | +public class SpeechResponse { | ||
| 7 | + | ||
| 8 | + private int code; | ||
| 9 | + | ||
| 10 | + private String message; | ||
| 11 | + | ||
| 12 | + private String sid; | ||
| 13 | + | ||
| 14 | + private AudioData data; | ||
| 15 | + | ||
| 16 | + public int getCode() { | ||
| 17 | + return code; | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + public void setCode(int code) { | ||
| 21 | + this.code = code; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + public String getMessage() { | ||
| 25 | + return message; | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + public void setMessage(String message) { | ||
| 29 | + this.message = message; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + public String getSid() { | ||
| 33 | + return sid; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + public void setSid(String sid) { | ||
| 37 | + this.sid = sid; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + public AudioData getData() { | ||
| 41 | + return data; | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + public void setData(AudioData data) { | ||
| 45 | + this.data = data; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + public final static class AudioData { | ||
| 49 | + | ||
| 50 | + private String audio; | ||
| 51 | + | ||
| 52 | + private String ced; | ||
| 53 | + | ||
| 54 | + private int status; | ||
| 55 | + | ||
| 56 | + public String getAudio() { | ||
| 57 | + return audio; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + public void setAudio(String audio) { | ||
| 61 | + this.audio = audio; | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + public String getCed() { | ||
| 65 | + return ced; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + public void setCed(String ced) { | ||
| 69 | + this.ced = ced; | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + public int getStatus() { | ||
| 73 | + return status; | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + public void setStatus(int status) { | ||
| 77 | + this.status = status; | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + @Override | ||
| 81 | + public String toString() { | ||
| 82 | + return "AudioData{" + | ||
| 83 | + "audio='" + audio + '\'' + | ||
| 84 | + ", ced='" + ced + '\'' + | ||
| 85 | + ", status=" + status + | ||
| 86 | + '}'; | ||
| 87 | + } | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + @Override | ||
| 91 | + public String toString() { | ||
| 92 | + return "SpeechResponse{" + | ||
| 93 | + "code=" + code + | ||
| 94 | + ", message='" + message + '\'' + | ||
| 95 | + ", sid='" + sid + '\'' + | ||
| 96 | + ", audioData=" + data + | ||
| 97 | + '}'; | ||
| 98 | + } | ||
| 99 | +} |
src/main/java/com/bsth/service/gps/GpsService.java
| 1 | package com.bsth.service.gps; | 1 | package com.bsth.service.gps; |
| 2 | 2 | ||
| 3 | +import com.bsth.entity.sys.CompanyAuthority; | ||
| 3 | import com.bsth.service.gps.entity.GpsOutbound_DTO; | 4 | import com.bsth.service.gps.entity.GpsOutbound_DTO; |
| 4 | import com.bsth.service.gps.entity.GpsSpeed; | 5 | import com.bsth.service.gps.entity.GpsSpeed; |
| 5 | import com.bsth.service.gps.entity.GpsSpeed_DTO; | 6 | import com.bsth.service.gps.entity.GpsSpeed_DTO; |
| @@ -17,7 +18,7 @@ public interface GpsService { | @@ -17,7 +18,7 @@ public interface GpsService { | ||
| 17 | 18 | ||
| 18 | Map<String, Object> findBuffAeraByCode(String lineCode, String code, String type); | 19 | Map<String, Object> findBuffAeraByCode(String lineCode, String code, String type); |
| 19 | 20 | ||
| 20 | - Map<String, Object> search(Map<String, Object> map, int page, int size, String order, String direction); | 21 | + Map<String, Object> search(Map<String, Object> map, int page, int size, String order, String direction, List<CompanyAuthority> cmyAuths); |
| 21 | 22 | ||
| 22 | Map<String,Object> removeRealGps(String device); | 23 | Map<String,Object> removeRealGps(String device); |
| 23 | 24 |
src/main/java/com/bsth/service/gps/GpsServiceImpl.java
| @@ -28,6 +28,9 @@ import java.util.Set; | @@ -28,6 +28,9 @@ import java.util.Set; | ||
| 28 | 28 | ||
| 29 | import javax.servlet.http.HttpServletResponse; | 29 | import javax.servlet.http.HttpServletResponse; |
| 30 | 30 | ||
| 31 | +import com.bsth.entity.sys.CompanyAuthority; | ||
| 32 | +import com.bsth.entity.sys.SysUser; | ||
| 33 | +import com.bsth.security.util.SecurityUtils; | ||
| 31 | import org.apache.commons.lang3.StringUtils; | 34 | import org.apache.commons.lang3.StringUtils; |
| 32 | import org.apache.poi.hssf.usermodel.HSSFCellStyle; | 35 | import org.apache.poi.hssf.usermodel.HSSFCellStyle; |
| 33 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; | 36 | import org.apache.poi.hssf.usermodel.HSSFWorkbook; |
| @@ -644,9 +647,13 @@ public class GpsServiceImpl implements GpsService { | @@ -644,9 +647,13 @@ public class GpsServiceImpl implements GpsService { | ||
| 644 | } | 647 | } |
| 645 | 648 | ||
| 646 | @Override | 649 | @Override |
| 647 | - public Map<String, Object> search(Map<String, Object> map, int page, int size, String order, String direction) { | 650 | + public Map<String, Object> search(Map<String, Object> map, int page, int size, String order, String direction, List<CompanyAuthority> cmyAuths) { |
| 648 | Map<String, Object> rsMap = new HashMap<>(); | 651 | Map<String, Object> rsMap = new HashMap<>(); |
| 652 | + Set<String> codes = new HashSet<>(); | ||
| 649 | try { | 653 | try { |
| 654 | + for (CompanyAuthority ca : cmyAuths) { | ||
| 655 | + codes.add(ca.getCompanyCode()); | ||
| 656 | + } | ||
| 650 | //全量 | 657 | //全量 |
| 651 | List<GpsEntity> list = new ArrayList<>(gpsRealData.all()); | 658 | List<GpsEntity> list = new ArrayList<>(gpsRealData.all()); |
| 652 | //过滤后的 | 659 | //过滤后的 |
| @@ -661,7 +668,8 @@ public class GpsServiceImpl implements GpsService { | @@ -661,7 +668,8 @@ public class GpsServiceImpl implements GpsService { | ||
| 661 | } | 668 | } |
| 662 | //过滤数据 | 669 | //过滤数据 |
| 663 | for (GpsEntity gps : list) { | 670 | for (GpsEntity gps : list) { |
| 664 | - if (fieldEquals(fs, gps, map)) | 671 | + String companyCode = BasicData.nbbm2CompanyCodeMap.get(gps.getNbbm()); |
| 672 | + if (codes.contains(companyCode) && fieldEquals(fs, gps, map)) | ||
| 665 | rs.add(gps); | 673 | rs.add(gps); |
| 666 | } | 674 | } |
| 667 | 675 |
src/main/java/com/bsth/service/impl/StationRouteServiceImpl.java
| @@ -5,27 +5,25 @@ import com.bsth.entity.*; | @@ -5,27 +5,25 @@ import com.bsth.entity.*; | ||
| 5 | import com.bsth.entity.search.CustomerSpecs; | 5 | import com.bsth.entity.search.CustomerSpecs; |
| 6 | import com.bsth.repository.*; | 6 | import com.bsth.repository.*; |
| 7 | import com.bsth.service.StationRouteService; | 7 | import com.bsth.service.StationRouteService; |
| 8 | -import com.bsth.util.CoordinateConverter; | ||
| 9 | -import com.bsth.util.ExcelUtil; | ||
| 10 | -import com.bsth.util.FTPClientUtils; | 8 | +import com.bsth.util.*; |
| 11 | import com.bsth.util.Geo.GeoUtils; | 9 | import com.bsth.util.Geo.GeoUtils; |
| 12 | import com.bsth.util.Geo.Point; | 10 | import com.bsth.util.Geo.Point; |
| 13 | -import com.bsth.util.PackTarGZUtils; | ||
| 14 | import com.bsth.util.db.DBUtils_MS; | 11 | import com.bsth.util.db.DBUtils_MS; |
| 15 | import com.google.common.base.Splitter; | 12 | import com.google.common.base.Splitter; |
| 16 | import org.apache.commons.lang3.StringUtils; | 13 | import org.apache.commons.lang3.StringUtils; |
| 17 | import org.geolatte.geom.Polygon; | 14 | import org.geolatte.geom.Polygon; |
| 18 | import org.springframework.beans.factory.annotation.Autowired; | 15 | import org.springframework.beans.factory.annotation.Autowired; |
| 16 | +import org.springframework.beans.factory.annotation.Value; | ||
| 19 | import org.springframework.data.domain.Sort; | 17 | import org.springframework.data.domain.Sort; |
| 20 | import org.springframework.data.domain.Sort.Direction; | 18 | import org.springframework.data.domain.Sort.Direction; |
| 21 | import org.springframework.stereotype.Service; | 19 | import org.springframework.stereotype.Service; |
| 22 | 20 | ||
| 23 | import javax.servlet.http.HttpServletResponse; | 21 | import javax.servlet.http.HttpServletResponse; |
| 24 | -import java.io.ByteArrayInputStream; | ||
| 25 | -import java.io.File; | ||
| 26 | -import java.io.InputStream; | 22 | +import java.io.*; |
| 27 | import java.text.DecimalFormat; | 23 | import java.text.DecimalFormat; |
| 28 | import java.util.*; | 24 | import java.util.*; |
| 25 | +import java.util.zip.ZipEntry; | ||
| 26 | +import java.util.zip.ZipOutputStream; | ||
| 29 | 27 | ||
| 30 | /** | 28 | /** |
| 31 | * | 29 | * |
| @@ -44,7 +42,13 @@ import java.util.*; | @@ -44,7 +42,13 @@ import java.util.*; | ||
| 44 | */ | 42 | */ |
| 45 | 43 | ||
| 46 | @Service | 44 | @Service |
| 47 | -public class StationRouteServiceImpl extends BaseServiceImpl<StationRoute, Integer> implements StationRouteService{ | 45 | +public class StationRouteServiceImpl extends BaseServiceImpl<StationRoute, Integer> implements StationRouteService { |
| 46 | + | ||
| 47 | + @Value("${path.speech.common}") | ||
| 48 | + private String commonPath; | ||
| 49 | + | ||
| 50 | + @Value("${path.speech.line}") | ||
| 51 | + private String linePathPattern; | ||
| 48 | 52 | ||
| 49 | @Autowired | 53 | @Autowired |
| 50 | private StationRouteRepository stationRouteRepository; | 54 | private StationRouteRepository stationRouteRepository; |
| @@ -422,6 +426,12 @@ public class StationRouteServiceImpl extends BaseServiceImpl<StationRoute, Integ | @@ -422,6 +426,12 @@ public class StationRouteServiceImpl extends BaseServiceImpl<StationRoute, Integ | ||
| 422 | /** 查询线路信息下的站点路由信息 @param:<lineId:线路ID> */ | 426 | /** 查询线路信息下的站点路由信息 @param:<lineId:线路ID> */ |
| 423 | List<Object[]> objects = stationRouteRepository.usingSingle(lineId); | 427 | List<Object[]> objects = stationRouteRepository.usingSingle(lineId); |
| 424 | if (objects.size()>0) { | 428 | if (objects.size()>0) { |
| 429 | + // 报站音频 | ||
| 430 | + Set<String> languages = new HashSet<>(); | ||
| 431 | + languages.add("cn"); | ||
| 432 | + //languages.add("sh"); | ||
| 433 | + //languages.add("en"); | ||
| 434 | + InputStream tts = ttsAndZip(objects, line, languages); | ||
| 425 | /** 获取配置文件里的ftp登录参数 */ | 435 | /** 获取配置文件里的ftp登录参数 */ |
| 426 | Map<String, Object> FTPParamMap = readPropertiesGetFTPParam(); | 436 | Map<String, Object> FTPParamMap = readPropertiesGetFTPParam(); |
| 427 | // 压缩文件名 | 437 | // 压缩文件名 |
| @@ -490,6 +500,8 @@ public class StationRouteServiceImpl extends BaseServiceImpl<StationRoute, Integ | @@ -490,6 +500,8 @@ public class StationRouteServiceImpl extends BaseServiceImpl<StationRoute, Integ | ||
| 490 | 500 | ||
| 491 | // textFile.delete(); | 501 | // textFile.delete(); |
| 492 | 502 | ||
| 503 | + clientUtils.deleteFtpFile(url, port, username, password, remotePath + "/voice/", String.format("%s.zip", line.getLineCode())); | ||
| 504 | + clientUtils.uploadFile(url, port, username, password, remotePath + "/voice/", String.format("%s.zip", line.getLineCode()), tts); | ||
| 493 | 505 | ||
| 494 | resultMap.put("status", ResponseCode.SUCCESS); | 506 | resultMap.put("status", ResponseCode.SUCCESS); |
| 495 | }else { | 507 | }else { |
| @@ -1001,4 +1013,266 @@ public class StationRouteServiceImpl extends BaseServiceImpl<StationRoute, Integ | @@ -1001,4 +1013,266 @@ public class StationRouteServiceImpl extends BaseServiceImpl<StationRoute, Integ | ||
| 1001 | } | 1013 | } |
| 1002 | } | 1014 | } |
| 1003 | } | 1015 | } |
| 1016 | + | ||
| 1017 | + private String subLine2Ftp(LineRegion lineRegion) { | ||
| 1018 | + StringBuilder builder = new StringBuilder(); | ||
| 1019 | + int len = lineRegion.getStationRoutes().size(); | ||
| 1020 | + int idx = 1; | ||
| 1021 | + for (int i = 0;i < len;i++) { | ||
| 1022 | + LsStationRoute route = lineRegion.getStationRoutes().get(i); | ||
| 1023 | + builder.append(route.getCenterPointWgs().getPosition().getCoordinate(0)) | ||
| 1024 | + .append("\t").append(route.getCenterPointWgs().getPosition().getCoordinate(1)) | ||
| 1025 | + .append("\t").append(i == len - 1 ? 2 : 1) | ||
| 1026 | + .append("\t").append(idx).append("\t"); | ||
| 1027 | + for (int j = 0;j < 8 - route.getStationCode().length();j++) { | ||
| 1028 | + builder.append("0"); | ||
| 1029 | + } | ||
| 1030 | + builder.append(route.getStationCode()) | ||
| 1031 | + .append("\t").append((int) route.getDistances().doubleValue() * 1000) | ||
| 1032 | + .append("\t0") | ||
| 1033 | + .append("\t").append(route.getStationName()) | ||
| 1034 | + .append("\t").append(route.getStationNameEn()) | ||
| 1035 | + .append("\r\n"); | ||
| 1036 | + | ||
| 1037 | + idx++; | ||
| 1038 | + } | ||
| 1039 | + | ||
| 1040 | + return builder.toString(); | ||
| 1041 | + } | ||
| 1042 | + | ||
| 1043 | + /** | ||
| 1044 | + * tts合成及打包 | ||
| 1045 | + * @param objects | ||
| 1046 | + * @param line | ||
| 1047 | + * @param languages 语言 如:cn、en、sh | ||
| 1048 | + */ | ||
| 1049 | + private InputStream ttsAndZip(List<Object[]> objects, Line line, Set<String> languages) throws Exception { | ||
| 1050 | + String lineId = line.getLineCode(); | ||
| 1051 | + StringBuilder cnBuilder = new StringBuilder(line.getName()).append("[p1000]"), enBuilder = new StringBuilder("Hello[p1000]"); | ||
| 1052 | + int ups = 0, downs = 0; | ||
| 1053 | + for (int i = 0;i < objects.size();i++) { | ||
| 1054 | + Object[] objArr = objects.get(i); | ||
| 1055 | + int direction = (int) objArr[8]; | ||
| 1056 | + String stationName = objArr[7] == null ? null : objArr[7].toString(), stationNameEn = objArr[9] == null ? null : objArr[9].toString(); | ||
| 1057 | + if (StringUtils.isEmpty(stationName)) { | ||
| 1058 | + throw new RuntimeException("存在异常的中文站点名称"); | ||
| 1059 | + } | ||
| 1060 | + // 如果要生成英语报站语音 | ||
| 1061 | + if (languages.contains("en")) { | ||
| 1062 | + if (StringUtils.isEmpty(stationNameEn)) { | ||
| 1063 | + throw new RuntimeException("存在异常的英文站点名称"); | ||
| 1064 | + } | ||
| 1065 | + enBuilder.append(stationNameEn).append("[p1000]"); | ||
| 1066 | + } | ||
| 1067 | + cnBuilder.append(stationName).append("[p1000]"); | ||
| 1068 | + if (direction == 0) { | ||
| 1069 | + ups++; | ||
| 1070 | + } else if (direction == 1) { | ||
| 1071 | + // 环线 | ||
| 1072 | + if (line.getLinePlayType() == 1) { | ||
| 1073 | + break; | ||
| 1074 | + } | ||
| 1075 | + downs++; | ||
| 1076 | + } | ||
| 1077 | + } | ||
| 1078 | + cnBuilder.delete(cnBuilder.length() - 8, cnBuilder.length() - 1); | ||
| 1079 | + enBuilder.delete(enBuilder.length() - 8, enBuilder.length() - 1); | ||
| 1080 | + | ||
| 1081 | + // 文本转语音并进行分割 | ||
| 1082 | + // 音频存放及压缩文件路径 | ||
| 1083 | + String linePath = String.format(linePathPattern, lineId), voicePath = String.format("%s%s.zip", linePath, lineId); | ||
| 1084 | + try { | ||
| 1085 | + String path = String.format("%scn.mp3", linePath); | ||
| 1086 | + IFlyUtils.textToSpeechCn(cnBuilder.toString(), path); | ||
| 1087 | + AudioOperationUtils.splitBySilence(path, String.format("%scn", linePath), 500, -40); | ||
| 1088 | + } catch (Exception e) { | ||
| 1089 | + throw new RuntimeException(e); | ||
| 1090 | + } | ||
| 1091 | + if (languages.contains("sh")) { | ||
| 1092 | + try { | ||
| 1093 | + String path = String.format("%ssh.mp3", linePath); | ||
| 1094 | + IFlyUtils.textToSpeechSh(cnBuilder.toString(), path); | ||
| 1095 | + AudioOperationUtils.splitBySilence(path, String.format("%ssh", linePath), 500, -40); | ||
| 1096 | + } catch (Exception e) { | ||
| 1097 | + throw new RuntimeException(e); | ||
| 1098 | + } | ||
| 1099 | + } | ||
| 1100 | + if (languages.contains("en")) { | ||
| 1101 | + try { | ||
| 1102 | + String path = String.format("%sen.mp3", linePath); | ||
| 1103 | + IFlyUtils.textToSpeechEn(enBuilder.toString(), path); | ||
| 1104 | + AudioOperationUtils.splitBySilence(path, String.format("%sen", linePath), 500, -40); | ||
| 1105 | + } catch (Exception e) { | ||
| 1106 | + throw new RuntimeException(e); | ||
| 1107 | + } | ||
| 1108 | + } | ||
| 1109 | + // 删除原线路音频 | ||
| 1110 | + File file = new File(linePath); | ||
| 1111 | + for (File f : file.listFiles()) { | ||
| 1112 | + if (f.isFile() && f.getName().endsWith(".mp3")) { | ||
| 1113 | + file.delete(); | ||
| 1114 | + } | ||
| 1115 | + } | ||
| 1116 | + | ||
| 1117 | + // 合并每站起步、到达语音 | ||
| 1118 | + int seq = 1, startSeq = 1, direction = 0; | ||
| 1119 | + seq = merge(lineId, seq, startSeq, direction, ups, languages); | ||
| 1120 | + startSeq = ups + 1; | ||
| 1121 | + direction = 1; | ||
| 1122 | + merge(lineId, seq, startSeq, direction, ups + downs, languages); | ||
| 1123 | + | ||
| 1124 | + // 压缩音频到zip | ||
| 1125 | + ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(voicePath)); | ||
| 1126 | + for (File f : file.listFiles()) { | ||
| 1127 | + if (f.isFile() && f.getName().endsWith(".mp3")) { | ||
| 1128 | + addFileToZip(zos, f); | ||
| 1129 | + } | ||
| 1130 | + } | ||
| 1131 | + // Key打头音频 | ||
| 1132 | + file = new File(commonPath); | ||
| 1133 | + for (File f : file.listFiles()) { | ||
| 1134 | + if (f.isFile() && f.getName().startsWith("Key-")) { | ||
| 1135 | + addFileToZip(zos, f); | ||
| 1136 | + } | ||
| 1137 | + } | ||
| 1138 | + zos.flush(); | ||
| 1139 | + zos.close(); | ||
| 1140 | + | ||
| 1141 | + return new FileInputStream(voicePath); | ||
| 1142 | + } | ||
| 1143 | + | ||
| 1144 | + private static void addFileToZip(ZipOutputStream zos, File file) throws IOException { | ||
| 1145 | + FileInputStream fis = new FileInputStream(file); | ||
| 1146 | + ZipEntry zipEntry = new ZipEntry(file.getName()); | ||
| 1147 | + zos.putNextEntry(zipEntry); | ||
| 1148 | + | ||
| 1149 | + byte[] bytes = new byte[4096]; | ||
| 1150 | + int length; | ||
| 1151 | + while ((length = fis.read(bytes)) >= 0) { | ||
| 1152 | + zos.write(bytes, 0, length); | ||
| 1153 | + } | ||
| 1154 | + | ||
| 1155 | + zos.closeEntry(); | ||
| 1156 | + fis.close(); | ||
| 1157 | + } | ||
| 1158 | + | ||
| 1159 | + private int merge(String lineId, int seq, int startSeq, int direction, int terminal, Set<String> languages) throws Exception { | ||
| 1160 | + for (int i = startSeq;i <= terminal;i++) { | ||
| 1161 | + if (i > startSeq) { | ||
| 1162 | + if (i == startSeq + 1) { | ||
| 1163 | + // 生成首站 | ||
| 1164 | + mergeOriginStart(lineId, seq, i, direction, terminal, languages); | ||
| 1165 | + mergeNormalArrive(lineId, seq, i, direction, terminal, languages); | ||
| 1166 | + } else if (i == terminal) { | ||
| 1167 | + // 生成终点站 | ||
| 1168 | + mergeNormalStart(lineId, seq, i, direction, terminal, languages); | ||
| 1169 | + mergeTerminalArrive(lineId, seq, i, direction, terminal, languages); | ||
| 1170 | + } else { | ||
| 1171 | + // 生成中途站 | ||
| 1172 | + mergeNormalStart(lineId, seq, i, direction, terminal, languages); | ||
| 1173 | + mergeNormalArrive(lineId, seq, i, direction, terminal, languages); | ||
| 1174 | + } | ||
| 1175 | + seq++; | ||
| 1176 | + } | ||
| 1177 | + } | ||
| 1178 | + | ||
| 1179 | + return seq; | ||
| 1180 | + } | ||
| 1181 | + | ||
| 1182 | + private void mergeOriginStart(String lineId, int seq, int stationLevel, int direction, int terminal, Set<String> languages) throws Exception { | ||
| 1183 | + String linePath = String.format(linePathPattern, lineId); | ||
| 1184 | + List<String> arr = Arrays.asList(commonPath + "cn_origin_1.mp3", linePath + String.format("cn/%03d.mp3", 0), commonPath + "cn_origin_2.mp3", linePath + String.format("cn/%03d.mp3", terminal), commonPath + "sh_origin_1.mp3", linePath + String.format("sh/%03d.mp3", 0), commonPath + "sh_origin_2.mp3", linePath + String.format("cn/%03d.mp3", terminal), commonPath + "cn_start_1.mp3", linePath + String.format("cn/%03d.mp3", stationLevel), commonPath + "cn_start_2.mp3", commonPath + "sh_start_1.mp3", linePath + String.format("sh/%03d.mp3", stationLevel), commonPath + "sh_start_2.mp3", commonPath + "en_1.mp3", linePath + String.format("en/%03d.mp3", stationLevel), commonPath + "cn_start_3.mp3", commonPath + "sh_start_3.mp3"); | ||
| 1185 | + List<String> inputPaths = new ArrayList<>(); | ||
| 1186 | + for (String path : arr) { | ||
| 1187 | + for (String lang : languages) { | ||
| 1188 | + if (path.indexOf(lang) > -1) { | ||
| 1189 | + inputPaths.add(path); | ||
| 1190 | + break; | ||
| 1191 | + } | ||
| 1192 | + } | ||
| 1193 | + } | ||
| 1194 | + AudioOperationUtils.merge(inputPaths, String.format("%s%03da%s-%03d-%s-Start.mp3", linePath, seq, direction == 0 ? "u" : "d", direction == 0 ? stationLevel : terminal - stationLevel + 1, direction == 0 ? "Up" : "Dn")); | ||
| 1195 | + } | ||
| 1196 | + | ||
| 1197 | + private void mergeNormalStart(String lineId, int seq, int stationLevel, int direction, int terminal, Set<String> languages) throws Exception { | ||
| 1198 | + String linePath = String.format(linePathPattern, lineId); | ||
| 1199 | + List<String> arr = Arrays.asList(commonPath + "cn_start.mp3", linePath + String.format("cn/%03d.mp3", stationLevel), commonPath + "cn_start_2.mp3", commonPath + "sh_start_1.mp3", linePath + String.format("sh/%03d.mp3", stationLevel), commonPath + "sh_start_2.mp3", commonPath + "en_1.mp3", linePath + String.format("en/%03d.mp3", stationLevel), commonPath + "cn_start_3.mp3", commonPath + "sh_start_3.mp3"); | ||
| 1200 | + List<String> inputPaths = new ArrayList<>(); | ||
| 1201 | + for (String path : arr) { | ||
| 1202 | + for (String lang : languages) { | ||
| 1203 | + if (path.indexOf(lang) > -1) { | ||
| 1204 | + inputPaths.add(path); | ||
| 1205 | + break; | ||
| 1206 | + } | ||
| 1207 | + } | ||
| 1208 | + } | ||
| 1209 | + AudioOperationUtils.merge(inputPaths, String.format("%s%03da%s-%03d-%s-Start.mp3", linePath, seq, direction == 0 ? "u" : "d", direction == 0 ? stationLevel : terminal - stationLevel + 1, direction == 0 ? "Up" : "Dn")); | ||
| 1210 | + } | ||
| 1211 | + | ||
| 1212 | + private void mergeNormalArrive(String lineId, int seq, int stationLevel, int direction, int terminal, Set<String> languages) throws Exception { | ||
| 1213 | + String linePath = String.format(linePathPattern, lineId); | ||
| 1214 | + List<String> arr = new ArrayList<>(Arrays.asList(commonPath + "cn_arrive.mp3", linePath + String.format("cn/%03d.mp3", stationLevel), commonPath + "cn_arrive_1.mp3", linePath + String.format("sh/%03d.mp3", stationLevel), commonPath + "sh_arrive_1.mp3", commonPath + "en_2.mp3", linePath + String.format("en/%03d.mp3", stationLevel))); | ||
| 1215 | + List<String> inputPaths = new ArrayList<>(); | ||
| 1216 | + if (languages.contains("sh")) { | ||
| 1217 | + for (int i = 0;i < 3;i++) { | ||
| 1218 | + arr.add(linePath + String.format("cn/%03d.mp3", 0)); | ||
| 1219 | + arr.add(commonPath + "cn_origin_2.mp3"); | ||
| 1220 | + arr.add(linePath + String.format("cn/%03d.mp3", terminal)); | ||
| 1221 | + arr.add(linePath + String.format("sh/%03d.mp3", 0)); | ||
| 1222 | + arr.add(commonPath + "sh_origin_2.mp3"); | ||
| 1223 | + arr.add(linePath + String.format("sh/%03d.mp3", terminal)); | ||
| 1224 | + } | ||
| 1225 | + } else { | ||
| 1226 | + arr.add(linePath + String.format("cn/%03d.mp3", 0)); | ||
| 1227 | + arr.add(commonPath + "cn_origin_2.mp3"); | ||
| 1228 | + arr.add(linePath + String.format("cn/%03d.mp3", terminal)); | ||
| 1229 | + } | ||
| 1230 | + for (String path : arr) { | ||
| 1231 | + for (String lang : languages) { | ||
| 1232 | + if (path.indexOf(lang) > -1) { | ||
| 1233 | + inputPaths.add(path); | ||
| 1234 | + break; | ||
| 1235 | + } | ||
| 1236 | + } | ||
| 1237 | + } | ||
| 1238 | + AudioOperationUtils.merge(inputPaths, String.format("%s%03db%s-%03d-%s-Arrive.mp3", linePath, seq, direction == 0 ? "u" : "d", direction == 0 ? stationLevel : terminal - stationLevel + 1, direction == 0 ? "Up" : "Dn")); | ||
| 1239 | + } | ||
| 1240 | + | ||
| 1241 | + private void mergeTerminalArrive(String lineId, int seq, int stationLevel, int direction, int terminal, Set<String> languages) throws Exception { | ||
| 1242 | + String linePath = String.format(linePathPattern, lineId); | ||
| 1243 | + List<String> arr = Arrays.asList(commonPath + "cn_terminal.mp3", linePath + String.format("cn/%03d.mp3", stationLevel), commonPath + "cn_arrive_1.mp3", commonPath + "sh_terminal.mp3", linePath + String.format("sh/%03d.mp3", stationLevel), commonPath + "sh_arrive_1.mp3", commonPath + "en_3.mp3", linePath + String.format("en/%03d.mp3", stationLevel), commonPath + "terminal_music.mp3"); | ||
| 1244 | + List<String> inputPaths = new ArrayList<>(); | ||
| 1245 | + for (String path : arr) { | ||
| 1246 | + for (String lang : languages) { | ||
| 1247 | + if (path.indexOf(lang) > -1 || path.indexOf("terminal_music") > -1) { | ||
| 1248 | + inputPaths.add(path); | ||
| 1249 | + break; | ||
| 1250 | + } | ||
| 1251 | + } | ||
| 1252 | + } | ||
| 1253 | + AudioOperationUtils.merge(inputPaths, String.format("%s%03db%s-%03d-%s-Arrive.mp3", linePath, seq, direction == 0 ? "u" : "d", direction == 0 ? stationLevel : terminal - stationLevel + 1, direction == 0 ? "Up" : "Dn")); | ||
| 1254 | + } | ||
| 1255 | + | ||
| 1256 | + private void description() { | ||
| 1257 | + // Next stop is (en_1.mp3) | ||
| 1258 | + // We are arrival at (en_2.mp3) | ||
| 1259 | + // We are arrival at the terminal (en_3.mp3) | ||
| 1260 | + // 叮咚+欢迎乘坐 (cn_origin_1.mp3) | ||
| 1261 | + // 公交车方向 (cn_origin_2.mp3) | ||
| 1262 | + // 叮咚+车辆起步请拉好扶手投币后请配合朝里走下一站 (cn_start.mp3) | ||
| 1263 | + // 下一站 (cn_start_1.mp3) | ||
| 1264 | + // 请准备从后门下车 (cn_start_2.mp3) | ||
| 1265 | + // 乘客们请给需要帮助的乘客让个座谢谢 (cn_start_3.mp3) | ||
| 1266 | + // 叮咚+车辆进站请注意安全 (cn_arrive.mp3) | ||
| 1267 | + // 到了请配合从后门下车开门请当心 (cn_arrive_1.mp3) | ||
| 1268 | + // 叮咚+终点站 (cn_terminal.mp3) | ||
| 1269 | + // 欢迎乘坐(沪) (sh_origin_1.mp3) | ||
| 1270 | + // 公交车方向(沪) (sh_origin_2.mp3) | ||
| 1271 | + // 下一站(沪) (sh_start_1.mp3) | ||
| 1272 | + // 请准备从后门下车 (sh_start_2.mp3) | ||
| 1273 | + // 乘客们请给需要帮助的乘客让个座谢谢(沪) (sh_start_3.mp3) | ||
| 1274 | + // 到了请配合从后门下车开门请当心(沪) (sh_arrive_1.mp3) | ||
| 1275 | + // 终点站(沪) (sh_terminal.mp3) | ||
| 1276 | + // 终点音乐 (terminal_music.mp3) | ||
| 1277 | + } | ||
| 1004 | } | 1278 | } |
src/main/java/com/bsth/util/AudioOperationUtils.java
0 → 100644
| 1 | +package com.bsth.util; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import org.bytedeco.javacv.FFmpegFrameGrabber; | ||
| 5 | +import org.bytedeco.javacv.FFmpegFrameRecorder; | ||
| 6 | +import org.bytedeco.javacv.Frame; | ||
| 7 | + | ||
| 8 | +import java.io.*; | ||
| 9 | +import java.nio.ShortBuffer; | ||
| 10 | +import java.util.ArrayList; | ||
| 11 | +import java.util.List; | ||
| 12 | + | ||
| 13 | +public class AudioOperationUtils { | ||
| 14 | + public static void main(String[] args) throws Exception { | ||
| 15 | +// int duration = 450000; | ||
| 16 | +// double silenceThreshold = -40; // 声音阈值,可以根据需要调整,单位通常是分贝dB | ||
| 17 | +// splitBySilence("D:\\tts.mp3", "D:\\88814\\cn", duration, silenceThreshold); | ||
| 18 | + | ||
| 19 | + List<String> paths = new ArrayList<>(); | ||
| 20 | + paths.add("D:/speech/803111/cn/000.mp3"); | ||
| 21 | + paths.add("D:/speech/803111/cn/001.mp3"); | ||
| 22 | + merge(paths, "D:/speech/803111/results.mp3"); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + public static void merge(List<String> inputPaths, String outputPath) throws Exception { | ||
| 26 | + File file = new File(outputPath); | ||
| 27 | + if (!file.getParentFile().exists()) { | ||
| 28 | + file.getParentFile().mkdirs(); | ||
| 29 | + } | ||
| 30 | + FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(new File(outputPath), 1); | ||
| 31 | + | ||
| 32 | + int i = 0; | ||
| 33 | + Frame frame = null; | ||
| 34 | + for (String inputPath : inputPaths) { | ||
| 35 | + FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputPath); | ||
| 36 | + grabber.start(); | ||
| 37 | + if (i == 0) { | ||
| 38 | + recorder.setAudioCodec(grabber.getAudioCodec()); | ||
| 39 | + recorder.setFrameRate(grabber.getFrameRate()); | ||
| 40 | + recorder.setFormat(grabber.getFormat()); | ||
| 41 | + recorder.start(); | ||
| 42 | + } | ||
| 43 | + while ((frame = grabber.grabSamples()) != null) { | ||
| 44 | + recorder.record(frame); | ||
| 45 | + } | ||
| 46 | + grabber.stop(); | ||
| 47 | + grabber.close(); | ||
| 48 | + i++; | ||
| 49 | + } | ||
| 50 | + recorder.stop(); | ||
| 51 | + recorder.close(); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + public static void splitBySilence(String inputPath, String outputPath, int duration, double silenceThreshold) throws Exception { | ||
| 55 | + File file = new File(outputPath); | ||
| 56 | + if (!file.exists()) { | ||
| 57 | + file.mkdirs(); | ||
| 58 | + } | ||
| 59 | + boolean isSilent = false; | ||
| 60 | + FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputPath); | ||
| 61 | + grabber.start(); | ||
| 62 | + Frame frame = null; | ||
| 63 | + List<SilenceInfo> silenceInfos = new ArrayList<>(); | ||
| 64 | + long start = 0, end = 0; | ||
| 65 | + while((frame = grabber.grabSamples()) != null) { | ||
| 66 | + ShortBuffer buffer = (ShortBuffer) frame.samples[0]; | ||
| 67 | + double energy = 0; | ||
| 68 | + while (buffer.hasRemaining()) { | ||
| 69 | + short sample = buffer.get(); | ||
| 70 | + energy += sample * sample; | ||
| 71 | + } | ||
| 72 | + energy /= buffer.capacity(); | ||
| 73 | + double db = 20 * Math.log10(Math.sqrt(energy)); | ||
| 74 | + if (db < silenceThreshold) { | ||
| 75 | + if (!isSilent && start == 0) { | ||
| 76 | + isSilent = true; | ||
| 77 | + start = frame.timestamp; | ||
| 78 | + } | ||
| 79 | + } else { | ||
| 80 | + if (start != 0 && frame.timestamp - start >= duration) { | ||
| 81 | + SilenceInfo info = new SilenceInfo(end, start); | ||
| 82 | + silenceInfos.add(info); | ||
| 83 | + end = frame.timestamp; | ||
| 84 | + } | ||
| 85 | + isSilent = false; | ||
| 86 | + start = 0; | ||
| 87 | + } | ||
| 88 | + } | ||
| 89 | + if (silenceInfos.size() > 0) { | ||
| 90 | + SilenceInfo info = new SilenceInfo(end, grabber.getLengthInTime()); | ||
| 91 | + silenceInfos.add(info); | ||
| 92 | + } | ||
| 93 | + grabber.stop(); | ||
| 94 | + grabber.close(); | ||
| 95 | + grabber = new FFmpegFrameGrabber(inputPath); | ||
| 96 | + grabber.start(); | ||
| 97 | + int idx = 0; | ||
| 98 | + boolean flag = false; | ||
| 99 | + FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(new File(String.format("%s%s%03d.mp3", outputPath, File.separator, idx)), 1); | ||
| 100 | + recorder.setAudioCodec(grabber.getAudioCodec()); | ||
| 101 | + recorder.setFrameRate(grabber.getFrameRate()); | ||
| 102 | + recorder.setFormat(grabber.getFormat()); | ||
| 103 | + recorder.start(); | ||
| 104 | + SilenceInfo info = silenceInfos.get(idx); | ||
| 105 | + while ((frame = grabber.grabSamples()) != null) { | ||
| 106 | + if (idx < silenceInfos.size()) { | ||
| 107 | + if (frame.timestamp >= info.start && frame.timestamp <= info.end) { | ||
| 108 | + recorder.record(frame); | ||
| 109 | + flag = false; | ||
| 110 | + } else { | ||
| 111 | + if (!flag) { | ||
| 112 | + flag = true; | ||
| 113 | + recorder.stop(); | ||
| 114 | + recorder.close(); | ||
| 115 | + idx++; | ||
| 116 | + info = silenceInfos.get(idx); | ||
| 117 | + recorder = new FFmpegFrameRecorder(new File(String.format("%s%s%03d.mp3", outputPath, File.separator, idx)), 1); | ||
| 118 | + recorder.start(); | ||
| 119 | + recorder.setAudioCodec(grabber.getAudioCodec()); | ||
| 120 | + recorder.setFrameRate(grabber.getFrameRate()); | ||
| 121 | + recorder.setFormat(grabber.getFormat()); | ||
| 122 | + } | ||
| 123 | + } | ||
| 124 | + } | ||
| 125 | + } | ||
| 126 | + if (recorder != null) { | ||
| 127 | + recorder.stop(); | ||
| 128 | + recorder.close(); | ||
| 129 | + } | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + public final static class SilenceInfo { | ||
| 133 | + | ||
| 134 | + private long start; | ||
| 135 | + | ||
| 136 | + private long end; | ||
| 137 | + | ||
| 138 | + public SilenceInfo() {} | ||
| 139 | + | ||
| 140 | + public SilenceInfo(long start, long end) { | ||
| 141 | + this.start = start; | ||
| 142 | + this.end = end; | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + public long getStart() { | ||
| 146 | + return start; | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + public void setStart(long start) { | ||
| 150 | + this.start = start; | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + public long getEnd() { | ||
| 154 | + return end; | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + public void setEnd(long end) { | ||
| 158 | + this.end = end; | ||
| 159 | + } | ||
| 160 | + } | ||
| 161 | +} |
src/main/java/com/bsth/util/IFlyUtils.java
0 → 100644
| 1 | +package com.bsth.util; | ||
| 2 | + | ||
| 3 | +import com.bsth.entity.speech.SpeechRequest; | ||
| 4 | +import com.bsth.entity.speech.SpeechResponse; | ||
| 5 | +import com.fasterxml.jackson.core.JsonProcessingException; | ||
| 6 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 7 | +import org.java_websocket.client.WebSocketClient; | ||
| 8 | +import org.java_websocket.handshake.ServerHandshake; | ||
| 9 | +import org.slf4j.Logger; | ||
| 10 | +import org.slf4j.LoggerFactory; | ||
| 11 | + | ||
| 12 | +import javax.crypto.Mac; | ||
| 13 | +import javax.crypto.spec.SecretKeySpec; | ||
| 14 | +import java.io.*; | ||
| 15 | +import java.net.URI; | ||
| 16 | +import java.net.URL; | ||
| 17 | +import java.net.URLEncoder; | ||
| 18 | +import java.nio.charset.StandardCharsets; | ||
| 19 | +import java.text.SimpleDateFormat; | ||
| 20 | +import java.util.*; | ||
| 21 | + | ||
| 22 | +public class IFlyUtils { | ||
| 23 | + | ||
| 24 | + private final static ObjectMapper mapper = new ObjectMapper(); | ||
| 25 | + | ||
| 26 | + private final static Logger log = LoggerFactory.getLogger(IFlyUtils.class); | ||
| 27 | + | ||
| 28 | + private final static String apiKey = "46780e6779b6b1ba93503f24f097b771"; | ||
| 29 | + | ||
| 30 | + private final static String apiSecret = "ZWFjNzkzMTkzNzI3YmMzMTgwMWUzMWE0"; | ||
| 31 | + | ||
| 32 | + private final static String appId = "b4b21ad4"; | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 生成普通话语音 | ||
| 36 | + * text以","进行分割 | ||
| 37 | + * @param text | ||
| 38 | + */ | ||
| 39 | + public static void textToSpeechCn(String text, String outputPath) throws Exception { | ||
| 40 | + File file = new File(outputPath); | ||
| 41 | + if (!file.getParentFile().exists()) { | ||
| 42 | + file.getParentFile().mkdirs(); | ||
| 43 | + } | ||
| 44 | + String wsUrl = getAuthUrl("https://tts-api.xfyun.cn/v2/tts", apiKey, apiSecret).replace("https://", "wss://"); | ||
| 45 | + SpeechRequest request = new SpeechRequest(); | ||
| 46 | + request.getCommon().put("app_id", appId); | ||
| 47 | + request.getBusiness().put("aue", "lame"); | ||
| 48 | + request.getBusiness().put("sfl", 1); | ||
| 49 | + request.getBusiness().put("vcn", "x4_lingxiaoshan_profnews"); | ||
| 50 | + request.getData().put("text", Base64.getEncoder().encodeToString(text.replace(",", "[p1000]").getBytes("GBK"))); | ||
| 51 | + request.getData().put("status", 2); | ||
| 52 | + websocketWork(wsUrl, request, new FileOutputStream(file)); | ||
| 53 | + while (!request.isCompleted()) { | ||
| 54 | + Thread.sleep(500); | ||
| 55 | + } | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * 生成上海话语音 | ||
| 60 | + * text以","进行分割 | ||
| 61 | + * @param text | ||
| 62 | + */ | ||
| 63 | + public static void textToSpeechSh(String text, String outputPath) throws Exception { | ||
| 64 | + String wsUrl = getAuthUrl("https://tts-api.xfyun.cn/v2/tts", apiKey, apiSecret).replace("https://", "wss://"); | ||
| 65 | + SpeechRequest request = new SpeechRequest(); | ||
| 66 | + request.getCommon().put("app_id", appId); | ||
| 67 | + request.getBusiness().put("aue", "lame"); | ||
| 68 | + request.getBusiness().put("sfl", 1); | ||
| 69 | + request.getBusiness().put("vcn", "x3_ziling"); | ||
| 70 | + request.getData().put("text", Base64.getEncoder().encodeToString(text.replace(",", "[p1000]").getBytes("GBK"))); | ||
| 71 | + request.getData().put("status", 2); | ||
| 72 | + websocketWork(wsUrl, request, new FileOutputStream(outputPath)); | ||
| 73 | + while (!request.isCompleted()) { | ||
| 74 | + Thread.sleep(500); | ||
| 75 | + } | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + /** | ||
| 79 | + * 生成英语语音 | ||
| 80 | + * text以","进行分割 | ||
| 81 | + * @param text | ||
| 82 | + */ | ||
| 83 | + public static void textToSpeechEn(String text, String outputPath) throws Exception { | ||
| 84 | + String wsUrl = getAuthUrl("https://tts-api.xfyun.cn/v2/tts", apiKey, apiSecret).replace("https://", "wss://"); | ||
| 85 | + SpeechRequest request = new SpeechRequest(); | ||
| 86 | + request.getCommon().put("app_id", appId); | ||
| 87 | + request.getBusiness().put("aue", "lame"); | ||
| 88 | + request.getBusiness().put("sfl", 1); | ||
| 89 | + request.getBusiness().put("vcn", "x4_enus_luna_assist"); | ||
| 90 | + request.getData().put("text", Base64.getEncoder().encodeToString(text.replace(",", "[p1000]").getBytes(StandardCharsets.UTF_8))); | ||
| 91 | + request.getData().put("status", 2); | ||
| 92 | + websocketWork(wsUrl, request, new FileOutputStream(outputPath)); | ||
| 93 | + while (!request.isCompleted()) { | ||
| 94 | + Thread.sleep(500); | ||
| 95 | + } | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + public static void websocketWork(String wsUrl, SpeechRequest request, OutputStream out) { | ||
| 99 | + try { | ||
| 100 | + URI uri = new URI(wsUrl); | ||
| 101 | + WebSocketClient webSocketClient = new WebSocketClient(uri) { | ||
| 102 | + @Override | ||
| 103 | + public void onOpen(ServerHandshake serverHandshake) { | ||
| 104 | + try { | ||
| 105 | + this.send(mapper.writeValueAsString(request)); | ||
| 106 | + } catch (JsonProcessingException e) { | ||
| 107 | + throw new RuntimeException(e); | ||
| 108 | + } | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + @Override | ||
| 112 | + public void onMessage(String text) { | ||
| 113 | + try { | ||
| 114 | + SpeechResponse response = mapper.readValue(text, SpeechResponse.class); | ||
| 115 | + log.info("response: {}", response); | ||
| 116 | + if (response.getCode() != 0) { | ||
| 117 | + log.error("在线语音合成发生错误"); | ||
| 118 | + } | ||
| 119 | + if (response.getData() != null) { | ||
| 120 | + byte[] bytes = Base64.getDecoder().decode(response.getData().getAudio()); | ||
| 121 | + out.write(bytes); | ||
| 122 | + out.flush(); | ||
| 123 | + if (response.getData().getStatus() == 2) { | ||
| 124 | + request.setCompleted(true); | ||
| 125 | + out.close(); | ||
| 126 | + } | ||
| 127 | + } | ||
| 128 | + } catch (IOException e) { | ||
| 129 | + throw new RuntimeException(e); | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + @Override | ||
| 134 | + public void onClose(int i, String s, boolean b) { | ||
| 135 | + System.out.println("ws链接已关闭,本次请求完成..."); | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + @Override | ||
| 139 | + public void onError(Exception e) { | ||
| 140 | + log.error("发生错误", e); | ||
| 141 | + } | ||
| 142 | + }; | ||
| 143 | + webSocketClient.connect(); | ||
| 144 | + } catch (Exception e) { | ||
| 145 | + log.error("", e); | ||
| 146 | + } | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + /** | ||
| 150 | + * 讯飞语音合成鉴权 | ||
| 151 | + * @param hostUrl | ||
| 152 | + * @param apiKey | ||
| 153 | + * @param apiSecret | ||
| 154 | + * @return | ||
| 155 | + * @throws Exception | ||
| 156 | + */ | ||
| 157 | + public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception { | ||
| 158 | + URL url = new URL(hostUrl); | ||
| 159 | + // 时间 | ||
| 160 | + SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); | ||
| 161 | + format.setTimeZone(TimeZone.getTimeZone("GMT")); | ||
| 162 | + String date = format.format(new Date()); | ||
| 163 | + // 拼接 | ||
| 164 | + String preStr = "host: " + url.getHost() + "\n" + | ||
| 165 | + "date: " + date + "\n" + | ||
| 166 | + "GET " + url.getPath() + " HTTP/1.1"; | ||
| 167 | + // SHA256加密 | ||
| 168 | + Mac mac = Mac.getInstance("hmacsha256"); | ||
| 169 | + SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256"); | ||
| 170 | + mac.init(spec); | ||
| 171 | + byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8)); | ||
| 172 | + // Base64加密 | ||
| 173 | + String sha = Base64.getEncoder().encodeToString(hexDigits); | ||
| 174 | + // 拼接 | ||
| 175 | + String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha); | ||
| 176 | + StringBuilder sb = new StringBuilder(hostUrl); | ||
| 177 | + sb.append("?authorization=").append(Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))) | ||
| 178 | + .append("&date=").append(URLEncoder.encode(date)) | ||
| 179 | + .append("&host=").append(URLEncoder.encode(url.getHost())); | ||
| 180 | +// // 拼接地址 | ||
| 181 | +// HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().// | ||
| 182 | +// addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).// | ||
| 183 | +// addQueryParameter("date", date).// | ||
| 184 | +// addQueryParameter("host", url.getHost()).// | ||
| 185 | +// build(); | ||
| 186 | + | ||
| 187 | + return sb.toString(); | ||
| 188 | + } | ||
| 189 | +} |
src/main/resources/application-cloud.properties
| @@ -73,4 +73,7 @@ sso.enabled= false | @@ -73,4 +73,7 @@ sso.enabled= false | ||
| 73 | sso.systemcode = SYS0023 | 73 | sso.systemcode = SYS0023 |
| 74 | sso.http.url.login= https://127.0.0.1/portal/index.html#/login | 74 | sso.http.url.login= https://127.0.0.1/portal/index.html#/login |
| 75 | sso.http.url.logout= https://127.0.0.1/information/api/v1/logout | 75 | sso.http.url.logout= https://127.0.0.1/information/api/v1/logout |
| 76 | -sso.http.url.auth= https://127.0.0.1/information/authenticate/authorityAuthentication | ||
| 77 | \ No newline at end of file | 76 | \ No newline at end of file |
| 77 | +sso.http.url.auth= https://127.0.0.1/information/authenticate/authorityAuthentication | ||
| 78 | + | ||
| 79 | +path.speech.common = /data/control/speech/common/ | ||
| 80 | +path.speech.line = /data/control/speech/%s/ | ||
| 78 | \ No newline at end of file | 81 | \ No newline at end of file |
src/main/resources/application-dev.properties
| @@ -71,4 +71,7 @@ sso.enabled= false | @@ -71,4 +71,7 @@ sso.enabled= false | ||
| 71 | sso.systemcode = SYS0019 | 71 | sso.systemcode = SYS0019 |
| 72 | sso.http.url.login= http://180.169.154.251:28090/portal/index.html#/login | 72 | sso.http.url.login= http://180.169.154.251:28090/portal/index.html#/login |
| 73 | sso.http.url.logout= http://180.169.154.251:18080/information/api/v1/logout | 73 | sso.http.url.logout= http://180.169.154.251:18080/information/api/v1/logout |
| 74 | -sso.http.url.auth= http://180.169.154.251:18080/information/authenticate/authorityAuthentication | ||
| 75 | \ No newline at end of file | 74 | \ No newline at end of file |
| 75 | +sso.http.url.auth= http://180.169.154.251:18080/information/authenticate/authorityAuthentication | ||
| 76 | + | ||
| 77 | +path.speech.common = D:/speech/common/ | ||
| 78 | +path.speech.line = D:/speech/%s/ | ||
| 76 | \ No newline at end of file | 79 | \ No newline at end of file |
src/main/resources/application-test.properties
| @@ -71,4 +71,7 @@ sso.enabled= false | @@ -71,4 +71,7 @@ sso.enabled= false | ||
| 71 | sso.systemcode = SYS0023 | 71 | sso.systemcode = SYS0023 |
| 72 | sso.http.url.login= https://112.64.45.51/portal/index.html#/login | 72 | sso.http.url.login= https://112.64.45.51/portal/index.html#/login |
| 73 | sso.http.url.logout= https://112.64.45.51/information/api/v1/logout | 73 | sso.http.url.logout= https://112.64.45.51/information/api/v1/logout |
| 74 | -sso.http.url.auth= https://112.64.45.51/information/authenticate/authorityAuthentication | ||
| 75 | \ No newline at end of file | 74 | \ No newline at end of file |
| 75 | +sso.http.url.auth= https://112.64.45.51/information/authenticate/authorityAuthentication | ||
| 76 | + | ||
| 77 | +path.speech.common = /data/control/speech/common/ | ||
| 78 | +path.speech.line = /data/control/speech/%s/ | ||
| 76 | \ No newline at end of file | 79 | \ No newline at end of file |
src/main/resources/static/pages/base/station/js/station-list-table.js
| @@ -13,27 +13,40 @@ | @@ -13,27 +13,40 @@ | ||
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | (function(){ | 15 | (function(){ |
| 16 | + var code2company = {}, cgsbm = []; | ||
| 16 | function getComp(cb) { | 17 | function getComp(cb) { |
| 17 | $.get('/user/companyData',null,function(rs) { | 18 | $.get('/user/companyData',null,function(rs) { |
| 18 | return cb && cb(rs); | 19 | return cb && cb(rs); |
| 19 | }); | 20 | }); |
| 20 | } | 21 | } |
| 21 | - function getCompInfo(cb) { | ||
| 22 | - // get请求获取公司 | ||
| 23 | - $get('/business/all', {upCode_eq: '88'}, function(gs_d){ | ||
| 24 | - return cb && cb(gs_d); | ||
| 25 | - }); | ||
| 26 | - } | ||
| 27 | - function gsdmTogsName(gsD,code) { | ||
| 28 | - var rsStr = ''; | ||
| 29 | - for(var s = 0 ; s < gsD.length; s++) { | ||
| 30 | - if(gsD[s].businessCode == code) { | ||
| 31 | - rsStr = rsStr + '(' + gsD[s].businessName.replace('公司','') + ')'; | ||
| 32 | - break; | 22 | + $.ajaxSettings.async = false; |
| 23 | + getComp(function(rs) { | ||
| 24 | + var html = new Array('<option value="">请选择</option>'); | ||
| 25 | + for (var i = 0;i < rs.length;i++) { | ||
| 26 | + var item = rs[i], children = item.children; | ||
| 27 | + var company = {}; | ||
| 28 | + company.name = item.companyName; | ||
| 29 | + company.children = children; | ||
| 30 | + for (var j = 0;j < children.length;j++) { | ||
| 31 | + cgsbm.push(item.companyCode + '_' + children[j].code); | ||
| 33 | } | 32 | } |
| 33 | + code2company[item.companyCode] = company; | ||
| 34 | + html.push('<option value="', item.companyCode, '">', item.companyName, '</option>'); | ||
| 34 | } | 35 | } |
| 35 | - return rsStr; | ||
| 36 | - } | 36 | + |
| 37 | + $('#companySelect').html(html.join('')); | ||
| 38 | + $('#companySelect').on('change', function() { | ||
| 39 | + var companyCode = $(this).val(), html = ['<option value="">请选择</option>']; | ||
| 40 | + if (companyCode) { | ||
| 41 | + for (var i = 0;i < code2company[companyCode].children.length;i++) { | ||
| 42 | + var item = code2company[companyCode].children[i]; | ||
| 43 | + html.push('<option value="', item.code, '">', item.name, '</option>'); | ||
| 44 | + } | ||
| 45 | + } | ||
| 46 | + $('#brancheCompanySelect').html(html.join('')); | ||
| 47 | + }).trigger('change'); | ||
| 48 | + }) | ||
| 49 | + $.ajaxSettings.async = true; | ||
| 37 | function splitxlName(str) { | 50 | function splitxlName(str) { |
| 38 | var rsStr = ''; | 51 | var rsStr = ''; |
| 39 | if(str) { | 52 | if(str) { |
| @@ -46,9 +59,9 @@ | @@ -46,9 +59,9 @@ | ||
| 46 | if (!$('body').hasClass('page-sidebar-closed')) {$('.menu-toggler.sidebar-toggler').click();} | 59 | if (!$('body').hasClass('page-sidebar-closed')) {$('.menu-toggler.sidebar-toggler').click();} |
| 47 | /** page : 当前页 initPag : */ | 60 | /** page : 当前页 initPag : */ |
| 48 | var page = 0,initPag; | 61 | var page = 0,initPag; |
| 49 | - | 62 | + |
| 50 | /** 表格数据分页加载 */ | 63 | /** 表格数据分页加载 */ |
| 51 | - loadTableDate(null,true); | 64 | + loadTableDate(null, true); |
| 52 | 65 | ||
| 53 | /** 重置按钮事件 */ | 66 | /** 重置按钮事件 */ |
| 54 | $('tr.filter .filter-cancel').on('click',function(){ | 67 | $('tr.filter .filter-cancel').on('click',function(){ |
| @@ -57,7 +70,7 @@ | @@ -57,7 +70,7 @@ | ||
| 57 | $('.tipso-animation').tipso('hide'); | 70 | $('.tipso-animation').tipso('hide'); |
| 58 | storage.setItem('xlName_AgursData',''); | 71 | storage.setItem('xlName_AgursData',''); |
| 59 | // 重新加载表格数据 | 72 | // 重新加载表格数据 |
| 60 | - loadTableDate(null,true); | 73 | + loadTableDate(null, true); |
| 61 | }); | 74 | }); |
| 62 | 75 | ||
| 63 | /** 搜索按钮事件 */ | 76 | /** 搜索按钮事件 */ |
| @@ -109,6 +122,7 @@ | @@ -109,6 +122,7 @@ | ||
| 109 | } | 122 | } |
| 110 | } | 123 | } |
| 111 | }); | 124 | }); |
| 125 | + | ||
| 112 | return params; | 126 | return params; |
| 113 | } | 127 | } |
| 114 | 128 | ||
| @@ -132,10 +146,12 @@ | @@ -132,10 +146,12 @@ | ||
| 132 | params['direction'] = 'ASC'; | 146 | params['direction'] = 'ASC'; |
| 133 | // 记录当前页数 | 147 | // 记录当前页数 |
| 134 | params['page'] = page; | 148 | params['page'] = page; |
| 149 | + params['cgsbm_in'] = cgsbm.join(); | ||
| 135 | // 弹出正在加载层 | 150 | // 弹出正在加载层 |
| 136 | var i = layer.load(2); | 151 | var i = layer.load(2); |
| 137 | // 异步请求获取表格数据 | 152 | // 异步请求获取表格数据 |
| 138 | $.get('/station',params,function(result){ | 153 | $.get('/station',params,function(result){ |
| 154 | + debugger | ||
| 139 | var data = {page: page, list: result.content}; | 155 | var data = {page: page, list: result.content}; |
| 140 | // 把数据填充到模版中 | 156 | // 把数据填充到模版中 |
| 141 | var tbodyHtml = template('station_datatable_template', data); | 157 | var tbodyHtml = template('station_datatable_template', data); |
src/main/resources/static/pages/base/station/list.html
| @@ -35,12 +35,14 @@ | @@ -35,12 +35,14 @@ | ||
| 35 | <th width="6%">序号</th> | 35 | <th width="6%">序号</th> |
| 36 | <th width="12%">站点名称</th> | 36 | <th width="12%">站点名称</th> |
| 37 | <th width="12%">站点编码</th> | 37 | <th width="12%">站点编码</th> |
| 38 | + <th width="8%">所属公司</th> | ||
| 39 | + <th width="9%">所属分公司</th> | ||
| 38 | <th width="12%">途经线路</th> | 40 | <th width="12%">途经线路</th> |
| 39 | <th width="12%">行业编码</th> | 41 | <th width="12%">行业编码</th> |
| 40 | <th width="12%">东西向</th> | 42 | <th width="12%">东西向</th> |
| 41 | <th width="12%">南北向</th> | 43 | <th width="12%">南北向</th> |
| 42 | - <th width="12%">道路编码</th> | ||
| 43 | - <th width="12%">地址</th> | 44 | + <!--<th width="12%">道路编码</th> |
| 45 | + <th width="12%">地址</th>--> | ||
| 44 | <th width="10%">操作</th> | 46 | <th width="10%">操作</th> |
| 45 | </tr> | 47 | </tr> |
| 46 | <tr role="row" class="filter"> | 48 | <tr role="row" class="filter"> |
| @@ -52,6 +54,12 @@ | @@ -52,6 +54,12 @@ | ||
| 52 | <input type="text" class="form-control form-filter input-sm" id="stationCode" name="stationCode_like"> | 54 | <input type="text" class="form-control form-filter input-sm" id="stationCode" name="stationCode_like"> |
| 53 | </td> | 55 | </td> |
| 54 | <td> | 56 | <td> |
| 57 | + <select name="company_eq" class="form-control" id="companySelect"></select> | ||
| 58 | + </td> | ||
| 59 | + <td> | ||
| 60 | + <select name="brancheCompany_eq" class="form-control" id="brancheCompanySelect"></select> | ||
| 61 | + </td> | ||
| 62 | + <td> | ||
| 55 | <input type="text" class="form-control form-filter input-sm" id="passLines" name="passLines_like"> | 63 | <input type="text" class="form-control form-filter input-sm" id="passLines" name="passLines_like"> |
| 56 | </td> | 64 | </td> |
| 57 | <td> | 65 | <td> |
| @@ -71,12 +79,12 @@ | @@ -71,12 +79,12 @@ | ||
| 71 | <option value="1">北->南</option> | 79 | <option value="1">北->南</option> |
| 72 | </select> | 80 | </select> |
| 73 | </td> | 81 | </td> |
| 74 | - <td> | 82 | + <!--<td> |
| 75 | <input type="text" class="form-control form-filter input-sm" id="roadCoding" name="roadCoding_eq"> | 83 | <input type="text" class="form-control form-filter input-sm" id="roadCoding" name="roadCoding_eq"> |
| 76 | </td> | 84 | </td> |
| 77 | <td> | 85 | <td> |
| 78 | <input type="text" class="form-control form-filter input-sm" id="address" name="address_eq"> | 86 | <input type="text" class="form-control form-filter input-sm" id="address" name="address_eq"> |
| 79 | - </td> | 87 | + </td>--> |
| 80 | <td> | 88 | <td> |
| 81 | <button class="btn btn-sm green btn-outline filter-submit margin-bottom" > | 89 | <button class="btn btn-sm green btn-outline filter-submit margin-bottom" > |
| 82 | <i class="fa fa-search"></i> 搜索 | 90 | <i class="fa fa-search"></i> 搜索 |
src/main/resources/static/real_control_v2/fragments/north/nav/dvr.html
| @@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
| 7 | <div style="display: flex;justify-content:center;align-items: center;height: 603px;"> | 7 | <div style="display: flex;justify-content:center;align-items: center;height: 603px;"> |
| 8 | <video id="dvr" style="width: 100%;height: 100%"/> | 8 | <video id="dvr" style="width: 100%;height: 100%"/> |
| 9 | </div> | 9 | </div> |
| 10 | - <div class="uk-grid" style="margin-left: 0px; margin-top: 20px;"> | 10 | + <div class="uk-grid" style="margin-left: 0px; margin-top: 20px;" id="ruiming"> |
| 11 | <div class="uk-width uk-width-dvr"> | 11 | <div class="uk-width uk-width-dvr"> |
| 12 | <div class="uk-panel uk-panel-box uk-panel-box-dvr uk-width-dvr-checked"> | 12 | <div class="uk-panel uk-panel-box uk-panel-box-dvr uk-width-dvr-checked"> |
| 13 | <span data-channel="1">ADAS</span> | 13 | <span data-channel="1">ADAS</span> |
| @@ -54,12 +54,59 @@ | @@ -54,12 +54,59 @@ | ||
| 54 | </div> | 54 | </div> |
| 55 | </div> | 55 | </div> |
| 56 | </div> | 56 | </div> |
| 57 | + <div class="uk-grid" style="margin-left: 0px; margin-top: 20px; display: none;" id="tuohua"> | ||
| 58 | + <div class="uk-width uk-width-dvr"> | ||
| 59 | + <div class="uk-panel uk-panel-box uk-panel-box-dvr uk-width-dvr-checked"> | ||
| 60 | + <span data-channel="2-1">ADAS</span> | ||
| 61 | + </div> | ||
| 62 | + </div> | ||
| 63 | + <div class="uk-width uk-width-dvr"> | ||
| 64 | + <div class="uk-panel uk-panel-box uk-panel-box-dvr"> | ||
| 65 | + <span data-channel="2-2">DSM</span> | ||
| 66 | + </div> | ||
| 67 | + </div> | ||
| 68 | + <div class="uk-width uk-width-dvr"> | ||
| 69 | + <div class="uk-panel uk-panel-box uk-panel-box-dvr"> | ||
| 70 | + <span data-channel="1-1">中门</span> | ||
| 71 | + </div> | ||
| 72 | + </div> | ||
| 73 | + <div class="uk-width uk-width-dvr"> | ||
| 74 | + <div class="uk-panel uk-panel-box uk-panel-box-dvr"> | ||
| 75 | + <span data-channel="1-3">车前</span> | ||
| 76 | + </div> | ||
| 77 | + </div> | ||
| 78 | + <div class="uk-width uk-width-dvr"> | ||
| 79 | + <div class="uk-panel uk-panel-box uk-panel-box-dvr"> | ||
| 80 | + <span data-channel="1-4">司机</span> | ||
| 81 | + </div> | ||
| 82 | + </div> | ||
| 83 | + <div class="uk-width uk-width-dvr"> | ||
| 84 | + <div class="uk-panel uk-panel-box uk-panel-box-dvr"> | ||
| 85 | + <span data-channel="1-5">前门</span> | ||
| 86 | + </div> | ||
| 87 | + </div> | ||
| 88 | + <div class="uk-width uk-width-dvr"> | ||
| 89 | + <div class="uk-panel uk-panel-box uk-panel-box-dvr"> | ||
| 90 | + <span data-channel="1-6">前车厢</span> | ||
| 91 | + </div> | ||
| 92 | + </div> | ||
| 93 | + <div class="uk-width uk-width-dvr"> | ||
| 94 | + <div class="uk-panel uk-panel-box uk-panel-box-dvr"> | ||
| 95 | + <span data-channel="1-7">后车厢</span> | ||
| 96 | + </div> | ||
| 97 | + </div> | ||
| 98 | + <div class="uk-width uk-width-dvr"> | ||
| 99 | + <div class="uk-panel uk-panel-box uk-panel-box-dvr"> | ||
| 100 | + <span data-channel="1-8">360</span> | ||
| 101 | + </div> | ||
| 102 | + </div> | ||
| 103 | + </div> | ||
| 57 | </div> | 104 | </div> |
| 58 | <script> | 105 | <script> |
| 59 | (function() { | 106 | (function() { |
| 60 | var player, requesting = false, info; | 107 | var player, requesting = false, info; |
| 61 | $('.uk-panel-box-dvr span').on('click', function() { | 108 | $('.uk-panel-box-dvr span').on('click', function() { |
| 62 | - var channel = $(this).data('channel'); | 109 | + var channel = $(this).data('channel') + '', param = {sim: info.sim, channel: channel}; |
| 63 | if (requesting) { | 110 | if (requesting) { |
| 64 | layer.msg('正在请求播放地址,请等待') | 111 | layer.msg('正在请求播放地址,请等待') |
| 65 | return; | 112 | return; |
| @@ -67,7 +114,12 @@ | @@ -67,7 +114,12 @@ | ||
| 67 | requesting = true; | 114 | requesting = true; |
| 68 | $('.uk-width-dvr-checked').removeClass('uk-width-dvr-checked'); | 115 | $('.uk-width-dvr-checked').removeClass('uk-width-dvr-checked'); |
| 69 | $(this).parent().addClass('uk-width-dvr-checked'); | 116 | $(this).parent().addClass('uk-width-dvr-checked'); |
| 70 | - $.post('/dvr/jt1078', {sim: info.sim, channel: channel}, function(res) { | 117 | + if (channel.indexOf('-') > -1) { |
| 118 | + var no = channel.split('-')[0], channelNum = channel.split('-')[1]; | ||
| 119 | + param.sim = no === '1' ? info.sim : info.sim2; | ||
| 120 | + param.channel = channelNum; | ||
| 121 | + } | ||
| 122 | + $.post('/dvr/jt1078', param, function(res) { | ||
| 71 | requesting = false; | 123 | requesting = false; |
| 72 | if (res.status == 'SUCCESS') { | 124 | if (res.status == 'SUCCESS') { |
| 73 | if (player) { | 125 | if (player) { |
| @@ -90,7 +142,11 @@ | @@ -90,7 +142,11 @@ | ||
| 90 | $('#dvr-modal').on('init', function(e, data) { | 142 | $('#dvr-modal').on('init', function(e, data) { |
| 91 | info = data; | 143 | info = data; |
| 92 | requesting = true; | 144 | requesting = true; |
| 93 | - $.post('/dvr/jt1078', {sim: info.sim, channel: 1}, function(res) { | 145 | + if (info.sim2) { |
| 146 | + $('#ruiming').css('display', 'none'); | ||
| 147 | + $('#tuohua').css('display', 'block'); | ||
| 148 | + } | ||
| 149 | + $.post('/dvr/jt1078', {sim: info.sim2 ? info.sim2 : info.sim, channel: 1}, function(res) { | ||
| 94 | requesting = false; | 150 | requesting = false; |
| 95 | if (res.status == 'SUCCESS') { | 151 | if (res.status == 'SUCCESS') { |
| 96 | player = videojs('dvr', {sources: [{src: res.data['hls']}], autoplay: true}); | 152 | player = videojs('dvr', {sources: [{src: res.data['hls']}], autoplay: true}); |
src/main/resources/static/real_control_v2/mapmonitor/fragments/map_infowindow.html
| @@ -70,7 +70,7 @@ | @@ -70,7 +70,7 @@ | ||
| 70 | {{if expectStopTime!=null}} | 70 | {{if expectStopTime!=null}} |
| 71 | <a href="javascript:;" style="color: #07D;margin-right: 7px;">预计 {{expectStopTime}} 分钟到达终点</a> | 71 | <a href="javascript:;" style="color: #07D;margin-right: 7px;">预计 {{expectStopTime}} 分钟到达终点</a> |
| 72 | {{/if}} | 72 | {{/if}} |
| 73 | - <a href="javascript:;" style="float: left;" onclick="javascript:gb_map_dvr.openDvr({sim: '{{sim}}'})">DVR</a> | 73 | + <a href="javascript:;" style="float: left;" onclick="javascript:gb_map_dvr.openDvr({nbbm: '{{nbbm}}', sim: '{{sim}}', sim2: '{{sim2}}'})">DVR</a> |
| 74 | {{if dvrcode != null}}<a href="javascript:void(0)" style="margin-left: 50px;" >拨打电话</a>{{/if}} | 74 | {{if dvrcode != null}}<a href="javascript:void(0)" style="margin-left: 50px;" >拨打电话</a>{{/if}} |
| 75 | <a href="javascript:;" style="float: right;" onclick="javascript:gb_map_play_back.initParams({deviceId: '{{deviceId}}', nbbm: '{{nbbm}}'});">轨迹回放</a> | 75 | <a href="javascript:;" style="float: right;" onclick="javascript:gb_map_play_back.initParams({deviceId: '{{deviceId}}', nbbm: '{{nbbm}}'});">轨迹回放</a> |
| 76 | </div> | 76 | </div> |