feat: 增加了shadcn和openapi

This commit is contained in:
2025-06-27 13:12:30 +08:00
parent 6650fd58f1
commit 3feab6a871
75 changed files with 3355 additions and 24 deletions

15
.prettierrc Normal file
View File

@@ -0,0 +1,15 @@
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 150,
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": true,
"bracketSameLine": false,
"arrowParens": "avoid",
"endOfLine": "lf",
"quoteProps": "as-needed",
"jsxSingleQuote": true,
"proseWrap": "preserve"
}

135
bun.lock
View File

@@ -5,6 +5,7 @@
"name": "web",
"dependencies": {
"@tailwindcss/vite": "^4.1.11",
"axios": "^1.6.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.523.0",
@@ -23,6 +24,8 @@
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
"globals": "^16.2.0",
"openapi-typescript": "^7.0.0",
"openapi-typescript-codegen": "^0.27.0",
"tw-animate-css": "^1.3.4",
"typescript": "~5.8.3",
"typescript-eslint": "^8.34.1",
@@ -33,6 +36,12 @@
"packages": {
"@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],
"@apidevtools/json-schema-ref-parser": ["@apidevtools/json-schema-ref-parser@10.1.0", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.11", "@types/lodash.clonedeep": "^4.5.7", "js-yaml": "^4.1.0", "lodash.clonedeep": "^4.5.0" } }, "sha512-3e+viyMuXdrcK8v5pvP+SDoAQ77FH6OyRmuK48SZKmdHJRFm87RsSs8qm6kP39a/pOPURByJw+OXzQIqcfmKtA=="],
"@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="],
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA=="],
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.5", "", { "os": "android", "cpu": "arm" }, "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA=="],
@@ -121,12 +130,20 @@
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="],
"@jsdevtools/ono": ["@jsdevtools/ono@7.1.3", "", {}, "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="],
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
"@redocly/ajv": ["@redocly/ajv@8.11.2", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js-replace": "^1.0.1" } }, "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg=="],
"@redocly/config": ["@redocly/config@0.22.2", "", {}, "sha512-roRDai8/zr2S9YfmzUfNhKjOF0NdcOIqF7bhf4MVC5UxpjIysDjyudvlAiVbpPHp3eDRWbdzUgtkK1a7YiDNyQ=="],
"@redocly/openapi-core": ["@redocly/openapi-core@1.34.3", "", { "dependencies": { "@redocly/ajv": "^8.11.2", "@redocly/config": "^0.22.0", "colorette": "^1.2.0", "https-proxy-agent": "^7.0.5", "js-levenshtein": "^1.1.6", "js-yaml": "^4.1.0", "minimatch": "^5.0.1", "pluralize": "^8.0.0", "yaml-ast-parser": "0.0.43" } }, "sha512-3arRdUp1fNx55itnjKiUhO6t4Mf91TsrTIYINDNLAZPS0TPd5YpiXRctwjel0qqWoOOhjA34cZ3m4dksLDFUYg=="],
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.11", "", {}, "sha512-L/gAA/hyCSuzTF1ftlzUSI/IKr2POHsv1Dd78GfqkR83KMNuswWD61JxGV2L7nRwBBBSDr6R1gCkdTmoN7W4ag=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.44.1", "", { "os": "android", "cpu": "arm" }, "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w=="],
@@ -229,6 +246,10 @@
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
"@types/lodash": ["@types/lodash@4.17.19", "", {}, "sha512-NYqRyg/hIQrYPT9lbOeYc3kIRabJDn/k4qQHIXUpx88CBDww2fD15Sg5kbXlW86zm2XEW4g0QxkTI3/Kfkc7xQ=="],
"@types/lodash.clonedeep": ["@types/lodash.clonedeep@4.5.9", "", { "dependencies": { "@types/lodash": "*" } }, "sha512-19429mWC+FyaAhOLzsS8kZUsI+/GmBAQ0HFiCPsKGU+7pBXOQWhyrY6xNNDwUSX8SMZMJvuFVMF9O5dQOlQK9Q=="],
"@types/node": ["@types/node@24.0.4", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA=="],
"@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="],
@@ -261,22 +282,36 @@
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
"agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="],
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
"ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
"axios": ["axios@1.10.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw=="],
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
"camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="],
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="],
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
"class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
@@ -287,6 +322,12 @@
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"colorette": ["colorette@1.4.0", "", {}, "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g=="],
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
"commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="],
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
@@ -297,10 +338,22 @@
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
"detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
"enhanced-resolve": ["enhanced-resolve@5.18.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ=="],
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
"esbuild": ["esbuild@0.25.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.5", "@esbuild/android-arm": "0.25.5", "@esbuild/android-arm64": "0.25.5", "@esbuild/android-x64": "0.25.5", "@esbuild/darwin-arm64": "0.25.5", "@esbuild/darwin-x64": "0.25.5", "@esbuild/freebsd-arm64": "0.25.5", "@esbuild/freebsd-x64": "0.25.5", "@esbuild/linux-arm": "0.25.5", "@esbuild/linux-arm64": "0.25.5", "@esbuild/linux-ia32": "0.25.5", "@esbuild/linux-loong64": "0.25.5", "@esbuild/linux-mips64el": "0.25.5", "@esbuild/linux-ppc64": "0.25.5", "@esbuild/linux-riscv64": "0.25.5", "@esbuild/linux-s390x": "0.25.5", "@esbuild/linux-x64": "0.25.5", "@esbuild/netbsd-arm64": "0.25.5", "@esbuild/netbsd-x64": "0.25.5", "@esbuild/openbsd-arm64": "0.25.5", "@esbuild/openbsd-x64": "0.25.5", "@esbuild/sunos-x64": "0.25.5", "@esbuild/win32-arm64": "0.25.5", "@esbuild/win32-ia32": "0.25.5", "@esbuild/win32-x64": "0.25.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ=="],
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
@@ -347,24 +400,50 @@
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
"follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="],
"form-data": ["form-data@4.0.3", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA=="],
"fs-extra": ["fs-extra@11.3.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
"globals": ["globals@16.2.0", "", {}, "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg=="],
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
"handlebars": ["handlebars@4.7.8", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ=="],
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
"index-to-position": ["index-to-position@1.1.0", "", {}, "sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg=="],
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
@@ -375,6 +454,10 @@
"jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],
"js-levenshtein": ["js-levenshtein@1.1.6", "", {}, "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g=="],
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
@@ -383,6 +466,8 @@
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
"jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="],
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
@@ -411,18 +496,28 @@
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
"lodash.clonedeep": ["lodash.clonedeep@4.5.0", "", {}, "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="],
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
"lucide-react": ["lucide-react@0.523.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-rUjQoy7egZT9XYVXBK1je9ckBnNp7qzRZOhLQx5RcEp2dCGlXo+mv6vf7Am4LimEcFBJIIZzSGfgTqc9QCrPSw=="],
"magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
"minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="],
@@ -435,6 +530,12 @@
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
"neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="],
"openapi-typescript": ["openapi-typescript@7.8.0", "", { "dependencies": { "@redocly/openapi-core": "^1.34.3", "ansi-colors": "^4.1.3", "change-case": "^5.4.4", "parse-json": "^8.3.0", "supports-color": "^10.0.0", "yargs-parser": "^21.1.1" }, "peerDependencies": { "typescript": "^5.x" }, "bin": { "openapi-typescript": "bin/cli.js" } }, "sha512-1EeVWmDzi16A+siQlo/SwSGIT7HwaFAVjvMA7/jG5HMLSnrUOzPL7uSTRZZa4v/LCRxHTApHKtNY6glApEoiUQ=="],
"openapi-typescript-codegen": ["openapi-typescript-codegen@0.27.0", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^10.1.0", "camelcase": "^6.3.0", "commander": "^11.1.0", "fs-extra": "^11.2.0", "handlebars": "^4.7.8" }, "bin": { "openapi": "bin/index.js" } }, "sha512-QyQEod/vuel3zfnTRC3GgmYsqLPSBzB2OL4ojMYjO9hJmfYW02T+7tbQWEnuqWdhh2KSOBf3L8h59vLStr6vwA=="],
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
@@ -443,6 +544,8 @@
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
"parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="],
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
@@ -451,10 +554,14 @@
"picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
"pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="],
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
"proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
@@ -463,6 +570,8 @@
"react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="],
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
@@ -479,11 +588,13 @@
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"supports-color": ["supports-color@10.0.0", "", {}, "sha512-HRVVSbCCMbj7/kdWF9Q+bbckjBHLtHMEoJWlkmYzzdwhYMkjkOwubLM6t7NbWKjgKamGDrWL1++KrjUO1t9oAQ=="],
"tailwind-merge": ["tailwind-merge@3.3.1", "", {}, "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="],
@@ -503,22 +614,36 @@
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
"type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
"typescript-eslint": ["typescript-eslint@8.35.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.35.0", "@typescript-eslint/parser": "8.35.0", "@typescript-eslint/utils": "8.35.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-uEnz70b7kBz6eg/j0Czy6K5NivaYopgxRjsnAJ2Fx5oTLo3wefTHIbL7AkQr1+7tJCRVpTs/wiM8JR/11Loq9A=="],
"uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="],
"undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
"universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
"uri-js-replace": ["uri-js-replace@1.0.1", "", {}, "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g=="],
"vite": ["vite@7.0.0", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", "picomatch": "^4.0.2", "postcss": "^8.5.6", "rollup": "^4.40.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g=="],
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
"wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="],
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
"yaml-ast-parser": ["yaml-ast-parser@0.0.43", "", {}, "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A=="],
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
@@ -529,6 +654,10 @@
"@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="],
"@redocly/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
"@redocly/openapi-core/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.4.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.4.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ=="],
@@ -545,10 +674,14 @@
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
"chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"@redocly/openapi-core/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
}
}

