feat(knowledge): 完成知识库基本功能开发

This commit is contained in:
v-zhangjc9
2025-05-28 15:06:30 +08:00
parent f7ed3bd270
commit 3ee6303cf5
30 changed files with 1787 additions and 273 deletions

View File

@@ -1,30 +1,85 @@
import React from 'react'
import {useParams} from 'react-router'
import {amisRender, crudCommonOptions} from '../../../util/amis.tsx'
import {useNavigate, useParams} from 'react-router'
import {amisRender, crudCommonOptions, mappingField, mappingItem} from '../../../util/amis.tsx'
const statusMapping = [
mappingItem('解析中', 'RUNNING', 'bg-warning'),
mappingItem('使用中', 'FINISHED', 'bg-success'),
]
const DataDetail: React.FC = () => {
const {name} = useParams()
const {knowledge_id} = useParams()
const navigate = useNavigate()
return (
<div className="import-detail h-full">
{amisRender(
{
className: 'h-full',
type: 'page',
title: `数据详情 (知识库:${name}`,
title: {
type: 'wrapper',
size: 'none',
body: [
'数据详情 (知识库:',
{
type: 'service',
className: 'inline',
api: {
method: 'get',
url: 'http://127.0.0.1:8080/knowledge/name',
headers: {
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
},
data: {
id: knowledge_id,
},
},
body: {
type: 'tpl',
tpl: '${name}',
},
},
'',
],
},
size: 'lg',
actions: [],
body: [
{
type: 'crud',
api: {
url: 'http://127.0.0.1:8080/knowledge/list_points?name=${name}',
method: 'get',
url: 'http://127.0.0.1:8080/group/list',
headers: {
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
},
data: {
knowledge_id,
},
},
...crudCommonOptions(),
headerToolbar: [
'reload',
{
type: 'action',
icon: 'fa fa-plus',
label: '',
tooltip: '新增',
tooltipPlacement: 'top',
onEvent: {
click: {
actions: [
{
actionType: 'custom',
// @ts-ignore
script: (context, action, event) => {
navigate(`/ai/knowledge/import/${knowledge_id}`)
},
},
],
},
},
},
],
columns: [
{
@@ -32,8 +87,15 @@ const DataDetail: React.FC = () => {
hidden: true,
},
{
name: 'text',
label: '内容',
name: 'name',
label: '文件名',
},
{
name: 'status',
label: '状态',
width: 50,
align: 'center',
...mappingField('status', statusMapping),
},
{
type: 'operation',
@@ -42,30 +104,17 @@ const DataDetail: React.FC = () => {
buttons: [
{
type: 'action',
label: '编辑',
label: '查看',
level: 'link',
size: 'lg',
actionType: 'dialog',
dialog: {
title: '编辑文段',
size: 'md',
body: {
type: 'form',
body: [
size: 'sm',
onEvent: {
click: {
actions: [
{
type: 'input-text',
name: 'id',
disabled: true,
label: '文段ID',
},
{
type: 'editor',
label: '内容',
name: 'text',
language: 'plaintext',
options: {
lineNumbers: 'off',
wordWrap: 'bounded',
actionType: 'custom',
// @ts-ignore
script: (context, action, event) => {
navigate(`/ai/knowledge/detail/${knowledge_id}/segment/${context.props.data['id']}`)
},
},
],
@@ -77,13 +126,17 @@ const DataDetail: React.FC = () => {
label: '删除',
className: 'text-danger hover:text-red-600',
level: 'link',
size: 'xs',
size: 'sm',
actionType: 'ajax',
api: {
method: 'get',
url: 'http://127.0.0.1:8080/group/delete',
headers: {
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
},
data: {
id: '${id}',
},
},
confirmText: '确认删除',
confirmTitle: '删除',

View File

@@ -10,12 +10,37 @@ const ImportDataDiv = styled.div`
`
const DataImport: React.FC = () => {
const {name} = useParams()
const {knowledge_id} = useParams()
return (
<ImportDataDiv className="import-data h-full">
{amisRender({
type: 'page',
title: `数据导入 (知识库:${name}`,
title: {
type: 'wrapper',
size: 'none',
body: [
'数据导入 (知识库:',
{
type: 'service',
className: 'inline',
api: {
method: 'get',
url: 'http://127.0.0.1:8080/knowledge/name',
headers: {
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
},
data: {
id: knowledge_id,
},
},
body: {
type: 'tpl',
tpl: '${name}',
},
},
'',
],
},
body: [
[
{
@@ -53,7 +78,7 @@ const DataImport: React.FC = () => {
name: 'type',
type: 'radios',
label: '数据形式',
value: 'text',
value: 'file',
options: [
{
value: 'text',
@@ -62,7 +87,6 @@ const DataImport: React.FC = () => {
{
value: 'file',
label: '文件',
disabled: true,
},
],
},
@@ -82,10 +106,38 @@ const DataImport: React.FC = () => {
type: 'input-file',
name: 'files',
label: '数据文件',
accept: '.txt,.csv',
autoUpload: false,
drag: true,
multiple: true,
useChunk: true,
accept: '*',
// 5MB 5242880
// 100MB 104857600
// 500MB 524288000
// 1GB 1073741824
maxSize: '',
maxLength: 0,
startChunkApi: {
method: 'post',
url: 'http://127.0.0.1:8080/upload/start',
headers: {
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
},
},
chunkApi: {
method: 'post',
url: 'http://127.0.0.1:8080/upload/slice',
headers: {
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
},
},
finishChunkApi: {
method: 'post',
url: 'http://127.0.0.1:8080/upload/finish',
headers: {
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
},
},
},
{
className: 'text-right',
@@ -103,16 +155,10 @@ const DataImport: React.FC = () => {
},
dataType: 'form',
data: {
mode: '${mode}',
type: '${type}',
content: '${content}',
},
// @ts-ignore
adaptor: (payload, response, api, context) => {
console.log(payload)
return {
items: payload,
}
mode: '${mode|default:undefined}',
type: '${type|default:undefined}',
content: '${content|default:undefined}',
files: '${files|default:undefined}',
},
},
reload: 'preview_list?rows=${items}',
@@ -121,6 +167,22 @@ const DataImport: React.FC = () => {
type: 'submit',
label: '提交',
level: 'primary',
actionType: 'ajax',
api: {
method: 'post',
url: 'http://127.0.0.1:8080/knowledge/submit_text',
headers: {
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
},
dataType: 'form',
data: {
id: knowledge_id,
mode: '${mode|default:undefined}',
type: '${type|default:undefined}',
content: '${content|default:undefined}',
files: '${files|default:undefined}',
},
},
},
],
},
@@ -155,6 +217,7 @@ const DataImport: React.FC = () => {
],
listItem: {
body: {
className: 'white-space-pre-line',
type: 'tpl',
tpl: '${text}',
},

View File

@@ -0,0 +1,133 @@
import React from 'react'
import {useParams} from 'react-router'
import {amisRender, crudCommonOptions} from '../../../util/amis.tsx'
const DataDetail: React.FC = () => {
const {knowledge_id, group_id} = useParams()
return (
<div className="import-detail h-full">
{amisRender(
{
className: 'h-full',
type: 'page',
title: {
type: 'wrapper',
size: 'none',
body: [
'数据详情 (知识库:',
{
type: 'service',
className: 'inline',
api: {
method: 'get',
url: 'http://127.0.0.1:8080/knowledge/name',
headers: {
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
},
data: {
id: knowledge_id,
},
},
body: {
type: 'tpl',
tpl: '${name}',
},
},
'',
],
},
size: 'lg',
actions: [],
body: [
{
type: 'crud',
api: {
method: 'get',
url: 'http://127.0.0.1:8080/segment/list',
headers: {
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
},
data: {
knowledge_id,
group_id,
},
},
...crudCommonOptions(),
headerToolbar: [
'reload',
],
columns: [
{
name: 'id',
hidden: true,
},
{
name: 'text',
label: '内容',
className: 'white-space-pre-line',
},
{
type: 'operation',
label: '操作',
width: 50,
buttons: [
/*{
type: 'action',
label: '编辑',
level: 'link',
size: 'lg',
actionType: 'dialog',
dialog: {
title: '编辑文段',
size: 'md',
body: {
type: 'form',
body: [
{
type: 'input-text',
name: 'id',
disabled: true,
label: '文段ID',
},
{
type: 'editor',
label: '内容',
name: 'text',
language: 'plaintext',
options: {
lineNumbers: 'off',
wordWrap: 'bounded',
},
},
],
},
},
},*/
{
type: 'action',
label: '删除',
className: 'text-danger hover:text-red-600',
level: 'link',
size: 'sm',
actionType: 'ajax',
api: {
method: 'get',
headers: {
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
},
},
confirmText: '删除后无法恢复,确认删除该记录?',
confirmTitle: '删除',
},
],
},
],
},
],
},
)}
</div>
)
}
export default DataDetail

View File

@@ -38,6 +38,8 @@ const Knowledge: React.FC = () => {
type: 'action',
label: '',
icon: 'fa fa-plus',
tooltip: '新增',
tooltipPlacement: 'top',
actionType: 'dialog',
dialog: {
title: '新增知识库',
@@ -111,7 +113,7 @@ const Knowledge: React.FC = () => {
type: 'action',
label: '详情',
level: 'link',
size: 'xs',
size: 'sm',
onEvent: {
click: {
actions: [
@@ -119,7 +121,7 @@ const Knowledge: React.FC = () => {
actionType: 'custom',
// @ts-ignore
script: (context, action, event) => {
navigate(`/ai/knowledge/detail/${context.props.data['name']}`)
navigate(`/ai/knowledge/detail/${context.props.data['id']}`)
},
},
],
@@ -130,7 +132,7 @@ const Knowledge: React.FC = () => {
type: 'action',
label: '导入',
level: 'link',
size: 'xs',
size: 'sm',
onEvent: {
click: {
actions: [
@@ -138,7 +140,7 @@ const Knowledge: React.FC = () => {
actionType: 'custom',
// @ts-ignore
script: (context, action, event) => {
navigate(`/ai/knowledge/import/${context.props.data['name']}`)
navigate(`/ai/knowledge/import/${context.props.data['id']}`)
},
},
],
@@ -150,14 +152,17 @@ const Knowledge: React.FC = () => {
label: '删除',
className: 'text-danger hover:text-red-600',
level: 'link',
size: 'xs',
size: 'sm',
actionType: 'ajax',
api: {
method: 'get',
url: 'http://127.0.0.1:8080/knowledge/delete?name=${name}',
url: 'http://127.0.0.1:8080/knowledge/delete',
headers: {
'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
},
data: {
id: '${id}',
},
},
confirmText: '确认删除',
confirmTitle: '删除',

View File

@@ -17,6 +17,7 @@ import Conversation from './pages/ai/Conversation.tsx'
import Inspection from './pages/ai/Inspection.tsx'
import DataDetail from './pages/ai/knowledge/DataDetail.tsx'
import DataImport from './pages/ai/knowledge/DataImport.tsx'
import DataSegment from './pages/ai/knowledge/DataSegment.tsx'
import Knowledge from './pages/ai/knowledge/Knowledge.tsx'
import App from './pages/App.tsx'
import Cloud from './pages/overview/Cloud.tsx'
@@ -95,13 +96,17 @@ export const routes: RouteObject[] = [
Component: Knowledge,
},
{
path: 'knowledge/import/:name',
path: 'knowledge/import/:knowledge_id',
Component: DataImport,
},
{
path: 'knowledge/detail/:name',
path: 'knowledge/detail/:knowledge_id',
Component: DataDetail,
},
{
path: 'knowledge/detail/:knowledge_id/segment/:group_id',
Component: DataSegment,
},
],
},
],

View File

@@ -77,6 +77,7 @@ export const amisRender = (schema: Schema, data: Record<any, any> = {}) => {
theme: theme,
},
{
enableAMISDebug: true,
fetcher: async (api: any) => {
let {url, method, data, responseType, config, headers} = api
config = config || {}