尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python+Vue学院兼职平台开发实战:Flask/Django后端与部署全解析
1. 项目概述与核心需求拆解站在一个做过类似项目的开发者角度第一次看到“基于Python的某学院兼职平台”这个题目我第一反应是这是一个非常典型的Web全栈练手项目也是很多计算机专业同学毕设或者课设最爱选的选题方向。它既有前端交互的复杂度又有后端业务逻辑的深度同时在数据建模上还能折腾出不少花样非常适合用来展示个人技术栈。这个平台的本质是什么说白了就是给校园场景做一个信息撮合系统一方面让需要兼职的学生能快速找到靠谱的岗位另一方面让校内部门或者周边商户能发布用人需求。但和58同城、BOSS直聘这类商业产品不同学院的兼职平台天然带着“受控”和“可信”两个属性。校园环境下管理者需要审核每一则招聘信息的安全性学生需要确认岗位的合法性这种信任关系的建立不能只靠用户自觉必须在系统设计层面通过流程来保障。整个项目包含的核心模块其实就四大块用户认证与管理、兼职信息发布与审核、学生申请与录用流程、后台数据统计与管理。每一块单拆出来看都不算难但组合在一起就需要你在设计架构时想清楚角色权限、数据流向、状态流转这些全局问题。这也是这个项目真正值得动手做一遍的原因——它不是简单的CRUD而是让你体验到从需求分析、表结构设计、接口定义到前端联调的全链路开发流程。从技术栈上看标题里锁定了Vue Python Flask/Django Pycharm这也是当下校园项目里非常主流的一套组合。Vue负责前端页面交互Python负责后端业务逻辑框架层面Flask和Django二选一开发工具统一在Pycharm里完成。整套方案学习成本适中社区资料丰富遇到问题基本都能搜到解决方案对初学者非常友好。如果你正准备做类似的项目或者刚接触Web开发想找个完整案例跟练一遍这篇文章的内容应该可以帮你省掉不少自己摸索的时间。2. 技术选型分析谁的组合更顺手2.1 前端框架为什么选Vue而不是其他兼职平台这种系统前端页面虽然算不上极其复杂但胜在交互场景多学生端要浏览列表、搜索筛选、详情查看、在线申请管理端要处理审核表格、数据统计图表发布端要填写表单、管理自己发布的岗位。这种多角色、多视图的应用如果还像以前那样用jQuery直接操作DOM代码很快就会变成一锅粥。Vue的核心优势在这里就体现出来了组件化。把页面拆成独立的组件结构清晰、复用方便改一个组件不动全局开发体验和后期维护的爽感是传统写法完全比不上的。另外Vue还有一个很适合新手的特性就是渐进式。你不需要一开始就掌握Vuex、Vue Router这些全家桶才能上手先把模板语法、指令、组件通信这些基础用起来项目就能跑起来。等到需要处理复杂状态共享时再逐步引入Vuex或者Pinia也不迟。我当时做类似项目的时候就是先用最基础的选项式API把页面搭起来后面越做越顺。再加上Vue对中文开发者极度友好官方文档翻译质量高遇到问题搜到的解决方案也大多能直接套用学习曲线非常平滑。相比之下React确实生态更庞大、就业市场需求更高但它的上手门槛略高一点JSX的写法、Hooks的概念、状态管理方案选择都是需要额外消化的内容。对于以完成一个校园项目为主要目标的开发者来说Vue的性价比更高能让你把更多精力放在业务逻辑而不是框架本身。2.2 后端框架对比Flask还是Django标题里同时写了Flask和Django这其实是很多人在选题阶段最纠结的一个问题。我的看法是这两个框架做这个项目都完全可行但选型逻辑完全不同。下面用表格把核心差异拉出来对比一下维度FlaskDjango定位轻量级微框架重量级全栈框架学习曲线平缓灵活自由陡峭体系庞大自带功能极简ORM/Admin/表单均需扩展全家桶ORM/Admin/Auth/表单全内置数据库操作SQLAlchemy相对自由ORM深度集成迁移机制完善适合场景中小型系统、接口开发、灵活定制企业级系统、快速搭建后台管理约束程度低代码结构自己定高遵循Django规范社区生态大量第三方扩展库官方生态完整一站式解决从我个人的实际体验来说如果你希望在开发过程中尽可能多地掌握底层细节感受“自己掌控一切”的灵活度Flask是更好的选择。用Flask做这个兼职平台你不仅要自己组织项目结构、配置数据库、设计登录认证方案还要手动搭建接口文档。这个过程会比较折腾但也正因为折腾你对Web框架运行机制的理解会比直接使用Django深得多。我当时用Flask写类似的系统时光是研究JWT认证和装饰器实现权限控制就花了不少时间但这些知识后来在工作里全都用上了。反过来如果你更看重开发效率希望把精力主要集中在业务实现上Django会让你省心很多。它自带的Admin后台可以用来做管理员的快速管理界面内置Auth系统解决了用户登录注册的问题ORM迁移机制让数据库变更变得非常方便。不过Django也有它的“坑”它的ORM对复杂查询的写法有自己的一套语法一不小心就会写出性能很差的查询语句它的“Django式思维”要求你按照它的目录风格组织代码新手经常会被框架的约定搞得头晕。我的建议是如果你是第一次接触Web开发这个项目又是你的毕设选Flask更稳妥。原因很简单Flask的学习深度足够你写出一份有技术含量的论文而且代码工作量看起来会更多答辩时能讲的东西也更多。但如果是为了快速完成一个能演示的成品或者你已经用过Django那就选Django省时省力。2.3 开发环境配置Pycharm下的项目搭建不管选哪个框架Pycharm都是效率很高的开发工具。我用它写Python项目的时间很长对比过VS Code和Sublime Text之后还是觉得Pycharm在Python工程方面的体验更顺手。以下几个配置细节值得留意虚拟环境必须从一开始就配置好。在Pycharm里新建项目时直接选择Virtualenv或者Conda环境后续安装的依赖包都装进这个隔离环境里不会污染全局Python换机器部署时通过requirements.txt一键还原非常方便。Flask项目的目录结构建议project_root/ ├── app/ │ ├── __init__.py # 应用工厂初始化Flask实例 │ ├── models/ # 数据库模型 │ ├── views/ # 蓝图路由 │ ├── utils/ # 工具函数 │ └── static/ # 静态资源 ├── config.py # 配置项数据库连接、密钥等 ├── requirements.txt # 依赖清单 └── run.py # 启动入口Django项目的创建命令django-admin startproject myproject python manage.py startapp user python manage.py startapp job python manage.py startapp application python manage.py migrate前后端协同开发时Pycharm里做两件事很重要一是在运行配置里设置好后端服务的端口和启动参数二是用Pycharm的“JavaScript Debug”配置把Vue的开发服务器跑起来。Vue默认跑在8080端口后端Flask跑在5000端口两者端口不同就需要在前端的vue.config.js里配置代理转发这样前端发请求时会把 /api 开头的请求转发到后端端口避免跨域问题// vue.config.js module.exports { devServer: { proxy: { /api: { target: http://localhost:5000, changeOrigin: true } } } }这个配置是我在建项目时首先做的一步能让前后端分离开发变得顺畅很多。3. 数据库设计与核心逻辑实现3.1 数据表规划与字段设计兼职平台的数据建模是整个项目的灵魂表设计好不好直接决定后续开发时要多写多少判断逻辑。我在设计这张数据库时最终规划了六张核心表用户表、兼职岗位表、申请记录表、审核记录表、收藏表、结算记录表。用户表是基础中的基础主要字段包括用户名、密码摘要、真实姓名、学号/工号、手机号、邮箱、角色学生/发布者/管理员、头像URL、注册时间、账号状态。这里我特意把身份字段设计为角色枚举而不是用一个布尔值因为后期很可能需要扩展更多角色比如“临时校外人员”。兼职岗位表的字段要相对丰富一些岗位标题、岗位描述、工作类型线上/线下/长期/短期、薪资待遇、招聘人数、已报名人数、工作地点、岗位标签、发布者ID外键、审核状态、上下架状态、浏览量、截止时间。这里有一个我当时反复考虑过的细节审核状态应该用数字表示0待审核1通过2拒绝还是用字符串pending, approved, rejected后来我选择了数字加注释的方式因为数字在数据库查询排序和索引处理上性能更好而且配合常量定义代码可读性也不差。申请记录表用来记录学生投递兼职的全过程。必须和岗位表分开建因为一个学生可以申请多个岗位一个岗位可以被多个学生申请这是典型的多对多关系。拆出一张独立的关联表同时还能承担申请状态存储的职责已投递、已查看、已录用、已拒绝、已完成。这张表还需要记录申请时间、备注信息、评价内容等。审核记录表则是对审核动作留痕谁能审核、审核了什么、审核结果是什么、为什么通过或者拒绝这些信息对于校园场景来说非常重要。出了纠纷之后要追溯到审核链路。我把六张表的核心关系用文字描述一下方便你理解用户(发布者) 1 —— N 兼职岗位用户(学生) N —— M 兼职岗位通过申请记录表关联兼职岗位 1 —— N 审核记录学生 N —— M 兼职岗位通过收藏表关联用户(学生) 1 —— N 结算记录兼职岗位 1 —— N 结算记录3.2 状态机的设计与心得表面上看兼职平台的数据表之间关系并不复杂真正考验设计功底的是状态流转逻辑。一个兼职岗位从被创建到最后完成要经历一个完整的生命周期待审核 - 已发布 - 已下架/已过期一个学生申请从投递到结束也要经历已投递 - 已查看 - 已录用/已拒绝 - 已完成。在开发之前就要把这些状态机画清楚否则后端的接口逻辑会写成一团乱麻。我当时是把状态常量写在一个公共文件里统一管理比如创建状态常量然后把状态的变更集中到少数几个方法里更新状态前做校验禁止非法跳转。比如不允许一个已拒绝的申请变回已录用不允许已下架的岗位重新被申请。这种约束放在后端校验前端隐藏按钮只是优化体验真正的安全边界永远在服务端。实际设计时我走了一个弯路提出来可以帮你避坑最开始我把“审核状态”和“上下架状态”合并到了一个字段里结果发现业务逻辑很难写。比如一个审核通过的岗位一旦发布者主动下架这个字段变成“已下架”后台管理员就没法区分“审核通过后下架”和“从未上架”的岗位。后来我把两个概念彻底拆开审核状态只管审核生命周期上下架状态只管展示生命周期各管各的代码逻辑一下子就清晰了。给字段做职责分离是这次项目给我上的很重要的一课。3.3 Flask和Django的模型代码示例用Flask配合SQLAlchemy写模型时岗位表的定义大致是这样的# app/models/job.py from datetime import datetime from app import db class Job(db.Model): __tablename__ job id db.Column(db.Integer, primary_keyTrue) title db.Column(db.String(100), nullableFalse) description db.Column(db.Text, nullableFalse) job_type db.Column(db.String(20), defaultoffline) # offline/online/short_term salary db.Column(db.String(50)) headcount db.Column(db.Integer, default1) applied_count db.Column(db.Integer, default0) location db.Column(db.String(200)) publisher_id db.Column(db.Integer, db.ForeignKey(user.id)) status db.Column(db.Integer, default0) # 0:审核中 1:已通过 2:已拒绝 3:已下架 is_active db.Column(db.Boolean, defaultTrue) view_count db.Column(db.Integer, default0) deadline db.Column(db.DateTime) created_at db.Column(db.DateTime, defaultdatetime.now) def to_dict(self): return { id: self.id, title: self.title, description: self.description, job_type: self.job_type, salary: self.salary, headcount: self.headcount, applied_count: self.applied_count, location: self.location, publisher_id: self.publisher_id, status: self.status, deadline: self.deadline.strftime(%Y-%m-%d %H:%M) if self.deadline else None }这段代码你仔细看我做了几件事给每个字段加了默认值避免插入时遗漏给时间的序列化做了格式转换否则前端拿到的是Python的datetime对象JSON序列化会直接报错状态字段用数字表达同时留出了扩展空间。这些细节在Django的模型里也是同样的处理原则只是Django需要额外指定choices属性来约束枚举范围。4. 前后端核心功能实现与联调4.1 后端的接口规划与认证方案后端部分我采用的是蓝图加RESTful风格接口的方式。把所有接口按资源划分好POST /api/auth/login学生/发布者登录POST /api/auth/register注册账号GET /api/jobs兼职列表支持关键词搜索、类型筛选、分页GET /api/jobs/int:job_id兼职详情POST /api/jobs发布新兼职仅发布者可调用PUT /api/jobs/int:job_id编辑兼职仅该岗位的发布者POST /api/jobs/int:job_id/apply学生投递简历GET /api/applications?rolepublisher按角色查看申请记录PUT /api/applications/int:app_id/review发布者处理录用/拒绝GET /api/admin/audit_list管理员待审核岗位列表PUT /api/admin/audit/int:job_id管理员审核通过/拒绝认证方案上我没有用传统的Session方案而是选择了JWTJSON Web Token。登录成功后后端返回一个带有过期时间的Token前端存到localStorage里每次请求在请求头里带上。后端通过装饰器来解析Token校验合法性然后从Token中解析出用户角色再做权限判断# app/utils/auth.py from functools import wraps from flask import request, jsonify import jwt def token_required(f): wraps(f) def decorated(*args, **kwargs): token request.headers.get(Authorization) if not token: return jsonify({msg: 未登录}), 401 try: # 去掉开头的 Bearer 前缀 payload jwt.decode(token.split( )[-1], app.config[SECRET_KEY], algorithms[HS256]) current_user User.query.get(payload[uid]) except jwt.ExpiredSignatureError: return jsonify({msg: 登录已过期}), 401 except Exception: return jsonify({msg: 无效Token}), 401 return f(current_user, *args, **kwargs) return decorated这个装饰器写好之后接口里只要在路由上加上token_required就能自动获得登录校验能力。然后再配合角色判断就能实现发布者接口、管理员接口的权限隔离。4.2 Vue前端的组件设计与请求封装前端部分我用Vue Router做页面路由用Axios发请求。重点说一下Axios的请求封装因为这是整个前端开发中最重要的一部分。我建了一个request.js文件统一做请求发送前的Token注入和响应返回后的统一错误处理// src/utils/request.js import axios from axios import router from ../router const service axios.create({ baseURL: /api, timeout: 10000 }) // 请求拦截器统一注入Token service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }) // 响应拦截器统一处理401等异常 service.interceptors.response.use( response response.data, error { if (error.response) { if (error.response.status 401) { localStorage.removeItem(token) router.push(/login) } return Promise.reject(error.response.data) } else { return Promise.reject({ msg: 网络异常请稍后重试 }) } } )封装完成后在业务代码里调用就非常简洁了login() { return request.post(/auth/login, this.form) }页面组件方面前端我重点做了三个页面兼职大厅、岗位详情、个人中心。兼职大厅用列表加筛选器的方式展示数据搜索框和类型下拉框都挂在同一个请求方法下通过修改查询参数请求后端接口。岗位详情页则分角色展示操作按钮学生看到“立即申请”发布者看到“编辑/下线”管理员看到“通过/拒绝”。这种基于角色的条件渲染是Vue指令和计算属性很自然的应用场景。4.3 前后端联调时我踩过的坑联调过程中最容易出问题的几个点我整理了以下几条每一行都是实际调试出来的经验第一时间格式不一致。Python后端默认返回的是2025-01-12 14:30:00但如果前端直接用new Date()去格式化会有兼容性问题。我最后的处理方案是后端所有时间字段在序列化前统一用strftime转成字符串前端不再自己解析直接展示原值。第二空字段处理不彻底。比如某个兼职岗位没有设置截止时间数据库里是nullJSON序列化后变成null前端某个地方拼字符串时粗心大意就直接显示成“null”。我后端模型里专门做了判断为空的字段返回空字符串。第三跨域问题在联调阶段暴露。虽然开发时配了Vue代理不会出问题但前后端分离部署之后就绕不过去了。解决方案是后端加一个CORS配置允许指定域名跨域访问或者统一通过Nginx反向代理把/api路径转发到后端服务上这样浏览器层面就不会有跨域问题。5. 常见问题与高频Bug排查实录5.1 开发中的典型问题速查整个开发过程中我遇到的绝大多数问题其实都是细节问题但如果没有经验一个小细节也能卡住很久。我把高频问题整理成了一份速查表直接照着排查就行问题现象可能原因解决方案Vue页面刷新后404前端路由是history模式开发服务器没有配置回退后端或开发服务器配置将所有非静态路由回退到index.htmlAxios请求返回401Token过期或未携带检查请求拦截器是否注入了Token检查Token过期时间列表页数据不展示后端返回的字段名和前端取用的字段名不一致在浏览器Network面板核对响应JSON字段逐个对照图片上传后访问404上传文件路径和静态资源映射没有对应后端配置静态文件映射到上传目录检查相对路径/绝对路径数据库增加字段后模型不同步改了模型类没有执行迁移Flask用flask db migrate upgradeDjango用makemigrations migrate后端API偶尔报500因为列表里混入了无需序列化的字段比如password检查模型类的to_dict方法确保没有返回敏感字段分页接口数据重复数据在排序字段上不稳定比如多条记录排序时间相同排序条件增加一个唯一字段如id确保排序稳定5.2 安全层面的几个重点问题兼职平台是校园内使用的系统安全意识不能因为是练手项目就放松。我遇到的具体问题和对应方案可以在你做类似项目时直接复用密码存储绝对禁止明文存储也不建议自己实现加密算法。直接用werkzeug库的generate_password_hash来做哈希验证时用check_password_hash比对。这个方案经过大量真实项目验证比你自己写一个所谓的“加密方法”要可靠得多。SQL注入很多人觉得自己写的是ORM就不会有注入风险这里有一个重大误解。ORM对参数化查询处理得确实比较完善但如果你在某些场景下拼接了原生SQL字符串尤其是用了db.session.execute执行原生SQL时拼接了外部参数注入风险就会回来。当时我排查一个搜索功能发现用字符串拼接的方式传进了SQL语句后来改成参数绑定方式才解决。记住一个原则永远不要拼接参数进SQL。权限越权这是最常见的安全漏洞。比如一个学生用户直接调用PUT /api/applications/3/review后端如果只校验了登录状态没校验当前用户是否为该兼职的发布者就存在越权风险。我的做法是在业务处理前先查一次关联关系比如处理申请前肯定要先把这个申请所属的岗位查出来校验岗位的发布者ID和当前登录用户ID是否一致不一致直接拒绝。图片上传漏洞用户上传的文件不能直接保存原本文件名因为可能带上路径穿越字符或者恶意脚本。我处理时统一用uuid生成新文件名并且校验文件扩展名白名单保存目录放在Web服务之外通过专门的静态路由来访问。5.3 部署上线的实操建议项目做完之后部署上线是检验成果的最后一关。校园项目通常不会买昂贵的服务器我一般建议方案是用一台云服务器加Nginx完成整个部署后端用Gunicorn启动Flask服务监听本地端口命令大致是gunicorn -w 4 -b 127.0.0.1:8000 run:app前端构建完成后把dist目录里的静态文件放在Nginx配置的根目录下同时配置一个location规则把/api路径的请求反向代理到http://127.0.0.1:8000server { listen 80; server_name your_domain; root /var/www/dist; index index.html; location /api { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location / { try_files $uri $uri/ /index.html; } }这个配置里有几个细节值得注意try_files $uri $uri/ /index.html这行是为了解决Vue history模式路由刷新404的问题proxy_set_header X-Real-IP $remote_addr是为了让后端能记录到客户端的真实IP方便后面做访问日志分析。数据库迁移和测试数据初始化也建议在上线前做一次演练。实际部署时最让人头疼的往往不是代码本身而是生产环境和开发环境的差异比如数据库版本不一致、系统依赖缺失、端口没开放这些问题。上线前先写一个部署文档把每一条命令记清楚按步骤执行一遍能避免百分之九十的闹心。6. 复盘与个人体会整个项目做完回头看最大的感受是这类校园管理系统的难点从来不在某个单一技术点上而是把多个模块整合在一起时暴露出的一连串问题。比如用户认证方案会影响后续所有接口的编写方式数据库表结构的设计决定了状态流转是不是顺畅前端组件划分是否合理直接关系到后期加功能时效率高不高。这些问题单独看都简单但连在一起就构成了一个完整系统的复杂度。这也正是做完整项目的意义所在——课本上学到的知识是零散的项目才能真正训练你把知识串起来的能力。最后分享一个我一直在用的开发习惯每个模块做完之后第一时间更新接口文档。我用的方法很简单就在项目目录里放一个Markdown文件每写一个接口就随手记录请求方法、路径、参数、返回示例这样联调时就不用反复往后端代码里翻遇到问题也能快速对照。给自己的项目写文档看似多花了十分钟但在后续开发调试和最终答辩时节省的时间远远不止这十分钟。
RELATED

