增加充值

This commit is contained in:
18796357645 2025-06-08 10:53:48 +08:00
parent 459bfbcf48
commit a190205309
33 changed files with 921 additions and 493 deletions

View File

@ -1,107 +1,107 @@
package io.modules.sys.controller; //package io.modules.sys.controller;
import io.common.annotation.LogOperation; //import io.common.annotation.LogOperation;
import io.common.constant.Constant; //import io.common.constant.Constant;
import io.modules.item.dto.ArticleDTO; //import io.modules.item.dto.AccountDTO;
//
import io.modules.item.service.ArticleService; //import io.modules.item.service.AccountService;
import io.common.page.PageData; //import io.common.page.PageData;
import io.common.utils.Result; //import io.common.utils.Result;
import io.common.validator.AssertUtils; //import io.common.validator.AssertUtils;
import io.common.validator.ValidatorUtils; //import io.common.validator.ValidatorUtils;
import io.common.validator.group.AddGroup; //import io.common.validator.group.AddGroup;
import io.common.validator.group.DefaultGroup; //import io.common.validator.group.DefaultGroup;
import io.common.validator.group.UpdateGroup; //import io.common.validator.group.UpdateGroup;
import io.modules.item.service.DictService; //import io.modules.item.service.DictService;
import io.swagger.v3.oas.annotations.Operation; //import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.enums.ParameterIn; //import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag; //import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.shiro.authz.annotation.RequiresPermissions; //import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired; //import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; //import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Parameter; //import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters; //import io.swagger.v3.oas.annotations.Parameters;
//
import java.util.List; //import java.util.List;
import java.util.Map; //import java.util.Map;
/** ///**
* 文章表 // * 文章表
//
*/ // */
@RestController //@RestController
@RequestMapping("item/article") //@RequestMapping("item/article")
@Tag(name="文章表") //@Tag(name="文章表")
public class ArticleController { //public class ArticleController {
@Autowired // @Autowired
private ArticleService articleService; // private AccountService articleService;
//
//
@Autowired // @Autowired
private DictService dictService; // private DictService dictService;
//
@GetMapping("page") // @GetMapping("page")
@Operation(summary = "分页") // @Operation(summary = "分页")
@Parameters({ // @Parameters({
@Parameter(name = Constant.PAGE, description = "当前页码从1开始", in = ParameterIn.QUERY, required = true, ref="int") , // @Parameter(name = Constant.PAGE, description = "当前页码从1开始", in = ParameterIn.QUERY, required = true, ref="int") ,
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY,required = true, ref="int") , // @Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY,required = true, ref="int") ,
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref="String") , // @Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref="String") ,
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref="String"), // @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref="String"),
@Parameter(name = "type", description = "类型", in = ParameterIn.QUERY, ref="String") // @Parameter(name = "type", description = "类型", in = ParameterIn.QUERY, ref="String")
}) // })
@RequiresPermissions("item:article:page") // @RequiresPermissions("item:article:page")
public Result<PageData<ArticleDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params){ // public Result<PageData<AccountDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params){
PageData<ArticleDTO> page = articleService.page(params); // PageData<AccountDTO> page = articleService.page(params);
return new Result<PageData<ArticleDTO>>().ok(page); // return new Result<PageData<AccountDTO>>().ok(page);
} // }
//
@GetMapping("{id}") // @GetMapping("{id}")
@Operation(summary = "信息") // @Operation(summary = "信息")
@RequiresPermissions("item:article:info") // @RequiresPermissions("item:article:info")
public Result<ArticleDTO> get(@PathVariable("id") Long id){ // public Result<AccountDTO> get(@PathVariable("id") Long id){
ArticleDTO data = articleService.get(id); // AccountDTO data = articleService.get(id);
//
return new Result<ArticleDTO>().ok(data); // return new Result<AccountDTO>().ok(data);
} // }
//
@PostMapping // @PostMapping
@Operation(summary = "保存") // @Operation(summary = "保存")
@LogOperation("保存") // @LogOperation("保存")
@RequiresPermissions("item:article:save") // @RequiresPermissions("item:article:save")
public Result save(@RequestBody ArticleDTO dto){ // public Result save(@RequestBody AccountDTO dto){
//效验数据 // //效验数据
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class); // ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
List<String> existsList = dictService.isExistsList(dto.getIntroduction()); // List<String> existsList = dictService.isExistsList(dto.getIntroduction());
if (!existsList.isEmpty()){ // if (!existsList.isEmpty()){
return new Result().error("简介出现敏感词:"+existsList); // return new Result().error("简介出现敏感词:"+existsList);
} // }
List<String> contentExistsList = dictService.isExistsList(dto.getContent()); // List<String> contentExistsList = dictService.isExistsList(dto.getContent());
if (!contentExistsList.isEmpty()){ // if (!contentExistsList.isEmpty()){
return new Result().error("发布内容出现敏感词:"+ contentExistsList); // return new Result().error("发布内容出现敏感词:"+ contentExistsList);
} // }
articleService.save(dto); // articleService.save(dto);
return new Result(); // return new Result();
} // }
@PutMapping // @PutMapping
@Operation(summary = "修改") // @Operation(summary = "修改")
@LogOperation("修改") // @LogOperation("修改")
@RequiresPermissions("item:article:update") // @RequiresPermissions("item:article:update")
public Result update(@RequestBody ArticleDTO dto){ // public Result update(@RequestBody AccountDTO dto){
//效验数据 // //效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class); // ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
articleService.update(dto); // articleService.update(dto);
return new Result(); // return new Result();
} // }
//
@DeleteMapping // @DeleteMapping
@Operation(summary = "删除") // @Operation(summary = "删除")
@LogOperation("删除") // @LogOperation("删除")
@RequiresPermissions("item:article:delete") // @RequiresPermissions("item:article:delete")
public Result delete(@RequestBody Long[] ids){ // public Result delete(@RequestBody Long[] ids){
//效验数据 // //效验数据
AssertUtils.isArrayEmpty(ids, "id"); // AssertUtils.isArrayEmpty(ids, "id");
articleService.delete(ids); // articleService.delete(ids);
return new Result(); // return new Result();
} // }
//
//
//
} //}

