feat(admin): standard pagination + synced profile columns on users list
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -264,8 +264,11 @@ describe('嵌入代码 v2 入口(UI-04:displayMode=vertical-stream → /embe
|
||||
})
|
||||
|
||||
describe('buildPreviewPlacement 本地预览停靠几何(草稿即时反映,纯本地)', () => {
|
||||
it('desktop:按配置展开(collapsed=collapsedDefault),几何随草稿字段变化', () => {
|
||||
const placement = buildPreviewPlacement({ ...DEFAULT_EMBED_SETTINGS }, 'desktop')
|
||||
it('desktop:按配置展开(collapsed=collapsedDefault),几何随草稿字段变化(carousel)', () => {
|
||||
const placement = buildPreviewPlacement(
|
||||
{ ...DEFAULT_EMBED_SETTINGS, displayMode: 'carousel' },
|
||||
'desktop'
|
||||
)
|
||||
expect(placement).toEqual({
|
||||
side: 'right',
|
||||
size: 'md',
|
||||
@@ -278,7 +281,14 @@ describe('buildPreviewPlacement 本地预览停靠几何(草稿即时反映,
|
||||
})
|
||||
// 表单字段变化 → 预览几何即时跟随(未保存修改即时反映的纯逻辑基础)
|
||||
const changed = buildPreviewPlacement(
|
||||
{ ...DEFAULT_EMBED_SETTINGS, position: 'left', size: 'sm', offsetX: 40, zIndex: 2000 },
|
||||
{
|
||||
...DEFAULT_EMBED_SETTINGS,
|
||||
displayMode: 'carousel',
|
||||
position: 'left',
|
||||
size: 'sm',
|
||||
offsetX: 40,
|
||||
zIndex: 2000
|
||||
},
|
||||
'desktop'
|
||||
)
|
||||
expect(changed.side).toBe('left')
|
||||
@@ -294,24 +304,30 @@ describe('buildPreviewPlacement 本地预览停靠几何(草稿即时反映,
|
||||
})
|
||||
// collapsedDefault 仅作用于桌面预览初始形态
|
||||
expect(
|
||||
buildPreviewPlacement({ ...DEFAULT_EMBED_SETTINGS, collapsedDefault: true }, 'desktop')
|
||||
.collapsed
|
||||
buildPreviewPlacement(
|
||||
{ ...DEFAULT_EMBED_SETTINGS, displayMode: 'carousel', collapsedDefault: true },
|
||||
'desktop'
|
||||
).collapsed
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it('mobile:窄屏强制 sm + 默认收起(§5.4 <480px);宽度按剩余宽收缩防溢出', () => {
|
||||
const placement = buildPreviewPlacement({ ...DEFAULT_EMBED_SETTINGS }, 'mobile')
|
||||
it('v2(vertical-stream):恒 195 宽(无 sm 降档),mobile 仍默认收起(§2.1)', () => {
|
||||
expect(buildPreviewPlacement({ ...DEFAULT_EMBED_SETTINGS }, 'desktop').width).toBe(195)
|
||||
expect(buildPreviewPlacement({ ...DEFAULT_EMBED_SETTINGS }, 'mobile').width).toBe(195)
|
||||
expect(buildPreviewPlacement({ ...DEFAULT_EMBED_SETTINGS }, 'mobile').size).toBe('md')
|
||||
expect(buildPreviewPlacement({ ...DEFAULT_EMBED_SETTINGS }, 'mobile').collapsed).toBe(true)
|
||||
expect(buildPreviewPlacement({ ...DEFAULT_EMBED_SETTINGS }, 'desktop').collapsed).toBe(false)
|
||||
})
|
||||
|
||||
it('mobile:窄屏强制 sm + 默认收起(§5.4 <480px);宽度按剩余宽收缩防溢出(carousel)', () => {
|
||||
const v1 = { ...DEFAULT_EMBED_SETTINGS, displayMode: 'carousel' }
|
||||
const placement = buildPreviewPlacement(v1, 'mobile')
|
||||
expect(placement.size).toBe('sm')
|
||||
expect(placement.width).toBe(280)
|
||||
expect(placement.collapsed).toBe(true) // 窄屏强制收起(与 collapsedDefault 无关)
|
||||
expect(
|
||||
buildPreviewPlacement({ ...DEFAULT_EMBED_SETTINGS, collapsedDefault: false }, 'mobile')
|
||||
.collapsed
|
||||
).toBe(true)
|
||||
expect(buildPreviewPlacement({ ...v1, collapsedDefault: false }, 'mobile').collapsed).toBe(true)
|
||||
// 偏移挤占剩余宽 → 宽度取小(375 - 120 - 8 = 247)
|
||||
expect(buildPreviewPlacement({ ...DEFAULT_EMBED_SETTINGS, offsetX: 120 }, 'mobile').width).toBe(
|
||||
247
|
||||
)
|
||||
expect(buildPreviewPlacement({ ...v1, offsetX: 120 }, 'mobile').width).toBe(247)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -39,6 +39,10 @@ export const EMBED_Z_INDEX_MAX = 2147483000
|
||||
export const EMBED_SCROLL_SPEED_MIN = 8
|
||||
export const EMBED_SCROLL_SPEED_MAX = 32
|
||||
|
||||
/** v2 固定窗尺寸(CSS px,§2.1 硬性:PC/手机同值;对齐 loader V2_WIDTH/HEIGHT)。 */
|
||||
export const EMBED_V2_WIDTH = 195
|
||||
export const EMBED_V2_HEIGHT = 280
|
||||
|
||||
/** size → 悬浮组件宽度 px(sm 窄屏降级档;与 loader SIZE_WIDTH 对齐) */
|
||||
export const EMBED_SIZE_WIDTH: Record<Api.EmbedSlot.Size, number> = { sm: 280, md: 320 }
|
||||
|
||||
@@ -253,22 +257,24 @@ export const EMBED_PREVIEW_FRAME_WIDTH: Record<'desktop' | 'mobile', number> = {
|
||||
mobile: 375
|
||||
}
|
||||
|
||||
/** 表单草稿 → 预览停靠几何(desktop=按配置;mobile=窄屏强制 sm+收起)。
|
||||
/** 表单草稿 → 预览停靠几何(desktop=按配置;mobile=窄屏强制收起)。
|
||||
* 数值全部经契约夹取——表单输入的中间态(空/越界)预览不抖动;宽度按
|
||||
* loader applyWrapperBox 同规则取配置宽与视口剩余宽的较小值。 */
|
||||
* loader applyWrapperBox 同规则取配置宽与视口剩余宽的较小值。
|
||||
* UI-04:vertical-stream 恒 195 宽(§2.1 硬性,无 sm 降档——mobile 仅默认收起)。 */
|
||||
export function buildPreviewPlacement(
|
||||
draft: EmbedSettingsDraft,
|
||||
mode: 'desktop' | 'mobile',
|
||||
frameWidth: number = EMBED_PREVIEW_FRAME_WIDTH[mode]
|
||||
): EmbedPreviewPlacement {
|
||||
const narrow = mode === 'mobile'
|
||||
const size: Api.EmbedSlot.Size = narrow ? 'sm' : draft.size
|
||||
const isV2 = draft.displayMode === 'vertical-stream'
|
||||
const size: Api.EmbedSlot.Size = narrow && !isV2 ? 'sm' : draft.size
|
||||
const offsetX = clampOffsetX(draft.offsetX)
|
||||
const available = Math.max(frameWidth - offsetX - 8, EMBED_PREVIEW_MIN_WIDTH)
|
||||
return {
|
||||
side: draft.position,
|
||||
size,
|
||||
width: Math.min(EMBED_SIZE_WIDTH[size], available),
|
||||
width: Math.min(isV2 ? EMBED_V2_WIDTH : EMBED_SIZE_WIDTH[size], available),
|
||||
offsetX,
|
||||
offsetBottom: clampOffsetBottom(draft.offsetBottom),
|
||||
zIndex: clampZIndex(draft.zIndex),
|
||||
|
||||
Reference in New Issue
Block a user