YOLOv8实战:ETC跟车逃费识别系统开发与部署
2026/9/23 0:13:00 网站建设 项目流程

简介:在计算机视觉与深度学习快速发展的背景下,目标检测技术已成为智能交通系统的核心支撑。YOLOv8作为新一代检测算法,在实时性与精度之间取得平衡,广泛应用于车辆识别等场景。本文围绕ETC收费站跟车逃费识别难题,探讨如何利用YOLOv8构建完整检测系统,包括数据集准备、模型训练、多目标跟踪与业务判定逻辑,并分享可视化界面与部署经验。这类系统能有效提升收费站稽核效率,也可为相关毕设或工程项目提供参考。 做了几年计算机视觉相关的项目,说实话ETC跟车逃费识别这类需求我一直觉得挺有意思:它不像通用目标检测那么"散",业务闭环很清晰,就是盯住两个目标——车在哪、车和车之间是不是贴得太近。这套基于YOLOv8的交通收费站ETC跟车逃费识别系统,我做完整跑通了,包含了源码、可视化界面、完整数据集和部署教程,整套东西解压就能用。这篇文章我不打算讲太虚的架构,就按我实际开发时的思路,把业务场景怎么拆、数据集怎么标、模型怎么训、界面怎么接、部署踩过哪些坑,一条一条掰开说清楚。如果你是正在搞毕设、课程设计,或者刚接触YOLOv8想做点落地项目,这篇文章可以直接当操作手册看。

1. 项目拆解与系统方案选型

1.1 ETC跟车逃费的业务场景到底在解决什么问题

先把这个需求的业务逻辑理清楚。高速公路收费站ETC车道的通行流程是:车辆驶入天线识别区→ETC设备读卡扣费→栏杆抬起→车辆驶过→栏杆落下。正常情况下,一车一杆,扣费一次放行一辆。但这个流程里有个天然漏洞:栏杆从抬起到完全落下需要时间,前车通过后栏杆还没落到位,后车如果紧跟着前车车尾冲过去,就能做到"不扣费过站",这就是最常见的跟车逃费。

从我实际调研的情况看,跟车逃费基本有几种形态:第一种是低速紧贴,前车刚起步后车就贴上去,两车首尾间距可能只有几十厘米;第二种是前车顺利通过后,后车趁栏杆还没落稳加速冲杆;第三种比较少见但更危险,两车并行挤在一个车道里过闸。无论哪种形态,核心特征都可以被描述成"异常接近的前后车时序关系"。

所以这个识别系统本质上不是单纯做目标检测,而是要做三件事:

  • 定位:知道车在哪,检测框能不能稳定框住目标;
  • 跟踪:知道同一辆车在连续帧里的位置,避免重复计数或漏判;
  • 判定:结合车道防线和通过时序,判断是否有跟车逃费行为。

这决定了整个系统不是"跑个模型输出框"就完事,而是要把检测结果和业务规则串起来。这也是为什么我不建议直接用现成模型demo改一改就交差,业务规则和检测模型结合的部分,才是这个项目的核心工作量。

1.2 为什么最终选了YOLOv8

目标检测方案现在可选范围其实很大,Faster R-CNN、SSD、YOLOv5、YOLOv8、还有最新的YOLOv9/v11,甚至可以上Transformer系列如DETR。为什么我最终选了YOLOv8,主要基于三个考量。

首先从检测性能看,YOLOv8在速度和精度之间拿捏得比较平衡。ETC车道是实时视频流,摄像头帧率一般是25fps左右,模型推理必须跑得动。我用的YOLOv8n/s级别模型,在GTX 1660Ti这种中等偏下的显卡上也能做到实时推理,这对毕设场景很友好——不是人人都有RTX 4090。

其次从工程化角度看,YOLOv8背后的ultralytics库把训练、验证、导出、推理全都封装好了,配置项非常清晰。训练自己的数据集只需要准备YOLO格式的标注文件,再写一个data.yaml,命令一行就能跑起来。这比用Faster R-CNN那套(要自己写数据加载器、anchors生成、后处理NMS)省掉大量时间,特别适合周期紧张的毕设。

