feat: build/preview layout

This commit is contained in:
yyh 2026-06-25 15:17:06 +08:00
parent 7c939ee6c2
commit aa5c10af55
No known key found for this signature in database
4 changed files with 81 additions and 1445 deletions

View File

@ -1,7 +1,57 @@
import { cn } from '@langgenius/dify-ui/cn'
import buildHeaderBackground from './build-header-background.svg'
export function AgentBuildHeaderBackground({
const buildPanelGridColumnCount = 384
const buildPanelGridRowCount = 32
function getBuildPanelGridCellOpacity(row: number, column: number) {
const seed = Math.sin((row + 1) * 12.9898 + (column + 1) * 78.233) * 43758.5453
const noise = seed - Math.floor(seed)
const verticalProgress = row / (buildPanelGridRowCount - 1)
const densityThreshold = 0.26 + verticalProgress * 0.72
const horizontalWeight = Math.min(1, column / 160)
const verticalWeight = (1 - verticalProgress) ** 1.7
if (noise < densityThreshold)
return 0
return Number(Math.min(0.272, (0.032 + noise * 0.058 + horizontalWeight * 0.09) * verticalWeight).toFixed(3))
}
const buildPanelGridCells = Array.from(
{ length: buildPanelGridColumnCount * buildPanelGridRowCount },
(_, index) => {
const row = Math.floor(index / buildPanelGridColumnCount)
const column = index % buildPanelGridColumnCount
const opacity = getBuildPanelGridCellOpacity(row, column)
return {
id: `build-panel-grid-cell-${row}-${column}`,
column: column + 1,
opacity,
row: row + 1,
}
},
).filter(cell => cell.opacity > 0)
function AgentBuildPanelGrid({
className,
}: {
className?: string
}) {
return (
<div className={cn('grid grid-cols-[repeat(384,4px)] grid-rows-[repeat(32,4px)] gap-0.5 opacity-70', className)}>
{buildPanelGridCells.map(cell => (
<span
key={cell.id}
className="rounded-[1px] bg-[#98A2B2]"
style={{ gridColumn: `${cell.column}`, gridRow: `${cell.row}`, opacity: cell.opacity }}
/>
))}
</div>
)
}
export function AgentBuildPanelBackground({
visible,
}: {
visible: boolean
@ -10,16 +60,12 @@ export function AgentBuildHeaderBackground({
<div
aria-hidden
className={cn(
'pointer-events-none absolute top-0 right-0 left-0 z-0 h-60 overflow-hidden opacity-0 transition-opacity duration-150 motion-reduce:transition-none',
'pointer-events-none absolute inset-0 z-0 overflow-hidden rounded-[inherit] opacity-0 transition-opacity duration-150 motion-reduce:transition-none',
visible && 'opacity-100',
)}
>
<img
src={buildHeaderBackground.src}
alt=""
className="absolute inset-0 size-full max-w-none object-fill"
draggable={false}
/>
<AgentBuildPanelGrid className="absolute top-0 left-0" />
<AgentBuildPanelGrid className="absolute bottom-0 left-0 origin-center scale-y-[-1]" />
</div>
)
}

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 257 KiB

View File

@ -55,7 +55,7 @@ export function AgentPreviewHeader({
const modeTip = `${buildLabel}. ${buildTipBody} ${previewLabel}. ${previewTipBody} ${learnMoreLabel}`
return (
<div className="relative z-1 flex h-12 shrink-0 items-center gap-3 py-2 pr-3 pl-4">
<div className="relative z-1 flex h-12 shrink-0 items-center justify-between gap-3 px-4 py-2">
<div className="flex min-w-0 flex-1 items-center gap-2">
<SegmentedControl<AgentConfigureRightPanelMode>
value={[mode]}
@ -107,38 +107,40 @@ export function AgentPreviewHeader({
</div>
</Infotip>
</div>
<div className="flex shrink-0 items-center gap-1">
<button
type="button"
onClick={onRefresh}
disabled={refreshDisabled}
className="flex size-6 items-center justify-center rounded-md p-0.5 text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50"
aria-label={t('agentDetail.configure.preview.restart')}
>
<span aria-hidden className="i-custom-vender-other-replay-line size-4" />
</button>
{mode === 'build' && (
<div className="flex shrink-0 items-center">
<div className="flex items-center gap-2">
<button
type="button"
onClick={onOpenVersions}
className="flex size-6 items-center justify-center rounded-md p-0.5 text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden"
aria-label={t('agentDetail.configure.publishBar.versionHistory')}
onClick={onRefresh}
disabled={refreshDisabled}
className="flex size-6 items-center justify-center rounded-md p-0.5 text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50"
aria-label={t('agentDetail.configure.preview.restart')}
>
<span aria-hidden className="i-ri-folder-3-line size-4" />
<span aria-hidden className="i-custom-vender-other-replay-line size-4" />
</button>
)}
<SegmentedControlDivider className="mx-1" />
{mode === 'build' && (
<button
type="button"
onClick={onOpenVersions}
className="flex size-6 items-center justify-center rounded-md p-0.5 text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden"
aria-label={t('agentDetail.configure.publishBar.versionHistory')}
>
<span aria-hidden className="i-ri-folder-3-line size-4" />
</button>
)}
</div>
<SegmentedControlDivider className="mx-3" />
<button
type="button"
aria-pressed={isChatFeaturesOpen}
onClick={onToggleChatFeatures}
className={cn(
'flex h-8 items-center justify-center gap-0.5 rounded-lg px-3 py-2 text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden',
'flex h-8 items-center justify-center gap-1 rounded-lg px-2 py-2 text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden',
isChatFeaturesOpen && 'bg-state-base-hover text-text-secondary',
)}
aria-label={t('agentDetail.configure.preview.chatFeatures')}
>
<span aria-hidden className="i-ri-apps-2-add-line size-4" />
<span aria-hidden className="i-ri-chat-settings-line size-4" />
<span className="px-0.5 system-sm-medium">{t('agentDetail.configure.preview.chatFeatures')}</span>
</button>
</div>

View File

@ -9,7 +9,7 @@ import { AgentComposerProvider } from '@/features/agent-v2/agent-composer/provid
import { useHydrateAgentSoulConfigDraft } from '@/features/agent-v2/agent-composer/store'
import { consoleQuery } from '@/service/client'
import { AgentOrchestratePanel } from './components/orchestrate'
import { AgentBuildHeaderBackground } from './components/preview/build-background'
import { AgentBuildPanelBackground } from './components/preview/build-background'
import { AgentBuildChat } from './components/preview/build-chat'
import { AgentChatFeaturesPanel } from './components/preview/chat-features-panel'
import { AgentPreviewHeader } from './components/preview/header'
@ -177,7 +177,7 @@ function AgentConfigurePageLoadedContent({
<section
aria-label={t('agentDetail.sections.configure')}
aria-busy={agentQuery.isFetching}
className="flex h-full min-w-0 flex-1 gap-1 overflow-hidden p-1"
className="flex h-full min-w-0 flex-1 gap-1 overflow-hidden bg-background-body p-1"
>
<AgentOrchestratePanel
agentId={agentId}
@ -199,8 +199,8 @@ function AgentConfigurePageLoadedContent({
{/* Preview area */}
<div className="flex min-w-105 flex-1 gap-1 overflow-hidden">
<div className="relative flex min-w-105 flex-1 flex-col overflow-hidden rounded-lg bg-background-gradient-bg-fill-chat-bg-2 shadow-xl shadow-shadow-shadow-5">
<AgentBuildHeaderBackground visible={rightPanelChatMode === 'build'} />
<div className="relative isolate flex min-w-105 flex-1 flex-col overflow-hidden rounded-lg border-[0.5px] border-components-panel-border bg-linear-to-b from-background-gradient-bg-fill-chat-bg-1 to-background-gradient-bg-fill-chat-bg-2 shadow-xl shadow-shadow-shadow-5">
<AgentBuildPanelBackground visible={rightPanelChatMode === 'build'} />
<AgentPreviewHeader
mode={rightPanelChatMode}
previewEnabled={false}