Files
guoju0808/proto/html/components/project-manage.html
T
郭庆泰 cf5790229a refactor: 合并 biz_support_unit/biz_execution_unit/biz_service_org 为 biz_org, 删除 2 张孤儿表, 改 biz_person.work_unit → org_id FK
主要改动:
- SQL: biz_support_unit → biz_org, 加 org_type, 加 business_nature; 删 biz_execution_unit, biz_service_org
- SQL: biz_project.support_unit_id/name + service_org_id/name → org_id/name/type
- SQL: biz_meeting.support_unit_name → org_name
- SQL: biz_person.work_unit → org_id (FK)
- 后端: 新 BizOrg entity/mapper/service/controller
- 后端: BizProject/BizMeeting 字段重命名
- 后端: 删 12 个 BizSupportUnit/BizExecutionUnit/BizServiceOrg Java 文件
- 后端: BizPersonImportVO.workUnit → orgName (导入时查 biz_org 取 org_id)
- 后端: BizAuthController.registerExecutor 完整实现 (原 registerSupplier stub)
- 前端: 新 admin/Orgs.vue + manager/Orgs.vue (原 SupportUnits)
- 前端: RegisterExecutor.vue (原 RegisterSupplier, 单页 2 步)
- 前端: sponsor/executor/manager 多个文件 workUnit → orgId/orgName 重命名
- 前端: 统一 supplier → executor, 业务命名 sponsor(赞助方) / executor(执行方=供应商)
- 前端: 全工程 execution → executor (company type / role / person unit_type)
2026-08-15 12:41:10 +08:00

676 lines
45 KiB
HTML

<!DOCTYPE html>
<!-- 角色:合规 父级:manager.html 原型:原型/项目管理.html
8 个操作按钮(按原型):
#1 建会 → navigateTo new-meeting.html?project_code=X
#2 分配 → 弹分配 modal(选监察员 + 备注)
#3 结题 → 弹确认 modal(您确定要结题吗?)
#4 详情 → navigateTo project-detail-compliance.html?code=X
#5 编辑 → navigateTo edit-project.html?code=X
#6 开通 → 弹确认 modal(您确定要开通吗?+开通截止时间)
#7 删除公告 → 弹确认 modal(您确定要删除公告吗?)
#8 执行单位评分 → 弹评分 modal(单行版,4 维度)
批量按钮:批量评分/批量结题/批量开通(已有) -->
<html lang="zh-CN">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>项目管理</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}body{font-family:-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;color:#333;background:#fafafa;min-height:100vh}
.content{padding:24px 32px}.page-header{margin-bottom:20px}
.page-title{font-size:22px;font-weight:600;color:#1a1a1a;margin-bottom:4px}
.page-subtitle{font-size:13px;color:#8c8c8c}
.card{background:#fff;border-radius:8px;padding:20px 24px;margin-bottom:16px;border:1px solid #f0f0f0}
.filter-row{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:12px;align-items:center;margin-bottom:16px}
.filter-row.row-2{grid-template-columns:1fr 1fr 1fr 1fr}
.filter-actions{display:flex;justify-content:flex-end;gap:12px;margin-top:4px;flex-wrap:wrap}
.filter-field{display:flex;align-items:center;gap:8px}
.filter-label{font-size:14px;color:#595959;white-space:nowrap;flex-shrink:0}
.filter-input,.filter-select{flex:1;height:32px;padding:0 10px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;color:#333;background:#fff;outline:none}
.filter-input:focus,.filter-select:focus{border-color:#1890ff;box-shadow:0 0 0 3px rgba(24,144,255,0.1)}
.filter-select{cursor:pointer;appearance:none;background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center;background-size:14px;padding-right:24px}
.filter-btn{height:32px;padding:0 16px;background:#1890ff;color:#fff;border:none;border-radius:4px;font-size:13px;cursor:pointer;white-space:nowrap}
.filter-btn:hover{background:#096dd9}
.filter-date-range{display:flex;align-items:center;gap:6px;flex:1}
.filter-date-range .filter-input{flex:1;min-width:0}
.filter-date-sep{color:#8c8c8c;font-size:13px;flex-shrink:0}
.filter-btn.export{background:#fff;color:#595959;border:1px solid #d9d9d9}
.filter-btn.export:hover{border-color:#1890ff;color:#1890ff}
.hint-text{font-size:12px;color:#ff4d4f;margin:8px 0;line-height:1.6}
.action-bar{display:flex;gap:12px;margin-bottom:12px}
.action-btn{display:inline-flex;align-items:center;justify-content:center;height:36px;padding:0 20px;background:#1890ff;color:#fff;border:none;border-radius:4px;font-size:14px;cursor:pointer;white-space:nowrap;text-decoration:none}
.action-btn:hover{background:#096dd9}
.action-btn.secondary{background:#fff;color:#1890ff;border:1px solid #1890ff}
.action-btn.secondary:hover{background:#e6f7ff}
.table-wrap{background:#fff;border:1px solid #f0f0f0;border-radius:8px;overflow-x:auto}
.data-table{width:100%;border-collapse:collapse;font-size:13px;table-layout:fixed;min-width:2900px}
.data-table thead th{background:#fafafa;padding:12px 10px;text-align:left;color:#1a1a1a;font-weight:600;border-bottom:1px solid #f0f0f0;white-space:nowrap}
.data-table tbody td{padding:12px 10px;border-bottom:1px solid #f5f5f5;color:#595959;vertical-align:middle;white-space:nowrap}
.data-table tbody tr:hover{background:#fafcff}
.col-check{width:40px}.col-code{width:105px}.col-name{width:165px}.col-sessions{width:110px;text-align:center}
.col-num{width:80px;text-align:center}.col-money{width:100px;text-align:right}.col-paid{width:130px;text-align:right}
.col-score{width:95px;text-align:center}.col-eval{width:120px;text-align:center}
.col-org{width:165px}.col-form{width:100px;text-align:center}.col-status{width:90px;text-align:center}.col-date{width:110px}.col-op{width:420px}
.data-table input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:#1890ff}
.col-code-link{color:#1890ff;font-family:ui-monospace,"Courier New",monospace;text-decoration:none}
.col-code-link:hover{text-decoration:underline}
.col-name-link{color:#1a1a1a;font-weight:500;text-decoration:none}
.col-name-link:hover{color:#1890ff}
.col-num-text{color:#1a1a1a;font-weight:500;font-family:ui-monospace,"Courier New",monospace}
.col-money-text{color:#1a1a1a;font-weight:500;font-family:ui-monospace,"Courier New",monospace;font-size:12px}
.col-score-link{color:#1890ff;font-weight:500;text-decoration:none;cursor:pointer}
.col-score-link:hover{text-decoration:underline}
.status-tag{display:inline-block;padding:2px 10px;border-radius:10px;font-size:12px}
.status-pending{background:#fff7e6;color:#fa8c16}.status-done{background:#f6ffed;color:#52c41a}.status-activated{background:#e6f4ff;color:#1890ff;border:1px solid #91d5ff}
.op-link{color:#1890ff;text-decoration:none;margin-right:10px;font-size:13px;display:inline-block;cursor:pointer}
.op-link:last-child{margin-right:0}.op-link:hover{text-decoration:underline}
.op-link.danger{color:#ff4d4f}
/* Modal 通用样式 */
.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:1000}
.modal-overlay.show{display:flex}
.modal-dialog{background:#fff;border-radius:8px;box-shadow:0 6px 24px rgba(0,0,0,.15);overflow:hidden;animation:modal-in .2s ease-out}
@keyframes modal-in{from{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}
.modal-title{padding:20px 24px 16px;font-size:16px;font-weight:600;color:#1a1a1a;text-align:center;border-bottom:1px solid #f0f0f0}
.modal-body{padding:24px}
.modal-row{display:flex;align-items:center;gap:12px;margin-bottom:8px}
.modal-row-col{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}
.modal-label{font-size:14px;color:#1a1a1a;white-space:nowrap;flex-shrink:0}
.modal-input{flex:1;height:32px;padding:0 10px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;color:#333;background:#fff;outline:none;font-family:inherit}
.modal-input:focus{border-color:#1890ff;box-shadow:0 0 0 3px rgba(24,144,255,.1)}
.modal-textarea{width:100%;min-height:60px;padding:8px 10px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;resize:vertical;outline:none;box-sizing:border-box;font-family:inherit}
.modal-textarea:focus{border-color:#1890ff;box-shadow:0 0 0 3px rgba(24,144,255,.1)}
.modal-hint{font-size:12px;color:#ff4d4f;margin-top:4px}
.modal-actions{padding:16px 24px 20px;display:flex;justify-content:center;gap:16px;border-top:1px solid #f0f0f0}
.modal-btn{height:36px;padding:0 32px;border:none;border-radius:4px;font-size:14px;cursor:pointer;min-width:100px}
.modal-btn.primary{background:#1890ff;color:#fff}.modal-btn.primary:hover{background:#096dd9}
.modal-btn.default{background:#fff;color:#595959;border:1px solid #d9d9d9}.modal-btn.default:hover{border-color:#1890ff;color:#1890ff}
.score-table{width:100%;border-collapse:collapse;font-size:13px}
.score-table thead th{background:#fafafa;padding:10px 12px;text-align:left;color:#1a1a1a;font-weight:600;border-bottom:1px solid #f0f0f0;white-space:nowrap}
.score-table tbody td{padding:10px 12px;border-bottom:1px solid #f5f5f5;color:#595959;white-space:nowrap}
.score-table tbody tr:last-child td{border-bottom:none}
.score-table .col-score-num{font-weight:600;color:#1890ff;font-family:ui-monospace,"Courier New",monospace;text-align:center}
.score-input-row{display:flex;align-items:center;padding:12px 0;border-bottom:1px solid #f5f5f5;gap:12px}
.score-input-row:last-child{border-bottom:none}
.score-input-row .row-dim{font-size:13px;color:#1a1a1a;font-weight:600;width:110px;flex-shrink:0}
.score-input-row .row-stars{display:flex;gap:4px}
.score-input-row .row-star{font-size:22px;color:#d9d9d9;cursor:pointer;user-select:none;line-height:1;transition:color .15s}
.score-input-row .row-star.active,.score-input-row .row-star:hover{color:#faad14}
.score-input-row .row-score-text{font-size:13px;color:#595959;margin-left:8px}
.assign-tag{display:inline-block;padding:4px 12px;margin:2px;border-radius:4px;background:#e6f4ff;color:#1890ff;border:1px solid #91d5ff;font-size:13px;cursor:pointer}
.assign-tag:hover{background:#1890ff;color:#fff}
@media(max-width:768px){.filter-row,.filter-row.row-2{grid-template-columns:1fr}.filter-actions{justify-content:flex-start}.content{padding:16px}.data-table{font-size:12px;display:block;overflow-x:auto;white-space:nowrap}}
</style>
</head>
<body>
<main class="content">
<div class="page-header">
<h1 class="page-title">项目管理</h1>
<p class="page-subtitle">查看所有项目、总场次、金额、结题情况</p>
</div>
<div class="card">
<div class="filter-row">
<div class="filter-field"><span class="filter-label">支持单位:</span><input type="text" class="filter-input" placeholder="输入支持单位"></div>
<div class="filter-field"><span class="filter-label">服务机构:</span><input type="text" class="filter-input" placeholder="输入服务机构"></div>
<div class="filter-field"><span class="filter-label">项目形式:</span>
<select class="filter-select"><option value="">请选择</option><option>线上</option><option>线下</option><option>线上+线下</option><option>其他</option></select>
</div>
<div class="filter-field"><span class="filter-label">项目编号:</span><input type="text" class="filter-input" placeholder="输入项目编号"></div>
</div>
<div class="filter-row row-2">
<div class="filter-field"><span class="filter-label">项目名称:</span><input type="text" class="filter-input" placeholder="输入项目名称"></div>
<div class="filter-field"><span class="filter-label">项目时间:</span>
<div class="filter-date-range"><input type="text" class="filter-input" placeholder="开始日期"><span class="filter-date-sep"></span><input type="text" class="filter-input" placeholder="结束日期"></div>
</div>
<div class="filter-field"><span class="filter-label">是否结题:</span>
<select class="filter-select"><option value="">请选择</option><option>已结题</option><option>未结题</option></select>
</div>
<div class="filter-field"><span class="filter-label">评价得分:</span><input type="text" class="filter-input" placeholder="输入评分"></div>
</div>
<div class="filter-actions">
<button class="filter-btn">查找</button>
<button class="filter-btn">重置</button>
<button class="filter-btn export">导出</button>
<button class="filter-btn export">项目评价导出</button>
<button class="filter-btn export">已报名专家信息导出</button>
</div>
</div>
<p class="hint-text">*项目分配给执行方,执行方管理员只能看到已分配的项目</p>
<p class="hint-text">*支持多个支持单位筛选</p>
<p class="hint-text">*支持按查询条件进行项目评价导出</p>
<p class="hint-text">*点击后可查看具体评价维度,评价标准与供应商系统保持一致</p>
<div class="action-bar">
<a class="action-btn" href="new-project.html">新建项目</a>
<a class="action-btn secondary" href="project-assign.html">项目分配</a>
<button class="action-btn secondary" id="btnBatchScore">批量评分</button>
<button class="action-btn secondary" id="btnBatchClose">批量结题</button>
<button class="action-btn secondary" id="btnBatchActivate">批量开通</button>
</div>
<div class="table-wrap">
<table class="data-table">
<colgroup>
<col class="col-check"><col class="col-code"><col class="col-name"><col class="col-sessions">
<col class="col-num"><col class="col-num"><col class="col-money"><col class="col-money">
<col class="col-paid"><col class="col-paid"><col class="col-score"><col class="col-eval">
<col class="col-org"><col class="col-org"><col class="col-form"><col class="col-status">
<col class="col-date"><col class="col-date"><col class="col-op">
</colgroup>
<thead>
<tr>
<th class="col-check"><input type="checkbox" id="selectAll"></th>
<th>项目编号</th><th>项目名称</th>
<th class="col-sessions">总场次/总期数</th>
<th class="col-num">已执行</th><th class="col-num">未执行</th>
<th class="col-money">总金额</th><th class="col-money">可用金额</th>
<th class="col-paid">已支付劳务费</th><th class="col-paid">已支付会务费</th>
<th class="col-score">执行单位得分(合规)</th>
<th class="col-eval">执行单位评价(支持方)</th>
<th>支持单位</th><th>服务机构</th>
<th class="col-form">项目形式</th>
<th class="col-status">是否结题</th>
<th class="col-date">项目开始时间</th><th class="col-date">项目结束时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr data-code="ZH-2026-658">
<td><input type="checkbox" class="row-check"></td>
<td><a class="col-code-link" href="javascript:void(0)">ZH-2026-658</a></td>
<td><a class="col-name-link" href="javascript:void(0)">小牛血清创新应用研讨会</a></td>
<td class="col-sessions"><span class="col-num-text">26</span></td>
<td class="col-num"><span class="col-num-text">16</span></td>
<td class="col-num"><span class="col-num-text">10</span></td>
<td class="col-money"><span class="col-money-text">3,112,000</span></td>
<td class="col-money"><span class="col-money-text">1,112,000</span></td>
<td class="col-paid"><span class="col-money-text">1,000,000</span></td>
<td class="col-paid"><span class="col-money-text">1,000,000</span></td>
<td class="col-score"><a class="col-score-link" onclick="openSingleScore(this)">5.0</a></td>
<td class="col-eval">-</td>
<td>北京XXXX有限公司</td><td>北京XXXX公司</td>
<td class="col-form">线上</td>
<td class="col-status"><span class="status-tag status-pending">未结题</span></td>
<td class="col-date">2026-05-11</td><td class="col-date">2026-06.30</td>
<td>
<a class="op-link" onclick="doCreateMeeting(this)">建会</a>
<a class="op-link" onclick="doAssign(this)">分配</a>
<a class="op-link" onclick="openClose(this)">结题</a>
<a class="op-link" onclick="doDetail(this)">查看</a>
<a class="op-link" onclick="doEdit(this)">编辑</a>
<a class="op-link" onclick="openActivate(this)">开通</a>
<a class="op-link" onclick="openDeleteAnnouncement(this)">删除公告</a>
<a class="op-link" onclick="openSingleScore(this)">执行单位评分</a>
</td>
</tr>
<tr data-code="ZH-2026-659">
<td><input type="checkbox" class="row-check"></td>
<td><a class="col-code-link" href="javascript:void(0)">ZH-2026-659</a></td>
<td><a class="col-name-link" href="javascript:void(0)">整合医学学会项目评审</a></td>
<td class="col-sessions"><span class="col-num-text">18</span></td>
<td class="col-num"><span class="col-num-text">12</span></td>
<td class="col-num"><span class="col-num-text">6</span></td>
<td class="col-money"><span class="col-money-text">2,500,000</span></td>
<td class="col-money"><span class="col-money-text">980,000</span></td>
<td class="col-paid"><span class="col-money-text">900,000</span></td>
<td class="col-paid"><span class="col-money-text">620,000</span></td>
<td class="col-score"><a class="col-score-link" onclick="openSingleScore(this)">4.5</a></td>
<td class="col-eval"><a class="col-score-link" onclick="void(0)">3.5</a></td>
<td>北京XXXX有限公司</td><td>北京XXXX公司</td>
<td class="col-form">线下</td>
<td class="col-status"><span class="status-tag status-pending">未结题</span></td>
<td class="col-date">2026-05-11</td><td class="col-date">2026-06.30</td>
<td>
<a class="op-link" onclick="doCreateMeeting(this)">建会</a>
<a class="op-link" onclick="doAssign(this)">分配</a>
<a class="op-link" onclick="openClose(this)">结题</a>
<a class="op-link" onclick="doDetail(this)">查看</a>
<a class="op-link" onclick="doEdit(this)">编辑</a>
<a class="op-link" onclick="openActivate(this)">开通</a>
<a class="op-link" onclick="openDeleteAnnouncement(this)">删除公告</a>
<a class="op-link" onclick="openSingleScore(this)">执行单位评分</a>
</td>
</tr>
<tr data-code="ZH-2026-650">
<td><input type="checkbox" class="row-check"></td>
<td><a class="col-code-link" href="javascript:void(0)">ZH-2026-650</a></td>
<td><a class="col-name-link" href="javascript:void(0)">智慧医院建设项目</a></td>
<td class="col-sessions"><span class="col-num-text">12</span></td>
<td class="col-num"><span class="col-num-text">7</span></td>
<td class="col-num"><span class="col-num-text">5</span></td>
<td class="col-money"><span class="col-money-text">1,800,000</span></td>
<td class="col-money"><span class="col-money-text">760,000</span></td>
<td class="col-paid"><span class="col-money-text">700,000</span></td>
<td class="col-paid"><span class="col-money-text">340,000</span></td>
<td class="col-score"><a class="col-score-link" onclick="openSingleScore(this)">4.0</a></td>
<td class="col-eval"><a class="col-score-link" onclick="void(0)">4.5</a></td>
<td>北京XXXX有限公司</td><td>北京XXXX公司</td>
<td class="col-form">线上+线下</td>
<td class="col-status"><span class="status-tag status-pending">未结题</span></td>
<td class="col-date">2026-05-11</td><td class="col-date">2026-06.30</td>
<td>
<a class="op-link" onclick="doCreateMeeting(this)">建会</a>
<a class="op-link" onclick="doAssign(this)">分配</a>
<a class="op-link" onclick="openClose(this)">结题</a>
<a class="op-link" onclick="doDetail(this)">查看</a>
<a class="op-link" onclick="doEdit(this)">编辑</a>
<a class="op-link" onclick="openActivate(this)">开通</a>
<a class="op-link" onclick="openDeleteAnnouncement(this)">删除公告</a>
<a class="op-link" onclick="openSingleScore(this)">执行单位评分</a>
</td>
</tr>
<tr data-code="ZH-2026-645">
<td><input type="checkbox" class="row-check"></td>
<td><a class="col-code-link" href="javascript:void(0)">ZH-2026-645</a></td>
<td><a class="col-name-link" href="javascript:void(0)">基层医疗改革试点项目</a></td>
<td class="col-sessions"><span class="col-num-text">20</span></td>
<td class="col-num"><span class="col-num-text">14</span></td>
<td class="col-num"><span class="col-num-text">6</span></td>
<td class="col-money"><span class="col-money-text">2,800,000</span></td>
<td class="col-money"><span class="col-money-text">1,050,000</span></td>
<td class="col-paid"><span class="col-money-text">950,000</span></td>
<td class="col-paid"><span class="col-money-text">800,000</span></td>
<td class="col-score"><a class="col-score-link" onclick="openSingleScore(this)">4.8</a></td>
<td class="col-eval"><a class="col-score-link" onclick="void(0)">3.0</a></td>
<td>北京XXXX有限公司</td><td>北京XXXX公司</td>
<td class="col-form">线下</td>
<td class="col-status"><span class="status-tag status-pending">未结题</span></td>
<td class="col-date">2026-05-11</td><td class="col-date">2026-06.30</td>
<td>
<a class="op-link" onclick="doCreateMeeting(this)">建会</a>
<a class="op-link" onclick="doAssign(this)">分配</a>
<a class="op-link" onclick="openClose(this)">结题</a>
<a class="op-link" onclick="doDetail(this)">查看</a>
<a class="op-link" onclick="doEdit(this)">编辑</a>
<a class="op-link" onclick="openActivate(this)">开通</a>
<a class="op-link" onclick="openDeleteAnnouncement(this)">删除公告</a>
<a class="op-link" onclick="openSingleScore(this)">执行单位评分</a>
</td>
</tr>
<tr data-code="ZH-2026-640">
<td><input type="checkbox" class="row-check"></td>
<td><a class="col-code-link" href="javascript:void(0)">ZH-2026-640</a></td>
<td><a class="col-name-link" href="javascript:void(0)">数字化医疗转型方案</a></td>
<td class="col-sessions"><span class="col-num-text">22</span></td>
<td class="col-num"><span class="col-num-text">15</span></td>
<td class="col-num"><span class="col-num-text">7</span></td>
<td class="col-money"><span class="col-money-text">3,000,000</span></td>
<td class="col-money"><span class="col-money-text">1,200,000</span></td>
<td class="col-paid"><span class="col-money-text">1,100,000</span></td>
<td class="col-paid"><span class="col-money-text">700,000</span></td>
<td class="col-score"><a class="col-score-link" onclick="openSingleScore(this)">4.2</a></td>
<td class="col-eval"><a class="col-score-link" onclick="void(0)">4.0</a></td>
<td>北京XXXX有限公司</td><td>北京XXXX公司</td>
<td class="col-form">线上</td>
<td class="col-status"><span class="status-tag status-pending">未结题</span></td>
<td class="col-date">2026-05-11</td><td class="col-date">2026-06.30</td>
<td>
<a class="op-link" onclick="doCreateMeeting(this)">建会</a>
<a class="op-link" onclick="doAssign(this)">分配</a>
<a class="op-link" onclick="openClose(this)">结题</a>
<a class="op-link" onclick="doDetail(this)">查看</a>
<a class="op-link" onclick="doEdit(this)">编辑</a>
<a class="op-link" onclick="openActivate(this)">开通</a>
<a class="op-link" onclick="openDeleteAnnouncement(this)">删除公告</a>
<a class="op-link" onclick="openSingleScore(this)">执行单位评分</a>
</td>
</tr>
<tr data-code="ZH-2026-635">
<td><input type="checkbox" class="row-check"></td>
<td><a class="col-code-link" href="javascript:void(0)">ZH-2026-635</a></td>
<td><a class="col-name-link" href="javascript:void(0)">临床医学研究方案评议</a></td>
<td class="col-sessions"><span class="col-num-text">14</span></td>
<td class="col-num"><span class="col-num-text">9</span></td>
<td class="col-num"><span class="col-num-text">5</span></td>
<td class="col-money"><span class="col-money-text">2,200,000</span></td>
<td class="col-money"><span class="col-money-text">820,000</span></td>
<td class="col-paid"><span class="col-money-text">740,000</span></td>
<td class="col-paid"><span class="col-money-text">640,000</span></td>
<td class="col-score"><a class="col-score-link" onclick="openSingleScore(this)">4.6</a></td>
<td class="col-eval"><a class="col-score-link" onclick="void(0)">4.2</a></td>
<td>北京XXXX有限公司</td><td>北京XXXX公司</td>
<td class="col-form">线下</td>
<td class="col-status"><span class="status-tag status-done">已结题</span></td>
<td class="col-date">2026-05-11</td><td class="col-date">2026-06.30</td>
<td>
<a class="op-link" onclick="doCreateMeeting(this)">建会</a>
<a class="op-link" onclick="openClose(this)">结题</a>
<a class="op-link" onclick="doDetail(this)">查看</a>
<a class="op-link" onclick="doAssign(this)">分配</a>
<a class="op-link" onclick="openActivate(this)">开通</a>
<a class="op-link" onclick="doEdit(this)">编辑</a>
<a class="op-link" onclick="openDeleteAnnouncement(this)">删除公告</a>
<a class="op-link" onclick="openSingleScore(this)">执行单位评分</a>
</td>
</tr>
<tr data-code="ZH-2026-628">
<td><input type="checkbox" class="row-check"></td>
<td><a class="col-code-link" href="javascript:void(0)">ZH-2026-628</a></td>
<td><a class="col-name-link" href="javascript:void(0)">公共卫生应急体系建设项目</a></td>
<td class="col-sessions"><span class="col-num-text">16</span></td>
<td class="col-num"><span class="col-num-text">11</span></td>
<td class="col-num"><span class="col-num-text">5</span></td>
<td class="col-money"><span class="col-money-text">2,400,000</span></td>
<td class="col-money"><span class="col-money-text">900,000</span></td>
<td class="col-paid"><span class="col-money-text">820,000</span></td>
<td class="col-paid"><span class="col-money-text">680,000</span></td>
<td class="col-score"><a class="col-score-link" onclick="openSingleScore(this)">4.4</a></td>
<td class="col-eval"><a class="col-score-link" onclick="void(0)">3.8</a></td>
<td>北京XXXX有限公司</td><td>北京XXXX公司</td>
<td class="col-form">线下</td>
<td class="col-status"><span class="status-tag status-pending">未结题</span></td>
<td class="col-date">2026-05-11</td><td class="col-date">2026-06.30</td>
<td>
<a class="op-link" onclick="doCreateMeeting(this)">建会</a>
<a class="op-link" onclick="doAssign(this)">分配</a>
<a class="op-link" onclick="openClose(this)">结题</a>
<a class="op-link" onclick="doDetail(this)">查看</a>
<a class="op-link" onclick="doEdit(this)">编辑</a>
<a class="op-link" onclick="openActivate(this)">开通</a>
<a class="op-link" onclick="openDeleteAnnouncement(this)">删除公告</a>
<a class="op-link" onclick="openSingleScore(this)">执行单位评分</a>
</td>
</tr>
<tr data-code="ZH-2026-622">
<td><input type="checkbox" class="row-check"></td>
<td><a class="col-code-link" href="javascript:void(0)">ZH-2026-622</a></td>
<td><a class="col-name-link" href="javascript:void(0)">中医诊疗标准化研究</a></td>
<td class="col-sessions"><span class="col-num-text">10</span></td>
<td class="col-num"><span class="col-num-text">6</span></td>
<td class="col-num"><span class="col-num-text">4</span></td>
<td class="col-money"><span class="col-money-text">1,500,000</span></td>
<td class="col-money"><span class="col-money-text">560,000</span></td>
<td class="col-paid"><span class="col-money-text">500,000</span></td>
<td class="col-paid"><span class="col-money-text">440,000</span></td>
<td class="col-score"><a class="col-score-link" onclick="openSingleScore(this)">4.7</a></td>
<td class="col-eval"><a class="col-score-link" onclick="void(0)">4.5</a></td>
<td>北京XXXX有限公司</td><td>北京XXXX公司</td>
<td class="col-form">线下</td>
<td class="col-status"><span class="status-tag status-pending">未结题</span></td>
<td class="col-date">2026-05-11</td><td class="col-date">2026-06.30</td>
<td>
<a class="op-link" onclick="doCreateMeeting(this)">建会</a>
<a class="op-link" onclick="doAssign(this)">分配</a>
<a class="op-link" onclick="openClose(this)">结题</a>
<a class="op-link" onclick="doDetail(this)">查看</a>
<a class="op-link" onclick="doEdit(this)">编辑</a>
<a class="op-link" onclick="openActivate(this)">开通</a>
<a class="op-link" onclick="openDeleteAnnouncement(this)">删除公告</a>
<a class="op-link" onclick="openSingleScore(this)">执行单位评分</a>
</td>
</tr>
<tr data-code="ZH-2026-618">
<td><input type="checkbox" class="row-check"></td>
<td><a class="col-code-link" href="javascript:void(0)">ZH-2026-618</a></td>
<td><a class="col-name-link" href="javascript:void(0)">医疗 AI 辅助诊断应用论坛</a></td>
<td class="col-sessions"><span class="col-num-text">8</span></td>
<td class="col-num"><span class="col-num-text">4</span></td>
<td class="col-num"><span class="col-num-text">4</span></td>
<td class="col-money"><span class="col-money-text">1,200,000</span></td>
<td class="col-money"><span class="col-money-text">480,000</span></td>
<td class="col-paid"><span class="col-money-text">420,000</span></td>
<td class="col-paid"><span class="col-money-text">300,000</span></td>
<td class="col-score"><a class="col-score-link" onclick="openSingleScore(this)">4.9</a></td>
<td class="col-eval"><a class="col-score-link" onclick="void(0)">4.8</a></td>
<td>北京XXXX有限公司</td><td>北京XXXX公司</td>
<td class="col-form">线上+线下</td>
<td class="col-status"><span class="status-tag status-pending">未结题</span></td>
<td class="col-date">2026-05-11</td><td class="col-date">2026-06.30</td>
<td>
<a class="op-link" onclick="doCreateMeeting(this)">建会</a>
<a class="op-link" onclick="doAssign(this)">分配</a>
<a class="op-link" onclick="openClose(this)">结题</a>
<a class="op-link" onclick="doDetail(this)">查看</a>
<a class="op-link" onclick="doEdit(this)">编辑</a>
<a class="op-link" onclick="openActivate(this)">开通</a>
<a class="op-link" onclick="openDeleteAnnouncement(this)">删除公告</a>
<a class="op-link" onclick="openSingleScore(this)">执行单位评分</a>
</td>
</tr>
</tbody>
</table>
</div>
</main>
<!-- Modal: 结题 (原型 u1858) -->
<div class="modal-overlay" id="closeModal">
<div class="modal-dialog" style="width:420px">
<div class="modal-title">您确定要结题吗?</div>
<div class="modal-actions" style="justify-content:center">
<button class="modal-btn primary" onclick="confirmClose()">确定</button>
<button class="modal-btn default" onclick="closeModal('closeModal')">取消</button>
</div>
</div>
</div>
<!-- Modal: 开通 (原型 u1668) -->
<div class="modal-overlay" id="activateModal">
<div class="modal-dialog" style="width:420px">
<div class="modal-title">您确定要开通吗?</div>
<div class="modal-actions" style="justify-content:center">
<button class="modal-btn primary" onclick="confirmActivate()">确定</button>
<button class="modal-btn default" onclick="closeModal('activateModal')">取消</button>
</div>
</div>
</div>
<!-- Modal: 删除公告 (原型 u1849) -->
<div class="modal-overlay" id="delAnnModal">
<div class="modal-dialog" style="width:420px">
<div class="modal-title">您确定要删除公告吗?删除后无法恢复</div>
<div class="modal-actions" style="justify-content:center">
<button class="modal-btn primary" onclick="confirmDeleteAnn()">确定</button>
<button class="modal-btn default" onclick="closeModal('delAnnModal')">取消</button>
</div>
</div>
</div>
<!-- Modal: 批量评分 (原型 u1842 — 4 个输入框,每个维度对应一个) -->
<div class="modal-overlay" id="scoreModal">
<div class="modal-dialog" style="width:626px">
<div class="modal-body" style="padding:24px 28px">
<table class="score-table">
<thead><tr><th style="width:110px">评价维度</th><th>评价内容(简洁版)</th><th style="width:130px;text-align:center">评分标准(1~5 分)</th></tr></thead>
<tbody>
<tr><td>履约质量</td><td>服务/活动效果达标度</td><td><input type="text" class="modal-input" id="batchScore1" placeholder="1~5"></td></tr>
<tr><td>时效响应</td><td>执行 &amp; 售后响应速度</td><td><input type="text" class="modal-input" id="batchScore2" placeholder="1~5"></td></tr>
<tr><td>配合度</td><td>沟通配合 &amp; 问题处理</td><td><input type="text" class="modal-input" id="batchScore3" placeholder="1~5"></td></tr>
<tr><td>合规安全</td><td>流程合规 &amp; 无安全事故</td><td><input type="text" class="modal-input" id="batchScore4" placeholder="1~5"></td></tr>
</tbody>
</table>
</div>
<div class="modal-actions" style="justify-content:center">
<button class="modal-btn primary" onclick="confirmBatchScore()">确定</button>
<button class="modal-btn default" onclick="closeModal('scoreModal')">取消</button>
</div>
</div>
</div>
<!-- Modal: 执行单位评分 (原型 u1867 — 与批量评分结构完全一致) -->
<div class="modal-overlay" id="singleScoreModal">
<div class="modal-dialog" style="width:626px">
<div class="modal-body" style="padding:24px 28px">
<table class="score-table">
<thead><tr><th style="width:110px">评价维度</th><th>评价内容(简洁版)</th><th style="width:130px;text-align:center">评分标准(1~5 分)</th></tr></thead>
<tbody>
<tr><td>履约质量</td><td>服务/活动效果达标度</td><td><input type="text" class="modal-input" id="evalScore1" placeholder="1~5"></td></tr>
<tr><td>时效响应</td><td>执行 &amp; 售后响应速度</td><td><input type="text" class="modal-input" id="evalScore2" placeholder="1~5"></td></tr>
<tr><td>配合度</td><td>沟通配合 &amp; 问题处理</td><td><input type="text" class="modal-input" id="evalScore3" placeholder="1~5"></td></tr>
<tr><td>合规安全</td><td>流程合规 &amp; 无安全事故</td><td><input type="text" class="modal-input" id="evalScore4" placeholder="1~5"></td></tr>
</tbody>
</table>
</div>
<div class="modal-actions" style="justify-content:center">
<button class="modal-btn primary" onclick="confirmSingleScore()">确定</button>
<button class="modal-btn default" onclick="closeModal('singleScoreModal')">取消</button>
</div>
</div>
</div>
<script>
document.getElementById('selectAll').addEventListener('change',function(){document.querySelectorAll('.row-check').forEach(c=>c.checked=this.checked)});
// 通用 iframe 路由
function navigateTo(href){
try{if(window.parent&&window.parent.document.getElementById('contentFrame')){window.parent.document.getElementById('contentFrame').src=href}else{window.location.href=href}}catch(e){window.location.href=href}
}
// 取行数据
function getRow(btn){return btn.closest('tr')}
function getCode(btn){return getRow(btn).dataset.code}
function getName(btn){return getRow(btn).querySelector('.col-name-link').textContent}
// 1. 建会
function doCreateMeeting(btn){
var code=getCode(btn);
navigateTo('new-meeting.html?project_code=' + encodeURIComponent(code));
}
// 4. 详情
function doDetail(btn){
navigateTo('project-detail-compliance.html?code=' + encodeURIComponent(getCode(btn)));
}
// 5. 编辑
function doEdit(btn){
navigateTo('new-project.html?code=' + encodeURIComponent(getCode(btn)));
}
// 2. 分配
function doAssign(btn){
navigateTo('project-assign.html?code=' + encodeURIComponent(getCode(btn)));
}
// 3. 结题
var closeTargetTr = null;
function openClose(btn){
closeTargetTr = getRow(btn);
var status=closeTargetTr.querySelector('.status-tag');
if(status.classList.contains('status-done')){alert('该项目已结题,无需重复操作');return}
document.getElementById('closeModal').classList.add('show');
}
function confirmClose(){
var status=closeTargetTr.querySelector('.status-tag');
status.className='status-tag status-done';
status.textContent='已结题';
alert('结题成功');
closeModal('closeModal');
}
// 6. 开通 (单行版,无 deadline 输入,仅确认)
var activateTargetTr = null;
function openActivate(btn){
activateTargetTr = getRow(btn);
document.getElementById('activateModal').classList.add('show');
}
function confirmActivate(){
var status=activateTargetTr.querySelector('.status-tag');
status.className='status-tag status-activated';
status.textContent='已开通';
alert('已开通');
closeModal('activateModal');
}
// 7. 删除公告
var delAnnTargetTr = null;
function openDeleteAnnouncement(btn){
delAnnTargetTr = getRow(btn);
document.getElementById('delAnnModal').classList.add('show');
}
function confirmDeleteAnn(){
alert('已删除项目 ' + getCode(delAnnTargetTr) + ' 的所有公告');
closeModal('delAnnModal');
}
// 8. 单行评分(原型 u1867 执行单位评分:有 4 个输入框)
var singleScoreTargetTr = null;
function openSingleScore(btn){
singleScoreTargetTr = getRow(btn);
document.getElementById('singleScoreModal').classList.add('show');
}
function confirmSingleScore(){
var s1=document.getElementById('evalScore1').value;
var s2=document.getElementById('evalScore2').value;
var s3=document.getElementById('evalScore3').value;
var s4=document.getElementById('evalScore4').value;
var dims=[s1,s2,s3,s4];
var labels=['履约质量','时效响应','配合度','合规安全'];
var scores=[];
for(var i=0;i<dims.length;i++){
var v=parseInt(dims[i]);
if(dims[i]===''){continue}
if(isNaN(v)||v<1||v>5){alert(labels[i]+'必须是 1~5 的数字');return}
scores.push(v);
}
if(!scores.length){alert('请至少填写一个维度的评分');return}
var avg=(scores.reduce(function(s,v){return s+v},0)/scores.length).toFixed(1);
var cell=singleScoreTargetTr.querySelector('.col-score');
if(cell){cell.innerHTML='<a class="col-score-link" onclick="openSingleScore(this)">'+avg+'</a>';}
alert('评分完成,平均分:' + avg);
closeModal('singleScoreModal');
}
// 批量开通(无 deadline,仅确认)
document.getElementById('btnBatchActivate').addEventListener('click',function(){
var checked=document.querySelectorAll('.row-check:checked');
if(!checked.length){alert('请先选择要开通的项目');return}
activateTargetTr=null;
document.getElementById('activateModal').classList.add('show');
});
// 批量评分 (原型 u1842 — 4 输入框,计算平均分批量更新)
var scoreModal=document.getElementById('scoreModal');
document.getElementById('btnBatchScore').addEventListener('click',function(){
var checked=document.querySelectorAll('.row-check:checked');
if(!checked.length){alert('请先选择要评分的项目');return}
['batchScore1','batchScore2','batchScore3','batchScore4'].forEach(function(id){document.getElementById(id).value=''});
scoreModal.classList.add('show');
});
function confirmBatchScore(){
var s=[document.getElementById('batchScore1').value,document.getElementById('batchScore2').value,document.getElementById('batchScore3').value,document.getElementById('batchScore4').value];
var labels=['履约质量','时效响应','配合度','合规安全'];
var scores=[];
for(var i=0;i<4;i++){
var v=parseInt(s[i]);
if(s[i]===''){continue}
if(isNaN(v)||v<1||v>5){alert(labels[i]+'必须是 1~5 的数字');return}
scores.push(v);
}
if(!scores.length){alert('请至少填写一个维度的评分');return}
var avg=(scores.reduce(function(s,v){return s+v},0)/scores.length).toFixed(1);
document.querySelectorAll('.row-check:checked').forEach(function(cb){
var row=cb.closest('tr');
var cell=row.querySelector('.col-score');
if(cell){cell.innerHTML='<a class="col-score-link" onclick="openSingleScore(this)">'+avg+'</a>';}
cb.checked=false;
});
alert('已为勾选项目完成评分\n平均分:' + avg);
closeModal('scoreModal');
}
// 批量结题
(function(){
var btn=document.getElementById('btnBatchClose');
if(btn){
btn.addEventListener('click',function(){
var checked=document.querySelectorAll('.row-check:checked');
if(!checked.length){alert('请先选择要结题的项目');return}
if(!confirm('确定要将 ' + checked.length + ' 个项目结题吗?'))return;
checked.forEach(cb=>{
var row=cb.closest('tr');
var s=row.querySelector('.status-tag');
s.className='status-tag status-done';s.textContent='已结题';
});
alert('已结题 ' + checked.length + ' 个项目');
});
}
})();
function closeModal(id){document.getElementById(id).classList.remove('show')}
document.querySelectorAll('.modal-overlay').forEach(m=>m.addEventListener('click',function(e){if(e.target===this)closeModal(this.id)}));
</script>
</body>
</html>