mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 07:16:51 +00:00
feat(export): add batch export section titles with info popovers
This commit is contained in:
@@ -20,6 +20,73 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.export-section-title-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-section-title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-info-tooltip {
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-info-trigger {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&.active {
|
||||||
|
border-color: rgba(var(--primary-rgb), 0.45);
|
||||||
|
color: var(--primary);
|
||||||
|
background: rgba(var(--primary-rgb), 0.08);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-info-popover {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 8px);
|
||||||
|
right: 0;
|
||||||
|
width: min(340px, calc(100vw - 40px));
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
background: var(--bg-primary);
|
||||||
|
box-shadow: 0 14px 30px rgba(0, 0, 0, 0.2);
|
||||||
|
padding: 10px 12px;
|
||||||
|
z-index: 70;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 6px 0 0;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.55;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.global-export-controls {
|
.global-export-controls {
|
||||||
background: var(--card-bg);
|
background: var(--card-bg);
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
@@ -2232,6 +2299,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 720px) {
|
||||||
|
.export-section-title {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
.table-wrap {
|
.table-wrap {
|
||||||
--contacts-message-col-width: 104px;
|
--contacts-message-col-width: 104px;
|
||||||
--contacts-action-col-width: 236px;
|
--contacts-action-col-width: 236px;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
Calendar,
|
Calendar,
|
||||||
Check,
|
Check,
|
||||||
CheckSquare,
|
CheckSquare,
|
||||||
|
CircleHelp,
|
||||||
Copy,
|
Copy,
|
||||||
Database,
|
Database,
|
||||||
Download,
|
Download,
|
||||||
@@ -801,6 +802,63 @@ const WriteLayoutSelector = memo(function WriteLayoutSelector({
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const SectionInfoTooltip = memo(function SectionInfoTooltip({
|
||||||
|
label,
|
||||||
|
heading,
|
||||||
|
messages
|
||||||
|
}: {
|
||||||
|
label: string
|
||||||
|
heading: string
|
||||||
|
messages: string[]
|
||||||
|
}) {
|
||||||
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
|
const containerRef = useRef<HTMLDivElement | null>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isOpen) return
|
||||||
|
|
||||||
|
const handleOutsideClick = (event: MouseEvent) => {
|
||||||
|
if (containerRef.current?.contains(event.target as Node)) return
|
||||||
|
setIsOpen(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
setIsOpen(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('mousedown', handleOutsideClick)
|
||||||
|
document.addEventListener('keydown', handleKeyDown)
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('mousedown', handleOutsideClick)
|
||||||
|
document.removeEventListener('keydown', handleKeyDown)
|
||||||
|
}
|
||||||
|
}, [isOpen])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="section-info-tooltip" ref={containerRef}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`section-info-trigger ${isOpen ? 'active' : ''}`}
|
||||||
|
onClick={() => setIsOpen(prev => !prev)}
|
||||||
|
aria-label={`查看${label}说明`}
|
||||||
|
aria-expanded={isOpen}
|
||||||
|
>
|
||||||
|
<CircleHelp size={14} />
|
||||||
|
</button>
|
||||||
|
{isOpen && (
|
||||||
|
<div className="section-info-popover" role="dialog" aria-label={`${label}说明`}>
|
||||||
|
<h4>{heading}</h4>
|
||||||
|
{messages.map(message => (
|
||||||
|
<p key={message}>{message}</p>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
interface TaskCenterModalProps {
|
interface TaskCenterModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
tasks: ExportTask[]
|
tasks: ExportTask[]
|
||||||
@@ -3700,6 +3758,17 @@ function ExportPage() {
|
|||||||
onTogglePerfTask={toggleTaskPerfDetail}
|
onTogglePerfTask={toggleTaskPerfDetail}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div className="export-section-title-row">
|
||||||
|
<h3 className="export-section-title">按类型批量导出</h3>
|
||||||
|
<SectionInfoTooltip
|
||||||
|
label="按类型批量导出"
|
||||||
|
heading="按类型批量导出说明"
|
||||||
|
messages={[
|
||||||
|
'按数据类型统一导出,适合横向汇总同类内容,比如集中导出图片、语音或视频。',
|
||||||
|
'发起前可先设置导出时间范围和格式,能减少无关数据,导出结果更聚焦。'
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="content-card-grid">
|
<div className="content-card-grid">
|
||||||
{contentCards.map(card => {
|
{contentCards.map(card => {
|
||||||
const Icon = card.icon
|
const Icon = card.icon
|
||||||
@@ -3758,6 +3827,17 @@ function ExportPage() {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="export-section-title-row">
|
||||||
|
<h3 className="export-section-title">按会话批量导出</h3>
|
||||||
|
<SectionInfoTooltip
|
||||||
|
label="按会话批量导出"
|
||||||
|
heading="按会话批量导出说明"
|
||||||
|
messages={[
|
||||||
|
'按会话维度导出完整上下文,适合按客户、项目或群组进行归档。',
|
||||||
|
'你可以先在列表中筛选目标会话,再批量导出,结果会保留每个会话的结构与时间线。'
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="session-table-section">
|
<div className="session-table-section">
|
||||||
<div className="table-toolbar">
|
<div className="table-toolbar">
|
||||||
<div className="table-tabs" role="tablist" aria-label="会话类型">
|
<div className="table-tabs" role="tablist" aria-label="会话类型">
|
||||||
|
|||||||
Reference in New Issue
Block a user