springboot-vue excel上传导出

news2024/11/28 2:58:37

数据库

device_manage表

字段,id,workshop,device_number,device_name,device_model,warn_time,expired_time

device_warn表

字段,id,warn_time,expired_time

后端

实体类格式

device_manage

@Data
@TableName("device_manage")

/*
设备管理
*/
public class DeviceManageEntity {

    private static final long serialVersionUID = 1L;
    /**
     * 主键
     */
    @TableId
    private Integer id;
 
    /**
     * 车间名称
     */
    private String workshop;


    /**
     * 设备编号
     */
    private String deviceNumber;

    /**
     * 设备名称
     */
    private String deviceName;

    /**
     * 设备型号
     */
    private String deviceModel;


    /**
     * 维保预警时间
     */
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
    private Date warnTime;

    /**
     * 维保到期时间
     */
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
    private Date expiredTime;

}

device_warn

@Data
@TableName("device_warn")

/*保养预警*/
public class DeviceWarnEntity {
    private static final long serialVersionUID = 1L;
    /**
     * 编号
     */
    @TableId
    private Integer id;

    /**
     * 保养到期时间
     */
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
    private Date expiredTime;

    /**
     * 预警时间
     */
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
    private Date warnTime;

}

选择导出的字段warnVo

@Data
@ColumnWidth(20)
public class WarnVo {
    //传输给前端展示
    //id
    @ExcelIgnore
    private Long id;
    //车间
    @ExcelProperty("车间名称")
    private String workshop;
    //设备编号
    @ExcelProperty("设备编号")
    private String deviceNumber;
    //设备名称
    @ExcelProperty("设备名称")
    private String deviceName;
    //设备型号
    @ExcelProperty("设备型号")
    private String deviceModel;
    //维保到期时间
    @ExcelProperty("维保到期时间")
    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
    private Date expiredTime;
    //预警时间
    @ExcelProperty("预警时间")
    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
    private Date warnTime;
}

controller层

@RestController
@RequestMapping("/dev/warn")
public class exportController {
    @Autowired
    private DeviceWarnService iTainWarnService;
//字典类,前端下拉框选项
    @Autowired
    private SysDictService sysDictService;
    @Autowired
    private DeviceManageService iDeviceService;
 

    //文件上传
    @PostMapping("/upload")
    @ResponseBody
    public R upload(MultipartFile file) throws IOException {
        if (file==null){
            System.out.println("文件为空");
        }
        WarnVoListener warnVoListener = new WarnVoListener(sysDictService, iTainWarnService, iDeviceService);
//初始化tips
        List<ImportTips> tips = new ArrayList<>();

            for (WarnVo data : warnVoListener.getDatas()) {
                tips = warnVoListener.getTips();

            }
            if (tips.size() > 0) {
                return R.error();
            }

        EasyExcel.read(file.getInputStream(), WarnVo.class, warnVoListener).sheet().doRead();
        return R.ok();
    }

    //文件导出
    /**
     * 文件下载并且失败的时候返回json(默认失败了会返回一个有部分数据的Excel)
     * 这种方法是将Excel文件的生成过程放在后端进行。前端发起一个请求到后端,后端处理数据并生成Excel文件,然后将文件返回给前端进行下载。
     * 这种方法的优点是可以将数据处理的压力放在后端,前端只需要处理请求和下载文件的逻辑。
     * @since 2.1.1,设置响应头
     */
    private  void setExcelResponseProp(HttpServletResponse response,String rawFileName) throws UnsupportedEncodingException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode(rawFileName, "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    }

    @GetMapping("/download")
    public void download(HttpServletResponse response) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("测试", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            this.setExcelResponseProp(response,"保养预警");
            List<WarnVo> warnVos = iTainWarnService.listAllWarn();
//得到字典类所有选项
            List<SysDictEntity> workShopList = sysDictService.maintenanceList(" workshop");
            for (WarnVo warnVo : warnVos) {
                for (SysDictEntity sysDictEntity :  workShopList) {
                    if (sysDictEntity.getValue().compareTo(warnVo.getWorkshop())==0){
                        warnVo.setWorkshop(sysDictEntity.getName());
                    }
                }
            }
            List<SysDictEntity> deviceModelList = sysDictService.maintenanceList("deviceModel");
            for (WarnVo warnVo : warnVos) {
                for (SysDictEntity sysDictEntity :  deviceModelList) {
                    if (sysDictEntity.getValue().compareTo(warnVo.getDeviceModel())==0){
                        warnVo.setDeviceModel(sysDictEntity.getName());
                    }
                }
            }
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), WarnVo.class)
                    // 导出Excel时在此处注册handler
                    .registerWriteHandler(new CustomSheetWriteHandler(sysDictService))
                    .autoCloseStream(Boolean.FALSE)
                    .sheet("保养预警")
                    .doWrite(warnVos);
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = new HashMap<>();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(map));
        }
    }

}

