area.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { defineStore } from 'pinia'
  2. import store from '@/store'
  3. import { ref } from 'vue'
  4. import * as AreaApi from '@/api/system/area'
  5. export interface AreaNode {
  6. id: number
  7. name: string
  8. children?: AreaNode[]
  9. }
  10. export const useAreaStore = defineStore('area', () => {
  11. const areaTree = ref<AreaNode[]>([])
  12. const cascaderOptions = computed(() => {
  13. const guangdong = areaTree.value.find((province) => province.name === '广东省')
  14. const guangzhou = guangdong?.children?.find((city) => city.name === '广州市')
  15. return [{ id: 0, name: '全国', children: areaTree }, ...(guangzhou ? [guangzhou] : [])]
  16. })
  17. async function loadAreaTree() {
  18. if (areaTree.value.length > 0) {
  19. return
  20. }
  21. const res = await AreaApi.getAreaTree()
  22. if (res.code === 0) {
  23. areaTree.value = res.data || []
  24. }
  25. return areaTree.value
  26. }
  27. const areaIdx = computed(() => {
  28. const nodeMap = new Map<number, AreaNode>()
  29. const ancestorsMap = new Map<number, AreaNode[]>()
  30. const stack: { node: AreaNode; parents: AreaNode[] }[] = []
  31. for (let i = areaTree.value.length - 1; i >= 0; i--) {
  32. stack.push({ node: areaTree.value[i], parents: [] })
  33. }
  34. while (stack.length > 0) {
  35. const { node, parents } = stack.pop()!
  36. nodeMap.set(node.id, node)
  37. ancestorsMap.set(node.id, parents)
  38. if (node.children?.length) {
  39. const newParents = [...parents, node]
  40. for (let i = node.children.length - 1; i >= 0; i--) {
  41. stack.push({ node: node.children[i], parents: newParents })
  42. }
  43. }
  44. }
  45. return [nodeMap, ancestorsMap]
  46. })
  47. const areaNodeMap = computed(() => areaIdx.value[0])
  48. const areaAncestorsMap = computed(() => areaIdx.value[1])
  49. function getDistrictName(districtId: number): string {
  50. if (areaNodeMap.value == null) {
  51. return ''
  52. }
  53. return areaNodeMap.value.get(districtId)?.name || `${districtId}`
  54. }
  55. function getDistrictFullName(districtId: number): string {
  56. if (areaNodeMap.value == null || areaAncestorsMap.value == null) {
  57. return ''
  58. }
  59. const ancestors = areaAncestorsMap.value.get(districtId) || []
  60. const node = areaNodeMap.value.get(districtId)
  61. const parts = [...ancestors.map((a) => a.name)]
  62. if (node) parts.push(node.name)
  63. return parts.join('') || `${districtId}`
  64. }
  65. const streetCache = ref<Record<number, AreaNode[]>>({})
  66. // 获取街道同时缓存
  67. async function getStreetsByDistrict(districtId: number) {
  68. if (streetCache.value[districtId]) {
  69. return streetCache.value[districtId]
  70. }
  71. const res = await AreaApi.getAreaTreeById(districtId)
  72. if (res.code === 0) {
  73. streetCache.value[districtId] = res.data || []
  74. }
  75. return streetCache.value[districtId] || []
  76. }
  77. function getStreetName(streetId: number, districtId?: number): string {
  78. if (!districtId) return ''
  79. const streets = streetCache.value[districtId]
  80. if (!streets) return ''
  81. const found = streets.find((s) => s.id === streetId)
  82. return found?.name || ''
  83. }
  84. return {
  85. areaTree,
  86. cascaderOptions,
  87. areaIdx,
  88. areaNodeMap,
  89. areaAncestorsMap,
  90. streetCache,
  91. loadAreaTree,
  92. getStreetsByDistrict,
  93. getDistrictFullName,
  94. getStreetName,
  95. }
  96. })
  97. export const useAreaStoreWithOut = () => {
  98. return useAreaStore(store)
  99. }