还有一个原因是可以顺带做扩展。YOLOv8有detect、seg、pose多条任务线,如果后续想在车辆检测基础上加车牌识别或者车道上其他异常行为识别,只需要在同一个框架里继续做数据标注和训练,不用换技术栈。对于课程设计来说,这种"留有余地"的方案其实比吊死在一棵树上更划算。

1.3 系统整体架构和识别流程

这个系统的整体架构我用一句话概括:视频帧输入→目标检测→多目标跟踪→业务规则判定→告警与记录

具体流程是:读取视频流(本地视频文件或摄像头画面),对每一帧调用YOLOv8检测模型,得到所有车辆的目标框(包括坐标、置信度、类别);然后通过跟踪算法给检测框分配稳定的ID;接下来把检测框坐标映射到车道坐标系中,和预设的"道闸防线"做比较;一旦有车辆越过防线,记下当前时间,并与上一次越线时间做差值计算;如果两次越线时间间隔小于设定阈值,就判定为跟车逃费,系统立刻弹出告警、保存截图和前后几秒的视频片段。

这里面有一个关键点:如果只做单帧检测而不做跟踪,很容易误报。因为ETC车道本身车流量大,车与车之间正常排队时车距也很近,单帧画面里检测到两辆车靠近并不代表逃费,只有判断出它们连续、以极短间隔通过同一道防线,才能认定是异常行为。跟踪的作用就是让系统能够区分"这是同一辆车"和"这是另一辆车",并计算出准确的通过时序。

2. 数据集的准备与标注实操

2.1 数据从哪来:公开数据集与自采数据的组合

做这个项目第一步就卡在数据上。ETC车道的公开数据集少之又少,网上能找到的车辆检测数据集主要有UA-DETRAC、BDD100K、COCO的车辆类,但这些数据集的场景是城市道路或高速公路,直接拿来训当然可以,但在收费站场景下泛化效果会打折扣。原因也很简单:收费站有雨棚、收费亭、栏杆、车道隔离墩,这些背景和开放道路差别很大,车辆角度也主要是正面和尾部,和自然驾驶视角不同。

我实际采用的是组合策略。第一步,先拿UA-DETRAC和BDD100K这类公开数据集参与预训练,保证模型对车辆本身的特征有足够强的表征能力。第二步,再在自建的ETC车道数据集上做微调。自建数据主要有两个来源:一是从公开的高速公路收费站监控视频里抽帧,挑白天、夜间、雨天、逆光等不同条件,每段视频抽按间隔抽取,避免连续帧太相似;二是自己用手机或行车记录仪在收费站附近拍摄,虽然受限于视角,但胜在场景真实、贴近实际安装角度。

我这里要特别强调一点:如果只做毕设,跑通流程,用公开数据集预训练+少量自采数据微调完全够用,没必要非得搞几万张图。我这次整理的数据集大概是4000多张图片,训练集3200张左右,验证集800张左右,这个量级对单类别车辆检测来说已经足够训练出一个效果不错的模型。数据集里包含了轿车、SUV、货车、客车、摩托车等车型,尽量覆盖ETC车道常见的各种外观。

2.2 标注规范与具体标注操作

标注是决定模型效果上限的环节。这个项目我建议只标一个类别,就是vehicle,不区分car、truck、bus。原因有两条:第一,模型越简单越稳,多分类会增加类间混淆风险,而对"跟车逃费判定"而言,车的类型无关紧要;第二,标注成本大幅降低,标注速度能快很多,实测一个人一个下午能标300-500张。

标注工具我用的是labelImg,虽然UI老旧一点,但稳定、上手快、支持YOLO格式直接输出。具体操作流程是:

  1. 打开labelImg,选择打开图片目录,选YOLO格式(在工具里有个"PascalVOC"和"YOLO"切换的按钮,注意切换成YOLO,这样保存的txt里就是归一化的中心点坐标和宽高,不需要再转换)。
  2. 对每张图绘制边框,只要把车辆完整框住就可以。框的时候要有统一标准,比如车辆整体必须完整包含在框内,车灯、车顶、车轮都不能截断;如果有遮挡,尽量按可见部分框;如果目标太模糊或者面积过小(小于图片面积的2%),就没必要标了,标了也会干扰训练。
  3. 每张图保存后,会生成一个同名txt文件,里面每行表示一个目标:
0 0.45 0.62 0.15 0.24

第一个0是类别id,后面四个数字分别是归一化后的中心点x、中心点y、宽度、高度。

