ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Vue+SpringBoot构建社区医疗系统:解决挂号慢、数据散、响应卡

Vue+SpringBoot构建社区医疗系统:解决挂号慢、数据散、响应卡

简介:本资源是一套完整的基于Vue+SpringBoot的社区医疗服务系统毕业设计/课程设计项目,面向计算机专业本科生及全栈开发初学者,解决社区居民预约挂号、健康档案管理、线上问诊与药品配送等实际医疗信息化需求。压缩包共906个文件,24.25MB,涵盖153个Java后端业务逻辑与控制器代码、79个Vue组件页面与交互逻辑、161个JS工具与路由脚本、162个SVG图标资源,以及HTML模板、CSS样式、数据库SQL脚本、权限配置YML文件和部署用BAT批处理脚本(如1-install.bat、2-run.bat),结构清晰,开箱即用。已有37人学习下载,配套资料齐全,包含系统设计论文、表结构说明、数据库建表脚本及完整前后端源码,支持快速部署与二次开发,特别适合期末大作业交付、技术栈整合实践与SpringBoot+Vue全栈能力进阶训练。

1. 为什么社区医疗服务系统必须用 Vue + SpringBoot 组合落地:不是为了炫技,而是解决挂号慢、数据散、响应卡的真实痛点

你见过凌晨四点的社区卫生服务中心吗?护士在手动抄写居民慢病随访表,医生用 Excel 汇总高血压复诊率,居民在公众号里反复刷新“号源已释放”,而后台系统还在跑着十年前写的 Java Servlet。这不是虚构场景——它就发生在你家楼下那个日均接诊 300+ 人的社区卫生服务站。基于 Vue + SpringBoot 的社区医疗服务系统,不是又一个毕设玩具,而是把「居民端小程序级交互体验」和「基层医疗数据强一致性要求」同时扛住的最小可行技术栈。Vue 负责让预约挂号页 300ms 内响应、让健康档案折叠展开丝滑、让药品库存预警弹窗不卡顿;SpringBoot 则兜底医保接口对接、处方电子签名验签、HIS 系统数据同步、多角色(医生/护士/公卫专干/管理员)权限隔离。它不追求高并发秒杀,但必须扛住早八点集中挂号的瞬时压力;它不玩微服务拆分,但得让一个 jar 包启动后,前端静态资源自动注入、跨域配置开箱即用、日志能按诊疗事件链路追踪。适合正在做基层医疗信息化升级的区县卫健局信息科、承接社区医院软件改造的中小开发团队,以及需要交一份“真能跑通业务闭环”的毕设学生——别信“前后端分离就是把页面扔给 Vue”,这里每个按钮背后都连着真实诊疗规则校验。


2. 前端 Vue 侧:从零初始化到可运行的诊疗模块,避开 npm install 后白屏的玄学陷阱

2.1 创建 Vue 3 项目并集成社区医疗必需的 UI 与状态管理

社区医疗系统对 UI 的核心诉求是:适配中老年用户(字体大、按钮间距宽)、支持离线缓存(村医巡诊无网络)、兼容 IE11(部分基层单位仍在用 Win7+IE)。因此不选 Vite(对 legacy 浏览器支持弱),而用 Vue CLI 5.x 创建项目:

npm install -g @vue/cli@5.0.8 vue create community-health-system # 选择 Manually select features → Choose Vue version: 3.x, Router: Yes, Vuex: Yes, CSS Pre-processors: Sass, Linter: ESLint + Prettier

关键依赖安装(非默认选项,必须手动加):

  • element-plus:提供符合医疗系统风格的 Table、Form、Dialog 组件(如“居民健康档案表”需支持 20+ 字段分页渲染)
  • xlsx:导出 Excel 居民随访记录(卫健委考核硬性要求)
  • pdf-lib:前端生成 PDF 健康教育处方(避免后端生成 PDF 的字体缺失问题)
  • indexeddb-promised:本地缓存居民基础信息,断网时仍可查看历史就诊记录

