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

数据库

设计数据库

设计几个字段,主键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已基本完善

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++弹球游戏:Jump Ball Game

一、下载压缩包 请查看网站C弹球游戏&#xff1a;Jump Ball Game并且下载&#xff0c;可以看到如下界面&#xff1a; 二、匹配图标 把压缩包解压了&#xff1a; 右键点击Jump Ball Game.lnk&#xff0c;点击“属性”它将会是我们要运行的文件。 点击“更改图标”&#xff0c;选…

【HarmonyOS 4.0 应用开发实战】ArkTS 快速入门

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

344. Reverse String(反转字符串)

题目描述 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 问题分析 以中间字符为轴&#xff0c;将两边的字符对换…

Python 轻量级定时任务调度:APScheduler

简述 APscheduler (Advanced Python Scheduler)&#xff0c;作用为按指定的时间规则执行指定的作业。提供了基于日期date、固定时间间隔interval 、以及类似于Linux上的定时任务crontab类型的定时任务。该框架不仅可以添加、删除定时任务&#xff0c;还可以将任务存储到数据库…

浅谈Zookeeper及windows下详细安装步骤

1. Zookeeper介绍 1.1 分布式系统面临的问题 分布式系统是一个硬件或软件组件分布在不同的网络计算机上&#xff0c;彼此之间仅仅通过消息传递进行通信和协调的系统。 面临的问题&#xff1a;系统每个节点之间信息同步及共享 以一个小团队为例,面临的问题 通过网络进行信息…

蓝桥杯---生日蜡烛

某君从某年开始每年都举办一次生日party&#xff0c;并且每次都要吹熄与年龄相同根数的蜡烛&#xff0c;现在算起来&#xff0c;他一共吹熄了236根蜡烛。请问,他从多少岁开始过生日party的? 请填写他开始过生日 party的年龄数。 注意:你提交的应该是一个整数&#xff0c;不要…

二分查找第二弹

目录 力扣852.山脉数组的峰顶索引 力扣162.寻找峰值 力扣153.寻找旋转排序数组中的最小值 力扣剑指Offer53.0-n-1缺失的数字 力扣852.山脉数组的峰顶索引 峰顶之前的全部比他小&#xff0c;峰顶之后的也比他小&#xff0c;把小于等于和大于分成两段 class Solution {publi…

TQ15EG开发板教程:使用vivado2023.1建立hello world工程

1:打开软件建立工程 2:使用vivado创建设计模块并生成bit文件 3:导出硬件平台&#xff0c;使用vitis建立工程 4:使用vitis创建应用程序项目 5:硬件设置与调试 1:打开软件建立工程 打开VIVADO2023.1 创建一个新的工程 输入项目名称和地址&#xff0c;下面那个选项为是否…

深入了解关联查询和子查询

推荐阅读 给软件行业带来了春天——揭秘Spring究竟是何方神圣&#xff08;一&#xff09; 给软件行业带来了春天——揭秘Spring究竟是何方神圣&#xff08;二&#xff09; 文章目录 推荐阅读关联查询子查询 关联查询 关联查询 从多张表中查询对应记录的信息&#xff0c;关联查…

网络原理-TCP/IP(5)

TCP协议 延迟应答 它也是基于滑动窗口,提高效率的一种机制,结合滑动窗口以及流量控制,能够以延迟应答ACK的方式,把反馈的窗口,搞大.核心在于允许范围内,让窗口尽可能大. 如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能比较小. 1.假设接收端缓冲区为1M.一次收到了5…

Java特别篇--关于线程创建的三种方式的总结对比

文章目录 一、常见3种创建线程的方式&#xff08;1&#xff09;方式1&#xff1a;继承Thread类的方式&#xff08;2&#xff09;方式2&#xff1a;实现Runnable接口的方式&#xff08;3&#xff09;方式3&#xff1a;通过Callable和Future接口创建线程 二、对比三种方式&#x…

CUDA/TensorRT部署知识点

CUDA相关: 1、CUDA核函数嵌套核函数的用法多吗? 答:这种用法非常少,主要是因为启动一个kernel本身就有一定延迟,会造成执行的不连续性。 2、如下代码里的 grid/block 对应硬件上的 SM 的关系是什么? 答:首先需要理解grid/block是软件层的概念,而SM是硬件层的概念。所…

python脚本将照片按时间线整理

说明&#xff1a;有一次自己瞎折腾&#xff0c;然后把服务器相册搞崩了&#xff0c;后来做了备份同步给找了回来&#xff0c;但是相册的时间线全乱了&#xff0c;看起来非常难受。所以就想通过文件夹的形式把照片重新分类&#xff0c;分类后的结构如下(红色字体为文件夹)&#…

人生百相,不过熵增熵减

这篇博文由两个问题衍生而来&#xff0c;分别是&#xff1a;“为什么除法比加法困难”、“什么是生命进化的目的”。在阅读其他人的解读时&#xff0c;发现都关联到了一个概念&#xff0c;熵。觉得十分有意思&#xff0c;因此记录一下自己的遐想。 熵&#xff08;Entropy&#…

vulhub中spring的CVE-2022-22965漏洞复现

在JDK 9上运行的Spring MVC或Spring WebFlux应用程序可能存在通过数据绑定执行远程代码&#xff08;RCE&#xff09;的漏洞。 现在已知的利用方法要求应用程序以WAR部署的形式在Tomcat上运行&#xff0c;然而&#xff0c;该漏洞的性质更为普遍&#xff0c;可能有其他方法可以利…

docker安装-centos

Docker CE 支持 64 位版本 CentOS 7&#xff0c;并且要求内核版本不低于 3.10 卸载旧版本Docker sudo yum remove docker \ docker-common \ docker-selinux \ docker-engine使用yum安装 yum 更新到最新版本: sudo yum update执行以下命令安装依赖包&#xff1a; sudo yum…

【无刷电机】无感方波驱动方案

无感方波驱动方案 1.通过无感过零信号构造霍尔换相信号2.无刷硬件驱动方案3.无感方波控制程序框架3.1有感方波控制3.2无感方波控制3.3无感启动方案3.4无感速度闭环控制1.通过无感过零信号构造霍尔换相信号 实现无感方波控制有软件比较和硬件比较两种方案。 软件比较是通过ADC采…

张维迎《博弈与社会》威胁与承诺(3)承诺行为

承诺的作用 上一节&#xff0c;我们探讨了如何在求解博弈时把不可置信的威胁或许诺排除出去&#xff0c;从而对参与人的行为做出合理的预测。如前所述&#xff0c;其中一个隐含的前提条件是&#xff0c;参与人要具有理性共识。而理性共识是一个要求很高的条件&#xff0c;现实生…

基于Springboot的校园失物招领网站(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的校园失物招领网站&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

基于Springboot的兼职网(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的兼职网&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0…