043 商品详情
文章目录
- 详情页数据
- 表结构
- vo
- SkuItemVo.java
- SkuItemSaleAttrVo.java
- AttrValueAndSkuIdVo.java
- SpuAttrGroupVo.java
- GroupAttrParamVo.java
- pom.xml
- SkuSaleAttrValueDao.xml
- SkuSaleAttrValueDao.java
- AttrGroupDao.xml
- AttrGroupServiceImpl.java
- SkuInfoServiceImpl.java
- SkuSaleAttrValueServiceImpl.java
- AttrGroupDao.java
- SkuSaleAttrValueDao.java
- SkuItemController.java
- 默认
- 点击选中
详情页数据
1.sku基本信息
2.sku图片信息(多个图片)
3.spu的销售属性
4.spu的描述信息
5.sku分组规格参数属性值
表结构
vo
SkuItemVo.java
package com.xd.cubemall.product.vo;
import com.xd.cubemall.product.entity.SkuImagesEntity;
import com.xd.cubemall.product.entity.SkuInfoEntity;
import com.xd.cubemall.product.entity.SpuInfoDescEntity;
import lombok.Data;
import lombok.ToString;
import java.util.List;
@ToString
@Data
public class SkuItemVo {
//1.sku基本信息
private SkuInfoEntity info;
//2.sku图片信息
private List<SkuImagesEntity> images;
//3.spu的销售属性组合
private List<SkuItemSaleAttrVo> attrSales;
//4.spu描述信息
private SpuInfoDescEntity desc;
//5.spu分组(主体,基本信息...)规格属性
private List<SpuAttrGroupVo> attrGroups;
}
SkuItemSaleAttrVo.java
package com.xd.cubemall.product.vo;
import lombok.Data;
import lombok.ToString;
import java.util.List;
@ToString
@Data
public class SkuItemSaleAttrVo {
private Long attrId;
private String attrName;
//属性值
private List<AttrValueAndSkuIdVo> attrValues;
}
AttrValueAndSkuIdVo.java
package com.xd.cubemall.product.vo;
import lombok.Data;
import lombok.ToString;
@ToString
@Data
public class AttrValueAndSkuIdVo {
// skuids组合id
private String skuIds;
// 属性值: 白色,128G
private String attrValue;
}
SpuAttrGroupVo.java
package com.xd.cubemall.product.vo;
import lombok.Data;
import lombok.ToString;
import java.util.List;
@ToString
@Data
public class SpuAttrGroupVo {
private String groupName;
// 属性参数
private List<Attr> attrs;
}
GroupAttrParamVo.java
package com.xd.cubemall.product.vo;
import lombok.Data;
import lombok.ToString;
@ToString
@Data
public class GroupAttrParamVo {
private Long spuId;
private Long categoryId;
}
pom.xml
<!--添加模板技术渲染页面-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
在MySQL中,当启用了ONLY_FULL_GROUP_BY SQL模式时,如果一个SELECT查询包含聚合函数(如GROUP_CONCAT),那么所有非聚合的列都必须在GROUP BY子句中明确指定。这是因为ONLY_FULL_GROUP_BY模式要求所有的结果列要么是通过聚合函数处理的,要么是在GROUP BY子句中明确指定的。
从错误信息来看,查询试图在不使用GROUP BY子句的情况下选择非聚合列v.attr_id、v.attr_name和v.attr_value,同时还使用了聚合函数GROUP_CONCAT(v.sku_id)。这违反了ONLY_FULL_GROUP_BY的规则。
为了解决这个问题,需要修改查询,添加一个GROUP BY子句,包含所有非聚合的列。这样,每个组都会有唯一的attr_id、attr_name和attr_value,而GROUP_CONCAT则会将同一组内的sku_id连接起来。
SkuSaleAttrValueDao.xml
<resultMap id="spuSaleAttrMap" type="com.xd.cubemall.product.vo.SkuItemSaleAttrVo">
<result property="attrId" column="attr_id"></result>
<result property="attrName" column="attr_name"></result>
<collection property="attrValues" ofType="com.xd.cubemall.product.vo.AttrValueAndSkuIdVo">
<result property="skuIds" column="skuIds"></result>
<result property="attrValue" column="attr_value"></result>
</collection>
</resultMap>
<!--sql: tb_sku_info,tb_sku_sale_attr_value-->
<select id="getSaleAttrs" resultMap="spuSaleAttrMap" parameterType="java.lang.Long">
SELECT
v.attr_id,
v.attr_name,
v.attr_value,
GROUP_CONCAT( v.sku_id ) AS skuIds
FROM
tb_sku_info i
LEFT JOIN tb_sku_sale_attr_value v ON i.id = v.sku_id
WHERE
spu_id = #{spuId}
GROUP BY
v.attr_id,
v.attr_name,
v.attr_value;
</select>
SkuSaleAttrValueDao.java
package com.xd.cubemall.product.dao;
import com.xd.cubemall.product.entity.SkuSaleAttrValueEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xd.cubemall.product.vo.SkuItemSaleAttrVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* sku销售属性值
*
* @author xuedong
* @email email@gmail.com
* @date 2024-08-13 01:36:04
*/
@Mapper
public interface SkuSaleAttrValueDao extends BaseMapper<SkuSaleAttrValueEntity> {
public List<SkuItemSaleAttrVo> getSaleAttrs(Long spuId);
}
AttrGroupDao.xml
<resultMap id="spuAttrGroupMap" type="com.xd.cubemall.product.vo.SpuAttrGroupVo">
<result property="groupName" column="groupName"></result>
<collection property="attrs" ofType="com.xd.cubemall.product.vo.Attr">
<result property="attrName" column="attrName"></result>
<result property="attrValue" column="attrValue"></result>
</collection>
</resultMap>
<!--SQL: 根据spuID,categoryId 查询 sku分组规格参数属性值-->
<select id="getGroupAttr" resultMap="spuAttrGroupMap" parameterType="com.xd.cubemall.product.vo.GroupAttrParamVo">
SELECT
g.NAME AS groupName,
v.attr_name AS attrName,
v.attr_value AS attrValue
FROM
tb_product_attr_value v
JOIN tb_attr_attrgroup_relation r ON v.attr_id = r.attr_id
JOIN tb_attr_group g ON r.attr_group_id = g.id
WHERE
spu_id = #{spuId}
AND g.category_id = #{categoryId}
</select>
AttrGroupServiceImpl.java
//根据spuID,categoryId 查询 sku分组规格参数属性值
@Override
public List<SpuAttrGroupVo> getGroupAttr(Long spuId, Long categoryId) {
GroupAttrParamVo paramVo = new GroupAttrParamVo();
paramVo.setSpuId(spuId);
paramVo.setCategoryId(categoryId);
List<SpuAttrGroupVo> attrGroupVos = this.baseMapper.getGroupAttr(paramVo);
return attrGroupVos;
}
SkuInfoServiceImpl.java
@Autowired
private SkuImagesService skuImagesService;
//注入销售属性组合服务
@Autowired
private SkuSaleAttrValueService skuSaleAttrValueService;
//注入spu描述服务
@Autowired
private SpuInfoDescService spuInfoDescService;
@Autowired
private AttrGroupService attrGroupService;
@Override
public SkuItemVo skuItem(Long skuId) {
// 新建一个包装类对象
SkuItemVo itemVo = new SkuItemVo();
/*
1.sku基本信息
2.sku图片信息(多个图片)
3.spu的销售属性
4.spu的描述信息
5.sku分组规格参数属性值
*/
// 1.根据skuId 查询 sku基本信息
SkuInfoEntity skuInfoEntity = this.getById(skuId);
itemVo.setInfo(skuInfoEntity);
// 获取sku与之对应的spuId
Long spuId = skuInfoEntity.getSpuId();
// 获取分类id
Long categoryId = skuInfoEntity.getCategoryId();
// 2.根据skuId查询sku图片信息(多个图片),skuId是外键
List<SkuImagesEntity> imageList = skuImagesService.list(new QueryWrapper<SkuImagesEntity>().eq("sku_id", skuId));
itemVo.setImages(imageList);
//3.根据spuID获取spu的销售属性
List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrs(spuId);
itemVo.setAttrSales(saleAttrVos);
//4.根据spuId查询spu的描述信息
SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getOne(new QueryWrapper<SpuInfoDescEntity>().eq("spu_id",spuId));
itemVo.setDesc(spuInfoDescEntity);
//5.根据spuID,categoryId查询 sku分组规格参数属性值
List<SpuAttrGroupVo> attrGroupVos = attrGroupService.getGroupAttr(spuId,categoryId);
itemVo.setAttrGroups(attrGroupVos);
return itemVo;
}
SkuSaleAttrValueServiceImpl.java
/**
* 根据id查询销售属性组合
* @param spuId
* @return
*/
@Override
public List<SkuItemSaleAttrVo> getSaleAttrs(Long spuId) {
//List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrs(spuId);
List<SkuItemSaleAttrVo> saleAttrVos = this.baseMapper.getSaleAttrs(spuId);
return saleAttrVos;
}
AttrGroupDao.java
package com.xd.cubemall.product.dao;
import com.xd.cubemall.product.entity.AttrGroupEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xd.cubemall.product.vo.GroupAttrParamVo;
import com.xd.cubemall.product.vo.SpuAttrGroupVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 属性分组表
*
* @author xuedong
* @email email@gmail.com
* @date 2024-08-13 01:36:04
*/
@Mapper
public interface AttrGroupDao extends BaseMapper<AttrGroupEntity> {
//根据spuID,categoryId 查询 sku分组规格参数属性值
public List<SpuAttrGroupVo> getGroupAttr(GroupAttrParamVo paramVo);
}
SkuSaleAttrValueDao.java
package com.xd.cubemall.product.dao;
import com.xd.cubemall.product.entity.SkuSaleAttrValueEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xd.cubemall.product.vo.SkuItemSaleAttrVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* sku销售属性值
*
* @author xuedong
* @email email@gmail.com
* @date 2024-08-13 01:36:04
*/
@Mapper
public interface SkuSaleAttrValueDao extends BaseMapper<SkuSaleAttrValueEntity> {
public List<SkuItemSaleAttrVo> getSaleAttrs(Long spuId);
}
SkuItemController.java
package com.xd.cubemall.product.web;
import com.xd.cubemall.product.service.SkuInfoService;
import com.xd.cubemall.product.vo.SkuItemVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@Controller
public class SkuItemController {
@Autowired
private SkuInfoService skuInfoService;
/**
* 根据skuId查询商品详情信息
*/
@GetMapping("/{skuId}.html")
public String skuItem(@PathVariable Long skuId, Model model){
// 调用服务层商品详情接口
SkuItemVo itemVo = skuInfoService.skuItem(skuId);
// 输出日志
log.info("商品详情接口,查询的数据:{}",itemVo);
// 把数据放入模型驱动
model.addAttribute("item",itemVo);
// 返回视图页面,做视图数据渲染
return "item";
}
}
默认
<a href="javascript:;" th:attr="class=${#lists.contains(#strings.listSplit(attrvalues.skuIds,','),item.info.id.toString())?'sku_attr_value selected':'sku_attr_value'},skus=${attrvalues.skuIds}">
<!--th:v-bind:class="|{selected:sel('${spec.key}','${arrValue}')}|"-->
<!-- th:@click="|selectSpecification('${spec.key}','${arrValue}')|" >-->
<!-- <i th:text="${arrValue}"></i>-->[[${attrvalues.attrValue}]]
<span title="点击取消选择"> </span>
</a>
点击选中
$(".sku_attr_value").click(function () {
// 移除选中状态
$(this).parent().parent().find(".sku_attr_value").removeClass("selected");
// 给点击元素添加选中状态属性
$(this).addClass("selected");
let skus = new Array();
//选择不同的规格属性后,根据不同的属性id重新加载相应的数据
$("a[class='sku_attr_value selected']").each(function () {
skus.push($(this).attr("skus").split(","));
})
// 获取第0个元素
let sku_1 = skus[0];
// 白色: skuIds = {1,3}
// 128GB : skuIds = {3,9}
// 白色+128GB 规则属性组合的id : 求交集 ,skuId = 3
for(let i=1;i<skus.length;i++){
// 遍历每一个属性的skuids,获取交集
// 比如:白色: skuIds = {1,3},128GB : skuIds = {3,9} ,此时: {1,3}.filter({3,9}) = 3
sku_1 = $(sku_1).filter(skus[i])[0];
}
// 拼接请求
location.href = "http://localhost:8081/"+sku_1+".html";
})