医院数据大屏前端实战:Bootstrap布局、Ajax加载与表格分页
2026/9/15 12:54:07 网站建设 项目流程

简介:基于Bootstrap和jQuery的医院大数据展示前端源码,面向网页开发者与医院数据可视化项目人员,用于快速搭建医院运营数据的交互看板,直观呈现病人数量、科室就诊量、医疗费用等核心指标,并能适配个人电脑、平板与手机等多种屏幕。资源压缩包共包含79个文件,容量仅1.4兆,其中网页文件5个、脚本文件12个、样式文件5个、图片40张,另附字体和图标资源,页面覆盖总览、慢性病、指标、趋势等常用模块,下载解压后可直接打开网页预览效果。目前已有149人学习下载,源码重点示范了Bootstrap响应式栅格布局、jQuery事件处理与异步数据加载的结合方法,也涉及图表联动、动态筛选、模态框等大数据展示常见交互。通过研读该项目,可以快速掌握前端大屏看板的搭建思路,适用于毕业设计、课程实践或医疗行业数据可视化项目的参考与二次开发。

1. 医院大屏项目里,最值钱的往往不是图表

医院数据大屏这类项目,最容易翻车的不是图表库不会用,而是页面一旦接入真实数据就散架:标题栏错位、表格撑破布局、接口返回结构一变整屏报错。这套 Bootstrap + jQuery 源码没有上重型可视化框架,却把大屏最容易被低估的模块——标题栏、信息卡片、统计表格、分页查询——做成了可以直接复用的结构,它解决的正是从设计稿到可维护前端之间的空白地带。适合三类人:做院内报表系统的前端、需要给运营大屏快速换肤的工程师、以及想用 bootstrap-table 搭数据管理后台的学生。里面的页面组织方式和分页参数设计,比单纯看文档更有参考价值。

2. 骨架怎么搭:Bootstrap 栅格、common.css 与五页共用的布局模板

打开压缩包先别急着看 JS,把 styles、views、images 三个目录的结构捋一遍,能省下大量排错时间。整个前端只依赖四个 CSS 文件:bootstrap.min.css提供栅格和基础组件,bootstrap-table.css负责表格样式,pagination.css定制分页条,common.css承载大屏专用布局。这种分层方式和后端代码里“框架层、业务层、工具层”的分层逻辑一致,换皮肤时只动 common.css,升级组件时只替换框架文件,互不干扰。

2.1 CSS 分工:基础框架、业务样式与表格组件

这套源码的样式管理思路很朴素但也最实用:框架文件原封不动,业务样式全部收敛到common.css,表格和分页单独拆文件。这样做的直接好处是,当你需要把 demo 改成医院实际品牌色时,不需要在 bootstrap.min.css 里做任何搜索替换,那里面被压缩过的类名会把你逼疯的。

CSS 文件承担职责改动频率
bootstrap.min.css栅格系统、按钮、下拉菜单、模态框等基础组件基本不动
bootstrap-table.css表格排序箭头、行 hover、选中态样式偶尔调
pagination.css分页按钮尺寸、间距、深色背景适配换肤时必改
common.css大屏背景、标题栏、信息卡片、导航、图表底板换肤时必改

pagination.css为例,大屏项目里分页条通常会做得比普通后台大一圈,按钮高度从默认的 30px 提到 38px 左右,字号放大到 14px,同时把active页码的背景色改成与主视觉一致的高亮色。这一类改动如果写进 bootstrap-table.css 里,下次升级表格组件时会被直接覆盖,单独拆出来就不会。

2.2 从 index.html 看大屏的布局骨架

五个页面里,index.html是总览大屏,结构上最完整;quota.htmlchronic.htmltrend.htmlNCDindex.html则是分主题页面。它们的共同点很明确:顶部是title_xx.png拼出来的标题栏,下方用 Bootstrap 栅格排布信息卡片和表格区,最底层铺一张chartBack.jpg作为图表区域的底板。

<div class="container-fluid dashboard-body"> <!-- 顶部标题栏:左侧 logo.png + 中间 title_13.png + 右侧时间/导航 --> <div class="row header-row"> <div class="col-xs-4"> <img src="images/logo.png" alt="医院标识" class="logo"> </div> <div class="col-xs-8 text-center"> <img src="images/title_13.png" alt="运营监测平台" class="page-title"> </div> </div> <!-- 信息卡片区:col-md-3 在桌面四分一排布 --> <div class="row card-row"> <div class="col-xs-6 col-md-3"> <div class="stat-card"> <img src="images/info_3.png" alt="门诊量"> <span class="stat-value" id="outpatientTotal">--</span> </div> </div> <div class="col-xs-6 col-md-3"> <div class="stat-card"> <img src="images/info_5.png" alt="住院量"> <span class="stat-value" id="inpatientTotal">--</span> </div> </div> </div> <!-- 图表与表格区 --> <div class="row"> <div class="col-md-8"> <div class="chart-panel" style="background: url('images/chartBack.jpg') no-repeat center;"> <table id="mainTable"></table> </div> </div> <div class="col-md-4"> <div class="side-panel" id="sidePanel"></div> </div> </div> </div>

