uview-pro 0.0.4 → 0.0.5
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/changelog.md +131 -0
- package/components/u-button/u-button.vue +101 -24
- package/components/u-city-select/u-city-select.vue +244 -0
- package/components/u-upload/u-upload.vue +11 -5
- package/libs/request/auto-http.ts +76 -0
- package/libs/request/uni-http.ts +128 -67
- package/package.json +5 -3
- package/readme.md +10 -6
package/changelog.md
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
## 0.0.5(2025-08-19)
|
|
2
|
+
|
|
3
|
+
### ✨ Features | 新功能
|
|
4
|
+
|
|
5
|
+
- 新增 u-city-select 城市选择器组件 ([0eb4806](https://gitee.com/anyup/uView-Pro/commit/0eb4806db3be39e1a6c6f33c9ea511d8445da884))
|
|
6
|
+
- 完善 u-button 的 open-type 支持类型 ([37c0db5](https://gitee.com/anyup/uView-Pro/commit/37c0db527258bca57dbd55d7013b633230489853))
|
|
7
|
+
|
|
8
|
+
### 🐛 Bug Fixes | Bug 修复
|
|
9
|
+
|
|
10
|
+
- u-upload 暴露 lists 属性 ([09f8424](https://gitee.com/anyup/uView-Pro/commit/09f8424774baaee3b6fc7a42458949f8d5903951))
|
|
11
|
+
- u-upload 深度监听文件列表变化并优化事件触发 ([a41a571](https://gitee.com/anyup/uView-Pro/commit/a41a5719ddf9d6793b78c55a13025bbdc88fdfe3))
|
|
12
|
+
|
|
13
|
+
### 🚀 Demos | 示例页面优化
|
|
14
|
+
|
|
15
|
+
- 优化关于页面布局和内容 ([ad5f6a4](https://gitee.com/anyup/uView-Pro/commit/ad5f6a47847999268b43b8c5dbf1a34cb8f70802))
|
|
16
|
+
- 删除分类数据文件 ([5ed7a11](https://gitee.com/anyup/uView-Pro/commit/5ed7a1113db58ff493ad606296a210358348affe))
|
|
17
|
+
- 重构 index list 页面 ([13d780e](https://gitee.com/anyup/uView-Pro/commit/13d780ea5acc4c8eed72062482735df826d4b37a))
|
|
18
|
+
- 更新商场菜单组件引用 ([a5f1bf3](https://gitee.com/anyup/uView-Pro/commit/a5f1bf3f256705d6cad028d60701b4b0544332de))
|
|
19
|
+
- 修改图片地址 ([c459893](https://gitee.com/anyup/uView-Pro/commit/c459893848936aa9a44e7bda3277ab1428109869))
|
|
20
|
+
- 重构 upload 上传组件示例页面 ([686831d](https://gitee.com/anyup/uView-Pro/commit/686831de357aca67bbf7015e2f0696cf6bf48164))
|
|
21
|
+
- 优化多个组件的代码结构和样式 ([f2af44c](https://gitee.com/anyup/uView-Pro/commit/f2af44ca1710334495e4c4fad99d04027b3788f8))
|
|
22
|
+
- 添加提交规范相关配置文件 git-cz/husky/changelog ([d93b816](https://gitee.com/anyup/uView-Pro/commit/d93b816a5a3e468c4bc45e3161d7c006cba5fbf6))
|
|
23
|
+
- 优化 deepClone 和 deepMerge 页面的结果展示 ([b0daa70](https://gitee.com/anyup/uView-Pro/commit/b0daa700b6a385e037d38dc1f10b3612596e2403))
|
|
24
|
+
- 新增优惠券模板 ([1b77762](https://gitee.com/anyup/uView-Pro/commit/1b777621615f7ebe9d83606d53650987c8b2c4e0))
|
|
25
|
+
- 更新 easycom 配置说明,一定要放在 custom 里,否则不生效 ([fc14bf9](https://gitee.com/anyup/uView-Pro/commit/fc14bf90cb77088d258e20e79e3d25820f37e97e))
|
|
26
|
+
- 添加模板示例页面 ([3336af4](https://gitee.com/anyup/uView-Pro/commit/3336af406161648d18578c988d9b3ad79b86059a))
|
|
27
|
+
- 新增模版相关页面 ([8925a02](https://gitee.com/anyup/uView-Pro/commit/8925a02f9fa88f4742d984f2ff02909afc6ad0d7))
|
|
28
|
+
- 重构 request 类,优化泛型支持 ([d7b2e6a](https://gitee.com/anyup/uView-Pro/commit/d7b2e6a224d96f717e5bdbaf09edb19b712ced47))
|
|
29
|
+
|
|
1
30
|
## 0.0.4(2025-08-14)
|
|
2
31
|
|
|
3
32
|
### 新增
|
|
@@ -31,3 +60,105 @@
|
|
|
31
60
|
- 兼容安卓,iOS,微信小程序,H5 等
|
|
32
61
|
- 详尽的文档支持,现代化的演示效果
|
|
33
62
|
- 按需引入,精简打包体积
|
|
63
|
+
|
|
64
|
+
### 基础组件(8)
|
|
65
|
+
|
|
66
|
+
- Color 色彩
|
|
67
|
+
- Icon 图标
|
|
68
|
+
- Image 图片
|
|
69
|
+
- Button 按钮
|
|
70
|
+
- Layout 布局
|
|
71
|
+
- Cell 单元格
|
|
72
|
+
- Badge 徽标数
|
|
73
|
+
- Tag 标签
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### 表单组件(15)
|
|
78
|
+
|
|
79
|
+
- Form 表单
|
|
80
|
+
- Calendar 日历
|
|
81
|
+
- Select 列选择器
|
|
82
|
+
- Keyboard 键盘
|
|
83
|
+
- Picker 选择器
|
|
84
|
+
- Rate 评分
|
|
85
|
+
- Search 搜索
|
|
86
|
+
- NumberBox 步进器
|
|
87
|
+
- Upload 上传
|
|
88
|
+
- VerificationCode 验证码倒计时
|
|
89
|
+
- Field 输入框
|
|
90
|
+
- Checkbox 复选框
|
|
91
|
+
- Radio 单选框
|
|
92
|
+
- Switch 开关选择器
|
|
93
|
+
- Slider 滑动选择器
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### 数据组件(4)
|
|
98
|
+
|
|
99
|
+
- Progress 进度条
|
|
100
|
+
- Table 表格
|
|
101
|
+
- CountDown 倒计时
|
|
102
|
+
- CountTo 数字滚动
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### 反馈组件(10)
|
|
107
|
+
|
|
108
|
+
- ActionSheet 操作菜单
|
|
109
|
+
- AlertTips 警告提示
|
|
110
|
+
- Toast 消息提示
|
|
111
|
+
- NoticeBar 滚动通知
|
|
112
|
+
- TopTips 顶部提示
|
|
113
|
+
- SwipeAction 滑动单元格
|
|
114
|
+
- Collapse 折叠面板
|
|
115
|
+
- Popup 弹出层
|
|
116
|
+
- Modal 模态框
|
|
117
|
+
- fullScreen 压窗屏
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### 布局组件(11)
|
|
122
|
+
|
|
123
|
+
- Line 线条
|
|
124
|
+
- Card 卡片
|
|
125
|
+
- Mask 遮罩层
|
|
126
|
+
- NoNetwork 无网络提示
|
|
127
|
+
- Grid 宫格布局
|
|
128
|
+
- Swiper 轮播图
|
|
129
|
+
- TimeLine 时间轴
|
|
130
|
+
- Skeleton 骨架屏
|
|
131
|
+
- Sticky 吸顶
|
|
132
|
+
- Waterfall 瀑布流
|
|
133
|
+
- Divider 分割线
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### 导航组件(11)
|
|
138
|
+
|
|
139
|
+
- Dropdown 下拉菜单
|
|
140
|
+
- Tabbar 底部导航栏
|
|
141
|
+
- BackTop 返回顶部
|
|
142
|
+
- Navbar 导航栏
|
|
143
|
+
- Tabs 标签
|
|
144
|
+
- TabsSwiper 全屏选项卡
|
|
145
|
+
- Subsection 分段器
|
|
146
|
+
- IndexList 索引列表
|
|
147
|
+
- Steps 步骤条
|
|
148
|
+
- Empty 内容为空
|
|
149
|
+
- Section 查看更多
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### 其他组件(8)
|
|
154
|
+
|
|
155
|
+
- MessageInput 验证码输入
|
|
156
|
+
- Loadmore 加载更多
|
|
157
|
+
- ReadMore 展开阅读更多
|
|
158
|
+
- LazyLoad 懒加载
|
|
159
|
+
- Gap 间隔槽
|
|
160
|
+
- Avatar 头像
|
|
161
|
+
- Link 超链接
|
|
162
|
+
- Loading 加载动画
|
|
163
|
+
|
|
164
|
+
---
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
:hover-stay-time="Number(hoverStayTime)"
|
|
16
16
|
:disabled="disabled"
|
|
17
17
|
:form-type="formType"
|
|
18
|
-
:open-type="openType"
|
|
18
|
+
:open-type="disabled || loading ? undefined : openType"
|
|
19
19
|
:app-parameter="appParameter"
|
|
20
20
|
:hover-stop-propagation="hoverStopPropagation"
|
|
21
21
|
:send-message-title="sendMessageTitle"
|
|
@@ -25,11 +25,15 @@
|
|
|
25
25
|
:session-from="sessionFrom"
|
|
26
26
|
:send-message-img="sendMessageImg"
|
|
27
27
|
:show-message-card="showMessageCard"
|
|
28
|
-
@
|
|
28
|
+
@getAuthorize="getAuthorize"
|
|
29
29
|
@getuserinfo="getuserinfo"
|
|
30
|
+
@contact="contact"
|
|
31
|
+
@getphonenumber="getphonenumber"
|
|
30
32
|
@error="error"
|
|
31
|
-
@opensetting="opensetting"
|
|
32
33
|
@launchapp="launchapp"
|
|
34
|
+
@opensetting="opensetting"
|
|
35
|
+
@chooseavatar="chooseavatar"
|
|
36
|
+
@agreeprivacyauthorization="agreeprivacyauthorization"
|
|
33
37
|
:style="[
|
|
34
38
|
customStyle,
|
|
35
39
|
{
|
|
@@ -57,7 +61,7 @@
|
|
|
57
61
|
</template>
|
|
58
62
|
|
|
59
63
|
<script setup lang="ts">
|
|
60
|
-
import { ref, computed, nextTick } from 'vue';
|
|
64
|
+
import { ref, computed, nextTick, type PropType } from 'vue';
|
|
61
65
|
import { $u } from '../../';
|
|
62
66
|
|
|
63
67
|
defineOptions({
|
|
@@ -74,7 +78,7 @@ defineOptions({
|
|
|
74
78
|
* @property {Boolean} plain 按钮是否镂空,背景色透明
|
|
75
79
|
* @property {Boolean} disabled 是否禁用
|
|
76
80
|
* @property {Boolean} hair-line 是否显示按钮的细边框(默认true)
|
|
77
|
-
* @property {
|
|
81
|
+
* @property {String} shape 按钮外观形状,见文档说明
|
|
78
82
|
* @property {Boolean} loading 按钮名称前是否带 loading 图标(App-nvue 平台,在 ios 上为雪花,Android上为圆圈)
|
|
79
83
|
* @property {String} form-type 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件
|
|
80
84
|
* @property {String} open-type 开放能力
|
|
@@ -83,23 +87,60 @@ defineOptions({
|
|
|
83
87
|
* @property {Number} hover-start-time 按住后多久出现点击态,单位毫秒
|
|
84
88
|
* @property {Number} hover-stay-time 手指松开后点击态保留时间,单位毫秒
|
|
85
89
|
* @property {Object} custom-style 对按钮的自定义样式,对象形式,见文档说明
|
|
90
|
+
* @property {String} app-parameter 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效
|
|
91
|
+
* @property {Boolean} hover-stop-propagation 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效
|
|
92
|
+
* @property {String} lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。只微信小程序有效
|
|
93
|
+
* @property {String} session-from 会话来源,open-type="contact"时有效。只微信小程序有效
|
|
94
|
+
* @property {String} send-message-title 会话内消息卡片标题,open-type="contact"时有效
|
|
95
|
+
* @property {String} send-message-path 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效
|
|
96
|
+
* @property {String} send-message-img 会话内消息卡片图片,open-type="contact"时有效
|
|
97
|
+
* @property {Boolean} show-message-card 是否显示会话内消息卡片,open-type="contact"时有效
|
|
98
|
+
* @property {Number|String} throttle-time 节流,一定时间内只能触发一次,单位毫秒
|
|
99
|
+
* @property {String} scope 支付宝小程序,当 open-type 为 getAuthorize 时有效。可选值:'phoneNumber' | 'userInfo'
|
|
86
100
|
* @event {Function} click 按钮点击
|
|
87
101
|
* @event {Function} getphonenumber open-type="getPhoneNumber"时有效
|
|
88
102
|
* @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,从返回参数的detail中获取到的值同uni.getUserInfo
|
|
89
103
|
* @event {Function} error 当使用开放能力时,发生错误的回调
|
|
90
104
|
* @event {Function} opensetting 在打开授权设置页并关闭后回调
|
|
91
105
|
* @event {Function} launchapp 打开 APP 成功的回调
|
|
106
|
+
* @event {Function} contact 客服消息回调
|
|
107
|
+
* @event {Function} chooseavatar 头像选择回调
|
|
108
|
+
* @event {Function} agreeprivacyauthorization 用户点击允许授权回调
|
|
92
109
|
* @example <u-button>月落</u-button>
|
|
93
110
|
*/
|
|
94
111
|
|
|
95
|
-
const emit = defineEmits
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
112
|
+
const emit = defineEmits(['click', 'getuserinfo', 'contact', 'getphonenumber', 'error', 'launchapp', 'opensetting', 'chooseavatar', 'agreeprivacyauthorization']);
|
|
113
|
+
|
|
114
|
+
type ButtonScope = 'phoneNumber' | 'userInfo';
|
|
115
|
+
|
|
116
|
+
type ButtonOpenType =
|
|
117
|
+
| 'feedback'
|
|
118
|
+
| 'share'
|
|
119
|
+
| 'getUserInfo'
|
|
120
|
+
| 'contact'
|
|
121
|
+
| 'getPhoneNumber'
|
|
122
|
+
| 'launchApp'
|
|
123
|
+
| 'openSetting'
|
|
124
|
+
| 'chooseAvatar'
|
|
125
|
+
| 'getAuthorize'
|
|
126
|
+
| 'lifestyle'
|
|
127
|
+
| 'contactShare'
|
|
128
|
+
| 'openGroupProfile'
|
|
129
|
+
| 'openGuildProfile'
|
|
130
|
+
| 'openPublicProfile'
|
|
131
|
+
| 'shareMessageToFriend'
|
|
132
|
+
| 'addFriend'
|
|
133
|
+
| 'addColorSign'
|
|
134
|
+
| 'addGroupApp'
|
|
135
|
+
| 'addToFavorites'
|
|
136
|
+
| 'chooseAddress'
|
|
137
|
+
| 'chooseInvoiceTitle'
|
|
138
|
+
| 'login'
|
|
139
|
+
| 'subscribe'
|
|
140
|
+
| 'favorite'
|
|
141
|
+
| 'watchLater'
|
|
142
|
+
| 'openProfile'
|
|
143
|
+
| 'agreePrivacyAuthorization';
|
|
103
144
|
|
|
104
145
|
const props = defineProps({
|
|
105
146
|
/** 是否细边框 */
|
|
@@ -116,8 +157,10 @@ const props = defineProps({
|
|
|
116
157
|
disabled: { type: Boolean, default: false },
|
|
117
158
|
/** 是否加载中 */
|
|
118
159
|
loading: { type: Boolean, default: false },
|
|
160
|
+
/** 支付宝小程序,当 open-type 为 getAuthorize 时有效 */
|
|
161
|
+
scope: { type: String as PropType<ButtonScope>, default: '' },
|
|
119
162
|
/** 开放能力,具体请看uniapp稳定关于button组件部分说明 */
|
|
120
|
-
openType: { type: String
|
|
163
|
+
openType: { type: String as PropType<ButtonOpenType>, default: '' },
|
|
121
164
|
/** 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件 */
|
|
122
165
|
formType: { type: String, default: '' },
|
|
123
166
|
/** 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效 */
|
|
@@ -278,32 +321,66 @@ function getElQuery(): Promise<any[]> {
|
|
|
278
321
|
/**
|
|
279
322
|
* open-type="getPhoneNumber"时有效
|
|
280
323
|
*/
|
|
281
|
-
function getphonenumber(
|
|
282
|
-
emit('getphonenumber',
|
|
324
|
+
function getphonenumber(event: any) {
|
|
325
|
+
emit('getphonenumber', event);
|
|
283
326
|
}
|
|
284
327
|
/**
|
|
285
328
|
* 用户点击该按钮时,会返回获取到的用户信息,从返回参数的detail中获取到的值同uni.getUserInfo
|
|
286
329
|
*/
|
|
287
|
-
function getuserinfo(
|
|
288
|
-
emit('getuserinfo',
|
|
330
|
+
function getuserinfo(event: any) {
|
|
331
|
+
emit('getuserinfo', event);
|
|
289
332
|
}
|
|
290
333
|
/**
|
|
291
334
|
* 当使用开放能力时,发生错误的回调
|
|
292
335
|
*/
|
|
293
|
-
function error(
|
|
294
|
-
emit('error',
|
|
336
|
+
function error(event: any) {
|
|
337
|
+
emit('error', event);
|
|
295
338
|
}
|
|
296
339
|
/**
|
|
297
340
|
* 在打开授权设置页并关闭后回调
|
|
298
341
|
*/
|
|
299
|
-
function opensetting(
|
|
300
|
-
emit('opensetting',
|
|
342
|
+
function opensetting(event: any) {
|
|
343
|
+
emit('opensetting', event);
|
|
301
344
|
}
|
|
302
345
|
/**
|
|
303
346
|
* 打开 APP 成功的回调
|
|
304
347
|
*/
|
|
305
|
-
function launchapp(
|
|
306
|
-
emit('launchapp',
|
|
348
|
+
function launchapp(event: any) {
|
|
349
|
+
emit('launchapp', event);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* 支付宝小程序授权
|
|
354
|
+
* @param event
|
|
355
|
+
*/
|
|
356
|
+
function getAuthorize(event: any) {
|
|
357
|
+
if (props.scope === 'phoneNumber') {
|
|
358
|
+
getphonenumber(event);
|
|
359
|
+
} else if (props.scope === 'userInfo') {
|
|
360
|
+
getuserinfo(event);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* 客服消息回调
|
|
366
|
+
* @param event
|
|
367
|
+
*/
|
|
368
|
+
function contact(event: any) {
|
|
369
|
+
emit('contact', event);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* 头像选择回调
|
|
373
|
+
* @param event
|
|
374
|
+
*/
|
|
375
|
+
function chooseavatar(event: any) {
|
|
376
|
+
emit('chooseavatar', event);
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* 用户点击允许授权回调
|
|
380
|
+
* @param event
|
|
381
|
+
*/
|
|
382
|
+
function agreeprivacyauthorization(event: any) {
|
|
383
|
+
emit('agreeprivacyauthorization', event);
|
|
307
384
|
}
|
|
308
385
|
</script>
|
|
309
386
|
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<u-popup
|
|
3
|
+
v-model="popupValue"
|
|
4
|
+
mode="bottom"
|
|
5
|
+
:popup="false"
|
|
6
|
+
:mask="true"
|
|
7
|
+
:closeable="true"
|
|
8
|
+
:safe-area-inset-bottom="true"
|
|
9
|
+
close-icon-color="#ffffff"
|
|
10
|
+
:z-index="uZIndex"
|
|
11
|
+
:maskCloseAble="props.maskCloseAble"
|
|
12
|
+
@close="close"
|
|
13
|
+
>
|
|
14
|
+
<u-tabs v-if="popupValue" :list="genTabsList" :is-scroll="true" :current="tabsIndex" @change="tabsChange" ref="tabs"></u-tabs>
|
|
15
|
+
<view class="area-box">
|
|
16
|
+
<view class="u-flex" :class="{ change: isChange }">
|
|
17
|
+
<!-- 省 -->
|
|
18
|
+
<view class="area-item">
|
|
19
|
+
<view class="u-padding-10 u-bg-gray" style="height: 100%">
|
|
20
|
+
<scroll-view :scroll-y="true" style="height: 100%">
|
|
21
|
+
<u-cell-group>
|
|
22
|
+
<u-cell-item v-for="(item, index) in provincesList" :title="item.label" :arrow="false" :index="index" :key="index" @click="provinceChange(index)">
|
|
23
|
+
<template v-if="isChooseP && province === index" #right-icon>
|
|
24
|
+
<u-icon size="34" name="checkbox-mark"></u-icon>
|
|
25
|
+
</template>
|
|
26
|
+
</u-cell-item>
|
|
27
|
+
</u-cell-group>
|
|
28
|
+
</scroll-view>
|
|
29
|
+
</view>
|
|
30
|
+
</view>
|
|
31
|
+
<!-- 市 -->
|
|
32
|
+
<view class="area-item">
|
|
33
|
+
<view class="u-padding-10 u-bg-gray" style="height: 100%">
|
|
34
|
+
<scroll-view :scroll-y="true" style="height: 100%">
|
|
35
|
+
<u-cell-group v-if="isChooseP">
|
|
36
|
+
<u-cell-item v-for="(item, index) in citys" :title="item.label" :arrow="false" :index="index" :key="index" @click="cityChange(index)">
|
|
37
|
+
<template v-if="isChooseC && city === index" #right-icon>
|
|
38
|
+
<u-icon size="34" name="checkbox-mark"></u-icon>
|
|
39
|
+
</template>
|
|
40
|
+
</u-cell-item>
|
|
41
|
+
</u-cell-group>
|
|
42
|
+
</scroll-view>
|
|
43
|
+
</view>
|
|
44
|
+
</view>
|
|
45
|
+
<!-- 区 -->
|
|
46
|
+
<view class="area-item">
|
|
47
|
+
<view class="u-padding-10 u-bg-gray" style="height: 100%">
|
|
48
|
+
<scroll-view :scroll-y="true" style="height: 100%">
|
|
49
|
+
<u-cell-group v-if="isChooseC">
|
|
50
|
+
<u-cell-item v-for="(item, index) in areas" :title="item.label" :arrow="false" :index="index" :key="index" @click="areaChange(index)">
|
|
51
|
+
<template v-if="isChooseA && area === index" #right-icon>
|
|
52
|
+
<u-icon size="34" name="checkbox-mark"></u-icon>
|
|
53
|
+
</template>
|
|
54
|
+
</u-cell-item>
|
|
55
|
+
</u-cell-group>
|
|
56
|
+
</scroll-view>
|
|
57
|
+
</view>
|
|
58
|
+
</view>
|
|
59
|
+
</view>
|
|
60
|
+
</view>
|
|
61
|
+
</u-popup>
|
|
62
|
+
</template>
|
|
63
|
+
|
|
64
|
+
<script setup lang="ts">
|
|
65
|
+
import { ref, computed, onMounted } from 'vue';
|
|
66
|
+
import provinces from '../../libs/util/province';
|
|
67
|
+
import citysData from '../../libs/util/city';
|
|
68
|
+
import areasData from '../../libs/util/area';
|
|
69
|
+
import type { PropType } from 'vue';
|
|
70
|
+
|
|
71
|
+
defineOptions({
|
|
72
|
+
name: 'u-city-select'
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* u-city-select 城市选择器
|
|
77
|
+
* @description 用于选择省、市、区三级行政区域,支持回显和自定义初始值。
|
|
78
|
+
* @property {Boolean} modelValue 控制弹窗显示与隐藏(v-model)
|
|
79
|
+
* @property {Array} defaultRegion 默认选中的省市区名称数组,如 ['广东省', '广州市', '天河区']
|
|
80
|
+
* @property {Array} areaCode 默认选中的省市区编码数组,如 ['440000', '440100', '440106']
|
|
81
|
+
* @property {Boolean} maskCloseAble 是否允许点击遮罩关闭弹窗(默认 true)
|
|
82
|
+
* @property {String|Number} zIndex 弹窗层级(默认 0,自动适配)
|
|
83
|
+
* @event update:modelValue v-model 绑定值变化时触发
|
|
84
|
+
* @event city-change 选择省市区后触发,返回选中的省市区对象
|
|
85
|
+
* @example <u-city-select v-model="show" :defaultRegion="['广东省','广州市','天河区']" @city-change="onChange"></u-city-select>
|
|
86
|
+
*/
|
|
87
|
+
|
|
88
|
+
// props 定义
|
|
89
|
+
const props = defineProps({
|
|
90
|
+
modelValue: { type: Boolean, default: false },
|
|
91
|
+
defaultRegion: { type: Array as PropType<string[]>, default: () => [] },
|
|
92
|
+
areaCode: { type: Array as PropType<string[]>, default: () => [] },
|
|
93
|
+
maskCloseAble: { type: Boolean, default: true },
|
|
94
|
+
zIndex: { type: [String, Number], default: 0 }
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// emits 定义
|
|
98
|
+
const emit = defineEmits(['update:modelValue', 'city-change']);
|
|
99
|
+
|
|
100
|
+
// 省市区选择相关响应式数据
|
|
101
|
+
const cityValue = ref('');
|
|
102
|
+
const isChooseP = ref(false); // 是否已选省
|
|
103
|
+
const province = ref(0); // 省下标
|
|
104
|
+
const provincesList = ref(provinces);
|
|
105
|
+
const isChooseC = ref(false); // 是否已选市
|
|
106
|
+
const city = ref(0); // 市下标
|
|
107
|
+
const citys = ref(citysData[0]);
|
|
108
|
+
const isChooseA = ref(false); // 是否已选区
|
|
109
|
+
const area = ref(0); // 区下标
|
|
110
|
+
const areas = ref(areasData[0][0]);
|
|
111
|
+
const tabsIndex = ref(0);
|
|
112
|
+
|
|
113
|
+
// v-model 双向绑定
|
|
114
|
+
const popupValue = computed({
|
|
115
|
+
get: () => props.modelValue,
|
|
116
|
+
set: val => emit('update:modelValue', val)
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// 是否切换到区级
|
|
120
|
+
const isChange = computed(() => tabsIndex.value > 1);
|
|
121
|
+
|
|
122
|
+
// 顶部 tab 列表
|
|
123
|
+
const genTabsList = computed(() => {
|
|
124
|
+
const tabsList = [{ name: '请选择' }];
|
|
125
|
+
if (isChooseP.value) {
|
|
126
|
+
tabsList[0].name = provincesList.value[province.value].label;
|
|
127
|
+
tabsList[1] = { name: '请选择' };
|
|
128
|
+
}
|
|
129
|
+
if (isChooseC.value) {
|
|
130
|
+
tabsList[1].name = citys.value[city.value].label;
|
|
131
|
+
tabsList[2] = { name: '请选择' };
|
|
132
|
+
}
|
|
133
|
+
if (isChooseA.value) {
|
|
134
|
+
tabsList[2].name = areas.value[area.value].label;
|
|
135
|
+
}
|
|
136
|
+
return tabsList;
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// z-index 计算
|
|
140
|
+
const uZIndex = computed(() => (props.zIndex ? props.zIndex : (uni as any).$u?.zIndex?.popup || 1075));
|
|
141
|
+
|
|
142
|
+
// 初始化选中项
|
|
143
|
+
function init() {
|
|
144
|
+
if (props.areaCode.length === 3) {
|
|
145
|
+
setProvince('', props.areaCode[0]);
|
|
146
|
+
setCity('', props.areaCode[1]);
|
|
147
|
+
setArea('', props.areaCode[2]);
|
|
148
|
+
} else if (props.defaultRegion.length === 3) {
|
|
149
|
+
setProvince(props.defaultRegion[0], '');
|
|
150
|
+
setCity(props.defaultRegion[1], '');
|
|
151
|
+
setArea(props.defaultRegion[2], '');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 选中省
|
|
156
|
+
function setProvince(label = '', value = '') {
|
|
157
|
+
provincesList.value.forEach((v, k) => {
|
|
158
|
+
if (value ? v.value == value : v.label == label) {
|
|
159
|
+
provinceChange(k);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
// 选中市
|
|
164
|
+
function setCity(label = '', value = '') {
|
|
165
|
+
citys.value.forEach((v, k) => {
|
|
166
|
+
if (value ? v.value == value : v.label == label) {
|
|
167
|
+
cityChange(k);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
// 选中区
|
|
172
|
+
function setArea(label = '', value = '') {
|
|
173
|
+
areas.value.forEach((v, k) => {
|
|
174
|
+
if (value ? v.value == value : v.label == label) {
|
|
175
|
+
isChooseA.value = true;
|
|
176
|
+
area.value = k;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 关闭弹窗
|
|
182
|
+
function close() {
|
|
183
|
+
emit('update:modelValue', false);
|
|
184
|
+
}
|
|
185
|
+
// tab 切换
|
|
186
|
+
function tabsChange(index: number) {
|
|
187
|
+
tabsIndex.value = index;
|
|
188
|
+
}
|
|
189
|
+
// 省点击
|
|
190
|
+
function provinceChange(index: number) {
|
|
191
|
+
isChooseP.value = true;
|
|
192
|
+
isChooseC.value = false;
|
|
193
|
+
isChooseA.value = false;
|
|
194
|
+
province.value = index;
|
|
195
|
+
citys.value = citysData[index];
|
|
196
|
+
tabsIndex.value = 1;
|
|
197
|
+
}
|
|
198
|
+
// 市点击
|
|
199
|
+
function cityChange(index: number) {
|
|
200
|
+
isChooseC.value = true;
|
|
201
|
+
isChooseA.value = false;
|
|
202
|
+
city.value = index;
|
|
203
|
+
areas.value = areasData[province.value][index];
|
|
204
|
+
tabsIndex.value = 2;
|
|
205
|
+
}
|
|
206
|
+
// 区点击
|
|
207
|
+
function areaChange(index: number) {
|
|
208
|
+
isChooseA.value = true;
|
|
209
|
+
area.value = index;
|
|
210
|
+
const result = {
|
|
211
|
+
province: provincesList.value[province.value],
|
|
212
|
+
city: citys.value[city.value],
|
|
213
|
+
area: areas.value[area.value]
|
|
214
|
+
};
|
|
215
|
+
emit('city-change', result);
|
|
216
|
+
close();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// 挂载时初始化
|
|
220
|
+
onMounted(init);
|
|
221
|
+
</script>
|
|
222
|
+
|
|
223
|
+
<style lang="scss">
|
|
224
|
+
.area-box {
|
|
225
|
+
width: 100%;
|
|
226
|
+
overflow: hidden;
|
|
227
|
+
height: 800rpx;
|
|
228
|
+
|
|
229
|
+
> view {
|
|
230
|
+
width: 150%;
|
|
231
|
+
transition: transform 0.3s ease-in-out 0s;
|
|
232
|
+
transform: translateX(0);
|
|
233
|
+
|
|
234
|
+
&.change {
|
|
235
|
+
transform: translateX(-33.3333333%);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.area-item {
|
|
240
|
+
width: 33.3333333%;
|
|
241
|
+
height: 800rpx;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
</style>
|
|
@@ -95,6 +95,8 @@ defineOptions({
|
|
|
95
95
|
* @event {Function} on-progress 图片上传过程中的进度变化过程触发
|
|
96
96
|
* @event {Function} on-uploaded 所有图片上传完毕触发
|
|
97
97
|
* @event {Function} on-choose-complete 每次选择图片后触发,只是让外部可以得知每次选择后,内部的文件列表
|
|
98
|
+
* @event {Function} on-choose-fail 文件选择失败时触发
|
|
99
|
+
* @event {Function} on-list-change 文件列表发生变化时触发
|
|
98
100
|
* @example <u-upload :action="action" :file-list="fileList" ></u-upload>
|
|
99
101
|
*/
|
|
100
102
|
|
|
@@ -193,13 +195,17 @@ watch(
|
|
|
193
195
|
!tmp && lists.value.push({ url: value.url, error: false, progress: 100 });
|
|
194
196
|
});
|
|
195
197
|
},
|
|
196
|
-
{ immediate: true }
|
|
198
|
+
{ immediate: true, deep: true }
|
|
197
199
|
);
|
|
198
200
|
|
|
199
201
|
// 监听 lists 变化,发出事件
|
|
200
|
-
watch(
|
|
201
|
-
|
|
202
|
-
|
|
202
|
+
watch(
|
|
203
|
+
lists,
|
|
204
|
+
n => {
|
|
205
|
+
emit('on-list-change', n, props.index);
|
|
206
|
+
},
|
|
207
|
+
{ deep: true }
|
|
208
|
+
);
|
|
203
209
|
|
|
204
210
|
/**
|
|
205
211
|
* 清除列表
|
|
@@ -502,7 +508,7 @@ function checkFileExt(file: any) {
|
|
|
502
508
|
return noArrowExt;
|
|
503
509
|
}
|
|
504
510
|
|
|
505
|
-
defineExpose({ clear, reUpload, selectFile, upload, retry, remove, doPreviewImage });
|
|
511
|
+
defineExpose({ clear, reUpload, selectFile, upload, retry, remove, doPreviewImage, lists });
|
|
506
512
|
</script>
|
|
507
513
|
|
|
508
514
|
<style lang="scss" scoped>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import deepMerge from '../function/deepMerge';
|
|
2
|
+
|
|
3
|
+
export function isFunction(f: any): boolean {
|
|
4
|
+
return typeof f === 'function';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function isPromise(p: any): boolean {
|
|
8
|
+
return !!(p && p.then && p.catch);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function isArray(arr: any) {
|
|
12
|
+
return Object.prototype.toString.call(arr) === '[object Array]';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 构建基础类
|
|
17
|
+
*/
|
|
18
|
+
class Builder<T> {
|
|
19
|
+
instance: any;
|
|
20
|
+
|
|
21
|
+
constructor(instance: any) {
|
|
22
|
+
this.instance = instance;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param urlConfig url 配置表
|
|
27
|
+
* @param extra 其他请求方法对象
|
|
28
|
+
* @returns Object
|
|
29
|
+
*/
|
|
30
|
+
dispatch(urlConfig: Record<string, any>, extra: Record<string, any> = {}): Record<string, any> {
|
|
31
|
+
const builder: Record<string, any> = {};
|
|
32
|
+
// 创建 API
|
|
33
|
+
Object.keys(urlConfig).forEach(name => {
|
|
34
|
+
builder[name] = this.use.bind(this, urlConfig[name]);
|
|
35
|
+
});
|
|
36
|
+
return { ...builder, ...extra };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 发送请求
|
|
40
|
+
* @param {*} urlConfig : url 配置表
|
|
41
|
+
* @demo urlConfig = { login: { url: '/user/login', method: 'GET', loading: true } }
|
|
42
|
+
* @param {*} config : 开放配置,用户主动配置的
|
|
43
|
+
* @demo api.login({ params: { username: "admin" } })
|
|
44
|
+
* @returns Promise
|
|
45
|
+
*/
|
|
46
|
+
use(urlConfig: Record<string, any>, config: Record<string, any> = {}): Promise<T> {
|
|
47
|
+
// 请求地址
|
|
48
|
+
let url = config?.url ?? urlConfig.url;
|
|
49
|
+
// 兼容 restful url,如果是使用url为function,则为restful格式
|
|
50
|
+
if (config.url && isFunction(config.url)) {
|
|
51
|
+
url = `${urlConfig.url}${config.url()}`;
|
|
52
|
+
}
|
|
53
|
+
// 请求类型,get,post,put,delete
|
|
54
|
+
const method = config?.method ?? urlConfig?.method ?? 'GET';
|
|
55
|
+
// 如果有自定义的工厂函数基础类
|
|
56
|
+
const options = { ...deepMerge(urlConfig, config), url, method };
|
|
57
|
+
if (isFunction(this.instance) || isPromise(this.instance)) {
|
|
58
|
+
return this.instance(options);
|
|
59
|
+
}
|
|
60
|
+
// 如果是使用的 instance
|
|
61
|
+
// 默认的请求基础类
|
|
62
|
+
return this.instance.request(options);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Http 基础类
|
|
68
|
+
*/
|
|
69
|
+
class AutoHttp {
|
|
70
|
+
static get Builder() {
|
|
71
|
+
return Builder;
|
|
72
|
+
}
|
|
73
|
+
constructor() {}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { AutoHttp };
|
package/libs/request/uni-http.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* 基于 Promise 对象实现更简单的 request 使用方式,支持请求和响应拦截
|
|
4
4
|
* @author anyup
|
|
5
5
|
*/
|
|
6
|
+
import deepMerge from '../function/deepMerge';
|
|
6
7
|
|
|
7
8
|
// 请求内容类型枚举
|
|
8
9
|
export enum ContentType {
|
|
@@ -20,28 +21,28 @@ export type HttpHeaderType = Record<string, string>;
|
|
|
20
21
|
// 请求配置类型
|
|
21
22
|
export interface HttpRequestConfig {
|
|
22
23
|
baseURL?: string;
|
|
23
|
-
url?: string;
|
|
24
|
+
url?: string | Function;
|
|
24
25
|
header?: HttpHeaderType;
|
|
25
|
-
data?:
|
|
26
|
+
data?: unknown;
|
|
26
27
|
method?: HttpMethod;
|
|
27
28
|
dataType?: string;
|
|
28
29
|
responseType?: string;
|
|
29
|
-
success?: (res:
|
|
30
|
-
fail?: (err:
|
|
31
|
-
complete?: (res:
|
|
32
|
-
[key: string]:
|
|
30
|
+
success?: (res: unknown) => void;
|
|
31
|
+
fail?: (err: unknown) => void;
|
|
32
|
+
complete?: (res: unknown) => void;
|
|
33
|
+
[key: string]: unknown;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
// 拦截器类型
|
|
36
|
-
export interface Interceptor<T =
|
|
37
|
-
handler?: (arg: T, P: typeof Promise) =>
|
|
38
|
-
onerror?: (arg: T, P: typeof Promise) =>
|
|
39
|
-
complete?: (arg: T, P: typeof Promise) =>
|
|
37
|
+
export interface Interceptor<T = unknown> {
|
|
38
|
+
handler?: (arg: T, P: typeof Promise) => unknown;
|
|
39
|
+
onerror?: (arg: T, P: typeof Promise) => unknown;
|
|
40
|
+
complete?: (arg: T, P: typeof Promise) => unknown;
|
|
40
41
|
use: (...args: any[]) => void;
|
|
41
42
|
lock?: () => void;
|
|
42
43
|
unlock?: () => void;
|
|
43
44
|
clear?: () => void;
|
|
44
|
-
p?: Promise<
|
|
45
|
+
p?: Promise<unknown> | null;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
/**
|
|
@@ -81,15 +82,17 @@ export class Builder {
|
|
|
81
82
|
/**
|
|
82
83
|
* 发送请求
|
|
83
84
|
*/
|
|
84
|
-
use(urlConfig: Record<string, any>, data?:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
85
|
+
use<T = unknown>(urlConfig: Record<string, any>, data?: unknown, config: HttpRequestConfig = {}): Promise<T> {
|
|
86
|
+
// 请求地址
|
|
87
|
+
let url = config?.url ?? urlConfig.url;
|
|
88
|
+
// 兼容 restful url,如果是使用url为function,则为restful格式
|
|
89
|
+
if (config.url && typeof config.url === 'function') {
|
|
90
|
+
url = `${urlConfig.url}${config.url()}`;
|
|
91
|
+
}
|
|
92
|
+
// 请求类型,get,post,put,delete
|
|
93
|
+
const method = config?.method ?? urlConfig?.method ?? 'GET';
|
|
94
|
+
const options = { ...deepMerge(urlConfig, config), url, method };
|
|
95
|
+
return this.http.request<T>(options);
|
|
93
96
|
}
|
|
94
97
|
}
|
|
95
98
|
|
|
@@ -154,11 +157,13 @@ export class Http {
|
|
|
154
157
|
/**
|
|
155
158
|
* 设置 data
|
|
156
159
|
*/
|
|
157
|
-
setData(data:
|
|
160
|
+
setData(data: unknown) {
|
|
158
161
|
if (isArray(data)) {
|
|
159
162
|
this.config.data = data;
|
|
163
|
+
} else if (isObject(data) && isObject(this.config.data)) {
|
|
164
|
+
this.config.data = { ...(this.config.data as object), ...(data as object) };
|
|
160
165
|
} else {
|
|
161
|
-
this.config.data =
|
|
166
|
+
this.config.data = data;
|
|
162
167
|
}
|
|
163
168
|
return this;
|
|
164
169
|
}
|
|
@@ -176,7 +181,7 @@ export class Http {
|
|
|
176
181
|
* @returns Promise
|
|
177
182
|
* 说明:配置优先级 实时传递的 options > 公共配置的 config
|
|
178
183
|
*/
|
|
179
|
-
request<T =
|
|
184
|
+
request<T = unknown>(options: HttpRequestConfig = {}): Promise<T> {
|
|
180
185
|
if (!options) options = {};
|
|
181
186
|
// 请求体
|
|
182
187
|
const data = options.data || {};
|
|
@@ -191,8 +196,10 @@ export class Http {
|
|
|
191
196
|
// 请求体:优先级为:实时传递的 > 公共配置的
|
|
192
197
|
if (isArray(data)) {
|
|
193
198
|
options.data = data;
|
|
199
|
+
} else if (isObject(data) && isObject(this.config.data)) {
|
|
200
|
+
options.data = { ...(this.config.data as object), ...(data as object) };
|
|
194
201
|
} else {
|
|
195
|
-
options.data =
|
|
202
|
+
options.data = data;
|
|
196
203
|
}
|
|
197
204
|
|
|
198
205
|
// 拦截器处理
|
|
@@ -201,11 +208,11 @@ export class Http {
|
|
|
201
208
|
const responseInterceptor = interceptors.response;
|
|
202
209
|
const requestInterceptorHandler = requestInterceptor.handler;
|
|
203
210
|
|
|
204
|
-
return new Promise((resolve: (value: T) => void, reject: (reason?:
|
|
205
|
-
function isPromise(p:
|
|
206
|
-
return p && typeof p.then === 'function' && typeof p.catch === 'function';
|
|
211
|
+
return new Promise((resolve: (value: T) => void, reject: (reason?: unknown) => void) => {
|
|
212
|
+
function isPromise(p: unknown): p is Promise<unknown> {
|
|
213
|
+
return !!p && typeof (p as any).then === 'function' && typeof (p as any).catch === 'function';
|
|
207
214
|
}
|
|
208
|
-
function enqueueIfLocked(promise: Promise<
|
|
215
|
+
function enqueueIfLocked(promise: Promise<unknown> | null | undefined, callback: () => void) {
|
|
209
216
|
if (promise) {
|
|
210
217
|
promise.then(() => {
|
|
211
218
|
callback();
|
|
@@ -214,31 +221,27 @@ export class Http {
|
|
|
214
221
|
callback();
|
|
215
222
|
}
|
|
216
223
|
}
|
|
217
|
-
function onresult(
|
|
218
|
-
handler: ((arg: any, P: typeof Promise) => any) | undefined,
|
|
219
|
-
response: any,
|
|
220
|
-
type: number
|
|
221
|
-
) {
|
|
224
|
+
function onresult(handler: ((arg: unknown, P: typeof Promise) => unknown) | undefined, response: unknown, type: number) {
|
|
222
225
|
enqueueIfLocked(responseInterceptor.p, function () {
|
|
223
226
|
if (handler) {
|
|
224
|
-
response.request = options;
|
|
227
|
+
(response as any).request = options;
|
|
225
228
|
const ret = handler.call(responseInterceptor, response, Promise);
|
|
226
229
|
response = ret === undefined ? response : ret;
|
|
227
230
|
}
|
|
228
231
|
if (!isPromise(response)) {
|
|
229
232
|
response = Promise[type === 0 ? 'resolve' : 'reject'](response);
|
|
230
233
|
}
|
|
231
|
-
response
|
|
232
|
-
.then((d:
|
|
233
|
-
resolve(d.data);
|
|
234
|
+
(response as Promise<unknown>)
|
|
235
|
+
.then((d: unknown) => {
|
|
236
|
+
resolve((d as any).data as T);
|
|
234
237
|
})
|
|
235
|
-
.catch((e:
|
|
238
|
+
.catch((e: unknown) => {
|
|
236
239
|
reject(e);
|
|
237
240
|
});
|
|
238
241
|
});
|
|
239
242
|
}
|
|
240
|
-
options.complete = (response:
|
|
241
|
-
const statusCode: number = response.statusCode;
|
|
243
|
+
(options as any).complete = (response: unknown) => {
|
|
244
|
+
const statusCode: number = (response as any).statusCode;
|
|
242
245
|
let type = 0;
|
|
243
246
|
if ((statusCode >= 200 && statusCode < 300) || statusCode === 304) {
|
|
244
247
|
type = 0;
|
|
@@ -251,26 +254,32 @@ export class Http {
|
|
|
251
254
|
};
|
|
252
255
|
enqueueIfLocked(requestInterceptor.p, () => {
|
|
253
256
|
options = Object.assign({}, this.config, options);
|
|
254
|
-
options.requestId = new Date().getTime();
|
|
255
|
-
let ret:
|
|
257
|
+
(options as any).requestId = new Date().getTime();
|
|
258
|
+
let ret: unknown = options;
|
|
256
259
|
if (requestInterceptorHandler) {
|
|
257
260
|
ret = requestInterceptorHandler.call(requestInterceptor, options, Promise) || options;
|
|
258
261
|
}
|
|
259
262
|
if (!isPromise(ret)) {
|
|
260
263
|
ret = Promise.resolve(ret);
|
|
261
264
|
}
|
|
262
|
-
ret.then(
|
|
263
|
-
(d:
|
|
265
|
+
(ret as Promise<unknown>).then(
|
|
266
|
+
(d: unknown) => {
|
|
264
267
|
if (d === options) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
268
|
+
// 这里断言为 any,兼容 baseURL、restURL、url、method 等属性
|
|
269
|
+
const req = d as any;
|
|
270
|
+
req.url = req.url && req.url.indexOf('http') !== 0 ? req.baseURL + req.url : req.url;
|
|
271
|
+
req.url = req.restURL ? req.url + req.restURL : req.url;
|
|
272
|
+
req.method = req.method.toUpperCase();
|
|
273
|
+
if (req.method === 'UPLOAD') {
|
|
274
|
+
uni.uploadFile(req);
|
|
275
|
+
} else {
|
|
276
|
+
uni.request(req);
|
|
277
|
+
}
|
|
269
278
|
} else {
|
|
270
|
-
resolve(d);
|
|
279
|
+
resolve(d as T);
|
|
271
280
|
}
|
|
272
281
|
},
|
|
273
|
-
(err:
|
|
282
|
+
(err: unknown) => {
|
|
274
283
|
reject(err);
|
|
275
284
|
}
|
|
276
285
|
);
|
|
@@ -281,29 +290,81 @@ export class Http {
|
|
|
281
290
|
/**
|
|
282
291
|
* 并发请求
|
|
283
292
|
*/
|
|
284
|
-
all<T =
|
|
293
|
+
all<T = unknown>(promises: Promise<T>[]): Promise<T[]> {
|
|
285
294
|
return Promise.all(promises);
|
|
286
295
|
}
|
|
287
296
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
+
/**
|
|
298
|
+
* GET 请求
|
|
299
|
+
*/
|
|
300
|
+
get<T = unknown>(url: string, data?: unknown, option?: HttpRequestConfig): Promise<T> {
|
|
301
|
+
return this.request<T>(merge({ url, data, method: 'GET' }, option));
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* POST 请求
|
|
305
|
+
*/
|
|
306
|
+
post<T = unknown>(url: string, data?: unknown, option?: HttpRequestConfig): Promise<T> {
|
|
307
|
+
return this.request<T>(merge({ url, data, method: 'POST' }, option));
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* PUT 请求
|
|
311
|
+
*/
|
|
312
|
+
put<T = unknown>(url: string, data?: unknown, option?: HttpRequestConfig): Promise<T> {
|
|
313
|
+
return this.request<T>(merge({ url, data, method: 'PUT' }, option));
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* PATCH 请求
|
|
317
|
+
*/
|
|
318
|
+
patch<T = unknown>(url: string, data?: unknown, option?: HttpRequestConfig): Promise<T> {
|
|
319
|
+
return this.request<T>(merge({ url, data, method: 'PATCH' }, option));
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* HEAD 请求
|
|
323
|
+
*/
|
|
324
|
+
head<T = unknown>(url: string, data?: unknown, option?: HttpRequestConfig): Promise<T> {
|
|
325
|
+
return this.request<T>(merge({ url, data, method: 'HEAD' }, option));
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* DELETE 请求
|
|
329
|
+
*/
|
|
330
|
+
delete<T = unknown>(url: string, data?: unknown, option?: HttpRequestConfig): Promise<T> {
|
|
331
|
+
return this.request<T>(merge({ url, data, method: 'DELETE' }, option));
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* UPLOAD 文件上传
|
|
335
|
+
*/
|
|
336
|
+
upload<T = unknown>(url: string, data?: unknown, option?: HttpRequestConfig): Promise<T> {
|
|
337
|
+
return this.request<T>(merge({ url, data, method: 'UPLOAD' }, option));
|
|
338
|
+
}
|
|
297
339
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
340
|
+
/**
|
|
341
|
+
* 拦截器锁定
|
|
342
|
+
*/
|
|
343
|
+
lock(): void {
|
|
344
|
+
const fn = this.interceptors.request.lock;
|
|
301
345
|
if (typeof fn === 'function') {
|
|
302
|
-
|
|
303
|
-
(fn as () => void).call(this.interceptors.request);
|
|
346
|
+
fn.call(this.interceptors.request);
|
|
304
347
|
}
|
|
305
|
-
}
|
|
306
|
-
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* 拦截器解锁
|
|
351
|
+
*/
|
|
352
|
+
unlock(): void {
|
|
353
|
+
const fn = this.interceptors.request.unlock;
|
|
354
|
+
if (typeof fn === 'function') {
|
|
355
|
+
fn.call(this.interceptors.request);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* 拦截器清空
|
|
360
|
+
*/
|
|
361
|
+
clear(): void {
|
|
362
|
+
const fn = this.interceptors.request.clear;
|
|
363
|
+
if (typeof fn === 'function') {
|
|
364
|
+
fn.call(this.interceptors.request);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
307
368
|
|
|
308
369
|
// 数据合并
|
|
309
370
|
function merge(a: any, b: any): any {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "uview-pro",
|
|
3
3
|
"name": "uview-pro",
|
|
4
|
-
"displayName": "uView Pro是uni-app
|
|
5
|
-
"version": "0.0.
|
|
6
|
-
"description": "uView Pro,是uni-app
|
|
4
|
+
"displayName": "uView Pro是uni-app全面支持Vue3+TS的uni-app生态框架,70+精选组件",
|
|
5
|
+
"version": "0.0.5",
|
|
6
|
+
"description": "uView Pro,是uni-app全面支持Vue3的uni-app生态框架,70+精选组件已使用TypeScript重构,已全面支持uni-app Vue3.0",
|
|
7
7
|
"main": "index.ts",
|
|
8
8
|
"module": "index.ts",
|
|
9
9
|
"browser": "index.ts",
|
|
@@ -58,6 +58,8 @@
|
|
|
58
58
|
"app-vue": "y",
|
|
59
59
|
"app-nvue": "n",
|
|
60
60
|
"app-uvue": "n",
|
|
61
|
+
"app-android": "y",
|
|
62
|
+
"app-ios": "y",
|
|
61
63
|
"app-harmony": "u"
|
|
62
64
|
},
|
|
63
65
|
"H5-mobile": {
|
package/readme.md
CHANGED
|
@@ -69,7 +69,7 @@ uView Pro QQ 交流群: [点击进入](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027
|
|
|
69
69
|
|
|
70
70
|
<table class="table">
|
|
71
71
|
<tr>
|
|
72
|
-
<td><img src="https://ik.imagekit.io/anyup/images/social/weixin-chat.png" width="250" height="345" ></td>
|
|
72
|
+
<td><img src="https://ik.imagekit.io/anyup/images/social/weixin-chat.png?updatedAt=1755597368053" width="250" height="345" ></td>
|
|
73
73
|
<td><img src="https://ik.imagekit.io/anyup/images/social/qq-chat.png" width="250" height="345" ></td>
|
|
74
74
|
</tr>
|
|
75
75
|
<tr>
|
|
@@ -112,6 +112,7 @@ pnpm add uview-pro
|
|
|
112
112
|
import { createSSRApp } from 'vue';
|
|
113
113
|
// npm安装方式
|
|
114
114
|
import uViewPro from 'uview-pro';
|
|
115
|
+
|
|
115
116
|
// uni_modules安装方式
|
|
116
117
|
// import uViewPro from '@/uni_modules/uview-pro';
|
|
117
118
|
|
|
@@ -154,11 +155,14 @@ export function createApp() {
|
|
|
154
155
|
// pages.json
|
|
155
156
|
{
|
|
156
157
|
"easycom": {
|
|
157
|
-
//
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
// 注意一定要放在custom里,否则无效,https://ask.dcloud.net.cn/question/131175
|
|
159
|
+
"custom": {
|
|
160
|
+
// uni_modules安装的方式需要前面的"@/uni_modules/",npm安装的方式无需"@/",以下方式任选其一
|
|
161
|
+
// npm安装方式
|
|
162
|
+
"^u-(.*)": "uview-pro/components/u-$1/u-$1.vue"
|
|
163
|
+
// uni_modules安装方式
|
|
164
|
+
// "^u-(.*)": "@/uni_modules/uview-pro/components/u-$1/u-$1.vue"
|
|
165
|
+
}
|
|
162
166
|
},
|
|
163
167
|
// 此为本身已有的内容
|
|
164
168
|
"pages": [
|