Compare commits
10 Commits
ae3f7eca91
...
f9450c9ffc
| Author | SHA1 | Date |
|---|---|---|
|
|
f9450c9ffc | |
|
|
e550137ebf | |
|
|
ffb4382070 | |
|
|
8f25f1e7ba | |
|
|
6a82179473 | |
|
|
a7d890843e | |
|
|
9f1baf17d2 | |
|
|
8bc1fe4e94 | |
|
|
0620f10e2d | |
|
|
b2773e47e2 |
|
|
@ -3,7 +3,8 @@ npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
pnpm-debug.log*
|
pnpm-debug.log*
|
||||||
|
CLAUDE.md
|
||||||
|
.claude/
|
||||||
/target/
|
/target/
|
||||||
!.mvn/wrapper/maven-wrapper.jar
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
$src="./target/fxkh-txl-service-1.0.jar"
|
||||||
|
$dst_dir="~/gunshiApp/fxkh"
|
||||||
|
$dst_host="10.0.41.112"
|
||||||
|
$dst_port=22
|
||||||
|
$user="root"
|
||||||
|
$identity="deploy_rsa"
|
||||||
|
|
||||||
|
scp -i deploy_rsa -P $dst_port $src $user@${dst_host}:${dst_dir}
|
||||||
|
|
||||||
|
ssh -i deploy_rsa -p $dst_port $user@${dst_host} "cd ${dst_dir}; docker compose restart"
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
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
|
||||||
|
-----END OPENSSH PRIVATE KEY-----
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDG05gojsKOFYGYgvnzdZGcr/KzAd3yth+B/4PDsZ5LppSxtLHVsTH5ZZEvfXFx8agWdoxglsDtvFXgPyESbRIhO+h3wcFW4Q+x8mjpGESvbf5zoZZy34GoUwmcrghKhBHYVz5L1DWKffRVvg4uXOR+SMISYTIlddHmml+AbjRnMfBWl0ADMu89rZbyzU/MonJQxbcuJ1y11Ivtm0ZmQ5pcuAcWLsmN1Gk0547liQqr2S0cvGK0mOAtLYgdFuuyZxWitMufYp7DsUQzgmxw/k/BabaFj5cGuXdU1froD8xU/ik5ae09PMSYQ6VBt2cN+F6YmCnXk28FLWTzfZoSOiTNzRssPDLK0Aom2JXmsqMKlshcC29TqweXowLJgPV7I9E0XgKPj2dqhakGVCOj5yiNVAvzq2J9sKb0rbZt77mpqrZ626MJJ7++zm2TWVzQ2gOs1g9TpoXw6XaJ0uGFX1/4JcpTonOgRFXXXKr5LJOikhVQAPBqhuTukpzdLslevffedvAL6ArSNwtbB8rKBmqAs40LPBC/hHMr1tNmLLXAguOe6S6Ce5aimclgnvWGwHo9IGubYnhPb0HbjuSiInVZRyj6GbKatU9ScjvWe0BFo5tAv/Jn9zMta/yuzlB5kZ+XP43yCE/OfBfpz1v9xh2cMEw7L/lv6n0rF2dq4ahXGQ== lyf66@Surface-Laptop2
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: docker.kubesre.xyz/openjdk:21
|
||||||
|
container_name: fxkhtxl
|
||||||
|
restart: always
|
||||||
|
network_mode: host
|
||||||
|
volumes:
|
||||||
|
- /root/gunshiApp/fxkh:/app
|
||||||
|
# - /etc/localtime:/etc/localtime:ro
|
||||||
|
# - /etc/timezone:/etc/timezone:ro
|
||||||
|
environment:
|
||||||
|
- SPRING_PROFILES_ACTIVE=gs
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
working_dir: /app
|
||||||
|
command: java -cp fxkh-txl-service-1.0.jar:dependency/* com.whdc.FxkhTxlApiApplication
|
||||||
|
|
@ -0,0 +1,220 @@
|
||||||
|
# 短信管理模块 API 文档
|
||||||
|
|
||||||
|
## 1. 生日短信管理 (SmsBirthdayController)
|
||||||
|
|
||||||
|
### 1.1 修改生日短信配置
|
||||||
|
- **接口地址**: `/smsBirthday/edit`
|
||||||
|
- **请求方法**: `POST`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "Long",
|
||||||
|
"executionTmStr": "String",
|
||||||
|
"status": "Integer",
|
||||||
|
"template": "String",
|
||||||
|
"createTm": "Date"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 查询生日短信配置
|
||||||
|
- **接口地址**: `/smsBirthday/get`
|
||||||
|
- **请求方法**: `GET`
|
||||||
|
- **参数**: 无
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 短信日志管理 (SmsLogController)
|
||||||
|
|
||||||
|
### 2.1 分页查询短信日志
|
||||||
|
- **接口地址**: `/smsLog/page`
|
||||||
|
- **请求方法**: `POST`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sendTm": "Date",
|
||||||
|
"name": "String",
|
||||||
|
"phone": "String",
|
||||||
|
"remark": "String",
|
||||||
|
"content": "String"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 新增短信日志
|
||||||
|
- **接口地址**: `/smsLog/add`
|
||||||
|
- **请求方法**: `POST`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sendTm": "Date",
|
||||||
|
"name": "String",
|
||||||
|
"phone": "String",
|
||||||
|
"remark": "String",
|
||||||
|
"content": "String"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 修改短信日志
|
||||||
|
- **接口地址**: `/smsLog/edit`
|
||||||
|
- **请求方法**: `POST`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "Long",
|
||||||
|
"sendTm": "Date",
|
||||||
|
"name": "String",
|
||||||
|
"phone": "String",
|
||||||
|
"remark": "String",
|
||||||
|
"content": "String"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.4 删除短信日志
|
||||||
|
- **接口地址**: `/smsLog/del/{id}`
|
||||||
|
- **请求方法**: `GET`
|
||||||
|
- **参数**:
|
||||||
|
- `id` (路径参数): Long
|
||||||
|
|
||||||
|
### 2.5 根据ID查询短信日志
|
||||||
|
- **接口地址**: `/smsLog/get/{id}`
|
||||||
|
- **请求方法**: `GET`
|
||||||
|
- **参数**:
|
||||||
|
- `id` (路径参数): Long
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 短信任务管理 (SmsTaskController)
|
||||||
|
|
||||||
|
### 3.1 分页查询短信任务
|
||||||
|
- **接口地址**: `/smsTask/page`
|
||||||
|
- **请求方法**: `POST`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"subjectName": "String",
|
||||||
|
"startDate": "Date",
|
||||||
|
"endDate": "Date",
|
||||||
|
"executionTmStr": "String",
|
||||||
|
"status": "Integer",
|
||||||
|
"template": "String",
|
||||||
|
"createTm": "Date"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 新增短信任务
|
||||||
|
- **接口地址**: `/smsTask/add`
|
||||||
|
- **请求方法**: `POST`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"subjectName": "String",
|
||||||
|
"startDate": "Date",
|
||||||
|
"endDate": "Date",
|
||||||
|
"executionTmStr": "String",
|
||||||
|
"status": "Integer",
|
||||||
|
"template": "String",
|
||||||
|
"createTm": "Date"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 修改短信任务
|
||||||
|
- **接口地址**: `/smsTask/edit`
|
||||||
|
- **请求方法**: `POST`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "Long",
|
||||||
|
"subjectName": "String",
|
||||||
|
"startDate": "Date",
|
||||||
|
"endDate": "Date",
|
||||||
|
"executionTmStr": "String",
|
||||||
|
"status": "Integer",
|
||||||
|
"template": "String",
|
||||||
|
"createTm": "Date"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4 删除短信任务
|
||||||
|
- **接口地址**: `/smsTask/del/{id}`
|
||||||
|
- **请求方法**: `GET`
|
||||||
|
- **参数**:
|
||||||
|
- `id` (路径参数): Long
|
||||||
|
|
||||||
|
### 3.5 根据ID查询短信任务
|
||||||
|
- **接口地址**: `/smsTask/get/{id}`
|
||||||
|
- **请求方法**: `GET`
|
||||||
|
- **参数**:
|
||||||
|
- `id` (路径参数): Long
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 专家通讯录管理 (SpecialistController)
|
||||||
|
|
||||||
|
### 4.1 分页查询专家通讯录
|
||||||
|
- **接口地址**: `/specialist/page`
|
||||||
|
- **请求方法**: `POST`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "String",
|
||||||
|
"position": "String",
|
||||||
|
"birthday": "Date",
|
||||||
|
"title": "String",
|
||||||
|
"phone": "String",
|
||||||
|
"status": "Integer",
|
||||||
|
"createTm": "Date"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 新增专家通讯录
|
||||||
|
- **接口地址**: `/specialist/add`
|
||||||
|
- **请求方法**: `POST`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "String",
|
||||||
|
"position": "String",
|
||||||
|
"birthday": "Date",
|
||||||
|
"title": "String",
|
||||||
|
"phone": "String",
|
||||||
|
"status": "Integer",
|
||||||
|
"createTm": "Date"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 修改专家通讯录
|
||||||
|
- **接口地址**: `/specialist/edit`
|
||||||
|
- **请求方法**: `POST`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "Long",
|
||||||
|
"name": "String",
|
||||||
|
"position": "String",
|
||||||
|
"birthday": "Date",
|
||||||
|
"title": "String",
|
||||||
|
"phone": "String",
|
||||||
|
"status": "Integer",
|
||||||
|
"createTm": "Date"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4 删除专家通讯录
|
||||||
|
- **接口地址**: `/specialist/del/{id}`
|
||||||
|
- **请求方法**: `GET`
|
||||||
|
- **参数**:
|
||||||
|
- `id` (路径参数): Long
|
||||||
|
|
||||||
|
### 4.5 根据ID查询专家通讯录
|
||||||
|
- **接口地址**: `/specialist/get/{id}`
|
||||||
|
- **请求方法**: `GET`
|
||||||
|
- **参数**:
|
||||||
|
- `id` (路径参数): Long
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 说明
|
||||||
|
|
||||||
|
- 所有接口返回格式统一为 `ResultJson<T>`
|
||||||
|
- 参数验证使用 `@Validated` 注解,新增时使用 `Insert.class`,修改时使用 `Update.class`
|
||||||
|
- 生日短信管理模块特殊处理,只维护单条记录 (ID=1)
|
||||||
|
- 文档生成时间: 2025-09-23
|
||||||
7
pom.xml
7
pom.xml
|
|
@ -260,6 +260,13 @@
|
||||||
<artifactId>okhttp</artifactId>
|
<artifactId>okhttp</artifactId>
|
||||||
<version>4.12.0</version>
|
<version>4.12.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- spring boot test -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
-- 姓名,职务,生日,称呼,电话号码,生效状态,创建日期
|
||||||
|
|
||||||
|
-- 达梦数据库SPECIALIST表建表语句
|
||||||
|
CREATE TABLE SPECIALIST (
|
||||||
|
ID BIGINT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
NAME VARCHAR(50) NOT NULL COMMENT '姓名',
|
||||||
|
POSITION VARCHAR(100) COMMENT '职务',
|
||||||
|
BIRTHDAY DATE COMMENT '生日',
|
||||||
|
ADDRESS VARCHAR(20) COMMENT '区域',
|
||||||
|
PHONE VARCHAR(20) UNIQUE COMMENT '电话号码',
|
||||||
|
STATUS INT DEFAULT 1 COMMENT '生效状态 1:有效 0:无效',
|
||||||
|
CREATE_TM DATETIME DEFAULT CURRENT_TIME COMMENT '创建日期'
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--主题名称,任务开始日期,任务结束日期,任务执行时间,状态,创建日期,操作
|
||||||
|
--2025年国庆,2025-10-01,2025-10-03,08:00:00,有效,2025-09-15
|
||||||
|
--2026年春节,2026-02-17,2026-02-17,08:00:00,有效,2025-09-15
|
||||||
|
-- 达梦数据库TASK表建表语句
|
||||||
|
CREATE TABLE SMS_TASK (
|
||||||
|
ID BIGINT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
SUBJECT_NAME VARCHAR(200) NOT NULL COMMENT '主题名称',
|
||||||
|
START_DATE DATE COMMENT '任务开始日期',
|
||||||
|
END_DATE DATE COMMENT '任务结束日期',
|
||||||
|
EXECUTION_TM_STR VARCHAR(8) COMMENT '任务执行时间',
|
||||||
|
STATUS INT DEFAULT 1 COMMENT '状态 1:有效 0:无效',
|
||||||
|
TEMPLATE VARCHAR(500),
|
||||||
|
CREATE_TM DATETIME DEFAULT CURRENT_TIME COMMENT '创建日期'
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE SMS_BIRTHDAY (
|
||||||
|
ID BIGINT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
EXECUTION_TM_STR VARCHAR(8) COMMENT '任务执行时间',
|
||||||
|
STATUS INT DEFAULT 1 COMMENT '状态 1:有效 0:无效',
|
||||||
|
TEMPLATE VARCHAR(500)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE SMS_LOG (
|
||||||
|
ID BIGINT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
SEND_TM DATETIME NOT NULL COMMENT '发送时间',
|
||||||
|
NAME VARCHAR(50) NOT NULL COMMENT '姓名',
|
||||||
|
PHONE VARCHAR(20) COMMENT '电话号码',
|
||||||
|
REMARK VARCHAR(500) COMMENT '备注',
|
||||||
|
CONTENT VARCHAR(500) COMMENT '短信内容'
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.whdc.controller;
|
||||||
|
|
||||||
|
import com.whdc.model.entity.SmsBirthday;
|
||||||
|
import com.whdc.model.group.Insert;
|
||||||
|
import com.whdc.model.group.Update;
|
||||||
|
import com.whdc.service.ISmsBirthdayService;
|
||||||
|
import com.whdc.utils.ResultJson;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生日短信控制器
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
@Api(tags = "生日短信 - Controller")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/smsBirthday")
|
||||||
|
public class SmsBirthdayController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISmsBirthdayService smsBirthdayService;
|
||||||
|
|
||||||
|
private static final Long THE_ONLY_ONE = 1L;
|
||||||
|
|
||||||
|
@ApiOperation(value = "修改")
|
||||||
|
@PostMapping(value = "edit")
|
||||||
|
public ResultJson<Boolean> edit(@RequestBody @Validated(Update.class) SmsBirthday model) {
|
||||||
|
return ResultJson.ok(smsBirthdayService.updateById(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "查询")
|
||||||
|
@GetMapping(value = "get")
|
||||||
|
public ResultJson<SmsBirthday> getById() {
|
||||||
|
return ResultJson.ok(smsBirthdayService.getById(THE_ONLY_ONE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.whdc.controller;
|
||||||
|
|
||||||
|
import com.whdc.model.entity.SmsLog;
|
||||||
|
import com.whdc.model.group.Insert;
|
||||||
|
import com.whdc.model.group.Update;
|
||||||
|
import com.whdc.service.ISmsLogService;
|
||||||
|
import com.whdc.utils.ResultJson;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信日志控制器
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
@Api(tags = "短信日志 - Controller")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/smsLog")
|
||||||
|
public class SmsLogController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISmsLogService smsLogService;
|
||||||
|
|
||||||
|
@ApiOperation(value = "分页查询")
|
||||||
|
@PostMapping(value = "page")
|
||||||
|
public ResultJson<List<SmsLog>> page(@RequestBody SmsLog dto) {
|
||||||
|
return ResultJson.ok(smsLogService.list());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "新增")
|
||||||
|
@PostMapping(value = "add")
|
||||||
|
public ResultJson<Boolean> add(@RequestBody @Validated(Insert.class) SmsLog model) {
|
||||||
|
return ResultJson.ok(smsLogService.save(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "修改")
|
||||||
|
@PostMapping(value = "edit")
|
||||||
|
public ResultJson<Boolean> edit(@RequestBody @Validated(Update.class) SmsLog model) {
|
||||||
|
return ResultJson.ok(smsLogService.updateById(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "删除")
|
||||||
|
@GetMapping(value = "del/{id}")
|
||||||
|
public ResultJson<Boolean> delete(@PathVariable("id") Long id) {
|
||||||
|
return ResultJson.ok(smsLogService.removeById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "根据ID查询")
|
||||||
|
@GetMapping(value = "get/{id}")
|
||||||
|
public ResultJson<SmsLog> getById(@PathVariable("id") Long id) {
|
||||||
|
return ResultJson.ok(smsLogService.getById(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.whdc.controller;
|
||||||
|
|
||||||
|
import com.whdc.model.entity.SmsTask;
|
||||||
|
import com.whdc.model.group.Insert;
|
||||||
|
import com.whdc.model.group.Update;
|
||||||
|
import com.whdc.service.ISmsTaskService;
|
||||||
|
import com.whdc.utils.ResultJson;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信任务控制器
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
@Api(tags = "短信任务 - Controller")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/smsTask")
|
||||||
|
public class SmsTaskController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISmsTaskService smsTaskService;
|
||||||
|
|
||||||
|
@ApiOperation(value = "分页查询")
|
||||||
|
@PostMapping(value = "page")
|
||||||
|
public ResultJson<List<SmsTask>> page(@RequestBody SmsTask dto) {
|
||||||
|
return ResultJson.ok(smsTaskService.list());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "新增")
|
||||||
|
@PostMapping(value = "add")
|
||||||
|
public ResultJson<Boolean> add(@RequestBody @Validated(Insert.class) SmsTask model) {
|
||||||
|
return ResultJson.ok(smsTaskService.save(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "修改")
|
||||||
|
@PostMapping(value = "edit")
|
||||||
|
public ResultJson<Boolean> edit(@RequestBody @Validated(Update.class) SmsTask model) {
|
||||||
|
return ResultJson.ok(smsTaskService.updateById(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "删除")
|
||||||
|
@GetMapping(value = "del/{id}")
|
||||||
|
public ResultJson<Boolean> delete(@PathVariable("id") Long id) {
|
||||||
|
return ResultJson.ok(smsTaskService.removeById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "根据ID查询")
|
||||||
|
@GetMapping(value = "get/{id}")
|
||||||
|
public ResultJson<SmsTask> getById(@PathVariable("id") Long id) {
|
||||||
|
return ResultJson.ok(smsTaskService.getById(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.whdc.controller;
|
||||||
|
|
||||||
|
import com.whdc.model.entity.Specialist;
|
||||||
|
import com.whdc.model.group.Insert;
|
||||||
|
import com.whdc.model.group.Update;
|
||||||
|
import com.whdc.service.ISpecialistService;
|
||||||
|
import com.whdc.utils.ResultJson;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 专家通讯录控制器
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
@Api(tags = "专家通讯录 - Controller")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/specialist")
|
||||||
|
public class SpecialistController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISpecialistService specialistService;
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation(value = "分页查询")
|
||||||
|
@PostMapping(value = "page")
|
||||||
|
public ResultJson<List<Specialist>> page(@RequestBody Specialist dto) {
|
||||||
|
return ResultJson.ok(specialistService.list());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "新增")
|
||||||
|
@PostMapping(value = "add")
|
||||||
|
public ResultJson<Boolean> add(@RequestBody @Validated(Insert.class) Specialist model) {
|
||||||
|
return ResultJson.ok(specialistService.save(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "修改")
|
||||||
|
@PostMapping(value = "edit")
|
||||||
|
public ResultJson<Boolean> edit(@RequestBody @Validated(Update.class) Specialist model) {
|
||||||
|
return ResultJson.ok(specialistService.updateById(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "删除")
|
||||||
|
@GetMapping(value = "del/{id}")
|
||||||
|
public ResultJson<Boolean> delete(@PathVariable("id") Long id) {
|
||||||
|
return ResultJson.ok(specialistService.removeById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "根据ID查询")
|
||||||
|
@GetMapping(value = "get/{id}")
|
||||||
|
public ResultJson<Specialist> getById(@PathVariable("id") Long id) {
|
||||||
|
return ResultJson.ok(specialistService.getById(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.whdc.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.whdc.model.entity.SmsBirthday;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
public interface SmsBirthdayMapper extends BaseMapper<SmsBirthday> {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.whdc.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.whdc.model.entity.SmsLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信日志Mapper接口
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
public interface SmsLogMapper extends BaseMapper<SmsLog> {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.whdc.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.whdc.model.entity.SmsTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信任务Mapper接口
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
public interface SmsTaskMapper extends BaseMapper<SmsTask> {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.whdc.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.whdc.model.entity.Specialist;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 专家通讯录Mapper接口
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
public interface SpecialistMapper extends BaseMapper<Specialist> {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.whdc.model.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务实体类
|
||||||
|
*
|
||||||
|
* @author
|
||||||
|
* @date
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@ApiModel(description = "生日短信")
|
||||||
|
@TableName("SMS_BIRTHDAY")
|
||||||
|
public class SmsBirthday implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "ID", type = IdType.AUTO)
|
||||||
|
@ApiModelProperty(value = "主键ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务执行时间
|
||||||
|
* 例:08:00:00
|
||||||
|
*/
|
||||||
|
@TableField("EXECUTION_TM_STR")
|
||||||
|
@ApiModelProperty(value = "任务执行时间")
|
||||||
|
private String executionTmStr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 1:有效 0:无效
|
||||||
|
*/
|
||||||
|
@TableField("STATUS")
|
||||||
|
@ApiModelProperty(value = "状态 1:有效 0:无效")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板
|
||||||
|
*/
|
||||||
|
@TableField("TEMPLATE")
|
||||||
|
@ApiModelProperty(value = "模板")
|
||||||
|
private String template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建日期
|
||||||
|
*/
|
||||||
|
@TableField("CREATE_TM")
|
||||||
|
@ApiModelProperty(value = "创建日期")
|
||||||
|
private Date createTm;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.whdc.model.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信日志实体类
|
||||||
|
*
|
||||||
|
* @author
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@ApiModel(description = "短信日志")
|
||||||
|
@TableName("SMS_LOG")
|
||||||
|
public class SmsLog implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "ID", type = IdType.AUTO)
|
||||||
|
@ApiModelProperty(value = "主键ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送时间
|
||||||
|
*/
|
||||||
|
@TableField("SEND_TM")
|
||||||
|
@ApiModelProperty(value = "发送时间")
|
||||||
|
private Date sendTm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 姓名
|
||||||
|
*/
|
||||||
|
@TableField("NAME")
|
||||||
|
@ApiModelProperty(value = "姓名")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电话号码
|
||||||
|
*/
|
||||||
|
@TableField("PHONE")
|
||||||
|
@ApiModelProperty(value = "电话号码")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
@TableField("REMARK")
|
||||||
|
@ApiModelProperty(value = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信内容
|
||||||
|
*/
|
||||||
|
@TableField("CONTENT")
|
||||||
|
@ApiModelProperty(value = "短信内容")
|
||||||
|
private String content;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
package com.whdc.model.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务实体类
|
||||||
|
*
|
||||||
|
* @author
|
||||||
|
* @date
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@ApiModel(description = "节日短信")
|
||||||
|
@TableName("SMS_TASK")
|
||||||
|
public class SmsTask implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "ID", type = IdType.AUTO)
|
||||||
|
@ApiModelProperty(value = "主键ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主题名称
|
||||||
|
*/
|
||||||
|
@TableField("SUBJECT_NAME")
|
||||||
|
@ApiModelProperty(value = "主题名称")
|
||||||
|
private String subjectName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务开始日期
|
||||||
|
*/
|
||||||
|
@TableField("START_DATE")
|
||||||
|
@ApiModelProperty(value = "任务开始日期")
|
||||||
|
private Date startDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务结束日期
|
||||||
|
*/
|
||||||
|
@TableField("END_DATE")
|
||||||
|
@ApiModelProperty(value = "任务结束日期")
|
||||||
|
private Date endDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务执行时间
|
||||||
|
*/
|
||||||
|
@TableField("EXECUTION_TM_STR")
|
||||||
|
@ApiModelProperty(value = "任务执行时间")
|
||||||
|
private String executionTmStr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 1:有效 0:无效
|
||||||
|
*/
|
||||||
|
@TableField("STATUS")
|
||||||
|
@ApiModelProperty(value = "状态 1:有效 0:无效")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板
|
||||||
|
*/
|
||||||
|
@TableField("TEMPLATE")
|
||||||
|
@ApiModelProperty(value = "模板")
|
||||||
|
private String template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建日期
|
||||||
|
*/
|
||||||
|
@TableField("CREATE_TM")
|
||||||
|
@ApiModelProperty(value = "创建日期")
|
||||||
|
private Date createTm;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
package com.whdc.model.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author
|
||||||
|
* @date
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@ApiModel(description = "专家")
|
||||||
|
@TableName("SPECIALIST")
|
||||||
|
public class Specialist implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "ID", type = IdType.AUTO)
|
||||||
|
@ApiModelProperty(value = "主键ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 姓名
|
||||||
|
*/
|
||||||
|
@TableField("NAME")
|
||||||
|
@ApiModelProperty(value = "姓名")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 职务
|
||||||
|
*/
|
||||||
|
@TableField("POSITION")
|
||||||
|
@ApiModelProperty(value = "职务")
|
||||||
|
private String position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生日
|
||||||
|
*/
|
||||||
|
@TableField("BIRTHDAY")
|
||||||
|
@ApiModelProperty(value = "生日")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||||
|
private Date birthday;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 职位称呼
|
||||||
|
*/
|
||||||
|
@TableField("ADDRESS")
|
||||||
|
@ApiModelProperty(value = "区域")
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电话号码
|
||||||
|
*/
|
||||||
|
@TableField("PHONE")
|
||||||
|
@ApiModelProperty(value = "电话号码")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生效状态 1:有效 0:无效
|
||||||
|
*/
|
||||||
|
@TableField("STATUS")
|
||||||
|
@ApiModelProperty(value = "生效状态 1:有效 0:无效")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建日期
|
||||||
|
*/
|
||||||
|
@TableField("CREATE_TM")
|
||||||
|
@ApiModelProperty(value = "创建日期")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
private Date createTm;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.whdc.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.whdc.model.entity.SmsBirthday;
|
||||||
|
import com.whdc.model.entity.Specialist;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生日短信服务接口
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
public interface ISmsBirthdayService extends IService<SmsBirthday> {
|
||||||
|
/**
|
||||||
|
* 查询今天过生日专家
|
||||||
|
*/
|
||||||
|
List<Specialist> listBirthdayToday();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送生日短信
|
||||||
|
*/
|
||||||
|
void sendBirthdaySms(List<Specialist> specialists);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.whdc.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.whdc.model.entity.SmsLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信日志服务接口
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
public interface ISmsLogService extends IService<SmsLog> {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.whdc.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.whdc.model.entity.SmsTask;
|
||||||
|
import com.whdc.model.entity.Specialist;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主题日短信服务接口
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
public interface ISmsTaskService extends IService<SmsTask> {
|
||||||
|
/**
|
||||||
|
* 查询当前活动中的主题日短信任务
|
||||||
|
*/
|
||||||
|
List<SmsTask> listActiveTasks();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询需要执行的今日主题日任务
|
||||||
|
*/
|
||||||
|
List<SmsTask> listTodayTasks();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送主题日短信
|
||||||
|
*/
|
||||||
|
void sendThemeSms(SmsTask smsTask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量发送主题日短信
|
||||||
|
*/
|
||||||
|
void sendBatchThemeSms(List<SmsTask> smsTasks);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.whdc.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.whdc.model.entity.Specialist;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 专家通讯录服务接口
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
public interface ISpecialistService extends IService<Specialist> {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,241 @@
|
||||||
|
package com.whdc.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.whdc.mapper.SmsBirthdayMapper;
|
||||||
|
import com.whdc.mapper.SmsLogMapper;
|
||||||
|
import com.whdc.mapper.SpecialistMapper;
|
||||||
|
import com.whdc.model.entity.SmsBirthday;
|
||||||
|
import com.whdc.model.entity.SmsLog;
|
||||||
|
import com.whdc.model.entity.Specialist;
|
||||||
|
import com.whdc.service.ISmsBirthdayService;
|
||||||
|
import com.whdc.utils.SmsHelper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生日短信服务实现类
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class SmsBirthdayServiceImpl extends ServiceImpl<SmsBirthdayMapper, SmsBirthday> implements ISmsBirthdayService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SpecialistMapper specialistMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SmsLogMapper smsLogMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SmsHelper smsHelper;
|
||||||
|
|
||||||
|
// 记录今日是否已发送生日短信 - 使用原子变量保证线程安全
|
||||||
|
private final AtomicBoolean birthdaySmsSentToday = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Specialist> listBirthdayToday() {
|
||||||
|
try {
|
||||||
|
// 获取当前日期的月和日
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
String monthDay = today.format(DateTimeFormatter.ofPattern("MM-dd"));
|
||||||
|
|
||||||
|
// 查询今天过生日的专家(状态为有效的)
|
||||||
|
LambdaQueryWrapper<Specialist> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper
|
||||||
|
.apply("DATE_FORMAT(BIRTHDAY, '%m-%d') = {0}", monthDay)
|
||||||
|
.eq(Specialist::getStatus, 1); // 1:有效
|
||||||
|
|
||||||
|
List<Specialist> specialists = specialistMapper.selectList(queryWrapper);
|
||||||
|
return specialists != null ? specialists : Collections.emptyList();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 记录异常并返回空列表
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendBirthdaySms(List<Specialist> specialists) {
|
||||||
|
if (specialists == null || specialists.isEmpty()) {
|
||||||
|
log.info("没有需要发送生日短信的专家");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取生日短信模板
|
||||||
|
SmsBirthday smsBirthday = this.getById(1L); // 使用ID=1的记录
|
||||||
|
if (smsBirthday == null || smsBirthday.getStatus() != 1) {
|
||||||
|
log.warn("生日短信模板不存在或未启用");
|
||||||
|
return; // 模板不存在或未启用
|
||||||
|
}
|
||||||
|
|
||||||
|
String template = smsBirthday.getTemplate();
|
||||||
|
if (template == null || template.trim().isEmpty()) {
|
||||||
|
log.warn("生日短信模板内容为空");
|
||||||
|
return; // 模板内容为空
|
||||||
|
}
|
||||||
|
|
||||||
|
// 逐个发送个性化短信
|
||||||
|
int totalSpecialists = specialists.size();
|
||||||
|
log.info("开始向{}位专家发送生日短信", totalSpecialists);
|
||||||
|
|
||||||
|
for (int i = 0; i < specialists.size(); i++) {
|
||||||
|
Specialist specialist = specialists.get(i);
|
||||||
|
String content = template.replace("{姓名}", specialist.getName());
|
||||||
|
try {
|
||||||
|
log.info("正在发送第{}/{}位专家{}的生日短信", i + 1, totalSpecialists, specialist.getName());
|
||||||
|
|
||||||
|
// 创建短信日志记录
|
||||||
|
SmsLog smsLog = new SmsLog();
|
||||||
|
smsLog.setName(specialist.getName())
|
||||||
|
.setPhone(specialist.getPhone())
|
||||||
|
.setContent(content)
|
||||||
|
.setRemark("生日短信")
|
||||||
|
.setSendTm(new java.util.Date());
|
||||||
|
|
||||||
|
// 使用SmsHelper发送个性化短信
|
||||||
|
List<String> phoneList = Collections.singletonList(specialist.getPhone());
|
||||||
|
String sendResult = smsHelper.send(phoneList, content);
|
||||||
|
log.info("向专家{}发送生日短信结果: {}", specialist.getName(), sendResult);
|
||||||
|
|
||||||
|
// 根据发送结果设置备注
|
||||||
|
if ("发送成功".equals(sendResult)) {
|
||||||
|
smsLog.setRemark("生日短信-发送成功");
|
||||||
|
} else {
|
||||||
|
smsLog.setRemark("生日短信-发送失败: " + sendResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存短信日志记录
|
||||||
|
smsLogMapper.insert(smsLog);
|
||||||
|
|
||||||
|
// 如果不是最后一位专家,等待3秒再发送下一条
|
||||||
|
if (i < specialists.size() - 1) {
|
||||||
|
try {
|
||||||
|
log.info("等待3秒后发送下一条短信...");
|
||||||
|
Thread.sleep(3000); // 3秒间隔
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
log.warn("生日短信发送间隔被中断");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("向专家{}发送生日短信时发生异常: {}", specialist.getName(), e.getMessage(), e);
|
||||||
|
|
||||||
|
// 即使发送失败,也保存短信记录
|
||||||
|
try {
|
||||||
|
SmsLog failedSmsLog = new SmsLog();
|
||||||
|
failedSmsLog.setName(specialist.getName())
|
||||||
|
.setPhone(specialist.getPhone())
|
||||||
|
.setContent(content)
|
||||||
|
.setRemark("生日短信-发送异常: " + e.getMessage())
|
||||||
|
.setSendTm(new java.util.Date());
|
||||||
|
smsLogMapper.insert(failedSmsLog);
|
||||||
|
} catch (Exception logException) {
|
||||||
|
log.error("保存发送失败的短信日志时发生异常: {}", logException.getMessage(), logException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("生日短信批量发送任务完成");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时检查并发送生日短信
|
||||||
|
* 每分钟执行一次
|
||||||
|
*/
|
||||||
|
@Scheduled(cron = "0 * * * * ?")
|
||||||
|
public void checkAndSendBirthdaySms() {
|
||||||
|
try {
|
||||||
|
// 如果已经发送过,不再重复发送
|
||||||
|
if (birthdaySmsSentToday.get()) {
|
||||||
|
log.debug("今日已经发送过生日短信,跳过执行");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取生日短信配置
|
||||||
|
SmsBirthday smsBirthday = this.getById(1L);
|
||||||
|
if (smsBirthday == null || smsBirthday.getStatus() != 1) {
|
||||||
|
log.debug("生日短信功能未启用");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查执行时间
|
||||||
|
String executionTime = smsBirthday.getExecutionTmStr();
|
||||||
|
if (executionTime == null || executionTime.trim().isEmpty()) {
|
||||||
|
log.warn("生日短信执行时间未配置");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前时间
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 将执行时间字符串与当前日期拼接
|
||||||
|
String todayWithExecutionTime = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " " + executionTime;
|
||||||
|
|
||||||
|
// 解析为完整的LocalDateTime
|
||||||
|
LocalDateTime scheduledTime = LocalDateTime.parse(
|
||||||
|
todayWithExecutionTime,
|
||||||
|
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
|
||||||
|
);
|
||||||
|
|
||||||
|
// 检查当前时间是否大于等于执行时间
|
||||||
|
if (now.isEqual(scheduledTime) || now.isAfter(scheduledTime)) {
|
||||||
|
// 原子性检查和设置发送状态
|
||||||
|
if (birthdaySmsSentToday.compareAndSet(false, true)) {
|
||||||
|
log.info("到达生日短信发送时间: {}, 开始执行发送任务", executionTime);
|
||||||
|
|
||||||
|
// 查询今天过生日的专家
|
||||||
|
List<Specialist> birthdaySpecialists = listBirthdayToday();
|
||||||
|
|
||||||
|
if (birthdaySpecialists.isEmpty()) {
|
||||||
|
log.info("今天没有专家过生日,无需发送生日短信");
|
||||||
|
} else {
|
||||||
|
log.info("今天有{}位专家过生日,开始发送生日短信", birthdaySpecialists.size());
|
||||||
|
|
||||||
|
// 发送生日短信
|
||||||
|
sendBirthdaySms(birthdaySpecialists);
|
||||||
|
log.info("生日短信发送任务完成");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.debug("其他线程正在执行生日短信发送任务");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.debug("当前时间{}未到执行时间{}", now.format(DateTimeFormatter.ofPattern("HH:mm:ss")), executionTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("执行时间格式解析失败: {}", executionTime, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("定时检查生日短信任务执行异常: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置每日发送状态
|
||||||
|
* 每天凌晨00:00:01执行
|
||||||
|
*/
|
||||||
|
@Scheduled(cron = "1 0 0 * * ?")
|
||||||
|
public void resetDailySendStatus() {
|
||||||
|
try {
|
||||||
|
birthdaySmsSentToday.set(false);
|
||||||
|
log.info("生日短信每日发送状态已重置");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("重置生日短信每日发送状态异常: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.whdc.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.whdc.mapper.SmsLogMapper;
|
||||||
|
import com.whdc.model.entity.SmsLog;
|
||||||
|
import com.whdc.service.ISmsLogService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信日志服务实现类
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class SmsLogServiceImpl extends ServiceImpl<SmsLogMapper, SmsLog> implements ISmsLogService {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,289 @@
|
||||||
|
package com.whdc.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.whdc.mapper.SmsLogMapper;
|
||||||
|
import com.whdc.mapper.SmsTaskMapper;
|
||||||
|
import com.whdc.mapper.SpecialistMapper;
|
||||||
|
import com.whdc.model.entity.SmsLog;
|
||||||
|
import com.whdc.model.entity.SmsTask;
|
||||||
|
import com.whdc.model.entity.Specialist;
|
||||||
|
import com.whdc.service.ISmsTaskService;
|
||||||
|
import com.whdc.utils.SmsHelper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主题日短信服务实现类
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class SmsTaskServiceImpl extends ServiceImpl<SmsTaskMapper, SmsTask> implements ISmsTaskService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SpecialistMapper specialistMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SmsLogMapper smsLogMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SmsHelper smsHelper;
|
||||||
|
|
||||||
|
// 记录每个任务今日是否已发送短信 - 使用并发Map保证线程安全
|
||||||
|
private final Map<Long, AtomicBoolean> taskSmsSentToday = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SmsTask> listActiveTasks() {
|
||||||
|
try {
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
|
||||||
|
// 查询当前活动中的主题日短信任务
|
||||||
|
LambdaQueryWrapper<SmsTask> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper
|
||||||
|
.eq(SmsTask::getStatus, 1) // 1:有效
|
||||||
|
.le(SmsTask::getStartDate, today) // 开始日期小于等于今天
|
||||||
|
.ge(SmsTask::getEndDate, today); // 结束日期大于等于今天
|
||||||
|
|
||||||
|
List<SmsTask> tasks = this.list(queryWrapper);
|
||||||
|
return tasks != null ? tasks : Collections.emptyList();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询活动中的主题日短信任务失败: {}", e.getMessage(), e);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SmsTask> listTodayTasks() {
|
||||||
|
try {
|
||||||
|
// 获取当前活动中的任务
|
||||||
|
List<SmsTask> activeTasks = listActiveTasks();
|
||||||
|
if (activeTasks.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
List<SmsTask> todayTasks = new java.util.ArrayList<>();
|
||||||
|
|
||||||
|
// 筛选今天需要执行的任务
|
||||||
|
for (SmsTask task : activeTasks) {
|
||||||
|
// 检查是否已经发送过
|
||||||
|
AtomicBoolean sentFlag = taskSmsSentToday.computeIfAbsent(task.getId(), k -> new AtomicBoolean(false));
|
||||||
|
if (sentFlag.get()) {
|
||||||
|
continue; // 今日已发送,跳过
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查执行时间
|
||||||
|
String executionTime = task.getExecutionTmStr();
|
||||||
|
if (executionTime == null || executionTime.trim().isEmpty()) {
|
||||||
|
log.warn("主题日任务{}执行时间未配置", task.getSubjectName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查当前时间是否达到执行时间
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
try {
|
||||||
|
String todayWithExecutionTime = today.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " " + executionTime;
|
||||||
|
LocalDateTime scheduledTime = LocalDateTime.parse(
|
||||||
|
todayWithExecutionTime,
|
||||||
|
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
|
||||||
|
);
|
||||||
|
|
||||||
|
if (now.isEqual(scheduledTime) || now.isAfter(scheduledTime)) {
|
||||||
|
todayTasks.add(task);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("主题日任务{}执行时间格式解析失败: {}", task.getSubjectName(), executionTime, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return todayTasks;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询今日主题日任务失败: {}", e.getMessage(), e);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendThemeSms(SmsTask smsTask) {
|
||||||
|
if (smsTask == null) {
|
||||||
|
log.warn("主题日短信任务为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取所有有效专家
|
||||||
|
List<Specialist> specialists = getValidSpecialists();
|
||||||
|
if (specialists.isEmpty()) {
|
||||||
|
log.info("没有有效专家,跳过主题日短信发送");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String template = smsTask.getTemplate();
|
||||||
|
if (template == null || template.trim().isEmpty()) {
|
||||||
|
log.warn("主题日任务{}模板内容为空", smsTask.getSubjectName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 逐个发送个性化短信
|
||||||
|
int totalSpecialists = specialists.size();
|
||||||
|
log.info("开始向{}位专家发送主题日短信[{}]", totalSpecialists, smsTask.getSubjectName());
|
||||||
|
|
||||||
|
for (int i = 0; i < specialists.size(); i++) {
|
||||||
|
Specialist specialist = specialists.get(i);
|
||||||
|
// 替换模板中的占位符
|
||||||
|
String content = template.replace("{姓名}", specialist.getName())
|
||||||
|
.replace("{主题}", smsTask.getSubjectName());
|
||||||
|
try {
|
||||||
|
log.info("正在发送第{}/{}位专家{}的主题日短信", i + 1, totalSpecialists, specialist.getName());
|
||||||
|
|
||||||
|
// 创建短信日志记录
|
||||||
|
SmsLog smsLog = new SmsLog();
|
||||||
|
smsLog.setName(specialist.getName())
|
||||||
|
.setPhone(specialist.getPhone())
|
||||||
|
.setContent(content)
|
||||||
|
.setRemark("主题日短信-" + smsTask.getSubjectName())
|
||||||
|
.setSendTm(new java.util.Date());
|
||||||
|
|
||||||
|
// 使用SmsHelper发送个性化短信
|
||||||
|
List<String> phoneList = Collections.singletonList(specialist.getPhone());
|
||||||
|
String sendResult = smsHelper.send(phoneList, content);
|
||||||
|
log.info("向专家{}发送主题日短信[{}]结果: {}", specialist.getName(), smsTask.getSubjectName(), sendResult);
|
||||||
|
|
||||||
|
// 根据发送结果设置备注
|
||||||
|
if ("发送成功".equals(sendResult)) {
|
||||||
|
smsLog.setRemark("主题日短信-" + smsTask.getSubjectName() + "-发送成功");
|
||||||
|
} else {
|
||||||
|
smsLog.setRemark("主题日短信-" + smsTask.getSubjectName() + "-发送失败: " + sendResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存短信日志记录
|
||||||
|
smsLogMapper.insert(smsLog);
|
||||||
|
|
||||||
|
// 如果不是最后一位专家,等待3秒再发送下一条
|
||||||
|
if (i < specialists.size() - 1) {
|
||||||
|
try {
|
||||||
|
log.info("等待3秒后发送下一条短信...");
|
||||||
|
Thread.sleep(3000); // 3秒间隔
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
log.warn("短信发送间隔被中断");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("向专家{}发送主题日短信[{}]时发生异常: {}", specialist.getName(), smsTask.getSubjectName(), e.getMessage(), e);
|
||||||
|
|
||||||
|
// 即使发送失败,也保存短信记录
|
||||||
|
try {
|
||||||
|
SmsLog failedSmsLog = new SmsLog();
|
||||||
|
failedSmsLog.setName(specialist.getName())
|
||||||
|
.setPhone(specialist.getPhone())
|
||||||
|
.setContent(content)
|
||||||
|
.setRemark("主题日短信-" + smsTask.getSubjectName() + "-发送异常: " + e.getMessage())
|
||||||
|
.setSendTm(new java.util.Date());
|
||||||
|
smsLogMapper.insert(failedSmsLog);
|
||||||
|
} catch (Exception logException) {
|
||||||
|
log.error("保存发送失败的短信日志时发生异常: {}", logException.getMessage(), logException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("主题日短信任务[{}]发送完成", smsTask.getSubjectName());
|
||||||
|
|
||||||
|
// 标记任务今日已发送
|
||||||
|
AtomicBoolean sentFlag = taskSmsSentToday.computeIfAbsent(smsTask.getId(), k -> new AtomicBoolean(false));
|
||||||
|
sentFlag.set(true);
|
||||||
|
log.info("主题日短信任务[{}]发送完成", smsTask.getSubjectName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendBatchThemeSms(List<SmsTask> smsTasks) {
|
||||||
|
if (smsTasks == null || smsTasks.isEmpty()) {
|
||||||
|
log.info("没有需要发送的主题日短信任务");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("开始批量发送{}个主题日短信任务", smsTasks.size());
|
||||||
|
for (SmsTask task : smsTasks) {
|
||||||
|
try {
|
||||||
|
sendThemeSms(task);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("发送主题日短信任务[{}]失败: {}", task.getSubjectName(), e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("批量主题日短信任务发送完成");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有有效专家
|
||||||
|
*/
|
||||||
|
private List<Specialist> getValidSpecialists() {
|
||||||
|
try {
|
||||||
|
LambdaQueryWrapper<Specialist> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(Specialist::getStatus, 1); // 1:有效
|
||||||
|
queryWrapper.isNotNull(Specialist::getPhone); // 手机号不为空
|
||||||
|
|
||||||
|
List<Specialist> specialists = specialistMapper.selectList(queryWrapper);
|
||||||
|
return specialists != null ? specialists : Collections.emptyList();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询有效专家失败: {}", e.getMessage(), e);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时检查并发送主题日短信
|
||||||
|
* 每分钟执行一次
|
||||||
|
*/
|
||||||
|
@Scheduled(cron = "0 * * * * ?")
|
||||||
|
public void checkAndSendThemeSms() {
|
||||||
|
try {
|
||||||
|
// 查询今日需要执行的主题日任务
|
||||||
|
List<SmsTask> todayTasks = listTodayTasks();
|
||||||
|
|
||||||
|
if (todayTasks.isEmpty()) {
|
||||||
|
log.debug("今日没有需要执行的主题日短信任务");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("检测到{}个主题日短信任务需要执行", todayTasks.size());
|
||||||
|
|
||||||
|
// 批量发送主题日短信
|
||||||
|
sendBatchThemeSms(todayTasks);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("定时检查主题日短信任务执行异常: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置每日发送状态
|
||||||
|
* 每天凌晨00:00:01执行
|
||||||
|
*/
|
||||||
|
@Scheduled(cron = "1 0 0 * * ?")
|
||||||
|
public void resetDailySendStatus() {
|
||||||
|
try {
|
||||||
|
// 重置所有任务的发送状态
|
||||||
|
for (AtomicBoolean sentFlag : taskSmsSentToday.values()) {
|
||||||
|
sentFlag.set(false);
|
||||||
|
}
|
||||||
|
log.info("主题日短信每日发送状态已重置");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("重置主题日短信每日发送状态异常: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.whdc.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.whdc.mapper.SpecialistMapper;
|
||||||
|
import com.whdc.model.entity.Specialist;
|
||||||
|
import com.whdc.service.ISpecialistService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 专家通讯录服务实现类
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-23
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class SpecialistServiceImpl extends ServiceImpl<SpecialistMapper, Specialist> implements ISpecialistService {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
package com.whdc.service.impl;
|
||||||
|
|
||||||
|
import com.whdc.model.entity.Specialist;
|
||||||
|
import com.whdc.utils.SmsHelper;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生日短信服务测试类 - 使用dev profile
|
||||||
|
*
|
||||||
|
* @author lyf
|
||||||
|
* @since 2025-09-25
|
||||||
|
*/
|
||||||
|
@SpringBootTest(classes = com.whdc.FxkhTxlApiApplication.class)
|
||||||
|
@ActiveProfiles("dev")
|
||||||
|
public class BirthdaySmsServiceTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SmsHelper smsHelper;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSendBirthdaySms() {
|
||||||
|
System.out.println("=== 开始测试生日短信发送功能 ===");
|
||||||
|
|
||||||
|
// 创建测试专家数据
|
||||||
|
Specialist specialist = new Specialist();
|
||||||
|
specialist.setName("李");
|
||||||
|
specialist.setPhone("15671545233");
|
||||||
|
specialist.setStatus(1);
|
||||||
|
|
||||||
|
List<Specialist> specialists = Arrays.asList(specialist);
|
||||||
|
|
||||||
|
System.out.println("专家信息:");
|
||||||
|
System.out.println("姓名:" + specialist.getName());
|
||||||
|
System.out.println("电话:" + specialist.getPhone());
|
||||||
|
System.out.println("模板:{姓名},测试短信接口");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 直接使用你提供的模板内容测试发送逻辑
|
||||||
|
String template = "{姓名},测试短信接口";
|
||||||
|
System.out.println("使用模板:" + template);
|
||||||
|
|
||||||
|
// 调用内部方法进行测试
|
||||||
|
testSendWithTemplate(specialists, template);
|
||||||
|
|
||||||
|
System.out.println("=== 生日短信发送测试完成!===");
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("测试过程中发生异常:" + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用指定模板测试发送短信
|
||||||
|
*/
|
||||||
|
private void testSendWithTemplate(List<Specialist> specialists, String template) {
|
||||||
|
System.out.println("开始使用模板发送短信...");
|
||||||
|
|
||||||
|
for (Specialist specialist : specialists) {
|
||||||
|
try {
|
||||||
|
// 替换模板中的占位符
|
||||||
|
String content = template.replace("{姓名}", specialist.getName());
|
||||||
|
System.out.println("生成的短信内容:" + content);
|
||||||
|
|
||||||
|
// 使用SmsHelper发送个性化短信
|
||||||
|
List<String> phoneList = Collections.singletonList(specialist.getPhone());
|
||||||
|
String sendResult = smsHelper.send(phoneList, content);
|
||||||
|
|
||||||
|
System.out.println("向专家" + specialist.getName() + "发送生日短信结果: " + sendResult);
|
||||||
|
System.out.println("短信发送完成,结果:" + sendResult);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("向专家" + specialist.getName() + "发送生日短信时发生异常: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue