Explorar o código

docs(api): 修复 uni.request params 无效问题

- 新增 uni.request 查询参数拼接修复文档
- 修改 userBinding.ts 手动拼接 query string
- 移除无效的 params 字段使用
- 添加 encodeURIComponent 编码防止特殊字符破坏 URL
- 提供 toQueryString 工具函数建议方案
- 补充 Snowflake ID 精度处理说明
mcbaiyun hai 1 mes
pai
achega
b9d8fc7be0
Modificáronse 2 ficheiros con 98 adicións e 1 borrados
  1. 96 0
      docs/uniapp-user-binding-params-querystring-fix.md
  2. 2 1
      src/api/userBinding.ts

+ 96 - 0
docs/uniapp-user-binding-params-querystring-fix.md

@@ -0,0 +1,96 @@
+# uni.request params 无效修复记录 — user-binding/list-by-patient
+
+## 概要 ✅
+在使用 `uni.request` 向后端请求 `POST /user-binding/list-by-patient` 时,尝试通过 `params` 传递 query 参数无效,问题被定位为 `uni.request` 并不会将 `params` 自动拼接到 url(或该项目的环境未实现该字段),最终采用在 URL 中拼接 Query String(`qs`)并 `encodeURIComponent` 编码后成功解决。
+
+---
+
+## 问题描述 ⚠️
+在 `src/api/userBinding.ts` 中最初写法:
+
+```ts
+const res: any = await uni.request({
+  url: 'https://wx.baiyun.work/user-binding/list-by-patient',
+  method: 'POST',
+  data: query,
+  params: {
+    patientUserId,
+    bindingType
+  },
+  header: {
+    'content-type': 'application/json',
+    Authorization: `Bearer ${token}`
+  }
+})
+```
+
+希望 `params` 被自动拼接到 URL(比如 `?patientUserId=...&bindingType=...`),但实践中该字段没有生效,于是后续改为把 query 直接放到 URL:
+
+```ts
+const qs = `?patientUserId=${encodeURIComponent(String(patientUserId))}&bindingType=${encodeURIComponent(bindingType)}`
+const res: any = await uni.request({
+  url: 'https://wx.baiyun.work/user-binding/list-by-patient' + qs,
+  method: 'POST',
+  data: query,
+  header: { ... }
+})
+```
+
+这样一来后端成功收到了查询字符串,接口返回正常。
+
+---
+
+## 为什么会这样?💡
+- `uni.request` 支持的参数与 `axios`/`fetch` 不完全一致。某些平台/版本在 `uni.request` 中并不会自动把 `params` 拼接到 URL(尤其是在 `POST` 请求中,Get请求中可能是生效的),或者该 SDK 在实现上没有 `params` 字段(或仅在特定平台生效)。
+- 后端在 `list-by-patient` 端点可能通过 `@RequestParam`(Spring)、query 参数或路由匹配等方式读取 query,因此必须把参数放到 URL 中。
+- 另外要注意:Snowflake 等 64 位 ID 要用字符串传递以避免 JavaScript Number 精度问题(项目中已有处理)。
+
+---
+
+## 建议与最佳实践 🔧
+1. 简单而稳妥的解决方法:在 url 上手动拼接 `qs`。
+   - 使用 `encodeURIComponent` 对参数进行编码,避免空格或特殊字符破坏查询字符串。
+2. 如果你期望 `params` 自动生效:
+   - 查看当前 `uni-app` SDK 版本与平台(H5、小程序、App)文档,确认 `params` 是否被支持和如何使用。某些平台可能不支持把 `params` 自动序列化到 URL。
+3. 后端改造建议(如果可能):
+   - 考虑将 `list`接口改为 `GET` 请求(更语义化),或同时支持从 body 和 query 中读取参数(兼容性更好)。
+4. 推荐封装函数:
+   - 为了避免每次都手写拼接字符串,封装一个通用的构建 URL 的工具:
+
+```ts
+function toQueryString(obj: Record<string, any>) {
+  return Object.entries(obj)
+    .filter(([, v]) => v !== undefined && v !== null)
+    .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)
+    .join('&')
+}
+
+// 使用示例
+const qs = toQueryString({ patientUserId, bindingType })
+const res = await uni.request({
+  url: `https://wx.baiyun.work/user-binding/list-by-patient?${qs}`,
+  method: 'POST',
+  data: query,
+  header: {...}
+})
+```
+
+5. 记录与测试:
+   - 在改动后,通过前端控制台或后端日志确认实际 hit 的 URL;
+   - 通过单元/集成测试模拟该请求,确保在不同平台(H5/小程序/APP)上行为一致;
+   - 如果使用 CORS,确保后端对 query 参数和 `Authorization` header 的处理没有冲突。
+
+---
+
+## 项目里与此相关的注意点 🧭
+- 在 `src/api/userBinding.ts` 已用字符串处理 Snowflake ID(`String(patientUserId)`) 防止精度丢失;保持该写法即可。
+- 当需要批量拼接多个可选参数时,确保 `toQueryString` 过滤掉 undefined / null 值。
+
+---
+
+## 结论 ✅
+问题的根本在于:`uni.request` 的 `params` 字段在该平台/项目里没有把参数自动拼接到 URL 上。稳妥且简单的修复是:在 URL 中手动拼接 querystring(使用 `encodeURIComponent`),或者改后端接口/规范。该修复已被验证成功。
+
+---
+
+如需我把 `toQueryString` 工具函数也写入 `src/utils/` 并替换所有类似拼接,请回复,我可以继续实现并加上对应的单元测试。

+ 2 - 1
src/api/userBinding.ts

@@ -37,8 +37,9 @@ export async function listUserBindingsByPatient(
   query: BaseQueryRequest
 ) {
   const token = uni.getStorageSync('token')
+  const qs = `?patientUserId=${encodeURIComponent(String(patientUserId))}&bindingType=${encodeURIComponent(bindingType)}`
   const res: any = await uni.request({
-    url: 'https://wx.baiyun.work/user-binding/list-by-patient',
+    url: 'https://wx.baiyun.work/user-binding/list-by-patient' + qs,
     method: 'POST',
     data: query,
     params: {