通过管理系统完成商品属性维护

news2025/1/16 5:41:42

文章目录

    • 1.数据库表设计
        • 1.商品属性表
    • 2.renren-generator生成CRUD
        • 1.基本配置检查
          • 1.generator.properties
          • 2.application.yml
        • 2.启动RenrenGeneratorApplication.java生成CRUD
          • 1.启动后访问localhost:81
          • 2.生成商品属性表的crud
        • 3.将crud代码集成到项目中
          • 1.解压,找到main目录
          • 2.将main目录替换为sunliving-commodity模块的main目录
        • 4.检查代码
          • 1.将AttrController.java的@RequiresPermissions注解注释掉
          • 2.application.yml
          • 3.AttrEntity.java
          • 4.AttrDao.java
          • 5.AttrDao.xml
          • 6.AttrService.java
          • 7.AttrServiceImpl.java
          • 8.AttrController.java
          • 9.测试接口
            • 1.http://localhost:5050/api/sunliving-commodity/commodity/attr/list
            • 2.http://localhost:5050/api/sunliving-commodity/commodity/attr/save
        • 5.显示基本界面
          • 1.将代码生成器生成的两个前端页面复制到前端项目
          • 2.修改attr.vue的名字为baseattr.vue因为后面还有一个销售属性的页面
          • 3.创建路由为 commodity/baseattr 的菜单
          • 4.修改baseattr.vue的所有请求(2个)为 环境变量 + 资源路径 的方式(由于没有更换模块所以gateway和多环境不需区分)
          • 5.修改 attr-add-or-update.vue(两个请求)
          • 6.测试基本界面的crud,没问题
    • 3.添加商品属性
        • 1.基本页面搭建
          • 1.将属性类型改成下拉框
            • 1.找到element-ui下拉框组件位置 https://element.eleme.cn/#/zh-CN/component/select#methods
            • 2.修改后的el-form-item
            • 3.结果展示
          • 2.将所属分类改成级联菜单
            • 1.修改后的el-form-item
            • 2.数据池
            • 3.方法池
            • 4.created调用
            • 5.结果展示
            • 6.dataForm的categoryId默认值设置为0,用户如果不填的话就没有所在分组
    • 4.销售属性与属性组的关联表
        • 1.关联表设计
        • 2.代码生成器生成crud
          • 1.生成代码
          • 2.测试 http://localhost:5050/api/sunliving-commodity/commodity/attrattrgrouprelation/list
    • 5.添加基本属性 attr-add-or-update.vue
        • 1.选择所属分类,联动显示所属分组
          • 1.所属分类下新增所属分组下拉框
          • 2.数据池新增attrGroups属性,表示属性组信息
          • 3.数据池的dataForm新增attrGroupId属性
          • 4.方法池前面新增一个watch,监控所属分类的id,一旦变化就根据这个id向后端发送请求得到该所属分类的所有分组
          • 5.表单提交时新增属性分组属性
        • 2.后端 sunliving-commodity 模块
          • 1.AttrEntity.java新增attrGroupId属性
          • 2.service层
            • 1.AttrService.java 新增方法,保存基本属性以及与属性分组的关联关系
            • 2.AttrServiceImpl.java 实现方法
          • 3.controller层
            • AttrController.java 修改save方法
          • 4.结果展示
            • 1.添加一个测试属性到节能灯的测试分组下
            • 2.查看属性表
            • 3.查看关联表
    • 6.基本属性分页查询
        • 1.后端
          • 1.首先确保引入了分页插件
          • 2.service层
            • 1.AttrService.java
            • 2.AttrServiceImpl.java 根据参数中的params的key构造查询条件为id等于key或者name like key
          • 3.AttrController.java
        • 2.前端
          • 只需要注意脚手架请求携带的参数即可,key为输入框的内容
        • 3.结果展示
          • 1.根据id查询
          • 2.根据属性名查询
    • 7.完成销售属性的维护
        • 1.后端初始化
          • 1.分页查询
            • 1.AttrService.java 新增方法
            • 2.AttrServiceImpl.java 实现方法,修改一下attr_type为0 即可
            • 3.AttrController.java 新增方法
            • 4.重启测试
        • 2.前端初始化
          • 1.接入页面
            • 1.粘贴一份baseattr.vue和attr-add-or-update.vue并修改名字
            • 2.创建菜单
            • 3.修改导入的组件为 sale-attr-add-or-update
            • 4.修改分页查询的请求为listOnSale
            • 5.此时应该无数据
        • 3.销售属性添加
          • 1.修改sale-attr-add-or-update.vue的对话框
          • 2.修改watch监听,只保留一句
          • 3.目前如果新增一条记录,将不会保存关联关系,只会保存传进去的基本属性
          • 4.新增一条记录测试
          • 5.修改saleattr.vue,删除几个不必要的表头
        • 4.点击修改,所属分类不回显问题
          • 1.问题引出
          • 2.找到前端点击修改的逻辑进行分析
            • 1.点击修改,跳转到这个init方法,并携带id
            • 2.这个后端接口,根据id获取一条记录然后直接返回,但是如果要显示级联菜单则需要一个id列表
          • 3.service层编写方法,根据所属分类id,找出所有父分类的id
            • 1.AttrService.java
            • 2.AttrServiceImpl.java
          • 4.AttrEntity.java新增一个级联菜单的id属性,用于controller返回数据
          • 5.AttrController.java返回数据
          • 6.前端sale-attr-add-or-update.vue修改init方法,回显级联菜单
          • 7.重启测试
    • 8.关于该阶段多表查询的小结
        • 1.E-R图
        • 2.外键解决方式
        • 3.关联表解决方式
        • 4.新增一个表的思路分析
          • 1.是否有关联?
          • 2.怎么体现关联?
          • 3.怎么实现关联?
          • 4.基本属性的新增功能的思路分析