这里的类名和图片编号是根据资源目录还原的常规写法,重点看两个设计决策。第一,信息卡片区用col-md-3,意味着在 1200px 以上的桌面端一行排四张,到了平板宽度自动变成两列,正是大屏项目在 1920x1080 和 1366x768 两种分辨率之间切换时最需要的弹性。第二,图表区没有硬编码高度,而是通过chartBack.jpg的宽高比撑起来,这样一旦某个科室的表格数据量超出预期,页面不会因为固定高度直接溢出滚动条。

2.3 图片资源的组织方式与换肤思路

图片目录里大量title_xx.pnginfo_xx.png是这套源码的视觉核心。title_开头的是各级标题栏背景,info_开头的是信息卡片图标,nav_开头的是底部导航图标,find.png是查询按钮的放大镜图标。它们的编号没有业务含义,纯粹是 UI 切图时的序列号。

换肤时最容易犯的错是直接改图片内容而不改命名规则。比如把title_13.png替换成新标题图,但新图尺寸比例和原来不一致,结果标题栏背景被拉伸变形。我一般会先量出原图宽高,再做同尺寸替换;如果医院要求换主色调,更快的方案是先看 common.css 里有没有引用这些图片的background-position,有的话优先改 CSS 里的颜色值,而不是重新切图。

提示:大屏项目中的切图资源,命名与物理路径一旦上线就不要随意变更。前端缓存、运维监控、后端模板都可能引用完整路径,改名等于制造一次隐蔽的线上故障。

3. 数据从哪来:jQuery Ajax 异步加载与五个脚本的分工

styles 目录解决了“长什么样”,scripts 目录则解决“数据怎么进来”。这套源码没有用 Vue 或 React,而是纯粹依赖 jQuery 的$.ajax手动操作 DOM 和刷新表格。这种方式的优点是不需要构建工具,改完 JS 刷新页面就能看到效果,对院内网环境尤其友好;缺点是数据流不集中,所以必须把脚本职责拆清楚,否则后期维护时找一个字段要翻五个文件。

3.1 scripts 目录的职责划分

脚本文件对应页面核心职责
index.jsindex.html总览大屏:统计卡片、全院核心指标、今日概览
quota.jsquota.html科室指标配额、完成率、月度目标进度
chronic.jschronic.html慢性病就诊人数、随访率、病种分布
trend.jstrend.html同比环比趋势、周期对比
NCDindex.jsNCDindex.html非传染性疾病指数、风险分层统计
common.js全部页面公共方法:日期格式化、数值千分位、请求封装

拆分的逻辑是按业务域切分,而不是按功能切分。common.js里的方法不依赖任何具体页面,比如数值格式化、请求失败提示、时间范围默认值;页面脚本只负责调用公共方法并绑定本页的 DOM 事件。这样的好处是,当你接到需求要新加一个“手术质量指标”页面,只需要复制quota.html的骨架,新建一个surgery.js,把表格列配置和数据接口地址换掉就行,公共方法一行都不用动。

3.2 一次完整的 Ajax 数据加载链路

index.js为例,页面初始化时首先要发起一个总览数据的请求,拿到结果后分别填充顶部的统计卡片和下方的表格。

// index.js 页面初始化入口 $(function () { initOverview(); }); function initOverview() { $.ajax({ url: './mock/overview.json', // 开发阶段指向本地 Mock,上线时替换为真实接口 method: 'GET', dataType: 'json', timeout: 10000, // 10 秒超时,避免接口卡死导致大屏空白 success: function (res) { if (res.code !== 0) { showError(res.msg || '数据加载失败'); return; } renderStatCards(res.data.cards); // 填充顶部统计卡片 renderMainTable(res.data.tableData); // 填充主表格 }, error: function (xhr, status) { showError('请求失败,请检查网络或接口地址'); } }); }

