f99c44f716
- Add bulletin_posts and bulletin_reads PocketBase collections with migrations - Add BulletinPost/BulletinRead types and priority levels (low/normal/high/urgent) - Add bulletin API (CRUD, read tracking, realtime subscription) - Add bulletin Pinia store with pinned/normal sections and expiration filtering - Add BulletinPinned header component for pinned announcements - Add BulletinBoard tab component with sectioned list layout - Add BulletinPostCard with priority tags, unread dots, and hover actions - Add CreateBulletinDialog with title, content, priority, pinned, expiresAt - Integrate bulletin tab into GroupView with Bell icon and real-time updates Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
114 lines
3.2 KiB
TypeScript
114 lines
3.2 KiB
TypeScript
import { pb } from './pocketbase'
|
|
import type { BulletinPost, BulletinRead } from '@/types'
|
|
|
|
export async function createBulletin(data: {
|
|
group: string
|
|
title: string
|
|
content: string
|
|
priority?: 'low' | 'normal' | 'high' | 'urgent'
|
|
pinned?: boolean
|
|
expiresAt?: string
|
|
}): Promise<BulletinPost> {
|
|
const user = pb.authStore.model
|
|
if (!user) throw new Error('未登录')
|
|
|
|
const post = await pb.collection('bulletin_posts').create({
|
|
group: data.group,
|
|
creator: user.id,
|
|
title: data.title,
|
|
content: data.content,
|
|
priority: data.priority || 'normal',
|
|
pinned: data.pinned || false,
|
|
expiresAt: data.expiresAt || '',
|
|
})
|
|
return post as unknown as BulletinPost
|
|
}
|
|
|
|
export async function listBulletins(groupId: string): Promise<BulletinPost[]> {
|
|
const result = await pb.collection('bulletin_posts').getFullList({
|
|
filter: `group="${groupId}"`,
|
|
sort: '-pinned,-created',
|
|
expand: 'creator',
|
|
$autoCancel: false,
|
|
})
|
|
return result as unknown as BulletinPost[]
|
|
}
|
|
|
|
export async function getBulletin(postId: string): Promise<BulletinPost> {
|
|
const result = await pb.collection('bulletin_posts').getOne(postId, {
|
|
expand: 'creator',
|
|
})
|
|
return result as unknown as BulletinPost
|
|
}
|
|
|
|
export async function updateBulletin(
|
|
postId: string,
|
|
data: {
|
|
title?: string
|
|
content?: string
|
|
priority?: 'low' | 'normal' | 'high' | 'urgent'
|
|
pinned?: boolean
|
|
expiresAt?: string
|
|
}
|
|
): Promise<BulletinPost> {
|
|
const payload: Record<string, any> = {}
|
|
if (data.title !== undefined) payload.title = data.title
|
|
if (data.content !== undefined) payload.content = data.content
|
|
if (data.priority !== undefined) payload.priority = data.priority
|
|
if (data.pinned !== undefined) payload.pinned = data.pinned
|
|
if (data.expiresAt !== undefined) payload.expiresAt = data.expiresAt
|
|
|
|
const result = await pb.collection('bulletin_posts').update(postId, payload)
|
|
return result as unknown as BulletinPost
|
|
}
|
|
|
|
export async function deleteBulletin(postId: string): Promise<void> {
|
|
await pb.collection('bulletin_posts').delete(postId)
|
|
}
|
|
|
|
// 已读追踪
|
|
export async function markBulletinAsRead(postId: string): Promise<BulletinRead | null> {
|
|
const user = pb.authStore.model
|
|
if (!user) return null
|
|
|
|
// 检查是否已存在
|
|
const existing = await pb.collection('bulletin_reads').getList(1, 1, {
|
|
filter: `post="${postId}" && user="${user.id}"`,
|
|
$autoCancel: false,
|
|
})
|
|
if (existing.items.length > 0) return existing.items[0] as unknown as BulletinRead
|
|
|
|
const result = await pb.collection('bulletin_reads').create({
|
|
post: postId,
|
|
user: user.id,
|
|
})
|
|
return result as unknown as BulletinRead
|
|
}
|
|
|
|
export async function listMyReads(): Promise<BulletinRead[]> {
|
|
const user = pb.authStore.model
|
|
if (!user) return []
|
|
|
|
const result = await pb.collection('bulletin_reads').getFullList({
|
|
filter: `user="${user.id}"`,
|
|
$autoCancel: false,
|
|
})
|
|
return result as unknown as BulletinRead[]
|
|
}
|
|
|
|
// 实时订阅
|
|
export async function subscribeBulletins(
|
|
groupId: string,
|
|
callback: (data: any) => void
|
|
): Promise<() => void> {
|
|
await pb.collection('bulletin_posts').subscribe('*', (data) => {
|
|
if (data.record?.group === groupId) {
|
|
callback(data)
|
|
}
|
|
})
|
|
|
|
return () => {
|
|
pb.collection('bulletin_posts').unsubscribe('*')
|
|
}
|
|
}
|