当前位置: 首页 > news >正文

vue单据打印 一维码、二维码实现

  1. 编码规则与 JavaScript 代码实现
    编码规则数组:定义了 Code 128 条形码编码规则数组 BARS,其中每个数字对应一种条形码的线条组合模式。
const BARS = [212222,222122,222221,121223,121322,131222,122213,122312,132212,221213,221312,231212,112232,122132,122231,113222,123122,123221,223211,221132,221231,213212,223112,312131,311222,321122,321221,312212,322112,322211,212123,212321,232121,111323,131123,131321,112313,132113,132311,211313,231113,231311,112133,112331,132131,113123,113321,133121,313121,211331,231131,213113,213311,213131,311123,311321,331121,312113,312311,332111,314111,221411,431111,111224,111422,121124,121421,141122,141221,112214,112412,122114,122411,142112,142211,241211,221114,413111,241112,134111,111242,121142,121241,114212,124112,124211,411212,421112,421211,212141,214121,412121,111143,111341,131141,114113,114311,411113,411131,113141,114131,311141,411131,211412,211214,211232,23311120];

起始码与结束码常量:定义了起始码的基础值 START_BASE 和结束码值 STOP。

const START_BASE = 38;
const STOP = 106;

生成条形码 HTML 代码的函数:code128 函数根据输入的条形码内容和类型生成对应的 HTML 代码。如果未指定条形码类型,会自动检测。对于类型为 C 且长度为奇数的条形码内容,会在前面补 0。

function code128(code, barcodeType) {if (arguments.length < 2) {barcodeType = code128Detect(code);}if (barcodeType === 'C' && code.length % 2 === 1) {code = '0' + code;}const bars = parseBarcode(code, barcodeType);return bar2html(bars.join(''));
}

将条形码编码转换为 HTML 元素的函数:bar2html 函数将条形码编码数组转换为 HTML 元素字符串,每个编码对应一个包含线条和间隔样式的

元素。
javascript
function bar2html(s) {
const elements = [];
for (let pos = 0; pos < s.length; pos += 2) {
elements.push( <div class="bar${s.charAt(pos)} space${s.charAt(pos + 1)}"></div>);
}
return elements.join(‘’);
}
检测条形码类型的函数:code128Detect 函数根据输入的条形码内容检测其类型,纯数字为 C 型,包含小写字母为 B 型,其他为 A 型。

function code128Detect(code) {if (/^[0-9]+$/.test(code)) return 'C';if (/[a-z]/.test(code)) return 'B';return 'A';
}

解析条形码字符串的函数:parseBarcode 函数解析条形码字符串,根据条形码类型进行字符编码转换,并计算校验码。最后添加起始码、校验码和结束码到条形码编码数组。
javascript

function parseBarcode(barcode, barcodeType) {const bars = [];let check = 0;// 添加起始码bars.push(BARS[START_BASE + barcodeType.charCodeAt(0)]);for (let i = 0; i < barcode.length; i++) {let code;if (barcodeType === 'C') {code = +barcode.substr(i++, 2);} else {code = barcode.charCodeAt(i);}const converted = fromType[barcodeType](code);if (isNaN(converted) || converted < 0 || converted > 106) {throw new Error(`Unrecognized character (${code}) at position ${i} in code '${barcode}'.`);}check = bars.length === 0? converted : check + converted * bars.length;bars.push(BARS[converted]);}// 添加校验码和结束码bars.push(BARS[check % 103], BARS[STOP]);return bars;
}
字符编码转换函数对象:fromType 对象包含了不同条形码类型的字符编码转换函数。
javascript
const fromType = {A: function(charCode) {if (charCode >= 0 && charCode < 32) return charCode + 64;if (charCode >= 32 && charCode < 96) return charCode - 32;return charCode;},B: function(charCode) {if (charCode >= 32 && charCode < 128) return charCode - 32;return charCode;},C: function(charCode) {return charCode;}
};

将 code128 函数挂载到 window 对象:使 code128 函数在全局可用。

window.code128 = code128;
  1. HTML 与 CSS 样式
    HTML 结构:在 HTML 页面中,使用一个 div 元素(id=“barCodeDiv”)来显示生成的条形码。
    html
