ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于Django DRF与Vue 3的全栈企业管理系统实战指南

基于Django DRF与Vue 3的全栈企业管理系统实战指南 简介这是一套面向Python全栈开发者与Web工程学习者的完整企业管理系统实战源码聚焦DjangoVue前后端分离架构解决中小型企业管理场景下的用户权限、部门协作、任务调度等核心业务建模与API集成问题。资源共109个文件含38个核心Python后端逻辑文件Django模型、视图、序列化器及DRF API配置、35个编译缓存文件pyc、27张界面截图与UI设计参考图jpg/png以及README说明文档压缩包仅5.24MB轻量易部署。已有1201人学习下载适合中高级学习者系统掌握MTV架构设计、RESTful接口开发、Vue组件通信、JWT认证集成及Django ORM多表关联建模等关键技术点项目目录结构规范前后端模块物理隔离附带典型业务实体用户/部门/任务的CRUD实现与权限控制示例可直接运行调试并作为二次开发基础模板。1. 项目背景与核心价值最近几年但凡聊到企业级应用开发“前后端分离”和“快速开发”几乎是绕不开的两个关键词。我手头刚结束的一个项目就是一个典型的基于 Django Django REST Framework (DRF) 作为后端Vue.js 作为前端的企业管理系统。这套技术栈组合在国内的中小型企业、创业团队以及需要快速验证产品的场景里出镜率相当高。很多人可能觉得这不就是个增删改查CRUD系统吗用现成的框架一搭不就完了但真正上手做一遍从零开始把前后端打通、权限理清、数据交互搞稳定你会发现里面门道不少远不是跑个脚手架命令那么简单。这个项目的核心价值在于它提供了一个全栈、可落地的参考实现。它不仅仅是一个“玩具项目”而是涵盖了企业管理系统中最常见、也最棘手的几个模块用户权限管理RBAC、部门组织架构、员工信息管理、以及基础的审批流程雏形。前端用 Vue 3 的 Composition API 配合 Element Plus 组件库构建出清晰、响应式的管理界面后端则依托 Django 强大的 ORM 和 DRF 稳健的序列化与视图机制构建出结构清晰、易于扩展的 RESTful API。更重要的是这套代码展示了如何将这两大技术栈优雅地“焊接”在一起处理跨域、认证、错误处理、API文档等工程化细节。对于想从单体应用转型前后端分离或者想深入学习全栈开发的朋友来说这个项目就像一份详细的“地图”告诉你每个路口该怎么走哪里有坑。2. 技术栈选型深度剖析为什么是 Django DRF Vue在启动任何项目前技术选型都是决定后续开发效率和维护成本的关键。为什么在这个企业管理系统里我们选择了 Django DRF Vue 这套组合拳这背后是一系列权衡和现实考量。2.1 后端Django 与 DRF 的“黄金搭档”首先看后端。Python 的 Django 框架以其“开箱即用”和“功能齐全”著称。对于企业管理这类业务逻辑明确、数据模型复杂的系统Django 的 ORM 能极大提升开发效率。你不需要手写复杂的 SQL 语句用 Python 类就能定义数据表结构并且自带强大的查询 API、数据迁移工具和后台管理界面Admin。这对于快速原型开发和初期数据管理非常友好。然而纯 Django 更适合传统的服务端渲染模式。在前后端分离架构中我们需要的是纯粹的数据接口。这时Django REST Framework (DRF) 就登场了。DRF 不是替代 Django而是基于 Django 构建的一套专门用于开发 Web API 的强大工具包。它的核心价值在于序列化Serializers这是 DRF 的灵魂。它优雅地解决了 Django 模型Model与 JSON 数据之间的双向转换问题。你可以在序列化器中定义字段的验证规则、读写权限、关联数据的嵌套展示方式等。例如在员工信息接口中你可以轻松地将员工模型及其关联的部门信息一次性序列化成前端需要的 JSON 结构。视图集ViewSets与路由器RoutersDRF 的ModelViewSet配合SimpleRouter或DefaultRouter可以用极少的代码自动生成一套完整的 CRUD API 端点Endpoints。这避免了为每个模型重复编写类似的视图函数保证了 API 风格的一致性。认证与权限Authentication Permissions企业系统对安全要求高。DRF 内置了多种认证方案Token、Session、JWT等和权限类IsAuthenticated, IsAdminUser, DjangoModelPermissions等。我们可以很方便地组合使用实现例如“普通员工只能查看自己部门数据部门经理可以管理本部门超级管理员拥有全部权限”这样的复杂 RBAC 逻辑。丰富的生态与可测试性DRF 有完善的文档、活跃的社区并且其基于类的视图CBV设计使得编写单元测试和集成测试非常方便这对于保证企业应用的质量至关重要。选择 Django DRF意味着你选择了“稳健”和“高效”。它可能不是性能极限最高的如 Go 或 Rust也不是最“新潮”的如 FastAPI但它提供了最全面的解决方案和最少的“踩坑”风险特别适合需要快速上线且长期维护的业务系统。2.2 前端Vue 3 与 Element Plus 的“效率引擎”前端选择 Vue尤其是 Vue 3是看中了其渐进式和高开发者友好度的特点。对于后端开发人员转型全栈或者团队中后端人员较多的情况Vue 的学习曲线相对平缓模板语法直观更容易上手。Composition APIVue 3 的 Composition API 是本次项目的重点。相比于 Vue 2 的 Options APIComposition API 允许我们将逻辑关注点如获取用户列表、处理表单提交组织成可复用的函数composable而不是分散在data,methods,computed等选项中。这使得代码在应对复杂业务逻辑时依然能保持清晰和可维护性。例如我们可以抽离一个useUserManagement函数专门处理所有与用户相关的数据获取、增删改查逻辑然后在多个组件中复用。状态管理对于企业管理系统前端状态管理是必须考虑的。虽然 Vuex 是经典选择但在 Vue 3 生态中Pinia 因其更简洁的 API、更好的 TypeScript 支持以及模块化的设计成为了更受欢迎的选择。在本项目中我们使用 Pinia 来集中管理用户登录状态、权限信息、全局配置等数据确保数据流清晰可控。UI 组件库Element Plus 是基于 Vue 3 的桌面端组件库它提供了丰富、美观且功能强大的 UI 组件如表格、表单、对话框、导航菜单等。使用它我们可以将主要精力放在业务逻辑实现上而不是重复造轮子去实现一个日期选择器或分页组件。它的设计风格也符合大多数企业管理后台的审美需求。构建工具我们使用 Vite 作为构建工具而不是传统的 Vue CLI。Vite 提供了闪电般的冷启动和热更新速度极大地提升了开发体验。它的配置也更简单、更现代。前后端分离的协同选定了 Vue 作为前端前后端就彻底解耦了。后端只提供 API前端通过 Axios 等 HTTP 客户端库来消费这些 API。这种模式让前后端团队可以并行开发定义好 API 接口文档我们使用 DRF 自动生成的 API 文档或 Swagger后前端就可以模拟数据进行开发后端则可以专注于业务逻辑和数据安全。部署时前端编译成静态文件HTML, CSS, JS由 Nginx 等服务后端则由 uWSGI/Gunicorn Nginx 作为应用服务器两者完全独立。3. 项目架构设计与核心模块拆解一个清晰的项目结构是长期可维护性的基石。下面我们来拆解这个前后端分离项目的目录结构和核心模块是如何组织的。3.1 后端项目结构enterprise_backend/ ├── manage.py ├── requirements.txt ├── .env # 环境变量配置数据库密码、密钥等 ├── config/ # 项目主配置目录 │ ├── __init__.py │ ├── settings.py # 拆分后的设置文件 │ ├── urls.py # 主路由 │ └── wsgi.py ├── apps/ # 核心应用目录 │ ├── users/ # 用户认证与权限应用 │ │ ├── models.py # 用户、角色、权限模型 │ │ ├── serializers.py # 用户序列化器 │ │ ├── views.py # 用户相关视图集 │ │ ├── permissions.py # 自定义权限类 │ │ └── urls.py │ ├── department/ # 部门组织架构应用 │ ├── employee/ # 员工信息管理应用 │ └── common/ # 公共应用工具函数、常量、自定义异常等 ├── utils/ # 项目级工具类 │ ├── pagination.py # 自定义分页类 │ ├── response.py # 统一API响应格式 │ └── exceptions.py # 自定义异常处理器 └── static/ # 静态文件如果需要关键设计点应用App拆分遵循 Django 的“一个应用负责一个核心功能”的原则。users应用专门处理所有与用户、认证、授权相关的事情department和employee则处理具体业务。这样拆分使得代码职责清晰便于团队协作和后期微服务化拆分如果需要。配置分离将settings.py中的敏感信息如SECRET_KEY,DATABASE_URL通过环境变量.env文件管理并使用django-environ库读取。同时可以将开发、测试、生产环境的配置进行分离。统一响应格式在utils/response.py中定义一个如JsonResponse的类确保所有 API 接口返回的数据格式一致例如{‘code’: 200, ‘message’: ‘success’, ‘data’: {}}。这极大方便了前端进行统一处理。自定义分页DRF 自带分页但样式可能不符合前端需求。在utils/pagination.py中自定义一个分页类可以控制返回的字段名如page,page_size,total,list使其与 Element Plus 的表格分页组件完美对接。3.2 前端项目结构enterprise_frontend/ ├── public/ ├── index.html ├── package.json ├── vite.config.js # Vite 配置 ├── .env.development # 开发环境变量 ├── .env.production # 生产环境变量 ├── src/ │ ├── api/ # 所有API请求封装 │ │ ├── index.js # 创建Axios实例配置拦截器 │ │ ├── user.js # 用户相关接口 │ │ ├── department.js │ │ └── employee.js │ ├── assets/ # 静态资源 │ ├── components/ # 公共组件 │ │ ├── Layout/ # 布局组件侧边栏、头部 │ │ ├── Table/ # 封装了高级功能的表格组件 │ │ └── Form/ # 动态表单生成组件 │ ├── composables/ # Composition API 可复用逻辑 │ │ ├── useTable.js # 表格数据获取、分页、搜索逻辑 │ │ └── useForm.js # 表单提交、验证、重置逻辑 │ ├── layouts/ # 页面布局如 MainLayout.vue │ ├── router/ # Vue Router 配置 │ ├── stores/ # Pinia 状态管理 │ │ ├── index.js # Pinia 主文件 │ │ ├── user.js # 用户状态token, userInfo, permissions │ │ └── app.js # 应用全局状态主题、尺寸等 │ ├── styles/ # 全局样式 │ ├── utils/ # 工具函数日期格式化、权限校验等 │ ├── views/ # 页面视图组件 │ │ ├── Login.vue # 登录页 │ │ ├── Dashboard.vue # 首页 │ │ ├── User/ # 用户管理相关页面 │ │ │ ├── index.vue # 用户列表 │ │ │ └── Edit.vue # 用户编辑/新增 │ │ ├── Department/ # 部门管理页面 │ │ └── Employee/ # 员工管理页面 │ └── main.js # 应用入口关键设计点API 层抽象在src/api/目录下将不同模块的接口请求函数封装起来。这样做的好处是前端组件中不再出现直接的axios.get(‘/api/users/’)这样的代码而是调用getUserList(params)这样的函数。当后端接口路径或请求方式发生变化时只需修改这一个文件维护性极佳。Composables 逻辑复用这是 Vue 3 Composition API 的精髓。useTable可以封装表格页的通用逻辑初始化加载数据、处理分页参数、处理搜索和筛选、监听查询条件变化自动重新请求。这样在User/index.vue和Employee/index.vue中我们只需几行代码就能获得一个功能完整的表格页面。状态管理Pinia将全局的、需要跨组件共享的数据放入 Pinia Store。例如用户登录后将 token 和用户信息存入userStore。任何需要判断用户权限或显示用户名的组件都可以直接从 store 中获取无需层层传递 props。路由与权限控制在router/index.js中我们配置动态路由。结合 Pinia 中的用户权限信息在全局路由守卫中判断用户是否有权访问某个页面实现前端层面的权限控制。对于无权限的访问可以重定向到 403 页面或登录页。4. 核心功能实现详解与避坑指南有了清晰的架构接下来我们深入几个核心功能的实现细节并分享一些实际开发中容易踩的“坑”。4.1 用户认证与权限控制RBAC的实现这是企业管理系统的安全基石。我们采用JWT (JSON Web Token)作为无状态认证方案。后端实现DRF安装依赖使用djangorestframework-simplejwt库它提供了完整的 JWT 签发与验证功能。配置在settings.py中配置 JWT 认证后端并设置 token 的有效期。# settings.py REST_FRAMEWORK { DEFAULT_AUTHENTICATION_CLASSES: ( rest_framework_simplejwt.authentication.JWTAuthentication, ), DEFAULT_PERMISSION_CLASSES: ( rest_framework.permissions.IsAuthenticated, # 默认需要认证 ), } SIMPLE_JWT { ACCESS_TOKEN_LIFETIME: timedelta(hours2), REFRESH_TOKEN_LIFETIME: timedelta(days7), # ... 其他配置 }登录视图simplejwt提供了TokenObtainPairView来获取 access/refresh token。我们通常会继承它自定义返回的数据格式比如除了 token还要返回用户基本信息、菜单权限列表等。权限模型设计在users/models.py中我们设计经典的 RBAC 模型User(用户) -Role(角色) -Permission(权限)。一个用户有多个角色一个角色有多个权限。权限可以关联到具体的 Django 模型和操作add, change, delete, view。自定义权限类DRF 的DjangoModelPermissions是基于 Django 的权限系统但有时不够灵活。我们需要在users/permissions.py中编写自定义权限类例如IsDepartmentAdmin用于判断当前用户是否是某个部门的负责人。前端实现Vue Pinia登录流程在登录页面调用api/user.js中的login函数。成功后将返回的access_token和refresh_token存储到localStorage或cookie注意 HttpOnly 安全性同时将用户信息和权限列表存入userStore。请求拦截器在src/api/index.js中创建 Axios 实例并设置请求拦截器在每次请求的 header 中自动添加Authorization: Bearer access_token。Token 刷新机制这是 JWT 无状态的一个挑战。当access_token过期后后端会返回 401 错误。此时在响应拦截器中捕获这个错误尝试用refresh_token调用刷新接口获取新的access_token然后重试失败的请求。这个过程对用户应该是无感的。如果refresh_token也过期了则跳转到登录页。// src/api/index.js service.interceptors.response.use( (response) response, async (error) { const originalRequest error.config; if (error.response?.status 401 !originalRequest._retry) { originalRequest._retry true; try { // 调用刷新token的接口 const { data } await refreshToken(); // 更新store和localStorage中的新token userStore.updateToken(data.access); // 用新token重试原请求 originalRequest.headers.Authorization Bearer ${data.access}; return service(originalRequest); } catch (refreshError) { // 刷新失败跳转登录 userStore.logout(); router.push(/login); return Promise.reject(refreshError); } } return Promise.reject(error); } );前端路由权限在router的全局守卫中根据userStore中的权限列表动态匹配用户有权访问的路由并过滤菜单。对于无权限的路由访问进行拦截。避坑指南Token 存储安全access_token可以存于内存或localStorage但refresh_token最好通过 HttpOnly Cookie 发送防止 XSS 攻击窃取。simplejwt支持将 refresh token 设置为 HttpOnly cookie。权限粒度不要过度设计。初期可以粗粒度一些如页面级、模块级随着业务复杂再细化到按钮级。按钮级权限可以通过前端自定义指令v-permission来实现根据权限列表控制元素的显示与隐藏。并发请求与 Token 刷新当多个请求同时发生且 token 过期时可能会触发多次刷新请求造成混乱。需要用一个标志位如isRefreshing和请求队列来管理确保只刷新一次。4.2 前后端数据交互与 API 设计规范清晰、一致的 API 设计是前后端高效协作的前提。后端 API 设计DRFURL 规范使用 RESTful 风格。资源使用复数名词动词由 HTTP 方法表示。GET /api/users/- 获取用户列表POST /api/users/- 创建新用户GET /api/users/{id}/- 获取单个用户详情PUT /api/users/{id}/- 更新整个用户信息PATCH /api/users/{id}/- 部分更新用户信息DELETE /api/users/{id}/- 删除用户序列化器嵌套与性能当需要返回关联数据时如员工信息中包含部门名称可以使用序列化器嵌套。但要警惕 N1 查询问题。DRF 提供了select_related(用于外键) 和prefetch_related(用于多对多) 来优化需要在视图的queryset中主动使用。# views.py class EmployeeViewSet(ModelViewSet): queryset Employee.objects.select_related(department).all() serializer_class EmployeeSerializer过滤、搜索与排序对于列表接口过滤、搜索和排序是刚需。推荐使用django-filter库它可以方便地与 DRF 集成在视图集中通过filterset_class定义过滤字段。搜索可以使用 DRF 的SearchFilter排序使用OrderingFilter。分页使用自定义的分页类返回格式与前端组件期望的格式对齐。API 文档DRF 自带可浏览的 API 页面但对于前后端协作更推荐使用drf-yasg或drf-spectacular自动生成 OpenAPI (Swagger) 文档界面更友好也便于前端调试。前端数据交互Vue Axios统一错误处理在 Axios 的响应拦截器中除了处理 token 过期还要统一处理网络错误、服务器错误5xx、业务逻辑错误后端返回的特定错误码如 4001 表示参数错误。将错误信息以友好的方式提示给用户例如使用 Element Plus 的ElMessage。请求取消在用户频繁操作时如快速切换筛选条件上一个请求可能还未完成新的请求又发出了。这可能导致数据显示错乱。可以使用 Axios 的 CancelToken 或 AbortController 来取消未完成的请求。表单数据处理对于复杂表单如创建员工需要上传头像使用FormData对象进行提交。Element Plus 的ElUpload组件可以很好地配合。加载状态管理在调用 API 时为按钮或表格添加 loading 状态提升用户体验。可以在useTable这个 composable 中统一管理表格的loading状态。避坑指南时间格式前后端对时间的序列化格式要统一建议使用 ISO 8601 格式字符串如”2023-10-27T10:30:00Z“。前端显示时再用dayjs或moment库进行格式化。大数字精度丢失JavaScript 的Number类型在处理后端返回的过大的整数如雪花算法生成的 64 位 ID时可能会丢失精度。解决方案是后端将这类字段以字符串类型返回。API 版本管理在项目初期就要考虑 API 版本化。可以在 URL 中体现如/api/v1/users/也可以在请求头中指定。这为后续不兼容的 API 升级留有余地。4.3 前端复杂表格与表单的工程化实践企业管理后台几乎就是表格和表单的“集合”。如何高效、优雅地处理它们是前端工程化的重点。高性能表格Element Plus Table 虚拟滚动 Element Plus 的ElTable功能强大但当数据量巨大成千上万行时一次性渲染会导致页面卡顿。解决方案是使用虚拟滚动。虚拟滚动原理只渲染可视区域内的表格行随着滚动动态替换内容。这可以借助vue-virtual-scroller这类库实现或者使用 Element Plus 表格的v-infinite-scroll指令进行无限滚动加载分页的另一种形式。自定义表格组件在components/Table/下封装一个高级表格组件。它接收列配置columns、数据源data、加载状态loading等 props。内部集成分页器列显示隐藏控制列排序自定义列模板插槽行选择功能 这样在业务页面中我们只需要配置列和数据源大大减少了重复代码。!-- User/index.vue -- template AdvancedTable :columnstableColumns :datatableData :loadingloading selection-changehandleSelectionChange !-- 自定义操作列 -- template #action{ row } el-button clickeditUser(row)编辑/el-button /template /AdvancedTable /template动态表单与验证 员工信息表单字段可能非常多且不同角色看到的字段可能不同。手动编写每个ElFormItem是低效的。表单配置化我们可以设计一个表单配置描述数组formConfig每个元素描述一个表单项的标签、字段名、组件类型input, select, date-picker等、验证规则等。const formConfig [ { label: 姓名, prop: name, component: el-input, rules: [{ required: true }] }, { label: 部门, prop: department_id, component: el-select, options: departmentList }, // ... 更多配置 ];动态渲染组件创建一个DynamicForm.vue组件它接收formConfig和formData利用 Vue 的component动态组件来循环渲染出完整的表单。这样增删改查表单都可以复用这个组件只需传入不同的配置。表单验证结合 Element Plus 表单的rules属性和async-validator库实现前后端统一的验证逻辑。复杂的联动验证如选择 A 后B 字段必填可以在配置中通过函数实现。避坑指南表格数据更新当使用composables/useTable获取数据后直接赋值给响应式变量tableData视图会自动更新。但如果遇到视图不更新的情况检查是否是响应式丢失了例如对数组进行了this.tableData[index] newItem这样的操作应使用Vue.set或数组的splice方法。表单重置在打开编辑对话框填充了数据后关闭对话框时需要彻底清空表单数据和验证状态。Element Plus 的ElForm提供了resetFields()方法但它依赖于初始的model值。更可靠的做法是在对话框关闭时手动将formData对象重置为一个新的空对象{}并调用resetFields()。文件上传处理文件上传时记得在 Axios 请求头中设置‘Content-Type’: ‘multipart/form-data’。同时后端 DRF 需要使用MultiPartParser来解析请求。4.4 项目部署与运维要点开发完成只是第一步让应用稳定运行在生产环境同样重要。后端部署Linux Nginx Gunicorn环境准备在服务器上安装 Python、Pip、虚拟环境venv、数据库如 PostgreSQL/MySQL、Nginx。项目部署将代码拉取到服务器创建虚拟环境并安装依赖 (pip install -r requirements.txt)。收集静态文件运行python manage.py collectstatic将 Django 的静态文件收集到指定目录供 Nginx 服务。数据库迁移运行python manage.py migrate应用数据迁移。使用 Gunicorn 作为应用服务器Gunicorn 是一个 WSGI HTTP 服务器比 Django 自带的开发服务器更适合生产环境。# 启动Gunicorn监听在本地8000端口 gunicorn config.wsgi:application -w 4 -b 127.0.0.1:8000-w 4表示启动 4 个工作进程根据服务器 CPU 核心数调整。配置 Nginx 作为反向代理Nginx 处理静态文件并将动态请求转发给 Gunicorn。server { listen 80; server_name your_domain.com; location /static/ { alias /path/to/your/staticfiles/; } location /media/ { # 如果有用户上传的文件 alias /path/to/your/media/; } location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }进程管理使用 Systemd 或 Supervisor 来管理 Gunicorn 进程实现开机自启和异常重启。前端部署构建生产版本在项目根目录运行npm run buildVite 项目或vue-cli-service build。这会在dist目录生成优化后的静态文件。部署静态文件将dist目录下的所有文件上传到服务器可以由一个专门的静态文件服务器如 Nginx提供服务也可以和后端共用同一个 Nginx推荐。# 在同一个Nginx配置中添加前端路由处理 server { listen 80; server_name your_domain.com; # 静态资源前端构建产物 location / { root /path/to/frontend/dist; try_files $uri $uri/ /index.html; # 支持Vue Router的history模式 } # 后端API代理 location /api/ { proxy_pass http://127.0.0.1:8000; # ... 其他proxy设置 } # 后端静态文件Django admin等 location /static/ { alias /path/to/backend/staticfiles/; } }关键指令try_files $uri $uri/ /index.html;确保了在直接访问前端路由如/user/list时Nginx 会返回index.html由 Vue Router 来处理路由避免了 404 错误。运维与监控日志配置 Django 的日志系统将错误日志、访问日志记录到文件。使用logging模块并设置合理的日志轮转。数据库备份定期对数据库进行备份可以使用pg_dump(PostgreSQL) 或mysqldump(MySQL) 命令并结合 cron 任务自动化。性能监控简单的监控可以使用django-debug-toolbar仅限开发环境或sentry错误追踪。对于更全面的监控可以考虑接入 APM 工具。安全加固确保DEBUGFalse设置正确的ALLOWED_HOSTS使用 HTTPS通过 Let‘s Encrypt 申请免费 SSL 证书定期更新依赖库以修复安全漏洞。避坑指南跨域问题CORS在开发阶段前后端分离必然遇到跨域。后端需要安装django-cors-headers库并正确配置CORS_ALLOWED_ORIGINS。在生产环境如果前后端同域通过 Nginx 反向代理则不存在跨域问题。静态文件 404确保 Nginx 配置中的alias或root路径正确并且运行collectstatic的用户对静态文件目录有读取权限。Vue Router History 模式如前所述必须配置 Nginx 的try_files指令否则刷新非根路径页面会 404。环境变量生产环境的数据库密码、密钥等绝不能写在代码里。使用.env.production文件前端和环境变量后端来管理并在部署脚本中正确设置。本文还有配套的精品资源点击获取
返回列表