首页 > 其他分享 >在实际开发中遇到的各种问题解决方案

在实际开发中遇到的各种问题解决方案

时间:2022-10-11 13:36:34浏览次数:77  
标签:文件 Excel 遇到 解决方案 导出 public 开发 response 邮件

目录

第一问:使用axios异步请求完成数据导出(Excel)(基于hutool工具包)

(1.1)编写后台接口,获取到response对象以及前端传来的数据,使用@RequestBody获取到需要进行导出的数据id

(1.1.1)引入jar包(hutool工具类实现)

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.8</version>
        </dependency>

(1.1.2)编写接口(HttpServletResponse response, @RequestBody List<Long> ids)

@Controller
@RequestMapping("/export")
public class ExcelExportController {
    @Autowired
    private DeptInfoMapper deptInfoMapper;

    @PostMapping("/deptInfo")
    public void exportNewsInfoExcel(HttpServletResponse response, @RequestBody List<Long> ids) throws IOException {
        // 设置文件导出的一些响应头等
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=test.xlsx");

        List<DeptInfo> list = deptInfoMapper.selectListByIds(ids);

        // 通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter(true);
        // 合并单元格后的标题行,使用默认标题样式,写的4,就代表一共有5列,因为是从0开始
        writer.merge(4, "部门信息表");

        //自定义标题别名
        writer.addHeaderAlias("id", "默认ID");
        writer.addHeaderAlias("name", "部门名称");
        writer.addHeaderAlias("description", "部门描述");
        writer.addHeaderAlias("principal", "部门负责人");
        writer.addHeaderAlias("tel", "联系电话");

        // 一次性写出内容,使用默认样式,强制输出标题
        writer.write(list, true);

        // 刷新到响应的输出流中
        writer.flush(response.getOutputStream());

        // 关闭writer,释放内存
        writer.close();
    }
}

(1.2)前端界面请求数据导出接口,选择性携带参数

(1.2.1)编写一个方法,专门用户做文件的导出请求

    // 发送post请求来模拟下载,需要传递条件, url是请求地址,data是请求的数据,格式为对象,filename为文件名称
    postDownLoadFile(url, data, filename = '部门列表.xlsx') {
        axios.request({
            url: url,
            method: 'post',   // 以post请求为例
            data: data,   // 筛选列表的请求参数
            responseType: 'blob', // 注意响应的类型,必须为blob类型,是一个原始数据的类文件对象,能够使用二进制或文本读取
        }).then(res=>{
            // 获取到response中的文件数据
            const data = res.data
            // 将二进制文件转化为可访问的url
            let url = window.URL.createObjectURL(data)
            // 使用原生的document操作来创建一个a标签,并添加到body标签中
            var a = document.createElement('a')
            document.body.appendChild(a)
            // 设置其href请求路径
            a.href = url
            // 设置好下载的文件名,需要带上后缀
            a.download = filename
            // 模拟点击下载
            a.click()
            // 清除刚刚使用window.URL.createObjectURL(data) 创建的数据,避免在内存中遗留
            window.URL.revokeObjectURL(url)
        })
    }

(1.2.2)编写一个按钮,设置点击事件,在点击后将已选中的表格id拿到,再拿着数据请求接口即可

    // 点击导出按钮时的点击事件
    exportExcel() {
        // 获取需要获取数据的id列表
        let ids = [];
        // 获取到现在选择的表格列表
        this.$refs.multipleTable.selection.forEach(row => ids.push(row.id));
        this.postDownLoadFile('/edusys/export/deptInfo', ids, '部门列表的excel表格.xlsx')
    }

第二问:发送邮件功能

2.1 原生发送邮件功能(使用qq邮箱进行演示)

  • 打开QQ邮箱,开通SMTP功能
    image
    image
    image

  • 创建一个Maven项目,引入如下依赖

        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
  • 编写Java代码
import com.sun.mail.util.MailSSLSocketFactory;
import org.junit.jupiter.api.Test;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

/**
 * @author codeStars
 * @date 2022/9/30 14:40
 */
public class SendEmailTest {

