Compare commits
7 Commits
95bd31b8ed
...
59ca885518
| Author | SHA1 | Date |
|---|---|---|
|
|
59ca885518 | |
|
|
0e64ff946f | |
|
|
19e6a66809 | |
|
|
c15272aeb2 | |
|
|
32ed999b48 | |
|
|
98e4a917e0 | |
|
|
6e5f780771 |
|
|
@ -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"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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": {
|
||||||
|
|
|
||||||
|
|
@ -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]);
|
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 354 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 360 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -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'
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 }}>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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' } }}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)}
|
||||||
>
|
>
|
||||||
系统配置
|
系统配置
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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',
|
|
||||||
};
|
|
||||||
|
|
@ -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,
|
||||||
|
|
@ -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');
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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' }}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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 }}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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' }
|
||||||
: {}
|
: {}),
|
||||||
}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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' }
|
||||||
: {}
|
: {}),
|
||||||
}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -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}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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 }} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ? (
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 && (
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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 = () => {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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',
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -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 }}>
|
||||||
门户网站 / 服务监听方式
|
门户网站 / 服务监听方式
|
||||||
|
|
|
||||||
|
|
@ -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}>
|
||||||
|
|
|
||||||