Browse Source

add ApprovalController

reghao 1 week ago
parent
commit
40bca9739a
47 changed files with 756 additions and 450 deletions
  1. 1 0
      auth/auth-api/src/main/java/cn/reghao/tnb/auth/api/iface/AdminAccountService.java
  2. 0 8
      auth/auth-service/src/main/java/cn/reghao/tnb/auth/app/controller/AccountProfileController.java
  3. 0 19
      auth/auth-service/src/main/java/cn/reghao/tnb/auth/app/model/dto/GrantRole.java
  4. 8 1
      auth/auth-service/src/main/java/cn/reghao/tnb/auth/app/rpc/AdminAccountServiceImpl.java
  5. 0 17
      auth/auth-service/src/main/java/cn/reghao/tnb/auth/app/service/AccountProfileService.java
  6. 1 4
      content/content-service/src/main/java/cn/reghao/tnb/content/app/vod/service/AdminVodService.java
  7. 31 9
      file/file-service/src/test/java/ChatTest.java
  8. 2 1
      message/message-api/src/main/java/cn/reghao/tnb/message/api/constant/MsgType.java
  9. 10 2
      message/message-api/src/main/java/cn/reghao/tnb/message/api/dto/UserMessageDto.java
  10. 1 2
      message/message-service/src/main/java/cn/reghao/tnb/message/app/service/MessageConsumer.java
  11. 1 2
      message/message-service/src/main/java/cn/reghao/tnb/message/app/service/NotifyService.java
  12. 39 0
      user/user-api/src/main/java/cn/reghao/tnb/user/api/constant/UserApprovalAction.java
  13. 40 0
      user/user-api/src/main/java/cn/reghao/tnb/user/api/constant/UserApprovalStatus.java
  14. 39 0
      user/user-api/src/main/java/cn/reghao/tnb/user/api/constant/UserApprovalType.java
  15. 5 6
      user/user-api/src/main/java/cn/reghao/tnb/user/api/dto/UserApproval.java
  16. 0 22
      user/user-api/src/main/java/cn/reghao/tnb/user/api/dto/WalletChargeDto.java
  17. 1 0
      user/user-api/src/main/java/cn/reghao/tnb/user/api/iface/UserService.java
  18. 0 20
      user/user-api/src/main/java/cn/reghao/tnb/user/api/iface/UserWalletService.java
  19. 27 34
      user/user-service/src/main/java/cn/reghao/tnb/user/app/controller/AdminUserController.java
  20. 45 0
      user/user-service/src/main/java/cn/reghao/tnb/user/app/controller/ApprovalController.java
  21. 6 19
      user/user-service/src/main/java/cn/reghao/tnb/user/app/controller/UserWalletController.java
  22. 16 0
      user/user-service/src/main/java/cn/reghao/tnb/user/app/db/mapper/ApprovalHistoryMapper.java
  23. 21 0
      user/user-service/src/main/java/cn/reghao/tnb/user/app/db/mapper/ApprovalRequestMapper.java
  24. 2 1
      user/user-service/src/main/java/cn/reghao/tnb/user/app/db/mapper/WalletBillMapper.java
  25. 0 21
      user/user-service/src/main/java/cn/reghao/tnb/user/app/db/mapper/WalletChargeMapper.java
  26. 29 0
      user/user-service/src/main/java/cn/reghao/tnb/user/app/db/repository/ApprovalRepository.java
  27. 22 0
      user/user-service/src/main/java/cn/reghao/tnb/user/app/model/dto/AuditApprovalRequest.java
  28. 1 1
      user/user-service/src/main/java/cn/reghao/tnb/user/app/model/dto/WalletDto.java
  29. 30 0
      user/user-service/src/main/java/cn/reghao/tnb/user/app/model/po/ApprovalHistory.java
  30. 32 0
      user/user-service/src/main/java/cn/reghao/tnb/user/app/model/po/ApprovalRequest.java
  31. 10 4
      user/user-service/src/main/java/cn/reghao/tnb/user/app/model/po/WalletBill.java
  32. 0 35
      user/user-service/src/main/java/cn/reghao/tnb/user/app/model/po/WalletCharge.java
  33. 40 0
      user/user-service/src/main/java/cn/reghao/tnb/user/app/model/vo/ApprovalQuery.java
  34. 30 0
      user/user-service/src/main/java/cn/reghao/tnb/user/app/model/vo/ApprovalRequestInfo.java
  35. 6 3
      user/user-service/src/main/java/cn/reghao/tnb/user/app/model/vo/MyWallet.java
  36. 23 0
      user/user-service/src/main/java/cn/reghao/tnb/user/app/model/vo/WalletBillInfo.java
  37. 17 1
      user/user-service/src/main/java/cn/reghao/tnb/user/app/rpc/UserServiceImpl.java
  38. 0 135
      user/user-service/src/main/java/cn/reghao/tnb/user/app/rpc/UserWalletServiceImpl.java
  39. 1 32
      user/user-service/src/main/java/cn/reghao/tnb/user/app/service/AdminUserService.java
  40. 101 0
      user/user-service/src/main/java/cn/reghao/tnb/user/app/service/ApprovalService.java
  41. 42 15
      user/user-service/src/main/java/cn/reghao/tnb/user/app/service/WalletService.java
  42. 1 1
      user/user-service/src/main/resources/application-dev.yml
  43. 23 0
      user/user-service/src/main/resources/mapper/ApprovalHistoryMapper.xml
  44. 50 0
      user/user-service/src/main/resources/mapper/ApprovalRequestMapper.xml
  45. 1 1
      user/user-service/src/main/resources/mapper/UserVipMapper.xml
  46. 1 1
      user/user-service/src/main/resources/mapper/WalletBillMapper.xml
  47. 0 33
      user/user-service/src/main/resources/mapper/WalletChargeMapper.xml

+ 1 - 0
auth/auth-api/src/main/java/cn/reghao/tnb/auth/api/iface/AdminAccountService.java

@@ -15,4 +15,5 @@ public interface AdminAccountService {
     void setAccountCode(AccountRegistryStatus accountRegistryStatus);
     PageList<AccountInfo> getByScreenName(String screenName, int pageNumber, int pageSize);
     void invalidCache(String key);
+    void grantRole(long userId, String role);
 }

+ 0 - 8
auth/auth-service/src/main/java/cn/reghao/tnb/auth/app/controller/AccountProfileController.java

@@ -1,7 +1,6 @@
 package cn.reghao.tnb.auth.app.controller;
 
 import cn.reghao.jutil.jdk.web.result.Result;
-import cn.reghao.tnb.auth.app.model.dto.GrantRole;
 import cn.reghao.tnb.common.web.WebResult;
 import cn.reghao.tnb.auth.app.model.dto.PasswordUpdateDto;
 import cn.reghao.tnb.auth.app.model.dto.UserEmailUpdate;
@@ -28,13 +27,6 @@ public class AccountProfileController {
         this.accountProfileService = accountProfileService;
     }
 
