2025年江西省职业院校技能大赛高职组"区块链技术应用"赛项赛卷(2卷)
文章目录
🔷博主介绍
致力于网络安全(漏洞挖掘、攻防实战)、Linux 内核系统(底层原理与性能调优)、区块链技术(Web3 安全与智能合约审计)、Python 语言应用(自动化攻防工具开发)、软件开发(全栈安全开发)等新一代信息技术领域的技术研究与干货分享,坚持以
极简篇幅承载硬核知识的创作理念,为技术爱好者提供高效、深度、可落地的阅读体验。CSDN认证网络安全领域优质创作者 、网络安全博客专家认证 、阿里云专家博主。
🌐各大技术专栏推荐
| 专栏名称 | 专栏介绍 |
|---|---|
| 网络安全攻防之道 | 为网络安全从业者、白帽黑客与技术爱好者打造的攻防知识阵地。深度剖析漏洞利用与防御的技术细节,实战演练渗透测试全流程,输出可落地的攻防策略,陪你在攻防对抗中持续进阶。 |
| Linux 系统运维:从底层原理到企业级实战 | 这里是 Linux 系统运维的实战修炼场:从系统初始化到高可用架构,从命令行魔术到自动化运维利器,深度拆解 CentOS/Ubuntu 在企业级业务、云原生环境中的运维密码。带你穿透系统底层逻辑,掌握性能调优、故障秒级定位、自动化脚本开发的硬核技能,进阶成为能扛住业务压力的 Linux 运维专家 |
| 【VulnHub 靶场攻防】从漏洞复现到实战渗透 | 不管你是刚入门的渗透新人,还是想强化实战能力的安全工程师,都能在这儿找到匹配的靶场练手项目。我们聚焦可复现的漏洞利用技巧,结合 Nmap、Metasploit、BurpSuite 等工具实战演示,帮你把靶场经验转化为真实渗透能力,一步步成长为能在实战中 "打怪升级" 的渗透高手 |
| 博主年度总结与收获 | 这里是旺仔 Sec 的创作成长日记!作为 CSDN 认证的网络安全优质创作者,我把每一年的技术深耕、创作思考、成长突破都浓缩在这儿 ------ 从漏洞分析的技术沉淀,到内容创作的经验复盘,再到从工程师到博主的身份进阶,每一篇总结都是 "技术探索 + 创作感悟" 的双料干货 |
背景描述 xx 市政府计划推出基于区块链+社会捐赠的社会应急物资捐赠平台,通过区块链的特性,链上+链下相结合的方式探索公益机构、捐赠方、物资运输方、受灾接收方以及监管者之间的具体运作。在此过程中,区块链智能合约的先天优势可倒逼管理业务流程再造,规避一些低效率的流转工作,提升物资捐赠过程相关参与方的协同效率。 在区块链+社会捐赠的社会应急物资捐赠平台,公益机构基于社会应急物资需求,在受灾接收方的委托下,发布公益项目需求筹集应急物资,捐赠方在捐赠平台中浏览公益项目发起捐赠物资,物资运输方协同运输,最后受灾接收方确认接收,在捐赠过程中,物资从捐赠发起登记捐赠信息、运输信息、接收信息均实现上链存证,保障应急物资捐赠高效、透明。

