Compare commits
7 Commits
95bd31b8ed
...
59ca885518
| Author | SHA1 | Date |
|---|---|---|
|
|
59ca885518 | |
|
|
0e64ff946f | |
|
|
19e6a66809 | |
|
|
c15272aeb2 | |
|
|
32ed999b48 | |
|
|
98e4a917e0 | |
|
|
6e5f780771 |
|
|
@ -6582,6 +6582,9 @@ const docTemplate = `{
|
|||
"position": {
|
||||
"type": "number"
|
||||
},
|
||||
"publisher_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"rag_info": {
|
||||
"$ref": "#/definitions/domain.RagInfo"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -6575,6 +6575,9 @@
|
|||
"position": {
|
||||
"type": "number"
|
||||
},
|
||||
"publisher_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"rag_info": {
|
||||
"$ref": "#/definitions/domain.RagInfo"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1763,6 +1763,8 @@ definitions:
|
|||
$ref: '#/definitions/domain.NodePermissions'
|
||||
position:
|
||||
type: number
|
||||
publisher_id:
|
||||
type: string
|
||||
rag_info:
|
||||
$ref: '#/definitions/domain.RagInfo'
|
||||
status:
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ type NodeListItemResp struct {
|
|||
EditorId string `json:"editor_id"`
|
||||
Creator string `json:"creator"`
|
||||
Editor string `json:"editor"`
|
||||
PublisherId string `json:"publisher_id" gorm:"-"`
|
||||
Permissions NodePermissions `json:"permissions" gorm:"type:jsonb"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -157,6 +157,32 @@ func (r *NodeRepository) GetLatestNodeReleaseByNodeIDs(ctx context.Context, kbID
|
|||
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 {
|
||||
// Use transaction to ensure data consistency
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
"build:dev": "vite build --m development",
|
||||
"build": "tsc -b && vite build",
|
||||
"build:analyze": "tsc -b && vite build -- --analyze",
|
||||
"icon": "node ./scripts/downLoadIcon.cjs",
|
||||
"api": "cx-swagger-api"
|
||||
},
|
||||
"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 { Avatar as MuiAvatar, SxProps } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconDandulogo } from '@panda-wiki/icons';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
interface AvatarProps {
|
||||
|
|
@ -15,9 +15,8 @@ const Avatar = (props: AvatarProps) => {
|
|||
const src = props.src;
|
||||
|
||||
const LogoIcon = (
|
||||
<Icon
|
||||
<IconDandulogo
|
||||
sx={{ width: '100%', height: '100%', color: 'text.primary' }}
|
||||
type='icon-dandulogo'
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { FooterSetting } from '@/api/type';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconShanchu2, IconDrag, IconTianjia } from '@panda-wiki/icons';
|
||||
import {
|
||||
closestCenter,
|
||||
DndContext,
|
||||
|
|
@ -100,7 +100,7 @@ const LinkItem = forwardRef<HTMLDivElement, LinkItemProps>(
|
|||
}}
|
||||
{...dragHandleProps}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
<Box
|
||||
sx={{
|
||||
|
|
@ -123,7 +123,7 @@ const LinkItem = forwardRef<HTMLDivElement, LinkItemProps>(
|
|||
ml: 'auto',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
<Controller
|
||||
|
|
@ -373,7 +373,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
{...dragHandleProps}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
<Box
|
||||
sx={{
|
||||
|
|
@ -396,7 +396,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
ml: 'auto',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
<Controller
|
||||
|
|
@ -513,8 +513,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
onClick={handleAddLink}
|
||||
>
|
||||
<Icon
|
||||
type='icon-tianjia'
|
||||
<IconTianjia
|
||||
sx={{ fontSize: '10px !important', color: '#5F58FE' }}
|
||||
/>
|
||||
<Box
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { CardWebHeaderBtn } from '@/api';
|
||||
import UploadFile from '@/components/UploadFile';
|
||||
import { useAppDispatch, useAppSelector } from '@/store';
|
||||
import { setAppPreviewData } from '@/store/slices/config';
|
||||
|
||||
import {
|
||||
Box,
|
||||
Checkbox,
|
||||
|
|
@ -13,16 +13,15 @@ import {
|
|||
Stack,
|
||||
TextField,
|
||||
} from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
|
||||
import {
|
||||
CSSProperties,
|
||||
Dispatch,
|
||||
forwardRef,
|
||||
HTMLAttributes,
|
||||
SetStateAction,
|
||||
useEffect,
|
||||
} from 'react';
|
||||
import { Control, Controller, useForm } from 'react-hook-form';
|
||||
import { Control, Controller } from 'react-hook-form';
|
||||
|
||||
export type ItemProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {
|
||||
item: CardWebHeaderBtn;
|
||||
|
|
@ -300,7 +299,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size='small'
|
||||
|
|
@ -311,7 +310,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
{...dragHandleProps}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import UploadFile from '@/components/UploadFile';
|
||||
import { DomainSocialMediaAccount } from '@/request/types';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
|
||||
import {
|
||||
Box,
|
||||
IconButton,
|
||||
|
|
@ -92,7 +92,7 @@ const Item = forwardRef<HTMLDivElement, SocialInfoProps>(
|
|||
}}
|
||||
{...dragHandleProps}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
<Box
|
||||
sx={{
|
||||
|
|
@ -120,7 +120,7 @@ const Item = forwardRef<HTMLDivElement, SocialInfoProps>(
|
|||
ml: 'auto',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
<Stack direction={'row'} gap={1}>
|
||||
|
|
@ -142,16 +142,10 @@ const Item = forwardRef<HTMLDivElement, SocialInfoProps>(
|
|||
}}
|
||||
renderValue={selected => {
|
||||
const option = options.find(i => i.key === selected);
|
||||
const AppIcon = option?.config_type || option?.type;
|
||||
return (
|
||||
<Stack justifyContent={'center'} sx={{ mt: '2px' }}>
|
||||
<Icon
|
||||
type={
|
||||
option
|
||||
? option?.config_type || option?.type || ''
|
||||
: ''
|
||||
}
|
||||
sx={{ fontSize: '14px' }}
|
||||
/>
|
||||
{AppIcon && <AppIcon sx={{ fontSize: '14px' }} />}
|
||||
</Stack>
|
||||
);
|
||||
}}
|
||||
|
|
@ -185,7 +179,9 @@ const Item = forwardRef<HTMLDivElement, SocialInfoProps>(
|
|||
borderRadius: 1,
|
||||
}}
|
||||
>
|
||||
{options.map(item => (
|
||||
{options.map(item => {
|
||||
const AppIcon = item?.config_type || item?.type;
|
||||
return (
|
||||
<ToggleButton
|
||||
key={item.key}
|
||||
value={item.key}
|
||||
|
|
@ -201,14 +197,13 @@ const Item = forwardRef<HTMLDivElement, SocialInfoProps>(
|
|||
gap={1}
|
||||
alignItems='center'
|
||||
>
|
||||
<Icon
|
||||
type={item?.config_type || item?.type}
|
||||
sx={{ fontSize: '16px' }}
|
||||
/>
|
||||
{/* <Box>{item.value || item.key}</Box> */}
|
||||
{AppIcon && (
|
||||
<AppIcon sx={{ fontSize: '16px' }} />
|
||||
)}
|
||||
</Stack>
|
||||
</ToggleButton>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</ToggleButtonGroup>
|
||||
</MenuItem>
|
||||
</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,
|
||||
} from '@mui/material';
|
||||
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 type { CSSProperties } from 'react';
|
||||
import { Component } from '../../index';
|
||||
|
|
@ -185,8 +185,7 @@ const ComponentBar = ({
|
|||
}}
|
||||
{...(!item.fixed ? { ...attributes, ...listeners } : {})}
|
||||
>
|
||||
<Icon
|
||||
type='icon-wangyeguajian'
|
||||
<IconWangyeguajian
|
||||
sx={{
|
||||
color:
|
||||
item.id === curComponent.id
|
||||
|
|
@ -196,7 +195,7 @@ const ComponentBar = ({
|
|||
: 'text.secondary',
|
||||
fontSize: '14px',
|
||||
}}
|
||||
></Icon>
|
||||
></IconWangyeguajian>
|
||||
<Typography
|
||||
sx={{
|
||||
marginLeft: '8px',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Box, IconButton, Stack, TextField } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
|
||||
import {
|
||||
CSSProperties,
|
||||
Dispatch,
|
||||
|
|
@ -118,7 +118,7 @@ const HotSearchItem = forwardRef<HTMLDivElement, HotSearchItemProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size='small'
|
||||
|
|
@ -129,7 +129,7 @@ const HotSearchItem = forwardRef<HTMLDivElement, HotSearchItemProps>(
|
|||
}}
|
||||
{...(dragHandleProps as any)}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
Select,
|
||||
MenuItem,
|
||||
} from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
|
||||
import {
|
||||
CSSProperties,
|
||||
Dispatch,
|
||||
|
|
@ -159,7 +159,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size='small'
|
||||
|
|
@ -170,7 +170,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
{...(dragHandleProps as any)}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -2,8 +2,14 @@ import { postApiV1NodeSummary } from '@/request/Node';
|
|||
import { DomainRecommendNodeListResp } from '@/request/types';
|
||||
import { useAppSelector } from '@/store';
|
||||
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 {
|
||||
IconShanchu2,
|
||||
IconDrag,
|
||||
IconWenjianjia,
|
||||
IconWenjian,
|
||||
} from '@panda-wiki/icons';
|
||||
|
||||
export type ItemProps = HTMLAttributes<HTMLDivElement> & {
|
||||
item: DomainRecommendNodeListResp;
|
||||
|
|
@ -80,9 +86,12 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
<Box sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}>
|
||||
{item.emoji}
|
||||
</Box>
|
||||
) : item.type === 1 ? (
|
||||
<IconWenjianjia
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
type={item.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'}
|
||||
<IconWenjian
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -121,12 +130,16 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
.slice(0, 4)
|
||||
.map(it => (
|
||||
<Stack direction={'row'} alignItems={'center'} gap={1}>
|
||||
<Icon
|
||||
type={
|
||||
it.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'
|
||||
}
|
||||
{it.type === 1 ? (
|
||||
<IconWenjianjia
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
) : (
|
||||
<IconWenjian
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Ellipsis sx={{ flex: 1, width: 0 }}>{it.name}</Ellipsis>
|
||||
</Stack>
|
||||
))}
|
||||
|
|
@ -147,7 +160,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
|
||||
<IconButton
|
||||
|
|
@ -159,7 +172,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
{...dragHandleProps}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
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 {
|
||||
CSSProperties,
|
||||
|
|
@ -132,7 +132,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size='small'
|
||||
|
|
@ -143,7 +143,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
{...(dragHandleProps as any)}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
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 {
|
||||
CSSProperties,
|
||||
|
|
@ -152,7 +152,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size='small'
|
||||
|
|
@ -163,7 +163,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
{...(dragHandleProps as any)}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Box, IconButton, Stack, TextField } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
|
||||
import {
|
||||
CSSProperties,
|
||||
Dispatch,
|
||||
|
|
@ -143,7 +143,7 @@ const ItemType = forwardRef<HTMLDivElement, ItemTypeProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size='small'
|
||||
|
|
@ -154,7 +154,7 @@ const ItemType = forwardRef<HTMLDivElement, ItemTypeProps>(
|
|||
}}
|
||||
{...(dragHandleProps as any)}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Box, IconButton, Stack, TextField } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
|
||||
import {
|
||||
CSSProperties,
|
||||
Dispatch,
|
||||
|
|
@ -185,7 +185,7 @@ const ItemType = forwardRef<HTMLDivElement, ItemTypeProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size='small'
|
||||
|
|
@ -196,7 +196,7 @@ const ItemType = forwardRef<HTMLDivElement, ItemTypeProps>(
|
|||
}}
|
||||
{...(dragHandleProps as any)}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,13 @@ import { postApiV1NodeSummary } from '@/request/Node';
|
|||
import { DomainRecommendNodeListResp } from '@/request/types';
|
||||
import { useAppSelector } from '@/store';
|
||||
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';
|
||||
|
||||
export type ItemProps = HTMLAttributes<HTMLDivElement> & {
|
||||
|
|
@ -82,9 +88,12 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
<Box sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}>
|
||||
{item.emoji}
|
||||
</Box>
|
||||
) : item.type === 1 ? (
|
||||
<IconWenjianjia
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
type={item.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'}
|
||||
<IconWenjian
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -128,11 +137,12 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
>
|
||||
{it.emoji}
|
||||
</Box>
|
||||
) : it.type === 1 ? (
|
||||
<IconWenjianjia
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
type={
|
||||
it.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'
|
||||
}
|
||||
<IconWenjian
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -157,7 +167,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
|
||||
<IconButton
|
||||
|
|
@ -169,7 +179,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
{...dragHandleProps}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Box, IconButton, Stack, TextField } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
|
||||
import {
|
||||
CSSProperties,
|
||||
Dispatch,
|
||||
|
|
@ -143,7 +143,7 @@ const FaqItem = forwardRef<HTMLDivElement, FaqItemProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size='small'
|
||||
|
|
@ -154,7 +154,7 @@ const FaqItem = forwardRef<HTMLDivElement, FaqItemProps>(
|
|||
}}
|
||||
{...(dragHandleProps as any)}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Box, IconButton, Stack, TextField } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
|
||||
import {
|
||||
CSSProperties,
|
||||
Dispatch,
|
||||
|
|
@ -143,7 +143,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size='small'
|
||||
|
|
@ -154,7 +154,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
{...(dragHandleProps as any)}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import { AppDetail, HeaderSetting } from '@/api';
|
||||
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 { Icon } from '@ctzhian/ui';
|
||||
import { Dispatch, SetStateAction, useEffect, useMemo } from 'react';
|
||||
import { Dispatch, SetStateAction, useEffect } from 'react';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { useAppDispatch, useAppSelector } from '@/store';
|
||||
import { setAppPreviewData } from '@/store/slices/config';
|
||||
|
|
@ -12,6 +11,13 @@ import Switch from '../basicComponents/Switch';
|
|||
import DragSocialInfo from '../basicComponents/DragSocialInfo';
|
||||
import VersionMask from '@/components/VersionMask';
|
||||
import { PROFESSION_VERSION_PERMISSION } from '@/constant/version';
|
||||
import { IconTianjia } from '@panda-wiki/icons';
|
||||
import {
|
||||
IconWeixingongzhonghao,
|
||||
IconDianhua,
|
||||
IconWeixingongzhonghaoDaiyanse,
|
||||
IconDianhua1,
|
||||
} from '@panda-wiki/icons';
|
||||
|
||||
interface FooterConfigProps {
|
||||
data?: AppDetail | null;
|
||||
|
|
@ -21,8 +27,8 @@ interface FooterConfigProps {
|
|||
export interface Option {
|
||||
key: string;
|
||||
value: string;
|
||||
type: string;
|
||||
config_type?: string;
|
||||
type: React.ComponentType<SvgIconProps>;
|
||||
config_type?: React.ComponentType<SvgIconProps>;
|
||||
text_placeholder?: string;
|
||||
text_label?: string;
|
||||
}
|
||||
|
|
@ -30,16 +36,16 @@ export const options: Option[] = [
|
|||
{
|
||||
key: 'wechat_oa',
|
||||
value: '微信公众号',
|
||||
type: 'icon-weixingongzhonghao',
|
||||
config_type: 'icon-weixingongzhonghao-daiyanse',
|
||||
type: IconWeixingongzhonghao,
|
||||
config_type: IconWeixingongzhonghaoDaiyanse,
|
||||
text_placeholder: '请输入公众号名称',
|
||||
text_label: '公众号名称',
|
||||
},
|
||||
{
|
||||
key: 'phone',
|
||||
value: '电话',
|
||||
type: 'icon-dianhua',
|
||||
config_type: 'icon-dianhua1',
|
||||
type: IconDianhua,
|
||||
config_type: IconDianhua1,
|
||||
text_placeholder: '请输入文字',
|
||||
text_label: '文字',
|
||||
},
|
||||
|
|
@ -331,8 +337,7 @@ const FooterConfig = ({ data, setIsEdit, isEdit }: FooterConfigProps) => {
|
|||
setIsEdit(true);
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type='icon-tianjia'
|
||||
<IconTianjia
|
||||
sx={{ fontSize: '10px !important', color: '#5F58FE' }}
|
||||
/>
|
||||
<Box
|
||||
|
|
@ -396,8 +401,7 @@ const FooterConfig = ({ data, setIsEdit, isEdit }: FooterConfigProps) => {
|
|||
setIsEdit(true);
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type='icon-tianjia'
|
||||
<IconTianjia
|
||||
sx={{ fontSize: '10px !important', color: '#5F58FE' }}
|
||||
/>
|
||||
<Box
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@ import { AppDetail, HeaderSetting } from '@/api';
|
|||
import DragBtn from '../basicComponents/DragBtn';
|
||||
import UploadFile from '@/components/UploadFile';
|
||||
import { Stack, Box, TextField } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { Dispatch, SetStateAction, useEffect } from 'react';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { useAppDispatch, useAppSelector } from '@/store';
|
||||
import { setAppPreviewData } from '@/store/slices/config';
|
||||
import { useAppSelector } from '@/store';
|
||||
import useDebounceAppPreviewData from '@/hooks/useDebounceAppPreviewData';
|
||||
import { IconTianjia } from '@panda-wiki/icons';
|
||||
|
||||
interface CardWebHeaderProps {
|
||||
data?: AppDetail | null;
|
||||
|
|
@ -17,7 +16,6 @@ interface CardWebHeaderProps {
|
|||
|
||||
const HeaderConfig = ({ data, setIsEdit, isEdit }: CardWebHeaderProps) => {
|
||||
const { appPreviewData } = useAppSelector(state => state.config);
|
||||
const dispatch = useAppDispatch();
|
||||
const debouncedDispatch = useDebounceAppPreviewData();
|
||||
const {
|
||||
control,
|
||||
|
|
@ -257,8 +255,7 @@ const HeaderConfig = ({ data, setIsEdit, isEdit }: CardWebHeaderProps) => {
|
|||
}}
|
||||
onClick={handleAddButton}
|
||||
>
|
||||
<Icon
|
||||
type='icon-tianjia'
|
||||
<IconTianjia
|
||||
sx={{ fontSize: '10px !important', color: '#5F58FE' }}
|
||||
/>
|
||||
<Box sx={{ fontSize: 14, lineHeight: '22px', marginLeft: 0.5 }}>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Box, IconButton, Stack, TextField } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
|
||||
import {
|
||||
CSSProperties,
|
||||
Dispatch,
|
||||
|
|
@ -143,7 +143,7 @@ const ItemType = forwardRef<HTMLDivElement, ItemTypeProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size='small'
|
||||
|
|
@ -154,7 +154,7 @@ const ItemType = forwardRef<HTMLDivElement, ItemTypeProps>(
|
|||
}}
|
||||
{...(dragHandleProps as any)}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Box, IconButton, Stack, TextField } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconShanchu2, IconDrag } from '@panda-wiki/icons';
|
||||
import {
|
||||
CSSProperties,
|
||||
Dispatch,
|
||||
|
|
@ -115,7 +115,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size='small'
|
||||
|
|
@ -126,7 +126,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
{...(dragHandleProps as any)}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
import { postApiV1NodeSummary } from '@/request/Node';
|
||||
import { DomainRecommendNodeListResp } from '@/request/types';
|
||||
import { useAppSelector } from '@/store';
|
||||
import { Box, IconButton, Stack } from '@mui/material';
|
||||
import { Ellipsis, Icon, message } from '@ctzhian/ui';
|
||||
import { CSSProperties, forwardRef, HTMLAttributes, useState } from 'react';
|
||||
import {
|
||||
IconShanchu2,
|
||||
IconDrag,
|
||||
IconWenjianjia,
|
||||
IconWenjian,
|
||||
} from '@panda-wiki/icons';
|
||||
import { Ellipsis } from '@ctzhian/ui';
|
||||
import { CSSProperties, forwardRef, HTMLAttributes } from 'react';
|
||||
|
||||
export type ItemProps = HTMLAttributes<HTMLDivElement> & {
|
||||
item: DomainRecommendNodeListResp;
|
||||
|
|
@ -66,9 +70,12 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
<Box sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}>
|
||||
{item.emoji}
|
||||
</Box>
|
||||
) : item.type === 1 ? (
|
||||
<IconWenjianjia
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
type={item.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'}
|
||||
<IconWenjian
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -91,7 +98,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
height: '28px',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-shanchu2' sx={{ fontSize: '12px' }} />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
|
||||
<IconButton
|
||||
|
|
@ -103,7 +110,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
{...dragHandleProps}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { useEffect, useState, useRef } from 'react';
|
||||
import { Button, Stack, Typography } from '@mui/material';
|
||||
import { CusTabs, Icon, message, Modal } from '@ctzhian/ui';
|
||||
import { CusTabs, message, Modal } from '@ctzhian/ui';
|
||||
import {
|
||||
getApiV1NodeRecommendNodes,
|
||||
getApiV1KnowledgeBaseDetail,
|
||||
|
|
@ -9,6 +9,7 @@ import {
|
|||
DomainAppDetailResp,
|
||||
DomainWebAppLandingConfigResp,
|
||||
} from '@/request/types';
|
||||
import { IconPCduan, IconYidongduan } from '@panda-wiki/icons';
|
||||
|
||||
import { getApiV1AppDetail, putApiV1App } from '@/request/App';
|
||||
import { useAppSelector, useAppDispatch } from '@/store';
|
||||
|
|
@ -338,18 +339,11 @@ const CustomModal = ({
|
|||
<CusTabs
|
||||
list={[
|
||||
{
|
||||
label: (
|
||||
<Icon type='icon-PCduan' sx={{ height: '32px' }} />
|
||||
),
|
||||
label: <IconPCduan sx={{ fontSize: 14 }} />,
|
||||
value: 'pc',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<Icon
|
||||
type='icon-yidongduan'
|
||||
sx={{ height: '32px' }}
|
||||
/>
|
||||
),
|
||||
label: <IconYidongduan sx={{ fontSize: 14 }} />,
|
||||
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 { 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 { IconDrag } from '@panda-wiki/icons';
|
||||
import { CSSProperties, forwardRef, HTMLAttributes } from 'react';
|
||||
|
||||
export type ItemProps = HTMLAttributes<HTMLDivElement> & {
|
||||
|
|
@ -62,10 +64,15 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
>
|
||||
<Stack direction={'row'} alignItems={'center'} gap={1}>
|
||||
<Icon
|
||||
type={item.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'}
|
||||
{item.type === 1 ? (
|
||||
<IconWenjianjia
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
) : (
|
||||
<IconWenjian
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
)}
|
||||
<Ellipsis sx={{ flex: 1, width: 0, lineHeight: '32px' }}>
|
||||
{item.name}
|
||||
</Ellipsis>
|
||||
|
|
@ -95,12 +102,15 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
.slice(0, 4)
|
||||
.map(it => (
|
||||
<Stack direction={'row'} alignItems={'center'} gap={1}>
|
||||
<Icon
|
||||
type={
|
||||
it.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'
|
||||
}
|
||||
{it.type === 1 ? (
|
||||
<IconWenjianjia
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
) : (
|
||||
<IconWenjian
|
||||
sx={{ fontSize: 14, color: '#2f80f7', flexShrink: 0 }}
|
||||
/>
|
||||
)}
|
||||
<Ellipsis sx={{ flex: 1, width: 0 }}>{it.name}</Ellipsis>
|
||||
</Stack>
|
||||
))}
|
||||
|
|
@ -119,7 +129,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
':hover': { color: 'error.main' },
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-icon_tool_close' />
|
||||
<IconShanchu2 sx={{ fontSize: '12px' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size='small'
|
||||
|
|
@ -130,7 +140,7 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
}}
|
||||
{...dragHandleProps}
|
||||
>
|
||||
<Icon type='icon-drag' />
|
||||
<IconDrag sx={{ fontSize: '18px' }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { ITreeItem } from '@/api';
|
||||
import Cascader from '@/components/Cascader';
|
||||
import { addOpacityToColor } from '@/utils';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { Box, IconButton, Stack, useTheme } from '@mui/material';
|
||||
import { IconXiala, IconGengduo } from '@panda-wiki/icons';
|
||||
|
||||
export type TreeMenuItem = {
|
||||
key: string;
|
||||
|
|
@ -96,10 +96,7 @@ const TreeMenu = ({
|
|||
>
|
||||
{value.label}
|
||||
{value.children && (
|
||||
<Icon
|
||||
type='icon-xiala'
|
||||
sx={{ fontSize: 20, transform: 'rotate(-90deg)' }}
|
||||
/>
|
||||
<IconXiala sx={{ fontSize: 20, transform: 'rotate(-90deg)' }} />
|
||||
)}
|
||||
</Stack>
|
||||
{value.key === 'next-line' && (
|
||||
|
|
@ -119,7 +116,7 @@ const TreeMenu = ({
|
|||
context={
|
||||
context || (
|
||||
<IconButton size='small'>
|
||||
<Icon type='icon-gengduo' />
|
||||
<IconGengduo sx={{ fontSize: '14px' }} />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
import data from '@emoji-mart/data';
|
||||
import Picker from '@emoji-mart/react';
|
||||
import { Box, IconButton, Popover, SxProps } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import React, { useCallback } from 'react';
|
||||
import {
|
||||
IconWenjianjia,
|
||||
IconWenjian,
|
||||
IconWenjianjiaKai,
|
||||
} from '@panda-wiki/icons';
|
||||
import zh from '../../assets/emoji-data/zh.json';
|
||||
|
||||
interface EmojiPickerProps {
|
||||
|
|
@ -66,17 +70,14 @@ const EmojiPicker: React.FC<EmojiPickerProps> = ({
|
|||
<Box component='span' sx={{ fontSize: 14, ...iconSx }}>
|
||||
{value}
|
||||
</Box>
|
||||
) : type === 1 ? (
|
||||
collapsed ? (
|
||||
<IconWenjianjia sx={{ fontSize: 16, ...iconSx }} />
|
||||
) : (
|
||||
<Icon
|
||||
type={
|
||||
type === 1
|
||||
? collapsed
|
||||
? 'icon-wenjianjia'
|
||||
: 'icon-wenjianjia-kai'
|
||||
: 'icon-wenjian'
|
||||
}
|
||||
sx={{ fontSize: 16, ...iconSx }}
|
||||
/>
|
||||
<IconWenjianjiaKai sx={{ fontSize: 16, ...iconSx }} />
|
||||
)
|
||||
) : (
|
||||
<IconWenjian sx={{ fontSize: 16, ...iconSx }} />
|
||||
)}
|
||||
</IconButton>
|
||||
<Popover
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { useAppSelector } from '@/store';
|
||||
import { Box, Stack, useTheme } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { IconXiala } from '@panda-wiki/icons';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { NavLink, useLocation } from 'react-router-dom';
|
||||
import KBSelect from '../KB/KBSelect';
|
||||
|
|
@ -76,10 +76,7 @@ const Bread = () => {
|
|||
...(idx === breads.length - 1 && { fontWeight: 'bold' }),
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type='icon-xiala'
|
||||
sx={{ fontSize: 20, transform: 'rotate(-90deg)' }}
|
||||
/>
|
||||
<IconXiala sx={{ fontSize: 20, transform: 'rotate(-90deg)' }} />
|
||||
{it.to === 'custom' ? (
|
||||
<Box
|
||||
sx={{ cursor: 'pointer', ':hover': { color: 'primary.main' } }}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ import { useAppSelector, useAppDispatch } from '@/store';
|
|||
import { setKbDetail } from '@/store/slices/config';
|
||||
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
|
||||
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 { useNavigate } from 'react-router-dom';
|
||||
import System from '../System';
|
||||
import Bread from './Bread';
|
||||
import { IconDengchu } from '@panda-wiki/icons';
|
||||
|
||||
const Header = () => {
|
||||
const navigate = useNavigate();
|
||||
|
|
@ -94,7 +95,7 @@ const Header = () => {
|
|||
setLogoutConfirmOpen(true);
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-dengchu' sx={{ fontSize: 18 }} />
|
||||
<IconDengchu sx={{ fontSize: 18 }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,13 @@ import { useFeatureValue } from '@/hooks';
|
|||
import { ConstsUserRole } from '@/request/types';
|
||||
import { useAppDispatch, useAppSelector } from '@/store';
|
||||
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 {
|
||||
Box,
|
||||
Button,
|
||||
|
|
@ -69,8 +75,7 @@ const KBSelect = () => {
|
|||
}}
|
||||
IconComponent={({ className, ...rest }) => {
|
||||
return (
|
||||
<Icon
|
||||
type='icon-xiala'
|
||||
<IconXiala
|
||||
className={className + ' icon-xiala'}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
|
|
@ -148,8 +153,7 @@ const KBSelect = () => {
|
|||
gap={1.5}
|
||||
sx={{ width: '100%' }}
|
||||
>
|
||||
<Icon
|
||||
type='icon-zuzhi'
|
||||
<IconZuzhi
|
||||
sx={{ fontSize: 14, color: 'text.secondary', flexShrink: 0 }}
|
||||
/>
|
||||
<Ellipsis>{item.name}</Ellipsis>
|
||||
|
|
@ -166,8 +170,7 @@ const KBSelect = () => {
|
|||
setModifyOpen(true);
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type='icon-tianjiawendang'
|
||||
<IconTianjiawendang
|
||||
sx={{
|
||||
fontSize: 14,
|
||||
color: 'text.tertiary',
|
||||
|
|
@ -185,8 +188,7 @@ const KBSelect = () => {
|
|||
setDeleteOpen(true);
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type='icon-shanchu'
|
||||
<IconShanchu
|
||||
sx={{
|
||||
fontSize: 14,
|
||||
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 { Box, IconButton, useTheme } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import 'katex/dist/katex.min.css';
|
||||
import React, { useState } from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
|
|
@ -12,6 +11,7 @@ import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
|
|||
import remarkBreaks from 'remark-breaks';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import remarkMath from 'remark-math';
|
||||
import { IconXiajiantou } from '@panda-wiki/icons';
|
||||
|
||||
interface MarkDownProps {
|
||||
loading?: boolean;
|
||||
|
|
@ -117,8 +117,7 @@ const MarkDown = ({ loading = false, content }: MarkDownProps) => {
|
|||
},
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type='icon-xiajiantou'
|
||||
<IconXiajiantou
|
||||
sx={{
|
||||
fontSize: 18,
|
||||
flexShrink: 0,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import { copyText } from '@/utils';
|
||||
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 {
|
||||
text: string[];
|
||||
copyable?: boolean;
|
||||
showIcon?: boolean;
|
||||
noEllipsis?: boolean;
|
||||
icon?: string;
|
||||
icon?: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
|
|
@ -15,7 +16,9 @@ const ShowText = ({
|
|||
text,
|
||||
copyable = true,
|
||||
showIcon = true,
|
||||
icon = 'icon-fuzhi',
|
||||
icon = (
|
||||
<IconFuzhi sx={{ fontSize: 16, color: 'text.disabled', flexShrink: 0 }} />
|
||||
),
|
||||
onClick,
|
||||
noEllipsis = false,
|
||||
}: ShowTextProps) => {
|
||||
|
|
@ -62,12 +65,7 @@ const ShowText = ({
|
|||
),
|
||||
)}
|
||||
</Stack>
|
||||
{showIcon && (
|
||||
<Icon
|
||||
type={icon}
|
||||
sx={{ fontSize: 16, color: 'text.disabled', flexShrink: 0 }}
|
||||
/>
|
||||
)}
|
||||
{showIcon && icon}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ import { useVersionInfo } from '@/hooks';
|
|||
import { useAppDispatch, useAppSelector } from '@/store';
|
||||
import { setLicense } from '@/store/slices/config';
|
||||
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 { useState } from 'react';
|
||||
import LottieIcon from '../LottieIcon';
|
||||
|
|
@ -312,11 +313,11 @@ const AuthTypeModal = ({
|
|||
}}
|
||||
>
|
||||
<Stack direction={'row'} alignItems={'center'} gap={1}>
|
||||
<Icon type='icon-wenjian' />
|
||||
<IconWenjian sx={{ fontSize: 16 }} />
|
||||
{file.name}
|
||||
</Stack>
|
||||
<IconButton onClick={() => setFile(undefined)}>
|
||||
<Icon type='icon-icon_tool_close' sx={{ fontSize: 16 }} />
|
||||
<IconIcon_tool_close sx={{ fontSize: 16 }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -3,19 +3,31 @@ import Qrcode from '@/assets/images/qrcode.png';
|
|||
|
||||
import { Box, Button, Stack, Typography, useTheme } from '@mui/material';
|
||||
import { ConstsUserKBPermission } from '@/request/types';
|
||||
import { Icon, Modal } from '@ctzhian/ui';
|
||||
import { Modal } from '@ctzhian/ui';
|
||||
import { useState, useMemo, useEffect } from 'react';
|
||||
import { NavLink, useLocation, useNavigate } from 'react-router-dom';
|
||||
import Avatar from '../Avatar';
|
||||
import Version from './Version';
|
||||
import { useAppSelector } from '@/store';
|
||||
import {
|
||||
IconBangzhuwendang1,
|
||||
IconNeirongguanli,
|
||||
IconTongjifenxi1,
|
||||
IconJushou,
|
||||
IconGongxian,
|
||||
IconPaperFull,
|
||||
IconDuihualishi1,
|
||||
IconChilun,
|
||||
IconGroup,
|
||||
IconGithub,
|
||||
} from '@panda-wiki/icons';
|
||||
|
||||
const MENUS = [
|
||||
{
|
||||
label: '文档',
|
||||
value: '/',
|
||||
pathname: 'document',
|
||||
icon: 'icon-neirongguanli',
|
||||
icon: IconNeirongguanli,
|
||||
show: true,
|
||||
perms: [
|
||||
ConstsUserKBPermission.UserKBPermissionFullControl,
|
||||
|
|
@ -26,7 +38,7 @@ const MENUS = [
|
|||
label: '统计',
|
||||
value: '/stat',
|
||||
pathname: 'stat',
|
||||
icon: 'icon-tongjifenxi1',
|
||||
icon: IconTongjifenxi1,
|
||||
show: true,
|
||||
perms: [
|
||||
ConstsUserKBPermission.UserKBPermissionFullControl,
|
||||
|
|
@ -37,7 +49,7 @@ const MENUS = [
|
|||
label: '贡献',
|
||||
value: '/contribution',
|
||||
pathname: 'contribution',
|
||||
icon: 'icon-gongxian',
|
||||
icon: IconGongxian,
|
||||
show: true,
|
||||
perms: [ConstsUserKBPermission.UserKBPermissionFullControl],
|
||||
},
|
||||
|
|
@ -45,7 +57,7 @@ const MENUS = [
|
|||
label: '问答',
|
||||
value: '/conversation',
|
||||
pathname: 'conversation',
|
||||
icon: 'icon-duihualishi1',
|
||||
icon: IconDuihualishi1,
|
||||
show: true,
|
||||
perms: [
|
||||
ConstsUserKBPermission.UserKBPermissionFullControl,
|
||||
|
|
@ -56,7 +68,7 @@ const MENUS = [
|
|||
label: '反馈',
|
||||
value: '/feedback',
|
||||
pathname: 'feedback',
|
||||
icon: 'icon-jushou',
|
||||
icon: IconJushou,
|
||||
show: true,
|
||||
perms: [
|
||||
ConstsUserKBPermission.UserKBPermissionFullControl,
|
||||
|
|
@ -67,7 +79,7 @@ const MENUS = [
|
|||
label: '发布',
|
||||
value: '/release',
|
||||
pathname: 'release',
|
||||
icon: 'icon-paper-full',
|
||||
icon: IconPaperFull,
|
||||
show: true,
|
||||
perms: [
|
||||
ConstsUserKBPermission.UserKBPermissionFullControl,
|
||||
|
|
@ -78,7 +90,7 @@ const MENUS = [
|
|||
label: '设置',
|
||||
value: '/setting',
|
||||
pathname: 'application-setting',
|
||||
icon: 'icon-chilun',
|
||||
icon: IconChilun,
|
||||
show: true,
|
||||
perms: [ConstsUserKBPermission.UserKBPermissionFullControl],
|
||||
},
|
||||
|
|
@ -153,6 +165,7 @@ const Sidebar = () => {
|
|||
isActive = pathname.includes(it.value);
|
||||
}
|
||||
if (!it.show) return null;
|
||||
const IconMenu = it.icon;
|
||||
return (
|
||||
<NavLink
|
||||
key={it.pathname}
|
||||
|
|
@ -181,8 +194,7 @@ const Sidebar = () => {
|
|||
},
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type={it.icon}
|
||||
<IconMenu
|
||||
sx={{
|
||||
fontSize: 14,
|
||||
mr: 1,
|
||||
|
|
@ -216,7 +228,7 @@ const Sidebar = () => {
|
|||
},
|
||||
}}
|
||||
startIcon={
|
||||
<Icon type='icon-bangzhuwendang1' sx={{ width: 14, height: 14 }} />
|
||||
<IconBangzhuwendang1 sx={{ fontSize: '14px !important' }} />
|
||||
}
|
||||
onClick={() =>
|
||||
window.open('https://pandawiki.docs.baizhi.cloud/', '_blank')
|
||||
|
|
@ -244,7 +256,7 @@ const Sidebar = () => {
|
|||
color: 'primary.main',
|
||||
},
|
||||
}}
|
||||
startIcon={<Icon type='icon-GitHub' sx={{ width: 14, height: 14 }} />}
|
||||
startIcon={<IconGithub sx={{ fontSize: '14px !important' }} />}
|
||||
onClick={() =>
|
||||
window.open('https://github.com/chaitin/PandaWiki', '_blank')
|
||||
}
|
||||
|
|
@ -271,7 +283,7 @@ const Sidebar = () => {
|
|||
},
|
||||
}}
|
||||
onClick={() => setShowQrcode(true)}
|
||||
startIcon={<Icon type='icon-group' sx={{ width: 14, height: 14 }} />}
|
||||
startIcon={<IconGroup sx={{ fontSize: '14px !important' }} />}
|
||||
>
|
||||
在线支持
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import Card from '@/components/Card';
|
||||
import { Icon, message } from '@ctzhian/ui';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Stack,
|
||||
TextField,
|
||||
Select,
|
||||
|
|
@ -10,6 +7,8 @@ import {
|
|||
InputAdornment,
|
||||
IconButton,
|
||||
} 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 VisibilityOff from '@mui/icons-material/VisibilityOff';
|
||||
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)',
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type='icon-info-circle'
|
||||
<InfoOutlineSharpIcon
|
||||
sx={{
|
||||
fontSize: 16,
|
||||
color: 'primary.main',
|
||||
|
|
@ -170,7 +168,7 @@ const AutoModelConfig = forwardRef<AutoModelConfigRef, AutoModelConfigProps>(
|
|||
gap: 0.5,
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-key' sx={{ fontSize: 14 }} />
|
||||
<KeySharpIcon sx={{ fontSize: 14, color: 'primary.main' }} />
|
||||
获取百智云 API Key
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ import Card from '@/components/Card';
|
|||
import { copyText, generatePassword } from '@/utils';
|
||||
import { CheckCircle } from '@mui/icons-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 { Controller, useForm } from 'react-hook-form';
|
||||
import { IconShuaxin } from '@panda-wiki/icons';
|
||||
|
||||
type UpdateMemberProps = {
|
||||
user: V1UserListItemResp;
|
||||
|
|
@ -163,7 +164,7 @@ const MemberUpdate = ({ user, refresh, type }: UpdateMemberProps) => {
|
|||
onClick={() => setValue('password', generatePassword())}
|
||||
sx={{ flexShrink: 0 }}
|
||||
>
|
||||
<Icon type='icon-shuaxin' />
|
||||
<IconShuaxin sx={{ fontSize: 16 }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
} from '@/request/Model';
|
||||
import { GithubComChaitinPandaWikiDomainModelListItem } from '@/request/types';
|
||||
import { addOpacityToColor } from '@/utils';
|
||||
import { Icon, message, Modal } from '@ctzhian/ui';
|
||||
import { message, Modal } from '@ctzhian/ui';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
|
|
@ -188,7 +188,7 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
|
|||
const handleSave = async () => {
|
||||
setIsSaving(true);
|
||||
try {
|
||||
let requestData: {
|
||||
const requestData: {
|
||||
mode: 'auto' | 'manual';
|
||||
auto_mode_api_key?: string;
|
||||
chat_model?: string;
|
||||
|
|
@ -224,11 +224,37 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
|
|||
);
|
||||
getModelList(); // 刷新模型列表
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
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 (
|
||||
<Stack gap={0}>
|
||||
<Box
|
||||
|
|
@ -331,14 +357,7 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
|
|||
>
|
||||
{chatModelData ? (
|
||||
<>
|
||||
<Icon
|
||||
type={
|
||||
ModelProvider[
|
||||
chatModelData.provider as keyof typeof ModelProvider
|
||||
].icon
|
||||
}
|
||||
sx={{ fontSize: 18 }}
|
||||
/>
|
||||
{IconModel && <IconModel sx={{ fontSize: 18 }} />}
|
||||
<Box
|
||||
sx={{
|
||||
fontSize: 14,
|
||||
|
|
@ -540,14 +559,10 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
|
|||
>
|
||||
{embeddingModelData ? (
|
||||
<>
|
||||
<Icon
|
||||
type={
|
||||
ModelProvider[
|
||||
embeddingModelData.provider as keyof typeof ModelProvider
|
||||
].icon
|
||||
}
|
||||
sx={{ fontSize: 18 }}
|
||||
/>
|
||||
{IconEmbeddingModel && (
|
||||
<IconEmbeddingModel sx={{ fontSize: 18 }} />
|
||||
)}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
fontSize: 14,
|
||||
|
|
@ -754,14 +769,10 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
|
|||
>
|
||||
{rerankModelData ? (
|
||||
<>
|
||||
<Icon
|
||||
type={
|
||||
ModelProvider[
|
||||
rerankModelData.provider as keyof typeof ModelProvider
|
||||
].icon
|
||||
}
|
||||
sx={{ fontSize: 18 }}
|
||||
/>
|
||||
{IconRerankModel && (
|
||||
<IconRerankModel sx={{ fontSize: 18 }} />
|
||||
)}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
fontSize: 14,
|
||||
|
|
@ -963,14 +974,10 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
|
|||
>
|
||||
{analysisModelData ? (
|
||||
<>
|
||||
<Icon
|
||||
type={
|
||||
ModelProvider[
|
||||
analysisModelData.provider as keyof typeof ModelProvider
|
||||
].icon
|
||||
}
|
||||
sx={{ fontSize: 18 }}
|
||||
/>
|
||||
{IconAnalysisModel && (
|
||||
<IconAnalysisModel sx={{ fontSize: 18 }} />
|
||||
)}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
fontSize: 14,
|
||||
|
|
@ -1172,14 +1179,9 @@ const ModelConfig = forwardRef<ModelConfigRef, ModelConfigProps>(
|
|||
>
|
||||
{analysisVLModelData ? (
|
||||
<>
|
||||
<Icon
|
||||
type={
|
||||
ModelProvider[
|
||||
analysisVLModelData.provider as keyof typeof ModelProvider
|
||||
].icon
|
||||
}
|
||||
sx={{ fontSize: 18 }}
|
||||
/>
|
||||
{IconAnalysisVLModel && (
|
||||
<IconAnalysisVLModel sx={{ fontSize: 18 }} />
|
||||
)}
|
||||
<Box
|
||||
sx={{
|
||||
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 { GithubComChaitinPandaWikiDomainModelListItem } from '@/request/types';
|
||||
import { useAppDispatch, useAppSelector } from '@/store';
|
||||
import { setModelList, setModelStatus } from '@/store/slices/config';
|
||||
import { Icon, message, Modal } from '@ctzhian/ui';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Stack,
|
||||
Tab,
|
||||
Tabs,
|
||||
Tooltip,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { Modal } from '@ctzhian/ui';
|
||||
import { IconAChilunshezhisheding } from '@panda-wiki/icons';
|
||||
import { Box, Button, Tab, Tabs, useTheme } from '@mui/material';
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
import LottieIcon from '../LottieIcon';
|
||||
|
||||
import Member from './component/Member';
|
||||
import ModelConfig, { ModelConfigRef } from './component/ModelConfig';
|
||||
|
||||
|
|
@ -91,7 +81,7 @@ const System = () => {
|
|||
<Button
|
||||
size='small'
|
||||
variant='outlined'
|
||||
startIcon={<Icon type='icon-a-chilunshezhisheding' />}
|
||||
startIcon={<IconAChilunshezhisheding />}
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
系统配置
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Icon } from '@ctzhian/ui';
|
||||
import { Upload as UploadIcon } from '@mui/icons-material';
|
||||
import { Box, Button, Stack, Typography, useTheme } from '@mui/material';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { FileRejection, useDropzone } from 'react-dropzone';
|
||||
import { IconShangchuan } from '@panda-wiki/icons';
|
||||
|
||||
// 文件扩展名到 MIME 类型的映射
|
||||
const FILE_EXTENSION_TO_MIME: Record<string, string> = {
|
||||
|
|
@ -110,8 +110,7 @@ const Upload = ({
|
|||
onClick={() => fileInputRef.current?.click()}
|
||||
>
|
||||
<input {...getInputProps()} />
|
||||
<Icon
|
||||
type='icon-shangchuan'
|
||||
<IconShangchuan
|
||||
sx={{ fontSize: 40, mb: 1, color: 'text.secondary' }}
|
||||
/>
|
||||
<Typography
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { CheckCircle } from '@mui/icons-material';
|
||||
import { Box, Stack, Typography, useTheme, SxProps } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import { IconShangchuan } from '@panda-wiki/icons';
|
||||
|
||||
interface FileTextProps {
|
||||
file?: File;
|
||||
|
|
@ -97,10 +97,7 @@ const FileText = ({
|
|||
{dropFiles.length > 0 ? (
|
||||
<CheckCircle sx={{ color: 'success.main', fontSize: 20 }} />
|
||||
) : (
|
||||
<Icon
|
||||
type='icon-shangchuan'
|
||||
sx={{ fontSize: 20, color: 'text.disabled' }}
|
||||
/>
|
||||
<IconShangchuan sx={{ fontSize: 20, color: 'text.disabled' }} />
|
||||
)}
|
||||
<Typography
|
||||
variant='body1'
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { uploadFile } from '@/api';
|
||||
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 CustomImage from '../CustomImage';
|
||||
import { IconShangchuan, IconIcon_tool_close } from '@panda-wiki/icons';
|
||||
|
||||
interface UploadFileProps {
|
||||
type: 'url' | 'base64';
|
||||
|
|
@ -241,7 +242,7 @@ const UploadFile = ({
|
|||
onChange('');
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-icon_tool_close' sx={{ color: '#fff' }} />
|
||||
<IconIcon_tool_close sx={{ fontSize: 16, color: '#fff' }} />
|
||||
</IconButton>
|
||||
</>
|
||||
) : (
|
||||
|
|
@ -253,8 +254,7 @@ const UploadFile = ({
|
|||
fontSize: width ? (width < 40 ? 8 : 12) : 12,
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type='icon-shangchuan'
|
||||
<IconShangchuan
|
||||
sx={{ fontSize: width ? (width < 40 ? 12 : 18) : 18 }}
|
||||
/>
|
||||
<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 = {
|
||||
1: {
|
||||
label: '正在处理',
|
||||
|
|
@ -30,47 +81,47 @@ export const IconMap = {
|
|||
export const AppType = {
|
||||
1: {
|
||||
label: 'Wiki 网站',
|
||||
icon: 'icon-a-Webyingyong',
|
||||
icon: IconAWebyingyong,
|
||||
},
|
||||
2: {
|
||||
label: '网页挂件',
|
||||
icon: 'icon-wangyeguajian',
|
||||
icon: IconWangyeguajian,
|
||||
},
|
||||
3: {
|
||||
label: '钉钉机器人',
|
||||
icon: 'icon-dingdingjiqiren',
|
||||
icon: IconDingdingjiqiren,
|
||||
},
|
||||
4: {
|
||||
label: '飞书机器人',
|
||||
icon: 'icon-feishujiqiren',
|
||||
icon: IconFeishujiqiren,
|
||||
},
|
||||
5: {
|
||||
label: '企业微信机器人',
|
||||
icon: 'icon-qiyeweixinjiqiren',
|
||||
icon: IconQiyeweixinjiqiren,
|
||||
},
|
||||
6: {
|
||||
label: '企业微信客服',
|
||||
icon: 'icon-qiyeweixinkefu',
|
||||
icon: IconQiyeweixinkefu,
|
||||
},
|
||||
7: {
|
||||
label: 'Discord 机器人',
|
||||
icon: 'icon-a-discordjiqiren',
|
||||
icon: IconADiscordjiqiren,
|
||||
},
|
||||
8: {
|
||||
label: '微信公众号',
|
||||
icon: 'icon-weixingongzhonghao-daiyanse',
|
||||
icon: IconWeixingongzhonghaoDaiyanse,
|
||||
},
|
||||
9: {
|
||||
label: '问答机器人 API',
|
||||
icon: 'icon-Wendajiqiren',
|
||||
icon: IconWendajiqiren,
|
||||
},
|
||||
10: {
|
||||
label: '企业微信智能机器人',
|
||||
icon: 'icon-qiyeweixinjiqiren',
|
||||
icon: IconQiyeweixinjiqiren,
|
||||
},
|
||||
11: {
|
||||
label: 'Lark 机器人',
|
||||
icon: 'icon-feishujiqiren',
|
||||
icon: IconFeishujiqiren,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -115,7 +166,7 @@ export const ModelProvider = {
|
|||
BaiZhiCloud: {
|
||||
label: 'BaiZhiCloud',
|
||||
cn: '百智云',
|
||||
icon: 'icon-baizhiyunlogo',
|
||||
icon: IconBaizhiyunlogo,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -129,7 +180,7 @@ export const ModelProvider = {
|
|||
ZhiPu: {
|
||||
label: 'ZhiPu',
|
||||
cn: '智谱',
|
||||
icon: 'icon-zhipuqingyan', // 需要添加对应的图标
|
||||
icon: IconZhipuqingyan, // 需要添加对应的图标
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -143,7 +194,7 @@ export const ModelProvider = {
|
|||
DeepSeek: {
|
||||
label: 'DeepSeek',
|
||||
cn: 'DeepSeek',
|
||||
icon: 'icon-deepseek',
|
||||
icon: IconDeepseek,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -157,7 +208,7 @@ export const ModelProvider = {
|
|||
Hunyuan: {
|
||||
label: 'Hunyuan',
|
||||
cn: '腾讯混元',
|
||||
icon: 'icon-tengxunhunyuan',
|
||||
icon: IconTengxunhunyuan,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -171,7 +222,7 @@ export const ModelProvider = {
|
|||
BaiLian: {
|
||||
label: 'BaiLian',
|
||||
cn: '阿里云百炼',
|
||||
icon: 'icon-aliyunbailian',
|
||||
icon: IconAliyunbailian,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -186,7 +237,7 @@ export const ModelProvider = {
|
|||
Volcengine: {
|
||||
label: 'Volcengine',
|
||||
cn: '火山引擎',
|
||||
icon: 'icon-huoshanyinqing',
|
||||
icon: IconHuoshanyinqing,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -200,7 +251,7 @@ export const ModelProvider = {
|
|||
OpenAI: {
|
||||
label: 'OpenAI',
|
||||
cn: 'OpenAI',
|
||||
icon: 'icon-chatgpt',
|
||||
icon: IconChatgpt,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -214,7 +265,7 @@ export const ModelProvider = {
|
|||
Ollama: {
|
||||
label: 'Ollama',
|
||||
cn: 'Ollama',
|
||||
icon: 'icon-ollama',
|
||||
icon: IconOllama,
|
||||
urlWrite: true,
|
||||
secretRequired: false,
|
||||
customHeader: true,
|
||||
|
|
@ -228,7 +279,7 @@ export const ModelProvider = {
|
|||
SiliconFlow: {
|
||||
label: 'SiliconFlow',
|
||||
cn: '硅基流动',
|
||||
icon: 'icon-a-ziyuan2',
|
||||
icon: IconAZiyuan2,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -242,7 +293,7 @@ export const ModelProvider = {
|
|||
Moonshot: {
|
||||
label: 'Moonshot',
|
||||
cn: '月之暗面',
|
||||
icon: 'icon-Kim',
|
||||
icon: IconKim,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -256,7 +307,7 @@ export const ModelProvider = {
|
|||
AzureOpenAI: {
|
||||
label: 'AzureOpenAI',
|
||||
cn: 'Azure OpenAI',
|
||||
icon: 'icon-azure',
|
||||
icon: IconAzure,
|
||||
urlWrite: true,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -271,7 +322,7 @@ export const ModelProvider = {
|
|||
Gemini: {
|
||||
label: 'Gemini',
|
||||
cn: 'Gemini',
|
||||
icon: 'icon-gemini',
|
||||
icon: IconGemini,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -285,7 +336,7 @@ export const ModelProvider = {
|
|||
Qiniu: {
|
||||
label: 'Qiniu',
|
||||
cn: '七牛云',
|
||||
icon: 'icon-qiniuyun',
|
||||
icon: IconQiniuyun,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -339,7 +390,7 @@ export const ModelProvider = {
|
|||
Xinference: {
|
||||
label: 'Xinference',
|
||||
cn: 'Xinference',
|
||||
icon: 'icon-Xinference',
|
||||
icon: IconXinference,
|
||||
urlWrite: true,
|
||||
secretRequired: false,
|
||||
customHeader: false,
|
||||
|
|
@ -355,7 +406,7 @@ export const ModelProvider = {
|
|||
gpustack: {
|
||||
label: 'gpustack',
|
||||
cn: 'GPUStack',
|
||||
icon: 'icon-gpustack',
|
||||
icon: IconGpustack,
|
||||
urlWrite: true,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -370,7 +421,7 @@ export const ModelProvider = {
|
|||
Yi: {
|
||||
label: 'Yi',
|
||||
cn: '零一万物',
|
||||
icon: 'icon-lingyiwanwu',
|
||||
icon: IconLingyiwanwu,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -445,7 +496,7 @@ export const ModelProvider = {
|
|||
CTYun: {
|
||||
label: 'CTYun',
|
||||
cn: '天翼云息壤',
|
||||
icon: 'icon-tianyiyun',
|
||||
icon: IconTianyiyun,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -459,7 +510,7 @@ export const ModelProvider = {
|
|||
TencentTI: {
|
||||
label: 'TencentTI',
|
||||
cn: '腾讯云TI',
|
||||
icon: 'icon-tengxunyun',
|
||||
icon: IconTengxunyun,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -473,7 +524,7 @@ export const ModelProvider = {
|
|||
BaiDuQianFan: {
|
||||
label: 'BaiDuQianFan',
|
||||
cn: '百度云千帆',
|
||||
icon: 'icon-baiduyun',
|
||||
icon: IconBaiduyun,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -487,7 +538,7 @@ export const ModelProvider = {
|
|||
ModelScope: {
|
||||
label: 'ModelScope',
|
||||
cn: '魔搭社区',
|
||||
icon: 'icon-modaGPT',
|
||||
icon: IconModaGPT,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -502,7 +553,7 @@ export const ModelProvider = {
|
|||
Infini: {
|
||||
label: 'Infini',
|
||||
cn: '无问芯穹',
|
||||
icon: 'icon-infini',
|
||||
icon: IconInfini,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -517,7 +568,7 @@ export const ModelProvider = {
|
|||
StepFun: {
|
||||
label: 'StepFun',
|
||||
cn: '阶跃星辰',
|
||||
icon: 'icon-step',
|
||||
icon: IconStep,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -531,7 +582,7 @@ export const ModelProvider = {
|
|||
LanYun: {
|
||||
label: 'LanYun',
|
||||
cn: '蓝耘科技',
|
||||
icon: 'icon-lanyun',
|
||||
icon: IconLanyun,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -545,7 +596,7 @@ export const ModelProvider = {
|
|||
AlayaNew: {
|
||||
label: 'AlayaNew',
|
||||
cn: '九章智算云',
|
||||
icon: 'icon-alayanew',
|
||||
icon: IconAlayanew,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -560,7 +611,7 @@ export const ModelProvider = {
|
|||
PPIO: {
|
||||
label: 'PPIO',
|
||||
cn: '欧派云',
|
||||
icon: 'icon-ppio',
|
||||
icon: IconPpio,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -575,7 +626,7 @@ export const ModelProvider = {
|
|||
AiHubMix: {
|
||||
label: 'AiHubMix',
|
||||
cn: 'AiHubMix',
|
||||
icon: 'icon-aihubmix',
|
||||
icon: IconAihubmix,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -589,7 +640,7 @@ export const ModelProvider = {
|
|||
OcoolAI: {
|
||||
label: 'OcoolAI',
|
||||
cn: 'OcoolAI',
|
||||
icon: 'icon-ocoolai',
|
||||
icon: IconOcoolai,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -603,7 +654,7 @@ export const ModelProvider = {
|
|||
DMXAPI: {
|
||||
label: 'DMXAPI',
|
||||
cn: 'DMXAPI',
|
||||
icon: 'icon-DMXAPI',
|
||||
icon: IconDMXAPI,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -617,7 +668,7 @@ export const ModelProvider = {
|
|||
BurnCloud: {
|
||||
label: 'BurnCloud',
|
||||
cn: 'BurnCloud',
|
||||
icon: 'icon-burncloud',
|
||||
icon: IconBurncloud,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -641,7 +692,7 @@ export const ModelProvider = {
|
|||
Nvidia: {
|
||||
label: 'Nvidia',
|
||||
cn: '英伟达',
|
||||
icon: 'icon-yingweida',
|
||||
icon: IconYingweida,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -655,7 +706,7 @@ export const ModelProvider = {
|
|||
TokenFlux: {
|
||||
label: 'TokenFlux',
|
||||
cn: 'TokenFlux',
|
||||
icon: 'icon-tokenflux',
|
||||
icon: IconTokenflux,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -669,7 +720,7 @@ export const ModelProvider = {
|
|||
AI302: {
|
||||
label: 'AI302',
|
||||
cn: '302.AI',
|
||||
icon: 'icon-a-302ai',
|
||||
icon: IconA302ai,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -683,7 +734,7 @@ export const ModelProvider = {
|
|||
Cephalon: {
|
||||
label: 'Cephalon',
|
||||
cn: 'Cephalon',
|
||||
icon: 'icon-cephalon',
|
||||
icon: IconCephalon,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -697,7 +748,7 @@ export const ModelProvider = {
|
|||
OpenRouter: {
|
||||
label: 'OpenRouter',
|
||||
cn: 'OpenRouter',
|
||||
icon: 'icon-openrouter',
|
||||
icon: IconOpenrouter,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -711,7 +762,7 @@ export const ModelProvider = {
|
|||
Fireworks: {
|
||||
label: 'Fireworks',
|
||||
cn: 'Fireworks',
|
||||
icon: 'icon-fireworks',
|
||||
icon: IconFireworks,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -725,7 +776,7 @@ export const ModelProvider = {
|
|||
Mistral: {
|
||||
label: 'Mistral',
|
||||
cn: 'Mistral',
|
||||
icon: 'icon-Mistral',
|
||||
icon: IconMistral,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -739,7 +790,7 @@ export const ModelProvider = {
|
|||
Perplexity: {
|
||||
label: 'Perplexity',
|
||||
cn: 'Perplexity',
|
||||
icon: 'icon-perplexity',
|
||||
icon: IconPerplexity,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -753,7 +804,7 @@ export const ModelProvider = {
|
|||
Hyperbolic: {
|
||||
label: 'Hyperbolic',
|
||||
cn: 'Hyperbolic',
|
||||
icon: 'icon-hyperbolic',
|
||||
icon: IconHyperbolic,
|
||||
urlWrite: false,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -767,7 +818,7 @@ export const ModelProvider = {
|
|||
Other: {
|
||||
label: 'Other',
|
||||
cn: '其他',
|
||||
icon: 'icon-a-AIshezhi',
|
||||
icon: IconAAIshezhi,
|
||||
urlWrite: true,
|
||||
secretRequired: true,
|
||||
customHeader: false,
|
||||
|
|
@ -11,8 +11,6 @@ import { BrowserRouter } from 'react-router-dom';
|
|||
import App from './App';
|
||||
import store from './store';
|
||||
|
||||
import '@/assets/fonts/iconfont';
|
||||
|
||||
dayjs.extend(duration);
|
||||
dayjs.extend(relativeTime);
|
||||
dayjs.locale('zh-cn');
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ import DragTree from '@/components/Drag/DragTree';
|
|||
import { useAppSelector } from '@/store';
|
||||
import { convertToTree } from '@/utils/drag';
|
||||
import { Box, Checkbox, Stack } from '@mui/material';
|
||||
import { Icon, Modal } from '@ctzhian/ui';
|
||||
import { Modal } from '@ctzhian/ui';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { getApiV1NodeList } from '@/request/Node';
|
||||
import { IconWenjianjiaKai } from '@panda-wiki/icons';
|
||||
|
||||
interface DocDeleteProps {
|
||||
open: boolean;
|
||||
|
|
@ -48,7 +49,7 @@ const DocModal = ({ open, onClose, onOk }: DocDeleteProps) => {
|
|||
setFolderIds(folderIds.includes('root') ? [] : ['root']);
|
||||
}}
|
||||
/>
|
||||
<Icon type={'icon-wenjianjia-kai'} />
|
||||
<IconWenjianjiaKai sx={{ fontSize: 16 }} />
|
||||
<Box>根路径</Box>
|
||||
</Stack>
|
||||
<DragTree
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import {
|
|||
} from '@mui/material';
|
||||
import { Ellipsis, Icon, Modal } from '@ctzhian/ui';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { IconDitu_diqiu } from '@panda-wiki/icons';
|
||||
|
||||
const handleThinkingContent = (content: string) => {
|
||||
const thinkRegex = /<think>([\s\S]*?)(?:<\/think>|$)/g;
|
||||
|
|
@ -302,8 +303,7 @@ const Detail = ({
|
|||
src={item.favicon}
|
||||
sx={{ width: 18, height: 18 }}
|
||||
errorIcon={
|
||||
<Icon
|
||||
type='icon-ditu_diqiu'
|
||||
<IconDitu_diqiu
|
||||
sx={{ fontSize: 18, color: 'text.tertiary' }}
|
||||
/>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useURLSearchParams } from '@/hooks';
|
||||
import { IconButton, InputAdornment, Stack, TextField } from '@mui/material';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { useState } from 'react';
|
||||
import { IconIcon_tool_close } from '@panda-wiki/icons';
|
||||
|
||||
const Search = () => {
|
||||
const [searchParams, setSearchParams] = useURLSearchParams();
|
||||
|
|
@ -37,8 +37,7 @@ const Search = () => {
|
|||
}}
|
||||
size='small'
|
||||
>
|
||||
<Icon
|
||||
type='icon-icon_tool_close'
|
||||
<IconIcon_tool_close
|
||||
sx={{ fontSize: 14, color: 'text.tertiary' }}
|
||||
/>
|
||||
</IconButton>
|
||||
|
|
@ -70,8 +69,7 @@ const Search = () => {
|
|||
}}
|
||||
size='small'
|
||||
>
|
||||
<Icon
|
||||
type='icon-icon_tool_close'
|
||||
<IconIcon_tool_close
|
||||
sx={{ fontSize: 14, color: 'text.tertiary' }}
|
||||
/>
|
||||
</IconButton>
|
||||
|
|
|
|||
|
|
@ -34,15 +34,12 @@ const Conversation = () => {
|
|||
title: '问题',
|
||||
render: (text: string, record) => {
|
||||
const isGroupChat = record.info?.user_info?.from === 1;
|
||||
const AppIcon =
|
||||
AppType[record.app_type as keyof typeof AppType]?.icon || '';
|
||||
return (
|
||||
<>
|
||||
<Stack direction={'row'} alignItems={'center'} gap={1}>
|
||||
<Icon
|
||||
sx={{ fontSize: 12 }}
|
||||
type={
|
||||
AppType[record.app_type as keyof typeof AppType]?.icon || ''
|
||||
}
|
||||
/>
|
||||
<AppIcon sx={{ fontSize: 12 }}></AppIcon>
|
||||
<Ellipsis
|
||||
className='primary-color'
|
||||
sx={{ cursor: 'pointer', flex: 1, width: 0 }}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { ConstsCrawlerSource, postApiV1CrawlerParse } from '@/request';
|
||||
import { useAppSelector } from '@/store';
|
||||
import { Ellipsis, Icon } from '@ctzhian/ui';
|
||||
import { Ellipsis } from '@ctzhian/ui';
|
||||
import {
|
||||
alpha,
|
||||
Box,
|
||||
|
|
@ -20,6 +20,7 @@ import { ListDataItem } from '..';
|
|||
import StatusBackground from '../components/StatusBackground';
|
||||
import StatusBadge from '../components/StatusBadge';
|
||||
import { flattenCrawlerParseResponse } from '../util';
|
||||
import { IconWenjianjia, IconWenjian } from '@panda-wiki/icons';
|
||||
|
||||
interface ListRenderItemProps {
|
||||
depth: number;
|
||||
|
|
@ -182,15 +183,9 @@ const ListRenderItem = ({
|
|||
)}
|
||||
<Box sx={{ ml: depth * 3 }}>
|
||||
{!data.file ? (
|
||||
<Icon
|
||||
type='icon-wenjianjia'
|
||||
sx={{ fontSize: 14, width: 20, ml: '10px' }}
|
||||
/>
|
||||
<IconWenjianjia sx={{ fontSize: 14, width: 20, ml: '10px' }} />
|
||||
) : (
|
||||
<Icon
|
||||
type='icon-wenjian'
|
||||
sx={{ fontSize: 14, width: 20, ml: '10px' }}
|
||||
/>
|
||||
<IconWenjian sx={{ fontSize: 14, width: 20, ml: '10px' }} />
|
||||
)}
|
||||
</Box>
|
||||
</ListItemIcon>
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import { useEffect, useMemo, useState } from 'react';
|
|||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { BUSINESS_VERSION_PERMISSION } from '@/constant/version';
|
||||
import { VersionCanUse } from '@/components/VersionMask';
|
||||
import { IconShuaxin } from '@panda-wiki/icons';
|
||||
|
||||
interface DocPropertiesModalProps {
|
||||
open: boolean;
|
||||
|
|
@ -472,13 +473,13 @@ const DocPropertiesModal = ({
|
|||
onClick={onGenerateSummary}
|
||||
disabled={loading}
|
||||
startIcon={
|
||||
<Icon
|
||||
type='icon-shuaxin'
|
||||
sx={
|
||||
loading
|
||||
<IconShuaxin
|
||||
sx={{
|
||||
fontSize: '16px !important',
|
||||
...(loading
|
||||
? { animation: 'loadingRotate 1s linear infinite' }
|
||||
: {}
|
||||
}
|
||||
: {}),
|
||||
}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { useURLSearchParams } from '@/hooks';
|
||||
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';
|
||||
|
||||
const DocSearch = () => {
|
||||
|
|
@ -32,8 +32,7 @@ const DocSearch = () => {
|
|||
}}
|
||||
size='small'
|
||||
>
|
||||
<Icon
|
||||
type='icon-icon_tool_close'
|
||||
<IconIcon_tool_close
|
||||
sx={{ fontSize: 14, color: 'text.tertiary' }}
|
||||
/>
|
||||
</IconButton>
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ import { postApiV1NodeBatchMove } from '@/request/Node';
|
|||
import { DomainNodeListItemResp } from '@/request/types';
|
||||
import { useAppSelector } from '@/store';
|
||||
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 { useEffect, useState } from 'react';
|
||||
import { IconWenjianjiaKai } from '@panda-wiki/icons';
|
||||
|
||||
interface DocDeleteProps {
|
||||
open: boolean;
|
||||
|
|
@ -83,7 +84,7 @@ const MoveDocs = ({
|
|||
setFolderIds(folderIds.includes('root') ? [] : ['root']);
|
||||
}}
|
||||
/>
|
||||
<Icon type={'icon-wenjianjia-kai'} />
|
||||
<IconWenjianjiaKai sx={{ fontSize: 14 }} />
|
||||
<Box>根路径</Box>
|
||||
</Stack>
|
||||
<DragTree
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { postApiV1NodeSummary, putApiV1NodeDetail } from '@/request/Node';
|
||||
import { DomainNodeListItemResp } from '@/request/types';
|
||||
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 { IconShuaxin } from '@panda-wiki/icons';
|
||||
|
||||
interface SummaryProps {
|
||||
kb_id: string;
|
||||
|
|
@ -63,13 +64,13 @@ const Summary = ({ open, data, kb_id, onClose, refresh }: SummaryProps) => {
|
|||
onClick={createSummary}
|
||||
disabled={loading}
|
||||
startIcon={
|
||||
<Icon
|
||||
type='icon-shuaxin'
|
||||
sx={
|
||||
loading
|
||||
<IconShuaxin
|
||||
sx={{
|
||||
fontSize: '16px !important',
|
||||
...(loading
|
||||
? { animation: 'loadingRotate 1s linear infinite' }
|
||||
: {}
|
||||
}
|
||||
: {}),
|
||||
}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { useAppSelector } from '@/store';
|
||||
import { Ellipsis, Icon } from '@ctzhian/ui';
|
||||
import { Ellipsis } from '@ctzhian/ui';
|
||||
import { Stack } from '@mui/material';
|
||||
import { useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { IconZuzhi } from '@panda-wiki/icons';
|
||||
|
||||
const KBSwitch = () => {
|
||||
// const dispatch = useAppDispatch();
|
||||
|
|
@ -46,7 +47,7 @@ const KBSwitch = () => {
|
|||
navigate('/');
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-zuzhi' sx={{ color: 'text.primary' }} />
|
||||
<IconZuzhi type='icon-zuzhi' sx={{ color: 'text.primary' }} />
|
||||
</Stack>
|
||||
<Ellipsis sx={{ flex: 1, width: 0, overflow: 'hidden' }}>
|
||||
{currentKb?.name}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,19 @@ import { DomainNodeListItemResp, V1NodeDetailResp } from '@/request/types';
|
|||
import { useAppSelector } from '@/store';
|
||||
import { addOpacityToColor } from '@/utils';
|
||||
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 { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import DocAddByCustomText from '../../component/DocAddByCustomText';
|
||||
import KBSwitch from './KBSwitch';
|
||||
import {
|
||||
IconIcon_tool_close,
|
||||
IconWenjianjia,
|
||||
IconWenjian,
|
||||
IconMulushouqi,
|
||||
IconXiajiantou,
|
||||
} from '@panda-wiki/icons';
|
||||
|
||||
interface CatalogProps {
|
||||
curNode: V1NodeDetailResp;
|
||||
|
|
@ -123,9 +130,8 @@ const Catalog = ({ curNode, setCatalogOpen }: CatalogProps) => {
|
|||
}}
|
||||
context={
|
||||
<IconButton>
|
||||
<Icon
|
||||
<IconIcon_tool_close
|
||||
className='catalog-folder-add-icon'
|
||||
type='icon-icon_tool_close'
|
||||
sx={{
|
||||
fontSize: 16,
|
||||
color: 'action.selected',
|
||||
|
|
@ -235,8 +241,7 @@ const Catalog = ({ curNode, setCatalogOpen }: CatalogProps) => {
|
|||
top: 13,
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type='icon-xiajiantou'
|
||||
<IconXiajiantou
|
||||
sx={{
|
||||
fontSize: 16,
|
||||
color: 'text.disabled',
|
||||
|
|
@ -251,10 +256,13 @@ const Catalog = ({ curNode, setCatalogOpen }: CatalogProps) => {
|
|||
)}
|
||||
{item.emoji ? (
|
||||
<Box sx={{ fontSize: 14, flexShrink: 0 }}>{item.emoji}</Box>
|
||||
) : item.type === 1 ? (
|
||||
<IconWenjianjia
|
||||
sx={{ color: '#2f80f7', flexShrink: 0, fontSize: 14 }}
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
type={item.type === 1 ? 'icon-wenjianjia' : 'icon-wenjian'}
|
||||
sx={{ color: '#2f80f7', flexShrink: 0 }}
|
||||
<IconWenjian
|
||||
sx={{ color: '#2f80f7', flexShrink: 0, fontSize: 14 }}
|
||||
/>
|
||||
)}
|
||||
<Ellipsis>{item.name}</Ellipsis>
|
||||
|
|
@ -336,8 +344,7 @@ const Catalog = ({ curNode, setCatalogOpen }: CatalogProps) => {
|
|||
},
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type='icon-mulushouqi'
|
||||
<IconMulushouqi
|
||||
sx={{
|
||||
fontSize: 24,
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
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 { postApiV1Node } from '@/request';
|
||||
import { V1NodeDetailResp } from '@/request/types';
|
||||
import { useAppSelector } from '@/store';
|
||||
import { addOpacityToColor, getShortcutKeyText } from '@/utils';
|
||||
import { Ellipsis, Icon, message } from '@ctzhian/ui';
|
||||
import InfoIcon from '@mui/icons-material/Info';
|
||||
import { Ellipsis, message } from '@ctzhian/ui';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
|
|
@ -16,14 +17,18 @@ import {
|
|||
Tooltip,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import {
|
||||
IconBaocun,
|
||||
IconDaochu,
|
||||
IconGengduo,
|
||||
IconMuluzhankai,
|
||||
} from '@panda-wiki/icons';
|
||||
import dayjs from 'dayjs';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useNavigate, useOutletContext } from 'react-router-dom';
|
||||
import { WrapContext } from '..';
|
||||
import DocAddByCustomText from '../../component/DocAddByCustomText';
|
||||
import DocDelete from '../../component/DocDelete';
|
||||
import { BUSINESS_VERSION_PERMISSION } from '@/constant/version';
|
||||
import { VersionCanUse } from '@/components/VersionMask';
|
||||
|
||||
interface HeaderProps {
|
||||
edit: boolean;
|
||||
|
|
@ -43,8 +48,14 @@ const Header = ({
|
|||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
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 } =
|
||||
useOutletContext<WrapContext>();
|
||||
|
||||
|
|
@ -58,6 +69,25 @@ const Header = ({
|
|||
return BUSINESS_VERSION_PERMISSION.includes(license.edition!);
|
||||
}, [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(() => {
|
||||
if (nodeDetail?.status === 2 && !edit) {
|
||||
message.info('当前已是最新版本!');
|
||||
|
|
@ -101,15 +131,13 @@ const Header = ({
|
|||
},
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type='icon-muluzhankai'
|
||||
<IconMuluzhankai
|
||||
sx={{
|
||||
fontSize: 24,
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
{/* {detail.meta?.content_type === 'md' && <Icon type='icon-a-icon_huaban1fuben22' sx={{ fontSize: 30 }} />} */}
|
||||
{detail.meta?.content_type === 'md' && (
|
||||
<Box
|
||||
component={'span'}
|
||||
|
|
@ -149,7 +177,7 @@ const Header = ({
|
|||
gap={0.5}
|
||||
sx={{ fontSize: 12, color: 'text.tertiary' }}
|
||||
>
|
||||
<Icon type='icon-baocun' />
|
||||
<IconBaocun sx={{ fontSize: 12 }} />
|
||||
{showSaveTip ? (
|
||||
'已保存'
|
||||
) : nodeDetail?.updated_at ? (
|
||||
|
|
@ -159,156 +187,9 @@ const Header = ({
|
|||
)}
|
||||
</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}>
|
||||
<Cascader
|
||||
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',
|
||||
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',
|
||||
textSx: { flex: 1 },
|
||||
|
|
@ -367,7 +260,7 @@ const Header = ({
|
|||
disabled={!detail.name}
|
||||
sx={{ flexShrink: 0 }}
|
||||
>
|
||||
<Icon type='icon-gengduo' />
|
||||
<IconGengduo sx={{ fontSize: 14 }} />
|
||||
</IconButton>
|
||||
}
|
||||
/>
|
||||
|
|
@ -435,7 +328,7 @@ const Header = ({
|
|||
size='small'
|
||||
variant='outlined'
|
||||
disabled={!detail.name}
|
||||
startIcon={<Icon type='icon-daochu' />}
|
||||
startIcon={<IconDaochu sx={{ fontSize: 14 }} />}
|
||||
>
|
||||
导出
|
||||
</Button>
|
||||
|
|
@ -511,7 +404,7 @@ const Header = ({
|
|||
size='small'
|
||||
variant='contained'
|
||||
disabled={!detail.name}
|
||||
startIcon={<Icon type='icon-baocun' />}
|
||||
startIcon={<IconBaocun sx={{ fontSize: 14 }} />}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -1,22 +1,13 @@
|
|||
import { useTiptap } from '@ctzhian/tiptap';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { Box, Skeleton, Stack } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import { useOutletContext } from 'react-router-dom';
|
||||
import { WrapContext } from '..';
|
||||
import Header from './Header';
|
||||
import Toolbar from './Toolbar';
|
||||
import { IconAShijian2, IconZiti } from '@panda-wiki/icons';
|
||||
|
||||
const LoadingEditorWrap = () => {
|
||||
const { catalogOpen } = useOutletContext<WrapContext>();
|
||||
const [isSyncing] = useState(false);
|
||||
const [collaborativeUsers] = useState<
|
||||
Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
color: string;
|
||||
}>
|
||||
>([]);
|
||||
|
||||
const editorRef = useTiptap({
|
||||
editable: false,
|
||||
|
|
@ -62,11 +53,11 @@ const LoadingEditorWrap = () => {
|
|||
</Stack>
|
||||
<Stack direction={'row'} alignItems={'center'} gap={2} sx={{ mb: 4 }}>
|
||||
<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} />
|
||||
</Stack>
|
||||
<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} />
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ import {
|
|||
V1NodeDetailResp,
|
||||
} from '@/request';
|
||||
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 { useEffect, useState } from 'react';
|
||||
import { useOutletContext } from 'react-router-dom';
|
||||
import { WrapContext } from '..';
|
||||
import { IconDJzhinengzhaiyao } from '@panda-wiki/icons';
|
||||
|
||||
interface SummaryProps {
|
||||
open: boolean;
|
||||
|
|
@ -95,7 +96,7 @@ const Summary = ({ open, onClose, updateDetail }: SummaryProps) => {
|
|||
loading ? (
|
||||
<CircularProgress size={16} />
|
||||
) : (
|
||||
<Icon type='icon-DJzhinengzhaiyao' sx={{ fontSize: 16 }} />
|
||||
<IconDJzhinengzhaiyao sx={{ fontSize: 16 }} />
|
||||
)
|
||||
}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@ import {
|
|||
H6Icon,
|
||||
TocList,
|
||||
} from '@ctzhian/tiptap';
|
||||
import { Ellipsis, Icon } from '@ctzhian/ui';
|
||||
import { Ellipsis } from '@ctzhian/ui';
|
||||
import { Box, Drawer, IconButton, Stack } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import { IconDingzi, IconIcon_tool_close } from '@panda-wiki/icons';
|
||||
|
||||
interface TocProps {
|
||||
headings: TocList;
|
||||
|
|
@ -139,10 +140,11 @@ const Toc = ({
|
|||
setFixed(!fixed);
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type={!fixed ? 'icon-dingzi' : 'icon-icon_tool_close'}
|
||||
sx={{ fontSize: 18 }}
|
||||
/>
|
||||
{!fixed ? (
|
||||
<IconDingzi sx={{ fontSize: 18 }} />
|
||||
) : (
|
||||
<IconIcon_tool_close sx={{ fontSize: 18 }} />
|
||||
)}
|
||||
</IconButton>
|
||||
</Stack>
|
||||
<Stack
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
useTiptap,
|
||||
UseTiptapReturn,
|
||||
} from '@ctzhian/tiptap';
|
||||
import { Icon, message } from '@ctzhian/ui';
|
||||
import { message } from '@ctzhian/ui';
|
||||
import { Box, Stack, TextField, Tooltip } from '@mui/material';
|
||||
import dayjs from 'dayjs';
|
||||
import { debounce } from 'lodash-es';
|
||||
|
|
@ -30,6 +30,12 @@ import Summary from './Summary';
|
|||
import Toc from './Toc';
|
||||
import Toolbar from './Toolbar';
|
||||
import { BUSINESS_VERSION_PERMISSION } from '@/constant/version';
|
||||
import {
|
||||
IconTianjiawendang,
|
||||
IconAShijian2,
|
||||
IconZiti,
|
||||
IconDJzhinengzhaiyao,
|
||||
} from '@panda-wiki/icons';
|
||||
|
||||
interface WrapProps {
|
||||
detail: V1NodeDetailResp;
|
||||
|
|
@ -379,7 +385,7 @@ const Wrap = ({ detail: defaultDetail }: WrapProps) => {
|
|||
color: 'text.tertiary',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-tianjiawendang' sx={{ fontSize: 9 }} />
|
||||
<IconTianjiawendang sx={{ fontSize: 9 }} />
|
||||
{nodeDetail?.editor_account} 编辑
|
||||
</Stack>
|
||||
</Tooltip>
|
||||
|
|
@ -403,7 +409,7 @@ const Wrap = ({ detail: defaultDetail }: WrapProps) => {
|
|||
}
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-a-shijian2' />
|
||||
<IconAShijian2 sx={{ fontSize: 12 }} />
|
||||
{dayjs(defaultDetail.created_at).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)}{' '}
|
||||
|
|
@ -416,7 +422,7 @@ const Wrap = ({ detail: defaultDetail }: WrapProps) => {
|
|||
gap={0.5}
|
||||
sx={{ fontSize: 12, color: 'text.tertiary' }}
|
||||
>
|
||||
<Icon type='icon-ziti' />
|
||||
<IconZiti sx={{ fontSize: 12 }} />
|
||||
{characterCount} 字
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
@ -463,7 +469,7 @@ const Wrap = ({ detail: defaultDetail }: WrapProps) => {
|
|||
},
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-DJzhinengzhaiyao' sx={{ fontSize: 12 }} />
|
||||
<IconDJzhinengzhaiyao sx={{ fontSize: 12 }} />
|
||||
文档摘要
|
||||
</Stack>
|
||||
{nodeDetail?.meta?.summary ? (
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
} from '@/request/pro';
|
||||
import { useAppSelector } from '@/store';
|
||||
import { Editor, useTiptap } from '@ctzhian/tiptap';
|
||||
import { Ellipsis, Icon } from '@ctzhian/ui';
|
||||
import { Ellipsis } from '@ctzhian/ui';
|
||||
import {
|
||||
alpha,
|
||||
Box,
|
||||
|
|
@ -22,6 +22,14 @@ import { useEffect, useState } from 'react';
|
|||
import { useNavigate, useOutletContext, useParams } from 'react-router-dom';
|
||||
import { WrapContext } from '..';
|
||||
import VersionRollback from '../../component/VersionRollback';
|
||||
import {
|
||||
IconMuluzhankai,
|
||||
IconChahao,
|
||||
IconTianjiawendang,
|
||||
IconZiti,
|
||||
IconFabu,
|
||||
IconAShijian2,
|
||||
} from '@panda-wiki/icons';
|
||||
|
||||
const History = () => {
|
||||
const { id = '' } = useParams();
|
||||
|
|
@ -128,8 +136,7 @@ const History = () => {
|
|||
},
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
type='icon-muluzhankai'
|
||||
<IconMuluzhankai
|
||||
sx={{
|
||||
fontSize: 24,
|
||||
}}
|
||||
|
|
@ -144,7 +151,7 @@ const History = () => {
|
|||
navigate(`/doc/editor/${id}`);
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-chahao' />
|
||||
<IconChahao sx={{ fontSize: 16 }} />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
<Box sx={{ mt: '56px', mr: '292px' }}>
|
||||
|
|
@ -211,17 +218,17 @@ const History = () => {
|
|||
gap={0.5}
|
||||
sx={{ cursor: 'pointer' }}
|
||||
>
|
||||
<Icon type='icon-tianjiawendang' sx={{ fontSize: 9 }} />
|
||||
<IconTianjiawendang sx={{ fontSize: 9 }} />
|
||||
{curNode.editor_account} 编辑
|
||||
</Stack>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Stack direction={'row'} alignItems={'center'} gap={0.5}>
|
||||
<Icon type='icon-a-shijian2' />
|
||||
<IconAShijian2 sx={{ fontSize: 12 }} />
|
||||
{curVersion?.release_message}
|
||||
</Stack>
|
||||
<Stack direction={'row'} alignItems={'center'} gap={0.5}>
|
||||
<Icon type='icon-ziti' />
|
||||
<IconZiti sx={{ fontSize: 12 }} />
|
||||
{characterCount} 字
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
@ -338,7 +345,7 @@ const History = () => {
|
|||
lineHeight: 1,
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-fabu' />
|
||||
<IconFabu sx={{ fontSize: 16 }} />
|
||||
{item.publisher_account}
|
||||
</Stack>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -17,17 +17,18 @@ import { useAppDispatch, useAppSelector } from '@/store';
|
|||
import { setIsRefreshDocList } from '@/store/slices/config';
|
||||
import { addOpacityToColor } from '@/utils';
|
||||
import { collapseAllFolders, convertToTree } from '@/utils/drag';
|
||||
import { Icon } from '@ctzhian/ui';
|
||||
import { message } from '@ctzhian/ui';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
ButtonBase,
|
||||
Checkbox,
|
||||
IconButton,
|
||||
Stack,
|
||||
useTheme,
|
||||
ButtonBase,
|
||||
} 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 AddDocBtn from './component/AddDocBtn';
|
||||
import AddDocByType from './component/AddDocByType';
|
||||
|
|
@ -41,7 +42,9 @@ import RagErrorReStart from './component/RagErrorReStart';
|
|||
import Summary from './component/Summary';
|
||||
|
||||
const Content = () => {
|
||||
const { kb_id, isRefreshDocList } = useAppSelector(state => state.config);
|
||||
const { kb_id, isRefreshDocList, kbList } = useAppSelector(
|
||||
state => state.config,
|
||||
);
|
||||
const dispatch = useAppDispatch();
|
||||
const theme = useTheme();
|
||||
const dragTreeRef = useRef<DragTreeHandle>(null);
|
||||
|
|
@ -49,6 +52,7 @@ const Content = () => {
|
|||
const [searchParams] = useURLSearchParams();
|
||||
const search = searchParams.get('search') || '';
|
||||
const [supportSelect, setBatchOpen] = useState(false);
|
||||
const [wikiUrl, setWikiUrl] = useState<string>('');
|
||||
|
||||
const [ragReStartCount, setRagStartCount] = useState(0);
|
||||
const [ragIds, setRagIds] = useState<string[]>([]);
|
||||
|
|
@ -139,6 +143,15 @@ const Content = () => {
|
|||
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 { item, createItem, renameItem, isEditing: isEditing } = opra;
|
||||
return [
|
||||
|
|
@ -292,6 +305,11 @@ const Content = () => {
|
|||
key: 'properties',
|
||||
onClick: () => handleProperties(item),
|
||||
},
|
||||
{
|
||||
label: '前台查看',
|
||||
key: 'front_doc',
|
||||
onClick: () => handleFrontDoc(item.id),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(!isEditing
|
||||
|
|
@ -367,6 +385,10 @@ const Content = () => {
|
|||
setData([...newData]);
|
||||
}, []);
|
||||
|
||||
const currentKb = useMemo(() => {
|
||||
return kbList?.find(item => item.id === kb_id);
|
||||
}, [kbList, kb_id]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleVisibilityChange = () => {
|
||||
if (document.visibilityState === 'visible' && kb_id) {
|
||||
|
|
@ -379,6 +401,25 @@ const Content = () => {
|
|||
};
|
||||
}, [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(() => {
|
||||
if (kb_id) getData();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
|
@ -529,7 +570,7 @@ const Content = () => {
|
|||
context={
|
||||
<Box>
|
||||
<IconButton size='small'>
|
||||
<Icon type='icon-gengduo' />
|
||||
<IconGengduo sx={{ fontSize: '16px' }} />
|
||||
</IconButton>
|
||||
</Box>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ import {
|
|||
alpha,
|
||||
ButtonBase,
|
||||
} 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 dayjs from 'dayjs';
|
||||
import { useEffect, useState, useMemo } from 'react';
|
||||
|
|
@ -129,7 +130,7 @@ const ActionMenu = ({
|
|||
return (
|
||||
<>
|
||||
<IconButton size='small' onClick={handleClick}>
|
||||
<Icon type='icon-gengduo' />
|
||||
<IconGengduo sx={{ fontSize: 16 }} />
|
||||
</IconButton>
|
||||
<Menu anchorEl={anchorEl} open={open} onClose={handleClose}>
|
||||
{record.status! !== 1 && (
|
||||
|
|
|
|||
|
|
@ -7,8 +7,13 @@ import { tableSx } from '@/constant/styles';
|
|||
import { useURLSearchParams } from '@/hooks';
|
||||
import { useAppSelector } from '@/store';
|
||||
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 {
|
||||
IconDianzanXuanzhong1,
|
||||
IconADiancaiWeixuanzhong2,
|
||||
IconDianzanWeixuanzhong,
|
||||
} from '@panda-wiki/icons';
|
||||
import dayjs from 'dayjs';
|
||||
import { useEffect, useState } from 'react';
|
||||
import Detail from './Detail';
|
||||
|
|
@ -33,15 +38,12 @@ const Evaluate = () => {
|
|||
dataIndex: 'question',
|
||||
title: '问题',
|
||||
render: (text: string, record) => {
|
||||
const AppIcon =
|
||||
AppType[record.app_type as keyof typeof AppType]?.icon || '';
|
||||
return (
|
||||
<>
|
||||
<Stack direction={'row'} alignItems={'center'} gap={1}>
|
||||
<Icon
|
||||
sx={{ fontSize: 12 }}
|
||||
type={
|
||||
AppType[record.app_type as keyof typeof AppType]?.icon || ''
|
||||
}
|
||||
/>
|
||||
<AppIcon sx={{ fontSize: 12 }}></AppIcon>
|
||||
<Ellipsis
|
||||
className='primary-color'
|
||||
sx={{ cursor: 'pointer', flex: 1, width: 0 }}
|
||||
|
|
@ -94,19 +96,24 @@ const Evaluate = () => {
|
|||
sx={{ cursor: 'pointer', fontSize: 14 }}
|
||||
>
|
||||
{value!.score === 1 ? (
|
||||
<Icon
|
||||
type='icon-dianzan-xuanzhong1'
|
||||
sx={{ cursor: 'pointer', color: 'success.main' }}
|
||||
<IconDianzanXuanzhong1
|
||||
sx={{
|
||||
fontSize: 14,
|
||||
cursor: 'pointer',
|
||||
color: 'success.main',
|
||||
}}
|
||||
/>
|
||||
) : value!.score === -1 ? (
|
||||
<Icon
|
||||
type='icon-a-diancai-weixuanzhong2'
|
||||
sx={{ cursor: 'pointer', color: 'error.main' }}
|
||||
<IconADiancaiWeixuanzhong2
|
||||
sx={{
|
||||
fontSize: 14,
|
||||
cursor: 'pointer',
|
||||
color: 'error.main',
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
type='icon-dianzan-weixuanzhong'
|
||||
sx={{ color: 'text.disabled' }}
|
||||
<IconDianzanWeixuanzhong
|
||||
sx={{ fontSize: 14, color: 'text.disabled' }}
|
||||
/>
|
||||
)}
|
||||
</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 { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
IconZhanghao,
|
||||
IconIcon_tool_close,
|
||||
IconMima,
|
||||
IconKejian,
|
||||
IconBukejian,
|
||||
} from '@panda-wiki/icons';
|
||||
|
||||
const Login = () => {
|
||||
const navigate = useNavigate();
|
||||
|
|
@ -90,10 +97,7 @@ const Login = () => {
|
|||
slotProps={{
|
||||
input: {
|
||||
startAdornment: (
|
||||
<Icon
|
||||
type='icon-zhanghao'
|
||||
sx={{ fontSize: 16, mr: 2, flexShrink: 0 }}
|
||||
/>
|
||||
<IconZhanghao sx={{ fontSize: 16, mr: 2, flexShrink: 0 }} />
|
||||
),
|
||||
endAdornment: account ? (
|
||||
<IconButton
|
||||
|
|
@ -101,8 +105,7 @@ const Login = () => {
|
|||
size='small'
|
||||
tabIndex={-1}
|
||||
>
|
||||
<Icon
|
||||
type='icon-icon_tool_close'
|
||||
<IconIcon_tool_close
|
||||
sx={{ fontSize: 14, color: 'text.tertiary' }}
|
||||
/>
|
||||
</IconButton>
|
||||
|
|
@ -128,34 +131,31 @@ const Login = () => {
|
|||
slotProps={{
|
||||
input: {
|
||||
startAdornment: (
|
||||
<Icon
|
||||
type='icon-mima'
|
||||
sx={{ fontSize: 16, mr: 2, flexShrink: 0 }}
|
||||
/>
|
||||
<IconMima sx={{ fontSize: 16, mr: 2, flexShrink: 0 }} />
|
||||
),
|
||||
endAdornment: password ? (
|
||||
<Stack
|
||||
direction={'row'}
|
||||
alignItems={'center'}
|
||||
sx={{ mr: '14px' }}
|
||||
>
|
||||
<Stack direction={'row'} alignItems={'center'}>
|
||||
<IconButton
|
||||
onClick={() => setSee(!see)}
|
||||
size='small'
|
||||
tabIndex={-1}
|
||||
>
|
||||
<Icon
|
||||
type={see ? 'icon-kejian' : 'icon-bukejian'}
|
||||
{see ? (
|
||||
<IconKejian
|
||||
sx={{ fontSize: 18, color: 'text.tertiary' }}
|
||||
/>
|
||||
) : (
|
||||
<IconBukejian
|
||||
sx={{ fontSize: 18, color: 'text.tertiary' }}
|
||||
/>
|
||||
)}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={() => setPassword('')}
|
||||
size='small'
|
||||
tabIndex={-1}
|
||||
>
|
||||
<Icon
|
||||
type='icon-icon_tool_close'
|
||||
<IconIcon_tool_close
|
||||
sx={{ fontSize: 14, color: 'text.tertiary' }}
|
||||
/>
|
||||
</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 = () => {
|
||||
|
|
|
|||
|
|
@ -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 { setRefreshAdminRequest } from '@/store/slices/config';
|
||||
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 {
|
||||
Box,
|
||||
|
|
@ -210,8 +212,7 @@ const ApiToken = () => {
|
|||
}}
|
||||
>
|
||||
{maskString(it.token!)}
|
||||
<Icon
|
||||
type='icon-fuzhi'
|
||||
<IconFuzhi
|
||||
sx={{
|
||||
cursor: 'pointer',
|
||||
fontSize: 16,
|
||||
|
|
@ -275,9 +276,9 @@ const ApiToken = () => {
|
|||
</Stack>
|
||||
|
||||
<Tooltip title={user.role !== 'admin' && ''} placement='top' arrow>
|
||||
<Icon
|
||||
type='icon-icon_tool_close'
|
||||
<IconIcon_tool_close
|
||||
sx={{
|
||||
fontSize: 16,
|
||||
cursor:
|
||||
!isBusiness ||
|
||||
kbDetail?.perm !==
|
||||
|
|
@ -457,7 +458,7 @@ const CardKB = () => {
|
|||
extra={
|
||||
<Button
|
||||
size='small'
|
||||
startIcon={<Icon type='icon-tianjiachengyuan' />}
|
||||
startIcon={<IconTianjiachengyuan />}
|
||||
onClick={() => setAddOpen(true)}
|
||||
sx={{ color: 'primary.main' }}
|
||||
>
|
||||
|
|
@ -557,9 +558,9 @@ const CardKB = () => {
|
|||
placement='top'
|
||||
arrow
|
||||
>
|
||||
<Icon
|
||||
type='icon-icon_tool_close'
|
||||
<IconIcon_tool_close
|
||||
sx={{
|
||||
fontSize: 16,
|
||||
cursor: it.role === 'admin' ? 'not-allowed' : 'pointer',
|
||||
color: it.role === 'admin' ? 'text.disabled' : 'error.main',
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ import {
|
|||
DomainKnowledgeBaseDetail,
|
||||
} from '@/request/types';
|
||||
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 {
|
||||
Box,
|
||||
|
|
@ -235,7 +236,7 @@ const CardRobotWebComponent = ({ kb }: CardRobotWebComponentProps) => {
|
|||
bgcolor: 'warning.light',
|
||||
}}
|
||||
>
|
||||
<Icon type='icon-jinggao' />
|
||||
<IconJinggao sx={{ fontSize: 16 }} />
|
||||
未配置域名,可在
|
||||
<Box component={'span'} sx={{ fontWeight: 500 }}>
|
||||
门户网站 / 服务监听方式
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ import {
|
|||
DomainKnowledgeBaseDetail,
|
||||
} from '@/request/types';
|
||||
import { useAppSelector } from '@/store';
|
||||
import { Icon, message } from '@ctzhian/ui';
|
||||
import { message } from '@ctzhian/ui';
|
||||
import { IconJinggao } from '@panda-wiki/icons';
|
||||
import {
|
||||
Box,
|
||||
FormControlLabel,
|
||||
|
|
@ -261,7 +262,7 @@ const CardRobotWecomService = ({
|
|||
gap={1}
|
||||
sx={{ fontSize: 14, fontWeight: 600, color: 'warning.main' }}
|
||||
>
|
||||
<Icon type='icon-jinggao' sx={{ fontSize: 18 }} />
|
||||
<IconJinggao sx={{ fontSize: 18 }} />
|
||||
人工客服转接配置:当用户触发以下场景时,会自动转接人工客服
|
||||
</Stack>
|
||||
<VersionMask permission={PROFESSION_VERSION_PERMISSION}>
|
||||
|
|
|
|||