-    @Operation(summary = "请求授予角色", description = "N")
-    @PostMapping(value = "/require_role", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String requireRole(@RequestBody @Validated GrantRole grantRole) {
-        Result result = accountProfileService.grantRole(grantRole);
-        return WebResult.result(result);
-    }
-
     @Operation(summary = "修改用户名", description = "N")
     @PostMapping(value = "/screenname", produces = MediaType.APPLICATION_JSON_VALUE)
     public String updateUserScreenName(@NotBlank(message = "用户名不能为空") String screenName) {

+ 0 - 19
auth/auth-service/src/main/java/cn/reghao/tnb/auth/app/model/dto/GrantRole.java

@@ -1,19 +0,0 @@
-package cn.reghao.tnb.auth.app.model.dto;
-
-import cn.reghao.jutil.jdk.web.validator.ValidEnum;
-import cn.reghao.tnb.common.auth.AccountRole;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Size;
-import lombok.Data;
-
-/**
- * @author reghao
- * @date 2026-05-11 16:48:09
- */
-@Data
-public class GrantRole {
-    //@ValidEnum(value = AccountRole.class, message = "角色类型不正确")
-    @NotBlank(message = "role 不能为空字符串")
-    @Size(min = 1, max = 10)
-    private String role;
-}

+ 8 - 1
auth/auth-service/src/main/java/cn/reghao/tnb/auth/app/rpc/AdminAccountServiceImpl.java

@@ -8,6 +8,7 @@ import cn.reghao.tnb.auth.api.iface.AdminAccountService;
 import cn.reghao.tnb.auth.app.db.repository.AccountRepository;
 import cn.reghao.tnb.auth.app.model.po.UserRegistry;
 import cn.reghao.tnb.auth.app.service.AccountRegistryService;
+import cn.reghao.tnb.common.auth.AccountRole;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboService;
 import org.springframework.data.redis.core.RedisTemplate;
@@ -25,7 +26,7 @@ import java.util.Set;
 public class AdminAccountServiceImpl implements AdminAccountService {
     private final AccountRepository accountRepository;
     private final AccountRegistryService accountRegistryService;
-    private RedisTemplate<String, Object> redisTemplate;
+    private final RedisTemplate<String, Object> redisTemplate;
 
     public AdminAccountServiceImpl(AccountRepository accountRepository, AccountRegistryService accountRegistryService,
                                    RedisTemplate<String, Object> redisTemplate) {
@@ -67,4 +68,10 @@ public class AdminAccountServiceImpl implements AdminAccountService {
             redisTemplate.delete(keys);
         }
     }
+
+    @Override
+    public void grantRole(long userId, String role) {
+        AccountRole accountRole = AccountRole.valueOf(role);
+        accountRepository.addUserRole(userId, accountRole.name());
+    }
 }

+ 0 - 17
auth/auth-service/src/main/java/cn/reghao/tnb/auth/app/service/AccountProfileService.java

@@ -5,18 +5,14 @@ import cn.reghao.jutil.jdk.security.RandomString;
 import cn.reghao.tnb.auth.app.model.constant.VerifyChannel;
 import cn.reghao.tnb.auth.app.db.mapper.UserAccountMapper;
 import cn.reghao.tnb.auth.app.db.repository.AccountRepository;
-import cn.reghao.tnb.auth.app.model.dto.GrantRole;
 import cn.reghao.tnb.auth.app.model.dto.PasswordResetDto;
 import cn.reghao.tnb.auth.app.model.dto.PasswordUpdateDto;
 import cn.reghao.tnb.auth.app.model.dto.UserEmailUpdate;
 import cn.reghao.tnb.auth.app.model.po.UserAccount;
 import cn.reghao.tnb.auth.app.security.form.AccountAuthToken;
-import cn.reghao.tnb.common.auth.AccountRole;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
 
-import java.util.Locale;
-
 /**
  * @author reghao
  * @date 2023-02-18 14:42:57
@@ -41,19 +37,6 @@ public class AccountProfileService {
         this.passwordEncoder = passwordEncoder;
     }
 
-    public Result grantRole(GrantRole grantRole) {
-        String roleName = String.format("ROLE_%s", grantRole.getRole()).toUpperCase(Locale.ROOT);
-        AccountRole accountRole = AccountRole.getByName(roleName);
-        if (accountRole == null) {
-            return Result.fail(String.format("role %s not exists", roleName));
-        }
-
-        AccountAuthToken authToken = accountTokenService.getAuthToken();
-        long userId = authToken.getUserId();
-        accountRepository.addUserRole(userId, accountRole.name());
-        return Result.success();
-    }
-
     public Result updateUserScreenName(String screenName) {
         AccountAuthToken authToken = accountTokenService.getAuthToken();
         long userId = authToken.getUserId();

+ 1 - 4
content/content-service/src/main/java/cn/reghao/tnb/content/app/vod/service/AdminVodService.java

@@ -85,15 +85,12 @@ public class AdminVodService {
         }
 
         long receiver = videoPostMapper.findByVideoId(videoId).getPublishBy();
-        int msgType = MsgType.chargeMsg.getValue();
         String title = "稿件审核";
         String content = String.format("稿件 %s 通过审核", videoId);
         if (decision != VideoStatus.PUBLISHED.getCode()) {
             content = String.format("稿件 %s 未通过审核", videoId);
         }
-
-        UserMessageDto userMessageDto = new UserMessageDto(msgType, title, content, receiver);
-        messageService.sendMessage(userMessageDto);
+        messageService.sendMessage(new UserMessageDto(title, content, receiver));
 
         int pageNumber = 1;
         int pageSize = 10;

+ 31 - 9
file/file-service/src/test/java/ChatTest.java

@@ -1,17 +1,17 @@
 import cn.reghao.jutil.jdk.converter.DateTimeConverter;
+import cn.reghao.jutil.jdk.serializer.JsonConverter;
 import cn.reghao.jutil.jdk.string.SnowFlake;
-import cn.reghao.oss.api.dto.ServerInfo;
-import cn.reghao.oss.api.dto.rest.UploadFileRet;
-import cn.reghao.oss.sdk.OssClient;
 import cn.reghao.tnb.file.app.FileApplication;
-import cn.reghao.tnb.file.app.model.dto.UploadFile;
 import cn.reghao.tnb.file.app.zchat.db.mapper.ChatDialogueMapper;
 import cn.reghao.tnb.file.app.zchat.db.mapper.ChatMessageMapper;
 import cn.reghao.tnb.file.app.zchat.db.mapper.ChatTransferMapper;
 import cn.reghao.tnb.file.app.zchat.model.constant.ChatMsgType;
-import cn.reghao.tnb.file.app.zchat.model.po.chat.ChatDialogue;
-import cn.reghao.tnb.file.app.zchat.model.po.chat.ChatMessage;
-import cn.reghao.tnb.file.app.zchat.model.po.message.ChatTransfer;
+import cn.reghao.tnb.file.app.zchat.model.po.ChatDialogue;
+import cn.reghao.tnb.file.app.zchat.model.po.ChatMessage;
+import cn.reghao.tnb.file.app.zchat.model.po.ChatTransfer;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
 import lombok.extern.slf4j.Slf4j;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -22,7 +22,6 @@ import java.io.File;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Random;
 
 /**
  * @author reghao
@@ -34,7 +33,30 @@ import java.util.Random;
 public class ChatTest {
     @Test
     public void chatTest() {
-        chatMessageTest();
+        List<ChatMessage> list = new ArrayList<>();
+        JsonArray jsonArray = JsonConverter.jsonFileToObject(new File("/home/reghao/Downloads/chat.json"), JsonArray.class);
+        for (JsonElement jsonElement : jsonArray) {
+            try {
+                JsonObject jsonObject = jsonElement.getAsJsonObject();
+                long senderId = jsonObject.get("senderId").getAsLong();
+                String content = jsonObject.get("content").getAsString();
+                String createAt = jsonObject.get("createAt").getAsString();
+                LocalDateTime createAt1 = DateTimeConverter.localDateTime2(createAt);
+
+                long messageId = snowFlake.nextId();
+                ChatMessage chatMessage = new ChatMessage(messageId, chatId, senderId);
+                chatMessage.setMsgType(ChatMsgType.text.getCode());
+                chatMessage.setContent(content);
+                chatMessage.setCreateAt(createAt1);
+                chatMessage.setSenderId(senderId);
+                list.add(chatMessage);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        //chatMessageTest();
+        chatMessageMapper.saveAll(list);
     }
 
     @Autowired

+ 2 - 1
message/message-api/src/main/java/cn/reghao/tnb/message/api/constant/MsgType.java

@@ -17,7 +17,8 @@ public enum MsgType {
     chargeMsg(7, "充值消息"),
     transferMsg(8, "转帐消息"),
     payMsg(9, "支付消息"),
-    sysMsg(10, "系统消息");
+    sysMsg(10, "系统消息"),
+    grantRole(11, "授予角色");
 
     private final int code;
     private final String desc;

+ 10 - 2
message/message-api/src/main/java/cn/reghao/tnb/message/api/dto/UserMessageDto.java

@@ -1,7 +1,8 @@
 package cn.reghao.tnb.message.api.dto;
 
-import lombok.AllArgsConstructor;
+import cn.reghao.tnb.message.api.constant.MsgType;
 import lombok.Getter;
+import lombok.NoArgsConstructor;
 import lombok.Setter;
 
 import java.io.Serializable;
@@ -10,7 +11,7 @@ import java.io.Serializable;
  * @author reghao
  * @date 2024-04-18 15:23:11
  */
-@AllArgsConstructor
+@NoArgsConstructor
 @Setter
 @Getter
 public class UserMessageDto implements Serializable {
@@ -20,4 +21,11 @@ public class UserMessageDto implements Serializable {
     private String title;
     private String content;
     private long receiver;
+
+    public UserMessageDto(String title, String content, long receiver) {
+        this.msgType = MsgType.sysMsg.getValue();
+        this.title = title;
+        this.content = content;
+        this.receiver = receiver;
+    }
 }

+ 1 - 2
message/message-service/src/main/java/cn/reghao/tnb/message/app/service/MessageConsumer.java

@@ -69,10 +69,9 @@ public class MessageConsumer {
             notifyService.notify(webhookName, dingMsg);
         }
 
-        int msgTypeCode = msgType.getValue();
         String title = "webhook 通知";
         String content = String.format("发送 %s 消息, 消息内容: %s", msgType.name(), jsonPayload);
-        UserMessageDto userMessageDto = new UserMessageDto(msgTypeCode, title, content, ConstantId.ANONYMOUS_USER_ID);
+        UserMessageDto userMessageDto = new UserMessageDto(title, content, ConstantId.ANONYMOUS_USER_ID);
         userMessageService.addMessage(userMessageDto);
     }
 }

+ 1 - 2
message/message-service/src/main/java/cn/reghao/tnb/message/app/service/NotifyService.java

@@ -68,10 +68,9 @@ public class NotifyService {
             try {
                 notify.send(receiver, msg);
             } catch (Exception e) {
-                int msgType = MsgType.sysMsg.getValue();
                 String title = "发送通知失败";
                 String content = String.format("发送给 %s 的通知失败 -> %s", receiver, e.getMessage());
-                UserMessageDto userMessageDto = new UserMessageDto(msgType, title, content, ConstantId.ANONYMOUS_USER_ID);
+                UserMessageDto userMessageDto = new UserMessageDto(title, content, ConstantId.ANONYMOUS_USER_ID);
                 userMessageService.addMessage(userMessageDto);
             }
         }

+ 39 - 0
user/user-api/src/main/java/cn/reghao/tnb/user/api/constant/UserApprovalAction.java

@@ -0,0 +1,39 @@
+package cn.reghao.tnb.user.api.constant;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author reghao
+ * @date 2026-06-12 11:03:19
+ */
+public enum UserApprovalAction {
+    pass(1, "通过"),
+    decline(2, "拒绝");
+
+    private final int code;
+    private final String desc;
+
+    private static Map<Integer, UserApprovalAction> descMap = new HashMap<>();
+    static {
+        for (UserApprovalAction type : UserApprovalAction.values()) {
+            descMap.put(type.code, type);
+        }
+    }
+    UserApprovalAction(int code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public String getDesc() {
+        return this.desc;
+    }
+
+    public int getValue() {
+        return code;
+    }
+
+    public static UserApprovalAction getByCode(int code) {
+        return descMap.get(code);
+    }
+}

+ 40 - 0
user/user-api/src/main/java/cn/reghao/tnb/user/api/constant/UserApprovalStatus.java

@@ -0,0 +1,40 @@
+package cn.reghao.tnb.user.api.constant;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author reghao
+ * @date 2026-06-12 11:09:21
+ */
+public enum UserApprovalStatus {
+    PENDING(1, "待审批"),
+    APPROVED(2, "已通过"),
+    REJECTED(3, "已拒绝");
+
+    private final int code;
+    private final String desc;
+
+    private static Map<Integer, UserApprovalStatus> descMap = new HashMap<>();
+    static {
+        for (UserApprovalStatus type : UserApprovalStatus.values()) {
+            descMap.put(type.code, type);
+        }
+    }
+    UserApprovalStatus(int code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public String getName() {
+        return this.name();
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public static UserApprovalStatus getByCode(int code) {
+        return descMap.get(code);
+    }
+}

+ 39 - 0
user/user-api/src/main/java/cn/reghao/tnb/user/api/constant/UserApprovalType.java

@@ -0,0 +1,39 @@
+package cn.reghao.tnb.user.api.constant;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author reghao
+ * @date 2026-06-11 17:26:59
+ */
+public enum UserApprovalType {
+    walletCharge(1, "钱包充值"),
+    applyRole(2, "申请角色");
+
+    private final int code;
+    private final String desc;
+
+    private static Map<Integer, UserApprovalType> descMap = new HashMap<>();
+    static {
+        for (UserApprovalType type : UserApprovalType.values()) {
+            descMap.put(type.code, type);
+        }
+    }
+    UserApprovalType(int code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public static UserApprovalType getByCode(int code) {
+        return descMap.get(code);
+    }
+}

+ 5 - 6
user/user-api/src/main/java/cn/reghao/tnb/user/api/dto/ChargeReq.java → user/user-api/src/main/java/cn/reghao/tnb/user/api/dto/UserApproval.java

@@ -1,7 +1,6 @@
 package cn.reghao.tnb.user.api.dto;
 
-import lombok.AllArgsConstructor;
-import lombok.Getter;
+import lombok.Data;
 import lombok.NoArgsConstructor;
 
 import java.io.Serializable;
@@ -11,10 +10,10 @@ import java.io.Serializable;
  * @date 2024-04-16 17:26:07
  */
 @NoArgsConstructor
-@AllArgsConstructor
-@Getter
-public class ChargeReq implements Serializable {
+@Data
+public class UserApproval implements Serializable {
     private static final long serialVersionUID = 1L;
 
-    private Double quantity;
+    private String bizType;
+    private String bizPayload;
 }

+ 0 - 22
user/user-api/src/main/java/cn/reghao/tnb/user/api/dto/WalletChargeDto.java

@@ -1,22 +0,0 @@
-package cn.reghao.tnb.user.api.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * @author reghao
- * @date 2024-07-06 11:47:47
- */
-@AllArgsConstructor
-@NoArgsConstructor
-@Getter
-public class WalletChargeDto implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    private Long chargeId;
-    private Double quantity;
-    private Long owner;
-}

+ 1 - 0
user/user-api/src/main/java/cn/reghao/tnb/user/api/iface/UserService.java

@@ -17,4 +17,5 @@ public interface UserService {
     boolean setRecommendMode(long userId, int mode);
     boolean contactContain(long userId, long friendId);
     List<ContactInfo> getUserContacts(long userId);
+    void charge(long userId, double amount);
 }

+ 0 - 20
user/user-api/src/main/java/cn/reghao/tnb/user/api/iface/UserWalletService.java

@@ -1,20 +0,0 @@
-package cn.reghao.tnb.user.api.iface;
-
-import cn.reghao.jutil.jdk.web.result.Result;
-import cn.reghao.tnb.user.api.dto.ChargeReq;
-import cn.reghao.tnb.user.api.dto.WalletChargeDto;
-
-import java.util.List;
-
-/**
- * @author reghao
- * @date 2024-07-06 00:21:16
- */
-public interface UserWalletService {
-    void charge(ChargeReq chargeReq);
-    List<WalletChargeDto> getChargeReqs();
-    void approveCharge(long chargeId);
-    void approveAllCharges();
-    void declineCharge(long chargeId);
-    Result pay(long fromUserId, double amount, long toUserId);
-}

+ 27 - 34
user/user-service/src/main/java/cn/reghao/tnb/user/app/controller/AdminUserController.java

@@ -2,15 +2,19 @@ package cn.reghao.tnb.user.app.controller;
 
 import cn.reghao.jutil.jdk.web.db.PageList;
 import cn.reghao.tnb.common.web.WebResult;
-import cn.reghao.tnb.user.api.dto.UserInfo;
+import cn.reghao.tnb.user.api.constant.UserApprovalStatus;
 import cn.reghao.tnb.user.api.dto.VipPlanInfo;
-import cn.reghao.tnb.user.api.dto.WalletChargeDto;
+import cn.reghao.tnb.user.app.model.dto.AuditApprovalRequest;
 import cn.reghao.tnb.user.app.model.dto.UserQuery;
 import cn.reghao.tnb.user.app.model.vo.AdminUser;
+import cn.reghao.tnb.user.app.model.vo.ApprovalQuery;
+import cn.reghao.tnb.user.app.model.vo.ApprovalRequestInfo;
 import cn.reghao.tnb.user.app.service.AdminUserService;
+import cn.reghao.tnb.user.app.service.ApprovalService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -24,9 +28,11 @@ import java.util.List;
 @RequestMapping("/api/admin/user")
 public class AdminUserController {
     private final AdminUserService adminUserService;
+    private final ApprovalService approvalService;
     
-    public AdminUserController(AdminUserService adminUserService) {
+    public AdminUserController(AdminUserService adminUserService, ApprovalService approvalService) {
         this.adminUserService = adminUserService;
+        this.approvalService = approvalService;
     }
 
     @Operation(summary = "用户帐号列表页面", description = "N")
@@ -36,37 +42,6 @@ public class AdminUserController {
         return WebResult.success(pageList);
     }
 
-    @Operation(summary = "充值请求列表页面", description = "N")
-    @GetMapping(value = "/charge", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String chargeReq(@RequestParam("pn") int pageNumber) {
-        List<WalletChargeDto> list = adminUserService.getChargeReqs();
-        return WebResult.success(list);
-    }
-
-    @Operation(summary = "同意用户充值", description = "N")
-    @PostMapping(value = "/charge/approve/{chargeId}", produces = MediaType.APPLICATION_JSON_VALUE)
-    @ResponseBody
-    public String approveCharge(@PathVariable("chargeId") Long chargeId) {
-        adminUserService.approve(chargeId);
-        return WebResult.success();
-    }
-
-    @Operation(summary = "同意所有用户充值", description = "N")
-    @PostMapping(value = "/charge/approve_all", produces = MediaType.APPLICATION_JSON_VALUE)
-    @ResponseBody
-    public String approveAllCharge() {
-        adminUserService.approveAll();
-        return WebResult.success();
-    }
-
-    @Operation(summary = "拒绝用户充值", description = "N")
-    @PostMapping(value = "/charge/decline/{chargeId}", produces = MediaType.APPLICATION_JSON_VALUE)
-    @ResponseBody
-    public String declineCharge(@PathVariable("chargeId") Long chargeId) {
-        adminUserService.decline(chargeId);
-        return WebResult.success();
-    }
-
     @Operation(summary = "会员计划列表页面", description = "N")
     @GetMapping(value = "/vip_plan", produces = MediaType.APPLICATION_JSON_VALUE)
     public String vipPage() {
@@ -79,4 +54,22 @@ public class AdminUserController {
     public String getOnlineUsers() {
         return WebResult.success();
     }
+
+    @Operation(summary = "审批工作流", description = "N")
+    @PostMapping("/approval/audit")
+    public String auditApprovalRequest(@RequestBody @Validated AuditApprovalRequest auditApprovalRequest) {
+        approvalService.auditApprovalRequest(auditApprovalRequest);
+        return WebResult.success();
+    }
+
+    @Operation(summary = "获取待审批工作流", description = "N")
+    @GetMapping("/approval/admin_list")
+    public String getApprovalRequests1(@RequestParam("pn") int pageNumber) {
+        int status = UserApprovalStatus.PENDING.getCode();
+        ApprovalQuery approvalQuery =  new ApprovalQuery.Builder()
+                .status(status)
+                .build();
+        PageList<ApprovalRequestInfo> pageList = approvalService.getApprovalRequests(pageNumber, approvalQuery);
+        return WebResult.success(pageList);
+    }
 }

+ 45 - 0
user/user-service/src/main/java/cn/reghao/tnb/user/app/controller/ApprovalController.java

@@ -0,0 +1,45 @@
+package cn.reghao.tnb.user.app.controller;
+
+import cn.reghao.jutil.jdk.web.db.PageList;
+import cn.reghao.tnb.common.auth.AuthUser;
+import cn.reghao.tnb.common.auth.UserContext;
+import cn.reghao.tnb.common.web.WebResult;
+import cn.reghao.tnb.user.api.dto.UserApproval;
+import cn.reghao.tnb.user.app.model.vo.ApprovalQuery;
+import cn.reghao.tnb.user.app.model.vo.ApprovalRequestInfo;
+import cn.reghao.tnb.user.app.service.ApprovalService;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author reghao
+ * @date 2026-06-11 17:32:57
+ */
+@AuthUser
+@Tag(name = "审批工作流接口")
+@RestController
+@RequestMapping("/api/user/approval")
+public class ApprovalController {
+    private final ApprovalService approvalService;
+
+    public ApprovalController(ApprovalService approvalService) {
+        this.approvalService = approvalService;
+    }
+
+    @PostMapping("/add")
+    public String addApprovalRequest(@RequestBody @Validated UserApproval userApproval) {
+        approvalService.addApproval(userApproval);
+        return WebResult.success();
+    }
+
+    @GetMapping("/user_list")
+    public String getApprovalRequests2(@RequestParam("pn") int pageNumber) {
+        long loginUser = UserContext.getUserId();
+        ApprovalQuery approvalQuery =  new ApprovalQuery.Builder()
+                .userId(loginUser)
+                .build();
+        PageList<ApprovalRequestInfo> pageList = approvalService.getApprovalRequests(pageNumber, approvalQuery);
+        return WebResult.success(pageList);
+    }
+}

+ 6 - 19
user/user-service/src/main/java/cn/reghao/tnb/user/app/controller/UserWalletController.java

@@ -3,11 +3,10 @@ package cn.reghao.tnb.user.app.controller;
 import cn.reghao.tnb.common.web.WebResult;
 import cn.reghao.tnb.common.auth.AuthUser;
 import cn.reghao.tnb.common.auth.UserContext;
-import cn.reghao.tnb.user.api.dto.ChargeReq;
-import cn.reghao.tnb.user.api.iface.UserWalletService;
 import cn.reghao.tnb.user.app.model.dto.WalletDto;
 import cn.reghao.tnb.user.app.model.po.WalletBill;
 import cn.reghao.tnb.user.app.model.vo.MyWallet;
+import cn.reghao.tnb.user.app.model.vo.WalletBillInfo;
 import cn.reghao.tnb.user.app.service.WalletService;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.Operation;
@@ -21,20 +20,18 @@ import java.util.List;
  * @author reghao
  * @date 2024-04-16 16:15:04
  */
+@AuthUser
 @Tag(name = "用户钱包接口")
 @RestController
 @RequestMapping("/api/user/wallet")
 public class UserWalletController {
-    private final UserWalletService userWalletService;
     private final WalletService walletService;
 
-    public UserWalletController(UserWalletService userWalletService, WalletService walletService) {
-        this.userWalletService = userWalletService;
+    public UserWalletController(WalletService walletService) {
         this.walletService = walletService;
     }
 
     @Operation(summary = "获取用户钱包", description = "N")
-    @AuthUser
     @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE)
     public String getUserWallet() {
         MyWallet myWallet = walletService.getMyWallet();
@@ -42,29 +39,19 @@ public class UserWalletController {
     }
 
     @Operation(summary = "获取钱包账单", description = "N")
-    @AuthUser
     @GetMapping(value = "/bill", produces = MediaType.APPLICATION_JSON_VALUE)
     public String getWalletBill() {
         int pageNumber = 1;
-        List<WalletBill> list = walletService.getWalletBillList(pageNumber);
+        List<WalletBillInfo> list = walletService.getWalletBillList(pageNumber);
         return WebResult.success(list);
     }
 
-    @Operation(summary = "向钱包充值", description = "N")
-    @AuthUser
-    @PostMapping("/charge")
-    public String chargeWallet(@RequestBody @Validated ChargeReq chargeReq) {
-        userWalletService.charge(chargeReq);
-        return WebResult.success();
-    }
-
     @Operation(summary = "使用钱包支付", description = "N")
-    @AuthUser
     @PostMapping("/pay")
     public String pay(@RequestBody @Validated WalletDto walletDto) throws Exception {
-        double quantity = 1.2;
+        double amount = walletDto.getAmount();
         long loginUser = UserContext.getUserId();
-        walletService.pay(quantity, loginUser);
+        walletService.pay(amount, loginUser);
         return WebResult.success();
     }
 }

+ 16 - 0
user/user-service/src/main/java/cn/reghao/tnb/user/app/db/mapper/ApprovalHistoryMapper.java

@@ -0,0 +1,16 @@
+package cn.reghao.tnb.user.app.db.mapper;
+
+import cn.reghao.jutil.jdk.web.db.BaseMapper;
+import cn.reghao.tnb.user.app.model.po.ApprovalHistory;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2026-06-11 17:54:04
+ */
+@Mapper
+public interface ApprovalHistoryMapper extends BaseMapper<ApprovalHistory> {
+    List<ApprovalHistory> findByAuditorId(long auditorId);
+}

+ 21 - 0
user/user-service/src/main/java/cn/reghao/tnb/user/app/db/mapper/ApprovalRequestMapper.java

@@ -0,0 +1,21 @@
+package cn.reghao.tnb.user.app.db.mapper;
+
+import cn.reghao.jutil.jdk.web.db.BaseMapper;
+import cn.reghao.jutil.jdk.web.db.Page;
+import cn.reghao.tnb.user.app.model.po.ApprovalRequest;
+import cn.reghao.tnb.user.app.model.vo.ApprovalQuery;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2026-06-11 17:53:54
+ */
+@Mapper
+public interface ApprovalRequestMapper extends BaseMapper<ApprovalRequest> {
+    ApprovalRequest findById(int id);
+    int countByQuery(ApprovalQuery approvalQuery);
+    List<ApprovalRequest> findQueryByPage(@Param("page") Page page, @Param("approvalQuery") ApprovalQuery approvalQuery);
+}

+ 2 - 1
user/user-service/src/main/java/cn/reghao/tnb/user/app/db/mapper/WalletBillMapper.java

@@ -5,6 +5,7 @@ import cn.reghao.tnb.user.app.model.po.WalletBill;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -14,5 +15,5 @@ import java.util.List;
 @Mapper
 public interface WalletBillMapper extends BaseMapper<WalletBill> {
     List<WalletBill> findByOwner(@Param("pageSize") int pageSize, @Param("owner") long owner);
-    double findSumByTypeAndOwner(@Param("type") int type, @Param("owner") long owner);
+    BigDecimal findSumByTypeAndOwner(@Param("type") int type, @Param("owner") long owner);
 }

+ 0 - 21
user/user-service/src/main/java/cn/reghao/tnb/user/app/db/mapper/WalletChargeMapper.java

@@ -1,21 +0,0 @@
-package cn.reghao.tnb.user.app.db.mapper;
-
-import cn.reghao.jutil.jdk.web.db.BaseMapper;
-import cn.reghao.tnb.user.api.dto.WalletChargeDto;
-import cn.reghao.tnb.user.app.model.po.WalletCharge;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * @author reghao
- * @date 2024-07-06 11:25:57
- */
-@Mapper
-public interface WalletChargeMapper extends BaseMapper<WalletCharge> {
-    void updateStatus(@Param("chargeId") long chargeId, @Param("status") int status);
-
-    List<WalletChargeDto> findByStatus(int status);
-    WalletCharge findByChargeId(long chargeId);
-}

+ 29 - 0
user/user-service/src/main/java/cn/reghao/tnb/user/app/db/repository/ApprovalRepository.java

@@ -0,0 +1,29 @@
+package cn.reghao.tnb.user.app.db.repository;
+
+import cn.reghao.tnb.user.app.db.mapper.ApprovalHistoryMapper;
+import cn.reghao.tnb.user.app.db.mapper.ApprovalRequestMapper;
+import cn.reghao.tnb.user.app.model.po.ApprovalHistory;
+import cn.reghao.tnb.user.app.model.po.ApprovalRequest;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author reghao
+ * @date 2026-06-12 11:38:05
+ */
+@Repository
+public class ApprovalRepository {
+    private final ApprovalRequestMapper approvalRequestMapper;
+    private final ApprovalHistoryMapper approvalHistoryMapper;
+
+    public ApprovalRepository(ApprovalRequestMapper approvalRequestMapper, ApprovalHistoryMapper approvalHistoryMapper) {
+        this.approvalRequestMapper = approvalRequestMapper;
+        this.approvalHistoryMapper = approvalHistoryMapper;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    public void updateAndSave(ApprovalRequest approvalRequest, ApprovalHistory approvalHistory) {
+        approvalRequestMapper.update(approvalRequest);
+        approvalHistoryMapper.save(approvalHistory);
+    }
+}

+ 22 - 0
user/user-service/src/main/java/cn/reghao/tnb/user/app/model/dto/AuditApprovalRequest.java

@@ -0,0 +1,22 @@
+package cn.reghao.tnb.user.app.model.dto;
+
+import cn.reghao.jutil.jdk.web.validator.ValidEnum;
+import cn.reghao.tnb.user.api.constant.UserApprovalAction;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+
+/**
+ * @author reghao
+ * @date 2026-06-12 09:46:07
+ */
+@Data
+public class AuditApprovalRequest {
+    @NotNull
+    private Integer requestId;
+    @ValidEnum(value = UserApprovalAction.class, message = "操作类型不正确")
+    private Integer action;
+    @NotNull
+    @Size(max = 255, message = "remark 长度不超过 255 个字符")
+    private String remark;
+}

+ 1 - 1
user/user-service/src/main/java/cn/reghao/tnb/user/app/model/dto/WalletDto.java

@@ -11,5 +11,5 @@ import jakarta.validation.constraints.NotNull;
 @Getter
 public class WalletDto {
     @NotNull
-    private Double quantity;
+    private Double amount;
 }

+ 30 - 0
user/user-service/src/main/java/cn/reghao/tnb/user/app/model/po/ApprovalHistory.java

@@ -0,0 +1,30 @@
+package cn.reghao.tnb.user.app.model.po;
+
+import cn.reghao.jutil.jdk.web.db.BaseObject;
+import cn.reghao.tnb.common.auth.UserContext;
+import cn.reghao.tnb.user.app.model.dto.AuditApprovalRequest;
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author reghao
+ * @date 2026-06-11 17:42:01
+ */
+@NoArgsConstructor
+@Setter
+@Getter
+public class ApprovalHistory extends BaseObject<Integer> {
+    private Integer requestId;
+    private Long auditorId;
+    private Integer action;
+    private String remark;
+
+    public ApprovalHistory(AuditApprovalRequest auditApprovalRequest) {
+        this.requestId = auditApprovalRequest.getRequestId();
+        this.auditorId = UserContext.getUserId();
+        this.action = auditApprovalRequest.getAction();
+        this.remark = auditApprovalRequest.getRemark();
+    }
+}

+ 32 - 0
user/user-service/src/main/java/cn/reghao/tnb/user/app/model/po/ApprovalRequest.java

@@ -0,0 +1,32 @@
+package cn.reghao.tnb.user.app.model.po;
+
+import cn.reghao.jutil.jdk.web.db.BaseObject;
+import cn.reghao.tnb.common.auth.UserContext;
+import cn.reghao.tnb.user.api.constant.UserApprovalStatus;
+import cn.reghao.tnb.user.api.constant.UserApprovalType;
+import cn.reghao.tnb.user.api.dto.UserApproval;
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author reghao
+ * @date 2026-06-11 17:42:14
+ */
+@NoArgsConstructor
+@Setter
+@Getter
+public class ApprovalRequest extends BaseObject<Integer> {
+    private Integer bizType;
+    private String bizPayload;
+    private Integer status;
+    private Long userId;
+
+    public ApprovalRequest(UserApproval userApproval) {
+        this.bizType = UserApprovalType.valueOf(userApproval.getBizType()).getCode();
+        this.bizPayload = userApproval.getBizPayload();
+        this.status = UserApprovalStatus.PENDING.getCode();
+        this.userId = UserContext.getUserId();
+    }
+}

+ 10 - 4
user/user-service/src/main/java/cn/reghao/tnb/user/app/model/po/WalletBill.java

@@ -7,6 +7,8 @@ import lombok.NoArgsConstructor;
 import lombok.Setter;
 
 import jakarta.validation.constraints.NotNull;
+
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
 /**
@@ -21,16 +23,20 @@ public class WalletBill extends BaseObject<Integer> {
     @NotNull
     private Integer type;
     @NotNull
-    private Double quantity;
+    private BigDecimal quantity;
     @NotNull
     private LocalDateTime createAt;
     @NotNull
     private Long owner;
 
-    private String typeStr;
-    private String createAtStr;
-
     public WalletBill(int type, double quantity, long owner) {
+        this.type = type;
+        this.quantity = new BigDecimal(String.valueOf(quantity));
+        this.createAt = LocalDateTime.now();
+        this.owner = owner;
+    }
+
+    public WalletBill(int type, BigDecimal quantity, long owner) {
         this.type = type;
         this.quantity = quantity;
         this.createAt = LocalDateTime.now();

+ 0 - 35
user/user-service/src/main/java/cn/reghao/tnb/user/app/model/po/WalletCharge.java

@@ -1,35 +0,0 @@
-package cn.reghao.tnb.user.app.model.po;
-
-import cn.reghao.jutil.jdk.web.db.BaseObject;
-import cn.reghao.tnb.common.auth.UserContext;
-import cn.reghao.tnb.user.api.dto.ChargeReq;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-import jakarta.validation.constraints.NotNull;
-
-/**
- * @author reghao
- * @date 2024-07-06 11:25:29
- */
-@AllArgsConstructor
-@NoArgsConstructor
-@Getter
-public class WalletCharge extends BaseObject<Integer> {
-    @NotNull
-    private Long chargeId;
-    @NotNull
-    private Double quantity;
-    @NotNull
-    private Long owner;
-    @NotNull
-    private Integer status;
-
-    public WalletCharge(long chargeId, ChargeReq chargeReq) {
-        this.chargeId = chargeId;
-        this.quantity = chargeReq.getQuantity();
-        this.owner = UserContext.getUserId();
-        this.status = 1;
-    }
-}

+ 40 - 0
user/user-service/src/main/java/cn/reghao/tnb/user/app/model/vo/ApprovalQuery.java

@@ -0,0 +1,40 @@
+package cn.reghao.tnb.user.app.model.vo;
+
+import lombok.Data;
+
+/**
+ * @author reghao
+ * @date 2026-06-12 09:38:30
+ */
+@Data
+public class ApprovalQuery {
+    private Long userId;
+    private Integer status;
+
+    public ApprovalQuery() {
+    }
+
+    private ApprovalQuery(Builder builder) {
+        this.userId = builder.userId;
+        this.status = builder.status;
+    }
+
+    public static final class Builder {
+        private Long userId;
+        private Integer status;
+
+        public Builder userId(long userId) {
+            this.userId = userId;
+            return this;
+        }
+
+        public Builder status(int status) {
+            this.status = status;
+            return this;
+        }
+
+        public ApprovalQuery build() {
+            return new ApprovalQuery(this);
+        }
+    }
+}

+ 30 - 0
user/user-service/src/main/java/cn/reghao/tnb/user/app/model/vo/ApprovalRequestInfo.java

@@ -0,0 +1,30 @@
+package cn.reghao.tnb.user.app.model.vo;
+
+import cn.reghao.jutil.jdk.converter.DateTimeConverter;
+import cn.reghao.tnb.user.api.constant.UserApprovalStatus;
+import cn.reghao.tnb.user.api.constant.UserApprovalType;
+import cn.reghao.tnb.user.app.model.po.ApprovalRequest;
+import lombok.Data;
+
+/**
+ * @author reghao
+ * @date 2026-06-12 11:16:45
+ */
+@Data
+public class ApprovalRequestInfo {
+    private Integer id;
+    private String bizType;
+    private String bizPayload;
+    private String status;
+    private Long userId;
+    private String createAt;
+
+    public ApprovalRequestInfo(ApprovalRequest approvalRequest) {
+        this.id = approvalRequest.getId();
+        this.bizType = UserApprovalType.getByCode(approvalRequest.getBizType()).name();
+        this.bizPayload = approvalRequest.getBizPayload();
+        this.status = UserApprovalStatus.getByCode(approvalRequest.getStatus()).name();
+        this.userId = approvalRequest.getUserId();
+        this.createAt = DateTimeConverter.format(approvalRequest.getCreateTime());
+    }
+}

+ 6 - 3
user/user-service/src/main/java/cn/reghao/tnb/user/app/model/vo/MyWallet.java

@@ -4,6 +4,9 @@ import cn.reghao.jutil.jdk.web.db.BaseObject;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
 /**
  * @author reghao
  * @date 2024-04-16 16:09:31
@@ -11,11 +14,11 @@ import lombok.NoArgsConstructor;
 @NoArgsConstructor
 @Getter
 public class MyWallet extends BaseObject<Integer> {
-    private Double balance;
+    private String balance;
     private Long owner;
 
-    public MyWallet(long owner, double balance) {
+    public MyWallet(long owner, BigDecimal balance) {
         this.owner = owner;
-        this.balance = balance;
+        this.balance = balance.setScale(2, RoundingMode.HALF_UP).toString();;
     }
 }

+ 23 - 0
user/user-service/src/main/java/cn/reghao/tnb/user/app/model/vo/WalletBillInfo.java

@@ -0,0 +1,23 @@
+package cn.reghao.tnb.user.app.model.vo;
+
+import cn.reghao.jutil.jdk.converter.DateTimeConverter;
+import cn.reghao.tnb.user.app.model.constant.BillType;
+import cn.reghao.tnb.user.app.model.po.WalletBill;
+
+/**
+ * @author reghao
+ * @date 2026-06-12 15:32:40
+ */
+public class WalletBillInfo {
+    private String type;
+    private String quantity;
+    private String createAt;
+    private Long owner;
+
+    public WalletBillInfo(WalletBill walletBill) {
+        this.type = BillType.getDescByCode(walletBill.getType());
+        this.quantity = walletBill.getQuantity().toString();
+        this.createAt = DateTimeConverter.format(walletBill.getCreateAt());
+        this.owner = walletBill.getOwner();
+    }
+}

+ 17 - 1
user/user-service/src/main/java/cn/reghao/tnb/user/app/rpc/UserServiceImpl.java

@@ -1,11 +1,15 @@
 package cn.reghao.tnb.user.app.rpc;
 
+import cn.reghao.jutil.jdk.string.SnowFlake;
 import cn.reghao.tnb.auth.api.dto.AccountInfo;
 import cn.reghao.tnb.auth.api.iface.AccountQuery;
 import cn.reghao.tnb.user.api.dto.ContactInfo;
 import cn.reghao.tnb.user.api.dto.UserCard;
 import cn.reghao.tnb.user.api.iface.UserService;
 import cn.reghao.tnb.user.app.db.mapper.UserContactMapper;
+import cn.reghao.tnb.user.app.db.mapper.WalletBillMapper;
+import cn.reghao.tnb.user.app.model.constant.BillType;
+import cn.reghao.tnb.user.app.model.po.WalletBill;
 import cn.reghao.tnb.user.app.model.vo.MyVip;
 import cn.reghao.tnb.user.app.service.UserRelationService;
 import cn.reghao.tnb.user.app.service.UserProfileService;
@@ -27,17 +31,22 @@ public class UserServiceImpl implements UserService {
     @DubboReference(check = false, retries = 0)
     private AccountQuery accountQuery;
 
+    private final SnowFlake idGenerator;
     private final UserRelationService userRelationService;
     private final UserVipService userVipService;
     private final UserProfileService userProfileService;
     private final UserContactMapper userContactMapper;
+    private final WalletBillMapper walletBillMapper;
 
     public UserServiceImpl(UserRelationService userRelationService, UserVipService userVipService,
-                           UserProfileService userProfileService, UserContactMapper userContactMapper) {
+                           UserProfileService userProfileService, UserContactMapper userContactMapper,
+                           WalletBillMapper walletBillMapper) {
+        this.idGenerator = new SnowFlake(1L, 1L);
         this.userRelationService = userRelationService;
         this.userVipService = userVipService;
         this.userProfileService = userProfileService;
         this.userContactMapper = userContactMapper;
+        this.walletBillMapper = walletBillMapper;
     }
 
     @Override
@@ -98,4 +107,11 @@ public class UserServiceImpl implements UserService {
                     return new ContactInfo(accountInfo);
                 }).toList();
     }
+
+    @Override
+    public void charge(long userId, double amount) {
+        long billId = idGenerator.nextId();
+        WalletBill walletBill = new WalletBill(BillType.InCome.getCode(), amount, userId);
+        walletBillMapper.save(walletBill);
+    }
 }

+ 0 - 135
user/user-service/src/main/java/cn/reghao/tnb/user/app/rpc/UserWalletServiceImpl.java

@@ -1,135 +0,0 @@
-package cn.reghao.tnb.user.app.rpc;
-
-import cn.reghao.jutil.jdk.web.result.Result;
-import cn.reghao.jutil.jdk.string.SnowFlake;
-import cn.reghao.tnb.common.auth.UserContext;
-import cn.reghao.tnb.common.util.ConstantId;
-import cn.reghao.tnb.message.api.constant.MsgType;
-import cn.reghao.tnb.message.api.iface.MessageService;
-import cn.reghao.tnb.user.api.dto.ChargeReq;
-import cn.reghao.tnb.message.api.dto.UserMessageDto;
-import cn.reghao.tnb.user.api.dto.WalletChargeDto;
-import cn.reghao.tnb.user.api.iface.UserService;
-import cn.reghao.tnb.user.api.iface.UserWalletService;
-import cn.reghao.tnb.user.app.db.mapper.WalletBillMapper;
-import cn.reghao.tnb.user.app.db.mapper.WalletChargeMapper;
-import cn.reghao.tnb.user.app.model.constant.BillType;
-import cn.reghao.tnb.user.app.model.po.WalletBill;
-import cn.reghao.tnb.user.app.model.po.WalletCharge;
-import cn.reghao.tnb.user.app.service.WalletService;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.dubbo.config.annotation.DubboReference;
-import org.apache.dubbo.config.annotation.DubboService;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.List;
-
-/**
- * @author reghao
- * @date 2024-07-06 00:22:33
- */
-@Slf4j
-@DubboService
-@Service
-public class UserWalletServiceImpl implements UserWalletService {
-    @DubboReference(check = false, retries = 0, timeout = 60_000)
-    private UserService userService;
-    @DubboReference(check = false, retries = 0, timeout = 60_000)
-    private MessageService messageService;
-
-    private final SnowFlake idGenerator;
-    private final WalletChargeMapper walletChargeMapper;
-    private final WalletBillMapper walletBillMapper;
-    private final WalletService walletService;
-
-    public UserWalletServiceImpl(WalletChargeMapper walletChargeMapper, WalletBillMapper walletBillMapper,
-                                 WalletService walletService) {
-        this.idGenerator = new SnowFlake(1L, 1L);
-        this.walletChargeMapper = walletChargeMapper;
-        this.walletBillMapper = walletBillMapper;
-        this.walletService = walletService;
-    }
-
-    @Override
-    public void charge(ChargeReq chargeReq) {
-        long chargeId = idGenerator.nextId();
-        WalletCharge walletCharge = new WalletCharge(chargeId, chargeReq);
-        walletChargeMapper.save(walletCharge);
-
-        long loginUser = UserContext.getUserId();
-        int msgType = MsgType.chargeMsg.getValue();
-        String title = "充值消息";
-        String content = String.format("来自 %s 的充值请求", loginUser);
-        UserMessageDto userMessageDto = new UserMessageDto(msgType, title, content, ConstantId.ANONYMOUS_USER_ID);
-        messageService.sendMessage(userMessageDto);
-    }
-
-    @Override
-    public List<WalletChargeDto> getChargeReqs() {
-        int status = 1;
-        return walletChargeMapper.findByStatus(status);
-    }
-
-    @Override
-    public void approveCharge(long chargeId) {
-        WalletCharge walletCharge = walletChargeMapper.findByChargeId(chargeId);
-        if (walletCharge == null) {
-            return;
-        }
-
-        int status = 2;
-        walletChargeMapper.updateStatus(chargeId, status);
-        double quantity = walletCharge.getQuantity();
-        long owner = walletCharge.getOwner();
-        WalletBill walletBill = new WalletBill(BillType.InCome.getCode(), quantity, owner);
-        walletBillMapper.save(walletBill);
-
-        long receiver = walletCharge.getOwner();
-        int msgType = MsgType.chargeMsg.getValue();
-        String title = "充值成功";
-        String content = String.format("系统同意了您的充值请求");
-        UserMessageDto userMessageDto = new UserMessageDto(msgType, title, content, receiver);
-        messageService.sendMessage(userMessageDto);
-    }
-
-    @Override
-    public void approveAllCharges() {
-        int status = 1;
-        walletChargeMapper.findByStatus(status).forEach(walletChargeDto -> {
-            long chargeId = walletChargeDto.getChargeId();
-            approveCharge(chargeId);
-        });
-    }
-
-    @Override
-    public void declineCharge(long chargeId) {
-        WalletCharge walletCharge = walletChargeMapper.findByChargeId(chargeId);
-        if (walletCharge == null) {
-            return;
-        }
-        int status = 3;
-        walletChargeMapper.updateStatus(chargeId, status);
-
-        long receiver = walletCharge.getOwner();
-        int msgType = MsgType.chargeMsg.getValue();
-        String title = "充值失败";
-        String content = String.format("系统拒绝了您的充值请求");
-        UserMessageDto userMessageDto = new UserMessageDto(msgType, title, content, receiver);
-        messageService.sendMessage(userMessageDto);
-    }
-
-    @Transactional(rollbackFor = Exception.class)
-    @Override
-    public Result pay(long fromUserId, double amount, long toUserId) {
-        double balance = walletService.getBalance(fromUserId);
-        if (balance < amount) {
-            return Result.fail("余额不足");
-        }
-
-        WalletBill walletBill1 = new WalletBill(BillType.Expenditure.getCode(), amount, fromUserId);
-        WalletBill walletBill2 = new WalletBill(BillType.InCome.getCode(), amount, toUserId);
-        walletBillMapper.saveAll(List.of(walletBill1, walletBill2));
-        return Result.success();
-    }
-}

+ 1 - 32
user/user-service/src/main/java/cn/reghao/tnb/user/app/service/AdminUserService.java

@@ -1,14 +1,11 @@
 package cn.reghao.tnb.user.app.service;
 
 import cn.reghao.jutil.jdk.web.db.PageList;
-import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
 import cn.reghao.tnb.auth.api.dto.AccountInfo;
 import cn.reghao.tnb.auth.api.iface.AccountQuery;
 import cn.reghao.tnb.auth.api.iface.AdminAccountService;
 import cn.reghao.tnb.user.app.model.dto.UserQuery;
 import cn.reghao.tnb.user.api.dto.VipPlanInfo;
-import cn.reghao.tnb.user.api.dto.WalletChargeDto;
-import cn.reghao.tnb.user.api.iface.UserWalletService;
 import cn.reghao.tnb.user.app.db.mapper.UserProfileMapper;
 import cn.reghao.tnb.user.app.model.po.UserProfile;
 import cn.reghao.tnb.user.app.model.vo.AdminUser;
@@ -20,7 +17,6 @@ import org.springframework.data.domain.PageRequest;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
-import java.util.concurrent.ExecutorService;
 import java.util.stream.Collectors;
 
 /**
@@ -35,14 +31,10 @@ public class AdminUserService {
     private AccountQuery accountQuery;
 
     private int pageSize = 100;
-    private final ExecutorService threadPool = ThreadPoolWrapper.threadPool("approve-charge-task", 1);
-    private final UserWalletService userWalletService;
     private final UserVipService userVipService;
     private final UserProfileMapper userProfileMapper;
 
-    public AdminUserService(UserWalletService userWalletService, UserVipService userVipService,
-                            UserProfileMapper userProfileMapper) {
-        this.userWalletService = userWalletService;
+    public AdminUserService(UserVipService userVipService, UserProfileMapper userProfileMapper) {
         this.userVipService = userVipService;
         this.userProfileMapper = userProfileMapper;
     }
@@ -100,27 +92,4 @@ public class AdminUserService {
 
         return null;
     }
-
-    public List<WalletChargeDto> getChargeReqs() {
-        return userWalletService.getChargeReqs();
-    }
-
-    public void approve(long chargeId) {
-        userWalletService.approveCharge(chargeId);
-    }
-
-    public void approveAll() {
-        threadPool.submit(new ApproveTask());
-    }
-
-    public void decline(long chargeId) {
-        userWalletService.declineCharge(chargeId);
-    }
-
-    class ApproveTask implements Runnable {
-        @Override
-        public void run() {
-            userWalletService.approveAllCharges();
-        }
-    }
 }

+ 101 - 0
user/user-service/src/main/java/cn/reghao/tnb/user/app/service/ApprovalService.java

@@ -0,0 +1,101 @@
+package cn.reghao.tnb.user.app.service;
+
+import cn.reghao.jutil.jdk.serializer.JsonConverter;
+import cn.reghao.jutil.jdk.web.db.Page;
+import cn.reghao.jutil.jdk.web.db.PageList;
+import cn.reghao.tnb.auth.api.iface.AdminAccountService;
+import cn.reghao.tnb.common.auth.AccountRole;
+import cn.reghao.tnb.common.util.ConstantId;
+import cn.reghao.tnb.message.api.constant.MsgType;
+import cn.reghao.tnb.message.api.dto.UserMessageDto;
+import cn.reghao.tnb.message.api.iface.MessageService;
+import cn.reghao.tnb.user.api.constant.UserApprovalAction;
+import cn.reghao.tnb.user.api.constant.UserApprovalStatus;
+import cn.reghao.tnb.user.api.constant.UserApprovalType;
+import cn.reghao.tnb.user.api.dto.UserApproval;
+import cn.reghao.tnb.user.api.iface.UserService;
+import cn.reghao.tnb.user.app.db.mapper.ApprovalRequestMapper;
+import cn.reghao.tnb.user.app.db.repository.ApprovalRepository;
+import cn.reghao.tnb.user.app.model.dto.AuditApprovalRequest;
+import cn.reghao.tnb.user.app.model.po.ApprovalHistory;
+import cn.reghao.tnb.user.app.model.po.ApprovalRequest;
+import cn.reghao.tnb.user.app.model.vo.ApprovalQuery;
+import cn.reghao.tnb.user.app.model.vo.ApprovalRequestInfo;
+import com.google.gson.JsonObject;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2026-06-11 17:33:39
+ */
+@Service
+public class ApprovalService {
+    @DubboReference(check = false, timeout = 60_000)
+    private AdminAccountService adminAccountService;
+    @DubboReference(check = false, retries = 0, timeout = 60_000)
+    private MessageService messageService;
+
+    private final ApprovalRequestMapper approvalRequestMapper;
+    private final ApprovalRepository approvalRepository;
+    private final UserService userService;
+
+    public ApprovalService(ApprovalRequestMapper approvalRequestMapper, ApprovalRepository approvalRepository,
+                           UserService userService) {
+        this.approvalRepository = approvalRepository;
+        this.approvalRequestMapper = approvalRequestMapper;
+        this.userService = userService;
+    }
+
+    public void addApproval(UserApproval userApproval) {
+        ApprovalRequest approvalRequest = new ApprovalRequest(userApproval);
+        approvalRequestMapper.save(approvalRequest);
+    }
+
+    public PageList<ApprovalRequestInfo> getApprovalRequests(int pageNumber, ApprovalQuery approvalQuery) {
+        Page page = new Page(pageNumber, ConstantId.PAGE_SIZE);
+        int total = approvalRequestMapper.countByQuery(approvalQuery);
+        List<ApprovalRequestInfo> list = approvalRequestMapper.findQueryByPage(page, approvalQuery).stream()
+                .map(ApprovalRequestInfo::new).toList();
+        return PageList.pageList(pageNumber, ConstantId.PAGE_SIZE,  total, list);
+    }
+
+    public void auditApprovalRequest(AuditApprovalRequest auditApprovalRequest) {
+        int requestId = auditApprovalRequest.getRequestId();
+        ApprovalRequest approvalRequest = approvalRequestMapper.findById(requestId);
+        if (approvalRequest == null) {
+            return;
+        }
+
+        UserApprovalType userApprovalType = UserApprovalType.getByCode(approvalRequest.getBizType());
+        UserApprovalAction userApprovalAction = UserApprovalAction.getByCode(auditApprovalRequest.getAction());
+        long userId = approvalRequest.getUserId();
+        ApprovalHistory approvalHistory = new ApprovalHistory(auditApprovalRequest);
+        if (userApprovalAction.name().equals(UserApprovalAction.decline.name())) {
+            approvalRequest.setStatus(UserApprovalStatus.REJECTED.getCode());
+        } else {
+            approvalRequest.setStatus(UserApprovalStatus.APPROVED.getCode());
+
+            JsonObject jsonObject = JsonConverter.jsonToJsonElement(approvalRequest.getBizPayload()).getAsJsonObject();
+            if (UserApprovalType.walletCharge.name().equals(userApprovalType.name())) {
+                double amount = jsonObject.get("amount").getAsDouble();
+                userService.charge(userId, amount);
+            } else if (UserApprovalType.applyRole.name().equals(userApprovalType.name())) {
+                String role = jsonObject.get("role").getAsString();;
+                AccountRole accountRole = AccountRole.getByName(role);
+                if (accountRole != null) {
+                    adminAccountService.grantRole(userId, accountRole.name());
+                } else {
+                    return;
+                }
+            }
+        }
+        approvalRepository.updateAndSave(approvalRequest, approvalHistory);
+
+        String title = "系统通知";
+        String content = String.format("系统 %s 了您的 %s 请求\n", userApprovalAction.getDesc(), userApprovalType.getDesc());
+        messageService.sendMessage(new UserMessageDto(title, content, userId));
+    }
+}

+ 42 - 15
user/user-service/src/main/java/cn/reghao/tnb/user/app/service/WalletService.java

@@ -6,9 +6,13 @@ import cn.reghao.tnb.user.app.db.mapper.WalletBillMapper;
 import cn.reghao.tnb.user.app.model.constant.BillType;
 import cn.reghao.tnb.user.app.model.vo.MyWallet;
 import cn.reghao.tnb.user.app.model.po.WalletBill;
+import cn.reghao.tnb.user.app.model.vo.WalletBillInfo;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * @author reghao
@@ -23,38 +27,61 @@ public class WalletService {
     }
 
     public synchronized void pay(double quantity, long owner) throws Exception {
-        double balance = getBalance(owner);
-        if (balance < quantity) {
-            String errMsg = "余额不足";
-            throw new Exception(errMsg);
+        BigDecimal amount = new BigDecimal(String.valueOf(quantity));
+        BigDecimal balance = getBalance(owner);
+        if (balance.compareTo(amount) < 0) {
+            throw new Exception("余额不足");
         }
-
-        WalletBill walletBill = new WalletBill(BillType.Expenditure.getCode(), quantity, owner);
+        WalletBill walletBill = new WalletBill(BillType.Expenditure.getCode(), amount, owner);
         walletBillMapper.save(walletBill);
+        // 💡 提示:这里后续应该还包含一步更新用户钱包余额的 SQL 操作:
+        // walletMapper.decreaseBalance(owner, amount);
+    }
+
+    public void pay(long fromUserId, double quantity, long toUserId) throws Exception {
+        BigDecimal amount = new BigDecimal(quantity);
+        BigDecimal balance = getBalance(fromUserId);
+        if (balance.compareTo(amount) < 0) {
+            throw new Exception("余额不足");
+        }
+
+        WalletBill walletBill1 = new WalletBill(BillType.Expenditure.getCode(), amount, fromUserId);
+        WalletBill walletBill2 = new WalletBill(BillType.InCome.getCode(), amount, toUserId);
+        walletBillMapper.saveAll(List.of(walletBill1, walletBill2));
     }
 
     public MyWallet getMyWallet() {
         long loginUser = UserContext.getUserId();
-        double balance = getBalance(loginUser);
+        BigDecimal balance = getBalance(loginUser);
         return new MyWallet(loginUser, balance);
     }
 
-    public List<WalletBill> getWalletBillList(int pageNumber) {
+    public List<WalletBillInfo> getWalletBillList(int pageNumber) {
         long owner = UserContext.getUserId();
         int pageSize = 10;
-        List<WalletBill> list = walletBillMapper.findByOwner(pageSize, owner);
-        list.forEach(walletBill -> {
+        return walletBillMapper.findByOwner(pageSize, owner).stream()
+                .map(WalletBillInfo::new)
+                .collect(Collectors.toList());
+        /*list.forEach(walletBill -> {
             String typeStr = BillType.getDescByCode(walletBill.getType());
             walletBill.setTypeStr(typeStr);
             String createAtStr = DateTimeConverter.format(walletBill.getCreateAt());
             walletBill.setCreateAtStr(createAtStr);
         });
-        return list;
+        return list;*/
     }
 
-    public double getBalance(long owner) {
-        double incomeSum = walletBillMapper.findSumByTypeAndOwner(BillType.InCome.getCode(), owner);
-        double expenditureSum = walletBillMapper.findSumByTypeAndOwner(BillType.Expenditure.getCode(), owner);
-        return incomeSum - expenditureSum;
+    public BigDecimal getBalance(long owner) {
+        BigDecimal incomeSum = walletBillMapper.findSumByTypeAndOwner(BillType.InCome.getCode(), owner);
+        if (incomeSum == null) {
+            incomeSum = BigDecimal.ZERO;
+        }
+
+        BigDecimal expenditureSum = walletBillMapper.findSumByTypeAndOwner(BillType.Expenditure.getCode(), owner);
+        if (expenditureSum == null) {
+            expenditureSum = BigDecimal.ZERO;
+        }
+
+        return incomeSum.subtract(expenditureSum).setScale(2, RoundingMode.HALF_UP);
     }
 }

+ 1 - 1
user/user-service/src/main/resources/application-dev.yml

@@ -5,7 +5,7 @@ spring:
   cloud:
     nacos:
       config:
-        server-addr: 192.168.0.209
+        server-addr: 127.0.0.1
         group: DEFAULT_GROUP
         file-extension: yaml
         username: nacos

+ 23 - 0
user/user-service/src/main/resources/mapper/ApprovalHistoryMapper.xml

@@ -0,0 +1,23 @@
+<?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="cn.reghao.tnb.user.app.db.mapper.ApprovalHistoryMapper">
+    <insert id="save">
+        insert into user_approval_history
+        (`request_id`,`auditor_id`,`action`,`remark`)
+        values
+        (#{requestId},#{auditorId},#{action},#{remark})
+    </insert>
+
+    <update id="updateUserVip">
+        update user_approval_history
+        set update_time=now(),`status`=#{status}
+        where id=#{id}
+    </update>
+
+    <select id="findByAuditorId" resultType="cn.reghao.tnb.user.app.model.po.ApprovalHistory">
+        select *
+        from user_approval_history
+        where auditor_id=#{auditorId}
+    </select>
+</mapper>

+ 50 - 0
user/user-service/src/main/resources/mapper/ApprovalRequestMapper.xml

@@ -0,0 +1,50 @@
+<?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="cn.reghao.tnb.user.app.db.mapper.ApprovalRequestMapper">
+    <insert id="save">
+        insert into user_approval_request
+        (`biz_type`,`biz_payload`,`status`,`user_id`)
+        values
+        (#{bizType},#{bizPayload},#{status},#{userId})
+    </insert>
+
+    <update id="update">
+        update user_approval_request
+        set update_time=now(), `status`=#{status}
+        where id=#{id}
+    </update>
+
+    <select id="findById" resultType="cn.reghao.tnb.user.app.model.po.ApprovalRequest">
+        select *
+        from user_approval_request
+        where id=#{id}
+    </select>
+    <select id="countByQuery" resultType="java.lang.Integer">
+        select count(*)
+        from user_approval_request
+        <where>
+            deleted=0
+            <if test="status != null">
+                and `status`=#{status}
+            </if>
+            <if test="userId != null">
+                and `user_id`=#{userId}
+            </if>
+        </where>
+    </select>
+    <select id="findQueryByPage" resultType="cn.reghao.tnb.user.app.model.po.ApprovalRequest">
+        select *
+        from user_approval_request
+        <where>
+            deleted=0
+            <if test="approvalQuery.status != null">
+                and status=#{approvalQuery.status}
+            </if>
+            <if test="approvalQuery.userId != null">
+                and user_id=#{approvalQuery.userId}
+            </if>
+        </where>
+        order by create_time desc
+    </select>
+</mapper>

+ 1 - 1
user/user-service/src/main/resources/mapper/UserVipMapper.xml

@@ -6,7 +6,7 @@
         insert into user_vip
         (`user_id`,`expire_at`,`rcmd_mode`)
         values
-        (#{userId},#{expireAt},#{rcmd_mode})
+        (#{userId},#{expireAt},#{rcmdMode})
     </insert>
 
     <select id="updateUserVip">

+ 1 - 1
user/user-service/src/main/resources/mapper/WalletBillMapper.xml

@@ -24,7 +24,7 @@
         order by create_at desc
         limit #{pageSize}
     </select>
-    <select id="findSumByTypeAndOwner" resultType="java.lang.Double">
+    <select id="findSumByTypeAndOwner" resultType="java.math.BigDecimal">
         select sum(quantity) as total
         from user_wallet_bill
         where type=#{type} and `owner`=#{owner}

+ 0 - 33
user/user-service/src/main/resources/mapper/WalletChargeMapper.xml

@@ -1,33 +0,0 @@
-<?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="cn.reghao.tnb.user.app.db.mapper.WalletChargeMapper">
-    <insert id="save" useGeneratedKeys="true" keyProperty="id">
-        insert into user_wallet_charge
-        (`charge_id`,`quantity`,`owner`,`status`)
-        values 
-        (#{chargeId},#{quantity},#{owner},#{status})
-    </insert>
-
-    <update id="updateStatus">
-        update user_wallet_charge
-        set `status`=#{status}
-        where `charge_id`=#{chargeId}
-    </update>
-    
-    <select id="findAll" resultType="cn.reghao.tnb.user.app.model.po.WalletCharge">
-        select *
-        from user_wallet_charge
-        limit 20
-    </select>
-    <select id="findByStatus" resultType="cn.reghao.tnb.user.api.dto.WalletChargeDto">
-        select *
-        from user_wallet_charge
-        where `status`=#{status}
-    </select>
-    <select id="findByChargeId" resultType="cn.reghao.tnb.user.app.model.po.WalletCharge">
-        select *
-        from user_wallet_charge
-        where charge_id=#{chargeId}
-    </select>
-</mapper>