feat: add storyforge ops ui prototype and tracking digest

This commit is contained in:
kris
2026-03-22 07:38:49 +08:00
parent 6b3774b543
commit 6899ebba60
27 changed files with 3560 additions and 0 deletions

View File

@@ -12,6 +12,12 @@ StoryForge 现在拆成独立项目目录,和 `AI-glasses` 分开维护。
- `data/collector/`SQLite、任务文件、下载产物
- `docs/`:审计、实施计划、联调说明、当前 MVP 状态
## 产品手册
- [新媒体运营中台产品逻辑手册](./docs/PRODUCT_LOGIC_NEW_MEDIA_OPERATING_SYSTEM_2026-03-22.md)
- [新媒体运营平台 UI 参考包](./output/ui/new-media-ops-reference-2026-03-22/README.md)
- [Web V4 UI 原型](./output/ui/storyforge-web-v4-html-prototype-2026-03-22/README.md)
## Android
```bash

View File

@@ -0,0 +1,549 @@
# StoryForge 产品逻辑重构手册
日期2026-03-22
## 1. 目标重定义
StoryForge 不应再被定义成“AI 内容工具集合”。
更准确的定位应是:
**一个以“项目”为入口、以 Agent 为执行中枢、面向多平台账号经营的新媒体运营与生产中台。**
覆盖的平台至少包括:
- 小红书
- 抖音
- 快手
- 微信视频号
- YouTube
- 哔哩哔哩
新的核心能力不是“直接生成一条内容”,而是先完成:
1. 用户先建项目,明确这是已绑定账号项目还是预调研项目
2. 项目创建后先创建 Agent
3. Agent 完成账号画像、多平台市场调研和导入分析
4. 持续跟踪重点创作者的更新并自动汇总日报
5. 再把分析结果转成内容生产链与复盘闭环
## 2. 为什么要调整
之前的系统更偏:
- 任务中心
- Agent 中心
- Pipeline 中心
这对研发是友好的,但对创作者不够自然。
创作者真正的心智顺序是:
1. 我先要建一个项目
2. 这个项目是运营自己的账号,还是先做市场调研
3. 我应该先创建哪个 Agent
4. 这个 Agent 要服务哪些平台、靠什么变现
5. 参考作品和主页怎么导入,谁来分析
6. 哪条内容该走文案、封面、实拍剪辑还是 AI 视频
7. 产生的额度和成本怎么管
8. 发完之后效果如何
因此 StoryForge 的主对象必须重构。
## 3. 新的主对象模型
### 3.1 项目 Project
项目是 StoryForge 的第一层入口,分为两类:
- `bound_account_project`:已绑定账号项目,适合直接围绕自己的账号运营
- `pre_research_project`:预调研项目,适合先做市场和账号研究,再决定后续是否绑定账号
项目创建后,不直接进入生产,而是先进入 Agent 创建流程。
### 3.2 工作区 Workspace
代表一个团队、品牌、创作者个人,或者一个客户项目集合。
### 3.3 平台账号 Platform Account
按平台保存账号实体,必须带平台字段:
- `xiaohongshu`
- `douyin`
- `kuaishou`
- `wechat_video`
- `youtube`
- `bilibili`
账号类型分两类:
- `reference_account`:参考账号 / 精品账号 / 对标账号
- `owned_account`:自己在运营的账号
### 3.4 Agent
Agent 是项目内的执行中枢,不是用户直接操作内容的替代品。
创建 Agent 时必须定义:
- 账号类型
- 变现方式
- 目标平台
- 默认主大模型
- 可选对比模型
目标平台必须支持多选,至少包括:
- 小红书
- 抖音
- 快手
- 微信视频号
- YouTube
- 哔哩哔哩
Agent 创建完成后,默认先做多平台市场调研,再进入账号导入、分析、生产和复盘。
### 3.5 多平台市场调研
这是 Agent 创建后的第一步工作,不是可选项。
调研输出建议包含:
- 平台机会判断
- 账号类型差异
- 内容形态偏好
- 变现方式匹配度
- 竞争密度
- 适合先做的平台建议
### 3.6 账号画像 Account Insight
对一个账号的阶段性总结,不是单次报告。
建议固定结构:
- 账号定位
- 栏目结构
- 内容支柱
- 爆款规律
- 商业化机会
- 风险与短板
- 下阶段动作建议
### 3.7 作品 Content Item
所有作品统一抽象,不管来源于哪个平台,都进入统一作品库。
作品需要统一字段:
- 标题
- 平台
- 作者
- 发布时间
- 内容类型:视频 / 图文 / 长视频 / Shorts
- 互动指标:播放、点赞、评论、收藏、转发
- 平台原链接
- 标准化热度分
- 标准化商业价值分
- 标准化可复刻分
### 3.8 跟踪账号 Tracking Account
这是区别于“一次性导入”的持续性对象。
用户可以手动把某些参考账号加入跟踪列表,系统随后持续监控:
- 是否有新作品发布
- 自上次打开后新增了哪些内容
- 哪些新内容值得借鉴
- 应该送给哪个 Agent 做进一步学习
跟踪账号需要绑定:
- 平台
- 账号主页
- 所属项目
- 关联 Agent
- 是否开启自动日报
### 3.9 更新日报 Update Digest
日报不是固定按自然日生成,而是按“自用户上次打开后”或“自上次已读后”的更新窗口动态汇总。
例如:
- 用户 1 天没打开,则生成 1 天更新汇总
- 用户 5 天没打开,则自动生成 5 天汇总
日报内容应包含:
- 跟踪账号新增内容
- 作品摘要
- Agent 标注的借鉴点
- 风险点
- 建议动作
- 一键加入学习集 / Playbook / 作品库
### 3.10 内容打法 Playbook
从精品账号和高分作品中总结出的可学习方法论。
例如:
- 开头钩子模板
- 文案结构模板
- 镜头节奏模板
- 情绪驱动模板
- 选题组合模板
### 3.11 生产任务 Production Task
生产任务不是平台发现逻辑,而是执行逻辑。
统一分为:
- 文案生成任务
- 封面生成任务
- 实拍剪辑任务
- AI 视频任务
- 发布准备任务
- 复盘任务
### 3.12 发布复盘 Publish Review
真正的闭环在发布后。
复盘必须沉淀:
- 作品最终版本
- 发布时间
- 实际平台链接
- 实际数据表现
- 是否达到目标
- 下一步建议
## 4. 核心业务闭环
StoryForge 的闭环应该改成下面 8 步:
### 第 1 步:创建项目
用户先建项目,项目分两类:
- 已绑定账号项目:直接围绕自己的账号运营
- 预调研项目:先研究市场和参考账号,再决定是否进入绑定账号运营
### 第 2 步:创建 Agent
项目创建后先创建 Agent并在创建时定义
- 账号类型
- 变现方式
- 目标平台
- 默认主大模型
- 可选对比模型
### 第 3 步:多平台市场调研
Agent 创建后先做多平台市场调研,为项目判断优先平台和内容方向。
### 第 4 步:导入参考作品或主页
参考作品 / 参考主页导入时必须支持:
- 手动绑定 Agent
- 自动关联 Agent
导入后的分析不由用户手工处理,而由 Agent 负责完成。
### 第 5 步:跟踪重点账号并生成更新日报
用户可以把重点参考账号加入“跟踪账号”列表。
系统应在账号更新后自动:
- 抓取最新作品
- 汇总自上次打开后的新增内容
- 由关联 Agent 标注借鉴点
- 生成日报供用户进入系统后优先查看
### 第 6 步:沉淀账号画像与内容打法
Agent 将调研和导入分析结果转成结构化资产:
- 账号画像
- 内容打法
- Playbook
- 选题池
### 第 7 步:进入生产链
生产链统一分流为:
- 文案
- 封面生成
- 实拍剪辑
- AI 视频
### 第 8 步:发布与复盘
发布后把真实反馈写回系统,更新:
- 项目策略
- 账号策略
- 选题池
- Playbook
- Agent 学习集
## 5. 页面与信息架构
## 5.1 Web 端一级导航
建议固定为:
- 运营总台
- 项目中心
- Agent 工作台
- 账号发现
- 跟踪账号
- 参考账号库
- 自运营账号
- 作品库
- Playbook
- 生产中心
- 发布与复盘
- 设置
## 5.2 运营总台
首页不应该先展示工具,而应该先展示业务动作:
- 今日待办
- 待创建的项目
- 待创建的 Agent
- 新发现的高价值账号
- 新发现的高价值作品
- 本周重点选题
- 待生产任务
- 待复盘任务
- 平台异常提醒
## 5.3 账号发现页
这个页面应借鉴 `飞瓜 / 千瓜` 的榜单和筛选思路。
核心结构:
- 页内搜索
- 顶部平台切换
- 赛道筛选
- 榜单类型切换
- 排序切换
- 列表区
- 右侧快速加入参考池
补充要求:
- 全局搜索保留,但账号发现页必须有页内搜索
- 页内搜索支持账号名、主页链接、作品链接、关键词
- “变现方式”不应只保留单一选项,至少支持不限、知识付费、广告合作、带货转化、私域咨询
## 5.4 跟踪账号页
这是一个高价值的持续运营页面,必须进入一级导航。
核心结构:
- 跟踪账号列表
- 最近更新时间
- 关联 Agent
- 更新日报
- 借鉴点标注
- 一键加入学习集 / Playbook / 作品库
逻辑要求:
- 跟踪账号由用户手动添加
- 系统自动监控更新
- 日报按“上次打开后”汇总,而不是死板按自然日切分
- 如果用户多天未登录,则进入平台后看到的是多天汇总日报
## 5.5 参考账号工作区
每个参考账号要有独立工作区,不只是“详情页”。
建议页签:
- 总览
- 作品
- 账号画像
- 内容打法
- 相似账号
- 已学习 Agent
## 5.6 项目中心
项目中心是新的主入口,建议展示:
- 项目类型
- 绑定状态
- 已创建 Agent
- 调研状态
- 导入状态
- 生产进度
- 复盘状态
项目详情里要能直接进入 Agent 创建和 Agent 管理。
## 5.7 自运营账号工作区
比参考账号多两块:
- 生产计划
- 发布复盘
## 5.8 作品库
作品库是最重要的资产页之一。
必须支持:
- 平台筛选
- 类型筛选
- 时间筛选
- AI 分数排序
- 互动热度排序
- 商业价值排序
- 可复刻排序
每条作品下面必须同时展示:
- 基础数据
- AI 摘要
- 可借鉴点
- 风险点
- 一键加入 Playbook / 选题池 / Agent 学习集
## 5.9 Playbook 页
这是 StoryForge 未来的核心资产层。
Playbook 不能只是文本。
应结构化为:
- 适用平台
- 适用赛道
- 适用人群
- 钩子模板
- 结构模板
- 表达模板
- 商业承接方式
- 不适用场景
## 5.10 Agent 工作台
Agent 页面不要做成技术配置页。
应分为:
- 学习源
- 能力标签
- 当前任务
- 输出风格
- 产出记录
- 账号类型
- 变现方式
- 目标平台
- 默认主大模型
- 可选对比模型
高级 Prompt 和模型切换才进入高级设置。
## 5.11 生产中心
生产中心统一承接所有内容生产,不要再拆成分散入口。
主分流:
- 文案
- 封面生成
- 实拍剪辑
- AI 视频
## 5.12 发布与复盘
这个模块是现在最缺的。
建议结构:
- 待发布
- 已发布
- 7 日复盘
- 30 日复盘
- 继续做 / 停止做 / 升级做
## 6. 产品规则补充
### 6.1 参考作品和主页导入
导入参考作品或主页时,必须支持两种方式:
- 手动绑定到某个 Agent
- 系统自动关联到推荐 Agent
无论哪种方式,后续的导入分析都由 Agent 负责,不再依赖用户手工整理。
### 6.2 跟踪账号与日报
跟踪账号是长期行为,不是一次性导入。
规则建议:
- 用户手动把账号加入跟踪列表
- 系统监控是否有新增作品
- 新增作品按“上次打开后”自动汇总
- 由用户创建的 Agent 分析借鉴点
- 用户打开平台后优先看到这组日报
- 高价值更新可一键送入学习集 / Playbook / 作品库
### 6.3 API key 管理
API key 统一后台托管,用户不直接管理密钥。
产品侧只展示:
- 当前可用模型
- 模型能力说明
- 额度消耗情况
- 是否支持对比模型
### 6.4 积分 / 额度体系
新增积分 / 额度体系,先按三类额度表达:
- 文案额度
- 封面额度
- 视频额度
额度用于控制生成、渲染和调用成本,不要求用户感知底层 API key。
## 7. 对当前 StoryForge 的直接调整建议
### 7.1 产品抽象调整
从:
- Workspace
- Job
- Pipeline
改成:
- 项目
- Agent
- 账号
- 作品
- Playbook
- 生产
- 复盘
### 7.2 Douyin Workbench 调整
当前 Douyin Workbench 是一个阶段性工具页。
下一步要升级成通用的 `Platform Account Workspace`
也就是:
- 不再只服务抖音
- 抖音先做出来,但模型上必须对齐未来多平台
### 7.3 Agent 展示方式调整
Agent 必须保留,并成为项目执行主中枢,但不应替代项目作为一级入口。
一级主视角应该是:
- 项目
- Agent
- 账号
- 作品
- Playbook
- 生产
- 复盘
### 7.4 API Key 管理调整
这一项直接沿用 6.3 的规则,产品落地时只需要把“可用模型、能力说明、额度消耗、对比模型支持情况”放到前台,不把密钥暴露给用户。
### 7.5 额度体系调整
这一项直接沿用 6.4 的规则,产品层面只暴露三类额度:
- 文案额度
- 封面额度
- 视频额度
额度用于控制生成、渲染和调用成本,不要求用户感知底层 API key。
## 8. 当前优先级建议
### P0
- 定义新的项目对象模型
- 定义多平台账号模型
- 重做 Web 信息架构
- 把“项目 -> Agent -> 调研 -> 导入分析 -> 生产 -> 复盘”的闭环做清楚
- 打通 API key 后台托管
- 打通文案 / 封面 / 视频三类额度
### P1
- 打通 Playbook
- 打通发布与复盘
- 把 Douyin Workbench 升级成多平台工作区框架
- 打通参考作品 / 主页导入时的手动绑定与自动关联 Agent
- 打通 Agent 的多平台市场调研
### P2
- 团队协作
- 审批流
- 批量投放与品牌协作
## 9. 最终一句话
StoryForge 的下一阶段不应该再做成“AI 工具后台”。
它应该做成:
**一个以项目为入口、由 Agent 驱动、覆盖多平台调研、导入分析、内容生产和复盘的新媒体运营中台。**

View File

@@ -0,0 +1,68 @@
# 新媒体运营平台 UI 参考包
这份参考包只保留更贴近 `StoryForge` 业务逻辑的页面,不再以通用 AI 后台为主。
目标场景:
- 发现各平台精品账号
- 分析账号和作品
- 沉淀可学习的内容方法论
- 创建 Agent 学习这些方法论
- 反推到自己的选题、生产、发布与复盘
预览入口:
- [图片墙预览](./index.html)
## 当前收录
### 千瓜数据
来源:
- `https://www.qian-gua.com/rank/fans/1/7/20250112/0.html`
- `https://www.qian-gua.com/Home/AllPrice`
适合借鉴:
- 小红书达人榜单页
- 多维筛选条件
- 榜单 -> 详情 -> 收藏/监控 的路径
- 平台能力地图
文件:
- [01-qiangua-rank-page.png](./raw/01-qiangua-rank-page.png)
- [02-qiangua-plan-and-modules.png](./raw/02-qiangua-plan-and-modules.png)
### 飞瓜数据
来源:
- `https://dy.feigua.cn/help/detail/9/447.html`
适合借鉴:
- 抖音运营后台一级导航
- 账号发现与涨粉榜
- 数据监测工作台
- 品牌投放 / 竞品投放
文件:
- [03-feigua-menu-structure.png](./raw/03-feigua-menu-structure.png)
- [04-feigua-account-discovery.png](./raw/04-feigua-account-discovery.png)
- [05-feigua-monitoring-workbench.png](./raw/05-feigua-monitoring-workbench.png)
- [06-feigua-brand-delivery.png](./raw/06-feigua-brand-delivery.png)
## 我对这批参考的判断
最适合 StoryForge 的,不是照搬它们某一家的界面,而是组合借法:
1.`飞瓜数据` 借后台主壳与一级导航分组
2.`千瓜数据` 借榜单、达人筛选、监测和内容资产视角
3. StoryForge 自己再把平台差异抽象成统一对象:
- 平台账号
- 参考账号
- 作品
- 账号洞察
- 内容打法
- Agent
- 生产任务
- 发布复盘
## 不建议直接照搬的点
- 不要照搬纯投放平台风格,那会过度偏品牌投放
- 不要把账号分析页做成单纯长报告
- 不要把 Agent 放在用户主视角,创作者更关心“账号、作品、选题、生产、复盘”

