2.04 商品服务-4-商品管理

文章展示了电商系统中关于商品管理的部分功能实现,包括会员模块的保存、修改和删除操作,Spu与Sku的关系解释,页面展示商品分类关联的品牌和属性,以及商品(Spu和Sku)的新增和检索功能。前端使用Vue.js组件进行交互设计,后端采用MyBatis进行数据操作。
摘要由CSDN通过智能技术生成
1.整合仓库服务

image-20230529202830026


mail-member模块的MemberController实现以下功能

  /**
   * 保存
   */
  @RequestMapping("/save")
  //@RequiresPermissions("member:member:save")
  public R save(@RequestBody MemberEntity member){
memberService.save(member);

      return R.ok();
  }

  /**
   * 修改
   */
  @RequestMapping("/update")
  //@RequiresPermissions("member:member:update")
  public R update(@RequestBody MemberEntity member){
memberService.updateById(member);

      return R.ok();
  }

  /**
   * 删除
   */
  @RequestMapping("/delete")
  //@RequiresPermissions("member:member:delete")
  public R delete(@RequestBody Long[] ids){
memberService.removeByIds(Arrays.asList(ids));

      return R.ok();
  }
2. Spu与Sku的关系

举个例子:

spu相当于iPhone

sku相当于iPhone其下的iPhone 14 黑色 256g、iPhone 14 白色 128g、iPhone 13 银色 256g

3. 页面展示image-20230529203705635

3.获取分类关联的品牌
  • 演示

    image-20230529203959880

    选择手机分类,会显示手机分类下的所有品牌


    image-20230529204129429

4.获取分类下的所有属性分组和规格参数

image-20230529204938971

获得手机分类下的所有属性分组和规格参数


image-20230529210917109

5.新增商品
  • 演示

    image-20230529211711273


    image-20230529211952090


    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PlLTIOCk-1685884522061)(C:/Users/PEIGEN/AppData/Roaming/Typora/typora-user-images/image-20230529213556041.png)]


    image-20230529213212050

  • 前端实现

    前端代码比较长,省略

  • 后端实现

    mail-product模块的SpuInfoController中编写save方法,使用mybatis自带的save方法

        /**
         * 保存
         */
        @RequestMapping("/save")
        //@RequiresPermissions("product:skuinfo:save")
        public R save(@RequestBody SkuInfoEntity skuInfo){
    		skuInfoService.save(skuInfo);
    
            return R.ok();
        }
    
