feat: 显示共享媒体识别统计

This commit is contained in:
jxxghp
2026-07-30 17:50:16 +08:00
parent ca2f3da7a5
commit 55e3a8cba2
6 changed files with 113 additions and 2 deletions

View File

@@ -1839,6 +1839,10 @@ export interface RecognitionCacheData {
recognized: number
// 未识别数量
unrecognized: number
// 共享识别成功命中数量
shared_recognized: number
// 是否开启共享识别
shared_recognize_enabled: boolean
// 缓存数据
data: RecognitionCacheItem[]
}

View File

@@ -45,6 +45,8 @@ const cacheData = ref<RecognitionCacheData>({
count: 0,
recognized: 0,
unrecognized: 0,
shared_recognized: 0,
shared_recognize_enabled: false,
data: [],
})
const mobileVisibleCount = ref(MOBILE_CACHE_PAGE_SIZE)
@@ -111,9 +113,18 @@ async function loadCacheData(showSuccess = false) {
loading.value = true
const response = (await api.get(recognitionCacheEndpoint.value)) as unknown as ApiResponse<RecognitionCacheData>
if (requestId !== cacheLoadRequestId) return
const responseData = response.data ?? { count: 0, recognized: 0, unrecognized: 0, data: [] }
const responseData = response.data ?? {
count: 0,
recognized: 0,
unrecognized: 0,
shared_recognized: 0,
shared_recognize_enabled: false,
data: [],
}
cacheData.value = {
...responseData,
shared_recognized: responseData.shared_recognized ?? 0,
shared_recognize_enabled: responseData.shared_recognize_enabled ?? false,
data: responseData.data.map(item => ({ ...item, recognition_id: getRecognitionId(item) })),
}
selectedItems.value = selectedItems.value.filter(key => cacheData.value.data.some(item => item.key === key))
@@ -276,13 +287,20 @@ watch(recognitionSource, () => {
<span>{{ t('setting.cache.recognized') }}</span>
</div>
</div>
<div v-if="!isMobile" class="cache-panel-stat cache-panel-stat--warning">
<div v-if="!isMobile || cacheData.shared_recognize_enabled" class="cache-panel-stat cache-panel-stat--warning">
<VIcon icon="mdi-help-circle-outline" size="22" />
<div>
<strong>{{ cacheData.unrecognized }}</strong>
<span>{{ t('setting.cache.unrecognized') }}</span>
</div>
</div>
<div v-if="cacheData.shared_recognize_enabled" class="cache-panel-stat cache-panel-stat--info">
<VIcon icon="mdi-cloud-check-outline" :size="isMobile ? 32 : 22" />
<div>
<strong>{{ cacheData.shared_recognized }}</strong>
<span>{{ t('setting.cache.sharedRecognized') }}</span>
</div>
</div>
</div>
<div v-if="!isMobile" class="cache-panel-actions">
@@ -550,6 +568,10 @@ watch(recognitionSource, () => {
color: rgb(var(--v-theme-warning));
}
.cache-panel-stat--info {
color: rgb(var(--v-theme-info));
}
.cache-panel-actions {
display: flex;
flex: 0 0 auto;

View File

@@ -0,0 +1,82 @@
import RecognitionCachePanel from '@/components/cache/RecognitionCachePanel.vue'
import { screen, waitFor } from '@testing-library/vue'
import { renderWithProviders } from '@tests/support/render'
import { beforeEach, describe, expect, it, vi } from 'vitest'
const mocks = vi.hoisted(() => ({
apiGet: vi.fn(),
toastError: vi.fn(),
toastSuccess: vi.fn(),
}))
vi.mock('@/api', () => ({
default: {
get: mocks.apiGet,
},
}))
vi.mock('vue-toastification', () => ({
useToast: () => ({
error: mocks.toastError,
success: mocks.toastSuccess,
}),
}))
async function renderRecognitionCachePanel() {
return renderWithProviders(RecognitionCachePanel, {
initialState: {
globalSettings: {
data: {
GLOBAL_IMAGE_CACHE: false,
RECOGNIZE_SOURCE: 'themoviedb',
TMDB_IMAGE_DOMAIN: 'image.tmdb.org',
},
},
},
})
}
describe('RecognitionCachePanel shared recognition statistics', () => {
beforeEach(() => {
mocks.apiGet.mockReset()
mocks.toastError.mockReset()
mocks.toastSuccess.mockReset()
})
it('shows the persisted shared recognition count when sharing is enabled', async () => {
mocks.apiGet.mockResolvedValue({
data: {
count: 12,
recognized: 9,
unrecognized: 3,
shared_recognized: 27,
shared_recognize_enabled: true,
data: [],
},
})
await renderRecognitionCachePanel()
expect(await screen.findByText('共享识别')).toBeInTheDocument()
expect(screen.getByText('27')).toBeInTheDocument()
expect(screen.getByText('未识别')).toBeInTheDocument()
})
it('hides shared recognition statistics when sharing is disabled', async () => {
mocks.apiGet.mockResolvedValue({
data: {
count: 12,
recognized: 9,
unrecognized: 3,
shared_recognized: 27,
shared_recognize_enabled: false,
data: [],
},
})
await renderRecognitionCachePanel()
await waitFor(() => expect(mocks.apiGet).toHaveBeenCalledWith('tmdb/cache'))
expect(screen.queryByText('共享识别')).not.toBeInTheDocument()
})
})

View File

@@ -2536,6 +2536,7 @@ export default {
totalCount: 'Total Count',
siteCount: 'Site Count',
recognized: 'Recognized',
sharedRecognized: 'Shared Recognition',
recognizedOnly: 'Recognized Only',
unrecognizedOnly: 'Unrecognized Only',
allStatuses: 'All Statuses',

View File

@@ -2485,6 +2485,7 @@ export default {
totalCount: '总条数',
siteCount: '站点数',
recognized: '已识别',
sharedRecognized: '共享识别',
recognizedOnly: '仅已识别',
unrecognizedOnly: '仅未识别',
allStatuses: '全部状态',

View File

@@ -2484,6 +2484,7 @@ export default {
totalCount: '總條數',
siteCount: '站點數',
recognized: '已識別',
sharedRecognized: '共享識別',
recognizedOnly: '僅已識別',
unrecognizedOnly: '僅未識別',
allStatuses: '全部狀態',