Browse Source

新增项目

zhoufan 1 year ago
commit
c8f66246f4
89 changed files with 7277 additions and 0 deletions
  1. 6 0
      .gitignore
  2. 79 0
      midware-api/pom.xml
  3. 39 0
      midware-api/src/main/java/midware/ApiApplication.java
  4. 79 0
      midware-api/src/main/java/midware/controller/BaseController.java
  5. 182 0
      midware-api/src/main/java/midware/controller/HomeController.java
  6. 50 0
      midware-api/src/main/java/midware/controller/rep/AgentActionController.java
  7. 51 0
      midware-api/src/main/java/midware/controller/rep/AgentStateController.java
  8. 46 0
      midware-api/src/main/java/midware/controller/rep/ChanEventController.java
  9. 81 0
      midware-api/src/main/java/midware/controller/rep/ConfigController.java
  10. 110 0
      midware-api/src/main/java/midware/controller/rep/IvrController.java
  11. 67 0
      midware-api/src/main/java/midware/controller/rep/RecordController.java
  12. 72 0
      midware-api/src/main/java/midware/filter/GlobalExceptionHandler.java
  13. 48 0
      midware-api/src/main/java/midware/filter/ResourcesConfig.java
  14. 10 0
      midware-api/src/main/java/midware/model/AjaxResult.java
  15. 8 0
      midware-api/src/main/java/midware/model/PageResult.java
  16. 46 0
      midware-api/src/main/resources/application-dev.yml
  17. 42 0
      midware-api/src/main/resources/application-production.yml
  18. 32 0
      midware-api/src/main/resources/application.yml
  19. 118 0
      midware-api/src/main/resources/logback.xml
  20. 28 0
      midware-entity/pom.xml
  21. 42 0
      midware-entity/src/main/java/midware/entity/database/rep/AgentAction.java
  22. 36 0
      midware-entity/src/main/java/midware/entity/database/rep/AgentState.java
  23. 31 0
      midware-entity/src/main/java/midware/entity/database/rep/ChanEvent.java
  24. 26 0
      midware-entity/src/main/java/midware/entity/database/rep/Config.java
  25. 61 0
      midware-entity/src/main/java/midware/entity/database/rep/Ivr.java
  26. 90 0
      midware-entity/src/main/java/midware/entity/database/rep/Record.java
  27. 14 0
      midware-entity/src/main/java/midware/entity/input/CodeInput.java
  28. 12 0
      midware-entity/src/main/java/midware/entity/input/PageInput.java
  29. 14 0
      midware-entity/src/main/java/midware/entity/input/rep/IvrInput.java
  30. 18 0
      midware-entity/src/main/java/midware/entity/input/rep/Node.java
  31. 19 0
      midware-entity/src/main/java/midware/entity/input/rep/Path.java
  32. 28 0
      midware-mapper/pom.xml
  33. 9 0
      midware-mapper/src/main/java/midware/mapper/rep/AgentActionMapper.java
  34. 9 0
      midware-mapper/src/main/java/midware/mapper/rep/AgentStateMapper.java
  35. 9 0
      midware-mapper/src/main/java/midware/mapper/rep/ChanEventMapper.java
  36. 9 0
      midware-mapper/src/main/java/midware/mapper/rep/ConfigMapper.java
  37. 9 0
      midware-mapper/src/main/java/midware/mapper/rep/IvrMapper.java
  38. 9 0
      midware-mapper/src/main/java/midware/mapper/rep/RecordMapper.java
  39. 40 0
      midware-service/pom.xml
  40. 234 0
      midware-service/src/main/java/midware/service/BaseServiceImpl.java
  41. 70 0
      midware-service/src/main/java/midware/service/IBaseService.java
  42. 225 0
      midware-service/src/main/java/midware/service/eslclient/EslCommon.java
  43. 150 0
      midware-service/src/main/java/midware/service/eslclient/EslEventListenerCustom.java
  44. 527 0
      midware-service/src/main/java/midware/service/eslclient/EslEventListenerEvent.java
  45. 65 0
      midware-service/src/main/java/midware/service/eslclient/entity/Agent.java
  46. 17 0
      midware-service/src/main/java/midware/service/eslclient/entity/Auth.java
  47. 39 0
      midware-service/src/main/java/midware/service/eslclient/entity/Channel.java
  48. 25 0
      midware-service/src/main/java/midware/service/eslclient/entity/Session.java
  49. 819 0
      midware-service/src/main/java/midware/service/init/EslClientService.java
  50. 35 0
      midware-service/src/main/java/midware/service/init/QuartzService.java
  51. 600 0
      midware-service/src/main/java/midware/service/init/WebSocketService.java
  52. 19 0
      midware-service/src/main/java/midware/service/quartz/job/AuthJob.java
  53. 50 0
      midware-service/src/main/java/midware/service/quartz/job/BatchInsertJob.java
  54. 28 0
      midware-service/src/main/java/midware/service/quartz/job/WsHeartJob.java
  55. 52 0
      midware-service/src/main/java/midware/service/quartz/util/QuartzHelper.java
  56. 31 0
      midware-service/src/main/java/midware/service/quartz/util/QuartzJob.java
  57. 7 0
      midware-service/src/main/java/midware/service/rep/IAgentActionService.java
  58. 7 0
      midware-service/src/main/java/midware/service/rep/IAgentStateService.java
  59. 7 0
      midware-service/src/main/java/midware/service/rep/IChanEventService.java
  60. 8 0
      midware-service/src/main/java/midware/service/rep/IConfigService.java
  61. 7 0
      midware-service/src/main/java/midware/service/rep/IIvrService.java
  62. 7 0
      midware-service/src/main/java/midware/service/rep/IRecordService.java
  63. 14 0
      midware-service/src/main/java/midware/service/rep/impl/AgentActionServiceImpl.java
  64. 14 0
      midware-service/src/main/java/midware/service/rep/impl/AgentStateServiceImpl.java
  65. 14 0
      midware-service/src/main/java/midware/service/rep/impl/ChanEventServiceImpl.java
  66. 27 0
      midware-service/src/main/java/midware/service/rep/impl/ConfigServiceImpl.java
  67. 287 0
      midware-service/src/main/java/midware/service/rep/impl/IvrServiceImpl.java
  68. 14 0
      midware-service/src/main/java/midware/service/rep/impl/RecordServiceImpl.java
  69. 65 0
      midware-util/pom.xml
  70. 58 0
      midware-util/src/main/java/midware/util/config/CommonConfig.java
  71. 43 0
      midware-util/src/main/java/midware/util/config/EslClientConfig.java
  72. 36 0
      midware-util/src/main/java/midware/util/config/MybatisPlusConfig.java
  73. 62 0
      midware-util/src/main/java/midware/util/config/ThreadPoolConfig.java
  74. 17 0
      midware-util/src/main/java/midware/util/config/WebSocketConfig.java
  75. 18 0
      midware-util/src/main/java/midware/util/enums/EslAgentEnum.java
  76. 72 0
      midware-util/src/main/java/midware/util/enums/EslCommandEnum.java
  77. 71 0
      midware-util/src/main/java/midware/util/enums/EslEventEnum.java
  78. 64 0
      midware-util/src/main/java/midware/util/enums/IvrType.java
  79. 91 0
      midware-util/src/main/java/midware/util/helper/AsyncHelper.java
  80. 322 0
      midware-util/src/main/java/midware/util/helper/CodeHelper.java
  81. 104 0
      midware-util/src/main/java/midware/util/helper/HttpHelper.java
  82. 63 0
      midware-util/src/main/java/midware/util/helper/IpHelper.java
  83. 206 0
      midware-util/src/main/java/midware/util/helper/RedisHelper.java
  84. 116 0
      midware-util/src/main/java/midware/util/helper/SecretHelper.java
  85. 110 0
      midware-util/src/main/java/midware/util/helper/ServletHelper.java
  86. 156 0
      midware-util/src/main/java/midware/util/helper/SpringHelper.java
  87. 337 0
      midware-util/src/main/java/midware/util/helper/StringHelper.java
  88. 120 0
      midware-util/src/main/java/midware/util/helper/TtsHelper.java
  89. 68 0
      pom.xml

+ 6 - 0
.gitignore

@@ -0,0 +1,6 @@
1
+logs/
2
+.idea/
3
+target/
4
+files/
5
+*.log
6
+*.iml

+ 79 - 0
midware-api/pom.xml

@@ -0,0 +1,79 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <modelVersion>4.0.0</modelVersion>
6
+    <parent>
7
+        <groupId>midware</groupId>
8
+        <artifactId>midware-base</artifactId>
9
+        <version>1.0.0</version>
10
+    </parent>
11
+
12
+    <artifactId>midware-api</artifactId>
13
+
14
+    <properties>
15
+        <maven.compiler.source>8</maven.compiler.source>
16
+        <maven.compiler.target>8</maven.compiler.target>
17
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18
+        <api.version>1.0.0</api.version>
19
+    </properties>
20
+
21
+    <dependencies>
22
+        <dependency>
23
+            <groupId>org.springframework.boot</groupId>
24
+            <artifactId>spring-boot-starter-web</artifactId>
25
+            <optional>true</optional>
26
+        </dependency>
27
+
28
+        <!-- mysql驱动 -->
29
+        <dependency>
30
+            <groupId>mysql</groupId>
31
+            <artifactId>mysql-connector-java</artifactId>
32
+            <version>8.0.28</version>
33
+        </dependency>
34
+
35
+        <dependency>
36
+            <groupId>midware</groupId>
37
+            <artifactId>midware-service</artifactId>
38
+            <version>${api.version}</version>
39
+        </dependency>
40
+        <dependency>
41
+            <groupId>midware</groupId>
42
+            <artifactId>midware-util</artifactId>
43
+            <version>${api.version}</version>
44
+        </dependency>
45
+        <dependency>
46
+            <groupId>midware</groupId>
47
+            <artifactId>midware-mapper</artifactId>
48
+            <version>${api.version}</version>
49
+        </dependency>
50
+        <dependency>
51
+            <groupId>midware</groupId>
52
+            <artifactId>midware-entity</artifactId>
53
+            <version>${api.version}</version>
54
+        </dependency>
55
+
56
+        <dependency>
57
+            <groupId>org.apache.commons</groupId>
58
+            <artifactId>commons-lang3</artifactId>
59
+            <version>3.9</version>
60
+        </dependency>
61
+
62
+        <dependency>
63
+            <groupId>com.alibaba</groupId>
64
+            <artifactId>druid</artifactId>
65
+            <version>1.1.22</version>
66
+        </dependency>
67
+
68
+    </dependencies>
69
+
70
+    <build>
71
+        <plugins>
72
+            <plugin>
73
+                <groupId>org.springframework.boot</groupId>
74
+                <artifactId>spring-boot-maven-plugin</artifactId>
75
+            </plugin>
76
+        </plugins>
77
+    </build>
78
+
79
+</project>

+ 39 - 0
midware-api/src/main/java/midware/ApiApplication.java

@@ -0,0 +1,39 @@
1
+package midware;
2
+
3
+import midware.util.helper.IpHelper;
4
+import org.springframework.boot.Banner;
5
+import org.springframework.boot.SpringApplication;
6
+import org.springframework.boot.autoconfigure.SpringBootApplication;
7
+import org.springframework.context.ConfigurableApplicationContext;
8
+import org.springframework.core.env.Environment;
9
+import org.springframework.scheduling.annotation.EnableAsync;
10
+
11
+@SpringBootApplication
12
+@EnableAsync
13
+public class ApiApplication {
14
+    public static void main(String[] args) {
15
+        //SpringApplication.run(WebApiApplication.class, args);
16
+        SpringApplication springApplication = new SpringApplication(ApiApplication.class);
17
+        springApplication.setBannerMode(Banner.Mode.OFF);
18
+        ConfigurableApplicationContext context = springApplication.run(args);
19
+
20
+        Environment env = context.getEnvironment();
21
+        //String ip = InetAddress.getLocalHost().getHostAddress();
22
+        String ip= IpHelper.getIp4();
23
+        String port = env.getProperty("server.port");
24
+        port = port == null ? "8000" : port;
25
+        String active = env.getProperty("spring.profiles.active");
26
+        active = active == null ? "" : active;
27
+
28
+        System.out.println("运行环境: " + active);
29
+        System.out.println("访问地址: http://" + ip + ":" + port);
30
+
31
+        System.out.println("|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||");
32
+        System.out.println("||||||||||                                                                     ||||||||||");
33
+        System.out.println("||||||||||                               SUCCESS                               ||||||||||");
34
+        System.out.println("||||||||||                                                                     ||||||||||");
35
+        System.out.println("|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||");
36
+    }
37
+
38
+
39
+}

+ 79 - 0
midware-api/src/main/java/midware/controller/BaseController.java

@@ -0,0 +1,79 @@
1
+package midware.controller;
2
+
3
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
4
+import midware.entity.input.PageInput;
5
+import midware.model.AjaxResult;
6
+import midware.model.PageResult;
7
+
8
+public class BaseController {
9
+
10
+    //是否分页
11
+    public <T> Page<T> GetPage(PageInput page) {
12
+        if (page.getPageNum() != null && page.getPageSize() != null) {
13
+            Page<T> ipage = new Page<>();
14
+            ipage.setCurrent(page.getPageNum());
15
+            ipage.setSize(page.getPageSize());
16
+            return ipage;
17
+        } else {
18
+            return null;
19
+        }
20
+    }
21
+
22
+    //成功的消息格式化
23
+    public AjaxResult Success(String message) {
24
+        AjaxResult result = new AjaxResult();
25
+        result.setState("success");
26
+        result.setMessage(message);
27
+
28
+        return result;
29
+    }
30
+
31
+    //成功的消息格式化
32
+    public AjaxResult Success(String message, Object data) {
33
+        AjaxResult result = new AjaxResult();
34
+        result.setState("success");
35
+        result.setMessage(message);
36
+        result.setData(data);
37
+
38
+        return result;
39
+    }
40
+
41
+    //分页成功的消息格式化
42
+    public AjaxResult Success(String message, Object data, Long total) {
43
+        PageResult result = new PageResult();
44
+        result.setState("success");
45
+        result.setMessage(message);
46
+        result.setData(data);
47
+        result.setTotal(total);
48
+
49
+        return result;
50
+    }
51
+
52
+    //错误的消息格式化
53
+    public AjaxResult Error(String message) {
54
+        AjaxResult result = new AjaxResult();
55
+        result.setState("error");
56
+        result.setMessage(message);
57
+
58
+        return result;
59
+    }
60
+
61
+    //跳转的消息格式化
62
+    public AjaxResult Redirect(String message, Object data) {
63
+        AjaxResult result = new AjaxResult();
64
+        result.setState("redirect");
65
+        result.setMessage(message);
66
+        result.setData(data);
67
+
68
+        return result;
69
+    }
70
+
71
+    //未登录或者登录已过期
72
+    public AjaxResult NoToken(String message) {
73
+        AjaxResult result = new AjaxResult();
74
+        result.setState("notoken");
75
+        result.setMessage(message);
76
+
77
+        return result;
78
+    }
79
+}

+ 182 - 0
midware-api/src/main/java/midware/controller/HomeController.java

@@ -0,0 +1,182 @@
1
+package midware.controller;
2
+
3
+import com.alibaba.fastjson2.JSON;
4
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
5
+import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
6
+import midware.entity.database.rep.Ivr;
7
+import midware.entity.input.CodeInput;
8
+import midware.model.AjaxResult;
9
+import midware.service.eslclient.EslCommon;
10
+import midware.service.eslclient.entity.Channel;
11
+import midware.service.eslclient.entity.Session;
12
+import midware.service.init.EslClientService;
13
+import midware.service.rep.IIvrService;
14
+import midware.util.helper.*;
15
+import org.springframework.beans.factory.annotation.Autowired;
16
+import org.springframework.web.bind.annotation.*;
17
+
18
+import javax.servlet.http.HttpServletResponse;
19
+import java.io.IOException;
20
+import java.io.PrintWriter;
21
+import java.util.*;
22
+import java.util.concurrent.TimeUnit;
23
+import java.util.stream.Collectors;
24
+
25
+@RestController
26
+@RequestMapping()
27
+public class HomeController extends BaseController {
28
+    @Autowired
29
+    private EslClientService eslClientService;
30
+
31
+    @Autowired
32
+    private IIvrService ivrService;
33
+
34
+    @Autowired
35
+    private RedisHelper redisHelper;
36
+
37
+    @GetMapping("/")
38
+    public AjaxResult Info() {
39
+        return Success("Hello World!", new Date());
40
+    }
41
+
42
+    @GetMapping("/test")
43
+    public AjaxResult Test() {
44
+        return Success("", new Date());
45
+    }
46
+
47
+    @GetMapping("/auth")
48
+    public AjaxResult Auth() {
49
+        return Success("",EslCommon.auth );
50
+    }
51
+
52
+    @GetMapping("/mac")
53
+    public AjaxResult Mac() {
54
+        return Success("", IpHelper.getMac());
55
+    }
56
+
57
+    @GetMapping("/authcode/{date}/{num}")
58
+    public AjaxResult AuthCode(@PathVariable String date,@PathVariable int num) {
59
+        String str = SecretHelper.MD5(IpHelper.getMac()) + "|" + date + "|" + num;
60
+        String result = Base64.getEncoder().encodeToString(SecretHelper.AesEncrypt(str).getBytes());
61
+        return Success("", result);
62
+    }
63
+    @GetMapping("/authcodemac/{mac}/{param}")
64
+    public AjaxResult AuthCodeByMac(@PathVariable String mac,@PathVariable String param) {
65
+        String str = SecretHelper.MD5(mac) + "|" + param ;
66
+        String result = Base64.getEncoder().encodeToString(SecretHelper.AesEncrypt(str).getBytes());
67
+        return Success("", result);
68
+    }
69
+
70
+    @GetMapping("/agentfree")
71
+    public String AgentFree() {
72
+        return EslCommon.agents.stream().anyMatch(p -> p.getAgentState() == 2) ? "1" : "0";
73
+    }
74
+
75
+    @GetMapping("/esl")
76
+    public AjaxResult Esl() {
77
+        Map<String, Object> map = new HashMap<>();
78
+        map.put("agents",EslCommon.agents);
79
+        map.put("channels",EslCommon.channels);
80
+        map.put("sessions",EslCommon.sessions);
81
+        map.put("groupWaitList",EslCommon.groupWaitList);
82
+        return Success("",map );
83
+    }
84
+
85
+    @GetMapping("/midware/{type}")
86
+    public AjaxResult Midware(@PathVariable int type) {
87
+        List<Map<String,Object>> maps=new ArrayList<>();
88
+        switch (type) {
89
+            case 1:
90
+                for (Session s : EslCommon.sessions) {
91
+                    List<Channel> chans = EslCommon.channels.stream().filter(p -> p.getSessionId().equals(s.getSessionId()))
92
+                            .sorted(Comparator.comparing(Channel::getSessionSort)).collect(Collectors.toList());
93
+                    Map<String, Object> map = new HashMap<>();
94
+                    map.put("type", s.getType());
95
+                    map.put("caller", chans.get(0).getNumber());
96
+                    if (chans.size() == 2) {
97
+                        map.put("callee", chans.get(1).getNumber());
98
+                    } else {
99
+                        chans.remove(0);
100
+                        map.put("callee", chans.stream().map(Channel::getNumber).collect(Collectors.joining(",")));
101
+                    }
102
+                    map.put("createtime", s.getCreateTime());
103
+
104
+                    maps.add(map);
105
+                }
106
+                break;
107
+        }
108
+        return Success("",maps );
109
+    }
110
+
111
+    @GetMapping("/callout/{ext}/{number}")
112
+    public AjaxResult Midware(@PathVariable String ext,@PathVariable String number) {
113
+        if (EslCommon.existExten(ext)) {
114
+            boolean result = eslClientService.extenCall(ext, number,"");
115
+            if(result) {
116
+                return Success("成功");
117
+            }else {
118
+                return Error("失败");
119
+            }
120
+        } else {
121
+            return Error("分机未注册");
122
+        }
123
+    }
124
+
125
+    @PostMapping("/ivr/{type}")
126
+    public String getIvrXml(@PathVariable Integer type) {
127
+        String result = null;
128
+
129
+        String key="";
130
+        if(type==1) {
131
+            key="ivr:context";
132
+            result = redisHelper.getCache(key);
133
+        }else {
134
+            key="ivr:menu";
135
+            result = redisHelper.getCache(key);
136
+        }
137
+
138
+        if(StringHelper.isEmpty(result)) {
139
+            LambdaQueryWrapper<Ivr> qw = new LambdaQueryWrapper<>();
140
+            qw.eq(Ivr::getDelFlag, 0);
141
+            if (type == 1) {
142
+                qw.select(Ivr::getContext);
143
+            } else {
144
+                qw.select(Ivr::getMenu);
145
+            }
146
+            qw.last("limit 1");
147
+            qw.orderByDesc(Ivr::getVersion);
148
+            Map<String, Object> map = ivrService.getMapFirst(qw);
149
+            if (map != null) {
150
+                result = map.values().stream().findFirst().get().toString();
151
+                redisHelper.setCache(key, result, 1, TimeUnit.DAYS);
152
+            }
153
+        }
154
+
155
+        return result;
156
+    }
157
+
158
+    @GetMapping("/getcode")
159
+    public void GetCode(HttpServletResponse response, CodeInput input) {
160
+        Map<String, Object> table = SqlRunner.db().selectOne("select table_name,table_comment from information_schema.tables"
161
+                + " where table_schema = (select database()) AND table_name = {0} ", input.getTableName());
162
+        if (table == null) {
163
+            Map<String, String> map = new HashMap();
164
+            map.put("state", "error");
165
+            map.put("message", "此表不存在");
166
+
167
+            try {
168
+                PrintWriter out = response.getWriter();
169
+                out.write(JSON.toJSONString(map));
170
+                out.flush();
171
+                out.close();
172
+            } catch (IOException ex) {
173
+                throw new RuntimeException(ex);
174
+            }
175
+            return;
176
+        }
177
+        List<Map<String, Object>> columns = SqlRunner.db().selectList("select column_name,data_type,column_type,is_nullable,"
178
+                + "column_key,column_comment from information_schema.columns where table_schema = (select database()) "
179
+                + "and table_name = {0} order by ordinal_position", input.getTableName());
180
+        CodeHelper.GetCode(response, table, columns, input.getPackageName(), input.getControllerName());
181
+    }
182
+}

+ 50 - 0
midware-api/src/main/java/midware/controller/rep/AgentActionController.java

@@ -0,0 +1,50 @@
1
+package midware.controller.rep;
2
+
3
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4
+import com.baomidou.mybatisplus.core.metadata.IPage;
5
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
6
+import midware.controller.BaseController;
7
+import midware.entity.database.rep.AgentAction;
8
+import midware.entity.database.rep.ChanEvent;
9
+import midware.entity.input.PageInput;
10
+import midware.model.AjaxResult;
11
+import midware.service.rep.IAgentActionService;
12
+import midware.util.helper.StringHelper;
13
+import org.springframework.beans.factory.annotation.Autowired;
14
+import org.springframework.web.bind.annotation.*;
15
+
16
+//@Api(value = "坐席操作表",tags = "坐席操作表")
17
+@RestController
18
+@RequestMapping("/rep/agentaction")
19
+public class AgentActionController extends BaseController {
20
+    @Autowired
21
+    private IAgentActionService agentActionService;
22
+
23
+    //@ApiOperation("列表")
24
+    @GetMapping
25
+    public AjaxResult getList(AgentAction input, PageInput pageInput) {
26
+        LambdaQueryWrapper<AgentAction> qw = new LambdaQueryWrapper<>();
27
+        qw.eq(input.getId() != null && input.getId() > 0, AgentAction::getId, input.getId());
28
+        qw.like(!StringHelper.isEmpty(input.getAgent()), AgentAction::getAgent, input.getAgent());
29
+        qw.like(!StringHelper.isEmpty(input.getGroupNo()), AgentAction::getGroupNo, input.getGroupNo());
30
+        qw.like(!StringHelper.isEmpty(input.getExten()), AgentAction::getExten, input.getExten());
31
+        qw.like(!StringHelper.isEmpty(input.getAction()), AgentAction::getAction, input.getAction());
32
+        qw.like(!StringHelper.isEmpty(input.getParam()), AgentAction::getParam, input.getParam());
33
+        qw.like(!StringHelper.isEmpty(input.getUuid()), AgentAction::getUuid, input.getUuid());
34
+        qw.eq(input.getCreateTime() != null , AgentAction::getCreateTime, input.getCreateTime());
35
+        qw.orderByDesc(AgentAction::getId);
36
+        Page<AgentAction> page = GetPage(pageInput);
37
+        if (page != null) {
38
+            IPage<AgentAction> iPage = agentActionService.getListPage(page, qw);
39
+            return Success("成功", iPage.getRecords(), iPage.getTotal());
40
+        } else {
41
+            return Success("成功", agentActionService.getList(qw));
42
+        }
43
+    }
44
+
45
+    //@ApiOperation("详情")
46
+    @GetMapping("/{id}")
47
+    public AjaxResult getInfo(@PathVariable long id) {
48
+        return Success("成功", agentActionService.getEntity(id));
49
+    }
50
+}

+ 51 - 0
midware-api/src/main/java/midware/controller/rep/AgentStateController.java

@@ -0,0 +1,51 @@
1
+package midware.controller.rep;
2
+
3
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4
+import com.baomidou.mybatisplus.core.metadata.IPage;
5
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
6
+import midware.controller.BaseController;
7
+import midware.entity.database.rep.AgentState;
8
+import midware.entity.database.rep.ChanEvent;
9
+import midware.entity.input.PageInput;
10
+import midware.model.AjaxResult;
11
+import midware.service.rep.IAgentStateService;
12
+import midware.util.helper.StringHelper;
13
+import org.springframework.beans.factory.annotation.Autowired;
14
+import org.springframework.web.bind.annotation.GetMapping;
15
+import org.springframework.web.bind.annotation.PathVariable;
16
+import org.springframework.web.bind.annotation.RequestMapping;
17
+import org.springframework.web.bind.annotation.RestController;
18
+
19
+//@Api(value = "坐席状态表",tags = "坐席状态表")
20
+@RestController
21
+@RequestMapping("/rep/agentstate")
22
+public class AgentStateController extends BaseController {
23
+    @Autowired
24
+    private IAgentStateService agentStateService;
25
+
26
+    //@ApiOperation("列表")
27
+    @GetMapping
28
+    public AjaxResult getList(AgentState input, PageInput pageInput) {
29
+        LambdaQueryWrapper<AgentState> qw = new LambdaQueryWrapper<>();
30
+        qw.like(!StringHelper.isEmpty(input.getAgent()), AgentState::getAgent, input.getAgent());
31
+        qw.eq(!StringHelper.isEmpty(input.getGroupNo()), AgentState::getGroupNo, input.getGroupNo());
32
+        qw.like(!StringHelper.isEmpty(input.getExten()), AgentState::getExten, input.getExten());
33
+        qw.eq(input.getState() != null && input.getState() > 0, AgentState::getState, input.getState());
34
+        qw.like(!StringHelper.isEmpty(input.getUuid()), AgentState::getUuid, input.getUuid());
35
+        qw.eq(input.getCreateTime() != null , AgentState::getCreateTime, input.getCreateTime());
36
+        qw.orderByDesc(AgentState::getId);
37
+        Page<AgentState> page = GetPage(pageInput);
38
+        if (page != null) {
39
+            IPage<AgentState> iPage = agentStateService.getListPage(page, qw);
40
+            return Success("成功", iPage.getRecords(), iPage.getTotal());
41
+        } else {
42
+            return Success("成功", agentStateService.getList(qw));
43
+        }
44
+    }
45
+
46
+    //@ApiOperation("详情")
47
+    @GetMapping("/{id}")
48
+    public AjaxResult getInfo(@PathVariable long id) {
49
+        return Success("成功", agentStateService.getEntity(id));
50
+    }
51
+}

+ 46 - 0
midware-api/src/main/java/midware/controller/rep/ChanEventController.java

@@ -0,0 +1,46 @@
1
+package midware.controller.rep;
2
+
3
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4
+import com.baomidou.mybatisplus.core.metadata.IPage;
5
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
6
+import midware.controller.BaseController;
7
+import midware.entity.database.rep.ChanEvent;
8
+import midware.entity.input.PageInput;
9
+import midware.model.AjaxResult;
10
+import midware.service.rep.IChanEventService;
11
+import midware.util.helper.StringHelper;
12
+import org.springframework.beans.factory.annotation.Autowired;
13
+import org.springframework.web.bind.annotation.*;
14
+
15
+//@Api(value = "通道事件表",tags = "通道事件表")
16
+@RestController
17
+@RequestMapping("/rep/chanevent")
18
+public class ChanEventController extends BaseController {
19
+    @Autowired
20
+    private IChanEventService chaneventService;
21
+
22
+    //@ApiOperation("列表")
23
+    @GetMapping
24
+    public AjaxResult getList(ChanEvent input, PageInput pageInput) {
25
+        LambdaQueryWrapper<ChanEvent> qw = new LambdaQueryWrapper<>();
26
+        qw.like(!StringHelper.isEmpty(input.getChan()), ChanEvent::getChan, input.getChan());
27
+        qw.like(!StringHelper.isEmpty(input.getEvent()), ChanEvent::getEvent, input.getEvent());
28
+        qw.eq(!StringHelper.isEmpty(input.getUuid()), ChanEvent::getUuid, input.getUuid());
29
+        qw.eq(input.getCreateTime() != null , ChanEvent::getCreateTime, input.getCreateTime());
30
+        qw.orderByDesc(ChanEvent::getId);
31
+        Page<ChanEvent> page = GetPage(pageInput);
32
+        if (page != null) {
33
+            IPage<ChanEvent> iPage = chaneventService.getListPage(page, qw);
34
+            return Success("成功", iPage.getRecords(), iPage.getTotal());
35
+        } else {
36
+            return Success("成功", chaneventService.getList(qw));
37
+        }
38
+    }
39
+
40
+    //@ApiOperation("详情")
41
+    @GetMapping("/{id}")
42
+    public AjaxResult getInfo(@PathVariable long id) {
43
+        return Success("成功", chaneventService.getEntity(id));
44
+    }
45
+
46
+}

+ 81 - 0
midware-api/src/main/java/midware/controller/rep/ConfigController.java

@@ -0,0 +1,81 @@
1
+package midware.controller.rep;
2
+
3
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4
+import com.baomidou.mybatisplus.core.metadata.IPage;
5
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
6
+import midware.controller.BaseController;
7
+import midware.entity.database.rep.ChanEvent;
8
+import midware.entity.database.rep.Config;
9
+import midware.entity.input.PageInput;
10
+import midware.model.AjaxResult;
11
+import midware.service.rep.IConfigService;
12
+import midware.util.helper.StringHelper;
13
+import org.springframework.beans.factory.annotation.Autowired;
14
+import org.springframework.web.bind.annotation.*;
15
+import java.util.Arrays;
16
+
17
+//@Api(value = "配置表",tags = "配置表")
18
+@RestController
19
+@RequestMapping("/rep/config")
20
+public class ConfigController extends BaseController {
21
+    @Autowired
22
+    private IConfigService configService;
23
+
24
+    //@ApiOperation("列表")
25
+    @GetMapping
26
+    public AjaxResult getList(Config input, PageInput pageInput) {
27
+        LambdaQueryWrapper<Config> qw = new LambdaQueryWrapper<>();
28
+        qw.eq(input.getId() != null && input.getId() > 0, Config::getId, input.getId());
29
+        qw.like(!StringHelper.isEmpty(input.getCode()), Config::getCode, input.getCode());
30
+        qw.like(!StringHelper.isEmpty(input.getValue()), Config::getValue, input.getValue());
31
+        qw.like(!StringHelper.isEmpty(input.getRemark()), Config::getRemark, input.getRemark());
32
+        qw.orderByDesc(Config::getId);
33
+        Page<Config> page = GetPage(pageInput);
34
+        if (page != null) {
35
+            IPage<Config> iPage = configService.getListPage(page, qw);
36
+            return Success("成功", iPage.getRecords(), iPage.getTotal());
37
+        } else {
38
+            return Success("成功", configService.getList(qw));
39
+        }
40
+    }
41
+
42
+    //@ApiOperation("详情")
43
+    @GetMapping("/{id}")
44
+    public AjaxResult getInfo(@PathVariable long id) {
45
+        return Success("成功", configService.getEntity(id));
46
+    }
47
+
48
+    //@ApiOperation("新增")
49
+    @PostMapping
50
+    public AjaxResult add(@RequestBody Config input) {
51
+        boolean result = configService.insert(input);
52
+        if (result) {
53
+            return Success("成功");
54
+        } else {
55
+            return Error("新增失败");
56
+        }
57
+    }
58
+
59
+    //@ApiOperation("编辑")
60
+    @PutMapping
61
+    public AjaxResult edit(@RequestBody Config input)  {
62
+        boolean result = configService.update(input);
63
+        if (result) {
64
+            return Success("成功");
65
+        } else {
66
+            return Error("修改失败");
67
+        }
68
+    }
69
+
70
+    //@ApiOperation("删除")
71
+    @DeleteMapping("/{ids}")
72
+    public AjaxResult delete(@PathVariable Long[] ids)  {
73
+        boolean result = configService.delete(Arrays.asList(ids));
74
+        if (result) {
75
+            return Success("成功");
76
+        } else {
77
+            return Error("删除失败");
78
+        }
79
+    }
80
+
81
+}

+ 110 - 0
midware-api/src/main/java/midware/controller/rep/IvrController.java

@@ -0,0 +1,110 @@
1
+package midware.controller.rep;
2
+
3
+import midware.controller.BaseController;
4
+import midware.entity.database.rep.ChanEvent;
5
+import midware.entity.database.rep.Ivr;
6
+import midware.entity.input.PageInput;
7
+import midware.model.AjaxResult;
8
+import midware.service.rep.IIvrService;
9
+import midware.util.helper.RedisHelper;
10
+import midware.util.helper.StringHelper;
11
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
12
+import com.baomidou.mybatisplus.core.metadata.IPage;
13
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
14
+import org.springframework.beans.factory.annotation.Autowired;
15
+import org.springframework.web.bind.annotation.*;
16
+
17
+import java.util.Arrays;
18
+import java.util.Date;
19
+
20
+//@Api(value = "rep_ivr",tags = "ivr")
21
+@RestController
22
+@RequestMapping("/rep/ivr")
23
+public class IvrController extends BaseController {
24
+    @Autowired
25
+    private IIvrService ivrService;
26
+    @Autowired
27
+    private RedisHelper redisHelper;
28
+
29
+    //@ApiOperation("列表")
30
+    @GetMapping
31
+    public AjaxResult getList(Ivr input, PageInput pageInput) {
32
+        LambdaQueryWrapper<Ivr> qw = new LambdaQueryWrapper<>();
33
+        qw.like(!StringHelper.isEmpty(input.getName()), Ivr::getName, input.getName());
34
+        qw.like(!StringHelper.isEmpty(input.getVersion()), Ivr::getVersion, input.getVersion());
35
+        qw.like(!StringHelper.isEmpty(input.getRemark()), Ivr::getRemark, input.getRemark());
36
+        qw.orderByDesc(Ivr::getIvrId);
37
+        Page<Ivr> page = GetPage(pageInput);
38
+        if (page != null) {
39
+            IPage<Ivr> iPage = ivrService.getListPage(page, qw);
40
+            return Success("成功", iPage.getRecords(), iPage.getTotal());
41
+        } else {
42
+            return Success("成功", ivrService.getList(qw));
43
+        }
44
+    }
45
+
46
+    //@ApiOperation("详情")
47
+    @GetMapping("/{id}")
48
+    public AjaxResult getInfo(@PathVariable long id) {
49
+        return Success("成功", ivrService.getEntity(id));
50
+    }
51
+
52
+    //@ApiOperation("新增")
53
+    @PostMapping
54
+    public AjaxResult add(@RequestBody Ivr input) {
55
+        LambdaQueryWrapper<Ivr> qw = new LambdaQueryWrapper();
56
+        qw.eq(Ivr::getName, input.getName());
57
+        if (ivrService.getCount(qw) > 0) {
58
+            return Error("此名称已经存在");
59
+        }
60
+
61
+        //input.setCreateBy(CurrentUser().getUserName());
62
+        input.setCreateTime(new Date());
63
+        input.setDelFlag("0");
64
+        boolean result = ivrService.insert(input);
65
+        if (result) {
66
+            redisHelper.deleteCache("ivr:menu");
67
+            redisHelper.deleteCache("ivr:context");
68
+            return Success("成功");
69
+        } else {
70
+            return Error("新增失败");
71
+        }
72
+    }
73
+
74
+
75
+
76
+    //@ApiOperation("编辑")
77
+    @PutMapping
78
+    public AjaxResult edit(@RequestBody Ivr input)  {
79
+        LambdaQueryWrapper<Ivr> qw = new LambdaQueryWrapper();
80
+        qw.ne( Ivr::getIvrId, input.getIvrId());
81
+        qw.eq( Ivr::getName, input.getName());
82
+        if(ivrService.getCount(qw)>0){
83
+            return Error("此名称已经存在");
84
+        }
85
+        //input.setUpdateBy(CurrentUser().getUserName());
86
+        input.setUpdateTime(new Date());
87
+        boolean result = ivrService.update(input);
88
+        if (result) {
89
+            redisHelper.deleteCache("ivr:menu");
90
+            redisHelper.deleteCache("ivr:context");
91
+            return Success("成功");
92
+        } else {
93
+            return Error("修改失败");
94
+        }
95
+    }
96
+
97
+    //@ApiOperation("删除")
98
+    @DeleteMapping("/{ids}")
99
+    public AjaxResult delete(@PathVariable Long[] ids)  {
100
+        boolean result = ivrService.delete(Arrays.asList(ids));
101
+        if (result) {
102
+            redisHelper.deleteCache("ivr:menu");
103
+            redisHelper.deleteCache("ivr:context");
104
+            return Success("成功");
105
+        } else {
106
+            return Error("删除失败");
107
+        }
108
+    }
109
+
110
+}

+ 67 - 0
midware-api/src/main/java/midware/controller/rep/RecordController.java

