From fefb649f462ae6b19dd8f0f6bc6096619db9a82e Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期六, 25 十月 2025 18:38:54 +0800
Subject: [PATCH] feat:消息体推送

---
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMessageController.java |  138 ++
 ruoyi-system/src/main/java/com/ruoyi/system/event/TaskCreatedEvent.java             |   55 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageMapper.java            |   94 +
 app/pages/index.vue                                                                 |   23 
 ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java       |  224 +++
 ruoyi-system/src/main/java/com/ruoyi/system/event/TaskAssignedEvent.java            |   68 +
 sql/sys_message.sql                                                                 |   26 
 prd/系统消息推送-文件变更清单.md                                                                |  245 ++++
 prd/事件驱动消息推送-实现总结.md                                                                |  508 ++++++++
 app/pages/message/index.vue                                                         |   85 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageService.java         |  120 ++
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessage.java                  |  186 +++
 prd/系统消息推送-快速开始.md                                                                  |  189 +++
 prd/系统消息推送功能实现总结.md                                                                 |  305 +++++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java    |   96 +
 ruoyi-system/src/main/resources/mapper/system/SysMessageMapper.xml                  |  137 ++
 app/api/message.js                                                                  |   76 +
 ruoyi-system/src/main/java/com/ruoyi/system/event/TaskEvent.java                    |   72 +
 ruoyi-system/src/main/java/com/ruoyi/system/event/TaskStatusChangedEvent.java       |   93 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageServiceImpl.java |  351 +++++
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java           |   40 
 prd/事件驱动消息推送-快速开始.md                                                                |  366 ++++++
 22 files changed, 3,465 insertions(+), 32 deletions(-)

diff --git a/app/api/message.js b/app/api/message.js
new file mode 100644
index 0000000..f5ac437
--- /dev/null
+++ b/app/api/message.js
@@ -0,0 +1,76 @@
+import request from '@/utils/request'
+
+// 鏌ヨ褰撳墠鐢ㄦ埛鐨勬秷鎭垪琛�
+export function getMyMessages() {
+  return request({
+    url: '/system/message/my',
+    method: 'get'
+  })
+}
+
+// 鏌ヨ绯荤粺娑堟伅鍒楄〃
+export function listMessage(query) {
+  return request({
+    url: '/system/message/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ绯荤粺娑堟伅璇︾粏
+export function getMessage(messageId) {
+  return request({
+    url: '/system/message/' + messageId,
+    method: 'get'
+  })
+}
+
+// 鏌ヨ鏈娑堟伅鏁伴噺
+export function getUnreadCount() {
+  return request({
+    url: '/system/message/unread/count',
+    method: 'get'
+  })
+}
+
+// 鏂板绯荤粺娑堟伅
+export function addMessage(data) {
+  return request({
+    url: '/system/message',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼绯荤粺娑堟伅
+export function updateMessage(data) {
+  return request({
+    url: '/system/message',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎绯荤粺娑堟伅
+export function delMessage(messageId) {
+  return request({
+    url: '/system/message/' + messageId,
+    method: 'delete'
+  })
+}
+
+// 鏍囪娑堟伅涓哄凡璇�
+export function markAsRead(messageId) {
+  return request({
+    url: '/system/message/read/' + messageId,
+    method: 'put'
+  })
+}
+
+// 鏍囪鎵�鏈夋秷鎭负宸茶
+export function markAllAsRead() {
+  return request({
+    url: '/system/message/read/all',
+    method: 'put'
+  })
+}
diff --git a/app/pages/index.vue b/app/pages/index.vue
index 16b1513..14fc8f5 100644
--- a/app/pages/index.vue
+++ b/app/pages/index.vue
@@ -162,6 +162,7 @@
   import { getMyTasks, changeTaskStatus } from '@/api/task'
   import { getUserProfile } from '@/api/system/user'
   import { getUserBoundVehicle } from '@/api/vehicle'
+  import { getUnreadCount } from '@/api/message'
   
   export default {
     data() {
@@ -172,6 +173,7 @@
         
         // 娑堟伅鏁版嵁
         messages: [],
+        unreadMessageCount: 0,
         
         // 姝e湪杩愯鐨勪换鍔″垪琛�
         taskList: [],
@@ -190,11 +192,6 @@
           // 鍖呭惈寰呭鐞嗐�佸嚭鍙戜腑銆佸凡鍒拌揪銆佽繑绋嬩腑绛夋墍鏈夋湭瀹屾垚鐨勭姸鎬�
           return ['PENDING', 'DEPARTING', 'ARRIVED', 'RETURNING', 'IN_PROGRESS'].includes(task.taskStatus)
         });
-      },
-      
-      // 鏈娑堟伅鏁伴噺
-      unreadMessageCount() {
-        return this.messages.filter(message => !message.read).length;
       }
     },
     onLoad() {
@@ -202,11 +199,14 @@
       this.loadUserVehicle()
       // 鍔犺浇姝e湪杩愯鐨勪换鍔�
       this.loadRunningTasks()
+      // 鍔犺浇鏈娑堟伅鏁伴噺
+      this.loadUnreadMessageCount()
     },
     onShow() {
-      // 姣忔鏄剧ず椤甸潰鏃跺埛鏂颁换鍔″垪琛ㄥ拰缁戝畾杞﹁締
+      // 姣忔鏄剧ず椤甸潰鏃跺埛鏂颁换鍔″垪琛ㄣ�佺粦瀹氳溅杈嗗拰娑堟伅鏁伴噺
       this.loadUserVehicle()
       this.loadRunningTasks()
+      this.loadUnreadMessageCount()
     },
     onPullDownRefresh() {
       // 涓嬫媺鍒锋柊
@@ -243,6 +243,17 @@
         })
       },
       
+      // 鍔犺浇鏈娑堟伅鏁伴噺
+      loadUnreadMessageCount() {
+        getUnreadCount().then(response => {
+          if (response.code === 200) {
+            this.unreadMessageCount = response.data || 0
+          }
+        }).catch(error => {
+          console.error('鑾峰彇鏈娑堟伅鏁伴噺澶辫触:', error)
+        })
+      },
+      
       // 鍔犺浇鐢ㄦ埛淇℃伅锛堜繚鐣欎互鍏煎涔嬪墠鐨勪唬鐮侊級
       loadUserProfile() {
         const userId = this.currentUser.userId
diff --git a/app/pages/message/index.vue b/app/pages/message/index.vue
index 113b7f9..e3dd348 100644
--- a/app/pages/message/index.vue
+++ b/app/pages/message/index.vue
@@ -15,11 +15,11 @@
         >
           <view class="message-main">
             <view class="message-title">
-              <text class="title-text">{{ getMessageTypeText(message.type) }}</text>
-              <view class="unread-dot" v-if="!message.read"></view>
+              <text class="title-text">{{ getMessageTypeText(message.messageType) }}</text>
+              <view class="unread-dot" v-if="message.isRead === '0'"></view>
             </view>
-            <view class="message-content">{{ message.content }}</view>
-            <view class="message-time">{{ message.time }}</view>
+            <view class="message-content">{{ message.messageContent }}</view>
+            <view class="message-time">{{ message.createTime }}</view>
           </view>
         </view>
         
@@ -33,47 +33,92 @@
 </template>
 
 <script>
+  import { getMyMessages, markAsRead } from '@/api/message'
+  
   export default {
     data() {
       return {
         // 娑堟伅鍒楄〃
-        messages: []
+        messages: [],
+        loading: false
       }
     },
     computed: {
       // 鎸夋湭璇�/宸茶鎺掑簭锛屾湭璇荤殑鍦ㄥ墠闈�
       sortedMessages() {
         return [...this.messages].sort((a, b) => {
-          if (a.read === b.read) {
+          if (a.isRead === b.isRead) {
             // 鐩稿悓鐘舵�佹寜鏃堕棿鍊掑簭
-            return new Date(b.time) - new Date(a.time);
+            return new Date(b.createTime) - new Date(a.createTime);
           }
           // 鏈鐨勬帓鍦ㄥ墠闈�
-          return a.read ? 1 : -1;
+          return a.isRead === '0' ? -1 : 1;
         });
       }
     },
+    onLoad() {
+      this.loadMessages()
+    },
+    onShow() {
+      // 姣忔鏄剧ず椤甸潰鏃跺埛鏂版秷鎭�
+      this.loadMessages()
+    },
+    onPullDownRefresh() {
+      this.loadMessages().then(() => {
+        uni.stopPullDownRefresh()
+      })
+    },
     methods: {
+      // 鍔犺浇娑堟伅鍒楄〃
+      async loadMessages() {
+        try {
+          this.loading = true
+          const response = await getMyMessages()
+          if (response.code === 200) {
+            this.messages = response.data || []
+          } else {
+            this.$modal.showToast(response.msg || '鍔犺浇娑堟伅澶辫触')
+          }
+        } catch (error) {
+          console.error('鍔犺浇娑堟伅澶辫触锛�', error)
+          this.$modal.showToast('鍔犺浇娑堟伅澶辫触')
+        } finally {
+          this.loading = false
+        }
+      },
+      
       // 鑾峰彇娑堟伅绫诲瀷鏂囨湰
       getMessageTypeText(type) {
         const typeMap = {
-          'create': '鍒涘缓鎴愬姛',
-          'push': '浠诲姟鎺ㄩ��',
-          'status': '浠诲姟鐘舵��'
+          'CREATE': '鍒涘缓鎴愬姛',
+          'PUSH': '浠诲姟鎺ㄩ��',
+          'STATUS': '鐘舵�佸彉鏇�',
+          'ASSIGN': '浠诲姟鍒嗛厤'
         }
         return typeMap[type] || '绯荤粺娑堟伅';
       },
       
       // 鏌ョ湅娑堟伅璇︽儏锛堣烦杞埌浠诲姟璇︽儏锛�
-      viewMessageDetail(message) {
-        // 鏍囪涓哄凡璇�
-        message.read = true;
-        
-        // 璺宠浆鍒颁换鍔¤鎯呴〉闈�
-        if (message.taskId) {
-          this.$tab.navigateTo(`/pages/task/detail?id=${message.taskId}`);
-        } else {
-          this.$modal.showToast('鏃犳硶鎵惧埌鍏宠仈浠诲姟');
+      async viewMessageDetail(message) {
+        try {
+          // 鏍囪涓哄凡璇�
+          if (message.isRead === '0') {
+            await markAsRead(message.messageId)
+            message.isRead = '1'
+          }
+          
+          // 璺宠浆鍒颁换鍔¤鎯呴〉闈�
+          if (message.taskId) {
+            this.$tab.navigateTo(`/pages/task/detail?id=${message.taskId}`)
+          } else {
+            this.$modal.showToast('鏃犳硶鎵惧埌鍏宠仈浠诲姟')
+          }
+        } catch (error) {
+          console.error('鏍囪娑堟伅宸茶澶辫触锛�', error)
+          // 鍗充娇鏍囪澶辫触锛屼篃鍏佽璺宠浆
+          if (message.taskId) {
+            this.$tab.navigateTo(`/pages/task/detail?id=${message.taskId}`)
+          }
         }
       }
     }
diff --git "a/prd/\344\272\213\344\273\266\351\251\261\345\212\250\346\266\210\346\201\257\346\216\250\351\200\201-\345\256\236\347\216\260\346\200\273\347\273\223.md" "b/prd/\344\272\213\344\273\266\351\251\261\345\212\250\346\266\210\346\201\257\346\216\250\351\200\201-\345\256\236\347\216\260\346\200\273\347\273\223.md"
new file mode 100644
index 0000000..83df3b1
--- /dev/null
+++ "b/prd/\344\272\213\344\273\266\351\251\261\345\212\250\346\266\210\346\201\257\346\216\250\351\200\201-\345\256\236\347\216\260\346\200\273\347\273\223.md"
@@ -0,0 +1,508 @@
+# 浜嬩欢椹卞姩娑堟伅鎺ㄩ�佺郴缁� - 瀹炵幇鎬荤粨
+
+## 鍔熻兘姒傝堪
+
+閲囩敤Spring浜嬩欢椹卞姩鏋舵瀯閲嶆瀯娑堟伅鎺ㄩ�佸姛鑳�,瀹炵幇涓氬姟閫昏緫涓庢秷鎭帹閫佺殑瀹屽叏瑙h��,浣垮叾浠栫郴缁熷彲浠ヨ交鏉惧彂甯冧簨浠舵潵瑙﹀彂娑堟伅鎺ㄩ�併��
+
+## 鏋舵瀯璁捐
+
+### 璁捐妯″紡
+
+閲囩敤**瑙傚療鑰呮ā寮�**锛圤bserver Pattern锛夌殑Spring浜嬩欢鏈哄埗瀹炵幇锛�
+
+```
+涓氬姟绯荤粺 --鍙戝竷--> 浜嬩欢 --鐩戝惉--> 娑堟伅鐩戝惉鍣� --淇濆瓨--> 娑堟伅搴�
+```
+
+### 鏍稿績缁勪欢
+
+```mermaid
+graph LR
+    A[浠诲姟鏈嶅姟] -->|鍙戝竷浜嬩欢| B[ApplicationEventPublisher]
+    B --> C[TaskCreatedEvent]
+    B --> D[TaskAssignedEvent]
+    B --> E[TaskStatusChangedEvent]
+    C -->|鐩戝惉| F[TaskMessageListener]
+    D -->|鐩戝惉| F
+    E -->|鐩戝惉| F
+    F -->|淇濆瓨娑堟伅| G[sys_message琛╙
+```
+
+## 瀹炵幇鍐呭
+
+### 1. 浜嬩欢绫昏璁�
+
+#### 1.1 浜嬩欢鍩虹被
+
+**鏂囦欢**: `ruoyi-system/src/main/java/com/ruoyi/system/event/TaskEvent.java`
+
+```java
+public abstract class TaskEvent extends ApplicationEvent {
+    private Long taskId;          // 浠诲姟ID
+    private String taskCode;      // 浠诲姟缂栧彿
+    private Long operatorId;      // 鎿嶄綔浜篒D
+    private String operatorName;  // 鎿嶄綔浜哄鍚�
+}
+```
+
+#### 1.2 浠诲姟鍒涘缓浜嬩欢
+
+**鏂囦欢**: `ruoyi-system/src/main/java/com/ruoyi/system/event/TaskCreatedEvent.java`
+
+```java
+public class TaskCreatedEvent extends TaskEvent {
+    private String taskType;      // 浠诲姟绫诲瀷
+    private Long creatorId;       // 鍒涘缓浜篒D
+    private String creatorName;   // 鍒涘缓浜哄鍚�
+}
+```
+
+#### 1.3 浠诲姟鍒嗛厤浜嬩欢
+
+**鏂囦欢**: `ruoyi-system/src/main/java/com/ruoyi/system/event/TaskAssignedEvent.java`
+
+```java
+public class TaskAssignedEvent extends TaskEvent {
+    private List<Long> assigneeIds;     // 鎵ц浜篒D鍒楄〃
+    private List<String> assigneeNames; // 鎵ц浜哄鍚嶅垪琛�
+    private Long assignerId;            // 鍒嗛厤浜篒D
+    private String assignerName;        // 鍒嗛厤浜哄鍚�
+}
+```
+
+#### 1.4 浠诲姟鐘舵�佸彉鏇翠簨浠�
+
+**鏂囦欢**: `ruoyi-system/src/main/java/com/ruoyi/system/event/TaskStatusChangedEvent.java`
+
+```java
+public class TaskStatusChangedEvent extends TaskEvent {
+    private String oldStatus;         // 鏃х姸鎬�
+    private String newStatus;         // 鏂扮姸鎬�
+    private String oldStatusDesc;     // 鏃х姸鎬佹弿杩�
+    private String newStatusDesc;     // 鏂扮姸鎬佹弿杩�
+    private List<Long> assigneeIds;   // 鎵ц浜篒D鍒楄〃
+    private Long creatorId;           // 鍒涘缓浜篒D
+}
+```
+
+### 2. 娑堟伅鐩戝惉鍣�
+
+**鏂囦欢**: `ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java`
+
+#### 2.1 鏍稿績鐗规��
+
+- 鉁� **寮傛澶勭悊**: 浣跨敤 `@Async` 娉ㄨВ,涓嶉樆濉炰富涓氬姟
+- 鉁� **浜嬩欢鐩戝惉**: 浣跨敤 `@EventListener` 娉ㄨВ鐩戝惉浜嬩欢
+- 鉁� **鑷姩淇濆瓨**: 鐩戝惉鍒颁簨浠跺悗鑷姩淇濆瓨娑堟伅鍒版暟鎹簱
+- 鉁� **瀹归敊澶勭悊**: 寮傚父涓嶅奖鍝嶄富涓氬姟娴佺▼
+
+#### 2.2 鐩戝惉鍣ㄦ柟娉�
+
+```java
+@Component
+public class TaskMessageListener {
+    
+    // 鐩戝惉浠诲姟鍒涘缓浜嬩欢
+    @Async
+    @EventListener
+    public void handleTaskCreatedEvent(TaskCreatedEvent event) {
+        // 淇濆瓨鍒涘缓鎴愬姛娑堟伅
+    }
+    
+    // 鐩戝惉浠诲姟鍒嗛厤浜嬩欢
+    @Async
+    @EventListener
+    public void handleTaskAssignedEvent(TaskAssignedEvent event) {
+        // 缁欐瘡涓墽琛屼汉鍙戦�佷换鍔℃帹閫佹秷鎭�
+    }
+    
+    // 鐩戝惉浠诲姟鐘舵�佸彉鏇翠簨浠�
+    @Async
+    @EventListener
+    public void handleTaskStatusChangedEvent(TaskStatusChangedEvent event) {
+        // 缁欐墽琛屼汉鍜屽垱寤轰汉鍙戦�佺姸鎬佸彉鏇存秷鎭�
+    }
+}
+```
+
+### 3. 寮傛閰嶇疆
+
+**鏂囦欢**: `ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java`
+
+```java
+@Configuration
+@EnableAsync
+public class AsyncConfig {
+    
+    @Bean(name = "taskExecutor")
+    public Executor taskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(5);         // 鏍稿績绾跨▼鏁�
+        executor.setMaxPoolSize(10);         // 鏈�澶х嚎绋嬫暟
+        executor.setQueueCapacity(100);      // 闃熷垪瀹归噺
+        executor.setThreadNamePrefix("async-task-");
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        executor.initialize();
+        return executor;
+    }
+}
+```
+
+### 4. 浠诲姟鏈嶅姟闆嗘垚
+
+**鏂囦欢**: `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java`
+
+#### 4.1 娉ㄥ叆浜嬩欢鍙戝竷鍣�
+
+```java
+@Autowired
+private ApplicationEventPublisher eventPublisher;
+```
+
+#### 4.2 鍙戝竷浜嬩欢
+
+**鍒涘缓浠诲姟鏃�**:
+```java
+// 鍙戝竷浠诲姟鍒涘缓浜嬩欢
+eventPublisher.publishEvent(new TaskCreatedEvent(
+    this, taskId, taskCode, taskType, creatorId, creatorName
+));
+
+// 鍙戝竷浠诲姟鍒嗛厤浜嬩欢
+eventPublisher.publishEvent(new TaskAssignedEvent(
+    this, taskId, taskCode, assigneeIds, assigneeNames, assignerId, assignerName
+));
+```
+
+**鍒嗛厤浠诲姟鏃�**:
+```java
+eventPublisher.publishEvent(new TaskAssignedEvent(
+    this, taskId, taskCode, assigneeIds, null, assignerId, assignerName
+));
+```
+
+**鐘舵�佸彉鏇存椂**:
+```java
+eventPublisher.publishEvent(new TaskStatusChangedEvent(
+    this, taskId, taskCode, oldStatus, newStatus, 
+    oldStatusDesc, newStatusDesc, assigneeIds, creatorId
+));
+```
+
+## 鏋舵瀯浼樺娍
+
+### 1. 瀹屽叏瑙h��
+
+| 瀵规瘮椤� | 鐩存帴璋冪敤 | 浜嬩欢椹卞姩 |
+|--------|---------|---------|
+| 鑰﹀悎搴� | 寮鸿�﹀悎 | 瀹屽叏瑙h�� |
+| 渚濊禆鍏崇郴 | 闇�瑕佹敞鍏ervice | 鍙渶鍙戝竷浜嬩欢 |
+| 淇敼褰卞搷 | 褰卞搷涓氬姟浠g爜 | 涓嶅奖鍝嶄笟鍔′唬鐮� |
+| 鎵╁睍鎬� | 闇�淇敼涓氬姟浠g爜 | 鍙渶娣诲姞鐩戝惉鍣� |
+
+### 2. 寮傛澶勭悊
+
+```
+鍚屾鏂瑰紡锛�
+涓氬姟澶勭悊 鈫� 淇濆瓨娑堟伅 鈫� 杩斿洖缁撴灉
+鎬昏�楁椂 = 涓氬姟鑰楁椂 + 娑堟伅鑰楁椂
+
+寮傛鏂瑰紡锛�
+涓氬姟澶勭悊 鈫� 杩斿洖缁撴灉
+    鈫�
+鍙戝竷浜嬩欢 鈫� 寮傛淇濆瓨娑堟伅锛堜笉褰卞搷涓绘祦绋嬶級
+鎬昏�楁椂 鈮� 涓氬姟鑰楁椂
+```
+
+### 3. 楂樻墿灞曟��
+
+鍏朵粬绯荤粺闇�瑕佽Е鍙戞秷鎭帹閫佹椂锛屽彧闇�锛�
+
+```java
+// 1. 鍙戝竷浜嬩欢
+eventPublisher.publishEvent(new TaskCreatedEvent(...));
+
+// 2. 鏃犻渶鍏冲績娑堟伅濡備綍淇濆瓨
+// 3. 鏃犻渶淇敼浠讳綍鐜版湁浠g爜
+```
+
+### 4. 鏄撶淮鎶ゆ��
+
+- **鍗曚竴鑱岃矗**: 涓氬姟鏈嶅姟鍙礋璐d笟鍔¢�昏緫锛岀洃鍚櫒鍙礋璐f秷鎭帹閫�
+- **鐙珛娴嬭瘯**: 鍙互鐙珛娴嬭瘯浜嬩欢鍙戝竷鍜岀洃鍚�
+- **鏃ュ織娓呮櫚**: 寮傛绾跨▼鏈夌嫭绔嬬殑绾跨▼鍚嶇О鍓嶇紑
+
+## 浣跨敤鎸囧崡
+
+### 鍏朵粬绯荤粺濡備綍浣跨敤
+
+#### 鍦烘櫙1: 璁㈠崟绯荤粺鎺ㄩ�佹秷鎭�
+
+```java
+@Service
+public class OrderServiceImpl {
+    
+    @Autowired
+    private ApplicationEventPublisher eventPublisher;
+    
+    public void createOrder(Order order) {
+        // 1. 涓氬姟閫昏緫
+        orderMapper.insert(order);
+        
+        // 2. 鍙戝竷浜嬩欢锛堟帹閫佹秷鎭級
+        eventPublisher.publishEvent(new OrderCreatedEvent(
+            this, order.getOrderId(), order.getOrderNo(), order.getCreatorId()
+        ));
+    }
+}
+```
+
+#### 鍦烘櫙2: 瀹℃壒绯荤粺鎺ㄩ�佹秷鎭�
+
+```java
+@Service
+public class ApprovalServiceImpl {
+    
+    @Autowired
+    private ApplicationEventPublisher eventPublisher;
+    
+    public void approveTask(Long taskId, String result) {
+        // 1. 涓氬姟閫昏緫
+        approvalMapper.updateStatus(taskId, result);
+        
+        // 2. 鍙戝竷浜嬩欢锛堟帹閫佹秷鎭級
+        eventPublisher.publishEvent(new ApprovalCompletedEvent(
+            this, taskId, result, approverId, applicantId
+        ));
+    }
+}
+```
+
+### 娣诲姞鏂扮殑浜嬩欢绫诲瀷
+
+#### 姝ラ1: 鍒涘缓浜嬩欢绫�
+
+```java
+package com.ruoyi.system.event;
+
+public class OrderCreatedEvent extends ApplicationEvent {
+    private Long orderId;
+    private String orderNo;
+    private Long creatorId;
+    
+    public OrderCreatedEvent(Object source, Long orderId, String orderNo, Long creatorId) {
+        super(source);
+        this.orderId = orderId;
+        this.orderNo = orderNo;
+        this.creatorId = creatorId;
+    }
+    
+    // getters and setters
+}
+```
+
+#### 姝ラ2: 娣诲姞鐩戝惉鍣ㄦ柟娉�
+
+```java
+@Component
+public class OrderMessageListener {
+    
+    @Autowired
+    private SysMessageMapper sysMessageMapper;
+    
+    @Async
+    @EventListener
+    public void handleOrderCreatedEvent(OrderCreatedEvent event) {
+        // 淇濆瓨娑堟伅
+        SysMessage message = new SysMessage();
+        message.setMessageType("ORDER_CREATE");
+        message.setMessageTitle("璁㈠崟鍒涘缓鎴愬姛");
+        message.setMessageContent("鎮ㄧ殑璁㈠崟宸插垱寤烘垚鍔�");
+        // ... 璁剧疆鍏朵粬瀛楁
+        
+        sysMessageMapper.insertSysMessage(message);
+    }
+}
+```
+
+#### 姝ラ3: 鍙戝竷浜嬩欢
+
+```java
+eventPublisher.publishEvent(new OrderCreatedEvent(this, orderId, orderNo, creatorId));
+```
+
+## 鎬ц兘浼樺寲
+
+### 1. 绾跨▼姹犻厤缃紭鍖�
+
+鏍规嵁瀹為檯璐熻浇璋冩暣绾跨▼姹犲弬鏁帮細
+
+```java
+// 楂樺苟鍙戝満鏅�
+executor.setCorePoolSize(10);
+executor.setMaxPoolSize(20);
+executor.setQueueCapacity(200);
+
+// 浣庡苟鍙戝満鏅�
+executor.setCorePoolSize(3);
+executor.setMaxPoolSize(5);
+executor.setQueueCapacity(50);
+```
+
+### 2. 鎵归噺淇濆瓨浼樺寲
+
+濡傛灉鍚屾椂鏈夊ぇ閲忔秷鎭紝鍙互鎵归噺淇濆瓨锛�
+
+```java
+@Async
+@EventListener
+public void handleTaskAssignedEvent(TaskAssignedEvent event) {
+    List<SysMessage> messages = new ArrayList<>();
+    
+    for (Long assigneeId : event.getAssigneeIds()) {
+        SysMessage message = new SysMessage();
+        // ... 璁剧疆瀛楁
+        messages.add(message);
+    }
+    
+    // 鎵归噺鎻掑叆
+    sysMessageMapper.batchInsert(messages);
+}
+```
+
+### 3. 娑堟伅鍘婚噸
+
+閬垮厤閲嶅鍙戦�佹秷鎭細
+
+```java
+@Async
+@EventListener
+public void handleTaskStatusChangedEvent(TaskStatusChangedEvent event) {
+    // 浣跨敤Set鍘婚噸
+    Set<Long> receiverIds = new HashSet<>();
+    receiverIds.addAll(event.getAssigneeIds());
+    receiverIds.add(event.getCreatorId());
+    
+    for (Long receiverId : receiverIds) {
+        // 淇濆瓨娑堟伅
+    }
+}
+```
+
+## 鐩戞帶涓庤皟璇�
+
+### 1. 鏌ョ湅浜嬩欢鏃ュ織
+
+```
+2025-10-25 14:30:15.123 [async-task-1] INFO  TaskMessageListener - 鏀跺埌浠诲姟鍒涘缓浜嬩欢锛屼换鍔D锛�1001锛屼换鍔$紪鍙凤細TASK-20251025-001
+2025-10-25 14:30:15.234 [async-task-1] INFO  TaskMessageListener - 浠诲姟鍒涘缓娑堟伅宸蹭繚瀛橈紝娑堟伅ID锛�5001
+2025-10-25 14:30:15.345 [async-task-2] INFO  TaskMessageListener - 鏀跺埌浠诲姟鍒嗛厤浜嬩欢锛屼换鍔D锛�1001锛屾墽琛屼汉鏁伴噺锛�3
+2025-10-25 14:30:15.456 [async-task-2] INFO  TaskMessageListener - 浠诲姟鍒嗛厤娑堟伅宸蹭繚瀛橈紝娑堟伅ID锛�5002锛屾帴鏀朵汉锛氬紶涓�
+```
+
+### 2. 鐩戞帶绾跨▼姹犵姸鎬�
+
+```java
+@Component
+public class ThreadPoolMonitor {
+    
+    @Autowired
+    @Qualifier("taskExecutor")
+    private ThreadPoolTaskExecutor executor;
+    
+    @Scheduled(fixedDelay = 60000) // 姣忓垎閽�
+    public void monitor() {
+        log.info("绾跨▼姹犵姸鎬� - 娲昏穬绾跨▼锛歿}锛岄槦鍒楀ぇ灏忥細{}锛屽畬鎴愪换鍔★細{}", 
+                executor.getActiveCount(),
+                executor.getThreadPoolExecutor().getQueue().size(),
+                executor.getThreadPoolExecutor().getCompletedTaskCount());
+    }
+}
+```
+
+## 娉ㄦ剰浜嬮」
+
+### 1. 浜嬪姟杈圭晫
+
+浜嬩欢鍙戝竷搴旇鍦ㄤ簨鍔℃彁浜や箣鍚庯細
+
+```java
+@Transactional
+public int insertSysTask(TaskCreateVO createVO) {
+    // 1. 淇濆瓨浠诲姟
+    int result = sysTaskMapper.insertSysTask(task);
+    
+    // 2. 鍦ㄤ簨鍔″唴鍙戝竷浜嬩欢锛堜簨鍔℃彁浜ゅ悗鎵嶄細瑙﹀彂鐩戝惉鍣級
+    if (result > 0) {
+        eventPublisher.publishEvent(new TaskCreatedEvent(...));
+    }
+    
+    return result;
+}
+```
+
+### 2. 寮傚父澶勭悊
+
+鐩戝惉鍣ㄤ腑鐨勫紓甯镐笉浼氬奖鍝嶄富涓氬姟锛�
+
+```java
+@Async
+@EventListener
+public void handleTaskCreatedEvent(TaskCreatedEvent event) {
+    try {
+        // 澶勭悊浜嬩欢
+    } catch (Exception e) {
+        log.error("澶勭悊浠诲姟鍒涘缓浜嬩欢澶辫触", e);
+        // 涓嶅悜涓婃姏鍑哄紓甯�
+    }
+}
+```
+
+### 3. 椤哄簭鎬�
+
+寮傛浜嬩欢涓嶄繚璇佹墽琛岄『搴忥細
+
+```java
+// 杩欎袱涓簨浠跺彲鑳戒互浠绘剰椤哄簭鎵ц
+eventPublisher.publishEvent(event1);
+eventPublisher.publishEvent(event2);
+```
+
+濡傞渶淇濊瘉椤哄簭锛屼娇鐢ㄥ悓姝ョ洃鍚櫒锛�
+
+```java
+@EventListener  // 涓嶄娇鐢ˊAsync
+public void handleEvent(Event event) {
+    // 鍚屾鎵ц锛屼繚璇侀『搴�
+}
+```
+
+## 瀵规瘮鎬荤粨
+
+| 鐗规�� | 鐩存帴璋冪敤Service | 浜嬩欢椹卞姩 |
+|------|---------------|---------|
+| 浠g爜鑰﹀悎搴� | 楂� | 浣� |
+| 鎬ц兘褰卞搷 | 鍚屾闃诲 | 寮傛闈為樆濉� |
+| 鎵╁睍鎬� | 闇�淇敼浠g爜 | 鍙渶娣诲姞鐩戝惉鍣� |
+| 鍙祴璇曟�� | 闇�妯℃嫙Service | 鍙渶鍙戝竷浜嬩欢 |
+| 鍙淮鎶ゆ�� | 涓氬姟浠g爜娣锋潅 | 鑱岃矗娓呮櫚鍒嗙 |
+| 瀛︿範鎴愭湰 | 浣� | 涓� |
+| 閫傜敤鍦烘櫙 | 绠�鍗曢」鐩� | 澶嶆潅/澶у瀷椤圭洰 |
+
+## 鎬荤粨
+
+閫氳繃寮曞叆Spring浜嬩欢椹卞姩鏋舵瀯锛屾垜浠垚鍔熷疄鐜颁簡锛�
+
+1. 鉁� **涓氬姟涓庢秷鎭畬鍏ㄨВ鑰�** - 涓氬姟浠g爜鍙渶鍙戝竷浜嬩欢
+2. 鉁� **寮傛闈為樆濉炲鐞�** - 涓嶅奖鍝嶄富涓氬姟鎬ц兘
+3. 鉁� **楂樺害鍙墿灞�** - 鍏朵粬绯荤粺杞绘澗闆嗘垚
+4. 鉁� **鑱岃矗娓呮櫚** - 鐩戝惉鍣ㄤ笓娉ㄦ秷鎭帹閫�
+5. 鉁� **鏄撲簬缁存姢** - 鐙珛鐨勪簨浠跺拰鐩戝惉鍣ㄧ鐞�
+
+杩欑鏋舵瀯鐗瑰埆閫傚悎澶у瀷椤圭洰鍜岄渶瑕侀珮鎵╁睍鎬х殑绯荤粺锛�
+
+---
+
+**鏇存柊鏃堕棿**: 2025-10-25  
+**鐗堟湰**: v2.0  
+**鏋舵瀯**: 浜嬩欢椹卞姩
diff --git "a/prd/\344\272\213\344\273\266\351\251\261\345\212\250\346\266\210\346\201\257\346\216\250\351\200\201-\345\277\253\351\200\237\345\274\200\345\247\213.md" "b/prd/\344\272\213\344\273\266\351\251\261\345\212\250\346\266\210\346\201\257\346\216\250\351\200\201-\345\277\253\351\200\237\345\274\200\345\247\213.md"
new file mode 100644
index 0000000..561e22f
--- /dev/null
+++ "b/prd/\344\272\213\344\273\266\351\251\261\345\212\250\346\266\210\346\201\257\346\216\250\351\200\201-\345\277\253\351\200\237\345\274\200\345\247\213.md"
@@ -0,0 +1,366 @@
+# 浜嬩欢椹卞姩娑堟伅鎺ㄩ�� - 蹇�熷紑濮�
+
+## 鏍稿績姒傚康
+
+浣跨敤Spring浜嬩欢鏈哄埗瀹炵幇娑堟伅鎺ㄩ�侊紝涓氬姟绯荤粺鍙渶鍙戝竷浜嬩欢锛屾秷鎭洃鍚櫒鑷姩淇濆瓨娑堟伅鍒版暟鎹簱銆�
+
+## 蹇�熼儴缃�
+
+### 1. 鏃犻渶棰濆閮ㄧ讲
+
+浜嬩欢椹卞姩鏋舵瀯宸茬粡闆嗘垚鍒扮幇鏈夌郴缁熶腑锛岄噸鍚悗绔湇鍔″嵆鍙敓鏁堬細
+
+```bash
+# Windows
+bin\run.bat
+
+# Linux
+sh bin/run.sh
+```
+
+### 2. 楠岃瘉閮ㄧ讲
+
+鏌ョ湅鍚姩鏃ュ織锛岀‘璁や互涓嬪唴瀹癸細
+
+```
+... AsyncConfig           : Bean 'taskExecutor' created
+... TaskMessageListener   : Bean created
+```
+
+## 浣跨敤鏂瑰紡
+
+### 鏂瑰紡1: 鍦ㄤ换鍔$郴缁熶腑锛堝凡闆嗘垚锛�
+
+**浠诲姟鍒涘缓銆佸垎閰嶃�佺姸鎬佸彉鏇存椂鑷姩鍙戝竷浜嬩欢锛屾棤闇�棰濆浠g爜**
+
+### 鏂瑰紡2: 鍦ㄥ叾浠栫郴缁熶腑浣跨敤
+
+#### 姝ラ1: 娉ㄥ叆浜嬩欢鍙戝竷鍣�
+
+```java
+@Service
+public class YourService {
+    
+    @Autowired
+    private ApplicationEventPublisher eventPublisher;
+    
+    // ...
+}
+```
+
+#### 姝ラ2: 鍙戝竷浜嬩欢
+
+**绀轰緥1: 浠诲姟鍒涘缓鏃舵帹閫佹秷鎭�**
+
+```java
+public void createTask(Task task) {
+    // 1. 涓氬姟閫昏緫
+    taskMapper.insert(task);
+    
+    // 2. 鍙戝竷浜嬩欢锛堣Е鍙戞秷鎭帹閫侊級
+    eventPublisher.publishEvent(new TaskCreatedEvent(
+        this,                    // source
+        task.getTaskId(),        // 浠诲姟ID
+        task.getTaskCode(),      // 浠诲姟缂栧彿
+        task.getTaskType(),      // 浠诲姟绫诲瀷
+        task.getCreatorId(),     // 鍒涘缓浜篒D
+        "寮犱笁"                    // 鍒涘缓浜哄鍚�
+    ));
+}
+```
+
+**绀轰緥2: 浠诲姟鍒嗛厤鏃舵帹閫佹秷鎭�**
+
+```java
+public void assignTask(Long taskId, List<Long> assigneeIds) {
+    // 1. 涓氬姟閫昏緫
+    taskMapper.updateAssignees(taskId, assigneeIds);
+    
+    // 2. 鍙戝竷浜嬩欢锛堣Е鍙戞秷鎭帹閫侊級
+    eventPublisher.publishEvent(new TaskAssignedEvent(
+        this,
+        taskId,
+        "TASK-001",
+        assigneeIds,            // 鎵ц浜篒D鍒楄〃
+        null,                   // 濮撳悕鍒楄〃锛堝彲閫夛紝鐩戝惉鍣ㄤ細鏌ヨ锛�
+        currentUserId,          // 鍒嗛厤浜篒D
+        "鏉庡洓"                  // 鍒嗛厤浜哄鍚�
+    ));
+}
+```
+
+**绀轰緥3: 鐘舵�佸彉鏇存椂鎺ㄩ�佹秷鎭�**
+
+```java
+public void changeStatus(Long taskId, String newStatus) {
+    Task task = taskMapper.selectById(taskId);
+    String oldStatus = task.getStatus();
+    
+    // 1. 涓氬姟閫昏緫
+    taskMapper.updateStatus(taskId, newStatus);
+    
+    // 2. 鍙戝竷浜嬩欢锛堣Е鍙戞秷鎭帹閫侊級
+    eventPublisher.publishEvent(new TaskStatusChangedEvent(
+        this,
+        taskId,
+        task.getTaskCode(),
+        oldStatus,              // 鏃х姸鎬�
+        newStatus,              // 鏂扮姸鎬�
+        "寰呭鐞�",               // 鏃х姸鎬佹弿杩�
+        "宸插畬鎴�",               // 鏂扮姸鎬佹弿杩�
+        task.getAssigneeIds(),  // 鎵ц浜篒D鍒楄〃
+        task.getCreatorId()     // 鍒涘缓浜篒D
+    ));
+}
+```
+
+## 浜嬩欢绫诲瀷
+
+| 浜嬩欢绫� | 鐢ㄩ�� | 娑堟伅绫诲瀷 |
+|--------|------|---------|
+| TaskCreatedEvent | 浠诲姟鍒涘缓 | CREATE |
+| TaskAssignedEvent | 浠诲姟鍒嗛厤 | PUSH/ASSIGN |
+| TaskStatusChangedEvent | 鐘舵�佸彉鏇� | STATUS |
+
+## 鎵╁睍鏂颁簨浠�
+
+### 鍦烘櫙: 璁㈠崟绯荤粺闇�瑕佹帹閫佹秷鎭�
+
+#### 1. 鍒涘缓璁㈠崟浜嬩欢绫�
+
+```java
+package com.ruoyi.system.event;
+
+import org.springframework.context.ApplicationEvent;
+
+public class OrderCreatedEvent extends ApplicationEvent {
+    private Long orderId;
+    private String orderNo;
+    private Long customerId;
+    
+    public OrderCreatedEvent(Object source, Long orderId, String orderNo, Long customerId) {
+        super(source);
+        this.orderId = orderId;
+        this.orderNo = orderNo;
+        this.customerId = customerId;
+    }
+    
+    // getters...
+}
+```
+
+#### 2. 鍒涘缓鐩戝惉鍣紙鎴栧湪鐜版湁鐩戝惉鍣ㄤ腑娣诲姞锛�
+
+```java
+@Component
+public class OrderMessageListener {
+    
+    @Autowired
+    private SysMessageMapper sysMessageMapper;
+    
+    @Async
+    @EventListener
+    public void handleOrderCreatedEvent(OrderCreatedEvent event) {
+        SysMessage message = new SysMessage();
+        message.setMessageType("ORDER_CREATE");
+        message.setMessageTitle("璁㈠崟鍒涘缓鎴愬姛");
+        message.setMessageContent("鎮ㄧ殑璁㈠崟" + event.getOrderNo() + "宸插垱寤�");
+        message.setReceiverId(event.getCustomerId());
+        message.setIsRead("0");
+        message.setCreateTime(DateUtils.getNowDate());
+        message.setDelFlag("0");
+        
+        sysMessageMapper.insertSysMessage(message);
+    }
+}
+```
+
+#### 3. 鍙戝竷浜嬩欢
+
+```java
+@Service
+public class OrderServiceImpl {
+    
+    @Autowired
+    private ApplicationEventPublisher eventPublisher;
+    
+    public void createOrder(Order order) {
+        orderMapper.insert(order);
+        
+        // 鍙戝竷浜嬩欢
+        eventPublisher.publishEvent(new OrderCreatedEvent(
+            this, order.getId(), order.getOrderNo(), order.getCustomerId()
+        ));
+    }
+}
+```
+
+## 鏍稿績浼樺娍
+
+### 1. 瀹屽叏瑙h��
+
+```java
+// 鉂� 鏃ф柟寮忥細闇�瑕佹敞鍏essageService
+@Autowired
+private IMessageService messageService;
+
+public void createTask() {
+    // ...
+    messageService.pushMessage(...);  // 寮轰緷璧�
+}
+
+// 鉁� 鏂版柟寮忥細鍙渶鍙戝竷浜嬩欢
+@Autowired
+private ApplicationEventPublisher eventPublisher;
+
+public void createTask() {
+    // ...
+    eventPublisher.publishEvent(event);  // 闆朵緷璧�
+}
+```
+
+### 2. 寮傛澶勭悊
+
+```
+涓氬姟澶勭悊 200ms 鈫� 杩斿洖缁撴灉
+    鈫擄紙涓嶉樆濉烇級
+鍙戝竷浜嬩欢 鈫� 寮傛淇濆瓨娑堟伅 50ms
+
+鎬昏�楁椂锛�200ms锛堣�岄潪250ms锛�
+```
+
+### 3. 杞绘澗鎵╁睍
+
+娣诲姞鏂扮殑娑堟伅鎺ㄩ�佸満鏅紝鍙渶锛�
+1. 鍙戝竷浜嬩欢 鉁�
+2. 鏃犻渶淇敼涓氬姟浠g爜 鉁�
+3. 鏃犻渶閲嶆柊閮ㄧ讲 鉁�
+
+## 鐩戞帶鍜岃皟璇�
+
+### 鏌ョ湅浜嬩欢鏃ュ織
+
+```bash
+# 鎼滅储浜嬩欢鍙戝竷鏃ュ織
+grep "publishEvent" logs/ruoyi-admin.log
+
+# 鎼滅储浜嬩欢鐩戝惉鏃ュ織
+grep "TaskMessageListener" logs/ruoyi-admin.log
+```
+
+### 鏃ュ織绀轰緥
+
+```
+2025-10-25 14:30:15 [main] INFO  鍙戝竷浠诲姟鍒涘缓浜嬩欢锛屼换鍔D锛�1001
+2025-10-25 14:30:15 [async-task-1] INFO  鏀跺埌浠诲姟鍒涘缓浜嬩欢锛屼换鍔D锛�1001
+2025-10-25 14:30:15 [async-task-1] INFO  浠诲姟鍒涘缓娑堟伅宸蹭繚瀛橈紝娑堟伅ID锛�5001
+```
+
+## 甯歌闂
+
+### Q1: 浜嬩欢鍙戝竷鍚庢秷鎭病鏈変繚瀛橈紵
+
+**鍘熷洜**: 鍙兘鏄紓姝ョ嚎绋嬫睜婊′簡
+
+**瑙e喅**: 
+1. 鏌ョ湅鏃ュ織鏄惁鏈夊紓甯�
+2. 璋冩暣绾跨▼姹犻厤缃紙AsyncConfig.java锛�
+3. 妫�鏌ユ暟鎹簱杩炴帴
+
+### Q2: 濡備綍纭繚娑堟伅涓�瀹氬彂閫侊紵
+
+**鏂规1**: 浣跨敤鍚屾鐩戝惉鍣紙鍘绘帀@Async锛�
+
+```java
+@EventListener  // 涓嶄娇鐢ˊAsync
+public void handleEvent(Event event) {
+    // 鍚屾鎵ц锛岀‘淇濇秷鎭繚瀛�
+}
+```
+
+**鏂规2**: 娣诲姞閲嶈瘯鏈哄埗
+
+```java
+@Async
+@EventListener
+@Retryable(maxAttempts = 3)
+public void handleEvent(Event event) {
+    // 澶辫触鑷姩閲嶈瘯3娆�
+}
+```
+
+### Q3: 濡備綍绂佺敤寮傛澶勭悊锛�
+
+淇敼鐩戝惉鍣紝鍘绘帀 `@Async` 娉ㄨВ锛�
+
+```java
+// @Async  // 娉ㄩ噴鎺�
+@EventListener
+public void handleEvent(Event event) {
+    // 鐜板湪鏄悓姝ユ墽琛�
+}
+```
+
+## 鎬ц兘浼樺寲
+
+### 鎵归噺澶勭悊娑堟伅
+
+```java
+// 鏀堕泦娑堟伅锛屾壒閲忎繚瀛�
+List<SysMessage> messages = new ArrayList<>();
+for (Long userId : userIds) {
+    SysMessage msg = new SysMessage();
+    // ...
+    messages.add(msg);
+}
+sysMessageMapper.batchInsert(messages);  // 鎵归噺鎻掑叆
+```
+
+### 璋冩暣绾跨▼姹�
+
+鏍规嵁瀹為檯璐熻浇璋冩暣 `AsyncConfig.java`:
+
+```java
+// 楂樺苟鍙戝満鏅�
+executor.setCorePoolSize(10);
+executor.setMaxPoolSize(20);
+
+// 浣庡苟鍙戝満鏅�
+executor.setCorePoolSize(3);
+executor.setMaxPoolSize(5);
+```
+
+## 瀵规瘮鏂瑰紡
+
+| 鐗规�� | 鐩存帴璋冪敤 | 浜嬩欢椹卞姩 |
+|------|---------|---------|
+| 浠g爜鑰﹀悎 | 寮轰緷璧朚essageService | 闆朵緷璧� |
+| 鎬ц兘 | 鍚屾闃诲 | 寮傛闈為樆濉� |
+| 鎵╁睍鎬� | 闇�淇敼浠g爜 | 鍙渶娣诲姞鐩戝惉鍣� |
+| 娴嬭瘯 | 闇�妯℃嫙Service | 鍙渶鍙戝竷浜嬩欢 |
+
+## 鏂囦欢娓呭崟
+
+### 鏂板鏂囦欢
+- `TaskEvent.java` - 浜嬩欢鍩虹被
+- `TaskCreatedEvent.java` - 鍒涘缓浜嬩欢
+- `TaskAssignedEvent.java` - 鍒嗛厤浜嬩欢
+- `TaskStatusChangedEvent.java` - 鐘舵�佷簨浠�
+- `TaskMessageListener.java` - 娑堟伅鐩戝惉鍣�
+- `AsyncConfig.java` - 寮傛閰嶇疆
+
+### 淇敼鏂囦欢
+- `SysTaskServiceImpl.java` - 鏀逛负鍙戝竷浜嬩欢
+
+## 涓嬩竴姝�
+
+1. 馃摉 闃呰璇︾粏鏂囨。锛歚prd/浜嬩欢椹卞姩娑堟伅鎺ㄩ��-瀹炵幇鎬荤粨.md`
+2. 馃敡 鏍规嵁闇�瑕佽皟鏁寸嚎绋嬫睜閰嶇疆
+3. 馃搳 鐩戞帶绯荤粺杩愯鏃ュ織
+4. 馃殌 鍦ㄥ叾浠栫郴缁熶腑浣跨敤浜嬩欢鏈哄埗
+
+---
+
+**鏇存柊鏃堕棿**: 2025-10-25  
+**鐗堟湰**: v2.0  
+**鎺ㄨ崘浣跨敤**: 閫傚悎鎵�鏈夐渶瑕佹秷鎭帹閫佺殑鍦烘櫙
diff --git "a/prd/\347\263\273\347\273\237\346\266\210\346\201\257\346\216\250\351\200\201-\345\277\253\351\200\237\345\274\200\345\247\213.md" "b/prd/\347\263\273\347\273\237\346\266\210\346\201\257\346\216\250\351\200\201-\345\277\253\351\200\237\345\274\200\345\247\213.md"
new file mode 100644
index 0000000..78d4156
--- /dev/null
+++ "b/prd/\347\263\273\347\273\237\346\266\210\346\201\257\346\216\250\351\200\201-\345\277\253\351\200\237\345\274\200\345\247\213.md"
@@ -0,0 +1,189 @@
+# 绯荤粺娑堟伅鎺ㄩ�佸姛鑳� - 蹇�熷紑濮�
+
+## 鍔熻兘璇存槑
+
+瀹炵幇浜嗗湪浠诲姟鍒涘缓銆佺姸鎬佸彉鏇淬�佸垎閰嶇敤鎴锋椂鑷姩鎺ㄩ�佹秷鎭粰鐩稿叧浜哄憳鐨勫姛鑳姐��
+
+## 蹇�熼儴缃�
+
+### 1. 鎵ц鏁版嵁搴撹剼鏈�
+
+```bash
+# 杩涘叆椤圭洰sql鐩綍
+cd d:\project\鎬ユ晳杞繍\code\Api\RuoYi-Vue-master\sql
+
+# 鎵ц娑堟伅琛ㄥ垱寤鸿剼鏈�
+mysql -u root -p your_database < sys_message.sql
+```
+
+鎴栬�呮墜鍔ㄦ墽琛孲QL锛�
+```sql
+-- 鍦∕ySQL瀹㈡埛绔腑鎵ц
+source d:/project/鎬ユ晳杞繍/code/Api/RuoYi-Vue-master/sql/sys_message.sql;
+```
+
+### 2. 閲嶅惎鍚庣鏈嶅姟
+
+```bash
+# Windows
+cd d:\project\鎬ユ晳杞繍\code\Api\RuoYi-Vue-master
+bin\run.bat
+
+# Linux
+cd /path/to/RuoYi-Vue-master
+sh bin/run.sh
+```
+
+### 3. 鍓嶇宸茶嚜鍔ㄩ泦鎴愶紝鏃犻渶棰濆鎿嶄綔
+
+## 蹇�熸祴璇�
+
+### 娴嬭瘯1锛氬垱寤轰换鍔℃秷鎭帹閫�
+
+1. 鍦ㄥ墠绔垱寤轰竴涓换鍔�
+2. 杩涘叆"娑堟伅涓績"椤甸潰
+3. 搴旇鐪嬪埌涓�鏉�"鍒涘缓鎴愬姛"娑堟伅
+
+### 娴嬭瘯2锛氫换鍔″垎閰嶆秷鎭帹閫�
+
+1. 鍒涘缓浠诲姟鏃堕�夋嫨鎵ц浜哄憳
+2. 鎵ц浜哄憳鐧诲綍绯荤粺
+3. 杩涘叆"娑堟伅涓績"椤甸潰
+4. 搴旇鐪嬪埌涓�鏉�"浠诲姟鎺ㄩ��"娑堟伅
+
+### 娴嬭瘯3锛氱姸鎬佸彉鏇存秷鎭帹閫�
+
+1. 鍦ㄩ椤电偣鍑讳换鍔$殑"鍑哄彂"鎸夐挳
+2. 鐩稿叧浜哄憳锛堟墽琛屼汉+鍒涘缓浜猴級杩涘叆"娑堟伅涓績"
+3. 搴旇鐪嬪埌涓�鏉�"鐘舵�佸彉鏇�"娑堟伅
+
+## 娑堟伅绫诲瀷
+
+| 绫诲瀷 | 鍦烘櫙 | 鎺ユ敹浜� | 鍐呭 |
+|------|------|--------|------|
+| 鍒涘缓鎴愬姛 | 鍒涘缓浠诲姟 | 鍒涘缓浜� | 鎮ㄥ垱寤虹殑浠诲姟宸叉垚鍔熸彁浜� |
+| 浠诲姟鎺ㄩ�� | 鍒嗛厤鎵ц浜� | 鎵ц浜� | 鎮ㄦ湁鏂扮殑浠诲姟锛岃鍙婃椂澶勭悊 |
+| 鐘舵�佸彉鏇� | 鏇存柊鐘舵�� | 鎵ц浜�+鍒涘缓浜� | 浠诲姟鐘舵�佸彉鏇翠负锛歑XX |
+
+## 鏍稿績鏂囦欢
+
+### 鍚庣
+- `sql/sys_message.sql` - 鏁版嵁搴撹〃
+- `SysMessage.java` - 瀹炰綋绫�
+- `SysMessageMapper.java` - Mapper鎺ュ彛
+- `SysMessageMapper.xml` - MyBatis鏄犲皠
+- `ISysMessageService.java` - Service鎺ュ彛
+- `SysMessageServiceImpl.java` - Service瀹炵幇
+- `SysMessageController.java` - Controller
+- `SysTaskServiceImpl.java` - 浠诲姟鏈嶅姟锛堝凡闆嗘垚娑堟伅鎺ㄩ�侊級
+
+### 鍓嶇
+- `app/api/message.js` - API鎺ュ彛
+- `app/pages/message/index.vue` - 娑堟伅涓績椤甸潰
+- `app/pages/index.vue` - 棣栭〉锛堟樉绀烘湭璇绘暟閲忥級
+
+## 涓昏API
+
+### 鍚庣鎺ュ彛
+
+```
+GET  /system/message/my              - 鑾峰彇褰撳墠鐢ㄦ埛娑堟伅鍒楄〃
+GET  /system/message/unread/count    - 鑾峰彇鏈娑堟伅鏁伴噺
+PUT  /system/message/read/{id}       - 鏍囪娑堟伅涓哄凡璇�
+PUT  /system/message/read/all        - 鏍囪鎵�鏈夋秷鎭负宸茶
+```
+
+### 鍓嶇璋冪敤绀轰緥
+
+```javascript
+import { getMyMessages, getUnreadCount, markAsRead } from '@/api/message'
+
+// 鑾峰彇娑堟伅鍒楄〃
+const messages = await getMyMessages()
+
+// 鑾峰彇鏈鏁伴噺
+const count = await getUnreadCount()
+
+// 鏍囪宸茶
+await markAsRead(messageId)
+```
+
+## 娑堟伅鎺ㄩ�佹椂鏈�
+
+### 1. 鍒涘缓浠诲姟锛坕nsertSysTask锛�
+```java
+// 鎺ㄩ�佸垱寤烘垚鍔熸秷鎭紙缁欏垱寤轰汉锛�
+if (result > 0 && sysMessageService != null) {
+    sysMessageService.pushTaskCreateMessage(task);
+}
+
+// 鎺ㄩ�佷换鍔″垎閰嶆秷鎭紙缁欐墽琛屼汉锛�
+if (result > 0 && createVO.getAssignees() != null && !createVO.getAssignees().isEmpty()) {
+    List<Long> assigneeIds = createVO.getAssignees().stream()
+        .map(assignee -> assignee.getUserId())
+        .collect(Collectors.toList());
+    sysMessageService.pushTaskAssignMessage(task, assigneeIds);
+}
+```
+
+### 2. 鍒嗛厤浠诲姟锛坅ssignTask锛�
+```java
+// 鎺ㄩ�佷换鍔″垎閰嶆秷鎭�
+if (result > 0 && sysMessageService != null) {
+    List<Long> assigneeIds = new ArrayList<>();
+    assigneeIds.add(assigneeId);
+    sysMessageService.pushTaskAssignMessage(task, assigneeIds);
+}
+```
+
+### 3. 鐘舵�佸彉鏇达紙changeTaskStatusWithLocation锛�
+```java
+// 鎺ㄩ�佷换鍔$姸鎬佸彉鏇存秷鎭�
+if (result > 0 && sysMessageService != null) {
+    sysMessageService.pushTaskStatusChangeMessage(
+        oldTask, 
+        oldTaskStatus.getCode(), 
+        newStatus.getCode()
+    );
+}
+```
+
+## 甯歌闂
+
+### Q1: 娑堟伅娌℃湁鎺ㄩ�佹�庝箞鍔烇紵
+A: 妫�鏌ヤ互涓嬪嚑鐐癸細
+1. 鏁版嵁搴撹〃鏄惁鍒涘缓鎴愬姛
+2. 鍚庣鏈嶅姟鏄惁閲嶅惎
+3. 鏌ョ湅鍚庣鏃ュ織鏄惁鏈夊紓甯�
+4. 纭 `ISysMessageService` 鏄惁娉ㄥ叆鎴愬姛
+
+### Q2: 娑堟伅鎺ㄩ�佸け璐ヤ細褰卞搷涓讳笟鍔″悧锛�
+A: 涓嶄細銆傛秷鎭帹閫佷娇鐢� `@Autowired(required = false)`锛屼笖鎵�鏈夊紓甯搁兘琚崟鑾凤紝涓嶄細褰卞搷浠诲姟鐨勫垱寤恒�佸垎閰嶅拰鐘舵�佸彉鏇淬��
+
+### Q3: 濡備綍鏌ョ湅娑堟伅鎺ㄩ�佹棩蹇楋紵
+A: 鏌ョ湅鍚庣鏃ュ織锛屾悳绱㈠叧閿瓧锛�
+- "鎺ㄩ�佷换鍔″垱寤烘垚鍔熸秷鎭�"
+- "鎺ㄩ�佷换鍔″垎閰嶆秷鎭�"
+- "鎺ㄩ�佷换鍔$姸鎬佸彉鏇存秷鎭�"
+
+### Q4: 鏈娑堟伅鏁伴噺涓嶆洿鏂版�庝箞鍔烇紵
+A: 
+1. 纭 `app/pages/index.vue` 宸叉洿鏂�
+2. 纭 `app/api/message.js` 宸插垱寤�
+3. 閲嶆柊缂栬瘧鍓嶇锛歚npm run build:h5`
+
+## 鎵╁睍寤鸿
+
+1. **WebSocket瀹炴椂鎺ㄩ��**锛氶泦鎴怶ebSocket瀹炵幇娑堟伅瀹炴椂鎺ㄩ��
+2. **鎺ㄩ�侀�氱煡**锛氶泦鎴愭瀬鍏夋帹閫佺瓑绗笁鏂规帹閫佹湇鍔�
+3. **娑堟伅妯℃澘**锛氶厤缃秷鎭ā鏉匡紝鏀寔鍙橀噺鏇挎崲
+4. **娑堟伅鍒嗙粍**锛氬鍔犳秷鎭垎缁勶紙绯荤粺閫氱煡銆佷换鍔℃彁閱掔瓑锛�
+
+## 璇︾粏鏂囨。
+
+璇锋煡鐪嬪畬鏁存枃妗o細`prd/绯荤粺娑堟伅鎺ㄩ�佸姛鑳藉疄鐜版�荤粨.md`
+
+---
+
+**鏇存柊鏃堕棿**: 2025-10-25  
+**鐗堟湰**: v1.0
diff --git "a/prd/\347\263\273\347\273\237\346\266\210\346\201\257\346\216\250\351\200\201-\346\226\207\344\273\266\345\217\230\346\233\264\346\270\205\345\215\225.md" "b/prd/\347\263\273\347\273\237\346\266\210\346\201\257\346\216\250\351\200\201-\346\226\207\344\273\266\345\217\230\346\233\264\346\270\205\345\215\225.md"
new file mode 100644
index 0000000..ad619da
--- /dev/null
+++ "b/prd/\347\263\273\347\273\237\346\266\210\346\201\257\346\216\250\351\200\201-\346\226\207\344\273\266\345\217\230\346\233\264\346\270\205\345\215\225.md"
@@ -0,0 +1,245 @@
+# 绯荤粺娑堟伅鎺ㄩ�佸姛鑳� - 鏂囦欢鍙樻洿娓呭崟
+
+## 鏂板鏂囦欢
+
+### 鏁版嵁搴撹剼鏈�
+- 鉁� `sql/sys_message.sql` - 娑堟伅琛ㄥ垱寤鸿剼鏈�
+
+### 鍚庣 - 瀹炰綋绫�
+- 鉁� `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessage.java` - 娑堟伅瀹炰綋绫�
+
+### 鍚庣 - Mapper灞�
+- 鉁� `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageMapper.java` - Mapper鎺ュ彛
+- 鉁� `ruoyi-system/src/main/resources/mapper/system/SysMessageMapper.xml` - MyBatis鏄犲皠鏂囦欢
+
+### 鍚庣 - Service灞�
+- 鉁� `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageService.java` - Service鎺ュ彛
+- 鉁� `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageServiceImpl.java` - Service瀹炵幇绫�
+
+### 鍚庣 - Controller灞�
+- 鉁� `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMessageController.java` - 娑堟伅Controller
+
+### 鍓嶇 - API
+- 鉁� `app/api/message.js` - 娑堟伅API鎺ュ彛
+
+### 鏂囨。
+- 鉁� `prd/绯荤粺娑堟伅鎺ㄩ�佸姛鑳藉疄鐜版�荤粨.md` - 瀹屾暣瀹炵幇鏂囨。
+- 鉁� `prd/绯荤粺娑堟伅鎺ㄩ��-蹇�熷紑濮�.md` - 蹇�熷紑濮嬫寚鍗�
+- 鉁� `prd/绯荤粺娑堟伅鎺ㄩ��-鏂囦欢鍙樻洿娓呭崟.md` - 鏈枃浠�
+
+## 淇敼鏂囦欢
+
+### 鍚庣
+- 鉁� `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java`
+  - 瀵煎叆 `ISysMessageService`
+  - 娉ㄥ叆 `ISysMessageService` 鏈嶅姟锛坮equired = false锛�
+  - 鍦� `insertSysTask` 鏂规硶涓坊鍔犲垱寤烘垚鍔熸秷鎭帹閫�
+  - 鍦� `insertSysTask` 鏂规硶涓坊鍔犱换鍔″垎閰嶆秷鎭帹閫�
+  - 鍦� `assignTask` 鏂规硶涓坊鍔犱换鍔″垎閰嶆秷鎭帹閫�
+  - 鍦� `changeTaskStatusWithLocation` 鏂规硶涓坊鍔犵姸鎬佸彉鏇存秷鎭帹閫�
+
+### 鍓嶇
+- 鉁� `app/pages/message/index.vue`
+  - 瀵煎叆 `message.js` API
+  - 瀹炵幇 `loadMessages` 鏂规硶鍔犺浇娑堟伅鍒楄〃
+  - 瀹炵幇 `loadUnreadMessageCount` 鏂规硶鍔犺浇鏈鏁伴噺
+  - 淇敼 `viewMessageDetail` 鏂规硶璋冪敤API鏍囪宸茶
+  - 娣诲姞 `onLoad` 鐢熷懡鍛ㄦ湡鍔犺浇鏁版嵁
+  - 娣诲姞 `onShow` 鐢熷懡鍛ㄦ湡鍒锋柊鏁版嵁
+  - 娣诲姞 `onPullDownRefresh` 鏀寔涓嬫媺鍒锋柊
+  - 淇敼娑堟伅瀛楁鏄犲皠锛坱ype鈫抦essageType, content鈫抦essageContent绛夛級
+
+- 鉁� `app/pages/index.vue`
+  - 瀵煎叆 `message.js` API涓殑 `getUnreadCount`
+  - 娣诲姞 `unreadMessageCount` 鏁版嵁瀛楁
+  - 娣诲姞 `loadUnreadMessageCount` 鏂规硶
+  - 鍦� `onLoad` 涓皟鐢� `loadUnreadMessageCount`
+  - 鍦� `onShow` 涓皟鐢� `loadUnreadMessageCount`
+  - 鍒犻櫎璁$畻灞炴�т腑鐨� `unreadMessageCount`锛堟敼涓篸ata瀛楁锛�
+
+## 鍙樻洿缁熻
+
+### 鏂板鏂囦欢鏁伴噺
+- 鏁版嵁搴撹剼鏈�: 1
+- Java鏂囦欢: 6
+- JavaScript鏂囦欢: 1
+- Vue鏂囦欢: 0锛堝凡瀛樺湪锛屼粎淇敼锛�
+- 鏂囨。鏂囦欢: 3
+- **鎬昏**: 11涓柊澧炴枃浠�
+
+### 淇敼鏂囦欢鏁伴噺
+- Java鏂囦欢: 1
+- Vue鏂囦欢: 2
+- **鎬昏**: 3涓慨鏀规枃浠�
+
+### 浠g爜琛屾暟缁熻
+- 鏂板浠g爜琛�: 绾�1400琛�
+  - SQL: 27琛�
+  - Java: 绾�900琛�
+  - JavaScript: 77琛�
+  - Vue淇敼: 绾�90琛�
+  - 鏂囨。: 绾�500琛�
+
+## 鍔熻兘妯″潡
+
+### 1. 鏁版嵁搴撳眰锛�1涓枃浠讹級
+- `sys_message` 琛ㄧ粨鏋�
+
+### 2. 鍚庣灞傦紙7涓枃浠讹級
+- 瀹炰綋绫伙紙1涓級
+- Mapper鎺ュ彛锛�1涓級
+- MyBatis鏄犲皠锛�1涓級
+- Service鎺ュ彛锛�1涓級
+- Service瀹炵幇锛�1涓級
+- Controller锛�1涓級
+- 浠诲姟鏈嶅姟闆嗘垚锛�1涓慨鏀癸級
+
+### 3. 鍓嶇灞傦紙3涓枃浠讹級
+- API鎺ュ彛锛�1涓柊澧烇級
+- 娑堟伅涓績椤甸潰锛�1涓慨鏀癸級
+- 棣栭〉鏈鏁伴噺锛�1涓慨鏀癸級
+
+### 4. 鏂囨。灞傦紙3涓枃浠讹級
+- 鍔熻兘瀹炵幇鎬荤粨
+- 蹇�熷紑濮嬫寚鍗�
+- 鏂囦欢鍙樻洿娓呭崟
+
+## 渚濊禆鍏崇郴
+
+### 鍚庣渚濊禆
+```
+SysMessageController
+    鈫� 渚濊禆
+ISysMessageService (鎺ュ彛)
+    鈫� 瀹炵幇
+SysMessageServiceImpl
+    鈫� 渚濊禆
+SysMessageMapper (鎺ュ彛)
+    鈫� 閰嶇疆
+SysMessageMapper.xml
+    鈫� 鎿嶄綔
+sys_message (鏁版嵁琛�)
+```
+
+### 浠诲姟鏈嶅姟闆嗘垚
+```
+SysTaskServiceImpl
+    鈫� 璋冪敤
+ISysMessageService.pushTaskCreateMessage()
+ISysMessageService.pushTaskAssignMessage()
+ISysMessageService.pushTaskStatusChangeMessage()
+    鈫� 鎿嶄綔
+sys_message (鏁版嵁琛�)
+```
+
+### 鍓嶇渚濊禆
+```
+index.vue / message/index.vue
+    鈫� 璋冪敤
+api/message.js
+    鈫� 璇锋眰
+鍚庣 SysMessageController
+    鈫� 鏌ヨ
+sys_message (鏁版嵁琛�)
+```
+
+## 閮ㄧ讲妫�鏌ユ竻鍗�
+
+- [ ] 1. 鎵ц鏁版嵁搴撹剼鏈� `sql/sys_message.sql`
+- [ ] 2. 纭 `sys_message` 琛ㄥ垱寤烘垚鍔�
+- [ ] 3. 閲嶆柊缂栬瘧鍚庣椤圭洰
+- [ ] 4. 閲嶅惎鍚庣鏈嶅姟
+- [ ] 5. 娓呯悊娴忚鍣ㄧ紦瀛�
+- [ ] 6. 娴嬭瘯鍒涘缓浠诲姟娑堟伅鎺ㄩ��
+- [ ] 7. 娴嬭瘯浠诲姟鍒嗛厤娑堟伅鎺ㄩ��
+- [ ] 8. 娴嬭瘯鐘舵�佸彉鏇存秷鎭帹閫�
+- [ ] 9. 娴嬭瘯娑堟伅鍒楄〃鏌ヨ
+- [ ] 10. 娴嬭瘯娑堟伅鏍囪宸茶
+- [ ] 11. 娴嬭瘯鏈娑堟伅鏁伴噺鏄剧ず
+
+## Git鎻愪氦寤鸿
+
+```bash
+# 鎻愪氦鏁版嵁搴撹剼鏈�
+git add sql/sys_message.sql
+git commit -m "feat: 娣诲姞绯荤粺娑堟伅琛ㄧ粨鏋�"
+
+# 鎻愪氦鍚庣浠g爜
+git add ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessage.java
+git add ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageMapper.java
+git add ruoyi-system/src/main/resources/mapper/system/SysMessageMapper.xml
+git add ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageService.java
+git add ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageServiceImpl.java
+git add ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMessageController.java
+git commit -m "feat: 瀹炵幇绯荤粺娑堟伅鎺ㄩ�佸悗绔湇鍔�"
+
+# 鎻愪氦浠诲姟鏈嶅姟闆嗘垚
+git add ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
+git commit -m "feat: 鍦ㄤ换鍔″垱寤恒�佸垎閰嶃�佺姸鎬佸彉鏇存椂闆嗘垚娑堟伅鎺ㄩ��"
+
+# 鎻愪氦鍓嶇浠g爜
+git add app/api/message.js
+git add app/pages/message/index.vue
+git add app/pages/index.vue
+git commit -m "feat: 瀹炵幇娑堟伅涓績鍓嶇椤甸潰鍜屾湭璇绘秷鎭鏁�"
+
+# 鎻愪氦鏂囨。
+git add prd/绯荤粺娑堟伅鎺ㄩ�佸姛鑳藉疄鐜版�荤粨.md
+git add prd/绯荤粺娑堟伅鎺ㄩ��-蹇�熷紑濮�.md
+git add prd/绯荤粺娑堟伅鎺ㄩ��-鏂囦欢鍙樻洿娓呭崟.md
+git commit -m "docs: 娣诲姞绯荤粺娑堟伅鎺ㄩ�佸姛鑳芥枃妗�"
+
+# 鎴栬�呬竴娆℃�ф彁浜�
+git add .
+git commit -m "feat: 瀹炵幇绯荤粺娑堟伅鎺ㄩ�佸姛鑳�
+
+- 鍒涘缓浠诲姟鏃舵帹閫佹秷鎭粰鍒涘缓浜哄拰鎵ц浜�
+- 浠诲姟鍒嗛厤鏃舵帹閫佹秷鎭粰鎵ц浜�
+- 鐘舵�佸彉鏇存椂鎺ㄩ�佹秷鎭粰鐩稿叧浜哄憳
+- 瀹炵幇娑堟伅涓績椤甸潰
+- 瀹炵幇鏈娑堟伅鏁伴噺鏄剧ず
+- 鏀寔娑堟伅宸茶鏍囪
+- 瀹屽杽鍔熻兘鏂囨。"
+```
+
+## 鍥炴粴鏂规
+
+濡傛灉闇�瑕佸洖婊氭鍔熻兘锛�
+
+### 1. 鏁版嵁搴撳洖婊�
+```sql
+DROP TABLE IF EXISTS `sys_message`;
+```
+
+### 2. 浠g爜鍥炴粴
+```bash
+# 鍒犻櫎鏂板鏂囦欢
+git rm ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessage.java
+git rm ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageMapper.java
+git rm ruoyi-system/src/main/resources/mapper/system/SysMessageMapper.xml
+git rm ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageService.java
+git rm ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageServiceImpl.java
+git rm ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMessageController.java
+git rm app/api/message.js
+
+# 鎭㈠淇敼鐨勬枃浠�
+git checkout ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
+git checkout app/pages/message/index.vue
+git checkout app/pages/index.vue
+
+git commit -m "revert: 鍥炴粴绯荤粺娑堟伅鎺ㄩ�佸姛鑳�"
+```
+
+## 娉ㄦ剰浜嬮」
+
+1. **鏁版嵁搴撳浠�**锛氭墽琛孲QL鑴氭湰鍓嶅缓璁浠芥暟鎹簱
+2. **鏈嶅姟閲嶅惎**锛氬悗绔慨鏀瑰悗蹇呴』閲嶅惎鏈嶅姟鎵嶈兘鐢熸晥
+3. **缂撳瓨娓呯悊**锛氬墠绔慨鏀瑰悗闇�瑕佹竻鐞嗘祻瑙堝櫒缂撳瓨
+4. **鍏煎鎬ф祴璇�**锛氶儴缃插悗闇�瑕佸叏闈㈡祴璇曞悇椤瑰姛鑳�
+5. **鎬ц兘鐩戞帶**锛氬叧娉ㄦ秷鎭帹閫佸绯荤粺鎬ц兘鐨勫奖鍝�
+
+---
+
+**鏇存柊鏃堕棿**: 2025-10-25  
+**鐗堟湰**: v1.0  
+**璐熻矗浜�**: AI Assistant
diff --git "a/prd/\347\263\273\347\273\237\346\266\210\346\201\257\346\216\250\351\200\201\345\212\237\350\203\275\345\256\236\347\216\260\346\200\273\347\273\223.md" "b/prd/\347\263\273\347\273\237\346\266\210\346\201\257\346\216\250\351\200\201\345\212\237\350\203\275\345\256\236\347\216\260\346\200\273\347\273\223.md"
new file mode 100644
index 0000000..2a27dfb
--- /dev/null
+++ "b/prd/\347\263\273\347\273\237\346\266\210\346\201\257\346\216\250\351\200\201\345\212\237\350\203\275\345\256\236\347\216\260\346\200\273\347\273\223.md"
@@ -0,0 +1,305 @@
+# 绯荤粺娑堟伅鎺ㄩ�佸姛鑳藉疄鐜版�荤粨
+
+## 鍔熻兘姒傝堪
+
+瀹炵幇浜嗗畬鏁寸殑绯荤粺娑堟伅鎺ㄩ�佸姛鑳斤紝鍖呮嫭鍦ㄤ换鍔″垱寤恒�佷换鍔″垎閰嶇敤鎴枫�佷换鍔$姸鎬佸彉鏇存椂鑷姩鎺ㄩ�佹秷鎭粰鐩稿叧鐢ㄦ埛銆�
+
+## 瀹炵幇鍐呭
+
+### 1. 鏁版嵁搴撹〃缁撴瀯
+
+**鏂囦欢浣嶇疆**: `sql/sys_message.sql`
+
+鍒涘缓浜� `sys_message` 琛紝鍖呭惈浠ヤ笅瀛楁锛�
+- `message_id`: 娑堟伅ID锛堜富閿級
+- `message_type`: 娑堟伅绫诲瀷锛圕REATE-鍒涘缓鎴愬姛, PUSH-浠诲姟鎺ㄩ��, STATUS-鐘舵�佸彉鏇�, ASSIGN-鍒嗛厤浠诲姟锛�
+- `message_title`: 娑堟伅鏍囬
+- `message_content`: 娑堟伅鍐呭
+- `task_id`: 鍏宠仈浠诲姟ID
+- `task_code`: 浠诲姟缂栧彿
+- `receiver_id`: 鎺ユ敹浜篒D
+- `receiver_name`: 鎺ユ敹浜哄鍚�
+- `sender_id`: 鍙戦�佷汉ID
+- `sender_name`: 鍙戦�佷汉濮撳悕
+- `is_read`: 鏄惁宸茶锛�0-鏈, 1-宸茶锛�
+- `read_time`: 璇诲彇鏃堕棿
+- `create_time`: 鍒涘缓鏃堕棿
+- `update_time`: 鏇存柊鏃堕棿
+- `del_flag`: 鍒犻櫎鏍囧織
+
+### 2. 鍚庣瀹炵幇
+
+#### 2.1 瀹炰綋绫�
+
+**鏂囦欢浣嶇疆**: `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessage.java`
+
+- 鍖呭惈鎵�鏈夋暟鎹簱瀛楁鐨刧etter/setter
+- 鏀寔Excel瀵煎嚭娉ㄨВ
+- 鏃ユ湡鏍煎紡鍖栨敞瑙�
+
+#### 2.2 Mapper灞�
+
+**鏂囦欢浣嶇疆**: 
+- `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageMapper.java`
+- `ruoyi-system/src/main/resources/mapper/system/SysMessageMapper.xml`
+
+鎻愪緵鐨勬柟娉曪細
+- `selectSysMessageList`: 鏌ヨ娑堟伅鍒楄〃
+- `selectSysMessageListByReceiverId`: 鏌ヨ鐢ㄦ埛娑堟伅鍒楄〃
+- `countUnreadMessageByReceiverId`: 鏌ヨ鏈娑堟伅鏁伴噺
+- `insertSysMessage`: 鏂板娑堟伅
+- `updateSysMessage`: 淇敼娑堟伅
+- `deleteSysMessageByMessageIds`: 鎵归噺鍒犻櫎娑堟伅
+- `markMessageAsRead`: 鏍囪娑堟伅涓哄凡璇�
+- `markAllMessagesAsRead`: 鏍囪鎵�鏈夋秷鎭负宸茶
+
+#### 2.3 Service灞�
+
+**鏂囦欢浣嶇疆**: 
+- `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageService.java`
+- `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageServiceImpl.java`
+
+鎻愪緵鐨勪笟鍔℃柟娉曪細
+- 鍩虹CRUD鏂规硶
+- `pushTaskCreateMessage`: 鎺ㄩ�佷换鍔″垱寤烘垚鍔熸秷鎭�
+- `pushTaskAssignMessage`: 鎺ㄩ�佷换鍔″垎閰嶆秷鎭�
+- `pushTaskStatusChangeMessage`: 鎺ㄩ�佷换鍔$姸鎬佸彉鏇存秷鎭�
+
+#### 2.4 Controller灞�
+
+**鏂囦欢浣嶇疆**: `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMessageController.java`
+
+鎻愪緵鐨凙PI鎺ュ彛锛�
+- `GET /system/message/list`: 鏌ヨ娑堟伅鍒楄〃
+- `GET /system/message/my`: 鏌ヨ褰撳墠鐢ㄦ埛娑堟伅鍒楄〃
+- `GET /system/message/unread/count`: 鏌ヨ鏈娑堟伅鏁伴噺
+- `GET /system/message/{messageId}`: 鑾峰彇娑堟伅璇︽儏
+- `POST /system/message`: 鏂板娑堟伅
+- `PUT /system/message`: 淇敼娑堟伅
+- `DELETE /system/message/{messageIds}`: 鍒犻櫎娑堟伅
+- `PUT /system/message/read/{messageId}`: 鏍囪娑堟伅涓哄凡璇�
+- `PUT /system/message/read/all`: 鏍囪鎵�鏈夋秷鎭负宸茶
+
+#### 2.5 浠诲姟鏈嶅姟闆嗘垚
+
+**鏂囦欢浣嶇疆**: `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java`
+
+鍦ㄤ互涓嬪満鏅嚜鍔ㄦ帹閫佹秷鎭細
+
+1. **浠诲姟鍒涘缓鎴愬姛**
+   - 鏃舵満锛歚insertSysTask` 鏂规硶鎵ц鎴愬姛鍚�
+   - 鎺ユ敹浜猴細浠诲姟鍒涘缓浜�
+   - 娑堟伅绫诲瀷锛欳REATE
+   - 娑堟伅鍐呭锛�"鎮ㄥ垱寤虹殑浠诲姟宸叉垚鍔熸彁浜�"
+
+2. **浠诲姟鍒嗛厤鐢ㄦ埛**
+   - 鏃舵満锛歚insertSysTask` 鏂规硶淇濆瓨鎵ц浜哄憳鍚庛�乣assignTask` 鏂规硶鎵ц鍚�
+   - 鎺ユ敹浜猴細鎵�鏈夋墽琛屼汉鍛�
+   - 娑堟伅绫诲瀷锛歅USH/ASSIGN
+   - 娑堟伅鍐呭锛�"鎮ㄦ湁鏂扮殑浠诲姟锛岃鍙婃椂澶勭悊"
+
+3. **浠诲姟鐘舵�佸彉鏇�**
+   - 鏃舵満锛歚changeTaskStatusWithLocation` 鏂规硶鎵ц鎴愬姛鍚�
+   - 鎺ユ敹浜猴細鎵�鏈夋墽琛屼汉鍛� + 鍒涘缓浜�
+   - 娑堟伅绫诲瀷锛歋TATUS
+   - 娑堟伅鍐呭锛氭牴鎹姸鎬佸彉鍖栧姩鎬佺敓鎴�
+     - PENDING: "浠诲姟鐘舵�佸彉鏇翠负锛氬緟澶勭悊"
+     - DEPARTED: "浠诲姟鐘舵�佸彉鏇翠负锛氬凡鍑哄彂"
+     - ARRIVED: "浠诲姟鐘舵�佸彉鏇翠负锛氬凡鍒拌揪"
+     - RETURNING: "浠诲姟鐘舵�佸彉鏇翠负锛氳繑绋嬩腑"
+     - COMPLETED: "浠诲姟鐘舵�佸彉鏇翠负锛氬凡瀹屾垚"
+     - CANCELLED: "浠诲姟鐘舵�佸彉鏇翠负锛氬凡鍙栨秷"
+
+### 3. 鍓嶇瀹炵幇
+
+#### 3.1 API鎺ュ彛
+
+**鏂囦欢浣嶇疆**: `app/api/message.js`
+
+鎻愪緵鐨勬柟娉曪細
+- `getMyMessages`: 鑾峰彇褰撳墠鐢ㄦ埛娑堟伅鍒楄〃
+- `listMessage`: 鏌ヨ娑堟伅鍒楄〃
+- `getMessage`: 鑾峰彇娑堟伅璇︽儏
+- `getUnreadCount`: 鑾峰彇鏈娑堟伅鏁伴噺
+- `addMessage`: 鏂板娑堟伅
+- `updateMessage`: 淇敼娑堟伅
+- `delMessage`: 鍒犻櫎娑堟伅
+- `markAsRead`: 鏍囪娑堟伅涓哄凡璇�
+- `markAllAsRead`: 鏍囪鎵�鏈夋秷鎭负宸茶
+
+#### 3.2 娑堟伅涓績椤甸潰
+
+**鏂囦欢浣嶇疆**: `app/pages/message/index.vue`
+
+鍔熻兘鐗规�э細
+- 鑷姩鍔犺浇褰撳墠鐢ㄦ埛鐨勬秷鎭垪琛�
+- 鏈娑堟伅鏄剧ず绾㈢偣鏍囪
+- 鏈娑堟伅鎺掑湪鍓嶉潰
+- 鏀寔涓嬫媺鍒锋柊
+- 鐐瑰嚮娑堟伅鑷姩鏍囪涓哄凡璇诲苟璺宠浆鍒颁换鍔¤鎯�
+- 娑堟伅绫诲瀷鏄剧ず锛堝垱寤烘垚鍔熴�佷换鍔℃帹閫併�佺姸鎬佸彉鏇淬�佷换鍔″垎閰嶏級
+
+#### 3.3 棣栭〉闆嗘垚
+
+**鏂囦欢浣嶇疆**: `app/pages/index.vue`
+
+鍔熻兘鐗规�э細
+- 娑堟伅涓績鍏ュ彛
+- 鏄剧ず鏈娑堟伅鏁伴噺寰界珷
+- 椤甸潰鏄剧ず鏃惰嚜鍔ㄥ埛鏂版湭璇绘秷鎭暟閲�
+
+## 娑堟伅绫诲瀷璇存槑
+
+| 娑堟伅绫诲瀷 | 浠g爜 | 瑙﹀彂鍦烘櫙 | 鎺ユ敹浜� | 娑堟伅鍐呭 |
+|---------|------|---------|--------|---------|
+| 鍒涘缓鎴愬姛 | CREATE | 浠诲姟鍒涘缓鎴愬姛 | 鍒涘缓浜� | 鎮ㄥ垱寤虹殑浠诲姟宸叉垚鍔熸彁浜� |
+| 浠诲姟鎺ㄩ�� | PUSH | 浠诲姟鍒嗛厤缁欐墽琛屼汉 | 鎵ц浜� | 鎮ㄦ湁鏂扮殑浠诲姟锛岃鍙婃椂澶勭悊 |
+| 浠诲姟鍒嗛厤 | ASSIGN | 閲嶆柊鍒嗛厤浠诲姟 | 鏂版墽琛屼汉 | 鎮ㄦ湁鏂扮殑浠诲姟锛岃鍙婃椂澶勭悊 |
+| 鐘舵�佸彉鏇� | STATUS | 浠诲姟鐘舵�佸彉鏇� | 鎵ц浜�+鍒涘缓浜� | 浠诲姟鐘舵�佸彉鏇翠负锛歑XX |
+
+## 浣跨敤鎸囧崡
+
+### 閮ㄧ讲姝ラ
+
+1. **鎵ц鏁版嵁搴撹剼鏈�**
+```bash
+mysql -u root -p your_database < sql/sys_message.sql
+```
+
+2. **閲嶆柊缂栬瘧鍚庣**
+```bash
+cd ruoyi-admin
+mvn clean package
+```
+
+3. **閲嶅惎鍚庣鏈嶅姟**
+```bash
+# Windows
+bin\run.bat
+
+# Linux
+sh bin/run.sh
+```
+
+4. **鍓嶇鏃犻渶棰濆鎿嶄綔**锛屼唬鐮佸凡鑷姩闆嗘垚
+
+### 娴嬭瘯楠岃瘉
+
+1. **鍒涘缓浠诲姟**
+   - 鍒涘缓浠诲姟鍚庯紝鍒涘缓浜哄簲鏀跺埌"鍒涘缓鎴愬姛"娑堟伅
+   - 鎵ц浜哄簲鏀跺埌"浠诲姟鎺ㄩ��"娑堟伅
+
+2. **鏇存柊浠诲姟鐘舵��**
+   - 鍦ㄥ墠绔偣鍑�"鍑哄彂"銆�"宸插埌杈�"绛夋寜閽�
+   - 鐩稿叧浜哄憳搴旀敹鍒�"鐘舵�佸彉鏇�"娑堟伅
+
+3. **鍒嗛厤浠诲姟**
+   - 璋冪敤浠诲姟鍒嗛厤鎺ュ彛
+   - 鏂版墽琛屼汉搴旀敹鍒�"浠诲姟鍒嗛厤"娑堟伅
+
+4. **鏌ョ湅娑堟伅**
+   - 杩涘叆娑堟伅涓績椤甸潰
+   - 鏈娑堟伅鏄剧ず绾㈢偣
+   - 鐐瑰嚮娑堟伅璺宠浆鍒颁换鍔¤鎯呭苟鏍囪涓哄凡璇�
+
+## 鎶�鏈壒鐐�
+
+### 1. 寮傛鎺ㄩ��
+- 娑堟伅鎺ㄩ�佷笉褰卞搷涓讳笟鍔℃祦绋�
+- 浣跨敤 `@Autowired(required = false)` 纭繚鏈嶅姟鍙��
+
+### 2. 浜嬪姟瀹夊叏
+- 娑堟伅鎺ㄩ�佸湪浜嬪姟鎻愪氦鍚庢墽琛�
+- 閬垮厤浜嬪姟鍥炴粴瀵艰嚧鐨勬暟鎹笉涓�鑷�
+
+### 3. 瀹归敊澶勭悊
+- 娑堟伅鎺ㄩ�佸け璐ヤ笉褰卞搷涓讳笟鍔�
+- 瀹屽杽鐨勫紓甯告崟鑾峰拰鏃ュ織璁板綍
+
+### 4. 鎬ц兘浼樺寲
+- 鎵归噺鏌ヨ鐢ㄦ埛淇℃伅
+- 绱㈠紩浼樺寲锛坮eceiver_id銆乼ask_id銆乮s_read銆乧reate_time锛�
+
+### 5. 鐢ㄦ埛浣撻獙
+- 瀹炴椂鏈娑堟伅璁℃暟
+- 娑堟伅鍒嗙被鏄剧ず
+- 鏈娑堟伅浼樺厛鎺掑簭
+- 涓�閿爣璁板凡璇�
+
+## 鎵╁睍寤鸿
+
+### 1. WebSocket瀹炴椂鎺ㄩ��
+鍙互闆嗘垚WebSocket瀹炵幇瀹炴椂娑堟伅鎺ㄩ�侊紝鑰屼笉闇�瑕佺敤鎴峰埛鏂伴〉闈細
+
+```java
+@Service
+public class WebSocketMessageService {
+    @Autowired
+    private SimpMessagingTemplate messagingTemplate;
+    
+    public void pushMessage(Long userId, SysMessage message) {
+        messagingTemplate.convertAndSendToUser(
+            userId.toString(), 
+            "/queue/messages", 
+            message
+        );
+    }
+}
+```
+
+### 2. 鎺ㄩ�侀�氱煡
+鍙互闆嗘垚绗笁鏂规帹閫佹湇鍔★紙濡傛瀬鍏夋帹閫併�佷釜鎺ㄧ瓑锛夊疄鐜癆PP閫氱煡锛�
+
+```java
+public void sendPushNotification(Long userId, String title, String content) {
+    // 璋冪敤鎺ㄩ�佹湇鍔DK
+    JPushClient.push(userId, title, content);
+}
+```
+
+### 3. 娑堟伅妯℃澘
+鍙互閰嶇疆娑堟伅妯℃澘锛屾敮鎸佸彉閲忔浛鎹細
+
+```java
+public class MessageTemplate {
+    private String type;
+    private String titleTemplate;
+    private String contentTemplate;
+    
+    public String render(Map<String, Object> params) {
+        // 妯℃澘娓叉煋閫昏緫
+    }
+}
+```
+
+### 4. 娑堟伅鍒嗙粍
+鍙互澧炲姞娑堟伅鍒嗙粍鍔熻兘锛�
+
+- 绯荤粺閫氱煡
+- 浠诲姟鎻愰啋
+- 瀹℃壒娑堟伅
+- 鍏憡娑堟伅
+
+### 5. 娑堟伅宸茶鍥炴墽
+鍙互璁板綍娑堟伅鐨勮缁嗛槄璇昏褰曪細
+
+```sql
+CREATE TABLE sys_message_read_log (
+    log_id BIGINT PRIMARY KEY,
+    message_id BIGINT,
+    user_id BIGINT,
+    read_time DATETIME,
+    device_type VARCHAR(20)
+);
+```
+
+## 娉ㄦ剰浜嬮」
+
+1. **鏉冮檺鎺у埗**锛氱‘淇濈敤鎴峰彧鑳芥煡鐪嬭嚜宸辩殑娑堟伅
+2. **鏁版嵁娓呯悊**锛氬畾鏈熸竻鐞嗚繃鏈熺殑宸茶娑堟伅
+3. **鎬ц兘鐩戞帶**锛氱洃鎺ф秷鎭帹閫佺殑鎬ц兘锛岄伩鍏嶅ぇ閲忔秷鎭帹閫侀�犳垚鎬ц兘闂
+4. **鏃ュ織璁板綍**锛氬畬鏁磋褰曟秷鎭帹閫佺殑鏃ュ織锛屼究浜庢帓鏌ラ棶棰�
+
+## 鎬荤粨
+
+鏈瀹炵幇浜嗗畬鏁寸殑绯荤粺娑堟伅鎺ㄩ�佸姛鑳斤紝娑电洊浜嗕换鍔″垱寤恒�佸垎閰嶃�佺姸鎬佸彉鏇翠笁涓牳蹇冨満鏅�傚悗绔噰鐢⊿ervice灞傜粺涓�绠$悊娑堟伅鎺ㄩ�侀�昏緫锛屽墠绔彁渚涘弸濂界殑娑堟伅涓績鐣岄潰銆傛暣涓郴缁熻璁″悎鐞嗭紝鏄撲簬鎵╁睍鍜岀淮鎶ゃ��
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMessageController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMessageController.java
new file mode 100644
index 0000000..7a7f03f
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMessageController.java
@@ -0,0 +1,138 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+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.enums.BusinessType;
+import com.ruoyi.system.domain.SysMessage;
+import com.ruoyi.system.service.ISysMessageService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.utils.SecurityUtils;
+
+/**
+ * 绯荤粺娑堟伅Controller
+ * 
+ * @author ruoyi
+ * @date 2025-10-25
+ */
+@RestController
+@RequestMapping("/system/message")
+public class SysMessageController extends BaseController {
+    
+    @Autowired
+    private ISysMessageService sysMessageService;
+
+    /**
+     * 鏌ヨ绯荤粺娑堟伅鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('system:message:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysMessage sysMessage) {
+        startPage();
+        List<SysMessage> list = sysMessageService.selectSysMessageList(sysMessage);
+        return getDataTable(list);
+    }
+
+    /**
+     * 鏌ヨ褰撳墠鐢ㄦ埛鐨勬秷鎭垪琛�
+     */
+    @GetMapping("/my")
+    public AjaxResult myMessages() {
+        Long userId = SecurityUtils.getUserId();
+        List<SysMessage> list = sysMessageService.selectSysMessageListByReceiverId(userId);
+        return AjaxResult.success(list);
+    }
+
+    /**
+     * 鏌ヨ褰撳墠鐢ㄦ埛鏈娑堟伅鏁伴噺
+     */
+    @GetMapping("/unread/count")
+    public AjaxResult unreadCount() {
+        Long userId = SecurityUtils.getUserId();
+        int count = sysMessageService.countUnreadMessageByReceiverId(userId);
+        return AjaxResult.success(count);
+    }
+
+    /**
+     * 瀵煎嚭绯荤粺娑堟伅鍒楄〃
+     */
+    @PreAuthorize("@ss.hasPermi('system:message:export')")
+    @Log(title = "绯荤粺娑堟伅", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysMessage sysMessage) {
+        List<SysMessage> list = sysMessageService.selectSysMessageList(sysMessage);
+        ExcelUtil<SysMessage> util = new ExcelUtil<SysMessage>(SysMessage.class);
+        util.exportExcel(response, list, "绯荤粺娑堟伅鏁版嵁");
+    }
+
+    /**
+     * 鑾峰彇绯荤粺娑堟伅璇︾粏淇℃伅
+     */
+    @PreAuthorize("@ss.hasPermi('system:message:query')")
+    @GetMapping(value = "/{messageId}")
+    public AjaxResult getInfo(@PathVariable("messageId") Long messageId) {
+        return AjaxResult.success(sysMessageService.selectSysMessageByMessageId(messageId));
+    }
+
+    /**
+     * 鏂板绯荤粺娑堟伅
+     */
+    @PreAuthorize("@ss.hasPermi('system:message:add')")
+    @Log(title = "绯荤粺娑堟伅", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody SysMessage sysMessage) {
+        return toAjax(sysMessageService.insertSysMessage(sysMessage));
+    }
+
+    /**
+     * 淇敼绯荤粺娑堟伅
+     */
+    @PreAuthorize("@ss.hasPermi('system:message:edit')")
+    @Log(title = "绯荤粺娑堟伅", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody SysMessage sysMessage) {
+        return toAjax(sysMessageService.updateSysMessage(sysMessage));
+    }
+
+    /**
+     * 鍒犻櫎绯荤粺娑堟伅
+     */
+    @PreAuthorize("@ss.hasPermi('system:message:remove')")
+    @Log(title = "绯荤粺娑堟伅", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{messageIds}")
+    public AjaxResult remove(@PathVariable Long[] messageIds) {
+        return toAjax(sysMessageService.deleteSysMessageByMessageIds(messageIds));
+    }
+
+    /**
+     * 鏍囪娑堟伅涓哄凡璇�
+     */
+    @Log(title = "绯荤粺娑堟伅", businessType = BusinessType.UPDATE)
+    @PutMapping("/read/{messageId}")
+    public AjaxResult markAsRead(@PathVariable Long messageId) {
+        return toAjax(sysMessageService.markMessageAsRead(messageId));
+    }
+
+    /**
+     * 鏍囪鎵�鏈夋秷鎭负宸茶
+     */
+    @Log(title = "绯荤粺娑堟伅", businessType = BusinessType.UPDATE)
+    @PutMapping("/read/all")
+    public AjaxResult markAllAsRead() {
+        Long userId = SecurityUtils.getUserId();
+        return toAjax(sysMessageService.markAllMessagesAsRead(userId));
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java
new file mode 100644
index 0000000..9941634
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java
@@ -0,0 +1,40 @@
+package com.ruoyi.framework.config;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+/**
+ * 寮傛浠诲姟閰嶇疆
+ * 鐢ㄤ簬鏀寔@Async娉ㄨВ鐨勫紓姝ユ柟娉曟墽琛�
+ * 
+ * @author ruoyi
+ */
+@Configuration
+@EnableAsync
+public class AsyncConfig {
+    
+    /**
+     * 鑷畾涔夊紓姝ヤ换鍔$嚎绋嬫睜
+     */
+    @Bean(name = "taskExecutor")
+    public Executor taskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        // 鏍稿績绾跨▼鏁�
+        executor.setCorePoolSize(5);
+        // 鏈�澶х嚎绋嬫暟
+        executor.setMaxPoolSize(10);
+        // 闃熷垪瀹归噺
+        executor.setQueueCapacity(100);
+        // 绾跨▼鍚嶇О鍓嶇紑
+        executor.setThreadNamePrefix("async-task-");
+        // 鎷掔粷绛栫暐锛氱敱璋冪敤绾跨▼鎵ц
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        // 鍒濆鍖�
+        executor.initialize();
+        return executor;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessage.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessage.java
new file mode 100644
index 0000000..4809ea1
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMessage.java
@@ -0,0 +1,186 @@
+package com.ruoyi.system.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 绯荤粺娑堟伅瀵硅薄 sys_message
+ * 
+ * @author ruoyi
+ * @date 2025-10-25
+ */
+public class SysMessage extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /** 娑堟伅ID */
+    private Long messageId;
+
+    /** 娑堟伅绫诲瀷锛欳REATE-鍒涘缓鎴愬姛,PUSH-浠诲姟鎺ㄩ��,STATUS-鐘舵�佸彉鏇�,ASSIGN-鍒嗛厤浠诲姟 */
+    @Excel(name = "娑堟伅绫诲瀷")
+    private String messageType;
+
+    /** 娑堟伅鏍囬 */
+    @Excel(name = "娑堟伅鏍囬")
+    private String messageTitle;
+
+    /** 娑堟伅鍐呭 */
+    @Excel(name = "娑堟伅鍐呭")
+    private String messageContent;
+
+    /** 鍏宠仈浠诲姟ID */
+    private Long taskId;
+
+    /** 浠诲姟缂栧彿 */
+    @Excel(name = "浠诲姟缂栧彿")
+    private String taskCode;
+
+    /** 鎺ユ敹浜篒D */
+    private Long receiverId;
+
+    /** 鎺ユ敹浜哄鍚� */
+    @Excel(name = "鎺ユ敹浜哄鍚�")
+    private String receiverName;
+
+    /** 鍙戦�佷汉ID */
+    private Long senderId;
+
+    /** 鍙戦�佷汉濮撳悕 */
+    @Excel(name = "鍙戦�佷汉濮撳悕")
+    private String senderName;
+
+    /** 鏄惁宸茶锛�0-鏈,1-宸茶 */
+    @Excel(name = "鏄惁宸茶", readConverterExp = "0=鏈,1=宸茶")
+    private String isRead;
+
+    /** 璇诲彇鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date readTime;
+
+    /** 鍒犻櫎鏍囧織 */
+    private String delFlag;
+
+    public void setMessageId(Long messageId) {
+        this.messageId = messageId;
+    }
+
+    public Long getMessageId() {
+        return messageId;
+    }
+
+    public void setMessageType(String messageType) {
+        this.messageType = messageType;
+    }
+
+    public String getMessageType() {
+        return messageType;
+    }
+
+    public void setMessageTitle(String messageTitle) {
+        this.messageTitle = messageTitle;
+    }
+
+    public String getMessageTitle() {
+        return messageTitle;
+    }
+
+    public void setMessageContent(String messageContent) {
+        this.messageContent = messageContent;
+    }
+
+    public String getMessageContent() {
+        return messageContent;
+    }
+
+    public void setTaskId(Long taskId) {
+        this.taskId = taskId;
+    }
+
+    public Long getTaskId() {
+        return taskId;
+    }
+
+    public void setTaskCode(String taskCode) {
+        this.taskCode = taskCode;
+    }
+
+    public String getTaskCode() {
+        return taskCode;
+    }
+
+    public void setReceiverId(Long receiverId) {
+        this.receiverId = receiverId;
+    }
+
+    public Long getReceiverId() {
+        return receiverId;
+    }
+
+    public void setReceiverName(String receiverName) {
+        this.receiverName = receiverName;
+    }
+
+    public String getReceiverName() {
+        return receiverName;
+    }
+
+    public void setSenderId(Long senderId) {
+        this.senderId = senderId;
+    }
+
+    public Long getSenderId() {
+        return senderId;
+    }
+
+    public void setSenderName(String senderName) {
+        this.senderName = senderName;
+    }
+
+    public String getSenderName() {
+        return senderName;
+    }
+
+    public void setIsRead(String isRead) {
+        this.isRead = isRead;
+    }
+
+    public String getIsRead() {
+        return isRead;
+    }
+
+    public void setReadTime(Date readTime) {
+        this.readTime = readTime;
+    }
+
+    public Date getReadTime() {
+        return readTime;
+    }
+
+    public void setDelFlag(String delFlag) {
+        this.delFlag = delFlag;
+    }
+
+    public String getDelFlag() {
+        return delFlag;
+    }
+
+    @Override
+    public String toString() {
+        return "SysMessage{" +
+                "messageId=" + messageId +
+                ", messageType='" + messageType + '\'' +
+                ", messageTitle='" + messageTitle + '\'' +
+                ", messageContent='" + messageContent + '\'' +
+                ", taskId=" + taskId +
+                ", taskCode='" + taskCode + '\'' +
+                ", receiverId=" + receiverId +
+                ", receiverName='" + receiverName + '\'' +
+                ", senderId=" + senderId +
+                ", senderName='" + senderName + '\'' +
+                ", isRead='" + isRead + '\'' +
+                ", readTime=" + readTime +
+                ", delFlag='" + delFlag + '\'' +
+                '}';
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskAssignedEvent.java b/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskAssignedEvent.java
new file mode 100644
index 0000000..3e21042
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskAssignedEvent.java
@@ -0,0 +1,68 @@
+package com.ruoyi.system.event;
+
+import java.util.List;
+
+/**
+ * 浠诲姟鍒嗛厤浜嬩欢
+ * 
+ * @author ruoyi
+ * @date 2025-10-25
+ */
+public class TaskAssignedEvent extends TaskEvent {
+    
+    private static final long serialVersionUID = 1L;
+    
+    /** 鎵ц浜篒D鍒楄〃 */
+    private List<Long> assigneeIds;
+    
+    /** 鎵ц浜哄鍚嶅垪琛� */
+    private List<String> assigneeNames;
+    
+    /** 鍒嗛厤浜篒D */
+    private Long assignerId;
+    
+    /** 鍒嗛厤浜哄鍚� */
+    private String assignerName;
+
+    public TaskAssignedEvent(Object source, Long taskId, String taskCode, 
+                            List<Long> assigneeIds, List<String> assigneeNames,
+                            Long assignerId, String assignerName) {
+        super(source, taskId, taskCode, assignerId, assignerName);
+        this.assigneeIds = assigneeIds;
+        this.assigneeNames = assigneeNames;
+        this.assignerId = assignerId;
+        this.assignerName = assignerName;
+    }
+
+    public List<Long> getAssigneeIds() {
+        return assigneeIds;
+    }
+
+    public void setAssigneeIds(List<Long> assigneeIds) {
+        this.assigneeIds = assigneeIds;
+    }
+
+    public List<String> getAssigneeNames() {
+        return assigneeNames;
+    }
+
+    public void setAssigneeNames(List<String> assigneeNames) {
+        this.assigneeNames = assigneeNames;
+    }
+
+    public Long getAssignerId() {
+        return assignerId;
+    }
+
+    public void setAssignerId(Long assignerId) {
+        this.assignerId = assignerId;
+    }
+
+    public String getAssignerName() {
+        return assignerName;
+    }
+
+    public void setAssignerName(String assignerName) {
+        this.assignerName = assignerName;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskCreatedEvent.java b/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskCreatedEvent.java
new file mode 100644
index 0000000..f96356d
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskCreatedEvent.java
@@ -0,0 +1,55 @@
+package com.ruoyi.system.event;
+
+import java.util.List;
+
+/**
+ * 浠诲姟鍒涘缓浜嬩欢
+ * 
+ * @author ruoyi
+ * @date 2025-10-25
+ */
+public class TaskCreatedEvent extends TaskEvent {
+    
+    private static final long serialVersionUID = 1L;
+    
+    /** 浠诲姟绫诲瀷 */
+    private String taskType;
+    
+    /** 鍒涘缓浜篒D */
+    private Long creatorId;
+    
+    /** 鍒涘缓浜哄鍚� */
+    private String creatorName;
+
+    public TaskCreatedEvent(Object source, Long taskId, String taskCode, String taskType, 
+                           Long creatorId, String creatorName) {
+        super(source, taskId, taskCode, creatorId, creatorName);
+        this.taskType = taskType;
+        this.creatorId = creatorId;
+        this.creatorName = creatorName;
+    }
+
+    public String getTaskType() {
+        return taskType;
+    }
+
+    public void setTaskType(String taskType) {
+        this.taskType = taskType;
+    }
+
+    public Long getCreatorId() {
+        return creatorId;
+    }
+
+    public void setCreatorId(Long creatorId) {
+        this.creatorId = creatorId;
+    }
+
+    public String getCreatorName() {
+        return creatorName;
+    }
+
+    public void setCreatorName(String creatorName) {
+        this.creatorName = creatorName;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskEvent.java b/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskEvent.java
new file mode 100644
index 0000000..1367312
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskEvent.java
@@ -0,0 +1,72 @@
+package com.ruoyi.system.event;
+
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * 浠诲姟浜嬩欢鍩虹被
+ * 
+ * @author ruoyi
+ * @date 2025-10-25
+ */
+public abstract class TaskEvent extends ApplicationEvent {
+    
+    private static final long serialVersionUID = 1L;
+    
+    /** 浠诲姟ID */
+    private Long taskId;
+    
+    /** 浠诲姟缂栧彿 */
+    private String taskCode;
+    
+    /** 鎿嶄綔浜篒D */
+    private Long operatorId;
+    
+    /** 鎿嶄綔浜哄鍚� */
+    private String operatorName;
+
+    public TaskEvent(Object source, Long taskId, String taskCode) {
+        super(source);
+        this.taskId = taskId;
+        this.taskCode = taskCode;
+    }
+
+    public TaskEvent(Object source, Long taskId, String taskCode, Long operatorId, String operatorName) {
+        super(source);
+        this.taskId = taskId;
+        this.taskCode = taskCode;
+        this.operatorId = operatorId;
+        this.operatorName = operatorName;
+    }
+
+    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 Long getOperatorId() {
+        return operatorId;
+    }
+
+    public void setOperatorId(Long operatorId) {
+        this.operatorId = operatorId;
+    }
+
+    public String getOperatorName() {
+        return operatorName;
+    }
+
+    public void setOperatorName(String operatorName) {
+        this.operatorName = operatorName;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskStatusChangedEvent.java b/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskStatusChangedEvent.java
new file mode 100644
index 0000000..81708b8
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskStatusChangedEvent.java
@@ -0,0 +1,93 @@
+package com.ruoyi.system.event;
+
+import java.util.List;
+
+/**
+ * 浠诲姟鐘舵�佸彉鏇翠簨浠�
+ * 
+ * @author ruoyi
+ * @date 2025-10-25
+ */
+public class TaskStatusChangedEvent extends TaskEvent {
+    
+    private static final long serialVersionUID = 1L;
+    
+    /** 鏃х姸鎬� */
+    private String oldStatus;
+    
+    /** 鏂扮姸鎬� */
+    private String newStatus;
+    
+    /** 鏃х姸鎬佹弿杩� */
+    private String oldStatusDesc;
+    
+    /** 鏂扮姸鎬佹弿杩� */
+    private String newStatusDesc;
+    
+    /** 鎵ц浜篒D鍒楄〃 */
+    private List<Long> assigneeIds;
+    
+    /** 鍒涘缓浜篒D */
+    private Long creatorId;
+
+    public TaskStatusChangedEvent(Object source, Long taskId, String taskCode,
+                                 String oldStatus, String newStatus,
+                                 String oldStatusDesc, String newStatusDesc,
+                                 List<Long> assigneeIds, Long creatorId) {
+        super(source, taskId, taskCode);
+        this.oldStatus = oldStatus;
+        this.newStatus = newStatus;
+        this.oldStatusDesc = oldStatusDesc;
+        this.newStatusDesc = newStatusDesc;
+        this.assigneeIds = assigneeIds;
+        this.creatorId = creatorId;
+    }
+
+    public String getOldStatus() {
+        return oldStatus;
+    }
+
+    public void setOldStatus(String oldStatus) {
+        this.oldStatus = oldStatus;
+    }
+
+    public String getNewStatus() {
+        return newStatus;
+    }
+
+    public void setNewStatus(String newStatus) {
+        this.newStatus = newStatus;
+    }
+
+    public String getOldStatusDesc() {
+        return oldStatusDesc;
+    }
+
+    public void setOldStatusDesc(String oldStatusDesc) {
+        this.oldStatusDesc = oldStatusDesc;
+    }
+
+    public String getNewStatusDesc() {
+        return newStatusDesc;
+    }
+
+    public void setNewStatusDesc(String newStatusDesc) {
+        this.newStatusDesc = newStatusDesc;
+    }
+
+    public List<Long> getAssigneeIds() {
+        return assigneeIds;
+    }
+
+    public void setAssigneeIds(List<Long> assigneeIds) {
+        this.assigneeIds = assigneeIds;
+    }
+
+    public Long getCreatorId() {
+        return creatorId;
+    }
+
+    public void setCreatorId(Long creatorId) {
+        this.creatorId = creatorId;
+    }
+}
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
new file mode 100644
index 0000000..8a14ec2
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java
@@ -0,0 +1,224 @@
+package com.ruoyi.system.listener;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.system.domain.SysMessage;
+import com.ruoyi.system.event.TaskCreatedEvent;
+import com.ruoyi.system.event.TaskAssignedEvent;
+import com.ruoyi.system.event.TaskStatusChangedEvent;
+import com.ruoyi.system.mapper.SysMessageMapper;
+import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.common.core.domain.entity.SysUser;
+
+/**
+ * 浠诲姟娑堟伅鐩戝惉鍣�
+ * 鐩戝惉浠诲姟鐩稿叧浜嬩欢骞朵繚瀛樻秷鎭埌娑堟伅搴�
+ * 
+ * @author ruoyi
+ * @date 2025-10-25
+ */
+@Component
+public class TaskMessageListener {
+    
+    private static final Logger log = LoggerFactory.getLogger(TaskMessageListener.class);
+    
+    @Autowired
+    private SysMessageMapper sysMessageMapper;
+    
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
+    /**
+     * 鐩戝惉浠诲姟鍒涘缓浜嬩欢
+     * 
+     * @param event 浠诲姟鍒涘缓浜嬩欢
+     */
+    @Async
+    @EventListener
+    public void handleTaskCreatedEvent(TaskCreatedEvent event) {
+        try {
+            log.info("鏀跺埌浠诲姟鍒涘缓浜嬩欢锛屼换鍔D锛歿}锛屼换鍔$紪鍙凤細{}", event.getTaskId(), event.getTaskCode());
+            
+            // 鑾峰彇鍒涘缓浜轰俊鎭�
+            SysUser creator = sysUserMapper.selectUserById(event.getCreatorId());
+            if (creator == null) {
+                log.warn("鎵句笉鍒板垱寤轰汉淇℃伅锛岀敤鎴稩D锛歿}", event.getCreatorId());
+                return;
+            }
+            
+            // 鍒涘缓娑堟伅
+            SysMessage message = new SysMessage();
+            message.setMessageType("CREATE");
+            message.setMessageTitle("浠诲姟鍒涘缓鎴愬姛");
+            message.setMessageContent("鎮ㄥ垱寤虹殑浠诲姟宸叉垚鍔熸彁浜�");
+            message.setTaskId(event.getTaskId());
+            message.setTaskCode(event.getTaskCode());
+            message.setReceiverId(event.getCreatorId());
+            message.setReceiverName(creator.getNickName());
+            message.setSenderId(event.getCreatorId());
+            message.setSenderName("绯荤粺");
+            message.setIsRead("0");
+            message.setCreateTime(DateUtils.getNowDate());
+            message.setDelFlag("0");
+            
+            // 淇濆瓨娑堟伅
+            sysMessageMapper.insertSysMessage(message);
+            log.info("浠诲姟鍒涘缓娑堟伅宸蹭繚瀛橈紝娑堟伅ID锛歿}", message.getMessageId());
+            
+        } catch (Exception e) {
+            log.error("澶勭悊浠诲姟鍒涘缓浜嬩欢澶辫触", e);
+        }
+    }
+
+    /**
+     * 鐩戝惉浠诲姟鍒嗛厤浜嬩欢
+     * 
+     * @param event 浠诲姟鍒嗛厤浜嬩欢
+     */
+    @Async
+    @EventListener
+    public void handleTaskAssignedEvent(TaskAssignedEvent event) {
+        try {
+            log.info("鏀跺埌浠诲姟鍒嗛厤浜嬩欢锛屼换鍔D锛歿}锛屼换鍔$紪鍙凤細{}锛屾墽琛屼汉鏁伴噺锛歿}", 
+                    event.getTaskId(), event.getTaskCode(), 
+                    event.getAssigneeIds() != null ? event.getAssigneeIds().size() : 0);
+            
+            if (event.getAssigneeIds() == null || event.getAssigneeIds().isEmpty()) {
+                log.warn("鎵ц浜篒D鍒楄〃涓虹┖锛屾棤娉曟帹閫佹秷鎭�");
+                return;
+            }
+            
+            // 缁欐瘡涓墽琛屼汉鍙戦�佹秷鎭�
+            for (int i = 0; i < event.getAssigneeIds().size(); i++) {
+                Long assigneeId = event.getAssigneeIds().get(i);
+                
+                // 鑾峰彇鎵ц浜轰俊鎭�
+                SysUser assignee = sysUserMapper.selectUserById(assigneeId);
+                if (assignee == null) {
+                    log.warn("鎵句笉鍒版墽琛屼汉淇℃伅锛岀敤鎴稩D锛歿}", assigneeId);
+                    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");
+                
+                // 淇濆瓨娑堟伅
+                sysMessageMapper.insertSysMessage(message);
+                log.info("浠诲姟鍒嗛厤娑堟伅宸蹭繚瀛橈紝娑堟伅ID锛歿}锛屾帴鏀朵汉锛歿}", message.getMessageId(), assignee.getNickName());
+            }
+            
+        } catch (Exception e) {
+            log.error("澶勭悊浠诲姟鍒嗛厤浜嬩欢澶辫触", e);
+        }
+    }
+
+    /**
+     * 鐩戝惉浠诲姟鐘舵�佸彉鏇翠簨浠�
+     * 
+     * @param event 浠诲姟鐘舵�佸彉鏇翠簨浠�
+     */
+    @Async
+    @EventListener
+    public void handleTaskStatusChangedEvent(TaskStatusChangedEvent event) {
+        try {
+            log.info("鏀跺埌浠诲姟鐘舵�佸彉鏇翠簨浠讹紝浠诲姟ID锛歿}锛屾棫鐘舵�侊細{}锛屾柊鐘舵�侊細{}", 
+                    event.getTaskId(), event.getOldStatus(), event.getNewStatus());
+            
+            // 鏋勫缓鐘舵�佸彉鏇村唴瀹�
+            String statusContent = getStatusChangeContent(event.getNewStatus(), event.getNewStatusDesc());
+            
+            // 鏀堕泦鎵�鏈夐渶瑕侀�氱煡鐨勭敤鎴稩D锛堟墽琛屼汉+鍒涘缓浜猴紝鍘婚噸锛�
+            java.util.Set<Long> receiverIds = new java.util.HashSet<>();
+            
+            // 娣诲姞鎵ц浜�
+            if (event.getAssigneeIds() != null) {
+                receiverIds.addAll(event.getAssigneeIds());
+            }
+            
+            // 娣诲姞鍒涘缓浜猴紙濡傛灉涓嶆槸鎵ц浜猴級
+            if (event.getCreatorId() != null) {
+                receiverIds.add(event.getCreatorId());
+            }
+            
+            // 缁欐瘡涓敤鎴峰彂閫佹秷鎭�
+            for (Long receiverId : receiverIds) {
+                SysUser user = sysUserMapper.selectUserById(receiverId);
+                if (user == null) {
+                    log.warn("鎵句笉鍒扮敤鎴蜂俊鎭紝鐢ㄦ埛ID锛歿}", receiverId);
+                    continue;
+                }
+                
+                // 鍒涘缓娑堟伅
+                SysMessage message = new SysMessage();
+                message.setMessageType("STATUS");
+                message.setMessageTitle("浠诲姟鐘舵�佸彉鏇�");
+                message.setMessageContent(statusContent);
+                message.setTaskId(event.getTaskId());
+                message.setTaskCode(event.getTaskCode());
+                message.setReceiverId(receiverId);
+                message.setReceiverName(user.getNickName());
+                message.setSenderId(event.getCreatorId());
+                message.setSenderName("绯荤粺");
+                message.setIsRead("0");
+                message.setCreateTime(DateUtils.getNowDate());
+                message.setDelFlag("0");
+                
+                // 淇濆瓨娑堟伅
+                sysMessageMapper.insertSysMessage(message);
+                log.info("浠诲姟鐘舵�佸彉鏇存秷鎭凡淇濆瓨锛屾秷鎭疘D锛歿}锛屾柊鐘舵�侊細{}锛屾帴鏀朵汉锛歿}", 
+                        message.getMessageId(), event.getNewStatus(), user.getNickName());
+            }
+            
+        } catch (Exception e) {
+            log.error("澶勭悊浠诲姟鐘舵�佸彉鏇翠簨浠跺け璐�", e);
+        }
+    }
+
+    /**
+     * 鏍规嵁鐘舵�佽幏鍙栫姸鎬佸彉鏇村唴瀹�
+     * 
+     * @param status 浠诲姟鐘舵��
+     * @param statusDesc 鐘舵�佹弿杩�
+     * @return 鐘舵�佸彉鏇村唴瀹�
+     */
+    private String getStatusChangeContent(String status, String statusDesc) {
+        if (statusDesc != null && !statusDesc.isEmpty()) {
+            return "浠诲姟鐘舵�佸彉鏇翠负锛�" + statusDesc;
+        }
+        
+        switch (status) {
+            case "PENDING":
+                return "浠诲姟鐘舵�佸彉鏇翠负锛氬緟澶勭悊";
+            case "DEPARTING":
+            case "DEPARTED":
+                return "浠诲姟鐘舵�佸彉鏇翠负锛氬凡鍑哄彂";
+            case "ARRIVED":
+                return "浠诲姟鐘舵�佸彉鏇翠负锛氬凡鍒拌揪";
+            case "RETURNING":
+                return "浠诲姟鐘舵�佸彉鏇翠负锛氳繑绋嬩腑";
+            case "COMPLETED":
+                return "浠诲姟鐘舵�佸彉鏇翠负锛氬凡瀹屾垚";
+            case "CANCELLED":
+                return "浠诲姟鐘舵�佸彉鏇翠负锛氬凡鍙栨秷";
+            default:
+                return "浠诲姟鐘舵�佸凡鏇存柊";
+        }
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageMapper.java
new file mode 100644
index 0000000..f92c006
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMessageMapper.java
@@ -0,0 +1,94 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysMessage;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 绯荤粺娑堟伅Mapper鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-10-25
+ */
+public interface SysMessageMapper {
+    
+    /**
+     * 鏌ヨ绯荤粺娑堟伅
+     * 
+     * @param messageId 绯荤粺娑堟伅涓婚敭
+     * @return 绯荤粺娑堟伅
+     */
+    public SysMessage selectSysMessageByMessageId(Long messageId);
+
+    /**
+     * 鏌ヨ绯荤粺娑堟伅鍒楄〃
+     * 
+     * @param sysMessage 绯荤粺娑堟伅
+     * @return 绯荤粺娑堟伅闆嗗悎
+     */
+    public List<SysMessage> selectSysMessageList(SysMessage sysMessage);
+
+    /**
+     * 鏌ヨ鐢ㄦ埛鐨勬秷鎭垪琛�
+     * 
+     * @param receiverId 鎺ユ敹浜篒D
+     * @return 绯荤粺娑堟伅闆嗗悎
+     */
+    public List<SysMessage> selectSysMessageListByReceiverId(@Param("receiverId") Long receiverId);
+
+    /**
+     * 鏌ヨ鐢ㄦ埛鏈娑堟伅鏁伴噺
+     * 
+     * @param receiverId 鎺ユ敹浜篒D
+     * @return 鏈娑堟伅鏁伴噺
+     */
+    public int countUnreadMessageByReceiverId(@Param("receiverId") Long receiverId);
+
+    /**
+     * 鏂板绯荤粺娑堟伅
+     * 
+     * @param sysMessage 绯荤粺娑堟伅
+     * @return 缁撴灉
+     */
+    public int insertSysMessage(SysMessage sysMessage);
+
+    /**
+     * 淇敼绯荤粺娑堟伅
+     * 
+     * @param sysMessage 绯荤粺娑堟伅
+     * @return 缁撴灉
+     */
+    public int updateSysMessage(SysMessage sysMessage);
+
+    /**
+     * 鍒犻櫎绯荤粺娑堟伅
+     * 
+     * @param messageId 绯荤粺娑堟伅涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteSysMessageByMessageId(Long messageId);
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺娑堟伅
+     * 
+     * @param messageIds 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteSysMessageByMessageIds(Long[] messageIds);
+
+    /**
+     * 鏍囪娑堟伅涓哄凡璇�
+     * 
+     * @param messageId 娑堟伅ID
+     * @return 缁撴灉
+     */
+    public int markMessageAsRead(@Param("messageId") Long messageId);
+
+    /**
+     * 鏍囪鐢ㄦ埛鎵�鏈夋秷鎭负宸茶
+     * 
+     * @param receiverId 鎺ユ敹浜篒D
+     * @return 缁撴灉
+     */
+    public int markAllMessagesAsRead(@Param("receiverId") Long receiverId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageService.java
new file mode 100644
index 0000000..830fba7
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMessageService.java
@@ -0,0 +1,120 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysMessage;
+import com.ruoyi.system.domain.SysTask;
+
+/**
+ * 绯荤粺娑堟伅Service鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-10-25
+ */
+public interface ISysMessageService {
+    
+    /**
+     * 鏌ヨ绯荤粺娑堟伅
+     * 
+     * @param messageId 绯荤粺娑堟伅涓婚敭
+     * @return 绯荤粺娑堟伅
+     */
+    public SysMessage selectSysMessageByMessageId(Long messageId);
+
+    /**
+     * 鏌ヨ绯荤粺娑堟伅鍒楄〃
+     * 
+     * @param sysMessage 绯荤粺娑堟伅
+     * @return 绯荤粺娑堟伅闆嗗悎
+     */
+    public List<SysMessage> selectSysMessageList(SysMessage sysMessage);
+
+    /**
+     * 鏌ヨ鐢ㄦ埛鐨勬秷鎭垪琛�
+     * 
+     * @param receiverId 鎺ユ敹浜篒D
+     * @return 绯荤粺娑堟伅闆嗗悎
+     */
+    public List<SysMessage> selectSysMessageListByReceiverId(Long receiverId);
+
+    /**
+     * 鏌ヨ鐢ㄦ埛鏈娑堟伅鏁伴噺
+     * 
+     * @param receiverId 鎺ユ敹浜篒D
+     * @return 鏈娑堟伅鏁伴噺
+     */
+    public int countUnreadMessageByReceiverId(Long receiverId);
+
+    /**
+     * 鏂板绯荤粺娑堟伅
+     * 
+     * @param sysMessage 绯荤粺娑堟伅
+     * @return 缁撴灉
+     */
+    public int insertSysMessage(SysMessage sysMessage);
+
+    /**
+     * 淇敼绯荤粺娑堟伅
+     * 
+     * @param sysMessage 绯荤粺娑堟伅
+     * @return 缁撴灉
+     */
+    public int updateSysMessage(SysMessage sysMessage);
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺娑堟伅
+     * 
+     * @param messageIds 闇�瑕佸垹闄ょ殑绯荤粺娑堟伅涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteSysMessageByMessageIds(Long[] messageIds);
+
+    /**
+     * 鍒犻櫎绯荤粺娑堟伅淇℃伅
+     * 
+     * @param messageId 绯荤粺娑堟伅涓婚敭
+     * @return 缁撴灉
+     */
+    public int deleteSysMessageByMessageId(Long messageId);
+
+    /**
+     * 鏍囪娑堟伅涓哄凡璇�
+     * 
+     * @param messageId 娑堟伅ID
+     * @return 缁撴灉
+     */
+    public int markMessageAsRead(Long messageId);
+
+    /**
+     * 鏍囪鐢ㄦ埛鎵�鏈夋秷鎭负宸茶
+     * 
+     * @param receiverId 鎺ユ敹浜篒D
+     * @return 缁撴灉
+     */
+    public int markAllMessagesAsRead(Long receiverId);
+
+    // ========== 娑堟伅鎺ㄩ�佷笟鍔℃柟娉� ==========
+
+    /**
+     * 鎺ㄩ�佷换鍔″垱寤烘垚鍔熸秷鎭紙缁欏垱寤轰汉锛�
+     * 
+     * @param task 浠诲姟瀵硅薄
+     */
+    public void pushTaskCreateMessage(SysTask task);
+
+    /**
+     * 鎺ㄩ�佷换鍔″垎閰嶆秷鎭紙缁欐墽琛屼汉锛�
+     * 
+     * @param task 浠诲姟瀵硅薄
+     * @param assigneeIds 鎵ц浜篒D鍒楄〃
+     */
+    public void pushTaskAssignMessage(SysTask task, List<Long> assigneeIds);
+
+    /**
+     * 鎺ㄩ�佷换鍔$姸鎬佸彉鏇存秷鎭紙缁欑浉鍏充汉鍛橈級
+     * 
+     * @param task 浠诲姟瀵硅薄
+     * @param oldStatus 鏃х姸鎬�
+     * @param newStatus 鏂扮姸鎬�
+     */
+    public void pushTaskStatusChangeMessage(SysTask task, String oldStatus, String newStatus);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageServiceImpl.java
new file mode 100644
index 0000000..04ec5a7
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMessageServiceImpl.java
@@ -0,0 +1,351 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.Date;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.mapper.SysMessageMapper;
+import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.mapper.SysTaskAssigneeMapper;
+import com.ruoyi.system.domain.SysMessage;
+import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.SysTaskAssignee;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.system.service.ISysMessageService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 绯荤粺娑堟伅Service涓氬姟灞傚鐞�
+ * 
+ * @author ruoyi
+ * @date 2025-10-25
+ */
+@Service
+public class SysMessageServiceImpl implements ISysMessageService {
+    
+    private static final Logger log = LoggerFactory.getLogger(SysMessageServiceImpl.class);
+    
+    @Autowired
+    private SysMessageMapper sysMessageMapper;
+    
+    @Autowired
+    private SysUserMapper sysUserMapper;
+    
+    @Autowired
+    private SysTaskAssigneeMapper sysTaskAssigneeMapper;
+
+    /**
+     * 鏌ヨ绯荤粺娑堟伅
+     * 
+     * @param messageId 绯荤粺娑堟伅涓婚敭
+     * @return 绯荤粺娑堟伅
+     */
+    @Override
+    public SysMessage selectSysMessageByMessageId(Long messageId) {
+        return sysMessageMapper.selectSysMessageByMessageId(messageId);
+    }
+
+    /**
+     * 鏌ヨ绯荤粺娑堟伅鍒楄〃
+     * 
+     * @param sysMessage 绯荤粺娑堟伅
+     * @return 绯荤粺娑堟伅
+     */
+    @Override
+    public List<SysMessage> selectSysMessageList(SysMessage sysMessage) {
+        return sysMessageMapper.selectSysMessageList(sysMessage);
+    }
+
+    /**
+     * 鏌ヨ鐢ㄦ埛鐨勬秷鎭垪琛�
+     * 
+     * @param receiverId 鎺ユ敹浜篒D
+     * @return 绯荤粺娑堟伅闆嗗悎
+     */
+    @Override
+    public List<SysMessage> selectSysMessageListByReceiverId(Long receiverId) {
+        return sysMessageMapper.selectSysMessageListByReceiverId(receiverId);
+    }
+
+    /**
+     * 鏌ヨ鐢ㄦ埛鏈娑堟伅鏁伴噺
+     * 
+     * @param receiverId 鎺ユ敹浜篒D
+     * @return 鏈娑堟伅鏁伴噺
+     */
+    @Override
+    public int countUnreadMessageByReceiverId(Long receiverId) {
+        return sysMessageMapper.countUnreadMessageByReceiverId(receiverId);
+    }
+
+    /**
+     * 鏂板绯荤粺娑堟伅
+     * 
+     * @param sysMessage 绯荤粺娑堟伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertSysMessage(SysMessage sysMessage) {
+        if (sysMessage.getCreateTime() == null) {
+            sysMessage.setCreateTime(DateUtils.getNowDate());
+        }
+        if (sysMessage.getIsRead() == null) {
+            sysMessage.setIsRead("0");
+        }
+        if (sysMessage.getDelFlag() == null) {
+            sysMessage.setDelFlag("0");
+        }
+        return sysMessageMapper.insertSysMessage(sysMessage);
+    }
+
+    /**
+     * 淇敼绯荤粺娑堟伅
+     * 
+     * @param sysMessage 绯荤粺娑堟伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateSysMessage(SysMessage sysMessage) {
+        sysMessage.setUpdateTime(DateUtils.getNowDate());
+        return sysMessageMapper.updateSysMessage(sysMessage);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺娑堟伅
+     * 
+     * @param messageIds 闇�瑕佸垹闄ょ殑绯荤粺娑堟伅涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteSysMessageByMessageIds(Long[] messageIds) {
+        return sysMessageMapper.deleteSysMessageByMessageIds(messageIds);
+    }
+
+    /**
+     * 鍒犻櫎绯荤粺娑堟伅淇℃伅
+     * 
+     * @param messageId 绯荤粺娑堟伅涓婚敭
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteSysMessageByMessageId(Long messageId) {
+        return sysMessageMapper.deleteSysMessageByMessageId(messageId);
+    }
+
+    /**
+     * 鏍囪娑堟伅涓哄凡璇�
+     * 
+     * @param messageId 娑堟伅ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int markMessageAsRead(Long messageId) {
+        return sysMessageMapper.markMessageAsRead(messageId);
+    }
+
+    /**
+     * 鏍囪鐢ㄦ埛鎵�鏈夋秷鎭负宸茶
+     * 
+     * @param receiverId 鎺ユ敹浜篒D
+     * @return 缁撴灉
+     */
+    @Override
+    public int markAllMessagesAsRead(Long receiverId) {
+        return sysMessageMapper.markAllMessagesAsRead(receiverId);
+    }
+
+    // ========== 娑堟伅鎺ㄩ�佷笟鍔℃柟娉� ==========
+
+    /**
+     * 鎺ㄩ�佷换鍔″垱寤烘垚鍔熸秷鎭紙缁欏垱寤轰汉锛�
+     * 
+     * @param task 浠诲姟瀵硅薄
+     */
+    @Override
+    public void pushTaskCreateMessage(SysTask task) {
+        try {
+            if (task == null || task.getCreatorId() == null) {
+                log.warn("浠诲姟瀵硅薄鎴栧垱寤轰汉ID涓虹┖锛屾棤娉曟帹閫佸垱寤烘垚鍔熸秷鎭�");
+                return;
+            }
+            
+            // 鑾峰彇鍒涘缓浜轰俊鎭�
+            SysUser creator = sysUserMapper.selectUserById(task.getCreatorId());
+            if (creator == null) {
+                log.warn("鎵句笉鍒板垱寤轰汉淇℃伅锛岀敤鎴稩D锛歿}", task.getCreatorId());
+                return;
+            }
+            
+            SysMessage message = new SysMessage();
+            message.setMessageType("CREATE");
+            message.setMessageTitle("浠诲姟鍒涘缓鎴愬姛");
+            message.setMessageContent("鎮ㄥ垱寤虹殑浠诲姟宸叉垚鍔熸彁浜�");
+            message.setTaskId(task.getTaskId());
+            message.setTaskCode(task.getTaskCode());
+            message.setReceiverId(task.getCreatorId());
+            message.setReceiverName(creator.getNickName());
+            message.setSenderId(task.getCreatorId());
+            message.setSenderName("绯荤粺");
+            
+            insertSysMessage(message);
+            log.info("鎺ㄩ�佷换鍔″垱寤烘垚鍔熸秷鎭紝浠诲姟缂栧彿锛歿}锛屾帴鏀朵汉锛歿}", task.getTaskCode(), creator.getNickName());
+        } catch (Exception e) {
+            log.error("鎺ㄩ�佷换鍔″垱寤烘垚鍔熸秷鎭け璐�", e);
+        }
+    }
+
+    /**
+     * 鎺ㄩ�佷换鍔″垎閰嶆秷鎭紙缁欐墽琛屼汉锛�
+     * 
+     * @param task 浠诲姟瀵硅薄
+     * @param assigneeIds 鎵ц浜篒D鍒楄〃
+     */
+    @Override
+    public void pushTaskAssignMessage(SysTask task, List<Long> assigneeIds) {
+        try {
+            if (task == null || assigneeIds == null || assigneeIds.isEmpty()) {
+                log.warn("浠诲姟瀵硅薄鎴栨墽琛屼汉ID鍒楄〃涓虹┖锛屾棤娉曟帹閫佷换鍔″垎閰嶆秷鎭�");
+                return;
+            }
+            
+            // 鑾峰彇鍒涘缓浜轰俊鎭�
+            SysUser creator = null;
+            if (task.getCreatorId() != null) {
+                creator = sysUserMapper.selectUserById(task.getCreatorId());
+            }
+            
+            String senderName = (creator != null && StringUtils.isNotEmpty(creator.getNickName())) 
+                ? creator.getNickName() : "绯荤粺";
+            
+            // 缁欐瘡涓墽琛屼汉鍙戦�佹秷鎭�
+            for (Long assigneeId : assigneeIds) {
+                SysUser assignee = sysUserMapper.selectUserById(assigneeId);
+                if (assignee == null) {
+                    log.warn("鎵句笉鍒版墽琛屼汉淇℃伅锛岀敤鎴稩D锛歿}", assigneeId);
+                    continue;
+                }
+                
+                SysMessage message = new SysMessage();
+                message.setMessageType("PUSH");
+                message.setMessageTitle("浠诲姟鎺ㄩ��");
+                message.setMessageContent("鎮ㄦ湁鏂扮殑浠诲姟锛岃鍙婃椂澶勭悊");
+                message.setTaskId(task.getTaskId());
+                message.setTaskCode(task.getTaskCode());
+                message.setReceiverId(assigneeId);
+                message.setReceiverName(assignee.getNickName());
+                message.setSenderId(task.getCreatorId());
+                message.setSenderName(senderName);
+                
+                insertSysMessage(message);
+                log.info("鎺ㄩ�佷换鍔″垎閰嶆秷鎭紝浠诲姟缂栧彿锛歿}锛屾帴鏀朵汉锛歿}", task.getTaskCode(), assignee.getNickName());
+            }
+        } catch (Exception e) {
+            log.error("鎺ㄩ�佷换鍔″垎閰嶆秷鎭け璐�", e);
+        }
+    }
+
+    /**
+     * 鎺ㄩ�佷换鍔$姸鎬佸彉鏇存秷鎭紙缁欑浉鍏充汉鍛橈級
+     * 
+     * @param task 浠诲姟瀵硅薄
+     * @param oldStatus 鏃х姸鎬�
+     * @param newStatus 鏂扮姸鎬�
+     */
+    @Override
+    public void pushTaskStatusChangeMessage(SysTask task, String oldStatus, String newStatus) {
+        try {
+            if (task == null || StringUtils.isEmpty(newStatus)) {
+                log.warn("浠诲姟瀵硅薄鎴栨柊鐘舵�佷负绌猴紝鏃犳硶鎺ㄩ�佺姸鎬佸彉鏇存秷鎭�");
+                return;
+            }
+            
+            // 鏋勫缓鐘舵�佸彉鏇村唴瀹�
+            String statusContent = getStatusChangeContent(newStatus);
+            
+            // 鏌ヨ浠诲姟鐨勬墍鏈夋墽琛屼汉
+            List<SysTaskAssignee> assignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(task.getTaskId());
+            
+            if (assignees != null && !assignees.isEmpty()) {
+                // 缁欐瘡涓墽琛屼汉鍙戦�佹秷鎭�
+                for (SysTaskAssignee assignee : assignees) {
+                    SysUser user = sysUserMapper.selectUserById(assignee.getUserId());
+                    if (user == null) {
+                        log.warn("鎵句笉鍒版墽琛屼汉淇℃伅锛岀敤鎴稩D锛歿}", assignee.getUserId());
+                        continue;
+                    }
+                    
+                    SysMessage message = new SysMessage();
+                    message.setMessageType("STATUS");
+                    message.setMessageTitle("浠诲姟鐘舵�佸彉鏇�");
+                    message.setMessageContent(statusContent);
+                    message.setTaskId(task.getTaskId());
+                    message.setTaskCode(task.getTaskCode());
+                    message.setReceiverId(assignee.getUserId());
+                    message.setReceiverName(user.getNickName());
+                    message.setSenderId(task.getCreatorId());
+                    message.setSenderName("绯荤粺");
+                    
+                    insertSysMessage(message);
+                    log.info("鎺ㄩ�佷换鍔$姸鎬佸彉鏇存秷鎭紝浠诲姟缂栧彿锛歿}锛屾柊鐘舵�侊細{}锛屾帴鏀朵汉锛歿}", 
+                            task.getTaskCode(), newStatus, user.getNickName());
+                }
+            }
+            
+            // 鍚屾椂缁欏垱寤轰汉鍙戦�佹秷鎭紙濡傛灉鍒涘缓浜轰笉鏄墽琛屼汉锛�
+            if (task.getCreatorId() != null) {
+                boolean isCreatorAlsoAssignee = assignees != null && assignees.stream()
+                    .anyMatch(a -> a.getUserId().equals(task.getCreatorId()));
+                
+                if (!isCreatorAlsoAssignee) {
+                    SysUser creator = sysUserMapper.selectUserById(task.getCreatorId());
+                    if (creator != null) {
+                        SysMessage message = new SysMessage();
+                        message.setMessageType("STATUS");
+                        message.setMessageTitle("浠诲姟鐘舵�佸彉鏇�");
+                        message.setMessageContent(statusContent);
+                        message.setTaskId(task.getTaskId());
+                        message.setTaskCode(task.getTaskCode());
+                        message.setReceiverId(task.getCreatorId());
+                        message.setReceiverName(creator.getNickName());
+                        message.setSenderId(task.getCreatorId());
+                        message.setSenderName("绯荤粺");
+                        
+                        insertSysMessage(message);
+                        log.info("鎺ㄩ�佷换鍔$姸鎬佸彉鏇存秷鎭粰鍒涘缓浜猴紝浠诲姟缂栧彿锛歿}锛屾柊鐘舵�侊細{}锛屾帴鏀朵汉锛歿}", 
+                                task.getTaskCode(), newStatus, creator.getNickName());
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.error("鎺ㄩ�佷换鍔$姸鎬佸彉鏇存秷鎭け璐�", e);
+        }
+    }
+
+    /**
+     * 鏍规嵁鐘舵�佽幏鍙栫姸鎬佸彉鏇村唴瀹�
+     * 
+     * @param status 浠诲姟鐘舵��
+     * @return 鐘舵�佸彉鏇村唴瀹�
+     */
+    private String getStatusChangeContent(String status) {
+        switch (status) {
+            case "PENDING":
+                return "浠诲姟鐘舵�佸彉鏇翠负锛氬緟澶勭悊";
+            case "DEPARTED":
+                return "浠诲姟鐘舵�佸彉鏇翠负锛氬凡鍑哄彂";
+            case "ARRIVED":
+                return "浠诲姟鐘舵�佸彉鏇翠负锛氬凡鍒拌揪";
+            case "RETURNING":
+                return "浠诲姟鐘舵�佸彉鏇翠负锛氳繑绋嬩腑";
+            case "COMPLETED":
+                return "浠诲姟鐘舵�佸彉鏇翠负锛氬凡瀹屾垚";
+            case "CANCELLED":
+                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 499b06f..3293c6c 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
@@ -42,7 +42,11 @@
 import com.ruoyi.system.domain.VehicleInfo;
 import com.ruoyi.system.service.ISysTaskService;
 import com.ruoyi.system.service.ILegacySystemSyncService;
+import com.ruoyi.system.event.TaskCreatedEvent;
+import com.ruoyi.system.event.TaskAssignedEvent;
+import com.ruoyi.system.event.TaskStatusChangedEvent;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
 
 /**
  * 浠诲姟绠$悊Service涓氬姟灞傚鐞�
@@ -79,6 +83,9 @@
 
     @Autowired(required = false)
     private ILegacySystemSyncService legacySystemSyncService;
+    
+    @Autowired
+    private ApplicationEventPublisher eventPublisher;
 
     /**
      * 鏌ヨ浠诲姟绠$悊
@@ -229,6 +236,38 @@
                          "浠诲姟绫诲瀷锛�" + createVO.getTaskType(), SecurityUtils.getUserId(), SecurityUtils.getUsername());
         }
         
+        // 鍙戝竷浠诲姟鍒涘缓浜嬩欢
+        if (result > 0) {
+            eventPublisher.publishEvent(new TaskCreatedEvent(
+                this,
+                task.getTaskId(),
+                task.getTaskCode(),
+                task.getTaskType(),
+                task.getCreatorId(),
+                SecurityUtils.getUsername()
+            ));
+        }
+        
+        // 鍙戝竷浠诲姟鍒嗛厤浜嬩欢
+        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()
+            ));
+        }
+        
         // 寮傛鍚屾鎬ユ晳杞繍浠诲姟鍒版棫绯荤粺
         if (result > 0 && "EMERGENCY_TRANSFER".equals(createVO.getTaskType()) && legacySystemSyncService != null) {
             final Long finalTaskId = task.getTaskId();
@@ -320,19 +359,40 @@
     @Override
     @Transactional
     public int assignTask(Long taskId, Long assigneeId, String remark) {
-        SysTask task = new SysTask();
-        task.setTaskId(taskId);
-        task.setAssigneeId(assigneeId);
-        task.setUpdateBy(SecurityUtils.getUsername());
-        task.setUpdateTime(DateUtils.getNowDate());
+        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
+        if (task == null) {
+            throw new RuntimeException("浠诲姟涓嶅瓨鍦�");
+        }
         
-        int result = sysTaskMapper.assignTask(task);
+        SysTask updateTask = new SysTask();
+        updateTask.setTaskId(taskId);
+        updateTask.setAssigneeId(assigneeId);
+        updateTask.setUpdateBy(SecurityUtils.getUsername());
+        updateTask.setUpdateTime(DateUtils.getNowDate());
+        
+        int result = sysTaskMapper.assignTask(updateTask);
         
         // 璁板綍鎿嶄綔鏃ュ織
         if (result > 0) {
             recordTaskLog(taskId, "ASSIGN", "鍒嗛厤浠诲姟", null, 
                          "鍒嗛厤缁欑敤鎴稩D锛�" + assigneeId + "锛屽娉細" + remark, 
                          SecurityUtils.getUserId(), SecurityUtils.getUsername());
+        }
+        
+        // 鍙戝竷浠诲姟鍒嗛厤浜嬩欢
+        if (result > 0) {
+            List<Long> assigneeIds = new ArrayList<>();
+            assigneeIds.add(assigneeId);
+            
+            eventPublisher.publishEvent(new TaskAssignedEvent(
+                this,
+                task.getTaskId(),
+                task.getTaskCode(),
+                assigneeIds,
+                null, // 濮撳悕鍒楄〃鍦ㄧ洃鍚櫒涓煡璇�
+                SecurityUtils.getUserId(),
+                SecurityUtils.getUsername()
+            ));
         }
         
         return result;
@@ -404,6 +464,30 @@
                          locationLog);
         }
         
+        // 鍙戝竷浠诲姟鐘舵�佸彉鏇翠簨浠�
+        if (result > 0) {
+            // 鏌ヨ浠诲姟鐨勬墍鏈夋墽琛屼汉
+            List<SysTaskAssignee> assignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
+            List<Long> assigneeIds = null;
+            if (assignees != null && !assignees.isEmpty()) {
+                assigneeIds = assignees.stream()
+                    .map(SysTaskAssignee::getUserId)
+                    .collect(Collectors.toList());
+            }
+            
+            eventPublisher.publishEvent(new TaskStatusChangedEvent(
+                this,
+                oldTask.getTaskId(),
+                oldTask.getTaskCode(),
+                oldTaskStatus.getCode(),
+                newStatus.getCode(),
+                oldTaskStatus.getInfo(),
+                newStatus.getInfo(),
+                assigneeIds,
+                oldTask.getCreatorId()
+            ));
+        }
+        
         return result;
     }
 
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysMessageMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMessageMapper.xml
new file mode 100644
index 0000000..d463d1a
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysMessageMapper.xml
@@ -0,0 +1,137 @@
+<?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.SysMessageMapper">
+    
+    <resultMap type="SysMessage" id="SysMessageResult">
+        <result property="messageId"    column="message_id"    />
+        <result property="messageType"    column="message_type"    />
+        <result property="messageTitle"    column="message_title"    />
+        <result property="messageContent"    column="message_content"    />
+        <result property="taskId"    column="task_id"    />
+        <result property="taskCode"    column="task_code"    />
+        <result property="receiverId"    column="receiver_id"    />
+        <result property="receiverName"    column="receiver_name"    />
+        <result property="senderId"    column="sender_id"    />
+        <result property="senderName"    column="sender_name"    />
+        <result property="isRead"    column="is_read"    />
+        <result property="readTime"    column="read_time"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="delFlag"    column="del_flag"    />
+    </resultMap>
+
+    <sql id="selectSysMessageVo">
+        select message_id, message_type, message_title, message_content, task_id, task_code, 
+               receiver_id, receiver_name, sender_id, sender_name, is_read, read_time, 
+               create_time, update_time, del_flag
+        from sys_message
+    </sql>
+
+    <select id="selectSysMessageList" parameterType="SysMessage" resultMap="SysMessageResult">
+        <include refid="selectSysMessageVo"/>
+        <where>
+            del_flag = '0'
+            <if test="messageType != null  and messageType != ''"> and message_type = #{messageType}</if>
+            <if test="receiverId != null "> and receiver_id = #{receiverId}</if>
+            <if test="taskId != null "> and task_id = #{taskId}</if>
+            <if test="isRead != null  and isRead != ''"> and is_read = #{isRead}</if>
+        </where>
+        order by is_read asc, create_time desc
+    </select>
+    
+    <select id="selectSysMessageByMessageId" parameterType="Long" resultMap="SysMessageResult">
+        <include refid="selectSysMessageVo"/>
+        where message_id = #{messageId} and del_flag = '0'
+    </select>
+
+    <select id="selectSysMessageListByReceiverId" parameterType="Long" resultMap="SysMessageResult">
+        <include refid="selectSysMessageVo"/>
+        where receiver_id = #{receiverId} and del_flag = '0'
+        order by is_read asc, create_time desc
+    </select>
+
+    <select id="countUnreadMessageByReceiverId" parameterType="Long" resultType="int">
+        select count(*) from sys_message 
+        where receiver_id = #{receiverId} and is_read = '0' and del_flag = '0'
+    </select>
+
+    <insert id="insertSysMessage" parameterType="SysMessage" useGeneratedKeys="true" keyProperty="messageId">
+        insert into sys_message
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="messageType != null and messageType != ''">message_type,</if>
+            <if test="messageTitle != null and messageTitle != ''">message_title,</if>
+            <if test="messageContent != null and messageContent != ''">message_content,</if>
+            <if test="taskId != null">task_id,</if>
+            <if test="taskCode != null and taskCode != ''">task_code,</if>
+            <if test="receiverId != null">receiver_id,</if>
+            <if test="receiverName != null and receiverName != ''">receiver_name,</if>
+            <if test="senderId != null">sender_id,</if>
+            <if test="senderName != null and senderName != ''">sender_name,</if>
+            <if test="isRead != null">is_read,</if>
+            <if test="readTime != null">read_time,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="delFlag != null">del_flag,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="messageType != null and messageType != ''">#{messageType},</if>
+            <if test="messageTitle != null and messageTitle != ''">#{messageTitle},</if>
+            <if test="messageContent != null and messageContent != ''">#{messageContent},</if>
+            <if test="taskId != null">#{taskId},</if>
+            <if test="taskCode != null and taskCode != ''">#{taskCode},</if>
+            <if test="receiverId != null">#{receiverId},</if>
+            <if test="receiverName != null and receiverName != ''">#{receiverName},</if>
+            <if test="senderId != null">#{senderId},</if>
+            <if test="senderName != null and senderName != ''">#{senderName},</if>
+            <if test="isRead != null">#{isRead},</if>
+            <if test="readTime != null">#{readTime},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="delFlag != null">#{delFlag},</if>
+        </trim>
+    </insert>
+
+    <update id="updateSysMessage" parameterType="SysMessage">
+        update sys_message
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="messageType != null and messageType != ''">message_type = #{messageType},</if>
+            <if test="messageTitle != null and messageTitle != ''">message_title = #{messageTitle},</if>
+            <if test="messageContent != null and messageContent != ''">message_content = #{messageContent},</if>
+            <if test="taskId != null">task_id = #{taskId},</if>
+            <if test="taskCode != null and taskCode != ''">task_code = #{taskCode},</if>
+            <if test="receiverId != null">receiver_id = #{receiverId},</if>
+            <if test="receiverName != null and receiverName != ''">receiver_name = #{receiverName},</if>
+            <if test="senderId != null">sender_id = #{senderId},</if>
+            <if test="senderName != null and senderName != ''">sender_name = #{senderName},</if>
+            <if test="isRead != null">is_read = #{isRead},</if>
+            <if test="readTime != null">read_time = #{readTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="delFlag != null">del_flag = #{delFlag},</if>
+        </trim>
+        where message_id = #{messageId}
+    </update>
+
+    <delete id="deleteSysMessageByMessageId" parameterType="Long">
+        update sys_message set del_flag = '1' where message_id = #{messageId}
+    </delete>
+
+    <delete id="deleteSysMessageByMessageIds" parameterType="Long">
+        update sys_message set del_flag = '1' where message_id in
+        <foreach item="messageId" collection="array" open="(" separator="," close=")">
+            #{messageId}
+        </foreach>
+    </delete>
+
+    <update id="markMessageAsRead" parameterType="Long">
+        update sys_message 
+        set is_read = '1', read_time = now()
+        where message_id = #{messageId} and del_flag = '0'
+    </update>
+
+    <update id="markAllMessagesAsRead" parameterType="Long">
+        update sys_message 
+        set is_read = '1', read_time = now()
+        where receiver_id = #{receiverId} and is_read = '0' and del_flag = '0'
+    </update>
+
+</mapper>
diff --git a/sql/sys_message.sql b/sql/sys_message.sql
new file mode 100644
index 0000000..d98bbc1
--- /dev/null
+++ b/sql/sys_message.sql
@@ -0,0 +1,26 @@
+-- ----------------------------
+-- 绯荤粺娑堟伅琛�
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_message`;
+CREATE TABLE `sys_message` (
+  `message_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '娑堟伅ID',
+  `message_type` varchar(20) NOT NULL COMMENT '娑堟伅绫诲瀷锛欳REATE-鍒涘缓鎴愬姛,PUSH-浠诲姟鎺ㄩ��,STATUS-鐘舵�佸彉鏇�,ASSIGN-鍒嗛厤浠诲姟',
+  `message_title` varchar(100) NOT NULL COMMENT '娑堟伅鏍囬',
+  `message_content` varchar(500) NOT NULL COMMENT '娑堟伅鍐呭',
+  `task_id` bigint(20) DEFAULT NULL COMMENT '鍏宠仈浠诲姟ID',
+  `task_code` varchar(50) DEFAULT NULL COMMENT '浠诲姟缂栧彿',
+  `receiver_id` bigint(20) NOT NULL COMMENT '鎺ユ敹浜篒D',
+  `receiver_name` varchar(50) DEFAULT NULL COMMENT '鎺ユ敹浜哄鍚�',
+  `sender_id` bigint(20) DEFAULT NULL COMMENT '鍙戦�佷汉ID',
+  `sender_name` varchar(50) DEFAULT NULL COMMENT '鍙戦�佷汉濮撳悕',
+  `is_read` char(1) DEFAULT '0' COMMENT '鏄惁宸茶锛�0-鏈,1-宸茶',
+  `read_time` datetime DEFAULT NULL COMMENT '璇诲彇鏃堕棿',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+  `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿',
+  `del_flag` char(1) DEFAULT '0' COMMENT '鍒犻櫎鏍囧織锛�0-姝e父,1-鍒犻櫎',
+  PRIMARY KEY (`message_id`),
+  KEY `idx_receiver_id` (`receiver_id`),
+  KEY `idx_task_id` (`task_id`),
+  KEY `idx_create_time` (`create_time`),
+  KEY `idx_is_read` (`is_read`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='绯荤粺娑堟伅琛�';

--
Gitblit v1.9.1