mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-02-06 13:05:09 +00:00
fix: 终端字符宽度&微调样式&路由切换动画
This commit is contained in:
@@ -187,7 +187,7 @@ export default function AudioPlayer(props: AudioPlayerProps) {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'fixed right-0 bottom-0 z-[9999] w-full md:w-96',
|
||||
'fixed right-0 bottom-0 z-[52] w-full md:w-96',
|
||||
!translateX && !translateY && 'transition-transform',
|
||||
isCollapsed && 'md:hover:!translate-x-80'
|
||||
)}
|
||||
|
||||
@@ -19,12 +19,6 @@ loader.config({
|
||||
}
|
||||
})
|
||||
|
||||
loader.config({
|
||||
'vs/nls': {
|
||||
availableLanguages: { '*': 'zh-cn' }
|
||||
}
|
||||
})
|
||||
|
||||
export interface CodeEditorProps extends React.ComponentProps<typeof Editor> {
|
||||
test?: string
|
||||
}
|
||||
|
||||
@@ -1125,7 +1125,7 @@ export const WebUIIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
@@ -1173,7 +1173,7 @@ export const WebUIIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
@@ -1220,7 +1220,7 @@ export const WebUIIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
@@ -1270,7 +1270,7 @@ export const WebUIIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
@@ -1320,7 +1320,7 @@ export const WebUIIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
@@ -1372,7 +1372,7 @@ export const BietiaopIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
@@ -1422,7 +1422,7 @@ export const BietiaopIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
@@ -1469,7 +1469,7 @@ export const BietiaopIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
@@ -1519,7 +1519,7 @@ export const BietiaopIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
@@ -1566,7 +1566,7 @@ export const BietiaopIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
@@ -1613,7 +1613,7 @@ export const BietiaopIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
@@ -1660,7 +1660,7 @@ export const BietiaopIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
@@ -1707,7 +1707,7 @@ export const BietiaopIcon = (props: IconSvgProps) => (
|
||||
>
|
||||
<g
|
||||
id="svgGroup"
|
||||
stroke-linecap="round"
|
||||
strokeLinecap="round"
|
||||
stroke="#000"
|
||||
fill="transparent"
|
||||
style={{
|
||||
|
||||
@@ -50,8 +50,8 @@ const Modal: React.FC<ModalProps> = React.memo((props) => {
|
||||
onNativeClose()
|
||||
}}
|
||||
classNames={{
|
||||
backdrop: 'z-[99999999]',
|
||||
wrapper: 'z-[999999999]'
|
||||
backdrop: 'z-[99]',
|
||||
wrapper: 'z-[99]'
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Input } from '@heroui/input'
|
||||
import { Snippet } from '@heroui/snippet'
|
||||
import { useLocalStorage } from '@uidotdev/usehooks'
|
||||
import { motion } from 'motion/react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import toast from 'react-hot-toast'
|
||||
import { IoLink, IoSend } from 'react-icons/io5'
|
||||
import { PiCatDuotone } from 'react-icons/pi'
|
||||
@@ -41,6 +41,7 @@ const OneBotApiDebug: React.FC<OneBotApiDebugProps> = (props) => {
|
||||
const [isCodeEditorOpen, setIsCodeEditorOpen] = useState(false)
|
||||
const [isResponseOpen, setIsResponseOpen] = useState(false)
|
||||
const [isFetching, setIsFetching] = useState(false)
|
||||
const responseRef = useRef<HTMLDivElement>(null)
|
||||
const parsedRequest = parse(data.request)
|
||||
const parsedResponse = parse(data.response)
|
||||
|
||||
@@ -69,6 +70,11 @@ const OneBotApiDebug: React.FC<OneBotApiDebugProps> = (props) => {
|
||||
})
|
||||
.finally(() => {
|
||||
setIsFetching(false)
|
||||
setIsResponseOpen(true)
|
||||
responseRef.current?.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
})
|
||||
toast.dismiss(r)
|
||||
})
|
||||
} catch (error) {
|
||||
@@ -84,8 +90,8 @@ const OneBotApiDebug: React.FC<OneBotApiDebugProps> = (props) => {
|
||||
}, [path])
|
||||
|
||||
return (
|
||||
<div className="flex-1 overflow-y-auto p-4 rounded-lg shadow-md">
|
||||
<h1 className="text-2xl font-bold mb-4 flex items-center gap-1 text-danger-400 ">
|
||||
<section className="p-4 pt-14 rounded-lg shadow-md">
|
||||
<h1 className="text-2xl font-bold mb-4 flex items-center gap-1 text-danger-400">
|
||||
<PiCatDuotone />
|
||||
{data.description}
|
||||
</h1>
|
||||
@@ -93,6 +99,9 @@ const OneBotApiDebug: React.FC<OneBotApiDebugProps> = (props) => {
|
||||
<Snippet
|
||||
className="bg-default-50 bg-opacity-50 backdrop-blur-md"
|
||||
symbol={<IoLink size={18} className="inline-block mr-1" />}
|
||||
tooltipProps={{
|
||||
content: '点击复制地址'
|
||||
}}
|
||||
>
|
||||
{path}
|
||||
</Snippet>
|
||||
@@ -125,7 +134,10 @@ const OneBotApiDebug: React.FC<OneBotApiDebugProps> = (props) => {
|
||||
<IoSend />
|
||||
</Button>
|
||||
</div>
|
||||
<Card shadow="sm" className="my-4 bg-opacity-50 backdrop-blur-md">
|
||||
<Card
|
||||
shadow="sm"
|
||||
className="my-4 bg-opacity-50 backdrop-blur-md overflow-visible z-20"
|
||||
>
|
||||
<CardHeader className="font-noto-serif font-bold text-lg gap-1 pb-0">
|
||||
<span className="mr-2">请求体</span>
|
||||
<Button
|
||||
@@ -140,7 +152,7 @@ const OneBotApiDebug: React.FC<OneBotApiDebugProps> = (props) => {
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<motion.div
|
||||
className="overflow-hidden"
|
||||
ref={responseRef}
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{
|
||||
opacity: isCodeEditorOpen ? 1 : 0,
|
||||
@@ -223,7 +235,7 @@ const OneBotApiDebug: React.FC<OneBotApiDebugProps> = (props) => {
|
||||
<h2 className="text-xl font-semibold mt-4 mb-2">响应体结构</h2>
|
||||
<DisplayStruct schema={parsedResponse} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,8 @@ const OneBotApiNavList: React.FC<OneBotApiNavListProps> = (props) => {
|
||||
return (
|
||||
<motion.div
|
||||
className={clsx(
|
||||
'flex-shrink-0 absolute md:!top-0 md:bottom-0 left-0 !overflow-hidden md:relative md:w-auto z-20',
|
||||
openSideBar &&
|
||||
'bottom-8 z-10 bg-background bg-opacity-20 backdrop-blur-md top-14'
|
||||
'h-[calc(100vh-3.5rem)] left-0 !overflow-hidden md:w-auto z-20 top-[3.3rem] md:top-[3rem] absolute md:sticky md:float-start',
|
||||
openSideBar && 'bg-background bg-opacity-20 backdrop-blur-md'
|
||||
)}
|
||||
initial={{ width: 0 }}
|
||||
transition={{
|
||||
@@ -32,7 +31,7 @@ const OneBotApiNavList: React.FC<OneBotApiNavListProps> = (props) => {
|
||||
animate={{ width: openSideBar ? '16rem' : '0rem' }}
|
||||
style={{ overflowY: openSideBar ? 'auto' : 'hidden' }}
|
||||
>
|
||||
<div className="w-64 h-full overflow-y-auto px-2 float-right">
|
||||
<div className="w-64 h-full overflow-y-auto px-2 pt-2 pb-10 md:pb-0">
|
||||
<Input
|
||||
className="sticky top-0 z-10 text-danger-600"
|
||||
classNames={{
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
import { useCallback, useRef } from 'react'
|
||||
import toast from 'react-hot-toast'
|
||||
|
||||
import ChatInputModal from '@/components/chat_input/modal'
|
||||
import CodeEditor from '@/components/code_editor'
|
||||
import type { CodeEditorRef } from '@/components/code_editor'
|
||||
|
||||
@@ -72,6 +73,8 @@ const OneBotSendModal: React.FC<OneBotSendModalProps> = (props) => {
|
||||
</div>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<ChatInputModal />
|
||||
|
||||
<Button color="danger" variant="flat" onPress={onClose}>
|
||||
取消
|
||||
</Button>
|
||||
|
||||
@@ -36,7 +36,9 @@ const XTerm = forwardRef<XTermRef, React.HTMLAttributes<HTMLDivElement>>(
|
||||
allowTransparency: true,
|
||||
fontFamily: '"Fira Code", "Harmony", "Noto Serif SC", monospace',
|
||||
cursorInactiveStyle: 'outline',
|
||||
drawBoldTextInBrightColors: false
|
||||
drawBoldTextInBrightColors: false,
|
||||
letterSpacing: 0,
|
||||
lineHeight: 1.0
|
||||
})
|
||||
terminalRef.current = terminal
|
||||
const fitAddon = new FitAddon()
|
||||
@@ -51,10 +53,6 @@ const XTerm = forwardRef<XTermRef, React.HTMLAttributes<HTMLDivElement>>(
|
||||
terminal.loadAddon(new WebglAddon())
|
||||
terminal.open(domRef.current)
|
||||
|
||||
setTimeout(() => {
|
||||
fitAddon.fit()
|
||||
}, 0)
|
||||
|
||||
terminal.writeln(
|
||||
gradientText(
|
||||
'Welcome to NapCat WebUI',
|
||||
@@ -69,16 +67,16 @@ const XTerm = forwardRef<XTermRef, React.HTMLAttributes<HTMLDivElement>>(
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
fitAddon.fit()
|
||||
})
|
||||
resizeObserver.observe(domRef.current)
|
||||
|
||||
const handleFontLoad = () => {
|
||||
terminal.refresh(0, terminal.rows - 1)
|
||||
}
|
||||
document.fonts.addEventListener('loadingdone', handleFontLoad)
|
||||
// 字体加载完成后重新调整终端大小
|
||||
document.fonts.ready.then(() => {
|
||||
fitAddon.fit()
|
||||
|
||||
resizeObserver.observe(domRef.current!)
|
||||
})
|
||||
|
||||
return () => {
|
||||
resizeObserver.disconnect()
|
||||
document.fonts.removeEventListener('loadingdone', handleFontLoad)
|
||||
setTimeout(() => {
|
||||
terminal.dispose()
|
||||
}, 0)
|
||||
|
||||
Reference in New Issue
Block a user