参数层面的几个细节值得说明。timeout: 10000是医院内网环境常见的超时配置,因为大屏项目挂在门诊大厅时网络质量不稳定,如果接口 30 秒不返回,页面会一直停留在加载状态,不如主动失败并展示提示。res.code !== 0是前后端约定的统一状态码,这里假设 0 为成功,实际项目里可能是"0000"或者200,关键是common.js里要封装一个isSuccess方法统一判断,避免每个页面重复写条件。renderStatCardsrenderMainTable是两个纯函数,一个负责把数据写进卡片 DOM,一个负责把数据交给表格组件,职责单一,出了问题只看对应函数就行。

3.3 common.js 公共方法:字段映射、格式化和异常兜底

真实接口返回的字段名通常和前端展示名不一致,比如后端叫pat_count,页面上要显示成“就诊人次”。如果把这种映射关系散落在每个页面脚本里,后端改一个字段名就要全局搜索替换。常见的做法是在common.js里提供统一的字段格式化函数:

// common.js 中的通用格式化方法 var Common = { // 数值千分位 1234567 -> 1,234,567 formatNumber: function (val) { var num = Number(val); if (isNaN(num)) return '--'; return num.toLocaleString('zh-CN'); }, // 百分比字段:后端可能返回 0.156 或 "15.6" formatPercent: function (val, digits) { var num = Number(val); digits = digits || 1; if (isNaN(num)) return '--'; if (num >= 0 && num < 1) { return (num * 100).toFixed(digits) + '%'; } return num.toFixed(digits) + '%'; }, // 对传入的字段做安全兜底 safeGet: function (obj, key, defaultVal) { return obj && obj[key] !== undefined && obj[key] !== null ? obj[key] : (defaultVal || '--'); } };

formatPercent处理的是一个很典型的坑:同一个占比字段,不同后端接口有的返回小数0.156,有的返回字符串"15.6",直接用toFixed会得到错误结果。这里先判断数值范围,小于 1 且大于 0 的按小数转百分比,其余按已有百分比处理。safeGet用于兜底字段缺失的情况,医院老系统的接口经常出现某个字段在某条记录里不存在的现象,不兜底的话表格那一列会直接显示undefined,影响大屏观感。

4. 表格分页、筛选与查询:bootstrap-table 的远程数据模式

表格分页是这套源码里最有参考价值的部分。bootstrap-table本身支持两种分页模式:clientserver。client 模式把全量数据一次性拉到浏览器,由插件在前端分页;server 模式每次只向接口请求当前页数据。这套源码选择的是 server 模式,也就是远程分页,院内报表系统里几千到几万行的数据量,用 client 模式会直接拖垮渲染,server 模式才是正确姿势。

4.1 为什么源码选择 server 模式分页

看资源目录里同时出现了bootstrap-table.csspagination.css,就知道表格和分页是深度耦合的。医院的大屏数据量虽然比不上互联网日志那种量级,但门诊记录按月查很容易到几十万行,一次性拉全量数据无论对后端数据库还是浏览器 DOM 都是灾难。server 模式下,后端每次只返回当前页数据,前端表格只渲染 10 到 50 行,性能瓶颈被彻底转移到后端 SQL 上,而分页 SQL 恰恰是所有后端开发都熟悉的能力。

另一个原因是筛选联动。大屏上通常会放科室下拉框、日期范围选择器、指标类型切换,这些条件必须拼进查询参数重新请求后端。server 模式天然支持把筛选条件随着翻页请求一起提交,而 client 模式虽然也能在前端过滤,但实现数据源切换时逻辑会绕很多。

4.2 远程分页的参数约定与返回格式

quota.js里初始化表格的代码逻辑大致如下,分页参数通过queryParams函数传给后端:

// quota.js 中 bootstrap-table 初始化配置 $('#quotaTable').bootstrapTable({ url: './mock/quota-page.json', method: 'get', pagination: true, sidePagination: 'server', // 关键:使用远程分页 pageNumber: 1, // 初始页码 pageSize: 10, // 每页条数 pageList: [10, 20, 50], // 每页条数切换选项 queryParams: function (params) { // 把前端筛选条件合并进分页参数 return { page: params.pageNumber, rows: params.pageSize, dept: $('#deptSelect').val(), // 科室下拉框 dateRange: $('#dateRange').val(), // 日期范围 order: params.sort, orderBy: params.order }; }, columns: [ { field: 'dept', title: '科室', sortable: true }, { field: 'quota', title: '指标值', sortable: true }, { field: 'completeRate', title: '完成率' } ] });

参数映射关系最好单独列出来,方便对照后端接口文档:

前端参数含义后端常见对应
page当前页码pageNum、pageIndex
rows每页条数pageSize、limit
dept科室筛选值deptCode、deptId
dateRange时间范围startDate、endDate
sort排序列字段名sortField
order排序方向asc / desc

这段配置里最容易被忽视的是queryParams的返回值没有沿用插件默认的limitoffset,而是改成了pagerows。原因很简单:很多 Java 后台的 PageHelper 插件、Python 的 DRF 分页,默认接收的参数就是pageNum/pageSize或者page/rows,前端按后端要求传参可以省掉一层参数转换。sortable: true开启列排序后,点击表头会触发重新请求,排序字段通过params.sort自动带出,不需要额外绑定事件。

4.3 从 queryParams 到 refresh 的筛选联动

筛选功能是另一个关键点。下拉框切换科室后,需要把表格重置到第一页并重新请求,否则用户会停留在第 5 页看到一堆不属于当前科室的数据。常见做法是监听筛选控件的change事件,调用表格的refresh方法:

// 科室下拉框变化时刷新表格 $('#deptSelect').on('change', function () { // 重置到第一页,并携带新的筛选条件 $('#quotaTable').bootstrapTable('refresh', { pageNumber: 1, silent: false // false 表示显示加载动画 }); }); // 查询按钮 click 事件,多条件同时生效 $('#searchBtn').on('click', function () { $('#quotaTable').bootstrapTable('refresh'); });

注意这里queryParams里用了$('#deptSelect').val(),意味着每次 refresh 时都会重新读取当前下拉框的值,所以不需要手动把筛选条件塞进 refresh 参数里。pageNumber: 1是必须的,不重置的话,用户在满足条件的数据只有 3 页的情况下停留在第 5 页,接口会返回空数据,表格显示空白,很容易被误判成 bug。

5. 把源码跑起来:HTTP 服务、Mock 替换与验收检查

拿到这套源码后最容易遇到的第一个坑就是双击index.html打开,结果页面空白、控制台报错。原因是浏览器对file://协议下的 Ajax 请求有严格限制,$.ajax读取本地 JSON 会被 CORS 策略拦截,同时页面里引用的相对路径资源也可能因为协议不同加载失败。所以第一步不是改代码,而是先把服务跑起来。

5.1 用本地 HTTP 服务启动

项目根目录下执行任意一个静态服务器命令即可:

# Python 3 自带,无需额外安装 cd bootstrap-jquery-hospital-dashboard python3 -m http.server 8080 # 或者使用 Node 生态 npx serve -l 8080

启动后浏览器访问http://localhost:8080/index.html。验证服务是否正常,直接在 shell 里请求接口:

curl -s http://localhost:8080/mock/quota-page.json | head -20

能返回 JSON 数据说明静态服务器正常,接下来重点检查浏览器控制台有没有 404 和 500 报错。404 通常是因为资源路径写死,比如代码里写/images/logo.png而根目录实际是./images/logo.png;500 则大概率是接口地址不存在,需要到对应 JS 文件的url字段里替换成真实接口。

5.2 把 Mock 数据换成真实医院接口

替换时先找出所有 JS 里的url: './mock/xxx.json',逐个替换成后端真实地址。这里有个需要注意的细节:不要把接口地址写死在各页面脚本里,而是统一放进一个config.js或挂在window.AppConfig上,后续环境切换只改一个文件。

// config.js 环境配置示例 window.AppConfig = { baseUrl: window.location.origin + '/api', timeout: 10000 };

真实医院接口的字段名几乎不可能和 Mock 完全一致,需要用common.js里的格式化函数做适配。另外,如果接口做了鉴权,需要在$.ajaxSetup里统一加请求头:

$.ajaxSetup({ headers: { 'Authorization': 'Bearer ' + (window.localStorage.getItem('token') || '') } });

医院数据属于敏感数据,接口必须做权限校验和脱敏处理,姓名、身份证号、详细住址绝不能出现在大屏上,这是上线前的硬性检查项。

5.3 大屏与业务终端的分辨率适配

这套源码的 Bootstrap 栅格在 1920x1080 大屏上通常没有问题,但在 1366x768 的办公终端上看,底部表格可能会被挤出一部分。检查方法是打开浏览器开发者工具的设备模拟,分别切到 1920x1080、1366x768、1280x720 三个分辨率,重点看标题栏是否换行、表格列是否被压缩、分页条有没有溢出。遇到表格列数较多时,可以在 bootstrap-table 的列定义里加visible: false隐藏次要列,或者用formatter把多列合并展示,而不是硬抗宽度。

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

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

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

立即咨询