Files
weicw-dshsa 8816dd2867 fix(visit): 修复客户拜访页定位时好时坏
根因:定位链路用区县「中文名」查 sys_area,重名区县(白云区=广州/贵阳、
朝阳区=北京/长春、南山区=深圳/鹤岗…)命中多条,后端 getOne 默认
throwEx=true 抛 TooManyResultsException,页面表现为「有时能定位、有时不能」
——取决于用户当前所在区县名是否唯一。

改动:
- 新增 util/geo.js(纯函数):buildGeocodeUrl / normalizeAdcode /
  parseGeocodeResult / formatLocationText
  · 天地图 postStr 补 URL 编码:实测未编码时接口返回 HTTP 400
    「参数格式错误」(admin 端 merchantEdit.vue 已是正确写法)
  · 严格校验响应结构,限流(429)/参数错误(400) 一律返回 null
  · 补直辖市 city 为空时用省名兜底(天地图对上海/北京/天津/重庆返回 city:"")
- util/index.js:抽出 locateOnce / fetchGeocode / resolveAreaInfo 共用
  · 清除两处模块作用域的 this.areaId 误用(严格模式下抛 TypeError 会让
    Promise 永久悬空,locating 再也回不到 false,即「反复点没反应」)
  · 优先按天地图 county_code(去 156 前缀 = sys_area.id)精确查询,
    从根上绕开重名;按中文名仅作降级,并注释其歧义风险
  · 行政区划查不到不再阻断定位:返回 null,仍给出经纬度与地址
    (area_id/city_id/province_id 全仓库无消费方)
- api/request.js:get/del 不再吞掉非 2xx 的 reject,避免调用方状态永久悬空
- pages/visit/index.vue:fetchLocation 加 15s 超时兜底 + 运行号丢弃迟到结果,
  保证失败后仍可重试;静默失败也给出可见提示
- 新增 util/geo.test.mjs(10 个单测),package.json 补 test 脚本

验证:前端单测 10/10;真实天地图 + 生产后端端到端 5 个重名区县全部可正常
定位(后端修复尚未部署即已生效)。
2026-10-16 21:23:48 +08:00

100 lines
3.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Request from '@/js_sdk/luch-request/luch-request/index.js'
import {API} from '@/config'
import {getUserInfo, clearUserInfo} from "@/util/user";
const http = new Request();
http.config.baseURL = API
http.interceptors.request.use((config) => {
// uni.showLoading({title: '加载中'})
const token = getUserInfo().token
if (token && token !== 'undefined') {
config.header.Authorization = token
}
config.header.tenantId = 10325
return config
}, config => {
return Promise.reject(config)
})
http.interceptors.response.use((response) => {
const url = response.config.url
// uni.hideLoading()
switch (parseInt(response.data.code)) {
case 401: {
if (['user-cart-num', 'new-order', 'user-cart-add', 'user-info'].indexOf(url) === -1) {
uni.showToast({
title: '请登录',
icon: 'error',
duration: 2000,
})
setTimeout(() => {
clearUserInfo()
}, 2000)
}
}
break;
case 500: {
if (['/user/change-pay-password', 'new-order-from-goods-list'].indexOf(url) === -1) {
console.log(response.data)
uni.showToast({
icon: 'none',
title: response.data.content.msg,
duration: 2000,
})
}
}
break;
case 502: {
uni.showToast({
icon: 'error',
title: '系统维护中',
duration: 2000,
})
}
}
return response
}, (error) => {
if (error.code === 502) {
uni.showToast({
icon: 'error',
title: '系统维护中',
duration: 2000,
})
}
return Promise.reject(error)
})
const post = (url, formData, options) => {
return new Promise((resolve, reject) => {
http.post(url, formData, options).then(res => {
if (res.data.code === 0) resolve(res.data)
else if (res.data.code === 401) reject(res.data)
else reject(res.data)
})
})
}
export const get = (url, options) => {
// 直接返回,不再用 new Promise 包一层纯转发:
// http.get 成功时给出 {data},失败(非 2xx,如天地图 400/429)时 reject,
// 链式 then 会让错误自然向下传递。若吞掉 reject,调用方的 loading /
// locating 等状态将再也回不到初始值,表现为「点了没反应」。
return http.get(url, options).then(res => res.data)
}
export const del = (url, options) => {
return http.delete(url, options).then(res => res.data)
}
export const put = (url, formData, options) => {
return new Promise((resolve, reject) => {
http.put(url, formData, options).then(res => {
if (res.data.code === 0) resolve(res.data)
else if (res.data.code === 401) reject(res.data)
else reject(res.data)
})
})
}
export default post