Merge branch 'master' of github.com:wyongk/juip-proxy-react
This commit is contained in:
@@ -1,9 +1,15 @@
|
|||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
|
手机端支付页面样式调整为类似电商的底部支付栏
|
||||||
|
|
||||||
|
MDX code 块语法高亮
|
||||||
|
|
||||||
|
全部替换封装时间范围组件,检查结束时间字段手机端适配问题(需要尾部对齐)
|
||||||
|
|
||||||
全局修改断点命名
|
全局修改断点命名
|
||||||
|
|
||||||
页头链接完善跳转地址
|
页头链接完善跳转地址
|
||||||
|
W
|
||||||
树组件优化
|
树组件优化
|
||||||
|
|
||||||
sse 向客户端推送通知与支付结果等事件
|
sse 向客户端推送通知与支付结果等事件
|
||||||
|
|||||||
@@ -1,20 +1,17 @@
|
|||||||
import type { NextConfig } from "next"
|
import createMDX from '@next/mdx'
|
||||||
import createMDX from "@next/mdx"
|
|
||||||
import remarkGfm from 'remark-gfm'
|
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
export default createMDX({
|
||||||
output: "standalone",
|
options: {
|
||||||
|
rehypePlugins: [
|
||||||
|
['rehype-highlight', null],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})({
|
||||||
|
output: 'standalone',
|
||||||
pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
|
pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
|
||||||
experimental: {
|
experimental: {
|
||||||
mdxRs: true,
|
mdxRs: {
|
||||||
}
|
mdxType: 'gfm',
|
||||||
}
|
},
|
||||||
|
},
|
||||||
const withMdx = createMDX({
|
|
||||||
options: {
|
|
||||||
remarkPlugins: [remarkGfm],
|
|
||||||
rehypePlugins: [],
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export default withMdx(nextConfig)
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
"@radix-ui/react-progress": "^1.1.3",
|
"@radix-ui/react-progress": "^1.1.3",
|
||||||
"@radix-ui/react-radio-group": "^1.2.3",
|
"@radix-ui/react-radio-group": "^1.2.3",
|
||||||
"@radix-ui/react-select": "^2.1.6",
|
"@radix-ui/react-select": "^2.1.6",
|
||||||
|
"@radix-ui/react-separator": "^1.1.7",
|
||||||
"@radix-ui/react-slot": "^1.1.2",
|
"@radix-ui/react-slot": "^1.1.2",
|
||||||
"@radix-ui/react-tabs": "^1.1.4",
|
"@radix-ui/react-tabs": "^1.1.4",
|
||||||
"@radix-ui/react-tooltip": "^1.2.6",
|
"@radix-ui/react-tooltip": "^1.2.6",
|
||||||
@@ -42,7 +43,6 @@
|
|||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"recharts": "^2.15.3",
|
"recharts": "^2.15.3",
|
||||||
"remark-gfm": "^4.0.1",
|
|
||||||
"sonner": "^2.0.1",
|
"sonner": "^2.0.1",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
@@ -65,7 +65,8 @@
|
|||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
"typescript": "^5"
|
"typescript": "^5",
|
||||||
|
"rehype-highlight": "^7.0.2"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.5.2+sha512.da9dc28cd3ff40d0592188235ab25d3202add8a207afbedc682220e4a0029ffbff4562102b9e6e46b4e3f9e8bd53e6d05de48544b0c57d4b0179e22c76d1199b",
|
"packageManager": "pnpm@10.5.2+sha512.da9dc28cd3ff40d0592188235ab25d3202add8a207afbedc682220e4a0029ffbff4562102b9e6e46b4e3f9e8bd53e6d05de48544b0c57d4b0179e22c76d1199b",
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
|
|||||||
280
pnpm-lock.yaml
generated
280
pnpm-lock.yaml
generated
@@ -56,6 +56,9 @@ importers:
|
|||||||
'@radix-ui/react-select':
|
'@radix-ui/react-select':
|
||||||
specifier: ^2.1.6
|
specifier: ^2.1.6
|
||||||
version: 2.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 2.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-separator':
|
||||||
|
specifier: ^1.1.7
|
||||||
|
version: 1.1.7(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
'@radix-ui/react-slot':
|
'@radix-ui/react-slot':
|
||||||
specifier: ^1.1.2
|
specifier: ^1.1.2
|
||||||
version: 1.1.2(@types/react@19.0.10)(react@19.0.0)
|
version: 1.1.2(@types/react@19.0.10)(react@19.0.0)
|
||||||
@@ -107,9 +110,6 @@ importers:
|
|||||||
recharts:
|
recharts:
|
||||||
specifier: ^2.15.3
|
specifier: ^2.15.3
|
||||||
version: 2.15.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 2.15.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
remark-gfm:
|
|
||||||
specifier: ^4.0.1
|
|
||||||
version: 4.0.1
|
|
||||||
sonner:
|
sonner:
|
||||||
specifier: ^2.0.1
|
specifier: ^2.0.1
|
||||||
version: 2.0.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 2.0.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
@@ -168,6 +168,9 @@ importers:
|
|||||||
husky:
|
husky:
|
||||||
specifier: ^9.1.7
|
specifier: ^9.1.7
|
||||||
version: 9.1.7
|
version: 9.1.7
|
||||||
|
rehype-highlight:
|
||||||
|
specifier: ^7.0.2
|
||||||
|
version: 7.0.2
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^4
|
specifier: ^4
|
||||||
version: 4.0.9
|
version: 4.0.9
|
||||||
@@ -1152,6 +1155,19 @@ packages:
|
|||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-separator@1.1.7':
|
||||||
|
resolution: {integrity: sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-slot@1.1.2':
|
'@radix-ui/react-slot@1.1.2':
|
||||||
resolution: {integrity: sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==}
|
resolution: {integrity: sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2040,10 +2056,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
|
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
escape-string-regexp@5.0.0:
|
|
||||||
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
|
|
||||||
engines: {node: '>=12'}
|
|
||||||
|
|
||||||
eslint-config-next@15.2.1:
|
eslint-config-next@15.2.1:
|
||||||
resolution: {integrity: sha512-mhsprz7l0no8X+PdDnVHF4dZKu9YBJp2Rf6ztWbXBLJ4h6gxmW//owbbGJMBVUU+PibGJDAqZhW4pt8SC8HSow==}
|
resolution: {integrity: sha512-mhsprz7l0no8X+PdDnVHF4dZKu9YBJp2Rf6ztWbXBLJ4h6gxmW//owbbGJMBVUU+PibGJDAqZhW4pt8SC8HSow==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2342,15 +2354,25 @@ packages:
|
|||||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
hast-util-is-element@3.0.0:
|
||||||
|
resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
|
||||||
|
|
||||||
hast-util-to-estree@3.1.3:
|
hast-util-to-estree@3.1.3:
|
||||||
resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==}
|
resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==}
|
||||||
|
|
||||||
hast-util-to-jsx-runtime@2.3.6:
|
hast-util-to-jsx-runtime@2.3.6:
|
||||||
resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
|
resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
|
||||||
|
|
||||||
|
hast-util-to-text@4.0.2:
|
||||||
|
resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==}
|
||||||
|
|
||||||
hast-util-whitespace@3.0.0:
|
hast-util-whitespace@3.0.0:
|
||||||
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
|
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
|
||||||
|
|
||||||
|
highlight.js@11.11.1:
|
||||||
|
resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
|
||||||
husky@9.1.7:
|
husky@9.1.7:
|
||||||
resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==}
|
resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -2657,6 +2679,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
lowlight@3.3.0:
|
||||||
|
resolution: {integrity: sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==}
|
||||||
|
|
||||||
lucide-react@0.479.0:
|
lucide-react@0.479.0:
|
||||||
resolution: {integrity: sha512-aBhNnveRhorBOK7uA4gDjgaf+YlHMdMhQ/3cupk6exM10hWlEU+2QtWYOfhXhjAsmdb6LeKR+NZnow4UxRRiTQ==}
|
resolution: {integrity: sha512-aBhNnveRhorBOK7uA4gDjgaf+YlHMdMhQ/3cupk6exM10hWlEU+2QtWYOfhXhjAsmdb6LeKR+NZnow4UxRRiTQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2666,37 +2691,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==}
|
resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
markdown-table@3.0.4:
|
|
||||||
resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
|
|
||||||
|
|
||||||
math-intrinsics@1.1.0:
|
math-intrinsics@1.1.0:
|
||||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
mdast-util-find-and-replace@3.0.2:
|
|
||||||
resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
|
|
||||||
|
|
||||||
mdast-util-from-markdown@2.0.2:
|
mdast-util-from-markdown@2.0.2:
|
||||||
resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==}
|
resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==}
|
||||||
|
|
||||||
mdast-util-gfm-autolink-literal@2.0.1:
|
|
||||||
resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}
|
|
||||||
|
|
||||||
mdast-util-gfm-footnote@2.1.0:
|
|
||||||
resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==}
|
|
||||||
|
|
||||||
mdast-util-gfm-strikethrough@2.0.0:
|
|
||||||
resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
|
|
||||||
|
|
||||||
mdast-util-gfm-table@2.0.0:
|
|
||||||
resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
|
|
||||||
|
|
||||||
mdast-util-gfm-task-list-item@2.0.0:
|
|
||||||
resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
|
|
||||||
|
|
||||||
mdast-util-gfm@3.1.0:
|
|
||||||
resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==}
|
|
||||||
|
|
||||||
mdast-util-mdx-expression@2.0.1:
|
mdast-util-mdx-expression@2.0.1:
|
||||||
resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
|
resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
|
||||||
|
|
||||||
@@ -2728,27 +2729,6 @@ packages:
|
|||||||
micromark-core-commonmark@2.0.3:
|
micromark-core-commonmark@2.0.3:
|
||||||
resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
|
resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
|
||||||
|
|
||||||
micromark-extension-gfm-autolink-literal@2.1.0:
|
|
||||||
resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==}
|
|
||||||
|
|
||||||
micromark-extension-gfm-footnote@2.1.0:
|
|
||||||
resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==}
|
|
||||||
|
|
||||||
micromark-extension-gfm-strikethrough@2.1.0:
|
|
||||||
resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==}
|
|
||||||
|
|
||||||
micromark-extension-gfm-table@2.1.1:
|
|
||||||
resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==}
|
|
||||||
|
|
||||||
micromark-extension-gfm-tagfilter@2.0.0:
|
|
||||||
resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
|
|
||||||
|
|
||||||
micromark-extension-gfm-task-list-item@2.1.0:
|
|
||||||
resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==}
|
|
||||||
|
|
||||||
micromark-extension-gfm@3.0.0:
|
|
||||||
resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
|
|
||||||
|
|
||||||
micromark-extension-mdx-expression@3.0.1:
|
micromark-extension-mdx-expression@3.0.1:
|
||||||
resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==}
|
resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==}
|
||||||
|
|
||||||
@@ -3145,12 +3125,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
|
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
rehype-highlight@7.0.2:
|
||||||
|
resolution: {integrity: sha512-k158pK7wdC2qL3M5NcZROZ2tR/l7zOzjxXd5VGdcfIyoijjQqpHd3JKtYSBDpDZ38UI2WJWuFAtkMDxmx5kstA==}
|
||||||
|
|
||||||
rehype-recma@1.0.0:
|
rehype-recma@1.0.0:
|
||||||
resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==}
|
resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==}
|
||||||
|
|
||||||
remark-gfm@4.0.1:
|
|
||||||
resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
|
|
||||||
|
|
||||||
remark-mdx@3.1.0:
|
remark-mdx@3.1.0:
|
||||||
resolution: {integrity: sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==}
|
resolution: {integrity: sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==}
|
||||||
|
|
||||||
@@ -3160,9 +3140,6 @@ packages:
|
|||||||
remark-rehype@11.1.2:
|
remark-rehype@11.1.2:
|
||||||
resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
|
resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
|
||||||
|
|
||||||
remark-stringify@11.0.0:
|
|
||||||
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
|
|
||||||
|
|
||||||
require-directory@2.1.1:
|
require-directory@2.1.1:
|
||||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -3461,6 +3438,9 @@ packages:
|
|||||||
unified@11.0.5:
|
unified@11.0.5:
|
||||||
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
|
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
|
||||||
|
|
||||||
|
unist-util-find-after@5.0.0:
|
||||||
|
resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==}
|
||||||
|
|
||||||
unist-util-is@6.0.0:
|
unist-util-is@6.0.0:
|
||||||
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
|
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
|
||||||
|
|
||||||
@@ -4517,6 +4497,15 @@ snapshots:
|
|||||||
'@types/react': 19.0.10
|
'@types/react': 19.0.10
|
||||||
'@types/react-dom': 19.0.4(@types/react@19.0.10)
|
'@types/react-dom': 19.0.4(@types/react@19.0.10)
|
||||||
|
|
||||||
|
'@radix-ui/react-separator@1.1.7(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
react: 19.0.0
|
||||||
|
react-dom: 19.0.0(react@19.0.0)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.0.10
|
||||||
|
'@types/react-dom': 19.0.4(@types/react@19.0.10)
|
||||||
|
|
||||||
'@radix-ui/react-slot@1.1.2(@types/react@19.0.10)(react@19.0.0)':
|
'@radix-ui/react-slot@1.1.2(@types/react@19.0.10)(react@19.0.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0)
|
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0)
|
||||||
@@ -5446,8 +5435,6 @@ snapshots:
|
|||||||
|
|
||||||
escape-string-regexp@4.0.0: {}
|
escape-string-regexp@4.0.0: {}
|
||||||
|
|
||||||
escape-string-regexp@5.0.0: {}
|
|
||||||
|
|
||||||
eslint-config-next@15.2.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2):
|
eslint-config-next@15.2.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@next/eslint-plugin-next': 15.2.1
|
'@next/eslint-plugin-next': 15.2.1
|
||||||
@@ -5836,6 +5823,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
function-bind: 1.1.2
|
function-bind: 1.1.2
|
||||||
|
|
||||||
|
hast-util-is-element@3.0.0:
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
|
||||||
hast-util-to-estree@3.1.3:
|
hast-util-to-estree@3.1.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.6
|
'@types/estree': 1.0.6
|
||||||
@@ -5877,10 +5868,19 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
hast-util-to-text@4.0.2:
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
'@types/unist': 3.0.3
|
||||||
|
hast-util-is-element: 3.0.0
|
||||||
|
unist-util-find-after: 5.0.0
|
||||||
|
|
||||||
hast-util-whitespace@3.0.0:
|
hast-util-whitespace@3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
|
|
||||||
|
highlight.js@11.11.1: {}
|
||||||
|
|
||||||
husky@9.1.7: {}
|
husky@9.1.7: {}
|
||||||
|
|
||||||
ieee754@1.2.1: {}
|
ieee754@1.2.1: {}
|
||||||
@@ -6155,23 +6155,20 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
js-tokens: 4.0.0
|
js-tokens: 4.0.0
|
||||||
|
|
||||||
|
lowlight@3.3.0:
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
devlop: 1.1.0
|
||||||
|
highlight.js: 11.11.1
|
||||||
|
|
||||||
lucide-react@0.479.0(react@19.0.0):
|
lucide-react@0.479.0(react@19.0.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 19.0.0
|
react: 19.0.0
|
||||||
|
|
||||||
markdown-extensions@2.0.0: {}
|
markdown-extensions@2.0.0: {}
|
||||||
|
|
||||||
markdown-table@3.0.4: {}
|
|
||||||
|
|
||||||
math-intrinsics@1.1.0: {}
|
math-intrinsics@1.1.0: {}
|
||||||
|
|
||||||
mdast-util-find-and-replace@3.0.2:
|
|
||||||
dependencies:
|
|
||||||
'@types/mdast': 4.0.4
|
|
||||||
escape-string-regexp: 5.0.0
|
|
||||||
unist-util-is: 6.0.0
|
|
||||||
unist-util-visit-parents: 6.0.1
|
|
||||||
|
|
||||||
mdast-util-from-markdown@2.0.2:
|
mdast-util-from-markdown@2.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/mdast': 4.0.4
|
'@types/mdast': 4.0.4
|
||||||
@@ -6189,63 +6186,6 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
mdast-util-gfm-autolink-literal@2.0.1:
|
|
||||||
dependencies:
|
|
||||||
'@types/mdast': 4.0.4
|
|
||||||
ccount: 2.0.1
|
|
||||||
devlop: 1.1.0
|
|
||||||
mdast-util-find-and-replace: 3.0.2
|
|
||||||
micromark-util-character: 2.1.1
|
|
||||||
|
|
||||||
mdast-util-gfm-footnote@2.1.0:
|
|
||||||
dependencies:
|
|
||||||
'@types/mdast': 4.0.4
|
|
||||||
devlop: 1.1.0
|
|
||||||
mdast-util-from-markdown: 2.0.2
|
|
||||||
mdast-util-to-markdown: 2.1.2
|
|
||||||
micromark-util-normalize-identifier: 2.0.1
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
|
|
||||||
mdast-util-gfm-strikethrough@2.0.0:
|
|
||||||
dependencies:
|
|
||||||
'@types/mdast': 4.0.4
|
|
||||||
mdast-util-from-markdown: 2.0.2
|
|
||||||
mdast-util-to-markdown: 2.1.2
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
|
|
||||||
mdast-util-gfm-table@2.0.0:
|
|
||||||
dependencies:
|
|
||||||
'@types/mdast': 4.0.4
|
|
||||||
devlop: 1.1.0
|
|
||||||
markdown-table: 3.0.4
|
|
||||||
mdast-util-from-markdown: 2.0.2
|
|
||||||
mdast-util-to-markdown: 2.1.2
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
|
|
||||||
mdast-util-gfm-task-list-item@2.0.0:
|
|
||||||
dependencies:
|
|
||||||
'@types/mdast': 4.0.4
|
|
||||||
devlop: 1.1.0
|
|
||||||
mdast-util-from-markdown: 2.0.2
|
|
||||||
mdast-util-to-markdown: 2.1.2
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
|
|
||||||
mdast-util-gfm@3.1.0:
|
|
||||||
dependencies:
|
|
||||||
mdast-util-from-markdown: 2.0.2
|
|
||||||
mdast-util-gfm-autolink-literal: 2.0.1
|
|
||||||
mdast-util-gfm-footnote: 2.1.0
|
|
||||||
mdast-util-gfm-strikethrough: 2.0.0
|
|
||||||
mdast-util-gfm-table: 2.0.0
|
|
||||||
mdast-util-gfm-task-list-item: 2.0.0
|
|
||||||
mdast-util-to-markdown: 2.1.2
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
|
|
||||||
mdast-util-mdx-expression@2.0.1:
|
mdast-util-mdx-expression@2.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree-jsx': 1.0.5
|
'@types/estree-jsx': 1.0.5
|
||||||
@@ -6349,64 +6289,6 @@ snapshots:
|
|||||||
micromark-util-symbol: 2.0.1
|
micromark-util-symbol: 2.0.1
|
||||||
micromark-util-types: 2.0.2
|
micromark-util-types: 2.0.2
|
||||||
|
|
||||||
micromark-extension-gfm-autolink-literal@2.1.0:
|
|
||||||
dependencies:
|
|
||||||
micromark-util-character: 2.1.1
|
|
||||||
micromark-util-sanitize-uri: 2.0.1
|
|
||||||
micromark-util-symbol: 2.0.1
|
|
||||||
micromark-util-types: 2.0.2
|
|
||||||
|
|
||||||
micromark-extension-gfm-footnote@2.1.0:
|
|
||||||
dependencies:
|
|
||||||
devlop: 1.1.0
|
|
||||||
micromark-core-commonmark: 2.0.3
|
|
||||||
micromark-factory-space: 2.0.1
|
|
||||||
micromark-util-character: 2.1.1
|
|
||||||
micromark-util-normalize-identifier: 2.0.1
|
|
||||||
micromark-util-sanitize-uri: 2.0.1
|
|
||||||
micromark-util-symbol: 2.0.1
|
|
||||||
micromark-util-types: 2.0.2
|
|
||||||
|
|
||||||
micromark-extension-gfm-strikethrough@2.1.0:
|
|
||||||
dependencies:
|
|
||||||
devlop: 1.1.0
|
|
||||||
micromark-util-chunked: 2.0.1
|
|
||||||
micromark-util-classify-character: 2.0.1
|
|
||||||
micromark-util-resolve-all: 2.0.1
|
|
||||||
micromark-util-symbol: 2.0.1
|
|
||||||
micromark-util-types: 2.0.2
|
|
||||||
|
|
||||||
micromark-extension-gfm-table@2.1.1:
|
|
||||||
dependencies:
|
|
||||||
devlop: 1.1.0
|
|
||||||
micromark-factory-space: 2.0.1
|
|
||||||
micromark-util-character: 2.1.1
|
|
||||||
micromark-util-symbol: 2.0.1
|
|
||||||
micromark-util-types: 2.0.2
|
|
||||||
|
|
||||||
micromark-extension-gfm-tagfilter@2.0.0:
|
|
||||||
dependencies:
|
|
||||||
micromark-util-types: 2.0.2
|
|
||||||
|
|
||||||
micromark-extension-gfm-task-list-item@2.1.0:
|
|
||||||
dependencies:
|
|
||||||
devlop: 1.1.0
|
|
||||||
micromark-factory-space: 2.0.1
|
|
||||||
micromark-util-character: 2.1.1
|
|
||||||
micromark-util-symbol: 2.0.1
|
|
||||||
micromark-util-types: 2.0.2
|
|
||||||
|
|
||||||
micromark-extension-gfm@3.0.0:
|
|
||||||
dependencies:
|
|
||||||
micromark-extension-gfm-autolink-literal: 2.1.0
|
|
||||||
micromark-extension-gfm-footnote: 2.1.0
|
|
||||||
micromark-extension-gfm-strikethrough: 2.1.0
|
|
||||||
micromark-extension-gfm-table: 2.1.1
|
|
||||||
micromark-extension-gfm-tagfilter: 2.0.0
|
|
||||||
micromark-extension-gfm-task-list-item: 2.1.0
|
|
||||||
micromark-util-combine-extensions: 2.0.1
|
|
||||||
micromark-util-types: 2.0.2
|
|
||||||
|
|
||||||
micromark-extension-mdx-expression@3.0.1:
|
micromark-extension-mdx-expression@3.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.6
|
'@types/estree': 1.0.6
|
||||||
@@ -6964,6 +6846,14 @@ snapshots:
|
|||||||
gopd: 1.2.0
|
gopd: 1.2.0
|
||||||
set-function-name: 2.0.2
|
set-function-name: 2.0.2
|
||||||
|
|
||||||
|
rehype-highlight@7.0.2:
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
hast-util-to-text: 4.0.2
|
||||||
|
lowlight: 3.3.0
|
||||||
|
unist-util-visit: 5.0.0
|
||||||
|
vfile: 6.0.3
|
||||||
|
|
||||||
rehype-recma@1.0.0:
|
rehype-recma@1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.6
|
'@types/estree': 1.0.6
|
||||||
@@ -6972,17 +6862,6 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
remark-gfm@4.0.1:
|
|
||||||
dependencies:
|
|
||||||
'@types/mdast': 4.0.4
|
|
||||||
mdast-util-gfm: 3.1.0
|
|
||||||
micromark-extension-gfm: 3.0.0
|
|
||||||
remark-parse: 11.0.0
|
|
||||||
remark-stringify: 11.0.0
|
|
||||||
unified: 11.0.5
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
|
|
||||||
remark-mdx@3.1.0:
|
remark-mdx@3.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
mdast-util-mdx: 3.0.0
|
mdast-util-mdx: 3.0.0
|
||||||
@@ -7007,12 +6886,6 @@ snapshots:
|
|||||||
unified: 11.0.5
|
unified: 11.0.5
|
||||||
vfile: 6.0.3
|
vfile: 6.0.3
|
||||||
|
|
||||||
remark-stringify@11.0.0:
|
|
||||||
dependencies:
|
|
||||||
'@types/mdast': 4.0.4
|
|
||||||
mdast-util-to-markdown: 2.1.2
|
|
||||||
unified: 11.0.5
|
|
||||||
|
|
||||||
require-directory@2.1.1: {}
|
require-directory@2.1.1: {}
|
||||||
|
|
||||||
require-main-filename@2.0.0: {}
|
require-main-filename@2.0.0: {}
|
||||||
@@ -7388,6 +7261,11 @@ snapshots:
|
|||||||
trough: 2.2.0
|
trough: 2.2.0
|
||||||
vfile: 6.0.3
|
vfile: 6.0.3
|
||||||
|
|
||||||
|
unist-util-find-after@5.0.0:
|
||||||
|
dependencies:
|
||||||
|
'@types/unist': 3.0.3
|
||||||
|
unist-util-is: 6.0.0
|
||||||
|
|
||||||
unist-util-is@6.0.0:
|
unist-util-is@6.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
|
|||||||
@@ -47,8 +47,7 @@ export async function GET(req: NextRequest) {
|
|||||||
|
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case 'json':
|
case 'json':
|
||||||
const body = JSON.stringify(params)
|
return NextResponse.json(result.data)
|
||||||
return NextResponse.json(body)
|
|
||||||
case 'text':
|
case 'text':
|
||||||
const text = result.data.map((item) => {
|
const text = result.data.map((item) => {
|
||||||
const list = [item.host, item.port]
|
const list = [item.host, item.port]
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export default function Provider(props: ProviderProps) {
|
|||||||
<div className="flex justify-between gap-8">
|
<div className="flex justify-between gap-8">
|
||||||
{/* logo */}
|
{/* logo */}
|
||||||
<Link href="/" className="flex items-center">
|
<Link href="/" className="flex items-center">
|
||||||
<Image src={logo} alt="logo" height={48}/>
|
<Image src={logo} alt="logo" height={40} className="translate-y-0.5"/>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{/* 菜单 */}
|
{/* 菜单 */}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ export default function Charts() {
|
|||||||
<Card className="h-full">
|
<Card className="h-full">
|
||||||
<CardContent className="overflow-hidden">
|
<CardContent className="overflow-hidden">
|
||||||
<Tabs defaultValue="dynamic" className="h-full gap-4">
|
<Tabs defaultValue="dynamic" className="h-full gap-4">
|
||||||
<TabsList>
|
<TabsList className="h-9">
|
||||||
<TabsTrigger value="dynamic" className="data-[state=active]:text-primary">
|
<TabsTrigger value="dynamic" className="data-[state=active]:text-primary">
|
||||||
动态 IP 套餐
|
动态 IP 套餐
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export default function Navbar(props: NavbarProps) {
|
|||||||
data-expand={navbar}
|
data-expand={navbar}
|
||||||
className={merge(
|
className={merge(
|
||||||
`transition-[flex-basis] duration-300 ease-in-out`,
|
`transition-[flex-basis] duration-300 ease-in-out`,
|
||||||
`flex flex-col overflow-hidden group`,
|
`h-full flex flex-col overflow-hidden group`,
|
||||||
`data-[expand=true]:basis-52 data-[expand=false]:basis-16`,
|
`data-[expand=true]:basis-52 data-[expand=false]:basis-16`,
|
||||||
)}>
|
)}>
|
||||||
{/* logo */}
|
{/* logo */}
|
||||||
@@ -54,7 +54,7 @@ export default function Navbar(props: NavbarProps) {
|
|||||||
{/* routes */}
|
{/* routes */}
|
||||||
<section className={merge(
|
<section className={merge(
|
||||||
`transition-[padding] duration-300 ease-in-out`,
|
`transition-[padding] duration-300 ease-in-out`,
|
||||||
`flex-auto overflow-x-hidden overflow-y-auto`,
|
`flex-auto overflow-x-hidden overflow-y-auto pb-4`,
|
||||||
`group-data-[expand=true]:px-4 group-data-[expand=false]:px-3`,
|
`group-data-[expand=true]:px-4 group-data-[expand=false]:px-3`,
|
||||||
)}>
|
)}>
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export type ExtractPageProps = {}
|
|||||||
export default async function ExtractPage(props: ExtractPageProps) {
|
export default async function ExtractPage(props: ExtractPageProps) {
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<Extract className="p-8"/>
|
<Extract/>
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {Button} from '@/components/ui/button'
|
|||||||
import {useForm, useFormContext} from 'react-hook-form'
|
import {useForm, useFormContext} from 'react-hook-form'
|
||||||
import {Alert, AlertTitle} from '@/components/ui/alert'
|
import {Alert, AlertTitle} from '@/components/ui/alert'
|
||||||
import {Box, CircleAlert, CopyIcon, ExternalLinkIcon, Loader, Timer} from 'lucide-react'
|
import {Box, CircleAlert, CopyIcon, ExternalLinkIcon, Loader, Timer} from 'lucide-react'
|
||||||
import {memo, useEffect, useRef, useState} from 'react'
|
import {memo, ReactNode, useEffect, useRef, useState} from 'react'
|
||||||
import {useStatus} from '@/lib/states'
|
import {useStatus} from '@/lib/states'
|
||||||
import {allResource} from '@/actions/resource'
|
import {allResource} from '@/actions/resource'
|
||||||
import {Resource} from '@/lib/models'
|
import {Resource} from '@/lib/models'
|
||||||
@@ -18,6 +18,8 @@ import {toast} from 'sonner'
|
|||||||
import {merge} from '@/lib/utils'
|
import {merge} from '@/lib/utils'
|
||||||
import {Combobox} from '@/components/ui/combobox'
|
import {Combobox} from '@/components/ui/combobox'
|
||||||
import cities from './_assets/cities.json'
|
import cities from './_assets/cities.json'
|
||||||
|
import ExtractDocs from '@/components/docs/extract.mdx'
|
||||||
|
import Markdown from '@/components/markdown'
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
resource: z.number({required_error: '请选择套餐'}),
|
resource: z.number({required_error: '请选择套餐'}),
|
||||||
@@ -64,25 +66,44 @@ export default function Extract(props: ExtractProps) {
|
|||||||
<Form
|
<Form
|
||||||
form={form}
|
form={form}
|
||||||
className={merge(
|
className={merge(
|
||||||
`bg-white flex flex-col gap-4 rounded-md`,
|
`flex flex-col gap-6`,
|
||||||
props.className,
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Alert variant="warn">
|
<CardSection>
|
||||||
<CircleAlert/>
|
<Alert variant="warn" >
|
||||||
<AlertTitle>提取IP前需要将本机IP添加到白名单后才可使用</AlertTitle>
|
<CircleAlert/>
|
||||||
</Alert>
|
<AlertTitle>提取IP前需要将本机IP添加到白名单后才可使用</AlertTitle>
|
||||||
|
</Alert>
|
||||||
|
|
||||||
<FormFields/>
|
<FormFields/>
|
||||||
|
</CardSection>
|
||||||
|
|
||||||
<ApplyLink/>
|
<CardSection>
|
||||||
|
<ApplyLink/>
|
||||||
|
</CardSection>
|
||||||
|
|
||||||
|
<CardSection>
|
||||||
|
<Markdown>
|
||||||
|
<ExtractDocs/>
|
||||||
|
</Markdown>
|
||||||
|
</CardSection>
|
||||||
</Form>
|
</Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function CardSection(props: {
|
||||||
|
children: ReactNode
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-4 p-4 md:p-6 bg-white rounded-lg">
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const FormFields = memo(() => {
|
const FormFields = memo(() => {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-6 items-stretch max-w-[calc(160px*4+1rem*3)]">
|
||||||
{/* 选择套餐 */}
|
{/* 选择套餐 */}
|
||||||
<SelectResource/>
|
<SelectResource/>
|
||||||
|
|
||||||
@@ -90,192 +111,177 @@ const FormFields = memo(() => {
|
|||||||
<SelectRegion/>
|
<SelectRegion/>
|
||||||
|
|
||||||
{/* 运营商筛选 */}
|
{/* 运营商筛选 */}
|
||||||
<div className="flex items-center">
|
<FormField name="isp" label="运营商筛选" classNames={{label: 'max-md:text-sm'}}>
|
||||||
<FormField name="isp" label="运营商筛选">
|
{({id, field}) => (
|
||||||
{({id, field}) => (
|
<RadioGroup
|
||||||
<RadioGroup
|
onValueChange={field.onChange}
|
||||||
onValueChange={field.onChange}
|
defaultValue={field.value}
|
||||||
defaultValue={field.value}
|
className="grid grid-cols-2 md:grid-cols-4 gap-4"
|
||||||
className="flex gap-4">
|
>
|
||||||
<FormLabel htmlFor={`${id}-v-all`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<FormLabel htmlFor={`${id}-v-all`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<RadioGroupItem value="all" id={`${id}-v-all`}/>
|
<RadioGroupItem value="all" id={`${id}-v-all`}/>
|
||||||
<span>不限</span>
|
<span>不限</span>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormLabel htmlFor={`${id}-v-telecom`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<FormLabel htmlFor={`${id}-v-telecom`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<RadioGroupItem value="1" id={`${id}-v-telecom`}/>
|
<RadioGroupItem value="1" id={`${id}-v-telecom`}/>
|
||||||
<span>电信</span>
|
<span>电信</span>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormLabel htmlFor={`${id}-v-mobile`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<FormLabel htmlFor={`${id}-v-mobile`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<RadioGroupItem value="2" id={`${id}-v-mobile`}/>
|
<RadioGroupItem value="2" id={`${id}-v-mobile`}/>
|
||||||
<span>联通</span>
|
<span>联通</span>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormLabel htmlFor={`${id}-v-unicom`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<FormLabel htmlFor={`${id}-v-unicom`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<RadioGroupItem value="3" id={`${id}-v-unicom`}/>
|
<RadioGroupItem value="3" id={`${id}-v-unicom`}/>
|
||||||
<span>移动</span>
|
<span>移动</span>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
)}
|
)}
|
||||||
</FormField>
|
</FormField>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 协议类型 */}
|
{/* 协议类型 */}
|
||||||
<div className="flex items-center">
|
<FormField name="proto" label="协议类型" classNames={{label: 'max-md:text-sm'}}>
|
||||||
<FormField name="proto" label="协议类型">
|
{({id, field}) => (
|
||||||
{({id, field}) => (
|
<RadioGroup
|
||||||
<RadioGroup
|
onValueChange={field.onChange}
|
||||||
onValueChange={field.onChange}
|
defaultValue={field.value}
|
||||||
defaultValue={field.value}
|
className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||||
className="flex gap-4">
|
<FormLabel htmlFor={`${id}-v-all`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-all`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="all" id={`${id}-v-all`} className="mr-2"/>
|
||||||
<RadioGroupItem value="all" id={`${id}-v-all`} className="mr-2"/>
|
<span>不限</span>
|
||||||
<span>不限</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
<FormLabel htmlFor={`${id}-v-http`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-http`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="1" id={`${id}-v-http`} className="mr-2"/>
|
||||||
<RadioGroupItem value="1" id={`${id}-v-http`} className="mr-2"/>
|
<span>HTTP</span>
|
||||||
<span>HTTP</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
<FormLabel htmlFor={`${id}-v-https`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-https`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="2" id={`${id}-v-https`} className="mr-2"/>
|
||||||
<RadioGroupItem value="2" id={`${id}-v-https`} className="mr-2"/>
|
<span>HTTPS</span>
|
||||||
<span>HTTPS</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
<FormLabel htmlFor={`${id}-v-socks5`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-socks5`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="3" id={`${id}-v-socks5`} className="mr-2"/>
|
||||||
<RadioGroupItem value="3" id={`${id}-v-socks5`} className="mr-2"/>
|
<span>SOCKS5</span>
|
||||||
<span>SOCKS5</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
</RadioGroup>
|
||||||
</RadioGroup>
|
)}
|
||||||
)}
|
</FormField>
|
||||||
</FormField>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 认证方式 */}
|
{/* 认证方式 */}
|
||||||
<div className="flex items-center">
|
<FormField name="authType" className="md:max-w-[calc(160px*2+1rem)]" label="认证方式" classNames={{label: 'max-md:text-sm'}}>
|
||||||
<FormField name="authType" label="协议类型">
|
{({id, field}) => (
|
||||||
{({id, field}) => (
|
<RadioGroup
|
||||||
<RadioGroup
|
onValueChange={field.onChange}
|
||||||
onValueChange={field.onChange}
|
defaultValue={field.value}
|
||||||
defaultValue={field.value}
|
className="flex gap-4">
|
||||||
className="flex gap-4">
|
<FormLabel htmlFor={`${id}-v-http`} className="px-3 h-10 flex-1 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-http`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="1" id={`${id}-v-http`} className="mr-2"/>
|
||||||
<RadioGroupItem value="1" id={`${id}-v-http`} className="mr-2"/>
|
<span>白名单</span>
|
||||||
<span>白名单</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
<FormLabel htmlFor={`${id}-v-https`} className="px-3 h-10 flex-1 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-https`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="2" id={`${id}-v-https`} className="mr-2"/>
|
||||||
<RadioGroupItem value="2" id={`${id}-v-https`} className="mr-2"/>
|
<span>密码</span>
|
||||||
<span>密码</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
</RadioGroup>
|
||||||
</RadioGroup>
|
)}
|
||||||
)}
|
</FormField>
|
||||||
</FormField>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 去重选项 */}
|
{/* 去重选项 */}
|
||||||
<div className="flex items-center">
|
<FormField name="distinct" className="md:max-w-[calc(160px*2+1rem)]" label="去重选项" classNames={{label: 'max-md:text-sm'}}>
|
||||||
<FormField name="distinct" label="去重选项">
|
{({id, field}) => (
|
||||||
{({id, field}) => (
|
<RadioGroup
|
||||||
<RadioGroup
|
onValueChange={field.onChange}
|
||||||
onValueChange={field.onChange}
|
defaultValue={field.value}
|
||||||
defaultValue={field.value}
|
className="flex gap-4">
|
||||||
className="flex gap-4">
|
<FormLabel htmlFor={`${id}-v-true`} className="px-3 h-10 flex-1 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-true`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="1" id={`${id}-v-true`} className="mr-2"/>
|
||||||
<RadioGroupItem value="1" id={`${id}-v-true`} className="mr-2"/>
|
<span>去重</span>
|
||||||
<span>去重</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
<FormLabel htmlFor={`${id}-v-false`} className="px-3 h-10 flex-1 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-false`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="0" id={`${id}-v-false`} className="mr-2"/>
|
||||||
<RadioGroupItem value="0" id={`${id}-v-false`} className="mr-2"/>
|
<span>不去重</span>
|
||||||
<span>不去重</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
</RadioGroup>
|
||||||
</RadioGroup>
|
)}
|
||||||
)}
|
</FormField>
|
||||||
</FormField>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 导出格式 */}
|
{/* 导出格式 */}
|
||||||
<div className="flex items-center">
|
<FormField name="format" className="md:max-w-[calc(160px*2+1rem)]" label="导出格式" classNames={{label: 'max-md:text-sm'}}>
|
||||||
<FormField name="format" label="导出格式">
|
{({id, field}) => (
|
||||||
{({id, field}) => (
|
<RadioGroup
|
||||||
<RadioGroup
|
onValueChange={field.onChange}
|
||||||
onValueChange={field.onChange}
|
defaultValue={field.value}
|
||||||
defaultValue={field.value}
|
className="flex gap-4"
|
||||||
className="flex gap-4"
|
>
|
||||||
>
|
<FormLabel htmlFor={`${id}-v-txt`} className="px-3 h-10 flex-1 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-txt`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="text" id={`${id}-v-txt`} className="mr-2"/>
|
||||||
<RadioGroupItem value="text" id={`${id}-v-txt`} className="mr-2"/>
|
<span>TXT 格式</span>
|
||||||
<span>TXT 格式</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
<FormLabel htmlFor={`${id}-v-json`} className="px-3 h-10 flex-1 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-json`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="json" id={`${id}-v-json`} className="mr-2"/>
|
||||||
<RadioGroupItem value="json" id={`${id}-v-json`} className="mr-2"/>
|
<span>JSON 格式</span>
|
||||||
<span>JSON 格式</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
</RadioGroup>
|
||||||
</RadioGroup>
|
)}
|
||||||
)}
|
</FormField>
|
||||||
</FormField>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 分隔符 */}
|
{/* 分隔符 */}
|
||||||
<div className="flex items-center">
|
<FormField name="separator" className="md:max-w-[calc(160px*3+1rem*2)]" label="分隔符" classNames={{label: 'max-md:text-sm'}}>
|
||||||
<FormField name="separator" label="分隔符">
|
{({id, field}) => (
|
||||||
{({id, field}) => (
|
<RadioGroup
|
||||||
<RadioGroup
|
onValueChange={field.onChange}
|
||||||
onValueChange={field.onChange}
|
defaultValue={field.value}
|
||||||
defaultValue={field.value}
|
className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
||||||
className="flex gap-4">
|
<FormLabel htmlFor={`${id}-v-comma`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-comma`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="124" id={`${id}-v-comma`} className="mr-2"/>
|
||||||
<RadioGroupItem value="124" id={`${id}-v-comma`} className="mr-2"/>
|
<span>竖线 ( | )</span>
|
||||||
<span>竖线 ( | )</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
<FormLabel htmlFor={`${id}-v-semicolon`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-semicolon`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="58" id={`${id}-v-semicolon`} className="mr-2"/>
|
||||||
<RadioGroupItem value="58" id={`${id}-v-semicolon`} className="mr-2"/>
|
<span>冒号 ( : )</span>
|
||||||
<span>冒号 ( : )</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
<FormLabel htmlFor={`${id}-v-space`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-space`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="9" id={`${id}-v-space`} className="mr-2"/>
|
||||||
<RadioGroupItem value="9" id={`${id}-v-space`} className="mr-2"/>
|
<span>制表符 ( \t )</span>
|
||||||
<span>制表符 ( \t )</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
</RadioGroup>
|
||||||
</RadioGroup>
|
)}
|
||||||
)}
|
</FormField>
|
||||||
</FormField>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 换行符 */}
|
{/* 换行符 */}
|
||||||
<div className="flex items-center">
|
<FormField name="breaker" className="md:max-w-[calc(160px*3+1rem*2)]" label="换行符" classNames={{label: 'max-md:text-sm'}}>
|
||||||
<FormField name="breaker" label="换行符">
|
{({id, field}) => (
|
||||||
{({id, field}) => (
|
<RadioGroup
|
||||||
<RadioGroup
|
onValueChange={field.onChange}
|
||||||
onValueChange={field.onChange}
|
defaultValue={field.value}
|
||||||
defaultValue={field.value}
|
className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
||||||
className="flex gap-4">
|
<FormLabel htmlFor={`${id}-v-newline2`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-newline2`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="13,10" id={`${id}-v-newline2`} className="mr-2"/>
|
||||||
<RadioGroupItem value="13,10" id={`${id}-v-newline2`} className="mr-2"/>
|
<span>回车换行 ( \r\n )</span>
|
||||||
<span>回车换行 ( \r\n )</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
<FormLabel htmlFor={`${id}-v-newline`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-newline`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="10" id={`${id}-v-newline`} className="mr-2"/>
|
||||||
<RadioGroupItem value="10" id={`${id}-v-newline`} className="mr-2"/>
|
<span>换行 ( \n )</span>
|
||||||
<span>换行 ( \n )</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
<FormLabel htmlFor={`${id}-v-newline3`} className="px-3 h-10 border rounded-md flex items-center text-sm">
|
||||||
<FormLabel htmlFor={`${id}-v-newline3`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<RadioGroupItem value="13" id={`${id}-v-newline3`} className="mr-2"/>
|
||||||
<RadioGroupItem value="13" id={`${id}-v-newline3`} className="mr-2"/>
|
<span>回车 ( \r )</span>
|
||||||
<span>回车 ( \r )</span>
|
</FormLabel>
|
||||||
</FormLabel>
|
</RadioGroup>
|
||||||
</RadioGroup>
|
)}
|
||||||
)}
|
</FormField>
|
||||||
</FormField>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 提取数量 */}
|
{/* 提取数量 */}
|
||||||
<div className="flex items-center">
|
<FormField name="count" className="max-w[160px*2+1rem]" label="提取数量" classNames={{label: 'max-md:text-sm'}}>
|
||||||
<FormField name="count" label="提取数量">
|
{({id, field}) => (
|
||||||
{({id, field}) => (
|
<Input
|
||||||
<Input
|
{...field}
|
||||||
{...field}
|
id={id}
|
||||||
id={id}
|
type="number"
|
||||||
type="number"
|
onChange={e => field.onChange(Number(e.target.value))}
|
||||||
onChange={e => field.onChange(Number(e.target.value))}
|
className="h-10"
|
||||||
className="h-10 w-84"
|
placeholder="输入提取数量"
|
||||||
placeholder="输入提取数量"
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
</FormField>
|
||||||
</FormField>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -308,116 +314,114 @@ function SelectResource() {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center">
|
<FormField name="resource" className="md:max-w-[calc(160px*2+1rem)]" label="选择套餐" classNames={{label: 'max-md:text-sm'}}>
|
||||||
<FormField name="resource" label="选择套餐">
|
{({field}) => (
|
||||||
{({field}) => (
|
<Select
|
||||||
<Select
|
value={field.value ? String(field.value) : undefined}
|
||||||
value={field.value ? String(field.value) : undefined}
|
onValueChange={value => field.onChange(Number(value))}
|
||||||
onValueChange={value => field.onChange(Number(value))}
|
>
|
||||||
>
|
<SelectTrigger className="min-h-10 h-auto w-full">
|
||||||
<SelectTrigger className="min-h-10 h-auto w-84">
|
<SelectValue placeholder="选择套餐"/>
|
||||||
<SelectValue placeholder="选择套餐"/>
|
</SelectTrigger>
|
||||||
</SelectTrigger>
|
<SelectContent>
|
||||||
<SelectContent>
|
{status === 'load' ? (
|
||||||
{status === 'load' ? (
|
<div className="p-4 flex gap-1 items-center">
|
||||||
<div className="p-4 flex gap-1 items-center">
|
<Loader className="animate-spin" size={20}/>
|
||||||
<Loader className="animate-spin" size={20}/>
|
<span>加载中...</span>
|
||||||
<span>加载中...</span>
|
</div>
|
||||||
</div>
|
) : resources.length === 0 ? (
|
||||||
) : resources.length === 0 ? (
|
<div className="p-4 flex gap-1 items-center">
|
||||||
<div className="p-4 flex gap-1 items-center">
|
<Loader className="animate-spin" size={20}/>
|
||||||
<Loader className="animate-spin" size={20}/>
|
<span>暂无可用套餐</span>
|
||||||
<span>暂无可用套餐</span>
|
</div>
|
||||||
</div>
|
) : resources.map((resource, i) => (
|
||||||
) : resources.map((resource, i) => (
|
<>
|
||||||
<>
|
<SelectItem
|
||||||
<SelectItem
|
key={`${resource.id}`}
|
||||||
key={`${resource.id}`}
|
value={String(resource.id)}
|
||||||
value={String(resource.id)}
|
className="p-3">
|
||||||
className="p-3">
|
<div className="flex flex-col gap-2 w-72">
|
||||||
<div className="flex flex-col gap-2 w-72">
|
{resource.type === 1 && resource.short.type === 1 && (
|
||||||
{resource.type === 1 && resource.short.type === 1 && (
|
<>
|
||||||
<>
|
<div className="flex gap-2 items-center bg-green-50 w-fit px-2 py-1 rounded-md text-sm">
|
||||||
<div className="flex gap-2 items-center bg-green-50 w-fit px-2 py-1 rounded-md text-sm">
|
<Timer size={20}/>
|
||||||
<Timer size={20}/>
|
<span>{name(resource)}</span>
|
||||||
<span>{name(resource)}</span>
|
</div>
|
||||||
</div>
|
<div className="flex justify-between gap-2 text-xs text-weak">
|
||||||
<div className="flex justify-between gap-2 text-xs text-weak">
|
<span>
|
||||||
<span>
|
到期时间:
|
||||||
到期时间:
|
{format(resource.short.expire, 'yyyy-MM-dd HH:mm')}
|
||||||
{format(resource.short.expire, 'yyyy-MM-dd HH:mm')}
|
</span>
|
||||||
</span>
|
<span>{intlFormatDistance(resource.short.expire, new Date())}</span>
|
||||||
<span>{intlFormatDistance(resource.short.expire, new Date())}</span>
|
</div>
|
||||||
</div>
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
{resource.type === 1 && resource.short.type === 2 && (
|
||||||
{resource.type === 1 && resource.short.type === 2 && (
|
<>
|
||||||
<>
|
<div className="flex gap-2 items-center bg-blue-50 w-fit px-2 py-1 rounded-md text-sm">
|
||||||
<div className="flex gap-2 items-center bg-blue-50 w-fit px-2 py-1 rounded-md text-sm">
|
<Box size={20}/>
|
||||||
<Box size={20}/>
|
<span>{name(resource)}</span>
|
||||||
<span>{name(resource)}</span>
|
</div>
|
||||||
</div>
|
<div className="flex justify-between gap-2 text-xs text-weak">
|
||||||
<div className="flex justify-between gap-2 text-xs text-weak">
|
<span>
|
||||||
<span>
|
提取数量:
|
||||||
提取数量:
|
{resource.short.used}
|
||||||
{resource.short.used}
|
{' '}
|
||||||
{' '}
|
/
|
||||||
/
|
{resource.short.quota}
|
||||||
{resource.short.quota}
|
</span>
|
||||||
</span>
|
<span>
|
||||||
<span>
|
剩余
|
||||||
剩余
|
{resource.short.quota - resource.short.used}
|
||||||
{resource.short.quota - resource.short.used}
|
</span>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
{resource.type === 2 && resource.long.type === 1 && (
|
||||||
{resource.type === 2 && resource.long.type === 1 && (
|
<>
|
||||||
<>
|
<div className="flex gap-2 items-center bg-green-50 w-fit px-2 py-1 rounded-md text-sm">
|
||||||
<div className="flex gap-2 items-center bg-green-50 w-fit px-2 py-1 rounded-md text-sm">
|
<Timer size={20}/>
|
||||||
<Timer size={20}/>
|
<span>{name(resource)}</span>
|
||||||
<span>{name(resource)}</span>
|
</div>
|
||||||
</div>
|
<div className="flex justify-between gap-2 text-xs text-weak">
|
||||||
<div className="flex justify-between gap-2 text-xs text-weak">
|
<span>
|
||||||
<span>
|
到期时间:
|
||||||
到期时间:
|
{format(resource.long.expire, 'yyyy-MM-dd HH:mm')}
|
||||||
{format(resource.long.expire, 'yyyy-MM-dd HH:mm')}
|
</span>
|
||||||
</span>
|
<span>{intlFormatDistance(resource.long.expire, new Date())}</span>
|
||||||
<span>{intlFormatDistance(resource.long.expire, new Date())}</span>
|
</div>
|
||||||
</div>
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
{resource.type === 2 && resource.long.type === 2 && (
|
||||||
{resource.type === 2 && resource.long.type === 2 && (
|
<>
|
||||||
<>
|
<div className="flex gap-2 items-center bg-blue-50 w-fit px-2 py-1 rounded-md text-sm">
|
||||||
<div className="flex gap-2 items-center bg-blue-50 w-fit px-2 py-1 rounded-md text-sm">
|
<Box size={20}/>
|
||||||
<Box size={20}/>
|
<span>{name(resource)}</span>
|
||||||
<span>{name(resource)}</span>
|
</div>
|
||||||
</div>
|
<div className="flex justify-between gap-2 text-xs text-weak">
|
||||||
<div className="flex justify-between gap-2 text-xs text-weak">
|
<span>
|
||||||
<span>
|
提取数量:
|
||||||
提取数量:
|
{resource.long.used}
|
||||||
{resource.long.used}
|
{' '}
|
||||||
{' '}
|
/
|
||||||
/
|
{resource.long.quota}
|
||||||
{resource.long.quota}
|
</span>
|
||||||
</span>
|
<span>
|
||||||
<span>
|
剩余
|
||||||
剩余
|
{resource.long.quota - resource.long.used}
|
||||||
{resource.long.quota - resource.long.used}
|
</span>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
</SelectItem>
|
||||||
</SelectItem>
|
{i < resources.length - 1 && <SelectSeparator className="m-1"/>}
|
||||||
{i < resources.length - 1 && <SelectSeparator className="m-1"/>}
|
</>
|
||||||
</>
|
))}
|
||||||
))}
|
</SelectContent>
|
||||||
</SelectContent>
|
</Select>
|
||||||
</Select>
|
)}
|
||||||
)}
|
</FormField>
|
||||||
</FormField>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,8 +432,8 @@ function SelectRegion() {
|
|||||||
const city = form.watch('city')
|
const city = form.watch('city')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4 md:max-w-[calc(160px*2+1rem)]">
|
||||||
<FormField name="regionType" label="地区筛选">
|
<FormField name="regionType" label="地区筛选" classNames={{label: 'max-md:text-sm'}}>
|
||||||
{({id, field}) => (
|
{({id, field}) => (
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
onValueChange={(e) => {
|
onValueChange={(e) => {
|
||||||
@@ -442,11 +446,11 @@ function SelectRegion() {
|
|||||||
defaultValue={field.value}
|
defaultValue={field.value}
|
||||||
className="flex gap-4"
|
className="flex gap-4"
|
||||||
>
|
>
|
||||||
<FormLabel htmlFor={`${id}-v-unlimited`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<FormLabel htmlFor={`${id}-v-unlimited`} className="px-3 h-10 flex-1 border rounded-md flex items-center text-sm">
|
||||||
<RadioGroupItem value="unlimited" id={`${id}-v-unlimited`} className="mr-2"/>
|
<RadioGroupItem value="unlimited" id={`${id}-v-unlimited`} className="mr-2"/>
|
||||||
<span>不限地区</span>
|
<span>不限地区</span>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormLabel htmlFor={`${id}-v-specific`} className="px-3 h-10 border rounded-md flex items-center w-40 text-sm">
|
<FormLabel htmlFor={`${id}-v-specific`} className="px-3 h-10 flex-1 border rounded-md flex items-center text-sm">
|
||||||
<RadioGroupItem value="specific" id={`${id}-v-specific`} className="mr-2"/>
|
<RadioGroupItem value="specific" id={`${id}-v-specific`} className="mr-2"/>
|
||||||
<span>指定地区</span>
|
<span>指定地区</span>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
@@ -456,7 +460,6 @@ function SelectRegion() {
|
|||||||
|
|
||||||
{regionType === 'specific' && (
|
{regionType === 'specific' && (
|
||||||
<Combobox
|
<Combobox
|
||||||
className="w-84"
|
|
||||||
placeholder="请选择地区"
|
placeholder="请选择地区"
|
||||||
options={cities.options}
|
options={cities.options}
|
||||||
value={[prov || '', city || '']}
|
value={[prov || '', city || '']}
|
||||||
@@ -531,11 +534,13 @@ function ApplyLink() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={merge(
|
<div className={merge(
|
||||||
`flex flex-col gap-4 sticky bottom-0 bg-muted p-4`,
|
`flex flex-col gap-4`,
|
||||||
`rounded-lg`,
|
`rounded-lg`,
|
||||||
)}>
|
)}>
|
||||||
|
<h4>API 链接</h4>
|
||||||
|
|
||||||
{/* 展示链接地址 */}
|
{/* 展示链接地址 */}
|
||||||
<div className="bg-neutral-900 text-white p-4 rounded-md break-all">
|
<div className="bg-secondary p-4 rounded-md break-all">
|
||||||
{link(values)}
|
{link(values)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
0
src/components/composites/purchase/form.tsx
Normal file
0
src/components/composites/purchase/form.tsx
Normal file
@@ -9,13 +9,14 @@ import Image from 'next/image'
|
|||||||
import check from '@/components/composites/purchase/_assets/check.svg'
|
import check from '@/components/composites/purchase/_assets/check.svg'
|
||||||
import {Schema} from '@/components/composites/purchase/long/form'
|
import {Schema} from '@/components/composites/purchase/long/form'
|
||||||
import {useFormContext} from 'react-hook-form'
|
import {useFormContext} from 'react-hook-form'
|
||||||
|
import {Card} from '@/components/ui/card'
|
||||||
|
|
||||||
export default function Center() {
|
export default function Center() {
|
||||||
const form = useFormContext<Schema>()
|
const form = useFormContext<Schema>()
|
||||||
const type = form.watch('type')
|
const type = form.watch('type')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex-auto p-8 flex flex-col gap-8 relative">
|
<Card className="flex-auto p-6 flex flex-col gap-6 relative">
|
||||||
|
|
||||||
{/* 计费方式 */}
|
{/* 计费方式 */}
|
||||||
<FormField
|
<FormField
|
||||||
@@ -27,7 +28,7 @@ export default function Center() {
|
|||||||
id={id}
|
id={id}
|
||||||
defaultValue={field.value}
|
defaultValue={field.value}
|
||||||
onValueChange={field.onChange}
|
onValueChange={field.onChange}
|
||||||
className="flex gap-4">
|
className="flex gap-4 max-md:flex-col">
|
||||||
|
|
||||||
<FormOption
|
<FormOption
|
||||||
id={`${id}-2`}
|
id={`${id}-2`}
|
||||||
@@ -166,7 +167,7 @@ export default function Center() {
|
|||||||
{/* 产品特性 */}
|
{/* 产品特性 */}
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<h3>产品特性</h3>
|
<h3>产品特性</h3>
|
||||||
<div className="grid grid-cols-3 auto-rows-fr gap-y-6">
|
<div className="grid grid-cols-2 md:grid-cols-3 auto-rows-fr gap-4 gap-y-6">
|
||||||
<p className="flex gap-2 items-center">
|
<p className="flex gap-2 items-center">
|
||||||
<Image src={check} alt="check" aria-hidden className="w-4 h-4"/>
|
<Image src={check} alt="check" aria-hidden className="w-4 h-4"/>
|
||||||
<span className="text-sm text-gray-500">支持高并发提取</span>
|
<span className="text-sm text-gray-500">支持高并发提取</span>
|
||||||
@@ -205,6 +206,6 @@ export default function Center() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export default function LongForm() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form form={form} className="bg-white rounded-lg flex flex-row">
|
<Form form={form} className="flex flex-col lg:flex-row gap-4">
|
||||||
<LongFormContext.Provider value={{form}}>
|
<LongFormContext.Provider value={{form}}>
|
||||||
<Center/>
|
<Center/>
|
||||||
<Right/>
|
<Right/>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import Link from 'next/link'
|
|||||||
import {merge} from '@/lib/utils'
|
import {merge} from '@/lib/utils'
|
||||||
import {useFormContext} from 'react-hook-form'
|
import {useFormContext} from 'react-hook-form'
|
||||||
import {Schema} from '@/components/composites/purchase/long/form'
|
import {Schema} from '@/components/composites/purchase/long/form'
|
||||||
|
import {Card} from '@/components/ui/card'
|
||||||
|
|
||||||
export default function Right() {
|
export default function Right() {
|
||||||
const profile = useProfileStore(store => store.profile)
|
const profile = useProfileStore(store => store.profile)
|
||||||
@@ -44,9 +45,8 @@ export default function Right() {
|
|||||||
}, [dailyLimit, expire, live, quota, mode])
|
}, [dailyLimit, expire, live, quota, mode])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={merge(
|
<Card className={merge(
|
||||||
`flex-none basis-90 p-6 flex flex-col gap-6 relative`,
|
`flex-none basis-90 p-6 flex flex-col gap-6 relative`,
|
||||||
`after:absolute after:inset-0 after:my-6 after:border-l after:border-gray-200 after:select-none after:pointer-events-none`,
|
|
||||||
)}>
|
)}>
|
||||||
<h3>订单详情</h3>
|
<h3>订单详情</h3>
|
||||||
<ul className="flex flex-col gap-3">
|
<ul className="flex flex-col gap-3">
|
||||||
@@ -166,6 +166,6 @@ export default function Right() {
|
|||||||
登录后支付
|
登录后支付
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</div>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,14 @@ import Image from 'next/image'
|
|||||||
import check from '@/components/composites/purchase/_assets/check.svg'
|
import check from '@/components/composites/purchase/_assets/check.svg'
|
||||||
import {useFormContext} from 'react-hook-form'
|
import {useFormContext} from 'react-hook-form'
|
||||||
import {Schema} from '@/components/composites/purchase/short/form'
|
import {Schema} from '@/components/composites/purchase/short/form'
|
||||||
|
import {Card} from '@/components/ui/card'
|
||||||
|
|
||||||
export default function Center() {
|
export default function Center() {
|
||||||
const form = useFormContext<Schema>()
|
const form = useFormContext<Schema>()
|
||||||
const type = form.watch('type')
|
const type = form.watch('type')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex-auto p-8 flex flex-col gap-8 relative">
|
<Card className="flex-auto p-6 flex flex-col gap-6 relative">
|
||||||
|
|
||||||
{/* 计费方式 */}
|
{/* 计费方式 */}
|
||||||
<FormField<Schema, 'type'>
|
<FormField<Schema, 'type'>
|
||||||
@@ -27,7 +28,7 @@ export default function Center() {
|
|||||||
id={id}
|
id={id}
|
||||||
defaultValue={field.value}
|
defaultValue={field.value}
|
||||||
onValueChange={field.onChange}
|
onValueChange={field.onChange}
|
||||||
className="flex gap-4">
|
className="flex gap-4 max-md:flex-col">
|
||||||
|
|
||||||
<FormOption
|
<FormOption
|
||||||
id={`${id}-2`}
|
id={`${id}-2`}
|
||||||
@@ -166,7 +167,7 @@ export default function Center() {
|
|||||||
{/* 产品特性 */}
|
{/* 产品特性 */}
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<h3>产品特性</h3>
|
<h3>产品特性</h3>
|
||||||
<div className="grid grid-cols-3 auto-rows-fr gap-y-6">
|
<div className="grid grid-cols-2 md:grid-cols-3 auto-rows-fr gap-4 md:gap-y-6">
|
||||||
<p className="flex gap-2 items-center">
|
<p className="flex gap-2 items-center">
|
||||||
<Image src={check} alt="check" aria-hidden className="w-4 h-4"/>
|
<Image src={check} alt="check" aria-hidden className="w-4 h-4"/>
|
||||||
<span className="text-sm text-gray-500">支持高并发提取</span>
|
<span className="text-sm text-gray-500">支持高并发提取</span>
|
||||||
@@ -205,6 +206,6 @@ export default function Center() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export default function PurchaseForm(props: PurchaseFormProps) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form form={form} className="bg-white rounded-lg flex flex-row">
|
<Form form={form} className="flex flex-col lg:flex-row gap-4">
|
||||||
<Center/>
|
<Center/>
|
||||||
<Right/>
|
<Right/>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import Link from 'next/link'
|
|||||||
import {merge} from '@/lib/utils'
|
import {merge} from '@/lib/utils'
|
||||||
import Pay from '@/components/composites/purchase/pay'
|
import Pay from '@/components/composites/purchase/pay'
|
||||||
import {useFormContext} from 'react-hook-form'
|
import {useFormContext} from 'react-hook-form'
|
||||||
|
import {Card} from '@/components/ui/card'
|
||||||
|
|
||||||
export default function Right() {
|
export default function Right() {
|
||||||
const profile = useProfileStore(store => store.profile)
|
const profile = useProfileStore(store => store.profile)
|
||||||
@@ -55,9 +56,8 @@ export default function Right() {
|
|||||||
}, [dailyLimit, expire, live, quota, mode])
|
}, [dailyLimit, expire, live, quota, mode])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={merge(
|
<Card className={merge(
|
||||||
`flex-none basis-90 p-6 flex flex-col gap-6 relative`,
|
`flex-none basis-90 p-6 flex flex-col gap-6 relative`,
|
||||||
`after:absolute after:inset-0 after:my-6 after:border-l after:border-gray-200 after:select-none after:pointer-events-none`,
|
|
||||||
)}>
|
)}>
|
||||||
<h3>订单详情</h3>
|
<h3>订单详情</h3>
|
||||||
<ul className="flex flex-col gap-3">
|
<ul className="flex flex-col gap-3">
|
||||||
@@ -177,6 +177,6 @@ export default function Right() {
|
|||||||
登录后支付
|
登录后支付
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</div>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
68
src/components/docs/extract.mdx
Normal file
68
src/components/docs/extract.mdx
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# 提取代理接口文档
|
||||||
|
|
||||||
|
## 请求方式
|
||||||
|
|
||||||
|
`GET https://lanhuip.com/api/extract`
|
||||||
|
|
||||||
|
## 请求参数
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 描述 |
|
||||||
|
|--------|----------|------|----------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| i | number | 是 | 用于提取的套餐 ID |
|
||||||
|
| t | number | 是 | 认证类型:1 - 白名单,2 - 密码 |
|
||||||
|
| a | string | 否 | 归属地省份。默认全局随机 |
|
||||||
|
| b | string | 否 | 归属地城市。默认全局随机 |
|
||||||
|
| s | string | 否 | 归属地运营商。默认全局随机 |
|
||||||
|
| d | string | 否 | 是否去重:1 - 是,0 - 否。默认为是 |
|
||||||
|
| rt | string | 否 | 返回类型:1 - TXT,2 - JSON。默认 TXT |
|
||||||
|
| rs | number[] | 否 | 返回时要使用的分隔符,值为该字符的 ascii 编码,可以有多个字符,多个字符用半角逗号连接。默认为 13,10,即回车 + 换行(\r\n) |
|
||||||
|
| rb | number[] | 否 | 返回时要使用的换行符,值为该字符的 ascii 编码,可以有多个字符,多个字符用半角逗号连接。默认为 124,即垂直线( \| ) |
|
||||||
|
| n | number | 否 | 提取数量。默认为 1 |
|
||||||
|
|
||||||
|
## 响应参数
|
||||||
|
|
||||||
|
如果请求参数中返回类型为 TXT,则响应为纯文本格式,内容为提取的代理列表,每个代理信息占一行。
|
||||||
|
|
||||||
|
如果请求参数中返回类型为 JSON,则响应为 JSON 格式,内容为提取的代理列表,每个代理信息为一个对象,包含以下字段:
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 描述 |
|
||||||
|
|----------|--------|--------------------------------------------- |
|
||||||
|
| host | string | 代理服务器地址 |
|
||||||
|
| port | number | 代理服务器端口 |
|
||||||
|
| username | string | 代理服务器用户名(仅在认证类型为密码时返回) |
|
||||||
|
| password | string | 代理服务器密码(仅在认证类型为密码时返回) |
|
||||||
|
|
||||||
|
|
||||||
|
## 示例
|
||||||
|
|
||||||
|
### 请求示例
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET https://lanhuip.com/api/extract?i=1&t=2&a=广东省&b=广州市&s=移动&d=1&rt=2&n=3
|
||||||
|
```
|
||||||
|
|
||||||
|
### 响应示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"host": "fwd1.lanhuip.com",
|
||||||
|
"port": 20000,
|
||||||
|
"username": "user1",
|
||||||
|
"password": "pass1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"host": "fwd1.lanhuip.com",
|
||||||
|
"port": 20001,
|
||||||
|
"username": "user2",
|
||||||
|
"password": "pass2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"host": "fwd1.lanhuip.com",
|
||||||
|
"port": 20002,
|
||||||
|
"username": "user3",
|
||||||
|
"password": "pass3"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
@@ -2,6 +2,12 @@ import {Button} from '@/components/ui/button';
|
|||||||
|
|
||||||
# qweqwe
|
# qweqwe
|
||||||
|
|
||||||
|
`dasdasd`
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
console.log('Hello, world!');
|
||||||
|
```
|
||||||
|
|
||||||
## awdasdasd
|
## awdasdasd
|
||||||
|
|
||||||
### zxczxczxc
|
### zxczxczxc
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import {merge} from '@/lib/utils'
|
|||||||
|
|
||||||
export default function Markdown(props: React.ComponentProps<'div'>) {
|
export default function Markdown(props: React.ComponentProps<'div'>) {
|
||||||
return (
|
return (
|
||||||
<div
|
<article
|
||||||
{...props}
|
{...props}
|
||||||
className={merge(
|
className={merge(
|
||||||
`prose`,
|
`prose max-w-none`,
|
||||||
props.className,
|
props.className,
|
||||||
)}>
|
)}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</article>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ export function Combobox(props: ComboboxProps) {
|
|||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent
|
<PopoverContent
|
||||||
className="p-0 rounded-lg h-[var(--radix-popover-content-available-height)] flex flex-col overflow-hidden"
|
className="p-0 rounded-lg w-[var(--radix-popover-trigger-width)] h-[var(--radix-popover-content-available-height)] flex flex-col overflow-hidden"
|
||||||
align="start"
|
align="start"
|
||||||
collisionPadding={6}
|
collisionPadding={6}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ function FormField<
|
|||||||
name={props.name}
|
name={props.name}
|
||||||
control={form.control}
|
control={form.control}
|
||||||
render={({field, fieldState, formState}) => (
|
render={({field, fieldState, formState}) => (
|
||||||
<div data-slot="form-field" className={merge('grid gap-2', props.className)}>
|
<div data-slot="form-field" className={merge('flex flex-col gap-2', props.className)}>
|
||||||
|
|
||||||
{/* label */}
|
{/* label */}
|
||||||
{!!props.label
|
{!!props.label
|
||||||
|
|||||||
28
src/components/ui/separator.tsx
Normal file
28
src/components/ui/separator.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import * as React from 'react'
|
||||||
|
import * as SeparatorPrimitive from '@radix-ui/react-separator'
|
||||||
|
|
||||||
|
import {merge} from '@/lib/utils'
|
||||||
|
|
||||||
|
function Separator({
|
||||||
|
className,
|
||||||
|
orientation = 'horizontal',
|
||||||
|
decorative = true,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
|
||||||
|
return (
|
||||||
|
<SeparatorPrimitive.Root
|
||||||
|
data-slot="separator"
|
||||||
|
decorative={decorative}
|
||||||
|
orientation={orientation}
|
||||||
|
className={merge(
|
||||||
|
'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {Separator}
|
||||||
Reference in New Issue
Block a user