View File

@ -1,13 +1,13 @@
package io.modules.item.dao; package io.modules.item.dao;
import io.common.dao.BaseDao; import io.common.dao.BaseDao;
import io.modules.item.entity.ArticleEntity; import io.modules.item.entity.AccountEntity;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
/** /**
* 文章表 * 文章表
*/ */
@Mapper @Mapper
public interface ArticleDao extends BaseDao<ArticleEntity> { public interface ArticleDao extends BaseDao<AccountEntity> {
} }

View File

@ -0,0 +1,24 @@
package io.modules.item.dto;
import io.swagger.v3.oas.annotations.media.SchemaProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 用户账户操作记录
*/
@Data
public class AccountDTO implements Serializable {
private static final long serialVersionUID = 1L;
@SchemaProperty(name = "编号")
private Long id;
private Long userId;
private String note;
private String paymentMethod;
private BigDecimal balance;
private Date createTime;
}

View File

@ -1,56 +0,0 @@
package io.modules.item.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.SchemaProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 文章表
*/
@Data
@Schema(name = "文章表")
public class ArticleDTO implements Serializable {
private static final long serialVersionUID = 1L;
@SchemaProperty(name = "编号")
private Long id;
@SchemaProperty(name = "文章标题")
private String title;
private String path;
@SchemaProperty(name = "简介")
private String introduction;
@SchemaProperty(name = "发表用户")
private Long userId;
@SchemaProperty(name = "内容")
private String content;
@SchemaProperty(name = "排序")
private Integer sort;
@SchemaProperty(name = "点赞数量")
private Integer star;
@SchemaProperty(name = "封面图")
private String cover;
@SchemaProperty(name = "创建时间")
private Date createTime;
private String tag;
private String type;
private Integer audit;
private String feedback;
}

View File

@ -42,6 +42,7 @@ public class OrderDTO implements Serializable {
@SchemaProperty(name = "订单总金额") @SchemaProperty(name = "订单总金额")
private BigDecimal totalAmount; private BigDecimal totalAmount;
private BigDecimal price; private BigDecimal price;
private AddressDTO addressDTO; private AddressDTO addressDTO;
@SchemaProperty(name = "支付状态") @SchemaProperty(name = "支付状态")

View File

@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.SchemaProperty; import io.swagger.v3.oas.annotations.media.SchemaProperty;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
@ -34,7 +35,5 @@ public class UserDTO implements Serializable {
private String nickName; private String nickName;
@SchemaProperty(name = "介绍") @SchemaProperty(name = "介绍")
private String introduce; private BigDecimal balance;
} }

View File

@ -0,0 +1,26 @@
package io.modules.item.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 用户账户操作记录
*/
@Data
@TableName("tb_account")
public class AccountEntity {
@TableId(value = "id",type = IdType.AUTO)
private Long id;
private Long userId;
private String note;
private String paymentMethod;
private BigDecimal balance;
private Date createTime;
}

View File

@ -1,68 +0,0 @@
package io.modules.item.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 文章表
*/
@Data
@TableName("tb_article")
public class ArticleEntity {
/**
* 编号
*/
@TableId(value = "id",type = IdType.AUTO)
private Long id;
/**
* 文章标题
*/
private String title;
private String path;
/**
* 简介
*/
private String introduction;
/**
* 发表用户
*/
private Long userId;
/**
* 内容
*/
private String content;
/**
* 排序
*/
private Integer sort;
/**
* 点赞数量
*/
private Integer star;
private Integer audit;
/**
* 封面图
*/
private String cover;
/**
* 创建时间
*/
private Date createTime;
/**
* 类型
*/
private String type;
private String tag;
private String feedback;
}

View File

@ -7,9 +7,6 @@ import java.util.Date;
/** /**
* 敏感词 * 敏感词
*
* @author Mark #
* @since 1.0.0 2024-12-12
*/ */
@Data @Data
@TableName("tb_dict") @TableName("tb_dict")

View File

@ -2,6 +2,8 @@ package io.modules.item.entity;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
/** /**
@ -30,8 +32,5 @@ public class FrontUserEntity {
* 昵称 * 昵称
*/ */
private String nickName; private String nickName;
/** private BigDecimal balance;
* 介绍
*/
private String introduce;
} }

View File

@ -7,9 +7,6 @@ import java.util.Date;
/** /**
* 用户行为表 * 用户行为表
*
* @author Mark #
* @since 1.0.0 2024-12-16
*/ */
@Data @Data
@TableName("tb_user_behavior") @TableName("tb_user_behavior")

View File

@ -0,0 +1,14 @@
package io.modules.item.service;
import io.modules.item.dto.AccountDTO;
import io.modules.item.entity.AccountEntity;
import io.common.service.CrudService;
/**
* 文章表
*/
public interface AccountService extends CrudService<AccountEntity, AccountDTO> {
}

View File

@ -1,14 +0,0 @@
package io.modules.item.service;
import io.modules.item.dto.ArticleDTO;
import io.modules.item.entity.ArticleEntity;
import io.common.service.CrudService;
/**
* 文章表
*/
public interface ArticleService extends CrudService<ArticleEntity, ArticleDTO> {
}

View File

