feat: 邀请函邮件发送 + 首次设密/密码为空 + 姓名单一可信源
邀请发送 (菜单暂隐藏, 待确认参数见 发送邀请-待确认参数.md): - 后端: BizInvite / BizInviteRecipient + Controller/Service/Mapper/XML - 邮件: InviteMailSender (spring-boot-starter-mail SMTP) + application*.yml 邮件配置 - 上传进度: UploadProgressRegistry + UploadProgressController - 前端: InviteList / InviteNew / InviteDetail / InviteView + api/business/invite.js - 原型: proto/html/components/invite-detail / new-invitation / send-invitation 登录/账号: - 首次设密: /getInfo 返回 isPasswordEmpty, SysProfileController 密码为空时跳过旧密码校验, ForcePasswordDialog 强制弹窗 - 姓名单一可信源 resolveDisplayName: doctor→biz_expert.name, sponsor/executor→biz_person.name, 其余回退 nick_name - OA compliance 门禁改为按手机号查 ecology 视图 (不再限定 manager/leader) 其它: - OSS zip 在线查看 (列清单+取单文件, 公开只读) + SecurityConfig permitAll - doctor 项目详情 ProjectDetail.vue - 数据库/测试/设计文档 (md) 入库
This commit is contained in:
@@ -0,0 +1,339 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
角色: 合规人员(manager)
|
||||
父级: manager.html
|
||||
进入: send-invitation.html 「查看」按钮
|
||||
原型: 合规系统0904/专家列表.html (页面标题就是"邀请详情",面包屑 "发送邀请 > 邀请详情")
|
||||
============================================================
|
||||
对应原型元素:
|
||||
面包屑(u6333) 发送邀请 > 邀请详情
|
||||
h3 邀请详情(u6321)
|
||||
顶部信息(会议名称u6315/项目编号u6317/期数u6319)
|
||||
hint 提示(u6341)
|
||||
h3 邀请专家列表(u6343)
|
||||
table 列: 专家姓名(u6323)/手机号(u6339)/邮箱地址(u6329)
|
||||
发送时间(u6347)/确认时间(u6359)
|
||||
确认状态(u6345)/发送状态(u6392)/备注(u6394)
|
||||
统计: 发送数量(u6388)/成功数量(u6477)/确认数量(u6481)
|
||||
hint(u6414) 备注为空默认
|
||||
按钮: 导出(u6385) / 返回(u6381)
|
||||
hint(u6386) 导出文件名规则
|
||||
============================================================
|
||||
-->
|
||||
<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; }
|
||||
|
||||
.breadcrumb {
|
||||
font-size: 13px;
|
||||
color: #8c8c8c;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.breadcrumb a { color: #1890ff; text-decoration: none; }
|
||||
.breadcrumb a:hover { text-decoration: underline; }
|
||||
|
||||
.page-title {
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* 顶部信息(对应原型 y=262/316/366, 左 3 行=会议信息 + 右 3 行=统计) */
|
||||
.info-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
column-gap: 32px;
|
||||
row-gap: 6px;
|
||||
background: #fff;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 8px;
|
||||
padding: 16px 24px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.info-row .info-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 14px;
|
||||
padding: 6px 0;
|
||||
}
|
||||
.info-row .info-cell .lbl {
|
||||
color: #8c8c8c;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.info-row .info-cell .val {
|
||||
color: #1a1a1a;
|
||||
font-weight: 500;
|
||||
}
|
||||
.info-row .info-cell.stats .val {
|
||||
color: #1890ff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* hint(对应原型 u6341 短信邮箱提示) */
|
||||
.hint-grey {
|
||||
color: #8c8c8c;
|
||||
font-size: 12px;
|
||||
margin: 8px 0 16px;
|
||||
}
|
||||
.hint-red {
|
||||
color: #ff4d4f;
|
||||
font-size: 12px;
|
||||
margin: 8px 0 16px;
|
||||
}
|
||||
|
||||
/* 卡片 */
|
||||
.card {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #f0f0f0;
|
||||
margin-bottom: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.card-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
/* 表格容器 */
|
||||
.table-wrap { overflow-x: auto; }
|
||||
|
||||
/* 表格 */
|
||||
.data-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 12px;
|
||||
}
|
||||
.data-table thead th {
|
||||
background: #fafafa;
|
||||
padding: 10px 12px;
|
||||
text-align: left;
|
||||
color: #1a1a1a;
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.data-table tbody td {
|
||||
padding: 10px 12px;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
color: #595959;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.data-table tbody tr:last-child td { border-bottom: none; }
|
||||
.data-table tbody tr:hover { background: #fafcff; }
|
||||
|
||||
/* 状态标签 */
|
||||
.status-tag {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.status-confirmed { background: #f6ffed; color: #389e0d; border: 1px solid #b7eb8f; }
|
||||
.status-pending { background: #fff7e6; color: #d46b08; border: 1px solid #ffd591; }
|
||||
.status-success { background: #f6ffed; color: #389e0d; border: 1px solid #b7eb8f; }
|
||||
.status-failed { background: #fff1f0; color: #cf1322; border: 1px solid #ffa39e; }
|
||||
|
||||
/* 底部操作区 */
|
||||
.form-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.btn {
|
||||
height: 32px;
|
||||
padding: 0 20px;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
min-width: 80px;
|
||||
}
|
||||
.btn-primary {
|
||||
background: #1890ff;
|
||||
color: #fff;
|
||||
border: 1px solid #1890ff;
|
||||
}
|
||||
.btn-primary:hover { background: #096dd9; border-color: #096dd9; }
|
||||
.btn-default {
|
||||
background: #fff;
|
||||
color: #333;
|
||||
border: 1px solid #797979;
|
||||
}
|
||||
.btn-default:hover { border-color: #1890ff; color: #1890ff; }
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.info-row { grid-template-columns: 1fr; row-gap: 8px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="content">
|
||||
|
||||
<!-- 面包屑(对应原型 u6333) -->
|
||||
<div class="breadcrumb">
|
||||
<a href="javascript:void(0)" onclick="goBack()">发送邀请</a> >
|
||||
<span>邀请详情</span>
|
||||
</div>
|
||||
|
||||
<!-- 页面标题(对应原型 u6321) -->
|
||||
<h1 class="page-title">邀请详情</h1>
|
||||
|
||||
<!-- 顶部信息(对应原型 y=262/316/366, 左 3 行=会议信息, 右 3 行=统计) -->
|
||||
<div class="info-row">
|
||||
<!-- 左列: 会议信息(对应 u6317/6315/6319) -->
|
||||
<div class="info-cell">
|
||||
<span class="lbl">项目编号:</span>
|
||||
<span class="val" id="d_projectNo">ZH-2026-658</span>
|
||||
</div>
|
||||
<div class="info-cell">
|
||||
<span class="lbl">会议名称:</span>
|
||||
<span class="val" id="d_meetingName">小牛血清创新应用研讨会</span>
|
||||
</div>
|
||||
<div class="info-cell">
|
||||
<span class="lbl">期数:</span>
|
||||
<span class="val" id="d_period">第 5 期</span>
|
||||
</div>
|
||||
<!-- 右列: 统计(对应 u6388/6477/6481) -->
|
||||
<div class="info-cell stats">
|
||||
<span class="lbl">发送数量:</span>
|
||||
<span class="val" id="s_total">6</span>
|
||||
</div>
|
||||
<div class="info-cell stats">
|
||||
<span class="lbl">成功数量:</span>
|
||||
<span class="val" id="s_success">5</span>
|
||||
</div>
|
||||
<div class="info-cell stats">
|
||||
<span class="lbl">确认数量:</span>
|
||||
<span class="val" id="s_confirmed">2</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- hint(对应原型 u6341) -->
|
||||
<p class="hint-grey">*短信和邮箱收到的是同一邀请链接,无论点击哪个进行确认,确认状态都是统一的</p>
|
||||
|
||||
<!-- 邀请专家列表(对应原型 u6343 标题) -->
|
||||
<div class="card">
|
||||
<div class="card-title">邀请专家列表</div>
|
||||
<div class="table-wrap">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>专家姓名</th>
|
||||
<th>手机号</th>
|
||||
<th>邮箱地址</th>
|
||||
<th>发送时间</th>
|
||||
<th>发送状态</th>
|
||||
<th>确认状态</th>
|
||||
<th>确认时间</th>
|
||||
<th>备注</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>张三</td>
|
||||
<td>13548976548</td>
|
||||
<td>zhengwg8976@126.com</td>
|
||||
<td>2026.09.03</td>
|
||||
<td>2026.09.05</td>
|
||||
<td><span class="status-tag status-confirmed">已确认</span></td>
|
||||
<td><span class="status-tag status-success">发送成功</span></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>李四</td>
|
||||
<td>13548971234</td>
|
||||
<td>13548976@qq.com</td>
|
||||
<td>2026.09.03</td>
|
||||
<td></td>
|
||||
<td><span class="status-tag status-pending">未确认</span></td>
|
||||
<td><span class="status-tag status-success">发送成功</span></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>张三</td>
|
||||
<td>13548976548</td>
|
||||
<td>zhengwg8976@126.com</td>
|
||||
<td>2026.09.03</td>
|
||||
<td>2026.09.05</td>
|
||||
<td><span class="status-tag status-confirmed">已确认</span></td>
|
||||
<td><span class="status-tag status-success">发送成功</span></td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>张三</td>
|
||||
<td>13548976548</td>
|
||||
<td>zhengwg8976@126.com</td>
|
||||
<td>2026.09.03</td>
|
||||
<td></td>
|
||||
<td><span class="status-tag status-pending">未确认</span></td>
|
||||
<td><span class="status-tag status-success">发送成功</span></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>张三</td>
|
||||
<td>13548976548</td>
|
||||
<td>zhengwg8976@126.com</td>
|
||||
<td>2026.09.03</td>
|
||||
<td></td>
|
||||
<td><span class="status-tag status-pending">未确认</span></td>
|
||||
<td><span class="status-tag status-success">发送成功</span></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>张三</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>2026.09.03</td>
|
||||
<td></td>
|
||||
<td><span class="status-tag status-confirmed">已确认</span></td>
|
||||
<td><span class="status-tag status-failed">发送失败</span></td>
|
||||
<td>未查到联系方式</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- hint(对应原型 u6414 备注为空默认规则) -->
|
||||
<p class="hint-grey" style="padding:12px 20px">*备注为空的,发送状态默认为发送成功,确认状态默认为已确认</p>
|
||||
</div>
|
||||
|
||||
<!-- 操作(对应原型 u6385 导出 / u6381 返回) -->
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn btn-primary" onclick="alert('导出专家列表 Excel')">导出</button>
|
||||
<button type="button" class="btn btn-default" onclick="goBack()">返回</button>
|
||||
</div>
|
||||
<p class="hint-grey">*导出表项与专家列表表项一致,导出文件名称为:项目编号+会议名称+期数</p>
|
||||
|
||||
</main>
|
||||
|
||||
<script>
|
||||
function goBack() {
|
||||
try {
|
||||
if (window.parent && window.parent.document.getElementById('contentFrame')) {
|
||||
window.parent.document.getElementById('contentFrame').src = 'send-invitation.html';
|
||||
} else {
|
||||
history.back();
|
||||
}
|
||||
} catch (e) { history.back(); }
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user