相关推荐

Excel存货健康度看板:12指标+3类归因的业财监控方案

Excel存货健康度看板:12指标+3类归因的业财监控方案

简介:本资源是一份面向企业财务、供应链及数据分析岗位从业者的「财经存货看板」专业文档,聚焦存货可视化管理与财务协同分析场景,解决实时库存监控、呆滞风险识别、周转率追踪及合规数据支撑等核心痛点。文档为单文件Word格式(.d…

📅 2026/10/18 13:53:12
第63篇:3DTiles-大雁塔模型——190 块瓦片不是八叉树,抬高的却是球心那条法线

第63篇:3DTiles-大雁塔模型——190 块瓦片不是八叉树,抬高的却是球心那条法线

上篇结尾我留了这么一句话: “下一篇我们换条线——不再画自己的数据,而是把别人做好的一整座塔搬进地球。3DTiles 的大雁塔模型,我们下一篇见。”从 #59 的面、#60 的线、#61 的体到 #62 的文字,我们一路都在干同一件事&#xff…

📅 2026/10/18 13:53:12
Postman 8.9.1 中文汉化包:界面替换与避坑指南

Postman 8.9.1 中文汉化包:界面替换与避坑指南

简介:Postman 8.9.1 中文包面向接口测试初学者与需要中文界面的开发、测试人员,解决官方英文界面理解成本高、菜单与提示不易上手的问题,适合日常调试 API、编写测试用例及团队协作场景。压缩包为 zip 格式,共约 2000 个文件&…

📅 2026/10/18 13:53:12
MORE NEWS

更多资讯

📰

本地AI部署实战:Ollama拉起开源模型,OpenClaw接入业务流程

2026 年还在纠结“本地 AI 到底值不值得部署”的人,我猜多半没经历过月底被云端 API 账单支配的恐惧,也没被敏感数据不能出内网的需求折磨过。我在帮不同团队搭本地模型服务时,被问得最多的两个问题分别是:Ollama 这类工具是不是只…

📰

科颜萃b5面霜代加工源头厂怎么选?车间老炮拆解膏体公差与防比价底牌

明明配方单上都写着泛醇,怎么你拿到的货一上脸就搓泥、放两个月就出水?这事在车间里天天见。B5面霜这个品类,看着简单,就一个泛醇保湿的活儿,实际上是最考验代工厂底层功力的品类之一。做得好的,膏体细腻服…

📰

迪奥720同款颜色口红同源配方到底怎么挑?车间老炮拆给你看

拿着手机里那张720色系的试色图来找厂里打样的老板,十有八九第一句话是“能不能做到一模一样”,第二句话是“价格能不能再压一压”。这两句话放一块儿,本身就是矛盾的。▼ 源头车间质检备案与合作授权说明 ▼色粉粒径压细一档、蜡基换成高熔点…

📰

Power BI MCP 企业落地方案:让企业 Agent 真正用上 BI 能力(TaoToken 统一 Key 接入篇)

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

📰

Everything Codex 使用说明:把 Codex auth.json 改到 TaoToken 的完整配置与验证

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

📰

LangChain Tools 工具集成与自定义开发:用 TaoToken 统一 Key 打通多模型调用链

/* 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

本月热门

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

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

📞 💬