@ -9,9 +9,6 @@ import java.util.List;
/** /**
* 订单表 * 订单表
*
* @author Mark #
* @since 1.0.0 2025-02-14
*/ */
public interface OrderService extends CrudService<OrderEntity, OrderDTO> { public interface OrderService extends CrudService<OrderEntity, OrderDTO> {

View File

@ -0,0 +1,29 @@
package io.modules.item.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.modules.item.dao.ArticleDao;
import io.modules.item.dto.AccountDTO;
import io.modules.item.entity.AccountEntity;
import io.modules.item.service.AccountService;
import cn.hutool.core.util.StrUtil;
import io.common.service.impl.CrudServiceImpl;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class AccountServiceImpl extends CrudServiceImpl<ArticleDao, AccountEntity, AccountDTO> implements AccountService {
@Override
public QueryWrapper<AccountEntity> getWrapper(Map<String, Object> params){
String id = (String)params.get("id");
String userId = (String)params.get("userId");
QueryWrapper<AccountEntity> wrapper = new QueryWrapper<>();
wrapper.eq(StrUtil.isNotBlank(id), "id", id);
wrapper.eq("user_id", userId);
wrapper.orderByDesc("create_time");
return wrapper;
}
}

View File

@ -1,42 +0,0 @@
package io.modules.item.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.modules.item.dao.ArticleDao;
import io.modules.item.dto.ArticleDTO;
import io.modules.item.entity.ArticleEntity;
import io.modules.item.service.ArticleService;
import cn.hutool.core.util.StrUtil;
import io.common.service.impl.CrudServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* 文章表
*/
@Service
public class ArticleServiceImpl extends CrudServiceImpl<ArticleDao, ArticleEntity, ArticleDTO> implements ArticleService {
@Override
public QueryWrapper<ArticleEntity> getWrapper(Map<String, Object> params){
String id = (String)params.get("id");
String type = (String)params.get("type");
Long userId = (Long)params.get("userId");
String audit = (String)params.get("audit");
QueryWrapper<ArticleEntity> wrapper = new QueryWrapper<>();
wrapper.eq(StrUtil.isNotBlank(id), "id", id);
wrapper.eq(StrUtil.isNotBlank(type), "type", type);
wrapper.eq(StrUtil.isNotBlank(audit), "audit", audit);
if (userId != null){
wrapper.eq("user_id", userId);
}
return wrapper;
}
}

View File

@ -41,6 +41,7 @@ public class OrderServiceImpl extends CrudServiceImpl<OrderDao, OrderEntity, Ord
wrapper.eq(StrUtil.isNotBlank(orderStatus), "order_status", orderStatus); wrapper.eq(StrUtil.isNotBlank(orderStatus), "order_status", orderStatus);
wrapper.eq(StrUtil.isNotBlank(paymentStatus), "payment_status", paymentStatus); wrapper.eq(StrUtil.isNotBlank(paymentStatus), "payment_status", paymentStatus);
wrapper.eq(StrUtil.isNotBlank(userId), "user_id", userId); wrapper.eq(StrUtil.isNotBlank(userId), "user_id", userId);
wrapper.orderByDesc("created_time");
return wrapper; return wrapper;
} }

View File

@ -4374,7 +4374,7 @@ CREATE TABLE `tb_user` (
`password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码', `password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
`create_date` datetime NULL DEFAULT NULL COMMENT '创建时间', `create_date` datetime NULL DEFAULT NULL COMMENT '创建时间',
`nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '昵称', `nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '昵称',
`introduce` varchar(600) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '介绍', `balance` varchar(600) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '介绍',
PRIMARY KEY (`id`) USING BTREE PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1893852107006558211 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户' ROW_FORMAT = Dynamic; ) ENGINE = InnoDB AUTO_INCREMENT = 1893852107006558211 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户' ROW_FORMAT = Dynamic;

View File

@ -0,0 +1,79 @@
package io.controller;
import io.annotation.Login;
import io.common.constant.Constant;
import io.modules.item.dto.AccountDTO;
import io.modules.item.service.AccountService;
import io.common.page.PageData;
import io.common.utils.Result;
import io.common.validator.AssertUtils;
import io.common.validator.ValidatorUtils;
import io.common.validator.group.AddGroup;
import io.common.validator.group.DefaultGroup;
import io.common.validator.group.UpdateGroup;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import java.util.Map;
@RestController
@RequestMapping("/api/account")
@CrossOrigin
public class AccountController {
@Autowired
private AccountService articleService;
@Login
@GetMapping("page")
@Operation(summary = "分页")
@Parameters({
@Parameter(name = Constant.PAGE, description = "当前页码从1开始", in = ParameterIn.QUERY, required = true, ref="int") ,
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY,required = true, ref="int") ,
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref="String") ,
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref="String"),
@Parameter(name = "type", description = "类型", in = ParameterIn.QUERY, ref="String")
})
public Result<PageData<AccountDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params,@Parameter(hidden = true) @RequestAttribute("userId") Long userId){
params.put("userId",userId.toString());
PageData<AccountDTO> page = articleService.page(params);
return new Result<PageData<AccountDTO>>().ok(page);
}
@GetMapping("{id}")
public Result<AccountDTO> get(@PathVariable("id") Long id){
AccountDTO data = articleService.get(id);
return new Result<AccountDTO>().ok(data);
}
@PostMapping
@Operation(summary = "保存")
public Result save(@RequestBody AccountDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
articleService.save(dto);
return new Result();
}
@PutMapping
@Operation(summary = "修改")
public Result update(@RequestBody AccountDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
articleService.update(dto);
return new Result();
}
@DeleteMapping
@Operation(summary = "删除")
public Result delete(@RequestBody Long[] ids){
//效验数据
AssertUtils.isArrayEmpty(ids, "id");
articleService.delete(ids);
return new Result();
}
}

View File

