feat(admin): standard pagination + synced profile columns on users list
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -54,12 +54,41 @@
|
||||
<!-- 悬浮组件本体(几何随草稿即时变化) -->
|
||||
<div
|
||||
class="embed-preview-dock"
|
||||
:class="`is-${placement.side}`"
|
||||
:class="[`is-${placement.side}`, { 'is-v2': isV2 }]"
|
||||
:style="widgetStyle"
|
||||
data-test="embed-preview-widget"
|
||||
>
|
||||
<!-- UI-04 v2:真实组件预览(iframe 载 viewer /embed-preview——真实
|
||||
EmbedStream/引擎/气泡层,样例数据注入;配置经 postMessage 实时
|
||||
更新,§8.2「preview 用真实展示组件,数据源注入」)。 -->
|
||||
<div v-if="isV2 && !isCollapsed" class="embed-preview-v2frame" data-test="embed-preview-v2">
|
||||
<iframe
|
||||
ref="previewFrame"
|
||||
:src="previewSrc"
|
||||
title="PhotoLive v2 preview"
|
||||
data-test="embed-preview-v2-iframe"
|
||||
></iframe>
|
||||
</div>
|
||||
<div
|
||||
v-if="isCollapsed"
|
||||
v-else-if="isCollapsed && isV2"
|
||||
class="embed-handle embed-handle--v2"
|
||||
data-test="embed-preview-handle"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
@click="expand"
|
||||
@keydown.enter.prevent="expand"
|
||||
@keydown.space.prevent="expand"
|
||||
>
|
||||
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true" focusable="false">
|
||||
<path
|
||||
fill="#1a73e8"
|
||||
d="M9 2 7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"
|
||||
/>
|
||||
</svg>
|
||||
<span>{{ $t('embedSlotsManage.preview.handleText') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="isCollapsed"
|
||||
class="embed-handle"
|
||||
data-test="embed-preview-handle"
|
||||
role="button"
|
||||
@@ -149,6 +178,19 @@
|
||||
<span v-if="mode === 'mobile'" class="embed-preview-caption-hint">
|
||||
{{ $t('embedSlotsManage.preview.collapsedHint') }}
|
||||
</span>
|
||||
<!-- 工具区(§8.2:仅管理预览,不在实际组件):模拟点赞事件(测试模拟)。 -->
|
||||
<button
|
||||
v-if="isV2 && mode === 'desktop'"
|
||||
type="button"
|
||||
class="embed-preview-sim"
|
||||
data-test="embed-preview-sim-like"
|
||||
@click="simulateLike"
|
||||
>
|
||||
{{ $t('embedSlotsManage.preview.simLike') }}
|
||||
</button>
|
||||
<span v-if="isV2" class="embed-preview-caption-hint">
|
||||
{{ $t('embedSlotsManage.preview.sampleDataHint') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -158,6 +200,8 @@
|
||||
import {
|
||||
buildPreviewPlacement,
|
||||
buildPreviewWidgetStyle,
|
||||
clampScrollSpeed,
|
||||
embedOriginFromEnv,
|
||||
type EmbedSettingsDraft
|
||||
} from '@/utils/system/embedSlots'
|
||||
|
||||
@@ -180,6 +224,43 @@
|
||||
const placement = computed(() => buildPreviewPlacement(props.draft, props.mode))
|
||||
const widgetStyle = computed(() => buildPreviewWidgetStyle(placement.value))
|
||||
|
||||
// ── UI-04 v2 真实组件预览(§8.2)──
|
||||
const isV2 = computed(() => props.draft.displayMode === 'vertical-stream')
|
||||
const previewFrame = ref<HTMLIFrameElement | null>(null)
|
||||
const embedOrigin = embedOriginFromEnv(import.meta.env)
|
||||
|
||||
/** 预览 iframe src:初始配置经查询(速度/气泡/语言);后续更新走
|
||||
* postMessage(不整页重载,避免滚动位置闪烁)。 */
|
||||
const previewSrc = computed(() => {
|
||||
const params = new URLSearchParams({
|
||||
speed: String(clampScrollSpeed(props.draft.scrollSpeed)),
|
||||
lang: props.draft.lang === 'auto' ? 'zh-CN' : props.draft.lang
|
||||
})
|
||||
if (!props.draft.reactionsEnabled) params.set('reactions', 'off')
|
||||
return `${embedOrigin}/embed-preview?${params.toString()}`
|
||||
})
|
||||
|
||||
function postPreview(payload: Record<string, unknown>): void {
|
||||
previewFrame.value?.contentWindow?.postMessage(
|
||||
{ photolivePreview: true, ...payload },
|
||||
embedOrigin
|
||||
)
|
||||
}
|
||||
|
||||
/** 草稿速度/气泡变化 → 实时推送(不发请求不写展示位,纯预览内生效)。 */
|
||||
watch(
|
||||
() => [props.draft.scrollSpeed, props.draft.reactionsEnabled] as const,
|
||||
([speed, reactions]) => {
|
||||
if (!isV2.value) return
|
||||
postPreview({ type: 'config', speed: clampScrollSpeed(speed), reactions })
|
||||
}
|
||||
)
|
||||
|
||||
/** 模拟点赞(§8.2 工具区按钮;事件为测试模拟,注入真实校验管线)。 */
|
||||
function simulateLike(): void {
|
||||
postPreview({ type: 'burst', photoIndex: -1 })
|
||||
}
|
||||
|
||||
/** 把手/关闭仅切换预览内展开态(用户选择优先于默认值;不持久化) */
|
||||
const expanded = ref(false)
|
||||
const isCollapsed = computed(() => placement.value.collapsed && !expanded.value)
|
||||
@@ -353,6 +434,47 @@
|
||||
box-shadow: 0 4px 16px rgb(0 0 0 / 0.18);
|
||||
overflow: hidden;
|
||||
}
|
||||
/* v2 壳(对齐 loader v2 wrapper:1px #fffc 边、#10161e 底、高 280)。 */
|
||||
.embed-preview-dock.is-v2 {
|
||||
border: 1px solid #fffc;
|
||||
background: #10161e;
|
||||
box-shadow: 0 4px 16px #0f172a29;
|
||||
height: 280px;
|
||||
}
|
||||
.embed-preview-v2frame {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.embed-preview-v2frame iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
display: block;
|
||||
}
|
||||
/* v2 收起把手(对齐 loader v2:白底 100×44、蓝图标)。 */
|
||||
.embed-handle--v2 {
|
||||
padding: 0;
|
||||
width: 100px;
|
||||
gap: 8px;
|
||||
border: 1px solid #e3eaf2;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 4px 16px #0f172a20;
|
||||
color: #32618e;
|
||||
font-size: 12px;
|
||||
}
|
||||
.embed-preview-sim {
|
||||
padding: 2px 10px;
|
||||
border: 1px solid #d5dfed;
|
||||
border-radius: 6px;
|
||||
background: #fff;
|
||||
color: #285586;
|
||||
font-size: 11px;
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.embed-preview-sim:hover {
|
||||
background: #f0f6ff;
|
||||
}
|
||||
.embed-root {
|
||||
background: #fff;
|
||||
font-family:
|
||||
|
||||
Reference in New Issue
Block a user