mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
update knowledge_kb (#34)
* update typescript * add chunk api * remove useless code
This commit is contained in:
@ -0,0 +1,99 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { connect, Dispatch } from 'umi';
|
||||
import i18n from 'i18next';
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { Input, Modal, Form } from 'antd'
|
||||
import styles from './index.less';
|
||||
import type { chunkModelState } from './model'
|
||||
import EditTag from './editTag'
|
||||
|
||||
type FieldType = {
|
||||
content_ltks?: string;
|
||||
};
|
||||
interface kFProps {
|
||||
dispatch: Dispatch;
|
||||
chunkModel: chunkModelState;
|
||||
getChunkList: () => void;
|
||||
doc_id: string
|
||||
}
|
||||
const Index: React.FC<kFProps> = ({ chunkModel, dispatch, getChunkList, doc_id }) => {
|
||||
const { isShowCreateModal, chunk_id, chunkInfo } = chunkModel
|
||||
const [important_kwd, setImportantKwd] = useState(['Unremovable', 'Tag 2', 'Tag 3']);
|
||||
const { t } = useTranslation()
|
||||
const handleCancel = () => {
|
||||
dispatch({
|
||||
type: 'chunkModel/updateState',
|
||||
payload: {
|
||||
isShowCreateModal: false
|
||||
}
|
||||
});
|
||||
};
|
||||
useEffect(() => {
|
||||
if (chunk_id && isShowCreateModal) {
|
||||
dispatch({
|
||||
type: 'chunkModel/get_chunk',
|
||||
payload: {
|
||||
chunk_id
|
||||
},
|
||||
callback(info: any) {
|
||||
console.log(info)
|
||||
const { content_ltks, important_kwd = [] } = info
|
||||
form.setFieldsValue({ content_ltks })
|
||||
setImportantKwd(important_kwd)
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [chunk_id, isShowCreateModal])
|
||||
const [form] = Form.useForm()
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
dispatch({
|
||||
type: 'chunkModel/create_hunk',
|
||||
payload: {
|
||||
content_ltks: values.content_ltks,
|
||||
doc_id,
|
||||
chunk_id,
|
||||
important_kwd
|
||||
},
|
||||
callback: () => {
|
||||
dispatch({
|
||||
type: 'chunkModel/updateState',
|
||||
payload: {
|
||||
isShowCreateModal: false
|
||||
}
|
||||
});
|
||||
getChunkList && getChunkList()
|
||||
}
|
||||
});
|
||||
|
||||
} catch (errorInfo) {
|
||||
console.log('Failed:', errorInfo);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal title="Basic Modal" open={isShowCreateModal} onOk={handleOk} onCancel={handleCancel}>
|
||||
<Form
|
||||
form={form}
|
||||
name="validateOnly"
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 19 }}
|
||||
style={{ maxWidth: 600 }}
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item<FieldType>
|
||||
label="chunk 内容"
|
||||
name="content_ltks"
|
||||
rules={[{ required: true, message: 'Please input name!' }]}
|
||||
>
|
||||
<Input.TextArea />
|
||||
</Form.Item>
|
||||
<EditTag tags={important_kwd} setTags={setImportantKwd} />
|
||||
</Form>
|
||||
</Modal >
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
export default connect(({ chunkModel, loading }) => ({ chunkModel, loading }))(Index);
|
||||
@ -0,0 +1,142 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import type { InputRef } from 'antd';
|
||||
import { Input, Space, Tag, theme, Tooltip } from 'antd';
|
||||
interface editTagsProps {
|
||||
tags: any[],
|
||||
setTags: (tags: any[]) => void
|
||||
}
|
||||
const App: React.FC<editTagsProps> = ({ tags, setTags }) => {
|
||||
const { token } = theme.useToken();
|
||||
|
||||
const [inputVisible, setInputVisible] = useState(false);
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
const [editInputIndex, setEditInputIndex] = useState(-1);
|
||||
const [editInputValue, setEditInputValue] = useState('');
|
||||
const inputRef = useRef<InputRef>(null);
|
||||
const editInputRef = useRef<InputRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (inputVisible) {
|
||||
inputRef.current?.focus();
|
||||
}
|
||||
}, [inputVisible]);
|
||||
|
||||
useEffect(() => {
|
||||
editInputRef.current?.focus();
|
||||
}, [editInputValue]);
|
||||
|
||||
const handleClose = (removedTag: string) => {
|
||||
const newTags = tags.filter((tag) => tag !== removedTag);
|
||||
console.log(newTags);
|
||||
setTags(newTags);
|
||||
};
|
||||
|
||||
const showInput = () => {
|
||||
setInputVisible(true);
|
||||
};
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setInputValue(e.target.value);
|
||||
};
|
||||
|
||||
const handleInputConfirm = () => {
|
||||
if (inputValue && !tags.includes(inputValue)) {
|
||||
setTags([...tags, inputValue]);
|
||||
}
|
||||
setInputVisible(false);
|
||||
setInputValue('');
|
||||
};
|
||||
|
||||
const handleEditInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setEditInputValue(e.target.value);
|
||||
};
|
||||
|
||||
const handleEditInputConfirm = () => {
|
||||
const newTags = [...tags];
|
||||
newTags[editInputIndex] = editInputValue;
|
||||
setTags(newTags);
|
||||
setEditInputIndex(-1);
|
||||
setEditInputValue('');
|
||||
};
|
||||
|
||||
const tagInputStyle: React.CSSProperties = {
|
||||
width: 64,
|
||||
height: 22,
|
||||
marginInlineEnd: 8,
|
||||
verticalAlign: 'top',
|
||||
};
|
||||
|
||||
const tagPlusStyle: React.CSSProperties = {
|
||||
height: 22,
|
||||
background: token.colorBgContainer,
|
||||
borderStyle: 'dashed',
|
||||
};
|
||||
|
||||
return (
|
||||
<Space size={[0, 8]} wrap>
|
||||
{tags.map((tag, index) => {
|
||||
if (editInputIndex === index) {
|
||||
return (
|
||||
<Input
|
||||
ref={editInputRef}
|
||||
key={tag}
|
||||
size="small"
|
||||
style={tagInputStyle}
|
||||
value={editInputValue}
|
||||
onChange={handleEditInputChange}
|
||||
onBlur={handleEditInputConfirm}
|
||||
onPressEnter={handleEditInputConfirm}
|
||||
/>
|
||||
);
|
||||
}
|
||||
const isLongTag = tag.length > 20;
|
||||
const tagElem = (
|
||||
<Tag
|
||||
key={tag}
|
||||
closable={index !== 0}
|
||||
style={{ userSelect: 'none' }}
|
||||
onClose={() => handleClose(tag)}
|
||||
>
|
||||
<span
|
||||
onDoubleClick={(e) => {
|
||||
if (index !== 0) {
|
||||
setEditInputIndex(index);
|
||||
setEditInputValue(tag);
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isLongTag ? `${tag.slice(0, 20)}...` : tag}
|
||||
</span>
|
||||
</Tag>
|
||||
);
|
||||
return isLongTag ? (
|
||||
<Tooltip title={tag} key={tag}>
|
||||
{tagElem}
|
||||
</Tooltip>
|
||||
) : (
|
||||
tagElem
|
||||
);
|
||||
})}
|
||||
{inputVisible ? (
|
||||
<Input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
size="small"
|
||||
style={tagInputStyle}
|
||||
value={inputValue}
|
||||
onChange={handleInputChange}
|
||||
onBlur={handleInputConfirm}
|
||||
onPressEnter={handleInputConfirm}
|
||||
/>
|
||||
) : (
|
||||
<Tag style={tagPlusStyle} onClick={showInput}>
|
||||
添加关键词
|
||||
</Tag>
|
||||
)}
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
@ -0,0 +1,70 @@
|
||||
.chunkPage {
|
||||
padding: 24px;
|
||||
|
||||
display: flex;
|
||||
height: calc(100vh - 112px);
|
||||
flex-direction: column;
|
||||
|
||||
.filter {
|
||||
margin: 10px 0;
|
||||
display: flex;
|
||||
height: 32px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.pageContent {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding-right: 12px;
|
||||
overflow-y: auto;
|
||||
|
||||
.spin {
|
||||
min-height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.pageFooter {
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.context {
|
||||
flex: 1;
|
||||
// width: 207px;
|
||||
height: 88px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
height: 20px;
|
||||
|
||||
.text {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
:global {
|
||||
.ant-card-body {
|
||||
padding: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
}
|
||||
224
web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx
Normal file
224
web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx
Normal file
@ -0,0 +1,224 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { useNavigate, connect, Dispatch } from 'umi'
|
||||
import { Card, Row, Col, Input, Select, Switch, Pagination, Spin, Button, Popconfirm } from 'antd';
|
||||
import { MinusSquareOutlined, DeleteOutlined, } from '@ant-design/icons';
|
||||
import type { PaginationProps } from 'antd';
|
||||
import { api_host } from '@/utils/api'
|
||||
import CreateModal from './createModal'
|
||||
|
||||
|
||||
import styles from './index.less'
|
||||
import { debounce } from 'lodash';
|
||||
import type { chunkModelState } from './model'
|
||||
interface chunkProps {
|
||||
dispatch: Dispatch;
|
||||
chunkModel: chunkModelState;
|
||||
doc_id: string
|
||||
}
|
||||
const Index: React.FC<chunkProps> = ({ chunkModel, dispatch, doc_id }) => {
|
||||
const [keywords, SetKeywords] = useState('')
|
||||
const [available_int, setAvailableInt] = useState(-1)
|
||||
const navigate = useNavigate()
|
||||
const [pagination, setPagination] = useState({ page: 1, size: 30 })
|
||||
// const [datas, setDatas] = useState(data)
|
||||
const { data = [], total, loading } = chunkModel
|
||||
console.log(chunkModel)
|
||||
const getChunkList = (value?: string) => {
|
||||
dispatch({
|
||||
type: 'chunkModel/updateState',
|
||||
payload: {
|
||||
loading: true
|
||||
}
|
||||
});
|
||||
interface payloadType {
|
||||
doc_id: string;
|
||||
keywords?: string;
|
||||
available_int?: number
|
||||
}
|
||||
const payload: payloadType = {
|
||||
doc_id,
|
||||
keywords: value || keywords,
|
||||
available_int
|
||||
}
|
||||
if (payload.available_int === -1) {
|
||||
delete payload.available_int
|
||||
}
|
||||
dispatch({
|
||||
type: 'chunkModel/chunk_list',
|
||||
payload: {
|
||||
...payload,
|
||||
...pagination
|
||||
}
|
||||
});
|
||||
}
|
||||
const confirm = (id: string) => {
|
||||
console.log(id)
|
||||
dispatch({
|
||||
type: 'chunkModel/rm_chunk',
|
||||
payload: {
|
||||
chunk_ids: [id]
|
||||
},
|
||||
callback: getChunkList
|
||||
});
|
||||
};
|
||||
const handleEditchunk = (chunk_id?: string) => {
|
||||
dispatch({
|
||||
type: 'chunkModel/updateState',
|
||||
payload: {
|
||||
isShowCreateModal: true,
|
||||
chunk_id
|
||||
},
|
||||
callback: getChunkList
|
||||
});
|
||||
}
|
||||
const onShowSizeChange: PaginationProps['onShowSizeChange'] = (page, size) => {
|
||||
setPagination({ page, size })
|
||||
};
|
||||
const switchChunk = (id: string, available_int: boolean) => {
|
||||
dispatch({
|
||||
type: 'chunkModel/updateState',
|
||||
payload: {
|
||||
loading: true
|
||||
}
|
||||
});
|
||||
dispatch({
|
||||
type: 'chunkModel/switch_chunk',
|
||||
payload: {
|
||||
chunk_ids: [id],
|
||||
available_int: Number(available_int),
|
||||
doc_id
|
||||
},
|
||||
callback: getChunkList
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getChunkList()
|
||||
}, [doc_id, available_int, pagination])
|
||||
const debounceChange = debounce(getChunkList, 300)
|
||||
const debounceCallback = useCallback((value: string) => debounceChange(value), [])
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
const value = e.target.value
|
||||
SetKeywords(value)
|
||||
debounceCallback(value)
|
||||
}
|
||||
const handleSelectChange = (value: number) => {
|
||||
setAvailableInt(value)
|
||||
}
|
||||
console.log('loading', loading)
|
||||
return (<>
|
||||
<div className={styles.chunkPage}>
|
||||
<div className={styles.filter}>
|
||||
<div>
|
||||
<Input placeholder="搜索" style={{ width: 220 }} value={keywords} allowClear onChange={handleInputChange} />
|
||||
<Select
|
||||
showSearch
|
||||
placeholder="是否启用"
|
||||
optionFilterProp="children"
|
||||
value={available_int}
|
||||
onChange={handleSelectChange}
|
||||
style={{ width: 220 }}
|
||||
options={[
|
||||
{
|
||||
value: -1,
|
||||
label: '全部',
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
label: '启用',
|
||||
},
|
||||
{
|
||||
value: 0,
|
||||
label: '未启用',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
</div>
|
||||
<Button onClick={() => { handleEditchunk() }} type='link'>添加分段</Button>
|
||||
</div>
|
||||
<div className={styles.pageContent}>
|
||||
<Spin spinning={loading} className={styles.spin} size='large'>
|
||||
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24 }} >
|
||||
{
|
||||
data.map((item: any) => {
|
||||
return (<Col className="gutter-row" key={item.chunk_id} xs={24} sm={12} md={12} lg={8}>
|
||||
<Card className={styles.card}
|
||||
onClick={() => { handleEditchunk(item.chunk_id) }}
|
||||
>
|
||||
<img style={{ width: '50px' }} src={`${api_host}/document/image/${item.img_id}`} alt="" />
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
<span className={styles.context}>
|
||||
{item.content_ltks}
|
||||
</span>
|
||||
<span className={styles.delete}>
|
||||
<Switch size="small" defaultValue={item.available_int == '1'} onChange={(checked: boolean, e: any) => {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation(); switchChunk(item.chunk_id, checked)
|
||||
}} />
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.footer}>
|
||||
<span className={styles.text}>
|
||||
<MinusSquareOutlined />{item.doc_num}文档
|
||||
</span>
|
||||
<span className={styles.text}>
|
||||
<MinusSquareOutlined />{item.chunk_num}个
|
||||
</span>
|
||||
<span className={styles.text}>
|
||||
<MinusSquareOutlined />{item.token_num}千字符
|
||||
</span>
|
||||
<span style={{ float: 'right' }}>
|
||||
<Popconfirm
|
||||
title="Delete the task"
|
||||
description="Are you sure to delete this task?"
|
||||
onConfirm={(e: any) => {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation()
|
||||
console.log(confirm)
|
||||
confirm(item.chunk_id)
|
||||
|
||||
}}
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
>
|
||||
<DeleteOutlined onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation()
|
||||
}} />
|
||||
</Popconfirm>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</Card>
|
||||
</Col>)
|
||||
})
|
||||
}
|
||||
</Row>
|
||||
</Spin>
|
||||
|
||||
</div>
|
||||
<div className={styles.pageFooter}>
|
||||
<Pagination
|
||||
responsive
|
||||
showLessItems
|
||||
showQuickJumper
|
||||
showSizeChanger
|
||||
onChange={onShowSizeChange}
|
||||
defaultPageSize={30}
|
||||
pageSizeOptions={[30, 60, 90]}
|
||||
defaultCurrent={pagination.page}
|
||||
total={total}
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div >
|
||||
<CreateModal doc_id={doc_id} getChunkList={getChunkList} />
|
||||
</>
|
||||
)
|
||||
};
|
||||
|
||||
export default connect(({ chunkModel, loading }) => ({ chunkModel, loading }))(Index);
|
||||
134
web/src/pages/add-knowledge/components/knowledge-chunk/model.ts
Normal file
134
web/src/pages/add-knowledge/components/knowledge-chunk/model.ts
Normal file
@ -0,0 +1,134 @@
|
||||
import { Effect, Reducer, Subscription } from 'umi'
|
||||
import { message } from 'antd';
|
||||
import kbService from '@/services/kbService';
|
||||
|
||||
export interface chunkModelState {
|
||||
loading: boolean;
|
||||
data: any[];
|
||||
total: number;
|
||||
isShowCreateModal: boolean;
|
||||
chunk_id: string;
|
||||
chunkInfo: any
|
||||
}
|
||||
export interface chunkgModelType {
|
||||
namespace: 'chunkModel';
|
||||
state: chunkModelState;
|
||||
effects: {
|
||||
chunk_list: Effect;
|
||||
get_chunk: Effect;
|
||||
create_hunk: Effect;
|
||||
switch_chunk: Effect;
|
||||
rm_chunk: Effect;
|
||||
};
|
||||
reducers: {
|
||||
updateState: Reducer<chunkModelState>;
|
||||
};
|
||||
subscriptions: { setup: Subscription };
|
||||
}
|
||||
const Model: chunkgModelType = {
|
||||
namespace: 'chunkModel',
|
||||
state: {
|
||||
loading: false,
|
||||
data: [],
|
||||
total: 0,
|
||||
isShowCreateModal: false,
|
||||
chunk_id: '',
|
||||
chunkInfo: {}
|
||||
},
|
||||
subscriptions: {
|
||||
setup({ dispatch, history }) {
|
||||
history.listen(location => {
|
||||
console.log(location)
|
||||
});
|
||||
}
|
||||
},
|
||||
effects: {
|
||||
* chunk_list({ payload = {}, callback }, { call, put }) {
|
||||
const { data, response } = yield call(kbService.chunk_list, payload);
|
||||
|
||||
const { retcode, data: res, retmsg } = data
|
||||
if (retcode === 0) {
|
||||
console.log(res)
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
data: res.chunks,
|
||||
total: res.total,
|
||||
loading: false
|
||||
}
|
||||
});
|
||||
callback && callback()
|
||||
|
||||
}
|
||||
},
|
||||
*switch_chunk({ payload = {}, callback }, { call, put }) {
|
||||
const { data, response } = yield call(kbService.switch_chunk, payload);
|
||||
const { retcode, data: res, retmsg } = data
|
||||
if (retcode === 0) {
|
||||
callback && callback()
|
||||
|
||||
}
|
||||
},
|
||||
*rm_chunk({ payload = {}, callback }, { call, put }) {
|
||||
console.log('shanchu')
|
||||
const { data, response } = yield call(kbService.rm_chunk, payload);
|
||||
const { retcode, data: res, retmsg } = data
|
||||
if (retcode === 0) {
|
||||
callback && callback()
|
||||
|
||||
}
|
||||
},
|
||||
* get_chunk({ payload = {}, callback }, { call, put }) {
|
||||
const { data, response } = yield call(kbService.get_chunk, payload);
|
||||
const { retcode, data: res, retmsg } = data
|
||||
if (retcode === 0) {
|
||||
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
chunkInfo: res
|
||||
}
|
||||
});
|
||||
callback && callback(res)
|
||||
|
||||
}
|
||||
},
|
||||
*create_hunk({ payload = {} }, { call, put }) {
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
loading: true
|
||||
}
|
||||
});
|
||||
let service = kbService.create_chunk
|
||||
if (payload.chunk_id) {
|
||||
service = kbService.set_chunk
|
||||
}
|
||||
const { data, response } = yield call(service, payload);
|
||||
const { retcode, data: res, retmsg } = data
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
loading: false
|
||||
}
|
||||
});
|
||||
if (retcode === 0) {
|
||||
yield put({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
isShowCreateModal: false
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
reducers: {
|
||||
updateState(state, { payload }) {
|
||||
return {
|
||||
...state,
|
||||
...payload
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
export default Model;
|
||||
@ -1,14 +1,21 @@
|
||||
import { connect } from 'umi';
|
||||
import React from 'react'
|
||||
import { connect, Dispatch } from 'umi';
|
||||
import i18n from 'i18next';
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { Input, Modal, Form } from 'antd'
|
||||
import { rsaPsw } from '@/utils'
|
||||
import styles from './index.less';
|
||||
import type { kFModelState } from './model'
|
||||
|
||||
type FieldType = {
|
||||
name?: string;
|
||||
};
|
||||
const Index = ({ kFModel, dispatch, getKfList, kb_id }) => {
|
||||
interface kFProps {
|
||||
dispatch: Dispatch;
|
||||
kFModel: kFModelState;
|
||||
getKfList: () => void;
|
||||
kb_id: string
|
||||
}
|
||||
const Index: React.FC<kFProps> = ({ kFModel, dispatch, getKfList, kb_id }) => {
|
||||
const { isShowCEFwModal } = kFModel
|
||||
const { t } = useTranslation()
|
||||
const handleCancel = () => {
|
||||
|
||||
@ -21,4 +21,8 @@
|
||||
|
||||
.column {
|
||||
min-width: 200px
|
||||
}
|
||||
|
||||
.tochunks {
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -1,14 +1,15 @@
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { connect, useNavigate, useLocation } from 'umi'
|
||||
import { Space, Table, Tag, Input, Button, Switch, Popover, Dropdown, } from 'antd';
|
||||
import { connect, Dispatch, useNavigate } from 'umi'
|
||||
import { Space, Table, Input, Button, Switch, Dropdown, } from 'antd';
|
||||
import type { MenuProps } from 'antd';
|
||||
import { PlusOutlined, DownOutlined } from '@ant-design/icons'
|
||||
import { DownOutlined } from '@ant-design/icons'
|
||||
import { debounce } from 'lodash';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import UploadFile from './upload'
|
||||
import CreateEPModal from './createEFileModal'
|
||||
import SegmentSetModal from './segmentSetModal'
|
||||
import styles from './index.less'
|
||||
import type { kFModelState } from './model'
|
||||
|
||||
interface DataType {
|
||||
name: string;
|
||||
@ -21,32 +22,37 @@ interface DataType {
|
||||
parser_id: string
|
||||
}
|
||||
|
||||
interface kFProps {
|
||||
dispatch: Dispatch;
|
||||
kFModel: kFModelState;
|
||||
kb_id: string
|
||||
}
|
||||
|
||||
|
||||
const Index: React.FC = ({ kFModel, dispatch, id }) => {
|
||||
const Index: React.FC<kFProps> = ({ kFModel, dispatch, kb_id }) => {
|
||||
const { data, loading } = kFModel
|
||||
const [inputValue, setInputValue] = useState('')
|
||||
const [doc_id, setDocId] = useState('0')
|
||||
const [parser_id, setParserId] = useState('0')
|
||||
const changeValue = (value: string) => {
|
||||
{
|
||||
console.log(value)
|
||||
let navigate = useNavigate();
|
||||
const getKfList = (keywords?: string) => {
|
||||
const payload = {
|
||||
kb_id,
|
||||
keywords
|
||||
}
|
||||
if (!keywords) {
|
||||
delete payload.keywords
|
||||
}
|
||||
}
|
||||
const getKfList = () => {
|
||||
dispatch({
|
||||
type: 'kFModel/getKfList',
|
||||
payload: {
|
||||
kb_id: id
|
||||
}
|
||||
payload
|
||||
});
|
||||
}
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
if (kb_id) {
|
||||
getKfList()
|
||||
}
|
||||
}, [id])
|
||||
const debounceChange = debounce(changeValue, 300)
|
||||
}, [kb_id])
|
||||
const debounceChange = debounce(getKfList, 300)
|
||||
const debounceCallback = useCallback((value: string) => debounceChange(value), [])
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
const value = e.target.value
|
||||
@ -101,7 +107,7 @@ const Index: React.FC = ({ kFModel, dispatch, id }) => {
|
||||
key: '1',
|
||||
label: (
|
||||
<div>
|
||||
<UploadFile kb_id={id} getKfList={getKfList} />
|
||||
<UploadFile kb_id={kb_id} getKfList={getKfList} />
|
||||
</div>
|
||||
|
||||
),
|
||||
@ -116,7 +122,7 @@ const Index: React.FC = ({ kFModel, dispatch, id }) => {
|
||||
// disabled: true,
|
||||
},
|
||||
]
|
||||
}, [id]);
|
||||
}, [kb_id]);
|
||||
const chunkItems: MenuProps['items'] = [
|
||||
{
|
||||
key: '1',
|
||||
@ -138,12 +144,16 @@ const Index: React.FC = ({ kFModel, dispatch, id }) => {
|
||||
// disabled: true,
|
||||
},
|
||||
]
|
||||
const toChunk = (id: string) => {
|
||||
console.log(id)
|
||||
navigate(`/knowledge/add/setting?activeKey=file&id=${kb_id}&doc_id=${id}`);
|
||||
}
|
||||
const columns: ColumnsType<DataType> = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
render: (text) => <a><img className={styles.img} src='https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg' alt="" />{text}</a>,
|
||||
render: (text: any, { id }) => <div className={styles.tochunks} onClick={() => toChunk(id)}><img className={styles.img} src='https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg' alt="" />{text}</div>,
|
||||
className: `${styles.column}`
|
||||
},
|
||||
{
|
||||
@ -198,7 +208,7 @@ const Index: React.FC = ({ kFModel, dispatch, id }) => {
|
||||
return <>
|
||||
<div className={styles.filter}>
|
||||
<div className="search">
|
||||
<Input placeholder="搜索" value={inputValue} allowClear onChange={handleInputChange} />
|
||||
<Input placeholder="搜索" value={inputValue} style={{ width: 220 }} allowClear onChange={handleInputChange} />
|
||||
</div>
|
||||
<div className="operate">
|
||||
<Dropdown menu={{ items: actionItems }} trigger={['click']} >
|
||||
@ -210,7 +220,7 @@ const Index: React.FC = ({ kFModel, dispatch, id }) => {
|
||||
</div>
|
||||
</div>
|
||||
<Table rowKey='id' columns={columns} dataSource={data} loading={loading} pagination={false} scroll={{ scrollToFirstRowOnChange: true, x: true }} />
|
||||
<CreateEPModal getKfList={getKfList} kb_id={id} />
|
||||
<CreateEPModal getKfList={getKfList} kb_id={kb_id} />
|
||||
<SegmentSetModal getKfList={getKfList} parser_id={parser_id} doc_id={doc_id} />
|
||||
</>
|
||||
};
|
||||
|
||||
@ -1,15 +1,42 @@
|
||||
import { message } from 'antd';
|
||||
import { addParam } from '@/utils';
|
||||
import { Effect, Reducer, Subscription } from 'umi'
|
||||
import kbService from '@/services/kbService';
|
||||
|
||||
const Model = {
|
||||
export interface kFModelState {
|
||||
isShowCEFwModal: boolean;
|
||||
isShowTntModal: boolean;
|
||||
isShowSegmentSetModal: boolean;
|
||||
loading: boolean;
|
||||
tenantIfo: any;
|
||||
data: any[]
|
||||
}
|
||||
export interface kFModelType {
|
||||
namespace: 'kFModel';
|
||||
state: kFModelState;
|
||||
effects: {
|
||||
createKf: Effect;
|
||||
updateKf: Effect;
|
||||
getKfDetail: Effect;
|
||||
getKfList: Effect;
|
||||
updateDocumentStatus: Effect;
|
||||
document_rm: Effect;
|
||||
document_create: Effect;
|
||||
document_change_parser: Effect;
|
||||
};
|
||||
reducers: {
|
||||
updateState: Reducer<kFModelState>;
|
||||
};
|
||||
subscriptions: { setup: Subscription };
|
||||
}
|
||||
const Model: kFModelType = {
|
||||
namespace: 'kFModel',
|
||||
state: {
|
||||
isShowCEFwModal: false,
|
||||
isShowTntModal: false,
|
||||
isShowSegmentSetModal: false,
|
||||
loading: false,
|
||||
tenantIfo: {}
|
||||
tenantIfo: {},
|
||||
data: []
|
||||
},
|
||||
subscriptions: {
|
||||
setup({ dispatch, history }) {
|
||||
|
||||
@ -1,15 +1,22 @@
|
||||
import { connect } from 'umi';
|
||||
import React from 'react';
|
||||
import { connect, Dispatch } from 'umi';
|
||||
import i18n from 'i18next';
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { Input, Modal, Form, Tag, Space } from 'antd'
|
||||
import { rsaPsw } from '@/utils'
|
||||
import { useTranslation, } from 'react-i18next'
|
||||
import { Modal, Tag, Space } from 'antd'
|
||||
import { useEffect, useState } from 'react';
|
||||
import styles from './index.less';
|
||||
import type { kFModelState } from './model'
|
||||
import type { settingModelState } from '@/pages/setting/model'
|
||||
const { CheckableTag } = Tag;
|
||||
type FieldType = {
|
||||
name?: string;
|
||||
};
|
||||
const Index = ({ kFModel, settingModel, dispatch, getKfList, parser_id, doc_id }) => {
|
||||
interface kFProps {
|
||||
dispatch: Dispatch;
|
||||
kFModel: kFModelState;
|
||||
settingModel: settingModelState;
|
||||
getKfList: () => void;
|
||||
parser_id: string;
|
||||
doc_id: string;
|
||||
}
|
||||
const Index: React.FC<kFProps> = ({ kFModel, settingModel, dispatch, getKfList, parser_id, doc_id }) => {
|
||||
const [selectedTag, setSelectedTag] = useState('')
|
||||
const { tenantIfo = {} } = settingModel
|
||||
const { parser_ids = '' } = tenantIfo
|
||||
|
||||
@ -1,20 +1,23 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'umi'
|
||||
import { UploadOutlined } from '@ant-design/icons';
|
||||
import type { UploadProps } from 'antd';
|
||||
import { Button, message, Upload } from 'antd';
|
||||
import { Button, Upload } from 'antd';
|
||||
import uploadService from '@/services/uploadService'
|
||||
|
||||
|
||||
const Index = ({ kb_id, getKfList }) => {
|
||||
console.log(kb_id)
|
||||
const createRequest = async function ({ file, onSuccess, onError }) {
|
||||
interface PropsType {
|
||||
kb_id: string;
|
||||
getKfList: () => void
|
||||
}
|
||||
type UploadRequestOption = Parameters<
|
||||
NonNullable<UploadProps["customRequest"]>
|
||||
>[0];
|
||||
const Index: React.FC<PropsType> = ({ kb_id, getKfList }) => {
|
||||
const createRequest: (props: UploadRequestOption) => void = async function ({ file, onSuccess, onError }) {
|
||||
const { retcode, data } = await uploadService.uploadFile(file, kb_id);
|
||||
if (retcode === 0) {
|
||||
onSuccess(data, file);
|
||||
onSuccess && onSuccess(data, file);
|
||||
|
||||
} else {
|
||||
onError(data);
|
||||
onError && onError(data);
|
||||
}
|
||||
getKfList && getKfList()
|
||||
};
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useNavigate, connect } from 'umi'
|
||||
import { Button, Form, Input, InputNumber, Radio, Select, Tag, Space, Avatar, Divider, List, Skeleton } from 'antd';
|
||||
import { useNavigate, connect, Dispatch } from 'umi'
|
||||
import { Button, Form, Input, Radio, Select, Tag, Space, } from 'antd';
|
||||
import type { kSModelState } from './model'
|
||||
import type { settingModelState } from '@/pages/setting/model'
|
||||
import styles from './index.less'
|
||||
const { CheckableTag } = Tag;
|
||||
const layout = {
|
||||
@ -10,41 +12,17 @@ const layout = {
|
||||
};
|
||||
const { Option } = Select
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
const validateMessages = {
|
||||
required: '${label} is required!',
|
||||
types: {
|
||||
email: '${label} is not a valid email!',
|
||||
number: '${label} is not a valid number!',
|
||||
},
|
||||
number: {
|
||||
range: '${label} must be between ${min} and ${max}',
|
||||
},
|
||||
};
|
||||
/* eslint-enable no-template-curly-in-string */
|
||||
|
||||
|
||||
interface DataType {
|
||||
gender: string;
|
||||
name: {
|
||||
title: string;
|
||||
first: string;
|
||||
last: string;
|
||||
};
|
||||
email: string;
|
||||
picture: {
|
||||
large: string;
|
||||
medium: string;
|
||||
thumbnail: string;
|
||||
};
|
||||
nat: string;
|
||||
interface kSProps {
|
||||
dispatch: Dispatch;
|
||||
kSModel: kSModelState;
|
||||
settingModel: settingModelState;
|
||||
kb_id: string
|
||||
}
|
||||
const tags = [{ title: '研报' }, { title: '法律' }, { title: '简历' }, { title: '说明书' }, { title: '书籍' }, { title: '演讲稿' }]
|
||||
|
||||
const Index: React.FC = ({ settingModel, kSModel, dispatch, ...props }) => {
|
||||
const Index: React.FC<kSProps> = ({ settingModel, kSModel, dispatch, kb_id }) => {
|
||||
let navigate = useNavigate();
|
||||
const { tenantIfo = {} } = settingModel
|
||||
const { parser_ids = '', embd_id = '' } = tenantIfo
|
||||
const { id = '' } = props
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
@ -53,12 +31,12 @@ const Index: React.FC = ({ settingModel, kSModel, dispatch, ...props }) => {
|
||||
payload: {
|
||||
}
|
||||
});
|
||||
if (id) {
|
||||
if (kb_id) {
|
||||
|
||||
dispatch({
|
||||
type: 'kSModel/getKbDetail',
|
||||
payload: {
|
||||
kb_id: id
|
||||
kb_id
|
||||
},
|
||||
callback(detail: any) {
|
||||
console.log(detail)
|
||||
@ -69,20 +47,20 @@ const Index: React.FC = ({ settingModel, kSModel, dispatch, ...props }) => {
|
||||
});
|
||||
}
|
||||
|
||||
}, [id])
|
||||
}, [kb_id])
|
||||
const [selectedTag, setSelectedTag] = useState('')
|
||||
const values = Form.useWatch([], form);
|
||||
console.log(values, '......变化')
|
||||
const onFinish = () => {
|
||||
form.validateFields().then(
|
||||
() => {
|
||||
if (id) {
|
||||
if (kb_id) {
|
||||
dispatch({
|
||||
type: 'kSModel/updateKb',
|
||||
payload: {
|
||||
...values,
|
||||
parser_id: selectedTag,
|
||||
kb_id: id,
|
||||
kb_id,
|
||||
embd_id: undefined
|
||||
}
|
||||
});
|
||||
@ -94,7 +72,7 @@ const Index: React.FC = ({ settingModel, kSModel, dispatch, ...props }) => {
|
||||
parser_id: selectedTag
|
||||
},
|
||||
callback(id: string) {
|
||||
navigate(`/knowledge/add/setting?activeKey=file&id=${id}`);
|
||||
navigate(`/knowledge/add/setting?activeKey=file&id=${kb_id}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -140,7 +118,7 @@ const Index: React.FC = ({ settingModel, kSModel, dispatch, ...props }) => {
|
||||
hasFeedback
|
||||
rules={[{ required: true, message: 'Please select your country!' }]}
|
||||
>
|
||||
<Select placeholder="Please select a country" disabled={id}>
|
||||
<Select placeholder="Please select a country" >
|
||||
{embd_id.split(',').map((item: string) => {
|
||||
return <Option value={item} key={item}>{item}</Option>
|
||||
})}
|
||||
|
||||
@ -1,8 +1,27 @@
|
||||
import { message } from 'antd';
|
||||
import { addParam } from '@/utils';
|
||||
import { Effect, Reducer, Subscription } from 'umi'
|
||||
import kbService from '@/services/kbService';
|
||||
|
||||
const Model = {
|
||||
export interface kSModelState {
|
||||
isShowPSwModal: boolean;
|
||||
isShowTntModal: boolean;
|
||||
loading: boolean;
|
||||
tenantIfo: any
|
||||
}
|
||||
export interface kSModelType {
|
||||
namespace: 'kSModel';
|
||||
state: kSModelState;
|
||||
effects: {
|
||||
createKb: Effect;
|
||||
updateKb: Effect;
|
||||
getKbDetail: Effect;
|
||||
};
|
||||
reducers: {
|
||||
updateState: Reducer<kSModelState>;
|
||||
};
|
||||
subscriptions: { setup: Subscription };
|
||||
}
|
||||
const Model: kSModelType = {
|
||||
namespace: 'kSModel',
|
||||
state: {
|
||||
isShowPSwModal: false,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { connect, useNavigate, useLocation } from 'umi'
|
||||
import React, { useMemo, useState, useEffect } from 'react';
|
||||
import { connect, useNavigate, useLocation, Dispatch } from 'umi'
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import type { MenuProps } from 'antd';
|
||||
import { Radio, Space, Tabs, Menu } from 'antd';
|
||||
import { Menu } from 'antd';
|
||||
import {
|
||||
ToolOutlined,
|
||||
BarsOutlined,
|
||||
@ -10,17 +10,24 @@ import {
|
||||
import File from './components/knowledge-file'
|
||||
import Setting from './components/knowledge-setting'
|
||||
import Search from './components/knowledge-search'
|
||||
import Chunk from './components/knowledge-chunk'
|
||||
import styles from './index.less'
|
||||
import { getWidth } from '@/utils'
|
||||
import { kAModelState } from './model'
|
||||
|
||||
|
||||
const Index: React.FC = ({ kAModel, dispatch }) => {
|
||||
interface kAProps {
|
||||
dispatch: Dispatch;
|
||||
kAModel: kAModelState;
|
||||
}
|
||||
const Index: React.FC<kAProps> = ({ kAModel, dispatch }) => {
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const { id, activeKey } = kAModel
|
||||
const { id, activeKey, doc_id } = kAModel
|
||||
const [windowWidth, setWindowWidth] = useState(getWidth());
|
||||
let navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
// 标记一下
|
||||
console.log(doc_id, '>>>>>>>>>>>>>doc_id')
|
||||
useEffect(() => {
|
||||
const widthSize = () => {
|
||||
const width = getWidth()
|
||||
@ -44,7 +51,9 @@ const Index: React.FC = ({ kAModel, dispatch }) => {
|
||||
dispatch({
|
||||
type: 'kAModel/updateState',
|
||||
payload: {
|
||||
...map
|
||||
doc_id: undefined,
|
||||
...map,
|
||||
|
||||
}
|
||||
});
|
||||
}, [location])
|
||||
@ -94,9 +103,11 @@ const Index: React.FC = ({ kAModel, dispatch }) => {
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.content}>
|
||||
{activeKey === 'file' && <File id={id} />}
|
||||
{activeKey === 'setting' && <Setting id={id} />}
|
||||
{activeKey === 'search' && <Search id={id} />}
|
||||
{activeKey === 'file' && !doc_id && <File kb_id={id} />}
|
||||
{activeKey === 'setting' && <Setting kb_id={id} />}
|
||||
{activeKey === 'search' && <Search />}
|
||||
{activeKey === 'file' && !!doc_id && <Chunk doc_id={doc_id} />}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@ -1,8 +1,27 @@
|
||||
import { Effect, Reducer, Subscription } from 'umi'
|
||||
import { message } from 'antd';
|
||||
import { addParam } from '@/utils';
|
||||
import kbService from '@/services/kbService';
|
||||
export interface kAModelState {
|
||||
isShowPSwModal: boolean;
|
||||
isShowTntModal: boolean;
|
||||
loading: boolean;
|
||||
tenantIfo: any;
|
||||
activeKey: string;
|
||||
id: string;
|
||||
doc_id: string
|
||||
}
|
||||
export interface kAModelType {
|
||||
namespace: 'kAModel';
|
||||
state: kAModelState;
|
||||
effects: {
|
||||
|
||||
const Model = {
|
||||
};
|
||||
reducers: {
|
||||
updateState: Reducer<kAModelState>;
|
||||
};
|
||||
subscriptions: { setup: Subscription };
|
||||
}
|
||||
const Model: kAModelType = {
|
||||
namespace: 'kAModel',
|
||||
state: {
|
||||
isShowPSwModal: false,
|
||||
@ -10,7 +29,8 @@ const Model = {
|
||||
loading: false,
|
||||
tenantIfo: {},
|
||||
activeKey: 'setting',
|
||||
id: ''
|
||||
id: '',
|
||||
doc_id: ''
|
||||
|
||||
},
|
||||
subscriptions: {
|
||||
|
||||
@ -1,19 +1,15 @@
|
||||
import React, { FC } from 'react';
|
||||
import { IndexModelState, ConnectProps, Loading, connect } from 'umi';
|
||||
import React from 'react';
|
||||
import { connect, Dispatch } from 'umi';
|
||||
import type { chatModelState } from './model'
|
||||
|
||||
interface PageProps extends ConnectProps {
|
||||
index: IndexModelState;
|
||||
loading: boolean;
|
||||
interface chatProps {
|
||||
chatModel: chatModelState;
|
||||
dispatch: Dispatch
|
||||
}
|
||||
|
||||
const IndexPage: FC<PageProps> = ({ index, dispatch }) => {
|
||||
const { name } = index;
|
||||
return <div>chat: {name}</div>;
|
||||
const View: React.FC<chatProps> = ({ chatModel, dispatch }) => {
|
||||
const { name } = chatModel;
|
||||
return <div>chat:{name} </div>;
|
||||
};
|
||||
|
||||
export default connect(
|
||||
({ index, loading }: { index: IndexModelState; loading: Loading }) => ({
|
||||
index,
|
||||
loading: loading.models.index,
|
||||
}),
|
||||
)(IndexPage);
|
||||
export default connect(({ chatModel, loading }) => ({ chatModel, loading }))(View);
|
||||
@ -1,25 +1,23 @@
|
||||
import { Effect, ImmerReducer, Reducer, Subscription } from 'umi';
|
||||
import { Effect, Reducer, Subscription } from 'umi';
|
||||
|
||||
export interface IndexModelState {
|
||||
export interface chatModelState {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface IndexModelType {
|
||||
namespace: 'index';
|
||||
state: IndexModelState;
|
||||
export interface chatModelType {
|
||||
namespace: 'chatModel';
|
||||
state: chatModelState;
|
||||
effects: {
|
||||
query: Effect;
|
||||
};
|
||||
reducers: {
|
||||
save: Reducer<IndexModelState>;
|
||||
// 启用 immer 之后
|
||||
// save: ImmerReducer<IndexModelState>;
|
||||
save: Reducer<chatModelState>;
|
||||
};
|
||||
subscriptions: { setup: Subscription };
|
||||
}
|
||||
|
||||
const IndexModel: IndexModelType = {
|
||||
namespace: 'index',
|
||||
const Model: chatModelType = {
|
||||
namespace: 'chatModel',
|
||||
state: {
|
||||
name: 'kate',
|
||||
},
|
||||
@ -34,10 +32,6 @@ const IndexModel: IndexModelType = {
|
||||
...action.payload,
|
||||
};
|
||||
},
|
||||
// 启用 immer 之后
|
||||
// save(state, action) {
|
||||
// state.name = action.payload;
|
||||
// },
|
||||
},
|
||||
subscriptions: {
|
||||
setup({ dispatch, history }) {
|
||||
@ -49,4 +43,4 @@ const IndexModel: IndexModelType = {
|
||||
},
|
||||
};
|
||||
|
||||
export default IndexModel;
|
||||
export default Model;
|
||||
@ -20,7 +20,7 @@ const App: React.FC = () => {
|
||||
}
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
setFileList((fileList) => {
|
||||
setFileList((fileList: any) => {
|
||||
const percent = fileList[0]?.percent
|
||||
if (percent + 10 >= 100) {
|
||||
clearInterval(timer)
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
import React, { useEffect, useState, } from 'react';
|
||||
import { useNavigate, connect } from 'umi'
|
||||
import { useNavigate, connect, Dispatch } from 'umi'
|
||||
import { Card, List, Popconfirm, message, FloatButton, Row, Col } from 'antd';
|
||||
import { MinusSquareOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import styles from './index.less'
|
||||
import { formatDate } from '@/utils/date'
|
||||
|
||||
const dd = [{
|
||||
title: 'Title 4',
|
||||
text: '4',
|
||||
des: '111'
|
||||
}]
|
||||
const Index: React.FC = ({ knowledgeModel, dispatch }) => {
|
||||
import type { knowledgeModelState } from './model'
|
||||
interface KnowledgeProps {
|
||||
dispatch: Dispatch;
|
||||
knowledgeModel: knowledgeModelState
|
||||
}
|
||||
const Index: React.FC<KnowledgeProps> = ({ knowledgeModel, dispatch }) => {
|
||||
const navigate = useNavigate()
|
||||
// const [datas, setDatas] = useState(data)
|
||||
const { data } = knowledgeModel
|
||||
const confirm = (id) => {
|
||||
const { data = [] } = knowledgeModel
|
||||
console.log(knowledgeModel)
|
||||
const confirm = (id: string) => {
|
||||
dispatch({
|
||||
type: 'knowledgeModel/rmKb',
|
||||
payload: {
|
||||
@ -49,8 +49,8 @@ const Index: React.FC = ({ knowledgeModel, dispatch }) => {
|
||||
<FloatButton onClick={handleAddKnowledge} icon={<PlusOutlined />} type="primary" style={{ right: 24, top: 100 }} />
|
||||
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
|
||||
{
|
||||
data.map((item, index) => {
|
||||
return (<Col className="gutter-row" key={item.title} xs={24} sm={12} md={8} lg={6}>
|
||||
data.map((item: any) => {
|
||||
return (<Col className="gutter-row" key={item.name} xs={24} sm={12} md={8} lg={6}>
|
||||
<Card className={styles.card}
|
||||
onClick={() => { handleEditKnowledge(item.id) }}
|
||||
>
|
||||
@ -63,7 +63,7 @@ const Index: React.FC = ({ knowledgeModel, dispatch }) => {
|
||||
<Popconfirm
|
||||
title="Delete the task"
|
||||
description="Are you sure to delete this task?"
|
||||
onConfirm={(e) => {
|
||||
onConfirm={(e: any) => {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation()
|
||||
confirm(item.id)
|
||||
|
||||
@ -1,8 +1,24 @@
|
||||
import { Effect, Reducer, Subscription } from 'umi'
|
||||
import { message } from 'antd';
|
||||
import { addParam } from '@/utils';
|
||||
import kbService from '@/services/kbService';
|
||||
|
||||
const Model = {
|
||||
export interface knowledgeModelState {
|
||||
loading: boolean;
|
||||
data: any[]
|
||||
}
|
||||
export interface knowledgegModelType {
|
||||
namespace: 'knowledgeModel';
|
||||
state: knowledgeModelState;
|
||||
effects: {
|
||||
rmKb: Effect;
|
||||
getList: Effect;
|
||||
};
|
||||
reducers: {
|
||||
updateState: Reducer<knowledgeModelState>;
|
||||
};
|
||||
subscriptions: { setup: Subscription };
|
||||
}
|
||||
const Model: knowledgegModelType = {
|
||||
namespace: 'knowledgeModel',
|
||||
state: {
|
||||
loading: false,
|
||||
|
||||
@ -3,6 +3,7 @@ import { Input, Form, Button, Checkbox } from 'antd';
|
||||
import styles from './index.less';
|
||||
import { rsaPsw } from '@/utils'
|
||||
import { useState, useEffect, FC } from 'react';
|
||||
|
||||
interface LoginProps {
|
||||
dispatch: Dispatch;
|
||||
}
|
||||
|
||||
@ -1,15 +1,30 @@
|
||||
import { Effect, Reducer, Subscription } from 'umi'
|
||||
import { message } from 'antd';
|
||||
import { addParam } from '@/utils';
|
||||
import userService from '@/services/userService';
|
||||
|
||||
const Model = {
|
||||
export interface loginModelState {
|
||||
list: any[];
|
||||
info: any;
|
||||
visible: boolean;
|
||||
}
|
||||
export interface logingModelType {
|
||||
namespace: 'loginModel';
|
||||
state: loginModelState;
|
||||
effects: {
|
||||
login: Effect;
|
||||
register: Effect;
|
||||
};
|
||||
reducers: {
|
||||
updateState: Reducer<loginModelState>;
|
||||
};
|
||||
subscriptions: { setup: Subscription };
|
||||
}
|
||||
const Model: logingModelType = {
|
||||
namespace: 'loginModel',
|
||||
state: {
|
||||
list: [],
|
||||
info: {},
|
||||
visible: false,
|
||||
pagination: {},
|
||||
campaignInfo: {}
|
||||
},
|
||||
subscriptions: {
|
||||
setup({ dispatch, history }) {
|
||||
|
||||
@ -9,7 +9,6 @@ import { useEffect, useState, FC } from 'react';
|
||||
import { RadarChartOutlined } from '@ant-design/icons';
|
||||
import { ProCard } from '@ant-design/pro-components';
|
||||
import { Button, Tag, Row, Col, Card } from 'antd';
|
||||
import { divide } from 'lodash';
|
||||
|
||||
|
||||
interface DataType {
|
||||
|
||||
@ -3,7 +3,6 @@ import i18n from 'i18next';
|
||||
import { FC } from 'react'
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { Input, Modal, Form } from 'antd'
|
||||
import { rsaPsw } from '@/utils'
|
||||
import styles from './index.less';
|
||||
|
||||
type FieldType = {
|
||||
|
||||
@ -3,7 +3,6 @@ import { FC } from 'react'
|
||||
import i18n from 'i18next';
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { Input, Modal, Form, Select } from 'antd'
|
||||
import { rsaPsw } from '@/utils'
|
||||
import styles from './index.less';
|
||||
|
||||
type FieldType = {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { connect, Dispatch } from 'umi';
|
||||
import i18n from 'i18next';
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { Button, Input, Modal, Form, FloatButton, Table } from 'antd'
|
||||
import { Button, FloatButton } from 'antd'
|
||||
|
||||
|
||||
import styles from './index.less';
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { Effect, Reducer, Subscription } from 'umi';
|
||||
import { message } from 'antd';
|
||||
import { addParam } from '@/utils';
|
||||
import userService from '@/services/userService';
|
||||
import { rearg } from 'lodash';
|
||||
|
||||
export interface settingModelState {
|
||||
isShowPSwModal: boolean;
|
||||
|
||||
Reference in New Issue
Block a user