1.数据库表设计

1.商品属性表
use sunliving_commodity;

CREATE TABLE commodity_attr
(
    attr_id      BIGINT NOT NULL AUTO_INCREMENT COMMENT '属性 id',
    attr_name    CHAR(30) COMMENT '属性名',
    search_type  TINYINT COMMENT '是否需要检索[0-不需要,1-需要]',
    icon         VARCHAR(255) COMMENT '图标',
    value_select CHAR(255) COMMENT '可选值列表[用逗号分隔]',
    attr_type    TINYINT COMMENT '属性类型[0-销售属性,1-基本属性]',
    ENABLE       BIGINT COMMENT '启用状态[0 - 禁用,1 - 启用]',
    category_id  BIGINT COMMENT '所属分类',
    show_desc    TINYINT COMMENT '快速展示【是否展示在介绍上;0-否 1-是】',
    PRIMARY KEY (attr_id)
) CHARSET = utf8mb4 COMMENT ='商品属性表';

SELECT *
FROM `commodity_attr`

2.renren-generator生成CRUD

1.基本配置检查
1.generator.properties

image-20240419140812037

2.application.yml

image-20240419140842964

2.启动RenrenGeneratorApplication.java生成CRUD
1.启动后访问localhost:81

image-20240419140930618

image-20240419141002165

2.生成商品属性表的crud

image-20240419141023861

3.将crud代码集成到项目中
1.解压,找到main目录

image-20240419141149148

2.将main目录替换为sunliving-commodity模块的main目录

image-20240419141259682

image-20240419141500537

4.检查代码
1.将AttrController.java的@RequiresPermissions注解注释掉

image-20240419141648532

2.application.yml
  • 主要是逻辑删除和主键自增

image-20240419142011729

3.AttrEntity.java
  • 主键自增,添加@TableId注解

image-20240419142340328

4.AttrDao.java
  • 注入容器,继承baseMapper

image-20240419142433182

5.AttrDao.xml
  • 关联AttrDao

image-20240419142519630

6.AttrService.java
  • 继承IService

image-20240419142609355

7.AttrServiceImpl.java
  • 注入容器,实现AttrService,继承ServiceImpl

image-20240419142646155

8.AttrController.java
  • 注入容器,基础路径 commodity/attr

image-20240419143046449

9.测试接口
1.http://localhost:5050/api/sunliving-commodity/commodity/attr/list

image-20240419143933533

2.http://localhost:5050/api/sunliving-commodity/commodity/attr/save

