🚧 developing
This commit is contained in:
4
components.d.ts
vendored
4
components.d.ts
vendored
@@ -31,6 +31,7 @@ declare module 'vue' {
|
||||
AInputGroup: typeof import('ant-design-vue/es')['InputGroup']
|
||||
AInputNumber: typeof import('ant-design-vue/es')['InputNumber']
|
||||
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
||||
AlbumShareModal: typeof import('./src/views/Album/Phoalbum/AlbumShareModal.vue')['default']
|
||||
AllPhoto: typeof import('./src/views/Photograph/AllPhoto/AllPhoto.vue')['default']
|
||||
AMenu: typeof import('ant-design-vue/es')['Menu']
|
||||
AMenuItem: typeof import('ant-design-vue/es')['MenuItem']
|
||||
@@ -42,6 +43,7 @@ declare module 'vue' {
|
||||
AProgress: typeof import('ant-design-vue/es')['Progress']
|
||||
AQrcode: typeof import('ant-design-vue/es')['QRCode']
|
||||
ARangePicker: typeof import('ant-design-vue/es')['RangePicker']
|
||||
ArrowDownOutlined: typeof import('@ant-design/icons-vue')['ArrowDownOutlined']
|
||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
||||
ASpin: typeof import('ant-design-vue/es')['Spin']
|
||||
@@ -70,6 +72,7 @@ declare module 'vue' {
|
||||
DownloadOutlined: typeof import('@ant-design/icons-vue')['DownloadOutlined']
|
||||
DownOutlined: typeof import('@ant-design/icons-vue')['DownOutlined']
|
||||
DynamicTitle: typeof import('./src/components/DynamicTitle/DynamicTitle.vue')['default']
|
||||
EditOutlined: typeof import('@ant-design/icons-vue')['EditOutlined']
|
||||
EyeInvisibleOutlined: typeof import('@ant-design/icons-vue')['EyeInvisibleOutlined']
|
||||
FileImageOutlined: typeof import('@ant-design/icons-vue')['FileImageOutlined']
|
||||
Folder: typeof import('./src/components/Folder/Folder.vue')['default']
|
||||
@@ -78,6 +81,7 @@ declare module 'vue' {
|
||||
ImageShare: typeof import('./src/views/Share/ImageShare/ImageShare.vue')['default']
|
||||
ImageToolbar: typeof import('./src/views/Photograph/ImageToolbar/ImageToolbar.vue')['default']
|
||||
ImageUpload: typeof import('./src/views/Photograph/ImageUpload/ImageUpload.vue')['default']
|
||||
ItalicOutlined: typeof import('@ant-design/icons-vue')['ItalicOutlined']
|
||||
LandingPage: typeof import('./src/views/Landing/LandingPage.vue')['default']
|
||||
LeftOutlined: typeof import('@ant-design/icons-vue')['LeftOutlined']
|
||||
LinkOutlined: typeof import('@ant-design/icons-vue')['LinkOutlined']
|
||||
|
1
public/provider_icon/ali.svg
Normal file
1
public/provider_icon/ali.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg t="1740245840658" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2464" width="200" height="200"><path d="M512 64a448 448 0 1 1 0 896A448 448 0 0 1 512 64z" fill="#FF6A00" p-id="2465"></path><path d="M324.8 602.624a26.752 26.752 0 0 1-21.312-25.92v-142.72a27.712 27.712 0 0 1 21.376-25.984l132.416-28.672 13.952-56.896H317.312a97.6 97.6 0 0 0-98.24 96.96v169.344c0.384 54.08 44.16 97.856 98.24 98.176h153.92l-13.888-56.512-132.544-27.776zM710.4 322.432c54.016 0.128 97.92 43.584 98.56 97.6v170.176a98.368 98.368 0 0 1-98.56 98.048H555.328l14.08-56.832 132.608-28.736a27.84 27.84 0 0 0 21.376-25.92v-142.72a26.88 26.88 0 0 0-21.376-25.984l-132.544-28.8-14.08-56.832zM570.368 497.92v13.952H457.28v-13.952h113.088z" fill="#FFFFFF" p-id="2466"></path></svg>
|
After Width: | Height: | Size: 803 B |
1
public/provider_icon/huawei.svg
Normal file
1
public/provider_icon/huawei.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg t="1740245977035" class="icon" viewBox="0 0 1027 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10116" width="200" height="200"><path d="M402.3125 208.25c16.875-5.62500027 33.75-8.4375 50.625-11.24999973 19.68749973 25.3125 25.3125 59.0625 33.75 89.99999946 5.62500027 33.75 11.24999973 67.5 11.24999973 101.25 5.62500027 22.50000027 2.81249973 47.81250027 2.81250054 70.31250054s-2.81249973 42.1875 0 64.68749946c0 30.93750027-2.81249973 59.0625-2.81250054 90.00000027-5.62500027 19.68749973 0 39.37500027-5.62499946 59.0625-8.4375-2.81249973-11.24999973-11.24999973-14.06250027-16.875-33.75-50.625-64.68750027-101.25-92.8125-154.68749973-28.12499973-56.25000027-56.25000027-112.49999973-59.0625-177.1875-5.62500027-50.625 28.12499973-98.43750027 75.9375-115.31250027z m174.37500027-8.4375c5.62500027-2.81249973 8.4375 0 14.06249946 0 22.50000027 5.62500027 47.81250027 8.4375 67.5 22.50000027s36.56249973 33.75 42.1875 56.24999946c8.4375 28.12499973 5.62500027 59.0625 0 87.18750054-8.4375 36.56249973-25.3125 70.31249973-42.1875 104.06249973-5.62500027 11.24999973-11.24999973 19.68749973-16.875 30.93750027-8.4375 19.68749973-22.50000027 39.37500027-33.75 59.0625-19.68749973 33.75-39.37500027 61.87499973-59.0625 95.62499973-2.81249973 2.81249973-5.62500027 11.24999973-11.24999973 5.62500027-2.81249973-33.75-5.62500027-67.5-8.4375-104.06250054-5.62500027-44.99999973-2.81249973-87.18749973-2.81249973-132.18749946 2.81249973-28.12499973 2.81249973-59.0625 5.62499946-87.18750054 5.62500027-33.75 11.24999973-70.31249973 22.50000027-104.06249973 11.24999973-8.4375 11.24999973-25.3125 22.50000027-33.75zM222.31250027 309.5c2.81249973 0 5.62500027 5.62500027 8.4375 8.4375 81.56250027 106.87500027 154.68749973 219.375 213.74999973 340.31249973 5.62500027 8.4375 11.24999973 19.68749973 11.24999973 30.93750027-11.24999973-2.81249973-19.68749973-8.4375-28.12499973-14.06250027-53.43749973-28.12499973-106.87500027-59.0625-160.3125-89.99999946-19.68749973-14.06250027-39.37500027-28.12499973-56.25000027-42.1875-33.75-22.50000027-56.25000027-64.68750027-53.43749973-106.87500027 2.81249973-50.625 30.93750027-92.8125 64.68750027-126.5625z m582.1875 0h5.62499946c14.06250027 19.68749973 33.75 39.37500027 45.00000054 61.87499973 11.24999973 19.68749973 16.875 44.99999973 19.68749973 67.5 0 25.3125-8.4375 53.43749973-28.12499973 73.12500027-11.24999973 11.24999973-19.68749973 22.50000027-33.75 30.93750027-64.68750027 50.625-135 90.00000027-208.12500027 126.5625-11.24999973 5.62500027-19.68749973 14.06250027-33.75 14.06249946 2.81249973-14.06250027 11.24999973-28.12499973 16.875-39.37499946 47.81250027-98.43750027 106.87500027-191.25000027 171.56249973-281.25000054 14.06250027-14.06250027 30.93750027-33.75 45.00000054-53.43749973z m-705.93750027 225.00000027c2.81249973-2.81249973 0-8.4375 5.62500027-11.25000054 8.4375 2.81249973 16.875 8.4375 22.49999946 11.25000054 101.25 56.25000027 202.5 112.49999973 300.93750027 174.37499946 2.81249973 2.81249973 5.62500027 5.62500027 5.62500027 8.4375H239.18750027c-39.37500027 0-75.9375-16.875-104.06250054-44.99999973-22.50000027-25.3125-42.1875-59.0625-44.99999973-92.8125 5.62500027-14.06250027 2.81249973-28.12499973 8.4375-44.99999973z m810-2.81250054c5.62500027-2.81249973 14.06250027-8.4375 19.68749973-5.62499946 0 14.06250027 5.62500027 30.93750027 5.62500027 44.99999973-2.81249973 19.68749973-2.81249973 36.56249973-11.24999973 53.43749973-5.62500027 14.06250027-14.06250027 30.93750027-25.3125 42.1875-14.06250027 11.24999973-22.50000027 25.3125-39.37500027 33.75-16.875 14.06250027-42.1875 16.875-61.87499973 19.68750054h-202.5c2.81249973-2.81249973 2.81249973-5.62500027 5.62499946-8.4375 101.25-64.68750027 205.31249973-123.75000027 309.37500027-180.00000054zM242 748.25c36.56249973-2.81249973 73.12500027 0 109.6875-5.62500027 25.3125 0 53.43749973-2.81249973 78.74999973 0-5.62500027 11.24999973-19.68749973 16.875-28.12499973 22.50000027-28.12499973 19.68749973-56.25000027 36.56249973-87.18749973 50.625s-67.5 8.4375-92.8125-11.24999973c-19.68749973-14.06250027-36.56249973-36.56249973-47.81250027-56.25000027h67.5z m357.18749973-5.62500027c25.3125-2.81249973 50.625 0 78.75000054 0 33.75 2.81249973 70.31249973 0 106.87499946 5.62500027 25.3125 2.81249973 50.625 0 73.12500027 2.81249973-8.4375 16.875-22.50000027 33.75-36.56249973 47.81250027-22.50000027 22.50000027-56.25000027 33.75-87.18750054 28.12499973-28.12499973-8.4375-50.625-25.3125-75.9375-39.37499946-14.06250027-8.4375-25.3125-16.875-39.37499946-25.3125-8.4375-8.4375-14.06250027-11.24999973-19.68750054-19.68750054z" fill="#C71F1E" p-id="10117"></path></svg>
|
After Width: | Height: | Size: 4.5 KiB |
1
public/provider_icon/minio.svg
Normal file
1
public/provider_icon/minio.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg t="1740245954753" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9138" width="200" height="200"><path d="M638.855218 56.525807s99.268136 159.838523 132.357514 216.623262a2.523766 2.523766 0 0 1 0 2.944394 2.383557 2.383557 0 0 1-3.50523 0L596.231612 97.326693l42.623606-40.800886z" fill="#dd113c" p-id="9139"></path><path d="M346.518971 639.655999a588.878771 588.878771 0 0 1 116.654081-165.446893 597.291325 597.291325 0 0 1 58.32704-51.176369v126.188308L346.518971 639.655999zM245.568325 756.590498l275.931767-140.209231v321.079139l62.112689 80.760517v-434.648616l37.716283-19.489084a187.179324 187.179324 0 0 0 51.456788-296.121896L530.753901 119.479752a31.547077 31.547077 0 0 1 1.542302-44.446327 31.687286 31.687286 0 0 1 44.586535 1.542302l19.909711 20.750966 42.062769-40.941095c-50.335114-65.337502-112.167385-57.065157-147.64032-24.396407a90.575163 90.575163 0 0 0-3.925859 127.870819l143.574253 149.60325a128.151237 128.151237 0 0 1-28.041846 197.414597l-19.489083 10.095065V314.090164A649.589368 649.589368 0 0 0 245.568325 755.889452v0.701046z" fill="#dd113c" p-id="9140"></path><path d="M583.612781 583.432097v65.617921l-62.112689 31.547077v-65.197293z" fill="#dd113c" p-id="9141"></path></svg>
|
After Width: | Height: | Size: 1.2 KiB |
1
public/provider_icon/tencent.svg
Normal file
1
public/provider_icon/tencent.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg t="1740245876441" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6099" width="200" height="200"><path d="M887.36 749.312c-18.176 18.048-50.752 38.528-104.128 40.32-24.704 0.896-53.504 0.96-66.688 0.96H429.696l205.696-199.808c9.472-9.216 30.72-29.568 49.152-46.08 40.32-36.288 76.544-43.584 102.208-43.328 40.192 0.384 76.8 16.768 102.848 43.264 55.936 57.152 54.592 148.48-2.24 204.672m68.736-269.696A236.16 236.16 0 0 0 787.2 408.32c-57.472 0-106.88 19.776-150.08 54.912-18.816 15.36-38.528 33.664-63.36 57.728-12.288 12.032-369.792 358.912-369.792 358.912 18.752 2.624 44.48 3.456 67.456 3.584 21.568 0.128 432.32 0.128 449.472 0.128 34.624 0 57.152-0.064 81.28-1.856 55.552-4.032 107.968-24.384 150.336-65.984a237.504 237.504 0 0 0 3.648-336.192z" fill="#00A3FF" p-id="6100"></path><path d="M379.328 457.28c-42.048-31.424-89.088-49.024-142.4-48.96a237.568 237.568 0 0 0-165.376 407.488c37.76 37.12 83.52 57.28 132.352 64.064l92.032-89.28c-14.848-0.064-36.224-0.256-55.168-0.896-53.376-1.856-85.888-22.336-104.128-40.32A145.024 145.024 0 0 1 134.4 544.64c26.112-26.496 62.72-42.88 102.848-43.264 25.216-0.128 59.392 7.168 98.048 39.232 18.432 15.296 59.392 51.2 77.312 67.456 0.896 0.832 2.048 0.896 3.072 0l63.36-61.824c1.152-1.024 1.088-2.496 0-3.456-30.528-27.52-73.728-66.112-99.712-85.504" fill="#00C8DC" p-id="6101"></path><path d="M811.968 354.688A318.336 318.336 0 0 0 512 142.656a318.72 318.72 0 0 0-314.368 268.992 236.608 236.608 0 0 1 92.992 3.008l0.96 0.192A225.28 225.28 0 0 1 512 235.776c89.984 0 168.896 54.272 204.48 131.136 0.576 1.216 1.536 1.6 2.496 1.344 26.752-7.36 58.88-11.648 89.792-9.344 3.072 0.192 4.224-1.472 3.2-4.224" fill="#006EFF" p-id="6102"></path></svg>
|
After Width: | Height: | Size: 1.7 KiB |
@@ -2,7 +2,7 @@ import {service} from "@/utils/alova/service.ts";
|
||||
import {uploadImageRequest} from "@/types/upscale";
|
||||
|
||||
export const uploadImage = (data: uploadImageRequest) => {
|
||||
return service.Post('/api/auth/upscale/phone/upload', {
|
||||
return service.Post('/api/auth/phone/upload', {
|
||||
image: data.image,
|
||||
access_token: data.access_token,
|
||||
user_id: data.user_id,
|
@@ -53,7 +53,7 @@ export const getFaceSamplesDetailList = (face_id: number, provider: string, buck
|
||||
ignoreToken: false,
|
||||
signature: false,
|
||||
},
|
||||
hitSource: ["modify-face-sample-name", "modify-face-sample-type"],
|
||||
hitSource: ["modify-face-sample-name", "modify-face-sample-type", "delete-images"],
|
||||
});
|
||||
};
|
||||
/**
|
||||
@@ -123,7 +123,7 @@ export const albumListApi = (type: number, sort: boolean) => {
|
||||
ignoreToken: false,
|
||||
signature: false,
|
||||
},
|
||||
hitSource: ["create-album", "rename-album", "delete-album"],
|
||||
hitSource: ["create-album", "rename-album", "delete-album", "album-share"],
|
||||
});
|
||||
};
|
||||
/**
|
||||
@@ -147,7 +147,7 @@ export const queryAlbumDetailListApi = (id: number, provider: string, bucket: st
|
||||
signature: false,
|
||||
},
|
||||
name: "album-detail-list",
|
||||
hitSource: ["upload-file", "delete-images"],
|
||||
hitSource: ["upload-file", "delete-images", "album-share"],
|
||||
});
|
||||
};
|
||||
|
||||
@@ -205,7 +205,7 @@ export const queryAllImagesApi = (type: string, sort: boolean, provider: string,
|
||||
ignoreToken: false,
|
||||
signature: false,
|
||||
},
|
||||
hitSource: ["upload-file", "delete-images"],
|
||||
hitSource: ["upload-file", "delete-images", "album-share"],
|
||||
});
|
||||
};
|
||||
|
||||
@@ -213,8 +213,11 @@ export const queryAllImagesApi = (type: string, sort: boolean, provider: string,
|
||||
/**
|
||||
* 获取最近照片列表
|
||||
*/
|
||||
export const queryRecentImagesApi = () => {
|
||||
return service.Post('/api/auth/storage/image/recent/list', {}, {
|
||||
export const queryRecentImagesApi = (provider: string, bucket: string) => {
|
||||
return service.Post('/api/auth/storage/image/recent/list', {
|
||||
provider: provider,
|
||||
bucket: bucket,
|
||||
}, {
|
||||
cacheFor: {
|
||||
expire: 60 * 60 * 24 * 7,
|
||||
mode: "restore",
|
||||
@@ -407,6 +410,31 @@ export const getBucketCapacityApi = (provider: string, bucket: string) => {
|
||||
ignoreToken: false,
|
||||
signature: false,
|
||||
},
|
||||
name: "delete-images",
|
||||
name: "get-bucket-capacity",
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 分享相册
|
||||
* @param id
|
||||
* @param expire_date
|
||||
* @param access_limit
|
||||
* @param access_password
|
||||
* @param provider
|
||||
* @param bucket
|
||||
*/
|
||||
export const albumShareApi = (id: number, expire_date: string, access_limit: number, access_password: string, provider: string, bucket: string) => {
|
||||
return service.Post('/api/auth/storage/album/share', {
|
||||
id: id,
|
||||
expire_date: expire_date,
|
||||
access_limit: access_limit,
|
||||
access_password: access_password,
|
||||
provider: provider,
|
||||
bucket: bucket,
|
||||
}, {
|
||||
meta: {
|
||||
ignoreToken: false,
|
||||
signature: false,
|
||||
},
|
||||
name: "album-share",
|
||||
});
|
||||
};
|
||||
|
@@ -80,3 +80,13 @@ html {
|
||||
.ant-table-wrapper .ant-table:not(.ant-table-bordered) .ant-table-tbody > tr:last-child > td {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
// 空白内容样式
|
||||
.empty-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
1
src/assets/svgs/oss.svg
Normal file
1
src/assets/svgs/oss.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg t="1740246256617" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19370" width="200" height="200"><path d="M622.08 162.816c-164.352 0-302.08 113.152-339.456 265.728-3.584 0-6.656-0.512-10.24-0.512-119.296 0-216.064 96.768-216.064 216.064 0 57.344 22.528 112.128 63.488 152.576 40.448 40.448 95.744 63.488 153.088 63.488s112.64-23.04 153.088-63.488c33.792-33.792 52.736-79.36 58.368-129.536l-78.336-6.144c-17.92-2.048-23.552-15.872-12.8-30.208l132.608-164.352c10.752-14.336 25.088-12.8 32.256 4.096l75.264 183.808c7.168 16.384-2.048 28.16-19.456 26.112l-58.368-5.12c-6.656 60.928-33.792 114.688-72.192 157.184 44.032 18.944 91.136 28.672 138.752 28.672 193.024 0 349.184-156.672 349.184-349.184s-156.16-349.184-349.184-349.184z" fill="#999999" p-id="19371"></path></svg>
|
After Width: | Height: | Size: 819 B |
1
src/assets/svgs/wenhao.svg
Normal file
1
src/assets/svgs/wenhao.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg t="1740249125892" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="27758" width="200" height="200"><path d="M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" fill="#EFEFF4" p-id="27759"></path><path d="M512 814.545455a302.545455 302.545455 0 0 1-213.934545-516.48 302.545455 302.545455 0 1 1 427.86909 427.86909A300.555636 300.555636 0 0 1 512 814.545455z m0-186.379637a49.850182 49.850182 0 1 0 49.838545 49.838546 49.896727 49.896727 0 0 0-49.838545-49.838546z m-19.362909-281.530182a46.289455 46.289455 0 0 0-45.975273 51.549091l19.374546 169.157818a46.277818 46.277818 0 0 0 91.927272 0l19.362909-169.169454a46.277818 46.277818 0 0 0-45.975272-51.549091z" fill="#D2D2D8" p-id="27760"></path></svg>
|
After Width: | Height: | Size: 760 B |
6
src/constant/provider_icon.ts
Normal file
6
src/constant/provider_icon.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const ProviderIcon = {
|
||||
"ali": "/provider_icon/ali.svg",
|
||||
"tencent": "/provider_icon/tencent.svg",
|
||||
"minio": "/provider_icon/minio.svg",
|
||||
"huawei": "/provider_icon/huawei.svg",
|
||||
};
|
@@ -58,10 +58,10 @@
|
||||
</AFlex>
|
||||
|
||||
</div>
|
||||
<div class="header-logo-popover-card" @click="router.push('/main/photo/upscale')">
|
||||
<div class="header-logo-popover-card" @click="router.push('/main/photo/phone')">
|
||||
<AFlex :vertical="false" align="center" justify="space-between">
|
||||
<AAvatar size="small" shape="square" :src="ai"/>
|
||||
<span class="header-logo-popover-text">{{ t('album.upscale') }}</span>
|
||||
<span class="header-logo-popover-text">{{ t('album.phone') }}</span>
|
||||
</AFlex>
|
||||
|
||||
</div>
|
||||
|
@@ -2,13 +2,23 @@
|
||||
<AFlex :vertical="false" align="center" justify="flex-end" class="header-menu-container">
|
||||
<AFlex :vertical="false" align="center" justify="flex-start" class="header-menu-item" gap="large">
|
||||
<!-- 存储选择 -->
|
||||
<div class="header-select-container">
|
||||
<ACascader v-model:value="uploadStore.storageSelected"
|
||||
:options="configList"
|
||||
:show-search="{ filter }"
|
||||
:field-names="{ label: 'name', value: 'value', children: 'children' }"
|
||||
placeholder="选择存储桶">
|
||||
</ACascader>
|
||||
<div class="button-wrapper">
|
||||
<APopover :arrow="false" trigger="click" placement="right">
|
||||
<template #content>
|
||||
<ACascader v-model:value="uploadStore.storageSelected"
|
||||
:options="configList"
|
||||
:bordered="false"
|
||||
style="width: 100%"
|
||||
:field-names="{ label: 'name', value: 'value', children: 'children' }"
|
||||
placeholder="选择存储桶">
|
||||
</ACascader>
|
||||
</template>
|
||||
<AButton type="text" shape="circle" size="large" class="header-menu-item-btn">
|
||||
<template #icon>
|
||||
<AAvatar size="default" shape="circle" :src="ProviderIcon[uploadStore.storageSelected?.[0]]? ProviderIcon[uploadStore.storageSelected?.[0]] : wenhao"/>
|
||||
</template>
|
||||
</AButton>
|
||||
</APopover>
|
||||
</div>
|
||||
|
||||
<!-- 社区按钮 -->
|
||||
@@ -141,15 +151,17 @@ import systemMessage from "@/assets/svgs/sys-msg.svg";
|
||||
import personalCenter from "@/assets/svgs/personal-center.svg";
|
||||
import accountSetting from "@/assets/svgs/setting.svg";
|
||||
import logout from "@/assets/svgs/logout.svg";
|
||||
import wenhao from "@/assets/svgs/wenhao.svg";
|
||||
|
||||
import useStore from "@/store";
|
||||
import ImageUpload from "@/views/Photograph/ImageUpload/ImageUpload.vue";
|
||||
import {getStorageConfigListApi} from "@/api/storage";
|
||||
import type {ShowSearchType} from 'ant-design-vue/es/cascader';
|
||||
import {ProviderIcon} from "@/constant/provider_icon.ts";
|
||||
|
||||
|
||||
const uploadStore = useStore().upload;
|
||||
const user = useStore().user;
|
||||
|
||||
|
||||
const configList = ref<any[]>([]);
|
||||
|
||||
async function getUserConfigList() {
|
||||
@@ -159,10 +171,6 @@ async function getUserConfigList() {
|
||||
}
|
||||
}
|
||||
|
||||
const filter: ShowSearchType['filter'] = (inputValue, path) => {
|
||||
return path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
|
||||
};
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
getUserConfigList();
|
||||
|
@@ -1,11 +1,20 @@
|
||||
export default [
|
||||
{
|
||||
path: '/upscale/app',
|
||||
path: '/main/upscale/phone/app',
|
||||
name: 'upscaleApp',
|
||||
component: () => import('@/views/Phone/UpscalePhoneUpload/UpscalePhoneUpload.vue'),
|
||||
meta: {
|
||||
requiresAuth: false,
|
||||
title: '手机上传'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/main/share/phone/app',
|
||||
name: 'shareApp',
|
||||
component: () => import('@/views/Phone/SharePhoneUpload/SharePhoneUpload.vue'),
|
||||
meta: {
|
||||
requiresAuth: false,
|
||||
title: '手机上传'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@@ -1,6 +1,6 @@
|
||||
export default [
|
||||
{
|
||||
path: '/main/photo/upscale',
|
||||
path: '/main/photo/phone',
|
||||
name: 'upscale',
|
||||
component: () => import('@/views/Upscale/index.vue'),
|
||||
meta: {
|
||||
|
@@ -18,6 +18,13 @@ export const useImageStore = defineStore(
|
||||
"gif": "动图",
|
||||
"screenshot": "截图",
|
||||
});
|
||||
// 清算模式切换
|
||||
const switchValue = ref<boolean>(false);
|
||||
|
||||
// 相册分享弹窗相关
|
||||
const openAlbumShareDialog = ref<boolean>(false);
|
||||
const albumShareCoverImage = ref<string>("");
|
||||
const albumShareId = ref<number>(0);
|
||||
|
||||
/**
|
||||
* 统计图片总数
|
||||
@@ -31,13 +38,24 @@ export const useImageStore = defineStore(
|
||||
return imageList.reduce((total, record) => total + record.list.length, 0);
|
||||
}
|
||||
|
||||
function openAlbumShareDialogHandler(value: boolean, coverImage: string, albumId: number) {
|
||||
openAlbumShareDialog.value = value;
|
||||
albumShareCoverImage.value = coverImage;
|
||||
albumShareId.value = albumId;
|
||||
}
|
||||
|
||||
return {
|
||||
selected,
|
||||
tabActiveKey,
|
||||
tabMap,
|
||||
homeTabMap,
|
||||
switchValue,
|
||||
homeTabActiveKey,
|
||||
countTotalImages
|
||||
albumShareCoverImage,
|
||||
albumShareId,
|
||||
countTotalImages,
|
||||
openAlbumShareDialog,
|
||||
openAlbumShareDialogHandler,
|
||||
};
|
||||
},
|
||||
{
|
||||
@@ -46,7 +64,7 @@ export const useImageStore = defineStore(
|
||||
persist: true,
|
||||
storage: localStorage,
|
||||
key: 'image',
|
||||
includePaths: ["tabActiveKey", "tabMap", "homeTabActiveKey", "homeTabMap"],
|
||||
includePaths: ["tabActiveKey", "tabMap", "homeTabActiveKey", "homeTabMap", "switchValue"],
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@@ -15,7 +15,6 @@ interface UploadPredictResult {
|
||||
thumb_size: number | null;
|
||||
}
|
||||
|
||||
|
||||
export const useUploadStore = defineStore(
|
||||
'upload',
|
||||
() => {
|
||||
@@ -38,6 +37,8 @@ export const useUploadStore = defineStore(
|
||||
|
||||
const storageSelected = ref<any[]>([]);
|
||||
|
||||
const albumSelected = ref<number>();
|
||||
|
||||
/**
|
||||
* 打开上传抽屉
|
||||
*/
|
||||
@@ -70,6 +71,7 @@ export const useUploadStore = defineStore(
|
||||
storageSelected,
|
||||
openUploadDrawerFn,
|
||||
clearPredictResult,
|
||||
albumSelected,
|
||||
};
|
||||
},
|
||||
{
|
||||
@@ -78,7 +80,7 @@ export const useUploadStore = defineStore(
|
||||
persist: true,
|
||||
storage: localStorage,
|
||||
key: 'upload',
|
||||
includePaths: ["storageSelected"]
|
||||
includePaths: ["storageSelected", "albumSelected"]
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@@ -42,8 +42,8 @@
|
||||
</AImagePreviewGroup>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<AEmpty :image="empty">
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty" :image-style="{width: '100%', height: '100%'}">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
暂无照片,快去上传吧
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<AButton type="link" size="large" class="location-album-button">地点</AButton>
|
||||
<span class="location-album-count">你一共在{{ locationAlbums ? locationAlbums.length : 0 }}个地点留下足迹</span>
|
||||
</div>
|
||||
<div class="location-album-content">
|
||||
<div class="location-album-content" v-if="locationAlbums && locationAlbums.length>0 ">
|
||||
<div class="location-album-content-item" v-for="(item, index) in locationAlbums" :key="index">
|
||||
<span class="location-album-description">{{ item.location }}</span>
|
||||
<div class="location-album-location-list">
|
||||
@@ -20,17 +20,27 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty" :image-style="{width: '100%', height: '100%'}">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
暂无照片,快去上传吧
|
||||
</span>
|
||||
</template>
|
||||
</AEmpty>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {queryLocationAlbumApi} from "@/api/storage";
|
||||
import useStore from "@/store";
|
||||
import empty from "@/assets/svgs/empty.svg";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const upload = useStore().upload;
|
||||
|
||||
function handleClick(id: number,name: string) {
|
||||
function handleClick(id: number, name: string) {
|
||||
router.push({path: route.path + `/${id}`, query: {name: name}});
|
||||
}
|
||||
|
||||
|
@@ -10,7 +10,7 @@
|
||||
</AButton>
|
||||
</div>
|
||||
<div class="people-album-detail-toolbar">
|
||||
<AAvatar shape="circle" size="default"></AAvatar>
|
||||
<AAvatar shape="circle" size="default" :src="route.query.thumb"></AAvatar>
|
||||
<span style="font-size: 14px;color: #333333">{{ route.query.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -19,7 +19,7 @@
|
||||
<span style="font-size: 14px;color: #999999">共{{ imageStore.countTotalImages(images) }}张照片</span>
|
||||
</div>
|
||||
<div class="people-album-detail-list">
|
||||
<div style="width:100%;height:100%;" v-if="images.length !== 0">
|
||||
<div style="width:100%;height:100%;" v-if="images &&images.length !== 0">
|
||||
<div v-for="(itemList, index) in images" :key="index">
|
||||
<span style="margin-left: 10px;font-size: 13px">{{ itemList.date }}</span>
|
||||
<AImagePreviewGroup>
|
||||
@@ -49,8 +49,8 @@
|
||||
</AImagePreviewGroup>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<AEmpty :image="empty">
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty" :image-style="{width: '100%', height: '100%'}">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
暂无照片,快去上传吧
|
||||
|
@@ -50,12 +50,12 @@
|
||||
</div>
|
||||
</transition>
|
||||
<div class="people-album-container">
|
||||
<ASpin :spinning="loading" size="large" wrapperClassName="people-album-container">
|
||||
<div class="people-album-content">
|
||||
<ASpin :spinning="loading" size="large" wrapperClassName="spin-container">
|
||||
<div class="people-album-content" v-if="faceList.length !== 0">
|
||||
<CheckCard
|
||||
v-for="(item, index) in faceList"
|
||||
:key="index"
|
||||
@click="handleClick(item.id, item.face_name)"
|
||||
@click="handleClick(item.id, item.face_name, item.face_image)"
|
||||
class="photo-item"
|
||||
margin="0"
|
||||
border-radius="0"
|
||||
@@ -115,12 +115,22 @@
|
||||
</CheckCard>
|
||||
|
||||
</div>
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty" :image-style="{width: '100%', height: '100%'}">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
暂无照片,快去上传吧
|
||||
</span>
|
||||
</template>
|
||||
</AEmpty>
|
||||
</div>
|
||||
</ASpin>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {getFaceSamplesList, modifyFaceSampleName, modifyFaceTypeBatch} from "@/api/storage";
|
||||
import empty from "@/assets/svgs/empty.svg";
|
||||
|
||||
|
||||
const faceList = ref<any[]>([]);
|
||||
@@ -217,9 +227,10 @@ const router = useRouter();
|
||||
* 点击人物跳转到详情页
|
||||
* @param id
|
||||
* @param name
|
||||
* @param thumb
|
||||
*/
|
||||
function handleClick(id: number, name: string | null) {
|
||||
router.push({path: route.path + `/${id}`, query: {name: name}});
|
||||
function handleClick(id: number, name: string | null,thumb: string | null) {
|
||||
router.push({path: route.path + `/${id}`, query: {name: name, thumb: thumb}});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@@ -332,6 +343,13 @@ onMounted(() => {
|
||||
align-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.spin-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.people-album-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
116
src/views/Album/Phoalbum/AlbumShareModal.vue
Normal file
116
src/views/Album/Phoalbum/AlbumShareModal.vue
Normal file
@@ -0,0 +1,116 @@
|
||||
<template>
|
||||
<AModal v-model:open="imageStore.openAlbumShareDialog" :footer="null" width="25%"
|
||||
@cancel="imageStore.openAlbumShareDialogHandler(false, '', 0)">
|
||||
<div class="share-modal">
|
||||
<div class="share-modal-title">
|
||||
<h3>分享相册</h3>
|
||||
</div>
|
||||
<AAvatar shape="square" :size="200">
|
||||
<template #icon>
|
||||
<AImage :preview="false" width="100%" height="100%"
|
||||
:src="imageStore.albumShareCoverImage?imageStore.albumShareCoverImage:default_cover"/>
|
||||
</template>
|
||||
</AAvatar>
|
||||
<div class="album-share-select">
|
||||
<div class="album-share-select-item">
|
||||
<span class="label-text">访问时效</span>
|
||||
<ASelect style="width: 50%" placeholder="请选择" :defaultValue="1" v-model:value="expire_date">
|
||||
<ASelectOption value="1">1天</ASelectOption>
|
||||
<ASelectOption value="3">3天</ASelectOption>
|
||||
<ASelectOption value="7">7天</ASelectOption>
|
||||
<ASelectOption value="15">15天</ASelectOption>
|
||||
<ASelectOption value="30">30天</ASelectOption>
|
||||
<ASelectOption value="0">永久</ASelectOption>
|
||||
</ASelect>
|
||||
</div>
|
||||
<div class="album-share-select-item">
|
||||
<span class="label-text">访问密码</span>
|
||||
<AInputPassword style="width: 50%" v-model:value="access_password" :maxlength="10"
|
||||
:showCount="true"></AInputPassword>
|
||||
</div>
|
||||
<div class="album-share-select-item">
|
||||
<span class="label-text">访问限制</span>
|
||||
<AInputNumber style="width: 50%" :defaultValue="100" :min="1"
|
||||
v-model:value="access_limit"></AInputNumber>
|
||||
</div>
|
||||
</div>
|
||||
<AButton type="primary" size="large" shape="round" style="width: 100%" @click="createShare">
|
||||
<template #icon>
|
||||
<PlusSquareOutlined/>
|
||||
</template>
|
||||
创建分享
|
||||
</AButton>
|
||||
</div>
|
||||
</AModal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import useStore from "@/store";
|
||||
import default_cover from "@/assets/images/default-cover.png";
|
||||
import {albumShareApi} from "@/api/storage";
|
||||
import {message} from "ant-design-vue";
|
||||
|
||||
const imageStore = useStore().image;
|
||||
const upload = useStore().upload;
|
||||
|
||||
const expire_date = ref<string>("1");
|
||||
|
||||
const access_limit = ref<number>(100);
|
||||
|
||||
const access_password = ref<string>("");
|
||||
|
||||
/**
|
||||
* 创建分享
|
||||
*/
|
||||
async function createShare() {
|
||||
const res: any = await albumShareApi(
|
||||
imageStore.albumShareId,
|
||||
expire_date.value,
|
||||
access_limit.value,
|
||||
access_password.value,
|
||||
upload.storageSelected?.[0],
|
||||
upload.storageSelected?.[1]
|
||||
);
|
||||
if (res && res.code === 200) {
|
||||
imageStore.openAlbumShareDialogHandler(false, '', 0);
|
||||
message.success("分享成功");
|
||||
} else {
|
||||
message.error("分享失败");
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.share-modal {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
|
||||
.album-share-select {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
.album-share-select-item {
|
||||
width: 100%;
|
||||
height: 5vh;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
|
||||
.label-text {
|
||||
width: 50%;
|
||||
color: #999999;
|
||||
font-size: 2.2vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -1,31 +1,45 @@
|
||||
<template>
|
||||
<div class="phoalbum-detail">
|
||||
<div class="phoalbum-detail-header">
|
||||
<AButton type="primary" shape="round" size="middle">
|
||||
<AButton type="primary" shape="round" size="middle" @click="openUploadModal()">
|
||||
<template #icon>
|
||||
<PlusSquareOutlined/>
|
||||
<CloudUploadOutlined/>
|
||||
</template>
|
||||
上传
|
||||
</AButton>
|
||||
<AButton type="default" shape="round" size="middle">
|
||||
<template #icon>
|
||||
<PlusSquareOutlined/>
|
||||
<APopover placement="right" trigger="click">
|
||||
<AButton type="default" shape="round" size="middle">
|
||||
<template #icon>
|
||||
<EditOutlined/>
|
||||
</template>
|
||||
重命名
|
||||
</AButton>
|
||||
<template #content>
|
||||
<AInput :placeholder="route.query.name"
|
||||
v-model:value="albumRenameValue">
|
||||
<template #suffix>
|
||||
<AButton type="text" @click.prevent size="small" style="color: #0e87cc"
|
||||
@click="renameAlbum(albumRenameValue)">
|
||||
确认
|
||||
</AButton>
|
||||
</template>
|
||||
</AInput>
|
||||
</template>
|
||||
重命名
|
||||
</AButton>
|
||||
<AButton type="default" shape="round" size="middle">
|
||||
</APopover>
|
||||
<AButton type="default" shape="round" size="middle" @click="deleteAlbum">
|
||||
<template #icon>
|
||||
<PlusSquareOutlined/>
|
||||
<DeleteOutlined/>
|
||||
</template>
|
||||
删除相册
|
||||
</AButton>
|
||||
<AButton type="default" shape="round" size="middle">
|
||||
<template #icon>
|
||||
<PlusSquareOutlined/>
|
||||
<DownloadOutlined/>
|
||||
</template>
|
||||
下载相册
|
||||
</AButton>
|
||||
</div>
|
||||
<ImageUpload/>
|
||||
<ImageToolbar :selected="imageStore.selected" :image-list="albumList"/>
|
||||
<div class="phoalbum-detail-content">
|
||||
<div class="phoalbum-detail-content-nav">
|
||||
@@ -45,7 +59,7 @@
|
||||
<span>相册描述</span>
|
||||
</div>
|
||||
<div class="phoalbum-detail-content-list">
|
||||
<div style="width:100%;height:100%;" v-if="albumList.length !== 0">
|
||||
<div style="width:100%;height:100%;" v-if="albumList && albumList.length !== 0">
|
||||
<div v-for="(itemList, index) in albumList" :key="index">
|
||||
<span style="margin-left: 10px;font-size: 13px">{{ itemList.date }}</span>
|
||||
<AImagePreviewGroup>
|
||||
@@ -75,7 +89,7 @@
|
||||
</AImagePreviewGroup>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
@@ -91,10 +105,12 @@
|
||||
<script setup lang="ts">
|
||||
import Vue3JustifiedLayout from "vue3-justified-layout";
|
||||
import 'vue3-justified-layout/dist/style.css';
|
||||
import {queryAlbumDetailListApi} from "@/api/storage";
|
||||
import {deleteAlbumApi, queryAlbumDetailListApi, renameAlbumApi} from "@/api/storage";
|
||||
import ImageToolbar from "@/views/Photograph/ImageToolbar/ImageToolbar.vue";
|
||||
import useStore from "@/store";
|
||||
import empty from "@/assets/svgs/empty.svg";
|
||||
import ImageUpload from "@/views/Photograph/ImageUpload/ImageUpload.vue";
|
||||
import {message} from "ant-design-vue";
|
||||
|
||||
|
||||
const imageStore = useStore().image;
|
||||
@@ -121,6 +137,47 @@ onMounted(() => {
|
||||
getAlbumList(parseInt(albumId, 10));
|
||||
});
|
||||
|
||||
function openUploadModal(): void {
|
||||
upload.openUploadDrawerFn();
|
||||
const idParam = route.params.id;
|
||||
const albumId = Array.isArray(idParam) ? idParam[0] : idParam;
|
||||
upload.albumSelected = parseInt(albumId);
|
||||
}
|
||||
|
||||
const albumRenameValue = ref<string>("");
|
||||
|
||||
/**
|
||||
* 重命名相册
|
||||
* @param name
|
||||
*/
|
||||
async function renameAlbum(name: string) {
|
||||
if (name.trim() === "") {
|
||||
message.warning("相册名称不能为空");
|
||||
return;
|
||||
}
|
||||
const idParam = route.params.id;
|
||||
const albumId = Array.isArray(idParam) ? idParam[0] : idParam;
|
||||
const res: any = await renameAlbumApi(parseInt(albumId), name);
|
||||
if (res && res.code === 200) {
|
||||
albumRenameValue.value = "";
|
||||
goBack();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除相册
|
||||
*/
|
||||
async function deleteAlbum() {
|
||||
const idParam = route.params.id;
|
||||
const id = Array.isArray(idParam) ? idParam[0] : idParam;
|
||||
const res: any = await deleteAlbumApi(parseInt(id));
|
||||
if (res && res.code === 200) {
|
||||
goBack();
|
||||
} else {
|
||||
message.error("删除相册失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回上一页
|
||||
*/
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="phoalbum">
|
||||
<div class="phoalbum-header">
|
||||
<APopover placement="bottom" trigger="click">
|
||||
<APopover placement="right" trigger="click">
|
||||
<AButton type="primary" shape="round" size="middle">
|
||||
<template #icon>
|
||||
<PlusSquareOutlined/>
|
||||
@@ -10,16 +10,15 @@
|
||||
</AButton>
|
||||
<template #content>
|
||||
<span style="color: #999; font-size: 15px;">创建相册</span>
|
||||
<AInputGroup compact style="display: flex;flex-direction: row;margin-top: 15px">
|
||||
<AInput placeholder="请填写相册名称" class="phoalbum-create-input"
|
||||
v-model:value="albumNameValue" size="large">
|
||||
<template #suffix>
|
||||
<AButton type="text" @click.prevent size="middle" style="color: #0e87cc" @click="createAlbumSubmit">
|
||||
确认
|
||||
</AButton>
|
||||
</template>
|
||||
</AInput>
|
||||
</AInputGroup>
|
||||
<AInput placeholder="请填写相册名称" class="phoalbum-create-input"
|
||||
style="margin-top: 15px"
|
||||
v-model:value="albumNameValue" size="large">
|
||||
<template #suffix>
|
||||
<AButton type="text" @click.prevent size="middle" style="color: #0e87cc" @click="createAlbumSubmit">
|
||||
确认
|
||||
</AButton>
|
||||
</template>
|
||||
</AInput>
|
||||
</template>
|
||||
|
||||
</APopover>
|
||||
@@ -57,8 +56,8 @@
|
||||
style="color: #999; font-size: 12px;">已全部加载,共 {{ albumList ? albumList.length : 0 }} 个相册</span>
|
||||
</template>
|
||||
<ATabPane key="-1" :tab="imageStore.tabMap[-1]">
|
||||
<ASpin tip="Loading..." :spinning="loading" size="large">
|
||||
<div class="phoalbum-item-container">
|
||||
<ASpin tip="Loading..." :spinning="loading" size="large" wrapperClassName="spin-container">
|
||||
<div class="phoalbum-item-container" v-if="albumList && albumList.length != 0">
|
||||
<div class="phoalbum-item"
|
||||
v-for="(album, index) in albumList"
|
||||
:key="album.id"
|
||||
@@ -95,7 +94,10 @@
|
||||
</AInput>
|
||||
</template>
|
||||
</APopover>
|
||||
<AMenuItem key="2">分享相册</AMenuItem>
|
||||
<AMenuItem key="2"
|
||||
@click.prevent="imageStore.openAlbumShareDialogHandler(true,album.cover_image ?`data:image/png;base64,`+album.cover_image: ``,album.id)">
|
||||
分享相册
|
||||
</AMenuItem>
|
||||
<AMenuItem key="3" @click.prevent="deleteAlbum(album.id)">删除相册</AMenuItem>
|
||||
<AMenuItem key="4">下载相册</AMenuItem>
|
||||
</AMenu>
|
||||
@@ -104,11 +106,20 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty" :image-style="{ width: '100%', height: '100%' }">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
暂无相册,快去创建一个吧!
|
||||
</span>
|
||||
</template>
|
||||
</AEmpty>
|
||||
</div>
|
||||
</ASpin>
|
||||
</ATabPane>
|
||||
<ATabPane key="0" :tab="imageStore.tabMap[0]">
|
||||
<ASpin tip="Loading..." :spinning="loading" size="large">
|
||||
<div class="phoalbum-item-container">
|
||||
<ASpin tip="Loading..." :spinning="loading" size="large" wrapperClassName="spin-container">
|
||||
<div class="phoalbum-item-container" v-if="albumList && albumList.length != 0">
|
||||
<div class="phoalbum-item"
|
||||
v-for="(album, index) in albumList"
|
||||
:key="album.id"
|
||||
@@ -145,7 +156,10 @@
|
||||
</AInput>
|
||||
</template>
|
||||
</APopover>
|
||||
<AMenuItem key="2">分享相册</AMenuItem>
|
||||
<AMenuItem key="2"
|
||||
@click.prevent="imageStore.openAlbumShareDialogHandler(true,album.cover_image ?`data:image/png;base64,`+album.cover_image: ``,album.id)">
|
||||
分享相册
|
||||
</AMenuItem>
|
||||
<AMenuItem key="3" @click.prevent="deleteAlbum(album.id)">删除相册</AMenuItem>
|
||||
<AMenuItem key="4">下载相册</AMenuItem>
|
||||
</AMenu>
|
||||
@@ -154,11 +168,20 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty" :image-style="{ width: '100%', height: '100%' }">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
暂无相册,快去创建一个吧!
|
||||
</span>
|
||||
</template>
|
||||
</AEmpty>
|
||||
</div>
|
||||
</ASpin>
|
||||
</ATabPane>
|
||||
<ATabPane key="1" :tab="imageStore.tabMap[1]">
|
||||
<ASpin tip="Loading..." :spinning="loading" size="large">
|
||||
<div class="phoalbum-item-container">
|
||||
<ASpin tip="Loading..." :spinning="loading" size="large" wrapperClassName="spin-container">
|
||||
<div class="phoalbum-item-container" v-if="albumList && albumList.length != 0">
|
||||
<div class="phoalbum-item"
|
||||
v-for="(album, index) in albumList"
|
||||
:key="album.id"
|
||||
@@ -195,7 +218,10 @@
|
||||
</AInput>
|
||||
</template>
|
||||
</APopover>
|
||||
<AMenuItem key="2">分享相册</AMenuItem>
|
||||
<AMenuItem key="2"
|
||||
@click.prevent="imageStore.openAlbumShareDialogHandler(true,album.cover_image ?`data:image/png;base64,`+album.cover_image: ``,album.id)">
|
||||
分享相册
|
||||
</AMenuItem>
|
||||
<AMenuItem key="3" @click.prevent="deleteAlbum(album.id)">删除相册</AMenuItem>
|
||||
<AMenuItem key="4">下载相册</AMenuItem>
|
||||
</AMenu>
|
||||
@@ -204,11 +230,20 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty" :image-style="{ width: '100%', height: '100%' }">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
暂无相册,快去创建一个吧!
|
||||
</span>
|
||||
</template>
|
||||
</AEmpty>
|
||||
</div>
|
||||
</ASpin>
|
||||
</ATabPane>
|
||||
<ATabPane key="2" :tab="imageStore.tabMap[2]">
|
||||
<ASpin tip="Loading..." :spinning="loading" size="large">
|
||||
<div class="phoalbum-item-container">
|
||||
<ASpin tip="Loading..." :spinning="loading" size="large" wrapperClassName="spin-container">
|
||||
<div class="phoalbum-item-container" v-if="albumList && albumList.length != 0">
|
||||
<div class="phoalbum-item"
|
||||
v-for="(album, index) in albumList"
|
||||
:key="album.id"
|
||||
@@ -245,7 +280,10 @@
|
||||
</AInput>
|
||||
</template>
|
||||
</APopover>
|
||||
<AMenuItem key="2">分享相册</AMenuItem>
|
||||
<AMenuItem key="2"
|
||||
@click.prevent="imageStore.openAlbumShareDialogHandler(true,album.cover_image ?`data:image/png;base64,`+album.cover_image: ``,album.id)">
|
||||
分享相册
|
||||
</AMenuItem>
|
||||
<AMenuItem key="3" @click.prevent="deleteAlbum(album.id)">删除相册</AMenuItem>
|
||||
<AMenuItem key="4">下载相册</AMenuItem>
|
||||
</AMenu>
|
||||
@@ -254,10 +292,20 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty" :image-style="{ width: '100%', height: '100%' }">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
暂无相册,快去创建一个吧!
|
||||
</span>
|
||||
</template>
|
||||
</AEmpty>
|
||||
</div>
|
||||
</ASpin>
|
||||
</ATabPane>
|
||||
</ATabs>
|
||||
</div>
|
||||
<AlbumShareModal/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
@@ -266,6 +314,8 @@ import {albumListApi, createAlbumApi, deleteAlbumApi, renameAlbumApi} from "@/ap
|
||||
import {message} from "ant-design-vue";
|
||||
import default_cover from "@/assets/images/default-cover.png";
|
||||
import useStore from "@/store";
|
||||
import empty from "@/assets/svgs/empty.svg";
|
||||
import AlbumShareModal from "@/views/Album/Phoalbum/AlbumShareModal.vue";
|
||||
|
||||
const isHovered = ref<number | null>(null);
|
||||
|
||||
@@ -413,6 +463,15 @@ onMounted(() => {
|
||||
width: 100%;
|
||||
height: calc(100% - 65px);
|
||||
|
||||
.spin-container {
|
||||
position: relative;
|
||||
transition: opacity 0.3s;
|
||||
width: 100%;
|
||||
height: 70vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.phoalbum-item-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<AButton type="link" size="large" class="thing-album-button">事物</AButton>
|
||||
|
||||
</div>
|
||||
<div class="thing-album-content">
|
||||
<div class="thing-album-content" v-if="thingAlbumList && thingAlbumList.length>0">
|
||||
<div class="thing-album-content-item" v-for="(item, index) in thingAlbumList" :key="index">
|
||||
<span class="thing-album-title">{{ getZhCategoryNameByEnName(item.category) }}</span>
|
||||
<div class="thing-album-wrapper">
|
||||
@@ -21,6 +21,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty" :image-style="{width: '100%', height: '100%'}">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
暂无照片,快去上传吧
|
||||
</span>
|
||||
</template>
|
||||
</AEmpty>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
@@ -29,6 +38,7 @@
|
||||
import {queryThingAlbumApi} from "@/api/storage";
|
||||
import {getZhCategoryNameByEnName, getZhLabelNameByEnName} from "@/constant/coco_ssd_label_category.ts";
|
||||
import useStore from "@/store";
|
||||
import empty from "@/assets/svgs/empty.svg";
|
||||
|
||||
const thingAlbumList = ref<any[]>([]);
|
||||
|
||||
|
@@ -1,9 +1,180 @@
|
||||
<template>
|
||||
|
||||
<div class="upscale-upload-content">
|
||||
<AUploadDragger
|
||||
name="file"
|
||||
accept="image/*"
|
||||
:multiple="true"
|
||||
:directory="false"
|
||||
:maxCount="1"
|
||||
:beforeUpload="beforeUpload"
|
||||
:fileList="fileList"
|
||||
:loading="uploading"
|
||||
:showUploadList="true">
|
||||
<div class="upscale-upload-content-main">
|
||||
<ABadge :offset="[-10, 10]">
|
||||
<template #count>
|
||||
<AAvatar :size="25" :src="sueccess" v-if="fileList.length > 0"/>
|
||||
<AAvatar :size="25" :src="warn" v-if="fileList.length === 0"/>
|
||||
</template>
|
||||
<AAvatar shape="square" :size="70" :src="file"/>
|
||||
</ABadge>
|
||||
<span class="upscale-upload-text">
|
||||
点击上传图片
|
||||
</span>
|
||||
</div>
|
||||
</AUploadDragger>
|
||||
<ADivider orientation="center" :plain="true">
|
||||
<span class="upscale-divider-title">图片预览</span>
|
||||
</ADivider>
|
||||
<div class="upscale-upload-image" v-if="fileList.length > 0">
|
||||
<ABadge v-for="(item, index) in fileList" :key="index">
|
||||
<template #count>
|
||||
<AButton type="text" size="small" class="upscale-file-btn">
|
||||
<template #icon>
|
||||
<AAvatar shape="square" :size="25" :src="remove"/>
|
||||
</template>
|
||||
</AButton>
|
||||
</template>
|
||||
<AAvatar shape="square" :size="100">
|
||||
<template #icon>
|
||||
<AImage :src="convertFileToUrl(item.file)" width="100%" height="100%"/>
|
||||
</template>
|
||||
</AAvatar>
|
||||
</ABadge>
|
||||
</div>
|
||||
<AEmpty v-else :image="empty" :description="null"/>
|
||||
<ADivider/>
|
||||
<div>
|
||||
<AButton type="primary" size="large" :disabled="fileList.length === 0" :loading="uploading"
|
||||
class="upscale-upload-btn">
|
||||
发送图片
|
||||
</AButton>
|
||||
</div>
|
||||
<ADivider/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import file from "@/assets/svgs/file.svg";
|
||||
import useStore from "@/store";
|
||||
import sueccess from '@/assets/svgs/success.svg';
|
||||
import warn from '@/assets/svgs/warn.svg';
|
||||
import remove from '@/assets/svgs/remove.svg';
|
||||
import empty from '@/assets/svgs/empty.svg';
|
||||
import {message} from "ant-design-vue";
|
||||
import {useI18n} from "vue-i18n";
|
||||
import i18n from "@/locales";
|
||||
import {initNSFWJs, predictNSFW} from "@/utils/tfjs/nsfw.ts";
|
||||
import {NSFWJS} from "nsfwjs";
|
||||
|
||||
const upscale = useStore().upscale;
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const {t} = useI18n();
|
||||
|
||||
const fileList = ref<any[]>([]);
|
||||
|
||||
const uploading = ref(false);
|
||||
|
||||
// async function sendImage() {
|
||||
// if (!upscale.imageData) {
|
||||
// return;
|
||||
// }
|
||||
// const base64 = await blobToBase64(upscale.imageData);
|
||||
// const data: uploadImageRequest = {
|
||||
// image: base64,
|
||||
// access_token: route.query.token as string,
|
||||
// user_id: route.query.user_id as string,
|
||||
// };
|
||||
// const res: any = await uploadImage(data);
|
||||
// if (res && res && res.code === 200) {
|
||||
// message.success(t('upload.uploadSuccess'));
|
||||
// } else {
|
||||
// message.error(res.message);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 上传文件前置
|
||||
* @param file
|
||||
*/
|
||||
async function beforeUpload(file: any) {
|
||||
if (!window.FileReader) return false; // 判断是否支持FileReader
|
||||
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'));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* 转换文件为 URL
|
||||
* @param file
|
||||
*/
|
||||
function convertFileToUrl(file: any) {
|
||||
return URL.createObjectURL(file);
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.upscale-upload-content {
|
||||
width: 90%;
|
||||
height: 30vh;
|
||||
padding: 15px;
|
||||
margin: 0 auto;
|
||||
|
||||
.upscale-upload-content-main {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
overflow: scroll;
|
||||
|
||||
|
||||
.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-divider-title {
|
||||
font-size: 13px;
|
||||
color: rgba(126, 126, 135, 0.99);
|
||||
}
|
||||
|
||||
.upscale-upload-image {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.upscale-upload-btn {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
@@ -62,7 +62,7 @@ import warn from '@/assets/svgs/warn.svg';
|
||||
import remove from '@/assets/svgs/remove.svg';
|
||||
import empty from '@/assets/svgs/empty.svg';
|
||||
import {blobToBase64} from "@/utils/imageUtils/blobToBase64.ts";
|
||||
import {uploadImage} from "@/api/upscale";
|
||||
import {uploadImage} from "src/api/phone";
|
||||
import {uploadImageRequest} from "@/types/upscale";
|
||||
import {message} from "ant-design-vue";
|
||||
import {useI18n} from "vue-i18n";
|
||||
|
@@ -7,12 +7,27 @@
|
||||
</template>
|
||||
上传照片
|
||||
</AButton>
|
||||
<AButton type="default" shape="round" size="middle">
|
||||
<template #icon>
|
||||
<PlusSquareOutlined/>
|
||||
<APopover placement="right" trigger="click">
|
||||
<AButton type="default" shape="round" size="middle">
|
||||
<template #icon>
|
||||
<PlusSquareOutlined/>
|
||||
</template>
|
||||
创建相册
|
||||
</AButton>
|
||||
|
||||
<template #content>
|
||||
<span style="color: #999; font-size: 15px;">创建相册</span>
|
||||
<AInput placeholder="请填写相册名称" class="phoalbum-create-input"
|
||||
style="margin-top: 15px"
|
||||
v-model:value="albumNameValue" size="large">
|
||||
<template #suffix>
|
||||
<AButton type="text" @click.prevent size="middle" style="color: #0e87cc" @click="createAlbumSubmit">
|
||||
确认
|
||||
</AButton>
|
||||
</template>
|
||||
</AInput>
|
||||
</template>
|
||||
创建相册
|
||||
</AButton>
|
||||
</APopover>
|
||||
</div>
|
||||
<image-toolbar :selected="imageStore.selected" :image-list="images"/>
|
||||
<div class="photo-list">
|
||||
@@ -21,10 +36,16 @@
|
||||
v-model:activeKey="imageStore.homeTabActiveKey"
|
||||
style="width: 99%;">
|
||||
<template #rightExtra>
|
||||
<ASwitch size="small" v-model:checked="switchValue"/>
|
||||
<AFlex :vertical="false" align="center" gap="10">
|
||||
<span style="color: #999999;">清爽模式</span>
|
||||
<ATooltip title="开启后即可隐藏已添加到相册的照片" placement="bottom">
|
||||
<QuestionCircleOutlined/>
|
||||
</ATooltip>
|
||||
<ASwitch size="default" v-model:checked="imageStore.switchValue"/>
|
||||
</AFlex>
|
||||
</template>
|
||||
<ATabPane key="all" :tab="imageStore.homeTabMap['all']">
|
||||
<ASpin size="large" :spinning="loading" :delay="500">
|
||||
<ASpin size="large" :spinning="loading" :delay="500" wrapper-class-name="spin-wrapper">
|
||||
<div style="width:100%;height:100%;" v-if="images">
|
||||
<div v-for="(itemList, index) in images" :key="index">
|
||||
<span style="margin-left: 10px;font-size: 13px">{{ itemList.date }}</span>
|
||||
@@ -59,7 +80,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty">
|
||||
<AEmpty :image="empty"
|
||||
:image-style="{
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
}">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
还没检测到任何图片,快去上传吧!
|
||||
@@ -237,13 +262,14 @@ import Vue3JustifiedLayout from "vue3-justified-layout";
|
||||
import 'vue3-justified-layout/dist/style.css';
|
||||
import ImageUpload from "@/views/Photograph/ImageUpload/ImageUpload.vue";
|
||||
import useStore from "@/store";
|
||||
import {queryAllImagesApi} from "@/api/storage";
|
||||
import {createAlbumApi, queryAllImagesApi} from "@/api/storage";
|
||||
import ImageToolbar from "@/views/Photograph/ImageToolbar/ImageToolbar.vue";
|
||||
import empty from "@/assets/svgs/empty.svg";
|
||||
import {message} from "ant-design-vue";
|
||||
|
||||
const imageStore = useStore().image;
|
||||
|
||||
const switchValue = ref<boolean>(false);
|
||||
|
||||
const upload = useStore().upload;
|
||||
|
||||
const options = reactive({
|
||||
@@ -252,6 +278,7 @@ const options = reactive({
|
||||
|
||||
const images = ref<any[]>([]);
|
||||
const loading = ref<boolean>(false);
|
||||
const router = useRouter();
|
||||
|
||||
/**
|
||||
* 获取所有图片
|
||||
@@ -259,7 +286,7 @@ const loading = ref<boolean>(false);
|
||||
async function getAllImages(type: string) {
|
||||
images.value = [];
|
||||
loading.value = true;
|
||||
const res: any = await queryAllImagesApi(type, false, upload.storageSelected?.[0], upload.storageSelected?.[1]);
|
||||
const res: any = await queryAllImagesApi(type, imageStore.switchValue, upload.storageSelected?.[0], upload.storageSelected?.[1]);
|
||||
if (res && res.code === 200) {
|
||||
images.value = res.data.records;
|
||||
}
|
||||
@@ -271,6 +298,27 @@ async function handleTabChange(activeKey: string) {
|
||||
await getAllImages(activeKey);
|
||||
}
|
||||
|
||||
const albumNameValue = ref<string>("未命名相册");
|
||||
|
||||
/**
|
||||
* 创建相册
|
||||
*/
|
||||
async function createAlbumSubmit() {
|
||||
if (albumNameValue.value.trim() === "") {
|
||||
message.error("相册名称不能为空");
|
||||
return;
|
||||
}
|
||||
const res: any = await createAlbumApi(albumNameValue.value);
|
||||
if (res && res.code === 200) {
|
||||
router.push({
|
||||
path: "/main/album/albums/" + `${res.data.id}`,
|
||||
query: {name: albumNameValue.value}
|
||||
});
|
||||
} else {
|
||||
message.error("创建相册失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
getAllImages(imageStore.homeTabActiveKey);
|
||||
@@ -314,12 +362,7 @@ onMounted(() => {
|
||||
box-shadow: 0 0 10px 0 rgba(77, 167, 255, 0.89);
|
||||
}
|
||||
|
||||
.empty-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.spin-wrapper {
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@@ -10,7 +10,8 @@
|
||||
<span style="font-size: 16px;font-weight: bold">
|
||||
已选择 {{ props.selected.length }} 张照片
|
||||
</span>
|
||||
<AButton type="text" shape="default" class="photo-toolbar-btn" size="middle" @click="selectAll">
|
||||
<AButton type="text" shape="default" class="photo-toolbar-btn" size="middle" @click="selectAll"
|
||||
:disabled="isAllSelected">
|
||||
全选
|
||||
</AButton>
|
||||
</div>
|
||||
@@ -76,7 +77,14 @@ const deleteImages = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const isAllSelected = computed(() => {
|
||||
// 确保 props.imageList 是一个数组
|
||||
const imageList = props.imageList || [];
|
||||
return props.selected.length === imageList.flatMap((record: ImageRecord) => record.list).length;
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
imageStore.selected = [];
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.photo-toolbar-header {
|
||||
|
@@ -2,8 +2,12 @@
|
||||
<ADrawer v-model:open="upload.openUploadDrawer" placement="right" title="上传照片" width="40%" @close="cancelUpload">
|
||||
<template #extra>
|
||||
<AFlex :vertical="false" align="center" gap="large" justify="center">
|
||||
<ASelect size="middle" style="width: 150px" placeholder="选择上传的相册">
|
||||
|
||||
<ASelect size="middle" style="width: 150px" placeholder="选择上传的相册"
|
||||
:options="albumList"
|
||||
v-model:value="upload.albumSelected"
|
||||
:allow-clear="true"
|
||||
:field-names="{label: 'name', value: 'id'}"
|
||||
>
|
||||
</ASelect>
|
||||
</AFlex>
|
||||
</template>
|
||||
@@ -61,7 +65,7 @@ import {animePredictImagePro} from "@/utils/tfjs/anime_classifier_pro.ts";
|
||||
import {cocoSsdPredict} from "@/utils/tfjs/mobilenet.ts";
|
||||
import {predictLandscape} from "@/utils/tfjs/landscape_recognition.ts";
|
||||
import {useRequest} from 'alova/client';
|
||||
import {uploadFile} from "@/api/storage";
|
||||
import {albumListApi, uploadFile} from "@/api/storage";
|
||||
import imageCompression from "browser-image-compression";
|
||||
import exifr from 'exifr';
|
||||
import isScreenshot from "@/utils/imageUtils/isScreenshot.ts";
|
||||
@@ -232,6 +236,7 @@ async function customUploadRequest(file: any) {
|
||||
provider: upload.storageSelected?.[0],
|
||||
bucket: upload.storageSelected?.[1],
|
||||
fileType: file.file.type,
|
||||
albumId: upload.albumSelected ? upload.albumSelected : 0,
|
||||
...upload.predictResult,
|
||||
}));
|
||||
watch(
|
||||
@@ -311,6 +316,18 @@ async function extractGPSExifData(file) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const albumList = ref<any[]>([]);
|
||||
|
||||
async function getAlbumList(type: number = 0, sort: boolean = true) {
|
||||
const res: any = await albumListApi(type, sort);
|
||||
if (res && res.code === 200) {
|
||||
albumList.value = res.data.albums;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getAlbumList();
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
|
||||
|
@@ -7,12 +7,27 @@
|
||||
</template>
|
||||
上传照片
|
||||
</AButton>
|
||||
<AButton type="default" shape="round" size="middle">
|
||||
<template #icon>
|
||||
<PlusSquareOutlined/>
|
||||
<APopover placement="right" trigger="click">
|
||||
<AButton type="default" shape="round" size="middle">
|
||||
<template #icon>
|
||||
<PlusSquareOutlined/>
|
||||
</template>
|
||||
创建相册
|
||||
</AButton>
|
||||
|
||||
<template #content>
|
||||
<span style="color: #999; font-size: 15px;">创建相册</span>
|
||||
<AInput placeholder="请填写相册名称" class="phoalbum-create-input"
|
||||
style="margin-top: 15px"
|
||||
v-model:value="albumNameValue" size="large">
|
||||
<template #suffix>
|
||||
<AButton type="text" @click.prevent size="middle" style="color: #0e87cc" @click="createAlbumSubmit">
|
||||
确认
|
||||
</AButton>
|
||||
</template>
|
||||
</AInput>
|
||||
</template>
|
||||
创建相册
|
||||
</AButton>
|
||||
</APopover>
|
||||
</div>
|
||||
<image-toolbar :selected="imageStore.selected" :image-list="images"/>
|
||||
<div class="photo-list">
|
||||
@@ -31,20 +46,29 @@
|
||||
:iconSize="20"
|
||||
:showSelectedEffect="true"
|
||||
:value="item.id">
|
||||
<AImage :src="item.url"
|
||||
<AImage :src="item.thumbnail"
|
||||
:alt="item.file_name"
|
||||
:key="index"
|
||||
style="height: 200px"
|
||||
:previewMask="false"
|
||||
loading="lazy"/>
|
||||
:preview="{
|
||||
src: item.url,
|
||||
}"
|
||||
loading="lazy">
|
||||
<template #previewMask>
|
||||
|
||||
</template>
|
||||
</AImage>
|
||||
</CheckCard>
|
||||
</template>
|
||||
</Vue3JustifiedLayout>
|
||||
</AImagePreviewGroup>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<AEmpty :image="empty">
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty" :image-style="{
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
}">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
暂无照片,快去上传吧
|
||||
@@ -62,9 +86,11 @@ import Vue3JustifiedLayout from "vue3-justified-layout";
|
||||
import 'vue3-justified-layout/dist/style.css';
|
||||
import useStore from "@/store";
|
||||
import ImageUpload from "@/views/Photograph/ImageUpload/ImageUpload.vue";
|
||||
import {queryRecentImagesApi} from "@/api/storage";
|
||||
import {createAlbumApi, queryRecentImagesApi} from "@/api/storage";
|
||||
import ImageToolbar from "@/views/Photograph/ImageToolbar/ImageToolbar.vue";
|
||||
import empty from "@/assets/svgs/empty.svg";
|
||||
import {message} from "ant-design-vue";
|
||||
import router from "@/router/router.ts";
|
||||
|
||||
const imageStore = useStore().image;
|
||||
const upload = useStore().upload;
|
||||
@@ -74,12 +100,33 @@ const options = reactive({
|
||||
});
|
||||
|
||||
const getRecentImages = async () => {
|
||||
const res: any = await queryRecentImagesApi();
|
||||
const res: any = await queryRecentImagesApi(upload.storageSelected?.[0], upload.storageSelected?.[1]);
|
||||
if (res && res.code === 200) {
|
||||
images.value = res.data.records;
|
||||
}
|
||||
};
|
||||
|
||||
const albumNameValue = ref<string>("未命名相册");
|
||||
|
||||
/**
|
||||
* 创建相册
|
||||
*/
|
||||
async function createAlbumSubmit() {
|
||||
if (albumNameValue.value.trim() === "") {
|
||||
message.error("相册名称不能为空");
|
||||
return;
|
||||
}
|
||||
const res: any = await createAlbumApi(albumNameValue.value);
|
||||
if (res && res.code === 200) {
|
||||
router.push({
|
||||
path: "/main/album/albums/" + `${res.data.id}`,
|
||||
query: {name: albumNameValue.value}
|
||||
});
|
||||
} else {
|
||||
message.error("创建相册失败");
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getRecentImages();
|
||||
});
|
||||
|
@@ -38,8 +38,8 @@
|
||||
</AImagePreviewGroup>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<AEmpty :image="empty">
|
||||
<div v-else class="empty-content">
|
||||
<AEmpty :image="empty" :image-style="{ width: '100%', height: '100%' }">
|
||||
<template #description>
|
||||
<span style="color: #999999;font-size: 16px;font-weight: 500;line-height: 1.5;">
|
||||
暂无照片,快去上传吧
|
||||
|
@@ -39,7 +39,8 @@
|
||||
:status="`active`"
|
||||
/>
|
||||
</template>
|
||||
<AButton @click.stop type="default" size="large" shape="round" style="width: 70%">
|
||||
<AButton type="default" size="large" shape="round" style="width: 70%"
|
||||
@click.stop="initWebSocket">
|
||||
<template #icon>
|
||||
<QrcodeOutlined/>
|
||||
</template>
|
||||
@@ -429,9 +430,10 @@ const wsOptions = {
|
||||
protocols: [user.token.accessToken],
|
||||
};
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener("resize", updateQrcodeSize);
|
||||
/**
|
||||
* 初始化 WebSocket
|
||||
*/
|
||||
function initWebSocket() {
|
||||
websocket.initialize(wsOptions);
|
||||
websocket.on("message", async (res: any) => {
|
||||
if (res && res.code === 200) {
|
||||
@@ -439,6 +441,10 @@ onMounted(() => {
|
||||
console.log(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener("resize", updateQrcodeSize);
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
websocket.close(false);
|
||||
|
@@ -10,7 +10,9 @@
|
||||
<div class="share-sidebar-body-top">
|
||||
<AAvatar :size="coverImageSize" shape="square">
|
||||
<template #icon>
|
||||
<AImage width="100%" height="100%" :src="`data:image/png;base64,`+shareInfo.cover_image" :preview="false">
|
||||
<AImage width="100%" height="100%"
|
||||
:src="shareInfo.cover_image?`data:image/png;base64,`+shareInfo.cover_image:default_cover"
|
||||
:preview="false">
|
||||
</AImage>
|
||||
</template>
|
||||
</AAvatar>
|
||||
@@ -41,6 +43,7 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {queryShareInfoApi} from "@/api/share";
|
||||
import default_cover from "@/assets/images/default-cover.png";
|
||||
|
||||
const coverImageSize = ref<number>(130);
|
||||
const shareInfo = ref<any>();
|
||||
|
@@ -10,12 +10,12 @@
|
||||
<div class="share-content-header">
|
||||
<AButton type="link" size="large" class="share-content-header-button">图片列表</AButton>
|
||||
</div>
|
||||
<div class="share-content-verify" v-if="images.length <= 0">
|
||||
<div class="share-content-verify" v-if="images && images.length <= 0">
|
||||
<AInputPassword size="large" placeholder="请输入访问密码" style="width: 20%" @pressEnter="getShareImages"/>
|
||||
<p style="font-size: 12px;color: #999;">回车后可查看图片列表</p>
|
||||
</div>
|
||||
<ASpin :spinning="loading" size="large">
|
||||
<div v-if="images.length !== 0">
|
||||
<div v-if="images && images.length !== 0">
|
||||
<AImagePreviewGroup>
|
||||
<Vue3JustifiedLayout v-model:list="images" :options="options">
|
||||
<template #default="{ item }">
|
||||
|
@@ -151,7 +151,7 @@ const updateQrcodeSize = () => {
|
||||
};
|
||||
|
||||
function generateQrCodeUrl(): string {
|
||||
return import.meta.env.VITE_APP_WEB_URL + "/upscale/app?user_id=" + user.user.uid + "&token=" + user.token.accessToken;
|
||||
return import.meta.env.VITE_APP_WEB_URL + "/main/upscale/phone/app?user_id=" + user.user.uid + "&token=" + user.token.accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -82,7 +82,7 @@ async function startTask() {
|
||||
if (upscale.input === null) return;
|
||||
upscale.isProcessing = true;
|
||||
const start = Date.now();
|
||||
const worker = new Worker(new URL("@/workers/upscale/upscale.worker.ts", import.meta.url), {
|
||||
const worker = new Worker(new URL("@/workers/phone/phone.worker.ts", import.meta.url), {
|
||||
type: "module",
|
||||
});
|
||||
worker.onmessage = (e: MessageEvent<any>) => {
|
||||
|
Reference in New Issue
Block a user