mirror of https://github.com/chaitin/PandaWiki.git
Compare commits
4 Commits
fe60e2924d
...
e5bad16b3c
| Author | SHA1 | Date |
|---|---|---|
|
|
e5bad16b3c | |
|
|
1a621205ef | |
|
|
0081f05cd9 | |
|
|
1d0e4857a9 |
|
|
@ -1,5 +1,8 @@
|
|||
import { AppType, IconMap, ModelProvider } from '@/constant/enums';
|
||||
import { DomainNodePermissions } from '@/request/types';
|
||||
import {
|
||||
ConstsNodeRagInfoStatus,
|
||||
DomainNodePermissions,
|
||||
} from '@/request/types';
|
||||
|
||||
export type Paging = {
|
||||
page?: number;
|
||||
|
|
@ -193,6 +196,8 @@ export interface ITreeItem {
|
|||
parentId?: string;
|
||||
content_type?: string;
|
||||
summary?: string;
|
||||
rag_status?: ConstsNodeRagInfoStatus;
|
||||
rag_message?: string;
|
||||
children?: ITreeItem[];
|
||||
type: 1 | 2;
|
||||
isEditting?: boolean;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import { postApiV1NodeSummary } from '@/request/Node';
|
||||
import { DomainRecommendNodeListResp } from '@/request/types';
|
||||
import { useAppSelector } from '@/store';
|
||||
import { Ellipsis, Icon } from '@ctzhian/ui';
|
||||
import { Box, IconButton, Stack } from '@mui/material';
|
||||
import { Ellipsis, Icon, message } from '@ctzhian/ui';
|
||||
import { CSSProperties, forwardRef, HTMLAttributes, useState } from 'react';
|
||||
import { CSSProperties, forwardRef, HTMLAttributes } from 'react';
|
||||
|
||||
export type ItemProps = HTMLAttributes<HTMLDivElement> & {
|
||||
item: DomainRecommendNodeListResp;
|
||||
|
|
@ -38,19 +37,6 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
minWidth: '0px',
|
||||
...style,
|
||||
};
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleCreateSummary = () => {
|
||||
setLoading(true);
|
||||
postApiV1NodeSummary({ ids: [item.id!], kb_id })
|
||||
.then(() => {
|
||||
message.success('生成摘要成功');
|
||||
refresh?.();
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Box ref={ref} style={inlineStyles} {...props}>
|
||||
|
|
@ -102,11 +88,6 @@ const Item = forwardRef<HTMLDivElement, ItemProps>(
|
|||
暂无摘要,可前往文档页生成并发布
|
||||
</Box>
|
||||
) : null}
|
||||
{/* : item.type === 2 ? <Button size='small' loading={loading} sx={{
|
||||
height: '21px',
|
||||
px: 0,
|
||||
ml: '18px',
|
||||
}} onClick={handleCreateSummary}>生成摘要</Button> : null} */}
|
||||
{item.recommend_nodes && item.recommend_nodes.length > 0 && (
|
||||
<Stack sx={{ fontSize: 14, color: 'text.tertiary', pl: '20px' }}>
|
||||
{item.recommend_nodes
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { FC } from 'react';
|
|||
import Item, { ItemProps } from './Item';
|
||||
|
||||
type SortableItemProps = ItemProps & {
|
||||
refresh: () => void;
|
||||
refresh?: () => void;
|
||||
};
|
||||
|
||||
const SortableItem: FC<SortableItemProps> = ({ item, refresh, ...rest }) => {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { DomainRecommendNodeListResp } from '@/request/types';
|
||||
import {
|
||||
closestCenter,
|
||||
DndContext,
|
||||
|
|
@ -9,7 +10,6 @@ import {
|
|||
useSensor,
|
||||
useSensors,
|
||||
} from '@dnd-kit/core';
|
||||
import { DomainRecommendNodeListResp } from '@/request/types';
|
||||
import {
|
||||
arrayMove,
|
||||
rectSortingStrategy,
|
||||
|
|
@ -23,7 +23,7 @@ import SortableItem from './SortableItem';
|
|||
interface DragRecommendProps {
|
||||
data: DomainRecommendNodeListResp[];
|
||||
columns?: number;
|
||||
refresh: () => void;
|
||||
refresh?: () => void;
|
||||
onChange: (data: DomainRecommendNodeListResp[]) => void;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ import {
|
|||
TreeItemComponentProps,
|
||||
TreeItemWrapper,
|
||||
} from '@/components/TreeDragSortable';
|
||||
import RAG_SOURCES from '@/constant/rag';
|
||||
import { treeSx } from '@/constant/styles';
|
||||
import { postApiV1Node, putApiV1NodeDetail } from '@/request/Node';
|
||||
import { ConstsNodeAccessPerm } from '@/request/types';
|
||||
import { ConstsNodeAccessPerm, ConstsNodeRagInfoStatus } from '@/request/types';
|
||||
import { useAppSelector } from '@/store';
|
||||
import { AppContext, updateTree } from '@/utils/drag';
|
||||
import { handleMultiSelect, updateAllParentStatus } from '@/utils/tree';
|
||||
|
|
@ -19,6 +20,7 @@ import {
|
|||
Stack,
|
||||
TextField,
|
||||
Theme,
|
||||
Tooltip,
|
||||
alpha,
|
||||
styled,
|
||||
} from '@mui/material';
|
||||
|
|
@ -520,6 +522,20 @@ const TreeItem = React.forwardRef<
|
|||
gap={1}
|
||||
sx={{ flexShrink: 0, fontSize: 12 }}
|
||||
>
|
||||
{item.type === 2 &&
|
||||
item.rag_status &&
|
||||
![
|
||||
ConstsNodeRagInfoStatus.NodeRagStatusBasicSucceeded,
|
||||
ConstsNodeRagInfoStatus.NodeRagStatusEnhanceSucceeded,
|
||||
].includes(item.rag_status) && (
|
||||
<Tooltip title={item.rag_message}>
|
||||
<StyledTag
|
||||
color={RAG_SOURCES[item.rag_status].color as any}
|
||||
>
|
||||
{RAG_SOURCES[item.rag_status].name}
|
||||
</StyledTag>
|
||||
</Tooltip>
|
||||
)}
|
||||
{item.status === 1 && (
|
||||
<StyledTag color='error'>更新未发布</StyledTag>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
import { ConstsNodeRagInfoStatus } from '@/request';
|
||||
|
||||
const RAG_SOURCES = {
|
||||
[ConstsNodeRagInfoStatus.NodeRagStatusBasicPending]: {
|
||||
name: '待学习',
|
||||
color: 'warning',
|
||||
},
|
||||
[ConstsNodeRagInfoStatus.NodeRagStatusBasicRunning]: {
|
||||
name: '正在学习',
|
||||
color: 'warning',
|
||||
},
|
||||
[ConstsNodeRagInfoStatus.NodeRagStatusBasicFailed]: {
|
||||
name: '学习失败',
|
||||
color: 'error',
|
||||
},
|
||||
[ConstsNodeRagInfoStatus.NodeRagStatusBasicSucceeded]: {
|
||||
name: '学习成功',
|
||||
color: 'success',
|
||||
},
|
||||
[ConstsNodeRagInfoStatus.NodeRagStatusEnhancePending]: {
|
||||
name: '等待增强学习',
|
||||
color: 'warning',
|
||||
},
|
||||
[ConstsNodeRagInfoStatus.NodeRagStatusEnhanceRunning]: {
|
||||
name: '正在增强学习',
|
||||
color: 'warning',
|
||||
},
|
||||
[ConstsNodeRagInfoStatus.NodeRagStatusEnhanceFailed]: {
|
||||
name: '增强学习失败',
|
||||
color: 'error',
|
||||
},
|
||||
[ConstsNodeRagInfoStatus.NodeRagStatusEnhanceSucceeded]: {
|
||||
name: '增强学习成功',
|
||||
color: 'success',
|
||||
},
|
||||
};
|
||||
|
||||
export default RAG_SOURCES;
|
||||
|
|
@ -196,24 +196,10 @@ const History = () => {
|
|||
curNode.creator_account || curNode.publisher_account ? (
|
||||
<Stack>
|
||||
{curNode.creator_account && (
|
||||
<Stack
|
||||
direction={'row'}
|
||||
alignItems={'center'}
|
||||
gap={0.5}
|
||||
>
|
||||
<Icon type='icon-chuangjian' />
|
||||
{curNode.creator_account} 创建
|
||||
</Stack>
|
||||
<Box>创建:{curNode.creator_account}</Box>
|
||||
)}
|
||||
{curNode.publisher_account && (
|
||||
<Stack
|
||||
direction={'row'}
|
||||
alignItems={'center'}
|
||||
gap={0.5}
|
||||
>
|
||||
<Icon type='icon-fabu' />
|
||||
{curNode.publisher_account} 发布
|
||||
</Stack>
|
||||
<Box>上次发布:{curNode.publisher_account}</Box>
|
||||
)}
|
||||
</Stack>
|
||||
) : null
|
||||
|
|
@ -225,7 +211,7 @@ const History = () => {
|
|||
gap={0.5}
|
||||
sx={{ cursor: 'pointer' }}
|
||||
>
|
||||
<Icon type='icon-tianjiawendang' />
|
||||
<Icon type='icon-tianjiawendang' sx={{ fontSize: 9 }} />
|
||||
{curNode.editor_account} 编辑
|
||||
</Stack>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { ITreeItem, NodeListFilterData } from '@/api';
|
||||
import { getApiV1NodeList } from '@/request/Node';
|
||||
import Nodata from '@/assets/images/nodata.png';
|
||||
import DragTree from '@/components/Drag/DragTree';
|
||||
import { getApiV1NodeList } from '@/request/Node';
|
||||
import { useAppSelector } from '@/store';
|
||||
import { convertToTree } from '@/utils/drag';
|
||||
import { filterEmptyFolders } from '@/utils/tree';
|
||||
import { Box, Skeleton, Stack } from '@mui/material';
|
||||
import { Modal } from '@ctzhian/ui';
|
||||
import { Box, Skeleton, Stack } from '@mui/material';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
interface AddRecommendContentProps {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { DomainKnowledgeBaseDetail } from '@/request/types';
|
||||
import { Box } from '@mui/material';
|
||||
import CardRobotWebComponent from './CardRobot/WebComponent';
|
||||
import CardRobotApi from './CardRobotApi';
|
||||
import CardRobotDing from './CardRobotDing';
|
||||
import CardRobotDiscord from './CardRobotDiscord';
|
||||
import CardRobotFeishu from './CardRobotFeishu';
|
||||
import CardRobotLark from './CardRobotLark';
|
||||
import CardRobotWebComponent from './CardRobotWebComponent';
|
||||
import CardRobotWechatOfficeAccount from './CardRobotWechatOfficeAccount';
|
||||
import CardRobotWecom from './CardRobotWecom';
|
||||
import CardRobotWecomAIBot from './CardRobotWecomAIBot';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
import DragRecommend from '@/components/Drag/DragRecommend';
|
||||
import {
|
||||
DomainRecommendNodeListResp,
|
||||
getApiV1NodeRecommendNodes,
|
||||
} from '@/request';
|
||||
import { useAppSelector } from '@/store';
|
||||
import { Box, Button, Stack } from '@mui/material';
|
||||
import { useEffect, useState } from 'react';
|
||||
import AddRecommendContent from '../../AddRecommendContent';
|
||||
|
||||
const RecommendDocDragList = ({
|
||||
ids,
|
||||
onChange,
|
||||
}: {
|
||||
ids: string[];
|
||||
onChange: (ids: string[]) => void;
|
||||
}) => {
|
||||
const { kb_id } = useAppSelector(state => state.config);
|
||||
const [data, setData] = useState<DomainRecommendNodeListResp[]>([]);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const getDetail = (node_ids: string[]) => {
|
||||
if (kb_id && node_ids.length > 0) {
|
||||
getApiV1NodeRecommendNodes({
|
||||
kb_id,
|
||||
node_ids,
|
||||
}).then(res => {
|
||||
setData(res || []);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getDetail(ids);
|
||||
}, [ids, kb_id]);
|
||||
|
||||
return (
|
||||
<Stack gap={1} flex={1}>
|
||||
<Box>
|
||||
<DragRecommend
|
||||
data={data}
|
||||
onChange={value => {
|
||||
setData(value);
|
||||
onChange(value.map(item => item.id!));
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Button
|
||||
color='primary'
|
||||
size='small'
|
||||
onClick={() => setOpen(true)}
|
||||
sx={{
|
||||
alignSelf: 'flex-start',
|
||||
}}
|
||||
>
|
||||
添加文档
|
||||
</Button>
|
||||
<AddRecommendContent
|
||||
open={open}
|
||||
selected={ids}
|
||||
onChange={onChange}
|
||||
onClose={() => setOpen(false)}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default RecommendDocDragList;
|
||||
|
|
@ -1,6 +1,14 @@
|
|||
import { DomainKnowledgeBaseDetail } from '@/request/types';
|
||||
import { FreeSoloAutocomplete } from '@/components/FreeSoloAutocomplete';
|
||||
import ShowText from '@/components/ShowText';
|
||||
import UploadFile from '@/components/UploadFile';
|
||||
import { useCommitPendingInput } from '@/hooks';
|
||||
import { getApiV1AppDetail, putApiV1App } from '@/request/App';
|
||||
import {
|
||||
DomainAppDetailResp,
|
||||
DomainKnowledgeBaseDetail,
|
||||
} from '@/request/types';
|
||||
import { useAppSelector } from '@/store';
|
||||
import { Icon, message } from '@ctzhian/ui';
|
||||
import {
|
||||
Box,
|
||||
FormControlLabel,
|
||||
|
|
@ -10,13 +18,10 @@ import {
|
|||
Stack,
|
||||
TextField,
|
||||
} from '@mui/material';
|
||||
import { Icon, message } from '@ctzhian/ui';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { FormItem, SettingCardItem } from './Common';
|
||||
import { DomainAppDetailResp } from '@/request/types';
|
||||
import { getApiV1AppDetail, putApiV1App } from '@/request/App';
|
||||
import { useAppSelector } from '@/store';
|
||||
import { FormItem, SettingCardItem } from '../../Common';
|
||||
import RecommendDocDragList from './RecommendDocDragList';
|
||||
|
||||
interface CardRobotWebComponentProps {
|
||||
kb: DomainKnowledgeBaseDetail;
|
||||
|
|
@ -31,6 +36,8 @@ const CardRobotWebComponent = ({ kb }: CardRobotWebComponentProps) => {
|
|||
control,
|
||||
handleSubmit,
|
||||
reset,
|
||||
watch,
|
||||
setValue,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
defaultValues: {
|
||||
|
|
@ -38,11 +45,24 @@ const CardRobotWebComponent = ({ kb }: CardRobotWebComponentProps) => {
|
|||
theme_mode: 'light',
|
||||
btn_text: '',
|
||||
btn_logo: '',
|
||||
recommend_questions: [] as string[],
|
||||
recommend_node_ids: [] as string[],
|
||||
},
|
||||
});
|
||||
|
||||
const [url, setUrl] = useState<string>('');
|
||||
|
||||
const recommend_questions = watch('recommend_questions') || [];
|
||||
const recommend_node_ids = watch('recommend_node_ids') || [];
|
||||
|
||||
const recommendQuestionsField = useCommitPendingInput<string>({
|
||||
value: recommend_questions,
|
||||
setValue: value => {
|
||||
setIsEdit(true);
|
||||
setValue('recommend_questions', value);
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (kb.access_settings?.base_url) {
|
||||
setUrl(kb.access_settings.base_url);
|
||||
|
|
@ -69,6 +89,10 @@ const CardRobotWebComponent = ({ kb }: CardRobotWebComponentProps) => {
|
|||
theme_mode: res.settings?.widget_bot_settings?.theme_mode || 'light',
|
||||
btn_text: res.settings?.widget_bot_settings?.btn_text || '在线客服',
|
||||
btn_logo: res.settings?.widget_bot_settings?.btn_logo,
|
||||
recommend_questions:
|
||||
res.settings?.widget_bot_settings?.recommend_questions || [],
|
||||
recommend_node_ids:
|
||||
res.settings?.widget_bot_settings?.recommend_node_ids || [],
|
||||
});
|
||||
setIsEnabled(res.settings?.widget_bot_settings?.is_open ? true : false);
|
||||
});
|
||||
|
|
@ -86,6 +110,8 @@ const CardRobotWebComponent = ({ kb }: CardRobotWebComponentProps) => {
|
|||
theme_mode: data.theme_mode as 'light' | 'dark',
|
||||
btn_text: data.btn_text,
|
||||
btn_logo: data.btn_logo,
|
||||
recommend_questions: data.recommend_questions || [],
|
||||
recommend_node_ids: data.recommend_node_ids || [],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -220,6 +246,21 @@ const CardRobotWebComponent = ({ kb }: CardRobotWebComponentProps) => {
|
|||
)}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label='推荐问题'>
|
||||
<FreeSoloAutocomplete
|
||||
{...recommendQuestionsField}
|
||||
placeholder='回车确认,填写下一个推荐问题'
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label='推荐文档'>
|
||||
<RecommendDocDragList
|
||||
ids={recommend_node_ids}
|
||||
onChange={(value: string[]) => {
|
||||
setIsEdit(true);
|
||||
setValue('recommend_node_ids', value);
|
||||
}}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label='嵌入代码'>
|
||||
{url ? (
|
||||
<ShowText
|
||||
|
|
@ -111,6 +111,8 @@ export function convertToTree(data: DomainNodeListItemResp[]) {
|
|||
emoji: item.emoji,
|
||||
content_type: item.content_type,
|
||||
type: item.type!,
|
||||
rag_status: item.rag_info?.status,
|
||||
rag_message: item.rag_info?.message,
|
||||
parentId: item.parent_id,
|
||||
children: [],
|
||||
canHaveChildren: item.type === 1,
|
||||
|
|
|
|||
|
|
@ -219,9 +219,9 @@ const DocContent = ({
|
|||
<>
|
||||
<Box>·</Box>
|
||||
<Box>
|
||||
{info?.creator_account && info?.creator_account === 'admin'
|
||||
{info?.editor_account && info?.editor_account === 'admin'
|
||||
? '管理员'
|
||||
: info?.creator_account}{' '}
|
||||
: info?.editor_account}{' '}
|
||||
{dayjs(info.updated_at).fromNow()}更新
|
||||
</Box>
|
||||
</>
|
||||
|
|
|
|||
Loading…
Reference in New Issue