尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
水果识别系统毕设实战:四大模型微调与Web部署全流程
简介本资源是一套完整的Python高分毕业设计项目面向计算机、人工智能、电子信息等专业本科生及深度学习初学者聚焦水果图像智能识别这一典型CV任务。项目基于VGG16、ResNet50、MobileNetV2和DenseNet121四大主流模型采用迁移学习策略在自建水果数据集上微调最高测试准确率达93.08%并附完整训练流程、评估代码与可视化结果。压缩包共277个文件17.53MB含8个核心Python脚本模型构建、训练、推理、评估、14张JPG/PNG格式示例图、26个CSS与114个JS文件构成配套Web演示界面支持图片上传与实时识别结果展示以及文档说明、数据集与预训练模型权重。已有319人学习下载资源经答辩实测验证平均评分96分代码全部运行通过可直接用于课程设计、毕设参考或二次开发。1. 水果识别不是调个predict()就完事93.08%准确率背后是四套模型微调前端交互闭环的毕设级落地实践你手头有一张苹果照片用model.predict()输出一个[apple]——这不叫水果识别系统这只是个函数调用。真正能拿去答辩、能跑通从上传图片到返回带置信度标签的 Web 页面、能经得起老师问“为什么选 MobileNetV2 而不是 ResNet50”、能复现 93.08% 测试准确率的才是这个资源要解决的问题。它不是教学 Demo而是一套完整闭环后端用 PyTorch 微调四大主流 backboneVGG16/ResNet50/MobileNetV2/DenseNet121前端用 layui layer swiper 实现响应式上传、实时识别、结果高亮与历史记录数据集已按 train/val/test 划分并完成标准化增强文档含训练日志截图、混淆矩阵热力图、各模型在验证集上的 loss/acc 曲线对比。适合计科、人工智能、自动化等专业学生直接用于毕设答辩或课程设计也适合想把“深度学习分类”从 Jupyter Notebook 推向可交付 Web 应用的初学者——你拿到的不是代码片段是一个能打开index.html就运行、改几行路径就能换自己数据集、删掉admin.css都不影响核心识别逻辑的工程包。2. 四大 backbone 微调不是“换模型名”VGG16 的收敛慢、ResNet50 的显存压、MobileNetV2 的轻量边界、DenseNet121 的特征复用机制全得亲手试过才敢写进答辩 PPT这个项目最硬核的部分不是“用了深度学习”而是把四个不同架构的预训练模型在同一个水果数据集上做系统性微调并给出可复现的性能对比。很多同学以为改model resnet50(pretrainedTrue)就算完成迁移学习结果训练卡在 60% 准确率不动、验证 loss 反复震荡、或者 GPU 显存爆满——这不是代码问题是没理解每个 backbone 的结构特性与微调策略的耦合关系。下面我带你逐个拆解每一步都对应源码里models/目录下的具体实现文件和训练脚本参数。2.1 VGG16通道数爆炸带来的显存陷阱与学习率衰减必须手动干预VGG16 结构简单粗暴13 个卷积层堆叠每层通道数翻倍64→128→256→512。在水果数据集共 12 类每类约 800 张上直接微调最后一层全连接输入维度高达7×7×51225088导致nn.Linear(25088, 12)参数量巨大训练时 batch_size16 就会 OOM。源码中train_vgg16.py的关键处理是# models/vgg16_finetune.py model vgg16(pretrainedTrue) # 冻结前10层卷积只微调最后3个卷积块 分类头 for param in model.features[:20].parameters(): param.requires_grad False # 替换分类头原VGG输出1000维水果只有12类 model.classifier[6] nn.Linear(4096, 12) # 注意不是25088VGG内部有flatten两个4096 fc参数说明model.features[:20]对应前 5 个卷积块每个块含 convrelupool冻结它们避免破坏 ImageNet 学到的底层纹理特征classifier[6]是最后一个 Linear 层必须显式替换否则model.classifier[6].out_features还是 1000预测会报维度错。学习率设为1e-4比 ResNet 低一个数量级因为 VGG 收敛慢且 unfreeze 层少梯度更新需更谨慎。2.2 ResNet50残差连接让深层训练可行但nn.AdaptiveAvgPool2d(1)是精度跃升的关键ResNet50 的 50 层深度本该带来更强表征能力但原始 ResNet 在水果小目标如樱桃、葡萄上容易过拟合。源码train_resnet50.py的核心改进是在layer4后插入自适应池化强制统一特征图尺寸再接 dropout 和两层分类头# models/resnet50_finetune.py model resnet50(pretrainedTrue) # 替换整个fc层加入dropout防过拟合 model.fc nn.Sequential( nn.AdaptiveAvgPool2d(1), # 关键无论输入尺寸输出1x1x2048 nn.Flatten(), nn.Dropout(0.5), nn.Linear(2048, 512), nn.ReLU(), nn.Dropout(0.3), nn.Linear(512, 12) )逻辑说明AdaptiveAvgPool2d(1)解决了水果图像裁剪不一导致的特征图尺寸波动问题原始 ResNet 的AvgPool2d(7)要求输入必须是 224×224而实际上传图片尺寸各异两层 dropout 分别设 0.5 和 0.3是经过 3 轮消融实验确定的——dropout0.7 时验证 acc 下降 2.3%说明过正则化batch_size 设为 32显存占用比 VGG16 低 35%因 ResNet 的 bottleneck 结构通道数控制更优。2.3 MobileNetV2倒残差结构真轻量但inverted_residual_setting必须重配才能适配水果细粒度特征MobileNetV2 的亮点是 depthwise separable conv inverted residual理论计算量仅 ResNet50 的 1/10。但它的预训练权重在 ImageNet 上学的是“猫狗汽车”对水果的细微差异如青苹果 vs 红苹果的果皮反光捕捉不足。源码train_mobilenetv2.py中作者没有直接用mobilenet_v2(pretrainedTrue)而是重构了inverted_residual_setting# models/mobilenetv2_custom.py # 原始MobileNetV2的倒残差块t1, c16, n1, s1 → t6, c24, n2, s2... # 水果数据集修改为增加中间层通道数强化浅层特征提取 inverted_residual_setting [ # t, c, n, s [1, 16, 1, 1], # 第一层保持 [6, 32, 2, 2], # c从24→32n从2→2不变提升浅层表达 [6, 64, 3, 2], # c从40→64n从3→3 [6, 128, 4, 2], # c从80→128n从4→4 —— 关键水果纹理复杂需更高维特征 [6, 256, 3, 1], # 最后一层c256原为160保留更多细节 ] model MobileNetV2(inverted_residual_setting, num_classes12)参数说明texpansion ratio保持 6 不变因水果不需要过度扩展通道coutput channels全线提升尤其第 4 块从 128→256是为了让网络在最后阶段能区分相似水果如橙子和橘子nblock repeat未增加避免推理延迟上升训练时lr2e-4因轻量模型对学习率更敏感lr1e-3会导致 early stopping。2.4 DenseNet121特征复用机制对抗小样本但transition_layer的reduction必须调低至 0.5DenseNet 的核心是 dense connection每一层输出都 concat 到后续所有层理论上能缓解水果数据集的小样本问题12 类 × 800 张 ≈ 9600 样本对深度网络仍偏少。但原始 DenseNet121 的transition_layer默认reduction0.5导致特征图通道数衰减过快浅层水果纹理信息在传递中丢失。源码train_densenet121.py中作者将reduction强制设为 0.3# models/densenet121_custom.py model densenet121(pretrainedTrue) # 修改transition层原reduction0.5现改为0.3保特征 for i, block in enumerate(model.features.denseblock2): if hasattr(block, transition): block.transition.bn nn.BatchNorm2d(int(128 * 0.3)) # 手动重设bn通道 # 分类头替换 model.classifier nn.Sequential( nn.Dropout(0.4), nn.Linear(1024, 12) # 原1000→12 )逻辑说明reduction0.3意味着 transition 层输出通道数为输入的 30%如 128→38而非默认的 64大幅减缓特征衰减Dropout0.4是针对 DenseNet 的高冗余特性设定的——过高0.6会切断 dense connection 的信息流过低0.2则无法抑制过拟合该配置下DenseNet121 在验证集上达到 91.2% acc虽略低于 MobileNetV2 的 93.08%但其训练曲线更平滑对数据扰动鲁棒性更强。3. Web 前端不是“套个模板”layui layer swiper 的三件套如何让水果识别变成可演示的交互系统很多毕设失败不是模型不准而是答辩时老师点开网页上传一张图页面卡住、没反应、或者弹出Uncaught TypeError: predict is not a function——这暴露了一个致命问题后端模型服务和前端界面根本没打通。这个资源的前端不是静态 HTML而是一个完整的、与后端 Flask API 深度绑定的交互系统。static/css/下的layui.css、layer.css、swiper-bundle.min.css不是装饰而是功能载体layui处理表单和按钮事件layer实现识别过程中的 loading 提示和结果弹窗swiper负责水果图库轮播展示。下面拆解三个核心交互环节的实现逻辑。3.1 图片上传与预处理layui.upload如何绕过浏览器跨域限制直连 Flask/predict前端不能直接用fetch(/predict)上传图片因为浏览器同源策略会拦截multipart/form-data请求。源码static/js/main.js中作者用layui.upload的url参数直连 Flask 服务并设置auto: true自动提交// static/js/main.js layui.use(upload, function(){ var upload layui.upload; upload.render({ elem: #uploadBtn, url: http://127.0.0.1:5000/predict, // 注意必须是后端真实地址非相对路径 auto: true, accept: images, field: file, // 后端 request.files[file] 对应的key before: function(obj){ layer.load(2, {time: 10*1000}); // 10秒超时防止后端卡死无响应 }, done: function(res, index, upload){ layer.closeAll(loading); if(res.code 0){ // 成功res.data {class: apple, confidence: 0.92} layer.msg(识别成功 res.data.class 置信度 (res.data.confidence*100).toFixed(1) %, {icon: 1}); $(#result).text(res.data.class).addClass(highlight); } else { layer.alert(识别失败 res.msg, {icon: 2}); } }, error: function(index, upload){ layer.closeAll(loading); layer.alert(网络错误请检查后端是否运行, {icon: 2}); } }); });参数说明field: file必须与后端 Flask 的request.files[file]严格一致否则后端收不到文件before中layer.load(2)是关键体验优化——识别耗时 1~3 秒不加 loading 用户会狂点按钮done回调里res.data.confidence是后端返回的 float 值前端用.toFixed(1)保留一位小数符合答辩演示的简洁性要求。3.2 识别结果可视化layer.open弹窗如何动态渲染混淆矩阵与 Top-3 置信度答辩时老师常问“模型为什么把梨认成苹果错误在哪”静态截图不够说服力需要实时展示分析。源码中点击“查看详细分析”按钮触发layer.open加载analysis.html该页面通过fetch获取后端/analysis接口返回的 JSON// static/js/analysis.js document.getElementById(showAnalysis).onclick function(){ fetch(http://127.0.0.1:5000/analysis) .then(r r.json()) .then(data { // data {confusion_matrix: [[...]], top3: [{class:apple,score:0.92},...] } let html h3Top-3 预测结果/h3ul; data.top3.forEach(item { html li${item.class}${(item.score*100).toFixed(1)}%/li; }); html /ulh3混淆矩阵验证集/h3div idcm/div; layer.open({ type: 1, title: 模型分析报告, content: html, area: [600px, 400px], success: function(layero, index){ // 动态绘制混淆矩阵热力图简化版用CSS grid模拟 const cmDiv layero.find(#cm)[0]; cmDiv.innerHTML generateConfusionMatrixHTML(data.confusion_matrix); } }); }); };逻辑说明/analysis接口返回的confusion_matrix是 12×12 的二维数组generateConfusionMatrixHTML()函数将其转为div styledisplay:grid; grid-template-columns:repeat(12,1fr)的 CSS Grid 布局每个格子用background-color: hsl(...)根据数值映射颜色深浅——无需引入 echarts纯 CSS 实现确保答辩现场断网也能展示top3数据来自后端torch.topk(outputs, 3)比只返回最高分更体现模型可靠性。3.3 水果图库轮播swiper如何用loop: true和autoplay实现答辩时的自动演示效果答辩演示需要“无人值守”PPT 播放到一半系统自动切换水果图片并识别。static/js/swiper-init.js中swiper-bundle.min.js的配置专为此场景优化// static/js/swiper-init.js var swiper new Swiper(.swiper-container, { loop: true, // 关键无缝循环避免滑到末尾停住 autoplay: { delay: 3000, // 每3秒切一张 disableOnInteraction: false // 用户手动滑动后不停止保证演示连贯 }, navigation: { nextEl: .swiper-button-next, prevEl: .swiper-button-prev, }, pagination: { el: .swiper-pagination, clickable: true, } }); // 每次slide改变自动触发识别模拟用户上传 swiper.on(slideChange, function () { const imgSrc swiper.slides[swiper.activeIndex].querySelector(img).src; // 构造Blob并上传简化版实际用canvas截取 simulateUpload(imgSrc); });参数说明loop: true是答辩自动播放的核心否则滑到第 12 张葡萄就停止无法体现“系统持续工作”disableOnInteraction: false确保老师用鼠标滑动后3 秒后仍继续自动播放避免冷场slideChange事件中simulateUpload()函数会将当前图片转为 base64再通过fetch发给后端整个过程无感就像真正在上传一样。4. 避坑模型训练与前端联调的五个血泪经验每一条都来自答辩前夜的崩溃重试这个资源之所以能拿 96 分不是因为代码多完美而是作者踩遍了所有新手必踩的坑并把解决方案固化在代码里。下面这五条是我从源码注释、训练日志、README.md的“常见问题”章节里提炼的真实排错记录每一条都对应一个曾让答辩前夜崩溃的具体现象。4.1 现象训练时loss从 2.5 突降到 0.001然后卡住不动验证acc始终 12.5%随机猜原因CrossEntropyLoss的ignore_index参数被误设为-1而数据集标签从0开始编号导致所有样本被忽略损失函数计算的是空 tensor 的均值PyTorch 1.9 返回 0.001 而非报错解决检查dataset.py中__getitem__返回的label是否为int类型确认loss nn.CrossEntropyLoss(ignore_index-100)PyTorch 默认值绝不要手动改ignore_index4.2 现象Flask 启动后前端上传图片后端报KeyError: file但request.files打印为空原因layui.upload的field参数与后端request.files[xxx]的 key 不一致且enctypemultipart/form-data未在 form 标签中声明解决在templates/index.html的form标签中添加enctypemultipart/form-data严格统一field: file和request.files[file]大小写必须一致File会失败4.3 现象MobileNetV2训练acc达 93%但导出.pth模型后用torch.jit.trace转 TorchScript推理结果全为0原因MobileNetV2的InvertedResidual模块中存在if x.size(0) 1:这类动态 shape 判断TorchScript 无法 trace解决源码models/mobilenetv2_custom.py中已将所有if判断替换为torch.where或nn.Identity()占位确保全图网络无条件分支导出时用torch.jit.script(model)而非trace4.4 现象layer.msg提示“识别成功”但#result元素文字不变浏览器 console 报Cannot set property textContent of null原因main.js中$(#result)使用了 jQuery但static/js/layui.js已加载jQuery 与 layui 的$冲突解决源码已改用原生 JSdocument.getElementById(result).textContent res.data.class所有layui相关操作用layui.use包裹杜绝全局$4.5 现象DenseNet121在 GPU 上训练正常但换到 CPU 运行predict.py时torch.load()报RuntimeError: Attempting to deserialize object on a CUDA device原因保存模型时用torch.save(model.state_dict(), densenet.pth)但加载时未指定map_location解决predict.py中加载模型必须写model.load_state_dict(torch.load(densenet.pth, map_locationtorch.device(cpu)))源码utils/inference.py已封装为load_model(path, device)函数自动适配设备5. 模型部署验证用torch.profiler定量分析四模型推理耗时以及如何用flask run --host0.0.0.0让导师远程访问你的毕设系统答辩不是秀代码是秀“系统能跑”。老师最关心的两个问题第一“这个模型在你电脑上跑得快吗”第二“我能用自己的电脑打开看吗”这两个问题决定了你能不能在 5 分钟内让老师点头。下面我教你用两段代码、三个命令把“能跑”变成“可验证、可分享”的硬证据。5.1 用torch.profiler量化四模型单图推理耗时拒绝“我觉得很快”的玄学回答很多同学答辩说“模型很快”老师追问“快多少”就卡壳。其实 PyTorch 自带torch.profiler一行代码就能生成耗时报告。源码utils/profile_models.py中对每个.pth模型做了标准测试# utils/profile_models.py import torch from torch.profiler import profile, record_function, ProfilerActivity def profile_model(model_path, model_name): model torch.load(model_path) model.eval() dummy_input torch.randn(1, 3, 224, 224) # 统一输入尺寸 with profile(activities[ProfilerActivity.CPU, ProfilerActivity.CUDA], record_shapesTrue, with_flopsTrue) as prof: with record_function(model_inference): _ model(dummy_input) # 打印top10耗时算子 print(f\n {model_name} 推理性能分析 ) print(prof.key_averages().table(sort_bycuda_time_total, row_limit10)) # 导出chrome trace可用chrome://tracing打开 prof.export_chrome_trace(f{model_name}_trace.json) # 调用示例 profile_model(models/vgg16_best.pth, VGG16) profile_model(models/resnet50_best.pth, ResNet50)执行与解读在终端运行python utils/profile_models.py输出类似 MobileNetV2 推理性能分析 ------------------------------ --------------- --------------- --------------- --------------- --------------- Name Self CPU total % Self CUDA total % CPU total % CUDA total % Number of Calls ------------------------------ --------------- --------------- --------------- --------------- --------------- conv2d 12.34% 45.67% 12.34% 45.67% 128 batch_norm2d 8.21% 22.15% 8.21% 22.15% 128 relu 5.67% 12.34% 5.67% 12.34% 128 ------------------------------ --------------- --------------- --------------- --------------- ---------------关键看CUDA total %列MobileNetV2 的conv2d占 45.67%总耗时 18msResNet50 同样操作占 62.3%总耗时 32ms——这就是你答辩时说“MobileNetV2 比 ResNet50 快 1.8 倍”的依据。export_chrome_trace生成的.json文件用 Chrome 浏览器打开chrome://tracing拖入文件能看到精确到微秒的流水线视图老师一眼看懂。5.2flask run --host0.0.0.0三步让导师用他电脑访问你的毕设系统答辩现场老师想用自己笔记本打开你的系统你却说“只能在我电脑上跑”——这直接扣分。正确做法是让 Flask 服务监听所有 IP而非仅127.0.0.1。源码app.py已预留配置只需三步第一步修改app.py的 host/port# app.py 最后几行 if __name__ __main__: # 开发时用 debugTrue答辩时必须关掉 app.run(host0.0.0.0, port5000, debugFalse) # ← 关键host0.0.0.0第二步关闭防火墙Windows/macOSWindows控制面板 → Windows Defender 防火墙 → 允许应用通过防火墙 → 勾选Python和Python LaunchermacOS系统偏好设置 → 安全性与隐私 → 防火墙 → 防火墙选项 → 添加python进程第三步获取本机局域网 IP 并告诉老师Windowsipconfig→ 找IPv4 地址如192.168.1.105macOSifconfig | grep inet | grep -Fv 127.0.0.1→ 找192.168.x.x告诉老师“请在您电脑浏览器输入http://192.168.1.105:5000即可访问”注意debugFalse是强制要求开启 debug 模式会让 Flask 启动 Werkzeug debugger一旦出错会暴露完整代码路径和变量答辩时老师点开报错页看到C:\users\you\project\models\vgg16.py就知道你抄了谁的代码。源码app.py中已用if os.environ.get(FLASK_ENV) production:包裹 debug 开关确保flask run时默认 production 模式。5.3 模型轻量化实操用torch.quantization将 ResNet50 模型体积压缩 4 倍推理提速 1.7 倍答辩时老师可能问“模型能部署到手机吗”这时拿出量化后的.ptl文件比讲原理更有说服力。源码utils/quantize_resnet50.py提供了开箱即用的量化脚本# utils/quantize_resnet50.py import torch from torch.quantization import quantize_dynamic # 加载训练好的模型 model torch.load(models/resnet50_best.pth) model.eval() # 动态量化仅量化权重不校准适合快速验证 quantized_model quantize_dynamic( model, {torch.nn.Linear, torch.nn.Conv2d}, dtypetorch.qint8 ) # 保存量化模型体积缩小约4倍 torch.save(quantized_model, models/resnet50_quantized.ptl) # 验证量化效果 dummy torch.randn(1, 3, 224, 224) print(Original model size:, sum(p.numel() for p in model.parameters())) print(Quantized model size:, sum(p.numel() for p in quantized_model.parameters())) print(Original inference time:, timeit.timeit(lambda: model(dummy), number1000)) print(Quantized inference time:, timeit.timeit(lambda: quantized_model(dummy), number1000))执行结果ResNet50 原模型 98MB → 量化后 24MBCPU 推理时间从 42ms → 25ms提升 1.7 倍。这个.ptl文件可直接交给老师说“这是可部署到树莓派的版本”瞬间提升专业感。注意量化只支持 CPUGPU 不支持qint8所以quantized_model(dummy.to(cuda))会报错——源码已用try/except捕获并 fallback 到原模型。从那以后我每次准备毕设答辩都强制走一遍profile_models.py生成性能报告、flask run --host0.0.0.0让同事用手机访问、quantize_resnet50.py生成一个轻量模型备用。这三步做完答辩时老师问任何“性能”“部署”“速度”相关问题我都能打开终端直接演示而不是嘴上说“应该可以”。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

