Mysql+MybatisPlus+Vue实现基础增删改查CRUD

news2024/11/23 6:21:00

数据库

设计数据库

设计几个字段,主键id自动增长且不可为空

create table if not exists `user`
(
    `id`       bigint(20) primary key auto_increment comment '主键id',
    `username` varchar(255)   not null comment '用户名',
    `sex`      char(1)        not null comment '性别',
    `phone`    varchar(22)    not null comment '手机号',
    `city`     varchar(255)   not null comment '所在城市',
    `position` varchar(255)   not null comment '职位',
    `salary`   decimal(18, 2) not null comment '工资:长度18,保留2位小数'
) engine InnoDB comment '用户表';

插入数据

随机插入几条数据

INSERT INTO `user` (`username`, `sex`, `phone`, `city`, `position`, `salary`) VALUES
('张三', '男', '13912345678', '北京', '软件工程师', 10000.00),
('李四', '女', '13723456789', '上海', '数据分析师', 12000.00),
('王五', '男', '15034567890', '广州', '产品经理', 15000.00),
('赵六', '女', '15145678901', '深圳', '前端工程师', 11000.00),
('刘七', '男', '15856789012', '成都', '测试工程师', 9000.00),
('陈八', '女', '13967890123', '重庆', 'UI设计师', 8000.00),
('朱九', '男', '13778901234', '武汉', '运维工程师', 10000.00),
('杨十', '女', '15089012345', '南京', '数据工程师', 13000.00),
('孙十一', '男', '15190123456', '杭州', '后端工程师', 12000.00),
('周十二', '女', '15801234567', '天津', '产品设计师', 11000.00);
select * from user;

查询成功则建表以及插入数据都成功
在这里插入图片描述

后端

实体类

根据数据库进行实体类的书写,功能要求可以后期再加

package com.wedu.modules.my.entity;

import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * <p>
 * 用户表
 * </p>
 *
 * @author xw
 * @since 2024-01-26
 */
@Data
@TableName("user")
@ApiModel(value="User对象", description="用户表")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键id")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @ApiModelProperty(value = "用户名")
    private String username;

    @ApiModelProperty(value = "性别")
    private String sex;

    @ApiModelProperty(value = "手机号")
    private String phone;

    @ApiModelProperty(value = "所在城市")
    private String city;

    @ApiModelProperty(value = "职位")
    private String position;

    @ApiModelProperty(value = "工资:长度18位,保留2位小数")
    private BigDecimal salary;


}

dao层

使用mybatisplus的框架方法
继承BaseMapper使用其中基础的功能,进行增删改查的撰写

/**
 * 系统用户 增删改查
 * 要给mapper层添加@Mapper和@Repository注解
 */
@Mapper
@Repository
public interface UserMapper extends BaseMapper<User> {
}

service层

在当前层下写一个接口继承IService模板提供的基础功能

/**
 * IUserService继承IService模板提供的基础功能和方法
 */
public interface IUserService extends IService<User> {

}


再写一个实现类去实现,由于现在接口中没有方法需要实现,所以实现类中无需实现

/**
 * MyUserServiceImpl实现了IService,提供了IService中基础功能的实现
 * 若MyUserServiceImpl无法满足业务需求,则可以使用自定的MyUserService定义方法,并在实现类中实现
 * service的impl实现类的注释要加实现的是哪个接口
 */