    @Test
    public void sendEmail() throws Exception{
        //创建一个配置文件并保存
        Properties properties = new Properties();

        properties.setProperty("mail.host","smtp.qq.com");

        properties.setProperty("mail.transport.protocol","smtp");

        properties.setProperty("mail.smtp.auth","true");


        //QQ存在一个特性设置SSL加密
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        properties.put("mail.smtp.ssl.enable", "true");
        properties.put("mail.smtp.ssl.socketFactory", sf);

        //创建一个session对象
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("你的QQ邮箱","你的授权码");
            }
        });

        //开启debug模式
        session.setDebug(true);

        //获取连接对象
        Transport transport = session.getTransport();

        //连接服务器
        transport.connect("smtp.qq.com","你的QQ邮箱","你的授权码");

        //创建邮件对象
        MimeMessage mimeMessage = new MimeMessage(session);

        //邮件发送人
        mimeMessage.setFrom(new InternetAddress("你的QQ邮箱"));

        //邮件接收人
        mimeMessage.setRecipient(Message.RecipientType.TO,new InternetAddress("邮件的接收者的邮箱"));

        //邮件标题
        mimeMessage.setSubject("Hello Mail,我是邓");

        //邮件内容
        mimeMessage.setContent("今天天气真好","text/html;charset=UTF-8");

        //发送邮件
        transport.sendMessage(mimeMessage,mimeMessage.getAllRecipients());

        //关闭连接
        transport.close();
    }
}

2.2 使用SpringBoot配合邮件启动器完成发送邮件功能

2.2.1 引入依赖

    <properties>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    </properties>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

2.2.2 在application.yml配置文件中配置一些基本信息

spring:
  #邮箱基本配置
  mail:
    #配置smtp服务主机地址
    host: smtp.qq.com
    #发送者邮箱
    username: [email protected]
    #配置密码,注意不是真正的密码,而是刚刚申请到的授权码
    password: bwzxbgdaeisexxxx
    #端口号465或587
    port: 587
    #默认的邮件编码为UTF-8
    default-encoding: UTF-8
    #其他参数
    properties:
      mail:
        #配置SSL 加密工厂
        smtp:
          ssl:
            #本地测试,先放开ssl,实际使用需要调整为true
            enable: false
            required: false
          #开启debug模式,这样邮件发送过程的日志会在控制台打印出来,方便排查错误
        debug: true

image

2.2.3 测试发送简单邮件

@SpringBootTest
public class SpringBootSendMailTest {
    /**
     * 邮件启动器为我们提供的邮件发送器
     */
    @Autowired
    private JavaMailSenderImpl javaMailSender;

    /**
     * 发信人,必须为一个邮箱,可以从刚刚在配置文件中进行的配置获取
     */
    @Value("${spring.mail.username}")
    private String addresser;

    @Test
    public void sendSimpleMail() {
        SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
        // 文件标题
        simpleMailMessage.setSubject("我是邮件标题aaa");
        // 文件内容
        simpleMailMessage.setText("我是文件内容");
        // 寄件人
        simpleMailMessage.setFrom(addresser);
        // 收件人
        simpleMailMessage.setTo("[email protected]");

        // 设置邮件发送时间,实际上还是立即发送的
        // 只是把邮件接收者看到的邮件接收时间往后推了10分钟
        LocalDateTime localDateTime = LocalDateTime.now().plusMinutes(10);
        long time = Timestamp.valueOf(localDateTime).getTime();
        simpleMailMessage.setSentDate(new Date(time));

        // 发送邮件
        javaMailSender.send(simpleMailMessage);
    }
}

2.2.4 测试发送有附件的邮件

@SpringBootTest
public class SpringBootSendMailTest {
    /**
     * 邮件启动器为我们提供的邮件发送器
     */
    @Autowired
    private JavaMailSenderImpl javaMailSender;

    /**
     * 发信人,必须为一个邮箱,可以从刚刚在配置文件中进行的配置获取
     */
    @Value("${spring.mail.username}")
    private String addresser;

    @Test
    public void sendFileMail() throws Exception{
        // 创建复杂类型的邮件
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        // 后面那个true的作用是设置需要发送附件或html
        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);

        // 文件标题
        mimeMessageHelper.setSubject("我是邮件标题aaa");
        // 文件内容
        mimeMessageHelper.setText("我是文件内容");
        // 寄件人
        mimeMessageHelper.setFrom(addresser);
        // 收件人
        mimeMessageHelper.setTo("[email protected]");

        // 添加需要发送的附件,并指定文件名称
        mimeMessageHelper.addAttachment("可爱图片.png", new File("C:\\Users\\DQX\\Downloads\\可可爱爱小盆栽-20.png"));

        // 发送邮件
        javaMailSender.send(mimeMessage);
    }
}