@@ -0,0 +1,67 @@
1
+package midware.controller.rep;
2
+
3
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4
+import com.baomidou.mybatisplus.core.metadata.IPage;
5
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
6
+import midware.controller.BaseController;
7
+import midware.entity.database.rep.ChanEvent;
8
+import midware.entity.database.rep.Record;
9
+import midware.entity.input.PageInput;
10
+import midware.model.AjaxResult;
11
+import midware.service.rep.IRecordService;
12
+import midware.util.helper.StringHelper;
13
+import org.springframework.beans.factory.annotation.Autowired;
14
+import org.springframework.web.bind.annotation.GetMapping;
15
+import org.springframework.web.bind.annotation.PathVariable;
16
+import org.springframework.web.bind.annotation.RequestMapping;
17
+import org.springframework.web.bind.annotation.RestController;
18
+
19
+//@Api(value = "通话记录表",tags = "通话记录表")
20
+@RestController
21
+@RequestMapping("/rep/record")
22
+public class RecordController extends BaseController {
23
+    @Autowired
24
+    private IRecordService recordService;
25
+
26
+    //@ApiOperation("列表")
27
+    @GetMapping
28
+    public AjaxResult getList(Record input, PageInput pageInput) {
29
+        LambdaQueryWrapper<Record> qw = new LambdaQueryWrapper<>();
30
+        qw.like(!StringHelper.isEmpty(input.getUuid()), Record::getUuid, input.getUuid());
31
+        qw.eq(input.getActionId() != null && input.getActionId() > 0, Record::getActionId, input.getActionId());
32
+        qw.like(!StringHelper.isEmpty(input.getCallerAgent()), Record::getCallerAgent, input.getCallerAgent());
33
+        qw.like(!StringHelper.isEmpty(input.getCaller()), Record::getCaller, input.getCaller());
34
+        qw.like(!StringHelper.isEmpty(input.getTrunkNum()), Record::getTrunkNum, input.getTrunkNum());
35
+        qw.like(!StringHelper.isEmpty(input.getCalleeAgent()), Record::getCalleeAgent, input.getCalleeAgent());
36
+        qw.like(!StringHelper.isEmpty(input.getCallee()), Record::getCallee, input.getCallee());
37
+        qw.like(!StringHelper.isEmpty(input.getGroupNo()), Record::getGroupNo, input.getGroupNo());
38
+        qw.eq(input.getCallType() != null && input.getCallType() > 0, Record::getCallType, input.getCallType());
39
+        qw.eq(input.getCreateTime() != null , Record::getCreateTime, input.getCreateTime());
40
+        qw.eq(input.getWaitTime() != null , Record::getWaitTime, input.getWaitTime());
41
+        qw.eq(input.getRingTime() != null , Record::getRingTime, input.getRingTime());
42
+        qw.eq(input.getAnswerTime() != null , Record::getAnswerTime, input.getAnswerTime());
43
+        qw.eq(input.getIsAnswer() != null && input.getIsAnswer() > 0, Record::getIsAnswer, input.getIsAnswer());
44
+        qw.eq(input.getHangupTime() != null , Record::getHangupTime, input.getHangupTime());
45
+        qw.eq(!StringHelper.isEmpty(input.getOpType()), Record::getOpType, input.getOpType());
46
+        qw.like(!StringHelper.isEmpty(input.getHangupCause()), Record::getHangupCause, input.getHangupCause());
47
+        qw.eq(input.getMyd() != null && input.getMyd() > 0, Record::getMyd, input.getMyd());
48
+        qw.like(!StringHelper.isEmpty(input.getNote()), Record::getNote, input.getNote());
49
+        qw.like(!StringHelper.isEmpty(input.getRecordPath()), Record::getRecordPath, input.getRecordPath());
50
+        qw.eq(input.getLeaveTime() != null , Record::getLeaveTime, input.getLeaveTime());
51
+        qw.like(!StringHelper.isEmpty(input.getLeavePath()), Record::getLeavePath, input.getLeavePath());
52
+        qw.orderByDesc(Record::getId);
53
+        Page<Record> page = GetPage(pageInput);
54
+        if (page != null) {
55
+            IPage<Record> iPage = recordService.getListPage(page, qw);
56
+            return Success("成功", iPage.getRecords(), iPage.getTotal());
57
+        } else {
58
+            return Success("成功", recordService.getList(qw));
59
+        }
60
+    }
61
+
62
+    //@ApiOperation("详情")
63
+    @GetMapping("/{id}")
64
+    public AjaxResult getInfo(@PathVariable long id) {
65
+        return Success("成功", recordService.getEntity(id));
66
+    }
67
+}

+ 72 - 0
midware-api/src/main/java/midware/filter/GlobalExceptionHandler.java

@@ -0,0 +1,72 @@
1
+package midware.filter;
2
+
3
+import midware.model.AjaxResult;
4
+import midware.util.helper.ServletHelper;
5
+import midware.util.helper.StringHelper;
6
+import lombok.extern.slf4j.Slf4j;
7
+import org.springframework.validation.BindException;
8
+import org.springframework.web.bind.annotation.ExceptionHandler;
9
+import org.springframework.web.bind.annotation.RestControllerAdvice;
10
+
11
+import javax.servlet.http.HttpServletRequest;
12
+import java.util.Objects;
13
+
14
+@Slf4j
15
+@RestControllerAdvice
16
+public class GlobalExceptionHandler {
17
+
18
+    /**
19
+     * 系统异常
20
+     */
21
+    @ExceptionHandler(Exception.class)
22
+    public AjaxResult handleException(Exception e, HttpServletRequest request) {
23
+        String requestURI = request.getRequestURL().toString();
24
+        String methodType = request.getMethod();
25
+        if (Objects.equals(methodType, "GET")) {
26
+            log.error("系统异常\n请求地址:" + methodType + "|{}", requestURI + "?" + request.getQueryString(), e);
27
+        } else {
28
+            String params = ServletHelper.getParams(request);
29
+            if (StringHelper.isNotEmpty(params)) {
30
+                log.error("系统异常\n请求地址:" + methodType + "|{}\n参数:{}", requestURI, params, e);
31
+            } else {
32
+                log.error("系统异常\n请求地址:" + methodType + "|{}", requestURI, e);
33
+            }
34
+        }
35
+
36
+        AjaxResult result = new AjaxResult();
37
+        result.setState("error");
38
+        result.setMessage("系统异常,请稍后重试");
39
+        return result;
40
+    }
41
+
42
+    /**
43
+     * 自定义验证异常
44
+     */
45
+    @ExceptionHandler(RuntimeException.class)
46
+    public AjaxResult handleBindException(RuntimeException e)
47
+    {
48
+        log.error("系统异常\n", e);
49
+
50
+        String message = e.getMessage();
51
+
52
+        AjaxResult result = new AjaxResult();
53
+        result.setState("error");
54
+        result.setMessage(message);
55
+        return result;
56
+    }
57
+
58
+    /**
59
+     * 自定义验证异常
60
+     */
61
+    @ExceptionHandler(BindException.class)
62
+    public AjaxResult handleBindException(BindException e)
63
+    {
64
+        log.error("系统异常\n", e);
65
+        String message = e.getAllErrors().get(0).getDefaultMessage();
66
+
67
+        AjaxResult result = new AjaxResult();
68
+        result.setState("error");
69
+        result.setMessage(message);
70
+        return result;
71
+    }
72
+}

+ 48 - 0
midware-api/src/main/java/midware/filter/ResourcesConfig.java

@@ -0,0 +1,48 @@
1
+package midware.filter;
2
+
3
+import org.springframework.context.annotation.Bean;
4
+import org.springframework.context.annotation.Configuration;
5
+import org.springframework.web.cors.CorsConfiguration;
6
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
7
+import org.springframework.web.filter.CorsFilter;
8
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
9
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
10
+
11
+import java.io.File;
12
+
13
+
14
+@Configuration
15
+public class ResourcesConfig implements WebMvcConfigurer
16
+{
17
+    @Override
18
+    public void addResourceHandlers(ResourceHandlerRegistry registry)
19
+    {
20
+        File file = new File("files");
21
+        /** 本地文件上传路径 */
22
+        registry.addResourceHandler( "/files/**")
23
+                .addResourceLocations("file:" + file.getAbsolutePath()+"/");
24
+    }
25
+
26
+    /**
27
+     * 跨域配置
28
+     */
29
+    @Bean
30
+    public CorsFilter corsFilter()
31
+    {
32
+        CorsConfiguration config = new CorsConfiguration();
33
+        config.setAllowCredentials(true);
34
+        // 设置访问源地址
35
+        config.addAllowedOriginPattern("*");
36
+        // 设置访问源请求头
37
+        config.addAllowedHeader("*");
38
+        // 设置访问源请求方法
39
+        config.addAllowedMethod("*");
40
+        // 有效期 3600秒
41
+        config.setMaxAge(3600L);
42
+        // 添加映射路径,拦截一切请求
43
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
44
+        source.registerCorsConfiguration("/**", config);
45
+        // 返回新的CorsFilter
46
+        return new CorsFilter(source);
47
+    }
48
+}

+ 10 - 0
midware-api/src/main/java/midware/model/AjaxResult.java

@@ -0,0 +1,10 @@
1
+package midware.model;
2
+
3
+import lombok.Data;
4
+
5
+@Data
6
+public class AjaxResult {
7
+    private String state;
8
+    private String message;
9
+    private Object data;
10
+}

+ 8 - 0
midware-api/src/main/java/midware/model/PageResult.java

@@ -0,0 +1,8 @@
1
+package midware.model;
2
+
3
+import lombok.Data;
4
+
5
+@Data
6
+public class PageResult extends AjaxResult{
7
+    private Long total;
8
+}

+ 46 - 0
midware-api/src/main/resources/application-dev.yml

@@ -0,0 +1,46 @@
1
+server:
2
+  port: 9000
3
+swagger: true
4
+
5
+spring:
6
+  datasource:
7
+    type: com.alibaba.druid.pool.DruidDataSource
8
+    driver-class-name: com.mysql.cj.jdbc.Driver
9
+    url: jdbc:mysql://192.168.1.200:3306/midware?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true
10
+    username: root
11
+    password: 800100
12
+
13
+  redis:
14
+    # 地址
15
+    host: 192.168.1.200
16
+    # 端口,默认为6379
17
+    port: 6379
18
+    # 数据库索引
19
+    database: 8
20
+    # 密码
21
+    password:
22
+    # 连接超时时间
23
+    timeout: 10s
24
+
25
+  freeswitch:
26
+    #不在一台服务器时修改为具体ip
27
+    host: 192.168.1.19
28
+    port: 8021
29
+    password: 123456
30
+    timeout: 20
31
+
32
+common:
33
+  tts:
34
+    #modelscope/ekho
35
+    type: modelscope
36
+    url: http://192.168.1.17:8000/call
37
+
38
+  ai:
39
+    llm: http://192.168.1.40:7861/chat/chat
40
+    zsk: http://192.168.1.40:7861/chat/kb_chat
41
+    sjk: http://192.168.1.40:7861/chat/db_chat
42
+    es: http://192.168.1.15:8800/km/doc/getLastInfo
43
+
44
+  funasr: ws://192.168.1.40:10095
45
+  #funasr/mrcp
46
+  asr: funasr

+ 42 - 0
midware-api/src/main/resources/application-production.yml

@@ -0,0 +1,42 @@
1
+server:
2
+  port: 9000
3
+swagger: false
4
+
5
+spring:
6
+  datasource:
7
+    type: com.alibaba.druid.pool.DruidDataSource
8
+    driver-class-name: com.mysql.cj.jdbc.Driver
9
+    url: jdbc:mysql://172.16.20.169:3306/kfyy?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true
10
+    username: kfyy
11
+    password: 29oBbf6rVhAc0xdk
12
+
13
+  redis:
14
+    # 地址
15
+    host: 172.16.20.169
16
+    # 端口,默认为6379
17
+    port: 6379
18
+    # 数据库索引
19
+    database: 7
20
+    # 密码
21
+    password: iVDOLix2bCC21ZEY
22
+    # 连接超时时间
23
+    timeout: 10s
24
+
25
+  freeswitch:
26
+    #不在一台服务器时修改为具体ip
27
+    host: 0.0.0.0
28
+    port: 8021
29
+    password: irFNj6snoWpxGIhF
30
+    timeout: 20
31
+
32
+common:
33
+  tts:
34
+    #modelscope/ekho
35
+    type: modelscope
36
+    url: http://192.168.1.17:8000/call
37
+
38
+  ai:
39
+    zsk: http://192.168.1.40:7861/chat/kb_chat
40
+    sjk: http://192.168.1.40:7861/db_base/search_db
41
+
42
+  funasr: ws://192.168.1.40:10095

+ 32 - 0
midware-api/src/main/resources/application.yml

@@ -0,0 +1,32 @@
1
+spring:
2
+  jackson:
3
+    date-format: yyyy-MM-dd HH:mm:ss
4
+    time-zone: GMT+8
5
+  profiles:
6
+    #active: production
7
+    active: dev
8
+  servlet:
9
+    multipart:
10
+      max-file-size: 20MB #单个文件最大为20M
11
+      max-request-size: 20MB #单次请求文件总数大小为20M
12
+#  web:
13
+#    resources:
14
+#      static-locations: files
15
+
16
+mybatis-plus:
17
+  global-config:
18
+    db-config:
19
+      #全局id策略 自增id,只有当插入对象ID 为空,才自动填充。
20
+      id-type: auto
21
+      #逻辑未删除 默认0  字段需要在@TableLogic注解
22
+      logic-not-delete-value: 0
23
+      #逻辑删除  默认1  字段需要在@TableLogic注解
24
+      logic-delete-value: 1
25
+    banner: off
26
+    enable-sql-runner: true
27
+  configuration:
28
+    map-underscore-to-camel-case: true
29
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
30
+  mapper-locations: classpath*:mapper/**/*Mapper.xml
31
+  type-aliases-package: api.**.domain
32
+

+ 118 - 0
midware-api/src/main/resources/logback.xml

@@ -0,0 +1,118 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<configuration>
3
+    <!-- 日志存放路径 -->
4
+	<property name="log.path" value="logs" />
5
+    <!-- 日志输出格式 -->
6
+	<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} - %msg%n" />
7
+
8
+	<!-- 控制台输出 -->
9
+	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
10
+		<encoder>
11
+			<pattern>${log.pattern}</pattern>
12
+		</encoder>
13
+	</appender>
14
+	
15
+	<!-- 系统日志输出 -->
16
+	<appender name="info" class="ch.qos.logback.core.rolling.RollingFileAppender">
17
+
18
+        <!-- 循环政策:基于时间创建日志文件 -->
19
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
20
+            <!-- 日志文件名格式 -->
21
+			<fileNamePattern>${log.path}/%d{yyyy-MM-dd}/info.log</fileNamePattern>
22
+			<!-- 日志最大的历史 60天 -->
23
+			<maxHistory>60</maxHistory>
24
+		</rollingPolicy>
25
+		<encoder>
26
+			<pattern>${log.pattern}</pattern>
27
+		</encoder>
28
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
29
+            <!-- 过滤的级别 -->
30
+            <level>INFO</level>
31
+            <!-- 匹配时的操作:接收(记录) -->
32
+            <onMatch>ACCEPT</onMatch>
33
+            <!-- 不匹配时的操作:拒绝(不记录) -->
34
+            <onMismatch>DENY</onMismatch>
35
+        </filter>
36
+	</appender>
37
+	
38
+	<appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
39
+
40
+        <!-- 循环政策:基于时间创建日志文件 -->
41
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
42
+            <!-- 日志文件名格式 -->
43
+            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/error.log</fileNamePattern>
44
+			<!-- 日志最大的历史 60天 -->
45
+			<maxHistory>60</maxHistory>
46
+        </rollingPolicy>
47
+        <encoder>
48
+            <pattern>${log.pattern}</pattern>
49
+        </encoder>
50
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
51
+            <!-- 过滤的级别 -->
52
+            <level>ERROR</level>
53
+			<!-- 匹配时的操作:接收(记录) -->
54
+            <onMatch>ACCEPT</onMatch>
55
+			<!-- 不匹配时的操作:拒绝(不记录) -->
56
+            <onMismatch>DENY</onMismatch>
57
+        </filter>
58
+    </appender>
59
+    <appender name="warn" class="ch.qos.logback.core.rolling.RollingFileAppender">
60
+
61
+        <!-- 循环政策:基于时间创建日志文件 -->
62
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
63
+            <!-- 日志文件名格式 -->
64
+            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/warn.log</fileNamePattern>
65
+            <!-- 日志最大的历史 60天 -->
66
+            <maxHistory>60</maxHistory>
67
+        </rollingPolicy>
68
+        <encoder>
69
+            <pattern>${log.pattern}</pattern>
70
+        </encoder>
71
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
72
+            <!-- 过滤的级别 -->
73
+            <level>WARN</level>
74
+            <!-- 匹配时的操作:接收(记录) -->
75
+            <onMatch>ACCEPT</onMatch>
76
+            <!-- 不匹配时的操作:拒绝(不记录) -->
77
+            <onMismatch>DENY</onMismatch>
78
+        </filter>
79
+    </appender>
80
+    <appender name="debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
81
+
82
+        <!-- 循环政策:基于时间创建日志文件 -->
83
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
84
+            <!-- 日志文件名格式 -->
85
+            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/debug.log</fileNamePattern>
86
+            <!-- 日志最大的历史 60天 -->
87
+            <maxHistory>60</maxHistory>
88
+        </rollingPolicy>
89
+        <encoder>
90
+            <pattern>${log.pattern}</pattern>
91
+        </encoder>
92
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
93
+            <!-- 过滤的级别 -->
94
+            <level>DEBUG</level>
95
+            <!-- 匹配时的操作:接收(记录) -->
96
+            <onMatch>ACCEPT</onMatch>
97
+            <!-- 不匹配时的操作:拒绝(不记录) -->
98
+            <onMismatch>DENY</onMismatch>
99
+        </filter>
100
+    </appender>
101
+	
102
+	<!-- 系统模块日志级别控制  -->
103
+	<logger name="api" level="info" />
104
+	<!-- Spring日志级别控制  -->
105
+	<logger name="org.springframework" level="warn" />
106
+
107
+	<root level="info">
108
+		<appender-ref ref="console" />
109
+	</root>
110
+
111
+    <root level="info">
112
+        <appender-ref ref="info" />
113
+        <appender-ref ref="error" />
114
+        <appender-ref ref="warn" />
115
+        <appender-ref ref="debug" />
116
+    </root>
117
+
118
+</configuration> 

+ 28 - 0
midware-entity/pom.xml

@@ -0,0 +1,28 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <modelVersion>4.0.0</modelVersion>
6
+    <parent>
7
+        <groupId>midware</groupId>
8
+        <artifactId>midware-base</artifactId>
9
+        <version>1.0.0</version>
10
+    </parent>
11
+
12
+    <artifactId>midware-entity</artifactId>
13
+
14
+    <properties>
15
+        <maven.compiler.source>8</maven.compiler.source>
16
+        <maven.compiler.target>8</maven.compiler.target>
17
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18
+    </properties>
19
+    <dependencies>
20
+        <dependency>
21
+            <groupId>midware</groupId>
22
+            <artifactId>midware-util</artifactId>
23
+            <version>1.0.0</version>
24
+            <scope>compile</scope>
25
+        </dependency>
26
+    </dependencies>
27
+
28
+</project>

+ 42 - 0
midware-entity/src/main/java/midware/entity/database/rep/AgentAction.java

@@ -0,0 +1,42 @@
1
+package midware.entity.database.rep;
2
+
3
+import com.baomidou.mybatisplus.annotation.IdType;
4
+import com.baomidou.mybatisplus.annotation.TableId;
5
+import com.baomidou.mybatisplus.annotation.TableName;
6
+import lombok.Data;
7
+import java.util.Date;
8
+
9
+/** rep_agent_action */
10
+//@ApiModel(value = "AgentAction", description = "坐席操作表实体")
11
+@Data
12
+@TableName("rep_agent_action")
13
+public class AgentAction {
14
+    /** id */
15
+    //@ApiModelProperty("id")
16
+    @TableId(type = IdType.AUTO)
17
+    private Long id;
18
+    /** 坐席工号 */
19
+    //@ApiModelProperty("坐席工号")
20
+    private String agent;
21
+    /** 坐席组 */
22
+    //@ApiModelProperty("坐席组")
23
+    private String groupNo;
24
+    /** 分机 */
25
+    //@ApiModelProperty("分机")
26
+    private String exten;
27
+    /** 操作 */
28
+    //@ApiModelProperty("操作")
29
+    private String action;
30
+    /** 参数 */
31
+    //@ApiModelProperty("参数")
32
+    private String param;
33
+    /** 通话记录id */
34
+    //@ApiModelProperty("通话记录id")
35
+    private String uuid;
36
+    /** 是否成功 */
37
+    //@ApiModelProperty("是否成功")
38
+    private Integer isSuccess;
39
+    /** 创建时间 */
40
+    //@ApiModelProperty("创建时间")
41
+    private Date createTime;
42
+}

+ 36 - 0
midware-entity/src/main/java/midware/entity/database/rep/AgentState.java

@@ -0,0 +1,36 @@
1
+package midware.entity.database.rep;
2
+
3
+import com.baomidou.mybatisplus.annotation.IdType;
4
+import com.baomidou.mybatisplus.annotation.TableId;
5
+import com.baomidou.mybatisplus.annotation.TableName;
6
+import lombok.Data;
7
+import java.util.Date;
8
+
9
+/** 坐席状态表 */
10
+//@ApiModel(value = "AgentState", description = "坐席状态表实体")
11
+@Data
12
+@TableName("rep_agent_state")
13
+public class AgentState {
14
+    /** id */
15
+    //@ApiModelProperty("id")
16
+    @TableId(type = IdType.AUTO)
17
+    private Long id;
18
+    /** 坐席工号 */
19
+    //@ApiModelProperty("坐席工号")
20
+    private String agent;
21
+    /** 坐席组 */
22
+    //@ApiModelProperty("坐席组")
23
+    private String groupNo;
24
+    /** 分机 */
25
+    //@ApiModelProperty("分机")
26
+    private String exten;
27
+    /** 状态1登录中,2空闲,3通话中,4话后处理中,5忙碌,6振铃,7注销 */
28
+    //@ApiModelProperty("状态1登录中,2空闲,3通话中,4话后处理中,5忙碌,6振铃,7注销")
29
+    private Integer state;
30
+    /** 通话记录id */
31
+    //@ApiModelProperty("通话记录id")
32
+    private String uuid;
33
+    /** 创建时间 */
34
+    //@ApiModelProperty("创建时间")
35
+    private Date createTime;
36
+}

+ 31 - 0
midware-entity/src/main/java/midware/entity/database/rep/ChanEvent.java

@@ -0,0 +1,31 @@
1
+package midware.entity.database.rep;
2
+
3
+import com.baomidou.mybatisplus.annotation.IdType;
4
+import com.baomidou.mybatisplus.annotation.TableId;
5
+import com.baomidou.mybatisplus.annotation.TableName;
6
+import lombok.Data;
7
+
8
+import java.util.Date;
9
+
10
+/** 通道事件表 */
11
+//@ApiModel(value = "ChanEvent", description = "通道事件表实体")
12
+@Data
13
+@TableName("rep_chan_event")
14
+public class ChanEvent {
15
+    /** id */
16
+    //@ApiModelProperty("id")
17
+    @TableId(type = IdType.AUTO)
18
+    private Long id;
19
+    /** 通道 */
20
+    //@ApiModelProperty("通道")
21
+    private String chan;
22
+    /** 事件 */
23
+    //@ApiModelProperty("事件")
24
+    private String event;
25
+    /** 会话id */
26
+    //@ApiModelProperty("会话id")
27
+    private String uuid;
28
+    /** 创建时间 */
29
+    //@ApiModelProperty("创建时间")
30
+    private Date createTime;
31
+}

+ 26 - 0
midware-entity/src/main/java/midware/entity/database/rep/Config.java

@@ -0,0 +1,26 @@
1
+package midware.entity.database.rep;
2
+
3
+import com.baomidou.mybatisplus.annotation.IdType;
4
+import com.baomidou.mybatisplus.annotation.TableId;
5
+import com.baomidou.mybatisplus.annotation.TableName;
6
+import lombok.Data;
7
+
8
+/** rep_config */
9
+//@ApiModel(value = "Config", description = "配置表")
10
+@Data
11
+@TableName("rep_config")
12
+public class Config {
13
+    /** 自增主键 */
14
+    //@ApiModelProperty("自增主键")
15
+    @TableId(type = IdType.AUTO)
16
+    private Integer id;
17
+    /** 编码 */
18
+    //@ApiModelProperty("编码")
19
+    private String code;
20
+    /** 值 */
21
+    //@ApiModelProperty("值")
22
+    private String value;
23
+    /** 描述 */
24
+    //@ApiModelProperty("描述")
25
+    private String remark;
26
+}

+ 61 - 0
midware-entity/src/main/java/midware/entity/database/rep/Ivr.java

@@ -0,0 +1,61 @@
1
+package midware.entity.database.rep;
2
+
3
+import com.baomidou.mybatisplus.annotation.IdType;
4
+import com.baomidou.mybatisplus.annotation.TableId;
5
+import com.baomidou.mybatisplus.annotation.TableName;
6
+import lombok.Data;
7
+
8
+import java.util.Date;
9
+
10
+/** call_ivr */
11
+//@ApiModel(value = "Ivr", description = "call_ivr实体")
12
+@Data
13
+@TableName("rep_ivr")
14
+public class Ivr {
15
+    /** 自增id */
16
+    //@ApiModelProperty("自增id")
17
+    @TableId(type = IdType.AUTO)
18
+    private Long ivrId;
19
+    /** 名称 */
20
+    //@ApiModelProperty("名称")
21
+    private String name;
22
+    /** json */
23
+    //@ApiModelProperty("json")
24
+    private String json;
25
+    /** context */
26
+    //@ApiModelProperty("context")
27
+    private String context;
28
+    /** menu */
29
+    //@ApiModelProperty("menu")
30
+    private String menu;
31
+    /** 路径 */
32
+    //@ApiModelProperty("路径")
33
+    private String path;
34
+    /** 版本 */
35
+    //@ApiModelProperty("版本")
36
+    private String version;
37
+    /** 备注 */
38
+    //@ApiModelProperty("备注")
39
+    private String remark;
40
+    /** 删除标志(0代表存在 2代表删除) */
41
+    //@ApiModelProperty("删除标志(0代表存在 2代表删除)")
42
+    private String delFlag;
43
+    /** 创建者 */
44
+    //@ApiModelProperty("创建者")
45
+    private String createBy;
46
+    /** 创建时间 */
47
+    //@ApiModelProperty("创建时间")
48
+    private Date createTime;
49
+    /** 更新者 */
50
+    //@ApiModelProperty("更新者")
51
+    private String updateBy;
52
+    /** 更新时间 */
53
+    //@ApiModelProperty("更新时间")
54
+    private Date updateTime;
55
+    /** 删除者 */
56
+    //@ApiModelProperty("删除者")
57
+    private String delBy;
58
+    /** 删除时间 */
59
+    //@ApiModelProperty("删除时间")
60
+    private Date delTime;
61
+}

+ 90 - 0
midware-entity/src/main/java/midware/entity/database/rep/Record.java

@@ -0,0 +1,90 @@
1
+package midware.entity.database.rep;
2
+
3
+import com.baomidou.mybatisplus.annotation.IdType;
4
+import com.baomidou.mybatisplus.annotation.TableId;
5
+import com.baomidou.mybatisplus.annotation.TableName;
6
+import lombok.Data;
7
+import java.util.Date;
8
+
9
+/** 通话记录表 */
10
+//@ApiModel(value = "Record", description = "通话记录表实体")
11
+@Data
12
+@TableName("rep_record")
13
+public class Record {
14
+    /** id */
15
+    //@ApiModelProperty("id")
16
+    @TableId(type = IdType.AUTO)
17
+    private Long id;
18
+    /** 会话标识,进行转移时会重复出现,这时和action_id一起可以组成唯一值 */
19
+    //@ApiModelProperty("会话标识,进行转移时会重复出现,这时和action_id一起可以组成唯一值")
20
+    private String uuid;
21
+    /** 会话标识,uuid+action_id 组合成唯一值 */
22
+    //@ApiModelProperty("会话标识,uuid+action_id 组合成唯一值")
23
+    private Integer actionId;
24
+    /** 是否视频 */
25
+    //@ApiModelProperty("是否视频")
26
+    private Integer isVideo;
27
+    /** 主叫坐席工号,分机为主叫且签入才会有值,否则为空 */
28
+    //@ApiModelProperty("主叫坐席工号,分机为主叫且签入才会有值,否则为空")
29
+    private String callerAgent;
30
+    /** 主叫号码,分机号或者手机号 */
31
+    //@ApiModelProperty("主叫号码,分机号或者手机号")
32
+    private String caller;
33
+    /** 中继号,手机号呼入系统时拨打号码(底号) */
34
+    //@ApiModelProperty("中继号,手机号呼入系统时拨打号码(底号)")
35
+    private String trunkNum;
36
+    /** 被叫坐席工号,分机为被叫且签入才会有值,否则为空 */
37
+    //@ApiModelProperty("被叫坐席工号,分机为被叫且签入才会有值,否则为空")
38
+    private String calleeAgent;
39
+    /** 被叫号码,分机号或手机号 */
40
+    //@ApiModelProperty("被叫号码,分机号或手机号")
41
+    private String callee;
42
+    /** 被叫坐席组 */
43
+    //@ApiModelProperty("被叫坐席组")
44
+    private String groupNo;
45
+    /** 呼叫类型,0呼入(外线即手机号打进系统),1呼出 */
46
+    //@ApiModelProperty("呼叫类型,0呼入(外线即手机号打进系统),1呼出")
47
+    private Integer callType;
48
+    /** 呼入系统时间 */
49
+    //@ApiModelProperty("呼入系统时间")
50
+    private Date createTime;
51
+    /** 等待开始时间 */
52
+    //@ApiModelProperty("等待开始时间")
53
+    private Date waitTime;
54
+    /** 被叫振铃时间 */
55
+    //@ApiModelProperty("被叫振铃时间")
56
+    private Date ringTime;
57
+    /** 被叫应答时间 */
58
+    //@ApiModelProperty("被叫应答时间")
59
+    private Date answerTime;
60
+    /** 被叫是否接听 */
61
+    //@ApiModelProperty("被叫是否接听")
62
+    private Integer isAnswer;
63
+    /** 挂机时间 */
64
+    //@ApiModelProperty("挂机时间")
65
+    private Date hangupTime;
66
+    /** 操作类型 */
67
+    //@ApiModelProperty("操作类型,转移,会议,留言")
68
+    private String opType;
69
+    /** 挂机原因,意义不大 */
70
+    //@ApiModelProperty("挂机原因,意义不大")
71
+    private String hangupCause;
72
+    /** 满意度,1,2,3 */
73
+    //@ApiModelProperty("满意度,1,2,3")
74
+    private Integer myd;
75
+    /** 目前只用来记录是否是黑名单,记录内容为“blacklist” */
76
+    //@ApiModelProperty("目前只用来记录是否是黑名单,记录内容为“blacklist”")
77
+    private String note;
78
+    /** 录音路径 */
79
+    //@ApiModelProperty("录音路径")
80
+    private String recordPath;
81
+    /** 留言开始时间 */
82
+    //@ApiModelProperty("留言开始时间")
83
+    private Date leaveTime;
84
+    /** 网关ip */
85
+    //@ApiModelProperty("网关ip")
86
+    private String gatwayip;
87
+    /** 留言路径 */
88
+    //@ApiModelProperty("留言路径")
89
+    private String leavePath;
90
+}

+ 14 - 0
midware-entity/src/main/java/midware/entity/input/CodeInput.java

@@ -0,0 +1,14 @@
1
+package midware.entity.input;
2
+
3
+import lombok.Data;
4
+
5
+//@ApiModel(value = "CodeInput", description = "代码生成实体")
6
+@Data
7
+public class CodeInput {
8
+    //@ApiModelProperty("包名")
9
+    private String packageName;
10
+    //@ApiModelProperty("控制器名")
11
+    private String controllerName;
12
+    //@ApiModelProperty("表名")
13
+    private String tableName;
14
+}

+ 12 - 0
midware-entity/src/main/java/midware/entity/input/PageInput.java

@@ -0,0 +1,12 @@
1
+package midware.entity.input;
2
+
3
+import lombok.Data;
4
+
5
+//@ApiModel(value = "PageInput", description = "分页实体")
6
+@Data
7
+public class PageInput{
8
+    //@ApiModelProperty("页码")
9
+    private Integer pageNum;
10
+    //@ApiModelProperty("每页条数")
11
+    private Integer pageSize;
12
+}

+ 14 - 0
midware-entity/src/main/java/midware/entity/input/rep/IvrInput.java

@@ -0,0 +1,14 @@
1
+package midware.entity.input.rep;
2
+
3
+import lombok.Data;
4
+
5
+import java.util.List;
6
+
7
+@Data
8
+public class IvrInput {
9
+    //路径集合
10
+    private List<Path> paths;
11
+    //节点集合
12
+    private List<Node> nodes;
13
+}
14
+

+ 18 - 0
midware-entity/src/main/java/midware/entity/input/rep/Node.java

@@ -0,0 +1,18 @@
1
+package midware.entity.input.rep;
2
+
3
+import midware.util.enums.IvrType;
4
+import lombok.Data;
5
+
6
+import java.util.Map;
7
+
8
+@Data
9
+public class Node {
10
+    //ID
11
+    private Integer id;
12
+    //名称
13
+    private String name;
14
+    //类型
15
+    private IvrType type;
16
+    //属性
17
+    private Map<String,Object> attr;
18
+}

+ 19 - 0
midware-entity/src/main/java/midware/entity/input/rep/Path.java

@@ -0,0 +1,19 @@
1
+package midware.entity.input.rep;
2
+
3
+import lombok.Data;
4
+
5
+@Data
6
+public class Path {
7
+    //ID
8
+    private Integer id;
9
+    //名称
10
+    private String name;
11
+    //开始节点
12
+    private Integer from;
13
+    //目标节点
14
+    private Integer to;
15
+    //变量
16
+    private String field;
17
+    //条件
18
+    private String expression;
19
+}

+ 28 - 0
midware-mapper/pom.xml

@@ -0,0 +1,28 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <modelVersion>4.0.0</modelVersion>
6
+    <parent>
7
+        <groupId>midware</groupId>
8
+        <artifactId>midware-base</artifactId>
9
+        <version>1.0.0</version>
10
+    </parent>
11
+
12
+    <artifactId>midware-mapper</artifactId>
13
+
14
+    <properties>
15
+        <maven.compiler.source>8</maven.compiler.source>
16
+        <maven.compiler.target>8</maven.compiler.target>
17
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18
+    </properties>
19
+    <dependencies>
20
+        <dependency>
21
+            <groupId>midware</groupId>
22
+            <artifactId>midware-entity</artifactId>
23
+            <version>1.0.0</version>
24
+            <scope>compile</scope>
25
+        </dependency>
26
+    </dependencies>
27
+
28
+</project>

+ 9 - 0
midware-mapper/src/main/java/midware/mapper/rep/AgentActionMapper.java

@@ -0,0 +1,9 @@
1
+package midware.mapper.rep;
2
+
3
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
+import midware.entity.database.rep.AgentAction;
5
+import org.apache.ibatis.annotations.Mapper;
6
+
7
+@Mapper
8
+public interface AgentActionMapper extends BaseMapper<AgentAction> {
9
+}

+ 9 - 0
midware-mapper/src/main/java/midware/mapper/rep/AgentStateMapper.java

@@ -0,0 +1,9 @@
1
+package midware.mapper.rep;
2
+
3
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
+import midware.entity.database.rep.AgentState;
5
+import org.apache.ibatis.annotations.Mapper;
6
+
7
+@Mapper
8
+public interface AgentStateMapper extends BaseMapper<AgentState> {
9
+}

+ 9 - 0
midware-mapper/src/main/java/midware/mapper/rep/ChanEventMapper.java

@@ -0,0 +1,9 @@
1
+package midware.mapper.rep;
2
+
3
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
+import midware.entity.database.rep.ChanEvent;
5
+import org.apache.ibatis.annotations.Mapper;
6
+
7
+@Mapper
8
+public interface ChanEventMapper extends BaseMapper<ChanEvent> {
9
+}

+ 9 - 0
midware-mapper/src/main/java/midware/mapper/rep/ConfigMapper.java

@@ -0,0 +1,9 @@
1
+package midware.mapper.rep;
2
+
3
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
+import midware.entity.database.rep.Config;
5
+import org.apache.ibatis.annotations.Mapper;
6
+
7
+@Mapper
8
+public interface ConfigMapper extends BaseMapper<Config> {
9
+}

+ 9 - 0
midware-mapper/src/main/java/midware/mapper/rep/IvrMapper.java

@@ -0,0 +1,9 @@
1
+package midware.mapper.rep;
2
+
3
+import midware.entity.database.rep.Ivr;
4
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5
+import org.apache.ibatis.annotations.Mapper;
6
+
7
+@Mapper
8
+public interface IvrMapper extends BaseMapper<Ivr> {
9
+}

+ 9 - 0
midware-mapper/src/main/java/midware/mapper/rep/RecordMapper.java

@@ -0,0 +1,9 @@
1
+package midware.mapper.rep;
2
+
3
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
+import midware.entity.database.rep.Record;
5
+import org.apache.ibatis.annotations.Mapper;
6
+
7
+@Mapper
8
+public interface RecordMapper extends BaseMapper<Record> {
9
+}

+ 40 - 0
midware-service/pom.xml

@@ -0,0 +1,40 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <modelVersion>4.0.0</modelVersion>
6
+    <parent>
7
+        <groupId>midware</groupId>
8
+        <artifactId>midware-base</artifactId>
9
+        <version>1.0.0</version>
10
+    </parent>
11
+
12
+    <artifactId>midware-service</artifactId>
13
+
14
+    <properties>
15
+        <maven.compiler.source>8</maven.compiler.source>
16
+        <maven.compiler.target>8</maven.compiler.target>
17
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18
+        <api.version>1.0.0</api.version>
19
+    </properties>
20
+
21
+    <dependencies>
22
+        <dependency>
23
+            <groupId>midware</groupId>
24
+            <artifactId>midware-util</artifactId>
25
+            <version>${api.version}</version>
26
+        </dependency>
27
+        <dependency>
28
+            <groupId>midware</groupId>
29
+            <artifactId>midware-entity</artifactId>
30
+            <version>${api.version}</version>
31
+        </dependency>
32
+        <dependency>
33
+            <groupId>midware</groupId>
34
+            <artifactId>midware-mapper</artifactId>
35
+            <version>${api.version}</version>
36
+        </dependency>
37
+
38
+    </dependencies>
39
+
40
+</project>

+ 234 - 0
midware-service/src/main/java/midware/service/BaseServiceImpl.java

