From 1f963e2344833ff02087c05411b112147492bd00 Mon Sep 17 00:00:00 2001
From: 啊鑫 <t2856754968@163.com>
Date: 星期六, 21 六月 2025 22:18:59 +0800
Subject: [PATCH] 添加钉钉推送消息功能

---
 PROJECT_SUMMARY.md                                                 |  233 ++++++++
 src/main/java/com/gs/xky/dto/DingTalkMessage.java                  |   21 
 src/main/java/com/gs/xky/mapper/DingtalkMsgMapper.java             |   18 
 src/main/resources/mapper/DingtalkInfoMapper.xml                   |    7 
 src/main/java/com/gs/xky/entity/DingtalkInfo.java                  |   39 +
 src/main/java/com/gs/xky/config/ResultMessage.java                 |   35 +
 src/main/java/com/gs/xky/entity/DingtalkMsg.java                   |   46 +
 src/main/java/com/gs/xky/service/DingtalkInfoService.java          |   14 
 src/main/java/com/gs/xky/controller/DingtalkController.java        |   61 ++
 src/main/resources/mapper/DingtalkMsgMapper.xml                    |   21 
 pom.xml                                                            |   12 
 src/test/java/com/gs/xky/XkyApplicationTests.java                  |    9 
 README.md                                                          |  204 +++++++
 src/main/java/com/gs/xky/dto/Result.java                           |   17 
 src/main/java/com/gs/xky/config/DataAcquisitionConfiguration.java  |   20 
 src/main/java/com/gs/xky/service/SimpleExample.java                |  239 +++++++++
 src/main/java/com/gs/xky/dto/DingTalkResponse.java                 |   23 
 API_DOCUMENTATION.md                                               |  204 +++++++
 src/main/java/com/gs/xky/service/Impl/DingtalkInfoServiceImpl.java |  155 +++++
 src/test/java/com/gs/xky/controller/DingtalkControllerTest.java    |  108 ++++
 src/main/java/com/gs/xky/mapper/DingtalkInfoMapper.java            |   18 
 src/main/java/com/gs/xky/dto/NumbericalDto.java                    |   14 
 22 files changed, 1,514 insertions(+), 4 deletions(-)

