mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 23:56:42 +08:00
fix(plugin): refine release version history UI (#495)
This commit is contained in:
@@ -227,12 +227,11 @@ onUnmounted(() => {
|
|||||||
class="mb-3"
|
class="mb-3"
|
||||||
:text="props.plugin?.system_version_message || t('plugin.incompatibleSystemVersion')"
|
:text="props.plugin?.system_version_message || t('plugin.incompatibleSystemVersion')"
|
||||||
/>
|
/>
|
||||||
<div class="text-center text-md-left">
|
<div class="plugin-market-detail-actions">
|
||||||
<VBtn
|
<VBtn
|
||||||
variant="tonal"
|
variant="tonal"
|
||||||
@click="showUpdateHistory"
|
@click="showUpdateHistory"
|
||||||
prepend-icon="mdi-update"
|
prepend-icon="mdi-update"
|
||||||
class="me-2"
|
|
||||||
>
|
>
|
||||||
{{ t('plugin.versionHistory') }}
|
{{ t('plugin.versionHistory') }}
|
||||||
</VBtn>
|
</VBtn>
|
||||||
@@ -244,7 +243,7 @@ onUnmounted(() => {
|
|||||||
>
|
>
|
||||||
{{ t('plugin.installToLocal') }}
|
{{ t('plugin.installToLocal') }}
|
||||||
</VBtn>
|
</VBtn>
|
||||||
<div class="text-xs mt-2" v-if="props.count">
|
<div class="plugin-market-detail-actions__downloads" v-if="props.count">
|
||||||
<VIcon icon="mdi-fire" />
|
<VIcon icon="mdi-fire" />
|
||||||
{{ t('plugin.totalDownloads', { count: formatDownloadCount(props.count) }) }}
|
{{ t('plugin.totalDownloads', { count: formatDownloadCount(props.count) }) }}
|
||||||
</div>
|
</div>
|
||||||
@@ -257,3 +256,30 @@ onUnmounted(() => {
|
|||||||
</VCard>
|
</VCard>
|
||||||
</VDialog>
|
</VDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.plugin-market-detail-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.75rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plugin-market-detail-actions__downloads {
|
||||||
|
flex-basis: 100%;
|
||||||
|
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
|
||||||
|
font-size: 0.75rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 960px) {
|
||||||
|
.plugin-market-detail-actions {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plugin-market-detail-actions__downloads {
|
||||||
|
text-align: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ const latestActionText = computed(() => props.actionMode === 'install' ? t('plug
|
|||||||
|
|
||||||
const releaseItems = computed(() => releaseDetail.value?.items || [])
|
const releaseItems = computed(() => releaseDetail.value?.items || [])
|
||||||
|
|
||||||
|
const shouldShowUpdatePanel = computed(() => props.showUpdateAction)
|
||||||
|
|
||||||
const releaseByHistoryVersion = computed(() => {
|
const releaseByHistoryVersion = computed(() => {
|
||||||
const releaseMap = new Map<string, PluginReleaseVersion>()
|
const releaseMap = new Map<string, PluginReleaseVersion>()
|
||||||
releaseItems.value.forEach(item => {
|
releaseItems.value.forEach(item => {
|
||||||
@@ -90,6 +92,11 @@ function releaseItemByHistoryVersion(version: string) {
|
|||||||
return releaseByHistoryVersion.value.get(version)
|
return releaseByHistoryVersion.value.get(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function shouldShowReleaseButton(item?: PluginReleaseVersion) {
|
||||||
|
if (!item || item.is_current) return false
|
||||||
|
return !(item.is_latest && shouldShowUpdatePanel.value && props.actionMode === 'update')
|
||||||
|
}
|
||||||
|
|
||||||
async function loadPluginHistory() {
|
async function loadPluginHistory() {
|
||||||
if (!props.plugin?.id) {
|
if (!props.plugin?.id) {
|
||||||
pluginDetail.value = null
|
pluginDetail.value = null
|
||||||
@@ -130,7 +137,7 @@ async function loadPluginHistory() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loadPluginReleases(plugin: Plugin | null | undefined = resolvedPlugin.value, force = false) {
|
async function loadPluginReleases(plugin: Plugin | null | undefined = resolvedPlugin.value, force = false) {
|
||||||
if (!plugin?.id || !plugin?.repo_url) {
|
if (!plugin?.id || !plugin?.repo_url || !plugin.release) {
|
||||||
releaseDetail.value = null
|
releaseDetail.value = null
|
||||||
releaseError.value = ''
|
releaseError.value = ''
|
||||||
return
|
return
|
||||||
@@ -190,47 +197,47 @@ watch(
|
|||||||
<VCardText v-if="releaseError" class="pb-0">
|
<VCardText v-if="releaseError" class="pb-0">
|
||||||
<VAlert type="warning" variant="tonal" density="compact" :text="releaseError" />
|
<VAlert type="warning" variant="tonal" density="compact" :text="releaseError" />
|
||||||
</VCardText>
|
</VCardText>
|
||||||
<VersionHistory :history="resolvedHistory">
|
<VersionHistory
|
||||||
<template #action="{ version }">
|
:history="resolvedHistory"
|
||||||
<div class="plugin-release-action" v-if="releaseItemByHistoryVersion(version)">
|
:has-action="version => shouldShowReleaseButton(releaseItemByHistoryVersion(version))"
|
||||||
<template v-if="releaseItemByHistoryVersion(version)">
|
>
|
||||||
<div class="plugin-release-action__meta">
|
<template #meta="{ version }">
|
||||||
<VChip v-if="releaseItemByHistoryVersion(version)?.is_current" size="x-small" color="success" variant="tonal">
|
<div v-if="releaseItemByHistoryVersion(version)" class="plugin-release-meta">
|
||||||
{{ t('plugin.currentVersion') }}
|
<span v-if="formatReleaseDate(releaseItemByHistoryVersion(version)?.published_at)" class="plugin-release-meta__date">
|
||||||
</VChip>
|
{{ formatReleaseDate(releaseItemByHistoryVersion(version)?.published_at) }}
|
||||||
<VChip v-if="releaseItemByHistoryVersion(version)?.is_latest" size="x-small" color="primary" variant="tonal">
|
</span>
|
||||||
{{ t('plugin.latestVersion') }}
|
<VChip v-if="releaseItemByHistoryVersion(version)?.is_latest" size="x-small" color="primary" variant="tonal">
|
||||||
</VChip>
|
{{ t('plugin.latestVersion') }}
|
||||||
<span v-if="formatReleaseDate(releaseItemByHistoryVersion(version)?.published_at)" class="text-caption text-medium-emphasis">
|
</VChip>
|
||||||
{{ formatReleaseDate(releaseItemByHistoryVersion(version)?.published_at) }}
|
<VChip v-if="releaseItemByHistoryVersion(version)?.is_current" size="x-small" color="success" variant="tonal">
|
||||||
</span>
|
{{ t('plugin.currentVersion') }}
|
||||||
</div>
|
</VChip>
|
||||||
<VBtn
|
|
||||||
size="small"
|
|
||||||
min-width="5.5rem"
|
|
||||||
:block="$vuetify.display.xs"
|
|
||||||
:color="releaseItemByHistoryVersion(version)?.is_latest ? 'primary' : undefined"
|
|
||||||
:variant="releaseItemByHistoryVersion(version)?.is_latest ? 'flat' : 'tonal'"
|
|
||||||
:disabled="
|
|
||||||
releaseItemByHistoryVersion(version)?.is_current ||
|
|
||||||
(releaseItemByHistoryVersion(version)?.is_latest && resolvedPlugin?.system_version_compatible === false)
|
|
||||||
"
|
|
||||||
@click.stop="handleUpdate(releaseItemByHistoryVersion(version))"
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
releaseItemByHistoryVersion(version)?.is_current
|
|
||||||
? t('plugin.installed')
|
|
||||||
: releaseItemByHistoryVersion(version)?.is_latest
|
|
||||||
? latestActionText
|
|
||||||
: t('plugin.installReleaseVersion')
|
|
||||||
}}
|
|
||||||
</VBtn>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template #action="{ version }">
|
||||||
|
<VBtn
|
||||||
|
v-if="shouldShowReleaseButton(releaseItemByHistoryVersion(version))"
|
||||||
|
class="plugin-release-button"
|
||||||
|
size="small"
|
||||||
|
min-width="5rem"
|
||||||
|
:color="releaseItemByHistoryVersion(version)?.is_latest ? 'primary' : undefined"
|
||||||
|
:variant="releaseItemByHistoryVersion(version)?.is_latest ? 'flat' : 'tonal'"
|
||||||
|
:disabled="
|
||||||
|
releaseItemByHistoryVersion(version)?.is_current ||
|
||||||
|
(releaseItemByHistoryVersion(version)?.is_latest && resolvedPlugin?.system_version_compatible === false)
|
||||||
|
"
|
||||||
|
@click.stop="handleUpdate(releaseItemByHistoryVersion(version))"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
releaseItemByHistoryVersion(version)?.is_latest
|
||||||
|
? latestActionText
|
||||||
|
: t('plugin.installReleaseVersion')
|
||||||
|
}}
|
||||||
|
</VBtn>
|
||||||
|
</template>
|
||||||
</VersionHistory>
|
</VersionHistory>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="props.showUpdateAction">
|
<template v-if="shouldShowUpdatePanel">
|
||||||
<VDivider />
|
<VDivider />
|
||||||
<VCardItem>
|
<VCardItem>
|
||||||
<VAlert
|
<VAlert
|
||||||
@@ -241,7 +248,11 @@ watch(
|
|||||||
class="mb-3"
|
class="mb-3"
|
||||||
:text="resolvedPlugin?.system_version_message || t('plugin.incompatibleSystemVersion')"
|
:text="resolvedPlugin?.system_version_message || t('plugin.incompatibleSystemVersion')"
|
||||||
/>
|
/>
|
||||||
<VBtn @click="handleUpdate()" block :disabled="resolvedPlugin?.system_version_compatible === false">
|
<VBtn
|
||||||
|
@click="handleUpdate()"
|
||||||
|
block
|
||||||
|
:disabled="resolvedPlugin?.system_version_compatible === false"
|
||||||
|
>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<VIcon icon="mdi-arrow-up-circle-outline" />
|
<VIcon icon="mdi-arrow-up-circle-outline" />
|
||||||
</template>
|
</template>
|
||||||
@@ -261,32 +272,22 @@ watch(
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-release-action,
|
.plugin-release-button {
|
||||||
.plugin-release-action__meta {
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plugin-release-meta {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-release-action {
|
.plugin-release-meta__date {
|
||||||
justify-content: flex-end;
|
color: rgba(var(--v-theme-on-surface), var(--v-disabled-opacity));
|
||||||
min-width: 10rem;
|
font-size: 0.875rem;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-release-action__meta {
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
.plugin-release-action,
|
|
||||||
.plugin-release-action__meta {
|
|
||||||
justify-content: flex-start;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.plugin-release-action {
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -27,43 +27,100 @@ function renderMarkdown(value: string) {
|
|||||||
// 输入参数
|
// 输入参数
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
history: Object as PropType<{ [key: string]: string }>,
|
history: Object as PropType<{ [key: string]: string }>,
|
||||||
|
hasAction: Function as PropType<(version: string) => boolean>,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function shouldRenderAction(version: string) {
|
||||||
|
return props.hasAction?.(version) ?? true
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VCardText class="version-history">
|
<VCardText class="version-history">
|
||||||
<VList bg-color="transparent" class="version-history__list">
|
<div class="version-history__list">
|
||||||
<VListItem v-for="(value, key) in props.history" :key="key" class="version-history__item">
|
<section v-for="(value, key) in props.history" :key="key" class="version-history__item">
|
||||||
<VListItemTitle class="font-bold text-lg">
|
<div
|
||||||
{{ key }}
|
class="version-history__top"
|
||||||
</VListItemTitle>
|
:class="{ 'version-history__top--with-action': $slots.action && shouldRenderAction(String(key)) }"
|
||||||
<div class="markdown-body text-gray-500" v-html="renderMarkdown(value)" />
|
>
|
||||||
<template v-if="$slots.action" #append>
|
<div class="version-history__header">
|
||||||
<slot name="action" :version="String(key)" />
|
<div class="version-history__version">
|
||||||
</template>
|
{{ key }}
|
||||||
</VListItem>
|
</div>
|
||||||
</VList>
|
<div v-if="$slots.meta" class="version-history__meta">
|
||||||
|
<slot name="meta" :version="String(key)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="$slots.action && shouldRenderAction(String(key))" class="version-history__action">
|
||||||
|
<slot name="action" :version="String(key)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="markdown-body text-medium-emphasis" v-html="renderMarkdown(value)" />
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.version-history {
|
.version-history {
|
||||||
padding-block: 1rem;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-history__list {
|
.version-history__list {
|
||||||
padding-block: 0;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-history__item {
|
.version-history__item {
|
||||||
align-items: start;
|
padding: 1.25rem 2rem;
|
||||||
padding-block: 0.75rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-history__item + .version-history__item {
|
.version-history__item + .version-history__item {
|
||||||
border-block-start: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
border-block-start: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.version-history__top {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
grid-template-areas: "main";
|
||||||
|
gap: 0;
|
||||||
|
align-items: center;
|
||||||
|
margin-block-end: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-history__top--with-action {
|
||||||
|
grid-template-columns: minmax(0, 1fr) max-content;
|
||||||
|
grid-template-areas: "main action";
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-history__header {
|
||||||
|
grid-area: main;
|
||||||
|
display: flex;
|
||||||
|
gap: 0.75rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-history__version {
|
||||||
|
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-history__meta {
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-history__action {
|
||||||
|
grid-area: action;
|
||||||
|
align-self: center;
|
||||||
|
justify-self: end;
|
||||||
|
}
|
||||||
|
|
||||||
.markdown-body :deep(h1),
|
.markdown-body :deep(h1),
|
||||||
.markdown-body :deep(h2),
|
.markdown-body :deep(h2),
|
||||||
.markdown-body :deep(h3) {
|
.markdown-body :deep(h3) {
|
||||||
@@ -135,22 +192,25 @@ const props = defineProps({
|
|||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.version-history {
|
.version-history {
|
||||||
padding-inline: 0.75rem;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-history__item {
|
.version-history__item {
|
||||||
padding-inline: 0;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.version-history__item .v-list-item__append) {
|
.version-history__top--with-action {
|
||||||
align-self: stretch;
|
gap: 0.75rem;
|
||||||
margin-inline-start: 0;
|
|
||||||
padding-inline-start: 0;
|
|
||||||
padding-block-start: 0.75rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.version-history__item .v-list-item__content) {
|
.version-history__header {
|
||||||
overflow: visible;
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.version-history__version {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user