store.js
3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// 门店数据处理工具:字段归一化、图片解析、定位与距离计算
// 后端 GetPickupStores 返回字段:id/name/city/address/phone/longitude/latitude/images/description/businessHours
/**
* 解析门店图片字段(可能是 JSON 数组字符串或逗号分隔字符串)
* @param {String} raw
* @returns {String[]}
*/
export function parseStoreImages(raw) {
if (!raw) return []
if (Array.isArray(raw)) return raw.filter(Boolean)
const str = String(raw).trim()
if (!str) return []
if (str[0] === '[') {
try {
const arr = JSON.parse(str)
return Array.isArray(arr) ? arr.filter(Boolean) : []
} catch (e) {
// 落到逗号分隔解析
}
}
return str.split(',').map(s => s.trim()).filter(Boolean)
}
/**
* 归一化后端门店记录为 UI 友好结构
* @param {Object} raw
* @returns {Object}
*/
export function normalizeStore(raw) {
const store = raw || {}
const images = parseStoreImages(store.images)
const lng = store.longitude !== undefined && store.longitude !== null && store.longitude !== '' ? Number(store.longitude) : null
const lat = store.latitude !== undefined && store.latitude !== null && store.latitude !== '' ? Number(store.latitude) : null
return {
id: store.id,
name: store.name || '门店',
city: store.city || '',
district: store.city || '',
address: store.address || '',
phone: store.phone || '',
longitude: isNaN(lng) ? null : lng,
latitude: isNaN(lat) ? null : lat,
images,
cover: images[0] || '',
description: store.description || '',
hours: store.businessHours || '',
// 距离,稍后按用户定位填充
distanceKm: null,
distance: ''
}
}
/**
* 获取用户定位(gcj02),失败不抛错,返回 null
* @returns {Promise<{latitude:number, longitude:number}|null>}
*/
export function getUserLocation() {
return new Promise((resolve) => {
uni.getLocation({
type: 'gcj02',
success: (res) => resolve({ latitude: res.latitude, longitude: res.longitude }),
fail: () => resolve(null)
})
})
}
/**
* 计算两点间距离(km,haversine)
*/
export function distanceKm(lat1, lng1, lat2, lng2) {
if ([lat1, lng1, lat2, lng2].some(v => v === null || v === undefined || isNaN(v))) return null
const toRad = (d) => (d * Math.PI) / 180
const R = 6371
const dLat = toRad(lat2 - lat1)
const dLng = toRad(lng2 - lng1)
const a = Math.sin(dLat / 2) ** 2 +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLng / 2) ** 2
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
return R * c
}
/**
* 距离文本格式化
*/
export function formatDistance(km) {
if (km === null || km === undefined || isNaN(km)) return ''
if (km < 1) return `${Math.round(km * 1000)}m`
return `${km.toFixed(1)}km`
}
/**
* 为门店列表填充距离;location 为空或门店无坐标则距离为空
* @param {Object[]} list 归一化后的门店列表
* @param {{latitude:number, longitude:number}|null} location
*/
export function attachDistance(list, location) {
if (!Array.isArray(list)) return []
list.forEach((s) => {
if (location && s.latitude !== null && s.longitude !== null) {
const km = distanceKm(location.latitude, location.longitude, s.latitude, s.longitude)
s.distanceKm = km
s.distance = formatDistance(km)
} else {
s.distanceKm = null
s.distance = ''
}
})
return list
}
/**
* 按距离升序排序(无距离的排最后)
*/
export function sortByDistance(list) {
return (list || []).slice().sort((a, b) => {
const da = a.distanceKm
const db = b.distanceKm
if (da === null && db === null) return 0
if (da === null) return 1
if (db === null) return -1
return da - db
})
}