@hlw-uni/mp-core 1.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/README.md ADDED
@@ -0,0 +1,229 @@
1
+ # @hlw-uni/mp-core
2
+
3
+ UniApp 运行时核心包,提供 `Composables`、`Utils`、`Components` 和统一的 `hlw` 全局命名空间,开箱即用。
4
+
5
+ ## 包含模块
6
+
7
+ | 模块 | 说明 |
8
+ |------|------|
9
+ | **hlw 全局命名空间** | `hlw.$msg`、`hlw.$device`、`hlw.$http` — 在 `app.config.globalProperties` 中注入 |
10
+ | **Composables** | `useHttp`、`useLoading`、`useMsg`、`useRefs`、`useDevice` |
11
+ | **Utils** | `format`、`validate`、`storage`、`device` 工具函数 |
12
+ | **Components** | `Avatar`、`Empty`、`Loading`、`MenuList` |
13
+
14
+ ## 安装
15
+
16
+ ```bash
17
+ npm install @hlw-uni/mp-core
18
+ ```
19
+
20
+ 配合 `@hlw-uni/mp-vite-plugin` 使用,可自动注入环境变量、SCSS 主题和 Auto-Import。
21
+
22
+ ## hlw 全局命名空间
23
+
24
+ 通过 `app.config.globalProperties['hlw'] = hlw` 注入后,可在任何 Vue 上下文直接访问:
25
+
26
+ ```ts
27
+ // 在 Options API 或模板中
28
+ this.hlw.$msg.success('操作成功');
29
+ this.hlw.$msg.confirm({ content: '确定删除?' });
30
+ this.hlw.$device.platform; // 'mp-weixin'
31
+ this.hlw.$device.statusBarHeight;
32
+
33
+ // 在 Composition API 中直接 import
34
+ import { hlw } from '@hlw-uni/mp-core';
35
+ hlw.$msg.toast('提示');
36
+ ```
37
+
38
+ > 旧写法 `$msg` 和 `$device` 仍然保留兼容。
39
+
40
+ ## Composables
41
+
42
+ ### useHttp — HTTP 请求
43
+
44
+ ```ts
45
+ import { useHttp } from '@hlw-uni/mp-core';
46
+
47
+ const { loading, data, error, run, get, post } = useHttp();
48
+
49
+ // GET 请求
50
+ const res = await get<UserInfo>('/user/info');
51
+
52
+ // POST 请求
53
+ const res = await post('/user/login', { phone, code });
54
+
55
+ // 状态追踪
56
+ if (loading.value) { /* 显示加载态 */ }
57
+ if (error.value) { /* 处理错误 */ }
58
+ console.log(data.value);
59
+
60
+ // 全局拦截器(建议在 main.ts 中集中配置)
61
+ import { http } from '@hlw-uni/mp-core';
62
+ http.onRequest((config) => {
63
+ const token = useUserStore().token;
64
+ if (token) config.headers!['token'] = token;
65
+ return config;
66
+ });
67
+ ```
68
+
69
+ 请求会自动携带 `token`(从用户 store 读取)。401 时自动清除存储。
70
+
71
+ > `VITE_API_BASE_URL` 通过 `@hlw-uni/mp-vite-plugin` 在编译时注入,无需手动配置。
72
+
73
+ ### useLoading — Loading 状态
74
+
75
+ ```ts
76
+ import { useLoading } from '@hlw-uni/mp-core';
77
+
78
+ const { loading, showLoading, hideLoading } = useLoading();
79
+
80
+ showLoading('加载中...');
81
+ const data = await fetchSomething();
82
+ hideLoading();
83
+ ```
84
+
85
+ ### useMsg — 消息提示
86
+
87
+ ```ts
88
+ import { useMsg } from '@hlw-uni/mp-core';
89
+
90
+ const msg = useMsg();
91
+
92
+ msg.success('保存成功'); // 成功提示
93
+ msg.error('提交失败'); // 失败提示
94
+ msg.toast({ message: '提示', position: 'top' });
95
+
96
+ await msg.confirm({ // 确认对话框
97
+ title: '提示',
98
+ content: '确定要删除吗?',
99
+ confirmText: '确定',
100
+ cancelText: '取消',
101
+ });
102
+ ```
103
+
104
+ 同时自动注入为 `this.hlw.$msg` 或 `this.$msg`。
105
+
106
+ ### useDevice — 设备信息
107
+
108
+ ```ts
109
+ import { useDevice } from '@hlw-uni/mp-core';
110
+
111
+ const device = useDevice();
112
+
113
+ console.log(device.value.platform); // 'mp-weixin'
114
+ console.log(device.value.brand); // 'weixin'
115
+ console.log(device.value.statusBarHeight); // 20
116
+ console.log(device.value.navBarHeight); // 64 (statusBar + 44)
117
+ ```
118
+
119
+ ### useRefs — 模板 Refs
120
+
121
+ ```ts
122
+ import { useRefs } from '@hlw-uni/mp-core';
123
+
124
+ const { refs, setRefs } = useRefs();
125
+
126
+ // 在 <template> 中使用
127
+ // <view :ref="setRefs('item0')">...</view>
128
+ // 访问: refs.value['item0']
129
+ ```
130
+
131
+ ## Utils
132
+
133
+ ### 格式化 (format)
134
+
135
+ ```ts
136
+ import { formatDate, formatMoney, formatPhone, formatFileSize } from '@hlw-uni/mp-core';
137
+
138
+ formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss'); // '2026-04-05 12:00:00'
139
+ formatMoney(1234567.89); // '1,234,567.89'
140
+ formatPhone('13812345678'); // '138****5678'
141
+ formatFileSize(1024 * 1024 * 5); // '5.00 MB'
142
+ ```
143
+
144
+ ### 校验 (validate)
145
+
146
+ ```ts
147
+ import { validatePhone, validateEmail, validateUrl, validateIdCard, validateCarNumber, validatePassword, isEmpty } from '@hlw-uni/mp-core';
148
+
149
+ validatePhone('13812345678'); // true
150
+ validateEmail('test@example.com'); // true
151
+ validateUrl('https://example.com'); // true
152
+ validateIdCard('110101199001011234'); // true
153
+ validateCarNumber('京A12345'); // true
154
+ validatePassword('Abc12345'); // true
155
+ isEmpty(null); // true
156
+ isEmpty({}); // true
157
+ ```
158
+
159
+ ### 存储 (storage)
160
+
161
+ ```ts
162
+ import { getStorage, setStorage, removeStorage, clearStorage, getStorageInfoSync } from '@hlw-uni/mp-core';
163
+
164
+ setStorage('token', 'abc123');
165
+ const token = getStorage<string>('token'); // 'abc123'
166
+ removeStorage('token');
167
+ clearStorage();
168
+ const info = getStorageInfoSync(); // { keys: [...], currentSize: 0, limitSize: 1024 }
169
+ ```
170
+
171
+ ### 设备 (device)
172
+
173
+ ```ts
174
+ import { getDeviceInfo, deviceToQuery, clearDeviceCache } from '@hlw-uni/mp-core';
175
+
176
+ const info = getDeviceInfo(); // 单例缓存,自动复用
177
+ const query = deviceToQuery(); // 转换为 URL query string
178
+ clearDeviceCache(); // 清除缓存(如切换账号)
179
+ ```
180
+
181
+ ## Components(easycom 方式使用)
182
+
183
+ 在 `pages.json` 中配置:
184
+
185
+ ```json
186
+ {
187
+ "easycom": {
188
+ "autoscan": true,
189
+ "regular": {
190
+ "^hlw-(.*)": "@hlw-uni/mp-core/components/$1.vue"
191
+ }
192
+ }
193
+ }
194
+ ```
195
+
196
+ 使用示例:
197
+
198
+ ```vue
199
+ <hlw-avatar :src="avatar" name="张三" size="medium" />
200
+ <hlw-empty text="暂无数据" />
201
+ <hlw-loading text="加载中..." />
202
+ <hlw-menu-list :items="menuItems" @click="onMenuClick" />
203
+ ```
204
+
205
+ ## 类型
206
+
207
+ ```ts
208
+ import type { RequestConfig, ApiResponse, PageResult, HlwMsg, HlwInstance, DeviceInfo } from '@hlw-uni/mp-core';
209
+ ```
210
+
211
+ 类型声明统一在 `@hlw-uni/mp-core/types/global.d.ts`,模板项目通过 `/// <reference types="@hlw-uni/mp-core/types/global" />` 引入即可获得完整类型提示。
212
+
213
+ ## 依赖
214
+
215
+ ```json
216
+ {
217
+ "peerDependencies": {
218
+ "pinia": ">=2.1.0",
219
+ "vue": ">=3.4.0"
220
+ }
221
+ }
222
+ ```
223
+
224
+ ## 构建
225
+
226
+ ```bash
227
+ npm run build # 构建产物到 dist/
228
+ npm run dev # 监听模式
229
+ ```
package/dist/app.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { createSSRApp } from '../node_modules/vue';
2
+
3
+ export interface InterceptorOptions {
4
+ /** 自动注入 Token 的 header 键名 */
5
+ tokenHeader?: string;
6
+ /** Token 来源函数(需平台自行提供) */
7
+ getToken?: () => string;
8
+ /** 登录失效时的处理函数(需平台自行提供) */
9
+ onUnauthorized?: () => void;
10
+ /** 接口业务错误码是否自动 toast */
11
+ autoToastError?: boolean;
12
+ }
13
+ export declare function useApp(): {
14
+ install: (app: Parameters<typeof createSSRApp>[0]) => {
15
+ app: any;
16
+ };
17
+ hlw: import('./hlw').HlwInstance;
18
+ http: any;
19
+ };
20
+ /**
21
+ * 注册默认拦截器
22
+ * @param options 可传入平台自定义的 token/unauthorized 处理
23
+ */
24
+ export declare function setupDefaultInterceptors(options?: InterceptorOptions & {
25
+ sigSecret?: string;
26
+ }): void;
@@ -0,0 +1,191 @@
1
+ .hlw-avatar[data-v-87dd25f7] {
2
+ border-radius: 50%;
3
+ overflow: hidden;
4
+ flex-shrink: 0;
5
+ }
6
+ .hlw-avatar--small[data-v-87dd25f7] {
7
+ width: 64rpx;
8
+ height: 64rpx;
9
+ }
10
+ .hlw-avatar--medium[data-v-87dd25f7] {
11
+ width: 88rpx;
12
+ height: 88rpx;
13
+ }
14
+ .hlw-avatar--large[data-v-87dd25f7] {
15
+ width: 120rpx;
16
+ height: 120rpx;
17
+ }
18
+ .hlw-avatar__image[data-v-87dd25f7] {
19
+ width: 100%;
20
+ height: 100%;
21
+ }
22
+ .hlw-avatar__placeholder[data-v-87dd25f7] {
23
+ width: 100%;
24
+ height: 100%;
25
+ background-color: #2979ff;
26
+ display: flex;
27
+ align-items: center;
28
+ justify-content: center;
29
+ }
30
+ .hlw-avatar__initial[data-v-87dd25f7] {
31
+ color: #ffffff;
32
+ font-size: 36rpx;
33
+ font-weight: 600;
34
+ }.hlw-empty[data-v-d78ade08] {
35
+ display: flex;
36
+ flex-direction: column;
37
+ align-items: center;
38
+ justify-content: center;
39
+ padding: 60rpx 0;
40
+ }
41
+ .hlw-empty__image[data-v-d78ade08] {
42
+ width: 200rpx;
43
+ height: 200rpx;
44
+ }
45
+ .hlw-empty__icon[data-v-d78ade08] {
46
+ font-size: 100rpx;
47
+ line-height: 1;
48
+ margin-bottom: 24rpx;
49
+ }
50
+ .hlw-empty__text[data-v-d78ade08] {
51
+ font-size: 28rpx;
52
+ color: #c0c4cc;
53
+ margin-top: 16rpx;
54
+ }.hlw-loading[data-v-6bf3a5a2] {
55
+ display: flex;
56
+ flex-direction: column;
57
+ align-items: center;
58
+ justify-content: center;
59
+ }
60
+ .hlw-loading__spinner[data-v-6bf3a5a2] {
61
+ position: relative;
62
+ width: 40px;
63
+ height: 40px;
64
+ }
65
+ .hlw-loading__dot[data-v-6bf3a5a2] {
66
+ position: absolute;
67
+ width: 8px;
68
+ height: 8px;
69
+ background-color: #2979ff;
70
+ border-radius: 50%;
71
+ animation: hlw-loading-fade-6bf3a5a2 1.2s infinite ease-in-out;
72
+ }
73
+ .hlw-loading__dot[data-v-6bf3a5a2]:nth-child(1) {
74
+ top: 0px;
75
+ left: 8px;
76
+ opacity: 1;
77
+ }
78
+ .hlw-loading__dot[data-v-6bf3a5a2]:nth-child(2) {
79
+ top: 0px;
80
+ left: 20px;
81
+ opacity: 0.92;
82
+ }
83
+ .hlw-loading__dot[data-v-6bf3a5a2]:nth-child(3) {
84
+ top: 0px;
85
+ left: 32px;
86
+ opacity: 0.84;
87
+ }
88
+ .hlw-loading__dot[data-v-6bf3a5a2]:nth-child(4) {
89
+ top: 10px;
90
+ left: 32px;
91
+ opacity: 0.76;
92
+ }
93
+ .hlw-loading__dot[data-v-6bf3a5a2]:nth-child(5) {
94
+ top: 20px;
95
+ left: 32px;
96
+ opacity: 0.68;
97
+ }
98
+ .hlw-loading__dot[data-v-6bf3a5a2]:nth-child(6) {
99
+ top: 20px;
100
+ left: 20px;
101
+ opacity: 0.6;
102
+ }
103
+ .hlw-loading__dot[data-v-6bf3a5a2]:nth-child(7) {
104
+ top: 20px;
105
+ left: 8px;
106
+ opacity: 0.52;
107
+ transform: scale(0.84);
108
+ }
109
+ .hlw-loading__dot[data-v-6bf3a5a2]:nth-child(8) {
110
+ top: 10px;
111
+ left: 8px;
112
+ opacity: 0.44;
113
+ transform: scale(0.76);
114
+ }
115
+ .hlw-loading__dot[data-v-6bf3a5a2]:nth-child(9) {
116
+ top: 10px;
117
+ left: 20px;
118
+ opacity: 0.36;
119
+ transform: scale(0.68);
120
+ }
121
+ .hlw-loading__dot[data-v-6bf3a5a2]:nth-child(10) {
122
+ top: 0px;
123
+ left: 20px;
124
+ opacity: 0.28;
125
+ transform: scale(0.6);
126
+ }
127
+ .hlw-loading__dot[data-v-6bf3a5a2]:nth-child(11) {
128
+ top: 0px;
129
+ left: 8px;
130
+ opacity: 0.2;
131
+ transform: scale(0.52);
132
+ }
133
+ .hlw-loading__dot[data-v-6bf3a5a2]:nth-child(12) {
134
+ top: 10px;
135
+ left: 8px;
136
+ opacity: 0.12;
137
+ transform: scale(0.44);
138
+ }
139
+ .hlw-loading__text[data-v-6bf3a5a2] {
140
+ margin-top: 12rpx;
141
+ font-size: 24rpx;
142
+ color: #606266;
143
+ }
144
+ @keyframes hlw-loading-fade-6bf3a5a2 {
145
+ 0%, 80%, 100% {
146
+ transform: scale(0.6);
147
+ opacity: 0.4;
148
+ }
149
+ 40% {
150
+ transform: scale(1);
151
+ opacity: 1;
152
+ }
153
+ }.hlw-menu-list[data-v-1dfe912b] {
154
+ background-color: #ffffff;
155
+ border-radius: 8rpx;
156
+ }
157
+ .hlw-menu-list__item[data-v-1dfe912b] {
158
+ display: flex;
159
+ align-items: center;
160
+ justify-content: space-between;
161
+ padding: 28rpx 32rpx;
162
+ border-bottom: 1rpx solid #ebedf0;
163
+ }
164
+ .hlw-menu-list__item[data-v-1dfe912b]:last-child {
165
+ border-bottom: none;
166
+ }
167
+ .hlw-menu-list__left[data-v-1dfe912b] {
168
+ display: flex;
169
+ align-items: center;
170
+ gap: 16rpx;
171
+ }
172
+ .hlw-menu-list__icon[data-v-1dfe912b] {
173
+ font-size: 40rpx;
174
+ }
175
+ .hlw-menu-list__label[data-v-1dfe912b] {
176
+ font-size: 28rpx;
177
+ color: #303133;
178
+ }
179
+ .hlw-menu-list__right[data-v-1dfe912b] {
180
+ display: flex;
181
+ align-items: center;
182
+ gap: 8rpx;
183
+ }
184
+ .hlw-menu-list__value[data-v-1dfe912b] {
185
+ font-size: 28rpx;
186
+ color: #606266;
187
+ }
188
+ .hlw-menu-list__arrow[data-v-1dfe912b] {
189
+ font-size: 32rpx;
190
+ color: #c0c4cc;
191
+ }
@@ -0,0 +1,67 @@
1
+ export interface DeviceInfo {
2
+ /** 小程序 appId */
3
+ appid: string;
4
+ /** 应用名称 */
5
+ app_name: string;
6
+ /** 小程序版本号(版本名称) */
7
+ app_version: string;
8
+ /** 小程序版本号(版本号) */
9
+ app_version_code: string;
10
+ /** 小程序来源渠道 */
11
+ app_channel: string;
12
+ /** 设备品牌。如:apple、huawei */
13
+ device_brand: string;
14
+ /** 设备型号 */
15
+ device_model: string;
16
+ /** 设备 ID */
17
+ device_id: string;
18
+ /** 设备类型:phone/pad/pc */
19
+ device_type: string;
20
+ /** 设备方向:portrait/landscape */
21
+ device_orientation: "portrait" | "landscape";
22
+ /** 手机品牌。H5 不支持 */
23
+ brand: string;
24
+ /** 手机型号 */
25
+ model: string;
26
+ /** 操作系统版本 */
27
+ system: string;
28
+ /** 操作系统版本(简写) */
29
+ os: string;
30
+ /** 设备像素比 */
31
+ pixel_ratio: number;
32
+ /** 屏幕宽度 (px) */
33
+ screen_width: number;
34
+ /** 屏幕高度 (px) */
35
+ screen_height: number;
36
+ /** 可用窗口宽度 (px) */
37
+ window_width: number;
38
+ /** 可用窗口高度 (px) */
39
+ window_height: number;
40
+ /** 状态栏高度 (px) */
41
+ status_bar_height: number;
42
+ /** 微信基础库版本 */
43
+ sdk_version: string;
44
+ /** 宿主名称。如:WeChat、alipay */
45
+ host_name: string;
46
+ /** 宿主版本。如:微信版本号 */
47
+ host_version: string;
48
+ /** 宿主语言 */
49
+ host_language: string;
50
+ /** 宿主主题:light/dark */
51
+ host_theme: string;
52
+ /** 平台类型 weapp/toutiao/h5 */
53
+ platform: string;
54
+ /** 客户端语言 */
55
+ language: string;
56
+ /** 客户端版本号 */
57
+ version: string;
58
+ }
59
+ export declare function useDevice(): any;
60
+ /**
61
+ * 把 deviceInfo 对象转成 URL query string(不含前导 ?)
62
+ */
63
+ export declare function deviceToQuery(): string;
64
+ /**
65
+ * 手动清除缓存(切换账号等场景可能需要)
66
+ */
67
+ export declare function clearDeviceCache(): void;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * useFormat — 格式化工具 composable
3
+ */
4
+ export declare function useFormat(): {
5
+ date: (date: Date | number | string, format?: string) => string;
6
+ fileSize: (bytes: number) => string;
7
+ phone: (value: string) => string;
8
+ money: (amount: number, decimals?: number, decPoint?: string, thousandsSep?: string) => string;
9
+ };
@@ -0,0 +1,3 @@
1
+ import { UploadAdapter } from './base';
2
+
3
+ export declare const alistAdapter: UploadAdapter;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 云存储上传适配器 — 上传上下文
3
+ */
4
+ /** 上传上下文 */
5
+ export interface UploadContext {
6
+ filePath: string;
7
+ fileName: string;
8
+ /** 云存储密钥凭证 */
9
+ credentials?: Record<string, string>;
10
+ /** 额外表单数据 */
11
+ extraData?: Record<string, string>;
12
+ }
13
+ /** 云存储适配器接口 */
14
+ export interface UploadAdapter {
15
+ /** 适配器名称 */
16
+ name: string;
17
+ /** 根据上下文构建表单数据 */
18
+ buildFormData(ctx: UploadContext): Record<string, string | number>;
19
+ }
@@ -0,0 +1,3 @@
1
+ import { UploadAdapter } from './base';
2
+
3
+ export declare const cosAdapter: UploadAdapter;
@@ -0,0 +1,13 @@
1
+ import { UploadAdapter } from './base';
2
+ /**
3
+ * 云存储上传适配器统一导出
4
+ */
5
+ export { cosAdapter } from './cos';
6
+ export { ossAdapter } from './oss';
7
+ export { qiniuAdapter } from './qiniu';
8
+ export { alistAdapter } from './alist';
9
+ export type { UploadAdapter, UploadContext } from './base';
10
+ /** 所有已注册的适配器 */
11
+ export declare const adapters: Record<string, UploadAdapter>;
12
+ /** 获取适配器,不存在则抛错 */
13
+ export declare function getAdapter(name: string): UploadAdapter;
@@ -0,0 +1,3 @@
1
+ import { UploadAdapter } from './base';
2
+
3
+ export declare const ossAdapter: UploadAdapter;
@@ -0,0 +1,3 @@
1
+ import { UploadAdapter } from './base';
2
+
3
+ export declare const qiniuAdapter: UploadAdapter;
@@ -0,0 +1,48 @@
1
+ import { ref } from '../../../node_modules/vue';
2
+ import { ApiResponse, RequestConfig, RequestInterceptor, ResponseInterceptor, ErrorInterceptor, UploadConfig, UploadResult } from './types';
3
+
4
+ /** 组件内请求返回的状态 */
5
+ export interface UseRequestReturn<T = unknown> {
6
+ loading: ReturnType<typeof ref<boolean>>;
7
+ data: ReturnType<typeof ref<T | null>>;
8
+ error: ReturnType<typeof ref<Error | null>>;
9
+ run: (config: RequestConfig) => Promise<ApiResponse<T>>;
10
+ get: (url: string, data?: unknown) => Promise<ApiResponse<T>>;
11
+ post: (url: string, data?: unknown) => Promise<ApiResponse<T>>;
12
+ put: (url: string, data?: unknown) => Promise<ApiResponse<T>>;
13
+ del: (url: string, data?: unknown) => Promise<ApiResponse<T>>;
14
+ }
15
+ export declare class HttpClient {
16
+ private _reqInterceptors;
17
+ private _resInterceptors;
18
+ private _errInterceptors;
19
+ private _baseURL;
20
+ private _defaultHeaders;
21
+ constructor(options?: {
22
+ baseURL?: string;
23
+ headers?: Record<string, string>;
24
+ });
25
+ /** 添加请求拦截器,返回取消函数 */
26
+ onRequest(fn: RequestInterceptor): () => void;
27
+ /** 添加响应拦截器 */
28
+ onResponse<T = unknown>(fn: ResponseInterceptor<T>): () => void;
29
+ /** 添加错误拦截器 */
30
+ onError(fn: ErrorInterceptor): () => void;
31
+ /**
32
+ * 全局请求
33
+ */
34
+ request<T = unknown>(config: RequestConfig): Promise<ApiResponse<T>>;
35
+ /**
36
+ * 组件内请求,返回带状态的 composable
37
+ */
38
+ useRequest<T = unknown>(): UseRequestReturn<T>;
39
+ /**
40
+ * 上传文件(策略模式)
41
+ */
42
+ upload(config: UploadConfig): Promise<UploadResult>;
43
+ private _buildUrl;
44
+ private _doRequest;
45
+ private _applyErrorInterceptors;
46
+ }
47
+ /** 全局 HTTP 实例 */
48
+ export declare const http: HttpClient;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * HTTP 模块统一导出
3
+ */
4
+ export { http, HttpClient } from './client';
5
+ export { useRequest, useUpload } from './useRequest';
6
+ export type { ApiResponse, PageResult, RequestConfig, RequestInterceptor, ResponseInterceptor, ErrorInterceptor, UploadConfig, UploadResult } from './types';
7
+ export type { UseRequestReturn } from './client';
8
+ export * from './adapters';
@@ -0,0 +1,51 @@
1
+ /**
2
+ * HTTP 类型定义
3
+ */
4
+ /** API 统一响应格式 */
5
+ export interface ApiResponse<T = unknown> {
6
+ code: number;
7
+ data: T;
8
+ message: string;
9
+ }
10
+ /** 分页数据 */
11
+ export interface PageResult<T = unknown> {
12
+ list: T[];
13
+ total: number;
14
+ page: number;
15
+ pageSize: number;
16
+ }
17
+ /** 请求配置 */
18
+ export interface RequestConfig {
19
+ url: string;
20
+ method?: "GET" | "POST" | "PUT" | "DELETE";
21
+ data?: unknown;
22
+ headers?: Record<string, string>;
23
+ timeout?: number;
24
+ }
25
+ /** 拦截器类型 */
26
+ export type RequestInterceptor = (config: RequestConfig) => RequestConfig | Promise<RequestConfig>;
27
+ export type ResponseInterceptor<T = unknown> = (res: ApiResponse<T>) => ApiResponse<T> | Promise<ApiResponse<T>>;
28
+ export type ErrorInterceptor = (err: Error) => void | Error | Promise<void | Error>;
29
+ /** 上传配置 */
30
+ export interface UploadConfig {
31
+ /** 上传接口地址 */
32
+ server: string;
33
+ /** 文件路径 */
34
+ filePath: string;
35
+ /** 文件名(可选,默认取 filePath) */
36
+ fileName?: string;
37
+ /** 上传类型:cos | oss | qiniu | alist */
38
+ type: string;
39
+ /** 云存储密钥凭证 */
40
+ credentials?: Record<string, string>;
41
+ /** 自定义请求头 */
42
+ header?: Record<string, string>;
43
+ /** 上传类型为 local 时,作为最终 server */
44
+ url?: string;
45
+ }
46
+ /** 上传结果 */
47
+ export interface UploadResult {
48
+ code: number;
49
+ msg: string;
50
+ data: string;
51
+ }