feat: 健康体检原型完善(单位体检计划新增新增/详情弹窗与员工选择弹窗,医院承检范围编辑抽屉改为弹窗并新增详情弹窗、预约量改为按日配置含跳过节假日/周末,医院项目费用列表加图片列与更新已生成费用等操作及新增关联项目弹窗,医院实时预约人数加日期范围筛选默认当月)

This commit is contained in:
liuyunqin
2026-09-01 18:04:57 +08:00
parent db8c2d1d08
commit 12f54cdbd9
5 changed files with 2027 additions and 574 deletions
@@ -50,6 +50,10 @@
.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-date{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 10px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;width:150px;}
.filter-date:focus{border-color:var(--primary);}
.filter-date::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.6;}
.filter-range-sep{color:var(--text-placeholder);font-size:var(--font-sm);}
.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:120px;}
.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;}
@@ -153,6 +157,12 @@
<option>请选择</option><option>泾河医院</option><option>庆阳医院</option><option>延安医院</option>
</select>
</div>
<div class="filter-item">
<label>日期范围:</label>
<input type="date" class="filter-date" id="filter-date-start">
<span class="filter-range-sep"></span>
<input type="date" class="filter-date" id="filter-date-end">
</div>
<button class="btn btn-primary">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6" cy="6" r="4" stroke="currentColor" stroke-width="1.4"/><path d="M10 10l2.5 2.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
查询
@@ -216,6 +226,16 @@ function toggleSubgroup(header){
var sub=active.closest('.sidebar-subgroup');
if(sub)sub.classList.add('open');
})();
/* 日期范围默认当月 */
(function(){
function pad(n){return n<10?'0'+n:''+n;}
var now=new Date();
var first=now.getFullYear()+'-'+pad(now.getMonth()+1)+'-01';
var last=now.getFullYear()+'-'+pad(now.getMonth()+1)+'-'+pad(new Date(now.getFullYear(),now.getMonth()+1,0).getDate());
document.getElementById('filter-date-start').value=first;
document.getElementById('filter-date-end').value=last;
})();
</script>
</body>
</html>
@@ -72,29 +72,31 @@
.tag-green{background:#F6FFED;color:var(--success);}
.tag-orange{background:#FFF7E6;color:var(--warning);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.tag-gray{background:#F5F5F5;color:var(--text-secondary);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.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;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 抽屉弹窗 */
.drawer-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0);z-index:999;pointer-events:none;transition:background .3s;}
.drawer-overlay.open{background:rgba(0,0,0,0.45);pointer-events:auto;}
.drawer{position:fixed;top:0;right:-480px;bottom:0;width:480px;background:#fff;box-shadow:-2px 0 8px rgba(0,0,0,0.15);z-index:1000;transition:right .3s;display:flex;flex-direction:column;}
.drawer.open{right:0;}
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid var(--border);flex-shrink:0;}
.drawer__title{font-size:var(--font-lg);font-weight:600;}
.drawer__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.drawer__close:hover{background:#F5F5F5;}
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
.drawer__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);flex-shrink:0;}
/* 中间弹窗 */
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:1001;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{width:860px;max-width:calc(100vw - 48px);max-height:calc(100vh - 80px);background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-md);display:flex;flex-direction:column;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);flex-shrink:0;}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{flex:1;overflow-y:auto;padding:20px 24px;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:14px 24px;border-top:1px solid var(--border);flex-shrink:0;}
/* 表单 */
.form-item{margin-bottom:20px;}
.form-item{margin-bottom:16px;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;display:flex;align-items:center;gap:4px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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{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::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.6;}
.form-input:disabled{background:#F5F5F5;color:var(--text-secondary);cursor:not-allowed;}
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 20px;}
/* 开关 */
.switch-row{display:flex;align-items:center;gap:12px;}
.switch{width:40px;height:22px;border-radius:11px;background:#E8E8E8;cursor:pointer;position:relative;transition:.2s;flex-shrink:0;}
@@ -102,7 +104,8 @@
.switch::after{content:'';position:absolute;width:18px;height:18px;border-radius:50%;background:#fff;top:2px;left:2px;transition:.2s;box-shadow:0 1px 3px rgba(0,0,0,0.2);}
.switch.on::after{left:20px;}
.switch-label{font-size:var(--font-sm);color:var(--text-primary);}
/* 可搜索下拉 */
.switch-group{display:flex;align-items:center;gap:28px;}
/* 可搜索下拉(筛选栏) */
.search-select{position:relative;}
.search-select__input{width:100%;height:40px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 32px 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 12px center;}
.search-select__input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
@@ -115,16 +118,31 @@
.filter-bar .search-select{width:200px;}
.filter-bar .search-select__input{height:36px;}
.filter-bar .search-select__dropdown{top:40px;}
/* 分区标题与动态行 */
.form-section{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:24px 0 4px;padding-top:16px;border-top:1px solid var(--border);}
.form-tip{font-size:var(--font-xs);color:var(--text-placeholder);margin-bottom:12px;line-height:1.5;}
.dynamic-list{margin-bottom:4px;}
.dynamic-row{display:flex;align-items:center;gap:8px;margin-bottom:8px;}
.dynamic-row .form-input{flex:1;}
.dynamic-row .row-del{width:32px;height:32px;border-radius:var(--radius-sm);border:1px solid var(--border);background:#fff;color:var(--danger);cursor:pointer;flex-shrink:0;font-size:16px;line-height:1;}
.dynamic-row .row-del:hover{background:#fff1f0;border-color:var(--danger);}
.add-row-btn{display:inline-flex;align-items:center;gap:4px;font-size:var(--font-sm);color:var(--primary);cursor:pointer;border:1px dashed var(--primary);border-radius:var(--radius-sm);padding:5px 12px;background:var(--primary-light);user-select:none;}
.add-row-btn:hover{background:#bae7ff;}
/* 分区标题 */
.form-section{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:20px 0 8px;padding-top:14px;border-top:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;}
.form-tip{font-size:var(--font-xs);color:var(--text-placeholder);margin-bottom:10px;line-height:1.5;}
/* 月视图日历 */
.cal-nav{display:flex;align-items:center;gap:8px;}
.cal-nav__btn{width:26px;height:26px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);color:var(--text-secondary);display:inline-flex;align-items:center;justify-content:center;}
.cal-nav__btn:hover{color:var(--primary);border-color:var(--primary);}
.cal-nav__label{font-size:var(--font-sm);font-weight:600;min-width:88px;text-align:center;}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:6px;}
.cal-week{font-size:var(--font-xs);color:var(--text-secondary);text-align:center;padding:2px 0;}
.cal-cell{min-height:58px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:4px 5px;background:#fff;}
.cal-cell__day{font-size:var(--font-xs);color:var(--text-primary);margin-bottom:4px;}
.cal-cell__day .cal-name{color:var(--danger);margin-left:2px;}
.cal-cell__input{width:100%;height:24px;border:1px solid var(--border);border-radius:var(--radius-sm);font-size:var(--font-xs);padding:0 4px;outline:none;color:var(--text-primary);}
.cal-cell__input:focus{border-color:var(--primary);}
.cal-cell__input::placeholder{color:#C0C4CC;}
.cal-cell.rest{background:#F5F5F5;border-color:#EBEBEB;}
.cal-cell.rest .cal-cell__day{color:var(--text-placeholder);}
.cal-cell.rest .cal-name{color:var(--text-placeholder);}
.cal-cell__rest{font-size:var(--font-xs);color:var(--text-placeholder);text-align:center;padding:3px 0;}
.cal-legend{display:flex;align-items:center;gap:16px;margin-top:10px;font-size:var(--font-xs);color:var(--text-secondary);}
.cal-legend__item{display:inline-flex;align-items:center;gap:5px;}
.cal-legend__box{width:12px;height:12px;border-radius:2px;border:1px solid var(--border);display:inline-block;}
.cal-legend__box.rest{background:#F5F5F5;border-color:#EBEBEB;}
.cal-legend__box.edit{background:#fff;}
/* 详情展示 */
.detail-item{margin-bottom:16px;}
.detail-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:6px;}
@@ -132,7 +150,10 @@
.detail-list-row{display:flex;justify-content:space-between;align-items:center;padding:10px 12px;background:#F8FBFF;border-radius:var(--radius-sm);margin-bottom:6px;font-size:var(--font-sm);}
.detail-list-row .detail-count{color:var(--primary);font-weight:600;}
.detail-empty{font-size:var(--font-sm);color:var(--text-placeholder);padding:4px 0;}
/* TAB 切换 */
.detail-summary{display:grid;grid-template-columns:repeat(2,1fr);gap:12px 24px;margin-bottom:4px;}
.detail-summary .detail-item{margin-bottom:0;}
.cal-cell__count{font-size:var(--font-xs);color:var(--primary);font-weight:600;text-align:center;background:var(--primary-light);border-radius:var(--radius-sm);padding:3px 0;}
.cal-cell__count.def{color:var(--text-secondary);font-weight:400;background:#F8FBFF;}
.tab-pane{display:none;}
.tab-pane.active{display:block;}
</style>
@@ -261,12 +282,12 @@
<table>
<thead>
<tr>
<th>序号</th><th>医院名称</th><th>每日最承检人数</th><th>承检开始日期</th><th>承检结束日期</th><th>有效标志</th><th>操作</th>
<th>序号</th><th>医院名称</th><th>每日最承检人数</th><th>承检开始日期</th><th>承检结束日期</th><th>有效标志</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr data-exceptions='[{"date":"2026-05-10","count":"50"}]' data-nodates='["2026-06-20"]'><td>1</td><td>长安胃肠镜医院</td><td>80</td><td>2026-03-01</td><td>2026-10-31</td><td><span class="tag tag-green">有效</span></td><td><span class="link" onclick="openDetail(this)">详情</span> <span class="link" style="margin-left:8px;" onclick="openEdit(this)">编辑</span></td></tr>
<tr data-exceptions='[]' data-nodates='[]'><td>2</td><td>庆阳医院</td><td>60</td><td>2026-03-01</td><td>2026-10-31</td><td><span class="tag tag-green">有效</span></td><td><span class="link" onclick="openDetail(this)">详情</span> <span class="link" style="margin-left:8px;" onclick="openEdit(this)">编辑</span></td></tr>
<tr data-daycounts='{"2026-05-10":"50"}' data-skip-holiday="1" data-skip-sat="1" data-skip-sun="1"><td>1</td><td>长安胃肠镜医院</td><td>80</td><td>2026-03-01</td><td>2026-10-31</td><td><span class="tag tag-green">有效</span></td><td><span class="link" onclick="openDetail(this)">详情</span> <span class="link" style="margin-left:8px;" onclick="openEdit(this)">编辑</span></td></tr>
<tr data-daycounts='{}' data-skip-holiday="0" data-skip-sat="0" data-skip-sun="0"><td>2</td><td>庆阳医院</td><td>60</td><td>2026-03-01</td><td>2026-10-31</td><td><span class="tag tag-green">有效</span></td><td><span class="link" onclick="openDetail(this)">详情</span> <span class="link" style="margin-left:8px;" onclick="openEdit(this)">编辑</span></td></tr>
</tbody>
</table>
</div>
@@ -280,95 +301,136 @@
</div>
</main>
<!-- 编辑医院承检范围抽屉 -->
<div class="drawer-overlay" id="drawer-overlay" onclick="closeDrawer()"></div>
<div class="drawer" id="scope-drawer">
<div class="drawer__header">
<div class="drawer__title">编辑医院承检范围</div>
<button class="drawer__close" onclick="closeDrawer()"></button>
</div>
<div class="drawer__body">
<div class="form-item">
<div class="form-label"><span class="required">*</span> 医院</div>
<div class="search-select" id="search-select">
<input type="text" class="search-select__input" id="search-input" placeholder="请输入医院名称搜索" autocomplete="off">
<input type="hidden" id="search-value">
<div class="search-select__dropdown" id="search-dropdown"></div>
<!-- 编辑医院承检范围中间弹窗 -->
<div class="modal-overlay" id="scope-modal-overlay">
<div class="modal" id="scope-modal">
<div class="modal__header">
<div class="modal__title">编辑医院承检范围</div>
<button class="modal__close" onclick="closeModal()"></button>
</div>
<div class="modal__body">
<div class="form-item">
<div class="form-label"><span class="required">*</span> 医院</div>
<input class="form-input" id="form-hospital" type="text" disabled>
</div>
<div class="form-grid">
<div class="form-item">
<div class="form-label"><span class="required">*</span> 每日最大承检人数</div>
<input class="form-input" id="form-capacity" type="number" min="1" placeholder="未单独设定的日期按此人数承检">
</div>
<div class="form-item">
<div class="form-label">有效标志</div>
<div class="switch-row" style="height:36px;">
<div class="switch on" id="switch-valid" onclick="toggleSwitch(this,'switch-valid-label','有效','无效')"></div>
<span class="switch-label" id="switch-valid-label">有效</span>
</div>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 承检开始日期</div>
<input class="form-input" id="form-start" type="date">
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 承检结束日期</div>
<input class="form-input" id="form-end" type="date">
</div>
</div>
<div class="form-item">
<div class="form-label">休息日设置</div>
<div class="switch-group">
<div class="switch-row">
<div class="switch" id="switch-skip-holiday" onclick="toggleSkipSwitch(this)"></div>
<span class="switch-label">跳过节假日</span>
</div>
<div class="switch-row">
<div class="switch" id="switch-skip-sat" onclick="toggleSkipSwitch(this)"></div>
<span class="switch-label">跳过周六</span>
</div>
<div class="switch-row">
<div class="switch" id="switch-skip-sun" onclick="toggleSkipSwitch(this)"></div>
<span class="switch-label">跳过周日</span>
</div>
</div>
</div>
<!-- 按月设定承检人数 -->
<div class="form-section">
<span>按月设定承检人数</span>
<span class="cal-nav">
<button class="cal-nav__btn" onclick="calPrevMonth()"></button>
<span class="cal-nav__label" id="cal-label"></span>
<button class="cal-nav__btn" onclick="calNextMonth()"></button>
</span>
</div>
<div class="form-tip">每个日期下方可自由设定当日承检人数,默认按"每日最大承检人数"执行;被跳过的节假日与周六日自动置灰、不可设定。</div>
<div class="cal-grid" id="cal-weekdays"></div>
<div class="cal-grid" id="cal-days" style="margin-top:6px;"></div>
<div class="cal-legend">
<span class="cal-legend__item"><span class="cal-legend__box edit"></span>可设定日期</span>
<span class="cal-legend__item"><span class="cal-legend__box rest"></span>置灰休息日(节假日 / 周六 / 周日 / 超出承检期)</span>
</div>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 每日最多承检人数</div>
<input class="form-input" id="form-capacity" type="number" min="1" placeholder="请输入人数">
<div class="modal__footer">
<button class="btn btn-default" onclick="closeModal()">取消</button>
<button class="btn btn-primary" onclick="saveEdit()">确认保存</button>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 承检开始日期</div>
<input class="form-input" id="form-start" type="date">
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 承检结束日期</div>
<input class="form-input" id="form-end" type="date">
</div>
<div class="form-item">
<div class="form-label">有效标志</div>
<div class="switch-row">
<div class="switch on" id="switch-valid" onclick="toggleValidSwitch(this)"></div>
<span class="switch-label" id="switch-valid-label">有效</span>
</div>
</div>
<!-- 例外人数设定 -->
<div class="form-section">例外人数设定</div>
<div class="form-tip">针对特定日期单独设置承检人数(覆盖"每日最多承检人数"),例如节假日或加号日期。</div>
<div class="dynamic-list" id="exception-list"></div>
<div class="add-row-btn" onclick="addExceptionRow()"> 添加例外</div>
<!-- 不参检日期 -->
<div class="form-section">不参检日期</div>
<div class="form-tip">设置该医院不承接体检的日期,系统将自动跳过这些日期。</div>
<div class="dynamic-list" id="nodate-list"></div>
<div class="add-row-btn" onclick="addNoDateRow()"> 添加日期</div>
</div>
<div class="drawer__footer">
<button class="btn btn-default" onclick="closeDrawer()">取消</button>
<button class="btn btn-primary" onclick="saveEdit()">确认保存</button>
</div>
</div>
<!-- 医院承检范围详情抽屉 -->
<div class="drawer-overlay" id="detail-overlay" onclick="closeDetail()"></div>
<div class="drawer" id="detail-drawer">
<div class="drawer__header">
<div class="drawer__title">医院承检范围详情</div>
<button class="drawer__close" onclick="closeDetail()"></button>
</div>
<div class="drawer__body">
<div class="detail-item">
<div class="detail-label">医院</div>
<div class="detail-value" id="detail-hospital"></div>
<!-- 医院承检范围详情中间弹窗 -->
<div class="modal-overlay" id="detail-overlay">
<div class="modal" id="detail-modal">
<div class="modal__header">
<div class="modal__title">医院承检范围详情</div>
<button class="modal__close" onclick="closeDetail()"></button>
</div>
<div class="detail-item">
<div class="detail-label">每日最多承检人数</div>
<div class="detail-value" id="detail-capacity"></div>
<div class="modal__body">
<div class="detail-summary">
<div class="detail-item">
<div class="detail-label">医院</div>
<div class="detail-value" id="detail-hospital"></div>
</div>
<div class="detail-item">
<div class="detail-label">每日最大承检人数</div>
<div class="detail-value" id="detail-capacity"></div>
</div>
<div class="detail-item">
<div class="detail-label">承检开始日期</div>
<div class="detail-value" id="detail-start"></div>
</div>
<div class="detail-item">
<div class="detail-label">承检结束日期</div>
<div class="detail-value" id="detail-end"></div>
</div>
<div class="detail-item">
<div class="detail-label">有效标志</div>
<div class="detail-value" id="detail-valid"></div>
</div>
<div class="detail-item">
<div class="detail-label">休息日设置</div>
<div class="detail-value" id="detail-skips"></div>
</div>
</div>
<!-- 按月查看承检人数(只读) -->
<div class="form-section">
<span>按月查看承检人数</span>
<span class="cal-nav">
<button class="cal-nav__btn" onclick="detailCalPrevMonth()"></button>
<span class="cal-nav__label" id="detail-cal-label"></span>
<button class="cal-nav__btn" onclick="detailCalNextMonth()"></button>
</span>
</div>
<div class="form-tip">标"休"的日期为承检休息日,不开放预约。</div>
<div class="cal-grid" id="detail-cal-weekdays"></div>
<div class="cal-grid" id="detail-cal-days" style="margin-top:6px;"></div>
<div class="cal-legend">
<span class="cal-legend__item"><span class="cal-legend__box edit"></span>可承检日期</span>
<span class="cal-legend__item"><span class="cal-legend__box rest"></span>休息日(节假日 / 周六 / 周日 / 超出承检期)</span>
</div>
</div>
<div class="detail-item">
<div class="detail-label">承检开始日期</div>
<div class="detail-value" id="detail-start"></div>
<div class="modal__footer">
<button class="btn btn-primary" onclick="closeDetail()">关闭</button>
</div>
<div class="detail-item">
<div class="detail-label">承检结束日期</div>
<div class="detail-value" id="detail-end"></div>
</div>
<div class="detail-item">
<div class="detail-label">有效标志</div>
<div class="detail-value" id="detail-valid"></div>
</div>
<div class="form-section">例外人数设定</div>
<div id="detail-exceptions"></div>
<div class="form-section">不参检日期</div>
<div id="detail-nodates"></div>
</div>
<div class="drawer__footer">
<button class="btn btn-primary" onclick="closeDetail()">关闭</button>
</div>
</div>
@@ -385,7 +447,7 @@ function toggleSubgroup(header){
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* ===== 编辑医院承检范围抽屉 ===== */
/* ===== 数据 ===== */
var hospitalData = {
'h1': '庆阳医院',
'h2': '兴隆园医院',
@@ -397,21 +459,48 @@ var hospitalData = {
'h8': '长安胃肠镜医院'
};
/* 2026 年法定节假日(休假日,原型内置) */
var holidayData = {
'2026-01-01':'元旦','2026-01-02':'元旦','2026-01-03':'元旦',
'2026-02-15':'春节','2026-02-16':'春节','2026-02-17':'春节','2026-02-18':'春节','2026-02-19':'春节','2026-02-20':'春节','2026-02-21':'春节','2026-02-22':'春节',
'2026-04-04':'清明节','2026-04-05':'清明节','2026-04-06':'清明节',
'2026-05-01':'劳动节','2026-05-02':'劳动节','2026-05-03':'劳动节','2026-05-04':'劳动节','2026-05-05':'劳动节',
'2026-06-19':'端午节','2026-06-20':'端午节','2026-06-21':'端午节',
'2026-09-25':'中秋节','2026-09-26':'中秋节','2026-09-27':'中秋节',
'2026-10-01':'国庆节','2026-10-02':'国庆节','2026-10-03':'国庆节','2026-10-04':'国庆节','2026-10-05':'国庆节','2026-10-06':'国庆节','2026-10-07':'国庆节'
};
/* 通用开关 */
function toggleSwitch(el, labelId, onText, offText){
el.classList.toggle('on');
document.getElementById(labelId).textContent = el.classList.contains('on') ? onText : offText;
}
/* ===== 编辑医院承检范围中间弹窗 ===== */
var editingTr = null;
var calYear = 2026, calMonth = 1; // calMonth: 1-12
var dayCounts = {}; // 弹窗内暂存的 { 'YYYY-MM-DD': '100' }
function pad2(n){ return n < 10 ? '0' + n : '' + n; }
function dateKey(y, m, d){ return y + '-' + pad2(m) + '-' + pad2(d); }
function readRowState(tr){
var counts = {};
try { counts = JSON.parse(tr.dataset.daycounts || '{}'); } catch(e){}
return {
daycounts: counts,
skipHoliday: tr.dataset.skipHoliday === '1',
skipSat: tr.dataset.skipSat === '1',
skipSun: tr.dataset.skipSun === '1'
};
}
function openEdit(btn){
var tr = btn.closest('tr');
editingTr = tr;
var cells = tr.cells;
var name = cells[1].textContent.trim();
var key = '';
for(var k in hospitalData){
if(hospitalData[k] === name){ key = k; break; }
}
document.getElementById('search-value').value = key;
document.getElementById('search-input').value = name;
document.getElementById('form-hospital').value = cells[1].textContent.trim();
document.getElementById('form-capacity').value = cells[2].textContent.trim();
document.getElementById('form-start').value = cells[3].textContent.trim();
document.getElementById('form-end').value = cells[4].textContent.trim();
@@ -421,83 +510,135 @@ function openEdit(btn){
sw.classList.toggle('on', valid);
document.getElementById('switch-valid-label').textContent = valid ? '有效' : '无效';
var exceptions = [];
try { exceptions = JSON.parse(tr.dataset.exceptions || '[]'); } catch(e){}
document.getElementById('exception-list').innerHTML = '';
if(exceptions.length === 0){ addExceptionRow(); }
else { exceptions.forEach(function(ex){ addExceptionRow(ex.date, ex.count); }); }
var state = readRowState(tr);
document.getElementById('switch-skip-holiday').classList.toggle('on', state.skipHoliday);
document.getElementById('switch-skip-sat').classList.toggle('on', state.skipSat);
document.getElementById('switch-skip-sun').classList.toggle('on', state.skipSun);
var noDates = [];
try { noDates = JSON.parse(tr.dataset.nodates || '[]'); } catch(e){}
document.getElementById('nodate-list').innerHTML = '';
if(noDates.length === 0){ addNoDateRow(); }
else { noDates.forEach(function(d){ addNoDateRow(d); }); }
document.getElementById('scope-drawer').classList.add('open');
document.getElementById('drawer-overlay').classList.add('open');
}
function closeDrawer(){
document.getElementById('scope-drawer').classList.remove('open');
document.getElementById('drawer-overlay').classList.remove('open');
}
/* 有效标志开关 */
function toggleValidSwitch(el){
el.classList.toggle('on');
document.getElementById('switch-valid-label').textContent = el.classList.contains('on') ? '有效' : '无效';
}
/* 可搜索下拉 */
(function(){
var input = document.getElementById('search-input');
var dropdown = document.getElementById('search-dropdown');
var hidden = document.getElementById('search-value');
function renderOptions(keyword){
dropdown.innerHTML = '';
var kw = keyword.trim().toLowerCase();
var has = false;
for(var key in hospitalData){
var name = hospitalData[key];
if(!kw || name.toLowerCase().indexOf(kw) !== -1){
has = true;
var opt = document.createElement('div');
opt.className = 'search-select__option';
if(hidden.value === key) opt.classList.add('active');
opt.textContent = name;
opt.dataset.value = key;
opt.onclick = function(){
hidden.value = key;
input.value = name;
dropdown.classList.remove('show');
};
dropdown.appendChild(opt);
}
}
if(!has){
var empty = document.createElement('div');
empty.className = 'search-select__empty';
empty.textContent = '无匹配医院';
dropdown.appendChild(empty);
}
dayCounts = state.daycounts;
var start = document.getElementById('form-start').value;
if(start){
calYear = parseInt(start.slice(0,4), 10);
calMonth = parseInt(start.slice(5,7), 10);
}
renderCalendar();
input.addEventListener('focus', function(){
renderOptions(this.value);
dropdown.classList.add('show');
});
input.addEventListener('input', function(){
hidden.value = '';
renderOptions(this.value);
dropdown.classList.add('show');
});
document.addEventListener('click', function(e){
if(!e.target.closest('#search-select')){
dropdown.classList.remove('show');
document.getElementById('scope-modal-overlay').classList.add('open');
}
function closeModal(){
document.getElementById('scope-modal-overlay').classList.remove('open');
}
function getSkipState(){
return {
skipHoliday: document.getElementById('switch-skip-holiday').classList.contains('on'),
skipSat: document.getElementById('switch-skip-sat').classList.contains('on'),
skipSun: document.getElementById('switch-skip-sun').classList.contains('on')
};
}
/* 切换跳过开关:先留存当前页人数输入,再重渲染日历(置灰状态随之变化) */
function toggleSkipSwitch(el){
commitCalendarInputs();
el.classList.toggle('on');
renderCalendar();
}
/* 日期是否置灰:承检期之外,或被开关命中的节假日 / 周六 / 周日 */
function isRestDay(key, dow){
var start = document.getElementById('form-start').value;
var end = document.getElementById('form-end').value;
if(start && key < start) return true;
if(end && key > end) return true;
var s = getSkipState();
if(s.skipSun && dow === 0) return true;
if(s.skipSat && dow === 6) return true;
if(s.skipHoliday && holidayData[key]) return true;
return false;
}
function calPrevMonth(){ commitCalendarInputs(); if(calMonth === 1){ calMonth = 12; calYear--; } else calMonth--; renderCalendar(); }
function calNextMonth(){ commitCalendarInputs(); if(calMonth === 12){ calMonth = 1; calYear++; } else calMonth++; renderCalendar(); }
function renderCalendar(){
document.getElementById('cal-label').textContent = calYear + ' 年 ' + calMonth + ' 月';
var wk = document.getElementById('cal-weekdays');
if(!wk.children.length){
wk.innerHTML = ['日','一','二','三','四','五','六'].map(function(w){ return '<div class="cal-week">' + w + '</div>'; }).join('');
}
var grid = document.getElementById('cal-days');
grid.innerHTML = '';
var firstDow = new Date(calYear, calMonth - 1, 1).getDay();
var daysInMonth = new Date(calYear, calMonth, 0).getDate();
for(var i = 0; i < firstDow; i++){
var blank = document.createElement('div');
grid.appendChild(blank);
}
for(var d = 1; d <= daysInMonth; d++){
var key = dateKey(calYear, calMonth, d);
var dow = new Date(calYear, calMonth - 1, d).getDay();
var cell = document.createElement('div');
var hName = holidayData[key] || '';
var dayLabel = '<div class="cal-cell__day">' + d + (hName ? '<span class="cal-name">' + hName + '</span>' : '') + '</div>';
if(isRestDay(key, dow)){
cell.className = 'cal-cell rest';
cell.innerHTML = dayLabel + '<div class="cal-cell__rest">休</div>';
} else {
cell.className = 'cal-cell';
cell.innerHTML = dayLabel + '<input type="number" min="0" class="cal-cell__input" data-key="' + key + '" placeholder="' + (document.getElementById('form-capacity').value.trim() || '人数') + '" value="' + (dayCounts[key] != null ? dayCounts[key] : '') + '">';
}
grid.appendChild(cell);
}
}
/* 把当前页输入写回 dayCounts */
function commitCalendarInputs(){
document.querySelectorAll('#cal-days .cal-cell__input').forEach(function(inp){
var v = inp.value.trim();
if(v) dayCounts[inp.dataset.key] = v;
else delete dayCounts[inp.dataset.key];
});
})();
}
/* 承检起止日期变化时重渲染(置灰范围随之变化) */
function bindDateReRender(){
['form-start','form-end','form-capacity'].forEach(function(id){
document.getElementById(id).addEventListener('change', function(){
commitCalendarInputs();
renderCalendar();
});
});
}
bindDateReRender();
/* 保存编辑 */
function saveEdit(){
if(!editingTr){ return; }
var name = document.getElementById('form-hospital').value.trim();
if(!name){ alert('未找到医院信息'); return; }
var capacity = document.getElementById('form-capacity').value.trim();
if(!capacity || Number(capacity) <= 0){ alert('请输入正确的每日最大承检人数'); return; }
var start = document.getElementById('form-start').value;
var end = document.getElementById('form-end').value;
if(!start){ alert('请选择承检开始日期'); return; }
if(!end){ alert('请选择承检结束日期'); return; }
if(start > end){ alert('承检结束日期不能早于开始日期'); return; }
commitCalendarInputs();
var s = getSkipState();
var valid = document.getElementById('switch-valid').classList.contains('on');
var cells = editingTr.cells;
cells[2].textContent = capacity;
cells[3].textContent = start;
cells[4].textContent = end;
cells[5].innerHTML = valid ? '<span class="tag tag-green">有效</span>' : '<span class="tag tag-red">无效</span>';
editingTr.dataset.daycounts = JSON.stringify(dayCounts);
editingTr.dataset.skipHoliday = s.skipHoliday ? '1' : '0';
editingTr.dataset.skipSat = s.skipSat ? '1' : '0';
editingTr.dataset.skipSun = s.skipSun ? '1' : '0';
closeModal();
}
/* 筛选栏可搜索下拉 */
(function(){
@@ -574,71 +715,61 @@ function resetFilter(){
if(activePane) activePane.querySelectorAll('tbody tr').forEach(function(tr){ tr.style.display = ''; });
}
/* 例外人数动态行 */
function addExceptionRow(date, count){
var list = document.getElementById('exception-list');
var row = document.createElement('div');
row.className = 'dynamic-row';
row.innerHTML = '<input type="date" class="form-input row-date" value="' + (date || '') + '">'
+ '<input type="number" class="form-input row-count" min="1" placeholder="例外人数" value="' + (count || '') + '" style="max-width:110px;">'
+ '<button class="row-del" onclick="this.parentElement.remove()">×</button>';
list.appendChild(row);
/* 详情(只读月历) */
var detailState = null; // 当前查看行的承检配置快照
var detailCalYear = 2026, detailCalMonth = 1;
function isRestDayByState(key, dow, s){
if(s.start && key < s.start) return true;
if(s.end && key > s.end) return true;
if(s.skipSun && dow === 0) return true;
if(s.skipSat && dow === 6) return true;
if(s.skipHoliday && holidayData[key]) return true;
return false;
}
/* 不参检日期动态行 */
function addNoDateRow(date){
var list = document.getElementById('nodate-list');
var row = document.createElement('div');
row.className = 'dynamic-row';
row.innerHTML = '<input type="date" class="form-input row-date" value="' + (date || '') + '" placeholder="选择日期">'
+ '<button class="row-del" onclick="this.parentElement.remove()">×</button>';
list.appendChild(row);
function detailCalPrevMonth(){ if(detailCalMonth === 1){ detailCalMonth = 12; detailCalYear--; } else detailCalMonth--; renderDetailCalendar(); }
function detailCalNextMonth(){ if(detailCalMonth === 12){ detailCalMonth = 1; detailCalYear++; } else detailCalMonth++; renderDetailCalendar(); }
function renderDetailCalendar(){
if(!detailState) return;
document.getElementById('detail-cal-label').textContent = detailCalYear + ' 年 ' + detailCalMonth + ' 月';
var wk = document.getElementById('detail-cal-weekdays');
if(!wk.children.length){
wk.innerHTML = ['日','一','二','三','四','五','六'].map(function(w){ return '<div class="cal-week">' + w + '</div>'; }).join('');
}
var grid = document.getElementById('detail-cal-days');
grid.innerHTML = '';
var firstDow = new Date(detailCalYear, detailCalMonth - 1, 1).getDay();
var daysInMonth = new Date(detailCalYear, detailCalMonth, 0).getDate();
for(var i = 0; i < firstDow; i++){
grid.appendChild(document.createElement('div'));
}
for(var d = 1; d <= daysInMonth; d++){
var key = dateKey(detailCalYear, detailCalMonth, d);
var dow = new Date(detailCalYear, detailCalMonth - 1, d).getDay();
var cell = document.createElement('div');
var hName = holidayData[key] || '';
var dayLabel = '<div class="cal-cell__day">' + d + (hName ? '<span class="cal-name">' + hName + '</span>' : '') + '</div>';
if(isRestDayByState(key, dow, detailState)){
cell.className = 'cal-cell rest';
cell.innerHTML = dayLabel + '<div class="cal-cell__rest">休</div>';
} else {
cell.className = 'cal-cell';
var v = detailState.daycounts[key];
cell.innerHTML = dayLabel + (v != null && v !== ''
? '<div class="cal-cell__count">' + v + ' 人</div>'
: '<div class="cal-cell__count def">' + detailState.capacity + ' 人</div>');
}
grid.appendChild(cell);
}
}
/* 保存编辑 */
function saveEdit(){
if(!editingTr){ return; }
var value = document.getElementById('search-value').value;
if(!value || !hospitalData[value]){ alert('请选择医院'); return; }
var capacity = document.getElementById('form-capacity').value.trim();
if(!capacity || Number(capacity) <= 0){ alert('请输入正确的每日最多承检人数'); return; }
var start = document.getElementById('form-start').value;
var end = document.getElementById('form-end').value;
if(!start){ alert('请选择承检开始日期'); return; }
if(!end){ alert('请选择承检结束日期'); return; }
if(start > end){ alert('承检结束日期不能早于开始日期'); return; }
var exceptions = [];
document.querySelectorAll('#exception-list .dynamic-row').forEach(function(row){
var d = row.querySelector('.row-date').value;
var c = row.querySelector('.row-count').value.trim();
if(d && c) exceptions.push({ date: d, count: c });
});
var noDates = [];
document.querySelectorAll('#nodate-list .dynamic-row').forEach(function(row){
var d = row.querySelector('.row-date').value;
if(d) noDates.push(d);
});
var valid = document.getElementById('switch-valid').classList.contains('on');
var name = hospitalData[value];
var cells = editingTr.cells;
cells[1].textContent = name;
cells[2].textContent = capacity;
cells[3].textContent = start;
cells[4].textContent = end;
cells[5].innerHTML = valid ? '<span class="tag tag-green">有效</span>' : '<span class="tag tag-red">无效</span>';
editingTr.dataset.exceptions = JSON.stringify(exceptions);
editingTr.dataset.nodates = JSON.stringify(noDates);
closeDrawer();
}
/* 详情 */
function openDetail(el){
var tr = el.closest('tr');
var cells = tr.cells;
document.getElementById('detail-hospital').textContent = cells[1].textContent.trim();
document.getElementById('detail-capacity').textContent = cells[2].textContent.trim();
document.getElementById('detail-capacity').textContent = cells[2].textContent.trim() + ' 人/日';
document.getElementById('detail-start').textContent = cells[3].textContent.trim();
document.getElementById('detail-end').textContent = cells[4].textContent.trim();
var valid = cells[5].textContent.trim() === '有效';
@@ -646,34 +777,33 @@ function openDetail(el){
? '<span class="tag tag-green">有效</span>'
: '<span class="tag tag-red">无效</span>';
var exceptions = [];
try { exceptions = JSON.parse(tr.dataset.exceptions || '[]'); } catch(e){}
var exWrap = document.getElementById('detail-exceptions');
if(exceptions.length === 0){
exWrap.innerHTML = '<div class="detail-empty">暂无例外人数设定</div>';
} else {
exWrap.innerHTML = exceptions.map(function(ex){
return '<div class="detail-list-row"><span>' + ex.date + '</span><span class="detail-count">' + ex.count + ' 人</span></div>';
}).join('');
}
var state = readRowState(tr);
var skipTags = [];
if(state.skipHoliday) skipTags.push('<span class="tag tag-orange">跳过节假日</span>');
if(state.skipSat) skipTags.push('<span class="tag tag-orange">跳过周六</span>');
if(state.skipSun) skipTags.push('<span class="tag tag-orange">跳过周日</span>');
document.getElementById('detail-skips').innerHTML = skipTags.length ? skipTags.join(' ') : '<span class="tag tag-gray">不跳过</span>';
var noDates = [];
try { noDates = JSON.parse(tr.dataset.nodates || '[]'); } catch(e){}
var ndWrap = document.getElementById('detail-nodates');
if(noDates.length === 0){
ndWrap.innerHTML = '<div class="detail-empty">暂无不参检日期</div>';
} else {
ndWrap.innerHTML = noDates.map(function(d){
return '<div class="detail-list-row"><span>' + d + '</span></div>';
}).join('');
detailState = {
daycounts: state.daycounts,
skipHoliday: state.skipHoliday,
skipSat: state.skipSat,
skipSun: state.skipSun,
capacity: cells[2].textContent.trim(),
start: cells[3].textContent.trim(),
end: cells[4].textContent.trim()
};
var start = detailState.start;
if(start){
detailCalYear = parseInt(start.slice(0,4), 10);
detailCalMonth = parseInt(start.slice(5,7), 10);
}
renderDetailCalendar();
document.getElementById('detail-drawer').classList.add('open');
document.getElementById('detail-overlay').classList.add('open');
}
function closeDetail(){
document.getElementById('detail-drawer').classList.remove('open');
document.getElementById('detail-overlay').classList.remove('open');
}
</script>
+397 -266
View File
@@ -72,29 +72,31 @@
.tag-green{background:#F6FFED;color:var(--success);}
.tag-orange{background:#FFF7E6;color:var(--warning);}
.tag-red{background:#FFF1F0;color:var(--danger);}
.tag-gray{background:#F5F5F5;color:var(--text-secondary);}
.link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;}
.pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);}
.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;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
/* 抽屉弹窗 */
.drawer-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0);z-index:999;pointer-events:none;transition:background .3s;}
.drawer-overlay.open{background:rgba(0,0,0,0.45);pointer-events:auto;}
.drawer{position:fixed;top:0;right:-480px;bottom:0;width:480px;background:#fff;box-shadow:-2px 0 8px rgba(0,0,0,0.15);z-index:1000;transition:right .3s;display:flex;flex-direction:column;}
.drawer.open{right:0;}
.drawer__header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid var(--border);flex-shrink:0;}
.drawer__title{font-size:var(--font-lg);font-weight:600;}
.drawer__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.drawer__close:hover{background:#F5F5F5;}
.drawer__body{flex:1;overflow-y:auto;padding:24px;}
.drawer__footer{display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--border);flex-shrink:0;}
/* 中间弹窗 */
.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:1001;display:none;align-items:center;justify-content:center;}
.modal-overlay.open{display:flex;}
.modal{width:860px;max-width:calc(100vw - 48px);max-height:calc(100vh - 80px);background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-md);display:flex;flex-direction:column;}
.modal__header{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--border);flex-shrink:0;}
.modal__title{font-size:var(--font-lg);font-weight:600;}
.modal__close{width:32px;height:32px;border-radius:50%;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:18px;}
.modal__close:hover{background:#F5F5F5;}
.modal__body{flex:1;overflow-y:auto;padding:20px 24px;}
.modal__footer{display:flex;justify-content:flex-end;gap:12px;padding:14px 24px;border-top:1px solid var(--border);flex-shrink:0;}
/* 表单 */
.form-item{margin-bottom:20px;}
.form-item{margin-bottom:16px;}
.form-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:8px;display:flex;align-items:center;gap:4px;font-weight:500;}
.form-label .required{color:var(--danger);}
.form-input{width:100%;height:40px;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{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::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.6;}
.form-input:disabled{background:#F5F5F5;color:var(--text-secondary);cursor:not-allowed;}
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 20px;}
/* 开关 */
.switch-row{display:flex;align-items:center;gap:12px;}
.switch{width:40px;height:22px;border-radius:11px;background:#E8E8E8;cursor:pointer;position:relative;transition:.2s;flex-shrink:0;}
@@ -102,7 +104,8 @@
.switch::after{content:'';position:absolute;width:18px;height:18px;border-radius:50%;background:#fff;top:2px;left:2px;transition:.2s;box-shadow:0 1px 3px rgba(0,0,0,0.2);}
.switch.on::after{left:20px;}
.switch-label{font-size:var(--font-sm);color:var(--text-primary);}
/* 可搜索下拉 */
.switch-group{display:flex;align-items:center;gap:28px;}
/* 可搜索下拉(筛选栏) */
.search-select{position:relative;}
.search-select__input{width:100%;height:40px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 32px 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 12px center;}
.search-select__input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(24,144,255,0.2);}
@@ -115,16 +118,31 @@
.filter-bar .search-select{width:200px;}
.filter-bar .search-select__input{height:36px;}
.filter-bar .search-select__dropdown{top:40px;}
/* 分区标题与动态行 */
.form-section{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:24px 0 4px;padding-top:16px;border-top:1px solid var(--border);}
.form-tip{font-size:var(--font-xs);color:var(--text-placeholder);margin-bottom:12px;line-height:1.5;}
.dynamic-list{margin-bottom:4px;}
.dynamic-row{display:flex;align-items:center;gap:8px;margin-bottom:8px;}
.dynamic-row .form-input{flex:1;}
.dynamic-row .row-del{width:32px;height:32px;border-radius:var(--radius-sm);border:1px solid var(--border);background:#fff;color:var(--danger);cursor:pointer;flex-shrink:0;font-size:16px;line-height:1;}
.dynamic-row .row-del:hover{background:#fff1f0;border-color:var(--danger);}
.add-row-btn{display:inline-flex;align-items:center;gap:4px;font-size:var(--font-sm);color:var(--primary);cursor:pointer;border:1px dashed var(--primary);border-radius:var(--radius-sm);padding:5px 12px;background:var(--primary-light);user-select:none;}
.add-row-btn:hover{background:#bae7ff;}
/* 分区标题 */
.form-section{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);margin:20px 0 8px;padding-top:14px;border-top:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;}
.form-tip{font-size:var(--font-xs);color:var(--text-placeholder);margin-bottom:10px;line-height:1.5;}
/* 月视图日历 */
.cal-nav{display:flex;align-items:center;gap:8px;}
.cal-nav__btn{width:26px;height:26px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);color:var(--text-secondary);display:inline-flex;align-items:center;justify-content:center;}
.cal-nav__btn:hover{color:var(--primary);border-color:var(--primary);}
.cal-nav__label{font-size:var(--font-sm);font-weight:600;min-width:88px;text-align:center;}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:6px;}
.cal-week{font-size:var(--font-xs);color:var(--text-secondary);text-align:center;padding:2px 0;}
.cal-cell{min-height:58px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:4px 5px;background:#fff;}
.cal-cell__day{font-size:var(--font-xs);color:var(--text-primary);margin-bottom:4px;}
.cal-cell__day .cal-name{color:var(--danger);margin-left:2px;}
.cal-cell__input{width:100%;height:24px;border:1px solid var(--border);border-radius:var(--radius-sm);font-size:var(--font-xs);padding:0 4px;outline:none;color:var(--text-primary);}
.cal-cell__input:focus{border-color:var(--primary);}
.cal-cell__input::placeholder{color:#C0C4CC;}
.cal-cell.rest{background:#F5F5F5;border-color:#EBEBEB;}
.cal-cell.rest .cal-cell__day{color:var(--text-placeholder);}
.cal-cell.rest .cal-name{color:var(--text-placeholder);}
.cal-cell__rest{font-size:var(--font-xs);color:var(--text-placeholder);text-align:center;padding:3px 0;}
.cal-legend{display:flex;align-items:center;gap:16px;margin-top:10px;font-size:var(--font-xs);color:var(--text-secondary);}
.cal-legend__item{display:inline-flex;align-items:center;gap:5px;}
.cal-legend__box{width:12px;height:12px;border-radius:2px;border:1px solid var(--border);display:inline-block;}
.cal-legend__box.rest{background:#F5F5F5;border-color:#EBEBEB;}
.cal-legend__box.edit{background:#fff;}
/* 详情展示 */
.detail-item{margin-bottom:16px;}
.detail-label{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:6px;}
@@ -132,6 +150,10 @@
.detail-list-row{display:flex;justify-content:space-between;align-items:center;padding:10px 12px;background:#F8FBFF;border-radius:var(--radius-sm);margin-bottom:6px;font-size:var(--font-sm);}
.detail-list-row .detail-count{color:var(--primary);font-weight:600;}
.detail-empty{font-size:var(--font-sm);color:var(--text-placeholder);padding:4px 0;}
.detail-summary{display:grid;grid-template-columns:repeat(2,1fr);gap:12px 24px;margin-bottom:4px;}
.detail-summary .detail-item{margin-bottom:0;}
.cal-cell__count{font-size:var(--font-xs);color:var(--primary);font-weight:600;text-align:center;background:var(--primary-light);border-radius:var(--radius-sm);padding:3px 0;}
.cal-cell__count.def{color:var(--text-secondary);font-weight:400;background:#F8FBFF;}
.tab-pane{display:none;}
.tab-pane.active{display:block;}
</style>
@@ -260,12 +282,12 @@
<table>
<thead>
<tr>
<th>序号</th><th>医院名称</th><th>每日最承检人数</th><th>承检开始日期</th><th>承检结束日期</th><th>有效标志</th><th>操作</th>
<th>序号</th><th>医院名称</th><th>每日最承检人数</th><th>承检开始日期</th><th>承检结束日期</th><th>有效标志</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr data-exceptions='[{"date":"2026-05-01","count":"100"},{"date":"2026-05-02","count":"80"}]' data-nodates='["2026-06-19","2026-06-20"]'><td>1</td><td>庆阳医院</td><td>200</td><td>2026-03-01</td><td>2026-10-31</td><td><span class="tag tag-green">有效</span></td><td><span class="link" onclick="openDetail(this)">详情</span> <span class="link" style="margin-left:8px;" onclick="openEdit(this)">编辑</span></td></tr>
<tr data-exceptions='[{"date":"2026-04-30","count":"120"}]' data-nodates='[]'><td>2</td><td>兴隆园医院</td><td>150</td><td>2026-03-01</td><td>2026-10-31</td><td><span class="tag tag-green">有效</span></td><td><span class="link" onclick="openDetail(this)">详情</span> <span class="link" style="margin-left:8px;" onclick="openEdit(this)">编辑</span></td></tr>
<tr data-daycounts='{"2026-05-01":"100","2026-05-02":"80","2026-09-05":"220"}' data-skip-holiday="1" data-skip-sat="0" data-skip-sun="1"><td>1</td><td>庆阳医院</td><td>200</td><td>2026-03-01</td><td>2026-10-31</td><td><span class="tag tag-green">有效</span></td><td><span class="link" onclick="openDetail(this)">详情</span> <span class="link" style="margin-left:8px;" onclick="openEdit(this)">编辑</span></td></tr>
<tr data-daycounts='{"2026-04-30":"120"}' data-skip-holiday="0" data-skip-sat="0" data-skip-sun="0"><td>2</td><td>兴隆园医院</td><td>150</td><td>2026-03-01</td><td>2026-10-31</td><td><span class="tag tag-green">有效</span></td><td><span class="link" onclick="openDetail(this)">详情</span> <span class="link" style="margin-left:8px;" onclick="openEdit(this)">编辑</span></td></tr>
</tbody>
</table>
</div>
@@ -279,95 +301,136 @@
</div>
</main>
<!-- 编辑医院承检范围抽屉 -->
<div class="drawer-overlay" id="drawer-overlay" onclick="closeDrawer()"></div>
<div class="drawer" id="scope-drawer">
<div class="drawer__header">
<div class="drawer__title">编辑医院承检范围</div>
<button class="drawer__close" onclick="closeDrawer()"></button>
</div>
<div class="drawer__body">
<div class="form-item">
<div class="form-label"><span class="required">*</span> 医院</div>
<div class="search-select" id="search-select">
<input type="text" class="search-select__input" id="search-input" placeholder="请输入医院名称搜索" autocomplete="off">
<input type="hidden" id="search-value">
<div class="search-select__dropdown" id="search-dropdown"></div>
<!-- 编辑医院承检范围中间弹窗 -->
<div class="modal-overlay" id="scope-modal-overlay">
<div class="modal" id="scope-modal">
<div class="modal__header">
<div class="modal__title">编辑医院承检范围</div>
<button class="modal__close" onclick="closeModal()"></button>
</div>
<div class="modal__body">
<div class="form-item">
<div class="form-label"><span class="required">*</span> 医院</div>
<input class="form-input" id="form-hospital" type="text" disabled>
</div>
<div class="form-grid">
<div class="form-item">
<div class="form-label"><span class="required">*</span> 每日最大承检人数</div>
<input class="form-input" id="form-capacity" type="number" min="1" placeholder="未单独设定的日期按此人数承检">
</div>
<div class="form-item">
<div class="form-label">有效标志</div>
<div class="switch-row" style="height:36px;">
<div class="switch on" id="switch-valid" onclick="toggleSwitch(this,'switch-valid-label','有效','无效')"></div>
<span class="switch-label" id="switch-valid-label">有效</span>
</div>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 承检开始日期</div>
<input class="form-input" id="form-start" type="date">
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 承检结束日期</div>
<input class="form-input" id="form-end" type="date">
</div>
</div>
<div class="form-item">
<div class="form-label">休息日设置</div>
<div class="switch-group">
<div class="switch-row">
<div class="switch" id="switch-skip-holiday" onclick="toggleSkipSwitch(this)"></div>
<span class="switch-label">跳过节假日</span>
</div>
<div class="switch-row">
<div class="switch" id="switch-skip-sat" onclick="toggleSkipSwitch(this)"></div>
<span class="switch-label">跳过周六</span>
</div>
<div class="switch-row">
<div class="switch" id="switch-skip-sun" onclick="toggleSkipSwitch(this)"></div>
<span class="switch-label">跳过周日</span>
</div>
</div>
</div>
<!-- 按月设定承检人数 -->
<div class="form-section">
<span>按月设定承检人数</span>
<span class="cal-nav">
<button class="cal-nav__btn" onclick="calPrevMonth()"></button>
<span class="cal-nav__label" id="cal-label"></span>
<button class="cal-nav__btn" onclick="calNextMonth()"></button>
</span>
</div>
<div class="form-tip">每个日期下方可自由设定当日承检人数,默认按"每日最大承检人数"执行;被跳过的节假日与周六日自动置灰、不可设定。</div>
<div class="cal-grid" id="cal-weekdays"></div>
<div class="cal-grid" id="cal-days" style="margin-top:6px;"></div>
<div class="cal-legend">
<span class="cal-legend__item"><span class="cal-legend__box edit"></span>可设定日期</span>
<span class="cal-legend__item"><span class="cal-legend__box rest"></span>置灰休息日(节假日 / 周六 / 周日 / 超出承检期)</span>
</div>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 每日最多承检人数</div>
<input class="form-input" id="form-capacity" type="number" min="1" placeholder="请输入人数">
<div class="modal__footer">
<button class="btn btn-default" onclick="closeModal()">取消</button>
<button class="btn btn-primary" onclick="saveEdit()">确认保存</button>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 承检开始日期</div>
<input class="form-input" id="form-start" type="date">
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 承检结束日期</div>
<input class="form-input" id="form-end" type="date">
</div>
<div class="form-item">
<div class="form-label">有效标志</div>
<div class="switch-row">
<div class="switch on" id="switch-valid" onclick="toggleValidSwitch(this)"></div>
<span class="switch-label" id="switch-valid-label">有效</span>
</div>
</div>
<!-- 例外人数设定 -->
<div class="form-section">例外人数设定</div>
<div class="form-tip">针对特定日期单独设置承检人数(覆盖"每日最多承检人数"),例如节假日或加号日期。</div>
<div class="dynamic-list" id="exception-list"></div>
<div class="add-row-btn" onclick="addExceptionRow()"> 添加例外</div>
<!-- 不参检日期 -->
<div class="form-section">不参检日期</div>
<div class="form-tip">设置该医院不承接体检的日期,系统将自动跳过这些日期。</div>
<div class="dynamic-list" id="nodate-list"></div>
<div class="add-row-btn" onclick="addNoDateRow()"> 添加日期</div>
</div>
<div class="drawer__footer">
<button class="btn btn-default" onclick="closeDrawer()">取消</button>
<button class="btn btn-primary" onclick="saveEdit()">确认保存</button>
</div>
</div>
<!-- 医院承检范围详情抽屉 -->
<div class="drawer-overlay" id="detail-overlay" onclick="closeDetail()"></div>
<div class="drawer" id="detail-drawer">
<div class="drawer__header">
<div class="drawer__title">医院承检范围详情</div>
<button class="drawer__close" onclick="closeDetail()"></button>
</div>
<div class="drawer__body">
<div class="detail-item">
<div class="detail-label">医院</div>
<div class="detail-value" id="detail-hospital"></div>
<!-- 医院承检范围详情中间弹窗 -->
<div class="modal-overlay" id="detail-overlay">
<div class="modal" id="detail-modal">
<div class="modal__header">
<div class="modal__title">医院承检范围详情</div>
<button class="modal__close" onclick="closeDetail()"></button>
</div>
<div class="detail-item">
<div class="detail-label">每日最多承检人数</div>
<div class="detail-value" id="detail-capacity"></div>
<div class="modal__body">
<div class="detail-summary">
<div class="detail-item">
<div class="detail-label">医院</div>
<div class="detail-value" id="detail-hospital"></div>
</div>
<div class="detail-item">
<div class="detail-label">每日最大承检人数</div>
<div class="detail-value" id="detail-capacity"></div>
</div>
<div class="detail-item">
<div class="detail-label">承检开始日期</div>
<div class="detail-value" id="detail-start"></div>
</div>
<div class="detail-item">
<div class="detail-label">承检结束日期</div>
<div class="detail-value" id="detail-end"></div>
</div>
<div class="detail-item">
<div class="detail-label">有效标志</div>
<div class="detail-value" id="detail-valid"></div>
</div>
<div class="detail-item">
<div class="detail-label">休息日设置</div>
<div class="detail-value" id="detail-skips"></div>
</div>
</div>
<!-- 按月查看承检人数(只读) -->
<div class="form-section">
<span>按月查看承检人数</span>
<span class="cal-nav">
<button class="cal-nav__btn" onclick="detailCalPrevMonth()"></button>
<span class="cal-nav__label" id="detail-cal-label"></span>
<button class="cal-nav__btn" onclick="detailCalNextMonth()"></button>
</span>
</div>
<div class="form-tip">标"休"的日期为承检休息日,不开放预约。</div>
<div class="cal-grid" id="detail-cal-weekdays"></div>
<div class="cal-grid" id="detail-cal-days" style="margin-top:6px;"></div>
<div class="cal-legend">
<span class="cal-legend__item"><span class="cal-legend__box edit"></span>可承检日期</span>
<span class="cal-legend__item"><span class="cal-legend__box rest"></span>休息日(节假日 / 周六 / 周日 / 超出承检期)</span>
</div>
</div>
<div class="detail-item">
<div class="detail-label">承检开始日期</div>
<div class="detail-value" id="detail-start"></div>
<div class="modal__footer">
<button class="btn btn-primary" onclick="closeDetail()">关闭</button>
</div>
<div class="detail-item">
<div class="detail-label">承检结束日期</div>
<div class="detail-value" id="detail-end"></div>
</div>
<div class="detail-item">
<div class="detail-label">有效标志</div>
<div class="detail-value" id="detail-valid"></div>
</div>
<div class="form-section">例外人数设定</div>
<div id="detail-exceptions"></div>
<div class="form-section">不参检日期</div>
<div id="detail-nodates"></div>
</div>
<div class="drawer__footer">
<button class="btn btn-primary" onclick="closeDetail()">关闭</button>
</div>
</div>
@@ -384,7 +447,7 @@ function toggleSubgroup(header){
while(sub){ sub.classList.add('open'); sub=sub.parentElement.closest('.sidebar-subgroup'); }
})();
/* ===== 编辑医院承检范围抽屉 ===== */
/* ===== 数据 ===== */
var hospitalData = {
'h1': '庆阳医院',
'h2': '兴隆园医院',
@@ -396,21 +459,48 @@ var hospitalData = {
'h8': '长安胃肠镜医院'
};
/* 2026 年法定节假日(休假日,原型内置) */
var holidayData = {
'2026-01-01':'元旦','2026-01-02':'元旦','2026-01-03':'元旦',
'2026-02-15':'春节','2026-02-16':'春节','2026-02-17':'春节','2026-02-18':'春节','2026-02-19':'春节','2026-02-20':'春节','2026-02-21':'春节','2026-02-22':'春节',
'2026-04-04':'清明节','2026-04-05':'清明节','2026-04-06':'清明节',
'2026-05-01':'劳动节','2026-05-02':'劳动节','2026-05-03':'劳动节','2026-05-04':'劳动节','2026-05-05':'劳动节',
'2026-06-19':'端午节','2026-06-20':'端午节','2026-06-21':'端午节',
'2026-09-25':'中秋节','2026-09-26':'中秋节','2026-09-27':'中秋节',
'2026-10-01':'国庆节','2026-10-02':'国庆节','2026-10-03':'国庆节','2026-10-04':'国庆节','2026-10-05':'国庆节','2026-10-06':'国庆节','2026-10-07':'国庆节'
};
/* 通用开关 */
function toggleSwitch(el, labelId, onText, offText){
el.classList.toggle('on');
document.getElementById(labelId).textContent = el.classList.contains('on') ? onText : offText;
}
/* ===== 编辑医院承检范围中间弹窗 ===== */
var editingTr = null;
var calYear = 2026, calMonth = 1; // calMonth: 1-12
var dayCounts = {}; // 弹窗内暂存的 { 'YYYY-MM-DD': '100' }
function pad2(n){ return n < 10 ? '0' + n : '' + n; }
function dateKey(y, m, d){ return y + '-' + pad2(m) + '-' + pad2(d); }
function readRowState(tr){
var counts = {};
try { counts = JSON.parse(tr.dataset.daycounts || '{}'); } catch(e){}
return {
daycounts: counts,
skipHoliday: tr.dataset.skipHoliday === '1',
skipSat: tr.dataset.skipSat === '1',
skipSun: tr.dataset.skipSun === '1'
};
}
function openEdit(btn){
var tr = btn.closest('tr');
editingTr = tr;
var cells = tr.cells;
var name = cells[1].textContent.trim();
var key = '';
for(var k in hospitalData){
if(hospitalData[k] === name){ key = k; break; }
}
document.getElementById('search-value').value = key;
document.getElementById('search-input').value = name;
document.getElementById('form-hospital').value = cells[1].textContent.trim();
document.getElementById('form-capacity').value = cells[2].textContent.trim();
document.getElementById('form-start').value = cells[3].textContent.trim();
document.getElementById('form-end').value = cells[4].textContent.trim();
@@ -420,83 +510,135 @@ function openEdit(btn){
sw.classList.toggle('on', valid);
document.getElementById('switch-valid-label').textContent = valid ? '有效' : '无效';
var exceptions = [];
try { exceptions = JSON.parse(tr.dataset.exceptions || '[]'); } catch(e){}
document.getElementById('exception-list').innerHTML = '';
if(exceptions.length === 0){ addExceptionRow(); }
else { exceptions.forEach(function(ex){ addExceptionRow(ex.date, ex.count); }); }
var state = readRowState(tr);
document.getElementById('switch-skip-holiday').classList.toggle('on', state.skipHoliday);
document.getElementById('switch-skip-sat').classList.toggle('on', state.skipSat);
document.getElementById('switch-skip-sun').classList.toggle('on', state.skipSun);
var noDates = [];
try { noDates = JSON.parse(tr.dataset.nodates || '[]'); } catch(e){}
document.getElementById('nodate-list').innerHTML = '';
if(noDates.length === 0){ addNoDateRow(); }
else { noDates.forEach(function(d){ addNoDateRow(d); }); }
document.getElementById('scope-drawer').classList.add('open');
document.getElementById('drawer-overlay').classList.add('open');
}
function closeDrawer(){
document.getElementById('scope-drawer').classList.remove('open');
document.getElementById('drawer-overlay').classList.remove('open');
}
/* 有效标志开关 */
function toggleValidSwitch(el){
el.classList.toggle('on');
document.getElementById('switch-valid-label').textContent = el.classList.contains('on') ? '有效' : '无效';
}
/* 可搜索下拉 */
(function(){
var input = document.getElementById('search-input');
var dropdown = document.getElementById('search-dropdown');
var hidden = document.getElementById('search-value');
function renderOptions(keyword){
dropdown.innerHTML = '';
var kw = keyword.trim().toLowerCase();
var has = false;
for(var key in hospitalData){
var name = hospitalData[key];
if(!kw || name.toLowerCase().indexOf(kw) !== -1){
has = true;
var opt = document.createElement('div');
opt.className = 'search-select__option';
if(hidden.value === key) opt.classList.add('active');
opt.textContent = name;
opt.dataset.value = key;
opt.onclick = function(){
hidden.value = key;
input.value = name;
dropdown.classList.remove('show');
};
dropdown.appendChild(opt);
}
}
if(!has){
var empty = document.createElement('div');
empty.className = 'search-select__empty';
empty.textContent = '无匹配医院';
dropdown.appendChild(empty);
}
dayCounts = state.daycounts;
var start = document.getElementById('form-start').value;
if(start){
calYear = parseInt(start.slice(0,4), 10);
calMonth = parseInt(start.slice(5,7), 10);
}
renderCalendar();
input.addEventListener('focus', function(){
renderOptions(this.value);
dropdown.classList.add('show');
});
input.addEventListener('input', function(){
hidden.value = '';
renderOptions(this.value);
dropdown.classList.add('show');
});
document.addEventListener('click', function(e){
if(!e.target.closest('#search-select')){
dropdown.classList.remove('show');
document.getElementById('scope-modal-overlay').classList.add('open');
}
function closeModal(){
document.getElementById('scope-modal-overlay').classList.remove('open');
}
function getSkipState(){
return {
skipHoliday: document.getElementById('switch-skip-holiday').classList.contains('on'),
skipSat: document.getElementById('switch-skip-sat').classList.contains('on'),
skipSun: document.getElementById('switch-skip-sun').classList.contains('on')
};
}
/* 切换跳过开关:先留存当前页人数输入,再重渲染日历(置灰状态随之变化) */
function toggleSkipSwitch(el){
commitCalendarInputs();
el.classList.toggle('on');
renderCalendar();
}
/* 日期是否置灰:承检期之外,或被开关命中的节假日 / 周六 / 周日 */
function isRestDay(key, dow){
var start = document.getElementById('form-start').value;
var end = document.getElementById('form-end').value;
if(start && key < start) return true;
if(end && key > end) return true;
var s = getSkipState();
if(s.skipSun && dow === 0) return true;
if(s.skipSat && dow === 6) return true;
if(s.skipHoliday && holidayData[key]) return true;
return false;
}
function calPrevMonth(){ commitCalendarInputs(); if(calMonth === 1){ calMonth = 12; calYear--; } else calMonth--; renderCalendar(); }
function calNextMonth(){ commitCalendarInputs(); if(calMonth === 12){ calMonth = 1; calYear++; } else calMonth++; renderCalendar(); }
function renderCalendar(){
document.getElementById('cal-label').textContent = calYear + ' 年 ' + calMonth + ' 月';
var wk = document.getElementById('cal-weekdays');
if(!wk.children.length){
wk.innerHTML = ['日','一','二','三','四','五','六'].map(function(w){ return '<div class="cal-week">' + w + '</div>'; }).join('');
}
var grid = document.getElementById('cal-days');
grid.innerHTML = '';
var firstDow = new Date(calYear, calMonth - 1, 1).getDay();
var daysInMonth = new Date(calYear, calMonth, 0).getDate();
for(var i = 0; i < firstDow; i++){
var blank = document.createElement('div');
grid.appendChild(blank);
}
for(var d = 1; d <= daysInMonth; d++){
var key = dateKey(calYear, calMonth, d);
var dow = new Date(calYear, calMonth - 1, d).getDay();
var cell = document.createElement('div');
var hName = holidayData[key] || '';
var dayLabel = '<div class="cal-cell__day">' + d + (hName ? '<span class="cal-name">' + hName + '</span>' : '') + '</div>';
if(isRestDay(key, dow)){
cell.className = 'cal-cell rest';
cell.innerHTML = dayLabel + '<div class="cal-cell__rest">休</div>';
} else {
cell.className = 'cal-cell';
cell.innerHTML = dayLabel + '<input type="number" min="0" class="cal-cell__input" data-key="' + key + '" placeholder="' + (document.getElementById('form-capacity').value.trim() || '人数') + '" value="' + (dayCounts[key] != null ? dayCounts[key] : '') + '">';
}
grid.appendChild(cell);
}
}
/* 把当前页输入写回 dayCounts */
function commitCalendarInputs(){
document.querySelectorAll('#cal-days .cal-cell__input').forEach(function(inp){
var v = inp.value.trim();
if(v) dayCounts[inp.dataset.key] = v;
else delete dayCounts[inp.dataset.key];
});
})();
}
/* 承检起止日期变化时重渲染(置灰范围随之变化) */
function bindDateReRender(){
['form-start','form-end','form-capacity'].forEach(function(id){
document.getElementById(id).addEventListener('change', function(){
commitCalendarInputs();
renderCalendar();
});
});
}
bindDateReRender();
/* 保存编辑 */
function saveEdit(){
if(!editingTr){ return; }
var name = document.getElementById('form-hospital').value.trim();
if(!name){ alert('未找到医院信息'); return; }
var capacity = document.getElementById('form-capacity').value.trim();
if(!capacity || Number(capacity) <= 0){ alert('请输入正确的每日最大承检人数'); return; }
var start = document.getElementById('form-start').value;
var end = document.getElementById('form-end').value;
if(!start){ alert('请选择承检开始日期'); return; }
if(!end){ alert('请选择承检结束日期'); return; }
if(start > end){ alert('承检结束日期不能早于开始日期'); return; }
commitCalendarInputs();
var s = getSkipState();
var valid = document.getElementById('switch-valid').classList.contains('on');
var cells = editingTr.cells;
cells[2].textContent = capacity;
cells[3].textContent = start;
cells[4].textContent = end;
cells[5].innerHTML = valid ? '<span class="tag tag-green">有效</span>' : '<span class="tag tag-red">无效</span>';
editingTr.dataset.daycounts = JSON.stringify(dayCounts);
editingTr.dataset.skipHoliday = s.skipHoliday ? '1' : '0';
editingTr.dataset.skipSat = s.skipSat ? '1' : '0';
editingTr.dataset.skipSun = s.skipSun ? '1' : '0';
closeModal();
}
/* 筛选栏可搜索下拉 */
(function(){
@@ -573,71 +715,61 @@ function resetFilter(){
if(activePane) activePane.querySelectorAll('tbody tr').forEach(function(tr){ tr.style.display = ''; });
}
/* 例外人数动态行 */
function addExceptionRow(date, count){
var list = document.getElementById('exception-list');
var row = document.createElement('div');
row.className = 'dynamic-row';
row.innerHTML = '<input type="date" class="form-input row-date" value="' + (date || '') + '">'
+ '<input type="number" class="form-input row-count" min="1" placeholder="例外人数" value="' + (count || '') + '" style="max-width:110px;">'
+ '<button class="row-del" onclick="this.parentElement.remove()">×</button>';
list.appendChild(row);
/* 详情(只读月历) */
var detailState = null; // 当前查看行的承检配置快照
var detailCalYear = 2026, detailCalMonth = 1;
function isRestDayByState(key, dow, s){
if(s.start && key < s.start) return true;
if(s.end && key > s.end) return true;
if(s.skipSun && dow === 0) return true;
if(s.skipSat && dow === 6) return true;
if(s.skipHoliday && holidayData[key]) return true;
return false;
}
/* 不参检日期动态行 */
function addNoDateRow(date){
var list = document.getElementById('nodate-list');
var row = document.createElement('div');
row.className = 'dynamic-row';
row.innerHTML = '<input type="date" class="form-input row-date" value="' + (date || '') + '" placeholder="选择日期">'
+ '<button class="row-del" onclick="this.parentElement.remove()">×</button>';
list.appendChild(row);
function detailCalPrevMonth(){ if(detailCalMonth === 1){ detailCalMonth = 12; detailCalYear--; } else detailCalMonth--; renderDetailCalendar(); }
function detailCalNextMonth(){ if(detailCalMonth === 12){ detailCalMonth = 1; detailCalYear++; } else detailCalMonth++; renderDetailCalendar(); }
function renderDetailCalendar(){
if(!detailState) return;
document.getElementById('detail-cal-label').textContent = detailCalYear + ' 年 ' + detailCalMonth + ' 月';
var wk = document.getElementById('detail-cal-weekdays');
if(!wk.children.length){
wk.innerHTML = ['日','一','二','三','四','五','六'].map(function(w){ return '<div class="cal-week">' + w + '</div>'; }).join('');
}
var grid = document.getElementById('detail-cal-days');
grid.innerHTML = '';
var firstDow = new Date(detailCalYear, detailCalMonth - 1, 1).getDay();
var daysInMonth = new Date(detailCalYear, detailCalMonth, 0).getDate();
for(var i = 0; i < firstDow; i++){
grid.appendChild(document.createElement('div'));
}
for(var d = 1; d <= daysInMonth; d++){
var key = dateKey(detailCalYear, detailCalMonth, d);
var dow = new Date(detailCalYear, detailCalMonth - 1, d).getDay();
var cell = document.createElement('div');
var hName = holidayData[key] || '';
var dayLabel = '<div class="cal-cell__day">' + d + (hName ? '<span class="cal-name">' + hName + '</span>' : '') + '</div>';
if(isRestDayByState(key, dow, detailState)){
cell.className = 'cal-cell rest';
cell.innerHTML = dayLabel + '<div class="cal-cell__rest">休</div>';
} else {
cell.className = 'cal-cell';
var v = detailState.daycounts[key];
cell.innerHTML = dayLabel + (v != null && v !== ''
? '<div class="cal-cell__count">' + v + ' 人</div>'
: '<div class="cal-cell__count def">' + detailState.capacity + ' 人</div>');
}
grid.appendChild(cell);
}
}
/* 保存编辑 */
function saveEdit(){
if(!editingTr){ return; }
var value = document.getElementById('search-value').value;
if(!value || !hospitalData[value]){ alert('请选择医院'); return; }
var capacity = document.getElementById('form-capacity').value.trim();
if(!capacity || Number(capacity) <= 0){ alert('请输入正确的每日最多承检人数'); return; }
var start = document.getElementById('form-start').value;
var end = document.getElementById('form-end').value;
if(!start){ alert('请选择承检开始日期'); return; }
if(!end){ alert('请选择承检结束日期'); return; }
if(start > end){ alert('承检结束日期不能早于开始日期'); return; }
var exceptions = [];
document.querySelectorAll('#exception-list .dynamic-row').forEach(function(row){
var d = row.querySelector('.row-date').value;
var c = row.querySelector('.row-count').value.trim();
if(d && c) exceptions.push({ date: d, count: c });
});
var noDates = [];
document.querySelectorAll('#nodate-list .dynamic-row').forEach(function(row){
var d = row.querySelector('.row-date').value;
if(d) noDates.push(d);
});
var valid = document.getElementById('switch-valid').classList.contains('on');
var name = hospitalData[value];
var cells = editingTr.cells;
cells[1].textContent = name;
cells[2].textContent = capacity;
cells[3].textContent = start;
cells[4].textContent = end;
cells[5].innerHTML = valid ? '<span class="tag tag-green">有效</span>' : '<span class="tag tag-red">无效</span>';
editingTr.dataset.exceptions = JSON.stringify(exceptions);
editingTr.dataset.nodates = JSON.stringify(noDates);
closeDrawer();
}
/* 详情 */
function openDetail(el){
var tr = el.closest('tr');
var cells = tr.cells;
document.getElementById('detail-hospital').textContent = cells[1].textContent.trim();
document.getElementById('detail-capacity').textContent = cells[2].textContent.trim();
document.getElementById('detail-capacity').textContent = cells[2].textContent.trim() + ' 人/日';
document.getElementById('detail-start').textContent = cells[3].textContent.trim();
document.getElementById('detail-end').textContent = cells[4].textContent.trim();
var valid = cells[5].textContent.trim() === '有效';
@@ -645,34 +777,33 @@ function openDetail(el){
? '<span class="tag tag-green">有效</span>'
: '<span class="tag tag-red">无效</span>';
var exceptions = [];
try { exceptions = JSON.parse(tr.dataset.exceptions || '[]'); } catch(e){}
var exWrap = document.getElementById('detail-exceptions');
if(exceptions.length === 0){
exWrap.innerHTML = '<div class="detail-empty">暂无例外人数设定</div>';
} else {
exWrap.innerHTML = exceptions.map(function(ex){
return '<div class="detail-list-row"><span>' + ex.date + '</span><span class="detail-count">' + ex.count + ' 人</span></div>';
}).join('');
}
var state = readRowState(tr);
var skipTags = [];
if(state.skipHoliday) skipTags.push('<span class="tag tag-orange">跳过节假日</span>');
if(state.skipSat) skipTags.push('<span class="tag tag-orange">跳过周六</span>');
if(state.skipSun) skipTags.push('<span class="tag tag-orange">跳过周日</span>');
document.getElementById('detail-skips').innerHTML = skipTags.length ? skipTags.join(' ') : '<span class="tag tag-gray">不跳过</span>';
var noDates = [];
try { noDates = JSON.parse(tr.dataset.nodates || '[]'); } catch(e){}
var ndWrap = document.getElementById('detail-nodates');
if(noDates.length === 0){
ndWrap.innerHTML = '<div class="detail-empty">暂无不参检日期</div>';
} else {
ndWrap.innerHTML = noDates.map(function(d){
return '<div class="detail-list-row"><span>' + d + '</span></div>';
}).join('');
detailState = {
daycounts: state.daycounts,
skipHoliday: state.skipHoliday,
skipSat: state.skipSat,
skipSun: state.skipSun,
capacity: cells[2].textContent.trim(),
start: cells[3].textContent.trim(),
end: cells[4].textContent.trim()
};
var start = detailState.start;
if(start){
detailCalYear = parseInt(start.slice(0,4), 10);
detailCalMonth = parseInt(start.slice(5,7), 10);
}
renderDetailCalendar();
document.getElementById('detail-drawer').classList.add('open');
document.getElementById('detail-overlay').classList.add('open');
}
function closeDetail(){
document.getElementById('detail-drawer').classList.remove('open');
document.getElementById('detail-overlay').classList.remove('open');
}
</script>
@@ -289,6 +289,7 @@
<button class="btn btn-primary" onclick="openAddDrawer()">+ 新增</button>
<button class="btn btn-default">批量删除</button>
<button class="btn btn-default" onclick="openMutualDrawer()">互斥项目配置</button>
<button class="btn btn-default" onclick="openRelDrawer()">关联项目配置</button>
</div>
<div class="table-card">
<div class="table-card__header">
@@ -298,13 +299,13 @@
<table>
<thead>
<tr>
<th>序号</th><th>项目名称</th><th>项目编号</th><th>检查分类</th><th>项目类别</th><th>项目图片</th><th>默认费用(元)</th><th>项目音频</th><th>项目视频</th><th>操作</th>
<th>序号</th><th>项目名称</th><th>项目编号</th><th>检查分类</th><th>项目类别</th><th>项目图片</th><th>默认费用(元)</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>经颅多普勒</td><td>TCD-001</td><td>常规检查</td><td>功能检查项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>260.00</td><td><span class="media-icon media-icon--empty" title="暂无音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--empty" title="暂无视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>2</td><td>腹部彩超</td><td>BUS-002</td><td>常规检查</td><td>影像检查项目</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>180.00</td><td><span class="media-icon media-icon--active" title="播放音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--active" title="播放视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>3</td><td>血常规</td><td>BLD-003</td><td>常规检查</td><td>检验项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>35.00</td><td><span class="media-icon media-icon--empty" title="暂无音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--active" title="播放视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>1</td><td>经颅多普勒</td><td>TCD-001</td><td>常规检查</td><td>功能检查项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>260.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>2</td><td>腹部彩超</td><td>BUS-002</td><td>常规检查</td><td>影像检查项目</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>180.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>3</td><td>血常规</td><td>BLD-003</td><td>常规检查</td><td>检验项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>35.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
</tbody>
</table>
</div>
@@ -347,6 +348,7 @@
<button class="btn btn-primary" onclick="openAddDrawer()">+ 新增</button>
<button class="btn btn-default">批量删除</button>
<button class="btn btn-default" onclick="openMutualDrawer()">互斥项目配置</button>
<button class="btn btn-default" onclick="openRelDrawer()">关联项目配置</button>
</div>
<div class="table-card">
<div class="table-card__header">
@@ -356,13 +358,13 @@
<table>
<thead>
<tr>
<th>序号</th><th>项目名称</th><th>项目编号</th><th>检查分类</th><th>项目类别</th><th>项目图片</th><th>默认费用(元)</th><th>项目音频</th><th>项目视频</th><th>操作</th>
<th>序号</th><th>项目名称</th><th>项目编号</th><th>检查分类</th><th>项目类别</th><th>项目图片</th><th>默认费用(元)</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>经颅多普勒</td><td>TCD-001</td><td>常规检查</td><td>功能检查项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>260.00</td><td><span class="media-icon media-icon--empty" title="暂无音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--empty" title="暂无视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>2</td><td>腹部彩超</td><td>BUS-002</td><td>常规检查</td><td>影像检查项目</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>180.00</td><td><span class="media-icon media-icon--active" title="播放音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--active" title="播放视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>3</td><td>血常规</td><td>BLD-003</td><td>常规检查</td><td>检验项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>35.00</td><td><span class="media-icon media-icon--empty" title="暂无音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--active" title="播放视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>1</td><td>经颅多普勒</td><td>TCD-001</td><td>常规检查</td><td>功能检查项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>260.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>2</td><td>腹部彩超</td><td>BUS-002</td><td>常规检查</td><td>影像检查项目</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>180.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>3</td><td>血常规</td><td>BLD-003</td><td>常规检查</td><td>检验项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>35.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
</tbody>
</table>
</div>
@@ -405,6 +407,7 @@
<button class="btn btn-primary" onclick="openAddDrawer()">+ 新增</button>
<button class="btn btn-default">批量删除</button>
<button class="btn btn-default" onclick="openMutualDrawer()">互斥项目配置</button>
<button class="btn btn-default" onclick="openRelDrawer()">关联项目配置</button>
</div>
<div class="table-card">
<div class="table-card__header">
@@ -414,13 +417,13 @@
<table>
<thead>
<tr>
<th>序号</th><th>项目名称</th><th>项目编号</th><th>检查分类</th><th>项目类别</th><th>项目图片</th><th>默认费用(元)</th><th>项目音频</th><th>项目视频</th><th>操作</th>
<th>序号</th><th>项目名称</th><th>项目编号</th><th>检查分类</th><th>项目类别</th><th>项目图片</th><th>默认费用(元)</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>经颅多普勒</td><td>TCD-001</td><td>常规检查</td><td>功能检查项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>260.00</td><td><span class="media-icon media-icon--empty" title="暂无音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--empty" title="暂无视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>2</td><td>腹部彩超</td><td>BUS-002</td><td>常规检查</td><td>影像检查项目</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>180.00</td><td><span class="media-icon media-icon--active" title="播放音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--active" title="播放视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>3</td><td>血常规</td><td>BLD-003</td><td>常规检查</td><td>检验项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>35.00</td><td><span class="media-icon media-icon--empty" title="暂无音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--active" title="播放视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>1</td><td>经颅多普勒</td><td>TCD-001</td><td>常规检查</td><td>功能检查项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>260.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>2</td><td>腹部彩超</td><td>BUS-002</td><td>常规检查</td><td>影像检查项目</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>180.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>3</td><td>血常规</td><td>BLD-003</td><td>常规检查</td><td>检验项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>35.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
</tbody>
</table>
</div>
@@ -463,6 +466,7 @@
<button class="btn btn-primary" onclick="openAddDrawer()">+ 新增</button>
<button class="btn btn-default">批量删除</button>
<button class="btn btn-default" onclick="openMutualDrawer()">互斥项目配置</button>
<button class="btn btn-default" onclick="openRelDrawer()">关联项目配置</button>
</div>
<div class="table-card">
<div class="table-card__header">
@@ -472,13 +476,13 @@
<table>
<thead>
<tr>
<th>序号</th><th>项目名称</th><th>项目编号</th><th>检查分类</th><th>项目类别</th><th>项目图片</th><th>默认费用(元)</th><th>项目音频</th><th>项目视频</th><th>操作</th>
<th>序号</th><th>项目名称</th><th>项目编号</th><th>检查分类</th><th>项目类别</th><th>项目图片</th><th>默认费用(元)</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>经颅多普勒</td><td>TCD-001</td><td>常规检查</td><td>功能检查项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>260.00</td><td><span class="media-icon media-icon--empty" title="暂无音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--empty" title="暂无视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>2</td><td>腹部彩超</td><td>BUS-002</td><td>常规检查</td><td>影像检查项目</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>180.00</td><td><span class="media-icon media-icon--active" title="播放音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--active" title="播放视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>3</td><td>血常规</td><td>BLD-003</td><td>常规检查</td><td>检验项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>35.00</td><td><span class="media-icon media-icon--empty" title="暂无音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--active" title="播放视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>1</td><td>经颅多普勒</td><td>TCD-001</td><td>常规检查</td><td>功能检查项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>260.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>2</td><td>腹部彩超</td><td>BUS-002</td><td>常规检查</td><td>影像检查项目</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>180.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>3</td><td>血常规</td><td>BLD-003</td><td>常规检查</td><td>检验项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>35.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
</tbody>
</table>
</div>
@@ -521,6 +525,7 @@
<button class="btn btn-primary" onclick="openAddDrawer()">+ 新增</button>
<button class="btn btn-default">批量删除</button>
<button class="btn btn-default" onclick="openMutualDrawer()">互斥项目配置</button>
<button class="btn btn-default" onclick="openRelDrawer()">关联项目配置</button>
</div>
<div class="table-card">
<div class="table-card__header">
@@ -530,13 +535,13 @@
<table>
<thead>
<tr>
<th>序号</th><th>项目名称</th><th>项目编号</th><th>检查分类</th><th>项目类别</th><th>项目图片</th><th>默认费用(元)</th><th>项目音频</th><th>项目视频</th><th>操作</th>
<th>序号</th><th>项目名称</th><th>项目编号</th><th>检查分类</th><th>项目类别</th><th>项目图片</th><th>默认费用(元)</th><th>操作</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>经颅多普勒</td><td>TCD-001</td><td>常规检查</td><td>功能检查项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>260.00</td><td><span class="media-icon media-icon--empty" title="暂无音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--empty" title="暂无视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>2</td><td>腹部彩超</td><td>BUS-002</td><td>常规检查</td><td>影像检查项目</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>180.00</td><td><span class="media-icon media-icon--active" title="播放音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--active" title="播放视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>3</td><td>血常规</td><td>BLD-003</td><td>常规检查</td><td>检验项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>35.00</td><td><span class="media-icon media-icon--empty" title="暂无音频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v9M8 2L5 5H3v4h2l3 3V2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 5.5a3 3 0 010 5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg></span></td><td><span class="media-icon media-icon--active" title="播放视频"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="4" width="9" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M11 7l3-2v6l-3-2V7z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>1</td><td>经颅多普勒</td><td>TCD-001</td><td>常规检查</td><td>功能检查项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>260.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>2</td><td>腹部彩超</td><td>BUS-002</td><td>常规检查</td><td>影像检查项目</td><td><span class="media-icon media-icon--active" title="查看图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>180.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
<tr><td>3</td><td>血常规</td><td>BLD-003</td><td>常规检查</td><td>检验项目</td><td><span class="media-icon media-icon--empty" title="暂无图片"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="6.5" r="1.2" stroke="currentColor" stroke-width="1"/><path d="M2 11l3.5-3 2.5 2 3-2.5L14 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></td><td>35.00</td><td><span class="link">更新已生成费用</span> <span class="link" style="margin-left:8px;">编辑</span> <span class="link" style="margin-left:8px;">详情</span> <span class="link" style="margin-left:8px;color:var(--danger);">删除</span></td></tr>
</tbody>
</table>
</div>
@@ -597,22 +602,6 @@
<input type="file" class="upload-file">
</label>
</div>
<div class="form-item">
<div class="form-label">项目音频</div>
<label class="upload-box">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 11V3M5 6l3-3 3 3" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 11v1a1 1 0 001 1h8a1 1 0 001-1v-1" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
上传音频
<input type="file" class="upload-file">
</label>
</div>
<div class="form-item">
<div class="form-label">项目视频</div>
<label class="upload-box">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 11V3M5 6l3-3 3 3" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 11v1a1 1 0 001 1h8a1 1 0 001-1v-1" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
上传视频
<input type="file" class="upload-file">
</label>
</div>
<div class="form-item">
<div class="form-label">描述</div>
<div class="editor-toolbar">
@@ -711,6 +700,72 @@
</div>
</div>
<!-- 关联项目配置抽屉 -->
<div class="drawer-overlay" id="rel-overlay" onclick="closeRelDrawer()"></div>
<div class="drawer drawer--wide" id="rel-drawer">
<div class="drawer__header">
<div class="drawer__title" id="rel-drawer-title">泾河医院 - 关联项目配置</div>
<button class="drawer__close" onclick="closeRelDrawer()"></button>
</div>
<div class="drawer__body">
<div style="display:flex;gap:12px;margin-bottom:16px;">
<button class="btn btn-primary" onclick="openRelAddModal()">+ 新增</button>
<button class="btn btn-danger" onclick="batchDeleteRel()">批量删除</button>
</div>
<div class="table-card">
<div class="table-card__content">
<table>
<thead>
<tr>
<th style="width:40px;"><input type="checkbox" id="rel-check-all" onclick="toggleRelCheckAll(this)"></th>
<th>序号</th><th>体检项目</th><th>关联项目</th><th>操作</th>
</tr>
</thead>
<tbody id="rel-tbody"></tbody>
</table>
</div>
</div>
</div>
</div>
<!-- 新增关联项目弹窗 -->
<div class="modal-overlay" id="rel-modal-overlay" onclick="if(event.target===this)closeRelAddModal()">
<div class="modal">
<div class="modal__header">
<div class="modal__title">新增关联项目</div>
<button class="modal__close" onclick="closeRelAddModal()"></button>
</div>
<div class="modal__body">
<div class="form-item">
<div class="form-label">体检医院</div>
<input class="form-input" id="rel-hospital" disabled>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 体检项目</div>
<div class="search-select" id="rel-item-select">
<input type="text" class="search-select__input" id="rel-item-input" placeholder="请输入项目名称搜索" autocomplete="off">
<input type="hidden" id="rel-item-value">
<span class="search-select__clear" id="rel-item-clear" title="清除"></span>
<div class="search-select__dropdown" id="rel-item-dropdown"></div>
</div>
</div>
<div class="form-item">
<div class="form-label"><span class="required">*</span> 关联项目</div>
<div class="search-select" id="rel-target-select">
<input type="text" class="search-select__input" id="rel-target-input" placeholder="请输入项目名称搜索" autocomplete="off">
<input type="hidden" id="rel-target-value">
<span class="search-select__clear" id="rel-target-clear" title="清除"></span>
<div class="search-select__dropdown" id="rel-target-dropdown"></div>
</div>
</div>
</div>
<div class="modal__footer">
<button class="btn btn-default" onclick="closeRelAddModal()">取消</button>
<button class="btn btn-primary" onclick="saveRelItem()">确认保存</button>
</div>
</div>
</div>
<script>
/* 医院TAB切换 */
function switchHospital(type, el){
@@ -1005,6 +1060,114 @@ function batchDeleteMutual(){
indexes.forEach(function(i){ mutualData.splice(i, 1); });
renderMutualTable();
}
/* ===== 关联项目配置 ===== */
var relData = [
{item:'胃镜(GAS-011', related:'心电图(ECG-004'},
{item:'肠镜(COL-012', related:'血常规(BLD-003'}
];
var relItemSelect = initSearchSelect({
containerId:'rel-item-select',
inputId:'rel-item-input',
hiddenId:'rel-item-value',
clearId:'rel-item-clear',
dropdownId:'rel-item-dropdown',
data:itemData,
getLabel:function(item){ return item.name + '' + item.code + ''; }
});
var relTargetSelect = initSearchSelect({
containerId:'rel-target-select',
inputId:'rel-target-input',
hiddenId:'rel-target-value',
clearId:'rel-target-clear',
dropdownId:'rel-target-dropdown',
data:itemData,
getLabel:function(item){ return item.name + '' + item.code + ''; }
});
/* 渲染关联项目列表 */
function renderRelTable(){
var tbody = document.getElementById('rel-tbody');
tbody.innerHTML = '';
relData.forEach(function(row, i){
var tr = document.createElement('tr');
tr.innerHTML =
'<td><input type="checkbox" class="rel-row-check" data-index="' + i + '" onchange="updateRelCheckAll()"></td>' +
'<td>' + (i + 1) + '</td>' +
'<td>' + row.item + '</td>' +
'<td>' + row.related + '</td>' +
'<td><span class="link" style="color:var(--danger);" onclick="deleteRelRow(' + i + ')">删除</span></td>';
tbody.appendChild(tr);
});
document.getElementById('rel-check-all').checked = false;
}
/* 打开关联项目配置抽屉 */
function openRelDrawer(){
var activeTab = document.querySelector('.hospital-tab.active');
var hospitalName = activeTab ? activeTab.textContent.trim() : '医院';
document.getElementById('rel-drawer-title').textContent = hospitalName + ' - 关联项目配置';
renderRelTable();
document.getElementById('rel-drawer').classList.add('open');
document.getElementById('rel-overlay').classList.add('open');
}
function closeRelDrawer(){
document.getElementById('rel-drawer').classList.remove('open');
document.getElementById('rel-overlay').classList.remove('open');
}
/* 新增关联项目弹窗 */
function openRelAddModal(){
var activeTab = document.querySelector('.hospital-tab.active');
document.getElementById('rel-hospital').value = activeTab ? activeTab.textContent.trim() : '';
relItemSelect.clear();
relTargetSelect.clear();
document.getElementById('rel-modal-overlay').classList.add('open');
}
function closeRelAddModal(){
document.getElementById('rel-modal-overlay').classList.remove('open');
}
function saveRelItem(){
var itemIdx = relItemSelect.getValue();
var targetIdx = relTargetSelect.getValue();
if(itemIdx === '' || targetIdx === ''){ alert('请选择体检项目和关联项目'); return; }
if(itemIdx === targetIdx){ alert('体检项目与关联项目不能相同'); return; }
var item = itemData[Number(itemIdx)];
var target = itemData[Number(targetIdx)];
var itemLabel = item.name + '' + item.code + '';
var targetLabel = target.name + '' + target.code + '';
var dup = relData.some(function(r){ return r.item === itemLabel && r.related === targetLabel; });
if(dup){ alert('该关联关系已存在'); return; }
relData.push({item:itemLabel, related:targetLabel});
renderRelTable();
closeRelAddModal();
}
/* 删除关联项目 */
function deleteRelRow(i){
if(!confirm('确认删除该关联关系?')) return;
relData.splice(i, 1);
renderRelTable();
}
function toggleRelCheckAll(el){
document.querySelectorAll('.rel-row-check').forEach(function(c){ c.checked = el.checked; });
}
function updateRelCheckAll(){
var all = document.querySelectorAll('.rel-row-check');
var checked = document.querySelectorAll('.rel-row-check:checked');
document.getElementById('rel-check-all').checked = all.length > 0 && checked.length === all.length;
}
function batchDeleteRel(){
var checked = document.querySelectorAll('.rel-row-check:checked');
if(checked.length === 0){ alert('请先选择要删除的记录'); return; }
if(!confirm('确认删除选中的 ' + checked.length + ' 条关联关系?')) return;
var indexes = [];
checked.forEach(function(c){ indexes.push(Number(c.dataset.index)); });
indexes.sort(function(a, b){ return b - a; });
indexes.forEach(function(i){ relData.splice(i, 1); });
renderRelTable();
}
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff