diff --git a/pom.xml b/pom.xml
index 2a8521c46..c051b066b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,6 +32,7 @@
3.15.2
2.2.1
3.4.0
+ 1.2.8
@@ -181,6 +182,13 @@
${ruoyi-vue-plus.version}
+
+
+ com.anji-plus
+ spring-boot-starter-captcha
+ ${captcha.version}
+
+
@@ -192,6 +200,9 @@
ruoyi-generator
ruoyi-common
ruoyi-demo
+ ruoyi-coupons
+ ruoyi-product
+ ruoyi-activity
pom
diff --git a/ruoyi-activity/pom.xml b/ruoyi-activity/pom.xml
new file mode 100644
index 000000000..66ddbe603
--- /dev/null
+++ b/ruoyi-activity/pom.xml
@@ -0,0 +1,19 @@
+
+
+
+ ruoyi-vue-plus
+ com.ruoyi
+ 2.4.0
+
+ 4.0.0
+
+ ruoyi-activity
+
+
+ 8
+ 8
+
+
+
diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index 031427fc0..eacad62b0 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -48,12 +48,24 @@
ruoyi-generator
+
+
+ com.ruoyi
+ ruoyi-product
+
+
com.ruoyi
ruoyi-demo
+
+
+ com.anji-plus
+ spring-boot-starter-captcha
+
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java
deleted file mode 100644
index 2f303ba95..000000000
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package com.ruoyi.web.controller.common;
-
-import cn.hutool.captcha.AbstractCaptcha;
-import cn.hutool.captcha.CircleCaptcha;
-import cn.hutool.captcha.LineCaptcha;
-import cn.hutool.captcha.ShearCaptcha;
-import cn.hutool.captcha.generator.CodeGenerator;
-import cn.hutool.captcha.generator.RandomGenerator;
-import cn.hutool.core.convert.Convert;
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.core.util.StrUtil;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.core.domain.AjaxResult;
-import com.ruoyi.common.core.redis.RedisCache;
-import com.ruoyi.framework.captcha.UnsignedMathGenerator;
-import com.ruoyi.framework.config.properties.CaptchaProperties;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.annotation.Resource;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * 验证码操作处理
- *
- * @author Lion Li
- */
-@RestController
-public class CaptchaController {
-
- // 圆圈干扰验证码
- @Resource(name = "CircleCaptcha")
- private CircleCaptcha circleCaptcha;
- // 线段干扰的验证码
- @Resource(name = "LineCaptcha")
- private LineCaptcha lineCaptcha;
- // 扭曲干扰验证码
- @Resource(name = "ShearCaptcha")
- private ShearCaptcha shearCaptcha;
-
- @Autowired
- private RedisCache redisCache;
-
- @Autowired
- private CaptchaProperties captchaProperties;
-
- /**
- * 生成验证码
- */
- @GetMapping("/captchaImage")
- public AjaxResult getCode() {
- Map ajax = new HashMap<>();
- Boolean enabled = captchaProperties.getEnabled();
- ajax.put("enabled", enabled);
- if (!enabled) {
- return AjaxResult.success(ajax);
- }
- // 保存验证码信息
- String uuid = IdUtil.simpleUUID();
- String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
- String code = null;
- // 生成验证码
- CodeGenerator codeGenerator;
- AbstractCaptcha captcha;
- switch (captchaProperties.getType()) {
- case "math":
- codeGenerator = new UnsignedMathGenerator(captchaProperties.getNumberLength());
- break;
- case "char":
- codeGenerator = new RandomGenerator(captchaProperties.getCharLength());
- break;
- default:
- throw new IllegalArgumentException("验证码类型异常");
- }
- switch (captchaProperties.getCategory()) {
- case "line":
- captcha = lineCaptcha;
- break;
- case "circle":
- captcha = circleCaptcha;
- break;
- case "shear":
- captcha = shearCaptcha;
- break;
- default:
- throw new IllegalArgumentException("验证码类别异常");
- }
- captcha.setGenerator(codeGenerator);
- captcha.createCode();
- if ("math".equals(captchaProperties.getType())) {
- code = getCodeResult(captcha.getCode());
- } else if ("char".equals(captchaProperties.getType())) {
- code = captcha.getCode();
- }
- redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
- ajax.put("uuid", uuid);
- ajax.put("img", captcha.getImageBase64());
- return AjaxResult.success(ajax);
- }
-
- private String getCodeResult(String capStr) {
- int numberLength = captchaProperties.getNumberLength();
- int a = Convert.toInt(StrUtil.sub(capStr, 0, numberLength).trim());
- char operator = capStr.charAt(numberLength);
- int b = Convert.toInt(StrUtil.sub(capStr, numberLength + 1, numberLength + 1 + numberLength).trim());
- switch (operator) {
- case '*':
- return a * b + "";
- case '+':
- return a + b + "";
- case '-':
- return a - b + "";
- default:
- return "";
- }
- }
-
-}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/product/ProBannerController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/product/ProBannerController.java
new file mode 100644
index 000000000..4d2b6d370
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/product/ProBannerController.java
@@ -0,0 +1,111 @@
+package com.ruoyi.web.controller.product;
+
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.product.bo.ProBannerAddBo;
+import com.ruoyi.product.bo.ProBannerEditBo;
+import com.ruoyi.product.bo.ProBannerQueryBo;
+import com.ruoyi.product.service.IProBannerService;
+import com.ruoyi.product.vo.ProBannerVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * banner管理Controller
+ *
+ * @author ruoyi
+ * @date 2021-06-30
+ */
+@Api(value = "banner管理控制器", tags = {"banner管理管理"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+@RestController
+@RequestMapping("/product/proBanner")
+public class ProBannerController extends BaseController {
+
+ private final IProBannerService iProBannerService;
+
+ /**
+ * 查询banner管理列表
+ */
+ @ApiOperation("查询banner管理列表")
+ @PreAuthorize("@ss.hasPermi('system:banner:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(@Validated ProBannerQueryBo bo) {
+ return iProBannerService.queryPageList(bo);
+ }
+
+ /**
+ * 导出banner管理列表
+ */
+ @ApiOperation("导出banner管理列表")
+ @PreAuthorize("@ss.hasPermi('system:banner:export')")
+ @Log(title = "banner管理", businessType = BusinessType.EXPORT)
+ @GetMapping("/export")
+ public AjaxResult export(@Validated ProBannerQueryBo bo) {
+ List list = iProBannerService.queryList(bo);
+ ExcelUtil util = new ExcelUtil(ProBannerVo.class);
+ return util.exportExcel(list, "banner管理");
+ }
+
+ /**
+ * 获取banner管理详细信息
+ */
+ @ApiOperation("获取banner管理详细信息")
+ @PreAuthorize("@ss.hasPermi('system:banner:query')")
+ @GetMapping("/{id}")
+ public AjaxResult getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable("id") Long id) {
+ return AjaxResult.success(iProBannerService.queryById(id));
+ }
+
+ /**
+ * 新增banner管理
+ */
+ @ApiOperation("新增banner管理")
+ @PreAuthorize("@ss.hasPermi('system:banner:add')")
+ @Log(title = "banner管理", businessType = BusinessType.INSERT)
+ @RepeatSubmit
+ @PostMapping()
+ public AjaxResult add(@Validated @RequestBody ProBannerAddBo bo) {
+ return toAjax(iProBannerService.insertByAddBo(bo) ? 1 : 0);
+ }
+
+ /**
+ * 修改banner管理
+ */
+ @ApiOperation("修改banner管理")
+ @PreAuthorize("@ss.hasPermi('system:banner:edit')")
+ @Log(title = "banner管理", businessType = BusinessType.UPDATE)
+ @RepeatSubmit
+ @PutMapping()
+ public AjaxResult edit(@Validated @RequestBody ProBannerEditBo bo) {
+ return toAjax(iProBannerService.updateByEditBo(bo) ? 1 : 0);
+ }
+
+ /**
+ * 删除banner管理
+ */
+ @ApiOperation("删除banner管理")
+ @PreAuthorize("@ss.hasPermi('system:banner:remove')")
+ @Log(title = "banner管理", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public AjaxResult remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ids) {
+ return toAjax(iProBannerService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/product/ProCategoryController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/product/ProCategoryController.java
new file mode 100644
index 000000000..97fc259b6
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/product/ProCategoryController.java
@@ -0,0 +1,114 @@
+package com.ruoyi.web.controller.product;
+
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.product.bo.ProCategoryAddBo;
+import com.ruoyi.product.bo.ProCategoryEditBo;
+import com.ruoyi.product.bo.ProCategoryQueryBo;
+import com.ruoyi.product.service.IProCategoryService;
+import com.ruoyi.product.vo.ProCategoryVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.constraints.NotEmpty;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 商品服务类别Controller
+ *
+ * @author ruoyi
+ * @date 2021-03-14
+ */
+@Api(value = "商品服务类别控制器", tags = {"商品服务类别管理"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+@RestController
+@RequestMapping("/product/proCategory")
+public class ProCategoryController extends BaseController {
+
+ private final IProCategoryService iProCategoryService;
+
+ /**
+ * 查询商品服务类别列表
+ */
+ @ApiOperation("查询商品服务类别列表")
+ @PreAuthorize("@ss.hasPermi('product:proCategory:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(@Validated ProCategoryQueryBo bo) {
+ return iProCategoryService.queryPageList(bo);
+ }
+
+ @PreAuthorize("@ss.hasPermi('product:proCategory:list')")
+ @GetMapping("/listCategoriesWithoutPage")
+ public List listCategoriesWithoutPage(ProCategoryQueryBo proCategory) {
+ return iProCategoryService.queryList(proCategory);
+ }
+
+ /**
+ * 导出商品服务类别列表
+ */
+ @ApiOperation("导出商品服务类别列表")
+ @PreAuthorize("@ss.hasPermi('product:proCategory:export')")
+ @Log(title = "商品服务类别", businessType = BusinessType.EXPORT)
+ @GetMapping("/export")
+ public AjaxResult export(@Validated ProCategoryQueryBo bo) {
+ List list = iProCategoryService.queryList(bo);
+ ExcelUtil util = new ExcelUtil<>(ProCategoryVo.class);
+ return util.exportExcel(list, "商品服务类别");
+ }
+
+ /**
+ * 获取商品服务类别详细信息
+ */
+ @PreAuthorize("@ss.hasPermi('product:proCategory:query')")
+ @GetMapping(value = "/{id}")
+ public AjaxResult getInfo(@PathVariable("id") Long id) {
+ return AjaxResult.success(iProCategoryService.getById(id));
+ }
+
+ /**
+ * 新增商品服务类别
+ */
+ @ApiOperation("新增商品服务类别")
+ @PreAuthorize("@ss.hasPermi('product:proCategory:add')")
+ @Log(title = "商品服务类别", businessType = BusinessType.INSERT)
+ @RepeatSubmit
+ @PostMapping()
+ public AjaxResult add(@Validated @RequestBody ProCategoryAddBo bo) {
+ return toAjax(iProCategoryService.insertByAddBo(bo) ? 1 : 0);
+ }
+
+ /**
+ * 修改商品服务类别
+ */
+ @ApiOperation("修改商品服务类别")
+ @PreAuthorize("@ss.hasPermi('product:proCategory:edit')")
+ @Log(title = "商品服务类别", businessType = BusinessType.UPDATE)
+ @RepeatSubmit
+ @PutMapping()
+ public AjaxResult edit(@Validated @RequestBody ProCategoryEditBo bo) {
+ return toAjax(iProCategoryService.updateByEditBo(bo) ? 1 : 0);
+ }
+
+ /**
+ * 删除商品服务类别
+ */
+ @ApiOperation("删除商品服务类别")
+ @PreAuthorize("@ss.hasPermi('product:proCategory:remove')")
+ @Log(title = "商品服务类别", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public AjaxResult remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ids) {
+ return toAjax(iProCategoryService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/product/ProItemController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/product/ProItemController.java
new file mode 100644
index 000000000..ee57ef5ef
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/product/ProItemController.java
@@ -0,0 +1,111 @@
+package com.ruoyi.web.controller.product;
+
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.product.bo.ProItemAddBo;
+import com.ruoyi.product.bo.ProItemEditBo;
+import com.ruoyi.product.bo.ProItemQueryBo;
+import com.ruoyi.product.service.IProItemService;
+import com.ruoyi.product.vo.ProItemVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 商品详情Controller
+ *
+ * @author ruoyi
+ * @date 2021-07-01
+ */
+@Api(value = "商品详情控制器", tags = {"商品详情管理"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+@RestController
+@RequestMapping("/product/proItem")
+public class ProItemController extends BaseController {
+
+ private final IProItemService iProItemService;
+
+ /**
+ * 查询商品详情列表
+ */
+ @ApiOperation("查询商品详情列表")
+ @PreAuthorize("@ss.hasPermi('product:proItem:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(@Validated ProItemQueryBo bo) {
+ return iProItemService.queryPageList(bo);
+ }
+
+ /**
+ * 导出商品详情列表
+ */
+ @ApiOperation("导出商品详情列表")
+ @PreAuthorize("@ss.hasPermi('product:proItem:export')")
+ @Log(title = "商品详情", businessType = BusinessType.EXPORT)
+ @GetMapping("/export")
+ public AjaxResult export(@Validated ProItemQueryBo bo) {
+ List list = iProItemService.queryList(bo);
+ ExcelUtil util = new ExcelUtil<>(ProItemVo.class);
+ return util.exportExcel(list, "商品详情");
+ }
+
+ /**
+ * 获取商品详情详细信息
+ */
+ @ApiOperation("获取商品详情详细信息")
+ @PreAuthorize("@ss.hasPermi('product:proItem:query')")
+ @GetMapping("/{id}")
+ public AjaxResult getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable("id") Long id) {
+ return AjaxResult.success(iProItemService.getProItemById(id));
+ }
+
+ /**
+ * 新增商品详情
+ */
+ @ApiOperation("新增商品详情")
+ @PreAuthorize("@ss.hasPermi('product:proItem:add')")
+ @Log(title = "商品详情", businessType = BusinessType.INSERT)
+ @RepeatSubmit
+ @PostMapping()
+ public AjaxResult add(@Validated @RequestBody ProItemAddBo bo) {
+ return toAjax(iProItemService.insertByAddBo(bo) ? 1 : 0);
+ }
+
+ /**
+ * 修改商品详情
+ */
+ @ApiOperation("修改商品详情")
+ @PreAuthorize("@ss.hasPermi('product:proItem:edit')")
+ @Log(title = "商品详情", businessType = BusinessType.UPDATE)
+ @RepeatSubmit
+ @PutMapping()
+ public AjaxResult edit(@Validated @RequestBody ProItemEditBo bo) {
+ return toAjax(iProItemService.updateByEditBo(bo) ? 1 : 0);
+ }
+
+ /**
+ * 删除商品详情
+ */
+ @ApiOperation("删除商品详情")
+ @PreAuthorize("@ss.hasPermi('product:proItem:remove')")
+ @Log(title = "商品详情", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public AjaxResult remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable Long[] ids) {
+ return toAjax(iProItemService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/product/ProItemSpecificationController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/product/ProItemSpecificationController.java
new file mode 100644
index 000000000..2888aef9a
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/product/ProItemSpecificationController.java
@@ -0,0 +1,121 @@
+/*
+package com.ruoyi.web.controller.product;
+
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.product.bo.ProItemSpecificationAddBo;
+import com.ruoyi.product.bo.ProItemSpecificationEditBo;
+import com.ruoyi.product.bo.ProItemSpecificationQueryBo;
+import com.ruoyi.product.service.IProItemSpecificationService;
+import com.ruoyi.product.vo.ProItemSpecificationVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collections;
+import java.util.List;
+
+*/
+/**
+ * 商品规格Controller
+ *
+ * @author ruoyi
+ * @date 2021-04-06
+ *//*
+
+@Api(value = "商品规格控制器", tags = {"商品规格管理"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+@RestController
+@RequestMapping("/product/proItemSpecification")
+public class ProItemSpecificationController extends BaseController {
+
+ private final IProItemSpecificationService iProItemSpecificationService;
+
+ */
+/**
+ * 查询商品规格列表
+ *//*
+
+ @ApiOperation("查询商品规格列表")
+ @PreAuthorize("@ss.hasPermi('product:proItemSpecification:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(ProItemSpecificationQueryBo bo) {
+ startPage();
+ List list = iProItemSpecificationService.queryList(bo);
+ return getDataTable(list);
+ }
+
+ */
+/**
+ * 导出商品规格列表
+ *//*
+
+ @ApiOperation("导出商品规格列表")
+ @PreAuthorize("@ss.hasPermi('product:proItemSpecification:export')")
+ @Log(title = "商品规格", businessType = BusinessType.EXPORT)
+ @GetMapping("/export")
+ public AjaxResult export(ProItemSpecificationQueryBo bo) {
+ List list = iProItemSpecificationService.queryList(bo);
+ ExcelUtil util = new ExcelUtil<>(ProItemSpecificationVo.class);
+ return util.exportExcel(list, "proItemSpecification");
+ }
+
+ */
+/**
+ * 获取商品规格详细信息
+ *//*
+
+ @ApiOperation("获取商品规格详细信息")
+ @PreAuthorize("@ss.hasPermi('product:proItemSpecification:query')")
+ @GetMapping(value = "/{id}")
+ public AjaxResult getInfo(@PathVariable("id") Long id) {
+ return AjaxResult.success(iProItemSpecificationService.queryById(id));
+ }
+
+ */
+/**
+ * 新增商品规格
+ *//*
+
+ @ApiOperation("新增商品规格")
+ @PreAuthorize("@ss.hasPermi('product:proItemSpecification:add')")
+ @Log(title = "商品规格", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@RequestBody ProItemSpecificationAddBo bo) {
+ return toAjax(iProItemSpecificationService.insertByAddBo(bo) ? 1 : 0);
+ }
+
+ */
+/**
+ * 修改商品规格
+ *//*
+
+ @ApiOperation("修改商品规格")
+ @PreAuthorize("@ss.hasPermi('product:proItemSpecification:edit')")
+ @Log(title = "商品规格", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@RequestBody ProItemSpecificationEditBo bo) {
+ return toAjax(iProItemSpecificationService.updateByEditBo(bo) ? 1 : 0);
+ }
+
+ */
+/**
+ * 删除商品规格
+ *//*
+
+ @ApiOperation("删除商品规格")
+ @PreAuthorize("@ss.hasPermi('product:proItemSpecification:remove')")
+ @Log(title = "商品规格", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public AjaxResult remove(@PathVariable Long ids) {
+ return toAjax(iProItemSpecificationService.deleteWithValidByIds(Collections.singletonList(ids), true) ? 1 : 0);
+ }
+}
+*/
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
index b2b9efb3d..f7ad819dc 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -1,11 +1,15 @@
package com.ruoyi.web.controller.system;
+import com.anji.captcha.model.common.ResponseModel;
+import com.anji.captcha.model.vo.CaptchaVO;
+import com.anji.captcha.service.CaptchaService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
@@ -17,10 +21,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
/**
* 登录验证
@@ -28,70 +29,74 @@ import java.util.Set;
* @author ruoyi
*/
@RestController
-public class SysLoginController
-{
- @Autowired
- private SysLoginService loginService;
+public class SysLoginController {
+ @Autowired
+ private SysLoginService loginService;
- @Autowired
- private ISysMenuService menuService;
+ @Autowired
+ private ISysMenuService menuService;
- @Autowired
- private SysPermissionService permissionService;
+ @Autowired
+ private SysPermissionService permissionService;
- @Autowired
- private TokenService tokenService;
+ @Autowired
+ private TokenService tokenService;
- /**
- * 登录方法
- *
- * @param loginBody 登录信息
- * @return 结果
- */
- @PostMapping("/login")
- public AjaxResult login(@RequestBody LoginBody loginBody)
- {
- Map ajax = new HashMap<>();
- // 生成令牌
- String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
- loginBody.getUuid());
- ajax.put(Constants.TOKEN, token);
- return AjaxResult.success(ajax);
- }
+ @Autowired
+ private CaptchaService captchaService;
- /**
- * 获取用户信息
- *
- * @return 用户信息
- */
- @GetMapping("getInfo")
- public AjaxResult getInfo()
- {
- LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
- SysUser user = loginUser.getUser();
- // 角色集合
- Set roles = permissionService.getRolePermission(user);
- // 权限集合
- Set permissions = permissionService.getMenuPermission(user);
- Map ajax = new HashMap<>();
- ajax.put("user", user);
- ajax.put("roles", roles);
- ajax.put("permissions", permissions);
- return AjaxResult.success(ajax);
- }
+ /**
+ * 登录方法
+ *
+ * @param loginBody 登录信息
+ * @return 结果
+ */
+ @PostMapping("/login")
+ public AjaxResult login(@RequestBody LoginBody loginBody) {
+ CaptchaVO vo = new CaptchaVO();
+ vo.setCaptchaVerification(loginBody.getCode());
+ ResponseModel verification = captchaService.verification(vo);
+ if (!Objects.equals("0000", verification.getRepCode())) {
+ throw new BaseException("验证码校验失败!");
+ }
+ // 生成令牌
+ String token = loginService.login(loginBody.getUsername(), loginBody.getPassword());
+ Map result = new HashMap<>();
+ result.put(Constants.TOKEN, token);
+ return AjaxResult.success(result);
+ }
- /**
- * 获取路由信息
- *
- * @return 路由信息
- */
- @GetMapping("getRouters")
- public AjaxResult getRouters()
- {
- LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
- // 用户信息
- SysUser user = loginUser.getUser();
- List menus = menuService.selectMenuTreeByUserId(user.getUserId());
- return AjaxResult.success(menuService.buildMenus(menus));
- }
+ /**
+ * 获取用户信息
+ *
+ * @return 用户信息
+ */
+ @GetMapping("getInfo")
+ public AjaxResult getInfo() {
+ LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+ SysUser user = loginUser.getUser();
+ // 角色集合
+ Set roles = permissionService.getRolePermission(user);
+ // 权限集合
+ Set permissions = permissionService.getMenuPermission(user);
+ Map ajax = new HashMap<>();
+ ajax.put("user", user);
+ ajax.put("roles", roles);
+ ajax.put("permissions", permissions);
+ return AjaxResult.success(ajax);
+ }
+
+ /**
+ * 获取路由信息
+ *
+ * @return 路由信息
+ */
+ @GetMapping("getRouters")
+ public AjaxResult getRouters() {
+ LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+ // 用户信息
+ SysUser user = loginUser.getUser();
+ List menus = menuService.selectMenuTreeByUserId(user.getUserId());
+ return AjaxResult.success(menuService.buildMenus(menus));
+ }
}
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index 35901b515..d02f29db8 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -12,9 +12,9 @@ spring:
# 主库数据源
master:
driverClassName: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
+ url: jdbc:mysql://${MYSQL_HOST:tb-mysql}:3306/meijai?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
username: root
- password: root
+ password: ${MYSQL_PWD}
# 从库数据源
slave:
driverClassName: com.mysql.cj.jdbc.Driver
@@ -66,13 +66,13 @@ spring:
# redis 配置
redis:
# 地址
- host: localhost
+ host: ${REDIS_HOST:tb-redis}
# 端口,默认为6379
port: 6379
# 数据库索引
- database: 0
+ database: 3
# 密码
- password:
+ password: ${MYSQL_PWD}
# 连接超时时间
timeout: 10s
# 是否开启ssl
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index e153d1948..99dff0734 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -13,17 +13,26 @@ ruoyi:
# 获取ip地址开关
addressEnabled: true
-captcha:
- # 验证码开关
- enabled: true
- # 验证码类型 math 数组计算 char 字符验证
- type: math
- # line 线段干扰 circle 圆圈干扰 shear 扭曲干扰
- category: circle
- # 数字验证码位数
- numberLength: 1
- # 字符验证码长度
- charLength: 4
+aj:
+ captcha:
+ jigsaw: classpath:images/jigsaw
+ pic-click: classpath:images/pic-click
+ cache-type: local
+ type: default
+ water-mark: RuoYi-Vue-Plus
+ slip-offset: 5
+ aes-status: true
+ interference-options: 2
+ history-data-clear-enable: true
+ req-frequency-limit-enable: true
+ req-get-lock-limit: 5
+ req-get-lock-seconds: 360
+ # get接口一分钟内请求数限制
+ req-get-minute-limit: 30
+ # check接口一分钟内请求数限制
+ req-check-minute-limit: 60
+ # verify接口一分钟内请求数限制
+ req-verify-minute-limit: 60
# 开发环境配置
server:
diff --git a/ruoyi-admin/src/main/resources/images.pic-click/bg1.png b/ruoyi-admin/src/main/resources/images.pic-click/bg1.png
new file mode 100644
index 000000000..51573a0c4
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images.pic-click/bg1.png differ
diff --git a/ruoyi-admin/src/main/resources/images.pic-click/bg10.png b/ruoyi-admin/src/main/resources/images.pic-click/bg10.png
new file mode 100644
index 000000000..f633aeed2
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images.pic-click/bg10.png differ
diff --git a/ruoyi-admin/src/main/resources/images.pic-click/bg2.png b/ruoyi-admin/src/main/resources/images.pic-click/bg2.png
new file mode 100644
index 000000000..909dc39ef
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images.pic-click/bg2.png differ
diff --git a/ruoyi-admin/src/main/resources/images.pic-click/bg3.png b/ruoyi-admin/src/main/resources/images.pic-click/bg3.png
new file mode 100644
index 000000000..59bc59c0b
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images.pic-click/bg3.png differ
diff --git a/ruoyi-admin/src/main/resources/images.pic-click/bg4.png b/ruoyi-admin/src/main/resources/images.pic-click/bg4.png
new file mode 100644
index 000000000..c856f4d97
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images.pic-click/bg4.png differ
diff --git a/ruoyi-admin/src/main/resources/images.pic-click/bg5.png b/ruoyi-admin/src/main/resources/images.pic-click/bg5.png
new file mode 100644
index 000000000..4594fcf65
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images.pic-click/bg5.png differ
diff --git a/ruoyi-admin/src/main/resources/images.pic-click/bg6.png b/ruoyi-admin/src/main/resources/images.pic-click/bg6.png
new file mode 100644
index 000000000..0f28d820b
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images.pic-click/bg6.png differ
diff --git a/ruoyi-admin/src/main/resources/images.pic-click/bg7.png b/ruoyi-admin/src/main/resources/images.pic-click/bg7.png
new file mode 100644
index 000000000..1e0449297
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images.pic-click/bg7.png differ
diff --git a/ruoyi-admin/src/main/resources/images.pic-click/bg8.png b/ruoyi-admin/src/main/resources/images.pic-click/bg8.png
new file mode 100644
index 000000000..f11545fd3
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images.pic-click/bg8.png differ
diff --git a/ruoyi-admin/src/main/resources/images.pic-click/bg9.png b/ruoyi-admin/src/main/resources/images.pic-click/bg9.png
new file mode 100644
index 000000000..2f3a86dab
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images.pic-click/bg9.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/original/bg1.png b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg1.png
new file mode 100644
index 000000000..4cde9dc04
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg1.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/original/bg2.png b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg2.png
new file mode 100644
index 000000000..93b70d4c4
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg2.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/original/bg3.png b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg3.png
new file mode 100644
index 000000000..f60f7b735
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg3.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/original/bg4.png b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg4.png
new file mode 100644
index 000000000..9bd65ef53
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg4.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/original/bg5.png b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg5.png
new file mode 100644
index 000000000..13585062a
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg5.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/original/bg6.png b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg6.png
new file mode 100644
index 000000000..0ea2b377d
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg6.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/original/bg7.png b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg7.png
new file mode 100644
index 000000000..8c05e9c33
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg7.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/original/bg8.png b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg8.png
new file mode 100644
index 000000000..bcd00c73c
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg8.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/original/bg9.png b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg9.png
new file mode 100644
index 000000000..b74f704c2
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/original/bg9.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/1.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/1.png
new file mode 100644
index 000000000..d6b975b57
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/1.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/10.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/10.png
new file mode 100644
index 000000000..7cec5028c
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/10.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/11.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/11.png
new file mode 100644
index 000000000..4f6133786
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/11.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/12.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/12.png
new file mode 100644
index 000000000..a7827fdab
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/12.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/13.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/13.png
new file mode 100644
index 000000000..9f7d813d7
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/13.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/14.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/14.png
new file mode 100644
index 000000000..9abec8a73
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/14.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/15.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/15.png
new file mode 100644
index 000000000..3fffdfcd2
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/15.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/16.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/16.png
new file mode 100644
index 000000000..f5944a0dc
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/16.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/17.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/17.png
new file mode 100644
index 000000000..e17c4fa06
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/17.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/18.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/18.png
new file mode 100644
index 000000000..5d0f9097c
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/18.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/19.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/19.png
new file mode 100644
index 000000000..6b39d72d9
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/19.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/8.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/8.png
new file mode 100644
index 000000000..3754bee0e
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/8.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/9.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/9.png
new file mode 100644
index 000000000..ff36a2156
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/9.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/1.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/1.png
new file mode 100644
index 000000000..369ed871e
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/1.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/2.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/2.png
new file mode 100644
index 000000000..adec30f91
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/2.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/3.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/3.png
new file mode 100644
index 000000000..69324725e
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/3.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/4.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/4.png
new file mode 100644
index 000000000..abfa4fdcd
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/4.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/5.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/5.png
new file mode 100644
index 000000000..77105ac5a
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/5.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/6.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/6.png
new file mode 100644
index 000000000..7c90bd772
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/6.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/7.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/7.png
new file mode 100644
index 000000000..9c6862d9e
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/11/xin替换/7.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/2.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/2.png
new file mode 100644
index 000000000..b1482d48b
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/2.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/3.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/3.png
new file mode 100644
index 000000000..cdbb0b18c
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/3.png differ
diff --git a/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/4.png b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/4.png
new file mode 100644
index 000000000..bc69c9622
Binary files /dev/null and b/ruoyi-admin/src/main/resources/images/jigsaw/slidingBlock/4.png differ
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
index a87117893..3a8ad80a2 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -136,4 +136,9 @@ public class Constants
* 资源映射路径 前缀
*/
public static final String REDIS_LOCK_KEY = "redis_lock:";
+
+ /**
+ * 日期相关常量
+ */
+ public static final String FULL_DATE_TIME = "yyyy-MM-dd HH:mm:ss";
}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
index d66686be1..d5adf96aa 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
@@ -5,7 +5,7 @@ import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
-import java.util.Date;
+import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@@ -18,29 +18,42 @@ import java.util.Map;
@Data
@NoArgsConstructor
@Accessors(chain = true)
-public class BaseEntity implements Serializable
-{
- private static final long serialVersionUID = 1L;
+public class BaseEntity implements Serializable {
+ private static final long serialVersionUID = 1L;
- /** 搜索值 */
- private String searchValue;
+ /**
+ * 搜索值
+ */
+ private String searchValue;
- /** 创建者 */
- private String createBy;
+ /**
+ * 创建者
+ */
+ private String createBy;
- /** 创建时间 */
- private Date createTime;
+ /**
+ * 创建时间
+ */
+ private LocalDateTime createTime;
- /** 更新者 */
- private String updateBy;
+ /**
+ * 更新者
+ */
+ private String updateBy;
- /** 更新时间 */
- private Date updateTime;
+ /**
+ * 更新时间
+ */
+ private LocalDateTime updateTime;
- /** 备注 */
- private String remark;
+ /**
+ * 备注
+ */
+ private String remark;
- /** 请求参数 */
- private Map params = new HashMap<>();
+ /**
+ * 请求参数
+ */
+ private Map params = new HashMap<>();
}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/IdUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/IdUtils.java
new file mode 100644
index 000000000..5a5bca8a7
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/IdUtils.java
@@ -0,0 +1,12 @@
+package com.ruoyi.common.utils;
+
+import cn.hutool.core.util.IdUtil;
+import lombok.experimental.UtilityClass;
+
+@UtilityClass
+public class IdUtils {
+
+ public Long nextId() {
+ return IdUtil.getSnowflake(1, 1).nextId();
+ }
+}
diff --git a/ruoyi-coupons/pom.xml b/ruoyi-coupons/pom.xml
new file mode 100644
index 000000000..1a6fff039
--- /dev/null
+++ b/ruoyi-coupons/pom.xml
@@ -0,0 +1,19 @@
+
+
+
+ ruoyi-vue-plus
+ com.ruoyi
+ 2.4.0
+
+ 4.0.0
+
+ ruoyi-coupons
+
+
+ 8
+ 8
+
+
+
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/captcha/UnsignedMathGenerator.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/captcha/UnsignedMathGenerator.java
deleted file mode 100644
index b4f8bfc12..000000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/captcha/UnsignedMathGenerator.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.ruoyi.framework.captcha;
-
-import cn.hutool.captcha.generator.CodeGenerator;
-import cn.hutool.core.math.Calculator;
-import cn.hutool.core.util.CharUtil;
-import cn.hutool.core.util.RandomUtil;
-import cn.hutool.core.util.StrUtil;
-
-/**
- * 无符号计算生成器
- *
- * @author Lion Li
- */
-public class UnsignedMathGenerator implements CodeGenerator {
-
- private static final long serialVersionUID = -5514819971774091076L;
-
- private static final String operators = "+-*";
-
- /**
- * 参与计算数字最大长度
- */
- private final int numberLength;
-
- /**
- * 构造
- */
- public UnsignedMathGenerator() {
- this(2);
- }
-
- /**
- * 构造
- *
- * @param numberLength 参与计算最大数字位数
- */
- public UnsignedMathGenerator(int numberLength) {
- this.numberLength = numberLength;
- }
-
- @Override
- public String generate() {
- final int limit = getLimit();
- int min = RandomUtil.randomInt(limit);
- int max = RandomUtil.randomInt(min, limit);
- String number1 = Integer.toString(max);
- String number2 = Integer.toString(min);
- number1 = StrUtil.padAfter(number1, this.numberLength, CharUtil.SPACE);
- number2 = StrUtil.padAfter(number2, this.numberLength, CharUtil.SPACE);
-
- return number1 + RandomUtil.randomChar(operators) + number2 + '=';
- }
-
- @Override
- public boolean verify(String code, String userInputCode) {
- int result;
- try {
- result = Integer.parseInt(userInputCode);
- } catch (NumberFormatException e) {
- // 用户输入非数字
- return false;
- }
-
- final int calculateResult = (int) Calculator.conversion(code);
- return result == calculateResult;
- }
-
- /**
- * 获取验证码长度
- *
- * @return 验证码长度
- */
- public int getLength() {
- return this.numberLength * 2 + 2;
- }
-
- /**
- * 根据长度获取参与计算数字最大值
- *
- * @return 最大值
- */
- private int getLimit() {
- return Integer.parseInt("1" + StrUtil.repeat('0', this.numberLength));
- }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java
deleted file mode 100644
index 4cd99970c..000000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.ruoyi.framework.config;
-
-import java.awt.*;
-
-import cn.hutool.captcha.*;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * 验证码配置
- *
- * @author Lion Li
- */
-@Configuration
-public class CaptchaConfig {
-
- private final int width = 160;
- private final int height = 60;
- private final Color background = Color.PINK;
- private final Font font = new Font("Arial", Font.BOLD, 48);
-
- /**
- * 圆圈干扰验证码
- */
- @Bean(name = "CircleCaptcha")
- public CircleCaptcha getCircleCaptcha() {
- CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(width, height);
- captcha.setBackground(background);
- captcha.setFont(font);
- return captcha;
- }
-
- /**
- * 线段干扰的验证码
- */
- @Bean(name = "LineCaptcha")
- public LineCaptcha getLineCaptcha() {
- LineCaptcha captcha = CaptchaUtil.createLineCaptcha(width, height);
- captcha.setBackground(background);
- captcha.setFont(font);
- return captcha;
- }
-
- /**
- * 扭曲干扰验证码
- */
- @Bean(name = "ShearCaptcha")
- public ShearCaptcha getShearCaptcha() {
- ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(width, height);
- captcha.setBackground(background);
- captcha.setFont(font);
- return captcha;
- }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
index 79ade7879..078ca0247 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
@@ -101,7 +101,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
// 过滤请求
.authorizeRequests()
// 对于登录login 验证码captchaImage 允许匿名访问
- .antMatchers("/login", "/captchaImage").anonymous()
+ .antMatchers("/login", "/captcha/get", "/captcha/check").anonymous()
.antMatchers(
HttpMethod.GET,
"/*.html",
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/CaptchaProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/CaptchaProperties.java
deleted file mode 100644
index 86ac70606..000000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/CaptchaProperties.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.ruoyi.framework.config.properties;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * 验证码 配置属性
- *
- * @author Lion Li
- */
-@Data
-@Component
-@ConfigurationProperties(prefix = "captcha")
-public class CaptchaProperties {
-
- /**
- * 验证码开关
- */
- private Boolean enabled;
-
- /**
- * 验证码类型
- */
- private String type;
-
- /**
- * 验证码类别
- */
- private String category;
-
- /**
- * 数字验证码位数
- */
- private Integer numberLength;
-
- /**
- * 字符验证码长度
- */
- private Integer charLength;
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
index d0b9511ea..e98fd3c76 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
@@ -5,13 +5,10 @@ import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.CustomException;
-import com.ruoyi.common.exception.user.CaptchaException;
-import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils;
-import com.ruoyi.framework.config.properties.CaptchaProperties;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
@@ -29,87 +26,63 @@ import javax.servlet.http.HttpServletRequest;
* @author ruoyi
*/
@Component
-public class SysLoginService
-{
- @Autowired
- private TokenService tokenService;
+public class SysLoginService {
+ @Autowired
+ private TokenService tokenService;
- @Resource
- private AuthenticationManager authenticationManager;
-
- @Autowired
- private RedisCache redisCache;
+ @Resource
+ private AuthenticationManager authenticationManager;
@Autowired
- private CaptchaProperties captchaProperties;
+ private RedisCache redisCache;
+
+/* @Autowired
+ private CaptchaProperties captchaProperties;*/
@Autowired
- private ISysUserService userService;
+ private ISysUserService userService;
@Autowired
private AsyncService asyncService;
- /**
- * 登录验证
- *
- * @param username 用户名
- * @param password 密码
- * @param code 验证码
- * @param uuid 唯一标识
- * @return 结果
- */
- public String login(String username, String password, String code, String uuid)
- {
+ /**
+ * 登录验证
+ *
+ * @param username 用户名
+ * @param password 密码
+ * @return 结果
+ */
+ public String login(String username, String password) {
HttpServletRequest request = ServletUtils.getRequest();
- if(captchaProperties.getEnabled()) {
- String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
- String captcha = redisCache.getCacheObject(verifyKey);
- redisCache.deleteObject(verifyKey);
- if (captcha == null) {
- asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"), request);
- throw new CaptchaExpireException();
- }
- if (!code.equalsIgnoreCase(captcha)) {
- asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"), request);
- throw new CaptchaException();
+ // 用户验证
+ Authentication authentication;
+ try {
+ // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
+ authentication = authenticationManager
+ .authenticate(new UsernamePasswordAuthenticationToken(username, password));
+ } catch (Exception e) {
+ if (e instanceof BadCredentialsException) {
+ asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"), request);
+ throw new UserPasswordNotMatchException();
+ } else {
+ asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage(), request);
+ throw new CustomException(e.getMessage());
}
}
- // 用户验证
- Authentication authentication = null;
- try
- {
- // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
- authentication = authenticationManager
- .authenticate(new UsernamePasswordAuthenticationToken(username, password));
- }
- catch (Exception e)
- {
- if (e instanceof BadCredentialsException)
- {
- asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"), request);
- throw new UserPasswordNotMatchException();
- }
- else
- {
- asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage(), request);
- throw new CustomException(e.getMessage());
- }
- }
asyncService.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);
- LoginUser loginUser = (LoginUser) authentication.getPrincipal();
- recordLoginInfo(loginUser.getUser());
- // 生成token
- return tokenService.createToken(loginUser);
- }
+ LoginUser loginUser = (LoginUser) authentication.getPrincipal();
+ recordLoginInfo(loginUser.getUser());
+ // 生成token
+ return tokenService.createToken(loginUser);
+ }
- /**
- * 记录登录信息
- */
- public void recordLoginInfo(SysUser user)
- {
- user.setLoginIp(ServletUtils.getClientIP());
- user.setLoginDate(DateUtils.getNowDate());
+ /**
+ * 记录登录信息
+ */
+ public void recordLoginInfo(SysUser user) {
+ user.setLoginIp(ServletUtils.getClientIP());
+ user.setLoginDate(DateUtils.getNowDate());
user.setUpdateBy(user.getUserName());
- userService.updateUserProfile(user);
- }
+ userService.updateUserProfile(user);
+ }
}
diff --git a/ruoyi-product/pom.xml b/ruoyi-product/pom.xml
new file mode 100644
index 000000000..0b4433834
--- /dev/null
+++ b/ruoyi-product/pom.xml
@@ -0,0 +1,33 @@
+
+
+
+ ruoyi-vue-plus
+ com.ruoyi
+ 2.4.0
+
+ 4.0.0
+
+ ruoyi-product
+
+
+ 8
+ 8
+
+
+ 产品详情模块
+
+
+
+
+ com.ruoyi
+ ruoyi-common
+
+
+
+ com.github.xiaoymin
+ knife4j-spring-boot-starter
+
+
+
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProBannerAddBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProBannerAddBo.java
new file mode 100644
index 000000000..591659f6b
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProBannerAddBo.java
@@ -0,0 +1,53 @@
+package com.ruoyi.product.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * banner管理添加对象 pro_banner
+ *
+ * @author ruoyi
+ * @date 2021-06-30
+ */
+@Data
+@ApiModel("banner管理添加对象")
+public class ProBannerAddBo {
+
+
+ /**
+ * 主键id
+ */
+ @ApiModelProperty("主键id")
+ private Long id;
+
+ /**
+ * banner标题
+ */
+ @ApiModelProperty("banner标题")
+ private String title;
+
+ /**
+ * url跳转(也可能是path)
+ */
+ @ApiModelProperty("url跳转(也可能是path)")
+ private String url;
+
+ /**
+ * 图片url
+ */
+ @ApiModelProperty("图片url")
+ private String picUrl;
+
+ /**
+ * 是否跳转
+ */
+ @ApiModelProperty("是否跳转")
+ private Integer redirectFlag;
+
+ /**
+ * banner类型,1应用内跳转,3外部跳转
+ */
+ @ApiModelProperty("banner类型,1应用内跳转,3外部跳转")
+ private Integer bannerType;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProBannerEditBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProBannerEditBo.java
new file mode 100644
index 000000000..6e05a0e4a
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProBannerEditBo.java
@@ -0,0 +1,63 @@
+package com.ruoyi.product.bo;
+
+/**
+ * @BelongsProject: RuoYi-Vue-Plus
+ * @BelongsPackage: com.ruoyi.product.bo
+ * @Author: yefei
+ * @CreateTime: 2021-06-30 16:41
+ * @Description: 编辑
+ */
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * banner管理编辑对象 pro_banner
+ *
+ * @author ruoyi
+ * @date 2021-06-30
+ */
+@Data
+@ApiModel("banner管理编辑对象")
+public class ProBannerEditBo {
+
+ /**
+ * 主键id
+ */
+ @JsonSerialize(using = ToStringSerializer.class)
+ @ApiModelProperty("主键id")
+ private Long id;
+
+ /**
+ * banner标题
+ */
+ @ApiModelProperty("banner标题")
+ private String title;
+
+ /**
+ * url跳转(也可能是path)
+ */
+ @ApiModelProperty("url跳转(也可能是path)")
+ private String url;
+
+ /**
+ * 图片url
+ */
+ @ApiModelProperty("图片url")
+ private String picUrl;
+
+ /**
+ * 是否跳转
+ */
+ @ApiModelProperty("是否跳转")
+ private Integer redirectFlag;
+
+ /**
+ * banner类型,1应用内跳转,3外部跳转
+ */
+ @ApiModelProperty("banner类型,1应用内跳转,3外部跳转")
+ private Integer bannerType;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProBannerQueryBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProBannerQueryBo.java
new file mode 100644
index 000000000..d8b6f84c2
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProBannerQueryBo.java
@@ -0,0 +1,70 @@
+package com.ruoyi.product.bo;
+
+import com.ruoyi.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @BelongsProject: RuoYi-Vue-Plus
+ * @BelongsPackage: com.ruoyi.product.bo
+ * @Author: yefei
+ * @CreateTime: 2021-06-30 16:37
+ * @Description:
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel("banner管理分页查询对象")
+public class ProBannerQueryBo extends BaseEntity {
+ /**
+ * 分页大小
+ */
+ @ApiModelProperty("分页大小")
+ private Integer pageSize;
+ /**
+ * 当前页数
+ */
+ @ApiModelProperty("当前页数")
+ private Integer pageNum;
+ /**
+ * 排序列
+ */
+ @ApiModelProperty("排序列")
+ private String orderByColumn;
+ /**
+ * 排序的方向desc或者asc
+ */
+ @ApiModelProperty(value = "排序的方向", example = "asc,desc")
+ private String isAsc;
+
+
+ /**
+ * banner标题
+ */
+ @ApiModelProperty("banner标题")
+ private String title;
+ /**
+ * url跳转(也可能是path)
+ */
+ @ApiModelProperty("url跳转(也可能是path)")
+ private String url;
+ /**
+ * 图片url
+ */
+ @ApiModelProperty("图片url")
+ private String picUrl;
+ /**
+ * 是否跳转
+ */
+ @ApiModelProperty("是否跳转")
+ private Integer redirectFlag;
+ /**
+ * banner类型,1应用内跳转,3外部跳转
+ */
+ @ApiModelProperty("banner类型,1应用内跳转,3外部跳转")
+ private Integer bannerType;
+
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProCategoryAddBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProCategoryAddBo.java
new file mode 100644
index 000000000..3d3ae0b03
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProCategoryAddBo.java
@@ -0,0 +1,62 @@
+package com.ruoyi.product.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+
+/**
+ * 商品服务类别添加对象 pro_category
+ *
+ * @author ruoyi
+ * @date 2021-07-01
+ */
+@Data
+@ApiModel("商品服务类别添加对象")
+public class ProCategoryAddBo {
+
+
+ /**
+ * 类别名字
+ */
+ @ApiModelProperty("类别名字")
+ private String categoryName;
+
+ /**
+ * icon图片
+ */
+ @ApiModelProperty("icon图片")
+ private String iconUrl;
+
+ /**
+ * 备注信息
+ */
+ @ApiModelProperty("备注信息")
+ private String remark;
+
+ /**
+ * 创建者
+ */
+ @ApiModelProperty("创建者")
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @ApiModelProperty("创建时间")
+ private Date createTime;
+
+ /**
+ * 更新者
+ */
+ @ApiModelProperty("更新者")
+ private String updateBy;
+
+ /**
+ * 更新时间
+ */
+ @ApiModelProperty("更新时间")
+ private Date updateTime;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProCategoryEditBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProCategoryEditBo.java
new file mode 100644
index 000000000..dc1c3bc17
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProCategoryEditBo.java
@@ -0,0 +1,45 @@
+package com.ruoyi.product.bo;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+
+/**
+ * 商品服务类别编辑对象 pro_category
+ *
+ * @author ruoyi
+ * @date 2021-07-01
+ */
+@Data
+@ApiModel("商品服务类别编辑对象")
+public class ProCategoryEditBo {
+
+
+ /**
+ * 主键id
+ */
+ @ApiModelProperty("主键id")
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long id;
+
+ /**
+ * 类别名字
+ */
+ @ApiModelProperty("类别名字")
+ private String categoryName;
+
+ /**
+ * icon图片
+ */
+ @ApiModelProperty("icon图片")
+ private String iconUrl;
+
+ /**
+ * 备注信息
+ */
+ @ApiModelProperty("备注信息")
+ private String remark;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProCategoryQueryBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProCategoryQueryBo.java
new file mode 100644
index 000000000..5176cfb2a
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProCategoryQueryBo.java
@@ -0,0 +1,54 @@
+package com.ruoyi.product.bo;
+
+import com.ruoyi.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 商品服务类别分页查询对象 pro_category
+ *
+ * @author ruoyi
+ * @date 2021-07-01
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel("商品服务类别分页查询对象")
+public class ProCategoryQueryBo extends BaseEntity {
+
+ /**
+ * 分页大小
+ */
+ @ApiModelProperty("分页大小")
+ private Integer pageSize;
+ /**
+ * 当前页数
+ */
+ @ApiModelProperty("当前页数")
+ private Integer pageNum;
+ /**
+ * 排序列
+ */
+ @ApiModelProperty("排序列")
+ private String orderByColumn;
+ /**
+ * 排序的方向desc或者asc
+ */
+ @ApiModelProperty(value = "排序的方向", example = "asc,desc")
+ private String isAsc;
+
+
+ /**
+ * 类别名字
+ */
+ @ApiModelProperty("类别名字")
+ private String categoryName;
+ /**
+ * icon图片
+ */
+ @ApiModelProperty("icon图片")
+ private String iconUrl;
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemAddBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemAddBo.java
new file mode 100644
index 000000000..08f36a818
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemAddBo.java
@@ -0,0 +1,94 @@
+package com.ruoyi.product.bo;
+
+import com.ruoyi.product.dto.ProItemPictureDTO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 商品详情添加对象 pro_item
+ *
+ * @author ruoyi
+ * @date 2021-07-01
+ */
+@Data
+@ApiModel("商品详情添加对象")
+public class ProItemAddBo {
+
+
+ /**
+ * 产品名字
+ */
+ @ApiModelProperty("产品名字")
+ private String proName;
+
+ /**
+ * 价钱
+ */
+ @ApiModelProperty("价钱")
+ private BigDecimal price;
+
+ /**
+ * 描述
+ */
+ @ApiModelProperty("描述")
+ private String description;
+
+ /**
+ * 库存(限量库存)
+ */
+ @ApiModelProperty("库存(限量库存)")
+ private Integer sku;
+
+ /**
+ * 封面图片
+ */
+ @ApiModelProperty("封面图片")
+ private String coverImage;
+
+ /**
+ * 是否发布
+ */
+ @ApiModelProperty("是否发布")
+ private Integer publishFlag;
+
+ /**
+ * 发布时间
+ */
+ @ApiModelProperty("发布时间")
+ private Date publishTime;
+
+ /**
+ * 创建者
+ */
+ @ApiModelProperty("创建者")
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @ApiModelProperty("创建时间")
+ private Date createTime;
+
+ /**
+ * 更新者
+ */
+ @ApiModelProperty("更新者")
+ private String updateBy;
+
+ /**
+ * 更新时间
+ */
+ @ApiModelProperty("更新时间")
+ private Date updateTime;
+
+ @ApiModelProperty("图片列表")
+ private List proItemPictures;
+
+ @ApiModelProperty("分类id集合")
+ private List proItemCategoryIds;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemEditBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemEditBo.java
new file mode 100644
index 000000000..099e12d95
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemEditBo.java
@@ -0,0 +1,27 @@
+package com.ruoyi.product.bo;
+
+import com.ruoyi.product.domain.ProItem;
+import com.ruoyi.product.dto.ProItemPictureDTO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 商品详情编辑对象 pro_item
+ *
+ * @author ruoyi
+ * @date 2021-07-01
+ */
+@Data
+@ApiModel("商品详情编辑对象")
+public class ProItemEditBo extends ProItem {
+
+
+ @ApiModelProperty("图片列表")
+ private List proItemPictures;
+
+ @ApiModelProperty("分类id集合")
+ private List proItemCategoryIds;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemQueryBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemQueryBo.java
new file mode 100644
index 000000000..4e46a3a4f
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemQueryBo.java
@@ -0,0 +1,69 @@
+package com.ruoyi.product.bo;
+
+import com.ruoyi.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * 商品详情分页查询对象 pro_item
+ *
+ * @author ruoyi
+ * @date 2021-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel("商品详情分页查询对象")
+public class ProItemQueryBo extends BaseEntity {
+
+ /**
+ * 分页大小
+ */
+ @ApiModelProperty("分页大小")
+ private Integer pageSize;
+ /**
+ * 当前页数
+ */
+ @ApiModelProperty("当前页数")
+ private Integer pageNum;
+ /**
+ * 排序列
+ */
+ @ApiModelProperty("排序列")
+ private String orderByColumn;
+ /**
+ * 排序的方向desc或者asc
+ */
+ @ApiModelProperty(value = "排序的方向", example = "asc,desc")
+ private String isAsc;
+
+
+ /**
+ * 产品名字
+ */
+ @ApiModelProperty("产品名字")
+ private String proName;
+ /**
+ * 库存(限量库存)
+ */
+ @ApiModelProperty("库存(限量库存)")
+ private Integer sku;
+ /**
+ * 封面图片
+ */
+ @ApiModelProperty("封面图片")
+ private String coverImage;
+ /**
+ * 是否发布
+ */
+ @ApiModelProperty("是否发布")
+ private Integer publishFlag;
+
+ @ApiModelProperty("是否分页,0不分页,1分页,默认分页")
+ private Integer bePage = 1;
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemRelationAddBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemRelationAddBo.java
new file mode 100644
index 000000000..16d7893d9
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemRelationAddBo.java
@@ -0,0 +1,41 @@
+package com.ruoyi.product.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 商品关系(预约记录、优惠券)添加对象 pro_item_relation
+ *
+ * @author ruoyi
+ * @date 2021-04-09
+ */
+@Data
+@ApiModel("商品关系(预约记录、优惠券)添加对象")
+public class ProItemRelationAddBo {
+
+ /** 业务id,可以是预约记录id,也可以是优惠券id */
+ @ApiModelProperty("业务id,可以是预约记录id,也可以是优惠券id")
+ private Long businessId;
+ /** 1表示优惠券类型关联关系,3表示预约类型关联关系 */
+ @ApiModelProperty("1表示优惠券类型关联关系,3表示预约类型关联关系")
+ private String type;
+ /** 商品id */
+ @ApiModelProperty("商品id")
+ private Long proItemId;
+ /** 创建时间 */
+ @ApiModelProperty("创建时间")
+ private Date createTime;
+ /** 创建人 */
+ @ApiModelProperty("创建人")
+ private String createBy;
+ /** 更新时间 */
+ @ApiModelProperty("更新时间")
+ private Date updateTime;
+ /** 更新人 */
+ @ApiModelProperty("更新人")
+ private String updateBy;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemRelationEditBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemRelationEditBo.java
new file mode 100644
index 000000000..7c19e7917
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemRelationEditBo.java
@@ -0,0 +1,39 @@
+package com.ruoyi.product.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.util.Date;
+
+
+/**
+ * 商品关系(预约记录、优惠券)编辑对象 pro_item_relation
+ *
+ * @author ruoyi
+ * @date 2021-04-09
+ */
+@Data
+@ApiModel("商品关系(预约记录、优惠券)编辑对象")
+public class ProItemRelationEditBo {
+
+
+ /** 业务id,可以是预约记录id,也可以是优惠券id */
+ @ApiModelProperty("业务id,可以是预约记录id,也可以是优惠券id")
+ private Long businessId;
+
+ /** 1表示优惠券类型关联关系,3表示预约类型关联关系 */
+ @ApiModelProperty("1表示优惠券类型关联关系,3表示预约类型关联关系")
+ private String type;
+
+ /** 商品id */
+ @ApiModelProperty("商品id")
+ private Long proItemId;
+
+ /** 更新时间 */
+ @ApiModelProperty("更新时间")
+ private Date updateTime;
+
+ /** 更新人 */
+ @ApiModelProperty("更新人")
+ private String updateBy;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemRelationQueryBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemRelationQueryBo.java
new file mode 100644
index 000000000..8ce111feb
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemRelationQueryBo.java
@@ -0,0 +1,49 @@
+package com.ruoyi.product.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.HashMap;
+
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 商品关系(预约记录、优惠券)分页查询对象 pro_item_relation
+ *
+ * @author ruoyi
+ * @date 2021-04-09
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel("商品关系(预约记录、优惠券)分页查询对象")
+public class ProItemRelationQueryBo extends BaseEntity {
+
+ /** 分页大小 */
+ @ApiModelProperty("分页大小")
+ private Integer pageSize;
+ /** 当前页数 */
+ @ApiModelProperty("当前页数")
+ private Integer pageNum;
+ /** 排序列 */
+ @ApiModelProperty("排序列")
+ private String orderByColumn;
+ /** 排序的方向desc或者asc */
+ @ApiModelProperty(value = "排序的方向", example = "asc,desc")
+ private String isAsc;
+
+
+ /** 业务id,可以是预约记录id,也可以是优惠券id */
+ @ApiModelProperty("业务id,可以是预约记录id,也可以是优惠券id")
+ private Long businessId;
+ /** 1表示优惠券类型关联关系,3表示预约类型关联关系 */
+ @ApiModelProperty("1表示优惠券类型关联关系,3表示预约类型关联关系")
+ private String type;
+ /** 商品id */
+ @ApiModelProperty("商品id")
+ private Long proItemId;
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemSpecificationAddBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemSpecificationAddBo.java
new file mode 100644
index 000000000..2d75eead1
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemSpecificationAddBo.java
@@ -0,0 +1,91 @@
+package com.ruoyi.product.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 商品规格添加对象 pro_item_specification
+ *
+ * @author ruoyi
+ * @date 2021-04-06
+ */
+@Data
+@ApiModel("商品规格添加对象")
+public class ProItemSpecificationAddBo {
+
+ /**
+ * 商品id
+ */
+ @ApiModelProperty("商品id")
+ private Long itemId;
+ /**
+ * 规格名字
+ */
+ @ApiModelProperty("规格名字")
+ private String specificationTitle;
+ /**
+ * 图片url地址
+ */
+ @ApiModelProperty("图片url地址")
+ private String urlPath;
+ /**
+ * 规格库存
+ */
+ @ApiModelProperty("规格库存")
+ private Integer specificationSku;
+ /**
+ * 价格
+ */
+ @ApiModelProperty("价格")
+ private BigDecimal price;
+ /**
+ * 别名
+ */
+ @ApiModelProperty("别名")
+ private String aliasName;
+ /**
+ * 描述
+ */
+ @ApiModelProperty("描述")
+ private String description;
+ /**
+ * 是否上架,0未上架,1上架,默认是0
+ */
+ @ApiModelProperty("是否上架,0未上架,1上架,默认是0")
+ private String publishFlag;
+ /**
+ * 上架时间
+ */
+ @ApiModelProperty("上架时间")
+ private LocalDateTime publishTime;
+ /**
+ * 创建时间
+ */
+ @ApiModelProperty("创建时间")
+ private LocalDateTime createTime;
+ /**
+ * 创建人id
+ */
+ @ApiModelProperty("创建人id")
+ private String createBy;
+ /**
+ * 更新时间
+ */
+ @ApiModelProperty("更新时间")
+ private LocalDateTime updateTime;
+ /**
+ * 更新人id
+ */
+ @ApiModelProperty("更新人id")
+ private String updateBy;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemSpecificationEditBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemSpecificationEditBo.java
new file mode 100644
index 000000000..b80429c4b
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemSpecificationEditBo.java
@@ -0,0 +1,95 @@
+package com.ruoyi.product.bo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import static com.ruoyi.common.constant.Constants.FULL_DATE_TIME;
+
+/**
+ * 商品规格编辑对象 pro_item_specification
+ *
+ * @author ruoyi
+ * @date 2021-04-06
+ */
+@Data
+@ApiModel("商品规格编辑对象")
+public class ProItemSpecificationEditBo {
+
+ @ApiModelProperty("商品规格id")
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long id;
+ /**
+ * 商品id
+ */
+ @JsonSerialize(using = ToStringSerializer.class)
+ @ApiModelProperty("商品id")
+ private Long itemId;
+
+ /**
+ * 规格名字
+ */
+ @ApiModelProperty("规格名字")
+ private String specificationTitle;
+
+ /**
+ * 图片url地址
+ */
+ @ApiModelProperty("图片url地址")
+ private String urlPath;
+
+ /**
+ * 规格库存
+ */
+ @ApiModelProperty("规格库存")
+ private Integer specificationSku;
+
+ /**
+ * 价格
+ */
+ @ApiModelProperty("价格")
+ private BigDecimal price;
+
+ /**
+ * 别名
+ */
+ @ApiModelProperty("别名")
+ private String aliasName;
+
+ /**
+ * 描述
+ */
+ @ApiModelProperty("描述")
+ private String description;
+
+ /**
+ * 是否上架,0未上架,1上架,默认是0
+ */
+ @ApiModelProperty("是否上架,0未上架,1上架,默认是0")
+ private String publishFlag;
+
+ /**
+ * 上架时间
+ */
+ @JsonFormat(pattern = FULL_DATE_TIME)
+ @ApiModelProperty("上架时间")
+ private LocalDateTime publishTime;
+
+ /**
+ * 更新时间
+ */
+ @ApiModelProperty("更新时间")
+ private LocalDateTime updateTime;
+
+ /**
+ * 更新人id
+ */
+ @ApiModelProperty("更新人id")
+ private String updateBy;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemSpecificationQueryBo.java b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemSpecificationQueryBo.java
new file mode 100644
index 000000000..fc4a7a7c6
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/bo/ProItemSpecificationQueryBo.java
@@ -0,0 +1,55 @@
+package com.ruoyi.product.bo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * 商品规格分页查询对象 pro_item_specification
+ *
+ * @author ruoyi
+ * @date 2021-04-06
+ */
+@Data
+@ApiModel("商品规格分页查询对象")
+public class ProItemSpecificationQueryBo {
+
+ /**
+ * 分页大小
+ */
+ @ApiModelProperty("分页大小")
+ private Integer pageSize;
+ /**
+ * 当前页数
+ */
+ @ApiModelProperty("当前页数")
+ private Integer pageNum;
+ /**
+ * 排序列
+ */
+ @ApiModelProperty("排序列")
+ private String orderByColumn;
+ /**
+ * 排序的方向desc或者asc
+ */
+ @ApiModelProperty(value = "排序的方向", example = "asc,desc")
+ private String isAsc;
+
+
+ /**
+ * 商品id
+ */
+ @ApiModelProperty("商品id")
+ private Long itemId;
+
+ @ApiModelProperty("规格标题")
+ private String specificationTitle;
+
+ @TableField(exist = false)
+ private Map params = new HashMap<>();
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProBanner.java b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProBanner.java
new file mode 100644
index 000000000..212fada2f
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProBanner.java
@@ -0,0 +1,83 @@
+package com.ruoyi.product.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * banner管理对象 pro_banner
+ *
+ * @author ruoyi
+ * @date 2021-03-14
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("pro_banner")
+public class ProBanner implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+
+ /**
+ * 主键id
+ */
+ @TableId(value = "id")
+ private Long id;
+
+ /**
+ * banner标题
+ */
+ private String title;
+
+ /**
+ * url跳转(也可能是path)
+ */
+ private String url;
+
+ /**
+ * 图片url
+ */
+ private String picUrl;
+
+ /**
+ * 是否跳转
+ */
+ private Integer redirectFlag;
+
+ /**
+ * banner类型,1应用内跳转,3外部跳转
+ */
+ private Integer bannerType;
+
+ /**
+ * 创建者
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private Date createTime;
+
+ /**
+ * 更新者
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private String updateBy;
+
+ /**
+ * 更新时间
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Date updateTime;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProCategory.java b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProCategory.java
new file mode 100644
index 000000000..f53249197
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProCategory.java
@@ -0,0 +1,84 @@
+package com.ruoyi.product.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.ruoyi.common.annotation.Excel;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 商品服务类别对象 pro_category
+ *
+ * @author ruoyi
+ * @date 2021-03-14
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("pro_category")
+public class ProCategory implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+
+ /**
+ * 主键id
+ */
+ @JsonSerialize(using = ToStringSerializer.class)
+ @TableId(value = "id", type = IdType.INPUT)
+ private Long id;
+
+ /**
+ * 类别名字
+ */
+ @Excel(name = "类别名字")
+ private String categoryName;
+
+ /**
+ * icon图片
+ */
+ @Excel(name = "icon图片")
+ private String iconUrl;
+
+ /**
+ * 备注信息
+ */
+ @Excel(name = "备注信息")
+ private String remark;
+
+ /**
+ * 创建者
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private Date createTime;
+
+ /**
+ * 更新者
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private String updateBy;
+
+ /**
+ * 更新时间
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Date updateTime;
+
+ @TableField(exist = false)
+ private Map params = new HashMap<>();
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItem.java b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItem.java
new file mode 100644
index 000000000..759fbd8e8
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItem.java
@@ -0,0 +1,121 @@
+package com.ruoyi.product.domain;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.product.dto.ProItemPictureDTO;
+import com.ruoyi.product.vo.ProItemVo;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 商品详情对象 pro_item
+ *
+ * @author ruoyi
+ * @date 2021-03-13
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("pro_item")
+public class ProItem implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+
+ /**
+ * 主键id
+ */
+ @JsonSerialize(using = ToStringSerializer.class)
+ @TableId(value = "id", type = IdType.INPUT)
+ private Long id;
+
+ /**
+ * 产品名字
+ */
+ @Excel(name = "产品名字")
+ private String proName;
+
+ /**
+ * 价钱
+ */
+ @Excel(name = "价钱")
+ private BigDecimal price;
+
+ /**
+ * 描述
+ */
+ private String description;
+
+ /**
+ * 库存(限量库存)
+ */
+ @Excel(name = "库存(限量库存)")
+ private Integer sku;
+
+ /**
+ * 封面图片
+ */
+ @Excel(name = "封面图片")
+ private String coverImage;
+
+ /**
+ * 是否发布
+ */
+ @Excel(name = "是否发布")
+ private Integer publishFlag;
+
+ /**
+ * 发布时间
+ */
+ @Excel(name = "发布时间", width = 30, dateFormat = "yyyy-MM-dd")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date publishTime;
+
+ /**
+ * 创建者
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private Date createTime;
+
+ /**
+ * 更新者
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private String updateBy;
+
+ /**
+ * 更新时间
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Date updateTime;
+
+ @TableField(exist = false)
+ private Map params = new HashMap<>();
+
+
+ public ProItemVo toVo(List pictures, List categoryIds) {
+ ProItemVo vo = new ProItemVo();
+ BeanUtil.copyProperties(this, vo);
+ vo.setProItemPictures(pictures);
+ vo.setProItemCategoryIds(categoryIds);
+ return vo;
+ }
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItemCategory.java b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItemCategory.java
new file mode 100644
index 000000000..9b9e6fe92
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItemCategory.java
@@ -0,0 +1,73 @@
+package com.ruoyi.product.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import org.springframework.data.annotation.Id;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * proItemCategory对象 pro_item_category
+ *
+ * @author ruoyi
+ * @date 2021-03-24
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("pro_item_category")
+public class ProItemCategory implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+
+ /**
+ * 主键
+ */
+ @TableId(value = "id", type = IdType.INPUT)
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long id;
+
+ /**
+ * 商品id
+ */
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long itemId;
+
+ /**
+ * 分类id
+ */
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long categoryId;
+
+ /**
+ * 创建人
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private Date createTime;
+
+ /**
+ * 更新人
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private String updateBy;
+
+ /**
+ * 更新时间
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Date updateTime;
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItemPicture.java b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItemPicture.java
new file mode 100644
index 000000000..2d4317579
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItemPicture.java
@@ -0,0 +1,66 @@
+package com.ruoyi.product.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.ruoyi.common.annotation.Excel;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import org.springframework.data.annotation.Id;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * proItemPicture对象 pro_item_picture
+ *
+ * @author ruoyi
+ * @date 2021-03-20
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("pro_item_picture")
+public class ProItemPicture implements Serializable {
+
+ private static final long serialVersionUID=1L;
+
+
+ /** 主键id */
+ @TableId(value = "id", type = IdType.INPUT)
+ private Long id;
+
+ /** 商品id */
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long itemId;
+
+ /** 图片地址 */
+ private String picUrl;
+
+ /** 类型,1是商品banner图, 3是评论图片 */
+ private Integer picType;
+
+ /** paixu */
+ private Integer picSort;
+
+ /** $column.columnComment */
+ private Date createTime;
+
+ /** 创建人id */
+ private String createBy;
+
+ /** $column.columnComment */
+ private Date updateTime;
+
+ /** 更新人id */
+ private String updateBy;
+
+ @TableField(exist = false)
+ private Map params = new HashMap<>();
+}
\ No newline at end of file
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItemRelation.java b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItemRelation.java
new file mode 100644
index 000000000..ca0920b0b
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItemRelation.java
@@ -0,0 +1,71 @@
+package com.ruoyi.product.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.math.BigDecimal;
+import com.ruoyi.common.annotation.Excel;
+
+/**
+ * 商品关系(预约记录、优惠券)对象 pro_item_relation
+ *
+ * @author ruoyi
+ * @date 2021-04-09
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+@TableName("pro_item_relation")
+public class ProItemRelation implements Serializable {
+
+private static final long serialVersionUID=1L;
+
+
+ /** 主键id */
+ @TableId(value = "id", type = IdType.INPUT)
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long id;
+
+ /** 业务id,可以是预约记录id,也可以是优惠券id */
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long businessId;
+
+ /** 1表示优惠券类型关联关系,3表示预约类型关联关系 */
+ private String type;
+
+ /** 商品id */
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long proItemId;
+
+ /** 创建时间 */
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ /** 创建人 */
+ @TableField(fill = FieldFill.INSERT)
+ private String createBy;
+
+ /** 更新时间 */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ /** 更新人 */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private String updateBy;
+
+ public String getStringForProItemId() {
+ return this.proItemId.toString();
+ }
+
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItemSpecification.java b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItemSpecification.java
new file mode 100644
index 000000000..34f381b13
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/domain/ProItemSpecification.java
@@ -0,0 +1,106 @@
+package com.ruoyi.product.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 商品规格对象 pro_item_specification
+ *
+ * @author ruoyi
+ * @date 2021-04-06
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("pro_item_specification")
+public class ProItemSpecification implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+
+ /**
+ * 主键id
+ */
+ @TableId(value = "id", type = IdType.INPUT)
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long id;
+
+ /**
+ * 商品id
+ */
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long itemId;
+
+ /**
+ * 规格名字
+ */
+ private String specificationTitle;
+
+ /**
+ * 图片url地址
+ */
+ private String urlPath;
+
+ /**
+ * 规格库存
+ */
+ private Integer specificationSku;
+
+ /**
+ * 价格
+ */
+ private BigDecimal price;
+
+ /**
+ * 别名
+ */
+ private String aliasName;
+
+ /**
+ * 描述
+ */
+ private String description;
+
+ /**
+ * 是否上架,0未上架,1上架,默认是0
+ */
+ private String publishFlag;
+
+ /**
+ * 上架时间
+ */
+ private LocalDateTime publishTime;
+
+ /**
+ * 创建时间
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ /**
+ * 创建人id
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private String createBy;
+
+ /**
+ * 更新时间
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ /**
+ * 更新人id
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private String updateBy;
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/dto/ProItemPictureDTO.java b/ruoyi-product/src/main/java/com/ruoyi/product/dto/ProItemPictureDTO.java
new file mode 100644
index 000000000..8e170d34b
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/dto/ProItemPictureDTO.java
@@ -0,0 +1,16 @@
+package com.ruoyi.product.dto;
+
+import lombok.*;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class ProItemPictureDTO {
+
+ private String key;
+ private String value;
+ // 返回出参的时候将值设置成url
+ private String url;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/enums/PictureTypeEnum.java b/ruoyi-product/src/main/java/com/ruoyi/product/enums/PictureTypeEnum.java
new file mode 100644
index 000000000..da3b9d3f5
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/enums/PictureTypeEnum.java
@@ -0,0 +1,17 @@
+package com.ruoyi.product.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum PictureTypeEnum {
+
+ SWIPER(1, "轮播图"),
+ COMMENT(3, "评论");
+ private Integer value;
+
+ private String description;
+
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/enums/PublishFlagEnum.java b/ruoyi-product/src/main/java/com/ruoyi/product/enums/PublishFlagEnum.java
new file mode 100644
index 000000000..687c0882a
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/enums/PublishFlagEnum.java
@@ -0,0 +1,16 @@
+package com.ruoyi.product.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum PublishFlagEnum {
+
+ YES("1", "已发布"),
+ NO("0", "未发布");
+
+ private String value;
+
+ private String description;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProBannerMapper.java b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProBannerMapper.java
new file mode 100644
index 000000000..07395fd84
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProBannerMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.product.mapper;
+
+import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache;
+import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
+import com.ruoyi.product.domain.ProBanner;
+import org.apache.ibatis.annotations.CacheNamespace;
+
+/**
+ * banner管理Mapper接口
+ *
+ * @author ruoyi
+ * @date 2021-06-30
+ */
+// 如使需切换数据源 请勿使用缓存 会造成数据不一致现象
+@CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
+public interface ProBannerMapper extends BaseMapperPlus {
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProCategoryMapper.java b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProCategoryMapper.java
new file mode 100644
index 000000000..c05f634d2
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProCategoryMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.product.mapper;
+
+import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache;
+import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
+import com.ruoyi.product.domain.ProCategory;
+import org.apache.ibatis.annotations.CacheNamespace;
+
+/**
+ * 商品服务类别Mapper接口
+ *
+ * @author ruoyi
+ * @date 2021-07-01
+ */
+// 如使需切换数据源 请勿使用缓存 会造成数据不一致现象
+@CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
+public interface ProCategoryMapper extends BaseMapperPlus {
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemCategoryMapper.java b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemCategoryMapper.java
new file mode 100644
index 000000000..e69803bbf
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemCategoryMapper.java
@@ -0,0 +1,14 @@
+package com.ruoyi.product.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.product.domain.ProItemCategory;
+
+/**
+ * proItemCategoryMapper接口
+ *
+ * @author ruoyi
+ * @date 2021-03-24
+ */
+public interface ProItemCategoryMapper extends BaseMapper {
+
+}
\ No newline at end of file
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemMapper.java b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemMapper.java
new file mode 100644
index 000000000..f124b618f
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.product.mapper;
+
+import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache;
+import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
+import com.ruoyi.product.domain.ProItem;
+import org.apache.ibatis.annotations.CacheNamespace;
+
+/**
+ * 商品详情Mapper接口
+ *
+ * @author ruoyi
+ * @date 2021-07-01
+ */
+// 如使需切换数据源 请勿使用缓存 会造成数据不一致现象
+@CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
+public interface ProItemMapper extends BaseMapperPlus {
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemPictureMapper.java b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemPictureMapper.java
new file mode 100644
index 000000000..89c876410
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemPictureMapper.java
@@ -0,0 +1,14 @@
+package com.ruoyi.product.mapper;
+
+import com.ruoyi.product.domain.ProItemPicture;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * proItemPictureMapper接口
+ *
+ * @author ruoyi
+ * @date 2021-03-20
+ */
+public interface ProItemPictureMapper extends BaseMapper {
+
+}
\ No newline at end of file
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemRelationMapper.java b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemRelationMapper.java
new file mode 100644
index 000000000..974b1c51f
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemRelationMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.product.mapper;
+
+import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache;
+import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
+import com.ruoyi.product.domain.ProItemRelation;
+import org.apache.ibatis.annotations.CacheNamespace;
+
+/**
+ * 商品关系(预约记录、优惠券)Mapper接口
+ *
+ * @author ruoyi
+ * @date 2021-04-09
+ */
+@CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
+public interface ProItemRelationMapper extends BaseMapperPlus {
+
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemSpecificationMapper.java b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemSpecificationMapper.java
new file mode 100644
index 000000000..dc6a2f329
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/mapper/ProItemSpecificationMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.product.mapper;
+
+import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache;
+import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
+import com.ruoyi.product.domain.ProItemSpecification;
+import org.apache.ibatis.annotations.CacheNamespace;
+
+/**
+ * 商品规格Mapper接口
+ *
+ * @author ruoyi
+ * @date 2021-06-30
+ */
+// 如使需切换数据源 请勿使用缓存 会造成数据不一致现象
+@CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
+public interface ProItemSpecificationMapper extends BaseMapperPlus {
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/IProBannerService.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProBannerService.java
new file mode 100644
index 000000000..6286a183a
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProBannerService.java
@@ -0,0 +1,65 @@
+package com.ruoyi.product.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.product.bo.ProBannerAddBo;
+import com.ruoyi.product.bo.ProBannerEditBo;
+import com.ruoyi.product.bo.ProBannerQueryBo;
+import com.ruoyi.product.bo.ProItemRelationQueryBo;
+import com.ruoyi.product.domain.ProBanner;
+import com.ruoyi.product.vo.ProBannerVo;
+import com.ruoyi.product.vo.ProItemRelationVo;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * banner管理Service接口
+ *
+ * @author ruoyi
+ * @date 2021-03-14
+ */
+public interface IProBannerService extends IServicePlus {
+ /**
+ * 查询单个
+ *
+ * @return
+ */
+ ProBannerVo queryById(Long id);
+
+ /**
+ * 查询列表
+ */
+ TableDataInfo queryPageList(ProBannerQueryBo bo);
+
+ /**
+ * 查询列表
+ */
+ List queryList(ProBannerQueryBo bo);
+
+ /**
+ * 根据新增业务对象插入banner管理
+ *
+ * @param bo banner管理新增业务对象
+ * @return
+ */
+ Boolean insertByAddBo(ProBannerAddBo bo);
+
+ /**
+ * 根据编辑业务对象修改banner管理
+ *
+ * @param bo banner管理编辑业务对象
+ * @return
+ */
+ Boolean updateByEditBo(ProBannerEditBo bo);
+
+ /**
+ * 校验并删除数据
+ *
+ * @param ids 主键集合
+ * @param isValid 是否校验,true-删除前校验,false-不校验
+ * @return
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/IProCategoryService.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProCategoryService.java
new file mode 100644
index 000000000..c38353012
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProCategoryService.java
@@ -0,0 +1,62 @@
+package com.ruoyi.product.service;
+
+import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.product.bo.ProCategoryAddBo;
+import com.ruoyi.product.bo.ProCategoryEditBo;
+import com.ruoyi.product.bo.ProCategoryQueryBo;
+import com.ruoyi.product.domain.ProCategory;
+import com.ruoyi.product.vo.ProCategoryVo;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 商品服务类别Service接口
+ *
+ * @author ruoyi
+ * @date 2021-07-01
+ */
+public interface IProCategoryService extends IServicePlus {
+ /**
+ * 查询单个
+ *
+ * @return
+ */
+ ProCategoryVo queryById(Long id);
+
+ /**
+ * 查询列表
+ */
+ TableDataInfo queryPageList(ProCategoryQueryBo bo);
+
+ /**
+ * 查询列表
+ */
+ List queryList(ProCategoryQueryBo bo);
+
+ /**
+ * 根据新增业务对象插入商品服务类别
+ *
+ * @param bo 商品服务类别新增业务对象
+ * @return
+ */
+ Boolean insertByAddBo(ProCategoryAddBo bo);
+
+ /**
+ * 根据编辑业务对象修改商品服务类别
+ *
+ * @param bo 商品服务类别编辑业务对象
+ * @return
+ */
+ Boolean updateByEditBo(ProCategoryEditBo bo);
+
+ /**
+ * 校验并删除数据
+ *
+ * @param ids 主键集合
+ * @param isValid 是否校验,true-删除前校验,false-不校验
+ * @return
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemCategoryService.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemCategoryService.java
new file mode 100644
index 000000000..aef256381
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemCategoryService.java
@@ -0,0 +1,14 @@
+package com.ruoyi.product.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.product.domain.ProItemCategory;
+
+/**
+ * proItemCategoryService接口
+ *
+ * @author ruoyi
+ * @date 2021-03-24
+ */
+public interface IProItemCategoryService extends IService {
+
+}
\ No newline at end of file
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemPictureService.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemPictureService.java
new file mode 100644
index 000000000..764320433
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemPictureService.java
@@ -0,0 +1,19 @@
+package com.ruoyi.product.service;
+
+import com.ruoyi.product.domain.ProItemPicture;
+import com.baomidou.mybatisplus.extension.service.IService;
+import java.util.List;
+
+/**
+ * proItemPictureService接口
+ *
+ * @author ruoyi
+ * @date 2021-03-20
+ */
+public interface IProItemPictureService extends IService {
+
+ /**
+ * 查询列表
+ */
+ List queryList(ProItemPicture proItemPicture);
+}
\ No newline at end of file
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemRelationService.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemRelationService.java
new file mode 100644
index 000000000..8bd2c2fb4
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemRelationService.java
@@ -0,0 +1,55 @@
+package com.ruoyi.product.service;
+
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.product.domain.ProItemRelation;
+import com.ruoyi.product.vo.ProItemRelationVo;
+import com.ruoyi.product.bo.ProItemRelationQueryBo;
+import com.ruoyi.product.bo.ProItemRelationAddBo;
+import com.ruoyi.product.bo.ProItemRelationEditBo;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 商品关系(预约记录、优惠券)Service接口
+ *
+ * @author ruoyi
+ * @date 2021-04-09
+ */
+public interface IProItemRelationService extends IService {
+ /**
+ * 查询单个
+ * @return
+ */
+ ProItemRelationVo queryById(Long id);
+
+ TableDataInfo queryPageList(ProItemRelationQueryBo bo);
+
+ /**
+ * 查询列表
+ */
+ List queryList(ProItemRelationQueryBo bo);
+
+ /**
+ * 根据新增业务对象插入商品关系(预约记录、优惠券)
+ * @param bo 商品关系(预约记录、优惠券)新增业务对象
+ * @return
+ */
+ Boolean insertByAddBo(ProItemRelationAddBo bo);
+
+ /**
+ * 根据编辑业务对象修改商品关系(预约记录、优惠券)
+ * @param bo 商品关系(预约记录、优惠券)编辑业务对象
+ * @return
+ */
+ Boolean updateByEditBo(ProItemRelationEditBo bo);
+
+ /**
+ * 校验并删除数据
+ * @param ids 主键集合
+ * @param isValid 是否校验,true-删除前校验,false-不校验
+ * @return
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemService.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemService.java
new file mode 100644
index 000000000..6885ea5ea
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemService.java
@@ -0,0 +1,60 @@
+package com.ruoyi.product.service;
+
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.product.bo.ProItemAddBo;
+import com.ruoyi.product.bo.ProItemEditBo;
+import com.ruoyi.product.bo.ProItemQueryBo;
+import com.ruoyi.product.domain.ProItem;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.product.vo.ProItemVo;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 商品详情Service接口
+ *
+ * @author ruoyi
+ * @date 2021-03-13
+ */
+public interface IProItemService extends IService {
+
+ /**
+ * 查询列表
+ */
+ TableDataInfo queryPageList(ProItemQueryBo bo);
+
+ /**
+ * 查询列表
+ */
+ List queryList(ProItemQueryBo bo);
+
+ /**
+ * 新增商品
+ * @param bo
+ * @return
+ */
+ boolean insertByAddBo(ProItemAddBo bo);
+
+ /**
+ * 根据id更新商品详情
+ * @param bo
+ * @return
+ */
+ boolean updateByEditBo(ProItemEditBo bo);
+
+ /**
+ * 根据id获取详情
+ * @param id
+ * @return
+ */
+ ProItemVo getProItemById(Long id);
+
+ /**
+ * 校验并删除数据
+ * @param ids 主键集合
+ * @param isValid 是否校验,true-删除前校验,false-不校验
+ * @return
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemSpecificationService.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemSpecificationService.java
new file mode 100644
index 000000000..74777394b
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/IProItemSpecificationService.java
@@ -0,0 +1,54 @@
+package com.ruoyi.product.service;
+
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.product.domain.ProItemSpecification;
+import com.ruoyi.product.vo.ProItemSpecificationVo;
+import com.ruoyi.product.bo.ProItemSpecificationQueryBo;
+import com.ruoyi.product.bo.ProItemSpecificationAddBo;
+import com.ruoyi.product.bo.ProItemSpecificationEditBo;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 商品规格Service接口
+ *
+ * @author ruoyi
+ * @date 2021-04-06
+ */
+public interface IProItemSpecificationService extends IService {
+ /**
+ * 查询单个
+ * @return
+ */
+ ProItemSpecificationVo queryById(Long id);
+
+ TableDataInfo queryPageList(ProItemSpecificationQueryBo bo);
+ /**
+ * 查询列表
+ */
+ List queryList(ProItemSpecificationQueryBo bo);
+
+ /**
+ * 根据新增业务对象插入商品规格
+ * @param bo 商品规格新增业务对象
+ * @return
+ */
+ Boolean insertByAddBo(ProItemSpecificationAddBo bo);
+
+ /**
+ * 根据编辑业务对象修改商品规格
+ * @param bo 商品规格编辑业务对象
+ * @return
+ */
+ Boolean updateByEditBo(ProItemSpecificationEditBo bo);
+
+ /**
+ * 校验并删除数据
+ * @param ids 主键集合
+ * @param isValid 是否校验,true-删除前校验,false-不校验
+ * @return
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProBannerServiceImpl.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProBannerServiceImpl.java
new file mode 100644
index 000000000..ee442dba6
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProBannerServiceImpl.java
@@ -0,0 +1,95 @@
+package com.ruoyi.product.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
+import com.ruoyi.common.core.page.PagePlus;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.utils.IdUtils;
+import com.ruoyi.common.utils.PageUtils;
+import com.ruoyi.product.bo.ProBannerAddBo;
+import com.ruoyi.product.bo.ProBannerEditBo;
+import com.ruoyi.product.bo.ProBannerQueryBo;
+import com.ruoyi.product.bo.ProItemRelationQueryBo;
+import com.ruoyi.product.domain.ProBanner;
+import com.ruoyi.product.mapper.ProBannerMapper;
+import com.ruoyi.product.service.IProBannerService;
+import com.ruoyi.product.vo.ProBannerVo;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * banner管理Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2021-03-14
+ */
+@Service
+public class ProBannerServiceImpl extends ServicePlusImpl implements IProBannerService {
+
+
+ @Override
+ public ProBannerVo queryById(Long id){
+ return getVoById(id, ProBannerVo.class);
+ }
+
+ @Override
+ public TableDataInfo queryPageList(ProBannerQueryBo bo) {
+ PagePlus result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), ProBannerVo.class);
+ return PageUtils.buildDataInfo(result);
+ }
+
+ @Override
+ public List queryList(ProBannerQueryBo bo) {
+ return listVo(buildQueryWrapper(bo), ProBannerVo.class);
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(ProBannerQueryBo bo) {
+ Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.like(StrUtil.isNotBlank(bo.getTitle()), ProBanner::getTitle, bo.getTitle());
+ lqw.eq(StrUtil.isNotBlank(bo.getUrl()), ProBanner::getUrl, bo.getUrl());
+ lqw.eq(bo.getRedirectFlag() != null, ProBanner::getRedirectFlag, bo.getRedirectFlag());
+ lqw.eq(bo.getBannerType() != null, ProBanner::getBannerType, bo.getBannerType());
+ return lqw;
+ }
+
+ @Override
+ public Boolean insertByAddBo(ProBannerAddBo bo) {
+ ProBanner add = BeanUtil.toBean(bo, ProBanner.class);
+ add.setId(IdUtils.nextId());
+ validEntityBeforeSave(add);
+ return save(add);
+ }
+
+ @Override
+ public Boolean updateByEditBo(ProBannerEditBo bo) {
+ ProBanner update = BeanUtil.toBean(bo, ProBanner.class);
+ validEntityBeforeSave(update);
+ return updateById(update);
+ }
+
+ /**
+ * 保存前的数据校验
+ *
+ * @param entity 实体类数据
+ */
+ private void validEntityBeforeSave(ProBanner entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return removeByIds(ids);
+ }
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProCategoryServiceImpl.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProCategoryServiceImpl.java
new file mode 100644
index 000000000..71b311afe
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProCategoryServiceImpl.java
@@ -0,0 +1,90 @@
+package com.ruoyi.product.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
+import com.ruoyi.common.core.page.PagePlus;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.utils.IdUtils;
+import com.ruoyi.common.utils.PageUtils;
+import com.ruoyi.product.bo.ProCategoryAddBo;
+import com.ruoyi.product.bo.ProCategoryEditBo;
+import com.ruoyi.product.bo.ProCategoryQueryBo;
+import com.ruoyi.product.domain.ProCategory;
+import com.ruoyi.product.mapper.ProCategoryMapper;
+import com.ruoyi.product.service.IProCategoryService;
+import com.ruoyi.product.vo.ProCategoryVo;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 商品服务类别Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2021-03-14
+ */
+@Service
+public class ProCategoryServiceImpl extends ServicePlusImpl implements IProCategoryService {
+
+ @Override
+ public ProCategoryVo queryById(Long id) {
+ return getVoById(id, ProCategoryVo.class);
+ }
+
+ @Override
+ public TableDataInfo queryPageList(ProCategoryQueryBo bo) {
+ PagePlus result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), ProCategoryVo.class);
+ return PageUtils.buildDataInfo(result);
+ }
+
+ @Override
+ public List queryList(ProCategoryQueryBo bo) {
+ return listVo(buildQueryWrapper(bo), ProCategoryVo.class);
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(ProCategoryQueryBo bo) {
+ Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.like(StrUtil.isNotBlank(bo.getCategoryName()), ProCategory::getCategoryName, bo.getCategoryName());
+ lqw.eq(StrUtil.isNotBlank(bo.getIconUrl()), ProCategory::getIconUrl, bo.getIconUrl());
+ return lqw;
+ }
+
+ @Override
+ public Boolean insertByAddBo(ProCategoryAddBo bo) {
+ ProCategory add = BeanUtil.toBean(bo, ProCategory.class);
+ add.setId(IdUtils.nextId());
+ validEntityBeforeSave(add);
+ return save(add);
+ }
+
+ @Override
+ public Boolean updateByEditBo(ProCategoryEditBo bo) {
+ ProCategory update = BeanUtil.toBean(bo, ProCategory.class);
+ validEntityBeforeSave(update);
+ return updateById(update);
+ }
+
+ /**
+ * 保存前的数据校验
+ *
+ * @param entity 实体类数据
+ */
+ private void validEntityBeforeSave(ProCategory entity) {
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if (isValid) {
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return removeByIds(ids);
+ }
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemCategoryServiceImpl.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemCategoryServiceImpl.java
new file mode 100644
index 000000000..f617feebe
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemCategoryServiceImpl.java
@@ -0,0 +1,19 @@
+package com.ruoyi.product.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.product.domain.ProItemCategory;
+import com.ruoyi.product.mapper.ProItemCategoryMapper;
+import com.ruoyi.product.service.IProItemCategoryService;
+import org.springframework.stereotype.Service;
+
+/**
+ * proItemCategoryService业务层处理
+ *
+ * @author ruoyi
+ * @date 2021-03-24
+ */
+@Service
+public class ProItemCategoryServiceImpl extends ServiceImpl implements IProItemCategoryService {
+
+
+}
\ No newline at end of file
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemPictureServiceImpl.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemPictureServiceImpl.java
new file mode 100644
index 000000000..9c183a43a
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemPictureServiceImpl.java
@@ -0,0 +1,27 @@
+package com.ruoyi.product.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.product.domain.ProItemPicture;
+import com.ruoyi.product.mapper.ProItemPictureMapper;
+import com.ruoyi.product.service.IProItemPictureService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * proItemPictureService业务层处理
+ *
+ * @author ruoyi
+ * @date 2021-03-20
+ */
+@Service
+public class ProItemPictureServiceImpl extends ServiceImpl implements IProItemPictureService {
+
+ @Override
+ public List queryList(ProItemPicture proItemPicture) {
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ return this.list(lqw);
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemRelationServiceImpl.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemRelationServiceImpl.java
new file mode 100644
index 000000000..2a46755ad
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemRelationServiceImpl.java
@@ -0,0 +1,90 @@
+package com.ruoyi.product.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
+import com.ruoyi.common.core.page.PagePlus;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.utils.PageUtils;
+import com.ruoyi.product.bo.ProItemRelationAddBo;
+import com.ruoyi.product.bo.ProItemRelationEditBo;
+import com.ruoyi.product.bo.ProItemRelationQueryBo;
+import com.ruoyi.product.domain.ProItemRelation;
+import com.ruoyi.product.mapper.ProItemRelationMapper;
+import com.ruoyi.product.service.IProItemRelationService;
+import com.ruoyi.product.vo.ProItemRelationVo;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 商品关系(预约记录、优惠券)Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2021-04-09
+ */
+@Service
+public class ProItemRelationServiceImpl extends ServicePlusImpl implements IProItemRelationService {
+
+ @Override
+ public ProItemRelationVo queryById(Long id) {
+ ProItemRelation db = this.baseMapper.selectById(id);
+ return BeanUtil.toBean(db, ProItemRelationVo.class);
+ }
+
+ @Override
+ public TableDataInfo queryPageList(ProItemRelationQueryBo bo) {
+ PagePlus result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), ProItemRelationVo.class);
+ return PageUtils.buildDataInfo(result);
+ }
+
+ @Override
+ public List queryList(ProItemRelationQueryBo bo) {
+ return listVo(buildQueryWrapper(bo), ProItemRelationVo.class);
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(ProItemRelationQueryBo bo) {
+ Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.eq(bo.getBusinessId() != null, ProItemRelation::getBusinessId, bo.getBusinessId());
+ lqw.eq(StrUtil.isNotBlank(bo.getType()), ProItemRelation::getType, bo.getType());
+ lqw.eq(bo.getProItemId() != null, ProItemRelation::getProItemId, bo.getProItemId());
+ return lqw;
+ }
+
+
+ @Override
+ public Boolean insertByAddBo(ProItemRelationAddBo bo) {
+ ProItemRelation add = BeanUtil.toBean(bo, ProItemRelation.class);
+ validEntityBeforeSave(add);
+ return this.save(add);
+ }
+
+ @Override
+ public Boolean updateByEditBo(ProItemRelationEditBo bo) {
+ ProItemRelation update = BeanUtil.toBean(bo, ProItemRelation.class);
+ validEntityBeforeSave(update);
+ return this.updateById(update);
+ }
+
+ /**
+ * 保存前的数据校验
+ *
+ * @param entity 实体类数据
+ */
+ private void validEntityBeforeSave(ProItemRelation entity) {
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if (isValid) {
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return this.removeByIds(ids);
+ }
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemServiceImpl.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemServiceImpl.java
new file mode 100644
index 000000000..1a5367845
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemServiceImpl.java
@@ -0,0 +1,160 @@
+package com.ruoyi.product.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
+import com.ruoyi.common.core.page.PagePlus;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.exception.BaseException;
+import com.ruoyi.common.utils.IdUtils;
+import com.ruoyi.common.utils.PageUtils;
+import com.ruoyi.product.bo.ProItemAddBo;
+import com.ruoyi.product.bo.ProItemEditBo;
+import com.ruoyi.product.bo.ProItemQueryBo;
+import com.ruoyi.product.domain.ProItem;
+import com.ruoyi.product.domain.ProItemCategory;
+import com.ruoyi.product.domain.ProItemPicture;
+import com.ruoyi.product.dto.ProItemPictureDTO;
+import com.ruoyi.product.enums.PictureTypeEnum;
+import com.ruoyi.product.enums.PublishFlagEnum;
+import com.ruoyi.product.mapper.ProItemMapper;
+import com.ruoyi.product.service.IProItemCategoryService;
+import com.ruoyi.product.service.IProItemPictureService;
+import com.ruoyi.product.service.IProItemService;
+import com.ruoyi.product.vo.ProItemVo;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 商品详情Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2021-03-13
+ */
+@Service
+@RequiredArgsConstructor
+public class ProItemServiceImpl extends ServicePlusImpl implements IProItemService {
+
+
+ private final ProItemMapper proItemMapper;
+ private final IProItemPictureService proItemPictureService;
+ private final IProItemCategoryService proItemCategoryService;
+
+ public boolean insertByAddBo(ProItemAddBo bo) {
+ if (Objects.equals(bo.getPublishFlag(), PublishFlagEnum.YES.getValue())) {
+ bo.setPublishTime(new Date());
+ }
+ ProItem proItem = new ProItem();
+ BeanUtil.copyProperties(bo, proItem);
+ proItem.setId(IdUtils.nextId());
+ proItemMapper.insert(proItem);
+ if (CollUtil.isNotEmpty(bo.getProItemPictures())) {
+ List pictures = getProItemPictures(bo.getProItemPictures(), proItem.getId());
+ proItemPictureService.saveBatch(pictures);
+ }
+ if (CollUtil.isNotEmpty(bo.getProItemCategoryIds())) {
+ List proItemCategories = getProItemCategories(bo.getProItemCategoryIds(), proItem.getId());
+ proItemCategoryService.saveBatch(proItemCategories);
+ }
+ return Boolean.TRUE;
+ }
+
+ private List getProItemCategories(List categoryIds, Long id) {
+ return categoryIds.stream().map(item -> {
+ ProItemCategory category = new ProItemCategory();
+ category.setId(IdUtils.nextId());
+ category.setCategoryId(Long.parseLong(item));
+ category.setItemId(id);
+ return category;
+ }).collect(Collectors.toList());
+ }
+
+ private List getProItemPictures(List pictureDTOS, Long id) {
+ List res = new ArrayList<>();
+ for (ProItemPictureDTO proItemPicture : pictureDTOS) {
+ ProItemPicture itemPicture = new ProItemPicture();
+ itemPicture.setId(IdUtils.nextId());
+ itemPicture.setItemId(id);
+ itemPicture.setPicUrl(proItemPicture.getValue());
+ itemPicture.setPicType(PictureTypeEnum.SWIPER.getValue());
+ itemPicture.setPicSort(pictureDTOS.indexOf(proItemPicture));
+ res.add(itemPicture);
+ }
+ return res;
+ }
+
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public boolean updateByEditBo(ProItemEditBo bo) {
+ ProItem exist = baseMapper.selectById(bo.getId());
+ Optional.ofNullable(exist).orElseThrow(() -> new BaseException("商品信息不存在!"));
+ // 开始更新图片信息
+ proItemPictureService.remove(Wrappers.lambdaUpdate().eq(ProItemPicture::getItemId, exist.getId()));
+ if (CollUtil.isNotEmpty(bo.getProItemPictures())) {
+ List pictures = getProItemPictures(bo.getProItemPictures(), bo.getId());
+ proItemPictureService.saveBatch(pictures);
+ }
+ proItemCategoryService.remove(Wrappers.lambdaUpdate().eq(ProItemCategory::getItemId, exist.getId()));
+ if (CollUtil.isNotEmpty(bo.getProItemCategoryIds())) {
+ List proItemCategories = getProItemCategories(bo.getProItemCategoryIds(), bo.getId());
+ proItemCategoryService.saveBatch(proItemCategories);
+ }
+ // 当库中未发布,参数中带着已发布,此时需要更新发布时间
+ if ((Objects.equals(PublishFlagEnum.NO.getValue(), exist.getPublishFlag()) || Objects.isNull(exist.getPublishFlag()))
+ && Objects.equals(PublishFlagEnum.YES.getValue(), bo.getPublishFlag())) {
+ bo.setPublishTime(new Date());
+ }
+ baseMapper.updateById(bo);
+ return Boolean.TRUE;
+ }
+
+ @Override
+ public ProItemVo getProItemById(Long id) {
+ ProItem proItem = baseMapper.selectById(id);
+ List pictures = proItemPictureService.list(
+ Wrappers.lambdaQuery().eq(ProItemPicture::getItemId, id));
+ List categories = proItemCategoryService.list(
+ Wrappers.lambdaQuery().eq(ProItemCategory::getItemId, id));
+ List pic = pictures.stream()
+ .map(item -> ProItemPictureDTO.builder().url(item.getPicUrl()).value(item.getPicUrl()).build())
+ .collect(Collectors.toList());
+ List categoryIds = categories.stream().map(item -> item.getCategoryId().toString()).collect(Collectors.toList());
+ return proItem.toVo(pic, categoryIds);
+ }
+
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return removeByIds(ids);
+ }
+
+ @Override
+ public TableDataInfo queryPageList(ProItemQueryBo proItemQueryBo) {
+ PagePlus result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(proItemQueryBo), ProItemVo.class);
+ return PageUtils.buildDataInfo(result);
+ }
+
+ @Override
+ public List queryList(ProItemQueryBo bo) {
+ return listVo(buildQueryWrapper(bo), ProItemVo.class);
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(ProItemQueryBo bo) {
+// Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.like(StrUtil.isNotBlank(bo.getProName()), ProItem::getProName, bo.getProName());
+ lqw.eq(bo.getSku() != null, ProItem::getSku, bo.getSku());
+ lqw.eq(bo.getPublishFlag() != null, ProItem::getPublishFlag, bo.getPublishFlag());
+// lqw.eq(bo.getPublishTime() != null, ProItem::getPublishTime, bo.getPublishTime());
+ return lqw;
+ }
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemSpecificationServiceImpl.java b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemSpecificationServiceImpl.java
new file mode 100644
index 000000000..a74df0612
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/service/impl/ProItemSpecificationServiceImpl.java
@@ -0,0 +1,98 @@
+package com.ruoyi.product.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
+import com.ruoyi.common.core.page.PagePlus;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.exception.BaseException;
+import com.ruoyi.common.utils.IdUtils;
+import com.ruoyi.common.utils.PageUtils;
+import com.ruoyi.product.bo.ProItemSpecificationAddBo;
+import com.ruoyi.product.bo.ProItemSpecificationEditBo;
+import com.ruoyi.product.bo.ProItemSpecificationQueryBo;
+import com.ruoyi.product.domain.ProItemSpecification;
+import com.ruoyi.product.enums.PublishFlagEnum;
+import com.ruoyi.product.mapper.ProItemSpecificationMapper;
+import com.ruoyi.product.service.IProItemSpecificationService;
+import com.ruoyi.product.vo.ProItemSpecificationVo;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.*;
+
+/**
+ * 商品规格Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2021-04-06
+ */
+@Service
+public class ProItemSpecificationServiceImpl extends ServicePlusImpl implements IProItemSpecificationService {
+
+ @Override
+ public ProItemSpecificationVo queryById(Long id) {
+ return getVoById(id, ProItemSpecificationVo.class);
+ }
+
+ @Override
+ public TableDataInfo queryPageList(ProItemSpecificationQueryBo bo) {
+ PagePlus result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), ProItemSpecificationVo.class);
+ return PageUtils.buildDataInfo(result);
+ }
+
+ @Override
+ public List queryList(ProItemSpecificationQueryBo bo) {
+ return listVo(buildQueryWrapper(bo), ProItemSpecificationVo.class);
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(ProItemSpecificationQueryBo bo) {
+ Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.eq(bo.getItemId() != null, ProItemSpecification::getItemId, bo.getItemId());
+ return lqw;
+ }
+
+ @Override
+ public Boolean insertByAddBo(ProItemSpecificationAddBo bo) {
+ ProItemSpecification add = BeanUtil.toBean(bo, ProItemSpecification.class);
+ validEntityBeforeSave(add, Boolean.TRUE);
+ add.setId(IdUtils.nextId());
+ return this.save(add);
+ }
+
+ @Override
+ public Boolean updateByEditBo(ProItemSpecificationEditBo bo) {
+ ProItemSpecification update = BeanUtil.toBean(bo, ProItemSpecification.class);
+ validEntityBeforeSave(update, Boolean.FALSE);
+ return this.updateById(update);
+ }
+
+ /**
+ * 保存前的数据校验
+ *
+ * @param entity 实体类数据
+ */
+ private void validEntityBeforeSave(ProItemSpecification entity, boolean beAdd) {
+ if (beAdd && Objects.equals(PublishFlagEnum.YES.getValue(), entity.getPublishFlag())) {
+ entity.setPublishTime(LocalDateTime.now());
+ }
+ if (!beAdd) {
+ ProItemSpecification exist = baseMapper.selectById(entity.getId());
+ Optional.ofNullable(exist).orElseThrow(() -> new BaseException("该规格不存在,请刷新重试!"));
+ if (Objects.equals(PublishFlagEnum.YES.getValue(), entity.getPublishFlag())
+ && (Objects.isNull(exist.getPublishFlag()) || Objects.equals(PublishFlagEnum.NO.getValue(), exist.getPublishFlag()))) {
+ entity.setPublishTime(LocalDateTime.now());
+ }
+ }
+ }
+
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if (isValid) {
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return this.removeByIds(ids);
+ }
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProBannerVo.java b/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProBannerVo.java
new file mode 100644
index 000000000..4c7686498
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProBannerVo.java
@@ -0,0 +1,72 @@
+package com.ruoyi.product.vo;
+
+/**
+ * @BelongsProject: RuoYi-Vue-Plus
+ * @BelongsPackage: com.ruoyi.product.vo
+ * @Author: yefei
+ * @CreateTime: 2021-06-30 16:37
+ * @Description:
+ */
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.ruoyi.common.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * banner管理视图对象 pro_banner
+ *
+ * @author ruoyi
+ * @date 2021-06-30
+ */
+@Data
+@ApiModel("banner管理视图对象")
+public class ProBannerVo {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @JsonSerialize(using = ToStringSerializer.class)
+ @ApiModelProperty("主键id")
+ private Long id;
+
+ /**
+ * banner标题
+ */
+ @Excel(name = "banner标题")
+ @ApiModelProperty("banner标题")
+ private String title;
+
+ /**
+ * url跳转(也可能是path)
+ */
+ @Excel(name = "url跳转(也可能是path)")
+ @ApiModelProperty("url跳转(也可能是path)")
+ private String url;
+
+ /**
+ * 图片url
+ */
+ @Excel(name = "图片url")
+ @ApiModelProperty("图片url")
+ private String picUrl;
+
+ /**
+ * 是否跳转
+ */
+ @Excel(name = "是否跳转")
+ @ApiModelProperty("是否跳转")
+ private Integer redirectFlag;
+
+ /**
+ * banner类型,1应用内跳转,3外部跳转
+ */
+ @Excel(name = "banner类型,1应用内跳转,3外部跳转")
+ @ApiModelProperty("banner类型,1应用内跳转,3外部跳转")
+ private Integer bannerType;
+
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProCategoryVo.java b/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProCategoryVo.java
new file mode 100644
index 000000000..86316fd56
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProCategoryVo.java
@@ -0,0 +1,76 @@
+package com.ruoyi.product.vo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.ruoyi.common.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @BelongsProject: RuoYi-Vue-Plus
+ * @BelongsPackage: com.ruoyi.product.vo
+ * @Author: yefei
+ * @CreateTime: 2021-07-01 12:00
+ * @Description:
+ */
+@Data
+@ApiModel("商品服务类别视图对象")
+public class ProCategoryVo {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @ApiModelProperty("主键id")
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long id;
+
+ /**
+ * 类别名字
+ */
+ @Excel(name = "类别名字")
+ @ApiModelProperty("类别名字")
+ private String categoryName;
+
+ /**
+ * icon图片
+ */
+ @Excel(name = "icon图片")
+ @ApiModelProperty("icon图片")
+ private String iconUrl;
+
+ /**
+ * 备注信息
+ */
+ @Excel(name = "备注信息")
+ @ApiModelProperty("备注信息")
+ private String remark;
+ /**
+ * 创建者
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private Date createTime;
+
+ /**
+ * 更新者
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private String updateBy;
+
+ /**
+ * 更新时间
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Date updateTime;
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProItemRelationVo.java b/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProItemRelationVo.java
new file mode 100644
index 000000000..d2b4d1e6e
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProItemRelationVo.java
@@ -0,0 +1,40 @@
+package com.ruoyi.product.vo;
+
+import com.ruoyi.common.annotation.Excel;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 商品关系(预约记录、优惠券)视图对象 mall_package
+ *
+ * @author ruoyi
+ * @date 2021-04-09
+ */
+@Data
+@ApiModel("商品关系(预约记录、优惠券)视图对象")
+public class ProItemRelationVo {
+ private static final long serialVersionUID = 1L;
+
+ /** 主键id */
+ @ApiModelProperty("主键id")
+ private Long id;
+
+ /** 业务id,可以是预约记录id,也可以是优惠券id */
+ @Excel(name = "业务id,可以是预约记录id,也可以是优惠券id")
+ @ApiModelProperty("业务id,可以是预约记录id,也可以是优惠券id")
+ private Long businessId;
+ /** 1表示优惠券类型关联关系,3表示预约类型关联关系 */
+ @Excel(name = "1表示优惠券类型关联关系,3表示预约类型关联关系")
+ @ApiModelProperty("1表示优惠券类型关联关系,3表示预约类型关联关系")
+ private String type;
+ /** 商品id */
+ @Excel(name = "商品id")
+ @ApiModelProperty("商品id")
+ private Long proItemId;
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProItemSpecificationVo.java b/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProItemSpecificationVo.java
new file mode 100644
index 000000000..fa9ed097d
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProItemSpecificationVo.java
@@ -0,0 +1,90 @@
+package com.ruoyi.product.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.ruoyi.common.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+
+/**
+ * 商品规格视图对象 mall_package
+ *
+ * @author ruoyi
+ * @date 2021-04-06
+ */
+@Data
+@ApiModel("商品规格视图对象")
+public class ProItemSpecificationVo {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @ApiModelProperty("主键id")
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long id;
+
+ /**
+ * 商品id
+ */
+ @Excel(name = "商品id")
+ @JsonSerialize(using = ToStringSerializer.class)
+ @ApiModelProperty("商品id")
+ private Long itemId;
+ /**
+ * 规格名字
+ */
+ @Excel(name = "规格名字")
+ @ApiModelProperty("规格名字")
+ private String specificationTitle;
+ /**
+ * 图片url地址
+ */
+ @Excel(name = "图片url地址")
+ @ApiModelProperty("图片url地址")
+ private String urlPath;
+ /**
+ * 规格库存
+ */
+ @Excel(name = "规格库存")
+ @ApiModelProperty("规格库存")
+ private Integer specificationSku;
+ /**
+ * 价格
+ */
+ @Excel(name = "价格")
+ @ApiModelProperty("价格")
+ private BigDecimal price;
+ /**
+ * 别名
+ */
+ @Excel(name = "别名")
+ @ApiModelProperty("别名")
+ private String aliasName;
+ /**
+ * 描述
+ */
+ @Excel(name = "描述")
+ @ApiModelProperty("描述")
+ private String description;
+ /**
+ * 是否上架,0未上架,1上架,默认是0
+ */
+ @Excel(name = "是否上架,0未上架,1上架,默认是0")
+ @ApiModelProperty("是否上架,0未上架,1上架,默认是0")
+ private String publishFlag;
+ /**
+ * 上架时间
+ */
+ @Excel(name = "上架时间", width = 30, dateFormat = "yyyy-MM-dd")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @ApiModelProperty("上架时间")
+ private LocalDateTime publishTime;
+
+}
diff --git a/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProItemVo.java b/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProItemVo.java
new file mode 100644
index 000000000..aff4d19f1
--- /dev/null
+++ b/ruoyi-product/src/main/java/com/ruoyi/product/vo/ProItemVo.java
@@ -0,0 +1,104 @@
+package com.ruoyi.product.vo;
+
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.product.dto.ProItemPictureDTO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 商品详情视图对象 pro_item
+ *
+ * @author ruoyi
+ * @date 2021-07-01
+ */
+@Data
+@ApiModel("商品详情视图对象")
+public class ProItemVo {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @ApiModelProperty("主键id")
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long id;
+
+ /**
+ * 产品名字
+ */
+ @Excel(name = "产品名字")
+ @ApiModelProperty("产品名字")
+ private String proName;
+
+ /**
+ * 价钱
+ */
+ @Excel(name = "价钱")
+ @ApiModelProperty("价钱")
+ private BigDecimal price;
+
+ /**
+ * 描述
+ */
+ @Excel(name = "描述")
+ @ApiModelProperty("描述")
+ private String description;
+
+ /**
+ * 库存(限量库存)
+ */
+ @Excel(name = "库存(限量库存)")
+ @ApiModelProperty("库存(限量库存)")
+ private Integer sku;
+
+ /**
+ * 封面图片
+ */
+ @Excel(name = "封面图片")
+ @ApiModelProperty("封面图片")
+ private String coverImage;
+
+ /**
+ * 是否发布
+ */
+ @Excel(name = "是否发布")
+ @ApiModelProperty("是否发布")
+ private Integer publishFlag;
+
+ /**
+ * 发布时间
+ */
+ @Excel(name = "发布时间", width = 30, dateFormat = "yyyy-MM-dd")
+ @ApiModelProperty("发布时间")
+ private Date publishTime;
+
+ /**
+ * 创建者
+ */
+ @Excel(name = "创建者")
+ @ApiModelProperty("创建者")
+ private String createBy;
+
+ /**
+ * 更新时间
+ */
+ @Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd")
+ @ApiModelProperty("更新时间")
+ private Date updateTime;
+
+ @ApiModelProperty("图片列表")
+ private List proItemPictures;
+
+ @ApiModelProperty("分类id集合")
+ private List proItemCategoryIds;
+
+}
diff --git a/ruoyi-product/src/main/resources/mapper.product/ProBannerMapper.xml b/ruoyi-product/src/main/resources/mapper.product/ProBannerMapper.xml
new file mode 100644
index 000000000..c3c7d860c
--- /dev/null
+++ b/ruoyi-product/src/main/resources/mapper.product/ProBannerMapper.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-product/src/main/resources/mapper.product/ProItemMapper.xml b/ruoyi-product/src/main/resources/mapper.product/ProItemMapper.xml
new file mode 100644
index 000000000..3d4c11ee5
--- /dev/null
+++ b/ruoyi-product/src/main/resources/mapper.product/ProItemMapper.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-product/src/main/resources/mapper.product/ProItemPictureMapper.xml b/ruoyi-product/src/main/resources/mapper.product/ProItemPictureMapper.xml
new file mode 100644
index 000000000..29ba9f907
--- /dev/null
+++ b/ruoyi-product/src/main/resources/mapper.product/ProItemPictureMapper.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-product/src/main/resources/mapper.product/ProItemRelationMapper.xml b/ruoyi-product/src/main/resources/mapper.product/ProItemRelationMapper.xml
new file mode 100644
index 000000000..75b279194
--- /dev/null
+++ b/ruoyi-product/src/main/resources/mapper.product/ProItemRelationMapper.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-product/src/main/resources/mapper.product/ProItemSpecificationMapper.xml b/ruoyi-product/src/main/resources/mapper.product/ProItemSpecificationMapper.xml
new file mode 100644
index 000000000..0a7ba3651
--- /dev/null
+++ b/ruoyi-product/src/main/resources/mapper.product/ProItemSpecificationMapper.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json
index af8db7e87..fe5c44c2a 100644
--- a/ruoyi-ui/package.json
+++ b/ruoyi-ui/package.json
@@ -40,6 +40,7 @@
"axios": "0.21.0",
"clipboard": "2.0.6",
"core-js": "3.8.1",
+ "crypto-js": "^4.0.0",
"echarts": "4.9.0",
"element-ui": "2.15.2",
"file-saver": "2.0.4",
@@ -50,6 +51,7 @@
"jsencrypt": "3.0.0-rc.1",
"nprogress": "0.2.0",
"quill": "1.3.7",
+ "quill-image-super-solution-module": "^2.0.0",
"screenfull": "5.0.2",
"sortablejs": "1.10.2",
"vue": "2.6.12",
@@ -75,6 +77,7 @@
"sass-loader": "10.1.0",
"script-ext-html-webpack-plugin": "2.1.5",
"svg-sprite-loader": "5.1.1",
+ "vue-quill-editor": "^3.0.6",
"vue-template-compiler": "2.6.12"
},
"engines": {
diff --git a/ruoyi-ui/src/api/product/proBanner.js b/ruoyi-ui/src/api/product/proBanner.js
new file mode 100644
index 000000000..44577460d
--- /dev/null
+++ b/ruoyi-ui/src/api/product/proBanner.js
@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询banner管理列表
+export function listBanner(query) {
+ return request({
+ url: '/product/proBanner/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 查询banner管理详细
+export function getBanner(id) {
+ return request({
+ url: '/product/proBanner/' + id,
+ method: 'get'
+ })
+}
+
+// 新增banner管理
+export function addBanner(data) {
+ return request({
+ url: '/product/proBanner',
+ method: 'post',
+ data: data
+ })
+}
+
+// 修改banner管理
+export function updateBanner(data) {
+ return request({
+ url: '/product/proBanner',
+ method: 'put',
+ data: data
+ })
+}
+
+// 删除banner管理
+export function delBanner(id) {
+ return request({
+ url: '/product/proBanner' + id,
+ method: 'delete'
+ })
+}
+
+// 导出banner管理
+export function exportBanner(query) {
+ return request({
+ url: '/product/proBanner/export',
+ method: 'get',
+ params: query
+ })
+}
diff --git a/ruoyi-ui/src/api/product/proCategory.js b/ruoyi-ui/src/api/product/proCategory.js
new file mode 100644
index 000000000..379b2a182
--- /dev/null
+++ b/ruoyi-ui/src/api/product/proCategory.js
@@ -0,0 +1,61 @@
+import request from '@/utils/request'
+
+// 查询商品服务类别列表
+export function listProCategory(query) {
+ return request({
+ url: '/product/proCategory/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 查询商品服务类别详细
+export function getProCategory(id) {
+ return request({
+ url: '/product/proCategory/' + id,
+ method: 'get'
+ })
+}
+
+// 新增商品服务类别
+export function addProCategory(data) {
+ return request({
+ url: '/product/proCategory',
+ method: 'post',
+ data: data
+ })
+}
+
+// 修改商品服务类别
+export function updateProCategory(data) {
+ return request({
+ url: '/product/proCategory',
+ method: 'put',
+ data: data
+ })
+}
+
+// 删除商品服务类别
+export function delProCategory(id) {
+ return request({
+ url: '/product/proCategory/' + id,
+ method: 'delete'
+ })
+}
+
+// 导出商品服务类别
+export function exportProCategory(query) {
+ return request({
+ url: '/product/proCategory/export',
+ method: 'get',
+ params: query
+ })
+}
+
+export function listCategoriesWithoutPage(query) {
+ return request({
+ url: '/product/proCategory/listCategoriesWithoutPage',
+ method: 'get',
+ params: query
+ })
+}
diff --git a/ruoyi-ui/src/api/product/proItem.js b/ruoyi-ui/src/api/product/proItem.js
new file mode 100644
index 000000000..e8883476f
--- /dev/null
+++ b/ruoyi-ui/src/api/product/proItem.js
@@ -0,0 +1,62 @@
+import request from '@/utils/request'
+
+// 查询商品详情列表
+export function listProItem(query) {
+ return request({
+ url: '/product/proItem/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 查询商品详情详细
+export function getProItem(id) {
+ return request({
+ url: '/product/proItem/' + id,
+ method: 'get'
+ })
+}
+
+// 新增商品详情
+export function addProItem(data) {
+ return request({
+ url: '/product/proItem',
+ method: 'post',
+ data: data
+ })
+}
+
+// 修改商品详情
+export function updateProItem(data) {
+ return request({
+ url: '/product/proItem',
+ method: 'put',
+ data: data
+ })
+}
+
+// 删除商品详情
+export function delProItem(id) {
+ return request({
+ url: '/product/proItem/' + id,
+ method: 'delete'
+ })
+}
+
+// 导出商品详情
+export function exportProItem(query) {
+ return request({
+ url: '/product/proItem/export',
+ method: 'get',
+ params: query
+ })
+}
+
+// 上传图片通用方法
+export function uploadFile(data) {
+ return request({
+ url: '/common/upload',
+ method: 'post',
+ data: data
+ })
+}
diff --git a/ruoyi-ui/src/api/product/proItemSpecification.js b/ruoyi-ui/src/api/product/proItemSpecification.js
new file mode 100644
index 000000000..88bb07fc8
--- /dev/null
+++ b/ruoyi-ui/src/api/product/proItemSpecification.js
@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询商品规格列表
+export function listProItemSpecification(query) {
+ return request({
+ url: '/product/proItemSpecification/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 查询商品规格详细
+export function getProItemSpecification(id) {
+ return request({
+ url: '/product/proItemSpecification/' + id,
+ method: 'get'
+ })
+}
+
+// 新增商品规格
+export function addProItemSpecification(data) {
+ return request({
+ url: '/product/proItemSpecification',
+ method: 'post',
+ data: data
+ })
+}
+
+// 修改商品规格
+export function updateProItemSpecification(data) {
+ return request({
+ url: '/product/proItemSpecification',
+ method: 'put',
+ data: data
+ })
+}
+
+// 删除商品规格
+export function delProItemSpecification(id) {
+ return request({
+ url: '/product/proItemSpecification/' + id,
+ method: 'delete'
+ })
+}
+
+// 导出商品规格
+export function exportProItemSpecification(query) {
+ return request({
+ url: '/product/proItemSpecification/export',
+ method: 'get',
+ params: query
+ })
+}
\ No newline at end of file
diff --git a/ruoyi-ui/src/assets/images/default.jpg b/ruoyi-ui/src/assets/images/default.jpg
new file mode 100644
index 000000000..aa0237bb9
Binary files /dev/null and b/ruoyi-ui/src/assets/images/default.jpg differ
diff --git a/ruoyi-ui/src/components/Editor/EditorDC.vue b/ruoyi-ui/src/components/Editor/EditorDC.vue
new file mode 100644
index 000000000..bd3464796
--- /dev/null
+++ b/ruoyi-ui/src/components/Editor/EditorDC.vue
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-ui/src/components/EditorDc/index.js b/ruoyi-ui/src/components/EditorDc/index.js
new file mode 100644
index 000000000..9a3a57c76
--- /dev/null
+++ b/ruoyi-ui/src/components/EditorDc/index.js
@@ -0,0 +1,321 @@
+/**
+ *@description 观察者模式 全局监听富文本编辑器
+ */
+export const QuillWatch = {
+ watcher: {}, // 登记编辑器信息
+ active: null, // 当前触发的编辑器
+ on: function(imageExtendId, ImageExtend) {
+ // 登记注册使用了ImageEXtend的编辑器
+ if (!this.watcher[imageExtendId]) {
+ this.watcher[imageExtendId] = ImageExtend;
+ }
+ },
+ emit: function(activeId, type = 1) {
+ // 事件发射触发
+ this.active = this.watcher[activeId];
+ if (type === 1) {
+ imgHandler();
+ }
+ },
+};
+
+/**
+ * @description 图片功能拓展: 增加上传 拖动 复制
+ */
+export class ImageExtend {
+ /**
+ * @param quill {Quill}富文本实例
+ * @param config {Object} options
+ * config keys: action, headers, editForm start end error size response
+ */
+ constructor(quill, config = {}) {
+ this.id = Math.random();
+ this.quill = quill;
+ this.quill.id = this.id;
+ this.config = config;
+ this.file = ""; // 要上传的图片
+ this.imgURL = ""; // 图片地址
+ quill.root.addEventListener("paste", this.pasteHandle.bind(this), false);
+ quill.root.addEventListener("drop", this.dropHandle.bind(this), false);
+ quill.root.addEventListener(
+ "dropover",
+ function(e) {
+ e.preventDefault();
+ },
+ false
+ );
+ this.cursorIndex = 0;
+ QuillWatch.on(this.id, this);
+ }
+
+ /**
+ * @description 检验图片大小是否超出限制
+ */
+ checkPicSize() {
+ let self = this;
+ if (self.config.size && self.file.size >= self.config.size * 1024 * 1024) {
+ if (self.config.sizeError) {
+ self.config.sizeError();
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @description 粘贴
+ * @param e
+ */
+ pasteHandle(e) {
+ e.preventDefault();
+ QuillWatch.emit(this.quill.id, 0);
+ let clipboardData = e.clipboardData;
+ let i = 0;
+ let items, item, types;
+
+ if (clipboardData) {
+ items = clipboardData.items;
+
+ if (!items) {
+ return;
+ }
+ item = items[0];
+ types = clipboardData.types || [];
+
+ for (; i < types.length; i++) {
+ if (types[i] === "Files") {
+ item = items[i];
+ break;
+ }
+ }
+ if (item && item.kind === "file" && item.type.match(/^image\//i)) {
+ this.file = item.getAsFile();
+ let self = this;
+ // 如果图片限制大小
+ if (!this.checkPicSize()) {
+ return;
+ }
+ if (this.config.action) {
+ this.uploadImg();
+ } else {
+ this.toBase64();
+ }
+ }
+ if (item && item.kind === "string" && ["text/plain", "text/html"].indexOf(item.types)) {
+ //将粘贴的文本内容插入到编辑器中
+ item.getAsString(function(s) {
+ const self = QuillWatch.active;
+ let length = self.quill.getSelection(true).index;
+ self.cursorIndex = length;
+ self.quill.insertText(QuillWatch.active.cursorIndex, s.replace(/\s{2,}/g, "\n"));
+ self.quill.update();
+ setTimeout(() => self.quill.setSelection(self.cursorIndex + s.length, 0), 0);
+ });
+ }
+ }
+ }
+
+ /**
+ * 拖拽
+ * @param e
+ */
+ dropHandle(e) {
+ QuillWatch.emit(this.quill.id, 0);
+ const self = this;
+ e.preventDefault();
+ // 如果图片限制大小
+ if (!self.checkPicSize()) {
+ return;
+ }
+ self.file = e.dataTransfer.files[0]; // 获取到第一个上传的文件对象
+ if (this.config.action) {
+ self.uploadImg();
+ } else {
+ self.toBase64();
+ }
+ }
+
+ /**
+ * @description 将图片转为base4
+ */
+ toBase64() {
+ const self = this;
+ const reader = new FileReader();
+ reader.onload = (e) => {
+ // 返回base64
+ self.imgURL = e.target.result;
+ self.insertImg();
+ };
+ reader.readAsDataURL(self.file);
+ }
+
+ /**
+ * @description 上传图片到服务器
+ */
+ uploadImg() {
+ const self = this;
+ let quillLoading = self.quillLoading;
+ let config = self.config;
+ // 构造表单
+ let formData = new FormData();
+ formData.append(config.name, self.file);
+ // 自定义修改表单
+ if (config.editForm) {
+ config.editForm(formData);
+ }
+ // 创建ajax请求
+ let xhr = new XMLHttpRequest();
+ xhr.open("post", config.action, true);
+ // 如果有设置请求头
+ if (config.headers) {
+ config.headers(xhr);
+ }
+ if (config.change) {
+ config.change(xhr, formData);
+ }
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4) {
+ if (xhr.status === 200) {
+ //success
+ let res = JSON.parse(xhr.responseText);
+ self.imgURL = config.response(res);
+ QuillWatch.active.uploadSuccess();
+ self.insertImg();
+ if (self.config.success) {
+ self.config.success();
+ }
+ } else {
+ //error
+ if (self.config.error) {
+ self.config.error();
+ }
+ QuillWatch.active.uploadError();
+ }
+ }
+ };
+ // 开始上传数据
+ xhr.upload.onloadstart = function(e) {
+ QuillWatch.active.uploading();
+ // let length = (self.quill.getSelection() || {}).index || self.quill.getLength()
+ // self.quill.insertText(length, '[uploading...]', { 'color': 'red'}, true)
+ if (config.start) {
+ config.start();
+ }
+ };
+ // 上传过程
+ xhr.upload.onprogress = function(e) {
+ let complete = (((e.loaded / e.total) * 100) | 0) + "%";
+ QuillWatch.active.progress(complete);
+ };
+ // 当发生网络异常的时候会触发,如果上传数据的过程还未结束
+ xhr.upload.onerror = function(e) {
+ QuillWatch.active.uploadError();
+ if (config.error) {
+ config.error();
+ }
+ };
+ // 上传数据完成(成功或者失败)时会触发
+ xhr.upload.onloadend = function(e) {
+ if (config.end) {
+ config.end();
+ }
+ };
+ xhr.send(formData);
+ }
+
+ /**
+ * @description 往富文本编辑器插入图片
+ */
+ insertImg() {
+ const self = QuillWatch.active;
+ self.quill.insertEmbed(QuillWatch.active.cursorIndex, "image", self.imgURL);
+ self.quill.update();
+ self.quill.setSelection(self.cursorIndex + 1);
+ }
+
+ /**
+ * @description 显示上传的进度
+ */
+ progress(pro) {
+ pro = "[" + "uploading" + pro + "]";
+ QuillWatch.active.quill.root.innerHTML = QuillWatch.active.quill.root.innerHTML.replace(
+ /\[uploading.*?\]/,
+ pro
+ );
+ }
+
+ /**
+ * 开始上传
+ */
+ uploading() {
+ let length = QuillWatch.active.quill.getSelection(true).index;
+ QuillWatch.active.cursorIndex = length;
+ QuillWatch.active.quill.insertText(QuillWatch.active.cursorIndex, "[uploading...]", { color: "red" }, true);
+ }
+
+ /**
+ * 上传失败
+ */
+ uploadError() {
+ QuillWatch.active.quill.root.innerHTML = QuillWatch.active.quill.root.innerHTML.replace(
+ /\[uploading.*?\]/,
+ "[upload error]"
+ );
+ }
+
+ uploadSuccess() {
+ QuillWatch.active.quill.root.innerHTML = QuillWatch.active.quill.root.innerHTML.replace(/\[uploading.*?\]/, "");
+ }
+}
+
+/**
+ * @description 点击图片上传
+ */
+export function imgHandler() {
+ let fileInput = document.querySelector(".quill-image-input");
+ if (fileInput === null) {
+ fileInput = document.createElement("input");
+ fileInput.setAttribute("type", "file");
+ fileInput.classList.add("quill-image-input");
+ fileInput.style.display = "none";
+ // 监听选择文件
+ fileInput.addEventListener("change", function() {
+ let self = QuillWatch.active;
+ self.file = fileInput.files[0];
+ fileInput.value = "";
+ // 可设置上传图片的格式
+ fileInput.setAttribute("accept", self.config.accept);
+ // 如果图片限制大小
+ if (!self.checkPicSize()) {
+ return;
+ }
+ if (self.config.action) {
+ self.uploadImg();
+ } else {
+ self.toBase64();
+ }
+ });
+ document.body.appendChild(fileInput);
+ }
+ fileInput.click();
+}
+
+/**
+ *@description 全部工具栏
+ */
+export const container = [
+ ["bold", "italic", "underline", "strike"],
+ ["blockquote", "code-block"],
+ [{ header: 1 }, { header: 2 }],
+ [{ list: "ordered" }, { list: "bullet" }],
+ [{ script: "sub" }, { script: "super" }],
+ [{ indent: "-1" }, { indent: "+1" }],
+ [{ direction: "rtl" }],
+ [{ size: ["small", false, "large", "huge"] }],
+ [{ header: [1, 2, 3, 4, 5, 6, false] }],
+ [{ color: [] }, { background: [] }],
+ [{ font: [] }],
+ [{ align: [] }],
+ ["clean"],
+ ["link", "image", "video"],
+];
diff --git a/ruoyi-ui/src/components/Verifition/Verify.vue b/ruoyi-ui/src/components/Verifition/Verify.vue
new file mode 100644
index 000000000..8087e9b73
--- /dev/null
+++ b/ruoyi-ui/src/components/Verifition/Verify.vue
@@ -0,0 +1,492 @@
+
+
+
+
+ 请完成安全验证
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-ui/src/components/Verifition/Verify/VerifyPoints.vue b/ruoyi-ui/src/components/Verifition/Verify/VerifyPoints.vue
new file mode 100644
index 000000000..e257f1bc6
--- /dev/null
+++ b/ruoyi-ui/src/components/Verifition/Verify/VerifyPoints.vue
@@ -0,0 +1,256 @@
+
+
+
+
+
+
+
+
![]()
+
+
+ {{index + 1}}
+
+
+
+
+
+ {{text}}
+
+
+
+
\ No newline at end of file
diff --git a/ruoyi-ui/src/components/Verifition/Verify/VerifySlide.vue b/ruoyi-ui/src/components/Verifition/Verify/VerifySlide.vue
new file mode 100644
index 000000000..3d550f6b2
--- /dev/null
+++ b/ruoyi-ui/src/components/Verifition/Verify/VerifySlide.vue
@@ -0,0 +1,359 @@
+
+
+
+
+
![]()
+
+
+
+ {{tipWords}}
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
diff --git a/ruoyi-ui/src/components/Verifition/api/index.js b/ruoyi-ui/src/components/Verifition/api/index.js
new file mode 100644
index 000000000..e30b9762e
--- /dev/null
+++ b/ruoyi-ui/src/components/Verifition/api/index.js
@@ -0,0 +1,27 @@
+/**
+ * 此处可直接引用自己项目封装好的 axios 配合后端联调
+ */
+
+
+import request from "./../utils/axios" //组件内部封装的axios
+// import request from "@/api/axios.js" //调用项目封装的axios
+
+//获取验证图片 以及token
+export function reqGet(data) {
+ return request({
+ url: '/dev-api/captcha/get',
+ method: 'post',
+ data
+ })
+}
+
+//滑动或者点选验证
+export function reqCheck(data) {
+ return request({
+ url: '/dev-api/captcha/check',
+ method: 'post',
+ data
+ })
+}
+
+
diff --git a/ruoyi-ui/src/components/Verifition/utils/ase.js b/ruoyi-ui/src/components/Verifition/utils/ase.js
new file mode 100644
index 000000000..4c1c55945
--- /dev/null
+++ b/ruoyi-ui/src/components/Verifition/utils/ase.js
@@ -0,0 +1,11 @@
+import CryptoJS from 'crypto-js'
+/**
+ * @word 要加密的内容
+ * @keyWord String 服务器随机返回的关键字
+ * */
+export function aesEncrypt(word,keyWord="XwKsGlMcdPMEhR1B"){
+ var key = CryptoJS.enc.Utf8.parse(keyWord);
+ var srcs = CryptoJS.enc.Utf8.parse(word);
+ var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
+ return encrypted.toString();
+}
diff --git a/ruoyi-ui/src/components/Verifition/utils/axios.js b/ruoyi-ui/src/components/Verifition/utils/axios.js
new file mode 100644
index 000000000..610d40323
--- /dev/null
+++ b/ruoyi-ui/src/components/Verifition/utils/axios.js
@@ -0,0 +1,30 @@
+import axios from 'axios';
+
+axios.defaults.baseURL = process.env.BASE_API;
+
+const service = axios.create({
+ timeout: 40000,
+ headers: {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'Content-Type': 'application/json; charset=UTF-8'
+ },
+})
+service.interceptors.request.use(
+ config => {
+ return config
+ },
+ error => {
+ Promise.reject(error)
+ }
+)
+
+// response interceptor
+service.interceptors.response.use(
+ response => {
+ const res = response.data;
+ return res
+ },
+ error => {
+ }
+)
+export default service
diff --git a/ruoyi-ui/src/components/Verifition/utils/util.js b/ruoyi-ui/src/components/Verifition/utils/util.js
new file mode 100644
index 000000000..55f65d426
--- /dev/null
+++ b/ruoyi-ui/src/components/Verifition/utils/util.js
@@ -0,0 +1,36 @@
+export function resetSize(vm) {
+ var img_width, img_height, bar_width, bar_height; //图片的宽度、高度,移动条的宽度、高度
+
+ var parentWidth = vm.$el.parentNode.offsetWidth || window.offsetWidth
+ var parentHeight = vm.$el.parentNode.offsetHeight || window.offsetHeight
+
+ if (vm.imgSize.width.indexOf('%') != -1) {
+ img_width = parseInt(this.imgSize.width) / 100 * parentWidth + 'px'
+ } else {
+ img_width = this.imgSize.width;
+ }
+
+ if (vm.imgSize.height.indexOf('%') != -1) {
+ img_height = parseInt(this.imgSize.height) / 100 * parentHeight + 'px'
+ } else {
+ img_height = this.imgSize.height
+ }
+
+ if (vm.barSize.width.indexOf('%') != -1) {
+ bar_width = parseInt(this.barSize.width) / 100 * parentWidth + 'px'
+ } else {
+ bar_width = this.barSize.width
+ }
+
+ if (vm.barSize.height.indexOf('%') != -1) {
+ bar_height = parseInt(this.barSize.height) / 100 * parentHeight + 'px'
+ } else {
+ bar_height = this.barSize.height
+ }
+
+ return {imgWidth: img_width, imgHeight: img_height, barWidth: bar_width, barHeight: bar_height}
+}
+
+export const _code_chars = [1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
+export const _code_color1 = ['#fffff0', '#f0ffff', '#f0fff0', '#fff0f0']
+export const _code_color2 = ['#FF0033', '#006699', '#993366', '#FF9900', '#66CC66', '#FF33CC']
\ No newline at end of file
diff --git a/ruoyi-ui/src/views/login.vue b/ruoyi-ui/src/views/login.vue
index e8da56b7e..a5d813f9a 100644
--- a/ruoyi-ui/src/views/login.vue
+++ b/ruoyi-ui/src/views/login.vue
@@ -28,19 +28,26 @@
>
-
-
![]()
-
记住密码
+
+
+
+
登 录
登 录 中...
@@ -54,12 +61,15 @@
+
diff --git a/ruoyi-ui/src/views/product/proCategory/index.vue b/ruoyi-ui/src/views/product/proCategory/index.vue
new file mode 100644
index 000000000..c02f3a38c
--- /dev/null
+++ b/ruoyi-ui/src/views/product/proCategory/index.vue
@@ -0,0 +1,291 @@
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+ 新增
+
+
+
+ 修改
+
+
+
+ 删除
+
+
+
+ 导出
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 修改
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-ui/src/views/product/proItem/index.vue b/ruoyi-ui/src/views/product/proItem/index.vue
new file mode 100644
index 000000000..165ce48cc
--- /dev/null
+++ b/ruoyi-ui/src/views/product/proItem/index.vue
@@ -0,0 +1,516 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+ 新增
+
+
+
+ 修改
+
+
+
+ 删除
+
+
+
+ 导出
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.publishFlag === 0 ? '未发布' : '已发布' }}
+
+
+
+ {{ parseTime(scope.row.publishTime, '{y}-{m}-{d} {h}:{i}:{s}') }}
+
+
+
+
+ 修改
+
+ 编辑规格
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 是
+ 否
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-ui/src/views/product/proItemSpecification/index.vue b/ruoyi-ui/src/views/product/proItemSpecification/index.vue
new file mode 100644
index 000000000..16e4b85bc
--- /dev/null
+++ b/ruoyi-ui/src/views/product/proItemSpecification/index.vue
@@ -0,0 +1,342 @@
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+ 新增
+
+
+
+ 修改
+
+
+
+ 删除
+
+
+
+ 导出
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.publishFlag === '0' ? '未上架' : '已上架' }}
+
+
+
+ {{ parseTime(scope.row.publishTime, '{y}-{m}-{d} {h}:{i}:{s}') }}
+
+
+
+
+ 修改
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+