<div class="left marginleft"><div class="barcode2" id="barCodeDiv"></div>
</div>

同时,通过一个隐藏的 input 元素(id=“barCodeValue”)获取要生成条形码的内容。
html

CSS 样式:定义了用于显示条形码的样式类,包括线条的宽度和间隔的大小。
css

.barcode2 {float: left;clear: both;overflow: auto;height: 1in;
}
.barcode2 + * {clear: both;
}
.barcode2 div {float: left;height: 0.7in;
}
.barcode2.bar1 {border-left: 2px solid black;
}
.barcode2.bar2 {border-left: 4px solid black;
}
.barcode2.bar3 {border-left: 6px solid black;
}
.barcode2.bar4 {border-left: 8px solid black;
}
.barcode2.space0 {margin-right: 0;
}
.barcode2.space1 {margin-right: 2px;
}
.barcode2.space2 {margin-right: 4px;
}
.barcode2.space3 {margin-right: 6px;
}
.barcode2.space4 {margin-right: 8px;
}
.barcode2 label {clear: both;display: block;text-align: center;font: 0.250in/100% helvetica;
}
  1. 最终渲染
    通过以下 JavaScript 代码获取隐藏 input 元素中的值,并使用 code128 函数生成条形码 HTML 代码,插入到指定的 div 元素中。
const divElement = document.getElementById("barCodeDiv");
const v = document.getElementById("barCodeValue").value;
if (v) {divElement.innerHTML = code128(v, "B");
}