image-20240419144313353

image-20240419144331981

5.显示基本界面
1.将代码生成器生成的两个前端页面复制到前端项目

image-20240419144753530

image-20240419144832747

2.修改attr.vue的名字为baseattr.vue因为后面还有一个销售属性的页面

image-20240419144950477

3.创建路由为 commodity/baseattr 的菜单

image-20240419145147832

4.修改baseattr.vue的所有请求(2个)为 环境变量 + 资源路径 的方式(由于没有更换模块所以gateway和多环境不需区分)

image-20240419145718913

image-20240419150003339

image-20240419145650701

5.修改 attr-add-or-update.vue(两个请求)

image-20240419145934259

image-20240419145942288

6.测试基本界面的crud,没问题

3.添加商品属性

1.基本页面搭建
1.将属性类型改成下拉框
1.找到element-ui下拉框组件位置 https://element.eleme.cn/#/zh-CN/component/select#methods

image-20240419160335587

2.修改后的el-form-item
  • el-option的属性
    • label表示显示的内容
    • :value表示代表的值
  • v-model="dataForm.attrType"表示绑定的是dataForm.attrType这个属性
    <el-form-item label="属性类型[0-销售属性,1-基本属性]" prop="attrType">
<!--      <el-input v-model="dataForm.attrType" placeholder="属性类型[0-销售属性,1-基本属性]"></el-input>-->
      <el-select v-model="dataForm.attrType" placeholder="请选择">
        <el-option
          label="销售属性"
          :value="0">
        </el-option>
        <el-option
          label="基本属性"
          :value="1">
        </el-option>
      </el-select>
    </el-form-item>
3.结果展示

image-20240419161552921

2.将所属分类改成级联菜单
1.修改后的el-form-item
    <el-form-item label="所属分类" prop="categoryId">
<!--      <el-input v-model="dataForm.categoryId" placeholder="所属分类"></el-input>-->
      <el-cascader
        filterable
        placeholder="请选择"
        v-model="cascadedCategoryId"
        :options="categories"
        :props="props"
      ></el-cascader>
    </el-form-item>
2.数据池
        categories: [], // 树形数据
        cascadedCategoryId: [], // 级联选择器的值,从 categories 中取
        props: {
          value: 'id', // 从 categories 中取 id放到 cascadedCategoryId
          label: 'name', // 从 categories 中取 name作为级联选择器的显示标签
          children: 'childrenCategories', // 从 categories 中取 childrenCategories作为级联选择器的子选项
          expandTrigger: 'hover' // 悬停展开
        }
3.方法池
      // 获取分类列表(带层级)
      getCategories() {
        this.$http({
          url: process.env.COMMODITY_BASEPATH + '/commodity/category/list/tree',
          method: 'get'
        }).then(({data}) => { // 解构了data
          console.log(data.data)
          this.categories = data.data; // 将树形数据赋值给 categories
        })
      }
4.created调用
    created() {
      this.getCategories()
    }
5.结果展示

image-20240419163013793

6.dataForm的categoryId默认值设置为0,用户如果不填的话就没有所在分组

image-20240420093637541

4.销售属性与属性组的关联表

1.关联表设计
use sunliving_commodity;

CREATE TABLE commodity_attr_attrgroup_relation
(
    id            BIGINT NOT NULL AUTO_INCREMENT COMMENT 'id',
    attr_id       BIGINT COMMENT '属性 id',
    attr_group_id BIGINT COMMENT '属性分组 id',
    attr_sort     INT COMMENT '属性组内排序',
    PRIMARY KEY (id)
) CHARSET = utf8mb4 COMMENT ='商品属性和商品属性组的关联表';

SELECT *
FROM `commodity_attr_attrgroup_relation`
2.代码生成器生成crud
1.生成代码

image-20240420095645124

2.测试 http://localhost:5050/api/sunliving-commodity/commodity/attrattrgrouprelation/list

image-20240420095948470

5.添加基本属性 attr-add-or-update.vue

