From 09faa36132c8cbada5327649875534ef01c1a3b1 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期四, 11 十二月 2025 20:44:31 +0800
Subject: [PATCH] feat: 优化任务里程统计
---
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskAssigneeService.java | 84
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskAttachmentService.java | 33
sql/sys_notify_task.sql | 95
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAssigneeServiceImpl.java | 260 +
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java | 9
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/NotifyChannelConfigController.java | 77
ruoyi-ui/src/views/system/notify/log/index.vue | 322 ++
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java | 91
ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java | 4
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysWelfareTaskService.java | 46
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifyTaskServiceImpl.java | 166 +
ruoyi-common/src/main/java/com/ruoyi/common/config/SmsConfig.java | 81
ruoyi-system/src/main/java/com/ruoyi/system/mapper/NotifySendLogMapper.java | 110
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacyTransferSyncTask.java | 8
ruoyi-ui/src/views/system/notify/channelConfig.vue | 311 +
ruoyi-ui/src/api/system/notify/task/index.js | 27
ruoyi-system/src/main/java/com/ruoyi/system/controller/NotifyTaskController.java | 69
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java | 154
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleMileageStatsTask.java | 2
ruoyi-ui/src/api/system/notify/channelConfig.js | 44
ruoyi-admin/src/main/resources/application.yml | 17
ruoyi-admin/src/main/java/com/ruoyi/web/controller/sms/SendTaskReq.java | 12
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleSyncTask.java | 4
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacyVehicleSyncTask.java | 2
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifyChannelConfigServiceImpl.java | 104
ruoyi-admin/src/main/java/com/ruoyi/web/controller/sms/NotifyController.java | 31
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskMapper.java | 13
ruoyi-system/src/main/java/com/ruoyi/system/mapper/NotifyTaskMapper.java | 98
ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleMileageStatsMapper.java | 2
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAssigneeMapper.java | 10
ruoyi-system/src/main/java/com/ruoyi/system/controller/SmsSendController.java | 25
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysEmergencyTaskService.java | 33
clean-logs.bat | 48
app/pagesTask/components/HospitalSelector.vue | 22
app/pagesTask/detail.vue | 25
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SmsServiceImpl.java | 298 +
ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java | 4
ruoyi-system/src/main/resources/mapper/system/NotifyTaskMapper.xml | 132
ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskCreateVO.java | 2
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/OaSyncTask.java | 34
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java | 20
app/utils/subscribe.js | 68
ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java | 244 +
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/ServiceOrderController.java | 2
run_sms_test.bat | 5
ruoyi-system/pom.xml | 10
sql/sys_notify_send_log.sql | 52
doc/日志优化说明.md | 306 +
run_sms_service_tests.bat | 9
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java | 35
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java | 4
ruoyi-system/src/main/java/com/ruoyi/system/controller/NotifySendLogController.java | 69
ruoyi-system/src/main/java/com/ruoyi/system/service/INotifySendLogService.java | 109
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAttachmentServiceImpl.java | 227 +
ruoyi-system/src/main/java/com/ruoyi/system/service/INotifyDispatchService.java | 81
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CmsVehicleSyncTask.java | 12
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java | 270
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleGpsSegmentMileageTask.java | 10
ruoyi-system/src/main/java/com/ruoyi/system/mapper/NotifyChannelConfigMapper.java | 80
sql/notify_menu.sql | 53
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifyDispatchServiceImpl.java | 321 +
sql/notify_dict.sql | 51
app/pages/index.vue | 4
ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java | 137
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysEmergencyTaskServiceImpl.java | 490 +++
ruoyi-system/src/main/resources/mapper/system/VehicleMileageStatsMapper.xml | 11
ruoyi-ui/src/views/system/mileageStats/index.vue | 69
ruoyi-system/src/main/java/com/ruoyi/system/domain/NotifySendLog.java | 210 +
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java | 25
ruoyi-admin/src/main/resources/logback.xml | 114
ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java | 2
ruoyi-system/src/main/java/com/ruoyi/system/service/INotifyChannelConfigService.java | 70
sql/sms_config.sql | 35
ruoyi-admin/src/main/java/com/ruoyi/web/controller/sms/SmsController.java | 43
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysWelfareTaskServiceImpl.java | 131
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifySendLogServiceImpl.java | 214 +
ruoyi-ui/src/api/system/notify/log/index.js | 27
ruoyi-system/src/main/java/com/ruoyi/system/domain/NotifyTask.java | 212 +
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/GpsSyncTask.java | 4
ruoyi-system/src/main/java/com/ruoyi/system/service/INotifyTaskService.java | 121
ruoyi-system/src/main/resources/mapper/system/SysTaskAssigneeMapper.xml | 4
ruoyi-common/src/main/java/com/ruoyi/common/utils/civilAviation/ServiceOrderUtil.java | 2
ruoyi-ui/src/views/system/notify/task/index.vue | 310 +
ruoyi-system/src/main/resources/mapper/system/VehicleGpsMapper.xml | 15
ruoyi-system/src/main/resources/mapper/system/NotifyChannelConfigMapper.xml | 91
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CleanVehicleGpsTask.java | 4
app/pagesTask/create-emergency.vue | 2
app/pages/message/index.vue | 4
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CmsGpsCollectServiceImpl.java | 20
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentSyncServiceImpl.java | 6
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java | 475 +-
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java | 1438 +-------
ruoyi-system/src/main/java/com/ruoyi/system/controller/SmsSendReq.java | 16
ruoyi-system/src/main/java/com/ruoyi/system/domain/NotifyChannelConfig.java | 112
ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml | 14
ruoyi-system/src/main/java/com/ruoyi/system/service/ISmsService.java | 64
ruoyi-system/src/main/resources/mapper/system/NotifySendLogMapper.xml | 174 +
97 files changed, 7,731 insertions(+), 1,886 deletions(-)
diff --git a/app/pages/index.vue b/app/pages/index.vue
index c5c90fe..556f5aa 100644
--- a/app/pages/index.vue
+++ b/app/pages/index.vue
@@ -244,7 +244,7 @@
loading: false,
// 璁㈤槄鐘舵��
- hasSubscribed: true,
+ hasSubscribed: false,
};
},
computed: {
@@ -279,7 +279,7 @@
this.hasSubscribed = subscribeManager.checkLocalSubscribeStatus();
// 鑷姩璁㈤槄锛堝鏋滄湭璁㈤槄鍒欐樉绀虹‘璁ゅ脊绐楋級
- // this.autoSubscribeOnLaunch();
+ this.autoSubscribeOnLaunch();
// 鍔犺浇鐢ㄦ埛缁戝畾杞﹁締淇℃伅
this.loadUserVehicle();
diff --git a/app/pages/message/index.vue b/app/pages/message/index.vue
index fd682d0..95e613f 100644
--- a/app/pages/message/index.vue
+++ b/app/pages/message/index.vue
@@ -47,7 +47,7 @@
// 娑堟伅鍒楄〃
messages: [],
loading: false,
- subscribed: true,
+ subscribed: false,
}
},
computed: {
@@ -68,7 +68,7 @@
onLoad() {
this.loadMessages()
// 鑷姩璁㈤槄锛堝鏋滄湭璁㈤槄鍒欐樉绀虹‘璁ゅ脊绐楋級
- // this.autoSubscribeOnLaunch()
+ this.autoSubscribeOnLaunch()
},
onShow() {
// 姣忔鏄剧ず椤甸潰鏃跺埛鏂版秷鎭�
diff --git a/app/pagesTask/components/HospitalSelector.vue b/app/pagesTask/components/HospitalSelector.vue
index b82dc5b..cd4fd01 100644
--- a/app/pagesTask/components/HospitalSelector.vue
+++ b/app/pagesTask/components/HospitalSelector.vue
@@ -224,21 +224,27 @@
// 閫夋嫨鍖婚櫌
selectHospital(hospital) {
- this.selectedHospitalName = hospital.hospName
- this.searchKeyword = hospital.hospName
+ // 娣诲姞null妫�鏌�
+ if (!hospital) {
+ console.warn('閫夋嫨鐨勫尰闄㈠璞′负绌�');
+ return;
+ }
+
+ this.selectedHospitalName = hospital.hospName || '';
+ this.searchKeyword = hospital.hospName || '';
const hospitalData = {
- id: hospital.hospId,
- name: hospital.hospName,
+ id: hospital.hospId || null,
+ name: hospital.hospName || '',
address: hospital.hospName === '瀹朵腑' ? '' : this.buildFullAddress(hospital)
}
- this.showResults = false
- this.searchResults = []
+ this.showResults = false;
+ this.searchResults = [];
// 瑙﹀彂鏇存柊浜嬩欢
- this.$emit('input', hospitalData)
- this.$emit('change', hospitalData)
+ this.$emit('input', hospitalData);
+ this.$emit('change', hospitalData);
},
diff --git a/app/pagesTask/create-emergency.vue b/app/pagesTask/create-emergency.vue
index e2b1d05..146f013 100644
--- a/app/pagesTask/create-emergency.vue
+++ b/app/pagesTask/create-emergency.vue
@@ -65,7 +65,7 @@
label="鎵ц浠诲姟浜哄憳"
:required="false"
:auto-add-current-user="true"
- :current-user-removable="false"
+ :current-user-removable="true"
:branch-dept-ids="allOrganizationIds"
@change="onStaffChange"
/>
diff --git a/app/pagesTask/detail.vue b/app/pagesTask/detail.vue
index c84acb7..0006bca 100644
--- a/app/pagesTask/detail.vue
+++ b/app/pagesTask/detail.vue
@@ -37,7 +37,7 @@
<view
class="assignee-item"
v-for="(assignee, index) in taskDetail.assignees"
- :key="'assignee-' + (assignee.userId || assignee.userName || index)"
+ :key="getAssigneeKey(assignee, index)"
>
<view class="assignee-index">{{ index + 1 }}</view>
<view class="assignee-info">
@@ -260,7 +260,7 @@
<view
class="payment-record-item"
v-for="(payment, index) in paymentInfo.paidPayments"
- :key="'payment-' + (payment.id || index)"
+ :key="getPaymentKey(payment, index)"
>
<view class="payment-header">
<view
@@ -1398,7 +1398,26 @@
// 鍑哄彂鍓嶄繚璇佸氨缁紙淇濈暀鍚戝悗鍏煎锛�
async ensureReadyThenDepart() {
this.handleDepartAction()
- }
+ },
+
+ // 鑾峰彇鎵ц浜哄憳鐨刱ey鍊�
+ getAssigneeKey(assignee, index) {
+ // 纭繚杩斿洖鏈夋晥鐨勫瓧绗︿覆key
+ if (!assignee) return 'assignee-' + index;
+ // 浼樺厛浣跨敤userId锛屽叾娆℃槸userName锛屾渶鍚庝娇鐢╥ndex
+ const key = assignee.userId || assignee.userName || index;
+ return 'assignee-' + (key !== null && key !== undefined ? key : index);
+ },
+
+ // 鑾峰彇鏀粯璁板綍鐨刱ey鍊�
+ getPaymentKey(payment, index) {
+ // 纭繚杩斿洖鏈夋晥鐨勫瓧绗︿覆key
+ if (!payment) return 'payment-' + index;
+ // 浼樺厛浣跨敤id锛屽叾娆′娇鐢╥ndex
+ const key = payment.id || index;
+ return 'payment-' + (key !== null && key !== undefined ? key : index);
+ },
+
}
}
</script>
diff --git a/app/utils/subscribe.js b/app/utils/subscribe.js
index 8066c8a..ab6d316 100644
--- a/app/utils/subscribe.js
+++ b/app/utils/subscribe.js
@@ -47,7 +47,7 @@
* @returns {boolean}
*/
checkLocalSubscribeStatus() {
- return true;// uni.getStorageSync('hasSubscribedTaskNotify') || false
+ return uni.getStorageSync('hasSubscribedTaskNotify') || false
}
/**
@@ -70,16 +70,43 @@
wx.getSetting({
withSubscriptions: true,
success: (res) => {
- console.log('寰俊璁㈤槄鐘舵�佹煡璇㈢粨鏋滐細', res)
-
+ // console.log('寰俊璁㈤槄鐘舵�佹煡璇㈢粨鏋滐細', res.subscriptionsSetting.mainSwitch)
+
// 妫�鏌ubscriptionsSetting涓槸鍚︽湁璇ユā鏉縄D鐨勮褰�
if (res.subscriptionsSetting && res.subscriptionsSetting.mainSwitch) {
- const subscribeStatus = res.subscriptionsSetting.mainSwitch;
- resolve(subscribeStatus)
+ resolve(false); // 濡傛灉鐢ㄦ埛鍚屾剰浜嗚闃咃紝鍒欒繑鍥瀎alse
+ // const subscribeStatus = res.subscriptionsSetting.mainSwitch;
+ // console.log(res.subscriptionsSetting.itemSettings[templateId])
+ // resolve(subscribeStatus)
// 'accept' 琛ㄧず鐢ㄦ埛鍚屾剰璁㈤槄锛�'reject' 琛ㄧず鎷掔粷锛�'ban' 琛ㄧず琚皝绂�
// const isSubscribed = subscribeStatus === 'accept'
// console.log(`妯℃澘ID ${templateId} 璁㈤槄鐘舵�侊細`, subscribeStatus, '鏄惁宸茶闃咃細', isSubscribed)
// resolve(isSubscribed)
+ // console.log("鍙戣捣璁㈤槄璇锋眰")
+ // wx.requestSubscribeMessage({
+ // tmplIds: [templateId],
+ // success: (res) => {
+ // console.log('璁㈤槄娑堟伅鐘舵�侊細', res)
+ // if (res[templateId] === 'accept') {
+ // console.log('鐢ㄦ埛宸茶闃�')
+ // resolve(true)
+ // } else if (res[templateId] === 'reject') {
+ // console.log('鐢ㄦ埛宸叉嫆缁濊闃�')
+ // resolve(false)
+ // } else if (res[templateId] === 'ban') {
+ // console.log('鐢ㄦ埛宸插皝绂佽闃�')
+ // resolve(false)
+ // } else {
+ // console.log('鏈煡璁㈤槄鐘舵��')
+ // resolve(false)
+ // }
+ // },fail: (err) => {
+ // console.error('璁㈤槄娑堟伅澶辫触锛�', err)
+ // resolve(false)
+ // }
+
+ // }
+ // )
} else {
console.log('鏈壘鍒拌闃呰缃俊鎭紝瑙嗕负鏈闃�')
resolve(false)
@@ -112,16 +139,16 @@
async checkSubscribeStatus() {
const localStatus = this.checkLocalSubscribeStatus()
const wechatStatus = await this.checkWechatSubscribeStatus()
-
+
// 濡傛灉鏈湴鏄剧ず宸茶闃咃紝浣嗗井淇″畼鏂规樉绀烘湭璁㈤槄锛岄渶瑕侀噸鏂拌闃�
- const needResubscribe = wechatStatus
-
+ const needResubscribe = !localStatus
+
if (needResubscribe) {
- console.warn('鏈湴鐘舵�佷笌寰俊瀹樻柟鐘舵�佷笉涓�鑷达紝闇�瑕侀噸鏂拌闃�')
+ // console.warn('鏈湴鐘舵�佷笌寰俊瀹樻柟鐘舵�佷笉涓�鑷达紝闇�瑕侀噸鏂拌闃�')
// 娓呴櫎鏈湴璁板綍
- uni.removeStorageSync('hasSubscribedTaskNotify')
+ // uni.removeStorageSync('hasSubscribedTaskNotify')
}
-
+
return {
local: localStatus,
wechat: wechatStatus,
@@ -175,7 +202,7 @@
* @returns {Promise}
*/
async subscribeTaskNotify(options = {}) {
- const {
+ const {
showConfirm = true,
onSuccess,
onReject,
@@ -208,7 +235,7 @@
success: (res) => {
console.log('璁㈤槄娑堟伅鎺堟潈缁撴灉锛�', res)
const templateId = this.wechatConfig.taskNotifyTemplateId
-
+
if (res[templateId] === 'accept') {
// 璁板綍宸茶闃�
uni.setStorageSync('hasSubscribedTaskNotify', true)
@@ -216,7 +243,7 @@
title: '璁㈤槄鎴愬姛',
icon: 'success'
})
-
+
if (onSuccess) onSuccess()
resolve({ success: true, action: 'accept' })
} else if (res[templateId] === 'reject') {
@@ -224,7 +251,7 @@
title: '鎮ㄦ嫆缁濅簡璁㈤槄',
icon: 'none'
})
-
+
if (onReject) onReject()
resolve({ success: false, action: 'reject' })
} else {
@@ -238,7 +265,7 @@
title: '璁㈤槄澶辫触',
icon: 'none'
})
-
+
if (onFail) onFail(err)
reject(err)
}
@@ -284,13 +311,13 @@
*/
async autoSubscribe(options = {}) {
const { force = false } = options
-
+
try {
// 缁煎悎妫�鏌ヨ闃呯姸鎬侊紙鏈湴 + 寰俊瀹樻柟锛�
const status = await this.checkSubscribeStatus()
-
+
console.log('璁㈤槄鐘舵�佹鏌ョ粨鏋滐細', status)
-
+
// 濡傛灉寰俊瀹樻柟鐘舵�佹樉绀哄凡璁㈤槄锛屼笖涓嶅己鍒惰闃�
if (status.isSubscribed && !force) {
console.log('鐢ㄦ埛宸茶闃呰繃锛堝井淇″畼鏂圭姸鎬侊級锛岃烦杩囪嚜鍔ㄨ闃�')
@@ -302,8 +329,9 @@
console.log('妫�娴嬪埌璁㈤槄鐘舵�佸け鏁堬紝瑙﹀彂閲嶆柊璁㈤槄娴佺▼')
} else {
console.log('鐢ㄦ埛鏈闃咃紝瑙﹀彂鑷姩璁㈤槄娴佺▼')
+ return { success: false, action: 'not_subscribed', skipped: true, status }
}
-
+
// 鏄剧ず纭寮圭獥骞惰闃� 鐩存帴榛樿璁㈤槄
const result = await this.subscribeWithConfirm();
return { ...result, status }
diff --git a/clean-logs.bat b/clean-logs.bat
new file mode 100644
index 0000000..b4ce404
--- /dev/null
+++ b/clean-logs.bat
@@ -0,0 +1,48 @@
+@echo off
+REM ============================================
+REM 鏃ュ織娓呯悊鑴氭湰 - Windows鐗堟湰
+REM 鐢ㄩ��: 娓呯悊瓒呰繃鎸囧畾澶╂暟鐨勬棩蹇楁枃浠�
+REM 浣跨敤: clean-logs.bat [澶╂暟] 榛樿30澶�
+REM ============================================
+
+setlocal enabledelayedexpansion
+
+REM 璁剧疆榛樿淇濈暀澶╂暟
+set DAYS=30
+if not "%1"=="" set DAYS=%1
+
+REM 鏃ュ織鐩綍
+set LOG_DIR=logs
+
+echo ========================================
+echo 鏃ュ織娓呯悊宸ュ叿
+echo ========================================
+echo 鏃ュ織鐩綍: %LOG_DIR%
+echo 淇濈暀澶╂暟: %DAYS% 澶�
+echo ========================================
+echo.
+
+REM 妫�鏌ユ棩蹇楃洰褰曟槸鍚﹀瓨鍦�
+if not exist "%LOG_DIR%" (
+ echo [閿欒] 鏃ュ織鐩綍涓嶅瓨鍦�: %LOG_DIR%
+ goto :end
+)
+
+echo 寮�濮嬫竻鐞� %DAYS% 澶╁墠鐨勬棩蹇楁枃浠�...
+echo.
+
+REM 娓呯悊鏃ф棩蹇楁枃浠�
+forfiles /p "%LOG_DIR%" /m *.log /d -%DAYS% /c "cmd /c echo 鍒犻櫎: @path && del @path" 2>nul
+
+if %errorlevel% equ 0 (
+ echo.
+ echo [鎴愬姛] 鏃ュ織娓呯悊瀹屾垚锛�
+) else (
+ echo.
+ echo [鎻愮ず] 娌℃湁鎵惧埌闇�瑕佹竻鐞嗙殑鏃ュ織鏂囦欢
+)
+
+:end
+echo.
+pause
+
diff --git "a/doc/\346\227\245\345\277\227\344\274\230\345\214\226\350\257\264\346\230\216.md" "b/doc/\346\227\245\345\277\227\344\274\230\345\214\226\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..235615f
--- /dev/null
+++ "b/doc/\346\227\245\345\277\227\344\274\230\345\214\226\350\257\264\346\230\216.md"
@@ -0,0 +1,306 @@
+# 鐢熶骇鐜鏃ュ織浼樺寲璇存槑
+
+## 馃搵 浼樺寲鍐呭鎬昏
+
+### 1. **鏃ュ織绾у埆浼樺寲**
+- 鉁� 鐢熶骇鐜鍏ㄥ眬鏃ュ織绾у埆浠� `INFO` 璋冩暣涓� `WARN`
+- 鉁� 绯荤粺妯″潡 `com.ruoyi` 浠� `INFO` 璋冩暣涓� `WARN`
+- 鉁� Spring 妗嗘灦浠� `WARN` 璋冩暣涓� `ERROR`
+- 鉁� 绗笁鏂圭粍浠讹紙Druid銆丮yBatis銆丠TTP瀹㈡埛绔級璁句负 `ERROR`
+
+### 2. **鏃ュ織鏂囦欢绠$悊浼樺寲**
+- 鉁� 鍗曚釜鏃ュ織鏂囦欢鏈�澶� **100MB**锛堣秴杩囧悗鑷姩鍒囧壊锛�
+- 鉁� INFO鏃ュ織淇濈暀 **30澶�**锛堝師60澶╋級
+- 鉁� ERROR鏃ュ織淇濈暀 **60澶�**锛堜繚鎸佷笉鍙橈級
+- 鉁� 鐢ㄦ埛鏃ュ織淇濈暀 **30澶�**锛堝師60澶╋級
+- 鉁� 鎱QL鏃ュ織淇濈暀 **15澶�**
+- 鉁� 鏃ュ織鎬诲ぇ灏忛檺鍒讹細
+ - INFO鏃ュ織: 10GB
+ - ERROR鏃ュ織: 5GB
+ - 鐢ㄦ埛鏃ュ織: 5GB
+ - 鎱QL鏃ュ織: 2GB
+
+### 3. **鏃ュ織鏂囦欢鍛藉悕**
+浼樺寲鍚庣殑鏃ュ織鏂囦欢鍛藉悕鏍煎紡锛�
+```
+sys-info.2025-12-06.0.log # 褰撳ぉ绗�1涓枃浠�
+sys-info.2025-12-06.1.log # 褰撳ぉ绗�2涓枃浠讹紙鍓嶄竴涓秴杩�100MB锛�
+sys-error.2025-12-06.0.log
+sys-user.2025-12-06.0.log
+slow-sql.2025-12-06.0.log # 鏂板鎱QL鏃ュ織
+```
+
+### 4. **鐜闅旂**
+- **寮�鍙�/娴嬭瘯鐜** (`dev`, `test`)
+ - 鏃ュ織绾у埆: INFO
+ - 杈撳嚭鍒版帶鍒跺彴 + 鏂囦欢
+ - 鍖呭惈SQL璋冭瘯鏃ュ織
+
+- **鐢熶骇鐜** (`prod`)
+ - 鏃ュ織绾у埆: WARN
+ - 浠呰緭鍑哄埌鏂囦欢锛堜笉杈撳嚭鎺у埗鍙帮紝鑺傜渷璧勬簮锛�
+ - 鎱QL鍗曠嫭璁板綍
+
+### 5. **鐗瑰畾妯″潡淇濈暀INFO鏃ュ織**
+浠ヤ笅妯″潡鍦ㄧ敓浜х幆澧冧粛淇濈暀INFO绾у埆锛堜究浜庨棶棰樻帓鏌ワ級锛�
+- `LegacySystemSyncServiceImpl` - 鏃х郴缁熷悓姝ユ湇鍔�
+- `VehicleGpsSegmentMileageServiceImpl` - GPS閲岀▼璁$畻鏈嶅姟
+
+---
+
+## 馃敡 閰嶇疆鏂囦欢璇存槑
+
+### logback.xml 鏍稿績閰嶇疆
+
+#### 鏃ュ織绾у埆璁剧疆
+```xml
+<!-- 鐢熶骇鐜 -->
+<springProfile name="prod">
+ <!-- 鍏ㄥ眬WARN绾у埆锛屽噺灏�90%鐨処NFO鏃ュ織 -->
+ <logger name="com.ruoyi" level="warn" />
+ <logger name="org.springframework" level="error" />
+
+ <!-- 閲嶈涓氬姟妯″潡淇濈暀INFO -->
+ <logger name="com.ruoyi.system.service.impl.LegacySystemSyncServiceImpl" level="info" />
+</springProfile>
+```
+
+#### 鏃ュ織婊氬姩绛栫暐
+```xml
+<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <!-- 鎸夊ぉ鍒嗗壊锛屾寜澶у皬鍒嗗壊 -->
+ <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <maxFileSize>100MB</maxFileSize> <!-- 鍗曟枃浠舵渶澶�100MB -->
+ <maxHistory>30</maxHistory> <!-- 淇濈暀30澶� -->
+ <totalSizeCap>10GB</totalSizeCap> <!-- 鎬诲ぇ灏忎笉瓒呰繃10GB -->
+</rollingPolicy>
+```
+
+---
+
+## 馃搳 浼樺寲鏁堟灉棰勪及
+
+### 鏃ュ織閲忓噺灏戝姣�
+
+| 鐜 | 浼樺寲鍓� | 浼樺寲鍚� | 鍑忓皯姣斾緥 |
+|------|--------|--------|----------|
+| **鏃ュ織绾у埆** | INFO | WARN | - |
+| **姣忔棩鏃ュ織閲�** | ~2-5GB | ~200-500MB | **80-90% 鈫�** |
+| **纾佺洏鍗犵敤** | ~120GB (60澶�) | ~15GB (30澶�) | **87.5% 鈫�** |
+| **I/O鍘嬪姏** | 楂� | 浣� | **80% 鈫�** |
+
+### 鎬ц兘鎻愬崌
+
+- 鉁� 鍑忓皯鏃ュ織鍐欏叆鐨� I/O 鎿嶄綔
+- 鉁� 闄嶄綆纾佺洏绌洪棿鍗犵敤
+- 鉁� 鍑忓皯鏃ュ織褰掓。鍘嬪姏
+- 鉁� 鎻愰珮鏃ュ織鏌ヨ鏁堢巼
+
+---
+
+## 馃搨 鏃ュ織鏂囦欢鍒嗙被
+
+### 1. sys-info.log
+- **鍐呭**: WARN绾у埆鐨勪笟鍔℃棩蹇�
+- **澶у皬**: 鍗曟枃浠�100MB
+- **淇濈暀**: 30澶╋紝鎬婚噺10GB
+- **鐢ㄩ��**: 鏃ュ父涓氬姟鐩戞帶
+
+### 2. sys-error.log
+- **鍐呭**: ERROR绾у埆鐨勯敊璇棩蹇�
+- **澶у皬**: 鍗曟枃浠�100MB
+- **淇濈暀**: 60澶╋紝鎬婚噺5GB
+- **鐢ㄩ��**: 閿欒鎺掓煡銆佹晠闅滃垎鏋�
+
+### 3. sys-user.log
+- **鍐呭**: 鐢ㄦ埛鎿嶄綔瀹¤鏃ュ織
+- **澶у皬**: 鍗曟枃浠�100MB
+- **淇濈暀**: 30澶╋紝鎬婚噺5GB
+- **鐢ㄩ��**: 鐢ㄦ埛琛屼负瀹¤
+
+### 4. slow-sql.log 猸� 鏂板
+- **鍐呭**: 鎱QL鏌ヨ鏃ュ織锛�>1000ms锛�
+- **澶у皬**: 鍗曟枃浠�50MB
+- **淇濈暀**: 15澶╋紝鎬婚噺2GB
+- **鐢ㄩ��**: 鏁版嵁搴撴�ц兘浼樺寲
+
+---
+
+## 馃洜锔� 鏃ュ織绠$悊宸ュ叿
+
+### 鎵嬪姩娓呯悊鏃ュ織
+```bash
+# Windows
+clean-logs.bat # 娓呯悊30澶╁墠鐨勬棩蹇�
+clean-logs.bat 15 # 娓呯悊15澶╁墠鐨勬棩蹇�
+
+# Linux (濡傞渶瑕佸彲鍒涘缓)
+./clean-logs.sh
+./clean-logs.sh 15
+```
+
+### 鏌ョ湅鏃ュ織缁熻
+```bash
+# 鏌ョ湅鏃ュ織鐩綍澶у皬
+cd logs
+dir /s
+
+# 鏌ョ湅鎱QL鏃ュ織
+type slow-sql.2025-12-06.0.log
+
+# 缁熻ERROR鏁伴噺
+findstr /c:"ERROR" sys-error.2025-12-06.0.log
+```
+
+---
+
+## 馃幆 浣跨敤寤鸿
+
+### 1. 浠g爜涓殑鏃ュ織浣跨敤瑙勮寖
+
+#### 鉁� 鎺ㄨ崘鍋氭硶
+```java
+// 鐢熶骇鐜寤鸿浣跨敤WARN绾у埆璁板綍閲嶈淇℃伅
+log.warn("浠诲姟鎵ц澶辫触锛屼换鍔D: {}, 鍘熷洜: {}", taskId, reason);
+
+// ERROR绾у埆璁板綍寮傚父
+log.error("鏁版嵁搴撹繛鎺ュけ璐�", exception);
+
+// INFO绾у埆浠呯敤浜庡叧閿笟鍔℃祦绋嬶紙浼氳璁板綍锛�
+log.info("璋冨害鍗曞悓姝ュ畬鎴愶紝浠诲姟ID: {}", taskId);
+```
+
+#### 鉂� 閬垮厤鍋氭硶
+```java
+// 閬垮厤鍦ㄥ惊鐜腑浣跨敤INFO鏃ュ織锛堢敓浜х幆澧冨凡鏀逛负WARN锛屼笉浼氳褰曪級
+for (Task task : tasks) {
+ log.info("澶勭悊浠诲姟: {}", task.getId()); // 鉂� 涓嶄細璁板綍
+}
+
+// 閬垮厤璁板綍澶ч噺璋冭瘯淇℃伅
+log.info("瀹屾暣鏁版嵁: {}", JSON.toJSONString(largeObject)); // 鉂� 涓嶄細璁板綍
+```
+
+### 2. 鎬ц兘鐩戞帶鍏虫敞鐐�
+
+#### 鎱QL鏃ュ織鐩戞帶
+```bash
+# 姣忓ぉ妫�鏌ユ參SQL鏃ュ織
+type logs\slow-sql.2025-12-06.0.log
+
+# 閲嶇偣鍏虫敞锛�
+# - 鎵ц鏃堕棿瓒呰繃1绉掔殑SQL
+# - 閲嶅鍑虹幇鐨勬參SQL
+# - 琛ㄦ壂鎻忥紙鍏ㄨ〃鎵弿锛�
+```
+
+#### 閿欒鏃ュ織鐩戞帶
+```bash
+# 姣忓ぉ妫�鏌ラ敊璇棩蹇�
+type logs\sys-error.2025-12-06.0.log
+
+# 閲嶇偣鍏虫敞锛�
+# - 鏁版嵁搴撹繛鎺ュ紓甯�
+# - 绌烘寚閽堝紓甯�
+# - 涓氬姟閫昏緫閿欒
+```
+
+### 3. 鏃ュ織鍒嗘瀽
+
+#### 浣跨敤鏃ュ織鍒嗘瀽宸ュ叿
+鎺ㄨ崘浣跨敤浠ヤ笅宸ュ叿鍒嗘瀽鏃ュ織锛�
+- **Logstash + Elasticsearch + Kibana (ELK)**
+- **Splunk**
+- **Graylog**
+- **鏈湴宸ュ叿**: Notepad++, VS Code
+
+#### 甯哥敤鍒嗘瀽鍛戒护
+```bash
+# 缁熻閿欒娆℃暟
+findstr /c:"ERROR" logs\sys-error.*.log | find /c "ERROR"
+
+# 鏌ユ壘鐗瑰畾鍏抽敭璇�
+findstr /c:"slow sql" logs\sys-info.*.log
+
+# 鏌ョ湅鏈�杩戠殑閿欒
+powershell "Get-Content logs\sys-error.log -Tail 50"
+```
+
+---
+
+## 鈿狅笍 娉ㄦ剰浜嬮」
+
+### 1. 鍗囩骇鍚庨娆¤繍琛�
+- 鏃ф棩蹇楁枃浠朵笉浼氳嚜鍔ㄥ垹闄わ紝闇�鎵嬪姩娓呯悊
+- 鏂扮殑鏃ュ織鏂囦欢鍚嶅寘鍚簭鍙� `.%i`
+
+### 2. 纾佺洏绌洪棿鐩戞帶
+- 寤鸿璁剧疆纾佺洏绌洪棿鍛婅锛堜綆浜�10GB锛�
+- 瀹氭湡妫�鏌ユ棩蹇楃洰褰曞ぇ灏�
+
+### 3. 鏃ュ織绾у埆璋冩暣
+濡傛灉鐢熶骇鐜闇�瑕佷复鏃跺惎鐢―EBUG鏃ュ織鎺掓煡闂锛�
+```xml
+<!-- 涓存椂淇敼logback.xml -->
+<springProfile name="prod">
+ <!-- 涓存椂鍚敤DEBUG -->
+ <logger name="com.ruoyi.system.service.impl.SysTaskServiceImpl" level="debug" />
+</springProfile>
+```
+
+璁板緱闂鎺掓煡鍚庢敼鍥� `warn` 绾у埆锛�
+
+### 4. 鎱QL闃堝�艰皟鏁�
+鍦� `application-prod.yml` 涓彲浠ヨ皟鏁存參SQL闃堝�硷細
+```yaml
+druid:
+ filter:
+ stat:
+ slow-sql-millis: 1000 # 璋冩暣涓�500ms鎴�2000ms
+```
+
+---
+
+## 馃攧 鍥炴粴鏂规
+
+濡傛灉浼樺寲鍚庡彂鐜伴棶棰橈紝鍙互蹇�熷洖婊氾細
+
+### 鏂规1: 淇敼鏃ュ織绾у埆
+```xml
+<!-- 鍦╨ogback.xml涓慨鏀� -->
+<springProfile name="prod">
+ <logger name="com.ruoyi" level="info" /> <!-- 鏀瑰洖info -->
+</springProfile>
+```
+
+### 鏂规2: 鎭㈠鍘熼厤缃�
+淇濈暀浜嗘棫閰嶇疆鐨勫浠斤紝鍙互浠嶨it鎭㈠锛�
+```bash
+git checkout HEAD~1 -- ruoyi-admin/src/main/resources/logback.xml
+```
+
+---
+
+## 馃摓 闂鍙嶉
+
+濡傚彂鐜颁互涓嬫儏鍐碉紝璇峰強鏃惰皟鏁撮厤缃細
+- 鉂� 閲嶈鏃ュ織娌℃湁璁板綍锛堟彁鍗囩浉鍏虫ā鍧楁棩蹇楃骇鍒級
+- 鉂� 鏃ュ織閲忎粛鐒惰繃澶э紙闄嶄綆鏃ュ織绾у埆鎴栧噺灏戜繚鐣欏ぉ鏁帮級
+- 鉂� 纾佺洏绌洪棿涓嶈冻锛堝噺灏� totalSizeCap 鎴� maxHistory锛�
+- 鉁� 闇�瑕佹洿璇︾粏鐨勮皟璇曚俊鎭紙涓存椂鍚敤DEBUG绾у埆锛�
+
+---
+
+## 馃搱 鍚庣画浼樺寲寤鸿
+
+1. **寮曞叆鏃ュ織鑱氬悎绯荤粺** (ELK Stack)
+2. **瀹炴椂鏃ュ織鐩戞帶鍛婅**
+3. **鎸変笟鍔℃ā鍧楀垎绂绘棩蹇楁枃浠�**
+4. **鏃ュ織閲囨牱**锛堥珮娴侀噺鎺ュ彛锛�
+5. **寮傛鏃ュ織鍐欏叆**锛堟彁鍗囨�ц兘锛�
+
+---
+
+**鏇存柊鏃堕棿**: 2025-12-06
+**浼樺寲鐗堟湰**: v2.0
+**缁存姢浜�**: 寮�鍙戝洟闃�
diff --git a/run_sms_service_tests.bat b/run_sms_service_tests.bat
new file mode 100644
index 0000000..84e63ce
--- /dev/null
+++ b/run_sms_service_tests.bat
@@ -0,0 +1,9 @@
+@echo off
+echo Running SmsService tests...
+cd /d "D:\project\鎬ユ晳杞繍\code\Api\RuoYi-Vue-master"
+echo.
+echo Running all SMS service tests...
+mvn test -pl ruoyi-system -Dtest=com.ruoyi.system.service.impl.SmsServiceAllTests
+echo.
+echo All tests completed.
+pause
\ No newline at end of file
diff --git a/run_sms_test.bat b/run_sms_test.bat
new file mode 100644
index 0000000..c79cbdf
--- /dev/null
+++ b/run_sms_test.bat
@@ -0,0 +1,5 @@
+@echo off
+echo Running SMS Service Test...
+cd /d "D:\project\鎬ユ晳杞繍\code\Api\RuoYi-Vue-master"
+mvn test -pl ruoyi-system -Dtest=SmsServiceImplTest
+pause
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/sms/NotifyController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/sms/NotifyController.java
new file mode 100644
index 0000000..9520acc
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/sms/NotifyController.java
@@ -0,0 +1,31 @@
+package com.ruoyi.web.controller.sms;
+
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.system.service.IWechatTaskNotifyService;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@Anonymous
+@RestController
+@RequestMapping("/system/notify")
+public class NotifyController {
+
+ @Autowired
+ private IWechatTaskNotifyService wechatTaskNotifyService;
+ @Anonymous
+ @PostMapping("/sendWeiXin")
+ public String notify(@RequestBody @Validated SendTaskReq req) {
+ List<Long> userIds = new java.util.ArrayList<>();
+ userIds.add(req.getUserId());
+ Integer result=wechatTaskNotifyService.sendTaskNotifyMessage(req.getTaskId(), userIds,null);
+ System.out.println(result);
+ return "success";
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/sms/SendTaskReq.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/sms/SendTaskReq.java
new file mode 100644
index 0000000..4c94294
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/sms/SendTaskReq.java
@@ -0,0 +1,12 @@
+package com.ruoyi.web.controller.sms;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class SendTaskReq implements Serializable {
+ private Long taskId;
+ private Long userId;
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/sms/SmsController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/sms/SmsController.java
new file mode 100644
index 0000000..4e39ab6
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/sms/SmsController.java
@@ -0,0 +1,43 @@
+package com.ruoyi.web.controller.sms;
+
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.system.controller.SmsSendController;
+import com.ruoyi.system.controller.SmsSendReq;
+import com.ruoyi.system.domain.OrderStatusCallBackVo;
+import com.ruoyi.web.controller.system.ServiceOrderController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+@Anonymous
+@RestController
+@RequestMapping("/system/sms")
+public class SmsController extends BaseController {
+
+ private static final Logger log = LoggerFactory.getLogger(SmsController.class);
+
+
+ @Autowired
+ private SmsSendController smsSendController;
+
+ @Anonymous
+ @PostMapping("/send")
+ public AjaxResult sendSms(@RequestBody SmsSendReq req) {
+ try {
+ String result= smsSendController.sendSms(req);
+ return AjaxResult.success(result);
+ } catch (Exception e) {
+ return AjaxResult.error("鍙戦�佸け璐ワ細" + e.getMessage());
+ }
+ }
+
+
+}
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/NotifyChannelConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/NotifyChannelConfigController.java
new file mode 100644
index 0000000..f661b05
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/NotifyChannelConfigController.java
@@ -0,0 +1,77 @@
+package com.ruoyi.web.controller.system;
+
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.NotifyChannelConfig;
+import com.ruoyi.system.service.INotifyChannelConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 閫氱煡娓犻亾閰嶇疆Controller
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+@RestController
+@RequestMapping("/system/notify/channel/config")
+public class NotifyChannelConfigController extends BaseController {
+ @Autowired
+ private INotifyChannelConfigService notifyChannelConfigService;
+
+ /**
+ * 鏌ヨ閫氱煡娓犻亾閰嶇疆鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:notify:channel:config:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(NotifyChannelConfig notifyChannelConfig) {
+ startPage();
+ List<NotifyChannelConfig> list = notifyChannelConfigService.selectNotifyChannelConfigList(notifyChannelConfig);
+ return getDataTable(list);
+ }
+
+ /**
+ * 鑾峰彇閫氱煡娓犻亾閰嶇疆璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:notify:channel:config:query')")
+ @GetMapping(value = "/{id}")
+ public AjaxResult getInfo(@PathVariable("id") Long id) {
+ return AjaxResult.success(notifyChannelConfigService.selectNotifyChannelConfigById(id));
+ }
+
+ /**
+ * 鏂板閫氱煡娓犻亾閰嶇疆
+ */
+ @PreAuthorize("@ss.hasPermi('system:notify:channel:config:add')")
+ @Log(title = "閫氱煡娓犻亾閰嶇疆", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@RequestBody NotifyChannelConfig notifyChannelConfig) {
+ return toAjax(notifyChannelConfigService.insertNotifyChannelConfig(notifyChannelConfig));
+ }
+
+ /**
+ * 淇敼閫氱煡娓犻亾閰嶇疆
+ */
+ @PreAuthorize("@ss.hasPermi('system:notify:channel:config:edit')")
+ @Log(title = "閫氱煡娓犻亾閰嶇疆", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@RequestBody NotifyChannelConfig notifyChannelConfig) {
+ return toAjax(notifyChannelConfigService.updateNotifyChannelConfig(notifyChannelConfig));
+ }
+
+ /**
+ * 鍒犻櫎閫氱煡娓犻亾閰嶇疆
+ */
+ @PreAuthorize("@ss.hasPermi('system:notify:channel:config:remove')")
+ @Log(title = "閫氱煡娓犻亾閰嶇疆", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public AjaxResult remove(@PathVariable Long[] ids) {
+ return toAjax(notifyChannelConfigService.deleteNotifyChannelConfigByIds(ids));
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/ServiceOrderController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/ServiceOrderController.java
index 4205f96..421a54a 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/ServiceOrderController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/ServiceOrderController.java
@@ -287,7 +287,7 @@
//鐭ユ儏鍚屾剰涔�
List<String> imageUrls = dispatchOrdService.selectImageUrlsByDOrdIDDt(orderDetail.getServiceOrdID()); //姝e紡浣跨敤
otherInfo.put("imageUrls", imageUrls);
- log.info("銆愮洃娴嬨�戠煡鎯呭悓鎰忎功:{}", imageUrls);
+// log.info("銆愮洃娴嬨�戠煡鎯呭悓鎰忎功:{}", imageUrls);
//鍙戠エ鑾峰彇
Map<String, Object> invoiceInfo = new HashMap<>();
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java
index cc7dd4d..0d9b76a 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java
@@ -142,7 +142,7 @@
@PostMapping("/assign")
public AjaxResult assignVehicle(@RequestBody AssignVehicleRequest request) {
try {
- int result = sysTaskVehicleService.assignVehicleToTask(request.getTaskId(), request.getVehicleId(), request.getRemark());
+ int result = sysTaskVehicleService.assignVehicleToTask(request.getTaskId(), request.getVehicleId(), request.getRemark(), getUserId(), getUsername());
if (result > 0) {
return success("鍒嗛厤鎴愬姛");
} else {
@@ -161,7 +161,7 @@
@PostMapping("/assign-batch")
public AjaxResult assignVehicles(@RequestBody BatchAssignVehicleRequest request) {
try {
- int result = sysTaskVehicleService.assignMultipleVehiclesToTask(request.getTaskId(), request.getVehicleIds(), request.getRemark());
+ int result = sysTaskVehicleService.assignMultipleVehiclesToTask(request.getTaskId(), request.getVehicleIds(), request.getRemark(), getUserId(), getUsername());
if (result > 0) {
return success("鎵归噺鍒嗛厤鎴愬姛锛屽叡鍒嗛厤 " + result + " 杈嗚溅");
} else {
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 8ab857f..105bc73 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -247,4 +247,19 @@
# 瀵硅处閰嶇疆
reconciliation:
enabled: true
- cron: "0 0 2 * * ?"
\ No newline at end of file
+ cron: "0 0 2 * * ?"
+
+# 鐭俊鏈嶅姟閰嶇疆
+sms:
+ # 鏄惁鍚敤鐭俊鍔熻兘锛堝彲鍦ㄦ暟鎹簱sys_config涓�氳繃sms.enabled閰嶇疆锛屼紭鍏堢骇鏇撮珮锛�
+ enabled: false
+ # 鐭俊鏈嶅姟鍦板潃
+ address: sms.izjun.com:8001
+ # 鐭俊璐﹀彿鐢ㄦ埛鍚�
+ userName: gdmhhy
+ # 鐭俊璐﹀彿瀵嗙爜
+ password: lLsZyz3YVYKQ
+ # 鐭俊绛惧悕
+ signName: "銆�966120鎬ユ晳杞繍銆�"
+ # 浠诲姟鍒嗛厤閫氱煡妯℃澘
+ taskAssignTemplate: "鎮ㄦ湁鏂扮殑杞繍浠诲姟锛屽嚭鍙戝湴:{departure}锛岀洰鐨勫湴:{destination}锛岃鍙婃椂澶勭悊銆�"
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml
index a8c526e..8c3fc6f 100644
--- a/ruoyi-admin/src/main/resources/logback.xml
+++ b/ruoyi-admin/src/main/resources/logback.xml
@@ -4,6 +4,10 @@
<property name="log.path" value="./logs" />
<!-- 鏃ュ織杈撳嚭鏍煎紡 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
+ <!-- 鍗曚釜鏃ュ織鏂囦欢鏈�澶уぇ灏� -->
+ <property name="log.maxFileSize" value="100MB" />
+ <!-- 鏃ュ織鏂囦欢鎬诲ぇ灏忎笂闄� -->
+ <property name="log.totalSizeCap" value="10GB" />
<!-- 鎺у埗鍙拌緭鍑� -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
@@ -15,12 +19,16 @@
<!-- 绯荤粺鏃ュ織杈撳嚭 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
- <!-- 寰幆鏀跨瓥锛氬熀浜庢椂闂村垱寤烘棩蹇楁枃浠� -->
- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <!-- 寰幆鏀跨瓥锛氬熀浜庢椂闂村拰澶у皬鍒涘缓鏃ュ織鏂囦欢 -->
+ <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 鏃ュ織鏂囦欢鍚嶆牸寮� -->
- <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
- <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
- <maxHistory>60</maxHistory>
+ <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <!-- 鍗曚釜鏃ュ織鏂囦欢鏈�澶уぇ灏� -->
+ <maxFileSize>${log.maxFileSize}</maxFileSize>
+ <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 30澶╋紙鐢熶骇鐜鍑忓皯淇濈暀鏃堕棿锛� -->
+ <maxHistory>30</maxHistory>
+ <!-- 鏃ュ織鏂囦欢鎬诲ぇ灏忎笂闄� -->
+ <totalSizeCap>${log.totalSizeCap}</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
@@ -37,12 +45,16 @@
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
- <!-- 寰幆鏀跨瓥锛氬熀浜庢椂闂村垱寤烘棩蹇楁枃浠� -->
- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <!-- 寰幆鏀跨瓥锛氬熀浜庢椂闂村拰澶у皬鍒涘缓鏃ュ織鏂囦欢 -->
+ <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 鏃ュ織鏂囦欢鍚嶆牸寮� -->
- <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
- <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
+ <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <!-- 鍗曚釜鏃ュ織鏂囦欢鏈�澶уぇ灏� -->
+ <maxFileSize>${log.maxFileSize}</maxFileSize>
+ <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶╋紙閿欒鏃ュ織淇濈暀鏇撮暱鏃堕棿锛� -->
<maxHistory>60</maxHistory>
+ <!-- 鏃ュ織鏂囦欢鎬诲ぇ灏忎笂闄� -->
+ <totalSizeCap>5GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
@@ -60,31 +72,81 @@
<!-- 鐢ㄦ埛璁块棶鏃ュ織杈撳嚭 -->
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-user.log</file>
- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 鎸夊ぉ鍥炴粴 daily -->
- <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
- <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
- <maxHistory>60</maxHistory>
+ <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <!-- 鍗曚釜鏃ュ織鏂囦欢鏈�澶уぇ灏� -->
+ <maxFileSize>${log.maxFileSize}</maxFileSize>
+ <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 30澶� -->
+ <maxHistory>30</maxHistory>
+ <!-- 鏃ュ織鏂囦欢鎬诲ぇ灏忎笂闄� -->
+ <totalSizeCap>5GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
- <!-- 绯荤粺妯″潡鏃ュ織绾у埆鎺у埗 -->
- <logger name="com.ruoyi" level="info" />
- <!-- Spring鏃ュ織绾у埆鎺у埗 -->
- <logger name="org.springframework" level="warn" />
-
- <root level="info">
- <appender-ref ref="console" />
- </root>
+ <!-- 鎱QL鏃ュ織鍗曠嫭杈撳嚭锛堜究浜庢�ц兘鐩戞帶鍜屼紭鍖栵級 -->
+ <appender name="slow-sql" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${log.path}/slow-sql.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <fileNamePattern>${log.path}/slow-sql.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <maxFileSize>50MB</maxFileSize>
+ <maxHistory>15</maxHistory>
+ <totalSizeCap>2GB</totalSizeCap>
+ </rollingPolicy>
+ <encoder>
+ <pattern>${log.pattern}</pattern>
+ </encoder>
+ </appender>
- <!--绯荤粺鎿嶄綔鏃ュ織-->
- <root level="info">
- <appender-ref ref="file_info" />
- <appender-ref ref="file_error" />
- </root>
+ <!-- 寮�鍙戠幆澧冮厤缃� -->
+ <springProfile name="dev,test">
+ <!-- 绯荤粺妯″潡鏃ュ織绾у埆鎺у埗 -->
+ <logger name="com.ruoyi" level="info" />
+ <!-- Spring鏃ュ織绾у埆鎺у埗 -->
+ <logger name="org.springframework" level="warn" />
+ <!-- MyBatis SQL鏃ュ織 -->
+ <logger name="com.ruoyi.system.mapper" level="debug" />
+
+ <root level="info">
+ <appender-ref ref="console" />
+ <appender-ref ref="file_info" />
+ <appender-ref ref="file_error" />
+ </root>
+ </springProfile>
+
+ <!-- 鐢熶骇鐜閰嶇疆 -->
+ <springProfile name="prod">
+ <!-- 绯荤粺妯″潡鏃ュ織绾у埆鎺у埗锛堢敓浜х幆澧冭皟鏁翠负WARN锛屽噺灏慖NFO鏃ュ織锛� -->
+ <logger name="com.ruoyi" level="warn" />
+ <!-- Spring鏃ュ織绾у埆鎺у埗 -->
+ <logger name="org.springframework" level="error" />
+ <!-- Druid鏁版嵁婧愭棩蹇楁帶鍒� -->
+ <logger name="com.alibaba.druid" level="error" />
+ <!-- MyBatis鏃ュ織鎺у埗 -->
+ <logger name="org.mybatis" level="error" />
+ <logger name="org.apache.ibatis" level="error" />
+ <!-- HTTP瀹㈡埛绔棩蹇楁帶鍒� -->
+ <logger name="org.apache.http" level="error" />
+
+ <!-- 鐗瑰畾涓氬姟妯″潡淇濈暀INFO绾у埆锛堟牴鎹渶瑕佽皟鏁达級 -->
+ <logger name="com.ruoyi.system.service.impl.LegacySystemSyncServiceImpl" level="info" />
+ <logger name="com.ruoyi.system.service.impl.VehicleGpsSegmentMileageServiceImpl" level="info" />
+
+ <!-- 鎱QL鏃ュ織锛圖ruid鐩戞帶锛� -->
+ <logger name="druid.sql.Statement" level="warn" additivity="false">
+ <appender-ref ref="slow-sql" />
+ </logger>
+
+ <root level="warn">
+ <!-- 鐢熶骇鐜涓嶈緭鍑哄埌鎺у埗鍙帮紝鍑忓皯璧勬簮娑堣�� -->
+ <!-- <appender-ref ref="console" /> -->
+ <appender-ref ref="file_info" />
+ <appender-ref ref="file_error" />
+ </root>
+ </springProfile>
<!--绯荤粺鐢ㄦ埛鎿嶄綔鏃ュ織-->
<logger name="sys-user" level="info">
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/SmsConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/SmsConfig.java
new file mode 100644
index 0000000..90ff2d9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/SmsConfig.java
@@ -0,0 +1,81 @@
+package com.ruoyi.common.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鐭俊鏈嶅姟閰嶇疆绫�
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+@Component
+@ConfigurationProperties(prefix = "sms")
+public class SmsConfig {
+
+ /** 鏄惁鍚敤鐭俊鍔熻兘 */
+ private boolean enabled = false;
+
+ /** 鐭俊鏈嶅姟鍦板潃 */
+ private String address = "sms.izjun.com:8001";
+
+ /** 鐭俊璐﹀彿鐢ㄦ埛鍚� */
+ private String userName;
+
+ /** 鐭俊璐﹀彿瀵嗙爜 */
+ private String password;
+
+ /** 鐭俊绛惧悕 */
+ private String signName = "銆�966120鎬ユ晳杞繍銆�";
+
+ /** 浠诲姟鍒嗛厤閫氱煡妯℃澘 */
+ private String taskAssignTemplate = "鎮ㄦ湁鏂扮殑杞繍浠诲姟(缂栧彿:{taskCode})锛屽嚭鍙戝湴:{departure}锛岀洰鐨勫湴:{destination}锛岃鍙婃椂澶勭悊銆�";
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getSignName() {
+ return signName;
+ }
+
+ public void setSignName(String signName) {
+ this.signName = signName;
+ }
+
+ public String getTaskAssignTemplate() {
+ return taskAssignTemplate;
+ }
+
+ public void setTaskAssignTemplate(String taskAssignTemplate) {
+ this.taskAssignTemplate = taskAssignTemplate;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java
new file mode 100644
index 0000000..a457f5a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java
@@ -0,0 +1,244 @@
+package com.ruoyi.common.utils;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.utils.http.HttpUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鐭俊鍙戦�佸伐鍏风被
+ * 鍙傝�働HP鐗堟湰鐨凷msUtils瀹炵幇
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+public class SmsUtils {
+
+ private static final Logger log = LoggerFactory.getLogger(SmsUtils.class);
+
+
+ /**
+ * 鍙戦�� POST 璇锋眰
+ *
+ * @param url 鏈嶅姟鍣ㄥ湴鍧�
+ * @param data 璇锋眰鍙傛暟
+ * @return 鍝嶅簲鍐呭
+ * @throws IOException
+ */
+ public static String post(String url, String data) throws IOException {
+ HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
+ connection.setRequestMethod("POST");
+ connection.setRequestProperty("Content-Type", "application/json");
+ connection.setDoOutput(true);
+ try (OutputStream os = connection.getOutputStream()) {
+ os.write(data.getBytes(StandardCharsets.UTF_8));
+ os.flush();
+ }
+ StringBuilder response = new StringBuilder();
+ try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
+ String line;
+ while ((line = br.readLine()) != null) {
+ response.append(line);
+ }
+ }
+ return response.toString();
+ }
+
+ /**
+ * 璁$畻 MD5 鍊�
+ *
+ * @param str 瀛楃涓�
+ * @return MD5 鍊�
+ * @throws NoSuchAlgorithmException
+ */
+ public static String md5(String str) throws NoSuchAlgorithmException {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ byte[] array = md.digest(str.getBytes(StandardCharsets.UTF_8));
+ StringBuilder sb = new StringBuilder();
+ for (byte item : array) {
+ sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * 鑾峰彇褰撳墠鏃堕棿鎴筹紙姣锛�
+ *
+ * @return 鏃堕棿鎴冲瓧绗︿覆
+ */
+ public static Long getTimestamp() {
+ return System.currentTimeMillis();
+ }
+
+ /**
+ * 鐢熸垚绛惧悕
+ * 绛惧悕绠楁硶锛歁D5(userName + password + timestamp)
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @param password 瀵嗙爜
+ * @param timestamp 鏃堕棿鎴�
+ * @return 绛惧悕瀛楃涓�
+ */
+ public static String generateSign(String userName, String password, Long timestamp) throws NoSuchAlgorithmException {
+ // 鏃堕棿鎴�
+
+
+ // 璁$畻 sign 鍙傛暟
+ String sign = md5(userName + timestamp + md5(password));
+ return sign;
+ }
+
+ /**
+ * 鍙戦�丠TTP POST璇锋眰
+ *
+ * @param url 璇锋眰鍦板潃
+ * @param data 璇锋眰鏁版嵁
+ * @return 鍝嶅簲缁撴灉
+ */
+ public static JSONObject sendPost(String url, Map<String, Object> data) {
+ try {
+ String jsonData = JSON.toJSONString(data);
+ log.debug("鐭俊API璇锋眰锛孶RL锛歿}锛屾暟鎹細{}", url, jsonData);
+
+ String response = post(url,jsonData);;//HttpUtils.sendPost(url, jsonData, "application/json");
+ log.debug("鐭俊API鍝嶅簲锛歿}", response);
+
+ if (StringUtils.isNotEmpty(response)) {
+ return JSON.parseObject(response);
+ }
+ } catch (Exception e) {
+ log.error("鐭俊API璇锋眰澶辫触锛孶RL锛歿}", url, e);
+ }
+ return null;
+ }
+
+ /**
+ * 缇ゅ彂鐭俊
+ *
+ * @param address 鐭俊鏈嶅姟鍦板潃
+ * @param userName 璐﹀彿
+ * @param password 瀵嗙爜
+ * @param phoneList 鎵嬫満鍙峰垪琛紝澶氫釜鐢ㄩ�楀彿鍒嗛殧
+ * @param content 鐭俊鍐呭
+ * @return 鍙戦�佺粨鏋�
+ */
+ public static JSONObject sendSmsMass(String address, String userName, String password,
+ String phoneList, String content) throws NoSuchAlgorithmException{
+ Long timestamp = getTimestamp();
+ String sign = generateSign(userName, password, timestamp);
+ String url = "http://" + address + "/sms/api/sendMessageMass";
+
+ Map<String, Object> data = new HashMap<>();
+ data.put("userName", userName);
+ data.put("content", content);
+ data.put("phoneList", phoneList);
+ data.put("timestamp", timestamp);
+ data.put("sign", sign);
+ data.put("sendTime", "");
+ data.put("extCode", "");
+ data.put("callData", "");
+
+ return sendPost(url, data);
+ }
+
+ /**
+ * 鍗曟潯/鐐瑰鐐圭煭淇″彂閫�
+ *
+ * @param address 鐭俊鏈嶅姟鍦板潃
+ * @param userName 璐﹀彿
+ * @param password 瀵嗙爜
+ * @param messageList 娑堟伅鍒楄〃 [{phone: "鎵嬫満鍙�", content: "鍐呭"}, ...]
+ * @return 鍙戦�佺粨鏋�
+ */
+ public static JSONObject sendSmsOne(String address, String userName, String password,
+ List<Map<String, String>> messageList) throws NoSuchAlgorithmException {
+ Long timestamp = getTimestamp();
+ String sign = generateSign(userName, password, timestamp);
+ String url = "http://" + address + "/sms/api/sendMessageOne";
+
+ Map<String, Object> data = new HashMap<>();
+ data.put("userName", userName);
+ data.put("timestamp", timestamp);
+ data.put("sign", sign);
+ data.put("messageList", messageList);
+
+ return sendPost(url, data);
+ }
+
+ /**
+ * 鍙戦�佸崟鏉$煭淇★紙绠�鍖栨柟娉曪級
+ *
+ * @param address 鐭俊鏈嶅姟鍦板潃
+ * @param userName 璐﹀彿
+ * @param password 瀵嗙爜
+ * @param phone 鎵嬫満鍙�
+ * @param content 鐭俊鍐呭
+ * @return 鍙戦�佺粨鏋�
+ */
+ public static JSONObject sendSms(String address, String userName, String password,
+ String phone, String content) throws NoSuchAlgorithmException{
+ List<Map<String, String>> messageList = new ArrayList<>();
+ messageList.add(new HashMap<String, String>() {{
+ put("phone", phone);
+ put("content", content);
+ }});
+ return sendSmsOne(address, userName, password, messageList);
+ }
+
+ /**
+ * 鏌ヨ璐︽埛浣欓
+ *
+ * @param address 鐭俊鏈嶅姟鍦板潃
+ * @param userName 璐﹀彿
+ * @param password 瀵嗙爜
+ * @return 浣欓淇℃伅
+ */
+ public static JSONObject getBalance(String address, String userName, String password) throws NoSuchAlgorithmException {
+ Long timestamp = getTimestamp();
+ String sign = generateSign(userName, password, timestamp);
+ String url = "http://" + address + "/sms/api/getBalance";
+
+ Map<String, Object> data = new HashMap<>();
+ data.put("userName", userName);
+ data.put("timestamp", timestamp);
+ data.put("sign", sign);
+
+ return sendPost(url, data);
+ }
+
+ /**
+ * 鑾峰彇鍙戦�佹姤鍛�
+ *
+ * @param address 鐭俊鏈嶅姟鍦板潃
+ * @param userName 璐﹀彿
+ * @param password 瀵嗙爜
+ * @return 鍙戦�佹姤鍛�
+ */
+ public static JSONObject getReport(String address, String userName, String password) throws NoSuchAlgorithmException {
+ Long timestamp = getTimestamp();
+ String sign = generateSign(userName, password, timestamp);
+ String url = "http://" + address + "/sms/api/getReport";
+
+ Map<String, Object> data = new HashMap<>();
+ data.put("userName", userName);
+ data.put("timestamp", timestamp);
+ data.put("sign", sign);
+
+ return sendPost(url, data);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/civilAviation/ServiceOrderUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/civilAviation/ServiceOrderUtil.java
index da4efa0..bdc72da 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/civilAviation/ServiceOrderUtil.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/civilAviation/ServiceOrderUtil.java
@@ -49,7 +49,7 @@
return null;
}
- log.info("鎺ュ彛鍦板潃锛�"+addServiceOrederAPI);
+// log.info("鎺ュ彛鍦板潃锛�"+addServiceOrederAPI);
//璁$畻鏃堕棿鎴冲拰绛惧悕
long unixTime = System.currentTimeMillis() / 1000; // 鑾峰彇褰撳墠鏃堕棿鎴筹紙绉掞級 Long.valueOf("1746444543") ;//
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java
index 9770af6..1eb1cb1 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java
@@ -23,7 +23,7 @@
*/
public static void setDataSourceType(String dsType)
{
- log.info("鍒囨崲鍒皗}鏁版嵁婧�", dsType);
+// log.info("鍒囨崲鍒皗}鏁版嵁婧�", dsType);
CONTEXT_HOLDER.set(dsType);
}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CleanVehicleGpsTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CleanVehicleGpsTask.java
index 321d326..f177d1d 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CleanVehicleGpsTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CleanVehicleGpsTask.java
@@ -21,9 +21,9 @@
*/
public void cleanVehicleGpsData() {
try {
- log.info("寮�濮嬫竻鐞嗚溅杈咷PS鍘嗗彶鏁版嵁");
+// log.info("寮�濮嬫竻鐞嗚溅杈咷PS鍘嗗彶鏁版嵁");
int count = vehicleGpsService.deleteVehicleGpsBeforeDate();
- log.info("娓呯悊杞﹁締GPS鍘嗗彶鏁版嵁瀹屾垚锛屽叡娓呯悊{}鏉¤褰�", count);
+// log.info("娓呯悊杞﹁締GPS鍘嗗彶鏁版嵁瀹屾垚锛屽叡娓呯悊{}鏉¤褰�", count);
} catch (Exception e) {
log.error("娓呯悊杞﹁締GPS鍘嗗彶鏁版嵁寮傚父", e);
}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CmsVehicleSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CmsVehicleSyncTask.java
index 1694256..b006eb5 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CmsVehicleSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/CmsVehicleSyncTask.java
@@ -37,7 +37,7 @@
private IVehicleGpsService vehicleGpsService;
public void syncVehicleInfo() {
- log.info("寮�濮嬪悓姝MS杞﹁締淇℃伅");
+// log.info("寮�濮嬪悓姝MS杞﹁締淇℃伅");
try {
// 鑾峰彇CMS鎵�鏈夎溅杈嗕俊鎭�
CmsVehicleDeviceListResponse response = cmsGpsCollectService.getDeviceByVehicle(null);
@@ -94,7 +94,7 @@
vehicleInfo.setStatus("0");
vehicleInfoService.insertVehicleInfo(vehicleInfo);
syncCarCount++;
- log.info("鏂板CMS杞﹁締: {}", plateNo);
+// log.info("鏂板CMS杞﹁締: {}", plateNo);
} else {
// 鏇存柊杞﹁締 - 浠呮洿鏂板繀瑕佸瓧娈�,閬垮厤瑙﹀彂鍏宠仈琛ㄦ搷浣�
vehicleInfo.setDeviceId(vehicle.getDid());
@@ -103,7 +103,7 @@
vehicleInfo.setDeptIds(null); // 涓嶆洿鏂伴儴闂ㄥ叧鑱�,閬垮厤姝婚攣
vehicleInfoService.updateVehicleInfo(vehicleInfo);
syncCarCount++;
- log.debug("鏇存柊CMS杞﹁締: {}", plateNo);
+// log.debug("鏇存柊CMS杞﹁締: {}", plateNo);
}
success = true;
} catch (org.springframework.dao.DeadlockLoserDataAccessException e) {
@@ -127,8 +127,8 @@
- log.info("鎴愬姛鍚屾{}涓狢MS杞﹁締淇℃伅", syncCarCount);
- log.info("CMS杞﹁締淇℃伅鍚屾瀹屾垚");
+// log.info("鎴愬姛鍚屾{}涓狢MS杞﹁締淇℃伅", syncCarCount);
+// log.info("CMS杞﹁締淇℃伅鍚屾瀹屾垚");
} catch (Exception e) {
log.error("鍚屾CMS杞﹁締淇℃伅寮傚父", e);
}
@@ -154,7 +154,7 @@
* 鍚屾CMS杞﹁締浣嶇疆淇℃伅
*/
public void syncVehicleLocation() {
- log.info("寮�濮嬪悓姝MS杞﹁締浣嶇疆淇℃伅");
+// log.info("寮�濮嬪悓姝MS杞﹁締浣嶇疆淇℃伅");
try {
//鍏堣幏寰楁湰鍦癈MS涓婄殑鎵�鏈塁MS杞﹁締
VehicleInfo query = new VehicleInfo();
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/GpsSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/GpsSyncTask.java
index ac0f9f2..5292236 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/GpsSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/GpsSyncTask.java
@@ -41,7 +41,7 @@
*/
public void syncGpsData() {
try {
- log.info("寮�濮嬪悓姝PS鏁版嵁...");
+// log.info("寮�濮嬪悓姝PS鏁版嵁...");
// 1. 鑾峰彇鎵�鏈夎溅杈嗕俊鎭�
List<VehicleInfo> vehicleList = vehicleInfoService.selectVehicleInfoList(new VehicleInfo());
@@ -68,7 +68,7 @@
}
}
- log.info("GPS鏁版嵁鍚屾瀹屾垚");
+// log.info("GPS鏁版嵁鍚屾瀹屾垚");
} catch (Exception e) {
log.error("GPS鏁版嵁鍚屾澶辫触: {}", e.getMessage());
}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java
index c55b98f..3c724a9 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java
@@ -168,10 +168,10 @@
* 3. 鏈夎皟搴﹀崟ID鍜屾湇鍔″崟ID
*/
public void syncPendingAttachments() {
- log.info("寮�濮嬫墽琛屼换鍔¢檮浠跺悓姝ュ畾鏃朵换鍔�");
+// log.info("寮�濮嬫墽琛屼换鍔¢檮浠跺悓姝ュ畾鏃朵换鍔�");
try {
int successCount = taskAttachmentSyncService.batchSyncPendingAttachments();
- log.info("浠诲姟闄勪欢鍚屾瀹屾垚锛屾垚鍔熷悓姝�: {} 涓檮浠�", successCount);
+// log.info("浠诲姟闄勪欢鍚屾瀹屾垚锛屾垚鍔熷悓姝�: {} 涓檮浠�", successCount);
} catch (Exception e) {
log.error("浠诲姟闄勪欢鍚屾寮傚父", e);
}
@@ -188,10 +188,10 @@
* cron琛ㄨ揪寮�: 0 0/10 * * * ? (姣�10鍒嗛挓鎵ц涓�娆�)
*/
public void syncPaymentToLegacy() {
- log.info("寮�濮嬫墽琛屾敮浠樹俊鎭悓姝ュ畾鏃朵换鍔★紙鏂扮郴缁� -> 鏃х郴缁燂級");
+// log.info("寮�濮嬫墽琛屾敮浠樹俊鎭悓姝ュ畾鏃朵换鍔★紙鏂扮郴缁� -> 鏃х郴缁燂級");
try {
int successCount = paymentSyncService.batchSyncPaymentToLegacy();
- log.info("鏀粯淇℃伅鍚屾瀹屾垚锛屾垚鍔熷悓姝�: {} 鏉¤褰�", successCount);
+// log.info("鏀粯淇℃伅鍚屾瀹屾垚锛屾垚鍔熷悓姝�: {} 鏉¤褰�", successCount);
} catch (Exception e) {
log.error("鏀粯淇℃伅鍚屾寮傚父", e);
}
@@ -208,10 +208,10 @@
* cron琛ㄨ揪寮�: 0 0/15 * * * ? (姣�15鍒嗛挓鎵ц涓�娆�)
*/
public void syncPaymentFromLegacy() {
- log.info("寮�濮嬫墽琛屾敮浠樹俊鎭悓姝ュ畾鏃朵换鍔★紙鏃х郴缁� -> 鏂扮郴缁燂級");
+// log.info("寮�濮嬫墽琛屾敮浠樹俊鎭悓姝ュ畾鏃朵换鍔★紙鏃х郴缁� -> 鏂扮郴缁燂級");
try {
int successCount = paymentSyncService.batchSyncPaymentFromLegacy();
- log.info("鏀粯淇℃伅鍚屾瀹屾垚锛屾垚鍔熷悓姝�: {} 鏉¤褰�", successCount);
+// log.info("鏀粯淇℃伅鍚屾瀹屾垚锛屾垚鍔熷悓姝�: {} 鏉¤褰�", successCount);
} catch (Exception e) {
log.error("鏀粯淇℃伅鍚屾寮傚父", e);
}
@@ -228,10 +228,10 @@
* cron琛ㄨ揪寮�: 0 0/10 * * * ? (姣�10鍒嗛挓鎵ц涓�娆�)
*/
public void syncAdditionalFeeToLegacy() {
- log.info("寮�濮嬫墽琛屾柊绯荤粺闄勫姞璐圭敤鍚屾瀹氭椂浠诲姟锛堟柊绯荤粺 -> 鏃х郴缁燂級");
+// log.info("寮�濮嬫墽琛屾柊绯荤粺闄勫姞璐圭敤鍚屾瀹氭椂浠诲姟锛堟柊绯荤粺 -> 鏃х郴缁燂級");
try {
int successCount = additionalFeeSyncService.batchSyncAdditionalFeeToLegacy();
- log.info("闄勫姞璐圭敤鍚屾瀹屾垚锛屾垚鍔熷悓姝�: {} 鏉¤褰�", successCount);
+// log.info("闄勫姞璐圭敤鍚屾瀹屾垚锛屾垚鍔熷悓姝�: {} 鏉¤褰�", successCount);
} catch (Exception e) {
log.error("闄勫姞璐圭敤鍚屾寮傚父", e);
}
@@ -248,11 +248,11 @@
* cron琛ㄨ揪寮忥細 0 0/15 * * * ? (姣�15鍒嗛挓鎵ц涓�娆�)
*/
public void syncAdditionalFeeFromLegacy() {
- log.info("寮�濮嬫墽琛屾棫绯荤粺闄勫姞璐圭敤鍚屾瀹氭椂浠诲姟锛堟棫绯荤粺 -> 鏂扮郴缁燂級");
+// log.info("寮�濮嬫墽琛屾棫绯荤粺闄勫姞璐圭敤鍚屾瀹氭椂浠诲姟锛堟棫绯荤粺 -> 鏂扮郴缁燂級");
try {
// 鍚屾鏈�杩�24灏忔椂鍐呯殑璁板綍
int successCount = additionalFeeSyncService.batchSyncAdditionalFeeFromLegacy(72);
- log.info("鏃х郴缁熼檮鍔犺垂鐢ㄥ悓姝ュ畬鎴愶紝鎴愬姛鍚屾: {} 鏉¤褰�", successCount);
+// log.info("鏃х郴缁熼檮鍔犺垂鐢ㄥ悓姝ュ畬鎴愶紝鎴愬姛鍚屾: {} 鏉¤褰�", successCount);
} catch (Exception e) {
log.error("闄勫姞璐圭敤鍚屾寮傚父", e);
}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacyTransferSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacyTransferSyncTask.java
index 21d8fdf..9e27a30 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacyTransferSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacyTransferSyncTask.java
@@ -24,10 +24,10 @@
* 鍚屾7澶╁墠鐨勬棫绯荤粺杞繍鍗曟暟鎹�
*/
public void syncTransferOrders7Days() {
- log.info("寮�濮嬫墽琛�7澶╁墠鏃х郴缁熻浆杩愬崟鍚屾浠诲姟");
+// log.info("寮�濮嬫墽琛�7澶╁墠鏃х郴缁熻浆杩愬崟鍚屾浠诲姟");
try {
int count = legacyTransferSyncService.syncLegacyTransferOrders(7);
- log.info("7澶╁墠鏃х郴缁熻浆杩愬崟鍚屾浠诲姟鎵ц瀹屾垚锛屽悓姝ユ暟閲�: {}", count);
+// log.info("7澶╁墠鏃х郴缁熻浆杩愬崟鍚屾浠诲姟鎵ц瀹屾垚锛屽悓姝ユ暟閲�: {}", count);
} catch (Exception e) {
log.error("7澶╁墠鏃х郴缁熻浆杩愬崟鍚屾浠诲姟鎵ц寮傚父", e);
}
@@ -39,11 +39,11 @@
* @param daysAgo 澶╂暟
*/
public void syncTransferOrders(String daysAgo) {
- log.info("寮�濮嬫墽琛寋}澶╁墠鏃х郴缁熻浆杩愬崟鍚屾浠诲姟", daysAgo);
+// log.info("寮�濮嬫墽琛寋}澶╁墠鏃х郴缁熻浆杩愬崟鍚屾浠诲姟", daysAgo);
try {
int days = Integer.parseInt(daysAgo);
int count = legacyTransferSyncService.syncLegacyTransferOrders(days);
- log.info("{}澶╁墠鏃х郴缁熻浆杩愬崟鍚屾浠诲姟鎵ц瀹屾垚锛屽悓姝ユ暟閲�: {}", daysAgo, count);
+// log.info("{}澶╁墠鏃х郴缁熻浆杩愬崟鍚屾浠诲姟鎵ц瀹屾垚锛屽悓姝ユ暟閲�: {}", daysAgo, count);
} catch (Exception e) {
log.error("{}澶╁墠鏃х郴缁熻浆杩愬崟鍚屾浠诲姟鎵ц寮傚父", daysAgo, e);
}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacyVehicleSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacyVehicleSyncTask.java
index dea2b2e..46caf06 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacyVehicleSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacyVehicleSyncTask.java
@@ -46,7 +46,7 @@
if (result.isSuccess() || result.isWarn())
{
- log.info("鏃х郴缁熻溅杈嗗悓姝ヤ换鍔℃墽琛屾垚鍔�: {}", result.get("msg"));
+// log.info("鏃х郴缁熻溅杈嗗悓姝ヤ换鍔℃墽琛屾垚鍔�: {}", result.get("msg"));
}
else if (result.isError())
{
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/OaSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/OaSyncTask.java
index 97d811a..2701b55 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/OaSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/OaSyncTask.java
@@ -74,29 +74,29 @@
log.info("##########寮�濮嬫墽琛孫A鏁版嵁鍚屾瀹氭椂浠诲姟##########");
// 绗竴姝ワ細鍚屾閮ㄩ棬
- log.info("銆愭楠�1/2銆戝紑濮嬪悓姝ラ儴闂ㄦ暟鎹�...");
+// log.info("銆愭楠�1/2銆戝紑濮嬪悓姝ラ儴闂ㄦ暟鎹�...");
AjaxResult deptResult = departmentSyncService.syncBranchDepartments(this.getDept(),this.getServiceOrdCode(),this.getDispatchOrdCode(),this.getAddressList());
if (deptResult.get("code").equals(200))
{
- log.info("銆愭楠�1/2銆戦儴闂ㄥ悓姝ユ垚鍔�: {}", deptResult.get("msg"));
+// log.info("銆愭楠�1/2銆戦儴闂ㄥ悓姝ユ垚鍔�: {}", deptResult.get("msg"));
// 绗簩姝ワ細鍚屾鐢ㄦ埛锛堝彧鏈夐儴闂ㄥ悓姝ユ垚鍔熸墠鎵ц锛�
- log.info("銆愭楠�2/2銆戝紑濮嬪悓姝ョ敤鎴锋暟鎹�...");
+// log.info("銆愭楠�2/2銆戝紑濮嬪悓姝ョ敤鎴锋暟鎹�...");
AjaxResult userResult = userSyncService.syncOaUsers(this.getUserData());
- if (userResult.get("code").equals(200))
- {
- log.info("銆愭楠�2/2銆戠敤鎴峰悓姝ユ垚鍔�: {}", userResult.get("msg"));
- log.info("##########OA鏁版嵁鍚屾瀹氭椂浠诲姟鎵ц瀹屾垚##########");
- log.info("鎬荤粨锛氶儴闂ㄥ悓姝ユ垚鍔燂紝鐢ㄦ埛鍚屾鎴愬姛");
- }
- else
- {
- log.error("銆愭楠�2/2銆戠敤鎴峰悓姝ュけ璐�: {}", userResult.get("msg"));
- log.warn("##########OA鏁版嵁鍚屾瀹氭椂浠诲姟閮ㄥ垎瀹屾垚##########");
- log.warn("鎬荤粨锛氶儴闂ㄥ悓姝ユ垚鍔燂紝鐢ㄦ埛鍚屾澶辫触");
- }
+// if (userResult.get("code").equals(200))
+// {
+// log.info("銆愭楠�2/2銆戠敤鎴峰悓姝ユ垚鍔�: {}", userResult.get("msg"));
+// log.info("##########OA鏁版嵁鍚屾瀹氭椂浠诲姟鎵ц瀹屾垚##########");
+// log.info("鎬荤粨锛氶儴闂ㄥ悓姝ユ垚鍔燂紝鐢ㄦ埛鍚屾鎴愬姛");
+// }
+// else
+// {
+// log.error("銆愭楠�2/2銆戠敤鎴峰悓姝ュけ璐�: {}", userResult.get("msg"));
+// log.warn("##########OA鏁版嵁鍚屾瀹氭椂浠诲姟閮ㄥ垎瀹屾垚##########");
+// log.warn("鎬荤粨锛氶儴闂ㄥ悓姝ユ垚鍔燂紝鐢ㄦ埛鍚屾澶辫触");
+// }
}
else
{
@@ -118,7 +118,7 @@
*/
public void syncOaData(String params)
{
- log.info("OA鏁版嵁鍚屾浠诲姟鍙傛暟: {}", params);
+// log.info("OA鏁版嵁鍚屾浠诲姟鍙傛暟: {}", params);
syncOaData();
}
@@ -129,7 +129,7 @@
{
try
{
- log.info("==========寮�濮嬫墽琛岄儴闂ㄥ悓姝ヤ换鍔�==========");
+// log.info("==========寮�濮嬫墽琛岄儴闂ㄥ悓姝ヤ换鍔�==========");
AjaxResult result = departmentSyncService.syncBranchDepartments(this.getDept(),this.getServiceOrdCode(),this.getDispatchOrdCode(),this.getAddressList());
if (result.get("code").equals(200))
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
index 866ba08..e70255f 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
@@ -103,7 +103,7 @@
for (AOrderStatus orderStatus : orderStatusList) {
int count = tbOrdersService.checkServiceOrdIDExists(orderStatus.getServiceOrdID());
if (count > 0) {
- log.info("鏈嶅姟璁㈠崟ID瀛樺湪锛�" + orderStatus.getServiceOrdID());
+// log.info("鏈嶅姟璁㈠崟ID瀛樺湪锛�" + orderStatus.getServiceOrdID());
TbOrders tbOrders = tbOrdersService.selectTbOrdersByServiceOrdID(orderStatus.getServiceOrdID());
@@ -144,7 +144,7 @@
//濡傛灉杞︾墝鍙蜂笉涓虹┖
if(carLicense!=null && carLicense.length()>0){
- log.info("鏇存柊璁㈠崟-杞︾墝鍙峰叧鑱旇〃锛屻��" + tbOrders.getOrderID() + "銆戣溅鐗屽彿锛�" + carLicense);
+// log.info("鏇存柊璁㈠崟-杞︾墝鍙峰叧鑱旇〃锛屻��" + tbOrders.getOrderID() + "銆戣溅鐗屽彿锛�" + carLicense);
//鏌ヨ鏄惁瀛樺湪鍏宠仈璁板綍
TbVehicleOrder tbVehicleOrder = tbVehicleOrderService.selectTbVehicleOrderById(tbOrders.getOrderID());
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleGpsSegmentMileageTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleGpsSegmentMileageTask.java
index a317652..1ecff68 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleGpsSegmentMileageTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleGpsSegmentMileageTask.java
@@ -49,12 +49,12 @@
}
}
- logger.info("========== 寮�濮嬫墽琛孏PS鍒嗘閲岀▼琛ュ伩璁$畻 - 鍥炴函{}澶� ==========", lookbackDays);
+// logger.info("========== 寮�濮嬫墽琛孏PS鍒嗘閲岀▼琛ュ伩璁$畻 - 鍥炴函{}澶� ==========", lookbackDays);
// 鎵ц琛ュ伩璁$畻
int successCount = segmentMileageService.compensateCalculation(lookbackDays);
- logger.info("========== GPS鍒嗘閲岀▼琛ュ伩璁$畻瀹屾垚 - 鎴愬姛澶勭悊 {} 杈嗚溅 ==========", successCount);
+// logger.info("========== GPS鍒嗘閲岀▼琛ュ伩璁$畻瀹屾垚 - 鎴愬姛澶勭悊 {} 杈嗚溅 ==========", successCount);
} catch (Exception e) {
logger.error("GPS鍒嗘閲岀▼琛ュ伩璁$畻澶辫触", e);
@@ -105,13 +105,13 @@
// 娉ㄦ剰锛氭鏂规硶鍙绠楁渶杩戞椂闂存鐨勬暟鎹紝鍘嗗彶閬楁紡鏁版嵁鐢辫ˉ鍋挎満鍒跺鐞�
- logger.info("寮�濮嬭绠桮PS鍒嗘閲岀▼ - 鏃堕棿鑼冨洿: {} 鍒� {}, 鏃堕棿娈甸棿闅�: {}鍒嗛挓",
- startTime, endTime, segmentMinutes);
+// logger.info("寮�濮嬭绠桮PS鍒嗘閲岀▼ - 鏃堕棿鑼冨洿: {} 鍒� {}, 鏃堕棿娈甸棿闅�: {}鍒嗛挓",
+// startTime, endTime, segmentMinutes);
// 鎵归噺璁$畻
int successCount = segmentMileageService.batchCalculateSegmentMileage(startTime, endTime);
- logger.info("GPS鍒嗘閲岀▼璁$畻瀹屾垚 - 鎴愬姛澶勭悊 {} 杈嗚溅", successCount);
+// logger.info("GPS鍒嗘閲岀▼璁$畻瀹屾垚 - 鎴愬姛澶勭悊 {} 杈嗚溅", successCount);
} catch (Exception e) {
logger.error("GPS鍒嗘閲岀▼璁$畻浠诲姟鎵ц澶辫触", e);
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleMileageStatsTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleMileageStatsTask.java
index 8619a88..68b9c2c 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleMileageStatsTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleMileageStatsTask.java
@@ -40,7 +40,7 @@
// 鎵归噺璁$畻閲岀▼缁熻
int successCount = vehicleMileageStatsService.batchCalculateMileageStats(yesterday);
- logger.info("杞﹁締閲岀▼缁熻瀹氭椂浠诲姟鎵ц瀹屾垚 - 鎴愬姛缁熻: {} 杈嗚溅", successCount);
+// logger.info("杞﹁締閲岀▼缁熻瀹氭椂浠诲姟鎵ц瀹屾垚 - 鎴愬姛缁熻: {} 杈嗚溅", successCount);
} catch (Exception e) {
logger.error("杞﹁締閲岀▼缁熻瀹氭椂浠诲姟鎵ц澶辫触", e);
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleSyncTask.java
index 6d80602..8f8212a 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/VehicleSyncTask.java
@@ -33,14 +33,14 @@
*/
public void syncVehicleInfo() {
try {
- log.info("寮�濮嬪悓姝ヨ溅杈嗕俊鎭�...");
+// log.info("寮�濮嬪悓姝ヨ溅杈嗕俊鎭�...");
// 鑾峰彇璁惧鍒楄〃锛岃繖浼氳嚜鍔ㄦ洿鏂拌溅杈嗕俊鎭腑鐨勮澶嘔D
GpsDeviceListResponse response = gpsCollectService.getDeviceList();
// 鏇存柊杞﹁締璁惧ID
updateVehicleDeviceIds(response);
- log.info("杞﹁締淇℃伅鍚屾瀹屾垚");
+// log.info("杞﹁締淇℃伅鍚屾瀹屾垚");
} catch (Exception e) {
log.error("杞﹁締淇℃伅鍚屾澶辫触: {}", e.getMessage());
}
diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml
index 844fc1e..c18868b 100644
--- a/ruoyi-system/pom.xml
+++ b/ruoyi-system/pom.xml
@@ -44,12 +44,22 @@
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
+
+ <!-- JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
+
+
+ <!-- Spring Test -->
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/NotifySendLogController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/NotifySendLogController.java
new file mode 100644
index 0000000..054a6c6
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/NotifySendLogController.java
@@ -0,0 +1,69 @@
+package com.ruoyi.system.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.NotifySendLog;
+import com.ruoyi.system.service.INotifySendLogService;
+
+/**
+ * 閫氱煡鍙戦�佹棩蹇桟ontroller
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+@RestController
+@RequestMapping("/system/notify/log")
+public class NotifySendLogController extends BaseController
+{
+ @Autowired
+ private INotifySendLogService notifySendLogService;
+
+ /**
+ * 鏌ヨ閫氱煡鍙戦�佹棩蹇楀垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('system:notify:log:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(NotifySendLog notifySendLog)
+ {
+ startPage();
+ List<NotifySendLog> list = notifySendLogService.selectNotifySendLogList(notifySendLog);
+ return getDataTable(list);
+ }
+
+ /**
+ * 瀵煎嚭閫氱煡鍙戦�佹棩蹇楀垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('system:notify:log:export')")
+ @Log(title = "閫氱煡鍙戦�佹棩蹇�", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, NotifySendLog notifySendLog)
+ {
+ List<NotifySendLog> list = notifySendLogService.selectNotifySendLogList(notifySendLog);
+ ExcelUtil<NotifySendLog> util = new ExcelUtil<NotifySendLog>(NotifySendLog.class);
+ util.exportExcel(response, list, "閫氱煡鍙戦�佹棩蹇楁暟鎹�");
+ }
+
+ /**
+ * 鑾峰彇閫氱煡鍙戦�佹棩蹇楄缁嗕俊鎭�
+ */
+ @PreAuthorize("@ss.hasPermi('system:notify:log:query')")
+ @GetMapping(value = "/{id}")
+ public AjaxResult getInfo(@PathVariable("id") Long id)
+ {
+ return AjaxResult.success(notifySendLogService.selectNotifySendLogById(id));
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/NotifyTaskController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/NotifyTaskController.java
new file mode 100644
index 0000000..cef1978
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/NotifyTaskController.java
@@ -0,0 +1,69 @@
+package com.ruoyi.system.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.NotifyTask;
+import com.ruoyi.system.service.INotifyTaskService;
+
+/**
+ * 閫氱煡浠诲姟Controller
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+@RestController
+@RequestMapping("/system/notify/task")
+public class NotifyTaskController extends BaseController
+{
+ @Autowired
+ private INotifyTaskService notifyTaskService;
+
+ /**
+ * 鏌ヨ閫氱煡浠诲姟鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:notify:task:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(NotifyTask notifyTask)
+ {
+ startPage();
+ List<NotifyTask> list = notifyTaskService.selectNotifyTaskList(notifyTask);
+ return getDataTable(list);
+ }
+
+ /**
+ * 瀵煎嚭閫氱煡浠诲姟鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:notify:task:export')")
+ @Log(title = "閫氱煡浠诲姟", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, NotifyTask notifyTask)
+ {
+ List<NotifyTask> list = notifyTaskService.selectNotifyTaskList(notifyTask);
+ ExcelUtil<NotifyTask> util = new ExcelUtil<NotifyTask>(NotifyTask.class);
+ util.exportExcel(response, list, "閫氱煡浠诲姟鏁版嵁");
+ }
+
+ /**
+ * 鑾峰彇閫氱煡浠诲姟璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:notify:task:query')")
+ @GetMapping(value = "/{id}")
+ public AjaxResult getInfo(@PathVariable("id") Long id)
+ {
+ return AjaxResult.success(notifyTaskService.selectNotifyTaskById(id));
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/SmsSendController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/SmsSendController.java
new file mode 100644
index 0000000..92fffad
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/SmsSendController.java
@@ -0,0 +1,25 @@
+package com.ruoyi.system.controller;
+
+import com.ruoyi.system.service.ISmsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+@Service
+public class SmsSendController {
+ @Autowired
+ private ISmsService smsService;
+
+
+ public String sendSms(SmsSendReq req) {
+ if (smsService.sendSms(req.getPhone(), req.getContent())) {
+ return "鍙戦�佹垚鍔�";
+ } else {
+ return "鍙戦�佸け璐�";
+ }
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/SmsSendReq.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/SmsSendReq.java
new file mode 100644
index 0000000..f893e3e
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/SmsSendReq.java
@@ -0,0 +1,16 @@
+package com.ruoyi.system.controller;
+
+import lombok.Data;
+import lombok.NonNull;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+@Data
+public class SmsSendReq implements Serializable {
+
+ @NotBlank(message = "鎵嬫満鍙蜂笉鑳戒负绌�")
+ private String phone;
+ @NotBlank(message = "鍐呭涓嶈兘涓虹┖")
+ private String content;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/NotifyChannelConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/NotifyChannelConfig.java
new file mode 100644
index 0000000..862dae5
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/NotifyChannelConfig.java
@@ -0,0 +1,112 @@
+package com.ruoyi.system.domain;
+
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 閫氱煡娓犻亾閰嶇疆瀹炰綋绫�
+ * 鐢ㄤ簬閰嶇疆鍚勭被閫氱煡鍚敤鐨勫彂閫佹笭閬�
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+public class NotifyChannelConfig extends BaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ // ==================== 娓犻亾甯搁噺 ====================
+ /** 娓犻亾锛氬井淇¤闃呮秷鎭� */
+ public static final String CHANNEL_WECHAT = "WECHAT";
+ /** 娓犻亾锛氱煭淇� */
+ public static final String CHANNEL_SMS = "SMS";
+ /** 娓犻亾锛氱珯鍐呮秷鎭� */
+ public static final String CHANNEL_SITE_MSG = "SITE_MSG";
+ /** 娓犻亾锛欰PP鎺ㄩ�� */
+ public static final String CHANNEL_APP_PUSH = "APP_PUSH";
+
+ // ==================== 鍚敤鐘舵�佸父閲� ====================
+ /** 鍚敤 */
+ public static final String ENABLED_YES = "1";
+ /** 绂佺敤 */
+ public static final String ENABLED_NO = "0";
+
+ /** 涓婚敭ID */
+ private Long id;
+
+ /** 閫氱煡绫诲瀷 */
+ @Excel(name = "閫氱煡绫诲瀷")
+ private String notifyType;
+
+ /** 娓犻亾 */
+ @Excel(name = "娓犻亾")
+ private String channel;
+
+ /** 鏄惁鍚敤 */
+ @Excel(name = "鏄惁鍚敤", readConverterExp = "0=绂佺敤,1=鍚敤")
+ private String enabled;
+
+ /** 浼樺厛绾� */
+ @Excel(name = "浼樺厛绾�")
+ private Integer priority;
+
+ /** 娓犻亾閰嶇疆(JSON鏍煎紡) */
+ private String configJson;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getNotifyType() {
+ return notifyType;
+ }
+
+ public void setNotifyType(String notifyType) {
+ this.notifyType = notifyType;
+ }
+
+ public String getChannel() {
+ return channel;
+ }
+
+ public void setChannel(String channel) {
+ this.channel = channel;
+ }
+
+ public String getEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(String enabled) {
+ this.enabled = enabled;
+ }
+
+ public Integer getPriority() {
+ return priority;
+ }
+
+ public void setPriority(Integer priority) {
+ this.priority = priority;
+ }
+
+ public String getConfigJson() {
+ return configJson;
+ }
+
+ public void setConfigJson(String configJson) {
+ this.configJson = configJson;
+ }
+
+ @Override
+ public String toString() {
+ return "NotifyChannelConfig{" +
+ "id=" + id +
+ ", notifyType='" + notifyType + '\'' +
+ ", channel='" + channel + '\'' +
+ ", enabled='" + enabled + '\'' +
+ ", priority=" + priority +
+ '}';
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/NotifySendLog.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/NotifySendLog.java
new file mode 100644
index 0000000..e14ee2d
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/NotifySendLog.java
@@ -0,0 +1,210 @@
+package com.ruoyi.system.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 閫氱煡鍙戦�佽褰曞璞� sys_notify_send_log
+ * 鐢ㄤ簬璁板綍鍚勭被閫氱煡娑堟伅鐨勫彂閫佽褰曪紝瀹炵幇闃查噸鏈哄埗
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+public class NotifySendLog extends BaseEntity {
+
+ private static final long serialVersionUID = 1L;
+
+ /** 涓婚敭ID */
+ private Long id;
+
+ /** 鍏宠仈鐨勯�氱煡浠诲姟ID */
+ @Excel(name = "閫氱煡浠诲姟ID")
+ private Long notifyTaskId;
+
+ /** 浠诲姟ID */
+ @Excel(name = "浠诲姟ID")
+ private Long taskId;
+
+ /** 鎺ユ敹鐢ㄦ埛ID */
+ @Excel(name = "鐢ㄦ埛ID")
+ private Long userId;
+
+ /** 鎺ユ敹鐢ㄦ埛濮撳悕 */
+ @Excel(name = "鐢ㄦ埛濮撳悕")
+ private String userName;
+
+ /** 閫氱煡绫诲瀷锛歍ASK_ASSIGN-浠诲姟鍒嗛厤, STATUS_CHANGE-鐘舵�佸彉鏇�, TASK_CREATE-浠诲姟鍒涘缓 */
+ @Excel(name = "閫氱煡绫诲瀷")
+ private String notifyType;
+
+ /** 閫氱煡娓犻亾锛歐ECHAT-寰俊璁㈤槄娑堟伅, SMS-鐭俊, APP_PUSH-APP鎺ㄩ��, SITE_MSG-绔欏唴娑堟伅 */
+ @Excel(name = "閫氱煡娓犻亾")
+ private String channel;
+
+ /** 鍙戦�佺姸鎬侊細0-寰呭彂閫�, 1-鍙戦�佹垚鍔�, 2-鍙戦�佸け璐� */
+ @Excel(name = "鍙戦�佺姸鎬�")
+ private String sendStatus;
+
+ /** 鍙戦�佹椂闂� */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Excel(name = "鍙戦�佹椂闂�", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+ private Date sendTime;
+
+ /** 鍙戦�佺粨鏋�/閿欒淇℃伅 */
+ @Excel(name = "鍙戦�佺粨鏋�")
+ private String sendResult;
+
+ /** 鍝嶅簲娑堟伅 */
+ private String responseMsg;
+
+ /** 閲嶈瘯娆℃暟 */
+ @Excel(name = "閲嶈瘯娆℃暟")
+ private Integer retryCount;
+
+ // ==================== 閫氱煡绫诲瀷甯搁噺 ====================
+ /** 浠诲姟鍒嗛厤閫氱煡 */
+ public static final String NOTIFY_TYPE_TASK_ASSIGN = "TASK_ASSIGN";
+ /** 鐘舵�佸彉鏇撮�氱煡 */
+ public static final String NOTIFY_TYPE_STATUS_CHANGE = "STATUS_CHANGE";
+ /** 浠诲姟鍒涘缓閫氱煡 */
+ public static final String NOTIFY_TYPE_TASK_CREATE = "TASK_CREATE";
+
+ // ==================== 閫氱煡娓犻亾甯搁噺 ====================
+ /** 寰俊璁㈤槄娑堟伅 */
+ public static final String CHANNEL_WECHAT = "WECHAT";
+ /** 鐭俊 */
+ public static final String CHANNEL_SMS = "SMS";
+ /** APP鎺ㄩ�� */
+ public static final String CHANNEL_APP_PUSH = "APP_PUSH";
+ /** 绔欏唴娑堟伅 */
+ public static final String CHANNEL_SITE_MSG = "SITE_MSG";
+
+ // ==================== 鍙戦�佺姸鎬佸父閲� ====================
+ /** 寰呭彂閫� */
+ public static final String SEND_STATUS_PENDING = "0";
+ /** 鍙戦�佹垚鍔� */
+ public static final String SEND_STATUS_SUCCESS = "1";
+ /** 鍙戦�佸け璐� */
+ public static final String SEND_STATUS_FAILED = "2";
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Long getNotifyTaskId() {
+ return notifyTaskId;
+ }
+
+ public void setNotifyTaskId(Long notifyTaskId) {
+ this.notifyTaskId = notifyTaskId;
+ }
+
+ public Long getTaskId() {
+ return taskId;
+ }
+
+ public void setTaskId(Long taskId) {
+ this.taskId = taskId;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+
+ public void setUserId(Long userId) {
+ this.userId = userId;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getNotifyType() {
+ return notifyType;
+ }
+
+ public void setNotifyType(String notifyType) {
+ this.notifyType = notifyType;
+ }
+
+ public String getChannel() {
+ return channel;
+ }
+
+ public void setChannel(String channel) {
+ this.channel = channel;
+ }
+
+ public String getSendStatus() {
+ return sendStatus;
+ }
+
+ public void setSendStatus(String sendStatus) {
+ this.sendStatus = sendStatus;
+ }
+
+ public Date getSendTime() {
+ return sendTime;
+ }
+
+ public void setSendTime(Date sendTime) {
+ this.sendTime = sendTime;
+ }
+
+ public String getSendResult() {
+ return sendResult;
+ }
+
+ public void setSendResult(String sendResult) {
+ this.sendResult = sendResult;
+ }
+
+ public String getResponseMsg() {
+ return responseMsg;
+ }
+
+ public void setResponseMsg(String responseMsg) {
+ this.responseMsg = responseMsg;
+ }
+
+ public Integer getRetryCount() {
+ return retryCount;
+ }
+
+ public void setRetryCount(Integer retryCount) {
+ this.retryCount = retryCount;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+ .append("id", getId())
+ .append("taskId", getTaskId())
+ .append("userId", getUserId())
+ .append("userName", getUserName())
+ .append("notifyType", getNotifyType())
+ .append("channel", getChannel())
+ .append("sendStatus", getSendStatus())
+ .append("sendTime", getSendTime())
+ .append("sendResult", getSendResult())
+ .append("retryCount", getRetryCount())
+ .append("createTime", getCreateTime())
+ .append("createBy", getCreateBy())
+ .append("updateTime", getUpdateTime())
+ .append("updateBy", getUpdateBy())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/NotifyTask.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/NotifyTask.java
new file mode 100644
index 0000000..6f7682a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/NotifyTask.java
@@ -0,0 +1,212 @@
+package com.ruoyi.system.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+import java.util.Date;
+
+/**
+ * 閫氱煡浠诲姟涓昏〃瀹炰綋绫�
+ * 鐢ㄤ簬缁熶竴绠$悊寰呭彂閫佺殑閫氱煡浠诲姟
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+public class NotifyTask extends BaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ // ==================== 閫氱煡绫诲瀷甯搁噺 ====================
+ /** 閫氱煡绫诲瀷锛氫换鍔″垎閰� */
+ public static final String NOTIFY_TYPE_TASK_ASSIGN = "TASK_ASSIGN";
+ /** 閫氱煡绫诲瀷锛氱姸鎬佸彉鏇� */
+ public static final String NOTIFY_TYPE_STATUS_CHANGE = "STATUS_CHANGE";
+ /** 閫氱煡绫诲瀷锛氫换鍔″垱寤� */
+ public static final String NOTIFY_TYPE_TASK_CREATE = "TASK_CREATE";
+
+ // ==================== 澶勭悊鐘舵�佸父閲� ====================
+ /** 澶勭悊鐘舵�侊細寰呭鐞� */
+ public static final String STATUS_PENDING = "0";
+ /** 澶勭悊鐘舵�侊細澶勭悊涓� */
+ public static final String STATUS_PROCESSING = "1";
+ /** 澶勭悊鐘舵�侊細宸插畬鎴� */
+ public static final String STATUS_COMPLETED = "2";
+ /** 澶勭悊鐘舵�侊細澶辫触 */
+ public static final String STATUS_FAILED = "3";
+
+ /** 涓婚敭ID */
+ private Long id;
+
+ /** 鍏宠仈鐨勪笟鍔′换鍔D */
+ @Excel(name = "浠诲姟ID")
+ private Long taskId;
+
+ /** 浠诲姟缂栧彿 */
+ @Excel(name = "浠诲姟缂栧彿")
+ private String taskCode;
+
+ /** 閫氱煡绫诲瀷 */
+ @Excel(name = "閫氱煡绫诲瀷")
+ private String notifyType;
+
+ /** 鎺ユ敹鐢ㄦ埛ID */
+ @Excel(name = "鐢ㄦ埛ID")
+ private Long userId;
+
+ /** 鎺ユ敹鐢ㄦ埛濮撳悕 */
+ @Excel(name = "鐢ㄦ埛濮撳悕")
+ private String userName;
+
+ /** 鎺ユ敹鐢ㄦ埛鎵嬫満鍙� */
+ @Excel(name = "鎵嬫満鍙�")
+ private String userPhone;
+
+ /** 閫氱煡鏍囬 */
+ @Excel(name = "閫氱煡鏍囬")
+ private String title;
+
+ /** 閫氱煡鍐呭 */
+ @Excel(name = "閫氱煡鍐呭")
+ private String content;
+
+ /** 鎵╁睍鏁版嵁(JSON鏍煎紡) */
+ private String extraData;
+
+ /** 澶勭悊鐘舵�� */
+ @Excel(name = "澶勭悊鐘舵��", readConverterExp = "0=寰呭鐞�,1=澶勭悊涓�,2=宸插畬鎴�,3=澶辫触")
+ private String status;
+
+ /** 閲嶈瘯娆℃暟 */
+ private Integer retryCount;
+
+ /** 鏈�澶ч噸璇曟鏁� */
+ private Integer maxRetry;
+
+ /** 閿欒淇℃伅 */
+ private String errorMsg;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Long getTaskId() {
+ return taskId;
+ }
+
+ public void setTaskId(Long taskId) {
+ this.taskId = taskId;
+ }
+
+ public String getTaskCode() {
+ return taskCode;
+ }
+
+ public void setTaskCode(String taskCode) {
+ this.taskCode = taskCode;
+ }
+
+ public String getNotifyType() {
+ return notifyType;
+ }
+
+ public void setNotifyType(String notifyType) {
+ this.notifyType = notifyType;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+
+ public void setUserId(Long userId) {
+ this.userId = userId;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getUserPhone() {
+ return userPhone;
+ }
+
+ public void setUserPhone(String userPhone) {
+ this.userPhone = userPhone;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public String getExtraData() {
+ return extraData;
+ }
+
+ public void setExtraData(String extraData) {
+ this.extraData = extraData;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public Integer getRetryCount() {
+ return retryCount;
+ }
+
+ public void setRetryCount(Integer retryCount) {
+ this.retryCount = retryCount;
+ }
+
+ public Integer getMaxRetry() {
+ return maxRetry;
+ }
+
+ public void setMaxRetry(Integer maxRetry) {
+ this.maxRetry = maxRetry;
+ }
+
+ public String getErrorMsg() {
+ return errorMsg;
+ }
+
+ public void setErrorMsg(String errorMsg) {
+ this.errorMsg = errorMsg;
+ }
+
+ @Override
+ public String toString() {
+ return "NotifyTask{" +
+ "id=" + id +
+ ", taskId=" + taskId +
+ ", taskCode='" + taskCode + '\'' +
+ ", notifyType='" + notifyType + '\'' +
+ ", userId=" + userId +
+ ", userName='" + userName + '\'' +
+ ", status='" + status + '\'' +
+ '}';
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskCreateVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskCreateVO.java
index abafe39..d4ec91b 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskCreateVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskCreateVO.java
@@ -123,6 +123,8 @@
private Date createTime;
+ private String taskStatus;
+
// 鎵ц浜哄憳淇℃伅鍐呴儴绫�
public static class AssigneeInfo {
/** 鐢ㄦ埛ID */
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java b/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java
index c46d1d8..629bed0 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java
@@ -11,6 +11,7 @@
import com.ruoyi.system.domain.SysMessage;
import com.ruoyi.system.domain.SysTask;
import com.ruoyi.system.domain.SysTaskEmergency;
+import com.ruoyi.system.domain.NotifyTask;
import com.ruoyi.system.event.TaskCreatedEvent;
import com.ruoyi.system.event.TaskAssignedEvent;
import com.ruoyi.system.event.TaskStatusChangedEvent;
@@ -19,9 +20,11 @@
import com.ruoyi.system.mapper.SysTaskMapper;
import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
import com.ruoyi.common.core.domain.entity.SysUser;
-import com.ruoyi.system.service.IWechatTaskNotifyService;
+import com.ruoyi.system.service.INotifyTaskService;
+import com.ruoyi.system.service.INotifyDispatchService;
-import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.List;
/**
* 浠诲姟娑堟伅鐩戝惉鍣�
@@ -48,7 +51,15 @@
private SysTaskEmergencyMapper sysTaskEmergencyMapper;
@Autowired
- private IWechatTaskNotifyService wechatTaskNotifyService;
+ private INotifyTaskService notifyTaskService;
+
+ @Autowired
+ private INotifyDispatchService notifyDispatchService;
+
+ /** 寰呭噯澶囩姸鎬� - 鍙互鍙戦�佺煭淇¢�氱煡 */
+ private static final String TASK_STATUS_PENDING = "PENDING";
+ /** 寰呭噯澶囩姸鎬� - 鍙互鍙戦�佺煭淇¢�氱煡 */
+ private static final String TASK_STATUS_PREPARING = "PREPARING";
/**
* 鐩戝惉浠诲姟鍒涘缓浜嬩欢
@@ -96,6 +107,7 @@
/**
* 鐩戝惉浠诲姟鍒嗛厤浜嬩欢
+ * 鍒涘缓閫氱煡浠诲姟锛岀敱閫氱煡鍒嗗彂鏈嶅姟鍐冲畾鍙戦�佹笭閬�
*
* @param event 浠诲姟鍒嗛厤浜嬩欢
*/
@@ -111,10 +123,39 @@
log.warn("鎵ц浜篒D鍒楄〃涓虹┖锛屾棤娉曟帹閫佹秷鎭�");
return;
}
+
+ // 鏌ヨ浠诲姟淇℃伅
+ SysTask task = sysTaskMapper.selectSysTaskByTaskId(event.getTaskId());
+ if (task == null) {
+ log.warn("浠诲姟涓嶅瓨鍦紝taskId={}", event.getTaskId());
+ return;
+ }
+
+ // 鏌ヨ鎬ユ晳鎵╁睍淇℃伅锛堢敤浜庢瀯寤洪�氱煡鍐呭锛�
+ SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(event.getTaskId());
+
+ Long creatorId = task.getCreatorId();
+ String taskStatus = task.getTaskStatus();
- // 缁欐瘡涓墽琛屼汉鍙戦�佺珯鍐呮秷鎭�
- for (int i = 0; i < event.getAssigneeIds().size(); i++) {
- Long assigneeId = event.getAssigneeIds().get(i);
+ // 浠呭湪寰呭噯澶囩姸鎬佷笅鍙戦�侀�氱煡
+ if (!TASK_STATUS_PENDING.equals(taskStatus) && !TASK_STATUS_PREPARING.equals(taskStatus)) {
+ log.info("浠诲姟鐘舵��({})闈炲緟鍑嗗鐘舵�侊紝璺宠繃閫氱煡锛宼askId={}", taskStatus, event.getTaskId());
+ return;
+ }
+
+ // 鏋勫缓閫氱煡鍐呭
+ String notifyContent = buildNotifyContent(task, emergency);
+
+ // 鏀堕泦鍒涘缓鐨勯�氱煡浠诲姟
+ List<NotifyTask> createdTasks = new ArrayList<>();
+
+ // 涓烘瘡涓墽琛屼汉鍒涘缓閫氱煡浠诲姟
+ for (Long assigneeId : event.getAssigneeIds()) {
+ // 鎺掗櫎鍒涘缓浜�
+ if (creatorId != null && creatorId.equals(assigneeId)) {
+ log.debug("璺宠繃鍒涘缓浜猴紝涓嶅彂閫佷换鍔″垎閰嶉�氱煡锛寀serId={}", assigneeId);
+ continue;
+ }
// 鑾峰彇鎵ц浜轰俊鎭�
SysUser assignee = sysUserMapper.selectUserById(assigneeId);
@@ -123,33 +164,32 @@
continue;
}
- // 鍒涘缓绔欏唴娑堟伅
- SysMessage message = new SysMessage();
- message.setMessageType("PUSH");
- message.setMessageTitle("浠诲姟鎺ㄩ��");
- message.setMessageContent("鎮ㄦ湁鏂扮殑浠诲姟锛岃鍙婃椂澶勭悊");
- message.setTaskId(event.getTaskId());
- message.setTaskCode(event.getTaskCode());
- message.setReceiverId(assigneeId);
- message.setReceiverName(assignee.getNickName());
- message.setSenderId(event.getAssignerId());
- message.setSenderName(event.getAssignerName() != null ? event.getAssignerName() : "绯荤粺");
- message.setIsRead("0");
- message.setCreateTime(DateUtils.getNowDate());
- message.setDelFlag("0");
+ // 鍒涘缓閫氱煡浠诲姟锛堝甫闃查噸锛�
+ NotifyTask notifyTask = new NotifyTask();
+ notifyTask.setTaskId(event.getTaskId());
+ notifyTask.setTaskCode(event.getTaskCode());
+ notifyTask.setNotifyType(NotifyTask.NOTIFY_TYPE_TASK_ASSIGN);
+ notifyTask.setUserId(assigneeId);
+ notifyTask.setUserName(assignee.getNickName());
+ notifyTask.setUserPhone(assignee.getPhonenumber());
+ notifyTask.setTitle("浠诲姟鎺ㄩ��");
+ notifyTask.setContent(notifyContent);
+ notifyTask.setCreateBy(event.getAssignerName() != null ? event.getAssignerName() : "绯荤粺");
- // 淇濆瓨娑堟伅
- sysMessageMapper.insertSysMessage(message);
- log.info("浠诲姟鍒嗛厤娑堟伅宸蹭繚瀛橈紝娑堟伅ID锛歿}锛屾帴鏀朵汉锛歿}", message.getMessageId(), assignee.getNickName());
+ NotifyTask created = notifyTaskService.createNotifyTask(notifyTask);
+ if (created != null) {
+ createdTasks.add(created);
+ log.info("鍒涘缓閫氱煡浠诲姟鎴愬姛锛宨d={}, userId={}", created.getId(), assigneeId);
+ } else {
+ log.info("閫氱煡浠诲姟宸插瓨鍦紝璺宠繃锛宼askId={}, userId={}", event.getTaskId(), assigneeId);
+ }
}
- // 鍙戦�佸井淇¤闃呮秷鎭紙鎺掗櫎鍒涘缓浜猴級
- try {
- SysTask task = sysTaskMapper.selectSysTaskByTaskId(event.getTaskId());
- Long creatorId = task != null ? task.getCreatorId() : null;
- wechatTaskNotifyService.sendTaskNotifyMessage(event.getTaskId(), event.getAssigneeIds(), creatorId);
- } catch (Exception e) {
- log.error("澶勭悊浠诲姟鍒嗛厤浜嬩欢鏃跺彂閫佸井淇¤闃呮秷鎭け璐�", e);
+ // 鍒嗗彂閫氱煡浠诲姟
+ if (!createdTasks.isEmpty()) {
+ int successCount = notifyDispatchService.dispatchNotifies(createdTasks);
+ log.info("閫氱煡鍒嗗彂瀹屾垚锛宼askId={}锛屽垱寤烘暟閲�={}锛屾垚鍔熸暟閲�={}",
+ event.getTaskId(), createdTasks.size(), successCount);
}
} catch (Exception e) {
@@ -158,6 +198,43 @@
}
/**
+ * 鏋勫缓閫氱煡鍐呭
+ */
+ private String buildNotifyContent(SysTask task, SysTaskEmergency emergency) {
+ StringBuilder content = new StringBuilder("鎮ㄦ湁鏂扮殑杞繍浠诲姟锛岃鍙婃椂澶勭悊锛屼换鍔″崟鍙�:"+task.getTaskCode());
+
+ // 娣诲姞鍑哄彂鍦颁俊鎭�
+ String departure = null;
+ if (emergency != null && StringUtils.isNotEmpty(emergency.getHospitalOutName())) {
+ departure = emergency.getHospitalOutName();
+ } else if (StringUtils.isNotEmpty(task.getDepartureAddress())) {
+ departure = task.getDepartureAddress();
+ }
+
+ // 娣诲姞鐩殑鍦颁俊鎭�
+ String destination = null;
+ if (emergency != null && StringUtils.isNotEmpty(emergency.getHospitalInName())) {
+ destination = emergency.getHospitalInName();
+ } else if (StringUtils.isNotEmpty(task.getDestinationAddress())) {
+ destination = task.getDestinationAddress();
+ }
+
+ if (departure != null || destination != null) {
+ content = new StringBuilder();
+ if (departure != null) {
+ content.append("鍑哄彂鍦帮細").append(departure);
+ }
+ if (destination != null) {
+ if (content.length() > 0) content.append("锛�");
+ content.append("鐩殑鍦帮細").append(destination);
+ }
+ content.append("锛岃鍙婃椂澶勭悊銆�");
+ }
+
+ return content.toString();
+ }
+
+ /**
* 鐩戝惉浠诲姟鐘舵�佸彉鏇翠簨浠�
*
* @param event 浠诲姟鐘舵�佸彉鏇翠簨浠�
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java
index 89fa80b..5a52599 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java
@@ -45,10 +45,10 @@
/**
* 鏍规嵁璋冨害鍗旾D鏌ヨ鎵ц浜轰俊鎭�
*
- * @param dispatchOrdID 璋冨害鍗旾D
+ * @param dispatchOrdID 璋冨害鍗旾D锛圔IGINT绫诲瀷锛�
* @return 鎵ц浜轰俊鎭垪琛�
*/
- List<Map<String, Object>> selectAssigneesByDispatchOrdID(@Param("dispatchOrdID") String dispatchOrdID);
+ List<Map<String, Object>> selectAssigneesByDispatchOrdID(@Param("dispatchOrdID") Long dispatchOrdID);
/**
* 鏍规嵁杞﹁締ID鏌ヨ杞︾墝鍙�
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/NotifyChannelConfigMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/NotifyChannelConfigMapper.java
new file mode 100644
index 0000000..28e0aba
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/NotifyChannelConfigMapper.java
@@ -0,0 +1,80 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.system.domain.NotifyChannelConfig;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+
+/**
+ * 閫氱煡娓犻亾閰嶇疆Mapper鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+public interface NotifyChannelConfigMapper {
+
+ /**
+ * 鏌ヨ閫氱煡娓犻亾閰嶇疆
+ *
+ * @param id 涓婚敭ID
+ * @return 閫氱煡娓犻亾閰嶇疆
+ */
+ NotifyChannelConfig selectNotifyChannelConfigById(Long id);
+
+ /**
+ * 鏌ヨ閫氱煡娓犻亾閰嶇疆鍒楄〃
+ *
+ * @param notifyChannelConfig 鏌ヨ鏉′欢
+ * @return 閫氱煡娓犻亾閰嶇疆鍒楄〃
+ */
+ List<NotifyChannelConfig> selectNotifyChannelConfigList(NotifyChannelConfig notifyChannelConfig);
+
+ /**
+ * 鏌ヨ鎸囧畾閫氱煡绫诲瀷鍚敤鐨勬笭閬撻厤缃�
+ * 鎸変紭鍏堢骇闄嶅簭鎺掑垪
+ *
+ * @param notifyType 閫氱煡绫诲瀷
+ * @return 鍚敤鐨勬笭閬撻厤缃垪琛�
+ */
+ List<NotifyChannelConfig> selectEnabledChannelsByType(@Param("notifyType") String notifyType);
+
+ /**
+ * 妫�鏌ユ寚瀹氭笭閬撴槸鍚﹀惎鐢�
+ *
+ * @param notifyType 閫氱煡绫诲瀷
+ * @param channel 娓犻亾
+ * @return 閰嶇疆淇℃伅
+ */
+ NotifyChannelConfig selectByTypeAndChannel(@Param("notifyType") String notifyType, @Param("channel") String channel);
+
+ /**
+ * 鏂板閫氱煡娓犻亾閰嶇疆
+ *
+ * @param notifyChannelConfig 閫氱煡娓犻亾閰嶇疆
+ * @return 褰卞搷琛屾暟
+ */
+ int insertNotifyChannelConfig(NotifyChannelConfig notifyChannelConfig);
+
+ /**
+ * 淇敼閫氱煡娓犻亾閰嶇疆
+ *
+ * @param notifyChannelConfig 閫氱煡娓犻亾閰嶇疆
+ * @return 褰卞搷琛屾暟
+ */
+ int updateNotifyChannelConfig(NotifyChannelConfig notifyChannelConfig);
+
+ /**
+ * 鍒犻櫎閫氱煡娓犻亾閰嶇疆
+ *
+ * @param id 涓婚敭ID
+ * @return 褰卞搷琛屾暟
+ */
+ int deleteNotifyChannelConfigById(Long id);
+
+ /**
+ * 鎵归噺鍒犻櫎閫氱煡娓犻亾閰嶇疆
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑涓婚敭ID闆嗗悎
+ * @return 褰卞搷琛屾暟
+ */
+ int deleteNotifyChannelConfigByIds(Long[] ids);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/NotifySendLogMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/NotifySendLogMapper.java
new file mode 100644
index 0000000..8e040df
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/NotifySendLogMapper.java
@@ -0,0 +1,110 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.ruoyi.system.domain.NotifySendLog;
+
+/**
+ * 閫氱煡鍙戦�佽褰昅apper鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+public interface NotifySendLogMapper {
+
+ /**
+ * 鏌ヨ閫氱煡鍙戦�佽褰�
+ *
+ * @param id 閫氱煡鍙戦�佽褰曚富閿�
+ * @return 閫氱煡鍙戦�佽褰�
+ */
+ NotifySendLog selectNotifySendLogById(Long id);
+
+ /**
+ * 鏌ヨ閫氱煡鍙戦�佽褰曞垪琛�
+ *
+ * @param notifySendLog 閫氱煡鍙戦�佽褰�
+ * @return 閫氱煡鍙戦�佽褰曢泦鍚�
+ */
+ List<NotifySendLog> selectNotifySendLogList(NotifySendLog notifySendLog);
+
+ /**
+ * 妫�鏌ユ槸鍚﹀凡瀛樺湪鍙戦�佽褰曪紙闃查噸妫�鏌ワ級
+ *
+ * @param taskId 浠诲姟ID
+ * @param userId 鐢ㄦ埛ID
+ * @param notifyType 閫氱煡绫诲瀷
+ * @param channel 閫氱煡娓犻亾
+ * @return 璁板綍鏁伴噺
+ */
+ int checkNotifySendLogExists(@Param("taskId") Long taskId,
+ @Param("userId") Long userId,
+ @Param("notifyType") String notifyType,
+ @Param("channel") String channel);
+
+ /**
+ * 鏍规嵁浠诲姟ID鍜岀敤鎴稩D鏌ヨ鍙戦�佽褰�
+ *
+ * @param taskId 浠诲姟ID
+ * @param userId 鐢ㄦ埛ID
+ * @param notifyType 閫氱煡绫诲瀷
+ * @param channel 閫氱煡娓犻亾
+ * @return 閫氱煡鍙戦�佽褰�
+ */
+ NotifySendLog selectNotifySendLog(@Param("taskId") Long taskId,
+ @Param("userId") Long userId,
+ @Param("notifyType") String notifyType,
+ @Param("channel") String channel);
+
+ /**
+ * 鏂板閫氱煡鍙戦�佽褰�
+ *
+ * @param notifySendLog 閫氱煡鍙戦�佽褰�
+ * @return 缁撴灉
+ */
+ int insertNotifySendLog(NotifySendLog notifySendLog);
+
+ /**
+ * 淇敼閫氱煡鍙戦�佽褰�
+ *
+ * @param notifySendLog 閫氱煡鍙戦�佽褰�
+ * @return 缁撴灉
+ */
+ int updateNotifySendLog(NotifySendLog notifySendLog);
+
+ /**
+ * 鏇存柊鍙戦�佺姸鎬�
+ *
+ * @param id 璁板綍ID
+ * @param sendStatus 鍙戦�佺姸鎬�
+ * @param sendResult 鍙戦�佺粨鏋�
+ * @return 缁撴灉
+ */
+ int updateSendStatus(@Param("id") Long id,
+ @Param("sendStatus") String sendStatus,
+ @Param("sendResult") String sendResult);
+
+ /**
+ * 鍒犻櫎閫氱煡鍙戦�佽褰�
+ *
+ * @param id 閫氱煡鍙戦�佽褰曚富閿�
+ * @return 缁撴灉
+ */
+ int deleteNotifySendLogById(Long id);
+
+ /**
+ * 鎵归噺鍒犻櫎閫氱煡鍙戦�佽褰�
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ int deleteNotifySendLogByIds(Long[] ids);
+
+ /**
+ * 鏌ヨ寰呴噸璇曠殑澶辫触璁板綍
+ *
+ * @param maxRetryCount 鏈�澶ч噸璇曟鏁�
+ * @return 澶辫触璁板綍鍒楄〃
+ */
+ List<NotifySendLog> selectFailedNotifySendLogs(@Param("maxRetryCount") Integer maxRetryCount);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/NotifyTaskMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/NotifyTaskMapper.java
new file mode 100644
index 0000000..96ecce9
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/NotifyTaskMapper.java
@@ -0,0 +1,98 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.system.domain.NotifyTask;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+
+/**
+ * 閫氱煡浠诲姟Mapper鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+public interface NotifyTaskMapper {
+
+ /**
+ * 鏌ヨ閫氱煡浠诲姟
+ *
+ * @param id 涓婚敭ID
+ * @return 閫氱煡浠诲姟
+ */
+ NotifyTask selectNotifyTaskById(Long id);
+
+ /**
+ * 鏌ヨ閫氱煡浠诲姟鍒楄〃
+ *
+ * @param notifyTask 鏌ヨ鏉′欢
+ * @return 閫氱煡浠诲姟鍒楄〃
+ */
+ List<NotifyTask> selectNotifyTaskList(NotifyTask notifyTask);
+
+ /**
+ * 鏌ヨ寰呭鐞嗙殑閫氱煡浠诲姟
+ *
+ * @param limit 鏌ヨ鏁伴噺闄愬埗
+ * @return 寰呭鐞嗙殑閫氱煡浠诲姟鍒楄〃
+ */
+ List<NotifyTask> selectPendingNotifyTasks(int limit);
+
+ /**
+ * 妫�鏌ラ�氱煡浠诲姟鏄惁宸插瓨鍦�
+ *
+ * @param taskId 涓氬姟浠诲姟ID
+ * @param userId 鐢ㄦ埛ID
+ * @param notifyType 閫氱煡绫诲瀷
+ * @return 鏁伴噺
+ */
+ int countByTaskUserType(@Param("taskId") Long taskId, @Param("userId") Long userId, @Param("notifyType") String notifyType);
+
+ /**
+ * 鏂板閫氱煡浠诲姟
+ *
+ * @param notifyTask 閫氱煡浠诲姟
+ * @return 褰卞搷琛屾暟
+ */
+ int insertNotifyTask(NotifyTask notifyTask);
+
+ /**
+ * 淇敼閫氱煡浠诲姟
+ *
+ * @param notifyTask 閫氱煡浠诲姟
+ * @return 褰卞搷琛屾暟
+ */
+ int updateNotifyTask(NotifyTask notifyTask);
+
+ /**
+ * 鏇存柊閫氱煡浠诲姟鐘舵��
+ *
+ * @param id 涓婚敭ID
+ * @param status 鐘舵��
+ * @param errorMsg 閿欒淇℃伅
+ * @return 褰卞搷琛屾暟
+ */
+ int updateNotifyTaskStatus(@Param("id") Long id, @Param("status") String status, @Param("errorMsg") String errorMsg);
+
+ /**
+ * 澧炲姞閲嶈瘯娆℃暟
+ *
+ * @param id 涓婚敭ID
+ * @return 褰卞搷琛屾暟
+ */
+ int incrementRetryCount(Long id);
+
+ /**
+ * 鍒犻櫎閫氱煡浠诲姟
+ *
+ * @param id 涓婚敭ID
+ * @return 褰卞搷琛屾暟
+ */
+ int deleteNotifyTaskById(Long id);
+
+ /**
+ * 鎵归噺鍒犻櫎閫氱煡浠诲姟
+ *
+ * @param ids 涓婚敭ID鏁扮粍
+ * @return 褰卞搷琛屾暟
+ */
+ int deleteNotifyTaskByIds(Long[] ids);
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAssigneeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAssigneeMapper.java
index 58b67bd..808db11 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAssigneeMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAssigneeMapper.java
@@ -1,6 +1,7 @@
package com.ruoyi.system.mapper;
import com.ruoyi.system.domain.SysTaskAssignee;
+import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
@@ -74,4 +75,13 @@
* @return 缁撴灉
*/
public int deleteSysTaskAssigneeByIds(Long[] ids);
+
+ /**
+ * 鏍规嵁浠诲姟ID鍜岀敤鎴稩D鍒犻櫎鎵ц浜哄憳鍏宠仈
+ *
+ * @param taskId 浠诲姟ID
+ * @param userId 鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ public int deleteByTaskIdAndUserId(@Param("taskId") Long taskId, @Param("userId") Long userId);
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskMapper.java
index deeda59..c918380 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskMapper.java
@@ -1,5 +1,6 @@
package com.ruoyi.system.mapper;
+import java.util.Date;
import java.util.List;
import com.ruoyi.common.annotation.DataSource;
@@ -7,6 +8,7 @@
import com.ruoyi.system.domain.SysTask;
import com.ruoyi.system.domain.vo.TaskQueryVO;
import com.ruoyi.system.domain.vo.TaskStatisticsVO;
+import org.apache.ibatis.annotations.Param;
/**
* 浠诲姟绠$悊Mapper鎺ュ彛
@@ -127,4 +129,15 @@
* @return 姝e湪杩涜涓殑浠诲姟鍒楄〃
*/
public List<SysTask> selectActiveTasksByVehicleId(Long vehicleId);
+
+ /**
+ * 鏍规嵁鏃堕棿鍜岃溅杈嗘潵鏌ヨ璇ヨ溅杈嗘槸鍚︽鍦ㄤ换鍔′腑
+ * @param vehicleId
+ * @param startTime
+ * @param endTime
+ * @return
+ */
+ public List<SysTask> selectTaskByVehicleIdAndDate(@Param("vehicleId") Long vehicleId,
+ @Param("startTime") Date startTime,
+ @Param("endTime") Date endTime);
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleMileageStatsMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleMileageStatsMapper.java
index 328dbe8..1740365 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleMileageStatsMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/VehicleMileageStatsMapper.java
@@ -71,7 +71,7 @@
/**
* 鏌ヨ杞﹁締鍦ㄦ寚瀹氭椂闂磋寖鍥村唴鐨勪换鍔℃椂闂村尯闂�
- *
+ *
* @param vehicleId 杞﹁締ID
* @param startTime 寮�濮嬫椂闂�
* @param endTime 缁撴潫鏃堕棿
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/INotifyChannelConfigService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/INotifyChannelConfigService.java
new file mode 100644
index 0000000..e82e459
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/INotifyChannelConfigService.java
@@ -0,0 +1,70 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.system.domain.NotifyChannelConfig;
+import java.util.List;
+
+/**
+ * 閫氱煡娓犻亾閰嶇疆Service鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+public interface INotifyChannelConfigService {
+ /**
+ * 鏌ヨ閫氱煡娓犻亾閰嶇疆
+ *
+ * @param id 涓婚敭ID
+ * @return 閫氱煡娓犻亾閰嶇疆
+ */
+ public NotifyChannelConfig selectNotifyChannelConfigById(Long id);
+
+ /**
+ * 鏌ヨ閫氱煡娓犻亾閰嶇疆鍒楄〃
+ *
+ * @param notifyChannelConfig 鏌ヨ鏉′欢
+ * @return 閫氱煡娓犻亾閰嶇疆鍒楄〃
+ */
+ public List<NotifyChannelConfig> selectNotifyChannelConfigList(NotifyChannelConfig notifyChannelConfig);
+
+ /**
+ * 鏌ヨ鎸囧畾閫氱煡绫诲瀷鍚敤鐨勬笭閬撻厤缃�
+ * 鎸変紭鍏堢骇闄嶅簭鎺掑垪
+ *
+ * @param notifyType 閫氱煡绫诲瀷
+ * @return 鍚敤鐨勬笭閬撻厤缃垪琛�
+ */
+ public List<NotifyChannelConfig> selectEnabledChannelsByType(String notifyType);
+
+ /**
+ * 妫�鏌ユ寚瀹氭笭閬撴槸鍚﹀惎鐢�
+ *
+ * @param notifyType 閫氱煡绫诲瀷
+ * @param channel 娓犻亾
+ * @return 閰嶇疆淇℃伅
+ */
+ public NotifyChannelConfig selectByTypeAndChannel(String notifyType, String channel);
+
+ /**
+ * 鏂板閫氱煡娓犻亾閰嶇疆
+ *
+ * @param notifyChannelConfig 閫氱煡娓犻亾閰嶇疆
+ * @return 缁撴灉
+ */
+ public int insertNotifyChannelConfig(NotifyChannelConfig notifyChannelConfig);
+
+ /**
+ * 淇敼閫氱煡娓犻亾閰嶇疆
+ *
+ * @param notifyChannelConfig 閫氱煡娓犻亾閰嶇疆
+ * @return 缁撴灉
+ */
+ public int updateNotifyChannelConfig(NotifyChannelConfig notifyChannelConfig);
+
+ /**
+ * 鎵归噺鍒犻櫎閫氱煡娓犻亾閰嶇疆
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑涓婚敭ID闆嗗悎
+ * @return 缁撴灉
+ */
+ public int deleteNotifyChannelConfigByIds(Long[] ids);
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/INotifyDispatchService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/INotifyDispatchService.java
new file mode 100644
index 0000000..b2ca905
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/INotifyDispatchService.java
@@ -0,0 +1,81 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.system.domain.NotifyTask;
+import com.ruoyi.system.domain.NotifyChannelConfig;
+import java.util.List;
+
+/**
+ * 閫氱煡鍒嗗彂鏈嶅姟鎺ュ彛
+ * 璐熻矗鏍规嵁閰嶇疆鍐冲畾鍙戦�佹笭閬撳苟鎵ц鍒嗗彂
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+public interface INotifyDispatchService {
+
+ /**
+ * 鑾峰彇鎸囧畾閫氱煡绫诲瀷鍚敤鐨勬笭閬撳垪琛�
+ *
+ * @param notifyType 閫氱煡绫诲瀷
+ * @return 鍚敤鐨勬笭閬撻厤缃垪琛紙鎸変紭鍏堢骇鎺掑簭锛�
+ */
+ List<NotifyChannelConfig> getEnabledChannels(String notifyType);
+
+ /**
+ * 妫�鏌ユ寚瀹氭笭閬撴槸鍚﹀惎鐢�
+ *
+ * @param notifyType 閫氱煡绫诲瀷
+ * @param channel 娓犻亾
+ * @return true=鍚敤, false=鏈惎鐢�
+ */
+ boolean isChannelEnabled(String notifyType, String channel);
+
+ /**
+ * 鍒嗗彂閫氱煡浠诲姟
+ * 鏍规嵁娓犻亾閰嶇疆锛屽悜鍚勫惎鐢ㄧ殑娓犻亾鍙戦�侀�氱煡
+ *
+ * @param notifyTask 閫氱煡浠诲姟
+ * @return 鎴愬姛鍙戦�佺殑娓犻亾鏁伴噺
+ */
+ int dispatchNotify(NotifyTask notifyTask);
+
+ /**
+ * 鎵归噺鍒嗗彂閫氱煡浠诲姟
+ *
+ * @param notifyTasks 閫氱煡浠诲姟鍒楄〃
+ * @return 鎴愬姛鍒嗗彂鐨勪换鍔℃暟閲�
+ */
+ int dispatchNotifies(List<NotifyTask> notifyTasks);
+
+ /**
+ * 澶勭悊寰呭彂閫佺殑閫氱煡浠诲姟锛堝彲鐢ㄤ簬瀹氭椂浠诲姟璋冪敤锛�
+ *
+ * @param limit 姣忔澶勭悊鐨勬暟閲忛檺鍒�
+ * @return 澶勭悊鐨勪换鍔℃暟閲�
+ */
+ int processPendingNotifies(int limit);
+
+ /**
+ * 鍙戦�佺珯鍐呮秷鎭�
+ *
+ * @param notifyTask 閫氱煡浠诲姟
+ * @return 鏄惁鍙戦�佹垚鍔�
+ */
+ boolean sendSiteMessage(NotifyTask notifyTask);
+
+ /**
+ * 鍙戦�佸井淇¤闃呮秷鎭�
+ *
+ * @param notifyTask 閫氱煡浠诲姟
+ * @return 鏄惁鍙戦�佹垚鍔�
+ */
+ boolean sendWechatMessage(NotifyTask notifyTask);
+
+ /**
+ * 鍙戦�佺煭淇℃秷鎭�
+ *
+ * @param notifyTask 閫氱煡浠诲姟
+ * @return 鏄惁鍙戦�佹垚鍔�
+ */
+ boolean sendSmsMessage(NotifyTask notifyTask);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/INotifySendLogService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/INotifySendLogService.java
new file mode 100644
index 0000000..a6385ad
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/INotifySendLogService.java
@@ -0,0 +1,109 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.NotifySendLog;
+
+/**
+ * 閫氱煡鍙戦�佽褰曟湇鍔℃帴鍙�
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+public interface INotifySendLogService {
+
+ /**
+ * 鏌ヨ閫氱煡鍙戦�佽褰�
+ *
+ * @param id 閫氱煡鍙戦�佽褰曚富閿�
+ * @return 閫氱煡鍙戦�佽褰�
+ */
+ NotifySendLog selectNotifySendLogById(Long id);
+
+ /**
+ * 鏌ヨ閫氱煡鍙戦�佽褰曞垪琛�
+ *
+ * @param notifySendLog 閫氱煡鍙戦�佽褰�
+ * @return 閫氱煡鍙戦�佽褰曢泦鍚�
+ */
+ List<NotifySendLog> selectNotifySendLogList(NotifySendLog notifySendLog);
+
+ /**
+ * 妫�鏌ユ槸鍚﹀凡鍙戦�佽繃閫氱煡锛堥槻閲嶆鏌ワ級
+ *
+ * @param taskId 浠诲姟ID
+ * @param userId 鐢ㄦ埛ID
+ * @param notifyType 閫氱煡绫诲瀷
+ * @param channel 閫氱煡娓犻亾
+ * @return true=宸插彂閫佽繃, false=鏈彂閫佽繃
+ */
+ boolean hasNotified(Long taskId, Long userId, String notifyType, String channel);
+
+ /**
+ * 灏濊瘯鍒涘缓鍙戦�佽褰曪紙闃查噸锛屽鏋滃凡瀛樺湪鍒欒繑鍥瀎alse锛�
+ *
+ * @param taskId 浠诲姟ID
+ * @param userId 鐢ㄦ埛ID
+ * @param userName 鐢ㄦ埛濮撳悕
+ * @param notifyType 閫氱煡绫诲瀷
+ * @param channel 閫氱煡娓犻亾
+ * @return 鍒涘缓鐨勮褰曪紝濡傛灉宸插瓨鍦ㄥ垯杩斿洖null
+ */
+ NotifySendLog tryCreateSendLog(Long taskId, Long userId, String userName,
+ String notifyType, String channel);
+
+ /**
+ * 鏇存柊鍙戦�佺姸鎬佷负鎴愬姛
+ *
+ * @param id 璁板綍ID
+ * @param result 鍙戦�佺粨鏋滀俊鎭�
+ */
+ void markSendSuccess(Long id, String result);
+
+ /**
+ * 鏇存柊鍙戦�佺姸鎬佷负澶辫触
+ *
+ * @param id 璁板綍ID
+ * @param errorMsg 閿欒淇℃伅
+ */
+ void markSendFailed(Long id, String errorMsg);
+
+ /**
+ * 鏂板閫氱煡鍙戦�佽褰�
+ *
+ * @param notifySendLog 閫氱煡鍙戦�佽褰�
+ * @return 缁撴灉
+ */
+ int insertNotifySendLog(NotifySendLog notifySendLog);
+
+ /**
+ * 淇敼閫氱煡鍙戦�佽褰�
+ *
+ * @param notifySendLog 閫氱煡鍙戦�佽褰�
+ * @return 缁撴灉
+ */
+ int updateNotifySendLog(NotifySendLog notifySendLog);
+
+ /**
+ * 鎵归噺鍒犻櫎閫氱煡鍙戦�佽褰�
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑閫氱煡鍙戦�佽褰曚富閿泦鍚�
+ * @return 缁撴灉
+ */
+ int deleteNotifySendLogByIds(Long[] ids);
+
+ /**
+ * 鍒犻櫎閫氱煡鍙戦�佽褰曚俊鎭�
+ *
+ * @param id 閫氱煡鍙戦�佽褰曚富閿�
+ * @return 缁撴灉
+ */
+ int deleteNotifySendLogById(Long id);
+
+ /**
+ * 鏌ヨ寰呴噸璇曠殑澶辫触璁板綍
+ *
+ * @param maxRetryCount 鏈�澶ч噸璇曟鏁�
+ * @return 澶辫触璁板綍鍒楄〃
+ */
+ List<NotifySendLog> selectFailedNotifySendLogs(Integer maxRetryCount);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/INotifyTaskService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/INotifyTaskService.java
new file mode 100644
index 0000000..eeaa253
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/INotifyTaskService.java
@@ -0,0 +1,121 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.system.domain.NotifyTask;
+import java.util.List;
+
+/**
+ * 閫氱煡浠诲姟鏈嶅姟鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+public interface INotifyTaskService {
+
+ /**
+ * 鏌ヨ閫氱煡浠诲姟
+ *
+ * @param id 涓婚敭ID
+ * @return 閫氱煡浠诲姟
+ */
+ NotifyTask selectNotifyTaskById(Long id);
+
+ /**
+ * 鏌ヨ閫氱煡浠诲姟鍒楄〃
+ *
+ * @param notifyTask 鏌ヨ鏉′欢
+ * @return 閫氱煡浠诲姟鍒楄〃
+ */
+ List<NotifyTask> selectNotifyTaskList(NotifyTask notifyTask);
+
+ /**
+ * 鏌ヨ寰呭鐞嗙殑閫氱煡浠诲姟
+ *
+ * @param limit 鏌ヨ鏁伴噺闄愬埗
+ * @return 寰呭鐞嗙殑閫氱煡浠诲姟鍒楄〃
+ */
+ List<NotifyTask> selectPendingNotifyTasks(int limit);
+
+ /**
+ * 妫�鏌ラ�氱煡浠诲姟鏄惁宸插瓨鍦紙闃查噸锛�
+ *
+ * @param taskId 涓氬姟浠诲姟ID
+ * @param userId 鐢ㄦ埛ID
+ * @param notifyType 閫氱煡绫诲瀷
+ * @return true=宸插瓨鍦�, false=涓嶅瓨鍦�
+ */
+ boolean existsNotifyTask(Long taskId, Long userId, String notifyType);
+
+ /**
+ * 鍒涘缓閫氱煡浠诲姟锛堝甫闃查噸锛�
+ * 濡傛灉宸插瓨鍦ㄥ垯杩斿洖null锛屽惁鍒欏垱寤哄苟杩斿洖
+ *
+ * @param notifyTask 閫氱煡浠诲姟
+ * @return 鍒涘缓鐨勯�氱煡浠诲姟锛屽鏋滃凡瀛樺湪杩斿洖null
+ */
+ NotifyTask createNotifyTask(NotifyTask notifyTask);
+
+ /**
+ * 鎵归噺鍒涘缓閫氱煡浠诲姟
+ *
+ * @param notifyTasks 閫氱煡浠诲姟鍒楄〃
+ * @return 鎴愬姛鍒涘缓鐨勬暟閲�
+ */
+ int createNotifyTasks(List<NotifyTask> notifyTasks);
+
+ /**
+ * 淇敼閫氱煡浠诲姟
+ *
+ * @param notifyTask 閫氱煡浠诲姟
+ * @return 褰卞搷琛屾暟
+ */
+ int updateNotifyTask(NotifyTask notifyTask);
+
+ /**
+ * 鏇存柊閫氱煡浠诲姟鐘舵�佷负澶勭悊涓�
+ *
+ * @param id 涓婚敭ID
+ * @return 褰卞搷琛屾暟
+ */
+ int markProcessing(Long id);
+
+ /**
+ * 鏇存柊閫氱煡浠诲姟鐘舵�佷负瀹屾垚
+ *
+ * @param id 涓婚敭ID
+ * @return 褰卞搷琛屾暟
+ */
+ int markCompleted(Long id);
+
+ /**
+ * 鏇存柊閫氱煡浠诲姟鐘舵�佷负澶辫触
+ *
+ * @param id 涓婚敭ID
+ * @param errorMsg 閿欒淇℃伅
+ * @return 褰卞搷琛屾暟
+ */
+ int markFailed(Long id, String errorMsg);
+
+ /**
+ * 澧炲姞閲嶈瘯娆℃暟
+ *
+ * @param id 涓婚敭ID
+ * @return 褰卞搷琛屾暟
+ */
+ int incrementRetryCount(Long id);
+
+ /**
+ * 鍒犻櫎閫氱煡浠诲姟
+ *
+ * @param id 涓婚敭ID
+ * @return 褰卞搷琛屾暟
+ */
+ int deleteNotifyTaskById(Long id);
+
+ /**
+ * 鎵归噺鍒犻櫎閫氱煡浠诲姟
+ *
+ * @param ids 涓婚敭ID鏁扮粍
+ * @return 褰卞搷琛屾暟
+ */
+ int deleteNotifyTaskByIds(Long[] ids);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISmsService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISmsService.java
new file mode 100644
index 0000000..59e7110
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISmsService.java
@@ -0,0 +1,64 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.system.domain.SysTask;
+import java.util.List;
+
+/**
+ * 鐭俊鍙戦�佹湇鍔℃帴鍙�
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+public interface ISmsService {
+
+ /**
+ * 妫�鏌ョ煭淇℃湇鍔℃槸鍚﹀惎鐢�
+ *
+ * @return true=鍚敤, false=绂佺敤
+ */
+ boolean isEnabled();
+
+ /**
+ * 鍙戦�佺煭淇�
+ *
+ * @param phone 鎵嬫満鍙�
+ * @param content 鐭俊鍐呭
+ * @return 鏄惁鍙戦�佹垚鍔�
+ */
+ boolean sendSms(String phone, String content);
+
+ /**
+ * 鎵归噺鍙戦�佺煭淇�
+ *
+ * @param phones 鎵嬫満鍙峰垪琛�
+ * @param content 鐭俊鍐呭
+ * @return 鎴愬姛鍙戦�佺殑鏁伴噺
+ */
+ int sendSmsBatch(List<String> phones, String content);
+
+ /**
+ * 鍙戦�佷换鍔″垎閰嶉�氱煡鐭俊
+ *
+ * @param taskId 浠诲姟ID
+ * @param userIds 鐢ㄦ埛ID鍒楄〃
+ * @param excludeUserId 鎺掗櫎鐨勭敤鎴稩D锛堝彲閫夛紝濡傚垱寤轰汉锛�
+ * @return 鎴愬姛鍙戦�佺殑鏁伴噺
+ */
+ int sendTaskAssignSms(Long taskId, List<Long> userIds, Long excludeUserId);
+
+ /**
+ * 鍙戦�佷换鍔″垎閰嶉�氱煡鐭俊锛堜笉鎺掗櫎浠讳綍鐢ㄦ埛锛�
+ *
+ * @param taskId 浠诲姟ID
+ * @param userIds 鐢ㄦ埛ID鍒楄〃
+ * @return 鎴愬姛鍙戦�佺殑鏁伴噺
+ */
+ int sendTaskAssignSms(Long taskId, List<Long> userIds);
+
+ /**
+ * 鏌ヨ鐭俊浣欓
+ *
+ * @return 浣欓淇℃伅
+ */
+ String getBalance();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysEmergencyTaskService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysEmergencyTaskService.java
new file mode 100644
index 0000000..3768c4e
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysEmergencyTaskService.java
@@ -0,0 +1,33 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.system.domain.SysTaskEmergency;
+import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.vo.TaskCreateVO;
+import com.ruoyi.system.domain.vo.TaskUpdateVO;
+
+public interface ISysEmergencyTaskService {
+
+ void saveEmergencyInfo(Long taskId, String createUserName, TaskCreateVO createVO,
+ String serviceOrderId, String dispatchOrderId, String serviceOrdNo);
+
+ void updateEmergencyInfoFromUpdateVO(SysTaskEmergency oldEmergency, TaskUpdateVO updateVO, String userName);
+
+ /**
+ * 浠� TaskCreateVO 鏇存柊鎬ユ晳杞繍浠诲姟鎵╁睍淇℃伅锛堢敤浜庢棫绯荤粺鍚屾锛�
+ *
+ * @param existingInfo 鐜版湁鐨勬�ユ晳浠诲姟淇℃伅
+ * @param createVO 浠诲姟鍒涘缓瀵硅薄
+ * @param userName 鎿嶄綔浜虹敤鎴峰悕
+ */
+ void updateEmergencyInfoFromCreateVO(SysTaskEmergency existingInfo, TaskCreateVO createVO, String userName);
+
+ void markNeedResyncIfNecessary(Long taskId, SysTask oldTask, TaskUpdateVO updateVO, Boolean updateFromLegacy);
+
+ boolean hasLegacyServiceOrdId(Long taskId);
+
+ boolean hasLegacyDispatchOrdId(Long taskId);
+
+ boolean existsByLegacyServiceOrdId(Long legacyServiceOrdId);
+
+ boolean existsByLegacyDispatchOrdId(Long legacyDispatchOrdId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskAssigneeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskAssigneeService.java
new file mode 100644
index 0000000..016bf8c
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskAssigneeService.java
@@ -0,0 +1,84 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.system.domain.SysTaskAssignee;
+import com.ruoyi.system.domain.vo.TaskCreateVO;
+
+import java.util.List;
+
+/**
+ * 浠诲姟鎵ц浜烘湇鍔℃帴鍙�
+ *
+ * @author ruoyi
+ */
+public interface ISysTaskAssigneeService {
+
+ /**
+ * 淇濆瓨浠诲姟鎵ц浜哄憳淇℃伅
+ *
+ * @param taskId 浠诲姟ID
+ * @param assignees 鎵ц浜哄憳淇℃伅鍒楄〃
+ * @param userName 鎿嶄綔浜�
+ */
+ void saveTaskAssignees(Long taskId, List<TaskCreateVO.AssigneeInfo> assignees, String userName);
+
+ /**
+ * 鏇存柊浠诲姟鎵ц浜哄憳锛堝惈鍙樻洿妫�娴嬶紝浠呭湪鏈夊彉鍖栨椂鎵嶆洿鏂帮級
+ *
+ * @param taskId 浠诲姟ID
+ * @param newAssignees 鏂扮殑鎵ц浜哄憳淇℃伅鍒楄〃
+ * @param userName 鎿嶄綔浜�
+ * @return 鏄惁鏈夊彉鏇�
+ */
+ boolean updateTaskAssignees(Long taskId, List<TaskCreateVO.AssigneeInfo> newAssignees, String userName);
+
+ /**
+ * 鏍规嵁浠诲姟ID鑾峰彇鎵ц浜哄垪琛�
+ *
+ * @param taskId 浠诲姟ID
+ * @return 鎵ц浜哄垪琛�
+ */
+ List<SysTaskAssignee> getAssigneesByTaskId(Long taskId);
+
+ /**
+ * 鍒犻櫎浠诲姟鐨勬墍鏈夋墽琛屼汉
+ *
+ * @param taskId 浠诲姟ID
+ * @return 鍒犻櫎鏁伴噺
+ */
+ int deleteAssigneesByTaskId(Long taskId);
+
+ /**
+ * 鎵ц浜虹偣鍑诲氨缁�
+ *
+ * @param taskId 浠诲姟ID
+ * @param userId 鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ AjaxResult setAssigneeReady(Long taskId, Long userId);
+
+ /**
+ * 鍙栨秷鎵ц浜哄氨缁�
+ *
+ * @param taskId 浠诲姟ID
+ * @param userId 鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ AjaxResult cancelAssigneeReady(Long taskId, Long userId);
+
+ /**
+ * 鑾峰彇鎵ц浜篒D鍒楄〃
+ *
+ * @param taskId 浠诲姟ID
+ * @return 鎵ц浜篒D鍒楄〃
+ */
+ List<Long> getAssigneeIds(Long taskId);
+
+ /**
+ * 鑾峰彇鎵ц浜哄鍚嶅垪琛�
+ *
+ * @param taskId 浠诲姟ID
+ * @return 鎵ц浜哄鍚嶅垪琛�
+ */
+ List<String> getAssigneeNames(Long taskId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskAttachmentService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskAttachmentService.java
new file mode 100644
index 0000000..6f9cd58
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskAttachmentService.java
@@ -0,0 +1,33 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.system.domain.SysTaskAttachment;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+public interface ISysTaskAttachmentService {
+ Long uploadAttachment(Long taskId, MultipartFile file, String category);
+
+ Long uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category);
+
+ int deleteAttachment(Long attachmentId);
+
+ SysTaskAttachment getAttachmentById(Long attachmentId);
+
+ List<SysTaskAttachment> getAttachmentsByTaskId(Long taskId);
+
+ /**
+ * 鑾峰彇闄勪欢鍒嗙被鎻忚堪
+ *
+ * @param category 闄勪欢鍒嗙被浠g爜
+ * @return 鍒嗙被鎻忚堪
+ */
+ String getCategoryDesc(String category);
+
+ /**
+ * 鏋勫缓闄勪欢鐨勫畬鏁碪RL
+ *
+ * @param attachment 闄勪欢瀵硅薄
+ */
+ void buildAttachmentUrl(SysTaskAttachment attachment);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java
index 0e1ec8b..98f0e82 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java
@@ -1,24 +1,17 @@
package com.ruoyi.system.service;
-import java.util.List;
-import java.util.Map;
import com.ruoyi.system.domain.SysTaskVehicle;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
/**
- * 浠诲姟杞﹁締鍏宠仈Service鎺ュ彛
+ * 浠诲姟杞﹁締鏈嶅姟鎺ュ彛
*
* @author ruoyi
- * @date 2024-01-15
*/
public interface ISysTaskVehicleService {
-
- /**
- * 鏌ヨ浠诲姟杞﹁締鍏宠仈
- *
- * @param id 浠诲姟杞﹁締鍏宠仈涓婚敭
- * @return 浠诲姟杞﹁締鍏宠仈
- */
- public SysTaskVehicle selectSysTaskVehicleById(Long id);
/**
* 鏌ヨ浠诲姟杞﹁締鍏宠仈鍒楄〃
@@ -26,7 +19,15 @@
* @param sysTaskVehicle 浠诲姟杞﹁締鍏宠仈
* @return 浠诲姟杞﹁締鍏宠仈闆嗗悎
*/
- public List<SysTaskVehicle> selectSysTaskVehicleList(SysTaskVehicle sysTaskVehicle);
+ List<SysTaskVehicle> selectSysTaskVehicleList(SysTaskVehicle sysTaskVehicle);
+
+ /**
+ * 鏌ヨ浠诲姟杞﹁締鍏宠仈淇℃伅
+ *
+ * @param id 浠诲姟杞﹁締鍏宠仈涓婚敭
+ * @return 浠诲姟杞﹁締鍏宠仈淇℃伅
+ */
+ SysTaskVehicle selectSysTaskVehicleById(Long id);
/**
* 鏍规嵁浠诲姟ID鏌ヨ鍏宠仈杞﹁締鍒楄〃
@@ -34,7 +35,7 @@
* @param taskId 浠诲姟ID
* @return 浠诲姟杞﹁締鍏宠仈闆嗗悎
*/
- public List<SysTaskVehicle> selectSysTaskVehicleByTaskId(Long taskId);
+ List<SysTaskVehicle> selectSysTaskVehicleByTaskId(Long taskId);
/**
* 鏂板浠诲姟杞﹁締鍏宠仈
@@ -42,7 +43,7 @@
* @param sysTaskVehicle 浠诲姟杞﹁締鍏宠仈
* @return 缁撴灉
*/
- public int insertSysTaskVehicle(SysTaskVehicle sysTaskVehicle);
+ int insertSysTaskVehicle(SysTaskVehicle sysTaskVehicle);
/**
* 淇敼浠诲姟杞﹁締鍏宠仈
@@ -50,15 +51,7 @@
* @param sysTaskVehicle 浠诲姟杞﹁締鍏宠仈
* @return 缁撴灉
*/
- public int updateSysTaskVehicle(SysTaskVehicle sysTaskVehicle);
-
- /**
- * 鎵归噺鍒犻櫎浠诲姟杞﹁締鍏宠仈
- *
- * @param ids 闇�瑕佸垹闄ょ殑浠诲姟杞﹁締鍏宠仈涓婚敭闆嗗悎
- * @return 缁撴灉
- */
- public int deleteSysTaskVehicleByIds(Long[] ids);
+ int updateSysTaskVehicle(SysTaskVehicle sysTaskVehicle);
/**
* 鍒犻櫎浠诲姟杞﹁締鍏宠仈淇℃伅
@@ -66,51 +59,73 @@
* @param id 浠诲姟杞﹁締鍏宠仈涓婚敭
* @return 缁撴灉
*/
- public int deleteSysTaskVehicleById(Long id);
+ int deleteSysTaskVehicleById(Long id);
/**
- * 鏍规嵁浠诲姟ID鍒犻櫎杞﹁締鍏宠仈
+ * 鎵归噺鍒犻櫎浠诲姟杞﹁締鍏宠仈淇℃伅
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ int deleteSysTaskVehicleByIds(Long[] ids);
+
+ /**
+ * 鏇存柊浠诲姟杞﹁締鍏宠仈鐘舵��
+ *
+ * @param id 浠诲姟杞﹁締鍏宠仈涓婚敭
+ * @param status 鐘舵��
+ * @return 缁撴灉
+ */
+ int updateSysTaskVehicleStatus(Long id, String status);
+
+ /**
+ * 鎵归噺鑾峰彇杞﹁締褰撳墠浠诲姟鐘舵��
+ *
+ * @param vehicleIds 杞﹁締ID鍒楄〃
+ * @return 杞﹁締浠诲姟鐘舵�佹槧灏�
+ */
+ Map<Long, Map<String, Object>> batchGetVehicleCurrentTaskStatus(List<Long> vehicleIds);
+
+ /**
+ * 淇濆瓨浠诲姟杞﹁締鍏宠仈
*
* @param taskId 浠诲姟ID
- * @return 缁撴灉
+ * @param vehicleIds 杞﹁締ID鍒楄〃
+ * @param userName 鎿嶄綔浜虹敤鎴峰悕
*/
- public int deleteSysTaskVehicleByTaskId(Long taskId);
+ void saveTaskVehicles(Long taskId, List<Long> vehicleIds, String userName);
/**
- * 鏍规嵁浠诲姟ID鍜岃溅杈咺D鍒犻櫎鍏宠仈
+ * 淇濆瓨浠诲姟杞﹁締鍏宠仈锛堟寚瀹氭椂闂达級
*
* @param taskId 浠诲姟ID
- * @param vehicleId 杞﹁締ID
- * @return 缁撴灉
+ * @param vehicleIds 杞﹁締ID鍒楄〃
+ * @param userName 鎿嶄綔浜虹敤鎴峰悕
+ * @param assignTime 鍒嗛厤鏃堕棿
+ * @param createTime 鍒涘缓鏃堕棿
+ * @param updateTime 鏇存柊鏃堕棿
*/
- public int deleteSysTaskVehicleByTaskIdAndVehicleId(Long taskId, Long vehicleId);
+ void saveTaskVehicles(Long taskId, List<Long> vehicleIds, String userName,
+ Date assignTime, Date createTime, Date updateTime);
/**
- * 妫�鏌ヤ换鍔¤溅杈嗗叧鑱旀槸鍚﹀瓨鍦�
+ * 鏇存柊浠诲姟杞﹁締鍏宠仈
*
* @param taskId 浠诲姟ID
- * @param vehicleId 杞﹁締ID
- * @return 缁撴灉
+ * @param newVehicleIds 鏂扮殑杞﹁締ID鍒楄〃
+ * @param userName 鎿嶄綔浜虹敤鎴峰悕
+ * @return 鏄惁鏈夊彉鏇�
*/
- public int checkTaskVehicleExists(Long taskId, Long vehicleId);
-
- /**
- * 鎵归噺鏂板浠诲姟杞﹁締鍏宠仈
- *
- * @param sysTaskVehicleList 浠诲姟杞﹁締鍏宠仈鍒楄〃
- * @return 缁撴灉
- */
- public int batchInsertSysTaskVehicle(List<SysTaskVehicle> sysTaskVehicleList);
-
- /**
- * 鍒嗛厤杞﹁締缁欎换鍔�
- *
+ boolean updateTaskVehicles(Long taskId, List<Long> newVehicleIds, String userName);
+ /*
* @param taskId 浠诲姟ID
* @param vehicleId 杞﹁締ID
* @param remark 澶囨敞
+ * @param userId 鎿嶄綔浜篒D
+ * @param userName 鎿嶄綔浜虹敤鎴峰悕
* @return 缁撴灉
*/
- public int assignVehicleToTask(Long taskId, Long vehicleId, String remark);
+ int assignVehicleToTask(Long taskId, Long vehicleId, String remark, Long userId, String userName);
/**
* 鍙栨秷浠诲姟杞﹁締鍒嗛厤
@@ -119,7 +134,7 @@
* @param vehicleId 杞﹁締ID
* @return 缁撴灉
*/
- public int unassignVehicleFromTask(Long taskId, Long vehicleId);
+ int unassignVehicleFromTask(Long taskId, Long vehicleId);
/**
* 鎵归噺鍒嗛厤杞﹁締缁欎换鍔�
@@ -127,9 +142,19 @@
* @param taskId 浠诲姟ID
* @param vehicleIds 杞﹁締ID鍒楄〃
* @param remark 澶囨敞
+ * @param userId 鎿嶄綔浜篒D
+ * @param userName 鎿嶄綔浜虹敤鎴峰悕
* @return 缁撴灉
*/
- public int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark);
+ int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark, Long userId, String userName);
+
+ /**
+ * 鏌ヨ浠诲姟鍏宠仈鐨勮溅杈�
+ *
+ * @param taskId 浠诲姟ID
+ * @return 浠诲姟杞﹁締鍏宠仈鍒楄〃
+ */
+ List<SysTaskVehicle> getTaskVehicles(Long taskId);
/**
* 鏌ヨ鍙敤杞﹁締
@@ -138,31 +163,22 @@
* @param taskType 浠诲姟绫诲瀷
* @return 鍙敤杞﹁締鍒楄〃
*/
- public List<SysTaskVehicle> getAvailableVehicles(Long deptId, String taskType);
+ List<SysTaskVehicle> getAvailableVehicles(Long deptId, String taskType);
/**
- * 鏇存柊浠诲姟杞﹁締鍏宠仈鐘舵��
+ * 鍒犻櫎浠诲姟鐨勬墍鏈夎溅杈嗗叧鑱�
*
- * @param id 鍏宠仈ID
- * @param status 鏂扮姸鎬�
+ * @param taskId 浠诲姟ID
* @return 缁撴灉
*/
- public int updateTaskVehicleStatus(Long id, String status);
+ int deleteTaskVehiclesByTaskId(Long taskId);
/**
- * 鎵归噺鑾峰彇杞﹁締褰撳墠浠诲姟鐘舵��
+ * 妫�鏌ヨ溅杈嗘槸鍚﹀凡鍒嗛厤缁欎换鍔�
*
- * @param vehicleIds 杞﹁締ID鍒楄〃
- * @return Map<杞﹁締ID, Map<"taskCode": 浠诲姟缂栧彿, "taskStatus": 浠诲姟鐘舵��>>
+ * @param taskId 浠诲姟ID
+ * @param vehicleId 杞﹁締ID
+ * @return true-宸插垎閰嶏紝false-鏈垎閰�
*/
- public Map<Long, Map<String, Object>> batchGetVehicleCurrentTaskStatus(List<Long> vehicleIds);
-
- /**
- * 鏇存柊浠诲姟杞﹁締鍏宠仈鐘舵�侊紙鏂版柟娉曪級
- *
- * @param id 鍏宠仈ID
- * @param status 鏂扮姸鎬�
- * @return 缁撴灉
- */
- public int updateSysTaskVehicleStatus(Long id, String status);
+ boolean checkVehicleAssigned(Long taskId, Long vehicleId);
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysWelfareTaskService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysWelfareTaskService.java
new file mode 100644
index 0000000..285efba
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysWelfareTaskService.java
@@ -0,0 +1,46 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.system.domain.SysTaskWelfare;
+import com.ruoyi.system.domain.vo.TaskCreateVO;
+
+/**
+ * 绂忕杞︿换鍔℃湇鍔℃帴鍙�
+ *
+ * @author ruoyi
+ */
+public interface ISysWelfareTaskService {
+
+ /**
+ * 淇濆瓨绂忕杞︿换鍔℃墿灞曚俊鎭�
+ *
+ * @param taskId 浠诲姟ID
+ * @param userName 鎿嶄綔浜虹敤鎴峰悕
+ * @param createVO 浠诲姟鍒涘缓瀵硅薄
+ */
+ void saveWelfareInfo(Long taskId, String userName, TaskCreateVO createVO);
+
+ /**
+ * 鏇存柊绂忕杞︿换鍔℃墿灞曚俊鎭�
+ *
+ * @param taskId 浠诲姟ID
+ * @param createVO 浠诲姟鍒涘缓/鏇存柊瀵硅薄
+ * @param userName 鎿嶄綔浜虹敤鎴峰悕
+ */
+ void updateWelfareInfo(Long taskId, TaskCreateVO createVO, String userName);
+
+ /**
+ * 鏍规嵁浠诲姟ID鏌ヨ绂忕杞︽墿灞曚俊鎭�
+ *
+ * @param taskId 浠诲姟ID
+ * @return 绂忕杞︽墿灞曚俊鎭�
+ */
+ SysTaskWelfare getWelfareInfoByTaskId(Long taskId);
+
+ /**
+ * 鍒犻櫎绂忕杞︽墿灞曚俊鎭�
+ *
+ * @param taskId 浠诲姟ID
+ * @return 缁撴灉
+ */
+ int deleteWelfareInfoByTaskId(Long taskId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CmsGpsCollectServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CmsGpsCollectServiceImpl.java
index 2c6b036..b93684a 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CmsGpsCollectServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CmsGpsCollectServiceImpl.java
@@ -191,11 +191,11 @@
// 瑙f瀽鍝嶅簲
CmsVehicleLocationResponse locationResponse = JSONObject.parseObject(response, CmsVehicleLocationResponse.class);
- if (locationResponse.getResult() == 0) {
- log.info("鑾峰彇杞﹁締浣嶇疆淇℃伅鎴愬姛锛岃溅鐗屽彿锛歿}", vehicleId);
- } else {
- log.error("鑾峰彇杞﹁締浣嶇疆淇℃伅澶辫触锛岃溅鐗屽彿锛歿}", vehicleId);
- }
+// if (locationResponse.getResult() == 0) {
+// log.info("鑾峰彇杞﹁締浣嶇疆淇℃伅鎴愬姛锛岃溅鐗屽彿锛歿}", vehicleId);
+// } else {
+// log.error("鑾峰彇杞﹁締浣嶇疆淇℃伅澶辫触锛岃溅鐗屽彿锛歿}", vehicleId);
+// }
return locationResponse;
} catch (Exception e) {
@@ -258,11 +258,11 @@
// 瑙f瀽鍝嶅簲
CmsTrackDetailResponse trackResponse = JSONObject.parseObject(response, CmsTrackDetailResponse.class);
- if (trackResponse.getResult() == 0) {
- log.info("鑾峰彇璁惧鍘嗗彶杞ㄨ抗鎴愬姛锛岃澶囧彿锛歿}", devIdno);
- } else {
- log.error("鑾峰彇璁惧鍘嗗彶杞ㄨ抗澶辫触锛岃澶囧彿锛歿}", devIdno);
- }
+// if (trackResponse.getResult() == 0) {
+// log.info("鑾峰彇璁惧鍘嗗彶杞ㄨ抗鎴愬姛锛岃澶囧彿锛歿}", devIdno);
+// } else {
+// log.error("鑾峰彇璁惧鍘嗗彶杞ㄨ抗澶辫触锛岃澶囧彿锛歿}", devIdno);
+// }
return trackResponse;
} catch (Exception e) {
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java
index 4413acb..487b710 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java
@@ -598,8 +598,20 @@
// 鎿嶄綔鍛戒护
params.put("DispatchOrd_Check", "0"); // 3=鐩存帴寮哄埗瀹屾垚
- // 缁╂晥鍜岃垂鐢�
- params.put("DispatchOrdPerfomance", emergency.getTransferPrice() != null ? emergency.getTransferPrice().toString() : "0");
+ // 缁╂晥鍜岃垂鐢細纭繚鏁板�煎瓧娈典笉涓簄ull
+ String transferPrice = "0";
+ if (emergency.getTransferPrice() != null) {
+ try {
+ transferPrice = emergency.getTransferPrice().toString();
+ if (transferPrice.contains(".")) {
+ transferPrice = new java.math.BigDecimal(transferPrice).stripTrailingZeros().toPlainString();
+ }
+ } catch (Exception e) {
+ log.warn("杞崲杞繍浠锋牸澶辫触锛屼换鍔D: {}, 浣跨敤榛樿鍊�0", task.getTaskId(), e);
+ transferPrice = "0";
+ }
+ }
+ params.put("DispatchOrdPerfomance", transferPrice);
params.put("StretcherMoney", "0"); // 鎶媴鏋惰垂
params.put("AddMoneyType", ""); // 闄勫姞椤圭洰
params.put("AddMoney", "0"); // 闄勫姞椤圭洰璐圭敤
@@ -632,7 +644,8 @@
params.put("ServiceOrdPtDoctorPhone", ""); // 鎮h�呭尰鐢熺數璇�
params.put("TransferModeID", ""); // 杞繍鏂瑰紡
params.put("ServiceOrdVIP", "0"); // VIP瀹㈡埛
- params.put("ServiceOrdTraTxnPrice", emergency.getTransferPrice() != null ? emergency.getTransferPrice().toString() : "0"); // 鎴愪氦浠�
+ // 浠锋牸瀛楁澶嶇敤锛岀‘淇濅竴鑷存��
+ params.put("ServiceOrdTraTxnPrice", transferPrice); // 鎴愪氦浠�
params.put("ServiceOrdTraPrePayment", "0"); // 闇�棰勪粯娆�
params.put("SettlementPrice", "0"); // 缁撶畻浠�
params.put("ServiceOrdTraPriceReason", ""); // 宸环鍘熷洜
@@ -649,7 +662,21 @@
params.put("ServiceOrdEstimatedOrderDate", ""); // 棰勮娲惧崟鏃堕棿
params.put("ServiceOrdEstimatedOrderDateOld", ""); // 鍘熼璁℃淳鍗曟椂闂�
params.put("ServiceOrdViaDistance", "0"); // 涓�旇窛绂�
- params.put("ServiceOrdTraDistance", emergency.getTransferDistance() != null ? emergency.getTransferDistance().toString() : "0"); // 璺濈
+ // 璺濈瀛楁锛氱‘淇濅笉涓虹┖锛岄伩鍏嶆棫绯荤粺鎺ュ彛鎶ラ敊
+ String transferDistance = "0";
+ if (emergency.getTransferDistance() != null) {
+ try {
+ transferDistance = emergency.getTransferDistance().toString();
+ // 鍘婚櫎鍙兘鐨勫皬鏁扮偣鍚庡浣欑殑0
+ if (transferDistance.contains(".")) {
+ transferDistance = new java.math.BigDecimal(transferDistance).stripTrailingZeros().toPlainString();
+ }
+ } catch (Exception e) {
+ log.warn("杞崲杞繍璺濈澶辫触锛屼换鍔D: {}, 浣跨敤榛樿鍊�0", task.getTaskId(), e);
+ transferDistance = "0";
+ }
+ }
+ params.put("ServiceOrdTraDistance", transferDistance);
params.put("OrderLevel", "0"); // 鏌ョ湅绛夌骇
params.put("ServiceOrdDepartureType", "1"); // 棰勭害绫诲瀷
params.put("ConditionLevel", "0"); // 鐥呴噸绾у埆
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java
index 7bdf7ab..4bf8466 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java
@@ -6,6 +6,7 @@
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysTaskEmergency;
import com.ruoyi.system.domain.VehicleInfo;
+import com.ruoyi.system.domain.enums.TaskStatus;
import com.ruoyi.system.domain.vo.TaskCreateVO;
import com.ruoyi.system.domain.vo.TaskUpdateVO;
import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
@@ -17,6 +18,7 @@
import com.ruoyi.system.mapper.VehicleInfoMapper;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.IWechatTaskNotifyService;
+import com.ruoyi.system.utils.TaskStatusConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
@@ -198,6 +200,13 @@
}
}
+ /**
+ * 鏇存柊鍗曚釜杞繍鍗�
+ * @param serviceOrdID
+ * @param dispatchOrdID
+ * @param order
+ * @return
+ */
private boolean updateTransferOrder(String serviceOrdID, String dispatchOrdID, Map<String, Object> order){
log.info("寮�濮嬪悓姝ュ崟涓浆杩愬崟: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
String sysTaskCode="";
@@ -209,13 +218,11 @@
}
// 鏋勯�燭askCreateVO瀵硅薄
TaskCreateVO createTaskVo = buildCreateTaskVo(serviceOrdID, dispatchOrdID, order);
-
- sysTaskCode = createTaskVo.getTaskCode();
if (createTaskVo == null) {
log.error("鏋勯�燭askCreateVO澶辫触: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
return false;
}
-
+ sysTaskCode = createTaskVo.getTaskCode();
// 璁板綍鍒涘缓鐨勪换鍔′俊鎭�
log.debug("鍑嗗鍒涘缓浠诲姟: ServiceOrdID={}, DispatchOrdID={}, 鎮h�呭鍚�={}, 杞嚭鍖婚櫌={}, 杞叆鍖婚櫌={}",
serviceOrdID, dispatchOrdID,
@@ -230,15 +237,26 @@
String serviceOrdClass = getStringValue(order,"ServiceOrdClass");
String serviceOrdNo = getStringValue(order,"ServiceOrdNo");
- Integer oauserId=getIntegerValue(order,"ServiceOrd_NS_ID");
+ Integer oauserId=getIntegerValue(order,"ServiceOrd_CC_ID");
+ if(oauserId==null){
+ oauserId=getIntegerValue(order,"ServiceOrd_NS_ID");
+ }
+ if(oauserId==null || oauserId==0){
+ log.error("鍒涘缓浠诲姟鏃讹紝鑾峰彇鍒涘缓浜轰俊鎭け璐ワ紝serviceOrdID={}, DispatchOrdID={} ServiceOrd_NS_ID={},ServiceOrd_CC_ID={}", serviceOrdID, dispatchOrdID, getIntegerValue(order,"ServiceOrd_NS_ID"),getIntegerValue(order,"ServiceOrd_CC_ID"));
+ return false;
+ }
SysUser sysUser=sysUserService.selectUserByOaUserId(oauserId);
Long taskCreatorId=sysUser==null?null:sysUser.getUserId();
String createUserName=sysUser==null?"system":sysUser.getUserName();
+ if(taskCreatorId==null || createUserName==null){
+ log.error("鍒涘缓浠诲姟鏃讹紝鑾峰彇鍒涘缓浜轰俊鎭け璐ワ紝serviceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
+ return false;
+ }
SysDept dept=sysDeptService.selectDeptByServiceClass(serviceOrdClass);
Long deptId=dept==null?null:dept.getDeptId();
TaskUpdateVO updateTaskVo = new TaskUpdateVO();
BeanUtils.copyProperties(createTaskVo, updateTaskVo);
-
+ log.info("寮�濮嬩繚瀛樿浆杩愪换鍔�,serviceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
int result = sysTaskService.updateTask(updateTaskVo,serviceOrdID,dispatchOrdID, serviceOrdNo, taskCreatorId,createUserName, deptId, ServiceOrd_CC_Time, ServiceOrd_CC_Time);
@@ -300,11 +318,19 @@
* 鍒涘缓浜篒D
*/
Integer oauserId=getIntegerValue(order,"ServiceOrd_CC_ID");
+ if(oauserId==null || oauserId==0) {
+ oauserId=getIntegerValue(order,"ServiceOrd_NS_ID");
+ }
SysUser sysUser=sysUserService.selectUserByOaUserId(oauserId);
- Long taskCreatorId=sysUser==null?null:sysUser.getUserId();
- String createUserName=sysUser==null?"system":sysUser.getUserName();
+ if(sysUser==null){
+ log.error("鍒涘缓浠诲姟鏃讹紝鑾峰彇鍒涘缓浜轰俊鎭け璐ワ紝serviceOrdID={}, DispatchOrdID={} ServiceOrd_CC_ID:{},ServiceOrd_NS_ID:{}", serviceOrdID, dispatchOrdID, getIntegerValue(order,"ServiceOrd_CC_ID"),getIntegerValue(order,"ServiceOrd_NS_ID"));
+ return false;
+ }
+ Long taskCreatorId= sysUser.getUserId();
+ String createUserName= sysUser.getUserName();
SysDept dept=sysDeptService.selectDeptByServiceClass(serviceOrdClass);
Long deptId=dept==null?null:dept.getDeptId();
+
int result = sysTaskService.insertTask(createTaskVo,serviceOrdID,dispatchOrdID, serviceOrdNo, taskCreatorId,createUserName, deptId, ServiceOrd_CC_Time, ServiceOrd_CC_Time);
@@ -394,7 +420,7 @@
*/
@Override
public TaskCreateVO buildCreateTaskVo(String serviceOrdID, String dispatchOrdID, Map<String, Object> order) {
- log.info("鏋勯�燭askCreateVO: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
+// log.info("鏋勯�燭askCreateVO: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
try {
// 妫�鏌ュ弬鏁版湁鏁堟��
@@ -408,11 +434,11 @@
return null;
}
String serviceOrdClass = getStringValue(order, "ServiceOrdClass");
- //TODO
+
TaskCreateVO createTaskVo = new TaskCreateVO();
String serviceOrdCode=this.getServiceOrdCode(getDateValue(order, "ServiceOrd_CC_Time"),serviceOrdClass,getStringValue(order, "ServiceOrdNo"));
createTaskVo.setTaskCode(serviceOrdCode);
- log.info("鏋勯�燭askCreateVO: ServiceOrdID={}, DispatchOrdID={},taskCode:{}", serviceOrdID, dispatchOrdID,serviceOrdCode);
+// log.info("鏋勯�燭askCreateVO: ServiceOrdID={}, DispatchOrdID={},taskCode:{}", serviceOrdID, dispatchOrdID,serviceOrdCode);
// 璁剧疆鍩烘湰淇℃伅
createTaskVo.setTaskType("EMERGENCY_TRANSFER"); // 鎬ユ晳杞繍浠诲姟
@@ -544,7 +570,8 @@
String carLicense = legacyTransferSyncMapper.selectCarLicenseByCarID(carID);
if (StringUtils.isNotEmpty(carLicense)) {
// 鏍规嵁杞︾墝鍙锋煡璇㈡柊绯荤粺涓殑杞﹁締ID
- log.debug("杞﹁締杞︾墝鍙�: {}", carLicense);
+ log.info("杞繍浠诲姟,ServiceOrdID:{},杞﹁締杞︾墝:{}",serviceOrdID,carLicense);
+// log.debug("杞﹁締杞︾墝鍙�: {}", carLicense);
// 棣栧厛灏濊瘯閫氳繃VehicleInfoMapper鏌ヨ杞﹁締淇℃伅
try {
@@ -556,7 +583,7 @@
List<Long> vehicleIds = new ArrayList<>();
vehicleIds.add(vehicleInfo.getVehicleId());
createTaskVo.setVehicleIds(vehicleIds);
- log.debug("閫氳繃car_id鎵惧埌杞﹁締淇℃伅: vehicle_id={}, vehicle_no={}", vehicleInfo.getVehicleId(), vehicleInfo.getVehicleNo());
+// log.debug("閫氳繃car_id鎵惧埌杞﹁締淇℃伅: vehicle_id={}, vehicle_no={}", vehicleInfo.getVehicleId(), vehicleInfo.getVehicleNo());
} else {
// 濡傛灉閫氳繃car_id鎵句笉鍒帮紝灏濊瘯閫氳繃杞︾墝鍙锋煡璇�
vehicleInfo = vehicleInfoMapper.selectVehicleInfoByVehicleNo(carLicense);
@@ -564,9 +591,9 @@
List<Long> vehicleIds = new ArrayList<>();
vehicleIds.add(vehicleInfo.getVehicleId());
createTaskVo.setVehicleIds(vehicleIds);
- log.debug("閫氳繃杞︾墝鍙锋壘鍒拌溅杈嗕俊鎭�: vehicle_id={}, vehicle_no={}", vehicleInfo.getVehicleId(), vehicleInfo.getVehicleNo());
+ log.debug("杞繍浠诲姟,ServiceOrdID:{} 閫氳繃杞︾墝鍙锋壘鍒拌溅杈嗕俊鎭�: vehicle_id={}, vehicle_no={}",serviceOrdID, vehicleInfo.getVehicleId(), vehicleInfo.getVehicleNo());
} else {
- log.warn("鏈壘鍒板搴旂殑杞﹁締淇℃伅: car_id={}, vehicle_no={}", carID, carLicense);
+ log.warn("杞繍浠诲姟,ServiceOrdID:{} 鏈壘鍒板搴旂殑杞﹁締淇℃伅: car_id={}, vehicle_no={}",serviceOrdID, carID, carLicense);
}
}
} catch (NumberFormatException e) {
@@ -585,6 +612,7 @@
}
}
+
// 璁剧疆鍏朵粬淇℃伅
createTaskVo.setTaskDescription("浠庢棫绯荤粺鍚屾鐨勮浆杩愬崟");
@@ -635,8 +663,15 @@
}
createTaskVo.setDiseaseIds(diseaseIds);
}
+
+ Integer dispatchOrdStatus = getIntegerValue(order, "DispatchOrdStatus");
+ TaskStatus status= TaskStatusConverter.convertFromLegacyStatus(dispatchOrdStatus);
+ if(status!=null) {
+ createTaskVo.setTaskStatus(status.getCode());
+ }
+
- log.info("TaskCreateVO鏋勯�犲畬鎴�: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
+// log.info("TaskCreateVO鏋勯�犲畬鎴�: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
return createTaskVo;
} catch (Exception e) {
@@ -652,6 +687,7 @@
* @return 鎵ц浜轰俊鎭垪琛�
*/
private List<TaskCreateVO.AssigneeInfo> queryAssignees(String dispatchOrdID) {
+ long startTime = System.currentTimeMillis();
try {
// 妫�鏌ュ弬鏁版湁鏁堟��
if (StringUtils.isEmpty(dispatchOrdID)) {
@@ -659,8 +695,24 @@
return new ArrayList<>();
}
- // 浠嶴QL Server鏌ヨ鎵ц浜轰俊鎭�
- List<Map<String, Object>> assigneeList = legacyTransferSyncMapper.selectAssigneesByDispatchOrdID(dispatchOrdID);
+ // 灏哠tring杞崲涓篖ong锛岄伩鍏嶆暟鎹簱绫诲瀷涓嶅尮閰嶅鑷寸殑鎬ц兘闂
+ Long dispatchOrdIdLong;
+ try {
+ dispatchOrdIdLong = Long.valueOf(dispatchOrdID);
+ } catch (NumberFormatException e) {
+ log.error("璋冨害鍗旾D鏍煎紡涓嶆纭�: {}", dispatchOrdID, e);
+ return new ArrayList<>();
+ }
+
+ // 浠嶴QL Server鏌ヨ鎵ц浜轰俊鎭紙浣跨敤Long绫诲瀷锛屽尮閰岯IGINT瀛楁锛�
+ List<Map<String, Object>> assigneeList = legacyTransferSyncMapper.selectAssigneesByDispatchOrdID(dispatchOrdIdLong);
+ long queryTime = System.currentTimeMillis() - startTime;
+
+ // 璁板綍鎱㈡煡璇紙瓒呰繃500ms锛�
+ if (queryTime > 500) {
+ log.warn("鏌ヨ鎵ц浜轰俊鎭�楁椂杩囬暱: {}ms, 璋冨害鍗旾D: {}, 寤鸿鍦� DispatchOrd_Entourage 琛ㄧ殑 DispatchOrdIDDt 瀛楁涓婂垱寤虹储寮�",
+ queryTime, dispatchOrdID);
+ }
// 杞崲涓篢askCreateVO.AssigneeInfo瀵硅薄
List<TaskCreateVO.AssigneeInfo> assignees = new ArrayList<>();
@@ -702,10 +754,11 @@
}
}
- log.info("鏌ヨ鍒皗}涓墽琛屼汉锛岃皟搴﹀崟ID: {}", assignees.size(), dispatchOrdID);
+ log.debug("鏌ヨ鍒皗}涓墽琛屼汉锛岃皟搴﹀崟ID: {}, 鑰楁椂: {}ms", assignees.size(), dispatchOrdID, System.currentTimeMillis() - startTime);
return assignees;
} catch (Exception e) {
- log.error("鏌ヨ鎵ц浜轰俊鎭紓甯革紝璋冨害鍗旾D: {}", dispatchOrdID, e);
+ long totalTime = System.currentTimeMillis() - startTime;
+ log.error("鏌ヨ鎵ц浜轰俊鎭紓甯革紝璋冨害鍗旾D: {}, 鑰楁椂: {}ms", dispatchOrdID, totalTime, e);
return new ArrayList<>(); // 杩斿洖绌哄垪琛ㄨ�屼笉鏄痭ull
}
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifyChannelConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifyChannelConfigServiceImpl.java
new file mode 100644
index 0000000..942d774
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifyChannelConfigServiceImpl.java
@@ -0,0 +1,104 @@
+package com.ruoyi.system.service.impl;
+
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.system.domain.NotifyChannelConfig;
+import com.ruoyi.system.mapper.NotifyChannelConfigMapper;
+import com.ruoyi.system.service.INotifyChannelConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 閫氱煡娓犻亾閰嶇疆Service涓氬姟灞傚鐞�
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+@Service
+public class NotifyChannelConfigServiceImpl implements INotifyChannelConfigService {
+ @Autowired
+ private NotifyChannelConfigMapper notifyChannelConfigMapper;
+
+ /**
+ * 鏌ヨ閫氱煡娓犻亾閰嶇疆
+ *
+ * @param id 涓婚敭ID
+ * @return 閫氱煡娓犻亾閰嶇疆
+ */
+ @Override
+ public NotifyChannelConfig selectNotifyChannelConfigById(Long id) {
+ return notifyChannelConfigMapper.selectNotifyChannelConfigById(id);
+ }
+
+ /**
+ * 鏌ヨ閫氱煡娓犻亾閰嶇疆鍒楄〃
+ *
+ * @param notifyChannelConfig 鏌ヨ鏉′欢
+ * @return 閫氱煡娓犻亾閰嶇疆鍒楄〃
+ */
+ @Override
+ public List<NotifyChannelConfig> selectNotifyChannelConfigList(NotifyChannelConfig notifyChannelConfig) {
+ return notifyChannelConfigMapper.selectNotifyChannelConfigList(notifyChannelConfig);
+ }
+
+ /**
+ * 鏌ヨ鎸囧畾閫氱煡绫诲瀷鍚敤鐨勬笭閬撻厤缃�
+ * 鎸変紭鍏堢骇闄嶅簭鎺掑垪
+ *
+ * @param notifyType 閫氱煡绫诲瀷
+ * @return 鍚敤鐨勬笭閬撻厤缃垪琛�
+ */
+ @Override
+ public List<NotifyChannelConfig> selectEnabledChannelsByType(String notifyType) {
+ return notifyChannelConfigMapper.selectEnabledChannelsByType(notifyType);
+ }
+
+ /**
+ * 妫�鏌ユ寚瀹氭笭閬撴槸鍚﹀惎鐢�
+ *
+ * @param notifyType 閫氱煡绫诲瀷
+ * @param channel 娓犻亾
+ * @return 閰嶇疆淇℃伅
+ */
+ @Override
+ public NotifyChannelConfig selectByTypeAndChannel(String notifyType, String channel) {
+ return notifyChannelConfigMapper.selectByTypeAndChannel(notifyType, channel);
+ }
+
+ /**
+ * 鏂板閫氱煡娓犻亾閰嶇疆
+ *
+ * @param notifyChannelConfig 閫氱煡娓犻亾閰嶇疆
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertNotifyChannelConfig(NotifyChannelConfig notifyChannelConfig) {
+ notifyChannelConfig.setCreateTime(DateUtils.getNowDate());
+ notifyChannelConfig.setUpdateTime(DateUtils.getNowDate());
+ return notifyChannelConfigMapper.insertNotifyChannelConfig(notifyChannelConfig);
+ }
+
+ /**
+ * 淇敼閫氱煡娓犻亾閰嶇疆
+ *
+ * @param notifyChannelConfig 閫氱煡娓犻亾閰嶇疆
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateNotifyChannelConfig(NotifyChannelConfig notifyChannelConfig) {
+ notifyChannelConfig.setUpdateTime(DateUtils.getNowDate());
+ return notifyChannelConfigMapper.updateNotifyChannelConfig(notifyChannelConfig);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎閫氱煡娓犻亾閰嶇疆
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑涓婚敭ID闆嗗悎
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteNotifyChannelConfigByIds(Long[] ids) {
+ return notifyChannelConfigMapper.deleteNotifyChannelConfigByIds(ids);
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifyDispatchServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifyDispatchServiceImpl.java
new file mode 100644
index 0000000..a918e86
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifyDispatchServiceImpl.java
@@ -0,0 +1,321 @@
+package com.ruoyi.system.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.*;
+import com.ruoyi.system.mapper.NotifyChannelConfigMapper;
+import com.ruoyi.system.mapper.SysMessageMapper;
+import com.ruoyi.system.service.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * 閫氱煡鍒嗗彂鏈嶅姟瀹炵幇绫�
+ * 璐熻矗鏍规嵁閰嶇疆鍐冲畾鍙戦�佹笭閬撳苟鎵ц鍒嗗彂
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+@Service
+public class NotifyDispatchServiceImpl implements INotifyDispatchService {
+
+ private static final Logger log = LoggerFactory.getLogger(NotifyDispatchServiceImpl.class);
+
+ @Autowired
+ private NotifyChannelConfigMapper channelConfigMapper;
+
+ @Autowired
+ private INotifyTaskService notifyTaskService;
+
+ @Autowired
+ private INotifySendLogService notifySendLogService;
+
+ @Autowired
+ private SysMessageMapper sysMessageMapper;
+
+ @Autowired
+ private IWechatTaskNotifyService wechatTaskNotifyService;
+
+ @Autowired
+ private ISmsService smsService;
+
+ /**
+ * 鑾峰彇鎸囧畾閫氱煡绫诲瀷鍚敤鐨勬笭閬撳垪琛�
+ */
+ @Override
+ public List<NotifyChannelConfig> getEnabledChannels(String notifyType) {
+ if (StringUtils.isEmpty(notifyType)) {
+ return Collections.emptyList();
+ }
+ return channelConfigMapper.selectEnabledChannelsByType(notifyType);
+ }
+
+ /**
+ * 妫�鏌ユ寚瀹氭笭閬撴槸鍚﹀惎鐢�
+ */
+ @Override
+ public boolean isChannelEnabled(String notifyType, String channel) {
+ NotifyChannelConfig config = channelConfigMapper.selectByTypeAndChannel(notifyType, channel);
+ return config != null && NotifyChannelConfig.ENABLED_YES.equals(config.getEnabled());
+ }
+
+ /**
+ * 鍒嗗彂閫氱煡浠诲姟
+ */
+ @Override
+ public int dispatchNotify(NotifyTask notifyTask) {
+ if (notifyTask == null) {
+ return 0;
+ }
+
+ log.info("寮�濮嬪垎鍙戦�氱煡浠诲姟锛宨d={}, taskId={}, userId={}, notifyType={}",
+ notifyTask.getId(), notifyTask.getTaskId(), notifyTask.getUserId(), notifyTask.getNotifyType());
+
+ // 鏇存柊鐘舵�佷负澶勭悊涓�
+ notifyTaskService.markProcessing(notifyTask.getId());
+
+ // 鑾峰彇鍚敤鐨勬笭閬�
+ List<NotifyChannelConfig> channels = getEnabledChannels(notifyTask.getNotifyType());
+ if (channels.isEmpty()) {
+ log.warn("娌℃湁鍚敤鐨勬笭閬擄紝notifyType={}", notifyTask.getNotifyType());
+ notifyTaskService.markCompleted(notifyTask.getId());
+ return 0;
+ }
+
+ int successCount = 0;
+ StringBuilder errorMsgs = new StringBuilder();
+
+ // 鎸変紭鍏堢骇渚濇鍙戦�佸悇娓犻亾
+ for (NotifyChannelConfig channelConfig : channels) {
+ String channel = channelConfig.getChannel();
+ boolean success = false;
+ String errorMsg = null;
+
+ try {
+ switch (channel) {
+ case NotifyChannelConfig.CHANNEL_SITE_MSG:
+ success = sendSiteMessage(notifyTask);
+ break;
+ case NotifyChannelConfig.CHANNEL_WECHAT:
+ success = sendWechatMessage(notifyTask);
+ break;
+ case NotifyChannelConfig.CHANNEL_SMS:
+ success = sendSmsMessage(notifyTask);
+ break;
+ default:
+ log.warn("涓嶆敮鎸佺殑娓犻亾绫诲瀷锛歿}", channel);
+ continue;
+ }
+ } catch (Exception e) {
+ errorMsg = e.getMessage();
+ log.error("鍙戦�亄}娑堟伅澶辫触锛宯otifyTaskId={}", channel, notifyTask.getId(), e);
+ }
+
+ // 璁板綍鍙戦�佹棩蹇�
+ recordSendLog(notifyTask, channel, success, errorMsg);
+
+ if (success) {
+ successCount++;
+ log.info("{}娓犻亾鍙戦�佹垚鍔燂紝notifyTaskId={}", channel, notifyTask.getId());
+ } else {
+ if (errorMsgs.length() > 0) {
+ errorMsgs.append("; ");
+ }
+ errorMsgs.append(channel).append(":").append(errorMsg != null ? errorMsg : "鍙戦�佸け璐�");
+ }
+ }
+
+ // 鏇存柊浠诲姟鐘舵��
+ if (successCount > 0) {
+ notifyTaskService.markCompleted(notifyTask.getId());
+ } else {
+ notifyTaskService.incrementRetryCount(notifyTask.getId());
+ // 妫�鏌ユ槸鍚﹁秴杩囨渶澶ч噸璇曟鏁�
+ NotifyTask updated = notifyTaskService.selectNotifyTaskById(notifyTask.getId());
+ if (updated.getRetryCount() >= updated.getMaxRetry()) {
+ notifyTaskService.markFailed(notifyTask.getId(), errorMsgs.toString());
+ } else {
+ // 閲嶇疆涓哄緟澶勭悊鐘舵�侊紝绛夊緟涓嬫閲嶈瘯
+ notifyTaskService.updateNotifyTask(createStatusUpdate(notifyTask.getId(), NotifyTask.STATUS_PENDING));
+ }
+ }
+
+ log.info("閫氱煡浠诲姟鍒嗗彂瀹屾垚锛宨d={}, 鎴愬姛娓犻亾鏁�={}", notifyTask.getId(), successCount);
+ return successCount;
+ }
+
+ /**
+ * 鍒涘缓鐘舵�佹洿鏂板璞�
+ */
+ private NotifyTask createStatusUpdate(Long id, String status) {
+ NotifyTask update = new NotifyTask();
+ update.setId(id);
+ update.setStatus(status);
+ return update;
+ }
+
+ /**
+ * 璁板綍鍙戦�佹棩蹇�
+ */
+ private void recordSendLog(NotifyTask notifyTask, String channel, boolean success, String errorMsg) {
+ try {
+ NotifySendLog sendLog = new NotifySendLog();
+ sendLog.setNotifyTaskId(notifyTask.getId());
+ sendLog.setTaskId(notifyTask.getTaskId());
+ sendLog.setUserId(notifyTask.getUserId());
+ sendLog.setUserName(notifyTask.getUserName());
+ sendLog.setNotifyType(notifyTask.getNotifyType());
+ sendLog.setChannel(channel);
+ sendLog.setSendStatus(success ? NotifySendLog.SEND_STATUS_SUCCESS : NotifySendLog.SEND_STATUS_FAILED);
+ sendLog.setSendTime(DateUtils.getNowDate());
+ sendLog.setResponseMsg(errorMsg);
+
+ notifySendLogService.insertNotifySendLog(sendLog);
+ } catch (Exception e) {
+ log.error("璁板綍鍙戦�佹棩蹇楀け璐�", e);
+ }
+ }
+
+ /**
+ * 鎵归噺鍒嗗彂閫氱煡浠诲姟
+ */
+ @Override
+ public int dispatchNotifies(List<NotifyTask> notifyTasks) {
+ if (notifyTasks == null || notifyTasks.isEmpty()) {
+ return 0;
+ }
+
+ int successCount = 0;
+ for (NotifyTask notifyTask : notifyTasks) {
+ int channelCount = dispatchNotify(notifyTask);
+ if (channelCount > 0) {
+ successCount++;
+ }
+ }
+ return successCount;
+ }
+
+ /**
+ * 澶勭悊寰呭彂閫佺殑閫氱煡浠诲姟
+ */
+ @Override
+ public int processPendingNotifies(int limit) {
+ List<NotifyTask> pendingTasks = notifyTaskService.selectPendingNotifyTasks(limit);
+ if (pendingTasks.isEmpty()) {
+ return 0;
+ }
+
+ log.info("寮�濮嬪鐞嗗緟鍙戦�侀�氱煡浠诲姟锛屾暟閲�={}", pendingTasks.size());
+ return dispatchNotifies(pendingTasks);
+ }
+
+ /**
+ * 鍙戦�佺珯鍐呮秷鎭�
+ */
+ @Override
+ public boolean sendSiteMessage(NotifyTask notifyTask) {
+ try {
+ SysMessage message = new SysMessage();
+ message.setMessageType(getMessageType(notifyTask.getNotifyType()));
+ message.setMessageTitle(notifyTask.getTitle());
+ message.setMessageContent(notifyTask.getContent());
+ message.setTaskId(notifyTask.getTaskId());
+ message.setTaskCode(notifyTask.getTaskCode());
+ message.setReceiverId(notifyTask.getUserId());
+ message.setReceiverName(notifyTask.getUserName());
+ message.setSenderId(0L);
+ message.setSenderName("绯荤粺");
+ message.setIsRead("0");
+ message.setCreateTime(DateUtils.getNowDate());
+ message.setDelFlag("0");
+
+ sysMessageMapper.insertSysMessage(message);
+ log.info("绔欏唴娑堟伅鍙戦�佹垚鍔燂紝messageId={}, userId={}", message.getMessageId(), notifyTask.getUserId());
+ return true;
+ } catch (Exception e) {
+ log.error("绔欏唴娑堟伅鍙戦�佸け璐ワ紝userId={}", notifyTask.getUserId(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 鏍规嵁閫氱煡绫诲瀷鑾峰彇娑堟伅绫诲瀷
+ */
+ private String getMessageType(String notifyType) {
+ switch (notifyType) {
+ case NotifyTask.NOTIFY_TYPE_TASK_ASSIGN:
+ return "PUSH";
+ case NotifyTask.NOTIFY_TYPE_STATUS_CHANGE:
+ return "STATUS";
+ case NotifyTask.NOTIFY_TYPE_TASK_CREATE:
+ return "CREATE";
+ default:
+ return "SYSTEM";
+ }
+ }
+
+ /**
+ * 鍙戦�佸井淇¤闃呮秷鎭�
+ */
+ @Override
+ public boolean sendWechatMessage(NotifyTask notifyTask) {
+ try {
+ // 璋冪敤寰俊閫氱煡鏈嶅姟
+ int result = wechatTaskNotifyService.sendTaskNotifyMessage(
+ notifyTask.getTaskId(),
+ Collections.singletonList(notifyTask.getUserId()),
+ null // 涓嶆帓闄や换浣曠敤鎴�
+ );
+
+ if (result > 0) {
+ log.info("寰俊璁㈤槄娑堟伅鍙戦�佹垚鍔燂紝taskId={}, userId={}", notifyTask.getTaskId(), notifyTask.getUserId());
+ return true;
+ } else {
+ log.warn("寰俊璁㈤槄娑堟伅鍙戦�佸け璐ワ紝taskId={}, userId={}", notifyTask.getTaskId(), notifyTask.getUserId());
+ return false;
+ }
+ } catch (Exception e) {
+ log.error("寰俊璁㈤槄娑堟伅鍙戦�佸紓甯革紝taskId={}, userId={}", notifyTask.getTaskId(), notifyTask.getUserId(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 鍙戦�佺煭淇℃秷鎭�
+ */
+ @Override
+ public boolean sendSmsMessage(NotifyTask notifyTask) {
+ try {
+ // 妫�鏌ョ煭淇℃湇鍔℃槸鍚﹀惎鐢�
+ if (!smsService.isEnabled()) {
+ log.info("鐭俊鏈嶅姟宸插叧闂紝璺宠繃鍙戦��");
+ return false;
+ }
+
+ String phone = notifyTask.getUserPhone();
+ if (StringUtils.isEmpty(phone)) {
+ log.warn("鐢ㄦ埛鎵嬫満鍙蜂负绌猴紝鏃犳硶鍙戦�佺煭淇★紝userId={}", notifyTask.getUserId());
+ return false;
+ }
+
+ // 鍙戦�佺煭淇�
+ boolean success = smsService.sendSms(phone, notifyTask.getContent());
+ if (success) {
+ log.info("鐭俊鍙戦�佹垚鍔燂紝phone={}, userId={}", phone, notifyTask.getUserId());
+ } else {
+ log.warn("鐭俊鍙戦�佸け璐ワ紝phone={}, userId={}", phone, notifyTask.getUserId());
+ }
+ return success;
+ } catch (Exception e) {
+ log.error("鐭俊鍙戦�佸紓甯革紝userId={}", notifyTask.getUserId(), e);
+ return false;
+ }
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifySendLogServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifySendLogServiceImpl.java
new file mode 100644
index 0000000..f671855
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifySendLogServiceImpl.java
@@ -0,0 +1,214 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.Date;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.system.domain.NotifySendLog;
+import com.ruoyi.system.mapper.NotifySendLogMapper;
+import com.ruoyi.system.service.INotifySendLogService;
+
+/**
+ * 閫氱煡鍙戦�佽褰曟湇鍔″疄鐜扮被
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+@Service
+public class NotifySendLogServiceImpl implements INotifySendLogService {
+
+ private static final Logger log = LoggerFactory.getLogger(NotifySendLogServiceImpl.class);
+
+ @Autowired
+ private NotifySendLogMapper notifySendLogMapper;
+
+ /**
+ * 鏌ヨ閫氱煡鍙戦�佽褰�
+ *
+ * @param id 閫氱煡鍙戦�佽褰曚富閿�
+ * @return 閫氱煡鍙戦�佽褰�
+ */
+ @Override
+ public NotifySendLog selectNotifySendLogById(Long id) {
+ return notifySendLogMapper.selectNotifySendLogById(id);
+ }
+
+ /**
+ * 鏌ヨ閫氱煡鍙戦�佽褰曞垪琛�
+ *
+ * @param notifySendLog 閫氱煡鍙戦�佽褰�
+ * @return 閫氱煡鍙戦�佽褰�
+ */
+ @Override
+ public List<NotifySendLog> selectNotifySendLogList(NotifySendLog notifySendLog) {
+ return notifySendLogMapper.selectNotifySendLogList(notifySendLog);
+ }
+
+ /**
+ * 妫�鏌ユ槸鍚﹀凡鍙戦�佽繃閫氱煡锛堥槻閲嶆鏌ワ級
+ *
+ * @param taskId 浠诲姟ID
+ * @param userId 鐢ㄦ埛ID
+ * @param notifyType 閫氱煡绫诲瀷
+ * @param channel 閫氱煡娓犻亾
+ * @return true=宸插彂閫佽繃, false=鏈彂閫佽繃
+ */
+ @Override
+ public boolean hasNotified(Long taskId, Long userId, String notifyType, String channel) {
+ int count = notifySendLogMapper.checkNotifySendLogExists(taskId, userId, notifyType, channel);
+ return count > 0;
+ }
+
+ /**
+ * 灏濊瘯鍒涘缓鍙戦�佽褰曪紙闃查噸锛屽鏋滃凡瀛樺湪鍒欒繑鍥瀗ull锛�
+ * 浣跨敤鏁版嵁搴撳敮涓�绱㈠紩淇濊瘉闃查噸
+ *
+ * @param taskId 浠诲姟ID
+ * @param userId 鐢ㄦ埛ID
+ * @param userName 鐢ㄦ埛濮撳悕
+ * @param notifyType 閫氱煡绫诲瀷
+ * @param channel 閫氱煡娓犻亾
+ * @return 鍒涘缓鐨勮褰曪紝濡傛灉宸插瓨鍦ㄥ垯杩斿洖null
+ */
+ @Override
+ @Transactional
+ public NotifySendLog tryCreateSendLog(Long taskId, Long userId, String userName,
+ String notifyType, String channel) {
+ // 鍏堟鏌ユ槸鍚﹀凡瀛樺湪
+ if (hasNotified(taskId, userId, notifyType, channel)) {
+ log.debug("閫氱煡璁板綍宸插瓨鍦紝璺宠繃鍒涘缓锛宼askId={}, userId={}, notifyType={}, channel={}",
+ taskId, userId, notifyType, channel);
+ return null;
+ }
+
+ try {
+ // 鍒涘缓鏂拌褰�
+ NotifySendLog sendLog = new NotifySendLog();
+ sendLog.setTaskId(taskId);
+ sendLog.setUserId(userId);
+ sendLog.setUserName(userName);
+ sendLog.setNotifyType(notifyType);
+ sendLog.setChannel(channel);
+ sendLog.setSendStatus(NotifySendLog.SEND_STATUS_PENDING);
+ sendLog.setRetryCount(0);
+ sendLog.setCreateTime(DateUtils.getNowDate());
+ sendLog.setCreateBy("system");
+
+ int result = notifySendLogMapper.insertNotifySendLog(sendLog);
+ if (result > 0) {
+ log.info("鍒涘缓閫氱煡鍙戦�佽褰曟垚鍔燂紝id={}, taskId={}, userId={}, notifyType={}, channel={}",
+ sendLog.getId(), taskId, userId, notifyType, channel);
+ return sendLog;
+ }
+ } catch (Exception e) {
+ // 鍙兘鏄苟鍙戞彃鍏ュ鑷寸殑鍞竴绱㈠紩鍐茬獊锛岃涓哄凡瀛樺湪
+ log.warn("鍒涘缓閫氱煡鍙戦�佽褰曞け璐ワ紙鍙兘鏄苟鍙戦噸澶嶏級锛宼askId={}, userId={}, notifyType={}, channel={}, error={}",
+ taskId, userId, notifyType, channel, e.getMessage());
+ }
+
+ return null;
+ }
+
+ /**
+ * 鏇存柊鍙戦�佺姸鎬佷负鎴愬姛
+ *
+ * @param id 璁板綍ID
+ * @param result 鍙戦�佺粨鏋滀俊鎭�
+ */
+ @Override
+ public void markSendSuccess(Long id, String result) {
+ if (id == null) {
+ return;
+ }
+ try {
+ notifySendLogMapper.updateSendStatus(id, NotifySendLog.SEND_STATUS_SUCCESS, result);
+ log.debug("鏇存柊閫氱煡鍙戦�佺姸鎬佷负鎴愬姛锛宨d={}", id);
+ } catch (Exception e) {
+ log.error("鏇存柊閫氱煡鍙戦�佺姸鎬佸け璐ワ紝id={}", id, e);
+ }
+ }
+
+ /**
+ * 鏇存柊鍙戦�佺姸鎬佷负澶辫触
+ *
+ * @param id 璁板綍ID
+ * @param errorMsg 閿欒淇℃伅
+ */
+ @Override
+ public void markSendFailed(Long id, String errorMsg) {
+ if (id == null) {
+ return;
+ }
+ try {
+ // 闄愬埗閿欒淇℃伅闀垮害
+ if (errorMsg != null && errorMsg.length() > 500) {
+ errorMsg = errorMsg.substring(0, 500);
+ }
+ notifySendLogMapper.updateSendStatus(id, NotifySendLog.SEND_STATUS_FAILED, errorMsg);
+ log.debug("鏇存柊閫氱煡鍙戦�佺姸鎬佷负澶辫触锛宨d={}, error={}", id, errorMsg);
+ } catch (Exception e) {
+ log.error("鏇存柊閫氱煡鍙戦�佺姸鎬佸け璐ワ紝id={}", id, e);
+ }
+ }
+
+ /**
+ * 鏂板閫氱煡鍙戦�佽褰�
+ *
+ * @param notifySendLog 閫氱煡鍙戦�佽褰�
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertNotifySendLog(NotifySendLog notifySendLog) {
+ notifySendLog.setCreateTime(DateUtils.getNowDate());
+ return notifySendLogMapper.insertNotifySendLog(notifySendLog);
+ }
+
+ /**
+ * 淇敼閫氱煡鍙戦�佽褰�
+ *
+ * @param notifySendLog 閫氱煡鍙戦�佽褰�
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateNotifySendLog(NotifySendLog notifySendLog) {
+ notifySendLog.setUpdateTime(DateUtils.getNowDate());
+ return notifySendLogMapper.updateNotifySendLog(notifySendLog);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎閫氱煡鍙戦�佽褰�
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑閫氱煡鍙戦�佽褰曚富閿�
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteNotifySendLogByIds(Long[] ids) {
+ return notifySendLogMapper.deleteNotifySendLogByIds(ids);
+ }
+
+ /**
+ * 鍒犻櫎閫氱煡鍙戦�佽褰曚俊鎭�
+ *
+ * @param id 閫氱煡鍙戦�佽褰曚富閿�
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteNotifySendLogById(Long id) {
+ return notifySendLogMapper.deleteNotifySendLogById(id);
+ }
+
+ /**
+ * 鏌ヨ寰呴噸璇曠殑澶辫触璁板綍
+ *
+ * @param maxRetryCount 鏈�澶ч噸璇曟鏁�
+ * @return 澶辫触璁板綍鍒楄〃
+ */
+ @Override
+ public List<NotifySendLog> selectFailedNotifySendLogs(Integer maxRetryCount) {
+ return notifySendLogMapper.selectFailedNotifySendLogs(maxRetryCount);
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifyTaskServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifyTaskServiceImpl.java
new file mode 100644
index 0000000..98e0ad3
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/NotifyTaskServiceImpl.java
@@ -0,0 +1,166 @@
+package com.ruoyi.system.service.impl;
+
+import com.ruoyi.system.domain.NotifyTask;
+import com.ruoyi.system.mapper.NotifyTaskMapper;
+import com.ruoyi.system.service.INotifyTaskService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 閫氱煡浠诲姟鏈嶅姟瀹炵幇绫�
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+@Service
+public class NotifyTaskServiceImpl implements INotifyTaskService {
+
+ private static final Logger log = LoggerFactory.getLogger(NotifyTaskServiceImpl.class);
+
+ @Autowired
+ private NotifyTaskMapper notifyTaskMapper;
+
+ /**
+ * 鏌ヨ閫氱煡浠诲姟
+ */
+ @Override
+ public NotifyTask selectNotifyTaskById(Long id) {
+ return notifyTaskMapper.selectNotifyTaskById(id);
+ }
+
+ /**
+ * 鏌ヨ閫氱煡浠诲姟鍒楄〃
+ */
+ @Override
+ public List<NotifyTask> selectNotifyTaskList(NotifyTask notifyTask) {
+ return notifyTaskMapper.selectNotifyTaskList(notifyTask);
+ }
+
+ /**
+ * 鏌ヨ寰呭鐞嗙殑閫氱煡浠诲姟
+ */
+ @Override
+ public List<NotifyTask> selectPendingNotifyTasks(int limit) {
+ return notifyTaskMapper.selectPendingNotifyTasks(limit);
+ }
+
+ /**
+ * 妫�鏌ラ�氱煡浠诲姟鏄惁宸插瓨鍦�
+ */
+ @Override
+ public boolean existsNotifyTask(Long taskId, Long userId, String notifyType) {
+ int count = notifyTaskMapper.countByTaskUserType(taskId, userId, notifyType);
+ return count > 0;
+ }
+
+ /**
+ * 鍒涘缓閫氱煡浠诲姟锛堝甫闃查噸锛�
+ */
+ @Override
+ public NotifyTask createNotifyTask(NotifyTask notifyTask) {
+ // 妫�鏌ユ槸鍚﹀凡瀛樺湪
+ if (existsNotifyTask(notifyTask.getTaskId(), notifyTask.getUserId(), notifyTask.getNotifyType())) {
+ log.info("閫氱煡浠诲姟宸插瓨鍦紝璺宠繃鍒涘缓锛宼askId={}, userId={}, notifyType={}",
+ notifyTask.getTaskId(), notifyTask.getUserId(), notifyTask.getNotifyType());
+ return null;
+ }
+
+ // 璁剧疆榛樿鍊�
+ if (notifyTask.getStatus() == null) {
+ notifyTask.setStatus(NotifyTask.STATUS_PENDING);
+ }
+ if (notifyTask.getRetryCount() == null) {
+ notifyTask.setRetryCount(0);
+ }
+ if (notifyTask.getMaxRetry() == null) {
+ notifyTask.setMaxRetry(3);
+ }
+
+ try {
+ notifyTaskMapper.insertNotifyTask(notifyTask);
+ log.info("鍒涘缓閫氱煡浠诲姟鎴愬姛锛宨d={}, taskId={}, userId={}, notifyType={}",
+ notifyTask.getId(), notifyTask.getTaskId(), notifyTask.getUserId(), notifyTask.getNotifyType());
+ return notifyTask;
+ } catch (Exception e) {
+ // 鍙兘鏄敮涓�绱㈠紩鍐茬獊锛堝苟鍙戞儏鍐碉級
+ log.warn("鍒涘缓閫氱煡浠诲姟澶辫触锛堝彲鑳藉苟鍙戝啿绐侊級锛宼askId={}, userId={}, notifyType={}",
+ notifyTask.getTaskId(), notifyTask.getUserId(), notifyTask.getNotifyType(), e);
+ return null;
+ }
+ }
+
+ /**
+ * 鎵归噺鍒涘缓閫氱煡浠诲姟
+ */
+ @Override
+ public int createNotifyTasks(List<NotifyTask> notifyTasks) {
+ int successCount = 0;
+ for (NotifyTask notifyTask : notifyTasks) {
+ NotifyTask created = createNotifyTask(notifyTask);
+ if (created != null) {
+ successCount++;
+ }
+ }
+ return successCount;
+ }
+
+ /**
+ * 淇敼閫氱煡浠诲姟
+ */
+ @Override
+ public int updateNotifyTask(NotifyTask notifyTask) {
+ return notifyTaskMapper.updateNotifyTask(notifyTask);
+ }
+
+ /**
+ * 鏇存柊閫氱煡浠诲姟鐘舵�佷负澶勭悊涓�
+ */
+ @Override
+ public int markProcessing(Long id) {
+ return notifyTaskMapper.updateNotifyTaskStatus(id, NotifyTask.STATUS_PROCESSING, null);
+ }
+
+ /**
+ * 鏇存柊閫氱煡浠诲姟鐘舵�佷负瀹屾垚
+ */
+ @Override
+ public int markCompleted(Long id) {
+ return notifyTaskMapper.updateNotifyTaskStatus(id, NotifyTask.STATUS_COMPLETED, null);
+ }
+
+ /**
+ * 鏇存柊閫氱煡浠诲姟鐘舵�佷负澶辫触
+ */
+ @Override
+ public int markFailed(Long id, String errorMsg) {
+ return notifyTaskMapper.updateNotifyTaskStatus(id, NotifyTask.STATUS_FAILED, errorMsg);
+ }
+
+ /**
+ * 澧炲姞閲嶈瘯娆℃暟
+ */
+ @Override
+ public int incrementRetryCount(Long id) {
+ return notifyTaskMapper.incrementRetryCount(id);
+ }
+
+ /**
+ * 鍒犻櫎閫氱煡浠诲姟
+ */
+ @Override
+ public int deleteNotifyTaskById(Long id) {
+ return notifyTaskMapper.deleteNotifyTaskById(id);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎閫氱煡浠诲姟
+ */
+ @Override
+ public int deleteNotifyTaskByIds(Long[] ids) {
+ return notifyTaskMapper.deleteNotifyTaskByIds(ids);
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentSyncServiceImpl.java
index ca8b487..67b86f2 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentSyncServiceImpl.java
@@ -115,14 +115,16 @@
PaidMoney paidMoney = new PaidMoney();
paidMoney.setPaidMoneyClass("FI"); // 榛樿FI
paidMoney.setServiceOrdIDDt(emergency.getLegacyServiceOrdId());
- paidMoney.setDispatchOrdIDDt(emergency.getLegacyDispatchOrdId());
+ if(emergency.getLegacyDispatchOrdId()!=null) {
+ paidMoney.setDispatchOrdIDDt(emergency.getLegacyDispatchOrdId());
+ }
paidMoney.setPaidMoney(payment.getSettlementAmount());
paidMoney.setPaidMoneyType(convertPaymentMethodToLegacy(payment.getPaymentMethod()));
paidMoney.setPaidMoneyMono(payment.getTradeNo() != null ? payment.getTradeNo() : payment.getOutTradeNo());
paidMoney.setPaidMoneyTime(payment.getPayTime() != null ? payment.getPayTime() : new Date());
paidMoney.setPaidMoneyOaID(oaUserId);
paidMoney.setPaidMoneyUnitID(0); // 榛樿涓�0
- paidMoney.setPaidMoneyAPCheck(1); // 宸茬‘璁�
+ paidMoney.setPaidMoneyAPCheck(0); // 宸茬‘璁�
paidMoney.setPaidMoneyAPTime(new Date());
paidMoney.setPaidMoneyTimestamp(String.valueOf(System.currentTimeMillis()));
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SmsServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SmsServiceImpl.java
new file mode 100644
index 0000000..61a8ef4
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SmsServiceImpl.java
@@ -0,0 +1,298 @@
+package com.ruoyi.system.service.impl;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.config.SmsConfig;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.SmsUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.SysTaskEmergency;
+import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
+import com.ruoyi.system.mapper.SysTaskMapper;
+import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.service.ISmsService;
+import com.ruoyi.system.service.ISysConfigService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 鐭俊鍙戦�佹湇鍔″疄鐜扮被
+ *
+ * @author ruoyi
+ * @date 2025-12-07
+ */
+@Service
+public class SmsServiceImpl implements ISmsService {
+
+ private static final Logger log = LoggerFactory.getLogger(SmsServiceImpl.class);
+
+ /** 绯荤粺閰嶇疆閿細鐭俊寮�鍏� */
+ private static final String CONFIG_KEY_SMS_ENABLED = "sms.enabled";
+
+ @Autowired
+ private SmsConfig smsConfig;
+
+ @Autowired
+ private ISysConfigService configService;
+
+ @Autowired
+ private SysUserMapper sysUserMapper;
+
+ @Autowired
+ private SysTaskMapper sysTaskMapper;
+
+ @Autowired
+ private SysTaskEmergencyMapper sysTaskEmergencyMapper;
+
+ /**
+ * 妫�鏌ョ煭淇℃湇鍔℃槸鍚﹀惎鐢�
+ * 浼樺厛浠庢暟鎹簱閰嶇疆璇诲彇锛屽叾娆′粠閰嶇疆鏂囦欢璇诲彇
+ *
+ * @return true=鍚敤, false=绂佺敤
+ */
+ @Override
+ public boolean isEnabled() {
+ try {
+ // 浼樺厛浠庢暟鎹簱閰嶇疆璇诲彇
+ String enabled = configService.selectConfigByKey(CONFIG_KEY_SMS_ENABLED);
+ if (StringUtils.isNotEmpty(enabled)) {
+ return "true".equalsIgnoreCase(enabled);
+ }
+ } catch (Exception e) {
+ log.warn("鑾峰彇鐭俊寮�鍏抽厤缃け璐ワ紝浣跨敤閰嶇疆鏂囦欢閰嶇疆", e);
+ }
+ // 浠庨厤缃枃浠惰鍙�
+ return smsConfig.isEnabled();
+ }
+
+ /**
+ * 鍙戦�佺煭淇�
+ *
+ * @param phone 鎵嬫満鍙�
+ * @param content 鐭俊鍐呭
+ * @return 鏄惁鍙戦�佹垚鍔�
+ */
+ @Override
+ public boolean sendSms(String phone, String content) {
+ if (!isEnabled()) {
+ log.info("鐭俊鏈嶅姟宸插叧闂紝璺宠繃鍙戦�侊紝phone={}", phone);
+ return false;
+ }
+
+ if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(content)) {
+ log.warn("鐭俊鍙戦�佸弬鏁颁笉瀹屾暣锛宲hone={}, content={}", phone, content);
+ return false;
+ }
+
+ try {
+ // 娣诲姞绛惧悕
+ String fullContent = smsConfig.getSignName() + content;
+
+ JSONObject result = SmsUtils.sendSms(
+ smsConfig.getAddress(),
+ smsConfig.getUserName(),
+ smsConfig.getPassword(),
+ phone,
+ fullContent
+ );
+
+ if (result != null) {
+ int code = result.getIntValue("code", -1);
+ if (code == 0) {
+ log.info("鐭俊鍙戦�佹垚鍔燂紝phone={}", phone);
+ return true;
+ } else {
+ log.error("鐭俊鍙戦�佸け璐ワ紝phone={}锛宑ode={}锛宮sg={}",
+ phone, code, result.getString("msg"));
+ }
+ }
+ } catch (Exception e) {
+ log.error("鐭俊鍙戦�佸紓甯革紝phone={}", phone, e);
+ }
+
+ return false;
+ }
+
+ /**
+ * 鎵归噺鍙戦�佺煭淇�
+ *
+ * @param phones 鎵嬫満鍙峰垪琛�
+ * @param content 鐭俊鍐呭
+ * @return 鎴愬姛鍙戦�佺殑鏁伴噺
+ */
+ @Override
+ public int sendSmsBatch(List<String> phones, String content) {
+ if (!isEnabled()) {
+ log.info("鐭俊鏈嶅姟宸插叧闂紝璺宠繃鎵归噺鍙戦��");
+ return 0;
+ }
+
+ if (phones == null || phones.isEmpty() || StringUtils.isEmpty(content)) {
+ log.warn("鎵归噺鐭俊鍙戦�佸弬鏁颁笉瀹屾暣");
+ return 0;
+ }
+
+ int successCount = 0;
+ for (String phone : phones) {
+ if (sendSms(phone, content)) {
+ successCount++;
+ }
+ }
+
+ log.info("鎵归噺鐭俊鍙戦�佸畬鎴愶紝鎬绘暟={}锛屾垚鍔�={}", phones.size(), successCount);
+ return successCount;
+ }
+
+ /**
+ * 鍙戦�佷换鍔″垎閰嶉�氱煡鐭俊
+ *
+ * @param taskId 浠诲姟ID
+ * @param userIds 鐢ㄦ埛ID鍒楄〃
+ * @param excludeUserId 鎺掗櫎鐨勭敤鎴稩D锛堝彲閫夛紝濡傚垱寤轰汉锛�
+ * @return 鎴愬姛鍙戦�佺殑鏁伴噺
+ */
+ @Override
+ public int sendTaskAssignSms(Long taskId, List<Long> userIds, Long excludeUserId) {
+ if (!isEnabled()) {
+ log.info("鐭俊鏈嶅姟宸插叧闂紝璺宠繃浠诲姟鍒嗛厤鐭俊鍙戦�侊紝taskId={}", taskId);
+ return 0;
+ }
+
+ if (taskId == null || userIds == null || userIds.isEmpty()) {
+ log.warn("浠诲姟鍒嗛厤鐭俊鍙戦�佸弬鏁颁笉瀹屾暣锛宼askId={}, userIds={}", taskId, userIds);
+ return 0;
+ }
+
+ // 鏌ヨ浠诲姟淇℃伅
+ SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
+ if (task == null) {
+ log.warn("浠诲姟涓嶅瓨鍦紝鏃犳硶鍙戦�佺煭淇★紝taskId={}", taskId);
+ return 0;
+ }
+
+ // 鏌ヨ鎬ユ晳鎵╁睍淇℃伅
+ SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
+
+ // 鏋勫缓鐭俊鍐呭
+ String content = buildTaskAssignSmsContent(task, emergency);
+
+ int successCount = 0;
+ for (Long userId : userIds) {
+ // 鎺掗櫎鎸囧畾鐢ㄦ埛
+ if (excludeUserId != null && excludeUserId.equals(userId)) {
+ log.debug("璺宠繃鎺掗櫎鐢ㄦ埛锛寀serId={}", userId);
+ continue;
+ }
+
+ // 鏌ヨ鐢ㄦ埛淇℃伅
+ SysUser user = sysUserMapper.selectUserById(userId);
+ if (user == null) {
+ log.warn("鐢ㄦ埛涓嶅瓨鍦紝璺宠繃鍙戦�侊紝userId={}", userId);
+ continue;
+ }
+
+ String phone = user.getPhonenumber();
+ if (StringUtils.isEmpty(phone)) {
+ log.warn("鐢ㄦ埛鎵嬫満鍙蜂负绌猴紝璺宠繃鍙戦�侊紝userId={}, userName={}", userId, user.getNickName());
+ continue;
+ }
+
+ // 鍙戦�佺煭淇�
+ if (sendSms(phone, content)) {
+ successCount++;
+ log.info("浠诲姟鍒嗛厤鐭俊鍙戦�佹垚鍔燂紝taskId={}锛寀serId={}锛宲hone={}", taskId, userId, phone);
+ }
+ }
+
+ log.info("浠诲姟鍒嗛厤鐭俊鍙戦�佸畬鎴愶紝taskId={}锛屾�绘暟={}锛屾垚鍔�={}", taskId, userIds.size(), successCount);
+ return successCount;
+ }
+
+ /**
+ * 鍙戦�佷换鍔″垎閰嶉�氱煡鐭俊锛堜笉鎺掗櫎浠讳綍鐢ㄦ埛锛�
+ *
+ * @param taskId 浠诲姟ID
+ * @param userIds 鐢ㄦ埛ID鍒楄〃
+ * @return 鎴愬姛鍙戦�佺殑鏁伴噺
+ */
+ @Override
+ public int sendTaskAssignSms(Long taskId, List<Long> userIds) {
+ return sendTaskAssignSms(taskId, userIds, null);
+ }
+
+ /**
+ * 鏋勫缓浠诲姟鍒嗛厤鐭俊鍐呭
+ *
+ * @param task 浠诲姟淇℃伅
+ * @param emergency 鎬ユ晳鎵╁睍淇℃伅锛堝彲閫夛級
+ * @return 鐭俊鍐呭
+ */
+ private String buildTaskAssignSmsContent(SysTask task, SysTaskEmergency emergency) {
+ String template = smsConfig.getTaskAssignTemplate();
+
+ // 浠诲姟缂栧彿
+ String taskCode = StringUtils.isNotEmpty(task.getTaskCode())
+ ? task.getTaskCode() : String.valueOf(task.getTaskId());
+
+ // 鍑哄彂鍦�
+ String departure;
+ if (emergency != null && StringUtils.isNotEmpty(emergency.getHospitalOutName())) {
+ departure = emergency.getHospitalOutName();
+ } else if (StringUtils.isNotEmpty(task.getDepartureAddress())) {
+ departure = task.getDepartureAddress();
+ } else {
+ departure = "寰呯‘璁�";
+ }
+
+ // 鐩殑鍦�
+ String destination;
+ if (emergency != null && StringUtils.isNotEmpty(emergency.getHospitalInName())) {
+ destination = emergency.getHospitalInName();
+ } else if (StringUtils.isNotEmpty(task.getDestinationAddress())) {
+ destination = task.getDestinationAddress();
+ } else {
+ destination = "寰呯‘璁�";
+ }
+
+ // 闄愬埗鍦板潃闀垮害锛岄伩鍏嶇煭淇¤繃闀�
+ if (departure.length() > 20) {
+ departure = departure.substring(0, 17) + "...";
+ }
+ if (destination.length() > 20) {
+ destination = destination.substring(0, 17) + "...";
+ }
+
+ // 鏇挎崲妯℃澘鍙橀噺
+ return template
+ .replace("{taskCode}", taskCode)
+ .replace("{departure}", departure)
+ .replace("{destination}", destination);
+ }
+
+ /**
+ * 鏌ヨ鐭俊浣欓
+ *
+ * @return 浣欓淇℃伅
+ */
+ @Override
+ public String getBalance() {
+ try {
+ JSONObject result = SmsUtils.getBalance(
+ smsConfig.getAddress(),
+ smsConfig.getUserName(),
+ smsConfig.getPassword()
+ );
+
+ if (result != null) {
+ return result.toJSONString();
+ }
+ } catch (Exception e) {
+ log.error("鏌ヨ鐭俊浣欓澶辫触", e);
+ }
+ return "鏌ヨ澶辫触";
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysEmergencyTaskServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysEmergencyTaskServiceImpl.java
new file mode 100644
index 0000000..20fcac3
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysEmergencyTaskServiceImpl.java
@@ -0,0 +1,490 @@
+package com.ruoyi.system.service.impl;
+
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.SysTaskEmergency;
+import com.ruoyi.system.domain.enums.TaskStatus;
+import com.ruoyi.system.domain.vo.TaskCreateVO;
+import com.ruoyi.system.domain.vo.TaskUpdateVO;
+import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
+import com.ruoyi.system.mapper.SysTaskMapper;
+import com.ruoyi.system.service.ISysEmergencyTaskService;
+import com.ruoyi.system.service.ISysTaskEmergencyService;
+import com.ruoyi.system.service.IMapService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Map;
+
+@Service
+public class SysEmergencyTaskServiceImpl implements ISysEmergencyTaskService {
+
+ private static final Logger log = LoggerFactory.getLogger(SysEmergencyTaskServiceImpl.class);
+
+ @Autowired
+ private SysTaskEmergencyMapper sysTaskEmergencyMapper;
+
+ @Autowired
+ private SysTaskMapper sysTaskMapper;
+
+ @Autowired(required = false)
+ private ISysTaskEmergencyService sysTaskEmergencyService;
+
+ @Autowired(required = false)
+ private IMapService mapService;
+
+ @Override
+ public void saveEmergencyInfo(Long taskId, String createUserName, TaskCreateVO createVO,
+ String serviceOrderId, String dispatchOrderId, String serviceOrdNo) {
+ SysTaskEmergency emergencyInfo = new SysTaskEmergency();
+ emergencyInfo.setTaskId(taskId);
+
+ if (createVO.getPatient() != null) {
+ emergencyInfo.setPatientContact(createVO.getPatient().getContact());
+ emergencyInfo.setPatientPhone(createVO.getPatient().getPhone());
+ emergencyInfo.setPatientName(createVO.getPatient().getName());
+ emergencyInfo.setPatientGender(createVO.getPatient().getGender());
+ emergencyInfo.setPatientIdCard(createVO.getPatient().getIdCard());
+ emergencyInfo.setPatientCondition(createVO.getPatient().getCondition());
+ }
+
+ if (createVO.getHospitalOut() != null) {
+ emergencyInfo.setHospitalOutId(createVO.getHospitalOut().getId());
+ emergencyInfo.setHospitalOutName(createVO.getHospitalOut().getName());
+ emergencyInfo.setHospitalOutDepartment(createVO.getHospitalOut().getDepartment());
+ emergencyInfo.setHospitalOutDepartmentId(createVO.getHospitalOut().getDepartmentId());
+ emergencyInfo.setHospitalOutBedNumber(createVO.getHospitalOut().getBedNumber());
+ emergencyInfo.setHospitalOutAddress(createVO.getHospitalOut().getAddress());
+
+ if (createVO.getHospitalOut().getLongitude() != null && createVO.getHospitalOut().getLatitude() != null) {
+ emergencyInfo.setHospitalOutLongitude(createVO.getHospitalOut().getLongitude());
+ emergencyInfo.setHospitalOutLatitude(createVO.getHospitalOut().getLatitude());
+ } else if (mapService != null && createVO.getHospitalOut().getAddress() != null) {
+ try {
+ Map<String, Double> coords = mapService.geocoding(
+ createVO.getHospitalOut().getAddress(),
+ extractCityFromAddress(createVO.getHospitalOut().getAddress())
+ );
+ if (coords != null) {
+ emergencyInfo.setHospitalOutLongitude(BigDecimal.valueOf(coords.get("lng")));
+ emergencyInfo.setHospitalOutLatitude(BigDecimal.valueOf(coords.get("lat")));
+ log.info("杞嚭鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+ }
+ } catch (Exception e) {
+ log.error("鑷姩鑾峰彇杞嚭鍖婚櫌GPS鍧愭爣澶辫触", e);
+ }
+ }
+ }
+
+ if (createVO.getHospitalIn() != null) {
+ emergencyInfo.setHospitalInId(createVO.getHospitalIn().getId());
+ emergencyInfo.setHospitalInName(createVO.getHospitalIn().getName());
+ emergencyInfo.setHospitalInDepartment(createVO.getHospitalIn().getDepartment());
+ emergencyInfo.setHospitalInDepartmentId(createVO.getHospitalIn().getDepartmentId());
+ emergencyInfo.setHospitalInBedNumber(createVO.getHospitalIn().getBedNumber());
+ emergencyInfo.setHospitalInAddress(createVO.getHospitalIn().getAddress());
+
+ if (createVO.getHospitalIn().getLongitude() != null && createVO.getHospitalIn().getLatitude() != null) {
+ emergencyInfo.setHospitalInLongitude(createVO.getHospitalIn().getLongitude());
+ emergencyInfo.setHospitalInLatitude(createVO.getHospitalIn().getLatitude());
+ } else if (mapService != null && createVO.getHospitalIn().getAddress() != null) {
+ try {
+ Map<String, Double> coords = mapService.geocoding(
+ createVO.getHospitalIn().getAddress(),
+ extractCityFromAddress(createVO.getHospitalIn().getAddress())
+ );
+ if (coords != null) {
+ emergencyInfo.setHospitalInLongitude(BigDecimal.valueOf(coords.get("lng")));
+ emergencyInfo.setHospitalInLatitude(BigDecimal.valueOf(coords.get("lat")));
+ log.info("杞叆鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+ }
+ } catch (Exception e) {
+ log.error("鑷姩鑾峰彇杞叆鍖婚櫌GPS鍧愭爣澶辫触", e);
+ }
+ }
+ }
+
+ emergencyInfo.setTransferDistance(createVO.getTransferDistance());
+ emergencyInfo.setTransferPrice(createVO.getPrice());
+ emergencyInfo.setDocumentTypeId(createVO.getDocumentTypeId());
+ emergencyInfo.setTaskTypeId(createVO.getTaskTypeId());
+
+ if (createVO.getDiseaseIds() != null && !createVO.getDiseaseIds().isEmpty()) {
+ String diseaseIdsStr = createVO.getDiseaseIds().stream()
+ .map(String::valueOf)
+ .collect(java.util.stream.Collectors.joining(","));
+ emergencyInfo.setDiseaseIds(diseaseIdsStr);
+ }
+
+ if (serviceOrderId != null) {
+ emergencyInfo.setLegacyServiceOrdId(Long.parseLong(serviceOrderId));
+ emergencyInfo.setSyncStatus(2);
+ emergencyInfo.setSyncTime(DateUtils.getNowDate());
+ emergencyInfo.setSyncErrorMsg("鏃х郴缁熷悓姝ヨ繃鏉�");
+ }
+ if (dispatchOrderId != null) {
+ emergencyInfo.setLegacyDispatchOrdId(Long.parseLong(dispatchOrderId));
+ emergencyInfo.setDispatchSyncStatus(2);
+ emergencyInfo.setDispatchSyncTime(DateUtils.getNowDate());
+ emergencyInfo.setDispatchSyncErrorMsg("鏃х郴缁熷悓姝ヨ繃鏉�");
+ }
+ if (serviceOrdNo != null) {
+ emergencyInfo.setLegacyServiceOrdNo(serviceOrdNo);
+ }
+
+ emergencyInfo.setCreateTime(DateUtils.getNowDate());
+ emergencyInfo.setUpdateTime(DateUtils.getNowDate());
+ emergencyInfo.setCreateBy(createUserName);
+ emergencyInfo.setUpdateBy(createUserName);
+
+ sysTaskEmergencyMapper.insertSysTaskEmergency(emergencyInfo);
+ }
+
+ @Override
+ public void updateEmergencyInfoFromUpdateVO(SysTaskEmergency oldEmergency, TaskUpdateVO updateVO, String userName) {
+ if (oldEmergency == null || updateVO == null) {
+ return;
+ }
+
+ if (updateVO.getPatient() != null) {
+ if (updateVO.getPatient().getContact() != null) {
+ oldEmergency.setPatientContact(updateVO.getPatient().getContact());
+ }
+ if (updateVO.getPatient().getPhone() != null) {
+ oldEmergency.setPatientPhone(updateVO.getPatient().getPhone());
+ }
+ if (updateVO.getPatient().getName() != null) {
+ oldEmergency.setPatientName(updateVO.getPatient().getName());
+ }
+ if (updateVO.getPatient().getGender() != null) {
+ oldEmergency.setPatientGender(updateVO.getPatient().getGender());
+ }
+ if (updateVO.getPatient().getIdCard() != null) {
+ oldEmergency.setPatientIdCard(updateVO.getPatient().getIdCard());
+ }
+ if (updateVO.getPatient().getCondition() != null) {
+ oldEmergency.setPatientCondition(updateVO.getPatient().getCondition());
+ }
+ }
+
+ if (updateVO.getHospitalOut() != null) {
+ if (updateVO.getHospitalOut().getId() != null) {
+ oldEmergency.setHospitalOutId(updateVO.getHospitalOut().getId());
+ }
+ if (updateVO.getHospitalOut().getName() != null) {
+ oldEmergency.setHospitalOutName(updateVO.getHospitalOut().getName());
+ }
+ if (updateVO.getHospitalOut().getDepartment() != null) {
+ oldEmergency.setHospitalOutDepartment(updateVO.getHospitalOut().getDepartment());
+ }
+ if (updateVO.getHospitalOut().getDepartmentId() != null) {
+ oldEmergency.setHospitalOutDepartmentId(updateVO.getHospitalOut().getDepartmentId());
+ }
+ if (updateVO.getHospitalOut().getBedNumber() != null) {
+ oldEmergency.setHospitalOutBedNumber(updateVO.getHospitalOut().getBedNumber());
+ }
+ if (updateVO.getHospitalOut().getAddress() != null
+ && !updateVO.getHospitalOut().getAddress().equals(oldEmergency.getHospitalOutAddress())) {
+ oldEmergency.setHospitalOutAddress(updateVO.getHospitalOut().getAddress());
+
+ if (updateVO.getHospitalOut().getLongitude() == null
+ && updateVO.getHospitalOut().getLatitude() == null && mapService != null) {
+ try {
+ Map<String, Double> coords = mapService.geocoding(
+ updateVO.getHospitalOut().getAddress(),
+ extractCityFromAddress(updateVO.getHospitalOut().getAddress())
+ );
+ if (coords != null) {
+ oldEmergency.setHospitalOutLongitude(BigDecimal.valueOf(coords.get("lng")));
+ oldEmergency.setHospitalOutLatitude(BigDecimal.valueOf(coords.get("lat")));
+ log.info("杞嚭鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+ }
+ } catch (Exception e) {
+ log.error("鑷姩鑾峰彇杞嚭鍖婚櫌GPS鍧愭爣澶辫触", e);
+ }
+ }
+ }
+ }
+
+ if (updateVO.getHospitalIn() != null) {
+ if (updateVO.getHospitalIn().getId() != null) {
+ oldEmergency.setHospitalInId(updateVO.getHospitalIn().getId());
+ }
+ if (updateVO.getHospitalIn().getName() != null) {
+ oldEmergency.setHospitalInName(updateVO.getHospitalIn().getName());
+ }
+ if (updateVO.getHospitalIn().getDepartment() != null) {
+ oldEmergency.setHospitalInDepartment(updateVO.getHospitalIn().getDepartment());
+ }
+ if (updateVO.getHospitalIn().getDepartmentId() != null) {
+ oldEmergency.setHospitalInDepartmentId(updateVO.getHospitalIn().getDepartmentId());
+ }
+ if (updateVO.getHospitalIn().getBedNumber() != null) {
+ oldEmergency.setHospitalInBedNumber(updateVO.getHospitalIn().getBedNumber());
+ }
+ if (updateVO.getHospitalIn().getAddress() != null
+ && !updateVO.getHospitalIn().getAddress().equals(oldEmergency.getHospitalInAddress())) {
+ oldEmergency.setHospitalInAddress(updateVO.getHospitalIn().getAddress());
+
+ if (updateVO.getHospitalIn().getLongitude() == null
+ && updateVO.getHospitalIn().getLatitude() == null && mapService != null) {
+ try {
+ Map<String, Double> coords = mapService.geocoding(
+ updateVO.getHospitalIn().getAddress(),
+ extractCityFromAddress(updateVO.getHospitalIn().getAddress())
+ );
+ if (coords != null) {
+ oldEmergency.setHospitalInLongitude(BigDecimal.valueOf(coords.get("lng")));
+ oldEmergency.setHospitalInLatitude(BigDecimal.valueOf(coords.get("lat")));
+ log.info("杞叆鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+ }
+ } catch (Exception e) {
+ log.error("鑷姩鑾峰彇杞叆鍖婚櫌GPS鍧愭爣澶辫触", e);
+ }
+ }
+ }
+ }
+
+ if (updateVO.getTransferDistance() != null) {
+ oldEmergency.setTransferDistance(updateVO.getTransferDistance());
+ }
+ if (updateVO.getPrice() != null) {
+ oldEmergency.setTransferPrice(updateVO.getPrice());
+ }
+
+ if (updateVO.getDocumentTypeId() != null) {
+ oldEmergency.setDocumentTypeId(updateVO.getDocumentTypeId());
+ }
+
+ if (updateVO.getTaskTypeId() != null) {
+ oldEmergency.setTaskTypeId(updateVO.getTaskTypeId());
+ }
+
+ if (updateVO.getDiseaseIds() != null && !updateVO.getDiseaseIds().isEmpty()) {
+ String diseaseIdsStr = updateVO.getDiseaseIds().stream()
+ .map(String::valueOf)
+ .collect(java.util.stream.Collectors.joining(","));
+ oldEmergency.setDiseaseIds(diseaseIdsStr);
+ }
+
+ oldEmergency.setUpdateTime(DateUtils.getNowDate());
+ oldEmergency.setUpdateBy(userName);
+
+ sysTaskEmergencyMapper.updateSysTaskEmergency(oldEmergency);
+ }
+
+ @Override
+ public void updateEmergencyInfoFromCreateVO(SysTaskEmergency existingInfo, TaskCreateVO createVO, String userName) {
+ if (existingInfo == null || createVO == null) {
+ return;
+ }
+
+ log.info("鏇存柊杞繍浠诲姟 taskId:{}", existingInfo.getTaskId());
+
+ // 鏇存柊鎮h�呬俊鎭�
+ if (createVO.getPatient() != null) {
+ if (createVO.getPatient().getContact() != null) {
+ existingInfo.setPatientContact(createVO.getPatient().getContact());
+ }
+ if (createVO.getPatient().getPhone() != null) {
+ existingInfo.setPatientPhone(createVO.getPatient().getPhone());
+ }
+ if (createVO.getPatient().getName() != null) {
+ existingInfo.setPatientName(createVO.getPatient().getName());
+ }
+ if (createVO.getPatient().getGender() != null) {
+ existingInfo.setPatientGender(createVO.getPatient().getGender());
+ }
+ if (createVO.getPatient().getIdCard() != null) {
+ existingInfo.setPatientIdCard(createVO.getPatient().getIdCard());
+ }
+ if (createVO.getPatient().getCondition() != null) {
+ existingInfo.setPatientCondition(createVO.getPatient().getCondition());
+ }
+ }
+
+ // 鏇存柊杞嚭鍖婚櫌淇℃伅
+ if (createVO.getHospitalOut() != null) {
+ if (createVO.getHospitalOut().getId() != null) {
+ existingInfo.setHospitalOutId(createVO.getHospitalOut().getId());
+ }
+ if (createVO.getHospitalOut().getName() != null) {
+ existingInfo.setHospitalOutName(createVO.getHospitalOut().getName());
+ }
+ if (createVO.getHospitalOut().getDepartment() != null) {
+ existingInfo.setHospitalOutDepartment(createVO.getHospitalOut().getDepartment());
+ }
+ if (createVO.getHospitalOut().getDepartmentId() != null) {
+ existingInfo.setHospitalOutDepartmentId(createVO.getHospitalOut().getDepartmentId());
+ }
+ if (createVO.getHospitalOut().getBedNumber() != null) {
+ existingInfo.setHospitalOutBedNumber(createVO.getHospitalOut().getBedNumber());
+ }
+ if (createVO.getHospitalOut().getAddress() != null
+ && !createVO.getHospitalOut().getAddress().equals(existingInfo.getHospitalOutAddress())) {
+ existingInfo.setHospitalOutAddress(createVO.getHospitalOut().getAddress());
+
+ // 濡傛灉鏇存柊浜嗗湴鍧�浣嗘病鏈塆PS鍧愭爣锛屽悗绔嚜鍔ㄨ幏鍙�
+ if (createVO.getHospitalOut().getLongitude() == null
+ && createVO.getHospitalOut().getLatitude() == null && mapService != null) {
+ try {
+ Map<String, Double> coords = mapService.geocoding(
+ createVO.getHospitalOut().getAddress(),
+ extractCityFromAddress(createVO.getHospitalOut().getAddress())
+ );
+ if (coords != null) {
+ existingInfo.setHospitalOutLongitude(BigDecimal.valueOf(coords.get("lng")));
+ existingInfo.setHospitalOutLatitude(BigDecimal.valueOf(coords.get("lat")));
+ log.info("杞嚭鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+ }
+ } catch (Exception e) {
+ log.error("鑷姩鑾峰彇杞嚭鍖婚櫌GPS鍧愭爣澶辫触", e);
+ }
+ }
+ }
+ }
+
+ // 鏇存柊杞叆鍖婚櫌淇℃伅
+ if (createVO.getHospitalIn() != null) {
+ if (createVO.getHospitalIn().getId() != null) {
+ existingInfo.setHospitalInId(createVO.getHospitalIn().getId());
+ }
+ if (createVO.getHospitalIn().getName() != null) {
+ existingInfo.setHospitalInName(createVO.getHospitalIn().getName());
+ }
+ if (createVO.getHospitalIn().getDepartment() != null) {
+ existingInfo.setHospitalInDepartment(createVO.getHospitalIn().getDepartment());
+ }
+ if (createVO.getHospitalIn().getDepartmentId() != null) {
+ existingInfo.setHospitalInDepartmentId(createVO.getHospitalIn().getDepartmentId());
+ }
+ if (createVO.getHospitalIn().getBedNumber() != null) {
+ existingInfo.setHospitalInBedNumber(createVO.getHospitalIn().getBedNumber());
+ }
+ if (createVO.getHospitalIn().getAddress() != null
+ && !createVO.getHospitalIn().getAddress().equals(existingInfo.getHospitalInAddress())) {
+ existingInfo.setHospitalInAddress(createVO.getHospitalIn().getAddress());
+
+ // 濡傛灉鏇存柊浜嗗湴鍧�浣嗘病鏈塆PS鍧愭爣锛屽悗绔嚜鍔ㄨ幏鍙�
+ if (createVO.getHospitalIn().getLongitude() == null
+ && createVO.getHospitalIn().getLatitude() == null && mapService != null) {
+ try {
+ Map<String, Double> coords = mapService.geocoding(
+ createVO.getHospitalIn().getAddress(),
+ extractCityFromAddress(createVO.getHospitalIn().getAddress())
+ );
+ if (coords != null) {
+ existingInfo.setHospitalInLongitude(BigDecimal.valueOf(coords.get("lng")));
+ existingInfo.setHospitalInLatitude(BigDecimal.valueOf(coords.get("lat")));
+ log.info("杞叆鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+ }
+ } catch (Exception e) {
+ log.error("鑷姩鑾峰彇杞叆鍖婚櫌GPS鍧愭爣澶辫触", e);
+ }
+ }
+ }
+ }
+
+ // 鏇存柊璐圭敤淇℃伅
+ if (createVO.getTransferDistance() != null) {
+ existingInfo.setTransferDistance(createVO.getTransferDistance());
+ }
+ if (createVO.getPrice() != null) {
+ existingInfo.setTransferPrice(createVO.getPrice());
+ }
+
+ // 鏇存柊鍗曟嵁绫诲瀷ID
+ if (createVO.getDocumentTypeId() != null) {
+ existingInfo.setDocumentTypeId(createVO.getDocumentTypeId());
+ }
+
+ // 鏇存柊浠诲姟绫诲瀷ID
+ if (createVO.getTaskTypeId() != null) {
+ existingInfo.setTaskTypeId(createVO.getTaskTypeId());
+ }
+
+ // 鏇存柊鐥呮儏ID鍒楄〃
+ if (createVO.getDiseaseIds() != null && !createVO.getDiseaseIds().isEmpty()) {
+ String diseaseIdsStr = createVO.getDiseaseIds().stream()
+ .map(String::valueOf)
+ .collect(java.util.stream.Collectors.joining(","));
+ existingInfo.setDiseaseIds(diseaseIdsStr);
+ }
+
+ // 绯荤粺瀛楁
+ existingInfo.setUpdateTime(DateUtils.getNowDate());
+ existingInfo.setUpdateBy(userName);
+
+ // 鎵ц鏇存柊
+ sysTaskEmergencyMapper.updateSysTaskEmergency(existingInfo);
+ }
+
+ @Override
+ public void markNeedResyncIfNecessary(Long taskId, SysTask oldTask, TaskUpdateVO updateVO, Boolean updateFromLegacy) {
+ if (!"EMERGENCY_TRANSFER".equals(oldTask.getTaskType()) || Boolean.TRUE.equals(updateFromLegacy)) {
+ return;
+ }
+ try {
+ sysTaskEmergencyService.markNeedResync(taskId);
+ } catch (Exception e) {
+ // 鏍囪澶辫触涓嶅奖鍝嶄富娴佺▼
+ }
+ }
+
+ @Override
+ public boolean hasLegacyServiceOrdId(Long taskId) {
+ SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
+ if (task != null && "EMERGENCY_TRANSFER".equals(task.getTaskType())) {
+ SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
+ return emergencyInfo != null && emergencyInfo.getLegacyServiceOrdId() != null;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean hasLegacyDispatchOrdId(Long taskId) {
+ SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
+ if (task != null && "EMERGENCY_TRANSFER".equals(task.getTaskType())) {
+ SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
+ return emergencyInfo != null && emergencyInfo.getLegacyDispatchOrdId() != null;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean existsByLegacyServiceOrdId(Long legacyServiceOrdId) {
+ if (legacyServiceOrdId == null) {
+ return false;
+ }
+ SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectByLegacyServiceOrdId(legacyServiceOrdId);
+ return emergencyInfo != null;
+ }
+
+ @Override
+ public boolean existsByLegacyDispatchOrdId(Long legacyDispatchOrdId) {
+ if (legacyDispatchOrdId == null) {
+ return false;
+ }
+ SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectByLegacyDispatchOrdId(legacyDispatchOrdId);
+ return emergencyInfo != null;
+ }
+
+ private String extractCityFromAddress(String address) {
+ if (address == null || address.trim().isEmpty()) {
+ return null;
+ }
+ String[] cities = {"骞垮窞", "娣卞湷", "涓滆帪", "浣涘北", "鐝犳捣", "鎯犲窞", "涓北", "姹熼棬", "婀涙睙", "鑲囧簡", "娓呰繙", "闊跺叧", "姊呭窞", "娌虫簮", "娼窞", "鎻槼", "姹曞ご", "姹曞熬", "浜戞诞", "闃虫睙","鍖椾含","涓婃捣","澶╂触"};
+ for (String city : cities) {
+ if (address.contains(city)) {
+ return city;
+ }
+ }
+ return null;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAssigneeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAssigneeServiceImpl.java
new file mode 100644
index 0000000..1953b3d
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAssigneeServiceImpl.java
@@ -0,0 +1,260 @@
+package com.ruoyi.system.service.impl;
+
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.system.domain.SysTaskAssignee;
+import com.ruoyi.system.domain.vo.TaskCreateVO;
+import com.ruoyi.system.mapper.SysTaskAssigneeMapper;
+import com.ruoyi.system.service.ISysTaskAssigneeService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 浠诲姟鎵ц浜烘湇鍔″疄鐜扮被
+ *
+ * @author ruoyi
+ */
+@Slf4j
+@Service
+public class SysTaskAssigneeServiceImpl implements ISysTaskAssigneeService {
+
+ @Autowired
+ private SysTaskAssigneeMapper sysTaskAssigneeMapper;
+
+ @Autowired
+ private ApplicationEventPublisher eventPublisher;
+
+ @Override
+ @Transactional
+ public void saveTaskAssignees(Long taskId, List<TaskCreateVO.AssigneeInfo> assignees, String userName) {
+ if (assignees == null || assignees.isEmpty()) {
+ return;
+ }
+
+ List<SysTaskAssignee> taskAssignees = new ArrayList<>();
+ Date now = DateUtils.getNowDate();
+
+ for (int i = 0; i < assignees.size(); i++) {
+ TaskCreateVO.AssigneeInfo assigneeInfo = assignees.get(i);
+
+ SysTaskAssignee taskAssignee = new SysTaskAssignee();
+ taskAssignee.setTaskId(taskId);
+ taskAssignee.setUserId(assigneeInfo.getUserId());
+ taskAssignee.setUserName(assigneeInfo.getUserName());
+ taskAssignee.setUserType(assigneeInfo.getUserType());
+ // 绗竴涓墽琛屼汉鍛樹负涓昏鎵ц浜�
+ taskAssignee.setIsPrimary(i == 0 ? "1" : "0");
+ taskAssignee.setSortOrder(i);
+ taskAssignee.setCreateTime(now);
+ taskAssignee.setCreateBy(userName);
+ taskAssignee.setUpdateTime(now);
+ taskAssignee.setUpdateBy(userName);
+
+ taskAssignees.add(taskAssignee);
+ }
+
+ // 鎵归噺淇濆瓨
+ if (!taskAssignees.isEmpty()) {
+ sysTaskAssigneeMapper.batchInsertSysTaskAssignee(taskAssignees);
+
+ }
+ }
+
+ @Override
+ @Transactional
+ public boolean updateTaskAssignees(Long taskId, List<TaskCreateVO.AssigneeInfo> newAssignees, String userName) {
+ if (newAssignees == null) {
+ return false;
+ }
+ try {
+ List<Long> newAssigneeIds = newAssignees.stream().map(TaskCreateVO.AssigneeInfo::getUserId).collect(Collectors.toList());
+ // 鏌ヨ鐜版湁鐨勬墽琛屼汉鍛�
+ List<SysTaskAssignee> existingAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
+
+ List<Long> existingAssigneeIds = existingAssignees.stream().map(SysTaskAssignee::getUserId).collect(Collectors.toList());
+ // 鎵惧嚭闇�瑕佸垹闄ょ殑鎵ц浜猴紙鍦ㄦ暟鎹簱涓瓨鍦ㄤ絾鍦ㄦ柊鍒楄〃涓笉瀛樺湪锛�
+ List<Long> assigneesToDelete = existingAssignees.stream().map(SysTaskAssignee::getUserId)
+ .filter(id -> !newAssigneeIds.contains(id))
+ .collect(Collectors.toList());
+
+ // 鎵惧嚭闇�瑕佹坊鍔犵殑鎵ц浜猴紙鍦ㄦ柊鍒楄〃涓瓨鍦ㄤ絾鍦ㄦ暟鎹簱涓笉瀛樺湪锛�
+ List<TaskCreateVO.AssigneeInfo> assigneesToAdd = newAssignees.stream()
+ .filter(assignee -> !existingAssigneeIds.contains(assignee.getUserId()))
+ .collect(Collectors.toList());
+
+
+ boolean hasChanges = !assigneesToDelete.isEmpty() || !assigneesToAdd.isEmpty();
+
+ // 鍙湁鎵ц浜哄憳鍙戠敓鍙樺寲鏃舵墠鏇存柊
+ if (hasChanges) {
+ // 鍒犻櫎涓嶉渶瑕佺殑鎵ц浜哄憳鍏宠仈
+ if (!assigneesToDelete.isEmpty()) {
+ for (Long userId : assigneesToDelete) {
+ sysTaskAssigneeMapper.deleteByTaskIdAndUserId(taskId, userId);
+ }
+ }
+
+ // 娣诲姞鏂扮殑鎵ц浜哄憳鍏宠仈
+ if (!assigneesToAdd.isEmpty()) {
+ // 涓烘柊澧炵殑鎵ц浜鸿缃帓搴忓拰涓昏鎵ц浜烘爣蹇�
+ Date now = DateUtils.getNowDate();
+ List<SysTaskAssignee> newTaskAssignees = new ArrayList<>();
+
+ for (int i = 0; i < assigneesToAdd.size(); i++) {
+ TaskCreateVO.AssigneeInfo assigneeInfo = assigneesToAdd.get(i);
+
+ SysTaskAssignee taskAssignee = new SysTaskAssignee();
+ taskAssignee.setTaskId(taskId);
+ taskAssignee.setUserId(assigneeInfo.getUserId());
+ taskAssignee.setUserName(assigneeInfo.getUserName());
+ taskAssignee.setUserType(assigneeInfo.getUserType());
+ // 娉ㄦ剰锛氳繖閲屾垜浠笉鐭ラ亾鏈�缁堢殑鎺掑簭锛屾墍浠ユ殏鏃惰缃负涓�涓緝澶х殑鍊�
+ // 鍦ㄥ悗缁噸鏂版帓搴忔椂浼氫慨姝�
+ taskAssignee.setIsPrimary("0"); // 榛樿涓嶆槸涓昏鎵ц浜�
+ taskAssignee.setSortOrder(999 + i); // 涓存椂鎺掑簭鍊�
+ taskAssignee.setCreateTime(now);
+ taskAssignee.setCreateBy(userName);
+ taskAssignee.setUpdateTime(now);
+ taskAssignee.setUpdateBy(userName);
+
+ newTaskAssignees.add(taskAssignee);
+ }
+
+ // 鎵归噺淇濆瓨鏂板鐨勬墽琛屼汉
+ if (!newTaskAssignees.isEmpty()) {
+ sysTaskAssigneeMapper.batchInsertSysTaskAssignee(newTaskAssignees);
+ }
+ }
+
+ // 閲嶆柊鏌ヨ鎵�鏈夋墽琛屼汉骞惰缃纭殑鎺掑簭鍜屼富瑕佹墽琛屼汉鏍囧織
+ List<SysTaskAssignee> allAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
+ Map<Long, SysTaskAssignee> allAssigneeMap = allAssignees.stream()
+ .collect(Collectors.toMap(SysTaskAssignee::getUserId, a -> a));
+
+
+ // 鏇存柊鎵�鏈夋墽琛屼汉鐨勬帓搴忓拰涓昏鎵ц浜烘爣蹇�
+ Date now = DateUtils.getNowDate();
+ for (int i = 0; i < newAssignees.size(); i++) {
+ TaskCreateVO.AssigneeInfo assigneeInfo = newAssignees.get(i);
+ SysTaskAssignee taskAssignee = allAssigneeMap.get(assigneeInfo.getUserId());
+
+ if (taskAssignee != null) {
+ // 淇濇寔鍘熸湁鐨勭姸鎬佷俊鎭紙濡傚氨缁姸鎬侊級锛屽彧鏇存柊鍩烘湰淇℃伅
+ taskAssignee.setUserName(assigneeInfo.getUserName());
+ taskAssignee.setUserType(assigneeInfo.getUserType());
+ taskAssignee.setIsPrimary(i == 0 ? "1" : "0"); // 绗竴涓负涓昏鎵ц浜�
+ taskAssignee.setSortOrder(i);
+ taskAssignee.setUpdateTime(now);
+ taskAssignee.setUpdateBy(userName);
+
+ sysTaskAssigneeMapper.updateSysTaskAssignee(taskAssignee);
+ }
+ }
+
+ return true;
+ }
+ }catch (Exception e){
+ log.error("鎶ラ敊浜嗭紝淇濆瓨鍒版墽琛屼汉鍛樺垎閰�,taskId:{}",taskId,e);
+ throw e;
+ }
+ return false;
+ }
+
+ @Override
+ public List<SysTaskAssignee> getAssigneesByTaskId(Long taskId) {
+ return sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
+ }
+
+ @Override
+ @Transactional
+ public int deleteAssigneesByTaskId(Long taskId) {
+ return sysTaskAssigneeMapper.deleteSysTaskAssigneeByTaskId(taskId);
+ }
+
+ @Override
+ @Transactional
+ public AjaxResult setAssigneeReady(Long taskId, Long userId) {
+ // 1. 鏌ヨ鎵ц浜哄叧鑱斾俊鎭�
+ List<SysTaskAssignee> assignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
+ SysTaskAssignee targetAssignee = assignees.stream()
+ .filter(a -> a.getUserId().equals(userId))
+ .findFirst()
+ .orElse(null);
+
+ if (targetAssignee == null) {
+ return AjaxResult.error("鎮ㄤ笉鏄浠诲姟鐨勬墽琛屼汉");
+ }
+
+ // 2. 鏇存柊灏辩华鐘舵��
+ targetAssignee.setIsReady("1");
+ targetAssignee.setReadyTime(new Date());
+ targetAssignee.setUpdateBy(SecurityUtils.getUsername());
+ targetAssignee.setUpdateTime(new Date());
+
+ sysTaskAssigneeMapper.updateSysTaskAssignee(targetAssignee);
+
+ // 3. 妫�鏌ユ槸鍚︽墍鏈夋墽琛屼汉閮藉凡灏辩华
+ boolean allReady = assignees.stream()
+ .allMatch(a -> a.getUserId().equals(userId) || "1".equals(a.getIsReady()));
+
+ Map<String, Object> result = new HashMap<>();
+ result.put("allReady", allReady);
+ result.put("message", "灏辩华鎴愬姛");
+
+ return AjaxResult.success(result);
+ }
+
+ @Override
+ @Transactional
+ public AjaxResult cancelAssigneeReady(Long taskId, Long userId) {
+ // 鏌ヨ鎵ц浜哄叧鑱斾俊鎭�
+ List<SysTaskAssignee> assignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
+ SysTaskAssignee targetAssignee = assignees.stream()
+ .filter(a -> a.getUserId().equals(userId))
+ .findFirst()
+ .orElse(null);
+
+ if (targetAssignee == null) {
+ return AjaxResult.error("鎮ㄤ笉鏄浠诲姟鐨勬墽琛屼汉");
+ }
+
+ // 鏇存柊灏辩华鐘舵��
+ targetAssignee.setIsReady("0");
+ targetAssignee.setReadyTime(null);
+ targetAssignee.setUpdateBy(SecurityUtils.getUsername());
+ targetAssignee.setUpdateTime(new Date());
+
+ sysTaskAssigneeMapper.updateSysTaskAssignee(targetAssignee);
+
+ return AjaxResult.success("宸插彇娑堝氨缁�");
+ }
+
+ @Override
+ public List<Long> getAssigneeIds(Long taskId) {
+ List<SysTaskAssignee> assignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
+ if (assignees == null || assignees.isEmpty()) {
+ return Collections.emptyList();
+ }
+ return assignees.stream()
+ .map(SysTaskAssignee::getUserId)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public List<String> getAssigneeNames(Long taskId) {
+ List<SysTaskAssignee> assignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
+ if (assignees == null || assignees.isEmpty()) {
+ return Collections.emptyList();
+ }
+ return assignees.stream()
+ .map(SysTaskAssignee::getUserName)
+ .collect(Collectors.toList());
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAttachmentServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAttachmentServiceImpl.java
new file mode 100644
index 0000000..7c0111f
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskAttachmentServiceImpl.java
@@ -0,0 +1,227 @@
+package com.ruoyi.system.service.impl;
+
+import com.ruoyi.common.config.ImageUrlConfig;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.common.utils.file.FileUtils;
+import com.ruoyi.system.domain.SysTaskAttachment;
+import com.ruoyi.system.mapper.SysTaskAttachmentMapper;
+import com.ruoyi.system.service.ISysTaskAttachmentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.List;
+
+@Service
+public class SysTaskAttachmentServiceImpl implements ISysTaskAttachmentService {
+
+ @Autowired
+ private SysTaskAttachmentMapper sysTaskAttachmentMapper;
+
+ @Autowired
+ private ImageUrlConfig imageUrlConfig;
+
+ @Override
+ @Transactional
+ public Long uploadAttachment(Long taskId, MultipartFile file, String category) {
+ try {
+ String fileName = category + "_" + System.currentTimeMillis() + "_" + file.getOriginalFilename();
+ String relativePath = saveLocalPath(fileName, file.getInputStream());
+
+ SysTaskAttachment attachment = new SysTaskAttachment();
+ attachment.setTaskId(taskId);
+ attachment.setFileName(file.getOriginalFilename());
+ attachment.setFilePath(relativePath);
+ attachment.setFileSize(file.getSize());
+ attachment.setFileType(getFileType(file.getOriginalFilename()));
+ attachment.setAttachmentCategory(category);
+ attachment.setUploadTime(DateUtils.getNowDate());
+ attachment.setUploadBy(SecurityUtils.getUsername());
+
+ Long result = sysTaskAttachmentMapper.insertSysTaskAttachment(attachment);
+ return result > 0 ? attachment.getAttachmentId() : 0L;
+ } catch (IOException e) {
+ throw new RuntimeException("鏂囦欢涓婁紶澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ @Override
+ @Transactional
+ public Long uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category) {
+ try {
+ String wechatUrl = String.format(
+ "https://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s",
+ accessToken, mediaId
+ );
+
+ byte[] fileBytes = downloadFromUrl(wechatUrl);
+ if (fileBytes == null || fileBytes.length == 0) {
+ throw new RuntimeException("浠庡井淇′笅杞芥枃浠跺け璐�");
+ }
+
+ String fileName = "wx_" + mediaId.substring(0, Math.min(20, mediaId.length())) + "_" + System.currentTimeMillis() + ".jpg";
+ String relativeFilePath = saveLocalPath(fileName, fileBytes);
+
+ SysTaskAttachment attachment = new SysTaskAttachment();
+ attachment.setTaskId(taskId);
+ attachment.setFileName(fileName);
+ attachment.setFilePath(relativeFilePath);
+ attachment.setFileSize((long) fileBytes.length);
+ attachment.setFileType("jpg");
+ attachment.setAttachmentCategory(category);
+ attachment.setUploadTime(DateUtils.getNowDate());
+ attachment.setUploadBy(SecurityUtils.getUsername());
+
+ Long result = sysTaskAttachmentMapper.insertSysTaskAttachment(attachment);
+ return result > 0 ? attachment.getAttachmentId() : 0L;
+ } catch (Exception e) {
+ throw new RuntimeException("浠庡井淇′笂浼犳枃浠跺け璐ワ細" + e.getMessage());
+ }
+ }
+
+ @Override
+ @Transactional
+ public int deleteAttachment(Long attachmentId) {
+ SysTaskAttachment attachment = sysTaskAttachmentMapper.selectSysTaskAttachmentByAttachmentId(attachmentId);
+ if (attachment == null) {
+ throw new RuntimeException("闄勪欢涓嶅瓨鍦�");
+ }
+
+ try {
+ FileUtils.deleteFile(attachment.getFilePath());
+ } catch (Exception e) {
+ // ignore
+ }
+
+ return sysTaskAttachmentMapper.deleteSysTaskAttachmentByAttachmentId(attachmentId);
+ }
+
+ @Override
+ public SysTaskAttachment getAttachmentById(Long attachmentId) {
+ SysTaskAttachment attachment = sysTaskAttachmentMapper.selectSysTaskAttachmentByAttachmentId(attachmentId);
+ if (attachment != null) {
+ buildAttachmentUrl(attachment);
+ }
+ return attachment;
+ }
+
+ @Override
+ public List<SysTaskAttachment> getAttachmentsByTaskId(Long taskId) {
+ List<SysTaskAttachment> list = sysTaskAttachmentMapper.selectSysTaskAttachmentByTaskId(taskId);
+ if (list != null && !list.isEmpty()) {
+ list.forEach(this::buildAttachmentUrl);
+ }
+ return list;
+ }
+
+ private String saveLocalPath(String fileName, InputStream stream) throws IOException {
+ String baseDir = FileUploadUtils.getDefaultBaseDir();
+ String datePath = DateUtils.datePath();
+ String uploadDir = baseDir + "/task/" + datePath;
+
+ File uploadPath = new File(uploadDir);
+ if (!uploadPath.exists()) {
+ uploadPath.mkdirs();
+ }
+
+ String filePath = uploadDir + "/" + fileName;
+ try (OutputStream os = new FileOutputStream(filePath)) {
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ while ((bytesRead = stream.read(buffer)) != -1) {
+ os.write(buffer, 0, bytesRead);
+ }
+ os.flush();
+ }
+
+ return "/task/" + datePath + "/" + fileName;
+ }
+
+ private String saveLocalPath(String fileName, byte[] fileBytes) throws IOException {
+ String baseDir = FileUploadUtils.getDefaultBaseDir();
+ String datePath = DateUtils.datePath();
+ String uploadDir = baseDir + "/task/" + datePath;
+
+ File uploadPath = new File(uploadDir);
+ if (!uploadPath.exists()) {
+ uploadPath.mkdirs();
+ }
+
+ String filePath = uploadDir + "/" + fileName;
+ File file = new File(filePath);
+ try (FileOutputStream fos = new FileOutputStream(file)) {
+ fos.write(fileBytes);
+ }
+
+ return "/task/" + datePath + "/" + fileName;
+ }
+
+ private byte[] downloadFromUrl(String fileUrl) throws IOException {
+ URL url = new URL(fileUrl);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setConnectTimeout(10000);
+ connection.setReadTimeout(30000);
+
+ try (InputStream inputStream = connection.getInputStream()) {
+ byte[] buffer = new byte[4096];
+ int bytesRead;
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+
+ return outputStream.toByteArray();
+ } finally {
+ connection.disconnect();
+ }
+ }
+
+ private String getFileType(String fileName) {
+ if (StringUtils.isEmpty(fileName)) {
+ return "";
+ }
+ int lastDotIndex = fileName.lastIndexOf(".");
+ if (lastDotIndex > 0 && lastDotIndex < fileName.length() - 1) {
+ return fileName.substring(lastDotIndex + 1).toLowerCase();
+ }
+ return "";
+ }
+
+ @Override
+ public void buildAttachmentUrl(SysTaskAttachment attachment) {
+ if (attachment == null || StringUtils.isEmpty(attachment.getFilePath())) {
+ return;
+ }
+ String baseUrl = imageUrlConfig.getImageUrl();
+ if (!attachment.getFilePath().startsWith("http")) {
+ attachment.setFileUrl(baseUrl + attachment.getFilePath());
+ } else {
+ attachment.setFileUrl(attachment.getFilePath());
+ }
+ }
+
+ @Override
+ public String getCategoryDesc(String category) {
+ if (category == null || category.isEmpty()) {
+ return "鏈垎绫�";
+ }
+ switch (category) {
+ case "1": return "鐭ユ儏鍚屾剰涔�";
+ case "2": return "鐥呬汉璧勬枡";
+ case "3": return "鎿嶄綔璁板綍";
+ case "4": return "鍑鸿溅鍓�";
+ case "5": return "鍑鸿溅鍚�";
+ case "6": return "绯诲畨鍏ㄥ甫";
+ default: return "鍏朵粬";
+ }
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
index a6bca50..d9c04d5 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
@@ -7,9 +7,11 @@
import java.net.HttpURLConnection;
import java.net.URL;
+import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.mapper.*;
+import com.ruoyi.system.service.*;
import com.ruoyi.system.utils.TaskCodeGenerator;
import com.ruoyi.common.config.ImageUrlConfig;
import org.springframework.beans.factory.annotation.Autowired;
@@ -31,12 +33,6 @@
import com.ruoyi.system.domain.SysTaskAssignee;
import com.ruoyi.system.domain.enums.TaskStatus;
import com.ruoyi.system.domain.VehicleInfo;
-import com.ruoyi.system.service.ISysTaskService;
-import com.ruoyi.system.service.ILegacySystemSyncService;
-import com.ruoyi.system.service.ISysTaskEmergencyService;
-import com.ruoyi.system.service.ITaskAttachmentSyncService;
-import com.ruoyi.system.service.IMapService;
-import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.event.TaskCreatedEvent;
import com.ruoyi.system.event.TaskAssignedEvent;
import com.ruoyi.system.event.TaskStatusChangedEvent;
@@ -60,9 +56,6 @@
private SysTaskMapper sysTaskMapper;
@Autowired
- private SysTaskVehicleMapper sysTaskVehicleMapper;
-
- @Autowired
private SysTaskAttachmentMapper sysTaskAttachmentMapper;
@Autowired
@@ -72,19 +65,13 @@
private SysTaskEmergencyMapper sysTaskEmergencyMapper;
@Autowired
- private SysTaskWelfareMapper sysTaskWelfareMapper;
-
- @Autowired
private SysTaskAssigneeMapper sysTaskAssigneeMapper;
- @Autowired
- private VehicleInfoMapper vehicleInfoMapper;
-
@Autowired(required = false)
private ILegacySystemSyncService legacySystemSyncService;
@Autowired
- private ISysTaskEmergencyService sysTaskEmergencyService;
+ private ISysEmergencyTaskService sysEmergencyTaskService;
@Autowired
private ApplicationEventPublisher eventPublisher;
@@ -92,8 +79,8 @@
@Autowired
private ImageUrlConfig imageUrlConfig;
- @Autowired(required = false)
- private ITaskAttachmentSyncService taskAttachmentSyncService;
+ @Autowired
+ private ISysTaskAttachmentService sysTaskAttachmentService;
@Autowired
private SysUserMapper sysUserMapper;
@@ -103,6 +90,15 @@
@Autowired
private ISysConfigService configService;
+
+ @Autowired
+ private ISysTaskAssigneeService sysTaskAssigneeService;
+
+ @Autowired
+ private ISysWelfareTaskService sysWelfareTaskService;
+
+ @Autowired
+ private ISysTaskVehicleService sysTaskVehicleService;
/**
* 鏌ヨ浠诲姟绠$悊
@@ -121,7 +117,7 @@
}
// 鍔犺浇绂忕杞︽墿灞曚俊鎭�
else if ("WELFARE".equals(task.getTaskType())) {
- SysTaskWelfare welfareInfo = sysTaskWelfareMapper.selectSysTaskWelfareByTaskId(taskId);
+ SysTaskWelfare welfareInfo = sysWelfareTaskService.getWelfareInfoByTaskId(taskId);
task.setWelfareInfo(welfareInfo);
}
}
@@ -149,6 +145,11 @@
@Transactional
public int insertSysTask(TaskCreateVO createVO) {
String username = SecurityUtils.getUsername();
+ Long userId = SecurityUtils.getUserId();
+ if(userId==null || userId==0){
+ log.error("insertSysTask 鐢ㄦ埛ID涓虹┖ userName:{}",username);
+ return 0;
+ }
SysTask task = new SysTask();
task.setTaskCode(generateTaskCode());
task.setTaskType(createVO.getTaskType());
@@ -157,7 +158,7 @@
task.setPlannedStartTime(createVO.getPlannedStartTime());
task.setPlannedEndTime(createVO.getPlannedEndTime());
task.setAssigneeId(createVO.getAssigneeId());
- task.setCreatorId(SecurityUtils.getUserId());
+ task.setCreatorId(userId);
// 浼樺厛浣跨敤鍓嶇浼犲叆鐨勯儴闂↖D锛屽鏋滄病鏈夊垯浣跨敤褰撳墠鐢ㄦ埛鐨勯儴闂↖D
task.setDeptId(createVO.getDeptId() != null ? createVO.getDeptId() : SecurityUtils.getDeptId());
task.setCreateBy(username);
@@ -167,123 +168,33 @@
task.setRemark(createVO.getRemark());
task.setDelFlag("0");
- // 璁剧疆閫氱敤鍦板潃鍜屽潗鏍囦俊鎭�
- if (createVO.getDepartureAddress() != null) {
- task.setDepartureAddress(createVO.getDepartureAddress());
- }
- if (createVO.getDestinationAddress() != null) {
- task.setDestinationAddress(createVO.getDestinationAddress());
- }
- if (createVO.getDepartureLongitude() != null) {
- task.setDepartureLongitude(createVO.getDepartureLongitude());
- }
- if (createVO.getDepartureLatitude() != null) {
- task.setDepartureLatitude(createVO.getDepartureLatitude());
- }
- if (createVO.getDestinationLongitude() != null) {
- task.setDestinationLongitude(createVO.getDestinationLongitude());
- }
- if (createVO.getDestinationLatitude() != null) {
- task.setDestinationLatitude(createVO.getDestinationLatitude());
- }
- if (createVO.getEstimatedDistance() != null) {
- task.setEstimatedDistance(createVO.getEstimatedDistance());
- }
-
- // 璁剧疆鎬ユ晳杞繍鐗瑰畾淇℃伅
- if (createVO.getTransferTime() != null) {
- task.setPlannedStartTime(createVO.getTransferTime());
- }
- if (createVO.getTransferDistance() != null) {
- task.setEstimatedDistance(createVO.getTransferDistance());
- }
-
- // 璁剧疆绂忕杞︾壒瀹氫俊鎭�
- if (createVO.getServiceTime() != null) {
- task.setPlannedStartTime(createVO.getServiceTime());
- }
- if (createVO.getStartAddress() != null) {
- task.setDepartureAddress(createVO.getStartAddress());
- }
- if (createVO.getEndAddress() != null) {
- task.setDestinationAddress(createVO.getEndAddress());
- }
- // 璁剧疆绂忕杞﹀叕閲屾暟
- if (createVO.getDistance() != null) {
- task.setEstimatedDistance(createVO.getDistance());
- }
-
- // 鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣锛堝鏋滅己澶憋級
- if (task.getDepartureAddress() != null &&
- (task.getDepartureLongitude() == null || task.getDepartureLatitude() == null) &&
- mapService != null) {
- try {
- Map<String, Double> coords = mapService.geocoding(
- task.getDepartureAddress(),
- extractCityFromAddress(task.getDepartureAddress())
- );
- if (coords != null) {
- task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
- task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
- log.info("鍑哄彂鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
- }
- } catch (Exception e) {
- log.error("鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣澶辫触", e);
- }
- }
-
- // 鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣锛堝鏋滅己澶憋級
- if (task.getDestinationAddress() != null &&
- (task.getDestinationLongitude() == null || task.getDestinationLatitude() == null) &&
- mapService != null) {
- try {
- Map<String, Double> coords = mapService.geocoding(
- task.getDestinationAddress(),
- extractCityFromAddress(task.getDestinationAddress())
- );
- if (coords != null) {
- task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
- task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
- log.info("鐩殑鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
- }
- } catch (Exception e) {
- log.error("鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣澶辫触", e);
- }
- }
+ // 璁剧疆鍦板潃鍜屽潗鏍囦俊鎭�
+ setAddressAndCoordinatesFromVO(task, createVO);
+ // 璁剧疆浠诲姟绫诲瀷鐗瑰畾淇℃伅
+ setTaskTypeSpecificInfo(task, createVO);
+ // 鑷姩濉厖缂哄け鐨凣PS鍧愭爣
+ autoFillMissingGpsCoordinates(task);
int result = sysTaskMapper.insertSysTask(task);
// 淇濆瓨杞﹁締鍏宠仈淇℃伅
if (result > 0 && createVO.getVehicleIds() != null && !createVO.getVehicleIds().isEmpty()) {
- for (Long vehicleId : createVO.getVehicleIds()) {
- SysTaskVehicle taskVehicle = new SysTaskVehicle();
- taskVehicle.setTaskId(task.getTaskId());
- taskVehicle.setVehicleId(vehicleId);
- taskVehicle.setAssignTime(DateUtils.getNowDate());
- taskVehicle.setAssignBy(username);
- taskVehicle.setStatus("ASSIGNED");
- taskVehicle.setCreateBy(username);
- taskVehicle.setCreateTime(DateUtils.getNowDate());
- taskVehicle.setUpdateBy(username);
- taskVehicle.setUpdateTime(DateUtils.getNowDate());
-
- sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
- }
+ sysTaskVehicleService.saveTaskVehicles(task.getTaskId(), createVO.getVehicleIds(), username);
}
// 淇濆瓨鎵ц浜哄憳淇℃伅锛堝寘鍚鑹茬被鍨嬶級
if (result > 0 && createVO.getAssignees() != null && !createVO.getAssignees().isEmpty()) {
- saveTaskAssignees(task.getTaskId(), createVO.getAssignees(),username);
+ sysTaskAssigneeService.saveTaskAssignees(task.getTaskId(), createVO.getAssignees(),username);
}
// 淇濆瓨鎬ユ晳杞繍鎵╁睍淇℃伅
if (result > 0 && "EMERGENCY_TRANSFER".equals(createVO.getTaskType())) {
- saveEmergencyInfo(task.getTaskId(),username, createVO,null,null,null);
+ sysEmergencyTaskService.saveEmergencyInfo(task.getTaskId(), username, createVO, null, null, null);
}
// 淇濆瓨绂忕杞︽墿灞曚俊鎭�
if (result > 0 && "WELFARE".equals(createVO.getTaskType())) {
- saveWelfareInfo(task.getTaskId(),SecurityUtils.getUsername(), createVO);
+ sysWelfareTaskService.saveWelfareInfo(task.getTaskId(), SecurityUtils.getUsername(), createVO);
}
// 璁板綍鎿嶄綔鏃ュ織
@@ -306,22 +217,7 @@
// 鍙戝竷浠诲姟鍒嗛厤浜嬩欢
if (result > 0 && createVO.getAssignees() != null && !createVO.getAssignees().isEmpty()) {
- List<Long> assigneeIds = createVO.getAssignees().stream()
- .map(assignee -> assignee.getUserId())
- .collect(Collectors.toList());
- List<String> assigneeNames = createVO.getAssignees().stream()
- .map(assignee -> assignee.getUserName())
- .collect(Collectors.toList());
-
- eventPublisher.publishEvent(new TaskAssignedEvent(
- this,
- task.getTaskId(),
- task.getTaskCode(),
- assigneeIds,
- assigneeNames,
- SecurityUtils.getUserId(),
- SecurityUtils.getUsername()
- ));
+ this.sendTaskAssigneeEvent(createVO,task,SecurityUtils.getUserId(),SecurityUtils.getUsername());
}
// 寮傛鍚屾鎬ユ晳杞繍浠诲姟鍒版棫绯荤粺
@@ -380,38 +276,15 @@
- // 璁剧疆閫氱敤鍦板潃鍜屽潗鏍囦俊鎭�
- if (createVO.getDepartureAddress() != null) {
- task.setDepartureAddress(createVO.getDepartureAddress());
- }
- if (createVO.getDestinationAddress() != null) {
- task.setDestinationAddress(createVO.getDestinationAddress());
- }
- if (createVO.getDepartureLongitude() != null) {
- task.setDepartureLongitude(createVO.getDepartureLongitude());
- }
- if (createVO.getDepartureLatitude() != null) {
- task.setDepartureLatitude(createVO.getDepartureLatitude());
- }
- if (createVO.getDestinationLongitude() != null) {
- task.setDestinationLongitude(createVO.getDestinationLongitude());
- }
- if (createVO.getDestinationLatitude() != null) {
- task.setDestinationLatitude(createVO.getDestinationLatitude());
- }
- if (createVO.getEstimatedDistance() != null) {
- task.setEstimatedDistance(createVO.getEstimatedDistance());
- }
-
- // 璁剧疆鎬ユ晳杞繍鐗瑰畾淇℃伅
+ // 璁剧疆鍦板潃鍜屽潗鏍囦俊鎭�
+ setAddressAndCoordinatesFromVO(task, createVO);
+ // 璁剧疆浠诲姟绫诲瀷鐗瑰畾淇℃伅锛堟敞锛歩nsertTask浣跨敤plannedStartTime鑰岄潪serviceTime锛�
if (createVO.getTransferTime() != null) {
task.setPlannedStartTime(createVO.getTransferTime());
}
if (createVO.getTransferDistance() != null) {
task.setEstimatedDistance(createVO.getTransferDistance());
}
-
- // 璁剧疆绂忕杞︾壒瀹氫俊鎭�
if (createVO.getPlannedStartTime() != null) {
task.setPlannedStartTime(createVO.getPlannedStartTime());
}
@@ -421,82 +294,33 @@
if (createVO.getEndAddress() != null) {
task.setDestinationAddress(createVO.getEndAddress());
}
- // 璁剧疆绂忕杞﹀叕閲屾暟
if (createVO.getDistance() != null) {
task.setEstimatedDistance(createVO.getDistance());
}
-
- // 鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣锛堝鏋滅己澶憋級
- if (task.getDepartureAddress() != null &&
- (task.getDepartureLongitude() == null || task.getDepartureLatitude() == null) &&
- mapService != null) {
- try {
- Map<String, Double> coords = mapService.geocoding(
- task.getDepartureAddress(),
- extractCityFromAddress(task.getDepartureAddress())
- );
- if (coords != null) {
- task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
- task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
- log.info("鍑哄彂鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
- }
- } catch (Exception e) {
- log.error("鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣澶辫触", e);
- }
- }
-
- // 鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣锛堝鏋滅己澶憋級
- if (task.getDestinationAddress() != null &&
- (task.getDestinationLongitude() == null || task.getDestinationLatitude() == null) &&
- mapService != null) {
- try {
- Map<String, Double> coords = mapService.geocoding(
- task.getDestinationAddress(),
- extractCityFromAddress(task.getDestinationAddress())
- );
- if (coords != null) {
- task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
- task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
- log.info("鐩殑鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
- }
- } catch (Exception e) {
- log.error("鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣澶辫触", e);
- }
- }
+ // 鑷姩濉厖缂哄け鐨凣PS鍧愭爣
+ autoFillMissingGpsCoordinates(task);
int result = sysTaskMapper.insertSysTask(task);
// 淇濆瓨杞﹁締鍏宠仈淇℃伅
if (result > 0 && createVO.getVehicleIds() != null && !createVO.getVehicleIds().isEmpty()) {
- for (Long vehicleId : createVO.getVehicleIds()) {
- SysTaskVehicle taskVehicle = new SysTaskVehicle();
- taskVehicle.setTaskId(task.getTaskId());
- taskVehicle.setVehicleId(vehicleId);
- taskVehicle.setAssignTime(updateTime);
- taskVehicle.setAssignBy(userName);
- taskVehicle.setStatus("ASSIGNED");
- taskVehicle.setCreateBy(userName);
- taskVehicle.setCreateTime(createTime);
- taskVehicle.setUpdateBy(userName);
- taskVehicle.setUpdateTime(updateTime);
-
- sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
- }
+ sysTaskVehicleService.saveTaskVehicles(task.getTaskId(), createVO.getVehicleIds(), userName,
+ updateTime, createTime, updateTime);
}
// 淇濆瓨鎵ц浜哄憳淇℃伅锛堝寘鍚鑹茬被鍨嬶級
if (result > 0 && createVO.getAssignees() != null && !createVO.getAssignees().isEmpty()) {
- saveTaskAssignees(task.getTaskId(), createVO.getAssignees(),userName);
+ sysTaskAssigneeService.saveTaskAssignees(task.getTaskId(), createVO.getAssignees(),userName);
}
// 淇濆瓨鎬ユ晳杞繍鎵╁睍淇℃伅
if (result > 0 && "EMERGENCY_TRANSFER".equals(createVO.getTaskType())) {
- saveEmergencyInfo(task.getTaskId(),userName, createVO, serviceOrderId, dispatchOrderId, serviceOrdNo);
+ sysEmergencyTaskService.saveEmergencyInfo(task.getTaskId(), userName, createVO, serviceOrderId, dispatchOrderId, serviceOrdNo);
}
// 淇濆瓨绂忕杞︽墿灞曚俊鎭�
if (result > 0 && "WELFARE".equals(createVO.getTaskType())) {
- saveWelfareInfo(task.getTaskId(),userName, createVO);
+ sysWelfareTaskService.saveWelfareInfo(task.getTaskId(), userName, createVO);
}
// 璁板綍鎿嶄綔鏃ュ織
@@ -519,14 +343,23 @@
// 鍙戝竷浠诲姟鍒嗛厤浜嬩欢
if (result > 0 && createVO.getAssignees() != null && !createVO.getAssignees().isEmpty()) {
- List<Long> assigneeIds = createVO.getAssignees().stream()
+ this.sendTaskAssigneeEvent(createVO,task,userId,userName);
+ }
+
+
+
+ return result;
+ }
+
+ private void sendTaskAssigneeEvent(TaskCreateVO createVO,SysTask task,Long userId,String userName){
+ List<Long> assigneeIds = createVO.getAssignees().stream()
.map(assignee -> assignee.getUserId())
.collect(Collectors.toList());
- List<String> assigneeNames = createVO.getAssignees().stream()
+ List<String> assigneeNames = createVO.getAssignees().stream()
.map(assignee -> assignee.getUserName())
.collect(Collectors.toList());
-
- eventPublisher.publishEvent(new TaskAssignedEvent(
+
+ eventPublisher.publishEvent(new TaskAssignedEvent(
this,
task.getTaskId(),
task.getTaskCode(),
@@ -534,12 +367,7 @@
assigneeNames,
userId,
userName
- ));
- }
-
-
-
- return result;
+ ));
}
/**
@@ -555,6 +383,7 @@
if (oldTask == null) {
throw new RuntimeException("浠诲姟涓嶅瓨鍦�");
}
+ Long userId = SecurityUtils.getUserId();
String userName = SecurityUtils.getUsername();
SysTask task = new SysTask();
@@ -609,7 +438,7 @@
if (coords != null) {
task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
- log.info("鍑哄彂鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+// log.info("鍑哄彂鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
}
} catch (Exception e) {
log.error("鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣澶辫触", e);
@@ -630,7 +459,7 @@
if (coords != null) {
task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
- log.info("鐩殑鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+// log.info("鐩殑鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
}
} catch (Exception e) {
log.error("鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣澶辫触", e);
@@ -638,40 +467,16 @@
}
}
// 鐢ㄤ簬璺熻釜鏄惁闇�瑕侀噸鏂板悓姝ワ紙杞﹁締銆佷汉鍛樸�佸湴鍧�銆佹垚浜や环鍙樻洿锛�
- boolean needResync = true;
+ boolean needResync = false;
int result = sysTaskMapper.updateSysTask(task);
// 鏇存柊杞﹁締鍏宠仈
if (result > 0 && updateVO.getVehicleIds() != null && !updateVO.getVehicleIds().isEmpty()) {
- // 鏌ヨ鐜版湁鐨勮溅杈嗗叧鑱�
- List<SysTaskVehicle> existingVehicles = sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(updateVO.getTaskId());
- List<Long> existingVehicleIds = existingVehicles.stream()
- .map(SysTaskVehicle::getVehicleId)
- .collect(Collectors.toList());
-
- // 姣旇緝鏂版棫杞﹁締ID鍒楄〃锛屽垽鏂槸鍚︽湁鍙樺寲
- boolean vehiclesChanged = !new HashSet<>(existingVehicleIds).equals(new HashSet<>(updateVO.getVehicleIds()));
-
- // 鍙湁杞﹁締鍙戠敓鍙樺寲鏃舵墠鏇存柊
+ boolean vehiclesChanged = sysTaskVehicleService.updateTaskVehicles(
+ updateVO.getTaskId(), updateVO.getVehicleIds(), userName);
if (vehiclesChanged) {
- // 鍒犻櫎鏃х殑杞﹁締鍏宠仈
- sysTaskVehicleMapper.deleteSysTaskVehicleByTaskId(updateVO.getTaskId());
-
- // 娣诲姞鏂扮殑杞﹁締鍏宠仈
- Date now = DateUtils.getNowDate();
- String currentUser = userName;
- for (Long vehicleId : updateVO.getVehicleIds()) {
- SysTaskVehicle taskVehicle = new SysTaskVehicle();
- taskVehicle.setTaskId(updateVO.getTaskId());
- taskVehicle.setVehicleId(vehicleId);
- taskVehicle.setAssignTime(now);
- taskVehicle.setAssignBy(currentUser);
- taskVehicle.setCreateTime(now);
- sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
- }
-
// 鏍囪闇�瑕侀噸鏂板悓姝ワ紙杞﹁締鍙樻洿锛�
needResync = true;
}
@@ -679,29 +484,9 @@
// 鏇存柊鎵ц浜哄憳锛堟娴嬩汉鍛樺彉鏇达級
if (result > 0 && updateVO.getAssignees() != null) {
- // 鏌ヨ鐜版湁鐨勬墽琛屼汉鍛�
- List<SysTaskAssignee> existingAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(updateVO.getTaskId());
- List<Long> existingAssigneeIds = existingAssignees.stream()
- .map(SysTaskAssignee::getUserId)
- .collect(Collectors.toList());
-
- List<Long> newAssigneeIds = updateVO.getAssignees().stream()
- .map(TaskCreateVO.AssigneeInfo::getUserId)
- .collect(Collectors.toList());
-
- // 姣旇緝鏂版棫鎵ц浜哄憳ID鍒楄〃锛屽垽鏂槸鍚︽湁鍙樺寲
- boolean assigneesChanged = !new HashSet<>(existingAssigneeIds).equals(new HashSet<>(newAssigneeIds));
-
- // 鍙湁鎵ц浜哄憳鍙戠敓鍙樺寲鏃舵墠鏇存柊
+ boolean assigneesChanged = sysTaskAssigneeService.updateTaskAssignees(
+ updateVO.getTaskId(), updateVO.getAssignees(), userName);
if (assigneesChanged) {
- // 鍒犻櫎鏃х殑鎵ц浜哄憳鍏宠仈
- sysTaskAssigneeMapper.deleteSysTaskAssigneeByTaskId(updateVO.getTaskId());
-
- // 娣诲姞鏂扮殑鎵ц浜哄憳鍏宠仈
- if (!updateVO.getAssignees().isEmpty()) {
- saveTaskAssignees(updateVO.getTaskId(), updateVO.getAssignees(), userName);
- }
-
// 鏍囪闇�瑕侀噸鏂板悓姝ワ紙浜哄憳鍙樻洿锛�
needResync = true;
}
@@ -709,70 +494,35 @@
// 鏇存柊鎬ユ晳杞繍鎵╁睍淇℃伅锛堟娴嬪湴鍧�鍜屾垚浜や环鍙樻洿锛�
if (result > 0 && "EMERGENCY_TRANSFER".equals(oldTask.getTaskType())) {
- // 鑾峰彇鏃х殑鎬ユ晳杞繍淇℃伅
SysTaskEmergency oldEmergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(updateVO.getTaskId());
-
- // 妫�娴嬭浆鍑哄尰闄㈠湴鍧�鍙樻洿
- boolean hospitalOutAddressChanged = false;
- if (updateVO.getHospitalOut() != null && updateVO.getHospitalOut().getAddress() != null
- && oldEmergency != null
- && !updateVO.getHospitalOut().getAddress().equals(oldEmergency.getHospitalOutAddress())) {
- hospitalOutAddressChanged = true;
- }
-
- // 妫�娴嬭浆鍏ュ尰闄㈠湴鍧�鍙樻洿
- boolean hospitalInAddressChanged = false;
- if (updateVO.getHospitalIn() != null && updateVO.getHospitalIn().getAddress() != null
- && oldEmergency != null
- && !updateVO.getHospitalIn().getAddress().equals(oldEmergency.getHospitalInAddress())) {
- hospitalInAddressChanged = true;
- }
-
- // 妫�娴嬫垚浜や环鍙樻洿
- boolean transferPriceChanged = false;
- if (updateVO.getPrice() != null
- && oldEmergency != null
- && oldEmergency.getTransferPrice() != null
- && updateVO.getPrice().compareTo(oldEmergency.getTransferPrice()) != 0) {
- transferPriceChanged = true;
- }
-
- ;
-
- // 鏇存柊鎬ユ晳杞繍淇℃伅
- if (updateVO.getHospitalOut() != null || updateVO.getHospitalIn() != null || updateVO.getPatient() != null) {
- updateEmergencyInfoFromCreateVO(updateVO.getTaskId(), updateVO, userName);
- }
-
- // 濡傛灉鍦板潃鎴栨垚浜や环鍙戠敓鍙樻洿锛屾爣璁伴渶瑕侀噸鏂板悓姝�
- if (hospitalOutAddressChanged || hospitalInAddressChanged || transferPriceChanged) {
- needResync = true;
- }
+ sysEmergencyTaskService.updateEmergencyInfoFromUpdateVO(oldEmergency, updateVO, userName);
+ sysEmergencyTaskService.markNeedResyncIfNecessary(updateVO.getTaskId(), oldTask, updateVO, updateFromLegacy);
}
// 鏇存柊绂忕杞︽墿灞曚俊鎭�
if (result > 0 && "WELFARE".equals(oldTask.getTaskType())) {
if (updateVO.getPassenger() != null || updateVO.getStartAddress() != null || updateVO.getEndAddress() != null) {
- updateWelfareInfoFromCreateVO(updateVO.getTaskId(), updateVO, userName);
+ sysWelfareTaskService.updateWelfareInfo(updateVO.getTaskId(), updateVO, userName);
}
}
// 濡傛灉鏄�ユ晳杞繍浠诲姟涓旀湁鍙樻洿锛屾爣璁伴渶瑕侀噸鏂板悓姝�
if (result > 0 && "EMERGENCY_TRANSFER".equals(oldTask.getTaskType()) && needResync && !updateFromLegacy) {
- try {
- sysTaskEmergencyService.markNeedResync(updateVO.getTaskId());
- } catch (Exception e) {
- // 鏍囪澶辫触涓嶅奖鍝嶄富娴佺▼
- }
+ sysEmergencyTaskService.markNeedResyncIfNecessary(updateVO.getTaskId(), oldTask, updateVO, updateFromLegacy);
}
// 璁板綍鎿嶄綔鏃ュ織
if (result > 0) {
recordTaskLog(updateVO.getTaskId(), "UPDATE", "鏇存柊浠诲姟",
buildTaskDescription(oldTask), buildTaskDescription(task),
- SecurityUtils.getUserId(), userName);
+ userId, userName);
}
-
+
+ if(result > 0 && oldTask.getTaskStatus().equals(TaskStatus.PENDING.getCode()) && updateVO.getAssignees() != null && !updateVO.getAssignees().isEmpty()){
+
+ this.sendTaskAssigneeEvent(updateVO,oldTask,userId,userName);
+ }
+
return result;
}
@@ -793,15 +543,25 @@
@Override
public int updateTask(TaskUpdateVO updateVO, String serviceOrderId, String dispatchOrderId, String serviceOrdNo,
Long userId, String userName, Long deptId, Date createTime, Date updateTime) {
+// log.info("寮�濮嬫洿鏂颁换鍔� ServiceOrdID: {} , dispatchOrdId:{}", serviceOrderId,dispatchOrderId);
// 閫氳繃鏃х郴缁熸湇鍔″崟ID鏌ユ壘浠诲姟
SysTaskEmergency taskEmergency = sysTaskEmergencyMapper.selectByLegacyServiceOrdId(Long.parseLong(serviceOrderId));
Long taskId = taskEmergency.getTaskId();
updateVO.setTaskId(taskId);
SysTask task = new SysTask();
task.setTaskId(taskId);
+ if(updateVO.getTaskStatus()!=null){
+ task.setTaskStatus(updateVO.getTaskStatus());
+ }
task.setTaskDescription(updateVO.getTaskDescription());
task.setPlannedStartTime(updateVO.getPlannedStartTime());
task.setPlannedEndTime(updateVO.getPlannedEndTime());
+ if(updateVO.getActualStartTime() != null) {
+ task.setActualStartTime(updateVO.getActualStartTime());
+ }
+ if(updateVO.getActualEndTime() != null) {
+ task.setActualEndTime(updateVO.getActualEndTime());
+ }
task.setAssigneeId(updateVO.getAssigneeId());
task.setUpdateBy(userName);
task.setUpdateTime(DateUtils.getNowDate());
@@ -842,7 +602,7 @@
if (coords != null) {
task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
- log.info("鍑哄彂鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+// log.info("鍑哄彂鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
}
} catch (Exception e) {
log.error("鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣澶辫触", e);
@@ -862,7 +622,7 @@
if (coords != null) {
task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
- log.info("鐩殑鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+// log.info("鐩殑鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
}
} catch (Exception e) {
log.error("鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣澶辫触", e);
@@ -870,62 +630,21 @@
}
int result = sysTaskMapper.updateSysTask(task);
-
+// log.info("鏇存柊杞繍浠诲姟锛孲erviceOrdID:{},dispatchOrderId:{},result:{}",serviceOrderId,dispatchOrderId,result);
+// log.info("鏇存柊浠诲姟杞﹁締 ServiceOrdID: {} , dispatchOrdId:{},VehicleIds:{}", serviceOrderId,dispatchOrderId,updateVO.getVehicleIds());
// 鏇存柊杞﹁締鍏宠仈
if (result > 0 && updateVO.getVehicleIds() != null && !updateVO.getVehicleIds().isEmpty()) {
- // 鏌ヨ鐜版湁鐨勮溅杈嗗叧鑱�
- List<SysTaskVehicle> existingVehicles = sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId);
- List<Long> existingVehicleIds = existingVehicles.stream()
- .map(SysTaskVehicle::getVehicleId)
- .collect(Collectors.toList());
-
- // 姣旇緝鏂版棫杞﹁締ID鍒楄〃锛屽垽鏂槸鍚︽湁鍙樺寲
- boolean vehiclesChanged = !new HashSet<>(existingVehicleIds).equals(new HashSet<>(updateVO.getVehicleIds()));
-
- // 鍙湁杞﹁締鍙戠敓鍙樺寲鏃舵墠鏇存柊
- if (vehiclesChanged) {
- // 鍒犻櫎鏃х殑杞﹁締鍏宠仈
- sysTaskVehicleMapper.deleteSysTaskVehicleByTaskId(taskId);
-
- // 娣诲姞鏂扮殑杞﹁締鍏宠仈
- Date now = DateUtils.getNowDate();
- for (Long vehicleId : updateVO.getVehicleIds()) {
- SysTaskVehicle taskVehicle = new SysTaskVehicle();
- taskVehicle.setTaskId(taskId);
- taskVehicle.setVehicleId(vehicleId);
- taskVehicle.setAssignTime(now);
- taskVehicle.setAssignBy(userName);
- taskVehicle.setCreateTime(now);
- sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
- }
- }
+// log.info("鏇存柊杞﹁締鍏宠仈 ServiceOrdID:{},dispatchOrderId:{}",serviceOrderId,dispatchOrderId);
+ sysTaskVehicleService.updateTaskVehicles(taskId, updateVO.getVehicleIds(), userName);
}
-
+
+ Boolean hasAssignee = updateVO.getAssigneeId() != null && !updateVO.getAssignees().isEmpty() ;
+// log.info("鏇存柊杞繍浠诲姟锛孲erviceOrdID:{},dispatchOrderId:{},result:{}, hasAssignee:{}",serviceOrderId,dispatchOrderId,result,hasAssignee);
+
// 鏇存柊鎵ц浜哄憳锛堟娴嬩汉鍛樺彉鏇达級
- if (result > 0 && updateVO.getAssignees() != null) {
- // 鏌ヨ鐜版湁鐨勬墽琛屼汉鍛�
- List<SysTaskAssignee> existingAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
- List<Long> existingAssigneeIds = existingAssignees.stream()
- .map(SysTaskAssignee::getUserId)
- .collect(Collectors.toList());
-
- List<Long> newAssigneeIds = updateVO.getAssignees().stream()
- .map(TaskCreateVO.AssigneeInfo::getUserId)
- .collect(Collectors.toList());
-
- // 姣旇緝鏂版棫鎵ц浜哄憳ID鍒楄〃锛屽垽鏂槸鍚︽湁鍙樺寲
- boolean assigneesChanged = !new HashSet<>(existingAssigneeIds).equals(new HashSet<>(newAssigneeIds));
-
- // 鍙湁鎵ц浜哄憳鍙戠敓鍙樺寲鏃舵墠鏇存柊
- if (assigneesChanged) {
- // 鍒犻櫎鏃х殑鎵ц浜哄憳鍏宠仈
- sysTaskAssigneeMapper.deleteSysTaskAssigneeByTaskId(taskId);
-
- // 娣诲姞鏂扮殑鎵ц浜哄憳鍏宠仈
- if (!updateVO.getAssignees().isEmpty()) {
- saveTaskAssignees(taskId, updateVO.getAssignees(), userName);
- }
- }
+ if (result > 0 && hasAssignee) {
+// log.info("鏇存柊鎵ц浜哄憳 ServiceOrdID:{},dispatchOrderId:{}",serviceOrderId,dispatchOrderId);
+ sysTaskAssigneeService.updateTaskAssignees(taskId, updateVO.getAssignees(), userName);
}
// 鏇存柊鎬ユ晳杞繍鎵╁睍淇℃伅
@@ -936,15 +655,28 @@
}
if (dispatchOrderId != null) {
taskEmergency.setLegacyDispatchOrdId(Long.parseLong(dispatchOrderId));
+ taskEmergency.setLegacyDispatchOrdId(Long.parseLong(dispatchOrderId));
+ taskEmergency.setDispatchSyncStatus(2);
+ taskEmergency.setDispatchSyncTime(new Date());
+ taskEmergency.setDispatchSyncErrorMsg("鏃х郴缁熷悓姝ヨ繃鏉�");
}
if (serviceOrdNo != null) {
taskEmergency.setLegacyServiceOrdNo(serviceOrdNo);
}
-
+ taskEmergency.setUpdateTime(DateUtils.getNowDate());
+
+ Boolean hasEmergencyInfo = updateVO.getHospitalOut() != null || updateVO.getHospitalIn() != null || updateVO.getPatient() != null;
+// log.info("鏇存柊杞繍浠诲姟淇℃伅 serviceOrdID:{},dispatchOrderId:{} hasEmergencyInfo:{}",serviceOrderId,
+// dispatchOrderId,hasEmergencyInfo);
+
// 浣跨敤TaskCreateVO鐨勫瓧娈垫潵鏇存柊鎬ユ晳杞繍淇℃伅
- if (updateVO.getHospitalOut() != null || updateVO.getHospitalIn() != null || updateVO.getPatient() != null) {
- updateEmergencyInfoFromCreateVO(taskId, updateVO, userName);
+ if (hasEmergencyInfo) {
+ sysEmergencyTaskService.updateEmergencyInfoFromCreateVO(taskEmergency, updateVO, userName);
}
+ }
+
+ if(updateVO.getTaskStatus()!=null && updateVO.getTaskStatus().equals(TaskStatus.PENDING.getCode()) && updateVO.getAssignees()!=null && !updateVO.getAssignees().isEmpty()){
+ this.sendTaskAssigneeEvent(updateVO,task,userId,userName);
}
return result;
@@ -1128,39 +860,7 @@
@Override
@Transactional
public Long uploadAttachment(Long taskId, MultipartFile file, String category) {
- try {
- // 涓婁紶鏂囦欢锛岃繑鍥炵浉瀵硅矾寰勶紙濡傦細/task/2025/01/15/xxx.jpg锛�
- String fileName = category+"_"+System.currentTimeMillis()+"_"+file.getOriginalFilename();
-
- fileName=saveLocalPath(fileName,file.getInputStream());
-
- SysTaskAttachment attachment = new SysTaskAttachment();
- attachment.setTaskId(taskId);
- attachment.setFileName(file.getOriginalFilename());
- // 淇濆瓨鐩稿璺緞锛屼笉鍖呭惈 baseDir
- attachment.setFilePath(fileName);
- attachment.setFileSize(file.getSize());
- attachment.setFileType(getFileType(file.getOriginalFilename()));
- attachment.setAttachmentCategory(category);
- attachment.setUploadTime(DateUtils.getNowDate());
- attachment.setUploadBy(SecurityUtils.getUsername());
-
- Long result = sysTaskAttachmentMapper.insertSysTaskAttachment(attachment);
-
- // 璁板綍鎿嶄綔鏃ュ織
- if (result > 0) {
- String categoryDesc = getCategoryDesc(category);
- recordTaskLog(taskId, "UPDATE", "涓婁紶闄勪欢", null,
- "涓婁紶鏂囦欢锛�" + file.getOriginalFilename() + "(鍒嗙被锛�" + categoryDesc + ")",
- SecurityUtils.getUserId(), SecurityUtils.getUsername());
-
-
- }
-
- return attachment.getAttachmentId();
- } catch (IOException e) {
- throw new RuntimeException("鏂囦欢涓婁紶澶辫触锛�" + e.getMessage());
- }
+ return sysTaskAttachmentService.uploadAttachment(taskId, file, category);
}
/**
@@ -1175,132 +875,9 @@
@Override
@Transactional
public Long uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category) {
- try {
- // 浠庡井淇℃湇鍔″櫒涓嬭浇鏂囦欢
- String wechatUrl = String.format(
- "https://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s",
- accessToken, mediaId
- );
-
- byte[] fileBytes = downloadFromUrl(wechatUrl);
- if (fileBytes == null || fileBytes.length == 0) {
- throw new RuntimeException("浠庡井淇′笅杞芥枃浠跺け璐�");
- }
-
- // 鐢熸垚鏂囦欢鍚嶏紙浣跨敤mediaId浣滀负鏂囦欢鍚嶇殑涓�閮ㄥ垎锛�
- String fileName = "wx_" + mediaId.substring(0, Math.min(20, mediaId.length())) + "_" + System.currentTimeMillis() + ".jpg";
-
- // 淇濆瓨鍒版湰鍦�
- String relativeFilePath = saveLocalPath(fileName, fileBytes);
-
- // 淇濆瓨闄勪欢璁板綍
- SysTaskAttachment attachment = new SysTaskAttachment();
- attachment.setTaskId(taskId);
- attachment.setFileName(fileName);
- // 淇濆瓨鐩稿璺緞
- attachment.setFilePath(relativeFilePath);
- attachment.setFileSize((long) fileBytes.length);
- attachment.setFileType("jpg");
- attachment.setAttachmentCategory(category);
- attachment.setUploadTime(DateUtils.getNowDate());
- attachment.setUploadBy(SecurityUtils.getUsername());
-
- Long result = sysTaskAttachmentMapper.insertSysTaskAttachment(attachment);
-
- // 璁板綍鎿嶄綔鏃ュ織
- if (result > 0) {
- String categoryDesc = getCategoryDesc(category);
- recordTaskLog(taskId, "UPDATE", "涓婁紶闄勪欢", null,
- "閫氳繃寰俊涓婁紶鏂囦欢锛�" + fileName + "(鍒嗙被锛�" + categoryDesc + ")",
- SecurityUtils.getUserId(), SecurityUtils.getUsername());
-
-
- }
-
- return attachment.getAttachmentId();
- } catch (Exception e) {
- throw new RuntimeException("浠庡井淇′笂浼犳枃浠跺け璐ワ細" + e.getMessage());
- }
+ return sysTaskAttachmentService.uploadAttachmentFromWechat(taskId, accessToken, mediaId, category);
}
- private static String saveLocalPath(String fileName, byte[] fileBytes) throws IOException {
- String baseDir = FileUploadUtils.getDefaultBaseDir();
- String datePath = DateUtils.datePath();
- String uploadDir = baseDir + "/task/" + datePath;
-
- // 鍒涘缓鐩綍
- File uploadPath = new File(uploadDir);
- if (!uploadPath.exists()) {
- uploadPath.mkdirs();
- }
-
- // 淇濆瓨鏂囦欢
- String filePath = uploadDir + "/" + fileName;
- File file = new File(filePath);
- try (FileOutputStream fos = new FileOutputStream(file)) {
- fos.write(fileBytes);
- }
-
- // 鐢熸垚鐩稿璺緞锛堜笉鍖呭惈baseDir锛�
- String relativeFilePath = "/task/" + datePath + "/" + fileName;
- return relativeFilePath;
- }
-
- private String saveLocalPath(String fileName,InputStream stream){
- String baseDir = FileUploadUtils.getDefaultBaseDir();
- String datePath = DateUtils.datePath();
- String uploadDir = baseDir + "/task/" + datePath;
-
- // 鍒涘缓鐩綍
- File uploadPath = new File(uploadDir);
- if (!uploadPath.exists()) {
- uploadPath.mkdirs();
- }
-
- // 淇濆瓨鏂囦欢
- String filePath = uploadDir + "/" + fileName;
- //灏唅nputstream鍐欏叆鏂囦欢
- try (OutputStream os = new FileOutputStream(filePath)) {
- byte[] buffer = new byte[1024]; // 缂撳啿鍖猴紝鍑忓皯 IO 娆℃暟
- int bytesRead;
- // 寰幆璇诲彇杈撳叆娴佷腑鐨勬暟鎹紝鍐欏叆杈撳嚭娴�
- while ((bytesRead = stream.read(buffer)) != -1) {
- os.write(buffer, 0, bytesRead);
- }
- os.flush(); // 寮哄埗鍒锋柊缂撳啿鍖猴紝纭繚鏁版嵁鍐欏叆鏂囦欢
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- // 鐢熸垚鐩稿璺緞锛堜笉鍖呭惈baseDir锛�
- String relativeFilePath = "/task/" + datePath + "/" + fileName;
- return relativeFilePath;
- }
-
- /**
- * 浠� URL 涓嬭浇鏂囦欢
- */
- private byte[] downloadFromUrl(String fileUrl) throws IOException {
- URL url = new URL(fileUrl);
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- connection.setRequestMethod("GET");
- connection.setConnectTimeout(10000);
- connection.setReadTimeout(30000);
-
- try (InputStream inputStream = connection.getInputStream()) {
- byte[] buffer = new byte[4096];
- int bytesRead;
- java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
-
- while ((bytesRead = inputStream.read(buffer)) != -1) {
- outputStream.write(buffer, 0, bytesRead);
- }
-
- return outputStream.toByteArray();
- } finally {
- connection.disconnect();
- }
- }
/**
* 鍒犻櫎浠诲姟闄勪欢
@@ -1311,28 +888,7 @@
@Override
@Transactional
public int deleteAttachment(Long attachmentId) {
- SysTaskAttachment attachment = sysTaskAttachmentMapper.selectSysTaskAttachmentByAttachmentId(attachmentId);
- if (attachment == null) {
- throw new RuntimeException("闄勪欢涓嶅瓨鍦�");
- }
-
- // 鍒犻櫎鐗╃悊鏂囦欢
- try {
- FileUtils.deleteFile(attachment.getFilePath());
- } catch (Exception e) {
- // 蹇界暐鏂囦欢鍒犻櫎澶辫触
- }
-
- int result = sysTaskAttachmentMapper.deleteSysTaskAttachmentByAttachmentId(attachmentId);
-
- // 璁板綍鎿嶄綔鏃ュ織
- if (result > 0) {
- recordTaskLog(attachment.getTaskId(), "UPDATE", "鍒犻櫎闄勪欢",
- "鍒犻櫎鏂囦欢锛�" + attachment.getFileName(), null,
- SecurityUtils.getUserId(), SecurityUtils.getUsername());
- }
-
- return result;
+ return sysTaskAttachmentService.deleteAttachment(attachmentId);
}
/**
@@ -1343,17 +899,12 @@
*/
@Override
public SysTaskAttachment getAttachmentById(Long attachmentId) {
- SysTaskAttachment attachment = sysTaskAttachmentMapper.selectSysTaskAttachmentByAttachmentId(attachmentId);
- if (attachment != null) {
- // 鎷兼帴瀹屾暣URL
- buildAttachmentUrl(attachment);
- }
- return attachment;
+ return sysTaskAttachmentService.getAttachmentById(attachmentId);
}
@Override
public List<SysTaskAttachment> getAttachmentsByTaskId(Long taskId) {
- return sysTaskAttachmentMapper.selectSysTaskAttachmentByTaskId(taskId);
+ return sysTaskAttachmentService.getAttachmentsByTaskId(taskId);
}
/**
@@ -1367,21 +918,7 @@
@Override
@Transactional
public int assignVehicleToTask(Long taskId, Long vehicleId, String remark,Long userId,String userName) {
- // 妫�鏌ユ槸鍚﹀凡缁忓垎閰�
- int exists = sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
- if (exists > 0) {
- throw new RuntimeException("杞﹁締宸茬粡鍒嗛厤缁欒浠诲姟");
- }
-
- SysTaskVehicle taskVehicle = new SysTaskVehicle();
- taskVehicle.setTaskId(taskId);
- taskVehicle.setVehicleId(vehicleId);
- taskVehicle.setAssignTime(DateUtils.getNowDate());
- taskVehicle.setAssignBy(userName);
- taskVehicle.setStatus("ASSIGNED");
- taskVehicle.setRemark(remark);
-
- int result = sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
+ int result = sysTaskVehicleService.assignVehicleToTask(taskId, vehicleId, remark, userId, userName);
// 璁板綍鎿嶄綔鏃ュ織
if (result > 0) {
@@ -1403,7 +940,7 @@
@Override
@Transactional
public int unassignVehicleFromTask(Long taskId, Long vehicleId) {
- int result = sysTaskVehicleMapper.deleteSysTaskVehicleByTaskIdAndVehicleId(taskId, vehicleId);
+ int result = sysTaskVehicleService.unassignVehicleFromTask(taskId, vehicleId);
// 璁板綍鎿嶄綔鏃ュ織
if (result > 0) {
@@ -1426,35 +963,13 @@
@Override
@Transactional
public int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark,Long userId,String userName) {
- List<SysTaskVehicle> taskVehicles = new ArrayList<>();
- Date now = DateUtils.getNowDate();
- String assignBy = userName;
-
- for (Long vehicleId : vehicleIds) {
- // 妫�鏌ユ槸鍚﹀凡缁忓垎閰�
- int exists = sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
- if (exists == 0) {
- SysTaskVehicle taskVehicle = new SysTaskVehicle();
- taskVehicle.setTaskId(taskId);
- taskVehicle.setVehicleId(vehicleId);
- taskVehicle.setAssignTime(now);
- taskVehicle.setAssignBy(assignBy);
- taskVehicle.setStatus("ASSIGNED");
- taskVehicle.setRemark(remark);
- taskVehicles.add(taskVehicle);
- }
- }
-
- int result = 0;
- if (!taskVehicles.isEmpty()) {
- result = sysTaskVehicleMapper.batchInsertSysTaskVehicle(taskVehicles);
- }
+ int result = sysTaskVehicleService.assignMultipleVehiclesToTask(taskId, vehicleIds, remark, userId, userName);
// 璁板綍鎿嶄綔鏃ュ織
if (result > 0) {
recordTaskLog(taskId, "ASSIGN", "鎵归噺鍒嗛厤杞﹁締", null,
"鍒嗛厤杞﹁締鏁伴噺锛�" + result + "锛屽娉細" + remark,
- userId,userName);
+ userId, userName);
}
return result;
@@ -1468,7 +983,7 @@
*/
@Override
public List<SysTaskVehicle> getTaskVehicles(Long taskId) {
- return sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId);
+ return sysTaskVehicleService.getTaskVehicles(taskId);
}
/**
@@ -1480,34 +995,7 @@
*/
@Override
public List<SysTaskVehicle> getAvailableVehicles(Long deptId, String taskType) {
- List<SysTaskVehicle> availableVehicles = new ArrayList<>();
-
- try {
- // 鏌ヨ鎵�鏈夌姸鎬佷负姝e父鐨勮溅杈嗭紙涓嶉檺鍒堕儴闂級
- VehicleInfo queryParam = new VehicleInfo();
- queryParam.setStatus("0"); // 0琛ㄧず姝e父鐘舵��
- // 涓嶈缃甦eptId锛屾煡璇㈡墍鏈夐儴闂ㄧ殑杞﹁締
- queryParam.setDeptId(deptId);
-
- List<VehicleInfo> vehicles = vehicleInfoMapper.selectVehicleInfoList(queryParam);
-
- // 杞崲涓篠ysTaskVehicle瀵硅薄
- for (VehicleInfo vehicle : vehicles) {
- SysTaskVehicle taskVehicle = new SysTaskVehicle();
- taskVehicle.setVehicleId(vehicle.getVehicleId());
- taskVehicle.setVehicleNo(vehicle.getVehicleNo());
- taskVehicle.setVehicleType(vehicle.getVehicleType());
- taskVehicle.setVehicleBrand(vehicle.getVehicleBrand());
- taskVehicle.setVehicleModel(vehicle.getVehicleModel());
- taskVehicle.setDeptName(vehicle.getDeptName()); // 娣诲姞閮ㄩ棬鍚嶇О
- availableVehicles.add(taskVehicle);
- }
- } catch (Exception e) {
- // 濡傛灉鏌ヨ澶辫触锛岃褰曟棩蹇楀苟杩斿洖绌哄垪琛�
- System.err.println("鏌ヨ鍙敤杞﹁締澶辫触: " + e.getMessage());
- }
-
- return availableVehicles;
+ return sysTaskVehicleService.getAvailableVehicles(deptId, taskType);
}
/**
@@ -1552,14 +1040,9 @@
SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
if (task != null) {
// 鏌ヨ鍏宠仈杞﹁締
- task.setAssignedVehicles(sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId));
- // 鏌ヨ闄勪欢
- List<SysTaskAttachment> attachments = sysTaskAttachmentMapper.selectSysTaskAttachmentByTaskId(taskId);
- // 涓烘瘡涓檮浠舵嫾鎺ュ畬鏁碪RL
- if (attachments != null && !attachments.isEmpty()) {
- attachments.forEach(this::buildAttachmentUrl);
- }
- task.setAttachments(attachments);
+ task.setAssignedVehicles(sysTaskVehicleService.getTaskVehicles(taskId));
+ // 鏌ヨ闄勪欢锛堝凡鑷姩鎷兼帴瀹屾暣URL锛�
+ task.setAttachments(sysTaskAttachmentService.getAttachmentsByTaskId(taskId));
// 鏌ヨ鎿嶄綔鏃ュ織
task.setOperationLogs(sysTaskLogMapper.selectSysTaskLogByTaskId(taskId));
// 鏌ヨ鎵ц浜哄憳鍒楄〃
@@ -1571,7 +1054,7 @@
}
// 鍔犺浇绂忕杞︽墿灞曚俊鎭�
else if ("WELFARE".equals(task.getTaskType())) {
- SysTaskWelfare welfareInfo = sysTaskWelfareMapper.selectSysTaskWelfareByTaskId(taskId);
+ SysTaskWelfare welfareInfo = sysWelfareTaskService.getWelfareInfoByTaskId(taskId);
task.setWelfareInfo(welfareInfo);
}
}
@@ -1598,13 +1081,7 @@
*/
@Override
public boolean hasLegacyServiceOrdId(Long taskId) {
- // 鍙湁鎬ユ晳杞繍浠诲姟鎵嶆湁鏃х郴缁烮D
- SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
- if (task != null && "EMERGENCY_TRANSFER".equals(task.getTaskType())) {
- SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
- return emergencyInfo != null && emergencyInfo.getLegacyServiceOrdId() != null;
- }
- return false;
+ return sysEmergencyTaskService.hasLegacyServiceOrdId(taskId);
}
/**
@@ -1615,13 +1092,7 @@
*/
@Override
public boolean hasLegacyDispatchOrdId(Long taskId) {
- // 鍙湁鎬ユ晳杞繍浠诲姟鎵嶆湁鏃х郴缁烮D
- SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
- if (task != null && "EMERGENCY_TRANSFER".equals(task.getTaskType())) {
- SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
- return emergencyInfo != null && emergencyInfo.getLegacyDispatchOrdId() != null;
- }
- return false;
+ return sysEmergencyTaskService.hasLegacyDispatchOrdId(taskId);
}
/**
@@ -1632,11 +1103,7 @@
*/
@Override
public boolean existsByLegacyServiceOrdId(Long legacyServiceOrdId) {
- if (legacyServiceOrdId == null) {
- return false;
- }
- SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectByLegacyServiceOrdId(legacyServiceOrdId);
- return emergencyInfo != null;
+ return sysEmergencyTaskService.existsByLegacyServiceOrdId(legacyServiceOrdId);
}
/**
@@ -1647,11 +1114,7 @@
*/
@Override
public boolean existsByLegacyDispatchOrdId(Long legacyDispatchOrdId) {
- if (legacyDispatchOrdId == null) {
- return false;
- }
- SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectByLegacyDispatchOrdId(legacyDispatchOrdId);
- return emergencyInfo != null;
+ return sysEmergencyTaskService.existsByLegacyDispatchOrdId(legacyDispatchOrdId);
}
@Autowired
@@ -1757,21 +1220,109 @@
return sb.toString();
}
+
/**
- * 鑾峰彇鏂囦欢绫诲瀷
+ * 浠嶵askCreateVO璁剧疆鍦板潃鍜屽潗鏍囦俊鎭埌浠诲姟瀵硅薄
*
- * @param fileName 鏂囦欢鍚�
- * @return 鏂囦欢绫诲瀷
+ * @param task 浠诲姟瀵硅薄
+ * @param createVO 鍒涘缓VO
*/
- private String getFileType(String fileName) {
- if (StringUtils.isEmpty(fileName)) {
- return "";
+ private void setAddressAndCoordinatesFromVO(SysTask task, TaskCreateVO createVO) {
+ // 璁剧疆閫氱敤鍦板潃鍜屽潗鏍囦俊鎭�
+ if (createVO.getDepartureAddress() != null) {
+ task.setDepartureAddress(createVO.getDepartureAddress());
}
- int lastDotIndex = fileName.lastIndexOf(".");
- if (lastDotIndex > 0 && lastDotIndex < fileName.length() - 1) {
- return fileName.substring(lastDotIndex + 1).toLowerCase();
+ if (createVO.getDestinationAddress() != null) {
+ task.setDestinationAddress(createVO.getDestinationAddress());
}
- return "";
+ if (createVO.getDepartureLongitude() != null) {
+ task.setDepartureLongitude(createVO.getDepartureLongitude());
+ }
+ if (createVO.getDepartureLatitude() != null) {
+ task.setDepartureLatitude(createVO.getDepartureLatitude());
+ }
+ if (createVO.getDestinationLongitude() != null) {
+ task.setDestinationLongitude(createVO.getDestinationLongitude());
+ }
+ if (createVO.getDestinationLatitude() != null) {
+ task.setDestinationLatitude(createVO.getDestinationLatitude());
+ }
+ if (createVO.getEstimatedDistance() != null) {
+ task.setEstimatedDistance(createVO.getEstimatedDistance());
+ }
+ }
+
+ /**
+ * 璁剧疆浠诲姟绫诲瀷鐗瑰畾淇℃伅锛堟�ユ晳杞繍/绂忕杞︼級
+ *
+ * @param task 浠诲姟瀵硅薄
+ * @param createVO 鍒涘缓VO
+ */
+ private void setTaskTypeSpecificInfo(SysTask task, TaskCreateVO createVO) {
+ // 璁剧疆鎬ユ晳杞繍鐗瑰畾淇℃伅
+ if (createVO.getTransferTime() != null) {
+ task.setPlannedStartTime(createVO.getTransferTime());
+ }
+ if (createVO.getTransferDistance() != null) {
+ task.setEstimatedDistance(createVO.getTransferDistance());
+ }
+
+ // 璁剧疆绂忕杞︾壒瀹氫俊鎭�
+ if (createVO.getServiceTime() != null) {
+ task.setPlannedStartTime(createVO.getServiceTime());
+ }
+ if (createVO.getStartAddress() != null) {
+ task.setDepartureAddress(createVO.getStartAddress());
+ }
+ if (createVO.getEndAddress() != null) {
+ task.setDestinationAddress(createVO.getEndAddress());
+ }
+ if (createVO.getDistance() != null) {
+ task.setEstimatedDistance(createVO.getDistance());
+ }
+ }
+
+ /**
+ * 鑷姩濉厖缂哄け鐨凣PS鍧愭爣
+ *
+ * @param task 浠诲姟瀵硅薄
+ */
+ private void autoFillMissingGpsCoordinates(SysTask task) {
+ // 鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣锛堝鏋滅己澶憋級
+ if (task.getDepartureAddress() != null &&
+ (task.getDepartureLongitude() == null || task.getDepartureLatitude() == null) &&
+ mapService != null) {
+ try {
+ Map<String, Double> coords = mapService.geocoding(
+ task.getDepartureAddress(),
+ extractCityFromAddress(task.getDepartureAddress())
+ );
+ if (coords != null) {
+ task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
+ task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
+ }
+ } catch (Exception e) {
+ log.error("鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣澶辫触", e);
+ }
+ }
+
+ // 鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣锛堝鏋滅己澶憋級
+ if (task.getDestinationAddress() != null &&
+ (task.getDestinationLongitude() == null || task.getDestinationLatitude() == null) &&
+ mapService != null) {
+ try {
+ Map<String, Double> coords = mapService.geocoding(
+ task.getDestinationAddress(),
+ extractCityFromAddress(task.getDestinationAddress())
+ );
+ if (coords != null) {
+ task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
+ task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
+ }
+ } catch (Exception e) {
+ log.error("鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣澶辫触", e);
+ }
+ }
}
/**
@@ -1805,473 +1356,6 @@
}
/**
- * 淇濆瓨浠诲姟鎵ц浜哄憳淇℃伅锛堝寘鍚鑹茬被鍨嬶級
- *
- * @param taskId 浠诲姟ID
- * @param assignees 鎵ц浜哄憳淇℃伅鍒楄〃
- */
- private void saveTaskAssignees(Long taskId, java.util.List<TaskCreateVO.AssigneeInfo> assignees,String userName) {
- if (assignees == null || assignees.isEmpty()) {
- return;
- }
-
- java.util.List<SysTaskAssignee> taskAssignees = new java.util.ArrayList<>();
- Date now = DateUtils.getNowDate();
- String currentUser = userName;
-
- for (int i = 0; i < assignees.size(); i++) {
- TaskCreateVO.AssigneeInfo assigneeInfo = assignees.get(i);
-
- SysTaskAssignee taskAssignee = new SysTaskAssignee();
- taskAssignee.setTaskId(taskId);
- taskAssignee.setUserId(assigneeInfo.getUserId());
- taskAssignee.setUserName(assigneeInfo.getUserName());
- taskAssignee.setUserType(assigneeInfo.getUserType());
- // 绗竴涓墽琛屼汉鍛樹负涓昏鎵ц浜�
- taskAssignee.setIsPrimary(i == 0 ? "1" : "0");
- taskAssignee.setSortOrder(i);
- taskAssignee.setCreateTime(now);
- taskAssignee.setCreateBy(currentUser);
- taskAssignee.setUpdateTime(now);
- taskAssignee.setUpdateBy(currentUser);
-
- taskAssignees.add(taskAssignee);
- }
-
- // 鎵归噺淇濆瓨
- if (!taskAssignees.isEmpty()) {
- sysTaskAssigneeMapper.batchInsertSysTaskAssignee(taskAssignees);
- }
- }
-
- /**
- * 淇濆瓨鎬ユ晳杞繍浠诲姟鎵╁睍淇℃伅
- *
- * @param taskId 浠诲姟ID
- * @param createVO 浠诲姟鍒涘缓瀵硅薄
- */
- private void saveEmergencyInfo(Long taskId,String createUserName, TaskCreateVO createVO,String serviceOrderId,String dispatchOrderId, String serviceOrdNo) {
- SysTaskEmergency emergencyInfo = new SysTaskEmergency();
- emergencyInfo.setTaskId(taskId);
-
- // 璁剧疆鎮h�呬俊鎭�
- if (createVO.getPatient() != null) {
- emergencyInfo.setPatientContact(createVO.getPatient().getContact());
- emergencyInfo.setPatientPhone(createVO.getPatient().getPhone());
- emergencyInfo.setPatientName(createVO.getPatient().getName());
- emergencyInfo.setPatientGender(createVO.getPatient().getGender());
- emergencyInfo.setPatientIdCard(createVO.getPatient().getIdCard());
- emergencyInfo.setPatientCondition(createVO.getPatient().getCondition());
- }
-
- // 璁剧疆杞嚭鍖婚櫌淇℃伅
- if (createVO.getHospitalOut() != null) {
- emergencyInfo.setHospitalOutId(createVO.getHospitalOut().getId());
- emergencyInfo.setHospitalOutName(createVO.getHospitalOut().getName());
- emergencyInfo.setHospitalOutDepartment(createVO.getHospitalOut().getDepartment());
- emergencyInfo.setHospitalOutDepartmentId(createVO.getHospitalOut().getDepartmentId());
- emergencyInfo.setHospitalOutBedNumber(createVO.getHospitalOut().getBedNumber());
- emergencyInfo.setHospitalOutAddress(createVO.getHospitalOut().getAddress());
-
- // GPS鍧愭爣锛氫紭鍏堜娇鐢ㄥ墠绔紶鍏ョ殑锛屽惁鍒欏悗绔嚜鍔ㄨ幏鍙�
- if (createVO.getHospitalOut().getLongitude() != null && createVO.getHospitalOut().getLatitude() != null) {
- emergencyInfo.setHospitalOutLongitude(createVO.getHospitalOut().getLongitude());
- emergencyInfo.setHospitalOutLatitude(createVO.getHospitalOut().getLatitude());
- } else if (mapService != null && createVO.getHospitalOut().getAddress() != null) {
- // 鍚庣鑷姩鑾峰彇GPS鍧愭爣
- try {
- Map<String, Double> coords = mapService.geocoding(
- createVO.getHospitalOut().getAddress(),
- extractCityFromAddress(createVO.getHospitalOut().getAddress())
- );
- if (coords != null) {
- emergencyInfo.setHospitalOutLongitude(BigDecimal.valueOf(coords.get("lng")));
- emergencyInfo.setHospitalOutLatitude(BigDecimal.valueOf(coords.get("lat")));
- log.info("杞嚭鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
- }
- } catch (Exception e) {
- log.error("鑷姩鑾峰彇杞嚭鍖婚櫌GPS鍧愭爣澶辫触", e);
- }
- }
- }
-
- // 璁剧疆杞叆鍖婚櫌淇℃伅
- if (createVO.getHospitalIn() != null) {
- emergencyInfo.setHospitalInId(createVO.getHospitalIn().getId());
- emergencyInfo.setHospitalInName(createVO.getHospitalIn().getName());
- emergencyInfo.setHospitalInDepartment(createVO.getHospitalIn().getDepartment());
- emergencyInfo.setHospitalInDepartmentId(createVO.getHospitalIn().getDepartmentId());
- emergencyInfo.setHospitalInBedNumber(createVO.getHospitalIn().getBedNumber());
- emergencyInfo.setHospitalInAddress(createVO.getHospitalIn().getAddress());
-
- // GPS鍧愭爣锛氫紭鍏堜娇鐢ㄥ墠绔紶鍏ョ殑锛屽惁鍒欏悗绔嚜鍔ㄨ幏鍙�
- if (createVO.getHospitalIn().getLongitude() != null && createVO.getHospitalIn().getLatitude() != null) {
- emergencyInfo.setHospitalInLongitude(createVO.getHospitalIn().getLongitude());
- emergencyInfo.setHospitalInLatitude(createVO.getHospitalIn().getLatitude());
- } else if (mapService != null && createVO.getHospitalIn().getAddress() != null) {
- // 鍚庣鑷姩鑾峰彇GPS鍧愭爣
- try {
- Map<String, Double> coords = mapService.geocoding(
- createVO.getHospitalIn().getAddress(),
- extractCityFromAddress(createVO.getHospitalIn().getAddress())
- );
- if (coords != null) {
- emergencyInfo.setHospitalInLongitude(BigDecimal.valueOf(coords.get("lng")));
- emergencyInfo.setHospitalInLatitude(BigDecimal.valueOf(coords.get("lat")));
- log.info("杞叆鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
- }
- } catch (Exception e) {
- log.error("鑷姩鑾峰彇杞叆鍖婚櫌GPS鍧愭爣澶辫触", e);
- }
- }
- }
-
- // 璁剧疆璐圭敤淇℃伅
- emergencyInfo.setTransferDistance(createVO.getTransferDistance());
- emergencyInfo.setTransferPrice(createVO.getPrice());
-
- // 璁剧疆鍗曟嵁绫诲瀷ID
- emergencyInfo.setDocumentTypeId(createVO.getDocumentTypeId());
-
- // 璁剧疆浠诲姟绫诲瀷ID
- emergencyInfo.setTaskTypeId(createVO.getTaskTypeId());
-
- // 璁剧疆鐥呮儏ID鍒楄〃锛堝皢List<Long>杞崲涓洪�楀彿鍒嗛殧鐨勫瓧绗︿覆锛�
- if (createVO.getDiseaseIds() != null && !createVO.getDiseaseIds().isEmpty()) {
- String diseaseIdsStr = createVO.getDiseaseIds().stream()
- .map(String::valueOf)
- .collect(Collectors.joining(","));
- emergencyInfo.setDiseaseIds(diseaseIdsStr);
- }
-
- if(serviceOrderId!=null){
- emergencyInfo.setLegacyServiceOrdId(Long.parseLong(serviceOrderId));
- emergencyInfo.setSyncStatus(2);
- emergencyInfo.setSyncTime(new Date());
- emergencyInfo.setSyncErrorMsg("鏃х郴缁熷悓姝ヨ繃鏉�");
- }
- if(dispatchOrderId!=null){
- emergencyInfo.setLegacyDispatchOrdId(Long.parseLong(dispatchOrderId));
- emergencyInfo.setDispatchSyncStatus(2);
- emergencyInfo.setDispatchSyncTime(new Date());
- emergencyInfo.setDispatchSyncErrorMsg("鏃х郴缁熷悓姝ヨ繃鏉�");
- }
- if(serviceOrdNo!=null){
- emergencyInfo.setLegacyServiceOrdNo(serviceOrdNo);
- }
- // 绯荤粺瀛楁
- emergencyInfo.setCreateTime(DateUtils.getNowDate());
- emergencyInfo.setUpdateTime(DateUtils.getNowDate());
- emergencyInfo.setCreateBy(createUserName);
- emergencyInfo.setUpdateBy(createUserName);
-
- sysTaskEmergencyMapper.insertSysTaskEmergency(emergencyInfo);
- }
-
- /**
- * 浠� TaskCreateVO 鏇存柊鎬ユ晳杞繍浠诲姟鎵╁睍淇℃伅
- *
- * @param taskId 浠诲姟ID
- * @param createVO 浠诲姟鍒涘缓/鏇存柊瀵硅薄
- * @param userName 鎿嶄綔浜哄悕
- */
- private void updateEmergencyInfoFromCreateVO(Long taskId, TaskCreateVO createVO, String userName) {
- // 鏌ヨ鐜版湁鐨勬墿灞曚俊鎭�
- SysTaskEmergency existingInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
- if (existingInfo == null) {
- // 濡傛灉涓嶅瓨鍦紝鍒欏垱寤烘柊鐨�
- existingInfo = new SysTaskEmergency();
- existingInfo.setTaskId(taskId);
- existingInfo.setCreateTime(DateUtils.getNowDate());
- existingInfo.setCreateBy(userName);
- }
-
- // 鏇存柊鎮h�呬俊鎭�
- if (createVO.getPatient() != null) {
- if (createVO.getPatient().getContact() != null) {
- existingInfo.setPatientContact(createVO.getPatient().getContact());
- }
- if (createVO.getPatient().getPhone() != null) {
- existingInfo.setPatientPhone(createVO.getPatient().getPhone());
- }
- if (createVO.getPatient().getName() != null) {
- existingInfo.setPatientName(createVO.getPatient().getName());
- }
- if (createVO.getPatient().getGender() != null) {
- existingInfo.setPatientGender(createVO.getPatient().getGender());
- }
- if (createVO.getPatient().getIdCard() != null) {
- existingInfo.setPatientIdCard(createVO.getPatient().getIdCard());
- }
- if (createVO.getPatient().getCondition() != null) {
- existingInfo.setPatientCondition(createVO.getPatient().getCondition());
- }
- }
-
- // 鏇存柊杞嚭鍖婚櫌淇℃伅
- if (createVO.getHospitalOut() != null) {
- if (createVO.getHospitalOut().getId() != null) {
- existingInfo.setHospitalOutId(createVO.getHospitalOut().getId());
- }
- if (createVO.getHospitalOut().getName() != null) {
- existingInfo.setHospitalOutName(createVO.getHospitalOut().getName());
- }
- if (createVO.getHospitalOut().getDepartment() != null) {
- existingInfo.setHospitalOutDepartment(createVO.getHospitalOut().getDepartment());
- }
- if (createVO.getHospitalOut().getDepartmentId() != null) {
- existingInfo.setHospitalOutDepartmentId(createVO.getHospitalOut().getDepartmentId());
- }
- if (createVO.getHospitalOut().getBedNumber() != null) {
- existingInfo.setHospitalOutBedNumber(createVO.getHospitalOut().getBedNumber());
- }
- if (createVO.getHospitalOut().getAddress() != null && !createVO.getHospitalOut().getAddress().equals(existingInfo.getHospitalOutAddress())) {
- existingInfo.setHospitalOutAddress(createVO.getHospitalOut().getAddress());
-
- // 濡傛灍鏇存柊浜嗗湴鍧�浣嗘病鏈塆PS鍧愭爣锛屽悗绔嚜鍔ㄨ幏鍙�
- if (createVO.getHospitalOut().getLongitude() == null && createVO.getHospitalOut().getLatitude() == null && mapService != null) {
- try {
-
- Map<String, Double> coords = mapService.geocoding(
- createVO.getHospitalOut().getAddress(),
- extractCityFromAddress(createVO.getHospitalOut().getAddress())
- );
- if (coords != null) {
- existingInfo.setHospitalOutLongitude(BigDecimal.valueOf(coords.get("lng")));
- existingInfo.setHospitalOutLatitude(BigDecimal.valueOf(coords.get("lat")));
- log.info("杞嚭鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
- }
- } catch (Exception e) {
- log.error("鑷姩鑾峰彇杞嚭鍖婚櫌GPS鍧愭爣澶辫触", e);
- }
- }
- }
-
- }
-
- // 鏇存柊杞叆鍖婚櫌淇℃伅
- if (createVO.getHospitalIn() != null) {
- if (createVO.getHospitalIn().getId() != null) {
- existingInfo.setHospitalInId(createVO.getHospitalIn().getId());
- }
- if (createVO.getHospitalIn().getName() != null) {
- existingInfo.setHospitalInName(createVO.getHospitalIn().getName());
- }
- if (createVO.getHospitalIn().getDepartment() != null) {
- existingInfo.setHospitalInDepartment(createVO.getHospitalIn().getDepartment());
- }
- if (createVO.getHospitalIn().getDepartmentId() != null) {
- existingInfo.setHospitalInDepartmentId(createVO.getHospitalIn().getDepartmentId());
- }
- if (createVO.getHospitalIn().getBedNumber() != null) {
- existingInfo.setHospitalInBedNumber(createVO.getHospitalIn().getBedNumber());
- }
- if (createVO.getHospitalIn().getAddress() != null && !createVO.getHospitalIn().getAddress().equals(existingInfo.getHospitalInAddress())) {
- existingInfo.setHospitalInAddress(createVO.getHospitalIn().getAddress());
-
- // 濡傛灉鏇存柊浜嗗湴鍧�浣嗘病鏈塆PS鍧愭爣锛屽悗绔嚜鍔ㄨ幏鍙�
- if (createVO.getHospitalIn().getLongitude() == null && createVO.getHospitalIn().getLatitude() == null && mapService != null) {
- try {
- Map<String, Double> coords = mapService.geocoding(
- createVO.getHospitalIn().getAddress(),
- extractCityFromAddress(createVO.getHospitalIn().getAddress())
- );
- if (coords != null) {
- existingInfo.setHospitalInLongitude(BigDecimal.valueOf(coords.get("lng")));
- existingInfo.setHospitalInLatitude(BigDecimal.valueOf(coords.get("lat")));
- log.info("杞叆鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
- }
- } catch (Exception e) {
- log.error("鑷姩鑾峰彇杞叆鍖婚櫌GPS鍧愭爣澶辫触", e);
- }
- }
- }
-
- }
-
- // 鏇存柊璐圭敤淇℃伅
- if (createVO.getTransferDistance() != null) {
- existingInfo.setTransferDistance(createVO.getTransferDistance());
- }
- if (createVO.getPrice() != null) {
- existingInfo.setTransferPrice(createVO.getPrice());
- }
-
- // 鏇存柊鍗曟嵁绫诲瀷ID
- if (createVO.getDocumentTypeId() != null) {
- existingInfo.setDocumentTypeId(createVO.getDocumentTypeId());
- }
-
- // 鏇存柊浠诲姟绫诲瀷ID
- if (createVO.getTaskTypeId() != null) {
- existingInfo.setTaskTypeId(createVO.getTaskTypeId());
- }
-
- // 鏇存柊鐥呮儏ID鍒楄〃
- if (createVO.getDiseaseIds() != null && !createVO.getDiseaseIds().isEmpty()) {
- String diseaseIdsStr = createVO.getDiseaseIds().stream()
- .map(String::valueOf)
- .collect(Collectors.joining(","));
- existingInfo.setDiseaseIds(diseaseIdsStr);
- }
-
- // 绯荤粺瀛楁
- existingInfo.setUpdateTime(DateUtils.getNowDate());
- existingInfo.setUpdateBy(userName);
-
- // 鎵ц鏇存柊
- sysTaskEmergencyMapper.updateSysTaskEmergency(existingInfo);
- }
-
- /**
- * 浠� TaskCreateVO 鏇存柊绂忕杞︿换鍔℃墿灞曚俊鎭�
- *
- * @param taskId 浠诲姟ID
- * @param createVO 浠诲姟鍒涘缓/鏇存柊瀵硅薄
- * @param userName 鎿嶄綔浜哄悕
- */
- private void updateWelfareInfoFromCreateVO(Long taskId, TaskCreateVO createVO, String userName) {
- // 鏌ヨ鐜版湁鐨勬墿灞曚俊鎭�
- SysTaskWelfare existingInfo = sysTaskWelfareMapper.selectSysTaskWelfareByTaskId(taskId);
- if (existingInfo == null) {
- // 濡傛灉涓嶅瓨鍦紝鍒欏垱寤烘柊鐨�
- existingInfo = new SysTaskWelfare();
- existingInfo.setTaskId(taskId);
- existingInfo.setCreateTime(DateUtils.getNowDate());
- existingInfo.setCreateBy(userName);
- }
-
- // 鏇存柊涔樺淇℃伅
- if (createVO.getPassenger() != null) {
- if (createVO.getPassenger().getContact() != null) {
- existingInfo.setPassengerContact(createVO.getPassenger().getContact());
- }
- if (createVO.getPassenger().getPhone() != null) {
- existingInfo.setPassengerPhone(createVO.getPassenger().getPhone());
- }
- }
-
- // 鏇存柊鍦板潃淇℃伅
- if (createVO.getStartAddress() != null) {
- existingInfo.setPickupAddress(createVO.getStartAddress());
- }
- if (createVO.getEndAddress() != null) {
- existingInfo.setDestinationAddress(createVO.getEndAddress());
- }
-
- // 鏇存柊GPS鍧愭爣
- if (createVO.getDepartureLongitude() != null) {
- existingInfo.setPickupLongitude(createVO.getDepartureLongitude());
- }
- if (createVO.getDepartureLatitude() != null) {
- existingInfo.setPickupLatitude(createVO.getDepartureLatitude());
- }
- if (createVO.getDestinationLongitude() != null) {
- existingInfo.setDestinationLongitude(createVO.getDestinationLongitude());
- }
- if (createVO.getDestinationLatitude() != null) {
- existingInfo.setDestinationLatitude(createVO.getDestinationLatitude());
- }
-
- // 鏇存柊璺濈鍜岃垂鐢�
- if (createVO.getDistance() != null) {
- existingInfo.setServiceDistance(createVO.getDistance());
- } else if (createVO.getEstimatedDistance() != null) {
- existingInfo.setServiceDistance(createVO.getEstimatedDistance());
- }
- if (createVO.getPrice() != null) {
- existingInfo.setServicePrice(createVO.getPrice());
- }
-
- // 绯荤粺瀛楁
- existingInfo.setUpdateTime(DateUtils.getNowDate());
- existingInfo.setUpdateBy(userName);
-
- // 鎵ц鏇存柊
- sysTaskWelfareMapper.updateSysTaskWelfare(existingInfo);
- }
-
- /**
- * 淇濆瓨绂忕杞︿换鍔℃墿灞曚俊鎭�
- *
- * @param taskId 浠诲姟ID
- * @param createVO 浠诲姟鍒涘缓瀵硅薄
- */
- private void saveWelfareInfo(Long taskId,String userName, TaskCreateVO createVO) {
- SysTaskWelfare welfareInfo = new SysTaskWelfare();
- welfareInfo.setTaskId(taskId);
-
- // 璁剧疆涔樺淇℃伅
- if (createVO.getPassenger() != null) {
- welfareInfo.setPassengerContact(createVO.getPassenger().getContact());
- welfareInfo.setPassengerPhone(createVO.getPassenger().getPhone());
- }
-
- // 璁剧疆鍦板潃淇℃伅
- welfareInfo.setPickupAddress(createVO.getStartAddress());
- welfareInfo.setDestinationAddress(createVO.getEndAddress());
-
- // 璁剧疆GPS鍧愭爣
- welfareInfo.setPickupLongitude(createVO.getDepartureLongitude());
- welfareInfo.setPickupLatitude(createVO.getDepartureLatitude());
- welfareInfo.setDestinationLongitude(createVO.getDestinationLongitude());
- welfareInfo.setDestinationLatitude(createVO.getDestinationLatitude());
-
- // 璁剧疆璺濈鍜岃垂鐢�
- // 浼樺厛浣跨敤绂忕杞︿笓鐢ㄧ殑distance瀛楁锛屽鏋滄病鏈夊垯浣跨敤閫氱敤鐨別stimatedDistance
- BigDecimal serviceDistance = createVO.getDistance() != null ? createVO.getDistance() : createVO.getEstimatedDistance();
- welfareInfo.setServiceDistance(serviceDistance);
- welfareInfo.setServicePrice(createVO.getPrice());
-
- // 绯荤粺瀛楁
- welfareInfo.setCreateTime(DateUtils.getNowDate());
- welfareInfo.setUpdateTime(DateUtils.getNowDate());
- welfareInfo.setCreateBy(userName);
- welfareInfo.setUpdateBy(userName);
-
- sysTaskWelfareMapper.insertSysTaskWelfare(welfareInfo);
- }
-
- /**
- * 鑾峰彇闄勪欢鍒嗙被鎻忚堪
- *
- * @param category 闄勪欢鍒嗙被浠g爜
- * @return 鍒嗙被鎻忚堪
- */
- private String getCategoryDesc(String category) {
- if (category == null || category.isEmpty()) {
- return "鏈垎绫�";
- }
- switch (category) {
- case "1": return "鐭ユ儏鍚屾剰涔�";
- case "2": return "鐥呬汉璧勬枡";
- case "3": return "鎿嶄綔璁板綍";
- case "4": return "鍑鸿溅鍓�";
- case "5": return "鍑鸿溅鍚�";
- case "6": return "绯诲畨鍏ㄥ甫";
- default: return "鍏朵粬";
- }
- }
-
- /**
- * 鏋勫缓闄勪欢鐨勫畬鏁碪RL
- *
- * @param attachment 闄勪欢瀵硅薄
- */
- private void buildAttachmentUrl(SysTaskAttachment attachment) {
- if (attachment != null && StringUtils.isNotEmpty(attachment.getFilePath())) {
- String imageUrl = imageUrlConfig.getImageUrl();
- if (StringUtils.isNotEmpty(imageUrl)) {
- // 鎷兼帴瀹屾暣URL锛氬煙鍚� + 鐩稿璺緞
- attachment.setFileUrl(imageUrl + attachment.getFilePath());
- } else {
- // 濡傛灉鏈厤缃煙鍚嶏紝鐩存帴浣跨敤鐩稿璺緞
- attachment.setFileUrl(attachment.getFilePath());
- }
- }
- }
-
- /**
* 妫�鏌ヤ换鍔℃槸鍚﹀彲浠ュ嚭鍙�
* 妫�鏌ワ細
* 1. 杞﹁締鏄惁鏈夋湭瀹屾垚鐨勪换鍔�
@@ -2281,11 +1365,11 @@
* @return AjaxResult 鏍¢獙缁撴灉
*/
@Override
- public com.ruoyi.common.core.domain.AjaxResult checkTaskCanDepart(Long taskId) {
+ public AjaxResult checkTaskCanDepart(Long taskId) {
// 鑾峰彇浠诲姟璇︽儏
SysTask task = this.getTaskDetail(taskId);
if (task == null) {
- return com.ruoyi.common.core.domain.AjaxResult.error("浠诲姟涓嶅瓨鍦�");
+ return AjaxResult.error("浠诲姟涓嶅瓨鍦�");
}
List<Map<String, Object>> conflicts = new ArrayList<>();
@@ -2369,7 +1453,7 @@
result.put("valid", conflicts.isEmpty());
result.put("conflicts", conflicts);
- return com.ruoyi.common.core.domain.AjaxResult.success(result);
+ return AjaxResult.success(result);
}
/**
@@ -2381,35 +1465,8 @@
*/
@Override
@Transactional
- public com.ruoyi.common.core.domain.AjaxResult setAssigneeReady(Long taskId, Long userId) {
- // 1. 鏌ヨ鎵ц浜哄叧鑱斾俊鎭�
- List<SysTaskAssignee> assignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
- SysTaskAssignee targetAssignee = assignees.stream()
- .filter(a -> a.getUserId().equals(userId))
- .findFirst()
- .orElse(null);
-
- if (targetAssignee == null) {
- return com.ruoyi.common.core.domain.AjaxResult.error("鎮ㄤ笉鏄浠诲姟鐨勬墽琛屼汉");
- }
-
- // 2. 鏇存柊灏辩华鐘舵��
- targetAssignee.setIsReady("1");
- targetAssignee.setReadyTime(new Date());
- targetAssignee.setUpdateBy(SecurityUtils.getUsername());
- targetAssignee.setUpdateTime(new Date());
-
- sysTaskAssigneeMapper.updateSysTaskAssignee(targetAssignee);
-
- // 3. 妫�鏌ユ槸鍚︽墍鏈夋墽琛屼汉閮藉凡灏辩华
- boolean allReady = assignees.stream()
- .allMatch(a -> a.getUserId().equals(userId) || "1".equals(a.getIsReady()));
-
- Map<String, Object> result = new HashMap<>();
- result.put("allReady", allReady);
- result.put("message", "灏辩华鎴愬姛");
-
- return com.ruoyi.common.core.domain.AjaxResult.success(result);
+ public AjaxResult setAssigneeReady(Long taskId, Long userId) {
+ return sysTaskAssigneeService.setAssigneeReady(taskId, userId);
}
/**
@@ -2421,27 +1478,8 @@
*/
@Override
@Transactional
- public com.ruoyi.common.core.domain.AjaxResult cancelAssigneeReady(Long taskId, Long userId) {
- // 鏌ヨ鎵ц浜哄叧鑱斾俊鎭�
- List<SysTaskAssignee> assignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
- SysTaskAssignee targetAssignee = assignees.stream()
- .filter(a -> a.getUserId().equals(userId))
- .findFirst()
- .orElse(null);
-
- if (targetAssignee == null) {
- return com.ruoyi.common.core.domain.AjaxResult.error("鎮ㄤ笉鏄浠诲姟鐨勬墽琛屼汉");
- }
-
- // 鏇存柊灏辩华鐘舵��
- targetAssignee.setIsReady("0");
- targetAssignee.setReadyTime(null);
- targetAssignee.setUpdateBy(SecurityUtils.getUsername());
- targetAssignee.setUpdateTime(new Date());
-
- sysTaskAssigneeMapper.updateSysTaskAssignee(targetAssignee);
-
- return com.ruoyi.common.core.domain.AjaxResult.success("宸插彇娑堝氨缁�");
+ public AjaxResult cancelAssigneeReady(Long taskId, Long userId) {
+ return sysTaskAssigneeService.cancelAssigneeReady(taskId, userId);
}
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java
index feab794..6f3a6d7 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java
@@ -1,55 +1,31 @@
package com.ruoyi.system.service.impl;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.system.domain.SysTaskVehicle;
+import com.ruoyi.system.domain.VehicleInfo;
+import com.ruoyi.system.mapper.SysTaskVehicleMapper;
+import com.ruoyi.system.mapper.VehicleInfoMapper;
+import com.ruoyi.system.service.ISysTaskVehicleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
-import com.ruoyi.common.utils.DateUtils;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.system.mapper.SysTaskVehicleMapper;
-import com.ruoyi.system.mapper.SysTaskMapper;
-import com.ruoyi.system.mapper.VehicleInfoMapper;
-import com.ruoyi.system.domain.SysTask;
-import com.ruoyi.system.domain.SysTaskVehicle;
-import com.ruoyi.system.domain.VehicleInfo;
-import com.ruoyi.system.service.ISysTaskVehicleService;
+
+import java.util.*;
+import java.util.stream.Collectors;
/**
- * 浠诲姟杞﹁締鍏宠仈Service涓氬姟灞傚鐞�
+ * 浠诲姟杞﹁締鏈嶅姟瀹炵幇绫�
*
* @author ruoyi
- * @date 2024-01-15
*/
@Service
public class SysTaskVehicleServiceImpl implements ISysTaskVehicleService {
-
- private static final Logger logger = LoggerFactory.getLogger(SysTaskVehicleServiceImpl.class);
-
+
@Autowired
private SysTaskVehicleMapper sysTaskVehicleMapper;
-
+
@Autowired
private VehicleInfoMapper vehicleInfoMapper;
-
- @Autowired
- private SysTaskMapper sysTaskMapper;
-
- /**
- * 鏌ヨ浠诲姟杞﹁締鍏宠仈
- *
- * @param id 浠诲姟杞﹁締鍏宠仈涓婚敭
- * @return 浠诲姟杞﹁締鍏宠仈
- */
- @Override
- public SysTaskVehicle selectSysTaskVehicleById(Long id) {
- return sysTaskVehicleMapper.selectSysTaskVehicleById(id);
- }
/**
* 鏌ヨ浠诲姟杞﹁締鍏宠仈鍒楄〃
@@ -60,6 +36,17 @@
@Override
public List<SysTaskVehicle> selectSysTaskVehicleList(SysTaskVehicle sysTaskVehicle) {
return sysTaskVehicleMapper.selectSysTaskVehicleList(sysTaskVehicle);
+ }
+
+ /**
+ * 鏌ヨ浠诲姟杞﹁締鍏宠仈淇℃伅
+ *
+ * @param id 浠诲姟杞﹁締鍏宠仈涓婚敭
+ * @return 浠诲姟杞﹁締鍏宠仈淇℃伅
+ */
+ @Override
+ public SysTaskVehicle selectSysTaskVehicleById(Long id) {
+ return sysTaskVehicleMapper.selectSysTaskVehicleById(id);
}
/**
@@ -80,20 +67,7 @@
* @return 缁撴灉
*/
@Override
- @Transactional
public int insertSysTaskVehicle(SysTaskVehicle sysTaskVehicle) {
- // 璁剧疆鍒嗛厤鏃堕棿鍜屽垎閰嶄汉
- if (sysTaskVehicle.getAssignTime() == null) {
- sysTaskVehicle.setAssignTime(DateUtils.getNowDate());
- }
- if (sysTaskVehicle.getAssignBy() == null || sysTaskVehicle.getAssignBy().isEmpty()) {
- sysTaskVehicle.setAssignBy(SecurityUtils.getUsername());
- }
- // 璁剧疆榛樿鐘舵��
- if (sysTaskVehicle.getStatus() == null || sysTaskVehicle.getStatus().isEmpty()) {
- sysTaskVehicle.setStatus("ASSIGNED");
- }
- sysTaskVehicle.setCreateTime(DateUtils.getNowDate());
return sysTaskVehicleMapper.insertSysTaskVehicle(sysTaskVehicle);
}
@@ -104,22 +78,8 @@
* @return 缁撴灉
*/
@Override
- @Transactional
public int updateSysTaskVehicle(SysTaskVehicle sysTaskVehicle) {
- sysTaskVehicle.setUpdateTime(DateUtils.getNowDate());
return sysTaskVehicleMapper.updateSysTaskVehicle(sysTaskVehicle);
- }
-
- /**
- * 鎵归噺鍒犻櫎浠诲姟杞﹁締鍏宠仈
- *
- * @param ids 闇�瑕佸垹闄ょ殑浠诲姟杞﹁締鍏宠仈涓婚敭
- * @return 缁撴灉
- */
- @Override
- @Transactional
- public int deleteSysTaskVehicleByIds(Long[] ids) {
- return sysTaskVehicleMapper.deleteSysTaskVehicleByIds(ids);
}
/**
@@ -129,186 +89,30 @@
* @return 缁撴灉
*/
@Override
- @Transactional
public int deleteSysTaskVehicleById(Long id) {
return sysTaskVehicleMapper.deleteSysTaskVehicleById(id);
}
/**
- * 鏍规嵁浠诲姟ID鍒犻櫎杞﹁締鍏宠仈
+ * 鎵归噺鍒犻櫎浠诲姟杞﹁締鍏宠仈淇℃伅
*
- * @param taskId 浠诲姟ID
+ * @param ids 闇�瑕佸垹闄ょ殑涓婚敭闆嗗悎
* @return 缁撴灉
*/
@Override
- @Transactional
- public int deleteSysTaskVehicleByTaskId(Long taskId) {
- return sysTaskVehicleMapper.deleteSysTaskVehicleByTaskId(taskId);
- }
-
- /**
- * 鏍规嵁浠诲姟ID鍜岃溅杈咺D鍒犻櫎鍏宠仈
- *
- * @param taskId 浠诲姟ID
- * @param vehicleId 杞﹁締ID
- * @return 缁撴灉
- */
- @Override
- @Transactional
- public int deleteSysTaskVehicleByTaskIdAndVehicleId(Long taskId, Long vehicleId) {
- return sysTaskVehicleMapper.deleteSysTaskVehicleByTaskIdAndVehicleId(taskId, vehicleId);
- }
-
- /**
- * 妫�鏌ヤ换鍔¤溅杈嗗叧鑱旀槸鍚﹀瓨鍦�
- *
- * @param taskId 浠诲姟ID
- * @param vehicleId 杞﹁締ID
- * @return 缁撴灉
- */
- @Override
- public int checkTaskVehicleExists(Long taskId, Long vehicleId) {
- return sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
- }
-
- /**
- * 鎵归噺鏂板浠诲姟杞﹁締鍏宠仈
- *
- * @param sysTaskVehicleList 浠诲姟杞﹁締鍏宠仈鍒楄〃
- * @return 缁撴灉
- */
- @Override
- @Transactional
- public int batchInsertSysTaskVehicle(List<SysTaskVehicle> sysTaskVehicleList) {
- return sysTaskVehicleMapper.batchInsertSysTaskVehicle(sysTaskVehicleList);
- }
-
- /**
- * 鍒嗛厤杞﹁締缁欎换鍔�
- *
- * @param taskId 浠诲姟ID
- * @param vehicleId 杞﹁締ID
- * @param remark 澶囨敞
- * @return 缁撴灉
- */
- @Override
- @Transactional
- public int assignVehicleToTask(Long taskId, Long vehicleId, String remark) {
- // 妫�鏌ユ槸鍚﹀凡缁忓垎閰�
- int exists = sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
- if (exists > 0) {
- throw new RuntimeException("杞﹁締宸茬粡鍒嗛厤缁欒浠诲姟");
- }
-
- SysTaskVehicle taskVehicle = new SysTaskVehicle();
- taskVehicle.setTaskId(taskId);
- taskVehicle.setVehicleId(vehicleId);
- taskVehicle.setAssignTime(DateUtils.getNowDate());
- taskVehicle.setAssignBy(SecurityUtils.getUsername());
- taskVehicle.setStatus("ASSIGNED");
- taskVehicle.setRemark(remark);
-
- return sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
- }
-
- /**
- * 鍙栨秷浠诲姟杞﹁締鍒嗛厤
- *
- * @param taskId 浠诲姟ID
- * @param vehicleId 杞﹁締ID
- * @return 缁撴灉
- */
- @Override
- @Transactional
- public int unassignVehicleFromTask(Long taskId, Long vehicleId) {
- return sysTaskVehicleMapper.deleteSysTaskVehicleByTaskIdAndVehicleId(taskId, vehicleId);
- }
-
- /**
- * 鎵归噺鍒嗛厤杞﹁締缁欎换鍔�
- *
- * @param taskId 浠诲姟ID
- * @param vehicleIds 杞﹁締ID鍒楄〃
- * @param remark 澶囨敞
- * @return 缁撴灉
- */
- @Override
- @Transactional
- public int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark) {
- List<SysTaskVehicle> taskVehicles = new ArrayList<>();
- Date now = DateUtils.getNowDate();
- String assignBy = SecurityUtils.getUsername();
-
- for (Long vehicleId : vehicleIds) {
- // 妫�鏌ユ槸鍚﹀凡缁忓垎閰�
- int exists = sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
- if (exists == 0) {
- SysTaskVehicle taskVehicle = new SysTaskVehicle();
- taskVehicle.setTaskId(taskId);
- taskVehicle.setVehicleId(vehicleId);
- taskVehicle.setAssignTime(now);
- taskVehicle.setAssignBy(assignBy);
- taskVehicle.setStatus("ASSIGNED");
- taskVehicle.setRemark(remark);
- taskVehicles.add(taskVehicle);
- }
- }
-
- if (!taskVehicles.isEmpty()) {
- return sysTaskVehicleMapper.batchInsertSysTaskVehicle(taskVehicles);
- }
-
- return 0;
- }
-
- /**
- * 鏌ヨ鍙敤杞﹁締
- *
- * @param deptId 閮ㄩ棬ID
- * @param taskType 浠诲姟绫诲瀷
- * @return 鍙敤杞﹁締鍒楄〃
- */
- @Override
- public List<SysTaskVehicle> getAvailableVehicles(Long deptId, String taskType) {
- // 鏌ヨ鎸囧畾閮ㄩ棬涓嬬姸鎬佷负姝e父鐨勮溅杈�
- List<SysTaskVehicle> availableVehicles = new ArrayList<>();
-
- try {
- // 鏌ヨ杞﹁締淇℃伅
- VehicleInfo queryParam = new VehicleInfo();
- queryParam.setDeptId(deptId);
- queryParam.setStatus("0"); // 0琛ㄧず姝e父鐘舵��
-
- List<VehicleInfo> vehicles = vehicleInfoMapper.selectVehicleInfoList(queryParam);
-
- // 杞崲涓� SysTaskVehicle 瀵硅薄
- for (VehicleInfo vehicle : vehicles) {
- SysTaskVehicle taskVehicle = new SysTaskVehicle();
- taskVehicle.setVehicleId(vehicle.getVehicleId());
- taskVehicle.setVehicleNo(vehicle.getVehicleNo());
- taskVehicle.setVehicleType(vehicle.getVehicleType());
- taskVehicle.setVehicleBrand(vehicle.getVehicleBrand());
- taskVehicle.setVehicleModel(vehicle.getVehicleModel());
- taskVehicle.setStatus(vehicle.getStatus());
- availableVehicles.add(taskVehicle);
- }
- } catch (Exception e) {
- logger.error("鏌ヨ鍙敤杞﹁締澶辫触", e);
- }
-
- return availableVehicles;
+ public int deleteSysTaskVehicleByIds(Long[] ids) {
+ return sysTaskVehicleMapper.deleteSysTaskVehicleByIds(ids);
}
/**
* 鏇存柊浠诲姟杞﹁締鍏宠仈鐘舵��
*
- * @param id 鍏宠仈ID
- * @param status 鏂扮姸鎬�
+ * @param id 浠诲姟杞﹁締鍏宠仈涓婚敭
+ * @param status 鐘舵��
* @return 缁撴灉
*/
@Override
- @Transactional
- public int updateTaskVehicleStatus(Long id, String status) {
+ public int updateSysTaskVehicleStatus(Long id, String status) {
SysTaskVehicle taskVehicle = new SysTaskVehicle();
taskVehicle.setId(id);
taskVehicle.setStatus(status);
@@ -320,58 +124,195 @@
* 鎵归噺鑾峰彇杞﹁締褰撳墠浠诲姟鐘舵��
*
* @param vehicleIds 杞﹁締ID鍒楄〃
- * @return Map<杞﹁締ID, Map<"taskCode": 浠诲姟缂栧彿, "taskStatus": 浠诲姟鐘舵��>>
+ * @return 杞﹁締浠诲姟鐘舵�佹槧灏�
*/
@Override
public Map<Long, Map<String, Object>> batchGetVehicleCurrentTaskStatus(List<Long> vehicleIds) {
- Map<Long, Map<String, Object>> resultMap = new HashMap<>();
+ Map<Long, Map<String, Object>> statusMap = new HashMap<>();
- if (vehicleIds == null || vehicleIds.isEmpty()) {
- return resultMap;
- }
-
- try {
- // 瀵规瘡涓溅杈嗘煡璇㈠叾褰撳墠姝e湪杩涜鐨勪换鍔�
+ if (vehicleIds != null && !vehicleIds.isEmpty()) {
+ // 杩欓噷鍙互鏍规嵁瀹為檯闇�姹傛煡璇㈣溅杈嗙殑褰撳墠浠诲姟鐘舵��
+ // 鐢变簬缂轰箯鍏蜂綋鐨勪笟鍔¢�昏緫锛岃繖閲岀畝鍗曡繑鍥炵┖鏄犲皠
for (Long vehicleId : vehicleIds) {
- if (vehicleId == null) {
- continue;
- }
-
- // 鏌ヨ杞﹁締鐨勬椿璺冧换鍔★紙鏈畬鎴愩�佹湭鍙栨秷鐨勪换鍔★級
- List<SysTask> activeTasks = sysTaskMapper.selectActiveTasksByVehicleId(vehicleId);
-
- if (activeTasks != null && !activeTasks.isEmpty()) {
- // 鍙栫涓�涓椿璺冧换鍔★紙鏈�鏂扮殑锛�
- SysTask currentTask = activeTasks.get(0);
-
- Map<String, Object> taskInfo = new HashMap<>();
- taskInfo.put("taskCode", currentTask.getTaskCode());
- taskInfo.put("taskStatus", currentTask.getTaskStatus());
- taskInfo.put("taskId", currentTask.getTaskId());
-
- resultMap.put(vehicleId, taskInfo);
- } else {
- // 娌℃湁娲昏穬浠诲姟
- resultMap.put(vehicleId, null);
- }
+ Map<String, Object> statusInfo = new HashMap<>();
+ statusInfo.put("vehicleId", vehicleId);
+ statusInfo.put("currentTaskId", null);
+ statusInfo.put("currentTaskStatus", "AVAILABLE");
+ statusInfo.put("lastUpdateTime", DateUtils.getNowDate());
+ statusMap.put(vehicleId, statusInfo);
}
- } catch (Exception e) {
- logger.error("鎵归噺鏌ヨ杞﹁締浠诲姟鐘舵�佸け璐�", e);
}
- return resultMap;
+ return statusMap;
}
- /**
- * 鏇存柊浠诲姟杞﹁締鍏宠仈鐘舵�侊紙鏂版柟娉曪級
- *
- * @param id 鍏宠仈ID
- * @param status 鏂扮姸鎬�
- * @return 缁撴灉
- */
@Override
@Transactional
- public int updateSysTaskVehicleStatus(Long id, String status) {
- return updateTaskVehicleStatus(id, status);
+ public void saveTaskVehicles(Long taskId, List<Long> vehicleIds, String userName) {
+ saveTaskVehicles(taskId, vehicleIds, userName,
+ DateUtils.getNowDate(), DateUtils.getNowDate(), DateUtils.getNowDate());
+ }
+
+ @Override
+ @Transactional
+ public void saveTaskVehicles(Long taskId, List<Long> vehicleIds, String userName,
+ Date assignTime, Date createTime, Date updateTime) {
+ if (vehicleIds == null || vehicleIds.isEmpty()) {
+ return;
+ }
+
+ for (Long vehicleId : vehicleIds) {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setTaskId(taskId);
+ taskVehicle.setVehicleId(vehicleId);
+ taskVehicle.setAssignTime(assignTime);
+ taskVehicle.setAssignBy(userName);
+ taskVehicle.setStatus("ASSIGNED");
+ taskVehicle.setCreateBy(userName);
+ taskVehicle.setCreateTime(createTime);
+ taskVehicle.setUpdateBy(userName);
+ taskVehicle.setUpdateTime(updateTime);
+
+ sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
+ }
+ }
+
+ @Override
+ @Transactional
+ public boolean updateTaskVehicles(Long taskId, List<Long> newVehicleIds, String userName) {
+ if (newVehicleIds == null || newVehicleIds.isEmpty()) {
+ return false;
+ }
+
+ // 鏌ヨ鐜版湁鐨勮溅杈嗗叧鑱�
+ List<SysTaskVehicle> existingVehicles = sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId);
+ List<Long> existingVehicleIds = existingVehicles.stream()
+ .map(SysTaskVehicle::getVehicleId)
+ .collect(Collectors.toList());
+
+ // 姣旇緝鏂版棫杞﹁締ID鍒楄〃锛屽垽鏂槸鍚︽湁鍙樺寲
+ boolean vehiclesChanged = !new HashSet<>(existingVehicleIds).equals(new HashSet<>(newVehicleIds));
+
+ // 鍙湁杞﹁締鍙戠敓鍙樺寲鏃舵墠鏇存柊
+ if (vehiclesChanged) {
+ // 鍒犻櫎鏃х殑杞﹁締鍏宠仈
+ sysTaskVehicleMapper.deleteSysTaskVehicleByTaskId(taskId);
+
+ // 娣诲姞鏂扮殑杞﹁締鍏宠仈
+ Date now = DateUtils.getNowDate();
+ for (Long vehicleId : newVehicleIds) {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setTaskId(taskId);
+ taskVehicle.setVehicleId(vehicleId);
+ taskVehicle.setAssignTime(now);
+ taskVehicle.setAssignBy(userName);
+ taskVehicle.setCreateTime(now);
+ sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ @Transactional
+ public int assignVehicleToTask(Long taskId, Long vehicleId, String remark, Long userId, String userName) {
+ // 妫�鏌ユ槸鍚﹀凡缁忓垎閰�
+ int exists = sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
+ if (exists > 0) {
+ throw new RuntimeException("杞﹁締宸茬粡鍒嗛厤缁欒浠诲姟");
+ }
+
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setTaskId(taskId);
+ taskVehicle.setVehicleId(vehicleId);
+ taskVehicle.setAssignTime(DateUtils.getNowDate());
+ taskVehicle.setAssignBy(userName);
+ taskVehicle.setStatus("ASSIGNED");
+ taskVehicle.setRemark(remark);
+
+ return sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
+ }
+
+ @Override
+ @Transactional
+ public int unassignVehicleFromTask(Long taskId, Long vehicleId) {
+ return sysTaskVehicleMapper.deleteSysTaskVehicleByTaskIdAndVehicleId(taskId, vehicleId);
+ }
+
+ @Override
+ @Transactional
+ public int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark,
+ Long userId, String userName) {
+ List<SysTaskVehicle> taskVehicles = new ArrayList<>();
+ Date now = DateUtils.getNowDate();
+
+ for (Long vehicleId : vehicleIds) {
+ // 妫�鏌ユ槸鍚﹀凡缁忓垎閰�
+ int exists = sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
+ if (exists == 0) {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setTaskId(taskId);
+ taskVehicle.setVehicleId(vehicleId);
+ taskVehicle.setAssignTime(now);
+ taskVehicle.setAssignBy(userName);
+ taskVehicle.setStatus("ASSIGNED");
+ taskVehicle.setRemark(remark);
+ taskVehicles.add(taskVehicle);
+ }
+ }
+
+ int result = 0;
+ if (!taskVehicles.isEmpty()) {
+ result = sysTaskVehicleMapper.batchInsertSysTaskVehicle(taskVehicles);
+ }
+
+ return result;
+ }
+
+ @Override
+ public List<SysTaskVehicle> getTaskVehicles(Long taskId) {
+ return sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId);
+ }
+
+ @Override
+ public List<SysTaskVehicle> getAvailableVehicles(Long deptId, String taskType) {
+ List<SysTaskVehicle> availableVehicles = new ArrayList<>();
+
+ try {
+ // 鏌ヨ鎵�鏈夌姸鎬佷负姝e父鐨勮溅杈�
+ VehicleInfo queryParam = new VehicleInfo();
+ queryParam.setStatus("0"); // 0琛ㄧず姝e父鐘舵��
+ queryParam.setDeptId(deptId);
+
+ List<VehicleInfo> vehicles = vehicleInfoMapper.selectVehicleInfoList(queryParam);
+
+ // 杞崲涓篠ysTaskVehicle瀵硅薄
+ for (VehicleInfo vehicle : vehicles) {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setVehicleId(vehicle.getVehicleId());
+ taskVehicle.setVehicleNo(vehicle.getVehicleNo());
+ taskVehicle.setVehicleType(vehicle.getVehicleType());
+ taskVehicle.setVehicleBrand(vehicle.getVehicleBrand());
+ taskVehicle.setVehicleModel(vehicle.getVehicleModel());
+ taskVehicle.setDeptName(vehicle.getDeptName());
+ availableVehicles.add(taskVehicle);
+ }
+ } catch (Exception e) {
+ System.err.println("鏌ヨ鍙敤杞﹁締澶辫触: " + e.getMessage());
+ }
+
+ return availableVehicles;
+ }
+
+ @Override
+ public int deleteTaskVehiclesByTaskId(Long taskId) {
+ return sysTaskVehicleMapper.deleteSysTaskVehicleByTaskId(taskId);
+ }
+
+ @Override
+ public boolean checkVehicleAssigned(Long taskId, Long vehicleId) {
+ return sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId) > 0;
}
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysWelfareTaskServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysWelfareTaskServiceImpl.java
new file mode 100644
index 0000000..954e0db
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysWelfareTaskServiceImpl.java
@@ -0,0 +1,131 @@
+package com.ruoyi.system.service.impl;
+
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.system.domain.SysTaskWelfare;
+import com.ruoyi.system.domain.vo.TaskCreateVO;
+import com.ruoyi.system.mapper.SysTaskWelfareMapper;
+import com.ruoyi.system.service.ISysWelfareTaskService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+
+/**
+ * 绂忕杞︿换鍔℃湇鍔″疄鐜扮被
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysWelfareTaskServiceImpl implements ISysWelfareTaskService {
+
+ @Autowired
+ private SysTaskWelfareMapper sysTaskWelfareMapper;
+
+ @Override
+ public void saveWelfareInfo(Long taskId, String userName, TaskCreateVO createVO) {
+ SysTaskWelfare welfareInfo = new SysTaskWelfare();
+ welfareInfo.setTaskId(taskId);
+
+ // 璁剧疆涔樺淇℃伅
+ if (createVO.getPassenger() != null) {
+ welfareInfo.setPassengerContact(createVO.getPassenger().getContact());
+ welfareInfo.setPassengerPhone(createVO.getPassenger().getPhone());
+ }
+
+ // 璁剧疆鍦板潃淇℃伅
+ welfareInfo.setPickupAddress(createVO.getStartAddress());
+ welfareInfo.setDestinationAddress(createVO.getEndAddress());
+
+ // 璁剧疆GPS鍧愭爣
+ welfareInfo.setPickupLongitude(createVO.getDepartureLongitude());
+ welfareInfo.setPickupLatitude(createVO.getDepartureLatitude());
+ welfareInfo.setDestinationLongitude(createVO.getDestinationLongitude());
+ welfareInfo.setDestinationLatitude(createVO.getDestinationLatitude());
+
+ // 璁剧疆璺濈鍜岃垂鐢�
+ // 浼樺厛浣跨敤绂忕杞︿笓鐢ㄧ殑distance瀛楁锛屽鏋滄病鏈夊垯浣跨敤閫氱敤鐨別stimatedDistance
+ BigDecimal serviceDistance = createVO.getDistance() != null ? createVO.getDistance() : createVO.getEstimatedDistance();
+ welfareInfo.setServiceDistance(serviceDistance);
+ welfareInfo.setServicePrice(createVO.getPrice());
+
+ // 绯荤粺瀛楁
+ welfareInfo.setCreateTime(DateUtils.getNowDate());
+ welfareInfo.setUpdateTime(DateUtils.getNowDate());
+ welfareInfo.setCreateBy(userName);
+ welfareInfo.setUpdateBy(userName);
+
+ sysTaskWelfareMapper.insertSysTaskWelfare(welfareInfo);
+ }
+
+ @Override
+ public void updateWelfareInfo(Long taskId, TaskCreateVO createVO, String userName) {
+ // 鏌ヨ鐜版湁鐨勬墿灞曚俊鎭�
+ SysTaskWelfare existingInfo = sysTaskWelfareMapper.selectSysTaskWelfareByTaskId(taskId);
+ if (existingInfo == null) {
+ // 濡傛灉涓嶅瓨鍦紝鍒欏垱寤烘柊鐨�
+ existingInfo = new SysTaskWelfare();
+ existingInfo.setTaskId(taskId);
+ existingInfo.setCreateTime(DateUtils.getNowDate());
+ existingInfo.setCreateBy(userName);
+ }
+
+ // 鏇存柊涔樺淇℃伅
+ if (createVO.getPassenger() != null) {
+ if (createVO.getPassenger().getContact() != null) {
+ existingInfo.setPassengerContact(createVO.getPassenger().getContact());
+ }
+ if (createVO.getPassenger().getPhone() != null) {
+ existingInfo.setPassengerPhone(createVO.getPassenger().getPhone());
+ }
+ }
+
+ // 鏇存柊鍦板潃淇℃伅
+ if (createVO.getStartAddress() != null) {
+ existingInfo.setPickupAddress(createVO.getStartAddress());
+ }
+ if (createVO.getEndAddress() != null) {
+ existingInfo.setDestinationAddress(createVO.getEndAddress());
+ }
+
+ // 鏇存柊GPS鍧愭爣
+ if (createVO.getDepartureLongitude() != null) {
+ existingInfo.setPickupLongitude(createVO.getDepartureLongitude());
+ }
+ if (createVO.getDepartureLatitude() != null) {
+ existingInfo.setPickupLatitude(createVO.getDepartureLatitude());
+ }
+ if (createVO.getDestinationLongitude() != null) {
+ existingInfo.setDestinationLongitude(createVO.getDestinationLongitude());
+ }
+ if (createVO.getDestinationLatitude() != null) {
+ existingInfo.setDestinationLatitude(createVO.getDestinationLatitude());
+ }
+
+ // 鏇存柊璺濈鍜岃垂鐢�
+ if (createVO.getDistance() != null) {
+ existingInfo.setServiceDistance(createVO.getDistance());
+ } else if (createVO.getEstimatedDistance() != null) {
+ existingInfo.setServiceDistance(createVO.getEstimatedDistance());
+ }
+ if (createVO.getPrice() != null) {
+ existingInfo.setServicePrice(createVO.getPrice());
+ }
+
+ // 绯荤粺瀛楁
+ existingInfo.setUpdateTime(DateUtils.getNowDate());
+ existingInfo.setUpdateBy(userName);
+
+ // 鎵ц鏇存柊
+ sysTaskWelfareMapper.updateSysTaskWelfare(existingInfo);
+ }
+
+ @Override
+ public SysTaskWelfare getWelfareInfoByTaskId(Long taskId) {
+ return sysTaskWelfareMapper.selectSysTaskWelfareByTaskId(taskId);
+ }
+
+ @Override
+ public int deleteWelfareInfoByTaskId(Long taskId) {
+ return sysTaskWelfareMapper.deleteSysTaskWelfareByTaskId(taskId);
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java
index a5c7675..57cfe6c 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java
@@ -41,7 +41,14 @@
if (address == null || address.trim().isEmpty()) {
return null;
}
-
+ if(address.indexOf(",")>0){
+ String[] split = address.split(",");
+ address=split[0];
+ }
+ if(address.indexOf("锛�")>0){
+ String[] split = address.split("锛�");
+ address=split[0];
+ }
try {
// 鏋勫缓澶╁湴鍥惧湴鐞嗙紪鐮丄PI URL
String url = "http://api.tianditu.gov.cn/geocoder";
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java
index fbeede2..3738cfb 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleGpsSegmentMileageServiceImpl.java
@@ -96,10 +96,19 @@
@Override
public int batchCalculateSegmentMileage(Date startTime, Date endTime) {
try {
- logger.info("寮�濮嬫壒閲忚绠桮PS鍒嗘閲岀▼ - 鏃堕棿鑼冨洿: {} 鍒� {}", startTime, endTime);
+// logger.info("寮�濮嬫壒閲忚绠桮PS鍒嗘閲岀▼ - 鏃堕棿鑼冨洿: {} 鍒� {}", startTime, endTime);
- // 鏌ヨ鍦ㄦ寚瀹氭椂闂磋寖鍥村唴鏈塆PS鏁版嵁鐨勬墍鏈夎溅杈�
+ // 鏌ヨ鍦ㄦ寚瀹氭椂闂磋寖鍥村唴鏈塆PS鏁版嵁鐨勬墍鏈夎溅杈嗭紙娣诲姞鎱QL鐩戞帶锛�
+ long startQueryTime = System.currentTimeMillis();
List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime);
+ long queryTime = System.currentTimeMillis() - startQueryTime;
+
+ // 鎱㈡煡璇㈣鍛婏紙瓒呰繃1绉掞級
+ if (queryTime > 1000) {
+ logger.warn("鏌ヨ娲昏穬杞﹁締ID鑰楁椂杩囬暱: {}ms, 寮�濮嬫椂闂�: {}, 寤鸿妫�鏌� tb_vehicle_gps 琛ㄧ殑绱㈠紩锛堥渶瑕� vehicle_id 鍜� collect_time 缁勫悎绱㈠紩锛�",
+ queryTime, startTime);
+ }
+ logger.info("鏌ヨ鍒� {} 杈嗘椿璺冭溅杈嗭紝鏌ヨ鑰楁椂: {}ms", vehicleIds != null ? vehicleIds.size() : 0, queryTime);
if (vehicleIds == null || vehicleIds.isEmpty()) {
logger.info("娌℃湁鎵惧埌娲昏穬杞﹁締");
@@ -115,14 +124,14 @@
for (int i = 0; i < vehicleIds.size(); i++) {
Long vehicleId = vehicleIds.get(i);
try {
- logger.info("姝e湪澶勭悊杞﹁締 {} ({}/{})", vehicleId, i + 1, vehicleIds.size());
+// logger.info("姝e湪澶勭悊杞﹁締 {} ({}/{})", vehicleId, i + 1, vehicleIds.size());
int segmentCount = calculateVehicleSegmentMileage(vehicleId, startTime, endTime);
if (segmentCount > 0) {
successCount++;
- logger.info("杞﹁締 {} 璁$畻鎴愬姛锛岀敓鎴� {} 涓垎娈佃褰�", vehicleId, segmentCount);
+// logger.info("杞﹁締 {} 璁$畻鎴愬姛锛岀敓鎴� {} 涓垎娈佃褰�", vehicleId, segmentCount);
} else {
- logger.debug("杞﹁締 {} 鏃犳湁鏂扮殑GPS鍒嗘鏁版嵁", vehicleId);
+// logger.debug("杞﹁締 {} 鏃犳湁鏂扮殑GPS鍒嗘鏁版嵁", vehicleId);
}
} catch (Exception e) {
failedCount++;
@@ -133,12 +142,12 @@
// 姣忓鐞�10杈嗚溅杈撳嚭涓�娆¤繘搴�
if ((i + 1) % 10 == 0) {
- logger.info("鎵归噺璁$畻杩涘害: {}/{}, 鎴愬姛: {}, 澶辫触: {}",
+ logger.info("鎵归噺璁$畻杩涘害: {}/{}, 鎴愬姛: {}, 澶辫触: {}",
i + 1, vehicleIds.size(), successCount, failedCount);
}
}
- logger.info("鎵归噺鍒嗘閲岀▼璁$畻瀹屾垚 - 鏃堕棿鑼冨洿: {} 鍒� {}, 鎬昏溅杈嗘暟: {}, 鎴愬姛: {}, 澶辫触: {}",
+ logger.info("鎵归噺鍒嗘閲岀▼璁$畻瀹屾垚 - 鏃堕棿鑼冨洿: {} 鍒� {}, 鎬昏溅杈嗘暟: {}, 鎴愬姛: {}, 澶辫触: {}",
startTime, endTime, vehicleIds.size(), successCount, failedCount);
return successCount;
@@ -831,7 +840,7 @@
Date segmentStartTime, Date segmentEndTime) {
try {
// 鏌ヨ璇ヨ溅杈嗘鍦ㄦ墽琛岀殑浠诲姟鍒楄〃
- List<SysTask> activeTasks = sysTaskMapper.selectActiveTasksByVehicleId(vehicleId);
+ List<SysTask> activeTasks = sysTaskMapper.selectTaskByVehicleIdAndDate(vehicleId,segmentStartTime,segmentEndTime);
if (activeTasks == null || activeTasks.isEmpty()) {
logger.debug("杞﹁締 {} 鍦ㄦ椂闂存 {} - {} 娌℃湁姝e湪鎵ц鐨勪换鍔�", vehicleId, segmentStartTime, segmentEndTime);
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java
index f795378..2f59384 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/VehicleMileageStatsServiceImpl.java
@@ -9,6 +9,8 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -117,16 +119,23 @@
List<VehicleGps> gpsList = vehicleGpsMapper.selectGpsDataByTimeRange(vehicleId, dayStart, dayEnd);
if (gpsList == null || gpsList.isEmpty()) {
- logger.info("杞﹁締ID: {} 鍦ㄦ棩鏈�: {} 鏃燝PS鏁版嵁", vehicleId, statDate);
+// logger.info("杞﹁締ID: {} 鍦ㄦ棩鏈�: {} 鏃燝PS鏁版嵁", vehicleId, statDate);
return null;
}
-
+// logger.info("杞﹁締ID:{} GPS鏁版嵁鏉℃暟:{}", vehicleId, gpsList.size());
// 3. 鏌ヨ杞﹁締鍦ㄨ鏃ユ湡鐨勪换鍔℃椂闂村尯闂�
List<TaskTimeInterval> taskIntervals = vehicleMileageStatsMapper.selectTaskTimeIntervals(vehicleId, dayStart, dayEnd);
-
- // 4. 璁$畻閲岀▼
- MileageCalculation calculation = calculateMileage(gpsList, taskIntervals);
-
+
+
+ List<VehicleGpsSegmentMileage> mileages = this.getTaskDistanceMileage(vehicleId, dayStart, dayEnd);
+ int totalGpsPoints = mileages.stream()
+ .filter(segment -> segment.getGpsPointCount() != null)
+ .mapToInt(VehicleGpsSegmentMileage::getGpsPointCount)
+ .sum();
+ BigDecimal taskDistance = getTaskDistance(taskIntervals,mileages);
+
+ MileageCalculation calculation = calculateMileage(gpsList, taskDistance);
+// logger.info("璁$畻鍑鸿溅杈嗗綋澶╂�婚噷绋嬶紝杞﹁締ID:{},鎬婚噷绋嬶細{},浠诲姟閲岀▼:{}",vehicleId,calculation.totalMileage,calculation.taskMileage);
// 5. 鏌ヨ鎴栧垱寤虹粺璁¤褰�
VehicleMileageStats stats = vehicleMileageStatsMapper.selectByVehicleIdAndDate(vehicleId, statDate);
boolean isNew = (stats == null);
@@ -157,6 +166,9 @@
stats.setTaskRatio(calculation.taskRatio);
stats.setGpsPointCount(gpsList.size());
stats.setTaskCount(taskIntervals == null ? 0 : taskIntervals.size());
+
+// logger.info("杞﹁締ID: {} 鏃ユ湡: {} 閲岀▼缁熻瀹屾垚 - 鎬婚噷绋�: {}km, 浠诲姟閲岀▼: {}km, 闈炰换鍔¢噷绋�: {}km, 鍗犳瘮: {}",
+// vehicleId, statDate, calculation.totalMileage, taskDistance, calculation.nonTaskMileage, calculation.taskRatio);
// 7. 淇濆瓨鍒版暟鎹簱
if (isNew) {
@@ -216,10 +228,18 @@
}
}
+
+
+ private BigDecimal calculateTotalMileage(List<VehicleGpsSegmentMileage> mileages) {
+ return mileages.stream()
+ .map(mileage -> mileage.getSegmentDistance())
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+ }
/**
* 璁$畻閲岀▼鐨勫唴閮ㄦ柟娉�
*/
- private MileageCalculation calculateMileage(List<VehicleGps> gpsList, List<TaskTimeInterval> taskIntervals) {
+ private MileageCalculation calculateMileage(List<VehicleGps> gpsList, BigDecimal taskDistance) {
MileageCalculation result = new MileageCalculation();
// 閬嶅巻GPS鐐癸紝璁$畻鐩搁偦鐐逛箣闂寸殑璺濈
@@ -234,23 +254,12 @@
p2.getLatitude().doubleValue(),
p2.getLongitude().doubleValue()
);
-
- // 鑾峰彇杩欐璺濈鐨勬椂闂村尯闂�
- Date segmentStart = parseDateTime(p1.getCollectTime());
- Date segmentEnd = parseDateTime(p2.getCollectTime());
-
- // 璁$畻杩欐璺濈鍦ㄤ换鍔℃椂娈电殑鍗犳瘮
- double taskRatio = calculateTaskOverlapRatio(segmentStart, segmentEnd, taskIntervals);
-
- // 鍒嗘憡閲岀▼
- double taskDistance = distance * taskRatio;
- double nonTaskDistance = distance * (1 - taskRatio);
-
+
result.totalMileage = result.totalMileage.add(BigDecimal.valueOf(distance));
- result.taskMileage = result.taskMileage.add(BigDecimal.valueOf(taskDistance));
- result.nonTaskMileage = result.nonTaskMileage.add(BigDecimal.valueOf(nonTaskDistance));
}
-
+
+ result.taskMileage=taskDistance;
+ result.nonTaskMileage=result.totalMileage.subtract(result.taskMileage);
// 璁$畻浠诲姟閲岀▼鍗犳瘮
if (result.totalMileage.compareTo(BigDecimal.ZERO) > 0) {
result.taskRatio = result.taskMileage.divide(result.totalMileage, 4, RoundingMode.HALF_UP);
@@ -299,32 +308,92 @@
return EARTH_RADIUS_KM * c;
}
+ //璁$畻浠诲姟鏃堕棿娈靛唴鐨勯噷绋嬶紝搴旇鎷垮埌璇ヤ换鍔″湪宸ヤ綔鏃堕棿娈甸噷鐨勫垎娈佃窛绂荤劧鍚庣浉鍔�
+ private List<VehicleGpsSegmentMileage> getTaskDistanceMileage(Long vehicleId, Date segmentStart, Date segmentEnd) {
+ return segmentMileageMapper.selectSegmentsByDateRange(vehicleId, segmentStart, segmentEnd);
+ }
+
/**
- * 璁$畻鏃堕棿娈典笌浠诲姟鏃舵鐨勯噸鍙犳瘮渚�
+ * 璁$畻鍦ㄤ换鍔℃椂闂存鍐呯殑瀹為檯浠诲姟閲岀▼
+ * 閫氳繃妫�鏌ュ垎娈甸噷绋嬫暟鎹槸鍚︿笌浠诲姟鏃堕棿娈甸噸鍙狅紝绱姞杩欎簺閲嶅彔鍒嗘鐨勫疄闄呴噷绋�
+ *
+ * @param taskTimeIntervals 浠诲姟鏃堕棿娈靛垪琛�
+ * @param segmentMileages 鍒嗘閲岀▼鏁版嵁鍒楄〃
+ * @return 鍦ㄤ换鍔℃椂闂存鍐呯殑鎬婚噷绋�
*/
- private double calculateTaskOverlapRatio(Date segmentStart, Date segmentEnd, List<TaskTimeInterval> taskIntervals) {
- if (taskIntervals == null || taskIntervals.isEmpty()) {
- return 0.0;
+ private BigDecimal getTaskDistance(List<TaskTimeInterval> taskTimeIntervals, List<VehicleGpsSegmentMileage> segmentMileages) {
+ if (taskTimeIntervals == null || taskTimeIntervals.isEmpty() ||
+ segmentMileages == null || segmentMileages.isEmpty()) {
+ return BigDecimal.ZERO;
}
- long segmentDuration = segmentEnd.getTime() - segmentStart.getTime();
- if (segmentDuration <= 0) {
- return 0.0;
- }
+ BigDecimal totalTaskDistance = BigDecimal.ZERO;
- long totalOverlap = 0;
-
- for (TaskTimeInterval task : taskIntervals) {
- // 璁$畻閲嶅彔鏃堕棿
- long overlapStart = Math.max(segmentStart.getTime(), task.getStartTime().getTime());
- long overlapEnd = Math.min(segmentEnd.getTime(), task.getEndTime().getTime());
+ // 閬嶅巻鎵�鏈夊垎娈甸噷绋嬫暟鎹�
+ for (VehicleGpsSegmentMileage segment : segmentMileages) {
+ // 鍙鐞嗘湁鍏宠仈浠诲姟ID涓旀湁璺濈鏁版嵁鐨勫垎娈�
+
+
+ // 妫�鏌ヨ鍒嗘鏄惁涓庝换浣曚换鍔℃椂闂存閲嶅彔
+ Date segmentStart = segment.getSegmentStartTime();
+ Date segmentEnd = segment.getSegmentEndTime();
- if (overlapEnd > overlapStart) {
- totalOverlap += (overlapEnd - overlapStart);
+ boolean isInTaskPeriod = false;
+ for (TaskTimeInterval taskInterval : taskTimeIntervals) {
+ // 璁$畻鏃堕棿閲嶅彔 --浠诲姟鏃堕棿娈�
+ long overlapStart = Math.max(segmentStart.getTime(), taskInterval.getStartTime().getTime());
+ long overlapEnd = Math.min(segmentEnd.getTime(), taskInterval.getEndTime().getTime());
+
+ // 濡傛灉鏈夋椂闂撮噸鍙狅紝鍒欒鍒嗘灞炰簬浠诲姟閲岀▼
+ if (overlapEnd > overlapStart) {
+ isInTaskPeriod = true;
+ break;
+ }
+ }
+
+ // 濡傛灉鍒嗘鍦ㄤ换鍔℃椂闂存鍐咃紝鍒欑疮鍔犲叾閲岀▼
+ if (isInTaskPeriod) {
+ totalTaskDistance = totalTaskDistance.add(segment.getSegmentDistance());
}
}
- return (double) totalOverlap / segmentDuration;
+ return totalTaskDistance;
+ }
+ /**
+ * 璁$畻鎸囧畾鏃堕棿娈靛唴鐨勫疄闄呬换鍔¢噷绋�
+ * 閫氳繃鏌ユ壘涓庤鏃堕棿娈甸噸鍙犵殑浠诲姟锛屽苟绱姞杩欎簺浠诲姟鍦ㄨ鏃堕棿娈靛唴鐨勫疄闄呴噷绋�
+ */
+ private double calculateActualTaskMileage(Date segmentStart, Date segmentEnd, List<VehicleGpsSegmentMileage> segmentMileages) {
+ if (segmentMileages == null || segmentMileages.isEmpty()) {
+ return 0.0;
+ }
+
+ double totalTaskMileage = 0.0;
+
+ // 閬嶅巻鎵�鏈夊垎娈甸噷绋嬫暟鎹紝鎵惧嚭涓庢寚瀹氭椂闂存閲嶅彔涓旀湁鍏宠仈浠诲姟鐨勫垎娈�
+ for (VehicleGpsSegmentMileage segment : segmentMileages) {
+ // 鍙鐞嗘湁鍏宠仈浠诲姟鐨勫垎娈�
+ if (segment.getTaskId() == null) {
+ continue;
+ }
+
+ // 妫�鏌ュ垎娈垫椂闂翠笌鎸囧畾鏃堕棿娈垫槸鍚︽湁閲嶅彔
+ Date segStart = segment.getSegmentStartTime();
+ Date segEnd = segment.getSegmentEndTime();
+
+ // 璁$畻閲嶅彔鏃堕棿
+ long overlapStart = Math.max(segmentStart.getTime(), segStart.getTime());
+ long overlapEnd = Math.min(segmentEnd.getTime(), segEnd.getTime());
+
+ // 濡傛灉鏈夋椂闂撮噸鍙狅紝鍒欏皢璇ュ垎娈电殑璺濈鍔犲叆浠诲姟閲岀▼
+ if (overlapEnd > overlapStart) {
+ if (segment.getSegmentDistance() != null) {
+ totalTaskMileage += segment.getSegmentDistance().doubleValue();
+ }
+ }
+ }
+
+ return totalTaskMileage;
}
/**
@@ -364,6 +433,8 @@
@Override
public VehicleMileageStats aggregateFromSegmentMileage(Long vehicleId, Date statDate) {
try {
+ calculateAndSaveMileageStats(vehicleId, statDate);
+ //TODO
// 1. 鑾峰彇缁熻鏃ユ湡鐨勫紑濮嬪拰缁撴潫鏃堕棿
Calendar calendar = Calendar.getInstance();
calendar.setTime(statDate);
@@ -383,102 +454,23 @@
logger.info("杞﹁締ID: {} 鍦ㄦ棩鏈�: {} 鏃犲垎娈甸噷绋嬫暟鎹�", vehicleId, statDate);
return null;
}
-
+
+ List<TaskTimeInterval> taskIntervals = vehicleMileageStatsMapper.selectTaskTimeIntervals(vehicleId, dayStart, dayEnd);
+ Integer taskCount = taskIntervals.size();
+
+
+ List<VehicleGpsSegmentMileage> mileages = this.getTaskDistanceMileage(vehicleId, dayStart, dayEnd);
+ Integer totalGpsPoints = mileages.stream()
+ .filter(segment -> segment.getGpsPointCount() != null)
+ .mapToInt(VehicleGpsSegmentMileage::getGpsPointCount)
+ .sum();
+ BigDecimal taskDistance = getTaskDistance(taskIntervals,mileages);
+ BigDecimal totalDistance = calculateTotalMileage(segments);
+ BigDecimal nonTaskDistance = totalDistance.subtract(taskDistance);
+ BigDecimal taskRatio = taskDistance.divide(totalDistance, 4, RoundingMode.HALF_UP);
// 3. 姹囨�婚噷绋嬫暟鎹�
- BigDecimal totalMileage = BigDecimal.ZERO;
- int totalGpsPoints = 0;
-
- for (VehicleGpsSegmentMileage segment : segments) {
- if (segment.getSegmentDistance() != null) {
- totalMileage = totalMileage.add(segment.getSegmentDistance());
- }
- if (segment.getGpsPointCount() != null) {
- totalGpsPoints += segment.getGpsPointCount();
- }
- }
-
- // 4. 璁$畻浠诲姟閲岀▼鍜岄潪浠诲姟閲岀▼锛堜紭鍖栵細浼樺厛浣跨敤task_id鐩存帴鑱氬悎锛�
- BigDecimal taskMileage = BigDecimal.ZERO;
- BigDecimal nonTaskMileage = BigDecimal.ZERO;
- int taskCount = 0; // 浠诲姟鏁伴噺
-
- // 4.1 缁熻鏈塼ask_id鐨勫垎娈垫暟閲�
- int segmentsWithTask = 0;
- for (VehicleGpsSegmentMileage segment : segments) {
- if (segment.getTaskId() != null) {
- segmentsWithTask++;
- }
- }
-
- // 4.2 濡傛灉澶ч儴鍒嗗垎娈甸兘鏈塼ask_id锛屼娇鐢ㄤ紭鍖栨柟妗堬紙鐩存帴鎸塼ask_id鑱氬悎锛�
- if (segmentsWithTask > segments.size() * 0.8) {
- logger.debug("杞﹁締ID: {} 鏃ユ湡: {} 浣跨敤浼樺寲鏂规锛氱洿鎺ユ寜task_id鑱氬悎锛坽}涓垎娈垫湁task_id锛屽崰姣攞}%锛�",
- vehicleId, statDate, segmentsWithTask, (segmentsWithTask * 100.0 / segments.size()));
-
- // 浣跨敤Set缁熻鍘婚噸鐨勪换鍔D鏁伴噺
- Set<Long> uniqueTaskIds = new HashSet<>();
-
- // 鐩存帴鎸塼ask_id鍒嗙粍鑱氬悎
- for (VehicleGpsSegmentMileage segment : segments) {
- BigDecimal segDistance = segment.getSegmentDistance() != null ? segment.getSegmentDistance() : BigDecimal.ZERO;
-
- if (segment.getTaskId() != null) {
- // 鏈変换鍔D锛岃鍏ヤ换鍔¢噷绋�
- taskMileage = taskMileage.add(segDistance);
- uniqueTaskIds.add(segment.getTaskId());
- } else {
- // 娌℃湁浠诲姟ID锛岃鍏ラ潪浠诲姟閲岀▼
- nonTaskMileage = nonTaskMileage.add(segDistance);
- }
- }
-
- // 璁剧疆鍘婚噸鍚庣殑浠诲姟鏁伴噺
- taskCount = uniqueTaskIds.size();
-
- } else {
- // 4.3 闄嶇骇鏂规锛氫娇鐢ㄥ師鏈夌殑鏃堕棿閲嶅彔璁$畻鏂瑰紡
- logger.debug("杞﹁締ID: {} 鏃ユ湡: {} 浣跨敤闄嶇骇鏂规锛氭椂闂撮噸鍙犺绠楋紙鍙湁{}涓垎娈垫湁task_id锛屽崰姣攞}%锛�",
- vehicleId, statDate, segmentsWithTask, (segmentsWithTask * 100.0 / segments.size()));
-
- List<TaskTimeInterval> taskIntervals = vehicleMileageStatsMapper.selectTaskTimeIntervals(vehicleId, dayStart, dayEnd);
-
- for (VehicleGpsSegmentMileage segment : segments) {
- Date segStart = segment.getSegmentStartTime();
- Date segEnd = segment.getSegmentEndTime();
- BigDecimal segDistance = segment.getSegmentDistance() != null ? segment.getSegmentDistance() : BigDecimal.ZERO;
-
- // 璁$畻璇ュ垎娈典笌浠诲姟鏃舵鐨勯噸鍙犳瘮渚�
- double taskRatio = calculateTaskOverlapRatio(segStart, segEnd, taskIntervals);
-
- // 鍒嗘憡閲岀▼
- BigDecimal taskDist = segDistance.multiply(BigDecimal.valueOf(taskRatio));
- BigDecimal nonTaskDist = segDistance.multiply(BigDecimal.valueOf(1 - taskRatio));
-
- taskMileage = taskMileage.add(taskDist);
- nonTaskMileage = nonTaskMileage.add(nonTaskDist);
- }
-
- // 璁剧疆浠诲姟鏁伴噺
- taskCount = taskIntervals == null ? 0 : taskIntervals.size();
- }
-
- // 璁$畻浠诲姟閲岀▼鍗犳瘮
- BigDecimal taskRatio = BigDecimal.ZERO;
- if (totalMileage.compareTo(BigDecimal.ZERO) > 0) {
- taskRatio = taskMileage.divide(totalMileage, 4, RoundingMode.HALF_UP);
-
- // 鏁版嵁鏍¢獙:鍗犳瘮搴斿湪0-1涔嬮棿,濡傛灉瓒呭嚭璇存槑鏁版嵁寮傚父
- if (taskRatio.compareTo(BigDecimal.ONE) > 0) {
- logger.warn("杞﹁締ID: {} 鏃ユ湡: {} 浠诲姟閲岀▼鍗犳瘮寮傚父: {} (浠诲姟閲岀▼:{}, 鎬婚噷绋�:{}), 寮哄埗璁句负1.0",
- vehicleId, statDate, taskRatio, taskMileage, totalMileage);
- taskRatio = BigDecimal.ONE;
- } else if (taskRatio.compareTo(BigDecimal.ZERO) < 0) {
- logger.warn("杞﹁締ID: {} 鏃ユ湡: {} 浠诲姟閲岀▼鍗犳瘮涓鸿礋: {}, 寮哄埗璁句负0",
- vehicleId, statDate, taskRatio);
- taskRatio = BigDecimal.ZERO;
- }
- }
-
+
+
// 5. 鏌ヨ鎴栧垱寤虹粺璁¤褰�
VehicleMileageStats stats = vehicleMileageStatsMapper.selectByVehicleIdAndDate(vehicleId, statDate);
boolean isNew = (stats == null);
@@ -503,9 +495,9 @@
}
// 6. 璁剧疆缁熻鏁版嵁
- stats.setTotalMileage(totalMileage.setScale(2, RoundingMode.HALF_UP));
- stats.setTaskMileage(taskMileage.setScale(2, RoundingMode.HALF_UP));
- stats.setNonTaskMileage(nonTaskMileage.setScale(2, RoundingMode.HALF_UP));
+ stats.setTotalMileage(totalDistance.setScale(2, RoundingMode.HALF_UP));
+ stats.setTaskMileage(taskDistance.setScale(2, RoundingMode.HALF_UP));
+ stats.setNonTaskMileage(nonTaskDistance.setScale(2, RoundingMode.HALF_UP));
stats.setTaskRatio(taskRatio);
stats.setGpsPointCount(totalGpsPoints);
stats.setTaskCount(taskCount);
@@ -519,8 +511,8 @@
vehicleMileageStatsMapper.updateVehicleMileageStats(stats);
}
- logger.info("杞﹁締ID: {} 鏃ユ湡: {} 浠庡垎娈垫眹鎬诲畬鎴� - 鎬婚噷绋�: {}km, 浠诲姟閲岀▼: {}km, 闈炰换鍔¢噷绋�: {}km, 鍒嗘鏁�: {}",
- vehicleId, statDate, totalMileage, taskMileage, nonTaskMileage, segments.size());
+// logger.info("杞﹁締ID: {} 鏃ユ湡: {} 浠庡垎娈垫眹鎬诲畬鎴� - 鎬婚噷绋�: {}km, 浠诲姟閲岀▼: {}km, 闈炰换鍔¢噷绋�: {}km, 鍒嗘鏁�: {}",
+// vehicleId, statDate, totalMileage, taskMileage, nonTaskMileage, segments.size());
return stats;
diff --git a/ruoyi-system/src/main/resources/mapper/system/NotifyChannelConfigMapper.xml b/ruoyi-system/src/main/resources/mapper/system/NotifyChannelConfigMapper.xml
new file mode 100644
index 0000000..a9fc896
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/NotifyChannelConfigMapper.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.NotifyChannelConfigMapper">
+
+ <resultMap type="NotifyChannelConfig" id="NotifyChannelConfigResult">
+ <id property="id" column="id"/>
+ <result property="notifyType" column="notify_type"/>
+ <result property="channel" column="channel"/>
+ <result property="enabled" column="enabled"/>
+ <result property="priority" column="priority"/>
+ <result property="configJson" column="config_json"/>
+ <result property="createBy" column="create_by"/>
+ <result property="createTime" column="create_time"/>
+ <result property="updateBy" column="update_by"/>
+ <result property="updateTime" column="update_time"/>
+ <result property="remark" column="remark"/>
+ </resultMap>
+
+ <sql id="selectNotifyChannelConfigVo">
+ select id, notify_type, channel, enabled, priority, config_json,
+ create_by, create_time, update_by, update_time, remark
+ from sys_notify_channel_config
+ </sql>
+
+ <select id="selectNotifyChannelConfigById" parameterType="Long" resultMap="NotifyChannelConfigResult">
+ <include refid="selectNotifyChannelConfigVo"/>
+ where id = #{id}
+ </select>
+
+ <select id="selectNotifyChannelConfigList" parameterType="NotifyChannelConfig" resultMap="NotifyChannelConfigResult">
+ <include refid="selectNotifyChannelConfigVo"/>
+ <where>
+ <if test="notifyType != null and notifyType != ''">
+ AND notify_type = #{notifyType}
+ </if>
+ <if test="channel != null and channel != ''">
+ AND channel = #{channel}
+ </if>
+ <if test="enabled != null and enabled != ''">
+ AND enabled = #{enabled}
+ </if>
+ </where>
+ order by priority desc
+ </select>
+
+ <select id="selectEnabledChannelsByType" parameterType="String" resultMap="NotifyChannelConfigResult">
+ <include refid="selectNotifyChannelConfigVo"/>
+ where notify_type = #{notifyType} and enabled = '1'
+ order by priority desc
+ </select>
+
+ <select id="selectByTypeAndChannel" resultMap="NotifyChannelConfigResult">
+ <include refid="selectNotifyChannelConfigVo"/>
+ where notify_type = #{notifyType} and channel = #{channel}
+ </select>
+
+ <insert id="insertNotifyChannelConfig" parameterType="NotifyChannelConfig" useGeneratedKeys="true" keyProperty="id">
+ insert into sys_notify_channel_config (
+ notify_type, channel, enabled, priority, config_json,
+ create_by, create_time, update_by, update_time, remark
+ ) values (
+ #{notifyType}, #{channel}, #{enabled}, #{priority}, #{configJson},
+ #{createBy}, sysdate(), #{updateBy}, sysdate(), #{remark}
+ )
+ </insert>
+
+ <update id="updateNotifyChannelConfig" parameterType="NotifyChannelConfig">
+ update sys_notify_channel_config
+ <set>
+ <if test="notifyType != null">notify_type = #{notifyType},</if>
+ <if test="channel != null">channel = #{channel},</if>
+ <if test="enabled != null">enabled = #{enabled},</if>
+ <if test="priority != null">priority = #{priority},</if>
+ <if test="configJson != null">config_json = #{configJson},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ update_time = sysdate()
+ </set>
+ where id = #{id}
+ </update>
+
+ <delete id="deleteNotifyChannelConfigById" parameterType="Long">
+ delete from sys_notify_channel_config where id = #{id}
+ </delete>
+
+ <delete id="deleteNotifyChannelConfigByIds" parameterType="Long">
+ delete from sys_notify_channel_config where id in
+ <foreach collection="array" item="id" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </delete>
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/NotifySendLogMapper.xml b/ruoyi-system/src/main/resources/mapper/system/NotifySendLogMapper.xml
new file mode 100644
index 0000000..636a623
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/NotifySendLogMapper.xml
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.NotifySendLogMapper">
+
+ <resultMap type="NotifySendLog" id="NotifySendLogResult">
+ <result property="id" column="id" />
+ <result property="notifyTaskId" column="notify_task_id"/>
+ <result property="taskId" column="task_id" />
+ <result property="userId" column="user_id" />
+ <result property="userName" column="user_name" />
+ <result property="notifyType" column="notify_type" />
+ <result property="channel" column="channel" />
+ <result property="sendStatus" column="send_status" />
+ <result property="sendTime" column="send_time" />
+ <result property="sendResult" column="send_result" />
+ <result property="responseMsg" column="response_msg" />
+ <result property="retryCount" column="retry_count" />
+ <result property="createTime" column="create_time" />
+ <result property="createBy" column="create_by" />
+ <result property="updateTime" column="update_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="remark" column="remark" />
+ </resultMap>
+
+ <sql id="selectNotifySendLogVo">
+ select id, notify_task_id, task_id, user_id, user_name, notify_type, channel, send_status,
+ send_time, send_result, response_msg, retry_count, create_time, create_by,
+ update_time, update_by, remark
+ from sys_notify_send_log
+ </sql>
+
+ <select id="selectNotifySendLogList" parameterType="NotifySendLog" resultMap="NotifySendLogResult">
+ <include refid="selectNotifySendLogVo"/>
+ <where>
+ <if test="taskId != null">
+ AND task_id = #{taskId}
+ </if>
+ <if test="userId != null">
+ AND user_id = #{userId}
+ </if>
+ <if test="userName != null and userName != ''">
+ AND user_name like concat('%', #{userName}, '%')
+ </if>
+ <if test="notifyType != null and notifyType != ''">
+ AND notify_type = #{notifyType}
+ </if>
+ <if test="channel != null and channel != ''">
+ AND channel = #{channel}
+ </if>
+ <if test="sendStatus != null and sendStatus != ''">
+ AND send_status = #{sendStatus}
+ </if>
+ <if test="params.beginSendTime != null and params.beginSendTime != ''">
+ AND send_time >= #{params.beginSendTime}
+ </if>
+ <if test="params.endSendTime != null and params.endSendTime != ''">
+ AND send_time <= #{params.endSendTime}
+ </if>
+ </where>
+ order by create_time desc
+ </select>
+
+ <select id="selectNotifySendLogById" parameterType="Long" resultMap="NotifySendLogResult">
+ <include refid="selectNotifySendLogVo"/>
+ where id = #{id}
+ </select>
+
+ <select id="checkNotifySendLogExists" resultType="int">
+ select count(1) from sys_notify_send_log
+ where task_id = #{taskId}
+ and user_id = #{userId}
+ and notify_type = #{notifyType}
+ and channel = #{channel}
+ </select>
+
+ <select id="selectNotifySendLog" resultMap="NotifySendLogResult">
+ <include refid="selectNotifySendLogVo"/>
+ where task_id = #{taskId}
+ and user_id = #{userId}
+ and notify_type = #{notifyType}
+ and channel = #{channel}
+ limit 1
+ </select>
+
+ <select id="selectFailedNotifySendLogs" resultMap="NotifySendLogResult">
+ <include refid="selectNotifySendLogVo"/>
+ where send_status = '2'
+ and retry_count < #{maxRetryCount}
+ order by create_time asc
+ limit 100
+ </select>
+
+ <insert id="insertNotifySendLog" parameterType="NotifySendLog" useGeneratedKeys="true" keyProperty="id">
+ insert into sys_notify_send_log
+ <trim prefix="(" suffix=")" suffixOverrides=",">
+ <if test="notifyTaskId != null">notify_task_id,</if>
+ <if test="taskId != null">task_id,</if>
+ <if test="userId != null">user_id,</if>
+ <if test="userName != null">user_name,</if>
+ <if test="notifyType != null and notifyType != ''">notify_type,</if>
+ <if test="channel != null and channel != ''">channel,</if>
+ <if test="sendStatus != null">send_status,</if>
+ <if test="sendTime != null">send_time,</if>
+ <if test="sendResult != null">send_result,</if>
+ <if test="responseMsg != null">response_msg,</if>
+ <if test="retryCount != null">retry_count,</if>
+ <if test="createTime != null">create_time,</if>
+ <if test="createBy != null">create_by,</if>
+ <if test="updateTime != null">update_time,</if>
+ <if test="updateBy != null">update_by,</if>
+ <if test="remark != null">remark,</if>
+ </trim>
+ <trim prefix="values (" suffix=")" suffixOverrides=",">
+ <if test="notifyTaskId != null">#{notifyTaskId},</if>
+ <if test="taskId != null">#{taskId},</if>
+ <if test="userId != null">#{userId},</if>
+ <if test="userName != null">#{userName},</if>
+ <if test="notifyType != null and notifyType != ''">#{notifyType},</if>
+ <if test="channel != null and channel != ''">#{channel},</if>
+ <if test="sendStatus != null">#{sendStatus},</if>
+ <if test="sendTime != null">#{sendTime},</if>
+ <if test="sendResult != null">#{sendResult},</if>
+ <if test="responseMsg != null">#{responseMsg},</if>
+ <if test="retryCount != null">#{retryCount},</if>
+ <if test="createTime != null">#{createTime},</if>
+ <if test="createBy != null">#{createBy},</if>
+ <if test="updateTime != null">#{updateTime},</if>
+ <if test="updateBy != null">#{updateBy},</if>
+ <if test="remark != null">#{remark},</if>
+ </trim>
+ </insert>
+
+ <update id="updateNotifySendLog" parameterType="NotifySendLog">
+ update sys_notify_send_log
+ <trim prefix="SET" suffixOverrides=",">
+ <if test="taskId != null">task_id = #{taskId},</if>
+ <if test="userId != null">user_id = #{userId},</if>
+ <if test="userName != null">user_name = #{userName},</if>
+ <if test="notifyType != null and notifyType != ''">notify_type = #{notifyType},</if>
+ <if test="channel != null and channel != ''">channel = #{channel},</if>
+ <if test="sendStatus != null">send_status = #{sendStatus},</if>
+ <if test="sendTime != null">send_time = #{sendTime},</if>
+ <if test="sendResult != null">send_result = #{sendResult},</if>
+ <if test="retryCount != null">retry_count = #{retryCount},</if>
+ <if test="updateTime != null">update_time = #{updateTime},</if>
+ <if test="updateBy != null">update_by = #{updateBy},</if>
+ <if test="remark != null">remark = #{remark},</if>
+ </trim>
+ where id = #{id}
+ </update>
+
+ <update id="updateSendStatus">
+ update sys_notify_send_log
+ set send_status = #{sendStatus},
+ send_result = #{sendResult},
+ send_time = now(),
+ update_time = now(),
+ retry_count = retry_count + 1
+ where id = #{id}
+ </update>
+
+ <delete id="deleteNotifySendLogById" parameterType="Long">
+ delete from sys_notify_send_log where id = #{id}
+ </delete>
+
+ <delete id="deleteNotifySendLogByIds" parameterType="String">
+ delete from sys_notify_send_log where id in
+ <foreach item="id" collection="array" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </delete>
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/NotifyTaskMapper.xml b/ruoyi-system/src/main/resources/mapper/system/NotifyTaskMapper.xml
new file mode 100644
index 0000000..be01049
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/NotifyTaskMapper.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.NotifyTaskMapper">
+
+ <resultMap type="NotifyTask" id="NotifyTaskResult">
+ <id property="id" column="id"/>
+ <result property="taskId" column="task_id"/>
+ <result property="taskCode" column="task_code"/>
+ <result property="notifyType" column="notify_type"/>
+ <result property="userId" column="user_id"/>
+ <result property="userName" column="user_name"/>
+ <result property="userPhone" column="user_phone"/>
+ <result property="title" column="title"/>
+ <result property="content" column="content"/>
+ <result property="extraData" column="extra_data"/>
+ <result property="status" column="status"/>
+ <result property="retryCount" column="retry_count"/>
+ <result property="maxRetry" column="max_retry"/>
+ <result property="errorMsg" column="error_msg"/>
+ <result property="createBy" column="create_by"/>
+ <result property="createTime" column="create_time"/>
+ <result property="updateBy" column="update_by"/>
+ <result property="updateTime" column="update_time"/>
+ <result property="remark" column="remark"/>
+ </resultMap>
+
+ <sql id="selectNotifyTaskVo">
+ select id, task_id, task_code, notify_type, user_id, user_name, user_phone,
+ title, content, extra_data, status, retry_count, max_retry, error_msg,
+ create_by, create_time, update_by, update_time, remark
+ from sys_notify_task
+ </sql>
+
+ <select id="selectNotifyTaskById" parameterType="Long" resultMap="NotifyTaskResult">
+ <include refid="selectNotifyTaskVo"/>
+ where id = #{id}
+ </select>
+
+ <select id="selectNotifyTaskList" parameterType="NotifyTask" resultMap="NotifyTaskResult">
+ <include refid="selectNotifyTaskVo"/>
+ <where>
+ <if test="taskId != null">
+ AND task_id = #{taskId}
+ </if>
+ <if test="taskCode != null and taskCode != ''">
+ AND task_code = #{taskCode}
+ </if>
+ <if test="notifyType != null and notifyType != ''">
+ AND notify_type = #{notifyType}
+ </if>
+ <if test="userId != null">
+ AND user_id = #{userId}
+ </if>
+ <if test="userName != null and userName != ''">
+ AND user_name like concat('%', #{userName}, '%')
+ </if>
+ <if test="status != null and status != ''">
+ AND status = #{status}
+ </if>
+ </where>
+ order by create_time desc
+ </select>
+
+ <select id="selectPendingNotifyTasks" parameterType="int" resultMap="NotifyTaskResult">
+ <include refid="selectNotifyTaskVo"/>
+ where status = '0' and retry_count < max_retry
+ order by create_time asc
+ limit #{limit}
+ </select>
+
+ <select id="countByTaskUserType" resultType="int">
+ select count(1) from sys_notify_task
+ where task_id = #{taskId} and user_id = #{userId} and notify_type = #{notifyType}
+ </select>
+
+ <insert id="insertNotifyTask" parameterType="NotifyTask" useGeneratedKeys="true" keyProperty="id">
+ insert into sys_notify_task (
+ task_id, task_code, notify_type, user_id, user_name, user_phone,
+ title, content, extra_data, status, retry_count, max_retry, error_msg,
+ create_by, create_time, update_by, update_time, remark
+ ) values (
+ #{taskId}, #{taskCode}, #{notifyType}, #{userId}, #{userName}, #{userPhone},
+ #{title}, #{content}, #{extraData}, #{status}, #{retryCount}, #{maxRetry}, #{errorMsg},
+ #{createBy}, sysdate(), #{updateBy}, sysdate(), #{remark}
+ )
+ </insert>
+
+ <update id="updateNotifyTask" parameterType="NotifyTask">
+ update sys_notify_task
+ <set>
+ <if test="taskId != null">task_id = #{taskId},</if>
+ <if test="taskCode != null">task_code = #{taskCode},</if>
+ <if test="notifyType != null">notify_type = #{notifyType},</if>
+ <if test="userId != null">user_id = #{userId},</if>
+ <if test="userName != null">user_name = #{userName},</if>
+ <if test="userPhone != null">user_phone = #{userPhone},</if>
+ <if test="title != null">title = #{title},</if>
+ <if test="content != null">content = #{content},</if>
+ <if test="extraData != null">extra_data = #{extraData},</if>
+ <if test="status != null">status = #{status},</if>
+ <if test="retryCount != null">retry_count = #{retryCount},</if>
+ <if test="maxRetry != null">max_retry = #{maxRetry},</if>
+ <if test="errorMsg != null">error_msg = #{errorMsg},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ update_time = sysdate()
+ </set>
+ where id = #{id}
+ </update>
+
+ <update id="updateNotifyTaskStatus">
+ update sys_notify_task
+ set status = #{status}, error_msg = #{errorMsg}, update_time = sysdate()
+ where id = #{id}
+ </update>
+
+ <update id="incrementRetryCount" parameterType="Long">
+ update sys_notify_task
+ set retry_count = retry_count + 1, update_time = sysdate()
+ where id = #{id}
+ </update>
+
+ <delete id="deleteNotifyTaskById" parameterType="Long">
+ delete from sys_notify_task where id = #{id}
+ </delete>
+
+ <delete id="deleteNotifyTaskByIds" parameterType="String">
+ delete from sys_notify_task where id in
+ <foreach item="id" collection="array" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </delete>
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskAssigneeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskAssigneeMapper.xml
index 67422e4..6ecb4d8 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskAssigneeMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskAssigneeMapper.xml
@@ -103,4 +103,8 @@
#{id}
</foreach>
</delete>
+
+ <delete id="deleteByTaskIdAndUserId">
+ delete from sys_task_assignee where task_id = #{taskId} and user_id = #{userId}
+ </delete>
</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
index a7efd95..1b5cfbb 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
@@ -186,6 +186,20 @@
t.create_time desc
</select>
+ <select id="selectTaskByVehicleIdAndDate" resultMap="SysTaskResult">
+ select tv.task_id, t.actual_start_time,
+ IFNULL(t.actual_end_time, NOW()) as t.actual_end_time
+ from sys_task_vehicle tv
+ inner join sys_task t on tv.task_id = t.task_id
+ where tv.vehicle_id = #{vehicleId}
+ and t.del_flag = '0'
+ and (
+ (t.actual_end_time is not null and t.actual_start_time > #{startTime} and t.actual_end_time < #{endTime} )
+ or (t.actual_end_time is null and t.actual_start_time > ${endTime} )
+ )
+ order by t.actual_start_time
+ </select>
+
<select id="selectTaskStatistics" resultType="TaskStatisticsVO">
select
count(*) as totalTasks,
diff --git a/ruoyi-system/src/main/resources/mapper/system/VehicleGpsMapper.xml b/ruoyi-system/src/main/resources/mapper/system/VehicleGpsMapper.xml
index 2c78bdf..650f10e 100644
--- a/ruoyi-system/src/main/resources/mapper/system/VehicleGpsMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/VehicleGpsMapper.xml
@@ -130,26 +130,29 @@
order by collect_time
</select>
- <!-- 鏌ヨ娲昏穬杞﹁締ID锛堜紭鍖栵細娣诲姞LIMIT闄愬埗锛岄伩鍏嶅ぇ琛ㄦ壂鎻忥級 -->
+ <!-- 鏌ヨ娲昏穬杞﹁締ID锛堜紭鍖栵細浣跨敤GROUP BY鏇夸唬DISTINCT锛屾彁鍗囨�ц兘锛� -->
<select id="selectActiveVehicleIds" resultType="Long">
- select distinct vehicle_id
+ select vehicle_id
from tb_vehicle_gps
where collect_time >= #{startTime}
+ group by vehicle_id
order by vehicle_id
</select>
- <!-- 鏌ヨ鏈璁$畻鐨凣PS鍧愭爣锛堜笉鍦╰b_vehicle_gps_calculated琛ㄤ腑鐨勮褰曪級 -->
+ <!-- 鏌ヨ鏈璁$畻鐨凣PS鍧愭爣锛堜紭鍖栵細浣跨敤NOT EXISTS鏇夸唬LEFT JOIN ... IS NULL锛� -->
<select id="selectUncalculatedGps" resultMap="VehicleGpsResult">
SELECT g.gps_id, g.vehicle_id, g.device_id, g.longitude, g.latitude, g.altitude,
g.speed, g.direction, g.collect_time, g.device_report_time,
g.platform_process_time, g.create_time, v.vehicle_no
FROM tb_vehicle_gps g
- LEFT JOIN tb_vehicle_info v ON g.vehicle_id = v.vehicle_id
- LEFT JOIN tb_vehicle_gps_calculated c ON g.gps_id = c.gps_id
+ INNER JOIN tb_vehicle_info v ON g.vehicle_id = v.vehicle_id
WHERE g.vehicle_id = #{vehicleId}
AND g.collect_time >= #{startTime}
AND g.collect_time <= #{endTime}
- AND c.gps_id IS NULL -- 鏈璁$畻鐨凣PS鐐�
+ AND NOT EXISTS (
+ SELECT 1 FROM tb_vehicle_gps_calculated c
+ WHERE c.gps_id = g.gps_id
+ )
ORDER BY g.collect_time
</select>
</mapper>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/VehicleMileageStatsMapper.xml b/ruoyi-system/src/main/resources/mapper/system/VehicleMileageStatsMapper.xml
index aee4324..47abb4d 100644
--- a/ruoyi-system/src/main/resources/mapper/system/VehicleMileageStatsMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/VehicleMileageStatsMapper.xml
@@ -88,16 +88,17 @@
</select>
<select id="selectTaskTimeIntervals" resultMap="TaskTimeIntervalResult">
- select tv.task_id, t.create_time as start_time,
+ select tv.task_id, t.actual_start_time as start_time,
IFNULL(t.actual_end_time, NOW()) as end_time
from sys_task_vehicle tv
inner join sys_task t on tv.task_id = t.task_id
where tv.vehicle_id = #{vehicleId}
and t.del_flag = '0'
- and t.actual_end_time is not null
- and t.create_time < #{endTime}
- and t.actual_end_time > #{startTime}
- order by t.create_time
+ and (
+ (t.actual_end_time is not null and t.actual_start_time > #{startTime} and t.actual_end_time < #{endTime})
+ or (t.actual_end_time is null and t.actual_start_time > #{startTime})
+ )
+ order by t.actual_start_time
</select>
<insert id="insertVehicleMileageStats" parameterType="VehicleMileageStats" useGeneratedKeys="true" keyProperty="statsId">
diff --git a/ruoyi-ui/src/api/system/notify/channelConfig.js b/ruoyi-ui/src/api/system/notify/channelConfig.js
new file mode 100644
index 0000000..b4ca2c0
--- /dev/null
+++ b/ruoyi-ui/src/api/system/notify/channelConfig.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ閫氱煡娓犻亾閰嶇疆鍒楄〃
+export function listChannelConfig(query) {
+ return request({
+ url: '/system/notify/channel/config/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鏌ヨ閫氱煡娓犻亾閰嶇疆璇︾粏
+export function getChannelConfig(id) {
+ return request({
+ url: '/system/notify/channel/config/' + id,
+ method: 'get'
+ })
+}
+
+// 鏂板閫氱煡娓犻亾閰嶇疆
+export function addChannelConfig(data) {
+ return request({
+ url: '/system/notify/channel/config',
+ method: 'post',
+ data: data
+ })
+}
+
+// 淇敼閫氱煡娓犻亾閰嶇疆
+export function updateChannelConfig(data) {
+ return request({
+ url: '/system/notify/channel/config',
+ method: 'put',
+ data: data
+ })
+}
+
+// 鍒犻櫎閫氱煡娓犻亾閰嶇疆
+export function delChannelConfig(id) {
+ return request({
+ url: '/system/notify/channel/config/' + id,
+ method: 'delete'
+ })
+}
\ No newline at end of file
diff --git a/ruoyi-ui/src/api/system/notify/log/index.js b/ruoyi-ui/src/api/system/notify/log/index.js
new file mode 100644
index 0000000..4b46fe3
--- /dev/null
+++ b/ruoyi-ui/src/api/system/notify/log/index.js
@@ -0,0 +1,27 @@
+import request from '@/utils/request'
+
+// 鏌ヨ閫氱煡鍙戦�佹棩蹇楀垪琛�
+export function listNotifySendLog(query) {
+ return request({
+ url: '/system/notify/log/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鑾峰彇閫氱煡鍙戦�佹棩蹇楄缁嗕俊鎭�
+export function getNotifySendLog(id) {
+ return request({
+ url: '/system/notify/log/' + id,
+ method: 'get'
+ })
+}
+
+// 瀵煎嚭閫氱煡鍙戦�佹棩蹇�
+export function exportNotifySendLog(query) {
+ return request({
+ url: '/system/notify/log/export',
+ method: 'post',
+ params: query
+ })
+}
\ No newline at end of file
diff --git a/ruoyi-ui/src/api/system/notify/task/index.js b/ruoyi-ui/src/api/system/notify/task/index.js
new file mode 100644
index 0000000..69058da
--- /dev/null
+++ b/ruoyi-ui/src/api/system/notify/task/index.js
@@ -0,0 +1,27 @@
+import request from '@/utils/request'
+
+// 鏌ヨ閫氱煡浠诲姟鍒楄〃
+export function listNotifyTask(query) {
+ return request({
+ url: '/system/notify/task/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鑾峰彇閫氱煡浠诲姟璇︾粏淇℃伅
+export function getNotifyTask(id) {
+ return request({
+ url: '/system/notify/task/' + id,
+ method: 'get'
+ })
+}
+
+// 瀵煎嚭閫氱煡浠诲姟
+export function exportNotifyTask(query) {
+ return request({
+ url: '/system/notify/task/export',
+ method: 'post',
+ params: query
+ })
+}
\ No newline at end of file
diff --git a/ruoyi-ui/src/views/system/mileageStats/index.vue b/ruoyi-ui/src/views/system/mileageStats/index.vue
index 4468509..0cbe724 100644
--- a/ruoyi-ui/src/views/system/mileageStats/index.vue
+++ b/ruoyi-ui/src/views/system/mileageStats/index.vue
@@ -168,8 +168,30 @@
<!-- 鎵嬪姩缁熻瀵硅瘽妗� -->
<el-dialog title="鎵嬪姩閲岀▼缁熻" :visible.sync="calculateOpen" width="500px" append-to-body>
<el-form ref="calculateForm" :model="calculateForm" :rules="calculateRules" label-width="100px">
- <el-form-item label="杞﹁締ID" prop="vehicleId">
- <el-input v-model="calculateForm.vehicleId" placeholder="璇疯緭鍏ヨ溅杈咺D" type="number" />
+ <el-form-item label="杞︾墝鍙�" prop="vehicleId">
+ <el-select
+ v-model="calculateForm.vehicleId"
+ placeholder="璇疯緭鍏ヨ溅鐗屽彿鎼滅储"
+ filterable
+ remote
+ :remote-method="searchVehicles"
+ :loading="vehicleSearchLoading"
+ clearable
+ style="width: 100%"
+ @change="handleVehicleChange"
+ >
+ <el-option
+ v-for="vehicle in vehicleOptions"
+ :key="vehicle.vehicleId"
+ :label="vehicle.vehicleNo"
+ :value="vehicle.vehicleId"
+ >
+ <span style="float: left">{{ vehicle.vehicleNo }}</span>
+ <span style="float: right; color: #8492a6; font-size: 13px" v-if="vehicle.deptName">
+ {{ vehicle.deptName }}
+ </span>
+ </el-option>
+ </el-select>
</el-form-item>
<el-form-item label="缁熻鏃ユ湡" prop="statDate">
<el-date-picker
@@ -297,6 +319,7 @@
<script>
import { listMileageStats, getMileageStats, delMileageStats, calculateMileageStats, batchCalculateMileageStats, getSegmentsByDateRange } from "@/api/system/mileageStats";
import { listDept } from "@/api/system/dept";
+import { listVehicle } from "@/api/system/vehicle";
export default {
name: "MileageStats",
@@ -338,6 +361,10 @@
calculateLoading: false,
// 鎵归噺缁熻鍔犺浇鐘舵��
batchCalculateLoading: false,
+ // 杞﹁締鎼滅储鍔犺浇鐘舵��
+ vehicleSearchLoading: false,
+ // 杞﹁締閫夐」鍒楄〃
+ vehicleOptions: [],
// 鏌ヨ鍙傛暟
queryParams: {
pageNum: 1,
@@ -359,7 +386,7 @@
// 鎵嬪姩缁熻琛ㄥ崟鏍¢獙
calculateRules: {
vehicleId: [
- { required: true, message: "杞﹁締ID涓嶈兘涓虹┖", trigger: "blur" }
+ { required: true, message: "璇烽�夋嫨杞﹁締", trigger: "change" }
],
statDate: [
{ required: true, message: "缁熻鏃ユ湡涓嶈兘涓虹┖", trigger: "change" }
@@ -413,7 +440,43 @@
/** 鎵嬪姩缁熻鎸夐挳鎿嶄綔 */
handleCalculate() {
this.reset();
+ this.vehicleOptions = [];
this.calculateOpen = true;
+ // 鎵撳紑瀵硅瘽妗嗘椂鍔犺浇涓�浜涜溅杈嗘暟鎹�
+ this.searchVehicles('');
+ },
+ /** 鎼滅储杞﹁締 */
+ searchVehicles(query) {
+ if (query !== '') {
+ this.vehicleSearchLoading = true;
+ listVehicle({
+ vehicleNo: query,
+ pageNum: 1,
+ pageSize: 50
+ }).then(response => {
+ this.vehicleOptions = response.rows || [];
+ this.vehicleSearchLoading = false;
+ }).catch(() => {
+ this.vehicleSearchLoading = false;
+ });
+ } else {
+ // 濡傛灉鏌ヨ涓虹┖锛屽姞杞藉墠50鏉¤溅杈嗘暟鎹�
+ this.vehicleSearchLoading = true;
+ listVehicle({
+ pageNum: 1,
+ pageSize: 50
+ }).then(response => {
+ this.vehicleOptions = response.rows || [];
+ this.vehicleSearchLoading = false;
+ }).catch(() => {
+ this.vehicleSearchLoading = false;
+ });
+ }
+ },
+ /** 杞﹁締閫夋嫨鍙樺寲 */
+ handleVehicleChange(value) {
+ // 鍙互鍦ㄨ繖閲屾坊鍔犻澶栫殑澶勭悊閫昏緫
+ console.log('閫夋嫨鐨勮溅杈咺D:', value);
},
/** 鎵归噺缁熻鎸夐挳鎿嶄綔 */
handleBatchCalculate() {
diff --git a/ruoyi-ui/src/views/system/notify/channelConfig.vue b/ruoyi-ui/src/views/system/notify/channelConfig.vue
new file mode 100644
index 0000000..f96689c
--- /dev/null
+++ b/ruoyi-ui/src/views/system/notify/channelConfig.vue
@@ -0,0 +1,311 @@
+<template>
+ <div class="app-container">
+ <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+ <el-form-item label="閫氱煡绫诲瀷" prop="notifyType">
+ <el-select v-model="queryParams.notifyType" placeholder="璇烽�夋嫨閫氱煡绫诲瀷" clearable>
+ <el-option label="浠诲姟鍒嗛厤" value="TASK_ASSIGN" />
+ <el-option label="鐘舵�佸彉鏇�" value="STATUS_CHANGE" />
+ <el-option label="浠诲姟鍒涘缓" value="TASK_CREATE" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="娓犻亾" prop="channel">
+ <el-select v-model="queryParams.channel" placeholder="璇烽�夋嫨娓犻亾" clearable>
+ <el-option label="寰俊璁㈤槄娑堟伅" value="WECHAT" />
+ <el-option label="鐭俊" value="SMS" />
+ <el-option label="绔欏唴娑堟伅" value="SITE_MSG" />
+ <el-option label="APP鎺ㄩ��" value="APP_PUSH" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鏄惁鍚敤" prop="enabled">
+ <el-select v-model="queryParams.enabled" placeholder="璇烽�夋嫨鍚敤鐘舵��" clearable>
+ <el-option label="鍚敤" value="1" />
+ <el-option label="绂佺敤" value="0" />
+ </el-select>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button
+ type="primary"
+ plain
+ icon="el-icon-plus"
+ size="mini"
+ @click="handleAdd"
+ v-hasPermi="['system:notify:channel:config:add']"
+ >鏂板</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="success"
+ plain
+ icon="el-icon-edit"
+ size="mini"
+ :disabled="single"
+ @click="handleUpdate"
+ v-hasPermi="['system:notify:channel:config:edit']"
+ >淇敼</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="danger"
+ plain
+ icon="el-icon-delete"
+ size="mini"
+ :disabled="multiple"
+ @click="handleDelete"
+ v-hasPermi="['system:notify:channel:config:remove']"
+ >鍒犻櫎</el-button>
+ </el-col>
+ <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+ </el-row>
+
+ <el-table v-loading="loading" :data="channelConfigList" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="55" align="center" />
+ <el-table-column label="ID" align="center" prop="id" />
+ <el-table-column label="閫氱煡绫诲瀷" align="center" prop="notifyType">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_notify_type" :value="scope.row.notifyType"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="娓犻亾" align="center" prop="channel">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_notify_channel" :value="scope.row.channel"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="鏄惁鍚敤" align="center" prop="enabled">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_enabled_disabled" :value="scope.row.enabled"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="浼樺厛绾�" align="center" prop="priority" />
+ <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+ <template slot-scope="scope">
+ <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+ <template slot-scope="scope">
+ <el-button
+ size="mini"
+ type="text"
+ icon="el-icon-edit"
+ @click="handleUpdate(scope.row)"
+ v-hasPermi="['system:notify:channel:config:edit']"
+ >淇敼</el-button>
+ <el-button
+ size="mini"
+ type="text"
+ icon="el-icon-delete"
+ @click="handleDelete(scope.row)"
+ v-hasPermi="['system:notify:channel:config:remove']"
+ >鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <pagination
+ v-show="total>0"
+ :total="total"
+ :page.sync="queryParams.pageNum"
+ :limit.sync="queryParams.pageSize"
+ @pagination="getList"
+ />
+
+ <!-- 娣诲姞鎴栦慨鏀归�氱煡娓犻亾閰嶇疆瀵硅瘽妗� -->
+ <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+ <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+ <el-form-item label="閫氱煡绫诲瀷" prop="notifyType">
+ <el-select v-model="form.notifyType" placeholder="璇烽�夋嫨閫氱煡绫诲瀷" style="width: 100%">
+ <el-option label="浠诲姟鍒嗛厤" value="TASK_ASSIGN" />
+ <el-option label="鐘舵�佸彉鏇�" value="STATUS_CHANGE" />
+ <el-option label="浠诲姟鍒涘缓" value="TASK_CREATE" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="娓犻亾" prop="channel">
+ <el-select v-model="form.channel" placeholder="璇烽�夋嫨娓犻亾" style="width: 100%">
+ <el-option label="寰俊璁㈤槄娑堟伅" value="WECHAT" />
+ <el-option label="鐭俊" value="SMS" />
+ <el-option label="绔欏唴娑堟伅" value="SITE_MSG" />
+ <el-option label="APP鎺ㄩ��" value="APP_PUSH" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鏄惁鍚敤" prop="enabled">
+ <el-radio-group v-model="form.enabled">
+ <el-radio label="1">鍚敤</el-radio>
+ <el-radio label="0">绂佺敤</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ <el-form-item label="浼樺厛绾�" prop="priority">
+ <el-input-number v-model="form.priority" controls-position="right" :min="0" :max="999" />
+ </el-form-item>
+ <el-form-item label="澶囨敞" prop="remark">
+ <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+ </el-form-item>
+ </el-form>
+ <div slot="footer" class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+ <el-button @click="cancel">鍙� 娑�</el-button>
+ </div>
+ </el-dialog>
+ </div>
+</template>
+
+<script>
+import { listChannelConfig, getChannelConfig, addChannelConfig, updateChannelConfig, delChannelConfig } from "@/api/system/notify/channelConfig";
+
+export default {
+ name: "NotifyChannelConfig",
+ dicts: ['sys_notify_type', 'sys_notify_channel', 'sys_enabled_disabled'],
+ data() {
+ return {
+ // 閬僵灞�
+ loading: true,
+ // 閫変腑鏁扮粍
+ ids: [],
+ // 闈炲崟涓鐢�
+ single: true,
+ // 闈炲涓鐢�
+ multiple: true,
+ // 鏄剧ず鎼滅储鏉′欢
+ showSearch: true,
+ // 鎬绘潯鏁�
+ total: 0,
+ // 閫氱煡娓犻亾閰嶇疆琛ㄦ牸鏁版嵁
+ channelConfigList: [],
+ // 寮瑰嚭灞傛爣棰�
+ title: "",
+ // 鏄惁鏄剧ず寮瑰嚭灞�
+ open: false,
+ // 鏌ヨ鍙傛暟
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ notifyType: null,
+ channel: null,
+ enabled: null
+ },
+ // 琛ㄥ崟鍙傛暟
+ form: {},
+ // 琛ㄥ崟鏍¢獙
+ rules: {
+ notifyType: [
+ { required: true, message: "閫氱煡绫诲瀷涓嶈兘涓虹┖", trigger: "change" }
+ ],
+ channel: [
+ { required: true, message: "娓犻亾涓嶈兘涓虹┖", trigger: "change" }
+ ],
+ enabled: [
+ { required: true, message: "鏄惁鍚敤涓嶈兘涓虹┖", trigger: "change" }
+ ],
+ priority: [
+ { required: true, message: "浼樺厛绾т笉鑳戒负绌�", trigger: "blur" }
+ ]
+ }
+ };
+ },
+ created() {
+ this.getList();
+ },
+ methods: {
+ /** 鏌ヨ閫氱煡娓犻亾閰嶇疆鍒楄〃 */
+ getList() {
+ this.loading = true;
+ listChannelConfig(this.queryParams).then(response => {
+ this.channelConfigList = response.rows;
+ this.total = response.total;
+ this.loading = false;
+ });
+ },
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ handleQuery() {
+ this.queryParams.pageNum = 1;
+ this.getList();
+ },
+ /** 閲嶇疆鎸夐挳鎿嶄綔 */
+ resetQuery() {
+ this.resetForm("queryForm");
+ this.handleQuery();
+ },
+ /** 澶氶�夋閫変腑鏁版嵁 */
+ handleSelectionChange(selection) {
+ this.ids = selection.map(item => item.id)
+ this.single = selection.length!==1
+ this.multiple = !selection.length
+ },
+ /** 鏂板鎸夐挳鎿嶄綔 */
+ handleAdd() {
+ this.reset();
+ this.open = true;
+ this.title = "娣诲姞閫氱煡娓犻亾閰嶇疆";
+ },
+ /** 淇敼鎸夐挳鎿嶄綔 */
+ handleUpdate(row) {
+ this.reset();
+ const id = row.id || this.ids
+ getChannelConfig(id).then(response => {
+ this.form = response.data;
+ this.open = true;
+ this.title = "淇敼閫氱煡娓犻亾閰嶇疆";
+ });
+ },
+ /** 鎻愪氦鎸夐挳 */
+ submitForm() {
+ this.$refs["form"].validate(valid => {
+ if (valid) {
+ if (this.form.id != null) {
+ updateChannelConfig(this.form).then(response => {
+ this.$modal.msgSuccess("淇敼鎴愬姛");
+ this.open = false;
+ this.getList();
+ });
+ } else {
+ addChannelConfig(this.form).then(response => {
+ this.$modal.msgSuccess("鏂板鎴愬姛");
+ this.open = false;
+ this.getList();
+ });
+ }
+ }
+ });
+ },
+ /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+ handleDelete(row) {
+ const ids = row.id || this.ids;
+ this.$modal.confirm('鏄惁纭鍒犻櫎閫氱煡娓犻亾閰嶇疆缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+ return delChannelConfig(ids);
+ }).then(() => {
+ this.getList();
+ this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ }).catch(() => {});
+ },
+ /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+ handleExport() {
+ this.download('system/notify/channel/config/export', {
+ ...this.queryParams
+ }, `channel_config_${new Date().getTime()}.xlsx`)
+ },
+ /** 琛ㄥ崟閲嶇疆 */
+ reset() {
+ this.form = {
+ id: null,
+ notifyType: null,
+ channel: null,
+ enabled: "1",
+ priority: 0,
+ remark: null
+ };
+ this.resetForm("form");
+ },
+ /** 鍙栨秷鎸夐挳 */
+ cancel() {
+ this.open = false;
+ this.reset();
+ }
+ }
+};
+</script>
\ No newline at end of file
diff --git a/ruoyi-ui/src/views/system/notify/log/index.vue b/ruoyi-ui/src/views/system/notify/log/index.vue
new file mode 100644
index 0000000..fbb1b60
--- /dev/null
+++ b/ruoyi-ui/src/views/system/notify/log/index.vue
@@ -0,0 +1,322 @@
+<template>
+ <div class="app-container">
+ <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+ <el-form-item label="浠诲姟ID" prop="taskId">
+ <el-input
+ v-model="queryParams.taskId"
+ placeholder="璇疯緭鍏ヤ换鍔D"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="閫氱煡浠诲姟ID" prop="notifyTaskId">
+ <el-input
+ v-model="queryParams.notifyTaskId"
+ placeholder="璇疯緭鍏ラ�氱煡浠诲姟ID"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="鐢ㄦ埛ID" prop="userId">
+ <el-input
+ v-model="queryParams.userId"
+ placeholder="璇疯緭鍏ョ敤鎴稩D"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="鐢ㄦ埛濮撳悕" prop="userName">
+ <el-input
+ v-model="queryParams.userName"
+ placeholder="璇疯緭鍏ョ敤鎴峰鍚�"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="閫氱煡绫诲瀷" prop="notifyType">
+ <el-select v-model="queryParams.notifyType" placeholder="璇烽�夋嫨閫氱煡绫诲瀷" clearable>
+ <el-option label="浠诲姟鍒嗛厤" value="TASK_ASSIGN" />
+ <el-option label="鐘舵�佸彉鏇�" value="STATUS_CHANGE" />
+ <el-option label="浠诲姟鍒涘缓" value="TASK_CREATE" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="閫氱煡娓犻亾" prop="channel">
+ <el-select v-model="queryParams.channel" placeholder="璇烽�夋嫨閫氱煡娓犻亾" clearable>
+ <el-option label="寰俊璁㈤槄娑堟伅" value="WECHAT" />
+ <el-option label="鐭俊" value="SMS" />
+ <el-option label="绔欏唴娑堟伅" value="SITE_MSG" />
+ <el-option label="APP鎺ㄩ��" value="APP_PUSH" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍙戦�佺姸鎬�" prop="sendStatus">
+ <el-select v-model="queryParams.sendStatus" placeholder="璇烽�夋嫨鍙戦�佺姸鎬�" clearable>
+ <el-option label="寰呭彂閫�" value="0" />
+ <el-option label="鍙戦�佹垚鍔�" value="1" />
+ <el-option label="鍙戦�佸け璐�" value="2" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍙戦�佹椂闂�">
+ <el-date-picker
+ v-model="dateRange"
+ style="width: 240px"
+ value-format="yyyy-MM-dd"
+ type="daterange"
+ range-separator="-"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ ></el-date-picker>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button
+ type="warning"
+ plain
+ icon="el-icon-download"
+ size="mini"
+ @click="handleExport"
+ v-hasPermi="['system:notify:log:export']"
+ >瀵煎嚭</el-button>
+ </el-col>
+ <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+ </el-row>
+
+ <el-table v-loading="loading" :data="notifySendLogList" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="55" align="center" />
+ <el-table-column label="ID" align="center" prop="id" />
+ <el-table-column label="閫氱煡浠诲姟ID" align="center" prop="notifyTaskId" />
+ <el-table-column label="浠诲姟ID" align="center" prop="taskId" />
+ <el-table-column label="鐢ㄦ埛ID" align="center" prop="userId" />
+ <el-table-column label="鐢ㄦ埛濮撳悕" align="center" prop="userName" />
+ <el-table-column label="閫氱煡绫诲瀷" align="center" prop="notifyType">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_notify_type" :value="scope.row.notifyType"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="閫氱煡娓犻亾" align="center" prop="channel">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_notify_channel" :value="scope.row.channel"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍙戦�佺姸鎬�" align="center" prop="sendStatus">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_notify_send_status" :value="scope.row.sendStatus"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍙戦�佹椂闂�" align="center" prop="sendTime" width="180">
+ <template slot-scope="scope">
+ <span>{{ parseTime(scope.row.sendTime) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍙戦�佺粨鏋�" align="center" prop="sendResult" show-overflow-tooltip />
+ <el-table-column label="閲嶈瘯娆℃暟" align="center" prop="retryCount" />
+ <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+ <template slot-scope="scope">
+ <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+ <template slot-scope="scope">
+ <el-button
+ size="mini"
+ type="text"
+ icon="el-icon-view"
+ @click="handleView(scope.row)"
+ v-hasPermi="['system:notify:log:query']"
+ >璇︽儏</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <pagination
+ v-show="total>0"
+ :total="total"
+ :page.sync="queryParams.pageNum"
+ :limit.sync="queryParams.pageSize"
+ @pagination="getList"
+ />
+
+ <!-- 閫氱煡鍙戦�佹棩蹇楄鎯呭璇濇 -->
+ <el-dialog :title="title" :visible.sync="open" width="780px" append-to-body>
+ <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="閫氱煡浠诲姟ID锛�">{{ form.notifyTaskId }}</el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="浠诲姟ID锛�">{{ form.taskId }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鐢ㄦ埛ID锛�">{{ form.userId }}</el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐢ㄦ埛濮撳悕锛�">{{ form.userName }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="閫氱煡绫诲瀷锛�">
+ <dict-tag :options="dict.type.sys_notify_type" :value="form.notifyType"/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閫氱煡娓犻亾锛�">
+ <dict-tag :options="dict.type.sys_notify_channel" :value="form.channel"/>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鍙戦�佺姸鎬侊細">
+ <dict-tag :options="dict.type.sys_notify_send_status" :value="form.sendStatus"/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閲嶈瘯娆℃暟锛�">{{ form.retryCount }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="24">
+ <el-form-item label="鍙戦�佹椂闂达細">{{ form.sendTime }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="24">
+ <el-form-item label="鍙戦�佺粨鏋滐細">{{ form.sendResult }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="24">
+ <el-form-item label="鍝嶅簲娑堟伅锛�">{{ form.responseMsg }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鍒涘缓浜猴細">{{ form.createBy }}</el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍒涘缓鏃堕棿锛�">{{ form.createTime }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鏇存柊浜猴細">{{ form.updateBy }}</el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏇存柊鏃堕棿锛�">{{ form.updateTime }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="24">
+ <el-form-item label="澶囨敞锛�">{{ form.remark }}</el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <div slot="footer" class="dialog-footer">
+ <el-button @click="open = false">鍏� 闂�</el-button>
+ </div>
+ </el-dialog>
+ </div>
+</template>
+
+<script>
+import { listNotifySendLog, getNotifySendLog } from "@/api/system/notify/log";
+
+export default {
+ name: "NotifySendLog",
+ dicts: ['sys_notify_type', 'sys_notify_channel', 'sys_notify_send_status'],
+ data() {
+ return {
+ // 閬僵灞�
+ loading: true,
+ // 閫変腑鏁扮粍
+ ids: [],
+ // 闈炲崟涓鐢�
+ single: true,
+ // 闈炲涓鐢�
+ multiple: true,
+ // 鏄剧ず鎼滅储鏉′欢
+ showSearch: true,
+ // 鎬绘潯鏁�
+ total: 0,
+ // 閫氱煡鍙戦�佹棩蹇楄〃鏍兼暟鎹�
+ notifySendLogList: [],
+ // 寮瑰嚭灞傛爣棰�
+ title: "",
+ // 鏄惁鏄剧ず寮瑰嚭灞�
+ open: false,
+ // 鏃ユ湡鑼冨洿
+ dateRange: [],
+ // 鏌ヨ鍙傛暟
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ taskId: null,
+ notifyTaskId: null,
+ userId: null,
+ userName: null,
+ notifyType: null,
+ channel: null,
+ sendStatus: null
+ },
+ // 琛ㄥ崟鍙傛暟
+ form: {},
+ // 琛ㄥ崟鏍¢獙
+ rules: {}
+ };
+ },
+ created() {
+ this.getList();
+ },
+ methods: {
+ /** 鏌ヨ閫氱煡鍙戦�佹棩蹇楀垪琛� */
+ getList() {
+ this.loading = true;
+ listNotifySendLog(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+ this.notifySendLogList = response.rows;
+ this.total = response.total;
+ this.loading = false;
+ });
+ },
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ handleQuery() {
+ this.queryParams.pageNum = 1;
+ this.getList();
+ },
+ /** 閲嶇疆鎸夐挳鎿嶄綔 */
+ resetQuery() {
+ this.dateRange = [];
+ this.resetForm("queryForm");
+ this.handleQuery();
+ },
+ /** 澶氶�夋閫変腑鏁版嵁 */
+ handleSelectionChange(selection) {
+ this.ids = selection.map(item => item.id)
+ this.single = selection.length!==1
+ this.multiple = !selection.length
+ },
+ /** 璇︽儏鎸夐挳鎿嶄綔 */
+ handleView(row) {
+ this.open = true;
+ this.title = "閫氱煡鍙戦�佹棩蹇楄鎯�";
+ const id = row.id || this.ids
+ getNotifySendLog(id).then(response => {
+ this.form = response.data;
+ });
+ },
+ /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+ handleExport() {
+ this.download('system/notify/log/export', {
+ ...this.queryParams
+ }, `notify_send_log_${new Date().getTime()}.xlsx`)
+ }
+ }
+};
+</script>
\ No newline at end of file
diff --git a/ruoyi-ui/src/views/system/notify/task/index.vue b/ruoyi-ui/src/views/system/notify/task/index.vue
new file mode 100644
index 0000000..b56d73c
--- /dev/null
+++ b/ruoyi-ui/src/views/system/notify/task/index.vue
@@ -0,0 +1,310 @@
+<template>
+ <div class="app-container">
+ <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+ <el-form-item label="浠诲姟ID" prop="taskId">
+ <el-input
+ v-model="queryParams.taskId"
+ placeholder="璇疯緭鍏ヤ换鍔D"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="浠诲姟缂栧彿" prop="taskCode">
+ <el-input
+ v-model="queryParams.taskCode"
+ placeholder="璇疯緭鍏ヤ换鍔$紪鍙�"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="閫氱煡绫诲瀷" prop="notifyType">
+ <el-select v-model="queryParams.notifyType" placeholder="璇烽�夋嫨閫氱煡绫诲瀷" clearable>
+ <el-option label="浠诲姟鍒嗛厤" value="TASK_ASSIGN" />
+ <el-option label="鐘舵�佸彉鏇�" value="STATUS_CHANGE" />
+ <el-option label="浠诲姟鍒涘缓" value="TASK_CREATE" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鐢ㄦ埛ID" prop="userId">
+ <el-input
+ v-model="queryParams.userId"
+ placeholder="璇疯緭鍏ョ敤鎴稩D"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="鐢ㄦ埛濮撳悕" prop="userName">
+ <el-input
+ v-model="queryParams.userName"
+ placeholder="璇疯緭鍏ョ敤鎴峰鍚�"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="澶勭悊鐘舵��" prop="status">
+ <el-select v-model="queryParams.status" placeholder="璇烽�夋嫨澶勭悊鐘舵��" clearable>
+ <el-option label="寰呭鐞�" value="0" />
+ <el-option label="澶勭悊涓�" value="1" />
+ <el-option label="宸插畬鎴�" value="2" />
+ <el-option label="澶辫触" value="3" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍒涘缓鏃堕棿">
+ <el-date-picker
+ v-model="dateRange"
+ style="width: 240px"
+ value-format="yyyy-MM-dd"
+ type="daterange"
+ range-separator="-"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ ></el-date-picker>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button
+ type="warning"
+ plain
+ icon="el-icon-download"
+ size="mini"
+ @click="handleExport"
+ v-hasPermi="['system:notify:task:export']"
+ >瀵煎嚭</el-button>
+ </el-col>
+ <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+ </el-row>
+
+ <el-table v-loading="loading" :data="notifyTaskList" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="55" align="center" />
+ <el-table-column label="ID" align="center" prop="id" />
+ <el-table-column label="浠诲姟ID" align="center" prop="taskId" />
+ <el-table-column label="浠诲姟缂栧彿" align="center" prop="taskCode" />
+ <el-table-column label="閫氱煡绫诲瀷" align="center" prop="notifyType">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_notify_type" :value="scope.row.notifyType"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="鐢ㄦ埛ID" align="center" prop="userId" />
+ <el-table-column label="鐢ㄦ埛濮撳悕" align="center" prop="userName" />
+ <el-table-column label="鎵嬫満鍙�" align="center" prop="userPhone" />
+ <el-table-column label="鏍囬" align="center" prop="title" />
+ <el-table-column label="鍐呭" align="center" prop="content" show-overflow-tooltip />
+ <el-table-column label="澶勭悊鐘舵��" align="center" prop="status">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_notify_task_status" :value="scope.row.status"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="閲嶈瘯娆℃暟" align="center" prop="retryCount" />
+ <el-table-column label="鏈�澶ч噸璇�" align="center" prop="maxRetry" />
+ <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+ <template slot-scope="scope">
+ <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+ <template slot-scope="scope">
+ <el-button
+ size="mini"
+ type="text"
+ icon="el-icon-view"
+ @click="handleView(scope.row)"
+ v-hasPermi="['system:notify:task:query']"
+ >璇︽儏</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <pagination
+ v-show="total>0"
+ :total="total"
+ :page.sync="queryParams.pageNum"
+ :limit.sync="queryParams.pageSize"
+ @pagination="getList"
+ />
+
+ <!-- 閫氱煡浠诲姟璇︽儏瀵硅瘽妗� -->
+ <el-dialog :title="title" :visible.sync="open" width="780px" append-to-body>
+ <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="浠诲姟ID锛�">{{ form.taskId }}</el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="浠诲姟缂栧彿锛�">{{ form.taskCode }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="閫氱煡绫诲瀷锛�">
+ <dict-tag :options="dict.type.sys_notify_type" :value="form.notifyType"/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="澶勭悊鐘舵�侊細">
+ <dict-tag :options="dict.type.sys_notify_task_status" :value="form.status"/>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鐢ㄦ埛ID锛�">{{ form.userId }}</el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐢ㄦ埛濮撳悕锛�">{{ form.userName }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鎵嬫満鍙凤細">{{ form.userPhone }}</el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閲嶈瘯娆℃暟锛�">{{ form.retryCount }} / {{ form.maxRetry }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="24">
+ <el-form-item label="鏍囬锛�">{{ form.title }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="24">
+ <el-form-item label="鍐呭锛�">{{ form.content }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="24">
+ <el-form-item label="鎵╁睍鏁版嵁锛�">{{ form.extraData }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="24">
+ <el-form-item label="閿欒淇℃伅锛�">{{ form.errorMsg }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鍒涘缓浜猴細">{{ form.createBy }}</el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍒涘缓鏃堕棿锛�">{{ form.createTime }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鏇存柊浜猴細">{{ form.updateBy }}</el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏇存柊鏃堕棿锛�">{{ form.updateTime }}</el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="24">
+ <el-form-item label="澶囨敞锛�">{{ form.remark }}</el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <div slot="footer" class="dialog-footer">
+ <el-button @click="open = false">鍏� 闂�</el-button>
+ </div>
+ </el-dialog>
+ </div>
+</template>
+
+<script>
+import { listNotifyTask, getNotifyTask } from "@/api/system/notify/task/index";
+
+export default {
+ name: "NotifyTask",
+ dicts: ['sys_notify_type', 'sys_notify_task_status'],
+ data() {
+ return {
+ // 閬僵灞�
+ loading: true,
+ // 閫変腑鏁扮粍
+ ids: [],
+ // 闈炲崟涓鐢�
+ single: true,
+ // 闈炲涓鐢�
+ multiple: true,
+ // 鏄剧ず鎼滅储鏉′欢
+ showSearch: true,
+ // 鎬绘潯鏁�
+ total: 0,
+ // 閫氱煡浠诲姟琛ㄦ牸鏁版嵁
+ notifyTaskList: [],
+ // 寮瑰嚭灞傛爣棰�
+ title: "",
+ // 鏄惁鏄剧ず寮瑰嚭灞�
+ open: false,
+ // 鏃ユ湡鑼冨洿
+ dateRange: [],
+ // 鏌ヨ鍙傛暟
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ taskId: null,
+ taskCode: null,
+ notifyType: null,
+ userId: null,
+ userName: null,
+ status: null
+ },
+ // 琛ㄥ崟鍙傛暟
+ form: {},
+ // 琛ㄥ崟鏍¢獙
+ rules: {}
+ };
+ },
+ created() {
+ this.getList();
+ },
+ methods: {
+ /** 鏌ヨ閫氱煡浠诲姟鍒楄〃 */
+ getList() {
+ this.loading = true;
+ listNotifyTask(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+ this.notifyTaskList = response.rows;
+ this.total = response.total;
+ this.loading = false;
+ });
+ },
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ handleQuery() {
+ this.queryParams.pageNum = 1;
+ this.getList();
+ },
+ /** 閲嶇疆鎸夐挳鎿嶄綔 */
+ resetQuery() {
+ this.dateRange = [];
+ this.resetForm("queryForm");
+ this.handleQuery();
+ },
+ /** 澶氶�夋閫変腑鏁版嵁 */
+ handleSelectionChange(selection) {
+ this.ids = selection.map(item => item.id)
+ this.single = selection.length!==1
+ this.multiple = !selection.length
+ },
+ /** 璇︽儏鎸夐挳鎿嶄綔 */
+ handleView(row) {
+ this.open = true;
+ this.title = "閫氱煡浠诲姟璇︽儏";
+ const id = row.id || this.ids
+ getNotifyTask(id).then(response => {
+ this.form = response.data;
+ });
+ },
+ /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+ handleExport() {
+ this.download('system/notify/task/export', {
+ ...this.queryParams
+ }, `notify_task_${new Date().getTime()}.xlsx`)
+ }
+ }
+};
+</script>
\ No newline at end of file
diff --git a/sql/notify_dict.sql b/sql/notify_dict.sql
new file mode 100644
index 0000000..be76d42
--- /dev/null
+++ b/sql/notify_dict.sql
@@ -0,0 +1,51 @@
+-- 閫氱煡绠$悊鐩稿叧瀛楀吀鏁版嵁
+
+-- 1. 閫氱煡绫诲瀷瀛楀吀
+INSERT INTO sys_dict_type(dict_name, dict_type, status, create_by, create_time, remark)
+VALUES
+('閫氱煡绫诲瀷', 'sys_notify_type', '0', 'admin', SYSDATE(), '閫氱煡绫诲瀷鍒楄〃');
+
+-- 閫氱煡绫诲瀷瀛楀吀鏁版嵁
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark)
+VALUES
+(1, '浠诲姟鍒嗛厤', 'TASK_ASSIGN', 'sys_notify_type', '', 'primary', 'Y', '0', 'admin', SYSDATE(), '浠诲姟鍒嗛厤閫氱煡'),
+(2, '鐘舵�佸彉鏇�', 'STATUS_CHANGE', 'sys_notify_type', '', 'success', 'N', '0', 'admin', SYSDATE(), '鐘舵�佸彉鏇撮�氱煡'),
+(3, '浠诲姟鍒涘缓', 'TASK_CREATE', 'sys_notify_type', '', 'info', 'N', '0', 'admin', SYSDATE(), '浠诲姟鍒涘缓閫氱煡');
+
+-- 2. 閫氱煡浠诲姟鐘舵�佸瓧鍏�
+INSERT INTO sys_dict_type(dict_name, dict_type, status, create_by, create_time, remark)
+VALUES
+('閫氱煡浠诲姟鐘舵��', 'sys_notify_task_status', '0', 'admin', SYSDATE(), '閫氱煡浠诲姟鐘舵�佸垪琛�');
+
+-- 閫氱煡浠诲姟鐘舵�佸瓧鍏告暟鎹�
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark)
+VALUES
+(1, '寰呭鐞�', '0', 'sys_notify_task_status', '', 'info', 'Y', '0', 'admin', SYSDATE(), '寰呭鐞�'),
+(2, '澶勭悊涓�', '1', 'sys_notify_task_status', '', 'primary', 'N', '0', 'admin', SYSDATE(), '澶勭悊涓�'),
+(3, '宸插畬鎴�', '2', 'sys_notify_task_status', '', 'success', 'N', '0', 'admin', SYSDATE(), '宸插畬鎴�'),
+(4, '澶辫触', '3', 'sys_notify_task_status', '', 'danger', 'N', '0', 'admin', SYSDATE(), '澶辫触');
+
+-- 3. 閫氱煡娓犻亾瀛楀吀
+INSERT INTO sys_dict_type(dict_name, dict_type, status, create_by, create_time, remark)
+VALUES
+('閫氱煡娓犻亾', 'sys_notify_channel', '0', 'admin', SYSDATE(), '閫氱煡娓犻亾鍒楄〃');
+
+-- 閫氱煡娓犻亾瀛楀吀鏁版嵁
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark)
+VALUES
+(1, '寰俊璁㈤槄娑堟伅', 'WECHAT', 'sys_notify_channel', '', 'primary', 'Y', '0', 'admin', SYSDATE(), '寰俊璁㈤槄娑堟伅'),
+(2, '鐭俊', 'SMS', 'sys_notify_channel', '', 'success', 'N', '0', 'admin', SYSDATE(), '鐭俊'),
+(3, '绔欏唴娑堟伅', 'SITE_MSG', 'sys_notify_channel', '', 'info', 'N', '0', 'admin', SYSDATE(), '绔欏唴娑堟伅'),
+(4, 'APP鎺ㄩ��', 'APP_PUSH', 'sys_notify_channel', '', 'warning', 'N', '0', 'admin', SYSDATE(), 'APP鎺ㄩ��');
+
+-- 4. 閫氱煡鍙戦�佺姸鎬佸瓧鍏�
+INSERT INTO sys_dict_type(dict_name, dict_type, status, create_by, create_time, remark)
+VALUES
+('閫氱煡鍙戦�佺姸鎬�', 'sys_notify_send_status', '0', 'admin', SYSDATE(), '閫氱煡鍙戦�佺姸鎬佸垪琛�');
+
+-- 閫氱煡鍙戦�佺姸鎬佸瓧鍏告暟鎹�
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark)
+VALUES
+(1, '寰呭彂閫�', '0', 'sys_notify_send_status', '', 'info', 'Y', '0', 'admin', SYSDATE(), '寰呭彂閫�'),
+(2, '鍙戦�佹垚鍔�', '1', 'sys_notify_send_status', '', 'success', 'N', '0', 'admin', SYSDATE(), '鍙戦�佹垚鍔�'),
+(3, '鍙戦�佸け璐�', '2', 'sys_notify_send_status', '', 'danger', 'N', '0', 'admin', SYSDATE(), '鍙戦�佸け璐�');
\ No newline at end of file
diff --git a/sql/notify_menu.sql b/sql/notify_menu.sql
new file mode 100644
index 0000000..1b83cdf
--- /dev/null
+++ b/sql/notify_menu.sql
@@ -0,0 +1,53 @@
+-- 閫氱煡绠$悊鑿滃崟鍜屾潈闄怱QL
+
+-- 鑿滃崟 SQL
+INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+VALUES
+('閫氱煡绠$悊', 1, 9, 'notify', NULL, 1, 0, 'M', '0', '0', '', 'message', 'admin', SYSDATE(), '', NULL, '閫氱煡绠$悊鐩綍');
+
+-- 鑾峰彇鍒氭彃鍏ョ殑鐖惰彍鍗旾D锛堥渶瑕佹墜鍔ㄦ墽琛屼笅闈㈢殑SQL锛屾浛鎹parentId锛�
+SET @parentId = (SELECT menu_id FROM sys_menu WHERE menu_name = '閫氱煡绠$悊' AND menu_type = 'M');
+
+-- 閫氱煡浠诲姟绠$悊鑿滃崟
+INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+VALUES
+('閫氱煡浠诲姟', @parentId, 1, 'task', 'system/notify/task/index', 1, 0, 'C', '0', '0', 'system:notify:task:list', 'task', 'admin', SYSDATE(), '', NULL, '閫氱煡浠诲姟鑿滃崟');
+
+-- 鑾峰彇鍒氭彃鍏ョ殑閫氱煡浠诲姟鑿滃崟ID
+SET @taskParentId = (SELECT menu_id FROM sys_menu WHERE menu_name = '閫氱煡浠诲姟' AND menu_type = 'C');
+
+-- 閫氱煡浠诲姟鎸夐挳 SQL
+INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+VALUES
+('閫氱煡浠诲姟鏌ヨ', @taskParentId, 1, '#', '', 1, 0, 'F', '0', '0', 'system:notify:task:query', '#', 'admin', SYSDATE(), '', NULL, ''),
+('閫氱煡浠诲姟瀵煎嚭', @taskParentId, 2, '#', '', 1, 0, 'F', '0', '0', 'system:notify:task:export', '#', 'admin', SYSDATE(), '', NULL, '');
+
+-- 閫氱煡鍙戦�佹棩蹇楄彍鍗�
+INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+VALUES
+('鍙戦�佹棩蹇�', @parentId, 2, 'log', 'system/notify/log/index', 1, 0, 'C', '0', '0', 'system:notify:log:list', 'log', 'admin', SYSDATE(), '', NULL, '閫氱煡鍙戦�佹棩蹇楄彍鍗�');
+
+-- 鑾峰彇鍒氭彃鍏ョ殑鍙戦�佹棩蹇楄彍鍗旾D
+SET @logParentId = (SELECT menu_id FROM sys_menu WHERE menu_name = '鍙戦�佹棩蹇�' AND menu_type = 'C');
+
+-- 閫氱煡鍙戦�佹棩蹇楁寜閽� SQL
+INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+VALUES
+('鍙戦�佹棩蹇楁煡璇�', @logParentId, 1, '#', '', 1, 0, 'F', '0', '0', 'system:notify:log:query', '#', 'admin', SYSDATE(), '', NULL, ''),
+('鍙戦�佹棩蹇楀鍑�', @logParentId, 2, '#', '', 1, 0, 'F', '0', '0', 'system:notify:log:export', '#', 'admin', SYSDATE(), '', NULL, '');
+
+-- 閫氱煡娓犻亾閰嶇疆鑿滃崟
+INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+VALUES
+('娓犻亾閰嶇疆', @parentId, 3, 'channelConfig', 'system/notify/channelConfig', 1, 0, 'C', '0', '0', 'system:notify:channel:config:list', 'config', 'admin', SYSDATE(), '', NULL, '閫氱煡娓犻亾閰嶇疆鑿滃崟');
+
+-- 鑾峰彇鍒氭彃鍏ョ殑娓犻亾閰嶇疆鑿滃崟ID
+SET @channelConfigParentId = (SELECT menu_id FROM sys_menu WHERE menu_name = '娓犻亾閰嶇疆' AND menu_type = 'C');
+
+-- 閫氱煡娓犻亾閰嶇疆鎸夐挳 SQL
+INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+VALUES
+('娓犻亾閰嶇疆鏌ヨ', @channelConfigParentId, 1, '#', '', 1, 0, 'F', '0', '0', 'system:notify:channel:config:query', '#', 'admin', SYSDATE(), '', NULL, ''),
+('娓犻亾閰嶇疆鏂板', @channelConfigParentId, 2, '#', '', 1, 0, 'F', '0', '0', 'system:notify:channel:config:add', '#', 'admin', SYSDATE(), '', NULL, ''),
+('娓犻亾閰嶇疆淇敼', @channelConfigParentId, 3, '#', '', 1, 0, 'F', '0', '0', 'system:notify:channel:config:edit', '#', 'admin', SYSDATE(), '', NULL, ''),
+('娓犻亾閰嶇疆鍒犻櫎', @channelConfigParentId, 4, '#', '', 1, 0, 'F', '0', '0', 'system:notify:channel:config:remove', '#', 'admin', SYSDATE(), '', NULL, '');
\ No newline at end of file
diff --git a/sql/sms_config.sql b/sql/sms_config.sql
new file mode 100644
index 0000000..c1b0f43
--- /dev/null
+++ b/sql/sms_config.sql
@@ -0,0 +1,35 @@
+-- ===========================================
+-- 鐭俊鏈嶅姟寮�鍏抽厤缃�
+-- 鐢ㄤ簬鎺у埗绯荤粺鏄惁鍚敤鐭俊閫氱煡鍔熻兘
+-- ===========================================
+
+-- 鎻掑叆鐭俊寮�鍏抽厤缃紙榛樿鍏抽棴锛�
+INSERT INTO sys_config (config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark)
+VALUES
+('鐭俊閫氱煡寮�鍏�', 'sms.enabled', 'false', 'N', 'admin', NOW(), 'admin', NOW(),
+ '鎺у埗鏄惁鍚敤鐭俊閫氱煡鍔熻兘銆倀rue=鍚敤锛宖alse=绂佺敤銆傚叧闂悗绯荤粺灏嗕笉鍐嶅彂閫佷换浣曠煭淇¢�氱煡銆�');
+
+-- ===========================================
+-- 浣跨敤璇存槑锛�
+-- 1. 榛樿鍏抽棴鐭俊鍔熻兘锛岄渶瑕佹墜鍔ㄥ紑鍚�
+-- 2. 寮�鍚墠璇风‘淇濆凡閰嶇疆姝g‘鐨勭煭淇¤处鍙蜂俊鎭�
+-- 3. 鍙湪绯荤粺绠$悊->鍙傛暟璁剧疆涓姩鎬佷慨鏀癸紝鏃犻渶閲嶅惎鏈嶅姟
+--
+-- 閰嶇疆閿鏄庯細
+-- sms.enabled - 鐭俊鏈嶅姟寮�鍏�
+-- true - 鍚敤鐭俊閫氱煡
+-- false - 绂佺敤鐭俊閫氱煡锛堥粯璁わ級
+--
+-- 鐩稿叧閰嶇疆锛堝湪application.yml涓厤缃級锛�
+-- sms.address - 鐭俊鏈嶅姟鍦板潃锛堥粯璁わ細sms.izjun.com:8001锛�
+-- sms.userName - 鐭俊璐﹀彿鐢ㄦ埛鍚�
+-- sms.password - 鐭俊璐﹀彿瀵嗙爜
+-- sms.signName - 鐭俊绛惧悕
+-- sms.taskAssignTemplate - 浠诲姟鍒嗛厤閫氱煡妯℃澘
+-- ===========================================
+
+-- 寮�鍚煭淇″姛鑳斤細
+-- UPDATE sys_config SET config_value = 'true' WHERE config_key = 'sms.enabled';
+
+-- 鍏抽棴鐭俊鍔熻兘锛�
+-- UPDATE sys_config SET config_value = 'false' WHERE config_key = 'sms.enabled';
diff --git a/sql/sys_notify_send_log.sql b/sql/sys_notify_send_log.sql
new file mode 100644
index 0000000..fa0f91b
--- /dev/null
+++ b/sql/sys_notify_send_log.sql
@@ -0,0 +1,52 @@
+-- ===========================================
+-- 閫氱煡鍙戦�佽褰曡〃
+-- 鐢ㄤ簬璁板綍鍚勭被閫氱煡娑堟伅鐨勫彂閫佽褰曪紝瀹炵幇闃查噸鏈哄埗
+-- 纭繚鍚屼竴浠诲姟鍚屼竴浜哄悓涓�閫氱煡绫诲瀷鍙彂閫佷竴娆�
+-- ===========================================
+
+DROP TABLE IF EXISTS `sys_notify_send_log`;
+
+CREATE TABLE `sys_notify_send_log` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+ `task_id` bigint(20) NOT NULL COMMENT '浠诲姟ID',
+ `user_id` bigint(20) NOT NULL COMMENT '鎺ユ敹鐢ㄦ埛ID',
+ `user_name` varchar(64) DEFAULT NULL COMMENT '鎺ユ敹鐢ㄦ埛濮撳悕',
+ `notify_type` varchar(32) NOT NULL COMMENT '閫氱煡绫诲瀷锛歍ASK_ASSIGN-浠诲姟鍒嗛厤, STATUS_CHANGE-鐘舵�佸彉鏇�, TASK_CREATE-浠诲姟鍒涘缓',
+ `channel` varchar(32) NOT NULL COMMENT '閫氱煡娓犻亾锛歐ECHAT-寰俊璁㈤槄娑堟伅, SMS-鐭俊, APP_PUSH-APP鎺ㄩ��, SITE_MSG-绔欏唴娑堟伅',
+ `send_status` char(1) DEFAULT '0' COMMENT '鍙戦�佺姸鎬侊細0-寰呭彂閫�, 1-鍙戦�佹垚鍔�, 2-鍙戦�佸け璐�',
+ `send_time` datetime DEFAULT NULL COMMENT '鍙戦�佹椂闂�',
+ `send_result` varchar(500) DEFAULT NULL COMMENT '鍙戦�佺粨鏋�/閿欒淇℃伅',
+ `retry_count` int(11) DEFAULT 0 COMMENT '閲嶈瘯娆℃暟',
+ `create_time` datetime NOT NULL COMMENT '鍒涘缓鏃堕棿',
+ `create_by` varchar(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+ `update_time` datetime DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+ `update_by` varchar(64) DEFAULT '' COMMENT '鏇存柊鑰�',
+ `remark` varchar(500) DEFAULT NULL COMMENT '澶囨敞',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_task_user_type_channel` (`task_id`, `user_id`, `notify_type`, `channel`) COMMENT '鍚屼竴浠诲姟鍚屼竴鐢ㄦ埛鍚屼竴绫诲瀷鍚屼竴娓犻亾鍙兘鏈変竴鏉¤褰�',
+ KEY `idx_task_id` (`task_id`),
+ KEY `idx_user_id` (`user_id`),
+ KEY `idx_notify_type` (`notify_type`),
+ KEY `idx_send_status` (`send_status`),
+ KEY `idx_create_time` (`create_time`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='閫氱煡鍙戦�佽褰曡〃';
+
+-- ===========================================
+-- 浣跨敤璇存槑锛�
+-- 1. 鍦ㄥ彂閫侀�氱煡鍓嶏紝鍏堟鏌ユ槸鍚﹀凡瀛樺湪鐩稿悓璁板綍
+-- 2. 濡傛灉涓嶅瓨鍦紝鍒欐彃鍏ヨ褰曞苟鍙戦�侀�氱煡
+-- 3. 鍙戦�佹垚鍔熷悗鏇存柊 send_status 涓� 1
+-- 4. 鍙戦�佸け璐ュ悗鏇存柊 send_status 涓� 2锛屽苟璁板綍閿欒淇℃伅
+-- 5. 鍙互閫氳繃瀹氭椂浠诲姟閲嶈瘯鍙戦�佸け璐ョ殑璁板綍
+--
+-- 閫氱煡绫诲瀷璇存槑锛�
+-- TASK_ASSIGN - 浠诲姟鍒嗛厤閫氱煡锛堟柊浠诲姟鎺ㄩ�佺粰鎵ц浜猴級
+-- STATUS_CHANGE - 浠诲姟鐘舵�佸彉鏇撮�氱煡
+-- TASK_CREATE - 浠诲姟鍒涘缓鎴愬姛閫氱煡
+--
+-- 閫氱煡娓犻亾璇存槑锛�
+-- WECHAT - 寰俊灏忕▼搴忚闃呮秷鎭�
+-- SMS - 鐭俊閫氱煡
+-- APP_PUSH - APP鎺ㄩ�侀�氱煡
+-- SITE_MSG - 绯荤粺绔欏唴娑堟伅
+-- ===========================================
diff --git a/sql/sys_notify_task.sql b/sql/sys_notify_task.sql
new file mode 100644
index 0000000..8a06596
--- /dev/null
+++ b/sql/sys_notify_task.sql
@@ -0,0 +1,95 @@
+-- ===========================================
+-- 閫氱煡浠诲姟涓昏〃
+-- 鐢ㄤ簬缁熶竴绠$悊寰呭彂閫佺殑閫氱煡浠诲姟锛岀敱娑堟伅绯荤粺鍐冲畾鍙戦�佹笭閬�
+-- ===========================================
+
+-- 鍒犻櫎鏃ц〃锛堝鏋滈渶瑕侀噸寤猴級
+-- DROP TABLE IF EXISTS `sys_notify_task`;
+
+CREATE TABLE `sys_notify_task` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+ `task_id` bigint(20) NOT NULL COMMENT '鍏宠仈鐨勪笟鍔′换鍔D',
+ `task_code` varchar(64) DEFAULT NULL COMMENT '浠诲姟缂栧彿',
+ `notify_type` varchar(32) NOT NULL COMMENT '閫氱煡绫诲瀷锛歍ASK_ASSIGN-浠诲姟鍒嗛厤, STATUS_CHANGE-鐘舵�佸彉鏇�, TASK_CREATE-浠诲姟鍒涘缓',
+ `user_id` bigint(20) NOT NULL COMMENT '鎺ユ敹鐢ㄦ埛ID',
+ `user_name` varchar(64) DEFAULT NULL COMMENT '鎺ユ敹鐢ㄦ埛濮撳悕',
+ `user_phone` varchar(20) DEFAULT NULL COMMENT '鎺ユ敹鐢ㄦ埛鎵嬫満鍙�',
+ `title` varchar(200) DEFAULT NULL COMMENT '閫氱煡鏍囬',
+ `content` varchar(500) DEFAULT NULL COMMENT '閫氱煡鍐呭',
+ `extra_data` text COMMENT '鎵╁睍鏁版嵁(JSON鏍煎紡锛岀敤浜庢ā鏉垮彉閲忕瓑)',
+ `status` char(1) NOT NULL DEFAULT '0' COMMENT '澶勭悊鐘舵�侊細0-寰呭鐞�, 1-澶勭悊涓�, 2-宸插畬鎴�, 3-澶辫触',
+ `retry_count` int(11) DEFAULT '0' COMMENT '閲嶈瘯娆℃暟',
+ `max_retry` int(11) DEFAULT '3' COMMENT '鏈�澶ч噸璇曟鏁�',
+ `error_msg` varchar(500) DEFAULT NULL COMMENT '閿欒淇℃伅',
+ `create_by` varchar(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+ `create_time` datetime DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+ `update_by` varchar(64) DEFAULT '' COMMENT '鏇存柊鑰�',
+ `update_time` datetime DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+ `remark` varchar(500) DEFAULT NULL COMMENT '澶囨敞',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_task_user_type` (`task_id`, `user_id`, `notify_type`) COMMENT '闃查噸绱㈠紩锛氬悓涓�浠诲姟鍚屼竴鐢ㄦ埛鍚屼竴绫诲瀷鍙兘鏈変竴鏉�',
+ KEY `idx_status` (`status`) COMMENT '鐘舵�佺储寮曪紝鐢ㄤ簬鏌ヨ寰呭鐞嗕换鍔�',
+ KEY `idx_user_id` (`user_id`) COMMENT '鐢ㄦ埛绱㈠紩',
+ KEY `idx_create_time` (`create_time`) COMMENT '鍒涘缓鏃堕棿绱㈠紩'
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='閫氱煡浠诲姟涓昏〃';
+
+-- ===========================================
+-- 閫氱煡娓犻亾閰嶇疆琛�
+-- 鐢ㄤ簬閰嶇疆鍚勭被閫氱煡鍚敤鐨勫彂閫佹笭閬�
+-- ===========================================
+
+CREATE TABLE `sys_notify_channel_config` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+ `notify_type` varchar(32) NOT NULL COMMENT '閫氱煡绫诲瀷',
+ `channel` varchar(32) NOT NULL COMMENT '娓犻亾锛歐ECHAT-寰俊璁㈤槄娑堟伅, SMS-鐭俊, SITE_MSG-绔欏唴娑堟伅, APP_PUSH-APP鎺ㄩ��',
+ `enabled` char(1) NOT NULL DEFAULT '1' COMMENT '鏄惁鍚敤锛�0-绂佺敤, 1-鍚敤',
+ `priority` int(11) DEFAULT '0' COMMENT '浼樺厛绾э紙鏁板瓧瓒婂ぇ浼樺厛绾ц秺楂橈級',
+ `config_json` text COMMENT '娓犻亾閰嶇疆(JSON鏍煎紡锛屽妯℃澘ID绛�)',
+ `create_by` varchar(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+ `create_time` datetime DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+ `update_by` varchar(64) DEFAULT '' COMMENT '鏇存柊鑰�',
+ `update_time` datetime DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+ `remark` varchar(500) DEFAULT NULL COMMENT '澶囨敞',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_type_channel` (`notify_type`, `channel`) COMMENT '閫氱煡绫诲瀷鍜屾笭閬撳敮涓�'
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='閫氱煡娓犻亾閰嶇疆琛�';
+
+-- ===========================================
+-- 鍒濆鍖栭�氱煡娓犻亾閰嶇疆
+-- ===========================================
+
+-- 浠诲姟鍒嗛厤閫氱煡 - 鍚敤寰俊銆佺煭淇°�佺珯鍐呮秷鎭�
+INSERT INTO `sys_notify_channel_config` (`notify_type`, `channel`, `enabled`, `priority`, `config_json`, `create_by`, `create_time`, `remark`) VALUES
+('TASK_ASSIGN', 'SITE_MSG', '1', 100, NULL, 'admin', NOW(), '浠诲姟鍒嗛厤-绔欏唴娑堟伅'),
+('TASK_ASSIGN', 'WECHAT', '1', 90, NULL, 'admin', NOW(), '浠诲姟鍒嗛厤-寰俊璁㈤槄娑堟伅'),
+('TASK_ASSIGN', 'SMS', '0', 80, NULL, 'admin', NOW(), '浠诲姟鍒嗛厤-鐭俊锛堥粯璁ゅ叧闂級');
+
+-- 鐘舵�佸彉鏇撮�氱煡 - 浠呭惎鐢ㄧ珯鍐呮秷鎭�
+INSERT INTO `sys_notify_channel_config` (`notify_type`, `channel`, `enabled`, `priority`, `config_json`, `create_by`, `create_time`, `remark`) VALUES
+('STATUS_CHANGE', 'SITE_MSG', '1', 100, NULL, 'admin', NOW(), '鐘舵�佸彉鏇�-绔欏唴娑堟伅');
+
+-- 浠诲姟鍒涘缓閫氱煡 - 浠呭惎鐢ㄧ珯鍐呮秷鎭�
+INSERT INTO `sys_notify_channel_config` (`notify_type`, `channel`, `enabled`, `priority`, `config_json`, `create_by`, `create_time`, `remark`) VALUES
+('TASK_CREATE', 'SITE_MSG', '1', 100, NULL, 'admin', NOW(), '浠诲姟鍒涘缓-绔欏唴娑堟伅');
+
+-- ===========================================
+-- 淇敼鍙戦�佽褰曡〃锛屽鍔犲叧鑱旈�氱煡浠诲姟涓昏〃鐨勫瓧娈�
+-- ===========================================
+
+-- 濡傛灉 sys_notify_send_log 琛ㄥ凡瀛樺湪锛屾坊鍔� notify_task_id 瀛楁
+ALTER TABLE `sys_notify_send_log`
+ADD COLUMN `notify_task_id` bigint(20) DEFAULT NULL COMMENT '鍏宠仈鐨勯�氱煡浠诲姟ID' AFTER `id`,
+ADD INDEX `idx_notify_task_id` (`notify_task_id`);
+
+-- ===========================================
+-- 璇存槑锛�
+-- 1. sys_notify_task 鏄�氱煡浠诲姟涓昏〃锛岃褰曢渶瑕佸彂閫佺殑閫氱煡
+-- 2. sys_notify_channel_config 閰嶇疆姣忕閫氱煡绫诲瀷鍚敤鍝簺娓犻亾
+-- 3. sys_notify_send_log 璁板綍姣忎釜娓犻亾鐨勫彂閫佹槑缁�
+--
+-- 宸ヤ綔娴佺▼锛�
+-- 1) 涓氬姟绯荤粺鍒涘缓閫氱煡浠诲姟锛堟彃鍏� sys_notify_task锛�
+-- 2) 閫氱煡鍒嗗彂鏈嶅姟璇诲彇娓犻亾閰嶇疆锛坰ys_notify_channel_config锛�
+-- 3) 鏍规嵁閰嶇疆鍚戝悇娓犻亾鍙戦�侀�氱煡锛屽苟璁板綍鍙戦�佹棩蹇楋紙sys_notify_send_log锛�
+-- 4) 鏇存柊閫氱煡浠诲姟鐘舵��
+-- ===========================================
--
Gitblit v1.9.1