6. spu检索功能
  • 演示

    image-20230530164330364


    image-20230530164718761

  • 前端代码

    <template>
      <div class="mod-config">
        <el-table
          :data="dataList"
          border
          v-loading="dataListLoading"
          @selection-change="selectionChangeHandle"
          style="width: 100%;"
        >
          <el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column>
          <el-table-column prop="id" header-align="center" align="center" label="id"></el-table-column>
          <el-table-column prop="spuName" header-align="center" align="center" label="名称"></el-table-column>
          <el-table-column prop="spuDescription" header-align="center" align="center" label="描述"></el-table-column>
          <el-table-column prop="catalogId" header-align="center" align="center" label="分类"></el-table-column>
          <el-table-column prop="brandId" header-align="center" align="center" label="品牌"></el-table-column>
          <el-table-column prop="weight" header-align="center" align="center" label="重量"></el-table-column>
          <el-table-column prop="publishStatus" header-align="center" align="center" label="上架状态">
            <template slot-scope="scope">
              <el-tag v-if="scope.row.publishStatus == 0">新建</el-tag>
              <el-tag v-if="scope.row.publishStatus == 1">已上架</el-tag>
              <el-tag v-if="scope.row.publishStatus == 2">已下架</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="createTime" header-align="center" align="center" label="创建时间"></el-table-column>
          <el-table-column prop="updateTime" header-align="center" align="center" label="修改时间"></el-table-column>
          <el-table-column fixed="right" header-align="center" align="center" width="150" label="操作">
            <template slot-scope="scope">
              <el-button
                v-if="scope.row.publishStatus == 0"
                type="text"
                size="small"
                @click="productUp(scope.row.id)"
              >上架</el-button>
              <el-button type="text" size="small" @click="attrUpdateShow(scope.row)">规格</el-button>
            </template>
          </el-table-column>
        </el-table>
    
        <el-pagination
          @size-change="sizeChangeHandle"
          @current-change="currentChangeHandle"
          :current-page="pageIndex"
          :page-sizes="[10, 20, 50, 100]"
          :page-size="pageSize"
          :total="totalPage"
          layout="total, sizes, prev, pager, next, jumper"
        ></el-pagination>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          dataSub: null,
          dataForm: {},
          dataList: [],
          pageIndex: 1,
          pageSize: 10,
          totalPage: 0,
          dataListLoading: false,
          dataListSelections: [],
          addOrUpdateVisible: false
        };
      },
      props: {
        catId: {
          type: Number,
          default: 0
        }
      },
      components: {},
      activated() {
        this.getDataList();
      },
      methods: {
        productUp(id) {
          this.$http({
            url: this.$http.adornUrl("/product/spuinfo/" + id + "/up"),
            method: "post"
          }).then(({ data }) => {
            if (data && data.code === 0) {
              this.$message({
                message: "操作成功",
                type: "success",
                duration: 1500,
                onClose: () => {
                  this.getDataList();
                }
              });
            } else {
              this.$message.error(data.msg);
            }
          });
        },
        attrUpdateShow(row) {
          console.log(row);
          this.$router.push({
            path: "/product-attrupdate",
            query: { spuId: row.id, catalogId: row.catalogId }
          });
        },
        // 获取数据列表
        getDataList() {
          this.dataListLoading = true;
          let param = {};
          Object.assign(param, this.dataForm, {
            page: this.pageIndex,
            limit: this.pageSize
          });
          this.$http({
            url: this.$http.adornUrl("/product/spuinfo/list"),
            method: "get",
            params: this.$http.adornParams(param)
          }).then(({ data }) => {
            if (data && data.code === 0) {
              this.dataList = data.page.list;
              this.totalPage = data.page.totalCount;
            } else {
              this.dataList = [];
              this.totalPage = 0;
            }
            this.dataListLoading = false;
          });
        },
        // 每页数
        sizeChangeHandle(val) {
          this.pageSize = val;
          this.pageIndex = 1;
          this.getDataList();
        },
        // 当前页
        currentChangeHandle(val) {
          this.pageIndex = val;
          this.getDataList();
        },
        // 多选
        selectionChangeHandle(val) {
          this.dataListSelections = val;
        },
        // 新增 / 修改
        addOrUpdateHandle(id) {}
      },
      mounted() {
        this.dataSub = PubSub.subscribe("dataForm", (msg, val) => {
          console.log("~~~~~", val);
          this.dataForm = val;
          this.getDataList();
        });
      },
      beforeDestroy() {
        PubSub.unsubscribe(this.dataSub);
      }
    };
    </script>
    
  • 后端代码

    SpuInfoController中编写info方法,调用mybatis自带的getById方法

        /**
         * 信息
         */
        @RequestMapping("/info/{id}")
        //@RequiresPermissions("product:spuinfo:info")
        public R info(@PathVariable("id") Long id){
    		SpuInfoEntity spuInfo = spuInfoService.getById(id);
    
            return R.ok().put("spuInfo", spuInfo);
        }
    
