add image upscale

This commit is contained in:
2024-12-10 12:17:02 +08:00
parent 4d9b23c443
commit 91fef89657
24 changed files with 734 additions and 31 deletions

8
components.d.ts vendored
View File

@@ -47,6 +47,8 @@ declare module 'vue' {
ARadio: typeof import('ant-design-vue/es')['Radio']
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
ARow: typeof import('ant-design-vue/es')['Row']
ASelect: typeof import('ant-design-vue/es')['Select']
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
ASkeleton: typeof import('ant-design-vue/es')['Skeleton']
ASpace: typeof import('ant-design-vue/es')['Space']
ASpin: typeof import('ant-design-vue/es')['Spin']
@@ -57,6 +59,7 @@ declare module 'vue' {
ATextarea: typeof import('ant-design-vue/es')['Textarea']
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
AUpload: typeof import('ant-design-vue/es')['Upload']
AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger']
Avatar: typeof import('./src/components/MyUI/Avatar/Avatar.vue')['default']
BackgroundAnimation: typeof import('./src/components/BackgroundAnimation/BackgroundAnimation.vue')['default']
BackTop: typeof import('./src/components/MyUI/BackTop/BackTop.vue')['default']
@@ -74,6 +77,7 @@ declare module 'vue' {
CloseCircleOutlined: typeof import('@ant-design/icons-vue')['CloseCircleOutlined']
Clouds: typeof import('./src/components/Clouds/Clouds.vue')['default']
CloudServerOutlined: typeof import('@ant-design/icons-vue')['CloudServerOutlined']
CloudUploadOutlined: typeof import('@ant-design/icons-vue')['CloudUploadOutlined']
Col: typeof import('./src/components/MyUI/Grid/Col.vue')['default']
Collapse: typeof import('./src/components/MyUI/Collapse/Collapse.vue')['default']
CommentInput: typeof import('./src/components/CommentReply/src/CommentInput/CommentInput.vue')['default']
@@ -81,6 +85,7 @@ declare module 'vue' {
CommentOutlined: typeof import('@ant-design/icons-vue')['CommentOutlined']
CommentReply: typeof import('./src/components/CommentReply/index.vue')['default']
CompareImage: typeof import('./src/components/ImageCompare/CompareImage.vue')['default']
CompareResult: typeof import('./src/views/Upscale/CompareResult.vue')['default']
Countdown: typeof import('./src/components/MyUI/Countdown/Countdown.vue')['default']
CustomerServiceOutlined: typeof import('@ant-design/icons-vue')['CustomerServiceOutlined']
DatePicker: typeof import('./src/components/MyUI/DatePicker/DatePicker.vue')['default']
@@ -104,6 +109,7 @@ declare module 'vue' {
ImageCompare: typeof import('./src/components/ImageCompare/ImageCompare.vue')['default']
ImageInPainting: typeof import('./src/views/Upscale/Upscale.vue')['default']
ImageShare: typeof import('./src/views/ImageShare/ImageShare.vue')['default']
InboxOutlined: typeof import('@ant-design/icons-vue')['InboxOutlined']
Input: typeof import('./src/components/MyUI/Input/Input.vue')['default']
InputSearch: typeof import('./src/components/MyUI/InputSearch/InputSearch.vue')['default']
LandingPage: typeof import('./src/views/Landing/LandingPage.vue')['default']
@@ -140,6 +146,7 @@ declare module 'vue' {
ReplyInput: typeof import('./src/components/CommentReply/src/ReplyInput/ReplyInput.vue')['default']
ReplyList: typeof import('./src/components/CommentReply/src/ReplyList/ReplyList.vue')['default']
ReplyReply: typeof import('./src/components/CommentReply/src/ReplyReplyInput/ReplyReply.vue')['default']
RestOutlined: typeof import('@ant-design/icons-vue')['RestOutlined']
Result: typeof import('./src/components/MyUI/Result/Result.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
@@ -174,6 +181,7 @@ declare module 'vue' {
TreeChart: typeof import('./src/components/MyUI/TreeChart/TreeChart.vue')['default']
UngroupOutlined: typeof import('@ant-design/icons-vue')['UngroupOutlined']
Upload: typeof import('./src/components/MyUI/Upload/Upload.vue')['default']
UploadImage: typeof import('./src/views/Upscale/UploadImage.vue')['default']
Upscale: typeof import('./src/views/Upscale/Upscale.vue')['default']
UserInfoCard: typeof import('./src/components/CommentReply/src/UserInfoCard/UserInfoCard.vue')['default']
UserOutlined: typeof import('@ant-design/icons-vue')['UserOutlined']

View File

@@ -42,7 +42,7 @@
"nprogress": "^0.2.0",
"nsfwjs": "^4.2.1",
"pinia": "^2.3.0",
"pinia-plugin-persistedstate": "^4.1.3",
"pinia-plugin-persistedstate-2": "^2.0.27",
"qrcode": "^1",
"seedrandom": "^3.0.5",
"swiper": "^11.1.15",
@@ -63,7 +63,7 @@
"globals": "^15.13.0",
"sass": "^1.82.0",
"typescript": "^5.7.2",
"typescript-eslint": "^8.17.0",
"typescript-eslint": "^8.18.0",
"unplugin-vue-components": "^0.27.5",
"vite": "^6.0.3",
"vite-plugin-bundle-obfuscator": "1.3.2",

View File

@@ -0,0 +1 @@
<svg t="1733799768960" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="34134" width="200" height="200"><path d="M514 912c-219.9 0-398.9-178.9-398.9-398.8S294 114.3 514 114.3c219.9 0 398.8 178.9 398.8 398.9C912.8 733.1 733.9 912 514 912z m0-701.5c-166.9 0-302.7 135.8-302.7 302.7S347.1 815.9 514 815.9s302.7-135.8 302.7-302.7S680.9 210.5 514 210.5z" fill="#BDD2EF" p-id="34135"></path><path d="M555.6 642l164.1-164.1c22.9-22.9 22.9-60.2 0-83.1-22.9-22.9-60.2-22.9-83.1 0l-63.8 63.8V229.9c0-32.5-26.3-58.8-58.8-58.8s-58.8 26.3-58.8 58.8v228.7l-63.8-63.8c-11.5-11.5-26.5-17.2-41.5-17.2s-30.1 5.7-41.5 17.2c-22.9 22.9-22.9 60.2 0 83.1L472.5 642c22.9 23 60.1 23 83.1 0z" fill="#2867CE" p-id="34136"></path><path d="M679.5 714H351c-14.8 0-26.7-12-26.7-26.7s12-26.7 26.7-26.7h328.5c14.8 0 26.7 12 26.7 26.7S694.3 714 679.5 714z" fill="#2867CE" p-id="34137"></path></svg>

After

Width:  |  Height:  |  Size: 908 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -1 +1 @@
<svg t="1733393188492" class="icon" viewBox="0 0 1089 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="28883" width="200" height="200"><path d="M32.628594 863.170688C16.851704 625.805116 30.306304 391.05104 79.527611 158.550188c14.563947-54.20689 67.726238-104.222436 115.596472-109.587873 184.237813-19.506365 368.475627-23.965333 552.71344-13.376903 47.883184 2.917969 96.116007 52.786754 105.543292 109.337514a2391.284402 2391.284402 0 0 1-9.535198 112.225269" fill="#F2C84B" p-id="28884"></path><path d="M626.86698 252.343905c116.835315 1.044598 233.670629 4.584147 350.505944 10.610013 56.870184 3.306456 98.951962 49.454398 89.244103 103.005176-29.352353 157.389043-82.488745 322.711855-144.888395 493.123847-21.440167 58.19104-92.377898 110.904413-156.193366 114.146121-213.957071 10.756774-427.914142 5.244575-641.871213-16.540914-63.828418-6.923702-103.18647-57.064427-84.8283-110.68427 52.670208-155.040855 118.971993-317.49318 186.400391-483.398722 23.861736-57.737805 77.891649-106.812349 119.977743-107.956228 42.457315-1.083447 77.196688-1.58848 77.196688-1.592796" fill="#FFE287" p-id="28885"></path><path d="M540.53653 511.784174m-80.42113 0a80.421131 80.421131 0 1 0 160.842261 0 80.421131 80.421131 0 1 0-160.842261 0Z" opacity=".4" p-id="28886"></path><path d="M683.163067 873.206603c55.229905 0 114.957627-36.781088 132.737383-81.73767l88.903098-224.813125c17.771123-44.952265-2.874804-57.370901-45.888951-27.578262l-203.019003 140.580504c-43.005514 29.784005-99.931812 33.478949-126.495692 8.201393-26.559563-25.277556-81.767886-19.868953-122.684202 12.038781l-147.871112 115.298633c-40.916317 31.903418-29.196958 58.001113 26.037264 58.001113l398.281215 0.008633z" opacity=".4" p-id="28887"></path></svg>
<svg t="1733731565547" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14899" width="200" height="200"><path d="M235.466 195.356v249.398H39.548v-179.51c0-38.59 31.296-69.888 69.888-69.888h35.726z" fill="#BED8FB" p-id="14900"></path><path d="M984.44 393.056v548.778c0 45.39-36.756 82.166-82.126 82.166H227.34c-29.072 0-54.6-15.102-69.208-37.87a81.72 81.72 0 0 1-10.714-25.136l-0.308-46.976-1.916-279.756V82.166C145.194 36.778 181.972 0 227.34 0h364.066c32.718 0 138.662 90.348 232.326 185.494 85.486 86.844 160.708 177.686 160.708 207.562z" fill="#DDEAFB" p-id="14901"></path><path d="M984.452 393.056v201.03c0-0.226-0.02-0.454-0.02-0.7C978.25 346.72 777.324 335.306 711.62 269.6l112.124-84.104c85.464 86.842 160.708 177.684 160.708 207.56z" fill="#CBE2FF" p-id="14902"></path><path d="M591.386 0H390.356c0.226 0 0.454 0.02 0.7 0.02 246.666 6.182 258.08 207.108 323.786 272.812l84.104-112.124C712.102 75.244 621.26 0 591.386 0z" fill="#CBE2FF" p-id="14903"></path><path d="M984.45 393.066v34.754c0-73.172-59.336-132.506-132.506-132.506h-80.648c-45.368 0-82.162-36.794-82.162-82.162V132.506C689.134 59.334 629.8 0 556.628 0h34.754c62.58 0 122.616 24.866 166.866 69.114l157.086 157.086a236.008 236.008 0 0 1 69.116 166.866zM701.41 693.93v184.278c0 59.606-48.316 107.922-107.922 107.922H158.132a81.72 81.72 0 0 1-10.714-25.136l-0.308-46.976-1.916-279.756v-48.254h448.294c59.606 0 107.922 48.316 107.922 107.922z" fill="#BED8FB" p-id="14904"></path><path d="M771.298 443.052v375.384c0 59.606-48.316 107.922-107.922 107.922H109.448c-2.08 0-4.12-0.082-6.16-0.288-35.706-3.09-63.726-33.068-63.726-69.6V265.244c0 19.286 7.83 36.756 20.48 49.408 11.27 11.29 26.394 18.75 43.246 20.192 2.04 0.206 4.08 0.288 6.16 0.288h553.928c59.608-0.002 107.922 48.314 107.922 107.92z" fill="#617881" p-id="14905"></path><path d="M668.278 492.9v275.676c0 5.068-0.68 9.972-1.978 14.608-6.388 23.158-27.608 40.156-52.786 40.156H192.438a49.648 49.648 0 0 1-39.106-18.956 49.52 49.52 0 0 1-10.756-30.906V487.996c0-27.526 22.314-49.84 49.86-49.84h421.076c30.248 0 54.766 24.52 54.766 54.744z" fill="#80B4FB" p-id="14906"></path><path d="M277.946 558.042m-53.742 0a53.742 53.742 0 1 0 107.484 0 53.742 53.742 0 1 0-107.484 0Z" fill="#F1D333" p-id="14907"></path><path d="M411.228 823.342H192.438a49.648 49.648 0 0 1-39.106-18.956l119.11-114.844z" fill="#EAB14D" p-id="14908"></path><path d="M666.3 783.186c-6.388 23.158-27.608 40.156-52.786 40.156H314.06l196.93-189.904z" fill="#F1D333" p-id="14909"></path><path d="M103.288 334.842v591.228c-35.706-3.09-63.726-33.068-63.726-69.6V265.244c0 19.286 7.83 36.756 20.48 49.408 11.27 11.29 26.392 18.748 43.246 20.19z" fill="#475959" p-id="14910"></path></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1 @@
<svg t="1733800047141" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="39002" width="200" height="200"><path d="M737.882353 584.282353c0 48.188235-39.152941 84.329412-84.329412 84.329412h-286.117647c-48.188235 0-84.329412-39.152941-84.329412-84.329412v-150.588235c0-48.188235 39.152941-84.329412 84.329412-84.329412 12.047059 0 21.082353 9.035294 21.082353 21.082353 0 12.047059-9.035294 21.082353-21.082353 21.082353-24.094118 0-42.164706 18.070588-42.164706 42.164706v150.588235c0 24.094118 18.070588 42.164706 42.164706 42.164706h286.117647c24.094118 0 42.164706-18.070588 42.164706-42.164706v-150.588235c0-24.094118-18.070588-42.164706-42.164706-42.164706-12.047059 0-21.082353-9.035294-21.082353-21.082353 0-12.047059 9.035294-21.082353 21.082353-21.082353 48.188235 0 84.329412 39.152941 84.329412 84.329412v150.588235z m-307.2-87.341177c0 18.070588-15.058824 33.129412-33.129412 33.129412-18.070588 0-33.129412-15.058824-33.129412-33.129412 0-18.070588 15.058824-33.129412 33.129412-33.129411 21.082353 3.011765 33.129412 15.058824 33.129412 33.129411z m78.305882-30.117647c18.070588 0 33.129412 15.058824 33.129412 33.129412 0 18.070588-15.058824 33.129412-33.129412 33.129412s-33.129412-15.058824-33.129411-33.129412c3.011765-21.082353 18.070588-33.129412 33.129411-33.129412z m51.2-189.741176c18.070588 0 33.129412 15.058824 33.129412 33.129412s-15.058824 33.129412-33.129412 33.129411-33.129412-15.058824-33.129411-33.129411 18.070588-33.129412 33.129411-33.129412zM508.988235 30.117647C243.952941 30.117647 27.105882 246.964706 27.105882 512s216.847059 481.882353 481.882353 481.882353 481.882353-216.847059 481.882353-481.882353-213.835294-481.882353-481.882353-481.882353z" fill="#7B9CFF" p-id="39003"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1 @@
<svg t="1733761095875" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="50680" width="200" height="200"><path d="M471.87259 871.430008a41.629505 41.629505 0 0 0 41.629506 41.629506 40.98575 40.98575 0 0 0 38.625314-41.629506 40.55658 40.55658 0 0 0-39.912825-40.98575h-1.072925a40.98575 40.98575 0 0 0-39.26907 40.98575z" fill="#B8BDCC" p-id="50681"></path><path d="M738.601844 55.792121a77.036044 77.036044 0 0 1 77.036044 77.036043v758.343672a77.036044 77.036044 0 0 1-77.036044 77.036043H285.398156a77.036044 77.036044 0 0 1-77.036044-77.036043V132.828164A77.036044 77.036044 0 0 1 285.398156 55.792121h453.203688m0-55.792121H285.398156A132.828164 132.828164 0 0 0 152.569992 132.828164v758.343672a132.828164 132.828164 0 0 0 132.828164 132.828164h453.203688a132.828164 132.828164 0 0 0 132.828164-132.828164V132.828164A132.828164 132.828164 0 0 0 738.601844 0z" fill="#B8BDCC" p-id="50682"></path><path d="M713.49539 793.964795H310.50461a39.483655 39.483655 0 0 1-41.629505-36.694049v-519.295893a39.26907 39.26907 0 0 1 41.629505-36.479463h402.99078a39.26907 39.26907 0 0 1 41.629505 36.479463v518.437553A39.483655 39.483655 0 0 1 713.49539 793.964795z" fill="#E3E5EB" p-id="50683"></path><path d="M425.736798 103.430008m25.964795 0l120.596814 0q25.964795 0 25.964795 25.964795l0 0q0 25.964795-25.964795 25.964795l-120.596814 0q-25.964795 0-25.964795-25.964795l0 0q0-25.964795 25.964795-25.964795Z" fill="#B8BDCC" p-id="50684"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1 @@
<svg t="1733762218316" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="53040" width="200" height="200"><path d="M514.5 511.5m-434.5 0a434.5 434.5 0 1 0 869 0 434.5 434.5 0 1 0-869 0Z" fill="#DB3131" p-id="53041"></path><path d="M453.13 319c14.68-0.64 39.84-1.5 68.42-1.5 28.21 0 53.61 0.87 68.42 1.51a13 13 0 0 0 13.59-13 82 82 0 0 0-82-82 82 82 0 0 0-82 82A13 13 0 0 0 453.13 319zM750.24 371l-61-4.87c-51.18-4.09-121.36-5.93-168.19-5.9-46.66 0-116.49 1.84-167.3 5.9L292.86 371a31.38 31.38 0 1 0 5 62.57l40-3.2a38.64 38.64 0 0 0-0.28 5.92c2.28 74.62 14.47 236.63 15.5 249.25l2 24.2c3.09 37.81 33.75 67.84 72.36 70.87l24.71 1.93c21.46 1.68 49.6 2.52 71.12 2.51s49.39-0.84 70.73-2.51l25.1-1.92c39.34-3 70.36-34 72.62-72.61l1.28-22.52c1-12.62 13.22-174.63 15.5-249.26a38.08 38.08 0 0 0-0.25-5.67l37 3c0.85 0.07 1.7 0.1 2.54 0.1a31.38 31.38 0 0 0 2.45-62.66zM459.83 716c-0.8 0.06-1.6 0.1-2.39 0.1a27.47 27.47 0 0 1-27.33-25.1c-1.16-13.46-8.79-164.6-8.79-189.52a27.46 27.46 0 0 1 54.92 0c0 24.21 7.66 173.94 8.59 184.8a27.47 27.47 0 0 1-25 29.72z m155.45-25A27.47 27.47 0 0 1 588 716.08c-0.79 0-1.59 0-2.39-0.1a27.46 27.46 0 0 1-25-29.72c1.6-18.63 8.59-168.89 8.59-184.8a27.46 27.46 0 0 1 54.92 0c-0.05 19.45-7.36 172.33-8.84 189.54z" fill="#FFFFFF" p-id="53042"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

1
src/assets/svgs/run.svg Normal file
View File

@@ -0,0 +1 @@
<svg t="1733748093314" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3982" width="200" height="200"><path d="M170.666667 0h682.666666c93.866667 0 170.666667 76.8 170.666667 170.666667v682.666666c0 93.866667-76.8 170.666667-170.666667 170.666667H170.666667c-93.866667 0-170.666667-76.8-170.666667-170.666667V170.666667c0-93.866667 76.8-170.666667 170.666667-170.666667z" fill="#32B84C" opacity=".2" p-id="3983"></path><path d="M200.533333 72.533333h622.933334c72.533333 0 128 55.466667 128 128v622.933334c0 72.533333-55.466667 128-128 128H200.533333c-72.533333 0-128-55.466667-128-128V200.533333c0-68.266667 59.733333-128 128-128z" fill="#32B84C" opacity=".3" p-id="3984"></path><path d="M230.4 145.066667h558.933333c46.933333 0 85.333333 38.4 85.333334 85.333333v558.933333c0 46.933333-38.4 85.333333-85.333334 85.333334H230.4c-46.933333 0-85.333333-38.4-85.333333-85.333334V230.4c0-46.933333 38.4-85.333333 85.333333-85.333333z" fill="#32B84C" opacity=".38" p-id="3985"></path><path d="M669.866667 537.6l-234.666667 149.333333c-29.866667 21.333333-68.266667-8.533333-68.266667-42.666666V341.333333c0-34.133333 38.4-64 68.266667-42.666666l234.666667 149.333333c34.133333 21.333333 34.133333 68.266667 0 89.6" fill="#26AE40" p-id="3986"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

1
src/assets/svgs/save.svg Normal file
View File

@@ -0,0 +1 @@
<svg t="1733799474807" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="32161" width="200" height="200"><path d="M826.026667 314.026667l-114.346667-114.346667c-29.013333-29.013333-68.266667-44.373333-109.226667-44.373333H256c-56.32 0-102.4 46.08-102.4 102.4v512c0 56.32 46.08 102.4 102.4 102.4h512c56.32 0 102.4-46.08 102.4-102.4V421.546667c0-40.96-15.36-78.506667-44.373333-107.52zM204.8 409.6h460.8v307.2H204.8V409.6z m614.4 358.4c0 29.013333-22.186667 51.2-51.2 51.2H256c-29.013333 0-51.2-22.186667-51.2-51.2h494.933333c10.24 0 17.066667-6.826667 17.066667-17.066667V375.466667c0-10.24-6.826667-17.066667-17.066667-17.066667H204.8v-102.4c0-29.013333 22.186667-51.2 51.2-51.2h346.453333c27.306667 0 52.906667 10.24 71.68 30.72l114.346667 114.346667c18.773333 18.773333 30.72 44.373333 30.72 71.68V768z" fill="#335056" p-id="32162"></path><path d="M256 256h204.8v51.2H256zM563.2 512h51.2v102.4h-51.2z" fill="#335056" p-id="32163"></path><path d="M204.8 409.6v307.2h460.8V409.6H204.8z m409.6 204.8h-51.2v-102.4h51.2v102.4z" fill="#78BDCC" p-id="32164"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -6,12 +6,13 @@ import router from "@/router/router.ts";
import "go-captcha-vue/dist/style.css";
import GoCaptcha from "go-captcha-vue";
import {createPinia, Pinia} from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
import {createPersistedStatePlugin} from 'pinia-plugin-persistedstate-2';
import VueDOMPurifyHTML from 'vue-dompurify-html';
import {registerDirectives} from "@/directives";
const pinia: Pinia = createPinia();
pinia.use(piniaPluginPersistedstate);
const installPersistedStatePlugin = createPersistedStatePlugin();
pinia.use((context) => installPersistedStatePlugin(context));
const app = createApp(App);
registerDirectives(app);
app.use(pinia);

View File

@@ -3,6 +3,7 @@ import {useThemeStore} from "@/store/modules/themeStore.ts";
import {langStore} from "@/store/modules/langStore.ts";
import {useCommentStore} from "@/store/modules/commentStore.ts";
import {useWebSocketStore} from "@/store/modules/websocketStore.ts";
import {useUpscaleStore} from "@/store/modules/upscaleStore.ts";
export default function useStore() {
return {
@@ -11,5 +12,6 @@ export default function useStore() {
lang: langStore(),
comment: useCommentStore(),
websocket: useWebSocketStore(),
upscale: useUpscaleStore(),
};
}

View File

@@ -8,6 +8,7 @@ import QQ_EMOJI from "@/constant/qq_emoji.ts";
import {initNSFWJs, predictNSFW} from "@/utils/nsfw/nsfw.ts";
import {NSFWJS} from "nsfwjs";
import i18n from "@/locales";
import localForage from "localforage";
export const useCommentStore = defineStore(
'comment',
@@ -325,10 +326,16 @@ export const useCommentStore = defineStore(
},
{
// 开启数据持久化
persist: {
// persist: {
// key: 'comment',
// storage: localStorage,
// pick: ["emojiList", "commentList", "replyVisibility", "commentMap"],
// }
persistedState: {
persist: true,
storage: localForage,
key: 'comment',
storage: localStorage,
pick: ["emojiList", "commentList", "replyVisibility", "commentMap"],
includePaths: ["emojiList", "commentList", "replyVisibility", "commentMap"]
}
}
);

View File

@@ -1,6 +1,7 @@
import {defineStore} from 'pinia';
import {ref} from "vue";
export const langStore = defineStore(
'lang',
() => {
@@ -11,10 +12,11 @@ export const langStore = defineStore(
},
{
// 开启数据持久化
persist: {
key: 'lang',
persistedState: {
persist: true,
storage: localStorage,
pick: ["lang"],
key: 'lang',
includePaths: ['lang']
}
}
);

View File

@@ -37,10 +37,11 @@ export const useThemeStore = defineStore(
return {themeName, themeConfig, darkMode, setThemeName, toggleDarkMode};
},
{
persist: {
key: 'theme',
persistedState: {
persist: true,
storage: localStorage,
pick: ["themeName", "darkMode"],
key: 'theme',
includePaths: ['themeName', 'darkMode']
}
}
);

View File

@@ -0,0 +1,88 @@
import {defineStore} from 'pinia';
import {initNSFWJs, predictNSFW} from "@/utils/nsfw/nsfw.ts";
import i18n from "@/locales";
import message from "@/components/MyUI/Message/Message.vue";
import {NSFWJS} from "nsfwjs";
import localForage from "localforage";
export const useUpscaleStore = defineStore(
'upscale',
() => {
const imageList = ref<string[]>([]);
const fileList = ref<string[]>([]);
const uploading = ref<boolean>(false);
/**
* 图片上传前的校验
* @param file
*/
async function beforeUpload(file: any) {
if (fileList.value.length >= 5) {
return false;
}
uploading.value = true;
if (!window.FileReader) return false;
const reader = new FileReader();
reader.readAsDataURL(file); // 文件转换
reader.onloadend = async function () {
const img: HTMLImageElement = document.createElement('img');
img.src = reader.result as string;
img.onload = async () => {
// 图片 NSFW 检测
const nsfw: NSFWJS = await initNSFWJs();
const isNSFW: boolean = await predictNSFW(nsfw, img);
if (isNSFW) {
message.error(i18n.global.t('comment.illegalImage'));
fileList.value.pop();
return false;
}
fileList.value.push(img.src);
};
uploading.value = false;
return true;
};
}
/**
* 自定义上传图片请求
*/
async function customUploadRequest() {
imageList.value = fileList.value;
}
/**
* 移除图片
* @param index
*/
async function removeImage(index: number) {
fileList.value.splice(index, 1);
imageList.value.splice(index, 1);
}
return {
imageList,
fileList,
uploading,
beforeUpload,
customUploadRequest,
removeImage
};
}
,
{
// 开启数据持久化
persistedState: {
persist: true,
storage:
localForage,
key:
'upscale',
includePaths:
['imageList', 'fileList']
}
}
)
;

View File

@@ -144,10 +144,16 @@ export const useAuthStore = defineStore(
},
{
// 开启数据持久化
persist: {
key: 'user',
// persist: {
// key: 'user',
// storage: localStorage,
// pick: ['user', "clientId", "githubRedirectUrl", "giteeRedirectUrl", "qqRedirectUrl"],
// }
persistedState: {
persist: true,
storage: localStorage,
pick: ['user', "clientId", "githubRedirectUrl", "giteeRedirectUrl", "qqRedirectUrl"],
key: 'user',
includePaths: ['user', "clientId", "githubRedirectUrl", "giteeRedirectUrl", "qqRedirectUrl"]
}
}
);

View File

@@ -49,5 +49,7 @@ export const useWebSocketStore = defineStore('websocket', () => {
getReadyState
};
}, {
persistedState: {
persist: false,
}
});

View File

@@ -9,7 +9,7 @@ let isInit: boolean = false;
const initNSFWJs = async (): Promise<NSFWJS> => {
tf.enableProdMode();
if (!isInit) {
const initialLoad: nsfwjs.NSFWJS = await nsfwjs.load("/nsfw/model/mobilenet_v2_mid/", {
const initialLoad: nsfwjs.NSFWJS = await nsfwjs.load("/nsfw/mobilenet_v2_mid/", {
size: 224,
type: "graph"
});

View File

@@ -3,23 +3,20 @@
flex-direction: column;
background-color: #eaeef6;
color: var(--text-color);
width: 100%;
min-height: 100vh;
.main-header {
}
width: 100vw;
.main-content {
display: flex;
flex-direction: row;
width: 100%;
height: calc(100vh - 70px);
.main-content-container {
width: calc(100% - 230px);
height: calc(100% - 110px);
padding: 20px;
overflow: scroll;
width: calc(100vw - 230px);
height: calc(100vh - 100px);
max-height: calc(100vh - 100px);
padding: 15px;
overflow: auto;
}
}

View File

@@ -0,0 +1,184 @@
<template>
<div class="upscale-comparison-result">
<div class="upscale-comparison-top">
<div class="upscale-comparison-top-left">
<VueCompareImage :left-image="bg" :right-image="bg2"
style="width: 45vw; height: 60vh;border-radius: 10px;box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);"
rightImageLabel="修复后"
leftImageLabel="原图"
/>
</div>
<div class="upscale-comparison-top-right" ref="avatarContainer">
<ABadge style="margin-top: 5px;" v-for="(item, index) in upscale.imageList"
:key="index">
<template #count>
<AButton type="text" size="small" class="upscale-file-btn" @click="upscale.removeImage(index)">
<template #icon>
<AAvatar shape="square" :size="20" :src="remove"/>
</template>
</AButton>
</template>
<AAvatar shape="square" :size="avatarSize" @click="bg = item">
<template #icon>
<AImage :src="item" width="100%" height="100%" :preview="true"/>
</template>
</AAvatar>
</ABadge>
</div>
</div>
<ADivider orientation="center" :plain="true"><span class="upscale-comparison-divider-text">保存下载</span>
</ADivider>
<div class="upscale-comparison-bottom">
<AFlex :vertical="false" align="center" justify="space-between" gap="large">
<AButton type="text" size="large" style="width: 50px; height: 50px;">
<template #icon>
<AAvatar shape="square" :size="40" :src="download"/>
</template>
</AButton>
<AButton type="text" style="width: 50px; height: 50px;">
<template #icon>
<AAvatar shape="square" :size="40" :src="save"/>
</template>
</AButton>
<AButton type="text" style="width: 50px; height: 50px;">
<template #icon>
<AAvatar shape="square" :size="35" :src="share"/>
</template>
</AButton>
<AButton type="text" style="width: 50px; height: 50px;">
<template #icon>
<AAvatar shape="square" :size="35" :src="packageDownload"/>
</template>
</AButton>
</AFlex>
<ADivider type="vertical" style="height: 30px;"/>
<AFlex :vertical="false" align="center" justify="space-between" gap="large" style="margin-left: 1%">
<AFlex :vertical="true" align="flex-start" justify="flex-start" gap="small">
<AFlex :vertical="false" align="center" justify="space-between">
<span class="upscale-comparison-bottom-text">处理数量</span>
<ATag color="orange">{{ 5 }}</ATag>
</AFlex>
<AFlex :vertical="false" align="center" justify="space-between">
<span class="upscale-comparison-bottom-text">处理大小</span>
<ATag color="green">{{ upscale.imageList.length }} /mb</ATag>
</AFlex>
</AFlex>
<AFlex :vertical="true" align="flex-start" justify="center" gap="small">
<AFlex :vertical="false" align="center" justify="space-between">
<span class="upscale-comparison-bottom-text">消耗时间</span>
<ATag color="cyan">{{ upscale.imageList.length }} /s</ATag>
</AFlex>
<AFlex :vertical="false" align="center" justify="space-between">
<span class="upscale-comparison-bottom-text">内存消耗</span>
<ATag color="purple">{{ upscale.imageList.length }} /mb</ATag>
</AFlex>
</AFlex>
</AFlex>
</div>
</div>
</template>
<script setup lang="ts">
import {VueCompareImage} from "@/components/VueCompareImage";
import bg1 from "@/assets/images/background.jpg";
import bg2 from "@/assets/images/background.png";
import useStore from "@/store";
import remove from "@/assets/svgs/remove.svg";
import download from "@/assets/svgs/download.svg";
import save from "@/assets/svgs/save.svg";
import share from "@/assets/svgs/share.svg";
import packageDownload from "@/assets/svgs/package-download.svg";
const upscale = useStore().upscale;
const avatarSize = ref<number>(60);
const avatarContainer = ref<HTMLDivElement | null>();
const bg = ref<string>(bg1);
/**
* 更新大小
*/
const updateSize = () => {
if (avatarContainer.value) {
// 设置图片列表大小
const container = avatarContainer.value?.clientWidth || 0;
avatarSize.value = Math.min(0.7 * container, 300); // 设置头像大小为容器宽度的10%最大不超过100
}
};
onMounted(() => {
updateSize();
window.addEventListener('resize', updateSize);
});
onBeforeUnmount(() => {
window.removeEventListener('resize', updateSize);
});
</script>
<style scoped lang="scss">
.upscale-comparison-result {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.upscale-comparison-top {
width: 100%;
height: 80%;
display: flex;
flex-direction: row;
justify-content: space-between;
.upscale-comparison-top-left {
width: 85%;
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
.upscale-comparison-image {
width: 40vw;
height: 60vh;
}
}
.upscale-comparison-top-right {
width: 14%;
height: 60vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
overflow-y: scroll;
border: 1px solid rgba(126, 126, 135, 0.48);
border-radius: 10px;
}
}
.upscale-comparison-divider-text {
font-size: 13px;
color: rgba(126, 126, 135, 0.99);
}
.upscale-comparison-bottom {
width: 100%;
height: 20%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-evenly;
.upscale-comparison-bottom-text {
font-size: 13px;
color: rgba(126, 126, 135, 0.99);
}
}
}
</style>

View File

@@ -0,0 +1,211 @@
<template>
<div class="upscale-upload-container">
<div class="upscale-upload-content">
<Spin :spinning="upscale.uploading" indicator="magic-ring">
<AUploadDragger
name="image"
accept="image/*"
:multiple="false"
:directory="false"
:maxCount="5"
:beforeUpload="upscale.beforeUpload"
:custom-request="upscale.customUploadRequest"
:disabled="upscale.uploading"
:showUploadList="false">
<div class="upscale-upload-content-main">
<div class="upscale-upload-content-left">
<ABadge :count="upscale.imageList.length" :offset="[-10, 10]">
<AAvatar shape="square" :size="70" :src="file"/>
</ABadge>
<span class="upscale-upload-text">
点击或拖拽上传图片
</span>
<span class="upscale-upload-tip">最多一次处理5张图片</span>
</div>
<div class="upscale-upload-content-right" ref="qrcodeContainer">
<AQrcode :value="'https://www.baidu.com'"
class="upscale-upload-qrcode"
:icon="qrphone"
:iconSize="iconSize"
:bordered="false"
:size="qrcodeSize"
color="rgba(126, 126, 135, 1)"/>
<span class="upscale-upload-qr-text">手机扫码上传</span>
</div>
</div>
</AUploadDragger>
</Spin>
</div>
</div>
<ADivider orientation="center" :plain="true"><span class="upscale-file-list-title">图片列表</span></ADivider>
<div class="upscale-file-list" ref="fileListContainer">
<div v-if="upscale.imageList.length > 0">
<AImagePreviewGroup>
<ABadge style="margin-left: 10px;" v-for="(item, index) in upscale.imageList"
:key="index">
<template #count>
<AButton type="text" size="small" class="upscale-file-btn" @click="upscale.removeImage(index)">
<template #icon>
<AAvatar shape="square" :size="20" :src="remove"/>
</template>
</AButton>
</template>
<AAvatar shape="square" :size="avatarSize" v-if="item">
<template #icon>
<AImage :src="item" width="100%" height="100%"/>
</template>
</AAvatar>
</ABadge>
</AImagePreviewGroup>
</div>
</div>
<AEmpty :image="empty" v-if="upscale.imageList.length === 0" :description="null"/>
</template>
<script setup lang="ts">
import file from "@/assets/svgs/file.svg";
import qrphone from "@/assets/svgs/qr-phone.svg";
import empty from "@/assets/svgs/empty.svg";
import useStore from "@/store";
import Spin from "@/components/MyUI/Spin/Spin.vue";
import remove from '@/assets/svgs/remove.svg';
const upscale = useStore().upscale;
const qrcodeSize = ref<number>(160);
const iconSize = ref<number>(30);
const qrcodeContainer = ref<HTMLElement | null>(null);
const avatarSize = ref<number>(80);
const fileListContainer = ref<HTMLDivElement | null>(null);
/**
* 更新大小
*/
const updateSize = () => {
if (qrcodeContainer.value && fileListContainer.value) {
// 设置 QRCode 大小
const containerWidth = qrcodeContainer.value.clientWidth;
qrcodeSize.value = containerWidth * 0.5; // 设置 QRCode 为父盒子宽度的80%
iconSize.value = Math.min(containerWidth * 0.1, 50); // 设置 icon 大小为父盒子宽度的10%
// 设置图片列表大小
const container = fileListContainer.value.clientWidth;
avatarSize.value = Math.min(0.17 * container, 300); // 设置头像大小为容器宽度的10%最大不超过100
}
};
onMounted(() => {
updateSize();
window.addEventListener('resize', updateSize);
});
onBeforeUnmount(() => {
window.removeEventListener('resize', updateSize);
});
</script>
<style scoped lang="scss">
.upscale-upload-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.upscale-upload-content {
width: 100%;
height: 30vh;
.upscale-upload-content-main {
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
overflow: scroll;
.upscale-upload-content-left {
width: 50%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
.upscale-upload-text {
font-size: 20px;
font-weight: bold;
}
.upscale-upload-btn {
width: 60%;
}
.upscale-upload-tip {
font-size: 12px;
color: rgba(126, 126, 135, 0.99);
}
}
.upscale-upload-content-right {
width: 50%;
display: flex;
flex-direction: column;
align-items: center;
.upscale-upload-qr-text {
font-size: 12px;
color: rgba(126, 126, 135, 0.99);
}
}
}
}
}
.upscale-file-list-title {
font-size: 13px;
color: rgba(126, 126, 135, 0.99);
}
.upscale-file-list {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
flex-wrap: wrap;
}
.upscale-file-remove-icon {
cursor: pointer;
font-size: 18px;
color: #ff0000;
//transform: scale(1.2);
}
@media (max-width: 1300px) {
.upscale-upload-text {
display: none !important;
}
.upscale-upload-btn {
display: none !important;
}
.upscale-upload-qr-text {
display: none !important;
}
.upscale-upload-content-left {
width: 100% !important;
height: 100% !important;
display: flex !important;
flex-direction: column !important;
align-items: center !important;
justify-content: center !important;
}
.upscale-upload-content-right {
display: none !important;
}
}
</style>

View File

@@ -1,15 +1,122 @@
<template>
<div class="upscale-container">
<AFlex :vertical="false" align="center" justify="flex-start">
<AAvatar shape="square" :size="30" :src="ai"/>
<span class="upscale-title">图像修复</span>
</AFlex>
<AFlex :vertical="false" align="center" justify="flex-start">
<AFlex class="upscale-content" :vertical="false" align="center" justify="flex-start">
<div class="upscale-content-left">
<ACard class="upscale-content-left-container">
<UploadImage/>
<ADivider orientation="center" :plain="true"><span class="upscale-divider-title">参数设置</span></ADivider>
<div class="upscale-content-left-params">
<div class="upscale-content-params-left">
<div class="upscale-content-params-item">
<div class="upscale-content-params-item-content">
<span class="upscale-content-params-title">类型:</span>
<ASelect style="width: 100%" size="default"
v-model:value="type"
:options="TypeData.map(item => ({label: item, value: item}))">
</ASelect>
</div>
<div class="upscale-content-params-item-content">
<span class="upscale-content-params-title">模型:</span>
<ASelect style="width: 100%" size="default"
v-model:value="model"
:options="modes.map(item => ({label: item, value: item}))">
</ASelect>
</div>
</div>
<div class="upscale-content-params-item">
<div class="upscale-content-params-item-content">
<span class="upscale-content-params-title">比列:</span>
<ASelect style="width: 100%" size="default"
v-model:value="scale"
:options="ScaleData.map(item => ({label: item, value: item}))">
</ASelect>
</div>
<div class="upscale-content-params-item-content">
<span class="upscale-content-params-title">分块大小:</span>
<ASelect style="width: 100%" size="default"
v-model:value="tileSize"
:options="tileSizes.map(item => ({label: item, value: item}))">
</ASelect>
</div>
</div>
<div class="upscale-content-params-item">
<div class="upscale-content-params-item-content">
<span class="upscale-content-params-title">重复:</span>
<ASelect style="width: 100%" size="default"
v-model:value="overlap"
:options="overlapList.map(item => ({label: item, value: item}))">
</ASelect>
</div>
<div class="upscale-content-params-item-content">
<span class="upscale-content-params-title">运行环境</span>
<ASelect style="width: 100%" size="default"
v-model:value="runOn"
:options="runOnList.map(item => ({label: item, value: item}))">
</ASelect>
</div>
</div>
</div>
<div class="upscale-content-params-right">
<AButton type="text" style="width: 60px;height: 60px;">
<template #icon>
<AAvatar shape="square" :size="50" :src="run"/>
</template>
</AButton>
</div>
</div>
</ACard>
</div>
<div class="upscale-content-right">
<ACard class="upscale-content-right-container">
<CompareResult/>
</ACard>
</div>
</AFlex>
</div>
</template>
<script setup lang="ts">
import UploadImage from "@/views/Upscale/UploadImage.vue";
import ai from "@/assets/svgs/ai.svg";
import run from "@/assets/svgs/run.svg";
import CompareResult from "@/views/Upscale/CompareResult.vue";
const TypeData = ['Real-ESRGAN', 'Real-CUGAN'];
const type = ref<string>(TypeData[0]);
const ModelData = {
'Real-ESRGAN': ['anime_fast', 'anime_plus', 'general_fast', 'general_plus'],
'Real-CUGAN': ['conservative', 'no-denoise', 'denoise3x'],
};
const model = ref(ModelData[type.value][0]);
const modes = computed(() => {
return ModelData[type.value];
});
watch(type, val => {
model.value = ModelData[val][0];
});
// Scale
const ScaleData = [2, 4];
const scale = ref<number>(ScaleData[0]);
//tile size
const tileSizes = [32, 48, 64, 96, 128, 192, 256, 384, 512];
const tileSize = ref<number>(tileSizes[4]);
// overlap
const overlapList = [0, 4, 8, 12, 16, 20];
const overlap = ref<number>(overlapList[3]);
// run on
const runOnList = ['WebGL', 'WebGPU'];
const runOn = [runOnList[0]];
</script>
<style scoped lang="scss" src="./index.scss">

View File

@@ -4,8 +4,88 @@
width: 100%;
height: 100%;
.upscale-title {
font-size: 20px;
font-weight: bold;
margin-left: 5px;
}
.upscale-content {
width: 100%;
height: 100%;
margin-top: 5px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.upscale-content-left {
width: 49%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
.upscale-content-left-container {
width: 100%;
height: 100%;
overflow: auto;
.upscale-divider-title {
font-size: 13px;
color: rgba(126, 126, 135, 0.99);
}
.upscale-content-left-params {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.upscale-content-params-left {
width: 80%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.upscale-content-params-item {
width: 30%;
display: flex;
flex-direction: column;
justify-content: center;
.upscale-content-params-title {
font-size: 13px;
color: rgba(126, 126, 135, 0.99);
}
}
}
.upscale-content-params-right {
width: 20%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
}
}
}
.upscale-content-right {
width: 50%;
height: 100%;
.upscale-content-right-container {
width: 100%;
height: 100%;
overflow: auto;
}
}
}
}