minitest2.0 0.0.0
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/.editorconfig +8 -0
- package/.env.development +3 -0
- package/.env.production +3 -0
- package/.env.test +3 -0
- package/.gitattributes +1 -0
- package/.oxlintrc.json +10 -0
- package/.prettierrc.json +6 -0
- package/.vscode/extensions.json +9 -0
- package/.vscode/settings.json +13 -0
- package/README.md +179 -0
- package/auto-imports.d.ts +629 -0
- package/components.d.ts +21 -0
- package/design-qa.md +36 -0
- package/docs/MX_API.md +244 -0
- package/docs/REQUEST.md +217 -0
- package/docs/jsapi.js +515 -0
- package/docs/package-json-guide.md +132 -0
- package/env.d.ts +15 -0
- package/eslint.config.ts +26 -0
- package/index.html +16 -0
- package/package.json +83 -0
- package/plugins/bump-version.ts +61 -0
- package/postcss.config.ts +15 -0
- package/public/favicon.ico +0 -0
- package/public/images/12a73787-86a9-4891-a65f-66104746f6a8.png +0 -0
- package/public/images/5798d7aa-ba8b-4605-8079-58b35495ac55.png +0 -0
- package/public/images/73fef1e4-0fd0-4a1a-9b8b-a70a5b6acbbc.png +0 -0
- package/public/images/bc685b4c-0cca-4a79-924c-a8ee10e6f8eb.png +0 -0
- package/public/images/c3dbbd9d-be56-490e-b9f4-6ee17ebefffc.png +0 -0
- package/public/images/ea745a10-42aa-4f44-8d7f-3ab02cc0adcd.png +0 -0
- package/public/images/f5876785-b927-4347-ba19-999114240649.png +0 -0
- package/public/images/img.png +0 -0
- package/public/images/opening-reserve-estimate.png +0 -0
- package/public/images/position-estimate-report.png +0 -0
- package/src/App.vue +131 -0
- package/src/api/announcement.ts +405 -0
- package/src/api/health.ts +13 -0
- package/src/api/pbc-position.ts +178 -0
- package/src/api/rmb-position.ts +233 -0
- package/src/api/tam.ts +173 -0
- package/src/api/user.ts +92 -0
- package/src/auto-imports.d.ts +633 -0
- package/src/components/AppTitleBar.vue +376 -0
- package/src/components.d.ts +33 -0
- package/src/config/config.properties +3 -0
- package/src/config/env.ts +6 -0
- package/src/config/plugin.properties.pro +6 -0
- package/src/config/plugin.properties.test +6 -0
- package/src/core/mxApi/index.ts +451 -0
- package/src/core/request/index.ts +135 -0
- package/src/main.ts +40 -0
- package/src/router/index.ts +144 -0
- package/src/stores/app.ts +103 -0
- package/src/stores/counter.ts +12 -0
- package/src/stores/user.ts +137 -0
- package/src/styles/nprogress.css +22 -0
- package/src/styles/vant-overrides.css +42 -0
- package/src/types/api.d.ts +14 -0
- package/src/types/nprogress.d.ts +8 -0
- package/src/utils/auth-token.ts +241 -0
- package/src/utils/code-highlight.ts +165 -0
- package/src/utils/copy.ts +36 -0
- package/src/utils/query.ts +27 -0
- package/src/utils/request.ts +238 -0
- package/src/utils/rmb-forecast.ts +84 -0
- package/src/utils/toast.ts +61 -0
- package/src/views/article-detail/index.vue +289 -0
- package/src/views/article-edit/index.vue +600 -0
- package/src/views/articles/index.vue +293 -0
- package/src/views/clearing-detail/index.vue +26 -0
- package/src/views/dashboard/index.vue +18 -0
- package/src/views/foreign-position/index.vue +26 -0
- package/src/views/home/index.vue +213 -0
- package/src/views/login/index.vue +275 -0
- package/src/views/mine/index.vue +147 -0
- package/src/views/net-debit/index.vue +26 -0
- package/src/views/opening-reserve-estimate/index.vue +28 -0
- package/src/views/pbc-position/index.vue +357 -0
- package/src/views/position-estimate/index.vue +67 -0
- package/src/views/position-estimate-report/index.vue +28 -0
- package/src/views/rmb-position/index.vue +1013 -0
- package/src/views/rmb-position-create/index.vue +221 -0
- package/src/views/rmb-position-detail/index.vue +355 -0
- package/src/views/settings/index.vue +67 -0
- package/src/views/warning/index.vue +26 -0
- package/tsconfig.app.json +18 -0
- package/tsconfig.json +11 -0
- package/tsconfig.node.json +28 -0
- package/vite.config.ts +100 -0
package/components.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
// biome-ignore lint: disable
|
|
4
|
+
// oxlint-disable
|
|
5
|
+
// ------
|
|
6
|
+
// Generated by unplugin-vue-components
|
|
7
|
+
// Read more: https://github.com/vuejs/core/pull/3399
|
|
8
|
+
|
|
9
|
+
export {}
|
|
10
|
+
|
|
11
|
+
/* prettier-ignore */
|
|
12
|
+
declare module 'vue' {
|
|
13
|
+
export interface GlobalComponents {
|
|
14
|
+
RouterLink: typeof import('vue-router')['RouterLink']
|
|
15
|
+
RouterView: typeof import('vue-router')['RouterView']
|
|
16
|
+
VanButton: typeof import('vant/es')['Button']
|
|
17
|
+
VanCellGroup: typeof import('vant/es')['CellGroup']
|
|
18
|
+
VanField: typeof import('vant/es')['Field']
|
|
19
|
+
VanForm: typeof import('vant/es')['Form']
|
|
20
|
+
}
|
|
21
|
+
}
|
package/design-qa.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
**Source Visual Truth**
|
|
2
|
+
- `/var/folders/9_/635n2vmx5017pd592w50p_d80000gn/T/codex-clipboard-1988700c-e4e0-41e1-95e6-db1b36fb6836.png`
|
|
3
|
+
|
|
4
|
+
**Implementation Screenshot**
|
|
5
|
+
- `/Users/bombingpig/WebstormProjects/mini2.0/output/playwright/rmb-position/rmb-position-page.png`
|
|
6
|
+
|
|
7
|
+
**Viewport**
|
|
8
|
+
- 428 x 926
|
|
9
|
+
|
|
10
|
+
**State**
|
|
11
|
+
- Authenticated local preview route `#/rmb-position`, default query state, two seeded forecast records.
|
|
12
|
+
|
|
13
|
+
**Full-View Comparison Evidence**
|
|
14
|
+
- `/Users/bombingpig/WebstormProjects/mini2.0/output/playwright/rmb-position/design-comparison.png`
|
|
15
|
+
|
|
16
|
+
**Focused Region Comparison Evidence**
|
|
17
|
+
- Full-view comparison was sufficient for this pass because the relevant detail surfaces are visible at 428 x 926: header, query panel, amount inputs, summary card, forecast list, status tags, and floating action button.
|
|
18
|
+
|
|
19
|
+
**Findings**
|
|
20
|
+
- No actionable P0/P1/P2 issues remain.
|
|
21
|
+
- P3: The hero illustration uses the closest existing project asset rather than the exact receipt/magnifier illustration in the reference.
|
|
22
|
+
- P3: Native browser/system overlays differ in local preview: the reference includes iOS status/home indicators and native vConsole, while the web preview shows Vue DevTools chrome.
|
|
23
|
+
|
|
24
|
+
**Patches Made**
|
|
25
|
+
- Implemented the RMB forecast query page in `src/views/rmb-position/index.vue`.
|
|
26
|
+
- Hid the bottom app tabbar for `/rmb-position` to match the detail-page reference.
|
|
27
|
+
- Adjusted the amount range row so placeholders and `亿元` fit without wrapping.
|
|
28
|
+
- Swapped the institution icon toward a building-style Vant icon for closer visual semantics.
|
|
29
|
+
|
|
30
|
+
**Verification**
|
|
31
|
+
- `npm run type-check` passed.
|
|
32
|
+
- `PATH=/Users/bombingpig/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin:$PATH npm run build-only` passed.
|
|
33
|
+
- Playwright CLI verified query, date picker, detail-free default rendering, add forecast popup, and successful add flow.
|
|
34
|
+
|
|
35
|
+
**Final Result**
|
|
36
|
+
- final result: passed
|
package/docs/MX_API.md
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# MX 原生桥接 API 使用指南
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
`core/mxApi` 是敏行混合应用的原生桥接模块,提供与原生 Android/iOS 应用通信的能力。
|
|
6
|
+
|
|
7
|
+
## 功能列表
|
|
8
|
+
|
|
9
|
+
### UI 控制
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { hideWebViewTitle, showOptionMenu, setCustomHeaderMenu } from '@/core/mxApi'
|
|
13
|
+
|
|
14
|
+
// 隐藏原生标题栏
|
|
15
|
+
hideWebViewTitle()
|
|
16
|
+
|
|
17
|
+
// 显示右上角菜单
|
|
18
|
+
showOptionMenu()
|
|
19
|
+
|
|
20
|
+
// 设置自定义菜单
|
|
21
|
+
setCustomHeaderMenu({
|
|
22
|
+
menus: [
|
|
23
|
+
{ id: '1', title: '设置' },
|
|
24
|
+
{ id: '2', title: '关于' }
|
|
25
|
+
]
|
|
26
|
+
})
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 获取用户信息
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { getCurrentUser } from '@/core/mxApi'
|
|
33
|
+
|
|
34
|
+
const user = await getCurrentUser()
|
|
35
|
+
console.log(user.id, user.name, user.token)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 选人组件
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { MXSelectUsers } from '@/core/mxApi'
|
|
42
|
+
|
|
43
|
+
const users = await MXSelectUsers({
|
|
44
|
+
enableSelectDept: false, // 是否允许选择部门
|
|
45
|
+
canSelectSelf: true // 是否可选自己
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
console.log('选中的用户:', users)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 原生 HTTP 请求(绕过跨域)
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { ajaxGet, ajaxPost, ajaxPut, ajaxDelete } from '@/core/mxApi'
|
|
55
|
+
|
|
56
|
+
// GET 请求
|
|
57
|
+
const { data } = await ajaxGet('/api/users', { page: 1, limit: 10 })
|
|
58
|
+
|
|
59
|
+
// POST 请求
|
|
60
|
+
const { data } = await ajaxPost('/api/users', { name: '张三' })
|
|
61
|
+
|
|
62
|
+
// PUT 请求
|
|
63
|
+
await ajaxPut('/api/users/123', { name: '李四' })
|
|
64
|
+
|
|
65
|
+
// DELETE 请求
|
|
66
|
+
await ajaxDelete('/api/users', '123')
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 环境检测
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { isNativeApp } from '@/core/mxApi'
|
|
73
|
+
|
|
74
|
+
if (isNativeApp()) {
|
|
75
|
+
// 在原生环境中,可使用所有原生 API
|
|
76
|
+
const user = await getCurrentUser()
|
|
77
|
+
} else {
|
|
78
|
+
// 在浏览器中,使用 axios 或降级方案
|
|
79
|
+
import('@/utils/request').then(({ request }) => {
|
|
80
|
+
// 使用 axios 发起请求
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## 与 axios 的区别
|
|
86
|
+
|
|
87
|
+
| 特性 | axios | MX ajax |
|
|
88
|
+
|------|-------|---------|
|
|
89
|
+
| 跨域限制 | 受同源策略限制 | 无限制 |
|
|
90
|
+
| 认证信息 | 需手动添加 Token | 可复用原生层认证 |
|
|
91
|
+
| 网络代理 | 无 | 使用原生层代理配置 |
|
|
92
|
+
| SSL 证书 | 浏览器验证 | 可使用企业证书 |
|
|
93
|
+
| 适用环境 | 浏览器、WebView | 仅混合应用原生环境 |
|
|
94
|
+
|
|
95
|
+
## 项目中的两种 HTTP 方案
|
|
96
|
+
|
|
97
|
+
### 方案 1:axios(默认)
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// src/utils/request.ts
|
|
101
|
+
import axios from 'axios'
|
|
102
|
+
import { apiConfig } from '@/config/env'
|
|
103
|
+
|
|
104
|
+
const service = axios.create({
|
|
105
|
+
baseURL: apiConfig.baseURL,
|
|
106
|
+
timeout: apiConfig.timeout,
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
export default service
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**适用场景**:
|
|
113
|
+
- 浏览器开发调试
|
|
114
|
+
- 不需要绕过跨域限制
|
|
115
|
+
- 使用标准 RESTful API
|
|
116
|
+
|
|
117
|
+
### 方案 2:原生 AJAX
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// src/core/mxApi/index.ts
|
|
121
|
+
import { ajaxGet, ajaxPost } from '@/core/mxApi'
|
|
122
|
+
|
|
123
|
+
// 使用原生 HTTP 客户端
|
|
124
|
+
const { data } = await ajaxGet('/api/users')
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**适用场景**:
|
|
128
|
+
- 需要绕过浏览器跨域限制
|
|
129
|
+
- 使用原生层认证信息
|
|
130
|
+
- 需要企业证书支持
|
|
131
|
+
- 在敏行 App 中运行
|
|
132
|
+
|
|
133
|
+
## 智能切换示例
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { isNativeApp, ajaxGet as nativeGet } from '@/core/mxApi'
|
|
137
|
+
import { request } from '@/utils/request'
|
|
138
|
+
|
|
139
|
+
export async function fetchUsers(page: number) {
|
|
140
|
+
if (isNativeApp()) {
|
|
141
|
+
// 使用原生 AJAX
|
|
142
|
+
const { data } = await nativeGet('/api/users', { page })
|
|
143
|
+
return data
|
|
144
|
+
} else {
|
|
145
|
+
// 使用 axios
|
|
146
|
+
const res = await request({
|
|
147
|
+
url: '/api/users',
|
|
148
|
+
params: { page }
|
|
149
|
+
})
|
|
150
|
+
return res.data
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## 注意事项
|
|
156
|
+
|
|
157
|
+
### 1. 设备就绪机制
|
|
158
|
+
|
|
159
|
+
mxApi 内置任务队列,在设备未就绪时会自动缓存调用请求。无需手动处理 `deviceready` 事件。
|
|
160
|
+
|
|
161
|
+
### 2. 环境变量
|
|
162
|
+
|
|
163
|
+
原生 AJAX 使用 `VITE_API_BASE_URL` 作为基础 URL,与 axios 配置保持一致。
|
|
164
|
+
|
|
165
|
+
### 3. 错误处理
|
|
166
|
+
|
|
167
|
+
当原生接口不存在时,会抛出错误。建议在调用前检测环境:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { isNativeApp } from '@/core/mxApi'
|
|
171
|
+
|
|
172
|
+
if (!isNativeApp()) {
|
|
173
|
+
showToast('请在敏行 App 中使用此功能')
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 4. TypeScript 类型支持
|
|
179
|
+
|
|
180
|
+
所有 API 都有完整的类型定义,包括:
|
|
181
|
+
- `MXUser` - 用户信息
|
|
182
|
+
- `MXSelectUsersOptions` - 选人配置
|
|
183
|
+
- `MXAjaxResponse<T>` - AJAX 响应
|
|
184
|
+
|
|
185
|
+
## 开发调试
|
|
186
|
+
|
|
187
|
+
在浏览器中开发时,原生接口不可用。建议:
|
|
188
|
+
|
|
189
|
+
1. **使用条件判断**:根据环境选择不同的请求方式
|
|
190
|
+
2. **使用 Vant 组件**:如 `showToast` 显示提示
|
|
191
|
+
3. **日志输出**:mxApi 会自动输出调用日志
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// 开发环境提示
|
|
195
|
+
if (!isNativeApp()) {
|
|
196
|
+
console.warn('当前为浏览器环境,原生 API 不可用')
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## 完整示例
|
|
201
|
+
|
|
202
|
+
```vue
|
|
203
|
+
<script setup lang="ts">
|
|
204
|
+
import { ref, onMounted } from 'vue'
|
|
205
|
+
import { showToast } from 'vant'
|
|
206
|
+
import { isNativeApp, getCurrentUser, MXSelectUsers } from '@/core/mxApi'
|
|
207
|
+
import type { MXUser } from '@/core/mxApi'
|
|
208
|
+
|
|
209
|
+
const user = ref<MXUser | null>(null)
|
|
210
|
+
const selectedUsers = ref<MXUser[]>([])
|
|
211
|
+
|
|
212
|
+
onMounted(async () => {
|
|
213
|
+
if (isNativeApp()) {
|
|
214
|
+
try {
|
|
215
|
+
user.value = await getCurrentUser()
|
|
216
|
+
showToast(`欢迎, ${user.value.name}`)
|
|
217
|
+
} catch (err) {
|
|
218
|
+
console.error('获取用户失败:', err)
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
const handleSelectUsers = async () => {
|
|
224
|
+
if (!isNativeApp()) {
|
|
225
|
+
showToast('请在敏行 App 中使用')
|
|
226
|
+
return
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
selectedUsers.value = await MXSelectUsers()
|
|
231
|
+
showToast(`已选择 ${selectedUsers.value.length} 人`)
|
|
232
|
+
} catch (err) {
|
|
233
|
+
console.error('选人失败:', err)
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
</script>
|
|
237
|
+
|
|
238
|
+
<template>
|
|
239
|
+
<div>
|
|
240
|
+
<van-cell title="当前用户" :value="user?.name || '未登录'" />
|
|
241
|
+
<van-button @click="handleSelectUsers">选择联系人</van-button>
|
|
242
|
+
</div>
|
|
243
|
+
</template>
|
|
244
|
+
```
|
package/docs/REQUEST.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# 统一请求中转层使用指南
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
`core/request` 是请求中转层,**接口与 `src/utils/request.ts` 完全一致**。
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
应用层(API 模块)
|
|
9
|
+
│
|
|
10
|
+
▼
|
|
11
|
+
┌─────────────────────────────────────┐
|
|
12
|
+
│ 中转层 core/request │
|
|
13
|
+
│ │
|
|
14
|
+
│ request() ← 与 utils/request 接口一致 │
|
|
15
|
+
│ │
|
|
16
|
+
│ • 自动环境检测 │
|
|
17
|
+
│ • 统一请求头管理 │
|
|
18
|
+
│ • Token 管理 │
|
|
19
|
+
└───────────────┬─────────────────────┘
|
|
20
|
+
│
|
|
21
|
+
┌─────────┴─────────┐
|
|
22
|
+
▼ ▼
|
|
23
|
+
┌────────┐ ┌────────┐
|
|
24
|
+
│ axios │ │ mxApi │
|
|
25
|
+
│(已封装) │ │(原生) │
|
|
26
|
+
└────────┘ └────────┘
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 核心特性
|
|
32
|
+
|
|
33
|
+
### 1. 接口完全一致
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// 原来使用 utils/request
|
|
37
|
+
import { request } from '@/utils/request'
|
|
38
|
+
|
|
39
|
+
// 现在使用 core/request(接口完全一致)
|
|
40
|
+
import { request } from '@/core/request'
|
|
41
|
+
|
|
42
|
+
// 用法完全相同,无需修改任何调用代码
|
|
43
|
+
const res = await request<UserInfo>({ url: '/user/1' })
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 2. 自动环境检测
|
|
47
|
+
|
|
48
|
+
- **浏览器环境**:调用 `utils/request`(axios 封装)
|
|
49
|
+
- **原生环境**:调用 `core/mxApi`(原生 AJAX)
|
|
50
|
+
|
|
51
|
+
### 3. 统一请求头
|
|
52
|
+
|
|
53
|
+
所有请求自动携带:
|
|
54
|
+
- `Content-Type: application/json`
|
|
55
|
+
- `Authorization: Bearer {token}`(如有)
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 使用方式
|
|
60
|
+
|
|
61
|
+
### Token 管理
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { setToken, getToken, clearToken } from '@/core/request'
|
|
65
|
+
|
|
66
|
+
// 登录后保存 Token
|
|
67
|
+
setToken('your-jwt-token')
|
|
68
|
+
|
|
69
|
+
// 获取 Token
|
|
70
|
+
const token = getToken()
|
|
71
|
+
|
|
72
|
+
// 退出登录
|
|
73
|
+
clearToken()
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 请求函数
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { request } from '@/core/request'
|
|
80
|
+
|
|
81
|
+
// GET 请求
|
|
82
|
+
const user = await request<UserInfo>({ url: '/user/1' })
|
|
83
|
+
|
|
84
|
+
// POST 请求
|
|
85
|
+
const { token } = await request<{ token: string }, LoginParams>({
|
|
86
|
+
url: '/login',
|
|
87
|
+
method: 'POST',
|
|
88
|
+
data: { username: 'admin', password: '123' }
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
// 带查询参数
|
|
92
|
+
const users = await request<UserList>({
|
|
93
|
+
url: '/users',
|
|
94
|
+
params: { page: 1, limit: 10 }
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
// 自定义请求头
|
|
98
|
+
const res = await request({
|
|
99
|
+
url: '/upload',
|
|
100
|
+
method: 'POST',
|
|
101
|
+
data: formData,
|
|
102
|
+
headers: { 'Content-Type': 'multipart/form-data' }
|
|
103
|
+
})
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## API 模块示例
|
|
109
|
+
|
|
110
|
+
### 用户模块
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// src/api/user.ts
|
|
114
|
+
import { request } from '@/core/request'
|
|
115
|
+
|
|
116
|
+
interface UserInfo {
|
|
117
|
+
id: number
|
|
118
|
+
username: string
|
|
119
|
+
avatar: string
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function getUserInfo(id: number) {
|
|
123
|
+
return request<UserInfo>({ url: `/user/${id}` })
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function login(data: { username: string; password: string }) {
|
|
127
|
+
return request<{ token: string }, typeof data>({
|
|
128
|
+
url: '/login',
|
|
129
|
+
method: 'POST',
|
|
130
|
+
data
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function updateUser(id: string, data: UpdateUserParams) {
|
|
135
|
+
return request<User, typeof data>({
|
|
136
|
+
url: `/user/${id}`,
|
|
137
|
+
method: 'PUT',
|
|
138
|
+
data
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function deleteUser(id: string) {
|
|
143
|
+
return request({
|
|
144
|
+
url: `/user/${id}`,
|
|
145
|
+
method: 'DELETE'
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 在组件中使用
|
|
151
|
+
|
|
152
|
+
```vue
|
|
153
|
+
<script setup lang="ts">
|
|
154
|
+
import { ref, onMounted } from 'vue'
|
|
155
|
+
import { showToast } from 'vant'
|
|
156
|
+
import { getUserInfo, login } from '@/api/user'
|
|
157
|
+
import { setToken } from '@/core/request'
|
|
158
|
+
|
|
159
|
+
const user = ref<UserInfo | null>(null)
|
|
160
|
+
|
|
161
|
+
onMounted(async () => {
|
|
162
|
+
try {
|
|
163
|
+
const res = await getUserInfo(1)
|
|
164
|
+
user.value = res.data
|
|
165
|
+
} catch (error) {
|
|
166
|
+
showToast('获取用户失败')
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
const handleLogin = async () => {
|
|
171
|
+
try {
|
|
172
|
+
const res = await login({
|
|
173
|
+
username: 'admin',
|
|
174
|
+
password: '123'
|
|
175
|
+
})
|
|
176
|
+
setToken(res.data.token)
|
|
177
|
+
showToast('登录成功')
|
|
178
|
+
} catch (error) {
|
|
179
|
+
showToast('登录失败')
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
</script>
|
|
183
|
+
|
|
184
|
+
<template>
|
|
185
|
+
<div>
|
|
186
|
+
<van-cell title="用户名" :value="user?.username" />
|
|
187
|
+
<van-button @click="handleLogin">登录</van-button>
|
|
188
|
+
</div>
|
|
189
|
+
</template>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 导出说明
|
|
195
|
+
|
|
196
|
+
| 导出 | 类型 | 说明 |
|
|
197
|
+
|------|------|------|
|
|
198
|
+
| `request` | 函数 | 核心中转函数,与 `utils/request` 接口一致 |
|
|
199
|
+
| `setToken` | 函数 | 设置 Token |
|
|
200
|
+
| `getToken` | 函数 | 获取 Token |
|
|
201
|
+
| `clearToken` | 函数 | 清除 Token |
|
|
202
|
+
| `getCommonHeaders` | 函数 | 获取公共请求头 |
|
|
203
|
+
| `RequestConfig` | 类型 | 请求配置接口 |
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 与 utils/request 的关系
|
|
208
|
+
|
|
209
|
+
| 特性 | utils/request | core/request |
|
|
210
|
+
|------|---------------|--------------|
|
|
211
|
+
| 底层实现 | axios | axios + mxApi |
|
|
212
|
+
| 环境支持 | 仅浏览器 | 浏览器 + 原生 |
|
|
213
|
+
| 接口格式 | ✅ | ✅ 完全一致 |
|
|
214
|
+
| Token 管理 | ❌ | ✅ 内置 |
|
|
215
|
+
| 请求头管理 | 分散 | 统一 |
|
|
216
|
+
|
|
217
|
+
**核心优势**:只需将 `import { request } from '@/utils/request'` 改为 `import { request } from '@/core/request'`,即可自动获得原生环境支持,无需修改任何业务代码。
|