实现了天地图的部分功能

This commit is contained in:
Xu Chang 2024-11-25 10:31:29 +08:00
parent 1270466056
commit 1f2dcf12f6
24 changed files with 479 additions and 26 deletions

2
.gitignore vendored
View File

@ -66,4 +66,4 @@ build
package-lock.json package-lock.json
dist dist
test/app-domain test

9
es/MapWorldSDK.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
import MapWorldInstance from "./service/mapWorld/mapWorld";
declare class MapWorldSDK {
webKeyMap: Record<string, MapWorldInstance>;
constructor();
getInstance(key: string): MapWorldInstance;
}
declare const SDK: MapWorldSDK;
export default SDK;
export { MapWorldInstance, };

20
es/MapWorldSDK.js Normal file
View File

@ -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, };

3
es/index.d.ts vendored
View File

@ -5,6 +5,7 @@ import SmsSdk, { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance } from './
import CTYunSDK, { CTYunInstance } from './CTYunSDK'; import CTYunSDK, { CTYunInstance } from './CTYunSDK';
import ALiYunSDK, { ALiYunInstance } from './ALiYunSDK'; import ALiYunSDK, { ALiYunInstance } from './ALiYunSDK';
import TencentYunSDK, { TencentYunInstance } from './TencentYunSDK'; import TencentYunSDK, { TencentYunInstance } from './TencentYunSDK';
import MapwordSDK, { MapWorldInstance } from './MapWorldSDK';
export * from './service/amap/Amap'; 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'; export * from './types';

View File

@ -5,6 +5,7 @@ import SmsSdk, { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance, } from '.
import CTYunSDK, { CTYunInstance } from './CTYunSDK'; import CTYunSDK, { CTYunInstance } from './CTYunSDK';
import ALiYunSDK, { ALiYunInstance } from './ALiYunSDK'; import ALiYunSDK, { ALiYunInstance } from './ALiYunSDK';
import TencentYunSDK, { TencentYunInstance } from './TencentYunSDK'; import TencentYunSDK, { TencentYunInstance } from './TencentYunSDK';
import MapwordSDK, { MapWorldInstance } from './MapWorldSDK';
export * from './service/amap/Amap'; 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'; export * from './types';

View File

