skill-forge-hub 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +82 -150
- package/annual-report/SKILL.md +23 -3
- package/annual-report/resources/data-collection.md +20 -4
- package/annual-report/resources/disk-and-html.md +3 -3
- package/annual-report/resources/reference.html +31 -10
- package/annual-report/resources/usage-guide.md +8 -0
- package/annual-report/user-config.md +5 -5
- package/article-to-html/SKILL.md +26 -7
- package/article-to-html/design-system.md +9 -3
- package/article-to-html/resources/reference.html +631 -0
- package/article-to-html/resources/usage-guide.md +9 -1
- package/article-to-html/user-config.md +6 -3
- package/cli.js +2 -2
- package/daily-report/SKILL.md +23 -3
- package/daily-report/resources/content-rules.md +1 -1
- package/daily-report/resources/data-collection.md +24 -4
- package/daily-report/resources/disk-and-html.md +2 -2
- package/daily-report/resources/reference.html +24 -3
- package/daily-report/resources/usage-guide.md +8 -0
- package/daily-report/user-config.md +5 -5
- package/deck-stage/SKILL.md +15 -4
- package/deck-stage/resources/cover-template.html +3 -3
- package/deck-stage/resources/data-schema.md +11 -1
- package/deck-stage/resources/pptx-builder.js +1 -1
- package/deck-stage/resources/usage-guide.md +9 -2
- package/docs/architecture.md +89 -0
- package/docs/images/article-to-html.png +0 -0
- package/docs/images/daily-report.png +0 -0
- package/docs/images/deck-stage.png +0 -0
- package/docs/images/magic-deck.png +0 -0
- package/docs/images/meeting-minutes.png +0 -0
- package/docs/images/prompt-pouch.png +0 -0
- package/docs/install.md +71 -0
- package/magic-deck/SKILL.md +23 -8
- package/magic-deck/resources/content-guide.md +5 -4
- package/magic-deck/resources/deck-spec.md +18 -11
- package/magic-deck/resources/reference.html +110 -32
- package/magic-deck/resources/usage-guide.md +10 -2
- package/magic-deck/user-config.md +4 -4
- package/meeting-minutes/SKILL.md +51 -0
- package/meeting-minutes/resources/content-rules.md +57 -0
- package/meeting-minutes/resources/disk-and-html.md +26 -0
- package/meeting-minutes/resources/meeting-type-dictionary.md +24 -0
- package/meeting-minutes/resources/reference.html +436 -0
- package/meeting-minutes/resources/usage-guide.md +63 -0
- package/meeting-minutes/user-config.md +56 -0
- package/meta-forge/SKILL.md +6 -6
- package/meta-forge/resources/forge-rules.md +60 -10
- package/meta-forge/resources/usage-guide.md +7 -2
- package/meta-forge/user-config.md +2 -1
- package/monthly-report/SKILL.md +62 -0
- package/monthly-report/resources/content-rules.md +40 -0
- package/monthly-report/resources/data-collection.md +44 -0
- package/monthly-report/resources/date-parsing.md +18 -0
- package/monthly-report/resources/disk-and-html.md +29 -0
- package/monthly-report/resources/industry-dictionary.md +21 -0
- package/monthly-report/resources/reference.html +531 -0
- package/monthly-report/resources/usage-guide.md +75 -0
- package/monthly-report/user-config.md +53 -0
- package/package.json +9 -2
- package/prompt-pouch/SKILL.md +17 -2
- package/prompt-pouch/resources/data-format.md +1 -1
- package/prompt-pouch/resources/reference.html +56 -24
- package/prompt-pouch/resources/usage-guide.md +10 -3
- package/quarterly-report/SKILL.md +63 -0
- package/quarterly-report/resources/content-rules.md +42 -0
- package/quarterly-report/resources/data-collection.md +46 -0
- package/quarterly-report/resources/date-parsing.md +19 -0
- package/quarterly-report/resources/disk-and-html.md +22 -0
- package/quarterly-report/resources/industry-dictionary.md +21 -0
- package/quarterly-report/resources/reference.html +509 -0
- package/quarterly-report/resources/usage-guide.md +76 -0
- package/quarterly-report/user-config.md +53 -0
- package/spec-doc2spec/SKILL.md +21 -22
- package/spec-doc2spec/resources/checklist.md +7 -0
- package/spec-doc2spec/resources/images.md +14 -5
- package/spec-doc2spec/resources/structure.md +19 -10
- package/spec-doc2spec/resources/usage-guide.md +10 -8
- package/spec-doc2spec/user-config.md +2 -2
- package/spec-spec2doc/SKILL.md +4 -4
- package/spec-spec2doc/resources/checklist.md +6 -0
- package/spec-spec2doc/resources/pdf-path.md +1 -0
- package/spec-spec2doc/resources/usage-guide.md +2 -2
- package/template/SKILL.md +18 -14
- package/template/resources/README.md +1 -1
- package/template/resources/usage-guide.md +17 -0
- package/template/user-config.md +28 -0
- package/weekly-report/SKILL.md +23 -3
- package/weekly-report/resources/content-rules.md +1 -1
- package/weekly-report/resources/data-collection.md +24 -4
- package/weekly-report/resources/disk-and-html.md +2 -2
- package/weekly-report/resources/reference.html +24 -3
- package/weekly-report/resources/usage-guide.md +8 -0
- package/weekly-report/user-config.md +5 -5
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# 季度解析
|
|
2
|
+
|
|
3
|
+
把自然语言定位到目标季度区间。季度区间决定提交统计范围与目录/文件名。季度编号:Q1=1-3 月、Q2=4-6 月、Q3=7-9 月、Q4=10-12 月。
|
|
4
|
+
|
|
5
|
+
## 定位规则
|
|
6
|
+
|
|
7
|
+
| 用户说法 | 目标季度 | 区间 |
|
|
8
|
+
|:---|:---|:---|
|
|
9
|
+
| 2026年Q4 / 这个季度 / 写个季报(未指定)| 当前自然季度(如 2026-Q4)| 季首 ~ 今天(未过完则到「今天」)|
|
|
10
|
+
| 上季度 / Q3 的总结 | 上一自然季度 | 完整季度(07-01 ~ 09-30)|
|
|
11
|
+
| 近三个月 / 最近90天 | 滚动 90 天 | 今天 - 90 天 ~ 今天 |
|
|
12
|
+
| 2026-Q3 / 2026年第三季度(明确指定)| 指定季度 | 完整季度 |
|
|
13
|
+
| 今年 Q1-Q4 总结 / 全年季度回顾 | 全年按季度(成果段按 Q1/Q2/Q3/Q4 时间线)| 01-01 ~ 今天 |
|
|
14
|
+
|
|
15
|
+
- 「这个季度」以当前系统日期为准(11 月 12 日写季报 → Q4,区间 10-01 ~ 11-12,标题注明「截至 2026-11-12」)
|
|
16
|
+
- 目录:`{DIR}/2026-Q4/`(滚动 90 天用起始年月,如 08-14~11-12 → 2026-08,目录内文件名仍按目标季度或滚动区间)
|
|
17
|
+
- 文件名:`quarterly-report-2026-Q4.md/.txt/.html`、截图 `quarterly-report-2026-Q4-content.png`;滚动 90 天文件名用区间(如 `quarterly-report-2026-08-14~11-12.html`);全年季度回顾文件名 `quarterly-report-2026-Q1-Q4.html`
|
|
18
|
+
- 同名目录已存在时直接复用(不重建、不清空),仅覆盖 FORMATS 清单内的同名文件;目录内其它文件一律保留不动(同目录下月报子目录互不干扰)
|
|
19
|
+
- 同一份季度总结重复生成默认直接覆盖;用户说「保留之前的/另存/不覆盖」时文件名追加时间戳(如 `quarterly-report-2026-Q4-1530.html`)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# 落盘与 HTML(季度版式)
|
|
2
|
+
|
|
3
|
+
> ⛔ **Reference 铁律(最高优先)**:本目录 `reference.html` 是定稿样式源码。生成 HTML 时必须先 Read `resources/reference.html` 与本文件两份,以 reference.html 为骨架模板逐处替换数据(标题/日期/四段条目/TL;DR 摘要/数据卡数字与双基准小字/Q1-Q4 走势图数据数组——IIFE 内 QVALS),本文件的描述是参数解释、变体规则与禁止项;两者冲突时**以 reference.html 为准**。修改本 skill 的 HTML 效果时,必须同步更新 `resources/reference.html` 与本文档的对应描述,禁止只改一处。
|
|
4
|
+
|
|
5
|
+
> HTML 视觉体系与报表族(日报/周报/月报/年报)同源(深蓝面板 + 五主题令牌 + 发光特效 + 复制按钮 + 换肤坞 + 截图模式),生成时以 reference.html 为唯一样式真相源,本文件只列季报版式差异与要点。
|
|
6
|
+
|
|
7
|
+
## 落盘
|
|
8
|
+
|
|
9
|
+
- FORMATS 默认 [md, txt, html, content-png]:md/txt/html 文件名 `quarterly-report-YYYY-QN.<格式>`、截图 `quarterly-report-YYYY-QN-content.png`;txt 为纯文本版;DISK: false 时全部不落盘
|
|
10
|
+
- 目录:`{DIR}/YYYY-QN/`(DIR 按系统取 DIR_MAC/DIR_WIN,不存在回退用户主目录下 reports);目录已存在直接复用,只覆盖本清单内同名文件;目录内存在非本 skill 命名的其它文件时对话中提示用户「该目录内已有其它文件,本次季度总结已与它们并列存放,未做任何改动」
|
|
11
|
+
- 对话中照常输出 md 正文(不受 FORMATS 影响);OPEN_HTML: true 且落盘了 html 时自动打开浏览器(macOS:open <html文件>;Windows PowerShell:Start-Process <html文件>)
|
|
12
|
+
- FORMATS 含 content-png 时生成内容区截图:只截四张分节卡片整体(季度概览/季度关键成果/问题与改进/下季度计划,不含头部标题区/复制按钮/页脚,四周保留对称合适的外边距约 40px 留白);html 内置 `?shot=content` 参数(页面 JS 检测后隐藏 header-card/footer、body 四周 padding 统一 40px,正常浏览不受影响);用 Chrome headless 访问带参 URL 截图(路径按系统选:macOS=`/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`;Windows 按序探测 `C:\Program Files\Google\Chrome\Application\chrome.exe` → `C:\Program Files (x86)\Google\Chrome\Application\chrome.exe` → `%LOCALAPPDATA%\Google\Chrome\Application\chrome.exe`,经 node child_process 执行 `--headless --disable-gpu --no-sandbox --hide-scrollbars --user-data-dir=<临时目录> --screenshot=<png路径> --window-size=760,<估算高度> --virtual-time-budget=4000 "file:///<html路径>?shot=content"`(Windows 下 URL 写作 file:///C:/...,用 node url.pathToFileURL 生成),跑完删除临时目录;禁止用 `--headless=new`(单例模式会静默失败生成占位图);若 Chrome 不存在则换 Edge,都找不到时跳过截图并在对话注明);高度估算基准(760 宽窄窗实测:概览 4 卡折 2 行 + 走势图 200px、成果 6 条 + 2 占位月、问题 2 条三环、计划 3 条 → 内容区约 2350px,图高 = 内容区 + 上下留白各 40px):每增减 1 条成果条目 ±~85、1 条问题 ±~100、1 条计划 ±~90、概览数据卡每多一行 ±~105;实测高度显著高于按 65~70px/条的旧估算,禁止低估导致截断,截图后用 Read 校验:四张卡片整体完整在图内、无头部/按钮/页脚残留、四周留白对称合适、不截断;底部留白过大减高度、截断加高度重截
|
|
13
|
+
|
|
14
|
+
## HTML 季度版式要点(基于 reference.html)
|
|
15
|
+
|
|
16
|
+
- 头部卡片:标题按行业词典「标题」变量取词 + 季度前缀(如「2026-Q4 研发季度总结」;话术含职业词 → 该词条标题,未提职业 → 按 ROLE 画像匹配词条,词典外行业 → 「YYYY-QN 季度总结」兜底)+ 副标题(ROLE 画像或季度区间)+ 生成时间行
|
|
17
|
+
- 概览节:一句话 TL;DR 引言行 + 核心数据卡 4-6 张横排(.stat-card:大数字 28px 渐变字 + 12px muted 标签 + **双基准两行小字**「较上季度:+18%」「较去年同期:+35%」,上涨 --green 绿、下跌 --rose 红,双基准均为 11.5px .stat-cmp 行,两行间距 2px;缺某一基准来源时只写有来源的一行,两条都没有则不写);数据卡下方 Q1-Q4 季度走势图(.cb-wrap + .ech 容器 200px 高,echarts 柱图:xAxis Q1/Q2/Q3/Q4(当年已有季度,未到的季度不画)、当前季度柱高亮 accent 色、其余柱 muted 半透明,tooltip「QN · N 次提交」)
|
|
18
|
+
- 成果节:纵向时间线(.timeline 左侧 2px 青色竖线 + 月节点:M1/M2/M3 圆形节点(节色渐变球 + 光晕,当前月节点加呼吸动画)+ 右侧内容(成果描述 15px + 量化小字 12px 青灰 + 月徽章 11px muted 胶囊「M1 · 10 月」);月内多条共用月节点,条目间青色虚线分隔;全季报(Q1-Q4 回顾)节点为 Q1/Q2/Q3/Q4
|
|
19
|
+
- 问题节/计划节:问题条目沿用 3D 立体圆球序号徽章(问题玫红);问题条三环展开(问题主行 + 影响行 + 改进行);计划条目卡(目标描述 15px + 量化指标加粗 + 月度行动节点小胶囊 11px(M1 起…/M2 完成…,muted 字 + 青色细边 + 淡青底))
|
|
20
|
+
- 数据卡数字选择:业务结果指标优先、提交统计兜底;数字凡有对比基准必带(环比上季度/同比去年同期至少其一)
|
|
21
|
+
- 页脚 10px muted 文字,署名固定 GENERATED BY AI TEAM · <季度>(动态跟随目标季度,如 GENERATED BY AI TEAM · 2026-Q4)
|
|
22
|
+
- 四段分节列表,条目保持中文顿号序号;md/txt 版同条目依次写,文本格式不变
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# 行业适配(职业词典)
|
|
2
|
+
|
|
3
|
+
报告骨架(四段式/TL;DR/核心数据卡/月时间线/反思三环)行业无关,只有「行业变量」随职业切换。用户对话中声明职业即按词典取词(如「帮我写份销售季报」→ 销售词条);词典没有的行业走兜底。
|
|
4
|
+
|
|
5
|
+
| 变量 | 研发 | 销售 | 运营 | 产品 | HR | 财务 | 市场 | 客服 | 项目/PMO | 行政 | 法务 | 设计 |
|
|
6
|
+
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
7
|
+
| 标题 | 研发季度总结 | 销售季度总结 | 运营季度总结 | 产品季度总结 | 人事季度总结 | 财务季度总结 | 市场季度总结 | 客服季度总结 | 项目季度总结 | 行政季度总结 | 法务季度总结 | 设计季度总结 |
|
|
8
|
+
| 工作单元 | 提交/版本/PR | 拜访/商机/回款 | 活动/渠道/内容 | 需求/迭代/上线 | 招聘/培训/入离职 | 报表/对账/税务 | 投放/活动/线索 | 工单/会话/满意度 | 里程碑/需求变更/资源/评审 | 会务/采购/资产/证照 | 合同审核/诉讼/合规/知产 | UI稿/设计规范/走查/交付 |
|
|
9
|
+
| 量化指标 | 季提交数·行数·版本数 | 季拜访数·商机数·回款额 | 季曝光·转化·GMV | 季交付数·上线数 | 季简历数·到面率·入职数 | 季凭证数·回款·预算执行率 | 季投放额·线索数·ROI | 季工单量·解决率·满意度 | 季里程碑达成数·任务完成数·变更数 | 季会务场次·采购完成数·资产盘点数 | 季合同审核数·案件进展·合规项数 | 季页面稿数·规范组件数·走查问题数 |
|
|
10
|
+
| 里程碑 | 版本发布/架构升级 | 大客户签约/区域突破 | 爆款活动/渠道扩张 | 重大版本迭代/核心功能上线 | 组织变革/人才梯队建设 | 系统上线/审计通过 | 品牌战役/投放升级 | 服务体系搭建/满意度跃升 | 重点项目交付/流程建设 | 办公搬迁/年会/体系建设 | 重大案件胜诉/合规体系落地 | 设计系统/规范落地 |
|
|
11
|
+
| 风险话术 | 阻塞点/技术债 | 竞争/预算审批 | 资源/渠道效果 | 需求变更/排期 | 用人缺口 | 资金/合规 | 渠道成本 | 舆情/高峰 | 范围蔓延/资源冲突 | 供应商延期/预算超支 | 合规风险/诉讼时效 | 需求反复/排期挤压 |
|
|
12
|
+
| 价值翻译 | 稳定性·效率·成本·体验 | 收入·客单价·转化·回款 | 曝光·线索·留存·ROI | 用户增长·留存·满意度 | 人效·到岗率·留存率 | 成本节约·资金效率·合规 | 曝光·线索·转化·品牌 | 满意度·处理时效·客诉率 | 准时率·交付质量·成本偏差 | 流程效率·成本·满意度 | 风险规避·合规·时效 | 转化·体验·一致性 |
|
|
13
|
+
|
|
14
|
+
- 用户角色画像:顶部「默认配置」的 ROLE 定义用户默认角色与主要工作内容(当前:全栈开发工程师(企业内技术开发));未提职业时按 ROLE 画像取词(当前等价研发词条:代码仓库当季提交聚合 + 提交/版本术语 + 提交数/行数/版本数指标 + 版本发布/架构升级里程碑)
|
|
15
|
+
- 价值翻译(技术动作→业务结果):技术动作一律翻译为业务结果表述——研发翻向稳定性/效率/成本/体验(「重写 SQL 加索引」→「查询响应 3.2s→0.4s」),其它岗位按「价值翻译」行各自方向取义(销售→收入/转化、客服→满意度/时效等);提交统计(提交数/文件数/行数)仅为兜底指标,口述含业务结果时业务结果优先;仅含动作无结果时保留动作描述,并在对话中提示可补充结果指标
|
|
16
|
+
- 触发:话术含职业词(销售/运营/产品/HR/财务/市场/客服/项目/PMO/行政/法务/设计等)→ 标题、工作单元术语、量化指标、里程碑主题、风险话术全部按该词典词条生成
|
|
17
|
+
- 临时换角色:说「以 XX 的身份写季报」(如「以销售经理的身份写」)→ 当次按该角色词条生成,不改配置
|
|
18
|
+
- 永久换角色:说「以后默认用 XX 角色 / 我的职业是 XX / 我的主要工作是 XX」→ 更新顶部 ROLE 配置(永久生效);词典没有的角色按用户描述新增词条
|
|
19
|
+
- 声明+临时指标覆盖:说「这次指标看签约额和回款」→ 词条 + 临时指标(仅当次);说「以后都用这套指标」→ 固化进词典(永久)
|
|
20
|
+
- 兜底:词典外的行业(工地施工、医生值班等)→ 骨架 + 用户素材(文字/图片/文件)现场生成词条(工作单元/指标/里程碑从素材提取),本次生效;说「记住这个行业」→ 固化为新词条
|
|
21
|
+
- 行业/角色切换只换内容与指标,HTML 骨架/色板/动效/落盘规范全部不变;纯文字整理模式同样适用词典;优先级:临时角色声明 > 顶部 ROLE 配置 > 词典表
|
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN" data-theme="tech">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<meta name="sf-template" content="quarterly-report@2">
|
|
7
|
+
<meta name="quarterly-id" content="REF-QUARTERLY-0000">
|
|
8
|
+
<title>2026-Q4 研发季度总结</title>
|
|
9
|
+
<style>
|
|
10
|
+
|
|
11
|
+
/* ═══ 五主题令牌:12 核心契约 + 报告扩展;html[data-theme] 运行时切换,THEME 生成时定默认 ═══ */
|
|
12
|
+
:root, [data-theme="tech"]{
|
|
13
|
+
--bg:#0a1929; --bg2:#071525; --panel:rgba(11,30,55,.9); --panel-solid:#0b1e37;
|
|
14
|
+
--text:#bae6fd; --muted:#5b7fa5; --accent:#0ea5e9; --accent2:#14b8a6;
|
|
15
|
+
--border:rgba(14,165,233,.18); --glow:rgba(14,165,233,.35); --glow-soft:rgba(14,165,233,.15);
|
|
16
|
+
--title-grad:linear-gradient(90deg,#7dd3fc,#0ea5e9 45%,#818cf8);
|
|
17
|
+
--tag-bg:rgba(14,165,233,.12);
|
|
18
|
+
--card-shadow:0 1px 0 rgba(255,255,255,.05) inset,0 12px 32px rgba(1,6,16,.5),0 0 24px rgba(14,165,233,.15);
|
|
19
|
+
--scan:rgba(0,240,255,.2); --scan-dim:rgba(0,240,255,.05);
|
|
20
|
+
--heat:rgba(14,165,233,.55);
|
|
21
|
+
--green:#14b8a6; --orange:#f97316; --rose:#f43f5e;
|
|
22
|
+
}
|
|
23
|
+
[data-theme="biz"]{
|
|
24
|
+
--bg:#e8ecf5; --bg2:#dde3ef; --panel:rgba(255,255,255,.97); --panel-solid:#ffffff;
|
|
25
|
+
--text:#1e293b; --muted:#64748b; --accent:#2563eb; --accent2:#0891b2;
|
|
26
|
+
--border:rgba(37,99,235,.14); --glow:rgba(37,99,235,.18); --glow-soft:rgba(37,99,235,.12);
|
|
27
|
+
--title-grad:linear-gradient(90deg,#1e40af,#2563eb 55%,#0891b2);
|
|
28
|
+
--tag-bg:rgba(37,99,235,.08);
|
|
29
|
+
--card-shadow:0 1px 2px rgba(15,23,42,.05),0 10px 28px rgba(15,23,42,.12);
|
|
30
|
+
--scan:rgba(37,99,235,.14); --scan-dim:rgba(37,99,235,.04);
|
|
31
|
+
--heat:rgba(37,99,235,.55);
|
|
32
|
+
--green:#0d9488; --orange:#ea580c; --rose:#e11d48;
|
|
33
|
+
}
|
|
34
|
+
[data-theme="mono"]{
|
|
35
|
+
--bg:#1e1f22; --bg2:#2b2d30; --panel:rgba(43,45,48,.95); --panel-solid:#2b2d30;
|
|
36
|
+
--card-shadow:0 1px 0 rgba(255,255,255,.06) inset, 0 12px 32px rgba(0,0,0,.5), 0 0 24px rgba(53,116,240,.16);
|
|
37
|
+
--text:#dfe1e5; --muted:#9aa0a6; --accent:#3574f0; --accent2:#5e9aff;
|
|
38
|
+
--border:rgba(53,116,240,.26); --glow:rgba(53,116,240,.3); --glow-soft:rgba(53,116,240,.13);
|
|
39
|
+
--title-grad:linear-gradient(90deg,#dfe1e5,#5e9aff 50%,#3574f0);
|
|
40
|
+
--tag-bg:rgba(53,116,240,.13);
|
|
41
|
+
--scan:rgba(223,225,229,.18); --scan-dim:rgba(223,225,229,.07);
|
|
42
|
+
--heat:rgba(53,116,240,.55);
|
|
43
|
+
--green:#4da36b; --orange:#d09645; --rose:#d85f73;
|
|
44
|
+
}
|
|
45
|
+
[data-theme="light"]{
|
|
46
|
+
--bg:#ffffff; --bg2:#f2f2f2; --panel:rgba(255,255,255,.98); --panel-solid:#ffffff;
|
|
47
|
+
--card-shadow:0 1px 2px rgba(30,31,34,.06), 0 10px 28px rgba(30,31,34,.12);
|
|
48
|
+
--text:#1e1f22; --muted:#6e7781; --accent:#2675bf; --accent2:#4a9be0;
|
|
49
|
+
--border:rgba(38,117,191,.18); --glow:rgba(38,117,191,.2); --glow-soft:rgba(38,117,191,.1);
|
|
50
|
+
--title-grad:linear-gradient(90deg,#1e5f9f,#2675bf 55%,#4a9be0);
|
|
51
|
+
--tag-bg:rgba(38,117,191,.08);
|
|
52
|
+
--scan:rgba(38,117,191,.12); --scan-dim:rgba(38,117,191,.04);
|
|
53
|
+
--heat:rgba(38,117,191,.55);
|
|
54
|
+
--green:#2f8a5b; --orange:#d97706; --rose:#d6336c;
|
|
55
|
+
}
|
|
56
|
+
[data-theme="warm"]{
|
|
57
|
+
--bg:#f7ebd9; --bg2:#efe0c8; --panel:rgba(255,250,243,.97); --panel-solid:#fffaf3;
|
|
58
|
+
--text:#43301f; --muted:#8a7565; --accent:#d97706; --accent2:#ea580c;
|
|
59
|
+
--border:rgba(217,119,6,.18); --glow:rgba(217,119,6,.22); --glow-soft:rgba(217,119,6,.14);
|
|
60
|
+
--title-grad:linear-gradient(90deg,#b45309,#d97706 50%,#ea580c);
|
|
61
|
+
--tag-bg:rgba(217,119,6,.1);
|
|
62
|
+
--card-shadow:0 1px 2px rgba(120,72,24,.07),0 10px 28px rgba(120,72,24,.13);
|
|
63
|
+
--scan:rgba(217,119,6,.16); --scan-dim:rgba(217,119,6,.04);
|
|
64
|
+
--heat:rgba(217,119,6,.55);
|
|
65
|
+
--green:#0d9488; --orange:#c2410c; --rose:#be123c;
|
|
66
|
+
}
|
|
67
|
+
[data-theme="biz"] .stars, [data-theme="light"] .stars, [data-theme="warm"] .stars{ opacity:.28; }
|
|
68
|
+
[data-theme="mono"] .stars{ background:radial-gradient(1px 1px at 12% 22%,rgba(223,225,229,.32),transparent),radial-gradient(1px 1px at 28% 68%,rgba(223,225,229,.28),transparent),radial-gradient(1.5px 1.5px at 45% 15%,rgba(223,225,229,.24),transparent),radial-gradient(1px 1px at 62% 78%,rgba(223,225,229,.26),transparent),radial-gradient(1px 1px at 78% 32%,rgba(223,225,229,.3),transparent),radial-gradient(1.5px 1.5px at 88% 58%,rgba(223,225,229,.28),transparent),radial-gradient(1px 1px at 8% 85%,rgba(223,225,229,.26),transparent),radial-gradient(1px 1px at 55% 45%,rgba(223,225,229,.24),transparent)}
|
|
69
|
+
|
|
70
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
71
|
+
html,body{background:var(--bg)}
|
|
72
|
+
body{
|
|
73
|
+
font-family:ui-monospace,'SF Mono',SFMono-Regular,Menlo,Consolas,'PingFang SC','Microsoft YaHei',monospace;
|
|
74
|
+
color:var(--text);-webkit-font-smoothing:antialiased;overflow-x:hidden;
|
|
75
|
+
}
|
|
76
|
+
.grid-pattern{position:fixed;inset:0;z-index:0;pointer-events:none;
|
|
77
|
+
background:linear-gradient(var(--scan-dim) 1px,transparent 1px),linear-gradient(90deg,var(--scan-dim) 1px,transparent 1px);
|
|
78
|
+
background-size:60px 60px}
|
|
79
|
+
.stars{position:fixed;inset:0;z-index:0;pointer-events:none;
|
|
80
|
+
background:radial-gradient(1px 1px at 12% 22%,rgba(255,255,255,.4),transparent),radial-gradient(1px 1px at 28% 68%,rgba(0,240,255,.5),transparent),radial-gradient(1.5px 1.5px at 45% 15%,rgba(168,85,247,.4),transparent),radial-gradient(1px 1px at 62% 78%,rgba(0,255,136,.4),transparent),radial-gradient(1px 1px at 78% 32%,rgba(255,255,255,.35),transparent),radial-gradient(1.5px 1.5px at 88% 58%,rgba(0,240,255,.45),transparent),radial-gradient(1px 1px at 8% 85%,rgba(255,255,255,.3),transparent),radial-gradient(1px 1px at 55% 45%,rgba(0,240,255,.35),transparent)}
|
|
81
|
+
.scanlines{position:fixed;inset:0;z-index:999;pointer-events:none;
|
|
82
|
+
background:repeating-linear-gradient(0deg,transparent,transparent 2px,var(--scan-dim) 2px,var(--scan-dim) 4px)}
|
|
83
|
+
.scanband{position:fixed;left:0;right:0;height:150px;z-index:998;pointer-events:none;
|
|
84
|
+
background:linear-gradient(180deg,transparent,var(--scan-dim) 50%,transparent);
|
|
85
|
+
animation:scanMove 11s linear infinite}
|
|
86
|
+
@keyframes scanMove{from{top:-22%}to{top:112%}}
|
|
87
|
+
.wrap{width:clamp(640px, 60%, 1200px); margin:0 auto; position:relative; z-index:1; padding:40px 0}
|
|
88
|
+
.header-card{position:relative;overflow:hidden;background:var(--panel-solid);border:1px solid var(--border);border-radius:6px;
|
|
89
|
+
padding:34px 28px 26px;text-align:center;margin-bottom:18px;
|
|
90
|
+
box-shadow:var(--card-shadow);
|
|
91
|
+
background-image:repeating-linear-gradient(180deg, rgba(255,255,255,.012) 0 1px, transparent 1px 8px)}
|
|
92
|
+
.header-card h1{font-size:26px;letter-spacing:2px;margin-bottom:8px;
|
|
93
|
+
background:var(--title-grad);-webkit-background-clip:text;background-clip:text;color:transparent;
|
|
94
|
+
animation:titleGlow 3s ease-in-out infinite}
|
|
95
|
+
@keyframes titleGlow{0%,100%{text-shadow:0 0 8px var(--glow),0 0 22px var(--glow-soft)}50%{text-shadow:0 0 14px var(--glow),0 0 34px var(--glow-soft)}}
|
|
96
|
+
.header-sub{font-size:12px;color:var(--muted);letter-spacing:1px;margin-bottom:12px}
|
|
97
|
+
.header-badge{display:inline-block;font-size:11px;color:var(--accent);border:1px solid var(--glow);border-radius:999px;padding:4px 14px}
|
|
98
|
+
.card-glow{position:absolute;inset:-40% -20% auto;height:70%;pointer-events:none;
|
|
99
|
+
background:radial-gradient(ellipse at 50% 10%,var(--glow),transparent 70%);
|
|
100
|
+
animation:cardGlow 3s ease-in-out infinite;transform-origin:top center;opacity:.5}
|
|
101
|
+
@keyframes cardGlow{0%,100%{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.6)}}
|
|
102
|
+
.scanline-el{position:absolute;pointer-events:none}
|
|
103
|
+
.scan-x{top:0;left:0;height:1px;width:100%;background:linear-gradient(90deg,transparent,var(--accent),transparent);animation:scanX 3s linear infinite}
|
|
104
|
+
.scan-y{top:0;right:0;width:1px;height:100%;background:linear-gradient(180deg,transparent,var(--accent),transparent);animation:scanY 3s linear infinite}
|
|
105
|
+
.scan-x-rev{bottom:0;left:0;height:1px;width:100%;background:linear-gradient(90deg,transparent,var(--accent),transparent);animation:scanXRev 3s linear infinite}
|
|
106
|
+
.scan-y-rev{top:0;left:0;width:1px;height:100%;background:linear-gradient(180deg,transparent,var(--accent),transparent);animation:scanYRev 3s linear infinite}
|
|
107
|
+
@keyframes scanX{from{transform:translateX(-100%)}to{transform:translateX(100%)}}
|
|
108
|
+
@keyframes scanY{from{transform:translateY(-100%)}to{transform:translateY(100%)}}
|
|
109
|
+
@keyframes scanXRev{from{transform:translateX(100%)}to{transform:translateX(-100%)}}
|
|
110
|
+
@keyframes scanYRev{from{transform:translateY(100%)}to{transform:translateY(-100%)}}
|
|
111
|
+
.section{position:relative;overflow:hidden;background:var(--panel-solid);border:1px solid var(--border);border-radius:6px;
|
|
112
|
+
padding:22px 24px 22px 32px;margin-bottom:18px;
|
|
113
|
+
box-shadow:var(--card-shadow);
|
|
114
|
+
background-image:repeating-linear-gradient(180deg, rgba(255,255,255,.012) 0 1px, transparent 1px 8px);
|
|
115
|
+
transition:transform .18s ease,box-shadow .18s ease}
|
|
116
|
+
.section:hover{transform:translateY(-2px);box-shadow:var(--card-shadow),inset 0 0 22px var(--glow-soft)}
|
|
117
|
+
.sec-bar{position:absolute;left:0;top:0;bottom:0;width:8px}
|
|
118
|
+
.sec-ov .sec-bar{background:linear-gradient(180deg,var(--accent2),var(--accent));box-shadow:0 0 12px var(--glow)}
|
|
119
|
+
.sec-ms .sec-bar{background:linear-gradient(180deg,#5eead4,#14b8a6);box-shadow:0 0 12px rgba(20,184,166,.3)}
|
|
120
|
+
.sec-pi .sec-bar{background:linear-gradient(180deg,#fda4af,#e11d48);box-shadow:0 0 12px rgba(244,63,94,.3)}
|
|
121
|
+
.sec-nm .sec-bar{background:linear-gradient(180deg,#fdba74,#f97316);box-shadow:0 0 12px rgba(249,115,22,.3)}
|
|
122
|
+
.sec-head{display:flex;align-items:center;gap:10px;margin-bottom:16px}
|
|
123
|
+
.sec-head svg{flex:0 0 auto}
|
|
124
|
+
.sec-head h2{font-size:18px;letter-spacing:1px;animation:secGlow 3s ease-in-out infinite}
|
|
125
|
+
.sec-ov .sec-head h2{color:var(--accent)}.sec-ms .sec-head h2{color:#5eead4}
|
|
126
|
+
.sec-pi .sec-head h2{color:#fda4af}.sec-nm .sec-head h2{color:#fdba74}
|
|
127
|
+
@keyframes secGlow{0%,100%{text-shadow:0 0 6px var(--glow)}50%{text-shadow:0 0 14px var(--glow)}}
|
|
128
|
+
.tldr-line{font-size:15px;line-height:1.75;margin-bottom:18px}
|
|
129
|
+
.tldr-line b{color:var(--accent);font-weight:700}
|
|
130
|
+
.stat-row{display:flex;gap:12px;flex-wrap:wrap}
|
|
131
|
+
.stat-card{flex:1 1 160px;position:relative;background:var(--tag-bg);border:1px solid var(--border);
|
|
132
|
+
border-radius:6px;padding:16px 14px;min-width:140px;overflow:hidden;
|
|
133
|
+
transition:transform .18s ease,box-shadow .18s ease}
|
|
134
|
+
.stat-card:hover{transform:translateY(-2px);box-shadow:0 8px 20px rgba(0,0,0,.35)}
|
|
135
|
+
.stat-card::before{content:'';position:absolute;left:0;top:0;bottom:0;width:4px;background:linear-gradient(180deg,var(--accent2),var(--accent))}
|
|
136
|
+
.stat-num{font-size:28px;font-weight:900;letter-spacing:1px;
|
|
137
|
+
background:var(--title-grad);-webkit-background-clip:text;background-clip:text;color:transparent}
|
|
138
|
+
.stat-label{font-size:12px;color:var(--muted);margin-top:6px}
|
|
139
|
+
.stat-cmp{font-size:11.5px;margin-top:3px}
|
|
140
|
+
.stat-cmp.up{color:var(--green)}
|
|
141
|
+
.stat-cmp.down{color:var(--rose)}
|
|
142
|
+
.timeline{position:relative;padding-left:26px}
|
|
143
|
+
.timeline::before{content:'';position:absolute;left:7px;top:6px;bottom:6px;width:2px;background:linear-gradient(180deg,var(--glow),var(--glow-soft))}
|
|
144
|
+
.tl-group{position:relative;margin-bottom:18px}
|
|
145
|
+
.tl-node{position:absolute;left:-26px;top:0;width:16px;height:16px;border-radius:50%;
|
|
146
|
+
display:flex;align-items:center;justify-content:center;font-size:8px;font-weight:900;color:#fff}
|
|
147
|
+
.tl-node.m1,.tl-node.m2,.tl-node.q1,.tl-node.q2,.tl-node.q3{background:radial-gradient(circle at 30% 28%,#64748b,#475569 60%,#334155);box-shadow:0 0 8px rgba(100,116,139,.3)}
|
|
148
|
+
.tl-node.m3,.tl-node.q4{background:radial-gradient(circle at 30% 28%,#7dd3fc,#0ea5e9 55%,#0369a1);box-shadow:0 0 10px rgba(14,165,233,.5);animation:nodePulse 2.4s ease-in-out infinite}
|
|
149
|
+
@keyframes nodePulse{0%,100%{box-shadow:0 0 8px rgba(14,165,233,.4)}50%{box-shadow:0 0 18px rgba(14,165,233,.8)}}
|
|
150
|
+
.tl-q{font-size:12px;font-weight:700;color:var(--accent);letter-spacing:1px;margin-bottom:8px}
|
|
151
|
+
.tl-item{position:relative;padding:10px 0 10px 16px;border-top:1px dashed var(--border)}
|
|
152
|
+
.tl-item::before{content:'';position:absolute;left:0;top:19px;width:5px;height:5px;border-radius:50%;background:rgba(94,234,212,.8);box-shadow:0 0 6px rgba(94,234,212,.5)}
|
|
153
|
+
.tl-desc{font-size:15px;line-height:1.65}
|
|
154
|
+
.tl-meta{font-size:12px;color:var(--muted);margin-top:4px}
|
|
155
|
+
.tl-badge{display:inline-block;font-size:11px;color:var(--muted);border:1px solid var(--border);border-radius:999px;padding:1px 10px;margin-left:6px}
|
|
156
|
+
.tl-empty{font-size:13px;color:var(--muted);padding:6px 0 10px 16px}
|
|
157
|
+
.cb-wrap{margin-top:18px;padding-top:14px;border-top:1px dashed var(--border)}
|
|
158
|
+
.cb-title{font-size:12px;color:var(--muted);margin-bottom:12px;letter-spacing:1px}
|
|
159
|
+
.ech{width:100%;height:200px}
|
|
160
|
+
.ech-off{display:flex;align-items:center;justify-content:center}
|
|
161
|
+
.ech-off::after{content:attr(data-off);font-size:11px;color:var(--muted);text-align:center;line-height:1.6;padding:0 10px}
|
|
162
|
+
.idx{flex:0 0 auto;width:28px;height:28px;border-radius:50%;position:relative;
|
|
163
|
+
display:flex;align-items:center;justify-content:center;color:#fff;
|
|
164
|
+
font-size:12px;font-weight:900;margin-top:2px;transition:transform .2s ease,font-size .2s ease}
|
|
165
|
+
.idx.pi{background:radial-gradient(circle at 30% 28%,#fdaab4,#f43f5e 55%,#be123c);
|
|
166
|
+
box-shadow:0 2px 4px rgba(0,0,0,.25),0 0 8px rgba(244,63,94,.4),inset -3px -4px 6px rgba(0,0,0,.3),inset 1px 2px 3px rgba(255,255,255,.25)}
|
|
167
|
+
.idx::before{content:'';position:absolute;top:5px;left:7px;width:8px;height:6px;border-radius:50%;
|
|
168
|
+
background:radial-gradient(circle,rgba(255,255,255,.7),rgba(255,255,255,0));transform:rotate(-28deg);pointer-events:none}
|
|
169
|
+
.idx b{display:inline-block;transition:transform .2s ease}
|
|
170
|
+
.entry{flex:1;min-width:0}
|
|
171
|
+
.entry-head{display:flex;align-items:flex-start;gap:12px}
|
|
172
|
+
.desc{font-size:15px;line-height:1.65}
|
|
173
|
+
.meta{display:block;font-size:12px;color:var(--muted);margin-top:4px}
|
|
174
|
+
.meta b{color:var(--accent);font-weight:700}
|
|
175
|
+
ol{list-style:none}
|
|
176
|
+
li{display:flex;align-items:flex-start;gap:12px;padding:10px;border-radius:4px;transition:background .18s}
|
|
177
|
+
li:hover{background:var(--tag-bg)}
|
|
178
|
+
li:hover .idx{transform:scale(1.18) rotate(-4deg);font-size:14px}
|
|
179
|
+
li:hover .idx b{transform:rotate(-6deg)}
|
|
180
|
+
.goal{background:rgba(249,115,22,.04);border:1px solid rgba(249,115,22,.18);border-radius:6px;
|
|
181
|
+
padding:14px 16px;margin-bottom:12px;transition:transform .18s ease,box-shadow .18s ease}
|
|
182
|
+
.goal:hover{transform:translateY(-2px);box-shadow:0 8px 20px rgba(0,0,0,.3)}
|
|
183
|
+
.goal-desc{font-size:15px;line-height:1.65;margin-bottom:8px}
|
|
184
|
+
.goal-desc b{color:#fdba74;font-weight:700}
|
|
185
|
+
.goal-q{display:flex;flex-wrap:wrap;gap:6px}
|
|
186
|
+
.q-chip{font-size:11px;color:var(--muted);border:1px solid var(--border);background:var(--tag-bg);
|
|
187
|
+
border-radius:999px;padding:2px 10px}
|
|
188
|
+
.copy-wrap{display:flex;justify-content:center;margin:18px 0 0}
|
|
189
|
+
.copy-btn{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:700;color:#fff;letter-spacing:2px;
|
|
190
|
+
background:linear-gradient(135deg,var(--accent),var(--accent2));border:none;border-radius:999px;padding:12px 38px;cursor:pointer;
|
|
191
|
+
box-shadow:0 0 30px var(--glow);transition:transform .18s ease,box-shadow .18s ease;
|
|
192
|
+
font-family:inherit}
|
|
193
|
+
.copy-btn:hover{transform:translateY(-2px);box-shadow:0 0 45px var(--glow)}
|
|
194
|
+
.copy-btn:active{transform:translateY(1px) scale(.98)}
|
|
195
|
+
footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;padding:8px 0 4px}
|
|
196
|
+
.header-card{animation:fadeDown .6s ease-out backwards}
|
|
197
|
+
.sec-ov{animation:riseIn .5s ease-out .13s backwards}
|
|
198
|
+
.sec-ms{animation:riseIn .5s ease-out .26s backwards}
|
|
199
|
+
.sec-pi{animation:riseIn .5s ease-out .4s backwards}
|
|
200
|
+
.sec-nm{animation:riseIn .5s ease-out .54s backwards}
|
|
201
|
+
.copy-wrap{animation:popIn .4s ease-out .8s backwards}
|
|
202
|
+
@keyframes fadeDown{from{opacity:0;transform:translateY(-14px)}to{opacity:1;transform:none}}
|
|
203
|
+
@keyframes riseIn{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
|
|
204
|
+
@keyframes popIn{from{opacity:0;transform:scale(.85)}to{opacity:1;transform:none}}
|
|
205
|
+
.section:hover{transform:perspective(900px) translateY(-2px) rotateY(calc(var(--mx,0)*2.5deg)) rotateX(calc(var(--my,0)*-2.5deg))}
|
|
206
|
+
.theme-dock{
|
|
207
|
+
position:fixed; right:18px; bottom:18px; z-index:1001;
|
|
208
|
+
display:flex; gap:8px; padding:8px 10px; border-radius:999px;
|
|
209
|
+
background:var(--panel-solid); border:1px solid var(--border);
|
|
210
|
+
box-shadow:0 4px 18px rgba(0,0,0,.3);
|
|
211
|
+
}
|
|
212
|
+
.theme-dock .th-dot{
|
|
213
|
+
width:22px; height:22px; border-radius:50%; cursor:pointer;
|
|
214
|
+
border:2px solid transparent; padding:0;
|
|
215
|
+
transition:transform .15s ease, border-color .15s ease;
|
|
216
|
+
}
|
|
217
|
+
.theme-dock .th-dot:hover{ transform:scale(1.18); }
|
|
218
|
+
.theme-dock .th-dot.on{ border-color:var(--text); }
|
|
219
|
+
.theme-dock .th-dot[data-theme="tech"]{ background:#0ea5e9; }
|
|
220
|
+
.theme-dock .th-dot[data-theme="biz"]{ background:#2563eb; }
|
|
221
|
+
.theme-dock .th-dot[data-theme="mono"]{ background:#1e1f22; }
|
|
222
|
+
.theme-dock .th-dot[data-theme="light"]{ background:#ffffff; }
|
|
223
|
+
.theme-dock .th-dot[data-theme="warm"]{ background:#d97706; }
|
|
224
|
+
@media print{ .theme-dock{ display:none; } .rv{ opacity:1 !important; translate:none !important; } }
|
|
225
|
+
html.js .rv{ opacity:0; translate:0 16px; transition:opacity .5s ease-out, translate .5s ease-out; }
|
|
226
|
+
html.js .rv.in{ opacity:1; translate:0 0; }
|
|
227
|
+
@media (max-width:680px){
|
|
228
|
+
body{ padding:24px 12px 32px; }
|
|
229
|
+
.wrap{ width:100%; max-width:none; }
|
|
230
|
+
.header-card{ padding:26px 18px 20px; }
|
|
231
|
+
.header-card h1{ font-size:26px; }
|
|
232
|
+
}
|
|
233
|
+
</style>
|
|
234
|
+
</head>
|
|
235
|
+
<body>
|
|
236
|
+
<div class="grid-pattern"></div>
|
|
237
|
+
<div class="stars"></div>
|
|
238
|
+
<div class="scanband"></div>
|
|
239
|
+
<div class="scanlines"></div>
|
|
240
|
+
<div class="wrap">
|
|
241
|
+
<header class="header-card" id="headerCard">
|
|
242
|
+
<span class="scanline-el scan-x"></span>
|
|
243
|
+
<span class="scanline-el scan-y"></span>
|
|
244
|
+
<span class="scanline-el scan-x-rev"></span>
|
|
245
|
+
<span class="scanline-el scan-y-rev"></span>
|
|
246
|
+
<div class="card-glow"></div>
|
|
247
|
+
<h1>2026-Q4 研发季度总结</h1>
|
|
248
|
+
<div class="header-sub">全栈开发工程师 · 2026-10-01 ~ 2026-11-12(截至 11-12)</div>
|
|
249
|
+
<span class="header-badge">生成时间 2026-11-12 19:10:38</span>
|
|
250
|
+
<div class="copy-wrap">
|
|
251
|
+
<button class="copy-btn" id="copyBtn" type="button">
|
|
252
|
+
<svg id="copyIcon" viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.4">
|
|
253
|
+
<rect x="5.5" y="5.5" width="8.5" height="8.5" rx="1.5"/>
|
|
254
|
+
<path d="M10.5 5.5V4a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 4v5A1.5 1.5 0 0 0 4 10.5h1.5"/>
|
|
255
|
+
</svg>
|
|
256
|
+
<span id="copyText">一键复制</span>
|
|
257
|
+
</button>
|
|
258
|
+
</div>
|
|
259
|
+
</header>
|
|
260
|
+
|
|
261
|
+
<section class="section sec-ov">
|
|
262
|
+
<div class="sec-bar"></div>
|
|
263
|
+
<div class="card-glow"></div>
|
|
264
|
+
<div class="sec-head">
|
|
265
|
+
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 15l4-5M8 15l4-5"/><circle cx="12" cy="14" r="8"/><path d="M12 14l4-5"/></svg>
|
|
266
|
+
<h2>季度概览</h2>
|
|
267
|
+
</div>
|
|
268
|
+
<div class="tldr-line"><b>TL;DR:</b>收敛与沉淀的一季:双周聚合发布全面落地,季度版本数从上季度 42 个收敛到 25 个,质量门禁覆盖全部命令族,示例项目 进入稳定迭代期。</div>
|
|
269
|
+
<div class="stat-row">
|
|
270
|
+
<div class="stat-card"><div class="stat-num">256</div><div class="stat-label">季度提交数(10-01 ~ 11-12)</div><div class="stat-cmp up">较上季度:+12%</div><div class="stat-cmp up">较去年同期:+35%</div></div>
|
|
271
|
+
<div class="stat-card"><div class="stat-num">25</div><div class="stat-label">版本发布(v8.3.377 → v8.3.412)</div><div class="stat-cmp down">较上季度:-40%(主动收敛)</div><div class="stat-cmp up">较去年同期:+8%</div></div>
|
|
272
|
+
<div class="stat-card"><div class="stat-num">+4.6万</div><div class="stat-label">净增代码行(+6.2万 / -1.6万)</div><div class="stat-cmp up">较上季度:+5%</div><div class="stat-cmp up">较去年同期:+20%</div></div>
|
|
273
|
+
<div class="stat-card"><div class="stat-num">96%</div><div class="stat-label">质量门禁通过率(季度全量)</div><div class="stat-cmp up">较上季度:+11%</div><div class="stat-cmp up">较去年同期:+24%</div></div>
|
|
274
|
+
</div>
|
|
275
|
+
<div class="cb-wrap">
|
|
276
|
+
<div class="cb-title">Q1-Q4 季度走势(提交数)</div>
|
|
277
|
+
<div class="ech" id="quarterChart" data-off="图表需联网加载 echarts,离线环境不显示"></div>
|
|
278
|
+
</div>
|
|
279
|
+
</section>
|
|
280
|
+
|
|
281
|
+
<section class="section sec-ms">
|
|
282
|
+
<div class="sec-bar"></div>
|
|
283
|
+
<div class="card-glow"></div>
|
|
284
|
+
<div class="sec-head">
|
|
285
|
+
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="#5eead4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4h12v3a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V4z"/><path d="M12 11v4M9 17h6v3H9z"/></svg>
|
|
286
|
+
<h2>季度关键成果</h2>
|
|
287
|
+
</div>
|
|
288
|
+
<div class="timeline">
|
|
289
|
+
<div class="tl-group">
|
|
290
|
+
<span class="tl-node m1">M1</span>
|
|
291
|
+
<div class="tl-q">第 1 月 · 10 月(10-01 ~ 10-31)</div>
|
|
292
|
+
<div class="tl-item"><div class="tl-desc">1、双周聚合发布机制上线:v8.3.377 起按双周批次发布,单批 ≤10 版本</div><div class="tl-meta">82 次提交 · +1.9 万行<span class="tl-badge">M1 · 10 月</span></div></div>
|
|
293
|
+
<div class="tl-item"><div class="tl-desc">2、发布平台 v0.4.0 发布:WebAuthn 破局发布认证,CI 自动建仓通道打通</div><div class="tl-meta">18 个版本<span class="tl-badge">M1 · 10 月</span></div></div>
|
|
294
|
+
<div class="tl-item"><div class="tl-desc">3、反推域隔离上线:global from-source 与 global analyze 职责彻底分离</div><div class="tl-meta">36 次提交<span class="tl-badge">M1 · 10 月</span></div></div>
|
|
295
|
+
</div>
|
|
296
|
+
<div class="tl-group">
|
|
297
|
+
<span class="tl-node m2">M2</span>
|
|
298
|
+
<div class="tl-q">第 2 月 · 11 月(11-01 ~ 11-30,截至当前)</div>
|
|
299
|
+
<div class="tl-item"><div class="tl-desc">4、质量门禁补全:execute 用例核对闸覆盖全部命令族,error 拦截率 100%</div><div class="tl-meta">52 次提交 · +1.1 万行<span class="tl-badge">M2 · 11 月</span></div></div>
|
|
300
|
+
<div class="tl-item"><div class="tl-desc">5、v8.3.412 累积发布:文档生成器升格、澄清链修复、测试工具 CLI v0.1.0 首发</div><div class="tl-meta">12 个版本<span class="tl-badge">M2 · 11 月</span></div></div>
|
|
301
|
+
<div class="tl-item"><div class="tl-desc">6、季报技能孵化:Q1-Q4 时间线 + 环比/同比双基准,汇报链补全五选一</div><div class="tl-meta">技能仓库<span class="tl-badge">M2 · 11 月</span></div></div>
|
|
302
|
+
</div>
|
|
303
|
+
<div class="tl-group">
|
|
304
|
+
<span class="tl-node m3">M3</span>
|
|
305
|
+
<div class="tl-q">第 3 月 · 12 月(12-01 ~ 12-31)</div>
|
|
306
|
+
<div class="tl-empty">尚未开始(示例占位)</div>
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
</section>
|
|
310
|
+
|
|
311
|
+
<section class="section sec-pi">
|
|
312
|
+
<div class="sec-bar"></div>
|
|
313
|
+
<div class="card-glow"></div>
|
|
314
|
+
<div class="sec-head">
|
|
315
|
+
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="#fda4af" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 9v4M12 17h.01"/><path d="M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/></svg>
|
|
316
|
+
<h2>问题与改进</h2>
|
|
317
|
+
</div>
|
|
318
|
+
<ol>
|
|
319
|
+
<li><span class="idx pi"><b>1</b></span><div class="entry"><div class="desc">版本发布节奏季度内波动明显:10 月 18 个版本、11 月仅 12 个,双周批次粒度仍需校准。</div><div class="meta">影响:回归验证耗时拖慢交付节奏,季度后半程发力不均。</div><div class="meta" style="color:var(--accent)"><b style="color:var(--accent)">改进:</b>Q1 起固定单批 ≤6 版本,验证前置到开发期,季度内月度版本数波动控制在 ±30% 内。</div></div></li>
|
|
320
|
+
<li><span class="idx pi"><b>2</b></span><div class="entry"><div class="desc">季度数据画像不完整:热力图仅覆盖主仓库,辅助仓库提交未纳入统计。</div><div class="meta">影响:季度工作量画像与环比/同比口径偏窄,双基准可比性打折。</div><div class="meta" style="color:var(--accent)"><b style="color:var(--accent)">改进:</b>数据收集层支持多仓合并去重,本季度内上线,下季度双基准全面覆盖。</div></div></li>
|
|
321
|
+
</ol>
|
|
322
|
+
</section>
|
|
323
|
+
|
|
324
|
+
<section class="section sec-nm">
|
|
325
|
+
<div class="sec-bar"></div>
|
|
326
|
+
<div class="card-glow"></div>
|
|
327
|
+
<div class="sec-head">
|
|
328
|
+
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="#fdba74" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="17" rx="2"/><path d="M8 2v4M16 2v4M3 10h18"/></svg>
|
|
329
|
+
<h2>下季度计划</h2>
|
|
330
|
+
</div>
|
|
331
|
+
<div class="goal"><div class="goal-desc">1、<b>发布节奏固化</b>:单批 ≤6 版本、双周一档,季度版本发布总量 ≤20 个</div><div class="goal-q"><span class="q-chip">M1 建立模板</span><span class="q-chip">M2 稳定运行</span><span class="q-chip">M3 季度复盘</span></div></div>
|
|
332
|
+
<div class="goal"><div class="goal-desc">2、<b>多仓数据画像</b>:数据收集层多仓合并去重上线,双基准口径全覆盖</div><div class="goal-q"><span class="q-chip">M1 开发</span><span class="q-chip">M2 上线</span></div></div>
|
|
333
|
+
<div class="goal"><div class="goal-desc">3、<b>质量门禁全覆盖</b>:全部命令族门禁通过率 ≥95%,季度内无重大回退</div><div class="goal-q"><span class="q-chip">M2 补齐</span><span class="q-chip">M3 验收</span></div></div>
|
|
334
|
+
</section>
|
|
335
|
+
|
|
336
|
+
<footer>GENERATED BY AI TEAM · 2026-Q4</footer>
|
|
337
|
+
</div>
|
|
338
|
+
|
|
339
|
+
<div class="theme-dock" id="themeDock">
|
|
340
|
+
<button class="th-dot" type="button" data-theme="tech" title="深蓝科技"></button>
|
|
341
|
+
<button class="th-dot" type="button" data-theme="biz" title="浅色商务"></button>
|
|
342
|
+
<button class="th-dot" type="button" data-theme="mono" title="IDEA 黑亮"></button>
|
|
343
|
+
<button class="th-dot" type="button" data-theme="light" title="IDEA 白亮"></button>
|
|
344
|
+
<button class="th-dot" type="button" data-theme="warm" title="温暖渐变"></button>
|
|
345
|
+
</div>
|
|
346
|
+
|
|
347
|
+
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js"></script>
|
|
348
|
+
<script>
|
|
349
|
+
// 复制源 = txt 纯文本全文
|
|
350
|
+
var TXT = "2026-Q4 研发季度总结\n\n生成时间:2026-11-12 19:10:38\n\n季度概览\nTL;DR:收敛与沉淀的一季:双周聚合发布全面落地,季度版本数从上季度 42 个收敛到 25 个,质量门禁覆盖全部命令族,示例项目 进入稳定迭代期。\n1、季度提交数:256 次(10-01 ~ 11-12,较上季度 +12%,较去年同期 +35%)\n2、版本发布:25 个(v8.3.377 → v8.3.412,较上季度 -40% 主动收敛,较去年同期 +8%)\n3、净增代码:+4.6 万行(+6.2 万 / -1.6 万,较上季度 +5%,较去年同期 +20%)\n4、质量门禁通过率:96%(较上季度 +11%,较去年同期 +24%)\n\n季度关键成果\n1、双周聚合发布机制上线:v8.3.377 起按双周批次发布,单批 ≤10 版本(82 次提交、+1.9 万行)- M1 · 10 月\n2、发布平台 v0.4.0 发布:WebAuthn 破局发布认证,CI 自动建仓通道打通(18 个版本)- M1 · 10 月\n3、反推域隔离上线:global from-source 与 global analyze 职责彻底分离(36 次提交)- M1 · 10 月\n4、质量门禁补全:execute 用例核对闸覆盖全部命令族,error 拦截率 100%(52 次提交、+1.1 万行)- M2 · 11 月\n5、v8.3.412 累积发布:文档生成器升格、澄清链修复、测试工具 CLI v0.1.0 首发(12 个版本)- M2 · 11 月\n6、季报技能孵化:Q1-Q4 时间线 + 环比/同比双基准,汇报链补全五选一(技能仓库)- M2 · 11 月\n\n问题与改进\n1、版本发布节奏季度内波动明显:10 月 18 个版本、11 月仅 12 个,双周批次粒度仍需校准。\n影响:回归验证耗时拖慢交付节奏,季度后半程发力不均。\n改进:Q1 起固定单批 ≤6 版本,验证前置到开发期,季度内月度版本数波动控制在 ±30% 内。\n2、季度数据画像不完整:热力图仅覆盖主仓库,辅助仓库提交未纳入统计。\n影响:季度工作量画像与环比/同比口径偏窄,双基准可比性打折。\n改进:数据收集层支持多仓合并去重,本季度内上线,下季度双基准全面覆盖。\n\n下季度计划\n1、发布节奏固化:单批 ≤6 版本、双周一档,季度版本发布总量 ≤20 个(M1 建立模板、M2 稳定运行、M3 季度复盘)。\n2、多仓数据画像:数据收集层多仓合并去重上线,双基准口径全覆盖(M1 开发、M2 上线)。\n3、质量门禁全覆盖:全部命令族门禁通过率 ≥95%,季度内无重大回退(M2 补齐、M3 验收)。";
|
|
351
|
+
|
|
352
|
+
// 一键复制
|
|
353
|
+
var btn = document.getElementById('copyBtn');
|
|
354
|
+
var icon = document.getElementById('copyIcon');
|
|
355
|
+
var txt = document.getElementById('copyText');
|
|
356
|
+
btn.addEventListener('click', function(){
|
|
357
|
+
function done(){ icon.innerHTML = '<path d="M2.5 8.5l3.5 3.5 7-7.5"/>'; txt.textContent = '已复制'; setTimeout(function(){ icon.innerHTML = '<rect x="5.5" y="5.5" width="8.5" height="8.5" rx="1.5"/><path d="M10.5 5.5V4a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 4v5A1.5 1.5 0 0 0 4 10.5h1.5"/>'; txt.textContent = '一键复制'; }, 1600); }
|
|
358
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
359
|
+
navigator.clipboard.writeText(TXT).then(done, function(){ fallback(); });
|
|
360
|
+
} else { fallback(); }
|
|
361
|
+
function fallback(){
|
|
362
|
+
var ta = document.createElement('textarea');
|
|
363
|
+
ta.value = TXT; ta.style.position = 'fixed'; ta.style.opacity = '0';
|
|
364
|
+
document.body.appendChild(ta); ta.select();
|
|
365
|
+
try { document.execCommand('copy'); done(); } catch(e){}
|
|
366
|
+
document.body.removeChild(ta);
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
// 卡片级 3D 微倾斜(仅 hover 卡片)
|
|
371
|
+
document.querySelectorAll('.section').forEach(function(card){
|
|
372
|
+
card.addEventListener('mousemove', function(e){
|
|
373
|
+
var r = card.getBoundingClientRect();
|
|
374
|
+
var mx = (e.clientX - r.left) / r.width * 2 - 1;
|
|
375
|
+
var my = (e.clientY - r.top) / r.height * 2 - 1;
|
|
376
|
+
card.style.setProperty('--mx', mx.toFixed(3));
|
|
377
|
+
card.style.setProperty('--my', my.toFixed(3));
|
|
378
|
+
});
|
|
379
|
+
card.addEventListener('mouseleave', function(){
|
|
380
|
+
card.style.setProperty('--mx', 0);
|
|
381
|
+
card.style.setProperty('--my', 0);
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// ?shot=content:内容区截图模式
|
|
386
|
+
if (location.search.indexOf('shot=content') > -1) {
|
|
387
|
+
document.getElementById('headerCard').style.display = 'none';
|
|
388
|
+
document.querySelector('.copy-wrap').style.display = 'none';
|
|
389
|
+
document.querySelector('footer').style.display = 'none';
|
|
390
|
+
document.querySelector('.wrap').style.padding = '40px';
|
|
391
|
+
document.querySelectorAll('.header-card,.section,.copy-wrap').forEach(function(el){
|
|
392
|
+
el.style.animation = 'none'; el.style.opacity = '1';
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Q1-Q4 季度走势图(echarts CDN 渲染;离线时容器降级提示;?shot 截图模式停动画——headless 虚拟时间下动画帧不推进会停在初始帧)
|
|
397
|
+
(function(){
|
|
398
|
+
var el = document.getElementById('quarterChart');
|
|
399
|
+
if (!el) return;
|
|
400
|
+
if (typeof echarts === 'undefined'){ el.classList.add('ech-off'); return; }
|
|
401
|
+
var noAnim = location.search.indexOf('shot=') !== -1;
|
|
402
|
+
var chart = echarts.init(el);
|
|
403
|
+
var QVALS = [['Q1',68],['Q2',81],['Q3',96],['Q4',112]];
|
|
404
|
+
var CURQ = 'Q4';
|
|
405
|
+
function tokens(){
|
|
406
|
+
var s = getComputedStyle(document.documentElement);
|
|
407
|
+
return {
|
|
408
|
+
accent:s.getPropertyValue('--accent').trim(), accent2:s.getPropertyValue('--accent2').trim(),
|
|
409
|
+
muted:s.getPropertyValue('--muted').trim(), text:s.getPropertyValue('--text').trim(),
|
|
410
|
+
border:s.getPropertyValue('--border').trim(), panel:s.getPropertyValue('--panel-solid').trim(),
|
|
411
|
+
tagBg:s.getPropertyValue('--tag-bg').trim()
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
function option(){
|
|
415
|
+
var t = tokens();
|
|
416
|
+
return {
|
|
417
|
+
animation: !noAnim,
|
|
418
|
+
grid:{ top:22, left:6, right:6, bottom:6, containLabel:true },
|
|
419
|
+
tooltip:{ backgroundColor:t.panel, borderColor:t.border,
|
|
420
|
+
textStyle:{ color:t.text, fontSize:11 },
|
|
421
|
+
formatter:function(p){ return p.name + ' · ' + p.value + ' 次提交'; } },
|
|
422
|
+
xAxis:{ type:'category', data:QVALS.map(function(d){ return d[0]; }),
|
|
423
|
+
axisLine:{ lineStyle:{ color:t.border } },
|
|
424
|
+
axisTick:{ show:false },
|
|
425
|
+
axisLabel:{ fontSize:11, color:t.muted } },
|
|
426
|
+
yAxis:{ type:'value', splitLine:{ lineStyle:{ color:t.border } }, axisLabel:{ fontSize:10, color:t.muted } },
|
|
427
|
+
series:[{ type:'bar', barWidth:44,
|
|
428
|
+
itemStyle:{ borderRadius:[6,6,0,0] },
|
|
429
|
+
data:QVALS.map(function(d){
|
|
430
|
+
return { value:d[1], name:d[0],
|
|
431
|
+
itemStyle:{ color: d[0] === CURQ ? t.accent : t.tagBg,
|
|
432
|
+
borderColor: d[0] === CURQ ? t.accent2 : t.border, borderWidth:1 } };
|
|
433
|
+
}) }]
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
chart.setOption(option());
|
|
437
|
+
window.__sfEchartsTheme = function(){ chart.setOption(option()); };
|
|
438
|
+
window.addEventListener('resize', function(){ chart.resize(); });
|
|
439
|
+
})();
|
|
440
|
+
// 主题换肤:五套配色随点随换;记忆上次选择(localStorage,失败静默);?shot 截图模式隐藏坞
|
|
441
|
+
|
|
442
|
+
/* 稳定身份命名空间:localStorage 键按页内嵌唯一 ID(meta quarterly-id)命名——Chrome/Safari 下 file:// 与 localhost 共享同源存储,固定键名会导致多份产物互相串台;ID 与文件路径解耦,改名/移动目录记忆不丢 */
|
|
443
|
+
var SF_ID = ((document.querySelector('meta[name="quarterly-id"]') || {}).content || 'REF-QUARTERLY-0000').trim();
|
|
444
|
+
/* ID 格式自愈(格式定死执行层):meta 非法或缺失(占位残留/手写变体/误沿用旧值)时按路径键自愈为 crypto.randomUUID() 标准 v4,同路径跨打开稳定;合法 UUID 原样使用(复制文件副本=同一身份共享数据,是特性) */
|
|
445
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(SF_ID)) {
|
|
446
|
+
var __sfHealKey = 'sf-heal:' + location.pathname;
|
|
447
|
+
try { SF_ID = localStorage.getItem(__sfHealKey) || SF_ID; } catch (e) {}
|
|
448
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(SF_ID)) {
|
|
449
|
+
try { SF_ID = crypto.randomUUID(); } catch (e) {
|
|
450
|
+
SF_ID = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c){ var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8); return v.toString(16); });
|
|
451
|
+
}
|
|
452
|
+
try { localStorage.setItem(__sfHealKey, SF_ID); } catch (e) {}
|
|
453
|
+
}
|
|
454
|
+
var __sfMeta = document.querySelector('meta[name="quarterly-id"]');
|
|
455
|
+
if (__sfMeta) __sfMeta.setAttribute('content', SF_ID);
|
|
456
|
+
console.warn('[quarterly-report] meta quarterly-id 非法或缺失,已自愈为标准 v4 ID(' + SF_ID + '),建议重新生成页面固化');
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
var SF_NS = 'quarterly:' + SF_ID;
|
|
460
|
+
(function(){
|
|
461
|
+
var THEMES = ['tech','biz','mono','light','warm'];
|
|
462
|
+
var dock = document.getElementById('themeDock');
|
|
463
|
+
if (!dock) return;
|
|
464
|
+
if (location.search.indexOf('shot=') !== -1){ dock.style.display = 'none'; }
|
|
465
|
+
function apply(t){ document.documentElement.setAttribute('data-theme', t);
|
|
466
|
+
dock.querySelectorAll('.th-dot').forEach(function(d){ d.classList.toggle('on', d.getAttribute('data-theme') === t); });
|
|
467
|
+
try{ localStorage.setItem(SF_NS + '-theme', t); }catch(e){}
|
|
468
|
+
if (window.__sfEchartsTheme) window.__sfEchartsTheme(); }
|
|
469
|
+
var cur = document.documentElement.getAttribute('data-theme');
|
|
470
|
+
var saved = null; try{ saved = localStorage.getItem(SF_NS + '-theme') || localStorage.getItem('sf:' + location.pathname + '-theme'); }catch(e){}
|
|
471
|
+
if (saved && THEMES.indexOf(saved) !== -1 && saved !== cur){ apply(saved); }
|
|
472
|
+
else{ dock.querySelectorAll('.th-dot').forEach(function(d){ d.classList.toggle('on', d.getAttribute('data-theme') === (cur || 'tech')); }); }
|
|
473
|
+
dock.querySelectorAll('.th-dot').forEach(function(d){ d.addEventListener('click', function(){ apply(d.getAttribute('data-theme')); }); });
|
|
474
|
+
})();
|
|
475
|
+
|
|
476
|
+
/* 滚动入场:初始视口外的卡片滚到视口才上浮渐显(首屏卡维持加载错峰动画);无 JS 时 html.js 不生效全显 */
|
|
477
|
+
(function(){
|
|
478
|
+
if (location.search.indexOf('shot=') !== -1) return;
|
|
479
|
+
document.documentElement.classList.add('js');
|
|
480
|
+
if (!('IntersectionObserver' in window)) return;
|
|
481
|
+
var els = Array.prototype.slice.call(document.querySelectorAll('.header-card,.overview,.section'));
|
|
482
|
+
var rvs = [];
|
|
483
|
+
els.forEach(function(el){
|
|
484
|
+
if (el.getBoundingClientRect().top < innerHeight * 0.92) return;
|
|
485
|
+
el.classList.add('rv');
|
|
486
|
+
rvs.push(el);
|
|
487
|
+
});
|
|
488
|
+
if (!rvs.length) return;
|
|
489
|
+
var io = new IntersectionObserver(function(es){
|
|
490
|
+
es.forEach(function(e){
|
|
491
|
+
if (e.isIntersecting){ e.target.classList.add('in'); io.unobserve(e.target); }
|
|
492
|
+
});
|
|
493
|
+
}, { threshold: 0.08 });
|
|
494
|
+
rvs.forEach(function(el, i){
|
|
495
|
+
el.addEventListener('transitionend', function h(ev){
|
|
496
|
+
if (ev.target !== el) return;
|
|
497
|
+
el.style.transitionDelay = '';
|
|
498
|
+
el.removeEventListener('transitionend', h);
|
|
499
|
+
});
|
|
500
|
+
el.style.transitionDelay = Math.min(i * 70, 280) + 'ms';
|
|
501
|
+
io.observe(el);
|
|
502
|
+
});
|
|
503
|
+
setTimeout(function(){
|
|
504
|
+
document.querySelectorAll('.rv:not(.in)').forEach(function(el){ el.classList.add('in'); });
|
|
505
|
+
}, 2000);
|
|
506
|
+
})();
|
|
507
|
+
</script>
|
|
508
|
+
</body>
|
|
509
|
+
</html>
|