feat: add preview and change edit and flow

This commit is contained in:
xion 2024-09-18 23:11:13 +08:00
parent b838488776
commit 052dd919cd
13 changed files with 755 additions and 58 deletions

View File

@ -12,7 +12,8 @@
"deploy": "rsync -avz --delete ./dist/ light:/root/apps/envision/web" "deploy": "rsync -avz --delete ./dist/ light:/root/apps/envision/web"
}, },
"dependencies": { "dependencies": {
"@abearxiong/flows": "0.0.1-alpha.6", "@abearxiong/container": "0.0.1-alpha.0",
"@abearxiong/flows": "0.0.1-alpha.8",
"@abearxiong/ui": "0.0.1-alpha.0", "@abearxiong/ui": "0.0.1-alpha.0",
"@ant-design/icons": "^5.4.0", "@ant-design/icons": "^5.4.0",
"@icon-park/react": "^1.4.2", "@icon-park/react": "^1.4.2",
@ -22,6 +23,7 @@
"antd": "^5.20.6", "antd": "^5.20.6",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"copy-to-clipboard": "^3.3.3",
"immer": "^10.1.1", "immer": "^10.1.1",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"nanoid": "^5.0.7", "nanoid": "^5.0.7",
@ -30,6 +32,7 @@
"react-router": "^6.26.2", "react-router": "^6.26.2",
"react-router-dom": "^6.26.2", "react-router-dom": "^6.26.2",
"react-toastify": "^10.0.5", "react-toastify": "^10.0.5",
"vite-plugin-tsconfig-paths": "^1.4.1",
"zustand": "^4.5.5" "zustand": "^4.5.5"
}, },
"devDependencies": { "devDependencies": {

228
pnpm-lock.yaml generated
View File

@ -8,9 +8,12 @@ importers:
.: .:
dependencies: dependencies:
'@abearxiong/container':
specifier: 0.0.1-alpha.0
version: 0.0.1-alpha.0
'@abearxiong/flows': '@abearxiong/flows':
specifier: 0.0.1-alpha.6 specifier: 0.0.1-alpha.8
version: 0.0.1-alpha.6(@xyflow/react@12.3.0(@types/react@18.3.7)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(zustand@4.5.5(@types/react@18.3.7)(immer@10.1.1)(react@18.3.1)) version: 0.0.1-alpha.8(@xyflow/react@12.3.0(@types/react@18.3.7)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(zustand@4.5.5(@types/react@18.3.7)(immer@10.1.1)(react@18.3.1))
'@abearxiong/ui': '@abearxiong/ui':
specifier: 0.0.1-alpha.0 specifier: 0.0.1-alpha.0
version: 0.0.1-alpha.0 version: 0.0.1-alpha.0
@ -38,6 +41,9 @@ importers:
clsx: clsx:
specifier: ^2.1.1 specifier: ^2.1.1
version: 2.1.1 version: 2.1.1
copy-to-clipboard:
specifier: ^3.3.3
version: 3.3.3
immer: immer:
specifier: ^10.1.1 specifier: ^10.1.1
version: 10.1.1 version: 10.1.1
@ -62,6 +68,9 @@ importers:
react-toastify: react-toastify:
specifier: ^10.0.5 specifier: ^10.0.5
version: 10.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) version: 10.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
vite-plugin-tsconfig-paths:
specifier: ^1.4.1
version: 1.4.1(typescript@5.6.2)(vite@5.4.6(@types/node@22.5.5))
zustand: zustand:
specifier: ^4.5.5 specifier: ^4.5.5
version: 4.5.5(@types/react@18.3.7)(immer@10.1.1)(react@18.3.1) version: 4.5.5(@types/react@18.3.7)(immer@10.1.1)(react@18.3.1)
@ -126,8 +135,11 @@ importers:
packages: packages:
'@abearxiong/flows@0.0.1-alpha.6': '@abearxiong/container@0.0.1-alpha.0':
resolution: {integrity: sha512-CV9U4WZBpebsK00s0LrdOj4QoUa3BgUqiA+UhWPSRxEqtp+r5Vgo2/7MDeoKLyhZ8YQZ7fMcGQl4w0zcWKKG3Q==, tarball: https://npm.pkg.github.com/download/@abearxiong/flows/0.0.1-alpha.6/a1af0defd5b351d7316f800201d222472a763369} resolution: {integrity: sha512-k0IccMq4Q05eSYsZOMGjOX4fs824JmXngnt6V3wZ01+0xGzvodmYe5ooEnb1TqUz3hWPFMOoPUCQbMsg00LHAA==, tarball: https://npm.pkg.github.com/download/@abearxiong/container/0.0.1-alpha.0/41c8dc7d007947465f35b91e78b74fc773c63e27}
'@abearxiong/flows@0.0.1-alpha.8':
resolution: {integrity: sha512-QLTH2gWw2HewLh8veK0ojmnhosgAOfs/Or9SlAMfNkOAYd2IypVebxAXEuYALrqDBalA1CLCi/f3IjaANS+tXg==, tarball: https://npm.pkg.github.com/download/@abearxiong/flows/0.0.1-alpha.8/3d86a1d0261cf3f810ab1a5633b74ecb5aadebf4}
peerDependencies: peerDependencies:
'@xyflow/react': ^12.3.0 '@xyflow/react': ^12.3.0
immer: ^10.1.1 immer: ^10.1.1
@ -274,12 +286,42 @@ packages:
resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
engines: {node: '>=10'} engines: {node: '>=10'}
'@emotion/babel-plugin@11.12.0':
resolution: {integrity: sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==}
'@emotion/cache@11.13.1':
resolution: {integrity: sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==}
'@emotion/css@11.13.0':
resolution: {integrity: sha512-BUk99ylT+YHl+W/HN7nv1RCTkDYmKKqa1qbvM/qLSQEg61gipuBF5Hptk/2/ERmX2DCv0ccuFGhz9i0KSZOqPg==}
'@emotion/hash@0.8.0': '@emotion/hash@0.8.0':
resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==}
'@emotion/hash@0.9.2':
resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==}
'@emotion/memoize@0.9.0':
resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==}
'@emotion/serialize@1.3.1':
resolution: {integrity: sha512-dEPNKzBPU+vFPGa+z3axPRn8XVDetYORmDC0wAiej+TNcOZE70ZMJa0X7JdeoM6q/nWTMZeLpN/fTnD9o8MQBA==}
'@emotion/sheet@1.4.0':
resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==}
'@emotion/unitless@0.10.0':
resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==}
'@emotion/unitless@0.7.5': '@emotion/unitless@0.7.5':
resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==}
'@emotion/utils@1.4.0':
resolution: {integrity: sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==}
'@emotion/weak-memoize@0.4.0':
resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==}
'@esbuild/aix-ppc64@0.21.5': '@esbuild/aix-ppc64@0.21.5':
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -716,6 +758,9 @@ packages:
'@types/node@22.5.5': '@types/node@22.5.5':
resolution: {integrity: sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==} resolution: {integrity: sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==}
'@types/parse-json@4.0.2':
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
'@types/prismjs@1.26.4': '@types/prismjs@1.26.4':
resolution: {integrity: sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg==} resolution: {integrity: sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg==}
@ -878,6 +923,10 @@ packages:
peerDependencies: peerDependencies:
postcss: ^8.1.0 postcss: ^8.1.0
babel-plugin-macros@3.1.0:
resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==}
engines: {node: '>=10', npm: '>=6'}
bail@2.0.2: bail@2.0.2:
resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
@ -977,16 +1026,26 @@ packages:
concat-map@0.0.1: concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
convert-source-map@1.9.0:
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
convert-source-map@2.0.0: convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
copy-to-clipboard@3.3.3: copy-to-clipboard@3.3.3:
resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==}
cosmiconfig@7.1.0:
resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==}
engines: {node: '>=10'}
cross-spawn@7.0.3: cross-spawn@7.0.3:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
crypto-js@4.2.0:
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
cssesc@3.0.0: cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -1080,6 +1139,9 @@ packages:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'} engines: {node: '>=0.12'}
error-ex@1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
esbuild@0.21.5: esbuild@0.21.5:
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -1180,6 +1242,9 @@ packages:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'} engines: {node: '>=8'}
find-root@1.1.0:
resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==}
find-up@5.0.0: find-up@5.0.0:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -1303,6 +1368,9 @@ packages:
is-alphanumerical@2.0.1: is-alphanumerical@2.0.1:
resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
is-arrayish@0.2.1:
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
is-binary-path@2.1.0: is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -1370,6 +1438,9 @@ packages:
json-buffer@3.0.1: json-buffer@3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
json-parse-even-better-errors@2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
json-schema-traverse@0.4.1: json-schema-traverse@0.4.1:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
@ -1525,6 +1596,10 @@ packages:
parse-entities@4.0.1: parse-entities@4.0.1:
resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==}
parse-json@5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
parse-numeric-range@1.3.0: parse-numeric-range@1.3.0:
resolution: {integrity: sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==} resolution: {integrity: sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==}
@ -1549,6 +1624,10 @@ packages:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'} engines: {node: '>=16 || 14 >=14.18'}
path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
picocolors@1.1.0: picocolors@1.1.0:
resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==}
@ -1974,6 +2053,10 @@ packages:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
source-map@0.5.7:
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
engines: {node: '>=0.10.0'}
space-separated-tokens@2.0.2: space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
@ -2003,6 +2086,9 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'} engines: {node: '>=8'}
stylis@4.2.0:
resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==}
stylis@4.3.4: stylis@4.3.4:
resolution: {integrity: sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==} resolution: {integrity: sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==}
@ -2089,6 +2175,11 @@ packages:
typescript: typescript:
optional: true optional: true
typescript-paths@1.5.1:
resolution: {integrity: sha512-lYErSLCON2MSplVV5V/LBgD4UNjMgY3guATdFCZY2q1Nr6OZEu4q6zX/rYMsG1TaWqqQSszg6C9EU7AGWMDrIw==}
peerDependencies:
typescript: ^4.7.2 || ^5
typescript@5.6.2: typescript@5.6.2:
resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==}
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
@ -2168,6 +2259,11 @@ packages:
vfile@6.0.3: vfile@6.0.3:
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
vite-plugin-tsconfig-paths@1.4.1:
resolution: {integrity: sha512-pGpvsPGDpiM5z7I9ZhBe7H2WAH0gAC2Lh55rM3pE+84V2q7qojNO28wdUl4i/M4XUfJcilhyucmbc9D7IKqpXA==}
peerDependencies:
vite: '*'
vite@5.4.6: vite@5.4.6:
resolution: {integrity: sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==} resolution: {integrity: sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==}
engines: {node: ^18.0.0 || >=20.0.0} engines: {node: ^18.0.0 || >=20.0.0}
@ -2222,6 +2318,10 @@ packages:
yallist@3.1.1: yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
yaml@1.10.2:
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
engines: {node: '>= 6'}
yaml@2.5.1: yaml@2.5.1:
resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==}
engines: {node: '>= 14'} engines: {node: '>= 14'}
@ -2251,7 +2351,15 @@ packages:
snapshots: snapshots:
'@abearxiong/flows@0.0.1-alpha.6(@xyflow/react@12.3.0(@types/react@18.3.7)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(zustand@4.5.5(@types/react@18.3.7)(immer@10.1.1)(react@18.3.1))': '@abearxiong/container@0.0.1-alpha.0':
dependencies:
'@emotion/css': 11.13.0
crypto-js: 4.2.0
eventemitter3: 5.0.1
transitivePeerDependencies:
- supports-color
'@abearxiong/flows@0.0.1-alpha.8(@xyflow/react@12.3.0(@types/react@18.3.7)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(zustand@4.5.5(@types/react@18.3.7)(immer@10.1.1)(react@18.3.1))':
dependencies: dependencies:
'@ant-design/icons': 5.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@ant-design/icons': 5.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@icon-park/react': 1.4.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@icon-park/react': 1.4.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -2453,10 +2561,64 @@ snapshots:
'@ctrl/tinycolor@3.6.1': {} '@ctrl/tinycolor@3.6.1': {}
'@emotion/babel-plugin@11.12.0':
dependencies:
'@babel/helper-module-imports': 7.24.7
'@babel/runtime': 7.25.6
'@emotion/hash': 0.9.2
'@emotion/memoize': 0.9.0
'@emotion/serialize': 1.3.1
babel-plugin-macros: 3.1.0
convert-source-map: 1.9.0
escape-string-regexp: 4.0.0
find-root: 1.1.0
source-map: 0.5.7
stylis: 4.2.0
transitivePeerDependencies:
- supports-color
'@emotion/cache@11.13.1':
dependencies:
'@emotion/memoize': 0.9.0
'@emotion/sheet': 1.4.0
'@emotion/utils': 1.4.0
'@emotion/weak-memoize': 0.4.0
stylis: 4.2.0
'@emotion/css@11.13.0':
dependencies:
'@emotion/babel-plugin': 11.12.0
'@emotion/cache': 11.13.1
'@emotion/serialize': 1.3.1
'@emotion/sheet': 1.4.0
'@emotion/utils': 1.4.0
transitivePeerDependencies:
- supports-color
'@emotion/hash@0.8.0': {} '@emotion/hash@0.8.0': {}
'@emotion/hash@0.9.2': {}
'@emotion/memoize@0.9.0': {}
'@emotion/serialize@1.3.1':
dependencies:
'@emotion/hash': 0.9.2
'@emotion/memoize': 0.9.0
'@emotion/unitless': 0.10.0
'@emotion/utils': 1.4.0
csstype: 3.1.3
'@emotion/sheet@1.4.0': {}
'@emotion/unitless@0.10.0': {}
'@emotion/unitless@0.7.5': {} '@emotion/unitless@0.7.5': {}
'@emotion/utils@1.4.0': {}
'@emotion/weak-memoize@0.4.0': {}
'@esbuild/aix-ppc64@0.21.5': '@esbuild/aix-ppc64@0.21.5':
optional: true optional: true
@ -2817,6 +2979,8 @@ snapshots:
dependencies: dependencies:
undici-types: 6.19.8 undici-types: 6.19.8
'@types/parse-json@4.0.2': {}
'@types/prismjs@1.26.4': {} '@types/prismjs@1.26.4': {}
'@types/prop-types@15.7.12': {} '@types/prop-types@15.7.12': {}
@ -3065,6 +3229,12 @@ snapshots:
postcss: 8.4.45 postcss: 8.4.45
postcss-value-parser: 4.2.0 postcss-value-parser: 4.2.0
babel-plugin-macros@3.1.0:
dependencies:
'@babel/runtime': 7.25.6
cosmiconfig: 7.1.0
resolve: 1.22.8
bail@2.0.2: {} bail@2.0.2: {}
balanced-match@1.0.2: {} balanced-match@1.0.2: {}
@ -3156,18 +3326,30 @@ snapshots:
concat-map@0.0.1: {} concat-map@0.0.1: {}
convert-source-map@1.9.0: {}
convert-source-map@2.0.0: {} convert-source-map@2.0.0: {}
copy-to-clipboard@3.3.3: copy-to-clipboard@3.3.3:
dependencies: dependencies:
toggle-selection: 1.0.6 toggle-selection: 1.0.6
cosmiconfig@7.1.0:
dependencies:
'@types/parse-json': 4.0.2
import-fresh: 3.3.0
parse-json: 5.2.0
path-type: 4.0.0
yaml: 1.10.2
cross-spawn@7.0.3: cross-spawn@7.0.3:
dependencies: dependencies:
path-key: 3.1.1 path-key: 3.1.1
shebang-command: 2.0.0 shebang-command: 2.0.0
which: 2.0.2 which: 2.0.2
crypto-js@4.2.0: {}
cssesc@3.0.0: {} cssesc@3.0.0: {}
csstype@3.1.3: {} csstype@3.1.3: {}
@ -3240,6 +3422,10 @@ snapshots:
entities@4.5.0: {} entities@4.5.0: {}
error-ex@1.3.2:
dependencies:
is-arrayish: 0.2.1
esbuild@0.21.5: esbuild@0.21.5:
optionalDependencies: optionalDependencies:
'@esbuild/aix-ppc64': 0.21.5 '@esbuild/aix-ppc64': 0.21.5
@ -3378,6 +3564,8 @@ snapshots:
dependencies: dependencies:
to-regex-range: 5.0.1 to-regex-range: 5.0.1
find-root@1.1.0: {}
find-up@5.0.0: find-up@5.0.0:
dependencies: dependencies:
locate-path: 6.0.0 locate-path: 6.0.0
@ -3533,6 +3721,8 @@ snapshots:
is-alphabetical: 2.0.1 is-alphabetical: 2.0.1
is-decimal: 2.0.1 is-decimal: 2.0.1
is-arrayish@0.2.1: {}
is-binary-path@2.1.0: is-binary-path@2.1.0:
dependencies: dependencies:
binary-extensions: 2.3.0 binary-extensions: 2.3.0
@ -3581,6 +3771,8 @@ snapshots:
json-buffer@3.0.1: {} json-buffer@3.0.1: {}
json-parse-even-better-errors@2.3.1: {}
json-schema-traverse@0.4.1: {} json-schema-traverse@0.4.1: {}
json-stable-stringify-without-jsonify@1.0.1: {} json-stable-stringify-without-jsonify@1.0.1: {}
@ -3732,6 +3924,13 @@ snapshots:
is-decimal: 2.0.1 is-decimal: 2.0.1
is-hexadecimal: 2.0.1 is-hexadecimal: 2.0.1
parse-json@5.2.0:
dependencies:
'@babel/code-frame': 7.24.7
error-ex: 1.3.2
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
parse-numeric-range@1.3.0: {} parse-numeric-range@1.3.0: {}
parse5@6.0.1: {} parse5@6.0.1: {}
@ -3751,6 +3950,8 @@ snapshots:
lru-cache: 10.4.3 lru-cache: 10.4.3
minipass: 7.1.2 minipass: 7.1.2
path-type@4.0.0: {}
picocolors@1.1.0: {} picocolors@1.1.0: {}
picomatch@2.3.1: {} picomatch@2.3.1: {}
@ -4279,6 +4480,8 @@ snapshots:
source-map-js@1.2.1: {} source-map-js@1.2.1: {}
source-map@0.5.7: {}
space-separated-tokens@2.0.2: {} space-separated-tokens@2.0.2: {}
string-convert@0.2.1: {} string-convert@0.2.1: {}
@ -4310,6 +4513,8 @@ snapshots:
strip-json-comments@3.1.1: {} strip-json-comments@3.1.1: {}
stylis@4.2.0: {}
stylis@4.3.4: {} stylis@4.3.4: {}
sucrase@3.35.0: sucrase@3.35.0:
@ -4410,6 +4615,10 @@ snapshots:
- eslint - eslint
- supports-color - supports-color
typescript-paths@1.5.1(typescript@5.6.2):
dependencies:
typescript: 5.6.2
typescript@5.6.2: {} typescript@5.6.2: {}
undici-types@6.19.8: {} undici-types@6.19.8: {}
@ -4530,6 +4739,13 @@ snapshots:
'@types/unist': 3.0.3 '@types/unist': 3.0.3
vfile-message: 4.0.2 vfile-message: 4.0.2
vite-plugin-tsconfig-paths@1.4.1(typescript@5.6.2)(vite@5.4.6(@types/node@22.5.5)):
dependencies:
typescript-paths: 1.5.1(typescript@5.6.2)
vite: 5.4.6(@types/node@22.5.5)
transitivePeerDependencies:
- typescript
vite@5.4.6(@types/node@22.5.5): vite@5.4.6(@types/node@22.5.5):
dependencies: dependencies:
esbuild: 0.21.5 esbuild: 0.21.5
@ -4561,6 +4777,8 @@ snapshots:
yallist@3.1.1: {} yallist@3.1.1: {}
yaml@1.10.2: {}
yaml@2.5.1: {} yaml@2.5.1: {}
yocto-queue@0.1.0: {} yocto-queue@0.1.0: {}

