95 lines
3.3 KiB
TypeScript
95 lines
3.3 KiB
TypeScript
|
|
import { useEffect, useState } from 'react'
|
|||
|
|
import { useOutletContext, useParams } from 'react-router-dom'
|
|||
|
|
import { api, ApiError } from '../api/client'
|
|||
|
|
import { DevToolsPanel } from '../components/DevToolsPanel'
|
|||
|
|
import { AcLink, Badge, Card, ErrorText, Notice, SectionTitle, SuccessText } from '../components/ui'
|
|||
|
|
import type { ThreadsAccountConnectionData, ThreadsAccountData } from '../types/api'
|
|||
|
|
|
|||
|
|
type WorkspaceContext = {
|
|||
|
|
accountId: string
|
|||
|
|
account: ThreadsAccountData | null
|
|||
|
|
loading: boolean
|
|||
|
|
error: string
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function ThreadsAccountConnectionsPage() {
|
|||
|
|
const { id = '' } = useParams()
|
|||
|
|
const { account, loading: workspaceLoading } = useOutletContext<WorkspaceContext>()
|
|||
|
|
const [connection, setConnection] = useState<ThreadsAccountConnectionData | null>(null)
|
|||
|
|
const [message, setMessage] = useState('')
|
|||
|
|
const [error, setError] = useState('')
|
|||
|
|
|
|||
|
|
const load = async () => {
|
|||
|
|
if (!id) return
|
|||
|
|
setError('')
|
|||
|
|
const conn = await api.get<ThreadsAccountConnectionData>(
|
|||
|
|
`/api/v1/threads-accounts/${encodeURIComponent(id)}/connection`,
|
|||
|
|
{ auth: true },
|
|||
|
|
)
|
|||
|
|
setConnection(conn)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
load().catch((e) => setError(e instanceof ApiError ? e.message : '載入連線設定失敗'))
|
|||
|
|
}, [id])
|
|||
|
|
|
|||
|
|
const apiReady = !!connection?.api_connected
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="grid gap-4">
|
|||
|
|
<Card className="grid gap-4">
|
|||
|
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
|||
|
|
<div className="grid gap-2">
|
|||
|
|
<SectionTitle>Threads API 連線</SectionTitle>
|
|||
|
|
<p className="text-sm leading-relaxed text-ink-secondary">
|
|||
|
|
正式流程的唯一通道。搜尋、發文、留言都走官方 API;帳號建立後預設使用此模式。
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
<Badge tone={apiReady ? 'success' : 'warning'}>
|
|||
|
|
{apiReady ? 'API 已連線' : 'API 尚未設定'}
|
|||
|
|
</Badge>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{apiReady ? (
|
|||
|
|
<Notice
|
|||
|
|
tone="success"
|
|||
|
|
title="Threads API 就緒"
|
|||
|
|
message={
|
|||
|
|
account?.username
|
|||
|
|
? `目前帳號 @${account.username.replace(/^@/, '')} 可透過 API 操作。`
|
|||
|
|
: '此帳號已具備 API 憑證,可執行任務。'
|
|||
|
|
}
|
|||
|
|
/>
|
|||
|
|
) : (
|
|||
|
|
<Notice
|
|||
|
|
tone="warning"
|
|||
|
|
title="尚未完成 API 連線"
|
|||
|
|
message="請完成 Threads OAuth / API token 設定(之後會在此頁提供授權按鈕)。在此之前任務可能無法發文或搜尋。"
|
|||
|
|
/>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
<p className="ac-hint">
|
|||
|
|
AI 產文用的 API key 在側欄「設定」管理;人設在 <AcLink to="/personas">人設庫</AcLink>{' '}
|
|||
|
|
建立,發文時於 <AcLink to={`/threads/${id}/publish`}>發文頁</AcLink> 選擇。
|
|||
|
|
</p>
|
|||
|
|
</Card>
|
|||
|
|
|
|||
|
|
{id && connection ? (
|
|||
|
|
<DevToolsPanel
|
|||
|
|
accountId={id}
|
|||
|
|
connection={connection}
|
|||
|
|
workspaceLoading={workspaceLoading}
|
|||
|
|
onConnectionChange={(data) => {
|
|||
|
|
setConnection(data)
|
|||
|
|
load().catch(() => undefined)
|
|||
|
|
}}
|
|||
|
|
onMessage={setMessage}
|
|||
|
|
onError={setError}
|
|||
|
|
/>
|
|||
|
|
) : null}
|
|||
|
|
|
|||
|
|
<ErrorText message={error} />
|
|||
|
|
<SuccessText message={message} />
|
|||
|
|
</div>
|
|||
|
|
)
|
|||
|
|
}
|