@@ -0,0 +1,234 @@
1
+package midware.service;
2
+
3
+import com.baomidou.mybatisplus.annotation.TableName;
4
+import midware.util.helper.RedisHelper;
5
+import midware.util.helper.SpringHelper;
6
+import midware.util.helper.StringHelper;
7
+import com.alibaba.fastjson2.JSON;
8
+import com.baomidou.mybatisplus.annotation.TableId;
9
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
10
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
11
+import com.baomidou.mybatisplus.core.metadata.IPage;
12
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
13
+
14
+import java.io.Serializable;
15
+import java.lang.reflect.Field;
16
+import java.util.Collection;
17
+import java.util.List;
18
+import java.util.Map;
19
+import java.util.Objects;
20
+import java.util.concurrent.TimeUnit;
21
+import java.util.function.Function;
22
+
23
+
24
+public class BaseServiceImpl<M extends BaseMapper<T>,T> extends ServiceImpl<M,T> implements IBaseService<T> {
25
+    private boolean enableCache;
26
+
27
+    public BaseServiceImpl(boolean cache) {
28
+        enableCache = cache;
29
+    }
30
+
31
+    //存在
32
+    @Override
33
+    public boolean exists(Wrapper<T> queryWrapper) {
34
+        return this.count(queryWrapper) > 0;
35
+    }
36
+
37
+    //插入单条
38
+    @Override
39
+    public boolean insert(T entity) {
40
+        if (enableCache) {
41
+            removeCache();
42
+        }
43
+        return this.save(entity);
44
+    }
45
+
46
+    //插入多条
47
+    @Override
48
+    public boolean insert(List<T> entities) {
49
+        if (enableCache) {
50
+            removeCache();
51
+        }
52
+        return this.saveBatch(entities, entities.size());
53
+    }
54
+
55
+    //更新
56
+    @Override
57
+    public boolean update(T entity) {
58
+        if (enableCache) {
59
+            removeCache();
60
+        }
61
+        return this.updateById(entity);
62
+    }
63
+
64
+    @Override
65
+    public boolean update(List<T> entities) {
66
+        if (enableCache) {
67
+            removeCache();
68
+        }
69
+        return this.updateBatchById(entities);
70
+    }
71
+
72
+    //根据条件更新
73
+    @Override
74
+    public boolean updateBatch(Wrapper<T> updateWrapper) {
75
+        if (enableCache) {
76
+            removeCache();
77
+        }
78
+        return this.update(updateWrapper);
79
+    }
80
+
81
+    //根据条件更新
82
+    @Override
83
+    public boolean updateBatch(T entity, Wrapper<T> updateWrapper) {
84
+        if (enableCache) {
85
+            removeCache();
86
+        }
87
+        return this.update(entity, updateWrapper);
88
+    }
89
+
90
+    //删除
91
+    @Override
92
+    public boolean delete(Serializable id) {
93
+        if (enableCache) {
94
+            removeCache();
95
+        }
96
+        return this.removeById(id);
97
+    }
98
+
99
+    //删除多个
100
+    @Override
101
+    public boolean delete(Collection<? extends Serializable> ids) {
102
+        if (enableCache) {
103
+            removeCache();
104
+        }
105
+        return this.removeByIds(ids);
106
+    }
107
+
108
+    //根据条件删除
109
+    @Override
110
+    public boolean delete(Wrapper<T> queryWrapper) {
111
+        if (enableCache) {
112
+            removeCache();
113
+        }
114
+        return this.remove(queryWrapper);
115
+    }
116
+
117
+    //根据条件获取数量
118
+    @Override
119
+    public long getCount(Wrapper<T> queryWrapper) {
120
+        return this.count(queryWrapper);
121
+    }
122
+
123
+    //获取实体
124
+    @Override
125
+    public T getEntity(Serializable id) {
126
+        if (enableCache) {
127
+            for (Field f : this.entityClass.getDeclaredFields()) {
128
+                if (f.getAnnotationsByType(TableId.class) != null) {
129
+                    for (T p : getListByCache()) {
130
+                        try {
131
+                            f.setAccessible(true);
132
+                            if (Objects.equals(f.get(p).toString(), id.toString())) {
133
+                                return p;
134
+                            }
135
+                        } catch (IllegalAccessException e) {
136
+                            throw new RuntimeException(e);
137
+                        }
138
+                    }
139
+                }
140
+            }
141
+        }
142
+        return this.getById(id);
143
+    }
144
+
145
+    //根据条件获取实体
146
+    @Override
147
+    public T getEntity(Wrapper<T> queryWrapper) {
148
+        return this.getOne(queryWrapper);
149
+    }
150
+
151
+    //根据条件获取实体指定字段
152
+    @Override
153
+    public Map<String, Object> getMapFirst(Wrapper<T> queryWrapper) {
154
+        return this.getMap(queryWrapper);
155
+    }
156
+
157
+    //获取列表
158
+    @Override
159
+    public List<T> getList() {
160
+        if (enableCache) {
161
+            return getListByCache();
162
+        }
163
+        return this.list();
164
+    }
165
+
166
+    //根据条件获取列表
167
+    @Override
168
+    public List<T> getList(Wrapper<T> queryWrapper) {
169
+        return this.list(queryWrapper);
170
+    }
171
+
172
+    //根据主键集合获取列表
173
+    @Override
174
+    public List<T> getListByIds(Collection<? extends Serializable> ids) {
175
+        return baseMapper.selectBatchIds(ids);
176
+    }
177
+
178
+    //根据条件获取列表指定字段
179
+    @Override
180
+    public List<Map<String, Object>> getMaps(Wrapper<T> queryWrapper) {
181
+        return baseMapper.selectMaps(queryWrapper);
182
+    }
183
+
184
+    ;
185
+
186
+    //获取第一个字段集合
187
+    @Override
188
+    public <V> List<V> getObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
189
+        return this.listObjs(queryWrapper, mapper);
190
+    }
191
+
192
+    //获取第一个字段集合
193
+    @Override
194
+    public List<Object> getObjs(Wrapper<T> queryWrapper) {
195
+        return this.listObjs(queryWrapper);
196
+    }
197
+
198
+    //分页
199
+    @Override
200
+    public <E extends IPage<T>> E getListPage(E page, Wrapper<T> queryWrapper) {
201
+        return this.page(page, queryWrapper);
202
+    }
203
+
204
+    //分页
205
+    @Override
206
+    public <E extends IPage<Map<String, Object>>> E getListMapPage(E page, Wrapper<T> queryWrapper) {
207
+        return this.pageMaps(page, queryWrapper);
208
+    }
209
+
210
+
211
+    private List<T> getListByCache() {
212
+        RedisHelper redisHelper = SpringHelper.getBean(RedisHelper.class);
213
+
214
+        String clsName = this.entityClass.getAnnotation(TableName.class).value();
215
+        String json = redisHelper.getCache("database:" + clsName);
216
+        if (StringHelper.isEmpty(json)) {
217
+            List<T> list = this.list();
218
+            redisHelper.setCache("database:" + clsName, JSON.toJSONString(list), 1, TimeUnit.DAYS);
219
+            return list;
220
+        } else {
221
+            return JSON.parseArray(json, this.entityClass);
222
+        }
223
+    }
224
+
225
+    private boolean removeCache() {
226
+        RedisHelper redisHelper = SpringHelper.getBean(RedisHelper.class);
227
+
228
+        String clsName = this.entityClass.getAnnotation(TableName.class).value();
229
+        if (redisHelper.hasKey("database:"  + clsName)) {
230
+            return redisHelper.deleteCache("database:" + clsName);
231
+        }
232
+        return true;
233
+    }
234
+}

+ 70 - 0
midware-service/src/main/java/midware/service/IBaseService.java

@@ -0,0 +1,70 @@
1
+package midware.service;
2
+
3
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
4
+import com.baomidou.mybatisplus.core.metadata.IPage;
5
+
6
+import java.io.Serializable;
7
+import java.util.Collection;
8
+import java.util.List;
9
+import java.util.Map;
10
+import java.util.function.Function;
11
+
12
+/**
13
+ * @author Administrator
14
+ */
15
+public interface IBaseService<T> {
16
+    //存在
17
+    boolean exists(Wrapper<T> queryWrapper);
18
+    //插入单条
19
+    boolean insert(T entity);
20
+    //插入多条
21
+    boolean insert(List<T> entities);
22
+    //更新
23
+    boolean update(T entity);
24
+    //更新多条
25
+    boolean update(List<T> entities);
26
+    //根据条件更新
27
+    boolean updateBatch(Wrapper<T> queryWrapper);
28
+    //根据条件更新
29
+    boolean updateBatch(T entity,Wrapper<T> queryWrapper);
30
+    //删除
31
+    boolean delete(Serializable id);
32
+    //删除多个
33
+    boolean delete(Collection<? extends Serializable> ids);
34
+    //根据条件删除
35
+    boolean delete(Wrapper<T> queryWrapper);
36
+    //根据条件获取数量
37
+    long getCount(Wrapper<T> queryWrapper);
38
+    //获取实体
39
+    T getEntity(Serializable id);
40
+
41
+    //根据条件获取实体
42
+    T getEntity(Wrapper<T> queryWrapper);
43
+
44
+    //根据条件获取实体指定字段
45
+    Map<String, Object> getMapFirst(Wrapper<T> queryWrapper);
46
+
47
+    //获取列表
48
+    List<T> getList();
49
+
50
+    //根据条件获取列表
51
+    List<T> getList(Wrapper<T> queryWrapper);
52
+
53
+    //根据主键集合获取列表
54
+    List<T> getListByIds(Collection<? extends Serializable> ids);
55
+
56
+    //获取指定字段集合
57
+    List<Map<String, Object>> getMaps(Wrapper<T> queryWrapper);
58
+
59
+    //获取第一个字段集合
60
+    <V> List<V> getObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
61
+
62
+    //获取第一个字段集合
63
+    List<Object> getObjs(Wrapper<T> queryWrapper);
64
+
65
+    //分页
66
+    <E extends IPage<T>> E getListPage(E page, Wrapper<T> queryWrapper);
67
+
68
+    //分页
69
+    <E extends IPage<Map<String, Object>>> E getListMapPage(E page, Wrapper<T> queryWrapper);
70
+}

+ 225 - 0
midware-service/src/main/java/midware/service/eslclient/EslCommon.java

@@ -0,0 +1,225 @@
1
+package midware.service.eslclient;
2
+
3
+import com.alibaba.fastjson2.JSON;
4
+import lombok.extern.slf4j.Slf4j;
5
+import midware.entity.database.rep.*;
6
+import midware.service.eslclient.entity.Agent;
7
+import midware.service.eslclient.entity.Auth;
8
+import midware.service.eslclient.entity.Channel;
9
+import midware.service.eslclient.entity.Session;
10
+import midware.service.init.EslClientService;
11
+import midware.service.init.WebSocketService;
12
+import midware.util.enums.EslAgentEnum;
13
+import midware.util.helper.IpHelper;
14
+import midware.util.helper.SecretHelper;
15
+import midware.util.helper.SpringHelper;
16
+import midware.util.helper.StringHelper;
17
+import org.w3c.dom.Document;
18
+import org.w3c.dom.NodeList;
19
+import org.xml.sax.InputSource;
20
+
21
+import javax.xml.parsers.DocumentBuilder;
22
+import javax.xml.parsers.DocumentBuilderFactory;
23
+import java.io.*;
24
+import java.nio.charset.StandardCharsets;
25
+import java.nio.file.Files;
26
+import java.text.ParseException;
27
+import java.text.SimpleDateFormat;
28
+import java.util.*;
29
+import java.util.stream.Collectors;
30
+
31
+@Slf4j
32
+public class EslCommon {
33
+    //授权信息
34
+    public static Auth auth=new Auth();
35
+    //坐席列表
36
+    public static List<Agent> agents=new ArrayList<>();
37
+    //通道列表
38
+    public static List<Channel> channels=new ArrayList<>();
39
+    //会话列表
40
+    public static List<Session> sessions=new ArrayList<>();
41
+    //坐席组排队列表
42
+    public static Map<String,List<String>> groupWaitList=new HashMap<>();
43
+    //坐席组临时列表
44
+    public static Map<String,List<String>> groupTempList=new HashMap<>();
45
+    //坐席操作临时列表
46
+    public static Map<String,AgentAction> actionTempList=new HashMap<>();
47
+
48
+    public static List<AgentAction> actions=new ArrayList<>();
49
+    public static List<AgentState> states=new ArrayList<>();
50
+    public static List<ChanEvent> events=new ArrayList<>();
51
+
52
+    //坐席是否存在
53
+    public static boolean existAgent(String agent){
54
+        return agents.stream().anyMatch(p ->p.getAgent().equals(agent));
55
+    }
56
+    //根据分机获取坐席
57
+    public static Agent getAgentByExten(String exten) {
58
+        List<Agent> cs = agents.stream().filter(p -> p.getExten().equals(exten)).collect(Collectors.toList());
59
+        if (cs.size() > 0) {
60
+            return cs.get(0);
61
+        }
62
+        return null;
63
+    }
64
+    //根据工号获取坐席
65
+    public static Agent getAgent(String agent) {
66
+        List<Agent> cs = agents.stream().filter(p -> p.getAgent().equals(agent)).collect(Collectors.toList());
67
+        if (cs.size() > 0) {
68
+            return cs.get(0);
69
+        }
70
+        return null;
71
+    }
72
+
73
+    //分机是否存在
74
+    public static boolean existExten(String exten){
75
+        return channels.stream().anyMatch(p -> p.getType() == 1 && p.getNumber().equals(exten));
76
+    }
77
+
78
+    //根据id获取通道
79
+    public static Channel getChanByNumber(String number) {
80
+        List<Channel> cs = channels.stream().filter(p -> p.getNumber().equals(number)).collect(Collectors.toList());
81
+        if (cs.size() > 0) {
82
+            return cs.get(0);
83
+        }
84
+        return null;
85
+    }
86
+
87
+    //根据分机获取通道
88
+    public static Channel getChanByExten(String exten) {
89
+        List<Channel> cs = channels.stream().filter(p -> p.getType() == 1 && p.getNumber().equals(exten)).collect(Collectors.toList());
90
+        if (cs.size() > 0) {
91
+            return cs.get(0);
92
+        }
93
+        return null;
94
+    }
95
+    //新增通道
96
+    public static Channel addChanel(String number){
97
+        Channel chan = new Channel();
98
+        chan.setNumber(number);
99
+        channels.add(chan);
100
+        return chan;
101
+    }
102
+
103
+    //根据会话id获取第一个通道
104
+    public static Channel getFirstChanBySessionId(String sessionId) {
105
+        List<Channel> cs = channels.stream().filter(p -> p.getSessionId().equals(sessionId) && p.getSessionSort() == 1).collect(Collectors.toList());
106
+        if (cs.size() > 0) {
107
+            return cs.get(0);
108
+        }
109
+        return null;
110
+    }
111
+
112
+    //根据id获取会话
113
+    public static Session getSessionById(String id){
114
+        List<Session> cs=sessions.stream().filter(p -> p.getSessionId().equals(id)).collect(Collectors.toList());
115
+        if(cs.size()>0){
116
+            return cs.get(0);
117
+        }
118
+        return null;
119
+    }
120
+
121
+    //号码是否在会话中
122
+    public static boolean isInSession(String number) {
123
+        return channels.stream().anyMatch(p -> p.getNumber().equals(number) && !p.getSessionId().equals(""));
124
+    }
125
+
126
+    //删除排队
127
+    public static void delWait(String queue,String phone){
128
+        if (EslCommon.groupTempList.containsKey(queue)) {
129
+            EslCommon.groupTempList.get(queue).remove(phone);
130
+        }
131
+        if (EslCommon.groupWaitList.containsKey(queue)) {
132
+            if (EslCommon.groupWaitList.get(queue).remove(phone)) {
133
+                //排队数量
134
+                Map<String, Object> result = new HashMap<>();
135
+                result.put("Type", "Wait");
136
+                result.put("Result", true);
137
+                result.put("Count", EslCommon.groupWaitList.get(queue).size());
138
+                SpringHelper.getBean(WebSocketService.class).sendMessageGroupAll(queue, JSON.toJSONString(result));
139
+            }
140
+        }
141
+    }
142
+
143
+    //获取识别结果
144
+    public static String getXmlResult(String xml, boolean islm) {
145
+        String result = "";
146
+        try {
147
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
148
+            DocumentBuilder builder = factory.newDocumentBuilder();
149
+            InputSource source = new InputSource(new StringReader(xml));
150
+            Document document = builder.parse(source);
151
+            NodeList list = document.getElementsByTagName("nlresult");
152
+            if (list.getLength() > 0) {
153
+                String[] results = list.item(0).getTextContent().split("\\|");
154
+                if (results.length > 1 && StringHelper.isNotEmpty(results[1])) {
155
+                    result = results[1];
156
+                    //乱码处理
157
+                    if (islm) {
158
+                        byte[] bytes = result.getBytes("Unicode");
159
+                        List<Byte> byteList = new LinkedList<>();
160
+                        for (int i = 0; i < bytes.length; ++i) {
161
+                            if (i % 2 == 0 || i == 1) {
162
+                                continue;
163
+                            }
164
+                            byteList.add(bytes[i]);
165
+                        }
166
+                        byte[] bytes2 = new byte[byteList.size()];
167
+                        for (int k = 0; k < byteList.size(); ++k) {
168
+                            bytes2[k] = byteList.get(k);
169
+                        }
170
+                        result = new String(bytes2, StandardCharsets.UTF_8);
171
+                    }
172
+                }
173
+            }
174
+        } catch (Exception e) {
175
+            log.error("xml解析失败:" + xml, e);
176
+        }
177
+        return result;
178
+    }
179
+
180
+    public static void checkAuth(){
181
+        boolean isAuth = false;
182
+        Date time = null;
183
+        int agentNum = 0;
184
+        try {
185
+            File file = new File("jyxx");
186
+            if (file.exists()) {
187
+                String s = "";
188
+                InputStreamReader in = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8);
189
+                BufferedReader br = new BufferedReader(in);
190
+                StringBuilder sb = new StringBuilder();
191
+                while ((s = br.readLine()) != null) {
192
+                    sb.append(s);
193
+                }
194
+                String content = sb.toString();
195
+                String result = SecretHelper.AesDecrypt(new String(Base64.getDecoder().decode(content)));
196
+                if (StringHelper.isNotEmpty(result)) {
197
+                    String[] results = result.split("\\|");
198
+                    if (SecretHelper.MD5(IpHelper.getMac()).equals(results[0])) {
199
+                        time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(results[1] + " 23:59:59");
200
+                        agentNum = Integer.parseInt(results[2]);
201
+                        isAuth = true;
202
+                    }
203
+                }
204
+            }
205
+
206
+        } catch (IOException | ParseException e) {
207
+            log.error("授权解析失败", e);
208
+        }
209
+        if (isAuth && time.compareTo(new Date()) > 0) {
210
+            EslCommon.auth.setExpire(false);
211
+            EslCommon.auth.setExpireTime(time);
212
+            EslCommon.auth.setAgentNum(agentNum);
213
+        } else {
214
+            EslCommon.auth = new Auth();
215
+            if (EslCommon.agents.size() > 0) {
216
+                EslClientService eslClientService = SpringHelper.getBean(EslClientService.class);
217
+                for (Agent a : EslCommon.agents) {
218
+                    eslClientService.logout(a.getAgent(), a.getGroup(),"");
219
+                    a.setAgentState(EslAgentEnum.logout.ordinal());
220
+                }
221
+                EslCommon.agents=new ArrayList<>();
222
+            }
223
+        }
224
+    }
225
+}

+ 150 - 0
midware-service/src/main/java/midware/service/eslclient/EslEventListenerCustom.java

@@ -0,0 +1,150 @@
1
+package midware.service.eslclient;
2
+
3
+import com.alibaba.fastjson2.JSON;
4
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
5
+import lombok.extern.slf4j.Slf4j;
6
+import midware.entity.database.rep.Record;
7
+import midware.service.eslclient.entity.Agent;
8
+import midware.service.eslclient.entity.Channel;
9
+import midware.service.init.EslClientService;
10
+import midware.service.init.WebSocketService;
11
+import midware.service.rep.IRecordService;
12
+import midware.util.enums.EslAgentEnum;
13
+import midware.util.enums.EslEventEnum;
14
+import midware.util.helper.SpringHelper;
15
+import midware.util.helper.StringHelper;
16
+import org.freeswitch.esl.client.IEslEventListener;
17
+import org.freeswitch.esl.client.transport.event.EslEvent;
18
+
19
+import java.util.*;
20
+import java.util.concurrent.ScheduledThreadPoolExecutor;
21
+import java.util.concurrent.TimeUnit;
22
+
23
+@Slf4j
24
+public class EslEventListenerCustom implements IEslEventListener {
25
+    @Override
26
+    public void eventReceived(EslEvent event) {
27
+
28
+        String eventname = event.getEventName();
29
+
30
+        Map<String, String> header = event.getEventHeaders();
31
+        if (eventname.equals("CUSTOM")) {
32
+
33
+            IRecordService iRecordService = SpringHelper.getBean(IRecordService.class);
34
+            EslClientService eslClientService = SpringHelper.getBean(EslClientService.class);
35
+            WebSocketService webSocketService = SpringHelper.getBean(WebSocketService.class);
36
+
37
+            String subclass = header.get("Event-Subclass").replace("::", "_").toLowerCase();
38
+            // 获取注册分机
39
+            String exten = header.get("username");
40
+            switch (EslEventEnum.valueOf(subclass)) {
41
+                case sofia_register:
42
+                    Channel chan = EslCommon.getChanByExten(exten);
43
+                    if (chan == null) {
44
+                        chan = EslCommon.addChanel(exten);
45
+                        chan.setType(1);
46
+                        chan.setAnswer(false);
47
+                        chan.setChanId("");
48
+                        chan.setRecordPath("");
49
+                        chan.setCallType(0);
50
+                        chan.setSessionId("");
51
+                        chan.setRecordId(0);
52
+                        chan.setRingTime(null);
53
+                        chan.setSessionSort(0);
54
+                        chan.setIp(header.get("network-ip"));
55
+                    }
56
+                    break;
57
+                case sofia_unregister:
58
+                    if (StringHelper.isEmpty(exten)) exten = header.get("from-user");
59
+                    Channel chan1 = EslCommon.getChanByExten(exten);
60
+                    if (chan1 != null) {
61
+                        //通话中或者振铃中,断开
62
+                        if (StringHelper.isNotEmpty(chan1.getSessionId())) {
63
+                            try {
64
+                                eslClientService.kill(chan1.getSessionId(), "");
65
+                                Thread.sleep(300);
66
+                            } catch (InterruptedException e) {
67
+                                throw new RuntimeException(e);
68
+                            }
69
+                        }
70
+                        EslCommon.channels.remove(chan1);
71
+                        Agent at = EslCommon.getAgentByExten(exten);
72
+                        if (at != null) {
73
+                            if (at.getAgentState() != EslAgentEnum.logout.ordinal()) {
74
+                                at.setAgentState(EslAgentEnum.logout.ordinal());
75
+                            }
76
+                            eslClientService.logout(at.getAgent(), at.getGroup(), "");
77
+                            EslCommon.agents.remove(at);
78
+                        }
79
+                    }
80
+                    break;
81
+                case callcenter_info:
82
+                    String caller = header.get("Caller-Username");
83
+                    String queue = header.get("CC-Queue");
84
+                    String action = header.get("CC-Action");
85
+                    switch (action) {
86
+                        case "member-queue-start":
87
+                            if (!EslCommon.groupTempList.containsKey(queue)) {
88
+                                EslCommon.groupTempList.put(queue, new ArrayList<>());
89
+                            }
90
+                            EslCommon.groupTempList.get(queue).add(caller);
91
+
92
+                            String uuid = header.get("Channel-Call-UUID");
93
+                            new ScheduledThreadPoolExecutor(1).schedule(() -> {
94
+                                if (EslCommon.groupTempList.get(queue).remove(caller)) {
95
+                                    if (!EslCommon.groupWaitList.containsKey(queue)) {
96
+                                        EslCommon.groupWaitList.put(queue, new ArrayList<>());
97
+                                    }
98
+                                    List<String> listWait = EslCommon.groupWaitList.get(queue);
99
+                                    listWait.add(caller);
100
+                                    //排队数量
101
+                                    Map<String, Object> result = new HashMap<>();
102
+                                    result.put("Type", "Wait");
103
+                                    result.put("Result", true);
104
+                                    result.put("Count", listWait.size());
105
+                                    webSocketService.sendMessageGroupAll(queue, JSON.toJSONString(result));
106
+
107
+                                    //播报位置
108
+                                    eslClientService.playPosition(listWait.indexOf(caller) + 1, uuid);
109
+
110
+                                    //更新排队时间
111
+                                    LambdaUpdateWrapper<Record> uw = new LambdaUpdateWrapper<>();
112
+                                    uw.set(Record::getWaitTime, new Date()).eq(Record::getUuid, uuid);
113
+                                    iRecordService.updateBatch(uw);
114
+
115
+                                    //每隔20s播报位置
116
+                                    ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
117
+                                    executor.scheduleAtFixedRate(() -> {
118
+                                        long wc = EslCommon.channels.stream().filter(p -> p.getSessionId().equals(uuid)).count();
119
+                                        int postion = EslCommon.groupWaitList.get(queue).indexOf(caller);
120
+                                        if (postion >= 0) {
121
+                                            if (wc == 1) {
122
+                                                eslClientService.playPosition(postion + 1, uuid);
123
+                                            } else {
124
+                                                EslCommon.delWait(queue, caller);
125
+                                                executor.shutdown();
126
+                                            }
127
+                                        } else {
128
+                                            executor.shutdown();
129
+                                        }
130
+                                    }, 20, 20, TimeUnit.SECONDS);
131
+                                }
132
+                            }, 1, TimeUnit.SECONDS);
133
+                            break;
134
+                        case "agent-offering":
135
+                            String phone = header.get("CC-Member-CID-Name");
136
+                            EslCommon.delWait(queue, phone);
137
+                            //eslClientService.playAgent(header.get("CC-Agent"), header.get("CC-Member-Session-UUID"));
138
+                            break;
139
+                        case "member-queue-end":
140
+                            EslCommon.delWait(queue, caller);
141
+                            break;
142
+                    }
143
+                    break;
144
+            }
145
+        }
146
+    }
147
+
148
+    @Override
149
+    public void backgroundJobResultReceived(EslEvent event) {}
150
+}

+ 527 - 0
midware-service/src/main/java/midware/service/eslclient/EslEventListenerEvent.java

@@ -0,0 +1,527 @@
1
+package midware.service.eslclient;
2
+
3
+import com.alibaba.fastjson2.JSON;
4
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
5
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
6
+import lombok.extern.slf4j.Slf4j;
7
+import midware.entity.database.rep.AgentAction;
8
+import midware.entity.database.rep.ChanEvent;
9
+import midware.entity.database.rep.Record;
10
+import midware.service.eslclient.entity.Agent;
11
+import midware.service.eslclient.entity.Channel;
12
+import midware.service.eslclient.entity.Session;
13
+import midware.service.init.EslClientService;
14
+import midware.service.init.WebSocketService;
15
+import midware.service.rep.IRecordService;
16
+import midware.util.enums.EslAgentEnum;
17
+import midware.util.enums.EslEventEnum;
18
+import midware.util.helper.SpringHelper;
19
+import midware.util.helper.StringHelper;
20
+import org.freeswitch.esl.client.IEslEventListener;
21
+import org.freeswitch.esl.client.transport.event.EslEvent;
22
+
23
+import java.io.File;
24
+import java.text.SimpleDateFormat;
25
+import java.util.Arrays;
26
+import java.util.Date;
27
+import java.util.HashMap;
28
+import java.util.Map;
29
+import java.util.concurrent.ScheduledThreadPoolExecutor;
30
+import java.util.concurrent.TimeUnit;
31
+
32
+@Slf4j
33
+public class EslEventListenerEvent implements IEslEventListener {
34
+    @Override
35
+    public void eventReceived(EslEvent event) {
36
+        //System.out.println(1 + "|" + JSON.toJSONString(event));
37
+        //log.warn(1 + "|" + JSON.toJSONString(event));
38
+
39
+        String eventname = event.getEventName();
40
+
41
+        Map<String, String> header = event.getEventHeaders();
42
+        if (!eventname.equals("CUSTOM")) {
43
+            IRecordService iRecordService = SpringHelper.getBean(IRecordService.class);
44
+            EslClientService eslClientService = SpringHelper.getBean(EslClientService.class);
45
+            WebSocketService webSocketService = SpringHelper.getBean(WebSocketService.class);
46
+
47
+            int callType = 0;
48
+            if (header.containsKey("variable_call_type")) {
49
+                callType = Integer.parseInt(header.get("variable_call_type"));
50
+            }
51
+            if (callType != 3) {
52
+                // 获取会话ID
53
+                String callId = header.get("Channel-Call-UUID");
54
+                // 获取通道名称
55
+                String[] chanNames = header.get("Channel-Name").split("\\@")[0].split("\\/");
56
+                // 获取通道ID
57
+                String chanId = header.get("Unique-ID");
58
+                // 获取主叫
59
+                String callerNum = header.get("Caller-Caller-ID-Number");
60
+                // 获取被叫
61
+                String calleeNum = header.get("Caller-Callee-ID-Number");
62
+                if (StringHelper.isEmpty(calleeNum)) calleeNum = header.get("Caller-Destination-Number");
63
+                //ccid 当该变量存在时用该变量代替callid
64
+                String ccId = header.get("variable_cc_member_session_uuid");
65
+                if (StringHelper.isNotEmpty(ccId)) callId = ccId;
66
+                //代码呼叫时,create事件得到正确的被叫号码
67
+                String called = header.get("variable_call_called");
68
+                if (StringHelper.isNotEmpty(called)) {
69
+                    calleeNum = called;
70
+                    //会议打外线主叫和被叫改变了
71
+                    if (calleeNum.equals(callerNum)) callerNum = header.get("Caller-Callee-ID-Number");
72
+                }
73
+
74
+                String codec = header.get("variable_ep_codec_string");
75
+                boolean isVideo = StringHelper.isNotEmpty(codec) && codec.contains("H264");
76
+
77
+                Channel chan = EslCommon.getChanByNumber(chanNames[2]);
78
+                Agent agent = EslCommon.getAgentByExten(chanNames[2]);
79
+                Session session = EslCommon.getSessionById(callId);
80
+                if (callType == 0) callType = EslCommon.existExten(callerNum) ? 2 : 1;
81
+
82
+                LambdaUpdateWrapper<Record> uw;
83
+
84
+                switch (EslEventEnum.valueOf(eventname)) {
85
+                    case CHANNEL_CREATE:
86
+                        if (session == null) {
87
+                            session = new Session();
88
+                            session.setSessionId(callId);
89
+                            session.setType(callType);
90
+                            session.setActionId(1);
91
+                            session.setVideo(isVideo);
92
+                            session.setCreateTime(new Date());
93
+                            EslCommon.sessions.add(session);
94
+                        }
95
+
96
+                        if (chan == null) {
97
+                            chan = EslCommon.addChanel(chanNames[2]);
98
+                            chan.setType(2);
99
+                            chan.setVideo(isVideo);
100
+                        }
101
+
102
+                        chan.setChanId(chanId);
103
+                        chan.setSessionId(session.getSessionId());
104
+                        chan.setCallType(session.getType());
105
+                        chan.setCreateTime(new Date());
106
+                        String finalCallId = callId;
107
+                        chan.setSessionSort(EslCommon.channels.stream().filter(p -> p.getSessionId().equals(finalCallId)).count());
108
+                        //更新坐席状态
109
+                        if (agent != null) {
110
+                            if (callType == 2) eslClientService.setWork(agent.getAgent(), false, "");
111
+                            agent.setAgentState(EslAgentEnum.requested.ordinal());
112
+                        }
113
+
114
+                        switch (callType) {
115
+                            case 1://呼入 查找记录更新被叫工号分机号坐席组
116
+                                LambdaQueryWrapper<Record> qw = new LambdaQueryWrapper<>();
117
+                                qw.eq(Record::getUuid, callId);
118
+                                qw.select(Record::getId).last("limit 1");
119
+                                Map<String, Object> map = iRecordService.getMapFirst(qw);
120
+                                if (map != null && map.get("id") != null) {
121
+                                    chan.setRecordId((Long) map.get("id"));
122
+                                }
123
+
124
+                                Agent calleeAgent = EslCommon.getAgentByExten(calleeNum);
125
+                                if (calleeAgent != null) {
126
+
127
+                                    String queue = calleeAgent.getGroup();
128
+                                    EslCommon.delWait(queue, callerNum);
129
+
130
+                                    calleeAgent.setCallType(1);
131
+                                    uw = new LambdaUpdateWrapper<>();
132
+                                    if (chan.getRecordId() > 0) {
133
+                                        uw.eq(Record::getId, chan.getRecordId());
134
+                                    } else {
135
+                                        uw.eq(Record::getUuid, chan.getSessionId());
136
+                                    }
137
+                                    uw.set(Record::getCalleeAgent, calleeAgent.getAgent());
138
+                                    uw.set(Record::getCallee, calleeNum);
139
+                                    uw.set(Record::getGroupNo, calleeAgent.getGroup());
140
+                                    iRecordService.updateBatch(uw);
141
+
142
+                                    Map<String, Object> result = new HashMap<>();
143
+                                    result.put("Type", "Incoming");
144
+                                    result.put("Result", true);
145
+                                    result.put("CallID", chan.getRecordId());
146
+                                    result.put("Number", callerNum);
147
+                                    webSocketService.sendMessage(calleeAgent.getAgent(), JSON.toJSONString(result));
148
+                                }
149
+                                break;
150
+                            case 2://呼出 新增呼出记录
151
+                                boolean isAdd = callerNum.equals(chanNames[2]);
152
+                                Agent calleeAgent1 = EslCommon.getAgentByExten(calleeNum);
153
+                                if (calleeAgent1 != null) calleeAgent1.setCallType(1);
154
+                                Agent callerAgent = EslCommon.getAgentByExten(callerNum);
155
+                                if (callerAgent != null) {
156
+                                    callerAgent.setCallType(2);
157
+                                    String opType = callerAgent.getOpType();
158
+                                    chan.setOpType(opType);
159
+                                    if (opType.equals("Listen")) return;
160
+                                    if (!(isAdd && opType.equals("MakeCall"))) callerAgent.setOpType("");
161
+                                    //过滤分机呼出/坐席呼出
162
+                                    if (!(opType.equals("") || opType.equals("MakeCall"))) {
163
+                                        session.setActionId(session.getActionId() + 1);
164
+                                        if (!isAdd) isAdd = true;
165
+                                    }
166
+                                }
167
+                                if (isAdd) {
168
+                                    Record record = new Record();
169
+                                    record.setCaller(callerNum);
170
+                                    record.setOpType(chan.getOpType());
171
+                                    if (callerAgent != null) {
172
+                                        record.setCallerAgent(callerAgent.getAgent());
173
+                                        record.setGroupNo(callerAgent.getGroup());
174
+                                    }
175
+                                    record.setCallee(calleeNum);
176
+                                    if (calleeAgent1 != null) record.setCalleeAgent(calleeAgent1.getAgent());
177
+                                    record.setCallType(2);
178
+                                    record.setUuid(callId);
179
+                                    record.setActionId(session.getActionId());
180
+                                    record.setIsAnswer(0);
181
+                                    record.setIsVideo(session.isVideo() ? 1 : 0);
182
+                                    record.setCreateTime(new Date());
183
+                                    iRecordService.insert(record);
184
+                                    chan.setRecordId(record.getId());
185
+                                    if (callerAgent != null) {
186
+                                        Map<String, Object> result = new HashMap<>();
187
+                                        result.put("Type", "CallID");
188
+                                        result.put("Result", true);
189
+                                        result.put("CallID", chan.getRecordId());
190
+                                        result.put("Number", calleeNum);
191
+                                        webSocketService.sendMessage(callerAgent.getAgent(), JSON.toJSONString(result));
192
+                                    }
193
+                                    if (chanNames[2].equals(calleeNum)) {
194
+                                        if (calleeAgent1 != null) {
195
+                                            Map<String, Object> result = new HashMap<>();
196
+                                            result.put("Type", "Incoming");
197
+                                            result.put("Result", true);
198
+                                            result.put("CallID", chan.getRecordId());
199
+                                            //result.put("Number", callerNum);
200
+                                            Channel fc = EslCommon.getFirstChanBySessionId(session.getSessionId());
201
+                                            result.put("Number", fc != null ? fc.getNumber() : callerNum);
202
+                                            result.put("Action", chan.getOpType());
203
+                                            webSocketService.sendMessage(calleeAgent1.getAgent(), JSON.toJSONString(result));
204
+                                        }
205
+                                    }
206
+                                } else {
207
+                                    chan.setRecordId(EslCommon.getChanByNumber(callerNum).getRecordId());
208
+                                    if (calleeAgent1 != null) {
209
+                                        Map<String, Object> result = new HashMap<>();
210
+                                        result.put("Type", "Incoming");
211
+                                        result.put("Result", true);
212
+                                        result.put("CallID", chan.getRecordId());
213
+                                        result.put("Number", callerNum);
214
+                                        webSocketService.sendMessage(calleeAgent1.getAgent(), JSON.toJSONString(result));
215
+                                    }
216
+                                }
217
+                                break;
218
+                        }
219
+                        break;
220
+                    case CHANNEL_PROGRESS:
221
+                    case CHANNEL_PROGRESS_MEDIA:
222
+                        if (chan != null) {
223
+                            //被叫振铃
224
+                            if (chan.getSessionSort() > 1 && chan.getRingTime() == null) {
225
+                                chan.setRingTime(new Date());
226
+                                if (chan.getOpType().equals("Listen")) return;
227
+                                uw = new LambdaUpdateWrapper<>();
228
+                                uw.set(Record::getRingTime, new Date());
229
+                                if (chan.getRecordId() > 0) {
230
+                                    uw.eq(Record::getId, chan.getRecordId());
231
+                                } else {
232
+                                    uw.eq(Record::getUuid, chan.getSessionId());
233
+                                }
234
+                                iRecordService.updateBatch(uw);
235
+                            }
236
+                            //签入视频话机外呼
237
+                            if (session != null) {
238
+                                if (chan.getSessionSort() == 1 && !session.isVideo() && isVideo) {
239
+                                    session.setVideo(true);
240
+                                    uw = new LambdaUpdateWrapper<>();
241
+                                    uw.eq(Record::getId, chan.getRecordId()).set(Record::getIsVideo, 1);
242
+                                    iRecordService.updateBatch(uw);
243
+                                }
244
+                            }
245
+                        }
246
+                        break;
247
+                    case CHANNEL_ANSWER:
248
+                        if (chan != null && !chan.isAnswer()) {
249
+                            chan.setAnswer(true);
250
+
251
+                            //呼出号码应答通知坐席
252
+                            if (callType == 2) {
253
+                                String opType = chan.getOpType();
254
+                                if (StringHelper.isNotEmpty(opType)) {
255
+                                    Agent callerAgent = EslCommon.getAgentByExten(callerNum);
256
+                                    if (callerAgent != null) {
257
+                                        if (!opType.equals("MakeCall") || calleeNum.equals(chanNames[2])) {
258
+                                            actionNotice(opType, callerAgent.getAgent(), callId, true);
259
+                                            if (opType.equals("Meeting") && chan.getSessionSort() == 3) {
260
+                                                eslClientService.talkJoinMeeting(callId);
261
+                                                eslClientService.setConferenceExitSound(callId, true);
262
+                                                if (session != null) session.setMeeting(true);
263
+                                            }
264
+                                        }
265
+                                    }
266
+                                }
267
+                            }
268
+                            //被叫应答
269
+                            if (chan.getSessionSort() > 1) {
270
+                                if (chan.getOpType().equals("Listen")) return;
271
+                                if (agent != null) agent.setAgentState(EslAgentEnum.talking.ordinal());
272
+                                //分机打分机时更新主叫坐席状态
273
+                                if (callType == 2 && !session.isAnswer() && !chan.getOpType().equals("Instead")) {
274
+                                    Agent callerAgent = EslCommon.getAgentByExten(callerNum);
275
+                                    if (callerAgent != null) callerAgent.setAgentState(EslAgentEnum.talking.ordinal());
276
+                                }
277
+
278
+                                String ext = callType == 1 ? calleeNum : callerNum;
279
+
280
+                                if (session.isVideo()) {
281
+                                    //视频
282
+                                    if (session.isMeeting()) {
283
+                                        chan.setRecordPath(session.getVideoPath());
284
+                                    } else {
285
+                                        String parentPath = "files/video/" + new SimpleDateFormat("yyyyMMdd").format(new Date()) + "/" + ext;
286
+                                        File file = new File(parentPath);
287
+                                        if (!file.exists()) file.mkdirs();
288
+                                        String filePath = parentPath + "/" + chanId + ".mp4";
289
+                                        chan.setRecordPath(filePath);
290
+                                        String recordPath = file.getAbsolutePath() + "/" + chanId + ".mp4";
291
+
292
+                                        eslClientService.record(callId, recordPath,true);
293
+                                    }
294
+                                } else {
295
+                                    //录音
296
+                                    String parentPath = "files/luyin/" + new SimpleDateFormat("yyyyMMdd").format(new Date()) + "/" + ext;
297
+                                    File file = new File(parentPath);
298
+                                    if (!file.exists()) file.mkdirs();
299
+                                    String filePath = parentPath + "/" + chanId + ".wav";
300
+                                    chan.setRecordPath(filePath);
301
+                                    String recordPath = file.getAbsolutePath() + "/" + chanId + ".wav";
302
+                                    eslClientService.record(chanId, recordPath,true);
303
+                                }
304
+
305
+                                uw = new LambdaUpdateWrapper<>();
306
+                                uw.set(Record::getAnswerTime, new Date()).set(Record::getIsAnswer, 1);
307
+                                uw.set(Record::getRecordPath, chan.getRecordPath());
308
+                                if (chan.getRecordId() > 0) {
309
+                                    uw.eq(Record::getId, chan.getRecordId());
310
+                                } else {
311
+                                    uw.eq(Record::getUuid, chan.getSessionId());
312
+                                }
313
+                                iRecordService.updateBatch(uw);
314
+
315
+                                session.setAnswer(true);
316
+                            }
317
+                        }
318
+                        break;
319
+                    case CHANNEL_BRIDGE:
320
+                        //呼入播报工号
321
+                        if (callType == 1) {
322
+                            Agent agent1 = EslCommon.getAgentByExten(calleeNum);
323
+                            if (agent1 != null) eslClientService.playAgent(agent1.getAgent(), chanId);
324
+                        }
325
+                        //代接
326
+                        if (chan != null && chan.getOpType().equals("Instead")) {
327
+                            Agent agent1 = EslCommon.getAgentByExten(header.get("Caller-Callee-ID-Number"));
328
+                            if (agent1 != null) agent1.setAgentState(EslAgentEnum.talking.ordinal());
329
+                        }
330
+                        break;
331
+                    case CHANNEL_HANGUP_COMPLETE:
332
+                        if (chan != null) {
333
+                            String sid = chan.getSessionId();
334
+                            if (session == null) session = EslCommon.getSessionById(sid);
335
+
336
+                            //呼出号码未接通挂断通知坐席
337
+                            if (callType == 2 && !chan.isAnswer()) {
338
+                                Agent callerAgent = EslCommon.getAgentByExten(callerNum);
339
+                                if (callerAgent != null && StringHelper.isNotEmpty(chan.getOpType())) {
340
+                                    actionNotice(chan.getOpType(), callerAgent.getAgent(), sid, false);
341
+                                }
342
+                            }
343
+
344
+                            boolean isupdate = true;
345
+                            //分机通道修改坐席状态
346
+                            if (chan.getType() == 1) {
347
+                                if (agent != null) {
348
+                                    String agentNo = agent.getAgent();
349
+                                    if (callType == 1 && chan.isAnswer()) {//呼入接通后挂断-话后处理
350
+                                        agent.setAgentState(EslAgentEnum.aftertalk.ordinal());
351
+                                        new ScheduledThreadPoolExecutor(1).schedule(() -> {
352
+                                            Agent agent2 = EslCommon.getAgent(agentNo);
353
+                                            if (agent2 != null && agent2.getAgentState() == EslAgentEnum.aftertalk.ordinal()) {
354
+                                                agent2.setAgentState(EslAgentEnum.free.ordinal());
355
+                                            }
356
+                                        }, 20, TimeUnit.SECONDS);
357
+                                    } else {//呼出挂断-空闲
358
+                                        chan.setSessionId("");
359
+                                        agent.setAgentState(EslAgentEnum.free.ordinal());
360
+                                    }
361
+                                    if (callType == 2) {
362
+                                        eslClientService.setWork(agentNo, true, "");
363
+                                    }
364
+                                    agent.setCallType(0);
365
+                                }
366
+                                //监听者挂机不更新
367
+                                if (chan.getOpType().equals("Listen")) isupdate = false;
368
+                            }
369
+
370
+                            //未接通挂断/被叫挂断
371
+                            if (isupdate && ((session != null && !session.isAnswer()) || chan.getSessionSort() > 1)) {
372
+                                // 获取挂机原因
373
+                                String hangUpCause = header.get("Hangup-Cause");
374
+                                uw = new LambdaUpdateWrapper<>();
375
+                                uw.set(Record::getHangupTime, new Date()).set(Record::getHangupCause, hangUpCause);
376
+                                if (chan.getRecordId() > 0) {
377
+                                    uw.eq(Record::getId, chan.getRecordId());
378
+                                } else {
379
+                                    uw.eq(Record::getUuid, sid);
380
+                                }
381
+                                iRecordService.updateBatch(uw);
382
+                            }
383
+
384
+                            if (chan.getType() == 2) {
385
+                                //外线挂机移除通道
386
+                                EslCommon.channels.remove(chan);
387
+                            } else {
388
+                                //内线挂机重置通道
389
+                                chan.setAnswer(false);
390
+                                chan.setChanId("");
391
+                                chan.setRecordPath("");
392
+                                chan.setCallType(0);
393
+                                chan.setSessionId("");
394
+                                chan.setRecordId(0);
395
+                                chan.setRingTime(null);
396
+                                chan.setSessionSort(0);
397
+                                chan.setOpType("");
398
+                            }
399
+                            if (session != null) {
400
+                                if (EslCommon.channels.stream().noneMatch(p -> p.getSessionId().equals(sid))) {
401
+                                    EslCommon.sessions.remove(session);
402
+                                }
403
+                                //会议剩下最后一个时挂机
404
+                                if (session.isMeeting()) {
405
+                                    if (EslCommon.channels.stream().filter(p -> p.getSessionId().equals(sid)).count() == 1) {
406
+                                        Channel last = EslCommon.channels.stream().filter(p -> p.getSessionId().equals(sid)).findFirst().get();
407
+                                        eslClientService.kill(last.getChanId(), "");
408
+                                    }
409
+                                }
410
+                            }
411
+                        }
412
+                        break;
413
+                    case DTMF:
414
+                    case CHANNEL_EXECUTE_COMPLETE:
415
+                    case DETECTED_SPEECH:
416
+                    case CHANNEL_HOLD:
417
+                    case CHANNEL_UNHOLD:
418
+                        break;
419
+                }
420
+                //过滤执行完成事件,识别事件
421
+                if (!Arrays.asList(EslEventEnum.CHANNEL_EXECUTE_COMPLETE, EslEventEnum.DETECTED_SPEECH).contains(EslEventEnum.valueOf(eventname))) {
422
+                    ChanEvent chanEvent = new ChanEvent();
423
+                    chanEvent.setChan(chanNames[2]);
424
+                    chanEvent.setEvent(eventname);
425
+                    if (session != null) chanEvent.setUuid(session.getSessionId());
426
+                    chanEvent.setCreateTime(new Date());
427
+
428
+                    synchronized (EslCommon.events) {
429
+                        EslCommon.events.add(chanEvent);
430
+                    }
431
+                }
432
+            }
433
+        }
434
+    }
435
+
436
+    @Override
437
+    public void backgroundJobResultReceived(EslEvent event) {
438
+        //System.out.println(2 + "|" + JSON.toJSONString(event));
439
+        //log.warn(2 + "|" + JSON.toJSONString(event));
440
+
441
+        String bodys = event.getEventBodyLines().size() > 0 ? event.getEventBodyLines().get(0) : "";
442
+        String uuid = event.getEventHeaders().get("Job-UUID");
443
+        if (uuid != null && !uuid.startsWith("|") && uuid.contains("|")) {
444
+            boolean isEnd = true;
445
+            String[] values = uuid.split("\\|");
446
+            String type = values[0];
447
+            String agentId = values[1];
448
+            Agent agent = EslCommon.getAgent(agentId);
449
+            switch (type) {
450
+                case "Login"://签入
451
+                    if (bodys.startsWith("+OK")) {
452
+                        agent.setAgentState(EslAgentEnum.free.ordinal());
453
+                    } else {
454
+                        SpringHelper.getBean(EslClientService.class).logout(agentId, agent.getGroup(), "");
455
+                        EslCommon.agents.remove(agent);
456
+                    }
457
+                    break;
458
+                case "Logout"://签出
459
+                    if (bodys.startsWith("+OK")) {
460
+                        agent.setAgentState(EslAgentEnum.logout.ordinal());
461
+                        EslCommon.agents.remove(agent);
462
+                    }
463
+                    break;
464
+                case "WorkOn"://置闲
465
+                    if (bodys.startsWith("+OK")) agent.setAgentState(EslAgentEnum.free.ordinal());
466
+                    break;
467
+                case "WorkOff"://置忙
468
+                    if (bodys.startsWith("+OK")) agent.setAgentState(EslAgentEnum.busy.ordinal());
469
+                    break;
470
+                case "ForceWorkOn"://强制置闲
471
+                    if (bodys.startsWith("+OK")) {
472
+                        Agent tagent = EslCommon.getAgent(values[2]);
473
+                        if (tagent != null) tagent.setAgentState(EslAgentEnum.free.ordinal());
474
+                    }
475
+                    break;
476
+                case "ForceWorkOff"://强制置忙
477
+                    if (bodys.startsWith("+OK")) {
478
+                        Agent tagent = EslCommon.getAgent(values[2]);
479
+                        if (tagent != null) tagent.setAgentState(EslAgentEnum.busy.ordinal());
480
+                    }
481
+                    break;
482
+                case "HoldOn"://开启保持
483
+                case "HoldOff"://关闭保持
484
+                case "MuteOn"://开启静音
485
+                case "MuteOff"://关闭静音
486
+                case "ConsultOff"://关闭协商
487
+                case "TurnMyd"://转满意度
488
+                case "DropCall"://挂机
489
+                case "Break"://强拆
490
+                    break;
491
+                case "MakeCall"://外呼
492
+                case "Transfer"://转移
493
+                case "ConsultOn"://开启协商
494
+                case "Meeting"://会议
495
+                case "Listen"://监听
496
+                case "Insert"://强插
497
+                case "Intercept"://强截
498
+                case "Instead"://代接
499
+                    isEnd = false;
500
+                    break;
501
+            }
502
+            if (isEnd) actionNotice(type, agentId, "", bodys.startsWith("+OK"));
503
+        }
504
+        if (!bodys.startsWith("+OK")) {
505
+            log.error("执行命令出错:" + JSON.toJSONString(event));
506
+        }
507
+    }
508
+
509
+    //操作通知
510
+    private void actionNotice(String type, String agentId, String sessionId, boolean isSuccess) {
511
+        Map<String, Object> result = new HashMap<>();
512
+        result.put("Type", type);
513
+        result.put("Result", "操作失败2");
514
+        if (isSuccess) result.put("Result", true);
515
+        SpringHelper.getBean(WebSocketService.class).sendMessage(agentId, JSON.toJSONString(result));
516
+        AgentAction aa = EslCommon.actionTempList.get(agentId);
517
+        if (aa != null) {
518
+            if (StringHelper.isNotEmpty(sessionId)) aa.setUuid(sessionId);
519
+            aa.setIsSuccess(isSuccess ? 1 : 0);
520
+
521
+            EslCommon.actionTempList.remove(agentId);
522
+            synchronized (EslCommon.actions) {
523
+                EslCommon.actions.add(aa);
524
+            }
525
+        }
526
+    }
527
+}