1.选择所属分类,联动显示所属分组
1.所属分类下新增所属分组下拉框
      <el-form-item label="所属分组">
        <el-select ref="groupSelect" v-model="dataForm.attrGroupId" placeholder="请选择">
          <el-option
            v-for="item in attrGroups"
            :key="item.id"
            :label="item.name"
            :value="item.id">
          </el-option>
        </el-select>
      </el-form-item>
2.数据池新增attrGroups属性,表示属性组信息

image-20240420105025382

3.数据池的dataForm新增attrGroupId属性

image-20240420105108802

4.方法池前面新增一个watch,监控所属分类的id,一旦变化就根据这个id向后端发送请求得到该所属分类的所有分组
  watch: {
    cascadedCategoryId(path) {
      // 监控级联选择器的值,如果是三级分类,就获取属性分组
      this.attrGroups = [];
      this.dataForm.attrGroupId = "";
      this.dataForm.categoryId = path[path.length - 1];
      if (path && path.length == 3) {
        this.$http({
          url: process.env.COMMODITY_BASEPATH + '/commodity/attrgroup/list/' + path[path.length - 1],
          method: "get",
          params: this.$http.adornParams({page: 1, limit: 10000000})
        }).then(({data}) => {
          console.log("data=", data.page.list)
          if (data && data.code === 0) {
            this.attrGroups = data.page.list;
          } else {
            this.$message.error(data.msg);
          }
        });
      } else if (path.length == 0) {
        this.dataForm.categoryId = "";
      } else {
        this.$message.error("请选择正确的分类");
        this.dataForm.categoryId = "";
      }
    }
  },
5.表单提交时新增属性分组属性

image-20240420110826225

2.后端 sunliving-commodity 模块
1.AttrEntity.java新增attrGroupId属性

image-20240420111713698

2.service层
1.AttrService.java 新增方法,保存基本属性以及与属性分组的关联关系
    /**
     * 保存基本属性以及基本属性与属性分组的关联关系
     * @param attr
     */
    void saveAttrAndRelation(AttrEntity attr);
2.AttrServiceImpl.java 实现方法
    @Transactional // 事务注解
    @Override
    public void saveAttrAndRelation(AttrEntity attr) {
        // 保存基本属性
        this.save(attr);
        // 保存关联关系
        if(attr.getAttrGroupId() != null && attr.getAttrType() == 1) {
            // 保存关联关系
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrId(attr.getAttrId());
            relationEntity.setAttrGroupId(attr.getAttrGroupId());
            attrAttrgroupRelationService.save(relationEntity);
        }
    }
3.controller层
AttrController.java 修改save方法
    /**
     * 保存
     */
    @RequestMapping("/save")
    // @RequiresPermissions("commodity:attr:save")
    public R save(@RequestBody AttrEntity attr){
		attrService.saveAttrAndRelation(attr);

        return R.ok();
    }
4.结果展示
1.添加一个测试属性到节能灯的测试分组下

image-20240420134251070

image-20240420134456333

2.查看属性表

image-20240420134517962

3.查看关联表

image-20240420134722523

6.基本属性分页查询

1.后端
1.首先确保引入了分页插件
package com.sun.sunliving.commodity.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * Description: 分页插件使用
 *
 * @Author sun
 * @Create 2024/4/18 13:06
 * @Version 1.0
 */
@Configuration
@EnableTransactionManagement // 开启事务
@MapperScan("com.sun.sunliving.commodity.dao") // 扫描mapper接口
public class MyBatisConfig {
    // 引入分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
    // 设置请求的页面大于最大页后操作,
    // true 调回到首页,false 继续请求 默认 false
        paginationInterceptor.setOverflow(true);
    // 设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInterceptor.setLimit(100);
        return paginationInterceptor;
    }
}

2.service层
1.AttrService.java
    PageUtils queryPage(Map<String, Object> params);
2.AttrServiceImpl.java 根据参数中的params的key构造查询条件为id等于key或者name like key
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        // 获取key
        String key = (String) params.get("key");
        
        QueryWrapper<AttrEntity> attrEntityQueryWrapper = new QueryWrapper<>();

        // 构造查询条件,首先只查询attr_type为1的基本属性
        attrEntityQueryWrapper.eq("attr_type", 1);

        // 如果key不为空,查询条件为attr_id等于key或者attr_name like %key%,否则查询条件为空
        if(StringUtils.isNotBlank(key)) {
            attrEntityQueryWrapper.and(wrapper -> {
                wrapper.eq("attr_id", key).or().like("attr_name", key);
            });
        }
        // 分页查询
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                attrEntityQueryWrapper
        );

        return new PageUtils(page);
    }
