- Debian-based api image (bookworm-slim), docker/debian mirrors, prisma binaryTargets for openssl 3.0 - nginx: admin SPA under /admin, TLS via acme.sh (ZeroSSL) + auto-renewal cron, http->https redirect - prisma: add origin_goods.delisted migration, sync missing schema (good_image/tag_font_color/good_tags), fix users.createdAt Timestamptz - api: CORS wildcard reflection, helmet CORP cross-origin, price backfill in persistProductDetail, categoryIcon ancestor fallback, mediaByColor per-color gallery in public goods detail - admin: /admin base path (vite + router) - import-data.mjs: udt_name casting, serial sequence advance fix
194 lines
6.9 KiB
Markdown
194 lines
6.9 KiB
Markdown
# AGENTS.md - AI Agent 开发规范
|
||
|
||
## 项目概述
|
||
|
||
InkReach 官网项目,基于 Nuxt 4 + Vue 3 + Tailwind CSS v4 的静态展示站点。
|
||
|
||
## 开发流程
|
||
|
||
- 包管理器:`npm`
|
||
- TypeScript strict 模式,所有代码必须通过类型检查
|
||
- 页面与组件代码放在 `app/` 目录下,符合 Nuxt 约定
|
||
|
||
### 1. 梳理需求
|
||
|
||
开发前确定好需求类型,在对应的 `plans/` 子目录下创建计划文档:
|
||
|
||
| 需求类型 | 计划目录 | 命名规则 | 示例 |
|
||
| -------- | ----------------- | --------------------- | ----------------------- |
|
||
| 新功能 | `plans/feature/` | `xxx-xxx-feature.md` | `hero-banner-feature.md` |
|
||
| 修 Bug | `plans/fix/` | `xxx-xxx-fix.md` | `layout-overflow-fix.md` |
|
||
| 重构 | `plans/refactor/` | `xxx-xxx-refactor.md` | `component-split-refactor.md` |
|
||
|
||
计划文档最末尾是开发任务表,每个任务项都有一个对应的二级标题的任务详情描述;当需求完成时任务项也标记勾选了。
|
||
|
||
### 2. 建立开发分支
|
||
|
||
使用 `enterprise-git-spec` 技能来建立分支。分支命名:
|
||
|
||
- 新功能:`feature/xxx-xxx`
|
||
- 修 Bug:`bugfix/xxx-xxx`
|
||
- 重构:`refactor/xxx-xxx`
|
||
|
||
### 3. 按照需求开发
|
||
|
||
按照计划文档的任务项逐步实现功能。
|
||
|
||
**重要原则:所有测试必须通过**
|
||
|
||
- 开发过程中,确保所有测试用例通过
|
||
- 如果发现现有测试失败,必须立即修复
|
||
- 只有在所有测试都通过的情况下,才能认为开发完成
|
||
|
||
### 4. 合并到开发分支
|
||
|
||
所有测试通过后,使用 `enterprise-git-spec` 技能提交分支,然后合并回 `develop` 分支。
|
||
|
||
### 5. 沉淀开发经验
|
||
|
||
实现功能过程中,将通用的编码好想法、好思想、注意点等及时追加到本文件中。
|
||
|
||
### 6. 更新项目结构文档
|
||
|
||
每次功能开发完成后,更新 `docs/references/structs.md` 文件,记录项目目录结构和模块功能描述。
|
||
|
||
### 7. 更新使用文档
|
||
|
||
1. `README.md` - 快速上手,新功能开发完成后更新
|
||
2. `docs/references/*` - 详细使用指南,每次功能变更后更新
|
||
3. `skills/inkreach-official-website/SKILL.md` - AI Agent 使用文档
|
||
|
||
## 技术栈
|
||
|
||
| 技术 | 版本 | 用途 |
|
||
| --------------- | ----- | -------------- |
|
||
| Nuxt | 4.x | SSR/SSG 框架 |
|
||
| Vue | 3.x | UI 框架 |
|
||
| Tailwind CSS | 4.x | 原子化 CSS |
|
||
| @nuxtjs/seo | 5.x | SEO 模块 |
|
||
| FontAwesome | 7.x | 图标库 |
|
||
|
||
## 开发规范
|
||
|
||
### Vue / Nuxt 规范
|
||
|
||
- 使用 `<script setup>` + Composition API + TypeScript
|
||
- 组件文件命名:PascalCase(如 `ProductCard.vue`)
|
||
- 页面放在 `app/pages/`,组件放在 `app/components/`
|
||
- 布局放在 `app/layouts/`
|
||
- 使用 Nuxt 自动导入,无需手动 import 组件和 composables
|
||
|
||
### 代码风格
|
||
|
||
- 缩进:2 空格
|
||
- 分号:必须
|
||
- 引号:单引号
|
||
- 行宽:100 字符
|
||
- 末尾逗号:es5
|
||
|
||
### TypeScript 规范
|
||
|
||
- 所有函数必须声明参数和返回值类型
|
||
- 优先使用 `interface`,交叉类型时用 `type`
|
||
- 避免使用 `any`,必须使用时用 `unknown` 替代
|
||
|
||
### Tailwind CSS 规范
|
||
|
||
- 自定义主题颜色在 `app/assets/css/tailwind.css` 的 `@theme` 中定义
|
||
- 自定义动画也在 `@theme` 中通过 `--animate-*` 和 `@keyframes` 注册
|
||
- 优先使用 Tailwind 工具类,必要时使用 `@apply` 或 `[任意值]` 语法
|
||
|
||
### 现有主题色
|
||
|
||
| 变量名 | 色值 | 用途 |
|
||
| --------------------------- | -------- | ------------ |
|
||
| `--color-primary` | `#fd6a03` | 主色调 |
|
||
| `--color-inkreach-homepage-1` | `#f3f4f5` | 浅灰背景 |
|
||
| `--color-inkreach-homepage-2` | `#f8f9fb` | 次浅灰背景 |
|
||
| `--color-inkreach-homepage-3` | `#fff6f0` | 暖色浅背景 |
|
||
| `--color-inkreach-homepage-4` | `#FF6800` | 橙色强调 |
|
||
| `--color-inkreach-homepage-5` | `#0C0501` | 深色/页脚 |
|
||
|
||
### 常用命令
|
||
|
||
```bash
|
||
npm run dev # 开发模式(nuxt dev --host)
|
||
npm run build # 构建(nuxt build)
|
||
npm run generate # 静态站点生成(nuxt generate)
|
||
npm run preview # 预览构建产物
|
||
```
|
||
|
||
## 经验沉淀
|
||
|
||
### 启用 Nuxt 文件式路由
|
||
|
||
项目原先用 `app/app.vue` 作为整页入口。要新增独立路由页(如 `/product-center`):
|
||
|
||
1. 把 `app/app.vue` 现有内容迁移到 `app/pages/index.vue`(保持 `/` 渲染原首页)。
|
||
2. 将 `app/app.vue` 替换为最小容器:
|
||
|
||
```vue
|
||
<template>
|
||
<NuxtPage />
|
||
</template>
|
||
```
|
||
|
||
3. 新建 `app/pages/<name>.vue` 即可通过 `/<name>` 访问。
|
||
|
||
### Nitro 后端代理模式
|
||
|
||
若要把外部 HTTP API(如 NestJS 后端)包装为同源 `/api/*` 路由:
|
||
|
||
```typescript
|
||
// server/api/backend/categories.get.ts
|
||
export default defineCachedEventHandler(
|
||
async (event) => {
|
||
const config = useRuntimeConfig();
|
||
return $fetch(`${config.public.backendUrl}/public/categories`);
|
||
},
|
||
{
|
||
maxAge: 60,
|
||
swr: true,
|
||
name: 'backend-categories',
|
||
getKey: () => 'tree',
|
||
},
|
||
);
|
||
```
|
||
|
||
`runtimeConfig.public.backendUrl` 通过 `.env` 的 `NUXT_PUBLIC_BACKEND_URL` 注入,可被前端直接 `$fetch('/api/backend/...')` 调用且保持 SSR 工作。
|
||
|
||
注意:带 query 的列表接口(如 goods)需在 `getKey` 中将 `getQuery(event)` JSON 序列化作为缓存键,避免不同筛选条件互相污染。
|
||
|
||
### 后端响应包络
|
||
|
||
NestJS 全局 `TransformInterceptor` 把所有响应包成 `{ data: T, success: true }`。前端 `$fetch` 必须读取 `response.data`,类型定义也要带 `BackendEnvelope<T>` 包装层。
|
||
|
||
### `defineModel` 用于组件 v-model
|
||
|
||
Nuxt 4 内置 `defineModel` 支持双向绑定,比手写 `modelValue`/`update:modelValue` props+emit 更简洁:
|
||
|
||
```typescript
|
||
const keyword = defineModel<string>('keyword', { default: '' });
|
||
const emit = defineEmits<{ search: [] }>();
|
||
```
|
||
|
||
父组件用法:`<ProductFilterBar v-model:keyword="searchKeyword" @search="onSearch" />`
|
||
|
||
### SSR 期间 watch query 触发请求
|
||
|
||
在 `<script setup>` 中用 `await loadFilters()` 等顶层 await 时,Nuxt 会等待 Promise 解析才渲染首屏 HTML;之后用 `watch(() => [query.countryId, ...], fetchProducts)` 监听筛选条件变化,重新拉取数据。Top-level await 在 Nuxt 中是合法的(会变为异步 setup)。
|
||
|
||
### `npm install` 与 `node_modules`
|
||
|
||
首次 clone 项目后必须 `npm install` 安装依赖(项目使用 `package-lock.json`),否则 `node_modules` 为空。`npm install` 会自动触发 `postinstall: nuxt prepare` 生成 `.nuxt/` 类型与组件清单。
|
||
|
||
### 类型检查
|
||
|
||
项目使用 Nuxt 4 默认的 TS 配置(`.nuxt/tsconfig.app.json` 等)。运行类型检查:
|
||
|
||
```bash
|
||
npx vue-tsc --noEmit -p ./.nuxt/tsconfig.app.json
|
||
```
|
||
|
||
退出码 0 表示无类型错误,可作为合并前的本地验证步骤。
|