Files
guoju0808/proto/html/components/sponsor-people.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

146 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<!-- 角色:赞助方 父级:sponsor.html 原型:原型/人员管理_1.html
补全(2026-08-08 测试反馈):原型里的红色注释文字(后端开发参考)
- u10474 左:275 上:270 颜色:#FF0000 "*新建时,管理员只能新建监察员"
- u10485 左:449 上:203 颜色:#FF0000 "*批量导入模板与列表表项一致"
- u10487 左:1213 上:373 颜色:#FF0000 "*点击禁用后,状态变为禁用,按钮变成恢复;禁用后,账号无法登录,提示请联系管理员" -->
<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{width:160px;height:32px;padding:0 12px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;color:#333;outline:none}
.filter-input:focus{border-color:#1890ff;box-shadow:0 0 0 3px rgba(24,144,255,.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}
.action-bar{display:flex;gap:12px;margin-bottom:16px;align-items:center;flex-wrap:wrap}
.primary-btn{height:32px;padding:0 20px;background:#1890ff;color:#fff;border:none;border-radius:4px;font-size:13px;cursor:pointer}.primary-btn:hover{background:#096dd9}
.default-btn{height:32px;padding:0 20px;background:#fff;color:#333;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;cursor:pointer}.default-btn:hover{border-color:#1890ff;color:#1890ff}
.hint-red{font-size:12px;color:#ff0000;line-height:1.6}
.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}.data-table tr:hover{background:#fafcff}
.data-table input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:#1890ff}
.col-name{color:#1a1a1a;font-weight:500}
.op-link{color:#1890ff;text-decoration:none;font-size:13px;margin-right:8px;cursor:pointer}.op-link:last-child{margin-right:0}.op-link:hover{text-decoration:underline}
.op-link.danger{color:#ff4d4f}.op-link.danger:hover{color:#cf1322}
.status-tag{display:inline-block;padding:2px 8px;border-radius:10px;font-size:12px;font-weight:500}
.status-tag.active{background:#f6ffed;color:#52c41a;border:1px solid #b7eb8f}
.status-tag.disabled{background:#fff1f0;color:#f5222d;border:1px solid #ffa39e}
/* 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:16px}
.modal-row-label{font-size:13px;color:#595959;margin-bottom:6px}
.modal-input{width:100%;height:32px;padding:0 12px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;color:#333;outline:none;box-sizing:border-box}
.modal-input:focus{border-color:#1890ff;box-shadow:0 0 0 3px rgba(24,144,255,.1)}
.modal-footer{padding:16px 24px;border-top:1px solid #f0f0f0;text-align:right;display:flex;gap:8px;justify-content:flex-end}
.modal-footer .default-btn,.modal-footer .primary-btn{height:32px;padding:0 20px;font-size:13px}
@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="输入工作单位"></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="输入职务"></div>
<button class="filter-btn">查找</button>
</div>
</div>
<div class="action-bar">
<button class="primary-btn" onclick="goNew()">新建人员</button>
<button class="default-btn" onclick="openImport()">批量导入</button>
<span class="hint-red">*新建时,管理员只能新建监察员</span>
<span class="hint-red">*批量导入模板与列表表项一致</span>
</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>手机号</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-name" href="javascript:void(0)">张三</a></td><td>13534621147</td><td>北京XXXX有限公司</td><td>会务部</td><td>经理</td><td><span class="status-tag active">启用</span></td><td><a class="op-link" href="sponsor-view.html">查看</a><a class="op-link" href="sponsor-new-person.html">编辑</a><a class="op-link danger" href="javascript:void(0)" onclick="toggleDisable(this)">禁用</a></td></tr>
<tr><td><input type="checkbox" class="row-check"></td><td><a class="col-name" href="javascript:void(0)">李四</a></td><td>13534621148</td><td>北京XXXX有限公司</td><td>会务部</td><td>专员</td><td><span class="status-tag active">启用</span></td><td><a class="op-link" href="sponsor-view.html">查看</a><a class="op-link" href="sponsor-new-person.html">编辑</a><a class="op-link danger" href="javascript:void(0)" onclick="toggleDisable(this)">禁用</a></td></tr>
<tr><td><input type="checkbox" class="row-check"></td><td><a class="col-name" href="javascript:void(0)">王五</a></td><td>13534621149</td><td>北京XXXX有限公司</td><td>会务部</td><td>主管</td><td><span class="status-tag disabled">禁用</span></td><td><a class="op-link" href="sponsor-view.html">查看</a><a class="op-link" href="sponsor-new-person.html">编辑</a><a class="op-link" href="javascript:void(0)" onclick="toggleDisable(this)">恢复</a></td></tr>
<tr><td><input type="checkbox" class="row-check"></td><td><a class="col-name" href="javascript:void(0)">赵六</a></td><td>13534621150</td><td>北京XXXX有限公司</td><td>会务部</td><td>专员</td><td><span class="status-tag active">启用</span></td><td><a class="op-link" href="sponsor-view.html">查看</a><a class="op-link" href="sponsor-new-person.html">编辑</a><a class="op-link danger" href="javascript:void(0)" onclick="toggleDisable(this)">禁用</a></td></tr>
<tr><td><input type="checkbox" class="row-check"></td><td><a class="col-name" href="javascript:void(0)">钱七</a></td><td>13534621151</td><td>北京XXXX有限公司</td><td>会务部</td><td>经理</td><td><span class="status-tag active">启用</span></td><td><a class="op-link" href="sponsor-view.html">查看</a><a class="op-link" href="sponsor-new-person.html">编辑</a><a class="op-link danger" href="javascript:void(0)" onclick="toggleDisable(this)">禁用</a></td></tr>
</tbody>
</table>
</div>
<p class="hint-red" style="margin-top:12px">*点击禁用后,状态变为禁用,按钮变成恢复;禁用后,账号无法登录,提示请联系管理员</p>
</main>
<!-- Modal: 批量导入 (原型 u10561) -->
<div class="modal-mask" id="importModal">
<div class="modal">
<div class="modal-header">
<span class="modal-title">批量导入</span>
<button class="modal-close" onclick="closeImport()">×</button>
</div>
<div class="modal-body">
<div class="modal-row">
<div class="modal-row-label">选择文件</div>
<div style="display:flex;align-items:center;gap:8px">
<input type="text" class="modal-input" id="importFileName" placeholder="未选择文件" readonly style="flex:1">
<input type="file" id="importFile" accept=".xls,.xlsx" style="display:none" onchange="document.getElementById('importFileName').value=this.files[0]?this.files[0].name:''">
<button type="button" class="default-btn" onclick="document.getElementById('importFile').click()">浏览</button>
<button type="button" class="primary-btn" onclick="uploadFile()">上传</button>
</div>
</div>
<div class="modal-row">
<a href="javascript:void(0)" class="op-link" onclick="downloadTemplate()" style="display:inline-flex;align-items:center;gap:4px">
<span style="font-size:14px">📥</span> 批量导入模板下载
</a>
</div>
<p class="hint-red">*批量导入模板xls与列表表项一致</p>
</div>
<div class="modal-footer">
<button type="button" class="default-btn" onclick="closeImport()">取消</button>
<button type="button" class="primary-btn" onclick="confirmImport()">确定</button>
</div>
</div>
</div>
<script>
document.getElementById('selectAll').addEventListener('change',function(){document.querySelectorAll('.row-check').forEach(c=>c.checked=this.checked)});
function toggleDisable(btn){
var tr=btn.closest('tr');
var tag=tr.querySelector('.status-tag');
if(btn.textContent.trim()==='禁用'){
tag.className='status-tag disabled';tag.textContent='禁用';
btn.textContent='恢复';btn.classList.remove('danger');
btn.style.color='#52c41a';
}else{
tag.className='status-tag active';tag.textContent='启用';
btn.textContent='禁用';btn.classList.add('danger');
btn.style.color='#ff4d4f';
}
}
function goNew(){
try{if(window.parent&&window.parent.document.getElementById('contentFrame')){window.parent.document.getElementById('contentFrame').src='sponsor-new-person.html'}else{window.location.href='sponsor-new-person.html'}}catch(e){window.location.href='sponsor-new-person.html'}
}
function openImport(){document.getElementById('importFileName').value='';document.getElementById('importFile').value='';document.getElementById('importModal').classList.add('show')}
function closeImport(){document.getElementById('importModal').classList.remove('show')}
function uploadFile(){
var f=document.getElementById('importFile').files[0];
if(!f){alert('请先选择文件');return}
alert('已上传文件:'+f.name+'\n(后端解析逻辑待对接)');
}
function downloadTemplate(){alert('下载批量导入模板.xlsx\n(后端提供模板文件接口待对接)')}
function confirmImport(){alert('导入完成\n(后端处理逻辑待对接)');closeImport()}
</script>
</body>
</html>