listener

CustomSheetWriteHandler导出

@Service
public class CustomSheetWriteHandler implements SheetWriteHandler {
    @Autowired
    private SysDictService sysDictService;


    public CustomSheetWriteHandler(SysDictService sysDictService) {
        this.sysDictService = sysDictService;
    }

    @Override
    public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {

    }

    /**
     * 想实现Excel引用其他sheet页数据作为单元格下拉选项值,
     * 需要重写该方法
     *
     * @param writeWorkbookHolder
     * @param writeSheetHolder
     */
    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        // 构造样例数据,该数据可根据实际需要,换成业务数据
        // 实际数据可通过构造方法,get、set方法等由外界传入
        List<String> selectworkshopList = new ArrayList<>();
        List<SysDictEntity> workshoplist = sysDictService.maintenanceList("workshop");
        for (SysDictEntity sysDictEntity : workshoplist) {
            if (sysDictEntity.getSort()!=null){
                selectworkshopList.add(sysDictEntity.getName());
            }
        }
        List<String> selectmodelList = new ArrayList<>();
        List<SysDictEntity> modellist = sysDictService.maintenanceList("deviceModel");
        for (SysDictEntity sysDictEntity : modellist) {
            if (sysDictEntity.getSort()!=null){
                selectmodelList.add(sysDictEntity.getName());
            }
        }

        // 构造下拉选项单元格列的位置,以及下拉选项可选参数值的map集合
        // key:下拉选项要放到哪个单元格,比如A列的单元格那就是0,C列的单元格,那就是2
        // value:key对应的那个单元格下拉列表里的数据项,比如这里就是下拉选项1..100
        Map<Integer, List<String>> selectParamMap = new HashMap<>();
        selectParamMap.put(0, selectworkshopList);
        selectParamMap.put(3, selectmodelList);

        // 获取第一个sheet页
        Sheet sheet = writeSheetHolder.getCachedSheet();
        // 获取sheet页的数据校验对象
        DataValidationHelper helper = sheet.getDataValidationHelper();
        // 获取工作簿对象,用于创建存放下拉数据的字典sheet数据页
        Workbook workbook = writeWorkbookHolder.getWorkbook();

