🚧 add sidebar

This commit is contained in:
2024-12-03 00:49:16 +08:00
parent 594bd5b280
commit 2a1bb215ac
31 changed files with 440 additions and 99 deletions

View File

@@ -19,16 +19,4 @@ const app = useStore().theme;
const lang = useStore().lang;
</script>
<style scoped lang="scss">
.animation-enter {
opacity: 0; /* 初始透明 */
}
.animation-enter-active {
transition: opacity 0.2s; /* 渐入效果 */
}
.animation-leave-active {
transition: opacity 0.2s; /* 渐出效果 */
}
.animation-leave-to {
opacity: 0; /* 离开时透明 */
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<AFlex :vertical="true" class="reply-item-child">
<ASpin :spinning="comment.replyLoading[item.id]" size="default">
<ASpin :delay="500" :spinning="comment.replyLoading[item.id]" size="default">
<AFlex :vertical="true" v-if="comment.replyVisibility[item.id]?.data.comments">
<AFlex :vertical="false" style="margin-top: 5px"
v-for="(child, index) in comment.replyVisibility[item.id]?.data.comments"

View File

@@ -1,33 +1,59 @@
<template>
<header class="header-main">
<div class="header-container">
<AFlex :vertical="false" align="center" justify="flex-end" class="header-logo-container">
<AFlex :vertical="false" align="center" justify="flex-start" class="header-logo-container">
<AAvatar :size="50" shape="square" :src="logo" @click="router.push('/')"/>
<span class="header-logo-text" @click="router.push('/')">S.Album</span>
</AFlex>
<AFlex class="header-search-container" :vertical="false" align="center" justify="center">
<APopover :arrow="false" :overlayInnerStyle="{width: '28vw'}"
trigger="click">
<AInput size="large" class="header-search-input" placeholder="Search">
<template #suffix>
<AButton size="small" type="text" shape="circle" @click.prevent>
<template #icon>
<SearchOutlined style="font-size: 16px"/>
</template>
</AButton>
</template>
</AInput>
<template #content>
<AFlex :vertical="false" align="center" justify="space-between" class="header-search-content-header">
<span>搜索历史</span>
<AButton type="text" size="small" style="color: #707072">清空搜索历史</AButton>
</AFlex>
<div class="header-search-content-body">
<ATag :style="{
padding: '5px 15px',
fontSize: '15px',
marginTop: '20px',
}" :bordered="false" closable>搜索历史1
</ATag>
</div>
</template>
</APopover>
</AFlex>
<AFlex :vertical="false" align="center" justify="flex-end" class="header-menu-container">
<AFlex :vertical="false" align="center" justify="flex-start" class="header-menu-item">
<ABadge count="0" :numberStyle="{
marginTop: '5px',
}">
<ABadge count="5" :numberStyle="{marginTop: '10px', marginRight: '5px'}">
<AButton type="text" shape="circle" size="large" class="header-menu-item-btn"
:icon="h(BellOutlined)"/>
</ABadge>
</AFlex>
<AFlex :vertical="false" align="center" justify="flex-start" class="header-menu-item">
<ADropdown>
<template #overlay>
<AMenu @click="changeLang">
<AMenuItem key="zh">{{ t("landing.chinese") }}</AMenuItem>
<AMenuItem key="en">{{ t("landing.english") }}</AMenuItem>
</AMenu>
</template>
<AButton type="text" shape="circle" size="large" :icon="h(TranslationOutlined)">
</AButton>
</ADropdown>
</AFlex>
<!-- <AFlex :vertical="false" align="center" justify="flex-start" class="header-menu-item">-->
<!-- <ADropdown>-->
<!-- <template #overlay>-->
<!-- <AMenu @click="changeLang">-->
<!-- <AMenuItem key="zh">{{ t("landing.chinese") }}</AMenuItem>-->
<!-- <AMenuItem key="en">{{ t("landing.english") }}</AMenuItem>-->
<!-- </AMenu>-->
<!-- </template>-->
<!-- <AButton type="text" shape="circle" size="large" :icon="h(TranslationOutlined)">-->
<!-- </AButton>-->
<!-- </ADropdown>-->
<!-- </AFlex>-->
<AFlex :vertical="false" align="center" justify="flex-start" class="header-user-container">
<AAvatar :size="35" class="header-user-avatar" :src="user.user.avatar"/>
<AAvatar :size="40" class="header-user-avatar" :src="user.user.avatar"/>
</AFlex>
</AFlex>
</div>
@@ -36,23 +62,22 @@
<script lang="ts" setup>
import logo from "@/assets/svgs/logo-album.svg";
import useStore from "@/store";
import {BellOutlined, TranslationOutlined} from "@ant-design/icons-vue";
import {BellOutlined} from "@ant-design/icons-vue";
import {h} from "vue";
import {useI18n} from "vue-i18n";
const user = useStore().user;
const {t, locale} = useI18n();
const lang = useStore().lang;
// const lang = useStore().lang;
const router = useRouter();
/**
* 切换语言
* @param language
*/
async function changeLang(language: any) {
lang.lang = language.key;
locale.value = language.key;
}
// /**
// * 切换语言
// * @param language
// */
// async function changeLang(language: any) {
// lang.lang = language.key;
// locale.value = language.key;
// }
</script>
<style scoped lang="scss" src="./index.scss">

