本接口提供一键重置功能,可以将商户状态退回到刚注册时的初始状态,清理所有入住申请、订单、优惠券、验券、消息等相关数据。适用于测试环境或商户需要重新申请入住的场景。
POST /merchantUser/resetToInitialStatus在商户申请入住及业务运营时,系统会进行以下数据变更:
重置接口会清理以上所有数据,恢复到刚注册状态。
┌─────────────────────────────────────────────┐
│ 1. 获取当前登录用户 │
│ userId = LoginUserUtil.getCurrentUserId() │
│ storeUser = selectById(userId) │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 2. 检查是否有关联店铺 │
│ IF storeId == null │
│ 返回成功(无需重置) │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 3. 删除店铺图片 │
│ DELETE FROM store_img │
│ WHERE store_id = ? AND img_type IN (14,15,25)│
│ - 14: 营业执照 │
│ - 15: 合同图片 │
│ - 25: 经营许可证 │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 4. 删除店铺标签关系 │
│ DELETE FROM tag_store_relation │
│ WHERE store_id = ? │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 5. 删除店铺信息 │
│ DELETE FROM store_info │
│ WHERE id = ? │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 6. 清理入住申请通知 │
│ DELETE FROM life_notice │
│ WHERE receiver_id = 'store_手机号' │
│ AND title = '入住店铺申请' │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 7. 查询该店铺的所有订单ID │
│ SELECT id FROM life_user_order │
│ WHERE store_id = ? │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 8. 删除订单-优惠券中间表(验券记录) │
│ DELETE FROM order_coupon_middle │
│ WHERE order_id IN (订单ID列表) │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 9. 删除该店铺的所有订单记录 │
│ DELETE FROM life_user_order │
│ WHERE store_id = ? │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 10. 删除该店铺发布的团购券 │
│ DELETE FROM life_coupon │
│ WHERE store_id = ? │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 11. 删除该店铺发布的代金券 │
│ DELETE FROM life_discount_coupon │
│ WHERE store_id = ? │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 12. 删除用户领取的优惠券 │
│ DELETE FROM life_discount_coupon_user │
│ WHERE user_id = ? │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 13. 清理所有通知消息 │
│ DELETE FROM life_notice │
│ WHERE receiver_id = 'store_手机号' │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 14. 重置用户信息 │
│ UPDATE store_user SET │
│ store_id = NULL, │
│ name = NULL, │
│ id_card = NULL │
│ WHERE id = ? │
└─────────────────┬───────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 15. 返回结果 │
│ 返回成功:"已退回到刚注册状态" │
└─────────────────────────────────────────────┘
无参数
从 JWT token 自动获取当前登录用户的 userId。
POST /merchantUser/resetToInitialStatus
Headers:
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
curl -X POST "http://localhost:8080/merchantUser/resetToInitialStatus" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json"
{
"code": 200,
"success": true,
"data": true,
"msg": "重置成功,已退回到刚注册状态"
}
| 字段名 | 类型 | 说明 |
|---|---|---|
| code | Integer | 状态码(200-成功) |
| success | Boolean | 是否成功 |
| data | Boolean | 重置结果(true-成功) |
| msg | String | 提示信息 |
{
"code": 500,
"success": false,
"data": null,
"msg": "请先登录"
}
{
"code": 500,
"success": false,
"data": null,
"msg": "重置失败:用户不存在"
}
{
"code": 500,
"success": false,
"data": null,
"msg": "重置失败:{异常信息}"
}
DELETE FROM store_img
WHERE store_id = ?
AND img_type IN (14, 15, 25)
img_type 说明:
14: 营业执照图片15: 合同图片25: 经营许可证图片DELETE FROM tag_store_relation
WHERE store_id = ?
DELETE FROM store_info
WHERE id = ?
影响范围:
DELETE FROM life_notice
WHERE receiver_id = ?
AND title = '入住店铺申请'
receiver_id 格式: store_{手机号}
SELECT id
FROM life_user_order
WHERE store_id = ?
用途: 获取订单ID列表,用于后续删除验券记录
DELETE FROM order_coupon_middle
WHERE order_id IN (订单ID列表)
说明:
order_coupon_middle 表没有 store_id 字段order_id 关联删除DELETE FROM life_user_order
WHERE store_id = ?
影响范围:
DELETE FROM life_coupon
WHERE store_id = ?
影响范围:
DELETE FROM life_discount_coupon
WHERE store_id = ?
影响范围:
DELETE FROM life_discount_coupon_user
WHERE user_id = ?
说明: 删除商户用户本人领取的优惠券
DELETE FROM life_notice
WHERE receiver_id = ?
receiver_id 格式: store_{手机号}
影响范围:
UPDATE store_user
SET store_id = NULL,
name = NULL,
id_card = NULL,
alipay_account = NULL
WHERE id = ?
技术实现:
// 使用 LambdaUpdateWrapper 显式设置为 null
LambdaUpdateWrapper<StoreUser> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(StoreUser::getId, userId)
.set(StoreUser::getStoreId, null)
.set(StoreUser::getName, null)
.set(StoreUser::getIdCard, null)
.set(StoreUser::getAlipayAccount, null);
storeUserMapper.update(null, updateWrapper);
为什么不能用 updateById?
updateById(entity) 默认会忽略 null 值UpdateWrapper.set() 显式设置为 nullupdate(null, wrapper) 来执行更新字段说明:
store_id: 解绑店铺关联name: 清空联系人姓名(入住时填写)id_card: 清空身份证号(入住时填写)alipay_account: 清空支付宝账号(入住时填写)保留字段:
phone: 手机号(注册信息)head_img: 头像money: 账户余额pay_password: 支付密码前置条件:
请求:
POST /merchantUser/resetToInitialStatus
Headers:
Authorization: Bearer VALID_TOKEN
响应:
{
"code": 200,
"success": true,
"data": true,
"msg": "重置成功,已退回到刚注册状态"
}
数据库变化:
前置条件:
请求:
POST /merchantUser/resetToInitialStatus
Headers:
Authorization: Bearer VALID_TOKEN
响应:
{
"code": 200,
"success": true,
"data": true,
"msg": "重置成功,已退回到刚注册状态"
}
说明: 用户未关联店铺,无需清理,直接返回成功。
请求:
POST /merchantUser/resetToInitialStatus
响应:
{
"code": 500,
"success": false,
"data": null,
"msg": "请先登录"
}
export default {
methods: {
async resetToInitialStatus() {
// 1. 确认提示
const confirmed = await this.$confirm(
'此操作将删除所有入住申请数据,恢复到刚注册状态,是否继续?',
'确认重置',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).catch(() => false);
if (!confirmed) {
return;
}
// 2. 发送请求
try {
const response = await this.$axios.post('/merchantUser/resetToInitialStatus');
if (response.data.success) {
this.$message.success('重置成功');
// 刷新页面或跳转
this.$router.push('/register-success');
} else {
this.$message.error(response.data.msg);
}
} catch (error) {
console.error('重置失败:', error);
this.$message.error('重置失败,请稍后重试');
}
}
}
}
import { useState } from 'react';
import axios from 'axios';
import { Modal } from 'antd';
function ResetButton() {
const [loading, setLoading] = useState(false);
const handleReset = () => {
Modal.confirm({
title: '确认重置',
content: '此操作将删除所有入住申请数据,恢复到刚注册状态,是否继续?',
okText: '确定',
cancelText: '取消',
okType: 'danger',
onOk: async () => {
setLoading(true);
try {
const response = await axios.post('/merchantUser/resetToInitialStatus');
if (response.data.success) {
alert('重置成功');
// 刷新或跳转
window.location.href = '/register-success';
} else {
alert(response.data.msg);
}
} catch (error) {
console.error('重置失败:', error);
alert('重置失败,请稍后重试');
} finally {
setLoading(false);
}
}
});
};
return (
<button onClick={handleReset} disabled={loading}>
{loading ? '重置中...' : '重置到刚注册状态'}
</button>
);
}
前置条件:
执行步骤:
预期结果:
前置条件:
执行步骤:
预期结果:
前置条件:
执行步骤:
预期结果:
答案:
答案: 不会。账户余额、支付密码等财务相关信息不受影响。
updateById 无法将字段设置为 null?答案:
updateById(entity) 默认会忽略 null 值LambdaUpdateWrapper.set(field, null) 显式设置✅ 正确用法:
LambdaUpdateWrapper<StoreUser> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(StoreUser::getId, userId)
.set(StoreUser::getStoreId, null)
.set(StoreUser::getName, null);
storeUserMapper.update(null, wrapper);
答案: 可以。重置后用户状态恢复到刚注册时,可以重新提交入住申请。
答案: 支持。使用 @Transactional 注解,任何异常都会导致所有操作回滚。
答案: 不会自动清理。如需清理 Redis 数据,需要额外调用相关清理接口。
答案: 不会。第一次重置后,storeId 已为空,后续重置会直接返回成功,不会执行删除操作。
答案:
@Transactional 保证原子性updateById 设置 null 值LambdaUpdateWrapper.set(field, null)update(null, wrapper) 执行更新// 前端实现二次确认
const confirmed = await this.$confirm('确认重置?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
});
// 建议记录重置操作日志
OperationLog log = new OperationLog();
log.setUserId(userId);
log.setOperation("RESET_TO_INITIAL_STATUS");
log.setDetails("重置商户到刚注册状态");
log.setIp(request.getRemoteAddr());
operationLogMapper.insert(log);
// 生产环境建议添加角色限制
@PreAuthorize("hasRole('ADMIN') or hasRole('TEST_USER')")
public boolean resetToInitialStatus()
| 表名 | 清理条件 | 说明 |
|---|---|---|
| store_info | id = storeId | 店铺信息 |
| store_img | store_id = storeId AND img_type IN (14,15,25) | 入住图片 |
| tag_store_relation | store_id = storeId | 店铺标签 |
| life_notice | receiverid = 'store{phone}' | 所有通知消息 |
| life_user_order | store_id = storeId | 所有订单记录 |
| order_coupon_middle | order_id IN (订单ID列表) | 验券记录 |
| life_coupon | store_id = storeId | 团购券 |
| life_discount_coupon | store_id = storeId | 代金券 |
| life_discount_coupon_user | user_id = userId | 用户优惠券 |
| store_user | store_id/name/id_card/alipay_account 设为NULL | 解绑并清空 |
| 表名 | 保留字段 | 说明 |
|---|---|---|
| store_user | phone | 手机号 |
| store_user | head_img | 头像 |
| store_user | money | 账户余额 |
| store_user | pay_password | 支付密码 |
| Redis | geo:stores | 地理位置(需手动清理) |
Bug 修复:
updateById 无法将字段设置为 null 的问题LambdaUpdateWrapper.set(field, null) 显式设置功能优化:
技术说明:
// ❌ 错误用法(不生效)
StoreUser user = new StoreUser();
user.setId(userId);
user.setStoreId(null);
storeUserMapper.updateById(user); // null 值会被忽略
// ✅ 正确用法
LambdaUpdateWrapper<StoreUser> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(StoreUser::getId, userId)
.set(StoreUser::getStoreId, null); // 显式设置为 null
storeUserMapper.update(null, wrapper);
功能增强:
清理范围扩展:
技术优化:
新增接口:
POST /merchantUser/resetToInitialStatus - 重置商户到刚注册状态核心功能:
适用场景:
涉及文件:
MerchantUserController.java - 新增 resetToInitialStatus 接口MerchantUserService.java - 新增方法定义MerchantUserServiceImpl.java - 新增方法实现代码质量:
开发人员: ssk
文档版本: v1.2
最后更新: 2025-11-21
维护人员: ssk