diff --git a/API_DOCUMENTATION.md b/API_DOCUMENTATION.md
new file mode 100644
index 0000000..4de446d
--- /dev/null
+++ b/API_DOCUMENTATION.md
@@ -0,0 +1,204 @@
+# 閽夐拤娑堟伅鍙戦�丄PI鏂囨。
+
+## 姒傝堪
+
+鏈枃妗f弿杩颁簡閲囪喘璁㈠崟绠$悊绯荤粺涓拤閽夋秷鎭彂閫佸姛鑳界殑REST API鎺ュ彛銆�
+
+## 鍩虹淇℃伅
+
+- **鍩虹URL**: `http://localhost:9095`
+- **API鐗堟湰**: v1.0
+- **鏁版嵁鏍煎紡**: JSON
+- **瀛楃缂栫爜**: UTF-8
+
+## 鎺ュ彛鍒楄〃
+
+### 1. 鍙戦�侀拤閽夋秷鎭�
+
+#### 鎺ュ彛淇℃伅
+
+- **鎺ュ彛鍚嶇О**: 鍙戦�侀拤閽夋秷鎭�
+- **璇锋眰鏂规硶**: POST
+- **鎺ュ彛璺緞**: `/api/dingtalk/sendMessage`
+- **鍔熻兘鎻忚堪**: 鏍规嵁妫�楠屽崟鍙峰彂閫佷笉鍚堟牸妫�楠屽崟鐨勯拤閽夐�氱煡娑堟伅
+
+#### 璇锋眰鍙傛暟
+
+**璇锋眰澶�**:
+
+```
+Content-Type: application/json
+```
+
+**璇锋眰浣�**:
+
+```json
+{
+  "releaseNo": "IQC202501270001"
+}
+```
+
+**鍙傛暟璇存槑**:
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|--------|------|------|------|
+| releaseNo | String | 鏄� | 妫�楠屽崟鍙凤紝鐢ㄤ簬鏌ヨ瀵瑰簲鐨勯拤閽夋秷鎭唴瀹� |
+
+#### 鍝嶅簲缁撴灉
+
+**鎴愬姛鍝嶅簲** (HTTP 200):
+
+```json
+{
+  "code": 200,
+  "message": null,
+  "successful": 0,
+  "data": "鎺ユ敹鎴愬姛"
+}
+```
+
+**澶辫触鍝嶅簲** (HTTP 200):
+
+```json
+{
+  "code": 500,
+  "message": "閿欒淇℃伅",
+  "successful": 1,
+  "data": "鎺ユ敹澶辫触"
+}
+```
+
+**鍝嶅簲瀛楁璇存槑**:
+| 瀛楁鍚� | 绫诲瀷 | 璇存槑 |
+|--------|------|------|
+| code | Integer | 鍝嶅簲鐘舵�佺爜锛�200琛ㄧず鎴愬姛锛�500琛ㄧず澶辫触 |
+| message | String | 閿欒淇℃伅锛屾垚鍔熸椂涓簄ull |
+| successful | Integer | 鎴愬姛鏍囪瘑锛�0琛ㄧず鎴愬姛锛�1琛ㄧず澶辫触 |
+| data | String | 鍝嶅簲鏁版嵁锛屾垚鍔熸椂涓�"鎺ユ敹鎴愬姛"锛屽け璐ユ椂涓�"鎺ユ敹澶辫触" |
+
+#### 閿欒鐮佽鏄�
+
+| 閿欒鐮� | 璇存槑   |
+|-----|------|
+| 200 | 璇锋眰鎴愬姛 |
+| 500 | 璇锋眰澶辫触 |
+
+#### 浣跨敤绀轰緥
+
+**cURL绀轰緥**:
+
+```bash
+curl -X POST http://localhost:9095/api/dingtalk/sendMessage \
+  -H "Content-Type: application/json" \
+  -d '{"releaseNo": "IQC202501270001"}'
+```
+
+**JavaScript绀轰緥**:
+
+```javascript
+fetch('http://localhost:9095/api/dingtalk/sendMessage', {
+  method: 'POST',
+  headers: {
+    'Content-Type': 'application/json'
+  },
+  body: JSON.stringify({
+    releaseNo: 'IQC202501270001'
+  })
+})
+.then(response => response.json())
+.then(data => {
+  if (data.code === 200) {
+    console.log('娑堟伅鍙戦�佹垚鍔�');
+  } else {
+    console.log('娑堟伅鍙戦�佸け璐�:', data.message);
+  }
+})
+.catch(error => {
+  console.error('璇锋眰澶辫触:', error);
+});
+```
+
+**Java绀轰緥**:
+
+```java
+import com.fasterxml.jackson.databind.ObjectMapper;
+import okhttp3.*;
+
+public class DingtalkApiClient {
+    private static final String BASE_URL = "http://localhost:9095";
+    private static final OkHttpClient client = new OkHttpClient();
+    private static final ObjectMapper objectMapper = new ObjectMapper();
+
+    public static void sendMessage(String releaseNo) throws Exception {
+        // 鏋勫缓璇锋眰浣�
+        String requestBody = objectMapper.writeValueAsString(
+                Map.of("releaseNo", releaseNo)
+        );
+
+        // 鍒涘缓璇锋眰
+        Request request = new Request.Builder()
+                .url(BASE_URL + "/api/dingtalk/sendMessage")
+                .post(RequestBody.create(
+                        MediaType.parse("application/json"),
+                        requestBody
+                ))
+                .build();
+
+        // 鍙戦�佽姹�
+        try (Response response = client.newCall(request).execute()) {
+            String responseBody = response.body().string();
+            System.out.println("鍝嶅簲: " + responseBody);
+        }
+    }
+}
+```
+
+#### 甯歌閿欒鍙婅В鍐虫柟妗�
+
+1. **妫�楠屽崟鍙蜂负绌�**
+    - 閿欒淇℃伅: "妫�楠屽崟鍙蜂笉鑳戒负绌�"
+    - 瑙e喅鏂规: 纭繚浼犲叆鐨剅eleaseNo鍙傛暟涓嶄负null涓斾笉涓虹┖瀛楃涓�
+
+2. **鏁版嵁涓嶅瓨鍦�**
+    - 閿欒淇℃伅: "閽夐拤娑堟伅鍙戦�佸け璐�"
+    - 瑙e喅鏂规: 纭繚妫�楠屽崟鍙峰湪`DINGTALK_MSG`琛ㄤ腑鏈夊搴旂殑璁板綍
+
+3. **閽夐拤API璋冪敤澶辫触**
+    - 閿欒淇℃伅: "閽夐拤娑堟伅鍙戦�佸け璐�"
+    - 瑙e喅鏂规: 妫�鏌ラ拤閽夊簲鐢ㄩ厤缃槸鍚︽纭紝纭繚鏈夊彂閫佹潈闄�
+
+4. **绯荤粺寮傚父**
+    - 閿欒淇℃伅: 鍏蜂綋鐨勫紓甯镐俊鎭�
+    - 瑙e喅鏂规: 妫�鏌ョ郴缁熸棩蹇楋紝鑱旂郴鎶�鏈敮鎸�
+
+#### 娉ㄦ剰浜嬮」
+
+1. **鏁版嵁鍑嗗**: 纭繚妫�楠屽崟鍙峰湪`DINGTALK_MSG`琛ㄤ腑鏈夊搴旂殑璁板綍
+2. **鏉冮檺閰嶇疆**: 纭繚閽夐拤搴旂敤閰嶇疆姝g‘涓旀湁鍙戦�佸伐浣滈�氱煡鐨勬潈闄�
+3. **璋冪敤棰戠巼**: 寤鸿鎺ュ彛璋冪敤棰戠巼涓嶈秴杩囨瘡鍒嗛挓1娆★紝閬垮厤瑙﹀彂閽夐拤API闄愬埗
+4. **鐢ㄦ埛閰嶇疆**: 纭繚鎺ユ敹娑堟伅鐨勭敤鎴峰湪`DINGTALK_INFO`琛ㄤ腑閰嶇疆姝g‘
+5. **缃戠粶鐜**: 纭繚鏈嶅姟鍣ㄨ兘澶熸甯歌闂拤閽夊紑鏀続PI
+
+#### 娑堟伅鏍煎紡
+
+鍙戦�佺殑閽夐拤娑堟伅鏍煎紡濡備笅锛�
+
+```
+渚涘簲鍟哰xxx] 鏉ユ枡鏃ユ湡[yyyy-MM-dd] 椤圭洰[xxx] 鏂欏彿[xxx]鐨勪笉鍚堟牸妫�楠屽崟琚玔xxx]瀹℃壒涓篬xxx]锛岃鏌ユ敹!
+```
+
+#### 鏁版嵁搴撲緷璧�
+
+璇ユ帴鍙d緷璧栦互涓嬫暟鎹簱琛細
+
+- `DINGTALK_MSG`: 瀛樺偍閽夐拤娑堟伅鍐呭
+- `DINGTALK_INFO`: 瀛樺偍閽夐拤鐢ㄦ埛淇℃伅
+
+#### 鐗堟湰鍘嗗彶
+
+| 鐗堟湰   | 鏃ユ湡         | 鏇存柊鍐呭               |
+|------|------------|--------------------|
+| v1.0 | 2025-01-27 | 鍒濆鐗堟湰锛屾敮鎸佸熀鏈殑閽夐拤娑堟伅鍙戦�佸姛鑳� |
+
+## 鑱旂郴鏀寔
+
+濡傛湁闂鎴栧缓璁紝璇疯仈绯绘妧鏈敮鎸佸洟闃熴�� 
\ No newline at end of file
diff --git a/PROJECT_SUMMARY.md b/PROJECT_SUMMARY.md
new file mode 100644
index 0000000..ad22052
--- /dev/null
+++ b/PROJECT_SUMMARY.md
@@ -0,0 +1,233 @@
+# 椤圭洰瀹屾垚鎬荤粨
+
+## 椤圭洰姒傝堪
+
+鏈浠诲姟鏄负閲囪喘璁㈠崟绠$悊绯荤粺鍒涘缓涓�涓猂EST API鎺ュ彛锛岀敤浜庡彂閫侀拤閽夋秷鎭�氱煡銆傛帴鍙d娇鐢╜NumbericalDto`浣滀负璇锋眰鍙傛暟锛�
+`ResultMessage`浣滀负鍝嶅簲缁撴灉銆�
+
+## 瀹屾垚鐨勫伐浣�
+
+### 1. 鍒涘缓Controller鎺ュ彛
+
+**鏂囦欢浣嶇疆**: `src/main/java/com/gs/xky/controller/DingtalkController.java`
+
+**涓昏鍔熻兘**:
+
+- 鎻愪緵POST鎺ュ彛 `/api/dingtalk/sendMessage`
+- 鎺ユ敹`NumbericalDto`鍙傛暟锛屽寘鍚楠屽崟鍙�
+- 杩斿洖`ResultMessage`鍝嶅簲缁撴灉
+- 鍖呭惈瀹屾暣鐨勫弬鏁版牎楠屽拰寮傚父澶勭悊
+- 璇︾粏鐨勬棩蹇楄褰�
+
+**鎺ュ彛鐗规��**:
+
+- RESTful璁捐椋庢牸
+- 缁熶竴鐨勯敊璇鐞嗘満鍒�
+- 瀹屾暣鐨勫弬鏁伴獙璇�
+- 璇︾粏鐨勬棩蹇楄褰�
+
+### 2. 鍒涘缓娴嬭瘯绫�
+
+**鏂囦欢浣嶇疆**: `src/test/java/com/gs/xky/controller/DingtalkControllerTest.java`
+
+**娴嬭瘯瑕嗙洊**:
+
+- 鎴愬姛鍦烘櫙娴嬭瘯
+- 澶辫触鍦烘櫙娴嬭瘯
+- 鍙傛暟涓虹┖娴嬭瘯
+- 鍙傛暟涓簄ull娴嬭瘯
+
+### 3. 鏇存柊椤圭洰鏂囨。
+
+**鏇存柊鐨勬枃浠�**:
+
+- `README.md`: 娣诲姞浜哛EST API鎺ュ彛璇存槑
+- `API_DOCUMENTATION.md`: 鍒涘缓浜嗚缁嗙殑API鏂囨。
+
+**鏂囨。鍐呭**:
+
+- 鎺ュ彛浣跨敤璇存槑
+- 璇锋眰/鍝嶅簲鏍煎紡
+- 閿欒澶勭悊璇存槑
+- 浣跨敤绀轰緥
+- 娉ㄦ剰浜嬮」
+
+### 4. 鍒涘缓杈呭姪鑴氭湰
+
+**鍒涘缓鐨勬枃浠�**:
+
+- `start_api.bat`: API鏈嶅姟鍚姩鑴氭湰
+- `test_api.bat`: API鎺ュ彛娴嬭瘯鑴氭湰
+
+## 椤圭洰缁撴瀯
+
+```
+src/
+鈹溾攢鈹� main/
+鈹�   鈹斺攢鈹� java/
+鈹�       鈹斺攢鈹� com/
+鈹�           鈹斺攢鈹� gs/
+鈹�               鈹斺攢鈹� xky/
+鈹�                   鈹溾攢鈹� controller/
+鈹�                   鈹�   鈹斺攢鈹� DingtalkController.java          # 鏂板垱寤虹殑Controller
+鈹�                   鈹溾攢鈹� service/
+鈹�                   鈹�   鈹溾攢鈹� DingtalkInfoService.java         # 鏈嶅姟鎺ュ彛
+鈹�                   鈹�   鈹斺攢鈹� Impl/
+鈹�                   鈹�       鈹斺攢鈹� DingtalkInfoServiceImpl.java # 鏈嶅姟瀹炵幇
+鈹�                   鈹溾攢鈹� dto/
+鈹�                   鈹�   鈹斺攢鈹� NumbericalDto.java               # 璇锋眰鍙傛暟DTO
+鈹�                   鈹斺攢鈹� config/
+鈹�                       鈹斺攢鈹� ResultMessage.java               # 鍝嶅簲缁撴灉绫�
+鈹溾攢鈹� test/
+鈹�   鈹斺攢鈹� java/
+鈹�       鈹斺攢鈹� com/
+鈹�           鈹斺攢鈹� gs/
+鈹�               鈹斺攢鈹� xky/
+鈹�                   鈹斺攢鈹� controller/
+鈹�                       鈹斺攢鈹� DingtalkControllerTest.java      # 鏂板垱寤虹殑娴嬭瘯绫�
+鈹斺攢鈹� resources/
+    鈹斺攢鈹� mapper/
+        鈹斺攢鈹� DingtalkMsgMapper.xml                            # 鏁版嵁璁块棶灞�
+
+鏂囨。鏂囦欢:
+鈹溾攢鈹� README.md                    # 椤圭洰涓绘枃妗o紙宸叉洿鏂帮級
+鈹溾攢鈹� API_DOCUMENTATION.md         # API璇︾粏鏂囨。锛堟柊鍒涘缓锛�
+鈹溾攢鈹� PROJECT_SUMMARY.md           # 椤圭洰鎬荤粨锛堟湰鏂囦欢锛�
+鈹溾攢鈹� start_api.bat               # 鍚姩鑴氭湰锛堟柊鍒涘缓锛�
+鈹斺攢鈹� test_api.bat                # 娴嬭瘯鑴氭湰锛堟柊鍒涘缓锛�
+```
+
+## 鎺ュ彛璇︽儏
+
+### 璇锋眰淇℃伅
+
+- **URL**: `POST /api/dingtalk/sendMessage`
+- **Content-Type**: `application/json`
+- **鍙傛暟**: `NumbericalDto` (鍖呭惈releaseNo瀛楁)
+
+### 鍝嶅簲淇℃伅
+
+- **鏍煎紡**: `ResultMessage`
+- **瀛楁**:
+    - `code`: 鐘舵�佺爜 (200鎴愬姛, 500澶辫触)
+    - `message`: 閿欒淇℃伅
+    - `successful`: 鎴愬姛鏍囪瘑 (0鎴愬姛, 1澶辫触)
+    - `data`: 鍝嶅簲鏁版嵁
+
+### 浣跨敤绀轰緥
+
+**璇锋眰**:
+
+```bash
+curl -X POST http://localhost:9095/api/dingtalk/sendMessage \
+  -H "Content-Type: application/json" \
+  -d '{"releaseNo": "IQC202501270001"}'
+```
+
+**鎴愬姛鍝嶅簲**:
+
+```json
+{
+  "code": 200,
+  "message": null,
+  "successful": 0,
+  "data": "鎺ユ敹鎴愬姛"
+}
+```
+
+**澶辫触鍝嶅簲**:
+
+```json
+{
+  "code": 500,
+  "message": "妫�楠屽崟鍙蜂笉鑳戒负绌�",
+  "successful": 1,
+  "data": "鎺ユ敹澶辫触"
+}
+```
+
+## 鎶�鏈壒鐐�
+
+### 1. 浠g爜璐ㄩ噺
+
+- 閬靛惊SOLID鍘熷垯
+- 浣跨敤璁捐妯″紡锛堜緷璧栨敞鍏ャ�佹ā鏉挎柟娉曪級
+- 瀹屾暣鐨勫紓甯稿鐞嗘満鍒�
+- 璇︾粏鐨勬棩蹇楄褰�
+
+### 2. 瀹夊叏鎬�
+
+- 鍙傛暟楠岃瘉
+- 寮傚父鎹曡幏
+- 閿欒淇℃伅澶勭悊
+
+### 3. 鍙淮鎶ゆ��
+
+- 娓呮櫚鐨勪唬鐮佺粨鏋�
+- 瀹屾暣鐨勬枃妗h鏄�
+- 鍗曞厓娴嬭瘯瑕嗙洊
+- 璇︾粏鐨勬敞閲�
+
+### 4. 鐢ㄦ埛浣撻獙
+
+- 缁熶竴鐨勫搷搴旀牸寮�
+- 娓呮櫚鐨勯敊璇俊鎭�
+- 璇︾粏鐨勪娇鐢ㄦ枃妗�
+- 渚挎嵎鐨勬祴璇曡剼鏈�
+
+## 閮ㄧ讲璇存槑
+
+### 鐜瑕佹眰
+
+- Java 8+
+- Oracle鏁版嵁搴�
+- 閽夐拤搴旂敤閰嶇疆
+
+### 鍚姩姝ラ
+
+1. 纭繚鏁版嵁搴撹繛鎺ユ甯�
+2. 纭繚閽夐拤搴旂敤閰嶇疆姝g‘
+3. 杩愯 `start_api.bat` 鍚姩鏈嶅姟
+4. 浣跨敤 `test_api.bat` 娴嬭瘯鎺ュ彛
+
+### 閰嶇疆璇存槑
+
+- 鏈嶅姟绔彛: 9095
+- 鏁版嵁搴撻厤缃�: `application.yml`
+- 閽夐拤閰嶇疆: `DataAcquisitionConfiguration.java`
+
+## 鍚庣画寤鸿
+
+### 1. 鍔熻兘鎵╁睍
+
+- 娣诲姞鎺ュ彛璁块棶鏉冮檺鎺у埗
+- 鏀寔鎵归噺鍙戦�佹秷鎭�
+- 娣诲姞娑堟伅鍙戦�佸巻鍙茶褰�
+- 鏀寔娑堟伅妯℃澘閰嶇疆
+
+### 2. 鎬ц兘浼樺寲
+
+- 娣诲姞鎺ュ彛缂撳瓨鏈哄埗
+- 瀹炵幇寮傛娑堟伅鍙戦��
+- 娣诲姞鎺ュ彛闄愭祦鎺у埗
+- 浼樺寲鏁版嵁搴撴煡璇�
+
+### 3. 鐩戞帶鍛婅
+
+- 娣诲姞鎺ュ彛璋冪敤鐩戞帶
+- 瀹炵幇娑堟伅鍙戦�佺姸鎬佽窡韪�
+- 娣诲姞寮傚父鍛婅鏈哄埗
+- 闆嗘垚鏃ュ織鍒嗘瀽绯荤粺
+
+## 鎬荤粨
+
+鏈浠诲姟鎴愬姛瀹屾垚浜嗕互涓嬬洰鏍囷細
+
+1. 鉁� 鍒涘缓浜嗙鍚堣姹傜殑REST API鎺ュ彛
+2. 鉁� 浣跨敤浜嗘寚瀹氱殑鍙傛暟鍜岃繑鍥炲�肩被鍨�
+3. 鉁� 瀹炵幇浜嗗畬鏁寸殑閿欒澶勭悊鏈哄埗
+4. 鉁� 鎻愪緵浜嗚缁嗙殑浣跨敤鏂囨。
+5. 鉁� 鍒涘缓浜嗘祴璇曠敤渚嬪拰杈呭姪鑴氭湰
+6. 鉁� 閬靛惊浜嗚壇濂界殑浠g爜瑙勮寖鍜岃璁″師鍒�
+
+椤圭洰浠g爜缁撴瀯娓呮櫚锛屾枃妗e畬鏁达紝鍏锋湁鑹ソ鐨勫彲缁存姢鎬у拰鎵╁睍鎬э紝鍙互婊¤冻褰撳墠鐨勯渶姹傚苟涓烘湭鏉ョ殑鍔熻兘鎵╁睍鎻愪緵鑹ソ鐨勫熀纭�銆� 
\ No newline at end of file
diff --git a/README.md b/README.md
index 393f5e4..c892473 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@
 4. 閫�璐х鐞�
 5. 渚涘簲鍟嗙鐞�
 6. ERP涓嶴RM绯荤粺鏁版嵁姣斿
+7. 閽夐拤娑堟伅閫氱煡
 
 ## 鏍稿績鏁版嵁瀹炰綋
 
@@ -40,6 +41,98 @@
 - API璋冪敤棰戠巼涓嶄綆浜�2灏忔椂
 - 璇锋眰鏃堕棿鑼冨洿涓嶅ぇ浜�24灏忔椂
 - 鏁版嵁绫诲瀷杞崲闇�娉ㄦ剰锛欵RP绯荤粺(Long)涓嶴RM绯荤粺(Integer)
+
+## REST API鎺ュ彛
+
+### 閽夐拤娑堟伅鍙戦�佹帴鍙�
+
+#### 鎺ュ彛淇℃伅
+
+- **URL**: `POST /api/dingtalk/sendMessage`
+- **鍔熻兘**: 鍙戦�侀拤閽夋秷鎭�氱煡
+- **鎻忚堪**: 鏍规嵁妫�楠屽崟鍙峰彂閫佷笉鍚堟牸妫�楠屽崟鐨勯拤閽夐�氱煡娑堟伅
+
+#### 璇锋眰鍙傛暟
+
+```json
+{
+  "releaseNo": "妫�楠屽崟鍙�"
+}
+```
+
+**鍙傛暟璇存槑**:
+
+- `releaseNo` (String, 蹇呭~): 妫�楠屽崟鍙凤紝鐢ㄤ簬鏌ヨ瀵瑰簲鐨勯拤閽夋秷鎭唴瀹�
+
+#### 鍝嶅簲缁撴灉
+
+```json
+{
+  "code": 200,
+  "message": null,
+  "successful": 0,
+  "data": "鎺ユ敹鎴愬姛"
+}
+```
+
+**鍝嶅簲瀛楁璇存槑**:
+
+- `code` (Integer): 鍝嶅簲鐘舵�佺爜锛�200琛ㄧず鎴愬姛锛�500琛ㄧず澶辫触
+- `message` (String): 閿欒淇℃伅锛屾垚鍔熸椂涓簄ull
+- `successful` (Integer): 鎴愬姛鏍囪瘑锛�0琛ㄧず鎴愬姛锛�1琛ㄧず澶辫触
+- `data` (String): 鍝嶅簲鏁版嵁锛屾垚鍔熸椂涓�"鎺ユ敹鎴愬姛"锛屽け璐ユ椂涓�"鎺ユ敹澶辫触"
+
+#### 浣跨敤绀轰緥
+
+**璇锋眰绀轰緥**:
+
+```bash
+curl -X POST http://localhost:9095/api/dingtalk/sendMessage \
+  -H "Content-Type: application/json" \
+  -d '{"releaseNo": "IQC202501270001"}'
+```
+
+**鎴愬姛鍝嶅簲绀轰緥**:
+
+```json
+{
+  "code": 200,
+  "message": null,
+  "successful": 0,
+  "data": "鎺ユ敹鎴愬姛"
+}
+```
+
+**澶辫触鍝嶅簲绀轰緥**:
+
+```json
+{
+  "code": 500,
+  "message": "妫�楠屽崟鍙蜂笉鑳戒负绌�",
+  "successful": 1,
+  "data": "鎺ユ敹澶辫触"
+}
+```
+
+#### 閿欒澶勭悊
+
+鎺ュ彛浼氬鐞嗕互涓嬮敊璇儏鍐碉細
+
+1. **鍙傛暟涓虹┖**: 妫�楠屽崟鍙蜂负绌烘垨null鏃惰繑鍥為敊璇俊鎭�
+2. **鏁版嵁涓嶅瓨鍦�**: 妫�楠屽崟鍙峰搴旂殑閽夐拤娑堟伅鍐呭涓嶅瓨鍦ㄦ椂杩斿洖澶辫触
+3. **鍙戦�佸け璐�**: 閽夐拤API璋冪敤澶辫触鏃惰繑鍥炲け璐ヤ俊鎭�
+4. **绯荤粺寮傚父**: 鍏朵粬绯荤粺寮傚父鏃惰繑鍥炲紓甯镐俊鎭�
+
+#### 娉ㄦ剰浜嬮」
+
+1. 纭繚妫�楠屽崟鍙峰湪`DINGTALK_MSG`琛ㄤ腑鏈夊搴旂殑璁板綍
+2. 纭繚閽夐拤搴旂敤閰嶇疆姝g‘涓旀湁鍙戦�佹潈闄�
+3. 鎺ュ彛璋冪敤棰戠巼寤鸿涓嶈秴杩囨瘡鍒嗛挓1娆�
+4. 寤鸿鍦ㄧ敓浜х幆澧冧腑娣诲姞鎺ュ彛璁块棶鏉冮檺鎺у埗
+
+#### 璇︾粏鏂囨。
+
+鏇村璇︾粏鐨凙PI浣跨敤璇存槑銆侀敊璇鐞嗐�佹渶浣冲疄璺电瓑鍐呭锛岃鍙傝�� [API_DOCUMENTATION.md](./API_DOCUMENTATION.md) 鏂囦欢銆�
 
 ## 鏁版嵁搴撹〃缁撴瀯
 
@@ -330,4 +423,113 @@
 寮傛绾跨▼2: 鎵规5澶勭悊瀹屾垚
 ```
 
