医院专家展示大屏实战开发
·
医院专家展示大屏实战开发
一、项目背景与需求分析
在现代医院信息化建设中,专家信息展示大屏是连接患者与医疗资源的重要桥梁。本文将详细介绍如何使用 ASP.NET Core MVC + Dapper + 原生JavaScript 技术栈,构建一个功能完善、视觉效果出色的医院专家介绍大屏系统。
核心功能需求
- 数据展示:实时展示医院专家的基本信息、职称、简介、坐诊时间
- 视觉标识:党员医生标识、浙二专家标识区分
- 自动轮播:支持多页数据自动切换展示
- 响应式布局:自适应不同分辨率的大屏设备
- 定时刷新:每30分钟自动更新专家数据

二、技术架构设计
2.1 整体架构
┌─────────────────────────────────────────────────────────────┐
│ 前端展示层 (View) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 原生JavaScript + CSS3 动画 + Grid弹性布局 │ │
│ │ • 自动分页轮播 • 响应式网格 • 科技感UI设计 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 控制器层 (Controller) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ExpertScreenController │ │
│ │ • GetExperts() - 获取专家列表API │ │
│ │ • Index() - 大屏展示页面 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 数据访问层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Dapper (轻量级ORM) + MySQL │ │
│ │ • 高性能SQL查询 • 动态数据映射 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
2.2 数据库表结构
CREATE TABLE expert_info (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(50) NOT NULL COMMENT '专家姓名',
depart_name VARCHAR(100) COMMENT '科室/职称',
picture VARCHAR(255) COMMENT '照片路径',
intro TEXT COMMENT '专家介绍',
work_time VARCHAR(500) COMMENT '专家门诊时间',
doc_lib_time VARCHAR(500) COMMENT '名医馆坐诊时间',
isPartyMember TINYINT(1) DEFAULT 0 COMMENT '是否党员',
isZheErExpert TINYINT(1) DEFAULT 0 COMMENT '是否浙二专家',
is_del TINYINT(1) DEFAULT 0 COMMENT '是否删除',
page INT COMMENT '排序页码',
ordering INT COMMENT '排序序号'
);
三、后端实现详解
3.1 数据模型定义
// Models/ExpertScreen/ExpertModel.cs
namespace QASystem.Models.ExpertScreen
{
public class ExpertModel
{
public int id { get; set; }
public string name { get; set; }
public string title { get; set; }
public string photo { get; set; }
public string description { get; set; }
public string schedule { get; set; }
public string schedule1 { get; set; }
public bool isPartyMember { get; set; }
public bool isZheErExpert { get; set; }
}
public class ExpertDataModel
{
public List<ExpertModel> experts { get; set; }
}
}
3.2 控制器实现
// Controllers/ExpertScreenController.cs
public class ExpertScreenController : Controller
{
private ILogger<ExpertScreenController> _logger;
private readonly string _qasystem;
private readonly IMysqlService _mysqlService;
public ExpertScreenController(
ILogger<ExpertScreenController> logger,
IConfiguration configuration,
IMysqlService mysqlService)
{
_logger = logger;
_qasystem = configuration.GetConnectionString("qasystem");
_mysqlService = mysqlService;
}
// 大屏展示页面
public IActionResult Index()
{
return View();
}
// API:获取专家列表
public JsonResult GetExperts()
{
string sql = @"SELECT
id,
NAME,
depart_name AS title,
picture AS photo,
intro AS description,
work_time AS SCHEDULE,
case when doc_lib_time is null then '' else doc_lib_time END AS SCHEDULE1,
isPartyMember,
isZheErExpert
FROM
expert_info
WHERE
is_del = 0
ORDER BY page,ordering asc";
List<ExpertModel> experts = _mysqlService.DBQuery<ExpertModel>(_qasystem, sql);
ExpertDataModel model = new ExpertDataModel
{
experts = experts
};
return Json(model);
}
}
3.3 关键技术点解析
3.3.1 Dapper动态查询
使用Dapper进行数据库操作,相比EF Core更加轻量高效:
// 泛型方法实现动态映射
List<ExpertModel> experts = _mysqlService.DBQuery<ExpertModel>(_qasystem, sql);
3.3.2 SQL优化技巧
-- 使用CASE处理NULL值,确保前端接收空字符串而非null
case when doc_lib_time is null then '' else doc_lib_time END AS SCHEDULE1
四、前端实现详解
4.1 状态管理设计
采用纯JavaScript实现状态管理,避免引入重型框架:
const state = {
experts: [], // 当前展示的专家列表
currentPage: 0, // 当前页码
expertsPerPage: 6, // 每页显示数量
totalPages: 0, // 总页数
autoSwitchInterval: null, // 自动切换定时器
isLoading: false, // 加载状态
allExperts: [], // 所有专家数据
nonZheErExperts: [] // 筛选后的专家
};
4.2 响应式网格布局
根据容器尺寸动态计算每页显示的专家数量:
function calculateExpertsPerPage() {
const containerWidth = document.querySelector('.experts-container').clientWidth;
const containerHeight = document.querySelector('.experts-container').clientHeight;
// 卡片宽度基准
const baseCardWidth = 400;
// 根据宽度计算列数
const cols = Math.floor((containerWidth - 30) / (baseCardWidth + 30));
const finalCols = Math.min(Math.max(1, cols), 12); // 限制最多12列
// 根据高度计算行数
const cardAspectRatio = 1.4;
const estimatedCardHeight = baseCardWidth / cardAspectRatio;
const rowsPerPage = Math.max(1, Math.floor(
(containerHeight - 80) / (estimatedCardHeight + 30)
));
// 每页最多60个专家
state.expertsPerPage = Math.min(60, finalCols * rowsPerPage);
state.totalPages = Math.ceil(state.experts.length / state.expertsPerPage);
}
4.3 数据获取与容错处理
async function fetchExpertsFromServer() {
try {
const response = await fetch('/ExpertScreen/GetExperts', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('获取专家数据失败:', error);
// 返回备用模拟数据,确保系统可用性
return {
experts: generateMockExperts()
};
}
}
4.4 定时数据刷新机制
function setupPeriodicDataFetching() {
const intervalMs = 30 * 60 * 1000; // 30分钟
setInterval(async () => {
console.log('定时更新专家数据...');
try {
const data = await fetchExpertsFromServer();
const allExperts = data.experts || [];
// 更新状态
state.allExperts = allExperts;
state.nonZheErExperts = allExperts;
state.experts = [...state.nonZheErExperts];
// 重新计算分页并渲染
calculateExpertsPerPage();
setupPagination();
renderCurrentPage();
} catch (error) {
console.error('定时更新专家数据失败:', error);
}
}, intervalMs);
}
4.5 自动轮播实现
function startAutoSwitch() {
if (state.autoSwitchInterval) {
clearInterval(state.autoSwitchInterval);
}
state.autoSwitchInterval = setInterval(() => {
nextPage();
}, 30000); // 30秒切换一次
}
// 页面可见性API优化性能
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
stopAutoSwitch(); // 页面隐藏时停止轮播
} else {
startAutoSwitch(); // 页面显示时恢复轮播
}
});
4.6 专家卡片动态渲染
function createExpertCard(expert) {
const card = document.createElement('div');
card.className = 'expert-card';
// 党员标识
const partyBadge = expert.isPartyMember
? `<div class="party-badge"><img src="../images/expert/partyImg.png" alt="党徽"></div>`
: '';
// 医院Logo根据专家类型切换
const logoSrc = expert.isZheErExpert
? '../images/expert/zErlogo.png'
: '../images/expert/logo.png';
card.innerHTML = `
<div class="expert-photo-container">
<img src="http://192.9.216.145:9000/expert/${expert.photo}"
alt="${expert.name}" class="expert-photo">
${partyBadge}
</div>
<div class="hospital-logo">
<img src="${logoSrc}" alt="医院Logo">
</div>
<div class="expert-info">
<div class="expert-name">${expert.name}</div>
<div class="expert-title">${expert.title}</div>
<div class="expert-description">${expert.description}</div>
<div class="expert-schedule">
<div class="schedule-title">坐诊时间:</div>
${expert.schedule1 != '' ? `
<div class="schedule-content">
<span style='font-weight:bold'>专家门诊:</span>${expert.schedule};
<span style='font-weight:bold'>名医馆:</span>${expert.schedule1}
</div>` : `
<div class="schedule-content">
<span style='font-weight:bold'>专家门诊:</span>${expert.schedule}
</div>`}
</div>
</div>
`;
return card;
}
五、UI设计亮点
5.1 科技感视觉风格
body {
background: #0c1428;
background-image:
radial-gradient(circle at 25% 25%, rgba(11, 36, 129, 0.3) 0%, transparent 50%),
radial-gradient(circle at 75% 75%, rgba(11, 36, 129, 0.3) 0%, transparent 50%),
linear-gradient(0deg, #0c1428 0%, #101a30 100%);
}
/* 科技感网格背景 */
body::before {
content: '';
position: fixed;
background-image:
linear-gradient(rgba(40, 80, 120, 0.5) 1px, transparent 1px),
linear-gradient(90deg, rgba(40, 80, 120, 0.5) 1px, transparent 1px);
background-size: 40px 40px;
opacity: 0.4;
}
5.2 卡片悬停效果
.expert-card {
background: rgba(28, 34, 56, 0.9);
border: 1px solid rgba(0, 191, 255, 0.2);
transition: all 0.3s ease;
}
.expert-card::before {
content: '';
position: absolute;
height: 2px;
background: linear-gradient(90deg, transparent, #00e5ff, transparent);
}
.expert-card:hover {
transform: translateY(-5px);
box-shadow: 0 0 40px rgba(0, 191, 255, 0.4);
}
六、性能优化策略
6.1 前端优化
| 优化点 | 实现方式 |
|---|---|
| 懒加载 | 按需渲染当前页专家卡片 |
| 防抖处理 | resize事件防抖,避免频繁重绘 |
| 定时器管理 | 页面隐藏时暂停自动切换 |
| 图片优化 | 使用对象存储CDN加速 |
6.2 后端优化
-- 添加复合索引优化查询
CREATE INDEX idx_expert_sort ON expert_info(page, ordering);
CREATE INDEX idx_expert_active ON expert_info(is_del);
七、项目总结
本系统采用轻量级技术栈,实现了以下核心优势:
- 架构简洁:ASP.NET Core MVC + Dapper,学习成本低,维护方便
- 性能优异:原生JavaScript无框架依赖,首屏加载快
- 扩展性强:模块化设计,易于功能扩展
- 稳定可靠:完善的错误处理和降级策略
适用场景
- 医院大厅专家信息展示大屏
- 企业人才展示墙
- 政务公开信息展示系统
- 任何需要数据可视化大屏的场景
八、源码参考
Controller: Controllers/ExpertScreenController.cs
View: Views/ExpertScreen/Index.cshtml
Models: Models/ExpertScreen/ExpertModel.cs
💡 小贴士:本文完整展示了从需求分析到代码实现的完整流程,适合有一定ASP.NET Core基础的开发者学习参考。如需获取完整源码或有任何疑问,欢迎在评论区留言交流!
标签: #ASP.NET Core #Dapper #大屏展示 #医疗信息化 #前端开发 #JavaScript
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)