View File

@ -4,7 +4,8 @@ import { TextArea } from '../components/TextArea';
import { useContainerStore } from '../store'; import { useContainerStore } from '../store';
import { useShallow } from 'zustand/react/shallow'; import { useShallow } from 'zustand/react/shallow';
import { Form } from 'antd'; import { Form } from 'antd';
import copy from 'copy-to-clipboard';
import { useNavigate } from 'react-router';
const FormModal = () => { const FormModal = () => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const containerStore = useContainerStore( const containerStore = useContainerStore(
@ -73,6 +74,7 @@ const FormModal = () => {
); );
}; };
export const ContainerList = () => { export const ContainerList = () => {
const navicate = useNavigate();
const containerStore = useContainerStore( const containerStore = useContainerStore(
useShallow((state) => { useShallow((state) => {
return { return {
@ -90,10 +92,23 @@ export const ContainerList = () => {
}, []); }, []);
const columns = [ const columns = [
// { {
// title: 'ID', title: 'ID',
// dataIndex: 'id', dataIndex: 'id',
// }, render: (text: string) => {
return (
<div
className='w-40 truncate cursor-pointer'
title={text}
onClick={() => {
copy(text);
message.success('copy success');
}}>
{text}
</div>
);
},
},
{ {
title: 'Title', title: 'Title',
dataIndex: 'title', dataIndex: 'title',
@ -124,6 +139,12 @@ export const ContainerList = () => {
}}> }}>
Edit Edit
</Button> </Button>
<Button
onClick={() => {
navicate('/container/preview/' + record.id);
}}>
Preview
</Button>
<Button <Button
danger danger
onClick={() => { onClick={() => {

View File

@ -1,13 +1,15 @@
import { Navigate, Route, Routes } from 'react-router-dom'; import { Navigate, Route, Routes } from 'react-router-dom';
import { ContainerList } from './edit/List'; import { ContainerList } from './edit/List';
import { Main } from './layouts'; import { Main } from './layouts';
import { Preview } from './preview';
export const App = () => { export const App = () => {
return ( return (
<Routes> <Routes>
<Route element={<Main />}> <Route element={<Main />}>
<Route path='/' element={<Navigate to='/container/edit/list' />}></Route> <Route path='/' element={<Navigate to='/container/edit/list' />}></Route>
<Route path='edit/list' element={<ContainerList />} /> <Route path='edit/list' element={<ContainerList />} />
<Route path='preview/:id' element={<Preview />} />
<Route path='/' element={<div>Home</div>} /> <Route path='/' element={<div>Home</div>} />
</Route> </Route>
</Routes> </Routes>

View File

@ -0,0 +1,61 @@
import { Container } from '@abearxiong/container';
import { useEffect, useRef, useState } from 'react';
import { useParams } from 'react-router';
import { query } from '@/modules';
import { message } from 'antd';
export const Preview = () => {
const params = useParams<{ id: string }>();
const id = params.id;
const ref = useRef<HTMLDivElement>(null);
const containerRef = useRef<any>(null);
const [data, setData] = useState<any>({});
useEffect(() => {
if (!id) return;
fetch();
}, []);
const fetch = async () => {
const res = await query.post({
path: 'container',
key: 'get',
id,
});
if (res.code === 200) {
const data = res.data;
// setData([data]);
console.log('data', data);
const code = {
id: data.id,
title: data.title,
code: data.code,
data: data.data,
};
init([code]);
} else {
message.error(res.msg || 'Failed to fetch data');
}
};
const init = async (data: any[]) => {
// console.log('data', data, ref.current);
const container = new Container({
root: ref.current!,
data: data as any,
showChild: false,
});
container.render(id!);
containerRef.current = container;
};
return (
<div className='w-full h-full bg-gray-200'>
<div className='text-center mb-10 font-bold text-4xl mt-4 '>Preview</div>
<div
className='flex '
style={{
height: 'calc(100% - 32px)',
}}>
<div className='mx-auto border bg-white h-h-full w-[80%] h-[80%]' ref={ref}></div>
</div>
</div>
);
};

View File

@ -0,0 +1,101 @@
import { Container } from '@abearxiong/container';
import { useEffect, useRef, useState } from 'react';
import { useParams } from 'react-router';
import { query } from '@/modules';
import { message } from 'antd';
export const Deck = () => {
const params = useParams<{ id: string }>();
const id = params.id;
const ref = useRef<HTMLDivElement>(null);
const containerRef = useRef<any>(null);
const [data, setData] = useState<any>({});
useEffect(() => {
if (!id) return;
fetch();
}, []);
const fetch = async () => {
const res = await query.post({
path: 'page',
key: 'getDeck',
id,
});
if (res.code === 200) {
const data = res.data;
console.log('data', data);
const { page, containerList } = data;
const { edges, nodes } = page.data;
for (let edge of edges) {
const { source, target } = edge;
const node = nodes.find((node: any) => node.id === source);
if (!node) continue;
node.children = node.children || [];
node.children.push(target);
}
for (let node of nodes) {
const container = containerList.find((container: any) => container.id === node.data?.cid);
if (container) {
node.container = container;
}
}
const codes = nodes.map((node: any) => {
const container = node.container;
const data = container?.data || {};
return {
id: node.id,
title: node.title,
code: container?.code || '',
data: data,
children: node.children,
...data, // style className shadowRoot showChild
};
});
// const code = {
// id: data.id,
// title: data.title,
// code: data.code,
// data: data.data,
// };
// init([code]);
init(codes);
console.log('codes', codes);
}
// if (res.code === 200) {
// const data = res.data;
// // setData([data]);
// console.log('data', data);
// const code = {
// id: data.id,
// title: data.title,
// code: data.code,
// data: data.data,
// };
// init([code]);
// } else {
// message.error(res.msg || 'Failed to fetch data');
// }
};
const init = async (data: any[]) => {
// console.log('data', data, ref.current);
const container = new Container({
root: ref.current!,
data: data as any,
showChild: true,
});
container.render(id!);
containerRef.current = container;
};
return (
<div className='w-full h-full bg-gray-200'>
<div className='text-center mb-10 font-bold text-4xl mt-4 '>Preview</div>
<div
className='flex '
style={{
height: 'calc(100% - 32px)',
}}>
<div className='mx-auto border bg-white h-h-full w-[80%] h-[80%]' ref={ref}></div>
</div>
</div>
);
};

View File

@ -1,3 +1,172 @@
export const List = () => { import { useEditStore } from '../store';
return <div>List</div>; import { Button, Input, message, Modal, Table } from 'antd';
import { useEffect, useState } from 'react';
import { useShallow } from 'zustand/react/shallow';
import { Form } from 'antd';
import copy from 'copy-to-clipboard';
import { useNavigate } from 'react-router';
const FormModal = () => {
const [form] = Form.useForm();
const editStore = useEditStore(
useShallow((state) => {
return {
showEdit: state.showEditModal,
setShowEdit: state.setShowEditModal,
formData: state.formData,
updateData: state.updateData,
};
}),
);
useEffect(() => {
const open = editStore.showEdit;
if (open) {
form.setFieldsValue(editStore.formData || {});
} else {
form.resetFields();
}
}, [editStore.showEdit]);
const onFinish = async (values: any) => {
editStore.updateData(values);
};
const onClose = () => {
editStore.setShowEdit(false);
form.resetFields();
};
const isEdit = editStore.formData.id;
return (
<Modal title={isEdit ? 'Edit' : 'Add'} open={editStore.showEdit} onClose={onClose} destroyOnClose footer={false} width={800} onCancel={onClose}>
<Form
form={form}
onFinish={onFinish}
labelCol={{
span: 4,
}}
wrapperCol={{
span: 20,
}}>
<Form.Item name='id' hidden>
<Input />
</Form.Item>
<Form.Item name='title' label='title'>
<Input />
</Form.Item>
{/* <Form.Item name='code' label='code'>
<TextArea value={containerStore.formData.code} />
</Form.Item> */}
<Form.Item label=' ' colon={false}>
<Button type='primary' htmlType='submit'>
Submit
</Button>
<Button className='ml-2' htmlType='reset' onClick={onClose}>
Cancel
</Button>
</Form.Item>
</Form>
</Modal>
);
};
export const List = () => {
const navicate = useNavigate();
const editStore = useEditStore(
useShallow((state) => {
return {
setFormData: state.setFormData,
setShowEdit: state.setShowEditModal,
list: state.list,
deleteData: state.deleteData,
getList: state.getList,
loading: state.loading,
};
}),
);
useEffect(() => {
editStore.getList();
}, []);
const columns = [
{
title: 'ID',
dataIndex: 'id',
render: (text: string) => {
return (
<div
className='w-40 truncate cursor-pointer'
title={text}
onClick={() => {
copy(text);
message.success('copy success');
}}>
{text}
</div>
);
},
},
{
title: 'Title',
dataIndex: 'title',
},
{
title: 'Operation',
dataIndex: 'operation',
render: (text: string, record: any) => {
return (
<div className='flex gap-2'>
<Button
type='primary'
onClick={() => {
editStore.setFormData(record);
editStore.setShowEdit(true);
}}>
Edit
</Button>
<Button
onClick={() => {
navicate('/container/preview/' + record.id);
}}>
Preview
</Button>
<Button
danger
onClick={() => {
editStore.deleteData(record.id);
}}>
Delete
</Button>
</div>
);
},
},
];
return (
<div className='w-full h-full flex flex-col'>
<div className='mb-2 w-full p-2 bg-white rounded-lg'>
<Button
className='w-20 '
type='primary'
onClick={() => {
editStore.setFormData({});
editStore.setShowEdit(true);
}}>
Add
</Button>
</div>
<div className='flex-grow overflow-scroll'>
<Table
pagination={false}
scroll={{
y: 600,
}}
loading={editStore.loading}
dataSource={editStore.list}
rowKey='id'
columns={columns}
/>
</div>
<div className='h-2'></div>
<FormModal />
</div>
);
}; };

View File

@ -14,33 +14,17 @@ import {
useStoreApi, useStoreApi,
Panel, Panel,
} from '@xyflow/react'; } from '@xyflow/react';
import type { Node } from '@xyflow/react';
import '@xyflow/react/dist/style.css'; import '@xyflow/react/dist/style.css';
import { useShallow } from 'zustand/react/shallow'; import { useShallow } from 'zustand/react/shallow';
import { useAddNode } from '@abearxiong/flows'; import { Container, useAddNode, ContainerMenusList, useMenuFlow } from '@abearxiong/flows';
import { Router, Container } from '@abearxiong/flows'; import { useMenuEmitter, ContainerMenusKeys } from '@abearxiong/flows';
console.log("R", Router); import { nanoid } from 'nanoid';
import { useContainerMenu, useRouterMenu } from '@abearxiong/flows';
import { Button } from 'antd'; import { Button } from 'antd';
import { usePanelStore } from '../store';
// router: Router // router: Router
const nodeTypes = { const nodeTypes = {
container: Container, container: Container,
}; };
export const initialNodes: Node[] = [
{ id: '1', position: { x: 100, y: 100 }, data: { label: '1' } },
{ id: '2', position: { x: 100, y: 400 }, data: { label: '2' } },
{ id: '3', position: { x: 100, y: 700 }, data: { label: '3' }, drag: true },
].map((node) => ({
...node,
// type: 'router',
type: 'container',
position: {
x: node.position.y,
y: node.position.x,
},
}));
export const initialEdges = [{ id: 'e1-2', source: '1', target: '2' }];
export const Flow = () => { export const Flow = () => {
return ( return (
@ -50,17 +34,58 @@ export const Flow = () => {
); );
}; };
const ReactFlowApp = () => { const ReactFlowApp = () => {
const [nodes, setNodes, onNodesChange] = useNodesState([...initialNodes]); const [nodes, setNodes, onNodesChange] = useNodesState([]);
const [edges, setEdges, onEdgesChange] = useEdgesState<any>([...initialEdges]); const [edges, setEdges, onEdgesChange] = useEdgesState<any>([]);
const reactFlow = useReactFlow();
const onConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)), [setEdges]); const onConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)), [setEdges]);
const panelStore = usePanelStore(
useShallow((state) => {
return {
data: state.data,
saveNodesEdges: state.saveNodesEdges,
};
}),
);
useEffect(() => {
if (panelStore.data?.id) {
const { data } = panelStore.data || {};
const nodes = data.nodes || [];
const edges = data.edges || [];
setNodes(nodes);
setEdges(edges);
} else {
setNodes([]);
setEdges([]);
}
}, [panelStore.data]);
const { menuCom, onContextMenu, onClose } = useMenuFlow(
(item, cacheData) => {
emit({
menu: item,
data: cacheData,
});
},
{
menusList: ContainerMenusList,
},
);
const { menuCom, onContextMenu, onClose } = useContainerMenu((item, cacheData) => { const { emit } = useMenuEmitter<ContainerMenusKeys>({
console.log(item, cacheData); preview: ({ menu, data }) => {
console.log('preview', data);
if (data?.data?.cid) {
window.open(`/container/preview/${data.data.cid}`, '_blank');
}
},
}); });
const { onNeedAdd, onAdd, onMouseMove, adding } = useAddNode(); const { onNeedAdd, onAdd, onMouseMove, adding } = useAddNode();
const onSave = useCallback(() => {
panelStore.saveNodesEdges({
nodes,
edges,
});
}, [nodes, edges]);
return ( return (
<ReactFlow <ReactFlow
nodes={nodes} nodes={nodes}
@ -99,16 +124,25 @@ const ReactFlowApp = () => {
}}> }}>
<MiniMap /> <MiniMap />
<Controls /> <Controls />
<Background gap={[14, 14]} size={2} color='#E4E5E7' /> {/* <Background gap={[14, 14]} size={2} color='#E4E5E7' /> */}
<Background color='#000' />
<Panel>{menuCom}</Panel> <Panel>{menuCom}</Panel>
<Panel> <Panel>
<Button <div className='flex gap-2'>
type='primary' <Button
onClick={(e) => { type='primary'
onNeedAdd({ id: '5', data: { label: '测试添加按钮' }, type: 'router' }, e); onClick={(e) => {
}}> onNeedAdd({ id: nanoid(6), data: { label: '容器' }, type: 'container' }, e);
}}>
</Button>
</Button>
<Button
onClick={() => {
onSave();
}}>
</Button>
</div>
</Panel> </Panel>
</ReactFlow> </ReactFlow>
); );

View File

@ -1,10 +1,31 @@
import { useParams } from 'react-router';
import Flow from './Flow'; import Flow from './Flow';
import { usePanelStore } from '../store';
import { useShallow } from 'zustand/react/shallow';
import { useEffect } from 'react';
export const App = () => { export const App = () => {
const param = useParams();
const id = param.id;
const panel = usePanelStore(
useShallow((state) => {
return {
getPanel: state.getPanel,
};
}),
);
useEffect(() => {
id && panel.getPanel(id);
}, []);
if (!id) {
return <>No ID</>;
}
return ( return (
<div className='w-full h-full'> <div className='w-full h-full p-4'>
sdf <div className='w-full h-full'>
<Flow /> <Flow />
</div>
</div> </div>
); );
}; };

View File

@ -2,14 +2,15 @@ import { Navigate, Route, Routes } from 'react-router-dom';
import { List } from './edit/List'; import { List } from './edit/List';
import { Main } from './layouts'; import { Main } from './layouts';
import { App as FlowApp } from './flow'; import { App as FlowApp } from './flow';
import { Deck } from './deck';
export const App = () => { export const App = () => {
return ( return (
<Routes> <Routes>
<Route element={<Main />}> <Route element={<Main />}>
<Route path='/' element={<Navigate to='/panel/edit/list' />}></Route> <Route path='/' element={<Navigate to='/panel/edit/list' />}></Route>
<Route path='edit/list' element={<List />} /> <Route path='edit/list' element={<List />} />
<Route path='flow' element={<FlowApp />} /> <Route path='flow/:id' element={<FlowApp />} />
<Route path='deck/:id' element={<Deck />} />
<Route path='*' element={'Not Found'}></Route> <Route path='*' element={'Not Found'}></Route>
</Route> </Route>
</Routes> </Routes>

View File

@ -26,7 +26,7 @@ export const useEditStore = create<EditStore>((set, get) => {
getList: async () => { getList: async () => {
set({ loading: true }); set({ loading: true });
const res = await query.post({ path: 'panel', key: 'list' }); const res = await query.post({ path: 'page', key: 'list' });
set({ loading: false }); set({ loading: false });
if (res.code === 200) { if (res.code === 200) {
set({ list: res.data }); set({ list: res.data });
@ -37,7 +37,7 @@ export const useEditStore = create<EditStore>((set, get) => {
updateData: async (data) => { updateData: async (data) => {
const { getList } = get(); const { getList } = get();
const res = await query.post({ const res = await query.post({
path: 'panel', path: 'page',
key: 'update', key: 'update',
data, data,
}); });
@ -52,7 +52,7 @@ export const useEditStore = create<EditStore>((set, get) => {
deleteData: async (id) => { deleteData: async (id) => {
const { getList } = get(); const { getList } = get();
const res = await query.post({ const res = await query.post({
path: 'panel', path: 'page',
key: 'delete', key: 'delete',
id, id,
}); });

View File

@ -1,14 +1,82 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { query } from '@/modules'; import { query } from '@/modules';
import { message } from 'antd'; import { message } from 'antd';
import { produce } from 'immer';
type PanelStore = { type PanelStore = {
id: string; id: string;
setId: (id: string) => void; setId: (id: string) => void;
loading: boolean;
setLoading: (loading: boolean) => void;
data: any;
setData: (data: any) => void;
getPanel: (id?: string) => Promise<void>;
saveNodesEdges: (data: { nodes?: any[]; edges?: any[]; viewport?: any }) => Promise<void>;
}; };
export const usePanelStore = create<PanelStore>((set, get) => { export const usePanelStore = create<PanelStore>((set, get) => {
return { return {
id: '', id: '',
setId: (id) => set({ id }), setId: (id) => set({ id }),
loading: false,
setLoading: (loading) => set({ loading }),
data: {},
setData: (data) => set({ data }),
getPanel: async (pid) => {
const id = pid || get().id;
if (!id) {
message.error('ID is required');
return;
}
set(
produce((state) => {
state.data = {};
state.loading = true;
}),
);
const res = await query.post({
path: 'page',
key: 'get',
id,
});
set({ loading: false });
console.log('res', res);
if (res.code === 200) {
set(
produce((state) => {
state.data = res.data;
state.id = res.data.id;
}),
);
} else {
message.error(res.msg || 'Request failed');
}
},
saveNodesEdges: async ({ edges, nodes, viewport }) => {
const { id, data: panelData } = get();
const { data } = panelData || {};
const res = await query.post({
path: 'page',
key: 'update',
data: {
id,
data: {
...data.data,
edges,
nodes,
viewport,
},
},
});
if (res.code === 200) {
message.success('Success');
set(
produce((state) => {
state.data = res.data;
}),
);
} else {
message.error(res.msg || 'Request failed');
}
},
}; };
}); });

View File

@ -32,7 +32,5 @@
}, },
"include": [ "include": [
"src", "src",
"./node_modules/@abearxiong/flows/**/*",
"./node_modules/.pnpm/@abearxiong+flows@0.0.1-alpha.6_@xyflow+react@12.3.0_@types+react@18.3.7_immer@10.1.1_react-d_f4d35tqb5yuohcch2fzlye5hn4/**/*"
] ]
} }