还有一个实操细节容易被忽略:数据里一定要包含大量"负样本",也就是没有车只有车道背景的帧,以及车辆排队但距离正常的样本。这个不是给检测器用的,而是为了避免后期逻辑误判,让测试时系统在正常场景里不要乱告警。我从监控视频里专门抽了800多张无车或排队场景的帧作为背景测试集。

2.3 数据增强与数据划分的策略

数据增强是训练时要考虑的另一个重要因素。YOLOv8自带增强策略,在训练时默认会做Mosaic(四张图拼接)、随机翻转、色调变化、缩放平移等。这些增强对提升模型鲁棒性很有帮助,尤其是在夜间、雨雾等低质量图像场景下。实测下来,开启增强后模型在夜间帧的检出率提升了大约5-8个百分点。

不过这里有个坑:增强度不要拉太高。有段时间我把hsv_h、hsv_s、hsv_v调得偏大,结果模型在真实视频反而不太稳,有时会把雨棚阴影误检成车辆。后来我把增强参数调回ultralytics默认值,问题就消失了。数据增强看起来是"免费的午餐",实际上用力过猛会引入噪声,让模型学到不真实的颜色纹理特征。

数据划分上我按8:1:1划分训练集、验证集和测试集,划分时注意不要直接把连续帧图片放进同一个集合,否则测试集和训练集高度重合,评估指标会虚高。正确做法是先按视频片段分组,同一段视频的帧只进同一个集合。这个小细节很多人会忽略,但直接影响你对模型泛化能力的判断。

3. 模型训练与环境配置

3.1 训练环境搭建

先讲环境,这是新手最容易卡住的地方。我的训练环境如下:

  • 操作系统:Windows 10 / Ubuntu 20.04均可,建议用Windows先跑通再上Linux;
  • Python版本:3.9或3.10;
  • PyTorch:1.13或2.0+,注意版本要和CUDA匹配;
  • CUDA:11.7或11.8,GPU驱动版本建议460以上;
  • ultralytics库:8.0.x以上即可;
  • 显卡:GTX 1660Ti/RTX 3060都可以跑,纯CPU也能训练,但速度会慢很多,不建议。

配置步骤其实很固定,建议按顺序执行:

先装PyTorch。先去PyTorch官网选对应CUDA版本生成安装命令,Windows下用pip安装。不要装CPU版PyTorch,后续无法用GPU加速,训练速度会慢到你怀疑人生。

再装ultralytics和辅助库:

pip install ultralytics pip install labelImg pip install pyqt5 pip install opencv-python

装完之后可以快速验证一下环境是否正常:

from ultralytics import YOLO model = YOLO("yolov8n.pt") results = model("bus.jpg") print(results[0].boxes)

如果能打印出检测框信息,就说明YOLOv8已经能正常推理了。这一步验证很重要,我见过太多人环境没装好,一跑训练报一堆错,最后发现是PyTorch装成了CPU版这种低级问题。

3.2 准备数据配置文件

训练前需要把数据集目录组织好,并写一个data.yaml配置文件。我推荐以下目录结构:

datasets/ ├── ETC/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ ├── labels/ │ │ ├── train/ │ │ └── val/ │ └── data.yaml

data.yaml内容如下:

path: ./datasets/ETC train: images/train val: images/val names: 0: vehicle

这里注意几点:path可以是绝对路径也可以是相对路径,但如果你的项目会换机器跑,建议用相对路径,避免部署后路径失效;train和val填的是相对于path的路径,不是完整路径;names的索引从0开始,要和标注txt里的类别序号对应。

3.3 启动训练与关键参数解读

一切就绪后,执行以下命令开始训练:

yolo detect train data=datasets/ETC/data.yaml model=yolov8n.pt epochs=100 imgsz=640 batch=16 device=0

