UNPKG

@simoko/tw-zip

Version:

台灣縣市、行政區、郵遞區號(3碼/6碼)查詢工具,支援 React/Vue/Svelte/SolidJS/Angular

1 lines 22.2 kB
{"version":3,"sources":["../../src/zip6/loader.ts","../../src/vue/lazy.ts"],"names":["DEFAULT_BASE_URL","cityDataCache","citiesData","citiesDataPromise","loadCitiesData","options","baseUrl","res","data","error","loadCityData","city","trimmedCity","cached","response","preloadCities","cities","isCityCached","clearCache","parsedRulesCache","parseRules","rulesStr","parsed","rule","parts","calculateZipCode","area","road","number","lane","alley","cityData","zip3Map","areaData","zip3","rules","suffix","even","rLane","rLane1","rAlley","rAlley1","noBgn","_noBgn1","noEnd","_noEnd1","maxNo","useTwZip6","preload","loading","ref","areas","roads","searchResults","setCity","value","requestedCity","newCityData","newAreas","areaDataObj","newRoads","setArea","setRoad","searchRoads","keyword","results","trimmed","a","r","result","computed","zipCode","onMounted","firstCity","firstCityData","citiesToPreload"],"mappings":"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","file":"lazy.cjs","sourcesContent":["/**\n * 動態載入 zip6 資料\n */\n\nexport type AreaData = Record<string, string>\nexport type CityAreaData = Record<string, AreaData>\nexport type Zip3Map = Record<string, Record<string, string>>\n\nexport interface CitiesData {\n cities: string[]\n zip3: Zip3Map\n}\n\n// 預設使用 jsDelivr CDN\nconst DEFAULT_BASE_URL = 'https://cdn.jsdelivr.net/npm/@simoko/tw-zip/data/zip6'\n\n// 快取\nconst cityDataCache = new Map<string, CityAreaData>()\nlet citiesData: CitiesData | null = null\nlet citiesDataPromise: Promise<CitiesData> | null = null\n\nexport interface LoaderOptions {\n baseUrl?: string\n}\n\n/**\n * 載入縣市列表和 zip3 對照表\n */\nexport async function loadCitiesData(options: LoaderOptions = {}): Promise<CitiesData> {\n if (citiesData) {\n return citiesData\n }\n\n if (citiesDataPromise) {\n return citiesDataPromise\n }\n\n const baseUrl = options.baseUrl || DEFAULT_BASE_URL\n\n citiesDataPromise = fetch(`${baseUrl}/cities.json`)\n .then((res) => {\n if (!res.ok) {\n throw new Error(`Failed to load cities data: HTTP ${res.status}`)\n }\n return res.json()\n })\n .then((data: CitiesData) => {\n citiesData = data\n return data\n })\n .catch((error) => {\n // 清除 promise 以允許重試\n citiesDataPromise = null\n throw error\n })\n\n return citiesDataPromise\n}\n\n/**\n * 載入指定縣市的資料\n */\nexport async function loadCityData(city: string, options: LoaderOptions = {}): Promise<CityAreaData> {\n const trimmedCity = city.trim()\n if (!trimmedCity) {\n throw new Error('City name cannot be empty')\n }\n\n const cached = cityDataCache.get(trimmedCity)\n if (cached) {\n return cached\n }\n\n const baseUrl = options.baseUrl || DEFAULT_BASE_URL\n\n const response = await fetch(`${baseUrl}/${encodeURIComponent(trimmedCity)}.json`)\n if (!response.ok) {\n throw new Error(`Failed to load city data for ${trimmedCity}: HTTP ${response.status}`)\n }\n\n const data = await response.json() as CityAreaData\n\n cityDataCache.set(trimmedCity, data)\n return data\n}\n\n/**\n * 預載入指定縣市\n */\nexport async function preloadCities(cities: string[], options: LoaderOptions = {}): Promise<void> {\n await Promise.all(cities.map(city => loadCityData(city, options)))\n}\n\n/**\n * 取得已快取的縣市資料(同步)\n */\nexport function getCachedCityData(city: string): CityAreaData | undefined {\n return cityDataCache.get(city)\n}\n\n/**\n * 檢查縣市資料是否已快取\n */\nexport function isCityCached(city: string): boolean {\n return cityDataCache.has(city)\n}\n\n/**\n * 清除快取\n */\nexport function clearCache(): void {\n cityDataCache.clear()\n citiesData = null\n citiesDataPromise = null\n}\n","import type { CityAreaData, Zip3Map } from '../zip6/loader'\nimport { computed, onMounted, ref } from 'vue'\nimport {\n clearCache,\n isCityCached,\n loadCitiesData,\n loadCityData,\n preloadCities,\n} from '../zip6/loader'\n\nexport interface SearchResult {\n city: string\n area: string\n road: string\n}\n\nexport interface Zip6Result {\n zipcode: string\n zip3: string\n city: string\n area: string\n road: string\n}\n\nexport interface UseTwZip6Options {\n /** 資料來源 URL(預設使用 jsDelivr CDN) */\n baseUrl?: string\n /** 預載入的縣市列表 */\n preload?: string[]\n}\n\n// 規則解析快取\nconst parsedRulesCache = new Map<string, Array<[string, ...number[]]>>()\n\n// 解析規則字串(帶快取)\nfunction parseRules(rulesStr: string): Array<[string, ...number[]]> {\n if (!rulesStr)\n return []\n\n const cached = parsedRulesCache.get(rulesStr)\n if (cached)\n return cached\n\n const parsed = rulesStr.split('|').map((rule) => {\n const parts = rule.split(',')\n return [parts[0], ...parts.slice(1).map(Number)] as [string, ...number[]]\n })\n\n parsedRulesCache.set(rulesStr, parsed)\n return parsed\n}\n\n// 計算郵遞區號\nfunction calculateZipCode(\n city: string,\n area: string,\n road: string,\n number: number | undefined,\n lane: number | undefined,\n alley: number | undefined,\n cityData: CityAreaData | undefined,\n zip3Map: Zip3Map,\n): Zip6Result | undefined {\n if (!cityData)\n return undefined\n\n const areaData = cityData[area]\n if (!areaData)\n return undefined\n\n const rulesStr = areaData[road]\n if (!rulesStr)\n return undefined\n\n const zip3 = zip3Map[city]?.[area]\n if (!zip3)\n return undefined\n\n const rules = parseRules(rulesStr)\n\n for (const rule of rules) {\n const [suffix, even = 0, rLane = 0, rLane1 = 0, rAlley = 0, rAlley1 = 0, noBgn = 0, _noBgn1 = 0, noEnd = 0, _noEnd1 = 0] = rule\n\n // 檢查巷\n if (rLane > 0 || rLane1 > 0) {\n if (!lane)\n continue\n if (rLane > 0 && rLane1 > 0) {\n if (lane < rLane || lane > rLane1)\n continue\n }\n else if (rLane > 0) {\n if (noEnd === 9999 || noEnd === 9998) {\n if (lane < rLane)\n continue\n }\n else if (lane !== rLane) {\n continue\n }\n }\n }\n\n // 檢查弄\n if (rAlley > 0 || rAlley1 > 0) {\n if (!alley)\n continue\n if (rAlley > 0 && rAlley1 > 0) {\n if (alley < rAlley || alley > rAlley1)\n continue\n }\n else if (rAlley > 0 && alley !== rAlley) {\n continue\n }\n }\n\n // 檢查門牌號碼\n if (number !== undefined && (noBgn > 0 || noEnd > 0)) {\n if (even === 1 && number % 2 === 0)\n continue\n if (even === 2 && number % 2 === 1)\n continue\n\n const maxNo = noEnd === 9999 || noEnd === 9998 ? Number.POSITIVE_INFINITY : noEnd\n if (noBgn > 0 && number < noBgn)\n continue\n if (maxNo !== Number.POSITIVE_INFINITY && number > maxNo)\n continue\n }\n else if (even !== 0 && number !== undefined) {\n if (even === 1 && number % 2 === 0)\n continue\n if (even === 2 && number % 2 === 1)\n continue\n }\n\n return { zipcode: zip3 + suffix, zip3, city, area, road }\n }\n\n // 沒有精確匹配,返回第一筆\n if (rules.length > 0) {\n const [suffix] = rules[0]\n return { zipcode: zip3 + suffix, zip3, city, area, road }\n }\n\n return undefined\n}\n\nexport function useTwZip6(options: UseTwZip6Options = {}) {\n const { baseUrl, preload } = options\n\n const loading = ref(true)\n const cities = ref<string[]>([])\n const zip3Map = ref<Zip3Map>({})\n\n const city = ref('')\n const area = ref('')\n const road = ref('')\n const number = ref<number | undefined>(undefined)\n const lane = ref<number | undefined>(undefined)\n const alley = ref<number | undefined>(undefined)\n\n const areas = ref<string[]>([])\n const roads = ref<string[]>([])\n const searchResults = ref<SearchResult[]>([])\n const cityData = ref<CityAreaData | undefined>(undefined)\n\n // 切換縣市(包含錯誤處理和競態條件防護)\n async function setCity(value: string) {\n const requestedCity = value\n city.value = value\n loading.value = true\n\n try {\n const newCityData = await loadCityData(value, { baseUrl })\n\n // 檢查競態條件:如果用戶已切換到其他縣市,忽略此結果\n if (city.value !== requestedCity) {\n return\n }\n\n cityData.value = newCityData\n\n const newAreas = Object.keys(newCityData)\n areas.value = newAreas\n area.value = newAreas[0] ?? ''\n roads.value = []\n road.value = ''\n number.value = undefined\n lane.value = undefined\n alley.value = undefined\n\n if (newAreas[0]) {\n const areaDataObj = newCityData[newAreas[0]]\n if (areaDataObj) {\n const newRoads = Object.keys(areaDataObj)\n roads.value = newRoads\n road.value = newRoads[0] ?? ''\n }\n }\n }\n catch (error) {\n console.error(`Failed to load city data for ${value}:`, error)\n }\n finally {\n loading.value = false\n }\n }\n\n // 切換行政區\n function setArea(value: string) {\n area.value = value\n if (cityData.value) {\n const areaDataObj = cityData.value[value]\n if (areaDataObj) {\n const newRoads = Object.keys(areaDataObj)\n roads.value = newRoads\n road.value = newRoads[0] ?? ''\n }\n else {\n roads.value = []\n road.value = ''\n }\n }\n number.value = undefined\n lane.value = undefined\n alley.value = undefined\n }\n\n // 切換路名\n function setRoad(value: string) {\n road.value = value\n number.value = undefined\n lane.value = undefined\n alley.value = undefined\n }\n\n // 路名搜尋\n function searchRoads(keyword: string) {\n if (!keyword.trim()) {\n searchResults.value = []\n return\n }\n\n const results: SearchResult[] = []\n const trimmed = keyword.trim()\n\n if (cityData.value) {\n for (const [a, areaDataObj] of Object.entries(cityData.value)) {\n for (const r of Object.keys(areaDataObj)) {\n if (r.includes(trimmed)) {\n results.push({ city: city.value, area: a, road: r })\n }\n }\n }\n }\n\n searchResults.value = results\n }\n\n // 計算郵遞區號\n const result = computed<Zip6Result | undefined>(() => {\n if (!city.value || !area.value || !road.value || !cityData.value)\n return undefined\n return calculateZipCode(\n city.value,\n area.value,\n road.value,\n number.value,\n lane.value,\n alley.value,\n cityData.value,\n zip3Map.value,\n )\n })\n\n const zipCode = computed(() => result.value?.zipcode ?? '')\n const zip3 = computed(() => result.value?.zip3 ?? '')\n\n // 初始化(包含錯誤處理)\n onMounted(async () => {\n loading.value = true\n\n try {\n const data = await loadCitiesData({ baseUrl })\n\n cities.value = data.cities\n zip3Map.value = data.zip3\n\n const firstCity = data.cities[0] ?? ''\n city.value = firstCity\n\n // 預載入指定縣市\n if (preload && preload.length > 0) {\n await preloadCities(preload, { baseUrl })\n }\n\n // 載入第一個縣市的資料\n if (firstCity) {\n const firstCityData = await loadCityData(firstCity, { baseUrl })\n cityData.value = firstCityData\n const newAreas = Object.keys(firstCityData)\n areas.value = newAreas\n area.value = newAreas[0] ?? ''\n\n if (newAreas[0]) {\n const areaDataObj = firstCityData[newAreas[0]]\n if (areaDataObj) {\n const newRoads = Object.keys(areaDataObj)\n roads.value = newRoads\n road.value = newRoads[0] ?? ''\n }\n }\n }\n }\n catch (error) {\n console.error('Failed to initialize tw-zip data:', error)\n }\n finally {\n loading.value = false\n }\n })\n\n return {\n // 載入狀態\n loading,\n\n // 選項列表\n cities,\n areas,\n roads,\n\n // 選中值\n city,\n area,\n road,\n number,\n lane,\n alley,\n\n // Setters\n setCity,\n setArea,\n setRoad,\n\n // 路名搜尋\n searchRoads,\n searchResults,\n\n // 結果\n zipCode,\n zip3,\n result,\n\n // 工具函數\n preloadCities: (citiesToPreload: string[]) => preloadCities(citiesToPreload, { baseUrl }),\n isCityCached,\n clearCache,\n }\n}\n"]}