Files
wecom_it_smart_desk/docs/01-产品文档/08-集成生态/原型-REQ-集成-001-OpenClaw合规检查-v1.0.html
T
Simon facc04aa65 chore: docs 结构整改 + compose 双目录对齐(合并重建提交)
本提交为 .git 对象库损坏后的重建提交,内容等价于原先三个本地提交
(5e2fd4c2 / 57a53c98 / 5d7e1873)的累积结果,未做任何额外改动。

一、docs 结构整改(整改 #14)
根因:重构时新结构为 untracked 文件,执行 git stash(未带 -u)未纳入,
随后 git reset 拉回 HEAD 旧 tracked 树,导致旧树复活、新旧两棵目录
树并存于 docs/,共 791 文件、双分类体系冲突。

修复动作:
- b2 同名异主题文件改名迁移保全 9 个
- C 类 39 个孤立文件按主题正确归类
- A/B1 类 222 个重复文件删除(新结构已有内容副本)
- 9 个旧独有空目录删除
- 270 处内部引用按 verified 映射改写
- 整改记录 #14 登记于 04-运维文档/部署运维

结果:docs 791 → 569 文件,顶层仅规范 8 类 + 治理文件,单树恢复。
残留:约 20 处指向从未存在文件的陈旧死链,归入独立文档卫生任务。

二、compose 双目录对齐(消除踩坑 A)
- docker-compose.yml:nginx 前端挂载全部由根目录 frontend-*/dist
  改为 src/frontend-*/dist(h5 / agent / admin / terminal)
- docker-compose.dev.yml:dev 服务 build context 与卷同步改 src/
- 效果:本地 docker compose up 不再把根目录 stale dist 挂回,
  与线上一致,分叉隐患消除(已 docker compose config 校验通过)

防复发铁律:
- 重构须提交;仓库修复须 git stash -u 或先 commit
- 新结构须 git add 并提交,避免再次 untracked 复活
- H5 改动只动 src/frontend-h5/,禁改根目录遗留 frontend-*/
2026-08-07 22:31:32 +08:00

807 lines
30 KiB
HTML

<!DOCTYPE html>
<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, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: #f5f5f5;
padding: 20px;
}
.page {
background: #fff;
border-radius: 8px;
padding: 24px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
max-width: 1200px;
margin: 0 auto 20px;
}
.page-title {
font-size: 18px;
font-weight: 600;
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 1px solid #eee;
color: #333;
}
.nav {
background: #fff;
border-radius: 8px;
padding: 12px 24px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
max-width: 1200px;
margin: 0 auto 20px;
overflow-x: auto;
}
.nav ul {
list-style: none;
display: flex;
gap: 16px;
white-space: nowrap;
}
.nav li {
cursor: pointer;
padding: 8px 16px;
border-radius: 4px;
color: #666;
font-size: 14px;
}
.nav li.active {
background: #07C160;
color: #fff;
}
.nav li:hover:not(.active) {
background: #f5f5f5;
}
.card {
background: #fafafa;
border-radius: 8px;
padding: 16px;
margin-bottom: 16px;
}
.card-title {
font-weight: 500;
margin-bottom: 12px;
color: #333;
display: flex;
justify-content: space-between;
align-items: center;
}
.stat-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
margin-bottom: 20px;
}
.stat-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 8px;
padding: 20px;
color: #fff;
}
.stat-card.success {
background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
}
.stat-card.warning {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
.stat-card.info {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
.stat-value {
font-size: 28px;
font-weight: 600;
margin-bottom: 4px;
}
.stat-label {
font-size: 14px;
opacity: 0.9;
}
.form-group {
margin-bottom: 16px;
}
.form-label {
display: block;
margin-bottom: 6px;
font-weight: 500;
color: #333;
}
.form-input {
width: 100%;
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
}
.form-input:focus {
outline: none;
border-color: #07C160;
}
.btn {
padding: 8px 16px;
border-radius: 6px;
border: none;
cursor: pointer;
font-size: 13px;
font-weight: 500;
}
.btn-sm {
padding: 4px 10px;
font-size: 12px;
}
.btn-primary {
background: #07C160;
color: #fff;
}
.btn-primary:hover {
background: #06ad56;
}
.btn-default {
background: #fff;
border: 1px solid #ddd;
color: #333;
}
.btn-default:hover {
background: #f5f5f5;
}
.btn-danger {
background: #fff;
border: 1px solid #f56c6c;
color: #f56c6c;
}
.table {
width: 100%;
border-collapse: collapse;
}
.table th,
.table td {
padding: 10px 12px;
text-align: left;
border-bottom: 1px solid #eee;
font-size: 13px;
}
.table th {
background: #fafafa;
font-weight: 500;
color: #666;
}
.table tr:hover {
background: #fafafa;
}
.tag {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
}
.tag-danger {
background: #fee;
color: #f56c6c;
}
.tag-success {
background: #e8f8f0;
color: #07C160;
}
.tag-warning {
background: #fdf6ec;
color: #e6a23c;
}
.tag-info {
background: #e6f7ff;
color: #1890ff;
}
.section-title {
font-size: 16px;
font-weight: 600;
margin: 20px 0 12px;
color: #333;
}
.flex {
display: flex;
gap: 12px;
align-items: center;
}
.flex-between {
display: flex;
justify-content: space-between;
align-items: center;
}
.text-muted {
color: #999;
font-size: 13px;
}
.badge {
display: inline-flex;
align-items: center;
padding: 2px 8px;
border-radius: 10px;
font-size: 11px;
font-weight: 500;
}
.badge-primary {
background: #e6f7ff;
color: #1890ff;
}
.grid-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}
</style>
</head>
<body>
<div class="nav">
<ul>
<li class="active" onclick="switchPage(this, 'overview')">检查概览</li>
<li onclick="switchPage(this, 'strategy')">策略管理</li>
<li onclick="switchPage(this, 'channel')">渠道管理</li>
<li onclick="switchPage(this, 'datasource')">数据源</li>
<li onclick="switchPage(this, 'records')">命中记录</li>
<li onclick="switchPage(this, 'template')">通知模板</li>
<li onclick="switchPage(this, 'schedule')">计划任务</li>
</ul>
</div>
<!-- 页面1: 检查概览 -->
<div class="page" id="page-overview">
<div class="page-title">安全策略检查平台 - 检查概览</div>
<div class="stat-grid">
<div class="stat-card">
<div class="stat-value">128</div>
<div class="stat-label">总终端数</div>
</div>
<div class="stat-card warning">
<div class="stat-value">3</div>
<div class="stat-label">今日命中</div>
</div>
<div class="stat-card success">
<div class="stat-value">125</div>
<div class="stat-label">合规终端</div>
</div>
<div class="stat-card info">
<div class="stat-value">97.6%</div>
<div class="stat-label">覆盖率</div>
</div>
</div>
<div class="flex-between" style="margin-bottom: 16px;">
<div>
<button class="btn btn-primary">立即检查</button>
<button class="btn btn-default">导出报告</button>
</div>
<div class="text-muted">最后检查: 2026-07-20 08:00:00</div>
</div>
<div class="card">
<div class="card-title">最近执行记录</div>
<table class="table">
<thead>
<tr>
<th>策略</th>
<th>执行时间</th>
<th>总终端</th>
<th>命中数</th>
<th>通知成功</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="badge badge-primary">OpenClaw远程软件</span></td>
<td>2026-07-20 08:00</td>
<td>128</td>
<td>3</td>
<td>3</td>
<td><span class="tag tag-success">成功</span></td>
</tr>
<tr>
<td><span class="badge badge-primary">OpenClaw远程软件</span></td>
<td>2026-07-19 08:00</td>
<td>127</td>
<td>5</td>
<td>5</td>
<td><span class="tag tag-success">成功</span></td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- 页面2: 策略管理 -->
<div class="page" id="page-strategy" style="display: none;">
<div class="page-title">策略管理</div>
<div class="card">
<div class="card-title">
<span>安全策略列表</span>
<button class="btn btn-primary btn-sm">+ 新增策略</button>
</div>
<table class="table">
<thead>
<tr>
<th>策略ID</th>
<th>策略名称</th>
<th>检测规则</th>
<th>数据源</th>
<th>推送渠道</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>openclaw_remote</td>
<td>OpenClaw远程软件检测</td>
<td>OpenClaw/向日葵/sunflower</td>
<td>火绒API</td>
<td>企微应用 + 企微群</td>
<td><span class="tag tag-success">已启用</span></td>
<td>
<button class="btn btn-default btn-sm">编辑</button>
<button class="btn btn-danger btn-sm">停用</button>
</td>
</tr>
<tr>
<td>unknown_usb</td>
<td>未知USB设备检测</td>
<td>未登记的USB设备</td>
<td>联软/火绒</td>
<td>企微应用</td>
<td><span class="tag tag-warning">未启用</span></td>
<td>
<button class="btn btn-default btn-sm">编辑</button>
<button class="btn btn-primary btn-sm">启用</button>
</td>
</tr>
<tr>
<td>illegal_proxy</td>
<td>非法代理软件检测</td>
<td>proxy/vpn类软件</td>
<td>火绒API</td>
<td>企微应用</td>
<td><span class="tag tag-warning">未启用</span></td>
<td>
<button class="btn btn-default btn-sm">编辑</button>
<button class="btn btn-primary btn-sm">启用</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="card">
<div class="card-title">新增策略</div>
<div class="grid-2">
<div class="form-group">
<label class="form-label">策略ID</label>
<input type="text" class="form-input" placeholder="如: unknown_usb">
</div>
<div class="form-group">
<label class="form-label">策略名称</label>
<input type="text" class="form-input" placeholder="如: 未知USB设备检测">
</div>
</div>
<div class="form-group">
<label class="form-label">检测规则(关键词,多个用逗号分隔)</label>
<input type="text" class="form-input" placeholder="如: proxy, vpn, 代理">
</div>
<div class="grid-2">
<div class="form-group">
<label class="form-label">数据源</label>
<select class="form-input">
<option>火绒API</option>
<option>联软Excel</option>
<option>火绒API + 联软</option>
</select>
</div>
<div class="form-group">
<label class="form-label">推送渠道</label>
<select class="form-input">
<option>企微应用</option>
<option>企微应用 + 企微群</option>
<option>企微 + 邮件</option>
</select>
</div>
</div>
<button class="btn btn-primary">保存策略</button>
</div>
</div>
<!-- 页面3: 渠道管理 -->
<div class="page" id="page-channel" style="display: none;">
<div class="page-title">渠道管理</div>
<div class="card">
<div class="card-title">
<span>推送渠道列表</span>
<button class="btn btn-primary btn-sm">+ 新增渠道</button>
</div>
<table class="table">
<thead>
<tr>
<th>渠道ID</th>
<th>渠道名称</th>
<th>类型</th>
<th>配置参数</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>wecom_app</td>
<td>企微应用消息</td>
<td><span class="badge badge-primary">企微</span></td>
<td class="text-muted">应用ID: wx123... Secret: ****</td>
<td><span class="tag tag-success">已启用</span></td>
<td>
<button class="btn btn-default btn-sm">配置</button>
</td>
</tr>
<tr>
<td>wecom_group</td>
<td>企微群通知</td>
<td><span class="badge badge-primary">企微</span></td>
<td class="text-muted">群ID: 123456789</td>
<td><span class="tag tag-success">已启用</span></td>
<td>
<button class="btn btn-default btn-sm">配置</button>
</td>
</tr>
<tr>
<td>email</td>
<td>邮件通知</td>
<td><span class="tag tag-info">邮件</span></td>
<td class="text-muted">SMTP: smtp.example.com</td>
<td><span class="tag tag-warning">未启用</span></td>
<td>
<button class="btn btn-default btn-sm">配置</button>
<button class="btn btn-primary btn-sm">启用</button>
</td>
</tr>
<tr>
<td>sms</td>
<td>短信通知</td>
<td><span class="tag tag-info">短信</span></td>
<td class="text-muted">未配置</td>
<td><span class="tag tag-warning">未启用</span></td>
<td>
<button class="btn btn-default btn-sm">配置</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="card">
<div class="card-title">新增渠道配置</div>
<div class="grid-2">
<div class="form-group">
<label class="form-label">渠道ID</label>
<input type="text" class="form-input" placeholder="如: email">
</div>
<div class="form-group">
<label class="form-label">渠道名称</label>
<input type="text" class="form-input" placeholder="如: 邮件通知">
</div>
</div>
<div class="form-group">
<label class="form-label">渠道类型</label>
<select class="form-input">
<option value="wecom">企微应用</option>
<option value="wecom_group">企微群</option>
<option value="email">邮件</option>
<option value="sms">短信</option>
<option value="dingtalk">钉钉</option>
</select>
</div>
<div class="form-group">
<label class="form-label">配置参数</label>
<textarea class="form-input" rows="3" placeholder="JSON格式配置"></textarea>
</div>
<button class="btn btn-primary">保存渠道</button>
<button class="btn btn-default">测试连接</button>
</div>
</div>
<!-- 页面4: 数据源管理 -->
<div class="page" id="page-datasource" style="display: none;">
<div class="page-title">数据源管理</div>
<div class="card">
<div class="card-title">
<span>火绒API配置</span>
<span class="text-muted" style="font-weight: normal; font-size: 12px;">(已存在,复用现有配置)</span>
</div>
<div class="grid-2">
<div class="form-group">
<label class="form-label">服务器地址</label>
<input type="text" class="form-input" value="https://huorong.company.com" disabled>
</div>
<div class="form-group">
<label class="form-label">连接状态</label>
<div style="padding: 10px;">
<span class="tag tag-success">已连接</span>
<span class="text-muted" style="margin-left: 8px;">最后同步: 2026-07-20 08:00</span>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-title">联软数据导入</div>
<div class="form-group">
<label class="form-label">上传Excel文件</label>
<input type="file" class="form-input" accept=".xlsx,.xls">
</div>
<div class="text-muted" style="margin-bottom: 12px;">
已导入: 2026-07-19 15:30 (94条记录, 88用户, 91设备)
</div>
<button class="btn btn-primary">导入Excel</button>
<button class="btn btn-default">查看历史</button>
</div>
</div>
<!-- 页面5: 命中记录 -->
<div class="page" id="page-records" style="display: none;">
<div class="page-title">命中记录</div>
<div class="flex" style="margin-bottom: 16px;">
<input type="text" class="form-input" placeholder="搜索用户名/设备名" style="max-width: 300px;">
<select class="form-input" style="width: auto;">
<option>全部策略</option>
<option>OpenClaw远程软件</option>
<option>未知USB设备</option>
</select>
<select class="form-input" style="width: auto;">
<option>全部状态</option>
<option>待处理</option>
<option>已通知</option>
<option>已解决</option>
<option>误报</option>
</select>
<button class="btn btn-default">筛选</button>
</div>
<div class="card">
<div class="card-title">
<span>命中记录列表</span>
<span class="text-muted" style="font-weight: normal; font-size: 12px;">共 3 条记录</span>
</div>
<table class="table">
<thead>
<tr>
<th>策略</th>
<th>用户名</th>
<th>部门</th>
<th>设备名称</th>
<th>IP地址</th>
<th>命中内容</th>
<th>首次检测</th>
<th>最近检测</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="badge badge-primary">OpenClaw</span></td>
<td>zhangsan</td>
<td>研发部</td>
<td>DESKTOP-ABC123</td>
<td>10.90.5.101</td>
<td>OpenClaw</td>
<td>2026-07-18</td>
<td>2026-07-20</td>
<td><span class="tag tag-danger">待处理</span></td>
<td>
<select class="form-input" style="width: auto; padding: 4px 8px; font-size: 12px;">
<option>标记为...</option>
<option>已通知</option>
<option>已解决</option>
<option>误报</option>
</select>
</td>
</tr>
<tr>
<td><span class="badge badge-primary">OpenClaw</span></td>
<td>lisi</td>
<td>销售部</td>
<td>DESKTOP-DEF456</td>
<td>10.90.5.102</td>
<td>向日葵</td>
<td>2026-07-15</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">已通知</span></td>
<td>
<select class="form-input" style="width: auto; padding: 4px 8px; font-size: 12px;">
<option>标记为...</option>
<option selected>已解决</option>
<option>误报</option>
</select>
</td>
</tr>
<tr>
<td><span class="badge badge-primary">OpenClaw</span></td>
<td>wangwu</td>
<td>市场部</td>
<td>DESKTOP-GHI789</td>
<td>10.90.5.103</td>
<td>OpenClaw</td>
<td>2026-07-10</td>
<td>2026-07-19</td>
<td><span class="tag tag-success">已解决</span></td>
<td>
<span class="text-muted" style="font-size: 12px;">2026-07-19 IT管理员</span>
</td>
</tr>
</tbody>
</table>
</div>
<div class="card">
<div class="card-title">状态说明</div>
<div class="text-muted" style="font-size: 13px;">
<span class="tag tag-danger" style="margin-right: 8px;">待处理</span> 新检测到,未处理<br><br>
<span class="tag tag-warning" style="margin-right: 8px;">已通知</span> 已发送企微通知,等待用户处理<br><br>
<span class="tag tag-success" style="margin-right: 8px;">已解决</span> 再次检测未命中(用户已卸载)或管理员手动标记<br><br>
<span class="tag tag-info" style="margin-right: 8px;">误报</span> 管理员确认为误报
</div>
</div>
</div>
<!-- 页面6: 通知模板 -->
<div class="page" id="page-template" style="display: none;">
<div class="page-title">通知模板管理</div>
<div class="card">
<div class="card-title">模板变量说明</div>
<div class="text-muted">
<code>{username}</code> 用户名 &nbsp;
<code>{fullname}</code> 用户全名 &nbsp;
<code>{device}</code> 设备名称 &nbsp;
<code>{dept}</code> 部门 &nbsp;
<code>{software}</code> 命中内容 &nbsp;
<code>{strategy}</code> 策略名称 &nbsp;
<code>{detect_time}</code> 检测时间
</div>
</div>
<div class="card">
<div class="card-title">企微应用消息模板</div>
<div class="form-group">
<label class="form-label">策略选择</label>
<select class="form-input" style="max-width: 300px;">
<option>OpenClaw远程软件检测</option>
<option>未知USB设备检测</option>
</select>
</div>
<div class="form-group">
<label class="form-label">标题</label>
<input type="text" class="form-input" value="【安全通知】您有设备需要处理">
</div>
<div class="form-group">
<label class="form-label">正文内容</label>
<textarea class="form-input" rows="6">尊敬的 {fullname} 您好:
经检测,您使用的设备 {device}(IP: {ip})安装了非授权软件 {software},请及时卸载。
策略:{strategy}
检测时间:{detect_time}
如有疑问,请联系IT部门。</textarea>
</div>
<button class="btn btn-primary">保存模板</button>
<button class="btn btn-default">预览效果</button>
</div>
<div class="card">
<div class="card-title">企微群通知模板(部门汇总)</div>
<div class="form-group">
<label class="form-label">标题</label>
<input type="text" class="form-input" value="【{dept}部门安全合规周报】">
</div>
<div class="form-group">
<label class="form-label">正文内容</label>
<textarea class="form-input" rows="4">部门:{dept}
命中数量:{count}台
详情:
{detail}
请部门负责人督促相关人员及时处理。</textarea>
</div>
<div class="flex">
<input type="checkbox" id="notifyDept" checked>
<label for="notifyDept">启用部门负责人汇总通知</label>
</div>
</div>
</div>
<!-- 页面7: 计划任务 -->
<div class="page" id="page-schedule" style="display: none;">
<div class="page-title">计划任务管理</div>
<div class="card">
<div class="card-title">活动期间配置</div>
<div class="grid-2">
<div class="form-group">
<label class="form-label">活动开始日期</label>
<input type="date" class="form-input" value="2026-07-20">
</div>
<div class="form-group">
<label class="form-label">活动结束日期</label>
<input type="date" class="form-input" value="2026-09-30">
</div>
</div>
<div class="flex">
<input type="checkbox" id="activityEnabled" checked>
<label for="activityEnabled">启用活动期间自动检查</label>
</div>
</div>
<div class="card">
<div class="card-title">策略定时配置</div>
<table class="table">
<thead>
<tr>
<th>策略</th>
<th>执行时间</th>
<th>频率</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>OpenClaw远程软件检测</td>
<td><input type="time" class="form-input" value="08:00" style="width: 120px;"></td>
<td>每天</td>
<td><span class="tag tag-success">已启用</span></td>
<td><button class="btn btn-default btn-sm">编辑</button></td>
</tr>
<tr>
<td>未知USB设备检测</td>
<td><input type="time" class="form-input" value="09:00" style="width: 120px;"></td>
<td>每周一</td>
<td><span class="tag tag-warning">已暂停</span></td>
<td><button class="btn btn-default btn-sm">编辑</button></td>
</tr>
</tbody>
</table>
</div>
<div class="card">
<div class="card-title">白名单管理</div>
<div class="form-group">
<label class="form-label">添加白名单用户/终端</label>
<input type="text" class="form-input" placeholder="输入用户名或设备名,多个用逗号分隔">
</div>
<button class="btn btn-default">添加</button>
<div class="text-muted" style="margin-top: 12px;">
当前白名单: 2项 (IT管理员, 测试设备)
</div>
</div>
</div>
<script>
function switchPage(el, pageId) {
document.querySelectorAll('.nav li').forEach(li => li.classList.remove('active'));
el.classList.add('active');
document.querySelectorAll('.page').forEach(page => page.style.display = 'none');
document.getElementById('page-' + pageId).style.display = 'block';
}
</script>
</body>
</html>