+ 65 - 0
midware-service/src/main/java/midware/service/eslclient/entity/Agent.java

@@ -0,0 +1,65 @@
1
+package midware.service.eslclient.entity;
2
+
3
+import com.alibaba.fastjson2.JSON;
4
+import lombok.Data;
5
+import lombok.Setter;
6
+import lombok.extern.slf4j.Slf4j;
7
+import midware.entity.database.rep.AgentState;
8
+import midware.service.eslclient.EslCommon;
9
+import midware.service.init.WebSocketService;
10
+import midware.util.helper.SpringHelper;
11
+
12
+import java.util.Date;
13
+import java.util.HashMap;
14
+import java.util.Map;
15
+
16
+@Slf4j
17
+@Data
18
+public class Agent {
19
+    //坐席工号
20
+    private String agent;
21
+    //分机号
22
+    private String exten;
23
+    //坐席组
24
+    private String group;
25
+    //方向(1呼入2呼出)
26
+    private int callType = 0;
27
+    //是否监控(0否1是)
28
+    private int isMonitor = 0;
29
+    // 操作类型
30
+    private String opType = "";
31
+    //坐席状态
32
+    @Setter
33
+    private int agentState;
34
+
35
+    public void setAgentState(int s) {
36
+        this.agentState = s;
37
+
38
+        Map<String, Object> result = new HashMap<>();
39
+        result.put("Type", "State");
40
+        result.put("Result", true);
41
+        result.put("State", s);
42
+
43
+        WebSocketService wsService = SpringHelper.getBean(WebSocketService.class);
44
+        wsService.sendMessage(agent, JSON.toJSONString(result));
45
+        //if(isMonitor==0) {
46
+        result.put("Type", "AgentState");
47
+        result.put("AgentId", agent);
48
+        result.put("Exten", exten);
49
+        result.put("Monitor", isMonitor);
50
+        wsService.sendMessageSubScribe(JSON.toJSONString(result));
51
+        //}
52
+
53
+        AgentState as = new AgentState();
54
+        as.setAgent(agent);
55
+        as.setExten(exten);
56
+        as.setGroupNo(group);
57
+        as.setState(s);
58
+        as.setCreateTime(new Date());
59
+        Channel chan = EslCommon.getChanByExten(exten);
60
+        if (chan != null) as.setUuid(chan.getSessionId());
61
+        synchronized (EslCommon.states) {
62
+            EslCommon.states.add(as);
63
+        }
64
+    }
65
+}

+ 17 - 0
midware-service/src/main/java/midware/service/eslclient/entity/Auth.java

@@ -0,0 +1,17 @@
1
+package midware.service.eslclient.entity;
2
+
3
+import lombok.Data;
4
+
5
+import java.util.Date;
6
+
7
+@Data
8
+public class Auth {
9
+    //过期时间
10
+    private Date ExpireTime = null;
11
+    //是否过期
12
+    private boolean isExpire = true;
13
+    // 通道数量
14
+    //private long channelNum = 0;
15
+    // 坐席数量
16
+    private long agentNum = 0;
17
+}

+ 39 - 0
midware-service/src/main/java/midware/service/eslclient/entity/Channel.java

@@ -0,0 +1,39 @@
1
+package midware.service.eslclient.entity;
2
+
3
+import lombok.Data;
4
+
5
+import java.util.Date;
6
+
7
+@Data
8
+public class Channel {
9
+    //通道id
10
+    private String chanId;
11
+    //类型(1坐席2中继)
12
+    private int type;
13
+    //方向(1呼入2呼出)
14
+    private int callType = 0;
15
+    //号码
16
+    private String number;
17
+    //会话id
18
+    private String sessionId = "";
19
+    //自增id
20
+    private long recordId = 0;
21
+    //通道状态
22
+    private int chanState = 0;
23
+    //振铃时间
24
+    private Date ringTime;
25
+    //是否接听
26
+    private boolean isAnswer = false;
27
+    //录音路径
28
+    private String recordPath = "";
29
+    //是否视频
30
+    private boolean isVideo = false;
31
+    // 操作类型
32
+    private String opType = "";
33
+    // 会话排序
34
+    private long sessionSort = 0;
35
+    //创建时间
36
+    private Date createTime;
37
+    //ip
38
+    private String ip;
39
+}

+ 25 - 0
midware-service/src/main/java/midware/service/eslclient/entity/Session.java

@@ -0,0 +1,25 @@
1
+package midware.service.eslclient.entity;
2
+
3
+import lombok.Data;
4
+
5
+import java.util.Date;
6
+
7
+@Data
8
+public class Session {
9
+    //会话id
10
+    private String sessionId;
11
+    // 类型1呼入2呼出
12
+    private int type;
13
+    // 默认0,成功接听一通后+1
14
+    private int actionId;
15
+    //是否接听
16
+    private boolean isAnswer = false;
17
+    //是否会议
18
+    private boolean isMeeting = false;
19
+    //是否视频
20
+    private boolean isVideo = false;
21
+    //视频路径
22
+    private String videoPath;
23
+    //创建时间
24
+    private Date createTime;
25
+}

+ 819 - 0
midware-service/src/main/java/midware/service/init/EslClientService.java

@@ -0,0 +1,819 @@
1
+package midware.service.init;
2
+
3
+import com.alibaba.fastjson2.JSON;
4
+import lombok.extern.slf4j.Slf4j;
5
+import midware.service.eslclient.*;
6
+import midware.service.eslclient.entity.Agent;
7
+import midware.service.eslclient.entity.Channel;
8
+import midware.service.eslclient.entity.Session;
9
+import midware.util.config.CommonConfig;
10
+import midware.util.config.EslClientConfig;
11
+import midware.util.enums.EslAgentEnum;
12
+import midware.util.enums.EslCommandEnum;
13
+import midware.util.enums.EslEventEnum;
14
+import midware.util.helper.SecretHelper;
15
+import midware.util.helper.StringHelper;
16
+import midware.util.helper.TtsHelper;
17
+import org.freeswitch.esl.client.inbound.Client;
18
+import org.freeswitch.esl.client.transport.SendMsg;
19
+import org.freeswitch.esl.client.transport.message.EslMessage;
20
+import org.springframework.beans.factory.annotation.Autowired;
21
+import org.springframework.core.annotation.Order;
22
+import org.springframework.stereotype.Service;
23
+
24
+import javax.annotation.PostConstruct;
25
+import javax.annotation.PreDestroy;
26
+import java.io.File;
27
+import java.text.SimpleDateFormat;
28
+import java.util.ArrayList;
29
+import java.util.Date;
30
+import java.util.HashMap;
31
+import java.util.Map;
32
+import java.util.concurrent.ScheduledThreadPoolExecutor;
33
+import java.util.concurrent.TimeUnit;
34
+import java.util.stream.Stream;
35
+
36
+@Slf4j
37
+@Service
38
+@Order(1)
39
+public class EslClientService {
40
+
41
+    @Autowired
42
+    private Client client;
43
+    @Autowired
44
+    private EslClientConfig config;
45
+
46
+    @PostConstruct
47
+    public void init() {
48
+
49
+        //client.addEventListener(new EslEventListener());
50
+        client.addEventListener(new EslEventListenerCustom());
51
+        client.addEventListener(new EslEventListenerEvent());
52
+
53
+        //单独起1个线程,定时检测连接状态
54
+        new ScheduledThreadPoolExecutor(1).scheduleAtFixedRate(() -> {
55
+            if (!client.canSend()) {
56
+                try {
57
+                    if (EslCommon.agents.size() > 0) {
58
+                        for (Agent a : EslCommon.agents) {
59
+                            logout(a.getAgent(), a.getGroup(),"");
60
+                            a.setAgentState(EslAgentEnum.logout.ordinal());
61
+                        }
62
+                        EslCommon.agents=new ArrayList<>();
63
+                    }
64
+
65
+                    client.connect(config.getHost(), config.getPort(), config.getPassword(), config.getTimeout());
66
+                    //移除事件
67
+                    client.cancelEventSubscriptions();
68
+                    Thread.sleep(500);
69
+                    //移除事件
70
+                    client.cancelEventSubscriptions();
71
+                    //设置监听事件
72
+                    client.setEventSubscriptions("plain", "all");
73
+                    Stream.of(EslEventEnum.values()).filter(s -> StringHelper.isEmpty(s.getSubclass()))
74
+                            .map(Enum::name).forEach(s -> client.addEventFilter("Event-Name", s));
75
+                    Stream.of(EslEventEnum.values()).filter(s -> StringHelper.isNotEmpty(s.getSubclass()))
76
+                            .map(EslEventEnum::getSubclass).forEach(s -> client.addEventFilter("Event-Subclass", s));
77
+
78
+                    //删除所有坐席
79
+                    delAgentAll();
80
+                    //扫描已注册的分机
81
+                    scanExten();
82
+                    //设置中间件根目录
83
+                    String path=new File("").getAbsolutePath();
84
+                    client.sendAsyncApiCommand(EslCommandEnum.global_setvar.name(), "md_base_dir=" +path );
85
+                } catch (Exception e) {
86
+                    log.error("fs reConnect Exception", e);
87
+                }
88
+            }
89
+        }, 1, 5000, TimeUnit.MILLISECONDS);
90
+
91
+        if (client.canSend()) {
92
+            //删除所有坐席
93
+            delAgentAll();
94
+            //扫描已注册的分机
95
+            scanExten();
96
+            //设置中间件根目录
97
+            String path=new File("").getAbsolutePath();
98
+            client.sendAsyncApiCommand(EslCommandEnum.global_setvar.name(), "md_base_dir=" +path );
99
+        }
100
+
101
+        EslCommon.checkAuth();
102
+    }
103
+
104
+    @PreDestroy
105
+    public void destroy() {
106
+        if (EslCommon.agents.size() > 0) {
107
+            for (Agent a : EslCommon.agents) {
108
+                logout(a.getAgent(), a.getGroup(),"");
109
+                a.setAgentState(EslAgentEnum.logout.ordinal());
110
+            }
111
+            EslCommon.agents=new ArrayList<>();
112
+        }
113
+    }
114
+
115
+    //删除所有坐席
116
+    public void delAgentAll() {
117
+        try {
118
+            String command = EslCommandEnum.callcenter_config.name();
119
+            //获取坐席组中所有坐席
120
+            EslMessage message = client.sendSyncApiCommand(command, "tier list");
121
+            if (message != null && message.getBodyLines().size() > 0) {
122
+                for (String line : message.getBodyLines()) {
123
+                    if (!line.startsWith("queue") && !line.startsWith("+OK")) {
124
+                        String[] lines = line.split("\\|");
125
+                        client.sendAsyncApiCommand(command, "agent del " + lines[1]);
126
+                        client.sendAsyncApiCommand(command, "tier del " + lines[0] + " " + lines[1]);
127
+                    }
128
+                }
129
+            }
130
+            //获取所有坐席
131
+            EslMessage message1 = client.sendSyncApiCommand(command, "agent list");
132
+            if (message1 != null && message1.getBodyLines().size() > 0) {
133
+                for (String line : message1.getBodyLines()) {
134
+                    if (!line.startsWith("name") && !line.startsWith("+OK")) {
135
+                        String[] lines = line.split("\\|");
136
+                        client.sendAsyncApiCommand(command, "agent del " + lines[0]);
137
+                    }
138
+                }
139
+            }
140
+        } catch (Exception e) {
141
+            log.error("删除所有坐席失败", e);
142
+        }
143
+    }
144
+
145
+    //扫描已注册的分机
146
+    public void scanExten() {
147
+        try {
148
+            //挂断所有
149
+            client.sendSyncApiCommand("hupall", "");
150
+            //获取已注册的分机
151
+            EslMessage message = client.sendSyncApiCommand("sofia status profile internal reg", "");
152
+            if (message != null && message.getBodyLines().size() > 0) {
153
+                String ip = "";
154
+                for (String line : message.getBodyLines()) {
155
+                    if (line.startsWith("Auth-User:")) {
156
+                        String exten = line.substring(10).trim();
157
+                        Channel chan = EslCommon.getChanByExten(exten);
158
+                        if (chan == null) {
159
+                            chan = new Channel();
160
+                            chan.setType(1);
161
+                            chan.setNumber(exten);
162
+                            EslCommon.channels.add(chan);
163
+                        }
164
+                        chan.setAnswer(false);
165
+                        chan.setChanId("");
166
+                        chan.setRecordPath("");
167
+                        chan.setCallType(0);
168
+                        chan.setSessionId("");
169
+                        chan.setRecordId(0);
170
+                        chan.setRingTime(null);
171
+                        chan.setSessionSort(0);
172
+                        chan.setIp(ip);
173
+                    }
174
+                    if (line.startsWith("IP:")) {
175
+                        ip = line.substring(3).trim();
176
+                    }
177
+                }
178
+            }
179
+        } catch (Exception e) {
180
+            log.error("扫描已注册的分机失败", e);
181
+        }
182
+    }
183
+
184
+    //坐席签入
185
+    public boolean login(String agent, String ext, String group,String action) {
186
+        String result = "";
187
+        try {
188
+            String command = EslCommandEnum.callcenter_config.name();
189
+            // 添加座席
190
+            String arg = " agent add " + agent + " Callback";
191
+            result = client.sendAsyncApiCommand(command, arg);
192
+            // 设置呼叫字符串
193
+            arg = " agent set contact " + agent + " [call_timeout=30]user/" + ext;
194
+            client.sendAsyncApiCommand(command, arg);
195
+            // 座席登录后默认空闲
196
+            arg = " agent set status " + agent + " Available";
197
+            client.sendAsyncApiCommand(command, arg);
198
+            // 座席登录后默认空闲
199
+            arg = " agent set state " + agent + " Waiting";
200
+            client.sendAsyncApiCommand(command, arg);
201
+            // 最大未接次数,到达次数后不再转接,0禁用
202
+            arg = " agent set max_no_answer " + agent + " 0";
203
+            client.sendAsyncApiCommand(command, arg);
204
+            // 话后处理时间(s)
205
+            //成功处理一个通话后,多久才会有电话进入的等待时长
206
+            arg = " agent set wrap_up_time " + agent + " 20";
207
+            client.sendAsyncApiCommand(command, arg);
208
+            // 挂机间隔时间(s)
209
+            //来电拒接后多久才会有电话进入的等待时长,0禁用
210
+            arg = " agent set reject_delay_time " + agent + " 0";
211
+            client.sendAsyncApiCommand(command, arg);
212
+            // 忙重试间隔时间(s)
213
+            //来电遇忙后多久才会有电话进入的等待时长
214
+            arg = " agent set busy_delay_time " + agent + " 0";
215
+            client.sendAsyncApiCommand(command, arg);
216
+            // 添加梯队到队列等价于坐席组
217
+            group = StringHelper.isEmpty(group) ? "ZXZ" : group;
218
+            arg = " tier add " + group + " " + agent + " 1 1"
219
+                    +"\r\nJob-UUID:" + action + "|"+ System.currentTimeMillis();
220
+            client.sendAsyncApiCommand(command, arg);
221
+            
222
+        } catch (Exception e) {
223
+            log.error(agent + "|" + ext + "|" + group + " 签入失败", e);
224
+        }
225
+        return !result.equals("");
226
+    }
227
+
228
+    //坐席签出
229
+    public boolean logout(String agent, String group,String action) {
230
+        String result = "";
231
+        try {
232
+            String command = EslCommandEnum.callcenter_config.name();
233
+            // 删除座席
234
+            String arg = " agent del " + agent;
235
+            result = client.sendAsyncApiCommand(command, arg);
236
+            // 删除梯队
237
+            group = StringHelper.isEmpty(group) ? "ZXZ" : group;
238
+            arg = " tier del " + group + " " + agent
239
+                    +"\r\nJob-UUID:" + action + "|"+ System.currentTimeMillis();
240
+            client.sendAsyncApiCommand(command, arg);
241
+            
242
+        } catch (Exception e) {
243
+            log.error(agent + "|" + group + " 签出失败", e);
244
+        }
245
+        return !result.equals("");
246
+    }
247
+
248
+    //坐席置忙/置闲
249
+    public boolean setWork(String agent, boolean isWork,String action) {
250
+        String result = "";
251
+        try {
252
+            String command = EslCommandEnum.callcenter_config.name();
253
+            String state = isWork ? "'Available'" : "'On Break'";
254
+            String arg = " agent set status " + agent + " " + state
255
+                    +"\r\nJob-UUID:" + action + "|"+ System.currentTimeMillis();
256
+            result = client.sendAsyncApiCommand(command, arg);
257
+            
258
+        } catch (Exception e) {
259
+            String state = isWork ? "置闲" : "置忙";
260
+            log.error(agent + "|" + isWork + " " + state + "失败", e);
261
+        }
262
+        return !result.equals("");
263
+    }
264
+
265
+    //删除
266
+    public boolean kill(String chanId,String action) {
267
+        String result = "";
268
+        try {
269
+            result = client.sendAsyncApiCommand(EslCommandEnum.uuid_kill.name(), chanId
270
+                    + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis());
271
+            
272
+        } catch (Exception e) {
273
+            log.error(chanId + " 删除失败", e);
274
+        }
275
+        return !result.equals("");
276
+    }
277
+
278
+    //app挂断
279
+    public boolean killApp(String chanId) {
280
+        String result = "";
281
+        try {
282
+            String command = EslCommandEnum.uuid_broadcast.name();
283
+            String arg = chanId + " hangup::NORMAL_CLEARING" ;
284
+            result = client.sendAsyncApiCommand(command, arg);
285
+        } catch (Exception e) {
286
+            log.error( chanId + " app挂断失败", e);
287
+        }
288
+        return !result.equals("");
289
+    }
290
+
291
+    //分机呼叫
292
+    public boolean extenCall(String callerNum, String calleeNum,String action) {
293
+        String result = "";
294
+        try {
295
+            String fix = action.substring(action.lastIndexOf("|") + 1);
296
+            String command = EslCommandEnum.originate.name();
297
+//            String arg = " {instant_ringback=true,origination_caller_id_number=" + callerNum
298
+//                    + ",call_called=" + calleeNum.substring(fix.length()) + ",record_concat_video=true"
299
+//                    + ",transfer_ringback=local_stream://moh,ignore_early_media=true"
300
+//                    + "}user/" + callerNum + " &bridge(" + getCallString(calleeNum) + ")"
301
+//                    + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
302
+            String arg = " {origination_caller_id_number=" + callerNum + ",call_called=" + calleeNum.substring(fix.length())
303
+                    + ",record_concat_video=true,transfer_ringback=local_stream://moh,ringback=${us-ring}"
304
+                    + "}user/" + callerNum + " &bridge(" + getCallString(calleeNum) + ")"
305
+                    + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
306
+            result = client.sendAsyncApiCommand(command, arg);
307
+
308
+        } catch (Exception e) {
309
+            log.error(callerNum + "|" + calleeNum + " 分机呼叫失败", e);
310
+        }
311
+        return !result.equals("");
312
+    }
313
+
314
+    //呼叫2个号码并桥接
315
+    public boolean bridgeNum(String callerNum, String calleeNum,String action) {
316
+        String result = "";
317
+        try {
318
+            String command = EslCommandEnum.originate.name();
319
+            String arg = " {origination_caller_id_number=" + callerNum + ",call_called=" + calleeNum
320
+                    + ",call_type=2}" + getCallString(callerNum) + " &bridge(" + getCallString(calleeNum) + ")"
321
+                    + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
322
+            result = client.sendAsyncApiCommand(command, arg);
323
+
324
+        } catch (Exception e) {
325
+            log.error(callerNum + "|" + calleeNum + " 呼叫号码并桥接失败", e);
326
+        }
327
+        return !result.equals("");
328
+    }
329
+
330
+    //协商呼叫
331
+    public boolean consult(String chanId, String callerNum,String calleeNum,String action) {
332
+        String result = "";
333
+        try {
334
+            String fix = action.substring(action.lastIndexOf("|")+1);
335
+            String command = EslCommandEnum.uuid_broadcast.name();
336
+            String arg = chanId + " att_xfer::{origination_caller_id_number=" + callerNum+",record_concat_video=true"
337
+                    + ",call_called=" + calleeNum.substring(fix.length()) + "}" + getCallString(calleeNum)
338
+                    + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
339
+            result = client.sendAsyncApiCommand(command, arg);
340
+            
341
+        } catch (Exception e) {
342
+            log.error(chanId + "|" + calleeNum + " 协商呼叫失败", e);
343
+        }
344
+        return !result.equals("");
345
+    }
346
+
347
+    //强插
348
+    public boolean insert(String callerNum,String calleeNum, String sessionId,String action) {
349
+        String result = "";
350
+        try {
351
+            String command = EslCommandEnum.originate.name();
352
+            String arg = " {origination_caller_id_number=" + callerNum + ",cc_member_session_uuid=" + sessionId
353
+                    + ",call_called=" + calleeNum + "}user/" + callerNum + " &three_way(" + sessionId + ")"
354
+                    + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
355
+            result = client.sendAsyncApiCommand(command, arg);
356
+        } catch (Exception e) {
357
+            log.error(callerNum + "|" + calleeNum + "|" + sessionId + " 强插失败", e);
358
+        }
359
+        return !result.equals("");
360
+    }
361
+
362
+    //强截
363
+    public boolean intercept(String callerNum,String calleeNum, String chanId,String sessionId,String action) {
364
+        String result = "";
365
+        try {
366
+            Session session = EslCommon.getSessionById(sessionId);
367
+            String command = EslCommandEnum.originate.name();
368
+            String arg = " {origination_caller_id_number=" + callerNum + ",cc_member_session_uuid=" + sessionId
369
+                    + ",call_called=" + calleeNum + "}user/" + callerNum + " &intercept(" + chanId + ")"
370
+                    + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
371
+            result = client.sendAsyncApiCommand(command, arg);
372
+
373
+        } catch (Exception e) {
374
+            log.error(callerNum + "|" + calleeNum + "|" + chanId + "|" + sessionId + " 强截失败", e);
375
+        }
376
+        return !result.equals("");
377
+    }
378
+
379
+    //监听
380
+    public boolean listen(String callerNum,String calleeNum, String sessionId,String action) {
381
+        String result = "";
382
+        try {
383
+            String command = EslCommandEnum.originate.name();
384
+            String arg = " {origination_caller_id_number=" + callerNum+ ",cc_member_session_uuid=" + sessionId
385
+                    + ",call_called=" + calleeNum+ "}user/" + callerNum + " &eavesdrop(" + sessionId + ")"
386
+                    + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
387
+            result = client.sendAsyncApiCommand(command, arg);
388
+            
389
+        } catch (Exception e) {
390
+            log.error(callerNum + "|" + sessionId + " 监听失败", e);
391
+        }
392
+        return !result.equals("");
393
+    }
394
+
395
+    //播放排队位置
396
+    public boolean playPosition(int num, String chanId) {
397
+        String result = "";
398
+        try {
399
+            String command = EslCommandEnum.uuid_broadcast.name();
400
+            //String path = "/home/wav/" + num + ".mp3";
401
+            String path = TtsHelper.TextToSpeechPosition("你当前的位置为" + num, num + "");
402
+            String arg = chanId + " playback::" + path;
403
+            result = client.sendAsyncApiCommand(command, arg);
404
+        } catch (Exception e) {
405
+            log.error(num + "|" + chanId + " 播放排队位置失败", e);
406
+        }
407
+        return !result.equals("");
408
+    }
409
+
410
+    //播放坐席工号
411
+    public boolean playAgent(String agent, String chanId) {
412
+        String result = "";
413
+        try {
414
+//            String command = EslCommandEnum.sched_broadcast.name();
415
+//            String path = "/home/wav/8001.wav";
416
+//            //1秒后播放坐席工号
417
+//            String arg = " +1 " + chanId + " playback::" + path + " both";
418
+
419
+            String command = EslCommandEnum.uuid_broadcast.name();
420
+            //String path = "/home/wav/8001.wav";
421
+
422
+            String at = agent;
423
+            try {
424
+                Integer.parseInt(agent);
425
+                at = agent.replaceAll("(.)", " $1").substring(1);
426
+            } catch (Exception ex) { }
427
+
428
+            String path = TtsHelper.TextToSpeechAgent("你好," + at + "号话务员为您服务", agent);
429
+            String arg = chanId + " playback::" + path + " both";
430
+
431
+            result = client.sendAsyncApiCommand(command, arg);
432
+        } catch (Exception e) {
433
+            log.error(chanId + " 播放坐席工号失败", e);
434
+        }
435
+        return !result.equals("");
436
+    }
437
+
438
+    //播放语音
439
+    public boolean playBack(String path, String chanId) {
440
+        String result = "";
441
+        try {
442
+            String command = EslCommandEnum.uuid_broadcast.name();
443
+            //path = "/home/wav/8001.wav";
444
+            String arg = chanId + " playback::" + path;
445
+            result = client.sendAsyncApiCommand(command, arg);
446
+        } catch (Exception e) {
447
+            log.error(path + "|" + chanId + " 播放语音失败", e);
448
+        }
449
+        return !result.equals("");
450
+    }
451
+
452
+    //播放语音文本
453
+    public boolean playBackWord(String word, String chanId) {
454
+        String result = "";
455
+        try {
456
+            String command = EslCommandEnum.uuid_broadcast.name();
457
+            //path = "/home/wav/8001.wav";
458
+            String path = TtsHelper.TextToSpeechWord(word, SecretHelper.MD5(word));
459
+            String arg = chanId + " playback::" + path;
460
+            result = client.sendAsyncApiCommand(command, arg);
461
+        } catch (Exception e) {
462
+            log.error(word + "|" + chanId + " 播放语音失败", e);
463
+        }
464
+        return !result.equals("");
465
+    }
466
+
467
+    //播放语音并挂断
468
+    public boolean playHangup(String path, String chanId) {
469
+        String result = "";
470
+        try {
471
+            String command = EslCommandEnum.uuid_broadcast.name();
472
+            //path = "/home/wav/8001.wav";
473
+            String arg = chanId + " playback!::" + path;
474
+            result = client.sendAsyncApiCommand(command, arg);
475
+        } catch (Exception e) {
476
+            log.error(path + "|" + chanId + " 播放语音并挂断失败", e);
477
+        }
478
+        return !result.equals("");
479
+    }
480
+
481
+    //放音收号
482
+    public boolean playAndGetDigits(String path,String var, String chanId) {
483
+        String result = "";
484
+        try {
485
+            String command = EslCommandEnum.uuid_broadcast.name();
486
+            //path = "/home/wav/8001.wav";
487
+
488
+            String arg = chanId + " 'play_and_get_digits::1 1 2 2000 # " + path + " silence_stream://250 " + var + " \\d+'";
489
+            result = client.sendAsyncApiCommand(command, arg);
490
+
491
+        } catch (Exception e) {
492
+            log.error(path + "|" + var + "|" + chanId + " 放音收号失败", e);
493
+        }
494
+        return !result.equals("");
495
+    }
496
+
497
+    //放音识别
498
+    public boolean playAndDetectSpeech(String path,String var,  String chanId) {
499
+        String result = "";
500
+        try {
501
+            String command = EslCommandEnum.uuid_broadcast.name();
502
+            //path = "/home/wav/8001.wav";
503
+
504
+            String arg = chanId + " 'play_and_detect_speech::" + path + " detect:unimrcp:mrcpv2 "
505
+                    + "{start-input-timers=false,no-input-timeout=5000,define-grammar=false," + var + "=0}hello'";
506
+            result = client.sendAsyncApiCommand(command, arg);
507
+
508
+        } catch (Exception e) {
509
+            log.error(path + "|" + var + "|" + chanId + " 放音识别失败", e);
510
+        }
511
+        return !result.equals("");
512
+    }
513
+
514
+    //暂停播放语音
515
+    public boolean playBreak(String chanId) {
516
+        String result = "";
517
+        try {
518
+            String command = EslCommandEnum.uuid_break.name();
519
+            String arg = chanId ;
520
+            result = client.sendAsyncApiCommand(command, arg);
521
+        } catch (Exception e) {
522
+            log.error( chanId + " 暂停播放语音失败", e);
523
+        }
524
+        return !result.equals("");
525
+    }
526
+
527
+    //语音识别
528
+    public boolean funasr(String chanId,boolean isAsr) {
529
+        String result = "";
530
+        try {
531
+            String command = EslCommandEnum.uuid_audio_stream.name();
532
+            Map<String, Object> params = new HashMap<>();
533
+            params.put("chunk_size", new int[]{5, 10, 5});
534
+            params.put("wav_name", "h5");
535
+            params.put("is_speaking", true);
536
+            params.put("chunk_interval", 10);
537
+            params.put("itn", true);
538
+            params.put("mode", "offline");
539
+            params.put("hotwords", null);
540
+            String arg = "";
541
+            if (isAsr) {
542
+                arg = chanId + " start " + CommonConfig.funasr + " mono 16k " + JSON.toJSONString(params);
543
+            } else {
544
+                arg = chanId + " stop " + JSON.toJSONString(params);
545
+            }
546
+            result = client.sendAsyncApiCommand(command, arg);
547
+
548
+        } catch (Exception e) {
549
+            String state = isAsr ? "开启" : "关闭";
550
+            log.error(chanId + " " + state + "语音识别失败", e);
551
+        }
552
+        return !result.equals("");
553
+    }
554
+
555
+    //会话加入会议
556
+    public boolean talkJoinMeeting(String sessionId) {
557
+        String result = "";
558
+        try {
559
+            String command = EslCommandEnum.uuid_transfer.name();
560
+            //String arg = sessionId + " -both " + sessionId + " xml ExtenMeeting";
561
+
562
+            String at = "threeway";
563
+            Session session = EslCommon.getSessionById(sessionId);
564
+            if (session != null && session.isVideo()) at = "video-mcu-stereo";
565
+            String arg = sessionId + " -both 'set:hangup_after_bridge=false,set:record_concat_video=true,"
566
+                    + "conference:" + sessionId + "@" + at + "' inline";
567
+            result = client.sendAsyncApiCommand(command, arg);
568
+        } catch (Exception e) {
569
+            log.error(sessionId + " 会话加入会议失败", e);
570
+        }
571
+        return !result.equals("");
572
+    }
573
+
574
+    //呼叫号码加入会议
575
+    public boolean callJoinMeeting(String callerNum, String calleeNum, String meetingId,String action) {
576
+        String result = "";
577
+        try {
578
+            String fix = action.substring(action.lastIndexOf("|") + 1);
579
+            String command = EslCommandEnum.originate.name();
580
+            String at = "threeway", argstr = "";
581
+            Session session = EslCommon.getSessionById(meetingId);
582
+            if (session != null && session.isVideo()) {
583
+                at = "video-mcu-stereo";
584
+                String parentPath = "files/video/meeting/" + new SimpleDateFormat("yyyyMMdd").format(new Date());
585
+                String path = new File(parentPath).getAbsolutePath() + "/" + meetingId + ".mp4";
586
+                session.setVideoPath(parentPath + "/" + meetingId + ".mp4");
587
+                argstr = ",record_concat_video=true,conference_auto_record=" + path;
588
+            }
589
+
590
+            String arg = " {origination_caller_id_number=" + callerNum + ",cc_member_session_uuid=" + meetingId
591
+                    + ",call_called=" + calleeNum.substring(fix.length())
592
+                    + ",transfer_ringback=local_stream://moh,ringback=${us-ring}"
593
+                    + argstr + "}" + getCallString(calleeNum)
594
+                    // + " " + meetingId + " xml ExtenMeeting";
595
+                    + " &conference(" + meetingId + "@" + at + ")"
596
+                    + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
597
+            result = client.sendAsyncApiCommand(command, arg);
598
+
599
+        } catch (Exception e) {
600
+            log.error(callerNum + "|" + calleeNum + "|" + meetingId + " 呼叫加入会议失败", e);
601
+        }
602
+        return !result.equals("");
603
+    }
604
+
605
+    //开启/关闭静音
606
+    public boolean setMute(String chanId, boolean isMute,String action) {
607
+        String result = "";
608
+        try {
609
+            String command = EslCommandEnum.uuid_audio.name();
610
+            String arg = chanId + (isMute ? " start" : " stop") + " write mute -4"
611
+                    +"\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
612
+            result = client.sendAsyncApiCommand(command, arg);
613
+
614
+        } catch (Exception e) {
615
+            String state = isMute ? "开启" : "关闭";
616
+            log.error(chanId + " " + state + "静音失败", e);
617
+        }
618
+        return !result.equals("");
619
+    }
620
+
621
+    //开启/关闭保持
622
+    public boolean setHold(String chanId, boolean isHold,String action) {
623
+        String result = "";
624
+        try {
625
+            String command = EslCommandEnum.uuid_hold.name();
626
+            String arg = (isHold ? " " : " off") + " " + chanId
627
+                    + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
628
+            result = client.sendAsyncApiCommand(command, arg);
629
+
630
+        } catch (Exception e) {
631
+            String state = isHold ? "开启" : "关闭";
632
+            log.error(chanId + " " + state + "保持失败", e);
633
+        }
634
+        return !result.equals("");
635
+    }
636
+
637
+    //录音
638
+    public boolean record(String chanId, String filePath,boolean isRecord) {
639
+        String result = "";
640
+        try {
641
+            String command = EslCommandEnum.uuid_record.name();
642
+            String arg = chanId + (isRecord ? " start" : " stop") + filePath;
643
+            result = client.sendAsyncApiCommand(command, arg);
644
+        } catch (Exception e) {
645
+            String state = isRecord ? "开启" : "关闭";
646
+            log.error(chanId + "|" + filePath + " " + state + "录音失败", e);
647
+        }
648
+        return !result.equals("");
649
+    }
650
+
651
+    //转队列
652
+    public boolean transferQueue(String chanId) {
653
+        String result = "";
654
+        try {
655
+            String command = EslCommandEnum.uuid_transfer.name();
656
+            //String arg = chanId + " queue xml queue";
657
+            String arg = chanId + " 'set:hangup_after_bridge=false,sleep:500,set:continue_on_fail=true,"
658
+                    + "callcenter:${group}' inline";
659
+            result = client.sendAsyncApiCommand(command, arg);
660
+        } catch (Exception e) {
661
+            log.error(chanId + " 转队列失败", e);
662
+        }
663
+        return !result.equals("");
664
+    }
665
+
666
+    //转满意度
667
+    public boolean transferMyd(String chanId,String action) {
668
+        String result = "";
669
+        try {
670
+            String command = EslCommandEnum.uuid_transfer.name();
671
+            //String arg = chanId + " turnmyd xml ForExten";
672
+            String arg = chanId + " 'set:hangup_after_bridge=false,ivr:myd' inline"
673
+                    +"\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
674
+            result = client.sendAsyncApiCommand(command, arg);
675
+            
676
+        } catch (Exception e) {
677
+            log.error(chanId + " 转满意度失败", e);
678
+        }
679
+        return !result.equals("");
680
+    }
681
+
682
+    //转移号码
683
+    public boolean transfer(String chanId,String callerNum, String calleeNum,String action) {
684
+        String result = "";
685
+        try {
686
+            String fix = action.substring(action.lastIndexOf("|") + 1);
687
+            String command = EslCommandEnum.uuid_transfer.name();
688
+            //String arg = chanId + " " + calleeNum + " xml ForExten";
689
+//            String arg = chanId + " 'm:^:set:hangup_after_bridge=false^set:record_concat_video=true^"
690
+//                    + "set:instant_ringback=true^set:transfer_ringback=local_stream://moh^"
691
+//                    + "bridge:{ignore_early_media=true,origination_caller_id_number=" + callerNum + ",call_called="
692
+//                    + calleeNum.substring(fix.length()) + "}" + getCallString(calleeNum) + "' inline"
693
+//                    + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
694
+            String arg = chanId + " 'm:^:set:hangup_after_bridge=false^set:record_concat_video=true^"
695
+                    + "set:transfer_ringback=local_stream://moh^set:ringback=${us-ring}^"
696
+                    + "bridge:{origination_caller_id_number=" + callerNum + ",call_called="
697
+                    + calleeNum.substring(fix.length()) + "}" + getCallString(calleeNum) + "' inline"
698
+                    + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
699
+            result = client.sendAsyncApiCommand(command, arg);
700
+
701
+        } catch (Exception e) {
702
+            log.error(chanId + "|" + calleeNum + " 转移失败", e);
703
+        }
704
+        return !result.equals("");
705
+    }
706
+
707
+    //发送按键
708
+    public boolean sendDtmf(String chanId, String dtmf,String action) {
709
+        String result = "";
710
+        try {
711
+            String command = EslCommandEnum.uuid_send_dtmf.name();
712
+            String arg = chanId + " " + dtmf
713
+                    +"\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
714
+            result = client.sendAsyncApiCommand(command, arg);
715
+            
716
+        } catch (Exception e) {
717
+            log.error(chanId + "|" + dtmf + " 发送按键失败", e);
718
+        }
719
+        return !result.equals("");
720
+    }
721
+
722
+    //设置会议人员离开是否播放声音
723
+    public boolean setConferenceExitSound(String meetingId, boolean isplay) {
724
+        String result = "";
725
+        try {
726
+            String command = EslCommandEnum.conference.name();
727
+            String arg = meetingId + " exit_sound " + (isplay ? "on" : "off");
728
+            result = client.sendAsyncApiCommand(command, arg);
729
+            
730
+        } catch (Exception e) {
731
+            log.error(meetingId + "|" + isplay + " 设置会议离开失败", e);
732
+        }
733
+        return !result.equals("");
734
+    }
735
+
736
+    //设置会议人员是否静音
737
+    public boolean setConferenceIsMute(String meetingId, String memberId, boolean isMute,String action) {
738
+        String result = "";
739
+        try {
740
+            String command = EslCommandEnum.conference.name();
741
+            if (isMute) {
742
+                String arg = meetingId + " deaf " + memberId;
743
+                client.sendAsyncApiCommand(command, arg);
744
+                arg = meetingId + " mute " + memberId
745
+                        +"\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
746
+                result = client.sendAsyncApiCommand(command, arg);
747
+            } else {
748
+                String arg = meetingId + " undeaf " + memberId;
749
+                client.sendAsyncApiCommand(command, arg);
750
+                arg = meetingId + " stop all " + memberId;
751
+                client.sendAsyncApiCommand(command, arg);
752
+                arg = meetingId + " unmute " + memberId
753
+                        +"\r\nJob-UUID: " + action + "|" + System.currentTimeMillis();
754
+                result = client.sendAsyncApiCommand(command, arg);
755
+            }
756
+            
757
+        } catch (Exception e) {
758
+            log.error(meetingId + "|" + memberId + "|" + isMute + " 设置会议静音失败", e);
759
+        }
760
+        return !result.equals("");
761
+    }
762
+
763
+    //自动外呼
764
+    public boolean autoCall(String callerNum, String calleeNum,String taskId,String phoneId) {
765
+        String result = "";
766
+        try {
767
+            String command = EslCommandEnum.originate.name();
768
+            String arg = " {origination_caller_id_number=" + callerNum + ",task_id=" + taskId + ",phone_id=" + phoneId + ",call_type=3}"
769
+                    + getCallString(calleeNum) + " &park()";
770
+            result = client.sendAsyncApiCommand(command, arg);
771
+
772
+        } catch (Exception e) {
773
+            log.error(callerNum + "|" + calleeNum + " 自动外呼失败", e);
774
+        }
775
+        return !result.equals("");
776
+    }
777
+
778
+    //api命令
779
+    public boolean apiCommand(String command, String arg) {
780
+        String result = "";
781
+        try {
782
+            result = client.sendAsyncApiCommand(command, arg);
783
+        } catch (Exception e) {
784
+            log.error(command + "|" + arg + " api命令失败", e);
785
+        }
786
+        return !result.equals("");
787
+    }
788
+
789
+    public boolean appCommand(String chanId,String command, String arg) {
790
+        try {
791
+            SendMsg sm=new SendMsg(chanId);
792
+            sm.addCallCommand("execute");
793
+            sm.addExecuteAppName(command);
794
+            sm.addExecuteAppArg(arg);
795
+            return client.sendMessage(sm).isOk();
796
+        } catch (Exception e) {
797
+            log.error(command + "|" + arg + " app命令失败", e);
798
+        }
799
+        return false;
800
+    }
801
+
802
+    //呼叫字符串
803
+    private String getCallString(String calleeNum) {
804
+        //呼叫内线分机号码
805
+        String callStr = "user/" + calleeNum;
806
+        //呼叫外线号码
807
+        if (!EslCommon.existExten(calleeNum)) {
808
+            callStr = "sofia/gateway/hykj/" + calleeNum;
809
+
810
+//            //动态ip
811
+//            EslMessage message = client.sendSyncApiCommand("sofia_contact", "");
812
+//            if (message != null && message.getBodyLines().size() > 0) {
813
+//                String gwip = message.getBodyLines().get(0);
814
+//                callStr = "sofia/internal/" + calleeNum + gwip.substring(gwip.indexOf("@"));
815
+//            }
816
+        }
817
+        return callStr;
818
+    }
819
+}

