SharedWorker 与 Worker 的区别

news/2025/11/19 18:08:14/文章来源:https://www.cnblogs.com/angdh/p/19243561

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>SharedWorker 与 Worker 的区别 - 单文件实现</title><style>* {box-sizing: border-box;margin: 0;padding: 0;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {background-color: #f5f7fa;color: #333;line-height: 1.6;padding: 20px;}.container {max-width: 1200px;margin: 0 auto;}header {text-align: center;margin-bottom: 40px;padding: 20px;background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);color: white;border-radius: 10px;box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);}h1 {font-size: 2.5rem;margin-bottom: 10px;}.subtitle {font-size: 1.2rem;opacity: 0.9;}.comparison {display: flex;flex-wrap: wrap;gap: 30px;margin-bottom: 40px;}.card {flex: 1;min-width: 300px;background: white;border-radius: 10px;padding: 25px;box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);transition: transform 0.3s ease;}.card:hover {transform: translateY(-5px);}.worker-card {border-top: 5px solid #ff6b6b;}.shared-worker-card {border-top: 5px solid #4cd97b;}.card h2 {display: flex;align-items: center;margin-bottom: 20px;font-size: 1.8rem;}.worker-card h2:before {content: "🔒";margin-right: 10px;}.shared-worker-card h2:before {content: "🔗";margin-right: 10px;}.feature-list {list-style-type: none;margin: 20px 0;}.feature-list li {padding: 10px 0;border-bottom: 1px solid #eee;display: flex;align-items: center;}.feature-list li:before {content: "✓";margin-right: 10px;font-weight: bold;}.worker-card .feature-list li:before {color: #ff6b6b;}.shared-worker-card .feature-list li:before {color: #4cd97b;}.demo-section {display: flex;flex-wrap: wrap;gap: 30px;margin-bottom: 40px;}.demo-panel {flex: 1;min-width: 300px;background: white;border-radius: 10px;padding: 25px;box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);}.demo-panel h3 {margin-bottom: 20px;font-size: 1.5rem;color: #444;}.demo-controls {display: flex;gap: 10px;margin-bottom: 20px;flex-wrap: wrap;}button {padding: 10px 15px;border: none;border-radius: 5px;cursor: pointer;font-weight: bold;transition: all 0.3s ease;}.worker-btn {background-color: #ff6b6b;color: white;}.worker-btn:hover {background-color: #ff5252;}.shared-worker-btn {background-color: #4cd97b;color: white;}.shared-worker-btn:hover {background-color: #38cc6c;}.output {background-color: #f8f9fa;border: 1px solid #e9ecef;border-radius: 5px;padding: 15px;min-height: 150px;max-height: 300px;overflow-y: auto;font-family: 'Courier New', monospace;font-size: 0.9rem;white-space: pre-wrap;}.status {margin-top: 10px;padding: 10px;border-radius: 5px;font-weight: bold;}.status.connected {background-color: #e8f5e9;color: #2e7d32;}.status.disconnected {background-color: #ffebee;color: #c62828;}.tab-info {background-color: #e3f2fd;border-left: 4px solid #2196f3;padding: 10px 15px;margin: 10px 0;border-radius: 0 5px 5px 0;}.technique-info {background-color: #fff3cd;border: 1px solid #ffeaa7;border-radius: 5px;padding: 15px;margin: 20px 0;}.code-example {background-color: #2d2d2d;color: #f8f8f2;border-radius: 5px;padding: 20px;margin-top: 30px;overflow-x: auto;}.code-example h3 {color: #f8f8f2;margin-bottom: 15px;}pre {white-space: pre-wrap;line-height: 1.5;}.highlight {color: #ff79c6;}.comment {color: #6272a4;}footer {text-align: center;padding: 20px;color: #666;font-size: 0.9rem;}@media (max-width: 768px) {.comparison, .demo-section {flex-direction: column;}.card, .demo-panel {min-width: 100%;}}</style>
</head>
<body><div class="container"><header><h1>SharedWorker 与 Worker 的区别 - 单文件实现</h1><p class="subtitle">使用Blob URL实现单文件SharedWorker演示</p></header><div class="technique-info"><h3>💡 技术实现说明</h3><p>此演示使用了一种技巧来实现单文件SharedWorker:</p><ul><li>使用<code>localStorage</code>在所有标签页间共享同一个Blob URL</li><li>第一个标签页创建Blob URL并保存到localStorage</li><li>后续标签页从localStorage读取并使用相同的Blob URL</li><li>这样所有标签页都会连接到同一个SharedWorker实例</li></ul></div><div class="tab-info"><strong>当前标签页ID: <span id="currentTabId">生成中...</span></strong><br><span>SharedWorker Blob URL: <span id="blobUrlInfo">未生成</span></span></div><div class="comparison"><div class="card worker-card"><h2>专用Worker (Dedicated Worker)</h2><p>专用Worker与创建它的脚本一对一关联,只能被创建它的页面访问。</p><ul class="feature-list"><li>与创建它的脚本一对一关联</li><li>生命周期与创建页面绑定</li><li>无法被其他页面或Worker访问</li><li>所有主流浏览器都支持</li><li>适用于单页面内的复杂计算任务</li></ul></div><div class="card shared-worker-card"><h2>共享Worker (SharedWorker)</h2><p>共享Worker可以被多个脚本共享,只要这些脚本与共享Worker同源。</p><ul class="feature-list"><li>可以被多个浏览器上下文(窗口、iframe等)共享</li><li>生命周期独立于创建它的页面</li><li>通过端口(port)与不同页面通信</li><li>浏览器支持相对较少</li><li>适用于多标签页应用的数据同步</li></ul></div></div><div class="demo-section"><div class="demo-panel"><h3>Worker 演示</h3><div class="demo-controls"><button class="worker-btn" id="startWorker">启动Worker</button><button class="worker-btn" id="sendToWorker">发送消息</button><button class="worker-btn" id="terminateWorker">终止Worker</button></div><div class="output" id="workerOutput">Worker输出将显示在这里...</div><div id="workerStatus" class="status disconnected">Worker状态: 未连接</div></div><div class="demo-panel"><h3>SharedWorker 演示(单文件实现)</h3><div class="demo-controls"><button class="shared-worker-btn" id="startSharedWorker">连接SharedWorker</button><button class="shared-worker-btn" id="sendToSharedWorker">发送消息</button><button class="shared-worker-btn" id="terminateSharedWorker">断开连接</button><button class="shared-worker-btn" id="newTab">在新标签页中打开</button><button class="shared-worker-btn" id="resetSharedWorker">重置SharedWorker</button></div><div class="output" id="sharedWorkerOutput">SharedWorker输出将显示在这里...</div><div id="sharedWorkerStatus" class="status disconnected">SharedWorker状态: 未连接 | 当前连接数: 0</div><p style="margin-top: 10px; font-size: 0.9rem; color: #666;">提示:打开多个标签页测试真正的SharedWorker共享功能</p></div></div><div class="code-example"><h3>单文件SharedWorker实现代码</h3><pre><code><span class="comment">// SharedWorker脚本内容(嵌入在HTML中)</span>
const sharedWorkerScript = `let connectionCount = 0;let ports = [];let messageCount = 0;self.onconnect = function(event) {const port = event.ports[0];connectionCount++;const clientId = 'client_' + Math.random().toString(36).substr(2, 9);port.clientId = clientId;ports.push(port);<span class="comment">// 欢迎新客户端</span>port.postMessage({type: 'welcome',clientId: clientId,connectionCount: connectionCount,message: '欢迎!你是第' + connectionCount + '个客户端'});<span class="comment">// 通知其他客户端</span>broadcastMessage({type: 'connection_update',connectionCount: connectionCount,message: '新客户端连接,当前共有' + connectionCount + '个连接'}, port);port.onmessage = function(event) {messageCount++;const message = event.data;<span class="comment">// 广播消息给所有客户端</span>broadcastMessage({type: 'client_message',clientId: clientId,messageId: messageCount,content: message,message: '客户端[' + clientId + '] 说: ' + message});};port.onclose = function() {const index = ports.indexOf(port);if (index > -1) {ports.splice(index, 1);connectionCount--;broadcastMessage({type: 'connection_update',connectionCount: connectionCount,message: '客户端断开,剩余' + connectionCount + '个连接'});}};port.start();};function broadcastMessage(message, excludePort = null) {ports.forEach(port => {if (port !== excludePort) {try {port.postMessage(message);} catch (e) {console.log('发送消息失败');}}});}
`;<span class="comment">// 创建Blob URL并共享给所有标签页</span>
const blob = new Blob([sharedWorkerScript], { type: 'application/javascript' });
const blobUrl = URL.createObjectURL(blob);<span class="comment">// 保存到localStorage供其他标签页使用</span>
localStorage.setItem('sharedWorkerBlobUrl', blobUrl);<span class="comment">// 创建SharedWorker</span>
const sharedWorker = new SharedWorker(blobUrl, 'demo-shared-worker');</code></pre></div><footer><p>© 2023 Web Workers 单文件演示 | 使用Blob URL技巧实现SharedWorker共享</p></footer></div><script>// 生成当前标签页的唯一IDconst tabId = 'tab_' + Math.random().toString(36).substr(2, 9);document.getElementById('currentTabId').textContent = tabId;// SharedWorker脚本内容const sharedWorkerScriptContent = `
let connectionCount = 0;
let ports = [];
let messageCount = 0;self.onconnect = function(event) {const port = event.ports[0];connectionCount++;const clientId = 'client_' + Math.random().toString(36).substr(2, 9);port.clientId = clientId;ports.push(port);console.log('新的SharedWorker连接,客户端ID:', clientId, '总连接数:', connectionCount);// 向新客户端发送欢迎消息port.postMessage({type: 'welcome',clientId: clientId,connectionCount: connectionCount,message: '欢迎连接到SharedWorker!你是第' + connectionCount + '个客户端'});// 向其他客户端广播连接更新broadcastMessage({type: 'connection_update',connectionCount: connectionCount,message: '系统: 新客户端连接,当前共有' + connectionCount + '个连接'}, port);// 处理客户端消息port.onmessage = function(event) {messageCount++;const message = event.data;console.log('收到来自客户端', clientId, '的消息:', message);// 广播消息给所有客户端broadcastMessage({type: 'client_message',clientId: clientId,messageId: messageCount,content: message,timestamp: new Date().toISOString(),message: '客户端[' + clientId + '] 说: ' + message});};// 处理连接关闭port.onclose = function() {const index = ports.indexOf(port);if (index > -1) {ports.splice(index, 1);connectionCount--;console.log('SharedWorker连接关闭,客户端ID:', clientId, '剩余连接数:', connectionCount);// 通知其他客户端broadcastMessage({type: 'connection_update',connectionCount: connectionCount,message: '系统: 客户端断开连接,剩余' + connectionCount + '个连接'});}};port.start();
};function broadcastMessage(message, excludePort = null) {const validPorts = ports.filter(port => port && port !== excludePort);validPorts.forEach(port => {try {port.postMessage(message);} catch (e) {console.log('向客户端发送消息失败,可能已断开连接');}});// 清理无效的端口引用ports = validPorts;
}`;// Worker 演示代码let worker;const workerOutput = document.getElementById('workerOutput');const workerStatus = document.getElementById('workerStatus');document.getElementById('startWorker').addEventListener('click', function() {if (worker) {workerOutput.textContent += '\nWorker已经存在,先终止旧Worker';worker.terminate();}const workerScript = `let messageCount = 0;self.onmessage = function(e) {messageCount++;const message = e.data;self.postMessage('Worker收到第' + messageCount + '条消息: ' + message + ' | 时间: ' + new Date().toLocaleTimeString());let result = 0;for (let i = 0; i < 10000000; i++) {result += Math.sqrt(i);}self.postMessage('计算完成! 结果: ' + result.toString().substring(0, 10) + '...');};`;const blob = new Blob([workerScript], { type: 'application/javascript' });const blobUrl = URL.createObjectURL(blob);worker = new Worker(blobUrl);worker.onmessage = function(e) {workerOutput.textContent += '\n' + e.data;workerOutput.scrollTop = workerOutput.scrollHeight;};workerOutput.textContent = 'Worker已启动! (标签页: ' + tabId + ')';workerStatus.textContent = 'Worker状态: 已连接';workerStatus.className = 'status connected';});document.getElementById('sendToWorker').addEventListener('click', function() {if (worker) {worker.postMessage('来自标签页 ' + tabId + ' 的消息 #' + Math.floor(Math.random() * 100));} else {workerOutput.textContent += '\n请先启动Worker!';}});document.getElementById('terminateWorker').addEventListener('click', function() {if (worker) {worker.terminate();worker = null;workerOutput.textContent += '\nWorker已终止!';workerStatus.textContent = 'Worker状态: 未连接';workerStatus.className = 'status disconnected';}});// SharedWorker 单文件实现let sharedWorker;let sharedWorkerBlobUrl;const sharedWorkerOutput = document.getElementById('sharedWorkerOutput');const sharedWorkerStatus = document.getElementById('sharedWorkerStatus');const blobUrlInfo = document.getElementById('blobUrlInfo');let sharedWorkerClientId = null;// 获取或创建共享的Blob URLfunction getSharedBlobUrl() {// 尝试从localStorage获取已存在的Blob URLconst existingBlobUrl = localStorage.getItem('sharedWorkerBlobUrl');if (existingBlobUrl) {console.log('使用现有的SharedWorker Blob URL');blobUrlInfo.textContent = existingBlobUrl.substring(0, 50) + '...';return existingBlobUrl;}// 创建新的Blob URLconsole.log('创建新的SharedWorker Blob URL');const blob = new Blob([sharedWorkerScriptContent], { type: 'application/javascript' });const newBlobUrl = URL.createObjectURL(blob);// 保存到localStorage供其他标签页使用localStorage.setItem('sharedWorkerBlobUrl', newBlobUrl);blobUrlInfo.textContent = newBlobUrl.substring(0, 50) + '...';return newBlobUrl;}document.getElementById('startSharedWorker').addEventListener('click', function() {if (sharedWorker) {sharedWorkerOutput.textContent += '\nSharedWorker已经连接';return;}try {// 获取共享的Blob URLsharedWorkerBlobUrl = getSharedBlobUrl();// 创建SharedWorker(使用相同的名称确保共享)sharedWorker = new SharedWorker(sharedWorkerBlobUrl, 'demo-shared-worker');sharedWorker.port.onmessage = function(event) {const data = event.data;switch (data.type) {case 'welcome':sharedWorkerClientId = data.clientId;sharedWorkerOutput.textContent = 'SharedWorker连接成功!\\n';sharedWorkerOutput.textContent += '客户端ID: ' + data.clientId + '\\n';sharedWorkerOutput.textContent += data.message;updateSharedWorkerStatus(true, data.connectionCount);break;case 'connection_update':sharedWorkerOutput.textContent += '\\n🔗 ' + data.message;updateSharedWorkerStatus(true, data.connectionCount);break;case 'client_message':if (data.clientId !== sharedWorkerClientId) {sharedWorkerOutput.textContent += '\\n📨 来自[' + data.clientId + ']: ' + data.content + ' | 时间: ' + new Date().toLocaleTimeString();}break;}sharedWorkerOutput.scrollTop = sharedWorkerOutput.scrollHeight;};sharedWorker.port.start();} catch (error) {sharedWorkerOutput.textContent = 'SharedWorker连接失败: ' + error.message;console.error('SharedWorker错误:', error);}});document.getElementById('sendToSharedWorker').addEventListener('click', function() {if (sharedWorker && sharedWorkerClientId) {const message = '来自标签页 ' + tabId + ' 的消息 #' + Math.floor(Math.random() * 100);sharedWorker.port.postMessage(message);sharedWorkerOutput.textContent += '\\n📤 我发送: ' + message;sharedWorkerOutput.scrollTop = sharedWorkerOutput.scrollHeight;} else {sharedWorkerOutput.textContent += '\\n请先连接SharedWorker!';}});document.getElementById('terminateSharedWorker').addEventListener('click', function() {if (sharedWorker) {sharedWorker.port.close();sharedWorker = null;sharedWorkerClientId = null;sharedWorkerOutput.textContent += '\\nSharedWorker连接已关闭!';updateSharedWorkerStatus(false, 0);}});document.getElementById('newTab').addEventListener('click', function() {window.open(window.location.href, '_blank');});document.getElementById('resetSharedWorker').addEventListener('click', function() {// 清理localStorage中的Blob URL,强制创建新的SharedWorkerlocalStorage.removeItem('sharedWorkerBlobUrl');if (sharedWorkerBlobUrl) {URL.revokeObjectURL(sharedWorkerBlobUrl);sharedWorkerBlobUrl = null;}if (sharedWorker) {sharedWorker.port.close();sharedWorker = null;}sharedWorkerClientId = null;sharedWorkerOutput.textContent = 'SharedWorker已重置,请重新连接';updateSharedWorkerStatus(false, 0);blobUrlInfo.textContent = '未生成';});function updateSharedWorkerStatus(connected, count) {if (connected) {sharedWorkerStatus.textContent = 'SharedWorker状态: 已连接 | 当前连接数: ' + count;sharedWorkerStatus.className = 'status connected';} else {sharedWorkerStatus.textContent = 'SharedWorker状态: 未连接 | 当前连接数: 0';sharedWorkerStatus.className = 'status disconnected';}}// 页面卸载时清理资源window.addEventListener('beforeunload', function() {if (worker) {worker.terminate();}if (sharedWorker) {sharedWorker.port.close();}});// 初始化:显示当前的Blob URL状态const existingBlobUrl = localStorage.getItem('sharedWorkerBlobUrl');if (existingBlobUrl) {blobUrlInfo.textContent = existingBlobUrl.substring(0, 50) + '...';}</script>
</body>
</html>

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

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

相关文章

2025年东营搬家公司服务力综合评估: 东营搬家公司电话/东营搬家搬厂/东营河口搬家/东营垦利搬家/专业能力与细分市场竞争力深度解析

随着东营城市化进程加快及居民跨区域流动需求上升,搬家服务市场呈现多元化发展趋势。从家庭日常搬迁到企业设备搬运,从区内短途运输到跨省长途物流,用户在选择搬家公司时面临诸多考量——如何判断企业服务专业性、如…

trae编译器前端agent提示词

你是资深 Vue 3 全栈开发专家,专注于现代前端架构设计、性能优化和组件化开发。精通 Vue 3 组合式 API、Pinia 状态管理、Vite 构建工具、TypeScript 应用和 Element Plus 组件库。前端为Andreas Hausberger的设计风格…

【19章】LLM开发工程师入行实战--从0到1开发轻量化私有大模型

【19章】LLM开发工程师入行实战--从0到1开发轻量化私有大模型 学习地址:……/s/1mnLPqFDyzOmQLgI4laU-PQ 提取码:1ih9 在人工智能浪潮席卷全球的今天,大型语言模型(LLM)已成为推动技术进步和产业变革的核心力量。…

块状链表

平衡树 constexpr int block=500,inf=2e9; struct BlockList{vector<vector<int>> b;void split(size_t idx){if(b[idx].size()>2*block){size_t mid=b[idx].size()/2;vector<int> temp;temp.ins…

常规链表建立

常规链表建立 列举常见的顺序表功能实现函数,进行编程练习常规顺序表(sequeue)建立定义一个顺序表的大小,结构体中采用数组而不是另一个堆内存空间表示存储的数据信息。 typedef int data_t; // 定义顺序表中数据元…

HDLBits网站学习——Procedures

Always block (combinational)由于数字电路由通过导线连接的逻辑门构成,任何电路都可以表示为模块和赋值语句的某种组合。但有时这并非描述电路最便捷的方式,过程块(always块是其中一种)提供了另一种电路描述语法。…

win11为什么我的不显示虚拟机平台选项

可能显示的是英文的 virtual machine platform 而不是中文的 虚拟机平台

2025 年最新http 代理服务商权威推荐排行榜:百万级 IP 资源 + 国际认证高可用率,爬虫 / 动态 / 高匿代理优选指南不限量 http 代理/独享 http 代理平台推荐

引言 在全球数字化浪潮下,大数据采集、跨境业务协同、网络安全防护等场景对 http 代理服务的依赖度持续攀升,市场规模年增速超 25%。然而行业资质参差不齐,部分服务商存在 IP 资源陈旧、匿名性不达标、稳定性不足等…

安装部署opengauss

背景: 项目需要,适配opengauss 环境准备 基础环境准备 准备一台4核8G的openEuler 22.03 (LTS-SP4)系统服务器1.关闭selinux setenforce 0 sed -i s/SELINUX=enforcing/SELINUX=disabled/g /etc/selinux/config2.关闭…

不只做语音,ElevenLabs 推出图像和视频生成平台;博通推出语音 AI 芯片,实现端侧 TTS 和实时翻译丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的技术」、「有亮点的产品」、「有思考的文章」、「有态…

海外直播源码选型指南:技术架构与合规性细节解析及成品多语言直播APP源码交付

除了海外客户对国际版多语言的直播APP咨询外,近期也接到了国内的软件服务商给自己客户开发的相关软件咨询。一般主要关注的就是价格和源码交付的细节,今天就来整体说明下我们海外国际版多语言直播语聊类APP成品源码的…

视频汇聚平台EasyCVR如何通过可视化管理与远程运维赋能安防“一张网”

在视频监控系统规模日益庞大的今天,无论是智慧城市、大型企业还是连锁门店,动辄成百上千路的摄像头管理已成为运维团队的巨大挑战,传统运维模式普遍面临:设备状态不透明:设备是否在线、运行是否健康,只能靠人工定…

单向循环链表接口设计

单向循环链表接口设计@file name: 单向循环链表接口设计 @brief :设计单向循环链表,实现各种功能函数并测试 @author m15629473867@163.com @date 2025/11/19 @version 1.0 @property @note CopyRight (c) 2025-2026…

2025 最新雕刻机源头厂家权威推荐榜:自主研发专利加持 + 国际测评认证,高精度设备优选清单数控雕刻机/激光雕刻机/小型雕刻机/金属雕刻机公司推荐

引言 在全球制造业向精密化、定制化转型的浪潮下,雕刻机作为核心加工装备,其性能表现直接影响生产效率与产品品质。当前市场品牌数量激增,技术水平参差不齐,部分产品存在精度波动大、适配场景有限、售后响应迟缓等…

linux firewall

在 Linux 系统中,防火墙(Firewall)主要用于控制网络流量,允许或拒绝特定的网络连接。常见的防火墙工具包括:1. iptables(传统方式) 这是 Linux 系统中最常用的防火墙工具,适用于大多数基于 iptables 的发行版(…

2025 年 11 月高温老化房厂家推荐排行榜,老化室、高温老化室、高温房、熟化房、固化房、恒温恒湿室、恒温房、恒温恒湿房公司推荐

2025 年 11 月高温老化房厂家推荐排行榜:老化室、高温老化室、高温房、熟化房、固化房、恒温恒湿室、恒温房、恒温恒湿房公司推荐 随着工业制造和科研测试领域的快速发展,高温老化房、老化室、高温老化室、高温房、熟…

2025 年 11 月耐磨钢板厂家推荐排行榜,高耐磨钢板,高锰耐磨钢板,焊达500耐磨钢板,进口复合耐磨钢板,双金属复合耐磨钢板公司推荐

2025年11月耐磨钢板厂家推荐排行榜:高耐磨钢板、高锰耐磨钢板、焊达500耐磨钢板、进口复合耐磨钢板、双金属复合耐磨钢板公司推荐 行业背景与发展现状 耐磨钢板作为工业领域的关键基础材料,其技术发展水平直接关系到…

wps如何快速交换列(调整列顺序),删除多个不连续的列

写表格的时候,最常见的两个小需求就是:把某两列换个位置,或者干脆删掉几列。其实这事儿不用折腾复杂功能,靠几招顺手的操作,几秒钟就能搞定。下面我把自己在 WPS 表格里常用的方法整理一下,能用鼠标的就用鼠标,…

2025 年 11 月耐磨板厂家推荐排行榜,国产耐磨板,悍达耐磨板,堆焊耐磨板,进口耐磨板,MN13耐磨板,NM360-NM600高强度耐磨板,高铬合金耐磨板公司推荐!

2025年11月耐磨板厂家推荐排行榜:专业指南助力工业设备升级 在工业生产领域,耐磨板作为关键材料,其性能直接影响设备使用寿命和运营效率。随着2025年工业技术标准的不断提升,各类耐磨材料在矿山机械、工程设备、物…

视频融合平台EasyCVR助力守护渔业牧区安全与增效

视频融合平台EasyCVR助力守护渔业牧区安全与增效在广袤的渔业水域和牧区草原,传统的安全管理方式正面临着巨大的挑战。地域广阔、环境复杂、人力监管成本高、风险响应滞后等问题,长期以来制约着农牧业的现代化发展。…