316
openapi.json Normal file
View File

@@ -0,0 +1,316 @@
{
"openapi": "3.0.0",
"info": {
"title": "Outfit API",
"description": "服装搭配API",
"version": "1.0.0"
},
"servers": [
{
"url": "http://localhost:3000",
"description": "开发环境"
}
],
"paths": {
"/api/users": {
"get": {
"summary": "获取用户列表",
"tags": ["用户"],
"responses": {
"200": {
"description": "成功",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/User"
}
}
}
}
}
}
},
"post": {
"summary": "创建用户",
"tags": ["用户"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateUserRequest"
}
}
}
},
"responses": {
"201": {
"description": "创建成功",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
}
}
}
},
"/api/users/{id}": {
"get": {
"summary": "获取用户详情",
"tags": ["用户"],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "成功",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
}
}
},
"put": {
"summary": "更新用户",
"tags": ["用户"],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateUserRequest"
}
}
}
},
"responses": {
"200": {
"description": "更新成功",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
}
}
},
"delete": {
"summary": "删除用户",
"tags": ["用户"],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"204": {
"description": "删除成功"
}
}
}
},
"/api/outfits": {
"get": {
"summary": "获取搭配列表",
"tags": ["搭配"],
"responses": {
"200": {
"description": "成功",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Outfit"
}
}
}
}
}
}
},
"post": {
"summary": "创建搭配",
"tags": ["搭配"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateOutfitRequest"
}
}
}
},
"responses": {
"201": {
"description": "创建成功",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Outfit"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"User": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "用户ID"
},
"username": {
"type": "string",
"description": "用户名"
},
"email": {
"type": "string",
"description": "邮箱"
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "创建时间"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"description": "更新时间"
}
},
"required": ["id", "username", "email"]
},
"CreateUserRequest": {
"type": "object",
"properties": {
"username": {
"type": "string",
"description": "用户名"
},
"email": {
"type": "string",
"description": "邮箱"
},
"password": {
"type": "string",
"description": "密码"
}
},
"required": ["username", "email", "password"]
},
"UpdateUserRequest": {
"type": "object",
"properties": {
"username": {
"type": "string",
"description": "用户名"
},
"email": {
"type": "string",
"description": "邮箱"
}
}
},
"Outfit": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "搭配ID"
},
"name": {
"type": "string",
"description": "搭配名称"
},
"description": {
"type": "string",
"description": "搭配描述"
},
"items": {
"type": "array",
"items": {
"type": "string"
},
"description": "服装项目列表"
},
"userId": {
"type": "string",
"description": "用户ID"
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "创建时间"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"description": "更新时间"
}
},
"required": ["id", "name", "userId"]
},
"CreateOutfitRequest": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "搭配名称"
},
"description": {
"type": "string",
"description": "搭配描述"
},
"items": {
"type": "array",
"items": {
"type": "string"
},
"description": "服装项目列表"
}
},
"required": ["name"]
}
}
}
}

View File

@@ -7,7 +7,10 @@
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
"preview": "vite preview",
"generate-api": "node scripts/generate-api.js",
"generate-api:dev": "OPENAPI_URL=http://localhost:3000/openapi.json node scripts/generate-api.js",
"generate-api:prod": "OPENAPI_URL=https://your-api-domain.com/openapi.json node scripts/generate-api.js"
},
"dependencies": {
"@tailwindcss/vite": "^4.1.11",
@@ -17,7 +20,8 @@
"react": "^19.1.0",
"react-dom": "^19.1.0",
"tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.11"
"tailwindcss": "^4.1.11",
"axios": "^1.6.0"
},
"devDependencies": {
"@eslint/js": "^9.29.0",
@@ -32,6 +36,8 @@
"tw-animate-css": "^1.3.4",
"typescript": "~5.8.3",
"typescript-eslint": "^8.34.1",
"vite": "^7.0.0"
"vite": "^7.0.0",
"openapi-typescript": "^7.0.0",
"openapi-typescript-codegen": "^0.27.0"
}
}

111
scripts/generate-api.js Normal file
View File

@@ -0,0 +1,111 @@
import { generate } from 'openapi-typescript-codegen';
import { readFileSync, writeFileSync, existsSync, readdirSync } from 'fs';
import { join } from 'path';
import axios from 'axios';
// 配置
const config = {
input: process.env.OPENAPI_URL || 'http://192.168.0.127:8010/openapi.json', // OpenAPI规范URL
output: './src/api', // 生成的API代码输出目录
client: 'axios', // 使用axios作为HTTP客户端
useOptions: true,
useUnionTypes: true,
exportSchemas: true,
exportServices: true,
exportCore: true,
exportModels: true,
exportClient: true,
};
async function fetchOpenApiSpec(url) {
try {
console.log(`📡 正在获取OpenAPI规范: ${url}`);
const response = await axios.get(url);
return response.data;
} catch (error) {
console.error(`❌ 获取OpenAPI规范失败: ${error.message}`);
throw error;
}
}
function createIndexFiles() {
const apiDir = config.output;
// 创建services/index.ts
const servicesDir = join(apiDir, 'services');
if (existsSync(servicesDir)) {
const serviceFiles = readdirSync(servicesDir)
.filter(file => file.endsWith('.ts') && file !== 'index.ts' && file !== 'Service.ts')
.map(file => file.replace('.ts', ''));
const servicesIndexContent = serviceFiles
.map(service => `export * from './${service}';`)
.join('\n');
writeFileSync(join(servicesDir, 'index.ts'), servicesIndexContent);
console.log('📝 创建services/index.ts完成');
}
// 创建models/index.ts
const modelsDir = join(apiDir, 'models');
if (existsSync(modelsDir)) {
const modelFiles = readdirSync(modelsDir)
.filter(file => file.endsWith('.ts') && file !== 'index.ts')
.map(file => file.replace('.ts', ''));
const modelsIndexContent = modelFiles
.map(model => `export * from './${model}';`)
.join('\n');
writeFileSync(join(modelsDir, 'index.ts'), modelsIndexContent);
console.log('📝 创建models/index.ts完成');
}
}
async function generateApi() {
try {
console.log('🚀 开始生成API代码...');
let openApiSpec;
// 检查输入是URL还是本地文件
if (config.input.startsWith('http://') || config.input.startsWith('https://')) {
// 从URL获取OpenAPI规范
openApiSpec = await fetchOpenApiSpec(config.input);
} else {
// 从本地文件读取
if (!existsSync(config.input)) {
console.error(`❌ OpenAPI文件不存在: ${config.input}`);
console.log('请确保openapi.json文件存在于项目根目录或设置OPENAPI_URL环境变量');
return;
}
openApiSpec = JSON.parse(readFileSync(config.input, 'utf8'));
}
// 生成API代码
await generate({
input: openApiSpec, // 直接传入规范对象
output: config.output,
client: config.client,
useOptions: config.useOptions,
useUnionTypes: config.useUnionTypes,
exportSchemas: config.exportSchemas,
exportServices: config.exportServices,
exportCore: config.exportCore,
exportModels: config.exportModels,
exportClient: config.exportClient,
});
console.log('✅ API代码生成完成');
console.log(`📁 输出目录: ${config.output}`);
// 创建索引文件
createIndexFiles();
} catch (error) {
console.error('❌ 生成API代码时出错:', error);
}
}
// 运行生成器
generateApi();

View File

@@ -1,35 +1,36 @@
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import { ApiClient } from './api/api-client';
function App() {
const [count, setCount] = useState(0)
const [count, setCount] = useState(0);
new ApiClient({
BASE: 'http://192.168.0.127:8010',
}).get('/api/v1/models');
return (
<>
<div>
<a href="https://vite.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
<a href='https://vite.dev' target='_blank'>
<img src={viteLogo} className='logo' alt='Vite logo' />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
<a href='https://react.dev' target='_blank'>
<img src={reactLogo} className='logo react' alt='React logo' />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<div className='card'>
<button onClick={() => setCount(count => count + 1)}>count is {count}</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
<p className='read-the-docs'>Click on the Vite and React logos to learn more</p>
</>
)
);
}
export default App
export default App;

114
src/api/api-client.ts Normal file
View File

