智能面试——录音及播放下载js-audio-recorder — post请求,formdata传参

news2024/12/23 3:02:13

录音插件 js-audio-recorder

image.png

bug:本地调试调取不起来麦克风

  • 浏览器配置安全域名 chrome://flags/
  • Insecure origins treated as secure
  • 输入域名即可
  • 电脑需要连接上耳机
<template>
  <div class="BaseRecorder">
    <div class="BaseRecorder-record">
      <el-button @click="startRecorder()">开始录音</el-button>
      <el-button @click="pauseRecorder()">暂停录音</el-button>
      <el-button @click="resumeRecorder()">继续录音</el-button>
      <el-button @click="stopRecorder()">结束录音</el-button>
    </div>
    <div class="BaseRecorder-play">
      <el-button @click="playRecorder()">录音播放</el-button>
      <el-button @click="pausePlayRecorder()">暂停录音播放</el-button>
      <el-button @click="resumePlayRecorder()">恢复录音播放</el-button>
      <el-button @click="stopPlayRecorder()">停止录音播放</el-button>
    </div>
    <div class="BaseRecorder-download">
      <el-button @click="downPCM()">下载PCM</el-button>
      <el-button @click="downWAV()">下载WAV</el-button>
    </div>
    <div class="BaseRecorder-destroy">
      <el-button type="error" @click="destroyRecorder()">销毁录音</el-button>
    </div>
    <div class="BaseRecorder-wave">
      <canvas ref="record"></canvas>
      <canvas ref="play"></canvas>
    </div>
  </div>
</template>

<script>
import Recorder from "js-audio-recorder";