第三问:通过JDK8的新特性获取现在到明天凌晨的小时、分钟、秒、毫秒

    @Test
    public void testTime() {
        // 获取当前的时间戳
        long nowTimeStamp = Instant.now().toEpochMilli();
        // 获取一天后的时间戳
        long tomorrowTimeStamp = LocalDateTime.now().plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0).toInstant(ZoneOffset.of("+8")).toEpochMilli();

        // 现在到明天凌晨的毫秒数
        long millisSecond = tomorrowTimeStamp - nowTimeStamp;
        System.out.println(millisSecond);

        // 现在到明天凌晨的秒数
        long second = millisSecond / 1000;
        System.out.println(second);

        // 现在到明天凌晨的分钟
        long minute = second / 60;
        System.out.println(minute);

        // 现在到明天凌晨的小时
        long hour = minute / 60;
        System.out.println(hour);
    }

(第四问)使用EasyExcel完成Excel的导入和导出

后端代码的实现

1、引入EasyExcel的依赖(准备工作)

        <!--excel导出实现-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.10</version>
        </dependency>

2、为需要被导出的实体类,进行相对应的注解配置(准备工作)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class DeptInfo implements Serializable {
    private static final long serialVersionUID = 294145927557737848L;

    /**
     * @ExcelIgnore 表示写或读Excel的时候,忽略该字段,若不忽略该字段,则会默认将字段名作为表头
     */
    @ExcelIgnore
    private Long id;

    /**
     * @ExcelProperty 设置表头
     */
    @ExcelProperty("部门名称")
    private String name;

    @ExcelProperty("部门描述")
    private String description;

    @ExcelProperty("部门负责人")
    private String principal;

    @ExcelProperty("部门电话")
    private String tel;
}

导出功能

(1)编写一个控制器,用于接收查询的参数,以及文件的导出

    @Autowired
    private DeptInfoMapper deptInfoMapper;

    /**
     * 部门的Excel导出功能
     * @param response
     * @param ids
     * @throws IOException
     */
    @PostMapping("/exportExcel")
    public void exportNewsInfoExcel2(HttpServletResponse response, @RequestBody List<Long> ids) throws IOException {
        // 查询出需要的数据
        List<DeptInfo> list = deptInfoMapper.selectListByIds(ids);
        // 导出Excel
        exportExcel(response, DeptInfo.class, list);
    }

(1.1)封装导出Excel的方法

    /**
     * 抽取导出功能
     * @param response  响应对象
     * @param clazz 导出的实体类型
     * @param list 导出的数据
     * @throws IOException
     */
    public void exportExcel(HttpServletResponse response, Class clazz, List list) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        EasyExcel.write(response.getOutputStream(), clazz).sheet("模板").doWrite(list);
    }

导入功能

(1)编写读取Excel时的监听器

@Slf4j
/**
 * 该类不能被spring管理
 */
public class DataListener implements ReadListener<DeptInfo> {

    /**
     * 用于存储每一条数据
     */
    private List<DeptInfo> cachedDataList = new ArrayList<>();

    /**
     * 访问数据库的Mapper对象
     */
    private DeptInfoMapper deptInfoMapper;

    public DataListener(DeptInfoMapper deptInfoMapper) {
        this.deptInfoMapper = deptInfoMapper;
    }

    /**
     * 这个每一条数据解析都会来调用
     */
    @Override
    public void invoke(DeptInfo deptInfo, AnalysisContext analysisContext) {
        // 放入缓存,读取完毕后再一起写入
        cachedDataList.add(deptInfo);
    }

    /**
     * 所有数据都读取完成后,则会调用该方法
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 将数据保存到数据库中
        saveData();
        log.info("所有数据解析完成!");
    }

    /**
     * 参照官方写法,返回true,若返回false则代表没有数据了,会直接读了个寂寞
     * @param analysisContext
     * @return
     */
    @Override
    public boolean hasNext(AnalysisContext analysisContext) {
        return true;
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        deptInfoMapper.insertBatch(cachedDataList);
        log.info("存储数据库成功!");
    }
    
    @Override
    public void invokeHead(Map<Integer, CellData> map, AnalysisContext analysisContext) {}
    

    @Override
    public void extra(CellExtra cellExtra, AnalysisContext analysisContext) { }

    @Override
    public void onException(Exception e, AnalysisContext analysisContext) throws Exception {
        log.error("Excel读取出现异常,{}", e.getMessage());
    }
}

