本文档为 markAllNoticesAsRead 接口的最新版本,该接口已从使用Query参数改为使用DTO接收JSON请求体。
POST /notice/markAllNoticesAsRead使用 MarkAllNoticesReadDTO 作为请求体:
| 参数名 | 类型 | 必填 | 说明 | 示例值 |
|---|---|---|---|---|
| receiverId | String | 是 | 接收人ID(商户ID) | "store_18241052019" |
| noticeType | Integer | 否 | 通知类型 | 1 |
noticeType 说明:
0: 系统通知和订单提醒之外的类型1: 系统通知2: 订单提醒null: 标记所有类型的通知@Data
@ApiModel(description = "批量标记通知已读请求参数")
public class MarkAllNoticesReadDTO implements Serializable {
@ApiModelProperty(value = "接收人ID(商户ID)", required = true, example = "store_18241052019")
private String receiverId;
@ApiModelProperty(value = "通知类型(0-系统通知和订单提醒之外的类型,1-系统通知,2-订单提醒)。不传则标记所有类型", required = false, example = "1")
private Integer noticeType;
}
POST /notice/markAllNoticesAsRead
Content-Type: application/json
{
"receiverId": "store_18241052019"
}
curl -X POST "http://localhost:8080/notice/markAllNoticesAsRead" \
-H "Content-Type: application/json" \
-d '{
"receiverId": "store_18241052019"
}'
POST /notice/markAllNoticesAsRead
Content-Type: application/json
{
"receiverId": "store_18241052019",
"noticeType": 1
}
curl -X POST "http://localhost:8080/notice/markAllNoticesAsRead" \
-H "Content-Type: application/json" \
-d '{
"receiverId": "store_18241052019",
"noticeType": 1
}'
POST /notice/markAllNoticesAsRead
Content-Type: application/json
{
"receiverId": "store_18241052019",
"noticeType": 2
}
curl -X POST "http://localhost:8080/notice/markAllNoticesAsRead" \
-H "Content-Type: application/json" \
-d '{
"receiverId": "store_18241052019",
"noticeType": 2
}'
{
"code": 200,
"success": true,
"data": 15,
"msg": "批量标记已读成功,共标记 15 条通知"
}
| 字段名 | 类型 | 说明 |
|---|---|---|
| code | Integer | 状态码,200表示成功 |
| success | Boolean | 是否成功 |
| data | Integer | 被标记的通知数量 |
| msg | String | 提示信息 |
请求:
{
"receiverId": "store_18241052019",
"noticeType": 1
}
响应:
{
"code": 200,
"success": true,
"data": 15,
"msg": "批量标记已读成功,共标记 15 条通知"
}
请求:
{
"receiverId": "store_18241052019",
"noticeType": 1
}
响应:
{
"code": 200,
"success": true,
"data": 0,
"msg": "没有需要标记的通知"
}
说明: 当前用户该类型的通知已全部已读,或不存在该类型的通知。
请求:
{
"noticeType": 1
}
响应:
{
"code": 500,
"success": false,
"data": null,
"msg": "receiverId不能为空"
}
响应:
{
"code": 500,
"success": false,
"data": null,
"msg": "标记失败:{异常信息}"
}
┌─────────────────────────────────────────────┐
│ 1. 接收DTO参数 │
│ - receiverId (必填) │
│ - noticeType (可选) │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 2. 参数验证 │
│ IF receiverId == null OR receiverId.isEmpty()│
│ RETURN 错误:receiverId不能为空 │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 3. 构建查询条件 │
│ wrapper.eq("receiver_id", receiverId) │
│ wrapper.eq("is_read", 0) // 未读 │
│ IF noticeType != null │
│ wrapper.eq("notice_type", noticeType) │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 4. 查询符合条件的未读通知 │
│ List<LifeNotice> notices = selectList(wrapper)│
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 5. 批量更新为已读状态 │
│ updateWrapper.set("is_read", 1) │
│ updateWrapper.eq("receiver_id", receiverId) │
│ updateWrapper.eq("is_read", 0) │
│ IF noticeType != null │
│ updateWrapper.eq("notice_type", noticeType)│
│ int count = update(null, updateWrapper) │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 6. 返回结果 │
│ IF count > 0 │
│ RETURN "批量标记已读成功,共标记 {count} 条"│
│ ELSE │
│ RETURN "没有需要标记的通知" │
└─────────────────────────────────────────────┘
UPDATE life_notice
SET is_read = 1
WHERE receiver_id = ?
AND is_read = 0
AND notice_type = ? -- 如果指定了noticeType
export default {
methods: {
// 一键已读(所有类型)
async markAllAsRead() {
try {
const response = await this.$axios.post('/notice/markAllNoticesAsRead', {
receiverId: this.currentUserId
});
if (response.data.success) {
this.$message.success(response.data.msg);
// 刷新通知列表
this.fetchNoticeList();
} else {
this.$message.error(response.data.msg);
}
} catch (error) {
console.error('标记失败:', error);
this.$message.error('操作失败,请稍后重试');
}
},
// 标记指定类型的通知为已读
async markTypeAsRead(noticeType) {
try {
const response = await this.$axios.post('/notice/markAllNoticesAsRead', {
receiverId: this.currentUserId,
noticeType: noticeType
});
if (response.data.success) {
const count = response.data.data;
this.$message.success(`成功标记 ${count} 条通知为已读`);
this.fetchNoticeList();
}
} catch (error) {
console.error('标记失败:', error);
}
}
}
}
import { useState } from 'react';
import axios from 'axios';
import { message } from 'antd';
function NoticeComponent() {
const [userId, setUserId] = useState('store_18241052019');
// 一键已读(所有类型)
const markAllAsRead = async () => {
try {
const response = await axios.post('/notice/markAllNoticesAsRead', {
receiverId: userId
});
if (response.data.success) {
message.success(response.data.msg);
// 刷新列表
fetchNoticeList();
}
} catch (error) {
message.error('操作失败');
}
};
// 标记指定类型
const markTypeAsRead = async (noticeType) => {
try {
const response = await axios.post('/notice/markAllNoticesAsRead', {
receiverId: userId,
noticeType: noticeType
});
if (response.data.success) {
const count = response.data.data;
message.success(`成功标记 ${count} 条通知为已读`);
}
} catch (error) {
message.error('操作失败');
}
};
return (
<div>
<button onClick={markAllAsRead}>一键已读(全部)</button>
<button onClick={() => markTypeAsRead(1)}>标记系统通知已读</button>
<button onClick={() => markTypeAsRead(2)}>标记订单提醒已读</button>
</div>
);
}
// 使用jQuery
function markAllNoticesAsRead(receiverId, noticeType) {
$.ajax({
url: '/notice/markAllNoticesAsRead',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
receiverId: receiverId,
noticeType: noticeType
}),
success: function(response) {
if (response.success) {
alert(response.msg);
// 刷新通知列表
loadNoticeList();
} else {
alert('操作失败:' + response.msg);
}
},
error: function(xhr, status, error) {
alert('网络错误,请稍后重试');
}
});
}
// 使用原生Fetch API
async function markAllNoticesAsRead(receiverId, noticeType = null) {
try {
const response = await fetch('/notice/markAllNoticesAsRead', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
receiverId: receiverId,
noticeType: noticeType
})
});
const data = await response.json();
if (data.success) {
console.log('标记成功:', data.msg);
return data.data; // 返回标记的数量
} else {
console.error('标记失败:', data.msg);
return 0;
}
} catch (error) {
console.error('请求失败:', error);
return 0;
}
}
// 使用示例
markAllNoticesAsRead('store_18241052019'); // 标记所有类型
markAllNoticesAsRead('store_18241052019', 1); // 只标记系统通知
@PostMapping("/markAllNoticesAsRead")
public R<Integer> markAllNoticesAsRead(
@RequestParam("receiverId") String receiverId,
@RequestParam(value = "noticeType", required = false) Integer noticeType
)
请求方式:
POST /notice/markAllNoticesAsRead?receiverId=store_18241052019¬iceType=1
@PostMapping("/markAllNoticesAsRead")
public R<Integer> markAllNoticesAsRead(@RequestBody MarkAllNoticesReadDTO dto)
请求方式:
POST /notice/markAllNoticesAsRead
Content-Type: application/json
{
"receiverId": "store_18241052019",
"noticeType": 1
}
| 项目 | 旧版本 | 新版本 | 说明 |
|---|---|---|---|
| 参数传递方式 | Query参数 | JSON Body | 更符合RESTful规范 |
| 参数定义 | 直接在方法参数中 | 使用DTO | 更易维护和扩展 |
| Content-Type | application/x-www-form-urlencoded | application/json | 标准JSON格式 |
| Swagger文档 | @ApiImplicitParams | @ApiModel/@ApiModelProperty | 自动生成完整文档 |
| 参数验证 | 手动验证 | 可使用@Valid + 验证注解 | 更规范 |
| 可扩展性 | 低 | 高 | 新增参数只需修改DTO |
如果需要更严格的参数验证,可以在DTO中添加验证注解:
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Min;
import javax.validation.constraints.Max;
@Data
@ApiModel(description = "批量标记通知已读请求参数")
public class MarkAllNoticesReadDTO implements Serializable {
@NotBlank(message = "接收人ID不能为空")
@ApiModelProperty(value = "接收人ID(商户ID)", required = true)
private String receiverId;
@Min(value = 0, message = "通知类型必须大于等于0")
@Max(value = 2, message = "通知类型必须小于等于2")
@ApiModelProperty(value = "通知类型", required = false)
private Integer noticeType;
}
然后在Controller中启用验证:
@PostMapping("/markAllNoticesAsRead")
public R<Integer> markAllNoticesAsRead(@RequestBody @Valid MarkAllNoticesReadDTO dto) {
// ...
}
答案:
答案: 不能。接口已改为使用JSON Body,必须按新的方式调用。
答案:
旧代码:
$.post('/notice/markAllNoticesAsRead?receiverId=' + userId + '¬iceType=1');
新代码:
$.ajax({
url: '/notice/markAllNoticesAsRead',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
receiverId: userId,
noticeType: 1
})
});
答案: 没有区别。不传或传null都表示标记所有类型的通知。
答案: data是被标记为已读的通知数量(Integer类型)。如果为0表示没有需要标记的通知。
请求:
{
"receiverId": "store_18241052019"
}
预期结果:
请求:
{
"receiverId": "store_18241052019",
"noticeType": 1
}
预期结果:
请求:
{
"noticeType": 1
}
预期结果:
前置条件:
请求:
{
"receiverId": "store_18241052019"
}
预期结果:
{
"code": 200,
"data": 0,
"msg": "没有需要标记的通知"
}
使用MyBatis-Plus的批量更新功能,一次SQL更新所有符合条件的记录:
UPDATE life_notice
SET is_read = 1
WHERE receiver_id = ?
AND is_read = 0
AND notice_type = ?
确保以下字段有索引:
-- 复合索引
ALTER TABLE life_notice
ADD INDEX idx_receiver_read_type (receiver_id, is_read, notice_type);
使用 update() 方法的返回值直接获取更新的记录数,避免额外查询。
⚠️ 必须设置 Content-Type: application/json,否则服务器无法解析JSON请求体。
⚠️ 请求体必须是有效的JSON格式,字段名需要与DTO中的字段名完全匹配。
⚠️ noticeType 是可选参数,不传或传null表示标记所有类型的通知。
⚠️ data 字段是Integer类型,表示被标记的数量,不是布尔值。
接口重构:
MarkAllNoticesReadDTO 类优势:
涉及文件:
MarkAllNoticesReadDTO.java - 新增NoticeController.java - 修改代码质量:
开发人员: ssk
文档版本: v2.0
最后更新: 2025-11-17
维护人员: ssk