feat: 检后模块新增影像数据管理菜单
This commit is contained in:
@@ -130,7 +130,7 @@ Web 管理端和员工端 APP 的其余模块(系统管理、运动管理、
|
||||
|
||||
- 2026-09-07:净菜类型拆分独立管理(commit 891678d)——①`din-ingredient.html`/`din-ingredient-add.html` 净菜类型按**规格行级**维护「可食部(%)」字段(位于规格别名后,新增规格时随行出现,新增/编辑/详情三页同步);②食材列表操作区「食材分类管理」按钮后新增「净菜管理」入口;③新建 `din-clean-veg-mgmt.html` 净菜管理二级页:统计卡片 + 食材名称(下拉搜索)/食材编码/净菜类型(净菜俗名/净菜标准名/规格俗名三源关键字)/切配形状筛选 + 异步导出按钮组(导出列表数据+查看导出任务,样式对齐全仓列表页惯例)+ 列表组级列 rowspan 合并、可食部/规格别名/切配规格/刀工按规格逐行拆分(组内虚线分隔、规格列区纵向分隔线)+ 先选食材回显已有净菜类型再新增/编辑的维护弹窗;SITE_MAP 与营养模块 CHANGELOG 同步。(相关决策:[[decisions.md#净菜类型数据模型与净菜管理页展示模式]])
|
||||
- 2026-09-07:全仓截图脚本与截图质量修复(commit 7f18470)——assistant/expert/health-monitor 截图脚本失效页面引用改回现存文件名并清理孤儿截图;weight-main-v2 初始化改为解析 `?type=` 参数,修复设计总览六种目标状态截图雷同问题,重拍 weight-main/bluetooth-scale 共 10 张;补拍 PRD 引用但从未生成的视频进行中截图;体重管理 PRD 修复两处截图断链。
|
||||
- 2026-09-04:医疗点PAD端首版原型(commit 15ca37b)——新建 `other-module/medical-pad/` 20 页(1280×800 横屏,抽屉交互页内实现),SITE_MAP 与项目背景尺寸规范同步,新增模块 CHANGELOG;同提交:全站演示数据脱敏(示例人名王建国→石维国、周明远→曲志明,机构长庆油田→CQ油田,覆盖约 30 页)、现场体检签到码改条形码/二维码双选项卡切换、新增健康长寿系统升级改造详细规划 V8 文档。(相关规范:[[feedback_medical_pad_migration.md]])
|
||||
- 2026-09-04:医疗点PAD端首版原型(commit 15ca37b)——新建 `other-module/medical-pad/` 20 页(1280×800 横屏,抽屉交互页内实现),SITE_MAP 与项目背景尺寸规范同步,新增模块 CHANGELOG;同提交:全站演示数据脱敏(示例人名王建国→石维国、周明远→曲志明,机构CQ能源→CQ油田,覆盖约 30 页)、现场体检签到码改条形码/二维码双选项卡切换、新增健康长寿系统升级改造详细规划 V8 文档。(相关规范:[[feedback_medical_pad_migration.md]])
|
||||
- 2026-09-04:体重管理员工端设计总览重构(commit 29a09e9)——总览页按目标承诺与签署/体重主页/每日打卡/历史记录/建议与报告/蓝牙设备六大主线重排,页面清单全面切换到 weight-main-v2/goal-management-v2 等 v2 新版页面,新增 playwright 统一截图脚本 `screenshot-weight.mjs` 并重新生成全部截图。
|
||||
- 2026-09-03~09-04:健康体检员工端与管理端多轮完善(commit 118d143、05e157e)——员工端:选项目页费用横幅重做为体检额度卡片(额度使用进度条+必检/选检/可用额度三格,年度额度 1600,新增心脏彩超与胃幽门螺杆菌两项选检),"我的预约"更名重做为"现场体检",胃肠镜预约结果页成功/失败两态演示;管理端:体检报告模板更名体检导入模板管理、模板额度配置更名群体额度配置、大病人员信息新增弹窗(员工搜索下拉+信息卡片)、指标异常通知固定列+发送通知/短信、单位/胃肠镜预约统计改单位级别 TAB。
|
||||
- 2026-09-02~09-03:健康体检预约流程与检中页面完善(commit a443c61、0d1c770、37ae054、3a838d0、2213106)——员工端"我的预约"合并单页+新增指标纵向对比与消息中心;胃肠镜医院预选征集/已提交页、检前首页预选通知条、选日期页预约状态条与可约窗口限制(常规近30天/胃肠镜7~30天)、预约结果页成功/失败演示与取消预约二次确认;管理端新增大病人员信息/指标异常通知/已选项目员工信息页,胃肠镜体检计划管理新增/编辑/详情抽屉(承检医院多选+机构树选人),组合模板/例外配置/医院费用/单位费用统一详情弹窗与编辑抽屉,检中页更名员工预约体检跟踪、统一员工编号筛选与列、体检编号更名体检编码。
|
||||
|
||||
@@ -271,6 +271,10 @@ const SITE_MAP = [
|
||||
{ file:'post-disease-info.html', label:'病种信息配置' },
|
||||
{ file:'post-conclusion-disease.html', label:'体检结论关联病种' },
|
||||
{ file:'post-auto-select-disease.html', label:'员工病种信息' },
|
||||
{ file:'post-imc-user.html', label:'用户体检信息' },
|
||||
{ file:'post-imc-class.html', label:'用户影像文件分类' },
|
||||
{ file:'post-imc-info.html', label:'用户影像文件详细' },
|
||||
{ file:'post-imc-log.html', label:'文件处理日志' },
|
||||
{ file:'agent-device.html', label:'前置机管理 · 常规体检前置服务' },
|
||||
{ file:'exception-dirty.html', label:'系统脏数据' },
|
||||
{ file:'exception-result.html', label:'结果异常' }
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
/**
|
||||
* 体重管理模块统一截图脚本
|
||||
* 规则(参考健康监测 screenshot-final.mjs):
|
||||
* - phone-shell 尺寸 390 宽
|
||||
* - 'fixed':弹窗/浮层类截图,严格 390×844,弹窗叠在当前页面之上
|
||||
* - 'auto' :纯页面截图,短页面最低 844,长页面按真实内容展开
|
||||
* 用法:node screenshot-weight.mjs [输出名子串过滤...]
|
||||
*/
|
||||
import { chromium } from 'playwright';
|
||||
import { fileURLToPath } from 'url';
|
||||
import path from 'path';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const docDir = path.join(__dirname, 'employee-app', 'weight-management', 'doc');
|
||||
const root = path.join(__dirname, 'employee-app', 'weight-management');
|
||||
|
||||
const tasks = [
|
||||
// ========== 目标承诺与签署 ==========
|
||||
{ html: 'goal-management-v2.html', out: 'goal-management', mode: 'auto' },
|
||||
{ html: 'goal-management-v2.html', out: 'goal-management-personal', mode: 'auto', eval: "switchType('personal')" },
|
||||
{ html: 'goal-management-v2.html', out: 'goal-management-activity', mode: 'fixed', eval: 'openActivitySheet()' },
|
||||
{ html: 'goal-management-v2.html', out: 'goal-management-confirm', mode: 'fixed', eval: "openActivitySheet();var i=document.querySelector('#actSheet .sheet-item');i.click();confirmActivity();closeActivitySheet();submitGoal()" },
|
||||
{ html: 'goal-management-v2.html', out: 'goal-management-confirm-personal', mode: 'fixed', eval: "switchType('personal');submitGoal()" },
|
||||
{ html: 'goal-detail-v2.html', out: 'goal-detail', mode: 'auto', query: '?type=activity&state=review' },
|
||||
{ html: 'goal-detail-v2.html', out: 'goal-detail-approved', mode: 'auto', query: '?type=activity&state=approved' },
|
||||
{ html: 'goal-detail-v2.html', out: 'goal-detail-rejected', mode: 'auto', query: '?type=activity&state=rejected' },
|
||||
{ html: 'goal-detail-v2.html', out: 'goal-detail-signed', mode: 'auto', query: '?type=activity&state=signed' },
|
||||
{ html: 'goal-detail-v2.html', out: 'goal-detail-ended', mode: 'auto', query: '?type=activity&state=ended' },
|
||||
{ html: 'goal-detail-v2.html', out: 'goal-detail-personal', mode: 'auto', query: '?type=personal' },
|
||||
{ html: 'goal-detail-v2.html', out: 'goal-detail-edit', mode: 'fixed', query: '?type=personal', eval: 'openEditGoalModal()' },
|
||||
{ html: 'goal-detail-v2.html', out: 'goal-detail-menu', mode: 'fixed', query: '?type=activity&state=signed', eval: "document.getElementById('navMore').click()" },
|
||||
{ html: 'promise-signing.html', out: 'promise-signing', mode: 'auto', landscape: true },
|
||||
{ html: 'promise-signing.html', out: 'promise-signing-giveup', mode: 'fixed', landscape: true, eval: 'openGiveup()' },
|
||||
{ html: 'my-promise.html', out: 'my-promise', mode: 'auto' },
|
||||
{ html: 'goal-history-v2.html', out: 'goal-history', mode: 'auto' },
|
||||
{ html: 'goal-history-v2.html', out: 'goal-history-personal', mode: 'auto', eval: "switchTab('personal')" },
|
||||
{ html: 'activity-detail.html', out: 'activity-detail', mode: 'auto' },
|
||||
{ html: 'basic-info.html', out: 'basic-info', mode: 'auto' },
|
||||
{ html: 'basic-info.html', out: 'basic-info-height', mode: 'fixed', eval: 'openHeightSheet()' },
|
||||
{ html: 'basic-info.html', out: 'basic-info-activity', mode: 'fixed', eval: 'openSheet()' },
|
||||
|
||||
// ========== 体重管理主页 ==========
|
||||
{ html: 'weight-main-v2.html', out: 'weight-main', mode: 'auto', query: '?type=hasact-signed' },
|
||||
{ html: 'weight-main-v2.html', out: 'weight-main-review', mode: 'auto', query: '?type=hasact-review' },
|
||||
{ html: 'weight-main-v2.html', out: 'weight-main-approved', mode: 'auto', query: '?type=hasact-approved' },
|
||||
{ html: 'weight-main-v2.html', out: 'weight-main-rejected', mode: 'auto', query: '?type=hasact-rejected' },
|
||||
{ html: 'weight-main-v2.html', out: 'weight-main-personal', mode: 'auto', query: '?type=personal' },
|
||||
{ html: 'weight-main-v2.html', out: 'weight-main-none', mode: 'auto', query: '?type=none' },
|
||||
{ html: 'weight-main-v2.html', out: 'weight-main-record', mode: 'fixed', query: '?type=hasact-signed', eval: 'openRecordSheet()' },
|
||||
{ html: 'weight-main-v2.html', out: 'weight-main-record-success', mode: 'fixed', query: '?type=hasact-signed', eval: "openRecordSheet();submitRecord()" },
|
||||
|
||||
// ========== 每日打卡(吃/动/体重) ==========
|
||||
{ html: 'eat-checkin-v2.html', out: 'eat-checkin', mode: 'auto' },
|
||||
{ html: 'eat-checkin-v2.html', out: 'eat-checkin-lunch', mode: 'auto', query: '?meal=lunch' },
|
||||
{ html: 'eat-checkin-v2.html', out: 'eat-checkin-recorded', mode: 'auto', eval: "selectCategory('recorded')" },
|
||||
{ html: 'eat-checkin-v2.html', out: 'eat-checkin-bag', mode: 'fixed', eval: 'openBagPanel()' },
|
||||
{ html: 'eat-checkin-v2.html', out: 'eat-checkin-gram', mode: 'fixed', eval: "var d;Object.keys(foodData).some(function(k){return foodData[k].items.some(function(it){if(it.name){d=it;return true}})});openGramPanel(d.id)" },
|
||||
{ html: 'eat-checkin-v2.html', out: 'eat-checkin-success', mode: 'fixed', eval: 'submitCheckin()' },
|
||||
{ html: 'eat-checkin-v2.html', out: 'eat-checkin-meals', mode: 'fixed', eval: "document.querySelector('.filter-row__meal-btn').click()" },
|
||||
{ html: 'exercise-checkin-v2.html', out: 'exercise-checkin', mode: 'auto' },
|
||||
{ html: 'exercise-checkin-v2.html', out: 'exercise-checkin-recorded', mode: 'auto', eval: "selectCategory('recorded')" },
|
||||
{ html: 'exercise-checkin-v2.html', out: 'exercise-checkin-bag', mode: 'fixed', eval: 'openBagPanel()' },
|
||||
{ html: 'exercise-checkin-v2.html', out: 'exercise-checkin-duration', mode: 'fixed', eval: "var d;Object.keys(exerciseData).some(function(k){return exerciseData[k].items.some(function(it){if(it.name){d=it;return true}})});openDurPanel(d.id)" },
|
||||
{ html: 'exercise-checkin-v2.html', out: 'exercise-checkin-success', mode: 'fixed', eval: 'submitCheckin()' },
|
||||
{ html: 'scan-checkin.html', out: 'scan-checkin', mode: 'fixed' },
|
||||
{ html: 'scan-checkin.html', out: 'scan-checkin-analyzing', mode: 'fixed', eval: "takePhoto();clearInterval(analyzeTimer);analyzeTimer=null;setTimeout(function(){document.getElementById('analyzingBar').style.width='45%';document.getElementById('analyzingSub').textContent='正在匹配食物数据库...'},300)", wait: 900 },
|
||||
{ html: 'scan-checkin.html', out: 'scan-checkin-result', mode: 'fixed', eval: 'showResult()' },
|
||||
|
||||
// ========== 历史记录 ==========
|
||||
{ html: 'weight-record-detail-v2.html', out: 'weight-record-detail', mode: 'auto' },
|
||||
{ html: 'weight-record-detail-v2.html', out: 'weight-record-detail-activity', mode: 'auto', eval: "switchTab('activity')" },
|
||||
{ html: 'eat-detail-v2.html', out: 'eat-detail', mode: 'auto' },
|
||||
{ html: 'eat-detail-v2.html', out: 'eat-detail-month', mode: 'fixed', eval: 'toggleMonthPicker()' },
|
||||
{ html: 'exercise-detail-v2.html', out: 'exercise-detail', mode: 'auto' },
|
||||
{ html: 'exercise-detail-v2.html', out: 'exercise-detail-month', mode: 'fixed', eval: 'toggleMonthPicker()' },
|
||||
{ html: 'exercise-detail-v2.html', out: 'exercise-detail-tip', mode: 'fixed', eval: "document.querySelector('.chart-dot').click()" },
|
||||
{ html: 'eat-exercise-detail-v2.html', out: 'eat-exercise-detail', mode: 'auto' },
|
||||
{ html: 'eat-exercise-detail-v2.html', out: 'eat-exercise-detail-month', mode: 'fixed', eval: 'toggleMonthPicker()' },
|
||||
{ html: 'weight-detail-v2.html', out: 'weight-detail', mode: 'auto' },
|
||||
{ html: 'weight-detail-v2.html', out: 'weight-detail-record', mode: 'fixed', eval: 'openRecordSheet()' },
|
||||
{ html: 'weight-detail-v2.html', out: 'weight-detail-month', mode: 'fixed', eval: 'toggleMonthPicker()' },
|
||||
{ html: 'weight-detail-v2.html', out: 'weight-detail-tip', mode: 'fixed', eval: "document.querySelector('.chart-dot').click()" },
|
||||
{ html: 'report-detail.html', out: 'report-detail-fat', mode: 'auto', query: '?device=fat' },
|
||||
{ html: 'report-detail.html', out: 'report-detail-scale', mode: 'auto', query: '?device=scale' },
|
||||
{ html: 'report-detail.html', out: 'report-detail-bluetooth', mode: 'auto', query: '?device=bluetooth' },
|
||||
{ html: 'body-fat-report.html', out: 'body-fat-report', mode: 'auto' },
|
||||
{ html: 'height-scale-report.html', out: 'height-scale-report', mode: 'auto' },
|
||||
|
||||
// ========== 建议与报告 ==========
|
||||
{ html: 'diet-advice-v2.html', out: 'diet-advice', mode: 'auto' },
|
||||
{ html: 'diet-advice-v2.html', out: 'diet-advice-detail', mode: 'fixed', eval: "openFoodDetail('breakfast',0)" },
|
||||
{ html: 'diet-advice-v2.html', out: 'diet-advice-dislike', mode: 'fixed', eval: 'showDislikeSheet()' },
|
||||
{ html: 'diet-advice-v2.html', out: 'diet-advice-nutrition', mode: 'fixed', eval: 'showNutritionEmpty(true)' },
|
||||
{ html: 'diet-advice-v2.html', out: 'diet-advice-nutrition-tab', mode: 'auto', eval: "switchTab('nutrition')" },
|
||||
{ html: 'diet-advice-v2.html', out: 'diet-advice-month', mode: 'fixed', eval: 'toggleMonthPicker()' },
|
||||
{ html: 'exercise-advice-v2.html', out: 'exercise-advice', mode: 'auto' },
|
||||
{ html: 'exercise-advice-v2.html', out: 'exercise-advice-month', mode: 'fixed', eval: 'toggleMonthPicker()' },
|
||||
{ html: 'weight-report.html', out: 'weight-report', mode: 'auto', query: '?type=hasact' },
|
||||
{ html: 'weight-report.html', out: 'weight-report-personal', mode: 'auto', query: '?type=personal' },
|
||||
{ html: 'weight-report.html', out: 'weight-report-none', mode: 'auto', query: '?type=none' },
|
||||
{ html: 'weight-ranking.html', out: 'weight-ranking', mode: 'auto', query: '?type=hasact' },
|
||||
{ html: 'weight-ranking.html', out: 'weight-ranking-personal', mode: 'auto', query: '?type=personal' },
|
||||
{ html: 'weight-ranking.html', out: 'weight-ranking-none', mode: 'auto', query: '?type=none' },
|
||||
|
||||
// ========== 蓝牙设备 ==========
|
||||
{ html: 'bluetooth-scale-v2.html', out: 'bluetooth-scale', mode: 'auto', query: '#paired' },
|
||||
{ html: 'bluetooth-scale-v2.html', out: 'bluetooth-scale-empty', mode: 'auto' },
|
||||
{ html: 'bluetooth-device-members-v2.html', out: 'bluetooth-device-members', mode: 'auto', query: '?device=s1' },
|
||||
{ html: 'bluetooth-device-members-v2.html', out: 'bluetooth-device-members-empty', mode: 'auto', query: '?device=b2' },
|
||||
{ html: 'bluetooth-device-members-v2.html', out: 'bluetooth-device-members-delete', mode: 'fixed', query: '?device=s1', eval: "document.querySelector('.action-btn--delete').click()" },
|
||||
{ html: 'bluetooth-device-members-v2.html', out: 'bluetooth-device-members-sync', mode: 'fixed', query: '?device=s1', eval: 'syncMembers()', wait: 1600 },
|
||||
{ html: 'bluetooth-search-v2.html', out: 'bluetooth-search', mode: 'auto' },
|
||||
{ html: 'bluetooth-wifi-v2.html', out: 'bluetooth-wifi', mode: 'auto' },
|
||||
];
|
||||
|
||||
(async () => {
|
||||
const filters = process.argv.slice(2);
|
||||
const runTasks = filters.length ? tasks.filter(t => filters.some(f => t.out.includes(f))) : tasks;
|
||||
|
||||
const browser = await chromium.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] });
|
||||
const context = await browser.newContext({ viewport: { width: 390, height: 4000 } });
|
||||
|
||||
for (const t of runTasks) {
|
||||
const page = await context.newPage();
|
||||
const filePath = path.join(root, t.html);
|
||||
const url = `file:///${filePath.replace(/\\/g, '/')}${t.query || ''}`;
|
||||
await page.goto(url, { waitUntil: 'networkidle' });
|
||||
|
||||
if (t.eval) {
|
||||
await page.evaluate(t.eval).catch(e => console.log(`! eval failed [${t.out}]: ${e.message}`));
|
||||
await page.waitForTimeout(t.wait || 300);
|
||||
}
|
||||
|
||||
if (t.landscape) {
|
||||
// 横屏页:phone-shell 固定 844×390,不展开、按元素原尺寸截取
|
||||
await page.evaluate(() => {
|
||||
const shell = document.querySelector('.phone-shell');
|
||||
if (shell) {
|
||||
shell.style.borderRadius = '0';
|
||||
shell.style.boxShadow = 'none';
|
||||
}
|
||||
document.body.style.padding = '0';
|
||||
document.body.style.margin = '0';
|
||||
document.body.style.minHeight = 'auto';
|
||||
document.body.style.background = '#fff';
|
||||
document.documentElement.style.display = 'block';
|
||||
});
|
||||
await page.setViewportSize({ width: 844, height: 390 });
|
||||
await page.waitForTimeout(200);
|
||||
} else if (t.mode === 'fixed') {
|
||||
await page.evaluate(() => {
|
||||
const shell = document.querySelector('.phone-shell');
|
||||
if (shell) {
|
||||
shell.style.borderRadius = '0';
|
||||
shell.style.boxShadow = 'none';
|
||||
}
|
||||
document.body.style.padding = '0';
|
||||
document.body.style.minHeight = 'auto';
|
||||
document.body.style.background = '#fff';
|
||||
});
|
||||
await page.setViewportSize({ width: 390, height: 844 });
|
||||
await page.waitForTimeout(200);
|
||||
} else {
|
||||
await page.evaluate(() => {
|
||||
const shell = document.querySelector('.phone-shell');
|
||||
if (shell) {
|
||||
shell.style.height = 'auto';
|
||||
shell.style.minHeight = '844px';
|
||||
shell.style.maxHeight = 'none';
|
||||
shell.style.borderRadius = '0';
|
||||
shell.style.boxShadow = 'none';
|
||||
shell.style.overflow = 'visible';
|
||||
shell.style.display = 'block';
|
||||
}
|
||||
document.querySelectorAll('.scroll-content, .page-content, .main-content, .list-wrap, .content').forEach(c => {
|
||||
c.style.overflow = 'visible';
|
||||
c.style.maxHeight = 'none';
|
||||
c.style.height = 'auto';
|
||||
c.style.flex = 'none';
|
||||
});
|
||||
document.body.style.padding = '0';
|
||||
document.body.style.minHeight = 'auto';
|
||||
document.body.style.background = '#fff';
|
||||
});
|
||||
await page.waitForTimeout(300);
|
||||
const measured = await page.evaluate(() => {
|
||||
const shell = document.querySelector('.phone-shell');
|
||||
if (!shell) return document.body.scrollHeight;
|
||||
return Math.ceil(shell.getBoundingClientRect().height);
|
||||
});
|
||||
const h = Math.max(measured, 844);
|
||||
await page.setViewportSize({ width: 390, height: h });
|
||||
await page.waitForTimeout(150);
|
||||
}
|
||||
|
||||
const shell = await page.$('.phone-shell');
|
||||
const target = shell || page;
|
||||
await target.screenshot({
|
||||
path: path.join(docDir, 'screenshots', `${t.out}.jpg`),
|
||||
type: 'jpeg',
|
||||
quality: 85,
|
||||
});
|
||||
console.log(`✓ ${t.out}.jpg [${t.mode}]`);
|
||||
await page.close();
|
||||
}
|
||||
|
||||
await browser.close();
|
||||
console.log(`\n完成!共截取 ${runTasks.length} 张`);
|
||||
})();
|
||||
@@ -1,5 +1,17 @@
|
||||
# 健康体检模块 CHANGELOG
|
||||
|
||||
## [Unreleased] 2026-09-18
|
||||
|
||||
### Added
|
||||
- 检后侧边栏新增「体检影像管理」二级菜单(位于冠脉CTA体检分组之后),复刻老系统 data-center-vue3 `views/imc` 四个列表页为纯 HTML 原型:
|
||||
- `post-imc-user.html`(用户体检信息):筛选(姓名/身份证号/体检年份/医院名称);行勾选 + 批量删除;主表列(单位信息/姓名/身份证号/体检年份/医院名称/体检编号/创建日期);行首箭头展开子表(检查项目名称/处理状态/影像信息·预览/影像报告·查看,无数据显示「暂无/无文件」);操作列编辑/详情/删除 + 编辑弹窗(7 字段)+ 详情弹窗
|
||||
- `post-imc-class.html`(用户影像文件分类):筛选(影像分类/检查项目名称/处理状态);操作栏新增/导出/导入 + 批量删除;列(影像分类/检查项目名称/影像文件类型/报告文件类型/处理状态/检查结果/错误信息/出报告时间/创建日期),检查结果与错误信息长文本截断、悬停显示全文;操作列编辑/详情/删除 + 新增/编辑弹窗(10 字段)+ 详情弹窗
|
||||
- `post-imc-info.html`(用户影像文件详细):筛选(文件类型/患者ID/研究实例ID);操作栏新增/导出/导入 + 批量删除;列(文件类型·影像/报告标签/影像序号/错误信息/文件地址·下载/dcm实例ID/研究实例ID/患者ID/研究ID/创建日期);操作列编辑/详情/删除 + 新增/编辑弹窗(10 字段)+ 详情弹窗
|
||||
- `post-imc-log.html`(文件处理日志):筛选(身份证号/体检年份/体检编号/影像分类/处理状态);行勾选 + 批量删除;列(医院名称/姓名/身份证号/体检年份/体检编号/影像分类/json数据·截断/文件地址·下载zip/文件大小MB/处理状态/错误信息/传输开始/传输完成/解析开始/解析完成时间),默认按传输开始时间倒序;操作列详情/删除 + 详情弹窗(15 字段含 json 数据代码块)
|
||||
- 数据字典沿用老系统:影像分类(超声/CT/MRI/X射线/心电)、处理状态(新建/待解析/失败/解析中/成功/失败待重试/最终失败,彩色标签)、文件类型(影像/报告)
|
||||
- `index.html` SITE_MAP 健康体检模块新增「用户体检信息/用户影像文件分类/用户影像文件详细/文件处理日志」四个入口
|
||||
- 25 个检后页面侧边栏统一新增「体检影像管理」分组(21 个存量页面批量同步 + 4 个新页面自身 active 指向)
|
||||
|
||||
## [Unreleased] 2026-09-17
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -198,6 +198,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -181,6 +181,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -208,6 +208,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -172,6 +172,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -239,6 +239,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -198,6 +198,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item active">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -206,6 +206,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -181,6 +181,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -194,6 +194,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -198,6 +198,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -181,6 +181,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -208,6 +208,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -0,0 +1,619 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>健康体检 - 用户影像文件分类 | 健康CQ原型</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
:root{
|
||||
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
|
||||
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
|
||||
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;--font-xl:20px;--font-xxl:24px;
|
||||
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
|
||||
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);--shadow-md:0 4px 12px rgba(0,0,0,0.12);
|
||||
}
|
||||
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
|
||||
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
|
||||
.top-bar__logo svg{width:28px;height:28px;}
|
||||
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
|
||||
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
|
||||
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
|
||||
.top-bar__nav a.active{color:#fff;background:var(--primary);}
|
||||
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
|
||||
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
|
||||
.top-bar__right .btn-back:hover{color:#fff;}
|
||||
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
|
||||
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
|
||||
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
|
||||
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
|
||||
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;padding-left:16px;}
|
||||
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
|
||||
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
|
||||
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
|
||||
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
|
||||
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:170px;}
|
||||
.filter-input:focus{border-color:var(--primary);}
|
||||
.filter-input::placeholder{color:var(--text-placeholder);}
|
||||
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:140px;}
|
||||
.filter-select:focus{border-color:var(--primary);}
|
||||
.filter-select.placeholder{color:var(--text-placeholder);}
|
||||
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
|
||||
.table-card__content table{min-width:100%;white-space:nowrap;}
|
||||
table{width:100%;border-collapse:collapse;}
|
||||
thead th{background:#FAFAFA;padding:12px 16px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;text-align:center;}
|
||||
tbody tr:last-child td{border-bottom:none;}
|
||||
tbody tr:hover{background:#F8FBFF;}
|
||||
#classTable thead th:last-child{position:sticky;right:0;background:#FAFAFA;border-left:1px solid var(--border);}
|
||||
#classTable tbody td:last-child{position:sticky;right:0;background:#fff;border-left:1px solid var(--border);}
|
||||
#classTable tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
|
||||
.link-danger{color:var(--danger);cursor:pointer;font-size:var(--font-sm);}.link-danger:hover{color:#ff7875;}
|
||||
.empty-tip{padding:48px 0;text-align:center;font-size:var(--font-sm);color:var(--text-placeholder);}
|
||||
.muted{color:var(--text-placeholder);}
|
||||
.tag{display:inline-flex;align-items:center;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);}
|
||||
.tag-blue{background:#E6F7FF;color:#1890FF;}
|
||||
.tag-green{background:#F6FFED;color:#52C41A;}
|
||||
.tag-orange{background:#FFF7E6;color:#FA8C16;}
|
||||
.tag-red{background:#FFF1F0;color:#FF4D4F;}
|
||||
.tag-gray{background:#FAFAFA;color:#999;}
|
||||
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);flex-wrap:wrap;}
|
||||
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
|
||||
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;color:var(--text-primary);}
|
||||
.page-btn:hover:not(:disabled),.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
|
||||
.page-btn:disabled{color:var(--text-placeholder);cursor:not-allowed;background:#FAFAFA;}
|
||||
.page-ellipsis{width:24px;text-align:center;color:var(--text-placeholder);font-size:var(--font-sm);}
|
||||
.page-size{height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 24px 0 10px;font-size:var(--font-sm);color:var(--text-primary);background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 8px center;appearance:none;cursor:pointer;outline:none;}
|
||||
.page-jump input{width:48px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);text-align:center;font-size:var(--font-sm);outline:none;margin:0 4px;}
|
||||
.page-jump input:focus{border-color:var(--primary);}
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,0.45);z-index:200;overflow-y:auto;}
|
||||
.modal-mask.open{display:flex;align-items:flex-start;justify-content:center;padding:60px 24px;}
|
||||
.modal{width:640px;max-width:100%;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);display:flex;flex-direction:column;max-height:calc(100vh - 120px);}
|
||||
.modal__header{display:flex;align-items:center;gap:12px;padding:16px 20px;border-bottom:1px solid var(--border);flex-shrink:0;}
|
||||
.modal__close{cursor:pointer;color:var(--text-secondary);display:flex;align-items:center;transition:color .2s;}
|
||||
.modal__close:hover{color:var(--danger);}
|
||||
.modal__title{font-size:var(--font-base);font-weight:600;}
|
||||
.modal__body{padding:20px;overflow-y:auto;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:14px 20px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
.form-item{margin-bottom:16px;}
|
||||
.form-item:last-child{margin-bottom:0;}
|
||||
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:6px;display:flex;align-items:center;gap:4px;font-weight:500;}
|
||||
.form-label .required{color:var(--danger);}
|
||||
.form-input{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
|
||||
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
|
||||
.form-input::placeholder{color:var(--text-placeholder);}
|
||||
.form-select{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;}
|
||||
.form-select:focus{border-color:var(--primary);}
|
||||
.form-textarea{width:100%;border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;resize:vertical;min-height:72px;font-family:inherit;}
|
||||
.form-textarea:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
|
||||
.detail-table{width:100%;border-collapse:collapse;border:1px solid var(--border);}
|
||||
.detail-table th,.detail-table td{border-bottom:1px solid var(--border);text-align:left;padding:12px 16px;font-size:var(--font-sm);}
|
||||
.detail-table tr:last-child td{border-bottom:none;}
|
||||
.detail-table th{width:130px;background:#FAFAFA;color:var(--text-secondary);font-weight:500;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="top-bar">
|
||||
<div class="top-bar__logo">
|
||||
<svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
|
||||
健康体检
|
||||
</div>
|
||||
<nav class="top-bar__nav">
|
||||
<a href="archive-personal.html">档案</a>
|
||||
<a href="config-material-notice.html">基础配置</a>
|
||||
<a href="pre-hospital-scope.html">检前</a>
|
||||
<a href="mid-appointment-track.html">检中</a>
|
||||
<a href="post-unit-count.html" class="active">检后</a>
|
||||
<a href="exception-dirty.html">异常事件</a>
|
||||
</nav>
|
||||
<div class="top-bar__right">
|
||||
<a class="btn-back" href="../../index.html">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
返回首页
|
||||
</a>
|
||||
<div class="avatar">管</div>
|
||||
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">检后</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
常规体检
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-report-employee.html" class="sidebar-item">常规体检报告</a>
|
||||
<a href="post-employee-master.html" class="sidebar-item">员工体检大表</a>
|
||||
<a href="post-illness-personnel.html" class="sidebar-item">大病人员信息</a>
|
||||
<a href="post-indicator-notify.html" class="sidebar-item">指标异常通知</a>
|
||||
<a href="post-report-unmatched.html" class="sidebar-item">体检报告未匹配项目</a>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检统计汇总
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-unit-count.html" class="sidebar-item">单位体检人数统计</a>
|
||||
<a href="post-unit-cost-stat.html" class="sidebar-item">单位体检费用统计</a>
|
||||
<a href="post-hospital-count.html" class="sidebar-item">医院体检人数统计</a>
|
||||
<a href="post-doctor-count.html" class="sidebar-item">医生检查人数统计</a>
|
||||
<a href="post-item-stat.html" class="sidebar-item">医院体检项目统计</a>
|
||||
<a href="post-cancer-screening.html" class="sidebar-item">防癌筛查人数统计</a>
|
||||
<a href="post-standard-stat.html" class="sidebar-item">系统标准化项目统计</a>
|
||||
<a href="post-contracted-hospital.html" class="sidebar-item">签约医院人数统计</a>
|
||||
<a href="post-key-indicator-stat.html" class="sidebar-item">重点指标异常统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
病种信息管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-disease-info.html" class="sidebar-item">病种信息配置</a>
|
||||
<a href="post-conclusion-disease.html" class="sidebar-item">体检结论关联病种</a>
|
||||
<a href="post-auto-select-disease.html" class="sidebar-item">员工病种信息</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
胃肠镜体检
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-report-gastro.html" class="sidebar-item">胃肠镜体检报告</a>
|
||||
<a href="post-gastro-stat.html" class="sidebar-item">胃肠镜体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
冠脉CTA体检
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-cta-report.html" class="sidebar-item">冠脉CTA体检报告</a>
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item active">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="main">
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>影像分类:</label>
|
||||
<select class="filter-select placeholder" id="f-imgclass" onchange="this.classList.toggle('placeholder',!this.value)">
|
||||
<option value="">请选择影像分类</option>
|
||||
<option value="超声">超声</option>
|
||||
<option value="CT">CT</option>
|
||||
<option value="MRI">MRI</option>
|
||||
<option value="X射线">X射线</option>
|
||||
<option value="心电">心电</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>检查项目名称:</label>
|
||||
<input class="filter-input" type="text" id="f-name" placeholder="请输入检查项目名称" style="min-width:180px;">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>处理状态:</label>
|
||||
<select class="filter-select placeholder" id="f-status" onchange="this.classList.toggle('placeholder',!this.value)">
|
||||
<option value="">请选择处理状态</option>
|
||||
<option value="1">新建</option>
|
||||
<option value="2">待解析</option>
|
||||
<option value="4">解析中</option>
|
||||
<option value="5">成功</option>
|
||||
<option value="6">失败待重试</option>
|
||||
<option value="3">失败</option>
|
||||
<option value="7">最终失败</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="margin-left:auto;display:flex;gap:12px;">
|
||||
<button class="btn btn-primary" onclick="doQuery()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6" cy="6" r="4.5" stroke="#fff" stroke-width="1.4"/><path d="M9.5 9.5l3 3" stroke="#fff" stroke-width="1.4" stroke-linecap="round"/></svg>
|
||||
查询
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="doReset()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M12 7a5 5 0 1 1-1.5-3.6M12 1.5V4h-2.5" stroke="#666" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
重置
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;gap:12px;margin-bottom:16px;align-items:center;">
|
||||
<button class="btn btn-primary" onclick="openForm(null)">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 2v10M2 7h10" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/></svg>
|
||||
新增
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="exportList()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 2v7M4 6l3 3 3-3M2 12.5h10" stroke="#666" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
导出
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="importList()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 9V2M4 5l3-3 3 3M2 12.5h10" stroke="#666" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
导入
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="batchDelete()" style="margin-left:auto;">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 3.5h10M5.5 3.5V2h3v1.5M3.5 3.5l.7 8.5h5.6l.7-8.5" stroke="#666" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
批量删除
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card__content">
|
||||
<table id="classTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:48px;"><input type="checkbox" id="checkAll" onclick="toggleCheckAll(this)"></th>
|
||||
<th style="width:56px;">序号</th>
|
||||
<th>影像分类</th>
|
||||
<th>检查项目名称</th>
|
||||
<th>影像文件类型</th>
|
||||
<th>报告文件类型</th>
|
||||
<th>处理状态</th>
|
||||
<th>检查结果</th>
|
||||
<th>错误信息</th>
|
||||
<th>出报告时间</th>
|
||||
<th>创建日期</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pagination" id="pagination"></div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div class="modal-mask" id="formMask" onclick="if(event.target===this)closeForm()">
|
||||
<div class="modal">
|
||||
<div class="modal__header">
|
||||
<span class="modal__close" onclick="closeForm()">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3.5 3.5l9 9M12.5 3.5l-9 9" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
|
||||
</span>
|
||||
<span class="modal__title" id="formTitle">新增用户影像文件分类</span>
|
||||
</div>
|
||||
<div class="modal__body">
|
||||
<div class="form-item">
|
||||
<div class="form-label">用户体检信息ID</div>
|
||||
<input class="form-input" id="formMuid" type="text" placeholder="请输入用户体检信息ID">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label"><span class="required">*</span> 影像分类</div>
|
||||
<select class="form-select" id="formImgclass">
|
||||
<option value="超声">超声</option>
|
||||
<option value="CT">CT</option>
|
||||
<option value="MRI">MRI</option>
|
||||
<option value="X射线">X射线</option>
|
||||
<option value="心电">心电</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label"><span class="required">*</span> 检查项目名称</div>
|
||||
<input class="form-input" id="formName" type="text" placeholder="请输入检查项目名称">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">影像文件类型</div>
|
||||
<select class="form-select" id="formImgtype">
|
||||
<option value="非DICOM">非DICOM</option>
|
||||
<option value="dic">dic</option>
|
||||
<option value="dcm">dcm</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">报告文件类型</div>
|
||||
<select class="form-select" id="formReptype">
|
||||
<option value="png">png</option>
|
||||
<option value="jpg">jpg</option>
|
||||
<option value="pdf">pdf</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">处理状态</div>
|
||||
<select class="form-select" id="formStatus">
|
||||
<option value="1">新建</option>
|
||||
<option value="2">待解析</option>
|
||||
<option value="3">失败</option>
|
||||
<option value="4">解析中</option>
|
||||
<option value="5">成功</option>
|
||||
<option value="6">失败待重试</option>
|
||||
<option value="7">最终失败</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">检查结果</div>
|
||||
<textarea class="form-textarea" id="formContent" placeholder="请输入检查结果"></textarea>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">错误信息</div>
|
||||
<textarea class="form-textarea" id="formMsg" placeholder="请输入错误信息"></textarea>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">出报告时间</div>
|
||||
<input class="form-input" id="formReportdate" type="text" placeholder="如 2026-08-15 12:00:00">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">创建日期</div>
|
||||
<input class="form-input" id="formCreatetime" type="text" placeholder="如 2026-08-15 11:30:00">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeForm()">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveForm()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-mask" id="detailMask" onclick="if(event.target===this)closeDetail()">
|
||||
<div class="modal">
|
||||
<div class="modal__header">
|
||||
<span class="modal__close" onclick="closeDetail()">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3.5 3.5l9 9M12.5 3.5l-9 9" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
|
||||
</span>
|
||||
<span class="modal__title">用户影像文件分类详情</span>
|
||||
</div>
|
||||
<div class="modal__body" id="detailBody"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var handleStatusMap={1:'新建',2:'待解析',3:'失败',4:'解析中',5:'成功',6:'失败待重试',7:'最终失败'};
|
||||
function statusTag(s){
|
||||
var cls='tag-gray';
|
||||
if(s===5)cls='tag-green';
|
||||
else if(s===4||s===6)cls='tag-orange';
|
||||
else if(s===3||s===7)cls='tag-red';
|
||||
else if(s===1)cls='tag-blue';
|
||||
return '<span class="tag '+cls+'">'+handleStatusMap[s]+'</span>';
|
||||
}
|
||||
var rows=[
|
||||
{imgClass:'CT',name:'胸部CT平扫',imgType:'dcm',repType:'pdf',status:5,content:'双肺纹理清晰,未见明显异常密度影,纵隔及肺门未见肿大淋巴结。',msg:'',reportDate:'2026-08-15 12:00:00',createTime:'2026-08-15 11:30:00',muId:'MU1001'},
|
||||
{imgClass:'MRI',name:'头颅MRI平扫',imgType:'dcm',repType:'pdf',status:5,content:'颅脑平扫未见明显异常信号影,脑室系统形态正常。',msg:'',reportDate:'2026-08-15 13:10:00',createTime:'2026-08-15 12:30:00',muId:'MU1001'},
|
||||
{imgClass:'超声',name:'腹部超声',imgType:'非DICOM',repType:'png',status:4,content:'',msg:'',reportDate:'',createTime:'2026-08-15 14:00:00',muId:'MU1001'},
|
||||
{imgClass:'CT',name:'胸部CT平扫',imgType:'dcm',repType:'pdf',status:5,content:'双肺纹理清晰,右肺上叶见微小结节影,建议随访。',msg:'',reportDate:'2026-08-15 15:20:00',createTime:'2026-08-15 14:50:00',muId:'MU1002'},
|
||||
{imgClass:'心电',name:'心电图',imgType:'非DICOM',repType:'jpg',status:5,content:'窦性心律,正常心电图。',msg:'',reportDate:'2026-08-15 15:40:00',createTime:'2026-08-15 15:10:00',muId:'MU1002'},
|
||||
{imgClass:'X射线',name:'胸部X射线',imgType:'dcm',repType:'jpg',status:7,content:'',msg:'DICOM标签解析失败:缺少 PatientID 标签',reportDate:'',createTime:'2026-08-15 16:00:00',muId:'MU1003'},
|
||||
{imgClass:'超声',name:'腹部超声',imgType:'非DICOM',repType:'png',status:6,content:'',msg:'文件服务器上传超时,等待重试',reportDate:'',createTime:'2026-08-15 16:20:00',muId:'MU1003'},
|
||||
{imgClass:'CT',name:'冠脉CTA',imgType:'dcm',repType:'pdf',status:2,content:'',msg:'',reportDate:'',createTime:'2026-08-16 09:12:00',muId:'MU1004'},
|
||||
{imgClass:'CT',name:'胸部CT平扫',imgType:'dcm',repType:'pdf',status:5,content:'双肺纹理清晰,未见明显异常。',msg:'',reportDate:'2025-08-20 16:00:00',createTime:'2025-08-20 15:30:00',muId:'MU1018'},
|
||||
{imgClass:'MRI',name:'头颅MRI平扫',imgType:'dcm',repType:'pdf',status:5,content:'颅脑平扫未见明显异常。',msg:'',reportDate:'2025-08-20 16:30:00',createTime:'2025-08-20 16:00:00',muId:'MU1018'},
|
||||
{imgClass:'超声',name:'腹部超声',imgType:'非DICOM',repType:'png',status:5,content:'肝胆胰脾肾未见明显异常。',msg:'',reportDate:'2025-08-21 10:00:00',createTime:'2025-08-21 09:30:00',muId:'MU1021'},
|
||||
{imgClass:'超声',name:'腹部超声',imgType:'非DICOM',repType:'png',status:7,content:'',msg:'报告文件格式与声明类型不一致',reportDate:'',createTime:'2025-08-21 11:00:00',muId:'MU1021'}
|
||||
];
|
||||
var state={imgclass:'',name:'',status:'',page:1,pageSize:10};
|
||||
|
||||
function doQuery(){
|
||||
state.imgclass=document.getElementById('f-imgclass').value;
|
||||
state.name=document.getElementById('f-name').value.trim();
|
||||
state.status=document.getElementById('f-status').value;
|
||||
state.page=1;
|
||||
renderTable();
|
||||
}
|
||||
function doReset(){
|
||||
var ic=document.getElementById('f-imgclass');ic.value='';ic.classList.add('placeholder');
|
||||
document.getElementById('f-name').value='';
|
||||
var st=document.getElementById('f-status');st.value='';st.classList.add('placeholder');
|
||||
state.imgclass='';state.name='';state.status='';
|
||||
state.page=1;
|
||||
renderTable();
|
||||
}
|
||||
|
||||
function filteredRows(){
|
||||
return rows.filter(function(r){
|
||||
if(state.imgclass&&r.imgClass!==state.imgclass)return false;
|
||||
if(state.name&&r.name.indexOf(state.name)===-1)return false;
|
||||
if(state.status&&String(r.status)!==state.status)return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
function renderTable(){
|
||||
var list=filteredRows();
|
||||
var totalPages=Math.max(1,Math.ceil(list.length/state.pageSize));
|
||||
if(state.page>totalPages)state.page=totalPages;
|
||||
var start=(state.page-1)*state.pageSize;
|
||||
var pageRows=list.slice(start,start+state.pageSize);
|
||||
var tbody=document.getElementById('tbody');
|
||||
tbody.innerHTML=pageRows.length?pageRows.map(function(r,pos){
|
||||
var idx=rows.indexOf(r);
|
||||
var content=r.content?r.content:'<span class="muted">—</span>';
|
||||
if(r.content&&r.content.length>18)content='<span title="'+r.content+'">'+r.content.slice(0,18)+'…</span>';
|
||||
var msg=r.msg?r.msg:'<span class="muted">—</span>';
|
||||
if(r.msg&&r.msg.length>18)msg='<span title="'+r.msg+'">'+r.msg.slice(0,18)+'…</span>';
|
||||
return '<tr>'
|
||||
+'<td><input type="checkbox" class="row-check" data-idx="'+idx+'"></td>'
|
||||
+'<td>'+(start+pos+1)+'</td>'
|
||||
+'<td>'+r.imgClass+'</td><td>'+r.name+'</td><td>'+r.imgType+'</td><td>'+r.repType+'</td>'
|
||||
+'<td>'+statusTag(r.status)+'</td><td style="text-align:left;">'+content+'</td><td style="text-align:left;">'+msg+'</td>'
|
||||
+'<td>'+(r.reportDate||'<span class="muted">—</span>')+'</td><td>'+r.createTime+'</td>'
|
||||
+'<td><span class="link" onclick="openForm('+idx+')">编辑</span> <span class="link" style="margin-left:8px;" onclick="openDetail('+idx+')">详情</span> <span class="link-danger" style="margin-left:8px;" onclick="deleteRow('+idx+')">删除</span></td>'
|
||||
+'</tr>';
|
||||
}).join(''):'<tr><td colspan="12"><div class="empty-tip">暂无数据</div></td></tr>';
|
||||
var all=tbody.querySelectorAll('.row-check');
|
||||
var checked=tbody.querySelectorAll('.row-check:checked');
|
||||
document.getElementById('checkAll').checked=all.length>0&&all.length===checked.length;
|
||||
renderPagination(list.length,totalPages);
|
||||
}
|
||||
|
||||
function pageSeq(p,last){
|
||||
var seq=[];
|
||||
if(last<=7){for(var i=1;i<=last;i++)seq.push(i);return seq;}
|
||||
if(p<=4){seq=[1,2,3,4,5,'...',last];}
|
||||
else if(p>=last-3){seq=[1,'...',last-4,last-3,last-2,last-1,last];}
|
||||
else{seq=[1,'...',p-1,p,p+1,'...',last];}
|
||||
return seq;
|
||||
}
|
||||
function renderPagination(total,totalPages){
|
||||
var html='<span>共 '+total+' 条数据</span>';
|
||||
if(totalPages>1){
|
||||
html+='<button class="page-btn"'+(state.page===1?' disabled':'')+' onclick="goPage('+(state.page-1)+')"><</button>';
|
||||
pageSeq(state.page,totalPages).forEach(function(p){
|
||||
if(p==='...')html+='<span class="page-ellipsis">...</span>';
|
||||
else html+='<button class="page-btn'+(p===state.page?' active':'')+'" onclick="goPage('+p+')">'+p+'</button>';
|
||||
});
|
||||
html+='<button class="page-btn"'+(state.page===totalPages?' disabled':'')+' onclick="goPage('+(state.page+1)+')">></button>';
|
||||
}
|
||||
html+='<select class="page-size" onchange="changeSize(this.value)">'
|
||||
+[10,20,50].map(function(n){return '<option value="'+n+'"'+(n===state.pageSize?' selected':'')+'>'+n+'条/页</option>';}).join('')
|
||||
+'</select>';
|
||||
html+='<span class="page-jump">跳至<input type="number" id="jumpInput" min="1" value="'+state.page+'" onkeydown="if(event.key===\'Enter\')jumpTo('+totalPages+')">页<button class="page-btn" onclick="jumpTo('+totalPages+')">跳</button></span>';
|
||||
document.getElementById('pagination').innerHTML=html;
|
||||
}
|
||||
function goPage(p){state.page=p;renderTable();}
|
||||
function changeSize(v){state.pageSize=parseInt(v,10);state.page=1;renderTable();}
|
||||
function jumpTo(totalPages){
|
||||
var input=document.getElementById('jumpInput');
|
||||
var p=parseInt(input.value,10);
|
||||
if(isNaN(p)||p<1)p=1;
|
||||
if(p>totalPages)p=totalPages;
|
||||
state.page=p;
|
||||
renderTable();
|
||||
}
|
||||
|
||||
function toggleCheckAll(cb){
|
||||
document.querySelectorAll('.row-check').forEach(function(c){c.checked=cb.checked;});
|
||||
}
|
||||
function checkedIdx(){
|
||||
var arr=[];
|
||||
document.querySelectorAll('.row-check:checked').forEach(function(c){arr.push(parseInt(c.dataset.idx,10));});
|
||||
return arr;
|
||||
}
|
||||
function batchDelete(){
|
||||
var idxs=checkedIdx();
|
||||
if(!idxs.length){alert('请先勾选要删除的记录');return;}
|
||||
if(!confirm('确认删除选中的 '+idxs.length+' 条记录?'))return;
|
||||
idxs.sort(function(a,b){return b-a;}).forEach(function(i){rows.splice(i,1);});
|
||||
renderTable();
|
||||
}
|
||||
function deleteRow(idx){
|
||||
if(!confirm('确认删除该影像文件分类记录?'))return;
|
||||
rows.splice(idx,1);
|
||||
renderTable();
|
||||
}
|
||||
function exportList(){alert('导出当前筛选结果(Excel)');}
|
||||
function importList(){alert('导入影像文件分类数据(Excel)');}
|
||||
|
||||
var editingIdx=null;
|
||||
function openForm(idx){
|
||||
editingIdx=idx;
|
||||
document.getElementById('formTitle').textContent=idx===null?'新增用户影像文件分类':'编辑用户影像文件分类';
|
||||
if(idx===null){
|
||||
document.getElementById('formMuid').value='';
|
||||
document.getElementById('formImgclass').value='超声';
|
||||
document.getElementById('formName').value='';
|
||||
document.getElementById('formImgtype').value='dcm';
|
||||
document.getElementById('formReptype').value='pdf';
|
||||
document.getElementById('formStatus').value='1';
|
||||
document.getElementById('formContent').value='';
|
||||
document.getElementById('formMsg').value='';
|
||||
document.getElementById('formReportdate').value='';
|
||||
document.getElementById('formCreatetime').value='';
|
||||
}else{
|
||||
var r=rows[idx];
|
||||
document.getElementById('formMuid').value=r.muId;
|
||||
document.getElementById('formImgclass').value=r.imgClass;
|
||||
document.getElementById('formName').value=r.name;
|
||||
document.getElementById('formImgtype').value=r.imgType;
|
||||
document.getElementById('formReptype').value=r.repType;
|
||||
document.getElementById('formStatus').value=String(r.status);
|
||||
document.getElementById('formContent').value=r.content;
|
||||
document.getElementById('formMsg').value=r.msg;
|
||||
document.getElementById('formReportdate').value=r.reportDate;
|
||||
document.getElementById('formCreatetime').value=r.createTime;
|
||||
}
|
||||
document.getElementById('formMask').classList.add('open');
|
||||
}
|
||||
function closeForm(){document.getElementById('formMask').classList.remove('open');}
|
||||
function saveForm(){
|
||||
var name=document.getElementById('formName').value.trim();
|
||||
if(!name){alert('请输入检查项目名称');return;}
|
||||
var data={
|
||||
imgClass:document.getElementById('formImgclass').value,
|
||||
name:name,
|
||||
imgType:document.getElementById('formImgtype').value,
|
||||
repType:document.getElementById('formReptype').value,
|
||||
status:parseInt(document.getElementById('formStatus').value,10),
|
||||
content:document.getElementById('formContent').value.trim(),
|
||||
msg:document.getElementById('formMsg').value.trim(),
|
||||
reportDate:document.getElementById('formReportdate').value.trim(),
|
||||
createTime:document.getElementById('formCreatetime').value.trim(),
|
||||
muId:document.getElementById('formMuid').value.trim()
|
||||
};
|
||||
if(editingIdx===null){
|
||||
rows.unshift(data);
|
||||
}else{
|
||||
rows[editingIdx]=data;
|
||||
}
|
||||
closeForm();
|
||||
renderTable();
|
||||
}
|
||||
|
||||
function openDetail(idx){
|
||||
var r=rows[idx];
|
||||
document.getElementById('detailBody').innerHTML=
|
||||
'<table class="detail-table"><tbody>'
|
||||
+'<tr><th>用户体检信息ID</th><td>'+r.muId+'</td></tr>'
|
||||
+'<tr><th>影像分类</th><td>'+r.imgClass+'</td></tr>'
|
||||
+'<tr><th>检查项目名称</th><td>'+r.name+'</td></tr>'
|
||||
+'<tr><th>影像文件类型</th><td>'+r.imgType+'</td></tr>'
|
||||
+'<tr><th>报告文件类型</th><td>'+r.repType+'</td></tr>'
|
||||
+'<tr><th>处理状态</th><td>'+handleStatusMap[r.status]+'</td></tr>'
|
||||
+'<tr><th>检查结果</th><td>'+(r.content||'<span class="muted">—</span>')+'</td></tr>'
|
||||
+'<tr><th>错误信息</th><td>'+(r.msg||'<span class="muted">—</span>')+'</td></tr>'
|
||||
+'<tr><th>出报告时间</th><td>'+(r.reportDate||'<span class="muted">—</span>')+'</td></tr>'
|
||||
+'<tr><th>创建日期</th><td>'+r.createTime+'</td></tr>'
|
||||
+'</tbody></table>';
|
||||
document.getElementById('detailMask').classList.add('open');
|
||||
}
|
||||
function closeDetail(){document.getElementById('detailMask').classList.remove('open');}
|
||||
document.addEventListener('keydown',function(e){
|
||||
if(e.key==='Escape'){closeForm();closeDetail();}
|
||||
});
|
||||
|
||||
function toggleSubgroup(header){
|
||||
header.parentElement.classList.toggle('open');
|
||||
}
|
||||
(function(){
|
||||
renderTable();
|
||||
var active=document.querySelector('.sidebar-item.active');
|
||||
if(!active)return;
|
||||
var sub=active.closest('.sidebar-subgroup');
|
||||
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,580 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>健康体检 - 用户影像文件详细 | 健康CQ原型</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
:root{
|
||||
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
|
||||
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
|
||||
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;--font-xl:20px;--font-xxl:24px;
|
||||
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
|
||||
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);--shadow-md:0 4px 12px rgba(0,0,0,0.12);
|
||||
}
|
||||
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
|
||||
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
|
||||
.top-bar__logo svg{width:28px;height:28px;}
|
||||
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
|
||||
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
|
||||
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
|
||||
.top-bar__nav a.active{color:#fff;background:var(--primary);}
|
||||
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
|
||||
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
|
||||
.top-bar__right .btn-back:hover{color:#fff;}
|
||||
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
|
||||
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
|
||||
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
|
||||
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
|
||||
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;padding-left:16px;}
|
||||
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
|
||||
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
|
||||
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
|
||||
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
|
||||
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:190px;}
|
||||
.filter-input:focus{border-color:var(--primary);}
|
||||
.filter-input::placeholder{color:var(--text-placeholder);}
|
||||
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:130px;}
|
||||
.filter-select:focus{border-color:var(--primary);}
|
||||
.filter-select.placeholder{color:var(--text-placeholder);}
|
||||
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
|
||||
.table-card__content table{min-width:100%;white-space:nowrap;}
|
||||
table{width:100%;border-collapse:collapse;}
|
||||
thead th{background:#FAFAFA;padding:12px 16px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;text-align:center;}
|
||||
tbody tr:last-child td{border-bottom:none;}
|
||||
tbody tr:hover{background:#F8FBFF;}
|
||||
#infoTable thead th:last-child{position:sticky;right:0;background:#FAFAFA;border-left:1px solid var(--border);}
|
||||
#infoTable tbody td:last-child{position:sticky;right:0;background:#fff;border-left:1px solid var(--border);}
|
||||
#infoTable tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
|
||||
.link-danger{color:var(--danger);cursor:pointer;font-size:var(--font-sm);}.link-danger:hover{color:#ff7875;}
|
||||
.empty-tip{padding:48px 0;text-align:center;font-size:var(--font-sm);color:var(--text-placeholder);}
|
||||
.muted{color:var(--text-placeholder);}
|
||||
.tag{display:inline-flex;align-items:center;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);}
|
||||
.tag-blue{background:#E6F7FF;color:#1890FF;}
|
||||
.tag-purple{background:#F9F0FF;color:#722ED1;}
|
||||
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);flex-wrap:wrap;}
|
||||
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
|
||||
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;color:var(--text-primary);}
|
||||
.page-btn:hover:not(:disabled),.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
|
||||
.page-btn:disabled{color:var(--text-placeholder);cursor:not-allowed;background:#FAFAFA;}
|
||||
.page-ellipsis{width:24px;text-align:center;color:var(--text-placeholder);font-size:var(--font-sm);}
|
||||
.page-size{height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 24px 0 10px;font-size:var(--font-sm);color:var(--text-primary);background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 8px center;appearance:none;cursor:pointer;outline:none;}
|
||||
.page-jump input{width:48px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);text-align:center;font-size:var(--font-sm);outline:none;margin:0 4px;}
|
||||
.page-jump input:focus{border-color:var(--primary);}
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,0.45);z-index:200;overflow-y:auto;}
|
||||
.modal-mask.open{display:flex;align-items:flex-start;justify-content:center;padding:60px 24px;}
|
||||
.modal{width:640px;max-width:100%;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);display:flex;flex-direction:column;max-height:calc(100vh - 120px);}
|
||||
.modal__header{display:flex;align-items:center;gap:12px;padding:16px 20px;border-bottom:1px solid var(--border);flex-shrink:0;}
|
||||
.modal__close{cursor:pointer;color:var(--text-secondary);display:flex;align-items:center;transition:color .2s;}
|
||||
.modal__close:hover{color:var(--danger);}
|
||||
.modal__title{font-size:var(--font-base);font-weight:600;}
|
||||
.modal__body{padding:20px;overflow-y:auto;}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:14px 20px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
.form-item{margin-bottom:16px;}
|
||||
.form-item:last-child{margin-bottom:0;}
|
||||
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:6px;display:flex;align-items:center;gap:4px;font-weight:500;}
|
||||
.form-label .required{color:var(--danger);}
|
||||
.form-input{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
|
||||
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
|
||||
.form-input::placeholder{color:var(--text-placeholder);}
|
||||
.form-select{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;}
|
||||
.form-select:focus{border-color:var(--primary);}
|
||||
.form-textarea{width:100%;border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;resize:vertical;min-height:72px;font-family:inherit;}
|
||||
.form-textarea:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
|
||||
.detail-table{width:100%;border-collapse:collapse;border:1px solid var(--border);}
|
||||
.detail-table th,.detail-table td{border-bottom:1px solid var(--border);text-align:left;padding:12px 16px;font-size:var(--font-sm);word-break:break-all;}
|
||||
.detail-table tr:last-child td{border-bottom:none;}
|
||||
.detail-table th{width:130px;background:#FAFAFA;color:var(--text-secondary);font-weight:500;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="top-bar">
|
||||
<div class="top-bar__logo">
|
||||
<svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
|
||||
健康体检
|
||||
</div>
|
||||
<nav class="top-bar__nav">
|
||||
<a href="archive-personal.html">档案</a>
|
||||
<a href="config-material-notice.html">基础配置</a>
|
||||
<a href="pre-hospital-scope.html">检前</a>
|
||||
<a href="mid-appointment-track.html">检中</a>
|
||||
<a href="post-unit-count.html" class="active">检后</a>
|
||||
<a href="exception-dirty.html">异常事件</a>
|
||||
</nav>
|
||||
<div class="top-bar__right">
|
||||
<a class="btn-back" href="../../index.html">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
返回首页
|
||||
</a>
|
||||
<div class="avatar">管</div>
|
||||
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">检后</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
常规体检
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-report-employee.html" class="sidebar-item">常规体检报告</a>
|
||||
<a href="post-employee-master.html" class="sidebar-item">员工体检大表</a>
|
||||
<a href="post-illness-personnel.html" class="sidebar-item">大病人员信息</a>
|
||||
<a href="post-indicator-notify.html" class="sidebar-item">指标异常通知</a>
|
||||
<a href="post-report-unmatched.html" class="sidebar-item">体检报告未匹配项目</a>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检统计汇总
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-unit-count.html" class="sidebar-item">单位体检人数统计</a>
|
||||
<a href="post-unit-cost-stat.html" class="sidebar-item">单位体检费用统计</a>
|
||||
<a href="post-hospital-count.html" class="sidebar-item">医院体检人数统计</a>
|
||||
<a href="post-doctor-count.html" class="sidebar-item">医生检查人数统计</a>
|
||||
<a href="post-item-stat.html" class="sidebar-item">医院体检项目统计</a>
|
||||
<a href="post-cancer-screening.html" class="sidebar-item">防癌筛查人数统计</a>
|
||||
<a href="post-standard-stat.html" class="sidebar-item">系统标准化项目统计</a>
|
||||
<a href="post-contracted-hospital.html" class="sidebar-item">签约医院人数统计</a>
|
||||
<a href="post-key-indicator-stat.html" class="sidebar-item">重点指标异常统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
病种信息管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-disease-info.html" class="sidebar-item">病种信息配置</a>
|
||||
<a href="post-conclusion-disease.html" class="sidebar-item">体检结论关联病种</a>
|
||||
<a href="post-auto-select-disease.html" class="sidebar-item">员工病种信息</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
胃肠镜体检
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-report-gastro.html" class="sidebar-item">胃肠镜体检报告</a>
|
||||
<a href="post-gastro-stat.html" class="sidebar-item">胃肠镜体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
冠脉CTA体检
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-cta-report.html" class="sidebar-item">冠脉CTA体检报告</a>
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item active">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="main">
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>文件类型:</label>
|
||||
<select class="filter-select placeholder" id="f-filetype" onchange="this.classList.toggle('placeholder',!this.value)">
|
||||
<option value="">请选择文件类型</option>
|
||||
<option value="影像">影像</option>
|
||||
<option value="报告">报告</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>患者ID:</label>
|
||||
<input class="filter-input" type="text" id="f-patient" placeholder="请输入患者ID" style="min-width:160px;">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>研究实例ID:</label>
|
||||
<input class="filter-input" type="text" id="f-study" placeholder="请输入研究实例ID" style="min-width:220px;">
|
||||
</div>
|
||||
<div style="margin-left:auto;display:flex;gap:12px;">
|
||||
<button class="btn btn-primary" onclick="doQuery()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6" cy="6" r="4.5" stroke="#fff" stroke-width="1.4"/><path d="M9.5 9.5l3 3" stroke="#fff" stroke-width="1.4" stroke-linecap="round"/></svg>
|
||||
查询
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="doReset()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M12 7a5 5 0 1 1-1.5-3.6M12 1.5V4h-2.5" stroke="#666" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
重置
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;gap:12px;margin-bottom:16px;align-items:center;">
|
||||
<button class="btn btn-primary" onclick="openForm(null)">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 2v10M2 7h10" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/></svg>
|
||||
新增
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="exportList()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 2v7M4 6l3 3 3-3M2 12.5h10" stroke="#666" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
导出
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="importList()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 9V2M4 5l3-3 3 3M2 12.5h10" stroke="#666" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
导入
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="batchDelete()" style="margin-left:auto;">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 3.5h10M5.5 3.5V2h3v1.5M3.5 3.5l.7 8.5h5.6l.7-8.5" stroke="#666" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
批量删除
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card__content">
|
||||
<table id="infoTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:48px;"><input type="checkbox" id="checkAll" onclick="toggleCheckAll(this)"></th>
|
||||
<th style="width:56px;">序号</th>
|
||||
<th>文件类型</th>
|
||||
<th>影像序号</th>
|
||||
<th>错误信息</th>
|
||||
<th>文件地址</th>
|
||||
<th>dcm实例ID</th>
|
||||
<th>研究实例ID</th>
|
||||
<th>患者ID</th>
|
||||
<th>研究ID</th>
|
||||
<th>创建日期</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pagination" id="pagination"></div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div class="modal-mask" id="formMask" onclick="if(event.target===this)closeForm()">
|
||||
<div class="modal">
|
||||
<div class="modal__header">
|
||||
<span class="modal__close" onclick="closeForm()">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3.5 3.5l9 9M12.5 3.5l-9 9" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
|
||||
</span>
|
||||
<span class="modal__title" id="formTitle">新增用户影像文件详细</span>
|
||||
</div>
|
||||
<div class="modal__body">
|
||||
<div class="form-item">
|
||||
<div class="form-label">用户影像文件分类ID</div>
|
||||
<input class="form-input" id="formMuicid" type="text" placeholder="请输入用户影像文件分类ID">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label"><span class="required">*</span> 文件类型</div>
|
||||
<select class="form-select" id="formFiletype">
|
||||
<option value="影像">影像</option>
|
||||
<option value="报告">报告</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">影像序号</div>
|
||||
<input class="form-input" id="formImageno" type="text" placeholder="请输入影像序号">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">错误信息</div>
|
||||
<textarea class="form-textarea" id="formMsg" placeholder="请输入错误信息"></textarea>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label"><span class="required">*</span> 文件地址</div>
|
||||
<input class="form-input" id="formFileurl" type="text" placeholder="请输入文件地址">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">dcm实例ID</div>
|
||||
<input class="form-input" id="formInsid" type="text" placeholder="请输入dcm实例ID">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">研究实例ID</div>
|
||||
<input class="form-input" id="formStudyins" type="text" placeholder="请输入研究实例ID">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">患者ID</div>
|
||||
<input class="form-input" id="formPatient" type="text" placeholder="请输入患者ID">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">研究ID</div>
|
||||
<input class="form-input" id="formStudyid" type="text" placeholder="请输入研究ID">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">创建日期</div>
|
||||
<input class="form-input" id="formCreatetime" type="text" placeholder="如 2026-08-15 11:30:00">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeForm()">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveForm()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-mask" id="detailMask" onclick="if(event.target===this)closeDetail()">
|
||||
<div class="modal">
|
||||
<div class="modal__header">
|
||||
<span class="modal__close" onclick="closeDetail()">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3.5 3.5l9 9M12.5 3.5l-9 9" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
|
||||
</span>
|
||||
<span class="modal__title">用户影像文件详细</span>
|
||||
</div>
|
||||
<div class="modal__body" id="detailBody"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var rows=[
|
||||
{fileType:'影像',imageNo:'1',msg:'',fileUrl:'/files/imc/PE20260001/chest/1.dcm',insId:'1.2.840.113619.6.55.201.1',studyInsId:'1.2.840.113619.6.55.201',patientId:'PAT0001',studyId:'1.2.840.113619.6.55.201',createTime:'2026-08-15 11:30:00',muicId:'MC1001'},
|
||||
{fileType:'影像',imageNo:'2',msg:'',fileUrl:'/files/imc/PE20260001/chest/2.dcm',insId:'1.2.840.113619.6.55.202.1',studyInsId:'1.2.840.113619.6.55.202',patientId:'PAT0001',studyId:'1.2.840.113619.6.55.202',createTime:'2026-08-15 11:30:10',muicId:'MC1001'},
|
||||
{fileType:'报告',imageNo:'1',msg:'',fileUrl:'/files/imc/PE20260001/chest/report.pdf',insId:'',studyInsId:'1.2.840.113619.6.55.201',patientId:'PAT0001',studyId:'1.2.840.113619.6.55.201',createTime:'2026-08-15 12:00:00',muicId:'MC1001'},
|
||||
{fileType:'影像',imageNo:'1',msg:'',fileUrl:'/files/imc/PE20260001/mri/1.dcm',insId:'1.2.840.113619.6.55.203.1',studyInsId:'1.2.840.113619.6.55.203',patientId:'PAT0001',studyId:'1.2.840.113619.6.55.203',createTime:'2026-08-15 12:30:00',muicId:'MC1002'},
|
||||
{fileType:'报告',imageNo:'1',msg:'',fileUrl:'/files/imc/PE20260001/mri/report.pdf',insId:'',studyInsId:'1.2.840.113619.6.55.203',patientId:'PAT0001',studyId:'1.2.840.113619.6.55.203',createTime:'2026-08-15 13:10:00',muicId:'MC1002'},
|
||||
{fileType:'报告',imageNo:'1',msg:'',fileUrl:'/files/imc/PE20260002/chest/report.pdf',insId:'',studyInsId:'1.2.840.113619.6.55.301',patientId:'PAT0002',studyId:'1.2.840.113619.6.55.301',createTime:'2026-08-15 15:20:00',muicId:'MC1004'},
|
||||
{fileType:'影像',imageNo:'1',msg:'DICOM标签解析失败:缺少 PatientID 标签',fileUrl:'/files/imc/PE20260003/xray/1.dcm',insId:'1.2.840.113619.6.55.401.1',studyInsId:'1.2.840.113619.6.55.401',patientId:'',studyId:'1.2.840.113619.6.55.401',createTime:'2026-08-15 16:00:00',muicId:'MC1006'},
|
||||
{fileType:'报告',imageNo:'1',msg:'',fileUrl:'/files/imc/PE20260002/ecg/report.jpg',insId:'',studyInsId:'1.2.840.113619.6.55.302',patientId:'PAT0002',studyId:'1.2.840.113619.6.55.302',createTime:'2026-08-15 15:40:00',muicId:'MC1005'},
|
||||
{fileType:'影像',imageNo:'1',msg:'',fileUrl:'/files/imc/PE20250018/chest/1.dcm',insId:'1.2.840.113619.6.55.501.1',studyInsId:'1.2.840.113619.6.55.501',patientId:'PAT0005',studyId:'1.2.840.113619.6.55.501',createTime:'2025-08-20 15:30:00',muicId:'MC1009'},
|
||||
{fileType:'报告',imageNo:'1',msg:'',fileUrl:'/files/imc/PE20250018/chest/report.pdf',insId:'',studyInsId:'1.2.840.113619.6.55.501',patientId:'PAT0005',studyId:'1.2.840.113619.6.55.501',createTime:'2025-08-20 16:00:00',muicId:'MC1009'},
|
||||
{fileType:'报告',imageNo:'1',msg:'报告文件格式与声明类型不一致',fileUrl:'/files/imc/PE20250021/us/report.png',insId:'',studyInsId:'1.2.840.113619.6.55.602',patientId:'PAT0006',studyId:'1.2.840.113619.6.55.602',createTime:'2025-08-21 11:00:00',muicId:'MC1012'}
|
||||
];
|
||||
var state={filetype:'',patient:'',study:'',page:1,pageSize:10};
|
||||
|
||||
function fileTypeTag(t){
|
||||
return t==='影像'?'<span class="tag tag-blue">影像</span>':'<span class="tag tag-purple">报告</span>';
|
||||
}
|
||||
function doQuery(){
|
||||
state.filetype=document.getElementById('f-filetype').value;
|
||||
state.patient=document.getElementById('f-patient').value.trim();
|
||||
state.study=document.getElementById('f-study').value.trim();
|
||||
state.page=1;
|
||||
renderTable();
|
||||
}
|
||||
function doReset(){
|
||||
var ft=document.getElementById('f-filetype');ft.value='';ft.classList.add('placeholder');
|
||||
document.getElementById('f-patient').value='';
|
||||
document.getElementById('f-study').value='';
|
||||
state.filetype='';state.patient='';state.study='';
|
||||
state.page=1;
|
||||
renderTable();
|
||||
}
|
||||
|
||||
function filteredRows(){
|
||||
return rows.filter(function(r){
|
||||
if(state.filetype&&r.fileType!==state.filetype)return false;
|
||||
if(state.patient&&r.patientId.indexOf(state.patient)===-1)return false;
|
||||
if(state.study&&r.studyInsId.indexOf(state.study)===-1)return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
function renderTable(){
|
||||
var list=filteredRows();
|
||||
var totalPages=Math.max(1,Math.ceil(list.length/state.pageSize));
|
||||
if(state.page>totalPages)state.page=totalPages;
|
||||
var start=(state.page-1)*state.pageSize;
|
||||
var pageRows=list.slice(start,start+state.pageSize);
|
||||
var tbody=document.getElementById('tbody');
|
||||
tbody.innerHTML=pageRows.length?pageRows.map(function(r,pos){
|
||||
var idx=rows.indexOf(r);
|
||||
var msg=r.msg?r.msg:'<span class="muted">—</span>';
|
||||
if(r.msg&&r.msg.length>18)msg='<span title="'+r.msg+'">'+r.msg.slice(0,18)+'…</span>';
|
||||
return '<tr>'
|
||||
+'<td><input type="checkbox" class="row-check" data-idx="'+idx+'"></td>'
|
||||
+'<td>'+(start+pos+1)+'</td>'
|
||||
+'<td>'+fileTypeTag(r.fileType)+'</td><td>'+r.imageNo+'</td><td style="text-align:left;">'+msg+'</td>'
|
||||
+'<td><span class="link" onclick="downloadFile(\''+r.fileUrl+'\')">下载</span></td>'
|
||||
+'<td>'+(r.insId||'<span class="muted">—</span>')+'</td><td>'+r.studyInsId+'</td><td>'+(r.patientId||'<span class="muted">—</span>')+'</td>'
|
||||
+'<td>'+r.studyId+'</td><td>'+r.createTime+'</td>'
|
||||
+'<td><span class="link" onclick="openForm('+idx+')">编辑</span> <span class="link" style="margin-left:8px;" onclick="openDetail('+idx+')">详情</span> <span class="link-danger" style="margin-left:8px;" onclick="deleteRow('+idx+')">删除</span></td>'
|
||||
+'</tr>';
|
||||
}).join(''):'<tr><td colspan="12"><div class="empty-tip">暂无数据</div></td></tr>';
|
||||
var all=tbody.querySelectorAll('.row-check');
|
||||
var checked=tbody.querySelectorAll('.row-check:checked');
|
||||
document.getElementById('checkAll').checked=all.length>0&&all.length===checked.length;
|
||||
renderPagination(list.length,totalPages);
|
||||
}
|
||||
|
||||
function pageSeq(p,last){
|
||||
var seq=[];
|
||||
if(last<=7){for(var i=1;i<=last;i++)seq.push(i);return seq;}
|
||||
if(p<=4){seq=[1,2,3,4,5,'...',last];}
|
||||
else if(p>=last-3){seq=[1,'...',last-4,last-3,last-2,last-1,last];}
|
||||
else{seq=[1,'...',p-1,p,p+1,'...',last];}
|
||||
return seq;
|
||||
}
|
||||
function renderPagination(total,totalPages){
|
||||
var html='<span>共 '+total+' 条数据</span>';
|
||||
if(totalPages>1){
|
||||
html+='<button class="page-btn"'+(state.page===1?' disabled':'')+' onclick="goPage('+(state.page-1)+')"><</button>';
|
||||
pageSeq(state.page,totalPages).forEach(function(p){
|
||||
if(p==='...')html+='<span class="page-ellipsis">...</span>';
|
||||
else html+='<button class="page-btn'+(p===state.page?' active':'')+'" onclick="goPage('+p+')">'+p+'</button>';
|
||||
});
|
||||
html+='<button class="page-btn"'+(state.page===totalPages?' disabled':'')+' onclick="goPage('+(state.page+1)+')">></button>';
|
||||
}
|
||||
html+='<select class="page-size" onchange="changeSize(this.value)">'
|
||||
+[10,20,50].map(function(n){return '<option value="'+n+'"'+(n===state.pageSize?' selected':'')+'>'+n+'条/页</option>';}).join('')
|
||||
+'</select>';
|
||||
html+='<span class="page-jump">跳至<input type="number" id="jumpInput" min="1" value="'+state.page+'" onkeydown="if(event.key===\'Enter\')jumpTo('+totalPages+')">页<button class="page-btn" onclick="jumpTo('+totalPages+')">跳</button></span>';
|
||||
document.getElementById('pagination').innerHTML=html;
|
||||
}
|
||||
function goPage(p){state.page=p;renderTable();}
|
||||
function changeSize(v){state.pageSize=parseInt(v,10);state.page=1;renderTable();}
|
||||
function jumpTo(totalPages){
|
||||
var input=document.getElementById('jumpInput');
|
||||
var p=parseInt(input.value,10);
|
||||
if(isNaN(p)||p<1)p=1;
|
||||
if(p>totalPages)p=totalPages;
|
||||
state.page=p;
|
||||
renderTable();
|
||||
}
|
||||
|
||||
function downloadFile(url){
|
||||
alert('下载文件:'+url);
|
||||
}
|
||||
function toggleCheckAll(cb){
|
||||
document.querySelectorAll('.row-check').forEach(function(c){c.checked=cb.checked;});
|
||||
}
|
||||
function checkedIdx(){
|
||||
var arr=[];
|
||||
document.querySelectorAll('.row-check:checked').forEach(function(c){arr.push(parseInt(c.dataset.idx,10));});
|
||||
return arr;
|
||||
}
|
||||
function batchDelete(){
|
||||
var idxs=checkedIdx();
|
||||
if(!idxs.length){alert('请先勾选要删除的记录');return;}
|
||||
if(!confirm('确认删除选中的 '+idxs.length+' 条记录?'))return;
|
||||
idxs.sort(function(a,b){return b-a;}).forEach(function(i){rows.splice(i,1);});
|
||||
renderTable();
|
||||
}
|
||||
function deleteRow(idx){
|
||||
if(!confirm('确认删除该影像文件记录?'))return;
|
||||
rows.splice(idx,1);
|
||||
renderTable();
|
||||
}
|
||||
function exportList(){alert('导出当前筛选结果(Excel)');}
|
||||
function importList(){alert('导入影像文件详细数据(Excel)');}
|
||||
|
||||
var editingIdx=null;
|
||||
function openForm(idx){
|
||||
editingIdx=idx;
|
||||
document.getElementById('formTitle').textContent=idx===null?'新增用户影像文件详细':'编辑用户影像文件详细';
|
||||
if(idx===null){
|
||||
document.getElementById('formMuicid').value='';
|
||||
document.getElementById('formFiletype').value='影像';
|
||||
document.getElementById('formImageno').value='';
|
||||
document.getElementById('formMsg').value='';
|
||||
document.getElementById('formFileurl').value='';
|
||||
document.getElementById('formInsid').value='';
|
||||
document.getElementById('formStudyins').value='';
|
||||
document.getElementById('formPatient').value='';
|
||||
document.getElementById('formStudyid').value='';
|
||||
document.getElementById('formCreatetime').value='';
|
||||
}else{
|
||||
var r=rows[idx];
|
||||
document.getElementById('formMuicid').value=r.muicId;
|
||||
document.getElementById('formFiletype').value=r.fileType;
|
||||
document.getElementById('formImageno').value=r.imageNo;
|
||||
document.getElementById('formMsg').value=r.msg;
|
||||
document.getElementById('formFileurl').value=r.fileUrl;
|
||||
document.getElementById('formInsid').value=r.insId;
|
||||
document.getElementById('formStudyins').value=r.studyInsId;
|
||||
document.getElementById('formPatient').value=r.patientId;
|
||||
document.getElementById('formStudyid').value=r.studyId;
|
||||
document.getElementById('formCreatetime').value=r.createTime;
|
||||
}
|
||||
document.getElementById('formMask').classList.add('open');
|
||||
}
|
||||
function closeForm(){document.getElementById('formMask').classList.remove('open');}
|
||||
function saveForm(){
|
||||
var fileUrl=document.getElementById('formFileurl').value.trim();
|
||||
if(!fileUrl){alert('请输入文件地址');return;}
|
||||
var data={
|
||||
muicId:document.getElementById('formMuicid').value.trim(),
|
||||
fileType:document.getElementById('formFiletype').value,
|
||||
imageNo:document.getElementById('formImageno').value.trim(),
|
||||
msg:document.getElementById('formMsg').value.trim(),
|
||||
fileUrl:fileUrl,
|
||||
insId:document.getElementById('formInsid').value.trim(),
|
||||
studyInsId:document.getElementById('formStudyins').value.trim(),
|
||||
patientId:document.getElementById('formPatient').value.trim(),
|
||||
studyId:document.getElementById('formStudyid').value.trim(),
|
||||
createTime:document.getElementById('formCreatetime').value.trim()
|
||||
};
|
||||
if(editingIdx===null){
|
||||
rows.unshift(data);
|
||||
}else{
|
||||
rows[editingIdx]=data;
|
||||
}
|
||||
closeForm();
|
||||
renderTable();
|
||||
}
|
||||
|
||||
function openDetail(idx){
|
||||
var r=rows[idx];
|
||||
document.getElementById('detailBody').innerHTML=
|
||||
'<table class="detail-table"><tbody>'
|
||||
+'<tr><th>用户影像文件分类ID</th><td>'+r.muicId+'</td></tr>'
|
||||
+'<tr><th>文件类型</th><td>'+r.fileType+'</td></tr>'
|
||||
+'<tr><th>影像序号</th><td>'+r.imageNo+'</td></tr>'
|
||||
+'<tr><th>错误信息</th><td>'+(r.msg||'<span class="muted">—</span>')+'</td></tr>'
|
||||
+'<tr><th>文件地址</th><td>'+r.fileUrl+'</td></tr>'
|
||||
+'<tr><th>dcm实例ID</th><td>'+(r.insId||'<span class="muted">—</span>')+'</td></tr>'
|
||||
+'<tr><th>研究实例ID</th><td>'+r.studyInsId+'</td></tr>'
|
||||
+'<tr><th>患者ID</th><td>'+(r.patientId||'<span class="muted">—</span>')+'</td></tr>'
|
||||
+'<tr><th>研究ID</th><td>'+r.studyId+'</td></tr>'
|
||||
+'<tr><th>创建日期</th><td>'+r.createTime+'</td></tr>'
|
||||
+'</tbody></table>';
|
||||
document.getElementById('detailMask').classList.add('open');
|
||||
}
|
||||
function closeDetail(){document.getElementById('detailMask').classList.remove('open');}
|
||||
document.addEventListener('keydown',function(e){
|
||||
if(e.key==='Escape'){closeForm();closeDetail();}
|
||||
});
|
||||
|
||||
function toggleSubgroup(header){
|
||||
header.parentElement.classList.toggle('open');
|
||||
}
|
||||
(function(){
|
||||
renderTable();
|
||||
var active=document.querySelector('.sidebar-item.active');
|
||||
if(!active)return;
|
||||
var sub=active.closest('.sidebar-subgroup');
|
||||
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,520 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>健康体检 - 文件处理日志 | 健康CQ原型</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
:root{
|
||||
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
|
||||
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
|
||||
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;--font-xl:20px;--font-xxl:24px;
|
||||
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
|
||||
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);--shadow-md:0 4px 12px rgba(0,0,0,0.12);
|
||||
}
|
||||
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
|
||||
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
|
||||
.top-bar__logo svg{width:28px;height:28px;}
|
||||
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
|
||||
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
|
||||
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
|
||||
.top-bar__nav a.active{color:#fff;background:var(--primary);}
|
||||
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
|
||||
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
|
||||
.top-bar__right .btn-back:hover{color:#fff;}
|
||||
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
|
||||
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
|
||||
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
|
||||
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
|
||||
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;padding-left:16px;}
|
||||
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
|
||||
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
|
||||
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
|
||||
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
|
||||
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:160px;}
|
||||
.filter-input:focus{border-color:var(--primary);}
|
||||
.filter-input::placeholder{color:var(--text-placeholder);}
|
||||
.filter-select{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;appearance:none;cursor:pointer;min-width:130px;}
|
||||
.filter-select:focus{border-color:var(--primary);}
|
||||
.filter-select.placeholder{color:var(--text-placeholder);}
|
||||
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
.year-picker{position:relative;}
|
||||
.year-picker .filter-input{padding-right:30px;cursor:pointer;min-width:100px;}
|
||||
.year-picker>svg{position:absolute;right:9px;top:50%;transform:translateY(-50%);pointer-events:none;}
|
||||
.year-picker__dropdown{display:none;position:absolute;top:40px;left:0;width:100px;background:#fff;border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:var(--shadow-md);z-index:50;max-height:180px;overflow-y:auto;}
|
||||
.year-picker__dropdown.open{display:block;}
|
||||
.year-picker__dropdown div{padding:8px 14px;font-size:var(--font-sm);cursor:pointer;}
|
||||
.year-picker__dropdown div:hover{background:var(--primary-light);}
|
||||
.year-picker__dropdown div.selected{color:var(--primary);font-weight:600;}
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
|
||||
.table-card__content table{min-width:100%;white-space:nowrap;}
|
||||
table{width:100%;border-collapse:collapse;}
|
||||
thead th{background:#FAFAFA;padding:12px 16px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;text-align:center;}
|
||||
tbody tr:last-child td{border-bottom:none;}
|
||||
tbody tr:hover{background:#F8FBFF;}
|
||||
#logTable thead th:last-child{position:sticky;right:0;background:#FAFAFA;border-left:1px solid var(--border);}
|
||||
#logTable tbody td:last-child{position:sticky;right:0;background:#fff;border-left:1px solid var(--border);}
|
||||
#logTable tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
|
||||
.link-danger{color:var(--danger);cursor:pointer;font-size:var(--font-sm);}.link-danger:hover{color:#ff7875;}
|
||||
.empty-tip{padding:48px 0;text-align:center;font-size:var(--font-sm);color:var(--text-placeholder);}
|
||||
.muted{color:var(--text-placeholder);}
|
||||
.mono{font-family:Consolas,Menlo,monospace;font-size:var(--font-xs);color:var(--text-secondary);}
|
||||
.tag{display:inline-flex;align-items:center;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);}
|
||||
.tag-blue{background:#E6F7FF;color:#1890FF;}
|
||||
.tag-green{background:#F6FFED;color:#52C41A;}
|
||||
.tag-orange{background:#FFF7E6;color:#FA8C16;}
|
||||
.tag-red{background:#FFF1F0;color:#FF4D4F;}
|
||||
.tag-gray{background:#FAFAFA;color:#999;}
|
||||
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);flex-wrap:wrap;}
|
||||
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
|
||||
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;color:var(--text-primary);}
|
||||
.page-btn:hover:not(:disabled),.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
|
||||
.page-btn:disabled{color:var(--text-placeholder);cursor:not-allowed;background:#FAFAFA;}
|
||||
.page-ellipsis{width:24px;text-align:center;color:var(--text-placeholder);font-size:var(--font-sm);}
|
||||
.page-size{height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 24px 0 10px;font-size:var(--font-sm);color:var(--text-primary);background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 8px center;appearance:none;cursor:pointer;outline:none;}
|
||||
.page-jump input{width:48px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);text-align:center;font-size:var(--font-sm);outline:none;margin:0 4px;}
|
||||
.page-jump input:focus{border-color:var(--primary);}
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,0.45);z-index:200;overflow-y:auto;}
|
||||
.modal-mask.open{display:flex;align-items:flex-start;justify-content:center;padding:60px 24px;}
|
||||
.modal{width:680px;max-width:100%;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);display:flex;flex-direction:column;max-height:calc(100vh - 120px);}
|
||||
.modal__header{display:flex;align-items:center;gap:12px;padding:16px 20px;border-bottom:1px solid var(--border);flex-shrink:0;}
|
||||
.modal__close{cursor:pointer;color:var(--text-secondary);display:flex;align-items:center;transition:color .2s;}
|
||||
.modal__close:hover{color:var(--danger);}
|
||||
.modal__title{font-size:var(--font-base);font-weight:600;}
|
||||
.modal__body{padding:20px;overflow-y:auto;}
|
||||
.detail-table{width:100%;border-collapse:collapse;border:1px solid var(--border);}
|
||||
.detail-table th,.detail-table td{border-bottom:1px solid var(--border);text-align:left;padding:12px 16px;font-size:var(--font-sm);word-break:break-all;}
|
||||
.detail-table tr:last-child td{border-bottom:none;}
|
||||
.detail-table th{width:130px;background:#FAFAFA;color:var(--text-secondary);font-weight:500;}
|
||||
.json-box{background:#FAFAFA;border:1px solid var(--border);border-radius:var(--radius-sm);padding:12px;font-family:Consolas,Menlo,monospace;font-size:var(--font-xs);color:var(--text-secondary);white-space:pre-wrap;word-break:break-all;max-height:200px;overflow-y:auto;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="top-bar">
|
||||
<div class="top-bar__logo">
|
||||
<svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
|
||||
健康体检
|
||||
</div>
|
||||
<nav class="top-bar__nav">
|
||||
<a href="archive-personal.html">档案</a>
|
||||
<a href="config-material-notice.html">基础配置</a>
|
||||
<a href="pre-hospital-scope.html">检前</a>
|
||||
<a href="mid-appointment-track.html">检中</a>
|
||||
<a href="post-unit-count.html" class="active">检后</a>
|
||||
<a href="exception-dirty.html">异常事件</a>
|
||||
</nav>
|
||||
<div class="top-bar__right">
|
||||
<a class="btn-back" href="../../index.html">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
返回首页
|
||||
</a>
|
||||
<div class="avatar">管</div>
|
||||
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">检后</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
常规体检
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-report-employee.html" class="sidebar-item">常规体检报告</a>
|
||||
<a href="post-employee-master.html" class="sidebar-item">员工体检大表</a>
|
||||
<a href="post-illness-personnel.html" class="sidebar-item">大病人员信息</a>
|
||||
<a href="post-indicator-notify.html" class="sidebar-item">指标异常通知</a>
|
||||
<a href="post-report-unmatched.html" class="sidebar-item">体检报告未匹配项目</a>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检统计汇总
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-unit-count.html" class="sidebar-item">单位体检人数统计</a>
|
||||
<a href="post-unit-cost-stat.html" class="sidebar-item">单位体检费用统计</a>
|
||||
<a href="post-hospital-count.html" class="sidebar-item">医院体检人数统计</a>
|
||||
<a href="post-doctor-count.html" class="sidebar-item">医生检查人数统计</a>
|
||||
<a href="post-item-stat.html" class="sidebar-item">医院体检项目统计</a>
|
||||
<a href="post-cancer-screening.html" class="sidebar-item">防癌筛查人数统计</a>
|
||||
<a href="post-standard-stat.html" class="sidebar-item">系统标准化项目统计</a>
|
||||
<a href="post-contracted-hospital.html" class="sidebar-item">签约医院人数统计</a>
|
||||
<a href="post-key-indicator-stat.html" class="sidebar-item">重点指标异常统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
病种信息管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-disease-info.html" class="sidebar-item">病种信息配置</a>
|
||||
<a href="post-conclusion-disease.html" class="sidebar-item">体检结论关联病种</a>
|
||||
<a href="post-auto-select-disease.html" class="sidebar-item">员工病种信息</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
胃肠镜体检
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-report-gastro.html" class="sidebar-item">胃肠镜体检报告</a>
|
||||
<a href="post-gastro-stat.html" class="sidebar-item">胃肠镜体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
冠脉CTA体检
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-cta-report.html" class="sidebar-item">冠脉CTA体检报告</a>
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item active">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="main">
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>身份证号:</label>
|
||||
<input class="filter-input" type="text" id="f-idcard" placeholder="请输入身份证号" style="min-width:170px;">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>体检年份:</label>
|
||||
<div class="year-picker">
|
||||
<input class="filter-input" type="text" readonly value="2026" id="f-year">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="1.5" y="2.5" width="11" height="10" rx="1.5" stroke="#999" stroke-width="1.2"/><path d="M1.5 5.5h11M4.5 1v3M9.5 1v3" stroke="#999" stroke-width="1.2" stroke-linecap="round"/></svg>
|
||||
<div class="year-picker__dropdown" id="yearDropdown">
|
||||
<div class="selected" onclick="pickYear(this)">2026</div>
|
||||
<div onclick="pickYear(this)">2025</div>
|
||||
<div onclick="pickYear(this)">2024</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>体检编号:</label>
|
||||
<input class="filter-input" type="text" id="f-peid" placeholder="请输入体检编号" style="min-width:160px;">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>影像分类:</label>
|
||||
<select class="filter-select placeholder" id="f-imgclass" onchange="this.classList.toggle('placeholder',!this.value)">
|
||||
<option value="">请选择影像分类</option>
|
||||
<option value="超声">超声</option>
|
||||
<option value="CT">CT</option>
|
||||
<option value="MRI">MRI</option>
|
||||
<option value="X射线">X射线</option>
|
||||
<option value="心电">心电</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>处理状态:</label>
|
||||
<select class="filter-select placeholder" id="f-status" onchange="this.classList.toggle('placeholder',!this.value)">
|
||||
<option value="">请选择处理状态</option>
|
||||
<option value="1">新建</option>
|
||||
<option value="2">待解析</option>
|
||||
<option value="4">解析中</option>
|
||||
<option value="5">成功</option>
|
||||
<option value="6">失败待重试</option>
|
||||
<option value="3">失败</option>
|
||||
<option value="7">最终失败</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="margin-left:auto;display:flex;gap:12px;">
|
||||
<button class="btn btn-primary" onclick="doQuery()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6" cy="6" r="4.5" stroke="#fff" stroke-width="1.4"/><path d="M9.5 9.5l3 3" stroke="#fff" stroke-width="1.4" stroke-linecap="round"/></svg>
|
||||
查询
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="doReset()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M12 7a5 5 0 1 1-1.5-3.6M12 1.5V4h-2.5" stroke="#666" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
重置
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作栏 -->
|
||||
<div style="display:flex;gap:12px;margin-bottom:16px;align-items:center;">
|
||||
<button class="btn btn-default" onclick="batchDelete()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 3.5h10M5.5 3.5V2h3v1.5M3.5 3.5l.7 8.5h5.6l.7-8.5" stroke="#666" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
批量删除
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-card__content">
|
||||
<table id="logTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:48px;"><input type="checkbox" id="checkAll" onclick="toggleCheckAll(this)"></th>
|
||||
<th style="width:56px;">序号</th>
|
||||
<th>医院名称</th>
|
||||
<th>姓名</th>
|
||||
<th>身份证号</th>
|
||||
<th>体检年份</th>
|
||||
<th>体检编号</th>
|
||||
<th>影像分类</th>
|
||||
<th>json数据</th>
|
||||
<th>文件地址</th>
|
||||
<th>文件大小(MB)</th>
|
||||
<th>处理状态</th>
|
||||
<th>错误信息</th>
|
||||
<th>传输开始时间</th>
|
||||
<th>传输完成时间</th>
|
||||
<th>解析开始时间</th>
|
||||
<th>解析完成时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pagination" id="pagination"></div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div class="modal-mask" id="detailMask" onclick="if(event.target===this)closeDetail()">
|
||||
<div class="modal">
|
||||
<div class="modal__header">
|
||||
<span class="modal__close" onclick="closeDetail()">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3.5 3.5l9 9M12.5 3.5l-9 9" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
|
||||
</span>
|
||||
<span class="modal__title">文件处理日志详情</span>
|
||||
</div>
|
||||
<div class="modal__body" id="detailBody"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var handleStatusMap={1:'新建',2:'待解析',3:'失败',4:'解析中',5:'成功',6:'失败待重试',7:'最终失败'};
|
||||
function statusTag(s){
|
||||
var cls='tag-gray';
|
||||
if(s===5)cls='tag-green';
|
||||
else if(s===4||s===6)cls='tag-orange';
|
||||
else if(s===3||s===7)cls='tag-red';
|
||||
else if(s===1)cls='tag-blue';
|
||||
return '<span class="tag '+cls+'">'+handleStatusMap[s]+'</span>';
|
||||
}
|
||||
/* 按传输开始时间倒序 */
|
||||
var rows=[
|
||||
{hospitalName:'重庆市人民医院',realname:'张伟',idCard:'500103197805121234',medicalYear:'2026',peId:'PE20260001',imgClass:'CT',jsonContent:'{"hospitalId":"H001","hospitalName":"重庆市人民医院","peId":"PE20260001","items":[{"name":"胸部CT平扫","type":"CT"},{"name":"头颅MRI平扫","type":"MRI"},{"name":"腹部超声","type":"超声"}]}',zipFileUrl:'/files/imc/PE20260001.zip',zipSize:128.5,status:5,msg:'',startTime:'2026-08-15 10:00:00',endTime:'2026-08-15 10:02:15',parseStartTime:'2026-08-15 10:05:00',parseEndTime:'2026-08-15 12:00:00'},
|
||||
{hospitalName:'重庆医科大学附属第一医院',realname:'李芳',idCard:'500107198812053467',medicalYear:'2026',peId:'PE20260002',imgClass:'CT',jsonContent:'{"hospitalId":"H002","hospitalName":"重庆医科大学附属第一医院","peId":"PE20260002","items":[{"name":"胸部CT平扫","type":"CT"},{"name":"心电图","type":"心电"}]}',zipFileUrl:'/files/imc/PE20260002.zip',zipSize:96.2,status:5,msg:'',startTime:'2026-08-15 11:00:00',endTime:'2026-08-15 11:01:30',parseStartTime:'2026-08-15 11:05:00',parseEndTime:'2026-08-15 13:00:00'},
|
||||
{hospitalName:'陆军军医大学西南医院',realname:'王强',idCard:'500105199203154567',medicalYear:'2026',peId:'PE20260003',imgClass:'X射线',jsonContent:'{"hospitalId":"H003","hospitalName":"陆军军医大学西南医院","peId":"PE20260003","items":[{"name":"胸部X射线","type":"X射线"},{"name":"腹部超声","type":"超声"}]}',zipFileUrl:'/files/imc/PE20260003.zip',zipSize:64.8,status:7,msg:'DICOM标签解析失败:缺少 PatientID 标签',startTime:'2026-08-15 13:40:00',endTime:'2026-08-15 13:42:10',parseStartTime:'2026-08-15 13:45:00',parseEndTime:'2026-08-15 14:10:00'},
|
||||
{hospitalName:'陆军特色医学中心',realname:'赵敏',idCard:'500104199001011234',medicalYear:'2026',peId:'PE20260004',imgClass:'CT',jsonContent:'{"hospitalId":"H004","hospitalName":"陆军特色医学中心","peId":"PE20260004","items":[{"name":"冠脉CTA","type":"CT"}]}',zipFileUrl:'/files/imc/PE20260004.zip',zipSize:210.3,status:2,msg:'',startTime:'2026-08-16 09:10:00',endTime:'2026-08-16 09:12:00',parseStartTime:'',parseEndTime:''},
|
||||
{hospitalName:'重庆市人民医院',realname:'陈刚',idCard:'500106198503094567',medicalYear:'2025',peId:'PE20250018',imgClass:'CT',jsonContent:'{"hospitalId":"H001","hospitalName":"重庆市人民医院","peId":"PE20250018","items":[{"name":"胸部CT平扫","type":"CT"},{"name":"头颅MRI平扫","type":"MRI"},{"name":"腹部超声","type":"超声"},{"name":"心电图","type":"心电"}]}',zipFileUrl:'/files/imc/PE20250018.zip',zipSize:152.7,status:5,msg:'',startTime:'2025-08-20 15:20:00',endTime:'2025-08-20 15:23:00',parseStartTime:'2025-08-20 15:30:00',parseEndTime:'2025-08-20 17:00:00'},
|
||||
{hospitalName:'重庆医科大学附属第一医院',realname:'刘洋',idCard:'500102199511223456',medicalYear:'2025',peId:'PE20250021',imgClass:'超声',jsonContent:'{"hospitalId":"H002","hospitalName":"重庆医科大学附属第一医院","peId":"PE20250021","items":[{"name":"胸部CT平扫","type":"CT"},{"name":"腹部超声","type":"超声"}]}',zipFileUrl:'/files/imc/PE20250021.zip',zipSize:88.9,status:7,msg:'报告文件格式与声明类型不一致',startTime:'2025-08-21 10:00:00',endTime:'2025-08-21 10:02:00',parseStartTime:'2025-08-21 10:10:00',parseEndTime:'2025-08-21 11:00:00'}
|
||||
];
|
||||
var state={idcard:'',year:'2026',peid:'',imgclass:'',status:'',page:1,pageSize:10};
|
||||
|
||||
function toggleYear(){document.getElementById('yearDropdown').classList.toggle('open');}
|
||||
function pickYear(el){
|
||||
document.getElementById('f-year').value=el.textContent.trim();
|
||||
document.getElementById('yearDropdown').classList.remove('open');
|
||||
document.querySelectorAll('#yearDropdown div').forEach(function(d){d.classList.remove('selected');});
|
||||
el.classList.add('selected');
|
||||
}
|
||||
document.getElementById('f-year').addEventListener('click',toggleYear);
|
||||
document.addEventListener('click',function(e){
|
||||
if(!e.target.closest('.year-picker'))document.getElementById('yearDropdown').classList.remove('open');
|
||||
});
|
||||
|
||||
function doQuery(){
|
||||
state.idcard=document.getElementById('f-idcard').value.trim();
|
||||
state.year=document.getElementById('f-year').value.trim();
|
||||
state.peid=document.getElementById('f-peid').value.trim();
|
||||
state.imgclass=document.getElementById('f-imgclass').value;
|
||||
state.status=document.getElementById('f-status').value;
|
||||
state.page=1;
|
||||
renderTable();
|
||||
}
|
||||
function doReset(){
|
||||
document.getElementById('f-idcard').value='';
|
||||
document.getElementById('f-year').value='2026';
|
||||
document.querySelectorAll('#yearDropdown div').forEach(function(d){
|
||||
d.classList.toggle('selected',d.textContent.trim()==='2026');
|
||||
});
|
||||
document.getElementById('f-peid').value='';
|
||||
var ic=document.getElementById('f-imgclass');ic.value='';ic.classList.add('placeholder');
|
||||
var st=document.getElementById('f-status');st.value='';st.classList.add('placeholder');
|
||||
state.idcard='';state.year='2026';state.peid='';state.imgclass='';state.status='';
|
||||
state.page=1;
|
||||
renderTable();
|
||||
}
|
||||
|
||||
function filteredRows(){
|
||||
return rows.filter(function(r){
|
||||
if(state.idcard&&r.idCard.indexOf(state.idcard)===-1)return false;
|
||||
if(state.year&&r.medicalYear!==state.year)return false;
|
||||
if(state.peid&&r.peId.indexOf(state.peid)===-1)return false;
|
||||
if(state.imgclass&&r.imgClass!==state.imgclass)return false;
|
||||
if(state.status&&String(r.status)!==state.status)return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
function renderTable(){
|
||||
var list=filteredRows();
|
||||
var totalPages=Math.max(1,Math.ceil(list.length/state.pageSize));
|
||||
if(state.page>totalPages)state.page=totalPages;
|
||||
var start=(state.page-1)*state.pageSize;
|
||||
var pageRows=list.slice(start,start+state.pageSize);
|
||||
var tbody=document.getElementById('tbody');
|
||||
tbody.innerHTML=pageRows.length?pageRows.map(function(r,pos){
|
||||
var idx=rows.indexOf(r);
|
||||
var json=r.jsonContent;
|
||||
if(json.length>24)json='<span class="mono" title="'+r.jsonContent.replace(/"/g,'"')+'">'+r.jsonContent.slice(0,24)+'…</span>';
|
||||
else json='<span class="mono">'+json+'</span>';
|
||||
var msg=r.msg?r.msg:'<span class="muted">—</span>';
|
||||
if(r.msg&&r.msg.length>18)msg='<span title="'+r.msg+'">'+r.msg.slice(0,18)+'…</span>';
|
||||
return '<tr>'
|
||||
+'<td><input type="checkbox" class="row-check" data-idx="'+idx+'"></td>'
|
||||
+'<td>'+(start+pos+1)+'</td>'
|
||||
+'<td>'+r.hospitalName+'</td><td>'+r.realname+'</td><td>'+r.idCard+'</td><td>'+r.medicalYear+'</td>'
|
||||
+'<td>'+r.peId+'</td><td>'+r.imgClass+'</td><td>'+json+'</td>'
|
||||
+'<td><span class="link" onclick="downloadFile(\''+r.zipFileUrl+'\')">下载</span></td>'
|
||||
+'<td>'+r.zipSize+'</td><td>'+statusTag(r.status)+'</td><td style="text-align:left;">'+msg+'</td>'
|
||||
+'<td>'+r.startTime+'</td><td>'+r.endTime+'</td><td>'+(r.parseStartTime||'<span class="muted">—</span>')+'</td><td>'+(r.parseEndTime||'<span class="muted">—</span>')+'</td>'
|
||||
+'<td><span class="link" onclick="openDetail('+idx+')">详情</span> <span class="link-danger" style="margin-left:8px;" onclick="deleteRow('+idx+')">删除</span></td>'
|
||||
+'</tr>';
|
||||
}).join(''):'<tr><td colspan="18"><div class="empty-tip">暂无数据</div></td></tr>';
|
||||
var all=tbody.querySelectorAll('.row-check');
|
||||
var checked=tbody.querySelectorAll('.row-check:checked');
|
||||
document.getElementById('checkAll').checked=all.length>0&&all.length===checked.length;
|
||||
renderPagination(list.length,totalPages);
|
||||
}
|
||||
|
||||
function pageSeq(p,last){
|
||||
var seq=[];
|
||||
if(last<=7){for(var i=1;i<=last;i++)seq.push(i);return seq;}
|
||||
if(p<=4){seq=[1,2,3,4,5,'...',last];}
|
||||
else if(p>=last-3){seq=[1,'...',last-4,last-3,last-2,last-1,last];}
|
||||
else{seq=[1,'...',p-1,p,p+1,'...',last];}
|
||||
return seq;
|
||||
}
|
||||
function renderPagination(total,totalPages){
|
||||
var html='<span>共 '+total+' 条数据</span>';
|
||||
if(totalPages>1){
|
||||
html+='<button class="page-btn"'+(state.page===1?' disabled':'')+' onclick="goPage('+(state.page-1)+')"><</button>';
|
||||
pageSeq(state.page,totalPages).forEach(function(p){
|
||||
if(p==='...')html+='<span class="page-ellipsis">...</span>';
|
||||
else html+='<button class="page-btn'+(p===state.page?' active':'')+'" onclick="goPage('+p+')">'+p+'</button>';
|
||||
});
|
||||
html+='<button class="page-btn"'+(state.page===totalPages?' disabled':'')+' onclick="goPage('+(state.page+1)+')">></button>';
|
||||
}
|
||||
html+='<select class="page-size" onchange="changeSize(this.value)">'
|
||||
+[10,20,50].map(function(n){return '<option value="'+n+'"'+(n===state.pageSize?' selected':'')+'>'+n+'条/页</option>';}).join('')
|
||||
+'</select>';
|
||||
html+='<span class="page-jump">跳至<input type="number" id="jumpInput" min="1" value="'+state.page+'" onkeydown="if(event.key===\'Enter\')jumpTo('+totalPages+')">页<button class="page-btn" onclick="jumpTo('+totalPages+')">跳</button></span>';
|
||||
document.getElementById('pagination').innerHTML=html;
|
||||
}
|
||||
function goPage(p){state.page=p;renderTable();}
|
||||
function changeSize(v){state.pageSize=parseInt(v,10);state.page=1;renderTable();}
|
||||
function jumpTo(totalPages){
|
||||
var input=document.getElementById('jumpInput');
|
||||
var p=parseInt(input.value,10);
|
||||
if(isNaN(p)||p<1)p=1;
|
||||
if(p>totalPages)p=totalPages;
|
||||
state.page=p;
|
||||
renderTable();
|
||||
}
|
||||
|
||||
function downloadFile(url){
|
||||
alert('下载文件:'+url);
|
||||
}
|
||||
function deleteRow(idx){
|
||||
if(!confirm('确认删除该文件处理日志记录?'))return;
|
||||
rows.splice(idx,1);
|
||||
renderTable();
|
||||
}
|
||||
|
||||
function toggleCheckAll(cb){
|
||||
document.querySelectorAll('.row-check').forEach(function(c){c.checked=cb.checked;});
|
||||
}
|
||||
function checkedIdx(){
|
||||
var arr=[];
|
||||
document.querySelectorAll('.row-check:checked').forEach(function(c){arr.push(parseInt(c.dataset.idx,10));});
|
||||
return arr;
|
||||
}
|
||||
function batchDelete(){
|
||||
var idxs=checkedIdx();
|
||||
if(!idxs.length){alert('请先勾选要删除的记录');return;}
|
||||
if(!confirm('确认删除选中的 '+idxs.length+' 条记录?'))return;
|
||||
idxs.sort(function(a,b){return b-a;}).forEach(function(i){rows.splice(i,1);});
|
||||
renderTable();
|
||||
}
|
||||
|
||||
function openDetail(idx){
|
||||
var r=rows[idx];
|
||||
document.getElementById('detailBody').innerHTML=
|
||||
'<table class="detail-table"><tbody>'
|
||||
+'<tr><th>医院名称</th><td>'+r.hospitalName+'</td></tr>'
|
||||
+'<tr><th>姓名</th><td>'+r.realname+'</td></tr>'
|
||||
+'<tr><th>身份证号</th><td>'+r.idCard+'</td></tr>'
|
||||
+'<tr><th>体检年份</th><td>'+r.medicalYear+'</td></tr>'
|
||||
+'<tr><th>体检编号</th><td>'+r.peId+'</td></tr>'
|
||||
+'<tr><th>影像分类</th><td>'+r.imgClass+'</td></tr>'
|
||||
+'<tr><th>json数据</th><td><div class="json-box">'+r.jsonContent+'</div></td></tr>'
|
||||
+'<tr><th>文件地址</th><td>'+r.zipFileUrl+'</td></tr>'
|
||||
+'<tr><th>文件大小(MB)</th><td>'+r.zipSize+'</td></tr>'
|
||||
+'<tr><th>处理状态</th><td>'+handleStatusMap[r.status]+'</td></tr>'
|
||||
+'<tr><th>错误信息</th><td>'+(r.msg||'<span class="muted">—</span>')+'</td></tr>'
|
||||
+'<tr><th>传输开始时间</th><td>'+r.startTime+'</td></tr>'
|
||||
+'<tr><th>传输完成时间</th><td>'+r.endTime+'</td></tr>'
|
||||
+'<tr><th>解析开始时间</th><td>'+(r.parseStartTime||'<span class="muted">—</span>')+'</td></tr>'
|
||||
+'<tr><th>解析完成时间</th><td>'+(r.parseEndTime||'<span class="muted">—</span>')+'</td></tr>'
|
||||
+'</tbody></table>';
|
||||
document.getElementById('detailMask').classList.add('open');
|
||||
}
|
||||
function closeDetail(){document.getElementById('detailMask').classList.remove('open');}
|
||||
document.addEventListener('keydown',function(e){
|
||||
if(e.key==='Escape')closeDetail();
|
||||
});
|
||||
|
||||
function toggleSubgroup(header){
|
||||
header.parentElement.classList.toggle('open');
|
||||
}
|
||||
(function(){
|
||||
renderTable();
|
||||
var active=document.querySelector('.sidebar-item.active');
|
||||
if(!active)return;
|
||||
var sub=active.closest('.sidebar-subgroup');
|
||||
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,658 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>健康体检 - 用户体检信息 | 健康CQ原型</title>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;background:#F5F7FA;color:#333;min-width:1280px;}
|
||||
:root{
|
||||
--primary:#1890FF;--primary-light:#E6F7FF;--success:#52C41A;--warning:#FAAD14;--danger:#FF4D4F;
|
||||
--text-primary:#333;--text-secondary:#666;--text-placeholder:#999;--border:#E8E8E8;--background:#F5F7FA;
|
||||
--font-xs:11px;--font-sm:13px;--font-base:15px;--font-lg:17px;--font-xl:20px;--font-xxl:24px;
|
||||
--radius-sm:4px;--radius-md:8px;--radius-lg:12px;
|
||||
--shadow-sm:0 1px 4px rgba(0,0,0,0.08);--shadow-md:0 4px 12px rgba(0,0,0,0.12);
|
||||
}
|
||||
/* 顶部导航 */
|
||||
.top-bar{display:flex;align-items:center;height:56px;background:#001529;padding:0 24px;position:fixed;top:0;left:0;right:0;z-index:100;}
|
||||
.top-bar__logo{display:flex;align-items:center;gap:8px;color:#fff;font-size:var(--font-lg);font-weight:600;white-space:nowrap;width:240px;flex-shrink:0;}
|
||||
.top-bar__logo svg{width:28px;height:28px;}
|
||||
.top-bar__nav{display:flex;align-items:center;gap:4px;flex:1;}
|
||||
.top-bar__nav a{color:rgba(255,255,255,0.65);text-decoration:none;padding:6px 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);transition:all .2s;}
|
||||
.top-bar__nav a:hover{color:#fff;background:rgba(255,255,255,0.08);}
|
||||
.top-bar__nav a.active{color:#fff;background:var(--primary);}
|
||||
.top-bar__right{display:flex;align-items:center;gap:16px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);}
|
||||
.top-bar__right .btn-back{color:rgba(255,255,255,0.65);cursor:pointer;display:flex;align-items:center;gap:4px;text-decoration:none;}
|
||||
.top-bar__right .btn-back:hover{color:#fff;}
|
||||
.avatar{width:32px;height:32px;border-radius:50%;background:#1890FF;display:flex;align-items:center;justify-content:center;color:#fff;font-size:var(--font-sm);cursor:pointer;}
|
||||
/* 侧边栏 */
|
||||
.sidebar{position:fixed;top:56px;left:0;bottom:0;width:240px;background:#001529;overflow-y:auto;z-index:90;padding-top:8px;}
|
||||
.sidebar-menu__title{color:rgba(255,255,255,0.35);font-size:var(--font-xs);padding:16px 24px 8px;text-transform:uppercase;letter-spacing:.5px;}
|
||||
.sidebar-item{display:flex;align-items:center;gap:8px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;text-decoration:none;}
|
||||
.sidebar-item:hover{color:#fff;background:rgba(255,255,255,0.06);}
|
||||
.sidebar-item.active{color:#fff;background:var(--primary);}
|
||||
.sidebar-subgroup__header{display:flex;align-items:center;gap:6px;padding:10px 24px;color:rgba(255,255,255,0.65);font-size:var(--font-sm);cursor:pointer;transition:all .15s;user-select:none;}
|
||||
.sidebar-subgroup__header:hover{color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.04);}
|
||||
.sidebar-subgroup__header .arrow{width:10px;height:10px;transition:transform .2s;flex-shrink:0;}
|
||||
.sidebar-subgroup__header .arrow path{stroke:rgba(255,255,255,0.45);}
|
||||
.sidebar-subgroup.open>.sidebar-subgroup__header{color:rgba(255,255,255,0.85);}
|
||||
.sidebar-subgroup.open>.sidebar-subgroup__header .arrow{transform:rotate(90deg);}
|
||||
.sidebar-subgroup__body{display:none;padding-left:16px;}
|
||||
.sidebar-subgroup.open>.sidebar-subgroup__body{display:block;}
|
||||
.sidebar-subgroup__body .sidebar-item{padding-left:36px;font-size:12px;}
|
||||
.sidebar-subgroup .sidebar-subgroup{padding-left:12px;}
|
||||
.sidebar-subgroup .sidebar-subgroup .sidebar-item{padding-left:40px;}
|
||||
.sidebar-subgroup .sidebar-subgroup>.sidebar-subgroup__header{font-size:12px;}
|
||||
/* 主内容 */
|
||||
.main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);}
|
||||
/* 筛选栏 */
|
||||
.filter-bar{background:#fff;border-radius:var(--radius-md);padding:20px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
|
||||
.filter-item{display:flex;align-items:center;gap:8px;}
|
||||
.filter-item label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
|
||||
.filter-input{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;min-width:200px;}
|
||||
.filter-input:focus{border-color:var(--primary);}
|
||||
.filter-input::placeholder{color:var(--text-placeholder);}
|
||||
.btn{height:36px;padding:0 16px;border-radius:var(--radius-sm);font-size:var(--font-sm);cursor:pointer;border:none;transition:all .2s;display:inline-flex;align-items:center;gap:6px;}
|
||||
.btn-primary{background:var(--primary);color:#fff;}.btn-primary:hover{background:#40a9ff;}
|
||||
.btn-default{background:#fff;color:var(--text-primary);border:1px solid var(--border);}.btn-default:hover{color:var(--primary);border-color:var(--primary);}
|
||||
/* 体检年份选择控件 */
|
||||
.year-picker{position:relative;}
|
||||
.year-picker .filter-input{padding-right:30px;cursor:pointer;min-width:110px;}
|
||||
.year-picker>svg{position:absolute;right:9px;top:50%;transform:translateY(-50%);pointer-events:none;}
|
||||
.year-picker__dropdown{display:none;position:absolute;top:40px;left:0;width:110px;background:#fff;border:1px solid var(--border);border-radius:var(--radius-sm);box-shadow:var(--shadow-md);z-index:50;max-height:180px;overflow-y:auto;}
|
||||
.year-picker__dropdown.open{display:block;}
|
||||
.year-picker__dropdown div{padding:8px 14px;font-size:var(--font-sm);cursor:pointer;}
|
||||
.year-picker__dropdown div:hover{background:var(--primary-light);}
|
||||
.year-picker__dropdown div.selected{color:var(--primary);font-weight:600;}
|
||||
/* 表格 */
|
||||
.table-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden;}
|
||||
.table-card__content{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
|
||||
.table-card__content table{min-width:100%;white-space:nowrap;}
|
||||
table{width:100%;border-collapse:collapse;}
|
||||
thead th{background:#FAFAFA;padding:12px 16px;text-align:center;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);white-space:nowrap;}
|
||||
tbody td{padding:14px 16px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);white-space:nowrap;text-align:center;}
|
||||
tbody tr:last-child td{border-bottom:none;}
|
||||
tbody tr:hover{background:#F8FBFF;}
|
||||
#userTable thead th:last-child{position:sticky;right:0;background:#FAFAFA;border-left:1px solid var(--border);}
|
||||
#userTable tbody td:last-child{position:sticky;right:0;background:#fff;border-left:1px solid var(--border);}
|
||||
#userTable tbody tr:hover td:last-child{background:#F8FBFF;}
|
||||
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
|
||||
.link-danger{color:var(--danger);cursor:pointer;font-size:var(--font-sm);}.link-danger:hover{color:#ff7875;}
|
||||
.empty-tip{padding:48px 0;text-align:center;font-size:var(--font-sm);color:var(--text-placeholder);}
|
||||
/* 展开列 */
|
||||
.expand-toggle{display:inline-flex;width:20px;height:20px;align-items:center;justify-content:center;cursor:pointer;color:var(--text-placeholder);transition:transform .2s,color .2s;}
|
||||
.expand-toggle svg{transition:transform .2s;}
|
||||
.expand-toggle.open{color:var(--primary);}
|
||||
.expand-toggle.open svg{transform:rotate(90deg);}
|
||||
/* 展开子表 */
|
||||
.expand-row td{background:#FAFBFC;padding:0 !important;text-align:left !important;}
|
||||
.expand-row:hover td{background:#FAFBFC !important;}
|
||||
.inner-wrap{padding:12px 20px 16px 52px;}
|
||||
.inner-table{width:100%;border:1px solid var(--border);border-collapse:collapse;background:#fff;}
|
||||
.inner-table th{background:#F5F7FA;padding:9px 14px;font-size:var(--font-sm);color:var(--text-secondary);font-weight:500;border:1px solid var(--border);text-align:center;white-space:nowrap;}
|
||||
.inner-table td{padding:10px 14px;font-size:var(--font-sm);color:var(--text-primary);border:1px solid var(--border);text-align:center;white-space:nowrap;}
|
||||
.inner-empty{color:var(--text-placeholder);font-style:italic;font-size:var(--font-xs);}
|
||||
/* 状态标签 */
|
||||
.tag{display:inline-flex;align-items:center;padding:2px 10px;border-radius:10px;font-size:var(--font-xs);}
|
||||
.tag-blue{background:#E6F7FF;color:#1890FF;}
|
||||
.tag-green{background:#F6FFED;color:#52C41A;}
|
||||
.tag-orange{background:#FFF7E6;color:#FA8C16;}
|
||||
.tag-red{background:#FFF1F0;color:#FF4D4F;}
|
||||
.tag-gray{background:#FAFAFA;color:#999;}
|
||||
/* 分页 */
|
||||
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);flex-wrap:wrap;}
|
||||
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
|
||||
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;color:var(--text-primary);}
|
||||
.page-btn:hover:not(:disabled),.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
|
||||
.page-btn:disabled{color:var(--text-placeholder);cursor:not-allowed;background:#FAFAFA;}
|
||||
.page-ellipsis{width:24px;text-align:center;color:var(--text-placeholder);font-size:var(--font-sm);}
|
||||
.page-size{height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 24px 0 10px;font-size:var(--font-sm);color:var(--text-primary);background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 8px center;appearance:none;cursor:pointer;outline:none;}
|
||||
.page-jump input{width:48px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);text-align:center;font-size:var(--font-sm);outline:none;margin:0 4px;}
|
||||
.page-jump input:focus{border-color:var(--primary);}
|
||||
/* 弹窗 */
|
||||
.modal-mask{display:none;position:fixed;inset:0;background:rgba(0,0,0,0.45);z-index:200;overflow-y:auto;}
|
||||
.modal-mask.open{display:flex;align-items:flex-start;justify-content:center;padding:60px 24px;}
|
||||
.modal{width:560px;max-width:100%;background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-md);display:flex;flex-direction:column;max-height:calc(100vh - 120px);}
|
||||
.modal__header{display:flex;align-items:center;gap:12px;padding:16px 20px;border-bottom:1px solid var(--border);flex-shrink:0;}
|
||||
.modal__close{cursor:pointer;color:var(--text-secondary);display:flex;align-items:center;transition:color .2s;}
|
||||
.modal__close:hover{color:var(--danger);}
|
||||
.modal__title{font-size:var(--font-base);font-weight:600;}
|
||||
.modal__body{padding:20px;overflow-y:auto;}
|
||||
/* 详情 */
|
||||
.detail-table{width:100%;border-collapse:collapse;border:1px solid var(--border);}
|
||||
.detail-table th,.detail-table td{border-bottom:1px solid var(--border);text-align:left;padding:12px 16px;font-size:var(--font-sm);}
|
||||
.detail-table tr:last-child td{border-bottom:none;}
|
||||
.detail-table th{width:120px;background:#FAFAFA;color:var(--text-secondary);font-weight:500;}
|
||||
/* 表单 */
|
||||
.form-item{margin-bottom:16px;}
|
||||
.form-item:last-child{margin-bottom:0;}
|
||||
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:6px;display:flex;align-items:center;gap:4px;font-weight:500;}
|
||||
.form-label .required{color:var(--danger);}
|
||||
.form-input{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
|
||||
.form-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
|
||||
.form-input::placeholder{color:var(--text-placeholder);}
|
||||
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:14px 20px;border-top:1px solid var(--border);flex-shrink:0;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- 顶部导航 -->
|
||||
<div class="top-bar">
|
||||
<div class="top-bar__logo">
|
||||
<svg viewBox="0 0 28 28" fill="none"><rect width="28" height="28" rx="6" fill="#1890FF"/><path d="M7 14h14M14 7v14" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/></svg>
|
||||
健康体检
|
||||
</div>
|
||||
<nav class="top-bar__nav">
|
||||
<a href="archive-personal.html">档案</a>
|
||||
<a href="config-material-notice.html">基础配置</a>
|
||||
<a href="pre-hospital-scope.html">检前</a>
|
||||
<a href="mid-appointment-track.html">检中</a>
|
||||
<a href="post-unit-count.html" class="active">检后</a>
|
||||
<a href="exception-dirty.html">异常事件</a>
|
||||
</nav>
|
||||
<div class="top-bar__right">
|
||||
<a class="btn-back" href="../../index.html">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M10 3L5 8l5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
返回首页
|
||||
</a>
|
||||
<div class="avatar">管</div>
|
||||
<span style="color:rgba(255,255,255,0.65);">系统管理员 ▾</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 侧边栏 -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-menu__title">检后</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
常规体检
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-report-employee.html" class="sidebar-item">常规体检报告</a>
|
||||
<a href="post-employee-master.html" class="sidebar-item">员工体检大表</a>
|
||||
<a href="post-illness-personnel.html" class="sidebar-item">大病人员信息</a>
|
||||
<a href="post-indicator-notify.html" class="sidebar-item">指标异常通知</a>
|
||||
<a href="post-report-unmatched.html" class="sidebar-item">体检报告未匹配项目</a>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检统计汇总
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-unit-count.html" class="sidebar-item">单位体检人数统计</a>
|
||||
<a href="post-unit-cost-stat.html" class="sidebar-item">单位体检费用统计</a>
|
||||
<a href="post-hospital-count.html" class="sidebar-item">医院体检人数统计</a>
|
||||
<a href="post-doctor-count.html" class="sidebar-item">医生检查人数统计</a>
|
||||
<a href="post-item-stat.html" class="sidebar-item">医院体检项目统计</a>
|
||||
<a href="post-cancer-screening.html" class="sidebar-item">防癌筛查人数统计</a>
|
||||
<a href="post-standard-stat.html" class="sidebar-item">系统标准化项目统计</a>
|
||||
<a href="post-contracted-hospital.html" class="sidebar-item">签约医院人数统计</a>
|
||||
<a href="post-key-indicator-stat.html" class="sidebar-item">重点指标异常统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
病种信息管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-disease-info.html" class="sidebar-item">病种信息配置</a>
|
||||
<a href="post-conclusion-disease.html" class="sidebar-item">体检结论关联病种</a>
|
||||
<a href="post-auto-select-disease.html" class="sidebar-item">员工病种信息</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
胃肠镜体检
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-report-gastro.html" class="sidebar-item">胃肠镜体检报告</a>
|
||||
<a href="post-gastro-stat.html" class="sidebar-item">胃肠镜体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
冠脉CTA体检
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-cta-report.html" class="sidebar-item">冠脉CTA体检报告</a>
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item active">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<main class="main">
|
||||
<!-- 筛选栏 -->
|
||||
<div class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>姓名:</label>
|
||||
<input class="filter-input" type="text" id="f-name" placeholder="请输入姓名" style="min-width:140px;">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>身份证号:</label>
|
||||
<input class="filter-input" type="text" id="f-idcard" placeholder="请输入身份证号" style="min-width:180px;">
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>体检年份:</label>
|
||||
<div class="year-picker">
|
||||
<input class="filter-input" type="text" readonly value="2026" id="f-year">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="1.5" y="2.5" width="11" height="10" rx="1.5" stroke="#999" stroke-width="1.2"/><path d="M1.5 5.5h11M4.5 1v3M9.5 1v3" stroke="#999" stroke-width="1.2" stroke-linecap="round"/></svg>
|
||||
<div class="year-picker__dropdown" id="yearDropdown">
|
||||
<div class="selected" onclick="pickYear(this)">2026</div>
|
||||
<div onclick="pickYear(this)">2025</div>
|
||||
<div onclick="pickYear(this)">2024</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>医院名称:</label>
|
||||
<input class="filter-input" type="text" id="f-hospital" placeholder="请输入医院名称" style="min-width:180px;">
|
||||
</div>
|
||||
<div style="margin-left:auto;display:flex;gap:12px;">
|
||||
<button class="btn btn-primary" onclick="doQuery()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6" cy="6" r="4.5" stroke="#fff" stroke-width="1.4"/><path d="M9.5 9.5l3 3" stroke="#fff" stroke-width="1.4" stroke-linecap="round"/></svg>
|
||||
查询
|
||||
</button>
|
||||
<button class="btn btn-default" onclick="doReset()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M12 7a5 5 0 1 1-1.5-3.6M12 1.5V4h-2.5" stroke="#666" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
重置
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作栏 -->
|
||||
<div style="display:flex;gap:12px;margin-bottom:16px;align-items:center;">
|
||||
<button class="btn btn-default" onclick="batchDelete()">
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 3.5h10M5.5 3.5V2h3v1.5M3.5 3.5l.7 8.5h5.6l.7-8.5" stroke="#666" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
批量删除
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<div class="table-card">
|
||||
<div class="table-card__content">
|
||||
<table id="userTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:48px;"><input type="checkbox" id="checkAll" onclick="toggleCheckAll(this)"></th>
|
||||
<th style="width:56px;">序号</th>
|
||||
<th style="width:48px;"></th>
|
||||
<th>单位信息</th>
|
||||
<th>姓名</th>
|
||||
<th>身份证号</th>
|
||||
<th>体检年份</th>
|
||||
<th>医院名称</th>
|
||||
<th>体检编号</th>
|
||||
<th>创建日期</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pagination" id="pagination"></div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<div class="modal-mask" id="formMask" onclick="if(event.target===this)closeForm()">
|
||||
<div class="modal">
|
||||
<div class="modal__header">
|
||||
<span class="modal__close" onclick="closeForm()">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3.5 3.5l9 9M12.5 3.5l-9 9" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
|
||||
</span>
|
||||
<span class="modal__title" id="formTitle">编辑用户体检信息</span>
|
||||
</div>
|
||||
<div class="modal__body">
|
||||
<div class="form-item">
|
||||
<div class="form-label">单位信息</div>
|
||||
<input class="form-input" id="formUnit" type="text" placeholder="请输入单位信息">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label"><span class="required">*</span> 姓名</div>
|
||||
<input class="form-input" id="formName" type="text" placeholder="请输入姓名">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label"><span class="required">*</span> 身份证号</div>
|
||||
<input class="form-input" id="formIdcard" type="text" placeholder="请输入身份证号">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">体检年份</div>
|
||||
<input class="form-input" id="formYear" type="text" placeholder="请输入体检年份">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">体检编号</div>
|
||||
<input class="form-input" id="formPeid" type="text" placeholder="请输入体检编号">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">医院ID</div>
|
||||
<input class="form-input" id="formHospid" type="text" placeholder="请输入医院ID">
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-label">医院名称</div>
|
||||
<input class="form-input" id="formHospital" type="text" placeholder="请输入医院名称">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal__footer">
|
||||
<button class="btn btn-default" onclick="closeForm()">取消</button>
|
||||
<button class="btn btn-primary" onclick="saveForm()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 详情弹窗 -->
|
||||
<div class="modal-mask" id="detailMask" onclick="if(event.target===this)closeDetail()">
|
||||
<div class="modal">
|
||||
<div class="modal__header">
|
||||
<span class="modal__close" onclick="closeDetail()">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3.5 3.5l9 9M12.5 3.5l-9 9" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
|
||||
</span>
|
||||
<span class="modal__title">用户体检信息详情</span>
|
||||
</div>
|
||||
<div class="modal__body" id="detailBody"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/* ============ 数据 ============ */
|
||||
var handleStatusMap={1:'新建',2:'待解析',3:'失败',4:'解析中',5:'成功',6:'失败待重试',7:'最终失败'};
|
||||
function statusTag(s){
|
||||
var cls='tag-gray';
|
||||
if(s===5)cls='tag-green';
|
||||
else if(s===4||s===6)cls='tag-orange';
|
||||
else if(s===3||s===7)cls='tag-red';
|
||||
else if(s===1)cls='tag-blue';
|
||||
return '<span class="tag '+cls+'">'+handleStatusMap[s]+'</span>';
|
||||
}
|
||||
var users=[
|
||||
{unit:'公司机关',realname:'张伟',idCard:'500103197805121234',medicalYear:'2026',hospitalName:'重庆市人民医院',hospitalId:'H001',peId:'PE20260001',createTime:'2026-08-15 10:23:45',children:[
|
||||
{name:'胸部CT平扫',status:5,studies:['1.2.840.113619.6.55.201','1.2.840.113619.6.55.202'],files:['report_chest_001.pdf']},
|
||||
{name:'头颅MRI平扫',status:5,studies:['1.2.840.113619.6.55.203'],files:['report_mri_001.pdf']},
|
||||
{name:'腹部超声',status:4,studies:['1.2.840.113619.6.55.204'],files:[]}
|
||||
]},
|
||||
{unit:'第一采油厂',realname:'李芳',idCard:'500107198812053467',medicalYear:'2026',hospitalName:'重庆医科大学附属第一医院',hospitalId:'H002',peId:'PE20260002',createTime:'2026-08-15 11:02:18',children:[
|
||||
{name:'胸部CT平扫',status:5,studies:['1.2.840.113619.6.55.301'],files:['report_chest_002.pdf']},
|
||||
{name:'心电图',status:5,studies:['1.2.840.113619.6.55.302'],files:['report_ecg_002.pdf']}
|
||||
]},
|
||||
{unit:'第二采油厂',realname:'王强',idCard:'500105199203154567',medicalYear:'2026',hospitalName:'陆军军医大学西南医院',hospitalId:'H003',peId:'PE20260003',createTime:'2026-08-15 13:45:09',children:[
|
||||
{name:'胸部X射线',status:7,studies:['1.2.840.113619.6.55.401'],files:[]},
|
||||
{name:'腹部超声',status:6,studies:['1.2.840.113619.6.55.402'],files:[]}
|
||||
]},
|
||||
{unit:'公共事务中心',realname:'赵敏',idCard:'500104199001011234',medicalYear:'2026',hospitalName:'陆军特色医学中心',hospitalId:'H004',peId:'PE20260004',createTime:'2026-08-16 09:12:33',children:[
|
||||
{name:'冠脉CTA',status:2,studies:[],files:[]}
|
||||
]},
|
||||
{unit:'公司机关',realname:'陈刚',idCard:'500106198503094567',medicalYear:'2025',hospitalName:'重庆市人民医院',hospitalId:'H001',peId:'PE20250018',createTime:'2025-08-20 15:30:00',children:[
|
||||
{name:'胸部CT平扫',status:5,studies:['1.2.840.113619.6.55.501'],files:['report_chest_018.pdf']},
|
||||
{name:'头颅MRI平扫',status:5,studies:['1.2.840.113619.6.55.502'],files:['report_mri_018.pdf']},
|
||||
{name:'腹部超声',status:5,studies:['1.2.840.113619.6.55.503'],files:['report_us_018.pdf']},
|
||||
{name:'心电图',status:5,studies:['1.2.840.113619.6.55.504'],files:['report_ecg_018.pdf']}
|
||||
]},
|
||||
{unit:'第一采油厂',realname:'刘洋',idCard:'500102199511223456',medicalYear:'2025',hospitalName:'重庆医科大学附属第一医院',hospitalId:'H002',peId:'PE20250021',createTime:'2025-08-21 10:05:52',children:[
|
||||
{name:'胸部CT平扫',status:5,studies:['1.2.840.113619.6.55.601'],files:['report_chest_021.pdf']},
|
||||
{name:'腹部超声',status:7,studies:['1.2.840.113619.6.55.602'],files:[]}
|
||||
]}
|
||||
];
|
||||
var state={name:'',idcard:'',year:'2026',hospital:'',page:1,pageSize:10};
|
||||
var expanded={};
|
||||
|
||||
/* ============ 年份选择 ============ */
|
||||
function toggleYear(){document.getElementById('yearDropdown').classList.toggle('open');}
|
||||
function pickYear(el){
|
||||
document.getElementById('f-year').value=el.textContent.trim();
|
||||
document.getElementById('yearDropdown').classList.remove('open');
|
||||
document.querySelectorAll('#yearDropdown div').forEach(function(d){d.classList.remove('selected');});
|
||||
el.classList.add('selected');
|
||||
}
|
||||
document.getElementById('f-year').addEventListener('click',toggleYear);
|
||||
document.addEventListener('click',function(e){
|
||||
if(!e.target.closest('.year-picker'))document.getElementById('yearDropdown').classList.remove('open');
|
||||
});
|
||||
|
||||
/* ============ 查询/重置 ============ */
|
||||
function doQuery(){
|
||||
state.name=document.getElementById('f-name').value.trim();
|
||||
state.idcard=document.getElementById('f-idcard').value.trim();
|
||||
state.year=document.getElementById('f-year').value.trim();
|
||||
state.hospital=document.getElementById('f-hospital').value.trim();
|
||||
state.page=1;
|
||||
expanded={};
|
||||
renderTable();
|
||||
}
|
||||
function doReset(){
|
||||
document.getElementById('f-name').value='';
|
||||
document.getElementById('f-idcard').value='';
|
||||
document.getElementById('f-year').value='2026';
|
||||
document.querySelectorAll('#yearDropdown div').forEach(function(d){
|
||||
d.classList.toggle('selected',d.textContent.trim()==='2026');
|
||||
});
|
||||
document.getElementById('f-hospital').value='';
|
||||
state.name='';state.idcard='';state.year='2026';state.hospital='';
|
||||
state.page=1;
|
||||
expanded={};
|
||||
renderTable();
|
||||
}
|
||||
|
||||
/* ============ 表格渲染 ============ */
|
||||
function filteredIdx(){
|
||||
var list=[];
|
||||
users.forEach(function(u,i){
|
||||
if(state.name&&u.realname.indexOf(state.name)===-1)return;
|
||||
if(state.idcard&&u.idCard.indexOf(state.idcard)===-1)return;
|
||||
if(state.year&&u.medicalYear!==state.year)return;
|
||||
if(state.hospital&&u.hospitalName.indexOf(state.hospital)===-1)return;
|
||||
list.push(i);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
function renderTable(){
|
||||
var list=filteredIdx();
|
||||
var totalPages=Math.max(1,Math.ceil(list.length/state.pageSize));
|
||||
if(state.page>totalPages)state.page=totalPages;
|
||||
var start=(state.page-1)*state.pageSize;
|
||||
var pageIdx=list.slice(start,start+state.pageSize);
|
||||
var tbody=document.getElementById('tbody');
|
||||
tbody.innerHTML=pageIdx.length?pageIdx.map(function(i,pos){
|
||||
var u=users[i];
|
||||
var isOpen=!!expanded[i];
|
||||
var html='<tr>'
|
||||
+'<td><input type="checkbox" class="row-check" data-idx="'+i+'"></td>'
|
||||
+'<td>'+(start+pos+1)+'</td>'
|
||||
+'<td><span class="expand-toggle'+(isOpen?' open':'')+'" onclick="toggleExpand('+i+')">'
|
||||
+'<svg width="12" height="12" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>'
|
||||
+'</span></td>'
|
||||
+'<td>'+u.unit+'</td><td>'+u.realname+'</td><td>'+u.idCard+'</td><td>'+u.medicalYear+'</td>'
|
||||
+'<td>'+u.hospitalName+'</td><td>'+u.peId+'</td><td>'+u.createTime+'</td>'
|
||||
+'<td><span class="link" onclick="openForm('+i+')">编辑</span> <span class="link" style="margin-left:8px;" onclick="openDetail('+i+')">详情</span> <span class="link-danger" style="margin-left:8px;" onclick="deleteRow('+i+')">删除</span></td>'
|
||||
+'</tr>';
|
||||
if(isOpen)html+=renderExpandRow(i);
|
||||
return html;
|
||||
}).join(''):'<tr><td colspan="11"><div class="empty-tip">暂无数据</div></td></tr>';
|
||||
var all=tbody.querySelectorAll('.row-check');
|
||||
var checked=tbody.querySelectorAll('.row-check:checked');
|
||||
document.getElementById('checkAll').checked=all.length>0&&all.length===checked.length;
|
||||
renderPagination(list.length,totalPages);
|
||||
}
|
||||
function renderExpandRow(i){
|
||||
var u=users[i];
|
||||
var body='';
|
||||
if(!u.children.length){
|
||||
body='<tr><td colspan="4"><div class="inner-empty" style="padding:16px 0;text-align:center;">暂无检查项目数据</div></td></tr>';
|
||||
}else{
|
||||
body=u.children.map(function(c){
|
||||
var studiesHtml=c.studies.length?c.studies.map(function(s){
|
||||
return '<span class="link" style="margin-right:6px;" onclick="previewStudy(\''+s+'\')">预览</span>';
|
||||
}).join(''):'<span class="inner-empty">暂无</span>';
|
||||
var filesHtml=c.files.length?c.files.map(function(f){
|
||||
return '<span class="link" style="margin-right:6px;" onclick="viewReport(\''+f+'\')">查看</span>';
|
||||
}).join(''):'<span class="inner-empty">无文件</span>';
|
||||
return '<tr><td>'+c.name+'</td><td>'+statusTag(c.status)+'</td><td>'+studiesHtml+'</td><td>'+filesHtml+'</td></tr>';
|
||||
}).join('');
|
||||
}
|
||||
return '<tr class="expand-row"><td colspan="11"><div class="inner-wrap">'
|
||||
+'<table class="inner-table"><thead><tr>'
|
||||
+'<th>检查项目名称</th><th>处理状态</th><th>影像信息</th><th>影像报告</th>'
|
||||
+'</tr></thead><tbody>'+body+'</tbody></table>'
|
||||
+'</div></td></tr>';
|
||||
}
|
||||
function toggleExpand(i){
|
||||
if(expanded[i])delete expanded[i];else expanded[i]=true;
|
||||
renderTable();
|
||||
}
|
||||
|
||||
/* ============ 分页 ============ */
|
||||
function pageSeq(p,last){
|
||||
var seq=[];
|
||||
if(last<=7){for(var i=1;i<=last;i++)seq.push(i);return seq;}
|
||||
if(p<=4){seq=[1,2,3,4,5,'...',last];}
|
||||
else if(p>=last-3){seq=[1,'...',last-4,last-3,last-2,last-1,last];}
|
||||
else{seq=[1,'...',p-1,p,p+1,'...',last];}
|
||||
return seq;
|
||||
}
|
||||
function renderPagination(total,totalPages){
|
||||
var html='<span>共 '+total+' 条数据</span>';
|
||||
if(totalPages>1){
|
||||
html+='<button class="page-btn"'+(state.page===1?' disabled':'')+' onclick="goPage('+(state.page-1)+')"><</button>';
|
||||
pageSeq(state.page,totalPages).forEach(function(p){
|
||||
if(p==='...')html+='<span class="page-ellipsis">...</span>';
|
||||
else html+='<button class="page-btn'+(p===state.page?' active':'')+'" onclick="goPage('+p+')">'+p+'</button>';
|
||||
});
|
||||
html+='<button class="page-btn"'+(state.page===totalPages?' disabled':'')+' onclick="goPage('+(state.page+1)+')">></button>';
|
||||
}
|
||||
html+='<select class="page-size" onchange="changeSize(this.value)">'
|
||||
+[10,20,50].map(function(n){return '<option value="'+n+'"'+(n===state.pageSize?' selected':'')+'>'+n+'条/页</option>';}).join('')
|
||||
+'</select>';
|
||||
html+='<span class="page-jump">跳至<input type="number" id="jumpInput" min="1" value="'+state.page+'" onkeydown="if(event.key===\'Enter\')jumpTo('+totalPages+')">页<button class="page-btn" onclick="jumpTo('+totalPages+')">跳</button></span>';
|
||||
document.getElementById('pagination').innerHTML=html;
|
||||
}
|
||||
function goPage(p){state.page=p;renderTable();}
|
||||
function changeSize(v){state.pageSize=parseInt(v,10);state.page=1;renderTable();}
|
||||
function jumpTo(totalPages){
|
||||
var input=document.getElementById('jumpInput');
|
||||
var p=parseInt(input.value,10);
|
||||
if(isNaN(p)||p<1)p=1;
|
||||
if(p>totalPages)p=totalPages;
|
||||
state.page=p;
|
||||
renderTable();
|
||||
}
|
||||
|
||||
/* ============ 影像预览/报告 ============ */
|
||||
function previewStudy(sid){
|
||||
alert('影像预览(Orthanc Web Viewer)\n研究实例ID:'+sid);
|
||||
}
|
||||
function viewReport(furl){
|
||||
alert('下载影像报告\n文件:'+furl);
|
||||
}
|
||||
|
||||
/* ============ 删除 ============ */
|
||||
function deleteRow(idx){
|
||||
var u=users[idx];
|
||||
if(!confirm('确认删除「'+u.realname+'」的体检影像信息?'))return;
|
||||
users.splice(idx,1);
|
||||
delete expanded[idx];
|
||||
renderTable();
|
||||
}
|
||||
|
||||
/* ============ 勾选 / 批量删除 ============ */
|
||||
function toggleCheckAll(cb){
|
||||
document.querySelectorAll('.row-check').forEach(function(c){c.checked=cb.checked;});
|
||||
}
|
||||
function checkedIdx(){
|
||||
var arr=[];
|
||||
document.querySelectorAll('.row-check:checked').forEach(function(c){arr.push(parseInt(c.dataset.idx,10));});
|
||||
return arr;
|
||||
}
|
||||
function batchDelete(){
|
||||
var idxs=checkedIdx();
|
||||
if(!idxs.length){alert('请先勾选要删除的记录');return;}
|
||||
if(!confirm('确认删除选中的 '+idxs.length+' 条体检影像信息?'))return;
|
||||
idxs.sort(function(a,b){return b-a;}).forEach(function(i){users.splice(i,1);delete expanded[i];});
|
||||
renderTable();
|
||||
}
|
||||
|
||||
/* ============ 详情 ============ */
|
||||
function openDetail(idx){
|
||||
var u=users[idx];
|
||||
document.getElementById('detailBody').innerHTML=
|
||||
'<table class="detail-table"><tbody>'
|
||||
+'<tr><th>单位信息</th><td>'+u.unit+'</td></tr>'
|
||||
+'<tr><th>姓名</th><td>'+u.realname+'</td></tr>'
|
||||
+'<tr><th>身份证号</th><td>'+u.idCard+'</td></tr>'
|
||||
+'<tr><th>体检年份</th><td>'+u.medicalYear+'</td></tr>'
|
||||
+'<tr><th>体检编号</th><td>'+u.peId+'</td></tr>'
|
||||
+'<tr><th>医院ID</th><td>'+u.hospitalId+'</td></tr>'
|
||||
+'<tr><th>医院名称</th><td>'+u.hospitalName+'</td></tr>'
|
||||
+'</tbody></table>';
|
||||
document.getElementById('detailMask').classList.add('open');
|
||||
}
|
||||
function closeDetail(){document.getElementById('detailMask').classList.remove('open');}
|
||||
|
||||
/* ============ 编辑 ============ */
|
||||
var editingIdx=null;
|
||||
function openForm(idx){
|
||||
editingIdx=idx;
|
||||
document.getElementById('formTitle').textContent='编辑用户体检信息';
|
||||
var u=users[idx];
|
||||
document.getElementById('formUnit').value=u.unit;
|
||||
document.getElementById('formName').value=u.realname;
|
||||
document.getElementById('formIdcard').value=u.idCard;
|
||||
document.getElementById('formYear').value=u.medicalYear;
|
||||
document.getElementById('formPeid').value=u.peId;
|
||||
document.getElementById('formHospid').value=u.hospitalId;
|
||||
document.getElementById('formHospital').value=u.hospitalName;
|
||||
document.getElementById('formMask').classList.add('open');
|
||||
}
|
||||
function closeForm(){document.getElementById('formMask').classList.remove('open');}
|
||||
function saveForm(){
|
||||
var name=document.getElementById('formName').value.trim();
|
||||
var idcard=document.getElementById('formIdcard').value.trim();
|
||||
if(!name){alert('请输入姓名');return;}
|
||||
if(!idcard){alert('请输入身份证号');return;}
|
||||
var u=users[editingIdx];
|
||||
u.unit=document.getElementById('formUnit').value.trim();
|
||||
u.realname=name;
|
||||
u.idCard=idcard;
|
||||
u.medicalYear=document.getElementById('formYear').value.trim();
|
||||
u.peId=document.getElementById('formPeid').value.trim();
|
||||
u.hospitalId=document.getElementById('formHospid').value.trim();
|
||||
u.hospitalName=document.getElementById('formHospital').value.trim();
|
||||
closeForm();
|
||||
renderTable();
|
||||
}
|
||||
document.addEventListener('keydown',function(e){
|
||||
if(e.key==='Escape'){closeForm();closeDetail();}
|
||||
});
|
||||
|
||||
/* ============ 通用 ============ */
|
||||
function toggleSubgroup(header){
|
||||
header.parentElement.classList.toggle('open');
|
||||
}
|
||||
/* 页面加载时自动展开当前页面所在的子分组 */
|
||||
(function(){
|
||||
renderTable();
|
||||
var active=document.querySelector('.sidebar-item.active');
|
||||
if(!active)return;
|
||||
var sub=active.closest('.sidebar-subgroup');
|
||||
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -180,6 +180,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -172,6 +172,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -205,6 +205,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -207,6 +207,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -258,6 +258,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -191,6 +191,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -181,6 +181,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -202,6 +202,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
@@ -211,6 +211,18 @@
|
||||
<a href="post-cta-stat.html" class="sidebar-item">冠脉CTA体检统计</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-subgroup">
|
||||
<div class="sidebar-subgroup__header" onclick="toggleSubgroup(this)">
|
||||
<svg class="arrow" viewBox="0 0 12 12"><path d="M4 2l4 4-4 4" fill="none" stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
体检影像管理
|
||||
</div>
|
||||
<div class="sidebar-subgroup__body">
|
||||
<a href="post-imc-user.html" class="sidebar-item">用户体检信息</a>
|
||||
<a href="post-imc-class.html" class="sidebar-item">用户影像文件分类</a>
|
||||
<a href="post-imc-info.html" class="sidebar-item">用户影像文件详细</a>
|
||||
<a href="post-imc-log.html" class="sidebar-item">文件处理日志</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 主内容 -->
|
||||
|
||||
Reference in New Issue
Block a user