mirror of https://github.com/chaitin/PandaWiki.git
Compare commits
1 Commits
035ce0284d
...
d9e07f89ba
| Author | SHA1 | Date |
|---|---|---|
|
|
d9e07f89ba |
|
|
@ -588,6 +588,7 @@ export type ChatConversationItem = {
|
|||
export type ChatConversationPair = {
|
||||
user: string;
|
||||
assistant: string;
|
||||
thinking_content: string;
|
||||
created_at: string;
|
||||
info: {
|
||||
feedback_content: string;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -262,7 +262,7 @@ const MemberAdd = ({
|
|||
MenuProps={{
|
||||
sx: {
|
||||
'.Mui-disabled': {
|
||||
opacity: 1,
|
||||
opacity: '1 !important',
|
||||
color: 'text.disabled',
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import { ChatConversationPair } from '@/api';
|
|||
import { getApiV1ConversationDetail } from '@/request/Conversation';
|
||||
import { DomainConversationDetailResp } from '@/request/types';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import Card from '@/components/Card';
|
||||
import MarkDown from '@/components/MarkDown';
|
||||
import { useAppSelector } from '@/store';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import {
|
||||
Accordion,
|
||||
AccordionDetails,
|
||||
|
|
@ -13,10 +13,169 @@ import {
|
|||
Box,
|
||||
Stack,
|
||||
useTheme,
|
||||
styled,
|
||||
alpha,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { Ellipsis, Icon, Modal } from '@ctzhian/ui';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
const handleThinkingContent = (content: string) => {
|
||||
const thinkRegex = /<think>([\s\S]*?)(?:<\/think>|$)/g;
|
||||
const thinkMatches = [];
|
||||
let match;
|
||||
while ((match = thinkRegex.exec(content)) !== null) {
|
||||
thinkMatches.push(match[1]);
|
||||
}
|
||||
|
||||
let answerContent = content.replace(/<think>[\s\S]*?<\/think>/g, '');
|
||||
answerContent = answerContent.replace(/<think>[\s\S]*$/, '');
|
||||
|
||||
return {
|
||||
thinkingContent: thinkMatches.join(''),
|
||||
answerContent: answerContent,
|
||||
};
|
||||
};
|
||||
|
||||
export const StyledConversationItem = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: theme.spacing(2),
|
||||
}));
|
||||
|
||||
// 聊天气泡相关组件
|
||||
export const StyledUserBubble = styled(Box)(({ theme }) => ({
|
||||
alignSelf: 'flex-end',
|
||||
maxWidth: '75%',
|
||||
padding: theme.spacing(1, 2),
|
||||
borderRadius: '10px 10px 0px 10px',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
color: theme.palette.primary.contrastText,
|
||||
fontSize: 14,
|
||||
wordBreak: 'break-word',
|
||||
}));
|
||||
|
||||
export const StyledAiBubble = styled(Box)(({ theme }) => ({
|
||||
alignSelf: 'flex-start',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
width: '100%',
|
||||
gap: theme.spacing(3),
|
||||
}));
|
||||
|
||||
export const StyledAiBubbleContent = styled(Box)(() => ({
|
||||
wordBreak: 'break-word',
|
||||
}));
|
||||
|
||||
// 对话相关组件
|
||||
export const StyledAccordion = styled(Accordion)(() => ({
|
||||
padding: 0,
|
||||
border: 'none',
|
||||
'&:before': {
|
||||
content: '""',
|
||||
height: 0,
|
||||
},
|
||||
background: 'transparent',
|
||||
backgroundImage: 'none',
|
||||
}));
|
||||
|
||||
export const StyledAccordionSummary = styled(AccordionSummary)(({ theme }) => ({
|
||||
paddingLeft: theme.spacing(2),
|
||||
paddingRight: theme.spacing(2),
|
||||
paddingTop: theme.spacing(1),
|
||||
paddingBottom: theme.spacing(1),
|
||||
userSelect: 'text',
|
||||
borderRadius: '10px',
|
||||
backgroundColor: theme.palette.background.paper3,
|
||||
border: '1px solid',
|
||||
borderColor: theme.palette.divider,
|
||||
}));
|
||||
|
||||
export const StyledAccordionDetails = styled(AccordionDetails)(({ theme }) => ({
|
||||
padding: theme.spacing(2),
|
||||
borderTop: 'none',
|
||||
}));
|
||||
|
||||
export const StyledQuestionText = styled(Box)(() => ({
|
||||
fontWeight: '700',
|
||||
fontSize: 16,
|
||||
lineHeight: '24px',
|
||||
wordBreak: 'break-all',
|
||||
}));
|
||||
|
||||
// 搜索结果相关组件
|
||||
export const StyledChunkAccordion = styled(Accordion)(({ theme }) => ({
|
||||
backgroundImage: 'none',
|
||||
background: 'transparent',
|
||||
border: 'none',
|
||||
padding: 0,
|
||||
}));
|
||||
|
||||
export const StyledChunkAccordionSummary = styled(AccordionSummary)(
|
||||
({ theme }) => ({
|
||||
justifyContent: 'flex-start',
|
||||
gap: theme.spacing(2),
|
||||
'.MuiAccordionSummary-content': {
|
||||
flexGrow: 0,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export const StyledChunkAccordionDetails = styled(AccordionDetails)(
|
||||
({ theme }) => ({
|
||||
paddingTop: 0,
|
||||
paddingLeft: theme.spacing(2),
|
||||
borderTop: 'none',
|
||||
borderLeft: '1px solid',
|
||||
borderColor: theme.palette.divider,
|
||||
}),
|
||||
);
|
||||
|
||||
export const StyledChunkItem = styled(Box)(({ theme }) => ({
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
'.hover-primary': {
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
// 思考过程相关组件
|
||||
export const StyledThinkingAccordion = styled(Accordion)(({ theme }) => ({
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
padding: 0,
|
||||
paddingBottom: theme.spacing(2),
|
||||
'&:before': {
|
||||
content: '""',
|
||||
height: 0,
|
||||
},
|
||||
}));
|
||||
|
||||
export const StyledThinkingAccordionSummary = styled(AccordionSummary)(
|
||||
({ theme }) => ({
|
||||
justifyContent: 'flex-start',
|
||||
gap: theme.spacing(2),
|
||||
'.MuiAccordionSummary-content': {
|
||||
flexGrow: 0,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export const StyledThinkingAccordionDetails = styled(AccordionDetails)(
|
||||
({ theme }) => ({
|
||||
paddingTop: 0,
|
||||
paddingLeft: theme.spacing(2),
|
||||
borderTop: 'none',
|
||||
borderLeft: '1px solid',
|
||||
borderColor: theme.palette.divider,
|
||||
'.markdown-body': {
|
||||
opacity: 0.75,
|
||||
fontSize: 12,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const Detail = ({
|
||||
id,
|
||||
open,
|
||||
|
|
@ -55,7 +214,11 @@ const Detail = ({
|
|||
};
|
||||
} else if (message.role === 'assistant') {
|
||||
if (currentPair.user) {
|
||||
currentPair.assistant = message.content;
|
||||
const { thinkingContent, answerContent } = handleThinkingContent(
|
||||
message.content || '',
|
||||
);
|
||||
currentPair.assistant = answerContent;
|
||||
currentPair.thinking_content = thinkingContent;
|
||||
currentPair.created_at = message.created_at;
|
||||
// @ts-expect-error 类型不兼容
|
||||
currentPair.info = message.info;
|
||||
|
|
@ -167,26 +330,43 @@ const Detail = ({
|
|||
<Stack gap={2}>
|
||||
{conversations &&
|
||||
conversations.map((item, index) => (
|
||||
<Box key={index}>
|
||||
<Accordion defaultExpanded={true}>
|
||||
<AccordionSummary
|
||||
expandIcon={<ExpandMoreIcon sx={{ fontSize: 24 }} />}
|
||||
sx={{
|
||||
userSelect: 'text',
|
||||
backgroundColor: 'background.paper3',
|
||||
fontSize: '18px',
|
||||
fontWeight: 'bold',
|
||||
}}
|
||||
>
|
||||
{item.user}
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<MarkDown
|
||||
content={item.assistant || '未查询到回答内容'}
|
||||
/>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</Box>
|
||||
<StyledConversationItem key={index}>
|
||||
{/* 用户问题气泡 - 右对齐 */}
|
||||
<StyledUserBubble>{item.user}</StyledUserBubble>
|
||||
|
||||
{/* AI回答气泡 - 左对齐 */}
|
||||
<StyledAiBubble>
|
||||
{/* 思考过程 */}
|
||||
{!!item.thinking_content && (
|
||||
<StyledThinkingAccordion defaultExpanded>
|
||||
<StyledThinkingAccordionSummary
|
||||
expandIcon={<ExpandMoreIcon sx={{ fontSize: 16 }} />}
|
||||
>
|
||||
<Stack direction='row' alignItems='center' gap={1}>
|
||||
<Typography
|
||||
variant='body2'
|
||||
sx={theme => ({
|
||||
fontSize: 12,
|
||||
color: alpha(theme.palette.text.primary, 0.5),
|
||||
})}
|
||||
>
|
||||
已思考
|
||||
</Typography>
|
||||
</Stack>
|
||||
</StyledThinkingAccordionSummary>
|
||||
|
||||
<StyledThinkingAccordionDetails>
|
||||
<MarkDown content={item.thinking_content || ''} />
|
||||
</StyledThinkingAccordionDetails>
|
||||
</StyledThinkingAccordion>
|
||||
)}
|
||||
|
||||
{/* AI回答内容 */}
|
||||
<StyledAiBubbleContent>
|
||||
<MarkDown content={item.assistant} />
|
||||
</StyledAiBubbleContent>
|
||||
</StyledAiBubble>
|
||||
</StyledConversationItem>
|
||||
))}
|
||||
</Stack>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -446,15 +446,19 @@ const Content = () => {
|
|||
>
|
||||
{ragReStartCount} 个文档未学习,
|
||||
</Box>
|
||||
<Button
|
||||
size='small'
|
||||
sx={{ minWidth: 0, p: 0, fontSize: 12 }}
|
||||
<ButtonBase
|
||||
disableRipple
|
||||
sx={{
|
||||
fontSize: 12,
|
||||
fontWeight: 400,
|
||||
color: 'primary.main',
|
||||
}}
|
||||
onClick={() => {
|
||||
setRagOpen(true);
|
||||
}}
|
||||
>
|
||||
去学习
|
||||
</Button>
|
||||
</ButtonBase>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,21 @@ import {
|
|||
AccordionDetails,
|
||||
AccordionSummary,
|
||||
Box,
|
||||
Stack,
|
||||
Typography,
|
||||
alpha,
|
||||
} from '@mui/material';
|
||||
import { Ellipsis, Icon, Modal } from '@ctzhian/ui';
|
||||
import { Ellipsis, Modal } from '@ctzhian/ui';
|
||||
import { useEffect, useState } from 'react';
|
||||
import {
|
||||
StyledConversationItem,
|
||||
StyledUserBubble,
|
||||
StyledAiBubble,
|
||||
StyledThinkingAccordion,
|
||||
StyledThinkingAccordionSummary,
|
||||
StyledThinkingAccordionDetails,
|
||||
StyledAiBubbleContent,
|
||||
} from '../conversation/Detail';
|
||||
|
||||
const Detail = ({
|
||||
id,
|
||||
|
|
@ -36,6 +48,7 @@ const Detail = ({
|
|||
user: data.question,
|
||||
assistant: res.content!,
|
||||
created_at: res.created_at!,
|
||||
thinking_content: '',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -62,24 +75,43 @@ const Detail = ({
|
|||
>
|
||||
<Box sx={{ fontSize: 14 }}>
|
||||
<Box>
|
||||
<Accordion defaultExpanded={true}>
|
||||
<AccordionSummary
|
||||
expandIcon={<ExpandMoreIcon sx={{ fontSize: 24 }} />}
|
||||
sx={{
|
||||
userSelect: 'text',
|
||||
backgroundColor: 'background.paper3',
|
||||
fontSize: '18px',
|
||||
fontWeight: 'bold',
|
||||
}}
|
||||
>
|
||||
{conversations?.user}
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<MarkDown
|
||||
content={conversations?.assistant || '未查询到回答内容'}
|
||||
/>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
<StyledConversationItem>
|
||||
{/* 用户问题气泡 - 右对齐 */}
|
||||
<StyledUserBubble>{conversations?.user}</StyledUserBubble>
|
||||
|
||||
{/* AI回答气泡 - 左对齐 */}
|
||||
<StyledAiBubble>
|
||||
{/* 思考过程 */}
|
||||
{!!conversations?.thinking_content && (
|
||||
<StyledThinkingAccordion defaultExpanded>
|
||||
<StyledThinkingAccordionSummary
|
||||
expandIcon={<ExpandMoreIcon sx={{ fontSize: 16 }} />}
|
||||
>
|
||||
<Stack direction='row' alignItems='center' gap={1}>
|
||||
<Typography
|
||||
variant='body2'
|
||||
sx={theme => ({
|
||||
fontSize: 12,
|
||||
color: alpha(theme.palette.text.primary, 0.5),
|
||||
})}
|
||||
>
|
||||
已思考
|
||||
</Typography>
|
||||
</Stack>
|
||||
</StyledThinkingAccordionSummary>
|
||||
|
||||
<StyledThinkingAccordionDetails>
|
||||
<MarkDown content={conversations?.thinking_content || ''} />
|
||||
</StyledThinkingAccordionDetails>
|
||||
</StyledThinkingAccordion>
|
||||
)}
|
||||
|
||||
{/* AI回答内容 */}
|
||||
<StyledAiBubbleContent>
|
||||
<MarkDown content={conversations?.assistant || ''} />
|
||||
</StyledAiBubbleContent>
|
||||
</StyledAiBubble>
|
||||
</StyledConversationItem>
|
||||
</Box>
|
||||
</Box>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ const AddRole = ({ open, onCancel, onOk, selectedIds }: AddRoleProps) => {
|
|||
MenuProps={{
|
||||
sx: {
|
||||
'.Mui-disabled': {
|
||||
opacity: 1,
|
||||
opacity: '1 !important',
|
||||
color: 'text.disabled',
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -873,7 +873,7 @@ const CardAuth = ({ kb, refresh }: CardAuthProps) => {
|
|||
MenuProps={{
|
||||
sx: {
|
||||
'.Mui-disabled': {
|
||||
opacity: 1,
|
||||
opacity: '1 !important',
|
||||
color: 'text.disabled',
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM node:20-alpine
|
||||
FROM node:22-alpine
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ export default isDevelopment
|
|||
|
||||
// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
|
||||
// This can increase your server load as well as your hosting bill.
|
||||
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
|
||||
// Note: Check that the configured route will not match with your Next.js proxy, otherwise reporting of client-
|
||||
// side errors will fail.
|
||||
tunnelRoute: '/monitoring',
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"version": "2.9.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack -p 3010",
|
||||
"dev": "next dev -p 3010",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
"@emoji-mart/data": "^1.2.1",
|
||||
"@emoji-mart/react": "^1.1.1",
|
||||
"@emotion/cache": "^11.14.0",
|
||||
"@mui/material-nextjs": "^7.1.0",
|
||||
"@mui/material-nextjs": "^7.3.5",
|
||||
"@sentry/nextjs": "^10.8.0",
|
||||
"@types/markdown-it": "13.0.1",
|
||||
"@vscode/markdown-it-katex": "^1.1.2",
|
||||
|
|
@ -25,12 +25,13 @@
|
|||
"highlight.js": "^11.11.1",
|
||||
"html-react-parser": "^5.2.5",
|
||||
"html-to-image": "^1.11.13",
|
||||
"import-in-the-middle": "^1.4.0",
|
||||
"js-cookie": "^3.0.5",
|
||||
"katex": "^0.16.22",
|
||||
"markdown-it": "13.0.1",
|
||||
"markdown-it-highlightjs": "^4.2.0",
|
||||
"mermaid": "^11.9.0",
|
||||
"next": "15.4.6",
|
||||
"next": "^16.0.0",
|
||||
"react-device-detect": "^2.2.3",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-photo-view": "^1.2.7",
|
||||
|
|
@ -41,17 +42,23 @@
|
|||
"remark-breaks": "^4.0.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"remark-math": "^6.0.0",
|
||||
"require-in-the-middle": "^7.5.2",
|
||||
"uuid": "^11.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ctzhian/cx-swagger-api": "^1.0.0",
|
||||
"@eslint/eslintrc": "^3",
|
||||
"@next/eslint-plugin-next": "^15.4.5",
|
||||
"@next/eslint-plugin-next": "^16.0.0",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/rangy": "^1.3.0",
|
||||
"@types/react-syntax-highlighter": "^15.5.13",
|
||||
"eslint-config-next": "15.3.2",
|
||||
"eslint-config-next": "16.0.0",
|
||||
"eslint-config-prettier": "^9.1.2"
|
||||
},
|
||||
"packageManager": "pnpm@10.12.1+sha512.f0dda8580f0ee9481c5c79a1d927b9164f2c478e90992ad268bbb2465a736984391d6333d2c327913578b2804af33474ca554ba29c04a8b13060a717675ae3ac"
|
||||
"packageManager": "pnpm@10.12.1+sha512.f0dda8580f0ee9481c5c79a1d927b9164f2c478e90992ad268bbb2465a736984391d6333d2c327913578b2804af33474ca554ba29c04a8b13060a717675ae3ac",
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"require-in-the-middle": "^7.5.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { ThemeStoreProvider } from '@/provider/themeStore';
|
|||
import { getShareV1AppWebInfo } from '@/request/ShareApp';
|
||||
import { getShareProV1AuthInfo } from '@/request/pro/ShareAuth';
|
||||
import { Box } from '@mui/material';
|
||||
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
|
||||
import { AppRouterCacheProvider } from '@mui/material-nextjs/v16-appRouter';
|
||||
import type { Metadata, Viewport } from 'next';
|
||||
import localFont from 'next/font/local';
|
||||
import { headers, cookies } from 'next/headers';
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
--color-primary-main: #6e73fe;
|
||||
|
||||
/* 代码块颜色 */
|
||||
--code-bg: #ffffff;
|
||||
--code-bg: rgba(0, 0, 0, 0.03);
|
||||
--code-color: #21222d;
|
||||
--inline-code-bg: #fff5f5;
|
||||
--inline-code-color: #ff502c;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
'use client';
|
||||
|
||||
import Logo from '@/assets/images/logo.png';
|
||||
import { Box } from '@mui/material';
|
||||
import { Stack, Box, IconButton, alpha, Tooltip } from '@mui/material';
|
||||
import { postShareProV1AuthLogout } from '@/request/pro/ShareAuth';
|
||||
import { IconDengchu } from '@panda-wiki/icons';
|
||||
import { useStore } from '@/provider';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useMemo } from 'react';
|
||||
import { Modal } from '@ctzhian/ui';
|
||||
import {
|
||||
Header as CustomHeader,
|
||||
WelcomeHeader as WelcomeHeaderComponent,
|
||||
|
|
@ -16,8 +19,42 @@ interface HeaderProps {
|
|||
isWelcomePage?: boolean;
|
||||
}
|
||||
|
||||
const LogoutButton = () => {
|
||||
const handleLogout = () => {
|
||||
Modal.confirm({
|
||||
title: '退出登录',
|
||||
content: '确定要退出登录吗?',
|
||||
onOk: () => {
|
||||
postShareProV1AuthLogout().then(() => {
|
||||
window.location.href = '/auth/login';
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
return (
|
||||
<Tooltip title='退出登录' arrow>
|
||||
<IconButton size='small' onClick={handleLogout}>
|
||||
<IconDengchu
|
||||
sx={theme => ({
|
||||
cursor: 'pointer',
|
||||
color: alpha(theme.palette.text.primary, 0.65),
|
||||
fontSize: 24,
|
||||
'&:hover': { color: theme.palette.primary.main },
|
||||
})}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
const Header = ({ isDocPage = false, isWelcomePage = false }: HeaderProps) => {
|
||||
const { mobile = false, kbDetail, catalogWidth, setQaModalOpen } = useStore();
|
||||
const {
|
||||
mobile = false,
|
||||
kbDetail,
|
||||
catalogWidth,
|
||||
setQaModalOpen,
|
||||
authInfo,
|
||||
} = useStore();
|
||||
const pathname = usePathname();
|
||||
const docWidth = useMemo(() => {
|
||||
if (isWelcomePage) return 'full';
|
||||
|
|
@ -55,16 +92,23 @@ const Header = ({ isDocPage = false, isWelcomePage = false }: HeaderProps) => {
|
|||
onSearch={handleSearch}
|
||||
onQaClick={() => setQaModalOpen?.(true)}
|
||||
>
|
||||
<Box sx={{ ml: 2 }}>
|
||||
<Stack sx={{ ml: 2 }} direction='row' alignItems='center' gap={1}>
|
||||
<ThemeSwitch />
|
||||
</Box>
|
||||
{!!authInfo && <LogoutButton />}
|
||||
</Stack>
|
||||
<QaModal />
|
||||
</CustomHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export const WelcomeHeader = () => {
|
||||
const { mobile = false, kbDetail, catalogWidth, setQaModalOpen } = useStore();
|
||||
const {
|
||||
mobile = false,
|
||||
kbDetail,
|
||||
catalogWidth,
|
||||
setQaModalOpen,
|
||||
authInfo,
|
||||
} = useStore();
|
||||
const handleSearch = (value?: string, type: 'chat' | 'search' = 'chat') => {
|
||||
if (value?.trim()) {
|
||||
if (type === 'chat') {
|
||||
|
|
@ -91,6 +135,7 @@ export const WelcomeHeader = () => {
|
|||
onSearch={handleSearch}
|
||||
onQaClick={() => setQaModalOpen?.(true)}
|
||||
>
|
||||
<Box sx={{ ml: 2 }}>{!!authInfo && <LogoutButton />}</Box>
|
||||
<QaModal />
|
||||
</WelcomeHeaderComponent>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ import React, { useState, useEffect } from 'react';
|
|||
import { createRoot } from 'react-dom/client';
|
||||
import { styled, SvgIcon, SvgIconProps } from '@mui/material';
|
||||
|
||||
// ==================== 图片数据缓存 ====================
|
||||
// 全局图片 blob URL 缓存,避免重复请求 OSS
|
||||
const imageBlobCache = new Map<string, string>();
|
||||
|
||||
// ==================== 图片数据缓存工具函数 ====================
|
||||
// 下载图片并转换为 blob URL
|
||||
const fetchImageAsBlob = async (src: string): Promise<string> => {
|
||||
const fetchImageAsBlob = async (
|
||||
src: string,
|
||||
imageBlobCache: Map<string, string>,
|
||||
): Promise<string> => {
|
||||
// 检查缓存
|
||||
if (imageBlobCache.has(src)) {
|
||||
return imageBlobCache.get(src)!;
|
||||
|
|
@ -39,12 +39,8 @@ const fetchImageAsBlob = async (src: string): Promise<string> => {
|
|||
}
|
||||
};
|
||||
|
||||
// 导出获取图片 blob URL 的函数
|
||||
export const getImageBlobUrl = (src: string): string | null => {
|
||||
return imageBlobCache.get(src) || null;
|
||||
};
|
||||
|
||||
export const clearImageBlobCache = () => {
|
||||
// 清理图片 blob 缓存
|
||||
export const clearImageBlobCache = (imageBlobCache: Map<string, string>) => {
|
||||
imageBlobCache.forEach(url => {
|
||||
URL.revokeObjectURL(url);
|
||||
});
|
||||
|
|
@ -54,7 +50,7 @@ export const clearImageBlobCache = () => {
|
|||
const StyledErrorContainer = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: theme.spacing(2),
|
||||
padding: theme.spacing(1, 6),
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
gap: '8px',
|
||||
|
|
@ -71,7 +67,7 @@ const StyledErrorContainer = styled('div')(({ theme }) => ({
|
|||
|
||||
const StyledErrorText = styled('div')(() => ({
|
||||
fontSize: '12px',
|
||||
marginBottom: 16,
|
||||
marginBottom: 10,
|
||||
}));
|
||||
|
||||
export const ImageErrorIcon = (props: SvgIconProps) => {
|
||||
|
|
@ -102,7 +98,7 @@ export const ImageErrorIcon = (props: SvgIconProps) => {
|
|||
const ImageErrorDisplay: React.FC = () => (
|
||||
<StyledErrorContainer>
|
||||
<ImageErrorIcon
|
||||
sx={{ color: 'var(--mui-palette-text-tertiary)', fontSize: 160 }}
|
||||
sx={{ color: 'var(--mui-palette-text-tertiary)', fontSize: 140 }}
|
||||
/>
|
||||
<StyledErrorText>图片加载失败</StyledErrorText>
|
||||
</StyledErrorContainer>
|
||||
|
|
@ -116,7 +112,7 @@ interface ImageComponentProps {
|
|||
imageIndex: number;
|
||||
onLoad: (index: number, html: string) => void;
|
||||
onError: (index: number, html: string) => void;
|
||||
onImageClick: (src: string) => void;
|
||||
imageBlobCache: Map<string, string>;
|
||||
}
|
||||
|
||||
// ==================== 图片组件 ====================
|
||||
|
|
@ -127,7 +123,7 @@ const ImageComponent: React.FC<ImageComponentProps> = ({
|
|||
imageIndex,
|
||||
onLoad,
|
||||
onError,
|
||||
onImageClick,
|
||||
imageBlobCache,
|
||||
}) => {
|
||||
const [status, setStatus] = useState<'loading' | 'success' | 'error'>(
|
||||
'loading',
|
||||
|
|
@ -149,7 +145,7 @@ const ImageComponent: React.FC<ImageComponentProps> = ({
|
|||
// 获取图片 blob URL
|
||||
useEffect(() => {
|
||||
let mounted = true;
|
||||
fetchImageAsBlob(src)
|
||||
fetchImageAsBlob(src, imageBlobCache)
|
||||
.then(url => {
|
||||
if (mounted) {
|
||||
setBlobUrl(url);
|
||||
|
|
@ -166,7 +162,7 @@ const ImageComponent: React.FC<ImageComponentProps> = ({
|
|||
return () => {
|
||||
mounted = false;
|
||||
};
|
||||
}, [src]);
|
||||
}, [src, imageBlobCache]);
|
||||
|
||||
// 解析自定义样式
|
||||
const parseStyleString = (styleStr: string) => {
|
||||
|
|
@ -238,7 +234,8 @@ const ImageComponent: React.FC<ImageComponentProps> = ({
|
|||
referrerPolicy='no-referrer'
|
||||
onLoad={handleLoad}
|
||||
onError={handleError}
|
||||
onClick={() => onImageClick(src)} // 传递原始 src 用于预览
|
||||
data-original-src={src}
|
||||
className='markdown-image'
|
||||
{...getOtherProps()}
|
||||
/>
|
||||
) : (
|
||||
|
|
@ -264,12 +261,13 @@ const ImageComponent: React.FC<ImageComponentProps> = ({
|
|||
export interface ImageRendererOptions {
|
||||
onImageLoad: (index: number, html: string) => void;
|
||||
onImageError: (index: number, html: string) => void;
|
||||
onImageClick: (src: string) => void;
|
||||
imageRenderCache: Map<number, string>;
|
||||
imageBlobCache: Map<string, string>;
|
||||
}
|
||||
|
||||
export const createImageRenderer = (options: ImageRendererOptions) => {
|
||||
const { onImageLoad, onImageError, imageRenderCache, onImageClick } = options;
|
||||
const { onImageLoad, onImageError, imageRenderCache, imageBlobCache } =
|
||||
options;
|
||||
return (
|
||||
src: string,
|
||||
alt: string,
|
||||
|
|
@ -279,29 +277,6 @@ export const createImageRenderer = (options: ImageRendererOptions) => {
|
|||
// 检查缓存
|
||||
const cached = imageRenderCache.get(imageIndex);
|
||||
if (cached) {
|
||||
// 下一帧对已缓存的DOM绑定原生点击事件,避免事件丢失且不引起重渲染
|
||||
requestAnimationFrame(() => {
|
||||
const container = document.querySelector(
|
||||
`.image-container-${imageIndex}`,
|
||||
) as HTMLElement | null;
|
||||
if (!container) return;
|
||||
const img = container.querySelector('img') as HTMLImageElement | null;
|
||||
if (!img) return;
|
||||
const alreadyBound = (img as HTMLElement).getAttribute(
|
||||
'data-click-bound',
|
||||
);
|
||||
if (!alreadyBound) {
|
||||
(img as HTMLElement).setAttribute('data-click-bound', '1');
|
||||
img.style.cursor = img.style.cursor || 'pointer';
|
||||
img.addEventListener('click', () => {
|
||||
try {
|
||||
onImageClick(img.src);
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return cached;
|
||||
}
|
||||
|
||||
|
|
@ -323,7 +298,7 @@ export const createImageRenderer = (options: ImageRendererOptions) => {
|
|||
imageIndex={imageIndex}
|
||||
onLoad={onImageLoad}
|
||||
onError={onImageError}
|
||||
onImageClick={onImageClick}
|
||||
imageBlobCache={imageBlobCache}
|
||||
/>,
|
||||
);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -15,11 +15,7 @@ import React, {
|
|||
useState,
|
||||
} from 'react';
|
||||
import { useSmartScroll } from '@/hooks';
|
||||
import {
|
||||
clearImageBlobCache,
|
||||
createImageRenderer,
|
||||
getImageBlobUrl,
|
||||
} from './imageRenderer';
|
||||
import { clearImageBlobCache, createImageRenderer } from './imageRenderer';
|
||||
import { incrementalRender } from './incrementalRenderer';
|
||||
import { createMermaidRenderer } from './mermaidRenderer';
|
||||
import {
|
||||
|
|
@ -88,7 +84,8 @@ const MarkDown2: React.FC<MarkDown2Props> = ({
|
|||
const lastContentRef = useRef<string>('');
|
||||
const mdRef = useRef<MarkdownIt | null>(null);
|
||||
const mermaidSuccessIdRef = useRef<Map<number, string>>(new Map());
|
||||
const imageRenderCacheRef = useRef<Map<number, string>>(new Map()); // 图片渲染缓存
|
||||
const imageRenderCacheRef = useRef<Map<number, string>>(new Map()); // 图片渲染缓存(HTML)
|
||||
const imageBlobCacheRef = useRef<Map<string, string>>(new Map()); // 图片 blob URL 缓存
|
||||
|
||||
// 使用智能滚动 hook
|
||||
const { scrollToBottom } = useSmartScroll({
|
||||
|
|
@ -125,13 +122,8 @@ const MarkDown2: React.FC<MarkDown2Props> = ({
|
|||
createImageRenderer({
|
||||
onImageLoad: handleImageLoad,
|
||||
onImageError: handleImageError,
|
||||
onImageClick: (src: string) => {
|
||||
// 尝试获取缓存的 blob URL,如果不存在则使用原始 src
|
||||
const blobUrl = getImageBlobUrl(src);
|
||||
setPreviewImgBlobUrl(blobUrl || src);
|
||||
setPreviewOpen(true);
|
||||
},
|
||||
imageRenderCache: imageRenderCacheRef.current,
|
||||
imageBlobCache: imageBlobCacheRef.current,
|
||||
}),
|
||||
[handleImageLoad, handleImageError],
|
||||
);
|
||||
|
|
@ -158,6 +150,7 @@ const MarkDown2: React.FC<MarkDown2Props> = ({
|
|||
const originalFenceRender = md.renderer.rules.fence;
|
||||
// 自定义图片渲染
|
||||
let imageCount = 0;
|
||||
let htmlImageCount = 0; // HTML 标签图片计数
|
||||
let mermaidCount = 0;
|
||||
md.renderer.rules.image = (tokens, idx) => {
|
||||
imageCount++;
|
||||
|
|
@ -240,6 +233,38 @@ const MarkDown2: React.FC<MarkDown2Props> = ({
|
|||
);
|
||||
};
|
||||
|
||||
// 解析 HTML img 标签并提取属性
|
||||
const parseImgTag = (
|
||||
html: string,
|
||||
): {
|
||||
src: string;
|
||||
alt: string;
|
||||
attrs: [string, string][];
|
||||
} | null => {
|
||||
// 匹配 <img> 标签(支持自闭合和普通标签)
|
||||
const imgMatch = html.match(/<img\s+([^>]*?)\/?>/i);
|
||||
if (!imgMatch) return null;
|
||||
|
||||
const attrsString = imgMatch[1];
|
||||
const attrs: [string, string][] = [];
|
||||
let src = '';
|
||||
let alt = '';
|
||||
|
||||
// 解析属性:匹配 name="value" 或 name='value' 或 name=value
|
||||
const attrRegex =
|
||||
/(\w+)(?:=["']([^"']*)["']|=(?:["'])?([^\s>]+)(?:["'])?)?/g;
|
||||
let attrMatch;
|
||||
while ((attrMatch = attrRegex.exec(attrsString)) !== null) {
|
||||
const name = attrMatch[1].toLowerCase();
|
||||
const value = attrMatch[2] || attrMatch[3] || '';
|
||||
attrs.push([name, value]);
|
||||
if (name === 'src') src = value;
|
||||
if (name === 'alt') alt = value;
|
||||
}
|
||||
|
||||
return { src, alt, attrs };
|
||||
};
|
||||
|
||||
md.renderer.rules.html_block = (
|
||||
tokens,
|
||||
idx,
|
||||
|
|
@ -278,6 +303,21 @@ const MarkDown2: React.FC<MarkDown2Props> = ({
|
|||
if (content.includes('<error>')) return '<span class="chat-error">';
|
||||
if (content.includes('</error>')) return '</span>';
|
||||
|
||||
// 处理 img 标签
|
||||
if (content.includes('<img')) {
|
||||
const imgData = parseImgTag(content);
|
||||
if (imgData && imgData.src) {
|
||||
const imageIndex = imageCount + htmlImageCount;
|
||||
htmlImageCount++;
|
||||
return renderImage(
|
||||
imgData.src,
|
||||
imgData.alt,
|
||||
imgData.attrs,
|
||||
imageIndex,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 🔒 安全检查:不在白名单的标签,转义输出
|
||||
if (!isAllowedTag(content)) {
|
||||
return md.utils.escapeHtml(content);
|
||||
|
|
@ -301,6 +341,21 @@ const MarkDown2: React.FC<MarkDown2Props> = ({
|
|||
if (content.includes('<error>')) return '<span class="chat-error">';
|
||||
if (content.includes('</error>')) return '</span>';
|
||||
|
||||
// 处理 img 标签
|
||||
if (content.includes('<img')) {
|
||||
const imgData = parseImgTag(content);
|
||||
if (imgData && imgData.src) {
|
||||
const imageIndex = imageCount + htmlImageCount;
|
||||
htmlImageCount++;
|
||||
return renderImage(
|
||||
imgData.src,
|
||||
imgData.alt,
|
||||
imgData.attrs,
|
||||
imageIndex,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 🔒 安全检查:不在白名单的标签,转义输出
|
||||
if (!isAllowedTag(content)) {
|
||||
return md.utils.escapeHtml(content);
|
||||
|
|
@ -352,7 +407,7 @@ const MarkDown2: React.FC<MarkDown2Props> = ({
|
|||
}
|
||||
}, [content, customizeRenderer, scrollToBottom]);
|
||||
|
||||
// 添加代码块点击复制功能
|
||||
// 添加代码块点击复制和图片点击预览功能(事件代理)
|
||||
useEffect(() => {
|
||||
const container = containerRef.current;
|
||||
if (!container) return;
|
||||
|
|
@ -360,6 +415,21 @@ const MarkDown2: React.FC<MarkDown2Props> = ({
|
|||
const handleClick = (e: MouseEvent) => {
|
||||
const target = e.target as HTMLElement;
|
||||
|
||||
// 检查是否点击了图片
|
||||
const imgElement = target.closest(
|
||||
'img.markdown-image',
|
||||
) as HTMLImageElement;
|
||||
if (imgElement) {
|
||||
const originalSrc = imgElement.getAttribute('data-original-src');
|
||||
if (originalSrc) {
|
||||
// 尝试获取缓存的 blob URL,如果不存在则使用原始 src
|
||||
const blobUrl = imageBlobCacheRef.current.get(originalSrc);
|
||||
setPreviewImgBlobUrl(blobUrl || originalSrc);
|
||||
setPreviewOpen(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否点击了代码块
|
||||
const preElement = target.closest('pre.hljs');
|
||||
if (preElement) {
|
||||
|
|
@ -368,6 +438,7 @@ const MarkDown2: React.FC<MarkDown2Props> = ({
|
|||
const code = codeElement.textContent || '';
|
||||
copyText(code.replace(/\n$/, ''));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否点击了行内代码
|
||||
|
|
@ -380,7 +451,7 @@ const MarkDown2: React.FC<MarkDown2Props> = ({
|
|||
container.addEventListener('click', handleClick);
|
||||
|
||||
return () => {
|
||||
clearImageBlobCache();
|
||||
clearImageBlobCache(imageBlobCacheRef.current);
|
||||
container.removeEventListener('click', handleClick);
|
||||
};
|
||||
}, []);
|
||||
|
|
@ -406,6 +477,9 @@ const MarkDown2: React.FC<MarkDown2Props> = ({
|
|||
position: 'relative',
|
||||
display: 'inline-block',
|
||||
},
|
||||
'.markdown-image': {
|
||||
cursor: 'pointer',
|
||||
},
|
||||
'.image-error': {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
import type { NextRequest } from 'next/server';
|
||||
import { NextResponse } from 'next/server';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { getShareV1AppWidgetInfo } from './request/ShareApp';
|
||||
import { middleware as homeMiddleware } from './middleware/home';
|
||||
|
||||
const proxyShare = async (request: NextRequest) => {
|
||||
// 转发到 process.env.TARGET
|
||||
const kb_id = request.headers.get('x-kb-id') || process.env.DEV_KB_ID || '';
|
||||
|
||||
const targetOrigin = process.env.TARGET!;
|
||||
const targetUrl = new URL(
|
||||
request.nextUrl.pathname + request.nextUrl.search,
|
||||
targetOrigin,
|
||||
);
|
||||
// 构造 fetch 选项
|
||||
const fetchHeaders = new Headers(request.headers);
|
||||
fetchHeaders.set('x-kb-id', kb_id);
|
||||
|
||||
const fetchOptions: RequestInit = {
|
||||
method: request.method,
|
||||
headers: fetchHeaders,
|
||||
body: ['GET', 'HEAD'].includes(request.method) ? undefined : request.body,
|
||||
redirect: 'manual',
|
||||
};
|
||||
const proxyRes = await fetch(targetUrl.toString(), fetchOptions);
|
||||
const nextRes = new NextResponse(proxyRes.body, {
|
||||
status: proxyRes.status,
|
||||
headers: proxyRes.headers,
|
||||
statusText: proxyRes.statusText,
|
||||
});
|
||||
return nextRes;
|
||||
};
|
||||
|
||||
export async function middleware(request: NextRequest) {
|
||||
const url = request.nextUrl.clone();
|
||||
const pathname = url.pathname;
|
||||
if (pathname.startsWith('/widget')) {
|
||||
const widgetInfo: any = await getShareV1AppWidgetInfo();
|
||||
if (widgetInfo) {
|
||||
if (!widgetInfo?.settings?.widget_bot_settings?.is_open) {
|
||||
return NextResponse.rewrite(new URL('/not-fount', request.url));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const headers: Record<string, string> = {};
|
||||
for (const [key, value] of request.headers.entries()) {
|
||||
headers[key] = value;
|
||||
}
|
||||
|
||||
let sessionId = request.cookies.get('x-pw-session-id')?.value || '';
|
||||
let needSetSessionId = false;
|
||||
|
||||
if (!sessionId) {
|
||||
sessionId = uuidv4();
|
||||
needSetSessionId = true;
|
||||
}
|
||||
|
||||
let response: NextResponse;
|
||||
|
||||
if (pathname.startsWith('/share/')) {
|
||||
response = await proxyShare(request);
|
||||
} else {
|
||||
response = await homeMiddleware(request, headers, sessionId);
|
||||
}
|
||||
|
||||
if (needSetSessionId) {
|
||||
response.cookies.set('x-pw-session-id', sessionId, {
|
||||
httpOnly: true,
|
||||
maxAge: 60 * 60 * 24 * 365, // 1 年
|
||||
});
|
||||
}
|
||||
if (!pathname.startsWith('/share')) {
|
||||
response.headers.set('x-current-path', pathname);
|
||||
response.headers.set('x-current-search', url.search);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
'/',
|
||||
'/home',
|
||||
'/share/:path*',
|
||||
'/chat/:path*',
|
||||
'/widget',
|
||||
'/welcome',
|
||||
'/auth/login',
|
||||
'/node/:path*',
|
||||
'/node',
|
||||
// '/client/:path*',
|
||||
],
|
||||
};
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
import { parsePathname } from '@/utils';
|
||||
import type { NextRequest } from 'next/server';
|
||||
import { NextResponse } from 'next/server';
|
||||
import { postShareV1StatPage } from '@/request/ShareStat';
|
||||
import { getShareV1NodeList } from '@/request/ShareNode';
|
||||
import { getShareV1AppWebInfo } from '@/request/ShareApp';
|
||||
import { filterEmptyFolders, convertToTree } from '@/utils/drag';
|
||||
import { deepSearchFirstNode } from '@/utils';
|
||||
|
||||
const StatPage = {
|
||||
welcome: 1,
|
||||
node: 2,
|
||||
chat: 3,
|
||||
auth: 4,
|
||||
} as const;
|
||||
|
||||
const getFirstNode = async () => {
|
||||
const nodeListResult: any = await getShareV1NodeList();
|
||||
const tree = filterEmptyFolders(convertToTree(nodeListResult || []));
|
||||
return deepSearchFirstNode(tree);
|
||||
};
|
||||
|
||||
const getHomePath = async () => {
|
||||
const info = await getShareV1AppWebInfo();
|
||||
return info?.settings?.home_page_setting;
|
||||
};
|
||||
|
||||
export async function middleware(
|
||||
request: NextRequest,
|
||||
headers: Record<string, string>,
|
||||
session: string,
|
||||
) {
|
||||
const url = request.nextUrl.clone();
|
||||
const { page, id } = parsePathname(url.pathname);
|
||||
try {
|
||||
// 获取节点列表
|
||||
if (url.pathname === '/') {
|
||||
const homePath = await getHomePath();
|
||||
if (homePath === 'custom') {
|
||||
return NextResponse.rewrite(new URL('/home', request.url));
|
||||
} else {
|
||||
const [firstNode] = await Promise.all([getFirstNode(), getHomePath()]);
|
||||
if (firstNode) {
|
||||
return NextResponse.rewrite(
|
||||
new URL(`/node/${firstNode.id}`, request.url),
|
||||
);
|
||||
}
|
||||
return NextResponse.rewrite(new URL('/node', request.url));
|
||||
}
|
||||
}
|
||||
|
||||
// 页面上报
|
||||
const pages = Object.keys(StatPage);
|
||||
if (pages.includes(page) || pages.includes(id)) {
|
||||
postShareV1StatPage(
|
||||
{
|
||||
scene: StatPage[page as keyof typeof StatPage],
|
||||
node_id: id || '',
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'x-pw-session-id': session,
|
||||
...headers,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
} catch (error) {
|
||||
if (
|
||||
typeof error === 'object' &&
|
||||
error !== null &&
|
||||
'message' in error &&
|
||||
error.message === 'NEXT_REDIRECT'
|
||||
) {
|
||||
return NextResponse.redirect(
|
||||
new URL(
|
||||
`/auth/login?redirect=${encodeURIComponent(url.pathname + url.search)}`,
|
||||
request.url,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
import type { NextRequest } from 'next/server';
|
||||
import { NextResponse } from 'next/server';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { getShareV1AppWidgetInfo } from './request/ShareApp';
|
||||
|
||||
import { parsePathname } from '@/utils';
|
||||
import { postShareV1StatPage } from '@/request/ShareStat';
|
||||
import { getShareV1NodeList } from '@/request/ShareNode';
|
||||
import { getShareV1AppWebInfo } from '@/request/ShareApp';
|
||||
import { filterEmptyFolders, convertToTree } from '@/utils/drag';
|
||||
import { deepSearchFirstNode } from '@/utils';
|
||||
|
||||
const StatPage = {
|
||||
welcome: 1,
|
||||
node: 2,
|
||||
chat: 3,
|
||||
auth: 4,
|
||||
} as const;
|
||||
|
||||
const getFirstNode = async () => {
|
||||
const nodeListResult: any = await getShareV1NodeList();
|
||||
const tree = filterEmptyFolders(convertToTree(nodeListResult || []));
|
||||
return deepSearchFirstNode(tree);
|
||||
};
|
||||
|
||||
const getHomePath = async () => {
|
||||
const info = await getShareV1AppWebInfo();
|
||||
return info?.settings?.home_page_setting;
|
||||
};
|
||||
|
||||
const homeProxy = async (
|
||||
request: NextRequest,
|
||||
headers: Record<string, string>,
|
||||
session: string,
|
||||
) => {
|
||||
const url = request.nextUrl.clone();
|
||||
const { page, id } = parsePathname(url.pathname);
|
||||
try {
|
||||
// 获取节点列表
|
||||
if (url.pathname === '/') {
|
||||
const homePath = await getHomePath();
|
||||
if (homePath === 'custom') {
|
||||
return NextResponse.rewrite(new URL('/home', request.url));
|
||||
} else {
|
||||
const [firstNode] = await Promise.all([getFirstNode(), getHomePath()]);
|
||||
if (firstNode) {
|
||||
return NextResponse.rewrite(
|
||||
new URL(`/node/${firstNode.id}`, request.url),
|
||||
);
|
||||
}
|
||||
return NextResponse.rewrite(new URL('/node', request.url));
|
||||
}
|
||||
}
|
||||
|
||||
// 页面上报
|
||||
const pages = Object.keys(StatPage);
|
||||
if (pages.includes(page) || pages.includes(id)) {
|
||||
postShareV1StatPage(
|
||||
{
|
||||
scene: StatPage[page as keyof typeof StatPage],
|
||||
node_id: id || '',
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'x-pw-session-id': session,
|
||||
...headers,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
} catch (error) {
|
||||
if (
|
||||
typeof error === 'object' &&
|
||||
error !== null &&
|
||||
'message' in error &&
|
||||
error.message === 'NEXT_REDIRECT'
|
||||
) {
|
||||
return NextResponse.redirect(
|
||||
new URL(
|
||||
`/auth/login?redirect=${encodeURIComponent(url.pathname + url.search)}`,
|
||||
request.url,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
};
|
||||
|
||||
const proxyShare = async (request: NextRequest) => {
|
||||
// 转发到 process.env.TARGET
|
||||
const kb_id = request.headers.get('x-kb-id') || process.env.DEV_KB_ID || '';
|
||||
|
||||
const targetOrigin = process.env.TARGET!;
|
||||
const targetUrl = new URL(
|
||||
request.nextUrl.pathname + request.nextUrl.search,
|
||||
targetOrigin,
|
||||
);
|
||||
// 构造 fetch 选项
|
||||
const fetchHeaders = new Headers(request.headers);
|
||||
fetchHeaders.set('x-kb-id', kb_id);
|
||||
|
||||
const hasBody = !['GET', 'HEAD'].includes(request.method);
|
||||
const fetchOptions: RequestInit = {
|
||||
method: request.method,
|
||||
headers: fetchHeaders,
|
||||
body: hasBody ? request.body : undefined,
|
||||
redirect: 'manual',
|
||||
...(hasBody && { duplex: 'half' as const }),
|
||||
};
|
||||
const proxyRes = await fetch(targetUrl.toString(), fetchOptions);
|
||||
const nextRes = new NextResponse(proxyRes.body, {
|
||||
status: proxyRes.status,
|
||||
headers: proxyRes.headers,
|
||||
statusText: proxyRes.statusText,
|
||||
});
|
||||
return nextRes;
|
||||
};
|
||||
|
||||
export async function proxy(request: NextRequest) {
|
||||
const url = request.nextUrl.clone();
|
||||
const pathname = url.pathname;
|
||||
if (pathname.startsWith('/widget')) {
|
||||
const widgetInfo: any = await getShareV1AppWidgetInfo();
|
||||
if (widgetInfo) {
|
||||
if (!widgetInfo?.settings?.widget_bot_settings?.is_open) {
|
||||
return NextResponse.rewrite(new URL('/not-fount', request.url));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const headers: Record<string, string> = {};
|
||||
for (const [key, value] of request.headers.entries()) {
|
||||
headers[key] = value;
|
||||
}
|
||||
|
||||
let sessionId = request.cookies.get('x-pw-session-id')?.value || '';
|
||||
let needSetSessionId = false;
|
||||
|
||||
if (!sessionId) {
|
||||
sessionId = uuidv4();
|
||||
needSetSessionId = true;
|
||||
}
|
||||
|
||||
let response: NextResponse;
|
||||
|
||||
if (pathname.startsWith('/share/')) {
|
||||
response = await proxyShare(request);
|
||||
} else {
|
||||
response = await homeProxy(request, headers, sessionId);
|
||||
}
|
||||
|
||||
if (needSetSessionId) {
|
||||
response.cookies.set('x-pw-session-id', sessionId, {
|
||||
httpOnly: true,
|
||||
maxAge: 60 * 60 * 24 * 365, // 1 年
|
||||
});
|
||||
}
|
||||
if (!pathname.startsWith('/share')) {
|
||||
response.headers.set('x-current-path', pathname);
|
||||
response.headers.set('x-current-search', url.search);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
'/',
|
||||
'/home',
|
||||
'/share/:path*',
|
||||
'/chat/:path*',
|
||||
'/widget',
|
||||
'/welcome',
|
||||
'/auth/login',
|
||||
'/node/:path*',
|
||||
'/node',
|
||||
],
|
||||
};
|
||||
|
|
@ -24,6 +24,7 @@ import {
|
|||
GithubComChaitinPandaWikiProApiShareV1AuthInfoResp,
|
||||
GithubComChaitinPandaWikiProApiShareV1AuthLDAPReq,
|
||||
GithubComChaitinPandaWikiProApiShareV1AuthLDAPResp,
|
||||
GithubComChaitinPandaWikiProApiShareV1AuthLogoutResp,
|
||||
GithubComChaitinPandaWikiProApiShareV1AuthOAuthReq,
|
||||
GithubComChaitinPandaWikiProApiShareV1AuthOAuthResp,
|
||||
GithubComChaitinPandaWikiProApiShareV1AuthWecomReq,
|
||||
|
|
@ -206,6 +207,32 @@ export const postShareProV1AuthLdap = (
|
|||
...params,
|
||||
});
|
||||
|
||||
/**
|
||||
* @description 用户登出
|
||||
*
|
||||
* @tags ShareAuth
|
||||
* @name PostShareProV1AuthLogout
|
||||
* @summary 用户登出
|
||||
* @request POST:/share/pro/v1/auth/logout
|
||||
* @response `200` `(DomainPWResponse & {
|
||||
data?: GithubComChaitinPandaWikiProApiShareV1AuthLogoutResp,
|
||||
|
||||
})` OK
|
||||
*/
|
||||
|
||||
export const postShareProV1AuthLogout = (params: RequestParams = {}) =>
|
||||
httpRequest<
|
||||
DomainPWResponse & {
|
||||
data?: GithubComChaitinPandaWikiProApiShareV1AuthLogoutResp;
|
||||
}
|
||||
>({
|
||||
path: `/share/pro/v1/auth/logout`,
|
||||
method: "POST",
|
||||
type: ContentType.Json,
|
||||
format: "json",
|
||||
...params,
|
||||
});
|
||||
|
||||
/**
|
||||
* @description OAuth登录
|
||||
*
|
||||
|
|
|
|||
|
|
@ -52,10 +52,12 @@ export enum ConstsSourceType {
|
|||
export enum ConstsLicenseEdition {
|
||||
/** 开源版 */
|
||||
LicenseEditionFree = 0,
|
||||
/** 联创版 */
|
||||
LicenseEditionContributor = 1,
|
||||
/** 专业版 */
|
||||
LicenseEditionProfession = 1,
|
||||
/** 企业版 */
|
||||
LicenseEditionEnterprise = 2,
|
||||
/** 商业版 */
|
||||
LicenseEditionBusiness = 3,
|
||||
}
|
||||
|
||||
export enum ConstsContributeType {
|
||||
|
|
@ -455,6 +457,11 @@ export type GithubComChaitinPandaWikiProApiShareV1AuthLDAPResp = Record<
|
|||
any
|
||||
>;
|
||||
|
||||
export type GithubComChaitinPandaWikiProApiShareV1AuthLogoutResp = Record<
|
||||
string,
|
||||
any
|
||||
>;
|
||||
|
||||
export interface GithubComChaitinPandaWikiProApiShareV1AuthOAuthReq {
|
||||
kb_id?: string;
|
||||
redirect_url?: string;
|
||||
|
|
@ -669,8 +676,6 @@ export interface GetApiProV1TokenListParams {
|
|||
}
|
||||
|
||||
export interface PostApiV1LicensePayload {
|
||||
/** license edition */
|
||||
license_edition: "contributor" | "enterprise";
|
||||
/** license type */
|
||||
license_type: "file" | "code";
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -171,14 +171,21 @@ export enum ConstsNodeAccessPerm {
|
|||
NodeAccessPermClosed = "closed",
|
||||
}
|
||||
|
||||
export enum ConstsModelSettingMode {
|
||||
ModelSettingModeManual = "manual",
|
||||
ModelSettingModeAuto = "auto",
|
||||
}
|
||||
|
||||
/** @format int32 */
|
||||
export enum ConstsLicenseEdition {
|
||||
/** 开源版 */
|
||||
LicenseEditionFree = 0,
|
||||
/** 联创版 */
|
||||
LicenseEditionContributor = 1,
|
||||
/** 专业版 */
|
||||
LicenseEditionProfession = 1,
|
||||
/** 企业版 */
|
||||
LicenseEditionEnterprise = 2,
|
||||
/** 商业版 */
|
||||
LicenseEditionBusiness = 3,
|
||||
}
|
||||
|
||||
export enum ConstsHomePageSetting {
|
||||
|
|
@ -922,6 +929,17 @@ export interface DomainMetricsConfig {
|
|||
type?: string;
|
||||
}
|
||||
|
||||
export interface DomainModelModeSetting {
|
||||
/** 百智云 API Key */
|
||||
auto_mode_api_key?: string;
|
||||
/** 自定义对话模型名称 */
|
||||
chat_model?: string;
|
||||
/** 手动模式下嵌入模型是否更新 */
|
||||
is_manual_embedding_updated?: boolean;
|
||||
/** 模式: manual 或 auto */
|
||||
mode?: ConstsModelSettingMode;
|
||||
}
|
||||
|
||||
export interface DomainMoveNodeReq {
|
||||
id: string;
|
||||
kb_id: string;
|
||||
|
|
@ -1195,6 +1213,18 @@ export interface DomainStatPageReq {
|
|||
scene: 1 | 2 | 3 | 4;
|
||||
}
|
||||
|
||||
export interface DomainSwitchModeReq {
|
||||
/** 百智云 API Key */
|
||||
auto_mode_api_key?: string;
|
||||
/** 自定义对话模型名称 */
|
||||
chat_model?: string;
|
||||
mode: "manual" | "auto";
|
||||
}
|
||||
|
||||
export interface DomainSwitchModeResp {
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export interface DomainTextConfig {
|
||||
title?: string;
|
||||
type?: string;
|
||||
|
|
@ -1336,11 +1366,18 @@ export interface DomainWecomAIBotSettings {
|
|||
}
|
||||
|
||||
export interface DomainWidgetBotSettings {
|
||||
btn_id?: string;
|
||||
btn_logo?: string;
|
||||
btn_position?: string;
|
||||
btn_style?: string;
|
||||
btn_text?: string;
|
||||
disclaimer?: string;
|
||||
is_open?: boolean;
|
||||
modal_position?: string;
|
||||
placeholder?: string;
|
||||
recommend_node_ids?: string[];
|
||||
recommend_questions?: string[];
|
||||
search_mode?: string;
|
||||
theme_mode?: string;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ const DocContent = ({
|
|||
setCommentImages([]);
|
||||
message.success(
|
||||
appDetail?.web_app_comment_settings?.moderation_enable
|
||||
? '正在审核中...'
|
||||
? '评论已提交,请耐心等待审核'
|
||||
: '评论成功',
|
||||
);
|
||||
} catch (error: any) {
|
||||
|
|
|
|||
|
|
@ -236,11 +236,11 @@ importers:
|
|||
specifier: ^11.14.0
|
||||
version: 11.14.0
|
||||
'@mui/material-nextjs':
|
||||
specifier: ^7.1.0
|
||||
version: 7.3.3(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(next@15.4.6(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)
|
||||
specifier: ^7.3.5
|
||||
version: 7.3.5(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(next@16.0.3(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)
|
||||
'@sentry/nextjs':
|
||||
specifier: ^10.8.0
|
||||
version: 10.22.0(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(next@15.4.6(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)(webpack@5.102.1)
|
||||
version: 10.22.0(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(next@16.0.3(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)(webpack@5.102.1)
|
||||
'@types/markdown-it':
|
||||
specifier: 13.0.1
|
||||
version: 13.0.1
|
||||
|
|
@ -262,6 +262,9 @@ importers:
|
|||
html-to-image:
|
||||
specifier: ^1.11.13
|
||||
version: 1.11.13
|
||||
import-in-the-middle:
|
||||
specifier: ^1.4.0
|
||||
version: 1.15.0
|
||||
js-cookie:
|
||||
specifier: ^3.0.5
|
||||
version: 3.0.5
|
||||
|
|
@ -278,8 +281,8 @@ importers:
|
|||
specifier: ^11.9.0
|
||||
version: 11.12.1
|
||||
next:
|
||||
specifier: 15.4.6
|
||||
version: 15.4.6(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||
specifier: ^16.0.0
|
||||
version: 16.0.3(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||
react-device-detect:
|
||||
specifier: ^2.2.3
|
||||
version: 2.2.3(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||
|
|
@ -310,6 +313,9 @@ importers:
|
|||
remark-math:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0
|
||||
require-in-the-middle:
|
||||
specifier: ^7.5.2
|
||||
version: 7.5.2
|
||||
uuid:
|
||||
specifier: ^11.1.0
|
||||
version: 11.1.0
|
||||
|
|
@ -321,8 +327,8 @@ importers:
|
|||
specifier: ^3
|
||||
version: 3.3.1
|
||||
'@next/eslint-plugin-next':
|
||||
specifier: ^15.4.5
|
||||
version: 15.5.6
|
||||
specifier: ^16.0.0
|
||||
version: 16.0.3
|
||||
'@types/js-cookie':
|
||||
specifier: ^3.0.6
|
||||
version: 3.0.6
|
||||
|
|
@ -333,8 +339,8 @@ importers:
|
|||
specifier: ^15.5.13
|
||||
version: 15.5.13
|
||||
eslint-config-next:
|
||||
specifier: 15.3.2
|
||||
version: 15.3.2(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
|
||||
specifier: 16.0.0
|
||||
version: 16.0.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
|
||||
eslint-config-prettier:
|
||||
specifier: ^9.1.2
|
||||
version: 9.1.2(eslint@9.39.1(jiti@2.6.1))
|
||||
|
|
@ -915,78 +921,92 @@ packages:
|
|||
resolution: {integrity: sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-arm@1.2.3':
|
||||
resolution: {integrity: sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-ppc64@1.2.3':
|
||||
resolution: {integrity: sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-s390x@1.2.3':
|
||||
resolution: {integrity: sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-x64@1.2.3':
|
||||
resolution: {integrity: sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.2.3':
|
||||
resolution: {integrity: sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.2.3':
|
||||
resolution: {integrity: sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linux-arm64@0.34.4':
|
||||
resolution: {integrity: sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-arm@0.34.4':
|
||||
resolution: {integrity: sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-ppc64@0.34.4':
|
||||
resolution: {integrity: sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-s390x@0.34.4':
|
||||
resolution: {integrity: sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-x64@0.34.4':
|
||||
resolution: {integrity: sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linuxmusl-arm64@0.34.4':
|
||||
resolution: {integrity: sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linuxmusl-x64@0.34.4':
|
||||
resolution: {integrity: sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-wasm32@0.34.4':
|
||||
resolution: {integrity: sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==}
|
||||
|
|
@ -1047,15 +1067,15 @@ packages:
|
|||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@mui/material-nextjs@7.3.3':
|
||||
resolution: {integrity: sha512-SHqEh/GIa/HkHzBMMGvTRCVSLvXYTATZ7QN7/QxngimW5kBDI+pWzjieS8HmLDgo36rxD8g+GcLY6Bu+pilciw==}
|
||||
'@mui/material-nextjs@7.3.5':
|
||||
resolution: {integrity: sha512-WWd8dbygIOnhqTlLiDP7lvKFZyIDTrZ0mClFxmYOYzohxJuYzeuax/yAgOW2lEGxIdoSDiSPqv/4qT8LZ96IVA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
'@emotion/cache': ^11.11.0
|
||||
'@emotion/react': ^11.11.4
|
||||
'@emotion/server': ^11.11.0
|
||||
'@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
next: ^13.0.0 || ^14.0.0 || ^15.0.0
|
||||
next: ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
|
||||
react: ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
peerDependenciesMeta:
|
||||
'@emotion/cache':
|
||||
|
|
@ -1145,59 +1165,63 @@ packages:
|
|||
'@napi-rs/wasm-runtime@0.2.12':
|
||||
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
|
||||
|
||||
'@next/env@15.4.6':
|
||||
resolution: {integrity: sha512-yHDKVTcHrZy/8TWhj0B23ylKv5ypocuCwey9ZqPyv4rPdUdRzpGCkSi03t04KBPyU96kxVtUqx6O3nE1kpxASQ==}
|
||||
'@next/env@16.0.3':
|
||||
resolution: {integrity: sha512-IqgtY5Vwsm14mm/nmQaRMmywCU+yyMIYfk3/MHZ2ZTJvwVbBn3usZnjMi1GacrMVzVcAxJShTCpZlPs26EdEjQ==}
|
||||
|
||||
'@next/eslint-plugin-next@15.3.2':
|
||||
resolution: {integrity: sha512-ijVRTXBgnHT33aWnDtmlG+LJD+5vhc9AKTJPquGG5NKXjpKNjc62woIhFtrAcWdBobt8kqjCoaJ0q6sDQoX7aQ==}
|
||||
'@next/eslint-plugin-next@16.0.0':
|
||||
resolution: {integrity: sha512-IB7RzmmtrPOrpAgEBR1PIQPD0yea5lggh5cq54m51jHjjljU80Ia+czfxJYMlSDl1DPvpzb8S9TalCc0VMo9Hw==}
|
||||
|
||||
'@next/eslint-plugin-next@15.5.6':
|
||||
resolution: {integrity: sha512-YxDvsT2fwy1j5gMqk3ppXlsgDopHnkM4BoxSVASbvvgh5zgsK8lvWerDzPip8k3WVzsTZ1O7A7si1KNfN4OZfQ==}
|
||||
'@next/eslint-plugin-next@16.0.3':
|
||||
resolution: {integrity: sha512-6sPWmZetzFWMsz7Dhuxsdmbu3fK+/AxKRtj7OB0/3OZAI2MHB/v2FeYh271LZ9abvnM1WIwWc/5umYjx0jo5sQ==}
|
||||
|
||||
'@next/swc-darwin-arm64@15.4.6':
|
||||
resolution: {integrity: sha512-667R0RTP4DwxzmrqTs4Lr5dcEda9OxuZsVFsjVtxVMVhzSpo6nLclXejJVfQo2/g7/Z9qF3ETDmN3h65mTjpTQ==}
|
||||
'@next/swc-darwin-arm64@16.0.3':
|
||||
resolution: {integrity: sha512-MOnbd92+OByu0p6QBAzq1ahVWzF6nyfiH07dQDez4/Nku7G249NjxDVyEfVhz8WkLiOEU+KFVnqtgcsfP2nLXg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-darwin-x64@15.4.6':
|
||||
resolution: {integrity: sha512-KMSFoistFkaiQYVQQnaU9MPWtp/3m0kn2Xed1Ces5ll+ag1+rlac20sxG+MqhH2qYWX1O2GFOATQXEyxKiIscg==}
|
||||
'@next/swc-darwin-x64@16.0.3':
|
||||
resolution: {integrity: sha512-i70C4O1VmbTivYdRlk+5lj9xRc2BlK3oUikt3yJeHT1unL4LsNtN7UiOhVanFdc7vDAgZn1tV/9mQwMkWOJvHg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-linux-arm64-gnu@15.4.6':
|
||||
resolution: {integrity: sha512-PnOx1YdO0W7m/HWFeYd2A6JtBO8O8Eb9h6nfJia2Dw1sRHoHpNf6lN1U4GKFRzRDBi9Nq2GrHk9PF3Vmwf7XVw==}
|
||||
'@next/swc-linux-arm64-gnu@16.0.3':
|
||||
resolution: {integrity: sha512-O88gCZ95sScwD00mn/AtalyCoykhhlokxH/wi1huFK+rmiP5LAYVs/i2ruk7xST6SuXN4NI5y4Xf5vepb2jf6A==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@next/swc-linux-arm64-musl@15.4.6':
|
||||
resolution: {integrity: sha512-XBbuQddtY1p5FGPc2naMO0kqs4YYtLYK/8aPausI5lyOjr4J77KTG9mtlU4P3NwkLI1+OjsPzKVvSJdMs3cFaw==}
|
||||
'@next/swc-linux-arm64-musl@16.0.3':
|
||||
resolution: {integrity: sha512-CEErFt78S/zYXzFIiv18iQCbRbLgBluS8z1TNDQoyPi8/Jr5qhR3e8XHAIxVxPBjDbEMITprqELVc5KTfFj0gg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@next/swc-linux-x64-gnu@15.4.6':
|
||||
resolution: {integrity: sha512-+WTeK7Qdw82ez3U9JgD+igBAP75gqZ1vbK6R8PlEEuY0OIe5FuYXA4aTjL811kWPf7hNeslD4hHK2WoM9W0IgA==}
|
||||
'@next/swc-linux-x64-gnu@16.0.3':
|
||||
resolution: {integrity: sha512-Tc3i+nwt6mQ+Dwzcri/WNDj56iWdycGVh5YwwklleClzPzz7UpfaMw1ci7bLl6GRYMXhWDBfe707EXNjKtiswQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@next/swc-linux-x64-musl@15.4.6':
|
||||
resolution: {integrity: sha512-XP824mCbgQsK20jlXKrUpZoh/iO3vUWhMpxCz8oYeagoiZ4V0TQiKy0ASji1KK6IAe3DYGfj5RfKP6+L2020OQ==}
|
||||
'@next/swc-linux-x64-musl@16.0.3':
|
||||
resolution: {integrity: sha512-zTh03Z/5PBBPdTurgEtr6nY0vI9KR9Ifp/jZCcHlODzwVOEKcKRBtQIGrkc7izFgOMuXDEJBmirwpGqdM/ZixA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@next/swc-win32-arm64-msvc@15.4.6':
|
||||
resolution: {integrity: sha512-FxrsenhUz0LbgRkNWx6FRRJIPe/MI1JRA4W4EPd5leXO00AZ6YU8v5vfx4MDXTvN77lM/EqsE3+6d2CIeF5NYg==}
|
||||
'@next/swc-win32-arm64-msvc@16.0.3':
|
||||
resolution: {integrity: sha512-Jc1EHxtZovcJcg5zU43X3tuqzl/sS+CmLgjRP28ZT4vk869Ncm2NoF8qSTaL99gh6uOzgM99Shct06pSO6kA6g==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@next/swc-win32-x64-msvc@15.4.6':
|
||||
resolution: {integrity: sha512-T4ufqnZ4u88ZheczkBTtOF+eKaM14V8kbjud/XrAakoM5DKQWjW09vD6B9fsdsWS2T7D5EY31hRHdta7QKWOng==}
|
||||
'@next/swc-win32-x64-msvc@16.0.3':
|
||||
resolution: {integrity: sha512-N7EJ6zbxgIYpI/sWNzpVKRMbfEGgsWuOIvzkML7wxAAZhPk1Msxuo/JDu1PKjWGrAoOLaZcIX5s+/pF5LIbBBg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
|
@ -1495,56 +1519,67 @@ packages:
|
|||
resolution: {integrity: sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.52.5':
|
||||
resolution: {integrity: sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.52.5':
|
||||
resolution: {integrity: sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.52.5':
|
||||
resolution: {integrity: sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.52.5':
|
||||
resolution: {integrity: sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.52.5':
|
||||
resolution: {integrity: sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.52.5':
|
||||
resolution: {integrity: sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.52.5':
|
||||
resolution: {integrity: sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.52.5':
|
||||
resolution: {integrity: sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.52.5':
|
||||
resolution: {integrity: sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.52.5':
|
||||
resolution: {integrity: sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-openharmony-arm64@4.52.5':
|
||||
resolution: {integrity: sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==}
|
||||
|
|
@ -1574,9 +1609,6 @@ packages:
|
|||
'@rtsao/scc@1.1.0':
|
||||
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
|
||||
|
||||
'@rushstack/eslint-patch@1.14.1':
|
||||
resolution: {integrity: sha512-jGTk8UD/RdjsNZW8qq10r0RBvxL8OWtoT+kImlzPDFilmozzM+9QmIJsmze9UiSBrFU45ZxhTYBypn9q9z/VfQ==}
|
||||
|
||||
'@sentry-internal/browser-utils@10.22.0':
|
||||
resolution: {integrity: sha512-BpJoLZEyJr7ORzkCrIjxRTnFWwO1mJNICVh3B9g5d9245niGT4OJvRozmLz89WgJkZFHWu84ls6Xfq5b/3tGFQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -2378,41 +2410,49 @@ packages:
|
|||
resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@unrs/resolver-binding-linux-arm64-musl@1.11.1':
|
||||
resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
|
||||
resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
|
||||
resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
|
||||
resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
|
||||
resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@unrs/resolver-binding-linux-x64-gnu@1.11.1':
|
||||
resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@unrs/resolver-binding-linux-x64-musl@1.11.1':
|
||||
resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@unrs/resolver-binding-wasm32-wasi@1.11.1':
|
||||
resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
|
||||
|
|
@ -3297,10 +3337,10 @@ packages:
|
|||
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
eslint-config-next@15.3.2:
|
||||
resolution: {integrity: sha512-FerU4DYccO4FgeYFFglz0SnaKRe1ejXQrDb8kWUkTAg036YWi+jUsgg4sIGNCDhAsDITsZaL4MzBWKB6f4G1Dg==}
|
||||
eslint-config-next@16.0.0:
|
||||
resolution: {integrity: sha512-DWKT1YAO9ex2rK0/EeiPpKU++ghTiG59z6m08/ReLRECOYIaEv17maSCYT8zmFQLwIrY5lhJ+iaJPQdT4sJd4g==}
|
||||
peerDependencies:
|
||||
eslint: ^7.23.0 || ^8.0.0 || ^9.0.0
|
||||
eslint: '>=9.0.0'
|
||||
typescript: '>=3.3.1'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
|
|
@ -3371,6 +3411,12 @@ packages:
|
|||
peerDependencies:
|
||||
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
|
||||
|
||||
eslint-plugin-react-hooks@7.0.1:
|
||||
resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
|
||||
|
||||
eslint-plugin-react-refresh@0.4.24:
|
||||
resolution: {integrity: sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==}
|
||||
peerDependencies:
|
||||
|
|
@ -3623,6 +3669,10 @@ packages:
|
|||
resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
globals@16.4.0:
|
||||
resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
globalthis@1.0.4:
|
||||
resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -3719,6 +3769,12 @@ packages:
|
|||
hastscript@9.0.1:
|
||||
resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}
|
||||
|
||||
hermes-estree@0.25.1:
|
||||
resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==}
|
||||
|
||||
hermes-parser@0.25.1:
|
||||
resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
|
||||
|
||||
highlight.js@10.7.3:
|
||||
resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
|
||||
|
||||
|
|
@ -4454,9 +4510,9 @@ packages:
|
|||
neo-async@2.6.2:
|
||||
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
|
||||
|
||||
next@15.4.6:
|
||||
resolution: {integrity: sha512-us++E/Q80/8+UekzB3SAGs71AlLDsadpFMXVNM/uQ0BMwsh9m3mr0UNQIfjKed8vpWXsASe+Qifrnu1oLIcKEQ==}
|
||||
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
|
||||
next@16.0.3:
|
||||
resolution: {integrity: sha512-Ka0/iNBblPFcIubTA1Jjh6gvwqfjrGq1Y2MTI5lbjeLIAfmC+p5bQmojpRZqgHHVu5cG4+qdIiwXiBSm/8lZ3w==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@opentelemetry/api': ^1.1.0
|
||||
|
|
@ -5781,6 +5837,15 @@ packages:
|
|||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
zod-validation-error@4.0.2:
|
||||
resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
peerDependencies:
|
||||
zod: ^3.25.0 || ^4.0.0
|
||||
|
||||
zod@4.1.12:
|
||||
resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==}
|
||||
|
||||
zrender@5.6.1:
|
||||
resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==}
|
||||
|
||||
|
|
@ -6519,11 +6584,11 @@ snapshots:
|
|||
optionalDependencies:
|
||||
'@types/react': 19.2.2
|
||||
|
||||
'@mui/material-nextjs@7.3.3(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(next@15.4.6(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)':
|
||||
'@mui/material-nextjs@7.3.5(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(next@16.0.3(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
'@emotion/react': 11.14.0(@types/react@19.2.2)(react@19.2.0)
|
||||
next: 15.4.6(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||
next: 16.0.3(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||
react: 19.2.0
|
||||
optionalDependencies:
|
||||
'@emotion/cache': 11.14.0
|
||||
|
|
@ -6613,38 +6678,38 @@ snapshots:
|
|||
'@tybys/wasm-util': 0.10.1
|
||||
optional: true
|
||||
|
||||
'@next/env@15.4.6': {}
|
||||
'@next/env@16.0.3': {}
|
||||
|
||||
'@next/eslint-plugin-next@15.3.2':
|
||||
'@next/eslint-plugin-next@16.0.0':
|
||||
dependencies:
|
||||
fast-glob: 3.3.1
|
||||
|
||||
'@next/eslint-plugin-next@15.5.6':
|
||||
'@next/eslint-plugin-next@16.0.3':
|
||||
dependencies:
|
||||
fast-glob: 3.3.1
|
||||
|
||||
'@next/swc-darwin-arm64@15.4.6':
|
||||
'@next/swc-darwin-arm64@16.0.3':
|
||||
optional: true
|
||||
|
||||
'@next/swc-darwin-x64@15.4.6':
|
||||
'@next/swc-darwin-x64@16.0.3':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-gnu@15.4.6':
|
||||
'@next/swc-linux-arm64-gnu@16.0.3':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-musl@15.4.6':
|
||||
'@next/swc-linux-arm64-musl@16.0.3':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-gnu@15.4.6':
|
||||
'@next/swc-linux-x64-gnu@16.0.3':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-musl@15.4.6':
|
||||
'@next/swc-linux-x64-musl@16.0.3':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-arm64-msvc@15.4.6':
|
||||
'@next/swc-win32-arm64-msvc@16.0.3':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-x64-msvc@15.4.6':
|
||||
'@next/swc-win32-x64-msvc@16.0.3':
|
||||
optional: true
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
|
|
@ -7031,8 +7096,6 @@ snapshots:
|
|||
|
||||
'@rtsao/scc@1.1.0': {}
|
||||
|
||||
'@rushstack/eslint-patch@1.14.1': {}
|
||||
|
||||
'@sentry-internal/browser-utils@10.22.0':
|
||||
dependencies:
|
||||
'@sentry/core': 10.22.0
|
||||
|
|
@ -7121,7 +7184,7 @@ snapshots:
|
|||
|
||||
'@sentry/core@10.22.0': {}
|
||||
|
||||
'@sentry/nextjs@10.22.0(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(next@15.4.6(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)(webpack@5.102.1)':
|
||||
'@sentry/nextjs@10.22.0(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(next@16.0.3(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)(webpack@5.102.1)':
|
||||
dependencies:
|
||||
'@opentelemetry/api': 1.9.0
|
||||
'@opentelemetry/semantic-conventions': 1.37.0
|
||||
|
|
@ -7134,7 +7197,7 @@ snapshots:
|
|||
'@sentry/react': 10.22.0(react@19.2.0)
|
||||
'@sentry/vercel-edge': 10.22.0
|
||||
'@sentry/webpack-plugin': 4.6.0(webpack@5.102.1)
|
||||
next: 15.4.6(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||
next: 16.0.3(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
|
||||
resolve: 1.22.8
|
||||
rollup: 4.52.5
|
||||
stacktrace-parser: 0.1.11
|
||||
|
|
@ -9047,22 +9110,22 @@ snapshots:
|
|||
|
||||
escape-string-regexp@5.0.0: {}
|
||||
|
||||
eslint-config-next@15.3.2(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3):
|
||||
eslint-config-next@16.0.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3):
|
||||
dependencies:
|
||||
'@next/eslint-plugin-next': 15.3.2
|
||||
'@rushstack/eslint-patch': 1.14.1
|
||||
'@typescript-eslint/eslint-plugin': 8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
|
||||
'@typescript-eslint/parser': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
|
||||
'@next/eslint-plugin-next': 16.0.0
|
||||
eslint: 9.39.1(jiti@2.6.1)
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1))
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1))
|
||||
eslint-plugin-import: 2.32.0(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1))
|
||||
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.1(jiti@2.6.1))
|
||||
eslint-plugin-react: 7.37.5(eslint@9.39.1(jiti@2.6.1))
|
||||
eslint-plugin-react-hooks: 5.2.0(eslint@9.39.1(jiti@2.6.1))
|
||||
eslint-plugin-react-hooks: 7.0.1(eslint@9.39.1(jiti@2.6.1))
|
||||
globals: 16.4.0
|
||||
typescript-eslint: 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
|
||||
optionalDependencies:
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- '@typescript-eslint/parser'
|
||||
- eslint-import-resolver-webpack
|
||||
- eslint-plugin-import-x
|
||||
- supports-color
|
||||
|
|
@ -9090,22 +9153,21 @@ snapshots:
|
|||
tinyglobby: 0.2.15
|
||||
unrs-resolver: 1.11.1
|
||||
optionalDependencies:
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1))
|
||||
eslint-plugin-import: 2.32.0(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)):
|
||||
eslint-module-utils@2.12.1(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
|
||||
eslint: 9.39.1(jiti@2.6.1)
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)):
|
||||
eslint-plugin-import@2.32.0(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)):
|
||||
dependencies:
|
||||
'@rtsao/scc': 1.1.0
|
||||
array-includes: 3.1.9
|
||||
|
|
@ -9116,7 +9178,7 @@ snapshots:
|
|||
doctrine: 2.1.0
|
||||
eslint: 9.39.1(jiti@2.6.1)
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1))
|
||||
eslint-module-utils: 2.12.1(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1))
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.16.1
|
||||
is-glob: 4.0.3
|
||||
|
|
@ -9127,8 +9189,6 @@ snapshots:
|
|||
semver: 6.3.1
|
||||
string.prototype.trimend: 1.0.9
|
||||
tsconfig-paths: 3.15.0
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
|
|
@ -9157,6 +9217,17 @@ snapshots:
|
|||
dependencies:
|
||||
eslint: 9.39.1(jiti@2.6.1)
|
||||
|
||||
eslint-plugin-react-hooks@7.0.1(eslint@9.39.1(jiti@2.6.1)):
|
||||
dependencies:
|
||||
'@babel/core': 7.28.5
|
||||
'@babel/parser': 7.28.5
|
||||
eslint: 9.39.1(jiti@2.6.1)
|
||||
hermes-parser: 0.25.1
|
||||
zod: 4.1.12
|
||||
zod-validation-error: 4.0.2(zod@4.1.12)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-react-refresh@0.4.24(eslint@9.39.1(jiti@2.6.1)):
|
||||
dependencies:
|
||||
eslint: 9.39.1(jiti@2.6.1)
|
||||
|
|
@ -9444,6 +9515,8 @@ snapshots:
|
|||
|
||||
globals@15.15.0: {}
|
||||
|
||||
globals@16.4.0: {}
|
||||
|
||||
globalthis@1.0.4:
|
||||
dependencies:
|
||||
define-properties: 1.2.1
|
||||
|
|
@ -9609,6 +9682,12 @@ snapshots:
|
|||
property-information: 7.1.0
|
||||
space-separated-tokens: 2.0.2
|
||||
|
||||
hermes-estree@0.25.1: {}
|
||||
|
||||
hermes-parser@0.25.1:
|
||||
dependencies:
|
||||
hermes-estree: 0.25.1
|
||||
|
||||
highlight.js@10.7.3: {}
|
||||
|
||||
highlight.js@11.11.1: {}
|
||||
|
|
@ -10575,9 +10654,9 @@ snapshots:
|
|||
|
||||
neo-async@2.6.2: {}
|
||||
|
||||
next@15.4.6(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0):
|
||||
next@16.0.3(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0):
|
||||
dependencies:
|
||||
'@next/env': 15.4.6
|
||||
'@next/env': 16.0.3
|
||||
'@swc/helpers': 0.5.15
|
||||
caniuse-lite: 1.0.30001753
|
||||
postcss: 8.4.31
|
||||
|
|
@ -10585,14 +10664,14 @@ snapshots:
|
|||
react-dom: 19.2.0(react@19.2.0)
|
||||
styled-jsx: 5.1.6(react@19.2.0)
|
||||
optionalDependencies:
|
||||
'@next/swc-darwin-arm64': 15.4.6
|
||||
'@next/swc-darwin-x64': 15.4.6
|
||||
'@next/swc-linux-arm64-gnu': 15.4.6
|
||||
'@next/swc-linux-arm64-musl': 15.4.6
|
||||
'@next/swc-linux-x64-gnu': 15.4.6
|
||||
'@next/swc-linux-x64-musl': 15.4.6
|
||||
'@next/swc-win32-arm64-msvc': 15.4.6
|
||||
'@next/swc-win32-x64-msvc': 15.4.6
|
||||
'@next/swc-darwin-arm64': 16.0.3
|
||||
'@next/swc-darwin-x64': 16.0.3
|
||||
'@next/swc-linux-arm64-gnu': 16.0.3
|
||||
'@next/swc-linux-arm64-musl': 16.0.3
|
||||
'@next/swc-linux-x64-gnu': 16.0.3
|
||||
'@next/swc-linux-x64-musl': 16.0.3
|
||||
'@next/swc-win32-arm64-msvc': 16.0.3
|
||||
'@next/swc-win32-x64-msvc': 16.0.3
|
||||
'@opentelemetry/api': 1.9.0
|
||||
sharp: 0.34.4
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -12184,6 +12263,12 @@ snapshots:
|
|||
|
||||
yocto-queue@0.1.0: {}
|
||||
|
||||
zod-validation-error@4.0.2(zod@4.1.12):
|
||||
dependencies:
|
||||
zod: 4.1.12
|
||||
|
||||
zod@4.1.12: {}
|
||||
|
||||
zrender@5.6.1:
|
||||
dependencies:
|
||||
tslib: 2.3.0
|
||||
|
|
|
|||
Loading…
Reference in New Issue