This commit is contained in:
biss committed 2026-07-18 12:40:30 +08:00
1 parent b20f5d736d
commit 03579c51d8
7 files changed
+916

No files matched your search

+102
View File
@@ -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",
+5
View File
@@ -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"
} }
} }
+68
View File
@@ -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