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

文章目录

    • 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-optionlabel="销售属性":value="0"></el-option><el-optionlabel="基本属性":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-cascaderfilterableplaceholder="请选择"v-model="cascadedCategoryId":options="categories":props="props"></el-cascader></el-form-item>
2.数据池
        categories: [], // 树形数据cascadedCategoryId: [], // 级联选择器的值,从 categories 中取props: {value: 'id', // 从 categories 中取 id放到 cascadedCategoryIdlabel: '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}) => { // 解构了dataconsole.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-optionv-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 // 事务注解@Overridepublic 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 {// 引入分页插件@Beanpublic PaginationInterceptor paginationInterceptor() {PaginationInterceptor paginationInterceptor = new PaginationInterceptor();// 设置请求的页面大于最大页后操作,// true 调回到首页,false 继续请求 默认 falsepaginationInterceptor.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
    @Overridepublic PageUtils queryPage(Map<String, Object> params) {// 获取keyString 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 即可
    @Overridepublic PageUtils queryPageOnSale(Map<String, Object> params) {// 获取keyString 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-optionlabel="销售属性":value="0"></el-option><el-optionlabel="基本属性":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-cascaderfilterableplaceholder="请选择"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
    @Overridepublic 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,找出所有父分类的idList<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.mzph.cn/news/839011.shtml

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

相关文章

python科研数据可视化之折线图

例如 &#xff1a; 下面的配色表画出的图很好看。选择喜欢的颜色&#xff0c;找到代码中颜色部分进行修改即可。 代码部分已经有详细的注释&#xff0c;就不一一解释了。另外&#xff0c;如果想要坐标轴从设定的值开始就把下面代码中的范围xlim&#xff0c;ylim进行注释。 imp…

设计模式12——外观模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 外观模式&#xff08;Facade&a…

javaSwing购物系统项目(文档+视频+源码)

摘要 由Java swing实现的一款简单的购物程序&#xff0c;数据库采用的是mysql&#xff0c;该项目非常简单&#xff0c;实现了管理员对商品类型和商品的管理及用户注册登录后浏览商品、加入购物车、购买商品等功能&#xff0c;旨在学习Java 图形界面开发 系统实现 我们先来管理…

CF451E: Devu and Flowers(容斥原理 + 考虑反面 + golang组合模版)

题目截图 题目翻译 题目分析 正难则反&#xff0c;考虑所有不符合的例子 由于n很小&#xff0c;所以可以状态压缩二进制遍历完全部不符合例子的组合 对于不符合的例子&#xff0c;假设其中第i个不符合&#xff0c;那么就消耗掉fi 1个球 以此类推&#xff0c;减剩下s2个球 这时…

一剪梅-答赠云安客刘自果

当众网友看了笔者“边吸氧边动鼠标”的短视频之后&#xff0c;纷纷发来微信问候。其中我的远房亲戚&#xff0c;那个正在潜心写作数十万字的长篇纪实文学《川江向东流》的66岁贤弟刘自果&#xff08;号云安客&#xff0c;亦称自果居士&#xff09;&#xff0c;发来微信鼓励我&a…

【Vue】性能优化

使用 key 对于通过循环生成的列表&#xff0c;应给每个列表项一个稳定且唯一的 key&#xff0c;这有利于在列表变动时&#xff0c;尽量少的删除和新增元素。 使用冻结的对象 冻结的对象&#xff08;Object.freeze(obj)&#xff09;不会被响应化&#xff0c;不可变。 使用函…

【Linux】网络层——IP协议

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;Linux 目录 &#x1f449;&#x1f3fb;IP协议基本概念&#x1f449;&#x1f3fb;IP的协议头格式&#x1f449;&#x1f3fb;IP协议的网段划分五类IP地址子…

mysql数据库主从复制,搭建从库

1 期望效果 假设我们现在有两个服务器&#xff0c;两个服务器都有数据库&#xff0c;然后我们命名一个叫主数据库&#xff08;Master&#xff09;&#xff0c;一个叫从数据库&#xff08;Slave&#xff09; 数据备份和容灾&#xff1a;通过主从复制&#xff0c;可以将主数据库…

618有什么宠物空气净化器推荐?希喂FreAir Lite宠物空气净化器真实体验

一、宠物空气净化器的必要性 掉毛季又来了&#xff0c;猫咪的毛发满天飞&#xff0c;怎么办&#xff1f;我家里的猫咪一到换毛季就掉满地的毛发&#xff0c;尤其喜欢在家里奔跑打闹&#xff0c;结果整个房间都是毛。为了减少家里空气中的浮毛&#xff0c;你都做过哪些努力呢&a…

关于「公 告」根据中华人民共和国法律,Bing 在中国内地暂停 “搜索自动建议” 功能 30 天

当我看见我们大家都这样我可放心了&#xff0c;我打开电脑搜索图片就发生了。 当我看见我们大家都这样我可放心了&#xff0c;坐等攻城狮修复。

关闭以及启动ubuntu图形界面

关闭以及启动ubuntu图形界面 文章目录 关闭以及启动ubuntu图形界面1. 关闭图形界面2. 打开图形界面 如果你误杀了Xorg进程&#xff0c;需要重新启动图形界面&#xff0c;可以按照以下步骤操作&#xff1a; 1. 关闭图形界面 查看当前启动的图形界面&#xff1a; 使用下面命令…

LeetCode刷题之HOT100之比特位计数

今天把仙剑三看完了&#xff0c;茂茂割肉让人无法释怀&#xff0c;眼泪止不住的流。长卿和紫萱的分离似乎也意味着重逢&#xff0c;这就是他们的宿命吧。怅然若失的感觉席卷全身&#xff0c;哎&#xff0c;做题吧。 1、题目描述 2、逻辑分析 题目要求将整数从0到此元素&#…

【GO基础】1. Go语言环境搭建

Go语言环境搭建 Go的三种安装方式Go标准包安装Windows 安装验证是否安装成功 4.Go的第一个程序 Hello World.go Go的三种安装方式 Go有多种安装方式&#xff0c;可以选择自己适合的。这里介绍三种最常见的安装方式&#xff1a; Go源码安装&#xff1a;这是一种标准的软件安装…

零门槛微调大模型:基于 Ludwig 低代码框架使用 LoRA 技术微调实践

一、Ludwig 介绍 自然语言处理 (NLP) 和人工智能 (AI) 的飞速发展催生了许多强大的模型&#xff0c;它们能够理解和生成如同人类般的文本&#xff0c;为聊天机器人、文档摘要等应用领域带来了革命性的改变。然而&#xff0c;释放这些模型的全部潜力需要针对特定用例进行微调。…

QTextEdit 控件上显示信息:

目录 1. 使用 append 方法: 2. 使用 setPlainText 方法 3.例子&#xff1a; 1. 使用 append 方法: 如果你希望在 QTextEdit 控件上追加显示新的信息&#xff0c;可以使用 append 方法。例如&#xff0c;当你想要追加一行新的日志信息&#xff1a; self.text_edit.append(&…

于ThinkPHP开发的赛事报名小程序

基于ThinkPHP开发的赛事报名微信小程序 功能包括 1、参赛公告 2、会员中心&#xff08;会员注册、登录、成绩查询、资料管理、参赛记录管理&#xff09; 3、个人报名和企业报名 &#xff08;身份证验证防止重复报名&#xff09; 4、培训报名 5、查询是否在库人员&#xff0c;根…

3---版本库和工作区、使用.git管理工作区的文件、HEAD指针和master的关系

一、本地仓库和工作区的概念&#xff1a; 1.1本地仓库——版本库&#xff1a; 本地仓库又称为版本库。版本库是隐藏目录.git&#xff0c;并不是.git所在的目录。版本库不属于工作区。我们不能手动操作.git目录及其中的文件&#xff0c;这样可能会直接破坏版本库。stage(暂存区…

Day21:Leetcode513.找树左下角的值 +112. 路径总和 113.路径总和ii + 106.从中序与后序遍历序列构造二叉树

LeetCode&#xff1a;513.找树左下角的值 解决方案&#xff1a; 1.思路 在遍历一个节点时&#xff0c;需要先把它的非空右子节点放入队列&#xff0c;然后再把它的非空左子节点放入队列&#xff0c;这样才能保证从右到左遍历每一层的节点。广度优先搜索所遍历的最后一个节点…

测试驱动编程(2)进阶单元测试(上)

文章目录 测试驱动编程(2)进阶单元测试&#xff08;上&#xff09;单元测试单元测试正确打开方式各类测试比较 TDD中的单元测试 测试驱动编程(2)进阶单元测试&#xff08;上&#xff09; 单元测试 要打造出出类拔萃的作品&#xff0c;你必须专注于最小的细节 单元测试正确打…

易刷多平台广告掘金挂机脚本,单号一天至少10-30+【挂机脚本+使用教程】

易刷多平台广告掘金挂机脚本&#xff0c;每天单号可以至少获取10-30的收益。我们提供【挂机脚本使用教程】。 项目介绍&#xff1a; 我们今天为大家带来的是一款多平台的掘金脚本。 这款脚本支持25个平台掘金&#xff0c;可以帮助您解决频繁下载其他脚本的问题。 设备需求&am…