@ -2,7 +2,9 @@ package io.controller;
import io.annotation.Login; import io.annotation.Login;
import io.annotation.LoginUser;
import io.common.constant.Constant; import io.common.constant.Constant;
import io.common.exception.RenException;
import io.common.page.PageData; import io.common.page.PageData;
import io.common.utils.Result; import io.common.utils.Result;
import io.common.validator.AssertUtils; import io.common.validator.AssertUtils;
@ -10,10 +12,14 @@ import io.common.validator.ValidatorUtils;
import io.common.validator.group.AddGroup; import io.common.validator.group.AddGroup;
import io.common.validator.group.DefaultGroup; import io.common.validator.group.DefaultGroup;
import io.common.validator.group.UpdateGroup; import io.common.validator.group.UpdateGroup;
import io.entity.UserEntity;
import io.modules.item.dto.AccountDTO;
import io.modules.item.dto.ItemDTO; import io.modules.item.dto.ItemDTO;
import io.modules.item.dto.OrderDTO; import io.modules.item.dto.OrderDTO;
import io.modules.item.service.AccountService;
import io.modules.item.service.ItemService; import io.modules.item.service.ItemService;
import io.modules.item.service.OrderService; import io.modules.item.service.OrderService;
import io.service.UserService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@ -23,6 +29,7 @@ import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.Parameters;
import java.math.BigDecimal;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -41,6 +48,10 @@ public class OrderController {
@Autowired @Autowired
private ItemService itemService; private ItemService itemService;
@Autowired
private UserService userService;
@Autowired
private AccountService accountService;
@Value("${upload.url}") @Value("${upload.url}")
private String uploadUrl; private String uploadUrl;
@ -80,12 +91,45 @@ public class OrderController {
@PostMapping @PostMapping
@Operation(summary = "保存") @Operation(summary = "保存")
@Login @Login
public Result save(@RequestBody OrderDTO dto,@Parameter(hidden = true) @RequestAttribute("userId") Long userId){ public Result save(@RequestBody OrderDTO dto, @Parameter(hidden = true) @LoginUser UserEntity user){
dto.setUserId(userId);
//判断余额是否充足
BigDecimal balance = user.getBalance();
BigDecimal totalAmount = dto.getTotalAmount();
if (!isBalanceSufficient(balance, totalAmount)) {
throw new RenException("账户余额不足,当前余额: " + balance + ",需支付: " + totalAmount);
}
//余额充足
BigDecimal subtract = user.getBalance().subtract(totalAmount);
user.setBalance(subtract);
userService.updateById(user);
//添加日志
AccountDTO account = new AccountDTO();
account.setUserId(user.getId());
account.setNote("购买");
account.setBalance(subtract);
accountService.save(account);
dto.setUserId(user.getId());
orderService.save(dto); orderService.save(dto);
return new Result(); return new Result();
} }
public boolean isBalanceSufficient(BigDecimal userBalance, BigDecimal requiredAmount) {
// 1. 检查参数是否为null安全防护
if (userBalance == null || requiredAmount == null) {
throw new IllegalArgumentException("金额参数不能为null");
}
// 2. 比较余额是否足够使用compareTo方法
// compareTo返回:
// -1 表示 userBalance < requiredAmount
// 0 表示 userBalance = requiredAmount
// 1 表示 userBalance > requiredAmount
return userBalance.compareTo(requiredAmount) >= 0;
}
@PutMapping @PutMapping
@Operation(summary = "修改") @Operation(summary = "修改")
public Result update(@RequestBody OrderDTO dto){ public Result update(@RequestBody OrderDTO dto){

View File

@ -8,14 +8,18 @@ import io.common.validator.ValidatorUtils;
import io.dto.LoginDTO; import io.dto.LoginDTO;
import io.dto.RegisterDTO; import io.dto.RegisterDTO;
import io.entity.UserEntity; import io.entity.UserEntity;
import io.modules.item.dto.AccountDTO;
import io.modules.item.service.AccountService;
import io.service.TokenService; import io.service.TokenService;
import io.service.UserService; import io.service.UserService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
@ -30,6 +34,7 @@ import java.util.Map;
public class UserController { public class UserController {
private final UserService userService; private final UserService userService;
private final AccountService accountService;
private final TokenService tokenService; private final TokenService tokenService;
@PostMapping("register") @PostMapping("register")
@Operation(summary = "注册") @Operation(summary = "注册")
@ -67,18 +72,60 @@ public class UserController {
@PutMapping("update") @PutMapping("update")
@Operation(summary = "修改信息") @Operation(summary = "修改信息")
public Result update(@RequestBody RegisterDTO dto) { public Result update(@RequestBody RegisterDTO dto) {
if (!dto.getPassword().equals(dto.getConfirmPassword())){
return new Result().error("密码不一致");
}
//表单校验 //表单校验
ValidatorUtils.validateEntity(dto); ValidatorUtils.validateEntity(dto);
UserEntity user = new UserEntity(); UserEntity user = new UserEntity();
user.setId(dto.getId()); BeanUtils.copyProperties(dto,user);
user.setUsername(dto.getUsername()); if (dto.getPassword() !=null){
user.setNickName(dto.getNickName());
user.setIntroduce(dto.getIntroduce());
user.setPassword(DigestUtil.sha256Hex(dto.getPassword())); user.setPassword(DigestUtil.sha256Hex(dto.getPassword()));
}
userService.updateById(user); userService.updateById(user);
return new Result(); return new Result();
} }
//充值
@Login
@PostMapping("recharge")
@Operation(summary = "充值")
public Result recharge(@RequestBody AccountDTO dto, @Parameter(hidden = true) @LoginUser UserEntity user) {
//添加账户金额
BigDecimal total = user.getBalance().add(dto.getBalance());
user.setBalance(total);
userService.updateById(user);
//添加记录
AccountDTO account = new AccountDTO();
account.setUserId(user.getId());
account.setNote("充值");
account.setBalance(total);
accountService.save(account);
return new Result();
}
//提现
// @Login
// @PostMapping("withdraw")
// @Operation(summary = "提现")
// public Result withdraw(@RequestBody AccountDTO dto, @Parameter(hidden = true) @LoginUser UserEntity user) {
//
// //添加账户金额
// BigDecimal total = user.getBalance().add(dto.getBalance());
// user.setBalance(total);
// userService.updateById(user);
// //添加记录
// AccountDTO account = new AccountDTO();
// account.setUserId(user.getId());
// account.setDescribe("充值");
// account.setBalance(total);
// accountService.save(account);
// return new Result();
// }
@Login @Login
@PostMapping("logout") @PostMapping("logout")
@ -95,10 +142,4 @@ public class UserController {
return new Result<UserEntity>().ok(user); return new Result<UserEntity>().ok(user);
} }
@Login
@GetMapping("userId")
@Operation(summary = "获取用户ID")
public Result<Long> userInfo(@Parameter(hidden = true) @RequestAttribute("userId") Long userId) {
return new Result<Long>().ok(userId);
}
} }

View File

@ -6,6 +6,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal;
/** /**
* 注册表单 * 注册表单
@ -26,10 +28,6 @@ public class RegisterDTO {
@Schema(title = "密码") @Schema(title = "密码")
@NotBlank(message="确认密码不能为空") @NotBlank(message="确认密码不能为空")
private String confirmPassword; private String confirmPassword;
@Schema(title = "昵称")
private String nickName; private String nickName;
private BigDecimal balance;
@Schema(title = "介绍")
private String introduce;
} }

View File

@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
/** /**
@ -32,7 +33,7 @@ public class UserEntity implements Serializable {
/** /**
* 介绍 * 介绍
*/ */
private String introduce; private BigDecimal balance;
/** /**
* 用户名 * 用户名
*/ */

View File

@ -162,8 +162,6 @@ const handleBuy = () => {
*/ */
const handleChange = () => { const handleChange = () => {
state.buyForm.totalAmount = (state.info.price * state.buyForm.quantity).toFixed(2); state.buyForm.totalAmount = (state.info.price * state.buyForm.quantity).toFixed(2);
} }
</script> </script>
<style scoped> <style scoped>

View File

@ -34,10 +34,10 @@ const state = reactive({
activeIndex:'/user', activeIndex:'/user',
userMenu:[ userMenu:[
{name: '个人中心', path: '/user'}, {name: '个人中心', path: '/user'},
{name: '账户明细', path: '/balance'},
{name: '我的订单', path: '/order'},
{name: '收货地址', path: '/address'}, {name: '收货地址', path: '/address'},
{name: '我的收藏', path: '/collect'}, {name: '我的收藏', path: '/collect'},
{name: '我的订单', path: '/order'},
] ]
}) })

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <el-card shadow="never">
<!--查交易记录的按钮--> <!--查交易记录的按钮-->
<el-button type="primary" round @click="openAddDialog" size="small">添加</el-button> <el-button type="primary" round @click="openAddDialog" size="small">添加</el-button>
@ -68,7 +68,7 @@
<el-button type="primary" @click="saveTransaction(formRef)">保存</el-button> <el-button type="primary" @click="saveTransaction(formRef)">保存</el-button>
</div> </div>
</el-dialog> </el-dialog>
</div> </el-card>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// //

View File

@ -13,12 +13,12 @@
<img :src="row.item.image" style="width: 100px; height: 100px;"> <img :src="row.item.image" style="width: 100px; height: 100px;">
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="price" label="购买单价" /> <el-table-column prop="price" label="购买单价" align="center" />
<el-table-column prop="quantity" label="购买数量" /> <el-table-column prop="quantity" label="购买数量" align="center" />
<el-table-column prop="totalAmount" label="成交总价" /> <el-table-column prop="totalAmount" label="成交总价" align="center" />
<el-table-column prop="createdTime" label="购买时间" width="220" /> <el-table-column prop="createdTime" label="购买时间"align="center" />
<el-table-column prop="addressDTO.city" label="收货地址" width="220" /> <el-table-column prop="addressDTO.city" label="收货地址" width="220" align="center" />
<el-table-column label="操作" min-width="120"> <el-table-column label="操作" min-width="120" align="center" >
<template #default="scope" > <template #default="scope" >
<el-button link type="primary" size="small" v-if="state.page.orderStatus == 0" @click="update(scope.row,1)">开始发货</el-button> <el-button link type="primary" size="small" v-if="state.page.orderStatus == 0" @click="update(scope.row,1)">开始发货</el-button>
<el-button link type="primary" size="small" v-if="state.page.orderStatus == 1" @click="update(scope.row,2)">确认收货</el-button> <el-button link type="primary" size="small" v-if="state.page.orderStatus == 1" @click="update(scope.row,2)">确认收货</el-button>

View File

@ -20,7 +20,7 @@
<el-table-column prop="username" label="账号"/> <el-table-column prop="username" label="账号"/>
<el-table-column prop="createDate" label="创建时间"/> <el-table-column prop="createDate" label="创建时间"/>
<el-table-column prop="nickName" label="昵称"/> <el-table-column prop="nickName" label="昵称"/>
<el-table-column prop="introduce" label="介绍"/> <el-table-column prop="balance" label="介绍"/>
<!--列表结束--> <!--列表结束-->
<el-table-column label="操作" align="center" > <el-table-column label="操作" align="center" >
<template #default="scope"> <template #default="scope">
@ -65,8 +65,8 @@
<el-form-item label="昵称" prop="nickName" :rules="[{ required: true, message: '请输入昵称', trigger: 'blur' }]"> <el-form-item label="昵称" prop="nickName" :rules="[{ required: true, message: '请输入昵称', trigger: 'blur' }]">
<el-input v-model="state.formData.nickName"/> <el-input v-model="state.formData.nickName"/>
</el-form-item> </el-form-item>
<el-form-item label="介绍" prop="introduce" :rules="[{ required: true, message: '请输入介绍', trigger: 'blur' }]"> <el-form-item label="介绍" prop="balance" :rules="[{ required: true, message: '请输入介绍', trigger: 'blur' }]">
<el-input v-model="state.formData.introduce"/> <el-input v-model="state.formData.balance"/>
</el-form-item> </el-form-item>
<!--表单结束===============================================================================================================================--> <!--表单结束===============================================================================================================================-->
</el-form> </el-form>

View File

@ -1,5 +1,6 @@
<!--用户详情--> <!--用户详情-->
<template> <template>
<el-card shadow="never">
<el-tabs v-model="state.activeName" > <el-tabs v-model="state.activeName" >
<el-tab-pane v-for="status in state.getOrderStatus" :label="status.name" :name="status.status"> <el-tab-pane v-for="status in state.getOrderStatus" :label="status.name" :name="status.status">
<el-table :data="state.getList"> <el-table :data="state.getList">
@ -34,6 +35,8 @@
</el-table> </el-table>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</el-card>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'

View File

@ -3,7 +3,81 @@
<!-- 顶部内容--> <!-- 顶部内容-->
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<info-top></info-top> <el-row :gutter="20" class="info">
<el-col :span="10">
<!-- 详情图片-->
<el-image :src="state.info.image" fit="contain" />
</el-col>
<el-col :span="14">
<!-- 标题-->
<h1>{{ state.info.title }} </h1>
<!-- 简介-->
<div class="introduction" v-if="state.info.tag"><span style="font-weight: 700">作者:</span>
{{ state.info.tag }}
</div>
<div class="introduction" v-if="state.info.stockQuantity"><span style="font-weight: 700">库存:</span>
{{ state.info.stockQuantity }}
</div>
<div class="introduction" v-if="state.info.price">
<span style="font-weight: 700">价格:</span> <span style="color:red">{{ state.info.price }} </span></div>
<!--操作-->
<div class="operate">
<!-- 加入购物车-->
<!-- <el-button type="primary" @click="handleCart">加入购物车</el-button>-->
<!-- 立即购买-->
<el-button type="primary" @click="handleBuy" v-if="state.info.price">立即购买</el-button>
<!-- 收藏-->
<el-button style="width: 220px" type="primary" @click="handleFavorite">
{{ state.info.isFavorite ? '已收藏' : '未收藏' }}
</el-button>
</div>
</el-col>
</el-row>
<!-- 抽屉-->
<el-drawer v-model="buyDrawer" title="购买">
<el-form
ref="formRef"
style="max-width: 600px"
:model="state.buyForm"
label-width="auto"
label-position="top"
>
<el-form-item prop="title" label="商品名称">
<el-input disabled v-model="state.buyForm.title" />
</el-form-item>
<el-form-item prop="title" label="商品单价">
<el-text class="mx-1" type="danger">{{ state.buyForm.price }}</el-text>
</el-form-item>
<el-form-item prop="total" label="购买数量">
<el-input-number
v-model="state.buyForm.quantity" :min="1" :max="state.info.stockQuantity" @change="handleChange" />
</el-form-item>
<el-form-item prop="title" label="总价">
<el-text class="mx-1" type="danger">{{ state.buyForm.totalAmount }}</el-text>
</el-form-item>
<el-form-item prop="addressId" label="选择收货地址" :rules="[
{
required: true,
message: '选择收货地址',
trigger: 'blur',
}
]">
<el-select v-model="state.buyForm.addressId" placeholder="请选择地址" style="width: 240px">
<el-option
v-for="item in state.cateList"
:key="item.id"
:label="item.city"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="buySubmitForm(formRef)">确定</el-button>
</el-form-item>
</el-form>
</el-drawer>
</el-col> </el-col>
</el-row> </el-row>
<div class="h-30px"></div> <div class="h-30px"></div>
@ -12,22 +86,136 @@
<info-bottom></info-bottom> <info-bottom></info-bottom>
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import InfoTop from '~/components/front/info-top.vue'
import InfoBottom from '~/components/front/info-bottom.vue' import InfoBottom from '~/components/front/info-bottom.vue'
import { useRouter } from 'vue-router' import { reactive } from 'vue'
const router = useRouter() import type { FormInstance } from 'element-plus'
const buyDrawer = ref(false)
const formRef = ref<FormInstance>()
import { useRoute } from 'vue-router'
const route = useRoute()
const itemId = route.params.id
const state = reactive(<any>{
info: {},
buyForm: {
itemId: itemId,
title: '',
quantity: 1,
totalAmount: 0
},
cateList: []
})
// route.params.id
watch(() => route.params.id,
(newId) => {
window.location.href = `/info/${newId}`
},
{ deep: true }
)
function init() {
frontRequest.get(`/api/item/${itemId}`).then(response => {
state.info = response.data
})
frontRequest.get(`api/address/page`).then(response => {
state.cateList = response.data.list
})
}
onMounted(() => { onMounted(() => {
if (!userStore().frontIsLogin){ init()
toast.warning("登录失效") })
router.push("/login")
/**
* 用户收藏
*/
function handleFavorite() {
if (state.info.isFavorite) {
frontRequest.post('/api/behavior/delete', { itemId: itemId, type: 1 }).then(res => {
ElMessage.success('取消成功')
init()
})
} else {
frontRequest.post('/api/behavior', { itemId: itemId, type: 1 }).then(res => {
ElMessage.success('收藏成功')
init()
})
}
}
/**
* 购买按钮提交
* @param formEl
*/
const buySubmitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
delete state.buyForm.id
frontRequest.post('/api/order', state.buyForm).then(res => {
ElMessage.success('购买成功')
buyDrawer.value = false
})
} }
}) })
}
/**
* 购买按钮
*/
const handleBuy = () => {
if (state.info.stockQuantity == 0) {
ElMessage.warning('当前库存不足')
return
}
buyDrawer.value = true
state.buyForm.title = state.info.title
state.buyForm.id = state.info.id
state.buyForm.price = state.info.price
state.buyForm.totalAmount = (state.info.price * state.buyForm.quantity).toFixed(2)
}
/**
* 添加数量
*/
const handleChange = () => {
state.buyForm.totalAmount = (state.info.price * state.buyForm.quantity).toFixed(2)
}
</script> </script>
<style scoped> <style scoped>
.info {
background: linear-gradient(to bottom, #dfe8f6, #e0e0e0); /* 清新渐变背景 */
background-color: #fdfdfe;
height: 500px;
padding: 20px;
h1 {
color: #11192d;
font-size: 38px;
font-weight: 600;
margin-bottom: 20px;
}
.introduction {
font-size: 14px;
margin-bottom: 20px;
}
.tag {
margin-bottom: 20px;
}
}
:deep(.el-image) {
border-radius: 10px;
height: 420px;
margin-left: 30px;
}
</style> </style>
<route lang="json"> <route lang="json">
{ {

View File

@ -1,5 +1,7 @@
<!--用户详情--> <!--用户详情-->
<template> <template>
<el-card shadow="never">
<el-tabs v-model="state.page.orderStatus" @tab-click="handleClick"> <el-tabs v-model="state.page.orderStatus" @tab-click="handleClick">
<el-tab-pane v-for="status in state.getOrderStatus" :label="status.name" :name="status.status"> <el-tab-pane v-for="status in state.getOrderStatus" :label="status.name" :name="status.status">
<el-table <el-table
@ -8,16 +10,16 @@
> >
<el-table-column prop="id" label="订单编号" /> <el-table-column prop="id" label="订单编号" />
<el-table-column prop="item.title" label="商品名称" /> <el-table-column prop="item.title" label="商品名称" />
<el-table-column prop="price" label="图片" > <el-table-column prop="price" label="图片" align="center" width="150">
<template #default="{ row }"> <template #default="{ row }">
<img :src="row.item.image" style="width: 100px; height: 100px;"> <img :src="row.item.image" style="width: 200px; height: 100px;">
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="price" label="购买单价" /> <el-table-column prop="price" label="购买单价" align="center"/>
<el-table-column prop="quantity" label="购买数量" /> <el-table-column prop="quantity" label="购买数量" align="center" />
<el-table-column prop="totalAmount" label="成交总价" /> <el-table-column prop="totalAmount" label="成交总价" align="center"/>
<el-table-column prop="createdTime" label="购买时间" width="220" /> <el-table-column prop="createdTime" label="购买时间" width="220" align="center"/>
<el-table-column label="操作" min-width="120"> <el-table-column label="操作" min-width="120" align="center">
<template #default="scope" > <template #default="scope" >
<el-button link type="primary" size="small" v-if="state.page.orderStatus == 1" @click="update(scope.row,2)">确认收货</el-button> <el-button link type="primary" size="small" v-if="state.page.orderStatus == 1" @click="update(scope.row,2)">确认收货</el-button>
<el-button link type="primary" size="small" v-if="state.page.orderStatus == 2" @click="update(scope.row,3)">我要评价</el-button> <el-button link type="primary" size="small" v-if="state.page.orderStatus == 2" @click="update(scope.row,3)">我要评价</el-button>
@ -71,13 +73,13 @@
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
</el-card>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive } from 'vue' import { reactive } from 'vue'
import { FormInstance, TabsPaneContext } from 'element-plus' import { FormInstance, TabsPaneContext } from 'element-plus'
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
const state = reactive({ const state = reactive({
getOrderStatus:[ getOrderStatus:[
@ -93,7 +95,6 @@ const state = reactive({
page:{ page:{
page:1, page:1,
limit:9999, limit:9999,
order:'desc',
orderStatus:0, orderStatus:0,
} }
}) })

View File

@ -1,12 +1,26 @@
<!--用户详情-->
<template> <template>
<el-card> <el-card>
<template #header> <template #header>
<div class="card-header"> <div class="card-header">
<span>个人信息</span> <span>个人信息</span>
</div> </div>
</template> </template>
<!-- 余额信息卡片 -->
<el-card shadow="hover" style="margin-bottom: 20px">
<div style="display: flex; justify-content: space-between; align-items: center">
<div>
<div style="font-size: 14px; color: #909399">账户余额</div>
<div style="font-size: 24px; font-weight: bold; color: #409EFF">
{{ state.balance }}
</div>
</div>
<div>
<el-button type="primary" @click="state.rechargeDialogVisible = true">充值</el-button>
<!-- <el-button type="success" @click="state.withdrawDialogVisible = true">提现</el-button>-->
</div>
</div>
</el-card>
<el-form <el-form
ref="formRef" ref="formRef"
style="max-width: 600px" style="max-width: 600px"
@ -50,7 +64,7 @@
}, },
]" ]"
> >
<el-input v-model="state.userInfo.password" /> <el-input v-model="state.userInfo.password" type="password" show-password />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
prop="confirmPassword" prop="confirmPassword"
@ -63,64 +77,221 @@
}, },
]" ]"
> >
<el-input v-model="state.userInfo.confirmPassword" /> <el-input v-model="state.userInfo.confirmPassword" type="password" show-password />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="submitForm(formRef)" style="width: 260px">提交</el-button> <el-button type="primary" @click="submitForm(formRef)" style="width: 260px">提交</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card>
<!-- 充值对话框 -->
<el-dialog v-model="state.rechargeDialogVisible" title="账户充值" width="30%">
<el-form :model="state.rechargeForm" label-width="100px">
<el-form-item label="充值金额" required>
<el-input-number
v-model="state.rechargeForm.amount"
:min="1"
:max="100000"
:precision="2"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="支付方式">
<el-select v-model="state.rechargeForm.paymentMethod" placeholder="请选择支付方式" style="width: 100%">
<el-option label="支付宝" value="alipay" />
<el-option label="微信支付" value="wechat" />
<el-option label="银行卡" value="bank" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="state.rechargeDialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleRecharge">确认充值</el-button>
</span>
</template> </template>
</el-dialog>
<!-- 提现对话框 -->
<el-dialog v-model="state.withdrawDialogVisible" title="账户提现" width="30%">
<el-form :model="state.withdrawForm" label-width="100px">
<el-form-item label="提现金额" required>
<el-input-number
v-model="state.withdrawForm.amount"
:min="1"
:max="state.balance"
:precision="2"
controls-position="right"
style="width: 100%"
/>
<div style="font-size: 12px; color: #909399; margin-top: 5px">
可提现余额: {{ state.balance.toFixed(2) }}
</div>
</el-form-item>
<el-form-item label="提现方式">
<el-select v-model="state.withdrawForm.withdrawMethod" placeholder="请选择提现方式" style="width: 100%">
<el-option label="支付宝" value="alipay" />
<el-option label="银行卡" value="bank" />
</el-select>
</el-form-item>
<el-form-item label="收款账号" required v-if="state.withdrawForm.withdrawMethod">
<el-input v-model="state.withdrawForm.account" placeholder="请输入收款账号" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="state.withdrawDialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleWithdraw">确认提现</el-button>
</span>
</template>
</el-dialog>
</el-card>
</template>
<script setup lang="ts"> <script setup lang="ts">
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import { reactive } from 'vue' import { reactive, ref } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
const router = useRouter() const router = useRouter()
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
const state = reactive({ const state = reactive({
userInfo: {} userInfo: {},
balance: 0,
rechargeDialogVisible: false,
withdrawDialogVisible: false,
rechargeForm: {
amount: 100,
paymentMethod: 'alipay'
},
withdrawForm: {
amount: 0,
withdrawMethod: '',
account: ''
}
}) })
function init() { function init() {
frontRequest.get("/api/user/userInfo").then(res => { frontRequest.get("/api/user/userInfo").then(res => {
state.userInfo = res.data state.userInfo = res.data || {}
console.log(res.data.balance)
state.balance = res.data.balance || 0
}) })
} }
onMounted(() => { onMounted(() => {
// if (!userStore().frontIsLogin){
// toast.warning("")
// router.push("/login")
// }
init() init()
}) })
/** /**
* 提交 * 提交表单
* @param formEl * @param formEl
*/ */
const submitForm = (formEl: FormInstance | undefined) => { const submitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.validate((valid) => { formEl.validate((valid) => {
if (valid) { if (valid) {
frontRequest.put("/api/user/update", state.userInfo).then(res => { frontRequest.put("/api/user/update", state.userInfo).then(res => {
ElMessage.success("修改成功") ElMessage.success("修改成功")
router.push("/login") router.push("/login")
}) })
} }
}) })
} }
/**
* 处理充值
*/
const handleRecharge = () => {
if (state.rechargeForm.amount <= 0) {
ElMessage.error('充值金额必须大于0')
return
}
frontRequest.post("/api/user/recharge", {
balance: state.rechargeForm.amount,
paymentMethod: state.rechargeForm.paymentMethod
}).then(res => {
ElMessage.success(`充值成功,金额: ${state.rechargeForm.amount}`)
init()
state.rechargeDialogVisible = false
//
state.rechargeForm.amount = 100
}).catch(err => {
ElMessage.error('充值失败: ' + (err.message || '未知错误'))
})
}
/**
* 处理提现
*/
const handleWithdraw = () => {
if (state.withdrawForm.amount <= 0) {
ElMessage.error('提现金额必须大于0')
return
}
if (state.withdrawForm.amount > state.balance) {
ElMessage.error('提现金额不能超过账户余额')
return
}
if (!state.withdrawForm.withdrawMethod) {
ElMessage.error('请选择提现方式')
return
}
if (!state.withdrawForm.account) {
ElMessage.error('请输入收款账号')
return
}
ElMessageBox.confirm(
`确认提现 ${state.withdrawForm.amount} 元到 ${state.withdrawForm.withdrawMethod === 'alipay' ? '支付宝' : '银行卡'} 账号 ${state.withdrawForm.account}?`,
'提现确认',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
frontRequest.post("/api/user/withdraw", {
amount: state.withdrawForm.amount,
withdrawMethod: state.withdrawForm.withdrawMethod,
account: state.withdrawForm.account
}).then(res => {
ElMessage.success(`提现申请已提交,金额: ${state.withdrawForm.amount}`)
state.balance -= state.withdrawForm.amount
state.withdrawDialogVisible = false
//
state.withdrawForm = {
amount: 0,
withdrawMethod: '',
account: ''
}
}).catch(err => {
ElMessage.error('提现失败: ' + (err.message || '未知错误'))
})
}).catch(() => {
//
})
}
</script> </script>
<style scoped> <style scoped>
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
/* 余额卡片样式 */
.el-card {
margin-bottom: 20px;
}
</style> </style>
<route lang="json"> <route lang="json">
{ {
"meta": { "meta": {