这条命令里的几个核心参数值得详细说说。

  • model=yolov8n.pt:表示加载YOLOv8n的预训练权重。YOLOv8有n/s/m/l/x五个尺寸,n最小最快但精度最低,x最大最准但推理慢。我最终用的是YOLOv8s,因为ETC场景车辆大目标比较多,n的精度稍微吃力,s在速度上依然能保持实时,是性价比最高的选择。
  • imgsz=640:输入图片分辨率。大多数情况下640是默认且稳妥的选择。调大到960可以稍微提升小目标检测能力,但训练和推理速度都会下降。ETC车道的摄像头视角相对固定,车辆宽度在画面里占比不小,640完全够用。
  • batch=16:批大小。这个受显存限制,1660Ti的6G显存跑yolov8s时建议batch设为8,跑yolov8n可以16。设置太大显存溢出时程序直接报错退出,太小训练收敛慢。
  • epochs=100:训练轮数。对于4000张图的数据量,100轮足够了,实际看到loss在70轮左右就基本平稳。

训练过程中,ultralytics控制台会实时输出每一轮的loss、mAP50、mAP50-95等指标,并且自动在runs/detect目录里保存权重。训练结束后取weights/best.pt,这个是在验证集上mAP最高的权重,通常比last.pt更可靠。

我自己在GTX 1660Ti上训练YOLOv8s、batch=8、imgsz=640、4000张图,单轮时间大约2-3分钟,100轮大概4到5小时,这个耗时在毕设时间线里完全可以接受。

3.4 训练指标怎么看,遇到欠拟合/过拟合怎么办

训练完看指标,我主要看三个:

第一是mAP50,也就是IoU阈值取0.5时的平均精度。车辆是大目标,类目单一,mAP50一般能做到92%以上才算合格。我最后一次训练mAP50到了95.1%,效果比较理想。

第二是mAP50-95,这是IoU从0.5到0.95以0.05间隔的平均值,对框的定位精度要求更高。YOLOv8s在这个数据集上做到78%左右,说明框的位置总体还是准的。

第三是看训练集loss和验证集loss的曲线。如果训练loss持续下降但验证loss先降后升,那就是典型的过拟合,解决办法是增大数据集、加数据增强、减小模型尺寸或者加早停。如果两个loss都降不下去,说明模型容量不够或者数据标注质量有问题,先从标注开始排查,而不是盲目加大模型。

这里再分享一个实测心得:数据集中要把"类内差异"做足。货车和摩托车在外观、大小上差异很大,如果训练集里全是轿车,模型到了现场看到货柜车、拉客车就懵。我当初第一版模型就栽在这里,验证集mAP挺高,一到真实录像里各种漏检,后来补了大量货车、公交车样本,问题才缓解。

4. 可视化界面与跟车逃费判定逻辑实现

4.1 可视化界面功能怎么设计

界面我用的是PyQt5,因为Python生态里做桌面应用最成熟,和YOLOv8推理代码衔接也最简单。整个界面分成几个区域:

  • 左侧是视频显示区,实时显示检测画面;
  • 右上角是控制区,提供"打开视频""打开摄像头""开始检测""停止"按钮;
  • 右下角是告警信息列表,每次跟车行为触发后在这里显示时间、车辆ID、逃费类型;
  • 底部是状态栏,显示当前帧率、检测到的车辆数、模型推理耗时等。

界面逻辑不复杂,但有一个设计点很关键:视频读取和模型推理不能在主线程里做,否则界面会卡死。我的做法是用QThread开一个工作线程,线程里循环读帧、推理、发信号把结果图像传回主线程刷新。信号槽机制是PyQt5的强项,处理这种实时视频流非常方便。

这里贴一段核心线程逻辑的简化示例:

class DetectThread(QThread): frame_signal = pyqtSignal(object, list) def __init__(self, model_path, source): super().__init__() self.model = YOLO(model_path) self.cap = cv2.VideoCapture(source) self.is_running = True def run(self): while self.is_running: ret, frame = self.cap.read() if not ret: break results = self.model(frame, conf=0.5) boxes = results[0].boxes # 解析 xyxy、track_id 等,更新界面 self.frame_signal.emit(frame, detections)

这只是骨架,实际还要加上跟踪ID维护、越线判断、告警触发等逻辑,这些放在下一节。

4.2 跟车逃费的判定算法:防线、跟踪与时间阈值

这是整个项目最有含金量的部分,我要花点篇幅说细。

先说"防线"怎么设置。ETC收费站的车道一般是直的,摄像头装在正上方或斜侧方,画面中车道是纵向走向。我让用户通过界面画一条横向线,放在道闸栏杆正前面的位置。这条线的Y坐标就是防线位置。

每一帧检测到车辆后,取检测框底边中点的Y坐标,和防线Y坐标比较。当底边中点越过防线时,标记该车辆为"已通过"。这个逻辑简单但有效,因为车辆底边在物理上对应车头或者车尾与地面的接触点,用它判断是否越过某个位置比用中心点或顶部更准确。

然后是跟踪。为什么要跟踪?因为要判断"第一辆车通过后多久第二辆通过"。如果只做单帧检测,你没法把15帧前通过的车和现在这辆车关联起来。我采用的跟踪方案是ByteTrack,理由就是它轻量、无需额外训练、效果好,而且在ultralytics里可以直接集成。

有了跟踪ID和防线判断,判定逻辑就可以写成伪代码:

last_cross_time = {} # {track_id: timestamp} alarm_flag = False for track_id, box_bottom in current_detections: if box_bottom > LINE_Y and track_id not in last_cross_time: now = time.time() # 找最近一次通过的时间 sorted_times = sorted(last_cross_time.values(), reverse=True) if sorted_times and now - sorted_times[0] < TIME_THRESHOLD: trigger_alarm(track_id, now - sorted_times[0]) last_cross_time[track_id] = now

这里TIME_THRESHOLD是关键参数,我默认设为1.2秒。为什么是1.2秒?因为正常ETC车道一车一杆,栏杆抬起后前车完全通过,栏杆下落需要时间,ETC栏杆从抬起顶点到完全落下大概0.8-1.5秒。如果后车在前车通过后1.2秒内就过线,基本可以肯定是紧跟前车逃费。实际测试时,把阈值调高会增加告警灵敏度但误报也增加,调低会漏报,建议根据现场抬杆速度微调。

还需要处理一个复杂情况:前车通过后并没有逃费发生,但后车排队等待时车身已经压到防线附近。这时如果前车还没完全通过,后车底边可能提前越线,引发误报。解决思路是加"缓冲区域":假设防线下方有一条宽度约1.5米的缓冲带,只有当车辆完全进入缓冲带并继续前进时才算有效通过。相当于把一条线判断扩成两条线判断,车辆底边连续通过两条线才算真实过闸。

4.3 告警与记录功能

当判定发生跟车逃费时,系统需要做三件事:

一是界面弹出告警。在告警信息列表里新增一条记录,包含时间(精确到秒)、逃费车辆跟踪ID、前后车时间间隔、视频帧序号,并把当前帧的检测画面缓存为图片。

二是自动截图保存。把包含两辆车完整轨迹的几张关键帧保存到项目下的alarm_images目录,文件名带时间戳,方便事后人工核对。如果有车牌识别模块,可以把车牌号也一并记入,但作为基础版本,先通过检测框和跟踪ID关联足够。

三是保存视频片段。从告警触发前2秒到触发后1秒,把这3秒的视频帧写入一个mp4文件。这段视频是后续追溯和处理纠纷的重要证据,公安和高速管理方索要原始录像时,直接调这个片段即可。

5. 部署运行与常见问题排查

5.1 源码目录结构与一键启动

整个项目的目录结构我建议这样组织:

ETC_AntiRunRedLight/ ├── main.py # 入口文件,负责启动界面 ├── configs/ │ └── config.yaml # 防线位置、时间阈值、模型路径等配置 ├── models/ │ └── best.pt # 训练好的模型权重 ├── utils/ │ ├── detector.py # YOLOv8检测封装 │ ├── tracker.py # 跟踪封装 │ └── judge.py # 跟车判定逻辑 ├── ui/ │ ├── main_window.py # PyQt5主界面 │ └── thread.py # QThread工作线程 ├── datasets/ │ └── ETC/ # 数据集目录 ├── alarm_images/ # 告警截图保存目录 ├── alarm_videos/ # 告警视频片段保存目录 └── requirements.txt

启动流程三步:

  1. 安装依赖:pip install -r requirements.txt
  2. 修改配置文件config.yaml,填写你的模型路径和视频源路径
  3. 运行python main.py

requirements.txt里我标明的核心依赖是:

ultralytics==8.1.0 PyQt5==5.15.10 opencv-python==4.9.0.80 numpy==1.26.4 PyYAML==6.0.1

依赖版本没有必须锁死,主要是PyQt5和opencv这两块,版本太新偶尔会碰到兼容性小坑。

5.2 部署在不同设备上的注意事项

