duhongyu месяцев назад: 4
Родитель
Сommit
863cb44473

+ 11 - 0
ltrq-api/src/main/java/api/controller/dify/DifyAssistantController.java

@@ -86,6 +86,13 @@ public class DifyAssistantController extends BaseController {
86 86
                                    HttpServletResponse response) throws IOException {
87 87
         return difyassistantService.chatMessages(input,CurrentUser(), response);
88 88
     }
89
+    @ApiOperation("工作流")
90
+    @PostMapping(value = "/workflows", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
91
+    public SseEmitter workflows(@RequestBody WorkflowsInput input,
92
+                                   HttpServletResponse response) throws IOException {
93
+        return difyassistantService.workflows(input,CurrentUser(), response);
94
+    }
95
+
89 96
     @ApiOperation("消息反馈")
90 97
     @Log(title = "消息反馈",businessType = BusinessType.QUERY)
91 98
     @PostMapping("/feedbacks")
@@ -136,6 +143,10 @@ public class DifyAssistantController extends BaseController {
136 143
     public AjaxResult rename(@RequestBody DifyRenameInput input) throws Exception {
137 144
         return Success("成功", difyassistantService.Rename(input,CurrentUser() ));
138 145
     }
146
+
147
+
148
+
149
+
139 150
     @ApiOperation("删除")
140 151
     @Log(title = "删除dify_assistant",businessType = BusinessType.DELETE)
141 152
     @DeleteMapping("/{ids}")

+ 152 - 3
ltrq-api/src/main/java/api/controller/order/OrderBaseController.java

@@ -4,6 +4,7 @@ import api.entity.database.call.CallLog;
4 4
 import api.entity.database.order.*;
5 5
 import api.entity.database.patient.Patient;
6 6
 import api.entity.database.system.*;
7
+import api.entity.input.order.SimilarOrdersInput;
7 8
 import api.entity.input.order.TransOrderInput;
8 9
 import api.entity.view.order.*;
9 10
 import api.entity.view.system.DeptView;
@@ -33,6 +34,7 @@ import api.service.order.IOrderBaseService;
33 34
 import api.util.annotation.Log;
34 35
 import api.util.enums.BusinessType;
35 36
 import api.util.helper.StringHelper;
37
+import io.milvus.response.SearchResultsWrapper;
36 38
 import io.swagger.annotations.Api;
37 39
 import io.swagger.annotations.ApiOperation;
38 40
 import lombok.var;
@@ -41,6 +43,7 @@ import org.springframework.web.bind.annotation.*;
41 43
 
42 44
 import java.text.SimpleDateFormat;
43 45
 import java.util.*;
46
+import java.util.concurrent.CompletableFuture;
44 47
 import java.util.stream.Collectors;
45 48
 
46 49
 @Api(value = "新加的controller,蓝天燃气工单用这个",tags = "新加的controller,蓝天燃气工单用这个")
@@ -410,6 +413,7 @@ public class OrderBaseController extends BaseController {
410 413
                     }
411 414
                 } catch (Exception e) {
412 415
                 }
416
+
413 417
                 boolean customerresult = patientService.insert(pt);
414 418
             }
415 419
             //添加操作日志
@@ -428,6 +432,14 @@ public class OrderBaseController extends BaseController {
428 432
 
429 433
                 }
430 434
             }
435
+            CompletableFuture.supplyAsync(() -> {
436
+                try {
437
+                    orderbaseService.historicalOrders(input);
438
+                } catch (Exception e) {
439
+                    throw new RuntimeException(e);
440
+                }
441
+                return null;
442
+            }).thenAccept(results -> System.out.println("Result: " + results));
431 443
             return Success("成功", input.getWorkOrderCode());
