mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-08-12 09:05:28 +08:00
feat: 显示共享媒体识别统计
This commit is contained in:
@@ -1839,6 +1839,10 @@ export interface RecognitionCacheData {
|
||||
recognized: number
|
||||
// 未识别数量
|
||||
unrecognized: number
|
||||
// 共享识别成功命中数量
|
||||
shared_recognized: number
|
||||
// 是否开启共享识别
|
||||
shared_recognize_enabled: boolean
|
||||
// 缓存数据
|
||||
data: RecognitionCacheItem[]
|
||||
}
|
||||
|
||||
26
src/components/cache/RecognitionCachePanel.vue
vendored
26
src/components/cache/RecognitionCachePanel.vue
vendored
@@ -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;
|
||||
|
||||
82
src/components/cache/__tests__/RecognitionCachePanel.spec.ts
vendored
Normal file
82
src/components/cache/__tests__/RecognitionCachePanel.spec.ts
vendored
Normal 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()
|
||||
})
|
||||
})
|
||||
@@ -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',
|
||||
|
||||
@@ -2485,6 +2485,7 @@ export default {
|
||||
totalCount: '总条数',
|
||||
siteCount: '站点数',
|
||||
recognized: '已识别',
|
||||
sharedRecognized: '共享识别',
|
||||
recognizedOnly: '仅已识别',
|
||||
unrecognizedOnly: '仅未识别',
|
||||
allStatuses: '全部状态',
|
||||
|
||||
@@ -2484,6 +2484,7 @@ export default {
|
||||
totalCount: '總條數',
|
||||
siteCount: '站點數',
|
||||
recognized: '已識別',
|
||||
sharedRecognized: '共享識別',
|
||||
recognizedOnly: '僅已識別',
|
||||
unrecognizedOnly: '僅未識別',
|
||||
allStatuses: '全部狀態',
|
||||
|
||||
Reference in New Issue
Block a user