Skip to content

Commit

Permalink
feat(web): add album to view all images
Browse files Browse the repository at this point in the history
  • Loading branch information
Chilfish committed Aug 6, 2024
1 parent a029109 commit 88ec83b
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 3 deletions.
115 changes: 115 additions & 0 deletions apps/web/src/pages/album.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<script setup lang="ts">
import type { Album } from '@shared'
const album = shallowRef<Album[]>([])
const postStore = usePostStore()
const width = '12rem'
const loadSize = 16
const loadedAlbum = ref<AlbumGroup[]>([]) // 用于存储已加载的相册
interface AlbumGroup {
imgs: {
id: string
url: string
}[]
date: string
}
function groupByDate(album: Album[]): AlbumGroup[] {
const groups: AlbumGroup[] = []
let currentGroup: AlbumGroup | null = null
for (const item of album) {
if (!currentGroup || currentGroup.date !== item.date) {
currentGroup = {
date: item.date,
imgs: [],
}
groups.push(currentGroup)
}
currentGroup.imgs.push(item)
}
return groups
}
function handleLoad() {
const loadedLength = loadedAlbum.value.map(({ imgs }) => imgs.length).reduce((a, b) => a + b, 0)
const loaded = album.value.splice(loadedLength, loadSize)
const groups = groupByDate(loaded)
groups.forEach(({ date, imgs }) => {
const loadedItem = loadedAlbum.value.find(item => item.date === date)
if (loadedItem) {
loadedItem.imgs.push(...imgs)
}
else {
loadedAlbum.value.push({
date,
imgs,
})
}
})
}
onMounted(async () => {
album.value = await postStore.getAllImgs()
handleLoad()
})
</script>

<template>
<main
id="album"
class="mx-auto mt-20 rounded-2 p-4 md:w-70rem"
bg="light dark:dark"
>
<n-infinite-scroll
:distance="5"
:style="{
height: 'calc(100vh - 8rem)',
}"
@load="handleLoad"
>
<n-image-group>
<section
v-for="item in loadedAlbum"
:id="item.date"
:key="item.date"
class="mb-4 flex flex-col gap-2"
>
<h2 class="w-full text-start text-2xl font-bold">
{{ item.date }}
</h2>
<div
class="flex flex-wrap items-center gap-1 px-6"
>
<!-- {{ item.imgs }} -->
<MainImage
v-for="{ id, url } in item.imgs"
:id="`img-${id}`"
:key="`img-${id}`"
:src="url"
:style="{
width,
height: width,
}"
:min-height="width"
fit="cover"
/>
</div>
</section>
</n-image-group>
</n-infinite-scroll>
</main>
</template>

<style>
#album .n-scrollbar > .n-scrollbar-container {
overflow-x: hidden !important;
}
#album .n-scrollbar-rail{
display: none !important;
}
</style>
32 changes: 31 additions & 1 deletion packages/core/src/stores/post.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { defineStore } from 'pinia'
import { useRoute, useRouter } from 'vue-router'
import type { Post, UID, UserBio, UserInfo } from '@shared'
import type { Album, Post, UID, UserBio, UserInfo } from '@shared'
import { EmptyIDB, IDB } from '../utils/storage'

export const usePostStore = defineStore('post', () => {
Expand Down Expand Up @@ -213,6 +213,35 @@ export const usePostStore = defineStore('post', () => {
.then(data => data.sort((a, b) => a.name.localeCompare(b.name)))
}

/**
* 获取所有图片,以月份分组
*/
async function getAllImgs() {
await waitIDB()
const imgs = await idb.value.getImgs()

/**
* [
* {
* date: '2021年01月',
* imgs: ['url1', 'url2', ...]
* }
* ]
*/
const result: Album[] = []

for (const { img, date, id } of imgs) {
const year = date.getFullYear()
const month = date.getMonth() + 1
const key = `${year}${month.toString().padStart(2, '0')}月`

const data = { url: img, id, date: key }
result.push(data)
}

return result
}

return {
total,
totalDB,
Expand Down Expand Up @@ -245,5 +274,6 @@ export const usePostStore = defineStore('post', () => {
searchPost,
searchAndTime,
getFollowings,
getAllImgs,
}
})
41 changes: 39 additions & 2 deletions packages/core/src/utils/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import Fuse from 'fuse.js'
import dayjs from 'dayjs'
import type { FuseResult } from 'fuse.js'
import type { DBSchema, IDBPDatabase } from 'idb'
import type { Post, UID, UserBio, UserInfo } from '@shared'
import type {
Post,
UID,
UserBio,
UserInfo,
} from '@shared'

const POST_STORE = 'posts'
const USER_STORE = 'user'
Expand Down Expand Up @@ -52,6 +57,7 @@ export async function checkDB(uid: number) {
export class IDB {
idb: Promise<IDBPDatabase<AppDB>>
name: UID
posts: Post[] = []

constructor(
name: UID,
Expand Down Expand Up @@ -140,8 +146,13 @@ export class IDB {
* 获取所有帖子
*/
async getAllDBPosts() {
if (this.posts.length)
return this.posts

const db = await this.idb
return await db.getAll(POST_STORE)
const posts = await db.getAll(POST_STORE)
this.posts = posts
return posts
}

/**
Expand Down Expand Up @@ -364,6 +375,31 @@ export class IDB {
const db = await this.idb
return await db.getAll(FLOWERINGS_STORE)
}

async getImgs() {
const result: Album[] = []
const posts = await this.getAllDBPosts()

posts
.reverse()
.forEach((post) => {
post.imgs.forEach((img) => {
result.push({
img,
date: new Date(post.created_at),
id: post.mblogid,
})
})
})

return result
}
}

interface Album {
img: string
id: string
date: Date
}

export type SeachResult = FuseResult<{
Expand Down Expand Up @@ -399,4 +435,5 @@ export class EmptyIDB extends IDB {
async setUserInfo(_user: UserInfo): Promise<void> {}
async addFollowings(_followings: UserBio[]): Promise<void> {}
async getFollowings(): Promise<UserBio[]> { return [] }
async getImgs(): Promise<Album[]> { return [] }
}
6 changes: 6 additions & 0 deletions packages/shared/src/types/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,9 @@ export interface PostData {
user: UserInfo
followings: UserBio[]
}

export interface Album {
url: string
id: string
date: string
}

0 comments on commit 88ec83b

Please sign in to comment.