export default {
  name: "home",
  data() {
    return {
      recorder: null,
      // 波浪图-录音
      drawRecordId: null,
      // 波浪图-播放
      drawPlayId: null,
    };
  },
  mounted() {
    this.init();
  },
  methods: {
    // 初始化
    init() {
      this.recorder = new Recorder({
        // 采样位数,支持 8 或 16,默认是16
        sampleBits: 16,
        // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值
        sampleRate: 48000,
        // 声道,支持 1 或 2, 默认是1
        numChannels: 1,
        // 是否边录边转换,默认是false
        compiling: false,
      });
    },
    // 开始录音
    startRecorder() {
      this.recorder.start().then(
        () => {
          console.log("开始录音", this.recorder);
          this.drawRecord();
          this.recorder.onprogress = (params) => {
            console.log(params);

            // 此处控制数据的收集频率
            if (this.recorder.config.compiling) {
              console.log("音频总数据:", params.data);
            }
          };
          // 定时获取录音的数据并播放
          this.recorder.config.compiling &&
            (playTimer = setInterval(() => {
              let newData = this.recorder.getNextData();
              if (!newData.length) {
                return;
              }
              let byteLength = newData[0].byteLength;
              let buffer = new ArrayBuffer(newData.length * byteLength);
              let dataView = new DataView(buffer);

              // 数据合并
              for (let i = 0, iLen = newData.length; i < iLen; ++i) {
                for (let j = 0, jLen = newData[i].byteLength; j < jLen; ++j) {
                  dataView.setInt8(i * byteLength + j, newData[i].getInt8(j));
                }
              }

              // 将录音数据转成WAV格式,并播放
              let a = encodeWAV(
                dataView,
                config.sampleRate,
                config.sampleRate,
                config.numChannels,
                config.sampleBits
              );
              let blob = new Blob([a], { type: "audio/wav" });

              blob.arrayBuffer().then((arraybuffer) => {
                console.log(arraybuffer);
                // Player.play(arraybuffer);
              });
            }, 3000));
        },
        (error) => {
          // 出错了
          console.log(`${error.name} : ${error.message}`);
        }
      );
    },
    // 继续录音
    resumeRecorder() {
      this.recorder.resume();
    },
    // 暂停录音
    pauseRecorder() {
      this.recorder.pause();
      this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
      this.drawRecordId = null;
    },
    // 结束录音
    stopRecorder() {
      this.recorder.stop();
      this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
      this.drawRecordId = null;
    },
    // 录音播放
    playRecorder() {
      this.recorder.play();
      this.drawPlay(); // 绘制波浪图
    },
    // 暂停录音播放
    pausePlayRecorder() {
      this.recorder.pausePlay();
    },
    // 恢复录音播放
    resumePlayRecorder() {
      this.recorder.resumePlay();
      this.drawPlay(); // 绘制波浪图
    },
    // 停止录音播放
    stopPlayRecorder() {
      this.recorder.stopPlay();
    },
    // 销毁录音
    destroyRecorder() {
      this.recorder.destroy().then(() => {
        this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
        this.drawRecordId = null;

        this.drawPlayId && cancelAnimationFrame(this.drawPlayId);
        this.drawPlayId = null;

        this.recorder = null;
      });
    },

    /**
     *  下载录音文件
     * */
    // 下载pcm
    downPCM() {
      console.log("pcm: ", this.recorder.getPCMBlob());
      // 这里传参进去的时文件名
      this.recorder.downloadPCM("新文件");
    },
    // 下载wav
    downWAV() {
      console.log("wav: ", this.recorder.getWAVBlob());
      // 这里传参进去的时文件名
      this.recorder.downloadWAV("新文件");
    },

    /**
     * 绘制波浪图-录音
     * */
    drawRecord() {
      this.drawRecordId = requestAnimationFrame(this.drawRecord);
      this.drawWave({
        canvas: this.$refs.record,
        dataArray: this.recorder.getRecordAnalyseData(),
        bgcolor: "rgb(255, 128, 200)",
        lineWidth: 1,
        lineColor: "rgb(0, 128, 255)",
      });
    },
    /**
     * 绘制波浪图-播放
     * */
    drawPlay() {
      this.drawPlayId = requestAnimationFrame(this.drawPlay);
      this.drawWave({
        canvas: this.$refs.play,
        dataArray: this.recorder.getPlayAnalyseData(),
      });
    },
    drawWave({
      canvas,
      dataArray,
      bgcolor = "rgb(200, 200, 200)",
      lineWidth = 2,
      lineColor = "rgb(0, 0, 0)",
    }) {
      if (!canvas) return;

      const ctx = canvas.getContext("2d");
      const bufferLength = dataArray.length;
      // 一个点占多少位置,共有bufferLength个点要绘制
      const sliceWidth = canvas.width / bufferLength;
      // 绘制点的x轴位置
      let x = 0;

      // 填充背景色
      ctx.fillStyle = bgcolor;
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      // 设定波形绘制颜色
      ctx.lineWidth = lineWidth;
      ctx.strokeStyle = lineColor;

      ctx.beginPath();

      for (let i = 0; i < bufferLength; i++) {
        const v = dataArray[i] / 128;
        const y = (v * canvas.height) / 2;

        if (i === 0) {
          // 第一个点
          ctx.moveTo(x, y);
        } else {
          // 剩余的点
          ctx.lineTo(x, y);
        }
        // 依次平移,绘制所有点
        x += sliceWidth;
      }

      // 最后一个点
      ctx.lineTo(canvas.width, canvas.height / 2);
      ctx.stroke();
    },
  },
};
</script>
<style lang="scss" scoped>
.BaseRecorder {
  & > div {
    margin: 20px 0;
  }
  &-wave {
    canvas {
      width: 100%;
      border: 1px solid #ccc;
    }
  }
}
</style>

智能面试页面

image.png