3.AttrController.java
    /**
     * 分页查询
     */
    @RequestMapping("/list")
    public R list(@RequestParam Map<String, Object> params){
        PageUtils page = attrService.queryPage(params);

        return R.ok().put("page", page);
    }

2.前端
只需要注意脚手架请求携带的参数即可,key为输入框的内容

image-20240420142816971

3.结果展示
1.根据id查询

image-20240420142922669

image-20240420142930828

2.根据属性名查询

image-20240420142951890

7.完成销售属性的维护

1.后端初始化
1.分页查询
1.AttrService.java 新增方法
    /**
     * 销售属性分页查询
     * @param params
     * @return
     */
    PageUtils queryPageOnSale(Map<String, Object> params);
2.AttrServiceImpl.java 实现方法,修改一下attr_type为0 即可
    @Override
    public PageUtils queryPageOnSale(Map<String, Object> params) {
        // 获取key
        String key = (String) params.get("key");

        QueryWrapper<AttrEntity> attrEntityQueryWrapper = new QueryWrapper<>();

        // 构造查询条件,首先只查询attr_type为0的基本属性
        attrEntityQueryWrapper.eq("attr_type", 0);

        // 如果key不为空,查询条件为attr_id等于key或者attr_name like %key%,否则查询条件为空
        if(StringUtils.isNotBlank(key)) {
            attrEntityQueryWrapper.and(wrapper -> {
                wrapper.eq("attr_id", key).or().like("attr_name", key);
            });
        }
        // 分页查询
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                attrEntityQueryWrapper
        );

        return new PageUtils(page);
    }
3.AttrController.java 新增方法
    /**
     * 销售属性分页查询
     */
    @RequestMapping("/listOnSale")
    public R listOnSale(@RequestParam Map<String, Object> params){
        PageUtils page = attrService.queryPageOnSale(params);

        return R.ok().put("page", page);
    }
4.重启测试

image-20240420150045493

2.前端初始化
1.接入页面
1.粘贴一份baseattr.vue和attr-add-or-update.vue并修改名字

image-20240420150414229

2.创建菜单

image-20240420150713745

3.修改导入的组件为 sale-attr-add-or-update

image-20240420151033475

4.修改分页查询的请求为listOnSale

image-20240420152940262

5.此时应该无数据

image-20240420152956331

3.销售属性添加
1.修改sale-attr-add-or-update.vue的对话框
  <el-dialog
    :title="!dataForm.attrId ? '新增' : '修改'"
    :close-on-click-modal="false"
    :visible.sync="visible">
    <el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()"
             label-width="80px">
      <el-form-item label="属性名" prop="attrName">
        <el-input v-model="dataForm.attrName" placeholder="属性名"></el-input>
      </el-form-item>
      <el-form-item label="图标" prop="icon">
        <el-input v-model="dataForm.icon" placeholder="图标"></el-input>
      </el-form-item>
      <el-form-item label="可选值列表[用逗号分隔]" prop="valueSelect">
        <el-input v-model="dataForm.valueSelect" placeholder="可选值列表[用逗号分隔]"></el-input>
      </el-form-item>
      <el-form-item label="属性类型[0-销售属性,1-基本属性]" prop="attrType">
        <!--      <el-input v-model="dataForm.attrType" placeholder="属性类型[0-销售属性,1-基本属性]"></el-input>-->
        <el-select v-model="dataForm.attrType" placeholder="请选择">
          <el-option
            label="销售属性"
            :value="0">
          </el-option>
          <el-option
            label="基本属性"
            :value="1">
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="启用状态[0 - 禁用,1 - 启用]" prop="enable">
        <el-input v-model="dataForm.enable" placeholder="启用状态[0 - 禁用,1 - 启用]"></el-input>
      </el-form-item>
      <el-form-item label="所属分类" prop="categoryId">
        <el-cascader
          filterable
          placeholder="请选择"
          v-model="cascadedCategoryId"
          :options="categories"
          :props="props"
        ></el-cascader>
      </el-form-item>
    </el-form>
    <span slot="footer" class="dialog-footer">
      <el-button @click="visible = false">取消</el-button>
      <el-button type="primary" @click="dataFormSubmit()">确定</el-button>
    </span>
  </el-dialog>