7. sku检索功能
  • 演示

    image-20230530165310591


    image-20230530165347570

  • 前端代码

    <template>
      <div class="mod-config">
        <el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
          <el-form :inline="true" :model="dataForm">
            <el-form-item label="分类">
              <category-cascader :catelogPath.sync="catelogPath"></category-cascader>
            </el-form-item>
            <el-form-item label="品牌">
              <brand-select style="width:160px"></brand-select>
            </el-form-item>
            <el-form-item label="价格">
              <el-input-number style="width:160px" v-model="dataForm.price.min" :min="0"></el-input-number>-
              <el-input-number style="width:160px" v-model="dataForm.price.max" :min="0"></el-input-number>
            </el-form-item>
            <el-form-item label="检索">
              <el-input style="width:160px" v-model="dataForm.key" clearable></el-input>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="searchSkuInfo">查询</el-button>
            </el-form-item>
          </el-form>
        </el-form>
        <el-table
          :data="dataList"
          border
          v-loading="dataListLoading"
          @selection-change="selectionChangeHandle"
          style="width: 100%;"
          @expand-change="getSkuDetails"
        >
          <el-table-column type="expand">
            <template slot-scope="scope">
              商品标题:{{scope.row.skuTitle}}
              <br />
              商品副标题:{{scope.row.skuSubtitle}}
              <br />
              商品描述:{{scope.row.skuDesc}}
              <br />
              分类ID:{{scope.row.catalogId}}
              <br />
              SpuID:{{scope.row.spuId}}
              <br />
              品牌ID:{{scope.row.brandId}}
              <br />
            </template>
          </el-table-column>
          <el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column>
          <el-table-column prop="skuId" header-align="center" align="center" label="skuId"></el-table-column>
          <el-table-column prop="skuName" header-align="center" align="center" label="名称"></el-table-column>
          <el-table-column prop="skuDefaultImg" header-align="center" align="center" label="默认图片">
            <template slot-scope="scope">
              <img :src="scope.row.skuDefaultImg" style="width:80px;height:80px;" />
            </template>
          </el-table-column>
          <el-table-column prop="price" header-align="center" align="center" label="价格"></el-table-column>
          <el-table-column prop="saleCount" header-align="center" align="center" label="销量"></el-table-column>
          <el-table-column fixed="right" header-align="center" align="center" width="150" label="操作">
            <template slot-scope="scope">
              <el-button type="text" size="small" @click="previewHandle(scope.row.skuId)">预览</el-button>
              <el-button type="text" size="small" @click="commentHandle(scope.row.skuId)">评论</el-button>
              <el-dropdown
                @command="handleCommand(scope.row,$event)"
                size="small"
                split-button
                type="text"
              >
                更多
                <el-dropdown-menu slot="dropdown">
                  <el-dropdown-item command="uploadImages">上传图片</el-dropdown-item>
                  <el-dropdown-item command="seckillSettings">参与秒杀</el-dropdown-item>
                  <el-dropdown-item command="reductionSettings">满减设置</el-dropdown-item>
                  <el-dropdown-item command="discountSettings">折扣设置</el-dropdown-item>
                  <el-dropdown-item command="memberPriceSettings">会员价格</el-dropdown-item>
                  <el-dropdown-item command="stockSettings">库存管理</el-dropdown-item>
                  <el-dropdown-item command="couponSettings">优惠劵</el-dropdown-item>
                </el-dropdown-menu>
              </el-dropdown>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination
          @size-change="sizeChangeHandle"
          @current-change="currentChangeHandle"
          :current-page="pageIndex"
          :page-sizes="[10, 20, 50, 100]"
          :page-size="pageSize"
          :total="totalPage"
          layout="total, sizes, prev, pager, next, jumper"
        ></el-pagination>
      </div>
    </template>
    
    <script>
    import CategoryCascader from "../common/category-cascader";
    import BrandSelect from "../common/brand-select";
    export default {
      data() {
        return {
          catPathSub: null,
          brandIdSub: null,
          dataForm: {
            key: "",
            brandId: 0,
            catelogId: 0,
            price: {
              min: 0,
              max: 0
            }
          },
          dataList: [],
          pageIndex: 1,
          pageSize: 10,
          totalPage: 0,
          dataListLoading: false,
          dataListSelections: [],
          addOrUpdateVisible: false,
          catelogPath: []
        };
      },
      components: {
        CategoryCascader,
        BrandSelect
      },
      activated() {
        this.getDataList();
      },
      methods: {
        getSkuDetails(row, expand) {
          //sku详情查询
          console.log("展开某行...", row, expand);
        },
        //处理更多指令
        handleCommand(row, command) {
          console.log("~~~~~", row, command);
          if ("stockSettings" == command) {
            this.$router.push({ path: "/ware-sku", query: { skuId: row.skuId } });
          }
        },
        searchSkuInfo() {
          this.getDataList();
        },
        // 获取数据列表
        getDataList() {
          this.dataListLoading = true;
          this.$http({
            url: this.$http.adornUrl("/product/skuinfo/list"),
            method: "get",
            params: this.$http.adornParams({
              page: this.pageIndex,
              limit: this.pageSize,
              key: this.dataForm.key,
              catelogId: this.dataForm.catelogId,
              brandId: this.dataForm.brandId,
              min: this.dataForm.price.min,
              max: this.dataForm.price.max
            })
          }).then(({ data }) => {
            if (data && data.code === 0) {
              this.dataList = data.page.list;
              this.totalPage = data.page.totalCount;
            } else {
              this.dataList = [];
              this.totalPage = 0;
            }
            this.dataListLoading = false;
          });
        },
        // 每页数
        sizeChangeHandle(val) {
          this.pageSize = val;
          this.pageIndex = 1;
          this.getDataList();
        },
        // 当前页
        currentChangeHandle(val) {
          this.pageIndex = val;
          this.getDataList();
        },
        // 多选
        selectionChangeHandle(val) {
          this.dataListSelections = val;
        }
      },
      mounted() {
        this.catPathSub = PubSub.subscribe("catPath", (msg, val) => {
          this.dataForm.catelogId = val[val.length - 1];
        });
        this.brandIdSub = PubSub.subscribe("brandId", (msg, val) => {
          this.dataForm.brandId = val;
        });
      },
      beforeDestroy() {
        PubSub.unsubscribe(this.catPathSub);
        PubSub.unsubscribe(this.brandIdSub);
      } //生命周期 - 销毁之前
    };
    </script>
    
  • 后端代码

    SkuInfoController中编写list方法

        /**
         * 列表
         */
        @RequestMapping("/list")
        public R list(@RequestParam Map<String, Object> params){
            PageUtils page = skuInfoService.queryPageByCondition(params);
    
            return R.ok().put("page", page);
        }
    

    SkuInfoServiceImpl中具体实现

        @Override
        public PageUtils queryPageByCondition(Map<String, Object> params) {
            QueryWrapper<SkuInfoEntity> queryWrapper = new QueryWrapper<>();
    
            String key = (String) params.get("key");
            if (!StringUtils.isEmpty(key) && !"0".equalsIgnoreCase(key)) {
                queryWrapper.and((wrapper) -> {
                    wrapper.eq("sku_id",key).or().like("sku_name",key);
                });
            }
    
            String catelogId = (String) params.get("catelogId");
            if (!StringUtils.isEmpty(catelogId) && !"0".equalsIgnoreCase(catelogId)) {
                queryWrapper.eq("catalog_id",catelogId);
            }
    
            String brandId = (String) params.get("brandId");
            if (!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)) {
                queryWrapper.eq("brand_id",brandId);
            }
    
            String min = (String) params.get("min");
            if (!StringUtils.isEmpty(min)) {
                queryWrapper.ge("price",min);
            }
    
            String max = (String) params.get("max");
    
            if (!StringUtils.isEmpty(max)) {
                try {
                    BigDecimal bigDecimal = new BigDecimal(max);
                    if (bigDecimal.compareTo(BigDecimal.ZERO) == 1) {
                        queryWrapper.le("price",max);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
            // key:
            // catelogId: 225
            // brandId: 9
            // min: 0
            // max: 0
    
            IPage<SkuInfoEntity> page = this.page(
                    new Query<SkuInfoEntity>().getPage(params),
                    queryWrapper
            );
            return new PageUtils(page);
        }
    
总结

该篇主要实现了商品添加和检索功能。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值