-杩欑鏂瑰紡纭繚浜嗕富绾跨▼涓嶄細琚暱鏃堕棿闃诲锛屽悓鏃跺厖鍒嗗埄鐢ㄤ簡绯荤粺璧勬簮杩涜骞惰澶勭悊銆� 
\ No newline at end of file
+杩欑鏂瑰紡纭繚浜嗕富绾跨▼涓嶄細琚暱鏃堕棿闃诲锛屽悓鏃跺厖鍒嗗埄鐢ㄤ簡绯荤粺璧勬簮杩涜骞惰澶勭悊銆�
+
+## 閽夐拤娑堟伅閫氱煡鍔熻兘
+
+绯荤粺闆嗘垚浜嗛拤閽夋秷鎭�氱煡鍔熻兘锛岀敤浜庡湪閲嶈浜嬩欢鍙戠敓鏃跺悜鎸囧畾鐢ㄦ埛鍙戦�侀�氱煡銆備富瑕佸寘鎷互涓嬪嚑涓儴鍒嗭細
+
+### 鍔熻兘姒傝堪
+
+1. **閫氱煡鍦烘櫙**锛�
+    - 閲囪喘璁㈠崟鏁版嵁姣斿瀹屾垚鍚庯紝閫氱煡鐩稿叧浜哄憳鏌ョ湅缁撴灉
+    - 鏁版嵁寮傚父鏃剁殑棰勮閫氱煡
+    - 绯荤粺閲嶈鎿嶄綔鐨勭‘璁ら�氱煡
+    - 涓嶅悎鏍兼楠屽崟瀹℃壒鎯呭喌閫氱煡
+
+2. **閫氱煡鏂瑰紡**锛�
+    - 涓汉宸ヤ綔閫氱煡锛氱洿鎺ュ彂閫佺粰鎸囧畾鐢ㄦ埛
+    - 缇ゆ満鍣ㄤ汉閫氱煡锛氬彂閫佸埌鎸囧畾鐨勯拤閽夌兢
+
+### 鏁版嵁缁撴瀯
+
+閽夐拤鐢ㄦ埛淇℃伅瀛樺偍鍦� `DINGTALK_INFO` 琛ㄤ腑锛岃〃缁撴瀯濡備笅锛�
+
+| 瀛楁鍚�              | 绫诲瀷      | 璇存槑                 |
+|------------------|---------|--------------------|
+| id               | Long    | 涓婚敭                 |
+| sid              | Long    | 鑱屽伐ID               |
+| phone            | String  | 鐢佃瘽鍙风爜               |
+| dingtalk_id      | String  | 閽夐拤鐢ㄦ埛ID             |
+| is_send_dingtalk | Integer | 鏄惁鍙戦�侀拤閽夐�氱煡(1:鏄�, 0:鍚�) |
+
+涓嶅悎鏍兼楠屽崟淇℃伅瀛樺偍鍦� `DINGTALK_MSG` 琛ㄤ腑锛岃〃缁撴瀯濡備笅锛�
+
+| 瀛楁鍚�           | 绫诲瀷     | 璇存槑    |
+|---------------|--------|-------|
+| release_no    | String | 妫�楠屽崟鍙�  |
+| supp_name     | String | 渚涘簲鍟嗗悕绉� |
+| create_date   | Date   | 鏉ユ枡鏃ユ湡  |
+| project_codes | String | 椤圭洰浠g爜  |
+| item_no       | String | 鏂欏彿    |
+| fname         | String | 瀹℃牳浜�   |
+| fng_handle    | String | 澶勭悊鏂瑰紡  |
+
+### 娑堟伅鍙戦�佹祦绋�
+
+1. **鑾峰彇閫氱煡鐢ㄦ埛**锛�
+    - 浠� `DINGTALK_INFO` 琛ㄤ腑绛涢�� `is_send_dingtalk` 涓�1鐨勭敤鎴�
+    - 濡傛灉鐢ㄦ埛鐨勯拤閽塈D涓虹┖锛屽垯閫氳繃閽夐拤API鏍规嵁鎵嬫満鍙疯幏鍙栭拤閽塈D
+    - 鏇存柊鏁版嵁搴撲腑鐨勯拤閽塈D
+
+2. **鍙戦�侀�氱煡**锛�
+    - 姹囨�绘墍鏈夋湁鏁堢殑閽夐拤鐢ㄦ埛ID
+    - 鏍规嵁妫�楠屽崟鍙锋煡璇� `DINGTALK_MSG` 琛ㄨ幏鍙栨秷鎭唴瀹�
+    - 璋冪敤閽夐拤寮�鏀続PI鍙戦�佸伐浣滈�氱煡
+
+### 閰嶇疆璇存槑
+
+閽夐拤搴旂敤閰嶇疆淇℃伅瀛樺偍鍦� `DataAcquisitionConfiguration` 涓細
+
+```java
+// 閽夐拤搴旂敤Key
+public static final String TALK_APP_KEY = "your_app_key";
+// 閽夐拤搴旂敤Secret
+public static final String TALK_APP_SECRET = "your_app_secret";
+// 閽夐拤鑷畾涔夋満鍣ㄤ汉Token
+public static final String CUSTOM_ROBOT_TOKEN = "your_robot_token";
+```
+
+### 浣跨敤鏂规硶
+
+瑕佸彂閫侀拤閽夐�氱煡锛屽彲浠ヨ皟鐢� `DingtalkInfoService` 鐨� `sendMessage` 鏂规硶锛�
+
+```java
+
+@Autowired
+private DingtalkInfoService dingtalkInfoService;
+
+// 鍙戦�佷笉鍚堟牸妫�楠屽崟閫氱煡
+boolean result = dingtalkInfoService.sendMessage("妫�楠屽崟鍙�");
+```
+
+### 瀹氭椂浠诲姟
+
+绯荤粺閰嶇疆浜嗗畾鏃朵换鍔¤嚜鍔ㄥ彂閫佷笉鍚堟牸妫�楠屽崟閫氱煡锛�
+
+```java
+/**
+ * 瀹氭椂鍙戦�佷笉鍚堟牸妫�楠屽崟閽夐拤閫氱煡
+ * 姣忓皬鏃舵鏌ヤ竴娆℃槸鍚︽湁鏂扮殑涓嶅悎鏍兼楠屽崟
+ */
+@Scheduled(cron = "0 0 */1 * * ?")
+public void sendInspectionNotification() {
+    // 浠诲姟瀹炵幇...
+}
+```
+
+### 娑堟伅鏍煎紡
+
+涓嶅悎鏍兼楠屽崟閫氱煡鐨勬牸寮忓涓嬶細
+
+```
+渚涘簲鍟哰xxx] 鏉ユ枡鏃ユ湡[yyyy-MM-dd] 椤圭洰[xxx] 鏂欏彿[xxx]鐨勪笉鍚堟牸妫�楠屽崟琚玔xxx]瀹℃壒涓篬xxx]锛岃鏌ユ敹!
+```
+
+### 娉ㄦ剰浜嬮」
+
+1. 閽夐拤娑堟伅鍙戦�侀鐜囨湁闄愬埗锛岃鍕胯繃浜庨绻佸彂閫�
+2. 纭繚搴旂敤鏈夊彂閫佸伐浣滈�氱煡鐨勬潈闄�
+3. 鐢ㄦ埛鎵嬫満鍙峰繀椤讳笌閽夐拤娉ㄥ唽鎵嬫満鍙蜂竴鑷�
+4. 寤鸿灏嗛噸瑕侀�氱煡鍚屾椂閫氳繃澶氱娓犻亾鍙戦�侊紙濡傞偖浠躲�佺煭淇$瓑锛�
+5. 妫�楠屽崟閫氱煡鍦╜DINGTALK_MSG`琛ㄤ腑蹇呴』鏈夊搴旂殑璁板綍 
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 1a500af..f9b3e16 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,6 +67,18 @@
             <version>4.9.3</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>dingtalk</artifactId>
+            <version>2.0.14</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>alibaba-dingtalk-service-sdk</artifactId>
+            <version>2.0.0</version>
+        </dependency>
+
 
         <dependency>
             <groupId>com.alibaba</groupId>
diff --git a/src/main/java/com/gs/xky/config/DataAcquisitionConfiguration.java b/src/main/java/com/gs/xky/config/DataAcquisitionConfiguration.java
index b516a43..68b01af 100644
--- a/src/main/java/com/gs/xky/config/DataAcquisitionConfiguration.java
+++ b/src/main/java/com/gs/xky/config/DataAcquisitionConfiguration.java
@@ -20,4 +20,24 @@
     public static final String APP_SECRET = "f13bd1bcb130f0090ed92dc021e5f4e1";
 
     public static final String ERP_CODE = "Z106";
+
+
+    /**
+     * 搴旂敤鐨� AgentId
+     */
+    public static final Long AGENT_ID = 3303296035L;
+    /**
+     * 搴旂敤鐨� AppKey
+     */
+    public static final String TALK_APP_KEY = "dingnpc4kma0t19nphhd";
+    /**
+     * 搴旂敤鐨� AppSecret
+     */
+    public static final String TALK_APP_SECRET = "uMecvKIfErf9htigYIyjI3svHpXEEDWROy2v1cXw7V6EXIG09oQI5N5e-EMqBo4r";
+
+    //缇よ亰鏈哄櫒浜虹浉鍏�
+
+    public static final String CUSTOM_ROBOT_TOKEN = "c2849e46cb0d91b0721c377742938b8ac5ef57e3c9eeab918e2cd5dd9c3aad2a";
+
+    public static final String SECRET = "SEC382027a5c81ea5152b71b687fb2c1ebf26acbde035355da6ab2fb37306454134";
 }
diff --git a/src/main/java/com/gs/xky/config/ResultMessage.java b/src/main/java/com/gs/xky/config/ResultMessage.java
new file mode 100644
index 0000000..260ab46
--- /dev/null
+++ b/src/main/java/com/gs/xky/config/ResultMessage.java
@@ -0,0 +1,35 @@
+package com.gs.xky.config;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ResultMessage {
+
+    private static final int SUCCESS = 200;
+    private static final int ERROR = 500;
+
+    private int code;
+
+    private String message;
+
+    private int successful;
+
+    private String data;
+
+    public static ResultMessage ok() {
+        return new ResultMessage(SUCCESS, null, 0, "鎺ユ敹鎴愬姛");
+    }
+
+    public static ResultMessage error(Exception e) {
+        return new ResultMessage(ERROR, e.getMessage(), 1, "鎺ユ敹澶辫触");
+    }
+
+    public static ResultMessage error(String message) {
+        return new ResultMessage(ERROR, message, 1, "鎺ユ敹澶辫触");
+    }
+}
diff --git a/src/main/java/com/gs/xky/controller/DingtalkController.java b/src/main/java/com/gs/xky/controller/DingtalkController.java
new file mode 100644
index 0000000..f84bca8
--- /dev/null
+++ b/src/main/java/com/gs/xky/controller/DingtalkController.java
@@ -0,0 +1,61 @@
+package com.gs.xky.controller;
+
+import com.gs.xky.config.ResultMessage;
+import com.gs.xky.dto.NumbericalDto;
+import com.gs.xky.service.DingtalkInfoService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 閽夐拤娑堟伅鍙戦�佹帶鍒跺櫒
+ *
+ * @author 28567
+ * @description 鎻愪緵閽夐拤娑堟伅鍙戦�佺浉鍏崇殑REST鎺ュ彛
+ * @createDate 2025-01-27
+ */
+@RestController
+@RequestMapping("/api/dingtalk")
+@RequiredArgsConstructor
+@Slf4j
+public class DingtalkController {
+
+    private final DingtalkInfoService dingtalkInfoService;
+
+    /**
+     * 鍙戦�侀拤閽夋秷鎭�
+     *
+     * @param numbericalDto 鍖呭惈妫�楠屽崟鍙风殑璇锋眰鍙傛暟
+     * @return ResultMessage 鎿嶄綔缁撴灉
+     */
+    @PostMapping("/sendMessage")
+    public ResultMessage sendMessage(@RequestBody NumbericalDto numbericalDto) {
+        try {
+            log.info("寮�濮嬪彂閫侀拤閽夋秷鎭紝妫�楠屽崟鍙凤細{}", numbericalDto.getReleaseNo());
+
+            // 鍙傛暟鏍¢獙
+            if (numbericalDto == null || numbericalDto.getReleaseNo() == null || numbericalDto.getReleaseNo().trim().isEmpty()) {
+                log.warn("妫�楠屽崟鍙蜂笉鑳戒负绌�");
+                return ResultMessage.error("妫�楠屽崟鍙蜂笉鑳戒负绌�");
+            }
+
+            // 璋冪敤鏈嶅姟灞傚彂閫佹秷鎭�
+            boolean result = dingtalkInfoService.sendMessage(numbericalDto.getReleaseNo());
+
+            if (result) {
+                log.info("閽夐拤娑堟伅鍙戦�佹垚鍔燂紝妫�楠屽崟鍙凤細{}", numbericalDto.getReleaseNo());
+                return ResultMessage.ok();
+            } else {
+                log.warn("閽夐拤娑堟伅鍙戦�佸け璐ワ紝妫�楠屽崟鍙凤細{}", numbericalDto.getReleaseNo());
+                return ResultMessage.error("閽夐拤娑堟伅鍙戦�佸け璐�");
+            }
+
+        } catch (Exception e) {
+            log.error("鍙戦�侀拤閽夋秷鎭椂鍙戠敓寮傚父锛屾楠屽崟鍙凤細{}", numbericalDto != null ? numbericalDto.getReleaseNo() : "null", e);
+            return ResultMessage.error(e);
+        }
+    }
+} 
\ No newline at end of file
diff --git a/src/main/java/com/gs/xky/dto/DingTalkMessage.java b/src/main/java/com/gs/xky/dto/DingTalkMessage.java
new file mode 100644
index 0000000..2d58449
--- /dev/null
+++ b/src/main/java/com/gs/xky/dto/DingTalkMessage.java
@@ -0,0 +1,21 @@
+package com.gs.xky.dto;
+
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class DingTalkMessage {
+    @SerializedName("errcode")
+    private int errcode;
+
+    @SerializedName("task_id")
+    private Long taskId;
+
+    @SerializedName("request_id")
+    private String requestId;
+}
diff --git a/src/main/java/com/gs/xky/dto/DingTalkResponse.java b/src/main/java/com/gs/xky/dto/DingTalkResponse.java
new file mode 100644
index 0000000..654fc96
--- /dev/null
+++ b/src/main/java/com/gs/xky/dto/DingTalkResponse.java
@@ -0,0 +1,23 @@
+package com.gs.xky.dto;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class DingTalkResponse {
+
+    @SerializedName("errcode")
+    private int errcode;
+
+    @SerializedName("errmsg")
+    private String errmsg;
+
+    @SerializedName("result")
+    private Result result;
+
+}
diff --git a/src/main/java/com/gs/xky/dto/NumbericalDto.java b/src/main/java/com/gs/xky/dto/NumbericalDto.java
new file mode 100644
index 0000000..5bda862
--- /dev/null
+++ b/src/main/java/com/gs/xky/dto/NumbericalDto.java
@@ -0,0 +1,14 @@
+package com.gs.xky.dto;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class NumbericalDto {
+
+    private String releaseNo;
+}
diff --git a/src/main/java/com/gs/xky/dto/Result.java b/src/main/java/com/gs/xky/dto/Result.java
new file mode 100644
index 0000000..4d522b9
--- /dev/null
+++ b/src/main/java/com/gs/xky/dto/Result.java
@@ -0,0 +1,17 @@
+package com.gs.xky.dto;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class Result {
+
+    // Getters and Setters
+    @SerializedName("exclusive_account_userid_list")
+    private List<String> exclusiveAccountUseridList;
+
+    private String userid;
+
+}
diff --git a/src/main/java/com/gs/xky/entity/DingtalkInfo.java b/src/main/java/com/gs/xky/entity/DingtalkInfo.java
new file mode 100644
index 0000000..7c42e5d
--- /dev/null
+++ b/src/main/java/com/gs/xky/entity/DingtalkInfo.java
@@ -0,0 +1,39 @@
+package com.gs.xky.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @TableName DINGTALK_INFO
+ */
+@TableName(value = "DINGTALK_INFO")
+@Data
+public class DingtalkInfo implements Serializable {
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+    /**
+     * SEQ_DingTalk
+     */
+    @TableId
+    private Long id;
+    /**
+     * 鑱屽伐id
+     */
+    private Long sid;
+    /**
+     * 鐢佃瘽
+     */
+    private String phone;
+    /**
+     * 閽夐拤id
+     */
+    private String dingtalkId;
+    /**
+     * 閽夐拤閫氱煡
+     */
+    private Integer isSendDingtalk;
+}
\ No newline at end of file
diff --git a/src/main/java/com/gs/xky/entity/DingtalkMsg.java b/src/main/java/com/gs/xky/entity/DingtalkMsg.java
new file mode 100644
index 0000000..b12dbb0
--- /dev/null
+++ b/src/main/java/com/gs/xky/entity/DingtalkMsg.java
@@ -0,0 +1,46 @@
+package com.gs.xky.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @TableName DINGTALK_MSG
+ */
+@TableName(value = "DINGTALK_MSG")
+@Data
+public class DingtalkMsg implements Serializable {
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+    /**
+     * 妫�楠屽崟鍙�
+     */
+    private String releaseNo;
+    /**
+     * 渚涘簲鍟�
+     */
+    private String suppName;
+    /**
+     * 鏉ユ枡鏃ユ湡
+     */
+    private Date createDate;
+    /**
+     * 椤圭洰
+     */
+    private String projectCodes;
+    /**
+     * 鏂欏彿
+     */
+    private String itemNo;
+    /**
+     * 瀹℃牳浜�
+     */
+    private String fname;
+    /**
+     * 澶勭悊鏂瑰紡
+     */
+    private String fngHandle;
+}
\ No newline at end of file
diff --git a/src/main/java/com/gs/xky/mapper/DingtalkInfoMapper.java b/src/main/java/com/gs/xky/mapper/DingtalkInfoMapper.java
new file mode 100644
index 0000000..77c635e
--- /dev/null
+++ b/src/main/java/com/gs/xky/mapper/DingtalkInfoMapper.java
@@ -0,0 +1,18 @@
+package com.gs.xky.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.gs.xky.entity.DingtalkInfo;
+
+/**
+ * @author 28567
+ * @description 閽堝琛ㄣ�怐INGTALK_INFO銆戠殑鏁版嵁搴撴搷浣淢apper
+ * @createDate 2025-06-20 16:12:48
+ * @Entity com.gs.xky.entity.DingtalkInfo
+ */
+public interface DingtalkInfoMapper extends BaseMapper<DingtalkInfo> {
+
+}
+
+
+
+
diff --git a/src/main/java/com/gs/xky/mapper/DingtalkMsgMapper.java b/src/main/java/com/gs/xky/mapper/DingtalkMsgMapper.java
new file mode 100644
index 0000000..3dac92c
--- /dev/null
+++ b/src/main/java/com/gs/xky/mapper/DingtalkMsgMapper.java
@@ -0,0 +1,18 @@
+package com.gs.xky.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.gs.xky.entity.DingtalkMsg;
+
+/**
+ * @author 28567
+ * @description 閽堝琛ㄣ�怐INGTALK_MSG銆戠殑鏁版嵁搴撴搷浣淢apper
+ * @createDate 2025-06-21 10:07:15
+ * @Entity com.gs.xky.entity.DingtalkMsg
+ */
+public interface DingtalkMsgMapper extends BaseMapper<DingtalkMsg> {
+
+}
+
+
+
+
diff --git a/src/main/java/com/gs/xky/service/DingtalkInfoService.java b/src/main/java/com/gs/xky/service/DingtalkInfoService.java
new file mode 100644
index 0000000..a397591
--- /dev/null
+++ b/src/main/java/com/gs/xky/service/DingtalkInfoService.java
@@ -0,0 +1,14 @@
+package com.gs.xky.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.gs.xky.entity.DingtalkInfo;
+
+/**
+ * @author 28567
+ * @description 閽堝琛ㄣ�怐INGTALK_INFO銆戠殑鏁版嵁搴撴搷浣淪ervice
+ * @createDate 2025-06-20 16:12:48
+ */
+public interface DingtalkInfoService extends IService<DingtalkInfo> {
+
+    boolean sendMessage(String releaseNo);
+}
diff --git a/src/main/java/com/gs/xky/service/Impl/DingtalkInfoServiceImpl.java b/src/main/java/com/gs/xky/service/Impl/DingtalkInfoServiceImpl.java
new file mode 100644
index 0000000..7b91468
--- /dev/null
+++ b/src/main/java/com/gs/xky/service/Impl/DingtalkInfoServiceImpl.java
@@ -0,0 +1,155 @@
+package com.gs.xky.service.Impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
+import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
+import com.gs.xky.entity.DingtalkInfo;
+import com.gs.xky.entity.DingtalkMsg;
+import com.gs.xky.mapper.DingtalkInfoMapper;
+import com.gs.xky.mapper.DingtalkMsgMapper;
+import com.gs.xky.service.DingtalkInfoService;
+import com.gs.xky.service.SimpleExample;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author 28567
+ * @description 閽堝琛ㄣ�怐INGTALK_INFO銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
+ * @createDate 2025-06-20 16:12:48
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class DingtalkInfoServiceImpl extends ServiceImpl<DingtalkInfoMapper, DingtalkInfo>
+        implements DingtalkInfoService {
+
+    private final SimpleExample simpleExample;
+    private final DingtalkMsgMapper dingtalkMsgMapper;
+
+    @Override
+    public boolean sendMessage(String releaseNo) {
+        try {
+            // 鏌ヨ閽夐拤娑堟伅鍐呭
+            LambdaQueryWrapper<DingtalkMsg> msgWrapper = new LambdaQueryWrapper<>();
+            msgWrapper.eq(DingtalkMsg::getReleaseNo, releaseNo);
+            DingtalkMsg dingtalkMsg = dingtalkMsgMapper.selectOne(msgWrapper);
+
+            if (dingtalkMsg == null) {
+                log.error("鏈壘鍒版楠屽崟鍙蜂负 {} 鐨勯拤閽夋秷鎭唴瀹�", releaseNo);
+                return false;
+            }
+
+            // 鏍煎紡鍖栨棩鏈�
+            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+            String createDateStr = (dingtalkMsg.getCreateDate() != null) ?
+                    dateFormat.format(dingtalkMsg.getCreateDate()) : "鏈煡";
+
+            // 鏋勫缓娑堟伅鍐呭
+            String message = String.format("渚涘簲鍟哰%s] 鏉ユ枡鏃ユ湡[%s] 椤圭洰[%s] 鏂欏彿[%s]鐨勪笉鍚堟牸妫�楠屽崟琚玔%s]瀹℃壒涓篬%s]锛岃鏌ユ敹!",
+                    dingtalkMsg.getSuppName(), createDateStr, dingtalkMsg.getProjectCodes(),
+                    dingtalkMsg.getItemNo(), dingtalkMsg.getFname(), dingtalkMsg.getFngHandle());
+
+            // 璋冪敤getDingtalkUserIdList鏂规硶鑾峰彇UserIdList
+            List<String> userIdList = getDingtalkUserIdList();
+
+            if (userIdList == null || userIdList.isEmpty()) {
+                log.warn("娌℃湁闇�瑕佸彂閫侀拤閽夋秷鎭殑鐢ㄦ埛");
+                return false;
+            }
+
+            // 閫氳繃閽夐拤鍙戦�佹秷鎭�
+            String userIdListStr = String.join(",", userIdList);
+
+            OapiMessageCorpconversationAsyncsendV2Response rsp = sendMessage(userIdListStr, message);
+            System.out.println(rsp.getBody());
+            log.info("鎴愬姛鍙戦�侀拤閽夋秷鎭�: {}", message);
+            return true;
+        } catch (Exception e) {
+            log.error("鍙戦�侀拤閽夋秷鎭け璐�", e);
+            return false;
+        }
+    }
+
+    private List<String> getDingtalkUserIdList() {
+        try {
+            LambdaQueryWrapper<DingtalkInfo> wrapper = new LambdaQueryWrapper<>();
+            wrapper.ge(DingtalkInfo::getIsSendDingtalk, 1);
+            List<DingtalkInfo> list = list(wrapper);
+
+            if (list == null || list.isEmpty()) {
+                return new ArrayList<>();
+            }
+
+            // 浣跨敤stream娴佽繃婊ゅ嚭list涓璬ingtalkId涓虹┖鐨勬暟鎹�
+            List<DingtalkInfo> emptyDingtalkIdList = list.stream()
+                    .filter(info -> !StringUtils.hasText(info.getDingtalkId()))
+                    .collect(Collectors.toList());
+
+            // 濡傛灉瀛樺湪涓虹┖鐨勬暟鎹氨閫氳繃閽夐拤鐨勬帴鍙h幏鍙栵紝涓篸ingtalkId璧嬪�硷紝骞朵笖鏇存柊鏁版嵁搴�
+            if (!emptyDingtalkIdList.isEmpty()) {
+                String accessToken = simpleExample.getAccessToken();
+
+                for (DingtalkInfo info : emptyDingtalkIdList) {
+                    if (StringUtils.hasText(info.getPhone())) {
+                        try {
+                            // 閫氳繃鎵嬫満鍙疯幏鍙栭拤閽夌敤鎴稩D
+                            com.dingtalk.api.response.OapiV2UserGetbymobileResponse response =
+                                    simpleExample.getOapiV2UserGetbymobileResponse(info.getPhone(), accessToken);
+
+                            if (response != null && response.getResult() != null) {
+                                info.setDingtalkId(response.getResult().getUserid());
+                                // 鏇存柊鏁版嵁搴�
+                                updateById(info);
+                            }
+                        } catch (Exception e) {
+                            log.error("鑾峰彇閽夐拤鐢ㄦ埛ID澶辫触锛屾墜鏈哄彿锛歿}", info.getPhone(), e);
+                        }
+                    }
+                }
+            }
+
+            // 涓嶅瓨鍦ㄤ负绌虹殑鏁版嵁鎴栬�呭鐞嗗畬绌烘暟鎹悗锛岃繑鍥炴墍鏈夋湁鏁堢殑dingtalkId鍒楄〃
+            return list.stream()
+                    .map(DingtalkInfo::getDingtalkId)
+                    .filter(StringUtils::hasText)
+                    .collect(Collectors.toList());
+        } catch (Exception e) {
+            log.error("鑾峰彇閽夐拤鐢ㄦ埛鍒楄〃澶辫触", e);
+            return new ArrayList<>();
+        }
+    }
+
+    private OapiMessageCorpconversationAsyncsendV2Response sendMessage(String userIdListStr, String message) throws Exception {
+
+        String accessToken = simpleExample.getAccessToken();
+
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");
+        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
+        request.setAgentId(3917187842L);
+        request.setUseridList(userIdListStr);
+        request.setToAllUser(false);
+
+        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
+        msg.setMsgtype("text");
+        msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());
+        msg.getText().setContent(message);
+        request.setMsg(msg);
+
+        return client.execute(request, accessToken);
+
+    }
+}
+
+
+
+
diff --git a/src/main/java/com/gs/xky/service/SimpleExample.java b/src/main/java/com/gs/xky/service/SimpleExample.java
new file mode 100644
index 0000000..18f7ee4
--- /dev/null
+++ b/src/main/java/com/gs/xky/service/SimpleExample.java
@@ -0,0 +1,239 @@
+package com.gs.xky.service;
+
+
+import cn.hutool.core.util.StrUtil;
+import com.aliyun.dingtalkoauth2_1_0.Client;
+import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest;
+import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse;
+import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTOHeaders;
+import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTORequest;
+import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTOResponse;
+import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTOResponseBody;
+import com.aliyun.tea.TeaException;
+import com.aliyun.teaopenapi.models.Config;
+import com.aliyun.teautil.Common;
+import com.aliyun.teautil.models.RuntimeOptions;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiRobotSendRequest;
+import com.dingtalk.api.request.OapiV2UserGetbymobileRequest;
+import com.dingtalk.api.response.OapiRobotSendResponse;
+import com.dingtalk.api.response.OapiV2UserGetbymobileResponse;
+import com.google.gson.Gson;
+import com.gs.xky.config.DataAcquisitionConfiguration;
+import com.gs.xky.dto.DingTalkMessage;
+import com.gs.xky.dto.DingTalkResponse;
+import com.taobao.api.ApiException;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.codec.binary.Base64;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.List;
+
+
+/**
+ * 鍙戦�佷釜浜烘秷鎭�
+ *
+ * @author tjx
+ * @date 2024/11/17 16:18
+ */
+@Service
+@RequiredArgsConstructor
+@Transactional(rollbackFor = Exception.class)
+public class SimpleExample {
+
+    /**
+     * 缇ら噷鏈哄櫒浜哄彂閫佹秷鎭�
+     *
+     * @author tjx
+     * @date 2024/11/18 08:54
+     */
+    public DingTalkResponse chatSendMessage(String message) throws Exception {
+        try {
+            Long timestamp = System.currentTimeMillis();
+            System.out.println(timestamp);
+            String secret = DataAcquisitionConfiguration.TALK_APP_SECRET;
+            String stringToSign = timestamp + "\n" + secret;
+            Mac mac = Mac.getInstance("HmacSHA256");
+            mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
+            byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
+            String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
+            System.out.println(sign);
+
+            //sign瀛楁鍜宼imestamp瀛楁蹇呴』鎷兼帴鍒拌姹俇RL涓婏紝鍚﹀垯浼氬嚭鐜� 310000 鐨勯敊璇俊鎭�
+            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/robot/send?sign=" + sign + "&timestamp=" + timestamp);
+            OapiRobotSendRequest req = new OapiRobotSendRequest();
+            /**
+             * 鍙戦�佹枃鏈秷鎭�
+             */
+            //瀹氫箟鏂囨湰鍐呭
+            OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
+            text.setContent(message);
+            //瀹氫箟 @ 瀵硅薄
+            OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
+            at.setIsAtAll(true);
+            //璁剧疆娑堟伅绫诲瀷
+            req.setMsgtype("text");
+            req.setText(text);
+            req.setAt(at);
+            OapiRobotSendResponse rsp = client.execute(req, DataAcquisitionConfiguration.CUSTOM_ROBOT_TOKEN);
+
+            Gson gson = new Gson();
+
+            return gson.fromJson(rsp.getBody(), DingTalkResponse.class);
+        } catch (ApiException e) {
+            e.printStackTrace();
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        } catch (InvalidKeyException e) {
+            throw new RuntimeException(e);
+        }
+
+        return null;
+    }
+
+    /**
+     * 鍙戦�佹秷鎭�
+     */
+    public DingTalkMessage sendMessage(String userIdListStr, String message) throws Exception {
+
+        if (!StrUtil.isNotEmpty(userIdListStr)) {
+            return new DingTalkMessage(1, 0L, "null");
+        }
+
+        String[] strArray = userIdListStr.split(",");
+        List<String> userIdList = Arrays.asList(strArray);
+
+        String accessToken = getAccessToken();
+
+        com.aliyun.dingtalkrobot_1_0.Client client1 = createClient1();
+        BatchSendOTOHeaders batchSendOTOHeaders = new BatchSendOTOHeaders();
+        batchSendOTOHeaders.xAcsDingtalkAccessToken = accessToken;
+        BatchSendOTORequest batchSendOTORequest = new BatchSendOTORequest()
+                .setRobotCode("ding7n8fldhylh2rt2l2")
+                .setUserIds(userIdList)
+                .setMsgKey("sampleText")
+                .setMsgParam("{\"content\": \"" + message + "\"}");
+
+        try {
+            BatchSendOTOResponse batchSendOTOResponse = client1.batchSendOTOWithOptions(batchSendOTORequest, batchSendOTOHeaders, new RuntimeOptions());
+
+            BatchSendOTOResponseBody body = batchSendOTOResponse.getBody();
+            if (StrUtil.isNotEmpty(body.getProcessQueryKey())) {
+                return new DingTalkMessage(0, 0L, "null");
+            }
+
+        } catch (TeaException err) {
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                System.out.println(err.code);
+                System.out.println(err.message);
+
+                System.out.println(err.accessDeniedDetail.toString());
+            }
+
+        } catch (Exception _err) {
+            TeaException err = new TeaException(_err.getMessage(), _err);
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                System.out.println(err.code);
+                System.out.println(err.message);
+            }
+
+        }
+
+        return new DingTalkMessage(1, 0L, "null");
+        //return gson.fromJson(rsp.getBody(), DingTalkMessage.class);
+    }
+
+    /**
+     * 鑾峰彇 AccessToken
+     *
+     * @return AccessToken
+     * @throws Exception
+     */
+    public String getAccessToken() throws Exception {
+        Client client = createClient();
+        GetAccessTokenRequest getAccessTokenRequest = new GetAccessTokenRequest()
+                .setAppKey(DataAcquisitionConfiguration.TALK_APP_KEY)
+                .setAppSecret(DataAcquisitionConfiguration.TALK_APP_SECRET);
+        try {
+            GetAccessTokenResponse accessToken = client.getAccessToken(getAccessTokenRequest);
+            return accessToken.body.getAccessToken();
+
+        } catch (TeaException err) {
+            if (!Common.empty(err.code) && !Common.empty(err.message)) {
+                // err 涓惈鏈� code 鍜� message 灞炴�э紝鍙府鍔╁紑鍙戝畾浣嶉棶棰�
+                System.out.println(err.code);
+                System.out.println(err.message);
+            }
+        } catch (Exception exception) {
+            TeaException err = new TeaException(exception.getMessage(), exception);
+            if (!Common.empty(err.code) && !Common.empty(err.message)) {
+                // err 涓惈鏈� code 鍜� message 灞炴�э紝鍙府鍔╁紑鍙戝畾浣嶉棶棰�
+                System.out.println(err.code);
+                System.out.println(err.message);
+            }
+        }
+        return null;
+    }
+
+    public static com.aliyun.dingtalkrobot_1_0.Client createClient1() throws Exception {
+        Config config = new Config();
+        config.protocol = "https";
+        config.regionId = "central";
+        return new com.aliyun.dingtalkrobot_1_0.Client(config);
+    }
+
+    /**
+     * 浣跨敤 Token 鍒濆鍖栬处鍙稢lient
+     *
+     * @return Client
+     * @throws Exception
+     */
+    public Client createClient() throws Exception {
+        Config config = new Config();
+        config.protocol = "https";
+        config.regionId = "central";
+        return new Client(config);
+    }
+
+
+    //    public OapiV2UserGetbymobileResponse getOapiV2UserGetbymobileResponse(SendDingtalk s, String accessToken) {
+//        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile");
+//        OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
+//        req.setMobile(s.getTelephone());
+//        req.setSupportExclusiveAccountSearch(true);
+//        OapiV2UserGetbymobileResponse rsp = null;
+//
+//        try {
+//            rsp = client.execute(req, accessToken);
+//        } catch (ApiException e) {
+//            throw new RuntimeException(e);
+//        }
+//        return rsp;
+//    }
+
+    public OapiV2UserGetbymobileResponse getOapiV2UserGetbymobileResponse(String mobile, String accessToken) {
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile");
+        OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
+        req.setMobile(mobile);
+        req.setSupportExclusiveAccountSearch(true);
+        OapiV2UserGetbymobileResponse rsp = null;
+
+        try {
+            rsp = client.execute(req, accessToken);
+        } catch (ApiException e) {
+            throw new RuntimeException(e);
+        }
+        return rsp;
+    }
+}
diff --git a/src/main/resources/mapper/DingtalkInfoMapper.xml b/src/main/resources/mapper/DingtalkInfoMapper.xml
new file mode 100644
index 0000000..89e5bb2
--- /dev/null
+++ b/src/main/resources/mapper/DingtalkInfoMapper.xml
@@ -0,0 +1,7 @@
+<?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.gs.xky.mapper.DingtalkInfoMapper">
+
+</mapper>
diff --git a/src/main/resources/mapper/DingtalkMsgMapper.xml b/src/main/resources/mapper/DingtalkMsgMapper.xml
new file mode 100644
index 0000000..6fa3fdd
--- /dev/null
+++ b/src/main/resources/mapper/DingtalkMsgMapper.xml
@@ -0,0 +1,21 @@
+<?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.gs.xky.mapper.DingtalkMsgMapper">
+
+    <resultMap id="BaseResultMap" type="com.gs.xky.entity.DingtalkMsg">
+        <result property="releaseNo" column="RELEASE_NO"/>
+        <result property="suppName" column="SUPP_NAME"/>
+        <result property="createDate" column="CREATE_DATE"/>
+        <result property="projectCodes" column="PROJECT_CODES"/>
+        <result property="itemNo" column="ITEM_NO"/>
+        <result property="fname" column="FNAME"/>
+        <result property="fngHandle" column="FNG_HANDLE"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        RELEASE_NO,SUPP_NAME,CREATE_DATE,PROJECT_CODES,ITEM_NO,FNAME,
+        FNG_HANDLE
+    </sql>
+</mapper>
diff --git a/src/test/java/com/gs/xky/XkyApplicationTests.java b/src/test/java/com/gs/xky/XkyApplicationTests.java
index 8f2383f..9caa7ad 100644
--- a/src/test/java/com/gs/xky/XkyApplicationTests.java
+++ b/src/test/java/com/gs/xky/XkyApplicationTests.java
@@ -40,6 +40,8 @@
     private MesInvItemArnService invItemArnService;
     @Autowired
     private PurchaseService service;
+    @Autowired
+    private DingtalkInfoService dingtalkInfoService;
 
     @Test
     void contextLoads() throws IOException {
@@ -58,7 +60,7 @@
     @Test
     void cs() throws IOException {
 
-        String str = "22250529195E;22250529EQHY;22250529HCM9;222505304W8Q;222505305XRK;22250530F6UC;22250530JQ31;22250531UF8T;222506013N09;222506015051;2225060152A2;2225060152EN;222506015AM7;222506015U07;2225060162K4;222506016C4C;222506017GEM;222506017YTU;222506019RWD;22250601A216;22250601C4C3;22250601GTT8;22250601GUGU;22250601H6Y7;22250601JN9X;22250601JVW5;22250601L6R5;22250601NANG;22250601NHK4;22250601NYAL;22250601Q669;22250601RGJX;22250601VCE2;22250601W6C6;22250601WFK1;22250601WH28;22250601XE2T;22250602M0MU;";
+        String str = "2225060624DY;";
 
 
         String[] split = str.split(";");
@@ -157,8 +159,9 @@
     }
 
     @Test
-    void cs3() throws IOException {
+    void cs3() throws Exception {
+        dingtalkInfoService.sendMessage("CGJY20250412166");
 
-//        service.syncPurchaseOrderDetails();
+
     }
 }
\ No newline at end of file
diff --git a/src/test/java/com/gs/xky/controller/DingtalkControllerTest.java b/src/test/java/com/gs/xky/controller/DingtalkControllerTest.java
new file mode 100644
index 0000000..de0fda2
--- /dev/null
+++ b/src/test/java/com/gs/xky/controller/DingtalkControllerTest.java
@@ -0,0 +1,108 @@
+package com.gs.xky.controller;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.gs.xky.dto.NumbericalDto;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * DingtalkController娴嬭瘯绫�
+ *
+ * @author 28567
+ * @description 娴嬭瘯閽夐拤娑堟伅鍙戦�佹帴鍙�
+ * @createDate 2025-01-27
+ */
+@WebMvcTest(DingtalkController.class)
+public class DingtalkControllerTest {
+
+    @Autowired
+    private MockMvc mockMvc;
+
+    @MockBean
+    private com.gs.xky.service.DingtalkInfoService dingtalkInfoService;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @Test
+    public void testSendMessage_Success() throws Exception {
+        // 鍑嗗娴嬭瘯鏁版嵁
+        NumbericalDto requestDto = new NumbericalDto();
+        requestDto.setReleaseNo("IQC202501270001");
+
+        // Mock鏈嶅姟灞傝繑鍥炴垚鍔�
+        when(dingtalkInfoService.sendMessage(anyString())).thenReturn(true);
+
+        // 鎵ц娴嬭瘯
+        mockMvc.perform(post("/api/dingtalk/sendMessage")
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(requestDto)))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code").value(200))
+                .andExpect(jsonPath("$.successful").value(0))
+                .andExpect(jsonPath("$.data").value("鎺ユ敹鎴愬姛"));
+    }
+
+    @Test
+    public void testSendMessage_Failure() throws Exception {
+        // 鍑嗗娴嬭瘯鏁版嵁
+        NumbericalDto requestDto = new NumbericalDto();
+        requestDto.setReleaseNo("IQC202501270001");
+
+        // Mock鏈嶅姟灞傝繑鍥炲け璐�
+        when(dingtalkInfoService.sendMessage(anyString())).thenReturn(false);
+
+        // 鎵ц娴嬭瘯
+        mockMvc.perform(post("/api/dingtalk/sendMessage")
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(requestDto)))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code").value(500))
+                .andExpect(jsonPath("$.successful").value(1))
+                .andExpect(jsonPath("$.data").value("鎺ユ敹澶辫触"));
+    }
+
+    @Test
+    public void testSendMessage_EmptyReleaseNo() throws Exception {
+        // 鍑嗗娴嬭瘯鏁版嵁 - 绌虹殑妫�楠屽崟鍙�
+        NumbericalDto requestDto = new NumbericalDto();
+        requestDto.setReleaseNo("");
+
+        // 鎵ц娴嬭瘯
+        mockMvc.perform(post("/api/dingtalk/sendMessage")
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(requestDto)))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code").value(500))
+                .andExpect(jsonPath("$.message").value("妫�楠屽崟鍙蜂笉鑳戒负绌�"))
+                .andExpect(jsonPath("$.successful").value(1))
+                .andExpect(jsonPath("$.data").value("鎺ユ敹澶辫触"));
+    }
+
+    @Test
+    public void testSendMessage_NullReleaseNo() throws Exception {
+        // 鍑嗗娴嬭瘯鏁版嵁 - null妫�楠屽崟鍙�
+        NumbericalDto requestDto = new NumbericalDto();
+        requestDto.setReleaseNo(null);
+
+        // 鎵ц娴嬭瘯
+        mockMvc.perform(post("/api/dingtalk/sendMessage")
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(requestDto)))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code").value(500))
+                .andExpect(jsonPath("$.message").value("妫�楠屽崟鍙蜂笉鑳戒负绌�"))
+                .andExpect(jsonPath("$.successful").value(1))
+                .andExpect(jsonPath("$.data").value("鎺ユ敹澶辫触"));
+    }
+} 
\ No newline at end of file

--
Gitblit v1.9.3