2.修改watch监听,只保留一句

image-20240420155938297

3.目前如果新增一条记录,将不会保存关联关系,只会保存传进去的基本属性

image-20240420155423393

4.新增一条记录测试

image-20240420160124150

5.修改saleattr.vue,删除几个不必要的表头

image-20240420160310739

4.点击修改,所属分类不回显问题
1.问题引出

image-20240420161057573

2.找到前端点击修改的逻辑进行分析
1.点击修改,跳转到这个init方法,并携带id

image-20240420161418265

2.这个后端接口,根据id获取一条记录然后直接返回,但是如果要显示级联菜单则需要一个id列表

image-20240420161813581

3.service层编写方法,根据所属分类id,找出所有父分类的id
1.AttrService.java
    /**
     * 根据id来获取该id对应的所有父id的数组
     *
     * @return
     */
    List<Long> getCascadedCategoryId(Long categoryId);
2.AttrServiceImpl.java
    @Override
    public List<Long> getCascadedCategoryId(Long categoryId) {
        ArrayList<Long> res = new ArrayList<>();
        // 根据categoryId查询出所有的父id,并放到res中
        // 查询一下当前记录
        CategoryEntity categoryEntity = categoryDao.selectById(categoryId);

        // 只要当前记录不为空,就一直循环
        while (categoryEntity != null) {
            res.add(categoryEntity.getId());
            categoryId = categoryEntity.getParentId();
            categoryEntity = categoryDao.selectById(categoryId);
        }

        // 使用 Collections.reverse 直接反转
        Collections.reverse(res);
        return res;
    }
4.AttrEntity.java新增一个级联菜单的id属性,用于controller返回数据

image-20240420170337749

5.AttrController.java返回数据
    /**
     * 信息
     */
    @RequestMapping("/info/{attrId}")
    // @RequiresPermissions("commodity:attr:info")
    public R info(@PathVariable("attrId") Long attrId){
		AttrEntity attr = attrService.getById(attrId);
        // 根据所属分类id,找出所有父分类的id
        List<Long> cascadedCategoryId = attrService.getCascadedCategoryId(attr.getCategoryId());
        attr.setCascadedCategoryId(cascadedCategoryId);
        return R.ok().put("attr", attr);
    }
6.前端sale-attr-add-or-update.vue修改init方法,回显级联菜单

image-20240420170605467

7.重启测试

image-20240420170631567

8.关于该阶段多表查询的小结

1.E-R图

image-20240420172021272

2.外键解决方式
  • 一对一,一对多一般通过外键解决
  • 通过在多方的表中添加一个外键字段指向一方的主键来实现
  • 此时这个外键的值只能从一方的主键中取,在该项目中,使用的是级联菜单,让用户只能选择一方的主键
3.关联表解决方式
  • 一对多,多对多一般通过关联表解决
  • 关联表具有两个表的主键,也可以有两个表name或者其他的冗余字段
  • 在该项目的基本属性保存功能,向属性的entity传入了一个属性组的id,使其在保存时同时完成了属性组与基本属性的关联
4.新增一个表的思路分析
1.是否有关联?
2.怎么体现关联?
3.怎么实现关联?
4.基本属性的新增功能的思路分析
  1. 有两个关联,分类表与属性表的一对多,属性组表与属性表的一对多
  2. 分类表与属性表:使用在属性表中添加外键的方式体现关联
  3. 属性组表与属性表:使用关联表的方式体现关联
  4. 分类表与属性表:在新增时使用级联菜单的形式让用户选择分类表的主键
  5. 属性组表与属性表,在新增时实现关联
    • 使用vue的watch监控分类的变化
    • 只要用户选中了所属分类,则取出该分类,根据这个分类的id来找到所有的分组,并以下拉框的形式显示
    • 点击确定,就将这个新增的所属分组的id也保存到entity中(需要新增加字段)
    • 后端首先将基本的属性信息保存到表中,然后根据所属分组的id和销售属性的id,将数据插入到关联表中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1682962.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Gittee