<template>
  <div class="flex1 w100 h100 bg">
    <div style="width: 300px" class="bg-white h100 flex-column center">
      <div class="blue size-30 mb-60">Java面试专场</div>
      <div class="size-26">张三</div>
      <div class="gray-2 mt-20 mb-100">18378562388</div>
      <el-button type="success" round @click="start()">开始面试</el-button>
    </div>
    <div class="flex-1 h100 over-hidden">
      <div
        class="h100 w65 flex1 flex-column"
        style="margin: 0 auto; min-width: 800px"
      >
        <div class="flex-1 scroll w100 pt-30">
          <div
            v-for="(item, index) in list.filter((item) => item.show)"
            :key="index"
            class="mb-30"
          >
            <div class="flex_l mb-30">
              <i class="el-icon-question size-28 blue mr-10"></i>
              <div class="">
                {{ item.topic }}
              </div>
            </div>
            <div class="flex_l" v-if="item.file">
              <el-avatar
                class="mr-10"
                size="small"
                src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png"
              ></el-avatar>
              <el-card class="flex-1"> 语音已发送 </el-card>
            </div>
            <div class="flex_l" v-if="item.answer">
              <el-avatar
                class="mr-10"
                size="small"
                src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png"
              ></el-avatar>
              <el-card class="flex-1">
                {{ item.answer }}
              </el-card>
            </div>
          </div>
        </div>
        <div class="w100 flex1 pb-30">
          <el-input
            type="textarea"
            placeholder="请输入内容"
            v-model="textarea"
            maxlength="500"
            show-word-limit
            :autosize="{ minRows: 4 }"
          >
          </el-input>
          <div class="w10 text-center">
            <el-button
              type="success"
              icon="el-icon-microphone"
              circle
              class="size-16 mb-10"
              @click="startRecorder"
              :disabled="disabled"
            ></el-button>
            <el-button
              :disabled="disabled"
              type="primary"
              round
              @click="submit(1)"
              >提交</el-button
            >
          </div>
        </div>
      </div>
    </div>
    <!-- 结果 -->
    <el-dialog
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      title="面试结果"
      :visible.sync="centerDialogVisible"
      width="600px"
      center
      :show-close="false"
      style="top: 16vh"
    >
      <el-result
        :icon="score >= 80 ? 'success' : score >= 60 ? 'warning' : 'error'"
        :title="score >= 80 ? '优秀' : score >= 60 ? '良好' : '不合格'"
        subTitle="面试结果"
      >
        <template slot="extra">
          <el-button type="primary" size="medium" @click="back">返回</el-button>
        </template>
      </el-result>
    </el-dialog>
    <!-- 录音 -->
    <el-dialog
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      title="正在录音..."
      :visible.sync="audioVisible"
      width="600px"
      center
      :show-close="false"
      style="top: 16vh"
    >
      <div class="mb-20 size-18" v-if="list[index]">
        {{ list[index].topic }}
      </div>
      <div class="BaseRecorder-wave">
        <canvas ref="record"></canvas>
        <!-- <canvas ref="play"></canvas> -->
      </div>
      <div class="center mt-20">
        <el-button type="primary" size="medium" @click="submit(2)"
          >提交</el-button
        >
      </div>
    </el-dialog>
  </div>
  <!-- <div class="BaseRecorder">
    <div class="BaseRecorder-record">
      <el-button @click="startRecorder()">开始录音</el-button>
      <el-button @click="pauseRecorder()">暂停录音</el-button>
      <el-button @click="resumeRecorder()">继续录音</el-button>
      <el-button @click="stopRecorder()">结束录音</el-button>
    </div>
    <div class="BaseRecorder-play">
      <el-button @click="playRecorder()">录音播放</el-button>
      <el-button @click="pausePlayRecorder()">暂停录音播放</el-button>
      <el-button @click="resumePlayRecorder()">恢复录音播放</el-button>
      <el-button @click="stopPlayRecorder()">停止录音播放</el-button>
    </div>
    <div class="BaseRecorder-download">
      <el-button @click="downPCM()">下载PCM</el-button>
      <el-button @click="downWAV()">下载WAV</el-button>
    </div>
    <div class="BaseRecorder-destroy">
      <el-button type="error" @click="destroyRecorder()">销毁录音</el-button>
    </div>
    <div class="BaseRecorder-wave">
      <canvas ref="record"></canvas>
      <canvas ref="play"></canvas>
    </div>
  </div> -->
</template>