        // 迭代索引,用于存放下拉数据的字典sheet数据页命名
        int index = 1;
        for (Map.Entry<Integer, List<String>> entry : selectParamMap.entrySet()) {

            // 设置存放下拉数据的字典sheet,并把这些sheet隐藏掉,这样用户交互更友好
            String dictSheetName = "dict_hide_sheet" + index;
            Sheet dictSheet = workbook.createSheet(dictSheetName);
            // 隐藏字典sheet页
            workbook.setSheetHidden(index++, true);

            // 设置下拉列表覆盖的行数,从第一行开始到最后一行,这里注意,Excel行的
            // 索引是从0开始的,我这边第0行是标题行,第1行开始时数据化,可根据实
            // 际业务设置真正的数据开始行,如果要设置到最后一行,那么一定注意,
            // 最后一行的行索引是1048575,千万别写成1048576,不然会导致下拉列表
            // 失效,出不来
            CellRangeAddressList infoList = new CellRangeAddressList(1, 1048575, entry.getKey(), entry.getKey());
            int rowLen = entry.getValue().size();
            for (int i = 0; i < rowLen; i++) {
                // 向字典sheet写数据,从第一行开始写,此处可根据自己业务需要,自定
                // 义从第几行还是写,写的时候注意一下行索引是从0开始的即可
                dictSheet.createRow(i).createCell(0).setCellValue(entry.getValue().get(i));
            }

            // 设置关联数据公式,这个格式跟Excel设置有效性数据的表达式是一样的
            String refers = dictSheetName + "!$A$1:$A$" + entry.getValue().size();
            Name name = workbook.createName();
            name.setNameName(dictSheetName);
            // 将关联公式和sheet页做关联
            name.setRefersToFormula(refers);

            // 将上面设置好的下拉列表字典sheet页和目标sheet关联起来
            DataValidationConstraint constraint = helper.createFormulaListConstraint(dictSheetName);
            DataValidation dataValidation = helper.createValidation(constraint, infoList);
            sheet.addValidationData(dataValidation);
        }
    }
}

WarnVoListener导入

@Slf4j
public class WarnVoListener extends AnalysisEventListener<WarnVo> {
    private static final Logger LOGGER = LoggerFactory.getLogger(WarnVoListener.class);
    /**
     * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 5;
    //    List<WarnVo> list = new ArrayList<>();
    List<DeviceManageEntity> deviceList = new ArrayList<>();
    List<DeviceWarnEntity> tainWarnList = new ArrayList<>();

    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private SysDictService sysDictService;
    private DeviceWarnService iTainWarnService;
    private DeviceManageService iDeviceService;

//    public WarnVoListener() {
//        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
//        demoDAO = new DemoDAO();
//    }

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     */
    public WarnVoListener(SysDictService sysDictService,DeviceWarnService iTainWarnService,DeviceManageService iDeviceService) {
        this.sysDictService = sysDictService;
        this.iTainWarnService = iTainWarnService;
        this.iDeviceService = iDeviceService;
    }

    /**
     * 返回提示语
     */
    private List<ImportTips> tips = new ArrayList<>();

