diff --git a/.gitignore b/.gitignore index 5c2bf67..f74affb 100644 --- a/.gitignore +++ b/.gitignore @@ -66,4 +66,4 @@ build package-lock.json dist -test/app-domain \ No newline at end of file +test \ No newline at end of file diff --git a/es/MapWorldSDK.d.ts b/es/MapWorldSDK.d.ts new file mode 100644 index 0000000..dcc16cf --- /dev/null +++ b/es/MapWorldSDK.d.ts @@ -0,0 +1,9 @@ +import MapWorldInstance from "./service/mapWorld/mapWorld"; +declare class MapWorldSDK { + webKeyMap: Record; + constructor(); + getInstance(key: string): MapWorldInstance; +} +declare const SDK: MapWorldSDK; +export default SDK; +export { MapWorldInstance, }; diff --git a/es/MapWorldSDK.js b/es/MapWorldSDK.js new file mode 100644 index 0000000..e664912 --- /dev/null +++ b/es/MapWorldSDK.js @@ -0,0 +1,20 @@ +import MapWorldInstance from "./service/mapWorld/mapWorld"; +class MapWorldSDK { + webKeyMap; + constructor() { + this.webKeyMap = {}; + } + getInstance(key) { + if (this.webKeyMap[key]) { + return this.webKeyMap[key]; + } + const instance = new MapWorldInstance(key); + Object.assign(this.webKeyMap, { + [key]: instance, + }); + return instance; + } +} +const SDK = new MapWorldSDK(); +export default SDK; +export { MapWorldInstance, }; diff --git a/es/index.d.ts b/es/index.d.ts index 3f74fee..cacf45a 100644 --- a/es/index.d.ts +++ b/es/index.d.ts @@ -5,6 +5,7 @@ import SmsSdk, { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance } from './ import CTYunSDK, { CTYunInstance } from './CTYunSDK'; import ALiYunSDK, { ALiYunInstance } from './ALiYunSDK'; import TencentYunSDK, { TencentYunInstance } from './TencentYunSDK'; +import MapwordSDK, { MapWorldInstance } from './MapWorldSDK'; export * from './service/amap/Amap'; -export { AmapSDK, QiniuSDK, WechatSDK, CTYunSDK, ALiYunSDK, TencentYunSDK, CTYunInstance, WechatMpInstance, WechatPublicInstance, WechatWebInstance, QiniuCloudInstance, ALiYunInstance, TencentYunInstance, SmsSdk, TencentSmsInstance, AliSmsInstance, CTYunSmsInstance, }; +export { AmapSDK, QiniuSDK, WechatSDK, CTYunSDK, ALiYunSDK, TencentYunSDK, MapwordSDK, CTYunInstance, WechatMpInstance, WechatPublicInstance, WechatWebInstance, QiniuCloudInstance, ALiYunInstance, TencentYunInstance, MapWorldInstance, SmsSdk, TencentSmsInstance, AliSmsInstance, CTYunSmsInstance, }; export * from './types'; diff --git a/es/index.js b/es/index.js index 8a49dbe..5acd246 100644 --- a/es/index.js +++ b/es/index.js @@ -5,6 +5,7 @@ import SmsSdk, { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance, } from '. import CTYunSDK, { CTYunInstance } from './CTYunSDK'; import ALiYunSDK, { ALiYunInstance } from './ALiYunSDK'; import TencentYunSDK, { TencentYunInstance } from './TencentYunSDK'; +import MapwordSDK, { MapWorldInstance } from './MapWorldSDK'; export * from './service/amap/Amap'; -export { AmapSDK, QiniuSDK, WechatSDK, CTYunSDK, ALiYunSDK, TencentYunSDK, CTYunInstance, WechatMpInstance, WechatPublicInstance, WechatWebInstance, QiniuCloudInstance, ALiYunInstance, TencentYunInstance, SmsSdk, TencentSmsInstance, AliSmsInstance, CTYunSmsInstance, }; +export { AmapSDK, QiniuSDK, WechatSDK, CTYunSDK, ALiYunSDK, TencentYunSDK, MapwordSDK, CTYunInstance, WechatMpInstance, WechatPublicInstance, WechatWebInstance, QiniuCloudInstance, ALiYunInstance, TencentYunInstance, MapWorldInstance, SmsSdk, TencentSmsInstance, AliSmsInstance, CTYunSmsInstance, }; export * from './types'; diff --git a/es/service/amap/Amap.d.ts b/es/service/amap/Amap.d.ts index 0d28b2e..e639676 100644 --- a/es/service/amap/Amap.d.ts +++ b/es/service/amap/Amap.d.ts @@ -5,7 +5,7 @@ export declare class AmapInstance { from: [number, number]; to: [number, number]; }): Promise; - regeo(data: { + regeo(params: { longitude: number; latitude: number; }): Promise; @@ -16,6 +16,11 @@ export declare class AmapInstance { keywords: string; subdistrict: string; }): Promise; + /** + * 高德这个接口搜索能力很弱,但高级接口要收费,只能先暂时用着 + * @param data + * @returns + */ geocode(data: { address: string; city?: string; diff --git a/es/service/amap/Amap.js b/es/service/amap/Amap.js index fbf691d..7cdd3a3 100644 --- a/es/service/amap/Amap.js +++ b/es/service/amap/Amap.js @@ -21,8 +21,8 @@ export class AmapInstance { } return jsonData; } - async regeo(data) { - const { longitude, latitude } = data; + async regeo(params) { + const { longitude, latitude } = params; const url = `https://restapi.amap.com/v3/geocode/regeo?location=${longitude},${latitude}&key=${this.key}`; let response; try { @@ -69,6 +69,11 @@ export class AmapInstance { } return jsonData; } + /** + * 高德这个接口搜索能力很弱,但高级接口要收费,只能先暂时用着 + * @param data + * @returns + */ async geocode(data) { const { address, city } = data; const url = `https://restapi.amap.com/v3/geocode/geo?address=${address}${city ? `&city=${city}` : ''}&key=${this.key}`; diff --git a/es/service/mapWorld/mapWorld.d.ts b/es/service/mapWorld/mapWorld.d.ts index e457d5b..2bb2c8e 100644 --- a/es/service/mapWorld/mapWorld.d.ts +++ b/es/service/mapWorld/mapWorld.d.ts @@ -1,6 +1,22 @@ export default class MapWorldInstance { key: string; constructor(key: string); - geo(): void; - regeo(): void; + /** + * http://lbs.tianditu.gov.cn/server/search2.html + * @param keyWord + * @param areaId + * @param start + * @param count + * @returns + */ + geo(keyWord: string, areaId?: string, start?: number, count?: number): Promise>; + regeo(params: { + longitude: number; + latitude: number; + }): Promise; } diff --git a/es/service/mapWorld/mapWorld.js b/es/service/mapWorld/mapWorld.js index 3259238..6446332 100644 --- a/es/service/mapWorld/mapWorld.js +++ b/es/service/mapWorld/mapWorld.js @@ -1,10 +1,97 @@ +require('../../utils/fetch'); +import assert from 'assert'; +import { OakExternalException, OakNetworkException, } from 'oak-domain/lib/types/Exception'; +function codeEnc(code) { + return code.startsWith('156') ? code : `156${code}`; +} +function codeDec(code) { + return code.startsWith('156') ? code.slice(3) : code; +} export default class MapWorldInstance { key; constructor(key) { this.key = key; } - geo() { + /** + * http://lbs.tianditu.gov.cn/server/search2.html + * @param keyWord + * @param areaId + * @param start + * @param count + * @returns + */ + async geo(keyWord, areaId, start, count) { + const start2 = start || 0; + const count2 = count || 100; + const url = `http://api.tianditu.gov.cn/v2/search?postStr={"keyWord":"${keyWord}","queryType":12,"start":${start2},"count":${count2},"specify": "${codeEnc(areaId || '000000')}","show":"2"}&type=query&tk=${this.key}`; + let response; + try { + response = await global.fetch(url); + } + catch (err) { + throw new OakNetworkException(`访问mapworld接口失败,「${url}」`); + } + const jsonData = await response.json(); + // 天地图的文档没有很规范的定义错误,只能根据测到的情况硬写 + if (!jsonData.status) { + const { code, msg, resolve } = jsonData; + if (msg) { + throw new OakExternalException('mapworld', code, msg); + } + throw new OakExternalException('mapworld', '-1', `${JSON.stringify(jsonData)}`); + } + if (jsonData.status.infocode !== 1000) { + throw new OakExternalException('mapworld', jsonData.status.infocode, jsonData.status.cndesc); + } + const { resultType, statistics, pois } = jsonData; + if (resultType === 2) { + // 如果以156000000(中国)作为搜索范围,可能会返回统计结果,用统计结果中的数据再次查询 + assert(statistics); + const { allAdmins } = statistics; + const result = []; + let passed = 0; + const getFromSub = async (idx) => { + const admin = allAdmins[idx]; + if (admin) { + const { adminCode, count: adminCount } = admin; + if (passed + adminCount < start2) { + // 这个sub已经被pass + passed += adminCount; + return await getFromSub(idx + 1); + } + else { + const start3 = start2 - passed; + result.push(...(await this.geo(keyWord, `${adminCode}`, start3, count2))); + if (result.length === count2) { + return result; + } + await getFromSub(idx + 1); + } + } + return result; + }; + return await getFromSub(0); + } + else { + assert(resultType === 1); + if (jsonData.count === '0') { + return []; + } + assert(pois); + // 天地图返回的是wgs84坐标 + return pois.map((ele) => { + const { name, lonlat, countyCode, cityCode, provinceCode } = ele; + const tudes = lonlat.split(',').map((ele) => parseFloat(ele)); + return { + poiName: name, + areaId: codeDec(countyCode || cityCode || provinceCode), + longitude: tudes[0], + latitude: tudes[1], + }; + }); + } } - regeo() { + regeo(params) { + throw new Error('not implement yet'); } } diff --git a/lib/MapWorldSDK.d.ts b/lib/MapWorldSDK.d.ts new file mode 100644 index 0000000..dcc16cf --- /dev/null +++ b/lib/MapWorldSDK.d.ts @@ -0,0 +1,9 @@ +import MapWorldInstance from "./service/mapWorld/mapWorld"; +declare class MapWorldSDK { + webKeyMap: Record; + constructor(); + getInstance(key: string): MapWorldInstance; +} +declare const SDK: MapWorldSDK; +export default SDK; +export { MapWorldInstance, }; diff --git a/lib/MapWorldSDK.js b/lib/MapWorldSDK.js new file mode 100644 index 0000000..da10b8d --- /dev/null +++ b/lib/MapWorldSDK.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MapWorldInstance = void 0; +const tslib_1 = require("tslib"); +const mapWorld_1 = tslib_1.__importDefault(require("./service/mapWorld/mapWorld")); +exports.MapWorldInstance = mapWorld_1.default; +class MapWorldSDK { + webKeyMap; + constructor() { + this.webKeyMap = {}; + } + getInstance(key) { + if (this.webKeyMap[key]) { + return this.webKeyMap[key]; + } + const instance = new mapWorld_1.default(key); + Object.assign(this.webKeyMap, { + [key]: instance, + }); + return instance; + } +} +const SDK = new MapWorldSDK(); +exports.default = SDK; diff --git a/lib/index.d.ts b/lib/index.d.ts index 3f74fee..cacf45a 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -5,6 +5,7 @@ import SmsSdk, { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance } from './ import CTYunSDK, { CTYunInstance } from './CTYunSDK'; import ALiYunSDK, { ALiYunInstance } from './ALiYunSDK'; import TencentYunSDK, { TencentYunInstance } from './TencentYunSDK'; +import MapwordSDK, { MapWorldInstance } from './MapWorldSDK'; export * from './service/amap/Amap'; -export { AmapSDK, QiniuSDK, WechatSDK, CTYunSDK, ALiYunSDK, TencentYunSDK, CTYunInstance, WechatMpInstance, WechatPublicInstance, WechatWebInstance, QiniuCloudInstance, ALiYunInstance, TencentYunInstance, SmsSdk, TencentSmsInstance, AliSmsInstance, CTYunSmsInstance, }; +export { AmapSDK, QiniuSDK, WechatSDK, CTYunSDK, ALiYunSDK, TencentYunSDK, MapwordSDK, CTYunInstance, WechatMpInstance, WechatPublicInstance, WechatWebInstance, QiniuCloudInstance, ALiYunInstance, TencentYunInstance, MapWorldInstance, SmsSdk, TencentSmsInstance, AliSmsInstance, CTYunSmsInstance, }; export * from './types'; diff --git a/lib/index.js b/lib/index.js index ef322e4..9e66279 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.CTYunSmsInstance = exports.AliSmsInstance = exports.TencentSmsInstance = exports.SmsSdk = exports.TencentYunInstance = exports.ALiYunInstance = exports.QiniuCloudInstance = exports.WechatWebInstance = exports.WechatPublicInstance = exports.WechatMpInstance = exports.CTYunInstance = exports.TencentYunSDK = exports.ALiYunSDK = exports.CTYunSDK = exports.WechatSDK = exports.QiniuSDK = exports.AmapSDK = void 0; +exports.CTYunSmsInstance = exports.AliSmsInstance = exports.TencentSmsInstance = exports.SmsSdk = exports.MapWorldInstance = exports.TencentYunInstance = exports.ALiYunInstance = exports.QiniuCloudInstance = exports.WechatWebInstance = exports.WechatPublicInstance = exports.WechatMpInstance = exports.CTYunInstance = exports.MapwordSDK = exports.TencentYunSDK = exports.ALiYunSDK = exports.CTYunSDK = exports.WechatSDK = exports.QiniuSDK = exports.AmapSDK = void 0; const tslib_1 = require("tslib"); const WechatSDK_1 = tslib_1.__importStar(require("./WechatSDK")); exports.WechatSDK = WechatSDK_1.default; @@ -26,5 +26,8 @@ Object.defineProperty(exports, "ALiYunInstance", { enumerable: true, get: functi const TencentYunSDK_1 = tslib_1.__importStar(require("./TencentYunSDK")); exports.TencentYunSDK = TencentYunSDK_1.default; Object.defineProperty(exports, "TencentYunInstance", { enumerable: true, get: function () { return TencentYunSDK_1.TencentYunInstance; } }); +const MapWorldSDK_1 = tslib_1.__importStar(require("./MapWorldSDK")); +exports.MapwordSDK = MapWorldSDK_1.default; +Object.defineProperty(exports, "MapWorldInstance", { enumerable: true, get: function () { return MapWorldSDK_1.MapWorldInstance; } }); tslib_1.__exportStar(require("./service/amap/Amap"), exports); tslib_1.__exportStar(require("./types"), exports); diff --git a/lib/service/amap/Amap.d.ts b/lib/service/amap/Amap.d.ts index 0d28b2e..e639676 100644 --- a/lib/service/amap/Amap.d.ts +++ b/lib/service/amap/Amap.d.ts @@ -5,7 +5,7 @@ export declare class AmapInstance { from: [number, number]; to: [number, number]; }): Promise; - regeo(data: { + regeo(params: { longitude: number; latitude: number; }): Promise; @@ -16,6 +16,11 @@ export declare class AmapInstance { keywords: string; subdistrict: string; }): Promise; + /** + * 高德这个接口搜索能力很弱,但高级接口要收费,只能先暂时用着 + * @param data + * @returns + */ geocode(data: { address: string; city?: string; diff --git a/lib/service/amap/Amap.js b/lib/service/amap/Amap.js index 3d352f7..eb43529 100644 --- a/lib/service/amap/Amap.js +++ b/lib/service/amap/Amap.js @@ -24,8 +24,8 @@ class AmapInstance { } return jsonData; } - async regeo(data) { - const { longitude, latitude } = data; + async regeo(params) { + const { longitude, latitude } = params; const url = `https://restapi.amap.com/v3/geocode/regeo?location=${longitude},${latitude}&key=${this.key}`; let response; try { @@ -72,6 +72,11 @@ class AmapInstance { } return jsonData; } + /** + * 高德这个接口搜索能力很弱,但高级接口要收费,只能先暂时用着 + * @param data + * @returns + */ async geocode(data) { const { address, city } = data; const url = `https://restapi.amap.com/v3/geocode/geo?address=${address}${city ? `&city=${city}` : ''}&key=${this.key}`; diff --git a/lib/service/mapWorld/mapWorld.d.ts b/lib/service/mapWorld/mapWorld.d.ts index e457d5b..2bb2c8e 100644 --- a/lib/service/mapWorld/mapWorld.d.ts +++ b/lib/service/mapWorld/mapWorld.d.ts @@ -1,6 +1,22 @@ export default class MapWorldInstance { key: string; constructor(key: string); - geo(): void; - regeo(): void; + /** + * http://lbs.tianditu.gov.cn/server/search2.html + * @param keyWord + * @param areaId + * @param start + * @param count + * @returns + */ + geo(keyWord: string, areaId?: string, start?: number, count?: number): Promise>; + regeo(params: { + longitude: number; + latitude: number; + }): Promise; } diff --git a/lib/service/mapWorld/mapWorld.js b/lib/service/mapWorld/mapWorld.js index 5101714..bbbb803 100644 --- a/lib/service/mapWorld/mapWorld.js +++ b/lib/service/mapWorld/mapWorld.js @@ -1,13 +1,101 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +const tslib_1 = require("tslib"); +require('../../utils/fetch'); +const assert_1 = tslib_1.__importDefault(require("assert")); +const Exception_1 = require("oak-domain/lib/types/Exception"); +function codeEnc(code) { + return code.startsWith('156') ? code : `156${code}`; +} +function codeDec(code) { + return code.startsWith('156') ? code.slice(3) : code; +} class MapWorldInstance { key; constructor(key) { this.key = key; } - geo() { + /** + * http://lbs.tianditu.gov.cn/server/search2.html + * @param keyWord + * @param areaId + * @param start + * @param count + * @returns + */ + async geo(keyWord, areaId, start, count) { + const start2 = start || 0; + const count2 = count || 100; + const url = `http://api.tianditu.gov.cn/v2/search?postStr={"keyWord":"${keyWord}","queryType":12,"start":${start2},"count":${count2},"specify": "${codeEnc(areaId || '000000')}","show":"2"}&type=query&tk=${this.key}`; + let response; + try { + response = await global.fetch(url); + } + catch (err) { + throw new Exception_1.OakNetworkException(`访问mapworld接口失败,「${url}」`); + } + const jsonData = await response.json(); + // 天地图的文档没有很规范的定义错误,只能根据测到的情况硬写 + if (!jsonData.status) { + const { code, msg, resolve } = jsonData; + if (msg) { + throw new Exception_1.OakExternalException('mapworld', code, msg); + } + throw new Exception_1.OakExternalException('mapworld', '-1', `${JSON.stringify(jsonData)}`); + } + if (jsonData.status.infocode !== 1000) { + throw new Exception_1.OakExternalException('mapworld', jsonData.status.infocode, jsonData.status.cndesc); + } + const { resultType, statistics, pois } = jsonData; + if (resultType === 2) { + // 如果以156000000(中国)作为搜索范围,可能会返回统计结果,用统计结果中的数据再次查询 + (0, assert_1.default)(statistics); + const { allAdmins } = statistics; + const result = []; + let passed = 0; + const getFromSub = async (idx) => { + const admin = allAdmins[idx]; + if (admin) { + const { adminCode, count: adminCount } = admin; + if (passed + adminCount < start2) { + // 这个sub已经被pass + passed += adminCount; + return await getFromSub(idx + 1); + } + else { + const start3 = start2 - passed; + result.push(...(await this.geo(keyWord, `${adminCode}`, start3, count2))); + if (result.length === count2) { + return result; + } + await getFromSub(idx + 1); + } + } + return result; + }; + return await getFromSub(0); + } + else { + (0, assert_1.default)(resultType === 1); + if (jsonData.count === '0') { + return []; + } + (0, assert_1.default)(pois); + // 天地图返回的是wgs84坐标 + return pois.map((ele) => { + const { name, lonlat, countyCode, cityCode, provinceCode } = ele; + const tudes = lonlat.split(',').map((ele) => parseFloat(ele)); + return { + poiName: name, + areaId: codeDec(countyCode || cityCode || provinceCode), + longitude: tudes[0], + latitude: tudes[1], + }; + }); + } } - regeo() { + regeo(params) { + throw new Error('not implement yet'); } } exports.default = MapWorldInstance; diff --git a/package.json b/package.json index 3fc9286..e519176 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "devDependencies": { "@types/ali-oss": "^6.16.11", "@types/node": "^20.6.1", + "@types/proj4": "^2.5.5", "ts-node": "^10.9.1", "tslib": "^2.4.0", "typescript": "^5.2.2" @@ -34,6 +35,7 @@ "cos-wx-sdk-v5": "^1.7.1", "isomorphic-fetch": "^3.0.0", "oak-domain": "file:../oak-domain", + "proj4": "^2.15.0", "tencentcloud-sdk-nodejs": "^4.0.746", "ts-md5": "^1.3.1" } diff --git a/src/MapWorldSDK.ts b/src/MapWorldSDK.ts new file mode 100644 index 0000000..bea5085 --- /dev/null +++ b/src/MapWorldSDK.ts @@ -0,0 +1,26 @@ +import MapWorldInstance from "./service/mapWorld/mapWorld"; + +class MapWorldSDK { + webKeyMap: Record; + + constructor() { + this.webKeyMap = {}; + } + + getInstance(key: string) { + if (this.webKeyMap[key]) { + return this.webKeyMap[key]; + } + const instance = new MapWorldInstance(key); + Object.assign(this.webKeyMap, { + [key]: instance, + }); + return instance; + } +} + +const SDK = new MapWorldSDK(); +export default SDK; +export { + MapWorldInstance, +} diff --git a/src/index.ts b/src/index.ts index 5bfae1a..c0d02e3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ import SmsSdk, { import CTYunSDK, { CTYunInstance } from './CTYunSDK'; import ALiYunSDK, { ALiYunInstance } from './ALiYunSDK'; import TencentYunSDK, { TencentYunInstance } from './TencentYunSDK'; +import MapwordSDK, { MapWorldInstance } from './MapWorldSDK'; export * from './service/amap/Amap'; export { @@ -18,6 +19,7 @@ export { CTYunSDK, ALiYunSDK, TencentYunSDK, + MapwordSDK, CTYunInstance, WechatMpInstance, WechatPublicInstance, @@ -25,6 +27,7 @@ export { QiniuCloudInstance, ALiYunInstance, TencentYunInstance, + MapWorldInstance, SmsSdk, TencentSmsInstance, diff --git a/src/service/amap/Amap.ts b/src/service/amap/Amap.ts index 6f82f9c..3ba0ed6 100644 --- a/src/service/amap/Amap.ts +++ b/src/service/amap/Amap.ts @@ -37,8 +37,8 @@ export class AmapInstance { return jsonData; } - async regeo(data: { longitude: number; latitude: number }) { - const { longitude, latitude } = data; + async regeo(params: { longitude: number; latitude: number }) { + const { longitude, latitude } = params; const url = `https://restapi.amap.com/v3/geocode/regeo?location=${longitude},${latitude}&key=${this.key}`; let response: Response; try { diff --git a/src/service/mapWorld/mapWorld.ts b/src/service/mapWorld/mapWorld.ts index c3cae30..58aa52f 100644 --- a/src/service/mapWorld/mapWorld.ts +++ b/src/service/mapWorld/mapWorld.ts @@ -1,14 +1,141 @@ +require('../../utils/fetch'); +import assert from 'assert'; +import { + OakExternalException, + OakNetworkException, + OakServerProxyException, +} from 'oak-domain/lib/types/Exception'; + +function codeEnc(code: string) { + return code.startsWith('156') ? code : `156${code}`; +} + +function codeDec(code: string) { + return code.startsWith('156') ? code.slice(3) : code; +} + export default class MapWorldInstance { key: string; + constructor(key: string) { this.key = key; } - geo() { + /** + * http://lbs.tianditu.gov.cn/server/search2.html + * @param keyWord + * @param areaId + * @param start + * @param count + * @returns + */ + async geo(keyWord: string, areaId?: string, start?: number, count?: number): Promise> { + const start2 = start || 0; + const count2 = count || 100; + const url = `http://api.tianditu.gov.cn/v2/search?postStr={"keyWord":"${keyWord}","queryType":12,"start":${start2},"count":${count2},"specify": "${codeEnc(areaId || '000000')}","show":"2"}&type=query&tk=${this.key}`; + let response: Response; + try { + response = await global.fetch(url); + } catch (err) { + throw new OakNetworkException(`访问mapworld接口失败,「${url}」`); + } + const jsonData = await response.json(); + // 天地图的文档没有很规范的定义错误,只能根据测到的情况硬写 + if (!jsonData.status) { + const { code, msg, resolve } = jsonData; + + if (msg) { + throw new OakExternalException( + 'mapworld', + code, + msg + ); + } + throw new OakExternalException( + 'mapworld', + '-1', + `${JSON.stringify(jsonData)}`, + ); + } + if (jsonData.status.infocode !== 1000) { + throw new OakExternalException( + 'mapworld', + jsonData.status.infocode, + jsonData.status.cndesc + ); + } + + const { resultType, statistics, pois } = jsonData; + + if (resultType === 2) { + // 如果以156000000(中国)作为搜索范围,可能会返回统计结果,用统计结果中的数据再次查询 + assert(statistics); + const { allAdmins } = statistics; + + const result: Array<{ + poiName: string; + areaId: string; + longitude: number; + latitude: number; + }> = []; + + let passed = 0; + const getFromSub = async (idx: number): Promise => { + const admin = allAdmins[idx]; + if (admin) { + const { adminCode, count: adminCount } = admin; + if (passed + adminCount < start2) { + // 这个sub已经被pass + passed += adminCount; + return await getFromSub(idx + 1); + } + else { + const start3 = start2 - passed; + result.push(...(await this.geo(keyWord, `${adminCode}`, start3, count2))); + if (result.length === count2) { + return result; + } + await getFromSub(idx + 1); + } + } + return result; + }; + + return await getFromSub(0); + } + else { + assert(resultType === 1); + if (jsonData.count === '0') { + return []; + } + assert(pois); + + // 天地图返回的是wgs84坐标 + return pois.map( + (ele: any) => { + const { name, lonlat, countyCode, cityCode, provinceCode } = ele; + + const tudes = lonlat.split(',').map( + (ele: string) => parseFloat(ele) + ) as [number, number]; + return { + poiName: name, + areaId: codeDec(countyCode || cityCode || provinceCode), + longitude: tudes[0], + latitude: tudes[1], + }; + } + ); + } } - regeo() { - + regeo(params: { longitude: number; latitude: number }): Promise { + throw new Error('not implement yet'); } } \ No newline at end of file diff --git a/test/test.ts b/test/test.ts index 3d67f07..bbcc406 100644 --- a/test/test.ts +++ b/test/test.ts @@ -1 +1 @@ -import './testTianDitu'; \ No newline at end of file +import './testTrans'; \ No newline at end of file diff --git a/test/testTianDitu.ts b/test/testTianDitu.ts index 1455209..eabf1f4 100644 --- a/test/testTianDitu.ts +++ b/test/testTianDitu.ts @@ -1,4 +1,4 @@ -fetch(encodeURI('http://api.tianditu.gov.cn/v2/search?postStr={"keyWord":"星洲花园","queryType":12,"start":0,"count":1,"specify":"156330102","show": "2"}&type=query&tk=f2dc58487a896ed5623231cde51b3dda')) +fetch(encodeURI('http://api.tianditu.gov.cn/v2/search?postStr={"keyWord":"浙江大学","queryType":12,"start":0,"count":10,"specify":"156330100","show":"2"}&type=query&tk=')) .then( (result) => { console.log(result.status);