Improve logging dialogs and word rules layout

This commit is contained in:
jxxghp
2026-07-03 19:45:58 +08:00
parent dd27bcdaca
commit 461ed560f0
7 changed files with 163 additions and 50 deletions
+29 -3
View File
@@ -51,8 +51,14 @@ function downloadLogger() {
</script>
<template>
<VDialog v-if="visible" v-model="visible" scrollable max-width="72rem" :fullscreen="!display.mdAndUp.value">
<VCard>
<VDialog
v-if="visible"
v-model="visible"
:scrollable="display.mdAndUp.value"
max-width="72rem"
:fullscreen="!display.mdAndUp.value"
>
<VCard class="logging-dialog-card">
<VDialogCloseBtn v-model="visible" />
<VCardItem>
<VCardTitle class="d-inline-flex">
@@ -75,9 +81,29 @@ function downloadLogger() {
</VCardTitle>
</VCardItem>
<VDivider />
<VCardText class="pa-0">
<VCardText class="logging-dialog-content pa-0">
<LoggingView :logfile="`plugins/${props.plugin?.id?.toLowerCase()}.log`" />
</VCardText>
</VCard>
</VDialog>
</template>
<style scoped>
@media (width <= 960px) {
.logging-dialog-card {
display: flex;
flex-direction: column;
overflow: hidden;
block-size: 100%;
}
.logging-dialog-content {
display: flex;
flex: 1 1 auto;
flex-direction: column;
inline-size: 100%;
min-block-size: 0;
overflow: hidden;
}
}
</style>
+29 -3
View File
@@ -42,8 +42,14 @@ function allLoggingDownloadUrl() {
</script>
<template>
<VDialog v-if="visible" v-model="visible" scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value">
<VCard>
<VDialog
v-if="visible"
v-model="visible"
:scrollable="display.mdAndUp.value"
max-width="80rem"
:fullscreen="!display.mdAndUp.value"
>
<VCard class="logging-dialog-card">
<VDialogCloseBtn v-model="visible" />
<VCardItem>
<VCardTitle class="d-inline-flex">
@@ -66,9 +72,29 @@ function allLoggingDownloadUrl() {
</VCardTitle>
</VCardItem>
<VDivider />
<VCardText class="pa-0">
<VCardText class="logging-dialog-content pa-0">
<LoggingView logfile="moviepilot.log" />
</VCardText>
</VCard>
</VDialog>
</template>
<style scoped>
@media (width <= 960px) {
.logging-dialog-card {
display: flex;
flex-direction: column;
overflow: hidden;
block-size: 100%;
}
.logging-dialog-content {
display: flex;
flex: 1 1 auto;
flex-direction: column;
inline-size: 100%;
min-block-size: 0;
overflow: hidden;
}
}
</style>
+4 -7
View File
@@ -2109,7 +2109,7 @@ export default {
episodeFormatRuleShort: 'Episode rules',
customIdentifiers: 'Custom Identifiers',
identifiersDesc: 'Add rules to preprocess torrent names or file names to correct identification',
identifiersPlaceholder: 'Support regular expressions, special characters need \\ escape, one line for each rule',
identifiersPlaceholder: 'Enter one identifier rule per line',
identifiersHint: 'Support regular expressions, special characters need \\ escape, one line for each rule',
formatTitle: 'Supported configuration formats (mind the spaces):',
formatContent:
@@ -2123,16 +2123,14 @@ export default {
customReleaseGroups: 'Custom Release/Subtitle Groups',
releaseGroupsDesc: 'Add release/subtitle groups that cannot be identified.',
releaseGroupsPlaceholder:
'Support regular expressions, special characters need \\ escape, one line for each group',
releaseGroupsPlaceholder: 'Enter one release/subtitle group per line',
releaseGroupsHint: 'Support regular expressions, special characters need \\ escape, one line for each group',
releaseGroupSaveSuccess: 'Custom release/subtitle groups saved successfully',
releaseGroupSaveFailed: 'Failed to save custom release/subtitle groups!',
customization: 'Custom Placeholders',
customizationDesc: 'Add custom placeholder regex patterns, use {customization} in rename format.',
customizationPlaceholder:
'Support regular expressions, special characters need \\ escape, separate multiple matches with new lines',
customizationPlaceholder: 'Enter one placeholder regex per line',
customizationHint:
'Support regular expressions, special characters need \\ escape, separate multiple matches with new lines',
customizationSaveSuccess: 'Custom placeholders saved successfully',
@@ -2140,8 +2138,7 @@ export default {
transferExcludeWords: 'File Organization Block Words',
excludeWordsDesc: 'Files or directories containing block words will not be organized.',
excludeWordsPlaceholder:
'Support regular expressions, special characters need \\ escape, one line for each block word',
excludeWordsPlaceholder: 'Enter one block word per line',
excludeWordsHint: 'Support regular expressions, special characters need \\ escape, one line for each block word',
excludeWordsSaveSuccess: 'File organization block words saved successfully',
excludeWordsSaveFailed: 'Failed to save file organization block words!',
+4 -4
View File
@@ -2073,7 +2073,7 @@ export default {
episodeFormatRuleShort: '集数规则',
customIdentifiers: '自定义识别词',
identifiersDesc: '添加规则对种子名或者文件名进行预处理以校正识别',
identifiersPlaceholder: '支持正则表达式,特殊字符需要\\转义,一行为一组',
identifiersPlaceholder: '每行输入一组识别规则',
identifiersHint: '支持正则表达式,特殊字符需要\\转义,一行为一组',
formatTitle: '支持的配置格式(注意空格):',
formatContent:
@@ -2087,21 +2087,21 @@ export default {
customReleaseGroups: '自定义制作组/字幕组',
releaseGroupsDesc: '添加无法识别的制作组/字幕组。',
releaseGroupsPlaceholder: '支持正则表达式,特殊字符需要\\转义,一行代表一个制作组/字幕组',
releaseGroupsPlaceholder: '每行输入一个制作组/字幕组',
releaseGroupsHint: '支持正则表达式,特殊字符需要\\转义,一行代表一个制作组/字幕组',
releaseGroupSaveSuccess: '自定义制作组/字幕组保存成功',
releaseGroupSaveFailed: '自定义制作组/字幕组保存失败!',
customization: '自定义占位符',
customizationDesc: '添加自定义占位符识别正则,重命名格式中添加{customization}使用。',
customizationPlaceholder: '支持正则表达式,特殊字符需要\\转义,多个匹配对象请换行分隔',
customizationPlaceholder: '每行输入一个占位符识别正则',
customizationHint: '支持正则表达式,特殊字符需要\\转义,多个匹配对象请换行分隔',
customizationSaveSuccess: '自定义占位符保存成功',
customizationSaveFailed: '自定义占位符保存失败!',
transferExcludeWords: '文件整理屏蔽词',
excludeWordsDesc: '目录名或文件名中包含屏蔽词时不进行整理。',
excludeWordsPlaceholder: '支持正则表达式,特殊字符需要\\转义,一行代表一个屏蔽词',
excludeWordsPlaceholder: '每行输入一个屏蔽词',
excludeWordsHint: '支持正则表达式,特殊字符需要\\转义,一行代表一个屏蔽词',
excludeWordsSaveSuccess: '文件整理屏蔽词保存成功',
excludeWordsSaveFailed: '文件整理屏蔽词保存失败!',
+4 -4
View File
@@ -2072,7 +2072,7 @@ export default {
episodeFormatRuleShort: '集數規則',
customIdentifiers: '自定義識別詞',
identifiersDesc: '添加規則對種子名或者文件名進行預處理以校正識別',
identifiersPlaceholder: '支持正則表達式,特殊字符需要\\轉義,一行為一組',
identifiersPlaceholder: '每行輸入一組識別規則',
identifiersHint: '支持正則表達式,特殊字符需要\\轉義,一行為一組',
formatTitle: '支持的配置格式(注意空格):',
formatContent:
@@ -2086,21 +2086,21 @@ export default {
customReleaseGroups: '自定義製作組/字幕組',
releaseGroupsDesc: '添加無法識別的製作組/字幕組。',
releaseGroupsPlaceholder: '支持正則表達式,特殊字符需要\\轉義,一行代表一個製作組/字幕組',
releaseGroupsPlaceholder: '每行輸入一個製作組/字幕組',
releaseGroupsHint: '支持正則表達式,特殊字符需要\\轉義,一行代表一個製作組/字幕組',
releaseGroupSaveSuccess: '自定義製作組/字幕組保存成功',
releaseGroupSaveFailed: '自定義製作組/字幕組保存失敗!',
customization: '自定義占位符',
customizationDesc: '添加自定義占位符識別正則,重命名格式中添加{customization}使用。',
customizationPlaceholder: '支持正則表達式,特殊字符需要\\轉義,多個匹配對象請換行分隔',
customizationPlaceholder: '每行輸入一個占位符識別正則',
customizationHint: '支持正則表達式,特殊字符需要\\轉義,多個匹配對象請換行分隔',
customizationSaveSuccess: '自定義占位符保存成功',
customizationSaveFailed: '自定義占位符保存失敗!',
transferExcludeWords: '文件整理屏蔽詞',
excludeWordsDesc: '目錄名或文件名中包含屏蔽詞時不進行整理。',
excludeWordsPlaceholder: '支持正則表達式,特殊字符需要\\轉義,一行代表一個屏蔽詞',
excludeWordsPlaceholder: '每行輸入一個屏蔽詞',
excludeWordsHint: '支持正則表達式,特殊字符需要\\轉義,一行代表一個屏蔽詞',
excludeWordsSaveSuccess: '文件整理屏蔽詞保存成功',
excludeWordsSaveFailed: '文件整理屏蔽詞保存失敗!',
+55 -9
View File
@@ -48,7 +48,8 @@ const theme = useTheme()
const display = useDisplay()
const { useSSE } = useBackground()
const DEFAULT_LEVELS = ['TRACE', 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
const DEFAULT_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR']
const HIDDEN_LEVELS = ['TRACE', 'CRITICAL']
const MAX_LOG_LINES = 600
const FLUSH_DELAY = 80
const GROUP_GAP_MS = 100
@@ -86,12 +87,12 @@ const isTransparentTheme = computed(() => theme.name.value === 'transparent')
const normalizedSearchQuery = computed(() => (searchQuery.value ?? '').trim().toLowerCase())
const { availableHeight } = useAvailableHeight(96, 320)
const loggingViewStyle = computed(() => ({
blockSize: display.mdAndUp.value ? `${availableHeight.value}px` : '100%',
}))
const loggingViewStyle = computed(() => (display.mdAndUp.value ? { blockSize: `${availableHeight.value}px` } : {}))
const levelOptions = computed(() => {
const extraLevels = parsedLogs.value.map(item => item.level).filter(level => level && !DEFAULT_LEVELS.includes(level))
const extraLevels = parsedLogs.value
.map(item => item.level)
.filter(level => level && !DEFAULT_LEVELS.includes(level) && !HIDDEN_LEVELS.includes(level))
return ['ALL', ...DEFAULT_LEVELS, ...new Set(extraLevels)]
})
@@ -700,6 +701,7 @@ onUnmounted(() => {
--logging-record-bg-even: rgba(var(--v-theme-surface-variant), 0.01);
--logging-record-bg-odd: rgba(var(--v-theme-surface-variant), 0.005);
--logging-text: rgba(var(--v-theme-on-surface), 0.88);
--logging-toolbar-control-size: 2rem;
--logging-muted: rgba(var(--v-theme-on-surface), 0.56);
display: flex;
@@ -770,7 +772,7 @@ onUnmounted(() => {
border: 1px solid rgba(var(--v-theme-on-surface), 0.14);
border-radius: var(--app-control-radius);
background: transparent;
block-size: 2rem;
block-size: var(--logging-toolbar-control-size);
box-shadow: none !important;
}
@@ -787,7 +789,6 @@ onUnmounted(() => {
text-transform: none;
}
.logging-level-toggle :deep(.logging-level-toggle__button--trace),
.logging-level-toggle :deep(.logging-level-toggle__button--debug) {
color: rgb(var(--v-theme-secondary));
}
@@ -800,8 +801,7 @@ onUnmounted(() => {
color: rgb(var(--v-theme-warning));
}
.logging-level-toggle :deep(.logging-level-toggle__button--error),
.logging-level-toggle :deep(.logging-level-toggle__button--critical) {
.logging-level-toggle :deep(.logging-level-toggle__button--error) {
color: rgb(var(--v-theme-error));
}
@@ -825,6 +825,46 @@ onUnmounted(() => {
padding-inline: 0;
}
@media (width >= 960px) {
.logging-toolbar {
padding-block-start: 0.25rem;
}
.logging-search,
.logging-stream-action {
align-self: center;
}
.logging-search :deep(.v-field) {
display: flex;
align-items: center;
block-size: var(--logging-toolbar-control-size);
min-block-size: var(--logging-toolbar-control-size);
}
.logging-search :deep(.v-field__field),
.logging-search :deep(.v-field__input),
.logging-search :deep(.v-field__prepend-inner),
.logging-search :deep(.v-field__clearable) {
align-items: center;
min-block-size: var(--logging-toolbar-control-size);
}
.logging-search :deep(.v-field__input) {
padding-block: 0;
}
.logging-search :deep(.v-field__prepend-inner),
.logging-search :deep(.v-field__clearable) {
padding-block: 0;
}
.logging-stream-action {
block-size: var(--logging-toolbar-control-size);
inline-size: var(--logging-toolbar-control-size);
}
}
.logging-shell {
position: relative;
overflow: auto;
@@ -1055,6 +1095,12 @@ onUnmounted(() => {
}
@media (width <= 960px) {
.logging-view {
flex: 1 1 auto;
block-size: auto;
min-block-size: 0;
}
.logging-record {
gap: 0.375rem;
grid-template-columns: 9.5rem minmax(0, 1fr);
+38 -20
View File
@@ -182,6 +182,11 @@ const activeGuideContent = computed(() => {
return activeTextHint.value
})
// 仅在提示内容能补充行内说明时展示折叠面板,避免捷径弹窗内重复出现相同文案。
const shouldShowGuidePanel = computed(
() => activeSection.value === 'identifiers' || activeSection.value === 'episodeRules',
)
/** 生成仅供前端拖拽列表使用的稳定规则标识。 */
function createEpisodeRuleLocalId() {
return `episode-rule-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`
@@ -519,16 +524,6 @@ onMounted(() => {
:label="t('common.enable')"
class="episode-rule-enabled"
/>
<IconBtn
variant="text"
color="error"
class="episode-rule-delete"
:aria-label="t('common.delete')"
@click.stop="deleteEpisodeRule(index)"
>
<VIcon icon="mdi-delete-outline" />
<VTooltip activator="parent" location="top">{{ t('common.delete') }}</VTooltip>
</IconBtn>
</div>
<VTextField
@@ -557,6 +552,16 @@ onMounted(() => {
required
class="episode-rule-size"
/>
<IconBtn
variant="text"
color="error"
class="episode-rule-delete"
:aria-label="t('common.delete')"
@click.stop="deleteEpisodeRule(index)"
>
<VIcon icon="mdi-delete-outline" />
<VTooltip activator="parent" location="top">{{ t('common.delete') }}</VTooltip>
</IconBtn>
</article>
</template>
</Draggable>
@@ -567,7 +572,12 @@ onMounted(() => {
</div>
</template>
<VExpansionPanels v-model="expandedHelp" class="words-help-panels" variant="accordion">
<VExpansionPanels
v-if="shouldShowGuidePanel"
v-model="expandedHelp"
class="words-help-panels"
variant="accordion"
>
<VExpansionPanel value="guide" elevation="0">
<VExpansionPanelTitle>
<template #default>
@@ -908,8 +918,10 @@ onMounted(() => {
border-radius: var(--app-surface-radius);
background: transparent;
gap: 0.75rem;
grid-template-areas: 'toolbar name pattern size';
grid-template-columns: max-content minmax(7rem, 0.8fr) minmax(13rem, 2fr) minmax(7rem, 0.65fr);
grid-template-areas:
'toolbar name size delete'
'pattern pattern pattern pattern';
grid-template-columns: max-content minmax(10rem, 1fr) minmax(9rem, 11rem) max-content;
padding: 0.85rem;
}
@@ -917,7 +929,7 @@ onMounted(() => {
display: flex;
min-block-size: 3.5rem;
align-items: center;
gap: 0.15rem;
gap: 0.3rem;
grid-area: toolbar;
}
@@ -941,6 +953,12 @@ onMounted(() => {
grid-area: size;
}
.episode-rule-delete {
align-self: center;
grid-area: delete;
justify-self: end;
}
.words-empty-state {
display: flex;
min-block-size: 10rem;
@@ -1072,11 +1090,11 @@ onMounted(() => {
.episode-rule-card {
grid-template-areas:
'toolbar'
'name'
'pattern'
'size';
grid-template-columns: minmax(0, 1fr);
'toolbar delete'
'name name'
'pattern pattern'
'size size';
grid-template-columns: minmax(0, 1fr) max-content;
gap: 0.75rem;
padding: 0.95rem;
}
@@ -1086,7 +1104,7 @@ onMounted(() => {
}
.episode-rule-delete {
margin-inline-start: auto;
margin-inline-start: 0;
}
.episode-rule-enabled :deep(.v-label) {