diff --git a/src/components/Search.tsx b/src/components/Search.tsx
index a6263e7..a7362e9 100644
--- a/src/components/Search.tsx
+++ b/src/components/Search.tsx
@@ -1,5 +1,5 @@
-import { useEffect, useState, useTransition } from 'react';
-import { useSearchParams } from 'react-router-dom';
+import { useEffect, useMemo, useState, useTransition } from 'react';
+import { Link, useSearchParams } from 'react-router-dom';
import {
Header,
Input,
@@ -14,10 +14,10 @@ import PersonCard from '@/components/PersonCard';
import getGrade, { currentYear } from '@/utils/getGrade';
import compareGrades from '@/utils/compareGrades';
import {
- provinces,
type OIer,
genders,
searchableGenderKeys,
+ provincesWithId,
} from '@/libs/OIerDb';
import styles from './Search.module.less';
@@ -49,6 +49,18 @@ const Search: React.FC = () => {
school: '',
});
+ const provinces = useMemo(
+ () =>
+ Object.entries(provincesWithId).map(([id, province]) => ({
+ key: id,
+ value: province,
+ text: `${province} (${id})`,
+ content: province,
+ label: { content: id, basic: true, size: 'mini' },
+ })),
+ []
+ );
+
const province = searchParams.get('province') || '';
const setProvince = (province: string) => setSearchParams({ province });
@@ -70,14 +82,15 @@ const Search: React.FC = () => {
startTransition(() => {
let result: OIer[] = [];
+
if (!advanced) {
result = OIerDb.oiers.filter(
(oier) => oier.lowered_name === input || oier.initials === input
);
+ } else if (!input && !grade && !school) {
+ result = [];
} else {
result = OIerDb.oiers.filter((oier) => {
- if (!(input || province || grade || school)) return false;
-
let res = Boolean(input || province || grade || school || gender);
if (input) {
@@ -156,11 +169,7 @@ const Search: React.FC = () => {
search
selection
clearable
- options={provinces.map((province) => ({
- key: province,
- value: province,
- text: province,
- }))}
+ options={provinces}
defaultValue={province}
onChange={(_, { value }) => setProvince(value as string)}
/>
@@ -231,7 +240,18 @@ const Search: React.FC = () => {
<>
{input || province || grade || school || gender ? (
- {gender ? '暂时不支持仅按照性别搜索选手。' : '未找到结果。'}
+ {gender || province ? (
+ gender ? (
+ '暂时不支持仅按照性别搜索选手。'
+ ) : (
+ <>
+ 请访问「
+ 选手」页面查询某省的所有选手。
+ >
+ )
+ ) : (
+ '未找到结果。'
+ )}
) : (
<>>
diff --git a/src/libs/OIerDb.ts b/src/libs/OIerDb.ts
index daf76ea..4ad97fe 100644
--- a/src/libs/OIerDb.ts
+++ b/src/libs/OIerDb.ts
@@ -442,42 +442,46 @@ export const initDb = async (setProgressPercent?: (p: number) => void) => {
};
// 省份列表
-export const provinces = [
- '安徽',
- '北京',
- '福建',
- '甘肃',
- '广东',
- '广西',
- '贵州',
- '海南',
- '河北',
- '河南',
- '黑龙江',
- '湖北',
- '湖南',
- '吉林',
- '江苏',
- '江西',
- '辽宁',
- '内蒙古',
- '山东',
- '山西',
- '陕西',
- '上海',
- '四川',
- '天津',
- '新疆',
- '浙江',
- '重庆',
- '宁夏',
- '云南',
- '澳门',
- '香港',
- '青海',
- '西藏',
- '台湾',
-] as const;
+export const provincesWithId = {
+ AH: '安徽',
+ BJ: '北京',
+ FJ: '福建',
+ GS: '甘肃',
+ GD: '广东',
+ GX: '广西',
+ GZ: '贵州',
+ HI: '海南',
+ HE: '河北',
+ HA: '河南',
+ HL: '黑龙江',
+ HB: '湖北',
+ HN: '湖南',
+ JL: '吉林',
+ JS: '江苏',
+ JX: '江西',
+ LN: '辽宁',
+ NM: '内蒙古',
+ SD: '山东',
+ SX: '山西',
+ SN: '陕西',
+ SH: '上海',
+ SC: '四川',
+ TJ: '天津',
+ XJ: '新疆',
+ ZJ: '浙江',
+ CQ: '重庆',
+ NX: '宁夏',
+ YN: '云南',
+ MO: '澳门',
+ HK: '香港',
+ QH: '青海',
+ XC: '西藏',
+ TW: '台湾',
+} as const;
+
+export const provinces = Object.values(
+ provincesWithId
+) as (typeof provincesWithId)[keyof typeof provincesWithId][];
// 奖项列表及颜色
export const awardColors = {
diff --git a/src/pages/contest/[id].tsx b/src/pages/contest/[id].tsx
index 905e12b..1195166 100644
--- a/src/pages/contest/[id].tsx
+++ b/src/pages/contest/[id].tsx
@@ -20,7 +20,7 @@ import getProgress from '@/utils/getProgress';
import fixContestName from '@/utils/fixContestName';
import Pagination from '@/components/Pagination';
import styles from './[id].module.less';
-import { awardColors, awardLevels } from '@/libs/OIerDb';
+import { awardColors, awardLevels, provincesWithId } from '@/libs/OIerDb';
import compareGrades from '@/utils/compareGrades';
const NotFound = lazy(() => import('@/pages/404'));
@@ -52,12 +52,23 @@ const Contest: React.FC = () => {
setSearchParams({ grade: String(grade), page: '1' });
};
- const provinces = useMemo(
- () => [
+ const provinces = useMemo(() => {
+ const withId2 = Object.fromEntries(
+ Object.entries(provincesWithId).map(([id, province]) => [province, id])
+ );
+
+ return [
...new Set(contest.contestants.map((contestant) => contestant.province)),
- ],
- [id]
- );
+ ]
+ .map((province) => ({
+ key: withId2[province],
+ value: province,
+ text: `${province} (${withId2[province]})`,
+ content: province,
+ label: { content: withId2[province], basic: true, size: 'mini' },
+ }))
+ .sort((a, b) => a.key.localeCompare(b.key));
+ }, [id]);
const grades = useMemo(
() => [
@@ -172,11 +183,7 @@ const Contest: React.FC = () => {
clearable
placeholder="省份"
value={province}
- options={provinces.map((province) => ({
- key: province,
- value: province,
- text: province,
- }))}
+ options={provinces}
onChange={(_, { value }) => setProvince(value as string)}
/>