From 1c1fcc5d9791ef22ad816b2a7a0f45474ec27c8a Mon Sep 17 00:00:00 2001 From: LHgeek <1209384461@qq.com> Date: Fri, 27 Feb 2026 15:01:59 +0800 Subject: [PATCH] feature-better by vibe coding use Seed-Code-PrimeRL Signed-off-by: LHgeek <1209384461@qq.com> --- package-lock.json | 285 ------------------------------------ src/App.tsx | 4 + src/components/Header.tsx | 5 + src/interfaces/index.d.ts | 10 ++ src/pages/topics/detail.tsx | 241 ++++++++++++++++++++++++++++++ src/pages/topics/index.tsx | 204 ++++++++++++++++++++++++++ 6 files changed, 464 insertions(+), 285 deletions(-) create mode 100644 src/pages/topics/detail.tsx create mode 100644 src/pages/topics/index.tsx diff --git a/package-lock.json b/package-lock.json index 02e8c03..34836fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2337,34 +2337,6 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", @@ -2587,52 +2559,6 @@ } } }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "optional": true, - "peer": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "optional": true, - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/express": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", - "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", - "optional": true, - "peer": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.31", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", - "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", - "optional": true, - "peer": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, "node_modules/@types/http-proxy": { "version": "1.17.9", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", @@ -2641,13 +2567,6 @@ "@types/node": "*" } }, - "node_modules/@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", - "optional": true, - "peer": true - }, "node_modules/@types/node": { "version": "18.17.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.1.tgz", @@ -2658,20 +2577,6 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "optional": true, - "peer": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "optional": true, - "peer": true - }, "node_modules/@types/react": { "version": "18.0.21", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.21.tgz", @@ -2695,17 +2600,6 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" }, - "node_modules/@types/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", - "optional": true, - "peer": true, - "dependencies": { - "@types/mime": "*", - "@types/node": "*" - } - }, "node_modules/@types/yoga-layout": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/@types/yoga-layout/-/yoga-layout-1.9.2.tgz", @@ -2750,20 +2644,6 @@ "node": ">= 0.6" } }, - "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/ajv-formats": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", @@ -7515,34 +7395,6 @@ "rimraf": "bin.js" } }, - "node_modules/terser": { - "version": "5.15.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz", - "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser/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==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -9579,33 +9431,6 @@ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" }, - "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, "@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", @@ -9753,52 +9578,6 @@ "use-sync-external-store": "^1.2.0" } }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "optional": true, - "peer": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "optional": true, - "peer": true, - "requires": { - "@types/node": "*" - } - }, - "@types/express": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", - "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", - "optional": true, - "peer": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.31", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", - "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", - "optional": true, - "peer": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, "@types/http-proxy": { "version": "1.17.9", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", @@ -9807,13 +9586,6 @@ "@types/node": "*" } }, - "@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", - "optional": true, - "peer": true - }, "@types/node": { "version": "18.17.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.1.tgz", @@ -9824,20 +9596,6 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "optional": true, - "peer": true - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "optional": true, - "peer": true - }, "@types/react": { "version": "18.0.21", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.21.tgz", @@ -9861,17 +9619,6 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" }, - "@types/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", - "optional": true, - "peer": true, - "requires": { - "@types/mime": "*", - "@types/node": "*" - } - }, "@types/yoga-layout": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/@types/yoga-layout/-/yoga-layout-1.9.2.tgz", @@ -9906,14 +9653,6 @@ "negotiator": "0.6.3" } }, - "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true, - "optional": true, - "peer": true - }, "ajv-formats": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", @@ -13375,30 +13114,6 @@ } } }, - "terser": { - "version": "5.15.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz", - "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "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==", - "dev": true, - "optional": true, - "peer": true - } - } - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", diff --git a/src/App.tsx b/src/App.tsx index 09a4d53..8802faf 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -13,6 +13,8 @@ import { ProfilePage } from "./pages/profile"; import { SettingsPage } from "./pages/settings"; import { EditorPage, EditArticlePage } from "./pages/editor"; import { ArticlePage } from "./pages/article"; +import { TopicsPage } from "./pages/topics"; +import { TopicDetailPage } from "./pages/topics/detail"; import { TOKEN_KEY } from "./constants"; @@ -78,6 +80,8 @@ function App() { } /> } /> + } /> + } /> } /> diff --git a/src/components/Header.tsx b/src/components/Header.tsx index aa88295..f6894d4 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -20,6 +20,11 @@ export const Header: React.FC = () => { Home +
  • + + 专题 + +
  • {!isLoggedIn ? ( <>
  • diff --git a/src/interfaces/index.d.ts b/src/interfaces/index.d.ts index a15cc74..cb5c130 100644 --- a/src/interfaces/index.d.ts +++ b/src/interfaces/index.d.ts @@ -33,3 +33,13 @@ export interface IAuthor { image: string; username: string; } + +export interface ITopic { + id: number; + slug: string; + title: string; + description: string; + coverImage: string; + articleCount: number; + createdAt: string; +} diff --git a/src/pages/topics/detail.tsx b/src/pages/topics/detail.tsx new file mode 100644 index 0000000..33c65e8 --- /dev/null +++ b/src/pages/topics/detail.tsx @@ -0,0 +1,241 @@ +import { useState } from "react"; +import { useParams, Link } from "react-router-dom"; +import { useTable } from "@refinedev/core"; +import { IArticle, ITopic } from "../../interfaces"; +import { ArticleList } from "../../components/article"; +import dayjs from "dayjs"; + +const headerStyle: React.CSSProperties = { + position: "relative", + background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)", + minHeight: "320px", + marginBottom: "-60px", + display: "flex", + alignItems: "flex-end", +}; + +const headerOverlayStyle: React.CSSProperties = { + position: "absolute", + top: 0, + left: 0, + right: 0, + bottom: 0, + background: "linear-gradient(180deg, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.6) 100%)", +}; + +const headerBgImageStyle: React.CSSProperties = { + position: "absolute", + top: 0, + left: 0, + right: 0, + bottom: 0, + backgroundSize: "cover", + backgroundPosition: "center", + filter: "blur(8px)", + transform: "scale(1.1)", +}; + +const headerContentStyle: React.CSSProperties = { + position: "relative", + zIndex: 1, + padding: "40px 20px 80px", + maxWidth: "900px", + margin: "0 auto", + color: "#fff", +}; + +const breadcrumbStyle: React.CSSProperties = { + fontSize: "0.9rem", + opacity: 0.9, + marginBottom: "16px", +}; + +const breadcrumbLinkStyle: React.CSSProperties = { + color: "#fff", + textDecoration: "none", + opacity: 0.8, +}; + +const titleStyle: React.CSSProperties = { + fontSize: "2.5rem", + fontWeight: "700", + marginBottom: "16px", + lineHeight: "1.3", +}; + +const descriptionStyle: React.CSSProperties = { + fontSize: "1.15rem", + lineHeight: "1.7", + opacity: 0.95, + marginBottom: "24px", +}; + +const metaRowStyle: React.CSSProperties = { + display: "flex", + alignItems: "center", + gap: "24px", + fontSize: "0.95rem", + opacity: 0.9, +}; + +const metaItemStyle: React.CSSProperties = { + display: "inline-flex", + alignItems: "center", + gap: "6px", + padding: "6px 14px", + background: "rgba(255,255,255,0.15)", + borderRadius: "20px", +}; + +const articleSectionStyle: React.CSSProperties = { + position: "relative", + zIndex: 2, + padding: "0 20px 40px", +}; + +const articleContainerStyle: React.CSSProperties = { + maxWidth: "900px", + margin: "0 auto", + background: "#fff", + borderRadius: "8px", + boxShadow: "0 4px 20px rgba(0,0,0,0.08)", + padding: "30px", +}; + +const sectionTitleStyle: React.CSSProperties = { + fontSize: "1.35rem", + fontWeight: "600", + marginBottom: "20px", + color: "#333", + display: "flex", + alignItems: "center", + gap: "8px", +}; + +const topicData: Record = { + "javascript-advanced": { + id: 1, + slug: "javascript-advanced", + title: "JavaScript 高级编程", + description: "深入探索 JavaScript 的高级特性和最佳实践,包括闭包、原型链、异步编程等核心概念。通过一系列精心设计的文章,带你掌握这门语言的精髓。", + coverImage: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=JavaScript+programming+code+abstract+technology+modern+gradient+background&image_size=landscape_16_9", + articleCount: 24, + createdAt: "2024-01-15T08:00:00Z" + }, + "react-hooks": { + id: 2, + slug: "react-hooks", + title: "React Hooks 实战指南", + description: "全面掌握 React Hooks 的使用方法,从基础 useState 到高级 useCallback、useMemo,构建高性能的现代化 React 应用。", + coverImage: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=React+framework+component+atomic+design+modern+technology+gradient&image_size=landscape_16_9", + articleCount: 18, + createdAt: "2024-02-20T10:30:00Z" + }, + "typescript-mastery": { + id: 3, + slug: "typescript-mastery", + title: "TypeScript 精通之路", + description: "从基础类型到高级类型系统,掌握泛型、条件类型、映射类型等,打造类型安全的企业级应用开发体系。", + coverImage: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=TypeScript+programming+blue+code+abstract+technology+modern+minimalist&image_size=landscape_16_9", + articleCount: 31, + createdAt: "2024-03-10T14:45:00Z" + }, + "nodejs-backend": { + id: 4, + slug: "nodejs-backend", + title: "Node.js 后端开发", + description: "使用 Node.js 构建高性能后端服务,深入学习 Express、RESTful API、数据库操作等核心后端开发技术。", + coverImage: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=Node.js+server+backend+green+technology+abstract+network&image_size=landscape_16_9", + articleCount: 27, + createdAt: "2024-04-05T09:20:00Z" + } +}; + +export const TopicDetailPage: React.FC = () => { + const { slug } = useParams<{ slug: string }>(); + const topic = slug ? topicData[slug] : null; + + const { tableQueryResult } = useTable({ + resource: "articles", + pagination: { + current: 1, + pageSize: 10, + }, + }); + + if (!topic) { + return ( +
    +

    专题未找到

    +

    返回 专题列表

    +
    + ); + } + + return ( + <> +
    +
    +
    +
    +
    + 专题合集 + / + {topic.title} +
    +

    {topic.title}

    +

    {topic.description}

    +
    + + + {topic.articleCount} 篇文章 + + + + {dayjs(topic.createdAt).format("YYYY 年 MM 月")} + +
    +
    +
    + +
    +
    +

    + + 专题文章 +

    + + {tableQueryResult.isLoading && ( +
    + 加载中... +
    + )} + + {!tableQueryResult.data?.data?.length && !tableQueryResult.isFetching && ( +
    + 暂无文章 +
    + )} + + {tableQueryResult?.data?.data.map((item) => ( +
    + {}} + isItemFavorited={item.favorited} + isItemLoading={false} + /> +
    + ))} +
    +
    + + ); +}; diff --git a/src/pages/topics/index.tsx b/src/pages/topics/index.tsx new file mode 100644 index 0000000..2b17499 --- /dev/null +++ b/src/pages/topics/index.tsx @@ -0,0 +1,204 @@ +import { useState } from "react"; +import { Link } from "react-router-dom"; +import { ITopic } from "../../interfaces"; + +const cardStyle: React.CSSProperties = { + display: "block", + background: "#fff", + borderRadius: "8px", + overflow: "hidden", + textDecoration: "none", + color: "inherit", + boxShadow: "0 2px 8px rgba(0,0,0,0.08)", + transition: "all 0.3s ease", + height: "100%", +}; + +const cardHoverStyle: React.CSSProperties = { + boxShadow: "0 8px 24px rgba(0,0,0,0.12)", + transform: "translateY(-4px)", +}; + +const coverStyle: React.CSSProperties = { + position: "relative", + height: "180px", + overflow: "hidden", + background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)", +}; + +const coverOverlayStyle: React.CSSProperties = { + position: "absolute", + bottom: "0", + left: "0", + right: "0", + height: "60%", + background: "linear-gradient(to top, rgba(0,0,0,0.4), transparent)", +}; + +const imgStyle: React.CSSProperties = { + width: "100%", + height: "100%", + objectFit: "cover", +}; + +const contentStyle: React.CSSProperties = { + padding: "20px", +}; + +const titleStyle: React.CSSProperties = { + fontSize: "1.25rem", + fontWeight: "600", + marginBottom: "12px", + color: "#333", + lineHeight: "1.4", +}; + +const descStyle: React.CSSProperties = { + fontSize: "0.9rem", + color: "#666", + lineHeight: "1.6", + marginBottom: "16px", + display: "-webkit-box", + WebkitLineClamp: 2, + WebkitBoxOrient: "vertical", + overflow: "hidden", +}; + +const metaStyle: React.CSSProperties = { + display: "flex", + alignItems: "center", + gap: "16px", + fontSize: "0.85rem", + color: "#999", +}; + +const badgeStyle: React.CSSProperties = { + display: "inline-flex", + alignItems: "center", + gap: "4px", + padding: "4px 12px", + background: "#f8f9fa", + borderRadius: "20px", + fontWeight: "500", +}; + +const pageHeaderStyle: React.CSSProperties = { + padding: "40px 0", + textAlign: "center", + marginBottom: "20px", +}; + +const pageTitleStyle: React.CSSProperties = { + fontSize: "2.5rem", + fontWeight: "700", + color: "#333", + marginBottom: "12px", +}; + +const pageSubtitleStyle: React.CSSProperties = { + fontSize: "1.1rem", + color: "#999", +}; + +interface TopicCardProps { + topic: ITopic; +} + +const TopicCard: React.FC = ({ topic }) => { + const [isHovered, setIsHovered] = useState(false); + + return ( + setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + > +
    + {topic.title} +
    +
    +
    +

    {topic.title}

    +

    {topic.description}

    +
    + + + {topic.articleCount} 篇文章 + +
    +
    + + ); +}; + +export const TopicsPage: React.FC = () => { + const [topics] = useState([ + { + id: 1, + slug: "javascript-advanced", + title: "JavaScript 高级编程", + description: "深入探索 JavaScript 的高级特性和最佳实践,包括闭包、原型链、异步编程等核心概念。", + coverImage: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=JavaScript+programming+code+abstract+technology+modern+gradient+background&image_size=landscape_16_9", + articleCount: 24, + createdAt: "2024-01-15T08:00:00Z" + }, + { + id: 2, + slug: "react-hooks", + title: "React Hooks 实战指南", + description: "全面掌握 React Hooks 的使用方法,从基础 useState 到高级 useCallback、useMemo,构建现代化应用。", + coverImage: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=React+framework+component+atomic+design+modern+technology+gradient&image_size=landscape_16_9", + articleCount: 18, + createdAt: "2024-02-20T10:30:00Z" + }, + { + id: 3, + slug: "typescript-mastery", + title: "TypeScript 精通之路", + description: "从基础类型到高级类型系统,掌握泛型、条件类型、映射类型等,打造类型安全的企业级应用。", + coverImage: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=TypeScript+programming+blue+code+abstract+technology+modern+minimalist&image_size=landscape_16_9", + articleCount: 31, + createdAt: "2024-03-10T14:45:00Z" + }, + { + id: 4, + slug: "nodejs-backend", + title: "Node.js 后端开发", + description: "使用 Node.js 构建高性能后端服务,深入学习 Express、RESTful API、数据库操作等核心技术。", + coverImage: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=Node.js+server+backend+green+technology+abstract+network&image_size=landscape_16_9", + articleCount: 27, + createdAt: "2024-04-05T09:20:00Z" + } + ]); + + return ( +
    +
    +

    专题合集

    +

    精选技术专题,深度系统学习

    +
    + +
    +
    + {topics.map((topic) => ( +
    + +
    + ))} +
    +
    + + +
    + ); +};