first commit

This commit is contained in:
2026-08-11 16:17:49 +08:00
commit 21d086aa23
170 changed files with 13204 additions and 0 deletions

94
CLAUDE.md Normal file
View File

@@ -0,0 +1,94 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
项目:缠论研习社——缠中说禅《教你炒股票》原文与杂文的沉浸式阅读站。
## 命令
```bash
pnpm install # 安装依赖(需 Node 20+ 与 pnpm
pnpm dev # 开发服务器 → http://localhost:5173vite open 自动开浏览器)
pnpm build # vue-tsc -b 类型检查 + vite 生产构建
pnpm build:only # 跳过类型检查,仅 vite build
pnpm typecheck # 仅 vue-tsc -b 类型检查(改完 TS/Vue 先跑这个)
pnpm preview # 预览生产构建
```
本机 pnpm v11 用 `pnpm-workspace.yaml``allowBuilds`(不是 `onlyBuiltDependencies`)放行 esbuild / vue-demi 的构建脚本;新增带构建脚本的 devDep 时需在此手动放行,否则安装会被拦。
## 样式约定(重要)
### 每个用 Tailwind 写的元素必须带一个「标记类名」
用 Tailwind 工具类写样式时,**必须给每个有独立含义的元素加一个语义化的标记 class并放在 class 列表最前面**。这样用户在对话里能精确指代「改哪个 div」。
```vue
<!-- 不要纯工具类堆叠用户无法指代 -->
<div class="flex items-center gap-2 rounded-md bg-surface px-3 py-2">
<!-- 标记类名打头组件名__部位kebab-case -->
<div class="article-card__lesson flex items-center gap-2 rounded-md bg-surface px-3 py-2">
```
命名规则:`<组件或区块名>__<部位>`,如 `home-hero__title``reader-meta``article-card__tags`。一个 `.vue` 文件内的标记类名以该组件的功能名为前缀,保证跨组件不撞。
> 现存组件(如 `ArticleCard.vue`)尚未遵循此约定;**新建或重写元素时一律补上**,改动既有元素时顺手补。
### 颜色必须走设计 Token禁止裸色值
所有颜色用 `src/style.css``@theme inline` 定义的语义类,**不要写 `bg-white` / `text-gray-500` / `#fff` 这类**
- 背景:`bg-app`(应用底)/ `bg-background`(卡片)/ `bg-surface` / `bg-surface-2` / `bg-hover`
- 文本:`text-foreground` / `text-muted` / `text-subtle` / `text-faint`
- 品牌/语义:`text-primary` / `bg-primary-soft` / `text-success` / `text-warning` / `text-danger`
- 边框:`border-line` / `border-line-strong` / `border-line-card`
- 圆角用 `rounded-xs/sm/md/lg/xl/2xl`4/8/12/16/20/24阴影用 `shadow-xs/sm/soft/md/lg/xl`
亮/暗主题切换靠 `<html class="dark">`,所有语义色自动适配——**只要用 Token就不用单独写 dark: 变体**。
### class 合并用 `cn()`
`src/utils/cn.ts``cn()` = clsx条件+ tailwind-merge冲突后写覆盖前写`px-2 px-4 → px-4`)。有条件 class 或动态拼接时用它,别手写字符串拼接。
## 架构(需要跨文件理解的)
**技术栈**Vue 3 `<script setup>` + Vite 6 + Tailwind v4CSS-first `@theme`+ TS strict + Pinia + Vue Router 4 + markdown-it + lucide-vue-next。`@` 别名 → `src/`
### 数据层是完全解耦的(核心设计)
页面不直接读数据文件,而是通过 `src/composables/useArticles.ts`:它把 `chanlunLessons``data/chanlun.ts`)和 `essays``data/essays.ts`)合并,提供 `chanlun / essaysList / latest / featured / find() / neighbors() / search()`
- 接入真实抓取数据时:只改数据源(替换 `data/*.ts`)或把 `useArticles.ts` 内的静态数组改成异步请求,**页面和组件无需改动**。
- 文章正文是 **markdown 字符串**`Article.content`,见 `types/article.ts`)。抓取的 HTML 入库时转 markdown或扩展 `useMarkdown.ts` 直接渲染 HTML。
### 文章正文排版 = `.prose-chan`(不要手写)
正文区一律挂 `prose-chan` 类(定义在 `style.css``@layer components`),它已处理 h2/h3/p/blockquote/code/table/列表等全部排版。字号/字体不写死,而是通过 `data-size``sm|base|lg|xl`)和 `data-font``serif|sans`)属性驱动,值来自 reading store。
### 两个 Pinia store 驱动全局体验
- `stores/theme.ts``light | dark | system`,持久化到 `localStorage['chan-theme']`,靠给 `<html>``.dark` 生效。
- `stores/reading.ts`:字号 / 字体 / 专注模式,分别持久化。
- **防闪烁FOUC**`index.html` 里有段内联脚本在 Vue 挂载前同步读 `chan-theme``.dark`。改主题存储 key 时,`index.html` 脚本和 `stores/theme.ts` 必须**同步改**,否则首屏会闪。
### 路由与布局
5 个 view两种 layout
- `DefaultLayout``/`):顶栏 + 侧栏 + 内容 + 页脚,包 home / chanlun / articles / about。
- `ReaderLayout``/read/:category/:slug`):沉浸阅读,含阅读进度、阅读设置、上下篇导航。
- markdown 的 h2/h3 会被 `useMarkdown.ts` 注入 `id`slug 来自 `utils/slug.ts`),便于锚点跳转。
### 现存组件缺标记类名
`components/ui/`BaseButton/Badge/Card/SearchInput`components/layout/`AppHeader/AppSidebar/AppFooter`ArticleCard` 等目前是纯工具类。改动它们时按上面的「标记类名」约定补齐。
## 其他约定
- TS strict 且开了 `noUnusedLocals` / `noUnusedParameters`**未用的 import / 变量会直接让 `pnpm build` 失败**,删代码时记得清干净。
- `<script setup lang="ts">` + Composition API。
- 图标:默认用 `lucide-vue-next`Vue 组件,按需 tree-shake。另装了 **Remix Icon**webfont补 lucide 缺的图标,品牌 Logo 即用 `ri-line-chart-line`
- CSS 已在 `main.ts` 全局引入 `remixicon/fonts/remixicon.css`,直接用 `<i class="ri-xxx-line" aria-hidden="true"></i>`
- webfont 字号靠 `text-*`font-size 驱动,不用 `size-*`);颜色继承 `currentColor`,所以放在 `text-white` 的容器里就是白色。
- 图标名查 https://remixicon.comv4.9,无 candlestick走势/图表类可用 `ri-line-chart-line` / `ri-bar-chart-line` / `ri-stock-line` / `ri-funds-line`)。
- `verbatimModuleSyntax: true`:类型 import 必须写 `import type { ... }`