添加AI摘要
parent
879c208948
commit
82fd803e6d
|
|
@ -4,7 +4,7 @@
|
|||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React</title>
|
||||
<title>会议助手</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
"dependencies": {
|
||||
"@uiw/react-md-editor": "^4.0.8",
|
||||
"axios": "^1.6.2",
|
||||
"jspdf": "^3.0.2",
|
||||
"lucide-react": "^0.294.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,258 @@
|
|||
.datetime-picker {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.datetime-display {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 12px 16px;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 8px;
|
||||
background: white;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
min-height: 48px;
|
||||
}
|
||||
|
||||
.datetime-display:hover {
|
||||
border-color: #9ca3af;
|
||||
}
|
||||
|
||||
.datetime-display:focus-within,
|
||||
.datetime-display:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.display-text {
|
||||
flex: 1;
|
||||
color: #374151;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.display-text.placeholder {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #9ca3af;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.clear-btn:hover {
|
||||
background: #f3f4f6;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.datetime-picker-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
z-index: 10;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.datetime-picker-panel {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: white;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||
z-index: 20;
|
||||
margin-top: 4px;
|
||||
padding: 20px;
|
||||
min-width: 320px;
|
||||
max-height: 500px;
|
||||
height: auto;
|
||||
min-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.picker-section {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.picker-section:last-of-type {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.picker-section h4 {
|
||||
margin: 0 0 12px 0;
|
||||
color: #374151;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.quick-date-options,
|
||||
.quick-time-options {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 8px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.quick-time-options {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
.quick-option {
|
||||
background: #f8fafc;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.quick-option:hover {
|
||||
background: #f1f5f9;
|
||||
border-color: #cbd5e1;
|
||||
}
|
||||
|
||||
.quick-option.selected {
|
||||
background: #667eea;
|
||||
border-color: #667eea;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.custom-date-input,
|
||||
.custom-time-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.custom-time-input {
|
||||
background: #f8fafc;
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.date-input,
|
||||
.time-input {
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 6px;
|
||||
padding: 8px 12px;
|
||||
font-size: 14px;
|
||||
background: white;
|
||||
transition: all 0.2s ease;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.time-input {
|
||||
border: none;
|
||||
background: transparent;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.date-input:focus,
|
||||
.time-input:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.time-input:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.picker-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 8px 16px;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.action-btn.cancel {
|
||||
background: #f8fafc;
|
||||
color: #6b7280;
|
||||
border-color: #d1d5db;
|
||||
}
|
||||
|
||||
.action-btn.cancel:hover {
|
||||
background: #f1f5f9;
|
||||
border-color: #9ca3af;
|
||||
}
|
||||
|
||||
.action-btn.confirm {
|
||||
background: #667eea;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.action-btn.confirm:hover {
|
||||
background: #5a67d8;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.datetime-picker-panel {
|
||||
min-width: 280px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.quick-date-options {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.quick-time-options {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
.picker-actions {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* 改进输入框在Safari中的显示 */
|
||||
.date-input::-webkit-calendar-picker-indicator,
|
||||
.time-input::-webkit-calendar-picker-indicator {
|
||||
background: transparent;
|
||||
color: #6b7280;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.date-input::-webkit-calendar-picker-indicator:hover,
|
||||
.time-input::-webkit-calendar-picker-indicator:hover {
|
||||
background: #f3f4f6;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Calendar, Clock } from 'lucide-react';
|
||||
import './DateTimePicker.css';
|
||||
|
||||
const DateTimePicker = ({ value, onChange, placeholder = "选择会议时间" }) => {
|
||||
const [date, setDate] = useState('');
|
||||
const [time, setTime] = useState('');
|
||||
const [showQuickSelect, setShowQuickSelect] = useState(false);
|
||||
const [isInitialized, setIsInitialized] = useState(false);
|
||||
|
||||
// 组件卸载时清理状态
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
setShowQuickSelect(false);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 初始化时间值
|
||||
useEffect(() => {
|
||||
if (value && !isInitialized) {
|
||||
const dateObj = new Date(value);
|
||||
if (!isNaN(dateObj.getTime())) {
|
||||
// 转换为本地时间字符串
|
||||
const timeZoneOffset = dateObj.getTimezoneOffset() * 60000;
|
||||
const localDate = new Date(dateObj.getTime() - timeZoneOffset);
|
||||
const isoString = localDate.toISOString();
|
||||
|
||||
setDate(isoString.split('T')[0]);
|
||||
setTime(isoString.split('T')[1].slice(0, 5));
|
||||
}
|
||||
setIsInitialized(true);
|
||||
} else if (!value && !isInitialized) {
|
||||
setDate('');
|
||||
setTime('');
|
||||
setIsInitialized(true);
|
||||
}
|
||||
}, [value, isInitialized]);
|
||||
|
||||
// 当日期或时间改变时,更新父组件的值
|
||||
useEffect(() => {
|
||||
// 只在初始化完成后才触发onChange
|
||||
if (!isInitialized) return;
|
||||
|
||||
if (date && time) {
|
||||
const dateTimeString = `${date}T${time}`;
|
||||
onChange?.(dateTimeString);
|
||||
} else if (!date && !time) {
|
||||
onChange?.('');
|
||||
}
|
||||
}, [date, time, isInitialized]); // 移除onChange依赖
|
||||
|
||||
// 快速选择时间的选项
|
||||
const timeOptions = [
|
||||
{ label: '09:00', value: '09:00' },
|
||||
{ label: '10:00', value: '10:00' },
|
||||
{ label: '11:00', value: '11:00' },
|
||||
{ label: '14:00', value: '14:00' },
|
||||
{ label: '15:00', value: '15:00' },
|
||||
{ label: '16:00', value: '16:00' },
|
||||
{ label: '17:00', value: '17:00' },
|
||||
];
|
||||
|
||||
// 快速选择日期的选项
|
||||
const getQuickDateOptions = () => {
|
||||
const today = new Date();
|
||||
const options = [];
|
||||
|
||||
// 今天
|
||||
options.push({
|
||||
label: '今天',
|
||||
value: today.toISOString().split('T')[0]
|
||||
});
|
||||
|
||||
// 明天
|
||||
const tomorrow = new Date(today);
|
||||
tomorrow.setDate(today.getDate() + 1);
|
||||
options.push({
|
||||
label: '明天',
|
||||
value: tomorrow.toISOString().split('T')[0]
|
||||
});
|
||||
|
||||
// 后天
|
||||
const dayAfterTomorrow = new Date(today);
|
||||
dayAfterTomorrow.setDate(today.getDate() + 2);
|
||||
options.push({
|
||||
label: '后天',
|
||||
value: dayAfterTomorrow.toISOString().split('T')[0]
|
||||
});
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
const quickDateOptions = getQuickDateOptions();
|
||||
|
||||
const formatDisplayText = () => {
|
||||
if (!date && !time) return placeholder;
|
||||
|
||||
if (date && time) {
|
||||
const dateObj = new Date(`${date}T${time}`);
|
||||
return dateObj.toLocaleString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
}
|
||||
|
||||
if (date) {
|
||||
const dateObj = new Date(date);
|
||||
return dateObj.toLocaleDateString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
});
|
||||
}
|
||||
|
||||
return placeholder;
|
||||
};
|
||||
|
||||
const clearDateTime = () => {
|
||||
setDate('');
|
||||
setTime('');
|
||||
// 重置初始化状态,允许后续值的设定
|
||||
setIsInitialized(false);
|
||||
onChange?.('');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="datetime-picker">
|
||||
<div className="datetime-display" onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setShowQuickSelect(!showQuickSelect);
|
||||
}}>
|
||||
<Calendar size={18} />
|
||||
<span className={`display-text ${(!date && !time) ? 'placeholder' : ''}`}>
|
||||
{formatDisplayText()}
|
||||
</span>
|
||||
{(date || time) && (
|
||||
<button
|
||||
type="button"
|
||||
className="clear-btn"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
clearDateTime();
|
||||
}}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{showQuickSelect && (
|
||||
<div className="datetime-picker-panel">
|
||||
<div className="picker-section">
|
||||
<h4>选择日期</h4>
|
||||
<div className="quick-date-options">
|
||||
{quickDateOptions.map((option) => (
|
||||
<button
|
||||
key={option.value}
|
||||
type="button"
|
||||
className={`quick-option ${date === option.value ? 'selected' : ''}`}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setDate(option.value);
|
||||
}}
|
||||
>
|
||||
{option.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="custom-date-input">
|
||||
<input
|
||||
type="date"
|
||||
value={date}
|
||||
onChange={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setDate(e.target.value);
|
||||
}}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="date-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="picker-section">
|
||||
<h4>选择时间</h4>
|
||||
<div className="quick-time-options">
|
||||
{timeOptions.map((option) => (
|
||||
<button
|
||||
key={option.value}
|
||||
type="button"
|
||||
className={`quick-option ${time === option.value ? 'selected' : ''}`}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setTime(option.value);
|
||||
}}
|
||||
>
|
||||
{option.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="custom-time-input">
|
||||
<Clock size={16} />
|
||||
<input
|
||||
type="time"
|
||||
value={time}
|
||||
onChange={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setTime(e.target.value);
|
||||
}}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="time-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="picker-actions">
|
||||
<button
|
||||
type="button"
|
||||
className="action-btn cancel"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setShowQuickSelect(false);
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="action-btn confirm"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setShowQuickSelect(false);
|
||||
}}
|
||||
>
|
||||
确认
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showQuickSelect && (
|
||||
<div
|
||||
className="datetime-picker-overlay"
|
||||
onClick={() => setShowQuickSelect(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DateTimePicker;
|
||||
|
|
@ -34,7 +34,7 @@ const MeetingTimeline = ({ meetingsByDate, currentUser, onDeleteMeeting }) => {
|
|||
return date.toLocaleDateString('zh-CN', { month: 'long', day: 'numeric' });
|
||||
};
|
||||
|
||||
const truncateSummary = (summary, maxLines = 3, maxLength = 80) => {
|
||||
const truncateSummary = (summary, maxLines = 3, maxLength = 100) => {
|
||||
if (!summary) return '暂无摘要';
|
||||
|
||||
// Split by lines and check line count
|
||||
|
|
@ -59,7 +59,7 @@ const MeetingTimeline = ({ meetingsByDate, currentUser, onDeleteMeeting }) => {
|
|||
return summary;
|
||||
};
|
||||
|
||||
const shouldShowMoreButton = (summary, maxLines = 3, maxLength = 80) => {
|
||||
const shouldShowMoreButton = (summary, maxLines = 3, maxLength = 100) => {
|
||||
if (!summary) return false;
|
||||
const lines = summary.split('\n');
|
||||
return lines.length > maxLines || summary.length > maxLength;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Link, useNavigate } from 'react-router-dom';
|
|||
import axios from 'axios';
|
||||
import { ArrowLeft, Upload, Users, Calendar, FileText, X, User, Plus } from 'lucide-react';
|
||||
import { buildApiUrl, API_ENDPOINTS } from '../config/api';
|
||||
import DateTimePicker from '../components/DateTimePicker';
|
||||
import './CreateMeeting.css';
|
||||
|
||||
const CreateMeeting = ({ user }) => {
|
||||
|
|
@ -169,20 +170,14 @@ const CreateMeeting = ({ user }) => {
|
|||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="meeting_time">
|
||||
<label>
|
||||
<Calendar size={18} />
|
||||
会议时间
|
||||
</label>
|
||||
<input
|
||||
type="datetime-local"
|
||||
id="meeting_time"
|
||||
name="meeting_time"
|
||||
<DateTimePicker
|
||||
value={formData.meeting_time}
|
||||
onChange={handleInputChange}
|
||||
onBlur={(e) => {
|
||||
// Force input to lose focus to save the value
|
||||
e.target.blur();
|
||||
}}
|
||||
onChange={(value) => setFormData(prev => ({ ...prev, meeting_time: value }))}
|
||||
placeholder="选择会议时间(可选)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { ArrowLeft, Users, Calendar, FileText, X, User, Save, Upload, Plus, Imag
|
|||
import MDEditor, * as commands from '@uiw/react-md-editor';
|
||||
import '@uiw/react-md-editor/markdown-editor.css';
|
||||
import { buildApiUrl, API_ENDPOINTS, API_BASE_URL } from '../config/api';
|
||||
import DateTimePicker from '../components/DateTimePicker';
|
||||
import './EditMeeting.css';
|
||||
|
||||
const EditMeeting = ({ user }) => {
|
||||
|
|
@ -48,8 +49,7 @@ const EditMeeting = ({ user }) => {
|
|||
setMeeting(meetingData);
|
||||
setFormData({
|
||||
title: meetingData.title,
|
||||
meeting_time: meetingData.meeting_time ?
|
||||
new Date(meetingData.meeting_time).toISOString().slice(0, 16) : '',
|
||||
meeting_time: meetingData.meeting_time || '',
|
||||
summary: meetingData.summary || '',
|
||||
attendees: meetingData.attendees || []
|
||||
});
|
||||
|
|
@ -378,20 +378,14 @@ const EditMeeting = ({ user }) => {
|
|||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="meeting_time">
|
||||
<label>
|
||||
<Calendar size={18} />
|
||||
会议时间
|
||||
</label>
|
||||
<input
|
||||
type="datetime-local"
|
||||
id="meeting_time"
|
||||
name="meeting_time"
|
||||
<DateTimePicker
|
||||
value={formData.meeting_time}
|
||||
onChange={handleInputChange}
|
||||
onBlur={(e) => {
|
||||
// Force input to lose focus to save the value
|
||||
e.target.blur();
|
||||
}}
|
||||
onChange={(value) => setFormData(prev => ({ ...prev, meeting_time: value }))}
|
||||
placeholder="选择会议时间(可选)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,55 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.meeting-actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 1rem;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.summary-btn {
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.summary-btn:hover {
|
||||
background: linear-gradient(135deg, #5a67d8, #6b46c1);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.edit-btn {
|
||||
background: #f59e0b;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.edit-btn:hover {
|
||||
background: #d97706;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
background: #ef4444;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.delete-btn:hover {
|
||||
background: #dc2626;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.details-layout {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
|
|
@ -385,13 +434,171 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Meeting Summary Section */
|
||||
.summary-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.summary-header h2 {
|
||||
margin: 0;
|
||||
color: #334155;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.export-pdf-btn-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 16px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.export-pdf-btn-main svg {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.export-pdf-btn-main:hover {
|
||||
background: linear-gradient(135deg, #5a67d8, #6b46c1);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.summary-content {
|
||||
background: #fafbfc;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 12px;
|
||||
padding: 0;
|
||||
min-height: 200px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.markdown-content {
|
||||
padding: 2rem;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.markdown-content h1,
|
||||
.markdown-content h2,
|
||||
.markdown-content h3,
|
||||
.markdown-content h4,
|
||||
.markdown-content h5,
|
||||
.markdown-content h6 {
|
||||
color: #1e293b;
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.markdown-content h1 { font-size: 1.5rem; }
|
||||
.markdown-content h2 { font-size: 1.375rem; }
|
||||
.markdown-content h3 { font-size: 1.25rem; }
|
||||
.markdown-content h4 { font-size: 1.125rem; }
|
||||
|
||||
.markdown-content p {
|
||||
line-height: 1.6;
|
||||
color: #475569;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.markdown-content ul,
|
||||
.markdown-content ol {
|
||||
margin: 1rem 0;
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.markdown-content li {
|
||||
margin-bottom: 0.5rem;
|
||||
line-height: 1.5;
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.markdown-content strong {
|
||||
color: #1e293b;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown-content code {
|
||||
background: #f1f5f9;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-family: 'Monaco', 'Consolas', monospace;
|
||||
font-size: 0.875rem;
|
||||
color: #be185d;
|
||||
}
|
||||
|
||||
.no-summary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 200px;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.no-summary-content {
|
||||
text-align: center;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.no-summary-content svg {
|
||||
color: #cbd5e1;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.no-summary-content h3 {
|
||||
margin: 0 0 0.5rem 0;
|
||||
color: #475569;
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
.no-summary-content p {
|
||||
margin: 0 0 1.5rem 0;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.generate-summary-cta {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 20px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.generate-summary-cta:hover {
|
||||
background: linear-gradient(135deg, #5a67d8, #6b46c1);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
/* Transcript Sidebar */
|
||||
.transcript-sidebar {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
height: fit-content;
|
||||
max-height: calc(100vh - 200px);
|
||||
height: calc(100vh - 120px);
|
||||
min-height: 600px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
|
@ -410,13 +617,12 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.edit-speakers-btn {
|
||||
.edit-speakers-btn,
|
||||
.ai-summary-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 6px 12px;
|
||||
background: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
|
|
@ -424,10 +630,24 @@
|
|||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.edit-speakers-btn {
|
||||
background: #007bff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.edit-speakers-btn:hover {
|
||||
background: #0056b3;
|
||||
}
|
||||
|
||||
.ai-summary-btn {
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ai-summary-btn:hover {
|
||||
background: linear-gradient(135deg, #5a67d8, #6b46c1);
|
||||
}
|
||||
|
||||
.transcript-header h3 {
|
||||
margin: 0;
|
||||
color: #334155;
|
||||
|
|
@ -437,22 +657,6 @@
|
|||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.toggle-transcript {
|
||||
background: #f1f5f9;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
padding: 0.5rem 1rem;
|
||||
color: #475569;
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.toggle-transcript:hover {
|
||||
background: #e2e8f0;
|
||||
}
|
||||
|
||||
.transcript-content {
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
|
|
@ -464,13 +668,21 @@
|
|||
padding: 1rem;
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
border-left: 3px solid #667eea;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
border-left: 3px solid transparent;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.transcript-item.active {
|
||||
background: #eff6ff;
|
||||
border-left-color: #667eea;
|
||||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.15);
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
.transcript-item:hover {
|
||||
background-color: #f0f2ff;
|
||||
background: #f1f5f9;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.transcript-header-item {
|
||||
|
|
@ -495,9 +707,13 @@
|
|||
}
|
||||
|
||||
.speaker-name {
|
||||
font-weight: 600;
|
||||
color: #334155;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
font-size: 0.95rem;
|
||||
background: #f1f5f9;
|
||||
padding: 4px 10px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.timestamp {
|
||||
|
|
@ -849,6 +1065,216 @@
|
|||
border-color: #9ca3af;
|
||||
}
|
||||
|
||||
/* AI Summary Modal Styles */
|
||||
.summary-modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.summary-modal {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
width: 90%;
|
||||
max-width: 800px;
|
||||
max-height: 90vh;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.summary-modal-content {
|
||||
padding: 0 24px 24px;
|
||||
max-height: calc(90vh - 120px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.summary-input-section {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.summary-input-section h4 {
|
||||
margin: 0 0 1rem 0;
|
||||
color: #1e293b;
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
.input-description {
|
||||
color: #64748b;
|
||||
font-size: 0.875rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.user-prompt-input {
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-family: inherit;
|
||||
margin-bottom: 1rem;
|
||||
resize: vertical;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.user-prompt-input:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.generate-summary-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 20px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.generate-summary-btn:hover:not(:disabled) {
|
||||
background: linear-gradient(135deg, #5a67d8, #6b46c1);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.generate-summary-btn:disabled {
|
||||
opacity: 0.7;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.loading-spinner.small {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.summary-result-section,
|
||||
.summary-history-section {
|
||||
border-top: 1px solid #e2e8f0;
|
||||
padding-top: 2rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.summary-result-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.summary-result-section h4,
|
||||
.summary-history-section h4 {
|
||||
margin: 0;
|
||||
color: #1e293b;
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
.export-pdf-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
background: #059669;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 14px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 2px 4px rgba(5, 150, 105, 0.3);
|
||||
}
|
||||
|
||||
.export-pdf-btn svg {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.export-pdf-btn:hover {
|
||||
background: #047857;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 8px rgba(5, 150, 105, 0.4);
|
||||
}
|
||||
|
||||
.summary-result-content {
|
||||
background: #f8fafc;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.summary-history-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.summary-history-item {
|
||||
background: #f8fafc;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.summary-history-item:hover {
|
||||
background: #f1f5f9;
|
||||
border-color: #cbd5e1;
|
||||
}
|
||||
|
||||
.summary-history-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.summary-date {
|
||||
color: #64748b;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.user-prompt-tag {
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.user-prompt-display {
|
||||
background: white;
|
||||
border-left: 3px solid #667eea;
|
||||
padding: 8px 12px;
|
||||
margin-bottom: 0.5rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.summary-content-preview {
|
||||
color: #475569;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 1200px) {
|
||||
.details-layout {
|
||||
|
|
@ -939,3 +1365,144 @@
|
|||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* Transcript Edit Modal */
|
||||
.transcript-edit-modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.transcript-edit-modal {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
width: 90%;
|
||||
max-width: 800px;
|
||||
max-height: 90vh;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.transcript-edit-content {
|
||||
padding: 20px;
|
||||
max-height: calc(90vh - 120px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-description {
|
||||
margin-bottom: 20px;
|
||||
color: #64748b;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.transcript-edit-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.transcript-edit-item {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.transcript-edit-item.current {
|
||||
border-color: #3b82f6;
|
||||
background: #eff6ff;
|
||||
}
|
||||
|
||||
.transcript-edit-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.current-indicator {
|
||||
background: #3b82f6;
|
||||
color: white;
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.transcript-edit-textarea {
|
||||
width: 100%;
|
||||
min-height: 80px;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 6px;
|
||||
padding: 12px;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.transcript-edit-textarea:focus {
|
||||
outline: none;
|
||||
border-color: #3b82f6;
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
||||
}
|
||||
|
||||
/* Audio Divider and Subtitle Display */
|
||||
.audio-divider {
|
||||
margin: 20px 0;
|
||||
height: 1px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.subtitle-display {
|
||||
margin-top: 20px;
|
||||
min-height: 80px;
|
||||
padding: 15px;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.subtitle-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.subtitle-text {
|
||||
color: white;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.speaker-indicator {
|
||||
font-weight: 600;
|
||||
color: #fbbf24;
|
||||
font-size: 0.9rem;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
align-self: flex-start;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.subtitle-placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.placeholder-text {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
font-size: 0.9rem;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { useParams, Link, useNavigate } from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
import { ArrowLeft, Clock, Users, FileText, User, Calendar, Play, Pause, Volume2, MessageCircle, Edit, Trash2, Settings, Save, X } from 'lucide-react';
|
||||
import { ArrowLeft, Clock, Users, FileText, User, Calendar, Play, Pause, Volume2, MessageCircle, Edit, Trash2, Settings, Save, X, Edit3, Brain, Sparkles, Download } from 'lucide-react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import rehypeRaw from 'rehype-raw';
|
||||
|
|
@ -27,7 +27,19 @@ const MeetingDetails = ({ user }) => {
|
|||
const [showSpeakerEdit, setShowSpeakerEdit] = useState(false);
|
||||
const [editingSpeakers, setEditingSpeakers] = useState({});
|
||||
const [speakerList, setSpeakerList] = useState([]);
|
||||
const [showTranscriptEdit, setShowTranscriptEdit] = useState(false);
|
||||
const [editingTranscriptIndex, setEditingTranscriptIndex] = useState(-1);
|
||||
const [editingTranscripts, setEditingTranscripts] = useState({});
|
||||
const [currentSubtitle, setCurrentSubtitle] = useState('');
|
||||
const [currentSpeaker, setCurrentSpeaker] = useState('');
|
||||
const [showSummaryModal, setShowSummaryModal] = useState(false);
|
||||
const [summaryLoading, setSummaryLoading] = useState(false);
|
||||
const [summaryResult, setSummaryResult] = useState(null);
|
||||
const [userPrompt, setUserPrompt] = useState('');
|
||||
const [summaryHistory, setSummaryHistory] = useState([]);
|
||||
const [currentHighlightIndex, setCurrentHighlightIndex] = useState(-1);
|
||||
const audioRef = useRef(null);
|
||||
const transcriptRefs = useRef([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchMeetingDetails();
|
||||
|
|
@ -133,7 +145,40 @@ const MeetingDetails = ({ user }) => {
|
|||
|
||||
const handleTimeUpdate = () => {
|
||||
if (audioRef.current) {
|
||||
setCurrentTime(audioRef.current.currentTime);
|
||||
const currentTime = audioRef.current.currentTime;
|
||||
setCurrentTime(currentTime);
|
||||
|
||||
// 更新字幕显示
|
||||
updateSubtitle(currentTime);
|
||||
}
|
||||
};
|
||||
|
||||
const updateSubtitle = (currentTime) => {
|
||||
const currentTimeMs = currentTime * 1000;
|
||||
const currentSegment = transcript.find(item =>
|
||||
currentTimeMs >= item.start_time_ms && currentTimeMs <= item.end_time_ms
|
||||
);
|
||||
|
||||
if (currentSegment) {
|
||||
setCurrentSubtitle(currentSegment.text_content);
|
||||
// 确保使用 speaker_tag 来保持一致性
|
||||
setCurrentSpeaker(currentSegment.speaker_tag || `发言人 ${currentSegment.speaker_id}`);
|
||||
|
||||
// 找到当前segment在transcript数组中的索引
|
||||
const currentIndex = transcript.findIndex(item => item.segment_id === currentSegment.segment_id);
|
||||
setCurrentHighlightIndex(currentIndex);
|
||||
|
||||
// 滚动到对应的转录条目
|
||||
if (currentIndex !== -1 && transcriptRefs.current[currentIndex]) {
|
||||
transcriptRefs.current[currentIndex].scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'center'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setCurrentSubtitle('');
|
||||
setCurrentSpeaker('');
|
||||
setCurrentHighlightIndex(-1);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -271,6 +316,247 @@ const MeetingDetails = ({ user }) => {
|
|||
setShowSpeakerEdit(true);
|
||||
};
|
||||
|
||||
const handleTranscriptEdit = (index) => {
|
||||
setEditingTranscriptIndex(index);
|
||||
|
||||
// 获取前一条、当前条、后一条的数据
|
||||
const editItems = [];
|
||||
if (index > 0) editItems.push({ ...transcript[index - 1], originalIndex: index - 1 });
|
||||
editItems.push({ ...transcript[index], originalIndex: index });
|
||||
if (index < transcript.length - 1) editItems.push({ ...transcript[index + 1], originalIndex: index + 1 });
|
||||
|
||||
// 初始化编辑状态
|
||||
const initialEditState = {};
|
||||
editItems.forEach(item => {
|
||||
initialEditState[item.originalIndex] = item.text_content;
|
||||
});
|
||||
setEditingTranscripts(initialEditState);
|
||||
setShowTranscriptEdit(true);
|
||||
};
|
||||
|
||||
const handleTranscriptTextChange = (index, newText) => {
|
||||
setEditingTranscripts(prev => ({
|
||||
...prev,
|
||||
[index]: newText
|
||||
}));
|
||||
};
|
||||
|
||||
const handleSaveTranscriptEdits = async () => {
|
||||
try {
|
||||
const baseUrl = "";
|
||||
const updates = Object.entries(editingTranscripts).map(([index, text_content]) => ({
|
||||
segment_id: transcript[index].segment_id,
|
||||
text_content: text_content
|
||||
}));
|
||||
|
||||
await axios.put(`${baseUrl}/api/meetings/${meeting_id}/transcript/batch`, {
|
||||
updates: updates
|
||||
});
|
||||
|
||||
// 更新本地状态
|
||||
setTranscript(prev => prev.map((item, idx) => {
|
||||
const newText = editingTranscripts[idx];
|
||||
return newText !== undefined ? { ...item, text_content: newText } : item;
|
||||
}));
|
||||
|
||||
setShowTranscriptEdit(false);
|
||||
setEditingTranscripts({});
|
||||
setEditingTranscriptIndex(-1);
|
||||
|
||||
} catch (err) {
|
||||
console.error('Error updating transcript:', err);
|
||||
setError('更新转录内容失败,请重试');
|
||||
}
|
||||
};
|
||||
|
||||
const getEditingItems = () => {
|
||||
if (editingTranscriptIndex === -1) return [];
|
||||
|
||||
const items = [];
|
||||
const index = editingTranscriptIndex;
|
||||
|
||||
if (index > 0) items.push({ ...transcript[index - 1], originalIndex: index - 1, position: 'prev' });
|
||||
items.push({ ...transcript[index], originalIndex: index, position: 'current' });
|
||||
if (index < transcript.length - 1) items.push({ ...transcript[index + 1], originalIndex: index + 1, position: 'next' });
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
// AI总结相关函数
|
||||
const generateSummary = async () => {
|
||||
if (summaryLoading) return;
|
||||
|
||||
setSummaryLoading(true);
|
||||
try {
|
||||
const baseUrl = "";
|
||||
const response = await axios.post(`${baseUrl}/api/meetings/${meeting_id}/generate-summary`, {
|
||||
user_prompt: userPrompt
|
||||
});
|
||||
|
||||
setSummaryResult(response.data);
|
||||
|
||||
// 刷新总结历史
|
||||
await fetchSummaryHistory();
|
||||
|
||||
} catch (err) {
|
||||
console.error('Error generating summary:', err);
|
||||
setError('生成AI总结失败,请重试');
|
||||
} finally {
|
||||
setSummaryLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchSummaryHistory = async () => {
|
||||
try {
|
||||
const baseUrl = "";
|
||||
const response = await axios.get(`${baseUrl}/api/meetings/${meeting_id}/summaries`);
|
||||
setSummaryHistory(response.data.summaries);
|
||||
} catch (err) {
|
||||
console.error('Error fetching summary history:', err);
|
||||
}
|
||||
};
|
||||
|
||||
const openSummaryModal = async () => {
|
||||
setShowSummaryModal(true);
|
||||
setUserPrompt('');
|
||||
setSummaryResult(null);
|
||||
await fetchSummaryHistory();
|
||||
};
|
||||
|
||||
const exportToPDF = async () => {
|
||||
try {
|
||||
// 检查是否有总结内容
|
||||
let summaryContent = summaryResult?.content ||
|
||||
meeting?.summary ||
|
||||
(summaryHistory.length > 0 ? summaryHistory[0].content : null);
|
||||
|
||||
if (!summaryContent) {
|
||||
alert('暂无会议总结内容,请先生成AI总结。');
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建一个临时的React容器用于渲染Markdown
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.style.position = 'fixed';
|
||||
tempDiv.style.top = '-9999px';
|
||||
tempDiv.style.width = '800px';
|
||||
tempDiv.style.padding = '20px';
|
||||
tempDiv.style.backgroundColor = 'white';
|
||||
|
||||
// 导入markdown-to-html转换所需的模块
|
||||
const ReactMarkdown = (await import('react-markdown')).default;
|
||||
const { createRoot } = await import('react-dom/client');
|
||||
|
||||
document.body.appendChild(tempDiv);
|
||||
const root = createRoot(tempDiv);
|
||||
|
||||
// 渲染Markdown内容并获取HTML
|
||||
await new Promise((resolve) => {
|
||||
root.render(
|
||||
React.createElement(ReactMarkdown, {
|
||||
remarkPlugins: [remarkGfm],
|
||||
rehypePlugins: [rehypeRaw, rehypeSanitize],
|
||||
children: summaryContent
|
||||
})
|
||||
);
|
||||
setTimeout(resolve, 100); // 等待渲染完成
|
||||
});
|
||||
|
||||
const renderedHTML = tempDiv.innerHTML;
|
||||
|
||||
// 创建一个隐藏的HTML容器用于生成PDF
|
||||
const printContainer = document.createElement('div');
|
||||
printContainer.style.position = 'fixed';
|
||||
printContainer.style.top = '-9999px';
|
||||
printContainer.style.width = '210mm';
|
||||
printContainer.style.padding = '20mm';
|
||||
printContainer.style.backgroundColor = 'white';
|
||||
printContainer.style.fontFamily = 'Arial, sans-serif';
|
||||
printContainer.style.fontSize = '14px';
|
||||
printContainer.style.lineHeight = '1.6';
|
||||
printContainer.style.color = '#333';
|
||||
|
||||
// 创建PDF内容的HTML,使用渲染后的Markdown内容
|
||||
const meetingTime = formatDateTime(meeting.meeting_time);
|
||||
const attendeesList = meeting.attendees.map(attendee =>
|
||||
typeof attendee === 'string' ? attendee : attendee.caption
|
||||
).join('、');
|
||||
|
||||
printContainer.innerHTML = `
|
||||
<div>
|
||||
<h1 style="color: #2563eb; margin-bottom: 30px; font-size: 24px; border-bottom: 2px solid #e5e7eb; padding-bottom: 10px;">
|
||||
${meeting.title || '会议总结'}
|
||||
</h1>
|
||||
|
||||
<div style="margin-bottom: 30px; background: #f9fafb; padding: 20px; border-radius: 8px;">
|
||||
<h2 style="color: #374151; font-size: 16px; margin-bottom: 15px;">会议信息</h2>
|
||||
<p style="margin: 8px 0;"><strong>会议时间:</strong>${meetingTime}</p>
|
||||
<p style="margin: 8px 0;"><strong>创建人:</strong>${meeting.creator_username}</p>
|
||||
<p style="margin: 8px 0;"><strong>参会人数:</strong>${meeting.attendees.length}人</p>
|
||||
<p style="margin: 8px 0;"><strong>参会人员:</strong>${attendeesList}</p>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 30px;">
|
||||
<h2 style="color: #374151; font-size: 16px; margin-bottom: 15px;">会议摘要</h2>
|
||||
<div style="line-height: 1.8;">${renderedHTML}</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 50px; padding-top: 20px; border-top: 1px solid #e5e7eb; font-size: 12px; color: #6b7280;">
|
||||
<p>导出时间:${new Date().toLocaleString('zh-CN')}</p>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(printContainer);
|
||||
|
||||
// 使用浏览器的打印功能生成PDF
|
||||
const originalContent = document.body.innerHTML;
|
||||
const originalTitle = document.title;
|
||||
|
||||
// 临时替换页面内容
|
||||
document.body.innerHTML = printContainer.innerHTML;
|
||||
document.title = `${meeting.title || '会议总结'}_${new Date().toISOString().split('T')[0]}`;
|
||||
|
||||
// 添加打印样式
|
||||
const printStyles = document.createElement('style');
|
||||
printStyles.innerHTML = `
|
||||
@media print {
|
||||
body { margin: 0; padding: 20px; font-family: 'Microsoft YaHei', Arial, sans-serif; }
|
||||
h1 { page-break-before: avoid; }
|
||||
h2 { page-break-before: avoid; }
|
||||
h3 { margin-top: 1.5rem; margin-bottom: 0.75rem; color: #1e293b; }
|
||||
h4 { margin-top: 1rem; margin-bottom: 0.5rem; color: #1e293b; }
|
||||
p { margin-bottom: 0.75rem; color: #475569; line-height: 1.6; }
|
||||
ul, ol { margin: 0.75rem 0; padding-left: 1.5rem; }
|
||||
li { margin-bottom: 0.25rem; color: #475569; }
|
||||
strong { color: #1e293b; font-weight: 600; }
|
||||
code { background: #f1f5f9; padding: 2px 4px; border-radius: 3px; color: #dc2626; }
|
||||
.page-break { page-break-before: always; }
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(printStyles);
|
||||
|
||||
// 打开打印对话框
|
||||
window.print();
|
||||
|
||||
// 清理:恢复原始内容
|
||||
setTimeout(() => {
|
||||
document.body.innerHTML = originalContent;
|
||||
document.title = originalTitle;
|
||||
document.head.removeChild(printStyles);
|
||||
document.body.removeChild(printContainer);
|
||||
document.body.removeChild(tempDiv);
|
||||
|
||||
// 重新初始化React组件(这是一个简化的处理)
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
|
||||
} catch (error) {
|
||||
console.error('PDF导出失败:', error);
|
||||
alert('PDF导出失败,请重试。建议使用浏览器的打印功能并选择"保存为PDF"。');
|
||||
}
|
||||
};
|
||||
|
||||
const isCreator = meeting && user && String(meeting.creator_id) === String(user.user_id);
|
||||
|
||||
if (loading) {
|
||||
|
|
@ -409,6 +695,27 @@ const MeetingDetails = ({ user }) => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 分割线 */}
|
||||
<div className="audio-divider"></div>
|
||||
|
||||
{/* 动态字幕显示 */}
|
||||
<div className="subtitle-display">
|
||||
{currentSubtitle ? (
|
||||
<div className="subtitle-content">
|
||||
<div className="speaker-indicator">
|
||||
{currentSpeaker}
|
||||
</div>
|
||||
<div className="subtitle-text">
|
||||
{currentSubtitle}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="subtitle-placeholder">
|
||||
<div className="placeholder-text">播放音频时将在此处显示实时字幕</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="no-audio">
|
||||
|
|
@ -422,16 +729,47 @@ const MeetingDetails = ({ user }) => {
|
|||
</section>
|
||||
|
||||
<section className="card-section">
|
||||
<h2><FileText size={20} /> 会议摘要</h2>
|
||||
<div className="summary-content">
|
||||
<div className="markdown-content">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
rehypePlugins={[rehypeRaw, rehypeSanitize]}
|
||||
<div className="summary-header">
|
||||
<h2><FileText size={20} /> 会议摘要</h2>
|
||||
{meeting?.summary && (
|
||||
<button
|
||||
className="export-pdf-btn-main"
|
||||
onClick={exportToPDF}
|
||||
title="导出PDF"
|
||||
>
|
||||
{meeting.summary || '暂无摘要信息。'}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
<Download size={16} />
|
||||
<span>导出PDF</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="summary-content">
|
||||
{meeting?.summary ? (
|
||||
<div className="markdown-content">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
rehypePlugins={[rehypeRaw, rehypeSanitize]}
|
||||
>
|
||||
{meeting.summary}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
) : (
|
||||
<div className="no-summary">
|
||||
<div className="no-summary-content">
|
||||
<FileText size={48} />
|
||||
<h3>暂无会议总结</h3>
|
||||
<p>该会议尚未生成总结内容</p>
|
||||
{isCreator && (
|
||||
<button
|
||||
className="generate-summary-cta"
|
||||
onClick={openSummaryModal}
|
||||
>
|
||||
<Brain size={16} />
|
||||
<span>生成AI总结</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
|
@ -443,30 +781,34 @@ const MeetingDetails = ({ user }) => {
|
|||
<h3><MessageCircle size={20} /> 对话转录</h3>
|
||||
<div className="transcript-controls">
|
||||
{isCreator && (
|
||||
<button
|
||||
className="edit-speakers-btn"
|
||||
onClick={handleSpeakerEditOpen}
|
||||
title="编辑发言人标签"
|
||||
>
|
||||
<Settings size={16} />
|
||||
<span>编辑标签</span>
|
||||
</button>
|
||||
<>
|
||||
<button
|
||||
className="edit-speakers-btn"
|
||||
onClick={handleSpeakerEditOpen}
|
||||
title="编辑发言人标签"
|
||||
>
|
||||
<Settings size={16} />
|
||||
<span>编辑标签</span>
|
||||
</button>
|
||||
<button
|
||||
className="ai-summary-btn"
|
||||
onClick={openSummaryModal}
|
||||
title="AI总结"
|
||||
>
|
||||
<Brain size={16} />
|
||||
<span>AI总结</span>
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
<button
|
||||
className="toggle-transcript"
|
||||
onClick={() => setShowTranscript(!showTranscript)}
|
||||
>
|
||||
{showTranscript ? '隐藏' : '显示'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{showTranscript && (
|
||||
<div className="transcript-content">
|
||||
{transcript.map((item) => (
|
||||
<div className="transcript-content">
|
||||
{transcript.map((item, index) => (
|
||||
<div
|
||||
key={item.segment_id}
|
||||
className="transcript-item"
|
||||
ref={(el) => transcriptRefs.current[index] = el}
|
||||
className={`transcript-item ${currentHighlightIndex === index ? 'active' : ''}`}
|
||||
>
|
||||
<div className="transcript-header-item">
|
||||
<span
|
||||
|
|
@ -484,6 +826,15 @@ const MeetingDetails = ({ user }) => {
|
|||
>
|
||||
{formatTime(item.start_time_ms / 1000)}
|
||||
</span>
|
||||
{isCreator && (
|
||||
<button
|
||||
className="edit-transcript-btn"
|
||||
onClick={() => handleTranscriptEdit(index)}
|
||||
title="编辑转录内容"
|
||||
>
|
||||
<Edit3 size={14} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -496,7 +847,6 @@ const MeetingDetails = ({ user }) => {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -587,6 +937,166 @@ const MeetingDetails = ({ user }) => {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Transcript Edit Modal */}
|
||||
{showTranscriptEdit && (
|
||||
<div className="transcript-edit-modal-overlay" onClick={() => setShowTranscriptEdit(false)}>
|
||||
<div className="transcript-edit-modal" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="modal-header">
|
||||
<h3>编辑转录内容</h3>
|
||||
<button
|
||||
className="close-btn"
|
||||
onClick={() => setShowTranscriptEdit(false)}
|
||||
>
|
||||
<X size={20} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="transcript-edit-content">
|
||||
<p className="modal-description">修改选中转录条目及其上下文内容:</p>
|
||||
|
||||
<div className="transcript-edit-list">
|
||||
{getEditingItems().map((item) => (
|
||||
<div key={item.originalIndex} className={`transcript-edit-item ${item.position}`}>
|
||||
<div className="transcript-edit-header">
|
||||
<span className="speaker-name">{item.speaker_tag}</span>
|
||||
<span className="timestamp">{formatTime(item.start_time_ms / 1000)}</span>
|
||||
{item.position === 'current' && (
|
||||
<span className="current-indicator">当前编辑</span>
|
||||
)}
|
||||
</div>
|
||||
<textarea
|
||||
value={editingTranscripts[item.originalIndex] || item.text_content}
|
||||
onChange={(e) => handleTranscriptTextChange(item.originalIndex, e.target.value)}
|
||||
className="transcript-edit-textarea"
|
||||
rows={3}
|
||||
placeholder="输入转录内容..."
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="modal-actions">
|
||||
<button
|
||||
className="btn-cancel"
|
||||
onClick={() => setShowTranscriptEdit(false)}
|
||||
>
|
||||
取消
|
||||
</button>
|
||||
<button
|
||||
className="btn-save"
|
||||
onClick={handleSaveTranscriptEdits}
|
||||
>
|
||||
<Save size={16} />
|
||||
保存修改
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* AI Summary Modal */}
|
||||
{showSummaryModal && (
|
||||
<div className="summary-modal-overlay" onClick={() => setShowSummaryModal(false)}>
|
||||
<div className="summary-modal" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="modal-header">
|
||||
<h3><Brain size={20} /> AI会议总结</h3>
|
||||
<button
|
||||
className="close-btn"
|
||||
onClick={() => setShowSummaryModal(false)}
|
||||
>
|
||||
<X size={20} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="summary-modal-content">
|
||||
<div className="summary-input-section">
|
||||
<h4>生成新的总结</h4>
|
||||
<p className="input-description">
|
||||
系统将使用通用提示词分析会议转录,您可以添加额外要求:
|
||||
</p>
|
||||
<textarea
|
||||
value={userPrompt}
|
||||
onChange={(e) => setUserPrompt(e.target.value)}
|
||||
className="user-prompt-input"
|
||||
placeholder="请输入您希望AI重点关注的内容,如:请重点分析决策事项和待办任务..."
|
||||
rows={3}
|
||||
/>
|
||||
<button
|
||||
className="generate-summary-btn"
|
||||
onClick={generateSummary}
|
||||
disabled={summaryLoading}
|
||||
>
|
||||
{summaryLoading ? (
|
||||
<>
|
||||
<div className="loading-spinner small"></div>
|
||||
<span>正在生成总结...</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Sparkles size={16} />
|
||||
<span>生成AI总结</span>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{summaryResult && (
|
||||
<div className="summary-result-section">
|
||||
<div className="summary-result-header">
|
||||
<h4>最新生成的总结</h4>
|
||||
<button
|
||||
className="export-pdf-btn"
|
||||
onClick={exportToPDF}
|
||||
title="导出PDF"
|
||||
>
|
||||
<Download size={14} />
|
||||
<span>导出PDF</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="summary-result-content">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
rehypePlugins={[rehypeRaw, rehypeSanitize]}
|
||||
>
|
||||
{summaryResult.content}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{summaryHistory.length > 0 && (
|
||||
<div className="summary-history-section">
|
||||
<h4>历史总结记录</h4>
|
||||
<div className="summary-history-list">
|
||||
{summaryHistory.map((summary, index) => (
|
||||
<div key={summary.id} className="summary-history-item">
|
||||
<div className="summary-history-header">
|
||||
<span className="summary-date">
|
||||
{new Date(summary.created_at).toLocaleString('zh-CN')}
|
||||
</span>
|
||||
{summary.user_prompt && (
|
||||
<span className="user-prompt-tag">自定义要求</span>
|
||||
)}
|
||||
</div>
|
||||
{summary.user_prompt && (
|
||||
<div className="user-prompt-display">
|
||||
<strong>用户要求:</strong>{summary.user_prompt}
|
||||
</div>
|
||||
)}
|
||||
<div className="summary-content-preview">
|
||||
{summary.content.substring(0, 200)}...
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ export default defineConfig({
|
|||
server: {
|
||||
host: true, // Optional: Allows the server to be accessible externally
|
||||
port: 5173, // Optional: Specify a port if needed
|
||||
allowedHosts: ['c0e02ee.r9.cpolar.top'], // Add the problematic hostname here
|
||||
allowedHosts: ['6fc3f0b0.r3.cpolar.cn'], // Add the problematic hostname here
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:8000', // 后端服务地址
|
||||
|
|
|
|||
397
yarn.lock
397
yarn.lock
|
|
@ -138,6 +138,11 @@
|
|||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.27.1"
|
||||
|
||||
"@babel/runtime@^7.12.5", "@babel/runtime@^7.26.9":
|
||||
version "7.28.3"
|
||||
resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.3.tgz#75c5034b55ba868121668be5d5bb31cc64e6e61a"
|
||||
integrity sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==
|
||||
|
||||
"@babel/runtime@^7.14.6", "@babel/runtime@^7.17.2":
|
||||
version "7.28.2"
|
||||
resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.2.tgz"
|
||||
|
|
@ -173,11 +178,136 @@
|
|||
"@babel/helper-string-parser" "^7.27.1"
|
||||
"@babel/helper-validator-identifier" "^7.27.1"
|
||||
|
||||
"@esbuild/aix-ppc64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz#a1414903bb38027382f85f03dda6065056757727"
|
||||
integrity sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==
|
||||
|
||||
"@esbuild/android-arm64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz#c859994089e9767224269884061f89dae6fb51c6"
|
||||
integrity sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==
|
||||
|
||||
"@esbuild/android-arm@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.8.tgz#96a8f2ca91c6cd29ea90b1af79d83761c8ba0059"
|
||||
integrity sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==
|
||||
|
||||
"@esbuild/android-x64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.8.tgz#a3a626c4fec4a024a9fa8c7679c39996e92916f0"
|
||||
integrity sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==
|
||||
|
||||
"@esbuild/darwin-arm64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz"
|
||||
integrity sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==
|
||||
|
||||
"@esbuild/darwin-x64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz#5271b0df2bb12ce8df886704bfdd1c7cc01385d2"
|
||||
integrity sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz#d0a0e7fdf19733b8bb1566b81df1aa0bb7e46ada"
|
||||
integrity sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==
|
||||
|
||||
"@esbuild/freebsd-x64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz#2de8b2e0899d08f1cb1ef3128e159616e7e85343"
|
||||
integrity sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==
|
||||
|
||||
"@esbuild/linux-arm64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz#a4209efadc0c2975716458484a4e90c237c48ae9"
|
||||
integrity sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==
|
||||
|
||||
"@esbuild/linux-arm@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz#ccd9e291c24cd8d9142d819d463e2e7200d25b19"
|
||||
integrity sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==
|
||||
|
||||
"@esbuild/linux-ia32@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz#006ad1536d0c2b28fb3a1cf0b53bcb85aaf92c4d"
|
||||
integrity sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==
|
||||
|
||||
"@esbuild/linux-loong64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz#127b3fbfb2c2e08b1397e985932f718f09a8f5c4"
|
||||
integrity sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==
|
||||
|
||||
"@esbuild/linux-mips64el@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz#837d1449517791e3fa7d82675a2d06d9f56cb340"
|
||||
integrity sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==
|
||||
|
||||
"@esbuild/linux-ppc64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz#aa2e3bd93ab8df084212f1895ca4b03c42d9e0fe"
|
||||
integrity sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==
|
||||
|
||||
"@esbuild/linux-riscv64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz#a340620e31093fef72767dd28ab04214b3442083"
|
||||
integrity sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==
|
||||
|
||||
"@esbuild/linux-s390x@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz#ddfed266c8c13f5efb3105a0cd47f6dcd0e79e71"
|
||||
integrity sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==
|
||||
|
||||
"@esbuild/linux-x64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz#9a4f78c75c051e8c060183ebb39a269ba936a2ac"
|
||||
integrity sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==
|
||||
|
||||
"@esbuild/netbsd-arm64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz#902c80e1d678047926387230bc037e63e00697d0"
|
||||
integrity sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==
|
||||
|
||||
"@esbuild/netbsd-x64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz#2d9eb4692add2681ff05a14ce99de54fbed7079c"
|
||||
integrity sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==
|
||||
|
||||
"@esbuild/openbsd-arm64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz#89c3b998c6de739db38ab7fb71a8a76b3fa84a45"
|
||||
integrity sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==
|
||||
|
||||
"@esbuild/openbsd-x64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz#2f01615cf472b0e48c077045cfd96b5c149365cc"
|
||||
integrity sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==
|
||||
|
||||
"@esbuild/openharmony-arm64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz#a201f720cd2c3ebf9a6033fcc3feb069a54b509a"
|
||||
integrity sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==
|
||||
|
||||
"@esbuild/sunos-x64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz#07046c977985a3334667f19e6ab3a01a80862afb"
|
||||
integrity sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==
|
||||
|
||||
"@esbuild/win32-arm64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz#4a5470caf0d16127c05d4833d4934213c69392d1"
|
||||
integrity sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==
|
||||
|
||||
"@esbuild/win32-ia32@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz#3de3e8470b7b328d99dbc3e9ec1eace207e5bbc4"
|
||||
integrity sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==
|
||||
|
||||
"@esbuild/win32-x64@0.25.8":
|
||||
version "0.25.8"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz#610d7ea539d2fcdbe39237b5cc175eb2c4451f9c"
|
||||
integrity sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.2.0":
|
||||
version "4.7.0"
|
||||
resolved "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz"
|
||||
|
|
@ -226,7 +356,7 @@
|
|||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/js@^9.30.1", "@eslint/js@9.32.0":
|
||||
"@eslint/js@9.32.0", "@eslint/js@^9.30.1":
|
||||
version "9.32.0"
|
||||
resolved "https://registry.npmmirror.com/@eslint/js/-/js-9.32.0.tgz"
|
||||
integrity sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==
|
||||
|
|
@ -303,11 +433,106 @@
|
|||
resolved "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz"
|
||||
integrity sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==
|
||||
|
||||
"@rollup/rollup-android-arm-eabi@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.1.tgz#c659481d5b15054d4636b3dd0c2f50ab3083d839"
|
||||
integrity sha512-oENme6QxtLCqjChRUUo3S6X8hjCXnWmJWnedD7VbGML5GUtaOtAyx+fEEXnBXVf0CBZApMQU0Idwi0FmyxzQhw==
|
||||
|
||||
"@rollup/rollup-android-arm64@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.1.tgz#7e05c3c0bf6a79ee6b40ab5e778679742f06815d"
|
||||
integrity sha512-OikvNT3qYTl9+4qQ9Bpn6+XHM+ogtFadRLuT2EXiFQMiNkXFLQfNVppi5o28wvYdHL2s3fM0D/MZJ8UkNFZWsw==
|
||||
|
||||
"@rollup/rollup-darwin-arm64@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.1.tgz"
|
||||
integrity sha512-EFYNNGij2WllnzljQDQnlFTXzSJw87cpAs4TVBAWLdkvic5Uh5tISrIL6NRcxoh/b2EFBG/TK8hgRrGx94zD4A==
|
||||
|
||||
"@rollup/rollup-darwin-x64@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.1.tgz#a4df7fa06ac318b66a6aa66d6f1e0a58fef58cd3"
|
||||
integrity sha512-ZaNH06O1KeTug9WI2+GRBE5Ujt9kZw4a1+OIwnBHal92I8PxSsl5KpsrPvthRynkhMck4XPdvY0z26Cym/b7oA==
|
||||
|
||||
"@rollup/rollup-freebsd-arm64@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.1.tgz#6634478a78a0c17dcf55adb621fa66faa58a017b"
|
||||
integrity sha512-n4SLVebZP8uUlJ2r04+g2U/xFeiQlw09Me5UFqny8HGbARl503LNH5CqFTb5U5jNxTouhRjai6qPT0CR5c/Iig==
|
||||
|
||||
"@rollup/rollup-freebsd-x64@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.1.tgz#db42c46c0263b2562e2ba5c2e00e318646f2b24c"
|
||||
integrity sha512-8vu9c02F16heTqpvo3yeiu7Vi1REDEC/yES/dIfq3tSXe6mLndiwvYr3AAvd1tMNUqE9yeGYa5w7PRbI5QUV+w==
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.1.tgz#88ca443ad42c70555978b000c6d1dd925fb3203b"
|
||||
integrity sha512-K4ncpWl7sQuyp6rWiGUvb6Q18ba8mzM0rjWJ5JgYKlIXAau1db7hZnR0ldJvqKWWJDxqzSLwGUhA4jp+KqgDtQ==
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.1.tgz#36106fe103d32c2a97583ebadcfb28dc63988bda"
|
||||
integrity sha512-YykPnXsjUjmXE6j6k2QBBGAn1YsJUix7pYaPLK3RVE0bQL2jfdbfykPxfF8AgBlqtYbfEnYHmLXNa6QETjdOjQ==
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.1.tgz#00c28bc9210dcfbb5e7fa8e52fd827fb570afe26"
|
||||
integrity sha512-kKvqBGbZ8i9pCGW3a1FH3HNIVg49dXXTsChGFsHGXQaVJPLA4f/O+XmTxfklhccxdF5FefUn2hvkoGJH0ScWOA==
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.1.tgz#45a13486b5523235eb87b349e7ca5a0bb85a5b0e"
|
||||
integrity sha512-zzX5nTw1N1plmqC9RGC9vZHFuiM7ZP7oSWQGqpbmfjK7p947D518cVK1/MQudsBdcD84t6k70WNczJOct6+hdg==
|
||||
|
||||
"@rollup/rollup-linux-loongarch64-gnu@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.1.tgz#b8edd99f072cd652acbbddc1c539b1ac4254381d"
|
||||
integrity sha512-O8CwgSBo6ewPpktFfSDgB6SJN9XDcPSvuwxfejiddbIC/hn9Tg6Ai0f0eYDf3XvB/+PIWzOQL+7+TZoB8p9Yuw==
|
||||
|
||||
"@rollup/rollup-linux-ppc64-gnu@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.1.tgz#0ec72a4f8b7a86b13c0f6b7666ed1d3b6e8e67cc"
|
||||
integrity sha512-JnCfFVEKeq6G3h3z8e60kAp8Rd7QVnWCtPm7cxx+5OtP80g/3nmPtfdCXbVl063e3KsRnGSKDHUQMydmzc/wBA==
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.1.tgz#99f06928528fb58addd12e50827e1a0269c1cca8"
|
||||
integrity sha512-dVxuDqS237eQXkbYzQQfdf/njgeNw6LZuVyEdUaWwRpKHhsLI+y4H/NJV8xJGU19vnOJCVwaBFgr936FHOnJsQ==
|
||||
|
||||
"@rollup/rollup-linux-riscv64-musl@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.1.tgz#3c14aba63b4170fe3d9d0b6ad98361366170590e"
|
||||
integrity sha512-CvvgNl2hrZrTR9jXK1ye0Go0HQRT6ohQdDfWR47/KFKiLd5oN5T14jRdUVGF4tnsN8y9oSfMOqH6RuHh+ck8+w==
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.1.tgz#34c647a823dcdca0f749a2bdcbde4fb131f37a4c"
|
||||
integrity sha512-x7ANt2VOg2565oGHJ6rIuuAon+A8sfe1IeUx25IKqi49OjSr/K3awoNqr9gCwGEJo9OuXlOn+H2p1VJKx1psxA==
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.1.tgz#3991010418c005e8791c415e7c2072b247157710"
|
||||
integrity sha512-9OADZYryz/7E8/qt0vnaHQgmia2Y0wrjSSn1V/uL+zw/i7NUhxbX4cHXdEQ7dnJgzYDS81d8+tf6nbIdRFZQoQ==
|
||||
|
||||
"@rollup/rollup-linux-x64-musl@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.1.tgz#f3943e5f284f40ffbcf4a14da9ee2e43d303b462"
|
||||
integrity sha512-NuvSCbXEKY+NGWHyivzbjSVJi68Xfq1VnIvGmsuXs6TCtveeoDRKutI5vf2ntmNnVq64Q4zInet0UDQ+yMB6tA==
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.1.tgz#45b5a1d3f0af63f85044913c371d7b0519c913ad"
|
||||
integrity sha512-mWz+6FSRb82xuUMMV1X3NGiaPFqbLN9aIueHleTZCc46cJvwTlvIh7reQLk4p97dv0nddyewBhwzryBHH7wtPw==
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.1.tgz#900ef7211d2929e9809f3a044c4e2fd3aa685a0c"
|
||||
integrity sha512-7Thzy9TMXDw9AU4f4vsLNBxh7/VOKuXi73VH3d/kHGr0tZ3x/ewgL9uC7ojUKmH1/zvmZe2tLapYcZllk3SO8Q==
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc@4.46.1":
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.1.tgz#932d8696dfef673bee1a1e291a5531d25a6903be"
|
||||
integrity sha512-7GVB4luhFmGUNXXJhH2jJwZCFB3pIOixv2E3s17GQHBFUOQaISlt7aGcQgqvCaDSxTZJUzlK/QJ1FN8S94MrzQ==
|
||||
|
||||
"@types/babel__core@^7.20.5":
|
||||
version "7.20.5"
|
||||
resolved "https://registry.npmmirror.com/@types/babel__core/-/babel__core-7.20.5.tgz"
|
||||
|
|
@ -355,7 +580,7 @@
|
|||
dependencies:
|
||||
"@types/estree" "*"
|
||||
|
||||
"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.6", "@types/estree@1.0.8":
|
||||
"@types/estree@*", "@types/estree@1.0.8", "@types/estree@^1.0.0", "@types/estree@^1.0.6":
|
||||
version "1.0.8"
|
||||
resolved "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz"
|
||||
integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==
|
||||
|
|
@ -391,11 +616,21 @@
|
|||
resolved "https://registry.npmmirror.com/@types/ms/-/ms-2.1.0.tgz"
|
||||
integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==
|
||||
|
||||
"@types/pako@^2.0.3":
|
||||
version "2.0.4"
|
||||
resolved "https://registry.npmmirror.com/@types/pako/-/pako-2.0.4.tgz#c3575ef8125e176c345fa0e7b301c1db41170c15"
|
||||
integrity sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==
|
||||
|
||||
"@types/prismjs@^1.0.0":
|
||||
version "1.26.5"
|
||||
resolved "https://registry.npmmirror.com/@types/prismjs/-/prismjs-1.26.5.tgz"
|
||||
integrity sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==
|
||||
|
||||
"@types/raf@^3.4.0":
|
||||
version "3.4.3"
|
||||
resolved "https://registry.npmmirror.com/@types/raf/-/raf-3.4.3.tgz#85f1d1d17569b28b8db45e16e996407a56b0ab04"
|
||||
integrity sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==
|
||||
|
||||
"@types/react-dom@^19.1.6":
|
||||
version "19.1.6"
|
||||
resolved "https://registry.npmmirror.com/@types/react-dom/-/react-dom-19.1.6.tgz"
|
||||
|
|
@ -408,17 +643,17 @@
|
|||
dependencies:
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/trusted-types@^2.0.7":
|
||||
version "2.0.7"
|
||||
resolved "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
|
||||
integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==
|
||||
|
||||
"@types/unist@*", "@types/unist@^3.0.0":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz"
|
||||
integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==
|
||||
|
||||
"@types/unist@^2":
|
||||
version "2.0.11"
|
||||
resolved "https://registry.npmmirror.com/@types/unist/-/unist-2.0.11.tgz"
|
||||
integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==
|
||||
|
||||
"@types/unist@^2.0.0":
|
||||
"@types/unist@^2", "@types/unist@^2.0.0":
|
||||
version "2.0.11"
|
||||
resolved "https://registry.npmmirror.com/@types/unist/-/unist-2.0.11.tgz"
|
||||
integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==
|
||||
|
|
@ -530,6 +765,11 @@ balanced-match@^1.0.0:
|
|||
resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
|
||||
base64-arraybuffer@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc"
|
||||
integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==
|
||||
|
||||
bcp-47-match@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.npmmirror.com/bcp-47-match/-/bcp-47-match-2.0.3.tgz"
|
||||
|
|
@ -576,6 +816,20 @@ caniuse-lite@^1.0.30001726:
|
|||
resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz"
|
||||
integrity sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==
|
||||
|
||||
canvg@^3.0.11:
|
||||
version "3.0.11"
|
||||
resolved "https://registry.npmmirror.com/canvg/-/canvg-3.0.11.tgz#4b4290a6c7fa36871fac2b14e432eff33b33cf2b"
|
||||
integrity sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@types/raf" "^3.4.0"
|
||||
core-js "^3.8.3"
|
||||
raf "^3.4.1"
|
||||
regenerator-runtime "^0.13.7"
|
||||
rgbcolor "^1.0.1"
|
||||
stackblur-canvas "^2.0.0"
|
||||
svg-pathdata "^6.0.3"
|
||||
|
||||
ccount@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmmirror.com/ccount/-/ccount-2.0.1.tgz"
|
||||
|
|
@ -648,6 +902,11 @@ cookie@^1.0.1:
|
|||
resolved "https://registry.npmmirror.com/cookie/-/cookie-1.0.2.tgz"
|
||||
integrity sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==
|
||||
|
||||
core-js@^3.6.0, core-js@^3.8.3:
|
||||
version "3.45.1"
|
||||
resolved "https://registry.npmmirror.com/core-js/-/core-js-3.45.1.tgz#5810e04a1b4e9bc5ddaa4dd12e702ff67300634d"
|
||||
integrity sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==
|
||||
|
||||
cross-spawn@^7.0.6:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz"
|
||||
|
|
@ -657,6 +916,13 @@ cross-spawn@^7.0.6:
|
|||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
css-line-break@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmmirror.com/css-line-break/-/css-line-break-2.1.0.tgz#bfef660dfa6f5397ea54116bb3cb4873edbc4fa0"
|
||||
integrity sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==
|
||||
dependencies:
|
||||
utrie "^1.0.2"
|
||||
|
||||
css-selector-parser@^3.0.0:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.npmmirror.com/css-selector-parser/-/css-selector-parser-3.1.3.tgz"
|
||||
|
|
@ -708,6 +974,13 @@ direction@^2.0.0:
|
|||
resolved "https://registry.npmmirror.com/direction/-/direction-2.0.1.tgz"
|
||||
integrity sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==
|
||||
|
||||
dompurify@^3.2.4:
|
||||
version "3.2.6"
|
||||
resolved "https://registry.npmmirror.com/dompurify/-/dompurify-3.2.6.tgz#ca040a6ad2b88e2a92dc45f38c79f84a714a1cad"
|
||||
integrity sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==
|
||||
optionalDependencies:
|
||||
"@types/trusted-types" "^2.0.7"
|
||||
|
||||
dunder-proto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz"
|
||||
|
|
@ -928,11 +1201,25 @@ fast-levenshtein@^2.0.6:
|
|||
resolved "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz"
|
||||
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
|
||||
|
||||
fast-png@^6.2.0:
|
||||
version "6.4.0"
|
||||
resolved "https://registry.npmmirror.com/fast-png/-/fast-png-6.4.0.tgz#807fc353ccab060d09151b7d082786e02d8e92d6"
|
||||
integrity sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==
|
||||
dependencies:
|
||||
"@types/pako" "^2.0.3"
|
||||
iobuffer "^5.3.2"
|
||||
pako "^2.1.0"
|
||||
|
||||
fdir@^6.4.4, fdir@^6.4.6:
|
||||
version "6.4.6"
|
||||
resolved "https://registry.npmmirror.com/fdir/-/fdir-6.4.6.tgz"
|
||||
integrity sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==
|
||||
|
||||
fflate@^0.8.1:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.npmmirror.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea"
|
||||
integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==
|
||||
|
||||
file-entry-cache@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz"
|
||||
|
|
@ -1274,6 +1561,14 @@ html-void-elements@^3.0.0:
|
|||
resolved "https://registry.npmmirror.com/html-void-elements/-/html-void-elements-3.0.0.tgz"
|
||||
integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==
|
||||
|
||||
html2canvas@^1.0.0-rc.5:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.npmmirror.com/html2canvas/-/html2canvas-1.4.1.tgz#7cef1888311b5011d507794a066041b14669a543"
|
||||
integrity sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==
|
||||
dependencies:
|
||||
css-line-break "^2.1.0"
|
||||
text-segmentation "^1.0.3"
|
||||
|
||||
ignore@^5.2.0:
|
||||
version "5.3.2"
|
||||
resolved "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz"
|
||||
|
|
@ -1297,6 +1592,11 @@ inline-style-parser@0.2.4:
|
|||
resolved "https://registry.npmmirror.com/inline-style-parser/-/inline-style-parser-0.2.4.tgz"
|
||||
integrity sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==
|
||||
|
||||
iobuffer@^5.3.2:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.npmmirror.com/iobuffer/-/iobuffer-5.4.0.tgz#f85dff957fd0579257472f0a4cfe5ed3430e63e1"
|
||||
integrity sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==
|
||||
|
||||
is-alphabetical@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmmirror.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz"
|
||||
|
|
@ -1379,6 +1679,20 @@ json5@^2.2.3:
|
|||
resolved "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz"
|
||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||
|
||||
jspdf@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npmmirror.com/jspdf/-/jspdf-3.0.2.tgz#f1e0e7f0954327bea4b8b02008613ad51e6024f6"
|
||||
integrity sha512-G0fQDJ5fAm6UW78HG6lNXyq09l0PrA1rpNY5i+ly17Zb1fMMFSmS+3lw4cnrAPGyouv2Y0ylujbY2Ieq3DSlKA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.26.9"
|
||||
fast-png "^6.2.0"
|
||||
fflate "^0.8.1"
|
||||
optionalDependencies:
|
||||
canvg "^3.0.11"
|
||||
core-js "^3.6.0"
|
||||
dompurify "^3.2.4"
|
||||
html2canvas "^1.0.0-rc.5"
|
||||
|
||||
keyv@^4.5.4:
|
||||
version "4.5.4"
|
||||
resolved "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz"
|
||||
|
|
@ -1958,6 +2272,11 @@ p-locate@^5.0.0:
|
|||
dependencies:
|
||||
p-limit "^3.0.2"
|
||||
|
||||
pako@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmmirror.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86"
|
||||
integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==
|
||||
|
||||
parent-module@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz"
|
||||
|
|
@ -2000,6 +2319,11 @@ path-key@^3.1.0:
|
|||
resolved "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz"
|
||||
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
||||
|
||||
performance-now@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==
|
||||
|
||||
picocolors@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz"
|
||||
|
|
@ -2044,6 +2368,13 @@ punycode@^2.1.0:
|
|||
resolved "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz"
|
||||
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
|
||||
|
||||
raf@^3.4.1:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.npmmirror.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
|
||||
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
|
||||
dependencies:
|
||||
performance-now "^2.1.0"
|
||||
|
||||
react-dom@^19.1.0:
|
||||
version "19.1.1"
|
||||
resolved "https://registry.npmmirror.com/react-dom/-/react-dom-19.1.1.tgz"
|
||||
|
|
@ -2119,6 +2450,11 @@ refractor@^4.8.0:
|
|||
hastscript "^7.0.0"
|
||||
parse-entities "^4.0.0"
|
||||
|
||||
regenerator-runtime@^0.13.7:
|
||||
version "0.13.11"
|
||||
resolved "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
|
||||
integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
|
||||
|
||||
rehype-attr@~3.0.1:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.npmmirror.com/rehype-attr/-/rehype-attr-3.0.3.tgz"
|
||||
|
|
@ -2157,10 +2493,10 @@ rehype-parse@^9.0.0:
|
|||
hast-util-from-html "^2.0.0"
|
||||
unified "^11.0.0"
|
||||
|
||||
rehype-prism-plus@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmmirror.com/rehype-prism-plus/-/rehype-prism-plus-2.0.1.tgz"
|
||||
integrity sha512-Wglct0OW12tksTUseAPyWPo3srjBOY7xKlql/DPKi7HbsdZTyaLCAoO58QBKSczFQxElTsQlOY3JDOFzB/K++Q==
|
||||
rehype-prism-plus@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmmirror.com/rehype-prism-plus/-/rehype-prism-plus-2.0.0.tgz"
|
||||
integrity sha512-FeM/9V2N7EvDZVdR2dqhAzlw5YI49m9Tgn7ZrYJeYHIahM6gcXpH0K1y2gNnKanZCydOMluJvX2cB9z3lhY8XQ==
|
||||
dependencies:
|
||||
hast-util-to-string "^3.0.0"
|
||||
parse-numeric-range "^1.3.0"
|
||||
|
|
@ -2169,10 +2505,10 @@ rehype-prism-plus@~2.0.0:
|
|||
unist-util-filter "^5.0.0"
|
||||
unist-util-visit "^5.0.0"
|
||||
|
||||
rehype-prism-plus@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmmirror.com/rehype-prism-plus/-/rehype-prism-plus-2.0.0.tgz"
|
||||
integrity sha512-FeM/9V2N7EvDZVdR2dqhAzlw5YI49m9Tgn7ZrYJeYHIahM6gcXpH0K1y2gNnKanZCydOMluJvX2cB9z3lhY8XQ==
|
||||
rehype-prism-plus@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmmirror.com/rehype-prism-plus/-/rehype-prism-plus-2.0.1.tgz"
|
||||
integrity sha512-Wglct0OW12tksTUseAPyWPo3srjBOY7xKlql/DPKi7HbsdZTyaLCAoO58QBKSczFQxElTsQlOY3JDOFzB/K++Q==
|
||||
dependencies:
|
||||
hast-util-to-string "^3.0.0"
|
||||
parse-numeric-range "^1.3.0"
|
||||
|
|
@ -2291,6 +2627,11 @@ resolve-from@^4.0.0:
|
|||
resolved "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz"
|
||||
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
||||
|
||||
rgbcolor@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmmirror.com/rgbcolor/-/rgbcolor-1.0.1.tgz#d6505ecdb304a6595da26fa4b43307306775945d"
|
||||
integrity sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==
|
||||
|
||||
rollup@^4.40.0:
|
||||
version "4.46.1"
|
||||
resolved "https://registry.npmmirror.com/rollup/-/rollup-4.46.1.tgz"
|
||||
|
|
@ -2357,6 +2698,11 @@ space-separated-tokens@^2.0.0:
|
|||
resolved "https://registry.npmmirror.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz"
|
||||
integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==
|
||||
|
||||
stackblur-canvas@^2.0.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.npmmirror.com/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz#af931277d0b5096df55e1f91c530043e066989b6"
|
||||
integrity sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==
|
||||
|
||||
stringify-entities@^4.0.0:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.npmmirror.com/stringify-entities/-/stringify-entities-4.0.4.tgz"
|
||||
|
|
@ -2391,6 +2737,18 @@ supports-color@^7.1.0:
|
|||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
svg-pathdata@^6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.npmmirror.com/svg-pathdata/-/svg-pathdata-6.0.3.tgz#80b0e0283b652ccbafb69ad4f8f73e8d3fbf2cac"
|
||||
integrity sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==
|
||||
|
||||
text-segmentation@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmmirror.com/text-segmentation/-/text-segmentation-1.0.3.tgz#52a388159efffe746b24a63ba311b6ac9f2d7943"
|
||||
integrity sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==
|
||||
dependencies:
|
||||
utrie "^1.0.2"
|
||||
|
||||
tinyglobby@^0.2.14:
|
||||
version "0.2.14"
|
||||
resolved "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.14.tgz"
|
||||
|
|
@ -2491,6 +2849,13 @@ uri-js@^4.2.2:
|
|||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
utrie@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmmirror.com/utrie/-/utrie-1.0.2.tgz#d42fe44de9bc0119c25de7f564a6ed1b2c87a645"
|
||||
integrity sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==
|
||||
dependencies:
|
||||
base64-arraybuffer "^1.0.2"
|
||||
|
||||
vfile-location@^5.0.0:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.npmmirror.com/vfile-location/-/vfile-location-5.0.3.tgz"
|
||||
|
|
|
|||
Loading…
Reference in New Issue