前言&#xff1a; 海鸥禁止 git简述 分布式版本控制系统 版本管理 集中式只有一个档案馆 分布式可以每人有一个档案馆&#xff0c;版本合并 协同工作 github&#xff0c;gitlab&#xff0c;gitee是git的托管平台 安装git 略 添加&#xff0c;提交文件 推到远程仓库 常…

vscode安装多版本esp-idf

安装 离线安装 vscode设置 建立一个新的配置文件, 这里面的插件是全新的 安装esp-idf 官网下载espidf 安装这一个 选项默认即可 记住各一个路径, 之后要用到 vscode安装插件 安装以后会进入这一个界面, 也可以CtrlShiftP输入ESP-IDFextension进入 使用espressif 问题 这一个…

微信小程序---小程序文档配置(2)

一、小程序文档配置 1、小程序的目录结构 1.1、目录结构 小程序包含一个描述整体程序的 app 和多个描述各自页面的 page 一个小程序主体部分由三个文件组成&#xff0c;必须放在项目的根目录 比如当前我们的《第一个小程序》项目根目录下就存在这三个文件&#xff1a; 1…

【论文速读】|探索ChatGPT在软件安全应用中的局限性

本次分享论文&#xff1a;Exploring the Limits of ChatGPT in Software Security Applications 基本信息 原文作者&#xff1a;Fangzhou Wu, Qingzhao Zhang, Ati Priya Bajaj, Tiffany Bao, Ning Zhang, Ruoyu "Fish" Wang, Chaowei Xiao 作者单位&#xff1a;威…

day08-Java常用API

day08——Java常用API 一、今日内容介绍、API概述 各位同学&#xff0c;我们前面已经学习了面向对象编程&#xff0c;使用面向编程这个套路&#xff0c;我们需要自己写类&#xff0c;然后创建对象来解决问题。但是在以后的实际开发中&#xff0c;更多的时候&#xff0c;我们是…

Linux软硬链接及动静态库

软硬链接与动静态库 软连接 创建链接的方法&#xff1a; ln -s test1.txt test2.txt 其中ln 是link(链接)&#xff0c;-s 是soft(软)&#xff0c;后者链接前者。 此时打开test2.txt&#xff0c;发现其中内容与test.txt一致。那么软连接到底建立了什么联系&#xff1f;…

Python函数进阶:四大高阶函数、匿名函数、枚举、拉链与递归详解

系列文章目录 Python数据类型&#xff1a;编程新手的必修课深入探索Python字符串&#xff1a;技巧、方法与实战Python 函数基础详解Python正则表达式详解&#xff1a;掌握文本匹配的魔法Python文件操作宝典&#xff1a;一步步教你玩转文件读写Python面向对象基础与魔法方法详解…

添加webpack.config.js配置

webpack 命令默认会去根目录查找webpack.config.js配置文件&#xff0c;如果没有&#xff0c;则会使用webpack默认的零配置打包规则进行打包&#xff0c;默认的零配置打包规则主要包括下面这几点&#xff1a; 1. 默认入口文件&#xff1a;Webpack 默认会将 ./src/index.js 作为…

“壕无人性”的沙特也要买量子计算机!巨头沙特阿美的合作方竟是它?

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨浪味仙 排版丨沛贤 深度好文&#xff1a;1200字丨5分钟阅读 摘要&#xff1a;石油巨头沙特阿美与 Pasqal 开启合作&#xff0c;计划于 2025 年部署一台 200 量子比特的量子计算机&#xff…

开源大模型与闭源大模型:技术哲学的较量

目录 前言一、 开源大模型的优势1. 社区支持与合作1.1 全球协作网络1.2 快速迭代与创新1.3 共享最佳实践 2. 透明性与可信赖性2.1 审计与验证2.2 减少偏见与错误2.3 安全性提升 3. 低成本与易访问性3.1 降低研发成本3.2 易于定制化3.3 教育资源丰富 4. 促进标准化5. 推动技术进…

