@ningboyz/wxmp 1.0.23 → 1.0.25

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ningboyz/wxmp
2
2
 
3
- 微信小程序请求库。目录、模块类和初始化方式沿用 PC 端 `@ningboyz/apis` 的结构,底层通过 `wx.request` 发送请求。
3
+ 微信小程序请求库。目录、模块类和初始化方式沿用 PC 端 `@ningboyz/apis` 的结构,普通请求通过 `wx.request` 发送,文件上传通过 `wx.uploadFile` 发送。
4
4
 
5
5
  ```text
6
6
  src/
@@ -9,7 +9,7 @@ src/
9
9
  index.ts 参数、类型和模块导出
10
10
  types.ts 请求配置与拦截器类型
11
11
  wx.ts 微信请求底层
12
- core/ 登录、单位接口
12
+ core/ 登录、单位、附件上传接口
13
13
  noti/ 公告接口
14
14
  wtui/ 启动配置、公钥接口
15
15
  ```
@@ -64,6 +64,40 @@ await Request.wtui.envr.startkey();
64
64
 
65
65
  业务统一通过 `Request.core`、`Request.noti`、`Request.wtui` 调用,由 `Request.createRequest` 完成模块初始化。
66
66
 
67
+ ## 上传附件
68
+
69
+ 先完成初始化,再把微信选择文件得到的本地路径传给 `uploaddb`:
70
+
71
+ ```ts
72
+ import Request, { TCorePathUploaddbQuerys } from "@ningboyz/wxmp";
73
+
74
+ wx.chooseMessageFile({
75
+ count: 1,
76
+ type: "file",
77
+ async success(res) {
78
+ try {
79
+ const result = await Request.core.path.uploaddb(
80
+ new TCorePathUploaddbQuerys(),
81
+ {
82
+ filePath: res.tempFiles[0].path,
83
+ name: "file" // 示例字段名,按后端接收文件的字段名填写
84
+ }
85
+ );
86
+ if (!result.ONSTATUS) throw new Error(result.ERORMEMO);
87
+ console.log(result.LISTDATA);
88
+ } catch (error) {
89
+ console.error("上传失败", error);
90
+ }
91
+ }
92
+ });
93
+ ```
94
+
95
+ 每次上传一个文件,多文件需逐个调用。上传参数可增加 `formData` 传额外表单字段;如需传 JSON,可使用 `formData: { params: JSON.stringify(data) }`。
96
+ `txupload` 按后端要求填写,参数类默认值与 Web 端一致为 `-1`。微信后台需配置上传接口的 `uploadFile` 合法域名。
97
+
98
+ 上传沿用鉴权、超时和请求/响应拦截器,请求拦截器中的 `data` 是额外表单字段。请保留其表单结构,文件本身由 `filePath` 和 `name` 指定。
99
+ 上传的 `Content-Type` 和 boundary 由微信生成,通用拦截器设置的 `Content-Type` 会被移除。服务器返回的 JSON 字符串解析后再进入统一响应处理。
100
+
67
101
  ## 构建
68
102
 
