!208 合并部分小程序 0.000000000000000000000000000001 版本

Merge pull request !208 from 芋道源码/feature/1.8.0-uniapp
This commit is contained in:
芋道源码 2022-07-05 14:02:34 +00:00 committed by Gitee
commit 0d06c7fe8b
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
752 changed files with 19470 additions and 17316 deletions

View File

@ -18,6 +18,7 @@
<module>yudao-module-system</module> <module>yudao-module-system</module>
<module>yudao-module-infra</module> <module>yudao-module-infra</module>
<module>yudao-module-pay</module> <module>yudao-module-pay</module>
<module>yudao-module-mall</module>
</modules> </modules>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>

287
sql/mall.sql Normal file
View File

@ -0,0 +1,287 @@
/*
Navicat Premium Data Transfer
Source Server : 127.0.0.1
Source Server Type : MySQL
Source Server Version : 80026
Source Host : localhost:3306
Source Schema : ruoyi-vue-pro
Target Server Type : MySQL
Target Server Version : 80026
File Encoding : 65001
Date: 05/02/2022 00:50:30
*/
SET
FOREIGN_KEY_CHECKS = 0;
SET NAMES utf8mb4;
-- ----------------------------
-- Table structure for product_category
-- ----------------------------
DROP TABLE IF EXISTS `product_category`;
CREATE TABLE `product_category`
(
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类编号',
`parent_id` bigint NOT NULL COMMENT '父分类编号',
`name` varchar(255) NOT NULL COMMENT '分类名称',
`icon` varchar(100) NOT NULL DEFAULT '#' COMMENT '分类图标',
`banner_url` varchar(255) NOT NULL COMMENT '分类图片',
`sort` int DEFAULT '0' COMMENT '分类排序',
`description` varchar(1024) DEFAULT NULL COMMENT '分类描述',
`status` tinyint NOT NULL COMMENT '开启状态',
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB COMMENT='商品分类';
-- ----------------------------
-- Table structure for product_brand
-- ----------------------------
DROP TABLE IF EXISTS `product_brand`;
CREATE TABLE `product_brand`
(
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '品牌编号',
`category_id` bigint NOT NULL COMMENT '分类编号',
`name` varchar(255) NOT NULL COMMENT '品牌名称',
`banner_url` varchar(255) NOT NULL COMMENT '品牌图片',
`sort` int DEFAULT '0' COMMENT '品牌排序',
`description` varchar(1024) DEFAULT NULL COMMENT '品牌描述',
`status` tinyint NOT NULL COMMENT '状态',
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB COMMENT='品牌';
-- TODO 父级菜单的 id 处理: 2000 2001
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES (2000, '商城', '', 1, 1, 0, '/mall', 'merchant', NULL, 0);
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES (2001, '商品', '', 1, 1, 2000, 'product', 'dict', NULL, 0);
-- 商品分类 菜单 SQL
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('分类管理', '', 2, 0, 2001, 'category', '', 'mall/product/category/index', 0);
-- 按钮父菜单ID
SELECT @parentId := LAST_INSERT_ID();
-- 按钮 SQL
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('分类查询', 'product:category:query', 3, 1, @parentId, '', '', '', 0);
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('分类创建', 'product:category:create', 3, 2, @parentId, '', '', '', 0);
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('分类更新', 'product:category:update', 3, 3, @parentId, '', '', '', 0);
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('分类删除', 'product:category:delete', 3, 4, @parentId, '', '', '', 0);
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('分类导出', 'product:category:export', 3, 5, @parentId, '', '', '', 0);
-- 品牌管理 菜单 SQL
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('品牌管理', '', 2, 1, 2001, 'brand', '', 'mall/product/brand/index', 0);
-- 按钮父菜单ID
SELECT @parentId := LAST_INSERT_ID();
-- 按钮 SQL
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('品牌查询', 'product:brand:query', 3, 1, @parentId, '', '', '', 0);
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('品牌创建', 'product:brand:create', 3, 2, @parentId, '', '', '', 0);
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('品牌更新', 'product:brand:update', 3, 3, @parentId, '', '', '', 0);
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('品牌删除', 'product:brand:delete', 3, 4, @parentId, '', '', '', 0);
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('品牌导出', 'product:brand:export', 3, 5, @parentId, '', '', '', 0);
-- ----------------------------
-- Table structure for market_activity
-- ----------------------------
DROP TABLE IF EXISTS `market_activity`;
CREATE TABLE `market_activity`
(
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '活动编号',
`title` varchar(50) NOT NULL DEFAULT '' COMMENT '活动标题',
`activity_type` tinyint(4) NOT NULL COMMENT '活动类型',
`status` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '活动状态',
`start_time` datetime NOT NULL COMMENT '开始时间',
`end_time` datetime NOT NULL COMMENT '结束时间',
`invalid_time` datetime DEFAULT NULL COMMENT '失效时间',
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`time_limited_discount` varchar(2000) DEFAULT NULL COMMENT '限制折扣字符串使用 JSON 序列化成字符串存储',
`full_privilege` varchar(2000) DEFAULT NULL COMMENT '限制折扣字符串使用 JSON 序列化成字符串存储',
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='促销活动';
-- 规格菜单 SQL
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('规格管理', '', 2, 3, 2001, 'property', '', 'mall/product/property/index', 0);
-- 按钮父菜单ID
SELECT @parentId := LAST_INSERT_ID();
-- 按钮 SQL
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('规格查询', 'product:property:query', 3, 1, @parentId, '', '', '', 0);
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('规格创建', 'product:property:create', 3, 2, @parentId, '', '', '', 0);
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('规格更新', 'product:property:update', 3, 3, @parentId, '', '', '', 0);
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('规格删除', 'product:property:delete', 3, 4, @parentId, '', '', '', 0);
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('规格导出', 'product:property:export', 3, 5, @parentId, '', '', '', 0);
-- 商品菜单 SQL
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('商品管理', '', 2, 2, 2001, 'spu', '', 'mall/product/spu/index', 0);
-- 按钮父菜单ID
SELECT @parentId := LAST_INSERT_ID();
-- 按钮 SQL
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('商品查询', 'product:spu:query', 3, 1, @parentId, '', '', '', 0);
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('商品创建', 'product:spu:create', 3, 2, @parentId, '', '', '', 0);
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('商品更新', 'product:spu:update', 3, 3, @parentId, '', '', '', 0);
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('商品删除', 'product:spu:delete', 3, 4, @parentId, '', '', '', 0);
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('商品导出', 'product:spu:export', 3, 5, @parentId, '', '', '', 0);
-- 规格名称表
drop table if exists product_property;
create table product_property
(
id bigint NOT NULL AUTO_INCREMENT comment '主键',
name varchar(64) comment '规格名称',
status tinyint comment '状态 0 开启 1 禁用',
create_time datetime default current_timestamp comment '创建时间',
update_time datetime default current_timestamp on update current_timestamp comment '更新时间',
creator varchar(64) comment '创建人',
updater varchar(64) comment '更新人',
tenant_id bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
deleted bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
primary key (id),
key idx_name ( name (32)) comment '规格名称索引'
) comment '规格名称' character set utf8mb4
collate utf8mb4_general_ci;
-- 规格值表
drop table if exists product_property_value;
create table product_property_value
(
id bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
property_id bigint comment '规格键id',
name varchar(128) comment '规格值名字',
status tinyint comment '状态 1 开启 2 禁用',
create_time datetime default current_timestamp comment '创建时间',
update_time datetime default current_timestamp on update current_timestamp comment '更新时间',
creator varchar(64) comment '创建人',
updater varchar(64) comment '更新人',
tenant_id bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
deleted bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
primary key (id)
) comment '规格值' character set utf8mb4
collate utf8mb4_general_ci;
-- spu
drop table if exists product_spu;
create table product_spu
(
id bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
name varchar(128) comment '商品名称',
sell_point varchar(128) not null comment '卖点',
description text not null comment '描述',
category_id bigint not null comment '分类id',
pic_urls varchar(1024) not null default '' comment '商品主图地址\n *\n * 数组以逗号分隔\n 最多上传15张',
sort int not null default 0 comment '排序字段',
like_count int comment '点赞初始人数',
price int comment '价格 单位使用',
quantity int comment '库存数量',
status bit(1) comment '上下架状态 0 上架开启 1 下架禁用',
create_time datetime default current_timestamp comment '创建时间',
update_time datetime default current_timestamp on update current_timestamp comment '更新时间',
creator varchar(64) comment '创建人',
updater varchar(64) comment '更新人',
tenant_id bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
deleted bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
primary key (id)
) comment '商品spu' character set utf8mb4
collate utf8mb4_general_ci;
-- sku
drop table if exists product_sku;
create table product_sku
(
id bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
spu_id bigint not null comment 'spu编号',
properties varchar(64) not null comment '规格值数组-json格式 [{propertId: , valueId: }, {propertId: , valueId: }]',
price int not null DEFAULT -1 comment '销售价格单位',
original_price int not null DEFAULT -1 comment '原价 单位 ',
cost_price int not null DEFAULT -1 comment '成本价单位 ',
bar_code varchar(64) not null comment '条形码',
pic_url VARCHAR(128) not null comment '图片地址',
status tinyint comment '状态 0-正常 1-禁用',
create_time datetime default current_timestamp comment '创建时间',
update_time datetime default current_timestamp on update current_timestamp comment '更新时间',
creator varchar(64) comment '创建人',
updater varchar(64) comment '更新人',
tenant_id bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
deleted bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
primary key (id)
) comment '商品sku' character set utf8mb4
collate utf8mb4_general_ci;
---Market-Banner管理SQL
drop table if exists market_banner;
CREATE TABLE `market_banner` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Banner编号',
`title` varchar(64) NOT NULL DEFAULT '' COMMENT 'Banner标题',
`pic_url` varchar(255) NOT NULL COMMENT '图片URL',
`status` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '活动状态',
`url` varchar(255) NOT NULL COMMENT '跳转地址',
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '租户编号',
`sort` tinyint(4) DEFAULT NULL COMMENT '排序',
`memo` varchar(255) DEFAULT NULL COMMENT '描述',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='Banner管理';
-- 菜单 SQL
INSERT INTO `system_menu`(`id`,`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES (2002, 'Banner管理', '', 2, 1, 2000, 'brand', '', 'mall/market/banner/index', 0);
-- 按钮父菜单ID
SELECT @parentId := LAST_INSERT_ID();
-- 按钮 SQL
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('Banner查询', 'market:banner:query', 3, 1, @parentId, '', '', '', 0);
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('Banner创建', 'market:banner:create', 3, 2, @parentId, '', '', '', 0);
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('Banner更新', 'market:banner:update', 3, 3, @parentId, '', '', '', 0);
INSERT INTO `system_menu`(`name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`)
VALUES ('Banner删除', 'market:banner:delete', 3, 4, @parentId, '', '', '', 0);

View File

@ -1,8 +1,11 @@
package cn.iocoder.yudao.framework.common.enums; package cn.iocoder.yudao.framework.common.enums;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import java.util.Arrays;
/** /**
* 通用状态枚举 * 通用状态枚举
* *
@ -10,11 +13,14 @@ import lombok.Getter;
*/ */
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum CommonStatusEnum { public enum CommonStatusEnum implements IntArrayValuable {
ENABLE(0, "开启"), ENABLE(0, "开启"),
DISABLE(1, "关闭"); DISABLE(1, "关闭");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CommonStatusEnum::getStatus).toArray();
/** /**
* 状态值 * 状态值
*/ */
@ -24,4 +30,9 @@ public enum CommonStatusEnum {
*/ */
private final String name; private final String name;
@Override
public int[] array() {
return ARRAYS;
}
} }

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.framework.social.config; package cn.iocoder.yudao.framework.social.config;
import cn.hutool.core.util.ReflectUtil;
import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory; import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;
import com.xkcoding.http.HttpUtil; import com.xkcoding.http.HttpUtil;
import com.xkcoding.http.support.hutool.HutoolImpl; import com.xkcoding.http.support.hutool.HutoolImpl;
@ -11,6 +10,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/** /**
* 社交自动装配类 * 社交自动装配类
@ -24,6 +24,7 @@ import org.springframework.context.annotation.Configuration;
public class YudaoSocialAutoConfiguration { public class YudaoSocialAutoConfiguration {
@Bean @Bean
@Primary
@ConditionalOnProperty(prefix = "justauth", value = "enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnProperty(prefix = "justauth", value = "enabled", havingValue = "true", matchIfMissing = true)
public YudaoAuthRequestFactory yudaoAuthRequestFactory(JustAuthProperties properties, AuthStateCache authStateCache) { public YudaoAuthRequestFactory yudaoAuthRequestFactory(JustAuthProperties properties, AuthStateCache authStateCache) {
// 需要修改 HttpUtil 使用的实现避免类报错 // 需要修改 HttpUtil 使用的实现避免类报错

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.social.core;
import cn.hutool.core.util.EnumUtil; import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.ReflectUtil;
import cn.iocoder.yudao.framework.social.core.enums.AuthExtendSource; import cn.iocoder.yudao.framework.social.core.enums.AuthExtendSource;
import cn.iocoder.yudao.framework.social.core.request.AuthWeChatMiniProgramRequest; import cn.iocoder.yudao.framework.social.core.request.AuthWeChatMiniAppRequest;
import com.xkcoding.justauth.AuthRequestFactory; import com.xkcoding.justauth.AuthRequestFactory;
import com.xkcoding.justauth.autoconfigure.JustAuthProperties; import com.xkcoding.justauth.autoconfigure.JustAuthProperties;
import me.zhyd.oauth.cache.AuthStateCache; import me.zhyd.oauth.cache.AuthStateCache;
@ -20,7 +20,6 @@ import java.lang.reflect.Method;
* @author timfruit * @author timfruit
* @date 2021-10-31 * @date 2021-10-31
*/ */
// TODO @timfruit单测
public class YudaoAuthRequestFactory extends AuthRequestFactory { public class YudaoAuthRequestFactory extends AuthRequestFactory {
protected JustAuthProperties properties; protected JustAuthProperties properties;
@ -69,15 +68,14 @@ public class YudaoAuthRequestFactory extends AuthRequestFactory {
if (config == null) { if (config == null) {
return null; return null;
} }
// 配置 http config // 反射调用配置 http config
ReflectUtil.invoke(this, configureHttpConfigMethod, ReflectUtil.invoke(this, configureHttpConfigMethod, authExtendSource.name(), config, properties.getHttpConfig());
authExtendSource.name(), config, properties.getHttpConfig());
// 获得拓展的 Request // 获得拓展的 Request
// noinspection SwitchStatementWithTooFewBranches // noinspection SwitchStatementWithTooFewBranches
switch (authExtendSource) { switch (authExtendSource) {
case WECHAT_MINI_PROGRAM: case WECHAT_MINI_APP:
return new AuthWeChatMiniProgramRequest(config, authStateCache); return new AuthWeChatMiniAppRequest(config, authStateCache);
default: default:
return null; return null;
} }

View File

@ -14,25 +14,25 @@ public enum AuthExtendSource implements AuthSource {
/** /**
* 微信小程序授权登录 * 微信小程序授权登录
*/ */
WECHAT_MINI_PROGRAM { WECHAT_MINI_APP {
@Override @Override
public String authorize() { public String authorize() {
// https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html // 参见 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html 文档
throw new UnsupportedOperationException("不支持获取授权url, 请使用小程序内置函数wx.login()登录获取code"); throw new UnsupportedOperationException("不支持获取授权 url请使用小程序内置函数 wx.login() 登录获取 code");
} }
@Override @Override
public String accessToken() { public String accessToken() {
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html // 参见 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html 文档
// 获取openid, unionid , session_key // 获取 openid, unionId , session_key 等字段
return "https://api.weixin.qq.com/sns/jscode2session"; return "https://api.weixin.qq.com/sns/jscode2session";
} }
@Override @Override
public String userInfo() { public String userInfo() {
//https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html // 参见 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html 文档
throw new UnsupportedOperationException("不支持获取用户信息url, 请使用小程序内置函数wx.getUserProfile()获取用户信息"); throw new UnsupportedOperationException("不支持获取用户信息 url请使用小程序内置函数 wx.getUserProfile() 获取用户信息");
} }
} }

View File

@ -1,23 +0,0 @@
package cn.iocoder.yudao.framework.social.core.model;
import lombok.*;
import me.zhyd.oauth.model.AuthToken;
/**
* 授权所需的 token 拓展类
*
* @author timfruit
* @date 2021-10-29
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class AuthExtendToken extends AuthToken {
/**
* 微信小程序 - 会话密钥
*/
private String miniSessionKey;
}

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.framework.social.core.request;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.social.core.enums.AuthExtendSource; import cn.iocoder.yudao.framework.social.core.enums.AuthExtendSource;
import cn.iocoder.yudao.framework.social.core.model.AuthExtendToken;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data; import lombok.Data;
import me.zhyd.oauth.cache.AuthStateCache; import me.zhyd.oauth.cache.AuthStateCache;
@ -16,45 +15,43 @@ import me.zhyd.oauth.utils.HttpUtils;
import me.zhyd.oauth.utils.UrlBuilder; import me.zhyd.oauth.utils.UrlBuilder;
/** /**
* 微信小程序登陆 * 微信小程序登陆 Request 请求
*
* 由于 JustAuth 定位是面向 Web 为主的三方登录所以微信小程序只能自己封装
* *
* @author timfruit * @author timfruit
* @date 2021-10-29 * @date 2021-10-29
*/ */
public class AuthWeChatMiniProgramRequest extends AuthDefaultRequest { public class AuthWeChatMiniAppRequest extends AuthDefaultRequest {
public AuthWeChatMiniProgramRequest(AuthConfig config) { public AuthWeChatMiniAppRequest(AuthConfig config, AuthStateCache authStateCache) {
super(config, AuthExtendSource.WECHAT_MINI_PROGRAM); super(config, AuthExtendSource.WECHAT_MINI_APP, authStateCache);
}
public AuthWeChatMiniProgramRequest(AuthConfig config, AuthStateCache authStateCache) {
super(config, AuthExtendSource.WECHAT_MINI_PROGRAM, authStateCache);
} }
@Override @Override
protected AuthToken getAccessToken(AuthCallback authCallback) { protected AuthToken getAccessToken(AuthCallback authCallback) {
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html // 参见 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html 文档
// 使用 code 获取对应的 openIdunionId 等字段
String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl(authCallback.getCode())); String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl(authCallback.getCode()));
CodeSessionResponse accessTokenObject = JsonUtils.parseObject(response, CodeSessionResponse.class); JSCode2SessionResponse accessTokenObject = JsonUtils.parseObject(response, JSCode2SessionResponse.class);
assert accessTokenObject != null;
this.checkResponse(accessTokenObject); checkResponse(accessTokenObject);
// 拼装结果
AuthExtendToken token = new AuthExtendToken(); return AuthToken.builder()
token.setMiniSessionKey(accessTokenObject.sessionKey); .openId(accessTokenObject.getOpenid())
token.setOpenId(accessTokenObject.openid); .unionId(accessTokenObject.getUnionId())
token.setUnionId(accessTokenObject.unionid); .build();
return token;
} }
@Override @Override
protected AuthUser getUserInfo(AuthToken authToken) { protected AuthUser getUserInfo(AuthToken authToken) {
// https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html // 参见 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html 文档
// 如果需要用户信息需要在小程序调用函数后传给后端 // 如果需要用户信息需要在小程序调用函数后传给后端
return AuthUser.builder() return AuthUser.builder()
.uuid(authToken.getOpenId()) .username("")
//TODO 是使用默认值还是有小程序获取用户信息 code 一起传过来
.nickname("") .nickname("")
.avatar("") .avatar("")
.uuid(authToken.getOpenId())
.token(authToken) .token(authToken)
.source(source.toString()) .source(source.toString())
.build(); .build();
@ -63,38 +60,38 @@ public class AuthWeChatMiniProgramRequest extends AuthDefaultRequest {
/** /**
* 检查响应内容是否正确 * 检查响应内容是否正确
* *
* @param object 请求响应内容 * @param response 请求响应内容
*/ */
private void checkResponse(CodeSessionResponse object) { private void checkResponse(JSCode2SessionResponse response) {
if (object.errcode != 0) { if (response.getErrorCode() != 0) {
throw new AuthException(object.errcode, object.errmsg); throw new AuthException(response.getErrorCode(), response.getErrorMsg());
} }
} }
/**
* 返回获取 accessToken url
*
* @param code 授权码
* @return 返回获取 accessToken url
*/
@Override @Override
protected String accessTokenUrl(String code) { protected String accessTokenUrl(String code) {
return UrlBuilder.fromBaseUrl(source.accessToken()) return UrlBuilder.fromBaseUrl(source.accessToken())
.queryParam("appid", config.getClientId()) .queryParam("appid", config.getClientId())
.queryParam("secret", config.getClientSecret()) .queryParam("secret", config.getClientSecret())
.queryParam("js_code", code) .queryParam("js_code", code) // 和父类不同所以需要重写该方法
.queryParam("grant_type", "authorization_code") .queryParam("grant_type", "authorization_code")
.build(); .build();
} }
@Data @Data
private static class CodeSessionResponse { @SuppressWarnings("SpellCheckingInspection")
private int errcode; private static class JSCode2SessionResponse {
private String errmsg;
@JsonProperty("errcode")
private int errorCode;
@JsonProperty("errmsg")
private String errorMsg;
@JsonProperty("session_key") @JsonProperty("session_key")
private String sessionKey; private String sessionKey;
private String openid; private String openid;
private String unionid; @JsonProperty("unionid")
private String unionId;
} }
} }

View File

@ -33,9 +33,13 @@
<!-- 三方云服务相关 --> <!-- 三方云服务相关 -->
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<!-- <artifactId>weixin-java-mp</artifactId>-->
<artifactId>wx-java-mp-spring-boot-starter</artifactId> <artifactId>wx-java-mp-spring-boot-starter</artifactId>
<version>4.1.9.B</version> <version>4.3.4.B</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
<version>4.3.4.B</version>
</dependency> </dependency>
<!-- TODO 芋艿:清理 --> <!-- TODO 芋艿:清理 -->
</dependencies> </dependencies>

View File

@ -0,0 +1,16 @@
package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "管理后台 - 上传文件 VO")
public class UploadRespVO {
@ApiModelProperty(value = "文件名", required = true, example = "yudao.jpg")
private String fileName;
@ApiModelProperty(value = "文件 URL", required = true, example = "https://www.iocoder.cn/yudao.jpg")
private String fileUrl;
}

28
yudao-module-mall/pom.xml Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>yudao</artifactId>
<groupId>cn.iocoder.boot</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-mall</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<description>
market模块主要实现营销相关功能
例如营销活动、banner广告、优惠券、优惠码等功能。
</description>
<modules>
<module>yudao-module-market-api</module>
<module>yudao-module-market-biz</module>
<module>yudao-module-product-api</module>
<module>yudao-module-product-biz</module>
</modules>
</project>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-mall</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-market-api</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
market 模块 API暴露给其它模块调用
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,4 @@
/**
* 占位
*/
package cn.iocoder.yudao.module.market.api;

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.market.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
* market 错误码枚举类
* <p>
* market 系统使用 1-003-000-000
*/
public interface ErrorCodeConstants {
// ========== 促销活动相关 1003001000============
ErrorCode ACTIVITY_NOT_EXISTS = new ErrorCode(1003001000, "促销活动不存在");
// ========== banner相关 1003002000============
ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1003002000, "Banner不存在");
}

View File

@ -0,0 +1,51 @@
package cn.iocoder.yudao.module.market.enums.activity;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import java.util.Arrays;
/**
* 促销活动状态枚举
*/
public enum MarketActivityStatusEnum implements IntArrayValuable {
WAIT(10, "未开始"),
RUN(20, "进行中"),
END(30, "已结束"),
/**
* 1. WAITRUNEND 可以转换成 INVALID 状态
* 2. INVALID 只可以转换成 DELETED 状态
*/
INVALID(40, "已撤销"),
DELETED(50, "已删除"),
;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MarketActivityStatusEnum::getValue).toArray();
/**
* 状态值
*/
private final Integer value;
/**
* 状态名
*/
private final String name;
MarketActivityStatusEnum(Integer value, String name) {
this.value = value;
this.name = name;
}
public Integer getValue() {
return value;
}
public String getName() {
return name;
}
@Override
public int[] array() {
return ARRAYS;
}
}

View File

@ -0,0 +1,44 @@
package cn.iocoder.yudao.module.market.enums.activity;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import java.util.Arrays;
/**
* 促销活动类型枚举
*/
public enum MarketActivityTypeEnum implements IntArrayValuable {
TIME_LIMITED_DISCOUNT(1, "限时折扣"),
FULL_PRIVILEGE(2, "满减送"),
;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MarketActivityTypeEnum::getValue).toArray();
/**
* 类型值
*/
private final Integer value;
/**
* 类型名
*/
private final String name;
MarketActivityTypeEnum(Integer value, String name) {
this.value = value;
this.name = name;
}
public Integer getValue() {
return value;
}
public String getName() {
return name;
}
@Override
public int[] array() {
return ARRAYS;
}
}

View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-mall</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>yudao-module-market-biz</artifactId>
<name>${project.artifactId}</name>
<description>
market模块主要实现营销相关功能
例如营销活动、banner广告、优惠券、优惠码等功能。
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-market-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-web</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.market.controller.admin;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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.RestController;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Api(tags = "管理后台 - 营销")
@RestController
@RequestMapping("/market/test")
@Validated
public class MarketTestController {
@GetMapping("/get")
@ApiOperation("获取 market 信息")
public CommonResult<String> get() {
return success("true");
}
}

View File

@ -0,0 +1,77 @@
package cn.iocoder.yudao.module.market.controller.admin.activity;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.*;
import javax.validation.*;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.module.market.controller.admin.activity.vo.*;
import cn.iocoder.yudao.module.market.dal.dataobject.activity.ActivityDO;
import cn.iocoder.yudao.module.market.convert.activity.ActivityConvert;
import cn.iocoder.yudao.module.market.service.activity.ActivityService;
@Api(tags = "管理后台 - 促销活动")
@RestController
@RequestMapping("/market/activity")
@Validated
public class ActivityController {
@Resource
private ActivityService activityService;
@PostMapping("/create")
@ApiOperation("创建促销活动")
@PreAuthorize("@ss.hasPermission('market:activity:create')")
public CommonResult<Long> createActivity(@Valid @RequestBody ActivityCreateReqVO createReqVO) {
return success(activityService.createActivity(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新促销活动")
@PreAuthorize("@ss.hasPermission('market:activity:update')")
public CommonResult<Boolean> updateActivity(@Valid @RequestBody ActivityUpdateReqVO updateReqVO) {
activityService.updateActivity(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除促销活动")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('market:activity:delete')")
public CommonResult<Boolean> deleteActivity(@RequestParam("id") Long id) {
activityService.deleteActivity(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得促销活动")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('market:activity:query')")
public CommonResult<ActivityRespVO> getActivity(@RequestParam("id") Long id) {
ActivityDO activity = activityService.getActivity(id);
return success(ActivityConvert.INSTANCE.convert(activity));
}
@GetMapping("/list")
@ApiOperation("获得促销活动列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('market:activity:query')")
public CommonResult<List<ActivityRespVO>> getActivityList(@RequestParam("ids") Collection<Long> ids) {
List<ActivityDO> list = activityService.getActivityList(ids);
return success(ActivityConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得促销活动分页")
@PreAuthorize("@ss.hasPermission('market:activity:query')")
public CommonResult<PageResult<ActivityRespVO>> getActivityPage(@Valid ActivityPageReqVO pageVO) {
PageResult<ActivityDO> pageResult = activityService.getActivityPage(pageVO);
return success(ActivityConvert.INSTANCE.convertPage(pageResult));
}
}

View File

@ -0,0 +1,59 @@
package cn.iocoder.yudao.module.market.controller.admin.activity.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.market.enums.activity.MarketActivityStatusEnum;
import cn.iocoder.yudao.module.market.enums.activity.MarketActivityTypeEnum;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 促销活动 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class ActivityBaseVO {
@ApiModelProperty(value = "活动标题", required = true)
@NotNull(message = "活动标题不能为空")
private String title;
@ApiModelProperty(value = "活动类型", required = true)
@NotNull(message = "活动类型不能为空")
@InEnum(MarketActivityTypeEnum.class)
private Integer activityType;
@ApiModelProperty(value = "活动状态", required = true)
@NotNull(message = "活动状态不能为空")
@InEnum(MarketActivityStatusEnum.class)
private Integer status;
@ApiModelProperty(value = "开始时间", required = true)
@NotNull(message = "开始时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date startTime;
@ApiModelProperty(value = "结束时间", required = true)
@NotNull(message = "结束时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date endTime;
@ApiModelProperty(value = "失效时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date invalidTime;
@ApiModelProperty(value = "删除时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date deleteTime;
@ApiModelProperty(value = "限制折扣字符串,使用 JSON 序列化成字符串存储")
private String timeLimitedDiscount;
@ApiModelProperty(value = "限制折扣字符串,使用 JSON 序列化成字符串存储")
private String fullPrivilege;
}

View File

@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.market.controller.admin.activity.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* @author xia
*/
@ApiModel("管理后台 - 促销活动创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ActivityCreateReqVO extends ActivityBaseVO {
}

View File

@ -0,0 +1,77 @@
package cn.iocoder.yudao.module.market.controller.admin.activity.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.market.enums.activity.MarketActivityStatusEnum;
import cn.iocoder.yudao.module.market.enums.activity.MarketActivityTypeEnum;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 促销活动分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ActivityPageReqVO extends PageParam {
@ApiModelProperty(value = "活动标题")
private String title;
@ApiModelProperty(value = "活动类型")
@InEnum(MarketActivityTypeEnum.class)
private Integer activityType;
@ApiModelProperty(value = "活动状态")
@InEnum(MarketActivityStatusEnum.class)
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始开始时间")
private Date beginStartTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束开始时间")
private Date endStartTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始结束时间")
private Date beginEndTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束结束时间")
private Date endEndTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始失效时间")
private Date beginInvalidTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束失效时间")
private Date endInvalidTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始删除时间")
private Date beginDeleteTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束删除时间")
private Date endDeleteTime;
@ApiModelProperty(value = "限制折扣字符串,使用 JSON 序列化成字符串存储")
private String timeLimitedDiscount;
@ApiModelProperty(value = "限制折扣字符串,使用 JSON 序列化成字符串存储")
private String fullPrivilege;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.market.controller.admin.activity.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 促销活动 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ActivityRespVO extends ActivityBaseVO {
@ApiModelProperty(value = "活动编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.market.controller.admin.activity.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 促销活动更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ActivityUpdateReqVO extends ActivityBaseVO {
@ApiModelProperty(value = "活动编号", required = true)
@NotNull(message = "活动编号不能为空")
private Long id;
}

View File

@ -0,0 +1,71 @@
package cn.iocoder.yudao.module.market.controller.admin.banner;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.market.controller.admin.banner.vo.*;
import cn.iocoder.yudao.module.market.convert.banner.BannerConvert;
import cn.iocoder.yudao.module.market.dal.dataobject.banner.BannerDO;
import cn.iocoder.yudao.module.market.service.banner.BannerService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Api(tags = "管理后台 - Banner 管理")
@RestController
@RequestMapping("/market/banner")
@Validated
public class BannerController {
@Resource
private BannerService bannerService;
@PostMapping("/create")
@ApiOperation("创建 Banner")
@PreAuthorize("@ss.hasPermission('market:banner:create')")
public CommonResult<Long> createBanner(@Valid @RequestBody BannerCreateReqVO createReqVO) {
return success(bannerService.createBanner(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新 Banner")
@PreAuthorize("@ss.hasPermission('market:banner:update')")
public CommonResult<Boolean> updateBanner(@Valid @RequestBody BannerUpdateReqVO updateReqVO) {
bannerService.updateBanner(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除 Banner")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('market:banner:delete')")
public CommonResult<Boolean> deleteBanner(@RequestParam("id") Long id) {
bannerService.deleteBanner(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得 Banner")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('market:banner:query')")
public CommonResult<BannerRespVO> getBanner(@RequestParam("id") Long id) {
BannerDO banner = bannerService.getBanner(id);
return success(BannerConvert.INSTANCE.convert(banner));
}
@GetMapping("/page")
@ApiOperation("获得 Banner 分页")
@PreAuthorize("@ss.hasPermission('market:banner:query')")
public CommonResult<PageResult<BannerRespVO>> getBannerPage(@Valid BannerPageReqVO pageVO) {
PageResult<BannerDO> pageResult = bannerService.getBannerPage(pageVO);
return success(BannerConvert.INSTANCE.convertPage(pageResult));
}
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.market.controller.admin.banner.vo;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* Banner Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
* @author xia
*/
@Data
public class BannerBaseVO {
@ApiModelProperty(value = "标题", required = true)
@NotNull(message = "标题不能为空")
private String title;
@ApiModelProperty(value = "跳转链接", required = true)
@NotNull(message = "跳转链接不能为空")
private String url;
@ApiModelProperty(value = "图片地址", required = true)
@NotNull(message = "图片地址不能为空")
private String picUrl;
@ApiModelProperty(value = "排序", required = true)
@NotNull(message = "排序不能为空")
private Integer sort;
@ApiModelProperty(value = "状态", required = true)
@NotNull(message = "状态不能为空")
@InEnum(CommonStatusEnum.class)
private Integer status;
@ApiModelProperty(value = "备注")
private String memo;
}

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.market.controller.admin.banner.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
/**
* @author xia
*/
@ApiModel("管理后台 - Banner 创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BannerCreateReqVO extends BannerBaseVO {
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.market.controller.admin.banner.vo;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* @author xia
*/
@ApiModel("管理后台 - Banner 分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BannerPageReqVO extends PageParam {
@ApiModelProperty(value = "标题")
private String title;
@ApiModelProperty(value = "状态")
@InEnum(CommonStatusEnum.class)
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.market.controller.admin.banner.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.util.Date;
/**
* @author xia
*/
@ApiModel("管理后台 - Banner Response VO")
@Data
@ToString(callSuper = true)
public class BannerRespVO extends BannerBaseVO {
@ApiModelProperty(value = "banner编号", required = true)
@NotNull(message = "banner编号不能为空")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.market.controller.admin.banner.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
/**
* @author xia
*/
@ApiModel("管理后台 - Banner更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BannerUpdateReqVO extends BannerBaseVO {
@ApiModelProperty(value = "banner 编号", required = true)
@NotNull(message = "banner 编号不能为空")
private Long id;
}

View File

@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.market.controller.app;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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.RestController;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Api(tags = "用户 App - 营销")
@RestController
@RequestMapping("/market/test")
@Validated
public class AppMarketTestController {
@GetMapping("/get")
@ApiOperation("获取 market 信息")
public CommonResult<String> get() {
return success("true");
}
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.market.controller.app.banner;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.market.controller.admin.banner.vo.BannerRespVO;
import cn.iocoder.yudao.module.market.convert.banner.BannerConvert;
import cn.iocoder.yudao.module.market.dal.dataobject.banner.BannerDO;
import cn.iocoder.yudao.module.market.service.banner.BannerService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
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.RestController;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
/**
* @author: XIA
*/
@RestController
@RequestMapping("/market/banner")
@Api(tags = "用户APP- 首页Banner")
@Validated
public class AppBannerController {
// TODO @xia使用 @Resource
@Autowired
private BannerService bannerService;
// TODO @xia新建一个 AppBannerRespVO只返回必要的字段status 要过滤下然后 sort 下结果
@GetMapping("/list")
@ApiOperation("获得banner列表")
@PreAuthorize("@ss.hasPermission('market:banner:query')")
public CommonResult<List<BannerRespVO>> getBannerList() {
List<BannerDO> list = bannerService.getBannerList();
return success(BannerConvert.INSTANCE.convertList(list));
}
}

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.market.convert.activity;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.market.controller.admin.activity.vo.*;
import cn.iocoder.yudao.module.market.dal.dataobject.activity.ActivityDO;
/**
* 促销活动 Convert
*
* @author 芋道源码
*/
@Mapper
public interface ActivityConvert {
ActivityConvert INSTANCE = Mappers.getMapper(ActivityConvert.class);
ActivityDO convert(ActivityCreateReqVO bean);
ActivityDO convert(ActivityUpdateReqVO bean);
ActivityRespVO convert(ActivityDO bean);
List<ActivityRespVO> convertList(List<ActivityDO> list);
PageResult<ActivityRespVO> convertPage(PageResult<ActivityDO> page);
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.market.convert.banner;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.market.controller.admin.banner.vo.BannerCreateReqVO;
import cn.iocoder.yudao.module.market.controller.admin.banner.vo.BannerRespVO;
import cn.iocoder.yudao.module.market.controller.admin.banner.vo.BannerUpdateReqVO;
import cn.iocoder.yudao.module.market.dal.dataobject.banner.BannerDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* Banner Convert
*
* @author xia
*/
@Mapper
public interface BannerConvert {
BannerConvert INSTANCE = Mappers.getMapper(BannerConvert.class);
List<BannerRespVO> convertList(List<BannerDO> list);
PageResult<BannerRespVO> convertPage(PageResult<BannerDO> pageResult);
BannerRespVO convert(BannerDO banner);
BannerDO convert(BannerCreateReqVO createReqVO);
BannerDO convert(BannerUpdateReqVO updateReqVO);
}

View File

@ -0,0 +1,64 @@
package cn.iocoder.yudao.module.market.dal.dataobject.activity;
import lombok.*;
import java.util.*;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 促销活动 DO
*
* @author 芋道源码
*/
@TableName("market_activity")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ActivityDO extends BaseDO {
/**
* 活动编号
*/
@TableId
private Long id;
/**
* 活动标题
*/
private String title;
/**
* 活动类型MarketActivityTypeEnum
*/
private Integer activityType;
/**
* 活动状态MarketActivityStatusEnum
*/
private Integer status;
/**
* 开始时间
*/
private Date startTime;
/**
* 结束时间
*/
private Date endTime;
/**
* 失效时间
*/
private Date invalidTime;
/**
* 删除时间
*/
private Date deleteTime;
/**
* 限制折扣字符串使用 JSON 序列化成字符串存储
*/
private String timeLimitedDiscount;
/**
* 限制折扣字符串使用 JSON 序列化成字符串存储
*/
private String fullPrivilege;
}

View File

@ -0,0 +1,53 @@
package cn.iocoder.yudao.module.market.dal.dataobject.banner;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* banner DO
*
* @author xia
*/
@TableName("market_banner")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BannerDO extends BaseDO {
/**
* 编号
*/
private Long id;
/**
* 标题
*/
private String title;
/**
* 跳转链接
*/
private String url;
/**
* 图片链接
*/
private String picUrl;
/**
* 排序
*/
private Integer sort;
/**
* 状态 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
*/
private Integer status;
/**
* 备注
*/
private String memo;
// TODO 芋艿 点击次数&& 其他数据相关
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.market.dal.mysql.activity;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.market.dal.dataobject.activity.ActivityDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.market.controller.admin.activity.vo.*;
/**
* 促销活动 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface ActivityMapper extends BaseMapperX<ActivityDO> {
default PageResult<ActivityDO> selectPage(ActivityPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<ActivityDO>()
.eqIfPresent(ActivityDO::getTitle, reqVO.getTitle())
.eqIfPresent(ActivityDO::getActivityType, reqVO.getActivityType())
.eqIfPresent(ActivityDO::getStatus, reqVO.getStatus())
.betweenIfPresent(ActivityDO::getStartTime, reqVO.getBeginStartTime(), reqVO.getEndStartTime())
.betweenIfPresent(ActivityDO::getEndTime, reqVO.getBeginEndTime(), reqVO.getEndEndTime())
.betweenIfPresent(ActivityDO::getInvalidTime, reqVO.getBeginInvalidTime(), reqVO.getEndInvalidTime())
.betweenIfPresent(ActivityDO::getDeleteTime, reqVO.getBeginDeleteTime(), reqVO.getEndDeleteTime())
.eqIfPresent(ActivityDO::getTimeLimitedDiscount, reqVO.getTimeLimitedDiscount())
.eqIfPresent(ActivityDO::getFullPrivilege, reqVO.getFullPrivilege())
.betweenIfPresent(ActivityDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc(ActivityDO::getId));
}
}

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.market.dal.mysql.banner;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.market.controller.admin.banner.vo.BannerPageReqVO;
import cn.iocoder.yudao.module.market.dal.dataobject.banner.BannerDO;
import org.apache.ibatis.annotations.Mapper;
/**
* Banner Mapper
*
* @author xia
*/
@Mapper
public interface BannerMapper extends BaseMapperX<BannerDO> {
default PageResult<BannerDO> selectPage(BannerPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<BannerDO>()
.likeIfPresent(BannerDO::getTitle, reqVO.getTitle())
.eqIfPresent(BannerDO::getStatus, reqVO.getStatus())
.betweenIfPresent(BannerDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.betweenIfPresent(BannerDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc(BannerDO::getSort));
}
}

View File

@ -0,0 +1,8 @@
/**
* market 模块我们放营销业务
* 例如说营销活动banner优惠券等等
*
* 1. Controller URL /market/ 开头避免和其它 Module 冲突
* 2. DataObject 表名 market_ 开头方便在数据库中区分
*/
package cn.iocoder.yudao.module.market;

View File

@ -0,0 +1,62 @@
package cn.iocoder.yudao.module.market.service.activity;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.market.controller.admin.activity.vo.*;
import cn.iocoder.yudao.module.market.dal.dataobject.activity.ActivityDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
/**
* 促销活动 Service 接口
*
* @author 芋道源码
*/
public interface ActivityService {
/**
* 创建促销活动
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createActivity(@Valid ActivityCreateReqVO createReqVO);
/**
* 更新促销活动
*
* @param updateReqVO 更新信息
*/
void updateActivity(@Valid ActivityUpdateReqVO updateReqVO);
/**
* 删除促销活动
*
* @param id 编号
*/
void deleteActivity(Long id);
/**
* 获得促销活动
*
* @param id 编号
* @return 促销活动
*/
ActivityDO getActivity(Long id);
/**
* 获得促销活动列表
*
* @param ids 编号
* @return 促销活动列表
*/
List<ActivityDO> getActivityList(Collection<Long> ids);
/**
* 获得促销活动分页
*
* @param pageReqVO 分页查询
* @return 促销活动分页
*/
PageResult<ActivityDO> getActivityPage(ActivityPageReqVO pageReqVO);
}

View File

@ -0,0 +1,77 @@
package cn.iocoder.yudao.module.market.service.activity;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import java.util.*;
import cn.iocoder.yudao.module.market.controller.admin.activity.vo.*;
import cn.iocoder.yudao.module.market.dal.dataobject.activity.ActivityDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.market.convert.activity.ActivityConvert;
import cn.iocoder.yudao.module.market.dal.mysql.activity.ActivityMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.market.enums.ErrorCodeConstants.*;
/**
* 促销活动 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class ActivityServiceImpl implements ActivityService {
@Resource
private ActivityMapper activityMapper;
@Override
public Long createActivity(ActivityCreateReqVO createReqVO) {
// 插入
ActivityDO activity = ActivityConvert.INSTANCE.convert(createReqVO);
activityMapper.insert(activity);
// 返回
return activity.getId();
}
@Override
public void updateActivity(ActivityUpdateReqVO updateReqVO) {
// 校验存在
this.validateActivityExists(updateReqVO.getId());
// 更新
ActivityDO updateObj = ActivityConvert.INSTANCE.convert(updateReqVO);
activityMapper.updateById(updateObj);
}
@Override
public void deleteActivity(Long id) {
// 校验存在
this.validateActivityExists(id);
// 删除
activityMapper.deleteById(id);
}
private void validateActivityExists(Long id) {
if (activityMapper.selectById(id) == null) {
throw exception(ACTIVITY_NOT_EXISTS);
}
}
@Override
public ActivityDO getActivity(Long id) {
return activityMapper.selectById(id);
}
@Override
public List<ActivityDO> getActivityList(Collection<Long> ids) {
return activityMapper.selectBatchIds(ids);
}
@Override
public PageResult<ActivityDO> getActivityPage(ActivityPageReqVO pageReqVO) {
return activityMapper.selectPage(pageReqVO);
}
}

View File

@ -0,0 +1,63 @@
package cn.iocoder.yudao.module.market.service.banner;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.market.controller.admin.banner.vo.BannerCreateReqVO;
import cn.iocoder.yudao.module.market.controller.admin.banner.vo.BannerPageReqVO;
import cn.iocoder.yudao.module.market.controller.admin.banner.vo.BannerUpdateReqVO;
import cn.iocoder.yudao.module.market.dal.dataobject.banner.BannerDO;
import javax.validation.Valid;
import java.util.List;
/**
* 首页 Banner Service 接口
*
* @author xia
*/
public interface BannerService {
/**
* 创建 Banner
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createBanner(@Valid BannerCreateReqVO createReqVO);
/**
* 更新 Banner
*
* @param updateReqVO 更新信息
*/
void updateBanner(@Valid BannerUpdateReqVO updateReqVO);
/**
* 删除 Banner
*
* @param id 编号
*/
void deleteBanner(Long id);
/**
* 获得 Banner
*
* @param id 编号
* @return Banner
*/
BannerDO getBanner(Long id);
/**
* 获得所有 Banner列表
* @return Banner列表
*/
List<BannerDO> getBannerList();
/**
* 获得 Banner 分页
*
* @param pageReqVO 分页查询
* @return Banner分页
*/
PageResult<BannerDO> getBannerPage(BannerPageReqVO pageReqVO);
}

View File

@ -0,0 +1,78 @@
package cn.iocoder.yudao.module.market.service.banner;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.market.controller.admin.banner.vo.BannerCreateReqVO;
import cn.iocoder.yudao.module.market.controller.admin.banner.vo.BannerPageReqVO;
import cn.iocoder.yudao.module.market.controller.admin.banner.vo.BannerUpdateReqVO;
import cn.iocoder.yudao.module.market.convert.banner.BannerConvert;
import cn.iocoder.yudao.module.market.dal.dataobject.banner.BannerDO;
import cn.iocoder.yudao.module.market.dal.mysql.banner.BannerMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.market.enums.ErrorCodeConstants.BANNER_NOT_EXISTS;
/**
* 首页banner 实现类
*
* @author xia
*/
@Service
@Validated
public class BannerServiceImpl implements BannerService {
@Resource
private BannerMapper bannerMapper;
@Override
public Long createBanner(BannerCreateReqVO createReqVO) {
// 插入
BannerDO banner = BannerConvert.INSTANCE.convert(createReqVO);
bannerMapper.insert(banner);
// 返回
return banner.getId();
}
@Override
public void updateBanner(BannerUpdateReqVO updateReqVO) {
// 校验存在
this.validateBannerExists(updateReqVO.getId());
// 更新
BannerDO updateObj = BannerConvert.INSTANCE.convert(updateReqVO);
bannerMapper.updateById(updateObj);
}
@Override
public void deleteBanner(Long id) {
// 校验存在
this.validateBannerExists(id);
// 删除
bannerMapper.deleteById(id);
}
private void validateBannerExists(Long id) {
if (bannerMapper.selectById(id) == null) {
throw exception(BANNER_NOT_EXISTS);
}
}
@Override
public BannerDO getBanner(Long id) {
return bannerMapper.selectById(id);
}
@Override
public List<BannerDO> getBannerList() {
return bannerMapper.selectList();
}
@Override
public PageResult<BannerDO> getBannerPage(BannerPageReqVO pageReqVO) {
return bannerMapper.selectPage(pageReqVO);
}
}

View File

@ -0,0 +1,202 @@
package cn.iocoder.yudao.module.market.service.activity;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.market.controller.admin.activity.vo.*;
import cn.iocoder.yudao.module.market.dal.dataobject.activity.ActivityDO;
import cn.iocoder.yudao.module.market.dal.mysql.activity.ActivityMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.context.annotation.Import;
import static cn.iocoder.yudao.module.market.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link ActivityServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(ActivityServiceImpl.class)
public class ActivityServiceImplTest extends BaseDbUnitTest {
@Resource
private ActivityServiceImpl activityService;
@Resource
private ActivityMapper activityMapper;
@Test
public void testCreateActivity_success() {
// 准备参数
ActivityCreateReqVO reqVO = randomPojo(ActivityCreateReqVO.class);
// 调用
Long activityId = activityService.createActivity(reqVO);
// 断言
assertNotNull(activityId);
// 校验记录的属性是否正确
ActivityDO activity = activityMapper.selectById(activityId);
assertPojoEquals(reqVO, activity);
}
@Test
public void testUpdateActivity_success() {
// mock 数据
ActivityDO dbActivity = randomPojo(ActivityDO.class);
activityMapper.insert(dbActivity);// @Sql: 先插入出一条存在的数据
// 准备参数
ActivityUpdateReqVO reqVO = randomPojo(ActivityUpdateReqVO.class, o -> {
o.setId(dbActivity.getId()); // 设置更新的 ID
});
// 调用
activityService.updateActivity(reqVO);
// 校验是否更新正确
ActivityDO activity = activityMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, activity);
}
@Test
public void testUpdateActivity_notExists() {
// 准备参数
ActivityUpdateReqVO reqVO = randomPojo(ActivityUpdateReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> activityService.updateActivity(reqVO), ACTIVITY_NOT_EXISTS);
}
@Test
public void testDeleteActivity_success() {
// mock 数据
ActivityDO dbActivity = randomPojo(ActivityDO.class);
activityMapper.insert(dbActivity);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbActivity.getId();
// 调用
activityService.deleteActivity(id);
// 校验数据不存在了
assertNull(activityMapper.selectById(id));
}
@Test
public void testDeleteActivity_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> activityService.deleteActivity(id), ACTIVITY_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值然后删除 @Disabled 注解
public void testGetActivityPage() {
// mock 数据
ActivityDO dbActivity = randomPojo(ActivityDO.class, o -> { // 等会查询到
o.setTitle(null);
o.setActivityType(null);
o.setStatus(null);
o.setStartTime(null);
o.setEndTime(null);
o.setInvalidTime(null);
o.setDeleteTime(null);
o.setTimeLimitedDiscount(null);
o.setFullPrivilege(null);
o.setCreateTime(null);
});
activityMapper.insert(dbActivity);
// 测试 title 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setTitle(null)));
// 测试 activityType 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setActivityType(null)));
// 测试 status 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setStatus(null)));
// 测试 startTime 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setStartTime(null)));
// 测试 endTime 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setEndTime(null)));
// 测试 invalidTime 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setInvalidTime(null)));
// 测试 deleteTime 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setDeleteTime(null)));
// 测试 timeLimitedDiscount 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setTimeLimitedDiscount(null)));
// 测试 fullPrivilege 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setFullPrivilege(null)));
// 测试 createTime 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setCreateTime(null)));
// 准备参数
ActivityPageReqVO reqVO = new ActivityPageReqVO();
reqVO.setTitle(null);
reqVO.setActivityType(null);
reqVO.setStatus(null);
reqVO.setBeginStartTime(null);
reqVO.setEndStartTime(null);
reqVO.setBeginEndTime(null);
reqVO.setEndEndTime(null);
reqVO.setBeginInvalidTime(null);
reqVO.setEndInvalidTime(null);
reqVO.setBeginDeleteTime(null);
reqVO.setEndDeleteTime(null);
reqVO.setTimeLimitedDiscount(null);
reqVO.setFullPrivilege(null);
reqVO.setBeginCreateTime(null);
reqVO.setEndCreateTime(null);
// 调用
PageResult<ActivityDO> pageResult = activityService.getActivityPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbActivity, pageResult.getList().get(0));
}
@Test
@Disabled // TODO 请修改 null 为需要的值然后删除 @Disabled 注解
public void testGetActivityList() {
// mock 数据
ActivityDO dbActivity = randomPojo(ActivityDO.class, o -> { // 等会查询到
o.setTitle(null);
o.setActivityType(null);
o.setStatus(null);
o.setStartTime(null);
o.setEndTime(null);
o.setInvalidTime(null);
o.setDeleteTime(null);
o.setTimeLimitedDiscount(null);
o.setFullPrivilege(null);
o.setCreateTime(null);
});
activityMapper.insert(dbActivity);
// 测试 title 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setTitle(null)));
// 测试 activityType 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setActivityType(null)));
// 测试 status 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setStatus(null)));
// 测试 startTime 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setStartTime(null)));
// 测试 endTime 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setEndTime(null)));
// 测试 invalidTime 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setInvalidTime(null)));
// 测试 deleteTime 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setDeleteTime(null)));
// 测试 timeLimitedDiscount 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setTimeLimitedDiscount(null)));
// 测试 fullPrivilege 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setFullPrivilege(null)));
// 测试 createTime 不匹配
activityMapper.insert(cloneIgnoreId(dbActivity, o -> o.setCreateTime(null)));
}
}

View File

@ -0,0 +1,49 @@
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; # 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 默认的配置足够使用,一般不需要进行调优
redis:
host: 127.0.0.1 # 地址
port: 16379 # 端口(单元测试,使用 16379 端口)
database: 0 # 数据库索引
mybatis:
lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
--- #################### 定时任务相关配置 ####################
--- #################### 配置中心相关配置 ####################
--- #################### 服务保障相关配置 ####################
# Lock4j 配置项(单元测试,禁用 Lock4j
# Resilience4j 配置项
--- #################### 监控相关配置 ####################
--- #################### 芋道相关配置 ####################
# 芋道配置项,设置当前项目所有自定义的配置
yudao:
info:
base-package: cn.iocoder.yudao.module

View File

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

View File

@ -0,0 +1 @@
DELETE FROM "market_activity";

View File

@ -0,0 +1,19 @@
CREATE TABLE IF NOT EXISTS "market_activity" (
"id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"title" varchar(50) NOT NULL,
"activity_type" tinyint(4) NOT NULL,
"status" tinyint(4) NOT NULL,
"start_time" datetime NOT NULL,
"end_time" datetime NOT NULL,
"invalid_time" datetime,
"delete_time" datetime,
"time_limited_discount" varchar(2000),
"full_privilege" varchar(2000),
"creator" varchar(64) DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint(20) NOT NULL,
PRIMARY KEY ("id")
) COMMENT '促销活动';

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-mall</artifactId>
<version>${revision}</version>
</parent>
<artifactId>yudao-module-product-api</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
product 模块 API暴露给其它模块调用
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,4 @@
/**
* 占位
*/
package cn.iocoder.yudao.module.product.api;

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.product.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
* product 错误码枚举类
* <p>
* product 系统使用 1-008-000-000
*/
public interface ErrorCodeConstants {
// ========== 商品分类相关 1008001000============
ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在");
ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在");
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001002, "存在子分类,无法删除");
// ========== 品牌相关编号 1008002000 ==========
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
// ========== 规格名称 1008003000 ==========
ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "规格名称不存在");
// ========== 规格值 1008004000 ==========
ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "规格值不存在");
// ========== 商品spu 1008005000 ==========
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品spu不存在");
// ========== 商品sku 1008006000 ==========
ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品sku不存在");
ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品sku的属性组合存在重复");
}

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-mall</artifactId>
<version>${revision}</version>
</parent>
<artifactId>yudao-module-product-biz</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
product 模块,主要实现商品相关功能
例如品牌、商品分类、spu、sku等功能。
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-product-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,89 @@
package cn.iocoder.yudao.module.product.controller.admin.brand;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*;
import cn.iocoder.yudao.module.product.convert.brand.BrandConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.brand.BrandDO;
import cn.iocoder.yudao.module.product.service.brand.BrandService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Api(tags = "管理后台 - 品牌")
@RestController
@RequestMapping("/product/brand")
@Validated
public class BrandController {
@Resource
private BrandService brandService;
@PostMapping("/create")
@ApiOperation("创建品牌")
@PreAuthorize("@ss.hasPermission('product:brand:create')")
public CommonResult<Long> createBrand(@Valid @RequestBody BrandCreateReqVO createReqVO) {
return success(brandService.createBrand(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新品牌")
@PreAuthorize("@ss.hasPermission('product:brand:update')")
public CommonResult<Boolean> updateBrand(@Valid @RequestBody BrandUpdateReqVO updateReqVO) {
brandService.updateBrand(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除品牌")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:brand:delete')")
public CommonResult<Boolean> deleteBrand(@RequestParam("id") Long id) {
brandService.deleteBrand(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得品牌")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:brand:query')")
public CommonResult<BrandRespVO> getBrand(@RequestParam("id") Long id) {
BrandDO brand = brandService.getBrand(id);
return success(BrandConvert.INSTANCE.convert(brand));
}
@GetMapping("/page")
@ApiOperation("获得品牌分页")
@PreAuthorize("@ss.hasPermission('product:brand:query')")
public CommonResult<PageResult<BrandRespVO>> getBrandPage(@Valid BrandPageReqVO pageVO) {
PageResult<BrandDO> pageResult = brandService.getBrandPage(pageVO);
return success(BrandConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出品牌 Excel")
@PreAuthorize("@ss.hasPermission('product:brand:export')")
@OperateLog(type = EXPORT)
public void exportBrandExcel(@Valid BrandExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<BrandDO> list = brandService.getBrandList(exportReqVO);
// 导出 Excel
List<BrandExcelVO> datas = BrandConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "品牌.xls", "数据", BrandExcelVO.class, datas);
}
}

View File

@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 品牌 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class BrandBaseVO {
@ApiModelProperty(value = "分类编号", required = true, example = "1")
@NotNull(message = "分类编号不能为空")
private Long categoryId;
@ApiModelProperty(value = "品牌名称", required = true, example = "芋道")
@NotNull(message = "品牌名称不能为空")
private String name;
@ApiModelProperty(value = "品牌图片", required = true)
@NotNull(message = "品牌图片不能为空")
private String bannerUrl;
@ApiModelProperty(value = "品牌排序", example = "1")
private Integer sort;
@ApiModelProperty(value = "品牌描述", example = "描述")
private String description;
@ApiModelProperty(value = "状态", required = true, example = "0")
@NotNull(message = "状态不能为空")
private Integer status;
}

View File

@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 品牌创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BrandCreateReqVO extends BrandBaseVO {
}

View File

@ -0,0 +1,45 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import com.alibaba.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
/**
* 品牌 Excel VO
*
* @author 芋道源码
*/
@Data
public class BrandExcelVO {
@ExcelProperty("品牌编号")
private Long id;
@ExcelProperty("分类编号")
private Long categoryId;
@ExcelProperty("品牌名称")
private String name;
@ExcelProperty("品牌图片")
private String bannerUrl;
@ExcelProperty("品牌排序")
private Integer sort;
@ExcelProperty("品牌描述")
private String description;
@ExcelProperty(value = "状态", converter = DictConvert.class)
@DictFormat("common_status") // TODO 代码优化建议设置到对应的 XXXDictTypeConstants 枚举类中
private Integer status;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - 品牌 Excel 导出 Request VO", description = "参数和 BrandPageReqVO 是一致的")
@Data
public class BrandExportReqVO {
@ApiModelProperty(value = "分类编号", example = "1")
private Long categoryId;
@ApiModelProperty(value = "品牌名称", example = "芋道")
private String name;
@ApiModelProperty(value = "状态", example = "0")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 品牌分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BrandPageReqVO extends PageParam {
@ApiModelProperty(value = "分类编号", example = "1")
private Long categoryId;
@ApiModelProperty(value = "品牌名称", example = "芋道")
private String name;
@ApiModelProperty(value = "状态", example = "0")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 品牌 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BrandRespVO extends BrandBaseVO {
@ApiModelProperty(value = "品牌编号", required = true, example = "1")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.product.controller.admin.brand.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 品牌更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BrandUpdateReqVO extends BrandBaseVO {
@ApiModelProperty(value = "品牌编号", required = true, example = "1")
@NotNull(message = "品牌编号不能为空")
private Long id;
}

View File

@ -0,0 +1,92 @@
package cn.iocoder.yudao.module.product.controller.admin.category;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.product.controller.admin.category.vo.*;
import cn.iocoder.yudao.module.product.convert.category.CategoryConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
import cn.iocoder.yudao.module.product.service.category.CategoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Comparator;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Api(tags = "管理后台 - 商品分类")
@RestController
@RequestMapping("/product/category")
@Validated
public class CategoryController {
@Resource
private CategoryService categoryService;
@PostMapping("/create")
@ApiOperation("创建商品分类")
@PreAuthorize("@ss.hasPermission('product:category:create')")
public CommonResult<Long> createCategory(@Valid @RequestBody CategoryCreateReqVO createReqVO) {
return success(categoryService.createCategory(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新商品分类")
@PreAuthorize("@ss.hasPermission('product:category:update')")
public CommonResult<Boolean> updateCategory(@Valid @RequestBody CategoryUpdateReqVO updateReqVO) {
categoryService.updateCategory(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除商品分类")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:category:delete')")
public CommonResult<Boolean> deleteCategory(@RequestParam("id") Long id) {
categoryService.deleteCategory(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得商品分类")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:category:query')")
public CommonResult<CategoryRespVO> getCategory(@RequestParam("id") Long id) {
CategoryDO category = categoryService.getCategory(id);
return success(CategoryConvert.INSTANCE.convert(category));
}
// TODO @JeromeSoar这应该是个 app 的接口提供商品分类的树结构这个调整下后端只返回列表前端构建 tree注意不需要返回创建时间是否开启等无关字段
// TODO @YunaiV: 这个是在管理端展示了一个类似菜单的分类树列表, treeListReqVO 只是查询参数的封装命名返给前端的是列表数据PS: 这里 /page 接口没有使用到
@GetMapping("/listByQuery")
@ApiOperation("获得商品分类列表")
@PreAuthorize("@ss.hasPermission('product:category:query')")
public CommonResult<List<CategoryRespVO>> listByQuery(@Valid CategoryTreeListReqVO treeListReqVO) {
List<CategoryDO> list = categoryService.getCategoryTreeList(treeListReqVO);
list.sort(Comparator.comparing(CategoryDO::getSort));
return success(CategoryConvert.INSTANCE.convertList(list));
}
@GetMapping("/export-excel")
@ApiOperation("导出商品分类 Excel")
@PreAuthorize("@ss.hasPermission('product:category:export')")
@OperateLog(type = EXPORT)
public void exportCategoryExcel(@Valid CategoryExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<CategoryDO> list = categoryService.getCategoryList(exportReqVO);
// 导出 Excel
List<CategoryExcelVO> datas = CategoryConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "商品分类.xls", "数据", CategoryExcelVO.class, datas);
}
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 商品分类 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class CategoryBaseVO {
@ApiModelProperty(value = "父分类编号", required = true, example = "1")
@NotNull(message = "父分类编号不能为空")
private Long parentId;
@ApiModelProperty(value = "分类名称", required = true, example = "办公文具")
@NotBlank(message = "分类名称不能为空")
private String name;
@ApiModelProperty(value = "分类图标")
@NotBlank(message = "分类图标不能为空")
private String icon;
@ApiModelProperty(value = "分类图片", required = true)
@NotBlank(message = "分类图片不能为空")
private String bannerUrl;
@ApiModelProperty(value = "分类排序", required = true, example = "1")
private Integer sort;
@ApiModelProperty(value = "分类描述", required = true, example = "描述")
private String description;
@ApiModelProperty(value = "开启状态", required = true, example = "0")
@NotNull(message = "开启状态不能为空")
private Integer status;
}

View File

@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 商品分类创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CategoryCreateReqVO extends CategoryBaseVO {
}

View File

@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 商品分类 Excel VO
*
* @author 芋道源码
*/
@Data
public class CategoryExcelVO {
@ExcelProperty("分类编号")
private Long id;
@ExcelProperty("父分类编号")
private Long parentId;
@ExcelProperty("分类名称")
private String name;
@ExcelProperty("分类图标")
private String icon;
@ExcelProperty("分类图片")
private String bannerUrl;
@ExcelProperty("分类排序")
private Integer sort;
@ExcelProperty("分类描述")
private String description;
@ExcelProperty(value = "开启状态", converter = DictConvert.class)
@DictFormat("common_status") // TODO 代码优化建议设置到对应的 XXXDictTypeConstants 枚举类中
private Integer status;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - 商品分类 Excel 导出 Request VO", description = "参数和 CategoryPageReqVO 是一致的")
@Data
public class CategoryExportReqVO {
@ApiModelProperty(value = "分类名称", example = "办公文具")
private String name;
@ApiModelProperty(value = "开启状态", example = "0")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 商品分类分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CategoryPageReqVO extends PageParam {
@ApiModelProperty(value = "分类名称", example = "办公文具")
private String name;
@ApiModelProperty(value = "开启状态", example = "0")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 商品分类 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CategoryRespVO extends CategoryBaseVO {
@ApiModelProperty(value = "分类编号", required = true, example = "2")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Data
@ApiModel(value = "管理后台 - 商品分类列表查询 Request VO", description = "参数和 CategoryPageReqVO 是一致的")
public class CategoryTreeListReqVO extends CategoryExportReqVO {
@ApiModelProperty(value = "分类名称", example = "办公文具")
private String name;
@ApiModelProperty(value = "开启状态", example = "0")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 商品分类更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CategoryUpdateReqVO extends CategoryBaseVO {
@ApiModelProperty(value = "分类编号", required = true, example = "2")
@NotNull(message = "分类编号不能为空")
private Long id;
}

View File

@ -0,0 +1,97 @@
package cn.iocoder.yudao.module.product.controller.admin.property;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.*;
import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
@Api(tags = "管理后台 - 规格名称")
@RestController
@RequestMapping("/product/property")
@Validated
public class ProductPropertyController {
@Resource
private ProductPropertyService productPropertyService;
@PostMapping("/create")
@ApiOperation("创建规格名称")
@PreAuthorize("@ss.hasPermission('product:property:create')")
public CommonResult<Long> createProperty(@Valid @RequestBody ProductPropertyCreateReqVO createReqVO) {
return success(productPropertyService.createProperty(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新规格名称")
@PreAuthorize("@ss.hasPermission('product:property:update')")
public CommonResult<Boolean> updateProperty(@Valid @RequestBody ProductPropertyUpdateReqVO updateReqVO) {
productPropertyService.updateProperty(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除规格名称")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:delete')")
public CommonResult<Boolean> deleteProperty(@RequestParam("id") Long id) {
productPropertyService.deleteProperty(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得规格名称")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult<ProductPropertyRespVO> getProperty(@RequestParam("id") Long id) {
return success(productPropertyService.getPropertyResp(id));
}
@GetMapping("/list")
@ApiOperation("获得规格名称列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult<List<ProductPropertyRespVO>> getPropertyList(@RequestParam("ids") Collection<Long> ids) {
List<ProductPropertyDO> list = productPropertyService.getPropertyList(ids);
return success(ProductPropertyConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得规格名称分页")
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult<PageResult<ProductPropertyRespVO>> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) {
return success(productPropertyService.getPropertyListPage(pageVO));
}
@GetMapping("/export-excel")
@ApiOperation("导出规格名称 Excel")
@PreAuthorize("@ss.hasPermission('product:property:export')")
@OperateLog(type = EXPORT)
public void exportPropertyExcel(@Valid ProductPropertyExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<ProductPropertyDO> list = productPropertyService.getPropertyList(exportReqVO);
// 导出 Excel
List<ProductPropertyExcelVO> datas = ProductPropertyConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "规格名称.xls", "数据", ProductPropertyExcelVO.class, datas);
}
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 规格名称 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class ProductPropertyBaseVO {
@ApiModelProperty(value = "规格名称")
private String name;
@ApiModelProperty(value = "状态: 0 开启 1 禁用")
private Integer status;
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo;
import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueCreateReqVO;
import lombok.*;
import io.swagger.annotations.*;
import javax.validation.constraints.NotNull;
import java.util.List;
@ApiModel("管理后台 - 规格名称创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyCreateReqVO extends ProductPropertyBaseVO {
@ApiModelProperty(value = "属性值")
@NotNull(message = "属性值不能为空")
List<ProductPropertyValueCreateReqVO> propertyValueList;
}

View File

@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import com.alibaba.excel.annotation.ExcelProperty;
/**
* 规格名称 Excel VO
*
* @author 芋道源码
*/
@Data
public class ProductPropertyExcelVO {
@ExcelProperty("主键")
private Long id;
@ExcelProperty("规格名称")
private String name;
@ExcelProperty("状态: 0 开启 1 禁用")
private Integer status;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - 规格名称 Excel 导出 Request VO", description = "参数和 PropertyPageReqVO 是一致的")
@Data
public class ProductPropertyExportReqVO {
@ApiModelProperty(value = "规格名称")
private String name;
@ApiModelProperty(value = "状态: 0 开启 1 禁用")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 规格名称分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyPageReqVO extends PageParam {
@ApiModelProperty(value = "规格名称")
private String name;
@ApiModelProperty(value = "状态: 0 开启 1 禁用")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo;
import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 规格名称 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyRespVO extends ProductPropertyBaseVO {
@ApiModelProperty(value = "主键", required = true)
private Long id;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "属性值")
private List<ProductPropertyValueRespVO> propertyValueList;
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo;
import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueCreateReqVO;
import lombok.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
import java.util.List;
@ApiModel("管理后台 - 规格名称更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyUpdateReqVO extends ProductPropertyBaseVO {
@ApiModelProperty(value = "主键", required = true)
@NotNull(message = "主键不能为空")
private Long id;
@ApiModelProperty(value = "属性值")
@NotNull(message = "属性值不能为空")
List<ProductPropertyValueCreateReqVO> propertyValueList;
}

View File

@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 规格值 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class ProductPropertyValueBaseVO {
@ApiModelProperty(value = "规格键id")
private Long propertyId;
@ApiModelProperty(value = "规格值名字")
private String name;
@ApiModelProperty(value = "状态: 1 开启 2 禁用")
private Integer status;
}

View File

@ -0,0 +1,12 @@
package cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo;
import lombok.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 规格值创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyValueCreateReqVO extends ProductPropertyValueBaseVO {
}

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 规格值 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyValueRespVO extends ProductPropertyValueBaseVO {
@ApiModelProperty(value = "主键", required = true)
private Long id;
@ApiModelProperty(value = "创建时间")
private Date createTime;
}

View File

@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo;
import lombok.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 规格值更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyValueUpdateReqVO extends ProductPropertyValueBaseVO {
@ApiModelProperty(value = "主键", required = true)
@NotNull(message = "主键不能为空")
private Integer id;
}

View File

@ -0,0 +1,99 @@
package cn.iocoder.yudao.module.product.controller.admin.sku;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*;
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Api(tags = "管理后台 - 商品 sku")
@RestController
@RequestMapping("/product/sku")
@Validated
public class ProductSkuController {
@Resource
private ProductSkuService ProductSkuService;
@PostMapping("/create")
@ApiOperation("创建商品sku")
@PreAuthorize("@ss.hasPermission('product:sku:create')")
public CommonResult<Long> createSku(@Valid @RequestBody ProductSkuCreateReqVO createReqVO) {
return success(ProductSkuService.createSku(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新商品sku")
@PreAuthorize("@ss.hasPermission('product:sku:update')")
public CommonResult<Boolean> updateSku(@Valid @RequestBody ProductSkuUpdateReqVO updateReqVO) {
ProductSkuService.updateSku(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除商品sku")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:sku:delete')")
public CommonResult<Boolean> deleteSku(@RequestParam("id") Long id) {
ProductSkuService.deleteSku(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得商品sku")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:sku:query')")
public CommonResult<ProductSkuRespVO> getSku(@RequestParam("id") Long id) {
ProductSkuDO sku = ProductSkuService.getSku(id);
return success(ProductSkuConvert.INSTANCE.convert(sku));
}
@GetMapping("/list")
@ApiOperation("获得商品sku列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('product:sku:query')")
public CommonResult<List<ProductSkuRespVO>> getSkuList(@RequestParam("ids") Collection<Long> ids) {
List<ProductSkuDO> list = ProductSkuService.getSkuList(ids);
return success(ProductSkuConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得商品sku分页")
@PreAuthorize("@ss.hasPermission('product:sku:query')")
public CommonResult<PageResult<ProductSkuRespVO>> getSkuPage(@Valid ProductSkuPageReqVO pageVO) {
PageResult<ProductSkuDO> pageResult = ProductSkuService.getSkuPage(pageVO);
return success(ProductSkuConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出商品sku Excel")
@PreAuthorize("@ss.hasPermission('product:sku:export')")
@OperateLog(type = EXPORT)
public void exportSkuExcel(@Valid ProductSkuExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<ProductSkuDO> list = ProductSkuService.getSkuList(exportReqVO);
// 导出 Excel
List<ProductSkuExcelVO> datas = ProductSkuConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "商品sku.xls", "数据", ProductSkuExcelVO.class, datas);
}
}

View File

@ -0,0 +1,58 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 商品sku Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class ProductSkuBaseVO {
// TODO @frankyexample 要写哈
@ApiModelProperty(value = "spu编号")
private Long spuId;
// TODO @franky类似这种字段有额外说明的可以写成 @ApiModelProperty(value = "规格值数组", required = true, notes = "json格式 [{propertyId: , valueId: }, {propertyId: , valueId: }]")
@ApiModelProperty(value = "规格值数组-json格式 [{propertyId: , valueId: }, {propertyId: , valueId: }]", required = true)
@NotNull(message = "规格值数组-json格式 [{propertyId: , valueId: }, {propertyId: , valueId: }]不能为空")
private List<Property> properties;
@ApiModelProperty(value = "销售价格,单位:分", required = true)
@NotNull(message = "销售价格,单位:分不能为空")
private Integer price;
@ApiModelProperty(value = "原价, 单位: 分", required = true)
@NotNull(message = "原价, 单位: 分不能为空")
private Integer originalPrice;
@ApiModelProperty(value = "成本价,单位: 分", required = true)
@NotNull(message = "成本价,单位: 分不能为空")
private Integer costPrice;
@ApiModelProperty(value = "条形码", required = true)
@NotNull(message = "条形码不能为空")
private String barCode;
@ApiModelProperty(value = "图片地址", required = true)
@NotNull(message = "图片地址不能为空")
private String picUrl;
@ApiModelProperty(value = "状态: 0-正常 1-禁用")
private Integer status;
// TODO @franky 要有 swagger 注解
@Data
public static class Property {
@NotNull(message = "规格属性名id不能为空")
private Long propertyId;
@NotNull(message = "规格属性值id不能为空")
private Long valueId;
}
}

View File

@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 商品sku创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSkuCreateReqVO extends ProductSkuBaseVO {
}

View File

@ -0,0 +1,53 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 商品sku Excel VO
*
* @author 芋道源码
*/
@Data
public class ProductSkuExcelVO {
@ExcelProperty("主键")
private Long id;
@ExcelProperty("spu编号")
private Long spuId;
// TODO @franky这个单元格可能会有点展示的问题
@ExcelProperty("规格值数组-json格式 [{propertId: , valueId: }, {propertId: , valueId: }]")
private List<Property> properties;
@ExcelProperty("销售价格,单位:分")
private Integer price;
@ExcelProperty("原价, 单位: 分")
private Integer originalPrice;
@ExcelProperty("成本价,单位: 分")
private Integer costPrice;
@ExcelProperty("条形码")
private String barCode;
@ExcelProperty("图片地址")
private String picUrl;
@ExcelProperty("状态: 0-正常 1-禁用")
private Integer status;
@ExcelProperty("创建时间")
private Date createTime;
@Data
public static class Property {
private Integer propertyId;
private Integer valueId;
}
}

View File

@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - 商品sku Excel 导出 Request VO", description = "参数和 SkuPageReqVO 是一致的")
@Data
public class ProductSkuExportReqVO {
@ApiModelProperty(value = "spu编号")
private Long spuId;
@ApiModelProperty(value = "规格值数组-json格式 [{propertId: , valueId: }, {propertId: , valueId: }]")
private String properties;
@ApiModelProperty(value = "销售价格,单位:分")
private Integer price;
@ApiModelProperty(value = "原价, 单位: 分")
private Integer originalPrice;
@ApiModelProperty(value = "成本价,单位: 分")
private Integer costPrice;
@ApiModelProperty(value = "条形码")
private String barCode;
@ApiModelProperty(value = "图片地址")
private String picUrl;
@ApiModelProperty(value = "状态: 0-正常 1-禁用")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,49 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 商品sku分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSkuPageReqVO extends PageParam {
@ApiModelProperty(value = "spu编号")
private Long spuId;
@ApiModelProperty(value = "规格值数组-json格式 [{propertId: , valueId: }, {propertId: , valueId: }]")
private String properties;
@ApiModelProperty(value = "销售价格,单位:分")
private Integer price;
@ApiModelProperty(value = "原价, 单位: 分")
private Integer originalPrice;
@ApiModelProperty(value = "成本价,单位: 分")
private Integer costPrice;
@ApiModelProperty(value = "条形码")
private String barCode;
@ApiModelProperty(value = "图片地址")
private String picUrl;
@ApiModelProperty(value = "状态: 0-正常 1-禁用")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 商品sku Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSkuRespVO extends ProductSkuBaseVO {
@ApiModelProperty(value = "主键", required = true)
private Long id;
@ApiModelProperty(value = "创建时间")
private Date createTime;
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 商品sku更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSkuUpdateReqVO extends ProductSkuBaseVO {
@ApiModelProperty(value = "主键", required = true)
@NotNull(message = "主键不能为空")
private Long id;
}

View File

@ -0,0 +1,98 @@
package cn.iocoder.yudao.module.product.controller.admin.spu;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Api(tags = "管理后台 - 商品spu")
@RestController
@RequestMapping("/product/spu")
@Validated
public class ProductSpuController {
@Resource
private ProductSpuService spuService;
@PostMapping("/create")
@ApiOperation("创建商品spu")
@PreAuthorize("@ss.hasPermission('product:spu:create')")
public CommonResult<Long> createSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) {
return success(spuService.createSpu(createReqVO));
}
// TODO @frankySpuUpdateReqVO 缺少前缀
@PutMapping("/update")
@ApiOperation("更新商品spu")
@PreAuthorize("@ss.hasPermission('product:spu:update')")
public CommonResult<Boolean> updateSpu(@Valid @RequestBody SpuUpdateReqVO updateReqVO) {
spuService.updateSpu(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除商品spu")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:spu:delete')")
public CommonResult<Boolean> deleteSpu(@RequestParam("id") Long id) {
spuService.deleteSpu(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得商品spu")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<SpuRespVO> getSpu(@RequestParam("id") Long id) {
return success(spuService.getSpu(id));
}
@GetMapping("/list")
@ApiOperation("获得商品spu列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<List<SpuRespVO>> getSpuList(@RequestParam("ids") Collection<Long> ids) {
List<ProductSpuDO> list = spuService.getSpuList(ids);
return success(ProductSpuConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得商品spu分页")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<PageResult<SpuRespVO>> getSpuPage(@Valid SpuPageReqVO pageVO) {
return success(spuService.getSpuPage(pageVO));
}
@GetMapping("/export-excel")
@ApiOperation("导出商品spu Excel")
@PreAuthorize("@ss.hasPermission('product:spu:export')")
@OperateLog(type = EXPORT)
public void exportSpuExcel(@Valid SpuExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<ProductSpuDO> list = spuService.getSpuList(exportReqVO);
// 导出 Excel
List<SpuExcelVO> datas = ProductSpuConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "商品spu.xls", "数据", SpuExcelVO.class, datas);
}
}

View File

@ -0,0 +1,50 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 商品spu Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class ProductSpuBaseVO {
@ApiModelProperty(value = "商品名称")
private String name;
@ApiModelProperty(value = "卖点", required = true)
@NotNull(message = "卖点不能为空")
private String sellPoint;
@ApiModelProperty(value = "描述", required = true)
@NotNull(message = "描述不能为空")
private String description;
@ApiModelProperty(value = "分类id", required = true)
@NotNull(message = "分类id不能为空")
private Long categoryId;
@ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张", required = true)
@NotNull(message = "商品主图地址,* 数组,以逗号分隔,最多上传15张不能为空")
private List<String> picUrls;
@ApiModelProperty(value = "排序字段", required = true)
@NotNull(message = "排序字段不能为空")
private Integer sort;
@ApiModelProperty(value = "点赞初始人数")
private Integer likeCount;
@ApiModelProperty(value = "价格 单位使用:分")
private Integer price;
@ApiModelProperty(value = "库存数量")
private Integer quantity;
@ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)")
private Boolean status;
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.Valid;
import java.util.List;
@ApiModel("管理后台 - 商品spu创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSpuCreateReqVO extends ProductSpuBaseVO {
@ApiModelProperty(value = "sku组合")
@Valid
List<ProductSkuCreateReqVO> skus;
}

View File

@ -0,0 +1,53 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import com.alibaba.excel.annotation.ExcelProperty;
/**
* 商品spu Excel VO
*
* @author 芋道源码
*/
@Data
public class SpuExcelVO {
@ExcelProperty("主键")
private Integer id;
@ExcelProperty("商品名称")
private String name;
@ExcelProperty("卖点")
private String sellPoint;
@ExcelProperty("描述")
private String description;
@ExcelProperty("分类id")
private Long categoryId;
@ExcelProperty("商品主图地址,* 数组,以逗号分隔,最多上传15张")
private List<String> picUrls;
@ExcelProperty("排序字段")
private Integer sort;
@ExcelProperty("点赞初始人数")
private Integer likeCount;
@ExcelProperty("价格 单位使用:分")
private Integer price;
@ExcelProperty("库存数量")
private Integer quantity;
@ExcelProperty("上下架状态: 0 上架(开启) 1 下架(禁用)")
private Boolean status;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@ -0,0 +1,53 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - 商品spu Excel 导出 Request VO", description = "参数和 SpuPageReqVO 是一致的")
@Data
public class SpuExportReqVO {
@ApiModelProperty(value = "商品名称")
private String name;
@ApiModelProperty(value = "卖点")
private String sellPoint;
@ApiModelProperty(value = "描述")
private String description;
@ApiModelProperty(value = "分类id")
private Long categoryId;
@ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张")
private List<String> picUrls;
@ApiModelProperty(value = "排序字段")
private Integer sort;
@ApiModelProperty(value = "点赞初始人数")
private Integer likeCount;
@ApiModelProperty(value = "价格 单位使用:分")
private Integer price;
@ApiModelProperty(value = "库存数量")
private Integer quantity;
@ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)")
private Boolean status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 商品spu分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SpuPageReqVO extends PageParam {
@ApiModelProperty(value = "商品名称")
private String name;
@ApiModelProperty(value = "卖点")
private String sellPoint;
@ApiModelProperty(value = "描述")
private String description;
@ApiModelProperty(value = "分类id")
private Long categoryId;
@ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张")
private String picUrls;
@ApiModelProperty(value = "排序字段")
private Integer sort;
@ApiModelProperty(value = "点赞初始人数")
private Integer likeCount;
@ApiModelProperty(value = "价格 单位使用:分")
private Integer price;
@ApiModelProperty(value = "库存数量")
private Integer quantity;
@ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)")
private Boolean status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
@ApiModel("管理后台 - 商品spu Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SpuRespVO extends ProductSpuBaseVO {
// TODO @franky注解要完整
@ApiModelProperty(value = "主键", required = true)
private Long id;
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**
* SKU 数组
*/
List<ProductSkuRespVO> skus;
@ApiModelProperty(value = "分类id数组一直递归到一级父节点", example = "[1,2,4]")
LinkedList<Long> categoryIds;
}

View File

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.Valid;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 商品spu更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SpuUpdateReqVO extends ProductSpuBaseVO {
@ApiModelProperty(value = "主键", required = true)
@NotNull(message = "主键不能为空")
private Long id;
@ApiModelProperty(value = "sku组合")
@Valid
List<ProductSkuCreateReqVO> skus;
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.product.convert.brand;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*;
import cn.iocoder.yudao.module.product.dal.dataobject.brand.BrandDO;
/**
* 品牌 Convert
*
* @author 芋道源码
*/
@Mapper
public interface BrandConvert {
BrandConvert INSTANCE = Mappers.getMapper(BrandConvert.class);
BrandDO convert(BrandCreateReqVO bean);
BrandDO convert(BrandUpdateReqVO bean);
BrandRespVO convert(BrandDO bean);
List<BrandRespVO> convertList(List<BrandDO> list);
PageResult<BrandRespVO> convertPage(PageResult<BrandDO> page);
List<BrandExcelVO> convertList02(List<BrandDO> list);
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.product.convert.category;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.product.controller.admin.category.vo.*;
import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
/**
* 商品分类 Convert
*
* @author 芋道源码
*/
@Mapper
public interface CategoryConvert {
CategoryConvert INSTANCE = Mappers.getMapper(CategoryConvert.class);
CategoryDO convert(CategoryCreateReqVO bean);
CategoryDO convert(CategoryUpdateReqVO bean);
CategoryRespVO convert(CategoryDO bean);
List<CategoryRespVO> convertList(List<CategoryDO> list);
PageResult<CategoryRespVO> convertPage(PageResult<CategoryDO> page);
List<CategoryExcelVO> convertList02(List<CategoryDO> list);
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.product.convert.property;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.*;
/**
* 规格名称 Convert
*
* @author 芋道源码
*/
@Mapper
public interface ProductPropertyConvert {
ProductPropertyConvert INSTANCE = Mappers.getMapper(ProductPropertyConvert.class);
ProductPropertyDO convert(ProductPropertyCreateReqVO bean);
ProductPropertyDO convert(ProductPropertyUpdateReqVO bean);
ProductPropertyRespVO convert(ProductPropertyDO bean);
List<ProductPropertyRespVO> convertList(List<ProductPropertyDO> list);
PageResult<ProductPropertyRespVO> convertPage(PageResult<ProductPropertyDO> page);
List<ProductPropertyExcelVO> convertList02(List<ProductPropertyDO> list);
}

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