feat(dimzou): complete admin monitoring filters

This commit is contained in:
2026-09-10 12:55:45 +08:00
parent c84fc90c3d
commit e72490c498
3 changed files with 95 additions and 26 deletions
+22 -1
View File
@@ -39,9 +39,12 @@ function DimzouTranslationsPage() {
// language filter applies on Enter/blur to avoid a request per keystroke // language filter applies on Enter/blur to avoid a request per keystroke
const [languageInput, setLanguageInput] = useState('') const [languageInput, setLanguageInput] = useState('')
const [language, setLanguage] = useState('') const [language, setLanguage] = useState('')
const [sourceInput, setSourceInput] = useState('')
const [sourceDocumentId, setSourceDocumentId] = useState('')
const filters: Record<string, string> = {} const filters: Record<string, string> = {}
if (status !== 'all') filters.status = status if (status !== 'all') filters.status = status
if (language) filters.language_code = language if (language) filters.language_code = language
if (sourceDocumentId) filters.source_document_id = sourceDocumentId
const list = useListPage('dimzou-translations', fetchDimzouTranslations, filters) const list = useListPage('dimzou-translations', fetchDimzouTranslations, filters)
@@ -119,7 +122,14 @@ function DimzouTranslationsPage() {
canRetranslate ? ( canRetranslate ? (
<ConfirmDialog <ConfirmDialog
trigger={ trigger={
<Button size="sm" variant="outline" disabled={!row.original.draft_version_id}> <Button
size="sm"
variant="outline"
disabled={
!row.original.draft_version_id ||
row.original.blocks.needs_translation + row.original.blocks.translation_failed === 0
}
>
</Button> </Button>
} }
@@ -150,6 +160,17 @@ function DimzouTranslationsPage() {
placeholder="语言,如 en" placeholder="语言,如 en"
className="h-8 w-28" className="h-8 w-28"
/> />
<Input
value={sourceInput}
onChange={(event) => setSourceInput(event.target.value)}
onBlur={() => setSourceDocumentId(sourceInput.trim())}
onKeyDown={(event) => {
if (event.key === 'Enter') setSourceDocumentId(sourceInput.trim())
}}
inputMode="numeric"
placeholder="源文档 ID"
className="h-8 w-28"
/>
<Select value={status} onValueChange={setStatus}> <Select value={status} onValueChange={setStatus}>
<SelectTrigger size="sm" className="w-28"> <SelectTrigger size="sm" className="w-28">
<SelectValue /> <SelectValue />
+41 -18
View File
@@ -11,6 +11,7 @@ import { PageHeader } from '@/components/page-header'
import { DetailSheet } from '@/features/studio/detail-sheet' import { DetailSheet } from '@/features/studio/detail-sheet'
import { Badge } from '@/components/ui/badge' import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { import {
Select, Select,
SelectContent, SelectContent,
@@ -45,13 +46,17 @@ const formatTime = (value?: string | null) =>
function DimzouDocumentsPage() { function DimzouDocumentsPage() {
const [state, setState] = useState<string>('all') const [state, setState] = useState<string>('all')
const [queryInput, setQueryInput] = useState('')
const [query, setQuery] = useState('')
const [ownerInput, setOwnerInput] = useState('')
const [ownerUid, setOwnerUid] = useState('')
const [detailId, setDetailId] = useState<number | null>(null) const [detailId, setDetailId] = useState<number | null>(null)
const list = useListPage( const filters: Record<string, string> = {}
'dimzou-documents', if (state !== 'all') filters.state = state
fetchDimzouDocuments, if (query) filters.q = query
state === 'all' ? {} : { state }, if (ownerUid) filters.owner_uid = ownerUid
) const list = useListPage('dimzou-documents', fetchDimzouDocuments, filters)
const detail = useQuery({ const detail = useQuery({
queryKey: ['dimzou-document', detailId], queryKey: ['dimzou-document', detailId],
@@ -108,19 +113,37 @@ function DimzouDocumentsPage() {
title="文档监控" title="文档监控"
description="全站协作文档及其版本、译文与待审情况(只读)" description="全站协作文档及其版本、译文与待审情况(只读)"
actions={ actions={
<Select value={state} onValueChange={setState}> <div className="flex items-center gap-2">
<SelectTrigger size="sm" className="w-28"> <Input
<SelectValue /> className="h-8 w-36"
</SelectTrigger> placeholder="搜索标题,回车"
<SelectContent> value={queryInput}
<SelectItem value="all"></SelectItem> onChange={(event) => setQueryInput(event.target.value)}
{Object.entries(STATE_LABELS).map(([value, label]) => ( onBlur={() => setQuery(queryInput.trim())}
<SelectItem key={value} value={value}> onKeyDown={(event) => event.key === 'Enter' && setQuery(queryInput.trim())}
{label} />
</SelectItem> <Input
))} className="h-8 w-44"
</SelectContent> placeholder="所有者 UID,回车"
</Select> value={ownerInput}
onChange={(event) => setOwnerInput(event.target.value)}
onBlur={() => setOwnerUid(ownerInput.trim())}
onKeyDown={(event) => event.key === 'Enter' && setOwnerUid(ownerInput.trim())}
/>
<Select value={state} onValueChange={setState}>
<SelectTrigger size="sm" className="w-28">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="all"></SelectItem>
{Object.entries(STATE_LABELS).map(([value, label]) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
} }
/> />
<DataTable <DataTable
+32 -7
View File
@@ -10,6 +10,7 @@ import { PageHeader } from '@/components/page-header'
import { DetailSheet } from '@/features/studio/detail-sheet' import { DetailSheet } from '@/features/studio/detail-sheet'
import { Badge } from '@/components/ui/badge' import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { import {
Select, Select,
SelectContent, SelectContent,
@@ -28,13 +29,17 @@ const formatTime = (value?: string | null) =>
function DimzouPublicationsPage() { function DimzouPublicationsPage() {
const [visibility, setVisibility] = useState<string>('all') const [visibility, setVisibility] = useState<string>('all')
const [queryInput, setQueryInput] = useState('')
const [query, setQuery] = useState('')
const [languageInput, setLanguageInput] = useState('')
const [language, setLanguage] = useState('')
const [detail, setDetail] = useState<DimzouPublication | null>(null) const [detail, setDetail] = useState<DimzouPublication | null>(null)
const list = useListPage( const filters: Record<string, string> = {}
'dimzou-publications', if (visibility !== 'all') filters.visibility = visibility
fetchDimzouPublications, if (query) filters.q = query
visibility === 'all' ? {} : { visibility }, if (language) filters.language = language
) const list = useListPage('dimzou-publications', fetchDimzouPublications, filters)
const columns: ColumnDef<DimzouPublication>[] = [ const columns: ColumnDef<DimzouPublication>[] = [
{ {
@@ -92,7 +97,26 @@ function DimzouPublicationsPage() {
title="发布监控" title="发布监控"
description="全站已发布内容快照(只读)" description="全站已发布内容快照(只读)"
actions={ actions={
<Select value={visibility} onValueChange={setVisibility}> <div className="flex items-center gap-2">
<Input
className="h-8 w-36"
placeholder="搜索标题,回车"
value={queryInput}
onChange={(event) => setQueryInput(event.target.value)}
onBlur={() => setQuery(queryInput.trim())}
onKeyDown={(event) => event.key === 'Enter' && setQuery(queryInput.trim())}
/>
<Input
className="h-8 w-28"
placeholder="语言,如 zh-cn"
value={languageInput}
onChange={(event) => setLanguageInput(event.target.value)}
onBlur={() => setLanguage(languageInput.trim())}
onKeyDown={(event) =>
event.key === 'Enter' && setLanguage(languageInput.trim())
}
/>
<Select value={visibility} onValueChange={setVisibility}>
<SelectTrigger size="sm" className="w-28"> <SelectTrigger size="sm" className="w-28">
<SelectValue /> <SelectValue />
</SelectTrigger> </SelectTrigger>
@@ -101,7 +125,8 @@ function DimzouPublicationsPage() {
<SelectItem value="public"></SelectItem> <SelectItem value="public"></SelectItem>
<SelectItem value="group_only"></SelectItem> <SelectItem value="group_only"></SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div>
} }
/> />
<DataTable <DataTable