mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-03-02 00:30:25 +00:00
refactor: 整体重构 (#1381)
* feat: pnpm new * Refactor build and release workflows, update dependencies Switch build scripts and workflows from npm to pnpm, update build and artifact paths, and simplify release workflow by removing version detection and changelog steps. Add new dependencies (silk-wasm, express, ws, node-pty-prebuilt-multiarch), update exports in package.json files, and add vite config for napcat-framework. Also, rename manifest.json for framework package and fix static asset copying in shell build config.
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
import { Avatar } from '@heroui/avatar';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@heroui/popover';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import { isOB11GroupMessage } from '@/utils/onebot';
|
||||
|
||||
import type {
|
||||
OB11GroupMessage,
|
||||
OB11Message,
|
||||
OB11PrivateMessage,
|
||||
} from '@/types/onebot';
|
||||
|
||||
import { renderMessageContent } from '../render_message';
|
||||
|
||||
export interface OneBotMessageProps {
|
||||
data: OB11Message
|
||||
}
|
||||
|
||||
export interface OneBotMessageGroupProps {
|
||||
data: OB11GroupMessage
|
||||
}
|
||||
|
||||
export interface OneBotMessagePrivateProps {
|
||||
data: OB11PrivateMessage
|
||||
}
|
||||
|
||||
const MessageContent: React.FC<{ data: OB11Message }> = ({ data }) => {
|
||||
return (
|
||||
<div className='h-full flex flex-col overflow-hidden flex-1'>
|
||||
<div className='flex gap-2 items-center flex-shrink-0'>
|
||||
<div className='font-bold'>
|
||||
{isOB11GroupMessage(data) && data.sender.card && (
|
||||
<span className='mr-1'>{data.sender.card}</span>
|
||||
)}
|
||||
<span
|
||||
className={clsx(
|
||||
isOB11GroupMessage(data) &&
|
||||
data.sender.card &&
|
||||
'text-default-400 font-normal'
|
||||
)}
|
||||
>
|
||||
{data.sender.nickname}
|
||||
</span>
|
||||
</div>
|
||||
<div>({data.sender.user_id})</div>
|
||||
<div className='text-sm'>消息ID: {data.message_id}</div>
|
||||
</div>
|
||||
<Popover showArrow triggerScaleOnOpen={false}>
|
||||
<PopoverTrigger>
|
||||
<div className='flex-1 break-all overflow-hidden whitespace-pre-wrap border border-default-100 p-2 rounded-md hover:bg-content2 md:cursor-pointer transition-background relative group'>
|
||||
<div className='absolute right-2 top-2 opacity-0 group-hover:opacity-100 text-default-300'>
|
||||
点击查看完整消息
|
||||
</div>
|
||||
{Array.isArray(data.message)
|
||||
? renderMessageContent(data.message, true)
|
||||
: data.raw_message}
|
||||
</div>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent>
|
||||
<div className='p-2'>
|
||||
{Array.isArray(data.message)
|
||||
? renderMessageContent(data.message)
|
||||
: data.raw_message}
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const OneBotMessageGroup: React.FC<OneBotMessageGroupProps> = ({ data }) => {
|
||||
return (
|
||||
<div className='h-full overflow-hidden flex flex-col w-full'>
|
||||
<div className='flex items-center p-1 flex-shrink-0'>
|
||||
<Avatar
|
||||
src={`https://p.qlogo.cn/gh/${data.group_id}/${data.group_id}/640/`}
|
||||
alt='群头像'
|
||||
size='sm'
|
||||
className='flex-shrink-0 mr-2'
|
||||
/>
|
||||
<div>群 {data.group_id}</div>
|
||||
</div>
|
||||
<div className='flex items-start p-1 rounded-md h-full flex-1 border border-default-100'>
|
||||
<Avatar
|
||||
src={`https://q1.qlogo.cn/g?b=qq&nk=${data.sender.user_id}&s=100`}
|
||||
alt='用户头像'
|
||||
size='md'
|
||||
className='flex-shrink-0 mr-2'
|
||||
/>
|
||||
<MessageContent data={data} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const OneBotMessagePrivate: React.FC<OneBotMessagePrivateProps> = ({
|
||||
data,
|
||||
}) => {
|
||||
return (
|
||||
<div className='flex items-start p-2 rounded-md h-full flex-1'>
|
||||
<Avatar
|
||||
src={`https://q1.qlogo.cn/g?b=qq&nk=${data.sender.user_id}&s=100`}
|
||||
alt='用户头像'
|
||||
size='md'
|
||||
className='flex-shrink-0 mr-2'
|
||||
/>
|
||||
<MessageContent data={data} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const OneBotMessage: React.FC<OneBotMessageProps> = ({ data }) => {
|
||||
if (data.message_type === 'group') {
|
||||
return <OneBotMessageGroup data={data} />;
|
||||
} else if (data.message_type === 'private') {
|
||||
return <OneBotMessagePrivate data={data} />;
|
||||
} else {
|
||||
return <div>未知消息类型</div>;
|
||||
}
|
||||
};
|
||||
|
||||
export default OneBotMessage;
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Chip } from '@heroui/chip';
|
||||
|
||||
import { getLifecycleColor, getLifecycleName } from '@/utils/onebot';
|
||||
|
||||
import type {
|
||||
OB11Meta,
|
||||
OneBot11Heartbeat,
|
||||
OneBot11Lifecycle,
|
||||
} from '@/types/onebot';
|
||||
|
||||
export interface OneBotDisplayMetaProps {
|
||||
data: OB11Meta
|
||||
}
|
||||
|
||||
export interface OneBotDisplayMetaHeartbeatProps {
|
||||
data: OneBot11Heartbeat
|
||||
}
|
||||
|
||||
export interface OneBotDisplayMetaLifecycleProps {
|
||||
data: OneBot11Lifecycle
|
||||
}
|
||||
|
||||
const OneBotDisplayMetaHeartbeat: React.FC<OneBotDisplayMetaHeartbeatProps> = ({
|
||||
data,
|
||||
}) => {
|
||||
return (
|
||||
<div className='flex gap-2'>
|
||||
<Chip>心跳</Chip>
|
||||
<Chip>间隔 {data.status.interval}ms</Chip>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const OneBotDisplayMetaLifecycle: React.FC<OneBotDisplayMetaLifecycleProps> = ({
|
||||
data,
|
||||
}) => {
|
||||
return (
|
||||
<div className='flex gap-2'>
|
||||
<Chip>生命周期</Chip>
|
||||
<Chip color={getLifecycleColor(data.sub_type)}>
|
||||
{getLifecycleName(data.sub_type)}
|
||||
</Chip>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const OneBotDisplayMeta: React.FC<OneBotDisplayMetaProps> = ({ data }) => {
|
||||
return (
|
||||
<div className='h-full flex items-center'>
|
||||
{data.meta_event_type === 'lifecycle' && (
|
||||
<OneBotDisplayMetaLifecycle data={data} />
|
||||
)}
|
||||
{data.meta_event_type === 'heartbeat' && (
|
||||
<OneBotDisplayMetaHeartbeat data={data} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OneBotDisplayMeta;
|
||||
@@ -0,0 +1,292 @@
|
||||
import { Chip } from '@heroui/chip';
|
||||
|
||||
import { getNoticeTypeName } from '@/utils/onebot';
|
||||
|
||||
import {
|
||||
OB11Notice,
|
||||
OB11NoticeType,
|
||||
OneBot11FriendAdd,
|
||||
OneBot11FriendRecall,
|
||||
OneBot11GroupAdmin,
|
||||
OneBot11GroupBan,
|
||||
OneBot11GroupCard,
|
||||
OneBot11GroupDecrease,
|
||||
OneBot11GroupEssence,
|
||||
OneBot11GroupIncrease,
|
||||
OneBot11GroupMessageReaction,
|
||||
OneBot11GroupRecall,
|
||||
OneBot11GroupUpload,
|
||||
OneBot11Honor,
|
||||
OneBot11LuckyKing,
|
||||
OneBot11Poke,
|
||||
} from '@/types/onebot';
|
||||
|
||||
export interface OneBotNoticeProps {
|
||||
data: OB11Notice
|
||||
}
|
||||
|
||||
export interface NoticeProps<T> {
|
||||
data: T
|
||||
}
|
||||
|
||||
const GroupUploadNotice: React.FC<NoticeProps<OneBot11GroupUpload>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { group_id, user_id, file } = data;
|
||||
return (
|
||||
<>
|
||||
<div>群号: {group_id}</div>
|
||||
<div>用户ID: {user_id}</div>
|
||||
<div>文件名: {file.name}</div>
|
||||
<div>文件大小: {file.size} 字节</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const GroupAdminNotice: React.FC<NoticeProps<OneBot11GroupAdmin>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { group_id, user_id, sub_type } = data;
|
||||
return (
|
||||
<>
|
||||
<div>群号: {group_id}</div>
|
||||
<div>用户ID: {user_id}</div>
|
||||
<div>变动类型: {sub_type === 'set' ? '设置管理员' : '取消管理员'}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const GroupDecreaseNotice: React.FC<NoticeProps<OneBot11GroupDecrease>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { group_id, operator_id, user_id, sub_type } = data;
|
||||
return (
|
||||
<>
|
||||
<div>群号: {group_id}</div>
|
||||
<div>操作者ID: {operator_id}</div>
|
||||
<div>用户ID: {user_id}</div>
|
||||
<div>原因: {sub_type}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const GroupIncreaseNotice: React.FC<NoticeProps<OneBot11GroupIncrease>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { group_id, operator_id, user_id, sub_type } = data;
|
||||
return (
|
||||
<>
|
||||
<div>群号: {group_id}</div>
|
||||
<div>操作者ID: {operator_id}</div>
|
||||
<div>用户ID: {user_id}</div>
|
||||
<div>增加类型: {sub_type}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const GroupBanNotice: React.FC<NoticeProps<OneBot11GroupBan>> = ({ data }) => {
|
||||
const { group_id, operator_id, user_id, sub_type, duration } = data;
|
||||
return (
|
||||
<>
|
||||
<div>群号: {group_id}</div>
|
||||
<div>操作者ID: {operator_id}</div>
|
||||
<div>用户ID: {user_id}</div>
|
||||
<div>禁言类型: {sub_type}</div>
|
||||
<div>禁言时长: {duration} 秒</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const FriendAddNotice: React.FC<NoticeProps<OneBot11FriendAdd>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { user_id } = data;
|
||||
return (
|
||||
<>
|
||||
<div>用户ID: {user_id}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const GroupRecallNotice: React.FC<NoticeProps<OneBot11GroupRecall>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { group_id, user_id, operator_id, message_id } = data;
|
||||
return (
|
||||
<>
|
||||
<div>群号: {group_id}</div>
|
||||
<div>用户ID: {user_id}</div>
|
||||
<div>操作者ID: {operator_id}</div>
|
||||
<div>消息ID: {message_id}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const FriendRecallNotice: React.FC<NoticeProps<OneBot11FriendRecall>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { user_id, message_id } = data;
|
||||
return (
|
||||
<>
|
||||
<div>用户ID: {user_id}</div>
|
||||
<div>消息ID: {message_id}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const PokeNotice: React.FC<NoticeProps<OneBot11Poke>> = ({ data }) => {
|
||||
const { group_id, user_id, target_id } = data;
|
||||
return (
|
||||
<>
|
||||
<div>群号: {group_id}</div>
|
||||
<div>用户ID: {user_id}</div>
|
||||
<div>目标ID: {target_id}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const LuckyKingNotice: React.FC<NoticeProps<OneBot11LuckyKing>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { group_id, user_id, target_id } = data;
|
||||
return (
|
||||
<>
|
||||
<div>群号: {group_id}</div>
|
||||
<div>用户ID: {user_id}</div>
|
||||
<div>目标ID: {target_id}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const HonorNotice: React.FC<NoticeProps<OneBot11Honor>> = ({ data }) => {
|
||||
const { group_id, user_id, honor_type } = data;
|
||||
return (
|
||||
<>
|
||||
<div>群号: {group_id}</div>
|
||||
<div>用户ID: {user_id}</div>
|
||||
<div>荣誉类型: {honor_type}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const GroupMessageReactionNotice: React.FC<
|
||||
NoticeProps<OneBot11GroupMessageReaction>
|
||||
> = ({ data }) => {
|
||||
const { group_id, user_id, message_id, likes } = data;
|
||||
return (
|
||||
<>
|
||||
<div>群号: {group_id}</div>
|
||||
<div>用户ID: {user_id}</div>
|
||||
<div>消息ID: {message_id}</div>
|
||||
<div>
|
||||
表情回应:
|
||||
{likes
|
||||
.map((like) => `表情ID: ${like.emoji_id}, 数量: ${like.count}`)
|
||||
.join(', ')}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const GroupEssenceNotice: React.FC<NoticeProps<OneBot11GroupEssence>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { group_id, message_id, sender_id, operator_id, sub_type } = data;
|
||||
return (
|
||||
<>
|
||||
<div>群号: {group_id}</div>
|
||||
<div>消息ID: {message_id}</div>
|
||||
<div>发送者ID: {sender_id}</div>
|
||||
<div>操作者ID: {operator_id}</div>
|
||||
<div>操作类型: {sub_type}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const GroupCardNotice: React.FC<NoticeProps<OneBot11GroupCard>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { group_id, user_id, card_new, card_old } = data;
|
||||
return (
|
||||
<>
|
||||
<div>群号: {group_id}</div>
|
||||
<div>用户ID: {user_id}</div>
|
||||
<div>新名片: {card_new}</div>
|
||||
<div>旧名片: {card_old}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const OneBotNotice: React.FC<OneBotNoticeProps> = ({ data }) => {
|
||||
let NoticeComponent: React.ReactNode;
|
||||
switch (data.notice_type) {
|
||||
case OB11NoticeType.GroupUpload:
|
||||
NoticeComponent = <GroupUploadNotice data={data} />;
|
||||
break;
|
||||
case OB11NoticeType.GroupAdmin:
|
||||
NoticeComponent = <GroupAdminNotice data={data} />;
|
||||
break;
|
||||
case OB11NoticeType.GroupDecrease:
|
||||
NoticeComponent = <GroupDecreaseNotice data={data} />;
|
||||
break;
|
||||
case OB11NoticeType.GroupIncrease:
|
||||
NoticeComponent = (
|
||||
<GroupIncreaseNotice data={data as OneBot11GroupIncrease} />
|
||||
);
|
||||
break;
|
||||
case OB11NoticeType.GroupBan:
|
||||
NoticeComponent = <GroupBanNotice data={data} />;
|
||||
break;
|
||||
case OB11NoticeType.FriendAdd:
|
||||
NoticeComponent = <FriendAddNotice data={data as OneBot11FriendAdd} />;
|
||||
break;
|
||||
case OB11NoticeType.GroupRecall:
|
||||
NoticeComponent = <GroupRecallNotice data={data as OneBot11GroupRecall} />;
|
||||
break;
|
||||
case OB11NoticeType.FriendRecall:
|
||||
NoticeComponent = (
|
||||
<FriendRecallNotice data={data as OneBot11FriendRecall} />
|
||||
);
|
||||
break;
|
||||
case OB11NoticeType.Notify:
|
||||
switch (data.sub_type) {
|
||||
case 'poke':
|
||||
NoticeComponent = <PokeNotice data={data as OneBot11Poke} />;
|
||||
break;
|
||||
case 'lucky_king':
|
||||
NoticeComponent = <LuckyKingNotice data={data as OneBot11LuckyKing} />;
|
||||
break;
|
||||
case 'honor':
|
||||
NoticeComponent = <HonorNotice data={data as OneBot11Honor} />;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OB11NoticeType.GroupMsgEmojiLike:
|
||||
NoticeComponent = (
|
||||
<GroupMessageReactionNotice
|
||||
data={data as OneBot11GroupMessageReaction}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case OB11NoticeType.GroupEssence:
|
||||
NoticeComponent = (
|
||||
<GroupEssenceNotice data={data as OneBot11GroupEssence} />
|
||||
);
|
||||
break;
|
||||
case OB11NoticeType.GroupCard:
|
||||
NoticeComponent = <GroupCardNotice data={data as OneBot11GroupCard} />;
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex gap-2 items-center'>
|
||||
<Chip color='warning' variant='flat'>
|
||||
通知
|
||||
</Chip>
|
||||
<Chip>{getNoticeTypeName(data.notice_type)}</Chip>
|
||||
{NoticeComponent}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OneBotNotice;
|
||||
@@ -0,0 +1,151 @@
|
||||
import { Button } from '@heroui/button';
|
||||
import { Card, CardBody, CardHeader } from '@heroui/card';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@heroui/popover';
|
||||
import { Snippet } from '@heroui/snippet';
|
||||
import { motion } from 'motion/react';
|
||||
import { IoCode } from 'react-icons/io5';
|
||||
|
||||
import OneBotDisplayMeta from '@/components/onebot/display_card/meta';
|
||||
|
||||
import { getEventName, isOB11Event } from '@/utils/onebot';
|
||||
import { timestampToDateString } from '@/utils/time';
|
||||
|
||||
import type {
|
||||
AllOB11WsResponse,
|
||||
OB11AllEvent,
|
||||
OB11Request,
|
||||
} from '@/types/onebot';
|
||||
|
||||
import OneBotMessage from './message';
|
||||
import OneBotNotice from './notice';
|
||||
import OneBotDisplayResponse from './response';
|
||||
|
||||
const itemVariants = {
|
||||
hidden: { opacity: 0, scale: 0.8, y: 50 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
y: 0,
|
||||
transition: { type: 'spring' as const, stiffness: 300, damping: 20 },
|
||||
},
|
||||
};
|
||||
|
||||
function RequestComponent ({ data: _ }: { data: OB11Request }) {
|
||||
return <div>Request消息,暂未适配</div>;
|
||||
}
|
||||
|
||||
export interface OneBotItemRenderProps {
|
||||
data: AllOB11WsResponse[]
|
||||
index: number
|
||||
style: React.CSSProperties
|
||||
}
|
||||
|
||||
export const getItemSize = (event: OB11AllEvent['post_type']) => {
|
||||
if (event === 'meta_event') {
|
||||
return 100;
|
||||
}
|
||||
if (event === 'message') {
|
||||
return 180;
|
||||
}
|
||||
if (event === 'request') {
|
||||
return 100;
|
||||
}
|
||||
if (event === 'notice') {
|
||||
return 100;
|
||||
}
|
||||
if (event === 'message_sent') {
|
||||
return 250;
|
||||
}
|
||||
return 100;
|
||||
};
|
||||
|
||||
const renderDetail = (data: AllOB11WsResponse) => {
|
||||
if (isOB11Event(data)) {
|
||||
switch (data.post_type) {
|
||||
case 'meta_event':
|
||||
return <OneBotDisplayMeta data={data} />;
|
||||
case 'message':
|
||||
return <OneBotMessage data={data} />;
|
||||
case 'request':
|
||||
return <RequestComponent data={data} />;
|
||||
case 'notice':
|
||||
return <OneBotNotice data={data} />;
|
||||
case 'message_sent':
|
||||
return <OneBotMessage data={data} />;
|
||||
default:
|
||||
return <div>未知类型的消息</div>;
|
||||
}
|
||||
}
|
||||
return <OneBotDisplayResponse data={data} />;
|
||||
};
|
||||
|
||||
const OneBotItemRender = ({ data, index, style }: OneBotItemRenderProps) => {
|
||||
const msg = data[index];
|
||||
const isEvent = isOB11Event(msg);
|
||||
return (
|
||||
<div style={style} className='p-1 overflow-visible w-full h-full'>
|
||||
<motion.div
|
||||
variants={itemVariants}
|
||||
initial='hidden'
|
||||
animate='visible'
|
||||
className='h-full px-2'
|
||||
>
|
||||
<Card className='w-full h-full py-2 bg-opacity-50 backdrop-blur-sm'>
|
||||
<CardHeader className='py-0 text-default-500 flex-row gap-2'>
|
||||
<div className='font-bold'>
|
||||
{isEvent ? getEventName(msg.post_type) : '请求响应'}
|
||||
</div>
|
||||
<div className='text-sm'>
|
||||
{isEvent && timestampToDateString(msg.time)}
|
||||
</div>
|
||||
<div className='ml-auto'>
|
||||
<Popover
|
||||
placement='left'
|
||||
showArrow
|
||||
classNames={{
|
||||
content: 'max-h-96 max-w-96 overflow-hidden p-0',
|
||||
}}
|
||||
>
|
||||
<PopoverTrigger>
|
||||
<Button
|
||||
size='sm'
|
||||
color='primary'
|
||||
variant='flat'
|
||||
radius='full'
|
||||
isIconOnly
|
||||
className='text-medium'
|
||||
>
|
||||
<IoCode />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent>
|
||||
<Snippet
|
||||
hideSymbol
|
||||
tooltipProps={{
|
||||
content: '点击复制',
|
||||
}}
|
||||
classNames={{
|
||||
copyButton: 'self-start sticky top-0 right-0',
|
||||
}}
|
||||
className='bg-content1 h-full overflow-y-scroll items-start'
|
||||
>
|
||||
{JSON.stringify(msg, null, 2)
|
||||
.split('\n')
|
||||
.map((line, i) => (
|
||||
<span key={i} className='whitespace-pre-wrap break-all'>
|
||||
{line}
|
||||
</span>
|
||||
))}
|
||||
</Snippet>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardBody className='py-0'>{renderDetail(msg)}</CardBody>
|
||||
</Card>
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OneBotItemRender;
|
||||
@@ -0,0 +1,75 @@
|
||||
import { Button } from '@heroui/button';
|
||||
import { Chip } from '@heroui/chip';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@heroui/popover';
|
||||
import { Snippet } from '@heroui/snippet';
|
||||
|
||||
import { getResponseStatusColor, getResponseStatusText } from '@/utils/onebot';
|
||||
|
||||
import { RequestResponse } from '@/types/onebot';
|
||||
|
||||
export interface OneBotDisplayResponseProps {
|
||||
data: RequestResponse
|
||||
}
|
||||
|
||||
const OneBotDisplayResponse: React.FC<OneBotDisplayResponseProps> = ({
|
||||
data,
|
||||
}) => {
|
||||
return (
|
||||
<div className='flex gap-2 items-center'>
|
||||
<Chip color={getResponseStatusColor(data.status)} variant='flat'>
|
||||
{getResponseStatusText(data.status)}
|
||||
</Chip>
|
||||
{data.data && (
|
||||
<Popover
|
||||
placement='right'
|
||||
showArrow
|
||||
classNames={{
|
||||
content: 'max-h-96 max-w-96 overflow-hidden p-0',
|
||||
}}
|
||||
>
|
||||
<PopoverTrigger>
|
||||
<Button
|
||||
size='sm'
|
||||
color='primary'
|
||||
variant='flat'
|
||||
radius='full'
|
||||
className='text-medium'
|
||||
>
|
||||
查看数据
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent>
|
||||
<Snippet
|
||||
hideSymbol
|
||||
tooltipProps={{
|
||||
content: '点击复制',
|
||||
}}
|
||||
classNames={{
|
||||
copyButton: 'self-start sticky top-0 right-0',
|
||||
}}
|
||||
className='bg-content1 h-full overflow-y-scroll items-start'
|
||||
>
|
||||
{JSON.stringify(data.data, null, 2)
|
||||
.split('\n')
|
||||
.map((line, i) => (
|
||||
<span key={i} className='whitespace-pre-wrap break-all'>
|
||||
{line}
|
||||
</span>
|
||||
))}
|
||||
</Snippet>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)}
|
||||
{data.message && (
|
||||
<Chip className='pl-0.5' variant='flat'>
|
||||
<Chip color='warning' size='sm' className='-ml-2 mr-1' variant='flat'>
|
||||
返回消息
|
||||
</Chip>
|
||||
{data.message}
|
||||
</Chip>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OneBotDisplayResponse;
|
||||
Reference in New Issue
Block a user