facc04aa65
本提交为 .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-*/
378 lines
21 KiB
HTML
378 lines
21 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
||
<meta http-equiv="Pragma" content="no-cache">
|
||
<meta http-equiv="Expires" content="0">
|
||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><text y='14' font-size='14'>📋</text></svg>">
|
||
<title>早班巡检报告 · 2026-08-06 06:00 · v3.0</title>
|
||
<style>
|
||
:root {
|
||
--accent: #07C160;
|
||
--accent-soft: #E7F8EF;
|
||
--warn: #FA9D3B;
|
||
--danger: #FA5151;
|
||
--info: #10AEFF;
|
||
--text: #1F2329;
|
||
--text-soft: #646A73;
|
||
--bg: #FFFFFF;
|
||
--bg-soft: #F7F8FA;
|
||
--border: #DEE0E3;
|
||
--shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||
--radius: 8px;
|
||
}
|
||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||
color: var(--text);
|
||
background: var(--bg-soft);
|
||
line-height: 1.6;
|
||
font-size: 14px;
|
||
}
|
||
.container { max-width: 1080px; margin: 0 auto; padding: 32px 24px 64px; }
|
||
header {
|
||
background: linear-gradient(135deg, var(--accent) 0%, #06AD56 100%);
|
||
color: #fff;
|
||
padding: 32px;
|
||
border-radius: var(--radius);
|
||
box-shadow: var(--shadow);
|
||
margin-bottom: 24px;
|
||
}
|
||
header h1 { font-size: 26px; font-weight: 600; margin-bottom: 8px; }
|
||
header .meta { font-size: 13px; opacity: 0.92; }
|
||
header .meta span { margin-right: 18px; }
|
||
header .meta strong { font-weight: 600; }
|
||
h2 {
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
margin: 32px 0 14px;
|
||
padding-left: 10px;
|
||
border-left: 4px solid var(--accent);
|
||
}
|
||
.summary-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||
gap: 12px;
|
||
margin-bottom: 8px;
|
||
}
|
||
.summary-card {
|
||
background: #fff;
|
||
padding: 14px 16px;
|
||
border-radius: var(--radius);
|
||
box-shadow: var(--shadow);
|
||
text-align: center;
|
||
}
|
||
.summary-card .num { font-size: 24px; font-weight: 700; color: var(--accent); }
|
||
.summary-card .label { font-size: 12px; color: var(--text-soft); margin-top: 4px; }
|
||
.summary-card.warn .num { color: var(--warn); }
|
||
.summary-card.danger .num { color: var(--danger); }
|
||
.summary-card.info .num { color: var(--info); }
|
||
table { width: 100%; border-collapse: collapse; background: #fff; border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; margin-bottom: 24px; }
|
||
th, td { padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--border); vertical-align: top; }
|
||
th { background: var(--bg-soft); font-size: 12px; font-weight: 600; color: var(--text-soft); }
|
||
tr:last-child td { border-bottom: none; }
|
||
.badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
|
||
.badge.p0 { background: #FEE; color: var(--danger); border: 1px solid var(--danger); }
|
||
.badge.p1 { background: #FFF3E0; color: var(--warn); border: 1px solid var(--warn); }
|
||
.badge.decide { background: #E6F4FF; color: var(--info); border: 1px solid var(--info); }
|
||
.badge.doing { background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent); }
|
||
.badge.ok { background: var(--accent-soft); color: var(--accent); }
|
||
.badge.fail { background: #FEE; color: var(--danger); }
|
||
code { background: var(--bg-soft); padding: 2px 6px; border-radius: 3px; font-family: "Cascadia Code", Consolas, monospace; font-size: 12px; }
|
||
.alert { background: #FFF8E6; border-left: 4px solid var(--warn); padding: 12px 16px; margin: 16px 0; border-radius: 4px; }
|
||
.alert.danger { background: #FEE; border-left-color: var(--danger); }
|
||
.alert strong { display: block; margin-bottom: 4px; }
|
||
.legend { color: var(--text-soft); font-size: 12px; margin-top: 4px; margin-bottom: 16px; }
|
||
footer { margin-top: 32px; padding-top: 16px; border-top: 1px solid var(--border); color: var(--text-soft); font-size: 12px; text-align: center; }
|
||
ul.condensed { list-style: none; padding: 0; }
|
||
ul.condensed li { padding: 8px 12px; border-bottom: 1px dashed var(--border); background: #fff; }
|
||
ul.condensed li:last-child { border-bottom: none; }
|
||
ul.condensed li:first-child { border-radius: var(--radius) var(--radius) 0 0; }
|
||
ul.condensed li:last-child { border-radius: 0 0 var(--radius) var(--radius); box-shadow: var(--shadow); }
|
||
|
||
.filter-bar { display: flex; flex-wrap: wrap; gap: 8px; margin: 16px 0 8px; padding: 12px 14px; background: #fff; border-radius: var(--radius); box-shadow: var(--shadow); align-items: center; }
|
||
.filter-bar .filter-label { font-size: 12px; color: var(--text-soft); font-weight: 600; margin-right: 4px; }
|
||
.filter-btn { cursor: pointer; border: 1px solid var(--border); background: #fff; color: var(--text-soft); padding: 6px 12px; border-radius: 16px; font-size: 12px; font-weight: 600; transition: all 0.15s ease; user-select: none; }
|
||
.filter-btn:hover { transform: translateY(-1px); box-shadow: 0 2px 6px rgba(0,0,0,0.08); }
|
||
.filter-btn.active { color: #fff; border-color: transparent; }
|
||
.filter-btn[data-cat="all"].active { background: var(--text); }
|
||
.filter-btn[data-cat="p0"].active { background: var(--danger); }
|
||
.filter-btn[data-cat="decide"].active { background: var(--info); }
|
||
.filter-btn[data-cat="doing"].active { background: var(--accent); }
|
||
.filter-btn[data-cat="server"].active { background: var(--danger); }
|
||
.filter-btn[data-cat="code"].active { background: #8B5CF6; }
|
||
.filter-btn[data-cat="security"].active { background: #DC2626; }
|
||
.filter-btn[data-cat="history"].active { background: #64748B; }
|
||
.filter-btn .badge-count { display: inline-block; margin-left: 6px; padding: 1px 6px; background: rgba(0,0,0,0.08); border-radius: 8px; font-size: 10px; }
|
||
.filter-btn.active .badge-count { background: rgba(255,255,255,0.25); }
|
||
.hidden { display: none !important; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
|
||
<header>
|
||
<h1>📋 早班巡检报告 · IT 智能服务台</h1>
|
||
<div class="meta">
|
||
<span>📅 <strong>2026-08-06 06:00</strong>(GMT+8)</span>
|
||
<span>🛰️ 服务器 <strong>10.90.5.110</strong></span>
|
||
<span>📄 看板 <strong>v1.9.0-DRAFT</strong></span>
|
||
<span>🤖 执行 <strong>Duckula</strong></span>
|
||
<span>📦 看板源 <code>docs/07-项目管理/项目状态看板.md</code></span>
|
||
</div>
|
||
</header>
|
||
|
||
|
||
<div class="summary-grid">
|
||
<div class="summary-card danger"><div class="num">5</div><div class="label">🔴 P0 必做</div></div>
|
||
<div class="summary-card info"><div class="num">2</div><div class="label">🟢 等决策</div></div>
|
||
<div class="summary-card"><div class="num">1</div><div class="label">⏳ 进行中</div></div>
|
||
<div class="summary-card danger"><div class="num">2</div><div class="label">🖥️ 服务器异常项</div></div>
|
||
</div>
|
||
|
||
|
||
<!-- 分类筛选 -->
|
||
<div class="filter-bar">
|
||
<span class="filter-label">🔍 分类筛选</span>
|
||
<button class="filter-btn active" data-cat="all">全部<span class="badge-count">11</span></button>
|
||
<button class="filter-btn" data-cat="p0">🔴 P0<span class="badge-count">5</span></button>
|
||
<button class="filter-btn" data-cat="decide">🟢 等决策<span class="badge-count">2</span></button>
|
||
<button class="filter-btn" data-cat="doing">⏳ 进行中<span class="badge-count">1</span></button>
|
||
<button class="filter-btn" data-cat="server">🖥️ 服务器<span class="badge-count">8</span></button>
|
||
<button class="filter-btn" data-cat="code">🔍 代码<span class="badge-count">5</span></button>
|
||
<button class="filter-btn" data-cat="security">🔐 安全<span class="badge-count">4</span></button>
|
||
<button class="filter-btn" data-cat="history">🔄 对比/关注<span class="badge-count">5</span></button>
|
||
</div>
|
||
|
||
<!-- P0 必做 -->
|
||
<h2 data-section="p0">🔴 P0 必做(高优先级)</h2>
|
||
<p class="legend">本次巡检最高优先级阻塞 / 待修复项</p>
|
||
<table>
|
||
<thead>
|
||
<tr><th>编号</th><th>任务</th><th>类别</th><th>说明</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr data-cat="p0">
|
||
<td><span class="badge p0">P0-1</span></td>
|
||
<td><code>/itportal/</code> 入口 500 错误</td>
|
||
<td>♻️ 历史遗留</td>
|
||
<td>2026-08-06 06:00 jumpserver-V2 实测仍 500,nginx error: <code>rewrite or internal redirection cycle while internally redirecting to "/itportal/index.html"</code>。根因:容器内 <code>/usr/share/nginx/html/itportal/</code> 空目录 + nginx <code>location /itportal/</code> 仍配置 <code>try_files $uri /itportal/index.html</code>。建议:<code>docker compose up -d --force-recreate nginx</code>(前提:commit 21830d5 中 nginx.conf 已删除该 location 块)</td>
|
||
</tr>
|
||
<tr data-cat="p0">
|
||
<td><span class="badge p0">P0-3</span></td>
|
||
<td><code>closing_service.py:467</code> datetime 时区错位</td>
|
||
<td>♻️ 历史遗留</td>
|
||
<td><code>datetime.now() - close_time</code> 报 <code>TypeError: can't subtract offset-naive and offset-aware datetimes</code>。影响 <code>POST /h5/conversations/current/reopen</code>。同文件 18 处 <code>datetime.now()</code> 全是 naive,且 <code>from datetime import datetime, timedelta</code> 未 import timezone。24h 内未触发,但用户使用 H5 重开会话即会爆</td>
|
||
</tr>
|
||
<tr data-cat="p0">
|
||
<td><span class="badge p0">P0-4</span></td>
|
||
<td><code>employee_profile_service.py:236</code> SessionLocal NoneType 🔥</td>
|
||
<td>🆕 位置修正</td>
|
||
<td><strong>看板 v1.8 行号描述错误</strong>:实际错误位置是 <code>app/services/employee_profile_service.py:236</code> 而非 <code>h5_ai_task.py:1198</code>。<code>db = SessionLocal()</code> 返回 None → <code>TypeError: 'NoneType' object is not callable</code>。2026-08-05 24h 内累计 10+ 次(01:33 / 03:25 / 04:07 / 04:11 多波次),影响 H5 IT 资产推荐异步推送。<strong>同根因 P0-5</strong></td>
|
||
</tr>
|
||
<tr data-cat="p0">
|
||
<td><span class="badge p0">P0-5</span></td>
|
||
<td>容器 <code>app/constants/</code> 打包错误 🔥</td>
|
||
<td>🆕 新增</td>
|
||
<td>容器内 <code>/app/app/constants/__init__.py</code> 11635 bytes 内容是 automation.py(两个文件互换了),<code>/app/app/constants/automation.py</code> <strong>不存在</strong>。直接后果:连续 10+ 次 <code>ModuleNotFoundError: No module named 'app.constants.ai_reply_mode'</code> + 同根因连锁导致 P0-4(SessionLocal 绑定失败)。建议:① 临时 <code>docker cp</code> 修补 → ② 长期排查 backend 镜像构建流程</td>
|
||
</tr>
|
||
<tr data-cat="p0">
|
||
<td><span class="badge p0">P0-6</span></td>
|
||
<td>后端 OAuth 40029 抖动</td>
|
||
<td>ℹ️ 信息类</td>
|
||
<td>218.75.34.87 等外部 IP 持续试探 <code>/api/auth/validate-sso</code> + 偶发 OAuth code 失效。属 WAF 扫描背景噪声,已 fail2ban 监控。无需主动处理</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<!-- 等用户决策 -->
|
||
<h2 data-section="decide">🟢 等用户决策(阻塞项)</h2>
|
||
<p class="legend">均超 3 天阈值,需 PM 升级催办</p>
|
||
<table>
|
||
<thead><tr><th>编号</th><th>任务</th><th>阻塞时长</th><th>卡点 / Owner</th></tr></thead>
|
||
<tbody>
|
||
<tr data-cat="decide">
|
||
<td><span class="badge decide">BLK-A</span></td>
|
||
<td>企微会议室 Secret</td>
|
||
<td>⚠️ <strong>26 天</strong>(自 2026-07-11)</td>
|
||
<td>需企业微信管理后台申请。Owner: 平台组</td>
|
||
</tr>
|
||
<tr data-cat="decide">
|
||
<td><span class="badge decide">BLK-B</span></td>
|
||
<td>ITSM API 授权</td>
|
||
<td>⚠️ <strong>26 天</strong>(自 2026-07-11)</td>
|
||
<td>需向 ITSM 平台方申请 app_id/app_secret。Owner: 平台组</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<!-- 进行中 -->
|
||
<h2 data-section="doing">⏳ 进行中 (In Progress)</h2>
|
||
<table>
|
||
<thead><tr><th>编号</th><th>任务</th><th>状态</th><th>说明</th></tr></thead>
|
||
<tbody>
|
||
<tr data-cat="doing">
|
||
<td><span class="badge doing">#81</span></td>
|
||
<td>敏感词检测 + 语气优化</td>
|
||
<td>v1.2 待排期</td>
|
||
<td>v1.1 阶段 1 已于 2026-07-28 完成(词库入库 + 后台管理 UI + 12 配套 API)。剩余 "语气优化、灰度策略细化" 待 v1.2 排期</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<!-- 服务器状态 -->
|
||
<h2 data-section="server">🖥️ 服务器运行状态</h2>
|
||
<table>
|
||
<thead><tr><th>组件</th><th>状态</th><th>实测数据</th></tr></thead>
|
||
<tbody>
|
||
<tr data-cat="server">
|
||
<td>Docker 容器</td>
|
||
<td><span class="badge ok">正常</span></td>
|
||
<td>5/5 healthy:nginx (Up 12h) / backend (Up 17h) / redis (Up 2w) / postgres (Up 3w) / neo4j (Up 3w)。无 Exited/Restarting/Unhealthy</td>
|
||
</tr>
|
||
<tr data-cat="server">
|
||
<td>后端 health</td>
|
||
<td><span class="badge ok">正常</span></td>
|
||
<td><code>/health</code> → HTTP 200(容器内 3.9ms);外部 <code>curl http://localhost:8000</code> 000(端口未映射给宿主,nginx 反代访问正常)</td>
|
||
</tr>
|
||
<tr data-cat="server">
|
||
<td>后端 5xx 错误</td>
|
||
<td><span class="badge fail">异常</span></td>
|
||
<td>24h 内仍见 2 类 Traceback:P0-5 ModuleNotFoundError(10+ 次)+ P0-4 SessionLocal NoneType(10+ 次)</td>
|
||
</tr>
|
||
<tr data-cat="server">
|
||
<td>PostgreSQL</td>
|
||
<td><span class="badge ok">正常</span></td>
|
||
<td><code>pg_isready -U postgres</code> → <code>accepting connections</code></td>
|
||
</tr>
|
||
<tr data-cat="server">
|
||
<td>Redis</td>
|
||
<td><span class="badge ok">正常</span></td>
|
||
<td><code>redis_version:7.4.9</code> / 独立模式 + 密码认证(NOAUTH 正常);已配密码 <code>WKzl7jgKTkeWxFWGIBXfzokm59Gvfr76</code></td>
|
||
</tr>
|
||
<tr data-cat="server">
|
||
<td>Nginx 配置</td>
|
||
<td><span class="badge ok">正常</span></td>
|
||
<td><code>nginx -t</code> → syntax OK;80/443 已 bind</td>
|
||
</tr>
|
||
<tr data-cat="server">
|
||
<td>前端入口</td>
|
||
<td><span class="badge fail">异常</span></td>
|
||
<td><code>/itportal/</code> <strong>500</strong>(rewrite cycle);<code>/h5/</code>、<code>/itdesk/</code> 200 OK;<code>/</code> 200(612 bytes root index.html)</td>
|
||
</tr>
|
||
<tr data-cat="server">
|
||
<td>磁盘 / 内存</td>
|
||
<td><span class="badge ok">正常</span></td>
|
||
<td>130G 可用(13% 用)/ 3.4G used / 11G available / 负载 0.99 / 已运行 54 天</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<!-- 代码规范与质量 -->
|
||
<h2 data-section="code">🔍 代码规范与质量检查</h2>
|
||
<ul class="condensed">
|
||
<li data-cat="code"><strong>🟢 鉴权补漏</strong>:sensitive_words.py 13 端点已正确加 <code>dependencies=[Depends(require_admin)]</code> (line 47-51)。看板描述脱节,v1.9 已迁移至已完成</li>
|
||
<li data-cat="code"><strong>🔴 容器/源码不一致</strong>:容器内 <code>app/constants/__init__.py</code> = automation.py 内容。排查镜像构建流程,重打 backend 镜像</li>
|
||
<li data-cat="code"><strong>🟡 死代码 / 残留</strong>:console.log 在 <code>src/frontend-*/src</code> 已搜不到。看板描述脱节,v1.9 已迁移至已完成</li>
|
||
<li data-cat="code"><strong>🟢 时区隐患</strong>:closing_service.py 全部 18 处 <code>datetime.now()</code> 全是 naive,无 import timezone。建议全文件改造为 <code>datetime.now(tz=timezone.utc)</code></li>
|
||
<li data-cat="code"><strong>🟢 未使用导入 / 硬编码</strong>:未发现明显问题(快速扫描未命中);源码层无硬编码(生产 env 路径已隔离)</li>
|
||
</ul>
|
||
|
||
<!-- 安全检查 -->
|
||
<h2 data-section="security">🔐 安全检查</h2>
|
||
<ul class="condensed">
|
||
<li data-cat="security"><strong>🟡 API 鉴权</strong>:sensitive_words.py 13 端点已 require_admin;其余 admin API 状态需逐项复核(本次未做全量扫描)</li>
|
||
<li data-cat="security"><strong>🟢 敏感数据处理</strong>:数据库连接串、Redis 密码均在 env 注入,未硬编码到源码</li>
|
||
<li data-cat="security"><strong>🟡 依赖包</strong>:<code>cryptography==42.0.8</code> / <code>pydantic==2.7.4</code>(2026-08-05 巡检已记录,仍待升级)</li>
|
||
<li data-cat="security"><strong>🟡 日志敏感信息</strong>:生产 logs 记录了用户 OAuth code(如 <code>code=OFVMVR7IB2dgFVWX...</code>),属企微临时凭据,建议在 <code>wecom_service.py:1411</code> 打印前 mask</li>
|
||
</ul>
|
||
|
||
<!-- 对比/关注 -->
|
||
<h2 data-section="history">🔄 与昨日对比 / PM 关注项</h2>
|
||
<table>
|
||
<thead><tr><th>条目</th><th>变化</th><th>说明</th></tr></thead>
|
||
<tbody>
|
||
<tr data-cat="history">
|
||
<td>P0-2 sensitive_words.py 13 端点无鉴权</td>
|
||
<td>♻️→✅</td>
|
||
<td>看板 v1.8 标"待治理",2026-08-06 06:00 巡检发现<strong>代码已修复</strong>(router 加 <code>dependencies=[Depends(require_admin)]</code> line 47-51),v1.9 看板已迁移至已完成区</td>
|
||
</tr>
|
||
<tr data-cat="history">
|
||
<td>P1-1 前端 console.log 残留 208 行</td>
|
||
<td>♻️→✅</td>
|
||
<td>看板 v1.8 标"待清理",2026-08-06 06:00 巡检发现 <code>rg/find</code> 搜不到任何 console.log,v1.9 看板已迁移至已完成区</td>
|
||
</tr>
|
||
<tr data-cat="history">
|
||
<td>P0-4 行号描述修正</td>
|
||
<td>🔄 修正</td>
|
||
<td>看板 v1.8 写 <code>h5_ai_task.py:1198</code>,实际是 <code>employee_profile_service.py:236</code>。<strong>同根因 P0-5</strong>,建议合并排查</td>
|
||
</tr>
|
||
<tr data-cat="history">
|
||
<td>BLK-A/B 阻塞时长刷新</td>
|
||
<td>📅 +1d</td>
|
||
<td>自 2026-07-11 起,2026-08-06 已 <strong>26 天</strong>(较昨日 +1 自然日),远超 3 天阈值</td>
|
||
</tr>
|
||
<tr data-cat="history">
|
||
<td>/itportal/ 500 持续 29 天</td>
|
||
<td>🔥 持续</td>
|
||
<td>2026-07-08 起至今,今日 06:00 jumpserver-V2 实测仍 500。需 PM 派单部署 commit 21830d5 或清理 nginx location 块</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<!-- PM 立即关注 -->
|
||
<h2 data-section="all">⚠️ PM 立即关注</h2>
|
||
<ul class="condensed">
|
||
<li data-cat="all">🔴 P0-NEW1(constants 包打包错误)必须当日修:直接导致 H5 异步任务全部崩溃(资产推荐推送 NoneType)。修复方向:① 临时 <code>docker cp</code> 修补 → ② 长期重打 backend 镜像</li>
|
||
<li data-cat="all">🔴 /itportal 500 已持续 29 天:根因明确(容器内空 dist + nginx location 块残留)。建议执行 <code>docker compose up -d --force-recreate nginx</code></li>
|
||
<li data-cat="all">🟡 看板 v1.8.0-FROZEN 2 项描述脱节:P0-2 sensitive_words / P1-1 console.log 实际已修复 / 已清理,v1.9 已修正</li>
|
||
<li data-cat="all">⚠️ BLK-A/B 阻塞已 26 天(+23 天超过 3 天阈值):建议 PM 升级催办或重新评估优先级</li>
|
||
<li data-cat="all">🟡 closing_service.py:467 时区隐患:24h 内未触发,修复成本低(<code>from datetime import timezone</code> + 18 处替换)</li>
|
||
</ul>
|
||
|
||
<footer>
|
||
📋 报告生成时间:2026-08-06 06:00 · 看板版本 v1.9.0-DRAFT · Duckula(达寇拉)自动化生成<br>
|
||
📎 数据源:jumpserver-V2 实测 + 后端 24h 日志审计 + 源码扫描 + 容器内文件核对<br>
|
||
🔗 服务地址:<code>https://itsupport.servyou.com.cn/docs/inspection/2026-08/2026-08-06-早班.html</code>
|
||
</footer>
|
||
</div>
|
||
|
||
<script>
|
||
(function () {
|
||
// 简易分类筛选
|
||
const all = { all: true };
|
||
document.querySelectorAll('.filter-btn').forEach((btn) => {
|
||
btn.addEventListener('click', () => filter(btn.dataset.cat));
|
||
});
|
||
function filter(cat) {
|
||
document.querySelectorAll('.filter-btn').forEach((b) => b.classList.remove('active'));
|
||
document.querySelector('.filter-btn[data-cat="' + cat + '"]').classList.add('active');
|
||
document.querySelectorAll('tr[data-cat], li[data-cat]').forEach((el) => {
|
||
if (cat === 'all') { el.classList.remove('hidden'); }
|
||
else if (el.dataset.cat === cat) { el.classList.remove('hidden'); }
|
||
else { el.classList.add('hidden'); }
|
||
});
|
||
document.querySelectorAll('h2[data-section]').forEach((h) => {
|
||
if (cat === 'all' || h.dataset.section === cat) { h.classList.remove('hidden'); }
|
||
else { h.classList.add('hidden'); }
|
||
});
|
||
history.replaceState(null, '', '#' + cat);
|
||
}
|
||
const initCat = (location.hash || '#all').slice(1);
|
||
if (['all','p0','decide','doing','server','code','security','history'].includes(initCat)) {
|
||
filter(initCat);
|
||
}
|
||
const keys = ['1','2','3','4','5','6','7','8','0'];
|
||
const map = ['p0','decide','doing','server','code','security','history','overview','all'];
|
||
document.addEventListener('keydown', (e) => {
|
||
if (['INPUT','TEXTAREA'].includes(e.target.tagName)) return;
|
||
const idx = keys.indexOf(e.key);
|
||
if (idx >= 0 && map[idx]) filter(map[idx]);
|
||
});
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|