diff --git a/web/app/components/app/overview/appCard.tsx b/web/app/components/app/overview/appCard.tsx index 4f5f93f22b..ae44664f9f 100644 --- a/web/app/components/app/overview/appCard.tsx +++ b/web/app/components/app/overview/appCard.tsx @@ -183,7 +183,7 @@ function AppCard({ setShowConfirmDelete(false)} onConfirm={() => { diff --git a/web/app/components/base/qrcode/index.tsx b/web/app/components/base/qrcode/index.tsx index 914095cdab..721f8c9029 100644 --- a/web/app/components/base/qrcode/index.tsx +++ b/web/app/components/base/qrcode/index.tsx @@ -1,7 +1,6 @@ 'use client' -import React, { useState } from 'react' +import React, { useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -import { debounce } from 'lodash-es' import QRCode from 'qrcode.react' import Tooltip from '../tooltip' import QrcodeStyle from './style.module.css' @@ -16,10 +15,27 @@ const prefixEmbedded = 'appOverview.overview.appInfo.qrcode.title' const ShareQRCode = ({ content, selectorId, className }: Props) => { const { t } = useTranslation() - const [isShow, setisShow] = useState(false) - const onClickShow = debounce(() => { - setisShow(true) - }, 100) + const [isShow, setIsShow] = useState(false) + const qrCodeRef = useRef(null) + + const toggleQRCode = (event: React.MouseEvent) => { + event.stopPropagation() + setIsShow(prev => !prev) + } + + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if (qrCodeRef.current && !qrCodeRef.current.contains(event.target as Node)) + setIsShow(false) + } + + if (isShow) + document.addEventListener('click', handleClickOutside) + + return () => { + document.removeEventListener('click', handleClickOutside) + } + }, [isShow]) const downloadQR = () => { const canvas = document.getElementsByTagName('canvas')[0] @@ -29,9 +45,9 @@ const ShareQRCode = ({ content, selectorId, className }: Props) => { link.click() } - const onMouseLeave = debounce(() => { - setisShow(false) - }, 500) + const handlePanelClick = (event: React.MouseEvent) => { + event.stopPropagation() + } return ( { >
- {isShow &&
- -
-
{t('appOverview.overview.appInfo.qrcode.scan')}
-
·
-
{t('appOverview.overview.appInfo.qrcode.download')}
+ {isShow && ( +
+ +
+
{t('appOverview.overview.appInfo.qrcode.scan')}
+
·
+
{t('appOverview.overview.appInfo.qrcode.download')}
+
-
- } + )}
) diff --git a/web/app/components/base/qrcode/style.module.css b/web/app/components/base/qrcode/style.module.css index 976aabf1fe..b0c4441e99 100644 --- a/web/app/components/base/qrcode/style.module.css +++ b/web/app/components/base/qrcode/style.module.css @@ -37,6 +37,7 @@ flex-direction: row; align-items: center; justify-content: center; + white-space: nowrap; gap: 4px; } .qrcodeform { @@ -46,7 +47,8 @@ margin: 0 !important; margin-top: 4px !important; margin-left: -75px !important; - position: absolute; + width: fit-content; + position: relative; border-radius: 8px; background-color: #fff; box-shadow: 0 12px 16px -4px rgba(16, 24, 40, 0.08), @@ -54,8 +56,6 @@ overflow: hidden; align-items: center; justify-content: center; - padding: 12px; + padding: 15px; gap: 8px; - z-index: 3; - font-family: "PingFang SC", serif; } diff --git a/web/i18n/en-US/app-overview.ts b/web/i18n/en-US/app-overview.ts index b8c7999415..5bf0b44563 100644 --- a/web/i18n/en-US/app-overview.ts +++ b/web/i18n/en-US/app-overview.ts @@ -3,23 +3,23 @@ const translation = { firstStepTip: 'To get started,', enterKeyTip: 'enter your OpenAI API Key below', getKeyTip: 'Get your API Key from OpenAI dashboard', - placeholder: 'Your OpenAI API Key(eg.sk-xxxx)', + placeholder: 'Your OpenAI API Key (eg.sk-xxxx)', }, apiKeyInfo: { cloud: { trial: { title: 'You are using the {{providerName}} trial quota.', - description: 'The trial quota is provided for your testing use. Before the trial quota calls are exhausted, please set up your own model provider or purchase additional quota.', + description: 'The trial quota is provided for your testing purposes. Before the trial quota is exhausted, please set up your own model provider or purchase additional quota.', }, exhausted: { title: 'Your trial quota have been used up, please set up your APIKey.', - description: 'Your trial quota has been exhausted. Please set up your own model provider or purchase additional quota.', + description: 'You have exhausted your trial quota. Please set up your own model provider or purchase additional quota.', }, }, selfHost: { title: { row1: 'To get started,', - row2: 'setup your model provider first.', + row2: 'setup your model provider first.', }, }, callTimes: 'Call times', @@ -76,8 +76,8 @@ const translation = { copy: 'Copy', }, qrcode: { - title: 'QR code to share', - scan: 'Scan Share Application', + title: 'Link QR Code', + scan: 'Scan To Share', download: 'Download QR Code', }, customize: { @@ -103,14 +103,14 @@ const translation = { }, }, apiInfo: { - title: 'Backend service API', + title: 'Backend Service API', explanation: 'Easily integrated into your application', accessibleAddress: 'Service API Endpoint', doc: 'API Reference', }, status: { - running: 'In service', - disable: 'Disable', + running: 'In Service', + disable: 'Disabled', }, }, analysis: {