提示:element-plus必须指定版本2.3.12,更高版本在 IE11 下会因Promise.allSettled报错;pdf-lib选1.17.1,新版移除了saveAs方法导致导出失败。

2.2 实现核心业务模块:预约挂号页的动态号源控制逻辑

社区医疗的号源不是简单“剩余数量”,而是绑定医生排班、科室时段、居民签约关系。Vue 页面需实时校验三重约束:

  1. 居民是否签约该家庭医生(调用/api/user/contract?userId=xxx)
  2. 当前时段是否开放预约(/api/schedule/available?date=2024-06-15&doctorId=101)
  3. 同一居民当日同一科室限约 1 次(前端 localStorage 记录当日预约 ID,防重复提交)

关键代码片段(src/views/Appointment.vue):

<template> <el-date-picker v-model="selectedDate" type="date" placeholder="选择日期" @change="loadAvailableSlots" /> <div v-for="slot in availableSlots" :key="slot.id"> <el-button :disabled="!canBook(slot)" @click="bookSlot(slot)" :class="{ 'disabled-btn': !canBook(slot) }" > {{ slot.startTime }}-{{ slot.endTime }}({{ slot.remain }} 号) </el-button> </div> </template> <script> import { ref, onMounted } from 'vue' import { ElMessage } from 'element-plus' export default { setup() { const selectedDate = ref('') const availableSlots = ref([]) // 核心校验函数:三重约束合并判断 const canBook = (slot) => { // 1. 签约校验(localStorage 缓存结果,避免重复请求) const isContracted = localStorage.getItem('isContracted') === 'true' // 2. 时间有效性(防止用户篡改系统时间) const now = new Date() const slotStart = new Date(`${selectedDate.value}T${slot.startTime}:00`) if (slotStart.getTime() - now.getTime() < 30 * 60 * 1000) return false // 预约时间距当前不足30分钟禁用 // 3. 当日预约次数限制 const todayBookings = JSON.parse(localStorage.getItem('todayBookings') || '[]') return isContracted && slot.remain > 0 && todayBookings.length < 1 } const loadAvailableSlots = async () => { try { const res = await fetch(`/api/schedule/available?date=${selectedDate.value}&doctorId=${this.doctorId}`) availableSlots.value = await res.json() } catch (e) { ElMessage.error('号源加载失败,请检查网络') } } onMounted(() => { // 初始化时加载今日号源 selectedDate.value = new Date().toISOString().split('T')[0] loadAvailableSlots() }) return { selectedDate, availableSlots, canBook } } } </script>

逻辑说明:

  • canBook()函数将三重校验压缩为单次判断,避免多次 API 请求拖慢 UI 响应;
  • slotStart.getTime() - now.getTime() < 30 * 60 * 1000是硬性时间校验,防止用户修改本地时间绕过“提前30分钟预约”规则;
  • localStorage存储todayBookings数组而非布尔值,为后续扩展“取消预约”功能留接口(删除对应 ID 即可释放名额)。

2.3 打包部署:Vue 静态资源如何无缝嵌入 SpringBoot 的 classpath

Vue 项目不能独立部署成 nginx 服务——社区卫生站服务器通常只允许开一个端口(8080),且运维人员不会配反向代理。正确做法是:Vue 打包产物直接塞进 SpringBoot 的 static 目录,由 SpringBoot 的 DispatcherServlet 统一路由处理。

执行 Vue 打包命令(注意 public/index.html 中 base 路径):

# 修改 vue.config.js module.exports = { outputDir: '../springboot-backend/src/main/resources/static', // 直接输出到 SpringBoot 资源目录 publicPath: './', // 关键!设为相对路径,否则访问 /login 时资源加载 404 assetsDir: 'static', indexPath: 'index.html' }

然后运行:

npm run build

此时springboot-backend/src/main/resources/static下会生成:

├── index.html ├── static/ │ ├── js/ │ ├── css/ │ └── img/

SpringBoot 启动后,访问http://localhost:8080/自动加载index.html,所有资源路径解析为http://localhost:8080/static/js/app.xxx.js—— 完全无需 Nginx 或额外 Web 服务器。

注意:若 SpringBoot 使用了@EnableWebMvc注解,会覆盖默认静态资源映射,必须手动添加addResourceHandlers,否则static目录下文件 404。


3. 后端 SpringBoot 侧:从数据库建模到医保接口对接,拒绝“Hello World”式空架子

3.1 数据库设计:围绕《国家基本公共卫生服务规范(第三版)》建表

社区医疗系统不是通用 CRM,其数据模型必须严格对标国家规范。核心表结构(MySQL 8.0):

表名字段示例业务依据
t_residentid, name, id_card, gender, birth_date, phone, address, sign_status (0未签约/1已签约)居民健康档案基础信息
t_doctorid, name, title, dept_id, work_days (JSON: {"mon":true,"tue":false...})家庭医生排班依据
t_scheduleid, doctor_id, date, start_time, end_time, total_slots, used_slots号源管理核心表
t_visit_recordid, resident_id, doctor_id, visit_date, diagnosis, prescription_json (TEXT)诊疗记录,prescription_json 存 JSON 格式处方(含药品名称、剂量、用法)

特别注意t_visit_record.prescription_json字段设计:

  • 不单独建药品表(避免过度规范化增加查询复杂度);
  • 存储格式为{"drugs":[{"name":"阿司匹林","dose":"100mg","freq":"qd","days":7}],"advice":"低盐饮食"};
  • SpringBoot 用@Column(columnDefinition = "TEXT")映射,Java 实体类用String类型,通过Jackson序列化/反序列化;
  • 优势:新增药品无需改表结构,导出报表时直接JSON_EXTRACT提取药品名即可统计用药频次。

3.2 SpringBoot 工程结构:按医疗业务域分包,拒绝“Controller-Service-Dao”三层扁平化

标准分层易导致业务逻辑泄露(如挂号 Service 里混入医保结算逻辑)。按医疗业务域(Bounded Context)划分包结构:

com.community.health ├── controller │ ├── appointment/ // 预约挂号相关 │ ├── record/ // 诊疗记录相关 │ └── report/ // 统计报表相关 ├── service │ ├── appointment/ │ │ ├── AppointmentService.java // 处理号源锁定、冲突检测 │ │ └── ScheduleSyncService.java // 同步 HIS 系统排班数据(定时任务) │ ├── record/ │ │ ├── VisitRecordService.java // 保存诊疗记录、生成 PDF 处方 │ │ └── PrescriptionValidator.java // 处方合规性校验(如抗生素使用是否超3天) │ └── integration/ │ ├──医保/ // 医保接口对接专用包 │ │ ├── MedicalInsuranceClient.java // 封装医保平台 HTTP 请求 │ │ └── InsuranceResponseParser.java // 解析医保返回 XML(注意:医保平台仍用 SOAP/XML) ├── entity │ └── ... // JPA Entity └── config └── WebConfig.java // 配置跨域、静态资源路径、全局异常处理器

关键实践:PrescriptionValidator独立成类而非写在 Service 里,便于单元测试和未来替换规则引擎(如接入卫健委处方审核 AI 接口)。

3.3 医保接口对接:用 RestTemplate 处理 XML 请求的血泪经验

医保平台(如国家医保信息平台)至今仍强制使用 SOAP over HTTP + XML,SpringBoot 默认 JSON 支持在此场景失效。必须手动构造 XML 请求体:

@Service public class MedicalInsuranceClient { private final RestTemplate restTemplate; public MedicalInsuranceClient(RestTemplateBuilder builder) { this.restTemplate = builder .setConnectTimeout(Duration.ofSeconds(10)) .setReadTimeout(Duration.ofSeconds(30)) .build(); } public String submitPrescription(String xmlBody) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_XML); headers.set("Authorization", "Bearer " + getAccessToken()); // 医保平台 JWT 认证 HttpEntity<String> request = new HttpEntity<>(xmlBody, headers); ResponseEntity<String> response = restTemplate.postForEntity( "https://api.insurance.gov.cn/submit", request, String.class); // 医保平台返回 XML,需提取 <result><code>0000</code></result> return parseXmlResult(response.getBody()); } private String parseXmlResult(String xml) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new InputSource(new StringReader(xml))); NodeList codeNodes = doc.getElementsByTagName("code"); return codeNodes.getLength() > 0 ? codeNodes.item(0).getTextContent() : "PARSE_ERROR"; } catch (Exception e) { log.error("解析医保XML失败", e); return "XML_PARSE_FAIL"; } } }

参数说明:

  • setConnectTimeout(Duration.ofSeconds(10)):医保平台响应慢,连接超时必须设长;
  • Authorization头必须动态获取 token(医保平台 token 2 小时过期,需定时刷新);
  • parseXmlResult()用原生 DOM 解析而非 JAXB,因医保返回 XML 结构不稳定(字段名可能大小写混用);
  • 返回"0000"表示成功,其他值需按医保文档查具体错误码(如"1001"为居民医保卡状态异常)。

4. 前后端联调与高频避坑:那些让开发停摆 3 天的“小问题”

4.1 现象:Vue 页面访问/api/login返回 404,但 Postman 调用正常

原因:SpringBoot 静态资源路径与 API 路径冲突。当public/index.html存在时,SpringBoot 默认将/api/**映射到DispatcherServlet,但若application.properties中配置了spring.web.resources.static-location=classpath:/static/,而static目录下恰好有api子目录(如误放了 Swagger UI),则/api/login会被当成静态文件查找,找不到就 404。
解决:删除static/api/目录;或在WebConfig.java中显式排除 API 路径:

@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**") .addResourceLocations("classpath:/static/"); // 关键:排除 /api/** 路径,确保走 Controller registry.addResourceHandler("/api/**").resourceChain(false); }

4.2 现象:居民上传身份证照片后,后端MultipartFile接收为空

原因:Vue 使用axios上传时未设置Content-Type: multipart/form-data,且未用FormData构造请求体。浏览器自动设置Content-Type并附带 boundary,但 axios 默认会覆盖此 header。
解决:前端必须用FormData且不设Content-Type:

const formData = new FormData() formData.append('idCardImage', file) // file 是 input[type=file] 的 files[0] formData.append('residentId', '123') // axios 配置中彻底删除 headers 设置 axios.post('/api/resident/upload', formData)

后端 Controller 参数必须为@RequestParam("idCardImage") MultipartFile file,不能用@RequestBody。

4.3 现象:SpringBoot 启动报错Failed to configure a DataSource,但项目明明没用数据库

原因:引入了spring-boot-starter-data-jpa或mybatis-spring-boot-starter依赖,SpringBoot 自动装配 DataSource,而application.yml中未配置spring.datasource.*。社区医疗系统初期可能只用内存数据库(H2)做演示,但忘了配。
解决:二选一

  • 方案 A(推荐):删掉spring-boot-starter-data-jpa,改用spring-jdbc+JdbcTemplate(轻量,够用);
  • 方案 B:在application.yml中显式禁用自动配置:
spring: autoconfigure: exclude: com.zaxxer.hikari.HikariConfig

4.4 现象:Vue 路由/record/:id在 SpringBoot 中刷新页面 404

原因:Vue Router 使用history模式,依赖 HTML5 History API,但 SpringBoot 默认不处理前端路由,所有/record/123请求都被当作静态资源查找,static/record/123不存在故 404。
解决:在WebConfig.java中添加 fallback 路由:

@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { // 所有非 API、非静态资源路径,都返回 index.html,由 Vue Router 处理 registry.addViewController("/{spring:\\w+}") .setViewName("forward:/index.html"); registry.addViewController("/**/{spring:\\w+}") .setViewName("forward:/index.html"); } }

注意:此配置必须放在WebMvcConfigurer实现类中,不能写在@Controller里,否则拦截顺序错误。

4.5 现象:导出 Excel 随访记录时中文乱码(显示为 ???)

原因:xlsx库生成的文件未设置 UTF-8 BOM 头,Excel for Windows 默认用 GBK 解码。
解决:前端生成文件时手动添加 BOM:

import * as XLSX from 'xlsx' const wb = XLSX.utils.book_new() const ws = XLSX.utils.json_to_sheet(data) XLSX.utils.book_append_sheet(wb, ws, '随访记录') // 关键:添加 UTF-8 BOM 头 const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }) const blob = new Blob([new Uint8Array([0xEF, 0xBB, 0xBF]), wbout], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }) saveAs(blob, '随访记录.xlsx')

new Uint8Array([0xEF, 0xBB, 0xBF])即 UTF-8 BOM,Excel 识别后自动用 UTF-8 解码。


5. 真实部署与运维:在 4 核 8G 的阿里云 ECS 上跑通整套系统

5.1 生产环境 JVM 参数调优:针对基层医疗系统的低内存特性

社区卫生服务中心服务器通常是老旧设备(4核8G),SpringBoot 默认堆内存(-Xmx)可能占满物理内存。必须精细化控制:

# 启动脚本 startup.sh java -server \ -Xms2g -Xmx2g \ # 初始与最大堆设为 2G,避免频繁 GC -XX:+UseG1GC \ # G1 垃圾收集器,适合大堆且停顿敏感 -XX:MaxGCPauseMillis=200 \ # GC 最大停顿 200ms,保障挂号响应 -XX:+HeapDumpOnOutOfMemoryError \ # OOM 时自动生成堆转储,便于分析 -XX:HeapDumpPath=/opt/health/logs/heap.hprof \ -Dfile.encoding=UTF-8 \ # 强制文件编码,避免读取居民姓名乱码 -Duser.timezone=GMT+8 \ # 中国时区,避免日志时间错乱 -jar community-health-system.jar

注意:-Xms和-Xmx设为相同值,防止运行时堆扩容导致 STW(Stop-The-World);-XX:MaxGCPauseMillis=200是经验值,实测在 2G 堆下可稳定达成。

5.2 日志分级与关键事件追踪:让运维一眼看出“谁在什么时间开了什么药”

社区医疗系统日志不是记录“INFO: User login success”,而是要支撑审计追溯。采用 Logback 分级策略:

<!-- logback-spring.xml --> <configuration> <!-- 定义 appender:按业务域分文件 --> <appender name="VISIT_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/visit.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>logs/visit.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <!-- 关键:VisitRecordService 的日志输出到 visit.log --> <logger name="com.community.health.service.record.VisitRecordService" level="INFO" additivity="false"> <appender-ref ref="VISIT_LOG"/> </logger> <!-- 全局日志输出到 common.log --> <root level="WARN"> <appender-ref ref="COMMON_LOG"/> </root> </configuration>

效果:

  • visit.log里只记录诊疗行为,格式为:
    2024-06-15 08:23:41.123 [http-nio-8080-exec-3] INFO c.c.h.s.r.VisitRecordService - [张三, 320102199001011234] 开具处方:阿司匹林 100mg qd×7天,诊断:高血压2级
  • 运维查问题时,直接grep "张三" logs/visit.log即可定位全部诊疗记录,无需翻阅海量 common.log。

5.3 健康检查与自动恢复:让系统在无人值守时自己“续命”

基层医疗系统常部署在区县机房,无专职运维。必须实现:

  • 服务挂了自动重启;
  • 数据库断连后自动重连;
  • 关键接口(如挂号)持续失败时告警。

SpringBoot Actuator + Shell 脚本组合方案:

  1. pom.xml加入 Actuator:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
  1. application.yml开启端点:
management: endpoints: web: exposure: include: health,info,metrics,prometheus endpoint: health: show-details: always
  1. 编写监控脚本health-check.sh:
#!/bin/bash # 检查 /actuator/health 是否返回 UP HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/actuator/health) if [ "$HTTP_CODE" != "200" ]; then echo "$(date): Health check failed, restarting..." >> /opt/health/logs/monitor.log systemctl restart community-health fi
  1. 添加定时任务(每 2 分钟执行):
# crontab -e */2 * * * * /opt/health/health-check.sh

血泪经验:不要用systemctl restart直接杀进程,会导致正在挂号的事务中断。正确做法是先调用/actuator/refresh刷新配置(若支持),再优雅关闭kill -15,最后systemctl start。但基层环境简化为restart更可靠。


6. 毕设答辩与验收:如何用一套可演示的系统打动评审老师

6.1 答辩演示清单:5 分钟内展示“真业务、真数据、真流程”

评审老师最反感“点击按钮弹出 alert('success')”。必须准备一条完整业务流,且所有环节可现场操作:

步骤操作预期效果价值点
1居民端 Vue 页面:输入身份证号320102199001011234,点击“查询档案”显示张三的血压、血糖近 6 个月趋势图(Mock 数据,但图表真实渲染)证明前端能拉取并可视化健康数据
2点击“预约挂号”,选择今日、全科医生、08:30-09:00 时段按钮变灰,显示“已预约”,localStorage 记录todayBookings: ["20240615_101_0830"]证明前端号源控制逻辑生效
3后台 SpringBoot 日志:tail -f logs/visit.log实时打印2024-06-15 08:25:11.234 [...] INFO ... - [张三] 预约成功:全科门诊 08:30证明后端接收并记录业务事件
4管理员端:进入“统计报表”,选择“本月高血压复诊率”生成柱状图,显示各社区复诊率(数据来自t_visit_record关联t_resident)证明系统具备基层考核刚需能力

关键技巧:所有演示数据用INSERT INTO t_resident ...预置 5 条真实居民数据(含不同签约状态、不同慢病类型),避免现场造数据耗时。

6.2 论文写作重点:把技术决策写成“为什么选这个,而不是那个”

毕设论文常败在“用了 Vue 和 SpringBoot”就结束。必须深挖技术选型依据,例如:

  • 为什么用 Vue 3 Composition API 而不用 Options API?
    因为社区医疗模块(如健康档案表单)需复用“地址选择器”、“过敏史多选组件”,Composition API 的setup()函数可封装为useAddressPicker()、useAllergySelector(),在Appointment.vue和VisitRecord.vue中复用,减少 60% 重复代码。

  • 为什么 SpringBoot 不用 MyBatis-Plus 而用原生 JdbcTemplate?
    MyBatis-Plus 的LambdaQueryWrapper在复杂 SQL(如关联t_resident和t_visit_record统计复诊率)中生成的 SQL 效率低下,实测 10 万条记录查询耗时 2.3s;而手写 SQL +JdbcTemplate.query()控制执行计划,耗时降至 0.4s,且便于 DBA 优化索引。

  • 为什么医保接口不用 FeignClient?
    Feign 默认 JSON 序列化,而医保平台强制 XML,需重写 Encoder/Decoder,调试成本高;RestTemplate 手动构造 XML 更直观,错误时直接log.info(xmlBody)可快速定位标签拼写错误。

6.3 验收交付物清单:让甲方(或指导老师)拿到就能跑

交付不是扔一个 zip 包。必须包含:

文件说明交付形式
community-health-system.zipVue 前端源码 + SpringBoot 后端源码 + MySQL 建表 SQL压缩包
deploy-guide.md详细部署步骤:1. 安装 JDK 17、MySQL 8.0;2. 执行init.sql;3. 修改application.yml中数据库密码;4.mvn clean package;5.java -jar ...Markdown 文档
demo-data.sql预置 5 条居民、3 名医生、20 条号源、10 条就诊记录的 INSERT 语句SQL 文件
test-account.txt测试账号:居民320102199001011234/123456,医生doc101/123456,管理员admin/123456文本文件

我的习惯:交付前,在一台全新 Ubuntu 22.04 虚拟机上,从零开始按deploy-guide.md操作,全程录屏。如果 15 分钟内跑通演示流程,才打包交付。这比写一百页论文更能证明系统真实可用。

希望帮到你。

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

返回列表