7 files changed
+916
No files matched your search
Generated
+102
@@ -10,10 +10,15 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/check": "^0.9.9",
|
"@astrojs/check": "^0.9.9",
|
||||||
"astro": "^7.1.0",
|
"astro": "^7.1.0",
|
||||||
|
"cn-atlas": "^0.1.2",
|
||||||
|
"d3-geo": "^3.1.1",
|
||||||
|
"topojson-client": "^3.1.0",
|
||||||
"typescript": "^6.0.3"
|
"typescript": "^6.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/d3-geo": "^3.1.0",
|
||||||
"@types/node": "^26.1.1",
|
"@types/node": "^26.1.1",
|
||||||
|
"@types/topojson-client": "^3.1.5",
|
||||||
"tsx": "^4.23.1"
|
"tsx": "^4.23.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2086,6 +2091,16 @@
|
|||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/d3-geo": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/geojson": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.9",
|
"version": "1.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
|
||||||
@@ -2101,6 +2116,13 @@
|
|||||||
"@types/estree": "*"
|
"@types/estree": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/geojson": {
|
||||||
|
"version": "7946.0.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
|
||||||
|
"integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/hast": {
|
"node_modules/@types/hast": {
|
||||||
"version": "3.0.5",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz",
|
||||||
@@ -2138,6 +2160,27 @@
|
|||||||
"undici-types": "~8.3.0"
|
"undici-types": "~8.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/topojson-client": {
|
||||||
|
"version": "3.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/topojson-client/-/topojson-client-3.1.5.tgz",
|
||||||
|
"integrity": "sha512-C79rySTyPxnQNNguTZNI1Ct4D7IXgvyAs3p9HPecnl6mNrJ5+UhvGNYcZfpROYV2lMHI48kJPxwR+F9C6c7nmw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/geojson": "*",
|
||||||
|
"@types/topojson-specification": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/topojson-specification": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/topojson-specification/-/topojson-specification-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-C7KvcQh+C2nr6Y2Ub4YfgvWvWCgP2nOQMtfhlnwsRL4pYmmwzBS7HclGiS87eQfDOU/DLQpX6GEscviaz4yLIQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/geojson": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/unist": {
|
"node_modules/@types/unist": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
||||||
@@ -2553,6 +2596,12 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cn-atlas": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cn-atlas/-/cn-atlas-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-boViEllOaFIANaZ4ujemMIR6ryDm1619qcdp20yEd5sAR/SF2uUAZLcV9IY7PlseaTCw4muSLSOPo1valLpOxw==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/color-convert": {
|
"node_modules/color-convert": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
@@ -2701,6 +2750,30 @@
|
|||||||
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
|
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
|
||||||
"license": "CC0-1.0"
|
"license": "CC0-1.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/d3-array": {
|
||||||
|
"version": "3.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
|
||||||
|
"integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"internmap": "1 - 2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-geo": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-array": "2.5.0 - 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/defu": {
|
"node_modules/defu": {
|
||||||
"version": "6.1.7",
|
"version": "6.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz",
|
||||||
@@ -3223,6 +3296,15 @@
|
|||||||
"integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
|
"integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
|
||||||
"license": "BSD-2-Clause"
|
"license": "BSD-2-Clause"
|
||||||
},
|
},
|
||||||
|
"node_modules/internmap": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/iron-webcrypto": {
|
"node_modules/iron-webcrypto": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz",
|
||||||
@@ -4393,6 +4475,26 @@
|
|||||||
"url": "https://github.com/sponsors/SuperchupuDev"
|
"url": "https://github.com/sponsors/SuperchupuDev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/topojson-client": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"topo2geo": "bin/topo2geo",
|
||||||
|
"topomerge": "bin/topomerge",
|
||||||
|
"topoquantize": "bin/topoquantize"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/topojson-client/node_modules/commander": {
|
||||||
|
"version": "2.20.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||||
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/trim-lines": {
|
"node_modules/trim-lines": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
|
||||||
|
|||||||
@@ -13,10 +13,15 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/check": "^0.9.9",
|
"@astrojs/check": "^0.9.9",
|
||||||
"astro": "^7.1.0",
|
"astro": "^7.1.0",
|
||||||
|
"cn-atlas": "^0.1.2",
|
||||||
|
"d3-geo": "^3.1.1",
|
||||||
|
"topojson-client": "^3.1.0",
|
||||||
"typescript": "^6.0.3"
|
"typescript": "^6.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/d3-geo": "^3.1.0",
|
||||||
"@types/node": "^26.1.1",
|
"@types/node": "^26.1.1",
|
||||||
|
"@types/topojson-client": "^3.1.5",
|
||||||
"tsx": "^4.23.1"
|
"tsx": "^4.23.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import { people } from "./people";
|
||||||
|
|
||||||
|
export interface ClassMapEntry {
|
||||||
|
personSlug: string;
|
||||||
|
city: string;
|
||||||
|
province: string;
|
||||||
|
/** 城市中心点经度,仅用于城市级地图投影。 */
|
||||||
|
longitude: number;
|
||||||
|
/** 城市中心点纬度,仅用于城市级地图投影。 */
|
||||||
|
latitude: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 只有明确同意在班级地图公开的同学,才应出现在这个列表中。
|
||||||
|
* 地图仅展示城市中心点,不采集或保存个人精确位置。
|
||||||
|
*/
|
||||||
|
export const classMapEntries: ClassMapEntry[] = [
|
||||||
|
{ personSlug: "student-a", city: "北京", province: "北京市", longitude: 116.4074, latitude: 39.9042 },
|
||||||
|
{ personSlug: "biss", city: "高平", province: "山西省", longitude: 112.9239, latitude: 35.798 }
|
||||||
|
];
|
||||||
|
|
||||||
|
const peopleBySlug = new Map(people.map((person) => [person.slug, person]));
|
||||||
|
|
||||||
|
const toMapPerson = (person: (typeof people)[number]) => ({
|
||||||
|
slug: person.slug,
|
||||||
|
initial: person.initial,
|
||||||
|
name: person.name,
|
||||||
|
photo: person.photo,
|
||||||
|
direction: person.direction
|
||||||
|
});
|
||||||
|
|
||||||
|
export const mapCities = Array.from(
|
||||||
|
classMapEntries.reduce((cities, entry) => {
|
||||||
|
const person = peopleBySlug.get(entry.personSlug);
|
||||||
|
if (!person) return cities;
|
||||||
|
|
||||||
|
const key = `${entry.province}-${entry.city}`;
|
||||||
|
const existing = cities.get(key);
|
||||||
|
|
||||||
|
if (existing) {
|
||||||
|
existing.people.push(toMapPerson(person));
|
||||||
|
} else {
|
||||||
|
cities.set(key, {
|
||||||
|
key,
|
||||||
|
city: entry.city,
|
||||||
|
province: entry.province,
|
||||||
|
longitude: entry.longitude,
|
||||||
|
latitude: entry.latitude,
|
||||||
|
people: [toMapPerson(person)]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return cities;
|
||||||
|
}, new Map<string, {
|
||||||
|
key: string;
|
||||||
|
city: string;
|
||||||
|
province: string;
|
||||||
|
longitude: number;
|
||||||
|
latitude: number;
|
||||||
|
people: ReturnType<typeof toMapPerson>[];
|
||||||
|
}>()).values()
|
||||||
|
).sort((a, b) => b.people.length - a.people.length || a.city.localeCompare(b.city, "zh-CN"));
|
||||||
|
|
||||||
|
export const mapStats = {
|
||||||
|
cityCount: mapCities.length,
|
||||||
|
publicPeopleCount: mapCities.reduce((total, city) => total + city.people.length, 0),
|
||||||
|
provinceCount: new Set(mapCities.map((city) => city.province)).size
|
||||||
|
};
|
||||||
Loaded 3 of 7 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user