@robot-admin/request-core 0.1.2 → 0.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/README.md +297 -311
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,426 +1,412 @@
|
|
|
1
1
|
# @robot-admin/request-core
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 为 Vue 3 打造的企业级请求解决方案:Axios 增强 + 7 大插件 + CRUD Composable
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@robot-admin/request-core)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
|
-
**[English](#english) | [中文文档](#中文文档)**
|
|
9
|
-
|
|
10
8
|
---
|
|
11
9
|
|
|
12
|
-
##
|
|
13
|
-
|
|
14
|
-
### ✨ 核心功能
|
|
15
|
-
|
|
16
|
-
#### 1. Axios 封装(7 个内置插件)
|
|
10
|
+
## ✨ 核心特性
|
|
17
11
|
|
|
18
|
-
-
|
|
19
|
-
- **
|
|
20
|
-
- **
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- **
|
|
24
|
-
- **reLogin**: 重新登录管理(Promise 队列)
|
|
12
|
+
- 🚀 **开箱即用**:3 步接入,5 分钟实现完整 CRUD
|
|
13
|
+
- 🔌 **7 大插件**:缓存、重试、去重、取消、reLogin 等开箱即用
|
|
14
|
+
- 📊 **useTableCrud**:配置式表格 CRUD,自动处理分页/搜索/增删改查
|
|
15
|
+
- 🎯 **智能适配**:自动兼容不同后端响应格式(字段名、成功码)
|
|
16
|
+
- 💪 **类型安全**:完整 TypeScript 支持
|
|
17
|
+
- 🎨 **Naive UI 集成**:深度集成 Naive UI 组件
|
|
25
18
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- 配置驱动的表格 CRUD 解决方案
|
|
29
|
-
- 支持分页、搜索、排序、自定义操作
|
|
30
|
-
- 内置详情查看、编辑、删除等功能
|
|
19
|
+
---
|
|
31
20
|
|
|
32
|
-
|
|
21
|
+
## 📦 安装
|
|
33
22
|
|
|
34
23
|
```bash
|
|
35
24
|
npm install @robot-admin/request-core
|
|
36
25
|
# 或
|
|
37
26
|
bun add @robot-admin/request-core
|
|
38
|
-
# 或
|
|
39
|
-
pnpm add @robot-admin/request-core
|
|
40
27
|
```
|
|
41
28
|
|
|
42
|
-
|
|
29
|
+
**Peer Dependencies**: `vue@^3.4.0`, `naive-ui@^2.38.0`
|
|
43
30
|
|
|
44
|
-
|
|
31
|
+
---
|
|
45
32
|
|
|
46
|
-
|
|
47
|
-
// main.ts
|
|
48
|
-
import { createApp } from "vue";
|
|
49
|
-
import { createRequestCore, onReLoginSuccess } from "@robot-admin/request-core";
|
|
50
|
-
import { useUserStore } from "@/stores/user";
|
|
33
|
+
## 🚀 30 秒快速上手
|
|
51
34
|
|
|
52
|
-
|
|
35
|
+
### 1️⃣ 初始化(main.ts)
|
|
53
36
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
timeout: 10000,
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
// 🎯 配置成功状态码(适配不同后端约定)
|
|
61
|
-
// 默认: [200, 0, '200', '0']
|
|
62
|
-
// successCodes: [1, '1', 'success'], // 示例:自定义成功码
|
|
37
|
+
```ts
|
|
38
|
+
import { createApp } from 'vue'
|
|
39
|
+
import { createRequestCore } from '@robot-admin/request-core'
|
|
63
40
|
|
|
64
|
-
|
|
65
|
-
// fieldAliases: {
|
|
66
|
-
// data: ['data', 'result', 'payload'], // 数据层字段
|
|
67
|
-
// list: ['list', 'items', 'records'], // 列表字段
|
|
68
|
-
// total: ['total', 'totalCount', 'count'], // 总数字段
|
|
69
|
-
// },
|
|
41
|
+
const app = createApp(App)
|
|
70
42
|
|
|
43
|
+
app.use(createRequestCore({
|
|
44
|
+
request: { baseURL: '/api', timeout: 10000 },
|
|
71
45
|
interceptors: {
|
|
72
|
-
// 请求拦截:注入 token
|
|
73
46
|
request: (config) => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
// 响应拦截:处理业务码
|
|
81
|
-
response: (response) => {
|
|
82
|
-
const { code, message } = response.data;
|
|
83
|
-
if (code !== 200) {
|
|
84
|
-
window.$message?.error(message || "请求失败");
|
|
85
|
-
return Promise.reject(new Error(message));
|
|
86
|
-
}
|
|
87
|
-
return response;
|
|
88
|
-
},
|
|
89
|
-
// 响应错误拦截:处理 401
|
|
90
|
-
responseError: async (error) => {
|
|
91
|
-
if (error.response?.status === 401) {
|
|
92
|
-
const userStore = useUserStore();
|
|
93
|
-
await userStore.reLogin();
|
|
94
|
-
onReLoginSuccess(); // 通知所有等待的请求继续
|
|
95
|
-
return Promise.reject(error);
|
|
96
|
-
}
|
|
97
|
-
return Promise.reject(error);
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
});
|
|
47
|
+
config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`
|
|
48
|
+
return config
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}))
|
|
52
|
+
```
|
|
101
53
|
|
|
102
|
-
|
|
54
|
+
### 2️⃣ 使用 CRUD(任意组件)
|
|
55
|
+
|
|
56
|
+
```vue
|
|
57
|
+
<script setup lang="ts">
|
|
58
|
+
import { useTableCrud } from '@robot-admin/request-core'
|
|
59
|
+
|
|
60
|
+
const table = useTableCrud({
|
|
61
|
+
api: { list: '/users', get: '/users/:id', create: '/users', update: '/users/:id', remove: '/users/:id' },
|
|
62
|
+
columns: [
|
|
63
|
+
{ key: 'id', title: 'ID' },
|
|
64
|
+
{ key: 'name', title: '姓名' },
|
|
65
|
+
{ key: 'email', title: '邮箱' }
|
|
66
|
+
]
|
|
67
|
+
})
|
|
68
|
+
</script>
|
|
69
|
+
|
|
70
|
+
<template>
|
|
71
|
+
<n-data-table :data="table.data.value" :columns="table.columns.value" :loading="table.loading.value" />
|
|
72
|
+
</template>
|
|
103
73
|
```
|
|
104
74
|
|
|
105
|
-
|
|
75
|
+
✅ **完成!** 一个完整的带分页、搜索、编辑、删除的数据表格!
|
|
106
76
|
|
|
107
|
-
|
|
77
|
+
---
|
|
108
78
|
|
|
109
|
-
|
|
79
|
+
## 📚 核心 API
|
|
80
|
+
|
|
81
|
+
### 请求方法
|
|
82
|
+
|
|
83
|
+
| 方法 | 说明 | 示例 |
|
|
84
|
+
|------|------|------|
|
|
85
|
+
| `getData(url, config?)` | GET 请求 | `getData('/users')` |
|
|
86
|
+
| `postData(url, data, config?)` | POST 请求 | `postData('/users', { name: '张三' })` |
|
|
87
|
+
| `putData(url, data, config?)` | PUT 请求 | `putData('/users/1', { name: '李四' })` |
|
|
88
|
+
| `deleteData(url, config?)` | DELETE 请求 | `deleteData('/users/1')` |
|
|
89
|
+
|
|
90
|
+
### useTableCrud 配置
|
|
91
|
+
|
|
92
|
+
| 属性 | 类型 | 必填 | 说明 |
|
|
93
|
+
|------|------|------|------|
|
|
94
|
+
| `api.list` | `string` | ✅ | 列表接口 |
|
|
95
|
+
| `api.get` | `string` | - | 详情接口(支持 `:id`) |
|
|
96
|
+
| `api.create` | `string` | - | 创建接口 |
|
|
97
|
+
| `api.update` | `string` | - | 更新接口(支持 `:id`) |
|
|
98
|
+
| `api.remove` | `string` | - | 删除接口(支持 `:id`) |
|
|
99
|
+
| `columns` | `TableColumn[]` | ✅ | 表格列配置 |
|
|
100
|
+
| `customActions` | `CustomAction[]` | - | 自定义操作按钮 |
|
|
101
|
+
| `idKey` | `string` | - | ID 字段名(默认 `'id'`) |
|
|
102
|
+
| `defaultPageSize` | `number` | - | 每页条数(默认 `10`) |
|
|
103
|
+
| `autoLoad` | `boolean` | - | 自动加载(默认 `true`) |
|
|
104
|
+
|
|
105
|
+
### useTableCrud 返回值
|
|
106
|
+
|
|
107
|
+
| 属性/方法 | 类型 | 说明 |
|
|
108
|
+
|-----------|------|------|
|
|
109
|
+
| `data` | `Ref<T[]>` | 表格数据 |
|
|
110
|
+
| `loading` | `Ref<boolean>` | 加载状态 |
|
|
111
|
+
| `total` | `Ref<number>` | 总条数 |
|
|
112
|
+
| `pagination` | `object` | 分页配置(Naive UI 格式) |
|
|
113
|
+
| `columns` | `Ref<DataTableColumn[]>` | 表格列(含操作列) |
|
|
114
|
+
| `search()` | `() => Promise<void>` | 搜索 |
|
|
115
|
+
| `resetSearch()` | `() => void` | 重置搜索 |
|
|
116
|
+
| `refresh()` | `() => Promise<void>` | 刷新数据 |
|
|
117
|
+
| `viewDetail(row)` | `(row: T) => void` | 查看详情 |
|
|
118
|
+
| `handleEdit(row)` | `(row: T) => void` | 编辑 |
|
|
119
|
+
| `handleDelete(row)` | `(row: T) => void` | 删除 |
|
|
110
120
|
|
|
111
|
-
|
|
112
|
-
const requestCore = createRequestCore({
|
|
113
|
-
request: { baseURL: "/api" },
|
|
121
|
+
---
|
|
114
122
|
|
|
115
|
-
|
|
116
|
-
successCodes: [1, "1", "success"], // 支持数字和字符串
|
|
123
|
+
## 🔌 插件系统
|
|
117
124
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
})
|
|
125
|
+
所有请求方法都支持插件配置:
|
|
126
|
+
|
|
127
|
+
### 缓存插件(仅 GET)
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
getData('/users', {
|
|
131
|
+
cache: {
|
|
132
|
+
enabled: true, // 启用缓存
|
|
133
|
+
ttl: 300000, // 5 分钟过期
|
|
134
|
+
forceUpdate: false // 不强制更新
|
|
135
|
+
}
|
|
136
|
+
})
|
|
130
137
|
```
|
|
131
138
|
|
|
132
|
-
|
|
139
|
+
### 重试插件
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
postData('/submit', data, {
|
|
143
|
+
retry: {
|
|
144
|
+
enabled: true, // 启用重试
|
|
145
|
+
count: 3, // 最多重试 3 次
|
|
146
|
+
delay: 1000, // 重试延迟 1 秒
|
|
147
|
+
exponentialBackoff: true // 指数退避(1s, 2s, 4s)
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
```
|
|
133
151
|
|
|
134
|
-
|
|
152
|
+
### 去重插件
|
|
135
153
|
|
|
136
154
|
```ts
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
// }
|
|
145
|
-
|
|
146
|
-
const requestCore = createRequestCore({
|
|
147
|
-
request: { baseURL: "/api" },
|
|
148
|
-
|
|
149
|
-
// 配置字段别名
|
|
150
|
-
fieldAliases: {
|
|
151
|
-
data: ["result", "data", "payload"], // 数据层字段(按优先级)
|
|
152
|
-
list: ["employees", "items", "list"], // 列表字段(按优先级)
|
|
153
|
-
total: ["totalRecords", "total", "count"], // 总数字段(按优先级)
|
|
154
|
-
},
|
|
155
|
+
getData('/users', {
|
|
156
|
+
dedupe: {
|
|
157
|
+
enabled: true, // 启用去重(默认启用)
|
|
158
|
+
keyGenerator: (config) => `${config.method}-${config.url}` // 自定义去重 key
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
```
|
|
155
162
|
|
|
156
|
-
|
|
157
|
-
});
|
|
163
|
+
### 取消插件
|
|
158
164
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
165
|
+
```ts
|
|
166
|
+
getData('/users', {
|
|
167
|
+
cancel: {
|
|
168
|
+
enabled: true, // 启用自动取消(路由切换时)
|
|
169
|
+
whitelist: [] // 白名单接口(不取消)
|
|
170
|
+
}
|
|
171
|
+
})
|
|
164
172
|
```
|
|
165
173
|
|
|
166
|
-
|
|
174
|
+
### reLogin 插件
|
|
167
175
|
|
|
168
|
-
|
|
176
|
+
自动管理重新登录场景,多个请求等待登录完成后自动重试:
|
|
169
177
|
|
|
170
178
|
```ts
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
// 针对特殊接口的自定义提取逻辑
|
|
176
|
-
extractListData: (response: any) => {
|
|
177
|
-
return {
|
|
178
|
-
items: response.result?.specialList || [],
|
|
179
|
-
total: response.result?.specialCount || 0,
|
|
180
|
-
};
|
|
181
|
-
},
|
|
182
|
-
});
|
|
179
|
+
import { onReLoginSuccess } from '@robot-admin/request-core'
|
|
180
|
+
|
|
181
|
+
// 在登录成功后调用
|
|
182
|
+
onReLoginSuccess() // 通知所有等待的请求继续
|
|
183
183
|
```
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 🎯 完整示例
|
|
188
|
+
|
|
189
|
+
### 场景 1:完整的数据表格(分页 + 搜索 + CRUD)
|
|
186
190
|
|
|
187
191
|
```vue
|
|
188
192
|
<script setup lang="ts">
|
|
189
|
-
import { useTableCrud } from
|
|
193
|
+
import { useTableCrud } from '@robot-admin/request-core'
|
|
190
194
|
|
|
191
|
-
interface
|
|
192
|
-
id: number
|
|
193
|
-
name: string
|
|
194
|
-
|
|
195
|
-
|
|
195
|
+
interface User {
|
|
196
|
+
id: number
|
|
197
|
+
name: string
|
|
198
|
+
email: string
|
|
199
|
+
role: string
|
|
196
200
|
}
|
|
197
201
|
|
|
198
|
-
const table = useTableCrud<
|
|
202
|
+
const table = useTableCrud<User>({
|
|
199
203
|
api: {
|
|
200
|
-
list:
|
|
201
|
-
get:
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
204
|
+
list: '/api/users/list',
|
|
205
|
+
get: '/api/users/:id',
|
|
206
|
+
create: '/api/users',
|
|
207
|
+
update: '/api/users/:id',
|
|
208
|
+
remove: '/api/users/:id'
|
|
205
209
|
},
|
|
206
210
|
columns: [
|
|
207
|
-
{ key:
|
|
208
|
-
{ key:
|
|
209
|
-
{ key:
|
|
210
|
-
{ key:
|
|
211
|
+
{ key: 'id', title: 'ID', width: 80 },
|
|
212
|
+
{ key: 'name', title: '姓名', width: 120 },
|
|
213
|
+
{ key: 'email', title: '邮箱', width: 200 },
|
|
214
|
+
{ key: 'role', title: '角色', width: 100 }
|
|
211
215
|
],
|
|
212
216
|
customActions: [
|
|
213
217
|
{
|
|
214
|
-
key:
|
|
215
|
-
label:
|
|
216
|
-
icon:
|
|
217
|
-
handler: (row, ctx) => {
|
|
218
|
-
|
|
219
|
-
ctx.message.success(
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
]
|
|
223
|
-
})
|
|
218
|
+
key: 'resetPassword',
|
|
219
|
+
label: '重置密码',
|
|
220
|
+
icon: 'mdi:lock-reset',
|
|
221
|
+
handler: async (row, ctx) => {
|
|
222
|
+
await postData(`/api/users/${row.id}/reset-password`, {})
|
|
223
|
+
ctx.message.success('密码已重置')
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
]
|
|
227
|
+
})
|
|
224
228
|
</script>
|
|
225
229
|
|
|
226
230
|
<template>
|
|
227
|
-
<
|
|
231
|
+
<n-space vertical>
|
|
228
232
|
<!-- 搜索栏 -->
|
|
229
233
|
<n-space>
|
|
230
|
-
<n-input
|
|
231
|
-
|
|
232
|
-
placeholder="搜索..."
|
|
233
|
-
/>
|
|
234
|
-
<n-button @click="table.search()">搜索</n-button>
|
|
234
|
+
<n-input v-model:value="table.searchKeyword.value" placeholder="搜索用户..." />
|
|
235
|
+
<n-button type="primary" @click="table.search()">搜索</n-button>
|
|
235
236
|
<n-button @click="table.resetSearch()">重置</n-button>
|
|
237
|
+
<n-button type="success" @click="table.handleCreate()">新增用户</n-button>
|
|
236
238
|
</n-space>
|
|
237
239
|
|
|
238
240
|
<!-- 表格 -->
|
|
239
241
|
<n-data-table
|
|
240
|
-
ref="table.tableRef.value"
|
|
241
242
|
:data="table.data.value"
|
|
242
243
|
:columns="table.columns.value"
|
|
243
244
|
:loading="table.loading.value"
|
|
244
245
|
:pagination="table.pagination"
|
|
245
246
|
/>
|
|
246
|
-
</
|
|
247
|
+
</n-space>
|
|
247
248
|
</template>
|
|
248
249
|
```
|
|
249
250
|
|
|
250
|
-
|
|
251
|
+
### 场景 2:自定义请求(带插件)
|
|
251
252
|
|
|
252
253
|
```ts
|
|
253
|
-
import { getData, postData } from
|
|
254
|
-
|
|
255
|
-
// 1. 开启缓存(5 分钟)
|
|
256
|
-
const users = await getData("/api/users", {
|
|
257
|
-
cache: { enabled: true, ttl: 300000 },
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
// 2. 开启重试(3 次,指数退避)
|
|
261
|
-
const data = await postData(
|
|
262
|
-
"/api/submit",
|
|
263
|
-
{ name: "张三" },
|
|
264
|
-
{
|
|
265
|
-
retry: { enabled: true, count: 3, exponentialBackoff: true },
|
|
266
|
-
},
|
|
267
|
-
);
|
|
254
|
+
import { getData, postData } from '@robot-admin/request-core'
|
|
268
255
|
|
|
269
|
-
//
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
})
|
|
256
|
+
// 带缓存的 GET 请求
|
|
257
|
+
const users = await getData('/api/users', {
|
|
258
|
+
cache: { enabled: true, ttl: 300000 } // 缓存 5 分钟
|
|
259
|
+
})
|
|
273
260
|
|
|
274
|
-
//
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
})
|
|
261
|
+
// 带重试的 POST 请求
|
|
262
|
+
const result = await postData('/api/submit', { data: 'test' }, {
|
|
263
|
+
retry: { enabled: true, count: 3 }
|
|
264
|
+
})
|
|
278
265
|
```
|
|
279
266
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
#### createRequestCore(config)
|
|
283
|
-
|
|
284
|
-
创建 Request Core 实例。
|
|
285
|
-
|
|
286
|
-
**参数:**
|
|
287
|
-
|
|
288
|
-
- `config.request` - Axios 基础配置(baseURL, timeout, headers 等)
|
|
289
|
-
- `config.successCodes` - 成功状态码配置(默认: `[200, 0, '200', '0']`)
|
|
290
|
-
- `config.fieldAliases` - 字段别名配置(用于适配不同的后端响应格式)
|
|
291
|
-
- `data` - 数据层字段别名(默认: `['data', 'list', 'items', 'records']`)
|
|
292
|
-
- `list` - 列表字段别名(默认: `['list', 'items', 'records', 'rows', 'data']`)
|
|
293
|
-
- `total` - 总数字段别名(默认: `['total', 'totalCount', 'count', 'totalElements']`)
|
|
294
|
-
- `config.interceptors` - 拦截器配置
|
|
295
|
-
- `request` - 请求拦截器
|
|
296
|
-
- `requestError` - 请求错误拦截器
|
|
297
|
-
- `response` - 响应拦截器
|
|
298
|
-
- `responseError` - 响应错误拦截器
|
|
299
|
-
|
|
300
|
-
**返回:**
|
|
301
|
-
|
|
302
|
-
- `install(app)` - Vue 插件安装方法
|
|
303
|
-
- `axiosInstance` - Axios 实例
|
|
304
|
-
|
|
305
|
-
#### useTableCrud\<T\>(config)
|
|
306
|
-
|
|
307
|
-
创建表格 CRUD 实例。
|
|
308
|
-
|
|
309
|
-
**参数:**
|
|
310
|
-
|
|
311
|
-
- `api` - API 端点配置(list, get, create, update, remove)
|
|
312
|
-
- `columns` - 表格列配置
|
|
313
|
-
- `customActions` - 自定义操作按钮
|
|
314
|
-
- `idKey` - ID 字段名(默认 'id')
|
|
315
|
-
- `defaultPageSize` - 默认分页大小(默认 10)
|
|
316
|
-
- `autoLoad` - 是否自动加载(默认 true)
|
|
317
|
-
|
|
318
|
-
**返回对象包含:**
|
|
319
|
-
|
|
320
|
-
- `data` - 表格数据
|
|
321
|
-
- `loading` - 加载状态
|
|
322
|
-
- `total` - 总数
|
|
323
|
-
- `pagination` - 分页配置
|
|
324
|
-
- `search()` - 搜索方法
|
|
325
|
-
- `resetSearch()` - 重置搜索
|
|
326
|
-
- `refresh()` - 刷新数据
|
|
327
|
-
- `viewDetail(row)` - 查看详情
|
|
328
|
-
- `handleEdit(row)` - 编辑
|
|
329
|
-
- `handleDelete(row)` - 删除
|
|
267
|
+
---
|
|
330
268
|
|
|
331
|
-
|
|
269
|
+
## ⚙️ 高级配置
|
|
332
270
|
|
|
333
|
-
|
|
271
|
+
### 适配不同后端响应格式
|
|
334
272
|
|
|
335
|
-
|
|
336
|
-
| ---------- | ------------------------------------------------- | ------------------ |
|
|
337
|
-
| **cache** | `enabled`, `ttl`, `forceUpdate` | 请求缓存(仅 GET) |
|
|
338
|
-
| **retry** | `enabled`, `count`, `delay`, `exponentialBackoff` | 请求重试 |
|
|
339
|
-
| **dedupe** | `enabled`, `keyGenerator` | 请求去重 |
|
|
340
|
-
| **cancel** | `enabled`, `whitelist` | 自动取消 |
|
|
273
|
+
#### 1. 自定义成功状态码
|
|
341
274
|
|
|
342
|
-
|
|
275
|
+
如果后端返回的成功码不是 `0` 或 `200`:
|
|
343
276
|
|
|
344
277
|
```ts
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
DetailConfig,
|
|
359
|
-
|
|
360
|
-
// 插件类型
|
|
361
|
-
CacheConfig,
|
|
362
|
-
RetryConfig,
|
|
363
|
-
DedupeConfig,
|
|
364
|
-
CancelConfig,
|
|
365
|
-
};
|
|
278
|
+
createRequestCore({
|
|
279
|
+
request: { baseURL: '/api' },
|
|
280
|
+
successCodes: [1, '1', 'success'], // 自定义成功码
|
|
281
|
+
interceptors: {
|
|
282
|
+
response: (response) => {
|
|
283
|
+
const { code } = response.data
|
|
284
|
+
if (![1, '1', 'success'].includes(code)) {
|
|
285
|
+
throw new Error(response.data.message)
|
|
286
|
+
}
|
|
287
|
+
return response
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
})
|
|
366
291
|
```
|
|
367
292
|
|
|
368
|
-
|
|
293
|
+
#### 2. 自定义字段名映射
|
|
369
294
|
|
|
370
|
-
|
|
371
|
-
# 安装依赖
|
|
372
|
-
bun install
|
|
295
|
+
如果后端返回的字段名不标准(如 `items` 而非 `list`):
|
|
373
296
|
|
|
374
|
-
|
|
375
|
-
|
|
297
|
+
```ts
|
|
298
|
+
createRequestCore({
|
|
299
|
+
request: { baseURL: '/api' },
|
|
300
|
+
fieldAliases: {
|
|
301
|
+
data: ['result', 'data'], // 数据层字段
|
|
302
|
+
list: ['items', 'records', 'list'], // 列表字段
|
|
303
|
+
total: ['totalCount', 'total'] // 总数字段
|
|
304
|
+
}
|
|
305
|
+
})
|
|
306
|
+
```
|
|
376
307
|
|
|
377
|
-
|
|
378
|
-
bun run build
|
|
308
|
+
#### 3. 单个接口特殊处理
|
|
379
309
|
|
|
380
|
-
|
|
381
|
-
|
|
310
|
+
```ts
|
|
311
|
+
useTableCrud({
|
|
312
|
+
api: { list: '/special/api' },
|
|
313
|
+
extractListData: (response) => ({
|
|
314
|
+
items: response.result?.data || [],
|
|
315
|
+
total: response.result?.count || 0
|
|
316
|
+
})
|
|
317
|
+
})
|
|
382
318
|
```
|
|
383
319
|
|
|
384
|
-
|
|
320
|
+
---
|
|
385
321
|
|
|
386
|
-
|
|
322
|
+
## 💡 最佳实践
|
|
323
|
+
|
|
324
|
+
### ✅ 推荐做法
|
|
325
|
+
|
|
326
|
+
1. **统一初始化配置**
|
|
327
|
+
```ts
|
|
328
|
+
// src/plugins/request-core.ts
|
|
329
|
+
export function setupRequestCore(app: App) {
|
|
330
|
+
app.use(createRequestCore({ /* 统一配置 */ }))
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
2. **使用 composable 封装业务逻辑**
|
|
335
|
+
```ts
|
|
336
|
+
// composables/useUsers.ts
|
|
337
|
+
export function useUsers() {
|
|
338
|
+
return useTableCrud<User>({
|
|
339
|
+
api: { /* ... */ },
|
|
340
|
+
columns: [ /* ... */ ]
|
|
341
|
+
})
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
3. **开启缓存减少重复请求**
|
|
346
|
+
```ts
|
|
347
|
+
getData('/api/config', { cache: { enabled: true, ttl: 600000 } })
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
4. **重要接口启用重试**
|
|
351
|
+
```ts
|
|
352
|
+
postData('/api/payment', data, { retry: { enabled: true, count: 3 } })
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### ❌ 避免的做法
|
|
356
|
+
|
|
357
|
+
1. ❌ 不要在每个组件中重复配置 axios
|
|
358
|
+
2. ❌ 不要禁用去重插件(除非有特殊需求)
|
|
359
|
+
3. ❌ 不要在 useTableCrud 外部调用其内部方法
|
|
387
360
|
|
|
388
361
|
---
|
|
389
362
|
|
|
390
|
-
##
|
|
363
|
+
## 📖 完整类型定义
|
|
391
364
|
|
|
392
|
-
|
|
365
|
+
```ts
|
|
366
|
+
// 核心配置
|
|
367
|
+
export type RequestCoreConfig = {
|
|
368
|
+
request: AxiosRequestConfig // Axios 基础配置
|
|
369
|
+
successCodes?: (string | number)[] // 成功状态码
|
|
370
|
+
fieldAliases?: FieldAliases // 字段映射
|
|
371
|
+
interceptors?: InterceptorConfig // 拦截器
|
|
372
|
+
}
|
|
393
373
|
|
|
394
|
-
|
|
374
|
+
// CRUD 配置
|
|
375
|
+
export type UseTableCrudConfig<T> = {
|
|
376
|
+
api: ApiEndpoints // API 端点
|
|
377
|
+
columns: TableColumn[] // 表格列
|
|
378
|
+
customActions?: CustomAction[] // 自定义操作
|
|
379
|
+
idKey?: string // ID 字段名
|
|
380
|
+
defaultPageSize?: number // 默认分页大小
|
|
381
|
+
autoLoad?: boolean // 是否自动加载
|
|
382
|
+
extractListData?: (res: any) => { items: T[]; total: number }
|
|
383
|
+
}
|
|
395
384
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
385
|
+
// 插件配置
|
|
386
|
+
export type EnhancedAxiosRequestConfig = AxiosRequestConfig & {
|
|
387
|
+
cache?: CacheConfig // 缓存配置
|
|
388
|
+
retry?: RetryConfig // 重试配置
|
|
389
|
+
dedupe?: DedupeConfig // 去重配置
|
|
390
|
+
cancel?: CancelConfig // 取消配置
|
|
391
|
+
}
|
|
392
|
+
```
|
|
403
393
|
|
|
404
|
-
|
|
394
|
+
查看完整类型定义:[src/index.ts](./src/index.ts)
|
|
405
395
|
|
|
406
|
-
|
|
407
|
-
- Supports pagination, search, sort, custom actions
|
|
408
|
-
- Built-in detail view, edit, delete features
|
|
396
|
+
---
|
|
409
397
|
|
|
410
|
-
|
|
398
|
+
## 🛠️ 开发
|
|
411
399
|
|
|
412
400
|
```bash
|
|
413
|
-
|
|
401
|
+
bun install # 安装依赖
|
|
402
|
+
bun run dev # 开发模式(watch)
|
|
403
|
+
bun run build # 构建
|
|
404
|
+
bun run type-check # 类型检查
|
|
414
405
|
```
|
|
415
406
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
See Chinese documentation above for detailed usage examples.
|
|
419
|
-
|
|
420
|
-
### 📝 Type Exports
|
|
407
|
+
---
|
|
421
408
|
|
|
422
|
-
|
|
409
|
+
## 📄 License
|
|
423
410
|
|
|
424
|
-
|
|
411
|
+
MIT © [ChenYu](https://github.com/ChenyCHENYU)
|
|
425
412
|
|
|
426
|
-
MIT © [ChenYu](mailto:ycyplus@gmail.com)
|