muzhiyu-ui 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 +202 -0
- package/components/muzhiyu/mu-action-sheet/mu-action-sheet.vue +335 -0
- package/components/muzhiyu/mu-alert/mu-alert.vue +220 -0
- package/components/muzhiyu/mu-back-top/mu-back-top.vue +161 -0
- package/components/muzhiyu/mu-badge/mu-badge.vue +150 -0
- package/components/muzhiyu/mu-barcode/mu-barcode.vue +100 -0
- package/components/muzhiyu/mu-blank/mu-blank.vue +30 -0
- package/components/muzhiyu/mu-bottom-nav/mu-bottom-nav.vue +331 -0
- package/components/muzhiyu/mu-bubble/mu-bubble.vue +316 -0
- package/components/muzhiyu/mu-button/mu-button.vue +431 -0
- package/components/muzhiyu/mu-calendar/mu-calendar.vue +429 -0
- package/components/muzhiyu/mu-car-input/mu-car-input.vue +209 -0
- package/components/muzhiyu/mu-card/mu-card.vue +317 -0
- package/components/muzhiyu/mu-cascader/mu-cascader.vue +336 -0
- package/components/muzhiyu/mu-cell/mu-cell.vue +368 -0
- package/components/muzhiyu/mu-checkbox/mu-checkbox.vue +116 -0
- package/components/muzhiyu/mu-checkbox-group/mu-checkbox-group.vue +40 -0
- package/components/muzhiyu/mu-code-input/mu-code-input.vue +264 -0
- package/components/muzhiyu/mu-collapse/mu-collapse.vue +316 -0
- package/components/muzhiyu/mu-color-picker/mu-color-picker.vue +466 -0
- package/components/muzhiyu/mu-config/index.js +34 -0
- package/components/muzhiyu/mu-config/mu-config.vue +54 -0
- package/components/muzhiyu/mu-countdown/mu-countdown.vue +338 -0
- package/components/muzhiyu/mu-cropper/mu-cropper.vue +415 -0
- package/components/muzhiyu/mu-date-picker/mu-date-picker.vue +290 -0
- package/components/muzhiyu/mu-datetime/mu-datetime.vue +262 -0
- package/components/muzhiyu/mu-divider/mu-divider.vue +229 -0
- package/components/muzhiyu/mu-drawer/mu-drawer.vue +172 -0
- package/components/muzhiyu/mu-dropdown/mu-dropdown.vue +215 -0
- package/components/muzhiyu/mu-dropdown-top/mu-dropdown-top.vue +243 -0
- package/components/muzhiyu/mu-empty/mu-empty.vue +217 -0
- package/components/muzhiyu/mu-fab/mu-fab.vue +324 -0
- package/components/muzhiyu/mu-footer/mu-footer.vue +21 -0
- package/components/muzhiyu/mu-form/mu-form.vue +170 -0
- package/components/muzhiyu/mu-grid/mu-grid.vue +95 -0
- package/components/muzhiyu/mu-grid-item/mu-grid-item.vue +247 -0
- package/components/muzhiyu/mu-html/mu-html.vue +145 -0
- package/components/muzhiyu/mu-icon/mu-icon.vue +822 -0
- package/components/muzhiyu/mu-image-grid/mu-image-grid.vue +225 -0
- package/components/muzhiyu/mu-image-preview/mu-image-preview.vue +286 -0
- package/components/muzhiyu/mu-index-list/mu-index-list.vue +381 -0
- package/components/muzhiyu/mu-input/mu-input.vue +570 -0
- package/components/muzhiyu/mu-input-number/mu-input-number.vue +193 -0
- package/components/muzhiyu/mu-keyboard/mu-keyboard.vue +415 -0
- package/components/muzhiyu/mu-list/mu-list.vue +89 -0
- package/components/muzhiyu/mu-loading/mu-loading.vue +124 -0
- package/components/muzhiyu/mu-loading-page/mu-loading-page.vue +529 -0
- package/components/muzhiyu/mu-loadmore/mu-loadmore.vue +26 -0
- package/components/muzhiyu/mu-modal/mu-modal.vue +298 -0
- package/components/muzhiyu/mu-navbar/mu-navbar.vue +223 -0
- package/components/muzhiyu/mu-nomore/mu-nomore.vue +107 -0
- package/components/muzhiyu/mu-notice-bar/mu-notice-bar.vue +284 -0
- package/components/muzhiyu/mu-notify/mu-notify.vue +202 -0
- package/components/muzhiyu/mu-overlay/mu-overlay.vue +94 -0
- package/components/muzhiyu/mu-pagination/mu-pagination.vue +330 -0
- package/components/muzhiyu/mu-password-input/mu-password-input.vue +119 -0
- package/components/muzhiyu/mu-picker/mu-picker.vue +297 -0
- package/components/muzhiyu/mu-popup/mu-popup.vue +297 -0
- package/components/muzhiyu/mu-progress/mu-progress.vue +156 -0
- package/components/muzhiyu/mu-pull-refresh/mu-pull-refresh.vue +54 -0
- package/components/muzhiyu/mu-qrcode/mu-qrcode.vue +340 -0
- package/components/muzhiyu/mu-qrcode/qrcode.js +2237 -0
- package/components/muzhiyu/mu-radio/mu-radio.vue +125 -0
- package/components/muzhiyu/mu-radio-group/mu-radio-group.vue +37 -0
- package/components/muzhiyu/mu-rate/mu-rate.vue +103 -0
- package/components/muzhiyu/mu-search/mu-search.vue +320 -0
- package/components/muzhiyu/mu-section/mu-section.vue +206 -0
- package/components/muzhiyu/mu-select/mu-select.vue +440 -0
- package/components/muzhiyu/mu-share-sheet/mu-share-sheet.vue +269 -0
- package/components/muzhiyu/mu-sidebar/mu-sidebar.vue +304 -0
- package/components/muzhiyu/mu-signature/mu-signature.vue +449 -0
- package/components/muzhiyu/mu-skeleton/mu-skeleton.vue +225 -0
- package/components/muzhiyu/mu-slider/mu-slider.vue +228 -0
- package/components/muzhiyu/mu-space/mu-space.vue +84 -0
- package/components/muzhiyu/mu-steps/mu-steps.vue +311 -0
- package/components/muzhiyu/mu-sticky/mu-sticky.vue +57 -0
- package/components/muzhiyu/mu-swipe-cell/mu-swipe-cell.vue +281 -0
- package/components/muzhiyu/mu-swiper/mu-swiper.vue +107 -0
- package/components/muzhiyu/mu-switch/mu-switch.vue +99 -0
- package/components/muzhiyu/mu-tabbar/mu-tabbar.vue +382 -0
- package/components/muzhiyu/mu-table/mu-table.vue +420 -0
- package/components/muzhiyu/mu-tabs/mu-tabs.vue +339 -0
- package/components/muzhiyu/mu-tag/mu-tag.vue +65 -0
- package/components/muzhiyu/mu-text-ellipsis/mu-text-ellipsis.vue +54 -0
- package/components/muzhiyu/mu-timeline/mu-timeline.vue +166 -0
- package/components/muzhiyu/mu-tips/mu-tips.vue +36 -0
- package/components/muzhiyu/mu-toast/mu-toast.vue +151 -0
- package/components/muzhiyu/mu-transfer/mu-transfer.vue +114 -0
- package/components/muzhiyu/mu-tree/mu-tree.vue +263 -0
- package/components/muzhiyu/mu-upload/mu-upload.vue +415 -0
- package/components/muzhiyu/mu-waterfall/mu-waterfall.vue +321 -0
- package/components/muzhiyu/mu-watermark/mu-watermark.vue +60 -0
- package/index.js +83 -0
- package/package.json +38 -0
- package/utils/index.js +600 -0
- package/utils/request.js +265 -0
package/utils/request.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MuZhiYu UI 极速网络请求客户端 (Enterprise Uni.Request HTTP Client)
|
|
3
|
+
* 支持请求/响应拦截器、Token 自动读取注入、HTTP/业务 Code 拦截、401 自动无感登出与防重叠 Loading 计数器
|
|
4
|
+
* @author muzhiyu
|
|
5
|
+
* @version 2.0.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 默认请求全局配置
|
|
10
|
+
*/
|
|
11
|
+
const defaultConfig = {
|
|
12
|
+
baseURL: 'https://api.example.com', // 默认 API 接口域名 (项目启动时建议通过 setBaseURL 覆盖)
|
|
13
|
+
timeout: 10000, // 全局请求超时时间 (10000 毫秒)
|
|
14
|
+
header: {
|
|
15
|
+
'Content-Type': 'application/json;charset=UTF-8',
|
|
16
|
+
'Accept': 'application/json'
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 防重叠 Loading 计数器 (防止多个并发请求导致 Loading 框闪烁)
|
|
22
|
+
*/
|
|
23
|
+
let loadingCount = 0
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 显示全屏 Loading 遮罩
|
|
27
|
+
* @param {string} [title='加载中...'] - 加载提示语
|
|
28
|
+
*/
|
|
29
|
+
function showLoading(title = '加载中...') {
|
|
30
|
+
if (loadingCount === 0) {
|
|
31
|
+
uni.showLoading({ title, mask: true })
|
|
32
|
+
}
|
|
33
|
+
loadingCount++
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 隐藏全屏 Loading 遮罩
|
|
38
|
+
*/
|
|
39
|
+
function hideLoading() {
|
|
40
|
+
if (loadingCount > 0) {
|
|
41
|
+
loadingCount--
|
|
42
|
+
}
|
|
43
|
+
if (loadingCount === 0) {
|
|
44
|
+
uni.hideLoading()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* HTTP 请求核心客户端类
|
|
50
|
+
*/
|
|
51
|
+
class HttpClient {
|
|
52
|
+
/**
|
|
53
|
+
* 构造函数
|
|
54
|
+
* @param {Object} [config={}] - 自定义初始化配置对象
|
|
55
|
+
*/
|
|
56
|
+
constructor(config = {}) {
|
|
57
|
+
this.config = { ...defaultConfig, ...config }
|
|
58
|
+
this.requestInterceptor = null
|
|
59
|
+
this.responseInterceptor = null
|
|
60
|
+
this.interceptors = {
|
|
61
|
+
request: {
|
|
62
|
+
use: (fn) => { this.requestInterceptor = fn }
|
|
63
|
+
},
|
|
64
|
+
response: {
|
|
65
|
+
use: (fn) => { this.responseInterceptor = fn }
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 动态设置请求根域名 (BaseURL)
|
|
72
|
+
* @param {string} baseURL - API 接口服务器根地址 (例如: 'https://api.yourdomain.com')
|
|
73
|
+
*/
|
|
74
|
+
setBaseURL(baseURL) {
|
|
75
|
+
this.config.baseURL = baseURL
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 核心通用 Request 发起请求函数
|
|
80
|
+
* @param {Object} [options={}] - 请求选项
|
|
81
|
+
* @param {string} options.url - 接口相对或绝对路径 (例如: '/api/v1/user')
|
|
82
|
+
* @param {string} [options.method='GET'] - HTTP 请求方法 (GET, POST, PUT, DELETE 等)
|
|
83
|
+
* @param {Object} [options.data] - POST / PUT 请求体 payload
|
|
84
|
+
* @param {Object} [options.params] - GET 请求 URL 参数对象
|
|
85
|
+
* @param {Object} [options.header] - 自定义请求头
|
|
86
|
+
* @param {boolean} [options.showLoading=true] - 是否自动开启全屏 Loading 遮罩
|
|
87
|
+
* @param {string} [options.loadingText='加载中...'] - Loading 提示文字
|
|
88
|
+
* @returns {Promise<any>} 返回接口成功的 Data 数据对象
|
|
89
|
+
*/
|
|
90
|
+
request(options = {}) {
|
|
91
|
+
return new Promise((resolve, reject) => {
|
|
92
|
+
// 1. 拼接 URL 与合并请求参数
|
|
93
|
+
let opts = {
|
|
94
|
+
url: options.url.startsWith('http') ? options.url : `${this.config.baseURL}${options.url}`,
|
|
95
|
+
method: (options.method || 'GET').toUpperCase(),
|
|
96
|
+
data: options.data || options.params || {},
|
|
97
|
+
header: { ...this.config.header, ...options.header },
|
|
98
|
+
timeout: options.timeout || this.config.timeout,
|
|
99
|
+
showLoading: options.showLoading !== false,
|
|
100
|
+
loadingText: options.loadingText || '加载中...'
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 2. 自动读取并注入 Bearer Token
|
|
104
|
+
const token = uni.getStorageSync('token') || uni.getStorageSync('mu_token')
|
|
105
|
+
if (token) {
|
|
106
|
+
opts.header['Authorization'] = `Bearer ${token}`
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 3. 执行前置请求拦截器
|
|
110
|
+
if (typeof this.requestInterceptor === 'function') {
|
|
111
|
+
opts = this.requestInterceptor(opts) || opts
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 4. 显示 Loading 遮罩
|
|
115
|
+
if (opts.showLoading) {
|
|
116
|
+
showLoading(opts.loadingText)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 5. 调用 uni.request 原生发起网络通信
|
|
120
|
+
uni.request({
|
|
121
|
+
url: opts.url,
|
|
122
|
+
method: opts.method,
|
|
123
|
+
data: opts.data,
|
|
124
|
+
header: opts.header,
|
|
125
|
+
timeout: opts.timeout,
|
|
126
|
+
success: (res) => {
|
|
127
|
+
if (opts.showLoading) hideLoading()
|
|
128
|
+
|
|
129
|
+
// 执行后置响应拦截器
|
|
130
|
+
let responseData = res
|
|
131
|
+
if (typeof this.responseInterceptor === 'function') {
|
|
132
|
+
responseData = this.responseInterceptor(res)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// HTTP 响应状态码 2XX 判断
|
|
136
|
+
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
137
|
+
const data = res.data
|
|
138
|
+
// 业务 Code 状态判空与兼容 (支持 code: 0 或 code: 200 或 success: true)
|
|
139
|
+
if (data && (data.code === 0 || data.code === 200 || data.success === true || data.code === undefined)) {
|
|
140
|
+
resolve(data)
|
|
141
|
+
} else {
|
|
142
|
+
const errorMsg = data.message || data.msg || '业务处理失败'
|
|
143
|
+
uni.showToast({ title: errorMsg, icon: 'none' })
|
|
144
|
+
reject(data)
|
|
145
|
+
}
|
|
146
|
+
} else if (res.statusCode === 401) {
|
|
147
|
+
// 401 未授权处理:自动清空 Token 缓存并平滑跳转至登录界面
|
|
148
|
+
uni.removeStorageSync('token')
|
|
149
|
+
uni.removeStorageSync('mu_token')
|
|
150
|
+
uni.showToast({ title: '登录已过期,请重新登录', icon: 'none' })
|
|
151
|
+
setTimeout(() => {
|
|
152
|
+
uni.navigateTo({ url: '/pages/common/login/login' })
|
|
153
|
+
}, 1200)
|
|
154
|
+
reject({ code: 401, message: '未授权或登录过期' })
|
|
155
|
+
} else {
|
|
156
|
+
const errorMsg = `HTTP 错误 ${res.statusCode}`
|
|
157
|
+
uni.showToast({ title: errorMsg, icon: 'none' })
|
|
158
|
+
reject(res)
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
fail: (err) => {
|
|
162
|
+
if (opts.showLoading) hideLoading()
|
|
163
|
+
const errMsg = err.errMsg || '网络开小差了,请稍后再试'
|
|
164
|
+
uni.showToast({ title: errMsg, icon: 'none' })
|
|
165
|
+
reject(err)
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* 快捷 GET 请求方法
|
|
173
|
+
* @param {string} url - 请求相对或绝对路径
|
|
174
|
+
* @param {Object} [params={}] - GET Query 参数
|
|
175
|
+
* @param {Object} [config={}] - 额外配置 (如 header, showLoading)
|
|
176
|
+
* @returns {Promise<any>} 响应数据
|
|
177
|
+
*/
|
|
178
|
+
get(url, params = {}, config = {}) {
|
|
179
|
+
return this.request({ url, method: 'GET', params, ...config })
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* 快捷 POST 请求方法
|
|
184
|
+
* @param {string} url - 请求相对或绝对路径
|
|
185
|
+
* @param {Object} [data={}] - POST Payload 数据
|
|
186
|
+
* @param {Object} [config={}] - 额外配置
|
|
187
|
+
* @returns {Promise<any>} 响应数据
|
|
188
|
+
*/
|
|
189
|
+
post(url, data = {}, config = {}) {
|
|
190
|
+
return this.request({ url, method: 'POST', data, ...config })
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* 快捷 PUT 请求方法
|
|
195
|
+
* @param {string} url - 请求相对或绝对路径
|
|
196
|
+
* @param {Object} [data={}] - PUT Payload 数据
|
|
197
|
+
* @param {Object} [config={}] - 额外配置
|
|
198
|
+
* @returns {Promise<any>} 响应数据
|
|
199
|
+
*/
|
|
200
|
+
put(url, data = {}, config = {}) {
|
|
201
|
+
return this.request({ url, method: 'PUT', data, ...config })
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* 快捷 DELETE 请求方法
|
|
206
|
+
* @param {string} url - 请求相对或绝对路径
|
|
207
|
+
* @param {Object} [params={}] - DELETE Query 参数
|
|
208
|
+
* @param {Object} [config={}] - 额外配置
|
|
209
|
+
* @returns {Promise<any>} 响应数据
|
|
210
|
+
*/
|
|
211
|
+
delete(url, params = {}, config = {}) {
|
|
212
|
+
return this.request({ url, method: 'DELETE', params, ...config })
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* 全平台单文件上传封装 (支持 H5 / 小程序 / App)
|
|
217
|
+
* @param {string} url - 文件上传接口相对或绝对路径
|
|
218
|
+
* @param {string} filePath - 原生临时文件路径
|
|
219
|
+
* @param {string} [name='file'] - 后端接收文件的表单字段 key
|
|
220
|
+
* @param {Object} [formData={}] - 随文件一并提交的额外表单键值对
|
|
221
|
+
* @param {Object} [config={}] - 额外配置
|
|
222
|
+
* @returns {Promise<any>} 响应数据对象
|
|
223
|
+
*/
|
|
224
|
+
upload(url, filePath, name = 'file', formData = {}, config = {}) {
|
|
225
|
+
return new Promise((resolve, reject) => {
|
|
226
|
+
const fullUrl = url.startsWith('http') ? url : `${this.config.baseURL}${url}`
|
|
227
|
+
const token = uni.getStorageSync('token') || uni.getStorageSync('mu_token')
|
|
228
|
+
|
|
229
|
+
showLoading(config.loadingText || '文件上传中...')
|
|
230
|
+
|
|
231
|
+
uni.uploadFile({
|
|
232
|
+
url: fullUrl,
|
|
233
|
+
filePath,
|
|
234
|
+
name,
|
|
235
|
+
formData,
|
|
236
|
+
header: {
|
|
237
|
+
Authorization: token ? `Bearer ${token}` : '',
|
|
238
|
+
...config.header
|
|
239
|
+
},
|
|
240
|
+
success: (res) => {
|
|
241
|
+
hideLoading()
|
|
242
|
+
try {
|
|
243
|
+
const data = JSON.parse(res.data)
|
|
244
|
+
uni.showToast({ title: '上传成功', icon: 'success' })
|
|
245
|
+
resolve(data)
|
|
246
|
+
} catch (e) {
|
|
247
|
+
resolve(res.data)
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
fail: (err) => {
|
|
251
|
+
hideLoading()
|
|
252
|
+
uni.showToast({ title: '上传失败', icon: 'none' })
|
|
253
|
+
reject(err)
|
|
254
|
+
}
|
|
255
|
+
})
|
|
256
|
+
})
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* 实例化并导出默认单例客户端
|
|
262
|
+
*/
|
|
263
|
+
export const http = new HttpClient()
|
|
264
|
+
|
|
265
|
+
export default http
|