imetting_frontend/src/pages/EditKnowledgeBase.jsx

252 lines
7.2 KiB
React
Raw Normal View History

2025-10-16 09:15:07 +00:00
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { Link, useNavigate, useParams } from 'react-router-dom';
import apiClient from '../utils/apiClient';
import { ArrowLeft, FileText, Tag, Save } from 'lucide-react';
import MDEditor, * as commands from '@uiw/react-md-editor';
import '@uiw/react-md-editor/markdown-editor.css';
import { buildApiUrl, API_ENDPOINTS } from '../config/api';
import TagEditor from '../components/TagEditor';
import './EditKnowledgeBase.css';
const EditKnowledgeBase = ({ user }) => {
const navigate = useNavigate();
const { kb_id } = useParams();
const [formData, setFormData] = useState({
title: '',
content: '',
tags: ''
});
const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false);
const [error, setError] = useState('');
const [kb, setKb] = useState(null);
const handleContentChange = useCallback((value) => {
setFormData(prev => ({ ...prev, content: value || '' }));
}, []);
useEffect(() => {
fetchKbData();
}, [kb_id]);
const fetchKbData = async () => {
try {
const response = await apiClient.get(buildApiUrl(API_ENDPOINTS.KNOWLEDGE_BASE.DETAIL(kb_id)));
const kbData = response.data;
// Check if current user is the creator
if (kbData.creator_id !== user.user_id) {
navigate('/knowledge-base');
return;
}
setKb(kbData);
setFormData({
title: kbData.title,
content: kbData.content || '',
tags: kbData.tags ? kbData.tags.map(t => t.name).join(', ') : ''
});
} catch (err) {
setError('无法加载知识库信息');
console.error('Error fetching knowledge base:', err);
} finally {
setIsLoading(false);
}
};
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
};
const handleSubmit = async (e) => {
e.preventDefault();
if (!formData.title.trim()) {
setError('请输入知识库标题');
return;
}
setIsSaving(true);
setError('');
try {
const updateData = {
title: formData.title,
content: formData.content,
tags: formData.tags
};
await apiClient.put(buildApiUrl(API_ENDPOINTS.KNOWLEDGE_BASE.UPDATE(kb_id)), updateData);
navigate('/knowledge-base');
} catch (err) {
setError(err.response?.data?.message || '更新知识库失败,请重试');
} finally {
setIsSaving(false);
}
};
// 自定义工具栏命令配置
const customCommands = [
commands.bold,
commands.italic,
commands.strikethrough,
commands.hr,
commands.group([
commands.title1,
commands.title2,
commands.title3,
commands.title4,
commands.title5,
commands.title6,
], {
name: 'title',
groupName: 'title',
buttonProps: { 'aria-label': '插入标题', title: '插入标题' }
}),
commands.divider,
commands.link,
commands.quote,
commands.code,
commands.codeBlock,
commands.image,
commands.divider,
commands.unorderedListCommand,
commands.orderedListCommand,
commands.checkedListCommand,
];
// 右侧额外命令(预览、全屏等)
const customExtraCommands = [
commands.codeEdit,
commands.codeLive,
commands.codePreview,
commands.divider,
commands.fullscreen,
];
if (isLoading) {
return (
<div className="edit-kb-page">
<div className="loading-container">
<div className="loading-spinner"></div>
<p>加载中...</p>
</div>
</div>
);
}
return (
<div className="edit-kb-page">
<div className="edit-header">
<Link to="/knowledge-base">
<span className="back-link">
<ArrowLeft size={20} />
<span>返回知识库</span>
</span>
</Link>
</div>
<div className="edit-content">
<div className="edit-card">
<header className="edit-card-header">
<h1>编辑知识库</h1>
<p>修改知识库标题标签和内容摘要</p>
</header>
<form onSubmit={handleSubmit} className="edit-form">
<div className="form-group">
<label htmlFor="title">
<FileText size={18} />
知识库标题 *
</label>
<input
type="text"
id="title"
name="title"
value={formData.title}
onChange={handleInputChange}
placeholder="请输入知识库标题"
required
/>
</div>
<div className="form-group">
<label htmlFor="tags">
<Tag size={18} />
标签
</label>
<TagEditor
value={formData.tags}
onChange={(value) => setFormData(prev => ({ ...prev, tags: value }))}
placeholder="输入标签,按回车或逗号分隔"
/>
</div>
<div className="form-group">
<div className="content-header">
<label htmlFor="content">
<FileText size={18} />
内容总结
</label>
</div>
<div className="markdown-editor-container">
<MDEditor
key="content-editor"
value={formData.content}
onChange={handleContentChange}
data-color-mode="light"
height={500}
preview="edit"
hideToolbar={false}
toolbarBottom={false}
commands={customCommands}
extraCommands={customExtraCommands}
autoFocus={false}
textareaProps={{
placeholder: '在这里编写知识库内容摘要...',
style: {
fontSize: '14px',
lineHeight: '1.5',
fontFamily: 'inherit'
},
spellCheck: false,
autoComplete: 'off',
autoCapitalize: 'off',
autoCorrect: 'off'
}}
/>
</div>
<div className="markdown-hint">
<small>使用Markdown格式编写知识库内容支持**粗体***斜体*# 标题- 列表等格式</small>
</div>
</div>
{error && (
<div className="error-message">{error}</div>
)}
<div className="form-actions">
<Link to="/knowledge-base">
<span className="btn-cancel">取消</span>
</Link>
<button
type="submit"
className="btn-submit"
disabled={isSaving}
>
<Save size={16} />
{isSaving ? '保存中...' : '保存更改'}
</button>
</div>
</form>
</div>
</div>
</div>
);
};
export default EditKnowledgeBase;