@Service("iUserService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}

controller层

新建一个UserController 继承AbstractController 中的方法,可以调用进行删除用户和后续修改根据id得到用户,@RequestMapping("/my/test")表示下面如果再加路径,比如@GetMapping("/select"),查询的路径则是/my/test/select,具有全局效应

@RestController
@RequestMapping("/my/test")
public class UserController extends AbstractController {

}

前端

test.vue

首先在modules文件夹下新建一个my文件夹,在my文件夹内新建一个userrr的vue文件,下载了帮助插件的小伙伴就可以打一个<v,选择第一行回车就能得到一个快速撰写vue界面的模板
在这里插入图片描述
出来的界面就像下面的代码片一样,可以在template标签中导入element 要显示的标签主键等,然后进行批量页面渲染,在script标签内写自己所创建的方法或者从外部的引入,style内放什么无需多讲,相信大家都学过css

<template>
  
</template>

<script>
export default {

}
</script>

<style>

</style>

此时我们数据库已经写好,后端和前端模板都已生成,下一步可以进行增删改查的书写

查询所有用户列表

我们需要查询数据库内所有数据,展示在前端页面中

1.新建表单

在template内新建表单,将表单设置为内联,使控件水平排列

<template>
  <div>
    <el-form :inline="true">
    
    </el-form>
  </div>
</template>

2.新建表单项

在新建的表单内新建表单项,在表单项内写一个查询按钮,触发点击即可查询事件

<template>
  <div>
    <el-form :inline="true">
      <!-- 按钮 -->
      <el-form-item>
        <!-- 查询按钮 -->
        <el-button @click="search()">查询</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

3.查询方法search

export default {}内的methods:{}中写一个查询方法search(),用这个方法获取当前数据列表getDataList

<script>
export default {
  methods: {
    // 查询
    search() {
      this.getDataList();
    },
  },
};
</script>

4.初始化数据集合

数据列表需要在data(){return{}}内进行初始化,当页的数据集合dataList初始化为空数组

<script>
export default {
  data() {
    return {
      dataList: [],
    };
  },
  methods: {
    // 查询
    search() {
      this.getDataList();
    },
  },
};
</script>

5.发送请求获取当前数据列表

获取当前数据列表的getDataList也是一个方法,在方法模块中和查询方法同级,获取数据列表需要向后端发送一个请求this.$http({}),使用ajax请求url地址,这里为了解决跨域问题用到了一个请求地址处理adornUrl(),写入请求路径/xx/xx/xx即可,请求方式根据restful url设计风格来,查询get,添加post,更新put,删除delete,这里查询到的参数还要进行get请求参数处理adornParams,根据后端传递的参数进行处理,有就写没有就忽略。发送请求之后要进行.then判断,如果data存在且data的code值恒等于(===)0则返回当页数据放入data初始化的集合内,不满足则还是为空。
需要code恒等于0是因为后端与前端交互是通过R返回数据,R构造器中默认code等于0的时候返回数据才会成功,恒等于代表着值相同且类型相同,避免了一些由于值相同但类型不同返回的错误数据

<script>
export default {
  data() {
    return {
      dataList: [],
    };
  },
  methods: {
    // 查询
    search() {
      this.getDataList();
    },
    // 获取数据列表
    getDataList() {
      this.$http({
        url: this.$http.adornUrl("/my/test/select"),
        method: "get",
        params: this.$http.adornParams({
        }),
      }).then(({ data }) => {
        if (data && data.code === 0) {
          this.dataList = data.dataList;
        } else {
          this.dataList = [];
        }
      });
    },
  },
};
</script>

6.activated生命周期钩子

在export default {}内可以使用生命周期钩子激活组件,这里就可以用activated生命周期钩子激活组件的时候执行getDataList方法获取数据列表,生命周期钩子与data、methods同级

<script>
export default {
  data() {
    return {
      dataList: [],
    };
  },
  activated() {
    this.getDataList();
  },
  methods: {
    // 查询
    search() {
      this.getDataList();
    },
    // 获取数据列表
    getDataList() {
      this.$http({
        url: this.$http.adornUrl("/my/test/select"),
        method: "get",
        params: this.$http.adornParams({
        }),
      }).then(({ data }) => {
        if (data && data.code === 0) {
          this.dataList = data.dataList;
        } else {
          this.dataList = [];
        }
      });
    },
  },
};
</script>

7.新建表格

和表单项同级,新建表格显示数据,表格双向绑定dataList,为每个元素生成一行数据,border边框,style属性设置宽度100%

<template>
  <div>
    <el-form :inline="true">
      <!-- 按钮 -->
      <el-form-item>
        <!-- 查询按钮 -->
        <el-button @click="search()">查询</el-button>
      </el-form-item>
    </el-form>
    <!-- 数据列表表格 -->
    <el-table :data="dataList" border style="width: 100%">
    </el-table>
  </div>
</template>

8.el-table-column

在新建的表格内写表格项el-table-column,内置属性prop写数据库对应列内容的字段名,header-align表头对齐方式和align对齐方式都可显示为居中center,label显示标题

<template>
  <div>
    <el-form :inline="true">
      <!-- 按钮 -->
      <el-form-item>
        <!-- 查询按钮 -->
        <el-button @click="search()">查询</el-button>
      </el-form-item>
    </el-form>
    <!-- 数据列表表格 -->
    <el-table :data="dataList" border style="width: 100%">
      <el-table-column
        prop="id"
        header-align="center"
        align="center"
        label="ID"
      ></el-table-column>
      <el-table-column
        prop="username"
        header-align="center"
        align="center"
        label="用户名"
      ></el-table-column>
      <el-table-column
        prop="sex"
        header-align="center"
        align="center"
        label="性别"
      ></el-table-column>
      <el-table-column
        prop="phone"
        header-align="center"
        align="center"
        label="手机号"
      ></el-table-column>
      <el-table-column
        prop="city"
        header-align="center"
        align="center"
        label="所在城市"
      ></el-table-column>
      <el-table-column
        prop="position"
        header-align="center"
        align="center"
        label="职位"
      ></el-table-column>
      <el-table-column
        prop="salary"
        header-align="center"
        align="center"
        label="工资"
      ></el-table-column>
    </el-table>
  </div>
</template>

9.在UserController内写查询方法

查询所有用户可以回忆一下之前mybatisplus是怎么查询的,仿照着写即可,不过有一些区别,上次写mybatisplus是纯后端,现在要和前端进行连接,所以要使用R这个对象,这是给前端返回的对象
LambdaQueryWrapper和QueryWrapper在这里都可以用作于简单的查询,LambdaQueryWrapper使用lambda表达式可以直接通过实体类get()属性,而QueryWrapper必须要与数据库的中表名一致

    
    //在controller层引用service层接口对象
    @Autowired
    private IUserService iUserService;

    /**
     * 查询所有用户列表
     */
    @GetMapping("/select")
    public R selectAll(){
        LambdaQueryWrapper<User> ulqw = new LambdaQueryWrapper<>();
        //查询出来的所有数据放入数据库表实体类对象的集合中
        List<User> dataList=iUserService.list(ulqw);
        
        //查询所有用户方法在mapper继承的baseMapper内有方法封装可直接调用,用多态的写法
		//List<User> dataList=iUserService.getBaseMapper().selectList(null);
		
		//通过R的ok方法put键值对返回给前端,这里返回的键就是获取数据列表发送请求成功后需要展示的数据集合
        return R.ok().put("dataList",dataList);
    }

10.前端接收查询并显示在页面上

在这里插入图片描述

分页查询

  • 1.在service接口内根据不同的key构建SQL查询条件,结合分页参数进行数据库查询,最后将查询结果封装成PageUtils对象返回给调用者
  • 2.在接口实现类里重写这个接口方法,先从map对象中获取键对应的值,再根据给定的参数查询实体类表中用户的信息,返回一个分页结果。定义一个泛型为SysUserEntity的分页对象,用于存储查询后的分页数据;创建一个新的Query对象,并调用getPage方法初始化一个分页对象;创建一个新的QueryWrapper对象,构建复杂条件查询SQL语句的对象;.like:如果username不为空或空白字符串isnotblank,则在生成的SQL查询中添加一个LIKE条件,匹配所有username字段与给定username值相匹配的记录;.eq:如果createUserId不为null,则在生成的SQL查询中添加一个等于(EQ)条件,匹配所有create_user_id字段与给定createUserId值相等的记录;返回新的分页对象PageUtils
  • 3.给service的接口传入params参数,返回一个分页page,返回一个成功的响应结果

IUserService

public interface IUserService extends IService<User> {

    /**
     * 在service接口内根据不同的key构建SQL查询条件,结合分页参数进行数据库查询,最后将查询结果封装成PageUtils对象返回给调用者
     */
    PageUtils queryPage(Map<String,Object> params);
}

UserServiceImpl

@Service("iUserService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
	@Override
    /*返回PageUtils工具类对象*/
    public PageUtils queryPage(Map<String, Object> params) {
        String username = (String) params.get("username");
        String phone = (String) params.get("phone");

        /*分页查询*/
        IPage<User> page=this.page(
                new Query<User>().getPage(params),
                new QueryWrapper<User>()
                        /*like-模糊查询*/
                .like(StringUtils.isNotBlank(username),"username",username)
                        /*eq-相等*/
                .eq(phone!=null,"phone",phone)
        );
        return new PageUtils(page);
    }
}

UserController

@RestController
@RequestMapping("/my/test")
public class UserController extends AbstractController {
    @Autowired
    private IUserService iUserService;

    //分页查询
    @GetMapping("/list")
    //@RequestParam 将前端发送的请求参数绑定到controller层的方法参数上
    public R list(@RequestParam Map<String,Object> params){
        PageUtils page = iUserService.queryPage(params);
        return R.ok().put("page",page);
    }

}

ttt.vue

<template>
  <div>
    <el-form :inline="true" :model="dataForm" @keyup.enter.native="search()">
        <el-form-item>
            <el-input v-model="dataForm.username" placeholder="请输入用户名" clearable></el-input>
        </el-form-item>
        <el-form-item>
            <el-button @click="search()">查询</el-button>
        </el-form-item>
    </el-form>
    <el-table :data="dataList" border style="width: 100%;">
        <el-table-column
        prop="id"
        header-align="center"
        align="center"
        width="80"
        label="ID"
      ></el-table-column>
      <el-table-column
        prop="username"
        header-align="center"
        align="center"
        label="用户名"
      ></el-table-column>
      <el-table-column
        prop="sex"
        header-align="center"
        align="center"
        label="性别"
      ></el-table-column>
      <el-table-column
        prop="phone"
        header-align="center"
        align="center"
        label="手机号"
      ></el-table-column>
      <el-table-column
        prop="city"
        header-align="center"
        align="center"
        label="所在城市"
      ></el-table-column>
      <el-table-column
        prop="position"
        header-align="center"
        align="center"
        label="职位"
      ></el-table-column>
      <el-table-column
        prop="salary"
        header-align="center"
        align="center"
        label="工资"
      ></el-table-column>
    </el-table>
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="pageIndex"
      :page-sizes="[10, 20, 50, 100]"
      :page-size="pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="totalPage"
    >
    </el-pagination>
  </div>
</template>

<script>
export default {
    data(){
        return{
            dataForm:{
                username:''
            },
            dataList:[],
            pageIndex:1,
            pageSize:10,
            totalPage:0
        }
    },
    activated(){
        this.getDataList()
    },
    methods:{
        search(){
            this.pageIndex = 1
            this.getDataList()
        },
        getDataList(){
            this.$http({
                url:this.$http.adornUrl("/my/test/list"),
                method:'get',
                params:this.$http.adornParams({
                    page:this.pageIndex,
                    limit:this.pageSize,
                    username:this.dataForm.username
                })
            }).then(({data})=>{
                if(data&&data.code===0){
                    this.dataList=data.page.list;
                    this.totalPage=data.page.totalCount;
                }else{
                    this.dataList=[];
                    this.totalPage=0
                }
            })
        },
        handleSizeChange(val){
            this.pageSize=val;
            this.pageIndex=1;
            this.getDataList();
        },
        handleCurrentChange(val){
            this.pageIndex=val;
            this.getDataList();
        }
    }
}
</script>

<style>

</style>

分页查询总结

默认查询数据库内全部信息,按照分页查询一页10条信息,左上角请输入用户名,可以输入完整的用户名,也可以模糊查询,写入按回车或者点查询都是可以查到想到的数据的,如果输错了可以点框框最右边的叉叉全删
在这里插入图片描述

删除(单个或批量)

  • 1.根据传入的一组用户id,一次性从数据库删除多个用户且无返回值
  • 2.将传入的用户id转换为一个ArrayList,再通过removeByIds方法一次性删除所有指定id对象
  • 3.删除用户前三个注释,系统日志注解SysLog、请求方式注解PostMapping、权限注解RequiresPermissions,其中权限注解暂时不写,在controller层的传入对象前加上请求体RequestBody;如果要删除的id里包含1就返回错误信息:它有系统管理员不能删除,调用service层的删除方法,传入ids进行删除,方法没有返回值,最后将结果返回给前端,让前端展现

方法一

IUserService

    /**
     * 根据传入的一组用户id,一次性从数据库删除多个用户且无返回值
     */
    void deleteBatch(Long[] ids);

UserServiceImpl

    @Override
    public void deleteBatch(Long[] ids) {
        this.removeByIds(Arrays.asList(ids));
    }

UserController

    //批量删除
    @SysLog("批量删除")
    @PostMapping("/delete")
    public R delete(@RequestBody Long[] ids){
        if (ArrayUtils.contains(ids,1l)){
            return R.error("有主键,不可删除");
        }

        iUserService.deleteBatch(ids);

        return R.ok();

    }

在这里插入图片描述
仿照写

ttt.vue

<template>
  <div>
    <el-form :inline="true" :model="dataForm" @keyup.enter.native="search()">
      <el-form-item>
        <el-input
          v-model="dataForm.username"
          placeholder="请输入用户名"
          clearable
        ></el-input>
      </el-form-item>
      <el-form-item>
        <el-button @click="search()">查询</el-button>
        <el-button
          type="danger"
          @click="deleteHandle()"
          :disabled="dataListSelections.length <= 0"
          >批量删除</el-button
        >
      </el-form-item>
    </el-form>
    <el-table
      :data="dataList"
      border
      @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"
        width="80"
        label="ID"
      ></el-table-column>
      <el-table-column
        prop="username"
        header-align="center"
        align="center"
        label="用户名"
      ></el-table-column>
      <el-table-column
        prop="sex"
        header-align="center"
        align="center"
        label="性别"
      ></el-table-column>
      <el-table-column
        prop="phone"
        header-align="center"
        align="center"
        label="手机号"
      ></el-table-column>
      <el-table-column
        prop="city"
        header-align="center"
        align="center"
        label="所在城市"
      ></el-table-column>
      <el-table-column
        prop="position"
        header-align="center"
        align="center"
        label="职位"
      ></el-table-column>
      <el-table-column
        prop="salary"
        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="medium"
            @click="deleteHandle(scope.row.id)"
            >删除</el-button
          >
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="pageIndex"
      :page-sizes="[10, 20, 50, 100]"
      :page-size="pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="totalPage"
    >
    </el-pagination>
  </div>
</template>

<script>
export default {
  data() {
    return {
      dataForm: {
        username: "",
      },
      dataList: [],
      pageIndex: 1,
      pageSize: 10,
      totalPage: 0,
      dataListSelections: [],
    };
  },
  activated() {
    this.getDataList();
  },
  methods: {
    search() {
      this.pageIndex = 1;
      this.getDataList();
    },
    getDataList() {
      this.$http({
        url: this.$http.adornUrl("/my/test/list"),
        method: "get",
        params: this.$http.adornParams({
          page: this.pageIndex,
          limit: this.pageSize,
          username: this.dataForm.username,
        }),
      }).then(({ data }) => {
        if (data && data.code === 0) {
          this.dataList = data.page.list;
          this.totalPage = data.page.totalCount;
        } else {
          this.dataList = [];
          this.totalPage = 0;
        }
      });
    },
    handleSizeChange(val) {
      this.pageSize = val;
      this.pageIndex = 1;
      this.getDataList();
    },
    handleCurrentChange(val) {
      this.pageIndex = val;
      this.getDataList();
    },
    selectionChangeHandle(val) {
      this.dataListSelections = val;
    },
    deleteHandle(id) {
      var ids = id
        ? [id]
        : this.dataListSelections.map((item) => {
            return item.id;
          });
      this.$confirm(
        `确定对[id=${ids.join(",")}]进行[${id ? "删除" : "批量删除"}]操作?`,
        "提示",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }
      ).then(() => {
        this.$http({
          url: this.$http.adornUrl("/my/test/delete"),
          method: "post",
          data: this.$http.adornData(ids, false),
        })
          .then(({ data }) => {
            if (data && data.code === 0) {
              this.$message({
                type: "success",
                message: "删除成功!",
                onClose: () => {
                  this.getDataList();
                },
              });
            } else {
              this.$message.error(data.msg);
            }
          })  
      }).catch(() => {
            this.$message({
              type: "info",
              message: "已取消删除",
            });
          });
    },
  },
};
</script>

