10 Commits

Author SHA1 Message Date
xuelijun
720937581f 库存 2025-10-31 15:16:15 +08:00
xuelijun
261a8b4797 商品详情1 2025-10-29 16:48:35 +08:00
c283800915 调整产品 2025-10-29 16:37:25 +08:00
483abcfd83 调整用户接口 2025-10-29 15:07:49 +08:00
4ebe4f9ac6 添加订单接口 2025-10-28 09:34:17 +08:00
90e28f056a 添加订单接口 2025-10-27 16:51:14 +08:00
a5a10898a2 Merge branch 'refs/heads/feature/xuelijun' into feature/order 2025-10-27 14:28:59 +08:00
4042fd297d 订单详情接口调整 2025-10-27 09:10:03 +08:00
xuelijun
3497962627 Merge branch 'feature/order' into xlj 2025-10-24 17:30:30 +08:00
xuelijun
7fdf546585 Merge remote-tracking branch 'origin/feature/order' into xlj 2025-10-16 15:30:47 +08:00
147 changed files with 1681 additions and 1755 deletions

View File

@@ -1,51 +0,0 @@
-- 会员用户表 (tz_member_user)
CREATE TABLE `tz_member_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`mobile` varchar(11) NOT NULL COMMENT '手机',
`password` varchar(128) NOT NULL COMMENT '加密后的密码',
`status` tinyint(4) NOT NULL COMMENT '帐号状态 (枚举 CommonStatusEnum)',
`register_ip` varchar(32) DEFAULT NULL COMMENT '注册 IP',
`register_terminal` tinyint(4) DEFAULT NULL COMMENT '注册终端 (枚举 TerminalEnum)',
`login_ip` varchar(32) DEFAULT NULL COMMENT '最后登录IP',
`login_date` datetime DEFAULT NULL COMMENT '最后登录时间',
`nickname` varchar(64) DEFAULT NULL COMMENT '用户昵称',
`avatar` varchar(512) DEFAULT NULL COMMENT '用户头像',
`name` varchar(64) DEFAULT NULL COMMENT '真实名字',
`sex` tinyint(4) DEFAULT NULL COMMENT '性别 (枚举 SexEnum)',
`birthday` datetime DEFAULT NULL COMMENT '出生日期',
`area_id` int(11) DEFAULT NULL COMMENT '所在地 (关联 Area.id 字段)',
`mark` varchar(512) DEFAULT NULL COMMENT '用户备注',
`point` int(11) DEFAULT NULL COMMENT '积分',
`tag_ids` varchar(512) DEFAULT NULL COMMENT '会员标签列表,以逗号分隔',
`level_id` bigint(20) DEFAULT NULL COMMENT '会员级别编号 (关联 MemberLevelDO.id 字段)',
`experience` int(11) DEFAULT NULL COMMENT '会员经验',
`group_id` bigint(20) DEFAULT NULL COMMENT '用户分组编号 (关联 MemberGroupDO.id 字段)',
`tenant_id` bigint(20) NOT NULL COMMENT '租户ID',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '最后更新时间',
`creator` varchar(64) NOT NULL COMMENT '创建者',
`updater` varchar(64) NOT NULL COMMENT '更新者',
`deleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_mobile` (`mobile`),
KEY `idx_level_id` (`level_id`),
KEY `idx_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员用户表';
-- 用户收件地址表 (tz_member_address)
CREATE TABLE `tz_member_address` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`user_id` bigint(20) NOT NULL COMMENT '用户编号',
`name` varchar(64) NOT NULL COMMENT '收件人名称',
`mobile` varchar(11) NOT NULL COMMENT '手机号',
`area_id` bigint(20) NOT NULL COMMENT '地区编号',
`detail_address` varchar(512) NOT NULL COMMENT '收件详细地址',
`default_status` tinyint(1) DEFAULT NULL COMMENT '是否默认 (true - 默认收件地址)',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '最后更新时间',
`creator` varchar(64) NOT NULL COMMENT '创建者',
`updater` varchar(64) NOT NULL COMMENT '更新者',
`deleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户收件地址表';

View File

@@ -307,4 +307,20 @@ CREATE TABLE `tz_trade_delivery_pick_up_store`
) ENGINE = InnoDB ) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='自提门店表'; DEFAULT CHARSET = utf8mb4 COMMENT ='自提门店表';
-- 订单预约时间修改记录表 (tz_trade_sub_log)
CREATE TABLE `tz_trade_sub_log`
(
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`user_id` bigint(20) NOT NULL COMMENT '用户编号',
`order_id` bigint(20) NOT NULL COMMENT '订单号',
`sub_time` datetime NOT NULL COMMENT '预约时间',
`create_time` datetime NOT NULL COMMENT '创建时间',
`creator` varchar(64) NOT NULL COMMENT '创建者',
`updater` varchar(64) NOT NULL COMMENT '更新者',
`deleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`),
KEY `idx_order_id` (`order_id`),
KEY `idx_user_id` (`user_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='订单预约时间修改记录表';

90
sql/mysql/user.sql Normal file
View File

