@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 +229 -0
- package/dist/app.d.ts +26 -0
- package/dist/assets/index.css +191 -0
- package/dist/composables/device/index.d.ts +67 -0
- package/dist/composables/format/index.d.ts +9 -0
- package/dist/composables/http/adapters/alist.d.ts +3 -0
- package/dist/composables/http/adapters/base.d.ts +19 -0
- package/dist/composables/http/adapters/cos.d.ts +3 -0
- package/dist/composables/http/adapters/index.d.ts +13 -0
- package/dist/composables/http/adapters/oss.d.ts +3 -0
- package/dist/composables/http/adapters/qiniu.d.ts +3 -0
- package/dist/composables/http/client.d.ts +48 -0
- package/dist/composables/http/index.d.ts +8 -0
- package/dist/composables/http/types.d.ts +51 -0
- package/dist/composables/http/useRequest.d.ts +36 -0
- package/dist/composables/index.d.ts +12 -0
- package/dist/composables/loading/index.d.ts +7 -0
- package/dist/composables/msg/index.d.ts +33 -0
- package/dist/composables/page-meta/index.d.ts +15 -0
- package/dist/composables/refs/index.d.ts +4 -0
- package/dist/composables/storage/index.d.ts +13 -0
- package/dist/composables/validate/index.d.ts +12 -0
- package/dist/hlw.d.ts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +310 -0
- package/dist/index.mjs +309 -0
- package/package.json +39 -0
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,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,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,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
|
+
}
|