69
103
  ```bash
package/es/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { CoreRequest as t } from "./packages/core/index.js";
2
2
  import { NotiRequest as r } from "./packages/noti/index.js";
3
3
  import { WtuiRequest as o } from "./packages/wtui/index.js";
4
- import { REQUEST_TIMEOUT_MILLISECONDS as d, TWxConfig as n } from "./packages/types.js";
4
+ import { REQUEST_TIMEOUT_MILLISECONDS as p, TWxConfig as C } from "./packages/types.js";
5
5
  import { WxRequestError as c } from "./packages/wx.js";
6
- import { TCoreUnitSelectdbQuerys as C, TCoreUserDetailddCardQuerys as R, TCoreUserUpdatedbQuerys as q, TWxLoginParams as Q } from "./packages/core/types.js";
7
- import { TNotiMainDetaildbQuerys as l, TNotiMainGet4NotiQuerys as w } from "./packages/noti/types.js";
8
- class m {
6
+ import { TCorePathUploaddbQuerys as x, TCoreUnitSelectdbQuerys as Q, TCoreUserDetailddCardQuerys as f, TCoreUserUpdateclQuerys as l, TCoreUserUpdatedbQuerys as y, TWxLoginParams as R } from "./packages/core/types.js";
7
+ import { TNotiMainDetaildbQuerys as w, TNotiMainGet4NotiQuerys as E } from "./packages/noti/types.js";
8
+ class T {
9
9
  static core;
10
10
  static noti;
11
11
  static wtui;
@@ -16,16 +16,18 @@ class m {
16
16
  export {
17
17
  t as CoreRequest,
18
18
  r as NotiRequest,
19
- d as REQUEST_TIMEOUT_MILLISECONDS,
20
- m as Request,
21
- C as TCoreUnitSelectdbQuerys,
22
- R as TCoreUserDetailddCardQuerys,
23
- q as TCoreUserUpdatedbQuerys,
24
- l as TNotiMainDetaildbQuerys,
25
- w as TNotiMainGet4NotiQuerys,
26
- n as TWxConfig,
27
- Q as TWxLoginParams,
19
+ p as REQUEST_TIMEOUT_MILLISECONDS,
20
+ T as Request,
21
+ x as TCorePathUploaddbQuerys,
22
+ Q as TCoreUnitSelectdbQuerys,
23
+ f as TCoreUserDetailddCardQuerys,
24
+ l as TCoreUserUpdateclQuerys,
25
+ y as TCoreUserUpdatedbQuerys,
26
+ w as TNotiMainDetaildbQuerys,
27
+ E as TNotiMainGet4NotiQuerys,
28
+ C as TWxConfig,
29
+ R as TWxLoginParams,
28
30
  o as WtuiRequest,
29
31
  c as WxRequestError,
30
- m as default
32
+ T as default
31
33
  };
@@ -1,9 +1,11 @@
1
1
  import { IWxConfig } from '../types';
2
2
  import { default as UserRequest } from './user';
3
3
  import { default as UnitRequest } from './unit';
4
+ import { default as PathRequest } from './path';
4
5
  declare class CoreRequest {
5
6
  user: UserRequest;
6
7
  unit: UnitRequest;
8
+ path: PathRequest;
7
9
  constructor(config: IWxConfig);
8
10
  }
9
11
  export default CoreRequest;
@@ -1,15 +1,17 @@
1
1
  import { createWxRequest as r } from "../wx.js";
2
2
  import s from "./user.js";
3
3
  import o from "./unit.js";
4
- class c {
4
+ import u from "./path.js";
5
+ class h {
5
6
  user;
6
7
  unit;
7
- constructor(t) {
8
- const e = r(t);
9
- this.user = new s(e), this.unit = new o(e);
8
+ path;
9
+ constructor(e) {
10
+ const t = r(e);
11
+ this.user = new s(t), this.unit = new o(t), this.path = new u(t);
10
12
  }
11
13
  }
12
14
  export {
13
- c as CoreRequest,
14
- c as default
15
+ h as CoreRequest,
16
+ h as default
15
17
  };
@@ -0,0 +1,16 @@
1
+ import { TCore } from '@ningboyz/types';
2
+ import { WxRequest } from '../wx';
3
+ import { IWxUploadFileParams } from '../types';
4
+ import { ICorePathUploaddbQuerys } from './types';
5
+ declare class PathRequest {
6
+ private wxRequest;
7
+ constructor(wxRequest: WxRequest);
8
+ /**
9
+ * 上传附件
10
+ * @param querys
11
+ * @param params 本地文件路径、文件字段名及额外表单字段
12
+ * @returns
13
+ */
14
+ uploaddb(querys: ICorePathUploaddbQuerys, params: IWxUploadFileParams): Promise<import('@ningboyz/types/es/response/IResponse.js').IResponse<TCore.IPathResponse[]>>;
15
+ }
16
+ export default PathRequest;
@@ -0,0 +1,18 @@
1
+ class u {
2
+ wxRequest;
3
+ constructor(t) {
4
+ this.wxRequest = t;
5
+ }
6
+ /**
7
+ * 上传附件
8
+ * @param querys
9
+ * @param params 本地文件路径、文件字段名及额外表单字段
10
+ * @returns
11
+ */
12
+ uploaddb(t, e) {
13
+ return this.wxRequest.postFile("/gapi/core/tpath/uploaddb", t, e);
14
+ }
15
+ }
16
+ export {
17
+ u as default
18
+ };
@@ -21,6 +21,12 @@ export interface ICoreUserDetailddCardQuerys {
21
21
  export declare class TCoreUserDetailddCardQuerys implements ICoreUserDetailddCardQuerys {
22
22
  usermain: number;
23
23
  }
24
+ export interface ICoreUserUpdateclQuerys {
25
+ entityid: string;
26
+ }
27
+ export declare class TCoreUserUpdateclQuerys implements ICoreUserUpdateclQuerys {
28
+ entityid: string;
29
+ }
24
30
  /** ========== unit ========== */
25
31
  export interface ICoreUnitSelectdbQuerys {
26
32
  unitmain: number;
@@ -30,3 +36,10 @@ export declare class TCoreUnitSelectdbQuerys implements ICoreUnitSelectdbQuerys
30
36
  unitmain: number;
31
37
  queuesby: string;
32
38
  }
39
+ /** ========== path ========== */
40
+ export interface ICorePathUploaddbQuerys {
41
+ txupload: number;
42
+ }
43
+ export declare class TCorePathUploaddbQuerys implements ICorePathUploaddbQuerys {
44
+ txupload: number;
45
+ }
@@ -10,12 +10,20 @@ class r {
10
10
  usermain = -1;
11
11
  }
12
12
  class d {
13
+ entityid = "";
14
+ }
15
+ class t {
13
16
  unitmain = -1;
14
17
  queuesby = "-1";
15
18
  }
19
+ class o {
20
+ txupload = -1;
21
+ }
16
22
  export {
17
- d as TCoreUnitSelectdbQuerys,
23
+ o as TCorePathUploaddbQuerys,
24
+ t as TCoreUnitSelectdbQuerys,
18
25
  r as TCoreUserDetailddCardQuerys,
26
+ d as TCoreUserUpdateclQuerys,
19
27
  a as TCoreUserUpdatedbQuerys,
20
28
  s as TWxLoginParams
21
29
  };
@@ -1,6 +1,6 @@
1
1
  import { TCore } from '@ningboyz/types';
2
2
  import { WxRequest } from '../wx';
3
- import { ICoreUserDetailddCardQuerys, ICoreUserUpdatedbQuerys, IWxLoginParams } from './types';
3
+ import { ICoreUserDetailddCardQuerys, ICoreUserUpdateclQuerys, ICoreUserUpdatedbQuerys, IWxLoginParams } from './types';
4
4
  declare class UserRequest {
5
5
  private wxRequest;
6
6
  constructor(wxRequest: WxRequest);
@@ -26,5 +26,11 @@ declare class UserRequest {
26
26
  updatedb(querys: ICoreUserUpdatedbQuerys, params: object): Promise<import('@ningboyz/types/es/response/IResponse.js').IResponse<TCore.IUserResponse[]>>;
27
27
  /** 获取用户详情(房产) */
28
28
  detailddCard(querys: ICoreUserDetailddCardQuerys, params: object): Promise<import('@ningboyz/types/es/response/IResponse.js').IResponse<TCore.IUserResponse[]>>;
29
+ /**
30
+ * 更新用户头像
31
+ * @param params
32
+ * @returns
33
+ */
34
+ updatecl(querys: ICoreUserUpdateclQuerys, params: object): Promise<import('@ningboyz/types/es/response/IResponse.js').IResponse<TCore.IUserResponse[]>>;
29
35
  }
30
36
  export default UserRequest;
@@ -33,6 +33,14 @@ class r {
33
33
  detailddCard(e, t) {
34
34
  return this.wxRequest.post("/gapi/core/tuser/detaildd", e, t);
35
35
  }
36
+ /**
37
+ * 更新用户头像
38
+ * @param params
39
+ * @returns
40
+ */
41
+ updatecl(e, t) {
42
+ return this.wxRequest.post("/gapi/core/tuser/coverurl/updatedb", e, t);
43
+ }
36
44
  }
37
45
  export {
38
46
  r as default
@@ -32,6 +32,15 @@ export interface IWxRequestOptions {
32
32
  headers?: Record<string, string>;
33
33
  contentType?: string;
34
34
  }
35
+ /** 微信小程序单文件上传参数。 */
36
+ export interface IWxUploadFileParams {
37
+ /** 选择文件后得到的本地临时路径。 */
38
+ filePath: string;
39
+ /** 后端接收文件的表单字段名。 */
40
+ name: string;
41
+ /** 额外表单字段;对象或数组请先 JSON.stringify。 */
42
+ formData?: Record<string, string | number | boolean>;
43
+ }
35
44
  export type TWxInterceptorsRequest = (request: IWxInternalRequestConfig) => IWxInternalRequestConfig | Promise<IWxInternalRequestConfig>;
36
45
  export type TWxInterceptorsResponse = (response: IWxResponse) => IWxResponse | Promise<IWxResponse>;
37
46
  export interface IWxConfig {
@@ -1,5 +1,5 @@
1
1
  import { TResp } from '@ningboyz/types';
2
- import { IWxConfig, IWxInternalRequestConfig, IWxRequestOptions } from './types';
2
+ import { IWxConfig, IWxInternalRequestConfig, IWxRequestOptions, IWxUploadFileParams } from './types';
3
3
  /** 网络和 HTTP 异常。HTTP 错误保留状态码、响应体及请求配置。 */
4
4
  declare class WxRequestError extends Error {
5
5
  readonly config: IWxInternalRequestConfig;
@@ -18,6 +18,8 @@ declare class WxRequest {
18
18
  * JSON 提交,对应 apis 里的 postJson。国密加密接口请走此方法。
19
19
  */
20
20
  postJson<T>(url: string, querys?: object, params?: object, headers?: Record<string, string>): Promise<TResp.IResponse<T>>;
21
+ /** 单文件上传。data 拦截的是额外表单字段,multipart boundary 由微信生成。 */
22
+ postFile<T>(url: string, querys: object | undefined, params: IWxUploadFileParams, headers?: Record<string, string>): Promise<TResp.IResponse<T>>;
21
23
  get<T>(url: string, querys?: object, headers?: Record<string, string>): Promise<TResp.IResponse<T>>;
22
24
  request<T>(url: string, options: IWxRequestOptions): Promise<TResp.IResponse<T>>;
23
25
  private send;
package/es/packages/wx.js CHANGED
@@ -1,62 +1,96 @@
1
1
  import { Const as T } from "@ningboyz/types";
2
2
  import n from "lodash";
3
- import { REQUEST_TIMEOUT_MILLISECONDS as R } from "./types.js";
4
- const E = 200, m = 300, h = "application/json", y = "application/x-www-form-urlencoded";
3
+ import { REQUEST_TIMEOUT_MILLISECONDS as p } from "./types.js";
4
+ const m = 200, R = 300, w = "application/json", y = "application/x-www-form-urlencoded";
5
5
  class u extends Error {
6
- constructor(e, s, t, i) {
7
- super(e), this.config = s, this.statusCode = t, this.data = i, this.name = "WxRequestError";
6
+ constructor(e, s, t, r) {
7
+ super(e), this.config = s, this.statusCode = t, this.data = r, this.name = "WxRequestError";
8
8
  }
9
9
  }
10
- class w {
10
+ class C {
11
11
  constructor(e) {
12
12
  this.config = e;
13
13
  }
14
14
  /**
15
15
  * 表单提交。body 字段名 params,值是 JSON 字符串,对应 apis 里的 post。
16
16
  */
17
- async post(e, s, t, i) {
18
- const r = n.isNil(t) ? void 0 : { params: JSON.stringify(t) }, o = this.createHeader(n.isNil(t) ? void 0 : y, i);
19
- return this.send("POST", e, s, r, o);
17
+ async post(e, s, t, r) {
18
+ const i = n.isNil(t) ? void 0 : { params: JSON.stringify(t) }, o = this.createHeader(n.isNil(t) ? void 0 : y, r);
19
+ return this.send("POST", e, s, i, o);
20
20
  }
21
21
  /**
22
22
  * JSON 提交,对应 apis 里的 postJson。国密加密接口请走此方法。
23
23
  */
24
- async postJson(e, s, t, i) {
25
- const r = this.createHeader(h, i);
26
- return this.send("POST", e, s, t, r);
24
+ async postJson(e, s, t, r) {
25
+ const i = this.createHeader(w, r);
26
+ return this.send("POST", e, s, t, i);
27
+ }
28
+ /** 单文件上传。data 拦截的是额外表单字段,multipart boundary 由微信生成。 */
29
+ async postFile(e, s, t, r) {
30
+ let i = {
31
+ url: e,
32
+ method: "POST",
33
+ querys: s,
34
+ data: t.formData,
35
+ header: this.createHeader(void 0, r)
36
+ };
37
+ this.config.interceptorsRequest && (i = await this.config.interceptorsRequest(i));
38
+ const o = Object.fromEntries(Object.entries(i.header).filter(([h]) => h.toLowerCase() !== "content-type"));
39
+ i = { ...i, header: o };
40
+ const c = this.createRequestUrl(i.url, i.querys), a = await new Promise((h, g) => {
41
+ this.getMiniProgramWx().uploadFile({
42
+ url: c,
43
+ filePath: t.filePath,
44
+ name: t.name,
45
+ formData: i.data,
46
+ header: o,
47
+ timeout: this.config.timeout ?? p,
48
+ success: h,
49
+ fail: (l) => g(new u(l.errMsg || "文件上传失败", i))
50
+ });
51
+ });
52
+ let d;
53
+ try {
54
+ d = JSON.parse(a.data);
55
+ } catch {
56
+ if (a.statusCode >= m && a.statusCode < R)
57
+ throw new u("文件上传响应不是有效的 JSON", i, a.statusCode, a.data);
58
+ d = a.data;
59
+ }
60
+ return this.handleResponse({ ...a, data: d }, i);
27
61
  }
28
62
  async get(e, s, t) {
29
- const i = this.createHeader(void 0, t);
30
- return this.send("GET", e, s, void 0, i);
63
+ const r = this.createHeader(void 0, t);
64
+ return this.send("GET", e, s, void 0, r);
31
65
  }
32
66
  async request(e, s) {
33
- const t = s.contentType ?? (s.method === "GET" ? void 0 : h), i = this.createHeader(t, s.headers);
34
- return this.send(s.method, e, s.querys, s.data, i);
67
+ const t = s.contentType ?? (s.method === "GET" ? void 0 : w), r = this.createHeader(t, s.headers);
68
+ return this.send(s.method, e, s.querys, s.data, r);
35
69
  }
36
- async send(e, s, t, i, r) {
70
+ async send(e, s, t, r, i) {
37
71
  let o = {
38
72
  url: s,
39
73
  method: e,
40
74
  querys: t,
41
- data: i,
42
- header: r
75
+ data: r,
76
+ header: i
43
77
  };
44
78
  this.config.interceptorsRequest && (o = await this.config.interceptorsRequest(o));
45
- const a = this.createRequestUrl(o.url, o.querys), d = this.config.timeout ?? R, f = await new Promise((g, l) => {
79
+ const c = this.createRequestUrl(o.url, o.querys), a = this.config.timeout ?? p, d = await new Promise((h, g) => {
46
80
  this.getMiniProgramWx().request({
47
- url: a,
81
+ url: c,
48
82
  method: o.method,
49
83
  data: o.data,
50
84
  header: o.header,
51
- timeout: d,
52
- success: g,
53
- fail: (p) => l(new u(p.errMsg || "网络请求失败", o))
85
+ timeout: a,
86
+ success: h,
87
+ fail: (l) => g(new u(l.errMsg || "网络请求失败", o))
54
88
  });
55
89
  });
56
- return this.handleResponse(f, o);
90
+ return this.handleResponse(d, o);
57
91
  }
58
92
  async handleResponse(e, s) {
59
- if (e.statusCode < E || e.statusCode >= m)
93
+ if (e.statusCode < m || e.statusCode >= R)
60
94
  throw this.tryHandleSessionExpired(e.data, e.statusCode), new u(`请求失败,状态码 ${e.statusCode}`, s, e.statusCode, e.data);
61
95
  let t = {
62
96
  data: e.data,
@@ -67,8 +101,8 @@ class w {
67
101
  }
68
102
  tryHandleSessionExpired(e, s) {
69
103
  if (!this.config.loseTokenState) return;
70
- const t = this.config.sessionExpiredErrorKey || T.ErrorKey.CONST_ERROR_KEY_TO_会话过期, i = e !== null && typeof e == "object" ? e.ERRORKEY : void 0;
71
- (s === 401 || i === t) && this.config.loseTokenState();
104
+ const t = this.config.sessionExpiredErrorKey || T.ErrorKey.CONST_ERROR_KEY_TO_会话过期, r = e !== null && typeof e == "object" ? e.ERRORKEY : void 0;
105
+ (s === 401 || r === t) && this.config.loseTokenState();
72
106
  }
73
107
  getMiniProgramWx() {
74
108
  const e = globalThis.wx;
@@ -77,11 +111,11 @@ class w {
77
111
  return e;
78
112
  }
79
113
  createRequestUrl(e, s) {
80
- const t = this.config.baseURL.endsWith("/") ? this.config.baseURL.slice(0, -1) : this.config.baseURL, i = e.startsWith("/") ? e : `/${e}`, r = {
114
+ const t = this.config.baseURL.endsWith("/") ? this.config.baseURL.slice(0, -1) : this.config.baseURL, r = e.startsWith("/") ? e : `/${e}`, i = {
81
115
  ...this.createAuthQuerys(),
82
116
  ...this.toLowerCase(s)
83
- }, o = Object.entries(r).filter(([, a]) => !n.isNil(a)).map(([a, d]) => `${encodeURIComponent(a)}=${encodeURIComponent(String(d))}`).join("&");
84
- return o.length === 0 ? `${t}${i}` : `${t}${i}?${o}`;
117
+ }, o = Object.entries(i).filter(([, c]) => !n.isNil(c)).map(([c, a]) => `${encodeURIComponent(c)}=${encodeURIComponent(String(a))}`).join("&");
118
+ return o.length === 0 ? `${t}${r}` : `${t}${r}?${o}`;
85
119
  }
86
120
  createAuthQuerys() {
87
121
  const e = {};
@@ -95,9 +129,9 @@ class w {
95
129
  return n.isNil(e) ? {} : n.mapKeys(e, (s, t) => t.toLowerCase());
96
130
  }
97
131
  }
98
- const S = (c) => new w(c);
132
+ const S = (f) => new C(f);
99
133
  export {
100
- w as WxRequest,
134
+ C as WxRequest,
101
135
  u as WxRequestError,
102
136
  S as createWxRequest
103
137
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ningboyz/wxmp",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "private": false,
5
5
  "description": "宁波甬政微信小程序库",
6
6
  "author": "nbyt-syq",
@@ -29,7 +29,7 @@
29
29
  "registry": "https://registry.npmjs.org/"
30
30
  },
31
31
  "dependencies": {
32
- "@ningboyz/types": "1.8.91-es.0",
32
+ "@ningboyz/types": "1.8.89-es.0",
33
33
  "lodash": "4.17.21"
34
34
  },
35
35
  "devDependencies": {