docs: register asset status acceptance — admin branding tab shows current banner/cover/logo

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-23 10:56:14 +08:00
parent 2618ad3163
commit 63b3e539fd
7 changed files with 32 additions and 54 deletions
+12 -35
View File
@@ -10,7 +10,7 @@ import PhotoActionBar from './viewer/PhotoActionBar.vue';
import HeartParticles from './viewer/HeartParticles.vue';
import InteractionNotice from './viewer/InteractionNotice.vue';
import ThumbnailStrip, { type ThumbnailItem } from './viewer/ThumbnailStrip.vue';
import { shareOrCopy } from '../support/share';
import ShareSheet from './viewer/ShareSheet.vue';
import { reducedMotion, toggleReducedMotion } from '../ui/prefs';
import { positionDisplay } from '../viewer/position';
import { MIN_SCALE, panBy, resetZoom, wheelFactor, zoomAt, type ZoomState } from '../viewer/zoom';
@@ -432,21 +432,12 @@ function onDownloadVariant(variant: DownloadVariant): void {
// 可选中文本。分享目标为照片深链(含 lang 参数,ActivityPage 组装),
// 不分享 OSS 签名 URL ——
const shareState = ref<'idle' | 'copied' | 'failed'>('idle');
const shareSheetOpen = ref(false);
const shareUrlText = ref('');
let shareResetTimer: ReturnType<typeof setTimeout> | undefined;
async function shareCurrent(): Promise<void> {
function shareCurrent(): void {
shareUrlText.value = props.shareUrl ?? window.location.href;
const outcome = await shareOrCopy({ title: props.albumTitle ?? '', url: shareUrlText.value });
shareState.value = outcome === 'copied' ? 'copied' : outcome === 'failed' ? 'failed' : 'idle';
if (shareResetTimer !== undefined) clearTimeout(shareResetTimer);
// 失败时保留可选中文本(不自动消失),成功反馈数秒后收起。
if (outcome === 'copied') {
shareResetTimer = setTimeout(() => {
shareState.value = 'idle';
}, 3000);
}
shareSheetOpen.value = true;
}
// —— 顶栏「⋯」更多菜单(§5.1:必须有实际功能——减少动画开关) ——
@@ -519,7 +510,6 @@ onBeforeUnmount(() => {
window.removeEventListener('keydown', onKeydown);
document.removeEventListener('pointerdown', onOuterPointerDown, true);
document.body.style.overflow = savedBodyOverflow;
if (shareResetTimer !== undefined) clearTimeout(shareResetTimer);
stopLocalLikeListener?.(); // 粒子订阅随大图卸载解除(useLikes 侧不残留)
// 焦点归还触发元素(瀑布流单元格;深链直达时为 body——无可归还则不动)。
if (savedFocus !== null && savedFocus.isConnected) savedFocus.focus();
@@ -628,14 +618,16 @@ onBeforeUnmount(() => {
点击定位 = 缩略图条共用入口(序列未含该照片时忽略——不伪造定位) -->
<InteractionNotice ref="interactionNotice" @select="selectThumbnail" />
<!-- 分享弹层(2026-09-23 用户需求:二维码 + 链接 + 复制,页面级提示退役) -->
<ShareSheet
v-model="shareSheetOpen"
:heading="t('viewer.sharePhoto')"
:title="albumTitle ?? ''"
:url="shareUrlText"
/>
<div class="stage-notices">
<p v-if="extending" class="loading">{{ t('album.loading') }}</p>
<!-- 分享反馈轻提示(回退复制成功/失败;失败保留可选中文本;原生分享
成功/取消不显示——面板已收尾,§5.4) -->
<p v-if="shareState !== 'idle'" class="share-status" role="status">
{{ shareState === 'copied' ? t('viewer.shareCopied') : t('viewer.shareCopyFailed') }}
<span v-if="shareState === 'failed'" class="share-url">{{ shareUrlText }}</span>
</p>
<!-- 下载失败轻提示(端点失败/网络;DOWNLOAD_DISABLED 专属文案):
仅归属到触发下载的那张照片(§5.4 异步错误归属)。 -->
<p
@@ -907,21 +899,6 @@ onBeforeUnmount(() => {
margin: 0;
color: #d1d5db;
}
.share-status {
margin: 0;
border-radius: var(--viewer-radius-pill, 20px);
background: rgba(22, 28, 36, 0.92);
color: #f3f4f6;
padding: 6px 16px;
font-size: 0.8125rem;
pointer-events: auto;
max-width: min(92%, 480px);
}
.share-url {
user-select: all;
word-break: break-all;
color: #9fc3f5;
}
.download-failed {
margin: 0;
border-radius: var(--viewer-radius-pill, 20px);
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed, onBeforeUnmount, ref, watch } from 'vue';
import { computed, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import type { PublicAlbum, SortMode } from '../../api/client';
@@ -154,9 +154,6 @@ watch(
{ flush: 'post' },
);
onBeforeUnmount(() => {
if (shareResetTimer !== undefined) clearTimeout(shareResetTimer);
});
</script>
<template>
@@ -352,17 +349,6 @@ onBeforeUnmount(() => {
outline: 2px solid var(--viewer-primary, #1a73e8);
outline-offset: 2px;
}
.share-status {
display: block;
margin: 2px 0 0;
color: var(--viewer-text-secondary, #647084);
font-size: 0.8125rem;
}
.share-url {
user-select: text;
color: var(--viewer-primary, #1a73e8);
word-break: break-all;
}
.text-expand {
border: none;
@@ -58,16 +58,17 @@ async function drawQr(): Promise<void> {
watch(
() => [open.value, props.url] as const,
([isOpen], [wasOpen]) => {
([isOpen, url], previous) => {
if (isOpen) {
void nextTick().then(() => {
drawQr();
sheetEl.value?.focus();
});
} else if (wasOpen) {
} else if (previous !== undefined && previous[0]) {
copyState.value = 'idle';
if (copyResetTimer !== undefined) clearTimeout(copyResetTimer);
}
void url;
},
{ immediate: true },
);