    /**
     * 自定义用于暂时存储data
     * 可以通过实例获取该值
     */
    private List<WarnVo> datas = new ArrayList<>();

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data
     *            one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(WarnVo data, AnalysisContext context) {
//        LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));

        // 该行数据是否有错误
        boolean checkRowError = false;
        LOGGER.info("数据导入,解析第{}行数据:{}" , context.readRowHolder().getRowIndex() , data);


        List<DeviceManageEntity> devList = iDeviceService.list();
        for (DeviceManageEntity devices : devList) {
            if (devices.getDeviceNumber().equals(data.getDeviceNumber())){
                saveTips(context.readRowHolder().getRowIndex(),"导入文件中设备编号有重复",tips);
                checkRowError = true;
            }
        }


        //当该行数据没有错误时,数据存储到集合,供批量处理。
        if(!checkRowError){
            //device表
            DeviceManageEntity device = new DeviceManageEntity();
//            device.setDeviceModel(data.getDeviceModel());
            device.setDeviceName(data.getDeviceName());
            device.setDeviceNumber(data.getDeviceNumber());
            device.setWarnTime(data.getWarnTime());
            device.setExpiredTime(data.getExpiredTime());

            List<SysDictEntity> list = sysDictService.maintenanceList("workshop");
            for (SysDictEntity sysDictEntity : list) {
                if (sysDictEntity.getName().compareTo(data.getWorkshop())!=0){
                    device.setWorkshop(sysDictEntity.getValue());
                }
            }
            List<SysDictEntity> modellist = sysDictService.maintenanceList("deviceModel");
            for (SysDictEntity sysDictEntity : modellist) {
                if (sysDictEntity.getName().compareTo(data.getDeviceModel())!=0){
                    device.setDeviceModel(sysDictEntity.getValue());
                }
            }
            this.deviceList.add(device);

            //tain_warn表
          /*  DeviceWarnEntity tainWarn = new DeviceWarnEntity();
            tainWarn.setExpiredTime(data.getExpiredTime());
            tainWarn.setWarnTime(data.getWarnTime());
            this.tainWarnList.add(tainWarn);*/
            datas.add(data);
        }

        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (this.deviceList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            this.deviceList.clear();
        }
        if (this.tainWarnList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            this.tainWarnList.clear();
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        LOGGER.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        LOGGER.info("{}条数据,开始存储数据库!", deviceList.size());
        LOGGER.info("{}条数据,开始存储数据库!", tainWarnList.size());
//        demoDAO.save(list);
//        iTainWarnService.saveBatch(list);
        //存入数据库

        iDeviceService.saveBatch(deviceList);
        iTainWarnService.saveBatch(tainWarnList);

        LOGGER.info("存储数据库成功!");
    }

    /**
     * 保存提示信息到集合
     * @param rowIndex 行数
     * @param desc 提示信息
     * @param tips 存入集合
     */
    private void saveTips(Integer rowIndex, String desc, List<ImportTips> tips) {
        ImportTips tip = new ImportTips();
        tip.setRowNum(rowIndex);
        tip.setTips(desc);
        tips.add(tip);
    }

    /**
     * 返回数据
     * @return 返回提示集合
     **/
    public List<ImportTips> getTips() {
        return tips;
    }

    /**
     * 返回数据
     * @return 返回读取的数据集合
     **/
    public List<WarnVo> getDatas() {
        return datas;
    }
}

service层

device_manage略

device_warn

public interface DeviceWarnService extends IService<DeviceWarnEntity> {

    List<WarnVo> listAllWarn();
}

service_impl层

@Service("DeviceWarnService")
public class DeviceWarnServiceImpl extends ServiceImpl<DeviceWarnDao, DeviceWarnEntity> implements DeviceWarnService {

    @Autowired
    private DeviceWarnDao deviceWarnDao;

    @Override
    public List<WarnVo> listAllWarn() {
        QueryWrapper<WarnVo> qw = new QueryWrapper<>();
        return this.deviceWarnDao.selectWarn(qw);
    }
}

Dao层,使用@Select注解写入sql语句获得所有信息

@Mapper
public interface DeviceWarnDao extends BaseMapper<DeviceWarnEntity> {

    @Select("select w.id,d.workshop,d.device_number,d.device_name,d.device_model,w.warn_time,w.expired_time,w.device_status from device_warn w left join device_manage d on d.id=w.device_id where w.is_deleted = 0")
    List<WarnVo> selectWarn(@Param(Constants.WRAPPER) QueryWrapper<WarnVo> wrapper);
}

前端

<template>
    <div class="mod-config">

      <!-- 导入导出 -->
      <el-form :inline="true">
      <el-form-item>
        <el-button type="primary" icon="el-icon-share" @click="download()" >一键导出
       </el-button>
      </el-form-item>
      <el-form-item>
        <el-upload
          style="width: 400px"
          action="http://localhost:8080/wedu/dev/warn/upload"
          :headers="tokenInfo"
          :on-preview="handlePreview"
          :on-remove="handleRemove"
          :before-remove="beforeRemove"
          multiple
          :limit="3"
          :on-exceed="handleExceed"
          :file-list="fileList">
          <el-button type="primary">点击上传</el-button>
        </el-upload>
      </el-form-item>
    
    </el-form>