<script>
import Recorder from "js-audio-recorder";
// import { subText, subAudio } from "../api/test.js";
import axios from "axios";
export default {
  name: "home",
  data() {
    return {
      index: null,
      disabled: true,
      list: [
        {
          topic: "题目1:1+2等于几?",
          show: false,
          answer: "",
          result: "",
          file: "",
        },
        {
          topic: "题目2:2+2等于几?",
          show: false,
          answer: "",
          result: "",
          file: "",
        },
        {
          topic: "题目3:白日依山尽的下一句是什么?",
          show: false,
          answer: "",
          result: "",
          file: "",
        },
      ],
      textarea: "",
      config: {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      },
      centerDialogVisible: false, //结果弹窗
      score: "", //得分
      audioVisible: false, //录音弹窗

      recorder: null,
      // 波浪图-录音
      drawRecordId: null,
      // 波浪图-播放
      drawPlayId: null,
    };
  },
  mounted() {
    this.init();
  },
  beforeDestroy() {
    this.destroyRecorder();
  },
  methods: {
    start(i = 0) {
      this.index = i;
      this.list[this.index].show = true;
      this.disabled = false;
    },
    // type 1 文字  2 语音
    async submit(type) {
      if (type == 1) {
        if (!this.textarea.trim()) {
          this.$message({
            message: "请输入答案",
            type: "warning",
          });
          return;
        }
        this.list[this.index].answer = this.textarea;
        this.disabled = true;
        this.textarea = "";

        const formData = new FormData();
        formData.append("topic", this.list[this.index].topic);
        formData.append("answer", this.list[this.index].answer);
        const { data } = await axios.post(
          "/ququ/recognize-text",
          formData,
          this.config
        );
        console.log(data.result, 99);
        this.list[this.index].result = data.result;
        this.index += 1;
        if (this.index == this.list.length) {
          this.centerDialogVisible = true;
          this.index = null;
          console.log(this.list, 88);
          this.score =
            (this.list.filter((item) => item.result == "对").length * 100) /
            this.list.length;
        } else {
          this.start(this.index);
        }
      } else {
        this.stopRecorder();
        this.audioVisible = false;
        this.list[this.index].file = this.recorder.getWAVBlob();
        this.disabled = true;

        const formData = new FormData();
        formData.append("topic", this.list[this.index].topic);
        formData.append("file", this.list[this.index].file);
        const { data } = await axios.post(
          "/ququ/recognize-video",
          formData,
          this.config
        );
        console.log(data.result, 99);
        this.list[this.index].result = data.result;
        this.index += 1;
        if (this.index == this.list.length) {
          this.centerDialogVisible = true;
          this.index = null;
          console.log(this.list, 88);
          this.score =
            (this.list.filter((item) => item.result == "对").length * 100) /
            this.list.length;
        } else {
          this.start(this.index);
        }
      }
    },
    back() {
      this.centerDialogVisible = false;
      this.list = [
        {
          topic: "题目1:1+2等于几?",
          show: false,
          answer: "",
          result: "",
          file: "",
        },
        {
          topic: "题目2:2+2等于几?",
          show: false,
          answer: "",
          result: "",
          file: "",
        },
        {
          topic: "题目3:白日依山尽的下一句是什么?",
          show: false,
          answer: "",
          result: "",
          file: "",
        },
      ];
    },

    // 初始化
    init() {
      this.recorder = new Recorder({
        // 采样位数,支持 8 或 16,默认是16
        sampleBits: 16,
        // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值
        sampleRate: 48000,
        // 声道,支持 1 或 2, 默认是1
        numChannels: 1,
        // 是否边录边转换,默认是false
        compiling: false,
      });
    },
    // 开始录音
    startRecorder() {
      this.recorder.start().then(
        () => {
          console.log("开始录音", this.recorder);
          this.audioVisible = true;
          this.drawRecord();
          this.recorder.onprogress = (params) => {
            console.log(params);

            // 此处控制数据的收集频率
            if (this.recorder.config.compiling) {
              console.log("音频总数据:", params.data);
            }
          };
          // 定时获取录音的数据并播放
          this.recorder.config.compiling &&
            (playTimer = setInterval(() => {
              let newData = this.recorder.getNextData();
              if (!newData.length) {
                return;
              }
              let byteLength = newData[0].byteLength;
              let buffer = new ArrayBuffer(newData.length * byteLength);
              let dataView = new DataView(buffer);

              // 数据合并
              for (let i = 0, iLen = newData.length; i < iLen; ++i) {
                for (let j = 0, jLen = newData[i].byteLength; j < jLen; ++j) {
                  dataView.setInt8(i * byteLength + j, newData[i].getInt8(j));
                }
              }

              // 将录音数据转成WAV格式,并播放
              let a = encodeWAV(
                dataView,
                config.sampleRate,
                config.sampleRate,
                config.numChannels,
                config.sampleBits
              );
              let blob = new Blob([a], { type: "audio/wav" });

              blob.arrayBuffer().then((arraybuffer) => {
                console.log(arraybuffer);
                // Player.play(arraybuffer);
              });
            }, 3000));
        },
        (error) => {
          // 出错了
          console.log(`${error.name} : ${error.message}`);
        }
      );
    },
    // 继续录音
    resumeRecorder() {
      this.recorder.resume();
    },
    // 暂停录音
    pauseRecorder() {
      this.recorder.pause();
      this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
      this.drawRecordId = null;
    },
    // 结束录音
    stopRecorder() {
      this.recorder.stop();
      this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
      this.drawRecordId = null;
    },
    // 录音播放
    playRecorder() {
      this.recorder.play();
      this.drawPlay(); // 绘制波浪图
    },
    // 暂停录音播放
    pausePlayRecorder() {
      this.recorder.pausePlay();
    },
    // 恢复录音播放
    resumePlayRecorder() {
      this.recorder.resumePlay();
      this.drawPlay(); // 绘制波浪图
    },
    // 停止录音播放
    stopPlayRecorder() {
      this.recorder.stopPlay();
    },
    // 销毁录音
    destroyRecorder() {
      this.recorder.destroy().then(() => {
        this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
        this.drawRecordId = null;

        this.drawPlayId && cancelAnimationFrame(this.drawPlayId);
        this.drawPlayId = null;

        this.recorder = null;
      });
    },

    /**
     *  下载录音文件
     * */
    // 下载pcm
    downPCM() {
      console.log("pcm: ", this.recorder.getPCMBlob());
      // 这里传参进去的时文件名
      this.recorder.downloadPCM("新文件");
    },
    // 下载wav
    downWAV() {
      console.log("wav: ", this.recorder.getWAVBlob());
      // 这里传参进去的时文件名
      this.recorder.downloadWAV("新文件");
    },

    /**
     * 绘制波浪图-录音
     * */
    drawRecord() {
      this.drawRecordId = requestAnimationFrame(this.drawRecord);
      this.drawWave({
        canvas: this.$refs.record,
        dataArray: this.recorder.getRecordAnalyseData(),
        bgcolor: "#a8e1fc",
        lineWidth: 1,
        lineColor: "rgb(255, 128, 200)",
      });
    },
    /**
     * 绘制波浪图-播放
     * */
    drawPlay() {
      this.drawPlayId = requestAnimationFrame(this.drawPlay);
      this.drawWave({
        canvas: this.$refs.play,
        dataArray: this.recorder.getPlayAnalyseData(),
      });
    },
    drawWave({
      canvas,
      dataArray,
      bgcolor = "rgb(200, 200, 200)",
      lineWidth = 2,
      lineColor = "rgb(0, 0, 0)",
    }) {
      if (!canvas) return;

      const ctx = canvas.getContext("2d");
      const bufferLength = dataArray.length;
      // 一个点占多少位置,共有bufferLength个点要绘制
      const sliceWidth = canvas.width / bufferLength;
      // 绘制点的x轴位置
      let x = 0;

      // 填充背景色
      ctx.fillStyle = bgcolor;
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      // 设定波形绘制颜色
      ctx.lineWidth = lineWidth;
      ctx.strokeStyle = lineColor;

      ctx.beginPath();

      for (let i = 0; i < bufferLength; i++) {
        const v = dataArray[i] / 128;
        const y = (v * canvas.height) / 2;

        if (i === 0) {
          // 第一个点
          ctx.moveTo(x, y);
        } else {
          // 剩余的点
          ctx.lineTo(x, y);
        }
        // 依次平移,绘制所有点
        x += sliceWidth;
      }

      // 最后一个点
      ctx.lineTo(canvas.width, canvas.height / 2);
      ctx.stroke();
    },
  },
};
</script>
<style lang="scss" scoped>
.BaseRecorder {
  & > div {
    margin: 20px 0;
  }
  &-wave {
    canvas {
      width: 100%;
      border: 1px solid #ccc;
    }
  }
}
</style>