@@ -0,0 +1,114 @@
import axios, {
type AxiosInstance,
type AxiosRequestConfig,
type AxiosResponse,
} from "axios";
export interface ApiClientConfig {
BASE: string;
TOKEN?: () => string;
USERNAME?: string;
PASSWORD?: string;
}
export class ApiClient {
private client: AxiosInstance;
private config: ApiClientConfig;
constructor(config: ApiClientConfig) {
this.config = config;
this.client = axios.create({
baseURL: config.BASE,
timeout: 10000,
headers: {
"Content-Type": "application/json",
},
});
// 请求拦截器
this.client.interceptors.request.use(
(config) => {
// 添加认证token
if (this.config.TOKEN) {
const token = this.config.TOKEN();
if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`;
}
}
return config;
},
(error: any) => {
return Promise.reject(error);
}
);
// 响应拦截器
this.client.interceptors.response.use(
(response: AxiosResponse) => {
return response;
},
(error: any) => {
// 统一错误处理
if (error.response) {
console.error("API错误:", error.response.data);
}
return Promise.reject(error);
}
);
}
// GET请求
async get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
const response = await this.client.get<T>(url, config);
return response.data;
}
// POST请求
async post<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<T> {
const response = await this.client.post<T>(url, data, config);
return response.data;
}
// PUT请求
async put<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<T> {
const response = await this.client.put<T>(url, data, config);
return response.data;
}
// DELETE请求
async delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
const response = await this.client.delete<T>(url, config);
return response.data;
}
// PATCH请求
async patch<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<T> {
const response = await this.client.patch<T>(url, data, config);
return response.data;
}
// 获取axios实例
getAxiosInstance(): AxiosInstance {
return this.client;
}
// 更新配置
updateConfig(newConfig: Partial<ApiClientConfig>) {
this.config = { ...this.config, ...newConfig };
if (newConfig.BASE) {
this.client.defaults.baseURL = newConfig.BASE;
}
}
}

25
src/api/core/ApiError.ts Normal file
View File

@@ -0,0 +1,25 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiResult } from './ApiResult';
export class ApiError extends Error {
public readonly url: string;
public readonly status: number;
public readonly statusText: string;
public readonly body: any;
public readonly request: ApiRequestOptions;
constructor(request: ApiRequestOptions, response: ApiResult, message: string) {
super(message);
this.name = 'ApiError';
this.url = response.url;
this.status = response.status;
this.statusText = response.statusText;
this.body = response.body;
this.request = request;
}
}

View File

@@ -0,0 +1,17 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type ApiRequestOptions = {
readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH';
readonly url: string;
readonly path?: Record<string, any>;
readonly cookies?: Record<string, any>;
readonly headers?: Record<string, any>;
readonly query?: Record<string, any>;
readonly formData?: Record<string, any>;
readonly body?: any;
readonly mediaType?: string;
readonly responseHeader?: string;
readonly errors?: Record<number, string>;
};

11
src/api/core/ApiResult.ts Normal file
View File

@@ -0,0 +1,11 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type ApiResult = {
readonly url: string;
readonly ok: boolean;
readonly status: number;
readonly statusText: string;
readonly body: any;
};

View File

@@ -0,0 +1,131 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export class CancelError extends Error {
constructor(message: string) {
super(message);
this.name = 'CancelError';
}
public get isCancelled(): boolean {
return true;
}
}
export interface OnCancel {
readonly isResolved: boolean;
readonly isRejected: boolean;
readonly isCancelled: boolean;
(cancelHandler: () => void): void;
}
export class CancelablePromise<T> implements Promise<T> {
#isResolved: boolean;
#isRejected: boolean;
#isCancelled: boolean;
readonly #cancelHandlers: (() => void)[];
readonly #promise: Promise<T>;
#resolve?: (value: T | PromiseLike<T>) => void;
#reject?: (reason?: any) => void;
constructor(
executor: (
resolve: (value: T | PromiseLike<T>) => void,
reject: (reason?: any) => void,
onCancel: OnCancel
) => void
) {
this.#isResolved = false;
this.#isRejected = false;
this.#isCancelled = false;
this.#cancelHandlers = [];
this.#promise = new Promise<T>((resolve, reject) => {
this.#resolve = resolve;
this.#reject = reject;
const onResolve = (value: T | PromiseLike<T>): void => {
if (this.#isResolved || this.#isRejected || this.#isCancelled) {
return;
}
this.#isResolved = true;
if (this.#resolve) this.#resolve(value);
};
const onReject = (reason?: any): void => {
if (this.#isResolved || this.#isRejected || this.#isCancelled) {
return;
}
this.#isRejected = true;
if (this.#reject) this.#reject(reason);
};
const onCancel = (cancelHandler: () => void): void => {
if (this.#isResolved || this.#isRejected || this.#isCancelled) {
return;
}
this.#cancelHandlers.push(cancelHandler);
};
Object.defineProperty(onCancel, 'isResolved', {
get: (): boolean => this.#isResolved,
});
Object.defineProperty(onCancel, 'isRejected', {
get: (): boolean => this.#isRejected,
});
Object.defineProperty(onCancel, 'isCancelled', {
get: (): boolean => this.#isCancelled,
});
return executor(onResolve, onReject, onCancel as OnCancel);
});
}
get [Symbol.toStringTag]() {
return "Cancellable Promise";
}
public then<TResult1 = T, TResult2 = never>(
onFulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
): Promise<TResult1 | TResult2> {
return this.#promise.then(onFulfilled, onRejected);
}
public catch<TResult = never>(
onRejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
): Promise<T | TResult> {
return this.#promise.catch(onRejected);
}
public finally(onFinally?: (() => void) | null): Promise<T> {
return this.#promise.finally(onFinally);
}
public cancel(): void {
if (this.#isResolved || this.#isRejected || this.#isCancelled) {
return;
}
this.#isCancelled = true;
if (this.#cancelHandlers.length) {
try {
for (const cancelHandler of this.#cancelHandlers) {
cancelHandler();
}
} catch (error) {
console.warn('Cancellation threw an error', error);
return;
}
}
this.#cancelHandlers.length = 0;
if (this.#reject) this.#reject(new CancelError('Request aborted'));
}
public get isCancelled(): boolean {
return this.#isCancelled;
}
}

32
src/api/core/OpenAPI.ts Normal file
View File

@@ -0,0 +1,32 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { ApiRequestOptions } from './ApiRequestOptions';
type Resolver<T> = (options: ApiRequestOptions) => Promise<T>;
type Headers = Record<string, string>;
export type OpenAPIConfig = {
BASE: string;
VERSION: string;
WITH_CREDENTIALS: boolean;
CREDENTIALS: 'include' | 'omit' | 'same-origin';
TOKEN?: string | Resolver<string> | undefined;
USERNAME?: string | Resolver<string> | undefined;
PASSWORD?: string | Resolver<string> | undefined;
HEADERS?: Headers | Resolver<Headers> | undefined;
ENCODE_PATH?: ((path: string) => string) | undefined;
};
export const OpenAPI: OpenAPIConfig = {
BASE: '',
VERSION: '1.0.0',
WITH_CREDENTIALS: false,
CREDENTIALS: 'include',
TOKEN: undefined,
USERNAME: undefined,
PASSWORD: undefined,
HEADERS: undefined,
ENCODE_PATH: undefined,
};

322
src/api/core/request.ts Normal file
View File

@@ -0,0 +1,322 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import { ApiError } from './ApiError';
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiResult } from './ApiResult';
import { CancelablePromise } from './CancelablePromise';
import type { OnCancel } from './CancelablePromise';
import type { OpenAPIConfig } from './OpenAPI';
export const isDefined = <T>(value: T | null | undefined): value is Exclude<T, null | undefined> => {
return value !== undefined && value !== null;
};
export const isString = (value: any): value is string => {
return typeof value === 'string';
};
export const isStringWithValue = (value: any): value is string => {
return isString(value) && value !== '';
};
export const isBlob = (value: any): value is Blob => {
return (
typeof value === 'object' &&
typeof value.type === 'string' &&
typeof value.stream === 'function' &&
typeof value.arrayBuffer === 'function' &&
typeof value.constructor === 'function' &&
typeof value.constructor.name === 'string' &&
/^(Blob|File)$/.test(value.constructor.name) &&
/^(Blob|File)$/.test(value[Symbol.toStringTag])
);
};
export const isFormData = (value: any): value is FormData => {
return value instanceof FormData;
};
export const base64 = (str: string): string => {
try {
return btoa(str);
} catch (err) {
// @ts-ignore
return Buffer.from(str).toString('base64');
}
};
export const getQueryString = (params: Record<string, any>): string => {
const qs: string[] = [];
const append = (key: string, value: any) => {
qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
};
const process = (key: string, value: any) => {
if (isDefined(value)) {
if (Array.isArray(value)) {
value.forEach(v => {
process(key, v);
});
} else if (typeof value === 'object') {
Object.entries(value).forEach(([k, v]) => {
process(`${key}[${k}]`, v);
});
} else {
append(key, value);
}
}
};
Object.entries(params).forEach(([key, value]) => {
process(key, value);
});
if (qs.length > 0) {
return `?${qs.join('&')}`;
}
return '';
};
const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => {
const encoder = config.ENCODE_PATH || encodeURI;
const path = options.url
.replace('{api-version}', config.VERSION)
.replace(/{(.*?)}/g, (substring: string, group: string) => {
if (options.path?.hasOwnProperty(group)) {
return encoder(String(options.path[group]));
}
return substring;
});
const url = `${config.BASE}${path}`;
if (options.query) {
return `${url}${getQueryString(options.query)}`;
}
return url;
};
export const getFormData = (options: ApiRequestOptions): FormData | undefined => {
if (options.formData) {
const formData = new FormData();
const process = (key: string, value: any) => {
if (isString(value) || isBlob(value)) {
formData.append(key, value);
} else {
formData.append(key, JSON.stringify(value));
}
};
Object.entries(options.formData)
.filter(([_, value]) => isDefined(value))
.forEach(([key, value]) => {
if (Array.isArray(value)) {
value.forEach(v => process(key, v));
} else {
process(key, value);
}
});
return formData;
}
return undefined;
};
type Resolver<T> = (options: ApiRequestOptions) => Promise<T>;
export const resolve = async <T>(options: ApiRequestOptions, resolver?: T | Resolver<T>): Promise<T | undefined> => {
if (typeof resolver === 'function') {
return (resolver as Resolver<T>)(options);
}
return resolver;
};
export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise<Headers> => {
const [token, username, password, additionalHeaders] = await Promise.all([
resolve(options, config.TOKEN),
resolve(options, config.USERNAME),
resolve(options, config.PASSWORD),
resolve(options, config.HEADERS),
]);
const headers = Object.entries({
Accept: 'application/json',
...additionalHeaders,
...options.headers,
})
.filter(([_, value]) => isDefined(value))
.reduce((headers, [key, value]) => ({
...headers,
[key]: String(value),
}), {} as Record<string, string>);
if (isStringWithValue(token)) {
headers['Authorization'] = `Bearer ${token}`;
}
if (isStringWithValue(username) && isStringWithValue(password)) {
const credentials = base64(`${username}:${password}`);
headers['Authorization'] = `Basic ${credentials}`;
}
if (options.body) {
if (options.mediaType) {
headers['Content-Type'] = options.mediaType;
} else if (isBlob(options.body)) {
headers['Content-Type'] = options.body.type || 'application/octet-stream';
} else if (isString(options.body)) {
headers['Content-Type'] = 'text/plain';
} else if (!isFormData(options.body)) {
headers['Content-Type'] = 'application/json';
}
}
return new Headers(headers);
};
export const getRequestBody = (options: ApiRequestOptions): any => {
if (options.body !== undefined) {
if (options.mediaType?.includes('/json')) {
return JSON.stringify(options.body)
} else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) {
return options.body;
} else {
return JSON.stringify(options.body);
}
}
return undefined;
};
export const sendRequest = async (
config: OpenAPIConfig,
options: ApiRequestOptions,
url: string,
body: any,
formData: FormData | undefined,
headers: Headers,
onCancel: OnCancel
): Promise<Response> => {
const controller = new AbortController();
const request: RequestInit = {
headers,
body: body ?? formData,
method: options.method,
signal: controller.signal,
};
if (config.WITH_CREDENTIALS) {
request.credentials = config.CREDENTIALS;
}
onCancel(() => controller.abort());
return await fetch(url, request);
};
export const getResponseHeader = (response: Response, responseHeader?: string): string | undefined => {
if (responseHeader) {
const content = response.headers.get(responseHeader);
if (isString(content)) {
return content;
}
}
return undefined;
};
export const getResponseBody = async (response: Response): Promise<any> => {
if (response.status !== 204) {
try {
const contentType = response.headers.get('Content-Type');
if (contentType) {
const jsonTypes = ['application/json', 'application/problem+json']
const isJSON = jsonTypes.some(type => contentType.toLowerCase().startsWith(type));
if (isJSON) {
return await response.json();
} else {
return await response.text();
}
}
} catch (error) {
console.error(error);
}
}
return undefined;
};
export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => {
const errors: Record<number, string> = {
400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
500: 'Internal Server Error',
502: 'Bad Gateway',
503: 'Service Unavailable',
...options.errors,
}
const error = errors[result.status];
if (error) {
throw new ApiError(options, result, error);
}
if (!result.ok) {
const errorStatus = result.status ?? 'unknown';
const errorStatusText = result.statusText ?? 'unknown';
const errorBody = (() => {
try {
return JSON.stringify(result.body, null, 2);
} catch (e) {
return undefined;
}
})();
throw new ApiError(options, result,
`Generic Error: status: ${errorStatus}; status text: ${errorStatusText}; body: ${errorBody}`
);
}
};
/**
* Request method
* @param config The OpenAPI configuration object
* @param options The request options from the service
* @returns CancelablePromise<T>
* @throws ApiError
*/
export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise<T> => {
return new CancelablePromise(async (resolve, reject, onCancel) => {
try {
const url = getUrl(config, options);
const formData = getFormData(options);
const body = getRequestBody(options);
const headers = await getHeaders(config, options);
if (!onCancel.isCancelled) {
const response = await sendRequest(config, options, url, body, formData, headers, onCancel);
const responseBody = await getResponseBody(response);
const responseHeader = getResponseHeader(response, options.responseHeader);
const result: ApiResult = {
url,
ok: response.ok,
status: response.status,
statusText: response.statusText,
body: responseHeader ?? responseBody,
};
catchErrorCodes(options, result);
resolve(result.body);
}
} catch (error) {
reject(error);
}
});
};

76
src/api/hooks/useApi.ts Normal file
View File

@@ -0,0 +1,76 @@
import { useState, useCallback } from 'react';
import { ApiClient } from '../api-client';
// 创建API客户端实例
const apiClient = new ApiClient({
BASE: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000',
});
// API请求状态
export interface ApiState<T> {
data: T | null;
loading: boolean;
error: string | null;
}
// API Hook返回值
export interface UseApiReturn<T> extends ApiState<T> {
execute: (...args: any[]) => Promise<T | null>;
reset: () => void;
}
// 创建API Hook
export function useApi<T = any>(apiFunction: (...args: any[]) => Promise<T>, initialData: T | null = null): UseApiReturn<T> {
const [state, setState] = useState<ApiState<T>>({
data: initialData,
loading: false,
error: null,
});
const execute = useCallback(
async (...args: any[]): Promise<T | null> => {
setState(prev => ({ ...prev, loading: true, error: null }));
try {
const result = await apiFunction(...args);
setState({ data: result, loading: false, error: null });
return result;
} catch (error: any) {
const errorMessage = error.response?.data?.message || error.message || '请求失败';
setState({ data: null, loading: false, error: errorMessage });
return null;
}
},
[apiFunction]
);
const reset = useCallback(() => {
setState({ data: initialData, loading: false, error: null });
}, [initialData]);
return {
...state,
execute,
reset,
};
}
// 创建GET请求Hook
export function useGet<T = any>(url: string, initialData: T | null = null) {
return useApi<T>(() => apiClient.get<T>(url), initialData);
}
// 创建POST请求Hook
export function usePost<T = any>(url: string, initialData: T | null = null) {
return useApi<T>((data?: any) => apiClient.post<T>(url, data), initialData);
}
// 创建PUT请求Hook
export function usePut<T = any>(url: string, initialData: T | null = null) {
return useApi<T>((data?: any) => apiClient.put<T>(url, data), initialData);
}
// 创建DELETE请求Hook
export function useDelete<T = any>(url: string, initialData: T | null = null) {
return useApi<T>(() => apiClient.delete<T>(url), initialData);
}

67
src/api/index.ts Normal file
View File

@@ -0,0 +1,67 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export { ApiError } from './core/ApiError';
export { CancelablePromise, CancelError } from './core/CancelablePromise';
export { OpenAPI } from './core/OpenAPI';
export type { OpenAPIConfig } from './core/OpenAPI';
export type { BatchImageEditData } from './models/BatchImageEditData';
export type { BatchVideoGenerateRequest } from './models/BatchVideoGenerateRequest';
export type { BatchVideoTaskRequest } from './models/BatchVideoTaskRequest';
export type { Body_async_custom_edit_image_api_async_custom_image_post } from './models/Body_async_custom_edit_image_api_async_custom_image_post';
export type { Body_background_custom_edit_image_api_background_custom_image_post } from './models/Body_background_custom_edit_image_api_background_custom_image_post';
export type { Body_create_model_api_models_create_post } from './models/Body_create_model_api_models_create_post';
export type { Body_handler_submit_task_api_comfy_async_submit_task_post } from './models/Body_handler_submit_task_api_comfy_async_submit_task_post';
export type { Body_local_async_batch_bg_opt_api_local_batch_change_bg_post } from './models/Body_local_async_batch_bg_opt_api_local_batch_change_bg_post';
export type { Body_local_async_change_bg_api_local_change_bg_post } from './models/Body_local_async_change_bg_api_local_change_bg_post';
export type { Body_local_async_change_bg_api_v2_local_batch_change_bg_post } from './models/Body_local_async_change_bg_api_v2_local_batch_change_bg_post';
export type { Body_local_async_gen_images_api_v2_local_batch_images_post } from './models/Body_local_async_gen_images_api_v2_local_batch_images_post';
export type { Body_local_sync_generate_image_api_local_batch_generate_image_post } from './models/Body_local_sync_generate_image_api_local_batch_generate_image_post';
export type { Body_opt_local_generate_image_api_local_batch_generate_image_latest_post } from './models/Body_opt_local_generate_image_api_local_batch_generate_image_latest_post';
export type { Body_sync_custom_edit_image_api_sync_custom_image_post } from './models/Body_sync_custom_edit_image_api_sync_custom_image_post';
export type { Body_update_model_api_models__model_id__put } from './models/Body_update_model_api_models__model_id__put';
export type { Body_upload_image_api_upload_post } from './models/Body_upload_image_api_upload_post';
export type { Body_upload_img_material_api_img_upload_material_post } from './models/Body_upload_img_material_api_img_upload_material_post';
export type { HTTPValidationError } from './models/HTTPValidationError';
export type { ImageEditItem } from './models/ImageEditItem';
export type { ScenarioItem } from './models/ScenarioItem';
export type { TaskQueryRequest } from './models/TaskQueryRequest';
export type { UploadResponse } from './models/UploadResponse';
export type { ValidationError } from './models/ValidationError';
export type { VideoGenerateRequest } from './models/VideoGenerateRequest';
export type { VideoTaskRequest } from './models/VideoTaskRequest';
export type { VideoTaskStatus } from './models/VideoTaskStatus';
export { $BatchImageEditData } from './schemas/$BatchImageEditData';
export { $BatchVideoGenerateRequest } from './schemas/$BatchVideoGenerateRequest';
export { $BatchVideoTaskRequest } from './schemas/$BatchVideoTaskRequest';
export { $Body_async_custom_edit_image_api_async_custom_image_post } from './schemas/$Body_async_custom_edit_image_api_async_custom_image_post';
export { $Body_background_custom_edit_image_api_background_custom_image_post } from './schemas/$Body_background_custom_edit_image_api_background_custom_image_post';
export { $Body_create_model_api_models_create_post } from './schemas/$Body_create_model_api_models_create_post';
export { $Body_handler_submit_task_api_comfy_async_submit_task_post } from './schemas/$Body_handler_submit_task_api_comfy_async_submit_task_post';
export { $Body_local_async_batch_bg_opt_api_local_batch_change_bg_post } from './schemas/$Body_local_async_batch_bg_opt_api_local_batch_change_bg_post';
export { $Body_local_async_change_bg_api_local_change_bg_post } from './schemas/$Body_local_async_change_bg_api_local_change_bg_post';
export { $Body_local_async_change_bg_api_v2_local_batch_change_bg_post } from './schemas/$Body_local_async_change_bg_api_v2_local_batch_change_bg_post';
export { $Body_local_async_gen_images_api_v2_local_batch_images_post } from './schemas/$Body_local_async_gen_images_api_v2_local_batch_images_post';
export { $Body_local_sync_generate_image_api_local_batch_generate_image_post } from './schemas/$Body_local_sync_generate_image_api_local_batch_generate_image_post';
export { $Body_opt_local_generate_image_api_local_batch_generate_image_latest_post } from './schemas/$Body_opt_local_generate_image_api_local_batch_generate_image_latest_post';
export { $Body_sync_custom_edit_image_api_sync_custom_image_post } from './schemas/$Body_sync_custom_edit_image_api_sync_custom_image_post';
export { $Body_update_model_api_models__model_id__put } from './schemas/$Body_update_model_api_models__model_id__put';
export { $Body_upload_image_api_upload_post } from './schemas/$Body_upload_image_api_upload_post';
export { $Body_upload_img_material_api_img_upload_material_post } from './schemas/$Body_upload_img_material_api_img_upload_material_post';
export { $HTTPValidationError } from './schemas/$HTTPValidationError';
export { $ImageEditItem } from './schemas/$ImageEditItem';
export { $ScenarioItem } from './schemas/$ScenarioItem';
export { $TaskQueryRequest } from './schemas/$TaskQueryRequest';
export { $UploadResponse } from './schemas/$UploadResponse';
export { $ValidationError } from './schemas/$ValidationError';
export { $VideoGenerateRequest } from './schemas/$VideoGenerateRequest';
export { $VideoTaskRequest } from './schemas/$VideoTaskRequest';
export { $VideoTaskStatus } from './schemas/$VideoTaskStatus';
export { Service } from './services/Service';
export { ComfyService } from './services/ComfyService';
export { DefaultService } from './services/DefaultService';
export { WebhookService } from './services/WebhookService';

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { ImageEditItem } from './ImageEditItem';
export type BatchImageEditData = {
tasks: Array<ImageEditItem>;
};

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { VideoGenerateRequest } from './VideoGenerateRequest';
export type BatchVideoGenerateRequest = {
data: Array<VideoGenerateRequest>;
};

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { VideoTaskRequest } from './VideoTaskRequest';
export type BatchVideoTaskRequest = {
tasks: Array<VideoTaskRequest>;
};

View File

@@ -0,0 +1,8 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_async_custom_edit_image_api_async_custom_image_post = {
img_path: Blob;
};

View File

@@ -0,0 +1,8 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_background_custom_edit_image_api_background_custom_image_post = {
img_path: Blob;
};

View File

@@ -0,0 +1,13 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_create_model_api_models_create_post = {
/**
* 标签格式性别_类别_尺寸_材质_颜色。例如: '女_上衣_长款_牛仔_红'
*/
tags: string;
cover_image: Blob;
status?: number;
};

View File

@@ -0,0 +1,10 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_handler_submit_task_api_comfy_async_submit_task_post = {
prompt: string;
edit_image: Blob;
aspect_ratio?: string;
};

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_local_async_batch_bg_opt_api_local_batch_change_bg_post = {
clothing_images: Array<Blob>;
scenario_categories?: Array<string>;
};

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_local_async_change_bg_api_local_change_bg_post = {
clothing_image: Blob;
scenario_categories?: Array<string>;
};

View File

@@ -0,0 +1,16 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_local_async_change_bg_api_v2_local_batch_change_bg_post = {
clothing_images: Array<Blob>;
/**
* 风格标签
*/
style: string;
/**
* 场景标签,支持多个标签,标签之间使用逗号分割
*/
scenes: string;
};

View File

@@ -0,0 +1,24 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_local_async_gen_images_api_v2_local_batch_images_post = {
clothing_images: Array<Blob>;
/**
* 标签,支持多个,多个之间使用逗号分割
*/
tag: string;
/**
* 风格标签
*/
style: string;
/**
* 场景标签,支持多个标签,标签之间使用逗号分割
*/
scenes: string;
/**
* 操作模式,支持 both, edit_only, bg_only
*/
mode?: string;
};

View File

@@ -0,0 +1,12 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_local_sync_generate_image_api_local_batch_generate_image_post = {
clothing_images: Array<Blob>;
model_names: string;
model_category: string;
mode?: string;
clothing_dec_prompt?: string;
};

View File

@@ -0,0 +1,13 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_opt_local_generate_image_api_local_batch_generate_image_latest_post = {
clothing_images: Array<Blob>;
model_url: string;
mode?: string;
model_category: string;
clothing_dec_prompt?: string;
scenario_categories?: Array<string>;
};

View File

@@ -0,0 +1,8 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_sync_custom_edit_image_api_sync_custom_image_post = {
img_path: Blob;
};

View File

@@ -0,0 +1,13 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_update_model_api_models__model_id__put = {
/**
* 标签格式性别_类别_尺寸_材质_颜色。例如: '女_上衣_长款_牛仔_红'
*/
tags?: (string | null);
cover_image?: (Blob | null);
status?: (number | null);
};

View File

@@ -0,0 +1,8 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_upload_image_api_upload_post = {
image: Blob;
};

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Body_upload_img_material_api_img_upload_material_post = {
category: string;
file: Blob;
};

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { ValidationError } from './ValidationError';
export type HTTPValidationError = {
detail?: Array<ValidationError>;
};

View File

@@ -0,0 +1,11 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type ImageEditItem = {
prompt: string;
edit_image: Blob;
aspect_ratio?: string;
task_id: string;
};

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type ScenarioItem = {
category: string;
description: string;
};

View File

@@ -0,0 +1,11 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type TaskQueryRequest = {
/**
* 任务ID列表
*/
task_id: Array<string>;
};

View File

@@ -0,0 +1,10 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type UploadResponse = {
success: boolean;
filename: string;
path: string;
};

View File

@@ -0,0 +1,10 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type ValidationError = {
loc: Array<(string | number)>;
msg: string;
type: string;
};

View File

@@ -0,0 +1,10 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type VideoGenerateRequest = {
img_url: string;
prompt: string;
duration?: string;
};

View File

@@ -0,0 +1,10 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type VideoTaskRequest = {
prompt: string;
img_url: string;
duration?: string;
};

View File

@@ -0,0 +1,8 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type VideoTaskStatus = {
job_ids: Array<string>;
};

26
src/api/models/index.ts Normal file
View File

@@ -0,0 +1,26 @@
export * from './BatchImageEditData';
export * from './BatchVideoGenerateRequest';
export * from './BatchVideoTaskRequest';
export * from './Body_async_custom_edit_image_api_async_custom_image_post';
export * from './Body_background_custom_edit_image_api_background_custom_image_post';
export * from './Body_create_model_api_models_create_post';
export * from './Body_handler_submit_task_api_comfy_async_submit_task_post';
export * from './Body_local_async_batch_bg_opt_api_local_batch_change_bg_post';
export * from './Body_local_async_change_bg_api_local_change_bg_post';
export * from './Body_local_async_change_bg_api_v2_local_batch_change_bg_post';
export * from './Body_local_async_gen_images_api_v2_local_batch_images_post';
export * from './Body_local_sync_generate_image_api_local_batch_generate_image_post';
export * from './Body_opt_local_generate_image_api_local_batch_generate_image_latest_post';
export * from './Body_sync_custom_edit_image_api_sync_custom_image_post';
export * from './Body_update_model_api_models__model_id__put';
export * from './Body_upload_image_api_upload_post';
export * from './Body_upload_img_material_api_img_upload_material_post';
export * from './HTTPValidationError';
export * from './ImageEditItem';
export * from './ScenarioItem';
export * from './TaskQueryRequest';
export * from './UploadResponse';
export * from './ValidationError';
export * from './VideoGenerateRequest';
export * from './VideoTaskRequest';
export * from './VideoTaskStatus';

View File

@@ -0,0 +1,15 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $BatchImageEditData = {
properties: {
tasks: {
type: 'array',
contains: {
type: 'ImageEditItem',
},
isRequired: true,
},
},
} as const;

View File

@@ -0,0 +1,15 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $BatchVideoGenerateRequest = {
properties: {
data: {
type: 'array',
contains: {
type: 'VideoGenerateRequest',
},
isRequired: true,
},
},
} as const;

View File

@@ -0,0 +1,15 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $BatchVideoTaskRequest = {
properties: {
tasks: {
type: 'array',
contains: {
type: 'VideoTaskRequest',
},
isRequired: true,
},
},
} as const;

View File

@@ -0,0 +1,13 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_async_custom_edit_image_api_async_custom_image_post = {
properties: {
img_path: {
type: 'binary',
isRequired: true,
format: 'binary',
},
},
} as const;

View File

@@ -0,0 +1,13 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_background_custom_edit_image_api_background_custom_image_post = {
properties: {
img_path: {
type: 'binary',
isRequired: true,
format: 'binary',
},
},
} as const;

View File

@@ -0,0 +1,21 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_create_model_api_models_create_post = {
properties: {
tags: {
type: 'string',
description: `标签格式性别_类别_尺寸_材质_颜色。例如: '女_上衣_长款_牛仔_红'`,
isRequired: true,
},
cover_image: {
type: 'binary',
isRequired: true,
format: 'binary',
},
status: {
type: 'number',
},
},
} as const;

View File

@@ -0,0 +1,20 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_handler_submit_task_api_comfy_async_submit_task_post = {
properties: {
prompt: {
type: 'string',
isRequired: true,
},
edit_image: {
type: 'binary',
isRequired: true,
format: 'binary',
},
aspect_ratio: {
type: 'string',
},
},
} as const;

View File

@@ -0,0 +1,22 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_local_async_batch_bg_opt_api_local_batch_change_bg_post = {
properties: {
clothing_images: {
type: 'array',
contains: {
type: 'binary',
format: 'binary',
},
isRequired: true,
},
scenario_categories: {
type: 'array',
contains: {
type: 'string',
},
},
},
} as const;

View File

@@ -0,0 +1,19 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_local_async_change_bg_api_local_change_bg_post = {
properties: {
clothing_image: {
type: 'binary',
isRequired: true,
format: 'binary',
},
scenario_categories: {
type: 'array',
contains: {
type: 'string',
},
},
},
} as const;

View File

@@ -0,0 +1,26 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_local_async_change_bg_api_v2_local_batch_change_bg_post = {
properties: {
clothing_images: {
type: 'array',
contains: {
type: 'binary',
format: 'binary',
},
isRequired: true,
},
style: {
type: 'string',
description: `风格标签`,
isRequired: true,
},
scenes: {
type: 'string',
description: `场景标签,支持多个标签,标签之间使用逗号分割`,
isRequired: true,
},
},
} as const;

View File

@@ -0,0 +1,35 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_local_async_gen_images_api_v2_local_batch_images_post = {
properties: {
clothing_images: {
type: 'array',
contains: {
type: 'binary',
format: 'binary',
},
isRequired: true,
},
tag: {
type: 'string',
description: `标签,支持多个,多个之间使用逗号分割`,
isRequired: true,
},
style: {
type: 'string',
description: `风格标签`,
isRequired: true,
},
scenes: {
type: 'string',
description: `场景标签,支持多个标签,标签之间使用逗号分割`,
isRequired: true,
},
mode: {
type: 'string',
description: `操作模式,支持 both, edit_only, bg_only`,
},
},
} as const;

View File

@@ -0,0 +1,30 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_local_sync_generate_image_api_local_batch_generate_image_post = {
properties: {
clothing_images: {
type: 'array',
contains: {
type: 'binary',
format: 'binary',
},
isRequired: true,
},
model_names: {
type: 'string',
isRequired: true,
},
model_category: {
type: 'string',
isRequired: true,
},
mode: {
type: 'string',
},
clothing_dec_prompt: {
type: 'string',
},
},
} as const;

View File

@@ -0,0 +1,36 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_opt_local_generate_image_api_local_batch_generate_image_latest_post = {
properties: {
clothing_images: {
type: 'array',
contains: {
type: 'binary',
format: 'binary',
},
isRequired: true,
},
model_url: {
type: 'string',
isRequired: true,
},
mode: {
type: 'string',
},
model_category: {
type: 'string',
isRequired: true,
},
clothing_dec_prompt: {
type: 'string',
},
scenario_categories: {
type: 'array',
contains: {
type: 'string',
},
},
},
} as const;

View File

@@ -0,0 +1,13 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_sync_custom_edit_image_api_sync_custom_image_post = {
properties: {
img_path: {
type: 'binary',
isRequired: true,
format: 'binary',
},
},
} as const;

View File

@@ -0,0 +1,34 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_update_model_api_models__model_id__put = {
properties: {
tags: {
type: 'any-of',
description: `标签格式性别_类别_尺寸_材质_颜色。例如: '女_上衣_长款_牛仔_红'`,
contains: [{
type: 'string',
}, {
type: 'null',
}],
},
cover_image: {
type: 'any-of',
contains: [{
type: 'binary',
format: 'binary',
}, {
type: 'null',
}],
},
status: {
type: 'any-of',
contains: [{
type: 'number',
}, {
type: 'null',
}],
},
},
} as const;

View File

@@ -0,0 +1,13 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_upload_image_api_upload_post = {
properties: {
image: {
type: 'binary',
isRequired: true,
format: 'binary',
},
},
} as const;

View File

@@ -0,0 +1,17 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $Body_upload_img_material_api_img_upload_material_post = {
properties: {
category: {
type: 'string',
isRequired: true,
},
file: {
type: 'binary',
isRequired: true,
format: 'binary',
},
},
} as const;

View File

@@ -0,0 +1,14 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $HTTPValidationError = {
properties: {
detail: {
type: 'array',
contains: {
type: 'ValidationError',
},
},
},
} as const;

View File

@@ -0,0 +1,24 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $ImageEditItem = {
properties: {
prompt: {
type: 'string',
isRequired: true,
},
edit_image: {
type: 'binary',
isRequired: true,
format: 'binary',
},
aspect_ratio: {
type: 'string',
},
task_id: {
type: 'string',
isRequired: true,
},
},
} as const;

View File

@@ -0,0 +1,16 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $ScenarioItem = {
properties: {
category: {
type: 'string',
isRequired: true,
},
description: {
type: 'string',
isRequired: true,
},
},
} as const;

View File

@@ -0,0 +1,15 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $TaskQueryRequest = {
properties: {
task_id: {
type: 'array',
contains: {
type: 'string',
},
isRequired: true,
},
},
} as const;

View File

@@ -0,0 +1,20 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $UploadResponse = {
properties: {
success: {
type: 'boolean',
isRequired: true,
},
filename: {
type: 'string',
isRequired: true,
},
path: {
type: 'string',
isRequired: true,
},
},
} as const;

View File

@@ -0,0 +1,28 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $ValidationError = {
properties: {
loc: {
type: 'array',
contains: {
type: 'any-of',
contains: [{
type: 'string',
}, {
type: 'number',
}],
},
isRequired: true,
},
msg: {
type: 'string',
isRequired: true,
},
type: {
type: 'string',
isRequired: true,
},
},
} as const;

View File

@@ -0,0 +1,19 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $VideoGenerateRequest = {
properties: {
img_url: {
type: 'string',
isRequired: true,
},
prompt: {
type: 'string',
isRequired: true,
},
duration: {
type: 'string',
},
},
} as const;

View File

@@ -0,0 +1,19 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $VideoTaskRequest = {
properties: {
prompt: {
type: 'string',
isRequired: true,
},
img_url: {
type: 'string',
isRequired: true,
},
duration: {
type: 'string',
},
},
} as const;

View File

@@ -0,0 +1,15 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $VideoTaskStatus = {
properties: {
job_ids: {
type: 'array',
contains: {
type: 'string',
},
isRequired: true,
},
},
} as const;

View File

@@ -0,0 +1,121 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { BatchImageEditData } from '../models/BatchImageEditData';
import type { Body_handler_submit_task_api_comfy_async_submit_task_post } from '../models/Body_handler_submit_task_api_comfy_async_submit_task_post';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class ComfyService {
/**
* 提交单个编辑图片任务
* ComfyUI任务提交接口
* @returns any Successful Response
* @throws ApiError
*/
public static handlerSubmitTaskApiComfyAsyncSubmitTaskPost({
formData,
}: {
formData: Body_handler_submit_task_api_comfy_async_submit_task_post,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/comfy/async/submit/task',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* Handler Query Task
* 查询单个任务状态接口
* :param task_id: 我们的任务ID
* :param db: 数据库会话
* :return: 任务状态信息
* @returns any Successful Response
* @throws ApiError
*/
public static handlerQueryTaskApiComfyAsyncQueryTaskTaskIdGet({
taskId,
}: {
taskId: string,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/comfy/async/query/task/{task_id}',
path: {
'task_id': taskId,
},
errors: {
422: `Validation Error`,
},
});
}
/**
* Handler Query All Tasks
* 查询所有任务列表接口
* :param skip: 跳过数量
* :param limit: 限制数量
* :param db: 数据库会话
* :return: 任务列表
* @returns any Successful Response
* @throws ApiError
*/
public static handlerQueryAllTasksApiComfyAsyncQueryTaskGet({
skip,
limit = 10,
}: {
skip?: number,
limit?: number,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/comfy/async/query/task',
query: {
'skip': skip,
'limit': limit,
},
errors: {
422: `Validation Error`,
},
});
}
/**
* Handler Query Pending Tasks
* 查询所有待处理的任务
* :param db: 数据库会话
* :return: 待处理任务列表
* @returns any Successful Response
* @throws ApiError
*/
public static handlerQueryPendingTasksApiComfyAsyncQueryTasksPendingGet(): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/comfy/async/query/tasks/pending',
});
}
/**
* 批量提交编辑图片任务,最大同时支持两个任务
* 批量提交编辑图片任务接收表单数据tasks_json是任务列表JSONfiles是文件列表
* @returns any Successful Response
* @throws ApiError
*/
public static bacthSyncSubmitTaskApiComfyasyncBatchSubmitTaskPost({
requestBody,
}: {
requestBody: BatchImageEditData,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/comfyasync/batch/submit/task',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
}

View File

@@ -0,0 +1,281 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { Body_async_custom_edit_image_api_async_custom_image_post } from '../models/Body_async_custom_edit_image_api_async_custom_image_post';
import type { Body_background_custom_edit_image_api_background_custom_image_post } from '../models/Body_background_custom_edit_image_api_background_custom_image_post';
import type { Body_local_async_batch_bg_opt_api_local_batch_change_bg_post } from '../models/Body_local_async_batch_bg_opt_api_local_batch_change_bg_post';
import type { Body_local_async_change_bg_api_local_change_bg_post } from '../models/Body_local_async_change_bg_api_local_change_bg_post';
import type { Body_local_async_change_bg_api_v2_local_batch_change_bg_post } from '../models/Body_local_async_change_bg_api_v2_local_batch_change_bg_post';
import type { Body_local_async_gen_images_api_v2_local_batch_images_post } from '../models/Body_local_async_gen_images_api_v2_local_batch_images_post';
import type { Body_local_sync_generate_image_api_local_batch_generate_image_post } from '../models/Body_local_sync_generate_image_api_local_batch_generate_image_post';
import type { Body_opt_local_generate_image_api_local_batch_generate_image_latest_post } from '../models/Body_opt_local_generate_image_api_local_batch_generate_image_latest_post';
import type { Body_sync_custom_edit_image_api_sync_custom_image_post } from '../models/Body_sync_custom_edit_image_api_sync_custom_image_post';
import type { Body_upload_image_api_upload_post } from '../models/Body_upload_image_api_upload_post';
import type { TaskQueryRequest } from '../models/TaskQueryRequest';
import type { UploadResponse } from '../models/UploadResponse';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class DefaultService {
/**
* Index
* @returns string Successful Response
* @throws ApiError
*/
public static indexGet(): CancelablePromise<string> {
return __request(OpenAPI, {
method: 'GET',
url: '/',
});
}
/**
* Upload Image
* @returns UploadResponse Successful Response
* @throws ApiError
*/
public static uploadImageApiUploadPost({
formData,
}: {
formData: Body_upload_image_api_upload_post,
}): CancelablePromise<UploadResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/upload',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 本地换背景
* @returns any Successful Response
* @throws ApiError
*/
public static localAsyncChangeBgApiLocalChangeBgPost({
formData,
}: {
formData: Body_local_async_change_bg_api_local_change_bg_post,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/local/change/bg',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 本地批量换背景图片
* @returns any Successful Response
* @throws ApiError
*/
public static localAsyncBatchBgOptApiLocalBatchChangeBgPost({
formData,
}: {
formData: Body_local_async_batch_bg_opt_api_local_batch_change_bg_post,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/local/batch/change/bg',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 自定义图片生成
* @returns any Successful Response
* @throws ApiError
*/
public static syncCustomEditImageApiSyncCustomImagePost({
formData,
}: {
formData: Body_sync_custom_edit_image_api_sync_custom_image_post,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/sync/custom/image',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 异步自定义图片生成 - 立即返回task_id
* 异步版本立即返回task_id避免阻塞worker
* 客户端需要用task_id轮询 /api/check_task 查询结果
* @returns any Successful Response
* @throws ApiError
*/
public static asyncCustomEditImageApiAsyncCustomImagePost({
formData,
}: {
formData: Body_async_custom_edit_image_api_async_custom_image_post,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/async/custom/image',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 后台任务版本 - 使用BackgroundTasks
* 后台任务版本:立即返回,任务在后台执行
* 推荐用于不需要立即获取结果的场景
* @returns any Successful Response
* @throws ApiError
*/
public static backgroundCustomEditImageApiBackgroundCustomImagePost({
formData,
}: {
formData: Body_background_custom_edit_image_api_background_custom_image_post,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/background/custom/image',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 本地异步生成图片 - 支持多个服装图片批处理
* @returns any Successful Response
* @throws ApiError
*/
public static localSyncGenerateImageApiLocalBatchGenerateImagePost({
formData,
}: {
formData: Body_local_sync_generate_image_api_local_batch_generate_image_post,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/local/batch/generate/image',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 新版 异步图片生成接口, 支持多个服装图片处理
* 新版异步图片生成接口 - 支持多个服装图片文件上传处理
*
* Args:
* clothing_images: 服装图片文件列表
* model_url: 模特图片URL
* mode: 处理模式both/edit_only/bg_only
* model_category: 模特分类
* clothing_dec_prompt: 服装描述提示词
* scenario_categories: 场景分类列表(暂未使用)
* db: 数据库会话
*
* Returns:
* dict: 异步任务提交结果
* @returns any Successful Response
* @throws ApiError
*/
public static optLocalGenerateImageApiLocalBatchGenerateImageLatestPost({
formData,
}: {
formData: Body_opt_local_generate_image_api_local_batch_generate_image_latest_post,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/local/batch/generate/image/latest',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 本地新版异步图片生成接口
* 本地新版异步图片生成接口
*
* Args:
* clothing_images: 服装图片文件列表
* tag: 模特标签(用于筛选模特)
* style: 风格标签(如:少女、马来)
* scenes: 场景标签(如:室内,室外)
* mode: 操作模式both/edit_only/bg_only
* db: 数据库会话
*
* Returns:
* dict: 异步任务提交结果
* @returns any Successful Response
* @throws ApiError
*/
public static localAsyncGenImagesApiV2LocalBatchImagesPost({
formData,
}: {
formData: Body_local_async_gen_images_api_v2_local_batch_images_post,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/v2/local/batch/images',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 本地新版异步换背景接口
* @returns any Successful Response
* @throws ApiError
*/
public static localAsyncChangeBgApiV2LocalBatchChangeBgPost({
formData,
}: {
formData: Body_local_async_change_bg_api_v2_local_batch_change_bg_post,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/v2/local/batch/change/bg',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 批量查询任务结果
* @returns any Successful Response
* @throws ApiError
*/
public static localSyncQueryTaskResultApiLocalBatchQueryTaskResultPost({
requestBody,
}: {
requestBody: TaskQueryRequest,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/local/batch/query/task/result',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
}

680
src/api/services/Service.ts Normal file
View File

@@ -0,0 +1,680 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { BatchVideoGenerateRequest } from '../models/BatchVideoGenerateRequest';
import type { BatchVideoTaskRequest } from '../models/BatchVideoTaskRequest';
import type { Body_create_model_api_models_create_post } from '../models/Body_create_model_api_models_create_post';
import type { Body_update_model_api_models__model_id__put } from '../models/Body_update_model_api_models__model_id__put';
import type { Body_upload_img_material_api_img_upload_material_post } from '../models/Body_upload_img_material_api_img_upload_material_post';
import type { ScenarioItem } from '../models/ScenarioItem';
import type { VideoGenerateRequest } from '../models/VideoGenerateRequest';
import type { VideoTaskStatus } from '../models/VideoTaskStatus';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class Service {
/**
* 异步批量提交任务
* @returns any Successful Response
* @throws ApiError
*/
public static submitVideoTaskApiJmSubmitTaskPost({
requestBody,
}: {
requestBody: BatchVideoTaskRequest,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/jm/submit/task',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
/**
* 查询视频生成任务状态
* @returns any Successful Response
* @throws ApiError
*/
public static queryVideoTaskApiJmQueryStatusGet({
jobId,
}: {
jobId: string,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/jm/query/status',
query: {
'job_id': jobId,
},
errors: {
422: `Validation Error`,
},
});
}
/**
* 批量查询视频生成任务状态
* 批量查询视频生成任务状态
*
* Args:
* data: VideoTaskStatus对象包含job_ids列表
*
* Returns:
* dict: 按状态分类的任务信息
* {
* 'data': {
* 'finished': [{'job_id': 'xxx', 'video_url': 'xxx'}],
* 'failed': ['失败的job_id'],
* 'running': ['处理中的job_id']
* },
* 'status': True,
* 'msg': ''
* }
* @returns any Successful Response
* @throws ApiError
*/
public static batchQueryVideoStatusApiJmBatchQueryStatusPost({
requestBody,
}: {
requestBody: VideoTaskStatus,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/jm/batch/query/status',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
/**
* 上传素材
* 上传图片素材
*
* Args:
* category: 素材所属的类别, 例如, women man
* file: 上传的图片文件
*
* Returns:
* dict: 包含上传结果的响应
* {
* 'status': 上传的状态,
* 'data': {
* 'id': 素材id,
* 'img_url': '素材列表'
* }
* }
* @returns any Successful Response
* @throws ApiError
*/
public static uploadImgMaterialApiImgUploadMaterialPost({
formData,
}: {
formData: Body_upload_img_material_api_img_upload_material_post,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/img/upload/material',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 获取模特素材分类列表
* 获取模特素材分类列表
*
* Args:
* db: 数据库会话
*
* Returns:
* dict: 包含分类列表的响应
* {
* 'status': 查询状态,
* 'data': ['category1', 'category2', ...],
* 'msg': '提示信息'
* }
* @returns any Successful Response
* @throws ApiError
*/
public static getImgCategoryListApiImgCategoriesGet(): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/img/categories',
});
}
/**
* 获取某个类别下模特素材列表,类别为空获取所有
* 获取某个类别下的模特素材列表
*
* Args:
* category: 素材类别列表,支持多个类别,为空时获取所有模特素材
* 例如: ?category=women&category=men&category=kids
* db: 数据库会话
*
* Returns:
* dict: 包含素材列表的响应
* {
* 'status': 查询状态,
* 'data': ['图片URL1', '图片URL2', ...],
* 'msg': '提示信息'
* }
* @returns any Successful Response
* @throws ApiError
*/
public static getModelListApiImgModelListGet({
category,
}: {
category?: (Array<string> | null),
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/img/model/list',
query: {
'category': category,
},
errors: {
422: `Validation Error`,
},
});
}
/**
* 删除图片,支持批量
* 批量删除图片(软删除)
*
* Args:
* img_url: 图片URL列表
* db: 数据库会话
*
* Returns:
* dict: 删除结果
* @returns any Successful Response
* @throws ApiError
*/
public static removeImageApiImgRemovePost({
requestBody,
}: {
requestBody: Array<string>,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/img/remove',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
/**
* 添加场景信息
* 添加场景信息
*
* Args:
* data: 场景数据包含category和description
* db: 数据库会话
*
* Returns:
* dict: 包含添加结果的响应
* {
* 'status': 添加状态,
* 'data': {
* 'id': 场景ID,
* 'category': '类别',
* 'description': '描述'
* },
* 'msg': '提示信息'
* }
* @returns any Successful Response
* @throws ApiError
*/
public static addScenarioInfoApiScenarioAddPost({
requestBody,
}: {
requestBody: ScenarioItem,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/scenario/add',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
/**
* 获取场景信息列表
* 获取场景信息列表
*
* Args:
* db: 数据库会话
*
* Returns:
* dict: 包含场景分类列表的响应
* {
* 'status': 查询状态,
* 'data': ['类别1', '类别2', ...],
* 'msg': '提示信息'
* }
* @returns any Successful Response
* @throws ApiError
*/
public static getScenarioListApiScenarioListGet(): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/scenario/list',
});
}
/**
* 获取场景详情列表
* 获取场景详情列表
*
* Args:
* category: 场景类别列表,支持多个类别,为空时获取所有场景详情
* 例如: ?category=indoor&category=outdoor&category=studio
* db: 数据库会话
*
* Returns:
* dict: 包含场景描述列表的响应
* {
* 'status': 查询状态,
* 'data': ['描述1', '描述2', ...],
* 'msg': '提示信息'
* }
* @returns any Successful Response
* @throws ApiError
*/
public static getScenarioDetailListApiScenarioDetailListGet({
category,
}: {
category?: (Array<string> | null),
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/scenario/detail/list',
query: {
'category': category,
},
errors: {
422: `Validation Error`,
},
});
}
/**
* 删除场景,支持批量
* 批量删除场景(软删除)
*
* Args:
* data_list: 场景值列表
* db: 数据库会话
*
* Returns:
* dict: 删除结果
* @returns any Successful Response
* @throws ApiError
*/
public static removeScenarioApiScenarioRemovePost({
requestBody,
}: {
requestBody: Array<string>,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/scenario/remove',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
/**
* 创建模型
* 创建模型
*
* Args:
* tags: 模型标签格式性别_类别_尺寸_材质_颜色
* cover_image: 封面图片文件
* status: 状态默认为1
* db: 数据库会话
*
* Returns:
* dict: 包含创建结果的响应
* {
* 'status': 创建状态,
* 'data': {
* 'id': 模型ID,
* 'tag': {'sex': '性别', 'category': '类别', 'size': '尺寸', 'material': '材质', 'color': '颜色'},
* 'cover_url': '封面URL',
* 'status': 状态,
* 'create_time': '创建时间'
* },
* 'msg': '提示信息'
* }
* @returns any Successful Response
* @throws ApiError
*/
public static createModelApiModelsCreatePost({
formData,
}: {
formData: Body_create_model_api_models_create_post,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/models/create',
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 获取模型列表
* 获取模型列表
*
* Args:
* status: 状态筛选1启用0禁用为空时获取所有
* db: 数据库会话
*
* Returns:
* dict: 包含模型列表的响应
* {
* 'status': 查询状态,
* 'data': [模型信息列表],
* 'msg': '提示信息'
* }
* @returns any Successful Response
* @throws ApiError
*/
public static getModelsListApiModelsListGet({
status,
}: {
/**
* 状态筛选1启用0禁用
*/
status?: (number | null),
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/models/list',
query: {
'status': status,
},
errors: {
422: `Validation Error`,
},
});
}
/**
* 更新模型
* 更新模型信息
*
* Args:
* model_id: 模型ID
* tags: 更新的标签格式性别_类别_尺寸_材质_颜色可选
* cover_image: 更新的封面图片文件(可选)
* status: 更新的状态(可选)
* db: 数据库会话
*
* Returns:
* dict: 包含更新结果的响应
* @returns any Successful Response
* @throws ApiError
*/
public static updateModelApiModelsModelIdPut({
modelId,
formData,
}: {
modelId: number,
formData?: Body_update_model_api_models__model_id__put,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'PUT',
url: '/api/models/{model_id}',
path: {
'model_id': modelId,
},
formData: formData,
mediaType: 'multipart/form-data',
errors: {
422: `Validation Error`,
},
});
}
/**
* 删除单个模型
* 删除单个模型(软删除)
*
* Args:
* model_id: 模型ID
* db: 数据库会话
*
* Returns:
* dict: 删除结果
* @returns any Successful Response
* @throws ApiError
*/
public static deleteModelApiModelsModelIdDelete({
modelId,
}: {
modelId: number,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/api/models/{model_id}',
path: {
'model_id': modelId,
},
errors: {
422: `Validation Error`,
},
});
}
/**
* 删除模型,支持批量
* 批量删除模型(软删除)
*
* Args:
* model_ids: 模型ID列表
* db: 数据库会话
*
* Returns:
* dict: 删除结果
* {
* 'status': 删除状态,
* 'data': {
* 'total': 总数,
* 'success': 成功数,
* 'failed': 失败数
* },
* 'msg': '提示信息'
* }
* @returns any Successful Response
* @throws ApiError
*/
public static removeModelsApiModelsRemovePost({
requestBody,
}: {
requestBody: Array<number>,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/models/remove',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
/**
* 根据标签筛选模型列表
* 根据标签筛选模型列表
* 支持格式性别_类别_尺寸_材质_颜色使用特殊匹配规则
*
* 匹配规则:
* - sex性别和 category类别等值匹配必须完全相同AND逻辑
* - size尺寸、material材质、color颜色非等值匹配所有字段都必须不同AND逻辑
*
* Args:
* tags: 标签字符串格式性别_类别_尺寸_材质_颜色
* status: 状态筛选默认为1
* db: 数据库会话
*
* Returns:
* dict: 包含筛选结果的响应
* @returns any Successful Response
* @throws ApiError
*/
public static getModelsByTagApiModelsByTagsGet({
tags,
status,
}: {
/**
* 标签格式性别_类别_尺寸_材质_颜色。例如: '女_上衣_长款_牛仔_红'
*/
tags: string,
/**
* 状态筛选1启用0禁用
*/
status?: (number | null),
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/models/by/tags',
query: {
'tags': tags,
'status': status,
},
errors: {
422: `Validation Error`,
},
});
}
/**
* 获取风格标签结构(外层风格 + 内层场景)
* @returns any Successful Response
* @throws ApiError
*/
public static fetchStyleAvailableTagsApiTagStyleTagListGet(): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/tag/style/tag_list',
});
}
/**
* 获取指定风格和多个场景的值列表
* 获取指定风格和多个场景下的值列表(最内层数组合并)
*
* Args:
* style: 风格名称,如:少女、马来
* scenes: 场景名称,多个用逗号分隔,如:室内,室外
*
* Returns:
* dict: 合并后的值列表
* @returns any Successful Response
* @throws ApiError
*/
public static fetchStyleSceneValuesApiTagStyleValuesGet({
style,
scenes,
}: {
style: string,
scenes: string,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/tag/style/values',
query: {
'style': style,
'scenes': scenes,
},
errors: {
422: `Validation Error`,
},
});
}
/**
* 获取模特标签列表
* @returns any Successful Response
* @throws ApiError
*/
public static fetchModelTagsApiTagModelTagListGet(): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/tag/model/tag_list',
});
}
/**
* 极梦视频生成任务提交
* 生成视频API
* @returns any Successful Response
* @throws ApiError
*/
public static generateVideoApiVideoGeneratePost({
requestBody,
}: {
requestBody: VideoGenerateRequest,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/video/generate',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
/**
* 最大支持同时提交5个任务
* 批量生成视频API - 并发处理最多同时5个任务
* @returns any Successful Response
* @throws ApiError
*/
public static batchGenerateVideoApiBatchVideoGeneratePost({
requestBody,
}: {
requestBody: BatchVideoGenerateRequest,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/batch/video/generate',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
/**
* 极梦视频生成进度查询
* 查询视频生成状态API
* @returns any Successful Response
* @throws ApiError
*/
public static queryVideoStatusApiVideoQueryTaskIdGet({
taskId,
}: {
taskId: string,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/video/query/{task_id}',
path: {
'task_id': taskId,
},
errors: {
422: `Validation Error`,
},
});
}
}

View File

@@ -0,0 +1,43 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class WebhookService {
/**
* 同步数据处理
* @returns any Successful Response
* @throws ApiError
*/
public static webhookHandlerApiHandlerWebhookPost(): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/handler/webhook',
});
}
/**
* 异步数据处理
* 异步Webhook处理接口 - 快速响应,后台处理
* @returns any Successful Response
* @throws ApiError
*/
public static asyncWebhookHandlerApiAsyncHandlerWebhookPost(): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/async/handler/webhook',
});
}
/**
* 异步数据处理
* @returns any Successful Response
* @throws ApiError
*/
public static asyncWebhookSlotApiAsyncWebhookReciverPost(): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/async/webhook/reciver',
});
}
}

View File

@@ -0,0 +1,3 @@
export * from './ComfyService';
export * from './DefaultService';
export * from './WebhookService';

View File

@@ -19,7 +19,6 @@
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,

View File

@@ -17,7 +17,6 @@
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},