<style>
</style>

方法二

在实现层只有一行代码无具体实现逻辑时可直接在controller层写该行实现代码(简便写法)
不用写service层方法,直接调用继承接口中的方法

UserController

    //批量删除
    @SysLog("批量删除")
    @PostMapping("/delete")
    public R delete(@RequestBody Long[] ids){
        if (ArrayUtils.contains(ids,1l)){
            return R.error("有主键,不可删除");
        }

        iUserService.removeByIds(Arrays.asList(ids));

        return R.ok();

    }

新增

  • 1.形参为用户实体类,用到的方法是IService中的save保存
  • 2.先使用hibernate-validator校验工具类ValidatorUtils里的校验方法validateEntity,传入实体类和新增数据所需验证规则的注解组AddGroup(一些数据不能为空或者有特定的规则)
  • 3.调用iUserService类接口继承的save方法,传入新增用户保存
  • 4.返回一个成功的响应结果

方法一

IUserService

void saveUser(User user);

UserServiceImpl

    @Override
    public void saveUser(User user) {
        this.save(user);
    }

UserController

    //新增
    @SysLog("新增用户")
    @PostMapping("/save")
    public R save(@RequestBody User user){
        ValidatorUtils.validateEntity(user, AddGroup.class);
        iUserService.saveUser(user);
        return R.ok();
    }