post请求,formdata传参

const formData = new FormData();
formData.append("topic", this.list[this.index].topic);
formData.append("answer", this.list[this.index].answer);
const { data } = await axios.post(
     "/ququ/recognize-text",
     formData,
     {
        headers: {
          "Content-Type": "multipart/form-data",
        },
     }
 );
console.log(data.result, 99);

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

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

相关文章

seo调优

SEO 网站地图&#xff1a;sitemap.xmlrobots.txtxxx.com/www.xxx.com 解析到服务器&#xff0c;xxx.com 301 到 www.xxx.comhttps百度站点管理标题描述关键词标签语义化内链外链死链链接html结尾友情链接前端架构 注意&#xff1a;已收录链接&#xff0c;禁止改变链接地址 ro…

【C++第三阶段】deque容器评委打分案例

以下内容仅为当前认识&#xff0c;可能有不足之处&#xff0c;欢迎讨论&#xff01; 文章目录 构造函数赋值操作大小操作插入删除数据存取排序评委评分案例描述 deque容器 双端数组&#xff0c;可以对头端插入删除操作。 如下图所示。 头部有插入删除操作&#xff0c;尾部亦然…

国内如何实现GPT升级付款

本来想找国外的朋友代付的&#xff0c;但是他告诉我他的信用卡已经被绑定了他也升级了所以只能自己想办法了。就在一位博主下边发现了这个方法真的可以。只是需要与支付宝验证信息。刚开始不敢付款害怕被骗哈哈&#xff0c;我反诈骗意识绝对杠杠的 该方法就是我们办理一张虚拟…

