Files
ebiz-dify-ai/web/app/components/app-sidebar/index.tsx
Huangzhe f083b64dbd feat(iframe): 实现 iframe 通信的消息通道功能
- 新增 useChannel hook 用于基于 iframe 通信管理布局显示
- 实现 MessageChannel 工具类,用于父页面与 iframe 之间的安全跨域通信
- 更新 header-wrapper 组件,根据通道通信状态条件性渲染
- 在多个组件中集成消息通道功能
- 添加通过 postMessage API 控制布局的支持
- 改进 iframe 与父应用程序的集成
2025-05-07 16:42:28 +08:00

151 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useEffect } from 'react'
import { useShallow } from 'zustand/react/shallow'
import { RiLayoutLeft2Line, RiLayoutRight2Line } from '@remixicon/react'
import type { NavIcon } from './navLink'
import NavLink from './navLink'
import AppBasic from './basic'
import AppInfo from './app-info'
import DatasetInfo from './dataset-info'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { useStore as useAppStore } from '@/app/components/app/store'
import cn from '@/utils/classnames'
import { useSearchParams } from 'next/navigation'
import { useGetLayoutByChannel } from '@/hooks/use-channel'
export type IAppDetailNavProps = {
iconType?: 'app' | 'dataset' | 'notion'
title: string
desc: string
isExternal?: boolean
icon: string
icon_background: string
navigation: Array<{
name: string
href: string
icon: NavIcon
selectedIcon: NavIcon
}>
extraInfo?: (modeState: string) => React.ReactNode
}
const AppDetailNav = ({
title,
desc,
isExternal,
icon,
icon_background,
navigation,
extraInfo,
iconType = 'app',
}: IAppDetailNavProps) => {
const { appSidebarExpand, setAppSiderbarExpand } = useAppStore(useShallow(state => ({
appSidebarExpand: state.appSidebarExpand,
setAppSiderbarExpand: state.setAppSiderbarExpand,
})))
const media = useBreakpoints()
const isMobile = media === MediaType.mobile
const expand = appSidebarExpand === 'expand'
const handleToggle = (state: string) => {
setAppSiderbarExpand(state === 'expand' ? 'collapse' : 'expand')
}
useEffect(() => {
if (appSidebarExpand) {
localStorage.setItem('app-detail-collapse-or-expand', appSidebarExpand)
setAppSiderbarExpand(appSidebarExpand)
}
}, [appSidebarExpand, setAppSiderbarExpand])
// 通过 channel 获取 layout 数据内容
const showLayout = useGetLayoutByChannel()
const searchParams = useSearchParams()
// 从 router 查询参数,若有 sidebar选项,按照参数设置,没有的话,默认是展示内容
const showSidebar = !(searchParams?.get('sidebar')) || (searchParams?.get('sidebar') === '1')
// console.log('searchParams?.get("sidebar"): ', searchParams?.get('sidebar'),!(searchParams?.get('sidebar')) , (searchParams?.get('sidebar') === '1'))
// console.log('showSidebar: ', showSidebar)
// 如果showSidebar为false不显示
if (!showSidebar) return null
return (
<div
className={`
${showLayout ? 'flex' : 'hidden'} shrink-0 flex-col border-r border-divider-burn bg-background-default-subtle transition-all
${expand ? 'w-[216px]' : 'w-14'}
`}
>
<div
className={`
shrink-0
${expand ? 'p-2' : 'p-1'}
`}
>
{iconType === 'app' && (
<AppInfo expand={expand}/>
)}
{iconType === 'dataset' && (
<DatasetInfo
name={title}
description={desc}
isExternal={isExternal}
expand={expand}
extraInfo={extraInfo && extraInfo(appSidebarExpand)}
/>
)}
{!['app', 'dataset'].includes(iconType) && (
<AppBasic
mode={appSidebarExpand}
iconType={iconType}
icon={icon}
icon_background={icon_background}
name={title}
type={desc}
isExternal={isExternal}
/>
)}
</div>
<div className='px-4'>
<div className={cn('mx-auto mt-1 h-[1px] bg-divider-subtle', !expand && 'w-6')}/>
</div>
<nav
className={`
grow space-y-1
${expand ? 'p-4' : 'px-2.5 py-4'}
`}
>
{navigation.map((item, index) => {
return (
<NavLink key={index} mode={appSidebarExpand} iconMap={{ selected: item.selectedIcon, normal: item.icon }}
name={item.name} href={item.href}/>
)
})}
</nav>
{
!isMobile && (
<div
className={`
shrink-0 py-3
${expand ? 'px-6' : 'px-4'}
`}
>
<div
className='flex h-6 w-6 cursor-pointer items-center justify-center'
onClick={() => handleToggle(appSidebarExpand)}
>
{
expand
? <RiLayoutRight2Line className='h-5 w-5 text-components-menu-item-text'/>
: <RiLayoutLeft2Line className='h-5 w-5 text-components-menu-item-text'/>
}
</div>
</div>
)
}
</div>
)
}
export default React.memo(AppDetailNav)