      <el-table
        :data="dataList"
        border
        v-loading="dataListLoading"
        @selection-change="selectionChangeHandle"
        style="width: 100%;">
        <el-table-column
          prop="workshop"
          header-align="center"
          align="center"
          label="车间名称">
        </el-table-column>
        <el-table-column
          prop="deviceNumber"
          header-align="center"
          align="center"
          label="设备编号">
        </el-table-column>
        <el-table-column
        prop="deviceName"
        header-align="center"
        align="center"
        label="设备名称">
      </el-table-column>
        <el-table-column
          prop="deviceModel"
          header-align="center"
          align="center"
          label="设备型号">
        </el-table-column>
        <el-table-column
          prop="expiredTime"
          header-align="center"
          align="center"
          label="维保到期时间">
        </el-table-column>
        <el-table-column
          prop="warnTime"
          header-align="center"
          align="center"
          label="维保预警时间">
        </el-table-column>
  </template>
  
  <script>
     export default {
      data () {
        return {
          tokenInfo: {
            token: this.$cookie.get("token"),
          },
          dataForm: {
            deviceNumber: ''
          },
           // 车间字典项
          allchejian: [],
          // 车间筛选
          workshops: [],
          bydicts: [],
          byMap: {},
          fileUploadBtnText: "点击上传", //上传文件提示文字
          fileList: [], // 上传文件列表
          fileUploadVisible:false
            }
          },
     
      activated () {
        this.getDataList();
        this.loadAllChejian("workshop");
        this.getBydicts("deviceModel");
      },
      methods: {
        fileUpload(){
          this.fileUploadVisible = true;
            this.$nextTick(() => {
              this.$refs.FileUpload.init();
            });
        },
        // 文件列表移除文件时的钩子
        handleRemove(file, fileList) {
          console.log(file, fileList);
        },
        // 点击文件列表中已上传的文件时的钩子
        handlePreview(file) {
          console.log(file);
        },
        // 限制上传文件的个数和定义超出限制时的行为
        handleExceed(files, fileList) {
          this.$message.warning(
            `当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${
              files.length + fileList.length
            } 个文件`
          );
        },
        // 文件列表移除文件时之前的钩子
        beforeRemove(file, fileList) {
          return this.$confirm(`确定移除 ${file.name}?`);
        },
        onUploadExcelError(response) {
          if (res.code === 500) this.$message.error(res.message);
        },

        //文件导出
        download() {
          this.$http({
            url: this.$http.adornUrl("/dev/warn/download"),
            method: "get",
            //设置响应类型(重要
            responseType: "blob",
          }).then((response) => {
            // 创建一个url,接收到的二进制数据
            const url = window.URL.createObjectURL(new Blob([response.data]));
            // 创建一个a标签,用于触发文件下载
            const link = document.createElement("a");
            // a元素的href属性为创建的url
            link.href = url;
            link.setAttribute("download", "保养预警.xlsx");
            // 将a添加到文档
            document.body.appendChild(link);
            // 触发a的点击事件开始下载
            link.click();
          });
        },

        getWorkshopName(value) {
          const workshop = this.allchejian.find((item) => item.value === value);
          return workshop ? workshop.name : "";
        },
        getBydicts(code) {
          this.$http({
            url: this.$http.adornUrl("/sys/dict/maintenanceList"),
            method: "get",
            params: this.$http.adornParams({
              code: code,
            }),
          }).then(({ data }) => {
            if (data && data.code === 0) {
              this.bydicts = data.list;
              this.bydicts.forEach((dict) => {
                this.$set(this.byMap, dict.value, dict.name);
              });
            } else {
              this.bydicts = [];
            }
          });
        },
        //加载车间 所需的数据zyb
        loadAllChejian(code) {
          this.allchejian = [];
          this.$http({
            url: this.$http.adornUrl("/sys/dict/maintenanceList"),
            method: "post",
            params: this.$http.adornParams({
              code: code,
            }),
          }).then(({ data }) => {
            if (data && data.code === 0) {
              this.allchejian = data.list.map((item) => ({
                name: item.name,
                value: item.value,
              }));
              this.workshop = data.list.map((item) => ({
                text: item.name,
                value: item.value,
              }));
            } else {
            }
          });
        },
        // 车间筛选方法 zyb
        filterHandler(value, row, column) {
          const property = column["property"];
          return row[property] === value;
        }
     
    }
  </script>

最终效果

点击导出

下载的excel表格中车间名称和设备型号有下拉框,对应前端配置的字典类

点击导入

将这个格式的excel导入

在数据库新增一条数据

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

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

相关文章

【简单好抄保姆级教学】javascript调用本地exe程序(谷歌,edge,百度,主流浏览器都可以使用....)

javascript调用本地exe程序 详细操作步骤结果 详细操作步骤 在本地创建一个txt文件依次输入 1.指明所使用注册表编程器版本 Windows Registry Editor Version 5.00这是脚本的第一行&#xff0c;指明了所使用的注册表编辑器版本。这是必需的&#xff0c;以确保脚本能够被正确解…

Redis五大基本类型——Zset有序集合命令详解(命令用法详解+思维导图详解)

目录 一、Zset有序集合类型介绍 二、常见命令 1、ZADD 2、ZCARD 3、ZCOUNT 4、ZRANGE 5、ZREVRANGE 6、ZRANGEBYSCORE 7、ZREVRANGEBYSCORE 8、ZPOPMAX 9、ZPOPMIN 10、ZRANK 11、ZREVRANK 12、ZSCORE 13、ZREM 14、ZREMRANGEBYRANK 15、ZREMRANGEBYSCORE 16…

设计模式之 责任链模式

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;旨在将多个处理对象通过链式结构连接起来&#xff0c;形成一条处理请求的链条。每个处理对象都有机会处理请求&#xff0c;或者将请求传递给链中的下一个对象。这样&#x…

新版布谷直播软件源码开发搭建功能更新明细

即将步入2025年也就是山东布谷科技专注直播系统开发,直播软件源码出售开发搭建等业务第9年,山东布谷科技不断更新直播软件功能&#xff0c;以适应当前新市场环境下的新要求。山东布谷科技始终秉承初心&#xff0c;做一款符合广大客户需求的直播系统软件。支持广大客户提交更多个…

VITE+VUE3+TS环境搭建

前言&#xff08;与搭建项目无关&#xff09;&#xff1a; 可以安装一个node管理工具&#xff0c;比如nvm&#xff0c;这样可以顺畅的切换vue2和vue3项目&#xff0c;以免出现项目跑不起来的窘境。我使用的nvm&#xff0c;当前node 22.11.0 目录 搭建项目 添加状态管理库&…

HTML飞舞的爱心

目录 系列文章 写在前面 完整代码 代码分析 写在后面 系列文章 序号目录1HTML满屏跳动的爱心&#xff08;可写字&#xff09;2HTML五彩缤纷的爱心3HTML满屏漂浮爱心4HTML情人节快乐5HTML蓝色爱心射线6HTML跳动的爱心&#xff08;简易版&#xff09;7HTML粒子爱心8HTML蓝色…

英伟达推出了全新的小型语言模型家族——Hymba 1.5B

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

低速接口项目之串口Uart开发(二)——FIFO实现串口数据的收发回环测试

本节目录 一、设计思路 二、loop环回模块 三、仿真模块 四、仿真验证 五、上板验证 六、往期文章链接本节内容 一、设计思路 串口数据的收发回环测试&#xff0c;最简单的硬件测试是把Tx和Rx连接在一起&#xff0c;然后上位机进行发送和接收测试&#xff0c;但是需要考虑到串…

《Java核心技术I》树集

树集 TreeSet类与散列类似&#xff0c;树集是一个有序集合(sorted collection)。 可以以任意顺序将元素插入到集合中&#xff0c;遍历集合时&#xff0c;自动按照排序后的顺序呈现。 插入5个字符串&#xff0c;访问添加的元素 package treeSet;import java.util.TreeSet;pu…

Tailwind CSS v4.0 开启

Tailwind CSS v4.0 发布了 Tailwind CSS 是一个为快速开发而精心设计的原子类 CSS 框架&#xff0c;它提供了充满设计感和应用程序至上的能力来创建组件&#xff0c;它在最新的 2.0 版本中加入了暗黑模式&#xff0c;开箱即用。 Tailwind Connect 大会上&#xff0c;与会者抢先…

QML TableView 实例演示 + 可能遇到的一些问题(Qt_6_5_3)

一、可能遇到的一些问题 Q1&#xff1a;如何禁用拖动&#xff1f; 在TableView下加一句代码即可&#xff1a; interactive: false 补充&#xff1a;这个属性并不专属于TableView&#xff0c;而是一个通用属性。很多Controls下的控件都可以使用&#xff0c;其主要作用就是控…

详细描述一下Elasticsearch更新和删除文档的过程?

大家好&#xff0c;我是锋哥。今天分享关于【详细描述一下Elasticsearch更新和删除文档的过程&#xff1f;】面试题。希望对大家有帮助&#xff1b; 详细描述一下Elasticsearch更新和删除文档的过程&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 E…

(五)Ubuntu22.04+Stable-Diffusion-webui AI绘画 模型转换插件安装及其使用

一、说明 这是秋叶大佬开发的一个模型转换插件&#xff0c;秋叶整合包中自带。如果你的 Stable Diffusion WebUI 中没有这个插件&#xff0c;请使用下面这个地址安装&#xff0c;安装完成之后别忘了重启 WebUI。 模型转换插件 https://github.com/Akegarasu/sd-webui-model-c…

Python数据分析实例五、US 大选捐款数据分析

美国联邦选举委员会 (FEC) 公布了对政治竞选活动的贡献数据。这包括投稿人姓名、职业和雇主、地址和投款金额。2012 年美国总统大选的贡献数据以单个 150 MB 的 CSV 文件P00000001-ALL.csv形式提供,该文件可以通过以下pandas.read_csv加载: import pandas as pdfec = pd.r…

原生微信小程序画表格

wxml部分&#xff1a; <view class"table__scroll__view"><view class"table__header"><view class"table__header__item" wx:for"{{TableHeadtitle}}" wx:key"index">{{item.title}}</view></…

TCP/IP协议攻击与防范

一、TCP/IP协议攻击介绍 1.1 Internet的结构​ LAN&#xff1a;局域网 WAN&#xff1a;广域网 WLAN&#xff1a;无线局域网 私有IP地址与公有IP地址&#xff1f; 私有地址&#xff1a;A类&#xff1a;10.0.0.0~10.255.255.255 B类&#xff1a;172.16.0.0~172.31.255.255…

微信小程序2-地图显示和地图标记

一、index修改页面&#xff0c;让页面能够显示地图和一个添加标记的按钮。 index.wxml <scroll-view class"scrollarea" scroll-y type"list"><view class"index_container"><map id"map" style"width: 100%; h…

【C++】从C语言到C++学习指南

如果你也是从C语言一路过来的&#xff0c;那么请一起看下去吧&#xff01; 文章目录 面型对象程序设计C基础C和C一些语法区别C在非对象方面对C语言的扩充C的一些标准&#xff08;兼容旧标准&#xff09; 首先&#xff0c;在C的学习中&#xff0c;我们要时刻清醒一点&#xff1…

Fakelocation Server服务器/专业版 ubuntu

前言:需要Ubuntu系统 Fakelocation开源文件系统需求 Ubuntu | Fakelocation | 任务一 任务一 更新Ubuntu&#xff08;安装下载不再赘述&#xff09; sudo -i # 提权 sudo apt update # 更新软件包列表 sudo apt upgrade # 升级已安装的软…

探索Python的HTTP之旅:揭秘Requests库的神秘面纱

文章目录 **探索Python的HTTP之旅&#xff1a;揭秘Requests库的神秘面纱**第一部分&#xff1a;背景介绍第二部分&#xff1a;Requests库是什么&#xff1f;第三部分&#xff1a;如何安装Requests库&#xff1f;第四部分&#xff1a;Requests库的五个简单函数使用方法第五部分&…