View File

@@ -1,19 +1,15 @@
.header-main {
height: 60px;
height: 70px;
width: 100%;
min-height: 70px;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(255, 255, 255, 0.38);
backdrop-filter: blur(20px);
transition: background-color 0.3s;
z-index: 3;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
//border-radius: 20px;
position: fixed;
top: 0;
left: 0;
//position: fixed;
.header-container {
@@ -21,40 +17,65 @@
flex-direction: row;
align-items: center;
justify-content: space-between;
width: 1200px;
max-width: 1200px;
width: 100%;
height: 100%;
padding: 0 2%;
.header-logo-text {
margin-left: 10px;
font-size: 25px;
font-family: "Comic Sans MS", cursive;
font-weight: bolder;
}
}
.header-logo-container {
min-width: 30%;
cursor: pointer;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
.header-logo-container {
min-width: 280px;
cursor: pointer;
}
.header-menu-container {
width: 30%;
.header-menu-item {
min-width: 50px;
.header-menu-item-btn {
font-size: 16px;
.header-logo-text {
margin-left: 2%;
font-size: 200%;
font-family: "Comic Sans MS", cursive;
font-weight: bolder;
}
}
.header-user-container {
min-width: 130px;
.header-search-container {
width: 30%;
.header-search-input {
border-radius: 20px;
}
.header-search-content-body {
margin-top: 10px;
.header-user-avatar {
cursor: pointer;
}
}
.header-menu-container {
width: 30%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.header-menu-item {
width: 85%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
}
.header-user-container {
.header-user-avatar {
cursor: pointer;
}
}
}
}
}

View File

@@ -0,0 +1,80 @@
<template>
<div>
<AMenu
v-model:selectedKeys="state.selectedKeys"
class="sidebar"
:selectable="true"
:multiple="false"
mode="vertical"
v-model:openKeys="state.openKeys"
:inlineIndent="30"
:inlineCollapsed="false"
:items="items"
@click="handleClick"
>
</AMenu>
</div>
</template>
<script lang="ts" setup>
import {VueElement, h, reactive} from 'vue';
import {
PictureOutlined,
TagsOutlined,
AppstoreOutlined,
UploadOutlined,
RestOutlined,
TagOutlined,
SmileOutlined,
EnvironmentOutlined,
AppstoreAddOutlined
} from '@ant-design/icons-vue';
import {ItemType} from 'ant-design-vue';
import {useI18n} from 'vue-i18n';
const {t} = useI18n();
const router = useRouter();
const state = reactive({
openKeys: [router.currentRoute.value.path.split('/').slice(-1)],
selectedKeys: [router.currentRoute.value.path.split('/').slice(-1)],
});
function getItem(
label: VueElement | string,
key: string,
icon?: any,
children?: ItemType[],
type?: 'group',
): ItemType {
return {
key,
icon,
children,
label,
type,
} as ItemType;
}
const items: ItemType[] = reactive([
getItem(t('album.photo'), 'photo', () => h(AppstoreOutlined), [
getItem(t('album.allAlbums'), 'all', () => h(PictureOutlined)),
getItem(t('album.recentUploads'), 'recent', () => h(UploadOutlined)),
]),
getItem(t('album.albums'), 'album', () => h(TagsOutlined), [
getItem(t('album.albums'), 'albums', () => h(TagOutlined)),
getItem(t('album.peopleAlbums'), 'people', () => h(SmileOutlined)),
getItem(t('album.locationAlbums'), 'location', () => h(EnvironmentOutlined)),
getItem(t('album.thingsAlbums'), 'thing', () => h(AppstoreAddOutlined)),
]),
getItem(t('album.recyclingBin'), 'recycling', () => h(RestOutlined)),
getItem('网盘导入', '10'),
]);
function handleClick({keyPath}) {
const path = keyPath.join('/');
router.push(`/main/${path}`);
}
</script>
<style scoped lang="scss" src="./index.scss">
</style>

View File

@@ -0,0 +1,6 @@
.sidebar {
width: 15vw;
height: calc(100vh - 70px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

View File

@@ -135,5 +135,15 @@ export default {
reportSeletion: 'Please select the reason for reporting the comment',
view: 'look',
replies: 'replies',
},
album: {
photo: 'Photo',
allAlbums: 'All Albums',
recentUploads: 'Recent Uploads',
albums: 'Albums',
peopleAlbums: 'People',
locationAlbums: 'Location',
thingsAlbums: 'Things',
recyclingBin: 'Recycling Bin',
}
};

View File

@@ -137,6 +137,16 @@ export default {
reportSeletion: '请选择举报原因',
view: '查看',
replies: '条回复',
},
album: {
photo: '照片',
allAlbums: '所有相册',
recentUploads: '最近上传',
albums: '相册',
peopleAlbums: '人物',
locationAlbums: '地点',
thingsAlbums: '事物',
recyclingBin: '回收站',
}
};

View File

@@ -0,0 +1,43 @@
import Phoalbum from "@/views/Album/Phoalbum/Phoalbum.vue";
import PeopleAlbum from "@/views/Album/PeopleAlbum/PeopleAlbum.vue";
import LocationAlbum from "@/views/Album/LocationAlbum/LocationAlbum.vue";
import ThingAlbum from "@/views/Album/ThingAlbum/ThingAlbum.vue";
export default [
{
path: '/main/album/albums',
name: 'albums',
component: Phoalbum,
meta: {
requiresAuth: true,
title: '相册'
},
},
{
path: '/main/album/people',
name: 'people',
component: PeopleAlbum,
meta: {
requiresAuth: true,
title: '人物相册'
},
},
{
path: '/main/album/location',
name: 'location',
component: LocationAlbum,
meta: {
requiresAuth: true,
title: '地点相册'
},
},
{
path: '/main/album/thing',
name: 'thing',
component: ThingAlbum,
meta: {
requiresAuth: true,
title: '事物相册'
},
},
];

View File

@@ -1,11 +1,22 @@
import photo from "@/router/modules/photos.ts";
import albums from "@/router/modules/albums.ts";
import recycling_bin from "@/router/modules/recycling_bin.ts";
export default [
{
path: '/main',
name: 'main',
redirect: '/main/photos',
component: () => import('@/views/Main/MainPage.vue'),
meta: {
requiresAuth: true,
title: '主页'
}
},
children: [
...photo,
...albums,
...recycling_bin
]
}
];

View File

@@ -0,0 +1,23 @@
import AllPhoto from "@/views/Photograph/AllPhoto/AllPhoto.vue";
import RecentUpload from "@/views/Photograph/RecentUpload/RecentUpload.vue";
export default [
{
path: '/main/photo/all',
name: 'photos',
component: AllPhoto,
meta: {
requiresAuth: true,
title: '全部照片'
},
},
{
path: '/main/photo/recent',
name: 'recent',
component: RecentUpload,
meta: {
requiresAuth: true,
title: '最近上传'
},
},
];

View File

@@ -0,0 +1,13 @@
import RecyclingBin from "@/views/RecyclingBin/RecyclingBin.vue";
export default [
{
path: '/main/recycling',
name: 'recycling',
component: RecyclingBin,
meta: {
requiresAuth: true,
title: '回收站'
},
},
];

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
</script>
<template>
</template>
<style scoped lang="scss" src="./index.scss">
</style>

View File

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
</script>
<template>
</template>
<style scoped lang="scss" src="./index.scss">
</style>

View File

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
</script>
<template>
</template>
<style scoped lang="scss" src="./index.scss">
</style>

View File

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
</script>
<template>
</template>
<style scoped lang="scss" src="./index.scss">
</style>

View File

View File

@@ -1,21 +1,26 @@
<template>
<div class="main-page">
<Header/>
<div style="margin-top: 100px">
<CommentReply/>
<div class="main-header">
<Header/>
</div>
<div class="main-content">
<Sidebar/>
<div class="main-content-container">
<!-- <ACard class="main-container-card">-->
<router-view/>
<!-- </ACard>-->
</div>
</div>
</div>
</template>
<script setup lang="ts">
import useStore from "@/store";
import CommentReply from "@/components/CommentReply/index.vue";
import {h, onMounted, onUnmounted} from "vue";
import Header from "@/layout/default/Header/Header.vue";
import {notification} from "ant-design-vue";
import {SmileOutlined} from "@ant-design/icons-vue";
import Sidebar from "@/layout/default/Sidebar/Sidebar.vue";
const websocket = useStore().websocket;

View File

@@ -1,9 +1,35 @@
.main-page {
display: flex;
flex-direction: column;
align-items: center;
background-color: var(--background-color);
background-color: #eaeef6;
color: var(--text-color);
width: 100%;
min-height: 100vh;
.main-header {
}
.main-content {
display: flex;
flex-direction: row;
.main-content-container {
display: flex;
flex-direction: column;
//justify-content: center;
//align-items: center;
width: calc(100% - 15vw);
height: calc(100vh - 90px);
padding: 10px;
.main-container-card {
width: 100%;
height: 100%;
overflow: scroll;
}
}
}
}

View File

@@ -0,0 +1,14 @@
<script setup lang="ts">
</script>
<template>
<div>
<p>AllPhoto</p>
</div>
</template>
<style scoped lang="scss" src="./index.scss">
</style>

View File

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
</script>
<template>
</template>
<style scoped lang="scss" src="./index.scss">
</style>

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
</script>
<template>
</template>
<style scoped lang="scss" src="./index.scss">
</style>

View File