Files
gamegroup2/frontend/src/api/memories.ts
T
congsh c5d3ac01ca feat: phase 2 - polls, memories, notifications, stats v0.1.0
- Group polls with option/rollcall modes, edit by creator, auto-settle
- Multimedia memories with upload, preview, inline video playback
- In-app notifications for poll/team/group events
- Points system and group stats dashboard
- Group detail tabs with icons (activity/polls/memories/stats)
- Fix: nginx file upload size, static cache blocking API, timezone, auto-cancel

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 18:19:46 +08:00

100 lines
2.8 KiB
TypeScript

import { pb } from './pocketbase'
import type { Memory } from '@/types'
export const GROUP_STORAGE_LIMIT = 10 * 1024 * 1024 * 1024
export function detectFileType(file: File): 'image' | 'video' | 'audio' | 'document' | 'other' {
const mime = file.type || ''
if (mime.startsWith('image/')) return 'image'
if (mime.startsWith('video/')) return 'video'
if (mime.startsWith('audio/')) return 'audio'
if (
mime.startsWith('application/pdf') ||
mime.startsWith('application/msword') ||
mime.startsWith('application/vnd.') ||
mime.startsWith('text/')
) return 'document'
return 'other'
}
export async function uploadMemory(
groupId: string,
file: File,
meta?: { title?: string; description?: string; tags?: string[] }
) {
const used = await getGroupStorageUsed(groupId)
if (used + file.size > GROUP_STORAGE_LIMIT) {
throw new Error('群组存储空间不足,无法上传')
}
const user = pb.authStore.model
const formData = new FormData()
formData.append('group', groupId)
formData.append('uploader', user?.id || '')
formData.append('file', file)
formData.append('fileType', detectFileType(file))
formData.append('size', file.size.toString())
formData.append('title', meta?.title || file.name)
if (meta?.description) formData.append('description', meta.description)
return pb.collection('memories').create(formData)
}
export async function listMemories(
groupId: string,
options?: {
page?: number
limit?: number
fileType?: string
}
): Promise<{ items: Memory[]; total: number }> {
const { page = 1, limit = 30, fileType } = options || {}
let filter = `group="${groupId}"`
if (fileType) filter += ` && fileType="${fileType}"`
const result = await pb.collection('memories').getList(page, limit, {
filter,
sort: '-created',
expand: 'uploader'
})
return { items: result.items as unknown as Memory[], total: result.totalItems }
}
export async function deleteMemory(memoryId: string) {
return pb.collection('memories').delete(memoryId)
}
export async function getGroupStorageUsed(groupId: string): Promise<number> {
let total = 0
let page = 1
const batchSize = 500
let hasMore = true
while (hasMore) {
const result = await pb.collection('memories').getList(page, batchSize, {
filter: `group="${groupId}"`,
fields: 'size'
})
total += result.items.reduce((sum: number, r: any) => sum + (r.size || 0), 0)
hasMore = result.items.length === batchSize && page * batchSize < result.totalItems
page++
}
return total
}
export function getGroupStorageLimit(): number {
return GROUP_STORAGE_LIMIT
}
export function subscribeMemories(
groupId: string,
callback: (data: any) => void
) {
return pb.collection('memories').subscribe('*', (data) => {
if (data.record?.group === groupId) {
callback(data)
}
})
}