release: v1.4.0 — 标签系统、操作日志扩展与文档截图更新
ci / ci (22, ubuntu-latest) (push) Canceled after 0s
GitHub Release / release (push) Canceled after 0s
Publish Docker image / build (linux/amd64, ubuntu-latest, amd64) (push) Canceled after 0s
Publish Docker image / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Canceled after 0s
Publish Docker image / merge (push) Canceled after 0s
ci / ci (22, ubuntu-latest) (push) Canceled after 0s
GitHub Release / release (push) Canceled after 0s
Publish Docker image / build (linux/amd64, ubuntu-latest, amd64) (push) Canceled after 0s
Publish Docker image / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Canceled after 0s
Publish Docker image / merge (push) Canceled after 0s
- 每用户标签与彩色打标,图库 OR/AND 筛选与批量打标 - 操作日志记录登录、删除、设置与标签操作 - API 标签/打标接口;README 与文档站截图同步
This commit is contained in:
1 parent
f17d79b236
commit
737235acff
110 files changed
+5881
-778
No files matched your search
@@ -19,16 +19,11 @@ const {
|
||||
const copyFormatItems = computed(() => [
|
||||
{ label: t('copy.url'), value: 'url' as const },
|
||||
{ label: t('copy.markdown'), value: 'markdown' as const },
|
||||
{ label: t('copy.html'), value: 'html' as const }
|
||||
{ label: t('copy.html'), value: 'html' as const },
|
||||
{ label: t('copy.bbcode'), value: 'bbcode' as const }
|
||||
])
|
||||
|
||||
const clientQualityLevel = computed(() => {
|
||||
if (clientWebpQuality.value >= 85) return t('preferences.qualityHigh')
|
||||
if (clientWebpQuality.value >= 60) return t('preferences.qualityMedium')
|
||||
return t('preferences.qualityLow')
|
||||
})
|
||||
|
||||
function setCopyFormat(value: 'url' | 'markdown' | 'html') {
|
||||
function setCopyFormat(value: 'url' | 'markdown' | 'html' | 'bbcode') {
|
||||
copyFormat.value = value
|
||||
}
|
||||
|
||||
@@ -37,6 +32,11 @@ function onClientQualityInput(event: Event) {
|
||||
clientWebpQuality.value = Number.isFinite(value) ? value : 80
|
||||
}
|
||||
|
||||
function onClientQualityNumberInput(value: string | number) {
|
||||
const num = Number(value)
|
||||
clientWebpQuality.value = Number.isFinite(num) ? Math.min(100, Math.max(1, Math.round(num))) : 80
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadPreferences()
|
||||
void loadUserSettings()
|
||||
@@ -53,7 +53,7 @@ onMounted(() => {
|
||||
/>
|
||||
<div
|
||||
v-if="userSettings"
|
||||
class="flex items-start justify-between gap-4 px-4 py-4 sm:px-5"
|
||||
class="flex items-start justify-between gap-4 py-4"
|
||||
>
|
||||
<div class="min-w-0 flex-1 pr-2">
|
||||
<p class="flex flex-wrap items-center gap-x-1.5 gap-y-1 text-sm font-medium text-highlighted">
|
||||
@@ -87,55 +87,61 @@ onMounted(() => {
|
||||
class="size-5 animate-spin text-muted"
|
||||
/>
|
||||
</div>
|
||||
<div class="px-4 py-4 sm:px-5">
|
||||
<div class="flex items-start justify-between gap-4">
|
||||
<div class="min-w-0 flex-1">
|
||||
<p class="text-sm font-medium text-highlighted">
|
||||
{{ t('preferences.webpQuality') }}
|
||||
</p>
|
||||
<p class="mt-1 text-xs leading-relaxed text-muted">
|
||||
{{ t('preferences.webpQualityHint') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="shrink-0 text-right text-xs text-muted">
|
||||
<p>{{ t('preferences.current', { n: clientWebpQuality }) }}</p>
|
||||
<p class="mt-0.5">
|
||||
{{ clientQualityLevel }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="py-4">
|
||||
<div class="min-w-0">
|
||||
<p class="text-sm font-medium text-highlighted">
|
||||
{{ t('preferences.webpQuality') }}
|
||||
</p>
|
||||
<p class="mt-1 text-xs leading-relaxed text-muted">
|
||||
{{ t('preferences.webpQualityHint') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-3 flex items-center gap-3">
|
||||
<input
|
||||
type="range"
|
||||
min="1"
|
||||
max="100"
|
||||
:value="clientWebpQuality"
|
||||
class="h-1.5 min-w-0 flex-1 cursor-pointer appearance-none rounded-full bg-muted accent-primary"
|
||||
@input="onClientQualityInput"
|
||||
>
|
||||
<UInput
|
||||
:model-value="clientWebpQuality"
|
||||
type="number"
|
||||
min="1"
|
||||
max="100"
|
||||
size="xs"
|
||||
class="w-14 shrink-0 tabular-nums"
|
||||
@update:model-value="onClientQualityNumberInput"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
min="1"
|
||||
max="100"
|
||||
:value="clientWebpQuality"
|
||||
class="mt-3 h-1.5 w-full cursor-pointer appearance-none rounded-full bg-muted accent-primary"
|
||||
@input="onClientQualityInput"
|
||||
>
|
||||
</div>
|
||||
</SettingsGroup>
|
||||
</SettingsSection>
|
||||
|
||||
<SettingsSection :title="t('settings.uploadConvenience')">
|
||||
<SettingsSection :title="t('preferences.title')">
|
||||
<SettingsGroup>
|
||||
<SettingsToggleRow
|
||||
v-model="autoCopyMarkdown"
|
||||
:title="t('preferences.autoCopy')"
|
||||
:hint="t('preferences.autoCopyHint')"
|
||||
/>
|
||||
<div class="flex flex-col gap-3 px-4 py-4 sm:flex-row sm:items-center sm:justify-between sm:px-5">
|
||||
<div class="py-4">
|
||||
<p class="text-sm font-medium text-highlighted">
|
||||
{{ t('settings.defaultCopyFormat') }}
|
||||
</p>
|
||||
<p class="mt-1 text-xs leading-relaxed text-muted">
|
||||
{{ t('settings.defaultCopyFormatHint') }}
|
||||
</p>
|
||||
<div
|
||||
class="flex w-full max-w-xs gap-1 rounded-lg border border-default p-0.5 sm:w-auto"
|
||||
class="mt-3 flex w-full max-w-md gap-1 rounded-lg border border-default p-0.5"
|
||||
:class="autoCopyMarkdown ? '' : 'pointer-events-none opacity-40'"
|
||||
>
|
||||
<UButton
|
||||
v-for="item in copyFormatItems"
|
||||
:key="item.value"
|
||||
size="xs"
|
||||
class="flex-1 justify-center sm:min-w-[4.5rem]"
|
||||
class="flex-1 justify-center"
|
||||
:variant="copyFormat === item.value ? 'solid' : 'ghost'"
|
||||
:color="copyFormat === item.value ? 'primary' : 'neutral'"
|
||||
:label="item.label"
|
||||
|
||||
Reference in new issue
Block a user