Compare commits

...

7 Commits

Author SHA1 Message Date
Coltea 59ca885518
Merge pull request #1539 from KuaiYu95/fe/doc
文档前台查看功能
2025-11-19 18:48:14 +08:00
Coltea 0e64ff946f
Merge pull request #1540 from coltea/feat-node-list-publisher
feat 文档相关页面支持直接跳转至前台
2025-11-19 18:47:43 +08:00
coltea 19e6a66809 feat node list publish id 2025-11-19 18:43:10 +08:00
yu.kuai c15272aeb2 feat: 分享文档 2025-11-19 18:39:18 +08:00
yu.kuai 32ed999b48 fix: 挂件 esc 快捷关闭 2025-11-19 17:24:15 +08:00
Coltea 98e4a917e0
Merge pull request #1538 from guanweiwang/feature/icon
pref: 统一图标地址, 去除无用文件
2025-11-19 17:13:59 +08:00
Gavan 6e5f780771 pref: 统一图标地址, 去除无用文件 2025-11-19 17:08:28 +08:00
129 changed files with 877 additions and 4179 deletions

View File

@ -6582,6 +6582,9 @@ const docTemplate = `{
"position": { "position": {
"type": "number" "type": "number"
}, },
"publisher_id": {
"type": "string"
},
"rag_info": { "rag_info": {
"$ref": "#/definitions/domain.RagInfo" "$ref": "#/definitions/domain.RagInfo"
}, },

View File

@ -6575,6 +6575,9 @@
"position": { "position": {
"type": "number" "type": "number"
}, },
"publisher_id": {
"type": "string"
},
"rag_info": { "rag_info": {
"$ref": "#/definitions/domain.RagInfo" "$ref": "#/definitions/domain.RagInfo"
}, },

View File

@ -1763,6 +1763,8 @@ definitions:
$ref: '#/definitions/domain.NodePermissions' $ref: '#/definitions/domain.NodePermissions'
position: position:
type: number type: number
publisher_id:
type: string
rag_info: rag_info:
$ref: '#/definitions/domain.RagInfo' $ref: '#/definitions/domain.RagInfo'
status: status:

View File

@ -174,6 +174,7 @@ type NodeListItemResp struct {
EditorId string `json:"editor_id"` EditorId string `json:"editor_id"`
Creator string `json:"creator"` Creator string `json:"creator"`
Editor string `json:"editor"` Editor string `json:"editor"`
PublisherId string `json:"publisher_id" gorm:"-"`
Permissions NodePermissions `json:"permissions" gorm:"type:jsonb"` Permissions NodePermissions `json:"permissions" gorm:"type:jsonb"`
} }

View File

@ -157,6 +157,32 @@ func (r *NodeRepository) GetLatestNodeReleaseByNodeIDs(ctx context.Context, kbID
return nodeReleases, nil return nodeReleases, nil
} }
func (r *NodeRepository) GetNodeReleasePublisherMap(ctx context.Context, kbID string) (map[string]string, error) {
type Result struct {
NodeID string `gorm:"column:node_id"`
PublisherID string `gorm:"column:publisher_id"`
}
var results []Result
if err := r.db.WithContext(ctx).
Model(&domain.NodeRelease{}).
Select("node_id, publisher_id").
Where("kb_id = ?", kbID).
Where("node_releases.doc_id != '' ").
Find(&results).Error; err != nil {
return nil, err
}
publisherMap := make(map[string]string)
for _, result := range results {
if result.PublisherID != "" {
publisherMap[result.NodeID] = result.PublisherID
}
}
return publisherMap, nil
}
func (r *NodeRepository) UpdateNodeContent(ctx context.Context, req *domain.UpdateNodeReq, userId string) error { func (r *NodeRepository) UpdateNodeContent(ctx context.Context, req *domain.UpdateNodeReq, userId string) error {
// Use transaction to ensure data consistency // Use transaction to ensure data consistency
err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {

View File

@ -86,6 +86,21 @@ func (u *NodeUsecase) GetList(ctx context.Context, req *domain.GetNodeListReq) (
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(nodes) == 0 {
return nodes, nil
}
publisherMap, err := u.nodeRepo.GetNodeReleasePublisherMap(ctx, req.KBID)
if err != nil {
return nil, err
}
for _, node := range nodes {
if publisherID, exists := publisherMap[node.ID]; exists {
node.PublisherId = publisherID
}
}
return nodes, nil return nodes, nil
} }

View File

@ -8,7 +8,6 @@
"build:dev": "vite build --m development", "build:dev": "vite build --m development",
"build": "tsc -b && vite build", "build": "tsc -b && vite build",
"build:analyze": "tsc -b && vite build -- --analyze", "build:analyze": "tsc -b && vite build -- --analyze",
"icon": "node ./scripts/downLoadIcon.cjs",
"api": "cx-swagger-api" "api": "cx-swagger-api"
}, },
"dependencies": { "dependencies": {

View File

@ -1,23 +0,0 @@
const fs = require("fs");
const path = require("path");
async function downloadFile(url) {
const iconPath = path.resolve(__dirname, "../src/assets/fonts/iconfont.js");
const iconDir = path.dirname(iconPath);
// 检查目录是否存在,不存在则创建
if (!fs.existsSync(iconDir)) {
fs.mkdirSync(iconDir, { recursive: true });
console.log(`目录 ${iconDir} 已创建`);
}
const response = await fetch(`https:${url}`, {
method: "GET",
// responseType: "stream", // fetch 不支持此参数
}).then((res) => res.text());
fs.writeFileSync(iconPath, response);
console.log("Download Icon Success");
}
let argument = process.argv.splice(2);
downloadFile(argument[0]);

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 360 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1,6 +1,6 @@
import Logo from '@/assets/images/logo.png'; import Logo from '@/assets/images/logo.png';
import { Avatar as MuiAvatar, SxProps } from '@mui/material'; import { Avatar as MuiAvatar, SxProps } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconDandulogo } from '@panda-wiki/icons';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
interface AvatarProps { interface AvatarProps {
@ -15,9 +15,8 @@ const Avatar = (props: AvatarProps) => {
const src = props.src; const src = props.src;
const LogoIcon = ( const LogoIcon = (
<Icon <IconDandulogo
sx={{ width: '100%', height: '100%', color: 'text.primary' }} sx={{ width: '100%', height: '100%', color: 'text.primary' }}
type='icon-dandulogo'
/> />
); );

View File

@ -1,5 +1,5 @@
import { FooterSetting } from '@/api/type'; import { FooterSetting } from '@/api/type';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag, IconTianjia } from '@panda-wiki/icons';
import { import {
closestCenter, closestCenter,
DndContext, DndContext,
@ -100,7 +100,7 @@ const LinkItem = forwardRef<HTMLDivElement, LinkItemProps>(
}} }}
{...dragHandleProps} {...dragHandleProps}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
<Box <Box
sx={{ sx={{
@ -123,7 +123,7 @@ const LinkItem = forwardRef<HTMLDivElement, LinkItemProps>(
ml: 'auto', ml: 'auto',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
<Controller <Controller
@ -373,7 +373,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
{...dragHandleProps} {...dragHandleProps}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
<Box <Box
sx={{ sx={{
@ -396,7 +396,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
ml: 'auto', ml: 'auto',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
<Controller <Controller
@ -513,8 +513,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
onClick={handleAddLink} onClick={handleAddLink}
> >
<Icon <IconTianjia
type='icon-tianjia'
sx={{ fontSize: '10px !important', color: '#5F58FE' }} sx={{ fontSize: '10px !important', color: '#5F58FE' }}
/> />
<Box <Box

View File

@ -1,7 +1,7 @@
import { CardWebHeaderBtn } from '@/api'; import { CardWebHeaderBtn } from '@/api';
import UploadFile from '@/components/UploadFile'; import UploadFile from '@/components/UploadFile';
import { useAppDispatch, useAppSelector } from '@/store'; import { useAppDispatch, useAppSelector } from '@/store';
import { setAppPreviewData } from '@/store/slices/config';
import { import {
Box, Box,
Checkbox, Checkbox,
@ -13,16 +13,15 @@ import {
Stack, Stack,
TextField, TextField,
} from '@mui/material'; } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
import { import {
CSSProperties, CSSProperties,
Dispatch, Dispatch,
forwardRef, forwardRef,
HTMLAttributes, HTMLAttributes,
SetStateAction, SetStateAction,
useEffect,
} from 'react'; } from 'react';
import { Control, Controller, useForm } from 'react-hook-form'; import { Control, Controller } from 'react-hook-form';
export type ItemProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & { export type ItemProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {
item: CardWebHeaderBtn; item: CardWebHeaderBtn;
@ -300,7 +299,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
size='small' size='small'
@ -311,7 +310,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
{...dragHandleProps} {...dragHandleProps}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -1,6 +1,6 @@
import UploadFile from '@/components/UploadFile'; import UploadFile from '@/components/UploadFile';
import { DomainSocialMediaAccount } from '@/request/types'; import { DomainSocialMediaAccount } from '@/request/types';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
import { import {
Box, Box,
IconButton, IconButton,
@ -92,7 +92,7 @@ const Item = forwardRef<HTMLDivElement, SocialInfoProps>(
}} }}
{...dragHandleProps} {...dragHandleProps}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
<Box <Box
sx={{ sx={{
@ -120,7 +120,7 @@ const Item = forwardRef<HTMLDivElement, SocialInfoProps>(
ml: 'auto', ml: 'auto',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
<Stack direction={'row'} gap={1}> <Stack direction={'row'} gap={1}>
@ -142,16 +142,10 @@ const Item = forwardRef<HTMLDivElement, SocialInfoProps>(
}} }}
renderValue={selected => { renderValue={selected => {
const option = options.find(i => i.key === selected); const option = options.find(i => i.key === selected);
const AppIcon = option?.config_type || option?.type;
return ( return (
<Stack justifyContent={'center'} sx={{ mt: '2px' }}> <Stack justifyContent={'center'} sx={{ mt: '2px' }}>
<Icon {AppIcon && <AppIcon sx={{ fontSize: '14px' }} />}
type={
option
? option?.config_type || option?.type || ''
: ''
}
sx={{ fontSize: '14px' }}
/>
</Stack> </Stack>
); );
}} }}
@ -185,30 +179,31 @@ const Item = forwardRef<HTMLDivElement, SocialInfoProps>(
borderRadius: 1, borderRadius: 1,
}} }}
> >
{options.map(item => ( {options.map(item => {
<ToggleButton const AppIcon = item?.config_type || item?.type;
key={item.key} return (
value={item.key} <ToggleButton
sx={{ key={item.key}
p: 1, value={item.key}
height: 'auto', sx={{
border: '1px solid #ddd !important', p: 1,
borderRadius: '0px', height: 'auto',
}} border: '1px solid #ddd !important',
> borderRadius: '0px',
<Stack }}
direction='row'
gap={1}
alignItems='center'
> >
<Icon <Stack
type={item?.config_type || item?.type} direction='row'
sx={{ fontSize: '16px' }} gap={1}
/> alignItems='center'
{/* <Box>{item.value || item.key}</Box> */} >
</Stack> {AppIcon && (
</ToggleButton> <AppIcon sx={{ fontSize: '16px' }} />
))} )}
</Stack>
</ToggleButton>
);
})}
</ToggleButtonGroup> </ToggleButtonGroup>
</MenuItem> </MenuItem>
</Select> </Select>

View File

@ -1,99 +0,0 @@
import { Box, Button, IconButton, Stack } from '@mui/material';
import { Icon } from '@ctzhian/ui';
import { AppSetting } from '@/api';
import { useState } from 'react';
import { getButtonThemeStyle } from './buttonThemeUtils';
const NavBtns = ({ detail }: { detail?: Partial<AppSetting> }) => {
const [open, setOpen] = useState(false);
return (
<>
<IconButton
size='small'
onClick={() => setOpen(!open)}
sx={{
color: 'text.primary',
width: 40,
height: 40,
}}
>
<Icon type='icon-a-caidan' />
</IconButton>
<Box
sx={{
position: 'absolute',
width: '100%',
height: '110vh',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 999,
transition: 'all 0.3s ease-in-out',
transform: 'translateX(200%) translateY(-200%)',
...(open && {
bgcolor: 'background.default',
transform: 'translateX(0) translateY(0)',
}),
}}
>
<Stack
direction='row'
alignItems='center'
gap={1.5}
sx={{ py: '14px', cursor: 'pointer', ml: 1.5, color: 'text.primary' }}
>
{detail?.icon && <img src={detail?.icon} alt='logo' width={32} />}
<Box sx={{ fontSize: 18 }}>{detail?.title}</Box>
</Stack>
<Stack gap={4} sx={{ px: 3, mt: 4, bgcolor: 'background.default' }}>
{detail?.btns?.map(item => (
<Button
key={item.id}
fullWidth
variant={item.variant}
startIcon={
item.showIcon && item.icon ? (
<img src={item.icon} alt='logo' width={36} height={36} />
) : null
}
sx={{
textTransform: 'none',
justifyContent: 'flex-start',
height: '60px',
px: 4,
gap: 3,
fontSize: 18,
'& .MuiButton-startIcon': {
ml: 0,
mr: 0,
},
...getButtonThemeStyle(detail?.theme_mode, item.variant),
}}
>
{item.text}
</Button>
))}
</Stack>
<IconButton
size='small'
onClick={() => setOpen(!open)}
sx={{
position: 'absolute',
top: 10,
right: 10,
color: 'text.primary',
width: 40,
height: 40,
zIndex: 1,
}}
>
<Icon type='icon-chahao' />
</IconButton>
</Box>
</>
);
};
export default NavBtns;

View File

@ -1,49 +0,0 @@
import React, { Dispatch, ReactNode, SetStateAction } from 'react';
import { Box, IconButton } from '@mui/material';
import CloseIcon from '@mui/icons-material/Close';
interface OverlayProps {
open: boolean;
onClose: Dispatch<SetStateAction<boolean>>;
children: ReactNode;
}
const Overlay: React.FC<OverlayProps> = ({ open, onClose, children }) => {
return (
<>
{open && (
<Box
sx={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.7)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
zIndex: 1300,
}}
onClick={() => onClose(false)}
>
<IconButton
onClick={() => onClose(false)}
sx={{
position: 'absolute',
top: 16,
right: 16,
color: 'white',
zIndex: 1310,
}}
>
<CloseIcon />
</IconButton>
<Box onClick={e => e.stopPropagation()}>{children}</Box>
</Box>
)}
</>
);
};
export default Overlay;

View File

@ -1,55 +0,0 @@
/**
*
* @param themeMode ('light' | 'dark')
* @param variant ('contained' | 'outlined' | 'text')
* @returns
*/
export const getButtonThemeStyle = (
themeMode: 'light' | 'dark' | undefined,
variant: string,
) => {
// 只在dark主题下应用特殊样式
if (themeMode === 'dark') {
switch (variant) {
case 'contained':
return {
bgcolor: 'primary.main',
color: 'primary.contrastText',
borderColor: 'primary.main',
'&:hover': {
bgcolor: 'primary.dark',
borderColor: 'primary.dark',
},
};
case 'outlined':
return {
borderColor: 'primary.main',
color: 'primary.main',
'&:hover': {
bgcolor: 'action.hover',
borderColor: 'primary.main',
},
};
case 'text':
return {
color: 'primary.main',
'&:hover': {
bgcolor: 'action.hover',
},
};
default:
return {};
}
}
if (themeMode === 'light') {
switch (variant) {
case 'text':
return {
color: 'text.primary',
};
}
}
return {};
};
export default getButtonThemeStyle;

View File

@ -1,69 +0,0 @@
import { SwitchProps, Box } from '@mui/material';
import { Icon } from '@ctzhian/ui';
import MySwitch from './Switch';
const ThemeSwitch = (props: SwitchProps) => {
return (
<MySwitch
{...props}
icon={
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Box
sx={{
width: 22,
height: 22,
bgcolor: '#fff',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Icon
type='icon-mingliangmoshi'
sx={{ color: '#000', fontSize: 16 }}
/>
</Box>
</Box>
}
checkedIcon={
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Box
sx={{
width: 22,
height: 22,
bgcolor: '#fff',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Icon
type='icon-shensemoshi'
sx={{ color: '#000', fontSize: 16 }}
/>
</Box>
</Box>
}
/>
);
};
export default ThemeSwitch;

View File

@ -10,7 +10,7 @@ import {
alpha, alpha,
} from '@mui/material'; } from '@mui/material';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { Icon } from '@ctzhian/ui'; import { IconWangyeguajian } from '@panda-wiki/icons';
import { Dispatch, SetStateAction, useMemo, useState } from 'react'; import { Dispatch, SetStateAction, useMemo, useState } from 'react';
import type { CSSProperties } from 'react'; import type { CSSProperties } from 'react';
import { Component } from '../../index'; import { Component } from '../../index';
@ -185,8 +185,7 @@ const ComponentBar = ({
}} }}
{...(!item.fixed ? { ...attributes, ...listeners } : {})} {...(!item.fixed ? { ...attributes, ...listeners } : {})}
> >
<Icon <IconWangyeguajian
type='icon-wangyeguajian'
sx={{ sx={{
color: color:
item.id === curComponent.id item.id === curComponent.id
@ -196,7 +195,7 @@ const ComponentBar = ({
: 'text.secondary', : 'text.secondary',
fontSize: '14px', fontSize: '14px',
}} }}
></Icon> ></IconWangyeguajian>
<Typography <Typography
sx={{ sx={{
marginLeft: '8px', marginLeft: '8px',

View File

@ -1,5 +1,5 @@
import { Box, IconButton, Stack, TextField } from '@mui/material'; import { Box, IconButton, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
import { import {
CSSProperties, CSSProperties,
Dispatch, Dispatch,
@ -118,7 +118,7 @@ const HotSearchItem = forwardRef<HTMLDivElement, HotSearchItemProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
size='small' size='small'
@ -129,7 +129,7 @@ const HotSearchItem = forwardRef<HTMLDivElement, HotSearchItemProps>(
}} }}
{...(dragHandleProps as any)} {...(dragHandleProps as any)}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -8,7 +8,7 @@ import {
Select, Select,
MenuItem, MenuItem,
} from '@mui/material'; } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
import { import {
CSSProperties, CSSProperties,
Dispatch, Dispatch,
@ -159,7 +159,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
size='small' size='small'
@ -170,7 +170,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
{...(dragHandleProps as any)} {...(dragHandleProps as any)}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -2,8 +2,14 @@ import { postApiV1NodeSummary } from '@/request/Node';
import { DomainRecommendNodeListResp } from '@/request/types'; import { DomainRecommendNodeListResp } from '@/request/types';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { Box, IconButton, Stack } from '@mui/material'; import { Box, IconButton, Stack } from '@mui/material';
import { Ellipsis, Icon, message } from '@ctzhian/ui'; import { Ellipsis, message } from '@ctzhian/ui';
import { CSSProperties, forwardRef, HTMLAttributes, useState } from 'react'; import { CSSProperties, forwardRef, HTMLAttributes, useState } from 'react';
import {
IconShanchu2,
IconDrag,
IconWenjianjia,
IconWenjian,
} from '@panda-wiki/icons';
export type ItemProps = HTMLAttributes<HTMLDivElement> & { export type ItemProps = HTMLAttributes<HTMLDivElement> & {
item: DomainRecommendNodeListResp; item: DomainRecommendNodeListResp;
@ -80,9 +86,12 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
<Box sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}> <Box sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}>
{item.emoji} {item.emoji}
</Box> </Box>
) : item.type === 1 ? (
<IconWenjianjia
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
/>
) : ( ) : (
<Icon <IconWenjian
type={item.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'}
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }} sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
/> />
)} )}
@ -121,12 +130,16 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
.slice(0, 4) .slice(0, 4)
.map(it => ( .map(it => (
<Stack direction={'row'} alignItems={'center'} gap={1}> <Stack direction={'row'} alignItems={'center'} gap={1}>
<Icon {it.type === 1 ? (
type={ <IconWenjianjia
it.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian' sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
} />
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }} ) : (
/> <IconWenjian
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
/>
)}
<Ellipsis sx={{ flex: 1, width: 0 }}>{it.name}</Ellipsis> <Ellipsis sx={{ flex: 1, width: 0 }}>{it.name}</Ellipsis>
</Stack> </Stack>
))} ))}
@ -147,7 +160,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
@ -159,7 +172,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
{...dragHandleProps} {...dragHandleProps}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -1,5 +1,5 @@
import { Box, IconButton, Stack, TextField } from '@mui/material'; import { Box, IconButton, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
import UploadFile from '@/components/UploadFile'; import UploadFile from '@/components/UploadFile';
import { import {
CSSProperties, CSSProperties,
@ -132,7 +132,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
size='small' size='small'
@ -143,7 +143,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
{...(dragHandleProps as any)} {...(dragHandleProps as any)}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -1,5 +1,5 @@
import { Box, IconButton, Stack, TextField } from '@mui/material'; import { Box, IconButton, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
import UploadFile from '@/components/UploadFile'; import UploadFile from '@/components/UploadFile';
import { import {
CSSProperties, CSSProperties,
@ -152,7 +152,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
size='small' size='small'
@ -163,7 +163,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
{...(dragHandleProps as any)} {...(dragHandleProps as any)}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -1,5 +1,5 @@
import { Box, IconButton, Stack, TextField } from '@mui/material'; import { Box, IconButton, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
import { import {
CSSProperties, CSSProperties,
Dispatch, Dispatch,
@ -143,7 +143,7 @@ const ItemType = forwardRef<HTMLDivElement, ItemTypeProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
size='small' size='small'
@ -154,7 +154,7 @@ const ItemType = forwardRef<HTMLDivElement, ItemTypeProps>(
}} }}
{...(dragHandleProps as any)} {...(dragHandleProps as any)}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -1,5 +1,5 @@
import { Box, IconButton, Stack, TextField } from '@mui/material'; import { Box, IconButton, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
import { import {
CSSProperties, CSSProperties,
Dispatch, Dispatch,
@ -185,7 +185,7 @@ const ItemType = forwardRef<HTMLDivElement, ItemTypeProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
size='small' size='small'
@ -196,7 +196,7 @@ const ItemType = forwardRef<HTMLDivElement, ItemTypeProps>(
}} }}
{...(dragHandleProps as any)} {...(dragHandleProps as any)}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -2,7 +2,13 @@ import { postApiV1NodeSummary } from '@/request/Node';
import { DomainRecommendNodeListResp } from '@/request/types'; import { DomainRecommendNodeListResp } from '@/request/types';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { Box, IconButton, Stack } from '@mui/material'; import { Box, IconButton, Stack } from '@mui/material';
import { Ellipsis, Icon, message } from '@ctzhian/ui'; import { Ellipsis, message } from '@ctzhian/ui';
import {
IconShanchu2,
IconDrag,
IconWenjianjia,
IconWenjian,
} from '@panda-wiki/icons';
import { CSSProperties, forwardRef, HTMLAttributes, useState } from 'react'; import { CSSProperties, forwardRef, HTMLAttributes, useState } from 'react';
export type ItemProps = HTMLAttributes<HTMLDivElement> & { export type ItemProps = HTMLAttributes<HTMLDivElement> & {
@ -82,9 +88,12 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
<Box sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}> <Box sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}>
{item.emoji} {item.emoji}
</Box> </Box>
) : item.type === 1 ? (
<IconWenjianjia
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
/>
) : ( ) : (
<Icon <IconWenjian
type={item.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'}
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }} sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
/> />
)} )}
@ -128,11 +137,12 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
> >
{it.emoji} {it.emoji}
</Box> </Box>
) : it.type === 1 ? (
<IconWenjianjia
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
/>
) : ( ) : (
<Icon <IconWenjian
type={
it.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'
}
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }} sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
/> />
)} )}
@ -157,7 +167,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
@ -169,7 +179,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
{...dragHandleProps} {...dragHandleProps}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -1,5 +1,5 @@
import { Box, IconButton, Stack, TextField } from '@mui/material'; import { Box, IconButton, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
import { import {
CSSProperties, CSSProperties,
Dispatch, Dispatch,
@ -143,7 +143,7 @@ const FaqItem = forwardRef<HTMLDivElement, FaqItemProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
size='small' size='small'
@ -154,7 +154,7 @@ const FaqItem = forwardRef<HTMLDivElement, FaqItemProps>(
}} }}
{...(dragHandleProps as any)} {...(dragHandleProps as any)}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -1,5 +1,5 @@
import { Box, IconButton, Stack, TextField } from '@mui/material'; import { Box, IconButton, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
import { import {
CSSProperties, CSSProperties,
Dispatch, Dispatch,
@ -143,7 +143,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
size='small' size='small'
@ -154,7 +154,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
{...(dragHandleProps as any)} {...(dragHandleProps as any)}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -1,9 +1,8 @@
import { AppDetail, HeaderSetting } from '@/api'; import { AppDetail, HeaderSetting } from '@/api';
import UploadFile from '@/components/UploadFile'; import UploadFile from '@/components/UploadFile';
import { Stack, Box, TextField } from '@mui/material'; import { Stack, Box, TextField, SvgIconProps } from '@mui/material';
import DragBrand from '../basicComponents/DragBrand'; import DragBrand from '../basicComponents/DragBrand';
import { Icon } from '@ctzhian/ui'; import { Dispatch, SetStateAction, useEffect } from 'react';
import { Dispatch, SetStateAction, useEffect, useMemo } from 'react';
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { useAppDispatch, useAppSelector } from '@/store'; import { useAppDispatch, useAppSelector } from '@/store';
import { setAppPreviewData } from '@/store/slices/config'; import { setAppPreviewData } from '@/store/slices/config';
@ -12,6 +11,13 @@ import Switch from '../basicComponents/Switch';
import DragSocialInfo from '../basicComponents/DragSocialInfo'; import DragSocialInfo from '../basicComponents/DragSocialInfo';
import VersionMask from '@/components/VersionMask'; import VersionMask from '@/components/VersionMask';
import { PROFESSION_VERSION_PERMISSION } from '@/constant/version'; import { PROFESSION_VERSION_PERMISSION } from '@/constant/version';
import { IconTianjia } from '@panda-wiki/icons';
import {
IconWeixingongzhonghao,
IconDianhua,
IconWeixingongzhonghaoDaiyanse,
IconDianhua1,
} from '@panda-wiki/icons';
interface FooterConfigProps { interface FooterConfigProps {
data?: AppDetail | null; data?: AppDetail | null;
@ -21,8 +27,8 @@ interface FooterConfigProps {
export interface Option { export interface Option {
key: string; key: string;
value: string; value: string;
type: string; type: React.ComponentType<SvgIconProps>;
config_type?: string; config_type?: React.ComponentType<SvgIconProps>;
text_placeholder?: string; text_placeholder?: string;
text_label?: string; text_label?: string;
} }
@ -30,16 +36,16 @@ export const options: Option[] = [
{ {
key: 'wechat_oa', key: 'wechat_oa',
value: '微信公众号', value: '微信公众号',
type: 'icon-weixingongzhonghao', type: IconWeixingongzhonghao,
config_type: 'icon-weixingongzhonghao-daiyanse', config_type: IconWeixingongzhonghaoDaiyanse,
text_placeholder: '请输入公众号名称', text_placeholder: '请输入公众号名称',
text_label: '公众号名称', text_label: '公众号名称',
}, },
{ {
key: 'phone', key: 'phone',
value: '电话', value: '电话',
type: 'icon-dianhua', type: IconDianhua,
config_type: 'icon-dianhua1', config_type: IconDianhua1,
text_placeholder: '请输入文字', text_placeholder: '请输入文字',
text_label: '文字', text_label: '文字',
}, },
@ -331,8 +337,7 @@ const FooterConfig = ({ data, setIsEdit, isEdit }: FooterConfigProps) => {
setIsEdit(true); setIsEdit(true);
}} }}
> >
<Icon <IconTianjia
type='icon-tianjia'
sx={{ fontSize: '10px !important', color: '#5F58FE' }} sx={{ fontSize: '10px !important', color: '#5F58FE' }}
/> />
<Box <Box
@ -396,8 +401,7 @@ const FooterConfig = ({ data, setIsEdit, isEdit }: FooterConfigProps) => {
setIsEdit(true); setIsEdit(true);
}} }}
> >
<Icon <IconTianjia
type='icon-tianjia'
sx={{ fontSize: '10px !important', color: '#5F58FE' }} sx={{ fontSize: '10px !important', color: '#5F58FE' }}
/> />
<Box <Box

View File

@ -2,12 +2,11 @@ import { AppDetail, HeaderSetting } from '@/api';
import DragBtn from '../basicComponents/DragBtn'; import DragBtn from '../basicComponents/DragBtn';
import UploadFile from '@/components/UploadFile'; import UploadFile from '@/components/UploadFile';
import { Stack, Box, TextField } from '@mui/material'; import { Stack, Box, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui';
import { Dispatch, SetStateAction, useEffect } from 'react'; import { Dispatch, SetStateAction, useEffect } from 'react';
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { useAppDispatch, useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { setAppPreviewData } from '@/store/slices/config';
import useDebounceAppPreviewData from '@/hooks/useDebounceAppPreviewData'; import useDebounceAppPreviewData from '@/hooks/useDebounceAppPreviewData';
import { IconTianjia } from '@panda-wiki/icons';
interface CardWebHeaderProps { interface CardWebHeaderProps {
data?: AppDetail | null; data?: AppDetail | null;
@ -17,7 +16,6 @@ interface CardWebHeaderProps {
const HeaderConfig = ({ data, setIsEdit, isEdit }: CardWebHeaderProps) => { const HeaderConfig = ({ data, setIsEdit, isEdit }: CardWebHeaderProps) => {
const { appPreviewData } = useAppSelector(state => state.config); const { appPreviewData } = useAppSelector(state => state.config);
const dispatch = useAppDispatch();
const debouncedDispatch = useDebounceAppPreviewData(); const debouncedDispatch = useDebounceAppPreviewData();
const { const {
control, control,
@ -257,8 +255,7 @@ const HeaderConfig = ({ data, setIsEdit, isEdit }: CardWebHeaderProps) => {
}} }}
onClick={handleAddButton} onClick={handleAddButton}
> >
<Icon <IconTianjia
type='icon-tianjia'
sx={{ fontSize: '10px !important', color: '#5F58FE' }} sx={{ fontSize: '10px !important', color: '#5F58FE' }}
/> />
<Box sx={{ fontSize: 14, lineHeight: '22px', marginLeft: 0.5 }}> <Box sx={{ fontSize: 14, lineHeight: '22px', marginLeft: 0.5 }}>

View File

@ -1,5 +1,5 @@
import { Box, IconButton, Stack, TextField } from '@mui/material'; import { Box, IconButton, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
import { import {
CSSProperties, CSSProperties,
Dispatch, Dispatch,
@ -143,7 +143,7 @@ const ItemType = forwardRef<HTMLDivElement, ItemTypeProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
size='small' size='small'
@ -154,7 +154,7 @@ const ItemType = forwardRef<HTMLDivElement, ItemTypeProps>(
}} }}
{...(dragHandleProps as any)} {...(dragHandleProps as any)}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -1,5 +1,5 @@
import { Box, IconButton, Stack, TextField } from '@mui/material'; import { Box, IconButton, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
import { import {
CSSProperties, CSSProperties,
Dispatch, Dispatch,
@ -115,7 +115,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
size='small' size='small'
@ -126,7 +126,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
{...(dragHandleProps as any)} {...(dragHandleProps as any)}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -1,9 +1,13 @@
import { postApiV1NodeSummary } from '@/request/Node';
import { DomainRecommendNodeListResp } from '@/request/types'; import { DomainRecommendNodeListResp } from '@/request/types';
import { useAppSelector } from '@/store';
import { Box, IconButton, Stack } from '@mui/material'; import { Box, IconButton, Stack } from '@mui/material';
import { Ellipsis, Icon, message } from '@ctzhian/ui'; import {
import { CSSProperties, forwardRef, HTMLAttributes, useState } from 'react'; IconShanchu2,
IconDrag,
IconWenjianjia,
IconWenjian,
} from '@panda-wiki/icons';
import { Ellipsis } from '@ctzhian/ui';
import { CSSProperties, forwardRef, HTMLAttributes } from 'react';
export type ItemProps = HTMLAttributes<HTMLDivElement> & { export type ItemProps = HTMLAttributes<HTMLDivElement> & {
item: DomainRecommendNodeListResp; item: DomainRecommendNodeListResp;
@ -66,9 +70,12 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
<Box sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}> <Box sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}>
{item.emoji} {item.emoji}
</Box> </Box>
) : item.type === 1 ? (
<IconWenjianjia
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
/>
) : ( ) : (
<Icon <IconWenjian
type={item.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'}
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }} sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
/> />
)} )}
@ -91,7 +98,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
height: '28px', height: '28px',
}} }}
> >
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
@ -103,7 +110,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
{...dragHandleProps} {...dragHandleProps}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -1,6 +1,6 @@
import { useEffect, useState, useRef } from 'react'; import { useEffect, useState, useRef } from 'react';
import { Button, Stack, Typography } from '@mui/material'; import { Button, Stack, Typography } from '@mui/material';
import { CusTabs, Icon, message, Modal } from '@ctzhian/ui'; import { CusTabs, message, Modal } from '@ctzhian/ui';
import { import {
getApiV1NodeRecommendNodes, getApiV1NodeRecommendNodes,
getApiV1KnowledgeBaseDetail, getApiV1KnowledgeBaseDetail,
@ -9,6 +9,7 @@ import {
DomainAppDetailResp, DomainAppDetailResp,
DomainWebAppLandingConfigResp, DomainWebAppLandingConfigResp,
} from '@/request/types'; } from '@/request/types';
import { IconPCduan, IconYidongduan } from '@panda-wiki/icons';
import { getApiV1AppDetail, putApiV1App } from '@/request/App'; import { getApiV1AppDetail, putApiV1App } from '@/request/App';
import { useAppSelector, useAppDispatch } from '@/store'; import { useAppSelector, useAppDispatch } from '@/store';
@ -338,18 +339,11 @@ const CustomModal = ({
<CusTabs <CusTabs
list={[ list={[
{ {
label: ( label: <IconPCduan sx={{ fontSize: 14 }} />,
<Icon type='icon-PCduan' sx={{ height: '32px' }} />
),
value: 'pc', value: 'pc',
}, },
{ {
label: ( label: <IconYidongduan sx={{ fontSize: 14 }} />,
<Icon
type='icon-yidongduan'
sx={{ height: '32px' }}
/>
),
value: 'mobile', value: 'mobile',
}, },
]} ]}

View File

@ -1,390 +0,0 @@
import { FooterSetting } from '@/api/type';
import {
closestCenter,
DndContext,
DragEndEvent,
DragOverlay,
DragStartEvent,
MouseSensor,
TouchSensor,
useSensor,
useSensors,
} from '@dnd-kit/core';
import {
rectSortingStrategy,
SortableContext,
useSortable,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { Box, Button, IconButton, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui';
import {
CSSProperties,
forwardRef,
HTMLAttributes,
useCallback,
useState,
} from 'react';
import {
Control,
Controller,
FieldErrors,
useFieldArray,
} from 'react-hook-form';
export type ItemProps = HTMLAttributes<HTMLDivElement> & {
groupIndex: number;
withOpacity?: boolean;
isDragging?: boolean;
dragHandleProps?: any;
control: Control<FooterSetting>;
errors: FieldErrors<FooterSetting>;
setIsEdit: (value: boolean) => void;
handleRemove?: () => void;
};
interface LinkItemProps extends HTMLAttributes<HTMLDivElement> {
linkId: string;
linkIndex: number;
groupIndex: number;
control: Control<FooterSetting>;
errors: FieldErrors<FooterSetting>;
setIsEdit: (value: boolean) => void;
onRemove: () => void;
withOpacity?: boolean;
isDragging?: boolean;
dragHandleProps?: any;
}
const LinkItem = forwardRef<HTMLDivElement, LinkItemProps>(
(
{
linkIndex,
groupIndex,
control,
errors,
setIsEdit,
onRemove,
withOpacity,
isDragging,
dragHandleProps,
style,
...props
},
ref,
) => {
const inlineStyles: CSSProperties = {
opacity: withOpacity ? '0.5' : '1',
cursor: isDragging ? 'grabbing' : 'grab',
...style,
};
return (
<Box ref={ref} style={inlineStyles} {...props}>
<Stack gap={1} alignItems='center' direction='row'>
<IconButton
size='small'
sx={{
cursor: 'grab',
color: 'text.secondary',
'&:hover': { color: 'primary.main' },
flexShrink: 0,
}}
{...dragHandleProps}
>
<Icon type='icon-drag' />
</IconButton>
<Box
sx={{
color: 'text.secondary',
flexShrink: 0,
fontSize: 12,
width: 20,
}}
>
{linkIndex + 1}.
</Box>
<Controller
control={control}
name={`brand_groups.${groupIndex}.links.${linkIndex}.name`}
rules={{ required: '请输入链接文字' }}
render={({ field }) => (
<TextField
{...field}
sx={{ width: 300 }}
label='链接文字'
placeholder='链接文字'
onChange={e => {
field.onChange(e.target.value);
setIsEdit(true);
}}
error={
!!errors.brand_groups?.[groupIndex]?.links?.[linkIndex]?.name
}
helperText={
errors.brand_groups?.[groupIndex]?.links?.[linkIndex]?.name
?.message
}
/>
)}
/>
<Controller
control={control}
name={`brand_groups.${groupIndex}.links.${linkIndex}.url`}
rules={{ required: '请输入链接地址' }}
render={({ field }) => (
<TextField
{...field}
fullWidth
label='链接地址'
placeholder='链接地址'
onChange={e => {
field.onChange(e.target.value);
setIsEdit(true);
}}
error={
!!errors.brand_groups?.[groupIndex]?.links?.[linkIndex]?.url
}
helperText={
errors.brand_groups?.[groupIndex]?.links?.[linkIndex]?.url
?.message
}
/>
)}
/>
<IconButton size='small' sx={{ flexShrink: 0 }} onClick={onRemove}>
<Icon type='icon-icon_tool_close' />
</IconButton>
</Stack>
</Box>
);
},
);
const SortableLinkItem: React.FC<LinkItemProps> = ({ linkId, ...rest }) => {
const {
isDragging,
attributes,
listeners,
setNodeRef,
transform,
transition,
} = useSortable({ id: linkId });
const style = {
transform: CSS.Transform.toString(transform),
transition: transition || undefined,
};
return (
<LinkItem
ref={setNodeRef}
style={style}
withOpacity={isDragging}
dragHandleProps={{
...attributes,
...listeners,
}}
linkId={linkId}
{...rest}
/>
);
};
const Item = forwardRef<HTMLDivElement, ItemProps>(
(
{
groupIndex,
withOpacity,
isDragging,
style,
dragHandleProps,
handleRemove,
control,
errors,
setIsEdit,
...props
},
ref,
) => {
const [activeId, setActiveId] = useState<string | null>(null);
const sensors = useSensors(useSensor(MouseSensor), useSensor(TouchSensor));
const {
fields: linkFields,
append: appendLink,
remove: removeLink,
move: moveLink,
} = useFieldArray({
control,
name: `brand_groups.${groupIndex}.links`,
});
const inlineStyles: CSSProperties = {
opacity: withOpacity ? '0.5' : '1',
borderRadius: '10px',
cursor: isDragging ? 'grabbing' : 'grab',
backgroundColor: '#ffffff',
width: '100%',
...style,
};
const handleLinkDragStart = useCallback((event: DragStartEvent) => {
setActiveId(event.active.id as string);
}, []);
const handleLinkDragEnd = useCallback(
(event: DragEndEvent) => {
const { active, over } = event;
if (active.id !== over?.id) {
const oldIndex = linkFields.findIndex(
(_, index) => `link-${groupIndex}-${index}` === active.id,
);
const newIndex = linkFields.findIndex(
(_, index) => `link-${groupIndex}-${index}` === over!.id,
);
moveLink(oldIndex, newIndex);
setIsEdit(true);
}
setActiveId(null);
},
[linkFields, moveLink, setIsEdit, groupIndex],
);
const handleLinkDragCancel = useCallback(() => {
setActiveId(null);
}, []);
const handleAddLink = () => {
appendLink({ name: '', url: '' });
setIsEdit(true);
};
const handleRemoveLink = (linkIndex: number) => {
removeLink(linkIndex);
setIsEdit(true);
};
return (
<Box ref={ref} style={inlineStyles} {...props}>
<Box
sx={{
border: '1px solid',
borderColor: 'divider',
borderRadius: '10px',
p: 2,
mb: 1,
pb: 1,
}}
>
<Stack direction='row' alignItems='center' gap={1} sx={{ mb: 1 }}>
<IconButton
size='small'
sx={{
cursor: 'grab',
color: 'text.secondary',
'&:hover': { color: 'primary.main' },
flexShrink: 0,
}}
{...dragHandleProps}
>
<Icon type='icon-drag' />
</IconButton>
<Controller
control={control}
name={`brand_groups.${groupIndex}.name`}
rules={{ required: '请输入链接组名称' }}
render={({ field }) => (
<TextField
{...field}
fullWidth
placeholder='输入链接组名称'
label='链接组名称'
onChange={e => {
field.onChange(e.target.value);
setIsEdit(true);
}}
error={!!errors.brand_groups?.[groupIndex]?.name}
helperText={errors.brand_groups?.[groupIndex]?.name?.message}
/>
)}
/>
<IconButton size='small' onClick={handleRemove}>
<Icon type='icon-icon_tool_close' />
</IconButton>
</Stack>
{/* 链接拖拽区域 */}
{linkFields.length > 0 && (
<Box
sx={{
border: '1px dashed',
borderColor: 'divider',
borderRadius: '10px',
py: 1,
pl: 2,
}}
>
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragStart={handleLinkDragStart}
onDragEnd={handleLinkDragEnd}
onDragCancel={handleLinkDragCancel}
>
<SortableContext
items={linkFields.map(
(_, index) => `link-${groupIndex}-${index}`,
)}
strategy={rectSortingStrategy}
>
<Stack gap={1}>
{linkFields.map((link, linkIndex) => (
<SortableLinkItem
key={link.id}
linkId={`link-${groupIndex}-${linkIndex}`}
linkIndex={linkIndex}
groupIndex={groupIndex}
control={control}
errors={errors}
setIsEdit={setIsEdit}
onRemove={() => handleRemoveLink(linkIndex)}
/>
))}
</Stack>
</SortableContext>
<DragOverlay adjustScale style={{ transformOrigin: '0 0' }}>
{activeId ? (
<LinkItem
isDragging
linkId={activeId}
linkIndex={parseInt(activeId.split('-')[2])}
groupIndex={groupIndex}
control={control}
errors={errors}
setIsEdit={setIsEdit}
onRemove={() => {}}
/>
) : null}
</DragOverlay>
</DndContext>
</Box>
)}
<Button
size='small'
startIcon={
<Icon type='icon-add' sx={{ fontSize: '12px !important' }} />
}
onClick={handleAddLink}
sx={{ mt: 1 }}
>
</Button>
</Box>
</Box>
);
},
);
export default Item;

View File

@ -1,49 +0,0 @@
import { FooterSetting } from '@/api/type';
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { FC } from 'react';
import { Control, FieldErrors } from 'react-hook-form';
import Item, { ItemProps } from './Item';
type SortableItemProps = Omit<
ItemProps,
'withOpacity' | 'isDragging' | 'dragHandleProps'
> & {
id: string;
groupIndex: number;
control: Control<FooterSetting>;
errors: FieldErrors<FooterSetting>;
setIsEdit: (value: boolean) => void;
handleRemove: () => void;
};
const SortableItem: FC<SortableItemProps> = ({ id, ...rest }) => {
const {
isDragging,
attributes,
listeners,
setNodeRef,
transform,
transition,
} = useSortable({ id });
const style = {
transform: CSS.Transform.toString(transform),
transition: transition || undefined,
};
return (
<Item
ref={setNodeRef}
style={style}
withOpacity={isDragging}
dragHandleProps={{
...attributes,
...listeners,
}}
{...rest}
/>
);
};
export default SortableItem;

View File

@ -1,159 +0,0 @@
import { FooterSetting } from '@/api/type';
import {
closestCenter,
DndContext,
DragEndEvent,
DragOverlay,
DragStartEvent,
MouseSensor,
TouchSensor,
useSensor,
useSensors,
} from '@dnd-kit/core';
import { rectSortingStrategy, SortableContext } from '@dnd-kit/sortable';
import { Box, Button } from '@mui/material';
import { Icon } from '@ctzhian/ui';
import { FC, useCallback, useState } from 'react';
import { Control, FieldErrors, useFieldArray } from 'react-hook-form';
import Item from './Item';
import SortableItem from './SortableItem';
export interface BrandGroup {
id: string;
name: string;
links: {
id: string;
name: string;
url: string;
}[];
}
interface DragBrandProps {
control: Control<FooterSetting>;
errors: FieldErrors<FooterSetting>;
setIsEdit: (value: boolean) => void;
}
const DragBrand: FC<DragBrandProps> = ({ control, errors, setIsEdit }) => {
const [activeId, setActiveId] = useState<string | null>(null);
const sensors = useSensors(useSensor(MouseSensor), useSensor(TouchSensor));
const {
fields: brandGroupFields,
append: appendBrandGroup,
remove: removeBrandGroup,
move,
} = useFieldArray({
control,
name: 'brand_groups',
});
const handleDragStart = useCallback((event: DragStartEvent) => {
setActiveId(event.active.id as string);
}, []);
const handleDragEnd = useCallback(
(event: DragEndEvent) => {
const { active, over } = event;
if (active.id !== over?.id) {
const oldIndex = brandGroupFields.findIndex(
(_, index) => `group-${index}` === active.id,
);
const newIndex = brandGroupFields.findIndex(
(_, index) => `group-${index}` === over!.id,
);
move(oldIndex, newIndex);
setIsEdit(true);
}
setActiveId(null);
},
[brandGroupFields, move, setIsEdit],
);
const handleDragCancel = useCallback(() => {
setActiveId(null);
}, []);
const handleRemove = useCallback(
(index: number) => {
removeBrandGroup(index);
setIsEdit(true);
},
[removeBrandGroup, setIsEdit],
);
const handleAddBrandGroup = () => {
appendBrandGroup({
name: '',
links: [{ name: '', url: '' }],
});
setIsEdit(true);
};
if (brandGroupFields.length === 0) {
return (
<Button
size='small'
startIcon={
<Icon type='icon-add' sx={{ fontSize: '12px !important' }} />
}
onClick={handleAddBrandGroup}
>
</Button>
);
}
return (
<>
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
onDragCancel={handleDragCancel}
>
<SortableContext
items={brandGroupFields.map((_, index) => `group-${index}`)}
strategy={rectSortingStrategy}
>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
{brandGroupFields.map((group, groupIndex) => (
<SortableItem
key={group.id}
id={`group-${groupIndex}`}
groupIndex={groupIndex}
control={control}
errors={errors}
setIsEdit={setIsEdit}
handleRemove={() => handleRemove(groupIndex)}
/>
))}
</Box>
</SortableContext>
<DragOverlay adjustScale style={{ transformOrigin: '0 0' }}>
{activeId ? (
<Item
isDragging
groupIndex={parseInt(activeId.split('-')[1])}
control={control}
errors={errors}
setIsEdit={setIsEdit}
/>
) : null}
</DragOverlay>
</DndContext>
<Button
size='small'
startIcon={
<Icon type='icon-add' sx={{ fontSize: '12px !important' }} />
}
onClick={handleAddBrandGroup}
>
</Button>
</>
);
};
export default DragBrand;

View File

@ -1,95 +0,0 @@
import { CardWebHeaderBtn } from '@/api';
import Avatar from '@/components/Avatar';
import { Box, Button, IconButton, Stack } from '@mui/material';
import { Icon } from '@ctzhian/ui';
import { CSSProperties, forwardRef, HTMLAttributes } from 'react';
export type ItemProps = HTMLAttributes<HTMLDivElement> & {
item: CardWebHeaderBtn;
withOpacity?: boolean;
isDragging?: boolean;
dragHandleProps?: any;
selectedBtnId: string | null;
setSelectedBtnId: (id: string | null) => void;
handleRemove?: (id: string) => void;
};
const Item = forwardRef<HTMLDivElement, ItemProps>(
(
{
item,
withOpacity,
isDragging,
style,
dragHandleProps,
selectedBtnId,
setSelectedBtnId,
handleRemove,
...props
},
ref,
) => {
const inlineStyles: CSSProperties = {
opacity: withOpacity ? '0.5' : '1',
borderRadius: '10px',
cursor: isDragging ? 'grabbing' : 'grab',
backgroundColor: '#ffffff',
...style,
};
return (
<Box ref={ref} style={inlineStyles} {...props}>
<Stack
direction={'row'}
alignItems={'center'}
gap={0.5}
sx={{
p: selectedBtnId === item.id ? '3px' : 0.5,
border: selectedBtnId === item.id ? '2px solid' : '1px solid',
borderColor: selectedBtnId === item.id ? 'primary.main' : 'divider',
borderRadius: '10px',
}}
onClick={() => {
if (selectedBtnId === item.id) setSelectedBtnId(null);
else setSelectedBtnId(item.id);
}}
>
<IconButton
size='small'
sx={{
cursor: 'grab',
color: 'text.secondary',
'&:hover': { color: 'primary.main' },
}}
{...dragHandleProps}
>
<Icon type='icon-drag' />
</IconButton>
<Button
variant={item.variant}
sx={{ textTransform: 'none' }}
startIcon={
item.showIcon ? (
<Avatar src={item.icon} sx={{ width: 24, height: 24 }} />
) : undefined
}
>
{item.text}
</Button>
<IconButton
size='small'
onClick={e => {
e.stopPropagation();
handleRemove?.(item.id);
}}
sx={{ color: 'text.tertiary', ':hover': { color: 'error.main' } }}
>
<Icon type='icon-icon_tool_close' />
</IconButton>
</Stack>
</Box>
);
},
);
export default Item;

View File

@ -1,41 +0,0 @@
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { FC } from 'react';
import Item, { ItemProps } from './Item';
type SortableItemProps = ItemProps & {
selectedBtnId: string | null;
setSelectedBtnId: (id: string | null) => void;
};
const SortableItem: FC<SortableItemProps> = ({ item, ...rest }) => {
const {
isDragging,
attributes,
listeners,
setNodeRef,
transform,
transition,
} = useSortable({ id: item.id });
const style = {
transform: CSS.Transform.toString(transform),
transition: transition || undefined,
};
return (
<Item
ref={setNodeRef}
style={style}
withOpacity={isDragging}
dragHandleProps={{
...attributes,
...listeners,
}}
item={item}
{...rest}
/>
);
};
export default SortableItem;

View File

@ -1,108 +0,0 @@
import { CardWebHeaderBtn } from '@/api';
import {
closestCenter,
DndContext,
DragEndEvent,
DragOverlay,
DragStartEvent,
MouseSensor,
TouchSensor,
useSensor,
useSensors,
} from '@dnd-kit/core';
import {
arrayMove,
rectSortingStrategy,
SortableContext,
} from '@dnd-kit/sortable';
import { Stack } from '@mui/material';
import { FC, useCallback, useState } from 'react';
import Item from './Item';
import SortableItem from './SortableItem';
interface DragBtnProps {
data: CardWebHeaderBtn[];
columns?: number;
onChange: (data: CardWebHeaderBtn[]) => void;
selectedBtnId: string | null;
setSelectedBtnId: (id: string | null) => void;
}
const DragBtn: FC<DragBtnProps> = ({
data,
onChange,
selectedBtnId,
setSelectedBtnId,
}) => {
const [activeId, setActiveId] = useState<string | null>(null);
const sensors = useSensors(useSensor(MouseSensor), useSensor(TouchSensor));
const handleDragStart = useCallback((event: DragStartEvent) => {
setActiveId(event.active.id as string);
}, []);
const handleDragEnd = useCallback(
(event: DragEndEvent) => {
const { active, over } = event;
if (active.id !== over?.id) {
const oldIndex = data.findIndex(item => item.id === active.id);
const newIndex = data.findIndex(item => item.id === over!.id);
const newData = arrayMove(data, oldIndex, newIndex);
onChange(newData);
}
setActiveId(null);
},
[data, onChange],
);
const handleDragCancel = useCallback(() => {
setActiveId(null);
}, []);
const handleRemove = useCallback(
(id: string) => {
const newData = data.filter(item => item.id !== id);
onChange(newData);
},
[data, onChange],
);
if (data.length === 0) return null;
return (
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
onDragCancel={handleDragCancel}
>
<SortableContext
items={data.map(item => item.id)}
strategy={rectSortingStrategy}
>
<Stack direction={'row'} flexWrap={'wrap'} gap={0.5}>
{data.map((item, idx) => (
<SortableItem
key={idx}
id={item.id}
selectedBtnId={selectedBtnId}
setSelectedBtnId={setSelectedBtnId}
item={item}
handleRemove={handleRemove}
/>
))}
</Stack>
</SortableContext>
<DragOverlay adjustScale style={{ transformOrigin: '0 0' }}>
{activeId ? (
<Item
isDragging
item={data.find(item => item.id === activeId)!}
selectedBtnId={selectedBtnId}
setSelectedBtnId={setSelectedBtnId}
/>
) : null}
</DragOverlay>
</DndContext>
);
};
export default DragBtn;

View File

@ -1,7 +1,9 @@
import { DomainRecommendNodeListResp } from '@/request/types'; import { DomainRecommendNodeListResp } from '@/request/types';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { Ellipsis, Icon } from '@ctzhian/ui'; import { Ellipsis } from '@ctzhian/ui';
import { IconWenjianjia, IconWenjian, IconShanchu2 } from '@panda-wiki/icons';
import { Box, IconButton, Stack } from '@mui/material'; import { Box, IconButton, Stack } from '@mui/material';
import { IconDrag } from '@panda-wiki/icons';
import { CSSProperties, forwardRef, HTMLAttributes } from 'react'; import { CSSProperties, forwardRef, HTMLAttributes } from 'react';
export type ItemProps = HTMLAttributes<HTMLDivElement> & { export type ItemProps = HTMLAttributes<HTMLDivElement> & {
@ -62,10 +64,15 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
> >
<Stack direction={'row'} alignItems={'center'} gap={1}> <Stack direction={'row'} alignItems={'center'} gap={1}>
<Icon {item.type === 1 ? (
type={item.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'} <IconWenjianjia
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }} sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
/> />
) : (
<IconWenjian
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
/>
)}
<Ellipsis sx={{ flex: 1, width: 0, lineHeight: '32px' }}> <Ellipsis sx={{ flex: 1, width: 0, lineHeight: '32px' }}>
{item.name} {item.name}
</Ellipsis> </Ellipsis>
@ -95,12 +102,15 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
.slice(0, 4) .slice(0, 4)
.map(it => ( .map(it => (
<Stack direction={'row'} alignItems={'center'} gap={1}> <Stack direction={'row'} alignItems={'center'} gap={1}>
<Icon {it.type === 1 ? (
type={ <IconWenjianjia
it.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian' sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
} />
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }} ) : (
/> <IconWenjian
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
/>
)}
<Ellipsis sx={{ flex: 1, width: 0 }}>{it.name}</Ellipsis> <Ellipsis sx={{ flex: 1, width: 0 }}>{it.name}</Ellipsis>
</Stack> </Stack>
))} ))}
@ -119,7 +129,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
':hover': { color: 'error.main' }, ':hover': { color: 'error.main' },
}} }}
> >
<Icon type='icon-icon_tool_close' /> <IconShanchu2 sx={{ fontSize: '12px' }} />
</IconButton> </IconButton>
<IconButton <IconButton
size='small' size='small'
@ -130,7 +140,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
}} }}
{...dragHandleProps} {...dragHandleProps}
> >
<Icon type='icon-drag' /> <IconDrag sx={{ fontSize: '18px' }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Stack> </Stack>

View File

@ -1,8 +1,8 @@
import { ITreeItem } from '@/api'; import { ITreeItem } from '@/api';
import Cascader from '@/components/Cascader'; import Cascader from '@/components/Cascader';
import { addOpacityToColor } from '@/utils'; import { addOpacityToColor } from '@/utils';
import { Icon } from '@ctzhian/ui';
import { Box, IconButton, Stack, useTheme } from '@mui/material'; import { Box, IconButton, Stack, useTheme } from '@mui/material';
import { IconXiala, IconGengduo } from '@panda-wiki/icons';
export type TreeMenuItem = { export type TreeMenuItem = {
key: string; key: string;
@ -96,10 +96,7 @@ const TreeMenu = ({
> >
{value.label} {value.label}
{value.children && ( {value.children && (
<Icon <IconXiala sx={{ fontSize: 20, transform: 'rotate(-90deg)' }} />
type='icon-xiala'
sx={{ fontSize: 20, transform: 'rotate(-90deg)' }}
/>
)} )}
</Stack> </Stack>
{value.key === 'next-line' && ( {value.key === 'next-line' && (
@ -119,7 +116,7 @@ const TreeMenu = ({
context={ context={
context || ( context || (
<IconButton size='small'> <IconButton size='small'>
<Icon type='icon-gengduo' /> <IconGengduo sx={{ fontSize: '14px' }} />
</IconButton> </IconButton>
) )
} }

View File

@ -1,8 +1,12 @@
import data from '@emoji-mart/data'; import data from '@emoji-mart/data';
import Picker from '@emoji-mart/react'; import Picker from '@emoji-mart/react';
import { Box, IconButton, Popover, SxProps } from '@mui/material'; import { Box, IconButton, Popover, SxProps } from '@mui/material';
import { Icon } from '@ctzhian/ui';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import {
IconWenjianjia,
IconWenjian,
IconWenjianjiaKai,
} from '@panda-wiki/icons';
import zh from '../../assets/emoji-data/zh.json'; import zh from '../../assets/emoji-data/zh.json';
interface EmojiPickerProps { interface EmojiPickerProps {
@ -66,17 +70,14 @@ const EmojiPicker: React.FC<EmojiPickerProps> = ({
<Box component='span' sx={{ fontSize: 14, ...iconSx }}> <Box component='span' sx={{ fontSize: 14, ...iconSx }}>
{value} {value}
</Box> </Box>
) : type === 1 ? (
collapsed ? (
<IconWenjianjia sx={{ fontSize: 16, ...iconSx }} />
) : (
<IconWenjianjiaKai sx={{ fontSize: 16, ...iconSx }} />
)
) : ( ) : (
<Icon <IconWenjian sx={{ fontSize: 16, ...iconSx }} />
type={
type === 1
? collapsed
? 'icon-wenjianjia'
: 'icon-wenjianjia-kai'
: 'icon-wenjian'
}
sx={{ fontSize: 16, ...iconSx }}
/>
)} )}
</IconButton> </IconButton>
<Popover <Popover

View File

@ -1,6 +1,6 @@
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { Box, Stack, useTheme } from '@mui/material'; import { Box, Stack, useTheme } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconXiala } from '@panda-wiki/icons';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { NavLink, useLocation } from 'react-router-dom'; import { NavLink, useLocation } from 'react-router-dom';
import KBSelect from '../KB/KBSelect'; import KBSelect from '../KB/KBSelect';
@ -76,10 +76,7 @@ const Bread = () => {
...(idx === breads.length - 1 && { fontWeight: 'bold' }), ...(idx === breads.length - 1 && { fontWeight: 'bold' }),
}} }}
> >
<Icon <IconXiala sx={{ fontSize: 20, transform: 'rotate(-90deg)' }} />
type='icon-xiala'
sx={{ fontSize: 20, transform: 'rotate(-90deg)' }}
/>
{it.to === 'custom' ? ( {it.to === 'custom' ? (
<Box <Box
sx={{ cursor: 'pointer', ':hover': { color: 'primary.main' } }} sx={{ cursor: 'pointer', ':hover': { color: 'primary.main' } }}

View File

@ -3,11 +3,12 @@ import { useAppSelector, useAppDispatch } from '@/store';
import { setKbDetail } from '@/store/slices/config'; import { setKbDetail } from '@/store/slices/config';
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline'; import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
import { Button, IconButton, Stack, Tooltip } from '@mui/material'; import { Button, IconButton, Stack, Tooltip } from '@mui/material';
import { Icon, message, Modal } from '@ctzhian/ui'; import { message, Modal } from '@ctzhian/ui';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import System from '../System'; import System from '../System';
import Bread from './Bread'; import Bread from './Bread';
import { IconDengchu } from '@panda-wiki/icons';
const Header = () => { const Header = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@ -94,7 +95,7 @@ const Header = () => {
setLogoutConfirmOpen(true); setLogoutConfirmOpen(true);
}} }}
> >
<Icon type='icon-dengchu' sx={{ fontSize: 18 }} /> <IconDengchu sx={{ fontSize: 18 }} />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
</Stack> </Stack>

View File

@ -4,7 +4,13 @@ import { useFeatureValue } from '@/hooks';
import { ConstsUserRole } from '@/request/types'; import { ConstsUserRole } from '@/request/types';
import { useAppDispatch, useAppSelector } from '@/store'; import { useAppDispatch, useAppSelector } from '@/store';
import { setKbC, setKbId } from '@/store/slices/config'; import { setKbC, setKbId } from '@/store/slices/config';
import { Ellipsis, Icon, message } from '@ctzhian/ui'; import { Ellipsis, message } from '@ctzhian/ui';
import {
IconXiala,
IconZuzhi,
IconTianjiawendang,
IconShanchu,
} from '@panda-wiki/icons';
import { import {
Box, Box,
Button, Button,
@ -69,8 +75,7 @@ const KBSelect = () => {
}} }}
IconComponent={({ className, ...rest }) => { IconComponent={({ className, ...rest }) => {
return ( return (
<Icon <IconXiala
type='icon-xiala'
className={className + ' icon-xiala'} className={className + ' icon-xiala'}
sx={{ sx={{
position: 'absolute', position: 'absolute',
@ -148,8 +153,7 @@ const KBSelect = () => {
gap={1.5} gap={1.5}
sx={{ width: '100%' }} sx={{ width: '100%' }}
> >
<Icon <IconZuzhi
type='icon-zuzhi'
sx={{ fontSize: 14, color: 'text.secondary', flexShrink: 0 }} sx={{ fontSize: 14, color: 'text.secondary', flexShrink: 0 }}
/> />
<Ellipsis>{item.name}</Ellipsis> <Ellipsis>{item.name}</Ellipsis>
@ -166,8 +170,7 @@ const KBSelect = () => {
setModifyOpen(true); setModifyOpen(true);
}} }}
> >
<Icon <IconTianjiawendang
type='icon-tianjiawendang'
sx={{ sx={{
fontSize: 14, fontSize: 14,
color: 'text.tertiary', color: 'text.tertiary',
@ -185,8 +188,7 @@ const KBSelect = () => {
setDeleteOpen(true); setDeleteOpen(true);
}} }}
> >
<Icon <IconShanchu
type='icon-shanchu'
sx={{ sx={{
fontSize: 14, fontSize: 14,
color: 'text.tertiary', color: 'text.tertiary',

View File

@ -1,155 +0,0 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { TrendData } from '@/api';
import { useThemeMode } from '@ctzhian/ui';
import * as echarts from 'echarts';
import { useEffect, useRef, useState } from 'react';
type ECharts = ReturnType<typeof echarts.init>;
export interface PropsData {
chartData: TrendData[];
height: number;
size?: 'small' | 'large';
}
const LineTrend = ({ chartData = [], height, size = 'large' }: PropsData) => {
const { mode } = useThemeMode();
const domWrapRef = useRef<HTMLDivElement>(null!);
const echartRef = useRef<ECharts>(null!);
const [loading, setLoading] = useState(true);
const [data, setData] = useState<TrendData[]>([]);
useEffect(() => {
if (domWrapRef.current) {
echartRef.current = echarts.init(domWrapRef.current, null, {
renderer: 'svg',
});
}
setData(chartData);
}, [chartData]);
useEffect(() => {
const option = {
grid: {
left: 0,
right: 0,
bottom: 10,
top: 10,
},
tooltip: {
trigger: 'axis',
position: function (
point: number[],
_params: any,
_dom: any,
_rect: any,
size: any,
) {
return [point[0] - size.contentSize[0], point[1] + 20];
},
axisPointer: {
type: 'shadow',
},
formatter: (
params: { name: string; seriesName: string; value: number }[],
) => {
if (params[0]) {
const { name, seriesName, value } = params[0];
return `<div style="font-family: G;">${name}<div>${seriesName} ${value}</div></div>`;
}
return '';
},
},
xAxis: {
type: 'category',
data: data.map(it => it.name),
splitLine: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
axisLabel: {
show: false,
},
},
yAxis: {
type: 'value',
splitNumber: 4,
axisLine: {
show: false,
},
axisTick: {
show: false,
},
axisLabel: {
show: false,
},
splitLine:
size === 'small'
? false
: {
lineStyle: {
type: 'dashed',
color: '#F2F3F5',
},
},
},
series: {
name: '问答次数',
symbol: 'none',
type: 'line',
smooth: true,
data: data.map(it => it.count),
lineStyle: {
color: {
type: 'linear',
x: 0, // 起点 x 坐标0: 左侧)
y: 0, // 起点 y 坐标0: 顶部)
x2: 1, // 终点 x 坐标1: 右侧)
y2: 1, // 终点 y 坐标0: 保持顶部,形成水平渐变)
colorStops: [
{ offset: 0, color: '#9E68FC' }, // 起始颜色
{ offset: 1, color: '#3248F2' }, // 结束颜色
],
},
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(158,104,252,0.1)' },
{ offset: 1, color: 'rgba(50,72,242,0)' },
],
global: false,
},
},
},
};
if (domWrapRef.current && echartRef.current) {
echartRef.current.setOption(option);
setLoading(false);
}
const resize = () => {
if (echartRef.current) {
echartRef.current.resize();
}
};
window.addEventListener('resize', resize);
return () => window.removeEventListener('resize', resize);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [data, mode]);
if (data.length === 0 && !loading)
return <div style={{ width: '100%', height }} />;
return <div ref={domWrapRef} style={{ width: '100%', height }} />;
};
export default LineTrend;

View File

@ -1,6 +1,5 @@
import { addOpacityToColor, copyText } from '@/utils'; import { addOpacityToColor, copyText } from '@/utils';
import { Box, IconButton, useTheme } from '@mui/material'; import { Box, IconButton, useTheme } from '@mui/material';
import { Icon } from '@ctzhian/ui';
import 'katex/dist/katex.min.css'; import 'katex/dist/katex.min.css';
import React, { useState } from 'react'; import React, { useState } from 'react';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
@ -12,6 +11,7 @@ import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
import remarkBreaks from 'remark-breaks'; import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm'; import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math'; import remarkMath from 'remark-math';
import { IconXiajiantou } from '@panda-wiki/icons';
interface MarkDownProps { interface MarkDownProps {
loading?: boolean; loading?: boolean;
@ -117,8 +117,7 @@ const MarkDown = ({ loading = false, content }: MarkDownProps) => {
}, },
}} }}
> >
<Icon <IconXiajiantou
type='icon-xiajiantou'
sx={{ sx={{
fontSize: 18, fontSize: 18,
flexShrink: 0, flexShrink: 0,

View File

@ -1,13 +1,14 @@
import { copyText } from '@/utils'; import { copyText } from '@/utils';
import { Box, Stack } from '@mui/material'; import { Box, Stack } from '@mui/material';
import { Ellipsis, Icon } from '@ctzhian/ui'; import { Ellipsis } from '@ctzhian/ui';
import { IconFuzhi } from '@panda-wiki/icons';
interface ShowTextProps { interface ShowTextProps {
text: string[]; text: string[];
copyable?: boolean; copyable?: boolean;
showIcon?: boolean; showIcon?: boolean;
noEllipsis?: boolean; noEllipsis?: boolean;
icon?: string; icon?: React.ReactNode;
onClick?: () => void; onClick?: () => void;
} }
@ -15,7 +16,9 @@ const ShowText = ({
text, text,
copyable = true, copyable = true,
showIcon = true, showIcon = true,
icon = 'icon-fuzhi', icon = (
<IconFuzhi sx={{ fontSize: 16, color: 'text.disabled', flexShrink: 0 }} />
),
onClick, onClick,
noEllipsis = false, noEllipsis = false,
}: ShowTextProps) => { }: ShowTextProps) => {
@ -62,12 +65,7 @@ const ShowText = ({
), ),
)} )}
</Stack> </Stack>
{showIcon && ( {showIcon && icon}
<Icon
type={icon}
sx={{ fontSize: 16, color: 'text.disabled', flexShrink: 0 }}
/>
)}
</Stack> </Stack>
); );
}; };

View File

@ -12,7 +12,8 @@ import { useVersionInfo } from '@/hooks';
import { useAppDispatch, useAppSelector } from '@/store'; import { useAppDispatch, useAppSelector } from '@/store';
import { setLicense } from '@/store/slices/config'; import { setLicense } from '@/store/slices/config';
import { Box, Button, IconButton, Stack, TextField } from '@mui/material'; import { Box, Button, IconButton, Stack, TextField } from '@mui/material';
import { CusTabs, Icon, message, Modal } from '@ctzhian/ui'; import { CusTabs, message, Modal } from '@ctzhian/ui';
import { IconWenjian, IconIcon_tool_close } from '@panda-wiki/icons';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useState } from 'react'; import { useState } from 'react';
import LottieIcon from '../LottieIcon'; import LottieIcon from '../LottieIcon';
@ -312,11 +313,11 @@ const AuthTypeModal = ({
}} }}
> >
<Stack direction={'row'} alignItems={'center'} gap={1}> <Stack direction={'row'} alignItems={'center'} gap={1}>
<Icon type='icon-wenjian' /> <IconWenjian sx={{ fontSize: 16 }} />
{file.name} {file.name}
</Stack> </Stack>
<IconButton onClick={() => setFile(undefined)}> <IconButton onClick={() => setFile(undefined)}>
<Icon type='icon-icon_tool_close' sx={{ fontSize: 16 }} /> <IconIcon_tool_close sx={{ fontSize: 16 }} />
</IconButton> </IconButton>
</Stack> </Stack>
)} )}

View File

@ -3,19 +3,31 @@ import Qrcode from '@/assets/images/qrcode.png';
import { Box, Button, Stack, Typography, useTheme } from '@mui/material'; import { Box, Button, Stack, Typography, useTheme } from '@mui/material';
import { ConstsUserKBPermission } from '@/request/types'; import { ConstsUserKBPermission } from '@/request/types';
import { Icon, Modal } from '@ctzhian/ui'; import { Modal } from '@ctzhian/ui';
import { useState, useMemo, useEffect } from 'react'; import { useState, useMemo, useEffect } from 'react';
import { NavLink, useLocation, useNavigate } from 'react-router-dom'; import { NavLink, useLocation, useNavigate } from 'react-router-dom';
import Avatar from '../Avatar'; import Avatar from '../Avatar';
import Version from './Version'; import Version from './Version';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import {
IconBangzhuwendang1,
IconNeirongguanli,
IconTongjifenxi1,
IconJushou,
IconGongxian,
IconPaperFull,
IconDuihualishi1,
IconChilun,
IconGroup,
IconGithub,
} from '@panda-wiki/icons';
const MENUS = [ const MENUS = [
{ {
label: '文档', label: '文档',
value: '/', value: '/',
pathname: 'document', pathname: 'document',
icon: 'icon-neirongguanli', icon: IconNeirongguanli,
show: true, show: true,
perms: [ perms: [
ConstsUserKBPermission.UserKBPermissionFullControl, ConstsUserKBPermission.UserKBPermissionFullControl,
@ -26,7 +38,7 @@ const MENUS = [
label: '统计', label: '统计',
value: '/stat', value: '/stat',
pathname: 'stat', pathname: 'stat',
icon: 'icon-tongjifenxi1', icon: IconTongjifenxi1,
show: true, show: true,
perms: [ perms: [
ConstsUserKBPermission.UserKBPermissionFullControl, ConstsUserKBPermission.UserKBPermissionFullControl,
@ -37,7 +49,7 @@ const MENUS = [
label: '贡献', label: '贡献',
value: '/contribution', value: '/contribution',
pathname: 'contribution', pathname: 'contribution',
icon: 'icon-gongxian', icon: IconGongxian,
show: true, show: true,
perms: [ConstsUserKBPermission.UserKBPermissionFullControl], perms: [ConstsUserKBPermission.UserKBPermissionFullControl],
}, },
@ -45,7 +57,7 @@ const MENUS = [
label: '问答', label: '问答',
value: '/conversation', value: '/conversation',
pathname: 'conversation', pathname: 'conversation',
icon: 'icon-duihualishi1', icon: IconDuihualishi1,
show: true, show: true,
perms: [ perms: [
ConstsUserKBPermission.UserKBPermissionFullControl, ConstsUserKBPermission.UserKBPermissionFullControl,
@ -56,7 +68,7 @@ const MENUS = [
label: '反馈', label: '反馈',
value: '/feedback', value: '/feedback',
pathname: 'feedback', pathname: 'feedback',
icon: 'icon-jushou', icon: IconJushou,
show: true, show: true,
perms: [ perms: [
ConstsUserKBPermission.UserKBPermissionFullControl, ConstsUserKBPermission.UserKBPermissionFullControl,
@ -67,7 +79,7 @@ const MENUS = [
label: '发布', label: '发布',
value: '/release', value: '/release',
pathname: 'release', pathname: 'release',
icon: 'icon-paper-full', icon: IconPaperFull,
show: true, show: true,
perms: [ perms: [
ConstsUserKBPermission.UserKBPermissionFullControl, ConstsUserKBPermission.UserKBPermissionFullControl,
@ -78,7 +90,7 @@ const MENUS = [
label: '设置', label: '设置',
value: '/setting', value: '/setting',
pathname: 'application-setting', pathname: 'application-setting',
icon: 'icon-chilun', icon: IconChilun,
show: true, show: true,
perms: [ConstsUserKBPermission.UserKBPermissionFullControl], perms: [ConstsUserKBPermission.UserKBPermissionFullControl],
}, },
@ -153,6 +165,7 @@ const Sidebar = () => {
isActive = pathname.includes(it.value); isActive = pathname.includes(it.value);
} }
if (!it.show) return null; if (!it.show) return null;
const IconMenu = it.icon;
return ( return (
<NavLink <NavLink
key={it.pathname} key={it.pathname}
@ -181,8 +194,7 @@ const Sidebar = () => {
}, },
}} }}
> >
<Icon <IconMenu
type={it.icon}
sx={{ sx={{
fontSize: 14, fontSize: 14,
mr: 1, mr: 1,
@ -216,7 +228,7 @@ const Sidebar = () => {
}, },
}} }}
startIcon={ startIcon={
<Icon type='icon-bangzhuwendang1' sx={{ width: 14, height: 14 }} /> <IconBangzhuwendang1 sx={{ fontSize: '14px !important' }} />
} }
onClick={() => onClick={() =>
window.open('https://pandawiki.docs.baizhi.cloud/', '_blank') window.open('https://pandawiki.docs.baizhi.cloud/', '_blank')
@ -244,7 +256,7 @@ const Sidebar = () => {
color: 'primary.main', color: 'primary.main',
}, },
}} }}
startIcon={<Icon type='icon-GitHub' sx={{ width: 14, height: 14 }} />} startIcon={<IconGithub sx={{ fontSize: '14px !important' }} />}
onClick={() => onClick={() =>
window.open('https://github.com/chaitin/PandaWiki', '_blank') window.open('https://github.com/chaitin/PandaWiki', '_blank')
} }
@ -271,7 +283,7 @@ const Sidebar = () => {
}, },
}} }}
onClick={() => setShowQrcode(true)} onClick={() => setShowQrcode(true)}
startIcon={<Icon type='icon-group' sx={{ width: 14, height: 14 }} />} startIcon={<IconGroup sx={{ fontSize: '14px !important' }} />}
> >
线 线
</Button> </Button>

View File

@ -1,8 +1,5 @@
import Card from '@/components/Card';
import { Icon, message } from '@ctzhian/ui';
import { import {
Box, Box,
Button,
Stack, Stack,
TextField, TextField,
Select, Select,
@ -10,6 +7,8 @@ import {
InputAdornment, InputAdornment,
IconButton, IconButton,
} from '@mui/material'; } from '@mui/material';
import InfoOutlineSharpIcon from '@mui/icons-material/InfoOutlineSharp';
import KeySharpIcon from '@mui/icons-material/KeySharp';
import Visibility from '@mui/icons-material/Visibility'; import Visibility from '@mui/icons-material/Visibility';
import VisibilityOff from '@mui/icons-material/VisibilityOff'; import VisibilityOff from '@mui/icons-material/VisibilityOff';
import { useState, useEffect, forwardRef, useImperativeHandle } from 'react'; import { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
@ -107,8 +106,7 @@ const AutoModelConfig = forwardRef<AutoModelConfigRef, AutoModelConfigProps>(
border: '1px solid rgba(25, 118, 210, 0.2)', border: '1px solid rgba(25, 118, 210, 0.2)',
}} }}
> >
<Icon <InfoOutlineSharpIcon
type='icon-info-circle'
sx={{ sx={{
fontSize: 16, fontSize: 16,
color: 'primary.main', color: 'primary.main',
@ -170,7 +168,7 @@ const AutoModelConfig = forwardRef<AutoModelConfigRef, AutoModelConfigProps>(
gap: 0.5, gap: 0.5,
}} }}
> >
<Icon type='icon-key' sx={{ fontSize: 14 }} /> <KeySharpIcon sx={{ fontSize: 14, color: 'primary.main' }} />
API Key API Key
</Box> </Box>
</Box> </Box>

View File

@ -4,9 +4,10 @@ import Card from '@/components/Card';
import { copyText, generatePassword } from '@/utils'; import { copyText, generatePassword } from '@/utils';
import { CheckCircle } from '@mui/icons-material'; import { CheckCircle } from '@mui/icons-material';
import { Box, IconButton, Stack, TextField } from '@mui/material'; import { Box, IconButton, Stack, TextField } from '@mui/material';
import { Icon, Modal } from '@ctzhian/ui'; import { Modal } from '@ctzhian/ui';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { IconShuaxin } from '@panda-wiki/icons';
type UpdateMemberProps = { type UpdateMemberProps = {
user: V1UserListItemResp; user: V1UserListItemResp;
@ -163,7 +164,7 @@ const MemberUpdate = ({ user, refresh, type }: UpdateMemberProps) => {
onClick={() => setValue('password', generatePassword())} onClick={() => setValue('password', generatePassword())}
sx={{ flexShrink: 0 }} sx={{ flexShrink: 0 }}
> >
<Icon type='icon-shuaxin' /> <IconShuaxin sx={{ fontSize: 16 }} />
</IconButton> </IconButton>
</Stack> </Stack>
</Modal> </Modal>

View File

@ -8,7 +8,7 @@ import {
} from '@/request/Model'; } from '@/request/Model';
import { GithubComChaitinPandaWikiDomainModelListItem } from '@/request/types'; import { GithubComChaitinPandaWikiDomainModelListItem } from '@/request/types';
import { addOpacityToColor } from '@/utils'; import { addOpacityToColor } from '@/utils';
import { Icon, message, Modal } from '@ctzhian/ui'; import { message, Modal } from '@ctzhian/ui';
import { import {
Box, Box,
Button, Button,
@ -188,7 +188,7 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
const handleSave = async () => { const handleSave = async () => {
setIsSaving(true); setIsSaving(true);
try { try {
let requestData: { const requestData: {
mode: 'auto' | 'manual'; mode: 'auto' | 'manual';
auto_mode_api_key?: string; auto_mode_api_key?: string;
chat_model?: string; chat_model?: string;
@ -224,11 +224,37 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
); );
getModelList(); // 刷新模型列表 getModelList(); // 刷新模型列表
} catch (err) { } catch (err) {
console.error(err);
} finally { } finally {
setIsSaving(false); setIsSaving(false);
} }
}; };
const IconModel = chatModelData
? ModelProvider[chatModelData.provider as keyof typeof ModelProvider].icon
: null;
const IconEmbeddingModel = embeddingModelData
? ModelProvider[embeddingModelData.provider as keyof typeof ModelProvider]
.icon
: null;
const IconRerankModel = rerankModelData
? ModelProvider[rerankModelData.provider as keyof typeof ModelProvider]
.icon
: null;
const IconAnalysisModel = analysisModelData
? ModelProvider[analysisModelData.provider as keyof typeof ModelProvider]
.icon
: null;
const IconAnalysisVLModel = analysisVLModelData
? ModelProvider[
analysisVLModelData.provider as keyof typeof ModelProvider
].icon
: null;
return ( return (
<Stack gap={0}> <Stack gap={0}>
<Box <Box
@ -331,14 +357,7 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
> >
{chatModelData ? ( {chatModelData ? (
<> <>
<Icon {IconModel && <IconModel sx={{ fontSize: 18 }} />}
type={
ModelProvider[
chatModelData.provider as keyof typeof ModelProvider
].icon
}
sx={{ fontSize: 18 }}
/>
<Box <Box
sx={{ sx={{
fontSize: 14, fontSize: 14,
@ -540,14 +559,10 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
> >
{embeddingModelData ? ( {embeddingModelData ? (
<> <>
<Icon {IconEmbeddingModel && (
type={ <IconEmbeddingModel sx={{ fontSize: 18 }} />
ModelProvider[ )}
embeddingModelData.provider as keyof typeof ModelProvider
].icon
}
sx={{ fontSize: 18 }}
/>
<Box <Box
sx={{ sx={{
fontSize: 14, fontSize: 14,
@ -754,14 +769,10 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
> >
{rerankModelData ? ( {rerankModelData ? (
<> <>
<Icon {IconRerankModel && (
type={ <IconRerankModel sx={{ fontSize: 18 }} />
ModelProvider[ )}
rerankModelData.provider as keyof typeof ModelProvider
].icon
}
sx={{ fontSize: 18 }}
/>
<Box <Box
sx={{ sx={{
fontSize: 14, fontSize: 14,
@ -963,14 +974,10 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
> >
{analysisModelData ? ( {analysisModelData ? (
<> <>
<Icon {IconAnalysisModel && (
type={ <IconAnalysisModel sx={{ fontSize: 18 }} />
ModelProvider[ )}
analysisModelData.provider as keyof typeof ModelProvider
].icon
}
sx={{ fontSize: 18 }}
/>
<Box <Box
sx={{ sx={{
fontSize: 14, fontSize: 14,
@ -1172,14 +1179,9 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
> >
{analysisVLModelData ? ( {analysisVLModelData ? (
<> <>
<Icon {IconAnalysisVLModel && (
type={ <IconAnalysisVLModel sx={{ fontSize: 18 }} />
ModelProvider[ )}
analysisVLModelData.provider as keyof typeof ModelProvider
].icon
}
sx={{ fontSize: 18 }}
/>
<Box <Box
sx={{ sx={{
fontSize: 14, fontSize: 14,

View File

@ -1,22 +1,12 @@
import ErrorJSON from '@/assets/json/error.json';
import Card from '@/components/Card';
import { ModelProvider } from '@/constant/enums';
import { getApiV1ModelList } from '@/request/Model'; import { getApiV1ModelList } from '@/request/Model';
import { GithubComChaitinPandaWikiDomainModelListItem } from '@/request/types'; import { GithubComChaitinPandaWikiDomainModelListItem } from '@/request/types';
import { useAppDispatch, useAppSelector } from '@/store'; import { useAppDispatch, useAppSelector } from '@/store';
import { setModelList, setModelStatus } from '@/store/slices/config'; import { setModelList, setModelStatus } from '@/store/slices/config';
import { Icon, message, Modal } from '@ctzhian/ui'; import { Modal } from '@ctzhian/ui';
import { import { IconAChilunshezhisheding } from '@panda-wiki/icons';
Box, import { Box, Button, Tab, Tabs, useTheme } from '@mui/material';
Button,
Stack,
Tab,
Tabs,
Tooltip,
useTheme,
} from '@mui/material';
import { useEffect, useState, useRef } from 'react'; import { useEffect, useState, useRef } from 'react';
import LottieIcon from '../LottieIcon';
import Member from './component/Member'; import Member from './component/Member';
import ModelConfig, { ModelConfigRef } from './component/ModelConfig'; import ModelConfig, { ModelConfigRef } from './component/ModelConfig';
@ -91,7 +81,7 @@ const System = () => {
<Button <Button
size='small' size='small'
variant='outlined' variant='outlined'
startIcon={<Icon type='icon-a-chilunshezhisheding' />} startIcon={<IconAChilunshezhisheding />}
onClick={() => setOpen(true)} onClick={() => setOpen(true)}
> >

View File

@ -1,8 +1,8 @@
import { Icon } from '@ctzhian/ui';
import { Upload as UploadIcon } from '@mui/icons-material'; import { Upload as UploadIcon } from '@mui/icons-material';
import { Box, Button, Stack, Typography, useTheme } from '@mui/material'; import { Box, Button, Stack, Typography, useTheme } from '@mui/material';
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { FileRejection, useDropzone } from 'react-dropzone'; import { FileRejection, useDropzone } from 'react-dropzone';
import { IconShangchuan } from '@panda-wiki/icons';
// 文件扩展名到 MIME 类型的映射 // 文件扩展名到 MIME 类型的映射
const FILE_EXTENSION_TO_MIME: Record<string, string> = { const FILE_EXTENSION_TO_MIME: Record<string, string> = {
@ -110,8 +110,7 @@ const Upload = ({
onClick={() => fileInputRef.current?.click()} onClick={() => fileInputRef.current?.click()}
> >
<input {...getInputProps()} /> <input {...getInputProps()} />
<Icon <IconShangchuan
type='icon-shangchuan'
sx={{ fontSize: 40, mb: 1, color: 'text.secondary' }} sx={{ fontSize: 40, mb: 1, color: 'text.secondary' }}
/> />
<Typography <Typography

View File

@ -1,8 +1,8 @@
import { CheckCircle } from '@mui/icons-material'; import { CheckCircle } from '@mui/icons-material';
import { Box, Stack, Typography, useTheme, SxProps } from '@mui/material'; import { Box, Stack, Typography, useTheme, SxProps } from '@mui/material';
import { Icon } from '@ctzhian/ui';
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { useDropzone } from 'react-dropzone'; import { useDropzone } from 'react-dropzone';
import { IconShangchuan } from '@panda-wiki/icons';
interface FileTextProps { interface FileTextProps {
file?: File; file?: File;
@ -97,10 +97,7 @@ const FileText = ({
{dropFiles.length > 0 ? ( {dropFiles.length > 0 ? (
<CheckCircle sx={{ color: 'success.main', fontSize: 20 }} /> <CheckCircle sx={{ color: 'success.main', fontSize: 20 }} />
) : ( ) : (
<Icon <IconShangchuan sx={{ fontSize: 20, color: 'text.disabled' }} />
type='icon-shangchuan'
sx={{ fontSize: 20, color: 'text.disabled' }}
/>
)} )}
<Typography <Typography
variant='body1' variant='body1'

View File

@ -1,8 +1,9 @@
import { uploadFile } from '@/api'; import { uploadFile } from '@/api';
import { Box, IconButton, LinearProgress, Stack } from '@mui/material'; import { Box, IconButton, LinearProgress, Stack } from '@mui/material';
import { Icon, message } from '@ctzhian/ui'; import { message } from '@ctzhian/ui';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import CustomImage from '../CustomImage'; import CustomImage from '../CustomImage';
import { IconShangchuan, IconIcon_tool_close } from '@panda-wiki/icons';
interface UploadFileProps { interface UploadFileProps {
type: 'url' | 'base64'; type: 'url' | 'base64';
@ -241,7 +242,7 @@ const UploadFile = ({
onChange(''); onChange('');
}} }}
> >
<Icon type='icon-icon_tool_close' sx={{ color: '#fff' }} /> <IconIcon_tool_close sx={{ fontSize: 16, color: '#fff' }} />
</IconButton> </IconButton>
</> </>
) : ( ) : (
@ -253,8 +254,7 @@ const UploadFile = ({
fontSize: width ? (width < 40 ? 8 : 12) : 12, fontSize: width ? (width < 40 ? 8 : 12) : 12,
}} }}
> >
<Icon <IconShangchuan
type='icon-shangchuan'
sx={{ fontSize: width ? (width < 40 ? 12 : 18) : 18 }} sx={{ fontSize: width ? (width < 40 ? 12 : 18) : 18 }}
/> />
<Box>{label}</Box> <Box>{label}</Box>

View File

@ -1,501 +0,0 @@
export const CountryEnums = {
Afghanistan: 'af',
'Aland Islands': 'ax',
Albania: 'al',
Algeria: 'dz',
'American Samoa': 'as',
Andorra: 'ad',
Angola: 'ao',
Anguilla: 'ai',
Antarctica: 'aq',
'Antigua and Barbuda': 'ag',
Argentina: 'ar',
Armenia: 'am',
Aruba: 'aw',
'Ascension Island': 'sh-ac',
'Association of Southeast Asian Nations': 'asean',
Australia: 'au',
Austria: 'at',
Azerbaijan: 'az',
Bahamas: 'bs',
Bahrain: 'bh',
Bangladesh: 'bd',
Barbados: 'bb',
'Basque Country': 'es-pv',
Belarus: 'by',
Belgium: 'be',
Belize: 'bz',
Benin: 'bj',
Bermuda: 'bm',
Bhutan: 'bt',
Bolivia: 'bo',
'Bonaire, Sint Eustatius and Saba': 'bq',
'Bosnia and Herzegovina': 'ba',
Botswana: 'bw',
'Bouvet Island': 'bv',
Brazil: 'br',
'British Indian Ocean Territory': 'io',
'Brunei Darussalam': 'bn',
Bulgaria: 'bg',
'Burkina Faso': 'bf',
Burundi: 'bi',
'Cabo Verde': 'cv',
Cambodia: 'kh',
Cameroon: 'cm',
Canada: 'ca',
'Canary Islands': 'ic',
Catalonia: 'es-ct',
'Cayman Islands': 'ky',
'Central African Republic': 'cf',
'Central European Free Trade Agreement': 'cefta',
Chad: 'td',
Chile: 'cl',
China: 'cn',
'Christmas Island': 'cx',
'Clipperton Island': 'cp',
'Cocos (Keeling) Islands': 'cc',
Colombia: 'co',
Comoros: 'km',
'Cook Islands': 'ck',
'Costa Rica': 'cr',
Croatia: 'hr',
Cuba: 'cu',
Curaçao: 'cw',
Cyprus: 'cy',
'Czech Republic': 'cz',
"Côte d'Ivoire": 'ci',
'Democratic Republic of the Congo': 'cd',
Denmark: 'dk',
'Diego Garcia': 'dg',
Djibouti: 'dj',
Dominica: 'dm',
'Dominican Republic': 'do',
'East African Community': 'eac',
Ecuador: 'ec',
Egypt: 'eg',
'El Salvador': 'sv',
England: 'gb-eng',
'Equatorial Guinea': 'gq',
Eritrea: 'er',
Estonia: 'ee',
Eswatini: 'sz',
Ethiopia: 'et',
Europe: 'eu',
'Falkland Islands': 'fk',
'Faroe Islands': 'fo',
'Federated States of Micronesia': 'fm',
Fiji: 'fj',
Finland: 'fi',
France: 'fr',
'French Guiana': 'gf',
'French Polynesia': 'pf',
'French Southern Territories': 'tf',
Gabon: 'ga',
Galicia: 'es-ga',
Gambia: 'gm',
Georgia: 'ge',
Germany: 'de',
Ghana: 'gh',
Gibraltar: 'gi',
Greece: 'gr',
Greenland: 'gl',
Grenada: 'gd',
Guadeloupe: 'gp',
Guam: 'gu',
Guatemala: 'gt',
Guernsey: 'gg',
Guinea: 'gn',
'Guinea-Bissau': 'gw',
Guyana: 'gy',
Haiti: 'ht',
'Heard Island and McDonald Islands': 'hm',
'Holy See': 'va',
Honduras: 'hn',
'Hong Kong': 'hk',
Hungary: 'hu',
Iceland: 'is',
India: 'in',
Indonesia: 'id',
Iran: 'ir',
Iraq: 'iq',
Ireland: 'ie',
'Isle of Man': 'im',
Israel: 'il',
Italy: 'it',
Jamaica: 'jm',
Japan: 'jp',
Jersey: 'je',
Jordan: 'jo',
Kazakhstan: 'kz',
Kenya: 'ke',
Kiribati: 'ki',
Kosovo: 'xk',
Kuwait: 'kw',
Kyrgyzstan: 'kg',
Laos: 'la',
Latvia: 'lv',
'League of Arab States': 'arab',
Lebanon: 'lb',
Lesotho: 'ls',
Liberia: 'lr',
Libya: 'ly',
Liechtenstein: 'li',
Lithuania: 'lt',
Luxembourg: 'lu',
Macau: 'mo',
Madagascar: 'mg',
Malawi: 'mw',
Malaysia: 'my',
Maldives: 'mv',
Mali: 'ml',
Malta: 'mt',
'Marshall Islands': 'mh',
Martinique: 'mq',
Mauritania: 'mr',
Mauritius: 'mu',
Mayotte: 'yt',
Mexico: 'mx',
Moldova: 'md',
Monaco: 'mc',
Mongolia: 'mn',
Montenegro: 'me',
Montserrat: 'ms',
Morocco: 'ma',
Mozambique: 'mz',
Myanmar: 'mm',
Namibia: 'na',
Nauru: 'nr',
Nepal: 'np',
'The Netherlands': 'nl',
'New Caledonia': 'nc',
'New Zealand': 'nz',
Nicaragua: 'ni',
Niger: 'ne',
Nigeria: 'ng',
Niue: 'nu',
'Norfolk Island': 'nf',
'North Korea': 'kp',
'North Macedonia': 'mk',
'Northern Ireland': 'gb-nir',
'Northern Mariana Islands': 'mp',
Norway: 'no',
Oman: 'om',
'Pacific Community': 'pc',
Pakistan: 'pk',
Palau: 'pw',
Panama: 'pa',
'Papua New Guinea': 'pg',
Paraguay: 'py',
Peru: 'pe',
Philippines: 'ph',
Pitcairn: 'pn',
Poland: 'pl',
Portugal: 'pt',
'Puerto Rico': 'pr',
Qatar: 'qa',
'Republic of the Congo': 'cg',
Romania: 'ro',
Russia: 'ru',
Rwanda: 'rw',
Réunion: 're',
'Saint Barthélemy': 'bl',
'Saint Helena': 'sh-hl',
'Saint Helena, Ascension and Tristan da Cunha': 'sh',
'Saint Kitts and Nevis': 'kn',
'Saint Lucia': 'lc',
'Saint Martin': 'mf',
'Saint Pierre and Miquelon': 'pm',
'Saint Vincent and the Grenadines': 'vc',
Samoa: 'ws',
'San Marino': 'sm',
'Sao Tome and Principe': 'st',
'Saudi Arabia': 'sa',
Scotland: 'gb-sct',
Senegal: 'sn',
Serbia: 'rs',
Seychelles: 'sc',
'Sierra Leone': 'sl',
Singapore: 'sg',
'Sint Maarten': 'sx',
Slovakia: 'sk',
Slovenia: 'si',
'Solomon Islands': 'sb',
Somalia: 'so',
'South Africa': 'za',
'South Georgia and the South Sandwich Islands': 'gs',
'South Korea': 'kr',
'South Sudan': 'ss',
Spain: 'es',
'Sri Lanka': 'lk',
'State of Palestine': 'ps',
Sudan: 'sd',
Suriname: 'sr',
'Svalbard and Jan Mayen': 'sj',
Sweden: 'se',
Switzerland: 'ch',
Syria: 'sy',
Taiwan: 'tw',
Tajikistan: 'tj',
Tanzania: 'tz',
Thailand: 'th',
'Timor-Leste': 'tl',
Togo: 'tg',
Tokelau: 'tk',
Tonga: 'to',
'Trinidad and Tobago': 'tt',
'Tristan da Cunha': 'sh-ta',
Tunisia: 'tn',
Turkmenistan: 'tm',
'Turks and Caicos Islands': 'tc',
Tuvalu: 'tv',
Türkiye: 'tr',
Uganda: 'ug',
Ukraine: 'ua',
'United Arab Emirates': 'ae',
'United Kingdom': 'gb',
'United Nations': 'un',
'United States': 'us',
Unknown: 'xx',
Uruguay: 'uy',
Uzbekistan: 'uz',
Vanuatu: 'vu',
Venezuela: 've',
Vietnam: 'vn',
'Viet Nam': 'vn',
'Virgin Islands (British)': 'vg',
'Virgin Islands (U.S.)': 'vi',
Wales: 'gb-wls',
'Wallis and Futuna': 'wf',
'Western Sahara': 'eh',
Yemen: 'ye',
Zambia: 'zm',
Zimbabwe: 'zw',
: 'xx',
: 'bt',
: 'tl',
: 'cn',
: 'cf',
: 'dk',
: 'ua',
: 'uz',
: 'ug',
: 'uy',
: 'td',
: 'ye',
: 'am',
: 'il',
: 'iq',
: 'ir',
: 'bz',
: 'cv',
: 'ru',
: 'bg',
: 'hr',
'关岛(美国)': 'gu',
: 'gm',
: 'is',
: 'gn',
: 'gw',
: 'li',
'刚果(金)': 'cd',
: 'cg',
: 'ly',
: 'lr',
: 'ca',
: 'gh',
: 'ga',
: 'hu',
: 'kp',
'北马里亚纳群岛(美国)': 'mp',
: 'ss',
: 'za',
: 'bw',
: 'qa',
: 'rw',
: 'lu',
: 'in',
西: 'id',
: 'gt',
: 'ec',
: 'er',
: 'sy',
: 'cu',
'台湾(中国)': 'tw',
: 'kg',
: 'dj',
: 'kz',
: 'co',
: 'cr',
: 'cm',
: '简称',
: 'tv',
: 'tm',
: 'tr',
西: 'lc',
: 'kn',
西: 'st',
: 'vc',
'圣皮埃尔和密克隆岛(法国)': 'pm',
: 'sh',
: 'sm',
: 'gy',
: 'tz',
: 'eg',
: 'et',
: 'ki',
: 'tj',
: 'sn',
: 'rs',
: 'sl',
: 'cy',
: 'sc',
西: 'mx',
: 'tg',
: 'dm',
: 'do',
: 'at',
: 've',
: 'bd',
: 'ao',
: 'ai',
: 'ag',
: 'ad',
西: 'fm',
: 'ni',
: 'ng',
: 'ne',
: 'np',
: 'ps',
: 'bs',
: 'pk',
: 'bb',
: 'pg',
: 'py',
: 'pa',
: 'bh',
西: 'br',
: 'bf',
: 'bi',
: 'gr',
: 'pw',
'库克群岛(新西兰)': 'ck',
'开曼群岛(英国)': 'ky',
: 'de',
: 'it',
: 'sb',
: 'tk',
: 'lv',
: 'no',
: 'cz',
: 'md',
: 'ma',
: 'mc',
: 'bn',
: 'fj',
: 'sz',
: 'sk',
: 'si',
: 'lk',
: 'sg',
'新喀里多尼亚(法国)': 'nc',
西: 'nz',
: 'jp',
: 'cl',
: 'kh',
: 'gd',
: 'gl',
: 'ge',
: 'be',
: 'mr',
: 'mu',
: 'to',
: 'sa',
: '',
: 'fr',
'法属圭亚那(法国)': 'gf',
西: 'pf',
'法罗群岛(丹麦)': 'fo',
: 'pl',
'波多黎各(美国)': 'pr',
: 'ba',
: 'th',
: 'zw',
: 'hn',
: 'ht',
: 'au',
'澳门(中国)': 'mo',
: 'ie',
: 'ee',
: 'jm',
'特克斯和凯科斯群岛(英国)': 'tc',
: 'tt',
: 'bo',
: 'nr',
: 'se',
: 'ch',
: 'gp',
'瓦利斯和富图纳群岛(法国)': 'wf',
: 'vu',
'留尼汪(法国)': 're',
: 'by',
: 'bm',
'直布罗陀(英国)': 'gi',
: 'kw',
: 'km',
: 'ci',
: 'pe',
: 'tn',
: 'lt',
: 'so',
: 'jo',
: 'na',
: 'nu',
: 'mm',
: 'ro',
: 'us',
'美属萨摩亚(美国)': 'as',
: 'la',
: 'ke',
: 'fi',
: 'sd',
: 'sr',
: 'gb',
'英属维京群岛(英国)': 'vg',
: 'nl',
: '',
: 'mz',
: 'ls',
: 'ph',
: 'sv',
: 'ws',
: 'pt',
: 'mn',
'蒙塞拉特岛(英国)': 'ms',
西: 'es',
: 'bj',
: 'zm',
: 'gq',
: 'vn',
: 'az',
: 'af',
: 'dz',
: 'al',
: 'ae',
: 'om',
: 'ar',
: 'aw',
: 'kr',
'香港(中国)': 'hk',
: 'mk',
: 'mv',
: 'mw',
'马提尼克(法国)': 'mq',
西: 'my',
: 'yt',
: 'mh',
: 'mt',
: 'mg',
: 'ml',
: 'lb',
: 'me',
};

View File

@ -1,3 +1,54 @@
import {
IconAWebyingyong,
IconWangyeguajian,
IconDingdingjiqiren,
IconWendajiqiren,
IconFeishujiqiren,
IconQiyeweixinjiqiren,
IconQiyeweixinkefu,
IconADiscordjiqiren,
IconWeixingongzhonghaoDaiyanse,
IconBaizhiyunlogo,
IconZhipuqingyan,
IconDeepseek,
IconTengxunhunyuan,
IconAliyunbailian,
IconHuoshanyinqing,
IconAzure,
IconGemini,
IconQiniuyun,
IconOllama,
IconAZiyuan2,
IconKim,
IconXinference,
IconGpustack,
IconLingyiwanwu,
IconChatgpt,
IconAAIshezhi,
IconHyperbolic,
IconPerplexity,
IconTianyiyun,
IconTengxunyun,
IconBaiduyun,
IconModaGPT,
IconInfini,
IconStep,
IconLanyun,
IconAlayanew,
IconPpio,
IconAihubmix,
IconOcoolai,
IconDMXAPI,
IconBurncloud,
IconYingweida,
IconTokenflux,
IconA302ai,
IconCephalon,
IconFireworks,
IconMistral,
IconOpenrouter,
} from '@panda-wiki/icons';
export const PageStatus = { export const PageStatus = {
1: { 1: {
label: '正在处理', label: '正在处理',
@ -30,47 +81,47 @@ export const IconMap = {
export const AppType = { export const AppType = {
1: { 1: {
label: 'Wiki 网站', label: 'Wiki 网站',
icon: 'icon-a-Webyingyong', icon: IconAWebyingyong,
}, },
2: { 2: {
label: '网页挂件', label: '网页挂件',
icon: 'icon-wangyeguajian', icon: IconWangyeguajian,
}, },
3: { 3: {
label: '钉钉机器人', label: '钉钉机器人',
icon: 'icon-dingdingjiqiren', icon: IconDingdingjiqiren,
}, },
4: { 4: {
label: '飞书机器人', label: '飞书机器人',
icon: 'icon-feishujiqiren', icon: IconFeishujiqiren,
}, },
5: { 5: {
label: '企业微信机器人', label: '企业微信机器人',
icon: 'icon-qiyeweixinjiqiren', icon: IconQiyeweixinjiqiren,
}, },
6: { 6: {
label: '企业微信客服', label: '企业微信客服',
icon: 'icon-qiyeweixinkefu', icon: IconQiyeweixinkefu,
}, },
7: { 7: {
label: 'Discord 机器人', label: 'Discord 机器人',
icon: 'icon-a-discordjiqiren', icon: IconADiscordjiqiren,
}, },
8: { 8: {
label: '微信公众号', label: '微信公众号',
icon: 'icon-weixingongzhonghao-daiyanse', icon: IconWeixingongzhonghaoDaiyanse,
}, },
9: { 9: {
label: '问答机器人 API', label: '问答机器人 API',
icon: 'icon-Wendajiqiren', icon: IconWendajiqiren,
}, },
10: { 10: {
label: '企业微信智能机器人', label: '企业微信智能机器人',
icon: 'icon-qiyeweixinjiqiren', icon: IconQiyeweixinjiqiren,
}, },
11: { 11: {
label: 'Lark 机器人', label: 'Lark 机器人',
icon: 'icon-feishujiqiren', icon: IconFeishujiqiren,
}, },
}; };
@ -115,7 +166,7 @@ export const ModelProvider = {
BaiZhiCloud: { BaiZhiCloud: {
label: 'BaiZhiCloud', label: 'BaiZhiCloud',
cn: '百智云', cn: '百智云',
icon: 'icon-baizhiyunlogo', icon: IconBaizhiyunlogo,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -129,7 +180,7 @@ export const ModelProvider = {
ZhiPu: { ZhiPu: {
label: 'ZhiPu', label: 'ZhiPu',
cn: '智谱', cn: '智谱',
icon: 'icon-zhipuqingyan', // 需要添加对应的图标 icon: IconZhipuqingyan, // 需要添加对应的图标
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -143,7 +194,7 @@ export const ModelProvider = {
DeepSeek: { DeepSeek: {
label: 'DeepSeek', label: 'DeepSeek',
cn: 'DeepSeek', cn: 'DeepSeek',
icon: 'icon-deepseek', icon: IconDeepseek,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -157,7 +208,7 @@ export const ModelProvider = {
Hunyuan: { Hunyuan: {
label: 'Hunyuan', label: 'Hunyuan',
cn: '腾讯混元', cn: '腾讯混元',
icon: 'icon-tengxunhunyuan', icon: IconTengxunhunyuan,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -171,7 +222,7 @@ export const ModelProvider = {
BaiLian: { BaiLian: {
label: 'BaiLian', label: 'BaiLian',
cn: '阿里云百炼', cn: '阿里云百炼',
icon: 'icon-aliyunbailian', icon: IconAliyunbailian,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -186,7 +237,7 @@ export const ModelProvider = {
Volcengine: { Volcengine: {
label: 'Volcengine', label: 'Volcengine',
cn: '火山引擎', cn: '火山引擎',
icon: 'icon-huoshanyinqing', icon: IconHuoshanyinqing,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -200,7 +251,7 @@ export const ModelProvider = {
OpenAI: { OpenAI: {
label: 'OpenAI', label: 'OpenAI',
cn: 'OpenAI', cn: 'OpenAI',
icon: 'icon-chatgpt', icon: IconChatgpt,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -214,7 +265,7 @@ export const ModelProvider = {
Ollama: { Ollama: {
label: 'Ollama', label: 'Ollama',
cn: 'Ollama', cn: 'Ollama',
icon: 'icon-ollama', icon: IconOllama,
urlWrite: true, urlWrite: true,
secretRequired: false, secretRequired: false,
customHeader: true, customHeader: true,
@ -228,7 +279,7 @@ export const ModelProvider = {
SiliconFlow: { SiliconFlow: {
label: 'SiliconFlow', label: 'SiliconFlow',
cn: '硅基流动', cn: '硅基流动',
icon: 'icon-a-ziyuan2', icon: IconAZiyuan2,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -242,7 +293,7 @@ export const ModelProvider = {
Moonshot: { Moonshot: {
label: 'Moonshot', label: 'Moonshot',
cn: '月之暗面', cn: '月之暗面',
icon: 'icon-Kim', icon: IconKim,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -256,7 +307,7 @@ export const ModelProvider = {
AzureOpenAI: { AzureOpenAI: {
label: 'AzureOpenAI', label: 'AzureOpenAI',
cn: 'Azure OpenAI', cn: 'Azure OpenAI',
icon: 'icon-azure', icon: IconAzure,
urlWrite: true, urlWrite: true,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -271,7 +322,7 @@ export const ModelProvider = {
Gemini: { Gemini: {
label: 'Gemini', label: 'Gemini',
cn: 'Gemini', cn: 'Gemini',
icon: 'icon-gemini', icon: IconGemini,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -285,7 +336,7 @@ export const ModelProvider = {
Qiniu: { Qiniu: {
label: 'Qiniu', label: 'Qiniu',
cn: '七牛云', cn: '七牛云',
icon: 'icon-qiniuyun', icon: IconQiniuyun,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -339,7 +390,7 @@ export const ModelProvider = {
Xinference: { Xinference: {
label: 'Xinference', label: 'Xinference',
cn: 'Xinference', cn: 'Xinference',
icon: 'icon-Xinference', icon: IconXinference,
urlWrite: true, urlWrite: true,
secretRequired: false, secretRequired: false,
customHeader: false, customHeader: false,
@ -355,7 +406,7 @@ export const ModelProvider = {
gpustack: { gpustack: {
label: 'gpustack', label: 'gpustack',
cn: 'GPUStack', cn: 'GPUStack',
icon: 'icon-gpustack', icon: IconGpustack,
urlWrite: true, urlWrite: true,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -370,7 +421,7 @@ export const ModelProvider = {
Yi: { Yi: {
label: 'Yi', label: 'Yi',
cn: '零一万物', cn: '零一万物',
icon: 'icon-lingyiwanwu', icon: IconLingyiwanwu,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -445,7 +496,7 @@ export const ModelProvider = {
CTYun: { CTYun: {
label: 'CTYun', label: 'CTYun',
cn: '天翼云息壤', cn: '天翼云息壤',
icon: 'icon-tianyiyun', icon: IconTianyiyun,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -459,7 +510,7 @@ export const ModelProvider = {
TencentTI: { TencentTI: {
label: 'TencentTI', label: 'TencentTI',
cn: '腾讯云TI', cn: '腾讯云TI',
icon: 'icon-tengxunyun', icon: IconTengxunyun,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -473,7 +524,7 @@ export const ModelProvider = {
BaiDuQianFan: { BaiDuQianFan: {
label: 'BaiDuQianFan', label: 'BaiDuQianFan',
cn: '百度云千帆', cn: '百度云千帆',
icon: 'icon-baiduyun', icon: IconBaiduyun,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -487,7 +538,7 @@ export const ModelProvider = {
ModelScope: { ModelScope: {
label: 'ModelScope', label: 'ModelScope',
cn: '魔搭社区', cn: '魔搭社区',
icon: 'icon-modaGPT', icon: IconModaGPT,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -502,7 +553,7 @@ export const ModelProvider = {
Infini: { Infini: {
label: 'Infini', label: 'Infini',
cn: '无问芯穹', cn: '无问芯穹',
icon: 'icon-infini', icon: IconInfini,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -517,7 +568,7 @@ export const ModelProvider = {
StepFun: { StepFun: {
label: 'StepFun', label: 'StepFun',
cn: '阶跃星辰', cn: '阶跃星辰',
icon: 'icon-step', icon: IconStep,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -531,7 +582,7 @@ export const ModelProvider = {
LanYun: { LanYun: {
label: 'LanYun', label: 'LanYun',
cn: '蓝耘科技', cn: '蓝耘科技',
icon: 'icon-lanyun', icon: IconLanyun,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -545,7 +596,7 @@ export const ModelProvider = {
AlayaNew: { AlayaNew: {
label: 'AlayaNew', label: 'AlayaNew',
cn: '九章智算云', cn: '九章智算云',
icon: 'icon-alayanew', icon: IconAlayanew,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -560,7 +611,7 @@ export const ModelProvider = {
PPIO: { PPIO: {
label: 'PPIO', label: 'PPIO',
cn: '欧派云', cn: '欧派云',
icon: 'icon-ppio', icon: IconPpio,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -575,7 +626,7 @@ export const ModelProvider = {
AiHubMix: { AiHubMix: {
label: 'AiHubMix', label: 'AiHubMix',
cn: 'AiHubMix', cn: 'AiHubMix',
icon: 'icon-aihubmix', icon: IconAihubmix,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -589,7 +640,7 @@ export const ModelProvider = {
OcoolAI: { OcoolAI: {
label: 'OcoolAI', label: 'OcoolAI',
cn: 'OcoolAI', cn: 'OcoolAI',
icon: 'icon-ocoolai', icon: IconOcoolai,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -603,7 +654,7 @@ export const ModelProvider = {
DMXAPI: { DMXAPI: {
label: 'DMXAPI', label: 'DMXAPI',
cn: 'DMXAPI', cn: 'DMXAPI',
icon: 'icon-DMXAPI', icon: IconDMXAPI,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -617,7 +668,7 @@ export const ModelProvider = {
BurnCloud: { BurnCloud: {
label: 'BurnCloud', label: 'BurnCloud',
cn: 'BurnCloud', cn: 'BurnCloud',
icon: 'icon-burncloud', icon: IconBurncloud,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -641,7 +692,7 @@ export const ModelProvider = {
Nvidia: { Nvidia: {
label: 'Nvidia', label: 'Nvidia',
cn: '英伟达', cn: '英伟达',
icon: 'icon-yingweida', icon: IconYingweida,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -655,7 +706,7 @@ export const ModelProvider = {
TokenFlux: { TokenFlux: {
label: 'TokenFlux', label: 'TokenFlux',
cn: 'TokenFlux', cn: 'TokenFlux',
icon: 'icon-tokenflux', icon: IconTokenflux,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -669,7 +720,7 @@ export const ModelProvider = {
AI302: { AI302: {
label: 'AI302', label: 'AI302',
cn: '302.AI', cn: '302.AI',
icon: 'icon-a-302ai', icon: IconA302ai,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -683,7 +734,7 @@ export const ModelProvider = {
Cephalon: { Cephalon: {
label: 'Cephalon', label: 'Cephalon',
cn: 'Cephalon', cn: 'Cephalon',
icon: 'icon-cephalon', icon: IconCephalon,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -697,7 +748,7 @@ export const ModelProvider = {
OpenRouter: { OpenRouter: {
label: 'OpenRouter', label: 'OpenRouter',
cn: 'OpenRouter', cn: 'OpenRouter',
icon: 'icon-openrouter', icon: IconOpenrouter,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -711,7 +762,7 @@ export const ModelProvider = {
Fireworks: { Fireworks: {
label: 'Fireworks', label: 'Fireworks',
cn: 'Fireworks', cn: 'Fireworks',
icon: 'icon-fireworks', icon: IconFireworks,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -725,7 +776,7 @@ export const ModelProvider = {
Mistral: { Mistral: {
label: 'Mistral', label: 'Mistral',
cn: 'Mistral', cn: 'Mistral',
icon: 'icon-Mistral', icon: IconMistral,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -739,7 +790,7 @@ export const ModelProvider = {
Perplexity: { Perplexity: {
label: 'Perplexity', label: 'Perplexity',
cn: 'Perplexity', cn: 'Perplexity',
icon: 'icon-perplexity', icon: IconPerplexity,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -753,7 +804,7 @@ export const ModelProvider = {
Hyperbolic: { Hyperbolic: {
label: 'Hyperbolic', label: 'Hyperbolic',
cn: 'Hyperbolic', cn: 'Hyperbolic',
icon: 'icon-hyperbolic', icon: IconHyperbolic,
urlWrite: false, urlWrite: false,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,
@ -767,7 +818,7 @@ export const ModelProvider = {
Other: { Other: {
label: 'Other', label: 'Other',
cn: '其他', cn: '其他',
icon: 'icon-a-AIshezhi', icon: IconAAIshezhi,
urlWrite: true, urlWrite: true,
secretRequired: true, secretRequired: true,
customHeader: false, customHeader: false,

View File

@ -11,8 +11,6 @@ import { BrowserRouter } from 'react-router-dom';
import App from './App'; import App from './App';
import store from './store'; import store from './store';
import '@/assets/fonts/iconfont';
dayjs.extend(duration); dayjs.extend(duration);
dayjs.extend(relativeTime); dayjs.extend(relativeTime);
dayjs.locale('zh-cn'); dayjs.locale('zh-cn');

View File

@ -4,9 +4,10 @@ import DragTree from '@/components/Drag/DragTree';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { convertToTree } from '@/utils/drag'; import { convertToTree } from '@/utils/drag';
import { Box, Checkbox, Stack } from '@mui/material'; import { Box, Checkbox, Stack } from '@mui/material';
import { Icon, Modal } from '@ctzhian/ui'; import { Modal } from '@ctzhian/ui';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { getApiV1NodeList } from '@/request/Node'; import { getApiV1NodeList } from '@/request/Node';
import { IconWenjianjiaKai } from '@panda-wiki/icons';
interface DocDeleteProps { interface DocDeleteProps {
open: boolean; open: boolean;
@ -48,7 +49,7 @@ const DocModal = ({ open, onClose, onOk }: DocDeleteProps) => {
setFolderIds(folderIds.includes('root') ? [] : ['root']); setFolderIds(folderIds.includes('root') ? [] : ['root']);
}} }}
/> />
<Icon type={'icon-wenjianjia-kai'} /> <IconWenjianjiaKai sx={{ fontSize: 16 }} />
<Box></Box> <Box></Box>
</Stack> </Stack>
<DragTree <DragTree

View File

@ -19,6 +19,7 @@ import {
} from '@mui/material'; } from '@mui/material';
import { Ellipsis, Icon, Modal } from '@ctzhian/ui'; import { Ellipsis, Icon, Modal } from '@ctzhian/ui';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { IconDitu_diqiu } from '@panda-wiki/icons';
const handleThinkingContent = (content: string) => { const handleThinkingContent = (content: string) => {
const thinkRegex = /<think>([\s\S]*?)(?:<\/think>|$)/g; const thinkRegex = /<think>([\s\S]*?)(?:<\/think>|$)/g;
@ -302,8 +303,7 @@ const Detail = ({
src={item.favicon} src={item.favicon}
sx={{ width: 18, height: 18 }} sx={{ width: 18, height: 18 }}
errorIcon={ errorIcon={
<Icon <IconDitu_diqiu
type='icon-ditu_diqiu'
sx={{ fontSize: 18, color: 'text.tertiary' }} sx={{ fontSize: 18, color: 'text.tertiary' }}
/> />
} }

View File

@ -1,7 +1,7 @@
import { useURLSearchParams } from '@/hooks'; import { useURLSearchParams } from '@/hooks';
import { IconButton, InputAdornment, Stack, TextField } from '@mui/material'; import { IconButton, InputAdornment, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui';
import { useState } from 'react'; import { useState } from 'react';
import { IconIcon_tool_close } from '@panda-wiki/icons';
const Search = () => { const Search = () => {
const [searchParams, setSearchParams] = useURLSearchParams(); const [searchParams, setSearchParams] = useURLSearchParams();
@ -37,8 +37,7 @@ const Search = () => {
}} }}
size='small' size='small'
> >
<Icon <IconIcon_tool_close
type='icon-icon_tool_close'
sx={{ fontSize: 14, color: 'text.tertiary' }} sx={{ fontSize: 14, color: 'text.tertiary' }}
/> />
</IconButton> </IconButton>
@ -70,8 +69,7 @@ const Search = () => {
}} }}
size='small' size='small'
> >
<Icon <IconIcon_tool_close
type='icon-icon_tool_close'
sx={{ fontSize: 14, color: 'text.tertiary' }} sx={{ fontSize: 14, color: 'text.tertiary' }}
/> />
</IconButton> </IconButton>

View File

@ -34,15 +34,12 @@ const Conversation = () => {
title: '问题', title: '问题',
render: (text: string, record) => { render: (text: string, record) => {
const isGroupChat = record.info?.user_info?.from === 1; const isGroupChat = record.info?.user_info?.from === 1;
const AppIcon =
AppType[record.app_type as keyof typeof AppType]?.icon || '';
return ( return (
<> <>
<Stack direction={'row'} alignItems={'center'} gap={1}> <Stack direction={'row'} alignItems={'center'} gap={1}>
<Icon <AppIcon sx={{ fontSize: 12 }}></AppIcon>
sx={{ fontSize: 12 }}
type={
AppType[record.app_type as keyof typeof AppType]?.icon || ''
}
/>
<Ellipsis <Ellipsis
className='primary-color' className='primary-color'
sx={{ cursor: 'pointer', flex: 1, width: 0 }} sx={{ cursor: 'pointer', flex: 1, width: 0 }}

View File

@ -1,6 +1,6 @@
import { ConstsCrawlerSource, postApiV1CrawlerParse } from '@/request'; import { ConstsCrawlerSource, postApiV1CrawlerParse } from '@/request';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { Ellipsis, Icon } from '@ctzhian/ui'; import { Ellipsis } from '@ctzhian/ui';
import { import {
alpha, alpha,
Box, Box,
@ -20,6 +20,7 @@ import { ListDataItem } from '..';
import StatusBackground from '../components/StatusBackground'; import StatusBackground from '../components/StatusBackground';
import StatusBadge from '../components/StatusBadge'; import StatusBadge from '../components/StatusBadge';
import { flattenCrawlerParseResponse } from '../util'; import { flattenCrawlerParseResponse } from '../util';
import { IconWenjianjia, IconWenjian } from '@panda-wiki/icons';
interface ListRenderItemProps { interface ListRenderItemProps {
depth: number; depth: number;
@ -182,15 +183,9 @@ const ListRenderItem = ({
)} )}
<Box sx={{ ml: depth * 3 }}> <Box sx={{ ml: depth * 3 }}>
{!data.file ? ( {!data.file ? (
<Icon <IconWenjianjia sx={{ fontSize: 14, width: 20, ml: '10px' }} />
type='icon-wenjianjia'
sx={{ fontSize: 14, width: 20, ml: '10px' }}
/>
) : ( ) : (
<Icon <IconWenjian sx={{ fontSize: 14, width: 20, ml: '10px' }} />
type='icon-wenjian'
sx={{ fontSize: 14, width: 20, ml: '10px' }}
/>
)} )}
</Box> </Box>
</ListItemIcon> </ListItemIcon>

View File

@ -33,6 +33,7 @@ import { useEffect, useMemo, useState } from 'react';
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { BUSINESS_VERSION_PERMISSION } from '@/constant/version'; import { BUSINESS_VERSION_PERMISSION } from '@/constant/version';
import { VersionCanUse } from '@/components/VersionMask'; import { VersionCanUse } from '@/components/VersionMask';
import { IconShuaxin } from '@panda-wiki/icons';
interface DocPropertiesModalProps { interface DocPropertiesModalProps {
open: boolean; open: boolean;
@ -472,13 +473,13 @@ const DocPropertiesModal = ({
onClick={onGenerateSummary} onClick={onGenerateSummary}
disabled={loading} disabled={loading}
startIcon={ startIcon={
<Icon <IconShuaxin
type='icon-shuaxin' sx={{
sx={ fontSize: '16px !important',
loading ...(loading
? { animation: 'loadingRotate 1s linear infinite' } ? { animation: 'loadingRotate 1s linear infinite' }
: {} : {}),
} }}
/> />
} }
> >

View File

@ -1,6 +1,6 @@
import { useURLSearchParams } from '@/hooks'; import { useURLSearchParams } from '@/hooks';
import { IconButton, InputAdornment, Stack, TextField } from '@mui/material'; import { IconButton, InputAdornment, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui'; import { IconIcon_tool_close } from '@panda-wiki/icons';
import { useState } from 'react'; import { useState } from 'react';
const DocSearch = () => { const DocSearch = () => {
@ -32,8 +32,7 @@ const DocSearch = () => {
}} }}
size='small' size='small'
> >
<Icon <IconIcon_tool_close
type='icon-icon_tool_close'
sx={{ fontSize: 14, color: 'text.tertiary' }} sx={{ fontSize: 14, color: 'text.tertiary' }}
/> />
</IconButton> </IconButton>

View File

@ -5,9 +5,10 @@ import { postApiV1NodeBatchMove } from '@/request/Node';
import { DomainNodeListItemResp } from '@/request/types'; import { DomainNodeListItemResp } from '@/request/types';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { convertToTree } from '@/utils/drag'; import { convertToTree } from '@/utils/drag';
import { Icon, message, Modal } from '@ctzhian/ui'; import { message, Modal } from '@ctzhian/ui';
import { Box, Checkbox, Stack } from '@mui/material'; import { Box, Checkbox, Stack } from '@mui/material';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { IconWenjianjiaKai } from '@panda-wiki/icons';
interface DocDeleteProps { interface DocDeleteProps {
open: boolean; open: boolean;
@ -83,7 +84,7 @@ const MoveDocs = ({
setFolderIds(folderIds.includes('root') ? [] : ['root']); setFolderIds(folderIds.includes('root') ? [] : ['root']);
}} }}
/> />
<Icon type={'icon-wenjianjia-kai'} /> <IconWenjianjiaKai sx={{ fontSize: 14 }} />
<Box></Box> <Box></Box>
</Stack> </Stack>
<DragTree <DragTree

View File

@ -1,8 +1,9 @@
import { postApiV1NodeSummary, putApiV1NodeDetail } from '@/request/Node'; import { postApiV1NodeSummary, putApiV1NodeDetail } from '@/request/Node';
import { DomainNodeListItemResp } from '@/request/types'; import { DomainNodeListItemResp } from '@/request/types';
import { Button, Stack, TextField } from '@mui/material'; import { Button, Stack, TextField } from '@mui/material';
import { Icon, message, Modal } from '@ctzhian/ui'; import { message, Modal } from '@ctzhian/ui';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { IconShuaxin } from '@panda-wiki/icons';
interface SummaryProps { interface SummaryProps {
kb_id: string; kb_id: string;
@ -63,13 +64,13 @@ const Summary = ({ open, data, kb_id, onClose, refresh }: SummaryProps) => {
onClick={createSummary} onClick={createSummary}
disabled={loading} disabled={loading}
startIcon={ startIcon={
<Icon <IconShuaxin
type='icon-shuaxin' sx={{
sx={ fontSize: '16px !important',
loading ...(loading
? { animation: 'loadingRotate 1s linear infinite' } ? { animation: 'loadingRotate 1s linear infinite' }
: {} : {}),
} }}
/> />
} }
> >

View File

@ -1,8 +1,9 @@
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { Ellipsis, Icon } from '@ctzhian/ui'; import { Ellipsis } from '@ctzhian/ui';
import { Stack } from '@mui/material'; import { Stack } from '@mui/material';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { IconZuzhi } from '@panda-wiki/icons';
const KBSwitch = () => { const KBSwitch = () => {
// const dispatch = useAppDispatch(); // const dispatch = useAppDispatch();
@ -46,7 +47,7 @@ const KBSwitch = () => {
navigate('/'); navigate('/');
}} }}
> >
<Icon type='icon-zuzhi' sx={{ color: 'text.primary' }} /> <IconZuzhi type='icon-zuzhi' sx={{ color: 'text.primary' }} />
</Stack> </Stack>
<Ellipsis sx={{ flex: 1, width: 0, overflow: 'hidden' }}> <Ellipsis sx={{ flex: 1, width: 0, overflow: 'hidden' }}>
{currentKb?.name} {currentKb?.name}

View File

@ -9,12 +9,19 @@ import { DomainNodeListItemResp, V1NodeDetailResp } from '@/request/types';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { addOpacityToColor } from '@/utils'; import { addOpacityToColor } from '@/utils';
import { convertToTree } from '@/utils/drag'; import { convertToTree } from '@/utils/drag';
import { Ellipsis, Icon } from '@ctzhian/ui'; import { Ellipsis } from '@ctzhian/ui';
import { alpha, Box, IconButton, Stack, useTheme } from '@mui/material'; import { alpha, Box, IconButton, Stack, useTheme } from '@mui/material';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import { useLocation, useNavigate, useParams } from 'react-router-dom'; import { useLocation, useNavigate, useParams } from 'react-router-dom';
import DocAddByCustomText from '../../component/DocAddByCustomText'; import DocAddByCustomText from '../../component/DocAddByCustomText';
import KBSwitch from './KBSwitch'; import KBSwitch from './KBSwitch';
import {
IconIcon_tool_close,
IconWenjianjia,
IconWenjian,
IconMulushouqi,
IconXiajiantou,
} from '@panda-wiki/icons';
interface CatalogProps { interface CatalogProps {
curNode: V1NodeDetailResp; curNode: V1NodeDetailResp;
@ -123,9 +130,8 @@ const Catalog = ({ curNode, setCatalogOpen }: CatalogProps) => {
}} }}
context={ context={
<IconButton> <IconButton>
<Icon <IconIcon_tool_close
className='catalog-folder-add-icon' className='catalog-folder-add-icon'
type='icon-icon_tool_close'
sx={{ sx={{
fontSize: 16, fontSize: 16,
color: 'action.selected', color: 'action.selected',
@ -235,8 +241,7 @@ const Catalog = ({ curNode, setCatalogOpen }: CatalogProps) => {
top: 13, top: 13,
}} }}
> >
<Icon <IconXiajiantou
type='icon-xiajiantou'
sx={{ sx={{
fontSize: 16, fontSize: 16,
color: 'text.disabled', color: 'text.disabled',
@ -251,10 +256,13 @@ const Catalog = ({ curNode, setCatalogOpen }: CatalogProps) => {
)} )}
{item.emoji ? ( {item.emoji ? (
<Box sx={{ fontSize: 14, flexShrink: 0 }}>{item.emoji}</Box> <Box sx={{ fontSize: 14, flexShrink: 0 }}>{item.emoji}</Box>
) : item.type === 1 ? (
<IconWenjianjia
sx={{ color: '#2f80f7', flexShrink: 0, fontSize: 14 }}
/>
) : ( ) : (
<Icon <IconWenjian
type={item.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'} sx={{ color: '#2f80f7', flexShrink: 0, fontSize: 14 }}
sx={{ color: '#2f80f7', flexShrink: 0 }}
/> />
)} )}
<Ellipsis>{item.name}</Ellipsis> <Ellipsis>{item.name}</Ellipsis>
@ -336,8 +344,7 @@ const Catalog = ({ curNode, setCatalogOpen }: CatalogProps) => {
}, },
}} }}
> >
<Icon <IconMulushouqi
type='icon-mulushouqi'
sx={{ sx={{
fontSize: 24, fontSize: 24,
}} }}

View File

@ -1,11 +1,12 @@
import Cascader from '@/components/Cascader'; import Cascader from '@/components/Cascader';
import { VersionCanUse } from '@/components/VersionMask';
import { BUSINESS_VERSION_PERMISSION } from '@/constant/version';
import VersionPublish from '@/pages/release/components/VersionPublish'; import VersionPublish from '@/pages/release/components/VersionPublish';
import { postApiV1Node } from '@/request'; import { postApiV1Node } from '@/request';
import { V1NodeDetailResp } from '@/request/types'; import { V1NodeDetailResp } from '@/request/types';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { addOpacityToColor, getShortcutKeyText } from '@/utils'; import { addOpacityToColor, getShortcutKeyText } from '@/utils';
import { Ellipsis, Icon, message } from '@ctzhian/ui'; import { Ellipsis, message } from '@ctzhian/ui';
import InfoIcon from '@mui/icons-material/Info';
import { import {
Box, Box,
Button, Button,
@ -16,14 +17,18 @@ import {
Tooltip, Tooltip,
useTheme, useTheme,
} from '@mui/material'; } from '@mui/material';
import {
IconBaocun,
IconDaochu,
IconGengduo,
IconMuluzhankai,
} from '@panda-wiki/icons';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useNavigate, useOutletContext } from 'react-router-dom'; import { useNavigate, useOutletContext } from 'react-router-dom';
import { WrapContext } from '..'; import { WrapContext } from '..';
import DocAddByCustomText from '../../component/DocAddByCustomText'; import DocAddByCustomText from '../../component/DocAddByCustomText';
import DocDelete from '../../component/DocDelete'; import DocDelete from '../../component/DocDelete';
import { BUSINESS_VERSION_PERMISSION } from '@/constant/version';
import { VersionCanUse } from '@/components/VersionMask';
interface HeaderProps { interface HeaderProps {
edit: boolean; edit: boolean;
@ -43,8 +48,14 @@ const Header = ({
const theme = useTheme(); const theme = useTheme();
const navigate = useNavigate(); const navigate = useNavigate();
const firstLoad = useRef(true); const firstLoad = useRef(true);
const [wikiUrl, setWikiUrl] = useState<string>('');
const { kb_id, license, kbList } = useAppSelector(state => state.config);
const currentKb = useMemo(() => {
return kbList?.find(item => item.id === kb_id);
}, [kbList, kb_id]);
const { kb_id, license } = useAppSelector(state => state.config);
const { catalogOpen, nodeDetail, setCatalogOpen } = const { catalogOpen, nodeDetail, setCatalogOpen } =
useOutletContext<WrapContext>(); useOutletContext<WrapContext>();
@ -58,6 +69,25 @@ const Header = ({
return BUSINESS_VERSION_PERMISSION.includes(license.edition!); return BUSINESS_VERSION_PERMISSION.includes(license.edition!);
}, [license]); }, [license]);
useEffect(() => {
if (currentKb?.access_settings?.base_url) {
setWikiUrl(currentKb.access_settings.base_url);
return;
}
const host = currentKb?.access_settings?.hosts?.[0] || '';
if (host === '') return;
const { ssl_ports = [], ports = [] } = currentKb?.access_settings || {};
if (ssl_ports) {
if (ssl_ports.includes(443)) setWikiUrl(`https://${host}`);
else if (ssl_ports.length > 0)
setWikiUrl(`https://${host}:${ssl_ports[0]}`);
} else if (ports) {
if (ports.includes(80)) setWikiUrl(`http://${host}`);
else if (ports.length > 0) setWikiUrl(`http://${host}:${ports[0]}`);
}
}, [currentKb]);
const handlePublish = useCallback(() => { const handlePublish = useCallback(() => {
if (nodeDetail?.status === 2 && !edit) { if (nodeDetail?.status === 2 && !edit) {
message.info('当前已是最新版本!'); message.info('当前已是最新版本!');
@ -101,15 +131,13 @@ const Header = ({
}, },
}} }}
> >
<Icon <IconMuluzhankai
type='icon-muluzhankai'
sx={{ sx={{
fontSize: 24, fontSize: 24,
}} }}
/> />
</Stack> </Stack>
)} )}
{/* {detail.meta?.content_type === 'md' && <Icon type='icon-a-icon_huaban1fuben22' sx={{ fontSize: 30 }} />} */}
{detail.meta?.content_type === 'md' && ( {detail.meta?.content_type === 'md' && (
<Box <Box
component={'span'} component={'span'}
@ -149,7 +177,7 @@ const Header = ({
gap={0.5} gap={0.5}
sx={{ fontSize: 12, color: 'text.tertiary' }} sx={{ fontSize: 12, color: 'text.tertiary' }}
> >
<Icon type='icon-baocun' /> <IconBaocun sx={{ fontSize: 12 }} />
{showSaveTip ? ( {showSaveTip ? (
'已保存' '已保存'
) : nodeDetail?.updated_at ? ( ) : nodeDetail?.updated_at ? (
@ -159,156 +187,9 @@ const Header = ({
)} )}
</Stack> </Stack>
</Stack> </Stack>
{/* <Box sx={{ mr: 1 }}>
{isSyncing ? (
collaborativeUsers.length > 0 && (
<Stack
direction={'row'}
alignItems={'center'}
gap={1}
sx={{ color: 'text.disabled', fontSize: 14 }}
>
<Box
sx={{
width: 6,
height: 6,
borderRadius: '50%',
bgcolor: 'success.main',
}}
/>
{collaborativeUsers.length} 线
</Stack>
)
) : (
<Stack
direction={'row'}
alignItems={'center'}
gap={1}
sx={{ color: 'text.disabled', fontSize: 14 }}
>
<Box
sx={{
width: 6,
height: 6,
borderRadius: '50%',
bgcolor: 'divider',
}}
/>
线
</Stack>
)}
</Box> */}
<Stack direction={'row'} gap={1}> <Stack direction={'row'} gap={1}>
<Cascader <Cascader
list={[ list={[
// {
// key: 'page_width',
// label: (
// <StyledMenuSelect sx={{ width: 120 }}>
// <Stack
// direction={'row'}
// alignItems={'center'}
// justifyContent={'space-between'}
// sx={{ width: '100%' }}
// >
// 页面宽度
// <Icon
// type='icon-xiala-copy'
// sx={{ color: 'text.disabled', fontSize: 18, mr: -1 }}
// />
// </Stack>
// </StyledMenuSelect>
// ),
// children: [
// {
// key: 'full',
// label: (
// <StyledMenuSelect>
// <Stack
// direction={'row'}
// alignItems={'center'}
// justifyContent={'space-between'}
// sx={{ width: '100%' }}
// >
// 全屏
// {docWidth === 'full' && (
// <Icon
// type='icon-duihao1'
// sx={{
// color: 'primary.main',
// fontSize: 14,
// mr: -1,
// mt: -0.5,
// }}
// />
// )}
// </Stack>
// </StyledMenuSelect>
// ),
// onClick: () => {
// updateDocWidth('full');
// },
// },
// {
// key: 'wide',
// label: (
// <StyledMenuSelect>
// <Stack
// direction={'row'}
// alignItems={'center'}
// justifyContent={'space-between'}
// sx={{ width: '100%' }}
// >
// 超宽
// {docWidth === 'wide' && (
// <Icon
// type='icon-duihao1'
// sx={{
// color: 'primary.main',
// fontSize: 14,
// mr: -1,
// mt: -0.5,
// }}
// />
// )}
// </Stack>
// </StyledMenuSelect>
// ),
// onClick: () => {
// updateDocWidth('wide');
// },
// },
// {
// key: 'normal',
// label: (
// <StyledMenuSelect>
// <Stack
// direction={'row'}
// alignItems={'center'}
// justifyContent={'space-between'}
// sx={{ width: '100%' }}
// >
// 常规
// {docWidth === 'normal' && (
// <Icon
// type='icon-duihao1'
// sx={{
// color: 'primary.main',
// fontSize: 14,
// mr: -1,
// mt: -0.5,
// }}
// />
// )}
// </Stack>
// </StyledMenuSelect>
// ),
// onClick: () => {
// updateDocWidth('normal');
// },
// },
// ],
// },
{ {
key: 'copy', key: 'copy',
textSx: { flex: 1 }, textSx: { flex: 1 },
@ -329,6 +210,18 @@ const Header = ({
} }
}, },
}, },
{
key: 'front_doc',
textSx: { flex: 1 },
label: <StyledMenuSelect></StyledMenuSelect>,
onClick: () => {
if (detail.status !== 2 && !detail.publisher_id) {
message.warning('当前文档未发布,无法查看前台文档');
return;
}
window.open(`${wikiUrl}/node/${detail.id}`, '_blank');
},
},
{ {
key: 'version', key: 'version',
textSx: { flex: 1 }, textSx: { flex: 1 },
@ -367,7 +260,7 @@ const Header = ({
disabled={!detail.name} disabled={!detail.name}
sx={{ flexShrink: 0 }} sx={{ flexShrink: 0 }}
> >
<Icon type='icon-gengduo' /> <IconGengduo sx={{ fontSize: 14 }} />
</IconButton> </IconButton>
} }
/> />
@ -435,7 +328,7 @@ const Header = ({
size='small' size='small'
variant='outlined' variant='outlined'
disabled={!detail.name} disabled={!detail.name}
startIcon={<Icon type='icon-daochu' />} startIcon={<IconDaochu sx={{ fontSize: 14 }} />}
> >
</Button> </Button>
@ -511,7 +404,7 @@ const Header = ({
size='small' size='small'
variant='contained' variant='contained'
disabled={!detail.name} disabled={!detail.name}
startIcon={<Icon type='icon-baocun' />} startIcon={<IconBaocun sx={{ fontSize: 14 }} />}
> >
</Button> </Button>

View File

@ -1,22 +1,13 @@
import { useTiptap } from '@ctzhian/tiptap'; import { useTiptap } from '@ctzhian/tiptap';
import { Icon } from '@ctzhian/ui';
import { Box, Skeleton, Stack } from '@mui/material'; import { Box, Skeleton, Stack } from '@mui/material';
import { useState } from 'react';
import { useOutletContext } from 'react-router-dom'; import { useOutletContext } from 'react-router-dom';
import { WrapContext } from '..'; import { WrapContext } from '..';
import Header from './Header'; import Header from './Header';
import Toolbar from './Toolbar'; import Toolbar from './Toolbar';
import { IconAShijian2, IconZiti } from '@panda-wiki/icons';
const LoadingEditorWrap = () => { const LoadingEditorWrap = () => {
const { catalogOpen } = useOutletContext<WrapContext>(); const { catalogOpen } = useOutletContext<WrapContext>();
const [isSyncing] = useState(false);
const [collaborativeUsers] = useState<
Array<{
id: string;
name: string;
color: string;
}>
>([]);
const editorRef = useTiptap({ const editorRef = useTiptap({
editable: false, editable: false,
@ -62,11 +53,11 @@ const LoadingEditorWrap = () => {
</Stack> </Stack>
<Stack direction={'row'} alignItems={'center'} gap={2} sx={{ mb: 4 }}> <Stack direction={'row'} alignItems={'center'} gap={2} sx={{ mb: 4 }}>
<Stack direction={'row'} alignItems={'center'} gap={0.5}> <Stack direction={'row'} alignItems={'center'} gap={0.5}>
<Icon type='icon-a-shijian2' sx={{ color: 'text.tertiary' }} /> <IconAShijian2 sx={{ color: 'text.tertiary', fontSize: 12 }} />
<Skeleton variant='text' width={130} height={24} /> <Skeleton variant='text' width={130} height={24} />
</Stack> </Stack>
<Stack direction={'row'} alignItems={'center'} gap={0.5}> <Stack direction={'row'} alignItems={'center'} gap={0.5}>
<Icon type='icon-ziti' sx={{ color: 'text.tertiary' }} /> <IconZiti sx={{ color: 'text.tertiary', fontSize: 12 }} />
<Skeleton variant='text' width={80} height={24} /> <Skeleton variant='text' width={80} height={24} />
</Stack> </Stack>
</Stack> </Stack>

View File

@ -4,11 +4,12 @@ import {
V1NodeDetailResp, V1NodeDetailResp,
} from '@/request'; } from '@/request';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { Icon, message, Modal } from '@ctzhian/ui'; import { message, Modal } from '@ctzhian/ui';
import { Button, CircularProgress, Stack, TextField } from '@mui/material'; import { Button, CircularProgress, Stack, TextField } from '@mui/material';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useOutletContext } from 'react-router-dom'; import { useOutletContext } from 'react-router-dom';
import { WrapContext } from '..'; import { WrapContext } from '..';
import { IconDJzhinengzhaiyao } from '@panda-wiki/icons';
interface SummaryProps { interface SummaryProps {
open: boolean; open: boolean;
@ -95,7 +96,7 @@ const Summary = ({ open, onClose, updateDetail }: SummaryProps) => {
loading ? ( loading ? (
<CircularProgress size={16} /> <CircularProgress size={16} />
) : ( ) : (
<Icon type='icon-DJzhinengzhaiyao' sx={{ fontSize: 16 }} /> <IconDJzhinengzhaiyao sx={{ fontSize: 16 }} />
) )
} }
> >

View File

@ -7,9 +7,10 @@ import {
H6Icon, H6Icon,
TocList, TocList,
} from '@ctzhian/tiptap'; } from '@ctzhian/tiptap';
import { Ellipsis, Icon } from '@ctzhian/ui'; import { Ellipsis } from '@ctzhian/ui';
import { Box, Drawer, IconButton, Stack } from '@mui/material'; import { Box, Drawer, IconButton, Stack } from '@mui/material';
import { useState } from 'react'; import { useState } from 'react';
import { IconDingzi, IconIcon_tool_close } from '@panda-wiki/icons';
interface TocProps { interface TocProps {
headings: TocList; headings: TocList;
@ -139,10 +140,11 @@ const Toc = ({
setFixed(!fixed); setFixed(!fixed);
}} }}
> >
<Icon {!fixed ? (
type={!fixed ? 'icon-dingzi' : 'icon-icon_tool_close'} <IconDingzi sx={{ fontSize: 18 }} />
sx={{ fontSize: 18 }} ) : (
/> <IconIcon_tool_close sx={{ fontSize: 18 }} />
)}
</IconButton> </IconButton>
</Stack> </Stack>
<Stack <Stack

View File

@ -11,7 +11,7 @@ import {
useTiptap, useTiptap,
UseTiptapReturn, UseTiptapReturn,
} from '@ctzhian/tiptap'; } from '@ctzhian/tiptap';
import { Icon, message } from '@ctzhian/ui'; import { message } from '@ctzhian/ui';
import { Box, Stack, TextField, Tooltip } from '@mui/material'; import { Box, Stack, TextField, Tooltip } from '@mui/material';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { debounce } from 'lodash-es'; import { debounce } from 'lodash-es';
@ -30,6 +30,12 @@ import Summary from './Summary';
import Toc from './Toc'; import Toc from './Toc';
import Toolbar from './Toolbar'; import Toolbar from './Toolbar';
import { BUSINESS_VERSION_PERMISSION } from '@/constant/version'; import { BUSINESS_VERSION_PERMISSION } from '@/constant/version';
import {
IconTianjiawendang,
IconAShijian2,
IconZiti,
IconDJzhinengzhaiyao,
} from '@panda-wiki/icons';
interface WrapProps { interface WrapProps {
detail: V1NodeDetailResp; detail: V1NodeDetailResp;
@ -379,7 +385,7 @@ const Wrap = ({ detail: defaultDetail }: WrapProps) => {
color: 'text.tertiary', color: 'text.tertiary',
}} }}
> >
<Icon type='icon-tianjiawendang' sx={{ fontSize: 9 }} /> <IconTianjiawendang sx={{ fontSize: 9 }} />
{nodeDetail?.editor_account} {nodeDetail?.editor_account}
</Stack> </Stack>
</Tooltip> </Tooltip>
@ -403,7 +409,7 @@ const Wrap = ({ detail: defaultDetail }: WrapProps) => {
} }
}} }}
> >
<Icon type='icon-a-shijian2' /> <IconAShijian2 sx={{ fontSize: 12 }} />
{dayjs(defaultDetail.created_at).format( {dayjs(defaultDetail.created_at).format(
'YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD HH:mm:ss',
)}{' '} )}{' '}
@ -416,7 +422,7 @@ const Wrap = ({ detail: defaultDetail }: WrapProps) => {
gap={0.5} gap={0.5}
sx={{ fontSize: 12, color: 'text.tertiary' }} sx={{ fontSize: 12, color: 'text.tertiary' }}
> >
<Icon type='icon-ziti' /> <IconZiti sx={{ fontSize: 12 }} />
{characterCount} {characterCount}
</Stack> </Stack>
</Stack> </Stack>
@ -463,7 +469,7 @@ const Wrap = ({ detail: defaultDetail }: WrapProps) => {
}, },
}} }}
> >
<Icon type='icon-DJzhinengzhaiyao' sx={{ fontSize: 12 }} /> <IconDJzhinengzhaiyao sx={{ fontSize: 12 }} />
</Stack> </Stack>
{nodeDetail?.meta?.summary ? ( {nodeDetail?.meta?.summary ? (

View File

@ -8,7 +8,7 @@ import {
} from '@/request/pro'; } from '@/request/pro';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { Editor, useTiptap } from '@ctzhian/tiptap'; import { Editor, useTiptap } from '@ctzhian/tiptap';
import { Ellipsis, Icon } from '@ctzhian/ui'; import { Ellipsis } from '@ctzhian/ui';
import { import {
alpha, alpha,
Box, Box,
@ -22,6 +22,14 @@ import { useEffect, useState } from 'react';
import { useNavigate, useOutletContext, useParams } from 'react-router-dom'; import { useNavigate, useOutletContext, useParams } from 'react-router-dom';
import { WrapContext } from '..'; import { WrapContext } from '..';
import VersionRollback from '../../component/VersionRollback'; import VersionRollback from '../../component/VersionRollback';
import {
IconMuluzhankai,
IconChahao,
IconTianjiawendang,
IconZiti,
IconFabu,
IconAShijian2,
} from '@panda-wiki/icons';
const History = () => { const History = () => {
const { id = '' } = useParams(); const { id = '' } = useParams();
@ -128,8 +136,7 @@ const History = () => {
}, },
}} }}
> >
<Icon <IconMuluzhankai
type='icon-muluzhankai'
sx={{ sx={{
fontSize: 24, fontSize: 24,
}} }}
@ -144,7 +151,7 @@ const History = () => {
navigate(`/doc/editor/${id}`); navigate(`/doc/editor/${id}`);
}} }}
> >
<Icon type='icon-chahao' /> <IconChahao sx={{ fontSize: 16 }} />
</IconButton> </IconButton>
</Stack> </Stack>
<Box sx={{ mt: '56px', mr: '292px' }}> <Box sx={{ mt: '56px', mr: '292px' }}>
@ -211,17 +218,17 @@ const History = () => {
gap={0.5} gap={0.5}
sx={{ cursor: 'pointer' }} sx={{ cursor: 'pointer' }}
> >
<Icon type='icon-tianjiawendang' sx={{ fontSize: 9 }} /> <IconTianjiawendang sx={{ fontSize: 9 }} />
{curNode.editor_account} {curNode.editor_account}
</Stack> </Stack>
</Tooltip> </Tooltip>
)} )}
<Stack direction={'row'} alignItems={'center'} gap={0.5}> <Stack direction={'row'} alignItems={'center'} gap={0.5}>
<Icon type='icon-a-shijian2' /> <IconAShijian2 sx={{ fontSize: 12 }} />
{curVersion?.release_message} {curVersion?.release_message}
</Stack> </Stack>
<Stack direction={'row'} alignItems={'center'} gap={0.5}> <Stack direction={'row'} alignItems={'center'} gap={0.5}>
<Icon type='icon-ziti' /> <IconZiti sx={{ fontSize: 12 }} />
{characterCount} {characterCount}
</Stack> </Stack>
</Stack> </Stack>
@ -338,7 +345,7 @@ const History = () => {
lineHeight: 1, lineHeight: 1,
}} }}
> >
<Icon type='icon-fabu' /> <IconFabu sx={{ fontSize: 16 }} />
{item.publisher_account} {item.publisher_account}
</Stack> </Stack>
) : ( ) : (

View File

@ -17,17 +17,18 @@ import { useAppDispatch, useAppSelector } from '@/store';
import { setIsRefreshDocList } from '@/store/slices/config'; import { setIsRefreshDocList } from '@/store/slices/config';
import { addOpacityToColor } from '@/utils'; import { addOpacityToColor } from '@/utils';
import { collapseAllFolders, convertToTree } from '@/utils/drag'; import { collapseAllFolders, convertToTree } from '@/utils/drag';
import { Icon } from '@ctzhian/ui'; import { message } from '@ctzhian/ui';
import { import {
Box, Box,
Button, Button,
ButtonBase,
Checkbox, Checkbox,
IconButton, IconButton,
Stack, Stack,
useTheme, useTheme,
ButtonBase,
} from '@mui/material'; } from '@mui/material';
import { useCallback, useEffect, useRef, useState } from 'react'; import { IconGengduo } from '@panda-wiki/icons';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import VersionPublish from '../release/components/VersionPublish'; import VersionPublish from '../release/components/VersionPublish';
import AddDocBtn from './component/AddDocBtn'; import AddDocBtn from './component/AddDocBtn';
import AddDocByType from './component/AddDocByType'; import AddDocByType from './component/AddDocByType';
@ -41,7 +42,9 @@ import RagErrorReStart from './component/RagErrorReStart';
import Summary from './component/Summary'; import Summary from './component/Summary';
const Content = () => { const Content = () => {
const { kb_id, isRefreshDocList } = useAppSelector(state => state.config); const { kb_id, isRefreshDocList, kbList } = useAppSelector(
state => state.config,
);
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const theme = useTheme(); const theme = useTheme();
const dragTreeRef = useRef<DragTreeHandle>(null); const dragTreeRef = useRef<DragTreeHandle>(null);
@ -49,6 +52,7 @@ const Content = () => {
const [searchParams] = useURLSearchParams(); const [searchParams] = useURLSearchParams();
const search = searchParams.get('search') || ''; const search = searchParams.get('search') || '';
const [supportSelect, setBatchOpen] = useState(false); const [supportSelect, setBatchOpen] = useState(false);
const [wikiUrl, setWikiUrl] = useState<string>('');
const [ragReStartCount, setRagStartCount] = useState(0); const [ragReStartCount, setRagStartCount] = useState(0);
const [ragIds, setRagIds] = useState<string[]>([]); const [ragIds, setRagIds] = useState<string[]>([]);
@ -139,6 +143,15 @@ const Content = () => {
setIsBatch(false); setIsBatch(false);
}; };
const handleFrontDoc = (id: string) => {
const currentNode = list.find(item => item.id === id);
if (currentNode?.status !== 2 && !currentNode?.publisher_id) {
message.warning('当前文档未发布,无法查看前台文档');
return;
}
window.open(`${wikiUrl}/node/${id}`, '_blank');
};
const menu = (opra: TreeMenuOptions): TreeMenuItem[] => { const menu = (opra: TreeMenuOptions): TreeMenuItem[] => {
const { item, createItem, renameItem, isEditing: isEditing } = opra; const { item, createItem, renameItem, isEditing: isEditing } = opra;
return [ return [
@ -292,6 +305,11 @@ const Content = () => {
key: 'properties', key: 'properties',
onClick: () => handleProperties(item), onClick: () => handleProperties(item),
}, },
{
label: '前台查看',
key: 'front_doc',
onClick: () => handleFrontDoc(item.id),
},
] ]
: []), : []),
...(!isEditing ...(!isEditing
@ -367,6 +385,10 @@ const Content = () => {
setData([...newData]); setData([...newData]);
}, []); }, []);
const currentKb = useMemo(() => {
return kbList?.find(item => item.id === kb_id);
}, [kbList, kb_id]);
useEffect(() => { useEffect(() => {
const handleVisibilityChange = () => { const handleVisibilityChange = () => {
if (document.visibilityState === 'visible' && kb_id) { if (document.visibilityState === 'visible' && kb_id) {
@ -379,6 +401,25 @@ const Content = () => {
}; };
}, [getData, kb_id]); }, [getData, kb_id]);
useEffect(() => {
if (currentKb?.access_settings?.base_url) {
setWikiUrl(currentKb.access_settings.base_url);
return;
}
const host = currentKb?.access_settings?.hosts?.[0] || '';
if (host === '') return;
const { ssl_ports = [], ports = [] } = currentKb?.access_settings || {};
if (ssl_ports) {
if (ssl_ports.includes(443)) setWikiUrl(`https://${host}`);
else if (ssl_ports.length > 0)
setWikiUrl(`https://${host}:${ssl_ports[0]}`);
} else if (ports) {
if (ports.includes(80)) setWikiUrl(`http://${host}`);
else if (ports.length > 0) setWikiUrl(`http://${host}:${ports[0]}`);
}
}, [currentKb]);
useEffect(() => { useEffect(() => {
if (kb_id) getData(); if (kb_id) getData();
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
@ -529,7 +570,7 @@ const Content = () => {
context={ context={
<Box> <Box>
<IconButton size='small'> <IconButton size='small'>
<Icon type='icon-gengduo' /> <IconGengduo sx={{ fontSize: '16px' }} />
</IconButton> </IconButton>
</Box> </Box>
} }

View File

@ -27,7 +27,8 @@ import {
alpha, alpha,
ButtonBase, ButtonBase,
} from '@mui/material'; } from '@mui/material';
import { Ellipsis, Table, Modal, Icon, message } from '@ctzhian/ui'; import { Ellipsis, Table, Modal, message } from '@ctzhian/ui';
import { IconGengduo } from '@panda-wiki/icons';
import { PROFESSION_VERSION_PERMISSION } from '@/constant/version'; import { PROFESSION_VERSION_PERMISSION } from '@/constant/version';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useEffect, useState, useMemo } from 'react'; import { useEffect, useState, useMemo } from 'react';
@ -129,7 +130,7 @@ const ActionMenu = ({
return ( return (
<> <>
<IconButton size='small' onClick={handleClick}> <IconButton size='small' onClick={handleClick}>
<Icon type='icon-gengduo' /> <IconGengduo sx={{ fontSize: 16 }} />
</IconButton> </IconButton>
<Menu anchorEl={anchorEl} open={open} onClose={handleClose}> <Menu anchorEl={anchorEl} open={open} onClose={handleClose}>
{record.status! !== 1 && ( {record.status! !== 1 && (

View File

@ -7,8 +7,13 @@ import { tableSx } from '@/constant/styles';
import { useURLSearchParams } from '@/hooks'; import { useURLSearchParams } from '@/hooks';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { Box, Stack, Tooltip } from '@mui/material'; import { Box, Stack, Tooltip } from '@mui/material';
import { Ellipsis, Icon, Table } from '@ctzhian/ui'; import { Ellipsis, Table } from '@ctzhian/ui';
import { ColumnsType } from '@ctzhian/ui/dist/Table'; import { ColumnsType } from '@ctzhian/ui/dist/Table';
import {
IconDianzanXuanzhong1,
IconADiancaiWeixuanzhong2,
IconDianzanWeixuanzhong,
} from '@panda-wiki/icons';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import Detail from './Detail'; import Detail from './Detail';
@ -33,15 +38,12 @@ const Evaluate = () => {
dataIndex: 'question', dataIndex: 'question',
title: '问题', title: '问题',
render: (text: string, record) => { render: (text: string, record) => {
const AppIcon =
AppType[record.app_type as keyof typeof AppType]?.icon || '';
return ( return (
<> <>
<Stack direction={'row'} alignItems={'center'} gap={1}> <Stack direction={'row'} alignItems={'center'} gap={1}>
<Icon <AppIcon sx={{ fontSize: 12 }}></AppIcon>
sx={{ fontSize: 12 }}
type={
AppType[record.app_type as keyof typeof AppType]?.icon || ''
}
/>
<Ellipsis <Ellipsis
className='primary-color' className='primary-color'
sx={{ cursor: 'pointer', flex: 1, width: 0 }} sx={{ cursor: 'pointer', flex: 1, width: 0 }}
@ -94,19 +96,24 @@ const Evaluate = () => {
sx={{ cursor: 'pointer', fontSize: 14 }} sx={{ cursor: 'pointer', fontSize: 14 }}
> >
{value!.score === 1 ? ( {value!.score === 1 ? (
<Icon <IconDianzanXuanzhong1
type='icon-dianzan-xuanzhong1' sx={{
sx={{ cursor: 'pointer', color: 'success.main' }} fontSize: 14,
cursor: 'pointer',
color: 'success.main',
}}
/> />
) : value!.score === -1 ? ( ) : value!.score === -1 ? (
<Icon <IconADiancaiWeixuanzhong2
type='icon-a-diancai-weixuanzhong2' sx={{
sx={{ cursor: 'pointer', color: 'error.main' }} fontSize: 14,
cursor: 'pointer',
color: 'error.main',
}}
/> />
) : ( ) : (
<Icon <IconDianzanWeixuanzhong
type='icon-dianzan-weixuanzhong' sx={{ fontSize: 14, color: 'text.disabled' }}
sx={{ color: 'text.disabled' }}
/> />
)} )}
</Stack> </Stack>

View File

@ -1,82 +0,0 @@
import { useURLSearchParams } from '@/hooks';
import { IconButton, InputAdornment, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui';
import { useState } from 'react';
const Search = () => {
const [searchParams, setSearchParams] = useURLSearchParams();
const oldSubject = searchParams.get('subject') || '';
const oldRemoteIp = searchParams.get('remote_ip') || '';
const [subject, setSubject] = useState(oldSubject);
const [remoteIp, setRemoteIp] = useState(oldRemoteIp);
return (
<Stack direction={'row'} alignItems={'center'} gap={2}>
<TextField
label='问题'
size='small'
sx={{ width: 200 }}
value={subject}
onKeyUp={event => {
if (event.key === 'Enter') {
setSearchParams({ subject: subject || '' });
}
}}
onBlur={event => setSearchParams({ subject: event.target.value })}
onChange={event => setSubject(event.target.value)}
InputProps={{
endAdornment: subject ? (
<InputAdornment position='end'>
<IconButton
onClick={() => {
setSubject('');
setSearchParams({ subject: '' });
}}
size='small'
>
<Icon
type='icon-icon_tool_close'
sx={{ fontSize: 14, color: 'text.tertiary' }}
/>
</IconButton>
</InputAdornment>
) : null,
}}
/>
<TextField
label='客户端'
size='small'
sx={{ width: 200 }}
value={remoteIp}
onKeyUp={event => {
if (event.key === 'Enter') {
setSearchParams({ remote_ip: remoteIp || '' });
}
}}
onBlur={event => setSearchParams({ remote_ip: event.target.value })}
onChange={event => setRemoteIp(event.target.value)}
InputProps={{
endAdornment: remoteIp ? (
<InputAdornment position='end'>
<IconButton
onClick={() => {
setRemoteIp('');
setSearchParams({ remote_ip: '' });
}}
size='small'
>
<Icon
type='icon-icon_tool_close'
sx={{ fontSize: 14, color: 'text.tertiary' }}
/>
</IconButton>
</InputAdornment>
) : null,
}}
/>
</Stack>
);
};
export default Search;

View File

@ -8,6 +8,13 @@ import { Box, Button, IconButton, Stack, TextField } from '@mui/material';
import { Icon, message } from '@ctzhian/ui'; import { Icon, message } from '@ctzhian/ui';
import { useState } from 'react'; import { useState } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import {
IconZhanghao,
IconIcon_tool_close,
IconMima,
IconKejian,
IconBukejian,
} from '@panda-wiki/icons';
const Login = () => { const Login = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@ -90,10 +97,7 @@ const Login = () => {
slotProps={{ slotProps={{
input: { input: {
startAdornment: ( startAdornment: (
<Icon <IconZhanghao sx={{ fontSize: 16, mr: 2, flexShrink: 0 }} />
type='icon-zhanghao'
sx={{ fontSize: 16, mr: 2, flexShrink: 0 }}
/>
), ),
endAdornment: account ? ( endAdornment: account ? (
<IconButton <IconButton
@ -101,8 +105,7 @@ const Login = () => {
size='small' size='small'
tabIndex={-1} tabIndex={-1}
> >
<Icon <IconIcon_tool_close
type='icon-icon_tool_close'
sx={{ fontSize: 14, color: 'text.tertiary' }} sx={{ fontSize: 14, color: 'text.tertiary' }}
/> />
</IconButton> </IconButton>
@ -128,34 +131,31 @@ const Login = () => {
slotProps={{ slotProps={{
input: { input: {
startAdornment: ( startAdornment: (
<Icon <IconMima sx={{ fontSize: 16, mr: 2, flexShrink: 0 }} />
type='icon-mima'
sx={{ fontSize: 16, mr: 2, flexShrink: 0 }}
/>
), ),
endAdornment: password ? ( endAdornment: password ? (
<Stack <Stack direction={'row'} alignItems={'center'}>
direction={'row'}
alignItems={'center'}
sx={{ mr: '14px' }}
>
<IconButton <IconButton
onClick={() => setSee(!see)} onClick={() => setSee(!see)}
size='small' size='small'
tabIndex={-1} tabIndex={-1}
> >
<Icon {see ? (
type={see ? 'icon-kejian' : 'icon-bukejian'} <IconKejian
sx={{ fontSize: 18, color: 'text.tertiary' }} sx={{ fontSize: 18, color: 'text.tertiary' }}
/> />
) : (
<IconBukejian
sx={{ fontSize: 18, color: 'text.tertiary' }}
/>
)}
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => setPassword('')} onClick={() => setPassword('')}
size='small' size='small'
tabIndex={-1} tabIndex={-1}
> >
<Icon <IconIcon_tool_close
type='icon-icon_tool_close'
sx={{ fontSize: 14, color: 'text.tertiary' }} sx={{ fontSize: 14, color: 'text.tertiary' }}
/> />
</IconButton> </IconButton>

View File

@ -262,31 +262,6 @@ const CardAuth = ({ kb, refresh }: CardAuthProps) => {
); );
}, },
}, },
// {
// title: '',
// dataIndex: 'action',
// width: 60,
// render: (text: string, record) => {
// return (
// <IconButton
// size='small'
// sx={{ p: '2px' }}
// onClick={() => {
// onDeleteUser(record.id!);
// }}
// >
// <Icon
// type='icon-icon_tool_close'
// sx={{
// cursor: 'pointer',
// color: 'error.main',
// }}
// />
// </IconButton>
// );
// },
// },
]; ];
const githubForm = () => { const githubForm = () => {

View File

@ -1,245 +0,0 @@
import { putApiV1App } from '@/request/App';
import { FooterSetting } from '@/api/type';
import DragBrand from '@/components/Drag/DragBrand';
import UploadFile from '@/components/UploadFile';
import { DomainAppDetailResp, DomainBrandGroup } from '@/request/types';
import {
Box,
Button,
FormControlLabel,
Radio,
RadioGroup,
Stack,
TextField,
} from '@mui/material';
import { message } from '@ctzhian/ui';
import { useEffect, useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { FormItem, SettingCardItem } from './Common';
import { useAppSelector } from '@/store';
interface CardFooterProps {
id: string;
data: DomainAppDetailResp;
refresh: (value: FooterSetting) => void;
}
const CardFooter = ({ id, data, refresh }: CardFooterProps) => {
const [isEdit, setIsEdit] = useState(false);
const { kb_id } = useAppSelector(state => state.config);
const {
control,
handleSubmit,
watch,
setValue,
formState: { errors },
} = useForm({
defaultValues: {
footer_style: 'simple',
corp_name: '',
icp: '',
brand_name: '',
brand_desc: '',
brand_logo: '',
brand_groups: [] as DomainBrandGroup[],
},
});
const footerStyle = watch('footer_style');
const onSubmit = handleSubmit(value => {
putApiV1App(
{ id },
{
kb_id,
settings: {
...data.settings,
footer_settings: {
...data.settings?.footer_settings,
...value,
},
},
},
).then(() => {
refresh(value as FooterSetting);
message.success('保存成功');
setIsEdit(false);
});
});
useEffect(() => {
setValue(
'footer_style',
data.settings?.footer_settings?.footer_style as 'simple' | 'complex',
);
setValue('corp_name', data.settings?.footer_settings?.corp_name || '');
setValue('icp', data.settings?.footer_settings?.icp || '');
setValue('brand_name', data.settings?.footer_settings?.brand_name || '');
setValue('brand_desc', data.settings?.footer_settings?.brand_desc || '');
setValue('brand_logo', data.settings?.footer_settings?.brand_logo || '');
setValue(
'brand_groups',
data.settings?.footer_settings?.brand_groups || [],
);
}, [data]);
return (
<SettingCardItem title='页脚' isEdit={isEdit} onSubmit={onSubmit}>
<FormItem label='页面模式'>
<Controller
control={control}
name='footer_style'
render={({ field }) => (
<RadioGroup
row
{...field}
onChange={e => {
field.onChange(e.target.value);
setIsEdit(true);
}}
>
<FormControlLabel
value={'simple'}
control={<Radio size='small' />}
label={<Box sx={{ width: 100 }}></Box>}
/>
<FormControlLabel
value={'complex'}
control={<Radio size='small' />}
label={<Box sx={{ width: 100 }}></Box>}
/>
</RadioGroup>
)}
/>
</FormItem>
<FormItem label='企业名称 / 组织名称'>
{' '}
<Controller
control={control}
name='corp_name'
render={({ field }) => (
<TextField
{...field}
fullWidth
placeholder='企业名称/组织名称'
onChange={e => {
field.onChange(e.target.value);
setIsEdit(true);
}}
error={!!errors.corp_name}
helperText={errors.corp_name?.message}
/>
)}
/>
</FormItem>
<FormItem label='ICP 备案编号'>
<Controller
control={control}
name='icp'
render={({ field }) => (
<TextField
{...field}
fullWidth
placeholder='ICP 备案编号'
onChange={e => {
field.onChange(e.target.value);
setIsEdit(true);
}}
error={!!errors.icp}
helperText={errors.icp?.message}
/>
)}
/>
</FormItem>
{footerStyle === 'complex' && (
<>
<FormItem label='品牌名称'>
<Controller
control={control}
name='brand_name'
render={({ field }) => (
<TextField
{...field}
fullWidth
placeholder='品牌名称'
onChange={e => {
field.onChange(e.target.value);
setIsEdit(true);
}}
error={!!errors.brand_name}
helperText={errors.brand_name?.message}
/>
)}
/>
</FormItem>
<FormItem label='品牌 Logo'>
<Controller
control={control}
name='brand_logo'
render={({ field }) => (
<UploadFile
{...field}
id='brand_logo'
type='url'
accept='image/*'
width={80}
onChange={url => {
field.onChange(url);
setIsEdit(true);
}}
/>
)}
/>
</FormItem>
<FormItem label='品牌介绍'>
<Controller
control={control}
name='brand_desc'
render={({ field }) => (
<TextField
{...field}
fullWidth
placeholder='品牌介绍'
onChange={e => {
field.onChange(e.target.value);
setIsEdit(true);
}}
error={!!errors.brand_desc}
helperText={errors.brand_desc?.message}
/>
)}
/>
</FormItem>
<Box>
<Box
sx={{
width: 156,
fontSize: 14,
lineHeight: '32px',
flexShrink: 0,
my: 1,
}}
>
</Box>
{/* 使用 DragBrand 组件替换原有的品牌链接组 */}
<DragBrand
// @ts-expect-error 类型不匹配
control={control}
errors={errors}
setIsEdit={setIsEdit}
/>
</Box>
</>
)}
</SettingCardItem>
);
};
export default CardFooter;

View File

@ -22,7 +22,9 @@ import {
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { setRefreshAdminRequest } from '@/store/slices/config'; import { setRefreshAdminRequest } from '@/store/slices/config';
import { copyText } from '@/utils'; import { copyText } from '@/utils';
import { Ellipsis, Icon, message, Modal } from '@ctzhian/ui'; import { Ellipsis, message, Modal } from '@ctzhian/ui';
import { IconIcon_tool_close, IconTianjiachengyuan } from '@panda-wiki/icons';
import { IconFuzhi } from '@panda-wiki/icons';
import InfoIcon from '@mui/icons-material/Info'; import InfoIcon from '@mui/icons-material/Info';
import { import {
Box, Box,
@ -210,8 +212,7 @@ const ApiToken = () => {
}} }}
> >
{maskString(it.token!)} {maskString(it.token!)}
<Icon <IconFuzhi
type='icon-fuzhi'
sx={{ sx={{
cursor: 'pointer', cursor: 'pointer',
fontSize: 16, fontSize: 16,
@ -275,9 +276,9 @@ const ApiToken = () => {
</Stack> </Stack>
<Tooltip title={user.role !== 'admin' && ''} placement='top' arrow> <Tooltip title={user.role !== 'admin' && ''} placement='top' arrow>
<Icon <IconIcon_tool_close
type='icon-icon_tool_close'
sx={{ sx={{
fontSize: 16,
cursor: cursor:
!isBusiness || !isBusiness ||
kbDetail?.perm !== kbDetail?.perm !==
@ -457,7 +458,7 @@ const CardKB = () => {
extra={ extra={
<Button <Button
size='small' size='small'
startIcon={<Icon type='icon-tianjiachengyuan' />} startIcon={<IconTianjiachengyuan />}
onClick={() => setAddOpen(true)} onClick={() => setAddOpen(true)}
sx={{ color: 'primary.main' }} sx={{ color: 'primary.main' }}
> >
@ -557,9 +558,9 @@ const CardKB = () => {
placement='top' placement='top'
arrow arrow
> >
<Icon <IconIcon_tool_close
type='icon-icon_tool_close'
sx={{ sx={{
fontSize: 16,
cursor: it.role === 'admin' ? 'not-allowed' : 'pointer', cursor: it.role === 'admin' ? 'not-allowed' : 'pointer',
color: it.role === 'admin' ? 'text.disabled' : 'error.main', color: it.role === 'admin' ? 'text.disabled' : 'error.main',
}} }}

View File

@ -10,7 +10,8 @@ import {
DomainKnowledgeBaseDetail, DomainKnowledgeBaseDetail,
} from '@/request/types'; } from '@/request/types';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { Icon, message } from '@ctzhian/ui'; import { message } from '@ctzhian/ui';
import { IconJinggao } from '@panda-wiki/icons';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { import {
Box, Box,
@ -235,7 +236,7 @@ const CardRobotWebComponent = ({ kb }: CardRobotWebComponentProps) => {
bgcolor: 'warning.light', bgcolor: 'warning.light',
}} }}
> >
<Icon type='icon-jinggao' /> <IconJinggao sx={{ fontSize: 16 }} />
<Box component={'span'} sx={{ fontWeight: 500 }}> <Box component={'span'} sx={{ fontWeight: 500 }}>
/ /

View File

@ -7,7 +7,8 @@ import {
DomainKnowledgeBaseDetail, DomainKnowledgeBaseDetail,
} from '@/request/types'; } from '@/request/types';
import { useAppSelector } from '@/store'; import { useAppSelector } from '@/store';
import { Icon, message } from '@ctzhian/ui'; import { message } from '@ctzhian/ui';
import { IconJinggao } from '@panda-wiki/icons';
import { import {
Box, Box,
FormControlLabel, FormControlLabel,
@ -261,7 +262,7 @@ const CardRobotWecomService = ({
gap={1} gap={1}
sx={{ fontSize: 14, fontWeight: 600, color: 'warning.main' }} sx={{ fontSize: 14, fontWeight: 600, color: 'warning.main' }}
> >
<Icon type='icon-jinggao' sx={{ fontSize: 18 }} /> <IconJinggao sx={{ fontSize: 18 }} />
</Stack> </Stack>
<VersionMask permission={PROFESSION_VERSION_PERMISSION}> <VersionMask permission={PROFESSION_VERSION_PERMISSION}>

Some files were not shown because too many files have changed in this diff Show More