模块一:区块链产品方案设计及系统运维(35分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块一提交结果.docx】中对应的任务序号下。
任务1-1:区块链产品需求分析与方案设计(10分)
区块链社会应急物资捐赠平台涉及到捐赠方、公益机构、接收方等参与方,他们需要在区块链系统平台中完成基于不同业务场景下的功能操作,公益机构面向社会发布公益项目、捐赠方通过公益机构发布的公益项目进行捐赠、接收方确认接收应急物资等核心背景,完成需求分析与方案设计,具体要求如下:
1.依据给定的背景信息,对区块链社会应急物资捐赠平台需求进行分析,要求使用Y模型即需求场景、背后目标、产品功能进行分析;
2.依据给定的背景信息,对考题进行核心业务分析,使用Visio 工具编制系统业务流程图,包含公益机构面向社会发布公益项目的核心业务流程、捐赠方通过公益机构发布的公益项目进行捐赠的核心业务流程、接收方确认接收应急物资的核心业务流程;
3.依据给定的背景信息,对考题进行核心业务分析,使用Visio 工具编制系统业务用例图,包含公益机构面向社会发布公益项目的核心业务用例、捐赠方通过公益机构发布的公益项目进行捐赠的核心业务用例、接收方确认接收应急物资的核心业务用例、物流方接收委托进行上门取送物资/运输物资的核心业务流程、监管机构例行检查公益项目执行情况的核心业务流程;
4.结合背景信息,依据你对需求分析、核心业务的理解,使用 Visio 工具编制业务系统的功能结构图;
5.结合背景信息,依据你对需求分析、核心业务、功能结构的理解,使用表格编制用户业务系统、管理系统的功能清单,功能清单至少包含序号、功能列表、功能描述等在内的 3 项信息;
任务1-2:区块链系统部署与运维(15分)
围绕社会应急物资捐赠平台部署与运维需求,进行项目相关系统、节点以及管理工具的部署工作。通过监控工具完成对网络、节点服务的监控。最终利用业务需求规范,完成系统日志、网络参数、节点服务等系统结构的维护,具体要求如下:
1.根据参数与端口设置要求,部署区块链系统并验证;
2.根据参数与端口设置要求,部署区块链网络管理平台并验证;
3.基于区块链系统相关管理平台,按照任务指南实施系统运维工作并验证;
4.基于区块链系统相关监管工具,按照任务指南对区块链系统进行监管。
子任务1-2-1: 搭建区块链系统并验证
基于给定服务器环境以及软件(地址"/root/tools"),搭建如下图所示的双机、三机构(学生、院校、用人单位)、二群组、七节点的星形组网拓扑区块链系统。其中,二群组名称分别为group1、group2,三个机构名称为agencyA、agencyB、agencyC。p2p_port、channel_port、jsonrpc_port起始端口分别为30330、20230、8545,确保搭建的区块链系统能正常运行。

具体工作内容如下:
(1)采用默认配置分别搭建双主机区块链网络;
(2)通过命令分别在M1-A和M1-B上验证区块链节点进程运行状况;
(3)通过命令分别在M1-A和M1-B上验证区块链连接状态和共识状态日志输出。
子任务1-2-2:搭建区块链系统管理平台并验证
基于给定服务器环境以及软件(地址"/root/tools"),搭建区块链控制台并开展相关运维工作,具体工作内容如下:
(1)在M1-A主机上面配置控制台,修改配置信息,使用Console连接agencyB中节点,部署HelloWorld.sol智能合约;
(3)使用控制台完成 HelloWorld.sol智能合约中的 set 与get 方法操作;
(3)使用机器M1-A控制台检查区块链中的当前区块高度以及查看部署合约的交易详情。
子任务1-2-3:区块链节点运维
基于已完成的区块链系统与管理平台搭建工作,开展区块链节点的加入与退出运维工作,具体内容如下:
(1)基于服务器中的扩容工具,在机器(M1-B)上进行新节点(Node7)扩容并加入群组Group1;
(2)使用机器(M1-B)检查扩容完成的区块链节点(Node7)的连接状况以
及新节点在群组(Group1)中的共识状态;
(3)修改配置文件,指定node3输出等级为警告级,并设置日志存储阈值
位50MB。
子任务1-2-4:区块链网络运维
根据任务描述要求,完成网络配置与管理运维操作,具体内容如下:
(1)设置区块链系统黑名单,修改M1-B的node7配置将node3设为黑名单,并通过命令检查;
(2)在M1-A上将区块链网络中群组2的最大交易数量设为3000;
(3)在M1-A上通过控制台检查群组2的区块最大打包交易数量。
任务1-3:区块链系统测试(10分)
设计对区块链系统的测试流程;结合实际业务需求,调用部署的智能合约进行系统测试、性能测试等;根据业务需求,分析并且修复给定智能合约中的安全漏洞。利用模拟业务和测试工具来完成对区块链系统服务数据的测试。
子任务1-3-1:系统测试
在M1-A登录linux服务器,进入指定操作目录(/root/tools)中完成区块链节点管理器的配置部署,并进行节点接口测试,具体操作任务如下:
(1)进入WeBASE-Node-Manager目录,完成数据库初始化操作;
(2)修改application.yml配置文件,进行WeBASE-Node-Manager的服务配置,包括数据库名称,数据库用户,数据库密码等;
(3)使用命令启动WeBASE-Node-Manager管理平台服务,并检查节点管理是否正常启动;
(4)进行节点管理服务的 API 接口测试。
子任务1-3-2:压力测试
参照工程项目(地址:"/root/projects")使用Caliper测试工具对
使用Caliper测试工具对HelloWorld.sol中set和get功能进行压力测试,具体操作任务如下:
修改testnw/fisco-bcos.json文件,同时指定测试HelloWorld.sol合约文件配置;
(1)配置进行压测的js信息;
(3)提供set功能核心测试代码;
(4)提供get功能核心测试代码;
(5)设置txNumber=100,tps=1,所有测试通过率为100%。
模块二:智能合约开发与测试(30分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块二提交结果.docx】中对应的任务序号下。
任务2-1:智能合约设计(5分)
根据区块链社会应急物资捐赠平台应用需求分析和方案设计文档的描述,编写该区块链产品的智能合约功能需求文档,以及设计该智能合约UML图。具体要求如下:
1.根据区块链社会应急物资捐赠平台产品项目背景和需求分析,编写该区块链社会应急物资捐赠的智能合约相关功能需求;
2.完成区块链社会应急物资捐赠智能合约的时序图;
设计区块链社会应急物资捐赠智能合约接口,画出区块社会应急物资捐赠智能合约的时序图。
任务2-2:智能合约开发(20分)
使用 Solidity 语言进行智能合约开发,根据需求功能介绍在待补充源码中
完成程序接口功能的编码,解决代码错误和警告,正确编译合约,功能调试正确,
并正确进行相关业务功能的验证,具体要求如下:
子任务 2-2-1:公益项目的接口编码
根据需求功能介绍在待补充源码中完成受赠方接口的编码,解决代码错误和警告,正确编译合约,功能调试正确。
(1)编写发布公益项目上链接口,代码截图保存;
java
function addPublicWelfare(string cardId,string _fields) public returns(int8 code) {
string memory localDateTime =选手填写部分;
string[] memory filedList = 选手填写部分;
require(filedList.length == 8,"This array is the wrong length!");
int8 getStatus;
(getStatus, )=selectOneRecordByCondToJson(选手填写部分);
require(getStatus==FAIL_NULL_RETURN,"id already exists");
string memory fieldsOne = string(选手填写部分);
code = 选手填写部分
emit addPublicWelfareEvent(code, fieldsOne);
require(code == 1,"insert Failed!");
}
(2)编写审批公益项目上链接口,代码截图保存。
java
function updatePublicWelfareStatus(string cardId,string _fields) public returns(int8 code) {
string[] memory filedList =选手填写部分;
require(选手填写部分,"This array is the wrong length!");
(int queryCode,string[] memory PublicWelfareMessage) = 选手填写部分;
require(queryCode == 1,"PublicWelfare is not found");
string memory fileds = getChangeFieldsString(PublicWelfareMessage, 9, filedList[1]);
code = 选手填写部分;
}
子任务 2-2-2:物流管理的接口编码
根据需求功能介绍在待补充源码中完成物流管理的编码,解决代码错误和警告,正确编译合约,功能调试正确。
(1)编写添加物流信息上链的接口,代码截图保存;
java
function addLogistics(string cardId,string _fields) public returns(int8) {
string[] memory filedList =选手填写部分;
require(filedList.length == 6,"This array is the wrong length!");
string memory localDateTime = 选手填写部分;
string memory filedsone = string(选手填写部分);
int8 code = insertOneRecord(选手填写部分);
require(选手填写部分,"insert Failed!");
emit 选手填写部分(code, filedsone);
return code;
}
(2)编写修改物流信息上链的接口,代码截图保存;
java
function updateLogisticsStatus(string cardId,string _fields) public returns(int8 code) {
string[] memory filedList = 选手填写部分;
require(选手填写部分,"This array is the wrong length!");
(int queryCode,string[] memory LogisticsMessage) = selectOneRecordToArray(选手填写部分);
require(选手填写部分,"PublicWelfare is not found");
string memory fileds = getChangeFieldsString(选手填写部分);
code = 选手填写部分(tb_logistics, cardId, fileds,["id",filedList[0]]);
}
任务2-3:智能合约测试(5分)
子任务 2-3-1:基于 Web 前置平台的合约测试
1.解决代码错误和警告,正确编译并部署合约,成功获取部署的合约地址和abi;
- 调用区块链社会应急物资捐赠智能合约的接口,完整验证业务流程;
子任务 2-3-2:智能合约安全漏洞测试。
有如下问题智能合约:
合约一:
bash
pragma solidity ^0.8.11;
contract WETH9 {
string public name = "Wrapped Ether";
string public symbol = "WETH";
uint8 public decimals = 18;
event Approval(address indexed src, address indexed guy, uint wad);
event Transfer(address indexed src, address indexed dst, uint wad);
event Deposit(address indexed dst, uint wad);
event Withdrawal(address indexed src, uint wad);
mapping (address => uint) public balanceOf;
mapping (address => mapping (address => uint)) public allowance;
fallback() external { deposit(); }
function deposit() public payable {
balanceOf[msg.sender] += msg.value;
}
function withdraw(uint wad) public {
require(balanceOf[msg.sender] >= wad);
balanceOf[msg.sender] -= wad;
payable(msg.sender).transfer(wad);
}
function totalSupply() public view returns (uint) {
return address(this).balance;
}
function approve(address guy, uint wad) public returns (bool) {
allowance[msg.sender][guy] = wad;
return true;
}
function transfer(address dst, uint wad) public returns (bool) {
return transferFrom(msg.sender, dst, wad);
}
function transferFrom(address src, address dst, uint wad)
public
returns (bool)
{
require(balanceOf[src] >= wad);
if (src != msg.sender && allowance[src][msg.sender] !=type(uint256).max) {
require(allowance[src][msg.sender] >= wad);
allowance[src][msg.sender] -= wad;
}
balanceOf[src] -= wad;
balanceOf[dst] += wad;
return true;
}
}
合约二:
bash
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.11;
import "./WETH9.sol";
interface ERC20 {
function transferFrom(address, address, uint) external;
function transfer(address, uint) external;
function balanceOf(address) external view returns (uint);
function permit(address,address,uint256,uint,uint,bytes32,bytes32) external;
function approve(address,address) external;
}
contract Vault{
constructor() {
}
function deposit(address token,uint256 amount) external{
ERC20(token).transferFrom(msg.sender,address(this),amount);
}
function depositwithPermit(address token,address target,uint256 vaule,uint deadline,uint v,bytes32 r, bytes32 s)external {
ERC20(token).permit(target,address(this),vaule,deadline,v,r,s);
ERC20(token).transferFrom(target,address(this),vaule);
}
}
contract Setup {
WETH9 public weth9;
Vault public vault;
constructor() payable {
uint256 amount = msg.value;
weth9 = new WETH9();
weth9.deposit{value: amount}();
vault = new Vault();
weth9.approve(address(vault),type(uint256).max);
vault.deposit(address(weth9),amount/2);
}
function withdraw(address token,address target,uint256 vaule,uint deadline,uint v,bytes32 r, bytes32 s) external {
vault.depositwithPermit(token, target, vaule, deadline, v, r, s);
}
function isSolved() external view returns (bool) {
uint256 balance = weth9.balanceOf(address(this));
return balance == 0;
}
}
(1)分析以上智能合约中存在的漏洞,并说明其可能造成的危害;
(2)编写测试用例,复现智能合约中存在的漏洞;
(3)创建修复后的智能合约,命名为setupRepair.sol,并编写测试用例修复结果,并说明修复内容。
模块三:区块链应用系统开发(30分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块三提交结果.docx】中对应的任务序号下。
任务3-1:区块链应用前端功能开发(10分)
任务 3-1-1:公益项目管理接口
使用Vue调用公益项目管理接口,将获取的需求详情、需求说明、需求数量等信息传递给前端模板,要求如下:
(1)在 Demand.vue 文件中完成功能并按照公益项目管理原型图的长度、宽度、行高、间距、文字样式、颜色等,完成公益项目管理页面的开发,将 Web 页面和代码截图保存;
html
<el-row style="text-align: left">
<el-button v-if="选手填写部分" type="primary" @click="dialogVisible = true"
>添加需求</el-button
>
</el-row>
<el-row>
<el-col :span="23">
<el-table :data="demandList" style="width: 100%" fixed-header>
<el-table-column
prop="选手填写部分"
label="ID"
min-width="30%"
></el-table-column>
<el-table-column
prop="选手填写部分"
label="需求详情"
min-width="50%"
></el-table-column>
<el-table-column
prop="选手填写部分"
label="需求说明"
min-width="50%"
></el-table-column>
<el-table-column
prop="选手填写部分"
label="需求数量"
min-width="50%"
></el-table-column>
<el-table-column
prop="选手填写部分"
label="发布时间"
min-width="50%"
></el-table-column>
<el-table-column
label="状态"
min-width="50%"
>
<template slot-scope="scope">
<span v-if="选手填写部分" style="margin-left: 10px">未完成</span>
<span v-if="选手填写部分" style="margin-left: 10px">已受理</span>
<span v-if="选手填写部分" style="margin-left: 10px">已完成</span>
</template>
</el-table-column>
<el-table-column v-if="选手填写部分" label="操作" min-width="50%">
<template slot-scope="scope">
<el-button
size="mini"
type="primary"
@click="选手填写部分"
>申请项目</el-button
>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
(2)完成 Vue 调用公益项目管理接口 API,获取接口返回的需求详情、需求说明、需求数量等信息,填充至 Vue 页面中,完成添加需求功能接口,添加成功后刷新页面,将 Web页面和代码截图保存。
html
query: function () {
this.axios.get(选手填写部分).then((response) => {
if (选手填写部分) {
this.demandList = 选手填写部分;
} else {
this.$message({
showClose: true,
message: `请求内容有误, ${response.data.msg}`,
type: "error",
});
}
});
},
任务 3-1-2:物流管理接口
使用Vue调用物流管理接口,将获取的捐赠方、受捐方、公益机构、项目名称、物流状态等信息传递给前端模板,要求如下:
(1)在 LogisticsInformation.vue 文件中完成功能并按照物流管理原型图的长度、宽度、行高、间距、文字样式、颜色等,完成物流管理页面的开发,将 Web 页面和代码截图保存;
html
<el-row>
<el-col :span="23" :offset="1" style="text-align: left">
<el-table :data="logisticsList" class="content" stripe>
<el-table-column
prop="选手填写部分"
label="ID"
min-width="50%"
></el-table-column>
<el-table-column
prop="选手填写部分"
label="捐赠方"
min-width="50%"
></el-table-column>
<el-table-column
prop="选手填写部分"
label="受捐方"
min-width="50%"
></el-table-column>
<el-table-column
prop="选手填写部分"
label="公益机构"
min-width="50%"
></el-table-column>
<el-table-column
prop="选手填写部分"
label="项目名称"
min-width="50%"
></el-table-column>
<el-table-column
prop="选手填写部分"
label="捐赠详情"
min-width="50%"
></el-table-column>
<el-table-column
prop="选手填写部分"
label="创建时间"
min-width="50%"
></el-table-column>
<el-table-column
prop="选手填写部分"
label="物流状态"
min-width="50%"
>
<template slot-scope="scope">
<span v-if="选手填写部分" style="margin-left: 10px">已取货</span>
<span v-if="选手填写部分" style="margin-left: 10px">运输</span>
<span v-if="选手填写部分" style="margin-left: 10px">已完成</span>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button
v-if="选手填写部分"
size="mini"
type="primary"
@click="选手填写部分"
>下一步</el-button
>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
(2)完成 Vue 调用课程管理接口 API,获取接口返回的捐赠方、受捐方、公益机构、项目名称、物流状态等信息,填充至 Vue 页面中,完成状态更新功能接口,将 Web页面和代码截图保存。
html
confirm(from){
if(from.status=="3"){
选手填写部分
}
let postData =选手填写部分;
postData.status=选手填写部分;
this.axios
.put(选手填写部分, postData)
.then((response) => {
if (选手填写部分) {
this.$message({
showClose: true,
message: "修改成功!",
type: "success"
});
this.projects=选手填写部分
选手填写部分
} else {
this.$message({
showClose: true,
message: `请求内容有误, ${response.data.message}`,
type: "error",
});
}
});
}
任务3-2:区块链应用后端功能开发(20分)
在区块链社会应急物资捐赠后端开发中,使用 Java 完成在区块链中实现捐赠方、物流方、受赠方、监管机构项目的管理,完善MySql 数据库表结构创建,完善后端中注册角色接口,发布需求、申请项目等功能,与前端页面交互,形成完整的区块链社会应急物资捐赠系统。
任务 3-2-1:区块链社会应急物资捐赠数据库设计
(1)根据提供的区块链社会应急物资捐赠数据库脚本文件,完善数据库的创建表语句,截图保存;
(2)打开mysql数据库客户端,并连接数据库,创建donationEmergency数据库,并执行第1步补全的sql脚本,将运行过程截图保存。
任务3-2-2:编写调用公益项目管理接口
使用 Java 语言完成 addDemand接口,完成需求的发布接口,通过 fisco sdk与公益项目管理接口进行交互,并将发布结果标识信息传递给前端模板,要求如下:
(1)接收 Web 端传递的对应实体类参数;
(2)调用service业务层,执行发布需求操作,将发布结果传递给前端页面;
(3)将获取到的课程信息进行解析,并通过数据库依赖包(mysql-connector-java-bin.jar)存储到数据库中;
(4)使 用 postman测 试 功 能 完 整 性 , 测 试 参 数 和 结 果 截 图,addDemand接口部分代码截图。
java
@ApiOperation(value = "添加需求",notes = "添加需求")
@ApiImplicitParam(name = "DemandBean",value = "需求bean",required = true,dataType = "DemandBean")
@PostMapping("/选手填写部分")
public AjaxResult<String> addDemand(选手填写部分 DemandBean demandBean, HttpServletRequest request) {
String token = request.getHeader("Authorization");
String username = TokenUtil.选手填写部分;
RegisterBean registerBean = userService.getUser(username);
选手填写部分
if (donationService.选手填写部分) {
return new AjaxResult<String>(200,"ok");
} else {
return new AjaxResult<String>(404,"fail");
}
}
任务3-2-3:编写调用物流管理接口
使用 Java 语言完成addLogistics 接口调用智能合约,完成物流创建接口,通过 fisco sdk与物流管理接口进行交互,并将学分上链信息传递给前端模板,要求如下:
(1)接收 Web 端传递的对应实体类参数;
(2)调用service业务层,执行物流上链操作,将创建结果传递给前端页面;
(3)信息上链之后,将获取到的发放信息进行解析,并通过数据库依赖包(mysql-connector-java-bin.jar)存储到数据库中;
(4)使 用 swagger-ui测 试 功 能 完 整 性 , 测 试 参 数 和 结 果 截 图,addLogistics 接口部分代码截图。
java
@ApiOperation(value = "添加物流信息",notes = "添加物流信息")
@PostMapping("/addLogistics")
public AjaxResult<String> addLogistics(选手填写部分){
String token = request.getHeader("Authorization");
String username = TokenUtil.选手填写部分
RegisterBean registerBean = userService.getUser(username);
选手填写部分
if(donationService选手填写部分){
return new AjaxResult<String>(200,"ok");
} else {
return new AjaxResult<String>(404,"fail");
}
}
职业素养(5分)
1.具有良好的文档写作能力,代码编写规范
2.具有团队合作精神和创新意识
区块链技能大赛参考答案链接
🤵♂️ 个人博客主页: @旺仔Sec的博客主页
WeChat公众号:鹏璃安全✍🏻 博主身份:网络安全兼技能大赛工程师(NISP、CISP、华为IE、IP、redhat、软考等职业证书报考可找我报考!)
🐋 希望大家多多支持,我们一起进步!😄
如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏 📂加关注(各大技能大赛参考答案链接如下)
🖥️:软件测试技能大赛参考答案