@@ -0,0 +1,90 @@
-- 登录用户表 (tz_login_user) 后续拓展用户信息表
CREATE TABLE `tz_user_login`
(
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`mobile` varchar(11) NOT NULL COMMENT '手机',
`password` varchar(128) NOT NULL COMMENT '加密后的密码',
`status` tinyint(4) NOT NULL COMMENT '帐号状态 (枚举 CommonStatusEnum)',
`register_ip` varchar(32) DEFAULT NULL COMMENT '注册 IP',
`register_terminal` tinyint(4) DEFAULT NULL COMMENT '注册渠道 (枚举 TerminalEnum)',
`register_date` datetime DEFAULT NULL COMMENT '注册时间',
`login_ip` varchar(32) DEFAULT NULL COMMENT '最后登录IP',
`login_date` datetime DEFAULT NULL COMMENT '最后登录时间',
`login_terminal` varchar(32) DEFAULT NULL COMMENT '最后登录设备',
`nickname` varchar(64) DEFAULT NULL COMMENT '用户昵称',
`avatar` varchar(512) DEFAULT NULL COMMENT '用户头像',
`remark` varchar(512) DEFAULT NULL COMMENT '用户备注',
`tenant_id` bigint(20) NOT NULL COMMENT '租户ID',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '最后更新时间',
`creator` varchar(64) NOT NULL COMMENT '创建者',
`updater` varchar(64) NOT NULL COMMENT '更新者',
`deleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_mobile` (`mobile`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='登录用户表';
-- 会员信息表 (tz_user_member)
CREATE TABLE `tz_user_member`
(
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`name` varchar(64) DEFAULT NULL COMMENT '真实名字',
`sex` tinyint DEFAULT NULL COMMENT '性别 (枚举 SexEnum)',
`birthday` datetime DEFAULT NULL COMMENT '出生日期',
`area_id` int DEFAULT NULL COMMENT '所在地 (关联 Area.id 字段)',
`point` int DEFAULT NULL COMMENT '积分',
`tag_ids` varchar(512) DEFAULT NULL COMMENT '会员标签列表,以逗号分隔',
`level_id` bigint DEFAULT NULL COMMENT '会员级别编号 (关联 MemberLevelDO.id 字段)',
`experience` int DEFAULT NULL COMMENT '会员经验',
`group_id` bigint DEFAULT NULL COMMENT '用户分组编号 (关联 MemberGroupDO.id 字段)',
`tenant_id` bigint(20) NOT NULL COMMENT '租户ID',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '最后更新时间',
`creator` varchar(64) NOT NULL COMMENT '创建者',
`updater` varchar(64) NOT NULL COMMENT '更新者',
`deleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='会员信息表';
-- 会员地址表 (tz_user_member_address)
CREATE TABLE `tz_user_member_address`
(
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户编号',
`name` varchar(128) DEFAULT NULL COMMENT '收件人名称',
`mobile` varchar(11) DEFAULT NULL COMMENT '手机号',
`areaId` bigint(20) DEFAULT NULL COMMENT '地区编号',
`detailAddress` varchar(255) DEFAULT NULL COMMENT '收件详细地址',
`defaultStatus` int DEFAULT NULL COMMENT '是否默认',
`tenant_id` bigint(20) NOT NULL COMMENT '租户ID',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '最后更新时间',
`creator` varchar(64) NOT NULL COMMENT '创建者',
`updater` varchar(64) NOT NULL COMMENT '更新者',
`deleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='会员地址表';
-- 会员等级表 (tz_user_member_level)
CREATE TABLE `tz_user_member_level`
(
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`level_name` varchar(64) DEFAULT NULL COMMENT '等级名称',
`level` int DEFAULT NULL COMMENT '性别 (枚举 SexEnum)',
`experience` int DEFAULT NULL COMMENT '会员经验',
`discount_percent` int DEFAULT NULL COMMENT '享受折扣',
`icon` varchar(128) DEFAULT NULL COMMENT '等级图标',
`background_url` varchar(128) DEFAULT NULL COMMENT '等级背景图',
`status` int DEFAULT NULL COMMENT '状态',
`tenant_id` bigint(20) NOT NULL COMMENT '租户ID',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '最后更新时间',
`creator` varchar(64) NOT NULL COMMENT '创建者',
`updater` varchar(64) NOT NULL COMMENT '更新者',
`deleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='会员等级表';

View File

@@ -193,6 +193,11 @@
<artifactId>tashow-sdk-payment</artifactId> <artifactId>tashow-sdk-payment</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency>
<groupId>com.tashow.cloud</groupId>
<artifactId>tashow-product-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- Spring 核心 --> <!-- Spring 核心 -->
<dependency> <dependency>

View File

@@ -1,19 +1,18 @@
package com.tashow.cloud.productapi.api.product; package com.tashow.cloud.productapi.api.product;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageResult; import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.productapi.api.product.dto.CategoryDO;
import com.tashow.cloud.productapi.api.product.dto.ProdDO; import com.tashow.cloud.productapi.api.product.dto.ProdDO;
import com.tashow.cloud.productapi.api.product.dto.ShopDetailDO;
import com.tashow.cloud.productapi.api.product.vo.prod.ProdListVO; import com.tashow.cloud.productapi.api.product.vo.prod.ProdListVO;
import com.tashow.cloud.productapi.api.product.vo.prod.ProdPageReqVO; import com.tashow.cloud.productapi.api.product.vo.prod.ProdPageReqVO;
import com.tashow.cloud.productapi.api.product.vo.prod.ProdServiceVO; import com.tashow.cloud.productapi.api.product.vo.prod.ProdServiceVO;
import com.tashow.cloud.productapi.enums.ApiConstants; import com.tashow.cloud.productapi.enums.ApiConstants;
import jakarta.annotation.security.PermitAll;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿fallbackFactory = @FeignClient(name = ApiConstants.NAME) // TODO 芋艿fallbackFactory =
/** RPC 服务 - 参数配置 */ /** RPC 服务 - 参数配置 */
public interface ProdApi { public interface ProdApi {
@@ -27,7 +26,8 @@ public interface ProdApi {
*/ */
@GetMapping(PREFIX + "/getProdInfo") @GetMapping(PREFIX + "/getProdInfo")
ProdDO getProdInfo(@RequestParam(value = "id", required = false) Long id); @PermitAll
CommonResult<ProdDO> getProdInfo(@RequestParam(value = "id", required = false) Long id);
/** /**
* 获取商品服务配置 * 获取商品服务配置
@@ -47,5 +47,20 @@ public interface ProdApi {
@GetMapping(PREFIX + "/getProdPage") @GetMapping(PREFIX + "/getProdPage")
PageResult<ProdListVO> getProdPage(ProdPageReqVO pageReqVO); PageResult<ProdListVO> getProdPage(ProdPageReqVO pageReqVO);
/**
* 扣减库存
* @param skuId 单品ID
* @param stocksNum 扣减数量
*/
@GetMapping(PREFIX + "/reduceStocks")
CommonResult<Boolean> reduceStocks(Long skuId, Integer stocksNum) ;
/**
* 增加库存
* @param skuId 单品ID
* @param stocksNum 增加数量
*/
@GetMapping(PREFIX + "/increaseStocks")
CommonResult<Boolean> increaseStocks(Long skuId, Integer stocksNum);
} }

View File

@@ -32,4 +32,10 @@ public interface ErrorCodeConstants {
ErrorCode SKU_SERVICES_FORM_NOT_EXISTS = new ErrorCode(10021, "商品SKU扩展服务表单不存在"); ErrorCode SKU_SERVICES_FORM_NOT_EXISTS = new ErrorCode(10021, "商品SKU扩展服务表单不存在");
ErrorCode SKU_SERVICE_TRANSPORT_NOT_EXISTS = new ErrorCode(10022, "服务遗体运输不存在"); ErrorCode SKU_SERVICE_TRANSPORT_NOT_EXISTS = new ErrorCode(10022, "服务遗体运输不存在");
ErrorCode SKU_SERVICE_DETAILS_NOT_EXISTS = new ErrorCode(10023, "服务详情不存在"); ErrorCode SKU_SERVICE_DETAILS_NOT_EXISTS = new ErrorCode(10023, "服务详情不存在");
ErrorCode SKU_DOES_NOT_EXIST = new ErrorCode(10030, "商品不存在");
ErrorCode SKU_DELETE = new ErrorCode(10030, "商品已删除");
ErrorCode SKU_DISABLE = new ErrorCode(10031, "商品已禁用");
} }

View File

@@ -16,6 +16,7 @@ public interface ErrorCodeConstants {
ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1_011_000_010, "交易订单项不存在"); ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1_011_000_010, "交易订单项不存在");
ErrorCode ORDER_NOT_FOUND = new ErrorCode(1_011_000_011, "交易订单不存在"); ErrorCode ORDER_NOT_FOUND = new ErrorCode(1_011_000_011, "交易订单不存在");
ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1_011_000_012, "交易订单项更新售后状态失败,请重试"); ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1_011_000_012, "交易订单项更新售后状态失败,请重试");
ErrorCode ORDER_UPDATE_UNWAITACCEPT_FAIL = new ErrorCode(1_011_000_012, "交易订单更新状态失败,当前订单不处于待验收状态");
ErrorCode ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_011_000_013, "交易订单更新支付状态失败,订单不是【未支付】状态"); ErrorCode ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_011_000_013, "交易订单更新支付状态失败,订单不是【未支付】状态");
ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1_011_000_014, "交易订单更新支付状态失败,支付单编号不匹配"); ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1_011_000_014, "交易订单更新支付状态失败,支付单编号不匹配");
ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1_011_000_015, "交易订单更新支付状态失败,支付单状态不是【支付成功】状态"); ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1_011_000_015, "交易订单更新支付状态失败,支付单状态不是【支付成功】状态");

View File

@@ -25,6 +25,7 @@ public enum TradeOrderOperateTypeEnum {
SYSTEM_COMMENT(34, "到期未评价,系统自动评价"), SYSTEM_COMMENT(34, "到期未评价,系统自动评价"),
MEMBER_CANCEL(40, "取消订单"), MEMBER_CANCEL(40, "取消订单"),
SYSTEM_CANCEL(41, "到期未支付,系统自动取消订单"), SYSTEM_CANCEL(41, "到期未支付,系统自动取消订单"),
ADMIN_CANCEL(42, "管理员取消订单"),
// 42 预留:管理员取消订单 // 42 预留:管理员取消订单
ADMIN_CANCEL_AFTER_SALE(43, "订单全部售后,管理员自动取消订单"), ADMIN_CANCEL_AFTER_SALE(43, "订单全部售后,管理员自动取消订单"),
MEMBER_DELETE(49, "删除订单"), MEMBER_DELETE(49, "删除订单"),

View File

@@ -55,6 +55,15 @@ public enum TradeOrderStatusEnum implements ArrayValuable<Integer> {
public static boolean isUnpaid(Integer status) { public static boolean isUnpaid(Integer status) {
return ObjectUtil.equal(WAITPAID.getStatus(), status); return ObjectUtil.equal(WAITPAID.getStatus(), status);
} }
/**
* 判断指定状态,是否正处于【待验收】状态
*
* @param status 指定状态
* @return 是否
*/
public static boolean isWaitAccept(Integer status) {
return ObjectUtil.equal(WAITACCEPT.getStatus(), status);
}
/** /**
* 判断指定状态,是否正处于【待发货】状态 * 判断指定状态,是否正处于【待发货】状态

View File

@@ -29,7 +29,7 @@ import java.util.List;
* 1. {@link BaseMapper} 为 MyBatis Plus 的基础接口,提供基础的 CRUD 能力 * 1. {@link BaseMapper} 为 MyBatis Plus 的基础接口,提供基础的 CRUD 能力
* 2. {@link MPJBaseMapper} 为 MyBatis Plus Join 的基础接口,提供连表 Join 能力 * 2. {@link MPJBaseMapper} 为 MyBatis Plus Join 的基础接口,提供连表 Join 能力
*/ */
public interface BaseMapperX<T> extends MPJBaseMapper<T> { public interface BaseMapperX<T> extends MPJBaseMapper<T>,BaseMapper<T> {
default PageResult<T> selectPage(SortablePageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) { default PageResult<T> selectPage(SortablePageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
return selectPage(pageParam, pageParam.getSortingFields(), queryWrapper); return selectPage(pageParam, pageParam.getSortingFields(), queryWrapper);

View File

@@ -33,7 +33,7 @@ public class EnvEnvironmentPostProcessor implements EnvironmentPostProcessor {
environment.getSystemProperties().put(hostNameKey, EnvUtils.getHostName()); environment.getSystemProperties().put(hostNameKey, EnvUtils.getHostName());
} }
// 1.1 如果没有 yudao.env.tag 配置项,则不进行配置项的修改 // 1.1 如果没有 tashow.env.tag 配置项,则不进行配置项的修改
String tag = EnvUtils.getTag(environment); String tag = EnvUtils.getTag(environment);
if (StrUtil.isEmpty(tag)) { if (StrUtil.isEmpty(tag)) {
return; return;

View File

@@ -136,7 +136,7 @@ public class WebSecurityConfigurerAdapter {
.requestMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll() .requestMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll()
.requestMatchers(HttpMethod.HEAD, permitAllUrls.get(HttpMethod.HEAD).toArray(new String[0])).permitAll() .requestMatchers(HttpMethod.HEAD, permitAllUrls.get(HttpMethod.HEAD).toArray(new String[0])).permitAll()
.requestMatchers(HttpMethod.PATCH, permitAllUrls.get(HttpMethod.PATCH).toArray(new String[0])).permitAll() .requestMatchers(HttpMethod.PATCH, permitAllUrls.get(HttpMethod.PATCH).toArray(new String[0])).permitAll()
// 1.3 基于 yudao.security.permit-all-urls 无需认证 // 1.3 基于 tashow.security.permit-all-urls 无需认证
.requestMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll() .requestMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll()
) )
// ②:每个项目的自定义规则 // ②:每个项目的自定义规则

View File

@@ -18,7 +18,7 @@
<module>tashow-module-ai</module> <module>tashow-module-ai</module>
<module>tashow-module-pay</module> <module>tashow-module-pay</module>
<module>tashow-module-trade</module> <module>tashow-module-trade</module>
<module>tashow-module-member</module> <module>tashow-module-user</module>
</modules> </modules>
</project> </project>

View File

@@ -6,6 +6,7 @@ import com.tashow.cloud.ai.controller.app.dialog.vo.TranslateReqVo;
import com.tashow.cloud.ai.controller.app.dialog.vo.TranslateRespVo; import com.tashow.cloud.ai.controller.app.dialog.vo.TranslateRespVo;
import com.tashow.cloud.ai.service.dialog.AiDialogService; import com.tashow.cloud.ai.service.dialog.AiDialogService;
import com.tashow.cloud.common.pojo.CommonResult; import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageParam;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll; import jakarta.annotation.security.PermitAll;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -15,8 +16,6 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static com.tashow.cloud.common.pojo.CommonResult.success; import static com.tashow.cloud.common.pojo.CommonResult.success;
/** /**
@@ -28,8 +27,6 @@ import static com.tashow.cloud.common.pojo.CommonResult.success;
@Slf4j @Slf4j
public class DialogController { public class DialogController {
List<String> message = List.of("渴了", "饿了", "想睡觉", "想出去玩", "想溜达", "情绪低落", "很开心", "很伤心", "想哭");
@Resource @Resource
private AiDialogService aiDialogService; private AiDialogService aiDialogService;
@@ -39,10 +36,10 @@ public class DialogController {
*/ */
@GetMapping("/getDialog") @GetMapping("/getDialog")
@PermitAll @PermitAll
public CommonResult<DialogResp> msList() { public CommonResult<DialogResp> msList(PageParam pageParam) {
//获取当前登录用户 //获取当前登录用户
Long userId = 1L; Long userId = 1L;
return success(aiDialogService.getDialog(userId)); return success(aiDialogService.getDialog(userId,pageParam));
} }

View File

@@ -1,14 +1,12 @@
package com.tashow.cloud.ai.controller.app.dialog.vo; package com.tashow.cloud.ai.controller.app.dialog.vo;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.tashow.cloud.common.util.json.databind.StringLocalDateTimeSerializer;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/** /**
* ai-对话消息 DO * ai-对话消息 DO
* *
@@ -71,7 +69,13 @@ public class AiDialogMessageRespVo {
/** /**
* 创建时间 * 创建时间
*/ */
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) //发送时间
@JsonSerialize(using = StringLocalDateTimeSerializer.class)
private LocalDateTime createTime; private LocalDateTime createTime;
private Integer emotion;
private String terminal;
private String fileType;
private String fileName;
} }

View File

@@ -1,10 +1,9 @@
package com.tashow.cloud.ai.controller.app.dialog.vo; package com.tashow.cloud.ai.controller.app.dialog.vo;
import com.tashow.cloud.common.pojo.PageResult;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import java.util.List;
@Schema(description = "api - 对话 Response VO") @Schema(description = "api - 对话 Response VO")
@Data @Data
@@ -17,5 +16,5 @@ public class DialogResp {
@Schema(description = "对话状态") @Schema(description = "对话状态")
private String dialogStatus; private String dialogStatus;
@Schema(description = "对话消息内容") @Schema(description = "对话消息内容")
private List<AiDialogMessageRespVo> messages; private PageResult<AiDialogMessageRespVo> messages;
} }

View File

@@ -14,11 +14,13 @@ public class TranslateReqVo {
//消息id //消息id
private Long msgId; private Long msgId;
private String terminal;
/** 文件附件 */ /** 文件附件 */
private MultipartFile file; private MultipartFile file;
//文件时长 //文件时长
private String contentDuration; private Long contentDuration;
} }

View File

@@ -39,6 +39,7 @@ public class TranslateRespVo {
private String transResult; private String transResult;
//文件时长 //文件时长
private Long contentDuration; private Long contentDuration;
private String terminal;
//发送时间 //发送时间
@JsonSerialize(using = StringLocalDateTimeSerializer.class) @JsonSerialize(using = StringLocalDateTimeSerializer.class)
private LocalDateTime createTime; private LocalDateTime createTime;

View File

@@ -97,4 +97,7 @@ public class AiDialogMessageDO {
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime createTime; private LocalDateTime createTime;
private Integer emotion;
private String terminal;
} }

View File

@@ -0,0 +1,27 @@
package com.tashow.cloud.ai.dal.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum EmotionEnums {
XF(1,"兴奋/玩耍","兴奋"),
PJ(2,"平静/放松","平静"),
je(3,"乞求/饥饿/口渴","饥饿"),
yk(4,"愉快/满足","愉快"),
tt(5,"疼痛/沮丧","疼痛"),
kj(6,"恐惧/不安","恐惧"),
hq(7,"问候/好奇","好奇"),
ng(8,"难过/焦虑","难过"),
fn(9,"愤怒/警告","愤怒"),
;
private Integer code;
private String name;
private String aiName;
}

View File

@@ -5,6 +5,7 @@ import com.tashow.cloud.ai.controller.app.dialog.vo.DialogResp;
import com.tashow.cloud.ai.controller.app.dialog.vo.TranslateReqVo; import com.tashow.cloud.ai.controller.app.dialog.vo.TranslateReqVo;
import com.tashow.cloud.ai.controller.app.dialog.vo.TranslateRespVo; import com.tashow.cloud.ai.controller.app.dialog.vo.TranslateRespVo;
import com.tashow.cloud.ai.dal.dataobject.dialog.AiDialogDO; import com.tashow.cloud.ai.dal.dataobject.dialog.AiDialogDO;
import com.tashow.cloud.common.pojo.PageParam;
/** /**
* ai-对话 Service 接口 * ai-对话 Service 接口
@@ -14,7 +15,7 @@ import com.tashow.cloud.ai.dal.dataobject.dialog.AiDialogDO;
public interface AiDialogService extends IService<AiDialogDO> { public interface AiDialogService extends IService<AiDialogDO> {
DialogResp getDialog(Long userId); DialogResp getDialog(Long userId, PageParam pageParam);
TranslateRespVo translate(TranslateReqVo fileReqVo); TranslateRespVo translate(TranslateReqVo fileReqVo);
} }

View File

@@ -1,6 +1,7 @@
package com.tashow.cloud.ai.service.dialog; package com.tashow.cloud.ai.service.dialog;
import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil; import cn.hutool.http.HttpUtil;
@@ -16,6 +17,8 @@ import com.tashow.cloud.ai.dal.dataobject.dialog.AiDialogDO;
import com.tashow.cloud.ai.dal.dataobject.dialog.AiDialogMessageDO; import com.tashow.cloud.ai.dal.dataobject.dialog.AiDialogMessageDO;
import com.tashow.cloud.ai.dal.mysql.dialog.AiDialogMapper; import com.tashow.cloud.ai.dal.mysql.dialog.AiDialogMapper;
import com.tashow.cloud.ai.dal.mysql.dialog.AiDialogMessageMapper; import com.tashow.cloud.ai.dal.mysql.dialog.AiDialogMessageMapper;
import com.tashow.cloud.common.pojo.PageParam;
import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.common.util.object.BeanUtils; import com.tashow.cloud.common.util.object.BeanUtils;
import com.tashow.cloud.infraapi.api.file.FileApi; import com.tashow.cloud.infraapi.api.file.FileApi;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -28,9 +31,6 @@ import org.springframework.web.multipart.MultipartFile;
import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem; import javax.sound.sampled.AudioSystem;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -55,10 +55,55 @@ public class AiDialogServiceImpl extends ServiceImpl<AiDialogMapper, AiDialogDO>
@Resource @Resource
private FileApi fileApi; private FileApi fileApi;
private List<String> failedStr =List.of(
"刚刚的音符太独特了,我没听清呢~可以再对我说一次吗?",
"哇,这是哪来的小可爱?声音太有魅力了,让我一时走了神。请靠近一点,慢慢再说一遍好?",
"背景音有点热闹我有点分心啦能在一个更安静的地方让我专心听听TA的声音吗",
"报告主人!声波受到不明干扰(可能是零食袋的声音?),翻译任务失败,请求二次输入!",
"我的‘物种雷达’刚才打了个盹儿~快让我再听一次这美妙的声音!",
"这声音太迷人了让我CPU过载了请简化一下环境音我们再来一次"
);
private Map<String,List<String>> failedMap =new HashMap<>(){{
put("cat",List.of(
"听得出是猫猫在说话但TA似乎在表达一种很深邃的情绪..也许是个小秘密呢?",
"喵星人的这段‘加密通话’等级太高了!翻译官正在努力学习中...你能通过TA的尾巴和眼神猜猜看吗",
"警报!警报!接收到喵星最高机密指令,我的权限不足,无法破译!建议提供小鱼干以获取更多线索"
));
put("dog",List.of(
"听得出是狗狗在说话但TA似乎在表达一种很深邃的情绪...也许是个小秘密呢?",
"汪语十级考试失败!这句大概是“今天的我比昨天更爱你了'之类的复杂情感吧",
"汪星人的这段‘加密通话’等级太高了!翻译官正在努力学习中..你能通过TA的尾巴和眼神猜猜看吗"
));
put("common",List.of(
"TA刚才可能用了某种古老的咒语或者...只是在打一个很有思想的哈欠?",
"这句的哲学深度超出了我的理解范围TA可能是一位诗人"
));
}};
private Map<String,List<String>> successMap =new HashMap<>(){{
put("舒服",List.of(
"TA 现在全身心都放松下来啦,正被满满的安全感包围着呢~ ",
"听这均匀的呼吸TA 的心正像云朵一样软绵绵、轻飘飘的哦。",
"这是幸福的声音此刻的TA觉得自己是全世界最被爱的小宝贝",
"环境很安心主人很贴心TA 正在小声说:好舒服呀~…"
));
put("等待喂食",List.of(
"小肚肚发出‘咕咕’警报啦!美食雷达正在全面启动,搜寻好吃的!",
"来自TA的紧急通讯报告能量储备严重不足请求立刻补充",
"你听到了吗那是小饭碗在思念食物的声音TA的眼神正在发出渴望的光波~",
"“开饭铃”已经摇响!再不开饭,小委屈就要溢出来啦!"
));
put("生气",List.of(
"TA 现在有点小紧张哦周围可能有让TA不安的东西快给TA一点安慰吧",
"检测到心跳加速模式TA需要一点空间和一个温柔的声音来平静下来",
"TA 现在有点小紧张哦周围可能有让TA不安的东西快给TA一点安慰吧"
));
}};
private Map<String, String> petAvatars = new HashMap<>() {{ private Map<String, String> petAvatars = new HashMap<>() {{
put("cat", "https://petshy.tashowz.com/admin-api/infra/file/29/get/89f4982de19aadae3248ffde37132857df255b3276de484fdf12e603e5e29a7e.png"); put("cat", "https://petshy.tashowz.com/admin-api/infra/file/29/get/默认的猫.png");
put("dog", "https://petshy.tashowz.com/admin-api/infra/file/29/get/175ba9f58dc812786bfe0598ca9c4a7f422fe138c1889e08d8228aebc953c1b3.png"); put("dog", "https://petshy.tashowz.com/admin-api/infra/file/29/get/默认的狗.png");
}}; }};
private Map<String, String> petName = new HashMap<>() {{ private Map<String, String> petName = new HashMap<>() {{
@@ -68,7 +113,7 @@ public class AiDialogServiceImpl extends ServiceImpl<AiDialogMapper, AiDialogDO>
@Override @Override
public DialogResp getDialog(Long userId) { public DialogResp getDialog(Long userId, PageParam pageParam) {
AiDialogDO aiDialogDO = this.getOne(new LambdaQueryWrapper<AiDialogDO>().eq(AiDialogDO::getUserId, userId)); AiDialogDO aiDialogDO = this.getOne(new LambdaQueryWrapper<AiDialogDO>().eq(AiDialogDO::getUserId, userId));
if (aiDialogDO == null) { if (aiDialogDO == null) {
aiDialogDO = new AiDialogDO(); aiDialogDO = new AiDialogDO();
@@ -77,7 +122,12 @@ public class AiDialogServiceImpl extends ServiceImpl<AiDialogMapper, AiDialogDO>
aiDialogDO.setUserId(userId); aiDialogDO.setUserId(userId);
this.save(aiDialogDO); this.save(aiDialogDO);
} }
List<AiDialogMessageDO> messageDOS = aiDialogMessageMapper.selectList(new LambdaQueryWrapper<AiDialogMessageDO>().eq(AiDialogMessageDO::getDialogId, aiDialogDO.getId()));
PageResult<AiDialogMessageDO> messageDOS = aiDialogMessageMapper.selectPage(pageParam,
new LambdaQueryWrapper<AiDialogMessageDO>().eq(AiDialogMessageDO::getDialogId, aiDialogDO.getId())
.orderByAsc(AiDialogMessageDO::getCreateTime)
);
DialogResp resp = new DialogResp(); DialogResp resp = new DialogResp();
resp.setDialogId(aiDialogDO.getId()); resp.setDialogId(aiDialogDO.getId());
resp.setTitle(aiDialogDO.getTitle()); resp.setTitle(aiDialogDO.getTitle());
@@ -89,43 +139,23 @@ public class AiDialogServiceImpl extends ServiceImpl<AiDialogMapper, AiDialogDO>
@Override @Override
@SneakyThrows @SneakyThrows
public TranslateRespVo translate(TranslateReqVo fileReqVo) { public TranslateRespVo translate(TranslateReqVo fileReqVo) {
AiDialogMessageDO messageDO = aiDialogMessageMapper.selectById(fileReqVo.getMsgId()); AiDialogMessageDO messageDO = new AiDialogMessageDO();
if (messageDO == null) { String fileName = fileReqVo.getFile().getOriginalFilename();
messageDO = new AiDialogMessageDO();
}
String fileName = StrUtil.isBlank(messageDO.getFileName()) ? fileReqVo.getFile().getOriginalFilename() : messageDO.getFileName();
//上传文件获取文件地址 //上传文件获取文件地址
String fileUrl = StrUtil.isBlank(messageDO.getContentText()) ? fileServer + fileApi.createFile(fileName, "", fileReqVo.getFile().getBytes()) : messageDO.getContentText(); String fileUrl = fileServer + fileApi.createFile(fileName, "", fileReqVo.getFile().getBytes());
//翻译结果 //翻译结果
translate(messageDO, fileUrl, fileName); translate(messageDO, fileUrl, fileName);
//创建消息 持久化消息 //创建消息
if (messageDO.getId() == null) {
messageDO.setFileName(fileName); messageDO.setFileName(fileName);
messageDO.setFileType(fileReqVo.getFile().getContentType()); messageDO.setFileType(fileReqVo.getFile().getContentType());
messageDO.setDialogId(fileReqVo.getDialogId()); messageDO.setDialogId(fileReqVo.getDialogId());
//前端无法转换时 后端进行转 //前端无法转换时 后端进行转
messageDO.setContentDuration( messageDO.setContentDuration(fileReqVo.getContentDuration());
StrUtil.isBlank(fileReqVo.getContentDuration()) || "Infinity".equals(fileReqVo.getContentDuration())
? 0 : Long.parseLong(fileReqVo.getContentDuration())
);
messageDO.setContentText(fileUrl); messageDO.setContentText(fileUrl);
messageDO.setContentType(2); messageDO.setContentType(2);
//获取当前最后的排序
AiDialogMessageDO aiDialogMessageDO = aiDialogMessageMapper.selectOne(new LambdaQueryWrapper<AiDialogMessageDO>()
.eq(AiDialogMessageDO::getDialogId, fileReqVo.getDialogId())
.orderByDesc(AiDialogMessageDO::getMessageOrder)
.last("limit 1")
);
messageDO.setMessageOrder(aiDialogMessageDO == null ? 1 : aiDialogMessageDO.getMessageOrder() + 1);
messageDO.setCreateTime(LocalDateTimeUtil.now()); messageDO.setCreateTime(LocalDateTimeUtil.now());
} return BeanUtils.toBean(messageDO, TranslateRespVo.class);
int i = messageDO.getId() == null ? aiDialogMessageMapper.insert(messageDO) : aiDialogMessageMapper.updateById(messageDO);
TranslateRespVo bean = BeanUtils.toBean(messageDO, TranslateRespVo.class);
bean.setId(messageDO.getId());
return bean;
} }
@SneakyThrows @SneakyThrows
@@ -148,51 +178,54 @@ public class AiDialogServiceImpl extends ServiceImpl<AiDialogMapper, AiDialogDO>
//数据解析 //数据解析
JSONObject translateResult = JSON.parseObject(result); JSONObject translateResult = JSON.parseObject(result);
//翻译失败
if (translateResult.isEmpty() if (translateResult.isEmpty()
|| !translateResult.containsKey("intent_result") || !translateResult.containsKey("intent_result")
|| !translateResult.getBoolean("is_species_sound") || !translateResult.getBoolean("is_species_sound")
|| translateResult.getInteger("confidence") < 0.7 || translateResult.getDouble("confidence") < 0.7
) { ) {
messageDO.setTransStatus(0); messageDO.setTransStatus(0);
messageDO.setTransResult(""); messageDO.setTransResult(failedStr.get(RandomUtil.randomInt(failedStr.size())));
return messageDO; return messageDO;
} }
//标签 如 cat dog //标签 如 cat dog
String speciesLabels = translateResult.getString("species_labels"); String speciesLabels = translateResult.getString("species_labels");
//解析翻译结果 //解析翻译结果
JSONObject probabilities = translateResult.getJSONObject("intent_result") JSONObject intentResult = translateResult.getJSONObject("intent_result");
.getJSONObject("probabilities");
String resultKey = probabilities.entrySet().stream()
.filter(entry -> entry.getValue() instanceof Number && ((Number) entry.getValue()).doubleValue() > 0.7)
.max(Comparator.comparingDouble(entry -> ((Number) entry.getValue()).doubleValue()))
.map(Map.Entry::getKey)
.orElse(null);
//返回结果
if (StrUtil.isBlank(resultKey)) {
messageDO.setTransStatus(0);
messageDO.setTransResult("");
return messageDO;
}
//宠物档案 todo //宠物档案 todo
messageDO.setPetId(1l); messageDO.setPetId(1l);
messageDO.setPetName(petName.get(speciesLabels)); messageDO.setPetName(petName.get(speciesLabels));
https:
//qcloud.dpfile.com/pc/qw4HqeQN5Af9tLaw0mx8pXQhxKUCvwHbCXmSRI-nKiW1NpX6wMdvSN80YpcTbMKw.jpg
messageDO.setPetAvatar(petAvatars.get(speciesLabels)); messageDO.setPetAvatar(petAvatars.get(speciesLabels));
messageDO.setPetType(speciesLabels); messageDO.setPetType(speciesLabels);
//识别物种,无法翻译音频
if (intentResult.getDouble("confidence")<0.7){
messageDO.setTransStatus(0);
List<String> petFailResult = failedMap.get(speciesLabels);
if (petFailResult == null) {
petFailResult = failedMap.get("common");
}
messageDO.setTransResult(petFailResult.get(RandomUtil.randomInt(petFailResult.size())));
return messageDO;
}
//都识别成功后 也有不同的翻译结果
JSONObject probabilities = intentResult.getJSONObject("probabilities");
String resultKey = probabilities.entrySet().stream()
.max(Comparator.comparingDouble(entry -> ((Number) entry.getValue()).doubleValue()))
.map(Map.Entry::getKey)
.orElse(null);
//根据key解析结果
String emo = StrUtil.isBlank(resultKey) ? "" : resultKey.split(cn.hutool.core.util.StrUtil.UNDERLINE)[1];
List<String> emoList = successMap.get(emo);
messageDO.setTransStatus(1); messageDO.setTransStatus(1);
messageDO.setTransResult(StrUtil.isBlank(resultKey) ? "" : resultKey.split(StrUtil.UNDERLINE)[1]); messageDO.setTransResult(emoList.get(RandomUtil.randomInt(emoList.size())));
return messageDO; return messageDO;
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
InputStream inputStream = getInputStreamFromUrl("https://petshy.tashowz.com/admin-api/infra/file/29/get/857def513547ec33a105f71108c8ece329cb64dacc3a4779c94b0fcc3398cc32.webm");
AudioInputStream audioStream = AudioSystem.getAudioInputStream(inputStream);
System.out.println((long) (audioStream.getFrameLength() / audioStream.getFormat().getFrameRate()));
// byte[] bytes = HttpUtil.downloadBytes("http://192.168.1.231:48080/admin-api/infra/file/29/get/c7351abf780f18600c104ec5662d843783ed8c309c01fb427046565217f51102.wav"); // byte[] bytes = HttpUtil.downloadBytes("http://192.168.1.231:48080/admin-api/infra/file/29/get/c7351abf780f18600c104ec5662d843783ed8c309c01fb427046565217f51102.wav");
// //
//// File file = new File("http://192.168.1.231:48080/admin-api/infra/file/29/get/c7351abf780f18600c104ec5662d843783ed8c309c01fb427046565217f51102.wav"); //// File file = new File("http://192.168.1.231:48080/admin-api/infra/file/29/get/c7351abf780f18600c104ec5662d843783ed8c309c01fb427046565217f51102.wav");
@@ -202,19 +235,4 @@ public class AiDialogServiceImpl extends ServiceImpl<AiDialogMapper, AiDialogDO>
} }
public static InputStream getInputStreamFromUrl(String urlString) throws Exception {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET"); // 可以是GET, POST等
connection.setConnectTimeout(5000); // 设置连接超时时间
connection.setReadTimeout(5000); // 设置读取超时时间
int responseCode = connection.getResponseCode(); // 获取响应码
if (responseCode == HttpURLConnection.HTTP_OK) { // 状态码200表示成功
return connection.getInputStream();
} else {
// 处理错误情况例如抛出异常或返回null等
throw new RuntimeException("Failed : HTTP error code : " + responseCode);
}
}
} }

View File

@@ -25,6 +25,14 @@
<artifactId>tashow-framework-env</artifactId> <artifactId>tashow-framework-env</artifactId>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.jaudiotagger/jaudiotagger -->
<dependency>
<groupId>org.jaudiotagger</groupId>
<artifactId>jaudiotagger</artifactId>
<version>2.0.1</version>
</dependency>
<!-- 依赖服务 --> <!-- 依赖服务 -->
<dependency> <dependency>
<groupId>com.tashow.cloud</groupId> <groupId>com.tashow.cloud</groupId>

View File

@@ -87,7 +87,6 @@ public class FileController {
response.setStatus(HttpStatus.NOT_FOUND.value()); response.setStatus(HttpStatus.NOT_FOUND.value());
return; return;
} }
response.setContentLength(content.length);
writeAttachment(response, path, content); writeAttachment(response, path, content);
} }

View File

@@ -6,8 +6,20 @@ import com.alibaba.ttl.TransmittableThreadLocal;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import org.apache.tika.Tika; import org.apache.tika.Tika;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.exceptions.CannotReadException;
import org.jaudiotagger.audio.exceptions.CannotWriteException;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.TagException;
import org.jaudiotagger.tag.id3.AbstractID3v2Tag;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder; import java.net.URLEncoder;
/** /**
@@ -64,7 +76,7 @@ public class FileTypeUtils {
String contentType = getMineType(content, filename); String contentType = getMineType(content, filename);
response.setContentType(contentType); response.setContentType(contentType);
// 针对 video 的特殊处理,解决视频地址在移动端播放的兼容性问题 // 针对 video 的特殊处理,解决视频地址在移动端播放的兼容性问题
if (StrUtil.containsIgnoreCase(contentType, "video")) { if (StrUtil.containsIgnoreCase(contentType, "video")||StrUtil.containsIgnoreCase(contentType, "audio")) {
response.setHeader("Content-Length", String.valueOf(content.length - 1)); response.setHeader("Content-Length", String.valueOf(content.length - 1));
response.setHeader("Content-Range", String.valueOf(content.length - 1)); response.setHeader("Content-Range", String.valueOf(content.length - 1));
response.setHeader("Accept-Ranges", "bytes"); response.setHeader("Accept-Ranges", "bytes");
@@ -73,4 +85,21 @@ public class FileTypeUtils {
IoUtil.write(response.getOutputStream(), false, content); IoUtil.write(response.getOutputStream(), false, content);
} }
public static void main(String[] args) throws CannotReadException, TagException, InvalidAudioFrameException, ReadOnlyFileException, IOException, CannotWriteException, URISyntaxException {
URL url = new URL("https://petshy.tashowz.com/admin-api/infra/file/29/get/jna2-雪球-难过焦虑.wav");
File file = new File(url.getFile());
System.out.println(file.exists());
AudioFile audioFile = AudioFileIO.read(file);
Tag tag = audioFile.getTag();
if (tag instanceof AbstractID3v2Tag) {
AbstractID3v2Tag id3v2Tag = (AbstractID3v2Tag) tag;
// id3v2Tag.delete(); // 删除所有ID3标签
} else {
System.out.println("The file does not contain ID3v2 tags.");
}
AudioFileIO.write(audioFile); // 保存更改
System.out.println("ID3 tags removed successfully.");
}
} }

View File

@@ -1,4 +1,4 @@
-- 将该建表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/create_tables.sql 文件里 -- 将该建表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/create_tableslogin.sql 文件里
CREATE TABLE IF NOT EXISTS "${table.tableName.toLowerCase()}" ( CREATE TABLE IF NOT EXISTS "${table.tableName.toLowerCase()}" (
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.javaType} == 'Long') #if (${column.javaType} == 'Long')
@@ -33,5 +33,5 @@ CREATE TABLE IF NOT EXISTS "${table.tableName.toLowerCase()}" (
PRIMARY KEY ("${primaryColumn.columnName.toLowerCase()}") PRIMARY KEY ("${primaryColumn.columnName.toLowerCase()}")
) COMMENT '${table.tableComment}'; ) COMMENT '${table.tableComment}';
-- 将该删表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/clean.sql 文件里 -- 将该删表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/cleanlogin.sql 文件里
DELETE FROM "${table.tableName}"; DELETE FROM "${table.tableName}";

View File

@@ -1,35 +0,0 @@
package com.tashow.cloud.member.address;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.memberapi.api.address.MemberAddressApi;
import com.tashow.cloud.memberapi.api.address.dto.MemberAddressRespDTO;
import com.tashow.cloud.member.convert.address.AddressConvert;
import com.tashow.cloud.member.service.address.AddressService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import static com.tashow.cloud.common.pojo.CommonResult.success;
/**
* 用户收件地址 API 实现类
*/
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class MemberAddressApiImpl implements MemberAddressApi {
@Resource
private AddressService addressService;
@Override
public CommonResult<MemberAddressRespDTO> getAddress(Long id, Long userId) {
return success(AddressConvert.INSTANCE.convert02(addressService.getAddress(userId, id)));
}
@Override
public CommonResult<MemberAddressRespDTO> getDefaultAddress(Long userId) {
return success(AddressConvert.INSTANCE.convert02(addressService.getDefaultUserAddress(userId)));
}
}

View File

@@ -1,39 +0,0 @@
package com.tashow.cloud.member.controller.admin.address;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.member.controller.admin.address.vo.AddressRespVO;
import com.tashow.cloud.member.convert.address.AddressConvert;
import com.tashow.cloud.member.dal.dataobject.address.MemberAddressDO;
import com.tashow.cloud.member.service.address.AddressService;
import jakarta.annotation.Resource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static com.tashow.cloud.common.pojo.CommonResult.success;
// 管理后台 - 用户收件地址
@RestController
@RequestMapping("/member/address")
@Validated
public class AddressController {
@Resource
private AddressService addressService;
@GetMapping("/list")
// 获得用户收件地址列表
// userId: 用户编号,必填
@PreAuthorize("@ss.hasPermission('member:user:query')")
public CommonResult<List<AddressRespVO>> getAddressList(@RequestParam("userId") Long userId) {
List<MemberAddressDO> list = addressService.getAddressList(userId);
return success(AddressConvert.INSTANCE.convertList2(list));
}
}

View File

@@ -1 +0,0 @@
package com.tashow.cloud.member.controller.admin.address;

View File

@@ -1,36 +0,0 @@
package com.tashow.cloud.member.controller.admin.address.vo;
import lombok.*;
import java.time.LocalDateTime;
import java.util.*;
import jakarta.validation.constraints.*;
/**
* 用户收件地址 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class AddressBaseVO {
// 收件人名称,必填,示例:张三
@NotNull(message = "收件人名称不能为空")
private String name;
// 手机号,必填
@NotNull(message = "手机号不能为空")
private String mobile;
// 地区编码必填示例15716
@NotNull(message = "地区编码不能为空")
private Long areaId;
// 收件详细地址,必填
@NotNull(message = "收件详细地址不能为空")
private String detailAddress;
// 是否默认必填示例2
@NotNull(message = "是否默认不能为空")
private Boolean defaultStatus;
}

View File

@@ -1,18 +0,0 @@
package com.tashow.cloud.member.controller.admin.address.vo;
import lombok.*;
import java.time.LocalDateTime;
// 管理后台 - 用户收件地址 Response VO
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AddressRespVO extends AddressBaseVO {
// 收件地址编号必填示例7380
private Long id;
// 创建时间,必填
private LocalDateTime createTime;
}

View File

@@ -1,65 +0,0 @@
package com.tashow.cloud.member.controller.admin.user.vo;
import lombok.Data;
import org.hibernate.validator.constraints.URL;
import org.springframework.format.annotation.DateTimeFormat;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
/**
* 会员用户 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class MemberUserBaseVO {
// 手机号必填示例15601691300
@NotNull(message = "手机号不能为空")
private String mobile;
// 状态必填示例2
@NotNull(message = "状态不能为空")
private Byte status;
// 用户昵称,必填,示例:李四
@NotNull(message = "用户昵称不能为空")
private String nickname;
// 头像必填示例https://www.iocoder.cn/x.png
@URL(message = "头像必须是 URL 格式")
private String avatar;
// 用户昵称,示例:李四
private String name;
// 用户性别示例1
private Integer sex;
// 所在地编号示例4371
private Long areaId;
// 所在地全程,示例:上海上海市普陀区
private String areaName;
// 出生日期示例2023-03-12
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
private LocalDateTime birthday;
// 会员备注,示例:我是小备注
private String mark;
// 会员标签,示例:[1, 2]
private List<Long> tagIds;
// 会员等级编号示例1
private Long levelId;
// 用户分组编号示例1
private Long groupId;
}

View File

@@ -1,48 +0,0 @@
package com.tashow.cloud.member.controller.admin.user.vo;
import com.tashow.cloud.common.pojo.PageParam;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.List;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
// 管理后台 - 会员用户分页 Request VO
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MemberUserPageReqVO extends PageParam {
// 手机号示例15601691300
private String mobile;
// 用户昵称,示例:李四
private String nickname;
// 最后登录时间
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] loginDate;
// 创建时间
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
// 会员标签编号列表,示例:[1, 2]
private List<Long> tagIds;
// 会员等级编号示例1
private Long levelId;
// 用户分组编号示例1
private Long groupId;
// TODO 芋艿:注册用户类型;
// TODO 芋艿:登录用户类型;
}

View File

@@ -1,51 +0,0 @@
package com.tashow.cloud.member.controller.admin.user.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
import java.util.List;
// 管理后台 - 会员用户 Response VO
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MemberUserRespVO extends MemberUserBaseVO {
// 编号必填示例23788
private Long id;
// 注册 IP必填示例127.0.0.1
private String registerIp;
// 最后登录IP必填示例127.0.0.1
private String loginIp;
// 最后登录时间,必填
private LocalDateTime loginDate;
// 创建时间,必填
private LocalDateTime createTime;
// ========== 其它信息 ==========
// 积分必填示例100
private Integer point;
// 总积分必填示例2000
private Integer totalPoint;
// 会员标签,示例:[红色, 快乐]
private List<String> tagNames;
// 会员等级,示例:黄金会员
private String levelName;
// 用户分组,示例:购物达人
private String groupName;
// 用户经验值必填示例200
private Integer experience;
}

View File

@@ -1,54 +0,0 @@
### 请求 /create 接口 => 成功
POST {{appApi}}//member/address/create
Content-Type: application/json
tenant-id: {{appTenantId}}
Authorization: Bearer {{appToken}}
{
"name": "yunai",
"mobile": "15601691300",
"areaId": "610632",
"postCode": "200000",
"detailAddress": "芋道源码 233 号 666 室",
"defaulted": true
}
### 请求 /update 接口 => 成功
PUT {{appApi}}//member/address/update
Content-Type: application/json
tenant-id: {{appTenantId}}
Authorization: Bearer {{appToken}}
{
"id": "1",
"name": "yunai888",
"mobile": "15601691300",
"areaId": "610632",
"postCode": "200000",
"detailAddress": "芋道源码 233 号 666 室",
"defaulted": false
}
### 请求 /delete 接口 => 成功
DELETE {{appApi}}//member/address/delete?id=2
Content-Type: application/json
tenant-id: {{appTenantId}}
Authorization: Bearer {{appToken}}
### 请求 /get 接口 => 成功
GET {{appApi}}//member/address/get?id=1
Content-Type: application/json
tenant-id: {{appTenantId}}
Authorization: Bearer {{appToken}}
### 请求 /get-default 接口 => 成功
GET {{appApi}}//member/address/get-default
Content-Type: application/json
tenant-id: {{appTenantId}}
Authorization: Bearer {{appToken}}
### 请求 /list 接口 => 成功
GET {{appApi}}//member/address/list
Content-Type: application/json
tenant-id: {{appTenantId}}
Authorization: Bearer {{appToken}}

View File

@@ -1,95 +0,0 @@
package com.tashow.cloud.member.controller.app.address;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.member.controller.app.address.vo.AppAddressCreateReqVO;
import com.tashow.cloud.member.controller.app.address.vo.AppAddressRespVO;
import com.tashow.cloud.member.controller.app.address.vo.AppAddressUpdateReqVO;
import com.tashow.cloud.member.convert.address.AddressConvert;
import com.tashow.cloud.member.dal.dataobject.address.MemberAddressDO;
import com.tashow.cloud.member.service.address.AddressService;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.security.security.core.util.SecurityFrameworkUtils.getLoginUserId;
/**
* 用户 APP - 用户收件地址
*/
@RestController
@RequestMapping("/member/address")
@Validated
public class AppAddressController {
@Resource
private AddressService addressService;
/**
* 创建用户收件地址
* @param createReqVO
* @return
*/
@PostMapping("/create")
public CommonResult<Long> createAddress(@Valid @RequestBody AppAddressCreateReqVO createReqVO) {
return success(addressService.createAddress(getLoginUserId(), createReqVO));
}
/**
* 更新用户收件地址
* @param updateReqVO
* @return
*/
@PutMapping("/update")
public CommonResult<Boolean> updateAddress(@Valid @RequestBody AppAddressUpdateReqVO updateReqVO) {
addressService.updateAddress(getLoginUserId(), updateReqVO);
return success(true);
}
/**
* 删除用户收件地址
* @param id 编号
* @return
*/
@DeleteMapping("/delete")
public CommonResult<Boolean> deleteAddress(@RequestParam("id") Long id) {
addressService.deleteAddress(getLoginUserId(), id);
return success(true);
}
/**
* 获得用户收件地址
* @param id 编号
* @return
*/
@GetMapping("/get")
public CommonResult<AppAddressRespVO> getAddress(@RequestParam("id") Long id) {
MemberAddressDO address = addressService.getAddress(getLoginUserId(), id);
return success(AddressConvert.INSTANCE.convert(address));
}
/**
* 获得默认的用户收件地址
* @return
*/
@GetMapping("/get-default")
public CommonResult<AppAddressRespVO> getDefaultUserAddress() {
MemberAddressDO address = addressService.getDefaultUserAddress(getLoginUserId());
return success(AddressConvert.INSTANCE.convert(address));
}
/**
* 获得用户收件地址列表
* @return
*/
@GetMapping("/list")
public CommonResult<List<AppAddressRespVO>> getAddressList() {
List<MemberAddressDO> list = addressService.getAddressList(getLoginUserId());
return success(AddressConvert.INSTANCE.convertList(list));
}
}

View File

@@ -1,32 +0,0 @@
package com.tashow.cloud.member.controller.app.address.vo;
import lombok.Data;
import jakarta.validation.constraints.NotNull;
/**
* 用户收件地址 Base VO提供给添加、修改、详细的子 VO 使用
*/
@Data
public class AppAddressBaseVO {
//收件人名称
@NotNull(message = "收件人名称不能为空")
private String name;
//手机号
@NotNull(message = "手机号不能为空")
private String mobile;
//地区编号
@NotNull(message = "地区编号不能为空")
private Long areaId;
//收件详细地址
@NotNull(message = "收件详细地址不能为空")
private String detailAddress;
//是否默认地址
@NotNull(message = "是否默认地址不能为空")
private Boolean defaultStatus;
}

View File

@@ -1,15 +0,0 @@
package com.tashow.cloud.member.controller.app.address.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 用户 APP - 用户收件地址创建 Request VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AppAddressCreateReqVO extends AppAddressBaseVO {
}

View File

@@ -1,21 +0,0 @@
package com.tashow.cloud.member.controller.app.address.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 用户 APP - 用户收件地址 Response VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AppAddressRespVO extends AppAddressBaseVO {
//编号
private Long id;
//地区名字
private String areaName;
}

View File

@@ -1,20 +0,0 @@
package com.tashow.cloud.member.controller.app.address.vo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 用户 APP - 用户收件地址更新 Request VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AppAddressUpdateReqVO extends AppAddressBaseVO {
//编号
@NotNull(message = "编号不能为空")
private Long id;
}

View File

@@ -1,45 +0,0 @@
package com.tashow.cloud.member.convert.address;
import com.tashow.cloud.common.util.ip.AreaUtils;
import com.tashow.cloud.memberapi.api.address.dto.MemberAddressRespDTO;
import com.tashow.cloud.member.controller.admin.address.vo.AddressRespVO;
import com.tashow.cloud.member.controller.app.address.vo.AppAddressCreateReqVO;
import com.tashow.cloud.member.controller.app.address.vo.AppAddressRespVO;
import com.tashow.cloud.member.controller.app.address.vo.AppAddressUpdateReqVO;
import com.tashow.cloud.member.dal.dataobject.address.MemberAddressDO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 用户收件地址 Convert
*
* @author 芋道源码
*/
@Mapper
public interface AddressConvert {
AddressConvert INSTANCE = Mappers.getMapper(AddressConvert.class);
MemberAddressDO convert(AppAddressCreateReqVO bean);
MemberAddressDO convert(AppAddressUpdateReqVO bean);
@Mapping(source = "areaId", target = "areaName", qualifiedByName = "convertAreaIdToAreaName")
AppAddressRespVO convert(MemberAddressDO bean);
List<AppAddressRespVO> convertList(List<MemberAddressDO> list);
MemberAddressRespDTO convert02(MemberAddressDO bean);
@Named("convertAreaIdToAreaName")
default String convertAreaIdToAreaName(Integer areaId) {
return AreaUtils.format(areaId);
}
List<AddressRespVO> convertList2(List<MemberAddressDO> list);
}

View File

@@ -1,41 +0,0 @@
package com.tashow.cloud.member.convert.user;
import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.memberapi.api.user.dto.MemberUserRespDTO;
import com.tashow.cloud.member.controller.admin.user.vo.MemberUserRespVO;
import com.tashow.cloud.member.controller.admin.user.vo.MemberUserUpdateReqVO;
import com.tashow.cloud.member.controller.app.user.vo.AppMemberUserInfoRespVO;
import com.tashow.cloud.member.convert.address.AddressConvert;
import com.tashow.cloud.member.dal.dataobject.user.MemberUserDO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper(uses = {AddressConvert.class})
public interface MemberUserConvert {
MemberUserConvert INSTANCE = Mappers.getMapper(MemberUserConvert.class);
AppMemberUserInfoRespVO convert(MemberUserDO bean);
@Mappings({
@Mapping(source = "bean.id", target = "id"),
})
MemberUserRespDTO convert2(MemberUserDO bean);
List<MemberUserRespDTO> convertList2(List<MemberUserDO> list);
MemberUserDO convert(MemberUserUpdateReqVO bean);
PageResult<MemberUserRespVO> convertPage(PageResult<MemberUserDO> page);
@Mapping(source = "areaId", target = "areaName", qualifiedByName = "convertAreaIdToAreaName")
MemberUserRespVO convert03(MemberUserDO bean);
}

View File

@@ -1,139 +0,0 @@
package com.tashow.cloud.member.dal.dataobject.user;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tashow.cloud.common.enums.CommonStatusEnum;
import com.tashow.cloud.common.enums.TerminalEnum;
import com.tashow.cloud.mybatis.mybatis.core.type.LongListTypeHandler;
import com.tashow.cloud.systemapi.enums.common.SexEnum;
import com.tashow.cloud.tenant.core.db.TenantBaseDO;
import lombok.*;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import java.time.LocalDateTime;
import java.util.List;
/**
* 会员用户 DO
*
* uk_mobile 索引:基于 {@link #mobile} 字段
*
*/
@TableName(value = "member_user", autoResultMap = true)
@Data
@EqualsAndHashCode(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MemberUserDO extends TenantBaseDO {
// ========== 账号信息 ==========
/**
* 用户ID
*/
@TableId
private Long id;
/**
* 手机
*/
private String mobile;
/**
* 加密后的密码
*
* 因为目前使用 {@link BCryptPasswordEncoder} 加密器,所以无需自己处理 salt 盐
*/
private String password;
/**
* 帐号状态
*
* 枚举 {@link CommonStatusEnum}
*/
private Integer status;
/**
* 注册 IP
*/
private String registerIp;
/**
* 注册终端
* 枚举 {@link TerminalEnum}
*/
private Integer registerTerminal;
/**
* 最后登录IP
*/
private String loginIp;
/**
* 最后登录时间
*/
private LocalDateTime loginDate;
// ========== 基础信息 ==========
/**
* 用户昵称
*/
private String nickname;
/**
* 用户头像
*/
private String avatar;
/**
* 真实名字
*/
private String name;
/**
* 性别
*
* 枚举 {@link SexEnum}
*/
private Integer sex;
/**
* 出生日期
*/
private LocalDateTime birthday;
/**
* 所在地
*
* 关联 {@link Area#getId()} 字段
*/
private Integer areaId;
/**
* 用户备注
*/
private String mark;
// ========== 其它信息 ==========
/**
* 积分
*/
private Integer point;
// TODO 疯狂:增加一个 totalPoint个人信息接口要返回
/**
* 会员标签列表,以逗号分隔
*/
@TableField(typeHandler = LongListTypeHandler.class)
private List<Long> tagIds;
/**
* 会员级别编号
*
* 关联 {@link MemberLevelDO#getId()} 字段
*/
private Long levelId;
/**
* 会员经验
*/
private Integer experience;
/**
* 用户分组编号
*
* 关联 {@link MemberGroupDO#getId()} 字段
*/
private Long groupId;
}

View File

@@ -1,22 +0,0 @@
package com.tashow.cloud.member.dal.mysql.address;
import com.tashow.cloud.member.dal.dataobject.address.MemberAddressDO;
import com.tashow.cloud.mybatis.mybatis.core.mapper.BaseMapperX;
import com.tashow.cloud.mybatis.mybatis.core.query.LambdaQueryWrapperX;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface MemberAddressMapper extends BaseMapperX<MemberAddressDO> {
default MemberAddressDO selectByIdAndUserId(Long id, Long userId) {
return selectOne(MemberAddressDO::getId, id, MemberAddressDO::getUserId, userId);
}
default List<MemberAddressDO> selectListByUserIdAndDefaulted(Long userId, Boolean defaulted) {
return selectList(new LambdaQueryWrapperX<MemberAddressDO>().eq(MemberAddressDO::getUserId, userId)
.eqIfPresent(MemberAddressDO::getDefaultStatus, defaulted));
}
}

View File

@@ -1,96 +0,0 @@
package com.tashow.cloud.member.dal.mysql.user;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.member.controller.admin.user.vo.MemberUserPageReqVO;
import com.tashow.cloud.member.dal.dataobject.user.MemberUserDO;
import com.tashow.cloud.mybatis.mybatis.core.mapper.BaseMapperX;
import com.tashow.cloud.mybatis.mybatis.core.query.LambdaQueryWrapperX;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.stream.Collectors;
/**
* 会员 User Mapper
*
* @author 芋道源码
*/
@Mapper
public interface MemberUserMapper extends BaseMapperX<MemberUserDO> {
default MemberUserDO selectByMobile(String mobile) {
return selectOne(MemberUserDO::getMobile, mobile);
}
default List<MemberUserDO> selectListByNicknameLike(String nickname) {
return selectList(new LambdaQueryWrapperX<MemberUserDO>()
.likeIfPresent(MemberUserDO::getNickname, nickname));
}
default PageResult<MemberUserDO> selectPage(MemberUserPageReqVO reqVO) {
// 处理 tagIds 过滤条件
String tagIdSql = "";
if (CollUtil.isNotEmpty(reqVO.getTagIds())) {
tagIdSql = reqVO.getTagIds().stream()
.map(tagId -> "FIND_IN_SET(" + tagId + ", tag_ids)")
.collect(Collectors.joining(" OR "));
}
// 分页查询
return selectPage(reqVO, new LambdaQueryWrapperX<MemberUserDO>()
.likeIfPresent(MemberUserDO::getMobile, reqVO.getMobile())
.betweenIfPresent(MemberUserDO::getLoginDate, reqVO.getLoginDate())
.likeIfPresent(MemberUserDO::getNickname, reqVO.getNickname())
.betweenIfPresent(MemberUserDO::getCreateTime, reqVO.getCreateTime())
.eqIfPresent(MemberUserDO::getLevelId, reqVO.getLevelId())
.eqIfPresent(MemberUserDO::getGroupId, reqVO.getGroupId())
.apply(StrUtil.isNotEmpty(tagIdSql), tagIdSql)
.orderByDesc(MemberUserDO::getId));
}
default Long selectCountByGroupId(Long groupId) {
return selectCount(MemberUserDO::getGroupId, groupId);
}
default Long selectCountByLevelId(Long levelId) {
return selectCount(MemberUserDO::getLevelId, levelId);
}
default Long selectCountByTagId(Long tagId) {
return selectCount(new LambdaQueryWrapperX<MemberUserDO>()
.apply("FIND_IN_SET({0}, tag_ids)", tagId));
}
/**
* 更新用户积分(增加)
*
* @param id 用户编号
* @param incrCount 增加积分(正数)
*/
default void updatePointIncr(Long id, Integer incrCount) {
Assert.isTrue(incrCount > 0);
LambdaUpdateWrapper<MemberUserDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<MemberUserDO>()
.setSql(" point = point + " + incrCount)
.eq(MemberUserDO::getId, id);
update(null, lambdaUpdateWrapper);
}
/**
* 更新用户积分(减少)
*
* @param id 用户编号
* @param incrCount 增加积分(负数)
* @return 更新行数
*/
default int updatePointDecr(Long id, Integer incrCount) {
Assert.isTrue(incrCount < 0);
LambdaUpdateWrapper<MemberUserDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<MemberUserDO>()
.setSql(" point = point + " + incrCount) // 负数,所以使用 + 号
.eq(MemberUserDO::getId, id);
return update(null, lambdaUpdateWrapper);
}
}

View File

@@ -1,4 +0,0 @@
/**
* 占位
*/
package com.tashow.cloud.member.framework.rpc;

View File

@@ -1,4 +0,0 @@
/**
* 占位
*/
package com.tashow.cloud.member.framework.security.core;

View File

@@ -1,4 +0,0 @@
/**
* 消息队列的消费者
*/
package com.tashow.cloud.member.mq.consumer;

View File

@@ -1,4 +0,0 @@
/**
* 消息队列的消息
*/
package com.tashow.cloud.member.mq.message;

View File

@@ -1,4 +0,0 @@
/**
* 消息队列的生产者
*/
package com.tashow.cloud.member.mq.producer;

View File

@@ -1,31 +0,0 @@
package com.tashow.cloud.member.mq.producer.user;
import com.tashow.cloud.memberapi.message.user.MemberUserCreateMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
/**
* 会员用户 Producer
*
* @author owen
*/
@Slf4j
@Component
public class MemberUserProducer {
@Resource
private ApplicationContext applicationContext;
/**
* 发送 {@link MemberUserCreateMessage} 消息
*
* @param userId 用户编号
*/
public void sendUserCreateMessage(Long userId) {
applicationContext.publishEvent(new MemberUserCreateMessage().setUserId(userId));
}
}

View File

@@ -1,8 +0,0 @@
/**
* member 模块,我们放会员业务。
* 例如说:会员中心等等
*
* 1. Controller URL以 /member/ 开头,避免和其它 Module 冲突
* 2. DataObject 表名:以 member_ 开头,方便在数据库中区分
*/
package com.tashow.cloud.member;

View File

@@ -1,67 +0,0 @@
package com.tashow.cloud.member.service.address;
import com.tashow.cloud.member.controller.app.address.vo.AppAddressCreateReqVO;
import com.tashow.cloud.member.controller.app.address.vo.AppAddressUpdateReqVO;
import com.tashow.cloud.member.dal.dataobject.address.MemberAddressDO;
import jakarta.validation.Valid;
import java.util.List;
/**
* 用户收件地址 Service 接口
*
* @author 芋道源码
*/
public interface AddressService {
/**
* 创建用户收件地址
*
*
* @param userId 用户编号
* @param createReqVO 创建信息
* @return 编号
*/
Long createAddress(Long userId, @Valid AppAddressCreateReqVO createReqVO);
/**
* 更新用户收件地址
*
* @param userId 用户编号
* @param updateReqVO 更新信息
*/
void updateAddress(Long userId, @Valid AppAddressUpdateReqVO updateReqVO);
/**
* 删除用户收件地址
*
* @param userId 用户编号
* @param id 编号
*/
void deleteAddress(Long userId, Long id);
/**
* 获得用户收件地址
*
* @param id 编号
* @return 用户收件地址
*/
MemberAddressDO getAddress(Long userId, Long id);
/**
* 获得用户收件地址列表
*
* @param userId 用户编号
* @return 用户收件地址列表
*/
List<MemberAddressDO> getAddressList(Long userId);
/**
* 获得用户默认的收件地址
*
* @param userId 用户编号
* @return 用户收件地址
*/
MemberAddressDO getDefaultUserAddress(Long userId);
}

View File

@@ -1,97 +0,0 @@
package com.tashow.cloud.member.service.address;
import cn.hutool.core.collection.CollUtil;
import com.tashow.cloud.member.controller.app.address.vo.AppAddressCreateReqVO;
import com.tashow.cloud.member.controller.app.address.vo.AppAddressUpdateReqVO;
import com.tashow.cloud.member.convert.address.AddressConvert;
import com.tashow.cloud.member.dal.dataobject.address.MemberAddressDO;
import com.tashow.cloud.member.dal.mysql.address.MemberAddressMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.List;
import static com.tashow.cloud.common.exception.util.ServiceExceptionUtil.exception;
import static com.tashow.cloud.memberapi.enums.ErrorCodeConstants.ADDRESS_NOT_EXISTS;
/**
* 用户收件地址 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class AddressServiceImpl implements AddressService {
@Resource
private MemberAddressMapper memberAddressMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createAddress(Long userId, AppAddressCreateReqVO createReqVO) {
// 如果添加的是默认收件地址,则将原默认地址修改为非默认
if (Boolean.TRUE.equals(createReqVO.getDefaultStatus())) {
List<MemberAddressDO> addresses = memberAddressMapper.selectListByUserIdAndDefaulted(userId, true);
addresses.forEach(address -> memberAddressMapper.updateById(new MemberAddressDO().setId(address.getId()).setDefaultStatus(false)));
}
// 插入
MemberAddressDO address = AddressConvert.INSTANCE.convert(createReqVO);
address.setUserId(userId);
memberAddressMapper.insert(address);
// 返回
return address.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateAddress(Long userId, AppAddressUpdateReqVO updateReqVO) {
// 校验存在,校验是否能够操作
validAddressExists(userId, updateReqVO.getId());
// 如果修改的是默认收件地址,则将原默认地址修改为非默认
if (Boolean.TRUE.equals(updateReqVO.getDefaultStatus())) {
List<MemberAddressDO> addresses = memberAddressMapper.selectListByUserIdAndDefaulted(userId, true);
addresses.stream().filter(u -> !u.getId().equals(updateReqVO.getId())) // 排除自己
.forEach(address -> memberAddressMapper.updateById(new MemberAddressDO().setId(address.getId()).setDefaultStatus(false)));
}
// 更新
MemberAddressDO updateObj = AddressConvert.INSTANCE.convert(updateReqVO);
memberAddressMapper.updateById(updateObj);
}
@Override
public void deleteAddress(Long userId, Long id) {
// 校验存在,校验是否能够操作
validAddressExists(userId, id);
// 删除
memberAddressMapper.deleteById(id);
}
private void validAddressExists(Long userId, Long id) {
MemberAddressDO addressDO = getAddress(userId, id);
if (addressDO == null) {
throw exception(ADDRESS_NOT_EXISTS);
}
}
@Override
public MemberAddressDO getAddress(Long userId, Long id) {
return memberAddressMapper.selectByIdAndUserId(id, userId);
}
@Override
public List<MemberAddressDO> getAddressList(Long userId) {
return memberAddressMapper.selectListByUserIdAndDefaulted(userId, null);
}
@Override
public MemberAddressDO getDefaultUserAddress(Long userId) {
List<MemberAddressDO> addresses = memberAddressMapper.selectListByUserIdAndDefaulted(userId, true);
return CollUtil.getFirst(addresses);
}
}

View File

@@ -1,48 +0,0 @@
spring:
main:
lazy-initialization: true # 开启懒加载,加快速度
banner-mode: off # 单元测试,禁用 Banner
--- #################### 数据库相关配置 ####################
spring:
# 数据源配置项
datasource:
name: ruoyi-vue-pro
url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式DATABASE_TO_UPPER 配置表和字段使用小写
driver-class-name: org.h2.Driver
username: sa
password:
druid:
async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
initial-size: 1 # 单元测试,配置为 1提升启动速度
sql:
init:
schema-locations: classpath:/sql/create_tables.sql
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
data:
redis:
host: 127.0.0.1 # 地址
port: 16379 # 端口(单元测试,使用 16379 端口)
database: 0 # 数据库索引
mybatis:
lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
--- #################### 定时任务相关配置 ####################
--- #################### 配置中心相关配置 ####################
--- #################### 服务保障相关配置 ####################
# Lock4j 配置项(单元测试,禁用 Lock4j
--- #################### 监控相关配置 ####################
--- #################### 芋道相关配置 ####################
# 芋道配置项,设置当前项目所有自定义的配置
yudao:
info:
base-package: cn.iocoder.yudao.module

View File

@@ -1,4 +0,0 @@
<configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
</configuration>

View File

@@ -1,5 +0,0 @@
DELETE FROM "member_user";
DELETE FROM "member_address";
DELETE FROM "member_tag";
DELETE FROM "member_level";
DELETE FROM "member_group";

View File

@@ -1,113 +0,0 @@
CREATE TABLE IF NOT EXISTS "member_user"
(
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '编号',
"nickname" varchar(30) NOT NULL DEFAULT '' COMMENT '用户昵称',
"name" varchar(30) NULL COMMENT '真实名字',
sex tinyint null comment '性别',
birthday datetime null comment '出生日期',
area_id int null comment '所在地',
mark varchar(255) null comment '用户备注',
point int default 0 null comment '积分',
"avatar" varchar(255) NOT NULL DEFAULT '' COMMENT '头像',
"status" tinyint NOT NULL COMMENT '状态',
"mobile" varchar(11) NOT NULL COMMENT '手机号',
"password" varchar(100) NOT NULL DEFAULT '' COMMENT '密码',
"register_ip" varchar(32) NOT NULL COMMENT '注册 IP',
"login_ip" varchar(50) NULL DEFAULT '' COMMENT '最后登录IP',
"login_date" datetime NULL DEFAULT NULL COMMENT '最后登录时间',
"tag_ids" varchar(255) NULL DEFAULT NULL COMMENT '用户标签编号列表,以逗号分隔',
"level_id" bigint NULL DEFAULT NULL COMMENT '等级编号',
"experience" bigint NULL DEFAULT NULL COMMENT '经验',
"group_id" bigint NULL DEFAULT NULL COMMENT '用户分组编号',
"creator" varchar(64) NULL DEFAULT '' COMMENT '创建者',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
"updater" varchar(64) NULL DEFAULT '' COMMENT '更新者',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
"deleted" bit(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
"tenant_id" bigint not null default '0',
PRIMARY KEY ("id")
) COMMENT '会员表';
CREATE TABLE IF NOT EXISTS "member_address" (
"id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"user_id" bigint(20) NOT NULL,
"name" varchar(10) NOT NULL,
"mobile" varchar(20) NOT NULL,
"area_id" bigint(20) NOT NULL,
"detail_address" varchar(250) NOT NULL,
"default_status" bit NOT NULL,
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"creator" varchar(64) DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"updater" varchar(64) DEFAULT '',
PRIMARY KEY ("id")
) COMMENT '用户收件地址';
CREATE TABLE IF NOT EXISTS "member_tag"
(
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar NOT NULL,
"creator" varchar DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint NOT NULL default '0',
PRIMARY KEY ("id")
) COMMENT '会员标签';
CREATE TABLE IF NOT EXISTS "member_level"
(
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar NOT NULL,
"experience" int NOT NULL,
"level" int NOT NULL,
"discount_percent" int NOT NULL,
"icon" varchar NOT NULL,
"background_url" varchar NOT NULL,
"creator" varchar DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
"status" tinyint NOT NULL DEFAULT '0',
PRIMARY KEY ("id")
) COMMENT '会员等级';
CREATE TABLE IF NOT EXISTS "member_group"
(
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar NOT NULL,
"remark" varchar NOT NULL,
"status" tinyint NOT NULL DEFAULT '0',
"creator" varchar DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
PRIMARY KEY ("id")
) COMMENT '用户分组';
CREATE TABLE IF NOT EXISTS "member_brokerage_record"
(
"id" int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"user_id" bigint NOT NULL,
"biz_id" varchar NOT NULL,
"biz_type" varchar NOT NULL,
"title" varchar NOT NULL,
"price" int NOT NULL,
"total_price" int NOT NULL,
"description" varchar NOT NULL,
"status" varchar NOT NULL,
"frozen_days" int NOT NULL,
"unfreeze_time" varchar,
"creator" varchar DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
PRIMARY KEY ("id")
) COMMENT '佣金记录';

View File

@@ -1,10 +1,8 @@
package com.tashow.cloud.product; package com.tashow.cloud.product;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan; import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableScheduling;
/** /**
* 应用服务启动类 * 应用服务启动类

View File

@@ -1,20 +1,20 @@
package com.tashow.cloud.product.api; package com.tashow.cloud.product.api;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageResult; import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.product.service.ProdService; import com.tashow.cloud.product.service.ProdService;
import com.tashow.cloud.product.service.ShopDetailService; import com.tashow.cloud.product.service.SkuService;
import com.tashow.cloud.productapi.api.product.ProdApi; import com.tashow.cloud.productapi.api.product.ProdApi;
import com.tashow.cloud.productapi.api.product.ShopDetailApi;
import com.tashow.cloud.productapi.api.product.dto.ProdDO; import com.tashow.cloud.productapi.api.product.dto.ProdDO;
import com.tashow.cloud.productapi.api.product.dto.ShopDetailDO;
import com.tashow.cloud.productapi.api.product.vo.prod.ProdListVO; import com.tashow.cloud.productapi.api.product.vo.prod.ProdListVO;
import com.tashow.cloud.productapi.api.product.vo.prod.ProdPageReqVO; import com.tashow.cloud.productapi.api.product.vo.prod.ProdPageReqVO;
import com.tashow.cloud.productapi.api.product.vo.prod.ProdServiceVO; import com.tashow.cloud.productapi.api.product.vo.prod.ProdServiceVO;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@RestController // 提供 RESTful API 接口,给 Feign 调用 @RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated @Validated
public class ProdImpl implements ProdApi { public class ProdImpl implements ProdApi {
@@ -22,9 +22,12 @@ public class ProdImpl implements ProdApi {
@Resource @Resource
private ProdService prodService; private ProdService prodService;
@Resource
private SkuService skuService;
@Override @Override
public ProdDO getProdInfo(Long id) { public CommonResult<ProdDO> getProdInfo(Long id) {
return prodService.getProd(id); return CommonResult.success(prodService.getProd(id));
} }
@Override @Override
@@ -37,4 +40,16 @@ public class ProdImpl implements ProdApi {
return prodService.getProdPage(pageReqVO); return prodService.getProdPage(pageReqVO);
} }
@Override
public CommonResult<Boolean> reduceStocks(Long skuId, Integer stocksNum) {
skuService.reduceStocks(skuId, stocksNum);
return success(true);
}
@Override
public CommonResult<Boolean> increaseStocks(Long skuId, Integer stocksNum) {
skuService.increaseStocks(skuId, stocksNum);
return success(true);
}
} }

View File

@@ -3,12 +3,10 @@ package com.tashow.cloud.product.controller.admin;
import com.tashow.cloud.common.pojo.CommonResult; import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageResult; import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.product.mapper.ProdMapper; import com.tashow.cloud.product.mapper.ProdMapper;
import com.tashow.cloud.productapi.api.product.dto.ProdDO;
import com.tashow.cloud.product.service.ProdService; import com.tashow.cloud.product.service.ProdService;
import com.tashow.cloud.productapi.api.product.dto.SkuDO; import com.tashow.cloud.product.service.SkuService;
import com.tashow.cloud.productapi.api.product.dto.ProdDO;
import com.tashow.cloud.productapi.api.product.vo.prod.*; import com.tashow.cloud.productapi.api.product.vo.prod.*;
import com.tashow.cloud.productapi.api.product.vo.sku.SkuPageReqVO;
import com.tashow.cloud.productapi.api.product.vo.sku.SkuRecycleBinVO;
import com.tashow.cloud.productapi.enums.BaseEnum; import com.tashow.cloud.productapi.enums.BaseEnum;
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;
@@ -33,6 +31,8 @@ public class ProdController {
@Resource @Resource
private ProdService prodService; private ProdService prodService;
@Resource @Resource
private SkuService skuService;
@Resource
private ProdMapper prodMapper; private ProdMapper prodMapper;
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建商品") @Operation(summary = "创建商品")
@@ -124,6 +124,7 @@ public class ProdController {
@GetMapping("/getProdInfo") @GetMapping("/getProdInfo")
@Operation(summary = "获得商品详情a") @Operation(summary = "获得商品详情a")
@Parameter(name = "id", description = "编号", required = true, example = "1024") @Parameter(name = "id", description = "编号", required = true, example = "1024")
@PermitAll
public CommonResult<ProdDO> getProdInfo(@RequestParam("id") Long id) { public CommonResult<ProdDO> getProdInfo(@RequestParam("id") Long id) {
ProdDO prod = prodService.getProd(id); ProdDO prod = prodService.getProd(id);
return success(prod); return success(prod);
@@ -156,4 +157,23 @@ public class ProdController {
} }
@PostMapping("/reduceStocks")
@Operation(summary = "扣减库存")
@PermitAll
public CommonResult<Boolean> reduceStocks(@RequestParam("skuid") Long skuId,
@RequestParam("stocksNum") Integer stocksNum) {
skuService.reduceStocks(skuId, stocksNum);
return success(true);
}
@PostMapping("/increaseStocks")
@Operation(summary = "增加库存")
@PermitAll
public CommonResult<Boolean> increaseStocks(@RequestParam("skuid") Long skuId,
@RequestParam("stocksNum") Integer stocksNum) {
skuService.increaseStocks(skuId, stocksNum);
return success(true);
}
} }

View File

@@ -9,6 +9,7 @@ import com.tashow.cloud.productapi.api.product.dto.SkuDO;
import com.tashow.cloud.productapi.api.product.vo.sku.SkuRecycleBinVO; import com.tashow.cloud.productapi.api.product.vo.sku.SkuRecycleBinVO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
/** /**
* 单品SKU Mapper * 单品SKU Mapper
@@ -44,4 +45,25 @@ public interface SkuMapper extends BaseMapperX<SkuDO> {
// 查询商品下所有 SKU 的 is_shelf 状态(未删除) // 查询商品下所有 SKU 的 is_shelf 状态(未删除)
List<Integer> selectShelfStatusByProdId(@Param("prodId") Long prodId); List<Integer> selectShelfStatusByProdId(@Param("prodId") Long prodId);
/**
* 扣减库存(带乐观锁)
* @param skuId 单品ID
* @param stocksNum 扣减数量
* @param version 版本号
* @return 更新影响的行数
*/
@Update("UPDATE tz_sku SET stocks = stocks - #{stocksNum}, version = version + 1, update_time = NOW() " +
"WHERE sku_id = #{skuId} AND version = #{version} AND stocks >= #{stocksNum} AND deleted = 0")
int reduceStocks(@Param("skuId") Long skuId,
@Param("stocksNum") Integer stocksNum,
@Param("version") Integer version);
/**
* 增加库存
*/
@Update("UPDATE tz_sku SET stocks = stocks + #{stocksNum}, version = version + 1, update_time = NOW() " +
"WHERE sku_id = #{skuId} AND deleted = 0")
int increaseStocks(@Param("skuId") Long skuId,
@Param("stocksNum") Integer stocksNum);
} }

View File

@@ -0,0 +1,43 @@
package com.tashow.cloud.product.security.config;
import com.tashow.cloud.productapi.enums.ApiConstants;
import com.tashow.cloud.security.security.config.AuthorizeRequestsCustomizer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
/**
* Infra 模块的 Security 配置
*/
@Configuration(proxyBeanMethods = false, value = "prodSecurityConfiguration")
public class ProdSecurityConfiguration {
@Value("${spring.boot.admin.context-path:''}")
private String adminSeverContextPath;
@Bean("prodAuthorizeRequestsCustomizer")
public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {
return new AuthorizeRequestsCustomizer() {
@Override
public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry registry) {
// Spring Boot Actuator 的安全配置
registry.requestMatchers("/actuator").permitAll()
.requestMatchers("/actuator/**").permitAll();
// Druid 监控
registry.requestMatchers("/druid/**").permitAll();
// Spring Boot Admin Server 的安全配置
registry.requestMatchers(adminSeverContextPath).permitAll()
.requestMatchers(adminSeverContextPath + "/**").permitAll();
// TODO 芋艿:这个每个项目都需要重复配置,得捉摸有没通用的方案
// RPC 服务的安全配置
registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll();
}
};
}
}

View File

@@ -175,5 +175,17 @@ public interface SkuService {
* @param skuServiceDeliverList 更新信息 * @param skuServiceDeliverList 更新信息
*/ */
void updateDeliver(List<SkuServiceDeliverDO> skuServiceDeliverList); void updateDeliver(List<SkuServiceDeliverDO> skuServiceDeliverList);
/**
* 扣减库存
* @param skuId 单品ID
* @param stocksNum 扣减数量
*/
void reduceStocks(Long skuId, Integer stocksNum);
/**
* 增加库存
* @param skuId 单品ID
* @param stocksNum 增加数量
*/
void increaseStocks(Long skuId, Integer stocksNum);
} }

View File

@@ -18,6 +18,7 @@ import com.tashow.cloud.productapi.api.product.vo.sku.*;
import com.tashow.cloud.productapi.enums.BaseEnum; import com.tashow.cloud.productapi.enums.BaseEnum;
import com.tashow.cloud.productapi.enums.ErrorCodeConstants; import com.tashow.cloud.productapi.enums.ErrorCodeConstants;
import com.tashow.cloud.productapi.enums.ServiceTypeEnum; import com.tashow.cloud.productapi.enums.ServiceTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -41,6 +42,7 @@ import static com.tashow.cloud.common.exception.util.ServiceExceptionUtil.except
*/ */
@Service @Service
@Validated @Validated
@Slf4j
public class SkuServiceImpl implements SkuService { public class SkuServiceImpl implements SkuService {
@Resource @Resource
@@ -967,6 +969,62 @@ public class SkuServiceImpl implements SkuService {
skuServiceDeliverMapper.insertBatch(skuServiceDeliverList); skuServiceDeliverMapper.insertBatch(skuServiceDeliverList);
} }
} }
@Override
@Transactional(rollbackFor = Exception.class)
public void reduceStocks(Long skuId, Integer stocksNum) {
if (stocksNum == null || stocksNum <= 0) {
stocksNum=1;
}
// 查询SKU信息
SkuDO sku = skuMapper.selectById(skuId);
if (sku == null) {
//商品不存在
throw exception(ErrorCodeConstants.SKU_DOES_NOT_EXIST);
}
if (sku.getDeleted() == 1) {
//商品已删除
throw exception(ErrorCodeConstants.SKU_DELETE);
}
if (sku.getStatus() == 0) {
//商品已禁用
throw exception(ErrorCodeConstants.SKU_DISABLE);
}
// 检查无限库存标志
if (sku.getStocksFlg() != null && sku.getStocksFlg() == 1) {
log.info("SKU {} 为无限库存,无需扣减", skuId);
return;
}
// 检查库存是否充足
if (sku.getStocks() < stocksNum) {
throw new IllegalArgumentException("库存不足,当前库存:" + sku.getStocks() + ",需要:" + stocksNum);
}
// 扣减库存
int updateRows = skuMapper.reduceStocks(skuId, stocksNum, sku.getVersion());
if (updateRows == 0) {
// 可能是版本号冲突或库存不足
SkuDO currentSku = skuMapper.selectById(skuId);
if (currentSku.getStocks() < stocksNum) {
throw new IllegalArgumentException("库存不足,当前库存:" + sku.getStocks() + ",需要:" + stocksNum);
} else {
throw new IllegalArgumentException("扣减库存失败,请重试");
}
}
log.info("扣减库存成功 - SKU: {}, 扣减数量: {}, 剩余库存: {}",skuId, stocksNum, sku.getStocks() - stocksNum);
}
@Override
public void increaseStocks(Long skuId, Integer stocksNum) {
// 查询SKU信息
SkuDO sku = skuMapper.selectById(skuId);
// 检查无限库存标志
if (sku.getStocksFlg() != null && sku.getStocksFlg() == 1) {
log.info("SKU {} 为无限库存,无需增加", skuId);
return;
}
skuMapper.increaseStocks(skuId, stocksNum);
}
} }

View File

@@ -1,9 +1,5 @@
package com.tashow.cloud.system.controller.admin.auth; package com.tashow.cloud.system.controller.admin.auth;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.common.util.collection.CollectionUtils.convertSet;
import static com.tashow.cloud.web.web.core.util.WebFrameworkUtils.getLoginUserId;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.tashow.cloud.common.enums.CommonStatusEnum; import com.tashow.cloud.common.enums.CommonStatusEnum;
@@ -11,14 +7,7 @@ import com.tashow.cloud.common.enums.UserTypeEnum;
import com.tashow.cloud.common.pojo.CommonResult; import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.security.security.config.SecurityProperties; import com.tashow.cloud.security.security.config.SecurityProperties;
import com.tashow.cloud.security.security.core.util.SecurityFrameworkUtils; import com.tashow.cloud.security.security.core.util.SecurityFrameworkUtils;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthLoginReqVO; import com.tashow.cloud.system.controller.admin.auth.vo.*;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthLoginRespVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthPermissionInfoRespVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthRegisterReqVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthResetPasswordReqVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthSmsLoginReqVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthSmsSendReqVO;
import com.tashow.cloud.system.controller.admin.auth.vo.AuthSocialLoginReqVO;
import com.tashow.cloud.system.convert.auth.AuthConvert; import com.tashow.cloud.system.convert.auth.AuthConvert;
import com.tashow.cloud.system.dal.dataobject.permission.MenuDO; import com.tashow.cloud.system.dal.dataobject.permission.MenuDO;
import com.tashow.cloud.system.dal.dataobject.permission.RoleDO; import com.tashow.cloud.system.dal.dataobject.permission.RoleDO;
@@ -34,17 +23,17 @@ import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll; import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated; import static com.tashow.cloud.common.pojo.CommonResult.success;
import org.springframework.web.bind.annotation.GetMapping; import static com.tashow.cloud.common.util.collection.CollectionUtils.convertSet;
import org.springframework.web.bind.annotation.PostMapping; import static com.tashow.cloud.web.web.core.util.WebFrameworkUtils.getLoginUserId;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/** 管理后台 - 认证 */ /** 管理后台 - 认证 */
@RestController @RestController

View File

@@ -46,6 +46,10 @@
<groupId>com.tashow.cloud</groupId> <groupId>com.tashow.cloud</groupId>
<artifactId>tashow-trade-api</artifactId> <artifactId>tashow-trade-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.tashow.cloud</groupId>
<artifactId>tashow-product-api</artifactId>
</dependency>
<!-- Web 相关 --> <!-- Web 相关 -->
<dependency> <dependency>

View File

@@ -4,14 +4,14 @@ import cn.hutool.core.collection.CollUtil;
import com.tashow.cloud.common.pojo.CommonResult; import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageResult; import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.memberapi.api.user.MemberUserApi; import com.tashow.cloud.memberapi.api.user.MemberUserApi;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderDetailRespVO; import com.tashow.cloud.productapi.api.product.ProdApi;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderPageReqVO; import com.tashow.cloud.productapi.api.product.dto.ProdDO;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderPageRespVO; import com.tashow.cloud.trade.controller.admin.order.vo.*;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderSummaryRespVO;
import com.tashow.cloud.trade.convert.order.TradeOrderConvert; import com.tashow.cloud.trade.convert.order.TradeOrderConvert;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderDO; import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderDO;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderItemDO; import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderItemDO;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderLogDO; import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderLogDO;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderSubLogDO;
import com.tashow.cloud.trade.service.order.TradeOrderLogService; import com.tashow.cloud.trade.service.order.TradeOrderLogService;
import com.tashow.cloud.trade.service.order.TradeOrderQueryService; import com.tashow.cloud.trade.service.order.TradeOrderQueryService;
import com.tashow.cloud.trade.service.order.TradeOrderUpdateService; import com.tashow.cloud.trade.service.order.TradeOrderUpdateService;
@@ -20,10 +20,7 @@ import jakarta.annotation.security.PermitAll;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
@@ -49,9 +46,12 @@ public class TradeOrderController {
@Resource @Resource
private MemberUserApi memberUserApi; private MemberUserApi memberUserApi;
@Resource
private ProdApi prodApi;
/** /**
* 获得交易订单分页 * 获得交易订单分页
*
* @param reqVO * @param reqVO
* @return * @return
*/ */
@@ -73,6 +73,7 @@ public class TradeOrderController {
/** /**
* 获得交易订单详情 * 获得交易订单详情
*
* @param id 订单编号 * @param id 订单编号
* @return * @return
*/ */
@@ -92,10 +93,9 @@ public class TradeOrderController {
return success(TradeOrderConvert.INSTANCE.convert(order, orderItems, orderLogs)); return success(TradeOrderConvert.INSTANCE.convert(order, orderItems, orderLogs));
} }
//
/** /**
* 获得交易订单统计 * 获得交易订单统计
*
* @return * @return
*/ */
@GetMapping("/summary") @GetMapping("/summary")
@@ -104,73 +104,81 @@ public class TradeOrderController {
public CommonResult<TradeOrderSummaryRespVO> getOrderSummary() { public CommonResult<TradeOrderSummaryRespVO> getOrderSummary() {
return success(tradeOrderQueryService.getOrderSummary()); return success(tradeOrderQueryService.getOrderSummary());
} }
//
// // 获得交易订单的物流轨迹 /**
// // id: 交易订单编号 * 取消订单
// @GetMapping("/get-express-track-list") *
* @return
*/
@PutMapping("/cancel")
@PermitAll
// @PreAuthorize("@ss.hasPermission('trade:order:query')") // @PreAuthorize("@ss.hasPermission('trade:order:query')")
// public CommonResult<List<?>> getOrderExpressTrackList(@RequestParam("id") Long id) { public CommonResult<Boolean> cancel(@RequestParam("id") Long id) {
// return success(TradeOrderConvert.INSTANCE.convertList02( return success(tradeOrderUpdateService.cancelOrderByAdmin(id));
// tradeOrderQueryService.getExpressTrackList(id))); }
// }
// /**
// // 订单发货 * 接单确认
// @PutMapping("/delivery") *
// @PreAuthorize("@ss.hasPermission('trade:order:update')") * @return
// public CommonResult<Boolean> deliveryOrder(@RequestBody TradeOrderDeliveryReqVO deliveryReqVO) { */
// tradeOrderUpdateService.deliveryOrder(deliveryReqVO); @PutMapping("/acceptConfirm")
// return success(true); @PermitAll
// }
//
// // 订单备注
// @PutMapping("/update-remark")
// @PreAuthorize("@ss.hasPermission('trade:order:update')")
// public CommonResult<Boolean> updateOrderRemark(@RequestBody TradeOrderRemarkReqVO reqVO) {
// tradeOrderUpdateService.updateOrderRemark(reqVO);
// return success(true);
// }
//
// // 订单调价
// @PutMapping("/update-price")
// @PreAuthorize("@ss.hasPermission('trade:order:update')")
// public CommonResult<Boolean> updateOrderPrice(@RequestBody TradeOrderUpdatePriceReqVO reqVO) {
// tradeOrderUpdateService.updateOrderPrice(reqVO);
// return success(true);
// }
//
// // 修改订单收货地址
// @PutMapping("/update-address")
// @PreAuthorize("@ss.hasPermission('trade:order:update')")
// public CommonResult<Boolean> updateOrderAddress(@RequestBody TradeOrderUpdateAddressReqVO reqVO) {
// tradeOrderUpdateService.updateOrderAddress(reqVO);
// return success(true);
// }
//
// // 订单核销
// // id: 交易订单编号
// @PutMapping("/pick-up-by-id")
// @PreAuthorize("@ss.hasPermission('trade:order:pick-up')")
// public CommonResult<Boolean> pickUpOrderById(@RequestParam("id") Long id) {
// tradeOrderUpdateService.pickUpOrderByAdmin(getLoginUserId(), id);
// return success(true);
// }
//
// // 订单核销
// // pickUpVerifyCode: 自提核销码
// @PutMapping("/pick-up-by-verify-code")
// @PreAuthorize("@ss.hasPermission('trade:order:pick-up')")
// public CommonResult<Boolean> pickUpOrderByVerifyCode(@RequestParam("pickUpVerifyCode") String pickUpVerifyCode) {
// tradeOrderUpdateService.pickUpOrderByAdmin(getLoginUserId(), pickUpVerifyCode);
// return success(true);
// }
//
// // 查询核销码对应的订单
// // pickUpVerifyCode: 自提核销码
// @GetMapping("/get-by-pick-up-verify-code")
// @PreAuthorize("@ss.hasPermission('trade:order:query')") // @PreAuthorize("@ss.hasPermission('trade:order:query')")
// public CommonResult<TradeOrderDetailRespVO> getByPickUpVerifyCode(@RequestParam("pickUpVerifyCode") String pickUpVerifyCode) { public CommonResult<Boolean> acceptConfirm(@RequestParam("id") Long id) {
// TradeOrderDO tradeOrder = tradeOrderUpdateService.getByPickUpVerifyCode(pickUpVerifyCode); tradeOrderUpdateService.acceptConfirmOrderByAdmin(id);
// return success(TradeOrderConvert.INSTANCE.convert2(tradeOrder, null)); return success(true);
// } }
/**
* 服务上报
*
* @return
*/
@PutMapping("/reportServe")
@PermitAll
// @PreAuthorize("@ss.hasPermission('trade:order:query')")
public CommonResult<Boolean> reportServe(@RequestParam("id") Long id) {
tradeOrderUpdateService.reportServeOrderByAdmin(id);
return success(true);
}
// 订单备注
@PutMapping("/update-remark")
@PermitAll
// @PreAuthorize("@ss.hasPermission('trade:order:update')")
public CommonResult<Boolean> updateOrderRemark(@RequestBody TradeOrderRemarkReqVO reqVO) {
tradeOrderUpdateService.updateOrderRemark(reqVO);
return success(true);
}
/**
* 交易快照
* @return
*/
@GetMapping("/fastPhoto")
@PermitAll
// @PreAuthorize("@ss.hasPermission('trade:order:query')")
public CommonResult<TradeOrderFastPhotoRespVo> fastPhoto(@Valid TradeOrderFastPhotoReqVo reqVo) {
//获取交易订单详情
TradeOrderItemDO orderItem = tradeOrderQueryService.getOrderItem(reqVo.getItemId());
//获取产品详情
CommonResult<ProdDO> prodInfo = prodApi.getProdInfo(reqVo.getSpuId());
return success(TradeOrderConvert.INSTANCE.convert(orderItem,prodInfo.getData()));
}
/**
* 服务信息修改记录
*
* @return
*/
@GetMapping("/subTimeLog/{id}")
@PermitAll
// @PreAuthorize("@ss.hasPermission('trade:order:query')")
public CommonResult<List<TradeOrderSubLogDO>> subTimeLog(@PathVariable("id") Long id) {
//获取订单预约时间修改列表
List<TradeOrderSubLogDO> subLogDO = tradeOrderQueryService.getSubTimeLogList(id);
return success(subLogDO);
}
} }

View File

@@ -0,0 +1,15 @@
package com.tashow.cloud.trade.controller.admin.order.vo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class TradeOrderFastPhotoReqVo {
//订单项id
@NotNull(message = "订单详情编号不能为空")
private Long itemId;
//产品id
@NotNull(message = "产品编号不能为空")
private Long spuId;
}

View File

@@ -0,0 +1,20 @@
package com.tashow.cloud.trade.controller.admin.order.vo;
import lombok.Data;
@Data
public class TradeOrderFastPhotoRespVo {
//产品主图
private String pic;
//产品轮播图
private String imgs;
//商品名称
private String spuName;
//商品概述
private String brief;
//sku
private String skuName;
//商品详细描述
private String content;
}

View File

@@ -0,0 +1,12 @@
package com.tashow.cloud.trade.controller.admin.order.vo;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderSubLogDO;
import lombok.Data;
import java.util.List;
@Data
public class TradeOrderSubTimeListRespVo {
private List<TradeOrderSubLogDO> subTimeList;
}

View File

@@ -3,7 +3,6 @@ package com.tashow.cloud.trade.convert.order;
import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tashow.cloud.common.pojo.PageResult; import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.common.util.collection.CollectionUtils; import com.tashow.cloud.common.util.collection.CollectionUtils;
import com.tashow.cloud.common.util.date.LocalDateTimeUtils; import com.tashow.cloud.common.util.date.LocalDateTimeUtils;
@@ -14,6 +13,8 @@ import com.tashow.cloud.memberapi.api.address.dto.MemberAddressRespDTO;
import com.tashow.cloud.memberapi.api.user.dto.MemberUserRespDTO; import com.tashow.cloud.memberapi.api.user.dto.MemberUserRespDTO;
import com.tashow.cloud.payapi.api.order.dto.PayOrderCreateReqDTO; import com.tashow.cloud.payapi.api.order.dto.PayOrderCreateReqDTO;
import com.tashow.cloud.payapi.enums.DictTypeConstants; import com.tashow.cloud.payapi.enums.DictTypeConstants;
import com.tashow.cloud.productapi.api.product.dto.ProdDO;
import com.tashow.cloud.productapi.api.product.vo.prod.ProdRespVO;
import com.tashow.cloud.trade.controller.admin.base.member.user.MemberUserRespVO; import com.tashow.cloud.trade.controller.admin.base.member.user.MemberUserRespVO;
import com.tashow.cloud.trade.controller.admin.order.vo.*; import com.tashow.cloud.trade.controller.admin.order.vo.*;
import com.tashow.cloud.trade.controller.app.order.vo.*; import com.tashow.cloud.trade.controller.app.order.vo.*;
@@ -36,7 +37,6 @@ import com.tashow.cloud.tradeapi.enums.order.TradeOrderStatusEnum;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -107,23 +107,20 @@ public interface TradeOrderConvert {
} }
return orderVO; return orderVO;
} }
// @Mappings(
// @Mapping(target ="items.tradeServeInfo", source = "tradeServeInfo",qualifiedByName = "jsonToMap")
// )
TradeOrderDetailRespVO convert2(TradeOrderDO order, List<TradeOrderItemDO> items, List<TradeOrderLogDO> statusList); TradeOrderDetailRespVO convert2(TradeOrderDO order, List<TradeOrderItemDO> items, List<TradeOrderLogDO> statusList);
@Named("jsonToMap")
default Map<String, Object> jsonToMap(String json) {
try {
return new ObjectMapper().readValue(json, Map.class);
} catch (Exception e) {
throw new RuntimeException("json转换map出错", e);
}
}
//endregion //endregion
//region修改订单
TradeOrderDO convert(TradeOrderRemarkReqVO reqVO);
//endregion
//region 订单快照
TradeOrderFastPhotoRespVo convert(TradeOrderItemDO itemDO, ProdDO prodDO);
//endregion
@Mappings({ @Mappings({
@Mapping(target = "id", ignore = true), @Mapping(target = "id", ignore = true),
@Mapping(source = "userId", target = "userId"), @Mapping(source = "userId", target = "userId"),
@@ -272,7 +269,7 @@ public interface TradeOrderConvert {
TradeOrderDO convert(TradeOrderUpdatePriceReqVO reqVO); TradeOrderDO convert(TradeOrderUpdatePriceReqVO reqVO);
TradeOrderDO convert(TradeOrderRemarkReqVO reqVO);
default BrokerageAddReqBO convert(MemberUserRespDTO user, TradeOrderItemDO item, default BrokerageAddReqBO convert(MemberUserRespDTO user, TradeOrderItemDO item,
ProductSpuRespDTO spu, ProductSkuRespDTO sku) { ProductSpuRespDTO spu, ProductSkuRespDTO sku) {

View File

@@ -0,0 +1,44 @@
package com.tashow.cloud.trade.dal.dataobject.order;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tashow.cloud.mybatis.mybatis.core.dataobject.BaseDO;
import lombok.*;
import java.time.LocalDateTime;
/**
* 订单预约时间修改记录 DO
*
* @author 芋道源码
*/
@TableName("tz_trade_sub_log")
@KeySequence("tz_trade_sub_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TradeOrderSubLogDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 用户编号
*/
private Long userId;
/**
* 订单号
*/
private Long orderId;
/**
* 预约时间
*/
private LocalDateTime subTime;
}

View File

@@ -0,0 +1,15 @@
package com.tashow.cloud.trade.dal.mysql.order;
import com.tashow.cloud.mybatis.mybatis.core.mapper.BaseMapperX;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderSubLogDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 订单预约时间修改记录 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface TradeOrderSubLogMapper extends BaseMapperX<TradeOrderSubLogDO> {
}

View File

@@ -6,6 +6,7 @@ import com.tashow.cloud.payapi.api.order.PayOrderApi;
import com.tashow.cloud.payapi.api.refund.PayRefundApi; import com.tashow.cloud.payapi.api.refund.PayRefundApi;
import com.tashow.cloud.payapi.api.transfer.PayTransferApi; import com.tashow.cloud.payapi.api.transfer.PayTransferApi;
import com.tashow.cloud.payapi.api.wallet.PayWalletApi; import com.tashow.cloud.payapi.api.wallet.PayWalletApi;
import com.tashow.cloud.productapi.api.product.ProdApi;
import com.tashow.cloud.systemapi.api.notify.NotifyMessageSendApi; import com.tashow.cloud.systemapi.api.notify.NotifyMessageSendApi;
import com.tashow.cloud.systemapi.api.social.SocialClientApi; import com.tashow.cloud.systemapi.api.social.SocialClientApi;
import com.tashow.cloud.systemapi.api.social.SocialUserApi; import com.tashow.cloud.systemapi.api.social.SocialUserApi;
@@ -16,6 +17,7 @@ import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@EnableFeignClients(clients = { @EnableFeignClients(clients = {
MemberUserApi.class, MemberAddressApi.class, MemberUserApi.class, MemberAddressApi.class,
ProdApi.class,
PayOrderApi.class, PayRefundApi.class, PayTransferApi.class, PayWalletApi.class, PayOrderApi.class, PayRefundApi.class, PayTransferApi.class, PayWalletApi.class,
AdminUserApi.class, NotifyMessageSendApi.class, SocialClientApi.class, SocialUserApi.class AdminUserApi.class, NotifyMessageSendApi.class, SocialClientApi.class, SocialUserApi.class
}) })

View File

@@ -7,6 +7,7 @@ import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderSummaryRespVO;
import com.tashow.cloud.trade.controller.app.order.vo.AppTradeOrderPageReqVO; import com.tashow.cloud.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderDO; import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderDO;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderItemDO; import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderItemDO;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderSubLogDO;
import com.tashow.cloud.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; import com.tashow.cloud.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import com.tashow.cloud.tradeapi.enums.order.TradeOrderTypeEnum; import com.tashow.cloud.tradeapi.enums.order.TradeOrderTypeEnum;
@@ -157,4 +158,10 @@ public interface TradeOrderQueryService {
*/ */
List<TradeOrderItemDO> getOrderItemListByOrderId(Collection<Long> orderIds); List<TradeOrderItemDO> getOrderItemListByOrderId(Collection<Long> orderIds);
/**
* 获取订单预约时间修改列表
* @param id
* @return
*/
List<TradeOrderSubLogDO> getSubTimeLogList(Long id);
} }

View File

@@ -3,6 +3,7 @@ package com.tashow.cloud.trade.service.order;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil; import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tashow.cloud.common.pojo.PageResult; import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderPageReqVO; import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderPageReqVO;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderSummaryRespVO; import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderSummaryRespVO;
@@ -10,8 +11,10 @@ import com.tashow.cloud.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
import com.tashow.cloud.trade.dal.dataobject.delivery.DeliveryExpressDO; import com.tashow.cloud.trade.dal.dataobject.delivery.DeliveryExpressDO;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderDO; import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderDO;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderItemDO; import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderItemDO;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderSubLogDO;
import com.tashow.cloud.trade.dal.mysql.order.TradeOrderItemMapper; import com.tashow.cloud.trade.dal.mysql.order.TradeOrderItemMapper;
import com.tashow.cloud.trade.dal.mysql.order.TradeOrderMapper; import com.tashow.cloud.trade.dal.mysql.order.TradeOrderMapper;
import com.tashow.cloud.trade.dal.mysql.order.TradeOrderSubLogMapper;
import com.tashow.cloud.trade.dal.redis.RedisKeyConstants; import com.tashow.cloud.trade.dal.redis.RedisKeyConstants;
import com.tashow.cloud.trade.framework.delivery.core.client.ExpressClientFactory; import com.tashow.cloud.trade.framework.delivery.core.client.ExpressClientFactory;
import com.tashow.cloud.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO; import com.tashow.cloud.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
@@ -46,6 +49,8 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
private TradeOrderMapper tradeOrderMapper; private TradeOrderMapper tradeOrderMapper;
@Resource @Resource
private TradeOrderItemMapper tradeOrderItemMapper; private TradeOrderItemMapper tradeOrderItemMapper;
@Resource
private TradeOrderSubLogMapper tradeOrderSubLogMapper;
@Resource @Resource
private DeliveryExpressService deliveryExpressService; private DeliveryExpressService deliveryExpressService;
@@ -238,4 +243,8 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
return SpringUtil.getBean(getClass()); return SpringUtil.getBean(getClass());
} }
@Override
public List<TradeOrderSubLogDO> getSubTimeLogList(Long id) {
return tradeOrderSubLogMapper.selectList(new LambdaQueryWrapper<TradeOrderSubLogDO>().eq(TradeOrderSubLogDO::getOrderId,id));
}
} }

View File

@@ -0,0 +1,14 @@
package com.tashow.cloud.trade.service.order;
import com.baomidou.mybatisplus.extension.service.IService;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderSubLogDO;
/**
* 订单预约时间修改记录 Service 接口
*
* @author 芋道源码
*/
public interface TradeOrderSubLogService extends IService<TradeOrderSubLogDO> {
}

View File

@@ -0,0 +1,20 @@
package com.tashow.cloud.trade.service.order;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderSubLogDO;
import com.tashow.cloud.trade.dal.mysql.order.TradeOrderSubLogMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
/**
* 订单预约时间修改记录 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class TradeOrderSubLogServiceImpl extends ServiceImpl<TradeOrderSubLogMapper, TradeOrderSubLogDO> implements TradeOrderSubLogService {
}

View File

@@ -41,6 +41,19 @@ public interface TradeOrderUpdateService {
*/ */
TradeOrderDO createOrder(Long userId, AppTradeOrderCreateReqVO createReqVO); TradeOrderDO createOrder(Long userId, AppTradeOrderCreateReqVO createReqVO);
/**
* 确认接单
* @param id
*/
void acceptConfirmOrderByAdmin(Long id);
/**
* 服务上报
* @param id
*/
void reportServeOrderByAdmin(Long id);
/** /**
* 更新交易订单已支付 * 更新交易订单已支付
* *
@@ -89,6 +102,12 @@ public interface TradeOrderUpdateService {
* @param id 订单编号 * @param id 订单编号
*/ */
void cancelOrderByMember(Long userId, Long id); void cancelOrderByMember(Long userId, Long id);
/**
* 【管理员】取消交易订单
*
* @param id 订单编号
*/
boolean cancelOrderByAdmin(Long id);
/** /**
* 【系统】自动取消订单 * 【系统】自动取消订单
@@ -218,4 +237,5 @@ public interface TradeOrderUpdateService {
*/ */
void updateOrderGiveCouponIds(Long userId, Long orderId, List<Long> giveCouponIds); void updateOrderGiveCouponIds(Long userId, Long orderId, List<Long> giveCouponIds);
} }

View File

@@ -246,6 +246,26 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
order.setPayOrderId(payOrderId); order.setPayOrderId(payOrderId);
} }
@Override
public void acceptConfirmOrderByAdmin(Long id) {
// 1.1 校验订单是否存在
TradeOrderDO order = validateOrderExists(id);
order.setOrderStatus(TradeOrderStatusEnum.WAITSERVE.getStatus());
tradeOrderMapper.updateById(order);
}
@Override
public void reportServeOrderByAdmin(Long id) {
// 1.1 校验订单是否存在
TradeOrderDO order = validateOrderExists(id);
if (!TradeOrderStatusEnum.isWaitAccept(order.getOrderStatus())){
throw exception(ORDER_UPDATE_UNWAITACCEPT_FAIL);
}
order.setFinishTime(LocalDateTime.now());
tradeOrderMapper.updateById(order);
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_PAY) @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_PAY)
@@ -516,14 +536,33 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
throw exception(ORDER_NOT_FOUND); throw exception(ORDER_NOT_FOUND);
} }
// 1.2 校验状态 // 1.2 校验状态
// if (ObjectUtil.notEqual(order.getOrderStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) { if (ObjectUtil.notEqual(order.getOrderStatus(), TradeOrderStatusEnum.WAITPAID.getStatus())) {
// throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
// } }
// 2. 取消订单 // 2. 取消订单
cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL); cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL);
} }
@Override
@Transactional(rollbackFor = Exception.class)
@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_CANCEL)
public boolean cancelOrderByAdmin(Long id) {
// 1.1 校验存在
TradeOrderDO order = tradeOrderMapper.selectById(id);
if (order == null) {
throw exception(ORDER_NOT_FOUND);
}
// 1.2 校验状态
if (ObjectUtil.notEqual(order.getOrderStatus(), TradeOrderStatusEnum.WAITPAID.getStatus())) {
throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
}
// 2. 取消订单
cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL);
return true;
}
@Override @Override
public int cancelOrderBySystem() { public int cancelOrderBySystem() {
// 1. 查询过期的待支付订单 // 1. 查询过期的待支付订单

View File

@@ -8,7 +8,7 @@
<version>${revision}</version> <version>${revision}</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>tashow-module-member</artifactId> <artifactId>tashow-module-user</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>

View File

@@ -1,4 +1,4 @@
package com.tashow.cloud.member; package com.tashow.cloud.user;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -7,10 +7,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
* 项目的启动类 * 项目的启动类
*/ */
@SpringBootApplication @SpringBootApplication
public class MemberServerApplication { public class UserServerApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(MemberServerApplication.class, args); SpringApplication.run(UserServerApplication.class, args);
} }
} }

View File

@@ -0,0 +1 @@
package com.tashow.cloud.user.controller.admin;

View File

@@ -1,25 +1,20 @@
package com.tashow.cloud.member.controller.admin.user; package com.tashow.cloud.user.controller.admin.user;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import com.tashow.cloud.common.pojo.CommonResult; import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageResult; import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.member.controller.admin.user.vo.MemberUserPageReqVO; import com.tashow.cloud.user.controller.admin.user.vo.UserLoginPageReqVO;
import com.tashow.cloud.member.controller.admin.user.vo.MemberUserRespVO; import com.tashow.cloud.user.controller.admin.user.vo.UserLoginRespVO;
import com.tashow.cloud.member.controller.admin.user.vo.MemberUserUpdateReqVO; import com.tashow.cloud.user.controller.admin.user.vo.MemberUserUpdateReqVO;
import com.tashow.cloud.member.convert.user.MemberUserConvert; import com.tashow.cloud.user.convert.user.MemberUserConvert;
import com.tashow.cloud.member.dal.dataobject.user.MemberUserDO; import com.tashow.cloud.user.dal.dataobject.user.UserLoginDO;
import com.tashow.cloud.member.service.user.MemberUserService; import com.tashow.cloud.user.service.user.UserLoginService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static com.tashow.cloud.common.pojo.CommonResult.success; import static com.tashow.cloud.common.pojo.CommonResult.success;
@@ -27,45 +22,38 @@ import static com.tashow.cloud.common.pojo.CommonResult.success;
@RestController @RestController
@RequestMapping("/member/user") @RequestMapping("/member/user")
@Validated @Validated
public class MemberUserController { public class UserLoginController {
@Resource @Resource
private MemberUserService memberUserService; private UserLoginService loginUserService;
@Resource
@PutMapping("/update")
// 更新会员用户 // 更新会员用户
@PutMapping("/update")
@PreAuthorize("@ss.hasPermission('member:user:update')") @PreAuthorize("@ss.hasPermission('member:user:update')")
public CommonResult<Boolean> updateUser(@Valid @RequestBody MemberUserUpdateReqVO updateReqVO) { public CommonResult<Boolean> updateUser(@Valid @RequestBody MemberUserUpdateReqVO updateReqVO) {
memberUserService.updateUser(updateReqVO); loginUserService.updateUser(updateReqVO);
return success(true); return success(true);
} }
@GetMapping("/get")
// 获得会员用户 // 获得会员用户
// id: 编号必填示例1024 // id: 编号必填示例1024
@GetMapping("/get")
@PreAuthorize("@ss.hasPermission('member:user:query')") @PreAuthorize("@ss.hasPermission('member:user:query')")
public CommonResult<MemberUserRespVO> getUser(@RequestParam("id") Long id) { public CommonResult<UserLoginRespVO> getUser(@RequestParam("id") Long id) {
MemberUserDO user = memberUserService.getUser(id); UserLoginDO user = loginUserService.getUser(id);
return success(MemberUserConvert.INSTANCE.convert03(user)); return success(MemberUserConvert.INSTANCE.convert03(user));
} }
@GetMapping("/page")
// 获得会员用户分页 // 获得会员用户分页
@GetMapping("/page")
@PreAuthorize("@ss.hasPermission('member:user:query')") @PreAuthorize("@ss.hasPermission('member:user:query')")
public CommonResult<PageResult<MemberUserRespVO>> getUserPage(@Valid MemberUserPageReqVO pageVO) { public CommonResult<PageResult<UserLoginRespVO>> getUserPage(@Valid UserLoginPageReqVO pageVO) {
PageResult<MemberUserDO> pageResult = memberUserService.getUserPage(pageVO); PageResult<UserLoginDO> pageResult = loginUserService.getUserPage(pageVO);
if (CollUtil.isEmpty(pageResult.getList())) { if (CollUtil.isEmpty(pageResult.getList())) {
return success(PageResult.empty()); return success(PageResult.empty());
} }
// 处理用户标签返显
Set<Long> tagIds = pageResult.getList().stream()
.map(MemberUserDO::getTagIds)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.collect(Collectors.toSet());
return success(MemberUserConvert.INSTANCE.convertPage(pageResult)); return success(MemberUserConvert.INSTANCE.convertPage(pageResult));
} }

View File

@@ -1,4 +1,4 @@
package com.tashow.cloud.member.controller.admin.user.vo; package com.tashow.cloud.user.controller.admin.user.vo;
import lombok.Data; import lombok.Data;
import lombok.ToString; import lombok.ToString;

View File

@@ -1,4 +1,4 @@
package com.tashow.cloud.member.controller.admin.user.vo; package com.tashow.cloud.user.controller.admin.user.vo;
import lombok.Data; import lombok.Data;
import lombok.ToString; import lombok.ToString;

View File

@@ -1,4 +1,4 @@
package com.tashow.cloud.member.controller.admin.user.vo; package com.tashow.cloud.user.controller.admin.user.vo;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@@ -10,7 +10,7 @@ import jakarta.validation.constraints.NotNull;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class MemberUserUpdateReqVO extends MemberUserBaseVO { public class MemberUserUpdateReqVO extends UserBaseVO {
// 编号必填示例23788 // 编号必填示例23788
@NotNull(message = "编号不能为空") @NotNull(message = "编号不能为空")

View File

@@ -0,0 +1,34 @@
package com.tashow.cloud.user.controller.admin.user.vo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.hibernate.validator.constraints.URL;
/**
* 会员用户 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class UserBaseVO {
// 手机号必填示例15601691300
@NotNull(message = "手机号不能为空")
private String mobile;
// 状态必填示例2
@NotNull(message = "状态不能为空")
private Byte status;
// 用户昵称,必填,示例:李四
@NotNull(message = "用户昵称不能为空")
private String nickname;
// 头像必填示例https://www.iocoder.cn/x.png
@URL(message = "头像必须是 URL 格式")
private String avatar;
// 备注,示例:我是小备注
private String remark;
}

View File

@@ -0,0 +1,33 @@
package com.tashow.cloud.user.controller.admin.user.vo;
import com.tashow.cloud.common.pojo.PageParam;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
// 管理后台 - 会员用户分页 Request VO
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class UserLoginPageReqVO extends PageParam {
// 搜索条件 手机号,昵称,姓名
private String searchField;
// 会员等级编号示例1
private Long levelId;
// 注册渠道
private Integer registerTerminal;
// 注册时间
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] registDate;
}

View File

@@ -0,0 +1,29 @@
package com.tashow.cloud.user.controller.admin.user.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
// 管理后台 - 会员用户 Response VO
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class UserLoginRespVO extends UserBaseVO {
// 编号必填示例23788
private Long id;
// 会员类型
private Integer memberType;
// 注册渠道
private Integer registerTerminal;
// 注册渠道
private LocalDateTime registerTime;
// 最后登录时间,必填
private LocalDateTime loginDate;
}

View File

@@ -1,15 +1,15 @@
package com.tashow.cloud.member.controller.app.auth; package com.tashow.cloud.user.controller.app.auth;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.tashow.cloud.common.enums.UserTypeEnum; import com.tashow.cloud.common.enums.UserTypeEnum;
import com.tashow.cloud.common.pojo.CommonResult; import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.member.controller.app.auth.vo.*;
import com.tashow.cloud.member.convert.auth.AuthConvert;
import com.tashow.cloud.member.service.auth.MemberAuthService;
import com.tashow.cloud.security.security.config.SecurityProperties; import com.tashow.cloud.security.security.config.SecurityProperties;
import com.tashow.cloud.security.security.core.util.SecurityFrameworkUtils; import com.tashow.cloud.security.security.core.util.SecurityFrameworkUtils;
import com.tashow.cloud.systemapi.api.social.SocialClientApi; import com.tashow.cloud.systemapi.api.social.SocialClientApi;
import com.tashow.cloud.systemapi.api.social.dto.SocialWxJsapiSignatureRespDTO; import com.tashow.cloud.systemapi.api.social.dto.SocialWxJsapiSignatureRespDTO;
import com.tashow.cloud.user.controller.app.auth.vo.*;
import com.tashow.cloud.user.convert.auth.AuthConvert;
import com.tashow.cloud.user.service.auth.MemberAuthService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll; import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;

View File

@@ -1,4 +1,4 @@
package com.tashow.cloud.member.controller.app.auth.vo; package com.tashow.cloud.user.controller.app.auth.vo;
import com.tashow.cloud.common.validation.InEnum; import com.tashow.cloud.common.validation.InEnum;
import com.tashow.cloud.common.validation.Mobile; import com.tashow.cloud.common.validation.Mobile;

View File

@@ -1,4 +1,4 @@
package com.tashow.cloud.member.controller.app.auth.vo; package com.tashow.cloud.user.controller.app.auth.vo;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.tashow.cloud.common.validation.InEnum; import com.tashow.cloud.common.validation.InEnum;

View File

@@ -1,4 +1,4 @@
package com.tashow.cloud.member.controller.app.auth.vo; package com.tashow.cloud.user.controller.app.auth.vo;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;

View File

@@ -1,4 +1,4 @@
package com.tashow.cloud.member.controller.app.auth.vo; package com.tashow.cloud.user.controller.app.auth.vo;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.tashow.cloud.common.validation.InEnum; import com.tashow.cloud.common.validation.InEnum;

View File

@@ -1,4 +1,4 @@
package com.tashow.cloud.member.controller.app.auth.vo; package com.tashow.cloud.user.controller.app.auth.vo;
import com.tashow.cloud.common.validation.InEnum; import com.tashow.cloud.common.validation.InEnum;
import com.tashow.cloud.common.validation.Mobile; import com.tashow.cloud.common.validation.Mobile;

Some files were not shown because too many files have changed in this diff Show More