After Effects 2024 中文激活版 高效工作流程与创新的视觉特效 mac/win

After Effects 2024是Adobe公司推出的一款专业视频特效制作软件&#xff0c;广泛应用于电影、电视、动画等媒体制作领域。它凭借强大的功能和灵活的操作&#xff0c;帮助用户轻松创建电影级影片字幕、片头和过渡效果&#xff0c;以及实现立体效果和动态场景的切换。 同时&#…

Java-接口—知识(基础)

承接上一节&#xff0c;我们讨论了抽象类和抽象方法。 那我们尝试在抽象的道路上走的更远一点&#xff0c;先来总结一下抽象&#xff1b; 抽象类&#xff1a;类中的属性规范了子类必须有什么样的特征&#xff0c;有什么状态。类中的方法规范了子类必须有什么行为&#xff0c;…

【Spring Security】2.实现最简单的身份验证

文章目录 一、找到官网的身份认证&#xff08;authentication&#xff09;示例代码二、实现最简单的身份验证1、创建Spring Boot项目2、创建IndexController3、创建index.html4、启动项目测试Controller 三、{/logout}的作用四、页面样式无法加载的问题 一、找到官网的身份认证…

文本处理常见命令

目录 前言-了解Linux目录结构 一、cat-查看文件内容 1.表现形式 2.常用选项 3.示例 二、more-查看文件内容 1.表现形式 2.交互操作方法 3.示例 三、less-查看文件内容 1.表现形式 2.交互操作方法 四、head-从头查看文件内容 五、tail-从尾查看文件内容 六、wc-统…

设计模式学习笔记 - 设计模式与范式 -行为型:10.迭代器模式(中):遍历集合时,为什么不能增删集合?

概述 上篇文章&#xff0c;我们通过给 ArrayList 和 LinkedList 容器实现迭代器&#xff0c;学习了迭代器模式的原理、实现和设计意图。迭代器模式主要主要是解耦容器代码和遍历代码。 本章&#xff0c;我们来深挖一下&#xff0c;如果在使用迭代器遍历集合的同时增加、删除集…

1999-2022年各省研究与试验发展人员全时当量数据/省研发人员全时当量数据/(RD)人员全时当量(无缺失)

1999-2022年各省研究与试验发展人员全时当量数据/省研发人员全时当量数据/(R&D)人员全时当量&#xff08;无缺失&#xff09; 1、时间&#xff1a;1999-2022年 2、来源&#xff1a;科技年鉴 3、指标&#xff1a;研究与试验发展人员全时当量/研发人员全时当量 4、范围&a…

代码随想录算法训练营Day50|LC123 买卖股票的最佳时机IIILC188 买卖股票的最佳时机IV

一句话总结&#xff1a;虽然是困难题&#xff0c;其实都只需要对122 买卖股票的最佳时机II稍作变形即可。 原题链接&#xff1a;123 买卖股票的最佳时机III 相较于买卖股票的最佳时机和股票II来说&#xff0c;本题加了最多操作两次的限制。那么这里实际上就可以直接用滚动数组…

用C代码实现环形缓冲区(ring buf)

用C代码实现环形缓冲区&#xff08;ring buf&#xff09; 概述环境介绍launch.json(没改&#xff09;tasks.json注意 代码ringbuf.cringbuf.hmain.c 测试说明工程代码下载 概述 因嵌入式项目需要&#xff0c;串口接收的数据有很高的周期性发送频率&#xff0c;原方式通过查询接…

小程序项目思路分享爬虫

小程序项目思路分享爬虫 具体需求&#xff1a; 有这几个就行&#xff0c;门店名称门店地址门店类型&#xff0c;再加上省、市、县/区门店名称&#xff1a;storeName 门店地址&#xff1a;storeAddress 程序运行&#xff1a; honor_spider获取经纬度信息。 经纬度——>详…

Mybatis plus 使用通用枚举

说明&#xff1a;mybatis plus 使用枚举可实现数据库存入时指定值保存&#xff0c; 读取时指定值展示&#xff08;返给前端&#xff09; 可通过继承IEnum<T>、 EnumValue实现 1、引包 <dependency><groupId>mysql</groupId><artifactId>mysql-…

esxi上给centos7虚拟机扩容硬盘

原来centos7硬盘分配的空间只有40GB 需要直接扩容到200GB 扩容前 扩容后 扩容步骤&#xff1a; 1 .在esxi平台上关机虚拟机&#xff0c;将硬盘调整为200GB&#xff0c;然后开机 2.请出chatGPT 1. 创建新分区 使用剩余的磁盘空间创建一个新的分区。你可以使用fdisk&#xf…

归档数据shell脚本

系统中数据很重要&#xff0c;为确保数据不会丢失&#xff0c;定时备份数据是一个必要的习惯。制定一个存储重要文件的数据备份计划也绝非易事&#xff0c;而shell脚本可以祝我们一臂之力。 1.创建需要备份配置文件的路径文件。(BACKUP_FILE) 2.以日期为备份文件的后缀。 3.判断…

LeetCode 热题 100 | 多维动态规划(二)

目录 1 5. 最长回文子串 2 1143. 最长公共子序列 菜鸟做题&#xff0c;语言是 C 1 5. 最长回文子串 核心思想&#xff1a;把总问题拆解为若干子问题。 总问题&#xff1a;从第 i 个字母到第 j 个字母是回文串子问题&#xff1a;从第 i 1 个字母到第 j - 1 个字母是回文…

【就近接入,智能DNS-Geo DNS ,大揭秘!】

做过后端服务或者网络加速的小伙伴&#xff0c;可能或多或少都听说过&#xff0c;智能DNS或者Geo DNS&#xff0c;就是根据用户的位置&#xff0c;返回离用户最近的服务节点&#xff0c;就近接入&#xff0c;以达到服务提速的效果。 那么大家有没想过&#xff0c;这个背后的原理…

ETLCloud结合kafka的数据集成

一、ETLCloud中实时数据集成的使用 在ETLCloud中数据集成有两种方式&#xff0c;一种是离线数据集成&#xff0c;另一种便是我们今天所要介绍的实时数据集成了&#xff0c;两者的区别从名字便可以得知&#xff0c;前者处理的数据是离线的没有时效性的&#xff0c;后者的数据是…

【Keil5-Boot和APP配置】

Keil5-Boot和App配置 ■ Keil5-Boot和APP配置■ 一&#xff1a;sct文件 sct文件配置■ 二&#xff1a;发布版本不需要在 C/C&#xff0c;Asm&#xff0c;Linker&#xff0c;中添加 CMDDEBUG 宏定义。■ 三&#xff1a;Debug版本需要在Linker添加 --pd"-DCMDDEBUG" 才…

4.进程相关 2

8.内存映射 8.1 内存映射相关定义 创建一个文件&#xff0c;将保存在磁盘中的文件映射到内存中&#xff0c;后期两个进程之间对内存中的数据进行操作&#xff0c;大大减少了访问磁盘的时间&#xff0c;也是一种最快的 IPC &#xff0c;因为进程之间可以直接对内存进行存取 8.…