+ 35 - 0
midware-service/src/main/java/midware/service/init/QuartzService.java

@@ -0,0 +1,35 @@
1
+package midware.service.init;
2
+
3
+import lombok.extern.slf4j.Slf4j;
4
+import midware.service.quartz.job.AuthJob;
5
+import midware.service.quartz.job.BatchInsertJob;
6
+import midware.service.quartz.job.WsHeartJob;
7
+import midware.service.quartz.util.QuartzHelper;
8
+import org.quartz.Scheduler;
9
+import org.quartz.SchedulerException;
10
+import org.springframework.beans.factory.annotation.Autowired;
11
+import org.springframework.core.annotation.Order;
12
+import org.springframework.stereotype.Service;
13
+
14
+import javax.annotation.PostConstruct;
15
+
16
+@Slf4j
17
+@Service
18
+@Order(2)
19
+public class QuartzService {
20
+    @Autowired
21
+    private Scheduler scheduler;
22
+
23
+    @PostConstruct
24
+    public void init() {
25
+        try {
26
+            scheduler.clear();
27
+        } catch (SchedulerException e) {
28
+            log.error("quartz初始化清理异常", e);
29
+        }
30
+
31
+        QuartzHelper.createScheduleJob(scheduler, new BatchInsertJob());
32
+        QuartzHelper.createScheduleJob(scheduler, new AuthJob());
33
+        QuartzHelper.createScheduleJob(scheduler, new WsHeartJob());
34
+    }
35
+}

+ 600 - 0
midware-service/src/main/java/midware/service/init/WebSocketService.java

@@ -0,0 +1,600 @@
1
+package midware.service.init;
2
+
3
+import com.alibaba.fastjson2.JSON;
4
+import lombok.extern.slf4j.Slf4j;
5
+import midware.entity.database.rep.AgentAction;
6
+import midware.service.eslclient.EslCommon;
7
+import midware.service.eslclient.entity.Agent;
8
+import midware.service.eslclient.entity.Channel;
9
+import midware.util.enums.EslAgentEnum;
10
+import midware.util.helper.SpringHelper;
11
+import midware.util.helper.StringHelper;
12
+import org.springframework.stereotype.Component;
13
+
14
+import javax.websocket.*;
15
+import javax.websocket.server.ServerEndpoint;
16
+import java.io.IOException;
17
+import java.util.*;
18
+import java.util.concurrent.ConcurrentHashMap;
19
+import java.util.stream.Collectors;
20
+
21
+@Slf4j
22
+@Component
23
+@ServerEndpoint("/ws")
24
+public class WebSocketService {
25
+    private EslClientService eslClientService = SpringHelper.getBean(EslClientService.class);
26
+    private Session session;
27
+    private String agentId;
28
+
29
+    //会话池
30
+    private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>();
31
+
32
+    //监控会话池
33
+    private static List<Session> subScribeSessionPool = new ArrayList<>();
34
+
35
+    /**
36
+     * 链接成功调用的方法
37
+     */
38
+    @OnOpen
39
+    public void onOpen(Session session) {
40
+        this.session = session;
41
+    }
42
+
43
+    /**
44
+     * 链接关闭调用的方法
45
+     */
46
+    @OnClose
47
+    public void onClose() {
48
+        try {
49
+            Agent a = EslCommon.getAgent(agentId);
50
+            if (a != null) {
51
+                if (a.getAgentState() != EslAgentEnum.logout.ordinal()) {
52
+                    a.setAgentState(EslAgentEnum.logout.ordinal());
53
+                }
54
+                eslClientService.logout(a.getAgent(), a.getGroup(),"");
55
+                EslCommon.agents.remove(a);
56
+                sessionPool.remove(agentId);
57
+            }
58
+            subScribeSessionPool.remove(session);
59
+        } catch (Exception e) {
60
+            log.error("close错误", e);
61
+        }
62
+    }
63
+
64
+    /**
65
+     * 收到客户端消息后调用的方法
66
+     *
67
+     * @param message
68
+     */
69
+    @OnMessage
70
+    public void onMessage(String message) {
71
+        try {
72
+            Map map = JSON.parseObject(message, Map.class);
73
+            String type = map.get("Type").toString();
74
+
75
+            Map<String, Object> result = new HashMap<>();
76
+            result.put("Type", type);
77
+
78
+            if(EslCommon.auth.isExpire()){
79
+                result.put("Result", "授权过期");
80
+                sendText(session,JSON.toJSONString(result));
81
+                return;
82
+            }
83
+
84
+            result.put("Result", "操作失败1");
85
+            Agent agent = EslCommon.getAgent(agentId);
86
+            Channel chan = null;
87
+            EslAgentEnum state =null;
88
+            if (agent != null) {
89
+                chan = EslCommon.getChanByExten(agent.getExten());
90
+                state = EslAgentEnum.values()[agent.getAgentState()];
91
+                if (chan == null) {
92
+                    result.put("Result", "分机未注册");
93
+                    state = null;
94
+                }
95
+            }
96
+
97
+            String param = "";
98
+            boolean isExec = false;
99
+            switch (type) {
100
+                case "Heart":
101
+                    result.put("Result", true);
102
+                    break;
103
+                case "Login"://签入
104
+                    String AgentId = map.get("AgentId").toString();
105
+                    String AgentExten = map.get("AgentExten").toString();
106
+                    String AgentGroup = map.get("AgentGroup").toString();
107
+                    param =  AgentGroup;
108
+                    //String AgentType = map.get("AgentType").toString();
109
+
110
+                    if (StringHelper.isNotEmpty(AgentId) && StringHelper.isNotEmpty(AgentExten) && StringHelper.isNotEmpty(AgentGroup)) {
111
+                        //判断是否坐席真的存在
112
+                        if (EslCommon.existAgent(AgentId)) {
113
+                            Map<String, Object> result1 = new HashMap<>();
114
+                            result1.put("Type", "Heart");
115
+                            result1.put("Result", true);
116
+                            sendMessageAll(JSON.toJSONString(result1));
117
+
118
+                            try {
119
+                                Thread.sleep(300);
120
+                            } catch (InterruptedException ignored) {
121
+                            }
122
+                        }
123
+                        if (EslCommon.existAgent(AgentId)) {
124
+                            result.put("Result", "坐席已存在");
125
+                        } else if (!EslCommon.existExten(AgentExten)) {
126
+                            result.put("Result", "分机未注册");
127
+                        } else if (EslCommon.getAgentByExten(AgentExten) != null) {
128
+                            result.put("Result", "分机已存在");
129
+                        } else if (EslCommon.auth.getAgentNum() > 0 && EslCommon.agents.size() >= EslCommon.auth.getAgentNum()) {
130
+                            result.put("Result", "坐席数量已达上限");
131
+                        } else {
132
+                            this.agentId = AgentId;
133
+                            sessionPool.put(AgentId, session);
134
+
135
+                            agent = new Agent();
136
+                            agent.setAgent(AgentId);
137
+                            agent.setExten(AgentExten);
138
+                            agent.setGroup(AgentGroup);
139
+                            agent.setAgentState(EslAgentEnum.loging.ordinal());
140
+
141
+                            EslCommon.agents.add(agent);
142
+                            chan = EslCommon.getChanByExten(AgentExten);
143
+                            isExec = eslClientService.login(AgentId, AgentExten, AgentGroup, type + "|" + AgentId + "|" + AgentExten + "|" + AgentGroup);
144
+                            if (!isExec) {
145
+                                EslCommon.agents.remove(agent);
146
+                            }
147
+                        }
148
+                    }
149
+                    break;
150
+                case "Logout"://签出
151
+                    //空闲/置忙/话后处理  可以签出
152
+                    if (Arrays.asList(EslAgentEnum.free, EslAgentEnum.busy, EslAgentEnum.aftertalk).contains(state)) {
153
+                        isExec = eslClientService.logout(agentId, agent.getGroup(), type + "|" + agentId);
154
+                        if (isExec && subScribeSessionPool.contains(session)) subScribeSessionPool.remove(session);
155
+                    }
156
+                    break;
157
+                case "WorkOn"://置闲
158
+                    //置忙/话后处理  可以置闲
159
+                    if (Arrays.asList(EslAgentEnum.busy, EslAgentEnum.aftertalk).contains(state)) {
160
+                        isExec = eslClientService.setWork(agentId, true,type + "|" + agentId);
161
+                    }
162
+                    break;
163
+                case "WorkOff"://置忙
164
+                    //空闲/话后处理  可以置忙
165
+                    if (Arrays.asList(EslAgentEnum.free, EslAgentEnum.aftertalk).contains(state)) {
166
+                        isExec = eslClientService.setWork(agentId, false,type + "|" + agentId);
167
+                    }
168
+                    break;
169
+                case "MakeCall"://外呼
170
+                    //空闲/置忙/话后处理  可以外呼
171
+                    if (map.get("DestinationNumber") != null && Arrays.asList(EslAgentEnum.free, EslAgentEnum.busy, EslAgentEnum.aftertalk).contains(state)) {
172
+                        String DestinationNumber = map.get("DestinationNumber").toString();
173
+                        String Fix = map.get("Fix") != null ? map.get("Fix").toString() : "";
174
+                        param = DestinationNumber + (Fix.equals("") ? "" : "|" + Fix);
175
+                        if (StringHelper.isNotEmpty(DestinationNumber)) {
176
+                            Agent tAgent = EslCommon.getAgentByExten(DestinationNumber);
177
+                            if (tAgent != null && tAgent.getAgentState() != EslAgentEnum.free.ordinal()) {
178
+                                result.put("Result", "目标坐席忙碌中");
179
+                            } else {
180
+                                agent.setOpType(type);
181
+                                isExec = eslClientService.extenCall(agent.getExten(), DestinationNumber, type + "|" + agentId + "|" + DestinationNumber + "|" + Fix);
182
+                            }
183
+                        }
184
+                    }
185
+                    break;
186
+                case "HoldOn"://开启保持
187
+                    //通话中  可以开启保持
188
+                    if (Objects.equals(state, EslAgentEnum.talking)) {
189
+                        isExec = eslClientService.setHold(chan.getSessionId(), true,type + "|" + agentId);
190
+                    }
191
+                    break;
192
+                case "HoldOff"://关闭保持
193
+                    //通话中  可以关闭保持
194
+                    if (Objects.equals(state, EslAgentEnum.talking)) {
195
+                        isExec = eslClientService.setHold(chan.getSessionId(), false,type + "|" + agentId);
196
+                    }
197
+                    break;
198
+                case "MuteOn"://开启静音
199
+                    //通话中  可以开启静音
200
+                    if (Objects.equals(state, EslAgentEnum.talking)) {
201
+                        isExec = eslClientService.setMute(chan.getChanId(), true,type + "|" + agentId);
202
+                    }
203
+                    break;
204
+                case "MuteOff"://关闭静音
205
+                    //通话中  可以关闭静音
206
+                    if (Objects.equals(state, EslAgentEnum.talking)) {
207
+                        isExec = eslClientService.setMute(chan.getChanId(), false,type + "|" + agentId);
208
+                    }
209
+                    break;
210
+                case "Transfer"://转移
211
+                    //通话中  可以转移
212
+                    if (map.get("DestinationNumber") != null && Objects.equals(state, EslAgentEnum.talking)) {
213
+                        String DestinationNumber = map.get("DestinationNumber").toString();
214
+                        String Fix = map.get("Fix") != null ? map.get("Fix").toString() : "";
215
+                        param = DestinationNumber + (Fix.equals("") ? "" : "|" + Fix);
216
+                        if (StringHelper.isNotEmpty(DestinationNumber)) {
217
+                            if (DestinationNumber.equals(agent.getExten())) {
218
+                                result.put("Result", "目标不能是自己");
219
+                            } else {
220
+                                Agent tAgent = EslCommon.getAgentByExten(DestinationNumber);
221
+                                if (tAgent != null && tAgent.getAgentState() != EslAgentEnum.free.ordinal()) {
222
+                                    result.put("Result", "目标坐席忙碌中");
223
+                                } else if (EslCommon.isInSession(DestinationNumber)) {
224
+                                    result.put("Result", "目标号码忙碌中");
225
+                                } else if (chan.getSessionSort() == 1) {//呼出方不可以转移
226
+                                    result.put("Result", "主叫不能此操作");
227
+                                } else {
228
+                                    agent.setOpType(type);
229
+                                    isExec = eslClientService.transfer(chan.getSessionId(), agent.getExten(), DestinationNumber, type + "|" + agentId + "|" + DestinationNumber+ "|" + Fix);
230
+                                }
231
+                            }
232
+                        }
233
+                    }
234
+                    break;
235
+                case "ConsultOn"://开启协商
236
+                    //通话中  可以协商
237
+                    if (map.get("DestinationNumber") != null && Objects.equals(state, EslAgentEnum.talking)) {
238
+                        String DestinationNumber = map.get("DestinationNumber").toString();
239
+                        String Fix = map.get("Fix") != null ? map.get("Fix").toString() : "";
240
+                        param = DestinationNumber + (Fix.equals("") ? "" : "|" + Fix);
241
+                        if (StringHelper.isNotEmpty(DestinationNumber)) {
242
+                            if (DestinationNumber.equals(agent.getExten())) {
243
+                                result.put("Result", "目标不能是自己");
244
+                            } else {
245
+                                Agent tAgent = EslCommon.getAgentByExten(DestinationNumber);
246
+                                if (tAgent != null && tAgent.getAgentState() != EslAgentEnum.free.ordinal()) {
247
+                                    result.put("Result", "目标坐席忙碌中");
248
+                                } else if (EslCommon.isInSession(DestinationNumber)) {
249
+                                    result.put("Result", "目标号码忙碌中");
250
+                                } else if (chan.getSessionSort() == 1) {//呼出方不可以协商
251
+                                    result.put("Result", "主叫不能此操作");
252
+                                } else {
253
+                                    agent.setOpType(type);
254
+                                    isExec = eslClientService.consult(chan.getSessionId(), agent.getExten(), DestinationNumber, type + "|" + agentId + "|" + DestinationNumber+ "|" + Fix);
255
+                                }
256
+                            }
257
+                        }
258
+                    }
259
+                    break;
260
+                case "ConsultOff"://关闭协商
261
+                    //通话中  可以协商取消
262
+                    if (Objects.equals(state, EslAgentEnum.talking)) {
263
+                        String sid = chan.getSessionId();
264
+                        Channel channel = EslCommon.channels.stream().filter(p -> p.getSessionId().equals(sid)
265
+                                && p.getSessionSort() == 3).findFirst().get();
266
+                        isExec = eslClientService.kill(channel.getChanId(),type + "|" + agentId);
267
+                    }
268
+                    break;
269
+                case "Meeting"://会议
270
+                    //通话中  可以会议
271
+                    if (map.get("DestinationNumber") != null && Objects.equals(state, EslAgentEnum.talking)) {
272
+                        String DestinationNumber = map.get("DestinationNumber").toString();
273
+                        String Fix = map.get("Fix") != null ? map.get("Fix").toString() : "";
274
+                        param = DestinationNumber + (Fix.equals("") ? "" : "|" + Fix);
275
+                        if (StringHelper.isNotEmpty(DestinationNumber)) {
276
+                            if (DestinationNumber.equals(agent.getExten())) {
277
+                                result.put("Result", "目标不能是自己");
278
+                            } else {
279
+                                Agent tAgent = EslCommon.getAgentByExten(DestinationNumber);
280
+                                if (tAgent != null && tAgent.getAgentState() != EslAgentEnum.free.ordinal()) {
281
+                                    result.put("Result", "目标坐席忙碌中");
282
+                                } else if (EslCommon.isInSession(DestinationNumber)) {
283
+                                    result.put("Result", "目标号码忙碌中");
284
+                                } else {
285
+                                    agent.setOpType(type);
286
+                                    isExec = eslClientService.callJoinMeeting(agent.getExten(), DestinationNumber, chan.getSessionId(), type + "|" + agentId + "|" + DestinationNumber+ "|" + Fix);
287
+                                }
288
+                            }
289
+                        }
290
+                    }
291
+                    break;
292
+                case "TurnMyd"://转满意度
293
+                    //通话中  可以转满意度
294
+                    if (Objects.equals(state, EslAgentEnum.talking)) {
295
+                        isExec = eslClientService.transferMyd(chan.getSessionId(),type + "|" + agentId);
296
+                    }
297
+                    break;
298
+                case "DropCall"://挂机
299
+                    //通话中/请求中  可以挂机
300
+                    if (Arrays.asList(EslAgentEnum.talking, EslAgentEnum.requested).contains(state)) {
301
+                        isExec = eslClientService.kill(chan.getChanId(),type + "|" + agentId);
302
+                    }
303
+                    break;
304
+                case "SendDtmf"://发送按键
305
+                    //通话中  可以发送按键
306
+                    if (map.get("Dtmf") != null &&Objects.equals(state, EslAgentEnum.talking)) {
307
+                        String dtmf = map.get("Dtmf").toString();
308
+                        param = dtmf;String sid=chan.getSessionId();
309
+                        Channel last= EslCommon.channels.stream().filter(p->p.getSessionId().equals(sid)).max(Comparator.comparing(Channel::getSessionSort)).get();
310
+                        isExec = eslClientService.sendDtmf(last.getChanId(),dtmf,type + "|" + agentId);
311
+                    }
312
+                    break;
313
+                case "SubScribeOn":
314
+                    if (agent != null) agent.setIsMonitor(1);
315
+                    subScribeSessionPool.add(this.session);
316
+                    result.put("Result", true);
317
+                    break;
318
+                case "SubScribeOff":
319
+                    if (agent != null) agent.setIsMonitor(0);
320
+                    subScribeSessionPool.remove(this.session);
321
+                    result.put("Result", true);
322
+                    break;
323
+                case "Listen"://监听
324
+                    //空闲/置忙  可以监听
325
+                    if (map.get("TargetAgentID") != null && Arrays.asList(EslAgentEnum.free, EslAgentEnum.busy).contains(state)) {
326
+                        String TargetAgentID = map.get("TargetAgentID").toString();
327
+                        param = TargetAgentID;
328
+                        if (StringHelper.isNotEmpty(TargetAgentID)) {
329
+                            if (TargetAgentID.equals(agentId)) {
330
+                                result.put("Result", "目标不能是自己");
331
+                            } else {
332
+                                Agent tAgent = EslCommon.getAgent(TargetAgentID);
333
+                                String check = checkTargetAgentTalk(tAgent);
334
+                                if (StringHelper.isEmpty(check)) {
335
+                                    Channel tchan = EslCommon.getChanByExten(tAgent.getExten());
336
+                                    if (tchan != null && StringHelper.isNotEmpty(tchan.getSessionId())) {
337
+                                        agent.setOpType(type);
338
+                                        isExec = eslClientService.listen(agent.getExten(),tchan.getNumber(), tchan.getSessionId(), type + "|" + agentId + "|" + agent.getExten());
339
+                                    }
340
+                                } else {
341
+                                    result.put("Result", check);
342
+                                }
343
+                            }
344
+                        }
345
+                    }
346
+                    break;
347
+                case "Insert"://强插
348
+                    //空闲/置忙  可以强插
349
+                    if (map.get("TargetAgentID") != null && Arrays.asList(EslAgentEnum.free, EslAgentEnum.busy).contains(state)) {
350
+                        String TargetAgentID = map.get("TargetAgentID").toString();
351
+                        param = TargetAgentID;
352
+                        if (StringHelper.isNotEmpty(TargetAgentID)) {
353
+                            if (TargetAgentID.equals(agentId)) {
354
+                                result.put("Result", "目标不能是自己");
355
+                            } else {
356
+                                Agent tAgent = EslCommon.getAgent(TargetAgentID);
357
+                                String check = checkTargetAgentTalk(tAgent);
358
+                                if (StringHelper.isEmpty(check)) {
359
+                                    Channel tchan = EslCommon.getChanByExten(tAgent.getExten());
360
+                                    if (tchan != null && StringHelper.isNotEmpty(tchan.getSessionId())) {
361
+                                        agent.setOpType(type);
362
+                                        String sid = tchan.getSessionId();
363
+                                        isExec = eslClientService.insert(agent.getExten(), tchan.getNumber(), sid, type + "|" + agentId + "|" + agent.getExten());
364
+                                    }
365
+                                } else {
366
+                                    result.put("Result", check);
367
+                                }
368
+                            }
369
+                        }
370
+                    }
371
+                    break;
372
+                case "Intercept"://强截
373
+                    //空闲/置忙  可以强截
374
+                    if (map.get("TargetAgentID") != null && Arrays.asList(EslAgentEnum.free, EslAgentEnum.busy).contains(state)) {
375
+                        String TargetAgentID = map.get("TargetAgentID").toString();
376
+                        param = TargetAgentID;
377
+                        if (StringHelper.isNotEmpty(TargetAgentID)) {
378
+                            if (TargetAgentID.equals(agentId)) {
379
+                                result.put("Result", "目标不能是自己");
380
+                            } else {
381
+                                Agent tAgent = EslCommon.getAgent(TargetAgentID);
382
+                                String check = checkTargetAgentTalk(tAgent);
383
+                                if (StringHelper.isEmpty(check)) {
384
+                                    Channel tchan = EslCommon.getChanByExten(tAgent.getExten());
385
+                                    if (tchan != null && StringHelper.isNotEmpty(tchan.getSessionId())) {
386
+                                        agent.setOpType(type);
387
+                                        String sid = tchan.getSessionId();
388
+                                        Channel channel = EslCommon.getFirstChanBySessionId(sid);
389
+                                        isExec = eslClientService.intercept(agent.getExten(), tAgent.getExten(), channel.getChanId(), sid, type + "|" + agentId + "|" + agent.getExten());
390
+                                    }
391
+                                } else {
392
+                                    result.put("Result", check);
393
+                                }
394
+                            }
395
+                        }
396
+                    }
397
+                    break;
398
+                case "Break"://强拆
399
+                    if (map.get("TargetAgentID") != null) {
400
+                        String TargetAgentID = map.get("TargetAgentID").toString();
401
+                        param = TargetAgentID;
402
+                        if (StringHelper.isNotEmpty(TargetAgentID)) {
403
+                            if (TargetAgentID.equals(agentId)) {
404
+                                result.put("Result", "目标不能是自己");
405
+                            } else {
406
+                                Agent tAgent = EslCommon.getAgent(TargetAgentID);
407
+                                String check = checkTargetAgentTalk(tAgent);
408
+                                if (StringHelper.isEmpty(check)) {
409
+                                    Channel tchan = EslCommon.getChanByExten(tAgent.getExten());
410
+                                    if (tchan != null && StringHelper.isNotEmpty(tchan.getSessionId())) {
411
+                                        isExec = eslClientService.kill(tchan.getSessionId(),type + "|" + agentId);
412
+                                    }
413
+                                } else {
414
+                                    result.put("Result", check);
415
+                                }
416
+                            }
417
+                        }
418
+                    }
419
+                    break;
420
+                case "Instead"://代接
421
+                    //空闲/置忙  可以代接
422
+                    if (map.get("TargetAgentID") != null && Arrays.asList(EslAgentEnum.free, EslAgentEnum.busy).contains(state)) {
423
+                        String TargetAgentID = map.get("TargetAgentID").toString();
424
+                        param = TargetAgentID;
425
+                        if (StringHelper.isNotEmpty(TargetAgentID)) {
426
+                            if (TargetAgentID.equals(agentId)) {
427
+                                result.put("Result", "目标不能是自己");
428
+                            } else {
429
+                                Agent tAgent = EslCommon.getAgent(TargetAgentID);
430
+                                if (tAgent == null) {
431
+                                    result.put("Result", "目标坐席未签入");
432
+                                } else if (tAgent.getAgentState() != EslAgentEnum.requested.ordinal()) {
433
+                                    result.put("Result", "目标坐席未振铃");
434
+                                } else {
435
+                                    Channel tchan = EslCommon.getChanByExten(tAgent.getExten());
436
+                                    if (tchan != null && StringHelper.isNotEmpty(tchan.getSessionId())) {
437
+                                        if (tchan.getSessionSort() == 1) {//不能代接开始方
438
+                                            result.put("Result", "主叫不能代接");
439
+                                        } else {
440
+                                            agent.setOpType(type);
441
+                                            String sid = tchan.getSessionId();
442
+                                            Channel channel = EslCommon.getFirstChanBySessionId(sid);
443
+                                            isExec = eslClientService.intercept(agent.getExten(), tAgent.getExten(), channel.getChanId(), sid, type + "|" + agentId + "|" + agent.getExten());
444
+                                        }
445
+                                    }
446
+                                }
447
+                            }
448
+                        }
449
+                    }
450
+                    break;
451
+                case "ForceWorkOn"://强制置闲
452
+                case "ForceWorkOff"://强制置忙
453
+                    if (map.get("TargetAgentID") != null) {
454
+                        String TargetAgentID = map.get("TargetAgentID").toString();
455
+                        param = TargetAgentID;
456
+                        if (StringHelper.isNotEmpty(TargetAgentID)) {
457
+                            Agent tAgent = EslCommon.getAgent(TargetAgentID);
458
+                            if (tAgent == null) {
459
+                                result.put("Result", "目标坐席未签入");
460
+//                            } else if (tAgent.getAgentState() != EslAgentEnum.free.ordinal()) {
461
+//                                result.put("Result", "目标坐席不能置忙");
462
+                            } else {
463
+                                isExec = eslClientService.setWork(TargetAgentID, type.equals("ForceWorkOn"), type + "|" + agentId + "|" + TargetAgentID);
464
+                            }
465
+                        }
466
+                    }
467
+                    break;
468
+            }
469
+
470
+            AgentAction aa = new AgentAction();
471
+            aa.setAction(type);
472
+            if(agent!=null) {
473
+                aa.setGroupNo(agent.getGroup());
474
+                aa.setAgent(agent.getAgent());
475
+                aa.setExten(agent.getExten());
476
+            }
477
+            aa.setParam(param);
478
+            if (chan != null) aa.setUuid(chan.getSessionId());
479
+            aa.setIsSuccess(0);
480
+            aa.setCreateTime(new Date());
481
+
482
+            if (!isExec) {
483
+                sendText(session,JSON.toJSONString(result));
484
+                if (!type.equals("Heart")) {
485
+                    synchronized (EslCommon.actions) {
486
+                        EslCommon.actions.add(aa);
487
+                    }
488
+                }
489
+                if (type.equals("SubScribeOn")) {
490
+                    Map<String, Object> result1 = new HashMap<>();
491
+                    result1.put("Type", "AgentState");
492
+                    result1.put("Result", true);
493
+                    List<Agent> agents = new ArrayList<>(EslCommon.agents);
494
+                    for (Agent agent1 : agents) {
495
+                        if(!agent1.getAgent().equals(agentId)) {
496
+                            result1.put("State", agent1.getAgentState());
497
+                            result1.put("AgentId", agent1.getAgent());
498
+                            result1.put("Exten", agent1.getExten());
499
+                            result1.put("Monitor", agent1.getIsMonitor());
500
+                            sendText(session, JSON.toJSONString(result1));
501
+                        }
502
+                    }
503
+                    //通知其他监控
504
+                    if (agent != null) agent.setAgentState(agent.getAgentState());
505
+                }
506
+                if (type.equals("SubScribeOff")) {
507
+                    //通知其他监控
508
+                    if (agent != null) agent.setAgentState(agent.getAgentState());
509
+                }
510
+            } else {
511
+                EslCommon.actionTempList.put(agent.getAgent(), aa);
512
+            }
513
+        } catch (Exception e) {
514
+            log.error(agentId + "|" + message + " 处理失败", e);
515
+        }
516
+    }
517
+
518
+    //判断目标坐席是否通话中
519
+    private String checkTargetAgentTalk(Agent agent) {
520
+        String result = "";
521
+        if (agent == null) {
522
+            result = "目标坐席未签入";
523
+        } else if (agent.getAgentState() != EslAgentEnum.talking.ordinal()) {
524
+            result = "目标坐席未通话";
525
+        }
526
+        return result;
527
+    }
528
+
529
+    /**
530
+     * 发送错误时的处理
531
+     *
532
+     * @param error
533
+     */
534
+    @OnError
535
+    public void onError(Throwable error) {
536
+        try {
537
+            Agent a = EslCommon.getAgent(agentId);
538
+            if (a != null) {
539
+                if (a.getAgentState() != EslAgentEnum.logout.ordinal()) {
540
+                    a.setAgentState(EslAgentEnum.logout.ordinal());
541
+                }
542
+                eslClientService.logout(a.getAgent(), a.getGroup(), "");
543
+                EslCommon.agents.remove(a);
544
+                sessionPool.remove(agentId);
545
+            }
546
+            subScribeSessionPool.remove(session);
547
+        } catch (Exception e) {
548
+            log.error("error错误", e);
549
+        }
550
+    }
551
+
552
+    //给坐席发送消息
553
+    public void sendMessage(String agentId, String message) {
554
+        Session s = sessionPool.get(agentId);
555
+        if (s != null) sendText(s, message);
556
+    }
557
+
558
+    //给所有坐席发送消息
559
+    public void sendMessageAll(String message) {
560
+        for (Session s : sessionPool.values()) {
561
+            sendText(s,message);
562
+        }
563
+    }
564
+
565
+    //给坐席组发送消息
566
+    public void sendMessageGroupAll(String group,String message) {
567
+        List<Agent> agents = EslCommon.agents.stream().filter(p -> p.getGroup().equals(group)).collect(Collectors.toList());
568
+        for (Agent a : agents) {
569
+            Session s = sessionPool.get(a.getAgent());
570
+            if (s != null) sendText(s, message);
571
+        }
572
+    }
573
+
574
+    //给所有监控发送消息
575
+    public void sendMessageSubScribe(String message) {
576
+        for (Session s : subScribeSessionPool) {
577
+            sendText(s,message);
578
+        }
579
+    }
580
+
581
+    //发送消息处理
582
+    private void sendText(Session s,String msg){
583
+        if (s != null && s.isOpen()) {
584
+            synchronized (s) {
585
+                try {
586
+                    s.getBasicRemote().sendText(msg);
587
+                } catch (IOException e) {
588
+                    log.error(msg+" 发送失败",e);
589
+                    if(e.getMessage().contains("close")) {
590
+                        try {
591
+                            s.close();
592
+                        } catch (IOException ex) {
593
+                            log.error(msg + " 关闭失败", ex);
594
+                        }
595
+                    }
596
+                }
597
+            }
598
+        }
599
+    }
600
+}