View File

@@ -0,0 +1,136 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>StoryForge 新媒体运营参考 UI</title>
<style>
:root {
--bg: #f4f8fd;
--panel: #fff;
--line: #dbe7f2;
--text: #152131;
--muted: #62758d;
--blue: #8fc2ff;
--blue-deep: #3f7fe7;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
color: var(--text);
background: linear-gradient(180deg, #f7fbff 0%, #eef4fb 100%);
}
.wrap { max-width: 1440px; margin: 0 auto; padding: 28px 22px 56px; }
.hero {
background: rgba(255,255,255,.86);
border: 1px solid rgba(143,194,255,.35);
border-radius: 24px;
box-shadow: 0 22px 48px rgba(80, 113, 145, .12);
padding: 28px;
}
h1 { margin: 0 0 10px; font-size: 30px; }
.hero p { margin: 0; line-height: 1.8; color: var(--muted); max-width: 980px; }
.hero ul { margin: 12px 0 0; padding-left: 18px; color: var(--muted); line-height: 1.9; }
.section { margin-top: 28px; }
.section h2 { margin: 0 0 12px; font-size: 22px; }
.section p { margin: 0 0 16px; color: var(--muted); }
.grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.card {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 18px;
overflow: hidden;
box-shadow: 0 10px 24px rgba(44, 72, 102, .08);
}
.card img { width: 100%; display: block; background: #eff5fc; }
.meta { padding: 16px 18px 18px; }
.meta h3 { margin: 0 0 8px; font-size: 18px; }
.meta .source { margin: 0 0 8px; color: var(--blue-deep); font-size: 13px; }
.meta .use { margin: 0; color: var(--muted); line-height: 1.8; font-size: 14px; }
@media (max-width: 960px) {
.grid { grid-template-columns: 1fr; }
.wrap { padding: 18px 14px 40px; }
h1 { font-size: 24px; }
}
</style>
</head>
<body>
<div class="wrap">
<div class="hero">
<h1>StoryForge 新媒体运营参考 UI</h1>
<p>
这批参考不是通用 AI 后台,而是更贴近“抖音 / 小红书 / B站 / YouTube 多平台账号运营”的产品形态。
重点观察的是:账号发现、精品账号分析、内容监控、竞品跟踪、品牌投放、内容复盘。
</p>
<ul>
<li>飞瓜:适合借抖音后台主壳、一级导航、监控与投放模块</li>
<li>千瓜:适合借小红书榜单、达人筛选、竞品监测与内容资产视角</li>
<li>StoryForge 自己再抽象成统一的跨平台工作区,而不是按平台裂成四套后台</li>
</ul>
</div>
<div class="section">
<h2>千瓜数据</h2>
<p>更适合作为“小红书方向的榜单发现、达人筛选、行业观察、内容洞察”的参考。</p>
<div class="grid">
<div class="card">
<img src="./raw/01-qiangua-rank-page.png" alt="千瓜达人榜单页" />
<div class="meta">
<h3>达人榜单页</h3>
<p class="source">来源qian-gua.com</p>
<p class="use">适合借榜单页的筛选区、排行表格、达人卡摘要信息。可转译为 StoryForge 的“精品账号发现”。</p>
</div>
</div>
<div class="card">
<img src="./raw/02-qiangua-plan-and-modules.png" alt="千瓜模块与能力地图" />
<div class="meta">
<h3>模块与能力地图</h3>
<p class="source">来源qian-gua.com</p>
<p class="use">这张不是最终界面参考,而是产品能力地图参考,适合帮助我们定义菜单层级和模块边界。</p>
</div>
</div>
</div>
</div>
<div class="section">
<h2>飞瓜数据</h2>
<p>更适合作为“抖音方向的后台主壳、账号发现、监控工作台、品牌投放”的参考。</p>
<div class="grid">
<div class="card">
<img src="./raw/03-feigua-menu-structure.png" alt="飞瓜菜单结构图" />
<div class="meta">
<h3>一级菜单结构</h3>
<p class="source">来源dy.feigua.cn/help</p>
<p class="use">适合借一级导航分组方式。StoryForge 可转译成运营总台、账号发现、内容库、Agent、生产、发布复盘、设置。</p>
</div>
</div>
<div class="card">
<img src="./raw/04-feigua-account-discovery.png" alt="飞瓜账号发现页" />
<div class="meta">
<h3>账号发现页</h3>
<p class="source">来源dy.feigua.cn/help</p>
<p class="use">适合借涨粉榜、行业筛选、账号列表和“详情”入口,用于 StoryForge 的精品账号发现和对标账号收录。</p>
</div>
</div>
<div class="card">
<img src="./raw/05-feigua-monitoring-workbench.png" alt="飞瓜监测工作台" />
<div class="meta">
<h3>数据监测工作台</h3>
<p class="source">来源dy.feigua.cn/help</p>
<p class="use">适合借监控任务页和持续追踪视角,可转译为 StoryForge 的“账号跟踪 / 作品跟踪 / 竞品跟踪”。</p>
</div>
</div>
<div class="card">
<img src="./raw/06-feigua-brand-delivery.png" alt="飞瓜品牌投放页" />
<div class="meta">
<h3>品牌投放与竞品页</h3>
<p class="source">来源dy.feigua.cn/help</p>
<p class="use">适合借品牌搜索、筛选和表格摘要区。StoryForge 可转译为“品牌案例库 / 商业化机会 / 竞品投放观察”。</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

View File

@@ -0,0 +1,42 @@
# StoryForge Web V4 HTML Prototype
这是一个只做界面、不接业务功能的静态 Web 原型。
入口:
- [index.html](./index.html)
包含页面:
- 项目总台
- 项目与接入
- 找参考
- 跟踪账号
- 参考详情
- 我的账号
- 作品库
- Agent
- 生产中心
- 发布与复盘
- 额度
说明:
- 这版不依赖后端接口
- 主要用于确认新的产品逻辑、信息架构和布局方向
- 主业务流已调整为:项目 -> Agent -> 首轮调研 -> 导入绑定 -> 生产 -> 发布复盘
- 新增:跟踪账号 -> 自动汇总更新 -> Agent 标注借鉴点 -> 日报回看
- 导入分析以 Agent 为中心,不再以规则判断为主
- 模型凭证默认后台托管,用户界面只表达模型选择与额度消耗
- 主题色以淡蓝、白、黑、灰为主
新增预览:
- [05-intake.png](./previews/05-intake.png)
- [06-agent.png](./previews/06-agent.png)
- [07-production.png](./previews/07-production.png)
- [08-credits.png](./previews/08-credits.png)
- [09-dashboard-lite.png](./previews/09-dashboard-lite.png)
- [10-find-reference-lite.png](./previews/10-find-reference-lite.png)
- [11-reference-detail-lite.png](./previews/11-reference-detail-lite.png)
- [12-tracking-digest.png](./previews/12-tracking-digest.png)
- [13-find-reference-search.png](./previews/13-find-reference-search.png)
备份:
- [pre-simplify backup](/Users/kris/code/StoryForge-gitea/output/ui/backups/storyforge-web-v4-html-prototype-2026-03-22-pre-simplify-2026-03-22)

View File

@@ -0,0 +1,24 @@
const navButtons = document.querySelectorAll("[data-screen-target]");
const screens = document.querySelectorAll("[data-screen]");
function activateScreen(id) {
navButtons.forEach((button) => {
const active = button.dataset.screenTarget === id;
button.classList.toggle("is-active", active);
});
screens.forEach((screen) => {
screen.classList.toggle("is-active", screen.dataset.screen === id);
});
}
navButtons.forEach((button) => {
button.addEventListener("click", () => {
const next = button.dataset.screenTarget;
activateScreen(next);
window.location.hash = next;
});
});
const initial = window.location.hash.replace("#", "") || "dashboard";
activateScreen(initial);

View File

@@ -0,0 +1,845 @@
:root {
--bg: #f4f8fd;
--bg-soft: #eef4fb;
--panel: #ffffff;
--panel-soft: #f7fbff;
--line: #d9e5f2;
--line-strong: #c8d8ea;
--text: #182433;
--muted: #66788f;
--blue-50: #f3f8ff;
--blue-100: #e8f1ff;
--blue-200: #d9e8ff;
--blue-300: #c4ddff;
--blue-500: #6aa4ff;
--blue-600: #4f8fee;
--blue-700: #3977d8;
--green: #2db584;
--orange: #f29a38;
--red: #e46767;
--shadow: 0 18px 40px rgba(67, 93, 125, 0.12);
--radius-xl: 24px;
--radius-lg: 18px;
--radius-md: 14px;
--radius-sm: 10px;
}
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
background:
radial-gradient(circle at top left, rgba(129, 180, 255, 0.18), transparent 28%),
linear-gradient(180deg, #f8fbff 0%, #eef4fb 100%);
color: var(--text);
}
a {
color: inherit;
text-decoration: none;
}
button,
input,
select {
font: inherit;
}
.app-shell {
display: grid;
grid-template-columns: 272px minmax(0, 1fr);
min-height: 100vh;
}
.sidebar {
background: rgba(255, 255, 255, 0.82);
border-right: 1px solid rgba(201, 220, 239, 0.75);
backdrop-filter: blur(14px);
padding: 22px 18px 18px;
position: sticky;
top: 0;
height: 100vh;
}
.brand {
display: flex;
align-items: center;
gap: 12px;
padding: 8px 10px 20px;
}
.brand-mark {
width: 42px;
height: 42px;
border-radius: 14px;
background: linear-gradient(145deg, #b9d7ff 0%, #6ea8ff 100%);
display: grid;
place-items: center;
color: white;
font-weight: 700;
letter-spacing: 0.04em;
}
.brand h1 {
margin: 0;
font-size: 18px;
}
.brand p {
margin: 4px 0 0;
font-size: 12px;
color: var(--muted);
}
.nav-group {
margin-top: 14px;
}
.nav-title {
padding: 0 10px 8px;
color: var(--muted);
font-size: 12px;
letter-spacing: 0.04em;
}
.nav-item {
display: flex;
align-items: center;
gap: 10px;
width: 100%;
border: none;
background: transparent;
border-radius: 14px;
padding: 11px 12px;
color: var(--text);
cursor: pointer;
text-align: left;
transition: 0.18s ease;
}
.nav-item:hover {
background: rgba(106, 164, 255, 0.08);
}
.nav-item.is-active {
background: linear-gradient(180deg, #edf5ff 0%, #e6f0ff 100%);
box-shadow: inset 0 0 0 1px rgba(106, 164, 255, 0.22);
color: var(--blue-700);
}
.nav-item .icon {
width: 28px;
height: 28px;
border-radius: 10px;
background: var(--blue-50);
display: grid;
place-items: center;
font-size: 14px;
}
.sidebar-foot {
margin-top: 22px;
padding: 14px;
border-radius: 18px;
background: linear-gradient(180deg, #f7fbff 0%, #eef5ff 100%);
border: 1px solid var(--line);
}
.sidebar-foot h3 {
margin: 0 0 8px;
font-size: 14px;
}
.sidebar-foot p {
margin: 0 0 10px;
color: var(--muted);
line-height: 1.55;
font-size: 12px;
}
.chip-row {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.chip {
padding: 6px 10px;
border-radius: 999px;
background: var(--blue-50);
border: 1px solid var(--line);
color: var(--muted);
font-size: 12px;
}
.chip.active {
background: var(--blue-100);
color: var(--blue-700);
border-color: rgba(79, 143, 238, 0.22);
}
.content {
padding: 18px 22px 26px;
}
.topbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 18px;
padding: 16px 18px;
border-radius: 22px;
background: rgba(255, 255, 255, 0.82);
backdrop-filter: blur(12px);
border: 1px solid rgba(201, 220, 239, 0.75);
box-shadow: var(--shadow);
}
.topbar-left,
.topbar-right {
display: flex;
align-items: center;
gap: 12px;
}
.workspace-switch,
.search,
.mini-card {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 14px;
}
.workspace-switch {
padding: 10px 14px;
min-width: 190px;
}
.workspace-switch strong {
display: block;
font-size: 13px;
}
.workspace-switch span {
font-size: 12px;
color: var(--muted);
}
.search {
display: flex;
align-items: center;
gap: 10px;
min-width: 340px;
padding: 12px 14px;
color: var(--muted);
}
.search input {
border: none;
outline: none;
background: transparent;
width: 100%;
color: var(--text);
}
.top-pill {
padding: 8px 12px;
border-radius: 999px;
background: var(--blue-50);
color: var(--muted);
border: 1px solid var(--line);
font-size: 12px;
}
.avatar {
width: 36px;
height: 36px;
border-radius: 12px;
background: linear-gradient(145deg, #bedcff 0%, #82b8ff 100%);
display: grid;
place-items: center;
font-size: 13px;
color: white;
font-weight: 700;
}
.screen {
display: none;
margin-top: 18px;
}
.screen.is-active {
display: block;
}
.screen-head {
display: flex;
align-items: end;
justify-content: space-between;
gap: 18px;
margin-bottom: 16px;
}
.screen-head h2 {
margin: 0 0 6px;
font-size: 28px;
}
.screen-head p {
margin: 0;
color: var(--muted);
font-size: 14px;
line-height: 1.55;
max-width: 720px;
}
.action-row {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.btn {
border: none;
border-radius: 12px;
padding: 11px 14px;
cursor: pointer;
}
.btn-primary {
background: linear-gradient(180deg, var(--blue-500) 0%, var(--blue-600) 100%);
color: white;
box-shadow: 0 8px 18px rgba(79, 143, 238, 0.22);
}
.btn-secondary {
background: white;
color: var(--text);
border: 1px solid var(--line);
}
.layout-grid {
display: grid;
gap: 18px;
}
.grid-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.grid-5 {
grid-template-columns: repeat(5, minmax(0, 1fr));
}
.grid-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.grid-main {
grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
}
.grid-split {
grid-template-columns: 280px minmax(0, 1fr) 310px;
}
.panel {
background: rgba(255, 255, 255, 0.9);
border: 1px solid rgba(201, 220, 239, 0.9);
border-radius: var(--radius-xl);
box-shadow: var(--shadow);
overflow: hidden;
}
.panel.pad {
padding: 18px;
}
.panel h3,
.panel h4 {
margin: 0;
}
.panel-subtitle {
margin-top: 6px;
color: var(--muted);
font-size: 12px;
}
.stat-card {
padding: 18px;
border-radius: 20px;
background: linear-gradient(180deg, #fbfdff 0%, #f3f8ff 100%);
border: 1px solid rgba(201, 220, 239, 0.9);
box-shadow: var(--shadow);
}
.stat-card small {
color: var(--muted);
}
.stat-card strong {
display: block;
margin-top: 10px;
font-size: 28px;
}
.stat-foot {
margin-top: 10px;
display: flex;
align-items: center;
justify-content: space-between;
color: var(--muted);
font-size: 12px;
}
.positive { color: var(--green); }
.warn { color: var(--orange); }
.negative { color: var(--red); }
.list {
display: grid;
gap: 12px;
}
.task-item,
.entity-card,
.topic-card,
.review-card,
.queue-card {
border-radius: 18px;
border: 1px solid var(--line);
background: linear-gradient(180deg, #fff 0%, #f9fbff 100%);
}
.task-item,
.queue-card,
.review-card {
padding: 16px;
}
.task-item h4,
.entity-card h4,
.topic-card h4,
.queue-card h4,
.review-card h4 {
margin: 0 0 6px;
font-size: 15px;
}
.task-item p,
.entity-card p,
.topic-card p,
.queue-card p,
.review-card p {
margin: 0;
color: var(--muted);
line-height: 1.5;
font-size: 12px;
}
.task-meta,
.entity-meta,
.row-meta {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 12px;
}
.tag {
padding: 6px 10px;
border-radius: 999px;
background: #f6f9fe;
border: 1px solid var(--line);
color: var(--muted);
font-size: 12px;
}
.tag.blue {
background: var(--blue-100);
color: var(--blue-700);
}
.tag.green {
background: rgba(45, 181, 132, 0.1);
border-color: rgba(45, 181, 132, 0.18);
color: #1b8b61;
}
.tag.orange {
background: rgba(242, 154, 56, 0.1);
border-color: rgba(242, 154, 56, 0.18);
color: #b76d16;
}
.tag.red {
background: rgba(228, 103, 103, 0.1);
border-color: rgba(228, 103, 103, 0.18);
color: #b24c4c;
}
.two-col {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: 16px;
}
.three-col {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
}
.table-wrap {
overflow: auto;
}
table {
width: 100%;
border-collapse: collapse;
min-width: 920px;
}
th,
td {
padding: 14px 12px;
border-bottom: 1px solid var(--line);
text-align: left;
vertical-align: top;
}
thead th {
background: #f8fbff;
color: var(--muted);
font-weight: 600;
font-size: 12px;
letter-spacing: 0.02em;
}
tbody tr:hover {
background: rgba(106, 164, 255, 0.04);
}
.entity-cell {
display: flex;
gap: 12px;
align-items: start;
}
.avatar-lg {
width: 46px;
height: 46px;
border-radius: 15px;
background: linear-gradient(145deg, #c9e2ff 0%, #8bbcff 100%);
display: grid;
place-items: center;
color: white;
font-weight: 700;
}
.cell-title {
font-weight: 600;
margin-bottom: 4px;
}
.cell-desc {
font-size: 12px;
color: var(--muted);
line-height: 1.5;
}
.kpi-inline {
display: flex;
flex-wrap: wrap;
gap: 14px;
color: var(--muted);
font-size: 12px;
}
.metric {
font-weight: 600;
color: var(--text);
}
.toolbar {
display: flex;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
padding: 18px;
border-bottom: 1px solid var(--line);
background: linear-gradient(180deg, #fbfdff 0%, #f4f9ff 100%);
}
.toolbar-stack {
display: grid;
gap: 10px;
min-width: min(760px, 100%);
}
.search-inline {
min-width: 320px;
width: min(720px, 100%);
padding: 10px 12px;
}
.filters {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.filter {
min-width: 132px;
padding: 11px 12px;
border-radius: 12px;
border: 1px solid var(--line);
background: white;
color: var(--muted);
}
.panel-head {
display: flex;
justify-content: space-between;
align-items: center;
gap: 14px;
margin-bottom: 14px;
}
.side-stack {
display: grid;
gap: 16px;
}
.insight-card {
padding: 16px;
border-radius: 18px;
border: 1px solid var(--line);
background: linear-gradient(180deg, #fff 0%, #f6faff 100%);
}
.insight-card h4 {
margin: 0 0 8px;
font-size: 15px;
}
.insight-card ul {
margin: 0;
padding-left: 18px;
color: var(--muted);
line-height: 1.65;
font-size: 12px;
}
.tab-row {
display: flex;
gap: 8px;
flex-wrap: wrap;
margin: 16px 0 18px;
}
.tab {
padding: 8px 12px;
border-radius: 999px;
border: 1px solid var(--line);
background: #fff;
color: var(--muted);
font-size: 13px;
}
.tab.active {
background: var(--blue-100);
color: var(--blue-700);
border-color: rgba(79, 143, 238, 0.2);
}
.hero-card {
padding: 22px;
border-radius: 24px;
background: linear-gradient(145deg, rgba(212, 230, 255, 0.85) 0%, rgba(245, 250, 255, 0.96) 72%);
border: 1px solid rgba(180, 210, 248, 0.85);
box-shadow: var(--shadow);
}
.hero-card h3 {
margin: 0 0 8px;
font-size: 20px;
}
.hero-card p {
margin: 0;
color: var(--muted);
line-height: 1.6;
font-size: 14px;
}
.mini-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
margin-top: 16px;
}
.mini-card {
padding: 14px;
}
.mini-card strong {
display: block;
margin-top: 8px;
font-size: 17px;
}
.playbook-list {
display: grid;
gap: 12px;
}
.playbook-item {
padding: 14px;
border-radius: 16px;
border: 1px solid var(--line);
background: linear-gradient(180deg, #fff 0%, #f8fbff 100%);
}
.playbook-item.active {
border-color: rgba(79, 143, 238, 0.24);
background: linear-gradient(180deg, #f8fbff 0%, #eef6ff 100%);
}
.timeline {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.step {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
border-radius: 999px;
background: #fff;
border: 1px solid var(--line);
color: var(--muted);
font-size: 12px;
}
.step.done {
color: #167657;
border-color: rgba(45, 181, 132, 0.18);
background: rgba(45, 181, 132, 0.08);
}
.step.current {
color: var(--blue-700);
border-color: rgba(79, 143, 238, 0.2);
background: var(--blue-100);
}
.bar-chart {
display: grid;
gap: 10px;
}
.bar-row {
display: grid;
grid-template-columns: 108px minmax(0, 1fr) 48px;
gap: 10px;
align-items: center;
font-size: 13px;
color: var(--muted);
}
.bar-track {
height: 10px;
border-radius: 999px;
background: #eef3f8;
overflow: hidden;
}
.bar-fill {
height: 100%;
border-radius: 999px;
background: linear-gradient(90deg, #93c3ff 0%, #5c95ef 100%);
}
.calendar {
display: grid;
grid-template-columns: repeat(7, minmax(0, 1fr));
gap: 10px;
}
.day {
min-height: 118px;
border: 1px solid var(--line);
border-radius: 16px;
padding: 12px;
background: linear-gradient(180deg, #fff 0%, #f9fbff 100%);
}
.day strong {
display: block;
margin-bottom: 8px;
font-size: 13px;
}
.slot {
margin-top: 8px;
padding: 8px 10px;
border-radius: 12px;
background: var(--blue-50);
border: 1px solid rgba(106, 164, 255, 0.16);
font-size: 12px;
color: var(--text);
line-height: 1.5;
}
.footer-note {
margin-top: 18px;
color: var(--muted);
font-size: 12px;
text-align: right;
}
@media (max-width: 1320px) {
.grid-main,
.grid-split,
.grid-5,
.grid-4,
.grid-3,
.three-col,
.two-col {
grid-template-columns: 1fr;
}
.calendar {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 1080px) {
.app-shell {
grid-template-columns: 1fr;
}
.sidebar {
position: relative;
height: auto;
}
.topbar {
flex-direction: column;
align-items: stretch;
}
.topbar-left,
.topbar-right {
flex-wrap: wrap;
}
.search {
min-width: 0;
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB