uview-pro 0.0.4 → 0.0.6

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.
@@ -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(lists, n => {
201
- emit('on-list-change', n, props.index);
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>
@@ -56,7 +56,7 @@ function hexToRgb(sColor: string, str: boolean = true): [number, number, number]
56
56
  }
57
57
 
58
58
  /**
59
- * rgb表示方式转换为hex表示方式
59
+ * rgbhex
60
60
  * @param rgb rgb字符串或hex字符串
61
61
  * @returns hex字符串
62
62
  */
@@ -88,6 +88,8 @@ function rgbToHex(rgb: string): string | undefined {
88
88
  } else {
89
89
  return rgb;
90
90
  }
91
+ // 默认返回原始值
92
+ return rgb;
91
93
  }
92
94
 
93
95
  /**
@@ -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 };
@@ -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?: any;
26
+ data?: unknown;
26
27
  method?: HttpMethod;
27
28
  dataType?: string;
28
29
  responseType?: string;
29
- success?: (res: any) => void;
30
- fail?: (err: any) => void;
31
- complete?: (res: any) => void;
32
- [key: string]: any;
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 = any> {
37
- handler?: (arg: T, P: typeof Promise) => any;
38
- onerror?: (arg: T, P: typeof Promise) => any;
39
- complete?: (arg: T, P: typeof Promise) => any;
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<any> | null;
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?: any, config: HttpRequestConfig = {}) {
85
- let url: string = config.url || urlConfig.url;
86
- const append: string = config.append || '';
87
- url = url + append;
88
- const defaultFn = (res: any) => res;
89
- const successFn: (res: any) => any = config.success || defaultFn;
90
- // 只传递一个参数,避免类型不符
91
- const callbackFn = (res: any) => successFn(res);
92
- return this.http.request({ url, data, ...urlConfig, ...config }).then(callbackFn);
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: any) {
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 = { ...this.config.data, ...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 = any>(options: HttpRequestConfig = {}): Promise<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 = { ...this.config.data, ...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?: any) => void) => {
205
- function isPromise(p: any): p is Promise<any> {
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<any> | null | undefined, callback: () => void) {
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: any) => {
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: any) => {
238
+ .catch((e: unknown) => {
236
239
  reject(e);
237
240
  });
238
241
  });
239
242
  }
240
- options.complete = (response: any) => {
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: any = options;
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: any) => {
265
+ (ret as Promise<unknown>).then(
266
+ (d: unknown) => {
264
267
  if (d === options) {
265
- d.url = d.url && d.url.indexOf('http') !== 0 ? d.baseURL + d.url : d.url;
266
- d.url = d.restURL ? d.url + d.restURL : d.url;
267
- d.method = d.method.toUpperCase();
268
- d.method === 'UPLOAD' ? uni.uploadFile(d) : uni.request(d);
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: any) => {
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 = any>(promises: Promise<T>[]): Promise<T[]> {
293
+ all<T = unknown>(promises: Promise<T>[]): Promise<T[]> {
285
294
  return Promise.all(promises);
286
295
  }
287
296
 
288
- // 动态方法扩展:get/post/put/patch/head/delete/upload
289
- [key: string]: any;
290
- }
291
-
292
- ['get', 'post', 'put', 'patch', 'head', 'delete', 'upload'].forEach(e => {
293
- Http.prototype[e] = function (url: string, data?: any, option?: HttpRequestConfig) {
294
- return this.request(merge({ url, data, method: e.toUpperCase() }, option));
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
- ['lock', 'unlock', 'clear'].forEach(e => {
299
- Http.prototype[e] = function () {
300
- const fn = this.interceptors.request[e as keyof Interceptor];
340
+ /**
341
+ * 拦截器锁定
342
+ */
343
+ lock(): void {
344
+ const fn = this.interceptors.request.lock;
301
345
  if (typeof fn === 'function') {
302
- // 只传递 this 作为上下文,不传参数,适配所有类型
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 {
@@ -0,0 +1,62 @@
1
+ /**
2
+ * async-validator 类型声明文件
3
+ * 适用于 uView Pro 内置 async-validator.js
4
+ * 支持 Schema、规则、校验回调、辅助类型等
5
+ */
6
+
7
+ declare type ValidateError = {
8
+ message: string;
9
+ field?: string;
10
+ [key: string]: any;
11
+ };
12
+
13
+ declare type ValidateCallback = (errors?: ValidateError[] | null, fields?: Record<string, ValidateError[]> | null) => void;
14
+
15
+ declare interface ValidateRule {
16
+ type?: string;
17
+ required?: boolean;
18
+ message?: string;
19
+ validator?: (
20
+ rule: ValidateRule,
21
+ value: any,
22
+ callback: ValidateCallback,
23
+ source: Record<string, any>,
24
+ options: ValidateOptions
25
+ ) => void | boolean | string | Error | string[] | Promise<any>;
26
+ asyncValidator?: (rule: ValidateRule, value: any, callback: ValidateCallback, source: Record<string, any>, options: ValidateOptions) => Promise<any>;
27
+ enum?: any[];
28
+ len?: number;
29
+ min?: number;
30
+ max?: number;
31
+ pattern?: RegExp | string;
32
+ whitespace?: boolean;
33
+ fields?: Record<string, ValidateRule | ValidateRule[]>;
34
+ defaultField?: ValidateRule | ValidateRule[];
35
+ transform?: (value: any) => any;
36
+ [key: string]: any;
37
+ }
38
+
39
+ declare interface ValidateOptions {
40
+ messages?: Record<string, any>;
41
+ suppressWarning?: boolean;
42
+ first?: boolean;
43
+ firstFields?: boolean | string[];
44
+ keys?: string[];
45
+ error?: (rule: ValidateRule, msg: string) => ValidateError;
46
+ [key: string]: any;
47
+ }
48
+
49
+ declare class Schema {
50
+ constructor(descriptor: Record<string, ValidateRule | ValidateRule[]>);
51
+ messages(messages?: Record<string, any>): Record<string, any>;
52
+ define(rules: Record<string, ValidateRule | ValidateRule[]>): void;
53
+ validate(source: Record<string, any>, options?: ValidateOptions | ValidateCallback, callback?: ValidateCallback): Promise<void>;
54
+ getType(rule: ValidateRule): string;
55
+ getValidationMethod(rule: ValidateRule): Function | false;
56
+ static register(type: string, validator: Function): void;
57
+ static warning: (...args: any[]) => void;
58
+ static messages: Record<string, any>;
59
+ }
60
+
61
+ export = Schema;
62
+ export as namespace Schema;
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全面兼容Vue3+TS的uni-app生态框架,70+精选组件",
5
- "version": "0.0.4",
6
- "description": "uView Pro,是uni-app全面兼容Vue3的uni-app生态框架,70+精选组件已使用TypeScript重构,已全面支持uni-app Vue3.0",
4
+ "displayName": "uView Pro 基于Vue3+TS全面重构的UI组件库,拥有70+精选组件",
5
+ "version": "0.0.6",
6
+ "description": "uView Pro,是全面支持Vue3的uni-app生态框架,70+精选组件已使用TypeScript重构,已全面支持uni-app Vue3.0",
7
7
  "main": "index.ts",
8
8
  "module": "index.ts",
9
9
  "browser": "index.ts",
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
- // uni_modules安装的方式需要前面的"@/uni_modules/",npm安装的方式无需"@/",以下方式任选其一
158
- // npm安装方式
159
- "^u-(.*)": "uview-pro/components/u-$1/u-$1.vue"
160
- // uni_modules安装方式
161
- // "^u-(.*)": "@/uni_modules/uview-pro/components/u-$1/u-$1.vue"
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": [