mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-07 08:46:40 +08:00
fix: compact plugin market settings dialog
This commit is contained in:
@@ -236,15 +236,6 @@ function formatRepoDisplay(url: string) {
|
|||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取仓库地址的主机名用于辅助显示。 */
|
|
||||||
function formatRepoHost(url: string) {
|
|
||||||
try {
|
|
||||||
return new URL(url).hostname
|
|
||||||
} catch {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 返回拖拽列表项的稳定键。 */
|
/** 返回拖拽列表项的稳定键。 */
|
||||||
function repoItemKey(repo: string) {
|
function repoItemKey(repo: string) {
|
||||||
return repo
|
return repo
|
||||||
@@ -256,26 +247,17 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VDialog width="56rem" scrollable :fullscreen="!display.mdAndUp.value">
|
<VDialog width="56rem" :fullscreen="!display.mdAndUp.value">
|
||||||
<VCard class="plugin-market-dialog-card">
|
<VCard class="plugin-market-dialog-card">
|
||||||
<VCardItem>
|
<VCardItem class="plugin-market-card-item">
|
||||||
<div class="plugin-market-header">
|
<div class="plugin-market-header">
|
||||||
<div class="plugin-market-title-block">
|
<VCardTitle class="plugin-market-title d-flex align-center pa-0">
|
||||||
<VCardTitle class="d-flex align-center pa-0">
|
<VIcon icon="mdi-store-cog" class="me-2" />
|
||||||
<VIcon icon="mdi-store-cog" class="me-2" />
|
{{ t('dialog.pluginMarketSetting.title') }}
|
||||||
{{ t('dialog.pluginMarketSetting.title') }}
|
</VCardTitle>
|
||||||
</VCardTitle>
|
|
||||||
<div class="plugin-market-subtitle">
|
|
||||||
{{ t('dialog.pluginMarketSetting.description') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<VChip color="primary" variant="tonal" prepend-icon="mdi-source-repository">
|
|
||||||
{{ t('dialog.pluginMarketSetting.repoCount', { count: activeRepoCount }) }}
|
|
||||||
</VChip>
|
|
||||||
</div>
|
</div>
|
||||||
<VDialogCloseBtn @click="emit('close')" />
|
<VDialogCloseBtn @click="emit('close')" />
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VDivider />
|
|
||||||
|
|
||||||
<VCardText class="plugin-market-dialog-body pt-4">
|
<VCardText class="plugin-market-dialog-body pt-4">
|
||||||
<div class="plugin-market-toolbar">
|
<div class="plugin-market-toolbar">
|
||||||
@@ -295,10 +277,6 @@ onMounted(() => {
|
|||||||
{{ t('dialog.pluginMarketSetting.textMode') }}
|
{{ t('dialog.pluginMarketSetting.textMode') }}
|
||||||
</VBtn>
|
</VBtn>
|
||||||
</VBtnToggle>
|
</VBtnToggle>
|
||||||
|
|
||||||
<div class="plugin-market-toolbar-info">
|
|
||||||
{{ editorMode === 'list' ? t('dialog.pluginMarketSetting.listHint') : t('dialog.pluginMarketSetting.textHint') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="editorMode === 'list'" class="plugin-market-list-panel">
|
<div v-if="editorMode === 'list'" class="plugin-market-list-panel">
|
||||||
@@ -353,15 +331,6 @@ onMounted(() => {
|
|||||||
<div class="plugin-market-repo-title">
|
<div class="plugin-market-repo-title">
|
||||||
<span class="plugin-market-repo-index">{{ index + 1 }}</span>
|
<span class="plugin-market-repo-index">{{ index + 1 }}</span>
|
||||||
<span class="text-truncate" :title="repo">{{ formatRepoDisplay(repo) }}</span>
|
<span class="text-truncate" :title="repo">{{ formatRepoDisplay(repo) }}</span>
|
||||||
<VChip
|
|
||||||
v-if="formatRepoHost(repo)"
|
|
||||||
size="x-small"
|
|
||||||
variant="tonal"
|
|
||||||
color="secondary"
|
|
||||||
class="plugin-market-host-chip"
|
|
||||||
>
|
|
||||||
{{ formatRepoHost(repo) }}
|
|
||||||
</VChip>
|
|
||||||
</div>
|
</div>
|
||||||
</VListItemTitle>
|
</VListItemTitle>
|
||||||
<VListItemSubtitle class="text-truncate mt-1" :title="repo">
|
<VListItemSubtitle class="text-truncate mt-1" :title="repo">
|
||||||
@@ -417,9 +386,7 @@ onMounted(() => {
|
|||||||
<VTextarea
|
<VTextarea
|
||||||
v-model="repoText"
|
v-model="repoText"
|
||||||
class="plugin-market-textarea"
|
class="plugin-market-textarea"
|
||||||
rows="11"
|
rows="8"
|
||||||
auto-grow
|
|
||||||
max-rows="18"
|
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
prepend-inner-icon="mdi-text-box-edit-outline"
|
prepend-inner-icon="mdi-text-box-edit-outline"
|
||||||
:placeholder="t('dialog.pluginMarketSetting.textPlaceholder')"
|
:placeholder="t('dialog.pluginMarketSetting.textPlaceholder')"
|
||||||
@@ -427,28 +394,6 @@ onMounted(() => {
|
|||||||
persistent-hint
|
persistent-hint
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="plugin-market-text-summary">
|
|
||||||
<VChip color="primary" variant="tonal" prepend-icon="mdi-check-circle-outline">
|
|
||||||
{{ t('dialog.pluginMarketSetting.repoCount', { count: parsedTextRepos.repos.length }) }}
|
|
||||||
</VChip>
|
|
||||||
<VChip
|
|
||||||
v-if="parsedTextRepos.duplicateRepos.length > 0"
|
|
||||||
color="warning"
|
|
||||||
variant="tonal"
|
|
||||||
prepend-icon="mdi-content-duplicate"
|
|
||||||
>
|
|
||||||
{{ t('dialog.pluginMarketSetting.duplicateCount', { count: parsedTextRepos.duplicateRepos.length }) }}
|
|
||||||
</VChip>
|
|
||||||
<VChip
|
|
||||||
v-if="parsedTextRepos.invalidRepos.length > 0"
|
|
||||||
color="error"
|
|
||||||
variant="tonal"
|
|
||||||
prepend-icon="mdi-alert-circle-outline"
|
|
||||||
>
|
|
||||||
{{ t('dialog.pluginMarketSetting.invalidCount', { count: parsedTextRepos.invalidRepos.length }) }}
|
|
||||||
</VChip>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<VAlert
|
<VAlert
|
||||||
v-if="parsedTextRepos.invalidRepos.length > 0"
|
v-if="parsedTextRepos.invalidRepos.length > 0"
|
||||||
type="error"
|
type="error"
|
||||||
@@ -473,15 +418,8 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
|
|
||||||
<VDivider />
|
|
||||||
<VCardActions class="plugin-market-actions">
|
<VCardActions class="plugin-market-actions">
|
||||||
<div class="plugin-market-footer-summary">
|
|
||||||
{{ t('dialog.pluginMarketSetting.repoCount', { count: activeRepoCount }) }}
|
|
||||||
</div>
|
|
||||||
<VSpacer />
|
<VSpacer />
|
||||||
<VBtn variant="text" @click="emit('close')">
|
|
||||||
{{ t('dialog.pluginMarketSetting.close') }}
|
|
||||||
</VBtn>
|
|
||||||
<VBtn
|
<VBtn
|
||||||
color="primary"
|
color="primary"
|
||||||
variant="flat"
|
variant="flat"
|
||||||
@@ -501,67 +439,56 @@ onMounted(() => {
|
|||||||
.plugin-market-dialog-card {
|
.plugin-market-dialog-card {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
max-block-size: min(82vh, 50rem);
|
block-size: min(82vh, 50rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.plugin-market-card-item {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
padding-block: 0.875rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-header {
|
.plugin-market-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
padding-inline-end: 2rem;
|
padding-inline-end: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-title-block {
|
.plugin-market-title {
|
||||||
min-inline-size: 0;
|
min-inline-size: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-subtitle {
|
|
||||||
color: rgba(var(--v-theme-on-surface), 0.68);
|
|
||||||
font-size: 0.875rem;
|
|
||||||
margin-block-start: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.plugin-market-dialog-body {
|
.plugin-market-dialog-body {
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 0.875rem;
|
||||||
min-block-size: 0;
|
min-block-size: 0;
|
||||||
|
padding-block: 0.875rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-toolbar {
|
.plugin-market-toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
flex-shrink: 0;
|
||||||
justify-content: space-between;
|
|
||||||
gap: 1rem;
|
|
||||||
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
|
||||||
border-radius: 8px;
|
|
||||||
background: rgba(var(--v-theme-surface-variant), 0.18);
|
|
||||||
padding: 0.75rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-mode-toggle {
|
.plugin-market-mode-toggle {
|
||||||
flex-shrink: 0;
|
inline-size: 100%;
|
||||||
|
|
||||||
:deep(.v-btn) {
|
:deep(.v-btn) {
|
||||||
min-inline-size: 7rem;
|
flex: 1;
|
||||||
|
min-inline-size: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-toolbar-info {
|
|
||||||
color: rgba(var(--v-theme-on-surface), 0.68);
|
|
||||||
font-size: 0.875rem;
|
|
||||||
text-align: end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.plugin-market-list-panel,
|
.plugin-market-list-panel,
|
||||||
.plugin-market-text-panel {
|
.plugin-market-text-panel {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 0.75rem;
|
||||||
min-block-size: 0;
|
min-block-size: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,7 +501,7 @@ onMounted(() => {
|
|||||||
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: rgba(var(--v-theme-surface), 0.72);
|
background: rgba(var(--v-theme-surface), 0.72);
|
||||||
min-block-size: 14rem;
|
min-block-size: 0;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,10 +528,6 @@ onMounted(() => {
|
|||||||
inline-size: 1.75rem;
|
inline-size: 1.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-host-chip {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.plugin-market-empty {
|
.plugin-market-empty {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -614,18 +537,30 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-textarea {
|
.plugin-market-textarea {
|
||||||
|
flex: 1;
|
||||||
|
min-block-size: 0;
|
||||||
|
|
||||||
|
:deep(.v-input__control),
|
||||||
|
:deep(.v-field),
|
||||||
|
:deep(.v-field__field) {
|
||||||
|
block-size: 100%;
|
||||||
|
min-block-size: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.v-field__input) {
|
||||||
|
align-items: stretch;
|
||||||
|
block-size: 100%;
|
||||||
|
min-block-size: 0;
|
||||||
|
}
|
||||||
|
|
||||||
:deep(textarea) {
|
:deep(textarea) {
|
||||||
|
block-size: 100%;
|
||||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-text-summary {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.plugin-market-invalid-alert {
|
.plugin-market-invalid-alert {
|
||||||
:deep(.v-alert__content) {
|
:deep(.v-alert__content) {
|
||||||
min-inline-size: 0;
|
min-inline-size: 0;
|
||||||
@@ -633,28 +568,34 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-actions {
|
.plugin-market-actions {
|
||||||
|
flex: 0 0 auto;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
padding: 0.75rem 1.5rem 1rem;
|
||||||
|
|
||||||
.plugin-market-footer-summary {
|
|
||||||
color: rgba(var(--v-theme-on-surface), 0.62);
|
|
||||||
font-size: 0.875rem;
|
|
||||||
margin-inline-start: 0.5rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.plugin-market-dialog-card {
|
.plugin-market-dialog-card {
|
||||||
max-block-size: 100vh;
|
block-size: 100dvh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-header,
|
.plugin-market-card-item {
|
||||||
.plugin-market-toolbar {
|
padding: 0.75rem 1rem 0.625rem;
|
||||||
align-items: stretch;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-toolbar-info {
|
.plugin-market-header {
|
||||||
text-align: start;
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding-inline-end: 2.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plugin-market-header :deep(.v-card-title) {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plugin-market-dialog-body {
|
||||||
|
gap: 0.625rem;
|
||||||
|
padding: 0.75rem 1rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-mode-toggle {
|
.plugin-market-mode-toggle {
|
||||||
@@ -666,8 +607,21 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.plugin-market-footer-summary {
|
.plugin-market-list-panel,
|
||||||
display: none;
|
.plugin-market-text-panel {
|
||||||
|
gap: 0.625rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plugin-market-list-wrap {
|
||||||
|
min-block-size: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plugin-market-empty {
|
||||||
|
min-block-size: 10rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plugin-market-actions {
|
||||||
|
padding: 0.75rem 1rem calc(0.75rem + env(safe-area-inset-bottom));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2485,7 +2485,6 @@ export default {
|
|||||||
},
|
},
|
||||||
pluginMarketSetting: {
|
pluginMarketSetting: {
|
||||||
title: 'Plugin Market Settings',
|
title: 'Plugin Market Settings',
|
||||||
description: 'Maintain plugin market repositories as an ordered list or by pasting bulk text.',
|
|
||||||
repoUrl: 'Plugin Repository URL',
|
repoUrl: 'Plugin Repository URL',
|
||||||
repoPlaceholder: 'Format: https://github.com/jxxghp/MoviePilot-Plugins/,https://github.com/xxxx/xxxxxx/',
|
repoPlaceholder: 'Format: https://github.com/jxxghp/MoviePilot-Plugins/,https://github.com/xxxx/xxxxxx/',
|
||||||
repoHint: 'Separate multiple URLs with new lines or commas',
|
repoHint: 'Separate multiple URLs with new lines or commas',
|
||||||
@@ -2493,13 +2492,9 @@ export default {
|
|||||||
textPlaceholder: 'https://github.com/jxxghp/MoviePilot-Plugins/\nhttps://github.com/xxxx/xxxxxx/',
|
textPlaceholder: 'https://github.com/jxxghp/MoviePilot-Plugins/\nhttps://github.com/xxxx/xxxxxx/',
|
||||||
listMode: 'List',
|
listMode: 'List',
|
||||||
textMode: 'Text',
|
textMode: 'Text',
|
||||||
listHint: 'Add, edit, delete, or drag repositories to adjust their order.',
|
|
||||||
textHint: 'Paste repository URLs one per line or separated by commas.',
|
textHint: 'Paste repository URLs one per line or separated by commas.',
|
||||||
addRepo: 'Add repository',
|
addRepo: 'Add repository',
|
||||||
noRepos: 'No plugin repository URLs',
|
noRepos: 'No plugin repository URLs',
|
||||||
repoCount: '{count} repositories',
|
|
||||||
duplicateCount: '{count} duplicates',
|
|
||||||
invalidCount: '{count} invalid',
|
|
||||||
invalidUrl: 'Please enter a valid URL',
|
invalidUrl: 'Please enter a valid URL',
|
||||||
duplicateUrl: 'This URL already exists',
|
duplicateUrl: 'This URL already exists',
|
||||||
invalidText: 'There are {count} invalid URLs in the text. Fix them before saving.',
|
invalidText: 'There are {count} invalid URLs in the text. Fix them before saving.',
|
||||||
|
|||||||
@@ -2440,7 +2440,6 @@ export default {
|
|||||||
},
|
},
|
||||||
pluginMarketSetting: {
|
pluginMarketSetting: {
|
||||||
title: '插件市场设置',
|
title: '插件市场设置',
|
||||||
description: '维护插件市场仓库来源,可按列表逐条调整,也可直接粘贴批量文本。',
|
|
||||||
repoUrl: '插件仓库地址',
|
repoUrl: '插件仓库地址',
|
||||||
repoPlaceholder: '格式:https://github.com/jxxghp/MoviePilot-Plugins/,https://github.com/xxxx/xxxxxx/',
|
repoPlaceholder: '格式:https://github.com/jxxghp/MoviePilot-Plugins/,https://github.com/xxxx/xxxxxx/',
|
||||||
repoHint: '多个地址可使用换行或英文逗号分隔',
|
repoHint: '多个地址可使用换行或英文逗号分隔',
|
||||||
@@ -2448,13 +2447,9 @@ export default {
|
|||||||
textPlaceholder: 'https://github.com/jxxghp/MoviePilot-Plugins/\nhttps://github.com/xxxx/xxxxxx/',
|
textPlaceholder: 'https://github.com/jxxghp/MoviePilot-Plugins/\nhttps://github.com/xxxx/xxxxxx/',
|
||||||
listMode: '列表维护',
|
listMode: '列表维护',
|
||||||
textMode: '文本维护',
|
textMode: '文本维护',
|
||||||
listHint: '逐条添加、编辑、删除或拖拽调整仓库顺序。',
|
|
||||||
textHint: '直接粘贴仓库地址串,一行一个或使用英文逗号分隔。',
|
textHint: '直接粘贴仓库地址串,一行一个或使用英文逗号分隔。',
|
||||||
addRepo: '添加仓库',
|
addRepo: '添加仓库',
|
||||||
noRepos: '暂无插件仓库地址',
|
noRepos: '暂无插件仓库地址',
|
||||||
repoCount: '{count} 个仓库',
|
|
||||||
duplicateCount: '{count} 个重复',
|
|
||||||
invalidCount: '{count} 个无效',
|
|
||||||
invalidUrl: '请输入有效的URL地址',
|
invalidUrl: '请输入有效的URL地址',
|
||||||
duplicateUrl: '该地址已存在',
|
duplicateUrl: '该地址已存在',
|
||||||
invalidText: '文本中有 {count} 个无效地址,请修正后保存。',
|
invalidText: '文本中有 {count} 个无效地址,请修正后保存。',
|
||||||
|
|||||||
@@ -2441,7 +2441,6 @@ export default {
|
|||||||
},
|
},
|
||||||
pluginMarketSetting: {
|
pluginMarketSetting: {
|
||||||
title: '插件市場設置',
|
title: '插件市場設置',
|
||||||
description: '維護插件市場倉庫來源,可按列表逐條調整,也可直接貼上批量文字。',
|
|
||||||
repoUrl: '插件倉庫地址',
|
repoUrl: '插件倉庫地址',
|
||||||
repoPlaceholder: '格式:https://github.com/jxxghp/MoviePilot-Plugins/,https://github.com/xxxx/xxxxxx/',
|
repoPlaceholder: '格式:https://github.com/jxxghp/MoviePilot-Plugins/,https://github.com/xxxx/xxxxxx/',
|
||||||
repoHint: '多個地址可使用換行或英文逗號分隔',
|
repoHint: '多個地址可使用換行或英文逗號分隔',
|
||||||
@@ -2449,13 +2448,9 @@ export default {
|
|||||||
textPlaceholder: 'https://github.com/jxxghp/MoviePilot-Plugins/\nhttps://github.com/xxxx/xxxxxx/',
|
textPlaceholder: 'https://github.com/jxxghp/MoviePilot-Plugins/\nhttps://github.com/xxxx/xxxxxx/',
|
||||||
listMode: '列表維護',
|
listMode: '列表維護',
|
||||||
textMode: '文字維護',
|
textMode: '文字維護',
|
||||||
listHint: '逐條新增、編輯、刪除或拖曳調整倉庫順序。',
|
|
||||||
textHint: '直接貼上倉庫地址串,一行一個或使用英文逗號分隔。',
|
textHint: '直接貼上倉庫地址串,一行一個或使用英文逗號分隔。',
|
||||||
addRepo: '新增倉庫',
|
addRepo: '新增倉庫',
|
||||||
noRepos: '暫無插件倉庫地址',
|
noRepos: '暫無插件倉庫地址',
|
||||||
repoCount: '{count} 個倉庫',
|
|
||||||
duplicateCount: '{count} 個重複',
|
|
||||||
invalidCount: '{count} 個無效',
|
|
||||||
invalidUrl: '請輸入有效的URL地址',
|
invalidUrl: '請輸入有效的URL地址',
|
||||||
duplicateUrl: '該地址已存在',
|
duplicateUrl: '該地址已存在',
|
||||||
invalidText: '文字中有 {count} 個無效地址,請修正後儲存。',
|
invalidText: '文字中有 {count} 個無效地址,請修正後儲存。',
|
||||||
|
|||||||
Reference in New Issue
Block a user