(1)编写一个控制器,用于接收导入的请求

    @PostMapping("/importExcel")
    @ResponseBody
    public ResponseEntity importExcel(MultipartFile file){
        try{
            // 导入Excel,将文件流,以及需要对应的实体类,以及读取的监听器传入
            importExcel(file.getInputStream(), DeptInfo.class, new DataListener(deptInfoMapper));
        }catch (Exception e) {
            return ResponseEntity.ok(new ResultMsg(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Excel导入失败,请检查上传的文件格式!"));
        }
        // 导入成功
        return ResponseEntity.ok(new ResultMsg(HttpStatus.OK.value(), "导入成功"));
    }

(2)封装导入Excel的方法

    /**
     * 抽取导入功能
     * @param inputStream 需要读取的文件输入流
     * @param clazz  读取的实体类型
     * @param readListener 读取文件时的监听器
     */
    public void importExcel(InputStream inputStream, Class clazz, ReadListener<?> readListener) {
        EasyExcel.read(inputStream, clazz, readListener).sheet().doRead();
    }

前端代码的实现

(1)导出功能(使用axios实现异步导出功能)

(1.1)添加导出功能的按钮,为该按钮设置一个@click点击事件

<el-button type="success" @click="exportExcel">导出数据为Excel</el-button>

(1.2)编写前端导出事件的核心代码,主要是获取当前已经选中的行

exportExcel() {
    // 获取需要获取数据的id列表
    let ids = [];
    // 获取到现在选择的表格列表
    this.$refs.multipleTable.selection.forEach(row => ids.push(row.id));
    // 调用自定义的导出方法
    this.postDownLoadFile('/edusys/excel/exportExcel', ids, '部门列表的excel表格.xlsx')
}

(1.3)自定义一个导出的方法,模拟下载

postDownLoadFile(url, data, filename = '部门列表.xlsx') {
    axios.request({
        url: url,
        method: 'post',   // 以post请求为例
        data: data,   // 筛选列表的请求参数
        responseType: 'blob', // 注意响应的类型,必须为blob类型,是一个原始数据的类文件对象,能够使用二进制或文本读取
    }).then(res=>{
        // 获取到response中的文件数据
        const data = res.data
        // 将二进制文件转化为可访问的url
        let url = window.URL.createObjectURL(data)
        // 使用原生的document操作来创建一个a标签,并添加到body标签中
        var a = document.createElement('a')
        document.body.appendChild(a)
        // 设置其href请求路径
        a.href = url
        // 设置好下载的文件名,需要带上后缀
        a.download = filename
        // 模拟点击下载
        a.click()
        // 清除刚刚使用window.URL.createObjectURL(data) 创建的数据,避免在内存中遗留
        window.URL.revokeObjectURL(url)
    })
}

(2)导出功能

(2.1)编写一个dialog组件,用于Excel文件上传的框

<!-- 上传excel导入功能 -->
<el-dialog
        :close-on-click-modal="false"
        title="导入excel"
        :visible.sync="dialogImportExcelVisible">
    <!--
        ref: 该文件上传的组件指定一个ref,这样的话就可以通过 this.$refs.excelUpload的方式获取到该组件,才能调用该组件的方法,例如submit()
        class: 这就不说了
        action: 文件需要上传到的地址,填写刚刚控制器的地址,为什么要带/edusys上下文呢?因为浏览器识别/的时候,只会识别到http://localhost:80
        :on-success: 当文件上传成功时的回调函数
        :multiple="false" 禁止选中多个文件
        :limit 设置文件的上传数量
        :auto-upload="false" 关闭文件上传的自动提交功能
        :file-list="importFileList" 会显示在页面中的文件列表
        :on-change 当文件列表发生改变时,就会调用该方法
        :on-exceed 当文件上传超出limit限制时,就会调用该方法,我这里的limit是1,因此只要上传第二个文件,那么就会调用该方法
     -->
    <el-upload
            ref="excelUpload"
            class="upload-excel"
            action="/edusys/excel/importExcel"
            :on-success="uploadExcelSuccess"
            :multiple="false"
            :limit="1"
            :auto-upload="false"
            :file-list="importFileList"
            :on-change="handleImportChange"
            :on-exceed="excelHandleExceed">
        <el-button size="small" type="primary">点击上传</el-button>
        <div slot="tip" class="el-upload__tip">只能上传xlsx、xls结尾的Excel文件,并且一次只能上传一个!</div>
    </el-upload>
    <div slot="footer" class="dialog-footer">
        <!-- 点击取消时,将该上传的dialog关闭 -->
        <el-button @click="dialogImportExcelVisible = false">取 消</el-button>
        <!-- 手动上传文件 -->
        <el-button type="primary" @click="submitImportExcel">确 定</el-button>
    </div>
</el-dialog>

(2.2)在Vue示例的data中添加几个相对应的变量

// 导入时的上传文件列表
importFileList: [],
// 导入excel的弹出框标识
dialogImportExcelVisible: false

(2.3)编写文件列表发生变更时的回调函数,检验上传文件的格式

// 文件列表发生变更时的回调函数,用于检验上传文件的格式
handleImportChange(file, fileList) {
    const isXlsx = file.raw.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
    const isXls = file.raw.type === 'application/vnd.ms-excel';

    // 如果不是xlsx文件,也不是xls文件,则禁止放入文件列表。并进行友好提示
    if(!(isXlsx || isXls)) {
        this.$message({
            type: 'error',
            message: '上传的文件只能是xls或xlsx结尾的Excel文件,请重试'
        });
        // 将已经放在文件列表中的该文件删除
        this.importFileList = [];
    }
}

(2.4) 编写上传的文件超出限制时的回调函数

// 当用户想要上传超出limit限制的文件数量时的回调函数
excelHandleExceed() {
    this.$message({
        type: 'error',
        message: '一次只能上传一个Excel文件!'
    });
}

(2.5) 编写文件手动提交的方法

// 进行excel的真正提交,会提交到el-upload组件的action中配置的地址
submitImportExcel() {
    this.$refs.excelUpload.submit();
}

(2.6)编写文件上传成功的回调函数

// Excel文件上传成功时的回调函数
uploadExcelSuccess(response) {
    // 默认的上传文件成功的提示为成功标识
    let messageType = 'success';
    // 如果响应不为200,代表出现了错误
    if(response.code != 200) {
        messageType = 'error';
    }
    // 文件导入的提示信息
    this.$message({
        type: messageType,
        message: response.msg
    });
    // 清空文件列表
    this.importFileList = [];
    // 关闭dialog弹出框
    this.dialogImportExcelVisible = false;
    // 初始化数据
    this.initData();
}

标签:文件,Excel,遇到,解决方案,导出,public,开发,response,邮件
From: https://www.cnblogs.com/itdqx/p/16746933.html

相关文章

  • 工厂设备巡检系统解决方案
    现代化工厂生产车间,各种设备的24小时的运行,以及多样化的生产流程,对于设备的正常运转有着很高的要求,设备稳定高效运行和安全的生产车间,是生产型企业最为重要的问题,每年全国......
  • windows下关于Objective-C开发环境的配置
    最近IOS一直很火,也想学习以以下OC开发,一般装个虚拟机,然后装个mac,我相信大多数人的机子跑不起来或者很卡,所以之前借鉴了一个文章,就是关于在windows下配置OC开发环境,这里我把......
  • 驱动开发:内核R3与R0内存映射拷贝
    在上一篇博文《驱动开发:内核通过PEB得到进程参数》中我们通过使用KeStackAttachProcess附加进程的方式得到了该进程的PEB结构信息,本篇文章同样需要使用进程附加功能,但这次我......
  • 驱动开发:内核R3与R0内存映射拷贝
    在上一篇博文《驱动开发:内核通过PEB得到进程参数》中我们通过使用KeStackAttachProcess附加进程的方式得到了该进程的PEB结构信息,本篇文章同样需要使用进程附加功能,但这次......
  • 开发一个微信小程序(4):查询天气-获取某个城市的实时天气
    从这一篇开始介绍如何实现一个查询天气小程序 准备工作:1、申请和风天气开发者账号,并创建一个WebAPI类型的应用(要调用和风天气api获取天气,关于如何使用和风天气api需......
  • 开发一个微信小程序(1):获取文章列表
    ​目前主要实现了3个功能:在小程序上展示个人微信公众号上的文章;在小程序上展示个人在博客园上写的文章;查询每日天气;从本篇开始,我会用几篇文章来记录一下整个小程序开发的学......
  • 第二十五章 软件开发的目录规范
    一、基本概述为了提高程序的可读性与可维护性,我们应该为软件设计良好的目录结构,这与规范的编码风格同等重要。软件的目录规范并无硬性标准,只要清晰可读即可,假设你的软件名......
  • Android开发 Jetpack_Compose_2 页面预览@Preview
    前言在学习jetpackcompose如何编写ui之前,我认为还是应该先了解与Androidstudio配合的页面预览@Preview。这样就可以立刻看到UI效果,从而方便后续学习验证代码。所......
  • ESP32开发环境搭建 IDF3.3.5+VScode
    1、 软件准备:①ESP-IDF:包含ESP32API和用于操作工具链的脚本。②工具链msys32:用于编译ESP32应用程序。③编辑工具VisualStudioCode  注意:工具链和ESP-IDF需......
  • Win10 环境下 vscode 没法在终端使用 conda activate 命令来更换 Python 环境的解决方
    在vscode上激活conda镜像如报下面错误:CommandNotFoundError:Yourshellhasnotbeenproperlyconfiguredtouse'condaactivate'.Ifusing'condaactivate'fr......