432 444
         } else {
433 445
             return Error("新增失败");
@@ -660,6 +672,10 @@ public class OrderBaseController extends BaseController {
660 672
     public AjaxResult end(@RequestBody HashMap<String,String> map) {
661 673
         String code= map.get("code");
662 674
 
675
+
676
+
677
+
678
+
663 679
         Date currentDate = new Date(System.currentTimeMillis());
664 680
 
665 681
         LambdaUpdateWrapper< OrderBase> qw = new LambdaUpdateWrapper<>();
@@ -678,6 +694,23 @@ public class OrderBaseController extends BaseController {
678 694
         }
679 695
 
680 696
         if (result) {
697
+            CompletableFuture.supplyAsync(() -> {
698
+                try {
699
+                    LambdaQueryWrapper<OrderBase> queryWrapper = new LambdaQueryWrapper<>();
700
+                    queryWrapper.eq(OrderBase::getWorkOrderCode, code);
701
+                    queryWrapper.last("limit 1");
702
+                    queryWrapper.orderByDesc(OrderBase::getWorkOrderId);
703
+                    OrderBase  orderBase    = orderbaseService.getEntity(queryWrapper);
704
+                    if (orderBase!=null&&StringHelper.isNotEmpty(orderBase.getCorrelation()))
705
+                    {
706
+                        overOrder(orderBase);
707
+                    }
708
+                } catch (Exception e) {
709
+                    throw new RuntimeException(e);
710
+                }
711
+                return null;
712
+            }).thenAccept(results -> System.out.println("Result: " + results));
713
+
681 714
             boolean logresult = addlog("完结了工单" + reason, "完结", CurrentUser().getUserName(), code, CurrentUser().getNickName(), "");
682 715
             return Success("完结成功");
683 716
         } else {
@@ -713,9 +746,90 @@ public class OrderBaseController extends BaseController {
713 746
         }
714 747
     }
715 748
 
749
+    @ApiOperation("关联工单")
750
+    @Log(title = "关联工单", businessType = BusinessType.UPDATE)
751
+    @PutMapping("/correlation/{ids}")
752
+    public AjaxResult correlation(@PathVariable List<Long> ids) {
753
+      LambdaQueryWrapper<OrderBase> qw=new LambdaQueryWrapper<>();
754
+      qw.eq(OrderBase::getIsDelete,0);
755
+      qw.in(OrderBase::getWorkOrderId,ids);
756
+      var list=orderbaseService.getList(qw);
757
+      if (list!=null&&list.size()>0)
758
+      {
759
+         var overList=list.stream().filter(x->x.getIsEnd()==1).collect(Collectors.toList());
760
+         var unfinished=list.stream().filter(x->x.getIsEnd()!=1).collect(Collectors.toList());
761
+         var mainWorkOrder=new OrderBase();
762
+         if (overList.size()>0)
763
+         {
764
+             mainWorkOrder=overList.get(0);
765
+         }
766
+         else
767
+         {
768
+             mainWorkOrder=list.get(0);
769
+         }
770
+         List<Long>unfinishedIds=new ArrayList<>();
771
+         if (unfinished.size()>0)
772
+         {
773
+             unfinishedIds=unfinished.stream() .map(OrderBase::getWorkOrderId)
774
+                     .collect(Collectors.toList());
775
+         }
776
+          LambdaUpdateWrapper<OrderBase> qu=new LambdaUpdateWrapper<>();
777
+          qu.eq(OrderBase::getIsDelete,0);
778
+          qu.in(OrderBase::getWorkOrderId,ids);
779
+          qu.set(OrderBase::getCorrelation,mainWorkOrder.getWorkOrderId());
780
+          boolean n=orderbaseService.updateBatch(qu);
781
+          if (n )
782
+          {
783
+              if (overList.size()>0&&unfinishedIds.size()>0)
784
+              {
785
+                  LambdaUpdateWrapper<OrderBase> qu1=new LambdaUpdateWrapper<>();
786
+                  qu1.eq(OrderBase::getIsDelete,0);
787
+                  qu1.eq(OrderBase::getCorrelation,mainWorkOrder.getWorkOrderId());
788
+                  qu1.eq(OrderBase::getIsEnd,0);
789
+                  qu1.set(OrderBase::getWorkOrderState,  EnumOrderStatus.end.getValue());
790
+                  qu1.set(OrderBase::getIsEnd, 1);
791
+                  qu1.set(OrderBase::getEndTime, new Date());
792
+                  qu1.set(OrderBase::getDealUserCode, mainWorkOrder.getDealUserCode());
793
+                  qu1.set(OrderBase::getDealDept, mainWorkOrder.getDealDept());
794
+                  qu1.set(OrderBase::getDealUserName, mainWorkOrder.getDealUserName());
795
+                  qu1.set(OrderBase::getFile,mainWorkOrder.getFile());
796
+                  qu1.set(OrderBase::getDealContent,mainWorkOrder.getDealContent());
797
+                  boolean n1=orderbaseService.updateBatch(qu1);
798
+                  if (!n1)
799
+                  {
800
+                      return Error("结案失败");
801
+                  }
802
+              }
803
+              return  Success("关联成功");
804
+          }
805
+          else
806
+          {
807
+              return Error("关联失败");
808
+          }
809
+      }
810
+      else
811
+      {
812
+          return Error("工单不存在");
813
+      }
716 814
 
815
+    }
717 816
 
718
-
817
+    private  void overOrder(OrderBase orderBase)
818
+    {
819
+        LambdaUpdateWrapper<OrderBase> qu=new LambdaUpdateWrapper<>();
820
+        qu.eq(OrderBase::getIsDelete,0);
821
+        qu.eq(OrderBase::getCorrelation,orderBase.getCorrelation());
822
+        qu.eq(OrderBase::getIsEnd,0);
823
+        qu.set(OrderBase::getWorkOrderState,  EnumOrderStatus.end.getValue());
824
+        qu.set(OrderBase::getIsEnd, 1);
825
+        qu.set(OrderBase::getEndTime, new Date());
826
+        qu.set(OrderBase::getDealUserCode, orderBase.getDealUserCode());
827
+        qu.set(OrderBase::getDealDept, orderBase.getDealDept());
828
+        qu.set(OrderBase::getDealUserName, orderBase.getDealUserName());
829
+        qu.set(OrderBase::getFile,orderBase.getFile());
830
+        qu.set(OrderBase::getDealContent,orderBase.getDealContent());
831
+        boolean n1=orderbaseService.updateBatch(qu);
832
+    }
719 833
     @ApiOperation(" 接单 code")
720 834
     @Log(title = "接单,参数是code,以后都用code", businessType = BusinessType.OTHER)
721 835
     @PutMapping("/receive")
@@ -807,7 +921,7 @@ public class OrderBaseController extends BaseController {
807 921
         String dealContent="";
808 922
         if(map.get("result")!=null && !StringHelper.isEmpty(map.get("result").toString())){
809 923
             dealContent=",回复内容:"+map.get("result").toString();
810
-
924
+            qw .set(OrderBase::getDealContent,map.get("result").toString());
811 925
         }
812 926
         boolean result =   orderbaseService.updateBatch(qw);
813 927
         if (result) {
@@ -874,6 +988,22 @@ public class OrderBaseController extends BaseController {
874 988
         visitLogService.insert(visitLog);
875 989
 
876 990
         if (result) {
991
+            CompletableFuture.supplyAsync(() -> {
992
+                try {
993
+                    LambdaQueryWrapper<OrderBase> queryWrapper = new LambdaQueryWrapper<>();
994
+                    queryWrapper.eq(OrderBase::getWorkOrderCode, code);
995
+                    queryWrapper.last("limit 1");
996
+                    queryWrapper.orderByDesc(OrderBase::getWorkOrderId);
997
+                    OrderBase  orderBase    = orderbaseService.getEntity(queryWrapper);
998
+                    if (orderBase!=null&&StringHelper.isNotEmpty(orderBase.getCorrelation()))
999
+                    {
1000
+                        overOrder(orderBase);
1001
+                    }
1002
+                } catch (Exception e) {
1003
+                    throw new RuntimeException(e);
1004
+                }
1005
+                return null;
1006
+            }).thenAccept(results -> System.out.println("Result: " + results));
877 1007
             boolean logresult = addlog("回访了工单" , "回访", CurrentUser().getUserName(),
878 1008
                     code , CurrentUser().getNickName(), "");
879 1009
             return Success("回访成功");
@@ -882,6 +1012,25 @@ public class OrderBaseController extends BaseController {
882 1012
         }
883 1013
     }
884 1014
 
885
-
1015
+    @ApiOperation("查找相似工单")
1016
+    @Log(title = "查找相似工单",businessType = BusinessType.QUERY)
1017
+    @PostMapping("/detection")
1018
+    @Anonymous
1019
+    public AjaxResult detection(@RequestBody SimilarOrdersInput input ) {
1020
+        var result = orderbaseService.findSimilarOrders(input.getContent(),input.getTopK());
1021
+        return Success("成功",result);
1022
+    }
1023
+    @ApiOperation("添加历史工单")
1024
+    @Log(title = "添加历史工单",businessType = BusinessType.INSERT)
1025
+    @GetMapping("/addHistorical")
1026
+    @Anonymous
1027
+    public AjaxResult addHistorical() {
1028
+        var list=orderbaseService.getList();
1029
+        for (OrderBase item :list)
1030
+        {
1031
+            orderbaseService.historicalOrders(item);
1032
+        }
1033
+        return  Success("添加工单");
1034
+    }
886 1035
 
887 1036
 }

+ 1 - 0
ltrq-api/src/main/resources/application-dev.yml

@@ -80,3 +80,4 @@ spring:
80 80
   milvusclient:
81 81
     host: 192.168.1.89
82 82
     port: 19530
83
+

+ 9 - 0
ltrq-entity/src/main/java/api/entity/database/order/OrderBase.java

@@ -132,4 +132,13 @@ public class OrderBase {
132 132
     /** 回访人 */
133 133
     @ApiModelProperty("回访人 ")
134 134
     private String visitUser ;
135
+
136
+    /** 关联工单 */
137
+    @ApiModelProperty("关联工单 ")
138
+    private String correlation ;
139
+
140
+    /** 处理结果 */
141
+    @ApiModelProperty("处理结果 ")
142
+    private String dealContent ;
143
+
135 144
 }

+ 14 - 0
ltrq-entity/src/main/java/api/entity/input/dify/WorkflowsInput.java

@@ -0,0 +1,14 @@
1
+package api.entity.input.dify;
2
+
3
+import io.swagger.annotations.ApiModelProperty;
4
+import lombok.Data;
5
+
6
+import java.util.Map;
7
+
8
+@Data
9
+public class WorkflowsInput {
10
+    @ApiModelProperty("允许传入 App 定义的各变量值。 inputs 参数包含了多组键值对")
11
+    private Map<String,Object> inputs;
12
+    @ApiModelProperty("选用助手id")
13
+    private Long id;
14
+}

+ 12 - 0
ltrq-entity/src/main/java/api/entity/input/order/SimilarOrdersInput.java

@@ -0,0 +1,12 @@
1
+package api.entity.input.order;
2
+
3
+import io.swagger.annotations.ApiModelProperty;
4
+import lombok.Data;
5
+
6
+@Data
7
+public class SimilarOrdersInput {
8
+    @ApiModelProperty("内容")
9
+    private  String  content;
10
+    @ApiModelProperty("条数")
11
+    private  Integer topK ;
12
+}

+ 12 - 0
ltrq-entity/src/main/java/api/entity/view/order/SimilarOrdersView.java

@@ -0,0 +1,12 @@
1
+package api.entity.view.order;
2
+
3
+
4
+import api.entity.database.order.OrderBase;
5
+import io.swagger.annotations.ApiModelProperty;
6
+import lombok.Data;
7
+
8
+@Data
9
+public class SimilarOrdersView extends OrderBase {
10
+    @ApiModelProperty("相似度")
11
+    private Float similarity;
12
+}

+ 12 - 0
ltrq-entity/src/main/java/api/entity/view/order/SimilarityView.java

@@ -0,0 +1,12 @@
1
+package api.entity.view.order;
2
+
3
+import io.swagger.annotations.ApiModelProperty;
4
+import lombok.Data;
5
+
6
+@Data
7
+public class SimilarityView {
8
+    @ApiModelProperty("工单id")
9
+    private Long id;
10
+    @ApiModelProperty("相似度")
11
+    private Float similarity;
12
+}

+ 4 - 0
ltrq-service/src/main/java/api/service/dify/IDifyAssistantService.java

@@ -14,6 +14,10 @@ public interface IDifyAssistantService extends IBaseService<DifyAssistant> {
14 14
     //发送对话消息
15 15
     SseEmitter chatMessages(DifyChatMessagesInput input, UserView userView, HttpServletResponse response) throws IOException;
16 16
 
17
+    //发送工作流
18
+    SseEmitter workflows(WorkflowsInput difyInput,
19
+                         UserView userView, HttpServletResponse response) throws IOException;
20
+
17 21
     //消息反馈
18 22
     String feedbacks(DifyFeedbacksInput input,
19 23
                      UserView userView) throws IOException;

+ 103 - 5
ltrq-service/src/main/java/api/service/dify/impl/DifyAssistantServiceImpl.java

@@ -9,6 +9,7 @@ import api.service.dify.IDifyAssistantService;
9 9
 import api.service.BaseServiceImpl;
10 10
 import api.util.helper.HttpHelper;
11 11
 import api.util.helper.StringHelper;
12
+import com.fasterxml.jackson.databind.ObjectMapper;
12 13
 import com.google.gson.Gson;
13 14
 import lombok.var;
14 15
 import org.springframework.stereotype.Service;
@@ -65,10 +66,15 @@ public class DifyAssistantServiceImpl extends BaseServiceImpl<DifyAssistantMappe
65 66
                 builder.append("]");
66 67
                 files=builder.toString();
67 68
             }
68
-
69
+            String jsonString="";
70
+            if (difyInput.getInputs()!=null)
71
+            {
72
+                ObjectMapper objectMapper = new ObjectMapper();
73
+                jsonString= objectMapper.writeValueAsString(difyInput.getInputs());
74
+            }
69 75
             // 2. 创建JSON请求体
70 76
             String jsonBody = "{"
71
-                    + "\"inputs\": {},"
77
+                    + "\"inputs\": "+jsonString+","
72 78
                     + "\"query\": \""+difyInput.getQuery()+"\","
73 79
                     + "\"response_mode\": \"streaming\","
74 80
                     + "\"conversation_id\": \""+difyInput.getConversation_id()+"\","
@@ -98,8 +104,9 @@ public class DifyAssistantServiceImpl extends BaseServiceImpl<DifyAssistantMappe
98 104
                 try {
99 105
                     while ((line = reader.readLine()) != null) {
100 106
                         if (line.startsWith("data: {\"event\": \"message\"") ||line.startsWith("data: {\"event\": \"message_end\"")) {
101
-                            writer.write(line);
102
-                            System.out.println(line);
107
+                            writer.write(unicodeToString(line)+"\n");
108
+                            // sseEmitter.send(unicodeToString(line)); // 实时发送单条结果
109
+                            System.out.println(unicodeToString(line));
103 110
                             writer.flush();
104 111
                         }
105 112
                     }
@@ -117,6 +124,97 @@ public class DifyAssistantServiceImpl extends BaseServiceImpl<DifyAssistantMappe
117 124
         return sseEmitter;
118 125
     }
119 126
 
127
+    //发送工作流
128
+    @Override
129
+    public SseEmitter workflows(WorkflowsInput difyInput,
130
+                                UserView userView, HttpServletResponse response) throws IOException {
131
+        SseEmitter sseEmitter = new SseEmitter();
132
+        // 设置MIME类型为text/event-stream以符合SSE要求
133
+        response.setContentType("text/event-stream");
134
+        response.setCharacterEncoding("UTF-8");
135
+        PrintWriter writer = response.getWriter();
136
+        try {
137
+            var dify=this .getEntity(difyInput.getId());
138
+            // 1. 设置URL和API密钥
139
+            String apiUrl = dify.getUrl()+"/workflows/run";
140
+            String apiKey = dify.getSecretKey(); // 替换为实际API密钥
141
+            String jsonString="";
142
+            if (difyInput.getInputs()!=null)
143
+            {
144
+                ObjectMapper objectMapper = new ObjectMapper();
145
+                jsonString= objectMapper.writeValueAsString(difyInput.getInputs());
146
+            }
147
+
148
+            // 2. 创建JSON请求体
149
+            String jsonBody = "{"
150
+                    + "\"inputs\": "+jsonString+","
151
+                    + "\"response_mode\": \"streaming\","
152
+                    + "\"user\": \""+userView.getUserName()+"\""
153
+                    + "}";
154
+            // 3. 创建HTTP连接
155
+            URL url = new URL(apiUrl);
156
+            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
157
+            conn.setRequestMethod("POST");
158
+            conn.setRequestProperty("Authorization", "Bearer " + apiKey);
159
+            conn.setRequestProperty("Content-Type", "application/json");
160
+            conn.setDoOutput(true);
161
+            // 4. 发送请求体
162
+            try (OutputStream os = conn.getOutputStream()) {
163
+                byte[] input = jsonBody.getBytes(StandardCharsets.UTF_8);
164
+                os.write(input, 0, input.length);
165
+            }
166
+            // 获取响应码
167
+            int responseCode = conn.getResponseCode();
168
+            if (responseCode == HttpURLConnection.HTTP_OK) {
169
+                // 获取响应输入流
170
+                InputStream inputStream = conn.getInputStream();
171
+                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
172
+                String line;
173
+                try {
174
+                    while ((line = reader.readLine()) != null) {
175
+                        writer.write(unicodeToString(line)+"\n");
176
+                        // sseEmitter.send(unicodeToString(line)); // 实时发送单条结果
177
+                        System.out.println(unicodeToString(line));
178
+                        writer.flush();
179
+                    }
180
+                } catch (IOException e) {
181
+                    e.printStackTrace();
182
+                }
183
+            } else {
184
+                System.out.println("POST Request is not successful");
185
+            }
186
+            conn.disconnect();
187
+        } catch (Exception e) {
188
+            e.printStackTrace();
189
+        }
190
+        sseEmitter.complete();
191
+        return sseEmitter;
192
+    }
193
+
194
+    private static String unicodeToString(String unicode) {
195
+        StringBuilder sb = new StringBuilder();
196
+        int i = -1;
197
+        int pos = 0;
198
+
199
+        while ((i = unicode.indexOf("\\u", pos)) != -1) {
200
+            sb.append(unicode.substring(pos, i));
201
+            if (i + 5 > unicode.length()) {
202
+                pos = i + 2;
203
+                continue;
204
+            }
205
+            String hex = unicode.substring(i + 2, i + 6);
206
+            try {
207
+                sb.append((char) Integer.parseInt(hex, 16));
208
+                pos = i + 6;
209
+            } catch (NumberFormatException e) {
210
+                sb.append(unicode.substring(i, i + 2));
211
+                pos = i + 2;
212
+            }
213
+        }
214
+
215
+        sb.append(unicode.substring(pos));
216
+        return sb.toString();
217
+    }
120 218
     //消息反馈
121 219
     @Override
122 220
     public  String feedbacks(DifyFeedbacksInput input,
@@ -135,7 +233,7 @@ public class DifyAssistantServiceImpl extends BaseServiceImpl<DifyAssistantMappe
135 233
     //获取APP的消息点赞和反馈
136 234
     @Override
137 235
     public  String appFeedbacks(PageInput pageInput,long  id
138
-                               ) throws Exception {
236
+    ) throws Exception {
139 237
         var dify=this .getEntity(id);
140 238
         String apiUrl = dify.getUrl()+"/app/feedbacks?page="+pageInput.getPageNum()+"&limit="+pageInput.getPageSize();
141 239
         return   HttpHelper.DifyHttpGet(apiUrl,dify.getSecretKey());

+ 4 - 1
ltrq-service/src/main/java/api/service/order/IOrderBaseService.java

@@ -1,6 +1,7 @@
1 1
 package api.service.order;
2 2
 
3 3
 import api.entity.database.order.OrderBase;
4
+import api.entity.view.order.SimilarOrdersView;
4 5
 import api.service.IBaseService;
5 6
 
6 7
 import java.util.List;
@@ -12,5 +13,7 @@ public interface IOrderBaseService extends IBaseService<OrderBase> {
12 13
     // 添加历史工单
13 14
     void historicalOrders(OrderBase order);
14 15
 
15
-    List<OrderBase> GetOrderSimilarity(OrderBase workOrder);
16
+
17
+    // 查找相似工单
18
+    List<SimilarOrdersView> findSimilarOrders(String content, Integer topK);
16 19
 }

+ 48 - 15
ltrq-service/src/main/java/api/service/order/impl/OrderBaseServiceImpl.java

@@ -1,16 +1,21 @@
1 1
 package api.service.order.impl;
2 2
 
3 3
 import api.entity.database.order.OrderBase;
4
+import api.entity.view.call.CallLogView;
4 5
 import api.entity.view.order.CustomSorterStream;
6
+import api.entity.view.order.SimilarOrdersView;
7
+import api.entity.view.order.SimilarityView;
5 8
 import api.mapper.order.OrderBaseMapper;
6 9
 import api.service.order.IOrderBaseService;
7 10
 import api.service.BaseServiceImpl;
8 11
 import api.util.helper.MilvusClientHelper;
12
+import com.alibaba.fastjson2.JSON;
9 13
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
10 14
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
11 15
 import com.google.common.hash.Hashing;
12 16
 import com.hankcs.hanlp.HanLP;
13 17
 import com.hankcs.hanlp.seg.common.Term;
18
+import lombok.var;
14 19
 import org.springframework.stereotype.Service;
15 20
 import org.springframework.transaction.annotation.Transactional;
16 21
 
@@ -73,24 +78,54 @@ public class OrderBaseServiceImpl extends BaseServiceImpl<OrderBaseMapper, Order
73 78
     }
74 79
 
75 80
     // 查找相似工单
76
-    public List<OrderBase> findSimilarOrders(OrderBase newOrder, int topK) {
77
-        // 预处理文本
78
-        List<String> terms = preprocess(  newOrder.getContent());
79
-
80
-        String text =newOrder.getContent();
81
+    @Override
82
+    public List<SimilarOrdersView> findSimilarOrders(String content, Integer topK) {
83
+        String text =content;
81 84
         List<String> words = preprocess(text);
82 85
         float[] vector = vectorize(words);
83
-
86
+        if (topK==null)
87
+        {
88
+            topK=5;
89
+        }
84 90
         // 在Milvus中搜索相似工单
85
-        List<Long> similarOrderIds = milvusClient.searchSimilarOrders(vector, topK);
86
-
87
-        if (similarOrderIds.size()>0)
91
+        List<Map<String,Object>>   similarOrder = milvusClient.searchSimilarOrders(vector, topK);
92
+        if (similarOrder.size()>0)
88 93
         {
89 94
             LambdaQueryWrapper<OrderBase> qw = new LambdaQueryWrapper<>();
90
-            qw.in( OrderBase::getWorkOrderId, similarOrderIds);
95
+
96
+            List<Long> ids = similarOrder.stream()
97
+                    .map(map -> map.get("Id"))
98
+                    .filter(Objects::nonNull)
99
+                    .map(value -> {
100
+                        try {
101
+                            return Long.valueOf(value.toString());
102
+                        } catch (NumberFormatException e) {
103
+                            return null; // 或者使用Optional处理异常
104
+                        }
105
+                    })
106
+                    .filter(Objects::nonNull)
107
+                    .collect(Collectors.toList());
108
+            qw.in( OrderBase::getWorkOrderId, ids);
91 109
             qw.orderByDesc(OrderBase::getWorkOrderId);
92 110
             List<OrderBase> list=this.getList(qw);
93
-            return CustomSorterStream.sortByTargetOrder(list, similarOrderIds, OrderBase::getWorkOrderId);
111
+            List<SimilarOrdersView>  similarOrdersViews=  JSON.parseArray(JSON.toJSONString(list),SimilarOrdersView.class);
112
+            for(SimilarOrdersView view :similarOrdersViews)
113
+            {
114
+                Float Similarity = similarOrder.stream()
115
+                        .filter(map -> {
116
+                            Object idValue = map.get("Id");
117
+                            return idValue != null && idValue.toString().equals(view.getWorkOrderId().toString());
118
+                        })
119
+                        .map(map -> (Float) map.get("Similarity"))
120
+                        .findFirst()
121
+                        .orElse(null);
122
+                if (Similarity!=null)
123
+                {
124
+                    view.setSimilarity(Similarity);
125
+                }
126
+
127
+            }
128
+            return CustomSorterStream.sortByTargetOrder(similarOrdersViews, ids, SimilarOrdersView::getWorkOrderId);
94 129
         }
95 130
         else
96 131
         {
@@ -108,8 +143,6 @@ public class OrderBaseServiceImpl extends BaseServiceImpl<OrderBaseMapper, Order
108 143
                 .filter(word -> word.length() > 1 && !STOP_WORDS.contains(word))
109 144
                 .collect(Collectors.toList());
110 145
     }
111
-    @Override
112
-    public List<OrderBase> GetOrderSimilarity(OrderBase workOrder) {
113
-        return  findSimilarOrders(workOrder,5);
114
-    }
146
+
147
+
115 148
 }

+ 10 - 0
ltrq-util/pom.xml

@@ -131,6 +131,16 @@
131 131
                 </exclusion>
132 132
             </exclusions>
133 133
         </dependency>
134
+        <dependency>
135
+            <groupId>com.google.protobuf</groupId>
136
+            <artifactId>protobuf-java</artifactId>
137
+            <version>3.21.12</version>  <!-- 使用兼容版本 -->
138
+        </dependency>
139
+        <dependency>
140
+            <groupId>com.google.protobuf</groupId>
141
+            <artifactId>protobuf-java-util</artifactId>
142
+            <version>3.21.12</version>
143
+        </dependency>
134 144
 
135 145
     </dependencies>
136 146
 

+ 46 - 11
ltrq-util/src/main/java/api/util/helper/MilvusClientHelper.java

@@ -1,22 +1,23 @@
1 1
 package api.util.helper;
2 2
 import io.milvus.client.MilvusServiceClient;
3 3
 import io.milvus.grpc.DataType;
4
+import io.milvus.grpc.MutationResult;
4 5
 import io.milvus.param.ConnectParam;
5 6
 import io.milvus.param.IndexType;
6 7
 import io.milvus.param.MetricType;
7 8
 import io.milvus.param.R;
8 9
 import io.milvus.param.RpcStatus;
9 10
 import io.milvus.param.collection.*;
11
+import io.milvus.param.dml.DeleteParam;
10 12
 import io.milvus.param.dml.InsertParam;
11 13
 import io.milvus.param.dml.SearchParam;
14
+import io.milvus.param.highlevel.dml.DeleteIdsParam;
12 15
 import io.milvus.param.index.CreateIndexParam;
13 16
 import io.milvus.response.SearchResultsWrapper;
14 17
 import lombok.extern.slf4j.Slf4j;
18
+import org.apache.commons.lang3.StringUtils;
15 19
 
16
-import java.util.ArrayList;
17
-import java.util.Arrays;
18
-import java.util.Collections;
19
-import java.util.List;
20
+import java.util.*;
20 21
 import java.util.stream.Collectors;
21 22
 @Slf4j
22 23
 public class MilvusClientHelper {
@@ -27,6 +28,7 @@ public class MilvusClientHelper {
27 28
     public static final String VECTOR_FIELD = "vector";
28 29
     private static final String ID_FIELD = "order_id";
29 30
     public static final int VECTOR_DIM = 1024; // 向量维度
31
+    public static final float score = 0.6F; // 向量维度
30 32
     private final MilvusServiceClient client;
31 33
 
32 34
     public MilvusClientHelper() {
@@ -38,7 +40,7 @@ public class MilvusClientHelper {
38 40
         client = new MilvusServiceClient(connectParam);
39 41
 
40 42
         // 初始化集合
41
-    //    initCollection();
43
+        initCollection();
42 44
     }
43 45
 
44 46
     private void initCollection() {
@@ -82,7 +84,7 @@ public class MilvusClientHelper {
82 84
             client.createIndex(createIndexParam);
83 85
             System.out.println("Milvus集合创建成功: " + COLLECTION_NAME);
84 86
         }
85
-        loadCollection();
87
+     //   loadCollection();
86 88
     }
87 89
 
88 90
     // 插入工单向量
@@ -106,6 +108,29 @@ public class MilvusClientHelper {
106 108
                 .addCollectionName(COLLECTION_NAME)
107 109
                 .build());
108 110
     }
111
+
112
+    public void deleteTickets(List<Long> ticketIds) {
113
+        if (ticketIds == null || ticketIds.isEmpty()) return;
114
+
115
+        // 构建删除表达式
116
+        String expr = ID_FIELD+" in [" + StringUtils.join(ticketIds, ",") + "]";
117
+
118
+        DeleteParam deleteParam = DeleteParam.newBuilder()
119
+                .withCollectionName(COLLECTION_NAME)
120
+                .withExpr(expr)
121
+                .build();
122
+
123
+        R<MutationResult> deleteRes = client.delete(deleteParam);
124
+        if (deleteRes.getStatus() != R.Status.Success.getCode()) {
125
+            throw new RuntimeException("删除失败: " + deleteRes.getMessage());
126
+        }
127
+
128
+        // 刷新删除操作
129
+        client.flush(FlushParam.newBuilder()
130
+                .addCollectionName(COLLECTION_NAME)
131
+                .build());
132
+    }
133
+
109 134
     // 加载集合到内存
110 135
     public void loadCollection() {
111 136
         try {
@@ -145,7 +170,7 @@ public class MilvusClientHelper {
145 170
     }
146 171
 
147 172
     // 搜索相似工单
148
-    public List<Long> searchSimilarOrders(float [] vector, int topK) {
173
+    public List<Map<String,Object>>  searchSimilarOrders(float [] vector, int topK) {
149 174
 
150 175
         List<Float> vectorList = new ArrayList<>(vector.length);
151 176
         for (float v : vector) {
@@ -161,6 +186,7 @@ public class MilvusClientHelper {
161 186
         // 构建搜索参数
162 187
         List<String> outputFields = Arrays.asList(ID_FIELD);
163 188
         List<List<Float>> searchVectors = Arrays.asList(vectorList);
189
+        List<Map<String,Object>> maps=new ArrayList<>();
164 190
 
165 191
         SearchParam searchParam = SearchParam.newBuilder()
166 192
                 .withCollectionName(COLLECTION_NAME)
@@ -176,10 +202,19 @@ public class MilvusClientHelper {
176 202
         R<io.milvus.grpc.SearchResults> response = client.search(searchParam);
177 203
         // 处理结果
178 204
         SearchResultsWrapper wrapper = new SearchResultsWrapper(response.getData().getResults());
179
-        return wrapper.getIDScore(0).stream()
180
-                .filter(x->x .getScore()>0.6)
181
-                .map(SearchResultsWrapper.IDScore::getLongID)
182
-                .collect(Collectors.toList());
205
+
206
+        for ( SearchResultsWrapper.IDScore item: wrapper.getIDScore(0))
207
+        {
208
+            if (item.getScore()>score)
209
+            {
210
+                Map<String,Object> map=new HashMap<>();
211
+                map.put("Similarity",item.getScore());
212
+                map.put("Id",item.getLongID());
213
+                maps.add(map);
214
+            }
215
+        }
216
+
217
+        return maps;
183 218
     }
184 219
 
185 220
     // 归一化向量(用于余弦相似度计算)