diff --git a/package-lock.json b/package-lock.json index 69c9f6c..ed2ffc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,10 @@ "@ant-design/v5-patch-for-react-19": "^1.0.3", "@codemirror/lang-markdown": "^6.5.0", "@codemirror/view": "^6.38.8", + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", "@fortawesome/fontawesome-svg-core": "^7.1.0", "@fortawesome/free-brands-svg-icons": "^7.1.0", "@fortawesome/free-regular-svg-icons": "^7.1.0", @@ -21,6 +25,7 @@ "@myriaddreamin/typst-ts-renderer": "^0.6.1-rc4", "@myriaddreamin/typst-ts-web-compiler": "^0.6.1-rc4", "@myriaddreamin/typst.ts": "^0.6.1-rc4", + "@reactuses/core": "^6.1.6", "@uiw/react-codemirror": "^4.25.2", "ajv": "^8.17.1", "antd": "^5.27.6", @@ -196,7 +201,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", @@ -349,7 +353,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1874,6 +1877,74 @@ "postcss": "^8.4" } }, + "node_modules/@dnd-kit/accessibility": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz", + "integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/core": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", + "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@dnd-kit/accessibility": "^3.1.1", + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/modifiers": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-9.0.0.tgz", + "integrity": "sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==", + "license": "MIT", + "dependencies": { + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.3.0", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/sortable": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz", + "integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==", + "license": "MIT", + "dependencies": { + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.3.0", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/utilities": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz", + "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/@emotion/hash": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", @@ -2767,6 +2838,12 @@ "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", "license": "MIT" }, + "node_modules/@microsoft/fetch-event-source": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@microsoft/fetch-event-source/-/fetch-event-source-2.0.1.tgz", + "integrity": "sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA==", + "license": "MIT" + }, "node_modules/@mr.python/promise-worker-ts": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@mr.python/promise-worker-ts/-/promise-worker-ts-1.0.0.tgz", @@ -3190,6 +3267,29 @@ "react-dom": ">=16.9.0" } }, + "node_modules/@reactuses/core": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@reactuses/core/-/core-6.1.6.tgz", + "integrity": "sha512-nRv/jNsv1MwYw6CMYNuYORgcHKzzcOe2JU6iizT039NoshJxvauPVjiTK9hZH1zUvdhj2/lfDqcucPlOQ72G8Q==", + "license": "Unlicense", + "dependencies": { + "@microsoft/fetch-event-source": "^2.0.1", + "@testing-library/dom": "^10.4.0", + "js-cookie": "^3.0.5", + "lodash-es": "^4.17.21", + "screenfull": "^5.0.0", + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "qrcode": "^1.5", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "qrcode": { + "optional": true + } + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.38", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.38.tgz", @@ -3522,6 +3622,31 @@ "tslib": "^2.8.0" } }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -4272,6 +4397,15 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -4361,6 +4495,15 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -5045,6 +5188,12 @@ "dev": true, "license": "MIT" }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "license": "MIT" + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -6022,11 +6171,19 @@ "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -6172,6 +6329,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -6205,6 +6368,15 @@ "yallist": "^3.0.2" } }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -7401,7 +7573,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -8251,6 +8422,38 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -9145,6 +9348,18 @@ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, + "node_modules/screenfull": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz", + "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/scroll-into-view-if-needed": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", @@ -9715,6 +9930,15 @@ "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 5e4e497..1fac7b2 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,10 @@ "@ant-design/v5-patch-for-react-19": "^1.0.3", "@codemirror/lang-markdown": "^6.5.0", "@codemirror/view": "^6.38.8", + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", "@fortawesome/fontawesome-svg-core": "^7.1.0", "@fortawesome/free-brands-svg-icons": "^7.1.0", "@fortawesome/free-regular-svg-icons": "^7.1.0", @@ -34,6 +38,7 @@ "@myriaddreamin/typst-ts-renderer": "^0.6.1-rc4", "@myriaddreamin/typst-ts-web-compiler": "^0.6.1-rc4", "@myriaddreamin/typst.ts": "^0.6.1-rc4", + "@reactuses/core": "^6.1.6", "@uiw/react-codemirror": "^4.25.2", "ajv": "^8.17.1", "antd": "^5.27.6", @@ -80,6 +85,7 @@ "eslint-plugin-react-refresh": "^0.4.22", "fontkit": "^2.0.4", "globals": "^16.4.0", + "husky": "^8.0.0", "jiti": "^2.6.1", "mdast-util-to-hast": "^13.2.0", "pdf-to-img": "^5.0.0", @@ -90,7 +96,6 @@ "typescript": "~5.9.3", "typescript-eslint": "^8.45.0", "vite": "^7.1.7", - "vitest": "^4.0.10", - "husky": "^8.0.0" + "vitest": "^4.0.10" } } diff --git a/src/contestEditor/configPanel.css b/src/contestEditor/configPanel/index.css similarity index 86% rename from src/contestEditor/configPanel.css rename to src/contestEditor/configPanel/index.css index fb9f0c5..c129411 100644 --- a/src/contestEditor/configPanel.css +++ b/src/contestEditor/configPanel/index.css @@ -29,18 +29,18 @@ } > .contest-editor-config-switches { display: flex; - &.contest-editor-config-switches-narrow { - flex-direction: column; - gap: 8px; - > label { - flex: unset; - } - } > label { flex: 1; max-width: 200px; } } + &.width-leq-300 > .contest-editor-config-switches { + flex-direction: column; + gap: 8px; + > label { + flex: unset; + } + } .contest-editor-config-problem-card-title { display: flex; align-items: center; @@ -81,13 +81,14 @@ } } } - .contest-editor-config-problem.contest-editor-config-problem-narrow { - .ant-card-body { - > *:not(.contest-editor-config-problem-languages) { - flex-direction: column; - > * { - flex: unset; - } + } + &.width-leq-300 .contest-editor-config-problem, + &.width-ge-300-leq-400 .contest-editor-config-problem { + .ant-card-body { + > *:not(.contest-editor-config-problem-languages) { + flex-direction: column; + > * { + flex: unset; } } } diff --git a/src/contestEditor/configPanel.tsx b/src/contestEditor/configPanel/index.tsx similarity index 52% rename from src/contestEditor/configPanel.tsx rename to src/contestEditor/configPanel/index.tsx index 091c1d9..b681c35 100644 --- a/src/contestEditor/configPanel.tsx +++ b/src/contestEditor/configPanel/index.tsx @@ -22,8 +22,6 @@ import type { DateArr, ImmerContestData } from "@/types/contestData"; import dayjs from "dayjs"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { - faChevronDown, - faChevronUp, faCircleQuestion, faInbox, faPenToSquare, @@ -31,11 +29,11 @@ import { faTrashCan, faXmark, } from "@fortawesome/free-solid-svg-icons"; -import { newProblem, removeProblemCallback } from "@/utils/contestDataUtils"; import { addImage, deleteImage } from "@/utils/imageManager"; -import "./configPanel.css"; +import "./index.css"; import { faMarkdown } from "@fortawesome/free-brands-svg-icons"; +import ProblemList from "./problemList"; const QuestionMarkToolTip: FC<{ children: string }> = ({ children }) => ( @@ -50,7 +48,7 @@ const ConfigPanel: FC<{ updateContestData: Updater; setPanel: Dispatch>; }> = ({ contestData, updateContestData, setPanel }) => { - const { modal, message } = App.useApp(); + const { message } = App.useApp(); const formRef = useRef(null); const [width, setWidth] = useState(220); const [imageEditModeId, setImageEditModeId] = useState( @@ -91,14 +89,6 @@ const ConfigPanel: FC<{ cb(x.support_languages[index]); }); } - function updateProblemData( - index: number, - cb: (x: ImmerContestData["problems"][number]) => void, - ) { - updateContestData((x) => { - cb(x.problems[index]); - }); - } function updateImages( index: number, cb: (x: ImmerContestData["images"][number]) => void, @@ -107,19 +97,18 @@ const ConfigPanel: FC<{ cb(x.images[index]); }); } - const removeProblem = removeProblemCallback( - modal, - setPanel, - updateContestData, - ); - function syncAdvancedFields(problem: ImmerContestData["problems"][number]) { - if (problem.advancedEditing) return; - problem.dir = problem.exec = problem.name; - problem.input = problem.name + ".in"; - problem.output = problem.name + ".out"; - } return ( -
+ -
+
-
-
题目信息
-
- {contestData.problems.map((problem, index) => ( - -
第 {index + 1} 题
-
- - updateProblemData(index, (v) => { - v.advancedEditing = x; - syncAdvancedFields(v); - }) - } - /> - 高级编辑 -
-
- } - extra={[ - -
-
+
本地图片
diff --git a/src/contestEditor/configPanel/problemList.tsx b/src/contestEditor/configPanel/problemList.tsx new file mode 100644 index 0000000..4a9d403 --- /dev/null +++ b/src/contestEditor/configPanel/problemList.tsx @@ -0,0 +1,409 @@ +import { + useEffect, + useRef, + type Dispatch, + type FC, + type SetStateAction, +} from "react"; +import { useDeepCompareEffect } from "@reactuses/core"; +import type { ImmerContestData } from "@/types/contestData"; +import type { Updater } from "use-immer"; +import { newProblem, removeProblemCallback } from "@/utils/contestDataUtils"; +import { + faChevronUp, + faChevronDown, + faXmark, + faPlus, + faBars, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Card, Switch, Button, Input, App } from "antd"; +import { DndContext, MeasuringStrategy, useDndContext } from "@dnd-kit/core"; +import { + arrayMove, + arraySwap, + SortableContext, + useSortable, + verticalListSortingStrategy, +} from "@dnd-kit/sortable"; +import { CSS } from "@dnd-kit/utilities"; +import { restrictToVerticalAxis } from "@dnd-kit/modifiers"; + +const ProblemItem: FC<{ + problemData: ImmerContestData["problems"][number]; + index: number; + problemCount: number; + noiStyle: boolean; + fileIO: boolean; + usePretest: boolean; + supportLanguages: ImmerContestData["support_languages"]; + onClickMoveUp: () => void; + onClickMoveDown: () => void; + onClickDelete: () => void; + updateProblemData: ( + cb: (x: ImmerContestData["problems"][number]) => void, + ) => void; +}> = ({ + problemData: problem, + index, + problemCount, + noiStyle, + fileIO, + usePretest, + supportLanguages, + onClickMoveUp, + onClickMoveDown, + onClickDelete, + updateProblemData, +}) => { + const { listeners, setNodeRef, transform, transition, isDragging } = + useSortable({ + id: problem.key, + animateLayoutChanges: (args) => !args.wasDragging, + }); + const dragBarStyle = { + transform: CSS.Transform.toString(transform), + transition, + zIndex: isDragging ? 154 : undefined, + opacity: isDragging ? 0.8 : 1, + }; + function syncAdvancedFields(problem: ImmerContestData["problems"][number]) { + if (problem.advancedEditing) return; + problem.dir = problem.exec = problem.name; + problem.input = problem.name + ".in"; + problem.output = problem.name + ".out"; + } + return ( + +
第 {index + 1} 题
+
+ + updateProblemData((v) => { + v.advancedEditing = x; + syncAdvancedFields(v); + }) + } + /> + 高级编辑 +
+
+ } + extra={[ + +
+ + ); +}; + +export default ProblemList;