Files
simapi-vue/README.md
T
xrain ae742d452d
Publish to npm / publish (push) Failing after 10s
修正无用的内容
2026-04-08 02:44:04 +08:00

390 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# @simcu/simapi
> 轻量级 HTTP 请求库,基于原生 fetch,支持任意 JS/TS 环境及 Vue3。
## 安装
```bash
npm install @simcu/simapi
```
## 架构
```
src/
├── types.ts # 类型定义(SimApiBaseResponse、SimApiOptions 等)
├── simapi.core.ts # 纯 TS 核心,无框架依赖
└── simapi.pinia.ts # Vue3 Pinia Store 封装
```
## 核心层(框架无关)
适用于浏览器、Node.js、小程序等任意环境。
```typescript
import { SimApiCore } from '@simcu/simapi'
const api = new SimApiCore()
// 从 window.simapi 读取配置(可选)
api.autoInit()
// 或手动配置
api.configure({
api: { endpoints: { default: 'https://api.example.com' } },
debug: true,
})
// 发起请求
const res = await api.query('/users/list', { page: 1 })
// res.code === 200res.data 为业务数据
// 登录
await api.login({ phone: '13800138000', code: '123456' })
// 登出
await api.logout()
// 注册业务错误码回调
api.setBusinessCallback(401, () => router.push('/login'))
api.setBusinessCallback('common', (data) => alert(data.message))
```
## Vue3
安装 Pinia
```bash
npm install pinia
```
```typescript
// main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
```
```typescript
// 任意组件
import { useSimApi } from '@simcu/simapi'
const api = useSimApi()
// 响应式
console.log(api.token) // 当前 Token
console.log(api.isLoggedIn) // 是否已登录
// 发起请求
const res = await api.query('/users/list', { page: 1 })
console.log(res.data)
// 登录 / 登出
await api.login({ phone: '13800138000', code: '123456' })
await api.logout()
// 调试模式
api.setDebug(true)
```
### 多端点
```typescript
api.setEndpoints({
default: 'https://api.example.com',
admin: 'https://admin.example.com',
})
// 指定端点发请求
await api.query('/stats', {}, 'admin')
```
## autoInit — 从 window 读取配置
支持字段:`endpoints``defaultEndpoint``debug`。业务回调需在代码中通过 `setBusinessCallback` 处理。
```html
<script>
window.simapi = {
endpoints: {
default: 'https://api.example.com',
admin: 'https://admin.example.com',
},
defaultEndpoint: 'default',
debug: false,
}
</script>
```
初始化时手动调用:
```typescript
// 方式一:从 window.simapi 读取
const api = useSimApi()
api.autoInit()
// 方式二:直接传入配置
const api = useSimApi()
api.configure({
api: { endpoints: { default: 'https://api.example.com' } },
})
```
## SimApiBaseResponse 响应格式
```typescript
interface SimApiBaseResponse<T = any> {
code: number // 200 = 成功,其他为业务错误码
message: string // 提示信息
data?: T // 业务数据
}
```
## 完整配置参考
### SimApiOptions — 完整配置结构
```typescript
interface SimApiOptions {
/** 调试模式,默认 true */
debug?: boolean
/** 认证相关配置 */
auth?: Partial<SimApiAuthConfig>
/** API 相关配置 */
api?: Partial<SimApiApiConfig>
}
```
### SimApiAuthConfig — 认证配置
```typescript
interface SimApiAuthConfig {
/** localStorage 中存储 Token 的 key */
token_name: string // 默认 'simapi-auth-token'
/** 检查登录状态的接口路径 */
check_url: string // 默认 '/auth/check'
/** 登出接口路径 */
logout_url: string // 默认 '/auth/logout'
/** 登录接口路径 */
login_url: string // 默认 '/auth/login'
}
```
### SimApiApiConfig — API 配置
```typescript
interface SimApiApiConfig {
/** 多端点映射,key 为端点名,value 为 baseURL */
endpoints: { [name: string]: string }
/** 默认端点名,默认 'default' */
defaultEndpoint: string
/** 业务错误码回调,key 为错误码或 'common' */
businessCallback: SimApiBusinessCallback
/** 响应拦截回调 */
responseCallback: SimApiResponseCallback
/** 请求超时时间(毫秒),默认 10000 */
timeout?: number
}
```
**⚠️ CORS 说明**
- 本库使用原生 fetch API,默认不发送 Cookie`credentials: 'omit'`
- Token 通过请求头 `Token` 传递,无需依赖 Cookie
- 服务器返回 `Access-Control-Allow-Origin: *` 不会有问题
### SimApiBusinessCallback — 业务回调
key 支持数字错误码或 `'common'`(通用兜底回调):
```typescript
type SimApiBusinessCallback = {
[code: number | string]: (data: SimApiBaseResponse) => void
}
// 示例
{
401: (data) => router.push('/login'), // 未授权
403: (data) => ElMessage.error('无权限'), // 无权限
500: (data) => console.error(data), // 服务器错误
'common': (data) => ElMessage.error(data.message) // 其他错误码兜底
}
```
### SimApiResponseCallback — 响应拦截
```typescript
interface SimApiResponseCallback {
/** 成功响应拦截,可在此统一处理数据结构 */
success: (response: any) => any
/** 网络/HTTP 错误拦截 */
error: (err: any) => void
}
// 示例:统一脱敏处理
{
success: (res) => {
// fetch 返回 { code, message, data }
return res
},
error: (err) => {
console.error('请求失败', err)
throw err
}
}
```
### SimApiVersions — 版本信息
```typescript
interface SimApiVersions {
uiApp: string // 前端应用版本
uiSimApi: string // 前端 SimApi 版本
apiApp: string // 后端应用版本(简化版,如 "1.2.3"
apiSimApi: string // 后端 SimApi 版本(简化版)
apiAppFull: string // 后端应用版本(完整版,如 "1.2.3+20240101"
apiSimApiFull: string // 后端 SimApi 版本(完整版)
}
```
### 完整配置示例
```typescript
api.configure({
debug: false,
auth: {
token_name: 'my-app-token',
check_url: '/api/auth/check',
logout_url: '/api/auth/logout',
login_url: '/api/auth/login',
},
api: {
endpoints: {
default: 'https://api.example.com',
admin: 'https://admin.example.com',
},
defaultEndpoint: 'default',
businessCallback: {
401: () => router.push('/login'),
403: () => ElMessage.error('无权限访问'),
500: (data) => console.error('服务器错误:', data.message),
'common': (data) => ElMessage.error(data.message || '请求失败'),
},
responseCallback: {
success: (res) => res.data ?? res,
error: (err) => {
console.error('网络错误', err)
},
},
},
})
```
## API 参考
### SimApiCore(核心类)
| 方法/属性 | 说明 |
|-----------|------|
| `configure(options)` | 批量配置(深合并) |
| `autoInit()` | 从 `window.simapi` 读取配置(endpoints、defaultEndpoint、debug |
| `setEndpoints(map)` | 设置端点 |
| `setBusinessCallback(code, fn)` | 注册业务错误码回调 |
| `query(uri, params?, endpointKey?, headers?)` | POST 请求,返回 `Promise<SimApiBaseResponse<T>>` |
| `login(request)` | 登录,自动存 Token |
| `logout(url?)` | 登出,清除 Token |
| `checkLogin(url?)` | 主动检查登录状态 |
| `getVersion(endpointName?)` | 获取版本信息,返回 `Promise<SimApiVersions>` |
| `getToken()` | 获取 Token |
| `setToken(token)` | 手动设置 Token |
| `removeToken()` | 清除 Token |
| `isLoggedIn` | getter,是否已登录 |
| `debug` | boolean,调试模式 |
| `logDebug(...args)` | 日志工具(仅在 debug 模式输出) |
## 构建
```bash
npm install
npm run build
npm link # 本地调试
```
### 版本号注入
库使用 `declare const` 声明版本常量,构建时通过 Vite 的 `define` 注入版本号。
**注意:**
- **SimApiVersion**:由 simapi 库构建时注入
- **AppVersion**:不注入,留给调用方 APP 注入
**本地构建:**
```bash
# 通过环境变量注入 SimApiVersion
# Windows PowerShell
$env:npm_config_SimApiVersion='1.0.0'; npm run build
# Linux/Mac
npm_config_SimApiVersion=1.0.0 npm run build
```
未指定时默认为 `0.0.0-develop`
**CI/CD 构建版本号:**
```yaml
env:
SimApiVersion: ${{ github.ref_name }}
run: npm run build
```
**调用方注入 AppVersion**
调用方在自己的 `vite.config.ts` 中添加:
```typescript
define: {
'AppVersion': JSON.stringify('1.0.0')
}
```
---
## 从旧版迁移
如果你之前使用的是带 axios 的版本,迁移非常简单:
```diff
- import axios from 'axios'
+ import { SimApiCore } from '@simcu/simapi'
- // ... 你的 axios 配置
+ const api = new SimApiCore()
+ api.setEndpoints({ default: 'https://api.example.com' })
+ const res = await api.query('/users/list', { page: 1 })
```
API 完全兼容,无需其他改动。主要变化:
- 使用原生 fetch 替代 axios
- Token 通过请求头 `Token` 传递(不是 `Authorization: Bearer`
- 默认不发送 Cookie,避免 CORS 问题