共富商城
This commit is contained in:
1 parent
49a5a7161d
commit
056bb95229
9 files changed
+370
-19
No files matched your search
+6
@@ -113,4 +113,10 @@ public class MallCategoryEntity extends Model<MallCategoryEntity> {
|
||||
*/
|
||||
@Schema(description="租户编号")
|
||||
private Long tenantId;
|
||||
|
||||
/**
|
||||
* 商户ID
|
||||
*/
|
||||
@Schema(description="商户ID")
|
||||
private Long merchantId;
|
||||
}
|
||||
+1
@@ -95,3 +95,4 @@ public interface MallConstants {
|
||||
}
|
||||
|
||||
|
||||
|
||||
+228
-14
@@ -27,6 +27,7 @@ import com.bsd.pjcloud.supermarket.vo.mall.MallCategoryTreeVo;
|
||||
import com.bsd.pjcloud.supermarket.vo.app.MallProductListAppVo;
|
||||
import com.bsd.pjcloud.supermarket.vo.app.MallProductDetailAppVo;
|
||||
import com.bsd.pjcloud.supermarket.vo.app.MallProductSkuAppVo;
|
||||
import com.bsd.pjcloud.supermarket.vo.app.MallMerchantListAppVo;
|
||||
import com.bsd.pjcloud.supermarket.dto.SkuStockChangeDTO;
|
||||
import com.bsd.pjcloud.supermarket.constant.MallConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@@ -35,6 +36,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springdoc.core.annotations.ParameterObject;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -67,9 +69,12 @@ public class MallAppController {
|
||||
*/
|
||||
@GetMapping("/category/tree")
|
||||
@Operation(summary = "获取分类树", description = "获取所有分类的树结构")
|
||||
public R<List<MallCategoryTreeVo>> getCategoryTree() {
|
||||
List<MallCategoryEntity> all = mallCategoryService.list(Wrappers.<MallCategoryEntity>lambdaQuery()
|
||||
.eq(MallCategoryEntity::getStatus, 1)); // 只查启用状态
|
||||
public R<List<MallCategoryTreeVo>> getCategoryTree(@RequestParam(required = false) Long merchantId) {
|
||||
LambdaQueryWrapper<MallCategoryEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(MallCategoryEntity::getStatus, 1); // 只查启用状态
|
||||
// 添加商户ID过滤条件
|
||||
wrapper.eq(merchantId != null, MallCategoryEntity::getMerchantId, merchantId);
|
||||
List<MallCategoryEntity> all = mallCategoryService.list(wrapper);
|
||||
List<MallCategoryTreeVo> tree = buildCategoryTree(all, 0L);
|
||||
return R.ok(tree);
|
||||
}
|
||||
@@ -79,12 +84,13 @@ public class MallAppController {
|
||||
*/
|
||||
@GetMapping("/category/listByParent/{parentId}")
|
||||
@Operation(summary = "根据父级ID获取子分类", description = "根据父级ID获取子分类列表")
|
||||
public R<List<MallCategoryEntity>> getCategoryListByParent(@PathVariable("parentId") Long parentId) {
|
||||
List<MallCategoryEntity> list = mallCategoryService.list(
|
||||
Wrappers.<MallCategoryEntity>lambdaQuery()
|
||||
.eq(MallCategoryEntity::getParentId, parentId)
|
||||
.eq(MallCategoryEntity::getStatus, 1)
|
||||
);
|
||||
public R<List<MallCategoryEntity>> getCategoryListByParent(@PathVariable("parentId") Long parentId, @RequestParam(required = false) Long merchantId) {
|
||||
LambdaQueryWrapper<MallCategoryEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(MallCategoryEntity::getParentId, parentId);
|
||||
wrapper.eq(MallCategoryEntity::getStatus, 1);
|
||||
// 添加商户ID过滤条件
|
||||
wrapper.eq(merchantId != null, MallCategoryEntity::getMerchantId, merchantId);
|
||||
List<MallCategoryEntity> list = mallCategoryService.list(wrapper);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
@@ -94,14 +100,112 @@ public class MallAppController {
|
||||
* 获取商户列表
|
||||
*/
|
||||
@GetMapping("/merchant/list")
|
||||
@Operation(summary = "获取商户列表", description = "获取所有启用的商户列表")
|
||||
public R<List<MallMerchantEntity>> getMerchantList() {
|
||||
List<MallMerchantEntity> list = mallMerchantService.list(
|
||||
@Operation(summary = "获取商户列表", description = "获取所有启用的商户列表,包含特色商品")
|
||||
public R<List<MallMerchantListAppVo>> getMerchantList(@RequestParam(defaultValue = "3") Integer productLimit) {
|
||||
// 查询所有启用的商户
|
||||
List<MallMerchantEntity> merchants = mallMerchantService.list(
|
||||
Wrappers.<MallMerchantEntity>lambdaQuery()
|
||||
.eq(MallMerchantEntity::getStatus, 1)
|
||||
.eq(MallMerchantEntity::getStatus, MallConstants.Status.ENABLED)
|
||||
.orderByAsc(MallMerchantEntity::getName)
|
||||
);
|
||||
return R.ok(list);
|
||||
|
||||
if (merchants.isEmpty()) {
|
||||
return R.ok(List.of());
|
||||
}
|
||||
|
||||
// 获取商户ID列表
|
||||
List<Long> merchantIds = merchants.stream()
|
||||
.map(MallMerchantEntity::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 查询每个商户的特色商品(按创建时间倒序,取前N个)
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
List<MallProductEntity> products = mallProductService.list(
|
||||
Wrappers.<MallProductEntity>lambdaQuery()
|
||||
.in(MallProductEntity::getMerchantId, merchantIds)
|
||||
.eq(MallProductEntity::getStatus, MallConstants.Status.ENABLED) // 只查上架商品
|
||||
.and(wrapper -> wrapper
|
||||
.isNull(MallProductEntity::getSaleStartTime)
|
||||
.or()
|
||||
.le(MallProductEntity::getSaleStartTime, now)
|
||||
)
|
||||
.and(wrapper -> wrapper
|
||||
.isNull(MallProductEntity::getSaleEndTime)
|
||||
.or()
|
||||
.ge(MallProductEntity::getSaleEndTime, now)
|
||||
)
|
||||
.orderByDesc(MallProductEntity::getCreateTime)
|
||||
);
|
||||
|
||||
// 按商户ID分组商品
|
||||
Map<Long, List<MallProductEntity>> productMap = products.stream()
|
||||
.collect(Collectors.groupingBy(MallProductEntity::getMerchantId));
|
||||
|
||||
// 获取商品ID列表,查询SKU信息
|
||||
List<Long> productIds = products.stream()
|
||||
.map(MallProductEntity::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<MallProductSkuEntity> skuList = productIds.isEmpty() ? List.of() :
|
||||
mallProductSkuService.list(
|
||||
Wrappers.<MallProductSkuEntity>lambdaQuery()
|
||||
.in(MallProductSkuEntity::getProductId, productIds)
|
||||
);
|
||||
|
||||
// 按商品ID分组SKU
|
||||
Map<Long, List<MallProductSkuEntity>> skuMap = skuList.stream()
|
||||
.collect(Collectors.groupingBy(MallProductSkuEntity::getProductId));
|
||||
|
||||
// 转换为VO
|
||||
List<MallMerchantListAppVo> result = merchants.stream().map(merchant -> {
|
||||
MallMerchantListAppVo vo = BeanUtils.toBean(merchant, MallMerchantListAppVo.class);
|
||||
|
||||
// 获取该商户的商品列表
|
||||
List<MallProductEntity> merchantProducts = productMap.getOrDefault(merchant.getId(), List.of());
|
||||
|
||||
// 设置商品总数
|
||||
vo.setProductCount(merchantProducts.size());
|
||||
|
||||
// 获取特色商品(限制数量)
|
||||
List<MallProductListAppVo> featuredProducts = merchantProducts.stream()
|
||||
.limit(productLimit)
|
||||
.map(product -> {
|
||||
MallProductListAppVo productVo = BeanUtils.toBean(product, MallProductListAppVo.class);
|
||||
List<MallProductSkuEntity> skus = skuMap.getOrDefault(product.getId(), List.of());
|
||||
|
||||
// 计算最低价格
|
||||
productVo.setMinPrice(skus.stream()
|
||||
.map(MallProductSkuEntity::getPrice)
|
||||
.filter(Objects::nonNull)
|
||||
.min(java.math.BigDecimal::compareTo)
|
||||
.orElse(java.math.BigDecimal.ZERO));
|
||||
|
||||
// 计算总库存
|
||||
productVo.setTotalStock(skus.stream()
|
||||
.map(MallProductSkuEntity::getStock)
|
||||
.filter(Objects::nonNull)
|
||||
.mapToInt(Integer::intValue)
|
||||
.sum());
|
||||
|
||||
|
||||
return productVo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
vo.setFeaturedProducts(featuredProducts);
|
||||
|
||||
// 设置商户营业时间
|
||||
if (merchant.getBusinessHours() != null && !merchant.getBusinessHours().trim().isEmpty()) {
|
||||
vo.setBusinessHours(merchant.getBusinessHours());
|
||||
} else {
|
||||
// 默认商户营业时间
|
||||
vo.setBusinessHours("10:00-22:00");
|
||||
}
|
||||
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -427,6 +531,116 @@ public class MallAppController {
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 商户分类管理接口 ====================
|
||||
|
||||
/**
|
||||
* 商户创建分类
|
||||
*/
|
||||
@PostMapping("/merchant/category/create")
|
||||
@Operation(summary = "商户创建分类", description = "移动端商户创建分类")
|
||||
public R<String> createCategory(@RequestBody MallCategoryEntity category) {
|
||||
try {
|
||||
Long merchantId = validateMerchant();
|
||||
// 自动设置商户ID
|
||||
category.setMerchantId(merchantId);
|
||||
category.setDeptId(SecurityUtils.getUser().getDeptId());
|
||||
|
||||
// 创建分类
|
||||
boolean success = mallCategoryService.save(category);
|
||||
if (success) {
|
||||
return R.ok("分类创建成功");
|
||||
} else {
|
||||
return R.failed("分类创建失败");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return R.failed("分类创建失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户更新分类
|
||||
*/
|
||||
@PutMapping("/merchant/category/update")
|
||||
@Operation(summary = "商户更新分类", description = "移动端商户更新分类")
|
||||
public R<String> updateCategory(@RequestBody MallCategoryEntity category) {
|
||||
try {
|
||||
Long merchantId = validateMerchant();
|
||||
// 验证分类权限
|
||||
validateCategoryPermission(category.getId(), merchantId);
|
||||
|
||||
// 验证分类ID
|
||||
if (category.getId() == null) {
|
||||
return R.failed("分类ID不能为空");
|
||||
}
|
||||
|
||||
// 更新分类
|
||||
boolean success = mallCategoryService.updateById(category);
|
||||
if (success) {
|
||||
return R.ok("分类更新成功");
|
||||
} else {
|
||||
return R.failed("分类更新失败");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return R.failed("分类更新失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户删除分类
|
||||
*/
|
||||
@DeleteMapping("/merchant/category/{id}")
|
||||
@Operation(summary = "商户删除分类", description = "移动端商户删除自己的分类")
|
||||
public R<String> deleteCategory(@PathVariable("id") Long id) {
|
||||
try {
|
||||
Long merchantId = validateMerchant();
|
||||
validateCategoryPermission(id, merchantId);
|
||||
|
||||
// 删除分类(逻辑删除)
|
||||
boolean success = mallCategoryService.removeById(id);
|
||||
if (success) {
|
||||
return R.ok("分类删除成功");
|
||||
} else {
|
||||
return R.failed("分类删除失败");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return R.failed("分类删除失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户获取自己的分类列表
|
||||
*/
|
||||
@GetMapping("/merchant/category/list")
|
||||
@Operation(summary = "商户分类列表", description = "移动端商户获取自己的分类列表")
|
||||
public R<List<MallCategoryEntity>> getMerchantCategoryList(@RequestParam(required = false) Long parentId) {
|
||||
try {
|
||||
Long merchantId = validateMerchant();
|
||||
|
||||
LambdaQueryWrapper<MallCategoryEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(MallCategoryEntity::getMerchantId, merchantId);
|
||||
wrapper.eq(parentId != null, MallCategoryEntity::getParentId, parentId);
|
||||
wrapper.orderByAsc(MallCategoryEntity::getSort);
|
||||
|
||||
List<MallCategoryEntity> list = mallCategoryService.list(wrapper);
|
||||
return R.ok(list);
|
||||
} catch (Exception e) {
|
||||
return R.failed("获取分类列表失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证是否有处理该条分类数据的权限
|
||||
*/
|
||||
private void validateCategoryPermission(Long categoryId, Long merchantId) {
|
||||
MallCategoryEntity category = mallCategoryService.getById(categoryId);
|
||||
if (category == null) {
|
||||
throw new BusinessException("分类不存在");
|
||||
}
|
||||
if (!merchantId.equals(category.getMerchantId())) {
|
||||
throw new BusinessException("无权限处理此分类");
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 库存相关接口 ====================
|
||||
|
||||
/**
|
||||
|
||||
+25
-5
@@ -52,6 +52,8 @@ public class MallCategoryController {
|
||||
public R getMallCategoryPage(@ParameterObject Page page, @ParameterObject MallCategoryEntity MallCategory) {
|
||||
LambdaQueryWrapper<MallCategoryEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(StrUtil.isNotBlank(MallCategory.getName()),MallCategoryEntity::getName,MallCategory.getName());
|
||||
// 添加商户ID过滤条件
|
||||
wrapper.eq(MallCategory.getMerchantId() != null, MallCategoryEntity::getMerchantId, MallCategory.getMerchantId());
|
||||
return R.ok(MallCategoryService.pageScope(page, wrapper));
|
||||
}
|
||||
|
||||
@@ -79,6 +81,13 @@ public class MallCategoryController {
|
||||
@PreAuthorize("@pms.hasPermission('supermarket_mallCategory_add')" )
|
||||
public R save(@RequestBody MallCategoryEntity MallCategory) {
|
||||
MallCategory.setDeptId(SecurityUtils.getUser().getDeptId());
|
||||
// 设置商户ID
|
||||
if (MallCategory.getMerchantId() == null) {
|
||||
return R.failed("商户ID不能为空");
|
||||
}
|
||||
// 如果前端没有传商户ID,可以从当前用户信息中获取
|
||||
// 这里需要根据实际业务逻辑来设置,可能需要从用户关联的商户信息中获取
|
||||
// MallCategory.setMerchantId(getCurrentUserMerchantId());
|
||||
return R.ok(MallCategoryService.save(MallCategory));
|
||||
}
|
||||
|
||||
@@ -119,7 +128,11 @@ public class MallCategoryController {
|
||||
@GetMapping("/export")
|
||||
@PreAuthorize("@pms.hasPermission('supermarket_mallCategory_export')" )
|
||||
public List<MallCategoryEntity> export(MallCategoryEntity MallCategory,Long[] ids) {
|
||||
return MallCategoryService.list(Wrappers.lambdaQuery(MallCategory).in(ArrayUtil.isNotEmpty(ids), MallCategoryEntity::getId, ids));
|
||||
LambdaQueryWrapper<MallCategoryEntity> wrapper = Wrappers.lambdaQuery(MallCategory);
|
||||
wrapper.in(ArrayUtil.isNotEmpty(ids), MallCategoryEntity::getId, ids);
|
||||
// 添加商户ID过滤条件
|
||||
wrapper.eq(MallCategory.getMerchantId() != null, MallCategoryEntity::getMerchantId, MallCategory.getMerchantId());
|
||||
return MallCategoryService.list(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,8 +140,11 @@ public class MallCategoryController {
|
||||
*/
|
||||
@GetMapping("/tree")
|
||||
@Operation(summary = "分类树", description = "获取所有分类的树结构")
|
||||
public R<List<MallCategoryTreeVo>> tree() {
|
||||
List<MallCategoryEntity> all = MallCategoryService.listScope();
|
||||
public R<List<MallCategoryTreeVo>> tree(@RequestParam(required = false) Long merchantId) {
|
||||
LambdaQueryWrapper<MallCategoryEntity> wrapper = Wrappers.lambdaQuery();
|
||||
// 添加商户ID过滤条件
|
||||
wrapper.eq(merchantId != null, MallCategoryEntity::getMerchantId, merchantId);
|
||||
List<MallCategoryEntity> all = MallCategoryService.list(wrapper);
|
||||
List<MallCategoryTreeVo> tree = buildCategoryTree(all, 0L);
|
||||
return R.ok(tree);
|
||||
}
|
||||
@@ -150,8 +166,12 @@ public class MallCategoryController {
|
||||
*/
|
||||
@GetMapping("/listByParent/{parentId}")
|
||||
@Operation(summary = "根据父级ID查子分类", description = "根据父级ID查子分类")
|
||||
public R<List<MallCategoryEntity>> listByParent(@PathVariable("parentId") Long parentId) {
|
||||
List<MallCategoryEntity> list = MallCategoryService.list(Wrappers.<MallCategoryEntity>lambdaQuery().eq(MallCategoryEntity::getParentId, parentId));
|
||||
public R<List<MallCategoryEntity>> listByParent(@PathVariable("parentId") Long parentId, @RequestParam(required = false) Long merchantId) {
|
||||
LambdaQueryWrapper<MallCategoryEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(MallCategoryEntity::getParentId, parentId);
|
||||
// 添加商户ID过滤条件
|
||||
wrapper.eq(merchantId != null, MallCategoryEntity::getMerchantId, merchantId);
|
||||
List<MallCategoryEntity> list = MallCategoryService.list(wrapper);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -89,6 +89,12 @@ public class MallMerchantEntity extends Model<MallMerchantEntity> {
|
||||
@Schema(description="备注")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 营业时间(格式:HH:mm-HH:mm,如:10:30-22:00)
|
||||
*/
|
||||
@Schema(description="营业时间(格式:HH:mm-HH:mm)")
|
||||
private String businessHours;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
|
||||
+1
@@ -83,3 +83,4 @@ public class MallMerchantUserVo {
|
||||
}
|
||||
|
||||
|
||||
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
package com.bsd.pjcloud.supermarket.vo.app;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 移动端商户列表VO
|
||||
*
|
||||
* @author zjf
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "移动端商户列表VO")
|
||||
public class MallMerchantListAppVo {
|
||||
|
||||
/**
|
||||
* 商户ID
|
||||
*/
|
||||
@Schema(description = "商户ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 商户名称
|
||||
*/
|
||||
@Schema(description = "商户名称")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 商户简称
|
||||
*/
|
||||
@Schema(description = "商户简称")
|
||||
private String shortName;
|
||||
|
||||
/**
|
||||
* 联系人
|
||||
*/
|
||||
@Schema(description = "联系人")
|
||||
private String contactName;
|
||||
|
||||
/**
|
||||
* 联系电话
|
||||
*/
|
||||
@Schema(description = "联系电话")
|
||||
private String contactPhone;
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
@Schema(description = "邮箱")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 状态(1启用 0停用)
|
||||
*/
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 营业执照号
|
||||
*/
|
||||
@Schema(description = "营业执照号")
|
||||
private String licenseNo;
|
||||
|
||||
/**
|
||||
* 详细地址
|
||||
*/
|
||||
@Schema(description = "详细地址")
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* 商户图片URL(逗号分隔)
|
||||
*/
|
||||
@Schema(description = "商户图片URL")
|
||||
private String images;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 特色商品列表(最多显示3个)
|
||||
*/
|
||||
@Schema(description = "特色商品列表")
|
||||
private List<MallProductListAppVo> featuredProducts;
|
||||
|
||||
/**
|
||||
* 商品总数
|
||||
*/
|
||||
@Schema(description = "商品总数")
|
||||
private Integer productCount;
|
||||
|
||||
/**
|
||||
* 商户营业时间(格式:HH:mm-HH:mm,如:10:30-22:00)
|
||||
*/
|
||||
@Schema(description = "商户营业时间")
|
||||
private String businessHours;
|
||||
}
|
||||
+1
@@ -104,5 +104,6 @@ public class MallProductListAppVo {
|
||||
*/
|
||||
@Schema(description = "最低价格")
|
||||
private BigDecimal minPrice;
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -18,5 +18,6 @@
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="delFlag" column="del_flag"/>
|
||||
<result property="tenantId" column="tenant_id"/>
|
||||
<result property="merchantId" column="merchant_id"/>
|
||||
</resultMap>
|
||||
</mapper>
|
||||
Reference in new issue
Block a user