@ -5,7 +5,7 @@ export declare class AmapInstance {
from: [number, number]; from: [number, number];
to: [number, number]; to: [number, number];
}): Promise<any>; }): Promise<any>;
regeo(data: { regeo(params: {
longitude: number; longitude: number;
latitude: number; latitude: number;
}): Promise<any>; }): Promise<any>;
@ -16,6 +16,11 @@ export declare class AmapInstance {
keywords: string; keywords: string;
subdistrict: string; subdistrict: string;
}): Promise<any>; }): Promise<any>;
/**
*
* @param data
* @returns
*/
geocode(data: { geocode(data: {
address: string; address: string;
city?: string; city?: string;

View File

@ -21,8 +21,8 @@ export class AmapInstance {
} }
return jsonData; return jsonData;
} }
async regeo(data) { async regeo(params) {
const { longitude, latitude } = data; const { longitude, latitude } = params;
const url = `https://restapi.amap.com/v3/geocode/regeo?location=${longitude},${latitude}&key=${this.key}`; const url = `https://restapi.amap.com/v3/geocode/regeo?location=${longitude},${latitude}&key=${this.key}`;
let response; let response;
try { try {
@ -69,6 +69,11 @@ export class AmapInstance {
} }
return jsonData; return jsonData;
} }
/**
* 高德这个接口搜索能力很弱但高级接口要收费只能先暂时用着
* @param data
* @returns
*/
async geocode(data) { async geocode(data) {
const { address, city } = data; const { address, city } = data;
const url = `https://restapi.amap.com/v3/geocode/geo?address=${address}${city ? `&city=${city}` : ''}&key=${this.key}`; const url = `https://restapi.amap.com/v3/geocode/geo?address=${address}${city ? `&city=${city}` : ''}&key=${this.key}`;

View File

@ -1,6 +1,22 @@
export default class MapWorldInstance { export default class MapWorldInstance {
key: string; key: string;
constructor(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<Array<{
poiName: string;
areaId: string;
longitude: number;
latitude: number;
}>>;
regeo(params: {
longitude: number;
latitude: number;
}): Promise<any>;
} }

View File

@ -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 { export default class MapWorldInstance {
key; key;
constructor(key) { constructor(key) {
this.key = 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');
} }
} }

9
lib/MapWorldSDK.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
import MapWorldInstance from "./service/mapWorld/mapWorld";
declare class MapWorldSDK {
webKeyMap: Record<string, MapWorldInstance>;
constructor();
getInstance(key: string): MapWorldInstance;
}
declare const SDK: MapWorldSDK;
export default SDK;
export { MapWorldInstance, };

24
lib/MapWorldSDK.js Normal file
View File

@ -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;

3
lib/index.d.ts vendored
View File

@ -5,6 +5,7 @@ import SmsSdk, { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance } from './
import CTYunSDK, { CTYunInstance } from './CTYunSDK'; import CTYunSDK, { CTYunInstance } from './CTYunSDK';
import ALiYunSDK, { ALiYunInstance } from './ALiYunSDK'; import ALiYunSDK, { ALiYunInstance } from './ALiYunSDK';
import TencentYunSDK, { TencentYunInstance } from './TencentYunSDK'; import TencentYunSDK, { TencentYunInstance } from './TencentYunSDK';
import MapwordSDK, { MapWorldInstance } from './MapWorldSDK';
export * from './service/amap/Amap'; 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'; export * from './types';

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); 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 tslib_1 = require("tslib");
const WechatSDK_1 = tslib_1.__importStar(require("./WechatSDK")); const WechatSDK_1 = tslib_1.__importStar(require("./WechatSDK"));
exports.WechatSDK = WechatSDK_1.default; 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")); const TencentYunSDK_1 = tslib_1.__importStar(require("./TencentYunSDK"));
exports.TencentYunSDK = TencentYunSDK_1.default; exports.TencentYunSDK = TencentYunSDK_1.default;
Object.defineProperty(exports, "TencentYunInstance", { enumerable: true, get: function () { return TencentYunSDK_1.TencentYunInstance; } }); 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("./service/amap/Amap"), exports);
tslib_1.__exportStar(require("./types"), exports); tslib_1.__exportStar(require("./types"), exports);

View File

@ -5,7 +5,7 @@ export declare class AmapInstance {
from: [number, number]; from: [number, number];
to: [number, number]; to: [number, number];
}): Promise<any>; }): Promise<any>;
regeo(data: { regeo(params: {
longitude: number; longitude: number;
latitude: number; latitude: number;
}): Promise<any>; }): Promise<any>;
@ -16,6 +16,11 @@ export declare class AmapInstance {
keywords: string; keywords: string;
subdistrict: string; subdistrict: string;
}): Promise<any>; }): Promise<any>;
/**
*
* @param data
* @returns
*/
geocode(data: { geocode(data: {
address: string; address: string;
city?: string; city?: string;

View File

@ -24,8 +24,8 @@ class AmapInstance {
} }
return jsonData; return jsonData;
} }
async regeo(data) { async regeo(params) {
const { longitude, latitude } = data; const { longitude, latitude } = params;
const url = `https://restapi.amap.com/v3/geocode/regeo?location=${longitude},${latitude}&key=${this.key}`; const url = `https://restapi.amap.com/v3/geocode/regeo?location=${longitude},${latitude}&key=${this.key}`;
let response; let response;
try { try {
@ -72,6 +72,11 @@ class AmapInstance {
} }
return jsonData; return jsonData;
} }
/**
* 高德这个接口搜索能力很弱但高级接口要收费只能先暂时用着
* @param data
* @returns
*/
async geocode(data) { async geocode(data) {
const { address, city } = data; const { address, city } = data;
const url = `https://restapi.amap.com/v3/geocode/geo?address=${address}${city ? `&city=${city}` : ''}&key=${this.key}`; const url = `https://restapi.amap.com/v3/geocode/geo?address=${address}${city ? `&city=${city}` : ''}&key=${this.key}`;

View File

@ -1,6 +1,22 @@
export default class MapWorldInstance { export default class MapWorldInstance {
key: string; key: string;
constructor(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<Array<{
poiName: string;
areaId: string;
longitude: number;
latitude: number;
}>>;
regeo(params: {
longitude: number;
latitude: number;
}): Promise<any>;
} }

View File

@ -1,13 +1,101 @@
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); 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 { class MapWorldInstance {
key; key;
constructor(key) { constructor(key) {
this.key = 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; exports.default = MapWorldInstance;

View File

@ -21,6 +21,7 @@
"devDependencies": { "devDependencies": {
"@types/ali-oss": "^6.16.11", "@types/ali-oss": "^6.16.11",
"@types/node": "^20.6.1", "@types/node": "^20.6.1",
"@types/proj4": "^2.5.5",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tslib": "^2.4.0", "tslib": "^2.4.0",
"typescript": "^5.2.2" "typescript": "^5.2.2"
@ -34,6 +35,7 @@
"cos-wx-sdk-v5": "^1.7.1", "cos-wx-sdk-v5": "^1.7.1",
"isomorphic-fetch": "^3.0.0", "isomorphic-fetch": "^3.0.0",
"oak-domain": "file:../oak-domain", "oak-domain": "file:../oak-domain",
"proj4": "^2.15.0",
"tencentcloud-sdk-nodejs": "^4.0.746", "tencentcloud-sdk-nodejs": "^4.0.746",
"ts-md5": "^1.3.1" "ts-md5": "^1.3.1"
} }

26
src/MapWorldSDK.ts Normal file
View File

@ -0,0 +1,26 @@
import MapWorldInstance from "./service/mapWorld/mapWorld";
class MapWorldSDK {
webKeyMap: Record<string, MapWorldInstance>;
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,
}

View File

@ -9,6 +9,7 @@ import SmsSdk, {
import CTYunSDK, { CTYunInstance } from './CTYunSDK'; import CTYunSDK, { CTYunInstance } from './CTYunSDK';
import ALiYunSDK, { ALiYunInstance } from './ALiYunSDK'; import ALiYunSDK, { ALiYunInstance } from './ALiYunSDK';
import TencentYunSDK, { TencentYunInstance } from './TencentYunSDK'; import TencentYunSDK, { TencentYunInstance } from './TencentYunSDK';
import MapwordSDK, { MapWorldInstance } from './MapWorldSDK';
export * from './service/amap/Amap'; export * from './service/amap/Amap';
export { export {
@ -18,6 +19,7 @@ export {
CTYunSDK, CTYunSDK,
ALiYunSDK, ALiYunSDK,
TencentYunSDK, TencentYunSDK,
MapwordSDK,
CTYunInstance, CTYunInstance,
WechatMpInstance, WechatMpInstance,
WechatPublicInstance, WechatPublicInstance,
@ -25,6 +27,7 @@ export {
QiniuCloudInstance, QiniuCloudInstance,
ALiYunInstance, ALiYunInstance,
TencentYunInstance, TencentYunInstance,
MapWorldInstance,
SmsSdk, SmsSdk,
TencentSmsInstance, TencentSmsInstance,

View File

@ -37,8 +37,8 @@ export class AmapInstance {
return jsonData; return jsonData;
} }
async regeo(data: { longitude: number; latitude: number }) { async regeo(params: { longitude: number; latitude: number }) {
const { longitude, latitude } = data; const { longitude, latitude } = params;
const url = `https://restapi.amap.com/v3/geocode/regeo?location=${longitude},${latitude}&key=${this.key}`; const url = `https://restapi.amap.com/v3/geocode/regeo?location=${longitude},${latitude}&key=${this.key}`;
let response: Response; let response: Response;
try { try {

View File

@ -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 { export default class MapWorldInstance {
key: string; key: string;
constructor(key: string) { constructor(key: string) {
this.key = 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: string, areaId?: string, start?: number, count?: number): Promise<Array<{
poiName: string;
areaId: string;
longitude: number;
latitude: number;
}>> {
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<typeof result> => {
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<any> {
throw new Error('not implement yet');
} }
} }

View File

@ -1 +1 @@
import './testTianDitu'; import './testTrans';

View File

@ -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( .then(
(result) => { (result) => {
console.log(result.status); console.log(result.status);