| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 |
- import { inject, onBeforeUnmount, provide, ref, watch, type InjectionKey, type Ref } from 'vue'
- import type { AgentClient } from '@agent-server/client'
- /** 组件只需要带鉴权地下载文件:AgentClient 与 BotClient 都满足 */
- export type FileClient = Pick<AgentClient, 'fileBlob'>
- const CLIENT_KEY: InjectionKey<FileClient> = Symbol('agent-client')
- export function provideClient(client: FileClient) {
- provide(CLIENT_KEY, client)
- }
- export function useClient(): FileClient {
- const c = inject(CLIENT_KEY)
- if (!c) throw new Error('chat-ui: 缺少 AgentClient(请在外层使用 <AgentChat> 或 provideClient)')
- return c
- }
- /** 带鉴权地加载文件为 object URL(Agent Key 模式下 <img src> 无法携带请求头) */
- export function useFileObjectUrl(fileId: Ref<string | null>): Ref<string | null> {
- const client = useClient()
- const url = ref<string | null>(null)
- let current: string | null = null
- const release = () => {
- if (current) URL.revokeObjectURL(current)
- current = null
- }
- watch(fileId, async id => {
- release()
- url.value = null
- if (!id) return
- try {
- current = URL.createObjectURL(await client.fileBlob(id))
- url.value = current
- } catch {
- url.value = null
- }
- }, { immediate: true })
- onBeforeUnmount(release)
- return url
- }
- export async function downloadFile(client: FileClient, fileId: string, name: string) {
- const blob = await client.fileBlob(fileId)
- const href = URL.createObjectURL(blob)
- const a = document.createElement('a')
- a.href = href
- a.download = name
- a.click()
- setTimeout(() => URL.revokeObjectURL(href), 10_000)
- }
|