Blame view

member-miniapp/utils/store.js 3.71 KB
e1dcb3a0   “wangming”   1
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)
      })
    })
  }
  
  /**
   * 计算两点间距离(kmhaversine
   */
  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
    })
  }