【qt】QDockWidget 浮动窗口

QDockWidget 浮动窗口 一.QDockWidget 的用法 前言&#xff1a;很简单&#xff0c;放心食用 一.QDockWidget 的用法 太简单了&#xff0c;直接来吧&#xff01; 直接做个小项目来了解QDockWidget 的用法 目标效果图&#xff1a; 开始拖放&#xff1a; 开始布局&#xff1a; …

Jenkins pipeline发布前端项目

说明&#xff1a;第一次使用jenkins生成pipeline片段&#xff0c;做个记录... 1.全局工具配置添加自定义node版本 2.系统管理添加前端应用部署服务器 2.1 点击高级选择账号密码验证方式&#xff0c;添加服务器的用户和密码 3.系统管理--凭据--系统--全局凭据--添加自己的git凭据…

R语言数据分析案例-巴西固体燃料排放量预测与分析

1 背景 自18世纪中叶以来&#xff0c;由于快速城市化、人口增长和技术发展&#xff0c;导致一氧化二氮&#xff08;N2O&#xff09;、 甲烷&#xff08;CH4&#xff09;和二氧化碳&#xff08;CO 2&#xff09;等温室气体浓度急剧上升&#xff0c;引发了全球变暖、海平面上 升…

[Cocos Creator 3.5赛车游戏]第5节 为汽车节点挂载自定义脚本

在前面的章节中您已经学会了如何创建一个汽车节点&#xff0c;这一章我们将会学习如何通过挂载自定义节点的方式让小车变得可控制&#xff0c;所以通过这一章的学习后&#xff0c;您将实现一个效果&#xff1a;开始运行后&#xff0c;小车每隔一帧就延y轴向上移动一段距离。在这…

vs无法打开或包括文件”QTxxx“

vs创建项目时默认引入core、gui、和widgets等模块&#xff0c;在需要网络通讯或者图表等开发时需要添加相应模块。 点击扩展 -> QT VS Tools -> QT Project Setting->Qt Modules&#xff0c;添加相应模块即可

OpenAI、微软、智谱AI 等全球 16 家公司共同签署前沿人工智能安全承诺

人工智能&#xff08;AI&#xff09;的安全问题&#xff0c;正以前所未有的关注度在全球范围内被讨论。 日前&#xff0c;OpenAI 联合创始人、首席科学家 Ilya Sutskever 与 OpenAI 超级对齐团队共同领导人 Jan Leike 相继离开 OpenAI&#xff0c;Leike 甚至在 X 发布了一系列…

Java中Spring MVC 来如何接收表单数据

目录 一、Java语言介绍 二、Spring MVC 框架介绍 三、什么是表单 四、Spring MVC 来如何接收表单数据 一、Java语言介绍 Java是一种广泛使用的面向对象的编程语言&#xff0c;由Sun Microsystems公司的James Gosling等人开发。它最初于1995年发布&#xff0c;被设计为具有…

以人为本的人工智能:李飞飞谈AI

随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;关于AI的讨论越来越多&#xff0c;特别是围绕其可能带来的威胁。有人担心高效的AI会夺走我们的工作&#xff0c;甚至不可控的AI最终会统治人类。对此&#xff0c;斯坦福大学计算机科学系教授李飞飞提出了不同…

【bug解决】文件chunk分包上传中断报错

文章目录 报错信息原因分析解决方案 一天闲着无聊&#xff0c;打开项目线上报错日志信息&#xff0c;突然发现一段很奇怪的报错&#xff1a;MultipartException&#xff0c;主观认为导致这个问题的原因无非就几个原因&#xff1a; 文件上传格式大小超出限制&#xff0c;在配置文…

Llama 3超级课堂作业笔记

文章目录 基础作业完成 Llama 3 Web Demo 部署环境配置下载模型Web Demo 部署对话截图 使用 XTuner 完成小助手认知微调Web Demo 部署自我认知训练数据集准备训练模型推理验证 使用 LMDeploy 成功部署 Llama 3 模型环境&#xff0c;模型准备LMDeploy CLI chatLMDeploy模型量化(…