提交 79c36a5a authored 作者: YunaiV's avatar YunaiV

- 前端:完善商品列表

- 后端:将商品模块的 Service 改成有业务异常时,抛出异常,而不是返回 CommonResult - 后端:将搜索模块的 Service 改成有业务异常时,抛出异常,而不是返回 CommonResult
上级 2519cf00
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
* 整体的功能如下图:![功能图](http://static.iocoder.cn/mall%20%E5%8A%9F%E8%83%BD%E5%9B%BE-min.png) * 整体的功能如下图:![功能图](http://static.iocoder.cn/mall%20%E5%8A%9F%E8%83%BD%E5%9B%BE-min.png)
> 功能图,和实际后端模块拆分,并不是绝对对应。 > 功能图,和实际后端模块拆分,并不是绝对对应。
* [功能列表 - H5 商城](https://gitee.com/zhijiantianya/onemall/blob/master/docs/guides/%E5%8A%9F%E8%83%BD%E5%88%97%E8%A1%A8/%E5%8A%9F%E8%83%BD%E5%88%97%E8%A1%A8-H5%20%E5%95%86%E5%9F%8E.md)
* [功能列表 - 管理后台](https://gitee.com/zhijiantianya/onemall/blob/master/docs/guides/%E5%8A%9F%E8%83%BD%E5%88%97%E8%A1%A8/%E5%8A%9F%E8%83%BD%E5%88%97%E8%A1%A8-%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0.md)
* 交流群:[传送门](http://www.iocoder.cn/mall-user-group/?vip&gitee) * 交流群:[传送门](http://www.iocoder.cn/mall-user-group/?vip&gitee)
> 一起交流,Get 知识。 > 一起交流,Get 知识。
......
...@@ -62,6 +62,9 @@ export default { ...@@ -62,6 +62,9 @@ export default {
const response = yield call(productSpuInfo, { const response = yield call(productSpuInfo, {
id: payload, id: payload,
}); });
if (response.code !== 0) {
return;
}
// 响应 // 响应
let skus = []; let skus = [];
let attrTree = []; let attrTree = [];
...@@ -193,6 +196,9 @@ export default { ...@@ -193,6 +196,9 @@ export default {
*add({ payload }, { call, put }) { *add({ payload }, { call, put }) {
const { callback, body } = payload; const { callback, body } = payload;
const response = yield call(productSpuAdd, body); const response = yield call(productSpuAdd, body);
if (response.code !== 0) {
return;
}
if (callback) { if (callback) {
callback(response); callback(response);
} }
...@@ -205,6 +211,9 @@ export default { ...@@ -205,6 +211,9 @@ export default {
*update({ payload }, { call, put }) { *update({ payload }, { call, put }) {
const { callback, body } = payload; const { callback, body } = payload;
const response = yield call(productSpuUpdate, body); const response = yield call(productSpuUpdate, body);
if (response.code !== 0) {
return;
}
if (callback) { if (callback) {
callback(response); callback(response);
} }
......
import { message } from 'antd'; import { message } from 'antd';
import { productSpuPage, productCategoryAdd, productCategoryUpdate, productCategoryUpdateStatus, productCategoryDelete } from '../../services/product'; import { productSpuPage, productSpuUpdateSort } from '../../services/product';
import {routerRedux} from "dva/router"; import {routerRedux} from "dva/router";
import PaginationHelper from '../../../helpers/PaginationHelper';
const SEARCH_PARAMS_DEFAULT = {
name: '',
status: 1,
cid: undefined,
};
export default { export default {
namespace: 'productSpuList', namespace: 'productSpuList',
state: { state: {
// 分页列表相关
list: [], list: [],
listLoading: false,
pagination: PaginationHelper.defaultPaginationConfig,
searchParams: SEARCH_PARAMS_DEFAULT,
// 添加 or 修改表单相关
// modalVisible: false,
// modalType: undefined, // 'add' or 'update' 表单
formVals: {}, // 当前表单值
// modalLoading: false,
sortModalVisible: false, // 修改排序弹窗
sortModalLoading: false, // 修改排序的加载
}, },
effects: { effects: {
...@@ -35,19 +56,76 @@ export default { ...@@ -35,19 +56,76 @@ export default {
}, },
*redirectToUpdate({ payload }, { call, put }) { *redirectToUpdate({ payload }, { call, put }) {
// const { callback, body } = payload; // const { callback, body } = payload;
debugger;
yield put(routerRedux.replace('/product/product-spu-update?id=' + payload)); yield put(routerRedux.replace('/product/product-spu-update?id=' + payload));
}, },
*page({ payload }, { call, put }) { *page({ payload }, { call, put }) {
// const { queryParams } = payload; // const { queryParams } = payload;
// const response = yield call(productSpuPage, payload);
// message.info('查询成功!');
// yield put({
// type: 'treeSuccess',
// payload: {
// list: response.data,
// },
// });
// 显示加载中
yield put({
type: 'changeListLoading',
payload: true,
});
// 请求
const response = yield call(productSpuPage, payload); const response = yield call(productSpuPage, payload);
message.info('查询成功!'); // 响应
yield put({ yield put({
type: 'treeSuccess', type: 'setAll',
payload: { payload: {
list: response.data, list: response.data.list,
pagination: PaginationHelper.formatPagination(response.data, payload),
searchParams: {
name: payload.name,
status: payload.status,
cid: payload.cid,
}
}, },
}); });
// 隐藏加载中
yield put({
type: 'changeListLoading',
payload: false,
});
},
*updateSort({ payload }, { call, put }) {
// 显示加载中
yield put({
type: 'changeSortModalLoading',
payload: true,
});
// 请求
const { callback, body } = payload;
// 响应
const response = yield call(productSpuUpdateSort, body);
if(response.code === 0) {
if (callback) {
callback(response);
}
yield put({
type: 'page',
payload: {
...this.state.pagination,
...this.state.searchParams,
},
});
}
// 隐藏加载中
yield put({
type: 'changeSortModalLoading',
payload: false,
});
}, },
}, },
...@@ -58,5 +136,25 @@ export default { ...@@ -58,5 +136,25 @@ export default {
...payload, ...payload,
}; };
}, },
// 修改加载中的状态
changeSortModalLoading(state, { payload }) {
return {
...state,
sortModalLoading: payload,
};
},
changeListLoading(state, { payload }) {
return {
...state,
listLoading: payload,
};
},
// 设置所有属性
setAll(state, { payload }) {
return {
...state,
...payload,
};
}
}, },
}; };
...@@ -137,7 +137,6 @@ function List ({ dataSource, loading, pagination, searchParams, dispatch, ...@@ -137,7 +137,6 @@ function List ({ dataSource, loading, pagination, searchParams, dispatch,
} }
// 搜索表单 // 搜索表单
// TODO 芋艿,有没办法换成上面那种写法
const SearchForm = Form.create()(props => { const SearchForm = Form.create()(props => {
const { const {
form, form,
......
...@@ -123,6 +123,7 @@ function List({ dataSource, loading, dispatch, ...@@ -123,6 +123,7 @@ function List({ dataSource, loading, dispatch,
columns={columns} columns={columns}
loading={loading} loading={loading}
rowKey="id" rowKey="id"
pagination={false}
dataSource={dataSource} /> dataSource={dataSource} />
) )
} }
......
...@@ -58,6 +58,13 @@ export async function productSpuUpdate(params) { ...@@ -58,6 +58,13 @@ export async function productSpuUpdate(params) {
}); });
} }
export async function productSpuUpdateSort(params) {
return request(`/product-api/admins/spu/update_sort?${stringify(params)}`, {
method: 'POST',
body: {},
});
}
export async function productSpuInfo(params) { export async function productSpuInfo(params) {
return request(`/product-api/admins/spu/info?${stringify(params)}`, { return request(`/product-api/admins/spu/info?${stringify(params)}`, {
method: 'GET', method: 'GET',
......
...@@ -2,8 +2,9 @@ package cn.iocoder.common.framework.config; ...@@ -2,8 +2,9 @@ package cn.iocoder.common.framework.config;
import cn.iocoder.common.framework.constant.SysErrorCodeEnum; import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
import cn.iocoder.common.framework.exception.ServiceException; import cn.iocoder.common.framework.exception.ServiceException;
import cn.iocoder.common.framework.util.ExceptionUtil;
import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.common.framework.vo.CommonResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
...@@ -11,20 +12,32 @@ import org.springframework.web.bind.annotation.ResponseBody; ...@@ -11,20 +12,32 @@ import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException; import javax.validation.ConstraintViolationException;
import java.lang.reflect.UndeclaredThrowableException;
@ControllerAdvice @ControllerAdvice
public class GlobalExceptionHandler { public class GlobalExceptionHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
// 逻辑异常
@ResponseBody @ResponseBody
@ExceptionHandler(value = ServiceException.class) @ExceptionHandler(value = ServiceException.class)
public CommonResult serviceExceptionHandler(HttpServletRequest req, ServiceException ex) { public CommonResult serviceExceptionHandler(HttpServletRequest req, ServiceException ex) {
logger.debug("[serviceExceptionHandler]", ex);
return CommonResult.error(ex.getCode(), ex.getMessage()); return CommonResult.error(ex.getCode(), ex.getMessage());
} }
// Spring MVC 参数不正确
@ResponseBody
@ExceptionHandler(value = MissingServletRequestParameterException.class)
public CommonResult missingServletRequestParameterExceptionHandler(HttpServletRequest req, MissingServletRequestParameterException ex) {
logger.warn("[missingServletRequestParameterExceptionHandler]", ex);
return CommonResult.error(SysErrorCodeEnum.MISSING_REQUEST_PARAM_ERROR.getCode(), SysErrorCodeEnum.MISSING_REQUEST_PARAM_ERROR.getMessage() + ":" + ex.getMessage());
}
@ResponseBody @ResponseBody
@ExceptionHandler(value = ConstraintViolationException.class) @ExceptionHandler(value = ConstraintViolationException.class)
public CommonResult constraintViolationExceptionHandler(HttpServletRequest req, ConstraintViolationException ex) { public CommonResult constraintViolationExceptionHandler(HttpServletRequest req, ConstraintViolationException ex) {
logger.info("[constraintViolationExceptionHandler]", ex);
// TODO 芋艿,后续要想一个更好的方式。 // TODO 芋艿,后续要想一个更好的方式。
// 拼接详细报错 // 拼接详细报错
StringBuilder detailMessage = new StringBuilder("\n\n详细错误如下:"); StringBuilder detailMessage = new StringBuilder("\n\n详细错误如下:");
...@@ -33,34 +46,12 @@ public class GlobalExceptionHandler { ...@@ -33,34 +46,12 @@ public class GlobalExceptionHandler {
+ detailMessage.toString()); + detailMessage.toString());
} }
@ResponseBody
@ExceptionHandler(value = UndeclaredThrowableException.class)
public CommonResult undeclaredThrowableExceptionHandler(HttpServletRequest req, UndeclaredThrowableException e) {
// 尝试获得 ServiceException 异常。如果是,则使用 serviceExceptionHandler 方法处理。
ServiceException serviceException = ExceptionUtil.getServiceException(e);
if (serviceException != null) {
return serviceExceptionHandler(req, serviceException);
}
// 尝试获得 ConstraintViolationException 异常。如果是,
ConstraintViolationException constraintViolationException = ExceptionUtil.getConstraintViolationException(e);
if (constraintViolationException != null) {
return constraintViolationExceptionHandler(req, constraintViolationException);
}
// 获得不到,使用 异常日志 方法处理。
return resultExceptionHandler(req, e);
}
@ResponseBody @ResponseBody
@ExceptionHandler(value = Exception.class) @ExceptionHandler(value = Exception.class)
public CommonResult resultExceptionHandler(HttpServletRequest req, Exception e) { public CommonResult resultExceptionHandler(HttpServletRequest req, Exception e) {
// TODO 翻译不同的异常 logger.error("[resultExceptionHandler]", e);
if (e instanceof MissingServletRequestParameterException) {
return CommonResult.error(SysErrorCodeEnum.MISSING_REQUEST_PARAM_ERROR.getCode(), SysErrorCodeEnum.MISSING_REQUEST_PARAM_ERROR.getMessage() + ":" + e.getMessage());
}
// TODO 异常日志
e.printStackTrace();
// 返回 // 返回
return CommonResult.error(SysErrorCodeEnum.SYS_ERROR.getCode(), SysErrorCodeEnum.SYS_ERROR.getMessage()); return CommonResult.error(SysErrorCodeEnum.SYS_ERROR.getCode(), SysErrorCodeEnum.SYS_ERROR.getMessage());
} }
} }
\ No newline at end of file
package cn.iocoder.common.framework.vo;
public class RestResult {
/**
* 错误码
*/
private Integer code;
/**
* 错误提示
*/
private String message;
/**
* 返回数据
*/
private Object data;
public static RestResult error(Integer code, String message) {
RestResult result = new RestResult();
result.code = code;
result.message = message;
return result;
}
public static RestResult ok(Object data) {
RestResult result = new RestResult();
result.code = 0;
result.data = data;
result.message = "";
return result;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
\ No newline at end of file
如下是 onemall 的功能列表。 如下是 onemall 的功能列表。
* 当功能被完成时,会标记已完成。 * 当功能被完成时,会标记已完成。
* 未完成的功能,欢迎一起来开发。 * 未完成的功能,欢迎一起来开发,特别是【待认领】的任务
- [ ] 首页 - [x] 首页
- 商品相关 - 商品相关
- [ ] 分类列表 - [x] 分类列表
- [ ] 商品搜索 - [x] 商品搜索
- [ ] 商品列表(基于分类) - [x] 商品列表(基于分类)
- [ ] 商品列表(基于促销活动) - [ ] 商品列表(基于促销活动)
- [ ] 商品详情 - [x] 商品详情
- [ ] 商品收藏 - [ ] 商品收藏【待认领】
- 订单相关 - 订单相关
- [ ] 下单(直接购买) - [x] 下单(直接购买)
- [ ] 下单(购物车购买) - [x] 下单(购物车购买)
- [ ] 下单(拼团) - [ ] 下单(拼团)
- [ ] 订单列表 - [x] 订单列表
- [ ] 订单详情 - [x] 订单详情
- [ ] 支付 - [x] 支付
- [ ] 退款 - [ ] 退款
- [ ] 购物车 - [x] 购物车
- [ ] 收获地址 - [x] 收获地址
- 营销相关 - 营销相关
- [ ] 优惠劵 - [x] 优惠劵
- [ ] 优惠码 - [ ] 优惠码【待认领】
- 用户相关 - 用户相关
- [ ] 登陆 - [x] 登陆
- [ ] 注册 - [x] 注册
- [ ] 个人信息 - [ ] 个人信息
如下是 onemall 的功能列表。 如下是 onemall 的功能列表。
* 当功能被完成时,会标记已完成。 * 当功能被完成时,会标记已完成。
* 未完成的功能,欢迎一起来开发。 * 未完成的功能,欢迎一起来开发,特别是【待认领】的任务
- [ ] 概述 TODO - [ ] 概述 TODO【待认领】
- [ ] 数据分析 - [ ] 数据分析【待认领】
- [ ] TODO 未开始 - [ ] TODO 未开始
- [ ] 店铺资产 - [ ] 店铺资产【待认领】
- [ ] TODO 未开始 - [ ] TODO 未开始
- [ ] 商品管理 - [ ] 商品管理
- [x] 发布商品 - [x] 发布商品
- [ ] 商品管理 - [x] 商品列表
- [x] 展示类目 - [x] 展示类目
- [ ] 品牌管理 - [ ] 品牌管理【待认领】
- [ ] 订单管理 - [ ] 订单管理
- [ ] 销售单 - [ ] 销售单
- [ ] 售后单 - [ ] 售后单
- [ ] 订单评价 - [ ] 订单评价【待认领】
- [ ] 会员管理 - [ ] 会员管理
- [ ] 会员资料 - [ ] 会员资料【待认领】
- TODO 需要补充 - TODO 需要补充
- [ ] 营销管理 - [ ] 营销管理
- [ ] 广告管理 - [ ] 广告管理
- [ ] 优惠劵 - [ ] 优惠劵
- [ ] 优惠码 - [ ] 优惠码【待认领】
- [ ] 商品推荐 - [ ] 商品推荐
- [ ] 满减送活动 - [ ] 满减送活动
- [ ] 限制折扣活动 - [ ] 限制折扣活动
- [ ] 团购活动 - [ ] 团购活动【待认领】
- [ ] 系统管理 - [ ] 系统管理
- [ ] 员工管理 - [ ] 员工管理
- [ ] 角色管理 - [ ] 角色管理
...@@ -35,4 +35,7 @@ ...@@ -35,4 +35,7 @@
- [ ] 短信管理 - [ ] 短信管理
- [ ] 短信模板 - [ ] 短信模板
- [ ] 发送日志 - [ ] 发送日志
- [ ] 操作日志 - [ ] 用户访问日志
- [ ] 员工访问日志
- [ ] 员工操作日志
- [ ] 异常日志
...@@ -50,11 +50,7 @@ public class CartServiceImpl implements CartService { ...@@ -50,11 +50,7 @@ public class CartServiceImpl implements CartService {
@SuppressWarnings("Duplicates") @SuppressWarnings("Duplicates")
public CommonResult<Boolean> add(Integer userId, Integer skuId, Integer quantity) { public CommonResult<Boolean> add(Integer userId, Integer skuId, Integer quantity) {
// 查询 SKU 是否合法 // 查询 SKU 是否合法
CommonResult<ProductSkuBO> skuResult = productSpuService.getProductSku(skuId); ProductSkuBO sku = productSpuService.getProductSku(skuId);
if (skuResult.isError()) {
return CommonResult.error(skuResult);
}
ProductSkuBO sku = skuResult.getData();
if (sku == null if (sku == null
|| CommonStatusEnum.DISABLE.getValue().equals(sku.getStatus())) { // sku 被禁用 || CommonStatusEnum.DISABLE.getValue().equals(sku.getStatus())) { // sku 被禁用
return ServiceExceptionUtil.error(OrderErrorCodeEnum.CARD_ITEM_SKU_NOT_FOUND.getCode()); return ServiceExceptionUtil.error(OrderErrorCodeEnum.CARD_ITEM_SKU_NOT_FOUND.getCode());
...@@ -93,11 +89,7 @@ public class CartServiceImpl implements CartService { ...@@ -93,11 +89,7 @@ public class CartServiceImpl implements CartService {
@SuppressWarnings("Duplicates") @SuppressWarnings("Duplicates")
public CommonResult<Boolean> updateQuantity(Integer userId, Integer skuId, Integer quantity) { public CommonResult<Boolean> updateQuantity(Integer userId, Integer skuId, Integer quantity) {
// 查询 SKU 是否合法 // 查询 SKU 是否合法
CommonResult<ProductSkuBO> skuResult = productSpuService.getProductSku(skuId); ProductSkuBO sku = productSpuService.getProductSku(skuId);
if (skuResult.isError()) {
return CommonResult.error(skuResult);
}
ProductSkuBO sku = skuResult.getData();
if (sku == null if (sku == null
|| CommonStatusEnum.DISABLE.getValue().equals(sku.getStatus())) { // sku 被禁用 || CommonStatusEnum.DISABLE.getValue().equals(sku.getStatus())) { // sku 被禁用
return ServiceExceptionUtil.error(OrderErrorCodeEnum.CARD_ITEM_SKU_NOT_FOUND.getCode()); return ServiceExceptionUtil.error(OrderErrorCodeEnum.CARD_ITEM_SKU_NOT_FOUND.getCode());
...@@ -160,7 +152,7 @@ public class CartServiceImpl implements CartService { ...@@ -160,7 +152,7 @@ public class CartServiceImpl implements CartService {
// 校验商品都存在 // 校验商品都存在
Map<Integer, CalcOrderPriceDTO.Item> calcOrderItemMap = calcOrderPriceDTO.getItems().stream() Map<Integer, CalcOrderPriceDTO.Item> calcOrderItemMap = calcOrderPriceDTO.getItems().stream()
.collect(Collectors.toMap(CalcOrderPriceDTO.Item::getSkuId, item -> item)); // KEY:skuId .collect(Collectors.toMap(CalcOrderPriceDTO.Item::getSkuId, item -> item)); // KEY:skuId
List<ProductSkuDetailBO> skus = productSpuService.getProductSkuDetailList(calcOrderItemMap.keySet()).getData(); List<ProductSkuDetailBO> skus = productSpuService.getProductSkuDetailList(calcOrderItemMap.keySet());
if (skus.size() != calcOrderPriceDTO.getItems().size()) { if (skus.size() != calcOrderPriceDTO.getItems().size()) {
return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_ITEM_SOME_NOT_EXISTS.getCode()); return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_ITEM_SOME_NOT_EXISTS.getCode());
} }
...@@ -210,11 +202,7 @@ public class CartServiceImpl implements CartService { ...@@ -210,11 +202,7 @@ public class CartServiceImpl implements CartService {
@SuppressWarnings("Duplicates") @SuppressWarnings("Duplicates")
public CommonResult<CalcSkuPriceBO> calcSkuPrice(Integer skuId) { public CommonResult<CalcSkuPriceBO> calcSkuPrice(Integer skuId) {
// 查询 SKU 是否合法 // 查询 SKU 是否合法
CommonResult<ProductSkuBO> skuResult = productSpuService.getProductSku(skuId); ProductSkuBO sku = productSpuService.getProductSku(skuId);
if (skuResult.isError()) {
return CommonResult.error(skuResult);
}
ProductSkuBO sku = skuResult.getData();
if (sku == null if (sku == null
|| CommonStatusEnum.DISABLE.getValue().equals(sku.getStatus())) { // sku 被禁用 || CommonStatusEnum.DISABLE.getValue().equals(sku.getStatus())) { // sku 被禁用
return ServiceExceptionUtil.error(OrderErrorCodeEnum.CARD_ITEM_SKU_NOT_FOUND.getCode()); return ServiceExceptionUtil.error(OrderErrorCodeEnum.CARD_ITEM_SKU_NOT_FOUND.getCode());
......
...@@ -218,28 +218,20 @@ public class OrderServiceImpl implements OrderService { ...@@ -218,28 +218,20 @@ public class OrderServiceImpl implements OrderService {
// 获取商品信息 // 获取商品信息
Set<Integer> skuIds = orderItemDOList.stream().map(OrderItemDO::getSkuId).collect(Collectors.toSet()); Set<Integer> skuIds = orderItemDOList.stream().map(OrderItemDO::getSkuId).collect(Collectors.toSet());
CommonResult<List<ProductSkuDetailBO>> productResult = productSpuService.getProductSkuDetailList(skuIds); List<ProductSkuDetailBO> productList = productSpuService.getProductSkuDetailList(skuIds);
if (orderItemDTOList.size() != productList.size()) { // 校验获得的数量,是否匹配
// 校验商品信息
if (productResult.isError()) {
return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_GET_SKU_FAIL.getCode());
}
if (productResult.getData() == null) {
return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_GET_SKU_NOT_EXISTENT.getCode());
}
if (orderItemDTOList.size() != productResult.getData().size()) {
return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_GET_GOODS_INFO_INCORRECT.getCode()); return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_GET_GOODS_INFO_INCORRECT.getCode());
} }
// 价格计算 // 价格计算
CommonResult<CalcOrderPriceBO> calcOrderPriceResult = calcOrderPrice(productResult.getData(), orderCreateDTO); CommonResult<CalcOrderPriceBO> calcOrderPriceResult = calcOrderPrice(productList, orderCreateDTO);
if (calcOrderPriceResult.isError()) { if (calcOrderPriceResult.isError()) {
return CommonResult.error(calcOrderPriceResult); return CommonResult.error(calcOrderPriceResult);
} }
CalcOrderPriceBO calcOrderPrice = calcOrderPriceResult.getData(); CalcOrderPriceBO calcOrderPrice = calcOrderPriceResult.getData();
// 设置 orderItem // 设置 orderItem
Map<Integer, ProductSkuDetailBO> productSpuBOMap = productResult.getData() Map<Integer, ProductSkuDetailBO> productSpuBOMap = productList
.stream().collect(Collectors.toMap(ProductSkuDetailBO::getId, o -> o)); // 商品 SKU 信息的集合 .stream().collect(Collectors.toMap(ProductSkuDetailBO::getId, o -> o)); // 商品 SKU 信息的集合
Map<Integer, CalcOrderPriceBO.Item> priceItemMap = new HashMap<>(); Map<Integer, CalcOrderPriceBO.Item> priceItemMap = new HashMap<>();
calcOrderPrice.getItemGroups().forEach(itemGroup -> calcOrderPrice.getItemGroups().forEach(itemGroup ->
......
...@@ -2,15 +2,22 @@ package cn.iocoder.mall.product.application.config; ...@@ -2,15 +2,22 @@ package cn.iocoder.mall.product.application.config;
import cn.iocoder.common.framework.config.GlobalExceptionHandler; import cn.iocoder.common.framework.config.GlobalExceptionHandler;
import cn.iocoder.common.framework.servlet.CorsFilter; import cn.iocoder.common.framework.servlet.CorsFilter;
import cn.iocoder.mall.admin.sdk.interceptor.AdminAccessLogInterceptor;
import cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.*; import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc @EnableWebMvc
@Configuration @Configuration
@Import(value = {GlobalExceptionHandler.class}) // 统一全局返回 @Import(value = {GlobalExceptionHandler.class, // 统一全局返回
AdminSecurityInterceptor.class, AdminAccessLogInterceptor.class})
public class MVCConfiguration implements WebMvcConfigurer { public class MVCConfiguration implements WebMvcConfigurer {
// @Autowired // @Autowired
...@@ -19,9 +26,16 @@ public class MVCConfiguration implements WebMvcConfigurer { ...@@ -19,9 +26,16 @@ public class MVCConfiguration implements WebMvcConfigurer {
// @Reference // @Reference
// private OAuth2Service oauth2Service; // private OAuth2Service oauth2Service;
@Autowired
private AdminSecurityInterceptor adminSecurityInterceptor;
@Autowired
private AdminAccessLogInterceptor adminAccessLogInterceptor;
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(securityInterceptor); // registry.addInterceptor(securityInterceptor);
registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**");
registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**");
} }
@Override @Override
......
...@@ -22,6 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -22,6 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
import static cn.iocoder.common.framework.vo.CommonResult.*;
@RestController @RestController
@RequestMapping("admins") @RequestMapping("admins")
...@@ -40,18 +41,18 @@ public class AdminsProductAttrController { ...@@ -40,18 +41,18 @@ public class AdminsProductAttrController {
// 创建 ProductAttrPageDTO 对象 // 创建 ProductAttrPageDTO 对象
ProductAttrPageDTO productAttrPageDTO = new ProductAttrPageDTO().setName(name).setPageNo(pageNo).setPageSize(pageSize); ProductAttrPageDTO productAttrPageDTO = new ProductAttrPageDTO().setName(name).setPageNo(pageNo).setPageSize(pageSize);
// 查询分页 // 查询分页
CommonResult<ProductAttrPageBO> result = productAttrService.getProductAttrPage(productAttrPageDTO); ProductAttrPageBO result = productAttrService.getProductAttrPage(productAttrPageDTO);
// 返回结果 // 返回结果
return ProductAttrConvert.INSTANCE.convert2(result); return success(ProductAttrConvert.INSTANCE.convert2(result));
} }
@GetMapping("/attr/tree") @GetMapping("/attr/tree")
@ApiOperation(value = "获得规格树结构", notes = "该接口返回的信息更为精简。一般用于前端缓存数据字典到本地。") @ApiOperation(value = "获得规格树结构", notes = "该接口返回的信息更为精简。一般用于前端缓存数据字典到本地。")
public CommonResult<List<AdminsProductAttrSimpleVO>> tree() { public CommonResult<List<AdminsProductAttrSimpleVO>> tree() {
// 查询全列表 // 查询全列表
CommonResult<List<ProductAttrSimpleBO>> result = productAttrService.getProductAttrList(); List<ProductAttrSimpleBO> result = productAttrService.getProductAttrList();
// 返回结果 // 返回结果
return ProductAttrConvert.INSTANCE.convert(result); return success(ProductAttrConvert.INSTANCE.convert(result));
} }
@PostMapping("/attr/add") @PostMapping("/attr/add")
...@@ -63,9 +64,9 @@ public class AdminsProductAttrController { ...@@ -63,9 +64,9 @@ public class AdminsProductAttrController {
// 创建 ProductAttrAddDTO 对象 // 创建 ProductAttrAddDTO 对象
ProductAttrAddDTO productAttrAddDTO = new ProductAttrAddDTO().setName(name); ProductAttrAddDTO productAttrAddDTO = new ProductAttrAddDTO().setName(name);
// 添加 // 添加
CommonResult<ProductAttrBO> result = productAttrService.addProductAttr(AdminSecurityContextHolder.getContext().getAdminId(), productAttrAddDTO); ProductAttrBO result = productAttrService.addProductAttr(AdminSecurityContextHolder.getContext().getAdminId(), productAttrAddDTO);
// 返回结果 // 返回结果
return ProductAttrConvert.INSTANCE.convert3(result); return success(ProductAttrConvert.INSTANCE.convert3(result));
} }
@PostMapping("/attr/update") @PostMapping("/attr/update")
...@@ -79,7 +80,7 @@ public class AdminsProductAttrController { ...@@ -79,7 +80,7 @@ public class AdminsProductAttrController {
// 创建 ProductAttrUpdateDTO 对象 // 创建 ProductAttrUpdateDTO 对象
ProductAttrUpdateDTO productAttrUpdateDTO = new ProductAttrUpdateDTO().setId(id).setName(name); ProductAttrUpdateDTO productAttrUpdateDTO = new ProductAttrUpdateDTO().setId(id).setName(name);
// 更新 // 更新
return productAttrService.updateProductAttr(AdminSecurityContextHolder.getContext().getAdminId(), productAttrUpdateDTO); return success(productAttrService.updateProductAttr(AdminSecurityContextHolder.getContext().getAdminId(), productAttrUpdateDTO));
} }
@PostMapping("/attr/update_status") @PostMapping("/attr/update_status")
...@@ -90,7 +91,7 @@ public class AdminsProductAttrController { ...@@ -90,7 +91,7 @@ public class AdminsProductAttrController {
}) })
public CommonResult<Boolean> updateAttrStatus(@RequestParam("id") Integer id, public CommonResult<Boolean> updateAttrStatus(@RequestParam("id") Integer id,
@RequestParam("status") Integer status) { @RequestParam("status") Integer status) {
return productAttrService.updateProductAttrStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status); return success(productAttrService.updateProductAttrStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status));
} }
// TODO 芋艿 暂时不考虑 delete Attr 。因为关联逻辑比较多 // TODO 芋艿 暂时不考虑 delete Attr 。因为关联逻辑比较多
...@@ -106,9 +107,9 @@ public class AdminsProductAttrController { ...@@ -106,9 +107,9 @@ public class AdminsProductAttrController {
// 创建 ProductAttrValueAddDTO 对象 // 创建 ProductAttrValueAddDTO 对象
ProductAttrValueAddDTO productAttrValueAddDTO = new ProductAttrValueAddDTO().setAttrId(attrId).setName(name); ProductAttrValueAddDTO productAttrValueAddDTO = new ProductAttrValueAddDTO().setAttrId(attrId).setName(name);
// 添加 // 添加
CommonResult<ProductAttrValueBO> result = productAttrService.addProductAttrValue(AdminSecurityContextHolder.getContext().getAdminId(), productAttrValueAddDTO); ProductAttrValueBO result = productAttrService.addProductAttrValue(AdminSecurityContextHolder.getContext().getAdminId(), productAttrValueAddDTO);
// 返回结果 // 返回结果
return ProductAttrConvert.INSTANCE.convert4(result); return success(ProductAttrConvert.INSTANCE.convert4(result));
} }
@PostMapping("/attr_value/update") @PostMapping("/attr_value/update")
...@@ -122,7 +123,7 @@ public class AdminsProductAttrController { ...@@ -122,7 +123,7 @@ public class AdminsProductAttrController {
// 创建 ProductAttrValueUpdateDTO 对象 // 创建 ProductAttrValueUpdateDTO 对象
ProductAttrValueUpdateDTO productAttrValueUpdateDTO = new ProductAttrValueUpdateDTO().setId(id).setName(name); ProductAttrValueUpdateDTO productAttrValueUpdateDTO = new ProductAttrValueUpdateDTO().setId(id).setName(name);
// 更新 // 更新
return productAttrService.updateProductAttrValue(AdminSecurityContextHolder.getContext().getAdminId(), productAttrValueUpdateDTO); return success(productAttrService.updateProductAttrValue(AdminSecurityContextHolder.getContext().getAdminId(), productAttrValueUpdateDTO));
} }
@PostMapping("/attr_value/update_status") @PostMapping("/attr_value/update_status")
...@@ -132,7 +133,7 @@ public class AdminsProductAttrController { ...@@ -132,7 +133,7 @@ public class AdminsProductAttrController {
}) })
public CommonResult<Boolean> updateAttrValueStatus(@RequestParam("id") Integer id, public CommonResult<Boolean> updateAttrValueStatus(@RequestParam("id") Integer id,
@RequestParam("status") Integer status) { @RequestParam("status") Integer status) {
return productAttrService.updateProductAttrValueStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status); return success(productAttrService.updateProductAttrValueStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status));
} }
// TODO 芋艿 暂时不考虑 delete Attr Value 。因为关联逻辑比较多 // TODO 芋艿 暂时不考虑 delete Attr Value 。因为关联逻辑比较多
......
...@@ -10,11 +10,11 @@ import cn.iocoder.mall.product.api.dto.ProductCategoryUpdateDTO; ...@@ -10,11 +10,11 @@ import cn.iocoder.mall.product.api.dto.ProductCategoryUpdateDTO;
import cn.iocoder.mall.product.application.convert.ProductCategoryConvert; import cn.iocoder.mall.product.application.convert.ProductCategoryConvert;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryTreeNodeVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryTreeNodeVO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryVO;
import org.apache.dubbo.config.annotation.Reference;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
...@@ -24,6 +24,8 @@ import java.util.List; ...@@ -24,6 +24,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static cn.iocoder.common.framework.vo.CommonResult.success;
@RestController @RestController
@RequestMapping("admins/category") @RequestMapping("admins/category")
@Api("商品分类") @Api("商品分类")
...@@ -36,7 +38,7 @@ public class AdminsProductCategoryController { ...@@ -36,7 +38,7 @@ public class AdminsProductCategoryController {
@GetMapping("/tree") @GetMapping("/tree")
@ApiOperation("获得分类树结构") @ApiOperation("获得分类树结构")
public CommonResult<List<AdminsProductCategoryTreeNodeVO>> tree() { public CommonResult<List<AdminsProductCategoryTreeNodeVO>> tree() {
List<ProductCategoryBO> productCategories = productCategoryService.getAll().getData(); List<ProductCategoryBO> productCategories = productCategoryService.getAll();
// 创建 ProductCategoryTreeNodeVO Map // 创建 ProductCategoryTreeNodeVO Map
Map<Integer, AdminsProductCategoryTreeNodeVO> treeNodeMap = productCategories.stream().collect(Collectors.toMap(ProductCategoryBO::getId, ProductCategoryConvert.Admins.INSTANCE::convert)); Map<Integer, AdminsProductCategoryTreeNodeVO> treeNodeMap = productCategories.stream().collect(Collectors.toMap(ProductCategoryBO::getId, ProductCategoryConvert.Admins.INSTANCE::convert));
// 处理父子关系 // 处理父子关系
...@@ -56,7 +58,7 @@ public class AdminsProductCategoryController { ...@@ -56,7 +58,7 @@ public class AdminsProductCategoryController {
.filter(node -> node.getPid().equals(ProductCategoryConstants.PID_ROOT)) .filter(node -> node.getPid().equals(ProductCategoryConstants.PID_ROOT))
.sorted(Comparator.comparing(AdminsProductCategoryTreeNodeVO::getSort)) .sorted(Comparator.comparing(AdminsProductCategoryTreeNodeVO::getSort))
.collect(Collectors.toList()); .collect(Collectors.toList());
return CommonResult.success(rootNodes); return success(rootNodes);
} }
@PostMapping("/add") @PostMapping("/add")
...@@ -77,9 +79,9 @@ public class AdminsProductCategoryController { ...@@ -77,9 +79,9 @@ public class AdminsProductCategoryController {
ProductCategoryAddDTO productCategoryAddDTO = new ProductCategoryAddDTO().setPid(pid).setName(name) ProductCategoryAddDTO productCategoryAddDTO = new ProductCategoryAddDTO().setPid(pid).setName(name)
.setDescription(description).setPicUrl(picUrl).setSort(sort); .setDescription(description).setPicUrl(picUrl).setSort(sort);
// 创建商品分类 // 创建商品分类
CommonResult<ProductCategoryBO> result = productCategoryService.addProductCategory(AdminSecurityContextHolder.getContext().getAdminId(), productCategoryAddDTO); ProductCategoryBO result = productCategoryService.addProductCategory(AdminSecurityContextHolder.getContext().getAdminId(), productCategoryAddDTO);
// 返回结果 // 返回结果
return ProductCategoryConvert.Admins.INSTANCE.convert2(result); return success(ProductCategoryConvert.Admins.INSTANCE.convert2(result));
} }
@PostMapping("/update") @PostMapping("/update")
...@@ -102,7 +104,7 @@ public class AdminsProductCategoryController { ...@@ -102,7 +104,7 @@ public class AdminsProductCategoryController {
ProductCategoryUpdateDTO productCategoryAddDTO = new ProductCategoryUpdateDTO().setId(id).setPid(pid).setName(name) ProductCategoryUpdateDTO productCategoryAddDTO = new ProductCategoryUpdateDTO().setId(id).setPid(pid).setName(name)
.setDescription(description).setPicUrl(picUrl).setSort(sort); .setDescription(description).setPicUrl(picUrl).setSort(sort);
// 更新商品分类 // 更新商品分类
return productCategoryService.updateProductCategory(AdminSecurityContextHolder.getContext().getAdminId(), productCategoryAddDTO); return success(productCategoryService.updateProductCategory(AdminSecurityContextHolder.getContext().getAdminId(), productCategoryAddDTO));
} }
@PostMapping("/update_status") @PostMapping("/update_status")
...@@ -113,14 +115,14 @@ public class AdminsProductCategoryController { ...@@ -113,14 +115,14 @@ public class AdminsProductCategoryController {
}) })
public CommonResult<Boolean> updateStatus(@RequestParam("id") Integer id, public CommonResult<Boolean> updateStatus(@RequestParam("id") Integer id,
@RequestParam("status") Integer status) { @RequestParam("status") Integer status) {
return productCategoryService.updateProductCategoryStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status); return success(productCategoryService.updateProductCategoryStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status));
} }
@PostMapping("/delete") @PostMapping("/delete")
@ApiOperation(value = "删除商品分类") @ApiOperation(value = "删除商品分类")
@ApiImplicitParam(name = "id", value = "商品分类编号", required = true, example = "1") @ApiImplicitParam(name = "id", value = "商品分类编号", required = true, example = "1")
public CommonResult<Boolean> delete(@RequestParam("id") Integer id) { public CommonResult<Boolean> delete(@RequestParam("id") Integer id) {
return productCategoryService.deleteProductCategory(AdminSecurityContextHolder.getContext().getAdminId(), id); return success(productCategoryService.deleteProductCategory(AdminSecurityContextHolder.getContext().getAdminId(), id));
} }
} }
...@@ -12,19 +12,21 @@ import cn.iocoder.mall.product.api.dto.ProductSpuUpdateDTO; ...@@ -12,19 +12,21 @@ import cn.iocoder.mall.product.api.dto.ProductSpuUpdateDTO;
import cn.iocoder.mall.product.application.convert.ProductSpuConvert; import cn.iocoder.mall.product.application.convert.ProductSpuConvert;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuDetailVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuDetailVO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuPageVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuPageVO;
import org.apache.dubbo.config.annotation.Reference;
import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import static cn.iocoder.common.framework.vo.CommonResult.success;
@RestController @RestController
@RequestMapping("admins") @RequestMapping("admins")
@Api("商品 SPU + SKU") @Api("商品 SPU + SKU")
...@@ -47,7 +49,6 @@ public class AdminsProductSpuController { ...@@ -47,7 +49,6 @@ public class AdminsProductSpuController {
@ApiImplicitParam(name = "picUrls", value = "商品主图地址的数组", required = true, example = "http://www.iocoder.cn"), @ApiImplicitParam(name = "picUrls", value = "商品主图地址的数组", required = true, example = "http://www.iocoder.cn"),
@ApiImplicitParam(name = "visible", value = "是否上架商品(是否可见)", required = true, example = "true"), @ApiImplicitParam(name = "visible", value = "是否上架商品(是否可见)", required = true, example = "true"),
@ApiImplicitParam(name = "skuStr", value = "SKU 字符串", required = true, example = "[{\"attrs\": [1,3 ], \"price\": 1, \"quantity\": 100, \"picUrl\": \"http://www.iocoder.cn\"}]"), @ApiImplicitParam(name = "skuStr", value = "SKU 字符串", required = true, example = "[{\"attrs\": [1,3 ], \"price\": 1, \"quantity\": 100, \"picUrl\": \"http://www.iocoder.cn\"}]"),
}) })
public CommonResult<AdminsProductSpuDetailVO> add(@RequestParam("name") String name, public CommonResult<AdminsProductSpuDetailVO> add(@RequestParam("name") String name,
@RequestParam("sellPoint") String sellPoint, @RequestParam("sellPoint") String sellPoint,
...@@ -61,9 +62,9 @@ public class AdminsProductSpuController { ...@@ -61,9 +62,9 @@ public class AdminsProductSpuController {
.setDescription(description).setCid(cid).setPicUrls(picUrls).setVisible(visible) .setDescription(description).setCid(cid).setPicUrls(picUrls).setVisible(visible)
.setSkus(parseSkus(skuStr, ProductSkuAddOrUpdateDTO.class)); .setSkus(parseSkus(skuStr, ProductSkuAddOrUpdateDTO.class));
// 保存商品 // 保存商品
CommonResult<ProductSpuDetailBO> result = productSpuService.addProductSpu(AdminSecurityContextHolder.getContext().getAdminId(), productSpuAddDTO); ProductSpuDetailBO result = productSpuService.addProductSpu(AdminSecurityContextHolder.getContext().getAdminId(), productSpuAddDTO);
// 返回结果 // 返回结果
return ProductSpuConvert.INSTANCE.convert(result); return success(ProductSpuConvert.INSTANCE.convert(result));
} }
@PostMapping("/spu/update") @PostMapping("/spu/update")
...@@ -77,7 +78,6 @@ public class AdminsProductSpuController { ...@@ -77,7 +78,6 @@ public class AdminsProductSpuController {
@ApiImplicitParam(name = "picUrls", value = "商品主图地址的数组", required = true, example = "http://www.iocoder.cn"), @ApiImplicitParam(name = "picUrls", value = "商品主图地址的数组", required = true, example = "http://www.iocoder.cn"),
@ApiImplicitParam(name = "visible", value = "是否上架商品(是否可见)", required = true, example = "true"), @ApiImplicitParam(name = "visible", value = "是否上架商品(是否可见)", required = true, example = "true"),
@ApiImplicitParam(name = "skuStr", value = "SKU 字符串", required = true, example = "[{\"attrs\": [1,3 ], \"price\": 1, \"quantity\": 100, \"picUrl\": \"http://www.iocoder.cn\"}]"), @ApiImplicitParam(name = "skuStr", value = "SKU 字符串", required = true, example = "[{\"attrs\": [1,3 ], \"price\": 1, \"quantity\": 100, \"picUrl\": \"http://www.iocoder.cn\"}]"),
}) })
public CommonResult<Boolean> update(@RequestParam("id") Integer id, public CommonResult<Boolean> update(@RequestParam("id") Integer id,
@RequestParam("name") String name, @RequestParam("name") String name,
...@@ -92,14 +92,15 @@ public class AdminsProductSpuController { ...@@ -92,14 +92,15 @@ public class AdminsProductSpuController {
.setDescription(description).setCid(cid).setPicUrls(picUrls).setVisible(visible) .setDescription(description).setCid(cid).setPicUrls(picUrls).setVisible(visible)
.setSkus(parseSkus(skuStr, ProductSkuAddOrUpdateDTO.class)); .setSkus(parseSkus(skuStr, ProductSkuAddOrUpdateDTO.class));
// 更新商品 // 更新商品
return productSpuService.updateProductSpu(AdminSecurityContextHolder.getContext().getAdminId(), productSpuUpdateDTO); productSpuService.updateProductSpu(AdminSecurityContextHolder.getContext().getAdminId(), productSpuUpdateDTO);
return success(true);
} }
@PostMapping("/spu/update_sort") @PostMapping("/spu/update_sort")
@ApiOperation("更新商品的排序") @ApiOperation("更新商品的排序")
public CommonResult<Boolean> updateSort(@RequestParam("id") Integer id, public CommonResult<Boolean> updateSort(@RequestParam("id") Integer id,
@RequestParam("sort") Integer sort) { @RequestParam("sort") Integer sort) {
return productSpuService.updateProductSpuSort(AdminSecurityContextHolder.getContext().getAdminId(), id, sort); return success(productSpuService.updateProductSpuSort(AdminSecurityContextHolder.getContext().getAdminId(), id, sort));
} }
// TODO 芋艿,删除功能暂时不做。主要原因是,关联的数据太多。删除带来的问题会比较大 // TODO 芋艿,删除功能暂时不做。主要原因是,关联的数据太多。删除带来的问题会比较大
...@@ -109,22 +110,37 @@ public class AdminsProductSpuController { ...@@ -109,22 +110,37 @@ public class AdminsProductSpuController {
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "商品名称,模糊匹配", example = "小王"), @ApiImplicitParam(name = "name", value = "商品名称,模糊匹配", example = "小王"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"), @ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
@ApiImplicitParam(name = "status", value = "状态", example = "可选值:1-在售中;2-已售罄;3-仓库中;"),
@ApiImplicitParam(name = "cid", value = "商品分类编号", example = "10"),
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"), @ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
}) })
public CommonResult<AdminsProductSpuPageVO> spuPage(@RequestParam(value = "name", required = false) String name, public CommonResult<AdminsProductSpuPageVO> spuPage(@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "status") Integer status,
@RequestParam(value = "cid", required = false) Integer cid,
@RequestParam(value = "pageNo", defaultValue = "0") Integer pageNo, @RequestParam(value = "pageNo", defaultValue = "0") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) { @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
// 创建 ProductSpuPageDTO 对象 // 创建 ProductSpuPageDTO 对象
ProductSpuPageDTO productSpuPageDTO = new ProductSpuPageDTO().setName(name).setPageNo(pageNo).setPageSize(pageSize); ProductSpuPageDTO productSpuPageDTO = new ProductSpuPageDTO().setName(name).setCid(cid).setPageNo(pageNo).setPageSize(pageSize);
CommonResult<ProductSpuPageBO> result = productSpuService.getProductSpuPage(productSpuPageDTO); switch (status) {
return ProductSpuConvert.INSTANCE.convert2(result); case 1:
productSpuPageDTO.setVisible(true).setHasQuantity(true);
break;
case 2:
productSpuPageDTO.setVisible(true).setHasQuantity(false);
break;
case 3:
productSpuPageDTO.setVisible(false);
break;
}
ProductSpuPageBO result = productSpuService.getProductSpuPage(productSpuPageDTO);
return success(ProductSpuConvert.INSTANCE.convert2(result));
} }
@GetMapping("/spu/info") @GetMapping("/spu/info")
@ApiOperation("商品 SPU 明细") @ApiOperation("商品 SPU 明细")
@ApiImplicitParam(name = "id", value = "SPU 编号", required = true, example = "100") @ApiImplicitParam(name = "id", value = "SPU 编号", required = true, example = "100")
public CommonResult<AdminsProductSpuDetailVO> info(@RequestParam("id") Integer id) { public CommonResult<AdminsProductSpuDetailVO> info(@RequestParam("id") Integer id) {
return ProductSpuConvert.INSTANCE.convert(productSpuService.getProductSpuDetail(id)); return success(ProductSpuConvert.INSTANCE.convert(productSpuService.getProductSpuDetail(id)));
} }
private <T> List<T> parseSkus(String skuStr, Class<T> clazz) { private <T> List<T> parseSkus(String skuStr, Class<T> clazz) {
......
...@@ -19,6 +19,8 @@ import org.springframework.web.bind.annotation.RequestMapping; ...@@ -19,6 +19,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import static cn.iocoder.common.framework.vo.CommonResult.success;
@RestController @RestController
@RequestMapping("users/spu") @RequestMapping("users/spu")
@Api("商品 SPU + SKU") @Api("商品 SPU + SKU")
...@@ -33,7 +35,7 @@ public class UsersProductSpuController { ...@@ -33,7 +35,7 @@ public class UsersProductSpuController {
@ApiImplicitParam(name = "id", value = "SPU 编号", required = true, example = "100") @ApiImplicitParam(name = "id", value = "SPU 编号", required = true, example = "100")
@PermitAll @PermitAll
public CommonResult<UsersProductSpuDetailVO> info(@RequestParam("id") Integer id) { public CommonResult<UsersProductSpuDetailVO> info(@RequestParam("id") Integer id) {
return ProductSpuConvert.INSTANCE.convert4(productSpuService.getProductSpuDetail(id)); return success(ProductSpuConvert.INSTANCE.convert4(productSpuService.getProductSpuDetail(id)));
} }
@GetMapping("/page") @GetMapping("/page")
...@@ -52,9 +54,9 @@ public class UsersProductSpuController { ...@@ -52,9 +54,9 @@ public class UsersProductSpuController {
ProductSpuPageDTO productSpuPageDTO = new ProductSpuPageDTO().setCid(cid).setVisible(true) ProductSpuPageDTO productSpuPageDTO = new ProductSpuPageDTO().setCid(cid).setVisible(true)
.setPageNo(pageNo).setPageSize(pageSize); .setPageNo(pageNo).setPageSize(pageSize);
// 查询分页 // 查询分页
CommonResult<ProductSpuPageBO> result = productSpuService.getProductSpuPage(productSpuPageDTO); ProductSpuPageBO result = productSpuService.getProductSpuPage(productSpuPageDTO);
// 返回结果 // 返回结果
return ProductSpuConvert.INSTANCE.convert3(result); return success(ProductSpuConvert.INSTANCE.convert3(result));
} }
} }
package cn.iocoder.mall.product.application.convert; package cn.iocoder.mall.product.application.convert;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.product.api.bo.ProductAttrBO; import cn.iocoder.mall.product.api.bo.ProductAttrBO;
import cn.iocoder.mall.product.api.bo.ProductAttrPageBO; import cn.iocoder.mall.product.api.bo.ProductAttrPageBO;
import cn.iocoder.mall.product.api.bo.ProductAttrSimpleBO; import cn.iocoder.mall.product.api.bo.ProductAttrSimpleBO;
...@@ -21,18 +20,15 @@ public interface ProductAttrConvert { ...@@ -21,18 +20,15 @@ public interface ProductAttrConvert {
ProductAttrConvert INSTANCE = Mappers.getMapper(ProductAttrConvert.class); ProductAttrConvert INSTANCE = Mappers.getMapper(ProductAttrConvert.class);
@Mappings({}) @Mappings({})
CommonResult<AdminsProductAttrPageVO> convert2(CommonResult<ProductAttrPageBO> result); AdminsProductAttrPageVO convert2(ProductAttrPageBO result);
@Mappings({}) @Mappings({})
CommonResult<List<AdminsProductAttrSimpleVO>> convert(CommonResult<List<ProductAttrSimpleBO>> result); List<AdminsProductAttrSimpleVO> convert(List<ProductAttrSimpleBO> result);
@Mappings({}) @Mappings({})
AdminsProductAttrVO convert3(ProductAttrBO productAttrBO); AdminsProductAttrVO convert3(ProductAttrBO productAttrBO);
@Mappings({}) @Mappings({})
CommonResult<AdminsProductAttrVO> convert3(CommonResult<ProductAttrBO> productAttrBO); AdminsProductAttrValueVO convert4(ProductAttrValueBO productAttrValueBO);
@Mappings({}) }
CommonResult<AdminsProductAttrValueVO> convert4(CommonResult<ProductAttrValueBO> productAttrValueBO);
}
\ No newline at end of file
package cn.iocoder.mall.product.application.convert; package cn.iocoder.mall.product.application.convert;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.product.api.bo.ProductCategoryBO; import cn.iocoder.mall.product.api.bo.ProductCategoryBO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryTreeNodeVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryTreeNodeVO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryVO;
...@@ -35,7 +34,7 @@ public interface ProductCategoryConvert { ...@@ -35,7 +34,7 @@ public interface ProductCategoryConvert {
AdminsProductCategoryTreeNodeVO convert(ProductCategoryBO category); AdminsProductCategoryTreeNodeVO convert(ProductCategoryBO category);
@Mappings({}) @Mappings({})
CommonResult<AdminsProductCategoryVO> convert2(CommonResult<ProductCategoryBO> result); AdminsProductCategoryVO convert2(ProductCategoryBO result);
} }
......
package cn.iocoder.mall.product.application.convert; package cn.iocoder.mall.product.application.convert;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.product.api.bo.ProductSpuDetailBO; import cn.iocoder.mall.product.api.bo.ProductSpuDetailBO;
import cn.iocoder.mall.product.api.bo.ProductSpuPageBO; import cn.iocoder.mall.product.api.bo.ProductSpuPageBO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuDetailVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuDetailVO;
...@@ -19,16 +18,16 @@ public interface ProductSpuConvert { ...@@ -19,16 +18,16 @@ public interface ProductSpuConvert {
@Mappings({}) @Mappings({})
AdminsProductSpuDetailVO convert(ProductSpuDetailBO productSpuDetailBO); AdminsProductSpuDetailVO convert(ProductSpuDetailBO productSpuDetailBO);
@Mappings({}) // @Mappings({})
CommonResult<AdminsProductSpuDetailVO> convert(CommonResult<ProductSpuDetailBO> result); // CommonResult<AdminsProductSpuDetailVO> convert(CommonResult<ProductSpuDetailBO> result);
@Mappings({}) @Mappings({})
CommonResult<AdminsProductSpuPageVO> convert2(CommonResult<ProductSpuPageBO> result); AdminsProductSpuPageVO convert2(ProductSpuPageBO result);
@Mappings({}) @Mappings({})
CommonResult<UsersProductSpuPageVO> convert3(CommonResult<ProductSpuPageBO> result); UsersProductSpuPageVO convert3(ProductSpuPageBO result);
@Mappings({}) @Mappings({})
CommonResult<UsersProductSpuDetailVO> convert4(CommonResult<ProductSpuDetailBO> result); UsersProductSpuDetailVO convert4(ProductSpuDetailBO result);
} }
\ No newline at end of file
...@@ -13,8 +13,8 @@ import java.util.List; ...@@ -13,8 +13,8 @@ import java.util.List;
public class AdminsProductSpuPageVO { public class AdminsProductSpuPageVO {
@ApiModelProperty(value = "spu 数组", required = true) @ApiModelProperty(value = "spu 数组", required = true)
private List<AdminsProductSpuVO> spus; private List<AdminsProductSpuVO> list;
@ApiModelProperty(value = "总数", required = true) @ApiModelProperty(value = "总数", required = true)
private Integer count; private Integer total;
} }
package cn.iocoder.mall.product.api; package cn.iocoder.mall.product.api;
import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.common.framework.constant.CommonStatusEnum;
import cn.iocoder.common.framework.validator.InEnum;
import cn.iocoder.mall.product.api.bo.ProductAttrBO; import cn.iocoder.mall.product.api.bo.ProductAttrBO;
import cn.iocoder.mall.product.api.bo.ProductAttrPageBO; import cn.iocoder.mall.product.api.bo.ProductAttrPageBO;
import cn.iocoder.mall.product.api.bo.ProductAttrSimpleBO; import cn.iocoder.mall.product.api.bo.ProductAttrSimpleBO;
...@@ -11,7 +12,7 @@ import java.util.List; ...@@ -11,7 +12,7 @@ import java.util.List;
public interface ProductAttrService { public interface ProductAttrService {
CommonResult<ProductAttrPageBO> getProductAttrPage(ProductAttrPageDTO productAttrPageDTO); ProductAttrPageBO getProductAttrPage(ProductAttrPageDTO productAttrPageDTO);
/** /**
* 获得规格属性数组 * 获得规格属性数组
...@@ -20,19 +21,20 @@ public interface ProductAttrService { ...@@ -20,19 +21,20 @@ public interface ProductAttrService {
* *
* @return 规格属性数组 * @return 规格属性数组
*/ */
CommonResult<List<ProductAttrSimpleBO>> getProductAttrList(); List<ProductAttrSimpleBO> getProductAttrList();
CommonResult<ProductAttrBO> addProductAttr(Integer adminId, ProductAttrAddDTO productAttrAddDTO); ProductAttrBO addProductAttr(Integer adminId, ProductAttrAddDTO productAttrAddDTO);
CommonResult<Boolean> updateProductAttr(Integer adminId, ProductAttrUpdateDTO productAttrUpdateDTO); Boolean updateProductAttr(Integer adminId, ProductAttrUpdateDTO productAttrUpdateDTO);
CommonResult<Boolean> updateProductAttrStatus(Integer adminId, Integer productAttrId, Integer status); Boolean updateProductAttrStatus(Integer adminId, Integer productAttrId,
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") Integer status);
ProductAttrValueBO addProductAttrValue(Integer adminId, ProductAttrValueAddDTO productAttrValueAddDTO);
CommonResult<ProductAttrValueBO> addProductAttrValue(Integer adminId, ProductAttrValueAddDTO productAttrValueAddDTO); Boolean updateProductAttrValue(Integer adminId, ProductAttrValueUpdateDTO productAttrValueUpdateDTO);
CommonResult<Boolean> updateProductAttrValue(Integer adminId, ProductAttrValueUpdateDTO productAttrValueUpdateDTO); Boolean updateProductAttrValueStatus(Integer adminId, Integer productAttrValueId,
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") Integer status);
CommonResult<Boolean> updateProductAttrValueStatus(Integer adminId, Integer productAttrValueId, Integer status); }
}
\ No newline at end of file
package cn.iocoder.mall.product.api; package cn.iocoder.mall.product.api;
import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.common.framework.constant.CommonStatusEnum;
import cn.iocoder.common.framework.validator.InEnum;
import cn.iocoder.mall.product.api.bo.ProductCategoryBO; import cn.iocoder.mall.product.api.bo.ProductCategoryBO;
import cn.iocoder.mall.product.api.dto.ProductCategoryAddDTO; import cn.iocoder.mall.product.api.dto.ProductCategoryAddDTO;
import cn.iocoder.mall.product.api.dto.ProductCategoryUpdateDTO; import cn.iocoder.mall.product.api.dto.ProductCategoryUpdateDTO;
...@@ -27,14 +28,15 @@ public interface ProductCategoryService { ...@@ -27,14 +28,15 @@ public interface ProductCategoryService {
/** /**
* @return 返回所有产品分类们 * @return 返回所有产品分类们
*/ */
CommonResult<List<ProductCategoryBO>> getAll(); List<ProductCategoryBO> getAll();
CommonResult<ProductCategoryBO> addProductCategory(Integer adminId, ProductCategoryAddDTO productCategoryAddDTO); ProductCategoryBO addProductCategory(Integer adminId, ProductCategoryAddDTO productCategoryAddDTO);
CommonResult<Boolean> updateProductCategory(Integer adminId, ProductCategoryUpdateDTO productCategoryUpdateDTO); Boolean updateProductCategory(Integer adminId, ProductCategoryUpdateDTO productCategoryUpdateDTO);
CommonResult<Boolean> updateProductCategoryStatus(Integer adminId, Integer productCategoryId, Integer status); Boolean updateProductCategoryStatus(Integer adminId, Integer productCategoryId,
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") Integer status);
CommonResult<Boolean> deleteProductCategory(Integer admin, Integer productCategoryId); Boolean deleteProductCategory(Integer admin, Integer productCategoryId);
} }
package cn.iocoder.mall.product.api; package cn.iocoder.mall.product.api;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.product.api.bo.*; import cn.iocoder.mall.product.api.bo.*;
import cn.iocoder.mall.product.api.dto.ProductSpuAddDTO; import cn.iocoder.mall.product.api.dto.ProductSpuAddDTO;
import cn.iocoder.mall.product.api.dto.ProductSpuPageDTO; import cn.iocoder.mall.product.api.dto.ProductSpuPageDTO;
...@@ -11,7 +10,7 @@ import java.util.List; ...@@ -11,7 +10,7 @@ import java.util.List;
public interface ProductSpuService { public interface ProductSpuService {
CommonResult<ProductSpuDetailBO> getProductSpuDetail(Integer id); ProductSpuDetailBO getProductSpuDetail(Integer id);
/** /**
* 增量获得商品列表,按照 lastId 递增获得 * 增量获得商品列表,按照 lastId 递增获得
...@@ -20,20 +19,20 @@ public interface ProductSpuService { ...@@ -20,20 +19,20 @@ public interface ProductSpuService {
* @param limit 大小 * @param limit 大小
* @return 商品列表 * @return 商品列表
*/ */
CommonResult<List<ProductSpuDetailBO>> getProductSpuDetailListForSync(Integer lastId, Integer limit); List<ProductSpuDetailBO> getProductSpuDetailListForSync(Integer lastId, Integer limit);
CommonResult<ProductSpuPageBO> getProductSpuPage(ProductSpuPageDTO productSpuPageDTO); ProductSpuPageBO getProductSpuPage(ProductSpuPageDTO productSpuPageDTO);
CommonResult<List<ProductSpuBO>> getProductSpuList(Collection<Integer> ids); List<ProductSpuBO> getProductSpuList(Collection<Integer> ids);
CommonResult<ProductSkuBO> getProductSku(Integer id); ProductSkuBO getProductSku(Integer id);
CommonResult<List<ProductSkuDetailBO>> getProductSkuDetailList(Collection<Integer> ids); List<ProductSkuDetailBO> getProductSkuDetailList(Collection<Integer> ids);
CommonResult<ProductSpuDetailBO> addProductSpu(Integer adminId, ProductSpuAddDTO productSpuAddDTO); ProductSpuDetailBO addProductSpu(Integer adminId, ProductSpuAddDTO productSpuAddDTO);
CommonResult<Boolean> updateProductSpu(Integer adminId, ProductSpuUpdateDTO productSpuUpdateDTO); void updateProductSpu(Integer adminId, ProductSpuUpdateDTO productSpuUpdateDTO);
CommonResult<Boolean> updateProductSpuSort(Integer adminId, Integer spuId, Integer sort); Boolean updateProductSpuSort(Integer adminId, Integer spuId, Integer sort);
} }
...@@ -16,10 +16,10 @@ public class ProductSpuPageBO implements Serializable { ...@@ -16,10 +16,10 @@ public class ProductSpuPageBO implements Serializable {
/** /**
* Spu 数组 * Spu 数组
*/ */
private List<ProductSpuBO> spus; private List<ProductSpuBO> list;
/** /**
* 总量 * 总量
*/ */
private Integer count; private Integer total;
} }
...@@ -26,6 +26,12 @@ public class ProductSpuPageDTO { ...@@ -26,6 +26,12 @@ public class ProductSpuPageDTO {
* 是否可见 * 是否可见
*/ */
private Boolean visible; private Boolean visible;
/**
* 是否有库存
*
* 允许为空。空时,不进行筛选
*/
private Boolean hasQuantity;
@NotNull(message = "页码不能为空") @NotNull(message = "页码不能为空")
private Integer pageNo; private Integer pageNo;
......
...@@ -32,11 +32,13 @@ public interface ProductSpuMapper { ...@@ -32,11 +32,13 @@ public interface ProductSpuMapper {
List<ProductSpuDO> selectListByNameLikeOrderBySortAsc(@Param("name") String name, List<ProductSpuDO> selectListByNameLikeOrderBySortAsc(@Param("name") String name,
@Param("cid") Integer cid, @Param("cid") Integer cid,
@Param("visible") Boolean visible, @Param("visible") Boolean visible,
@Param("hasQuantity") Boolean hasQuantity,
@Param("offset") Integer offset, @Param("offset") Integer offset,
@Param("limit") Integer limit); @Param("limit") Integer limit);
Integer selectCountByNameLike(@Param("name") String name, Integer selectCountByNameLike(@Param("name") String name,
@Param("cid") Integer cid, @Param("cid") Integer cid,
@Param("hasQuantity") Boolean hasQuantity,
@Param("visible") Boolean visible); @Param("visible") Boolean visible);
} }
package cn.iocoder.mall.product.service; package cn.iocoder.mall.product.service;
import cn.iocoder.common.framework.constant.DeletedStatusEnum; import cn.iocoder.common.framework.constant.DeletedStatusEnum;
import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
import cn.iocoder.common.framework.util.ServiceExceptionUtil; import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.product.api.ProductCategoryService; import cn.iocoder.mall.product.api.ProductCategoryService;
import cn.iocoder.mall.product.api.bo.ProductCategoryBO; import cn.iocoder.mall.product.api.bo.ProductCategoryBO;
import cn.iocoder.mall.product.api.constant.ProductCategoryConstants; import cn.iocoder.mall.product.api.constant.ProductCategoryConstants;
...@@ -40,13 +38,13 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { ...@@ -40,13 +38,13 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
} }
@Override @Override
public CommonResult<List<ProductCategoryBO>> getAll() { public List<ProductCategoryBO> getAll() {
List<ProductCategoryDO> categoryList = productCategoryMapper.selectList(); List<ProductCategoryDO> categoryList = productCategoryMapper.selectList();
return CommonResult.success(ProductCategoryConvert.INSTANCE.convertToBO(categoryList)); return ProductCategoryConvert.INSTANCE.convertToBO(categoryList);
} }
@Override @Override
public CommonResult<ProductCategoryBO> addProductCategory(Integer adminId, ProductCategoryAddDTO productCategoryAddDTO) { public ProductCategoryBO addProductCategory(Integer adminId, ProductCategoryAddDTO productCategoryAddDTO) {
// 校验父分类 // 校验父分类
validParent(productCategoryAddDTO.getPid()); validParent(productCategoryAddDTO.getPid());
// 保存到数据库 // 保存到数据库
...@@ -57,62 +55,58 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { ...@@ -57,62 +55,58 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
productCategoryMapper.insert(productCategory); productCategoryMapper.insert(productCategory);
// TODO 操作日志 // TODO 操作日志
// 返回成功 // 返回成功
return CommonResult.success(ProductCategoryConvert.INSTANCE.convertToBO(productCategory)); return ProductCategoryConvert.INSTANCE.convertToBO(productCategory);
} }
@Override @Override
public CommonResult<Boolean> updateProductCategory(Integer adminId, ProductCategoryUpdateDTO productCategoryUpdateDTO) { public Boolean updateProductCategory(Integer adminId, ProductCategoryUpdateDTO productCategoryUpdateDTO) {
// 校验父分类 // 校验父分类
validParent(productCategoryUpdateDTO.getPid()); validParent(productCategoryUpdateDTO.getPid());
// 校验不能设置自己为父分类 // 校验不能设置自己为父分类
if (productCategoryUpdateDTO.getId().equals(productCategoryUpdateDTO.getPid())) { if (productCategoryUpdateDTO.getId().equals(productCategoryUpdateDTO.getPid())) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_PARENT_NOT_SELF.getCode()); throw ServiceExceptionUtil.exception(ProductErrorCodeEnum.PRODUCT_CATEGORY_PARENT_NOT_SELF.getCode());
} }
// 校验父分类是否存在 // 校验父分类是否存在
if (!ProductCategoryConstants.PID_ROOT.equals(productCategoryUpdateDTO.getPid()) if (!ProductCategoryConstants.PID_ROOT.equals(productCategoryUpdateDTO.getPid())
&& productCategoryMapper.selectById(productCategoryUpdateDTO.getPid()) == null) { && productCategoryMapper.selectById(productCategoryUpdateDTO.getPid()) == null) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_PARENT_NOT_EXISTS.getCode()); throw ServiceExceptionUtil.exception(ProductErrorCodeEnum.PRODUCT_CATEGORY_PARENT_NOT_EXISTS.getCode());
} }
// 更新到数据库 // 更新到数据库
ProductCategoryDO updateProductCategory = ProductCategoryConvert.INSTANCE.convert(productCategoryUpdateDTO); ProductCategoryDO updateProductCategory = ProductCategoryConvert.INSTANCE.convert(productCategoryUpdateDTO);
productCategoryMapper.update(updateProductCategory); productCategoryMapper.update(updateProductCategory);
// TODO 操作日志 // TODO 操作日志
return CommonResult.success(true); return true;
} }
@Override @Override
public CommonResult<Boolean> updateProductCategoryStatus(Integer adminId, Integer productCategoryId, Integer status) { public Boolean updateProductCategoryStatus(Integer adminId, Integer productCategoryId, Integer status) {
// 校验参数
if (!isValidStatus(status)) {
return CommonResult.error(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), "变更状态必须是开启(1)或关闭(2)"); // TODO 有点搓
}
// 校验分类是否存在 // 校验分类是否存在
ProductCategoryDO productCategory = productCategoryMapper.selectById(productCategoryId); ProductCategoryDO productCategory = productCategoryMapper.selectById(productCategoryId);
if (productCategory == null) { if (productCategory == null) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS.getCode()); throw ServiceExceptionUtil.exception(ProductErrorCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS.getCode());
} }
// 如果状态相同,则返回错误 // 如果状态相同,则返回错误
if (productCategory.getStatus().equals(status)) { if (productCategory.getStatus().equals(status)) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_STATUS_EQUALS.getCode()); throw ServiceExceptionUtil.exception(ProductErrorCodeEnum.PRODUCT_CATEGORY_STATUS_EQUALS.getCode());
} }
// 更新商品分类 // 更新商品分类
ProductCategoryDO updateProductCategory = new ProductCategoryDO() ProductCategoryDO updateProductCategory = new ProductCategoryDO()
.setId(productCategoryId).setStatus(status); .setId(productCategoryId).setStatus(status);
productCategoryMapper.update(updateProductCategory); productCategoryMapper.update(updateProductCategory);
// TODO 操作日志 // TODO 操作日志
return CommonResult.success(true); return true;
} }
@Override @Override
public CommonResult<Boolean> deleteProductCategory(Integer admin, Integer productCategoryId) { public Boolean deleteProductCategory(Integer admin, Integer productCategoryId) {
// 校验分类是否存在 // 校验分类是否存在
ProductCategoryDO productCategory = productCategoryMapper.selectById(productCategoryId); ProductCategoryDO productCategory = productCategoryMapper.selectById(productCategoryId);
if (productCategory == null) { if (productCategory == null) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS.getCode()); throw ServiceExceptionUtil.exception(ProductErrorCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS.getCode());
} }
// 只有禁用的商品分类才可以删除 // 只有禁用的商品分类才可以删除
if (ProductCategoryConstants.STATUS_ENABLE.equals(productCategory.getStatus())) { if (ProductCategoryConstants.STATUS_ENABLE.equals(productCategory.getStatus())) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_DELETE_ONLY_DISABLE.getCode()); throw ServiceExceptionUtil.exception(ProductErrorCodeEnum.PRODUCT_CATEGORY_DELETE_ONLY_DISABLE.getCode());
} }
// TODO 芋艿:考虑下,是否需要判断下该分类下是否有商品 // TODO 芋艿:考虑下,是否需要判断下该分类下是否有商品
// TODO 芋艿,需要补充下,还有子分类 // TODO 芋艿,需要补充下,还有子分类
...@@ -122,30 +116,25 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { ...@@ -122,30 +116,25 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
updateProductCategory.setDeleted(DeletedStatusEnum.DELETED_YES.getValue()); updateProductCategory.setDeleted(DeletedStatusEnum.DELETED_YES.getValue());
productCategoryMapper.update(updateProductCategory); productCategoryMapper.update(updateProductCategory);
// TODO 操作日志 // TODO 操作日志
return CommonResult.success(true); return true;
} }
public ProductCategoryDO getProductCategory(Integer productCategoryId) { public ProductCategoryDO getProductCategory(Integer productCategoryId) {
return productCategoryMapper.selectById(productCategoryId); return productCategoryMapper.selectById(productCategoryId);
} }
public CommonResult<ProductCategoryDO> validProductCategory(Integer productCategoryId) { public ProductCategoryDO validProductCategory(Integer productCategoryId) {
// 校验分类是否存在 // 校验分类是否存在
ProductCategoryDO productCategory = productCategoryMapper.selectById(productCategoryId); ProductCategoryDO productCategory = productCategoryMapper.selectById(productCategoryId);
if (productCategory == null) { if (productCategory == null) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS.getCode()); throw ServiceExceptionUtil.exception(ProductErrorCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS.getCode());
} }
// 只有禁用的商品分类才可以删除 // 只有禁用的商品分类才可以删除
if (ProductCategoryConstants.STATUS_DISABLE.equals(productCategory.getStatus())) { if (ProductCategoryConstants.STATUS_DISABLE.equals(productCategory.getStatus())) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_MUST_ENABLE.getCode()); throw ServiceExceptionUtil.exception(ProductErrorCodeEnum.PRODUCT_CATEGORY_MUST_ENABLE.getCode());
} }
// 返回结果 // 返回结果
return CommonResult.success(productCategory); return productCategory;
}
private boolean isValidStatus(Integer status) {
return ProductCategoryConstants.STATUS_ENABLE.equals(status)
|| ProductCategoryConstants.STATUS_DISABLE.equals(status);
} }
private void validParent(Integer pid) { private void validParent(Integer pid) {
......
...@@ -104,6 +104,12 @@ ...@@ -104,6 +104,12 @@
<if test="visible != null"> <if test="visible != null">
AND visible = #{visible} AND visible = #{visible}
</if> </if>
<if test="hasQuantity == true">
AND quantity > 0
</if>
<if test="hasQuantity == false">
AND quantity = 0
</if>
AND deleted = 0 AND deleted = 0
</where> </where>
ORDER BY sort ASC ORDER BY sort ASC
...@@ -124,6 +130,12 @@ ...@@ -124,6 +130,12 @@
<if test="visible != null"> <if test="visible != null">
AND visible = #{visible} AND visible = #{visible}
</if> </if>
<if test="hasQuantity == true">
AND quantity > 0
</if>
<if test="hasQuantity == false">
AND quantity = 0
</if>
AND deleted = 0 AND deleted = 0
</where> </where>
</select> </select>
......
...@@ -43,7 +43,7 @@ public class UsersProductRecommendController { ...@@ -43,7 +43,7 @@ public class UsersProductRecommendController {
null, CommonStatusEnum.ENABLE.getValue()).getData(); null, CommonStatusEnum.ENABLE.getValue()).getData();
// 获得商品集合 // 获得商品集合
List<ProductSpuBO> spus = productSpuService.getProductSpuList( List<ProductSpuBO> spus = productSpuService.getProductSpuList(
productRecommends.stream().map(ProductRecommendBO::getProductSpuId).collect(Collectors.toSet())).getData(); productRecommends.stream().map(ProductRecommendBO::getProductSpuId).collect(Collectors.toSet()));
Map<Integer, ProductSpuBO> spuMap = spus.stream().collect(Collectors.toMap(ProductSpuBO::getId, account -> account)); Map<Integer, ProductSpuBO> spuMap = spus.stream().collect(Collectors.toMap(ProductSpuBO::getId, account -> account));
// 组合结果,返回 // 组合结果,返回
Multimap<Integer, UsersProductRecommendVO> result = HashMultimap.create(); Multimap<Integer, UsersProductRecommendVO> result = HashMultimap.create();
......
...@@ -17,6 +17,8 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -17,6 +17,8 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.Collections; import java.util.Collections;
import static cn.iocoder.common.framework.vo.CommonResult.success;
@RestController @RestController
@RequestMapping("users/product") @RequestMapping("users/product")
@Api("商品搜索") @Api("商品搜索")
...@@ -39,7 +41,7 @@ public class UsersProductSearchController { ...@@ -39,7 +41,7 @@ public class UsersProductSearchController {
productSearchPageDTO.setSorts(Collections.singletonList(new SortingField(sortField, sortOrder))); productSearchPageDTO.setSorts(Collections.singletonList(new SortingField(sortField, sortOrder)));
} }
// 执行搜索 // 执行搜索
return productSearchService.getSearchPage(productSearchPageDTO); return success(productSearchService.getSearchPage(productSearchPageDTO));
} }
@GetMapping("/condition") // TODO 芋艿,后面把 BO 改成 VO @GetMapping("/condition") // TODO 芋艿,后面把 BO 改成 VO
...@@ -48,7 +50,7 @@ public class UsersProductSearchController { ...@@ -48,7 +50,7 @@ public class UsersProductSearchController {
ProductConditionDTO productConditionDTO = new ProductConditionDTO().setKeyword(keyword) ProductConditionDTO productConditionDTO = new ProductConditionDTO().setKeyword(keyword)
.setFields(Collections.singleton(ProductConditionDTO.FIELD_CATEGORY)); .setFields(Collections.singleton(ProductConditionDTO.FIELD_CATEGORY));
// 执行搜索 // 执行搜索
return productSearchService.getSearchCondition(productConditionDTO); return success(productSearchService.getSearchCondition(productConditionDTO));
} }
} }
package cn.iocoder.mall.search.api; package cn.iocoder.mall.search.api;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.search.api.bo.ProductConditionBO; import cn.iocoder.mall.search.api.bo.ProductConditionBO;
import cn.iocoder.mall.search.api.bo.ProductPageBO; import cn.iocoder.mall.search.api.bo.ProductPageBO;
import cn.iocoder.mall.search.api.dto.ProductConditionDTO; import cn.iocoder.mall.search.api.dto.ProductConditionDTO;
...@@ -8,7 +7,7 @@ import cn.iocoder.mall.search.api.dto.ProductSearchPageDTO; ...@@ -8,7 +7,7 @@ import cn.iocoder.mall.search.api.dto.ProductSearchPageDTO;
public interface ProductSearchService { public interface ProductSearchService {
CommonResult<Integer> rebuild(); Integer rebuild();
/** /**
* 构建商品的搜索索引 * 构建商品的搜索索引
...@@ -16,10 +15,10 @@ public interface ProductSearchService { ...@@ -16,10 +15,10 @@ public interface ProductSearchService {
* @param id 商品编号 * @param id 商品编号
* @return 构建结果 * @return 构建结果
*/ */
CommonResult<Boolean> save(Integer id); Boolean save(Integer id);
CommonResult<ProductPageBO> getSearchPage(ProductSearchPageDTO searchPageDTO); ProductPageBO getSearchPage(ProductSearchPageDTO searchPageDTO);
CommonResult<ProductConditionBO> getSearchCondition(ProductConditionDTO conditionDTO); ProductConditionBO getSearchCondition(ProductConditionDTO conditionDTO);
} }
package cn.iocoder.mall.search.biz.mq; package cn.iocoder.mall.search.biz.mq;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.product.api.message.ProductUpdateMessage; import cn.iocoder.mall.product.api.message.ProductUpdateMessage;
import cn.iocoder.mall.search.api.ProductSearchService; import cn.iocoder.mall.search.api.ProductSearchService;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
...@@ -21,8 +20,8 @@ public class PayTransactionPaySuccessConsumer implements RocketMQListener<Produc ...@@ -21,8 +20,8 @@ public class PayTransactionPaySuccessConsumer implements RocketMQListener<Produc
@Override @Override
public void onMessage(ProductUpdateMessage message) { public void onMessage(ProductUpdateMessage message) {
CommonResult<Boolean> result = productSearchService.save(message.getId()); Boolean result = productSearchService.save(message.getId());
Assert.isTrue(result.isSuccess(), String.format("重构商品 ES 索引,必然成功。实际结果是 %s", result)); Assert.isTrue(result, String.format("重构商品 ES 索引,必然成功。实际结果是 %s", result));
} }
} }
...@@ -55,14 +55,12 @@ public class ProductSearchServiceImpl implements ProductSearchService { ...@@ -55,14 +55,12 @@ public class ProductSearchServiceImpl implements ProductSearchService {
private CartService cartService; private CartService cartService;
@Override @Override
public CommonResult<Integer> rebuild() { public Integer rebuild() {
// TODO 芋艿,因为目前商品比较少,所以写的很粗暴。等未来重构 // TODO 芋艿,因为目前商品比较少,所以写的很粗暴。等未来重构
Integer lastId = null; Integer lastId = null;
int rebuildCounts = 0; int rebuildCounts = 0;
while (true) { while (true) {
CommonResult<List<ProductSpuDetailBO>> result = productSpuService.getProductSpuDetailListForSync(lastId, REBUILD_FETCH_PER_SIZE); List<ProductSpuDetailBO> spus = productSpuService.getProductSpuDetailListForSync(lastId, REBUILD_FETCH_PER_SIZE);
Assert.isTrue(result.isSuccess(), "获得商品列表必然成功");
List<ProductSpuDetailBO> spus = result.getData();
rebuildCounts += spus.size(); rebuildCounts += spus.size();
// 存储到 ES 中 // 存储到 ES 中
List<ESProductDO> products = spus.stream().map(this::convert).collect(Collectors.toList()); List<ESProductDO> products = spus.stream().map(this::convert).collect(Collectors.toList());
...@@ -75,19 +73,18 @@ public class ProductSearchServiceImpl implements ProductSearchService { ...@@ -75,19 +73,18 @@ public class ProductSearchServiceImpl implements ProductSearchService {
} }
} }
// 返回成功 // 返回成功
return CommonResult.success(rebuildCounts); return rebuildCounts;
} }
@Override @Override
public CommonResult<Boolean> save(Integer id) { public Boolean save(Integer id) {
// 获得商品性情 // 获得商品性情
CommonResult<ProductSpuDetailBO> result = productSpuService.getProductSpuDetail(id); ProductSpuDetailBO result = productSpuService.getProductSpuDetail(id);
Assert.isTrue(result.isSuccess(), "获得商品详情必然成功");
// 存储到 ES 中 // 存储到 ES 中
ESProductDO product = convert(result.getData()); ESProductDO product = convert(result);
productRepository.save(product); productRepository.save(product);
// 返回成功 // 返回成功
return CommonResult.success(Boolean.TRUE); return true;
} }
@SuppressWarnings("OptionalGetWithoutIsPresent") @SuppressWarnings("OptionalGetWithoutIsPresent")
...@@ -102,16 +99,15 @@ public class ProductSearchServiceImpl implements ProductSearchService { ...@@ -102,16 +99,15 @@ public class ProductSearchServiceImpl implements ProductSearchService {
} }
@Override @Override
public CommonResult<ProductPageBO> getSearchPage(ProductSearchPageDTO searchPageDTO) { public ProductPageBO getSearchPage(ProductSearchPageDTO searchPageDTO) {
checkSortFieldInvalid(searchPageDTO.getSorts()); checkSortFieldInvalid(searchPageDTO.getSorts());
// 执行查询 // 执行查询
Page<ESProductDO> searchPage = productRepository.search(searchPageDTO.getCid(), searchPageDTO.getKeyword(), Page<ESProductDO> searchPage = productRepository.search(searchPageDTO.getCid(), searchPageDTO.getKeyword(),
searchPageDTO.getPageNo(), searchPageDTO.getPageSize(), searchPageDTO.getSorts()); searchPageDTO.getPageNo(), searchPageDTO.getPageSize(), searchPageDTO.getSorts());
// 转换结果 // 转换结果
ProductPageBO resultPage = new ProductPageBO() return new ProductPageBO()
.setList(ProductSearchConvert.INSTANCE.convert(searchPage.getContent())) .setList(ProductSearchConvert.INSTANCE.convert(searchPage.getContent()))
.setTotal((int) searchPage.getTotalElements()); .setTotal((int) searchPage.getTotalElements());
return CommonResult.success(resultPage);
} }
private void checkSortFieldInvalid(List<SortingField> sorts) { private void checkSortFieldInvalid(List<SortingField> sorts) {
...@@ -123,7 +119,7 @@ public class ProductSearchServiceImpl implements ProductSearchService { ...@@ -123,7 +119,7 @@ public class ProductSearchServiceImpl implements ProductSearchService {
} }
@Override @Override
public CommonResult<ProductConditionBO> getSearchCondition(ProductConditionDTO conditionDTO) { public ProductConditionBO getSearchCondition(ProductConditionDTO conditionDTO) {
// 创建 ES 搜索条件 // 创建 ES 搜索条件
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder(); NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
// 筛选 // 筛选
...@@ -161,7 +157,7 @@ public class ProductSearchServiceImpl implements ProductSearchService { ...@@ -161,7 +157,7 @@ public class ProductSearchServiceImpl implements ProductSearchService {
condition.getCategories().forEach(category -> category.setName(categoryMap.get(category.getId()).getName())); condition.getCategories().forEach(category -> category.setName(categoryMap.get(category.getId()).getName()));
} }
// 返回结果 // 返回结果
return CommonResult.success(condition); return condition;
} }
} }
...@@ -18,7 +18,7 @@ public class ProductSearchServiceImplTest { ...@@ -18,7 +18,7 @@ public class ProductSearchServiceImplTest {
@Test @Test
public void testRebuild() { public void testRebuild() {
int counts = productSearchService.rebuild().getData(); int counts = productSearchService.rebuild();
System.out.println("重建数量:" + counts); System.out.println("重建数量:" + counts);
System.out.println(productRepository.count()); System.out.println(productRepository.count());
......
...@@ -33,7 +33,7 @@ public class AdminAccessLogInterceptor extends HandlerInterceptorAdapter { ...@@ -33,7 +33,7 @@ public class AdminAccessLogInterceptor extends HandlerInterceptorAdapter {
*/ */
private static final ThreadLocal<Integer> ADMIN_ID = new ThreadLocal<>(); private static final ThreadLocal<Integer> ADMIN_ID = new ThreadLocal<>();
@Reference(lazy = true) @Reference(validation = "true")
@Autowired(required = false) // TODO 芋艿,初始化时,会存在 spring boot 启动时,服务无法引用的情况,先暂时这么解决。 @Autowired(required = false) // TODO 芋艿,初始化时,会存在 spring boot 启动时,服务无法引用的情况,先暂时这么解决。
private AdminAccessLogService adminAccessLogService; private AdminAccessLogService adminAccessLogService;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论