From 0ffdf00009b0bede0859fa33deddefb55c075a7b Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期日, 01 二月 2026 16:42:36 +0800
Subject: [PATCH] feat:优化增加任务同步接口,允许前端手动控制同步
---
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/HospDataController.java | 2
ruoyi-common/src/main/java/com/ruoyi/common/utils/image/package-info.java | 63 ++++
ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml | 29 +
ruoyi-system/src/main/java/com/ruoyi/system/controller/OCRController.java | 35 +-
ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java | 89 +++++
ruoyi-ui/src/views/task/general/detail.vue | 57 +++
app/pagesTask/create-emergency.vue | 96 ++++--
ruoyi-common/src/main/java/com/ruoyi/common/utils/HospitalTokenizerUtil.java | 17
ruoyi-common/src/main/java/com/ruoyi/common/utils/image/ImageCompressUtil.java | 374 ++++++++++++++++++++++++
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java | 16
ruoyi-system/src/main/java/com/ruoyi/system/utils/TencentOCRUtil.java | 79 ++++
ruoyi-ui/src/api/task.js | 18 +
12 files changed, 802 insertions(+), 73 deletions(-)
diff --git a/app/pagesTask/create-emergency.vue b/app/pagesTask/create-emergency.vue
index e68decb..d1adac9 100644
--- a/app/pagesTask/create-emergency.vue
+++ b/app/pagesTask/create-emergency.vue
@@ -2006,6 +2006,14 @@
// - YYYYMMDD
// - yyyy-MM-dd HH:mm:ss
console.log('灏濊瘯鏍煎紡鍖栨棩鏈熷瓧绗︿覆:', dateStr)
+
+ // 濡傛灉杈撳叆涓虹┖鎴栨棤鏁堬紝杩斿洖绌哄瓧绗︿覆
+ if (!dateStr || typeof dateStr !== 'string') {
+ console.warn('鏃ユ湡瀛楃涓叉棤鏁�:', dateStr)
+ return ''
+ }
+
+ // 娓呮礂鏃ユ湡瀛楃涓�
let cleaned = dateStr
.replace(/[骞存湀]/g, '-')
.replace(/[鏃ュ彿]/g, ' ') // 鏃�/鍙� 鈫� 绌烘牸锛屼繚鐣欐棩鏈熷拰鏃堕棿鐨勫垎闅�
@@ -2014,50 +2022,76 @@
.replace(/绉�/g, '')
.replace(/\s+/g, ' ') // 澶氫釜绌烘牸鍚堝苟涓轰竴涓�
.trim()
+
console.log('娓呯悊鍚庣殑鏃ユ湡瀛楃涓�:', cleaned)
+
+ // 鍒嗙鏃ユ湡鍜屾椂闂撮儴鍒�
+ const parts = cleaned.split(' ')
+ let datePart = parts[0] || ''
+ let timePart = parts[1] || ''
+
let dateResult = ''
+ // 澶勭悊鏃ユ湡閮ㄥ垎
// 濡傛灉鏄痀YMMDD鏍煎紡
- if (/^\d{6}$/.test(cleaned)) {
- const year = '20' + cleaned.substring(0, 2)
- const month = cleaned.substring(2, 4)
- const day = cleaned.substring(4, 6)
- dateResult = `${year}-${month}-${day}`;
- }
- // 濡傛灉鏄痀YYYMMDD鏍煎紡
- else if (/^\d{8}$/.test(cleaned)) {
- const year = cleaned.substring(0, 4)
- const month = cleaned.substring(4, 6)
- const day = cleaned.substring(6, 8)
+ if (/^\d{6}$/.test(datePart)) {
+ const year = '20' + datePart.substring(0, 2)
+ const month = datePart.substring(2, 4)
+ const day = datePart.substring(4, 6)
dateResult = `${year}-${month}-${day}`
}
- // 濡傛灉宸茬粡鏄悎鐞嗘牸寮忥紝鐩存帴浣跨敤
- else if (cleaned.match(/^\d{4}[-/]\d{1,2}[-/]\d{1,2}$/)) {
- dateResult = cleaned.replace(/[//]/g, '-')
+ // 濡傛灉鏄痀YYYMMDD鏍煎紡
+ else if (/^\d{8}$/.test(datePart)) {
+ const year = datePart.substring(0, 4)
+ const month = datePart.substring(4, 6)
+ const day = datePart.substring(6, 8)
+ dateResult = `${year}-${month}-${day}`
}
- // 濡傛灉宸茬粡鍖呭惈鏃跺垎绉掞紝鐩存帴杩斿洖
- else if (cleaned.match(/^\d{4}[-/]\d{1,2}[-/]\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2}$/)) {
- return cleaned.replace(/[//]/g, '-')
- }
- // 濡傛灉鍖呭惈鏃跺垎浣嗙己灏戠锛坹yyy-MM-dd HH:mm:锛�
- else if (cleaned.match(/^\d{4}[-/]\d{1,2}[-/]\d{1,2}\s+\d{1,2}:\d{1,2}:$/)) {
- // 鍘绘帀鏈熬鐨勫啋鍙凤紝琛ヤ笂绉掓暟00
- return cleaned.replace(/[//]/g, '-').replace(/:$/, '') + ':00'
- }
- // 濡傛灉鍙寘鍚椂鍒嗭紙yyyy-MM-dd HH:mm锛�
- else if (cleaned.match(/^\d{4}[-/]\d{1,2}[-/]\d{1,2}\s+\d{1,2}:\d{1,2}$/)) {
- return cleaned.replace(/[//]/g, '-') + ':00'
+ // 濡傛灉鏄痽yyy-MM-dd鎴杫yyy/MM/dd鏍煎紡
+ else if (datePart.match(/^\d{4}[-\/]\d{1,2}[-\/]\d{1,2}$/)) {
+ dateResult = datePart.replace(/\//g, '-')
}
else {
- dateResult = dateStr
+ dateResult = datePart
}
- // 濡傛灉鏃ユ湡鏍煎紡姝g‘锛屾坊鍔犻粯璁ゆ椂鍒嗙 00:00:00
- if (dateResult && dateResult.match(/^\d{4}-\d{1,2}-\d{1,2}$/)) {
- return dateResult + ' 00:00:00'
+ // 楠岃瘉鏃ユ湡閮ㄥ垎鏄惁鏈夋晥
+ if (!dateResult.match(/^\d{4}-\d{1,2}-\d{1,2}$/)) {
+ console.warn('鏃ユ湡鏍煎紡涓嶆纭�:', dateResult)
+ return ''
}
- return dateResult
+ // 澶勭悊鏃堕棿閮ㄥ垎
+ let timeResult = '00:00:00' // 榛樿鏃堕棿
+
+ if (timePart) {
+ // 绉婚櫎鏈熬澶氫綑鐨勫啋鍙�
+ timePart = timePart.replace(/:+$/, '')
+
+ // 鍒嗗壊鏃躲�佸垎銆佺
+ const timeParts = timePart.split(':')
+ const hour = timeParts[0] || '00'
+ const minute = timeParts[1] || '00'
+ const second = timeParts[2] || '00'
+
+ // 楠岃瘉鏃堕棿鏁板瓧鏄惁鏈夋晥
+ const hourNum = parseInt(hour, 10)
+ const minuteNum = parseInt(minute, 10)
+ const secondNum = parseInt(second, 10)
+
+ if (!isNaN(hourNum) && !isNaN(minuteNum) && !isNaN(secondNum) &&
+ hourNum >= 0 && hourNum < 24 && minuteNum >= 0 && minuteNum < 60 && secondNum >= 0 && secondNum < 60) {
+ // 琛ラ綈涓や綅鏁�
+ timeResult = `${String(hourNum).padStart(2, '0')}:${String(minuteNum).padStart(2, '0')}:${String(secondNum).padStart(2, '0')}`
+ } else {
+ console.warn('鏃堕棿鏁板�艰秴鍑鸿寖鍥达紝浣跨敤榛樿鍊�00:00:00')
+ }
+ }
+
+ const finalResult = `${dateResult} ${timeResult}`
+ console.log('鏈�缁堟牸寮忓寲缁撴灉:', finalResult)
+
+ return finalResult
}
}
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/HospDataController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/HospDataController.java
index d17147c..5904fca 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/HospDataController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/HospDataController.java
@@ -39,7 +39,7 @@
/**
* 鍖婚櫌鎼滅储鏈�浣庡尮閰嶅垎鏁伴槇鍊硷紙浣庝簬姝ゅ垎鏁扮殑缁撴灉灏嗚杩囨护锛�
*/
- private static final int MIN_MATCH_SCORE_THRESHOLD = 50;
+ private static final int MIN_MATCH_SCORE_THRESHOLD = 1;
@Autowired
private HospDataMapper hospDataMapper;
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java
index 56ad818..36a79da 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java
@@ -11,6 +11,8 @@
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.SysTaskEmergency;
import com.ruoyi.system.service.*;
+import com.ruoyi.system.service.ILegacySystemSyncService;
+import com.ruoyi.system.service.ITaskDispatchSyncService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
@@ -70,6 +72,12 @@
@Autowired
@Qualifier("tiandituMapService")
private IMapService mapService;
+
+ @Autowired
+ private ILegacySystemSyncService legacySystemSyncService;
+
+ @Autowired
+ private ITaskDispatchSyncService taskDispatchSyncService;
/**
* 鏌ヨ浠诲姟绠$悊鍒楄〃锛堝悗鍙扮鐞嗙锛�
@@ -615,4 +623,85 @@
this.actualEndTime = actualEndTime;
}
}
+
+ /**
+ * 鎵嬪姩鍚屾鏈嶅姟鍗曞埌鏃х郴缁�
+ * 褰撴湇鍔″崟鍚屾澶辫触鎴栨湭鍚屾鏃讹紝鍙互閫氳繃姝ゆ帴鍙f墜鍔ㄨЕ鍙戝悓姝�
+ */
+ @PreAuthorize("@ss.hasPermi('task:general:edit')")
+ @Log(title = "鎵嬪姩鍚屾鏈嶅姟鍗�", businessType = BusinessType.UPDATE)
+ @PostMapping("/syncServiceOrder/{taskId}")
+ public AjaxResult syncServiceOrder(@PathVariable Long taskId) {
+ try {
+ // 鏌ヨ浠诲姟淇℃伅
+ SysTask task = sysTaskService.selectSysTaskByTaskId(taskId);
+ if (task == null) {
+ return error("浠诲姟涓嶅瓨鍦�");
+ }
+
+ // 鍙敮鎸佹�ユ晳杞繍浠诲姟
+ if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
+ return error("鍙湁鎬ユ晳杞繍浠诲姟鎵嶈兘鍚屾鍒版棫绯荤粺");
+ }
+
+ // 璋冪敤鍚屾鏈嶅姟
+ Long serviceOrdId = legacySystemSyncService.syncEmergencyTaskToLegacy(taskId);
+
+ if (serviceOrdId != null && serviceOrdId > 0) {
+ return success("鏈嶅姟鍗曞悓姝ユ垚鍔燂紝ServiceOrdID: " + serviceOrdId);
+ } else {
+ return error("鏈嶅姟鍗曞悓姝ュけ璐ワ紝璇锋煡鐪嬪悓姝ラ敊璇俊鎭�");
+ }
+
+ } catch (Exception e) {
+ logger.error("鎵嬪姩鍚屾鏈嶅姟鍗曞紓甯革紝taskId: {}", taskId, e);
+ return error("鍚屾寮傚父: " + e.getMessage());
+ }
+ }
+
+ /**
+ * 鎵嬪姩鍚屾璋冨害鍗曞埌鏃х郴缁�
+ * 褰撹皟搴﹀崟鍚屾澶辫触鎴栨湭鍚屾鏃讹紝鍙互閫氳繃姝ゆ帴鍙f墜鍔ㄨЕ鍙戝悓姝�
+ */
+ @PreAuthorize("@ss.hasPermi('task:general:edit')")
+ @Log(title = "鎵嬪姩鍚屾璋冨害鍗�", businessType = BusinessType.UPDATE)
+ @PostMapping("/syncDispatchOrder/{taskId}")
+ public AjaxResult syncDispatchOrder(@PathVariable Long taskId) {
+ try {
+ // 鏌ヨ浠诲姟淇℃伅
+ SysTask task = sysTaskService.selectSysTaskByTaskId(taskId);
+ if (task == null) {
+ return error("浠诲姟涓嶅瓨鍦�");
+ }
+
+ // 鍙敮鎸佹�ユ晳杞繍浠诲姟
+ if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
+ return error("鍙湁鎬ユ晳杞繍浠诲姟鎵嶈兘鍚屾鍒版棫绯荤粺");
+ }
+
+ // 鏌ヨ鎬ユ晳杞繍鎵╁睍淇℃伅
+ SysTaskEmergency emergency = sysTaskEmergencyService.selectSysTaskEmergencyByTaskId(taskId);
+ if (emergency == null) {
+ return error("鎬ユ晳杞繍鎵╁睍淇℃伅涓嶅瓨鍦�");
+ }
+
+ // 蹇呴』鍏堟湁鏈嶅姟鍗�
+ if (emergency.getLegacyServiceOrdId() == null || emergency.getLegacyServiceOrdId() <= 0) {
+ return error("璇峰厛鍚屾鏈嶅姟鍗�");
+ }
+
+ // 璋冪敤鍚屾鏈嶅姟
+ Long dispatchOrdId = taskDispatchSyncService.syncDispatch(taskId);
+
+ if (dispatchOrdId != null && dispatchOrdId > 0) {
+ return success("璋冨害鍗曞悓姝ユ垚鍔燂紝DispatchOrdID: " + dispatchOrdId);
+ } else {
+ return error("璋冨害鍗曞悓姝ュけ璐ワ紝璇锋煡鐪嬪悓姝ラ敊璇俊鎭�");
+ }
+
+ } catch (Exception e) {
+ logger.error("鎵嬪姩鍚屾璋冨害鍗曞紓甯革紝taskId: {}", taskId, e);
+ return error("鍚屾寮傚父: " + e.getMessage());
+ }
+ }
}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/HospitalTokenizerUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/HospitalTokenizerUtil.java
index 839d971..bb7c8ba 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/HospitalTokenizerUtil.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/HospitalTokenizerUtil.java
@@ -25,7 +25,7 @@
private static final Set<String> STOP_WORDS = new HashSet<>(Arrays.asList(
"鍖婚櫌", "璇婃墍", "鍗敓", "闀�", "涔�",
"琛楅亾", "璺�", "鍙�", "鏍�", "鍗曞厓", "瀹�", "灞�", "妤�", "鐨�", "浜�",
- "鍦�", "涓�", "鍜�", "鍙�", "绛�", "涔�", "浜�", "涓�", "鏈�", "鏃�"
+ "鍦�", "涓�", "鍜�", "鍙�", "绛�", "涔�", "浜�", "涓�", "鏈�", "鏃�","(",")","锛�","锛�","銆�","锛�","銆�","锛�","锛�","锛�","锛�","鈥�","鈥�","鈥�","鈥�"
));
/**
@@ -35,8 +35,10 @@
private static final Set<String> HIGH_WEIGHT_WORDS = new HashSet<>(Arrays.asList(
"浜烘皯", "涓尰", "涓タ鍖�", "涓タ鍖荤粨鍚�", "鍖荤枟", "濡囧辜", "鍎跨", "鑲ょ",
"鍙h厰", "鐪肩", "楠ㄧ", "鏁村舰", "绮剧", "搴峰", "鎬ユ晳", "鍖诲闄�",
- "鍖荤澶у", "涓撶", "绗竴", "绗簩", "绗笁", "绗洓", "绗簲",
- "鍐涘尯", "鍐涘尰", "涓績", "闄勫睘", "鐪佺珛", "甯傜珛", "鍖虹珛"
+ "鍖荤澶у", "涓撶",
+ "鍐涘尯", "鍐涘尰", "涓績", "闄勫睘", "鐪佺珛", "甯傜珛", "鍖虹珛", "鑴戠", "鎬婚櫌", "鎱堝杽", "淇濆仴闄�", "鍙h厰", "绁堢", "鐪肩", "閾佽矾", "闄勪竴", "闄勪簩", "闄勪笁", "闄勫洓", "闄勪簲", "闄勫叚",
+ "绗竴", "绗簩", "绗笁", "绗洓", "绗簲", "绗叚", "绗竷", "绗叓", "绗節", "绗崄",
+ "鑲跨槫"
));
/**
@@ -46,7 +48,7 @@
private static final Set<String> HOSPITAL_KEYWORD_DICT = new HashSet<>(Arrays.asList(
"涓尰闄�", "涓尰鍖婚櫌", "甯傚尰闄�", "鐪佸尰闄�", "浜烘皯鍖婚櫌", "涓績鍖婚櫌", "鍙h厰鍖婚櫌",
"鍗庝鲸鍖婚櫌", "鍎跨鍖婚櫌", "鐪肩涓績", "绂忓埄闄�", "闂ㄨ瘖閮�", "涓北澶у", "闄勫睘鍖婚櫌",
- "瀛欓�镐粰"
+ "瀛欓�镐粰","闂ㄨ瘖"
));
/** 缁勫悎璇嶇敓鎴愮殑鏈�灏忓瓧绗﹂暱搴� */
@@ -568,8 +570,11 @@
// 鍒嗛櫌鐗瑰緛鍏抽敭璇�
String[] branchKeywords = {
- "鍒嗛櫌", "鍒嗛儴", "闂ㄨ瘖閮�", "绀惧尯鍗敓", "鍗敓绔�", "鍗敓鏈嶅姟涓績",
- "涓滈櫌", "瑗块櫌", "鍗楅櫌", "鍖楅櫌", "鏂伴櫌", "鑰侀櫌"
+ "鍒嗛櫌", "鍒嗛儴", "闂ㄨ瘖閮�","闂ㄨ瘖", "绀惧尯鍗敓", "鍗敓绔�", "鍗敓鏈嶅姟涓績",
+ "涓滈櫌", "瑗块櫌", "鍗楅櫌", "鍖楅櫌", "鏂伴櫌", "鑰侀櫌",
+ "浜烘皯鍖婚櫌","闄勫睘鍖婚櫌","绂忓埄闄�","鍒嗛櫌"
+
+
};
for (String keyword : branchKeywords) {
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/image/ImageCompressUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/image/ImageCompressUtil.java
new file mode 100644
index 0000000..a79f960
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/image/ImageCompressUtil.java
@@ -0,0 +1,374 @@
+package com.ruoyi.common.utils.image;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.imageio.IIOImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+import javax.imageio.stream.ImageOutputStream;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+
+/**
+ * 鍥剧墖鍘嬬缉宸ュ叿绫�
+ * 涓撲负OCR璇嗗埆浼樺寲锛屽湪淇濊瘉鏂囧瓧娓呮櫚搴︾殑鍓嶆彁涓嬪帇缂╁浘鐗囧ぇ灏�
+ *
+ * @author ruoyi
+ * @date 2025-01-20
+ */
+public class ImageCompressUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(ImageCompressUtil.class);
+
+ /**
+ * 榛樿鏈�澶ф枃浠跺ぇ灏忥紙10MB锛�
+ */
+ public static final long DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
+
+ /**
+ * OCR鏈�浣宠瘑鍒垎杈ㄧ巼锛堟渶灏忚竟鍍忕礌锛�
+ */
+ public static final int OCR_OPTIMAL_MIN_SIZE = 1500;
+
+ /**
+ * 楂樿川閲忓帇缂╄川閲忓弬鏁帮紙0.90 = 90%璐ㄩ噺锛�
+ */
+ public static final float HIGH_QUALITY = 0.90f;
+
+ /**
+ * 涓瓑璐ㄩ噺鍘嬬缉璐ㄩ噺鍙傛暟锛�0.80 = 80%璐ㄩ噺锛�
+ */
+ public static final float MEDIUM_QUALITY = 0.80f;
+
+ /**
+ * 浣庤川閲忓帇缂╄川閲忓弬鏁帮紙0.75 = 75%璐ㄩ噺锛�
+ */
+ public static final float LOW_QUALITY = 0.75f;
+
+ /**
+ * 鏅鸿兘鍘嬬缉鍥剧墖锛堥拡瀵筄CR浼樺寲锛�
+ * 浣跨敤榛樿3MB闄愬埗
+ *
+ * @param file 涓婁紶鐨勫浘鐗囨枃浠�
+ * @return 鍘嬬缉鍚庣殑涓存椂鏂囦欢
+ * @throws IOException IO寮傚父
+ */
+ public static File compressForOCR(MultipartFile file) throws IOException {
+ return compressForOCR(file, DEFAULT_MAX_FILE_SIZE);
+ }
+
+ /**
+ * 鏅鸿兘鍘嬬缉鍥剧墖锛堥拡瀵筄CR浼樺寲锛�
+ * 淇濊瘉璇嗗埆鍑嗙‘鐜囩殑鍚屾椂鍘嬬缉鍒版寚瀹氬ぇ灏忎互涓�
+ *
+ * @param file 涓婁紶鐨勫浘鐗囨枃浠�
+ * @param maxSize 鏈�澶ф枃浠跺ぇ灏忥紙瀛楄妭锛�
+ * @return 鍘嬬缉鍚庣殑涓存椂鏂囦欢
+ * @throws IOException IO寮傚父
+ */
+ public static File compressForOCR(MultipartFile file, long maxSize) throws IOException {
+ long fileSize = file.getSize();
+
+ // 濡傛灉鏂囦欢灏忎簬闄愬埗锛岀洿鎺ヤ繚瀛�
+ if (fileSize <= maxSize) {
+ log.debug("鍥剧墖澶у皬 {} KB 鏈秴杩囬檺鍒� {} KB锛屾棤闇�鍘嬬缉",
+ fileSize / 1024.0, maxSize / 1024.0);
+ return saveToTempFile(file);
+ }
+
+ log.info("鍥剧墖澶у皬 {} MB 瓒呰繃闄愬埗 {} MB锛屽紑濮嬫櫤鑳藉帇缂�...",
+ fileSize / 1024.0 / 1024.0, maxSize / 1024.0 / 1024.0);
+
+ // 璇诲彇鍘熷鍥剧墖
+ BufferedImage originalImage = ImageIO.read(file.getInputStream());
+ if (originalImage == null) {
+ throw new IOException("鏃犳硶璇诲彇鍥剧墖鏂囦欢锛屽彲鑳芥牸寮忎笉鏀寔");
+ }
+
+ int originalWidth = originalImage.getWidth();
+ int originalHeight = originalImage.getHeight();
+ log.info("鍘熷鍥剧墖灏哄: {}x{}", originalWidth, originalHeight);
+
+ // 绛栫暐1锛氬厛灏濊瘯楂樿川閲廕PEG鍘嬬缉锛堜笉鏀瑰彉灏哄锛�
+ File compressedFile = compressWithQuality(originalImage, file.getOriginalFilename(), HIGH_QUALITY);
+
+ if (compressedFile.length() <= maxSize) {
+ log.info("鍘嬬缉鎴愬姛锛堥珮璐ㄩ噺鍘嬬缉锛夛紝鏂囦欢澶у皬: {} MB",
+ compressedFile.length() / 1024.0 / 1024.0);
+ return compressedFile;
+ }
+
+ // 绛栫暐2锛氬鏋滆繕鏄お澶э紝閫傚害缂╁皬灏哄锛堜繚璇丱CR璇嗗埆锛�
+ double scaleFactor = calculateScaleFactor(originalWidth, originalHeight, maxSize, compressedFile.length());
+
+ if (scaleFactor < 1.0) {
+ int newWidth = (int) (originalWidth * scaleFactor);
+ int newHeight = (int) (originalHeight * scaleFactor);
+ log.info("璋冩暣鍥剧墖灏哄鑷�: {}x{} (缂╂斁姣斾緥: {}%)",
+ newWidth, newHeight, (int)(scaleFactor * 100));
+
+ BufferedImage resizedImage = resizeImageHighQuality(originalImage, newWidth, newHeight);
+ compressedFile.delete(); // 鍒犻櫎涔嬪墠鐨勪复鏃舵枃浠�
+ compressedFile = compressWithQuality(resizedImage, file.getOriginalFilename(), HIGH_QUALITY);
+ }
+
+ // 绛栫暐3锛氬鏋滆繕鏄お澶э紝闄嶄綆鍘嬬缉璐ㄩ噺锛堟渶鍚庢墜娈碉級
+ if (compressedFile.length() > maxSize) {
+ log.warn("灏哄璋冩暣鍚庝粛瓒呴檺锛岄檷浣庡帇缂╄川閲�");
+ BufferedImage finalImage;
+ if (scaleFactor < 1.0) {
+ int newWidth = (int) (originalWidth * scaleFactor);
+ int newHeight = (int) (originalHeight * scaleFactor);
+ finalImage = resizeImageHighQuality(originalImage, newWidth, newHeight);
+ } else {
+ finalImage = originalImage;
+ }
+
+ compressedFile.delete(); // 鍒犻櫎涔嬪墠鐨勪复鏃舵枃浠�
+
+ // 灏濊瘯涓瓑璐ㄩ噺
+ compressedFile = compressWithQuality(finalImage, file.getOriginalFilename(), MEDIUM_QUALITY);
+
+ // 濡傛灉杩樹笉琛岋紝浣跨敤浣庤川閲�
+ if (compressedFile.length() > maxSize) {
+ log.warn("浣跨敤浣庤川閲忓帇缂╋紙75%锛�");
+ compressedFile.delete();
+ compressedFile = compressWithQuality(finalImage, file.getOriginalFilename(), LOW_QUALITY);
+ }
+ }
+
+ long finalSize = compressedFile.length();
+ double compressionRatio = (1 - (double)finalSize / fileSize) * 100;
+ log.info("鏈�缁堝帇缂╁畬鎴愶紝鏂囦欢澶у皬: {} MB (鍘嬬缉鐜�: {}%)",
+ finalSize / 1024.0 / 1024.0, (int)compressionRatio);
+
+ if (finalSize > maxSize) {
+ log.warn("璀﹀憡锛氬帇缂╁悗鏂囦欢澶у皬 {} MB 浠嶈秴杩囬檺鍒� {} MB",
+ finalSize / 1024.0 / 1024.0, maxSize / 1024.0 / 1024.0);
+ }
+
+ return compressedFile;
+ }
+
+ /**
+ * 浣跨敤鎸囧畾璐ㄩ噺鍘嬬缉鍥剧墖涓篔PEG鏍煎紡
+ *
+ * @param image 鍥剧墖瀵硅薄
+ * @param originalFilename 鍘熷鏂囦欢鍚�
+ * @param quality 鍘嬬缉璐ㄩ噺锛�0.0-1.0锛�
+ * @return 鍘嬬缉鍚庣殑鏂囦欢
+ * @throws IOException IO寮傚父
+ */
+ public static File compressWithQuality(BufferedImage image, String originalFilename, float quality) throws IOException {
+ if (quality < 0.0f || quality > 1.0f) {
+ throw new IllegalArgumentException("鍘嬬缉璐ㄩ噺蹇呴』鍦�0.0鍒�1.0涔嬮棿");
+ }
+
+ // 杞崲涓篟GB鏍煎紡锛圝PEG涓嶆敮鎸侀�忔槑搴︼級
+ BufferedImage rgbImage = convertToRGB(image);
+
+ // 鍒涘缓涓存椂鏂囦欢
+ String tempDir = System.getProperty("java.io.tmpdir");
+ String filename = System.currentTimeMillis() + "_compressed_" +
+ getJpegFilename(originalFilename);
+ File outputFile = new File(tempDir, filename);
+
+ // 浣跨敤ImageWriter杩涜楂樿川閲忓帇缂�
+ Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
+ if (!writers.hasNext()) {
+ throw new IOException("绯荤粺涓嶆敮鎸丣PEG缂栫爜");
+ }
+
+ ImageWriter writer = writers.next();
+ ImageWriteParam param = writer.getDefaultWriteParam();
+
+ // 璁剧疆鍘嬬缉妯″紡鍜岃川閲�
+ param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ param.setCompressionQuality(quality);
+
+ try (ImageOutputStream ios = ImageIO.createImageOutputStream(outputFile)) {
+ writer.setOutput(ios);
+ writer.write(null, new IIOImage(rgbImage, null, null), param);
+ } finally {
+ writer.dispose();
+ }
+
+ log.debug("鍘嬬缉瀹屾垚锛岃川閲�: {}%, 鏂囦欢澶у皬: {} KB",
+ (int)(quality * 100), outputFile.length() / 1024.0);
+
+ return outputFile;
+ }
+
+ /**
+ * 楂樿川閲忓浘鐗囩缉鏀撅紙涓撲负OCR浼樺寲锛�
+ * 浣跨敤鍙屼笁娆℃彃鍊肩畻娉曚繚璇佹枃瀛楁竻鏅板害
+ *
+ * @param originalImage 鍘熷鍥剧墖
+ * @param targetWidth 鐩爣瀹藉害
+ * @param targetHeight 鐩爣楂樺害
+ * @return 缂╂斁鍚庣殑鍥剧墖
+ */
+ public static BufferedImage resizeImageHighQuality(BufferedImage originalImage, int targetWidth, int targetHeight) {
+ if (targetWidth <= 0 || targetHeight <= 0) {
+ throw new IllegalArgumentException("鐩爣瀹藉害鍜岄珮搴﹀繀椤诲ぇ浜�0");
+ }
+
+ BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g2d = resizedImage.createGraphics();
+
+ try {
+ // 璁剧疆楂樿川閲忔覆鏌撳弬鏁帮紙鍏抽敭锛侊級
+ g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+ g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
+
+ g2d.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);
+ } finally {
+ g2d.dispose();
+ }
+
+ return resizedImage;
+ }
+
+ /**
+ * 閫氱敤鍥剧墖鍘嬬缉锛堟寜鐩爣瀹介珮锛�
+ *
+ * @param file 涓婁紶鐨勫浘鐗囨枃浠�
+ * @param targetWidth 鐩爣瀹藉害
+ * @param targetHeight 鐩爣楂樺害
+ * @param quality 鍘嬬缉璐ㄩ噺锛�0.0-1.0锛�
+ * @return 鍘嬬缉鍚庣殑鏂囦欢
+ * @throws IOException IO寮傚父
+ */
+ public static File compress(MultipartFile file, int targetWidth, int targetHeight, float quality) throws IOException {
+ BufferedImage originalImage = ImageIO.read(file.getInputStream());
+ if (originalImage == null) {
+ throw new IOException("鏃犳硶璇诲彇鍥剧墖鏂囦欢");
+ }
+
+ BufferedImage resizedImage = resizeImageHighQuality(originalImage, targetWidth, targetHeight);
+ return compressWithQuality(resizedImage, file.getOriginalFilename(), quality);
+ }
+
+ /**
+ * 鎸夋瘮渚嬪帇缂╁浘鐗�
+ *
+ * @param file 涓婁紶鐨勫浘鐗囨枃浠�
+ * @param scale 缂╂斁姣斾緥锛�0.0-1.0锛�
+ * @param quality 鍘嬬缉璐ㄩ噺锛�0.0-1.0锛�
+ * @return 鍘嬬缉鍚庣殑鏂囦欢
+ * @throws IOException IO寮傚父
+ */
+ public static File compressByScale(MultipartFile file, double scale, float quality) throws IOException {
+ if (scale <= 0.0 || scale > 1.0) {
+ throw new IllegalArgumentException("缂╂斁姣斾緥蹇呴』鍦�0.0鍒�1.0涔嬮棿");
+ }
+
+ BufferedImage originalImage = ImageIO.read(file.getInputStream());
+ if (originalImage == null) {
+ throw new IOException("鏃犳硶璇诲彇鍥剧墖鏂囦欢");
+ }
+
+ int newWidth = (int) (originalImage.getWidth() * scale);
+ int newHeight = (int) (originalImage.getHeight() * scale);
+
+ BufferedImage resizedImage = resizeImageHighQuality(originalImage, newWidth, newHeight);
+ return compressWithQuality(resizedImage, file.getOriginalFilename(), quality);
+ }
+
+ /**
+ * 璁$畻鏈�浣崇缉鏀炬瘮渚�
+ *
+ * @param width 鍘熷瀹藉害
+ * @param height 鍘熷楂樺害
+ * @param targetSize 鐩爣鏂囦欢澶у皬
+ * @param currentSize 褰撳墠鏂囦欢澶у皬
+ * @return 缂╂斁姣斾緥
+ */
+ private static double calculateScaleFactor(int width, int height, long targetSize, long currentSize) {
+ int minDimension = Math.min(width, height);
+ double scaleFactor = 1.0;
+
+ // 鍩轰簬鏂囦欢澶у皬浼扮畻缂╂斁姣斾緥
+ double sizeRatio = Math.sqrt((double) targetSize / currentSize);
+
+ // 淇濇姢鏈�灏忓昂瀵革紙淇濊瘉OCR璇嗗埆锛�
+ if (minDimension > 2000) {
+ // 澶у浘鐗囷紝鍙互閫傚害缂╁皬
+ scaleFactor = Math.min(sizeRatio, 2000.0 / minDimension);
+ } else if (minDimension > OCR_OPTIMAL_MIN_SIZE) {
+ // 涓瓑鍥剧墖锛岃交寰缉灏�
+ scaleFactor = Math.min(sizeRatio, (double) OCR_OPTIMAL_MIN_SIZE / minDimension);
+ } else {
+ // 灏忓浘鐗囷紝灏介噺涓嶇缉灏�
+ scaleFactor = Math.min(sizeRatio, 0.95);
+ }
+
+ return scaleFactor;
+ }
+
+ /**
+ * 灏嗗浘鐗囪浆鎹负RGB鏍煎紡
+ *
+ * @param image 鍘熷鍥剧墖
+ * @return RGB鏍煎紡鍥剧墖
+ */
+ private static BufferedImage convertToRGB(BufferedImage image) {
+ if (image.getType() == BufferedImage.TYPE_INT_RGB) {
+ return image;
+ }
+
+ BufferedImage rgbImage = new BufferedImage(
+ image.getWidth(),
+ image.getHeight(),
+ BufferedImage.TYPE_INT_RGB
+ );
+ Graphics2D g = rgbImage.createGraphics();
+ try {
+ g.drawImage(image, 0, 0, null);
+ } finally {
+ g.dispose();
+ }
+
+ return rgbImage;
+ }
+
+ /**
+ * 灏嗘枃浠跺悕杞崲涓篔PEG鏍煎紡
+ *
+ * @param originalFilename 鍘熷鏂囦欢鍚�
+ * @return JPEG鏂囦欢鍚�
+ */
+ private static String getJpegFilename(String originalFilename) {
+ if (originalFilename == null || originalFilename.isEmpty()) {
+ return "image.jpg";
+ }
+
+ return originalFilename.replaceAll("\\.(png|PNG|gif|GIF|bmp|BMP|webp|WEBP)$", ".jpg");
+ }
+
+ /**
+ * 淇濆瓨MultipartFile鍒颁复鏃舵枃浠�
+ *
+ * @param file 涓婁紶鐨勬枃浠�
+ * @return 涓存椂鏂囦欢
+ * @throws IOException IO寮傚父
+ */
+ private static File saveToTempFile(MultipartFile file) throws IOException {
+ String tempDir = System.getProperty("java.io.tmpdir");
+ String originalFilename = file.getOriginalFilename();
+ File tempFile = new File(tempDir, System.currentTimeMillis() + "_" + originalFilename);
+ file.transferTo(tempFile);
+ return tempFile;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/image/package-info.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/image/package-info.java
new file mode 100644
index 0000000..e8f5406
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/image/package-info.java
@@ -0,0 +1,63 @@
+/**
+ * 鍥剧墖澶勭悊宸ュ叿鍖�
+ *
+ * <h2>涓昏鍔熻兘</h2>
+ * <ul>
+ * <li>鏅鸿兘鍥剧墖鍘嬬缉锛堜笓涓篛CR浼樺寲锛�</li>
+ * <li>楂樿川閲忓浘鐗囩缉鏀�</li>
+ * <li>鍥剧墖鏍煎紡杞崲</li>
+ * </ul>
+ *
+ * <h2>浣跨敤绀轰緥</h2>
+ *
+ * <h3>1. OCR鍥剧墖鏅鸿兘鍘嬬缉锛堟帹鑽愶級</h3>
+ * <pre>
+ * // 鑷姩鍘嬬缉鍒�3MB浠ヤ笅锛屼繚璇丱CR璇嗗埆鍑嗙‘鐜�
+ * File compressedFile = ImageCompressUtil.compressForOCR(multipartFile);
+ *
+ * // 鑷畾涔夊ぇ灏忛檺鍒�
+ * File compressedFile = ImageCompressUtil.compressForOCR(multipartFile, 5 * 1024 * 1024); // 5MB
+ * </pre>
+ *
+ * <h3>2. 鎸夊昂瀵稿帇缂�</h3>
+ * <pre>
+ * // 鍘嬬缉鍒版寚瀹氬楂�
+ * File compressedFile = ImageCompressUtil.compress(multipartFile, 1920, 1080, 0.85f);
+ * </pre>
+ *
+ * <h3>3. 鎸夋瘮渚嬪帇缂�</h3>
+ * <pre>
+ * // 缂╁皬鍒板師鏉ョ殑50%
+ * File compressedFile = ImageCompressUtil.compressByScale(multipartFile, 0.5, 0.90f);
+ * </pre>
+ *
+ * <h3>4. 楂樿川閲忓浘鐗囩缉鏀�</h3>
+ * <pre>
+ * BufferedImage originalImage = ImageIO.read(file);
+ * BufferedImage resizedImage = ImageCompressUtil.resizeImageHighQuality(originalImage, 800, 600);
+ * </pre>
+ *
+ * <h3>5. 鑷畾涔夎川閲忓帇缂�</h3>
+ * <pre>
+ * BufferedImage image = ImageIO.read(file);
+ * File compressed = ImageCompressUtil.compressWithQuality(image, "photo.jpg", 0.80f); // 80%璐ㄩ噺
+ * </pre>
+ *
+ * <h2>鍘嬬缉璐ㄩ噺甯搁噺</h2>
+ * <ul>
+ * <li>{@code ImageCompressUtil.HIGH_QUALITY} - 0.90锛堥珮璐ㄩ噺锛屾帹鑽怬CR浣跨敤锛�</li>
+ * <li>{@code ImageCompressUtil.MEDIUM_QUALITY} - 0.80锛堜腑绛夎川閲忥級</li>
+ * <li>{@code ImageCompressUtil.LOW_QUALITY} - 0.75锛堜綆璐ㄩ噺锛�</li>
+ * </ul>
+ *
+ * <h2>娉ㄦ剰浜嬮」</h2>
+ * <ul>
+ * <li>鍘嬬缉鍚庣殑鏂囦欢淇濆瓨鍦ㄧ郴缁熶复鏃剁洰褰曪紝浣跨敤瀹屾瘯鍚庨渶鎵嬪姩鍒犻櫎</li>
+ * <li>OCR鍘嬬缉浼氫繚璇佹渶灏忚竟涓嶅皬浜�1500px锛岀‘淇濇枃瀛楁竻鏅�</li>
+ * <li>鏀寔PNG銆丅MP銆丟IF绛夋牸寮忚嚜鍔ㄨ浆涓篔PEG</li>
+ * </ul>
+ *
+ * @author ruoyi
+ * @since 2025-01-20
+ */
+package com.ruoyi.common.utils.image;
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/OCRController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/OCRController.java
index d370b89..57da753 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/OCRController.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/OCRController.java
@@ -4,6 +4,7 @@
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.common.utils.image.ImageCompressUtil;
import com.ruoyi.system.utils.AliOCRUtil;
import com.ruoyi.system.utils.BaiduOCRUtil;
import com.ruoyi.system.utils.TencentOCRUtil;
@@ -55,11 +56,8 @@
return error("涓嶆敮鎸佺殑璇嗗埆绫诲瀷: " + type + ", 鏀寔鐨勭被鍨�: " + String.join(",", SUPPORTED_TYPES));
}
- // 淇濆瓨涓存椂鏂囦欢
- String tempDir = System.getProperty("java.io.tmpdir");
- String originalFilename = file.getOriginalFilename();
- File tempFile = new File(tempDir, System.currentTimeMillis() + "_" + originalFilename);
- file.transferTo(tempFile);
+ // 鏅鸿兘鍘嬬缉鍥剧墖锛堣嚜鍔ㄥ鐞嗚秴杩�3MB鐨勫浘鐗囷級
+ File tempFile = ImageCompressUtil.compressForOCR(file);
// 鏍规嵁鎻愪緵鍟嗚皟鐢ㄤ笉鍚岀殑OCR鏈嶅姟
JSONObject ocrResult;
@@ -92,7 +90,10 @@
// 鏋勫缓杩斿洖缁撴灉
Map<String, Object> result = new HashMap<>();
result.put("ocrResult", ocrResult);
- result.put("fileName", originalFilename);
+ result.put("fileName", file.getOriginalFilename());
+ result.put("originalSize", file.getSize());
+ result.put("processedSize", tempFile.length());
+ result.put("compressed", file.getSize() > tempFile.length());
result.put("type", type);
result.put("provider", provider);
@@ -263,11 +264,8 @@
return error("涓婁紶鍥剧墖涓嶈兘涓虹┖");
}
- // 淇濆瓨涓存椂鏂囦欢
- String tempDir = System.getProperty("java.io.tmpdir");
- String originalFilename = file.getOriginalFilename();
- File tempFile = new File(tempDir, System.currentTimeMillis() + "_" + originalFilename);
- file.transferTo(tempFile);
+ // 鏅鸿兘鍘嬬缉鍥剧墖锛堣嚜鍔ㄥ鐞嗚秴杩�3MB鐨勫浘鐗囷級
+ File tempFile = ImageCompressUtil.compressForOCR(file);
// 璋冪敤鑵捐浜戞墜鍐欎綋璇嗗埆
Map<String, String> resultMap = TencentOCRUtil.handwritingRecognizeWith(tempFile.getAbsolutePath(), itemNames);
@@ -282,7 +280,7 @@
// 鏋勫缓杩斿洖缁撴灉
Map<String, Object> result = new HashMap<>();
- result.put("fileName", originalFilename);
+ result.put("fileName", file.getOriginalFilename());
result.put("type", "HandWriting");
result.put("provider", "tencent");
result.put("fields", resultMap);
@@ -356,11 +354,8 @@
}
try {
- // 淇濆瓨涓存椂鏂囦欢
- String tempDir = System.getProperty("java.io.tmpdir");
- String originalFilename = file.getOriginalFilename();
- File tempFile = new File(tempDir, System.currentTimeMillis() + "_" + originalFilename);
- file.transferTo(tempFile);
+ // 鏅鸿兘鍘嬬缉鍥剧墖锛堣嚜鍔ㄥ鐞嗚秴杩�3MB鐨勫浘鐗囷級
+ File tempFile = ImageCompressUtil.compressForOCR(file);
// 璋冪敤鑵捐浜戞墜鍐欎綋璇嗗埆
Map<String, String> resultMap = TencentOCRUtil.handwritingRecognizeWith(tempFile.getAbsolutePath(), itemNames);
@@ -371,8 +366,8 @@
// 妫�鏌ユ槸鍚︽湁閿欒
if (resultMap.containsKey("error")) {
failCount++;
- errorMessages.append(originalFilename).append(":").append(resultMap.get("error")).append("; ");
- logger.warn("鍥剧墖 {} 璇嗗埆澶辫触: {}", originalFilename, resultMap.get("error"));
+ errorMessages.append(file.getOriginalFilename()).append(":").append(resultMap.get("error")).append("; ");
+ logger.warn("鍥剧墖 {} 璇嗗埆澶辫触: {}", file.getOriginalFilename(), resultMap.get("error"));
} else {
// 鍚堝苟璇嗗埆缁撴灉锛堝鏋渒ey宸插瓨鍦紝涓嶈鐩栵級
for (Map.Entry<String, String> entry : resultMap.entrySet()) {
@@ -381,7 +376,7 @@
}
}
successCount++;
- logger.info("鍥剧墖 {} 璇嗗埆鎴愬姛锛屾彁鍙� {} 涓瓧娈�", originalFilename, resultMap.size());
+ logger.info("鍥剧墖 {} 璇嗗埆鎴愬姛锛屾彁鍙� {} 涓瓧娈�", file.getOriginalFilename(), resultMap.size());
}
} catch (Exception e) {
failCount++;
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java
index b8c9b2e..e200cec 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java
@@ -65,7 +65,7 @@
return AjaxResult.warn("浼犲叆鐨勭敤鎴锋暟鎹负绌�");
}
- log.info("寮�濮嬪悓姝� {} 鏉A鐢ㄦ埛鏁版嵁鍒� MySQL 鏁版嵁搴�...", oaUsers.size());
+// log.info("寮�濮嬪悓姝� {} 鏉A鐢ㄦ埛鏁版嵁鍒� MySQL 鏁版嵁搴�...", oaUsers.size());
int createdCount = 0;
int updatedCount = 0;
@@ -109,8 +109,8 @@
// 鐢ㄦ埛宸插瓨鍦紝鏇存柊淇℃伅
updateExistingUser(existingUser, dto, deptId);
updatedCount++;
- log.info("鏇存柊鐢ㄦ埛: {} ({}), oaUserId: {}",
- dto.getNickName(), dto.getUserName(), dto.getOaUserId());
+// log.info("鏇存柊鐢ㄦ埛: {} ({}), oaUserId: {}",
+// dto.getNickName(), dto.getUserName(), dto.getOaUserId());
}
else
{
@@ -140,16 +140,16 @@
userByName.setUpdateBy("sync");
sysUserMapper.updateUser(userByName);
updatedCount++;
- log.info("鏇存柊宸插瓨鍦ㄧ敤鎴峰悕鐨勭敤鎴�: {} ({}), 璁剧疆oaUserId: {}",
- dto.getNickName(), dto.getUserName(), dto.getOaUserId());
+// log.info("鏇存柊宸插瓨鍦ㄧ敤鎴峰悕鐨勭敤鎴�: {} ({}), 璁剧疆oaUserId: {}",
+// dto.getNickName(), dto.getUserName(), dto.getOaUserId());
}
else
{
// 鍒涘缓鏂扮敤鎴�
createNewUser(dto, deptId);
createdCount++;
- log.info("鍒涘缓鏂扮敤鎴�: {} ({}), oaUserId: {}, deptId: {}",
- dto.getNickName(), dto.getUserName(), dto.getOaUserId(), deptId);
+// log.info("鍒涘缓鏂扮敤鎴�: {} ({}), oaUserId: {}, deptId: {}",
+// dto.getNickName(), dto.getUserName(), dto.getOaUserId(), deptId);
}
}
}
@@ -163,7 +163,7 @@
String message = String.format("鍚屾瀹屾垚锛佸垱寤虹敤鎴�: %d, 鏇存柊鐢ㄦ埛: %d, 璺宠繃: %d, 澶辫触: %d",
createdCount, updatedCount, skippedCount, errorCount);
- log.info(message);
+// log.info(message);
Map<String, Object> result = new HashMap<>();
result.put("created", createdCount);
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/TencentOCRUtil.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/TencentOCRUtil.java
index 6597b02..2f0ea18 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/utils/TencentOCRUtil.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/TencentOCRUtil.java
@@ -18,10 +18,8 @@
import org.springframework.stereotype.Component;
import java.io.File;
-import java.util.Base64;
+import java.util.*;
import java.nio.file.Files;
-import java.util.HashMap;
-import java.util.Map;
/**
* 鑵捐浜慜CR宸ュ叿绫�
@@ -222,7 +220,7 @@
// {"鎮h�呯鍚嶏紙鎵嬪嵃锛�", "绛惧瓧浜鸿韩浠借瘉鍙风爜", "鏃ユ湡", "鑱旂郴鐢佃瘽", "鏈汉", "绛惧瓧浜轰笌鎮h�呭叧绯�"}
req.setItemNames(itemNames != null ? itemNames : new String[]{"鎮h�呭鍚�", "鎬у埆", "骞撮緞", "韬唤璇佸彿", "璇婃柇", "闇�鏀粯杞繍璐圭敤", "琛岀▼", "寮�濮嬫椂闂�", "缁撴潫鏃堕棿", "瀹跺睘绛惧悕"});
req.setOutputLanguage("cn");
- req.setReturnFullText(false);
+ req.setReturnFullText(true);
req.setItemNamesShowMode(false);
ExtractDocMultiResponse resp = client.ExtractDocMulti(req);
@@ -295,7 +293,42 @@
}
}
}
-
+ //灏� WordList
+ List<String> wordListResult = new ArrayList<>();
+ if (responseData.containsKey("WordList") && responseData.getJSONArray("WordList") != null){
+ JSONArray wordList = responseData.getJSONArray("WordList");
+ for (int i = 0; i < wordList.size(); i++) {
+ JSONObject word = wordList.getJSONObject(i);
+ // {
+ // "Coord": {
+ // "LeftBottom": {
+ // "X": 472,
+ // "Y": 1500
+ // },
+ // "LeftTop": {
+ // "X": 467,
+ // "Y": 1420
+ // },
+ // "RightBottom": {
+ // "X": 636,
+ // "Y": 1490
+ // },
+ // "RightTop": {
+ // "X": 631,
+ // "Y": 1410
+ // }
+ // },
+ // "DetectedText": "琛岀▼:"
+ // }
+ String detectedText = word.getString("DetectedText");
+ wordListResult.add(detectedText);
+ }
+ }
+ //鎴戜滑浠巜ordListResult涓绋�:鍚庨潰锛岄渶瑕佹敮浠樿浆杩愯垂鐢�:涔嬮棿鐨勬枃瀛�
+ String content = extractContentFromWordList(wordListResult, "琛岀▼:", "闇�鏀粯杞繍璐圭敤:");
+ log.info("鎻愬彇鍒拌绋�: {}", content);
+ resultMap.put("琛岀▼", content);
+
log.info("鎵嬪啓浣撹瘑鍒彁鍙栧埌 {} 涓瓧娈�", resultMap.size());
return resultMap;
@@ -306,6 +339,42 @@
}
}
+ private static String extractContentFromWordList(List<String> wordListResult, String s, String s1) {
+ //鎻愬彇s鍜宻1涔嬮棿鐨勫唴瀹�
+ //濡傛灉word涓彧鏈変竴鎴�-鎴�->锛岀粺涓�澶勭悊鎴�->
+
+
+ int startIndex = -1;
+ int endIndex = -1;
+
+ for (int i = 0; i < wordListResult.size(); i++) {
+ String word = wordListResult.get(i);
+ if (word.contains(s)) {
+ startIndex = i;
+ }
+
+ if (word.contains(s1)) {
+ endIndex = i;
+ }
+ }
+ if (startIndex == -1 || endIndex == -1 || startIndex >= endIndex) {
+ return "";
+ }
+ List<String> w=wordListResult.subList(startIndex + 1, endIndex);
+ Boolean findAle=false;
+ List<String> result=new ArrayList<>();
+ for(String word:w){
+ if (!findAle && (word.equals("-") || word.equals("->") || word.equals("鈫�") || word.equals("涓�") || word.equals("=>")) ){
+ findAle = true;
+ word = word.replace("-", "鈫�")
+ .replace("涓�", "鈫�")
+ .replace("=>", "鈫�");
+ }
+ result.add(word);
+ };
+ return String.join("", result);
+ }
+
/**
* 韬唤璇佽瘑鍒�
* @param imagePath 鍥剧墖璺緞
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
index 4fe1ac6..99faf07 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
@@ -354,4 +354,33 @@
and e.patient_phone = #{phone}
and DATE(t.create_time) = #{createDate}
</select>
+
+ <!-- 鏌ヨ杞﹁締鍦ㄦ寚瀹氭椂闂磋寖鍥村唴鐨勪换鍔″垪琛� -->
+ <select id="selectVehicleTasksInTimeRange" parameterType="map" resultMap="SysTaskResult">
+ select t.task_id, t.task_code, t.task_type, t.task_status,
+ t.departure_address, t.destination_address,
+ t.actual_start_time, t.actual_end_time,
+ t.planned_start_time, t.planned_end_time,
+ t.estimated_distance,
+ tv.vehicle_id
+ from sys_task t
+ inner join sys_task_vehicle tv on t.task_id = tv.task_id
+ where tv.vehicle_id = #{vehicleId}
+ and t.del_flag = '0'
+ and t.task_status not in ('CANCELLED')
+ and (
+ <!-- 瀹為檯鏃堕棿鏈夊�兼椂锛屼娇鐢ㄥ疄闄呮椂闂村垽鏂噸鍙� -->
+ (t.actual_start_time is not null and t.actual_end_time is not null
+ and t.actual_start_time <= #{endTime} and t.actual_end_time >= #{startTime})
+ or
+ <!-- 瀹為檯寮�濮嬫椂闂存湁鍊间絾鏈粨鏉熸椂锛屼娇鐢ㄥ綋鍓嶆椂闂翠綔涓虹粨鏉熸椂闂� -->
+ (t.actual_start_time is not null and t.actual_end_time is null
+ and t.actual_start_time <= #{endTime})
+ or
+ <!-- 瀹為檯鏃堕棿閮戒负绌烘椂锛屼娇鐢ㄨ鍒掓椂闂村垽鏂噸鍙� -->
+ (t.actual_start_time is null and t.actual_end_time is null
+ and t.planned_start_time <= #{endTime} and t.planned_end_time >= #{startTime})
+ )
+ order by t.actual_start_time, t.planned_start_time
+ </select>
</mapper>
diff --git a/ruoyi-ui/src/api/task.js b/ruoyi-ui/src/api/task.js
index 8a1ae69..b72da8d 100644
--- a/ruoyi-ui/src/api/task.js
+++ b/ruoyi-ui/src/api/task.js
@@ -284,4 +284,22 @@
method: 'get',
params: { taskId }
})
+}
+
+// ========== 鏃х郴缁熷悓姝ョ浉鍏矨PI ==========
+
+// 鎵嬪姩鍚屾鏈嶅姟鍗曞埌鏃х郴缁�
+export function syncServiceOrder(taskId) {
+ return request({
+ url: '/task/syncServiceOrder/' + taskId,
+ method: 'post'
+ })
+}
+
+// 鎵嬪姩鍚屾璋冨害鍗曞埌鏃х郴缁�
+export function syncDispatchOrder(taskId) {
+ return request({
+ url: '/task/syncDispatchOrder/' + taskId,
+ method: 'post'
+ })
}
\ No newline at end of file
diff --git a/ruoyi-ui/src/views/task/general/detail.vue b/ruoyi-ui/src/views/task/general/detail.vue
index 036d380..bd5a736 100644
--- a/ruoyi-ui/src/views/task/general/detail.vue
+++ b/ruoyi-ui/src/views/task/general/detail.vue
@@ -74,6 +74,16 @@
<i class="el-icon-error"></i> 鍚屾澶辫触
</el-tag>
<span v-else style="color: #C0C4CC;">--</span>
+ <!-- 鏈悓姝ユ垨鍚屾澶辫触鏃舵樉绀哄悓姝ユ寜閽� -->
+ <el-button
+ v-if="taskDetail.emergencyInfo.syncStatus === 0 || taskDetail.emergencyInfo.syncStatus === 3"
+ type="primary"
+ size="mini"
+ icon="el-icon-refresh"
+ :loading="syncingServiceOrder"
+ @click="syncServiceOrder"
+ style="margin-left: 10px;"
+ >鍚屾鏈嶅姟鍗�</el-button>
</el-descriptions-item>
<el-descriptions-item label="鏈嶅姟鍗曞彿">
<span v-if="taskDetail.emergencyInfo.legacyServiceOrdId">
@@ -109,6 +119,16 @@
<i class="el-icon-error"></i> 鍚屾澶辫触
</el-tag>
<span v-else style="color: #C0C4CC;">--</span>
+ <!-- 鏈悓姝ユ垨鍚屾澶辫触鏃舵樉绀哄悓姝ユ寜閽� -->
+ <el-button
+ v-if="taskDetail.emergencyInfo.dispatchSyncStatus === 0 || taskDetail.emergencyInfo.dispatchSyncStatus === 3"
+ type="primary"
+ size="mini"
+ icon="el-icon-refresh"
+ :loading="syncingDispatchOrder"
+ @click="syncDispatchOrder"
+ style="margin-left: 10px;"
+ >鍚屾璋冨害鍗�</el-button>
</el-descriptions-item>
<el-descriptions-item label="璋冨害鍗曞彿">
<span v-if="taskDetail.emergencyInfo.legacyDispatchOrdId">
@@ -738,7 +758,7 @@
</template>
<script>
-import { getTask, updateTask, assignTask, changeTaskStatus, uploadAttachment, deleteAttachment, getTaskVehicles, getAvailableVehicles, assignVehiclesToTask, unassignVehicleFromTask, getPaymentInfo } from "@/api/task";
+import { getTask, updateTask, assignTask, changeTaskStatus, uploadAttachment, deleteAttachment, getTaskVehicles, getAvailableVehicles, assignVehiclesToTask, unassignVehicleFromTask, getPaymentInfo, syncServiceOrder, syncDispatchOrder } from "@/api/task";
import { listUser } from "@/api/system/user";
import { getToken } from "@/utils/auth";
@@ -827,7 +847,10 @@
category: [
{ required: true, message: "涓氬姟鍒嗙被涓嶈兘涓虹┖", trigger: "change" }
]
- }
+ },
+ // 鍚屾鍔犺浇鐘舵��
+ syncingServiceOrder: false,
+ syncingDispatchOrder: false
};
},
created() {
@@ -1125,6 +1148,36 @@
if (!fileType) return false;
const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
return imageTypes.includes(fileType.toLowerCase());
+ },
+ /** 鎵嬪姩鍚屾鏈嶅姟鍗� */
+ syncServiceOrder() {
+ this.$modal.confirm('鏄惁纭鍚屾鏈嶅姟鍗曞埌鏃х郴缁燂紵').then(() => {
+ this.syncingServiceOrder = true;
+ return syncServiceOrder(this.taskDetail.taskId);
+ }).then(() => {
+ this.$modal.msgSuccess("鏈嶅姟鍗曞悓姝ユ垚鍔�");
+ // 閲嶆柊鍔犺浇浠诲姟璇︽儏
+ this.getDetail();
+ }).catch(() => {
+ // 澶勭悊鍙栨秷鍜岄敊璇�
+ }).finally(() => {
+ this.syncingServiceOrder = false;
+ });
+ },
+ /** 鎵嬪姩鍚屾璋冨害鍗� */
+ syncDispatchOrder() {
+ this.$modal.confirm('鏄惁纭鍚屾璋冨害鍗曞埌鏃х郴缁燂紵').then(() => {
+ this.syncingDispatchOrder = true;
+ return syncDispatchOrder(this.taskDetail.taskId);
+ }).then(() => {
+ this.$modal.msgSuccess("璋冨害鍗曞悓姝ユ垚鍔�");
+ // 閲嶆柊鍔犺浇浠诲姟璇︽儏
+ this.getDetail();
+ }).catch(() => {
+ // 澶勭悊鍙栨秷鍜岄敊璇�
+ }).finally(() => {
+ this.syncingDispatchOrder = false;
+ });
}
}
};
--
Gitblit v1.9.1