+ 19 - 0
midware-service/src/main/java/midware/service/quartz/job/AuthJob.java

@@ -0,0 +1,19 @@
1
+package midware.service.quartz.job;
2
+
3
+import lombok.extern.slf4j.Slf4j;
4
+import midware.service.eslclient.EslCommon;
5
+import midware.service.quartz.util.QuartzJob;
6
+import org.quartz.JobExecutionContext;
7
+
8
+//批量插入数据库
9
+@Slf4j
10
+public class AuthJob extends QuartzJob {
11
+    public AuthJob() {
12
+        cron = "0 0/1 * * * ?";
13
+    }
14
+
15
+    @Override
16
+    protected void doExecute(JobExecutionContext context) {
17
+        EslCommon.checkAuth();
18
+    }
19
+}

+ 50 - 0
midware-service/src/main/java/midware/service/quartz/job/BatchInsertJob.java

@@ -0,0 +1,50 @@
1
+package midware.service.quartz.job;
2
+
3
+import com.alibaba.fastjson2.JSON;
4
+import midware.entity.database.rep.*;
5
+import midware.service.eslclient.EslCommon;
6
+import midware.service.quartz.util.QuartzJob;
7
+import midware.service.rep.*;
8
+import midware.util.helper.SpringHelper;
9
+import org.quartz.JobExecutionContext;
10
+
11
+import java.util.ArrayList;
12
+import java.util.List;
13
+
14
+//批量插入数据库
15
+public class BatchInsertJob extends QuartzJob {
16
+    public BatchInsertJob() {
17
+        cron = "0 0/1 * * * ?";
18
+    }
19
+    @Override
20
+    protected void doExecute(JobExecutionContext context)
21
+    {
22
+        if(EslCommon.actions.size()>0) {
23
+            List<AgentAction> actions;
24
+            synchronized (EslCommon.actions) {
25
+                actions = JSON.parseArray(JSON.toJSONString(EslCommon.actions), AgentAction.class);
26
+                EslCommon.actions = new ArrayList<>();
27
+            }
28
+
29
+            SpringHelper.getBean(IAgentActionService.class).insert(actions);
30
+        }
31
+
32
+        if(EslCommon.states.size()>0) {
33
+            List<AgentState> states;
34
+            synchronized (EslCommon.states) {
35
+                states = JSON.parseArray(JSON.toJSONString(EslCommon.states), AgentState.class);
36
+                EslCommon.states = new ArrayList<>();
37
+            }
38
+            SpringHelper.getBean(IAgentStateService.class).insert(states);
39
+        }
40
+
41
+        if(EslCommon.events.size()>0) {
42
+            List<ChanEvent> events;
43
+            synchronized (EslCommon.events) {
44
+                events = JSON.parseArray(JSON.toJSONString(EslCommon.events), ChanEvent.class);
45
+                EslCommon.events = new ArrayList<>();
46
+            }
47
+            SpringHelper.getBean(IChanEventService.class).insert(events);
48
+        }
49
+    }
50
+}

+ 28 - 0
midware-service/src/main/java/midware/service/quartz/job/WsHeartJob.java

@@ -0,0 +1,28 @@
1
+package midware.service.quartz.job;
2
+
3
+import com.alibaba.fastjson2.JSON;
4
+import lombok.extern.slf4j.Slf4j;
5
+import midware.service.init.WebSocketService;
6
+import midware.service.quartz.util.QuartzJob;
7
+import midware.util.helper.SpringHelper;
8
+import org.quartz.JobExecutionContext;
9
+
10
+import java.util.HashMap;
11
+import java.util.Map;
12
+
13
+//ws心跳
14
+@Slf4j
15
+public class WsHeartJob extends QuartzJob {
16
+    public WsHeartJob() {
17
+        cron = "0/30 * * * * ?";
18
+    }
19
+
20
+    @Override
21
+    protected void doExecute(JobExecutionContext context) {
22
+        WebSocketService webSocketService = SpringHelper.getBean(WebSocketService.class);
23
+        Map<String, Object> result = new HashMap<>();
24
+        result.put("Type", "Heart");
25
+        result.put("Result", true);
26
+        webSocketService.sendMessageAll(JSON.toJSONString(result) );
27
+    }
28
+}

+ 52 - 0
midware-service/src/main/java/midware/service/quartz/util/QuartzHelper.java

@@ -0,0 +1,52 @@
1
+package midware.service.quartz.util;
2
+
3
+import lombok.extern.slf4j.Slf4j;
4
+import org.quartz.*;
5
+
6
+@Slf4j
7
+public class QuartzHelper {
8
+    /**
9
+     * 创建定时任务
10
+     */
11
+    public static void createScheduleJob(Scheduler scheduler, QuartzJob job) {
12
+        Class<? extends Job> jobClass = job.getClass();
13
+        String name=jobClass.getName();
14
+        try {
15
+            // 构建job信息
16
+            JobKey jobKey = JobKey.jobKey("job_" + name, "jobgroup_" + name);
17
+            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobKey).build();
18
+            TriggerKey triggerKey = TriggerKey.triggerKey("trigger_" + name, "triggergroup_" + name);
19
+
20
+            // 表达式调度构建器
21
+            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCron());
22
+//        //失败后策略
23
+//        switch (job.getMisfirePolicy())
24
+//        {
25
+//            case "1"://立即执行
26
+//                 cronScheduleBuilder.withMisfireHandlingInstructionIgnoreMisfires();
27
+//            case "2"://执行一次
28
+//                 cronScheduleBuilder.withMisfireHandlingInstructionFireAndProceed();
29
+//            case "3"://放弃执行
30
+//                 cronScheduleBuilder.withMisfireHandlingInstructionDoNothing();
31
+//        }
32
+
33
+            // 按新的cronExpression表达式构建一个新的trigger
34
+            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
35
+
36
+            // 放入参数,运行时的方法可以获取
37
+            jobDetail.getJobDataMap().put("jobname", name);
38
+
39
+            // 判断是否存在
40
+            if (scheduler.checkExists(jobKey)) {
41
+                // 防止创建时存在数据问题 先移除,然后在执行创建操作
42
+                scheduler.deleteJob(jobKey);
43
+            }
44
+
45
+            // 执行调度任务
46
+            scheduler.scheduleJob(jobDetail, trigger);
47
+
48
+        } catch (Exception ex) {
49
+            log.error(name + "-创建定时任务失败", ex);
50
+        }
51
+    }
52
+}

+ 31 - 0
midware-service/src/main/java/midware/service/quartz/util/QuartzJob.java

@@ -0,0 +1,31 @@
1
+package midware.service.quartz.util;
2
+
3
+import lombok.Data;
4
+import lombok.extern.slf4j.Slf4j;
5
+import org.quartz.Job;
6
+import org.quartz.JobExecutionContext;
7
+
8
+@Slf4j
9
+@Data
10
+public abstract class QuartzJob implements Job {
11
+
12
+    public String cron;
13
+
14
+    @Override
15
+    public void execute(JobExecutionContext context) {
16
+        String name = context.getMergedJobDataMap().get("jobname").toString();
17
+        try {
18
+            doExecute(context);
19
+        } catch (Exception e) {
20
+            log.error(name + "-执行异常", e);
21
+        }
22
+    }
23
+
24
+    /**
25
+     * 执行方法,由子类重载
26
+     *
27
+     * @param context 工作执行上下文对象
28
+     * @throws Exception 执行过程中的异常
29
+     */
30
+    protected abstract void doExecute(JobExecutionContext context) ;
31
+}

+ 7 - 0
midware-service/src/main/java/midware/service/rep/IAgentActionService.java

@@ -0,0 +1,7 @@
1
+package midware.service.rep;
2
+
3
+import midware.entity.database.rep.AgentAction;
4
+import midware.service.IBaseService;
5
+
6
+public interface IAgentActionService extends IBaseService<AgentAction> {
7
+}

+ 7 - 0
midware-service/src/main/java/midware/service/rep/IAgentStateService.java

@@ -0,0 +1,7 @@
1
+package midware.service.rep;
2
+
3
+import midware.entity.database.rep.AgentState;
4
+import midware.service.IBaseService;
5
+
6
+public interface IAgentStateService extends IBaseService<AgentState> {
7
+}

+ 7 - 0
midware-service/src/main/java/midware/service/rep/IChanEventService.java

@@ -0,0 +1,7 @@
1
+package midware.service.rep;
2
+
3
+import midware.entity.database.rep.ChanEvent;
4
+import midware.service.IBaseService;
5
+
6
+public interface IChanEventService extends IBaseService<ChanEvent> {
7
+}

+ 8 - 0
midware-service/src/main/java/midware/service/rep/IConfigService.java

@@ -0,0 +1,8 @@
1
+package midware.service.rep;
2
+
3
+import midware.entity.database.rep.Config;
4
+import midware.service.IBaseService;
5
+
6
+public interface IConfigService extends IBaseService<Config> {
7
+    String getConfigValue(String code);
8
+}

+ 7 - 0
midware-service/src/main/java/midware/service/rep/IIvrService.java

@@ -0,0 +1,7 @@
1
+package midware.service.rep;
2
+
3
+import midware.entity.database.rep.Ivr;
4
+import midware.service.IBaseService;
5
+
6
+public interface IIvrService extends IBaseService<Ivr> {
7
+}

+ 7 - 0
midware-service/src/main/java/midware/service/rep/IRecordService.java

@@ -0,0 +1,7 @@
1
+package midware.service.rep;
2
+
3
+import midware.entity.database.rep.Record;
4
+import midware.service.IBaseService;
5
+
6
+public interface IRecordService extends IBaseService<Record> {
7
+}

+ 14 - 0
midware-service/src/main/java/midware/service/rep/impl/AgentActionServiceImpl.java

@@ -0,0 +1,14 @@
1
+package midware.service.rep.impl;
2
+
3
+import midware.entity.database.rep.AgentAction;
4
+import midware.mapper.rep.AgentActionMapper;
5
+import midware.service.rep.IAgentActionService;
6
+import midware.service.BaseServiceImpl;
7
+import org.springframework.stereotype.Service;
8
+import org.springframework.transaction.annotation.Transactional;
9
+
10
+@Transactional
11
+@Service
12
+public class AgentActionServiceImpl extends BaseServiceImpl<AgentActionMapper, AgentAction> implements IAgentActionService{
13
+    public AgentActionServiceImpl(){ super(false); }
14
+}

+ 14 - 0
midware-service/src/main/java/midware/service/rep/impl/AgentStateServiceImpl.java

@@ -0,0 +1,14 @@
1
+package midware.service.rep.impl;
2
+
3
+import midware.entity.database.rep.AgentState;
4
+import midware.mapper.rep.AgentStateMapper;
5
+import midware.service.rep.IAgentStateService;
6
+import midware.service.BaseServiceImpl;
7
+import org.springframework.stereotype.Service;
8
+import org.springframework.transaction.annotation.Transactional;
9
+
10
+@Transactional
11
+@Service
12
+public class AgentStateServiceImpl extends BaseServiceImpl<AgentStateMapper, AgentState> implements IAgentStateService{
13
+    public AgentStateServiceImpl(){ super(false); }
14
+}

+ 14 - 0
midware-service/src/main/java/midware/service/rep/impl/ChanEventServiceImpl.java

@@ -0,0 +1,14 @@
1
+package midware.service.rep.impl;
2
+
3
+import midware.entity.database.rep.ChanEvent;
4
+import midware.mapper.rep.ChanEventMapper;
5
+import midware.service.rep.IChanEventService;
6
+import midware.service.BaseServiceImpl;
7
+import org.springframework.stereotype.Service;
8
+import org.springframework.transaction.annotation.Transactional;
9
+
10
+@Transactional
11
+@Service
12
+public class ChanEventServiceImpl extends BaseServiceImpl<ChanEventMapper, ChanEvent> implements IChanEventService{
13
+    public ChanEventServiceImpl(){ super(false); }
14
+}

+ 27 - 0
midware-service/src/main/java/midware/service/rep/impl/ConfigServiceImpl.java

@@ -0,0 +1,27 @@
1
+package midware.service.rep.impl;
2
+
3
+import midware.entity.database.rep.Config;
4
+import midware.mapper.rep.ConfigMapper;
5
+import midware.service.rep.IConfigService;
6
+import midware.service.BaseServiceImpl;
7
+import org.springframework.stereotype.Service;
8
+import org.springframework.transaction.annotation.Transactional;
9
+
10
+import java.util.List;
11
+import java.util.stream.Collectors;
12
+
13
+@Transactional
14
+@Service
15
+public class ConfigServiceImpl extends BaseServiceImpl<ConfigMapper, Config> implements IConfigService{
16
+    public ConfigServiceImpl(){ super(true); }
17
+
18
+    @Override
19
+    public String getConfigValue(String code) {
20
+        List<Config> configs = getList().stream().filter(p->p.getCode().equals(code)).collect(Collectors.toList());
21
+        if (configs.size()>0) {
22
+            return configs.get(0).getValue();
23
+        } else {
24
+            return null;
25
+        }
26
+    }
27
+}

+ 287 - 0
midware-service/src/main/java/midware/service/rep/impl/IvrServiceImpl.java

@@ -0,0 +1,287 @@
1
+package midware.service.rep.impl;
2
+
3
+import midware.entity.database.rep.Ivr;
4
+import midware.entity.input.rep.IvrInput;
5
+import midware.entity.input.rep.Node;
6
+import midware.entity.input.rep.Path;
7
+import midware.mapper.rep.IvrMapper;
8
+import midware.service.BaseServiceImpl;
9
+import midware.service.rep.IIvrService;
10
+import midware.util.enums.IvrType;
11
+import midware.util.helper.StringHelper;
12
+import com.alibaba.fastjson2.JSON;
13
+import org.springframework.stereotype.Service;
14
+import org.springframework.transaction.annotation.Transactional;
15
+
16
+import java.util.ArrayList;
17
+import java.util.List;
18
+import java.util.Map;
19
+import java.util.stream.Collectors;
20
+
21
+@Transactional
22
+@Service
23
+public class IvrServiceImpl extends BaseServiceImpl<IvrMapper, Ivr> implements IIvrService{
24
+    public IvrServiceImpl(){ super(false); }
25
+
26
+    //新增
27
+    @Override
28
+    public boolean insert(Ivr entity) {
29
+        dealIvr(entity);
30
+        return this.save(entity);
31
+    }
32
+
33
+    //编辑
34
+    @Override
35
+    public boolean update(Ivr entity) {
36
+        dealIvr(entity);
37
+        return this.updateById(entity);
38
+    }
39
+
40
+    //拨号计划默认节点(分机互拨,外呼,转满意度,会议)
41
+    private final String contextDefault=""+
42
+            "        <context name=\"ForExten\">\n" +
43
+            "            <extension name=\"ExtenCallExten\">\n" +
44
+            "                <condition field=\"destination_number\" expression=\"^(1[0-9][0-9][0-9])$\">\n" +
45
+            "                    <action application=\"set\" data=\"hangup_after_bridge=false\"/>\n" +
46
+            "                    <action application=\"export\" data=\"dialed_extension=$1\"/>\n" +
47
+            "                    <action application=\"set\" data=\"ringback=${us-ring}\"/>\n" +
48
+            "                    <action application=\"set\" data=\"transfer_ringback=$${hold_music}\"/>\n" +
49
+            "                    <action application=\"set\" data=\"call_timeout=30\"/>\n" +
50
+            "                    <action application=\"set\" data=\"continue_on_fail=true\"/>\n" +
51
+            "                    <action application=\"hash\" data=\"insert/${domain_name}-call_return/${dialed_extension}/${caller_id_number}\"/>\n" +
52
+            "                    <action application=\"hash\" data=\"insert/${domain_name}-last_dial_ext/${dialed_extension}/${uuid}\"/>\n" +
53
+            "                    <action application=\"set\" data=\"called_party_callgroup=${user_data(${dialed_extension}@${domain_name} var callgroup)}\"/>\n" +
54
+            "                    <action application=\"hash\" data=\"insert/${domain_name}-last_dial_ext/${called_party_callgroup}/${uuid}\"/>\n" +
55
+            "                    <action application=\"hash\" data=\"insert/${domain_name}-last_dial_ext/global/${uuid}\"/>\n" +
56
+            "                    <action application=\"hash\" data=\"insert/${domain_name}-last_dial/${called_party_callgroup}/${uuid}\"/>\n" +
57
+            "                    <action application=\"bridge\" data=\"user/${dialed_extension}@${domain_name}\"/>\n" +
58
+            "                    <action application=\"answer\"/>\n" +
59
+            "                    <action application=\"sleep\" data=\"500\"/>\n" +
60
+            "                    <action application=\"hangup\" data=\"NORMAL_CLEARING\"/>\n" +
61
+            "                </condition>\n" +
62
+            "            </extension>\n" +
63
+            "            <extension name=\"ExtenCallTrunk\">\n" +
64
+            "                <condition field=\"destination_number\" expression=\"^9(.*)$\">\n" +
65
+            "                    <action application=\"set\" data=\"call_timeout=60\"/>\n" +
66
+            "                    <action application=\"set\" data=\"continue_on_fail=USER_BUSY,NO_ANSWER\"/>\n" +
67
+            "                    <action application=\"bridge\" data=\"sofia/gateway/hykj/$1\"/>\n" +
68
+            "                    <action application=\"hangup\" data=\"${originate_disposition}\"/>\n" +
69
+            "                    <action name=\"start_dtmf\"/>\n" +
70
+            "                </condition>\n" +
71
+            "            </extension>\n" +
72
+//            "            <extension name=\"turnmyd\">\n" +
73
+//            "                <condition field=\"destination_number\" expression=\"^(turnmyd)$\">\n" +
74
+//            "                    <action application=\"ivr\" data=\"myd\" />\n" +
75
+//            "                </condition>\n" +
76
+//            "            </extension>\n"+
77
+            "        </context>\n" +
78
+//            "        <context name=\"ExtenMeeting\">\n" +
79
+//            "            <extension name=\"ExtenMeeting\" >\n" +
80
+//            "                <condition field=\"destination_number\" expression=\"^(.*)$\">\n" +
81
+//            "                    <action application=\"conference\" data=\"$1@threeway\" />\n" +
82
+//            "                </condition>\n" +
83
+//            "            </extension>\n" +
84
+//            "        </context>\n"+
85
+            "        <context name=\"SaveMyd\">\n" +
86
+            "            <extension name=\"SaveMyd\" >\n" +
87
+            "                <condition field=\"destination_number\" expression=\"^(.*)$\">\n" +
88
+            "                    <action application=\"odbc_query\" inline=\"true\" data=\"call save_myd('$1','${uuid}')\"/>\n" +
89
+            "                    <action application=\"playback\" data=\"/home/wav/thankjoin.wav\"/>\n" +
90
+            "                    <action application=\"hangup\" />\n" +
91
+            "                </condition>\n" +
92
+            "            </extension>\n" +
93
+            "        </context>\n";
94
+
95
+    //菜单默认节点(满意度)
96
+    private final String menuDefault=""+
97
+            "                <menu name=\"myd\" greet-long=\"/home/wav/myd.mp3\" greet-short=\"/home/wav/myd.mp3\"" +
98
+            " invalid-sound=\"/home/wav/invalid.wav\" exit-sound=\"/home/wav/exit.wav\" confirm-macro=\"\" confirm-key=\"\"" +
99
+            " tts-engine=\"flite\" tts-voice=\"rms\" confirm-attempts=\"3\" timeout=\"10000\"" +
100
+            " inter-digit-timeout=\"2000\" max-failures=\"3\" max-timeouts=\"3\" digit-len=\"1\">\n" +
101
+            "                    <entry action=\"menu-exec-app\" digits=\"/^([1-3])$/\" param=\"transfer ${1} XML SaveMyd\"/>\n" +
102
+            "                </menu>\n";
103
+
104
+    //处理ivr
105
+    private void dealIvr(Ivr entity){
106
+        IvrInput ivrInput = JSON.parseObject(entity.getJson(), IvrInput.class);
107
+        //获取所有节点
108
+        List<Node> nodes = ivrInput.getNodes();
109
+        //获取所有路径
110
+        List<Path> paths = ivrInput.getPaths();
111
+        //获取开始节点
112
+        Node startNode = nodes.stream().filter(p -> p.getType().equals(IvrType.START)).findFirst().get();
113
+        //获取开始节点的路径
114
+        List<Path> startPaths = paths.stream().filter(p -> p.getFrom().equals(startNode.getId())).collect(Collectors.toList());
115
+        if (startPaths.size() > 0) {
116
+            Path path = startPaths.get(0);
117
+            Node toNode = nodes.stream().filter(p -> p.getId().equals(path.getTo())).findFirst().get();
118
+            List<Integer> ids = new ArrayList<>();
119
+            StringBuilder menuXml = new StringBuilder();
120
+            StringBuilder contextXml = getXml(ivrInput, toNode, ids, menuXml);
121
+
122
+            String cXml = "" +
123
+                    "<document type=\"freeswitch/xml\">\n" +
124
+                    "    <section name=\"dialplan\">\n" +
125
+                    contextDefault +
126
+                    "        <context name=\"public\">\n" +
127
+                    "            <extension name=\"public_1\">\n" +
128
+                    "                <condition field=\"destination_number\" expression=\"^(.*)$\">\n" +
129
+                    "                    <action application=\"sleep\" data=\"500\"/>\n" +
130
+                    "                    <action application=\"answer\"/>\n" +
131
+                    "                    <action application=\"set\" data=\"basenumber=$1\"/>\n" +
132
+                    "                    <action application=\"transfer\" data=\"$1 XML " + toNode.getName() + "\"/>\n" +
133
+                    "                </condition>\n" +
134
+                    "            </extension>\n" +
135
+                    "        </context>\n" +
136
+                    contextXml +
137
+                    "    </section>\n" +
138
+                    "</document>";
139
+            String mXml = "" +
140
+                    "<document type=\"freeswitch/xml\">\n" +
141
+                    "    <section name=\"configuration\">\n" +
142
+                    "        <configuration name=\"ivr.conf\" description=\"IVR menus\">\n" +
143
+                    "            <menus>\n" +
144
+                    menuXml +
145
+                    menuDefault +
146
+                    "            </menus>\n" +
147
+                    "        </configuration>\n" +
148
+                    "    </section>\n" +
149
+                    "</document>";
150
+            entity.setContext(cXml);
151
+            entity.setMenu(mXml);
152
+        }
153
+    }
154
+
155
+    //获取xml
156
+    private StringBuilder getXml(IvrInput input,Node currNode,List<Integer> ids,StringBuilder menuXml) {
157
+        //获取所有节点
158
+        List<Node> nodes = input.getNodes();
159
+        //获取所有路径
160
+        List<Path> paths = input.getPaths();
161
+
162
+        boolean isexist = ids.contains(currNode.getId());
163
+        if (!isexist) {
164
+            ids.add(currNode.getId());
165
+        }
166
+
167
+        StringBuilder xml = new StringBuilder();
168
+        StringBuilder nextXml = new StringBuilder();
169
+        Map<String, Object> data = currNode.getAttr();
170
+        //获取节点的路径
171
+        List<Path> nodePaths = paths.stream().filter(p -> p.getFrom().equals(currNode.getId())).collect(Collectors.toList());
172
+        paths.removeAll(nodePaths);
173
+        //放音收号节点
174
+        if (currNode.getType().equals(IvrType.AUDIODTMF)) {
175
+            StringBuilder mxml = new StringBuilder("                <menu name=\"" + currNode.getName() + "\" ");
176
+            for (Map.Entry<String, Object> entry : data.entrySet()) {
177
+                mxml.append(entry.getKey()).append("=\"").append(entry.getValue().toString()).append("\" ");
178
+            }
179
+            mxml.append(">\n");
180
+            for (Path path : nodePaths) {
181
+                Node toNode = nodes.stream().filter(p -> p.getId().equals(path.getTo())).findFirst().get();
182
+                if (toNode.getType().equals(IvrType.AUDIODTMF)) {
183
+                    mxml.append("                    <entry action=\"menu-sub\" digits=\"").append(path.getExpression()).append("\" param=\"").append(toNode.getName()).append("\"/>\n");
184
+                } else {
185
+                    mxml.append("                    <entry action=\"menu-exec-app\" digits=\"").append(path.getExpression()).append("\" param=\"transfer ").append(path.getExpression()).append(" XML ").append(toNode.getName()).append("\"/>\n");
186
+                }
187
+                nextXml.append(getXml(input, toNode, ids, menuXml));
188
+            }
189
+            mxml.append("                </menu>\n");
190
+            menuXml.append(mxml);
191
+        }
192
+        //分支节点
193
+        else if (currNode.getType().equals(IvrType.BRANCH)) {
194
+            xml = new StringBuilder("        <context name=\"" + currNode.getName() + "\">\n");
195
+
196
+            int i = 1;
197
+            for (Path path : nodePaths) {
198
+                xml.append("            <extension name=\"").append(currNode.getName()).append("_").append(i).append("\" >\n");
199
+                if (StringHelper.isNotEmpty(path.getField())) {
200
+                    xml.append("                <condition field=\"").append(path.getField()).append("\" expression=\"").append(path.getExpression()).append("\">\n");
201
+                } else if (StringHelper.isNotEmpty(path.getExpression())) {
202
+                    xml.append("                <condition field=\"destination_number\" expression=\"").append(path.getExpression()).append("\">\n");
203
+                } else {
204
+                    xml.append("                <condition>\n");
205
+                }
206
+                Node toNode = nodes.stream().filter(p -> p.getId().equals(path.getTo())).findFirst().get();
207
+                if (toNode.getType().equals(IvrType.AUDIODTMF)) {
208
+                    xml.append("                    <action application=\"ivr\" data=\"").append(toNode.getName()).append("\"/>\n");
209
+                } else {
210
+                    xml.append("                    <action application=\"transfer\" data=\"${destination_number} XML ").append(toNode.getName()).append("\"/>\n");
211
+                }
212
+                xml.append("                </condition>\n");
213
+                xml.append("            </extension>\n");
214
+                nextXml.append(getXml(input, toNode, ids, menuXml));
215
+                i++;
216
+            }
217
+            xml.append("        </context>\n");
218
+        }
219
+        //其他类型节点
220
+        else {
221
+            xml = new StringBuilder();
222
+            xml.append("        <context name=\"").append(currNode.getName()).append("\">\n");
223
+            xml.append("            <extension name=\"").append(currNode.getName()).append("_1\">\n");
224
+            xml.append("                <condition>\n");
225
+
226
+            switch (currNode.getType()) {
227
+                case DEFINEVAR:
228
+                    for (Map.Entry<String, Object> entry : data.entrySet()) {
229
+                        xml.append("                    <action application=\"set\" data=\"").append(entry.getKey()).append("=").append(entry.getValue().toString()).append("\"/>\n");
230
+                    }
231
+                    break;
232
+                case SQL:
233
+                    xml.append("                    <action application=\"odbc_query\" data=\"").append(data.get("sql").toString()).append("\"/>\n");
234
+                    break;
235
+                case AUDIO:
236
+                    xml.append("                    <action application=\"playback\" data=\"").append(data.get("path").toString()).append("\"/>\n");
237
+                    break;
238
+                case QUEUE:
239
+                    xml.append("                    <action application=\"set\" data=\"hangup_after_bridge=true\"/>\n");
240
+                    xml.append("                    <action application=\"sleep\" data=\"500\"/>\n");
241
+                    xml.append("                    <action application=\"set\" data=\"continue_on_fail=true\"/>\n");
242
+                    xml.append("                    <action application=\"callcenter\" data=\"${group}\"/>\n");
243
+                    break;
244
+                case LEAVEWORD:
245
+                    xml.append("                    <action application=\"playback\" data=\"/home/wav/leaveword.wav\"/>\n");
246
+                    xml.append("                    <action application=\"set\" data=\"RECORD_TITLE=Recording ${destination_number} ${caller_id_number} ${strftime(%Y-%m-%d %H:%M)}\"/>\n");
247
+                    xml.append("                    <action application=\"set\" data=\"record_path=files/liuyan/${strftime(%Y%m%d)}\"/>\n");
248
+                    xml.append("                    <action application=\"mkdir\" data=\"$${md_base_dir}/${record_path}\"/>\n");
249
+                    xml.append("                    <action application=\"set\" data=\"record_path=${record_path}/${uuid}.wav\"/>\n");
250
+                    xml.append("                    <action application=\"odbc_query\" data=\"update rep_record set op_type=‘LeaveWord’,leave_time=now(),leave_path='${record_path}' where uuid = '${uuid}'\"/>\n");
251
+                    xml.append("                    <action application=\"record\" data=\"$${md_base_dir}/${record_path}\"/>\n");
252
+                    break;
253
+                case TRANSFEROUT:
254
+                    xml.append("                    <action application=\"set\" data=\"call_timeout=60\"/>\n");
255
+                    xml.append("                    <action application=\"set\" data=\"continue_on_fail=USER_BUSY,NO_ANSWER\"/>\n");
256
+                    xml.append("                    <action application=\"odbc_query\" inline=\"true\" data=\"update rep_record set op_type=1 where uuid = '${uuid}'\"/>\n");
257
+                    xml.append("                    <action application=\"bridge\" data=\"sofia/gateway/hykj/${phone}\"/>\n");
258
+                    xml.append("                    <action application=\"hangup\"/>\n");
259
+                    break;
260
+                case HANGUP:
261
+                    xml.append("                    <action application=\"hangup\"/>\n");
262
+                    break;
263
+            }
264
+
265
+            if (nodePaths.size() > 0) {
266
+                Path path = nodePaths.get(0);
267
+                Node toNode = nodes.stream().filter(p -> p.getId().equals(path.getTo())).findFirst().get();
268
+                if (toNode.getType().equals(IvrType.AUDIODTMF)) {
269
+                    xml.append("                    <action application=\"ivr\" data=\"").append(toNode.getName()).append("\"/>\n");
270
+                } else {
271
+                    xml.append("                    <action application=\"transfer\" data=\"${destination_number} XML ").append(toNode.getName()).append("\"/>\n");
272
+                }
273
+                nextXml.append(getXml(input, toNode, ids, menuXml));
274
+            }
275
+            xml.append("                </condition>\n");
276
+            xml.append("            </extension>\n");
277
+            xml.append("        </context>\n");
278
+        }
279
+
280
+        if (isexist) {
281
+            return nextXml;
282
+        } else {
283
+            xml.append(nextXml);
284
+            return xml;
285
+        }
286
+    }
287
+}

+ 14 - 0
midware-service/src/main/java/midware/service/rep/impl/RecordServiceImpl.java

@@ -0,0 +1,14 @@
1
+package midware.service.rep.impl;
2
+
3
+import midware.entity.database.rep.Record;
4
+import midware.mapper.rep.RecordMapper;
5
+import midware.service.rep.IRecordService;
6
+import midware.service.BaseServiceImpl;
7
+import org.springframework.stereotype.Service;
8
+import org.springframework.transaction.annotation.Transactional;
9
+
10
+@Transactional
11
+@Service
12
+public class RecordServiceImpl extends BaseServiceImpl<RecordMapper, Record> implements IRecordService{
13
+    public RecordServiceImpl(){ super(false); }
14
+}

+ 65 - 0
midware-util/pom.xml

@@ -0,0 +1,65 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <modelVersion>4.0.0</modelVersion>
6
+    <parent>
7
+        <groupId>midware</groupId>
8
+        <artifactId>midware-base</artifactId>
9
+        <version>1.0.0</version>
10
+    </parent>
11
+
12
+    <artifactId>midware-util</artifactId>
13
+
14
+    <properties>
15
+        <maven.compiler.source>8</maven.compiler.source>
16
+        <maven.compiler.target>8</maven.compiler.target>
17
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18
+    </properties>
19
+
20
+    <dependencies>
21
+        <!-- SpringBoot Web容器 -->
22
+        <dependency>
23
+            <groupId>org.springframework.boot</groupId>
24
+            <artifactId>spring-boot-starter-web</artifactId>
25
+        </dependency>
26
+        <!-- SpringBoot redis -->
27
+        <dependency>
28
+            <groupId>org.springframework.boot</groupId>
29
+            <artifactId>spring-boot-starter-data-redis</artifactId>
30
+        </dependency>
31
+
32
+        <!-- httpclient依赖 -->
33
+        <dependency>
34
+            <groupId>org.apache.httpcomponents</groupId>
35
+            <artifactId>httpclient</artifactId>
36
+            <version>4.5.2</version>
37
+        </dependency>
38
+
39
+        <!-- 定时任务 -->
40
+        <dependency>
41
+            <groupId>org.quartz-scheduler</groupId>
42
+            <artifactId>quartz</artifactId>
43
+            <exclusions>
44
+                <exclusion>
45
+                    <groupId>com.mchange</groupId>
46
+                    <artifactId>c3p0</artifactId>
47
+                </exclusion>
48
+            </exclusions>
49
+        </dependency>
50
+        <!-- websocket -->
51
+        <dependency>
52
+            <groupId>org.springframework.boot</groupId>
53
+            <artifactId>spring-boot-starter-websocket</artifactId>
54
+        </dependency>
55
+        <!-- freeswitch-esl -->
56
+        <dependency>
57
+            <groupId>org.freeswitch.esl.client</groupId>
58
+            <artifactId>org.freeswitch.esl.client</artifactId>
59
+            <version>0.9.2</version>
60
+        </dependency>
61
+
62
+
63
+    </dependencies>
64
+
65
+</project>

+ 58 - 0
midware-util/src/main/java/midware/util/config/CommonConfig.java

