mirror of
https://github.com/langgenius/dify.git
synced 2024-11-16 11:42:29 +08:00
Application share qrcode (#1277)
Co-authored-by: luowei <glpat-EjySCyNjWiLqAED-YmwM> Co-authored-by: crazywoola <427733928@qq.com>
This commit is contained in:
parent
52bec63275
commit
b711ce33b7
|
@ -22,6 +22,7 @@ import Tag from '@/app/components/base/tag'
|
|||
import Switch from '@/app/components/base/switch'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import CopyFeedback from '@/app/components/base/copy-feedback'
|
||||
import ShareQRCode from '@/app/components/base/qrcode'
|
||||
import SecretKeyButton from '@/app/components/develop/secret-key/secret-key-button'
|
||||
import type { AppDetailResponse } from '@/models/app'
|
||||
import { AppType } from '@/types/app'
|
||||
|
@ -168,6 +169,7 @@ function AppCard({
|
|||
</div>
|
||||
</div>
|
||||
<Divider type="vertical" className="!h-3.5 shrink-0 !mx-0.5" />
|
||||
{isApp && <ShareQRCode content={isApp ? appUrl : apiUrl} selectorId={randomString(8)} className={'hover:bg-gray-200'} />}
|
||||
<CopyFeedback
|
||||
content={isApp ? appUrl : apiUrl}
|
||||
selectorId={randomString(8)}
|
||||
|
|
61
web/app/components/base/qrcode/index.tsx
Normal file
61
web/app/components/base/qrcode/index.tsx
Normal file
|
@ -0,0 +1,61 @@
|
|||
'use client'
|
||||
import React, { 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'
|
||||
|
||||
type Props = {
|
||||
content: string
|
||||
selectorId: string
|
||||
className?: string
|
||||
}
|
||||
|
||||
const prefixEmbedded = 'appOverview.overview.appInfo.qrcode.title'
|
||||
|
||||
const ShareQRCode = ({ content, selectorId, className }: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const [isShow, setisShow] = useState<boolean>(false)
|
||||
const onClickShow = debounce(() => {
|
||||
setisShow(true)
|
||||
}, 100)
|
||||
|
||||
const downloadQR = () => {
|
||||
const canvas = document.getElementsByTagName('canvas')[0]
|
||||
const link = document.createElement('a')
|
||||
link.download = 'qrcode.png'
|
||||
link.href = canvas.toDataURL()
|
||||
link.click()
|
||||
}
|
||||
|
||||
const onMouseLeave = debounce(() => {
|
||||
setisShow(false)
|
||||
}, 500)
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
selector={`common-qrcode-show-${selectorId}`}
|
||||
content={t(`${prefixEmbedded}`) || ''}
|
||||
>
|
||||
<div
|
||||
className={`w-8 h-8 cursor-pointer rounded-lg ${className ?? ''}`}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={onClickShow}
|
||||
>
|
||||
<div className={`w-full h-full ${QrcodeStyle.QrcodeIcon} ${isShow ? QrcodeStyle.show : ''}`} />
|
||||
{isShow && <div className={QrcodeStyle.qrcodeform}>
|
||||
<QRCode size={160} value={content} className={QrcodeStyle.qrcodeimage}/>
|
||||
<div className={QrcodeStyle.text}>
|
||||
<div className={`text-gray-500 ${QrcodeStyle.scan}`}>{t('appOverview.overview.appInfo.qrcode.scan')}</div>
|
||||
<div className={`text-gray-500 ${QrcodeStyle.scan}`}>·</div>
|
||||
<div className={QrcodeStyle.download} onClick={downloadQR}>{t('appOverview.overview.appInfo.qrcode.download')}</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
export default ShareQRCode
|
61
web/app/components/base/qrcode/style.module.css
Normal file
61
web/app/components/base/qrcode/style.module.css
Normal file
|
@ -0,0 +1,61 @@
|
|||
.QrcodeIcon {
|
||||
background-image: url(~@/app/components/develop/secret-key/assets/qrcode.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.QrcodeIcon:hover {
|
||||
background-image: url(~@/app/components/develop/secret-key/assets/qrcode-hover.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.QrcodeIcon.show {
|
||||
background-image: url(~@/app/components/develop/secret-key/assets/qrcode-hover.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.qrcodeimage {
|
||||
position: relative;
|
||||
object-fit: cover;
|
||||
}
|
||||
.scan {
|
||||
margin: 0;
|
||||
line-height: 1rem;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
.download {
|
||||
position: relative;
|
||||
color: #155eef;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1rem;
|
||||
}
|
||||
.text {
|
||||
align-self: stretch;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.qrcodeform {
|
||||
border: 0.5px solid #eaecf0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0 !important;
|
||||
margin-top: 4px !important;
|
||||
margin-left: -75px !important;
|
||||
position: absolute;
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 12px 16px -4px rgba(16, 24, 40, 0.08),
|
||||
0 4px 6px -2px rgba(16, 24, 40, 0.03);
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 12px;
|
||||
gap: 8px;
|
||||
z-index: 3;
|
||||
font-family: "PingFang SC", serif;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.33333 4.33333H4.34M11.6667 4.33333H11.6733M4.33333 11.6667H4.34M8.66667 8.66667H8.67333M11.6667 11.6667H11.6733M11.3333 14H14V11.3333M9.33333 11V14M14 9.33333H11M10.4 6.66667H12.9333C13.3067 6.66667 13.4934 6.66667 13.636 6.594C13.7614 6.53009 13.8634 6.4281 13.9273 6.30266C14 6.16005 14 5.97337 14 5.6V3.06667C14 2.6933 14 2.50661 13.9273 2.36401C13.8634 2.23856 13.7614 2.13658 13.636 2.07266C13.4934 2 13.3067 2 12.9333 2H10.4C10.0266 2 9.83995 2 9.69734 2.07266C9.5719 2.13658 9.46991 2.23856 9.406 2.36401C9.33333 2.50661 9.33333 2.6933 9.33333 3.06667V5.6C9.33333 5.97337 9.33333 6.16005 9.406 6.30266C9.46991 6.4281 9.5719 6.53009 9.69734 6.594C9.83995 6.66667 10.0266 6.66667 10.4 6.66667ZM3.06667 6.66667H5.6C5.97337 6.66667 6.16005 6.66667 6.30266 6.594C6.4281 6.53009 6.53009 6.4281 6.594 6.30266C6.66667 6.16005 6.66667 5.97337 6.66667 5.6V3.06667C6.66667 2.6933 6.66667 2.50661 6.594 2.36401C6.53009 2.23856 6.4281 2.13658 6.30266 2.07266C6.16005 2 5.97337 2 5.6 2H3.06667C2.6933 2 2.50661 2 2.36401 2.07266C2.23856 2.13658 2.13658 2.23856 2.07266 2.36401C2 2.50661 2 2.6933 2 3.06667V5.6C2 5.97337 2 6.16005 2.07266 6.30266C2.13658 6.4281 2.23856 6.53009 2.36401 6.594C2.50661 6.66667 2.6933 6.66667 3.06667 6.66667ZM3.06667 14H5.6C5.97337 14 6.16005 14 6.30266 13.9273C6.4281 13.8634 6.53009 13.7614 6.594 13.636C6.66667 13.4934 6.66667 13.3067 6.66667 12.9333V10.4C6.66667 10.0266 6.66667 9.83995 6.594 9.69734C6.53009 9.5719 6.4281 9.46991 6.30266 9.406C6.16005 9.33333 5.97337 9.33333 5.6 9.33333H3.06667C2.6933 9.33333 2.50661 9.33333 2.36401 9.406C2.23856 9.46991 2.13658 9.5719 2.07266 9.69734C2 9.83995 2 10.0266 2 10.4V12.9333C2 13.3067 2 13.4934 2.07266 13.636C2.13658 13.7614 2.23856 13.8634 2.36401 13.9273C2.50661 14 2.6933 14 3.06667 14Z" stroke="#1D2939" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
4
web/app/components/develop/secret-key/assets/qrcode.svg
Normal file
4
web/app/components/develop/secret-key/assets/qrcode.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.33333 4.33333H4.34M11.6667 4.33333H11.6733M4.33333 11.6667H4.34M8.66667 8.66667H8.67333M11.6667 11.6667H11.6733M11.3333 14H14V11.3333M9.33333 11V14M14 9.33333H11M10.4 6.66667H12.9333C13.3067 6.66667 13.4934 6.66667 13.636 6.594C13.7614 6.53009 13.8634 6.4281 13.9273 6.30266C14 6.16005 14 5.97337 14 5.6V3.06667C14 2.6933 14 2.50661 13.9273 2.36401C13.8634 2.23856 13.7614 2.13658 13.636 2.07266C13.4934 2 13.3067 2 12.9333 2H10.4C10.0266 2 9.83995 2 9.69734 2.07266C9.5719 2.13658 9.46991 2.23856 9.406 2.36401C9.33333 2.50661 9.33333 2.6933 9.33333 3.06667V5.6C9.33333 5.97337 9.33333 6.16005 9.406 6.30266C9.46991 6.4281 9.5719 6.53009 9.69734 6.594C9.83995 6.66667 10.0266 6.66667 10.4 6.66667ZM3.06667 6.66667H5.6C5.97337 6.66667 6.16005 6.66667 6.30266 6.594C6.4281 6.53009 6.53009 6.4281 6.594 6.30266C6.66667 6.16005 6.66667 5.97337 6.66667 5.6V3.06667C6.66667 2.6933 6.66667 2.50661 6.594 2.36401C6.53009 2.23856 6.4281 2.13658 6.30266 2.07266C6.16005 2 5.97337 2 5.6 2H3.06667C2.6933 2 2.50661 2 2.36401 2.07266C2.23856 2.13658 2.13658 2.23856 2.07266 2.36401C2 2.50661 2 2.6933 2 3.06667V5.6C2 5.97337 2 6.16005 2.07266 6.30266C2.13658 6.4281 2.23856 6.53009 2.36401 6.594C2.50661 6.66667 2.6933 6.66667 3.06667 6.66667ZM3.06667 14H5.6C5.97337 14 6.16005 14 6.30266 13.9273C6.4281 13.8634 6.53009 13.7614 6.594 13.636C6.66667 13.4934 6.66667 13.3067 6.66667 12.9333V10.4C6.66667 10.0266 6.66667 9.83995 6.594 9.69734C6.53009 9.5719 6.4281 9.46991 6.30266 9.406C6.16005 9.33333 5.97337 9.33333 5.6 9.33333H3.06667C2.6933 9.33333 2.50661 9.33333 2.36401 9.406C2.23856 9.46991 2.13658 9.5719 2.07266 9.69734C2 9.83995 2 10.0266 2 10.4V12.9333C2 13.3067 2 13.4934 2.07266 13.636C2.13658 13.7614 2.23856 13.8634 2.36401 13.9273C2.50661 14 2.6933 14 3.06667 14Z" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
|
@ -61,6 +61,11 @@ const translation = {
|
|||
copied: 'Copied',
|
||||
copy: 'Copy',
|
||||
},
|
||||
qrcode: {
|
||||
title: 'QR code to share',
|
||||
scan: 'Scan Share Application',
|
||||
download: 'Download QR Code',
|
||||
},
|
||||
customize: {
|
||||
way: 'way',
|
||||
entry: 'Customize',
|
||||
|
|
|
@ -61,6 +61,11 @@ const translation = {
|
|||
copied: '已复制',
|
||||
copy: '复制',
|
||||
},
|
||||
qrcode: {
|
||||
title: '二维码分享',
|
||||
scan: '扫码分享应用',
|
||||
download: '下载二维码',
|
||||
},
|
||||
customize: {
|
||||
way: '方法',
|
||||
entry: '定制化',
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
"mermaid": "10.4.0",
|
||||
"negotiator": "^0.6.3",
|
||||
"next": "13.3.1",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"qs": "^6.11.1",
|
||||
"react": "^18.2.0",
|
||||
"react-18-input-autosize": "^3.0.0",
|
||||
|
|
Loading…
Reference in New Issue
Block a user