主要改动: - 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)
307 lines
23 KiB
HTML
307 lines
23 KiB
HTML
<!DOCTYPE html>
|
||
<!-- 角色:赞助方 父级:sponsor.html 原型:原型/会议列表.html
|
||
补全(2026-08-08 测试反馈):
|
||
筛选区(6 字段):
|
||
- 项目编号(u9704 label 左:281 + u9706 input 左:348)
|
||
- 会议名称(u9707 label 左:515 + u9709 input 左:582)
|
||
- 第X期(u9714「第」左:758 + u9713 input 左:783 + u9715「期」左:946)
|
||
- 会议时间(u9863 label 左:984 + u9895 input 左:1051)
|
||
- 当前阶段(u9716 label 左:1228 + u9722 select 选项:请选择/已执行/未执行)
|
||
- 查找按钮(u9710 左:1377)
|
||
表格列(10 列,按 left 升序):
|
||
- u9694 项目编号 左:302
|
||
- u9846 会议ID 左:429
|
||
- u9848 项目形式 左:521 (线上/线下/线上+线下/其他)
|
||
- u9844 会议名称 左:644
|
||
- u9850 会议开始时间 左:794
|
||
- u9852 会议结束时间 左:940
|
||
- u9854 总期数 左:1070
|
||
- u9858 期数 左:1147
|
||
- u9716 已执行未传材料 左:1232
|
||
- u9702 操作 左:1377
|
||
红色注释:
|
||
- u9768 *会议详情页,增加学会已审核及审核意见...
|
||
- u9770 *支持方状态(当前阶段)未执行/已执行未传材料/待监管/监管通过/待整改/待结算/已结算
|
||
- u9776 *支持方点击监察意见保存确认后,按钮变为查看监察意见 -->
|
||
<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-title { font-size: 22px; font-weight: 600; color: #1a1a1a; margin-bottom: 20px; }
|
||
.card { background: #fff; border-radius: 8px; padding: 20px 24px; margin-bottom: 16px; border: 1px solid #f0f0f0; }
|
||
.filter-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
|
||
.filter-field { display: flex; align-items: center; gap: 8px; }
|
||
.filter-label { font-size: 14px; color: #595959; white-space: nowrap; }
|
||
.filter-input,.filter-select,.filter-date { width: 180px; height: 32px; padding: 0 12px; border: 1px solid #d9d9d9; border-radius: 4px; font-size: 13px; color: #333; background: #fff; outline: none; }
|
||
.filter-date { width: 140px; }
|
||
.filter-range { display: flex; align-items: center; gap: 6px; }
|
||
.filter-range-sep { color: #8c8c8c; font-size: 13px; }
|
||
.filter-prefix,.filter-suffix { font-size: 13px; color: #595959; }
|
||
.filter-select { cursor: pointer; appearance: none; background: #fff url("data:image/svg+xml,%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") no-repeat right 10px center / 14px; padding-right: 28px; }
|
||
.filter-input:focus,.filter-select:focus,.filter-date:focus { border-color: #1890ff; box-shadow: 0 0 0 3px rgba(24,144,255,0.1); }
|
||
.filter-btn { height: 32px; padding: 0 20px; background: #1890ff; color: #fff; border: none; border-radius: 4px; font-size: 13px; cursor: pointer; }
|
||
.filter-btn:hover { background: #096dd9; }
|
||
.hint-red { font-size: 12px; color: #ff0000; line-height: 1.7; }
|
||
.hint-red-block { background: #fff5f5; border-left: 3px solid #ff0000; padding: 10px 14px; border-radius: 4px; margin-bottom: 12px; }
|
||
.hint-red-block .hint-red-title { font-weight: 600; margin-bottom: 4px; }
|
||
.data-card { padding: 0; overflow-x: auto; }
|
||
.data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
|
||
.data-table th { background: #fafafa; padding: 10px 12px; text-align: left; color: #1a1a1a; font-weight: 600; border-bottom: 1px solid #f0f0f0; white-space: nowrap; }
|
||
.data-table td { padding: 10px 12px; border-bottom: 1px solid #f5f5f5; color: #595959; vertical-align: middle; white-space: nowrap; }
|
||
.data-table tr:hover { background: #fafcff; }
|
||
.data-table input[type="checkbox"] { cursor: pointer; width: 14px; height: 14px; accent-color: #1890ff; }
|
||
.col-code { color: #1890ff; font-family: ui-monospace, "Courier New", monospace; }
|
||
.col-name { color: #1a1a1a; font-weight: 500; }
|
||
.col-datetime { font-family: ui-monospace, "Courier New", monospace; color: #595959; font-size: 12px; }
|
||
.col-period { color: #722ed1; font-weight: 500; cursor: pointer; }
|
||
.col-period:hover { color: #1890ff; text-decoration: underline; }
|
||
.status-tag { display: inline-block; padding: 2px 10px; border-radius: 10px; font-size: 12px; }
|
||
.status-pending { background: #fff7e6; color: #fa8c16; border: 1px solid #ffd591; }
|
||
.status-done { background: #f6ffed; color: #52c41a; border: 1px solid #b7eb8f; }
|
||
.status-warn { background: #fffbe6; color: #faad14; border: 1px solid #ffe58f; }
|
||
.status-process { background: #e6f4ff; color: #1890ff; border: 1px solid #91d5ff; }
|
||
.status-purple { background: #f9f0ff; color: #722ed1; border: 1px solid #d3adf7; }
|
||
.form-tag { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 12px; }
|
||
.form-online { background: #e6f4ff; color: #1890ff; border: 1px solid #91d5ff; }
|
||
.form-offline { background: #fff7e6; color: #fa8c16; border: 1px solid #ffd591; }
|
||
.form-mixed { background: #f9f0ff; color: #722ed1; border: 1px solid #d3adf7; }
|
||
.op-link { color: #1890ff; text-decoration: none; font-size: 13px; cursor: pointer; }
|
||
.op-link:hover { text-decoration: underline; }
|
||
|
||
/* Modal */
|
||
.modal-mask { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.45); z-index: 1000; align-items: center; justify-content: center; }
|
||
.modal-mask.show { display: flex; }
|
||
.modal { background: #fff; border-radius: 8px; width: 520px; max-width: 90vw; max-height: 90vh; overflow-y: auto; box-shadow: 0 10px 40px rgba(0,0,0,.2); }
|
||
.modal-header { padding: 20px 24px; border-bottom: 1px solid #f0f0f0; display: flex; align-items: center; justify-content: space-between; }
|
||
.modal-title { font-size: 16px; font-weight: 600; color: #1a1a1a; }
|
||
.modal-close { cursor: pointer; color: #8c8c8c; font-size: 20px; background: none; border: none; padding: 4px; line-height: 1; }
|
||
.modal-close:hover { color: #1a1a1a; }
|
||
.modal-body { padding: 24px; }
|
||
.modal-row { margin-bottom: 14px; }
|
||
.modal-row-label { font-size: 13px; color: #595959; margin-bottom: 4px; }
|
||
.modal-row-value { font-size: 14px; color: #1a1a1a; }
|
||
.opinion-box { background: #fafafa; border-left: 3px solid #1890ff; padding: 12px; border-radius: 4px; color: #595959; font-size: 13px; line-height: 1.7; }
|
||
.modal-footer { padding: 16px 24px; border-top: 1px solid #f0f0f0; text-align: right; }
|
||
.btn-default { height: 32px; padding: 0 20px; background: #fff; color: #333; border: 1px solid #d9d9d9; border-radius: 4px; font-size: 13px; cursor: pointer; }
|
||
.btn-primary { height: 32px; padding: 0 20px; background: #1890ff; color: #fff; border: 1px solid #1890ff; border-radius: 4px; font-size: 13px; cursor: pointer; margin-left: 8px; }
|
||
.btn-primary:hover { background: #096dd9; }
|
||
|
||
@media (max-width:768px) { .content { padding: 16px; } .data-table { font-size: 12px; } .modal { width: 96vw; } }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<main class="content">
|
||
<h1 class="page-title">会议列表</h1>
|
||
<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>
|
||
<input type="text" class="filter-input" placeholder="期数" style="width:80px">
|
||
<span class="filter-suffix">期</span>
|
||
</div>
|
||
<div class="filter-field">
|
||
<span class="filter-label">会议时间:</span>
|
||
<div class="filter-range">
|
||
<input type="date" class="filter-date" value="2026-01-01">
|
||
<span class="filter-range-sep">至</span>
|
||
<input type="date" class="filter-date" value="2026-12-31">
|
||
</div>
|
||
</div>
|
||
<div class="filter-field"><span class="filter-label">当前阶段:</span>
|
||
<select class="filter-select">
|
||
<option value="">请选择</option>
|
||
<option>已执行</option>
|
||
<option>未执行</option>
|
||
</select>
|
||
</div>
|
||
<button class="filter-btn">查找</button>
|
||
</div>
|
||
</div>
|
||
<div class="card data-card">
|
||
<table class="data-table">
|
||
<thead>
|
||
<tr>
|
||
<th style="width:40px"><input type="checkbox" id="selectAll"></th>
|
||
<th>项目编号</th>
|
||
<th>会议ID</th>
|
||
<th>项目形式</th>
|
||
<th>会议名称</th>
|
||
<th>会议开始时间</th>
|
||
<th>会议结束时间</th>
|
||
<th>总期数</th>
|
||
<th>期数</th>
|
||
<th>当前阶段</th>
|
||
<th>操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><input type="checkbox" class="row-check"></td><td><a class="col-code" href="javascript:void(0)">ZH-2026-658</a></td><td>5643145673</td><td><span class="form-tag form-online">线上</span></td><td><a class="col-name" href="javascript:void(0)">小牛血清创新应用研讨会</a></td><td class="col-datetime">2026-05-11 11:30</td><td class="col-datetime">2026-05-11 14:30</td><td style="text-align:center">26</td><td style="text-align:center"><a class="col-period" title="点击可筛选该系列会所有会议">第 3 期</a></td><td><span class="status-tag status-pending">待监管</span></td><td><a class="op-link" href="sponsor-meeting-detail.html">查看</a><a class="op-link" onclick="openOpinion(this)">监察意见</a></td></tr>
|
||
<tr><td><input type="checkbox" class="row-check"></td><td><a class="col-code" href="javascript:void(0)">ZH-2026-650</a></td><td>5643145674</td><td><span class="form-tag form-offline">线下</span></td><td><a class="col-name" href="javascript:void(0)">整合医学学会项目评审会</a></td><td class="col-datetime">2026-04-01 09:00</td><td class="col-datetime">2026-04-01 17:00</td><td style="text-align:center">18</td><td style="text-align:center"><a class="col-period" title="点击可筛选该系列会所有会议">第 18 期</a></td><td><span class="status-tag status-done">监管通过</span></td><td><a class="op-link" href="sponsor-meeting-detail.html">查看</a><a class="op-link" onclick="openOpinion(this)">查看监察意见</a></td></tr>
|
||
<tr><td><input type="checkbox" class="row-check"></td><td><a class="col-code" href="javascript:void(0)">ZH-2026-645</a></td><td>5643145675</td><td><span class="form-tag form-mixed">线上+线下</span></td><td><a class="col-name" href="javascript:void(0)">智慧医院建设项目方案论证会</a></td><td class="col-datetime">2026-03-15 14:00</td><td class="col-datetime">2026-03-15 16:30</td><td style="text-align:center">12</td><td style="text-align:center"><a class="col-period" title="点击可筛选该系列会所有会议">第 7 期</a></td><td><span class="status-tag status-warn">待整改</span></td><td><a class="op-link" href="sponsor-meeting-detail.html">查看</a><a class="op-link" onclick="openOpinion(this)">监察意见</a></td></tr>
|
||
<tr><td><input type="checkbox" class="row-check"></td><td><a class="col-code" href="javascript:void(0)">ZH-2026-640</a></td><td>5643145676</td><td><span class="form-tag form-online">线上</span></td><td><a class="col-name" href="javascript:void(0)">基层医疗改革试点中期评估会</a></td><td class="col-datetime">2026-02-01 09:30</td><td class="col-datetime">2026-02-01 12:00</td><td style="text-align:center">20</td><td style="text-align:center"><a class="col-period" title="点击可筛选该系列会所有会议">第 14 期</a></td><td><span class="status-tag status-purple">已结算</span></td><td><a class="op-link" href="sponsor-meeting-detail.html">查看</a><a class="op-link" onclick="openOpinion(this)">查看监察意见</a></td></tr>
|
||
<tr><td><input type="checkbox" class="row-check"></td><td><a class="col-code" href="javascript:void(0)">ZH-2026-635</a></td><td>5643145677</td><td><span class="form-tag form-offline">线下</span></td><td><a class="col-name" href="javascript:void(0)">数字化医疗转型方案评审会</a></td><td class="col-datetime">2026-01-10 10:00</td><td class="col-datetime">2026-01-10 17:00</td><td style="text-align:center">22</td><td style="text-align:center"><a class="col-period" title="点击可筛选该系列会所有会议">第 15 期</a></td><td><span class="status-tag status-purple">已结题</span></td><td><a class="op-link" href="sponsor-meeting-detail.html">查看</a><a class="op-link" onclick="openOpinion(this)">监察意见</a></td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<p class="hint-red" style="margin-top:12px">*支持方点击监察意见保存确认后,按钮变为查看监察意见</p>
|
||
<div class="hint-red-block" style="margin-top:16px">
|
||
<p class="hint-red">*会议详情页,增加学会已审核及审核意见,增加支持方监督意见详情,两个意见,合规人员能看到,执行方也可看到</p>
|
||
</div>
|
||
<div class="hint-red-block">
|
||
<p class="hint-red hint-red-title">*支持方状态(当前阶段):</p>
|
||
<p class="hint-red">未执行:会议开始时间前,显示为未执行;</p>
|
||
<p class="hint-red">已执行未传材料:合规人员未审核通过前,一直显示该状态;</p>
|
||
<p class="hint-red">待监管:支持方未填写监管意见时,显示该状态;</p>
|
||
<p class="hint-red">监管通过:支持方选择确认无误后,则显示该状态;监管通过默认只显示 1 个工作日,之后显示为待结算</p>
|
||
<p class="hint-red">待整改:监管未通过后,则显示该状态;</p>
|
||
<p class="hint-red">待结算:支持方监管通过后,1 个工作日后变为待结算,显示该状态;</p>
|
||
<p class="hint-red">已结算:合规人员当操作结算后,状态变为已结算;</p>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- 监督意见 Modal (原型 u9942) -->
|
||
<div class="modal-mask" id="opinionModal">
|
||
<div class="modal">
|
||
<div class="modal-header">
|
||
<span class="modal-title" id="modalTitle">监督意见</span>
|
||
<button class="modal-close" onclick="closeModal()">×</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="modal-row">
|
||
<div class="modal-row-label">会议名称</div>
|
||
<div class="modal-row-value" id="modalName"></div>
|
||
</div>
|
||
<!-- 编辑态:单选 + 文本框 + 字数 -->
|
||
<div id="editView">
|
||
<div class="modal-row">
|
||
<label style="display:flex;align-items:center;gap:8px;cursor:pointer">
|
||
<input type="radio" name="opinionType" value="ok" checked onchange="toggleTextarea()">
|
||
<span>确认无误</span>
|
||
</label>
|
||
</div>
|
||
<div class="modal-row">
|
||
<label style="display:flex;align-items:center;gap:8px;cursor:pointer">
|
||
<input type="radio" name="opinionType" value="fix" onchange="toggleTextarea()">
|
||
<span>存在需整改的问题</span>
|
||
</label>
|
||
</div>
|
||
<div class="modal-row" id="textareaWrap" style="display:none">
|
||
<div style="display:flex;align-items:center;gap:4px;margin-bottom:4px">
|
||
<span style="color:#ff4d4f">*</span>
|
||
<span class="modal-row-label" style="margin:0">详细意见</span>
|
||
<span style="flex:1"></span>
|
||
<span style="font-size:12px;color:#8c8c8c"><span id="charCount">0</span>/500</span>
|
||
</div>
|
||
<textarea class="modal-textarea" id="opinionText" maxlength="500" placeholder="请输入详细意见..." style="width:100%;min-height:90px;padding:8px 12px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;resize:vertical;outline:none;box-sizing:border-box;font-family:inherit" oninput="document.getElementById('charCount').textContent=this.value.length"></textarea>
|
||
</div>
|
||
<p class="hint-red">*3个工作日之内如果未填写,则默认为确认无误</p>
|
||
<p class="hint-red">*点击存在需整改的问题时,才显示详细意见</p>
|
||
</div>
|
||
<!-- 查看态:已保存的意见 -->
|
||
<div id="viewView" style="display:none">
|
||
<div class="modal-row">
|
||
<div class="modal-row-label">监督结果</div>
|
||
<div class="modal-row-value" id="viewResult"></div>
|
||
</div>
|
||
<div class="modal-row" id="viewOpinionWrap" style="display:none">
|
||
<div class="modal-row-label">详细意见</div>
|
||
<div class="opinion-box" id="viewOpinion"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer" id="modalFooter">
|
||
<button class="btn-default" onclick="closeModal()">取消</button>
|
||
<button class="btn-primary" id="saveBtn" onclick="saveOpinion()">保存</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
document.getElementById('selectAll').addEventListener('change', function () { document.querySelectorAll('.row-check').forEach(c => c.checked = this.checked); });
|
||
|
||
// 当前操作的会议数据(简化:从行内取)
|
||
function getRowData(btn) {
|
||
var tr = btn.closest('tr');
|
||
return {
|
||
name: tr.querySelector('.col-name').textContent,
|
||
stage: tr.querySelector('.status-tag').textContent,
|
||
tr: tr
|
||
};
|
||
}
|
||
|
||
function openOpinion(btn) {
|
||
var data = getRowData(btn);
|
||
var isView = btn.textContent.trim() === '查看监察意见' || data.stage !== '待监管';
|
||
document.getElementById('modalName').textContent = data.name;
|
||
if (isView) {
|
||
// 查看态(读取 data-tr 上的 data-opinion 属性,无则给默认值)
|
||
var saved = btn.getAttribute('data-opinion') || '已确认无误';
|
||
var savedFix = btn.getAttribute('data-opinion-fix') || '';
|
||
document.getElementById('viewResult').textContent = saved;
|
||
if (savedFix) {
|
||
document.getElementById('viewOpinionWrap').style.display = 'block';
|
||
document.getElementById('viewOpinion').textContent = savedFix;
|
||
}
|
||
document.getElementById('editView').style.display = 'none';
|
||
document.getElementById('viewView').style.display = 'block';
|
||
document.getElementById('modalFooter').innerHTML = '<button class="btn-default" onclick="closeModal()">关闭</button>';
|
||
} else {
|
||
// 编辑态
|
||
document.getElementById('editView').style.display = 'block';
|
||
document.getElementById('viewView').style.display = 'none';
|
||
document.getElementById('modalFooter').innerHTML = '<button class="btn-default" onclick="closeModal()">取消</button><button class="btn-primary" onclick="saveOpinion()">保存</button>';
|
||
document.querySelector('input[name="opinionType"][value="ok"]').checked = true;
|
||
toggleTextarea();
|
||
document.getElementById('opinionText').value = '';
|
||
document.getElementById('charCount').textContent = '0';
|
||
}
|
||
document.getElementById('opinionModal').classList.add('show');
|
||
}
|
||
|
||
function toggleTextarea() {
|
||
var isFix = document.querySelector('input[name="opinionType"]:checked').value === 'fix';
|
||
document.getElementById('textareaWrap').style.display = isFix ? 'block' : 'none';
|
||
}
|
||
|
||
function saveOpinion() {
|
||
var type = document.querySelector('input[name="opinionType"]:checked').value;
|
||
var text = document.getElementById('opinionText').value.trim();
|
||
if (type === 'fix' && !text) {
|
||
alert('请填写详细意见');
|
||
return;
|
||
}
|
||
// 找出当前行(简化:从 modal 反查)
|
||
var name = document.getElementById('modalName').textContent;
|
||
var rows = document.querySelectorAll('.data-table tbody tr');
|
||
for (var i = 0; i < rows.length; i++) {
|
||
var tr = rows[i];
|
||
if (tr.querySelector('.col-name').textContent === name) {
|
||
var btn = tr.querySelector('.op-link[onclick*="openOpinion"]');
|
||
if (btn) {
|
||
btn.setAttribute('data-opinion', type === 'ok' ? '已确认无误' : '存在需整改的问题');
|
||
if (type === 'fix') btn.setAttribute('data-opinion-fix', text);
|
||
btn.textContent = '查看监察意见';
|
||
}
|
||
var stage = tr.querySelector('.status-tag');
|
||
stage.className = 'status-tag status-done';
|
||
stage.textContent = '监管通过';
|
||
break;
|
||
}
|
||
}
|
||
alert('监督意见已保存');
|
||
closeModal();
|
||
}
|
||
|
||
function closeModal() { document.getElementById('opinionModal').classList.remove('show'); }
|
||
document.getElementById('opinionModal').addEventListener('click', function (e) { if (e.target === this) closeModal(); });
|
||
</script>
|
||
</body>
|
||
</html> |