@@ -0,0 +1,58 @@
1
+package midware.util.config;
2
+
3
+import lombok.Data;
4
+import org.springframework.beans.factory.annotation.Value;
5
+import org.springframework.context.annotation.Configuration;
6
+
7
+@Data
8
+@Configuration
9
+public class CommonConfig {
10
+    public static String tts_type;
11
+    @Value("${common.tts.type}")
12
+    private void setTtsType(String ttsType) {
13
+        CommonConfig.tts_type = ttsType;
14
+    }
15
+
16
+    public static String tts_url;
17
+    @Value("${common.tts.url}")
18
+    private void setTtsUrl(String ttsUrl) {
19
+        CommonConfig.tts_url = ttsUrl;
20
+    }
21
+
22
+
23
+    public static String ai_llm;
24
+    @Value("${common.ai.llm}")
25
+    private void setAiLlm(String aiLlm) {
26
+        CommonConfig.ai_llm = aiLlm;
27
+    }
28
+
29
+    public static String ai_zsk;
30
+    @Value("${common.ai.zsk}")
31
+    private void setAiZsk(String aiZsk) {
32
+        CommonConfig.ai_zsk = aiZsk;
33
+    }
34
+
35
+    public static String ai_sjk;
36
+    @Value("${common.ai.sjk}")
37
+    private void setAiSjk(String aiSjk) {
38
+        CommonConfig.ai_sjk = aiSjk;
39
+    }
40
+
41
+    public static String ai_es;
42
+    @Value("${common.ai.es}")
43
+    private void setAiEs(String aiEs) {
44
+        CommonConfig.ai_es = aiEs;
45
+    }
46
+
47
+    public static String funasr;
48
+    @Value("${common.funasr}")
49
+    private void setFunasr(String funasr) {
50
+        CommonConfig.funasr = funasr;
51
+    }
52
+
53
+    public static String asr;
54
+    @Value("${common.asr}")
55
+    private void setAsr(String asr) {
56
+        CommonConfig.asr = asr;
57
+    }
58
+}

+ 43 - 0
midware-util/src/main/java/midware/util/config/EslClientConfig.java

@@ -0,0 +1,43 @@
1
+package midware.util.config;
2
+
3
+import lombok.Data;
4
+import lombok.extern.slf4j.Slf4j;
5
+import midware.util.enums.EslEventEnum;
6
+import midware.util.helper.StringHelper;
7
+import org.freeswitch.esl.client.inbound.Client;
8
+import org.springframework.beans.factory.annotation.Value;
9
+import org.springframework.context.annotation.Bean;
10
+import org.springframework.context.annotation.Configuration;
11
+
12
+import java.util.stream.Stream;
13
+
14
+@Data
15
+@Slf4j
16
+@Configuration
17
+public class EslClientConfig {
18
+    @Value("${spring.freeswitch.host}")
19
+    private String host;
20
+    @Value("${spring.freeswitch.port}")
21
+    private Integer port;
22
+    @Value("${spring.freeswitch.password}")
23
+    private String password;
24
+    @Value("${spring.freeswitch.timeout}")
25
+    private int timeout;
26
+
27
+    @Bean
28
+    public Client client() {
29
+        Client client = new Client();
30
+        try {
31
+            client.connect(host, port, password, timeout);
32
+            Thread.sleep(500);
33
+            client.setEventSubscriptions("plain", "all");
34
+            Stream.of(EslEventEnum.values()).filter(s -> StringHelper.isEmpty(s.getSubclass()))
35
+                    .map(Enum::name).forEach(s -> client.addEventFilter("Event-Name", s));
36
+            Stream.of(EslEventEnum.values()).filter(s -> StringHelper.isNotEmpty(s.getSubclass()))
37
+                    .map(EslEventEnum::getSubclass).forEach(s -> client.addEventFilter("Event-Subclass", s));
38
+        } catch (Exception e) {
39
+            log.error("fs connect Exception",e);
40
+        }
41
+        return client;
42
+    }
43
+}

+ 36 - 0
midware-util/src/main/java/midware/util/config/MybatisPlusConfig.java

@@ -0,0 +1,36 @@
1
+package midware.util.config;
2
+
3
+import com.baomidou.mybatisplus.annotation.DbType;
4
+import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
5
+import com.baomidou.mybatisplus.extension.MybatisMapWrapperFactory;
6
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
7
+import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
8
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
9
+import org.springframework.context.annotation.Bean;
10
+import org.springframework.context.annotation.Configuration;
11
+
12
+@Configuration
13
+public class MybatisPlusConfig {
14
+
15
+    /**
16
+     * 插件配置
17
+     *
18
+     * @return
19
+     */
20
+    @Bean
21
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
22
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
23
+
24
+        // 向Mybatis-Plus的过滤器链中添加分页拦截器,需要设置数据库类型(主要用于分页方言)
25
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
26
+        // 添加乐观锁拦截器
27
+        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
28
+        return interceptor;
29
+    }
30
+
31
+    //listMaps、getMap等 方法获取数据后,下划线未转驼峰问题
32
+    @Bean
33
+    public ConfigurationCustomizer configurationCustomizer() {
34
+        return i -> i.setObjectWrapperFactory(new MybatisMapWrapperFactory());
35
+    }
36
+}

+ 62 - 0
midware-util/src/main/java/midware/util/config/ThreadPoolConfig.java

@@ -0,0 +1,62 @@
1
+package midware.util.config;
2
+
3
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
4
+import org.springframework.context.annotation.Bean;
5
+import org.springframework.context.annotation.Configuration;
6
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
7
+
8
+import java.util.concurrent.ScheduledExecutorService;
9
+import java.util.concurrent.ScheduledThreadPoolExecutor;
10
+import java.util.concurrent.ThreadPoolExecutor;
11
+
12
+/**
13
+ * 线程池配置
14
+ *
15
+ * @author jiayi
16
+ **/
17
+@Configuration
18
+public class ThreadPoolConfig
19
+{
20
+    // 核心线程池大小
21
+    private int corePoolSize = 50;
22
+
23
+    // 最大可创建的线程数
24
+    private int maxPoolSize = 200;
25
+
26
+    // 队列最大长度
27
+    private int queueCapacity = 1000;
28
+
29
+    // 线程池维护线程所允许的空闲时间
30
+    private int keepAliveSeconds = 300;
31
+
32
+    @Bean(name = "threadPoolTaskExecutor")
33
+    public ThreadPoolTaskExecutor threadPoolTaskExecutor()
34
+    {
35
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
36
+        executor.setMaxPoolSize(maxPoolSize);
37
+        executor.setCorePoolSize(corePoolSize);
38
+        executor.setQueueCapacity(queueCapacity);
39
+        executor.setKeepAliveSeconds(keepAliveSeconds);
40
+        // 线程池对拒绝任务(无线程可用)的处理策略
41
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
42
+        return executor;
43
+    }
44
+
45
+    /**
46
+     * 执行周期性或定时任务
47
+     */
48
+    @Bean(name = "scheduledExecutorService")
49
+    protected ScheduledExecutorService scheduledExecutorService()
50
+    {
51
+        return new ScheduledThreadPoolExecutor(corePoolSize,
52
+                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
53
+                new ThreadPoolExecutor.CallerRunsPolicy())
54
+        {
55
+            @Override
56
+            protected void afterExecute(Runnable r, Throwable t)
57
+            {
58
+                super.afterExecute(r, t);
59
+            }
60
+        };
61
+    }
62
+}

+ 17 - 0
midware-util/src/main/java/midware/util/config/WebSocketConfig.java

@@ -0,0 +1,17 @@
1
+package midware.util.config;
2
+
3
+import org.springframework.context.annotation.Bean;
4
+import org.springframework.context.annotation.Configuration;
5
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
6
+
7
+@Configuration
8
+public class WebSocketConfig {
9
+    /**
10
+     * 	注入ServerEndpointExporter,
11
+     * 	这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
12
+     */
13
+    @Bean
14
+    public ServerEndpointExporter serverEndpointExporter() {
15
+        return new ServerEndpointExporter();
16
+    }
17
+}

+ 18 - 0
midware-util/src/main/java/midware/util/enums/EslAgentEnum.java

@@ -0,0 +1,18 @@
1
+package midware.util.enums;
2
+
3
+public enum EslAgentEnum {
4
+    unkown("未知"),
5
+    loging("登录中"),
6
+    free("空闲"),
7
+    talking("通话中"),
8
+    aftertalk("话后处理"),
9
+    busy("忙碌"),
10
+    requested("被请求"),
11
+    logout("注销"),
12
+    ;
13
+
14
+    private String description;
15
+    EslAgentEnum(String description) {
16
+        this.description = description;
17
+    }
18
+}

+ 72 - 0
midware-util/src/main/java/midware/util/enums/EslCommandEnum.java

@@ -0,0 +1,72 @@
1
+package midware.util.enums;
2
+
3
+public enum EslCommandEnum {
4
+    //acl <ip> <list_name>
5
+    acl("比较IP地址是否与有访问控制列表匹配。"),
6
+    //alias [add|stickyadd] <alias> <command> | del [<alias>|*]
7
+    //参数说明:
8
+    //add:添加别名
9
+    //  alias:别名
10
+    //  command:命令
11
+    //stickyadd:添加别名,重启后仍然有效,参数与add相同
12
+    //del:删除别名
13
+    //  alias:别名
14
+    //  *:删除所有别名
15
+    alias("设置别名"),
16
+    domain_exists("检查一个FreeSWITCH域是否存在"),
17
+    eval("在呼叫会话期间查看通道变量"),
18
+
19
+    // expand bgapi originate sofia/internal/1001%${domain} 9999  -> bgapi originate sofia/internal/1001%192.168.1.1 9999
20
+    expand("有变量的呼叫串最前面加上expand 会先赋值变量然后执行  加到 bgapi前面"),
21
+    fsctl("发送控制消息到FreeSWITCH."),
22
+    global_getvar("获取全局变量的值。如果未提供参数,则它将获取所有全局变量。"),
23
+    global_setvar("global_setvar <变量名> = <值>"),
24
+    //group_call group@domain[+F|+A|+E]
25
+    group_call("返回组呼bridge字符串"),
26
+    create_uuid("创建一个新的UUID并将其作为字符串返回。"),
27
+
28
+    originate("发起一个呼叫"),
29
+    //pause <uuid> <on|off>
30
+    pause("暂停媒体播放"),
31
+    uuid_answer("应答该UUID的通话"),
32
+    //uuid_audio <uuid> [start [read|write] [mute|level <level>]|stop]
33
+    //注:level的值范围从-4到4,默认值为0。
34
+    uuid_audio("调整信道上面的音量"),
35
+    //uuid_break <uuid> [all]
36
+    //注:如果使用all标记的话,所有信道上面正在排队等待播放的音频文件都会被移除,但是如果没有all标记的话,只有当前正在播放的音频文件会被断开。
37
+    uuid_break("断开发送至指定信道的媒体流。"),
38
+    //uuid_bridge <uuid> <other_uuid>
39
+    //注:至少需要有一条腿是被呼通的。
40
+    uuid_bridge("桥接两条呼叫的腿。"),
41
+    //uuid_broadcast <uuid> <path> [aleg|bleg|both]
42
+    uuid_broadcast("在一个指定UUID的信道上执行任意一个拨号方案程序。"),
43
+    uuid_buglist("列出信道上面的媒体bug(media bugs)"),
44
+    //uuid_chat <uuid> <text>
45
+    //注:如果和会话(session,由uuid指定)相关的终端有一个receive_event handler,该消息会被发往终端,并以及时消息的形式显示出来。
46
+    uuid_chat("发送聊天信息"),
47
+    uuid_exists("检查给定的uuid是否存在。"),
48
+    //uuid_hold <uuid>           保持通话
49
+    //uuid_hold off <uuid>       结束保持,恢复正常通话
50
+    //uuid_hold toggle <uuid>    在保持和取消保持间切换
51
+    uuid_hold("保持通话"),
52
+    //uuid_kill <uuid> [cause]
53
+    uuid_kill("重置(杀掉)指定的信道"),
54
+    uuid_park(""),
55
+    //uuid_record <uuid> [start|stop|mask|unmask] <path> [<limit>]
56
+    uuid_record("将与具有给定UUID的频道相关联的音频记录到文件中 "),
57
+    //uuid_transfer <uuid> [-bleg|-both] <dest-exten> [<dialplan>] [<context>]
58
+    uuid_transfer("将现有呼叫转移到和中的特定分机。拨号计划可以是“xml”或“directory”。"),
59
+
60
+    uuid_audio_stream("asr"),
61
+
62
+    callcenter_config("配置"),
63
+    uuid_send_dtmf("按键"),
64
+    conference("会议"),
65
+    sched_broadcast("预定广播"),
66
+    ;
67
+
68
+    private String description;
69
+    EslCommandEnum(String description) {
70
+        this.description = description;
71
+    }
72
+}

+ 71 - 0
midware-util/src/main/java/midware/util/enums/EslEventEnum.java

@@ -0,0 +1,71 @@
1
+package midware.util.enums;
2
+
3
+public enum EslEventEnum {
4
+    CHANNEL_CREATE("创建"),
5
+    //CHANNEL_BRIDGE("转接"),
6
+    CHANNEL_PROGRESS("进度"),
7
+    CHANNEL_PROGRESS_MEDIA("媒体进度"),
8
+    CHANNEL_ANSWER("接听"),
9
+    CHANNEL_BRIDGE("桥接"),
10
+    CHANNEL_HANGUP_COMPLETE("挂机完成"),
11
+    CHANNEL_HOLD("保持"),
12
+    CHANNEL_UNHOLD("接回"),
13
+    CHANNEL_EXECUTE_COMPLETE("执行完成"),
14
+    DTMF("按键"),
15
+    DETECTED_SPEECH("语音识别"),
16
+    BACKGROUND_JOB("后台任务"),
17
+
18
+    sofia_register("分机上线","sofia::register","custom"),
19
+    sofia_unregister("分机下线","sofia::unregister","custom"),
20
+
21
+    callcenter_info("呼叫信息","callcenter::info","custom"),
22
+
23
+    conference_maintenance("会议","conference::maintenance","custom"),
24
+
25
+    mod_funasr_json("识别结果","mod_funasr::json","custom"),
26
+    ;
27
+
28
+
29
+    //事件描述
30
+    private String description;
31
+    //自定义事件
32
+    private String subclass;
33
+    private String type;
34
+
35
+    EslEventEnum() {
36
+    }
37
+
38
+    EslEventEnum(String description) {
39
+        this.description = description;
40
+    }
41
+
42
+    EslEventEnum(String description, String subclass, String type) {
43
+        this.description = description;
44
+        this.subclass = subclass;
45
+        this.type = type;
46
+    }
47
+
48
+    public String getDescription() {
49
+        return description;
50
+    }
51
+
52
+    public void setDescription(String description) {
53
+        this.description = description;
54
+    }
55
+
56
+    public String getSubclass() {
57
+        return subclass;
58
+    }
59
+
60
+    public void setSubclass(String subclass) {
61
+        this.subclass = subclass;
62
+    }
63
+
64
+    public String getType() {
65
+        return type;
66
+    }
67
+
68
+    public void setType(String type) {
69
+        this.type = type;
70
+    }
71
+}

+ 64 - 0
midware-util/src/main/java/midware/util/enums/IvrType.java

@@ -0,0 +1,64 @@
1
+package midware.util.enums;
2
+
3
+/**
4
+ * 业务操作类型
5
+ * 
6
+ * @author jiayi
7
+ */
8
+public enum IvrType
9
+{
10
+    /**
11
+     * 开始
12
+     */
13
+    START,
14
+
15
+    /**
16
+     * 定义变量
17
+     */
18
+    DEFINEVAR,
19
+
20
+    /**
21
+     * 执行sql
22
+     */
23
+    SQL,
24
+
25
+    /**
26
+     * 放音
27
+     */
28
+    AUDIO,
29
+
30
+    /**
31
+     * 放音收号
32
+     */
33
+    AUDIODTMF,
34
+
35
+    /**
36
+     * 分支
37
+     */
38
+    BRANCH,
39
+
40
+    /**
41
+     * 队列
42
+     */
43
+    QUEUE,
44
+
45
+    /**
46
+     * 排队
47
+     */
48
+    WAIT,
49
+
50
+    /**
51
+     * 呼叫转移
52
+     */
53
+    TRANSFEROUT,
54
+
55
+    /**
56
+     * 留言
57
+     */
58
+    LEAVEWORD,
59
+
60
+    /**
61
+     * 挂机
62
+     */
63
+    HANGUP
64
+}

+ 91 - 0
midware-util/src/main/java/midware/util/helper/AsyncHelper.java

@@ -0,0 +1,91 @@
1
+package midware.util.helper;
2
+
3
+import lombok.extern.slf4j.Slf4j;
4
+import org.springframework.stereotype.Component;
5
+
6
+import javax.annotation.PreDestroy;
7
+import java.util.TimerTask;
8
+import java.util.concurrent.ScheduledExecutorService;
9
+import java.util.concurrent.TimeUnit;
10
+
11
+/**
12
+ * 异步任务管理器
13
+ *
14
+ */
15
+
16
+@Slf4j
17
+@Component
18
+public class AsyncHelper
19
+{
20
+    /**
21
+     * 操作延迟毫秒
22
+     */
23
+    private final int OPERATE_DELAY_TIME = 0;
24
+
25
+    /**
26
+     * 异步操作任务调度线程池
27
+     */
28
+    private ScheduledExecutorService executor = SpringHelper.getBean("scheduledExecutorService");
29
+
30
+    /**
31
+     * 单例模式
32
+     */
33
+    private AsyncHelper(){}
34
+
35
+    private static AsyncHelper  instance = new AsyncHelper();
36
+
37
+    public static AsyncHelper  instance()
38
+    {
39
+        return  instance;
40
+    }
41
+
42
+    /**
43
+     * 执行任务
44
+     * 
45
+     * @param task 任务
46
+     */
47
+    public void execute(TimerTask task)
48
+    {
49
+        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
50
+    }
51
+
52
+    /**
53
+     * 停止任务线程池
54
+     */
55
+    public void shutdown()
56
+    {
57
+        if (executor != null && !executor.isShutdown())
58
+        {
59
+            executor.shutdown();
60
+            try
61
+            {
62
+                if (!executor.awaitTermination(120, TimeUnit.SECONDS))
63
+                {
64
+                    executor.shutdownNow();
65
+                    if (!executor.awaitTermination(120, TimeUnit.SECONDS))
66
+                    {
67
+                        log.info("Pool did not terminate");
68
+                    }
69
+                }
70
+            }
71
+            catch (InterruptedException ie)
72
+            {
73
+                executor.shutdownNow();
74
+                Thread.currentThread().interrupt();
75
+            }
76
+        }
77
+    }
78
+
79
+    @PreDestroy
80
+    public void destroy()
81
+    {
82
+        try
83
+        {
84
+            instance.shutdown();
85
+        }
86
+        catch (Exception e)
87
+        {
88
+            log.error(e.getMessage(), e);
89
+        }
90
+    }
91
+}

+ 322 - 0
midware-util/src/main/java/midware/util/helper/CodeHelper.java

@@ -0,0 +1,322 @@
1
+package midware.util.helper;
2
+
3
+import com.alibaba.fastjson2.JSON;
4
+import lombok.extern.slf4j.Slf4j;
5
+import org.springframework.stereotype.Component;
6
+
7
+import javax.servlet.ServletOutputStream;
8
+import javax.servlet.http.HttpServletResponse;
9
+import java.io.BufferedOutputStream;
10
+import java.io.ByteArrayOutputStream;
11
+import java.io.IOException;
12
+import java.io.PrintWriter;
13
+import java.nio.charset.StandardCharsets;
14
+import java.util.*;
15
+import java.util.zip.ZipEntry;
16
+import java.util.zip.ZipOutputStream;
17
+
18
+@Slf4j
19
+@Component
20
+public class CodeHelper {
21
+    /** 数据库字符串类型 */
22
+    public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
23
+
24
+    /** 数据库文本类型 */
25
+    public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
26
+
27
+    /** 数据库时间类型 */
28
+    public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
29
+
30
+    /** 数据库数字类型 */
31
+    public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
32
+            "bit", "bigint", "float", "double", "decimal" };
33
+
34
+    /** 字符串类型 */
35
+    public static final String TYPE_STRING = "String";
36
+
37
+    /** 整型 */
38
+    public static final String TYPE_INTEGER = "Integer";
39
+
40
+    /** 长整型 */
41
+    public static final String TYPE_LONG = "Long";
42
+
43
+    /** 浮点型 */
44
+    public static final String TYPE_DOUBLE = "Double";
45
+
46
+    /** 高精度计算类型 */
47
+    public static final String TYPE_BIGDECIMAL = "BigDecimal";
48
+
49
+    /** 时间类型 */
50
+    public static final String TYPE_DATE = "Date";
51
+
52
+    //获取代码
53
+    public static void GetCode(HttpServletResponse response,Map<String, Object> table, List<Map<String, Object>> columns, String packageName, String controllerName) {
54
+
55
+        try {
56
+            String tablename = table.get("tableName").toString();
57
+            String tabledesc = table.get("tableComment").toString();
58
+            if (StringHelper.isEmpty(tabledesc)) {
59
+                tabledesc = tablename;
60
+            }
61
+
62
+            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
63
+            ZipOutputStream zip = new ZipOutputStream(outputStream);
64
+
65
+            String condition = "";
66
+            String order = "";
67
+
68
+            //entity代码
69
+            StringBuilder entityCode = new StringBuilder();
70
+            entityCode.append("package midware.entity.database." + packageName + ";\n");
71
+            entityCode.append("\n");
72
+            entityCode.append("import com.baomidou.mybatisplus.annotation.IdType;\n");
73
+            entityCode.append("import com.baomidou.mybatisplus.annotation.TableId;\n");
74
+            entityCode.append("import com.baomidou.mybatisplus.annotation.TableName;\n");
75
+            //entityCode.append("import com.baomidou.mybatisplus.annotation.TableField;\n");
76
+            entityCode.append("import io.swagger.annotations.ApiModel;\n");
77
+            entityCode.append("import io.swagger.annotations.ApiModelProperty;\n");
78
+            entityCode.append("import lombok.Data;\n");
79
+            entityCode.append("import java.util.Date;\n");
80
+            entityCode.append("\n");
81
+            entityCode.append("/** " + tabledesc + " */\n");
82
+            entityCode.append("@ApiModel(value = \"" + controllerName + "\", description = \"" + tabledesc + "实体\")\n");
83
+            entityCode.append("@Data\n");
84
+            entityCode.append("@TableName(\"" + tablename + "\")\n");
85
+            entityCode.append("public class " + controllerName + " {\n");
86
+
87
+            for (Map<String, Object> column : columns) {
88
+                String columnname = column.get("columnName").toString();
89
+                String columndesc = column.get("columnComment").toString();
90
+                if (StringHelper.isEmpty(columndesc)) {
91
+                    columndesc = columnname;
92
+                }
93
+                entityCode.append("    /** " + columndesc + " */\n");
94
+                entityCode.append("    @ApiModelProperty(\"" + columndesc + "\")\n");
95
+
96
+                String javacolumnname=StringHelper.toCamelCase(columnname);
97
+                String ct = StringHelper.firstUpper(javacolumnname);
98
+
99
+                String columnkey = column.get("columnKey").toString();
100
+                if (Objects.equals(columnkey, "PRI")) {
101
+                    entityCode.append("    @TableId(type = IdType.AUTO)\n");
102
+                    order = "        qw.orderByDesc(" + controllerName + "::get" + ct + ");\n";
103
+                }
104
+
105
+                String datatype = column.get("dataType").toString();
106
+                String columntype = column.get("columnType").toString();
107
+                String javaType = TYPE_STRING;
108
+                if (Arrays.asList(COLUMNTYPE_TIME).contains(datatype)) {
109
+                    javaType = TYPE_DATE;
110
+                    condition += "        qw.eq(input.get" + ct + "() != null , "
111
+                            + controllerName + "::get" + ct + ", input.get" + ct + "());\n";
112
+                } else if (Arrays.asList(COLUMNTYPE_NUMBER).contains(datatype)) {
113
+                    // 如果是浮点型 统一用BigDecimal
114
+                    String[] str = StringHelper.substringBetween(columntype, "(", ")").split("\\,");
115
+                    if (str.length == 2 && Integer.parseInt(str[1]) > 0) {
116
+                        javaType = TYPE_BIGDECIMAL;
117
+                    }
118
+                    // 如果是整形
119
+                    else if (str.length == 1 && Integer.parseInt(str[0]) <= 11) {
120
+                        javaType = TYPE_INTEGER;
121
+                    }
122
+                    // 长整形
123
+                    else {
124
+                        javaType = TYPE_LONG;
125
+                    }
126
+
127
+                    condition += "        qw.eq(input.get" + ct + "() != null && input.get" + ct + "() > 0, "
128
+                            + controllerName + "::get" + ct + ", input.get" + ct + "());\n";
129
+                }
130
+                if (javaType.equals(TYPE_STRING)) {
131
+                    condition += "        qw.like(!StringHelper.isEmpty(input.get" + ct + "()), "
132
+                            + controllerName + "::get" + ct + ", input.get" + ct + "());\n";
133
+                }
134
+                //entityCode.append("    @TableField(\""+columnname+"\")\n");
135
+                entityCode.append("    private " + javaType + " " + javacolumnname + ";\n");
136
+            }
137
+            entityCode.append("}\n");
138
+
139
+            zip.putNextEntry(new ZipEntry(controllerName + ".java"));
140
+            zip.write(entityCode.toString().getBytes(StandardCharsets.UTF_8));
141
+            zip.closeEntry();
142
+
143
+
144
+            //mapper代码
145
+            StringBuilder mapperCode = new StringBuilder();
146
+            mapperCode.append("package midware.mapper." + packageName + ";\n");
147
+            mapperCode.append("\n");
148
+            mapperCode.append("import com.baomidou.mybatisplus.core.mapper.BaseMapper;\n");
149
+            mapperCode.append("import midware.entity.database." + packageName + "." + controllerName + ";\n");
150
+            mapperCode.append("import org.apache.ibatis.annotations.Mapper;\n");
151
+            mapperCode.append("\n");
152
+            mapperCode.append("@Mapper\n");
153
+            mapperCode.append("public interface " + controllerName + "Mapper extends BaseMapper<" + controllerName + "> {\n");
154
+            mapperCode.append("}\n");
155
+
156
+            zip.putNextEntry(new ZipEntry(controllerName + "Mapper.java"));
157
+            zip.write(mapperCode.toString().getBytes(StandardCharsets.UTF_8));
158
+            zip.closeEntry();
159
+
160
+            //service代码
161
+            StringBuilder serviceCode = new StringBuilder();
162
+            serviceCode.append("package midware.service." + packageName + ";\n");
163
+            serviceCode.append("\n");
164
+            serviceCode.append("import midware.entity.database." + packageName + "." + controllerName + ";\n");
165
+            serviceCode.append("import midware.service.IBaseService;\n");
166
+            serviceCode.append("\n");
167
+            serviceCode.append("public interface I" + controllerName + "Service extends IBaseService<" + controllerName + "> {\n");
168
+            serviceCode.append("}\n");
169
+
170
+            zip.putNextEntry(new ZipEntry("I" + controllerName + "Service.java"));
171
+            zip.write(serviceCode.toString().getBytes(StandardCharsets.UTF_8));
172
+            zip.closeEntry();
173
+
174
+            //service.impl代码
175
+            StringBuilder serviceimplCode = new StringBuilder();
176
+            serviceimplCode.append("package midware.service." + packageName + ".impl;\n");
177
+            serviceimplCode.append("\n");
178
+            serviceimplCode.append("import midware.entity.database." + packageName + "." + controllerName + ";\n");
179
+            serviceimplCode.append("import midware.mapper." + packageName + "." + controllerName + "Mapper;\n");
180
+            serviceimplCode.append("import midware.service." + packageName + ".I" + controllerName + "Service;\n");
181
+            serviceimplCode.append("import midware.service.BaseServiceImpl;\n");
182
+            serviceimplCode.append("import org.springframework.stereotype.Service;\n");
183
+            serviceimplCode.append("import org.springframework.transaction.annotation.Transactional;\n");
184
+            serviceimplCode.append("\n");
185
+            serviceimplCode.append("@Transactional\n");
186
+            serviceimplCode.append("@Service\n");
187
+            serviceimplCode.append("public class " + controllerName + "ServiceImpl extends BaseServiceImpl<" + controllerName + "Mapper, " + controllerName + "> implements I" + controllerName + "Service{\n");
188
+            serviceimplCode.append("    public " + controllerName + "ServiceImpl(){ super(false); }\n");
189
+            serviceimplCode.append("}\n");
190
+
191
+            zip.putNextEntry(new ZipEntry(controllerName + "ServiceImpl.java"));
192
+            zip.write(serviceimplCode.toString().getBytes(StandardCharsets.UTF_8));
193
+            zip.closeEntry();
194
+
195
+            //controller代码
196
+            String controller = controllerName.toLowerCase();
197
+            StringBuilder controllerCode = new StringBuilder();
198
+            controllerCode.append("package midware.controller." + packageName + ";\n");
199
+            controllerCode.append("\n");
200
+            controllerCode.append("import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\n");
201
+            controllerCode.append("import com.baomidou.mybatisplus.core.metadata.IPage;\n");
202
+            controllerCode.append("import com.baomidou.mybatisplus.extension.plugins.pagination.Page;\n");
203
+            controllerCode.append("import midware.controller.BaseController;\n");
204
+            controllerCode.append("import midware.entity.database." + packageName + "." + controllerName + ";\n");
205
+            controllerCode.append("import midware.entity.input.PageInput;\n");
206
+            controllerCode.append("import midware.model.AjaxResult;\n");
207
+            controllerCode.append("import midware.service." + packageName + ".I" + controllerName + "Service;\n");
208
+            controllerCode.append("import midware.util.annotation.Log;\n");
209
+            controllerCode.append("import midware.util.enums.BusinessType;\n");
210
+            controllerCode.append("import midware.util.helper.StringHelper;\n");
211
+            controllerCode.append("import io.swagger.annotations.Api;\n");
212
+            controllerCode.append("import io.swagger.annotations.ApiOperation;\n");
213
+            controllerCode.append("import org.springframework.beans.factory.annotation.Autowired;\n");
214
+            controllerCode.append("import org.springframework.web.bind.annotation.*;\n");
215
+            controllerCode.append("import java.util.Arrays;\n");
216
+            controllerCode.append("\n");
217
+            controllerCode.append("@Api(value = \"" + tabledesc + "\",tags = \"" + tabledesc + "\")\n");
218
+            controllerCode.append("@RestController\n");
219
+            controllerCode.append("@RequestMapping(\"/" + packageName + "/" + controller + "\")\n");
220
+            controllerCode.append("public class " + controllerName + "Controller extends BaseController {\n");
221
+            controllerCode.append("    @Autowired\n");
222
+            controllerCode.append("    private I" + controllerName + "Service " + controller + "Service;\n");
223
+            controllerCode.append("\n");
224
+            controllerCode.append("    @ApiOperation(\"列表\")\n");
225
+            controllerCode.append("    @Log(title = \"查询"+tabledesc+"列表\",businessType = BusinessType.QUERY)\n");
226
+            controllerCode.append("    @GetMapping\n");
227
+            controllerCode.append("    public AjaxResult getList(" + controllerName + " input, PageInput pageInput) {\n");
228
+            controllerCode.append("        LambdaQueryWrapper<" + controllerName + "> qw = new LambdaQueryWrapper<>();\n");
229
+            controllerCode.append(condition);
230
+            controllerCode.append(order);
231
+            controllerCode.append("        Page<" + controllerName + "> page = GetPage(pageInput);\n");
232
+            controllerCode.append("        if (page != null) {\n");
233
+            controllerCode.append("            IPage<" + controllerName + "> iPage = " + controller + "Service.getListPage(page, qw);\n");
234
+            controllerCode.append("            return Success(\"成功\", iPage.getRecords(), iPage.getTotal());\n");
235
+            controllerCode.append("        } else {\n");
236
+            controllerCode.append("            return Success(\"成功\", " + controller + "Service.getList(qw));\n");
237
+            controllerCode.append("        }\n");
238
+            controllerCode.append("    }\n");
239
+            controllerCode.append("\n");
240
+            controllerCode.append("    @ApiOperation(\"详情\")\n");
241
+            controllerCode.append("    @Log(title = \"查询"+tabledesc+"详情\",businessType = BusinessType.QUERY)\n");
242
+            controllerCode.append("    @GetMapping(\"/{id}\")\n");
243
+            controllerCode.append("    public AjaxResult getInfo(@PathVariable long id) {\n");
244
+            controllerCode.append("        return Success(\"成功\", " + controller + "Service.getEntity(id));\n");
245
+            controllerCode.append("    }\n");
246
+            controllerCode.append("\n");
247
+
248
+            controllerCode.append("    @ApiOperation(\"新增\")\n");
249
+            controllerCode.append("    @Log(title = \"新增"+tabledesc+"\",businessType = BusinessType.INSERT)\n");
250
+            controllerCode.append("    @PostMapping\n");
251
+            controllerCode.append("    public AjaxResult add(@RequestBody " + controllerName + " input) {\n");
252
+            controllerCode.append("        boolean result = " + controller + "Service.insert(input);\n");
253
+            controllerCode.append("        if (result) {\n");
254
+            controllerCode.append("            return Success(\"成功\");\n");
255
+            controllerCode.append("        } else {\n");
256
+            controllerCode.append("            return Error(\"新增失败\");\n");
257
+            controllerCode.append("        }\n");
258
+            controllerCode.append("    }\n");
259
+            controllerCode.append("\n");
260
+            controllerCode.append("    @ApiOperation(\"编辑\")\n");
261
+            controllerCode.append("    @Log(title = \"编辑"+tabledesc+"\",businessType = BusinessType.UPDATE)\n");
262
+            controllerCode.append("    @PutMapping\n");
263
+            controllerCode.append("    public AjaxResult edit(@RequestBody " + controllerName + " input)  {\n");
264
+            controllerCode.append("        boolean result = " + controller + "Service.update(input);\n");
265
+            controllerCode.append("        if (result) {\n");
266
+            controllerCode.append("            return Success(\"成功\");\n");
267
+            controllerCode.append("        } else {\n");
268
+            controllerCode.append("            return Error(\"修改失败\");\n");
269
+            controllerCode.append("        }\n");
270
+            controllerCode.append("    }\n");
271
+            controllerCode.append("\n");
272
+            controllerCode.append("    @ApiOperation(\"删除\")\n");
273
+            controllerCode.append("    @Log(title = \"删除"+tabledesc+"\",businessType = BusinessType.DELETE)\n");
274
+            controllerCode.append("    @DeleteMapping(\"/{ids}\")\n");
275
+            controllerCode.append("    public AjaxResult delete(@PathVariable Long[] ids)  {\n");
276
+            controllerCode.append("        boolean result = " + controller + "Service.delete(Arrays.asList(ids));\n");
277
+            controllerCode.append("        if (result) {\n");
278
+            controllerCode.append("            return Success(\"成功\");\n");
279
+            controllerCode.append("        } else {\n");
280
+            controllerCode.append("            return Error(\"删除失败\");\n");
281
+            controllerCode.append("        }\n");
282
+            controllerCode.append("    }\n");
283
+            controllerCode.append("\n");
284
+            controllerCode.append("}\n");
285
+
286
+            zip.putNextEntry(new ZipEntry(controllerName + "Controller.java"));
287
+            zip.write(controllerCode.toString().getBytes(StandardCharsets.UTF_8));
288
+            zip.closeEntry();
289
+
290
+            byte[] data = outputStream.toByteArray();
291
+
292
+            response.reset();
293
+            response.addHeader("Access-Control-Allow-Origin", "*");
294
+            response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
295
+            response.setHeader("Content-Disposition", "attachment; filename=\"" + controllerName + ".zip\"");
296
+            response.addHeader("Content-Length", "" + data.length);
297
+            response.setContentType("application/octet-stream; charset=UTF-8");
298
+            ServletOutputStream servletOutputStream = response.getOutputStream();
299
+            BufferedOutputStream buffer = new BufferedOutputStream(servletOutputStream);
300
+            buffer.write(data);
301
+            buffer.flush();
302
+            buffer.close();
303
+        }
304
+        catch (Exception e)
305
+        {
306
+            log.error("代码生成异常",e);
307
+
308
+            Map map = new HashMap();
309
+            map.put("state", "error");
310
+            map.put("message", "代码生成失败");
311
+
312
+            try {
313
+                PrintWriter out = response.getWriter();
314
+                out.write(JSON.toJSONString(map));
315
+                out.flush();
316
+                out.close();
317
+            } catch (IOException ex) {
318
+                throw new RuntimeException(ex);
319
+            }
320
+        }
321
+    }
322
+}

+ 104 - 0
midware-util/src/main/java/midware/util/helper/HttpHelper.java

@@ -0,0 +1,104 @@
1
+package midware.util.helper;
2
+
3
+import lombok.extern.slf4j.Slf4j;
4
+import org.apache.http.HttpEntity;
5
+import org.apache.http.HttpStatus;
6
+import org.apache.http.client.methods.CloseableHttpResponse;
7
+import org.apache.http.client.methods.HttpGet;
8
+import org.apache.http.client.methods.HttpPost;
9
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
10
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
11
+import org.apache.http.entity.StringEntity;
12
+import org.apache.http.impl.client.CloseableHttpClient;
13
+import org.apache.http.impl.client.HttpClients;
14
+import org.apache.http.ssl.SSLContextBuilder;
15
+import org.apache.http.util.EntityUtils;
16
+import org.springframework.stereotype.Component;
17
+
18
+import javax.net.ssl.SSLContext;
19
+import java.nio.charset.StandardCharsets;
20
+
21
+@Component
22
+@Slf4j
23
+public class HttpHelper {
24
+    /**
25
+     * 向指定 URL 发送GET方法的请求
26
+     *
27
+     * @param url 发送请求的 URL
28
+     * @return 所代表远程资源的响应结果
29
+     */
30
+    public static String get(String url) {
31
+        String result = "";
32
+        try {
33
+            // 创建httpclient对象
34
+            CloseableHttpClient httpClient = HttpClients.createDefault();
35
+            // 创建请求对象
36
+            HttpGet httpGet = new HttpGet(url);
37
+            // 发送请求,接收响应
38
+            CloseableHttpResponse response = httpClient.execute(httpGet);
39
+            // 获取状态码
40
+            int statusCode = response.getStatusLine().getStatusCode();
41
+            if (statusCode == HttpStatus.SC_OK) {
42
+                // 获取响应数据
43
+                HttpEntity entity = response.getEntity();
44
+                result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
45
+            } else {
46
+                log.warn("get请求状态:" + url + "," + statusCode);
47
+            }
48
+            // 关闭资源
49
+            response.close();
50
+            httpClient.close();
51
+        } catch (Exception ex) {
52
+            log.error("get请求异常:" + url, ex);
53
+        }
54
+        return result;
55
+    }
56
+
57
+    /**
58
+     * 向指定 URL 发送POST方法的请求
59
+     *
60
+     * @param url   发送请求的 URL
61
+     * @param param 请求参数json
62
+     * @return 所代表远程资源的响应结果
63
+     */
64
+    public static String post(String url, String param) {
65
+        String result = "";
66
+        try {
67
+            // 创建httpclient对象
68
+            CloseableHttpClient httpClient = HttpClients.createDefault();
69
+            if (url.startsWith("https")) {
70
+                SSLContext sslContext = new SSLContextBuilder()
71
+                        .loadTrustMaterial(null, new TrustSelfSignedStrategy())
72
+                        .build();
73
+
74
+                httpClient = HttpClients.custom()
75
+                        .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
76
+                        .setSSLContext(sslContext)
77
+                        .build();
78
+            }
79
+
80
+            // 创建请求对象
81
+            HttpPost httpPost = new HttpPost(url);
82
+            httpPost.setEntity(new StringEntity(param, StandardCharsets.UTF_8));
83
+            httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
84
+
85
+            // 发送请求,接收响应
86
+            CloseableHttpResponse response = httpClient.execute(httpPost);
87
+            // 获取状态码
88
+            int statusCode = response.getStatusLine().getStatusCode();
89
+            if (statusCode == HttpStatus.SC_OK) {
90
+                // 获取响应数据
91
+                HttpEntity entity1 = response.getEntity();
92
+                result = EntityUtils.toString(entity1, StandardCharsets.UTF_8);
93
+            } else {
94
+                log.warn("post请求状态:" + url + (StringHelper.isNotEmpty(param) ? "|" + param : "") + "," + statusCode);
95
+            }
96
+            // 关闭资源
97
+            response.close();
98
+            httpClient.close();
99
+        } catch (Exception ex) {
100
+            log.error("post请求异常:" + url + (StringHelper.isNotEmpty(param) ? "|" + param : ""), ex);
101
+        }
102
+        return result;
103
+    }
104
+}

+ 63 - 0
midware-util/src/main/java/midware/util/helper/IpHelper.java

@@ -0,0 +1,63 @@
1
+package midware.util.helper;
2
+
3
+import java.net.Inet4Address;
4
+import java.net.InetAddress;
5
+import java.net.NetworkInterface;
6
+import java.net.SocketException;
7
+import java.util.Enumeration;
8
+
9
+public class IpHelper {
10
+    public static String getIp4(){
11
+        String hostIP="";
12
+        try {
13
+            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
14
+            while (networkInterfaces.hasMoreElements()) {
15
+                NetworkInterface ni = networkInterfaces.nextElement();
16
+                Enumeration<InetAddress> nias = ni.getInetAddresses();
17
+                while (nias.hasMoreElements()) {
18
+                    InetAddress ia = nias.nextElement();
19
+                    if (!ia.isLinkLocalAddress() && !ia.isLoopbackAddress() && ia instanceof Inet4Address) {
20
+                        hostIP=ia.getHostAddress();
21
+                    }
22
+                }
23
+            }
24
+        } catch (SocketException e) {
25
+            e.printStackTrace();
26
+        }
27
+        return hostIP;
28
+    }
29
+
30
+    public static String getMac() {
31
+        String mac = "";
32
+        try {
33
+            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
34
+            while (networkInterfaces.hasMoreElements()) {
35
+                NetworkInterface ni = networkInterfaces.nextElement();
36
+                if (ni.isLoopback() || ni.isVirtual() || !ni.isUp()) continue;
37
+                boolean ip4 = false;
38
+                Enumeration<InetAddress> nias = ni.getInetAddresses();
39
+                while (nias.hasMoreElements()) {
40
+                    InetAddress ia = nias.nextElement();
41
+                    if (!ia.isLinkLocalAddress() && !ia.isLoopbackAddress() && ia instanceof Inet4Address) {
42
+                        ip4 = true;
43
+                    }
44
+                }
45
+                if (!ip4) continue;
46
+                byte[] macByte = ni.getHardwareAddress();
47
+                if (macByte == null) continue;
48
+                StringBuilder buf = new StringBuilder();
49
+                for (byte aMac : macByte) {
50
+                    buf.append(String.format("%02X-", aMac));
51
+                }
52
+                if (buf.length() > 0) {
53
+                    buf.deleteCharAt(buf.length() - 1);
54
+                    mac = buf.toString();
55
+                    break;
56
+                }
57
+            }
58
+        } catch (SocketException e) {
59
+            e.printStackTrace();
60
+        }
61
+        return mac;
62
+    }
63
+}

+ 206 - 0
midware-util/src/main/java/midware/util/helper/RedisHelper.java

@@ -0,0 +1,206 @@
1
+package midware.util.helper;
2
+
3
+import org.springframework.beans.factory.annotation.Autowired;
4
+import org.springframework.data.redis.core.RedisTemplate;
5
+import org.springframework.data.redis.core.StringRedisTemplate;
6
+import org.springframework.stereotype.Component;
7
+
8
+import java.util.ArrayList;
9
+import java.util.Collection;
10
+import java.util.List;
11
+import java.util.Set;
12
+import java.util.concurrent.TimeUnit;
13
+
14
+@SuppressWarnings(value = { "unchecked", "rawtypes" })
15
+@Component
16
+public class RedisHelper {
17
+    @Autowired
18
+    public StringRedisTemplate stringRedisTemplate;
19
+    @Autowired
20
+    private RedisTemplate redisTemplate;
21
+    /**
22
+     * 缓存String
23
+     *
24
+     * @param key 缓存的键值
25
+     * @param value 缓存的值
26
+     */
27
+    public  void setCache(final String key, final String value)
28
+    {
29
+        stringRedisTemplate.opsForValue().set(key, value );
30
+    }
31
+
32
+
33
+    /**
34
+     * 缓存String
35
+     *
36
+     * @param key 缓存的键值
37
+     * @param value 缓存的值
38
+     * @param timeout 时间
39
+     * @param timeUnit 时间颗粒度
40
+     */
41
+    public  void setCache(final String key, final String value, final Integer timeout, final TimeUnit timeUnit)
42
+    {
43
+        stringRedisTemplate.opsForValue().set(key, value, timeout, timeUnit);
44
+    }
45
+
46
+    /**
47
+     * 设置有效时间
48
+     *
49
+     * @param key Redis键
50
+     * @param timeout 超时时间
51
+     * @return true=设置成功;false=设置失败
52
+     */
53
+    public boolean expire(final String key, final long timeout)
54
+    {
55
+        return expire(key, timeout, TimeUnit.SECONDS);
56
+    }
57
+
58
+    /**
59
+     * 设置有效时间
60
+     *
61
+     * @param key Redis键
62
+     * @param timeout 超时时间
63
+     * @param unit 时间单位
64
+     * @return true=设置成功;false=设置失败
65
+     */
66
+    public boolean expire(final String key, final long timeout, final TimeUnit unit)
67
+    {
68
+        return stringRedisTemplate.expire(key, timeout, unit);
69
+    }
70
+
71
+    /**
72
+     * 获取有效时间
73
+     *
74
+     * @param key Redis键
75
+     * @return 有效时间
76
+     */
77
+    public long getExpire(final String key)
78
+    {
79
+        return stringRedisTemplate.getExpire(key);
80
+    }
81
+
82
+    /**
83
+     * 判断 key是否存在
84
+     *
85
+     * @param key 键
86
+     * @return true 存在 false不存在
87
+     */
88
+    public Boolean hasKey(String key)
89
+    {
90
+        return stringRedisTemplate.hasKey(key);
91
+    }
92
+
93
+    /**
94
+     * 获得缓存。
95
+     *
96
+     * @param key 缓存键值
97
+     * @return 缓存键值对应的数据
98
+     */
99
+    public String getCache(final String key)
100
+    {
101
+        return stringRedisTemplate.opsForValue().get(key);
102
+    }
103
+
104
+    /**
105
+     * 删除单个对象
106
+     *
107
+     * @param key
108
+     */
109
+    public boolean deleteCache(final String key)
110
+    {
111
+        return stringRedisTemplate.delete(key);
112
+    }
113
+
114
+    /**
115
+     * 删除集合对象
116
+     *
117
+     * @param collection 多个对象
118
+     * @return
119
+     */
120
+    public boolean deleteCache(final Collection collection)
121
+    {
122
+        return stringRedisTemplate.delete(collection) > 0;
123
+    }
124
+
125
+
126
+    /**
127
+     * 获得缓存的基本对象列表
128
+     *
129
+     * @param pattern 字符串前缀
130
+     * @return 对象列表
131
+     */
132
+    public Collection<String> getKeys(final String pattern)
133
+    {
134
+        return stringRedisTemplate.keys(pattern);
135
+    }
136
+
137
+    /**
138
+     * add:向集合中添加一个或多个元素
139
+     */
140
+    public void addSet(final String key, String value){
141
+        stringRedisTemplate.opsForSet().add(key,value);
142
+    }
143
+
144
+
145
+
146
+    /**
147
+     * 普通缓存放入并设置时间
148
+     * @param key 键
149
+     * @param value 值
150
+     * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
151
+     * @return true成功 false 失败
152
+     */
153
+    public boolean set(String key,String value,long time){
154
+        try {
155
+            if(time>0){
156
+                stringRedisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
157
+            }
158
+            return true;
159
+        } catch (Exception e) {
160
+            e.printStackTrace();
161
+            return false;
162
+        }
163
+    }
164
+
165
+
166
+        public Object get(String key) {
167
+            return isBlank(key) ? null : redisTemplate.opsForValue().get(key);
168
+        }
169
+
170
+
171
+        public List<String> getVals(String key) {
172
+            Set<String> keys =  isBlank(key) ? null : stringRedisTemplate.keys(key);
173
+            List<String> vals = new ArrayList<>();
174
+            if (keys == null) {
175
+                return null;
176
+            } else {
177
+                for (String k : keys) {
178
+                    vals.add(stringRedisTemplate.opsForValue().get(k));
179
+                }
180
+                return vals;
181
+            }
182
+        }
183
+
184
+    public Set<String> getSetKeys(String key) {
185
+        Set<String> keys =  isBlank(key) ? null : stringRedisTemplate.keys(key);
186
+        if (keys == null) {
187
+            return null;
188
+        } else {
189
+            return keys;
190
+        }
191
+    }
192
+
193
+        public boolean isBlank(String s) {
194
+            int len;
195
+            if (s != null && (len = s.length()) != 0) {
196
+                for(int i = 0; i < len; ++i) {
197
+                    if (!Character.isWhitespace(s.charAt(i))) {
198
+                        return false;
199
+                    }
200
+                }
201
+            }
202
+            return true;
203
+        }
204
+
205
+    }
206
+

+ 116 - 0
midware-util/src/main/java/midware/util/helper/SecretHelper.java

@@ -0,0 +1,116 @@
1
+package midware.util.helper;
2
+
3
+import org.springframework.util.DigestUtils;
4
+
5
+import javax.crypto.Cipher;
6
+import javax.crypto.SecretKey;
7
+import javax.crypto.spec.SecretKeySpec;
8
+import java.io.ByteArrayInputStream;
9
+import java.io.IOException;
10
+import java.io.InputStream;
11
+import java.security.MessageDigest;
12
+import java.security.NoSuchAlgorithmException;
13
+import java.util.Base64;
14
+
15
+public class SecretHelper {
16
+    public static String MD5(String decrypt) {
17
+        return DigestUtils.md5DigestAsHex(decrypt.getBytes());
18
+    }
19
+
20
+    public static String SHA1(String decrypt) {
21
+        try {
22
+            MessageDigest digest = MessageDigest.getInstance("SHA-1");
23
+            digest.update(decrypt.getBytes());
24
+            byte[] messageDigest = digest.digest();
25
+            // Create Hex String
26
+            StringBuilder hexString = new StringBuilder();
27
+            // 字节数组转换为 十六进制 数
28
+            for (byte b : messageDigest) {
29
+                String shaHex = Integer.toHexString(b & 0xFF);
30
+                if (shaHex.length() < 2) {
31
+                    hexString.append(0);
32
+                }
33
+                hexString.append(shaHex);
34
+            }
35
+            return hexString.toString();
36
+
37
+        } catch (NoSuchAlgorithmException e) {
38
+            e.printStackTrace();
39
+        }
40
+        return "";
41
+    }
42
+
43
+    public static String SHA256(String s) {
44
+        InputStream fis = new ByteArrayInputStream(s.getBytes());
45
+        return SHA256(fis);
46
+    }
47
+    public static String SHA256(InputStream inputStream)
48
+    {
49
+        byte[] buffer = new byte[1024 * 10];
50
+        MessageDigest md5 = null;
51
+        try {
52
+            md5 = MessageDigest.getInstance("SHA-256");
53
+            for (int numRead = 0; (numRead = inputStream.read(buffer)) > 0; ) {
54
+                md5.update(buffer, 0, numRead);
55
+            }
56
+            byte[] digest = md5.digest();
57
+            StringBuilder strHexString = new StringBuilder();
58
+            for (byte b : digest) {
59
+                String hex = Integer.toHexString(0xff & b);
60
+                if (hex.length() == 1) {
61
+                    strHexString.append('0');
62
+                }
63
+                strHexString.append(hex);
64
+            }
65
+            return strHexString.toString();
66
+        } catch (NoSuchAlgorithmException | IOException e) {
67
+            e.printStackTrace();
68
+        } finally {
69
+            try {
70
+                inputStream.close();
71
+            } catch (IOException e) {
72
+                e.printStackTrace();
73
+            }
74
+        }
75
+        return null;
76
+    }
77
+
78
+
79
+    private static String AES_KEY = "j8z&j*a$t{w#k}e@";
80
+    private static String AES_ECB = "AES/ECB/PKCS5Padding";
81
+    /**
82
+     * 使用AES加密原始字符串.
83
+     *
84
+     * @param input 原始输入字符串
85
+     */
86
+    public static String AesEncrypt(String input) {
87
+        try{
88
+            SecretKey secretKey = new SecretKeySpec(AES_KEY.getBytes(), "AES");
89
+            Cipher cipher = Cipher.getInstance(AES_ECB);
90
+            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
91
+            byte[] result = cipher.doFinal(input.getBytes("utf-8"));
92
+            return Base64.getEncoder().encodeToString(result);
93
+        } catch (Exception e) {
94
+            e.printStackTrace();
95
+        }
96
+        return "";
97
+    }
98
+
99
+    /**
100
+     * 使用AES解密原始字符串.
101
+     *
102
+     * @param input 原始输入字符串
103
+     */
104
+    public static String AesDecrypt(String input) {
105
+        try{
106
+            SecretKey secretKey = new SecretKeySpec(AES_KEY.getBytes(), "AES");
107
+            Cipher cipher = Cipher.getInstance(AES_ECB);
108
+            cipher.init(Cipher.DECRYPT_MODE,secretKey);
109
+            byte[] result = cipher.doFinal(Base64.getDecoder().decode(input));
110
+            return new String(result, "utf-8");
111
+        } catch (Exception e) {
112
+            e.printStackTrace();
113
+        }
114
+        return "";
115
+    }
116
+}

+ 110 - 0
midware-util/src/main/java/midware/util/helper/ServletHelper.java

@@ -0,0 +1,110 @@
1
+package midware.util.helper;
2
+
3
+import com.alibaba.fastjson2.JSON;
4
+import org.springframework.stereotype.Component;
5
+import org.springframework.web.context.request.RequestAttributes;
6
+import org.springframework.web.context.request.RequestContextHolder;
7
+import org.springframework.web.context.request.ServletRequestAttributes;
8
+import org.springframework.web.multipart.MultipartFile;
9
+import org.springframework.web.multipart.MultipartHttpServletRequest;
10
+import org.springframework.web.multipart.MultipartResolver;
11
+import org.springframework.web.multipart.support.StandardServletMultipartResolver;
12
+import org.springframework.web.util.ContentCachingRequestWrapper;
13
+import org.springframework.web.util.WebUtils;
14
+
15
+import javax.servlet.http.HttpServletRequest;
16
+import javax.servlet.http.HttpServletResponse;
17
+import java.util.HashMap;
18
+import java.util.List;
19
+import java.util.Map;
20
+import java.util.Objects;
21
+import java.util.stream.Collectors;
22
+
23
+@Component
24
+public class ServletHelper {
25
+
26
+
27
+    /**
28
+     * 获取request属性
29
+     *
30
+     * @return
31
+     */
32
+    public static ServletRequestAttributes getRequestAttributes() {
33
+        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
34
+        return (ServletRequestAttributes) attributes;
35
+    }
36
+
37
+    /**
38
+     * 获取request
39
+     */
40
+    public static HttpServletRequest getRequest() {
41
+        return getRequestAttributes().getRequest();
42
+    }
43
+
44
+    /**
45
+     * 获取response
46
+     */
47
+    public static HttpServletResponse getResponse() {
48
+        return getRequestAttributes().getResponse();
49
+    }
50
+
51
+    /**
52
+     * 获取客户端IP
53
+     *
54
+     * @param request 请求对象
55
+     * @return IP地址
56
+     */
57
+    public static String getIpAddr(HttpServletRequest request) {
58
+        if (request == null) {
59
+            return "unknown";
60
+        }
61
+        String ip = request.getHeader("x-forwarded-for");
62
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
63
+            ip = request.getHeader("Proxy-Client-IP");
64
+        }
65
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
66
+            ip = request.getHeader("X-Forwarded-For");
67
+        }
68
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
69
+            ip = request.getHeader("WL-Proxy-Client-IP");
70
+        }
71
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
72
+            ip = request.getHeader("X-Real-IP");
73
+        }
74
+
75
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
76
+            ip = request.getRemoteAddr();
77
+        }
78
+
79
+        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
80
+    }
81
+
82
+    /**
83
+     * 获取请求参数
84
+     *
85
+     * @param request
86
+     * @return
87
+     */
88
+    public static String getParams(HttpServletRequest request) {
89
+        String paramstr = "";
90
+        // 设置参数
91
+        if (!Objects.equals(request.getMethod(), "GET")) {
92
+            ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
93
+            if (request.getContentType() != null && request.getContentType().contains("multipart/form-data")) {
94
+                MultipartResolver resolver = new StandardServletMultipartResolver();
95
+                MultipartHttpServletRequest mRequest = resolver.resolveMultipart(request);
96
+                Map<String, Object> params = new HashMap<>();
97
+                for (Map.Entry<String, List<MultipartFile>> item : mRequest.getMultiFileMap().entrySet()) {
98
+                    params.put(item.getKey(), item.getValue().stream().map(p -> p.getOriginalFilename()).collect(Collectors.toList()));
99
+                }
100
+                paramstr = JSON.toJSONString(params);
101
+            } else {
102
+                paramstr = new String(wrapper.getContentAsByteArray());
103
+            }
104
+        } else {
105
+            paramstr = request.getQueryString();
106
+        }
107
+        return paramstr;
108
+    }
109
+
110
+}

+ 156 - 0
midware-util/src/main/java/midware/util/helper/SpringHelper.java

@@ -0,0 +1,156 @@
1
+package midware.util.helper;
2
+
3
+import org.springframework.aop.framework.AopContext;
4
+import org.springframework.beans.BeansException;
5
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
6
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
7
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
8
+import org.springframework.context.ApplicationContext;
9
+import org.springframework.context.ApplicationContextAware;
10
+import org.springframework.stereotype.Component;
11
+
12
+@Component
13
+public class SpringHelper implements BeanFactoryPostProcessor, ApplicationContextAware {
14
+    /** Spring应用上下文环境 */
15
+    private static ConfigurableListableBeanFactory beanFactory;
16
+
17
+    private static ApplicationContext applicationContext;
18
+
19
+    @Override
20
+    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
21
+    {
22
+        SpringHelper.beanFactory = beanFactory;
23
+    }
24
+
25
+    @Override
26
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
27
+    {
28
+        SpringHelper.applicationContext = applicationContext;
29
+    }
30
+
31
+    /**
32
+     * 获取对象
33
+     *
34
+     * @param name
35
+     * @return Object 一个以所给名字注册的bean的实例
36
+     * @throws BeansException
37
+     *
38
+     */
39
+    @SuppressWarnings("unchecked")
40
+    public static <T> T getBean(String name) throws BeansException
41
+    {
42
+        return (T) beanFactory.getBean(name);
43
+    }
44
+
45
+    /**
46
+     * 获取类型为requiredType的对象
47
+     *
48
+     * @param clz
49
+     * @return
50
+     * @throws BeansException
51
+     *
52
+     */
53
+    public static <T> T getBean(Class<T> clz) throws BeansException
54
+    {
55
+        T result = (T) beanFactory.getBean(clz);
56
+        return result;
57
+    }
58
+
59
+    /**
60
+     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
61
+     *
62
+     * @param name
63
+     * @return boolean
64
+     */
65
+    public static boolean containsBean(String name)
66
+    {
67
+        return beanFactory.containsBean(name);
68
+    }
69
+
70
+    /**
71
+     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
72
+     *
73
+     * @param name
74
+     * @return boolean
75
+     * @throws NoSuchBeanDefinitionException
76
+     *
77
+     */
78
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
79
+    {
80
+        return beanFactory.isSingleton(name);
81
+    }
82
+
83
+    /**
84
+     * @param name
85
+     * @return Class 注册对象的类型
86
+     * @throws NoSuchBeanDefinitionException
87
+     *
88
+     */
89
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
90
+    {
91
+        return beanFactory.getType(name);
92
+    }
93
+
94
+    /**
95
+     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
96
+     *
97
+     * @param name
98
+     * @return
99
+     * @throws NoSuchBeanDefinitionException
100
+     *
101
+     */
102
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
103
+    {
104
+        return beanFactory.getAliases(name);
105
+    }
106
+
107
+    /**
108
+     * 获取aop代理对象
109
+     *
110
+     * @param invoker
111
+     * @return
112
+     */
113
+    @SuppressWarnings("unchecked")
114
+    public static <T> T getAopProxy(T invoker)
115
+    {
116
+        return (T) AopContext.currentProxy();
117
+    }
118
+
119
+    /**
120
+     * 获取当前的环境配置,无配置返回null
121
+     *
122
+     * @return 当前的环境配置
123
+     */
124
+    public static String[] getActiveProfiles()
125
+    {
126
+        return applicationContext.getEnvironment().getActiveProfiles();
127
+    }
128
+
129
+    /**
130
+     * 获取当前的环境配置,当有多个环境配置时,只获取第一个
131
+     *
132
+     * @return 当前的环境配置
133
+     */
134
+    public static String getActiveProfile() {
135
+        final String[] activeProfiles = getActiveProfiles();
136
+        return activeProfiles != null && activeProfiles.length > 0 ? activeProfiles[0] : null;
137
+    }
138
+
139
+    /**
140
+     * 获取配置文件中的值
141
+     *
142
+     * @param key 配置文件的key
143
+     * @return 当前的配置文件的值
144
+     *
145
+     */
146
+    public static String getRequiredProperty(String key)
147
+    {
148
+        return applicationContext.getEnvironment().getRequiredProperty(key);
149
+    }
150
+
151
+    @SuppressWarnings("unchecked")
152
+    public static <T> T getAttribute(String name)
153
+    {
154
+        return (T) ServletHelper.getRequestAttributes().getAttribute(name, 0);
155
+    }
156
+}

+ 337 - 0
midware-util/src/main/java/midware/util/helper/StringHelper.java

@@ -0,0 +1,337 @@
1
+package midware.util.helper;
2
+
3
+import org.springframework.stereotype.Component;
4
+
5
+import java.util.ArrayList;
6
+import java.util.Arrays;
7
+import java.util.List;
8
+
9
+@Component
10
+public class StringHelper {
11
+    /** 下划线 */
12
+    private static final char SEPARATOR = '_';
13
+    /**
14
+     * * 判断一个对象是否为空
15
+     *
16
+     * @param object Object
17
+     * @return true:为空 false:非空
18
+     */
19
+    public static boolean isNull(Object object)
20
+    {
21
+        return object == null;
22
+    }
23
+    /**
24
+     * * 判断一个字符串是否为空串
25
+     *
26
+     * @param str String
27
+     * @return true:为空 false:非空
28
+     */
29
+    public static boolean isEmpty(String str)
30
+    {
31
+        return isNull(str) || str.trim().equals("");
32
+    }
33
+
34
+    /**
35
+     * * 判断一个字符串是否为非空串
36
+     *
37
+     * @param str String
38
+     * @return true:非空串 false:空串
39
+     */
40
+    public static boolean isNotEmpty(String str)
41
+    {
42
+        return !isEmpty(str);
43
+    }
44
+
45
+
46
+    public static boolean isBlank(CharSequence cs) {
47
+        int strLen = cs == null ? 0 : cs.length();
48
+        if (strLen == 0) {
49
+            return true;
50
+        } else {
51
+            for(int i = 0; i < strLen; ++i) {
52
+                if (!Character.isWhitespace(cs.charAt(i))) {
53
+                    return false;
54
+                }
55
+            }
56
+
57
+            return true;
58
+        }
59
+    }
60
+    public static boolean isNotBlank(CharSequence cs) {
61
+        return !isBlank(cs);
62
+    }
63
+
64
+    /**
65
+     * * 获取中间字符串
66
+     *
67
+     * @param str String
68
+     * @param open String
69
+     * @param close String
70
+     * @return String
71
+     */
72
+    public static String substringBetween(String str, String open, String close) {
73
+        int start = str.indexOf(open);
74
+        if (start != -1) {
75
+            int end = str.indexOf(close, start + open.length());
76
+            if (end != -1) {
77
+                return str.substring(start + open.length(), end);
78
+            }
79
+        }
80
+        return null;
81
+    }
82
+
83
+    /**
84
+     * 截取字符串
85
+     *
86
+     * @param str 字符串
87
+     * @param start 开始
88
+     * @param end 结束
89
+     * @return 结果
90
+     */
91
+    public static String substring(final String str, int start, int end)
92
+    {
93
+        if (str == null)
94
+        {
95
+            return "";
96
+        }
97
+
98
+        if (end < 0)
99
+        {
100
+            end = str.length() + end;
101
+        }
102
+        if (start < 0)
103
+        {
104
+            start = str.length() + start;
105
+        }
106
+
107
+        if (end > str.length())
108
+        {
109
+            end = str.length();
110
+        }
111
+
112
+        if (start > end)
113
+        {
114
+            return "";
115
+        }
116
+
117
+        if (start < 0)
118
+        {
119
+            start = 0;
120
+        }
121
+        if (end < 0)
122
+        {
123
+            end = 0;
124
+        }
125
+
126
+        return str.substring(start, end);
127
+    }
128
+
129
+    /**
130
+     * * 字符串首字母大写
131
+     *
132
+     * @param str String
133
+     * @return String
134
+     */
135
+    public static String firstUpper(String str)
136
+    {
137
+        char[] strs=str.toCharArray();
138
+
139
+        if(strs[0]>=65||strs[0]<=90) {
140
+            strs[0] -= 32;
141
+        }
142
+        return String.valueOf(strs);
143
+    }
144
+
145
+    /**
146
+     * 驼峰式命名法
147
+     * 例如:user_name->userName
148
+     */
149
+    public static String toCamelCase(String s)
150
+    {
151
+        if (s == null)
152
+        {
153
+            return null;
154
+        }
155
+        if (s.indexOf(SEPARATOR) == -1)
156
+        {
157
+            return s;
158
+        }
159
+        s = s.toLowerCase();
160
+        StringBuilder sb = new StringBuilder(s.length());
161
+        boolean upperCase = false;
162
+        for (int i = 0; i < s.length(); i++)
163
+        {
164
+            char c = s.charAt(i);
165
+
166
+            if (c == SEPARATOR)
167
+            {
168
+                upperCase = true;
169
+            }
170
+            else if (upperCase)
171
+            {
172
+                sb.append(Character.toUpperCase(c));
173
+                upperCase = false;
174
+            }
175
+            else
176
+            {
177
+                sb.append(c);
178
+            }
179
+        }
180
+        return sb.toString();
181
+    }
182
+
183
+    /**
184
+     * 驼峰转下划线命名
185
+     */
186
+    public static String toUnderScoreCase(String str)
187
+    {
188
+        if (str == null)
189
+        {
190
+            return null;
191
+        }
192
+        StringBuilder sb = new StringBuilder();
193
+        // 前置字符是否大写
194
+        boolean preCharIsUpperCase;
195
+        // 当前字符是否大写
196
+        boolean curreCharIsUpperCase;
197
+        // 下一字符是否大写
198
+        boolean nexteCharIsUpperCase = true;
199
+        for (int i = 0; i < str.length(); i++)
200
+        {
201
+            char c = str.charAt(i);
202
+            if (i > 0)
203
+            {
204
+                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
205
+            }
206
+            else
207
+            {
208
+                preCharIsUpperCase = false;
209
+            }
210
+
211
+            curreCharIsUpperCase = Character.isUpperCase(c);
212
+
213
+            if (i < (str.length() - 1))
214
+            {
215
+                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
216
+            }
217
+
218
+            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
219
+            {
220
+                sb.append(SEPARATOR);
221
+            }
222
+            else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
223
+            {
224
+                sb.append(SEPARATOR);
225
+            }
226
+            sb.append(Character.toLowerCase(c));
227
+        }
228
+
229
+        return sb.toString();
230
+    }
231
+
232
+    public static boolean equals(CharSequence cs1, CharSequence cs2) {
233
+        if (cs1 == cs2) {
234
+            return true;
235
+        } else if (cs1 != null && cs2 != null) {
236
+            if (cs1.length() != cs2.length()) {
237
+                return false;
238
+            } else if (cs1 instanceof String && cs2 instanceof String) {
239
+                return cs1.equals(cs2);
240
+            } else {
241
+                int length = cs1.length();
242
+
243
+                for(int i = 0; i < length; ++i) {
244
+                    if (cs1.charAt(i) != cs2.charAt(i)) {
245
+                        return false;
246
+                    }
247
+                }
248
+
249
+                return true;
250
+            }
251
+        } else {
252
+            return false;
253
+        }
254
+    }
255
+
256
+    public static String stripStart(String str, String stripChars) {
257
+        int strLen = str.length();
258
+        if (strLen == 0) {
259
+            return str;
260
+        } else {
261
+            int start = 0;
262
+            if (stripChars == null) {
263
+                while(start != strLen && Character.isWhitespace(str.charAt(start))) {
264
+                    ++start;
265
+                }
266
+            } else {
267
+                if (stripChars.isEmpty()) {
268
+                    return str;
269
+                }
270
+
271
+                while(start != strLen && stripChars.indexOf(str.charAt(start)) != -1) {
272
+                    ++start;
273
+                }
274
+            }
275
+
276
+            return str.substring(start);
277
+        }
278
+    }
279
+    public static <T> List<T> objToList(Object obj, Class<T> cla){
280
+        List<T> list = new ArrayList<T>();
281
+        if (obj instanceof ArrayList<?>) {
282
+            for (Object o : (List<?>) obj) {
283
+                list.add(cla.cast(o));
284
+            }
285
+            return list;
286
+        }
287
+        return null;
288
+    }
289
+
290
+    public static String getFileSuffix(String fileName){
291
+        int pos=fileName.lastIndexOf(".");
292
+        if(pos>=0){
293
+            if(pos+1!=fileName.length()){
294
+                return fileName.substring(pos+1,fileName.length()).toLowerCase();
295
+            }
296
+        }
297
+        return "";
298
+    }
299
+
300
+    public static String getFileNameWithoutSuffix(String fileName){
301
+        int pos=fileName.lastIndexOf(".");
302
+        if(pos>=0){
303
+            if(pos+1!=fileName.length()){
304
+                return fileName.substring(0,pos);
305
+            }
306
+        }
307
+        return "";
308
+    }
309
+
310
+    public  static List<String> splitStrListToList(List<String> sourceList){
311
+        List<String> resultList = new ArrayList<>();
312
+        for (int i = 0; i < sourceList.size(); i++) {
313
+            resultList.addAll(splitStringToList(sourceList.get(i)));
314
+        }
315
+
316
+        return resultList;
317
+    }
318
+
319
+    //更换其他字符或空格为",",最后得到string数组
320
+    public static List<String> splitStringToList(String source){
321
+        List<String> resultList = new ArrayList<>();
322
+        List<String> tmptList = new ArrayList<>();
323
+        //String regExpress = "-~!@#%&_`=}:\"<>]\\\\;\'/\\$\\(\\)\\*\\+\\.\\[\\?\\\\\\^\\{\\|";
324
+        String regExpress = "[<~!@#%&_`=}:\">\\;'/\\$\\(\\)\\*\\+\\.\\[\\?\\\\\\^\\{\\|\\-\\]]";
325
+        if(source !=null && source.length()>0){
326
+            source = source.replaceAll(regExpress,",")
327
+                    .replace(" ",",");
328
+            tmptList = Arrays.asList(source.split(","));
329
+            tmptList.forEach((e)->{
330
+                if(!e.isEmpty()){
331
+                    resultList.add(e);
332
+                }
333
+            });
334
+        }
335
+        return resultList;
336
+    }
337
+}

+ 120 - 0
midware-util/src/main/java/midware/util/helper/TtsHelper.java

@@ -0,0 +1,120 @@
1
+package midware.util.helper;
2
+
3
+import com.alibaba.fastjson2.JSON;
4
+import lombok.extern.slf4j.Slf4j;
5
+import midware.util.config.CommonConfig;
6
+
7
+import java.io.File;
8
+import java.io.FileOutputStream;
9
+import java.io.IOException;
10
+import java.text.SimpleDateFormat;
11
+import java.util.Base64;
12
+import java.util.Date;
13
+import java.util.HashMap;
14
+import java.util.Map;
15
+
16
+@Slf4j
17
+public class TtsHelper {
18
+
19
+    private static void transfer(String word, String filePath) {
20
+        switch (CommonConfig.tts_type) {
21
+            case "ekho":
22
+                try {
23
+                    String command = "ekho " + word + " -o " + filePath;
24
+                    Process process = Runtime.getRuntime().exec(command);
25
+                    process.waitFor();
26
+                } catch (IOException | InterruptedException ex) {
27
+                    log.error("ekho异常", ex);
28
+                }
29
+                break;
30
+            case "modelscope":
31
+                Map<String, Object> param = new HashMap<>();
32
+                param.put("input", word);
33
+                Map<String, Object> param1 = new HashMap<>();
34
+                param1.put("voice", "zhitian_emo");
35
+                param.put("parameters", param1);
36
+
37
+                String result = HttpHelper.post(CommonConfig.tts_url, JSON.toJSONString(param));
38
+                if (StringHelper.isNotEmpty(result)) {
39
+                    try {
40
+                        Map map = JSON.parseObject(result, Map.class);
41
+
42
+                        byte[] bytes = Base64.getDecoder().decode(map.get("output_wav").toString());
43
+                        File file = new File(filePath);
44
+                        FileOutputStream outputStream = new FileOutputStream(file);
45
+                        outputStream.write(bytes);
46
+                        outputStream.close();
47
+                    } catch (Exception ex) {
48
+                        log.error("modelscope异常", ex);
49
+                    }
50
+                }
51
+                break;
52
+        }
53
+    }
54
+
55
+    public static String TextToSpeech(String word) {
56
+        return TextToSpeech(word, "");
57
+    }
58
+
59
+    public static String TextToSpeech(String word, String filename) {
60
+        String parentPath = "files/audio/" + new SimpleDateFormat("yyyy-MM-dd").format(new Date());
61
+        File file = new File(parentPath);
62
+        if (!file.exists()) {
63
+            file.mkdirs();
64
+        }
65
+
66
+        if (StringHelper.isEmpty(filename)) {
67
+            filename = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
68
+        }
69
+        String filePath = file.getAbsolutePath() + "/" + filename + ".wav";
70
+        transfer(word,filePath);
71
+
72
+        return filePath;
73
+    }
74
+
75
+    public static String TextToSpeechWord(String word, String filename) {
76
+        String parentPath = "files/audio/" ;
77
+        File file = new File(parentPath);
78
+        if (!file.exists()) {
79
+            file.mkdirs();
80
+        }
81
+
82
+        String filePath = file.getAbsolutePath() + "/" + filename + ".wav";
83
+
84
+        if (!new File(filePath).exists()) {
85
+            transfer(word,filePath);
86
+        }
87
+
88
+        return filePath;
89
+    }
90
+
91
+    public static String TextToSpeechAgent(String word, String filename) {
92
+        String parentPath = "files/agent/";
93
+        File file = new File(parentPath);
94
+        if (!file.exists()) {
95
+            file.mkdirs();
96
+        }
97
+
98
+        String filePath = file.getAbsolutePath() + "/" + filename + ".wav";
99
+
100
+//        if (!new File(filePath).exists()) {
101
+//            transfer(word,filePath);
102
+//        }
103
+        return filePath;
104
+    }
105
+
106
+    public static String TextToSpeechPosition(String word, String filename) {
107
+        String parentPath = "files/position/";
108
+        File file = new File(parentPath);
109
+        if (!file.exists()) {
110
+            file.mkdirs();
111
+        }
112
+
113
+        String filePath = file.getAbsolutePath() + "/" + filename + ".wav";
114
+
115
+//        if (!new File(filePath).exists()) {
116
+//            transfer(word,filePath);
117
+//        }
118
+        return filePath;
119
+    }
120
+}

+ 68 - 0
pom.xml

@@ -0,0 +1,68 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <modelVersion>4.0.0</modelVersion>
6
+
7
+    <parent>
8
+        <groupId>org.springframework.boot</groupId>
9
+        <artifactId>spring-boot-starter-parent</artifactId>
10
+        <version>2.5.14</version>
11
+        <relativePath/> <!-- lookup parent from repository -->
12
+    </parent>
13
+    <groupId>midware</groupId>
14
+    <artifactId>midware-base</artifactId>
15
+    <version>1.0.0</version>
16
+    <packaging>pom</packaging>
17
+    <name>midware</name>
18
+    <description>midware</description>
19
+    <modules>
20
+        <module>midware-api</module>
21
+        <module>midware-util</module>
22
+        <module>midware-service</module>
23
+        <module>midware-entity</module>
24
+        <module>midware-mapper</module>
25
+    </modules>
26
+    <properties>
27
+        <java.version>1.8</java.version>
28
+        <mybatis.plus.version>3.5.3</mybatis.plus.version>
29
+        <fastjson.version>2.0.25</fastjson.version>
30
+    </properties>
31
+    <dependencies>
32
+
33
+        <!-- mybatis-plus启动器 -->
34
+        <dependency>
35
+            <groupId>com.baomidou</groupId>
36
+            <artifactId>mybatis-plus-boot-starter</artifactId>
37
+            <version>${mybatis.plus.version}</version>
38
+        </dependency>
39
+
40
+        <!-- lombok插件 -->
41
+        <dependency>
42
+            <groupId>org.projectlombok</groupId>
43
+            <artifactId>lombok</artifactId>
44
+            <optional>true</optional>
45
+        </dependency>
46
+
47
+        <!-- 自定义验证注解 -->
48
+        <dependency>
49
+            <groupId>org.springframework.boot</groupId>
50
+            <artifactId>spring-boot-starter-validation</artifactId>
51
+        </dependency>
52
+
53
+        <!-- 阿里JSON解析器 -->
54
+        <dependency>
55
+            <groupId>com.alibaba.fastjson2</groupId>
56
+            <artifactId>fastjson2</artifactId>
57
+            <version>${fastjson.version}</version>
58
+        </dependency>
59
+
60
+        <dependency>
61
+            <groupId>org.apache.commons</groupId>
62
+            <artifactId>commons-lang3</artifactId>
63
+            <version>3.5</version>
64
+        </dependency>
65
+
66
+    </dependencies>
67
+
68
+</project>