feat(ts): 实现 Polaris 可交互首页
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
@@ -0,0 +1,453 @@
|
||||
# Polaris 首页实现规格
|
||||
|
||||
> 日期:2026-08-26
|
||||
>
|
||||
> 状态:用户已批准,可进入实施
|
||||
>
|
||||
> 实现分支:`feat/polaris-homepage`
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
Polaris 是一个轻量、安静、高效的个人浏览器起始页,不是后台管理系统或信息密集型 Dashboard。
|
||||
|
||||
本次工作只建立推荐的项目结构并实现完整可交互首页。用户验收首页视觉和交互后,才会明确决定是否继续实现分类页及第一阶段其余目标。
|
||||
|
||||
## 2. 范围
|
||||
|
||||
### 2.1 本次实现
|
||||
|
||||
- 初始化 Next.js App Router 项目;
|
||||
- 建立 Feature-first 混合目录;
|
||||
- 整理现有设计文档和资产位置;
|
||||
- 实现低饱和青蓝 CSS 渐变背景与浅色玻璃视觉;
|
||||
- 实现可折叠且持久化的桌面侧栏;
|
||||
- 实现实时时钟、日期和分时问候语;
|
||||
- 实现 Google、Bing、GitHub、Local 四种严格分离的搜索模式;
|
||||
- 实现 Local 搜索结果、键盘导航和空状态;
|
||||
- 实现 8 个常用链接;
|
||||
- 实现统一图标 fallback;
|
||||
- 建立本地 JSON、service、类型与数据校验边界;
|
||||
- 完成单元测试、组件交互测试、静态构建和真实页面视觉检查。
|
||||
|
||||
### 2.2 本次不实现
|
||||
|
||||
- 正式分类页;
|
||||
- Go API 与 PostgreSQL;
|
||||
- 管理页或隐藏管理入口;
|
||||
- 深色模式;
|
||||
- 移动端与平板布局;
|
||||
- 自定义背景上传;
|
||||
- 自定义搜索引擎、URL 直达、AI 搜索;
|
||||
- 加载骨架和后端错误重试。
|
||||
|
||||
## 3. 已确认决策
|
||||
|
||||
| 决策项 | 结论 |
|
||||
| ---------- | ----------------------------------------------------------------- |
|
||||
| 首页范围 | 完整可交互首页 |
|
||||
| 目录方案 | Feature-first + 共享基础层 |
|
||||
| 分支粒度 | 项目骨架与首页位于同一个 `feat/polaris-homepage` 分支 |
|
||||
| 文档整理 | 三份文档迁入 `docs/design/`,设计图迁入 `docs/assets/` |
|
||||
| Logo | 现有占位 Logo 迁入 `public/brand/`,不追加品牌设计 |
|
||||
| 运行时背景 | CSS 低饱和青蓝渐变;设计图只作构图参考 |
|
||||
| 外部搜索 | Google、Bing、GitHub 在当前标签页跳转 |
|
||||
| 本地链接 | Local 结果与常用链接在新标签页打开 |
|
||||
| 排序模型 | `sort` 管理分类内顺序;可选 `pinnedSort` 独立管理首页常用链接顺序 |
|
||||
| 分类导航 | 首页验收阶段展示但禁用,避免进入未实现路由;分类页完成后启用 |
|
||||
| 注释 | 关键规则、非显然决策、边界条件和阶段性限制使用简洁中文注释 |
|
||||
| 提交时机 | 分支全部目标完成并验证后再提交 |
|
||||
|
||||
## 4. 技术基线
|
||||
|
||||
- Next.js App Router;
|
||||
- React;
|
||||
- TypeScript strict;
|
||||
- Tailwind CSS v4,使用 CSS-first 配置;
|
||||
- shadcn/ui,只引入实际使用的基础原语;
|
||||
- lucide-react;
|
||||
- simple-icons;
|
||||
- pnpm;
|
||||
- Vitest;
|
||||
- Testing Library;
|
||||
- ESLint;
|
||||
- Prettier。
|
||||
|
||||
`next.config.ts` 使用 `output: "export"`,构建产物必须能作为纯静态文件部署。
|
||||
|
||||
不引入 Redux、Zustand、React Query、Zod、Storybook、Repository interface 或依赖注入容器。当前规模下这些抽象没有必要。
|
||||
|
||||
## 5. 推荐目录
|
||||
|
||||
```text
|
||||
polaris/
|
||||
├─ docs/
|
||||
│ ├─ design/
|
||||
│ │ ├─ Polaris 项目说明文档.md
|
||||
│ │ ├─ Polaris 首页设计文档.md
|
||||
│ │ ├─ Polaris 分类页设计文档.md
|
||||
│ │ └─ 2026-08-26-Polaris-首页实现规格.md
|
||||
│ └─ assets/
|
||||
│ └─ Polaris页面设计图.png
|
||||
├─ public/
|
||||
│ ├─ brand/
|
||||
│ │ └─ logo.svg
|
||||
│ └─ icons/
|
||||
├─ src/
|
||||
│ ├─ app/
|
||||
│ │ ├─ globals.css
|
||||
│ │ ├─ layout.tsx
|
||||
│ │ └─ page.tsx
|
||||
│ ├─ components/
|
||||
│ │ ├─ ui/
|
||||
│ │ └─ shared/
|
||||
│ ├─ features/
|
||||
│ │ ├─ home/
|
||||
│ │ │ ├─ components/
|
||||
│ │ │ ├─ hooks/
|
||||
│ │ │ └─ lib/
|
||||
│ │ └─ navigation/
|
||||
│ │ └─ components/
|
||||
│ ├─ data/
|
||||
│ │ ├─ categories.json
|
||||
│ │ ├─ links.json
|
||||
│ │ └─ settings.json
|
||||
│ ├─ services/
|
||||
│ │ ├─ categories.ts
|
||||
│ │ ├─ links.ts
|
||||
│ │ └─ settings.ts
|
||||
│ ├─ types/
|
||||
│ │ ├─ navigation.ts
|
||||
│ │ ├─ search.ts
|
||||
│ │ └─ settings.ts
|
||||
│ ├─ lib/
|
||||
│ │ └─ utils.ts
|
||||
│ └─ test/
|
||||
│ └─ setup.ts
|
||||
├─ components.json
|
||||
├─ eslint.config.mjs
|
||||
├─ next.config.ts
|
||||
├─ package.json
|
||||
├─ pnpm-lock.yaml
|
||||
├─ postcss.config.mjs
|
||||
├─ prettier.config.mjs
|
||||
├─ tsconfig.json
|
||||
└─ vitest.config.ts
|
||||
```
|
||||
|
||||
### 5.1 目录职责
|
||||
|
||||
- `app/`:路由、metadata、根布局、全局样式和页面组合;
|
||||
- `features/`:按功能聚合组件、hooks 和专属纯函数;
|
||||
- `components/ui/`:shadcn/ui 基础原语;
|
||||
- `components/shared/`:跨功能复用组件,例如 `GlassPanel`、`SiteIcon`;
|
||||
- `data/`:第一版本地 JSON;
|
||||
- `services/`:页面与数据源之间的唯一访问边界;
|
||||
- `types/`:跨功能共享的数据契约;
|
||||
- `lib/`:真正通用且不依赖业务功能的工具;
|
||||
- `test/`:全局测试环境与共享测试辅助代码。
|
||||
|
||||
测试文件与被测试实现就近放置,`src/test/` 不作为所有测试的集中目录。
|
||||
|
||||
## 6. 渲染与组件边界
|
||||
|
||||
`src/app/page.tsx` 保持为 Server Component,在构建时调用 service 层读取数据,再将可序列化数据传给页面组件。
|
||||
|
||||
```text
|
||||
app/page.tsx
|
||||
└─ AppShell
|
||||
├─ Sidebar
|
||||
│ ├─ SidebarHeader
|
||||
│ └─ SidebarNav
|
||||
└─ HomeContent
|
||||
├─ ClockGreeting
|
||||
├─ SearchBox
|
||||
│ ├─ SearchProviderMenu
|
||||
│ └─ LocalSearchResults
|
||||
└─ QuickLinks
|
||||
└─ QuickLinkCard
|
||||
└─ SiteIcon
|
||||
```
|
||||
|
||||
Client Component 边界仅用于浏览器状态:
|
||||
|
||||
- `AppShell`:侧栏折叠与持久化;
|
||||
- `ClockGreeting`:当前时间;
|
||||
- `SearchBox`:Provider、query、结果选中项和快捷键;
|
||||
- `SiteIcon`:图标加载失败后的 fallback。
|
||||
|
||||
把 Server Component 作为 `AppShell` 的 `children` 传入,不因为外层存在 Client Component 就将全部展示代码改成客户端代码。
|
||||
|
||||
不为每个小标签或图标创建组件。只有存在独立状态、复用价值或清晰职责时才拆分。
|
||||
|
||||
## 7. 数据模型与数据流
|
||||
|
||||
### 7.1 数据规模
|
||||
|
||||
- 7 个分类;
|
||||
- 开发工具 15 条;
|
||||
- ChatGPT、Gmail、Notion、YouTube、Bilibili 5 条跨分类链接;
|
||||
- 共 20 条链接;
|
||||
- 8 条 `pinned` 常用链接;
|
||||
- `sort` 只表示分类内顺序,可选 `pinnedSort` 只表示首页常用链接顺序。
|
||||
|
||||
首页常用链接固定按以下 `pinnedSort` 顺序展示:GitHub、ChatGPT、Gmail、Notion、Figma、YouTube、Vercel、Bilibili。该字段解决开发工具分类中 Vercel 位于 Figma 之前、但首页中 Figma 位于 Vercel 之前的双重排序需求。
|
||||
|
||||
设计资源、学习资料、生活服务保持无链接;AI 工具、效率工具和娱乐媒体因常用链接而有少量数据。
|
||||
|
||||
### 7.2 访问路径
|
||||
|
||||
1. `page.tsx` 调用 `getCategories()`、`getLinks()` 和 `getSettings()`;
|
||||
2. service 层复制、排序和筛选数据;
|
||||
3. 页面不直接 import JSON;
|
||||
4. 首页只把所需的分类、全部搜索候选、8 条常用链接和设置传给客户端;
|
||||
5. 未来接 Go API 时保持 service 的对外职责不变,只替换其内部数据来源。
|
||||
|
||||
### 7.3 数据校验
|
||||
|
||||
Vitest 必须校验:
|
||||
|
||||
- 必填字段类型;
|
||||
- 分类和链接 ID 唯一;
|
||||
- URL 合法;
|
||||
- `categoryId` 必须指向现有分类;
|
||||
- `sort` 与可选 `pinnedSort` 合法;
|
||||
- Provider 配置有效;
|
||||
- `pinned` 数量为 8,且每条 pinned 链接都有唯一 `pinnedSort`。
|
||||
|
||||
## 8. 视觉系统
|
||||
|
||||
### 8.1 背景
|
||||
|
||||
使用多层 CSS 渐变和柔和光斑模拟晨雾、天空和水面氛围,不把 `Polaris页面设计图.png` 作为运行时背景。
|
||||
|
||||
增加浅色遮罩和适度模糊,保证未来替换背景时仍具有可读性。
|
||||
|
||||
### 8.2 布局
|
||||
|
||||
- 侧栏外边距:`20px`;
|
||||
- 展开宽度:`240px`;
|
||||
- 折叠宽度:`72px`;
|
||||
- 主内容视觉重心位于中上方;
|
||||
- 使用 `minmax()` 与 `clamp()` 适配 1024px 以上桌面窗口;
|
||||
- 搜索框最大宽度约 `760px`、高度约 `68px`;
|
||||
- 常用链接最大四列、共两行,缩窄窗口时允许减少列数;
|
||||
- 第一版不实现移动端抽屉侧栏。
|
||||
|
||||
### 8.3 Design tokens
|
||||
|
||||
在 `globals.css` 中定义 Polaris 语义变量,并通过 Tailwind v4 `@theme inline` 映射:
|
||||
|
||||
- 主文本、次级文本、弱文本;
|
||||
- 主色、hover 色、柔和主色;
|
||||
- 侧栏、搜索框、卡片表面;
|
||||
- 玻璃边框;
|
||||
- 软阴影、中等阴影;
|
||||
- 圆角与模糊强度。
|
||||
|
||||
第一版只实现浅色值,但变量命名允许以后通过主题选择器覆盖。
|
||||
|
||||
### 8.4 动效与无障碍
|
||||
|
||||
- hover、focus 和折叠过渡约为 180ms;
|
||||
- 不使用夸张缩放或弹跳;
|
||||
- 尊重 `prefers-reduced-motion`;
|
||||
- 所有图标按钮有可访问名称;
|
||||
- 键盘焦点清晰;
|
||||
- 搜索输入与结果使用合理的 combobox/listbox 语义;
|
||||
- 禁用分类项使用 `aria-disabled` 并提供“分类页将在下一阶段提供”的轻量提示。
|
||||
|
||||
## 9. 首页交互
|
||||
|
||||
### 9.1 时钟与问候
|
||||
|
||||
问候规则:
|
||||
|
||||
```text
|
||||
05:00 - 11:59 早上好
|
||||
12:00 - 13:59 中午好
|
||||
14:00 - 17:59 下午好
|
||||
18:00 - 23:59 晚上好
|
||||
00:00 - 04:59 夜深了
|
||||
```
|
||||
|
||||
客户端按分钟更新;跨午夜后日期、星期和问候语同步变化。
|
||||
|
||||
### 9.2 Provider 状态
|
||||
|
||||
- 初始值来自 `settings.search.defaultProvider`;
|
||||
- 用户切换后保存到 `localStorage`;
|
||||
- 无效值或存储不可用时回退到设置默认值;
|
||||
- 外部 Provider 与 Local 模式严格分离。
|
||||
|
||||
### 9.3 外部搜索
|
||||
|
||||
Google、Bing、GitHub:
|
||||
|
||||
- 输入先 `trim()`;
|
||||
- 空内容不提交;
|
||||
- 使用 `URLSearchParams` 编码;
|
||||
- 在当前标签页跳转;
|
||||
- 不显示 Local 结果下拉。
|
||||
|
||||
### 9.4 Local 搜索
|
||||
|
||||
匹配字段:
|
||||
|
||||
- 链接标题;
|
||||
- 关键词;
|
||||
- 描述;
|
||||
- 分类名称;
|
||||
- 分类 ID。
|
||||
|
||||
优先级:
|
||||
|
||||
```text
|
||||
标题完全匹配
|
||||
标题前缀或包含
|
||||
关键词匹配
|
||||
描述匹配
|
||||
分类匹配
|
||||
```
|
||||
|
||||
同分时按链接 `sort` 和标题稳定排序,最多返回 8 条。
|
||||
|
||||
交互:
|
||||
|
||||
- 默认选中第一项;
|
||||
- `↑` / `↓` 移动;
|
||||
- `Enter` 打开选中项;
|
||||
- 鼠标点击直接打开;
|
||||
- 结果在新标签页打开;
|
||||
- `Esc` 清空输入并关闭面板;
|
||||
- 无结果显示“没有匹配的网站”。
|
||||
|
||||
### 9.5 快捷键
|
||||
|
||||
- 首页加载后自动聚焦搜索框;
|
||||
- Windows/Linux:`Ctrl+K`;
|
||||
- macOS:`⌘K`;
|
||||
- 快捷键阻止浏览器默认行为后聚焦;
|
||||
- 监听器只存在于首页生命周期内。
|
||||
|
||||
### 9.6 侧栏
|
||||
|
||||
- 折叠状态保存到 `localStorage`;
|
||||
- 存储不可用或值损坏时回退到设置默认值;
|
||||
- hydration 后同步持久化值;
|
||||
- 同步完成前禁用布局过渡,减少闪动;
|
||||
- 首页项为当前选中态;
|
||||
- 分类项本次显示但禁用,不进入 404。
|
||||
|
||||
### 9.7 常用链接
|
||||
|
||||
- 对 `pinned` 链接按 `pinnedSort` 排序取前 8 条;
|
||||
- `pinned: true` 时必须提供唯一的 `pinnedSort`;
|
||||
- 使用真实 `<a>`;
|
||||
- `target="_blank"`;
|
||||
- `rel="noopener noreferrer"`;
|
||||
- 卡片仅显示图标与名称。
|
||||
|
||||
## 10. 图标策略
|
||||
|
||||
运行时优先级:
|
||||
|
||||
```text
|
||||
自定义本地图标
|
||||
明确映射的 Simple Icons
|
||||
favicon
|
||||
标题首字符文字占位
|
||||
```
|
||||
|
||||
当前 20 条数据尽量命中显式 Simple Icons 映射,避免正常页面依赖远程 favicon。远程图标失败时不得显示破图。
|
||||
|
||||
侧栏分类图标使用 lucide-react,不参与站点图标 fallback。
|
||||
|
||||
## 11. 状态与故障处理
|
||||
|
||||
- 静态 JSON 无 Loading UI;
|
||||
- 数据结构错误由测试和构建阶段阻止;
|
||||
- `localStorage` 读写使用容错封装;
|
||||
- favicon 失败显示文字占位;
|
||||
- 空搜索不跳转;
|
||||
- Local 无结果显示轻量空状态;
|
||||
- 非法 Provider 回退到配置默认值;
|
||||
- Server 初始值与 Client 首次渲染保持一致,避免 hydration error。
|
||||
|
||||
## 12. 注释规范
|
||||
|
||||
必须为以下非显然逻辑添加简洁中文注释,解释“为什么”:
|
||||
|
||||
- Local 搜索权重及稳定排序;
|
||||
- Server/Client 边界选择;
|
||||
- 图标 fallback 顺序;
|
||||
- hydration 后同步 `localStorage`;
|
||||
- 分类导航临时禁用;
|
||||
- 数据校验中的跨分类引用规则。
|
||||
|
||||
普通 JSX、显然的变量赋值和框架惯用代码不添加复述式注释。
|
||||
|
||||
## 13. 测试设计
|
||||
|
||||
### 13.1 纯函数
|
||||
|
||||
- 问候语全部时间边界;
|
||||
- 日期格式;
|
||||
- 搜索 URL 与特殊字符编码;
|
||||
- Local 搜索字段、权重、排序和数量上限;
|
||||
- 图标引用解析;
|
||||
- 数据结构及交叉引用。
|
||||
|
||||
### 13.2 组件交互
|
||||
|
||||
- 自动聚焦;
|
||||
- Provider 严格分离;
|
||||
- Provider 持久化与非法值回退;
|
||||
- Local 键盘导航、Enter、Esc、点击和无结果;
|
||||
- `Ctrl+K` / `⌘K`;
|
||||
- 侧栏折叠、恢复和异常存储回退;
|
||||
- 新标签页链接安全属性;
|
||||
- 分类项禁用状态。
|
||||
|
||||
## 14. 验证与视觉验收
|
||||
|
||||
完成后必须运行:
|
||||
|
||||
```text
|
||||
pnpm lint
|
||||
pnpm typecheck
|
||||
pnpm test
|
||||
pnpm build
|
||||
```
|
||||
|
||||
随后实际启动页面并检查:
|
||||
|
||||
- `1440 × 900`;
|
||||
- `1920 × 1080`;
|
||||
- `1024 × 768`。
|
||||
|
||||
检查项:
|
||||
|
||||
- 无横向溢出;
|
||||
- 背景渐变层次和文本对比度;
|
||||
- 玻璃透明度、边框与阴影一致;
|
||||
- 侧栏展开/折叠比例;
|
||||
- 搜索聚焦与 Provider 交互;
|
||||
- Local 结果定位和键盘交互;
|
||||
- 卡片排列、hover 和 focus;
|
||||
- `prefers-reduced-motion`;
|
||||
- 控制台无 hydration error 或运行时错误。
|
||||
|
||||
设计图用于构图和氛围参照,不要求像素级复制图片背景。
|
||||
|
||||
## 15. 完成定义
|
||||
|
||||
只有以下条件全部满足,`feat/polaris-homepage` 才完成:
|
||||
|
||||
1. 推荐目录和工程配置建立;
|
||||
2. 文档及资产迁移完成,内部链接有效;
|
||||
3. 完整可交互首页实现;
|
||||
4. 自动化检查全部通过;
|
||||
5. 真实页面完成三个尺寸的视觉检查;
|
||||
6. 实际结果、视觉观察和已知偏差如实报告;
|
||||
7. 未提前实现正式分类页;
|
||||
8. 完成后再执行提交操作。
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,433 @@
|
||||
# Polaris 项目说明文档
|
||||
|
||||
> 关联文档:
|
||||
> [Polaris 首页设计文档](./Polaris%20首页设计文档.md) —— 首页布局、搜索交互、视觉规范
|
||||
> [Polaris 分类页设计文档](./Polaris%20分类页设计文档.md) —— 分类页布局、卡片、状态设计
|
||||
>
|
||||
> 配套资产:[占位 Logo](../../public/brand/logo.svg)(后续替换)、[Polaris 页面设计图](../assets/Polaris页面设计图.png)
|
||||
|
||||
## 1. 项目名称
|
||||
|
||||
**Polaris**
|
||||
|
||||
Polaris 原意为“北极星”,具有方向、导航、定位、指引的含义。该名称与个人导航站的产品定位非常契合。
|
||||
|
||||
本项目的核心目标是打造一个轻量、安静、高效、可长期维护的个人导航站,用于集中管理和访问常用网站、分类资源与个人入口。
|
||||
|
||||
---
|
||||
|
||||
## 2. 项目定位
|
||||
|
||||
Polaris 不是后台管理系统,也不是信息密集型 Dashboard。
|
||||
|
||||
> 一个具有个人审美、可自定义背景、可快速搜索和访问常用链接的浏览器起始页。
|
||||
|
||||
产品形态是**动态可配置的个人导航站**:第一版可以静态部署,数据写死在本地配置中,但页面具有动态交互(实时时钟、搜索、侧边栏折叠、快捷键等),后续将本地数据源替换为 Go 后端 API,不需要推翻前端整体结构。
|
||||
|
||||
---
|
||||
|
||||
## 3. 项目目标
|
||||
|
||||
第一阶段目标:
|
||||
|
||||
1. 提供一个美观的个人导航首页;
|
||||
2. 支持快速访问常用链接;
|
||||
3. 支持左侧分类导航与分类页;
|
||||
4. 支持搜索框(Google / Bing / GitHub / 本地);
|
||||
5. 支持当前时间与日期展示;
|
||||
6. 支持左侧边栏折叠(状态持久化);
|
||||
7. 支持背景自定义的设计预留;
|
||||
8. 数据第一版写死在本地 JSON 数据配置中;
|
||||
9. 代码结构预留未来接入 Go 后端接口的能力。
|
||||
|
||||
后续阶段目标:
|
||||
|
||||
1. 从 Go 后端 API 获取链接、分类、设置等数据;
|
||||
2. 使用数据库持久化配置;
|
||||
3. 支持后台或隐藏入口管理链接;
|
||||
4. 支持用户自定义背景;
|
||||
5. 支持主题色、深色模式、导入导出、移动端适配等个性化能力。
|
||||
|
||||
---
|
||||
|
||||
## 4. 已确认的关键决策
|
||||
|
||||
以下决策已于 2026-08-21 确认,作为实施基线:
|
||||
|
||||
| # | 决策项 | 结论 |
|
||||
| --- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 1 | 技术栈 | 以本文档为准:Next.js + TypeScript + Tailwind CSS + shadcn/ui + lucide-react(早期 README 中 Astro 设想作废) |
|
||||
| 2 | 渲染策略 | 静态导出(`output: 'export'`),时钟/搜索/侧边栏折叠为 client 岛屿 |
|
||||
| 3 | 包管理器 | pnpm |
|
||||
| 4 | 项目位置 | `ts/web/nextjs/polaris/` |
|
||||
| 5 | Logo | 现有 `logo.svg` 仅作占位,后续替换,不投入设计精力 |
|
||||
| 6 | 数据载体 | 本地 JSON 数据文件(`links.json` / `categories.json` / `settings.json`),结构以 Vitest 校验测试兜底 |
|
||||
| 7 | 第一版数据范围 | 「开发工具」15 条 + 首页常用链接 8 条(跨分类条目归入真实分类,见首页设计文档 8.1);设计资源、学习资料、生活服务三个分类展示空状态 |
|
||||
| 8 | 默认背景 | CSS 低饱和青蓝渐变,不依赖图片资产;`settings.background.type` 预留 `image` |
|
||||
| 9 | 深色模式 | 第一版不做;CSS 变量按双主题友好组织,后续以 `[data-theme="dark"]` 覆盖 |
|
||||
| 10 | 移动端 | 第一版不适配,仅桌面端 |
|
||||
| 11 | 快捷键 | Ctrl+K(macOS ⌘K)聚焦搜索框,仅首页生效;提示按平台检测显示 |
|
||||
| 12 | 图标方案 | 四级 fallback:自定义图标 → Simple Icons / 本地图标库 → favicon 自动抓取 → 文字占位(见 6.4) |
|
||||
| 13 | 后端数据库 | PostgreSQL(后续阶段);表结构不锁死 PG 特有语法(JSON 存通用 TEXT) |
|
||||
| 14 | 搜索行为 | 按模式严格分离:选中哪个引擎就只用哪个引擎搜索(回车直跳);仅 Local 模式显示本地结果下拉 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术选型
|
||||
|
||||
### 5.1 前端技术栈
|
||||
|
||||
```text
|
||||
Next.js(App Router)
|
||||
TypeScript
|
||||
Tailwind CSS
|
||||
shadcn/ui
|
||||
lucide-react
|
||||
simple-icons
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
1. **Next.js**:适合从静态页面起步,后续接入动态接口;
|
||||
2. **TypeScript**:适合维护链接、分类、配置等结构化数据;
|
||||
3. **Tailwind CSS**:适合快速实现玻璃感、响应式、主题变量;
|
||||
4. **shadcn/ui**:用于基础组件,例如 Button、Input、Dialog、Command;
|
||||
5. **lucide-react**:用于侧边栏和操作图标;
|
||||
6. **simple-icons**:品牌图标库(npm 包,按 slug 引用)。
|
||||
|
||||
测试:Vitest + Testing Library,重点覆盖纯函数(问候语分段、本地搜索匹配排序、icon 解析、搜索 URL 模板)与核心交互组件。
|
||||
|
||||
### 5.2 渲染策略
|
||||
|
||||
采用静态导出:
|
||||
|
||||
```ts
|
||||
// next.config.ts
|
||||
const nextConfig = { output: "export" }
|
||||
```
|
||||
|
||||
- 首页与全部分类页在构建时从本地数据生成(`generateStaticParams`);
|
||||
- 时钟、搜索、侧边栏折叠等交互以 client 组件实现;
|
||||
- 产物为纯静态文件,可部署到任意静态服务器;
|
||||
- 后续接 Go 后端时,改造 service 层为 fetch,数据页面改为客户端获取。
|
||||
|
||||
### 5.3 数据访问层
|
||||
|
||||
**页面组件不直接依赖数据文件,一律通过 service 层获取数据。**
|
||||
|
||||
第一版:
|
||||
|
||||
```ts
|
||||
import links from "@/data/links.json"
|
||||
|
||||
export function getLinks(): NavLink[] {
|
||||
return links
|
||||
}
|
||||
```
|
||||
|
||||
后续接 Go 后端时,只需要修改 service 层:
|
||||
|
||||
```ts
|
||||
export async function getLinks() {
|
||||
const res = await fetch("/api/links")
|
||||
if (!res.ok) {
|
||||
throw new Error("Failed to fetch links")
|
||||
}
|
||||
return res.json()
|
||||
}
|
||||
```
|
||||
|
||||
这样页面组件不用大规模重构。
|
||||
|
||||
JSON 缺少编译期类型检查,用 **Vitest 数据校验测试**兜底:校验 `data/*.json` 满足 `Category[]` / `NavLink[]` / `AppSettings` 结构(必填字段齐全、类型正确、categoryId 存在于分类中),字段拼错或漏填在测试阶段即报错。
|
||||
|
||||
### 5.4 后端技术栈(后续阶段)
|
||||
|
||||
后端由 Go 实现,数据库 PostgreSQL。
|
||||
|
||||
候选组合:
|
||||
|
||||
```text
|
||||
Go + Chi + sqlc —— 结构清晰、SQL 可控(推荐)
|
||||
Go + Gin + GORM —— 开发更快、上手成本低
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 数据结构
|
||||
|
||||
### 6.1 分类数据
|
||||
|
||||
```ts
|
||||
{
|
||||
id: "dev",
|
||||
title: "开发工具",
|
||||
description: "高效的开发工具和资源集合,提升你的开发体验和效率。",
|
||||
icon: "code",
|
||||
sort: 20
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
|
||||
```text
|
||||
id: 分类唯一标识
|
||||
title: 分类名称
|
||||
description: 分类描述(分类页标题下方展示)
|
||||
icon: 图标名称(侧边栏,lucide 图标名)
|
||||
sort: 排序值
|
||||
```
|
||||
|
||||
### 6.2 链接数据
|
||||
|
||||
```ts
|
||||
{
|
||||
id: "github",
|
||||
title: "GitHub",
|
||||
description: "全球最大的代码托管平台",
|
||||
url: "https://github.com",
|
||||
icon: "si:github",
|
||||
categoryId: "dev",
|
||||
pinned: true,
|
||||
pinnedSort: 10,
|
||||
keywords: ["代码", "仓库", "开源", "git"],
|
||||
sort: 10
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
|
||||
```text
|
||||
id: 链接唯一标识
|
||||
title: 链接名称
|
||||
description: 简短描述(分类页卡片展示,8-16 个中文字)
|
||||
url: 链接地址
|
||||
icon: 图标引用,格式见 6.4
|
||||
categoryId: 所属分类
|
||||
pinned: 是否展示在首页常用链接区域
|
||||
pinnedSort: 首页常用链接顺序(仅 pinned 为 true 时必填)
|
||||
keywords: 本地搜索关键词
|
||||
sort: 分类内排序值
|
||||
```
|
||||
|
||||
### 6.3 设置数据
|
||||
|
||||
```ts
|
||||
{
|
||||
siteName: "Polaris",
|
||||
theme: "light-glass",
|
||||
search: {
|
||||
defaultProvider: "google",
|
||||
enabledProviders: ["google", "bing", "github", "local"]
|
||||
},
|
||||
background: {
|
||||
type: "gradient", // "gradient" | "image"
|
||||
url: null, // type 为 image 时生效
|
||||
blur: 8,
|
||||
overlay: 0.32
|
||||
},
|
||||
sidebar: {
|
||||
defaultCollapsed: false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.4 统一图标方案
|
||||
|
||||
链接卡片与搜索结果的图标按以下顺序解析,逐级 fallback:
|
||||
|
||||
```text
|
||||
1. 自定义图标 icon: "local:xxx" → public/icons/xxx.svg
|
||||
2. Simple Icons icon: "si:github" → simple-icons npm 包按 slug 渲染品牌图标
|
||||
3. favicon 抓取 icon: "url:https://..." → 远程图标;icon 缺省时按链接 url 域名自动抓取
|
||||
4. 文字占位 以上全部失败 → 标题首字符 + 圆角玻璃底兜底
|
||||
```
|
||||
|
||||
侧边栏分类导航图标使用 lucide-react(如 `home` / `code` / `palette`),不参与此 fallback 链。
|
||||
|
||||
---
|
||||
|
||||
## 7. 未来 Go 后端 API 设计
|
||||
|
||||
后续接入 Go 后端时,推荐 API:
|
||||
|
||||
```text
|
||||
GET /api/categories
|
||||
GET /api/links
|
||||
GET /api/links?categoryId=dev
|
||||
GET /api/settings
|
||||
```
|
||||
|
||||
后续管理能力:
|
||||
|
||||
```text
|
||||
POST /api/links
|
||||
PUT /api/links/:id
|
||||
DELETE /api/links/:id
|
||||
|
||||
POST /api/categories
|
||||
PUT /api/categories/:id
|
||||
DELETE /api/categories/:id
|
||||
|
||||
PUT /api/settings
|
||||
```
|
||||
|
||||
背景相关:
|
||||
|
||||
```text
|
||||
POST /api/backgrounds
|
||||
GET /api/backgrounds
|
||||
PUT /api/settings/background
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 数据库表设计草案
|
||||
|
||||
> 草案使用跨数据库通用语法;JSON 以 TEXT 存储。PostgreSQL 下可将 `TEXT`(存 JSON)字段替换为 `JSONB` 以获得索引与查询能力。
|
||||
|
||||
### 8.1 categories
|
||||
|
||||
```sql
|
||||
CREATE TABLE categories (
|
||||
id TEXT PRIMARY KEY,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
icon TEXT NOT NULL,
|
||||
sort INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
### 8.2 links
|
||||
|
||||
```sql
|
||||
CREATE TABLE links (
|
||||
id TEXT PRIMARY KEY,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
url TEXT NOT NULL,
|
||||
icon TEXT,
|
||||
category_id TEXT NOT NULL,
|
||||
pinned BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
pinned_sort INTEGER,
|
||||
keywords TEXT NOT NULL DEFAULT '[]', -- JSON 数组字符串
|
||||
sort INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT fk_links_category
|
||||
FOREIGN KEY (category_id)
|
||||
REFERENCES categories(id)
|
||||
);
|
||||
```
|
||||
|
||||
### 8.3 settings
|
||||
|
||||
```sql
|
||||
CREATE TABLE settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL, -- JSON 字符串
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 开发阶段
|
||||
|
||||
### 第一阶段:前端静态版(当前阶段)
|
||||
|
||||
目标:完成首页与分类页基础体验。
|
||||
|
||||
```text
|
||||
页面背景(CSS 渐变)与背景遮罩
|
||||
左侧边栏 + 折叠(localStorage 持久化)+ 导航选中态
|
||||
时间 / 日期 / 问候语
|
||||
搜索框(Google / Bing / GitHub / 本地搜索)+ Ctrl+K 快捷键
|
||||
常用链接(pinned,8 个)
|
||||
分类页路由 + 卡片网格 + 空状态
|
||||
桌面端响应式
|
||||
```
|
||||
|
||||
数据范围:开发工具 15 个链接 + 首页 8 个常用链接(跨分类条目归入真实分类:ChatGPT → AI 工具,Gmail / Notion → 效率工具,YouTube / Bilibili → 娱乐媒体);设计资源、学习资料、生活服务三个分类展示空状态。
|
||||
|
||||
### 第二阶段:数据补全与体验完善
|
||||
|
||||
```text
|
||||
补全其余 6 个分类的链接数据
|
||||
深色玻璃主题
|
||||
移动端 / 平板适配
|
||||
```
|
||||
|
||||
### 第三阶段:数据访问层抽象
|
||||
|
||||
```text
|
||||
封装 links / categories / settings service
|
||||
统一 TypeScript 类型
|
||||
统一错误处理与 loading 状态
|
||||
```
|
||||
|
||||
此阶段完成后,页面组件不直接关心数据来自本地配置还是 API。
|
||||
|
||||
### 第四阶段:Go 后端 API
|
||||
|
||||
```text
|
||||
Go API 服务
|
||||
数据库连接(PostgreSQL)
|
||||
links / categories / settings 查询接口
|
||||
基础 CORS 配置
|
||||
Docker 部署预留
|
||||
```
|
||||
|
||||
### 第五阶段:管理能力
|
||||
|
||||
```text
|
||||
新增 / 编辑 / 删除链接
|
||||
调整排序、修改分类
|
||||
修改背景、主题
|
||||
导入导出配置
|
||||
```
|
||||
|
||||
管理能力不进入首页主视觉,放到独立管理页或隐藏入口。
|
||||
|
||||
---
|
||||
|
||||
## 10. 项目目录结构
|
||||
|
||||
```text
|
||||
polaris/
|
||||
public/
|
||||
icons/ # 自定义 SVG 图标(icon: "local:xxx" 引用)
|
||||
logo.svg
|
||||
|
||||
src/
|
||||
app/
|
||||
layout.tsx # 背景层 + 字体
|
||||
page.tsx # 首页
|
||||
categories/
|
||||
[categoryId]/
|
||||
page.tsx # 分类页(generateStaticParams 生成)
|
||||
globals.css # Tailwind + CSS 变量(浅色值,深色预留覆盖位)
|
||||
|
||||
components/
|
||||
layout/ # AppShell / Sidebar / SidebarNavItem
|
||||
home/ # ClockGreeting / SearchBox / SearchResults / QuickLinks
|
||||
category/ # CategoryHeader / ToolGrid / ToolCard
|
||||
common/ # SiteIcon(四级 fallback)/ GlassPanel
|
||||
|
||||
data/ # links.json / categories.json / settings.json
|
||||
services/ # links.ts / categories.ts / settings.ts / search.ts
|
||||
types/ # navigation.ts / settings.ts / search.ts
|
||||
lib/ # cn.ts / greeting.ts / local-search.ts / search-providers.ts / icon.ts(纯函数)
|
||||
|
||||
next.config.ts # output: 'export'
|
||||
vitest.config.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 最终目标
|
||||
|
||||
> 打开 Polaris 后,用户可以立刻搜索、立刻访问常用网站,也可以通过侧边栏进入分类页面。页面具有个人氛围,但保持干净、高效、克制。第一版数据本地配置,后续平滑切换到 Go 后端。
|
||||
@@ -0,0 +1,780 @@
|
||||
# Polaris 首页设计文档
|
||||
|
||||
> 关联文档:
|
||||
> [Polaris 项目说明文档](./Polaris%20项目说明文档.md) —— 项目定位、技术选型、数据结构、开发阶段
|
||||
> [Polaris 分类页设计文档](./Polaris%20分类页设计文档.md) —— 分类页布局与交互
|
||||
>
|
||||
> 配套设计图:[Polaris 页面设计图](../assets/Polaris页面设计图.png)(示意图,视觉细节以本文档文字规范为准)
|
||||
|
||||
## 1. 页面定位
|
||||
|
||||
Polaris 首页是一个**浏览器起始页**,不是后台管理系统,也不是信息密集型 Dashboard。
|
||||
|
||||
> 一个具有个人审美、可自定义背景、可快速搜索和访问常用链接的浏览器起始页。
|
||||
|
||||
首页应给人的感觉是:
|
||||
|
||||
```text
|
||||
私人入口
|
||||
浏览器首页
|
||||
轻量工具启动页
|
||||
个人网址导航
|
||||
安静、高效、有氛围感
|
||||
```
|
||||
|
||||
而不是:
|
||||
|
||||
```text
|
||||
后台系统
|
||||
资源管理平台
|
||||
复杂书签管理器
|
||||
信息看板
|
||||
数据仪表盘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 整体视觉风格
|
||||
|
||||
首页推荐采用:
|
||||
|
||||
> 轻量玻璃感 + 极简浏览器起始页 + 柔和个人空间感
|
||||
|
||||
设计关键词:
|
||||
|
||||
```text
|
||||
极简
|
||||
半透明
|
||||
玻璃感
|
||||
柔和阴影
|
||||
大留白
|
||||
低饱和
|
||||
可换背景
|
||||
个人化
|
||||
安静
|
||||
高级感
|
||||
```
|
||||
|
||||
整体视觉应避免过重的管理系统风格。
|
||||
|
||||
首页不应常驻展示以下元素:
|
||||
|
||||
```text
|
||||
设置按钮
|
||||
编辑按钮
|
||||
管理按钮
|
||||
新增按钮
|
||||
统计数据
|
||||
用户头像
|
||||
访问次数
|
||||
站点域名副标题
|
||||
复杂分类卡片
|
||||
```
|
||||
|
||||
这些能力在后续阶段通过隐藏入口、独立配置页或快捷键面板实现。
|
||||
|
||||
---
|
||||
|
||||
## 3. 首页整体布局
|
||||
|
||||
首页采用左右结构:
|
||||
|
||||
```text
|
||||
┌──────────────────┬────────────────────────────────────────────┐
|
||||
│ 左侧边栏 │ 主内容区域 │
|
||||
│ │ │
|
||||
│ Logo + 折叠按钮 │ 问候语 + 当前时间 │
|
||||
│ 首页 │ 日期 / 星期 │
|
||||
│ AI 工具 │ 搜索框 │
|
||||
│ 开发工具 │ 常用链接 │
|
||||
│ 设计资源 │ │
|
||||
│ 学习资料 │ │
|
||||
│ 效率工具 │ │
|
||||
│ 娱乐媒体 │ │
|
||||
│ 生活服务 │ │
|
||||
└──────────────────┴────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
布局原则:
|
||||
|
||||
1. 左侧边栏负责分类导航;
|
||||
2. 主内容区域只展示最高频内容;
|
||||
3. 首页不展示分类卡片;
|
||||
4. 首页不展示编辑、设置、管理类按钮;
|
||||
5. 常用链接只做轻量展示。
|
||||
|
||||
主内容整体居中,视觉重心位于页面中上方。
|
||||
|
||||
推荐信息层级:
|
||||
|
||||
```text
|
||||
1. 当前时间 / 问候语
|
||||
2. 搜索框
|
||||
3. 常用链接
|
||||
4. 左侧分类导航
|
||||
5. 背景氛围
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 左侧边栏设计
|
||||
|
||||
### 4.1 边栏内容
|
||||
|
||||
左侧边栏从上到下依次展示:
|
||||
|
||||
```text
|
||||
Logo
|
||||
折叠按钮
|
||||
首页
|
||||
AI 工具
|
||||
开发工具
|
||||
设计资源
|
||||
学习资料
|
||||
效率工具
|
||||
娱乐媒体
|
||||
生活服务
|
||||
```
|
||||
|
||||
「首页」指向 `/`,各分类指向 `/categories/{categoryId}`。当前路由对应的导航项处于选中态,选中样式见[分类页设计文档](./Polaris%20分类页设计文档.md) 6.2 节。
|
||||
|
||||
暂时不展示:
|
||||
|
||||
```text
|
||||
设置
|
||||
关于
|
||||
编辑
|
||||
管理
|
||||
新增分类
|
||||
账户信息
|
||||
```
|
||||
|
||||
### 4.2 折叠按钮位置
|
||||
|
||||
折叠按钮放在侧边栏顶部右侧,与 Logo 位于同一行。
|
||||
|
||||
示意:
|
||||
|
||||
```text
|
||||
┌──────────────────────┐
|
||||
│ Logo ≪ │
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
不采用侧边栏中间悬浮按钮。
|
||||
|
||||
原因:
|
||||
|
||||
1. 中间悬浮按钮视觉上突兀;
|
||||
2. 容易产生后台管理系统的感觉;
|
||||
3. 会破坏页面边界的干净感;
|
||||
4. 顶部右侧更符合用户对全局控制按钮的认知。
|
||||
|
||||
### 4.3 边栏宽度
|
||||
|
||||
展开状态:
|
||||
|
||||
```text
|
||||
推荐宽度:240px
|
||||
可选范围:220px - 260px
|
||||
```
|
||||
|
||||
折叠状态:
|
||||
|
||||
```text
|
||||
推荐宽度:72px
|
||||
可选范围:68px - 80px
|
||||
```
|
||||
|
||||
展开时显示图标和文字。
|
||||
|
||||
折叠时只显示图标。
|
||||
|
||||
折叠状态持久化到 `localStorage`,刷新后保持。
|
||||
|
||||
### 4.4 边栏视觉样式
|
||||
|
||||
推荐样式:
|
||||
|
||||
```css
|
||||
background: rgba(255, 255, 255, 0.68);
|
||||
backdrop-filter: blur(24px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.45);
|
||||
box-shadow: 0 24px 80px rgba(15, 23, 42, 0.1);
|
||||
border-radius: 24px;
|
||||
```
|
||||
|
||||
边栏与页面边缘保持一定距离,形成悬浮玻璃面板感。
|
||||
|
||||
推荐边距:
|
||||
|
||||
```text
|
||||
left: 20px;
|
||||
top: 20px;
|
||||
bottom: 20px;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 时间与问候语
|
||||
|
||||
首页顶部展示问候语和当前时间。
|
||||
|
||||
示例:
|
||||
|
||||
```text
|
||||
晚上好,21:56
|
||||
2026 年 8 月 20 日 星期四
|
||||
```
|
||||
|
||||
问候语规则:
|
||||
|
||||
```text
|
||||
05:00 - 11:59 早上好
|
||||
12:00 - 13:59 中午好
|
||||
14:00 - 17:59 下午好
|
||||
18:00 - 23:59 晚上好
|
||||
00:00 - 04:59 夜深了
|
||||
```
|
||||
|
||||
推荐样式:
|
||||
|
||||
```css
|
||||
font-size: 56px;
|
||||
font-weight: 700;
|
||||
color: #0f172a;
|
||||
```
|
||||
|
||||
日期样式:
|
||||
|
||||
```css
|
||||
font-size: 16px;
|
||||
color: #64748b;
|
||||
```
|
||||
|
||||
时间为客户端实时时钟,每分钟更新。
|
||||
|
||||
---
|
||||
|
||||
## 6. 搜索框设计
|
||||
|
||||
### 6.1 搜索框定位
|
||||
|
||||
搜索框是 Polaris 首页最核心的交互组件。
|
||||
|
||||
搜索框位于时间与日期下方,居中展示,首页加载后**自动聚焦**。
|
||||
|
||||
### 6.2 搜索范围
|
||||
|
||||
首页搜索框支持以下四种搜索方式:
|
||||
|
||||
```text
|
||||
Google 搜索
|
||||
Bing 搜索
|
||||
GitHub 搜索
|
||||
本地搜索
|
||||
```
|
||||
|
||||
其中:
|
||||
|
||||
1. **Google 搜索**:使用 Google 搜索引擎搜索输入内容;
|
||||
2. **Bing 搜索**:使用 Bing 搜索引擎搜索输入内容;
|
||||
3. **GitHub 搜索**:在 GitHub 中搜索输入内容;
|
||||
4. **本地搜索**:搜索 Polaris 本地配置中的链接、分类和名称。
|
||||
|
||||
第一版不支持:
|
||||
|
||||
```text
|
||||
直接输入 URL 跳转
|
||||
自定义搜索引擎
|
||||
多搜索引擎聚合结果
|
||||
AI 搜索
|
||||
站外爬取搜索
|
||||
全文索引搜索
|
||||
```
|
||||
|
||||
这些能力作为后续扩展。
|
||||
|
||||
### 6.3 搜索框尺寸
|
||||
|
||||
桌面端推荐:
|
||||
|
||||
```text
|
||||
width: 760px;
|
||||
height: 68px;
|
||||
```
|
||||
|
||||
可选范围:
|
||||
|
||||
```text
|
||||
宽度:720px - 860px
|
||||
高度:64px - 72px
|
||||
```
|
||||
|
||||
> 移动端尺寸第一版不定义,移动端整体适配为后续阶段工作。
|
||||
|
||||
### 6.4 搜索框视觉样式
|
||||
|
||||
推荐样式:
|
||||
|
||||
```css
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
backdrop-filter: blur(22px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.65);
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 20px 60px rgba(15, 23, 42, 0.12);
|
||||
```
|
||||
|
||||
placeholder 统一为:
|
||||
|
||||
```text
|
||||
搜索网站、书签或关键词...
|
||||
```
|
||||
|
||||
右侧展示快捷键提示,**按平台检测显示**:
|
||||
|
||||
```text
|
||||
macOS:⌘K
|
||||
Windows / Linux:Ctrl K
|
||||
```
|
||||
|
||||
快捷键行为:按下后聚焦搜索框(详见 7.4)。
|
||||
|
||||
### 6.5 搜索模式切换
|
||||
|
||||
搜索模式可以通过以下方式切换:
|
||||
|
||||
```text
|
||||
搜索框左侧下拉选择
|
||||
快捷键切换
|
||||
命令面板中选择
|
||||
默认使用上一次选择的搜索方式
|
||||
```
|
||||
|
||||
第一版采用简单方案:
|
||||
|
||||
```text
|
||||
搜索框左侧或右侧提供当前搜索模式标识
|
||||
点击后可切换 Google / Bing / GitHub / 本地
|
||||
```
|
||||
|
||||
### 6.6 本地搜索范围
|
||||
|
||||
本地搜索的数据来自本地数据配置。
|
||||
|
||||
搜索范围包括:
|
||||
|
||||
```text
|
||||
链接标题
|
||||
链接关键词
|
||||
链接描述
|
||||
分类名称
|
||||
分类 ID
|
||||
```
|
||||
|
||||
链接数据预留 `keywords` 字段,完整数据结构见[项目说明文档](./Polaris%20项目说明文档.md)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 搜索功能设计
|
||||
|
||||
### 7.1 搜索 Provider
|
||||
|
||||
支持四个 provider:
|
||||
|
||||
```ts
|
||||
export type SearchProvider = "google" | "bing" | "github" | "local"
|
||||
```
|
||||
|
||||
### 7.2 搜索行为
|
||||
|
||||
Google:
|
||||
|
||||
```text
|
||||
https://www.google.com/search?q={keyword}
|
||||
```
|
||||
|
||||
Bing:
|
||||
|
||||
```text
|
||||
https://www.bing.com/search?q={keyword}
|
||||
```
|
||||
|
||||
GitHub:
|
||||
|
||||
```text
|
||||
https://github.com/search?q={keyword}
|
||||
```
|
||||
|
||||
Local:
|
||||
|
||||
```text
|
||||
在本地 links / categories 数据中搜索
|
||||
```
|
||||
|
||||
### 7.3 本地搜索匹配规则
|
||||
|
||||
本地搜索匹配字段:
|
||||
|
||||
```text
|
||||
title
|
||||
keywords
|
||||
categoryId
|
||||
category title
|
||||
```
|
||||
|
||||
推荐匹配逻辑(权重从高到低):
|
||||
|
||||
```text
|
||||
完全匹配优先
|
||||
标题匹配其次
|
||||
关键词匹配再次
|
||||
分类匹配最后
|
||||
```
|
||||
|
||||
搜索结果展示:
|
||||
|
||||
```text
|
||||
图标
|
||||
标题
|
||||
所属分类
|
||||
```
|
||||
|
||||
搜索行为**按模式严格分离**:选择使用哪个搜索引擎,就只用它搜索。
|
||||
|
||||
```text
|
||||
Google / Bing / GitHub 模式:回车直接跳转对应引擎搜索,不显示任何下拉
|
||||
Local 模式:输入时实时显示本地结果下拉(见 7.5)
|
||||
```
|
||||
|
||||
Local 模式回车行为:
|
||||
|
||||
```text
|
||||
如果只有一个高匹配本地结果,回车打开该链接
|
||||
如果有多个结果,↑ / ↓ 选择后回车打开选中项(默认选中第一项)
|
||||
如果没有结果,展示空状态
|
||||
```
|
||||
|
||||
### 7.4 快捷键
|
||||
|
||||
```text
|
||||
Ctrl K(macOS 为 ⌘K):聚焦搜索框
|
||||
Esc:清空输入 / 关闭结果列表
|
||||
```
|
||||
|
||||
快捷键仅在首页生效,分类页不响应。
|
||||
|
||||
---
|
||||
|
||||
### 7.5 结果下拉面板(仅 Local 模式)
|
||||
|
||||
面板出现在搜索框正下方,与搜索框同宽,间距 8px,视觉上与搜索框衔接为一体。
|
||||
|
||||
面板样式:
|
||||
|
||||
```css
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
backdrop-filter: blur(22px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.65);
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 20px 60px rgba(15, 23, 42, 0.12);
|
||||
```
|
||||
|
||||
列表项内容:
|
||||
|
||||
```text
|
||||
图标(遵循统一图标方案)
|
||||
标题
|
||||
所属分类
|
||||
```
|
||||
|
||||
交互:
|
||||
|
||||
```text
|
||||
↑ / ↓ 在结果间移动选中项
|
||||
回车打开选中项(新标签页)
|
||||
Esc 关闭面板
|
||||
鼠标点击直接打开
|
||||
选中项背景 rgba(59, 130, 246, 0.10)
|
||||
```
|
||||
|
||||
结果数量上限 8 条;无匹配时面板内展示空状态「没有匹配的网站」。
|
||||
|
||||
---
|
||||
|
||||
## 8. 常用链接区域
|
||||
|
||||
### 8.1 区域定位
|
||||
|
||||
常用链接用于展示用户最高频访问的网站。
|
||||
|
||||
首页不展示分类卡片,以保持页面干净。
|
||||
|
||||
第一版展示 8 个常用链接:
|
||||
|
||||
```text
|
||||
GitHub
|
||||
ChatGPT
|
||||
Gmail
|
||||
Notion
|
||||
Figma
|
||||
YouTube
|
||||
Vercel
|
||||
Bilibili
|
||||
```
|
||||
|
||||
实际项目中根据个人习惯调整。
|
||||
|
||||
数据来源:`pinned: true` 的链接,按 `pinnedSort` 排序取前 8 个;超出 8 个时按 4 列网格换行展示。`sort` 仅用于分类内排序,避免首页顺序与分类页顺序相互约束。
|
||||
|
||||
第一版数据构成(8 条 pinned 分布于各分类,归入真实分类):
|
||||
|
||||
```text
|
||||
GitHub → 开发工具(dev)
|
||||
Vercel → 开发工具(dev)
|
||||
Figma → 开发工具(dev)
|
||||
ChatGPT → AI 工具(ai)
|
||||
Gmail → 效率工具(efficiency)
|
||||
Notion → 效率工具(efficiency)
|
||||
YouTube → 娱乐媒体(media)
|
||||
Bilibili → 娱乐媒体(media)
|
||||
```
|
||||
|
||||
其中 ChatGPT、Gmail、Notion、YouTube、Bilibili 5 条是为首页常用链接补入的跨分类条目。受此影响,AI 工具、效率工具、娱乐媒体三个分类页会展示少量链接而非空状态;纯空状态分类为设计资源、学习资料、生活服务。
|
||||
|
||||
### 8.2 链接卡片内容
|
||||
|
||||
常用链接卡片只展示:
|
||||
|
||||
```text
|
||||
图标
|
||||
名称
|
||||
```
|
||||
|
||||
不展示:
|
||||
|
||||
```text
|
||||
域名
|
||||
描述
|
||||
编辑按钮
|
||||
更多按钮
|
||||
拖拽按钮
|
||||
访问统计
|
||||
```
|
||||
|
||||
图标来源遵循统一图标方案(见[项目说明文档](./Polaris%20项目说明文档.md)):自定义图标 → Simple Icons / 本地图标库 → favicon 自动抓取 → 文字占位兜底。
|
||||
|
||||
### 8.3 链接卡片样式
|
||||
|
||||
推荐样式:
|
||||
|
||||
```css
|
||||
background: rgba(255, 255, 255, 0.62);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.56);
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 14px 40px rgba(15, 23, 42, 0.1);
|
||||
```
|
||||
|
||||
推荐尺寸:
|
||||
|
||||
```text
|
||||
width: 200px;
|
||||
height: 76px;
|
||||
```
|
||||
|
||||
推荐布局:
|
||||
|
||||
```text
|
||||
两行四列
|
||||
```
|
||||
|
||||
示意:
|
||||
|
||||
```text
|
||||
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ GitHub │ │ChatGPT │ │ Gmail │ │ Notion │
|
||||
└────────┘ └────────┘ └────────┘ └────────┘
|
||||
|
||||
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Figma │ │YouTube │ │ Vercel │ │Bilibili│
|
||||
└────────┘ └────────┘ └────────┘ └────────┘
|
||||
```
|
||||
|
||||
Hover 效果:
|
||||
|
||||
```css
|
||||
transform: translateY(-2px);
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
box-shadow: 0 18px 50px rgba(15, 23, 42, 0.14);
|
||||
transition: all 180ms ease;
|
||||
```
|
||||
|
||||
点击卡片在新标签页打开链接。
|
||||
|
||||
---
|
||||
|
||||
## 9. 背景设计
|
||||
|
||||
### 9.1 背景类型
|
||||
|
||||
Polaris 支持背景自定义的设计预留。
|
||||
|
||||
**第一版默认背景为 CSS 低饱和青蓝渐变**(模拟晨雾 / 天空氛围),不依赖图片资产。
|
||||
|
||||
后续支持:
|
||||
|
||||
```text
|
||||
静态图片背景
|
||||
渐变背景
|
||||
纯色背景
|
||||
本地上传背景
|
||||
远程图片背景
|
||||
深色背景
|
||||
```
|
||||
|
||||
图片背景建议:
|
||||
|
||||
```text
|
||||
湖面
|
||||
雪山
|
||||
晨雾
|
||||
天空
|
||||
抽象渐变
|
||||
低对比度风景图
|
||||
```
|
||||
|
||||
背景类型通过 `settings.background.type`(`gradient` / `image`)配置。
|
||||
|
||||
### 9.2 背景遮罩
|
||||
|
||||
由于用户未来可能更换任意背景,因此需要增加背景遮罩层,保证内容可读。
|
||||
|
||||
浅色主题:
|
||||
|
||||
```css
|
||||
background-overlay: rgba(255, 255, 255, 0.32);
|
||||
backdrop-filter: blur(8px);
|
||||
```
|
||||
|
||||
深色主题(后续阶段预留):
|
||||
|
||||
```css
|
||||
background-overlay: rgba(15, 23, 42, 0.42);
|
||||
backdrop-filter: blur(8px);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 配色系统
|
||||
|
||||
默认采用浅色玻璃主题。
|
||||
|
||||
推荐 CSS 变量:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-text-primary: #0f172a;
|
||||
--color-text-secondary: #64748b;
|
||||
--color-text-muted: #94a3b8;
|
||||
|
||||
--color-primary: #3b82f6;
|
||||
--color-primary-hover: #2563eb;
|
||||
--color-primary-soft: rgba(59, 130, 246, 0.1);
|
||||
|
||||
--color-surface-sidebar: rgba(255, 255, 255, 0.68);
|
||||
--color-surface-card: rgba(255, 255, 255, 0.62);
|
||||
--color-surface-search: rgba(255, 255, 255, 0.72);
|
||||
|
||||
--color-border-light: rgba(255, 255, 255, 0.56);
|
||||
--color-border-subtle: rgba(15, 23, 42, 0.08);
|
||||
|
||||
--shadow-soft: 0 14px 40px rgba(15, 23, 42, 0.1);
|
||||
--shadow-medium: 0 20px 60px rgba(15, 23, 42, 0.12);
|
||||
}
|
||||
```
|
||||
|
||||
变量按双主题友好方式组织:第一版只实现浅色值;深色玻璃主题为后续阶段,届时以 `[data-theme="dark"]` 覆盖同名变量,组件无需改动。
|
||||
|
||||
---
|
||||
|
||||
## 11. 字体建议
|
||||
|
||||
推荐字体栈:
|
||||
|
||||
```css
|
||||
font-family:
|
||||
Inter,
|
||||
"SF Pro Display",
|
||||
"SF Pro Text",
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
"Segoe UI",
|
||||
"PingFang SC",
|
||||
"Hiragino Sans GB",
|
||||
"Microsoft YaHei",
|
||||
sans-serif;
|
||||
```
|
||||
|
||||
字体原则:
|
||||
|
||||
```text
|
||||
标题清晰
|
||||
正文轻盈
|
||||
导航可读
|
||||
不要使用过度装饰性字体
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. 首页线框
|
||||
|
||||
```text
|
||||
┌──────────────────────┬────────────────────────────────────────────────────┐
|
||||
│ │ │
|
||||
│ LOGO ≪ │ │
|
||||
│ │ │
|
||||
│ ⌂ 首页 │ │
|
||||
│ ✦ AI 工具 │ 晚上好,21:56 │
|
||||
│ <> 开发工具 │ 2026 年 8 月 20 日 星期四 │
|
||||
│ ◌ 设计资源 │ │
|
||||
│ 📖 学习资料 │ ┌────────────────────────────────────┐ │
|
||||
│ ⚡ 效率工具 │ │ 🔍 搜索网站、书签或关键词... Ctrl K │ │
|
||||
│ ▶ 娱乐媒体 │ └────────────────────────────────────┘ │
|
||||
│ ☕ 生活服务 │ │
|
||||
│ │ 常用链接 │
|
||||
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │ │ GitHub │ │ChatGPT │ │ Gmail │ │ Notion │ │
|
||||
│ │ └────────┘ └────────┘ └────────┘ └────────┘ │
|
||||
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │ │ Figma │ │YouTube │ │ Vercel │ │Bilibili│ │
|
||||
│ │ └────────┘ └────────┘ └────────┘ └────────┘ │
|
||||
│ │ │
|
||||
└──────────────────────┴────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 13. 设计原则总结
|
||||
|
||||
首页遵循以下原则:
|
||||
|
||||
```text
|
||||
首页只放最高频内容
|
||||
搜索框是核心入口
|
||||
搜索范围保持克制
|
||||
常用链接轻量展示
|
||||
分类入口放在左侧边栏
|
||||
首页不展示分类卡片
|
||||
首页不展示编辑和设置按钮
|
||||
背景可换,但内容必须始终清晰
|
||||
玻璃感要轻,不要炫技
|
||||
交互动效要柔和,不要夸张
|
||||
整体像浏览器起始页,不像后台系统
|
||||
第一版数据本地配置,后续平滑切换到 Go 后端
|
||||
第一版仅实现浅色主题、仅适配桌面端
|
||||
```
|
||||
|
||||
最终目标:
|
||||
|
||||
> 打开 Polaris 后,用户可以立刻搜索、立刻访问常用网站,也可以通过侧边栏进入分类页面。页面具有个人氛围,但保持干净、高效、克制。
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user