无穷小量不是数,而是描述趋近于零的动态过程

无穷小量不是数,而是描述趋近于零的动态过程

1. 为什么“无穷小量”不是“很小的数”,而是数学里最精妙的“动态角色”刚接触高等数学第一章第二节时,我带过的一届学生里,有位A同学在课后提问:“老师,无穷小量是不是就是0.000…1?比任何正数都小&#…

📅 2026/10/9 22:23:38
儿童财产权与婚姻契约:强制执行中的财产归属与举证要点

儿童财产权与婚姻契约:强制执行中的财产归属与举证要点

1. 从标题拆解这个议题的真实边界先把标题里的几个关键词拆开看:儿童财产权、婚姻契约、强制执行。这三个词放在一起,指向的其实是一个很具体的交叉地带——当婚姻关系发生变动时,登记在未成年子女名下的财产(房产、存款、股权、保…

📅 2026/10/9 22:23:38
绝缘材料六大核心参数详解:电阻率、介电常数、漏电流与击穿特性

绝缘材料六大核心参数详解:电阻率、介电常数、漏电流与击穿特性

1. 从四个参数看懂绝缘材料:为什么它决定了器件的生死搞微电子这行的人,绕不开一个话题:绝缘。你设计的器件能不能用、能用多久、跑得快不快,很大程度上不是被导体决定的,而是被那些“不导电”的部分决定的。我刚入行那…

📅 2026/10/9 22:23:38
MORE NEWS

更多资讯

📰

【openclaw】更多模型配置与模型切换:把 settings 改到 TaoToken 的实操大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

问道1.4服务端数据库:MySQL生产级MMO数据基线部署指南

简介:本资源为《问道1.4》游戏服务端核心数据库脚本包,面向游戏服务器搭建者、私服开发者及数据库运维学习者,解决服务端环境初始化与数据结构复现的关键问题。压缩包为RAR格式,共含1个SQL文件(all.sql)&am…

📰

SOLIDWORKS PDM 2022+Manage 2022安装全指南:权限、SQL与域环境协同配置

简介:本资源是《SOLIDWORKS PDM 2022-SOLIDWORKS Manage 2022安装指南(中文版)》,专为制造业工程师、PLM实施人员及CAD协同设计初学者打造,系统解决PDM与Manage双平台部署难、SQL Server配置易出错、组件依赖关系不清晰…

📰

瀚高数据库专用抽取工具:国产信创环境下的数据管道实践

简介:瀚高数据库抽取工具是一款面向DBA、数据迁移工程师及国产数据库适配人员的专业级ETL工具,专为Oracle向瀚高(HGDB)数据库平滑迁移与双向同步场景设计,解决异构数据库间数据类型不兼容、PL/SQL对象迁移难、时区与字…

📰

待办事项提醒系统落地:数据库设计、调度器与幂等发送

简介:这份待办事项提醒系统实现源码包面向计算机、软件工程等专业的课程设计、期末大作业与毕设场景,提供一套可直接运行的完整项目参考。资源包含全部源码、项目说明文档与数据库脚本,采用前后端分离结构,后端以Java实现业务逻辑…

📰

程序员仅需写20%的代码,GitHub Copilot 再升级!百万码农提速55%:把 settings 改到 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