diff --git a/src/views/plugin/PluginCardListView.vue b/src/views/plugin/PluginCardListView.vue index d04affbf..ab750165 100644 --- a/src/views/plugin/PluginCardListView.vue +++ b/src/views/plugin/PluginCardListView.vue @@ -955,12 +955,14 @@ async function fetchInstalledPlugins(context: KeepAliveRefreshContext = {}) { /** 将市场更新元数据投影到当前已安装快照。 */ function mergeMarketMetadataIntoInstalled() { - const marketById = new Map(uninstalledList.value.map(plugin => [plugin.id, plugin])) + const marketById = new Map( + uninstalledList.value.filter(plugin => plugin.has_update).map(plugin => [plugin.id, plugin]), + ) dataList.value.forEach(plugin => { const marketPlugin = marketById.get(plugin.id) + plugin.has_update = Boolean(marketPlugin) if (!marketPlugin) return - plugin.has_update = true plugin.repo_url = marketPlugin.repo_url plugin.history = marketPlugin.history plugin.system_version = marketPlugin.system_version diff --git a/src/views/plugin/__tests__/PluginCardListView.spec.ts b/src/views/plugin/__tests__/PluginCardListView.spec.ts index f4b2db0f..bbc42a63 100644 --- a/src/views/plugin/__tests__/PluginCardListView.spec.ts +++ b/src/views/plugin/__tests__/PluginCardListView.spec.ts @@ -694,6 +694,26 @@ describe('PluginCardListView loading and request ownership', () => { await waitForRequestsToFinish() }) + it('clears the installed update marker after a successful update refresh removes the market entry', async () => { + let marketRequest = 0 + await renderList({ + installed: () => [createPlugin({ id: 'Shared', installed: true, plugin_name: '已更新插件' })], + market: () => { + marketRequest += 1 + return marketRequest === 1 + ? [createPlugin({ has_update: true, id: 'Shared', installed: true, plugin_name: '待更新插件' })] + : [] + }, + }) + + await waitFor(() => expect(screen.getByLabelText('update-Shared')).toHaveTextContent('true')) + await fireEvent.click(screen.getByRole('button', { name: 'refresh-plugin-Shared' })) + + await waitFor(() => expect(screen.getByLabelText('update-Shared')).toHaveTextContent('false')) + expect(marketRequest).toBe(2) + await waitForRequestsToFinish() + }) + it('keeps an initial installed failure retryable instead of presenting a successful empty list', async () => { await renderList({ installedStatus: 500 }) @@ -901,6 +921,10 @@ describe('PluginCardListView installed filtering and host callbacks', () => { createPlugin({ has_update: false, id: 'Beta', installed: true, plugin_name: 'Beta', state: true }), createPlugin({ has_update: true, id: 'Gamma', installed: true, plugin_name: 'Gamma', state: false }), ], + market: () => [ + createPlugin({ has_update: true, id: 'Alpha', installed: true, plugin_name: 'Alpha' }), + createPlugin({ has_update: true, id: 'Gamma', installed: true, plugin_name: 'Gamma' }), + ], }) await screen.findByText('plugin:Alpha') await waitForRequestsToFinish()