方法二

不用写service层方法,直接调用继承接口中的方法

UserController

    //新增
    @SysLog("新增用户")
    @PostMapping("/save")
    public R save(@RequestBody User user){
        ValidatorUtils.validateEntity(user, AddGroup.class);
        iUserService.save(user);
        return R.ok();
    }

修改

  • 1.和新增用户类似,使用方法为updateById,也是继承接口中的方法
  • 2.注解组变为UpdateGroup,也需要验证

方法一

IUserService

void updateUser(User user);

UserServiceImpl

    @Override
    public void updateUser(User user) {
        this.updateById(user);
    }

UserController

    //修改
    @SysLog("修改用户")
    @PostMapping("/update")
    public R update(@RequestBody User user){
        ValidatorUtils.validateEntity(user, UpdateGroup.class);
        iUserService.updateUser(user);
        return R.ok();
    }

方法二

不用写service层方法,直接调用继承接口中的方法

UserController

    //修改
    @SysLog("修改用户")
    @PostMapping("/update")
    public R update(@RequestBody User user){
        ValidatorUtils.validateEntity(user, UpdateGroup.class);
        iUserService.updateById(user);
        return R.ok();
    }

新增和修改为相同的方法

二者区别在于是否传入id,可以根据是否传入id来进行新增或是修改

ttt.vue最终版

  • 1.新增按钮:在查询和批量删除中间,类型为primary主要,点击触发addOrUpdateHandle事件
  • 2.修改按钮:和删除并列,写法也与删除类似
  • 3.在分页下写一个弹窗add-or-update:和addOrUpdateVisible双向绑定,默认false不弹出,需要在data内初始化,注册组件引用addOrUpdate,刷新数据集合refreshDataList,和getDataList双向绑定
  • 4.import...from...:从xx导入AddOrUpdate模块->对新增和修改的具体写法放在另一个界面内
  • 5.注册组件:components内写组件的名字
  • 6.addOrUpdateHandle方法:传入一个id,有id值的则为修改,没有传入的则为新增;此时需要弹出新增/修改弹窗,所以要把addOrUpdateVisible写为true弹出;弹出之后才会有下一步$nextTick指向当前访问的$refs对象,在访问的对象中查找addOrUpdate的子组件,调用子组件的init方法并传入一个id
  • 此时主页面已写完,需要自行写addOrUpdate子组件
