mdk-skills 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/.install.log +4 -0
- package/.claude/settings.json +64 -0
- package/.claude/settings.local.json +7 -0
- package/.claude/skills/agentation/.meta.json +6 -0
- package/.claude/skills/agentation/SKILL.md +107 -0
- package/.claude/skills/fe-biz-patterns/.meta.json +6 -0
- package/.claude/skills/fe-biz-patterns/SKILL.md +26 -0
- package/.claude/skills/fe-biz-patterns/references/infinite-scroll.md +292 -0
- package/.claude/skills/fe-biz-patterns/references/pinia-store.md +174 -0
- package/.claude/skills/fe-biz-patterns/references/service-layer.md +198 -0
- package/.claude/skills/fe-biz-patterns/references/tab-anchor.md +1125 -0
- package/.claude/skills/fe-biz-patterns/references/use-loading.md +114 -0
- package/.claude/skills/frontend-code-review/.meta.json +6 -0
- package/.claude/skills/frontend-code-review/SKILL.md +167 -0
- package/.claude/skills/frontend-code-review/references/checklist.md +298 -0
- package/.claude/skills/frontend-design/.meta.json +6 -0
- package/.claude/skills/frontend-design/LICENSE.txt +177 -0
- package/.claude/skills/frontend-design/SKILL.md +42 -0
- package/.claude/skills/moai-framework-electron/.meta.json +6 -0
- package/.claude/skills/moai-framework-electron/SKILL.md +328 -0
- package/.claude/skills/skill-creator/.meta.json +6 -0
- package/.claude/skills/skill-creator/SKILL.md +356 -0
- package/.claude/skills/skill-creator/references/output-patterns.md +82 -0
- package/.claude/skills/skill-creator/references/workflows.md +28 -0
- package/.claude/skills/skill-creator/scripts/init_skill.py +303 -0
- package/.claude/skills/skill-creator/scripts/package_skill.py +110 -0
- package/.claude/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/.claude/skills/ui-ux-pro-max/.meta.json +6 -0
- package/.claude/skills/ui-ux-pro-max/SKILL.md +228 -0
- package/.claude/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/.claude/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/.claude/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/.claude/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/.claude/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.claude/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/.claude/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/.claude/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.claude/skills/ui-ux-pro-max/scripts/core.py +238 -0
- package/.claude/skills/ui-ux-pro-max/scripts/search.py +61 -0
- package/.claude/skills/vue/.meta.json +6 -0
- package/.claude/skills/vue/SKILL.md +103 -0
- package/.claude/skills/vue/references/components.md +323 -0
- package/.claude/skills/vue/references/composables.md +358 -0
- package/.claude/skills/vue/references/directives.md +225 -0
- package/.claude/skills/vue/references/gotchas.md +438 -0
- package/.claude/skills/vue/references/provide-inject.md +174 -0
- package/.claude/skills/vue/references/reactivity.md +289 -0
- package/.claude/skills/vue/references/router.md +181 -0
- package/.claude/skills/vue/references/testing.md +294 -0
- package/.claude/skills/vue/references/typescript.md +172 -0
- package/.claude/skills/vue/references/utils-client.md +156 -0
- package/CLAUDE.md +131 -0
- package/package.json +23 -0
- package/scripts/cli.js +260 -0
- package/scripts/copy-skills.js +86 -0
- package/scripts/core.js +256 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Service 层封装方案
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
基于 axios 的请求层封装,核心模式:
|
|
6
|
+
|
|
7
|
+
1. **Request 类 + 单例** — 封装 axios 实例,统一配置和拦截器
|
|
8
|
+
2. **按业务域拆分模块** — `modules/[domain].ts`,类型与函数共置
|
|
9
|
+
3. **config 集中管理** — baseURL、超时、状态码映射统一维护
|
|
10
|
+
|
|
11
|
+
## 目录结构
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
src/service/
|
|
15
|
+
index.ts -- 统一导出
|
|
16
|
+
request/
|
|
17
|
+
config.ts -- 配置集中管理
|
|
18
|
+
index.ts -- Request 类(axios 封装)
|
|
19
|
+
modules/
|
|
20
|
+
home.ts -- 首页 API
|
|
21
|
+
city.ts -- 城市 API
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Request 类封装
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
class Request {
|
|
28
|
+
private instance: AxiosInstance
|
|
29
|
+
|
|
30
|
+
constructor() {
|
|
31
|
+
this.instance = axios.create({
|
|
32
|
+
baseURL: config.baseURL,
|
|
33
|
+
timeout: config.timeout,
|
|
34
|
+
headers: config.headers,
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public get<T>(url, params?, options?): Promise<T>
|
|
39
|
+
public post<T>(url, data?, options?): Promise<T>
|
|
40
|
+
public put<T>(url, data?, options?): Promise<T>
|
|
41
|
+
public delete<T>(url, params?, options?): Promise<T>
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const request = new Request()
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
关键设计点:
|
|
48
|
+
|
|
49
|
+
- **单例模式**:整个应用共享一个 Request 实例,避免重复创建
|
|
50
|
+
- **泛型方法**:`get<T>` 返回 `Promise<T>`,调用方通过类型参数控制返回值类型
|
|
51
|
+
- **RequestOptions**:扩展 `AxiosRequestConfig`,预留 `showLoading`、`showError` 等业务字段
|
|
52
|
+
|
|
53
|
+
## 拦截器(可选启用)
|
|
54
|
+
|
|
55
|
+
拦截器默认不激活,需要时显式调用 `request.enableInterceptors()`:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
class Request {
|
|
59
|
+
/** 启用拦截器:token 注入 + 统一错误处理 */
|
|
60
|
+
enableInterceptors() {
|
|
61
|
+
// 请求拦截器:自动注入 token
|
|
62
|
+
this.instance.interceptors.request.use((config) => {
|
|
63
|
+
const token = localStorage.getItem('token')
|
|
64
|
+
if (token) {
|
|
65
|
+
config.headers.Authorization = `Bearer ${token}`
|
|
66
|
+
}
|
|
67
|
+
return config
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
// 响应拦截器:解包数据 + 统一错误提示
|
|
71
|
+
this.instance.interceptors.response.use(
|
|
72
|
+
(response) => {
|
|
73
|
+
const { code, message, data } = response.data
|
|
74
|
+
if (code === 0) return data // 成功:直接返回业务数据
|
|
75
|
+
console.error('请求失败:', message)
|
|
76
|
+
return Promise.reject(new Error(message))
|
|
77
|
+
},
|
|
78
|
+
(error) => {
|
|
79
|
+
if (error.response) {
|
|
80
|
+
console.error(statusCodeMap[error.response.status] || '网络请求失败')
|
|
81
|
+
} else {
|
|
82
|
+
console.error('网络连接失败')
|
|
83
|
+
}
|
|
84
|
+
return Promise.reject(error)
|
|
85
|
+
},
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
启用后,API 函数的写法会简化——不再需要手动解 `res.data`,因为响应拦截器已经解了一层。
|
|
92
|
+
|
|
93
|
+
## Config 集中管理
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
// src/service/request/config.ts
|
|
97
|
+
export interface RequestConfig {
|
|
98
|
+
baseURL: string
|
|
99
|
+
timeout: number
|
|
100
|
+
headers?: Record<string, string>
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const config: RequestConfig = {
|
|
104
|
+
baseURL: 'http://xxx/api',
|
|
105
|
+
timeout: 10000,
|
|
106
|
+
headers: { 'Content-Type': 'application/json' },
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export const statusCodeMap: Record<number, string> = {
|
|
110
|
+
400: '请求参数错误',
|
|
111
|
+
401: '未授权,请登录',
|
|
112
|
+
403: '拒绝访问',
|
|
113
|
+
404: '请求地址不存在',
|
|
114
|
+
500: '服务器内部错误',
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
多 API 源时,在 config 中添加对应配置对象,Request 类中用单独 instance 隔离:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
export const mapConfig = {
|
|
122
|
+
baseURL: '/api/map',
|
|
123
|
+
key: 'xxx',
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// request/index.ts
|
|
127
|
+
class Request {
|
|
128
|
+
private mapInstance: AxiosInstance | null = null
|
|
129
|
+
|
|
130
|
+
public mapGet<T>(url, params?): Promise<T> {
|
|
131
|
+
if (!this.mapInstance) {
|
|
132
|
+
this.mapInstance = axios.create({ baseURL: mapConfig.baseURL, timeout: config.timeout })
|
|
133
|
+
}
|
|
134
|
+
return this.mapInstance.get(url, { params })
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## API 模块组织
|
|
140
|
+
|
|
141
|
+
### 按业务域拆分
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
// src/service/modules/home.ts
|
|
145
|
+
import { request } from '../request'
|
|
146
|
+
|
|
147
|
+
// 类型定义与 API 函数共置
|
|
148
|
+
export interface HouseListItem { /* ... */ }
|
|
149
|
+
|
|
150
|
+
export const getHotSuggests = async () => {
|
|
151
|
+
const res = await request.get('/home/hotSuggests')
|
|
152
|
+
return res.data
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export const getHouseList = async (page = 1) => {
|
|
156
|
+
const res = await request.get('/home/houselist', { page })
|
|
157
|
+
return res.data
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 规则
|
|
162
|
+
|
|
163
|
+
| 原则 | 说明 |
|
|
164
|
+
|------|------|
|
|
165
|
+
| 一域一文件 | 每个业务模块一个文件,命名与后端资源对应 |
|
|
166
|
+
| 类型共置 | 接口响应类型定义在 API 函数同一文件,就近维护 |
|
|
167
|
+
| 函数即接口 | 每个 API 导出一个 async 函数,参数即业务参数 |
|
|
168
|
+
| 统一导出 | `service/index.ts` 只导出 request 实例和核心类型,modules 由消费方按需 import |
|
|
169
|
+
|
|
170
|
+
## View 层消费方式
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
import { getHotSuggests } from '@/service/modules/home'
|
|
174
|
+
|
|
175
|
+
onMounted(async () => {
|
|
176
|
+
const res = await getHotSuggests()
|
|
177
|
+
hotSuggests.value = res.data || []
|
|
178
|
+
})
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
或通过 store 间接调用:
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
// store 中调用 service
|
|
185
|
+
const fetchHotSuggests = async () => {
|
|
186
|
+
const res = await getHotSuggests()
|
|
187
|
+
hotSuggests.value = res.data || []
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// view 中调用 store action
|
|
191
|
+
onMounted(() => store.fetchHotSuggests())
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## 注意事项
|
|
195
|
+
|
|
196
|
+
1. **拦截器启用时机**:`enableInterceptors()` 应在应用初始化时(如 `main.ts`)调用一次,避免重复注册
|
|
197
|
+
2. **响应拦截器副作用**:启用后 API 函数返回的是解包后的业务数据,而非完整 AxiosResponse,与之配套的 store 逻辑需要同步调整
|
|
198
|
+
3. **泛型参数**:`request.get<T>` 的 `T` 只是类型标注,不会在运行时做校验,后端返回格式异常仍需前端容错
|