vue3实现实现手机/PC端录音:recorder-core

在这里插入图片描述

通过 recorder-core 这个插件实现录音

recorder-core插件使用

下方的js文件是安装后封装的一个js文件,在需要使用的地方直接引入这个文件:import record from “./recorderCore.js”;

//  文件名称:recorderCore.js// recorder-core插件使用方式:https://huaweicloud.csdn.net/6549fb3434bf9e25c799ca07.html?dp_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MTI5NDc5OSwiZXhwIjoxNzUzOTM3ODg5LCJpYXQiOjE3NTMzMzMwODksInVzZXJuYW1lIjoic2lzdWliYW4ifQ.Y2_R3XsABjzRvhML0rdYMuGJhYrIDM-rrPob4RDJtro&spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-6-131902136-blog-147322532.235%5Ev43%5Econtrol&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-6-131902136-blog-147322532.235%5Ev43%5Econtrol&utm_relevant_index=13
// 例子 https://blog.csdn.net/weixin_47137972/article/details/147322532?ops_request_misc=%257B%2522request%255Fid%2522%253A%25226a538d344bc89fef66029e7d7a2a0b06%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=6a538d344bc89fef66029e7d7a2a0b06&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~sobaiduend~default-1-147322532-null-null.nonecase&utm_term=vue%E5%AE%9E%E7%8E%B0%E5%BD%95%E9%9F%B3%E5%8A%9F%E8%83%BD&spm=1018.2226.3001.4450
//必须引入的核心
import Recorder from 'recorder-core';//引入mp3格式支持文件;如果需要多个格式支持,把这些格式的编码引擎js文件放到后面统统引入进来即可
import 'recorder-core/src/engine/mp3';
import 'recorder-core/src/engine/mp3-engine';
//录制wav格式的用这一句就行
import 'recorder-core/src/engine/wav';const record = {RecordApp: null,recBlob: null,/**麦克风授权 */getPermission: (fn) => {const newRec = Recorder({type: 'wav',bitRate: 16,sampleRate: 16000, //阿里采样率16000onProcess: function (buffers, powerLevel, duration, bufferSampleRate) {// console.log(buffers);},});//打开录音,获得权限newRec.open(() => {record.RecordApp = newRec;fn({ status: 'success', data: '开启成功' });},(msg, isUserNotAllow) => {//用户拒绝了录音权限,或者浏览器不支持录音fn({ status: 'fail', data: msg });// console.log((isUserNotAllow ? 'UserNotAllow,' : '') + '无法录音:' + msg);});},/**开始录音 */startRecorder: () => {if (record.RecordApp && Recorder.IsOpen()) {record.RecordApp.start();}},/** 停止录音 */stopRecorder: (fn) => {try {if (!record) {// console.error('未打开录音');return;}record.RecordApp.stop((blob, duration) => {// console.log('录音成功', blob, '时长:' + duration + 'ms');if (blob) {record.recBlob = blob;const url = URL.createObjectURL(blob);const formData = new FormData();formData.append('audio', blob);fn({ loading: true }, url, blob);}/* eslint-enable */record.RecordApp.close();record.RecordApp = null;});} catch (err) {fn({ err: err });// console.error('结束录音出错:' + err);record.RecordApp.close();record.RecordApp = null;}},/**关闭录音,释放麦克风资源 */destroyRecorder: () => {if (record.RecordApp) {record.RecordApp.close();record.RecordApp = null;}},/**暂停 */pauseRecorder: () => {if (record.RecordApp) {record.RecordApp.pause();}},/**恢复继续录音 */resumeRecorder: () => {if (record.RecordApp) {record.RecordApp.resume();}},
};export default record;

接下来就是使用上方的js文件

import record from "./config/recorderCore.js";// 点击了开始录音按钮
const onclick_luyin = () => {record.getPermission(function (permiss) {if (permiss.status == "fail") {ElMessage.error(permiss.data); //这里直接写一个报错提示,我这用的是elementUI的} else {record.startRecorder(); //开始录音}});
};
// 录音停止按钮
const onclick_guanbi = () => {record.stopRecorder((res, url, blob) => {if (blob && blob.size) {console.log("文件大小:", blob.size);// 调用语音转文字的接口AudioToText(blob);}});
};
// 语音转文字
const AudioToText = async (file) => {const maxSize = 14 * 1024 * 1024; // 14MBif (file.size > maxSize) {ElMessage.error("语音文件的大小超过14MB,请重新录音");return;}const baseurl = `${DEEPSEEK_CONFIG.baseURL}/audio-to-text`;const apiKey = `${DEEPSEEK_CONFIG.apiKey}`;// 强制指定 MIME 为 audio/mp3const newFile = new File([file], "语音", { type: "audio/mp3" });const formData = new FormData();formData.append("file", newFile);try {const response = await fetch(baseurl, {method: "POST",headers: {Authorization: `Bearer ${apiKey}`,},body: formData,});const text = await response.text();try {const data = JSON.parse(text);if (response.ok) {queryKeys.value = data.text;} else {queryKeys.value = "";ElMessage.error(`语音转文字接口错误:${JSON.stringify(data)}`);}} catch {queryKeys.value = "";ElMessage.error(`语音转文字接口响应不是 JSON:${text}`);}} catch (error) {queryKeys.value = "";ElMessage.error(`语音转文字接口请求异常:${error.message}`);}
};

提供一个vue录音动画组件

<template><transition name="modal-fade"><div v-if="isOpen" class="modal-overlay" @click="handleOverlayClick"><!-- 科技感网格背景 --><div class="tech-grid"></div><!-- 扫描线效果 --><div class="scan-line" :class="{ active: props.isOpen }"></div><div class="modal-container"><!-- 装饰性光效 --><div class="glow-effect top"></div><div class="glow-effect bottom"></div><div class="audio-animation-container"><!-- 高科技风格波形容器 --><div class="wave-container"><divv-for="(bar, index) in bars":key="index"class="wave-bar":style="{height: bar.height,background: bar.gradient,boxShadow: bar.glow,transitionDelay: `${bar.delay}ms`,transform: `scaleX(${bar.scale})`}"></div><!-- 倒计时显示 - 现在位于波形中央 --><div class="countdown-display"><span class="countdown-number">{{ countdown }} / 60</span></div></div></div><!-- 状态指示器 --><div class="status-indicator"><div class="pulse-dot"></div><span style="color:#fff">可以开始讲话了,总共能讲60秒</span></div></div></div></transition>
</template><script setup>
import { ref, onBeforeUnmount, watch, onUnmounted } from "vue";const props = defineProps({isOpen: {type: Boolean,required: true,},// 科技感主色调primaryColor: {type: String,default: '#fff'},// 动画速度(毫秒)speed: {type: Number,default: 80},// 波形条数量barCount: {type: Number,default: 40, // 更多的波形条增强科技感validator: (value) => value >= 20 && value <= 40},// 最大高度比例maxHeightRatio: {type: Number,default: 85,validator: (value) => value >= 70 && value <= 100}
});const emit = defineEmits(["close"]);// 倒计时相关
const countdown = ref(0);
let countdownTimer = null;// 关闭模态框
const closeModal = () => {stopAnimation();stopCountdown();emit("close");
};// 点击遮罩关闭
const handleOverlayClick = () => {closeModal();
};// 生成科技感渐变色
const generateGradient = (index) => {// 基于位置生成微妙的色调变化const hueOffset = (index % 10) * 3;const baseColor = props.primaryColor;const lightColor = shadeColor(baseColor, 30);return `linear-gradient(180deg, ${lightColor} 0%, ${baseColor} 70%)`;
};// 调整颜色明暗度
const shadeColor = (color, percent) => {let R = parseInt(color.substring(1, 3), 16);let G = parseInt(color.substring(3, 5), 16);let B = parseInt(color.substring(5, 7), 16);R = parseInt(R * (100 + percent) / 100);G = parseInt(G * (100 + percent) / 100);B = parseInt(B * (100 + percent) / 100);R = (R < 255) ? R : 255;G = (G < 255) ? G : 255;B = (B < 255) ? B : 255;R = Math.round(R);G = Math.round(G);B = Math.round(B);const RR = ((R.toString(16).length === 1) ? "0" + R.toString(16) : R.toString(16));const GG = ((G.toString(16).length === 1) ? "0" + G.toString(16) : G.toString(16));const BB = ((B.toString(16).length === 1) ? "0" + B.toString(16) : B.toString(16));return `#${RR}${GG}${BB}`;
};// 波形数据数组
const bars = ref([]);
// 初始化波形数据
for (let i = 0; i < props.barCount; i++) {const color = generateGradient(i);const glowColor = shadeColor(props.primaryColor, 50);bars.value.push({height: '5%',gradient: color,glow: `0 0 8px ${glowColor}, 0 0 12px ${glowColor}33`,delay: calculateDelay(i, props.barCount),scale: 1});
}// 计算每个波形条的动画延迟,创建同步波动效果
function calculateDelay(index, total) {// 创造波浪式延迟模式,增强科技感return (index % 5) * 40;
}// 动画定时器
let animationTimer = null;
let pulseTimer = null;// 生成更有规律的波形高度,符合高科技感
const generateHeights = () => {const newBars = [...bars.value];const maxHeight = props.isOpen ? props.maxHeightRatio : 10;const minHeight = props.isOpen ? 5 : 3;// 创建更有规律的波形模式,类似音频频谱const time = Date.now() / 500;newBars.forEach((bar, index) => {// 使用正弦函数创建更流畅的波形const frequency = 0.5 + (index / newBars.length) * 2;const amplitude = props.isOpen ? 0.5 + Math.random() * 0.5 : 0.2;const baseHeight = (maxHeight - minHeight) * 0.5 + minHeight;const wave = Math.sin(time * frequency + (index * 0.3)) * amplitude;const height = Math.floor(baseHeight * (1 + wave));// 添加微妙的缩放效果const scale = props.isOpen ? 1 + (wave * 0.1) : 1;newBars[index] = {...bar,height: `${height}%`,scale: scale,gradient: generateGradient(index)};});bars.value = newBars;
};// 启动动画
const startAnimation = () => {if (animationTimer) clearInterval(animationTimer);if (pulseTimer) clearInterval(pulseTimer);generateHeights();animationTimer = setInterval(generateHeights, props.speed);// 启动脉冲效果pulseTimer = setInterval(() => {const glowElements = document.querySelectorAll('.glow-effect');glowElements.forEach(el => {el.classList.add('pulse');setTimeout(() => el.classList.remove('pulse'), 500);});}, 2000);
};// 停止动画并重置
const stopAnimation = () => {if (animationTimer) {clearInterval(animationTimer);animationTimer = null;}if (pulseTimer) {clearInterval(pulseTimer);pulseTimer = null;}// 平滑重置为低波形const newBars = [...bars.value].map(bar => ({...bar,height: '5%',scale: 1}));bars.value = newBars;
};// 启动倒计时
const startCountdown = () => {// 重置倒计时countdown.value = 0;// 清除现有定时器if (countdownTimer) {clearInterval(countdownTimer);}// 设置新定时器countdownTimer = setInterval(() => {countdown.value++;// 当倒计时达到60时关闭模态框if (countdown.value >= 60) {handleOverlayClick();}}, 1000);
};// 停止倒计时
const stopCountdown = () => {if (countdownTimer) {clearInterval(countdownTimer);countdownTimer = null;}
};// 监听isOpen状态变化,控制动画和倒计时
watch(() => props.isOpen,(newVal) => {if (newVal) {startAnimation();startCountdown();} else {stopCountdown();}},{ immediate: true }
);// 监听颜色变化
watch(() => props.primaryColor,(newVal) => {const updatedBars = [...bars.value].map((bar, index) => {const color = generateGradient(index);const glowColor = shadeColor(newVal, 50);return {...bar,gradient: color,glow: `0 0 8px ${glowColor}, 0 0 12px ${glowColor}33`};});bars.value = updatedBars;}
);// 组件卸载时清理
onBeforeUnmount(() => {stopAnimation();stopCountdown();
});onUnmounted(() => {if (animationTimer) clearInterval(animationTimer);if (pulseTimer) clearInterval(pulseTimer);if (countdownTimer) clearInterval(countdownTimer);
});
</script><style scoped>
/* 高科技风格配色方案 */
:root {--tech-blue: #00e5ff;--tech-dark: #0a1929;--tech-darker: #050f1a;--tech-light: #64ffda;--glow: 0 0 10px var(--tech-blue), 0 0 20px rgba(0, 229, 255, 0.3);--glow-strong: 0 0 15px var(--tech-blue), 0 0 30px rgba(0, 229, 255, 0.5);--transition-fast: all 0.1s ease-out;--transition-slow: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}.modal-overlay {position: fixed;left: 0;right: 0;bottom: 200px;display: flex;justify-content: center;align-items: center;z-index: 1000;height: 200px;overflow: hidden;
}/* 科技感网格背景 */
.tech-grid {position: absolute;top: 0;left: 0;right: 0;bottom: 0;background-image: linear-gradient(rgba(0, 229, 255, 0.1) 1px, transparent 1px),linear-gradient(90deg, rgba(0, 229, 255, 0.1) 1px, transparent 1px);background-size: 20px 20px;z-index: -1;animation: gridMove 8s linear infinite;
}/* 扫描线效果 */
.scan-line {position: absolute;top: -5%;left: 0;right: 0;height: 2px;background: linear-gradient(90deg, transparent, var(--tech-blue), transparent);opacity: 0.3;z-index: 1;transition: opacity 0.5s ease;
}.scan-line.active {opacity: 0.6;animation: scan 3s linear infinite;
}@keyframes scan {0% { top: -5%; }100% { top: 105%; }
}@keyframes gridMove {0% { background-position: 0 0; }100% { background-position: 20px 20px; }
}.modal-container {position: relative;background-color: var(--tech-dark);border: 1px solid rgba(0, 229, 255, 0.3);border-radius: 8px;backdrop-filter: blur(10px);box-shadow: var(--glow);width: 90%;max-width: 600px;padding: 20px;display: flex;flex-direction: column;align-items: center;overflow: hidden;
}/* 装饰性光效 */
.glow-effect {position: absolute;left: 0;right: 0;height: 2px;background: linear-gradient(90deg, transparent, var(--tech-blue), transparent);opacity: 0.6;transition: var(--transition-slow);
}.glow-effect.top { top: 0; }
.glow-effect.bottom { bottom: 0; }.glow-effect.pulse {opacity: 1;box-shadow: var(--glow-strong);
}.audio-animation-container {display: flex;justify-content: center;align-items: center;width: 100%;height: 140px;
}.wave-container {display: flex;align-items: center;justify-content: center;gap: 2px; /* 更紧密的波形条 */width: 100%;height: 100%;position: relative; /* 新增:为了让倒计时能绝对定位在波形内部 */
}.wave-bar {width: 3px; /* 更细的波形条 */border-radius: 1px;transition: var(--transition-fast);transform-origin: center bottom;
}/* 倒计时显示样式 - 现在位于波形中央 */
.countdown-display {position: absolute;display: flex;flex-direction: column;align-items: center;justify-content: center;color: var(--tech-blue);font-family: 'Courier New', monospace;z-index: 2; /* 确保在波形条上方显示 */pointer-events: none; /* 允许点击穿透到下方的波形 */
}.countdown-number {font-size: 24px;font-weight: 600;font-weight: bold;text-shadow: 0 0 8px var(--tech-blue), 0 0 12px rgba(0, 229, 255, 0.5);line-height: 1;
}.countdown-label {font-size: 10px;opacity: 0.8;margin-top: 2px;
}/* 状态指示器 */
.status-indicator {display: flex;align-items: center;gap: 8px;margin-top: 10px;
}.status-indicator span {color: var(--tech-blue);font-family: 'Courier New', monospace;font-size: 11px;letter-spacing: 1px;opacity: 0.8;
}.pulse-dot {width: 6px;height: 6px;border-radius: 50%;background-color: #ff3e3e;animation: pulse 1.5s infinite;
}@keyframes pulse {0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(255, 62, 62, 0.7); }70% { transform: scale(1); box-shadow: 0 0 0 6px rgba(255, 62, 62, 0); }100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(255, 62, 62, 0); }
}/* 过渡动画 */
.modal-fade-enter-active,
.modal-fade-leave-active {transition: opacity 0.4s ease, transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
}.modal-fade-enter-from {opacity: 0;transform: translateY(20px) scale(0.98);
}.modal-fade-leave-to {opacity: 0;transform: translateY(10px) scale(0.99);
}
</style>

组件使用:

<AudioWaveAnimation:isOpen="isRecording":primaryColor="getRandomShadow()"@close="onclick_guanbi"/>// js
import AudioWaveAnimation from "./component/AudioWaveAnimation.vue";// 组件的显示与隐藏开关
const isRecording = ref(false);
// 生成随机颜色
function getRandomShadow() {const hue = Math.floor(Math.random() * 360); // 色相(0-360)const saturation = Math.floor(Math.random() * 30) + 70; // 饱和度(70%-100%)const lightness = Math.floor(Math.random() * 20) + 60; // 明度(60%-80%)const alpha = 0.3 + Math.random() * 0.3; // 透明度(0.3-0.6)// 直接返回hsla颜色值return `hsla(${hue}, ${saturation}%, ${lightness}%, ${alpha})`;
}

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

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

相关文章

deepseek 本地部署,如何支持工具调用

这里需要考虑显卡是否和模型匹配&#xff0c;支不支持推理 先把模版拉取到本地&#xff1a;git clone https://github.com/sgl-project/sglang.git 我的位置是 /data/home/sglang 注意模版位于sglang下的examples/chat_template中 根据对应的模版部署模型&#xff0c;比如 …

Excel中运行VB的函数

“插入” -》 “模块”Function FormatCodeFlex(inputStr As String, Optional defaultVal As String "0") As StringOn Error GoTo ErrorHandlerDim parts() As StringDim i As Integer 使用 "-" 分割字符串parts Split(inputStr, "-") 确保至…

《零基础入门AI:深度学习之NLP基础学习》

一、自然语言处理&#xff08;NLP&#xff09;概述 1. 基本概念 ​ 自然语言处理&#xff08;Natural Language Processing, NLP&#xff09;是人工智能与计算语言学交叉的核心领域&#xff0c;致力于实现计算机对人类自然语言的自动理解、分析、生成与交互。其研究目标在于构…

保姆级Debezium抽取SQL Server同步kafka

前言&#xff1a; Debezium SQL Server连接器捕获SQL Server数据库模式中发生的行级更改。 官方2.0文档&#xff1a; Debezium connector for SQL Server :: Debezium Documentation 有关与此连接器兼容的SQL Server版本的信息&#xff0c;请参阅 SQL Server Database: 201…

鸿蒙安卓前端中加载丢帧:ArkWeb分析

序章&#xff1a;卡顿的数字世界 在每秒60帧的视觉交响乐中&#xff0c;每一帧都是精心编排的节拍。当这些节拍开始丢失——就像交响乐中突然静音的提琴部——我们便遭遇了加载丢帧的数字噩梦。这不是简单的性能下降&#xff0c;而是一场渲染管线的全面崩溃&#xff0c;是数字…

Spring Cloud Netflix学习笔记06-Zuul

文章目录概述什么是Zuul?Zuul 能干嘛&#xff1f;Zuul入门案例pom依赖application.yml启动类隐藏真实路径概述 什么是Zuul? Zuul包含了对请求的路由(用来跳转的)和过滤两个最主要功能&#xff1a; 其中路由功能负责将外部请求转发到具体的微服务实例上&#xff0c;是实现外…

c# 和 c++ 怎样结合

c# 和 c 怎样结合在软件开发中&#xff0c;C# 和 C 通常用于不同的场景和目的&#xff0c;但有时需要将它们结合使用以充分利用两种语言的优点。以下是几种常见的方法来实现 C# 和 C 的结合&#xff1a;1. P/Invoke&#xff08;Platform Invocation Services&#xff09;P/Invo…

开源分布式数据库(Dgraph)

Dgraph 是一款专为处理复杂关系数据设计的开源分布式图数据库&#xff0c;核心目标是提供高性能、高可扩展性的图数据存储与查询能力。其设计融合了原生图模型与分布式架构&#xff0c;支持 GraphQL 查询语言&#xff0c;适用于社交网络、知识图谱、推荐系统等场景。 一、技术架…

Apache ShenYu和Nacos之间的通信原理

这是一个非常经典的服务注册发现和动态配置管理的案例。ShenYu 作为网关,需要实时感知后端微服务的上线、下线以及其元数据信息(如 API 接口列表)的变化,同时它自身的配置也可能需要动态调整。Nacos 则作为注册中心和配置中心,扮演了“服务电话簿”和“动态配置仓库”的角…

强制重启导致Ubuntu24.04LTS amd的WIFI无法使用的解决方案

强制重启导致Ubuntu24.04LTS amd的WIFI无法使用的解决方案 前言 ‍ 我按下了<ctrl><alt><prtsc>组合键&#xff0c;然后按住<ctrl><alt>不放&#xff0c;让我的死机的图形化的Ubuntu强制重启&#xff0c;然后再次打开发现&#xff0c;我的ubu…

Java基础面试题02

引用&#xff1a;&#xff08;代码随想录的八股转免费了&#xff09;以下为网址 卡码笔记 本文为学习以上文章的笔记&#xff0c;如果有时间推荐直接去原网址 Java中的数据类型有哪些&#xff1f;分为哪两大类&#xff1f; (考点&#xff1a;Java数据类型及其分类) 【简单】 基…

RabbitMQ:SpringAMQP Fanout Exchange(扇型交换机)

目录一、案例需求二、基础配置三、代码实现扇形交换机也叫做广播交换机&#xff0c;通过交换机将消息发送给所有的队列。 生产者源码 消费者源码 一、案例需求 在RabbitMQ控制台中&#xff0c;声明队列fanout.queue1和fanout.queue2。在RabbitMQ控制台中&#xff0c;声明交换…

深度解析DeepSeek V3.1 :6850 亿参数开源模型如何以 71.6% 编码得分、68 倍成本优势重构全球 AI 竞争格局

深度解析DeepSeek V3.1 &#xff1a;6850 亿参数开源模型如何以 71.6% 编码得分、68 倍成本优势重构全球 AI 竞争格局当DeepSeek悄然将其 6850 亿参数的 V3.1 模型上传至 Hugging Face 平台时&#xff0c;这个看似低调的举动却在全球 AI 领域投下了一颗 “深水炸弹”。这款融合…

Java 大视界 -- Java 大数据在智能安防视频监控系统中的视频内容理解与智能预警升级(401)

Java 大视界 -- Java 大数据在智能安防视频监控系统中的视频内容理解与智能预警升级&#xff08;401&#xff09;引言&#xff1a;正文&#xff1a;一、传统安防监控的 “三重困局”&#xff1a;看不全、看不懂、反应慢1.1 人工盯屏 “力不从心”1.1.1 摄像头密度与人力的矛盾1…

ansible playbook 实战案例roles | 实现基于node_exporter的节点部署

文章目录一、核心功能描述二、roles内容2.1 文件结构2.2 主配置文件2.3 tasks文件内容2.4 vars文件内容免费个人运维知识库&#xff0c;欢迎您的订阅&#xff1a;literator_ray.flowus.cn 一、核心功能描述 这个 Ansible Role 的核心功能是&#xff1a;​自动化部署 Prometheu…

.NET Core MongoDB 查询数据异常及解决

.NET Core 查询 MongoDB异常消息Element _class does not match any field or property of class WebApiServer.Model.Enity.Ypxxx.图中写的修改实际是查询分页出现的异常&#xff0c;异常是查询转换为List<T>时出现的&#xff1a; 这个错误通常发生在MongoDB文档中包含的…

政策技术双轮驱动智慧灯杆市场扩容,塔能科技破解行业痛点

在新型城市基础设施建设不断加速&#xff0c;以及“双碳”战略持续深化这样的双重背景之下&#xff0c;智慧灯杆市场恰恰迎来了政策红利得以释放、技术出现迭代突破并且需求在持续升级的极为难得的黄金发展时期。智慧城市建设 的核心承载从国家层面所开展的全域智能化改造规划&…

JetBrains Mono字体

好的,我们来详细解析一下 JetBrains Mono 的 8 种主要字体风格(实际上官方提供了 9 种字重,但通常我们讨论其核心风格)及其区别。 这些风格的区别主要体现在两个方面:字重 和 字形。 核心区别:字重 字重就是字体的粗细程度。JetBrains Mono 提供了从细到极粗的多种选择…

MySQL 分页查询:用 LIMIT 高效处理大量数据

MySQL 分页查询&#xff1a;用 LIMIT 高效处理大量数据 在实际开发中&#xff0c;当查询结果包含成百上千条记录时&#xff0c;一次性展示所有数据会导致加载缓慢、用户体验差。分页查询能将数据分段展示&#xff0c;既减轻服务器压力&#xff0c;又方便用户浏览。MySQL 中通过…

GraphQL 与 REST 在微服务架构中的对比与设计实践

GraphQL 与 REST 在微服务架构中的对比与设计实践 随着微服务架构的普及&#xff0c;API 设计已经成为系统性能、可维护性和开发效率的关键。REST&#xff08;Representational State Transfer&#xff09;作为传统的无状态架构风格&#xff0c;拥有简单、成熟的生态&#xff1…