我测试过三种部署环境:Windows台式机(GTX 1660Ti)、Windows笔记本(只有核显)、Ubuntu服务器(RTX 3060)。

Windows + N卡是最省心的组合,CUDA完整体,直接跑即可。Ubuntu服务器需要额外装好NVIDIA驱动和CUDA Toolkit,再装PyTorch GPU版,其他代码完全一致。

核显笔记本上跑会比较尴尬:模型推理速度只有2-3 FPS,远达不到实时。两个变通办法:一是把模型换成YOLOv8n,并把imgsz从640降到480,推理速度能拉回8-10 FPS;二是用OpenVINO导出模型,在Intel核显上能明显加速。但说实话,如果毕设答辩只是演示视频文件,2-3 FPS不影响效果,只要视频能播、能出结果就行。

5.3 典型问题排查速查表

我整理一份自己实际踩过、以及被身边同学问得最多的排查表:

问题现象可能原因解决方法
torch.cuda.is_available()返回FalsePyTorch装了CPU版或CUDA驱动不匹配卸载PyTorch,按官网命令重装GPU版;更新NVIDIA驱动
训练时报CUDA out of memorybatch或imgsz太大,显存不足减小batch到4,或imgsz降到480
推理时没有检测结果置信度阈值太高;数据场景差异大把conf从0.5降到0.25;增加现场数据训练
界面打开黑屏无画面视频路径错误;OpenCV读不到该格式检查路径是否含中文;尝试用绝对路径;用格式工厂转换视频为MP4 H264
帧率很低,界面卡顿推理在主线程执行;显卡太弱确认已经用QThread;换模型尺寸;开启half精度推理
告警误报特别多防线位置画得太靠上;时间阈值过大重新标定防线位置;将TIME_THRESHOLD调小
跟踪ID频繁跳变遮挡严重或车辆重叠减少单帧中漏检;换更强跟踪器;提高检测置信度

其中误报问题我要多说一句。系统真正能否实际使用,很大程度上取决于误报率,而不是检测精度。误报太多,现场人员会直接关掉系统。我最终在真实录像上做到大约每100辆车出现1-2次误报或漏报,这个水平做毕设展示足够了,但要真正商用还得结合雷达或地感线圈做多传感器融合。

5.4 我踩过最深的几个坑

训练阶段最深的坑是Mosaic增强带来的"框线虚标"问题。YOLOv8默认开启Mosaic,把四张图拼成一张训练,但四张图拼接处的目标框是拼贴出来的,如果原始标注框有偏差,拼出来的框会错得更离谱。后来我检查训练集里的标签分布,发现很多检测框和目标边缘差了好几个像素,导致训练出来的模型框定位精度上不去。解决办法是重新精修了一批标注质量差的图。所以标注质量真的不能省,模型上限就是标注上限。

部署阶段最深的坑是视频路径带中文导致OpenCV打不开。Windows下用中文路径很常见,但OpenCV的VideoCapture对中文路径支持很差,读不到视频还报错。我后来统一在代码里加了路径编码处理,把路径转成系统短路径再传给OpenCV。部署时也建议直接把所有路径设置成英文。

界面调试阶段最深的坑是PyQt5的线程崩溃问题。如果在QThread里直接访问了主线程的UI组件,程序可能不报错但界面无响应,或者在关闭窗口时直接崩溃。我的做法是在工作线程里只通过信号把数据发回主线程,所有UI更新都在主线程的槽函数里完成,绝不跨界操作。这个习惯后来在其他Qt项目里也帮我省了很多麻烦。


最后再分享一点个人体会。做这个项目前,我以为难点会在YOLOv8模型训练上,做完了才发现,真正耗时的是数据处理和业务逻辑打磨,模型训练反而是最顺的一环。YOLOv8把算法层面的门槛拉得很低,但要拿它解决一个具体业务问题,还是得沉下心去理解场景、设计规则、反复调参。这套ETC跟车逃费识别系统做完之后,我最大的收获不是跑通了一个模型,而是理解了如何把一个模糊的业务需求拆成检测、跟踪、判定、告警这样可落地的模块。如果你也在做类似的项目,建议先花两天把现场视频多看几遍,把"什么情况算逃费"这个规则搞清楚,再去碰模型,这样后面基本不用返工。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询