修改1.4.0版本的UI

This commit is contained in:
2025-11-28 11:41:31 +08:00
parent 88f7076630
commit d1e19dc8bf
13 changed files with 178 additions and 202 deletions

View File

@@ -137,22 +137,7 @@ const Sidebar = ({ isPanel }: Props) => {
</div> </div>
<div className='flex shrink-0 items-center justify-between p-3'> <div className='flex shrink-0 items-center justify-between p-3'>
<MenuDropdown placement='top-start' data={appData?.site} /> <MenuDropdown placement='top-start' data={appData?.site} />
{/* powered by */}
<div className='shrink-0'>
{!appData?.custom_config?.remove_webapp_brand && (
<div className={cn(
'flex shrink-0 items-center gap-1.5 px-1',
)}>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div>
{appData?.custom_config?.replace_webapp_logo && (
<img src={appData?.custom_config?.replace_webapp_logo} alt='logo' className='block h-5 w-auto' />
)}
{!appData?.custom_config?.replace_webapp_logo && (
<DifyLogo size='small' />
)}
</div>
)}
</div>
</div> </div>
{!!showConfirm && ( {!!showConfirm && (
<Confirm <Confirm

View File

@@ -106,24 +106,7 @@ const Chatbot = () => {
)} )}
</div> </div>
</div> </div>
{/* powered by */}
{isMobile && (
<div className='flex h-[60px] shrink-0 items-center pl-2'>
{!appData?.custom_config?.remove_webapp_brand && (
<div className={cn(
'flex shrink-0 items-center gap-1.5 px-2',
)}>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div>
{appData?.custom_config?.replace_webapp_logo && (
<img src={appData?.custom_config?.replace_webapp_logo} alt='logo' className='block h-5 w-auto' />
)}
{!appData?.custom_config?.replace_webapp_logo && (
<DifyLogo size='small' />
)}
</div>
)}
</div>
)}
</div> </div>
) )
} }

View File

