44e77dcb0e
**重构前**(旧编号 02-11): - docs/02-产品需求/ → 00 产品规划/PRD - docs/03-技术架构/ → 01-05 子目录散落 - docs/04-原型设计/ → 01-02 产品设计(HTML 原型) - docs/05-原型设计/ → screens/ - docs/06-测试素材/ → 02-E2E / 03-功能 / 04-版本测试 - docs/07-项目管理/ → 任务说明书/日报/计划 - docs/08-安全审计/ → 审计报告 - docs/09-堡垒运维/ → toolbox / deploy - docs/10-项目管理/ → 任务说明书(重复) - docs/11-历史归档/ → deploy-nas-archived **重构后**(新编号 00-07,语义化): - docs/00-产品开发流程与文档管理规范.md - docs/00-版本迭代总览.md - docs/01-产品文档/ (PRD/原型/认证/会话/AI 服务/坐席/集成) - docs/02-技术文档/ (技术方案/架构图/重构记录/前端改造/实现配置) - docs/03-测试文档/ (E2E/功能用例/版本报告/缺陷单) - docs/04-运维文档/ (部署运维/运维指南) - docs/05-运营文档/ (品牌推广/用户手册) - docs/06-安全审计/ (审计报告) - docs/07-项目管理/ (任务说明书/日报/计划/看板) **净收益**: - 目录编号与产品文档管理规范对齐(按文档阶段 01-07 编号) - 消除 02-产品需求 与 10-项目管理 的编号重叠 - 子目录按文档类型分组(如 01-产品文档/00-产品规划、01-产品文档/01-认证与登录) - 把运维/安全/项目管理从 0X 散落改为 04/06/07 合计 494 文件 + 78495 行 / - 14076 行
618 lines
17 KiB
HTML
618 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
<title>H5端 - 群聊参与者展开/缩略双模式原型</title>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body {
|
|
font-family: -apple-system, 'PingFang SC', 'Helvetica Neue', sans-serif;
|
|
background: #f5f5f5;
|
|
max-width: 375px;
|
|
margin: 0 auto;
|
|
min-height: 100vh;
|
|
position: relative;
|
|
}
|
|
|
|
/* 模拟手机状态栏 */
|
|
.status-bar {
|
|
height: 44px;
|
|
background: #07C160;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #fff;
|
|
font-size: 17px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* 聊天区域 */
|
|
.chat-area {
|
|
background: #ededed;
|
|
min-height: 500px;
|
|
padding-bottom: 60px;
|
|
position: relative;
|
|
}
|
|
|
|
/* === 参与者缩略条 === */
|
|
.participant-strip {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 8px 12px;
|
|
background: #fff;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
cursor: pointer;
|
|
}
|
|
.participant-strip:hover { background: #fafafa; }
|
|
|
|
.strip-avatars {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
/* 头像基础样式 */
|
|
.avatar {
|
|
width: 28px;
|
|
height: 28px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
color: #fff;
|
|
flex-shrink: 0;
|
|
border: 2px solid transparent;
|
|
background-size: cover;
|
|
background-position: center;
|
|
}
|
|
.avatar + .avatar { margin-left: -6px; }
|
|
|
|
/* 角色边框色 */
|
|
.avatar.role-primary { border-color: #3b82f6; }
|
|
.avatar.role-collaborator { border-color: #07C160; }
|
|
.avatar.role-owner { border-color: #FF9800; }
|
|
.avatar.role-invitee { border-color: transparent; }
|
|
|
|
/* 自己高亮环 */
|
|
.avatar.is-self {
|
|
box-shadow: 0 0 0 2px #07C160;
|
|
transform: scale(1.1);
|
|
z-index: 10;
|
|
}
|
|
|
|
/* 超员 +N */
|
|
.avatar-more {
|
|
width: 28px;
|
|
height: 28px;
|
|
border-radius: 50%;
|
|
background: #e0e0e0;
|
|
color: #666;
|
|
font-size: 11px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-left: -6px;
|
|
border: 2px solid #fff;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.strip-label {
|
|
font-size: 12px;
|
|
color: #999;
|
|
margin-left: 4px;
|
|
}
|
|
|
|
/* 待加入红点角标 */
|
|
.avatar-wrap { position: relative; display: inline-flex; }
|
|
.pending-dot {
|
|
position: absolute;
|
|
top: -2px;
|
|
right: -2px;
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: #ee0a24;
|
|
border: 1.5px solid #fff;
|
|
}
|
|
|
|
/* === 底部弹出 Popup === */
|
|
.popup-overlay {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 100%;
|
|
max-width: 375px;
|
|
height: 100%;
|
|
background: rgba(0, 0, 0, 0.7);
|
|
z-index: 100;
|
|
display: none;
|
|
align-items: flex-end;
|
|
}
|
|
.popup-overlay.show { display: flex; }
|
|
|
|
.popup-content {
|
|
background: #fff;
|
|
border-radius: 16px 16px 0 0;
|
|
width: 100%;
|
|
max-height: 60vh;
|
|
overflow-y: auto;
|
|
padding: 0 0 env(safe-area-inset-bottom);
|
|
animation: slideUp 0.3s ease;
|
|
}
|
|
@keyframes slideUp {
|
|
from { transform: translateY(100%); }
|
|
to { transform: translateY(0); }
|
|
}
|
|
|
|
.popup-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 16px;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
position: sticky;
|
|
top: 0;
|
|
background: #fff;
|
|
border-radius: 16px 16px 0 0;
|
|
z-index: 1;
|
|
}
|
|
.popup-title { font-size: 16px; font-weight: 600; color: #333; }
|
|
.popup-close {
|
|
width: 24px; height: 24px;
|
|
display: flex; align-items: center; justify-content: center;
|
|
font-size: 18px; color: #999; cursor: pointer;
|
|
}
|
|
|
|
.popup-body { padding: 8px 0; }
|
|
|
|
/* 参与者列表项 */
|
|
.participant-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
padding: 12px 16px;
|
|
}
|
|
.participant-item:active { background: #f5f5f5; }
|
|
|
|
.participant-item .avatar-lg {
|
|
width: 40px;
|
|
height: 40px;
|
|
font-size: 16px;
|
|
border-width: 2px;
|
|
}
|
|
|
|
.participant-info {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
.participant-name {
|
|
font-size: 15px;
|
|
color: #333;
|
|
font-weight: 500;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
.participant-dept {
|
|
font-size: 12px;
|
|
color: #999;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
/* 角色标签 */
|
|
.role-tag {
|
|
font-size: 10px;
|
|
padding: 1px 6px;
|
|
border-radius: 4px;
|
|
font-weight: 500;
|
|
}
|
|
.role-tag.primary { background: #3b82f6; color: #fff; }
|
|
.role-tag.collaborator { background: #07C160; color: #fff; }
|
|
.role-tag.owner { background: #FF9800; color: #fff; }
|
|
.role-tag.invitee { background: #f0f0f0; color: #666; }
|
|
|
|
/* 退出按钮 */
|
|
.leave-btn {
|
|
font-size: 13px;
|
|
color: #ee0a24;
|
|
padding: 4px 12px;
|
|
border: 1px solid #ee0a24;
|
|
border-radius: 4px;
|
|
background: transparent;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* 底部输入栏模拟 */
|
|
.input-bar {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 100%;
|
|
max-width: 375px;
|
|
height: 50px;
|
|
background: #f7f7f7;
|
|
border-top: 1px solid #e0e0e0;
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 0 12px;
|
|
gap: 8px;
|
|
z-index: 10;
|
|
}
|
|
.input-bar input {
|
|
flex: 1;
|
|
height: 36px;
|
|
border: 1px solid #e0e0e0;
|
|
border-radius: 18px;
|
|
padding: 0 16px;
|
|
font-size: 14px;
|
|
background: #fff;
|
|
}
|
|
|
|
/* 控制面板 */
|
|
.control-panel {
|
|
position: fixed;
|
|
top: 10px;
|
|
right: 10px;
|
|
z-index: 200;
|
|
background: rgba(0,0,0,0.8);
|
|
border-radius: 8px;
|
|
padding: 8px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
}
|
|
.control-panel button {
|
|
font-size: 12px;
|
|
color: #fff;
|
|
background: #07C160;
|
|
border: none;
|
|
border-radius: 4px;
|
|
padding: 4px 10px;
|
|
cursor: pointer;
|
|
white-space: nowrap;
|
|
}
|
|
.control-panel button:hover { opacity: 0.85; }
|
|
|
|
/* 注释标签 */
|
|
.annotation {
|
|
position: absolute;
|
|
right: -180px;
|
|
top: 0;
|
|
width: 160px;
|
|
background: #fff3cd;
|
|
border: 1px solid #ffc107;
|
|
border-radius: 6px;
|
|
padding: 6px 10px;
|
|
font-size: 11px;
|
|
color: #856404;
|
|
line-height: 1.5;
|
|
}
|
|
.annotation::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: -20px;
|
|
top: 10px;
|
|
border: 10px solid transparent;
|
|
border-right-color: #ffc107;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 12px;
|
|
color: #999;
|
|
padding: 8px 16px 4px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* 聊天消息模拟 */
|
|
.chat-msg {
|
|
display: flex;
|
|
margin: 12px;
|
|
gap: 8px;
|
|
}
|
|
.chat-msg .msg-avatar {
|
|
width: 36px; height: 36px; border-radius: 4px;
|
|
background: #ccc; flex-shrink: 0;
|
|
display: flex; align-items: center; justify-content: center;
|
|
font-size: 14px; color: #fff;
|
|
}
|
|
.chat-msg .msg-content {
|
|
max-width: 70%;
|
|
}
|
|
.chat-msg .msg-name {
|
|
font-size: 11px; color: #999; margin-bottom: 2px;
|
|
}
|
|
.chat-msg .msg-bubble {
|
|
background: #fff; padding: 8px 12px; border-radius: 0 8px 8px 8px;
|
|
font-size: 14px; color: #333; display: inline-block;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="control-panel">
|
|
<button onclick="togglePopup()">点击缩略条展开/收起</button>
|
|
<button onclick="toggleScene()">切换场景(3人/6人/8人)</button>
|
|
</div>
|
|
|
|
<div class="status-bar">IT服务支持</div>
|
|
|
|
<div class="chat-area">
|
|
<!-- 参与者缩略条 -->
|
|
<div class="participant-strip" onclick="togglePopup()" id="strip">
|
|
<div class="strip-avatars" id="stripAvatars">
|
|
<!-- JS 动态生成 -->
|
|
</div>
|
|
<span class="strip-label" id="stripLabel">点击查看全部</span>
|
|
</div>
|
|
|
|
<!-- 聊天消息模拟 -->
|
|
<div class="chat-msg">
|
|
<div class="msg-avatar" style="background:#3b82f6">张</div>
|
|
<div class="msg-content">
|
|
<div class="msg-name">张明(主责坐席)</div>
|
|
<div class="msg-bubble">您好,您的网络问题我来帮您处理。我已经邀请了网络组的同事一起协助。</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="chat-msg">
|
|
<div class="msg-avatar" style="background:#FF9800">李</div>
|
|
<div class="msg-content">
|
|
<div class="msg-name">李四(发起人)</div>
|
|
<div class="msg-bubble">好的谢谢,我们网段的电脑都上不了网</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="chat-msg">
|
|
<div class="msg-avatar" style="background:#07C160">王</div>
|
|
<div class="msg-content">
|
|
<div class="msg-name">王五(被邀请人)</div>
|
|
<div class="msg-bubble">我看了一下交换机的日志,发现端口有异常告警,正在排查。</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 底部弹出 Popup -->
|
|
<div class="popup-overlay" id="popup">
|
|
<div class="popup-content">
|
|
<div class="popup-header">
|
|
<span class="popup-title">参与者 (<span id="totalCount">0</span>)</span>
|
|
<span class="popup-close" onclick="togglePopup()">✕</span>
|
|
</div>
|
|
<div class="popup-body" id="popupBody">
|
|
<!-- JS 动态生成 -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 底部输入栏 -->
|
|
<div class="input-bar">
|
|
<input type="text" placeholder="输入消息..." readonly>
|
|
</div>
|
|
|
|
<script>
|
|
// 角色边框色
|
|
const ROLE_COLORS = {
|
|
primary_agent: '#3b82f6',
|
|
collaborator: '#07C160',
|
|
owner: '#FF9800',
|
|
invitee: 'transparent'
|
|
};
|
|
const ROLE_LABELS = {
|
|
primary_agent: '主责坐席',
|
|
collaborator: '协作坐席',
|
|
owner: '发起人',
|
|
invitee: '被邀请人'
|
|
};
|
|
const ROLE_BG = {
|
|
primary_agent: '#3b82f6',
|
|
collaborator: '#07C160',
|
|
owner: '#FF9800',
|
|
invitee: '#bbb'
|
|
};
|
|
|
|
const MAX_AVATARS = 4; // H5端超员阈值
|
|
|
|
// 场景数据
|
|
const scenes = [
|
|
// 3人场景
|
|
[
|
|
{ id: '1', name: '张明', avatar: '', dept: 'IT支持组', role: 'primary_agent', joined: true, isSelf: false, joinedAt: '2026-07-10T10:00:00' },
|
|
{ id: '2', name: '李四', avatar: '', dept: '财务部', role: 'owner', joined: true, isSelf: true, joinedAt: '2026-07-10T10:01:00' },
|
|
{ id: '3', name: '王五', avatar: '', dept: '网络运维组', role: 'invitee', joined: true, isSelf: false, joinedAt: '2026-07-10T10:05:00' }
|
|
],
|
|
// 6人场景
|
|
[
|
|
{ id: '1', name: '张明', avatar: '', dept: 'IT支持组', role: 'primary_agent', joined: true, isSelf: false, joinedAt: '2026-07-10T10:00:00' },
|
|
{ id: '2', name: '李四', avatar: '', dept: '财务部', role: 'owner', joined: true, isSelf: true, joinedAt: '2026-07-10T10:01:00' },
|
|
{ id: '3', name: '王五', avatar: '', dept: '网络运维组', role: 'invitee', joined: true, isSelf: false, joinedAt: '2026-07-10T10:05:00' },
|
|
{ id: '4', name: '赵六', avatar: '', dept: '系统组', role: 'invitee', joined: true, isSelf: false, joinedAt: '2026-07-10T10:06:00' },
|
|
{ id: '5', name: '钱七', avatar: '', dept: '安全组', role: 'invitee', joined: false, isSelf: false, joinedAt: null },
|
|
{ id: '6', name: '孙八', avatar: '', dept: '桌面组', role: 'invitee', joined: true, isSelf: false, joinedAt: '2026-07-10T10:08:00' }
|
|
],
|
|
// 8人场景(超员)
|
|
[
|
|
{ id: '1', name: '张明', avatar: '', dept: 'IT支持组', role: 'primary_agent', joined: true, isSelf: false, joinedAt: '2026-07-10T10:00:00' },
|
|
{ id: '2', name: '李四', avatar: '', dept: '财务部', role: 'owner', joined: true, isSelf: true, joinedAt: '2026-07-10T10:01:00' },
|
|
{ id: '3', name: '王五', avatar: '', dept: '网络运维组', role: 'invitee', joined: true, isSelf: false, joinedAt: '2026-07-10T10:05:00' },
|
|
{ id: '4', name: '赵六', avatar: '', dept: '系统组', role: 'invitee', joined: true, isSelf: false, joinedAt: '2026-07-10T10:06:00' },
|
|
{ id: '5', name: '钱七', avatar: '', dept: '安全组', role: 'invitee', joined: false, isSelf: false, joinedAt: null },
|
|
{ id: '6', name: '孙八', avatar: '', dept: '桌面组', role: 'invitee', joined: true, isSelf: false, joinedAt: '2026-07-10T10:08:00' },
|
|
{ id: '7', name: '周九', avatar: '', dept: '数据库组', role: 'invitee', joined: true, isSelf: false, joinedAt: '2026-07-10T10:09:00' },
|
|
{ id: '8', name: '吴十', avatar: '', dept: '中间件组', role: 'invitee', joined: false, isSelf: false, joinedAt: null }
|
|
]
|
|
];
|
|
|
|
let currentScene = 0;
|
|
let participants = [];
|
|
|
|
function getInitial(name) {
|
|
return name ? name.charAt(0) : '?';
|
|
}
|
|
|
|
function renderStrip() {
|
|
const container = document.getElementById('stripAvatars');
|
|
const label = document.getElementById('stripLabel');
|
|
container.innerHTML = '';
|
|
|
|
// 排列:主责 → 发起人 → 被邀请人(按joinedAt)
|
|
const sorted = [...participants].sort((a, b) => {
|
|
const order = { primary_agent: 0, owner: 1, invitee: 2 };
|
|
if (order[a.role] !== order[b.role]) return order[a.role] - order[b.role];
|
|
if (a.joinedAt && b.joinedAt) return new Date(a.joinedAt) - new Date(b.joinedAt);
|
|
return 0;
|
|
});
|
|
|
|
const showCount = Math.min(sorted.length, MAX_AVATARS);
|
|
const hasPending = sorted.some(p => !p.joined);
|
|
|
|
for (let i = 0; i < showCount; i++) {
|
|
const p = sorted[i];
|
|
const wrap = document.createElement('div');
|
|
wrap.className = 'avatar-wrap';
|
|
|
|
const av = document.createElement('div');
|
|
av.className = `avatar role-${p.role}`;
|
|
if (p.isSelf) av.classList.add('is-self');
|
|
av.style.background = ROLE_BG[p.role];
|
|
av.textContent = getInitial(p.name);
|
|
|
|
// 待加入红点
|
|
if (!p.joined) {
|
|
const dot = document.createElement('div');
|
|
dot.className = 'pending-dot';
|
|
wrap.appendChild(dot);
|
|
}
|
|
|
|
wrap.appendChild(av);
|
|
container.appendChild(wrap);
|
|
}
|
|
|
|
// 超员 +N
|
|
if (sorted.length > MAX_AVATARS) {
|
|
const more = document.createElement('div');
|
|
more.className = 'avatar-more';
|
|
more.textContent = `+${sorted.length - MAX_AVATARS}`;
|
|
container.appendChild(more);
|
|
}
|
|
|
|
label.textContent = `${participants.length}位参与者${hasPending ? ' · 有待加入' : ''} · 点击查看`;
|
|
}
|
|
|
|
function renderPopup() {
|
|
const body = document.getElementById('popupBody');
|
|
const count = document.getElementById('totalCount');
|
|
count.textContent = participants.length;
|
|
body.innerHTML = '';
|
|
|
|
const sorted = [...participants].sort((a, b) => {
|
|
const order = { primary_agent: 0, owner: 1, invitee: 2 };
|
|
if (order[a.role] !== order[b.role]) return order[a.role] - order[b.role];
|
|
if (a.joinedAt && b.joinedAt) return new Date(a.joinedAt) - new Date(b.joinedAt);
|
|
return 0;
|
|
});
|
|
|
|
// 已加入
|
|
const joined = sorted.filter(p => p.joined);
|
|
const pending = sorted.filter(p => !p.joined);
|
|
|
|
if (joined.length > 0) {
|
|
const title = document.createElement('div');
|
|
title.className = 'section-title';
|
|
title.textContent = `已加入 (${joined.length})`;
|
|
body.appendChild(title);
|
|
|
|
joined.forEach(p => body.appendChild(createItem(p)));
|
|
}
|
|
|
|
if (pending.length > 0) {
|
|
const title = document.createElement('div');
|
|
title.className = 'section-title';
|
|
title.textContent = `待加入 (${pending.length})`;
|
|
body.appendChild(title);
|
|
|
|
pending.forEach(p => body.appendChild(createItem(p)));
|
|
}
|
|
}
|
|
|
|
function createItem(p) {
|
|
const item = document.createElement('div');
|
|
item.className = 'participant-item';
|
|
|
|
const av = document.createElement('div');
|
|
av.className = `avatar avatar-lg role-${p.role}`;
|
|
if (p.isSelf) av.classList.add('is-self');
|
|
av.style.background = ROLE_BG[p.role];
|
|
av.textContent = getInitial(p.name);
|
|
|
|
const info = document.createElement('div');
|
|
info.className = 'participant-info';
|
|
|
|
const nameRow = document.createElement('div');
|
|
nameRow.className = 'participant-name';
|
|
|
|
const name = document.createElement('span');
|
|
name.textContent = p.name + (p.isSelf ? '(我)' : '');
|
|
nameRow.appendChild(name);
|
|
|
|
const tag = document.createElement('span');
|
|
tag.className = `role-tag ${p.role}`;
|
|
tag.textContent = ROLE_LABELS[p.role];
|
|
nameRow.appendChild(tag);
|
|
|
|
const dept = document.createElement('div');
|
|
dept.className = 'participant-dept';
|
|
dept.textContent = p.dept + (p.joined ? '' : ' · 待加入');
|
|
|
|
info.appendChild(nameRow);
|
|
info.appendChild(dept);
|
|
|
|
item.appendChild(av);
|
|
item.appendChild(info);
|
|
|
|
// 退出按钮(仅发起人可退出)
|
|
if (p.isSelf) {
|
|
const btn = document.createElement('button');
|
|
btn.className = 'leave-btn';
|
|
btn.textContent = '退出';
|
|
btn.onclick = (e) => {
|
|
e.stopPropagation();
|
|
alert('确认退出此会话?退出后将不再接收消息。');
|
|
};
|
|
item.appendChild(btn);
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
function togglePopup() {
|
|
const popup = document.getElementById('popup');
|
|
popup.classList.toggle('show');
|
|
if (popup.classList.contains('show')) {
|
|
renderPopup();
|
|
}
|
|
}
|
|
|
|
function toggleScene() {
|
|
currentScene = (currentScene + 1) % scenes.length;
|
|
participants = JSON.parse(JSON.stringify(scenes[currentScene]));
|
|
renderStrip();
|
|
}
|
|
|
|
// 初始化
|
|
participants = JSON.parse(JSON.stringify(scenes[0]));
|
|
renderStrip();
|
|
|
|
// 点击遮罩关闭
|
|
document.getElementById('popup').addEventListener('click', (e) => {
|
|
if (e.target.id === 'popup') togglePopup();
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|