diff --git a/package.json b/package.json index d7411c5..5807689 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@ant-design/cssinjs": "^2.1.2", + "@ant-design/icons": "^6.2.2", "@reduxjs/toolkit": "^2.11.2", "@tailwindcss/vite": "^4.2.4", "@tanstack/react-virtual": "^3.13.24", @@ -27,6 +28,7 @@ "tailwindcss": "^4.2.4" }, "devDependencies": { + "@tailwindcss/typography": "^0.5.19", "@types/node": "^22.19.17", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", @@ -35,6 +37,7 @@ "prettier": "^3.8.3", "typescript": "~6.0.3", "vite": "^8.0.11", + "vite-plugin-markdown": "^2.2.0", "vite-plugin-port-checker": "^1.0.1" }, "pnpm": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9796d18..3751038 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@ant-design/cssinjs': specifier: ^2.1.2 version: 2.1.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@ant-design/icons': + specifier: ^6.2.2 + version: 6.2.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@reduxjs/toolkit': specifier: ^2.11.2 version: 2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.6)(redux@5.0.1))(react@19.2.6) @@ -51,6 +54,9 @@ importers: specifier: ^4.2.4 version: 4.2.4 devDependencies: + '@tailwindcss/typography': + specifier: ^0.5.19 + version: 0.5.19(tailwindcss@4.2.4) '@types/node': specifier: ^22.19.17 version: 22.19.17 @@ -75,6 +81,9 @@ importers: vite: specifier: ^8.0.11 version: 8.0.11(@types/node@22.19.17)(jiti@2.6.1) + vite-plugin-markdown: + specifier: ^2.2.0 + version: 2.2.0(vite@8.0.11(@types/node@22.19.17)(jiti@2.6.1)) vite-plugin-port-checker: specifier: ^1.0.1 version: 1.0.1(vite@8.0.11(@types/node@22.19.17)(jiti@2.6.1)) @@ -656,6 +665,11 @@ packages: resolution: {integrity: sha512-9El/iI069DKDSXwTvB9J4BwdO5JhRrOweGaK25taBAvBXyXqJAX+Jqdvs8r8gKpsI/1m0LeJLyQYTf/WLrBT1Q==} engines: {node: '>= 20'} + '@tailwindcss/typography@0.5.19': + resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' + '@tailwindcss/vite@4.2.4': resolution: {integrity: sha512-pCvohwOCspk3ZFn6eJzrrX3g4n2JY73H6MmYC87XfGPyTty4YsCjYTMArRZm/zOI8dIt3+EcrLHAFPe5A4bgtw==} peerDependencies: @@ -706,6 +720,12 @@ packages: react: '>=18.0.0' react-dom: '>=18.0.0' + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -731,6 +751,11 @@ packages: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -745,6 +770,19 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -753,6 +791,12 @@ packages: resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==} engines: {node: '>=10.13.0'} + entities@2.1.0: + resolution: {integrity: sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -769,6 +813,11 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -791,6 +840,9 @@ packages: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} + front-matter@4.0.2: + resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -830,6 +882,9 @@ packages: resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} engines: {node: '>= 0.4'} + htmlparser2@6.1.0: + resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} + immer@11.1.4: resolution: {integrity: sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==} @@ -840,6 +895,10 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + hasBin: true + json2mq@0.2.0: resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} @@ -917,13 +976,23 @@ packages: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} + linkify-it@3.0.3: + resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==} + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + markdown-it@12.3.2: + resolution: {integrity: sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==} + hasBin: true + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + mdurl@1.0.1: + resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} + mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -944,6 +1013,10 @@ packages: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} + postcss-selector-parser@6.0.10: + resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} + engines: {node: '>=4'} + postcss@8.5.14: resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} engines: {node: ^10 || ^12 || >=14} @@ -1036,6 +1109,9 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + string-convert@0.2.1: resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==} @@ -1065,6 +1141,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + uc.micro@1.0.6: + resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} + undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} @@ -1073,6 +1152,14 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vite-plugin-markdown@2.2.0: + resolution: {integrity: sha512-eH2tXMZcx3EHb5okd+/0VIyoR8Gp9pGe24UXitOOcGkzObbJ1vl48aGOAbakoT88FBdzC8MXNkMfBIB9VK0Ndg==} + peerDependencies: + vite: '>= 2.0.0' + vite-plugin-port-checker@1.0.1: resolution: {integrity: sha512-Mx/Pj5zyu4oak+SKGwQyRLGAvnp9zx0nqjCLhaJoGJeZk2t4EarZojTcHGG0gPMJWj9X6c0MIfzaZDslg80/GA==} peerDependencies: @@ -1702,6 +1789,11 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.2.4 '@tailwindcss/oxide-win32-x64-msvc': 4.2.4 + '@tailwindcss/typography@0.5.19(tailwindcss@4.2.4)': + dependencies: + postcss-selector-parser: 6.0.10 + tailwindcss: 4.2.4 + '@tailwindcss/vite@4.2.4(vite@8.0.11(@types/node@22.19.17)(jiti@2.6.1))': dependencies: '@tailwindcss/node': 4.2.4 @@ -1798,6 +1890,12 @@ snapshots: - luxon - moment + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + asynckit@0.4.0: {} axios@1.16.0: @@ -1823,6 +1921,8 @@ snapshots: cookie@1.1.1: {} + cssesc@3.0.0: {} + csstype@3.2.3: {} dayjs@1.11.20: {} @@ -1831,6 +1931,24 @@ snapshots: detect-libc@2.1.2: {} + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + domelementtype@2.3.0: {} + + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 + + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -1842,6 +1960,10 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.3 + entities@2.1.0: {} + + entities@2.2.0: {} + es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -1857,6 +1979,8 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.3 + esprima@4.0.1: {} + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: picomatch: 4.0.4 @@ -1871,6 +1995,10 @@ snapshots: hasown: 2.0.3 mime-types: 2.1.35 + front-matter@4.0.2: + dependencies: + js-yaml: 3.14.2 + fsevents@2.3.3: optional: true @@ -1910,12 +2038,24 @@ snapshots: dependencies: function-bind: 1.1.2 + htmlparser2@6.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + domutils: 2.8.0 + entities: 2.2.0 + immer@11.1.4: {} is-mobile@5.0.0: {} jiti@2.6.1: {} + js-yaml@3.14.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + json2mq@0.2.0: dependencies: string-convert: 0.2.1 @@ -1969,12 +2109,26 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 + linkify-it@3.0.3: + dependencies: + uc.micro: 1.0.6 + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + markdown-it@12.3.2: + dependencies: + argparse: 2.0.1 + entities: 2.1.0 + linkify-it: 3.0.3 + mdurl: 1.0.1 + uc.micro: 1.0.6 + math-intrinsics@1.1.0: {} + mdurl@1.0.1: {} + mime-db@1.52.0: {} mime-types@2.1.35: @@ -1987,6 +2141,11 @@ snapshots: picomatch@4.0.4: {} + postcss-selector-parser@6.0.10: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + postcss@8.5.14: dependencies: nanoid: 3.3.12 @@ -2074,6 +2233,8 @@ snapshots: source-map-js@1.2.1: {} + sprintf-js@1.0.3: {} + string-convert@0.2.1: {} stylis@4.3.6: {} @@ -2094,12 +2255,24 @@ snapshots: typescript@6.0.3: {} + uc.micro@1.0.6: {} + undici-types@6.21.0: {} use-sync-external-store@1.6.0(react@19.2.6): dependencies: react: 19.2.6 + util-deprecate@1.0.2: {} + + vite-plugin-markdown@2.2.0(vite@8.0.11(@types/node@22.19.17)(jiti@2.6.1)): + dependencies: + domhandler: 4.3.1 + front-matter: 4.0.2 + htmlparser2: 6.1.0 + markdown-it: 12.3.2 + vite: 8.0.11(@types/node@22.19.17)(jiti@2.6.1) + vite-plugin-port-checker@1.0.1(vite@8.0.11(@types/node@22.19.17)(jiti@2.6.1)): dependencies: vite: 8.0.11(@types/node@22.19.17)(jiti@2.6.1) diff --git a/public/nav_bg.png b/public/nav_bg.png deleted file mode 100644 index 582155c..0000000 Binary files a/public/nav_bg.png and /dev/null differ diff --git a/src/api/firearm-api.ts b/src/api/firearm-api.ts index 9b0bbba..c62cb31 100644 --- a/src/api/firearm-api.ts +++ b/src/api/firearm-api.ts @@ -7,9 +7,9 @@ interface FirearmParams extends PageQueryParams { } /** - * 查询武器列表 + * Fetch firearm list * - * @param params 分页查询参数¬ + * @param params Paged query parameters */ export async function getFirearms(params?: FirearmParams): Promise> { let uri = "/firearms" @@ -28,9 +28,9 @@ export async function getFirearms(params?: FirearmParams): Promise } /** - * 根据 ID 查询武器 + * Fetch firearm by ID * - * @param id 武器 ID + * @param id Firearm ID */ export async function getFirearm(id: number): Promise { const { data } = await WebClient.get(`/firearms/${id}`) @@ -38,7 +38,7 @@ export async function getFirearm(id: number): Promise { } /** - * 新建武器 + * Create firearm * @param request */ export async function addFirearm(request: AddFirearmRequest): Promise { diff --git a/src/components/markdown-renderer/index.tsx b/src/components/markdown-renderer/index.tsx new file mode 100644 index 0000000..732fbe3 --- /dev/null +++ b/src/components/markdown-renderer/index.tsx @@ -0,0 +1,17 @@ +import React from "react" + +interface MarkdownRendererProps { + /** HTML string processed by vite-plugin-markdown */ + html: string + /** Optional custom class name */ + className?: string +} + +export default function MarkdownRenderer({ html, className = "" }: MarkdownRendererProps) { + return ( +
+ ) +} diff --git a/src/index.css b/src/index.css index 63db6f0..a03856c 100644 --- a/src/index.css +++ b/src/index.css @@ -1,6 +1,7 @@ @layer theme, base, antd, components, utilities; @import 'tailwindcss'; +@plugin "@tailwindcss/typography"; html, body { margin: 0; @@ -56,7 +57,7 @@ html, body { .nav-item:hover::after, .nav-item.active::after { - height: 80%; /* 向上打光的高度,可以调整 */ + height: 80%; /* Height of the upward glow; adjustable. */ } .nav-item:hover, diff --git a/src/layout/hero-layout/index.tsx b/src/layout/hero-layout/index.tsx index f45b8bc..ef83e32 100644 --- a/src/layout/hero-layout/index.tsx +++ b/src/layout/hero-layout/index.tsx @@ -2,10 +2,16 @@ import { Outlet, Link, NavLink } from "react-router-dom" import { useMemo } from "react" import dayjs from "dayjs" import { Dropdown } from "antd" +import { + FileTextOutlined, + GithubOutlined, + LockOutlined, + LoginOutlined, +} from "@ant-design/icons" import { AuthApi } from "@/api" import { useAppDispatch, useAppSelector } from "@/store/hooks" import { clearCurrentUser } from "@/store/auth-slice" -import { useState } from 'react'; +import { useState } from "react" /** * Main application component that serves as the root layout. @@ -15,7 +21,7 @@ export default function HeroLayout() { const today = useMemo(() => dayjs(), []) const user = useAppSelector((state) => state.auth.user) const dispatch = useAppDispatch() - const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const [isDropdownOpen, setIsDropdownOpen] = useState(false) async function handleLogout() { try { @@ -28,29 +34,29 @@ export default function HeroLayout() { return (
{/* Navigation Header */} -
-
-
+
+
+

《三角洲》指南

-
diff --git a/src/markdown.d.ts b/src/markdown.d.ts new file mode 100644 index 0000000..ad2af77 --- /dev/null +++ b/src/markdown.d.ts @@ -0,0 +1,6 @@ +declare module "*.md" { + const attributes: Record + const html: string + const toc: { level: string; content: string; slug: string }[] + export { attributes, html, toc } +} diff --git a/src/page/legal/index.tsx b/src/page/legal/index.tsx new file mode 100644 index 0000000..c108514 --- /dev/null +++ b/src/page/legal/index.tsx @@ -0,0 +1,34 @@ +import { Tabs } from "antd" +import { useSearchParams } from "react-router-dom" +import MarkdownRenderer from "@/components/markdown-renderer" +import { html as EulaHtml } from "@/docs/EULA.md" +import { html as PrivacyHtml } from "@/docs/PrivacyPolicy.md" + +const tabKeys = new Set(["eula", "privacy"]) + +export default function LegalPage() { + const [searchParams, setSearchParams] = useSearchParams() + const rawTab = searchParams.get("tab") + const activeTab = rawTab && tabKeys.has(rawTab) ? rawTab : "eula" + + return ( +
+ setSearchParams({ tab: key })} + items={[ + { + key: "eula", + label: "最终用户许可协议", + children: , + }, + { + key: "privacy", + label: "隐私政策", + children: , + }, + ]} + /> +
+ ) +} diff --git a/src/router/index.tsx b/src/router/index.tsx index c45341f..a9bd1aa 100644 --- a/src/router/index.tsx +++ b/src/router/index.tsx @@ -40,6 +40,10 @@ const router = createBrowserRouter( path: "mod-codes", lazy: lazy(() => import("@/page/mod-codes")), }, + { + path: "legal", + lazy: lazy(() => import("@/page/legal")) + } ], }, { diff --git a/tailwind.config.ts b/tailwind.config.ts new file mode 100644 index 0000000..5170b8b --- /dev/null +++ b/tailwind.config.ts @@ -0,0 +1,10 @@ +import type { Config } from "tailwindcss" +import typography from "@tailwindcss/typography" + +export default { + content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], + theme: { + extend: {}, + }, + plugins: [typography], +} satisfies Config diff --git a/vite.config.ts b/vite.config.ts index dde1d6d..629a4ba 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -3,10 +3,11 @@ import { defineConfig } from "vite" import react from "@vitejs/plugin-react" import tailwindcss from "@tailwindcss/vite" import portChecker from "vite-plugin-port-checker" +import { Mode, plugin as markdown } from "vite-plugin-markdown" // https://vite.dev/config/ export default defineConfig({ - plugins: [react(), tailwindcss(), portChecker()], + plugins: [react(), tailwindcss(), portChecker(), markdown({ mode: [Mode.HTML, Mode.TOC] })], base: "/", build: { rolldownOptions: {