<template>
  <div>
    <el-form :inline="true" :model="dataForm" @keyup.enter.native="search()">
      <el-form-item>
        <el-input
          v-model="dataForm.username"
          placeholder="请输入用户名"
          clearable
        ></el-input>
      </el-form-item>
      <el-form-item>
        <el-button @click="search()">查询</el-button>
        <el-button type="primary" @click="addOrUpdateHandle()">新增</el-button>
        <el-button
          type="danger"
          @click="deleteHandle()"
          :disabled="dataListSelections.length <= 0"
          >批量删除</el-button
        >
      </el-form-item>
    </el-form>
    <el-table
      :data="dataList"
      border
      @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"
        width="80"
        label="ID"
      ></el-table-column>
      <el-table-column
        prop="username"
        header-align="center"
        align="center"
        label="用户名"
      ></el-table-column>
      <el-table-column
        prop="sex"
        header-align="center"
        align="center"
        label="性别"
      ></el-table-column>
      <el-table-column
        prop="phone"
        header-align="center"
        align="center"
        label="手机号"
      ></el-table-column>
      <el-table-column
        prop="city"
        header-align="center"
        align="center"
        label="所在城市"
      ></el-table-column>
      <el-table-column
        prop="position"
        header-align="center"
        align="center"
        label="职位"
      ></el-table-column>
      <el-table-column
        prop="salary"
        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="medium"
            @click="deleteHandle(scope.row.id)"
            >删除</el-button
          >
          <el-button
            type="text"
            size="medium"
            @click="addOrUpdateHandle(scope.row.id)"
            >修改</el-button
          >
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="pageIndex"
      :page-sizes="[10, 20, 50, 100]"
      :page-size="pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="totalPage"
    >
    </el-pagination>
    <add-or-update
      v-if="addOrUpdateVisible"
      ref="addOrUpdate"
      @refreshDataList="getDataList"
    ></add-or-update>
  </div>
</template>
  
  <script>
