初始化

This commit is contained in:
OPGame
2019-07-04 10:24:32 +08:00
parent a4df532316
commit daf1372481
563 changed files with 38885 additions and 0 deletions

4
CHANGELOG.md Normal file
View File

@@ -0,0 +1,4 @@
### 1.0.0
*2019-07-02*

108
README.md Normal file
View File

@@ -0,0 +1,108 @@
一个基于spring boot、spring oauth2.0、mybatis、redis的轻量级、前后端分离、拥有完整sku和下单流程的完全开源商城
该项目仅供学习参考、可供个人学习使用、如需商用联系作者进行授权,否则必将追究法律责任
## 前言
`亚米商城`项目致力于为中小企业打造一个完整、易于维护的开源的电商系统,采用现阶段流行技术实现。后台管理系统包含商品管理、订单管理、运费模板、规格管理、会员管理、运营管理、内容管理、统计报表、权限管理、设置等模块。
## 项目链接
java后台https://gitee.com/gz-yami/mall4j
vue后台https://gitee.com/gz-yami/mall4v
小程序https://gitee.com/gz-yami/mall4m
## 演示地址
后台:<http://mall4j-admin.gz-yami.com> 账号admin/123456
小程序1. 扫描二维码
![小程序](https://gitee.com/gz-yami/mall4j/raw/master/screenshot/miniQrcode.jpg)
2. 搜索小程序 **亚米商城**
## 技术选型
| 技术 | 版本 | 说明 |
| ---------------------- | ------ | --------------------------------------- |
| Spring Boot | 2.1.6 | MVC核心框架 |
| Spring Security oauth2 | 2.1.5 | 认证和授权框架 |
| MyBatis | 3.5.0 | ORM框架 |
| MyBatisPlus | 3.1.0 | 基于mybatis使用lambda表达式的 |
| Swagger-UI | 2.9.2 | 文档生产工具 |
| Hibernator-Validator | 6.0.17 | 验证框架 |
| redisson | 3.10.6 | 对redis进行封装、集成分布式锁等 |
| hikari | 3.2.0 | 数据库连接池 |
| log4j2 | 2.11.2 | 更快的log日志工具 |
| fst | 2.57 | 更快的序列化和反序列化工具 |
| orika | 1.5.4 | 更快的bean复制工具 |
| lombok | 1.18.8 | 简化对象封装工具 |
| hutool | 4.5.0 | 更适合国人的java工具集 |
| swagger-bootstrap | 1.9.3 | 基于swagger更便于国人使用的swagger ui |
## 部署教程
### 1.开发环境
| 工具 | 版本 |
| ----- | ---- |
| jdk | 1.8+ |
| mysql | 5.7+ |
| redis | 3.2+ |
### 2.启动
- 推荐使用idea安装lombok插件后使用idea导入maven项目
- 将shop.sql导入到mysql中修改`application-dev.yml`更改 datasource.url、user、password
- 通过修改`ma.properties` 修改微信小程序信息
- 通过修改`mp.properties` 修改微信公众号信息
- 通过修改`pay.properties` 修改微信支付信息
- 通过修改`shop.properties` 修改七牛云、阿里大于等信息
- 修改`api.properties` 修改当前接口所在域名,用于支付回调
- 启动redis端口6379
- 通过`WebApplication`启动项目后台接口,`ApiApplication` 启动项目前端接口
## 相关截图
![登陆](https://gitee.com/gz-yami/mall4j/raw/master/screenshot/login.png)
![订单](https://gitee.com/gz-yami/mall4j/raw/master/screenshot/order.png)
![商品列表](https://gitee.com/gz-yami/mall4j/raw/master/screenshot/prodList.png)
![sku](https://gitee.com/gz-yami/mall4j/raw/master/screenshot/sku.png)
![运费模板](https://gitee.com/gz-yami/mall4j/raw/master/screenshot/transport.png)
## 提交反馈
提问之前,请先阅读[提问的智慧](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md)
- QQ群722835385
![QQ群](https://gitee.com/gz-yami/mall4j/raw/master/screenshot/qqGroup.png)
- 论坛:<http://bbs.gz-yami.com>
- 商务邮箱yamitech@163.com

6351
db/yami_shop.sql Normal file

File diff suppressed because it is too large Load Diff

209
pom.xml Normal file
View File

@@ -0,0 +1,209 @@
<?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>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>yami-shop-admin</module>
<module>yami-shop-sys</module>
<module>yami-shop-common</module>
<module>yami-shop-api</module>
<module>yami-shop-bean</module>
<module>yami-shop-service</module>
<module>yami-shop-security</module>
<module>yami-shop-quartz</module>
<module>yami-shop-mp</module>
</modules>
<properties>
<yami.shop.version>0.0.1-SNAPSHOT</yami.shop.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.plugin.version>3.7.0</maven.compiler.plugin.version>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
<security.oauth.auto.version>2.1.5.RELEASE</security.oauth.auto.version>
<java.version>1.8</java.version>
<guava.version>20.0</guava.version>
<hutool.version>4.5.0</hutool.version>
<jsoup.version>1.11.3</jsoup.version>
<poi.version>3.17</poi.version>
<qiniu.version>7.2.18</qiniu.version>
<weixin.version>3.4.0</weixin.version>
<orika.version>1.5.4</orika.version>
<swagger2.version>2.9.2</swagger2.version>
<swagger-bootstrap.version>1.9.3</swagger-bootstrap.version>
<emoji.version>4.0.0</emoji.version>
<aliyun-core.version>4.3.9</aliyun-core.version>
<aliyun-dysmsapi.version>1.1.0</aliyun-dysmsapi.version>
<mybatis-plus.version>3.1.0</mybatis-plus.version>
<redisson.version>3.10.6</redisson.version>
<fst.version>2.57</fst.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>${security.oauth.auto.version}</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>${weixin.version}</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>${weixin.version}</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>${weixin.version}</version>
</dependency>
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>${orika.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>${swagger-bootstrap.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>${aliyun-core.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>${aliyun-dysmsapi.version}</version>
</dependency>
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>emoji-java</artifactId>
<version>${emoji.version}</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>${qiniu.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!-- 使用redisson集成分布式锁等 -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>${redisson.version}</version>
</dependency>
<!-- 用于序列化和反序列化-->
<dependency>
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
<version>${fst.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>aliyun</id>
<name>aliyun</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

BIN
screenshot/login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

BIN
screenshot/miniQrcode.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
screenshot/order.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

BIN
screenshot/prodList.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

BIN
screenshot/qqGroup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
screenshot/sku.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
screenshot/transport.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

65
yami-shop-admin/pom.xml Normal file
View File

@@ -0,0 +1,65 @@
<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>
<artifactId>yami-shop-admin</artifactId>
<parent>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-service</artifactId>
<version>${yami.shop.version}</version>
</dependency>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-sys</artifactId>
<version>${yami.shop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-security</artifactId>
<version>${yami.shop.version}</version>
</dependency>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-quartz</artifactId>
<version>${yami.shop.version}</version>
</dependency>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-mp</artifactId>
<version>${yami.shop.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
/**
* @author lgh
*/
@SpringBootApplication
@ComponentScan("com.yami.shop")
public class WebApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(WebApplication.class);
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.config;
import cn.hutool.core.lang.Snowflake;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@AllArgsConstructor
public class AdminBeanConfig {
private final AdminConfig adminConfig;
@Bean
public Snowflake snowflake() {
return new Snowflake(adminConfig.getWorkerId(), adminConfig.getDatacenterId());
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
/**
* 商城配置文件
* @author lgh
*/
@Data
@Component
@PropertySource("classpath:admin.properties")
@ConfigurationProperties(prefix = "admin")
public class AdminConfig {
/**
* 数据中心ID
*/
private Integer datacenterId;
/**
* 终端ID
*/
private Integer workerId;
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger文档只有在测试环境才会使用
* @author LGH
*/
//@Profile("dev")
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.yami"))
.paths(PathSelectors.any())
.build();
}
@Bean
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("亚米管理系统接口文档")
.description("亚米商城接口文档Swagger版")
.termsOfServiceUrl("https://www.gz-yami.com/")
.contact(new Contact("广州亚米信息科技有限公司","https://www.gz-yami.com/", ""))
.version("1.0")
.build();
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.model.Area;
import com.yami.shop.service.AreaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
/**
* @author lgh on 2018/10/26.
*/
@RestController
@RequestMapping("/admin/area")
public class AreaController {
@Autowired
private AreaService areaService;
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('admin:area:page')")
public ResponseEntity<IPage<Area>> page(Area area,PageParam<Area> page) {
IPage<Area> sysUserPage = areaService.page(page, new LambdaQueryWrapper<Area>());
return ResponseEntity.ok(sysUserPage);
}
/**
* 获取省市
*/
@GetMapping("/list")
@PreAuthorize("@pms.hasPermission('admin:area:list')")
public ResponseEntity<List<Area>> list(Area area) {
List<Area> areas = areaService.list(new LambdaQueryWrapper<Area>()
.like(area.getAreaName() != null, Area::getAreaName, area.getAreaName()));
return ResponseEntity.ok(areas);
}
/**
* 通过父级id获取区域列表
*/
@GetMapping("/listByPid")
public ResponseEntity<List<Area>> listByPid(Long pid) {
List<Area> list = areaService.listByPid(pid);
return ResponseEntity.ok(list);
}
/**
* 获取信息
*/
@GetMapping("/info/{id}")
@PreAuthorize("@pms.hasPermission('admin:area:info')")
public ResponseEntity<Area> info(@PathVariable("id") Long id) {
Area area = areaService.getById(id);
return ResponseEntity.ok(area);
}
/**
* 保存
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('admin:area:save')")
public ResponseEntity<Void> save(@Valid @RequestBody Area area) {
if (area.getParentId() != null) {
Area parentArea = areaService.getById(area.getParentId());
area.setLevel(parentArea.getLevel() + 1);
areaService.removeAreaCacheByParentId(area.getParentId());
}
areaService.save(area);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('admin:area:update')")
public ResponseEntity<Void> update(@Valid @RequestBody Area area) {
areaService.updateById(area);
areaService.removeAreaCacheByParentId(area.getParentId());
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping("/{id}")
@PreAuthorize("@pms.hasPermission('admin:area:delete')")
public ResponseEntity<Void> delete(@PathVariable Long id) {
Area area = areaService.getById(id);
areaService.removeById(id);
areaService.removeAreaCacheByParentId(area.getParentId());
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import java.util.Objects;
import javax.validation.Valid;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.common.enums.YamiHttpStatus;
import com.yami.shop.security.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.bean.enums.ProdPropRule;
import com.yami.shop.bean.model.ProdProp;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.service.ProdPropService;
import com.baomidou.mybatisplus.core.metadata.IPage;
/**
* 参数管理
* @author lgh
*/
@RestController
@RequestMapping("/admin/attribute")
public class AttributeController {
@Autowired
private ProdPropService prodPropService;
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('admin:attribute:page')")
public ResponseEntity<IPage<ProdProp>> page(ProdProp prodProp,PageParam<ProdProp> page){
prodProp.setRule(ProdPropRule.ATTRIBUTE.value());
prodProp.setShopId(SecurityUtils.getSysUser().getShopId());
IPage<ProdProp> prodPropIPage = prodPropService.pagePropAndValue(prodProp,page);
return ResponseEntity.ok(prodPropIPage);
}
/**
* 获取信息
*/
@GetMapping("/info/{id}")
@PreAuthorize("@pms.hasPermission('admin:attribute:info')")
public ResponseEntity<ProdProp> info(@PathVariable("id") Long id){
ProdProp prodProp = prodPropService.getById(id);
return ResponseEntity.ok(prodProp);
}
/**
* 保存
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('admin:attribute:save')")
public ResponseEntity<Void> save(@Valid ProdProp prodProp){
prodProp.setRule(ProdPropRule.ATTRIBUTE.value());
prodProp.setShopId(SecurityUtils.getSysUser().getShopId());
prodPropService.saveProdPropAndValues(prodProp);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('admin:attribute:update')")
public ResponseEntity<Void> update(@Valid ProdProp prodProp){
ProdProp dbProdProp = prodPropService.getById(prodProp.getPropId());
if (!Objects.equals(dbProdProp.getShopId(), SecurityUtils.getSysUser().getShopId())) {
throw new YamiShopBindException("没有权限获取该商品规格信息");
}
prodProp.setRule(ProdPropRule.ATTRIBUTE.value());
prodProp.setShopId(SecurityUtils.getSysUser().getShopId());
prodPropService.updateProdPropAndValues(prodProp);
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping("/{id}")
@PreAuthorize("@pms.hasPermission('admin:attribute:delete')")
public ResponseEntity<Void> delete(@PathVariable Long id){
prodPropService.deleteProdPropAndValues(id,ProdPropRule.ATTRIBUTE.value(),SecurityUtils.getSysUser().getShopId());
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.Brand;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.service.BrandService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Objects;
/**
* 品牌管理
*
* @author lgh
*/
@RestController
@RequestMapping("/admin/brand")
public class BrandController {
@Autowired
private BrandService brandService;
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('admin:brand:page')")
public ResponseEntity<IPage<Brand>> page(Brand brand,PageParam<Brand> page) {
page.setAsc("first_char");
IPage<Brand> brands = brandService.page(page,
new LambdaQueryWrapper<Brand>()
.like(StrUtil.isNotBlank(brand.getBrandName()), Brand::getBrandName, brand.getBrandName()));
return ResponseEntity.ok(brands);
}
/**
* 获取信息
*/
@GetMapping("/info/{id}")
@PreAuthorize("@pms.hasPermission('admin:brand:info')")
public ResponseEntity<Brand> info(@PathVariable("id") Long id) {
Brand brand = brandService.getById(id);
return ResponseEntity.ok(brand);
}
/**
* 保存
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('admin:brand:save')")
public ResponseEntity<?> save(@Valid Brand brand) {
Brand dbBrand = brandService.getByBrandName(brand.getBrandName());
if (dbBrand != null) {
return ResponseEntity.badRequest().body("该品牌名称已存在");
}
brandService.save(brand);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('admin:brand:update')")
public ResponseEntity<?> update(@Valid Brand brand) {
Brand dbBrand = brandService.getByBrandName(brand.getBrandName());
if (dbBrand != null && !Objects.equals(dbBrand.getBrandId(), brand.getBrandId())) {
return ResponseEntity.badRequest().body("该品牌名称已存在");
}
brandService.updateById(brand);
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping("/{id}")
@PreAuthorize("@pms.hasPermission('admin:brand:delete')")
public ResponseEntity<Void> delete(@PathVariable Long id) {
brandService.deleteByBrand(id);
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.security.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.bean.model.Category;
import com.yami.shop.common.annotation.SysLog;
import com.yami.shop.service.BrandService;
import com.yami.shop.service.CategoryService;
import com.yami.shop.service.ProdPropService;
import cn.hutool.core.collection.CollectionUtil;
/**
* 分类管理
* @author lgh
*
*/
@RestController
@RequestMapping("/prod/category")
public class CategoryController {
@Autowired
private CategoryService categoryService;
/**
* 获取菜单页面的表
* @return
*/
@GetMapping("/table")
@PreAuthorize("@pms.hasPermission('prod:category:page')")
public ResponseEntity<List<Category>> table(){
List<Category> categoryMenuList = categoryService.tableCategory(SecurityUtils.getSysUser().getShopId());
return ResponseEntity.ok(categoryMenuList);
}
/**
* 获取分类信息
*/
@GetMapping("/info/{categoryId}")
public ResponseEntity<Category> info(@PathVariable("categoryId") Long categoryId){
Category category = categoryService.getById(categoryId);
return ResponseEntity.ok(category);
}
/**
* 保存分类
*/
@SysLog("保存分类")
@PostMapping
@PreAuthorize("@pms.hasPermission('prod:category:save')")
public ResponseEntity<Void> save(@RequestBody Category category){
category.setShopId(SecurityUtils.getSysUser().getShopId());
category.setRecTime(new Date());
categoryService.saveCategroy(category);
return ResponseEntity.ok().build();
}
/**
* 更新分类
*/
@SysLog("更新分类")
@PutMapping
@PreAuthorize("@pms.hasPermission('prod:category:update')")
public ResponseEntity<String> update(@RequestBody Category category){
category.setShopId(SecurityUtils.getSysUser().getShopId());
if (Objects.equals(category.getParentId(),category.getCategoryId())) {
return ResponseEntity.badRequest().body("分类的上级不能是自己本身");
}
categoryService.updateCategroy(category);
return ResponseEntity.ok().build();
}
/**
* 删除分类
*/
@SysLog("删除分类")
@DeleteMapping("/{categoryId}")
@PreAuthorize("@pms.hasPermission('prod:category:delete')")
public ResponseEntity<String> delete(@PathVariable("categoryId") Long categoryId){
if (CollectionUtil.isNotEmpty(categoryService.listByParentId(categoryId))) {
return ResponseEntity.badRequest().body("请删除子分类,再删除该分类");
}
categoryService.deleteCategroy(categoryId);
return ResponseEntity.ok().build();
}
/**
* 所有的
*/
@GetMapping("/listCategory")
public ResponseEntity<List<Category>> listCategory(){
return ResponseEntity.ok(categoryService.list(new LambdaQueryWrapper<Category>()
.le(Category::getGrade, 2)
.eq(Category::getShopId, SecurityUtils.getSysUser().getShopId())
.orderByAsc(Category::getSeq)));
}
/**
* 所有的产品分类
*/
@GetMapping("/listProdCategory")
public ResponseEntity<List<Category>> listProdCategory(){
List<Category> categories = categoryService.treeSelect(SecurityUtils.getSysUser().getShopId(),2);
return ResponseEntity.ok(categories);
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.bean.model.Delivery;
import com.yami.shop.service.DeliveryService;
/**
*
* @author lgh on 2018/11/26.
*/
@RestController
@RequestMapping("/admin/delivery")
public class DeliveryController {
@Autowired
private DeliveryService deliveryService;
/**
* 分页获取
*/
@GetMapping("/list")
public ResponseEntity<List<Delivery>> page(){
List<Delivery> list = deliveryService.list();
return ResponseEntity.ok(list);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.yami.shop.bean.dto.TinymceEditorDto;
import com.yami.shop.common.bean.Qiniu;
import com.yami.shop.service.AttachFileService;
/**
* 文件上传 controller
* @author lgh
*
*/
@RestController
@RequestMapping("/admin/file")
public class FileController {
@Autowired
private AttachFileService attachFileService;
@Autowired
private Qiniu qiniu;
@PostMapping("/upload/element")
public ResponseEntity<String> uploadElementFile(@RequestParam("file") MultipartFile file) throws IOException{
if(file.isEmpty()){
return ResponseEntity.noContent().build();
}
String fileName = attachFileService.uploadFile(file.getBytes(),file.getOriginalFilename());
return ResponseEntity.ok(fileName);
}
@PostMapping("/upload/tinymceEditor")
public ResponseEntity<String> uploadTinymceEditorImages(@RequestParam("editorFile") MultipartFile editorFile) throws IOException{
String fileName = attachFileService.uploadFile(editorFile.getBytes(),editorFile.getOriginalFilename());
return ResponseEntity.ok(qiniu.getResourcesUrl() + fileName);
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.security.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.service.HotSearchService;
import com.yami.shop.bean.model.HotSearch;
/**
*
* @author lgh on 2019/03/27.
*/
@RestController
@RequestMapping("/admin/hotSearch")
public class HotSearchController {
@Autowired
private HotSearchService hotSearchService;
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('admin:hotSearch:page')")
public ResponseEntity<IPage<HotSearch>> page(HotSearch hotSearch,PageParam<HotSearch> page){
IPage<HotSearch> hotSearchs = hotSearchService.page(page,new LambdaQueryWrapper<HotSearch>()
.eq(HotSearch::getShopId, SecurityUtils.getSysUser().getShopId())
.like(StrUtil.isNotBlank(hotSearch.getContent()), HotSearch::getContent,hotSearch.getContent())
.like(StrUtil.isNotBlank(hotSearch.getTitle()), HotSearch::getTitle,hotSearch.getTitle())
.eq(hotSearch.getStatus()!=null, HotSearch::getStatus,hotSearch.getStatus())
);
return ResponseEntity.ok(hotSearchs);
}
/**
* 获取信息
*/
@GetMapping("/info/{id}")
@PreAuthorize("@pms.hasPermission('admin:hotSearch:info')")
public ResponseEntity<HotSearch> info(@PathVariable("id") Long id){
HotSearch hotSearch = hotSearchService.getById(id);
return ResponseEntity.ok(hotSearch);
}
/**
* 保存
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('admin:hotSearch:save')")
public ResponseEntity<Void> save(@RequestBody @Valid HotSearch hotSearch){
hotSearch.setRecDate(new Date());
hotSearch.setShopId(SecurityUtils.getSysUser().getShopId());
hotSearchService.save(hotSearch);
//清除缓存
hotSearchService.removeHotSearchDtoCacheByshopId(SecurityUtils.getSysUser().getShopId());
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('admin:hotSearch:update')")
public ResponseEntity<Void> update(@RequestBody @Valid HotSearch hotSearch){
hotSearchService.updateById(hotSearch);
//清除缓存
hotSearchService.removeHotSearchDtoCacheByshopId(SecurityUtils.getSysUser().getShopId());
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping
@PreAuthorize("@pms.hasPermission('admin:hotSearch:delete')")
public ResponseEntity<Void> delete(@RequestBody List<Long> ids){
hotSearchService.removeByIds(ids);
//清除缓存
hotSearchService.removeHotSearchDtoCacheByshopId(SecurityUtils.getSysUser().getShopId());
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.IndexImg;
import com.yami.shop.bean.model.Product;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.IndexImgService;
import com.yami.shop.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Date;
import java.util.Objects;
/**
* @author lgh on 2018/11/26.
*/
@RestController
@RequestMapping("/admin/indexImg")
public class IndexImgController {
@Autowired
private IndexImgService indexImgService;
@Autowired
private ProductService productService;
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('admin:indexImg:page')")
public ResponseEntity<IPage<IndexImg>> page(IndexImg indexImg, PageParam<IndexImg> page) {
IPage<IndexImg> indexImgIPage = indexImgService.page(page,
new LambdaQueryWrapper<IndexImg>()
.eq(indexImg.getStatus() != null, IndexImg::getStatus, indexImg.getStatus())
.orderByDesc(IndexImg::getSeq));
return ResponseEntity.ok(indexImgIPage);
}
/**
* 获取信息
*/
@GetMapping("/info/{imgId}")
@PreAuthorize("@pms.hasPermission('admin:indexImg:info')")
public ResponseEntity<IndexImg> info(@PathVariable("imgId") Long imgId) {
Long shopId = SecurityUtils.getSysUser().getShopId();
IndexImg indexImg = indexImgService.getOne(new LambdaQueryWrapper<IndexImg>().eq(IndexImg::getShopId, shopId).eq(IndexImg::getImgId, imgId));
if (Objects.nonNull(indexImg.getRelation())) {
Product product = productService.getProductByProdId(indexImg.getRelation());
indexImg.setPic(product.getPic());
indexImg.setProdName(product.getProdName());
}
return ResponseEntity.ok(indexImg);
}
/**
* 保存
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('admin:indexImg:save')")
public ResponseEntity<Void> save(@RequestBody @Valid IndexImg indexImg) {
Long shopId = SecurityUtils.getSysUser().getShopId();
indexImg.setShopId(shopId);
indexImg.setUploadTime(new Date());
indexImgService.save(indexImg);
indexImgService.removeIndexImgs();
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('admin:indexImg:update')")
public ResponseEntity<Void> update(@RequestBody @Valid IndexImg indexImg) {
indexImgService.updateById(indexImg);
indexImgService.removeIndexImgs();
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping
@PreAuthorize("@pms.hasPermission('admin:indexImg:delete')")
public ResponseEntity<Void> delete(@RequestBody Long[] ids) {
indexImgService.deleteIndexImgsByIds(ids);
indexImgService.removeIndexImgs();
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import java.util.Arrays;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.enums.MessageStatus;
import com.yami.shop.bean.model.Message;
import com.yami.shop.service.MessageService;
import cn.hutool.core.util.StrUtil;
/**
* @author lgh on 2018/10/15.
*/
@RestController
@RequestMapping("/admin/message")
public class MessageController {
@Autowired
private MessageService messageService;
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('admin:message:page')")
public ResponseEntity<IPage<Message>> page(Message message,PageParam<Message> page) {
IPage<Message> messages = messageService.page(page, new LambdaQueryWrapper<Message>()
.like(StrUtil.isNotBlank(message.getUserName()), Message::getUserName, message.getUserName())
.eq(message.getStatus() != null, Message::getStatus, message.getStatus()));
return ResponseEntity.ok(messages);
}
/**
* 获取信息
*/
@GetMapping("/info/{id}")
@PreAuthorize("@pms.hasPermission('admin:message:info')")
public ResponseEntity<Message> info(@PathVariable("id") Long id) {
Message message = messageService.getById(id);
return ResponseEntity.ok(message);
}
/**
* 保存
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('admin:message:save')")
public ResponseEntity<Void> save(@RequestBody Message message) {
messageService.save(message);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('admin:message:update')")
public ResponseEntity<Void> update(@RequestBody Message message) {
messageService.updateById(message);
return ResponseEntity.ok().build();
}
/**
* 公开留言
*/
@PutMapping("/release/{id}")
@PreAuthorize("@pms.hasPermission('admin:message:release')")
public ResponseEntity<Void> release(@PathVariable("id") Long id) {
Message message = new Message();
message.setId(id);
message.setStatus(MessageStatus.RELEASE.value());
messageService.updateById(message);
return ResponseEntity.ok().build();
}
/**
* 取消公开留言
*/
@PutMapping("/cancel/{id}")
@PreAuthorize("@pms.hasPermission('admin:message:cancel')")
public ResponseEntity<Void> cancel(@PathVariable("id") Long id) {
Message message = new Message();
message.setId(id);
message.setStatus(MessageStatus.CANCEL.value());
messageService.updateById(message);
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping("/{ids}")
@PreAuthorize("@pms.hasPermission('admin:message:delete')")
public ResponseEntity<Void> delete(@PathVariable Long[] ids) {
messageService.removeByIds(Arrays.asList(ids));
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.model.Notice;
import com.yami.shop.common.annotation.SysLog;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.NoticeService;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Date;
/**
* 公告管理
*
* @author hzm
* @date
*/
@RestController
@AllArgsConstructor
@RequestMapping("/shop/notice")
public class NoticeController {
private final NoticeService noticeService;
/**
* 分页查询
*
* @param page 分页对象
* @param notice 公告管理
* @return 分页数据
*/
@GetMapping("/page")
public ResponseEntity<IPage<Notice>> getNoticePage(PageParam<Notice> page, Notice notice) {
IPage<Notice> noticeIPage = noticeService.page(page, new LambdaQueryWrapper<Notice>()
.eq(notice.getStatus() != null, Notice::getStatus, notice.getStatus())
.like(notice.getTitle() != null, Notice::getTitle, notice.getTitle()).orderByDesc(Notice::getUpdateTime));
return ResponseEntity.ok(noticeIPage);
}
/**
* 通过id查询公告管理
*
* @param id id
* @return 单个数据
*/
@GetMapping("/info/{id}")
public ResponseEntity<Notice> getById(@PathVariable("id") Long id) {
return ResponseEntity.ok(noticeService.getById(id));
}
/**
* 新增公告管理
*
* @param notice 公告管理
* @return 是否新增成功
*/
@SysLog("新增公告管理")
@PostMapping
@PreAuthorize("@pms.hasPermission('shop:notice:save')")
public ResponseEntity<Boolean> save(@RequestBody @Valid Notice notice) {
notice.setShopId(SecurityUtils.getSysUser().getShopId());
if (notice.getStatus() == 1) {
notice.setPublishTime(new Date());
}
notice.setUpdateTime(new Date());
noticeService.removeNoticeList();
return ResponseEntity.ok(noticeService.save(notice));
}
/**
* 修改公告管理
*
* @param notice 公告管理
* @return 是否修改成功
*/
@SysLog("修改公告管理")
@PutMapping
@PreAuthorize("@pms.hasPermission('shop:notice:update')")
public ResponseEntity<Boolean> updateById(@RequestBody @Valid Notice notice) {
Notice oldNotice = noticeService.getById(notice.getId());
if (oldNotice.getStatus() == 0 && notice.getStatus() == 1) {
notice.setPublishTime(new Date());
}
notice.setUpdateTime(new Date());
noticeService.removeNoticeList();
noticeService.removeNoticeById(notice.getId());
return ResponseEntity.ok(noticeService.updateById(notice));
}
/**
* 通过id删除公告管理
*
* @param id id
* @return 是否删除成功
*/
@SysLog("删除公告管理")
@DeleteMapping("/{id}")
@PreAuthorize("@pms.hasPermission('shop:notice:delete')")
public ResponseEntity<Boolean> removeById(@PathVariable Long id) {
noticeService.removeNoticeList();
noticeService.removeNoticeById(id);
return ResponseEntity.ok(noticeService.removeById(id));
}
}

View File

@@ -0,0 +1,297 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import com.yami.shop.bean.param.OrderParam;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.*;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.base.Objects;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.OrderItem;
import com.yami.shop.bean.model.UserAddrOrder;
import com.yami.shop.bean.param.DeliveryOrderParam;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
/**
* @author lgh on 2018/09/15.
*/
@Controller
@RequestMapping("/order/order")
public class OrderController {
@Autowired
private OrderService orderService;
@Autowired
private OrderItemService orderItemService;
@Autowired
private UserAddrOrderService userAddrOrderService;
@Autowired
private ProductService productService;
@Autowired
private SkuService skuService;
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('order:order:page')")
public ResponseEntity<IPage<Order>> page(OrderParam orderParam,PageParam<Order> page) {
Long shopId = SecurityUtils.getSysUser().getShopId();
orderParam.setShopId(shopId);
IPage<Order> orderIPage = orderService.pageOrdersDetialByOrderParam(page, orderParam);
return ResponseEntity.ok(orderIPage);
}
/**
* 获取信息
*/
@GetMapping("/orderInfo/{orderNumber}")
@PreAuthorize("@pms.hasPermission('order:order:info')")
public ResponseEntity<Order> info(@PathVariable("orderNumber") String orderNumber) {
Long shopId = SecurityUtils.getSysUser().getShopId();
Order order = orderService.getOrderByOrderNumber(orderNumber);
if (!Objects.equal(shopId, order.getShopId())) {
throw new YamiShopBindException("您没有权限获取该订单信息");
}
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
order.setOrderItems(orderItems);
UserAddrOrder userAddrOrder = userAddrOrderService.getById(order.getAddrOrderId());
order.setUserAddrOrder(userAddrOrder);
return ResponseEntity.ok(order);
}
/**
* 发货
*/
@PutMapping("/delivery")
@PreAuthorize("@pms.hasPermission('order:order:delivery')")
public ResponseEntity<Void> delivery(@RequestBody DeliveryOrderParam deliveryOrderParam) {
Long shopId = SecurityUtils.getSysUser().getShopId();
Order order = orderService.getOrderByOrderNumber(deliveryOrderParam.getOrderNumber());
if (!Objects.equal(shopId, order.getShopId())) {
throw new YamiShopBindException("您没有权限修改该订单信息");
}
Order orderParam = new Order();
orderParam.setOrderId(order.getOrderId());
orderParam.setDvyId(deliveryOrderParam.getDvyId());
orderParam.setDvyFlowId(deliveryOrderParam.getDvyFlowId());
orderParam.setDvyTime(new Date());
orderParam.setStatus(OrderStatus.CONSIGNMENT.value());
orderParam.setUserId(order.getUserId());
orderService.delivery(orderParam);
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(deliveryOrderParam.getOrderNumber());
for (OrderItem orderItem : orderItems) {
productService.removeProductCacheByProdId(orderItem.getProdId());
skuService.removeSkuCacheBySkuId(orderItem.getSkuId(),orderItem.getProdId());
}
return ResponseEntity.ok().build();
}
/**
* 打印待发货的订单表
*
* @param order
* @param consignmentName 发件人姓名
* @param consignmentMobile 发货人手机号
* @param consignmentAddr 发货地址
*/
@GetMapping("/waitingConsignmentExcel")
@PreAuthorize("@pms.hasPermission('order:order:waitingConsignmentExcel')")
public void waitingConsignmentExcel(Order order, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime,
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime, String consignmentName, String consignmentMobile,
String consignmentAddr, HttpServletResponse response) {
Long shopId = SecurityUtils.getSysUser().getShopId();
order.setShopId(shopId);
order.setStatus(OrderStatus.PADYED.value());
List<Order> orders = orderService.listOrdersDetialByOrder(order, startTime, endTime);
//通过工具类创建writer
ExcelWriter writer = ExcelUtil.getWriter();
Sheet sheet = writer.getSheet();
sheet.setColumnWidth(0, 20 * 256);
sheet.setColumnWidth(1, 20 * 256);
sheet.setColumnWidth(2, 20 * 256);
sheet.setColumnWidth(3, 60 * 256);
sheet.setColumnWidth(4, 60 * 256);
sheet.setColumnWidth(7, 60 * 256);
sheet.setColumnWidth(8, 60 * 256);
sheet.setColumnWidth(9, 60 * 256);
// 待发货
String[] hearder = {"订单编号", "收件人", "手机", "收货地址", "商品名称", "数量", "发件人姓名", "发件人手机号", "发货地址", "备注"};
writer.merge(hearder.length - 1, "发货信息整理");
writer.writeRow(Arrays.asList(hearder));
int row = 1;
for (Order dbOrder : orders) {
UserAddrOrder addr = dbOrder.getUserAddrOrder();
String addrInfo = addr.getProvince() + addr.getCity() + addr.getArea() + addr.getAddr();
List<OrderItem> orderItems = dbOrder.getOrderItems();
row++;
for (OrderItem orderItem : orderItems) {
// 第0列开始
int col = 0;
writer.writeCellValue(col++, row, dbOrder.getOrderNumber());
writer.writeCellValue(col++, row, addr.getReceiver());
writer.writeCellValue(col++, row, addr.getMobile());
writer.writeCellValue(col++, row, addrInfo);
writer.writeCellValue(col++, row, orderItem.getProdName());
writer.writeCellValue(col++, row, orderItem.getProdCount());
writer.writeCellValue(col++, row, consignmentName);
writer.writeCellValue(col++, row, consignmentMobile);
writer.writeCellValue(col++, row, consignmentAddr);
writer.writeCellValue(col++, row, dbOrder.getRemarks());
}
}
writeExcel(response, writer);
}
/**
* 已销售订单
*
* @param order
*/
@GetMapping("/soldExcel")
@PreAuthorize("@pms.hasPermission('order:order:soldExcel')")
public void soldExcel(Order order, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime,
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime, HttpServletResponse response) {
Long shopId = SecurityUtils.getSysUser().getShopId();
order.setShopId(shopId);
order.setIsPayed(1);
List<Order> orders = orderService.listOrdersDetialByOrder(order, startTime, endTime);
//通过工具类创建writer
ExcelWriter writer = ExcelUtil.getWriter();
// 待发货
String[] hearder = {"订单编号", "下单时间", "收件人", "手机", "收货地址", "商品名称", "数量", "订单应付", "订单运费", "订单实付"};
Sheet sheet = writer.getSheet();
sheet.setColumnWidth(0, 20 * 256);
sheet.setColumnWidth(1, 20 * 256);
sheet.setColumnWidth(3, 20 * 256);
sheet.setColumnWidth(4, 60 * 256);
sheet.setColumnWidth(5, 60 * 256);
writer.merge(hearder.length - 1, "销售信息整理");
writer.writeRow(Arrays.asList(hearder));
int row = 1;
for (Order dbOrder : orders) {
UserAddrOrder addr = dbOrder.getUserAddrOrder();
String addrInfo = addr.getProvince() + addr.getCity() + addr.getArea() + addr.getAddr();
List<OrderItem> orderItems = dbOrder.getOrderItems();
int firstRow = row + 1;
int lastRow = row + orderItems.size();
int col = -1;
// 订单编号
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getOrderNumber());
// 下单时间
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getCreateTime());
// 收件人
mergeIfNeed(writer, firstRow, lastRow, ++col, col, addr.getReceiver());
// "手机"
mergeIfNeed(writer, firstRow, lastRow, ++col, col, addr.getMobile());
// "收货地址"
mergeIfNeed(writer, firstRow, lastRow, ++col, col, addrInfo);
int prodNameCol = ++col;
int prodCountCol = ++col;
for (OrderItem orderItem : orderItems) {
row++;
// 商品名称
writer.writeCellValue(prodNameCol, row, orderItem.getProdName());
// 数量
writer.writeCellValue(prodCountCol, row, orderItem.getProdCount());
}
// 订单应付
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getTotal());
// 订单运费
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getFreightAmount());
// 订单实付
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getActualTotal());
}
writeExcel(response, writer);
}
/**
* 如果需要合并的话,就合并
*/
private void mergeIfNeed(ExcelWriter writer, int firstRow, int lastRow, int firstColumn, int lastColumn, Object content) {
if (lastRow - firstRow > 0 || lastColumn - firstColumn > 0) {
writer.merge(firstRow, lastRow, firstColumn, lastColumn, content, false);
} else {
writer.writeCellValue(firstColumn, firstRow, content);
}
}
private void writeExcel(HttpServletResponse response, ExcelWriter writer) {
//response为HttpServletResponse对象
response.setContentType("application/vnd.ms-excel;charset=utf-8");
//test.xls是弹出下载对话框的文件名不能为中文中文请自行编码
response.setHeader("Content-Disposition", "attachment;filename=1.xls");
ServletOutputStream servletOutputStream = null;
try {
servletOutputStream = response.getOutputStream();
writer.flush(servletOutputStream);
servletOutputStream.flush();
} catch (IORuntimeException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
writer.close();
try {
servletOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.validation.Valid;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.common.enums.YamiHttpStatus;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.PickAddr;
import com.yami.shop.service.PickAddrService;
import cn.hutool.core.util.StrUtil;
/**
*
* @author lgh on 2018/10/17.
*/
@RestController
@RequestMapping("/shop/pickAddr")
public class PickAddrController {
@Autowired
private PickAddrService pickAddrService;
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('shop:pickAddr:page')")
public ResponseEntity<IPage<PickAddr>> page(PickAddr pickAddr,PageParam<PickAddr> page){
IPage<PickAddr> pickAddrs = pickAddrService.page(page,new LambdaQueryWrapper<PickAddr>()
.like(StrUtil.isNotBlank(pickAddr.getAddrName()),PickAddr::getAddrName,pickAddr.getAddrName())
.orderByDesc(PickAddr::getAddrId));
return ResponseEntity.ok(pickAddrs);
}
/**
* 获取信息
*/
@GetMapping("/info/{id}")
@PreAuthorize("@pms.hasPermission('shop:pickAddr:info')")
public ResponseEntity<PickAddr> info(@PathVariable("id") Long id){
PickAddr pickAddr = pickAddrService.getById(id);
return ResponseEntity.ok(pickAddr);
}
/**
* 保存
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('shop:pickAddr:save')")
public ResponseEntity<Void> save(@Valid @RequestBody PickAddr pickAddr){
pickAddr.setShopId(SecurityUtils.getSysUser().getShopId());
pickAddrService.save(pickAddr);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('shop:pickAddr:update')")
public ResponseEntity<Void> update(@Valid @RequestBody PickAddr pickAddr){
PickAddr dbPickAddr = pickAddrService.getById(pickAddr.getAddrId());
if (!Objects.equals(dbPickAddr.getShopId(),pickAddr.getShopId())) {
throw new YamiShopBindException(YamiHttpStatus.UNAUTHORIZED);
}
pickAddrService.updateById(pickAddr);
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping
@PreAuthorize("@pms.hasPermission('shop:pickAddr:delete')")
public ResponseEntity<Void> delete(@RequestBody Long[] ids){
pickAddrService.removeByIds(Arrays.asList(ids));
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import javax.validation.Valid;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.service.PointsChangeService;
import com.yami.shop.bean.model.PointsChange;
/**
*
* @author lgh on 2019/04/10.
*/
@RestController
@RequestMapping("/admin/pointsChange")
public class PointsChangeController {
@Autowired
private PointsChangeService pointsChangeService;
/**
* 分页获取
*/
@GetMapping("/page")
// @PreAuthorize("@pms.hasPermission('admin:pointsChange:page')")
public ResponseEntity<IPage<PointsChange>> page(PointsChange pointsChange,PageParam<PointsChange> page){
IPage<PointsChange> list = pointsChangeService.page(page,new LambdaQueryWrapper<PointsChange>());
return ResponseEntity.ok(list);
}
/**
* 获取信息
*/
@GetMapping("/info/{id}")
//@PreAuthorize("@pms.hasPermission('admin:pointsChange:info')")
public ResponseEntity<PointsChange> info(@PathVariable("id") Long id){
PointsChange pointsChange = pointsChangeService.getById(id);
return ResponseEntity.ok(pointsChange);
}
/**
* 保存
*/
@PostMapping
// @PreAuthorize("@pms.hasPermission('admin:pointsChange:save')")
public ResponseEntity<Void> save(@RequestBody @Valid PointsChange pointsChange){
pointsChangeService.save(pointsChange);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
// @PreAuthorize("@pms.hasPermission('admin:pointsChange:update')")
public ResponseEntity<Void> update(@RequestBody @Valid PointsChange pointsChange){
pointsChangeService.updateById(pointsChange);
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping("/{id}")
//@PreAuthorize("@pms.hasPermission('admin:pointsChange:delete')")
public ResponseEntity<Void> delete(@PathVariable Long id){
pointsChangeService.removeById(id);
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.security.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.service.PointsService;
import com.yami.shop.bean.model.Points;
/**
*
* @author lgh on 2019/04/10.
*/
@RestController
@RequestMapping("/points/points")
public class PointsController {
@Autowired
private PointsService pointsService;
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('points:points:page')")
public ResponseEntity<IPage<Points>> page(Points points,PageParam<Points> page){
IPage<Points> list = pointsService.page(page,new LambdaQueryWrapper<Points>());
return ResponseEntity.ok(list);
}
/**
* 分页获取(携带user)
*/
@GetMapping("/page/anduser")
@PreAuthorize("@pms.hasPermission('points:points:page')")
public ResponseEntity<IPage<Points>> andUserPage( Points points ,PageParam< Points> page){
points.setShopId(SecurityUtils.getSysUser().getShopId());
IPage<Points> list = pointsService.getPointsAndSysUserPage(page,points);
return ResponseEntity.ok(list);
}
/**
* 分页获取(只取name和id)
*/
@GetMapping("/page/name")
@PreAuthorize("@pms.hasPermission('points:points:page')")
public ResponseEntity<List<Points>> nameAndIdPage(Points points){
points.setShopId(SecurityUtils.getSysUser().getShopId());
List<Points> list = pointsService.getNameAndId(points);
return ResponseEntity.ok(list);
}
/**
* 获取信息
*/
@GetMapping("/info/{id}")
@PreAuthorize("@pms.hasPermission('points:points:info')")
public ResponseEntity<Points> info(@PathVariable("id") Long id){
Points points = pointsService.getById(id);
return ResponseEntity.ok(points);
}
/**
* 保存
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('points:points:save')")
public ResponseEntity<Void> save(@RequestBody @Valid Points points){
points.setModifier(SecurityUtils.getSysUser().getUserId());
points.setUpdateTime(new Date());
points.setShopId(SecurityUtils.getSysUser().getShopId());
pointsService.save(points);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('points:points:update')")
public ResponseEntity<Void> update(@RequestBody @Valid Points points){
points.setModifier(SecurityUtils.getSysUser().getUserId());
points.setUpdateTime(new Date());
pointsService.updateById(points);
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping
@PreAuthorize("@pms.hasPermission('points:points:delete')")
public ResponseEntity<Void> delete(@RequestBody List<Long> ids){
pointsService.removeByIds(ids);
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import javax.validation.Valid;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.service.PointsProdService;
import com.yami.shop.bean.model.PointsProd;
/**
*
* @author lgh on 2019/04/10.
*/
@RestController
@RequestMapping("/admin/pointsProd")
public class PointsProdController {
@Autowired
private PointsProdService pointsProdService;
/**
* 分页获取
*/
@GetMapping("/page")
//@PreAuthorize("@pms.hasPermission('admin:pointsProd:page')")
public ResponseEntity<IPage<PointsProd>> page(PointsProd pointsProd,PageParam<PointsProd> page){
IPage<PointsProd> list = pointsProdService.page(page,new LambdaQueryWrapper<PointsProd>());
return ResponseEntity.ok(list);
}
/**
* 获取信息
*/
@GetMapping("/info/{id}")
//@PreAuthorize("@pms.hasPermission('admin:pointsProd:info')")
public ResponseEntity<PointsProd> info(@PathVariable("id") Long id){
PointsProd pointsProd = pointsProdService.getById(id);
return ResponseEntity.ok(pointsProd);
}
/**
* 保存
*/
@PostMapping
// @PreAuthorize("@pms.hasPermission('admin:pointsProd:save')")
public ResponseEntity<Void> save(@RequestBody @Valid PointsProd pointsProd){
pointsProdService.save(pointsProd);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
//@PreAuthorize("@pms.hasPermission('admin:pointsProd:update')")
public ResponseEntity<Void> update(@RequestBody @Valid PointsProd pointsProd){
pointsProdService.updateById(pointsProd);
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping("/{id}")
//@PreAuthorize("@pms.hasPermission('admin:pointsProd:delete')")
public ResponseEntity<Void> delete(@PathVariable Long id){
pointsProdService.removeById(id);
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import javax.validation.Valid;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.service.PointsWalletService;
import com.yami.shop.bean.model.PointsWallet;
/**
*
* @author lgh on 2019/04/10.
*/
@RestController
@RequestMapping("/admin/pointsWallet")
public class PointsWalletController {
@Autowired
private PointsWalletService pointsWalletService;
/**
* 分页获取
*/
@GetMapping("/page")
//@PreAuthorize("@pms.hasPermission('admin:pointsWallet:page')")
public ResponseEntity<IPage<PointsWallet>> page(PointsWallet pointsWallet,PageParam<PointsWallet> page){
IPage<PointsWallet> list = pointsWalletService.page(page,new LambdaQueryWrapper<PointsWallet>());
return ResponseEntity.ok(list);
}
/**
* 获取信息
*/
@GetMapping("/info/{id}")
//@PreAuthorize("@pms.hasPermission('admin:pointsWallet:info')")
public ResponseEntity<PointsWallet> info(@PathVariable("id") Long id){
PointsWallet pointsWallet = pointsWalletService.getById(id);
return ResponseEntity.ok(pointsWallet);
}
/**
* 保存
*/
@PostMapping
//@PreAuthorize("@pms.hasPermission('admin:pointsWallet:save')")
public ResponseEntity<Void> save(@RequestBody @Valid PointsWallet pointsWallet){
pointsWalletService.save(pointsWallet);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
//@PreAuthorize("@pms.hasPermission('admin:pointsWallet:update')")
public ResponseEntity<Void> update(@RequestBody @Valid PointsWallet pointsWallet){
pointsWalletService.updateById(pointsWallet);
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping("/{id}")
//@PreAuthorize("@pms.hasPermission('admin:pointsWallet:delete')")
public ResponseEntity<Void> delete(@PathVariable Long id){
pointsWalletService.removeById(id);
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yami.shop.bean.model.ProdComm;
import com.yami.shop.common.annotation.SysLog;
import com.yami.shop.common.util.Json;
import com.yami.shop.service.ProdCommService;
import lombok.AllArgsConstructor;
import javax.validation.Valid;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import java.util.ArrayList;
import java.util.Date;
/**
* 商品评论
*
* @author xwc
* @date 2019-04-19 10:43:57
*/
@RestController
@AllArgsConstructor
@RequestMapping("/prod/prodComm" )
public class ProdCommController {
private final ProdCommService prodCommService;
/**
* 分页查询
* @param page 分页对象
* @param prodComm 商品评论
* @return 分页数据
*/
@GetMapping("/page" )
@PreAuthorize("@pms.hasPermission('prod:prodComm:page')" )
public ResponseEntity<IPage<ProdComm>> getProdCommPage(PageParam page, ProdComm prodComm) {
return ResponseEntity.ok(prodCommService.getProdCommPage(page,prodComm));
}
/**
* 通过id查询商品评论
* @param prodCommId id
* @return 单个数据
*/
@GetMapping("/info/{prodCommId}" )
@PreAuthorize("@pms.hasPermission('prod:prodComm:info')" )
public ResponseEntity<ProdComm> getById(@PathVariable("prodCommId" ) Long prodCommId) {
return ResponseEntity.ok(prodCommService.getById(prodCommId));
}
/**
* 新增商品评论
* @param prodComm 商品评论
* @return 是否新增成功
*/
@SysLog("新增商品评论" )
@PostMapping
@PreAuthorize("@pms.hasPermission('prod:prodComm:save')" )
public ResponseEntity<Boolean> save(@RequestBody @Valid ProdComm prodComm) {
return ResponseEntity.ok(prodCommService.save(prodComm));
}
/**
* 修改商品评论
* @param prodComm 商品评论
* @return 是否修改成功
*/
@SysLog("修改商品评论" )
@PutMapping
@PreAuthorize("@pms.hasPermission('prod:prodComm:update')" )
public ResponseEntity<Boolean> updateById(@RequestBody @Valid ProdComm prodComm) {
prodComm.setReplyTime(new Date());
return ResponseEntity.ok(prodCommService.updateById(prodComm));
}
/**
* 通过id删除商品评论
* @param prodCommId id
* @return 是否删除成功
*/
@SysLog("删除商品评论" )
@DeleteMapping("/{prodCommId}" )
@PreAuthorize("@pms.hasPermission('prod:prodComm:delete')" )
public ResponseEntity<Boolean> removeById(@PathVariable Long prodCommId) {
return ResponseEntity.ok(prodCommService.removeById(prodCommId));
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.model.ProdTag;
import com.yami.shop.common.annotation.SysLog;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.ProdTagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
/**
* 商品分组
*
* @author hzm
* @date 2019-04-18 09:08:36
*/
@RestController
@RequestMapping("/prod/prodTag")
public class ProdTagController {
@Autowired
private ProdTagService prodTagService;
/**
* 分页查询
*
* @param page 分页对象
* @param prodTag 商品分组标签
* @return 分页数据
*/
@GetMapping("/page")
public ResponseEntity<IPage<ProdTag>> getProdTagPage(PageParam<ProdTag> page, ProdTag prodTag) {
IPage<ProdTag> tagIPage = prodTagService.page(
page, new LambdaQueryWrapper<ProdTag>()
.eq(prodTag.getStatus() != null, ProdTag::getStatus, prodTag.getStatus())
.like(prodTag.getTitle() != null, ProdTag::getTitle, prodTag.getTitle())
.orderByDesc(ProdTag::getSeq));
return ResponseEntity.ok(tagIPage);
}
/**
* 通过id查询商品分组标签
*
* @param id id
* @return 单个数据
*/
@GetMapping("/info/{id}")
public ResponseEntity<ProdTag> getById(@PathVariable("id") Long id) {
return ResponseEntity.ok(prodTagService.getById(id));
}
/**
* 新增商品分组标签
*
* @param prodTag 商品分组标签
* @return 是否新增成功
*/
@SysLog("新增商品分组标签")
@PostMapping
@PreAuthorize("@pms.hasPermission('prod:prodTag:save')")
public ResponseEntity<Boolean> save(@RequestBody @Valid ProdTag prodTag) {
prodTag.setCreateTime(new Date());
prodTag.setUpdateTime(new Date());
prodTag.setIsDefault(0);
prodTag.setShopId(SecurityUtils.getSysUser().getShopId());
prodTag.setStatus(1);
prodTag.setProdCount(0L);
prodTagService.removeProdTag();
return ResponseEntity.ok(prodTagService.save(prodTag));
}
/**
* 修改商品分组标签
*
* @param prodTag 商品分组标签
* @return 是否修改成功
*/
@SysLog("修改商品分组标签")
@PutMapping
@PreAuthorize("@pms.hasPermission('prod:prodTag:update')")
public ResponseEntity<Boolean> updateById(@RequestBody @Valid ProdTag prodTag) {
prodTag.setUpdateTime(new Date());
prodTagService.removeProdTag();
return ResponseEntity.ok(prodTagService.updateById(prodTag));
}
/**
* 通过id删除商品分组标签
*
* @param id id
* @return 是否删除成功
*/
@SysLog("删除商品分组标签")
@DeleteMapping("/{id}")
@PreAuthorize("@pms.hasPermission('prod:prodTag:delete')")
public ResponseEntity<Boolean> removeById(@PathVariable Long id) {
ProdTag prodTag = prodTagService.getById(id);
if (prodTag.getIsDefault() != 0) {
throw new YamiShopBindException("默认标签不能删除");
}
prodTagService.removeProdTag();
return ResponseEntity.ok(prodTagService.removeById(id));
}
@GetMapping("/listTagList")
@PreAuthorize("@pms.hasPermission('prod:prodTag:update')")
public ResponseEntity<List<ProdTag>> listTagList() {
return ResponseEntity.ok(prodTagService.list());
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.model.ProdTagReference;
import com.yami.shop.common.annotation.SysLog;
import com.yami.shop.service.ProdTagReferenceService;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* 分组标签引用
*
* @author hzm
* @date 2019-04-18 16:28:01
*/
@RestController
@AllArgsConstructor
@RequestMapping("/generator/prodTagReference" )
public class ProdTagReferenceController {
private final ProdTagReferenceService prodTagReferenceService;
/**
* 分页查询
* @param page 分页对象
* @param prodTagReference 分组标签引用
* @return 分页数据
*/
@GetMapping("/page" )
public ResponseEntity<IPage<ProdTagReference>> getProdTagReferencePage(PageParam page, ProdTagReference prodTagReference) {
return ResponseEntity.ok(prodTagReferenceService.page(page, new LambdaQueryWrapper<ProdTagReference>()));
}
/**
* 通过id查询分组标签引用
* @param referenceId id
* @return 单个数据
*/
@GetMapping("/info/{referenceId}" )
public ResponseEntity<ProdTagReference> getById(@PathVariable("referenceId" ) Long referenceId) {
return ResponseEntity.ok(prodTagReferenceService.getById(referenceId));
}
/**
* 新增分组标签引用
* @param prodTagReference 分组标签引用
* @return 是否新增成功
*/
@SysLog("新增分组标签引用" )
@PostMapping
@PreAuthorize("@pms.hasPermission('generator:prodTagReference:save')" )
public ResponseEntity<Boolean> save(@RequestBody @Valid ProdTagReference prodTagReference) {
return ResponseEntity.ok(prodTagReferenceService.save(prodTagReference));
}
/**
* 修改分组标签引用
* @param prodTagReference 分组标签引用
* @return 是否修改成功
*/
@SysLog("修改分组标签引用" )
@PutMapping
@PreAuthorize("@pms.hasPermission('generator:prodTagReference:update')" )
public ResponseEntity<Boolean> updateById(@RequestBody @Valid ProdTagReference prodTagReference) {
return ResponseEntity.ok(prodTagReferenceService.updateById(prodTagReference));
}
/**
* 通过id删除分组标签引用
* @param referenceId id
* @return 是否删除成功
*/
@SysLog("删除分组标签引用" )
@DeleteMapping("/{referenceId}" )
@PreAuthorize("@pms.hasPermission('generator:prodTagReference:delete')" )
public ResponseEntity<Boolean> removeById(@PathVariable Long referenceId) {
return ResponseEntity.ok(prodTagReferenceService.removeById(referenceId));
}
}

View File

@@ -0,0 +1,230 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.Sku;
import com.yami.shop.bean.param.ProductParam;
import com.yami.shop.common.enums.YamiHttpStatus;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Json;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.BasketService;
import com.yami.shop.service.ProdTagReferenceService;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.SkuService;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
* 商品列表、商品发布controller
*
* @author lgh
*/
@Controller
@RequestMapping("/prod/prod")
public class ProductController {
@Autowired
private ProductService productService;
@Autowired
private MapperFacade mapperFacade;
@Autowired
private SkuService skuService;
@Autowired
private ProdTagReferenceService prodTagReferenceService;
@Autowired
private BasketService basketService;
/**
* 分页获取商品信息
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('prod:prod:page')")
public ResponseEntity<IPage<Product>> page(ProductParam product, PageParam<Product> page) {
IPage<Product> products = productService.page(page,
new LambdaQueryWrapper<Product>()
.like(StrUtil.isNotBlank(product.getProdName()), Product::getProdName, product.getProdName())
.eq(Product::getShopId, SecurityUtils.getSysUser().getShopId())
.eq(product.getStatus() != null, Product::getStatus, product.getStatus())
.orderByDesc(Product::getPutawayTime));
return ResponseEntity.ok(products);
}
/**
* 获取信息
*/
@GetMapping("/info/{prodId}")
@PreAuthorize("@pms.hasPermission('prod:prod:info')")
public ResponseEntity<Product> info(@PathVariable("prodId") Long prodId) {
Product prod = productService.getProductByProdId(prodId);
if (!Objects.equals(prod.getShopId(), SecurityUtils.getSysUser().getShopId())) {
throw new YamiShopBindException("没有权限获取该商品规格信息");
}
List<Sku> skuList = skuService.listByProdId(prodId);
prod.setSkuList(skuList);
//获取分组标签
List<Long> listTagId = prodTagReferenceService.listTagIdByProdId(prodId);
prod.setTagList(listTagId);
return ResponseEntity.ok(prod);
}
/**
* 保存
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('prod:prod:save')")
public ResponseEntity<String> save(@Valid @RequestBody ProductParam productParam) {
checkParam(productParam);
Product product = mapperFacade.map(productParam, Product.class);
product.setDeliveryMode(Json.toJsonString(productParam.getDeliveryModeVo()));
product.setShopId(SecurityUtils.getSysUser().getShopId());
product.setUpdateTime(new Date());
if (product.getStatus() == 1) {
product.setPutawayTime(new Date());
}
product.setCreateTime(new Date());
productService.saveProduct(product);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('prod:prod:update')")
public ResponseEntity<String> update(@Valid @RequestBody ProductParam productParam) {
checkParam(productParam);
Product dbProduct = productService.getProductByProdId(productParam.getProdId());
if (!Objects.equals(dbProduct.getShopId(), SecurityUtils.getSysUser().getShopId())) {
return ResponseEntity.badRequest().body("无法修改非本店铺商品信息");
}
List<Sku> dbSkus = skuService.listByProdId(dbProduct.getProdId());
Product product = mapperFacade.map(productParam, Product.class);
product.setDeliveryMode(Json.toJsonString(productParam.getDeliveryModeVo()));
product.setUpdateTime(new Date());
if (dbProduct.getStatus() == 0 || productParam.getStatus() == 1) {
product.setPutawayTime(new Date());
}
dbProduct.setSkuList(dbSkus);
productService.updateProduct(product, dbProduct);
List<String> userIds = basketService.listUserIdByProdId(product.getProdId());
for (String userId : userIds) {
basketService.removeShopCartItemsCacheByUserId(userId);
}
for (Sku sku : dbSkus) {
skuService.removeSkuCacheBySkuId(sku.getSkuId(), sku.getProdId());
}
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping("/{prodId}")
@PreAuthorize("@pms.hasPermission('prod:prod:delete')")
public ResponseEntity<Void> delete(@PathVariable("prodId") Long prodId) {
Product dbProduct = productService.getProductByProdId(prodId);
if (!Objects.equals(dbProduct.getShopId(), SecurityUtils.getSysUser().getShopId())) {
throw new YamiShopBindException("无法获取非本店铺商品信息");
}
List<Sku> dbSkus = skuService.listByProdId(dbProduct.getProdId());
// 删除商品
productService.removeProductByProdId(prodId);
for (Sku sku : dbSkus) {
skuService.removeSkuCacheBySkuId(sku.getSkuId(), sku.getProdId());
}
List<String> userIds = basketService.listUserIdByProdId(prodId);
for (String userId : userIds) {
basketService.removeShopCartItemsCacheByUserId(userId);
}
return ResponseEntity.ok().build();
}
/**
* 更新商品状态
*/
@PutMapping("/prodStatus")
@PreAuthorize("@pms.hasPermission('prod:prod:status')")
public ResponseEntity<Void> shopStatus(@RequestParam Long prodId, @RequestParam Integer prodStatus) {
Product product = new Product();
product.setProdId(prodId);
product.setStatus(prodStatus);
if (prodStatus == 1) {
product.setPutawayTime(new Date());
}
productService.updateById(product);
productService.removeProductCacheByProdId(prodId);
List<String> userIds = basketService.listUserIdByProdId(prodId);
for (String userId : userIds) {
basketService.removeShopCartItemsCacheByUserId(userId);
}
return ResponseEntity.ok().build();
}
private void checkParam(ProductParam productParam) {
if (CollectionUtil.isEmpty(productParam.getTagList())) {
throw new YamiShopBindException("请选择产品分组");
}
Product.DeliveryModeVO deliveryMode = productParam.getDeliveryModeVo();
boolean hasDeliverMode = deliveryMode != null
&& (deliveryMode.getHasShopDelivery() || deliveryMode.getHasUserPickUp());
if (!hasDeliverMode) {
throw new YamiShopBindException("请选择配送方式");
}
List<Sku> skuList = productParam.getSkuList();
boolean isAllUnUse = true;
for (Sku sku : skuList) {
if (sku.getStatus() == 1) {
isAllUnUse = false;
}
}
if (isAllUnUse) {
throw new YamiShopBindException("至少要启用一种商品规格");
}
}
}

View File

@@ -0,0 +1,170 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import javax.validation.Valid;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.security.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.ShopDetail;
import com.yami.shop.bean.param.ShopDetailParam;
import com.yami.shop.service.ShopDetailService;
import cn.hutool.core.util.StrUtil;
import ma.glasnost.orika.MapperFacade;
/**
*
* @author lgh on 2018/08/29.
*/
@Controller
@RequestMapping("/shop/shopDetail")
public class ShopDetailController {
@Autowired
private ShopDetailService shopDetailService;
@Autowired
private MapperFacade mapperFacade;
/**
* 修改分销开关
*/
@PutMapping("/isDistribution")
//@PreAuthorize("@pms.hasPermission('shop:shopDetail:update')")
public ResponseEntity<Void> updateIsDistribution(@RequestParam Integer isDistribution){
ShopDetail shopDetail=new ShopDetail();
shopDetail.setShopId(SecurityUtils.getSysUser().getShopId());
shopDetail.setIsDistribution(isDistribution);
shopDetailService.updateById(shopDetail);
// 更新完成后删除缓存
shopDetailService.removeShopDetailCacheByShopId(shopDetail.getShopId());
return ResponseEntity.ok().build();
}
/**
* 获取信息
*/
@GetMapping("/info")
@PreAuthorize("@pms.hasPermission('shop:shopDetail:info')")
public ResponseEntity<ShopDetail> info(){
ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(SecurityUtils.getSysUser().getShopId());
return ResponseEntity.ok(shopDetail);
}
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('shop:shopDetail:page')")
public ResponseEntity<IPage<ShopDetail>> page(ShopDetail shopDetail,PageParam<ShopDetail> page){
IPage<ShopDetail> shopDetails = shopDetailService.page(page,
new LambdaQueryWrapper<ShopDetail>()
.like(StrUtil.isNotBlank(shopDetail.getShopName()),ShopDetail::getShopName,shopDetail.getShopName())
.orderByDesc(ShopDetail::getShopId));
return ResponseEntity.ok(shopDetails);
}
/**
* 获取信息
*/
@GetMapping("/info/{shopId}")
@PreAuthorize("@pms.hasPermission('shop:shopDetail:info')")
public ResponseEntity<ShopDetail> info(@PathVariable("shopId") Long shopId){
ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(shopId);
// 店铺图片
return ResponseEntity.ok(shopDetail);
}
/**
* 保存
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('shop:shopDetail:save')")
public ResponseEntity<Void> save(@Valid ShopDetailParam shopDetailParam){
ShopDetail shopDetail = mapperFacade.map(shopDetailParam, ShopDetail.class);
shopDetail.setCreateTime(new Date());
shopDetail.setShopStatus(1);
shopDetailService.save(shopDetail);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('shop:shopDetail:update')")
public ResponseEntity<Void> update(@Valid ShopDetailParam shopDetailParam){
ShopDetail daShopDetail = shopDetailService.getShopDetailByShopId(shopDetailParam.getShopId());
ShopDetail shopDetail = mapperFacade.map(shopDetailParam, ShopDetail.class);
shopDetail.setUpdateTime(new Date());
shopDetailService.updateShopDetail(shopDetail,daShopDetail);
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping("/{id}")
@PreAuthorize("@pms.hasPermission('shop:shopDetail:delete')")
public ResponseEntity<Void> delete(@PathVariable Long id){
shopDetailService.deleteShopDetailByShopId(id);
return ResponseEntity.ok().build();
}
/**
* 更新店铺状态
*/
@PutMapping("/shopStatus")
@PreAuthorize("@pms.hasPermission('shop:shopDetail:shopStatus')")
public ResponseEntity<Void> shopStatus(@RequestParam Long shopId,@RequestParam Integer shopStatus){
ShopDetail shopDetail = new ShopDetail();
shopDetail.setShopId(shopId);
shopDetail.setShopStatus(shopStatus);
shopDetailService.updateById(shopDetail);
// 更新完成后删除缓存
shopDetailService.removeShopDetailCacheByShopId(shopDetail.getShopId());
return ResponseEntity.ok().build();
}
/**
* 获取所有的店铺名称
*/
@GetMapping("/listShopName")
public ResponseEntity<List<ShopDetail>> listShopName(){
List<ShopDetail> list = shopDetailService.list().stream().map((dbShopDetail) ->{
ShopDetail shopDetail = new ShopDetail();
shopDetail.setShopId(dbShopDetail.getShopId());
shopDetail.setShopName(dbShopDetail.getShopName());
return shopDetail;
}).collect(Collectors.toList());
return ResponseEntity.ok(list);
}
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import java.util.List;
import java.util.Objects;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.common.enums.YamiHttpStatus;
import com.yami.shop.security.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.enums.ProdPropRule;
import com.yami.shop.bean.model.ProdProp;
import com.yami.shop.bean.model.ProdPropValue;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.service.ProdPropService;
import com.yami.shop.service.ProdPropValueService;
/**
* 规格管理
*
* @author lgh
*/
@RestController
@RequestMapping("/prod/spec")
public class SpecController {
@Autowired
private ProdPropService prodPropService;
@Autowired
private ProdPropValueService prodPropValueService;
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('prod:spec:page')")
public ResponseEntity<IPage<ProdProp>> page(ProdProp prodProp,PageParam<ProdProp> page) {
prodProp.setRule(ProdPropRule.SPEC.value());
prodProp.setShopId(SecurityUtils.getSysUser().getShopId());
IPage<ProdProp> list = prodPropService.pagePropAndValue(prodProp, page);
return ResponseEntity.ok(list);
}
/**
* 获取所有的规格
*/
@GetMapping("/list")
public ResponseEntity<List<ProdProp>> list() {
List<ProdProp> list = prodPropService.list(new LambdaQueryWrapper<ProdProp>().eq(ProdProp::getRule, ProdPropRule.SPEC.value()).eq(ProdProp::getShopId, SecurityUtils.getSysUser().getShopId()));
return ResponseEntity.ok(list);
}
/**
* 根据规格id获取规格值
*/
@GetMapping("/listSpecValue/{specId}")
public ResponseEntity<List<ProdPropValue>> listSpecValue(@PathVariable("specId") Long specId) {
List<ProdPropValue> list = prodPropValueService.list(new LambdaQueryWrapper<ProdPropValue>().eq(ProdPropValue::getPropId, specId));
return ResponseEntity.ok(list);
}
/**
* 保存
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('prod:spec:save')")
public ResponseEntity<Void> save(@RequestBody ProdProp prodProp) {
prodProp.setRule(ProdPropRule.SPEC.value());
prodProp.setShopId(SecurityUtils.getSysUser().getShopId());
prodPropService.saveProdPropAndValues(prodProp);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('prod:spec:update')")
public ResponseEntity<Void> update(@RequestBody ProdProp prodProp) {
ProdProp dbProdProp = prodPropService.getById(prodProp.getPropId());
if (!Objects.equals(dbProdProp.getShopId(), SecurityUtils.getSysUser().getShopId())) {
throw new YamiShopBindException("没有权限获取该商品规格信息");
}
prodProp.setRule(ProdPropRule.SPEC.value());
prodProp.setShopId(SecurityUtils.getSysUser().getShopId());
prodPropService.updateProdPropAndValues(prodProp);
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping("/{id}")
@PreAuthorize("@pms.hasPermission('prod:spec:delete')")
public ResponseEntity<Void> delete(@PathVariable Long id) {
prodPropService.deleteProdPropAndValues(id, ProdPropRule.SPEC.value(), SecurityUtils.getSysUser().getShopId());
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.security.util.SecurityUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.Transport;
import com.yami.shop.service.TransportService;
/**
* @author lgh on 2018/11/16.
*/
@RestController
@RequestMapping("/shop/transport")
public class TransportController {
@Autowired
private TransportService transportService;
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('shop:transport:page')")
public ResponseEntity<IPage<Transport>> page(Transport transport,PageParam<Transport> page) {
Long shopId = SecurityUtils.getSysUser().getShopId();
IPage<Transport> transports = transportService.page(page,
new LambdaQueryWrapper<Transport>()
.eq(Transport::getShopId, shopId)
.like(StringUtils.isNotBlank(transport.getTransName()), Transport::getTransName, transport.getTransName()));
return ResponseEntity.ok(transports);
}
/**
* 获取信息
*/
@GetMapping("/info/{id}")
@PreAuthorize("@pms.hasPermission('shop:transport:info')")
public ResponseEntity<Transport> info(@PathVariable("id") Long id) {
Transport transport = transportService.getTransportAndAllItems(id);
return ResponseEntity.ok(transport);
}
/**
* 保存
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('shop:transport:save')")
public ResponseEntity<Void> save(@RequestBody Transport transport) {
Long shopId = SecurityUtils.getSysUser().getShopId();
transport.setShopId(shopId);
Date createTime = new Date();
transport.setCreateTime(createTime);
transportService.insertTransportAndTransfee(transport);
return ResponseEntity.ok().build();
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('shop:transport:update')")
public ResponseEntity<Void> update(@RequestBody Transport transport) {
transportService.updateTransportAndTransfee(transport);
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping
@PreAuthorize("@pms.hasPermission('shop:transport:delete')")
public ResponseEntity<Void> delete(@RequestBody Long[] ids) {
transportService.deleteTransportAndTransfeeAndTranscity(ids);
// 删除运费模板的缓存
for (Long id : ids) {
transportService.removeTransportAndAllItemsCache(id);
}
return ResponseEntity.ok().build();
}
/**
* 获取运费模板列表
*/
@GetMapping("/list")
public ResponseEntity<List<Transport>> list() {
Long shopId = SecurityUtils.getSysUser().getShopId();
List<Transport> list = transportService.list(new LambdaQueryWrapper<Transport>().eq(Transport::getShopId, shopId));
return ResponseEntity.ok(list);
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.model.UserAddr;
import com.yami.shop.common.annotation.SysLog;
import com.yami.shop.service.UserAddrService;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* 用户地址管理
*
* @author hzm
* @date 2019-04-15 10:49:40
*/
@RestController
@AllArgsConstructor
@RequestMapping("/user/addr")
public class UserAddrController {
private final UserAddrService userAddrService;
/**
* 分页查询
*
* @param page 分页对象
* @param userAddr 用户地址管理
* @return 分页数据
*/
@GetMapping("/page")
public ResponseEntity<IPage<UserAddr>> getUserAddrPage(PageParam page, UserAddr userAddr) {
return ResponseEntity.ok(userAddrService.page(page, new LambdaQueryWrapper<UserAddr>()));
}
/**
* 通过id查询用户地址管理
*
* @param addrId id
* @return 单个数据
*/
@GetMapping("/info/{addrId}")
public ResponseEntity<UserAddr> getById(@PathVariable("addrId") Long addrId) {
return ResponseEntity.ok(userAddrService.getById(addrId));
}
/**
* 新增用户地址管理
*
* @param userAddr 用户地址管理
* @return 是否新增成功
*/
@SysLog("新增用户地址管理")
@PostMapping
@PreAuthorize("@pms.hasPermission('user:addr:save')")
public ResponseEntity<Boolean> save(@RequestBody @Valid UserAddr userAddr) {
return ResponseEntity.ok(userAddrService.save(userAddr));
}
/**
* 修改用户地址管理
*
* @param userAddr 用户地址管理
* @return 是否修改成功
*/
@SysLog("修改用户地址管理")
@PutMapping
@PreAuthorize("@pms.hasPermission('user:addr:update')")
public ResponseEntity<Boolean> updateById(@RequestBody @Valid UserAddr userAddr) {
return ResponseEntity.ok(userAddrService.updateById(userAddr));
}
/**
* 通过id删除用户地址管理
*
* @param addrId id
* @return 是否删除成功
*/
@SysLog("删除用户地址管理")
@DeleteMapping("/{addrId}")
@PreAuthorize("@pms.hasPermission('user:addr:delete')")
public ResponseEntity<Boolean> removeById(@PathVariable Long addrId) {
return ResponseEntity.ok(userAddrService.removeById(addrId));
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.controller;
import java.util.Arrays;
import java.util.Date;
import java.util.UUID;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.User;
import com.yami.shop.service.UserService;
import cn.hutool.extra.emoji.EmojiUtil;
/**
* @author lgh on 2018/10/16.
*/
@RestController
@RequestMapping("/admin/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 分页获取
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('admin:user:page')")
public ResponseEntity<IPage<User>> page(User user,PageParam<User> page) {
IPage<User> userIPage = userService.page(page, new LambdaQueryWrapper<User>()
.like(StrUtil.isNotBlank(user.getNickName()), User::getNickName, user.getNickName())
.eq(user.getStatus() != null, User::getStatus, user.getStatus()));
for (User userResult : userIPage.getRecords()) {
userResult.setNickName(EmojiUtil.toUnicode(userResult.getNickName() == null ? "" : userResult.getNickName()));
}
return ResponseEntity.ok(userIPage);
}
/**
* 获取信息
*/
@GetMapping("/info/{userId}")
@PreAuthorize("@pms.hasPermission('admin:user:info')")
public ResponseEntity<User> info(@PathVariable("userId") String userId) {
User user = userService.getById(userId);
user.setNickName(EmojiUtil.toUnicode(user.getNickName() == null ? "" : user.getNickName()));
return ResponseEntity.ok(user);
}
/**
* 修改
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('admin:user:update')")
public ResponseEntity<Void> update(@RequestBody User user) {
user.setModifyTime(new Date());
user.setNickName(EmojiUtil.toAlias(user.getNickName() == null ? "" : user.getNickName()));
userService.updateById(user);
return ResponseEntity.ok().build();
}
/**
* 删除
*/
@DeleteMapping
@PreAuthorize("@pms.hasPermission('admin:user:delete')")
public ResponseEntity<Void> delete(@RequestBody String[] userIds) {
userService.removeByIds(Arrays.asList(userIds));
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.security;
import com.yami.shop.security.constants.SecurityConstants;
import com.yami.shop.security.service.YamiClientDetailsService;
import com.yami.shop.security.service.YamiSysUser;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.service.YamiUserDetailsService;
import com.yami.shop.security.util.YamiTokenServices;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
import javax.sql.DataSource;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@Configuration
//@Order(2)
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private YamiUserDetailsService yamiUserDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Autowired
private RedisConnectionFactory redisConnectionFactory;
private AuthorizationServerEndpointsConfigurer endpoints;
@Bean
public TokenStore tokenStore() {
RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
tokenStore.setPrefix(SecurityConstants.YAMI_PREFIX + SecurityConstants.OAUTH_PREFIX);
return tokenStore;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 使用JdbcClientDetailsService客户端详情服务
YamiClientDetailsService clientDetailsService = new YamiClientDetailsService(dataSource);
clientDetailsService.setSelectClientDetailsSql(SecurityConstants.DEFAULT_SELECT_STATEMENT);
clientDetailsService.setFindClientDetailsSql(SecurityConstants.DEFAULT_FIND_STATEMENT);
clients.withClientDetails(clientDetailsService);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancer())
.reuseRefreshTokens(false)
.userDetailsService(yamiUserDetailsService);
this.endpoints = endpoints;
endpoints.tokenServices(yamiTokenServices());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer
// 开启/oauth/token_key验证端口无权限访问
.tokenKeyAccess("permitAll()")
// 开启/oauth/check_token验证端口认证权限访问
.checkTokenAccess("isAuthenticated()");
}
/**
* token增强。
*
* @return TokenEnhancer
*/
@Bean
public TokenEnhancer tokenEnhancer() {
return (accessToken, authentication) -> {
final Map<String, Object> additionalInfo = new HashMap<>(8);
YamiSysUser yamiSysUser = (YamiSysUser) authentication.getUserAuthentication().getPrincipal();
additionalInfo.put("shopId", yamiSysUser.getShopId());
additionalInfo.put("userId", yamiSysUser.getUserId());
additionalInfo.put("authorities", yamiSysUser.getAuthorities());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
};
}
@Primary
@Bean
@Lazy
public AuthorizationServerTokenServices yamiTokenServices() {
YamiTokenServices tokenServices = new YamiTokenServices();
tokenServices.setTokenStore(tokenStore());
tokenServices.setSupportRefreshToken(true);//支持刷新token
tokenServices.setReuseRefreshToken(true);
tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
addUserDetailsService(tokenServices);
return tokenServices;
}
private void addUserDetailsService(YamiTokenServices tokenServices) {
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>(
yamiUserDetailsService));
tokenServices.setAuthenticationManager(new ProviderManager(Collections.singletonList(provider)));
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.security;
import com.yami.shop.security.filter.LoginAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Autowired
private LoginAuthenticationFilter loginAuthenticationFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.addFilterBefore(loginAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
// Since we want the protected resources to be accessible in the UI as well we need
// session creation to be allowed (it's disabled by default in 2.0.6)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.requestMatchers().anyRequest()
.and()
.anonymous()
.and()
.authorizeRequests()
.antMatchers(
"/webjars/**",
"/swagger/**",
"/v2/api-docs",
"/doc.html",
"/swagger-ui.html",
"/swagger-resources/**",
"/captcha.jpg").permitAll()
.and()
.authorizeRequests()
.antMatchers("/**").authenticated();//配置所有访问控制,必须认证过后才可以访问
// @formatter:on
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.security;
import com.yami.shop.security.filter.LoginAuthenticationFilter;
import com.yami.shop.security.handler.LoginAuthFailedHandler;
import com.yami.shop.security.handler.LoginAuthSuccessHandler;
import com.yami.shop.security.provider.AdminAuthenticationProvider;
import com.yami.shop.security.service.YamiUserDetailsService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@Order(90)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private LoginAuthSuccessHandler loginAuthSuccessHandler;
@Autowired
private LoginAuthFailedHandler loginAuthFailedHandler;
@Autowired
private AdminAuthenticationProvider adminAuthenticationProvider;
@Override
@Bean
@SneakyThrows
public AuthenticationManager authenticationManagerBean() {
return super.authenticationManagerBean();
}
/**
* 用户验证
* @param auth
*/
@Override
public void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(adminAuthenticationProvider);
}
@Bean
public PasswordEncoder passwordEncoder(){
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Bean
public LoginAuthenticationFilter loginAuthenticationFilter() {
LoginAuthenticationFilter filter = new LoginAuthenticationFilter();
try {
filter.setAuthenticationManager(authenticationManagerBean());
} catch (Exception e) {
e.printStackTrace();
}
filter.setAuthenticationSuccessHandler(loginAuthSuccessHandler);
filter.setAuthenticationFailureHandler(loginAuthFailedHandler);
return filter;
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.security;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yami.shop.common.util.CacheManagerUtil;
import com.yami.shop.sys.constant.Constant;
import com.yami.shop.security.enums.App;
import com.yami.shop.security.exception.UsernameNotFoundExceptionBase;
import com.yami.shop.security.model.AppConnect;
import com.yami.shop.security.service.YamiSysUser;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.service.YamiUserDetailsService;
import com.yami.shop.sys.dao.SysMenuMapper;
import com.yami.shop.sys.dao.SysUserMapper;
import com.yami.shop.sys.model.SysMenu;
import com.yami.shop.sys.model.SysUser;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 用户详细信息
*
* @author
*/
@Slf4j
@Service
@AllArgsConstructor
public class YamiSysUserDetailsServiceImpl implements YamiUserDetailsService {
private final SysMenuMapper sysMenuMapper;
private final SysUserMapper sysUserMapper;
private final CacheManagerUtil cacheManagerUtil;
/**
* 用户密码登录
*
* @param username 用户名
* @return
* @throws UsernameNotFoundExceptionBase
*/
@Override
@SneakyThrows
public YamiSysUser loadUserByUsername(String username) {
YamiSysUser userDetails = cacheManagerUtil.getCache("yami_sys_user", username);
if (userDetails != null) {
return userDetails;
}
userDetails = getUserDetails(username);
cacheManagerUtil.putCache("yami_sys_user",username, userDetails);
return userDetails;
}
/**
* 构建userdetails
*
* @param username 用户名称
* @return
*/
private YamiSysUser getUserDetails(String username) {
SysUser sysUser = sysUserMapper.selectByUsername(username);
if (sysUser == null) {
throw new UsernameNotFoundExceptionBase("用户不存在");
}
Collection<? extends GrantedAuthority> authorities
= AuthorityUtils.createAuthorityList(getUserPermissions(sysUser.getUserId()).toArray(new String[0]));
// 构造security用户
return new YamiSysUser(sysUser.getUserId(), sysUser.getShopId(), sysUser.getUsername(), sysUser.getPassword(), sysUser.getStatus() == 1,
true, true, true , authorities);
}
private Set<String> getUserPermissions(Long userId) {
List<String> permsList;
//系统管理员,拥有最高权限
if(userId == Constant.SUPER_ADMIN_ID){
List<SysMenu> menuList = sysMenuMapper.selectList(Wrappers.emptyWrapper());
permsList = menuList.stream().map(SysMenu::getPerms).collect(Collectors.toList());
}else{
permsList = sysUserMapper.queryAllPerms(userId);
}
Set<String> permsSet = permsList.stream().flatMap((perms)->{
if (StrUtil.isBlank(perms)) {
return null;
}
return Arrays.stream(perms.trim().split(","));
}
).collect(Collectors.toSet());
return permsSet;
}
@Override
public YamiUser loadUserByAppIdAndBizUserId(App app, String bizUserId) {
return null;
}
@Override
public void insertUserIfNecessary(AppConnect appConnect) {
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.task;
import java.util.Date;
import java.util.List;
import com.yami.shop.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.OrderItem;
import com.yami.shop.bean.model.User;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
@Component("orderTask")
public class OrderTask {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private OrderService orderService;
@Autowired
private ProductService productService;
@Autowired
private SkuService skuService;
public void cancelOrder(){
Date now = new Date();
logger.info("取消超时未支付订单。。。");
// 获取30分钟之前未支付的订单
List<Order> orders = orderService.listOrderAndOrderItems(OrderStatus.UNPAY.value(),DateUtil.offsetMinute(now, -30));
if (CollectionUtil.isEmpty(orders)) {
return;
}
orderService.cancelOrders(orders);
for (Order order : orders) {
List<OrderItem> orderItems = order.getOrderItems();
for (OrderItem orderItem : orderItems) {
productService.removeProductCacheByProdId(orderItem.getProdId());
skuService.removeSkuCacheBySkuId(orderItem.getSkuId(),orderItem.getProdId());
}
}
}
/**
* 确认收货
*/
public void confirmOrder(){
Date now = new Date();
logger.info("系统自动确认收货订单。。。");
// 获取15天之前未支付的订单
List<Order> orders = orderService.listOrderAndOrderItems(OrderStatus.CONSIGNMENT.value(),DateUtil.offsetDay(now, -15));
if (CollectionUtil.isEmpty(orders)) {
return;
}
orderService.confirmOrder(orders);
for (Order order : orders) {
List<OrderItem> orderItems = order.getOrderItems();
for (OrderItem orderItem : orderItems) {
productService.removeProductCacheByProdId(orderItem.getProdId());
skuService.removeSkuCacheBySkuId(orderItem.getSkuId(),orderItem.getProdId());
}
}
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.admin.task;
import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class TestTask {
public void test1(){
System.out.println(DateUtil.now() + ": test1 running.................");
}
public void test2(String param){
System.out.println(DateUtil.now() + ": test2 running.................");
}
}

View File

@@ -0,0 +1,2 @@
admin.datacenterId=1
admin.workerId=0

View File

@@ -0,0 +1,24 @@
server:
port: 8085
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/yami_shops?allowMultiQueries=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 0
maximum-pool-size: 20
idle-timeout: 10000
auto-commit: true
connection-test-query: SELECT 1
cache:
type: redis
redis:
cache-null-values: true
redis:
redisson:
config: classpath:redisson.yml
logging:
config: classpath:log4j2_dev.xml

View File

@@ -0,0 +1,20 @@
server:
port: 8111
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/yami_shops?allowMultiQueries=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 0
maximum-pool-size: 20
idle-timeout: 25000
auto-commit: true
connection-test-query: SELECT 1
redis:
redisson:
config: classpath:redisson.yml
logging:
config: classpath:log4j2_prod.xml

View File

@@ -0,0 +1,28 @@
spring:
# 环境 dev|test|prod quart定时任务
profiles:
active: dev,quartz
#文件上传设置
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
enabled: true
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
# mybaits-plus配置
mybatis-plus:
# MyBatis Mapper所对应的XML文件位置
mapper-locations: classpath*:/mapper/*Mapper.xml
global-config:
# 关闭MP3.0自带的banner
banner: false
db-config:
# 主键类型 0:数据库ID自增 1.未定义 2.用户输入 3 id_worker 4.uuid 5.id_worker字符串表示
id-type: AUTO
#字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
field-strategy: NOT_NULL
# 默认数据库表下划线命名
table-underline: true

View File

@@ -0,0 +1,11 @@
.----------------. .----------------. .----------------. .----------------.
| .--------------. || .--------------. || .--------------. || .--------------. |
| | ____ ____ | || | __ | || | ____ ____ | || | _____ | |
| | |_ _||_ _| | || | / \ | || ||_ \ / _|| || | |_ _| | |
| | \ \ / / | || | / /\ \ | || | | \/ | | || | | | | |
| | \ \/ / | || | / ____ \ | || | | |\ /| | | || | | | | |
| | _| |_ | || | _/ / \ \_ | || | _| |_\/_| |_ | || | _| |_ | |
| | |______| | || ||____| |____|| || ||_____||_____|| || | |_____| | |
| | | || | | || | | || | | |
| '--------------' || '--------------' || '--------------' || '--------------' |
'----------------' '----------------' '----------------' '----------------'

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--monitorIntervalLog4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="WARN" monitorInterval="60">
<Properties>
<Property name="PID">????</Property>
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property>
<!-- 控制台日志格式化,包含颜色-->
<Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
</Properties>
<!--定义appender -->
<Appenders>
<!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->
<Console name="Console" target="SYSTEM_OUT" follow="false">
<PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" />
</Console>
</Appenders>
<Loggers>
<Logger name="org.mybatis" level="debug"/>
<Logger name="com.yami.shop" level="debug"/>
<Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
<Logger name="org.apache.catalina.util.LifecycleBase" level="error" />
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
<Logger name="org.apache.sshd.common.util.SecurityUtils" level="warn"/>
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
<Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
<Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
<Logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
<!--关闭swagger的类型转换异常的日志 https://github.com/springfox/springfox/issues/2528-->
<Logger name="springfox.documentation.swagger2" level="off"/>
<Logger name="io.swagger.models.parameters" level="off"/>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</configuration>

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--monitorIntervalLog4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="WARN" monitorInterval="60">
<Properties>
<Property name="PID">????</Property>
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property>
<!-- 控制台日志格式化,包含颜色-->
<Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
<!-- 日志文件默认输出格式,不带行号输出(行号显示会影响日志输出性能);%C:大写,类名;%M:方法名;%m:错误信息;%n:换行 -->
<Property name="FILE_LOG_PATTERN">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
<!-- 日志默认同类型日志,同一文件夹下可以存放的数量,不设置此属性则默认为7个 -->
<Property name="FILE_MAX_HISTORY">50</Property>
<Property name="FILE_MAX_SIZE">50MB</Property>
<Property name="PROJECT_PATH">/opt/projects/mall4j</Property>
</Properties>
<!--定义appender -->
<Appenders>
<!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->
<Console name="Console" target="SYSTEM_OUT" follow="false">
<PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" />
</Console>
<!--fileName 文件名称-->
<!--filePattern 文件路径-->
<RollingFile name="DefaultFile" fileName="${PROJECT_PATH}/log/admin.log" filePattern="${PROJECT_PATH}/log/$${date:yyyy-MM}/admin-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout>
<Pattern>${sys:FILE_LOG_PATTERN}</Pattern>
</PatternLayout>
<DefaultRolloverStrategy max="${FILE_MAX_HISTORY}"/>
<Policies>
<!--TimeBasedTriggeringPolicy 与 filePattern 结合使用目前表示每间隔1天保存一遍日志-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="${FILE_MAX_SIZE}" />
</Policies>
</RollingFile>
<RollingFile name="ScheduleFile" fileName="${PROJECT_PATH}/log/schedule.log" filePattern="${PROJECT_PATH}/log/$${date:yyyy-MM}/schedule-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout>
<Pattern>${sys:FILE_LOG_PATTERN}</Pattern>
</PatternLayout>
<DefaultRolloverStrategy max="${FILE_MAX_HISTORY}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="${FILE_MAX_SIZE}" />
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="org.mybatis" level="debug"/>
<Logger name="com.yami.shop" level="debug"/>
<Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
<Logger name="org.apache.catalina.util.LifecycleBase" level="error" />
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
<Logger name="org.apache.sshd.common.util.SecurityUtils" level="warn"/>
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
<Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
<Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
<Logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
<!--addtivity:用来描述是否向上级logger传递打印信息。默认是true。 -->
<!--指定定时任务在特定的log -->
<Logger name="com.yami.shop.sys.schedule" level="info" additivity="false">
<AppenderRef ref="ScheduleFile"/>
</Logger>
<!---->
<Root level="info">
<AppenderRef ref="DefaultFile" />
</Root>
</Loggers>
</configuration>

View File

@@ -0,0 +1,31 @@
# 单节点设置
singleServerConfig:
address: redis://127.0.0.1:6379
database: 0
password: null
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
clientName: null
# 发布和订阅连接的最小空闲连接数 默认1
subscriptionConnectionMinimumIdleSize: 1
# 发布和订阅连接池大小 默认50
subscriptionConnectionPoolSize: 10
# 单个连接最大订阅数量 默认5
subscriptionsPerConnection: 5
# 最小空闲连接数 默认32现在暂时不需要那么多的线程
connectionMinimumIdleSize: 4
# connectionPoolSize 默认64现在暂时不需要那么多的线程
connectionPoolSize: 20
# 这个线程池数量被所有RTopic对象监听器RRemoteService调用者和RExecutorService任务共同共享。
threads: 0
# 这个线程池数量是在一个Redisson实例内被其创建的所有分布式数据类型和服务以及底层客户端所一同共享的线程池里保存的线程数量。
nettyThreads: 0
codec:
class: com.yami.shop.common.serializer.redisson.FstCodec
transportMode: NIO

49
yami-shop-api/pom.xml Normal file
View File

@@ -0,0 +1,49 @@
<?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>yami-shop</artifactId>
<groupId>com.yami.shop</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yami-shop-api</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-service</artifactId>
<version>${yami.shop.version}</version>
</dependency>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-security</artifactId>
<version>${yami.shop.version}</version>
</dependency>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-mp</artifactId>
<version>${yami.shop.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
/**
* @author lgh
*/
@SpringBootApplication
@ComponentScan(basePackages = {"com.yami.shop"})
public class ApiApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(ApiApplication.class);
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.config;
import cn.hutool.core.lang.Snowflake;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@AllArgsConstructor
public class ApiBeanConfig {
private final ApiConfig apiConfig;
@Bean
public Snowflake snowflake() {
return new Snowflake(apiConfig.getWorkerId(), apiConfig.getDatacenterId());
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
/**
* 商城配置文件
* @author lgh
*/
@Data
@Component
@PropertySource("classpath:api.properties")
@ConfigurationProperties(prefix = "api")
public class ApiConfig {
/**
* 数据中心ID
*/
private Integer datacenterId;
/**
* 终端ID
*/
private Integer workerId;
/**
* 域名
*/
private String domainName;
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger文档只有在测试环境才会使用
* @author LGH
*/
//@Profile("dev")
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
@Bean
public Docket baseRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.groupName("基础版")
.select()
.apis(RequestHandlerSelectors.basePackage("com.yami.shop.api"))
.paths(PathSelectors.any())
.build();
}
@Bean
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("亚米商城接口文档")
.description("亚米商城接口文档Swagger版")
.termsOfServiceUrl("http://www.gz-yami.com/")
.contact(new Contact("广州亚米信息科技有限公司","https://www.gz-yami.com/", ""))
.version("1.0")
.build();
}
}

View File

@@ -0,0 +1,170 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import java.util.Date;
import java.util.List;
import javax.validation.Valid;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.bean.app.dto.UserAddrDto;
import com.yami.shop.bean.app.param.AddrParam;
import com.yami.shop.bean.model.UserAddr;
import com.yami.shop.service.UserAddrService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
@RestController
@RequestMapping("/p/address")
@Api(tags = "地址接口")
@AllArgsConstructor
public class AddrController {
@Autowired
private MapperFacade mapperFacade;
@Autowired
private UserAddrService userAddrService;
/**
* 选择订单配送地址
*/
@GetMapping("/list")
@ApiOperation(value = "用户地址列表", notes = "获取用户的所有地址信息")
public ResponseEntity<List<UserAddrDto>> dvyList() {
String userId = SecurityUtils.getUser().getUserId();
List<UserAddr> userAddrs = userAddrService.list(new LambdaQueryWrapper<UserAddr>().eq(UserAddr::getUserId, userId).orderByDesc(UserAddr::getCommonAddr).orderByDesc(UserAddr::getUpdateTime));
return ResponseEntity.ok(mapperFacade.mapAsList(userAddrs, UserAddrDto.class));
}
/**
* 新增用户订单配送地址
*/
@PostMapping("/addAddr")
@ApiOperation(value = "新增用户地址", notes = "新增用户地址")
public ResponseEntity<String> addAddr(@Valid @RequestBody AddrParam addrParam) {
String userId = SecurityUtils.getUser().getUserId();
if (addrParam.getAddrId() != null && addrParam.getAddrId() != 0) {
return ResponseEntity.badRequest().body("该地址已存在");
}
int addrCount = userAddrService.count(new LambdaQueryWrapper<UserAddr>().eq(UserAddr::getUserId, userId));
UserAddr userAddr = mapperFacade.map(addrParam, UserAddr.class);
if (addrCount == 0) {
userAddr.setCommonAddr(1);
// 清除默认地址缓存
userAddrService.removeUserAddrByUserId(0L, userId);
} else {
userAddr.setCommonAddr(0);
}
userAddr.setUserId(userId);
userAddr.setStatus(1);
userAddr.setCreateTime(new Date());
userAddr.setUpdateTime(new Date());
userAddrService.save(userAddr);
return ResponseEntity.ok("添加地址成功");
}
/**
* 修改订单配送地址
*/
@PutMapping("/updateAddr")
@ApiOperation(value = "修改订单用户地址", notes = "修改用户地址")
public ResponseEntity<String> updateAddr(@Valid @RequestBody AddrParam addrParam) {
String userId = SecurityUtils.getUser().getUserId();
UserAddr dbUserAddr = userAddrService.getUserAddrByUserId(addrParam.getAddrId(), userId);
if (dbUserAddr == null) {
return ResponseEntity.badRequest().body("该地址已被删除");
}
UserAddr userAddr = mapperFacade.map(addrParam, UserAddr.class);
userAddr.setUserId(userId);
userAddr.setUpdateTime(new Date());
userAddrService.updateById(userAddr);
// 清除当前地址缓存
userAddrService.removeUserAddrByUserId(addrParam.getAddrId(), userId);
// 清除默认地址缓存
userAddrService.removeUserAddrByUserId(0L, userId);
return ResponseEntity.ok("修改地址成功");
}
/**
* 删除订单配送地址
*/
@DeleteMapping("/deleteAddr/{addrId}")
@ApiOperation(value = "删除订单用户地址", notes = "根据地址id删除用户地址")
@ApiImplicitParam(name = "addrId", value = "地址ID", required = true, dataType = "Long")
public ResponseEntity<String> deleteDvy(@PathVariable("addrId") Long addrId) {
String userId = SecurityUtils.getUser().getUserId();
UserAddr userAddr = userAddrService.getUserAddrByUserId(addrId, userId);
if (userAddr == null) {
return ResponseEntity.badRequest().body("该地址已被删除");
}
if (userAddr.getCommonAddr() == 1) {
return ResponseEntity.badRequest().body("默认地址无法删除");
}
userAddrService.removeById(addrId);
userAddrService.removeUserAddrByUserId(addrId, userId);
return ResponseEntity.ok("删除地址成功");
}
/**
* 设置默认地址
*/
@PutMapping("/defaultAddr/{addrId}")
@ApiOperation(value = "设置默认地址", notes = "根据地址id设置默认地址")
public ResponseEntity<String> defaultAddr(@PathVariable("addrId") Long addrId) {
String userId = SecurityUtils.getUser().getUserId();
userAddrService.updateDefaultUserAddr(addrId, userId);
userAddrService.removeUserAddrByUserId(0L, userId);
userAddrService.removeUserAddrByUserId(addrId, userId);
return ResponseEntity.ok("修改地址成功");
}
/**
* 获取地址信息订单配送地址
*/
@GetMapping("/addrInfo/{addrId}")
@ApiOperation(value = "获取地址信息", notes = "根据地址id获取地址信息")
@ApiImplicitParam(name = "addrId", value = "地址ID", required = true, dataType = "Long")
public ResponseEntity<UserAddrDto> addrInfo(@PathVariable("addrId") Long addrId) {
String userId = SecurityUtils.getUser().getUserId();
UserAddr userAddr = userAddrService.getUserAddrByUserId(addrId, userId);
if (userAddr == null) {
throw new YamiShopBindException("该地址已被删除");
}
return ResponseEntity.ok(mapperFacade.map(userAddr, UserAddrDto.class));
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import java.util.List;
import com.yami.shop.service.AreaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.bean.model.Area;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
/**
*
* @author lgh on 2018/10/26.
*/
@RestController
@RequestMapping("/p/area")
@Api(tags="省市区接口")
public class AreaController {
@Autowired
private AreaService areaService;
/**
* 分页获取
*/
@GetMapping("/listByPid")
@ApiOperation(value="获取省市区信息", notes="根据省市区的pid获取地址信息")
@ApiImplicitParam(name = "pid", value = "省市区的pid(pid为0获取所有省份)", required = true, dataType = "String")
public ResponseEntity<List<Area>> listByPid(Long pid){
List<Area> list = areaService.listByPid(pid);
return ResponseEntity.ok(list);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.bean.app.dto.CategoryDto;
import com.yami.shop.bean.model.Category;
import com.yami.shop.service.CategoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
@RestController
@RequestMapping("/category")
@Api(tags = "分类接口")
public class CategoryController {
@Autowired
private CategoryService categoryService;
@Autowired
private MapperFacade mapperFacade;
/**
* 分类信息列表接口
*/
@GetMapping("/categoryInfo")
@ApiOperation(value = "分类信息列表", notes = "获取所有的产品分类信息顶级分类的parentId为0,默认为顶级分类")
@ApiImplicitParam(name = "parentId", value = "分类ID", required = false, dataType = "Long")
public ResponseEntity<List<CategoryDto>> categoryInfo(@RequestParam(value = "parentId", defaultValue = "0") Long parentId) {
List<Category> categories = categoryService.listByParentId(parentId);
List<CategoryDto> categoryDtos = mapperFacade.mapAsList(categories, CategoryDto.class);
return ResponseEntity.ok(categoryDtos);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import com.yami.shop.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.bean.app.dto.DeliveryDto;
import com.yami.shop.bean.model.Delivery;
import com.yami.shop.bean.model.Order;
import com.yami.shop.common.util.Json;
import com.yami.shop.service.DeliveryService;
import cn.hutool.http.HttpUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
@RestController
@RequestMapping("/delivery")
@Api(tags="查看物流接口")
public class DeliveryController {
@Autowired
private DeliveryService deliveryService;
@Autowired
private OrderService orderService;
/**
* 查看物流接口
*/
@GetMapping("/check")
@ApiOperation(value="查看物流", notes="根据订单号查看物流")
@ApiImplicitParam(name = "orderNumber", value = "订单号", required = true, dataType = "String")
public ResponseEntity<DeliveryDto> checkDelivery(String orderNumber) {
Order order = orderService.getOrderByOrderNumber(orderNumber);
Delivery delivery = deliveryService.getById(order.getDvyId());
String url = delivery.getQueryUrl().replace("{dvyFlowId}", order.getDvyFlowId());
String deliveryJson = HttpUtil.get(url);
DeliveryDto deliveryDto = Json.parseObject(deliveryJson, DeliveryDto.class);
deliveryDto.setDvyFlowId(order.getDvyFlowId());
deliveryDto.setCompanyHomeUrl(delivery.getCompanyHomeUrl());
deliveryDto.setCompanyName(delivery.getDvyName());
return ResponseEntity.ok(deliveryDto);
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import com.yami.shop.bean.app.dto.IndexImgDto;
import com.yami.shop.bean.model.IndexImg;
import com.yami.shop.service.IndexImgService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@Api(tags = "首页轮播图接口")
public class IndexImgController {
@Autowired
private MapperFacade mapperFacade;
@Autowired
private IndexImgService indexImgService;
/**
* 首页轮播图接口
*/
@GetMapping("/indexImgs")
@ApiOperation(value = "首页轮播图", notes = "获取首页轮播图列表信息")
public ResponseEntity<List<IndexImgDto>> indexImgs() {
List<IndexImg> indexImgList = indexImgService.listIndexImgs();
List<IndexImgDto> indexImgDtos = mapperFacade.mapAsList(indexImgList, IndexImgDto.class);
return ResponseEntity.ok(indexImgDtos);
}
}

View File

@@ -0,0 +1,216 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.dao.OrderMapper;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.*;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.OrderItem;
import com.yami.shop.bean.model.ShopDetail;
import com.yami.shop.bean.model.UserAddrOrder;
import com.yami.shop.common.util.Arith;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
@RestController
@RequestMapping("/p/myOrder")
@Api(tags = "我的订单接口")
@AllArgsConstructor
public class MyOrderController {
private final OrderService orderService;
private final MapperFacade mapperFacade;
private final UserAddrOrderService userAddrOrderService;
private final ProductService productService;
private final SkuService skuService;
private final MyOrderService myOrderService;
private final ShopDetailService shopDetailService;
private final OrderItemService orderItemService;
/**
* 订单详情信息接口
*/
@GetMapping("/orderDetail")
@ApiOperation(value = "订单详情信息", notes = "根据订单号获取订单详情信息")
@ApiImplicitParam(name = "orderNumber", value = "订单号", required = true, dataType = "String")
public ResponseEntity<OrderShopDto> orderDetail(@RequestParam(value = "orderNumber", required = true) String orderNumber) {
String userId = SecurityUtils.getUser().getUserId();
OrderShopDto orderShopDto = new OrderShopDto();
Order order = orderService.getOrderByOrderNumber(orderNumber);
if (order == null) {
throw new RuntimeException("该订单不存在");
}
if (!Objects.equals(order.getUserId(), userId)) {
throw new RuntimeException("你没有权限获取该订单信息");
}
ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(order.getShopId());
UserAddrOrder userAddrOrder = userAddrOrderService.getById(order.getAddrOrderId());
UserAddrDto userAddrDto = mapperFacade.map(userAddrOrder, UserAddrDto.class);
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
List<OrderItemDto> orderItemDtos = mapperFacade.mapAsList(orderItems, OrderItemDto.class);
orderShopDto.setShopId(shopDetail.getShopId());
orderShopDto.setShopName(shopDetail.getShopName());
orderShopDto.setActualTotal(order.getActualTotal());
orderShopDto.setUserAddrDto(userAddrDto);
orderShopDto.setOrderItemDtos(orderItemDtos);
orderShopDto.setTransfee(order.getFreightAmount());
orderShopDto.setReduceAmount(order.getReduceAmount());
orderShopDto.setCreateTime(order.getCreateTime());
orderShopDto.setRemarks(order.getRemarks());
orderShopDto.setStatus(order.getStatus());
double total = 0.0;
Integer totalNum = 0;
for (OrderItemDto orderItem : orderShopDto.getOrderItemDtos()) {
total = Arith.add(total, orderItem.getProductTotalAmount());
totalNum += orderItem.getProdCount();
}
orderShopDto.setTotal(total);
orderShopDto.setTotalNum(totalNum);
return ResponseEntity.ok(orderShopDto);
}
/**
* 订单列表接口
*/
@GetMapping("/myOrder")
@ApiOperation(value = "订单列表信息", notes = "根据订单状态获取订单列表信息状态为0时获取所有订单")
@ApiImplicitParams({
@ApiImplicitParam(name = "status", value = "订单状态 1:待付款 2:待发货 3:待收货 4:待评价 5:成功 6:失败", required = false, dataType = "Integer")
})
public ResponseEntity<IPage<MyOrderDto>> myOrder(@RequestParam(value = "status") Integer status,PageParam<MyOrderDto> page) {
String userId = SecurityUtils.getUser().getUserId();
IPage<MyOrderDto> myOrderDtoIpage = myOrderService.pageMyOrderByUserIdAndStatus(page, userId, status);
return ResponseEntity.ok(myOrderDtoIpage);
}
/**
* 取消订单
*/
@PutMapping("/cancel/{orderNumber}")
@ApiOperation(value = "根据订单号取消订单", notes = "根据订单号取消订单")
@ApiImplicitParam(name = "orderNumber", value = "订单号", required = true, dataType = "String")
public ResponseEntity<String> cancel(@PathVariable("orderNumber") String orderNumber) {
String userId = SecurityUtils.getUser().getUserId();
Order order = orderService.getOrderByOrderNumber(orderNumber);
if (!Objects.equals(order.getUserId(), userId)) {
throw new YamiShopBindException("你没有权限获取该订单信息");
}
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
order.setOrderItems(orderItems);
// 取消订单
orderService.cancelOrders(Arrays.asList(order));
// 清除缓存
for (OrderItem orderItem : orderItems) {
productService.removeProductCacheByProdId(orderItem.getProdId());
skuService.removeSkuCacheBySkuId(orderItem.getSkuId(),orderItem.getProdId());
}
return ResponseEntity.ok().build();
}
/**
* 确认收货
*/
@PutMapping("/receipt/{orderNumber}")
@ApiOperation(value = "根据订单号确认收货", notes = "根据订单号确认收货")
public ResponseEntity<String> receipt(@PathVariable("orderNumber") String orderNumber) {
String userId = SecurityUtils.getUser().getUserId();
Order order = orderService.getOrderByOrderNumber(orderNumber);
if (!Objects.equals(order.getUserId(), userId)) {
throw new YamiShopBindException("你没有权限获取该订单信息");
}
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
order.setOrderItems(orderItems);
// 确认收货
orderService.confirmOrder(Arrays.asList(order));
for (OrderItem orderItem : orderItems) {
productService.removeProductCacheByProdId(orderItem.getProdId());
skuService.removeSkuCacheBySkuId(orderItem.getSkuId(),orderItem.getProdId());
}
return ResponseEntity.ok().build();
}
/**
* 删除订单
*/
@DeleteMapping("/{orderNumber}")
@ApiOperation(value = "根据订单号删除订单", notes = "根据订单号删除订单")
@ApiImplicitParam(name = "orderNumber", value = "订单号", required = true, dataType = "String")
public ResponseEntity<String> delete(@PathVariable("orderNumber") String orderNumber) {
String userId = SecurityUtils.getUser().getUserId();
Order order = orderService.getOrderByOrderNumber(orderNumber);
if (order == null) {
throw new YamiShopBindException("该订单不存在");
}
if (!Objects.equals(order.getUserId(), userId)) {
throw new YamiShopBindException("你没有权限获取该订单信息");
}
// 删除订单
orderService.deleteOrders(Arrays.asList(order));
return ResponseEntity.ok("删除成功");
}
/**
* 获取我的订单订单数量
*/
@GetMapping("/orderCount")
@ApiOperation(value = "获取我的订单订单数量", notes = "获取我的订单订单数量")
public ResponseEntity<OrderCountData> getOrderCount() {
String userId = SecurityUtils.getUser().getUserId();
OrderCountData orderCountMap = orderService.getOrderCount(userId);
return ResponseEntity.ok(orderCountMap);
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.fasterxml.jackson.annotation.JsonView;
import com.sun.tracing.dtrace.ArgsAttributes;
import com.yami.shop.bean.app.dto.IndexImgDto;
import com.yami.shop.bean.app.dto.NoticeDto;
import com.yami.shop.bean.app.dto.ProductDto;
import com.yami.shop.bean.model.IndexImg;
import com.yami.shop.bean.model.Notice;
import com.yami.shop.service.NoticeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/shop/notice")
@Api(tags = "公告管理接口")
@AllArgsConstructor
public class NoticeController {
private NoticeService noticeService;
private MapperFacade mapperFacade;
/**
* 置顶公告列表接口
*/
@GetMapping("/topNoticeList")
@ApiOperation(value = "置顶公告列表信息", notes = "获取所有置顶公告列表信息")
@JsonView(NoticeDto.NoContent.class)
public ResponseEntity<List<NoticeDto>> getTopNoticeList() {
List<Notice> noticeList = noticeService.listNotice();
List<NoticeDto> noticeDtoList = mapperFacade.mapAsList(noticeList, NoticeDto.class);
return ResponseEntity.ok(noticeDtoList);
}
/**
* 获取公告详情
*/
@GetMapping("/info/{id}")
@ApiOperation(value = "公告详情", notes = "获取公告id公告详情")
@JsonView(NoticeDto.WithContent.class)
public ResponseEntity<NoticeDto> getNoticeById(@PathVariable("id") Long id) {
Notice notice = noticeService.getNoticeById(id);
NoticeDto noticeDto = mapperFacade.map(notice, NoticeDto.class);
return ResponseEntity.ok(noticeDto);
}
/**
* 公告列表
*/
@GetMapping("/noticeList")
@ApiOperation(value = "公告列表信息", notes = "获取所有公告列表信息")
@ApiImplicitParams({
})
public ResponseEntity<IPage<NoticeDto>> pageNotice(PageParam<NoticeDto> page) {
return ResponseEntity.ok(noticeService.pageNotice(page));
}
}

View File

@@ -0,0 +1,198 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import java.util.*;
import javax.validation.Valid;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.bean.event.ConfirmOrderEvent;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.bean.app.param.OrderParam;
import com.yami.shop.bean.app.param.OrderShopParam;
import com.yami.shop.bean.app.param.SubmitOrderParam;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.UserAddr;
import com.yami.shop.common.util.Arith;
import cn.hutool.core.collection.CollectionUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
@RestController
@RequestMapping("/p/order")
@Api(tags = "订单接口")
public class OrderController {
@Autowired
private OrderService orderService;
@Autowired
private MapperFacade mapperFacade;
@Autowired
private SkuService skuService;
@Autowired
private ProductService productService;
@Autowired
private UserAddrService userAddrService;
@Autowired
private BasketService basketService;
@Autowired
private ApplicationContext applicationContext;
/**
* 生成订单
*/
@PostMapping("/confirm")
@ApiOperation(value = "结算,生成订单信息", notes = "传入下单所需要的参数进行下单")
public ResponseEntity<ShopCartOrderMergerDto> confirm(@Valid @RequestBody OrderParam orderParam) {
String userId = SecurityUtils.getUser().getUserId();
// 订单的地址信息
UserAddr userAddr = userAddrService.getUserAddrByUserId(orderParam.getAddrId(), userId);
UserAddrDto userAddrDto = mapperFacade.map(userAddr, UserAddrDto.class);
// 组装获取用户提交的购物车商品项
List<ShopCartItemDto> shopCartItems = basketService.getShopCartItemsByOrderItems(orderParam.getBasketIds(),orderParam.getOrderItem(),userId);
if (CollectionUtil.isEmpty(shopCartItems)) {
throw new YamiShopBindException("请选择您需要的商品加入购物车");
}
// 根据店铺组装购车中的商品信息,返回每个店铺中的购物车商品信息
List<ShopCartDto> shopCarts = basketService.getShopCarts(shopCartItems);
// 将要返回给前端的完整的订单信息
ShopCartOrderMergerDto shopCartOrderMergerDto = new ShopCartOrderMergerDto();
shopCartOrderMergerDto.setUserAddr(userAddrDto);
// 所有店铺的订单信息
List<ShopCartOrderDto> shopCartOrders = new ArrayList<>();
double actualTotal = 0.0;
double total = 0.0;
int totalCount = 0;
double orderReduce = 0.0;
// List<CouponOrderDto> coupons = new ArrayList<>();
for (ShopCartDto shopCart : shopCarts) {
// 每个店铺的订单信息
ShopCartOrderDto shopCartOrder = new ShopCartOrderDto();
shopCartOrder.setShopId(shopCart.getShopId());
shopCartOrder.setShopName(shopCart.getShopName());
List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCart.getShopCartItemDiscounts();
// 店铺中的所有商品项信息
List<ShopCartItemDto> shopAllShopCartItems = new ArrayList<>();
for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
List<ShopCartItemDto> discountShopCartItems = shopCartItemDiscount.getShopCartItems();
shopAllShopCartItems.addAll(discountShopCartItems);
}
shopCartOrder.setShopCartItemDiscounts(shopCartItemDiscounts);
applicationContext.publishEvent(new ConfirmOrderEvent(shopCartOrder,orderParam,shopAllShopCartItems));
actualTotal = Arith.add(actualTotal,shopCartOrder.getActualTotal());
total = Arith.add(total,shopCartOrder.getTotal());
totalCount = totalCount + shopCartOrder.getTotalCount();
orderReduce = Arith.add(orderReduce,shopCartOrder.getShopReduce());
shopCartOrders.add(shopCartOrder);
}
shopCartOrderMergerDto.setActualTotal(actualTotal);
shopCartOrderMergerDto.setTotal(total);
shopCartOrderMergerDto.setTotalCount(totalCount);
shopCartOrderMergerDto.setShopCartOrders(shopCartOrders);
shopCartOrderMergerDto.setOrderReduce(orderReduce);
orderService.putConfirmOrderCache(userId,shopCartOrderMergerDto);
return ResponseEntity.ok(shopCartOrderMergerDto);
}
/**
* 购物车/立即购买 提交订单,根据店铺拆单
*/
@PostMapping("/submit")
@ApiOperation(value = "提交订单,返回支付流水号", notes = "根据传入的参数判断是否为购物车提交订单,同时对购物车进行删除,用户开始进行支付")
public ResponseEntity<OrderNumbersDto> submitOrders(@Valid @RequestBody SubmitOrderParam submitOrderParam) {
String userId = SecurityUtils.getUser().getUserId();
ShopCartOrderMergerDto mergerOrder = orderService.getConfirmOrderCache(userId);
if (mergerOrder == null) {
throw new YamiShopBindException("订单已过期,请重新下单");
}
List<OrderShopParam> orderShopParams = submitOrderParam.getOrderShopParam();
List<ShopCartOrderDto> shopCartOrders = mergerOrder.getShopCartOrders();
// 设置备注
if (CollectionUtil.isNotEmpty(orderShopParams)) {
for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
for (OrderShopParam orderShopParam : orderShopParams) {
if (Objects.equals(shopCartOrder.getShopId(), orderShopParam.getShopId())) {
shopCartOrder.setRemarks(orderShopParam.getRemarks());
}
}
}
}
List<Order> orders = orderService.submit(userId,mergerOrder);
StringBuilder orderNumbers = new StringBuilder();
for (Order order : orders) {
orderNumbers.append(order.getOrderNumber()).append(",");
}
orderNumbers.deleteCharAt(orderNumbers.length() - 1);
boolean isShopCartOrder = false;
// 移除缓存
for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartOrder.getShopCartItemDiscounts()) {
for (ShopCartItemDto shopCartItem : shopCartItemDiscount.getShopCartItems()) {
Long basketId = shopCartItem.getBasketId();
if (basketId != null && basketId != 0) {
isShopCartOrder = true;
}
skuService.removeSkuCacheBySkuId(shopCartItem.getSkuId(),shopCartItem.getProdId());
productService.removeProductCacheByProdId(shopCartItem.getProdId());
}
}
}
// 购物车提交订单时(即有购物车ID时)
if (isShopCartOrder) {
basketService.removeShopCartItemsCacheByUserId(userId);
}
orderService.removeConfirmOrderCache(userId);
return ResponseEntity.ok(new OrderNumbersDto(orderNumbers.toString()));
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.service.WxPayService;
import com.yami.shop.api.config.ApiConfig;
import com.yami.shop.bean.app.param.PayParam;
import com.yami.shop.bean.pay.PayInfoDto;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.IPHelper;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.PayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/p/order")
@Api(tags = "订单接口")
@AllArgsConstructor
public class PayController {
private final PayService payService;
private final ApiConfig apiConfig;
private final WxPayService wxMiniPayService;
/**
* 支付接口
*/
@PostMapping("/pay")
@ApiOperation(value = "根据订单号进行支付", notes = "根据订单号进行支付")
@SneakyThrows
public ResponseEntity<WxPayMpOrderResult> pay(@RequestBody PayParam payParam) {
YamiUser user = SecurityUtils.getUser();
String userId = user.getUserId();
String openId = user.getBizUserId();
PayInfoDto payInfo = payService.pay(userId, payParam);
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
orderRequest.setBody(payInfo.getBody());
orderRequest.setOutTradeNo(payInfo.getPayNo());
orderRequest.setTotalFee((int) Arith.mul(payInfo.getPayAmount(), 100));
orderRequest.setSpbillCreateIp(IPHelper.getIpAddr());
orderRequest.setNotifyUrl(apiConfig.getDomainName() + "/notice/pay/order");
orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);
orderRequest.setOpenid(openId);
return ResponseEntity.ok(wxMiniPayService.createOrder(orderRequest));
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.yami.shop.service.PayService;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
@ApiIgnore
@RestController
@RequestMapping("/notice/pay")
@AllArgsConstructor
public class PayNoticeController {
/**
* 小程序支付
*/
private final WxPayService wxMiniPayService;
private final PayService payService;
@RequestMapping("/order")
public ResponseEntity<?> submit(@RequestBody String xmlData) throws WxPayException {
WxPayOrderNotifyResult parseOrderNotifyResult = wxMiniPayService.parseOrderNotifyResult(xmlData);
String payNo = parseOrderNotifyResult.getOutTradeNo();
String bizPayNo = parseOrderNotifyResult.getTransactionId();
// 根据内部订单号更新order settlement
payService.paySuccess(payNo, bizPayNo);
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.app.dto.ProdCommDataDto;
import com.yami.shop.bean.app.dto.ProdCommDto;
import com.yami.shop.bean.app.param.ProdCommParam;
import com.yami.shop.bean.model.ProdComm;
import com.yami.shop.common.util.Json;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.ProdCommService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
@RestController
@RequestMapping("/prodComm")
@Api(tags = "评论接口")
@AllArgsConstructor
public class ProdCommController {
private final ProdCommService prodCommService;
@GetMapping("/prodCommData")
@ApiOperation(value = "返回商品评论数据(好评率 好评数量 中评数 差评数)", notes = "根据商品id获取")
public ResponseEntity<ProdCommDataDto> getProdCommData(Long prodId) {
return ResponseEntity.ok(prodCommService.getProdCommDataByProdId(prodId, SecurityUtils.getUser().getUserId()));
}
@GetMapping("/prodCommPageByUser")
@ApiOperation(value = "根据用户返回评论分页数据", notes = "传入页码")
public ResponseEntity<IPage<ProdCommDto>> getProdCommPage(PageParam page) {
return ResponseEntity.ok(prodCommService.getProdCommDtoPageByUserId(page, SecurityUtils.getUser().getUserId()));
}
@GetMapping("/prodCommPageByProd")
@ApiOperation(value = "根据商品返回评论分页数据", notes = "传入商品id和页码")
@ApiImplicitParams({
@ApiImplicitParam(name = "prodId", value = "商品id", required = true, dataType = "Long"),
@ApiImplicitParam(name = "evaluate", value = "-1或null 全部0好评 1中评 2差评 3有图", required = true, dataType = "Long"),
})
public ResponseEntity<IPage<ProdCommDto>> getProdCommPageByProdId(PageParam page, Long prodId, Integer evaluate) {
return ResponseEntity.ok(prodCommService.getProdCommDtoPageByProdId(page, prodId, evaluate, SecurityUtils.getUser().getUserId()));
}
@PostMapping
@ApiOperation(value = "添加评论")
public ResponseEntity<Void> saveProdCommPage(ProdCommParam prodCommParam) {
ProdComm prodComm = new ProdComm();
prodComm.setProdId(prodCommParam.getProdId());
prodComm.setOrderItemId(prodCommParam.getOrderItemId());
prodComm.setUserId(SecurityUtils.getUser().getUserId());
prodComm.setScore(prodCommParam.getScore());
prodComm.setContent(prodCommParam.getContent());
prodComm.setPics(prodCommParam.getPics());
prodComm.setIsAnonymous(prodCommParam.getIsAnonymous());
prodComm.setRecTime(new Date());
prodComm.setStatus(0);
prodComm.setEvaluate(prodCommParam.getEvaluate());
prodCommService.save(prodComm);
return ResponseEntity.ok().build();
}
@DeleteMapping
@ApiOperation(value = "删除评论", notes = "根据id删除")
public ResponseEntity<Void> deleteProdComm(Long prodCommId) {
prodCommService.removeById(prodCommId);
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import java.util.List;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.fasterxml.jackson.annotation.JsonView;
import com.yami.shop.bean.app.dto.SkuDto;
import com.yami.shop.bean.app.dto.TagProductDto;
import com.yami.shop.bean.model.Basket;
import com.yami.shop.bean.model.Sku;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.service.*;
import io.swagger.annotations.ApiImplicitParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.yami.shop.bean.app.dto.ProductDto;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.Transport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
@RestController
@RequestMapping("/prod")
@Api(tags = "商品接口")
public class ProdController {
@Autowired
private ProductService prodService;
@Autowired
private MapperFacade mapperFacade;
@Autowired
private SkuService skuService;
@Autowired
private TransportService transportService;
@GetMapping("/pageProd")
@ApiOperation(value = "通过分类id商品列表信息", notes = "根据分类ID获取该分类下所有的商品列表信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "categoryId", value = "分类ID", required = true, dataType = "Long"),
})
public ResponseEntity<IPage<ProductDto>> prodList(
@RequestParam(value = "categoryId") Long categoryId,PageParam<ProductDto> page) {
IPage<ProductDto> productDtoIPage = prodService.pageByCategoryId(page, categoryId);
return ResponseEntity.ok(productDtoIPage);
}
@GetMapping("/prodInfo")
@ApiOperation(value = "商品详情信息", notes = "根据商品IDprodId获取商品信息")
@ApiImplicitParam(name = "prodId", value = "商品ID", required = true, dataType = "Long")
public ResponseEntity<ProductDto> prodInfo(Long prodId) {
Product product = prodService.getProductByProdId(prodId);
if (product == null) {
return ResponseEntity.ok(null);
}
List<Sku> skuList = skuService.listByProdId(prodId);
// 启用的sku列表
List<Sku> useSkuList = skuList.stream().filter(sku -> sku.getStatus() == 1).collect(Collectors.toList());
product.setSkuList(useSkuList);
ProductDto productDto = mapperFacade.map(product, ProductDto.class);
Transport transportAndAllItems = transportService.getTransportAndAllItems(product.getDeliveryTemplateId());
productDto.setTransport(transportAndAllItems);
return ResponseEntity.ok(productDto);
}
@GetMapping("/lastedProdPage")
@ApiOperation(value = "新品推荐", notes = "获取新品推荐商品列表")
@ApiImplicitParams({
})
public ResponseEntity<IPage<ProductDto>> lastedProdPage(PageParam<ProductDto> page) {
IPage<ProductDto> productDtoIPage = prodService.pageByPutawayTime(page);
return ResponseEntity.ok(productDtoIPage);
}
@GetMapping("/prodListByTagId")
@ApiOperation(value = "通过分组标签获取商品列表", notes = "通过分组标签idtagId获取商品列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "tagId", value = "当前页默认为1", required = true, dataType = "Long"),
})
public ResponseEntity<IPage<ProductDto>> prodListByTagId(
@RequestParam(value = "tagId") Long tagId,PageParam<ProductDto> page) {
IPage<ProductDto> productDtoIPage = prodService.pageByTagId(page, tagId);
return ResponseEntity.ok(productDtoIPage);
}
@GetMapping("/discountProdList")
@ApiOperation(value = "限时特惠", notes = "获取限时特惠商品列表")
@ApiImplicitParams({
})
public ResponseEntity<IPage<ProductDto>> discountProdList(PageParam<ProductDto> page) {
IPage<ProductDto> productDtoIPage = prodService.discountProdList(page);
return ResponseEntity.ok(productDtoIPage);
}
@GetMapping("/moreBuyProdList")
@ApiOperation(value = "每日疯抢", notes = "获取销量最多的商品列表")
@ApiImplicitParams({})
public ResponseEntity<IPage<ProductDto>> moreBuyProdList(PageParam<ProductDto> page) {
IPage<ProductDto> productDtoIPage = prodService.moreBuyProdList(page);
return ResponseEntity.ok(productDtoIPage);
}
@GetMapping("/tagProdList")
@ApiOperation(value = "首页所有标签商品接口", notes = "获取首页所有标签商品接口")
public ResponseEntity<List<TagProductDto>> getTagProdList() {
List<TagProductDto> productDtoList = prodService.tagProdList();
return ResponseEntity.ok(productDtoList);
}
@GetMapping("/discountProds")
@ApiOperation(value = "根据活动id获取活动商品列表", notes = "根据活动id获取活动商品列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "discountId", value = "活动id", required = true, dataType = "Long"),
})
public ResponseEntity<IPage<ProductDto>> getDiscountProds(
@RequestParam(value = "discountId", required = true) Long discountId,
PageParam<ProductDto> page) {
IPage<ProductDto> productDtoList = prodService.pageByDiscountId(page, discountId);
return ResponseEntity.ok(productDtoList);
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.app.dto.ProdTagDto;
import com.yami.shop.bean.model.ProdTag;
import com.yami.shop.service.ProdTagService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.http.ResponseEntity;
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;
@RestController
@RequestMapping("/prod/tag")
@Api(tags = "商品分组标签接口")
@AllArgsConstructor
public class ProdTagController {
private ProdTagService prodTagService;
private MapperFacade mapperFacade;
/**
* 商品分组标签列表接口
*/
@GetMapping("/prodTagList")
@ApiOperation(value = "商品分组标签列表", notes = "获取所有的商品分组列表")
public ResponseEntity<List<ProdTagDto>> getProdTagList() {
List<ProdTag> prodTagList = prodTagService.listProdTag();
List<ProdTagDto> prodTagDtoList = mapperFacade.mapAsList(prodTagList, ProdTagDto.class);
return ResponseEntity.ok(prodTagDtoList);
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.dto.HotSearchDto;
import com.yami.shop.bean.dto.SearchProdDto;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.service.HotSearchService;
import com.yami.shop.service.ProductService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
@RestController
@RequestMapping("/search")
@Api(tags = "搜索接口")
@AllArgsConstructor
public class SearchController {
private final HotSearchService hotSearchService;
private final ProductService productService;
@GetMapping("/hotSearchByShopId")
@ApiOperation(value = "查看店铺热搜", notes = "根据店铺id,热搜数量获取热搜")
@ApiImplicitParams({
@ApiImplicitParam(name = "shopId", value = "店铺id", required = true, dataType = "Long"),
@ApiImplicitParam(name = "number", value = "取数", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "sort", value = "是否按照顺序(0 否 1是)", required = false, dataType = "Integer"),
})
public ResponseEntity<List<HotSearchDto>> hotSearchByShopId(Long shopId,Integer number,Integer sort) {
List<HotSearchDto> list = hotSearchService.getHotSearchDtoByshopId(shopId);
return getListResponseEntity(number, sort, list);
}
@GetMapping("/hotSearch")
@ApiOperation(value = "查看全局热搜", notes = "根据店铺id,热搜数量获取热搜")
@ApiImplicitParams({
@ApiImplicitParam(name = "number", value = "取数", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "sort", value = "是否按照顺序(0 否 1是)", required = false, dataType = "Integer"),
})
public ResponseEntity<List<HotSearchDto>> hotSearch(Integer number,Integer sort) {
List<HotSearchDto> list = hotSearchService.getHotSearchDtoByshopId(0L);
return getListResponseEntity(number, sort, list);
}
private ResponseEntity<List<HotSearchDto>> getListResponseEntity(Integer number, Integer sort, List<HotSearchDto> list) {
if(sort == null || sort == 0){
Collections.shuffle(list);
}
if(!CollectionUtil.isNotEmpty(list) || list.size()< number){
return ResponseEntity.ok(list);
}
return ResponseEntity.ok(list.subList(0, number));
}
@GetMapping("/searchProdPage")
@ApiOperation(value = "分页排序搜索商品", notes = "根据商品名搜索")
@ApiImplicitParams({
@ApiImplicitParam(name = "prodName", value = "商品名", required = true, dataType = "String"),
@ApiImplicitParam(name = "sort", value = "排序(0 默认排序 1销量排序 2价格排序)", required = false, dataType = "Integer"),
@ApiImplicitParam(name = "orderBy", value = "排序(0升序 1降序)", required = false, dataType = "Integer"),
@ApiImplicitParam(name = "shopId", value = "店铺id", required = true, dataType = "Long"),
})
public ResponseEntity<IPage<SearchProdDto>> searchProdPage(PageParam page, String prodName, Integer sort, Integer orderBy, Long shopId) {
return ResponseEntity.ok(productService.getSearchProdDtoPageByProdName(page,prodName,sort,orderBy));
}
}

View File

@@ -0,0 +1,246 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import com.google.common.collect.Lists;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.bean.app.param.ChangeShopCartParam;
import com.yami.shop.bean.app.param.ShopCartParam;
import com.yami.shop.bean.event.ShopCartEvent;
import com.yami.shop.bean.model.*;
import com.yami.shop.common.util.Arith;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.*;
import io.swagger.annotations.*;
import lombok.AllArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/p/shopCart")
@Api(tags = "购物车接口")
@AllArgsConstructor
public class ShopCartController {
private BasketService basketService;
private ProductService productService;
private SkuService skuService;
private ApplicationContext applicationContext;
/**
* 获取用户购物车信息
*
* @param basketIdShopCartParamMap 购物车参数对象列表
* @return
*/
@PostMapping("/info")
@ApiOperation(value = "获取用户购物车信息", notes = "获取用户购物车信息,参数为用户选中的活动项数组,以购物车id为key")
public ResponseEntity<List<ShopCartDto>> info(@RequestBody Map<Long, ShopCartParam> basketIdShopCartParamMap) {
String userId = SecurityUtils.getUser().getUserId();
// 更新购物车信息,
if (MapUtil.isNotEmpty(basketIdShopCartParamMap)) {
basketService.updateBasketByShopCartParam(userId, basketIdShopCartParamMap);
}
// 拿到购物车的所有item
List<ShopCartItemDto> shopCartItems = basketService.getShopCartItems(userId);
return ResponseEntity.ok(basketService.getShopCarts(shopCartItems));
}
@DeleteMapping("/deleteItem")
@ApiOperation(value = "删除用户购物车物品", notes = "通过购物车id删除用户购物车物品")
public ResponseEntity<Void> deleteItem(@RequestBody List<Long> basketIds) {
String userId = SecurityUtils.getUser().getUserId();
basketService.deleteShopCartItemsByBasketIds(userId, basketIds);
return ResponseEntity.ok().build();
}
@DeleteMapping("/deleteAll")
@ApiOperation(value = "清空用户购物车所有物品", notes = "清空用户购物车所有物品")
public ResponseEntity<String> deleteAll() {
String userId = SecurityUtils.getUser().getUserId();
basketService.deleteAllShopCartItems(userId);
return ResponseEntity.ok("删除成功");
}
@PostMapping("/changeItem")
@ApiOperation(value = "添加、修改用户购物车物品", notes = "通过商品id(prodId)、skuId、店铺Id(shopId),添加/修改用户购物车商品,并传入改变的商品个数(count)" +
"当count为正值时增加商品数量当count为负值时将减去商品的数量当最终count值小于0时会将商品从购物车里面删除")
public ResponseEntity<String> addItem(@Valid @RequestBody ChangeShopCartParam param) {
if (param.getCount() == 0) {
return ResponseEntity.badRequest().body("输入更改数量");
}
String userId = SecurityUtils.getUser().getUserId();
List<ShopCartItemDto> shopCartItems = basketService.getShopCartItems(userId);
Product prodParam = productService.getProductByProdId(param.getProdId());
Sku skuParam = skuService.getSkuBySkuId(param.getSkuId());
// 当商品状态不正常时,不能添加到购物车
if (prodParam.getStatus() != 1 || skuParam.getStatus() != 1) {
return ResponseEntity.badRequest().body("当前商品已下架");
}
for (ShopCartItemDto shopCartItemDto : shopCartItems) {
if (Objects.equals(param.getSkuId(), shopCartItemDto.getSkuId())) {
Basket basket = new Basket();
basket.setUserId(userId);
basket.setBasketCount(param.getCount() + shopCartItemDto.getProdCount());
basket.setBasketId(shopCartItemDto.getBasketId());
// 防止购物车变成负数
if (basket.getBasketCount() <= 0) {
basketService.deleteShopCartItemsByBasketIds(userId, Collections.singletonList(basket.getBasketId()));
return ResponseEntity.ok().build();
}
// 当sku实际库存不足时不能添加到购物车
if (skuParam.getStocks() < basket.getBasketCount() && shopCartItemDto.getProdCount() > 0) {
return ResponseEntity.badRequest().body("库存不足");
}
basketService.updateShopCartItem(basket);
return ResponseEntity.ok().build();
}
}
// 防止购物车已被删除的情况下,添加了负数的商品
if (param.getCount() < 0) {
return ResponseEntity.badRequest().body("商品已从购物车移除");
}
// 当sku实际库存不足时不能添加到购物车
if (skuParam.getStocks() < param.getCount()) {
return ResponseEntity.badRequest().body("库存不足");
}
// 所有都正常时
basketService.addShopCartItem(param,userId);
return ResponseEntity.ok("添加成功");
}
@GetMapping("/prodCount")
@ApiOperation(value = "获取购物车商品数量", notes = "获取所有购物车商品数量")
public ResponseEntity<Integer> prodCount() {
String userId = SecurityUtils.getUser().getUserId();
List<ShopCartItemDto> shopCartItems = basketService.getShopCartItems(userId);
if (CollectionUtil.isEmpty(shopCartItems)) {
return ResponseEntity.ok(0);
}
Integer totalCount = shopCartItems.stream().map(ShopCartItemDto::getProdCount).reduce(0, Integer::sum);
return ResponseEntity.ok(totalCount);
}
@GetMapping("/expiryProdList")
@ApiOperation(value = "获取购物车失效商品信息", notes = "获取购物车失效商品列表")
public ResponseEntity<List<ShopCartExpiryItemDto>> expiryProdList() {
String userId = SecurityUtils.getUser().getUserId();
List<ShopCartItemDto> shopCartItems = basketService.getShopCartExpiryItems(userId);
//根据店铺ID划分item
Map<Long, List<ShopCartItemDto>> shopCartItemDtoMap = shopCartItems.stream().collect(Collectors.groupingBy(ShopCartItemDto::getShopId));
// 返回一个店铺对应的所有信息
List<ShopCartExpiryItemDto> shopcartExpiryitems = Lists.newArrayList();
for (Long key : shopCartItemDtoMap.keySet()) {
ShopCartExpiryItemDto shopCartExpiryItemDto = new ShopCartExpiryItemDto();
shopCartExpiryItemDto.setShopId(key);
List<ShopCartItemDto> shopCartItemDtos = Lists.newArrayList();
for (ShopCartItemDto tempShopCartItemDto : shopCartItemDtoMap.get(key)) {
shopCartExpiryItemDto.setShopName(tempShopCartItemDto.getShopName());
shopCartItemDtos.add(tempShopCartItemDto);
}
shopCartExpiryItemDto.setShopCartItemDtoList(shopCartItemDtos);
shopcartExpiryitems.add(shopCartExpiryItemDto);
}
return ResponseEntity.ok(shopcartExpiryitems);
}
@DeleteMapping("/cleanExpiryProdList")
@ApiOperation(value = "清空用户失效商品", notes = "清空用户失效商品")
public ResponseEntity<Void> cleanExpiryProdList() {
String userId = SecurityUtils.getUser().getUserId();
basketService.cleanExpiryProdList(userId);
return ResponseEntity.ok().build();
}
@PostMapping("/totalPay")
@ApiOperation(value = "获取选中购物项总计、选中的商品数量", notes = "获取选中购物项总计、选中的商品数量,参数为购物车id数组")
public ResponseEntity<ShopCartAmountDto> getTotalPay(@RequestBody List<Long> basketIds) {
// 拿到购物车的所有item
List<ShopCartItemDto> dbShopCartItems = basketService.getShopCartItems(SecurityUtils.getUser().getUserId());
List<ShopCartItemDto> chooseShopCartItems = dbShopCartItems
.stream()
.filter(shopCartItemDto -> {
for (Long basketId : basketIds) {
if (Objects.equals(basketId,shopCartItemDto.getBasketId())) {
return true;
}
}
return false;
})
.collect(Collectors.toList());
// 根据店铺ID划分item
Map<Long, List<ShopCartItemDto>> shopCartMap = chooseShopCartItems.stream().collect(Collectors.groupingBy(ShopCartItemDto::getShopId));
double total = 0.0;
int count = 0;
double reduce = 0.0;
for (Long shopId : shopCartMap.keySet()) {
//获取店铺的所有商品项
List<ShopCartItemDto> shopCartItemDtoList = shopCartMap.get(shopId);
// 构建每个店铺的购物车信息
ShopCartDto shopCart = new ShopCartDto();
shopCart.setShopId(shopId);
applicationContext.publishEvent(new ShopCartEvent(shopCart, shopCartItemDtoList));
List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCart.getShopCartItemDiscounts();
for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
List<ShopCartItemDto> shopCartItems = shopCartItemDiscount.getShopCartItems();
ChooseDiscountItemDto chooseDiscountItemDto = shopCartItemDiscount.getChooseDiscountItemDto();
// 如果满足优惠活动
if (chooseDiscountItemDto != null && chooseDiscountItemDto.getNeedAmount() <= chooseDiscountItemDto.getProdsPrice()) {
reduce = Arith.add(reduce, chooseDiscountItemDto.getReduceAmount());
}
for (ShopCartItemDto shopCartItem : shopCartItems) {
count = shopCartItem.getProdCount() + count;
total = Arith.add(shopCartItem.getProductTotalAmount(), total);
}
}
}
ShopCartAmountDto shopCartAmountDto = new ShopCartAmountDto();
shopCartAmountDto.setCount(count);
shopCartAmountDto.setTotalMoney(total);
shopCartAmountDto.setSubtractMoney(reduce);
shopCartAmountDto.setFinalMoney(Arith.sub(shopCartAmountDto.getTotalMoney(), shopCartAmountDto.getSubtractMoney()));
return ResponseEntity.ok(shopCartAmountDto);
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.app.dto.SkuDto;
import com.yami.shop.bean.model.Sku;
import com.yami.shop.service.SkuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.http.ResponseEntity;
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;
@RestController
@RequestMapping("/sku")
@Api(tags = "sku规格接口")
@AllArgsConstructor
public class SkuController {
private final SkuService skuService;
private final MapperFacade mapperFacade;
@GetMapping("/getSkuList")
@ApiOperation(value = "通过prodId获取商品全部规格列表", notes = "通过prodId获取商品全部规格列表")
@ApiImplicitParam(name = "prodId", value = "商品id", dataType = "Long")
public ResponseEntity<List<SkuDto>> getSkuListByProdId(Long prodId) {
List<Sku> skus = skuService.list(new LambdaQueryWrapper<Sku>()
.eq(Sku::getStatus, 1)
.eq(Sku::getIsDelete, 0)
.eq(Sku::getProdId, prodId)
);
List<SkuDto> skuDtoList = mapperFacade.mapAsList(skus, SkuDto.class);
return ResponseEntity.ok(skuDtoList);
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import com.yami.shop.security.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.google.common.collect.Maps;
import com.yami.shop.bean.app.param.SendSmsParam;
import com.yami.shop.bean.enums.SmsType;
import com.yami.shop.service.SmsLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@RestController
@RequestMapping("/p/sms")
@Api(tags="发送验证码接口")
public class SmsController {
@Autowired
private SmsLogService smsLogService;
/**
* 发送验证码接口
*/
@PostMapping("/send")
@ApiOperation(value="发送验证码", notes="用户的发送验证码")
public ResponseEntity<Void> audit(@RequestBody SendSmsParam sendSmsParam) {
String userId = SecurityUtils.getUser().getUserId();
smsLogService.sendSms(SmsType.VALID, userId, sendSmsParam.getMobile(),Maps.newHashMap());
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.app.dto.ProductDto;
import com.yami.shop.bean.app.dto.UserCollectionDto;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.UserCollection;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.UserCollectionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.Objects;
@RestController
@RequestMapping("/p/user/collection")
@Api(tags = "收藏接口")
@AllArgsConstructor
public class UserCollectionController {
private final UserCollectionService userCollectionService;
private final ProductService productService;
@GetMapping("/page")
@ApiOperation(value = "分页返回收藏数据", notes = "根据用户id获取")
public ResponseEntity<IPage<UserCollectionDto>> getUserCollectionDtoPageByUserId(PageParam page) {
return ResponseEntity.ok(userCollectionService.getUserCollectionDtoPageByUserId(page, SecurityUtils.getUser().getUserId()));
}
@GetMapping("isCollection")
@ApiOperation(value = "根据商品id获取该商品是否在收藏夹中", notes = "传入收藏商品id")
public ResponseEntity<Boolean> isCollection(Long prodId) {
if (productService.count(new LambdaQueryWrapper<Product>()
.eq(Product::getProdId, prodId)) < 1) {
throw new YamiShopBindException("该商品不存在");
}
return ResponseEntity.ok(userCollectionService.count(new LambdaQueryWrapper<UserCollection>()
.eq(UserCollection::getProdId, prodId)
.eq(UserCollection::getUserId, SecurityUtils.getUser().getUserId())) > 0);
}
@PostMapping("/addOrCancel")
@ApiOperation(value = "添加/取消收藏", notes = "传入收藏商品id,如果商品未收藏则收藏商品,已收藏则取消收藏")
@ApiImplicitParam(name = "prodId", value = "商品id", required = true, dataType = "Long")
public ResponseEntity<Void> addOrCancel(@RequestBody Long prodId) {
if (Objects.isNull(productService.getProductByProdId(prodId))) {
throw new YamiShopBindException("该商品不存在");
}
String userId = SecurityUtils.getUser().getUserId();
if (userCollectionService.count(new LambdaQueryWrapper<UserCollection>()
.eq(UserCollection::getProdId, prodId)
.eq(UserCollection::getUserId, userId)) > 0) {
userCollectionService.remove(new LambdaQueryWrapper<UserCollection>()
.eq(UserCollection::getProdId, prodId)
.eq(UserCollection::getUserId, userId));
} else {
UserCollection userCollection = new UserCollection();
userCollection.setCreateTime(new Date());
userCollection.setUserId(userId);
userCollection.setProdId(prodId);
userCollectionService.save(userCollection);
}
return ResponseEntity.ok().build();
}
/**
* 查询用户收藏商品数量
*/
@GetMapping("count")
@ApiOperation(value = "查询用户收藏商品数量", notes = "查询用户收藏商品数量")
public int findUserCollectionCount() {
String userId = SecurityUtils.getUser().getUserId();
return userCollectionService.count(new LambdaQueryWrapper<UserCollection>().eq(UserCollection::getUserId, userId));
}
@GetMapping("/prods")
@ApiOperation(value = "获取用户收藏商品列表", notes = "获取用户收藏商品列表")
public ResponseEntity<IPage<ProductDto>> collectionProds(PageParam page) {
String userId = SecurityUtils.getUser().getUserId();
IPage<ProductDto> productDtoIPage = productService.collectionProds(page, userId);
return ResponseEntity.ok(productDtoIPage);
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.controller;
import cn.hutool.core.util.StrUtil;
import com.yami.shop.common.util.CacheManagerUtil;
import com.yami.shop.security.enums.App;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.bean.app.dto.UserDto;
import com.yami.shop.bean.app.param.UserInfoParam;
import com.yami.shop.bean.model.User;
import com.yami.shop.service.UserService;
import cn.hutool.extra.emoji.EmojiUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
@RestController
@RequestMapping("/p/user")
@Api(tags="用户接口")
@AllArgsConstructor
public class UserController {
private final UserService userService;
private final MapperFacade mapperFacade;
private final CacheManagerUtil cacheManagerUtil;
/**
* 查看用户接口
*/
@GetMapping("/userInfo")
@ApiOperation(value="查看用户信息", notes="根据用户IDuserId获取用户信息")
public ResponseEntity<UserDto> userInfo() {
String userId = SecurityUtils.getUser().getUserId();
User user = userService.getById(userId);
UserDto userDto = mapperFacade.map(user, UserDto.class);
return ResponseEntity.ok(userDto);
}
@PutMapping("/setUserInfo")
@ApiOperation(value="设置用户信息", notes="设置用户信息")
public ResponseEntity<Void> setUserInfo(@RequestBody UserInfoParam userInfoParam) {
String userId = SecurityUtils.getUser().getUserId();
User user = new User();
user.setUserId(userId);
user.setPic(userInfoParam.getAvatarUrl());
user.setNickName(EmojiUtil.toAlias(userInfoParam.getNickName()));
userService.updateById(user);
String cacheKey = App.MINI.value() + StrUtil.COLON + SecurityUtils.getUser().getBizUserId();
cacheManagerUtil.evictCache("yami_user", cacheKey);
return ResponseEntity.ok(null);
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.listener;
import com.google.common.collect.Lists;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.bean.app.param.OrderParam;
import com.yami.shop.bean.event.ConfirmOrderEvent;
import com.yami.shop.bean.event.ShopCartEvent;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.Sku;
import com.yami.shop.bean.model.UserAddr;
import com.yami.shop.bean.order.ConfirmOrderOrder;
import com.yami.shop.bean.order.ShopCartEventOrder;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.SkuService;
import com.yami.shop.service.TransportManagerService;
import com.yami.shop.service.UserAddrService;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* 确认订单信息时的默认操作
* @author LGH
*/
@Component("defaultConfirmOrderListener")
@AllArgsConstructor
public class ConfirmOrderListener {
private final UserAddrService userAddrService;
private final TransportManagerService transportManagerService;
private final ProductService productService;
private final SkuService skuService;
/**
* 计算订单金额
*/
@EventListener(ConfirmOrderEvent.class)
@Order(ConfirmOrderOrder.DEFAULT)
public void defaultConfirmOrderEvent(ConfirmOrderEvent event) {
ShopCartOrderDto shopCartOrderDto = event.getShopCartOrderDto();
OrderParam orderParam = event.getOrderParam();
String userId = SecurityUtils.getUser().getUserId();
// 订单的地址信息
UserAddr userAddr = userAddrService.getUserAddrByUserId(orderParam.getAddrId(), userId);
double total = 0.0;
int totalCount = 0;
double transfee = 0.0;
for (ShopCartItemDto shopCartItem : event.getShopCartItems()) {
// 获取商品信息
Product product = productService.getProductByProdId(shopCartItem.getProdId());
// 获取sku信息
Sku sku = skuService.getSkuBySkuId(shopCartItem.getSkuId());
if (product == null || sku == null) {
throw new YamiShopBindException("购物车包含无法识别的商品");
}
if (product.getStatus() != 1 || sku.getStatus() != 1) {
throw new YamiShopBindException("商品[" + sku.getProdName() + "]已下架");
}
totalCount = shopCartItem.getProdCount() + totalCount;
total = Arith.add(shopCartItem.getProductTotalAmount(), total);
// 用户地址如果为空,则表示该用户从未设置过任何地址相关信息
if (userAddr != null) {
// 每个产品的运费相加
transfee = Arith.add(transfee, transportManagerService.calculateTransfee(shopCartItem, userAddr));
}
shopCartItem.setActualTotal(shopCartItem.getProductTotalAmount());
shopCartOrderDto.setActualTotal(Arith.sub(total, transfee));
shopCartOrderDto.setTotal(total);
shopCartOrderDto.setTotalCount(totalCount);
shopCartOrderDto.setTransfee(transfee);
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.listener;
import com.google.common.collect.Lists;
import com.yami.shop.bean.app.dto.ShopCartDto;
import com.yami.shop.bean.app.dto.ShopCartItemDiscountDto;
import com.yami.shop.bean.app.dto.ShopCartItemDto;
import com.yami.shop.bean.event.ShopCartEvent;
import com.yami.shop.bean.order.ShopCartEventOrder;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 默认的购物车链进行组装时的操作
* @author LGH
*/
@Component("defaultShopCartListener")
public class ShopCartListener {
/**
* 将店铺下的所有商品归属到该店铺的购物车当中
* @param event#getShopCart() 购物车
* @param event#shopCartItemDtoList 该购物车的商品
* @return 是否继续组装
*/
@EventListener(ShopCartEvent.class)
@Order(ShopCartEventOrder.DEFAULT)
public void defaultShopCartEvent(ShopCartEvent event) {
ShopCartDto shopCart = event.getShopCartDto();
List<ShopCartItemDto> shopCartItemDtoList = event.getShopCartItemDtoList();
// 对数据进行组装
List<ShopCartItemDiscountDto> shopCartItemDiscountDtoList = Lists.newArrayList();
ShopCartItemDiscountDto shopCartItemDiscountDto = new ShopCartItemDiscountDto();
shopCartItemDiscountDto.setShopCartItems(shopCartItemDtoList);
shopCartItemDiscountDtoList.add(shopCartItemDiscountDto);
shopCart.setShopCartItemDiscounts(shopCartItemDiscountDtoList);
}
}

View File

@@ -0,0 +1,288 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.listener;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.StrUtil;
import com.yami.shop.bean.app.dto.ShopCartItemDiscountDto;
import com.yami.shop.bean.app.dto.ShopCartItemDto;
import com.yami.shop.bean.app.dto.ShopCartOrderDto;
import com.yami.shop.bean.app.dto.ShopCartOrderMergerDto;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.event.SubmitOrderEvent;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.order.SubmitOrderOrder;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.dao.*;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.SkuService;
import com.yami.shop.service.UserAddrOrderService;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* 确认订单信息时的默认操作
*
* @author LGH
*/
@Component("defaultSubmitOrderListener")
@AllArgsConstructor
public class SubmitOrderListener {
private final MapperFacade mapperFacade;
private final UserAddrOrderService userAddrOrderService;
private final ProductService productService;
private final SkuService skuService;
private final Snowflake snowflake;
private final OrderItemMapper orderItemMapper;
private final SkuMapper skuMapper;
private final ProductMapper productMapper;
private final OrderMapper orderMapper;
private final OrderSettlementMapper orderSettlementMapper;
private final BasketMapper basketMapper;
/**
* 计算订单金额
*/
@EventListener(SubmitOrderEvent.class)
@Order(SubmitOrderOrder.DEFAULT)
public void defaultSubmitOrderListener(SubmitOrderEvent event) {
Date now = new Date();
String userId = SecurityUtils.getUser().getUserId();
ShopCartOrderMergerDto mergerOrder = event.getMergerOrder();
// 订单商品参数
List<ShopCartOrderDto> shopCartOrders = mergerOrder.getShopCartOrders();
List<Long> basketIds = new ArrayList<>();
// 商品skuid为key 需要更新的sku为value的map
Map<Long, Sku> skuStocksMap = new HashMap<>(16);
// 商品productid为key 需要更新的product为value的map
Map<Long, Product> prodStocksMap = new HashMap<>(16);
// 把订单地址保存到数据库
UserAddrOrder userAddrOrder = mapperFacade.map(mergerOrder.getUserAddr(), UserAddrOrder.class);
if (userAddrOrder == null) {
throw new YamiShopBindException("请填写收货地址");
}
userAddrOrder.setUserId(userId);
userAddrOrder.setCreateTime(now);
userAddrOrderService.save(userAddrOrder);
// 订单地址id
Long addrOrderId = userAddrOrder.getAddrOrderId();
// 每个店铺生成一个订单
for (ShopCartOrderDto shopCartOrderDto : shopCartOrders) {
// 使用雪花算法生成的订单号
String orderNumber = String.valueOf(snowflake.nextId());
shopCartOrderDto.setOrderNumber(orderNumber);
Long shopId = shopCartOrderDto.getShopId();
// 订单商品名称
StringBuilder orderProdName = new StringBuilder(100);
List<OrderItem> orderItems = new ArrayList<>();
List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCartOrderDto.getShopCartItemDiscounts();
for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
List<ShopCartItemDto> shopCartItems = shopCartItemDiscount.getShopCartItems();
for (ShopCartItemDto shopCartItem : shopCartItems) {
Sku sku = checkAndGetSku(shopCartItem.getSkuId(), shopCartItem, skuStocksMap);
Product product = checkAndGetProd(shopCartItem.getProdId(), shopCartItem, prodStocksMap);
OrderItem orderItem = new OrderItem();
orderItem.setShopId(shopId);
orderItem.setOrderNumber(orderNumber);
orderItem.setProdId(sku.getProdId());
orderItem.setSkuId(sku.getSkuId());
orderItem.setSkuName(sku.getSkuName());
orderItem.setProdCount(shopCartItem.getProdCount());
orderItem.setProdName(sku.getProdName());
orderItem.setPic(StrUtil.isBlank(sku.getPic()) ? product.getPic() : sku.getPic());
orderItem.setPrice(shopCartItem.getPrice());
orderItem.setUserId(userId);
orderItem.setProductTotalAmount(shopCartItem.getProductTotalAmount());
orderItem.setRecTime(now);
orderItem.setCommSts(0);
orderItem.setBasketDate(shopCartItem.getBasketDate());
orderProdName.append(orderItem.getProdName()).append(",");
//推广员卡号
orderItem.setDistributionCardNo(shopCartItem.getDistributionCardNo());
orderItems.add(orderItem);
if (shopCartItem.getBasketId() != null && shopCartItem.getBasketId() != 0) {
basketIds.add(shopCartItem.getBasketId());
}
}
}
orderProdName.subSequence(0, Math.min(orderProdName.length() - 1, 100));
if (orderProdName.lastIndexOf(",") == orderProdName.length() - 1) {
orderProdName.deleteCharAt(orderProdName.length() - 1);
}
// 订单信息
com.yami.shop.bean.model.Order order = new com.yami.shop.bean.model.Order();
order.setShopId(shopId);
order.setOrderNumber(orderNumber);
// 订单商品名称
order.setProdName(orderProdName.toString());
// 用户id
order.setUserId(userId);
// 商品总额
order.setTotal(shopCartOrderDto.getTotal());
// 实际总额
order.setActualTotal(shopCartOrderDto.getActualTotal());
order.setStatus(OrderStatus.UNPAY.value());
order.setUpdateTime(now);
order.setCreateTime(now);
order.setIsPayed(0);
order.setDeleteStatus(0);
order.setProductNums(shopCartOrderDto.getTotalCount());
order.setAddrOrderId(addrOrderId);
order.setReduceAmount(Arith.sub(shopCartOrderDto.getTotal(), shopCartOrderDto.getActualTotal()));
order.setFreightAmount(shopCartOrderDto.getTransfee());
order.setRemarks(shopCartOrderDto.getRemarks());
order.setOrderItems(orderItems);
event.getOrders().add(order);
// 插入订单结算表
OrderSettlement orderSettlement = new OrderSettlement();
orderSettlement.setUserId(userId);
orderSettlement.setIsClearing(0);
orderSettlement.setCreateTime(now);
orderSettlement.setOrderNumber(orderNumber);
orderSettlement.setPayAmount(order.getActualTotal());
orderSettlement.setPayStatus(0);
orderSettlement.setVersion(0);
orderSettlementMapper.insert(orderSettlement);
}
// 删除购物车的商品信息
if (!basketIds.isEmpty()) {
basketMapper.deleteShopCartItemsByBasketIds(userId, basketIds);
}
// 更新sku库存
skuStocksMap.forEach((key, sku) -> {
if (skuMapper.updateStocks(sku) == 0) {
skuService.removeSkuCacheBySkuId(key, sku.getProdId());
throw new YamiShopBindException("商品:[" + sku.getProdName() + "]库存不足");
}
});
// 更新商品库存
prodStocksMap.forEach((prodId, prod) -> {
if (productMapper.updateStocks(prod) == 0) {
productService.removeProductCacheByProdId(prodId);
throw new YamiShopBindException("商品:[" + prod.getProdName() + "]库存不足");
}
});
}
@SuppressWarnings({"Duplicates"})
private Product checkAndGetProd(Long prodId, ShopCartItemDto shopCartItem, Map<Long, Product> prodStocksMap) {
Product product = productService.getProductByProdId(prodId);
if (product == null) {
throw new YamiShopBindException("购物车包含无法识别的商品");
}
if (product.getStatus() != 1) {
throw new YamiShopBindException("商品[" + product.getProdName() + "]已下架");
}
// 商品需要改变的库存
Product mapProduct = prodStocksMap.get(prodId);
if (mapProduct == null) {
mapProduct = new Product();
mapProduct.setTotalStocks(0);
mapProduct.setProdId(prodId);
mapProduct.setProdName(product.getProdName());
}
if (product.getTotalStocks() != -1) {
mapProduct.setTotalStocks(mapProduct.getTotalStocks() + shopCartItem.getProdCount());
prodStocksMap.put(product.getProdId(), mapProduct);
}
// -1为无限库存
if (product.getTotalStocks() != -1 && mapProduct.getTotalStocks() > product.getTotalStocks()) {
throw new YamiShopBindException("商品:[" + product.getProdName() + "]库存不足");
}
return product;
}
@SuppressWarnings({"Duplicates"})
private Sku checkAndGetSku(Long skuId, ShopCartItemDto shopCartItem, Map<Long, Sku> skuStocksMap) {
// 获取sku信息
Sku sku = skuService.getSkuBySkuId(skuId);
if (sku == null) {
throw new YamiShopBindException("购物车包含无法识别的商品");
}
if (sku.getStatus() != 1) {
throw new YamiShopBindException("商品[" + sku.getProdName() + "]已下架");
}
// -1为无限库存
if (sku.getStocks() != -1 && shopCartItem.getProdCount() > sku.getStocks()) {
throw new YamiShopBindException("商品:[" + sku.getProdName() + "]库存不足");
}
if (sku.getStocks() != -1) {
Sku mapSku = new Sku();
mapSku.setProdId(sku.getProdId());
// 这里的库存是改变的库存
mapSku.setStocks(shopCartItem.getProdCount());
mapSku.setSkuId(sku.getSkuId());
mapSku.setProdName(sku.getProdName());
skuStocksMap.put(sku.getSkuId(), mapSku);
}
return sku;
}
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.security;
import com.yami.shop.security.constants.SecurityConstants;
import com.yami.shop.security.service.YamiClientDetailsService;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.service.YamiUserDetailsService;
import com.yami.shop.security.util.YamiTokenServices;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
import javax.sql.DataSource;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
*
*/
@Configuration
//@Order(2)
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private YamiUserDetailsService yamiUserDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Autowired
private RedisConnectionFactory redisConnectionFactory;
private AuthorizationServerEndpointsConfigurer endpoints;
@Bean
public TokenStore tokenStore() {
RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
tokenStore.setPrefix(SecurityConstants.YAMI_PREFIX + SecurityConstants.OAUTH_PREFIX);
return tokenStore;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 使用JdbcClientDetailsService客户端详情服务
YamiClientDetailsService clientDetailsService = new YamiClientDetailsService(dataSource);
clientDetailsService.setSelectClientDetailsSql(SecurityConstants.DEFAULT_SELECT_STATEMENT);
clientDetailsService.setFindClientDetailsSql(SecurityConstants.DEFAULT_FIND_STATEMENT);
clients.withClientDetails(clientDetailsService);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancer())
// refresh_token需要userDetailsService
.reuseRefreshTokens(false)
.userDetailsService(yamiUserDetailsService);
this.endpoints = endpoints;
endpoints.tokenServices(yamiTokenServices());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer
// 开启/oauth/token_key验证端口无权限访问
.tokenKeyAccess("permitAll()")
// 开启/oauth/check_token验证端口认证权限访问
.checkTokenAccess("isAuthenticated()");
}
/**
* token增强。
*
* @return TokenEnhancer
*/
@Bean
public TokenEnhancer tokenEnhancer() {
return (accessToken, authentication) -> {
Map<String, Object> additionalInfo = new HashMap<>(8);
YamiUser yamiUser = (YamiUser) authentication.getUserAuthentication().getPrincipal();
additionalInfo.put("userId", yamiUser.getUserId());
additionalInfo.put("nickName",yamiUser.getName());
additionalInfo.put("pic",yamiUser.getPic());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
};
}
@Primary
@Bean
@Lazy
public AuthorizationServerTokenServices yamiTokenServices() {
YamiTokenServices tokenServices = new YamiTokenServices();
tokenServices.setTokenStore(tokenStore());
tokenServices.setSupportRefreshToken(true);//支持刷新token
tokenServices.setReuseRefreshToken(true);
tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
addUserDetailsService(tokenServices);
return tokenServices;
}
private void addUserDetailsService(YamiTokenServices tokenServices) {
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>(
yamiUserDetailsService));
tokenServices.setAuthenticationManager(new ProviderManager(Collections.singletonList(provider)));
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.security;
import com.yami.shop.security.filter.LoginAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Autowired
private LoginAuthenticationFilter loginAuthenticationFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(loginAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
// Since we want the protected resources to be accessible in the UI as well we need
// session creation to be allowed (it's disabled by default in 2.0.6)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.requestMatchers().anyRequest()
.and()
.anonymous()
.and()
.authorizeRequests()
//配置/p访问控制必须认证过后才可以访问
.antMatchers("/p/**").authenticated();
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.security;
import cn.binarywang.wx.miniapp.api.WxMaService;
import com.yami.shop.security.filter.LoginAuthenticationFilter;
import com.yami.shop.security.handler.LoginAuthFailedHandler;
import com.yami.shop.security.handler.LoginAuthSuccessHandler;
import com.yami.shop.security.provider.MiniAppAuthenticationProvider;
import com.yami.shop.security.service.YamiUserDetailsService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
*/
@Configuration
@Order(90)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 自动注入UserDetailsService
*/
@Autowired
private YamiUserDetailsService yamiUserDetailsService;
@Autowired
private LoginAuthSuccessHandler loginAuthSuccessHandler;
@Autowired
private LoginAuthFailedHandler loginAuthFailedHandler;
@Autowired
private WxMaService wxService;
@Autowired
private MiniAppAuthenticationProvider miniAppAuthenticationProvider;
@Override
@Bean
@SneakyThrows
public AuthenticationManager authenticationManagerBean() {
return super.authenticationManagerBean();
}
/**
* 用户验证
* @param auth
*/
@Override
public void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(miniAppAuthenticationProvider);
}
@Bean
public PasswordEncoder passwordEncoder(){
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Bean
public LoginAuthenticationFilter loginAuthenticationFilter() {
LoginAuthenticationFilter filter = new LoginAuthenticationFilter();
try {
filter.setAuthenticationManager(this.authenticationManagerBean());
} catch (Exception e) {
e.printStackTrace();
}
filter.setAuthenticationSuccessHandler(loginAuthSuccessHandler);
filter.setAuthenticationFailureHandler(loginAuthFailedHandler);
return filter;
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.security;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.emoji.EmojiUtil;
import com.yami.shop.bean.model.User;
import com.yami.shop.common.annotation.RedisLock;
import com.yami.shop.common.util.CacheManagerUtil;
import com.yami.shop.dao.UserMapper;
import com.yami.shop.security.dao.AppConnectMapper;
import com.yami.shop.security.enums.App;
import com.yami.shop.security.exception.UsernameNotFoundExceptionBase;
import com.yami.shop.security.model.AppConnect;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.service.YamiUserDetailsService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
/**
* 用户详细信息
*
* @author
*/
@Slf4j
@Service
@AllArgsConstructor
public class YamiUserServiceImpl implements YamiUserDetailsService {
private final UserMapper userMapper;
private final AppConnectMapper appConnectMapper;
private final CacheManagerUtil cacheManagerUtil;
@Override
@SneakyThrows
public YamiUser loadUserByUsername(String username) {
if (StrUtil.isBlank(username) || !username.contains(StrUtil.COLON) ) {
throw new UsernameNotFoundExceptionBase("无法获取用户信息");
}
String[] splitInfo = username.split(StrUtil.COLON);
App app = App.instance(Integer.valueOf(splitInfo[0]));
String bizUserId = splitInfo[1];
return loadUserByAppIdAndBizUserId(app,bizUserId);
}
/**
* 获取前端登陆的用户信息
*
* @param app
* @param bizUserId openId
* @return UserDetails
* @throws UsernameNotFoundExceptionBase
*/
@Override
public YamiUser loadUserByAppIdAndBizUserId(App app, String bizUserId) {
String cacheKey = app.value() + StrUtil.COLON + bizUserId;
YamiUser yamiUser = cacheManagerUtil.getCache("yami_user", cacheKey);
if (yamiUser != null) {
return yamiUser;
}
User user = userMapper.getUserByBizUserId(app.value(), bizUserId);
if (user == null) {
throw new UsernameNotFoundExceptionBase("无法获取用户信息");
}
String name = StrUtil.isBlank(user.getRealName()) ? user.getNickName() : user.getRealName();
yamiUser = new YamiUser(user.getUserId(), bizUserId, app.value(), user.getStatus() == 1);
yamiUser.setName(name);
yamiUser.setPic(user.getPic());
cacheManagerUtil.putCache("yami_sys_user",cacheKey, yamiUser);
return yamiUser;
}
@Override
@Transactional(rollbackFor = Exception.class)
@RedisLock(lockName = "insertUser", key = "#appConnect.appId + ':' + #appConnect.bizUserId")
@Caching(evict = {
@CacheEvict(cacheNames = "yami_user", key = "#appConnect.appId + ':' + #appConnect.bizUserId"),
@CacheEvict(cacheNames = "AppConnect", key = "#appConnect.appId + ':' + #appConnect.bizUserId")
})
public void insertUserIfNecessary(AppConnect appConnect) {
// 进入锁后再重新判断一遍用户是否创建
AppConnect dbAppConnect = appConnectMapper.getByBizUserId(appConnect.getBizUserId(), appConnect.getAppId());
if(dbAppConnect != null) {
return;
}
String bizUnionId = appConnect.getBizUnionid();
String userId = null;
User user;
if (StrUtil.isNotBlank(bizUnionId)) {
userId = appConnectMapper.getUserIdByUnionId(bizUnionId);
}
if (StrUtil.isBlank(userId)) {
userId = IdUtil.simpleUUID();
Date now = new Date();
user = new User();
user.setUserId(userId);
user.setModifyTime(now);
user.setUserRegtime(now);
user.setStatus(1);
user.setRealName(EmojiUtil.toAlias(StrUtil.isBlank(appConnect.getNickName()) ? "" : appConnect.getNickName()));
user.setPic(appConnect.getImageUrl());
userMapper.insert(user);
} else {
user = userMapper.selectById(userId);
}
appConnect.setUserId(user.getUserId());
appConnectMapper.insert(appConnect);
}
}

View File

@@ -0,0 +1,3 @@
api.datacenterId=1
api.workerId=1
api.domainName=http://xxx.com

View File

@@ -0,0 +1,20 @@
server:
port: 8086
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/yami_shops?allowMultiQueries=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 0
maximum-pool-size: 20
idle-timeout: 10000
connection-test-query: select 1
redis:
redisson:
config: classpath:redisson.yml
logging:
config: classpath:log4j2_dev.xml

View File

@@ -0,0 +1,21 @@
server:
port: 8112
undertow:
worker-threads: 200
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/yami_shops?allowMultiQueries=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 0
maximum-pool-size: 20
connection-test-query: select 1
redis:
redisson:
config: classpath:redisson.yml
logging:
config: classpath:log4j2_prod.xml

View File

@@ -0,0 +1,52 @@
spring:
# 环境 dev|test|prod
profiles:
active: dev
#文件上传设置
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
enabled: true
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mvc:
formcontent:
filter:
enabled: false
autoconfigure:
exclude: org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.TraceRepositoryAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.TraceWebFilterAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration
# mybaits-plus配置
mybatis-plus:
# MyBatis Mapper所对应的XML文件位置
mapper-locations: classpath*:/mapper/*Mapper.xml
global-config:
# 关闭MP3.0自带的banner
banner: false
db-config:
# 主键类型 0:数据库ID自增 1.未定义 2.用户输入 3 id_worker 4.uuid 5.id_worker字符串表示
id-type: AUTO
#字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
field-strategy: NOT_NULL
# 默认数据库表下划线命名
table-underline: true
management:
server:
add-application-context-header: false

View File

@@ -0,0 +1,11 @@
.----------------. .----------------. .----------------. .----------------.
| .--------------. || .--------------. || .--------------. || .--------------. |
| | ____ ____ | || | __ | || | ____ ____ | || | _____ | |
| | |_ _||_ _| | || | / \ | || ||_ \ / _|| || | |_ _| | |
| | \ \ / / | || | / /\ \ | || | | \/ | | || | | | | |
| | \ \/ / | || | / ____ \ | || | | |\ /| | | || | | | | |
| | _| |_ | || | _/ / \ \_ | || | _| |_\/_| |_ | || | _| |_ | |
| | |______| | || ||____| |____|| || ||_____||_____|| || | |_____| | |
| | | || | | || | | || | | |
| '--------------' || '--------------' || '--------------' || '--------------' |
'----------------' '----------------' '----------------' '----------------'

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--monitorIntervalLog4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="WARN" monitorInterval="60">
<Properties>
<Property name="PID">????</Property>
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property>
<!-- 控制台日志格式化,包含颜色-->
<Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
</Properties>
<!--定义appender -->
<Appenders>
<!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->
<Console name="Console" target="SYSTEM_OUT" follow="false">
<PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" />
</Console>
</Appenders>
<Loggers>
<Logger name="org.mybatis" level="debug"/>
<Logger name="com.yami.shop" level="debug"/>
<Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
<Logger name="org.apache.catalina.util.LifecycleBase" level="error" />
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
<Logger name="org.apache.sshd.common.util.SecurityUtils" level="warn"/>
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
<Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
<Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
<Logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
<!--关闭swagger的类型转换异常的日志 https://github.com/springfox/springfox/issues/2528-->
<Logger name="springfox.documentation.swagger2" level="off"/>
<Logger name="io.swagger.models.parameters" level="off"/>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</configuration>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--monitorIntervalLog4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="WARN" monitorInterval="60">
<Properties>
<Property name="PID">????</Property>
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property>
<!-- 控制台日志格式化,包含颜色-->
<Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
<!-- 日志文件默认输出格式,不带行号输出(行号显示会影响日志输出性能);%C:大写,类名;%M:方法名;%m:错误信息;%n:换行 -->
<Property name="FILE_LOG_PATTERN">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
<!-- 日志默认同类型日志,同一文件夹下可以存放的数量,不设置此属性则默认为7个 -->
<Property name="FILE_MAX_HISTORY">50</Property>
<Property name="FILE_MAX_SIZE">50MB</Property>
<Property name="PROJECT_PATH">/opt/projects/mall4j</Property>
</Properties>
<!--定义appender -->
<Appenders>
<!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->
<Console name="Console" target="SYSTEM_OUT" follow="false">
<PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" />
</Console>
<!--fileName 文件名称-->
<!--filePattern 文件路径-->
<RollingFile name="DefaultFile" fileName="${PROJECT_PATH}/log/api.log" filePattern="${PROJECT_PATH}/log/$${date:yyyy-MM}/api-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout>
<Pattern>${sys:FILE_LOG_PATTERN}</Pattern>
</PatternLayout>
<DefaultRolloverStrategy max="${FILE_MAX_HISTORY}"/>
<Policies>
<!--TimeBasedTriggeringPolicy 与 filePattern 结合使用目前表示每间隔1天保存一遍日志-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="${FILE_MAX_SIZE}" />
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="org.mybatis" level="debug"/>
<Logger name="com.yami.shop" level="debug"/>
<Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
<Logger name="org.apache.catalina.util.LifecycleBase" level="error" />
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
<Logger name="org.apache.sshd.common.util.SecurityUtils" level="warn"/>
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
<Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
<Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
<Logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
<Logger name="org.mybatis" level="debug"/>
<Logger name="com.yami.shop" level="debug"/>
<!---->
<Root level="info">
<AppenderRef ref="DefaultFile" />
</Root>
</Loggers>
</configuration>

View File

@@ -0,0 +1,31 @@
# 单节点设置
singleServerConfig:
address: redis://127.0.0.1:6379
database: 0
password: null
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
clientName: null
# 发布和订阅连接的最小空闲连接数 默认1
subscriptionConnectionMinimumIdleSize: 1
# 发布和订阅连接池大小 默认50
subscriptionConnectionPoolSize: 10
# 单个连接最大订阅数量 默认5
subscriptionsPerConnection: 5
# 最小空闲连接数 默认32现在暂时不需要那么多的线程
connectionMinimumIdleSize: 4
# connectionPoolSize 默认64现在暂时不需要那么多的线程
connectionPoolSize: 20
# 这个线程池数量被所有RTopic对象监听器RRemoteService调用者和RExecutorService任务共同共享。
threads: 0
# 这个线程池数量是在一个Redisson实例内被其创建的所有分布式数据类型和服务以及底层客户端所一同共享的线程池里保存的线程数量。
nettyThreads: 0
codec:
class: com.yami.shop.common.serializer.redisson.FstCodec
transportMode: NIO

26
yami-shop-bean/pom.xml Normal file
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>
<artifactId>yami-shop</artifactId>
<groupId>com.yami.shop</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yami-shop-bean</artifactId>
<dependencies>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-common</artifactId>
<version>${yami.shop.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.bean;
import java.util.ArrayList;
import java.util.List;
import com.yami.shop.bean.bo.SmsInfoBo;
import cn.hutool.core.collection.CollectionUtil;
public class SmsInfoContext {
/** The request holder. */
private static ThreadLocal<List<SmsInfoBo>> smsInfoHolder = new ThreadLocal<List<SmsInfoBo>>();
public static List<SmsInfoBo> get(){
List<SmsInfoBo> list = smsInfoHolder.get();
if (CollectionUtil.isEmpty(list)) {
return new ArrayList<>();
}
return smsInfoHolder.get();
}
public static void set(List<SmsInfoBo> smsInfoBos){
smsInfoHolder.set(smsInfoBos);
}
public static void put(SmsInfoBo smsInfoBo){
List<SmsInfoBo> smsInfoBos = smsInfoHolder.get();
if (CollectionUtil.isEmpty(smsInfoBos)) {
smsInfoBos = new ArrayList<>();
}
smsInfoBos.add(smsInfoBo);
smsInfoHolder.set(smsInfoBos);
}
public static void clean() {
if (smsInfoHolder.get() != null) {
smsInfoHolder.remove();
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.bean.app.dto;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.yami.shop.common.serializer.json.ImgJsonSerializer;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class BasketItemDto implements Serializable {
@ApiModelProperty(value = "购物车ID", required = true)
private Long basketId;
@ApiModelProperty(value = "店铺ID", required = true)
private Long shopId;
/**
* 商品名称
*/
@JsonIgnore
private String shopName;
@ApiModelProperty(value = "产品ID", required = true)
private Long prodId;
@ApiModelProperty(value = "skuID", required = true)
private Long skuId;
@ApiModelProperty(value = "产品个数", required = true)
private Integer prodCount;
@ApiModelProperty(value = "产品名称", required = true)
private String prodName;
@ApiModelProperty(value = "产品主图", required = true)
@JsonSerialize(using = ImgJsonSerializer.class)
private String pic;
@ApiModelProperty(value = "产品现价", required = true)
private Double price;
@ApiModelProperty(value = "产品原价", required = true)
private Double oriPrice;
@ApiModelProperty(value = "产品简介", required = true)
private String brief;
@ApiModelProperty(value = "产品sku信息", required = true)
private String skuName;
@ApiModelProperty("参与满减活动列表")
private List<DiscountDto> discounts;
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.bean.app.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.yami.shop.common.serializer.json.ImgJsonSerializer;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class CategoryDto {
@ApiModelProperty(value = "分类id",required=true)
private Long categoryId;
@ApiModelProperty(value = "分类父id",required=true)
private Long parentId;
@ApiModelProperty(value = "分类名称",required=true)
private String categoryName;
@ApiModelProperty(value = "分类图片",required=true)
@JsonSerialize(using = ImgJsonSerializer.class)
private String pic;
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.bean.app.dto;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.models.auth.In;
import lombok.Data;
import java.io.Serializable;
/**
* 购物车中选中的满减活动项信息
*/
@Data
public class ChooseDiscountItemDto implements Serializable {
@ApiModelProperty("满减满折优惠id")
private Long discountId;
@ApiModelProperty("优惠规则(0:满钱减钱 1:满件减钱 2:满钱打折 3:满件打折)")
private Integer discountRule;
@ApiModelProperty(value = "优惠项id")
@JsonIgnore
private Long discountItemId;
@ApiModelProperty(value = "所需需要金额")
private Double needAmount;
@ApiModelProperty(value = "减免类型 0按满足最高层级减一次 1每满一次减一次")
private Integer discountType;
@ApiModelProperty(value = "参与满减满折优惠的商品数量")
private int prodCount = 0;
@ApiModelProperty(value = "参与满减满折优惠的商品金额")
private double prodsPrice = 0.00;
@ApiModelProperty(value = "优惠(元/折)")
private Double discount;
@ApiModelProperty(value = "参与满减满折优惠的金额")
private Double reduceAmount = 0.0;
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.bean.app.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.yami.shop.common.serializer.json.ImgJsonSerializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
@Data
@ApiModel("优惠券对象")
public class CouponDto implements Serializable {
@ApiModelProperty(value = "优惠券id")
private Long couponId;
@ApiModelProperty(value = "店铺ID")
private Long shopId;
@ApiModelProperty(value = "店铺名称")
private String shopName;
@ApiModelProperty(value = "优惠券名称")
private String couponName;
@ApiModelProperty(value = "副标题")
private String subTitle;
@ApiModelProperty(value = "优惠类型 1:代金券 2:折扣券 3:兑换券")
private Integer couponType;
@ApiModelProperty(value = "使用条件")
private Double cashCondition;
@ApiModelProperty(value = "减免金额")
private Double reduceAmount;
@ApiModelProperty(value = "折扣额度")
private Double couponDiscount;
@ApiModelProperty(value = "生效时间 1:固定时间 2:领取后生效")
private Integer validTimeType;
@ApiModelProperty(value = "开始时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date startTime;
@ApiModelProperty(value = "结束时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date endTime;
@ApiModelProperty(value = "领券后X天起生效")
private Integer afterReceiveDays;
@ApiModelProperty(value = "有效天数")
private Integer validDays;
@ApiModelProperty(value = "库存")
private Integer stocks;
@ApiModelProperty(value = "适用商品类型 0全部商品参与 1指定商品参与 2指定商品不参与")
private Integer suitableProdType;
@ApiModelProperty(value = "指定商品图片")
@JsonSerialize(using = ImgJsonSerializer.class)
private String pic;
@ApiModelProperty(value = "指定商品id")
private Long prodId;
@ApiModelProperty(value = "指定商品价格")
private Double price;
@ApiModelProperty(value = "每个用户领券上限")
private Integer limitNum;
@ApiModelProperty(value = "优惠券过期状态 0:过期 1:未过期")
private Integer overdueStatus;
@ApiModelProperty(value = "优惠券投放状态 0:未投放 1:投放")
private Integer putonStatus;
@ApiModelProperty(value = "用户优惠券id")
private Long couponUserId;
@ApiModelProperty(value = "领券时间")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date receiveTime;
}

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