通过以上步骤,在 HTML 页面中实现了 Code 128 一维码的生成与显示。
html 删除其他无关代码,只保留一维码部分

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Code 128 Barcode</title><style type="text/css">.barcode2 {float: left;clear: both;overflow: auto;height: 1in;}.barcode2 + * {clear: both;}.barcode2 div {float: left;height: 0.7in;}.barcode2.bar1 {border-left: 2px solid black;}.barcode2.bar2 {border-left: 4px solid black;}.barcode2.bar3 {border-left: 6px solid black;}.barcode2.bar4 {border-left: 8px solid black;}.barcode2.space0 {margin-right: 0;}.barcode2.space1 {margin-right: 2px;}.barcode2.space2 {margin-right: 4px;}.barcode2.space3 {margin-right: 6px;}.barcode2.space4 {margin-right: 8px;}.barcode2 label {clear: both;display: block;text-align: center;font: 0.250in/100% helvetica;}</style>
</head><body><div class="left marginleft"><div class="barcode2" id="barCodeDiv"></div></div><input id="barCodeValue" type="hidden" value="SCMRMEGA1904128156"><script>(function () {// Code 128 条形码编码规则数组const BARS = [212222, 222122, 222221, 121223, 121322, 131222, 122213, 122312, 132212, 221213, 221312, 231212, 112232, 122132, 122231, 113222, 123122, 123221, 223211, 221132, 221231, 213212, 223112, 312131, 311222, 321122, 321221, 312212, 322112, 322211, 212123, 212321, 232121, 111323, 131123, 131321, 112313, 132113, 132311, 211313, 231113, 231311, 112133, 112331, 132131, 113123, 113321, 133121, 313121, 211331, 231131, 213113, 213311, 213131, 311123, 311321, 331121, 312113, 312311, 332111, 314111, 221411, 431111, 111224, 111422, 121124, 121421, 141122, 141221, 112214, 112412, 122114, 122411, 142112, 142211, 241211, 221114, 413111, 241112, 134111, 111242, 121142, 121241, 114212, 124112, 124211, 411212, 421112, 421211, 212141, 214121, 412121, 111143, 111341, 131141, 114113, 114311, 411113, 411131, 113141, 114131, 311141, 411131, 211412, 211214, 211232, 23311120];const START_BASE = 38;const STOP = 106;// 生成 Code 128 条形码 HTML 代码function code128(code, barcodeType) {if (arguments.length < 2) {barcodeType = code128Detect(code);}if (barcodeType === 'C' && code.length % 2 === 1) {code = '0' + code;}const bars = parseBarcode(code, barcodeType);return bar2html(bars.join(''));}// 将条形码编码转换为 HTML 元素function bar2html(s) {const elements = [];for (let pos = 0; pos < s.length; pos += 2) {elements.push(`<div class="bar${s.charAt(pos)} space${s.charAt(pos + 1)}"></div>`);}return elements.join('');}// 检测条形码类型function code128Detect(code) {if (/^[0 - 9]+$/.test(code)) return 'C';if (/[a - z]/.test(code)) return 'B';return 'A';}// 解析条形码字符串function parseBarcode(barcode, barcodeType) {const bars = [];let check = 0;// 添加起始码bars.push(BARS[START_BASE + barcodeType.charCodeAt(0)]);for (let i = 0; i < barcode.length; i++) {let code;if (barcodeType === 'C') {code = +barcode.substr(i++, 2);} else {code = barcode.charCodeAt(i);}const converted = fromType[barcodeType](code);if (isNaN(converted) || converted < 0 || converted > 106) {throw new Error(`Unrecognized character (${code}) at position ${i} in code '${barcode}'.`);}check = bars.length === 0? converted : check + converted * bars.length;bars.push(BARS[converted]);}// 添加校验码和结束码bars.push(BARS[check % 103], BARS[STOP]);return bars;}// 字符编码转换函数const fromType = {A: function (charCode) {if (charCode >= 0 && charCode < 32) return charCode + 64;if (charCode >= 32 && charCode < 96) return charCode - 32;return charCode;},B: function (charCode) {if (charCode >= 32 && charCode < 128) return charCode - 32;return charCode;},C: function (charCode) {return charCode;}};// 将 code128 函数挂载到 window 对象上window.code128 = code128;})();const divElement = document.getElementById("barCodeDiv");const v = document.getElementById("barCodeValue").value;if (v) {divElement.innerHTML = code128(v, "B");}</script>
</body></html>

vue打印代码

 let newOpen = window.open()newOpen.document.write(this.html)setTimeout(() => {newOpen.window.print()// 如果直接关窗口,弹警告if (newOpen.closed) {// 请勿直接关闭打印窗口alert(this.$t('MSG040005'))return}// 打印或取消,自动关闭新窗口newOpen.close()}, 100)
 document.body.innerHTML = this.htmlconsole.log(this.html)window.print()setTimeout(() => {window.location.reload()}, 100)

区别总结
窗口操作:第一段代码打开一个新的窗口进行打印,不会影响当前页面;第二段代码直接在当前页面进行打印,并在打印完成后重新加载页面。
页面内容处理:第一段代码将内容写入新窗口,不改变当前页面的内容;第二段代码直接替换当前页面的 body 内容。
用户体验:第一段代码提供了一个独立的打印窗口,用户可以在不影响当前页面的情况下进行打印操作;第二段代码会临时改变当前页面的内容,可能会给用户带来一些干扰。
综上所述,选择使用哪段代码取决于具体的需求和场景。如果需要独立的打印环境,避免影响当前页面,建议使用第一段代码;如果需要临时修改当前页面内容进行打印,并且希望打印完成后恢复页面状态,可以使用第二段代码。
如下是二维码的生成代码

<input id="barCodeValue" value="110000918" type="hidden" th:value="${runcardId}"/>
<script>// 生成第二个二维码var qrcodeDiv2 = document.getElementById("barCodeDiv");var v1 = document.getElementById("barCodeValue").value;if (v1!== '') {var qr = new QRCode(qrcodeDiv2, {text: v1,width: 130, // 设置二维码的宽度,可根据需要调整height: 130, // 设置二维码的高度,可根据需要调整});}
</script>
 <div class="barcode"style="height:150px;width: 150px" id="barCodeDiv"></div>
 #barCodeDiv {position: absolute;top: 0;right: 0;}.barcode {float: left;clear: both;padding: 0; /*quiet zone*/overflow: auto;/*height:0.5in;!*size*!*/}.barcode {float:left;clear:both;padding: 0; /*quiet zone*/overflow:auto;/*height:0.5in; !*size*!*/}.right { float:right; }.barcode + * { clear:both; }.barcode div {float:left;height: 0.35in; /*size*/}.barcode .bar1 { border-left:1px solid black; }.barcode .bar2 { border-left:2px solid black; }.barcode .bar3 { border-left:3px solid black; }.barcode .bar4 { border-left:4px solid black; }.barcode .space0 { margin-right:0 }.barcode .space1 { margin-right:1px }.barcode .space2 { margin-right:2px }.barcode .space3 { margin-right:3px }.barcode .space4 { margin-right:4px }.barcode label {clear:both;display:block;text-align:center;font: 0.125in/100% helvetica; /*size*/}
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>

相关文章:

vue单据打印 一维码、二维码实现

编码规则与 JavaScript 代码实现 编码规则数组&#xff1a;定义了 Code 128 条形码编码规则数组 BARS&#xff0c;其中每个数字对应一种条形码的线条组合模式。 const BARS [212222,222122,222221,121223,121322,131222,122213,122312,132212,221213,221312,231212,112232,12…...

远程控制macOS一直卡在100%,能连接上了却只显示了壁纸?

前言 前段时间有个朋友过来咨询关于Windows使用第三方远程软件&#xff08;向日葵、Todesk等&#xff09;远程连接控制macOS系统&#xff0c;但出现了一些奇奇怪怪的问题。 比如在连接的时候&#xff0c;一直卡在100%连接&#xff0c;对方的电脑却已经显示已经被控制的状态。…...

Spring Boot定时任务原理

Spring Boot定时任务原理 在现代应用中&#xff0c;定时任务的调度是实现周期性操作的关键机制。Spring Boot 提供了强大的定时任务支持&#xff0c;通过注解驱动的方式&#xff0c;开发者可以轻松地为方法添加定时任务功能。本文将深入探讨 Spring Boot 中定时任务的实现原理…...

C#初级教程(7)——初级期末检测

练习 1&#xff1a;计算圆的周长和面积 改编题目&#xff1a;编写一个 C# 程序&#xff0c;让用户输入圆的半径&#xff0c;然后计算并输出该圆的周长和面积&#xff0c;结果保留两位小数。 using System;class CircleCalculation {static void Main(){const double pi 3.14…...

原生稀疏注意力机制(NSA):硬件对齐且可原生训练的稀疏注意力机制-论文阅读

摘要 长上下文建模对于下一代语言模型至关重要&#xff0c;但标准注意力机制的高计算成本带来了巨大的计算挑战。稀疏注意力提供了一种在保持模型能力的同时提高效率的有前途的方向。本文提出了一种名为 NSA&#xff08;原生可训练稀疏注意力机制&#xff09; 的方法&#xff…...

Apache Struts RCE (CVE-2024-53677)

前言 对目前的Apache Struts RCE (CVE-2024-53677)的poc进行总结&#xff0c;由于只能单个ip验证&#xff0c;所以自己更改一下代码&#xff0c;实现&#xff1a;多线程读取url验证并保存&#xff0c;更改为中文解释 免责声明 请勿利用文章内的相关技术从事非法测试&#xf…...

GIS地图、轨道交通与智能驾驶UI设计:未来交通的智能化探索

随着科技的飞速发展&#xff0c;我们正迎来一个高度智能化的未来。在这个时代背景下&#xff0c;GIS&#xff08;地理信息系统&#xff09;、轨道交通以及智能驾驶UI设计正逐步成为推动交通行业变革的重要力量。本文将深入探讨这三者之间的内在联系及其在未来交通系统中的应用前…...

OpenResty

文章目录 OpenResty执行原理getting-started 核心模块: lua-nginx-module (ngx_lua)常用指令配置指令的执行顺序 API OpenResty 官方文档: http://openresty.org/ 官方文档完全不明所以, 除了getting-started完全不知道下一步该干啥 (都不知道ngx是什么它就开始用了), 找不到架…...

如何将公钥正确添加到服务器的 authorized_keys 文件中以实现免密码 SSH 登录

1. 下载密钥文件 2. RSA 解析 将 id_ed25519 类型的私钥转换为 RSA 类型&#xff0c;要将 ED25519 私钥转换为 RSA 私钥&#xff0c;需要重新生成一个新的 RSA 密钥对。 步骤&#xff1a; 生成新的 RSA 密钥对 使用 ssh-keygen 来生成一个新的 RSA 密钥对。比如&#xff0c;执…...

SQLMesh 系列教程7- 详解 seed 模型

SQLMesh 是一个强大的数据建模和管道管理工具&#xff0c;允许用户通过 SQL 语句定义数据模型并进行版本控制。Seed 模型是 SQLMesh 中的一种特殊模型&#xff0c;主要用于初始化和填充基础数据集。它通常包含静态数据&#xff0c;如参考数据和配置数据&#xff0c;旨在为后续的…...

Git常见命令--助力开发

git常见命令&#xff1a; 创建初始化仓库&#xff1a; git 将文件提交到暂存区 git add 文件名 将文件提交到工作区 git commit -m "注释&#xff08;例如这是发行的版本1&#xff09;" 文件名 查看状态 如果暂存区没有文件被提交显示&#xff1a; $ git status On…...

学习整理安装php的uuid扩展以及uuid调用方法

学习整理安装php的uuid扩展以及uuid调用方法 1、安装uuid依赖库2、下载并安装3、ini中添加扩展4、re2c版本报错5、uuid调用方法 1、安装uuid依赖库 yum -y install uuid uuid-devel e2fsprogs-devel libuuid-devel2、下载并安装 点我下载uuid安装包 wget http://pecl.php.ne…...

算法系列之贪心算法

在算法中&#xff0c;贪心算法&#xff08;Greedy Algorithm&#xff09;是一种常见的解决优化问题的算法。贪心算法的核心思想是&#xff1a;在每一步选择中都采取当前状态下最优的选择&#xff0c;即贪心的做出局部最优的决策&#xff0c;从而希望最终能够得到全局最优解。尽…...

将产品照片(form.productPhotos)转为 JSON 字符串发送给后端

文章目录 1. 前端 form.productPhotos 的当前处理a. 组件绑定b. 当前发送逻辑 2. 如何将 form.productPhotos 转为 JSON 字符串发送给后端a. 修改前端 save() 方法b. 确保 esave API 支持接收字符串 基于你提供的 identify-form.vue 代码&#xff0c;我将分析如何将产品照片&a…...

『大模型笔记』详细对比GraphRAG与传统RAG!

详细对比GraphRAG与传统RAG! 文章目录 详细对比GraphRAG与传统RAG!要点最终内容1. GraphRAG的作用与应用场景2. GraphRAG与传统RAG的对比3. GraphRAG的工作原理4. GraphRAG如何提高准确性和提供完整答案5. GraphRAG在开发和维护中的优势6. GraphRAG对生产环境的影响7. GraphR…...

安全面试3

文章目录 一个单位的一级域名可能不止一个&#xff0c;怎么收集某个单位的所有域名&#xff0c;注意不是子域名用转义字符防御时&#xff0c;如果遇到数据库的列名或是表名本身就带着特殊字符&#xff0c;应该怎么做宽字节注入原理防御宽字节注入的方法 基于黑白名单的修复&…...

软件测试:1、单元测试

1. 单元测试的基本概念 单元&#xff08;Unit&#xff09;&#xff1a;软件系统的基本组成单位&#xff0c;可以是函数、模块、方法或类。 单元测试&#xff08;Unit Testing&#xff09;&#xff1a;对软件单元进行的测试&#xff0c;验证代码的正确性、规范性、安全性和性能…...

球队训练信息管理系统设计与实现(代码+数据库+LW)

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装球队训练信息管理系统软件来发挥其高效地信息处理的作用&a…...

【Bluedroid】AVRCP 连接源码分析(二)

接着上一篇【Bluedroid】AVRCP 连接源码分析(一)-CSDN博客,继续AVRCP连接的源码分析。 getcapabilities_cmd packages/modules/Bluetooth/system/btif/src/btif_rc.cc /***************************************************************************** Function …...

OSS(对象存储服务)

OSS&#xff08;对象存储服务&#xff09; 是一种用于存储和管理非结构化数据的云存储服务&#xff0c;其核心设计面向海量数据的高扩展性、高可靠性和低成本存储。以下从定义、核心原理、架构特点和应用场景等方面详细介绍&#xff1a; 一、什么是OSS&#xff1f; OSS&#x…...

保研面试避坑指南:为什么我刷了两个月408和OJ,导师却只问我的大创项目?

保研面试的认知突围&#xff1a;为什么导师更关注你的项目而非专业课&#xff1f; 每年保研季&#xff0c;总有一批计算机专业的学生陷入同样的困境——他们刷遍了408四门专业课的习题集&#xff0c;在LeetCode上解决了上百道算法题&#xff0c;却在面试现场被导师连续追问一个…...

Rusted PackFile Manager:现代化架构重构与高性能游戏模组开发技术指南

Rusted PackFile Manager&#xff1a;现代化架构重构与高性能游戏模组开发技术指南 【免费下载链接】rpfm Rusted PackFile Manager (RPFM) is a... reimplementation in Rust and Qt5 of PackFile Manager (PFM), one of the best modding tools for Total War Games. 项目地…...

从Intel 600P到三星980 Pro:聊聊Linux内核里那些针对NVMe SSD的‘特殊照顾’(Quirks)

从Intel 600P到三星980 Pro&#xff1a;Linux内核如何为不同NVMe SSD定制电源管理方案 当你在Linux服务器上部署一块三星980 Pro NVMe SSD时&#xff0c;可能不会想到内核开发者早已为这块盘准备了特殊的"照顾"——就像对待一个需要特别关照的VIP客人。这种隐藏在驱动…...

告别手写报告!手把手教你用LIS系统搞定医院检验科全流程条码管理(附实战避坑点)

告别手写报告&#xff01;手把手教你用LIS系统搞定医院检验科全流程条码管理&#xff08;附实战避坑点&#xff09; 在三级医院检验科工作多年的张主任最近终于松了一口气——自从上线LIS系统的全流程条码管理功能后&#xff0c;科室的标本差错率从每月15例骤降到2例以内。这个…...

TMSpeech:如何在Windows上实现完全离线的实时语音转文字

TMSpeech&#xff1a;如何在Windows上实现完全离线的实时语音转文字 【免费下载链接】TMSpeech 腾讯会议摸鱼工具 项目地址: https://gitcode.com/gh_mirrors/tm/TMSpeech 你是否曾因会议记录手忙脚乱&#xff0c;或者在线课程笔记跟不上老师的语速&#xff1f;传统的语…...

XUnity.AutoTranslator完整指南:为Unity游戏开启实时翻译新时代

XUnity.AutoTranslator完整指南&#xff1a;为Unity游戏开启实时翻译新时代 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 想要畅玩日系游戏却苦于语言障碍&#xff1f;XUnity.AutoTranslator就是你的终…...

Windows PDF处理终极指南:零依赖的完整解决方案

Windows PDF处理终极指南&#xff1a;零依赖的完整解决方案 【免费下载链接】poppler-windows Download Poppler binaries packaged for Windows with dependencies 项目地址: https://gitcode.com/gh_mirrors/po/poppler-windows 还在为Windows系统上复杂的PDF处理工具…...

番茄小说下载器:三步解决你的离线阅读难题

番茄小说下载器&#xff1a;三步解决你的离线阅读难题 【免费下载链接】Tomato-Novel-Downloader 番茄小说下载器不精简版 项目地址: https://gitcode.com/gh_mirrors/to/Tomato-Novel-Downloader 还在为无法随时随地阅读番茄小说而烦恼吗&#xff1f;想要把心爱的小说保…...

1688 官方接口实用整理:常用接口清单 + 字段对照 + 可直接调试代码

下面全部按照1688 开放平台真实规范来写&#xff0c;内容偏实操、通俗易懂&#xff0c;没有花哨术语&#xff0c;拿到手就能对接项目用。一、1688 常用接口清单&#xff08;业务最常用&#xff09;主要分三类&#xff1a;商品基础信息、商品评论、店铺商品列表&#xff0c;基本…...

局域网概述

一、什么是局域网局域网&#xff08;LAN&#xff0c;Local Area Network&#xff09; 是指在较小地理范围内&#xff08;如一栋楼、一个校园、一家公司内部&#xff09;&#xff0c;将多台计算机、服务器、打印机等设备通过通信介质连接起来&#xff0c;实现资源共享和数据通信…...