@@ -2,36 +2,28 @@
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Fragment, useState } from 'react' import { Fragment, useState } from 'react'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { useContextSelector } from 'use-context-selector'
import { import {
RiAccountCircleLine, RiAccountCircleLine,
RiArrowRightUpLine, RiArrowRightUpLine,
RiBookOpenLine,
RiGithubLine,
RiGraduationCapFill, RiGraduationCapFill,
RiInformation2Line, RiInformation2Line,
RiLogoutBoxRLine, RiLogoutBoxRLine,
RiMap2Line,
RiSettings3Line, RiSettings3Line,
RiStarLine,
RiTShirt2Line, RiTShirt2Line,
} from '@remixicon/react' } from '@remixicon/react'
import Link from 'next/link' import Link from 'next/link'
import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react' import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react'
import Indicator from '../indicator' import Indicator from '../indicator'
import AccountAbout from '../account-about' import AccountAbout from '../account-about'
import GithubStar from '../github-star'
import Support from './support'
import Compliance from './compliance' import Compliance from './compliance'
import PremiumBadge from '@/app/components/base/premium-badge' import PremiumBadge from '@/app/components/base/premium-badge'
import { useGetDocLanguage } from '@/context/i18n'
import Avatar from '@/app/components/base/avatar' import Avatar from '@/app/components/base/avatar'
import ThemeSwitcher from '@/app/components/base/theme-switcher' import ThemeSwitcher from '@/app/components/base/theme-switcher'
import { logout } from '@/service/common' import { logout } from '@/service/common'
import AppContext, { useAppContext } from '@/context/app-context' import { useAppContext } from '@/context/app-context'
import { useProviderContext } from '@/context/provider-context' import { useProviderContext } from '@/context/provider-context'
import { useModalContext } from '@/context/modal-context' import { useModalContext } from '@/context/modal-context'
import { LicenseStatus } from '@/types/feature'
import { IS_CLOUD_EDITION } from '@/config' import { IS_CLOUD_EDITION } from '@/config'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
@@ -42,13 +34,11 @@ export default function AppSelector() {
` `
const router = useRouter() const router = useRouter()
const [aboutVisible, setAboutVisible] = useState(false) const [aboutVisible, setAboutVisible] = useState(false)
const systemFeatures = useContextSelector(AppContext, v => v.systemFeatures)
const { t } = useTranslation() const { t } = useTranslation()
const { userProfile, langeniusVersionInfo, isCurrentWorkspaceOwner } = useAppContext() const { userProfile, langeniusVersionInfo, isCurrentWorkspaceOwner } = useAppContext()
const { isEducationAccount } = useProviderContext() const { isEducationAccount } = useProviderContext()
const { setShowAccountSettingModal } = useModalContext() const { setShowAccountSettingModal } = useModalContext()
const docLanguage = useGetDocLanguage()
const handleLogout = async () => { const handleLogout = async () => {
await logout({ await logout({
@@ -128,49 +118,9 @@ export default function AppSelector() {
</MenuItem> </MenuItem>
</div> </div>
<div className='p-1'> <div className='p-1'>
<MenuItem>
<Link
className={cn(itemClassName, 'group justify-between',
'data-[active]:bg-state-base-hover',
)}
href={`https://docs.dify.ai/${docLanguage}/introduction`}
target='_blank' rel='noopener noreferrer'>
<RiBookOpenLine className='size-4 shrink-0 text-text-tertiary' />
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.helpCenter')}</div>
<RiArrowRightUpLine className='size-[14px] shrink-0 text-text-tertiary' />
</Link>
</MenuItem>
<Support />
{IS_CLOUD_EDITION && isCurrentWorkspaceOwner && <Compliance />} {IS_CLOUD_EDITION && isCurrentWorkspaceOwner && <Compliance />}
</div> </div>
<div className='p-1'> <div className='p-1'>
<MenuItem>
<Link
className={cn(itemClassName, 'group justify-between',
'data-[active]:bg-state-base-hover',
)}
href='https://roadmap.dify.ai'
target='_blank' rel='noopener noreferrer'>
<RiMap2Line className='size-4 shrink-0 text-text-tertiary' />
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.roadmap')}</div>
<RiArrowRightUpLine className='size-[14px] shrink-0 text-text-tertiary' />
</Link>
</MenuItem>
{systemFeatures.license.status === LicenseStatus.NONE && <MenuItem>
<Link
className={cn(itemClassName, 'group justify-between',
'data-[active]:bg-state-base-hover',
)}
href='https://github.com/langgenius/dify'
target='_blank' rel='noopener noreferrer'>
<RiGithubLine className='size-4 shrink-0 text-text-tertiary' />
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.github')}</div>
<div className='flex items-center gap-0.5 rounded-[5px] border border-divider-deep bg-components-badge-bg-dimm px-[5px] py-[3px]'>
<RiStarLine className='size-3 shrink-0 text-text-tertiary' />
<GithubStar className='system-2xs-medium-uppercase text-text-tertiary' />
</div>
</Link>
</MenuItem>}
{ {
document?.body?.getAttribute('data-public-site-about') !== 'hide' && ( document?.body?.getAttribute('data-public-site-about') !== 'hide' && (
<MenuItem> <MenuItem>

View File

@@ -624,22 +624,7 @@ const TextGeneration: FC<IMainProps> = ({
/> />
)} )}
</div> </div>
{/* powered by */}
{!customConfig?.remove_webapp_brand && (
<div className={cn(
'flex shrink-0 items-center gap-1.5 bg-components-panel-bg py-3',
isPC ? 'px-8' : 'px-4',
!isPC && resultExisted && 'rounded-b-2xl border-b-[0.5px] border-divider-regular',
)}>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div>
{customConfig?.replace_webapp_logo && (
<img src={customConfig?.replace_webapp_logo} alt='logo' className='block h-5 w-auto' />
)}
{!customConfig?.replace_webapp_logo && (
<DifyLogo size='small' />
)}
</div>
)}
</div> </div>
{/* Result */} {/* Result */}
<div className={cn( <div className={cn(

View File

@@ -0,0 +1,42 @@
@echo off
setlocal EnableDelayedExpansion
REM Check if a version number is provided; prompt if missing
if "%~1"=="" (
echo Usage: %~nx0 [version]
set /p VERSION=Enter version:
if not defined VERSION (
echo Version cannot be empty.
pause
exit /b 1
)
) else (
set "VERSION=%~1"
)
set "IMAGE_NAME=dify-web-rowger"
set "TAGGED_IMAGE_NAME=%IMAGE_NAME%:%VERSION%"
set "TAR_FILE_NAME=%IMAGE_NAME%.%VERSION%.tar"
REM Build the Docker image
echo Building Docker image: %TAGGED_IMAGE_NAME%
docker build -t %TAGGED_IMAGE_NAME% .
REM Check if the build was successful
if errorlevel 1 (
echo Docker build failed.
exit /b 1
)
REM Save the Docker image to a .tar file
echo Saving Docker image to %TAR_FILE_NAME%
docker save -o %TAR_FILE_NAME% %TAGGED_IMAGE_NAME%
if errorlevel 1 (
echo Docker save failed.
exit /b 1
)
echo Docker image built and saved successfully.
pause
endlocal

View File

@@ -1,5 +1,5 @@
# base image # base image
FROM node:22-alpine3.21 AS base FROM fiof1uwu2mjtuh.xuanyuan.run/node:22-alpine3.21 AS base
LABEL maintainer="takatost@gmail.com" LABEL maintainer="takatost@gmail.com"
# if you located in China, you can use aliyun mirror to speed up # if you located in China, you can use aliyun mirror to speed up

View File

@@ -145,23 +145,7 @@ const Sidebar = ({ isPanel, panelVisible }: Props) => {
data={appData?.site} data={appData?.site}
forceClose={isPanel && !panelVisible} forceClose={isPanel && !panelVisible}
/> />
{/* powered by */} {/* 移除左下角 Powered by 区域 */}
<div className='shrink-0'>
{!appData?.custom_config?.remove_webapp_brand && (
<div className={cn(
'flex shrink-0 items-center gap-1.5 px-1',
)}>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div>
{
systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
? <img src={systemFeatures.branding.workspace_logo} alt='logo' className='block h-5 w-auto' />
: appData?.custom_config?.replace_webapp_logo
? <img src={`${appData?.custom_config?.replace_webapp_logo}`} alt='logo' className='block h-5 w-auto' />
: <DifyLogo size='small' />
}
</div>
)}
</div>
{!!showConfirm && ( {!!showConfirm && (
<Confirm <Confirm
title={t('share.chat.deleteConversation.title')} title={t('share.chat.deleteConversation.title')}

View File

@@ -71,25 +71,7 @@ const Chatbot = () => {
)} )}
</div> </div>
</div> </div>
{/* powered by */} {/* 移除移动端左下角 Powered by 区域 */}
{isMobile && (
<div className='flex h-[60px] shrink-0 items-center pl-2'>
{!appData?.custom_config?.remove_webapp_brand && (
<div className={cn(
'flex shrink-0 items-center gap-1.5 px-2',
)}>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div>
{
systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
? <img src={systemFeatures.branding.workspace_logo} alt='logo' className='block h-5 w-auto' />
: appData?.custom_config?.replace_webapp_logo
? <img src={`${appData?.custom_config?.replace_webapp_logo}`} alt='logo' className='block h-5 w-auto' />
: <DifyLogo size='small' />
}
</div>
)}
</div>
)}
</div> </div>
) )
} }

View File

@@ -0,0 +1,80 @@
'use client'
import { useEffect, useRef } from 'react'
/**
* IframePostMessage
* 页面加载完成后向父页面发送一次消息,并每 5 秒发送一次。
* 仅当当前窗口运行在 iframe 中时才发送。
*/
const IframePostMessage = () => {
const initializedRef = useRef(false)
/**
* sendMessage
* 向父页面发送消息的函数:收集当前页面的 localStorage 全量键值并发送。
* 如果不在 iframe 环境中则不发送。
*/
const sendMessage = () => {
try {
if (typeof window === 'undefined') return
// 只在 iframe 环境下发送
if (window.parent === window) return
// 收集 localStorage 全量数据
const localStorageData: Record<string, string | null> = {}
try {
const { localStorage } = window
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i)
if (!key) continue
localStorageData[key] = localStorage.getItem(key)
}
}
catch {
// 可能因浏览器隐私设置导致不可访问 localStorage
}
window.parent.postMessage(
{
type: 'dify-localstorage',
status: 1,
message: '将智能体本地缓存发送给父页面!',
data: localStorageData,
},
'*',
)
}
catch {
// 忽略跨域或其他运行时错误
}
}
useEffect(() => {
if (initializedRef.current) return
initializedRef.current = true
let timer: number | undefined
const init = () => {
sendMessage()
timer = window.setInterval(sendMessage, 5000)
}
if (document.readyState === 'loading') {
const onReady = () => {
init()
document.removeEventListener('DOMContentLoaded', onReady)
}
document.addEventListener('DOMContentLoaded', onReady)
}
else {
init()
}
return () => {
if (timer) window.clearInterval(timer)
}
}, [])
return null
}
export default IframePostMessage

View File

@@ -5,22 +5,17 @@ import { useRouter } from 'next/navigation'
import { import {
RiAccountCircleLine, RiAccountCircleLine,
RiArrowRightUpLine, RiArrowRightUpLine,
RiBookOpenLine,
RiGithubLine,
RiGraduationCapFill, RiGraduationCapFill,
RiInformation2Line, RiInformation2Line,
RiLogoutBoxRLine, RiLogoutBoxRLine,
RiMap2Line,
RiSettings3Line, RiSettings3Line,
RiStarLine,
RiTShirt2Line, RiTShirt2Line,
} from '@remixicon/react' } from '@remixicon/react'
import Link from 'next/link' import Link from 'next/link'
import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react' import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react'
import Indicator from '../indicator' import Indicator from '../indicator'
import AccountAbout from '../account-about' import AccountAbout from '../account-about'
import GithubStar from '../github-star' // Removed: GithubStar, Support
import Support from './support'
import Compliance from './compliance' import Compliance from './compliance'
import PremiumBadge from '@/app/components/base/premium-badge' import PremiumBadge from '@/app/components/base/premium-badge'
import Avatar from '@/app/components/base/avatar' import Avatar from '@/app/components/base/avatar'
@@ -133,49 +128,11 @@ export default function AppSelector() {
</div> </div>
{!systemFeatures.branding.enabled && <> {!systemFeatures.branding.enabled && <>
<div className='p-1'> <div className='p-1'>
<MenuItem> {/* 移除:帮助文档与支持按钮 */}
<Link
className={cn(itemClassName, 'group justify-between',
'data-[active]:bg-state-base-hover',
)}
href={docLink('/introduction')}
target='_blank' rel='noopener noreferrer'>
<RiBookOpenLine className='size-4 shrink-0 text-text-tertiary' />
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.helpCenter')}</div>
<RiArrowRightUpLine className='size-[14px] shrink-0 text-text-tertiary' />
</Link>
</MenuItem>
<Support />
{IS_CLOUD_EDITION && isCurrentWorkspaceOwner && <Compliance />} {IS_CLOUD_EDITION && isCurrentWorkspaceOwner && <Compliance />}
</div> </div>
<div className='p-1'> <div className='p-1'>
<MenuItem> {/* 移除:路线图与 GitHub 按钮 */}
<Link
className={cn(itemClassName, 'group justify-between',
'data-[active]:bg-state-base-hover',
)}
href='https://roadmap.dify.ai'
target='_blank' rel='noopener noreferrer'>
<RiMap2Line className='size-4 shrink-0 text-text-tertiary' />
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.roadmap')}</div>
<RiArrowRightUpLine className='size-[14px] shrink-0 text-text-tertiary' />
</Link>
</MenuItem>
<MenuItem>
<Link
className={cn(itemClassName, 'group justify-between',
'data-[active]:bg-state-base-hover',
)}
href='https://github.com/langgenius/dify'
target='_blank' rel='noopener noreferrer'>
<RiGithubLine className='size-4 shrink-0 text-text-tertiary' />
<div className='system-md-regular grow px-1 text-text-secondary'>{t('common.userProfile.github')}</div>
<div className='flex items-center gap-0.5 rounded-[5px] border border-divider-deep bg-components-badge-bg-dimm px-[5px] py-[3px]'>
<RiStarLine className='size-3 shrink-0 text-text-tertiary' />
<GithubStar className='system-2xs-medium-uppercase text-text-tertiary' />
</div>
</Link>
</MenuItem>
{ {
document?.body?.getAttribute('data-public-site-about') !== 'hide' && ( document?.body?.getAttribute('data-public-site-about') !== 'hide' && (
<MenuItem> <MenuItem>

View File

@@ -583,23 +583,7 @@ const TextGeneration: FC<IMainProps> = ({
/> />
)} )}
</div> </div>
{/* powered by */} {/* 移除左下角 Powered by 区域 */}
{!customConfig?.remove_webapp_brand && (
<div className={cn(
'flex shrink-0 items-center gap-1.5 bg-components-panel-bg py-3',
isPC ? 'px-8' : 'px-4',
!isPC && resultExisted && 'rounded-b-2xl border-b-[0.5px] border-divider-regular',
)}>
<div className='system-2xs-medium-uppercase text-text-tertiary'>{t('share.chat.poweredBy')}</div>
{
systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
? <img src={systemFeatures.branding.workspace_logo} alt='logo' className='block h-5 w-auto' />
: customConfig?.replace_webapp_logo
? <img src={`${customConfig?.replace_webapp_logo}`} alt='logo' className='block h-5 w-auto' />
: <DifyLogo size='small' />
}
</div>
)}
</div> </div>
{/* Result */} {/* Result */}
<div className={cn( <div className={cn(

View File

@@ -4,6 +4,7 @@ import I18nServer from './components/i18n-server'
import BrowserInitializer from './components/browser-initializer' import BrowserInitializer from './components/browser-initializer'
import SentryInitializer from './components/sentry-initializer' import SentryInitializer from './components/sentry-initializer'
import Zendesk from './components/base/zendesk' import Zendesk from './components/base/zendesk'
import IframePostMessage from './components/base/iframe-postmessage'
import { getLocaleOnServer } from '@/i18n-config/server' import { getLocaleOnServer } from '@/i18n-config/server'
import { TanstackQueryInitializer } from '@/context/query-client' import { TanstackQueryInitializer } from '@/context/query-client'
import { ThemeProvider } from 'next-themes' import { ThemeProvider } from 'next-themes'
@@ -106,6 +107,7 @@ const LocaleLayout = async ({
</ThemeProvider> </ThemeProvider>
<RoutePrefixHandle /> <RoutePrefixHandle />
<Zendesk /> <Zendesk />
<IframePostMessage />
</body> </body>
</html> </html>
) )

View File

@@ -0,0 +1,42 @@
@echo off
setlocal EnableDelayedExpansion
REM Check if a version number is provided; prompt if missing
if "%~1"=="" (
echo Usage: %~nx0 [version]
set /p VERSION=Enter version:
if not defined VERSION (
echo Version cannot be empty.
pause
exit /b 1
)
) else (
set "VERSION=%~1"
)
set "IMAGE_NAME=dify-web-rowger"
set "TAGGED_IMAGE_NAME=%IMAGE_NAME%:%VERSION%"
set "TAR_FILE_NAME=%IMAGE_NAME%.%VERSION%.tar"
REM Build the Docker image
echo Building Docker image: %TAGGED_IMAGE_NAME%
docker build -t %TAGGED_IMAGE_NAME% .
REM Check if the build was successful
if errorlevel 1 (
echo Docker build failed.
exit /b 1
)
REM Save the Docker image to a .tar file
echo Saving Docker image to %TAR_FILE_NAME%
docker save -o %TAR_FILE_NAME% %TAGGED_IMAGE_NAME%
if errorlevel 1 (
echo Docker save failed.
exit /b 1
)
echo Docker image built and saved successfully.
pause
endlocal