import AddOrUpdate from "./ttt-add-or-update";
export default {
  data() {
    return {
      dataForm: {
        username: "",
      },
      dataList: [],
      pageIndex: 1,
      pageSize: 10,
      totalPage: 0,
      dataListSelections: [],
      addOrUpdateVisible: false,
    };
  },
  components: {
    AddOrUpdate,
  },
  activated() {
    this.getDataList();
  },
  methods: {
    search() {
      this.pageIndex = 1;
      this.getDataList();
    },
    getDataList() {
      this.$http({
        url: this.$http.adornUrl("/my/test/list"),
        method: "get",
        params: this.$http.adornParams({
          page: this.pageIndex,
          limit: this.pageSize,
          username: this.dataForm.username,
        }),
      }).then(({ data }) => {
        if (data && data.code === 0) {
          this.dataList = data.page.list;
          this.totalPage = data.page.totalCount;
        } else {
          this.dataList = [];
          this.totalPage = 0;
        }
      });
    },
    handleSizeChange(val) {
      this.pageSize = val;
      this.pageIndex = 1;
      this.getDataList();
    },
    handleCurrentChange(val) {
      this.pageIndex = val;
      this.getDataList();
    },
    selectionChangeHandle(val) {
      this.dataListSelections = val;
    },
    deleteHandle(id) {
      var ids = id
        ? [id]
        : this.dataListSelections.map((item) => {
            return item.id;
          });
      this.$confirm(
        `确定对[id=${ids.join(",")}]进行[${id ? "删除" : "批量删除"}]操作?`,
        "提示",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }
      )
        .then(() => {
          this.$http({
            url: this.$http.adornUrl("/my/test/delete"),
            method: "post",
            data: this.$http.adornData(ids, false),
          }).then(({ data }) => {
            if (data & (data.code === 0)) {
              this.$message({
                type: "success",
                message: "删除成功!",
                onClose: () => {
                  this.getDataList();
                },
              });
            } else {
              this.$message.error(data.msg);
            }
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },
    addOrUpdateHandle(id) {
      this.addOrUpdateVisible = true;
      this.$nextTick(() => {
        this.$refs.addOrUpdate.init(id);
      });
    },
  },
};
</script>
  
  <style>
</style>

ttt-add-or-update.vue

  • 1.根据对话框组件dialog写弹窗内容,动态设置标题内容,属性都需要双向绑定,无id传入就新增,有id传入就修改,将close-on-click-modal设置为false
  • 2.在对话框内写表单,和dataForm双向绑定,dataForm内有数据库全部字段;和dataRule双向绑定,用户名等不为空,手机号有特殊验证格式,通过ref直接访问dataForm dom元素,绑定回车即提交表单事件
  • 3.表单项:username、sex、phone、city、position、salary,均有label、prop属性
  • 4.表单项内username输入框,双向绑定dataForm的username,占位文本placeholder
  • 5.性别男女保密单选
  • 6.最后复制底部插槽 修改确定的点击事件为提交表单事件
  • 可以去element官网找寻自己需要的组件 点击进入element官网
    在这里插入图片描述
<template>
  <el-dialog
    :title="!dataForm.id ? '新增' : '修改'"
    :visible.sync="dialogVisible"
    :before-close="handleClose"
    :close-on-click-modal="false"
  >
    <el-form
      :model="dataForm"
      :rules="dataRule"
      ref="dataForm"
      @keyup.enter.native="dataFormSubmit()"
    >
      <el-form-item label="用户名" prop="username">
        <el-input
          v-model="dataForm.username"
          placeholder="请输入用户名"
        ></el-input>
      </el-form-item>
      <el-form-item label="性别" prop="sex">
        <el-radio-group v-model="dataForm.sex">
           <el-radio label=""></el-radio> 
          <el-radio label=""></el-radio> 
          <el-radio label="保密"></el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="手机号" prop="phone">
        <el-input
          v-model="dataForm.phone"
          placeholder="请输入手机号"
        ></el-input>
      </el-form-item>
      <el-form-item label="所在城市" prop="city">
        <el-input
          v-model="dataForm.city"
          placeholder="请输入所在城市"
        ></el-input>
      </el-form-item>
      <el-form-item label="职位" prop="position">
        <el-input
          v-model="dataForm.position"
          placeholder="请输入职位"
        ></el-input>
      </el-form-item>
      <el-form-item label="工资" prop="salary">
        <el-input v-model="dataForm.salary" placeholder="请输入工资"></el-input>
      </el-form-item>
    </el-form>
    <span slot="footer" class="dialog-footer">
      <el-button @click="dialogVisible = false">取 消</el-button>
      <el-button type="primary" @click="dataFormSubmit()">确 定</el-button>
    </span>
  </el-dialog>
</template>
    
    <script>
export default {
  data() {
    return {
      dialogVisible: false,
      dataForm: {
        id: 0,
        username: "",
        sex: "",
        phone: "",
        city: "",
        position: "",
        salary: "",
      },
      dataRule: {},
    };
  },
  methods: {
      handleClose(done) {
        this.$confirm('确认关闭?')
          .then(_ => {
            done();
          })
          .catch(_ => {});
      },
    }
};
</script>
    
    <style>
</style>
    
    

init方法

1.init(id)根据传入的id值,真则修改,假则为0新增,左上角的标题随之动态改变
2.判断完了设置弹出弹窗为true
3.弹出了再进行下一步操作$nextTick用resetFields把表单内的数据都置空
4.如果有id,则修改单条数据,先根据id查询单条数据,请求方式以及参数处理,then对把data数据放入表单,如果data存在且code恒等于0则进行修改this.dataForm.xxx=data.user.xxx
这里涉及到一个根据id查找返回用户信息的方法

  methods: {
      handleClose(done) {
        this.$confirm('确认关闭?')
          .then(_ => {
            done();
          })
          .catch(_ => {});
      },
      init(id){
        this.dataForm.id=id||0;
        this.dialogVisible = true;
        this.$nextTick(()=>{
            this.$refs['dataForm'].resetFields();
        })
        if(this.dataForm.id){
            this.$http({
                url:this.$http.adornUrl(`/my/test/info/${this.dataForm.id}`),
                method:'get',
            }).then(({data})=>{
                if(data&&data.code===0){
                    this.dataForm.username=data.user.username;
                    this.dataForm.sex=data.user.sex;
                    this.dataForm.phone=data.user.phone;
                    this.dataForm.city=data.user.city;
                    this.dataForm.position=data.user.position;
                    this.dataForm.salary=data.user.salary;
                }
            })
        }
      }
    }

涉及到的info方法

    //根据id拿出用户信息
    @GetMapping("/info/{id}")
    public R info(@PathVariable Long id){
        User user = iUserService.getById(id);
        return R.ok().put("user",user);
    }

dataRule

1.不能为空:字段:[{required:true,message:“”,trigger:“blur”}]
2.手机号有特殊认证,再加一个{},在里面写验证函数validator: validateMobile
3.自定义函数validateMobile,验证规则对象rule,待验证的值value,回调函数用于通知验证结果callback
4.如果这个待验证的值不符合手机号格式(从另一个格式页面导入)就用回调函数返回一个错误消息,否则就通过验证,回调函数内什么也不写

<template>
  <el-dialog
    :title="!dataForm.id ? '新增' : '修改'"
    :visible.sync="dialogVisible"
    :before-close="handleClose"
    :close-on-click-modal="false"
  >
    <el-form
      :model="dataForm"
      :rules="dataRule"
      ref="dataForm"
      @keyup.enter.native="dataFormSubmit()"
    >
      <el-form-item label="用户名" prop="username">
        <el-input
          v-model="dataForm.username"
          placeholder="请输入用户名"
        ></el-input>
      </el-form-item>
      <el-form-item label="性别" prop="sex">
        <el-radio-group v-model="dataForm.sex">
           <el-radio label=""></el-radio> 
          <el-radio label=""></el-radio> 
          <el-radio label="保密"></el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="手机号" prop="phone">
        <el-input
          v-model="dataForm.phone"
          placeholder="请输入手机号"
        ></el-input>
      </el-form-item>
      <el-form-item label="所在城市" prop="city">
        <el-input
          v-model="dataForm.city"
          placeholder="请输入所在城市"
        ></el-input>
      </el-form-item>
      <el-form-item label="职位" prop="position">
        <el-input
          v-model="dataForm.position"
          placeholder="请输入职位"
        ></el-input>
      </el-form-item>
      <el-form-item label="工资" prop="salary">
        <el-input v-model="dataForm.salary" placeholder="请输入工资"></el-input>
      </el-form-item>
    </el-form>
    <span slot="footer" class="dialog-footer">
      <el-button @click="dialogVisible = false">取 消</el-button>
      <el-button type="primary" @click="dataFormSubmit()">确 定</el-button>
    </span>
  </el-dialog>
</template>
    
    <script>
    import { isMobile } from "@/utils/validate";
export default {
  data() {
    var valicatePhone=(rule,value,callback)=>{
        if(!isMobile(value)){
            callback(new Error('手机号格式错误,请重新输入'))
        }else{
            callback()
        }
    }
    return {
      dialogVisible: false,
      dataForm: {
        id: 0,
        username: "",
        sex: "",
        phone: "",
        city: "",
        position: "",
        salary: "",
      },
      dataRule: {
        username:[{required: true,message:'用户名不为空',trigger:'blur'}],
        phone:[{required: true,message:'手机号不为空',trigger:'blur'},{valivate:valicatePhone,trigger:'blur'}],
        city:[{required: true,message:'所在城市不为空',trigger:'blur'}],
        position:[{required: true,message:'职位不为空',trigger:'blur'}],
        salary:[{required: true,message:'薪水不为空',trigger:'blur'}],
      },
    };
  },
  methods: {
      handleClose(done) {
        this.$confirm('确认关闭?')
          .then(_ => {
            done();
          })
          .catch(_ => {});
      },
      init(id){
        this.dataForm.id=id||0;
        this.dialogVisible = true;
        this.$nextTick(()=>{
            this.$refs['dataForm'].resetFields();
        })
        if(this.dataForm.id){
            this.$http({
                url:this.$http.adornUrl(`/my/test/info/${this.dataForm.id}`),
                method:'get',
            }).then(({data})=>{
                if(data&&data.code===0){
                    this.dataForm.username=data.user.username;
                    this.dataForm.sex=data.user.sex;
                    this.dataForm.phone=data.user.phone;
                    this.dataForm.city=data.user.city;
                    this.dataForm.position=data.user.position;
                    this.dataForm.salary=data.user.salary;
                }
            })
        }
      }
    }
};
</script>
    
    <style>
</style>
    
    

dataFormSubmit

1.访问特定ref属性的dom元素dataForm并进行表单验证validate接收参数
2.如果验证成功,则发送请求,url内写一个三元表达式/xx/xx/${},和title的三元一样,没有id就save,有id就update,要用着重符号处理特殊字符,确保能发送请求,请求方式post要调用adornData传入数据对象,id要写一个逻辑或,是真的就取前面的值,假的就为undefined,其他全this.dataForm.xxx
3.then再处理data,如果存在且code恒等于0就发出提示信息,操作成功,关闭窗口的时候触发关闭事件,把标题重新设置为false,再用$emit方法触发刷新列表数据事件refreshDataList,否则显示data的错误信息

      dataFormSubmit() {
        this.$refs["dataForm"].validate((val) => {
          if (val) {
            this.$http({
              url: this.$http.adornUrl(
                `/my/test/${!this.dataForm.id ? "save" : "update"}`
              ),
              method: "post",
              data: this.$http.adornData({
                id: this.dataForm.id || undefined,
                username: this.dataForm.username,
                sex: this.dataForm.sex,
                phone: this.dataForm.phone,
                city: this.dataForm.city,
                position: this.dataForm.position,
                salary: this.dataForm.salary,
              }),
            }).then(({ data }) => {
              if (data && data.code === 0) {
                this.$message({
                  message: "操作成功",
                  type: "success",
                  onClose: () => {
                    this.dialogVisible = false;
                    this.$emit("refreshDataList");
                  },
                });
              } else {
                this.$message.Error(data.msg);
              }
            });
          }
        });
      },

ttt-add-or-update.vue最终版

<template>
  <el-dialog
    :title="!dataForm.id ? '新增' : '修改'"
    :visible.sync="dialogVisible"
    :close-on-click-modal="false"
    :before-close="handleClose"
  >
    <el-form
      :model="dataForm"
      :rules="dataRule"
      ref="dataForm"
      @keyup.enter.native="dataFormSubmit()"
    >
      <el-form-item label="用户名" prop="username">
        <el-input
          v-model="dataForm.username"
          placeholder="请输入用户名"
        ></el-input>
      </el-form-item>
      <el-form-item label="性别" prop="sex">
        <el-radio-group v-model="dataForm.sex">
          <el-radio label=""></el-radio>
          <el-radio label=""></el-radio>
          <el-radio label="保密"></el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="手机号" prop="phone">
        <el-input
          v-model="dataForm.phone"
          placeholder="请输入手机号"
        ></el-input>
      </el-form-item>
      <el-form-item label="所在城市" prop="city">
        <el-input
          v-model="dataForm.city"
          placeholder="请输入所在城市"
        ></el-input>
      </el-form-item>
      <el-form-item label="职位" prop="position">
        <el-input
          v-model="dataForm.position"
          placeholder="请输入职位"
        ></el-input>
      </el-form-item>
      <el-form-item label="工资" prop="salary">
        <el-input v-model="dataForm.salary" placeholder="请输入工资"></el-input>
      </el-form-item>
    </el-form>
    <span slot="footer" class="dialog-footer">
      <el-button @click="dialogVisible = false">取 消</el-button>
      <el-button type="primary" @click="dataFormSubmit()">确 定</el-button>
    </span>
  </el-dialog>
</template>

<script>
import { isMobile } from "@/utils/validate";
export default {
  data() {
    var validatePhone = (rule, value, callback) => {
      if (!isMobile(value)) {
        callback(new Error("手机号格式错误,请重新输入"));
      } else {
        callback();
      }
    };
    return {
      dataForm: {
        id: 0,
        username: "",
        sex: "",
        phone: "",
        city: "",
        position: "",
        salary: "",
      },
      dialogVisible: false,
      dataRule: {
        username: [
          { required: true, message: "用户名不为空", trigger: "blur" },
        ],
        phone: [
          { required: true, message: "手机号不为空", trigger: "blur" },
          { validator: validatePhone, trigger: "blur" },
        ],
        city: [{ required: true, message: "所在城市不为空", trigger: "blur" }],
        position: [{ required: true, message: "职位不为空", trigger: "blur" }],
        salary: [{ required: true, message: "工资不为空", trigger: "blur" }],
      },
    };
  },
  methods: {
    handleClose(done) {
      this.$confirm("确认关闭?")
        .then((_) => {
          done();
        })
        .catch((_) => {});
    },
    init(id) {
      this.dataForm.id = id || 0;
      this.dialogVisible = true;
      this.$nextTick(() => {
        this.$refs["dataForm"].resetFields();
      });
      if (this.dataForm.id) {
        this.$http({
          url: this.$http.adornUrl(`/my/test/info/${this.dataForm.id}`),
          method: "get",
        }).then(({ data }) => {
          if (data && data.code === 0) {
            (this.dataForm.username = data.user.username),
              (this.dataForm.sex = data.user.sex),
              (this.dataForm.phone = data.user.phone),
              (this.dataForm.city = data.user.city),
              (this.dataForm.position = data.user.position),
              (this.dataForm.salary = data.user.salary);
          } 
        });
      }
    },
    dataFormSubmit() {
      this.$refs["dataForm"].validate((val) => {
        if (val) {
          this.$http({
            url: this.$http.adornUrl(
              `/my/test/${!this.dataForm.id ? "save" : "update"}`
            ),
            method: "post",
            data: this.$http.adornData({
              id: this.dataForm.id || undefined,
              username: this.dataForm.username,
              sex: this.dataForm.sex,
              phone: this.dataForm.phone,
              city: this.dataForm.city,
              position: this.dataForm.position,
              salary: this.dataForm.salary,
            }),
          }).then(({ data }) => {
            if (data && data.code === 0) {
              this.$message({
                message: "操作成功",
                type: "success",
                onClose: () => {
                  this.dialogVisible = false;
                  this.$emit("refreshDataList");
                },
              });
            } else {
              this.$message.Error(data.msg);
            }
          });
        }
      });
    },
  },
};
</script>

<style>
</style>

至此Mysql+MybatisPlus+Vue实现基础增删改查CRUD已基本完善

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

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

相关文章

十一、常用API——练习

常用API——练习 练习1 键盘录入&#xff1a;练习2 算法水题&#xff1a;练习3 算法水题&#xff1a;练习4 算法水题&#xff1a;练习5 算法水题&#xff1a; 练习1 键盘录入&#xff1a; 键盘录入一些1~100之间的整数&#xff0c;并添加到集合中。 直到集合中所有数据和超过2…

【新课】安装部署系列Ⅲ—Oracle 19c Data Guard部署之两节点RAC部署实战

本课程由云贝教育-刘峰老师出品&#xff0c;感谢关注 课程介绍 Oracle Real Application Clusters (RAC) 是一种跨多个节点分布数据库的企业级解决方案。它使组织能够通过实现容错和负载平衡来提高可用性和可扩展性&#xff0c;同时提高性能。本课程基于当前主流版本Oracle 1…

017 JavaDoc生成文档

什么是JavaDoc 示例 package se;/*** 用于学习Java* author Admin* version 1.0* since 1.8*/ public class Test20240119 {/*** 主方法* param args*/public static void main(String[] args) {// 你好&#xff0c;世界System.out.println("Hello world");} } 写一…

故障诊断 | 一文解决,GRU门控循环单元故障诊断(Matlab)

文章目录 效果一览文章概述专栏介绍模型描述源码设计参考资料效果一览 文章概述 故障诊断 | 一文解决,GRU门控循环单元故障诊断(Matlab) 专栏介绍 订阅【故障诊断】专栏,不定期更新机器学习和深度学习在故障诊断中的应用;订阅

opencv#40 图像细化

图像细化原理 作用&#xff1a;图像细化是将图像的线条从多像素宽度减少到单位像素宽度的过程&#xff0c;又被称为“骨架化”&#xff0c;删除像素点的标准&#xff1a; 通常情况下&#xff0c;我们使用二值化图像&#xff0c;我们在判断是否要删除某些像素点时&#xff0c;要…

遍历删除空文件夹

文章目录 遍历删除空文件夹概述笔记END 遍历删除空文件夹 概述 在手工整理openssl3.2编译完的源码工程中的文档, 其中有好多空文件夹. 做了一个小工具, 将空文件夹都遍历删除掉. 这样找文档方便一些. 删除后比对了一下, 空文件夹还真不少. 笔记 // EmptyDirRemove.cpp : 此…

音视频数字化(数字与模拟-音频广播)

在互联网飞速发展的今天,每晚能坐在电视机前面的人越来越少,但是每天收听广播仍旧是很多人的习惯。 从1906年美国费森登在实验室首次进行无线电广播算起,“广播”系统已经陪伴人们115年了。1916年,收音机开始上市,收音机核心是“矿石”。1920年开始“调幅”广播,1941年开…

Uniapp小程序端打包优化实践

背景描述&#xff1a; 在我们最近开发的一款基于uniapp的小程序项目中&#xff0c;随着功能的不断丰富和完善&#xff0c;发现小程序包体积逐渐增大&#xff0c;加载速度也受到了明显影响。为了提升用户体验&#xff0c;团队决定对小程序进行一系列打包优化。 项目优化点&…

Optimism的挑战期

1. 引言 前序博客&#xff1a; Optimism的Fault proof 用户将资产从OP主网转移到以太坊主网时需要等待一周的时间。这段时间称为挑战期&#xff0c;有助于保护 OP 主网上存储的资产。 而OP测试网的挑战期仅为60秒&#xff0c;以简化开发过程。 2. OP与L1数据交互 L1&#xf…

无人机除冰保障电网稳定运行

无人机除冰保障电网稳定运行 近日&#xff0c;受低温雨雪冰冻天气影响&#xff0c;福鼎市多条输配电线路出现不同程度覆冰。 为保障福鼎电网安全可靠运行&#xff0c;供电所员工运用无人机飞行技术&#xff0c;通过在无人机下方悬挂器具&#xff0c;将无人机飞到10千伏青坑线…

第5章 python深度学习——波斯美女

第5章 深度学习用于计算机视觉 本章包括以下内容&#xff1a; 理解卷积神经网络&#xff08;convnet&#xff09; 使用数据增强来降低过拟合 使用预训练的卷积神经网络进行特征提取 微调预训练的卷积神经网络 将卷积神经网络学到的内容及其如何做出分类决策可视化 本章将…

HBase表结构

HBase是非关系型数据库&#xff0c;是高可靠性、高性能、面向列、可伸缩、实时读写的分布式数据库。 HBase使用场景 大规模数据存储&#xff1a;如日志记录、数据库备份等。实时数据访问&#xff1a;如实时搜索、实时分析等。高性能读写&#xff1a;如高并发、低延迟的读写操…

(2)(2.10) LTM telemetry

文章目录 前言 1 协议概述 2 配置 3 带FPV视频发射器的使用示例 4 使用TCM3105的FSK调制解调器示例 前言 轻量级 TeleMetry 协议 (LTM) 是一种单向通信协议&#xff08;从飞行器下行的数据链路&#xff09;&#xff0c;可让你以低带宽/低波特率&#xff08;通常为 2400 波…

Linux下如何编译C/C++代码?从.c到.exe经历了什么?

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;强烈推荐优质专栏: &#x1f354;&#x1f35f;&#x1f32f;C的世界(持续更新中) &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;…

百度智能小程序开发平台:SEO关键词推广优化 带完整的搭建教程

移动互联网的普及&#xff0c;小程序成为了众多企业和开发者关注的焦点。百度智能小程序开发平台为开发者提供了一站式的解决方案&#xff0c;帮助企业快速搭建并推广自己的小程序。本文将重点介绍百度智能小程序开发平台的SEO关键词推广优化功能&#xff0c;并带完整的搭建教程…

MySQL原理(三)锁定机制(1)综述

一、介绍&#xff1a; 1、锁的本质 业务场景中存在共享资源&#xff0c;多个进程或线程需要竞争获取并处理共享资源&#xff0c;为了保证公平、可靠、结果正确等业务逻辑&#xff0c;要把并发执行的问题变为串行&#xff0c;串行时引入第三方锁当成谁有权限来操作共享资源的判…

06 单目初始化器 Initializer

文章目录 06 单目初始化器 Initializer6.1 成员变量/函数6.2 初始化函数 Initialize()6.3 计算基础矩阵 F \boldsymbol{F} F 和单应矩阵 H \boldsymbol{H} H6.3.1 RANSAC 算法6.3.2 八点法计算 F \boldsymbol{F} F 矩阵: ComputeF21()6.3.3 计算基础矩阵 F \boldsymbol{F} …

基于yolov2深度学习网络的视频手部检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 输入mp4格式的视频文件进行测试&#xff0c;视频格式为1080p30. 2.算法运行软件版本 matlab2022a 3.部分核心程序 ..........................…

大数据分析案例-基于随机森林算法构建电影票房预测模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

软连接和硬链接

1.软连接 软连接是一个独立的文件&#xff0c;有独立的inode&#xff0c;也有独立的数据块&#xff0c;它的数据块里面保存的是指向的文件路径-------相当于windows的快捷方式 删除一个软连接 2.硬链接 所谓的建立硬链接&#xff0c;本质就是在特定目录的数据块中新增文件名和…