初始化

This commit is contained in:
谢宇宁
2026-09-15 15:25:05 +07:00
commit 77c16ab4a2
1310 changed files with 132250 additions and 0 deletions
@@ -0,0 +1,148 @@
# 参考模板
## 1) Service 方法模板
```ts
import request from '@/utils/request';
export interface QueryListParams {
pageNumber: number;
pageSize: number;
mediaId?: string;
}
export interface QueryListResp {
list: Array<{
id: string;
title: string;
}>;
total: number;
}
export default class ExampleApi {
static queryList(params: QueryListParams): Promise<QueryListResp> {
return request.get('/example/list', params);
}
}
```
## 2) Hook 模板(单一职责)
```ts
import { reactive } from 'vue';
import ExampleApi, { QueryListParams } from '@/service/example';
export function useExampleList(initialParams: QueryListParams) {
const state = reactive({
loading: false,
error: false,
list: [] as Array<{ id: string; title: string }>,
total: 0,
});
const fetchList = async (params = initialParams) => {
state.loading = true;
state.error = false;
try {
const res = await ExampleApi.queryList(params);
state.list = res.list || [];
state.total = Number(res.total || 0);
} catch (err) {
state.error = true;
state.list = [];
state.total = 0;
} finally {
state.loading = false;
}
};
return {
state,
fetchList,
};
}
```
## 3) 容器页模板(Container View
```vue
<script setup lang="ts">
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import { useExampleList } from './hooks/useExampleList';
const route = useRoute();
const mediaId = computed(() => String(route.query.id || ''));
const { state, fetchList } = useExampleList({
pageNumber: 1,
pageSize: 30,
mediaId: mediaId.value,
});
fetchList();
</script>
```
## 4) 错误处理最低检查项
- 每个异步动作都具备成对的 loading 开关。
- 请求失败时会落到确定性兜底状态。
- 接口细节与类型由 service 层承载。
- UI 层能展示空态/错误态,不允许静默失败。
## 5) 旧代码 any 的渐进迁移模式
```ts
// 改造前
// static getMediaHot(data: any) {
// return request.get('/media/hot', data);
// }
// 改造后(增量迁移)
export interface GetMediaHotParams {
pageNumber: number;
pageSize: number;
moduleId?: string;
}
export interface GetMediaHotResp {
list: Types.Acg.MediaContentListItem[];
total: number;
}
static getMediaHot(data: GetMediaHotParams): Promise<GetMediaHotResp> {
return request.get('/media/hot', data);
}
```
## 6) PR 自检输出模板
在实现说明中必须附上以下区块(与 `SKILL.md` 保持一致):
```markdown
### 自检结果
- [x] view/hook 层没有直接请求调用
- [x] service 边界方法具备明确类型
- [x] 未新增宽泛 any
- [x] 异步失败分支具备兜底状态
- [x] 混杂职责已拆分为聚焦 hooks/components
```
## 7) 轻量自动校验命令(可执行)
在仓库根目录执行以下命令进行快速自检:
```bash
# 1) 优先检查本次改动的 view/hook 文件是否直接调用 request
rg "request\\.(get|post|put|delete|deletes)\\(" <changed-view-or-hook-files>
# 2) 检查本次改动文件是否引入 any(人工结合 diff 判断)
rg "\\bany\\b" <changed-files>
```
判定规则:
- 命令 1 预期为“无结果”;有结果则说明可能绕过 service。
- 命令 2 不要求仓库清零,但本次改动不应新增宽泛 `any`
- 只有在做全仓治理或用户明确要求时,才扩展到 `src/views src/hooks src/service` 全量扫描。