加入脑图功能

mula.liu 2025-09-16 20:05:25 +08:00
parent c7846a9f03
commit 2735697fc7
7 changed files with 77 additions and 72 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
dist.zip

Binary file not shown.

View File

@ -17,11 +17,9 @@ function App() {
// Load user from localStorage on app start
useEffect(() => {
const savedUser = localStorage.getItem('iMeetingUser');
console.log('Saved user from localStorage:', savedUser);
if (savedUser) {
try {
const parsedUser = JSON.parse(savedUser);
console.log('Parsed user:', parsedUser);
setUser(parsedUser);
} catch (error) {
console.error('Error parsing saved user:', error);

View File

@ -86,8 +86,9 @@ const MindMap = ({ meetingId, meetingTitle, meeting, formatDateTime }) => {
// 线
processed = processed.replace(/^---+$/gm, '');
//
if (!processed.startsWith('# ')) {
//
const hasMainTitle = processed.match(/^#+\s+.*会议总结/m);
if (!processed.startsWith('# ') && !hasMainTitle) {
processed = `# 会议总结\n\n${processed}`;
}
@ -96,18 +97,25 @@ const MindMap = ({ meetingId, meetingTitle, meeting, formatDateTime }) => {
let i = 0;
while (i < lines.length) {
const line = lines[i].trim();
const line = lines[i];
const trimmedLine = line.trim();
if (line === '') {
if (trimmedLine === '') {
i++;
continue;
}
//
if (line.match(/^#+\s+/)) {
if (trimmedLine.match(/^#+\s+/)) {
//
let cleanTitle = line.replace(/\*\*([^*]+)\*\*/g, '$1'); //
let cleanTitle = trimmedLine.replace(/\*\*([^*]+)\*\*/g, '$1'); //
cleanTitle = cleanTitle.replace(/[*_]/g, ''); // markdown
// ""
if (cleanTitle.includes('会议总结') && !cleanTitle.startsWith('# ')) {
cleanTitle = `# ${cleanTitle.replace(/^#+\s*/, '')}`;
}
processedLines.push(cleanTitle);
//
@ -119,16 +127,19 @@ const MindMap = ({ meetingId, meetingTitle, meeting, formatDateTime }) => {
//
if (j < lines.length) {
const nextLine = lines[j].trim();
if (!nextLine.match(/^#+\s+/) && !nextLine.match(/^[-*+]\s+/) && !nextLine.includes('|') && nextLine.length > 0) {
const nextLineOriginal = lines[j];
if (!nextLine.match(/^#+\s+/) && !nextLine.match(/^[-*+]\s+/) && !nextLineOriginal.match(/^\s+[-*+]\s+/) && !nextLine.includes('|') && nextLine.length > 0) {
//
const paragraphLines = [];
while (j < lines.length) {
const currentLine = lines[j].trim();
const currentLineOriginal = lines[j];
if (currentLine === '') {
j++;
continue;
}
if (currentLine.match(/^#+\s+/) || currentLine.match(/^[-*+]\s+/) || currentLine.includes('|')) {
//
if (currentLine.match(/^#+\s+/) || currentLine.match(/^[-*+]\s+/) || currentLineOriginal.match(/^\s+[-*+]\s+/) || currentLine.includes('|')) {
break;
}
paragraphLines.push(currentLine);
@ -163,18 +174,21 @@ const MindMap = ({ meetingId, meetingTitle, meeting, formatDateTime }) => {
}
}
}
//
else if (line.match(/^[-*+]\s+/)) {
const cleanListItem = line.replace(/\*\*([^*]+)\*\*/g, '$1'); //
processedLines.push(cleanListItem);
//
else if (trimmedLine.match(/^[-*+]\s+/)) {
//
if (!line.match(/^\s/)) {
const cleanListItem = trimmedLine.replace(/\*\*([^*]+)\*\*/g, '$1'); //
processedLines.push(cleanListItem);
}
}
// markmap
else if (line.includes('|')) {
processedLines.push(line);
else if (trimmedLine.includes('|')) {
processedLines.push(trimmedLine);
}
//
else if (line.length > 0 && !line.match(/\*\*总字数:\d+字\*\*/)) {
processedLines.push(`- ${line}`);
else if (trimmedLine.length > 0 && !trimmedLine.match(/\*\*总字数:\d+字\*\*/)) {
processedLines.push(`- ${trimmedLine}`);
}
i++;
@ -193,14 +207,10 @@ const MindMap = ({ meetingId, meetingTitle, meeting, formatDateTime }) => {
try {
const processedMarkdown = preprocessMarkdownForMindMap(markdown);
console.log('原始markdown内容:', markdown);
console.log('预处理后的markdown:', processedMarkdown);
const transformer = new Transformer();
const { root } = transformer.transform(processedMarkdown);
console.log('转换后的思维导图数据:', root);
if (markmapRef.current) {
markmapRef.current.setData(root);
} else {

View File

@ -6,8 +6,6 @@ import UserManagement from '../components/admin/UserManagement';
import SystemConfiguration from '../components/admin/SystemConfiguration';
import './AdminManagement.css';
const { TabPane } = Tabs;
const AdminManagement = () => {
const navigate = useNavigate();
@ -28,20 +26,22 @@ const AdminManagement = () => {
</header>
<div className="admin-content">
<div className="admin-wrapper">
<Tabs defaultActiveKey="userManagement" className="admin-tabs">
<TabPane
tab={<span><Users size={16} /> 用户管理</span>}
key="userManagement"
>
<UserManagement />
</TabPane>
<TabPane
tab={<span><Settings size={16} /> 系统配置</span>}
key="systemConfiguration"
>
<SystemConfiguration />
</TabPane>
</Tabs>
<Tabs
defaultActiveKey="userManagement"
className="admin-tabs"
items={[
{
key: 'userManagement',
label: <span><Users size={16} /> 用户管理</span>,
children: <UserManagement />
},
{
key: 'systemConfiguration',
label: <span><Settings size={16} /> 系统配置</span>,
children: <SystemConfiguration />
}
]}
/>
</div>
</div>
</div>

View File

@ -39,14 +39,10 @@ const Dashboard = ({ user, onLogout }) => {
const fetchUserData = async () => {
try {
setLoading(true);
console.log('Fetching user data for user_id:', user.user_id);
const userResponse = await apiClient.get(buildApiUrl(API_ENDPOINTS.USERS.DETAIL(user.user_id)));
console.log('User response:', userResponse.data);
setUserInfo(userResponse.data);
const meetingsResponse = await apiClient.get(buildApiUrl(`${API_ENDPOINTS.MEETINGS.LIST}?user_id=${user.user_id}`));
console.log('Meetings response:', meetingsResponse.data);
setMeetings(meetingsResponse.data);
} catch (err) {

View File

@ -12,8 +12,6 @@ import MeetingSummary from '../components/MeetingSummary';
import { Tabs } from 'antd';
import './MeetingDetails.css';
const { TabPane } = Tabs;
const MeetingDetails = ({ user }) => {
const { meeting_id } = useParams();
const navigate = useNavigate();
@ -224,15 +222,11 @@ const MeetingDetails = ({ user }) => {
const transcriptResponse = await apiClient.get(`${baseUrl}${transcriptEndpoint}`);
setTranscript(transcriptResponse.data);
console.log('First transcript item:', transcriptResponse.data[0]);
// 使speaker_id
const allSpeakerIds = transcriptResponse.data
.map(item => item.speaker_id)
.filter(speakerId => speakerId !== null && speakerId !== undefined);
console.log('Extracted speaker IDs:', allSpeakerIds);
const uniqueSpeakers = [...new Set(allSpeakerIds)]
.map(speakerId => {
const segment = transcriptResponse.data.find(item => item.speaker_id === speakerId);
@ -243,7 +237,6 @@ const MeetingDetails = ({ user }) => {
})
.sort((a, b) => a.speaker_id - b.speaker_id); // speaker_id
console.log('Final unique speakers:', uniqueSpeakers);
setSpeakerList(uniqueSpeakers);
//
@ -467,9 +460,6 @@ const MeetingDetails = ({ user }) => {
const handleSpeakerEditOpen = () => {
console.log('Opening speaker edit modal');
console.log('Current transcript:', transcript);
console.log('Current speakerList:', speakerList);
console.log('Current editingSpeakers:', editingSpeakers);
setShowSpeakerEdit(true);
};
@ -947,26 +937,37 @@ const MeetingDetails = ({ user }) => {
</section>
<section className="card-section summary-tabs-section">
<Tabs defaultActiveKey="1">
<TabPane tab={<span><FileText size={16} /> 会议总结</span>} key="1">
<MeetingSummary
meeting={meeting}
summaryResult={summaryResult}
summaryHistory={summaryHistory}
isCreator={isCreator}
onOpenSummaryModal={openSummaryModal}
formatDateTime={formatDateTime}
/>
</TabPane>
<TabPane tab={<span><Brain size={16} /> 会议脑图</span>} key="2">
<MindMap
meetingId={meeting_id}
meetingTitle={meeting.title}
meeting={meeting}
formatDateTime={formatDateTime}
/>
</TabPane>
</Tabs>
<Tabs
defaultActiveKey="1"
items={[
{
key: '1',
label: <span><FileText size={16} /> 会议总结</span>,
children: (
<MeetingSummary
meeting={meeting}
summaryResult={summaryResult}
summaryHistory={summaryHistory}
isCreator={isCreator}
onOpenSummaryModal={openSummaryModal}
formatDateTime={formatDateTime}
/>
)
},
{
key: '2',
label: <span><Brain size={16} /> 会议脑图</span>,
children: (
<MindMap
meetingId={meeting_id}
meetingTitle={meeting.title}
meeting={meeting}
formatDateTime={formatDateTime}
/>
)
}
]}
/>
</section>
</div>
</div>