mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 15:25:50 +00:00
fix:优化了设置中下拉菜单的视觉表现
This commit is contained in:
@@ -221,6 +221,100 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.select-field {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-trigger {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 16px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 9999px;
|
||||||
|
font-size: 14px;
|
||||||
|
background: var(--bg-primary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--text-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
border-color: var(--primary);
|
||||||
|
box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 15%, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-value {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
text-align: left;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-dropdown {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 6px);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: color-mix(in srgb, var(--bg-primary) 85%, var(--bg-secondary));
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 6px;
|
||||||
|
box-shadow: var(--shadow-md);
|
||||||
|
z-index: 20;
|
||||||
|
max-height: 320px;
|
||||||
|
overflow-y: auto;
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
-webkit-backdrop-filter: blur(14px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-option {
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s;
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--bg-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: color-mix(in srgb, var(--primary) 12%, transparent);
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-label {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-desc {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-option.active .option-desc {
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
.input-with-toggle {
|
.input-with-toggle {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1096,13 +1190,15 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
background: var(--bg-secondary);
|
background: color-mix(in srgb, var(--bg-primary) 85%, var(--bg-secondary));
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
-webkit-backdrop-filter: blur(14px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wxid-option {
|
.wxid-option {
|
||||||
|
|||||||
@@ -41,6 +41,12 @@ function SettingsPage() {
|
|||||||
const [wxidOptions, setWxidOptions] = useState<WxidOption[]>([])
|
const [wxidOptions, setWxidOptions] = useState<WxidOption[]>([])
|
||||||
const [showWxidSelect, setShowWxidSelect] = useState(false)
|
const [showWxidSelect, setShowWxidSelect] = useState(false)
|
||||||
const wxidDropdownRef = useRef<HTMLDivElement>(null)
|
const wxidDropdownRef = useRef<HTMLDivElement>(null)
|
||||||
|
const [showExportFormatSelect, setShowExportFormatSelect] = useState(false)
|
||||||
|
const [showExportDateRangeSelect, setShowExportDateRangeSelect] = useState(false)
|
||||||
|
const [showExportExcelColumnsSelect, setShowExportExcelColumnsSelect] = useState(false)
|
||||||
|
const exportFormatDropdownRef = useRef<HTMLDivElement>(null)
|
||||||
|
const exportDateRangeDropdownRef = useRef<HTMLDivElement>(null)
|
||||||
|
const exportExcelColumnsDropdownRef = useRef<HTMLDivElement>(null)
|
||||||
const [cachePath, setCachePath] = useState('')
|
const [cachePath, setCachePath] = useState('')
|
||||||
const [logEnabled, setLogEnabled] = useState(false)
|
const [logEnabled, setLogEnabled] = useState(false)
|
||||||
const [whisperModelName, setWhisperModelName] = useState('base')
|
const [whisperModelName, setWhisperModelName] = useState('base')
|
||||||
@@ -85,13 +91,23 @@ function SettingsPage() {
|
|||||||
// 点击外部关闭下拉框
|
// 点击外部关闭下拉框
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (e: MouseEvent) => {
|
const handleClickOutside = (e: MouseEvent) => {
|
||||||
if (showWxidSelect && wxidDropdownRef.current && !wxidDropdownRef.current.contains(e.target as Node)) {
|
const target = e.target as Node
|
||||||
|
if (showWxidSelect && wxidDropdownRef.current && !wxidDropdownRef.current.contains(target)) {
|
||||||
setShowWxidSelect(false)
|
setShowWxidSelect(false)
|
||||||
}
|
}
|
||||||
|
if (showExportFormatSelect && exportFormatDropdownRef.current && !exportFormatDropdownRef.current.contains(target)) {
|
||||||
|
setShowExportFormatSelect(false)
|
||||||
|
}
|
||||||
|
if (showExportDateRangeSelect && exportDateRangeDropdownRef.current && !exportDateRangeDropdownRef.current.contains(target)) {
|
||||||
|
setShowExportDateRangeSelect(false)
|
||||||
|
}
|
||||||
|
if (showExportExcelColumnsSelect && exportExcelColumnsDropdownRef.current && !exportExcelColumnsDropdownRef.current.contains(target)) {
|
||||||
|
setShowExportExcelColumnsSelect(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener('mousedown', handleClickOutside)
|
document.addEventListener('mousedown', handleClickOutside)
|
||||||
return () => document.removeEventListener('mousedown', handleClickOutside)
|
return () => document.removeEventListener('mousedown', handleClickOutside)
|
||||||
}, [showWxidSelect])
|
}, [showWxidSelect, showExportFormatSelect, showExportDateRangeSelect, showExportExcelColumnsSelect])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const removeDb = window.electronAPI.key.onDbKeyStatus((payload) => {
|
const removeDb = window.electronAPI.key.onDbKeyStatus((payload) => {
|
||||||
@@ -863,48 +879,114 @@ function SettingsPage() {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
const renderExportTab = () => (
|
const exportFormatOptions = [
|
||||||
|
{ value: 'excel', label: 'Excel', desc: '电子表格,适合统计分析' },
|
||||||
|
{ value: 'chatlab', label: 'ChatLab', desc: '标准格式,支持其他软件导入' },
|
||||||
|
{ value: 'chatlab-jsonl', label: 'ChatLab JSONL', desc: '流式格式,适合大量消息' },
|
||||||
|
{ value: 'json', label: 'JSON', desc: '详细格式,包含完整消息信息' },
|
||||||
|
{ value: 'html', label: 'HTML', desc: '网页格式,可直接浏览' },
|
||||||
|
{ value: 'txt', label: 'TXT', desc: '纯文本,通用格式' },
|
||||||
|
{ value: 'sql', label: 'PostgreSQL', desc: '数据库脚本,便于导入到数据库' }
|
||||||
|
]
|
||||||
|
const exportDateRangeOptions = [
|
||||||
|
{ value: 'today', label: '今天' },
|
||||||
|
{ value: '7d', label: '最近7天' },
|
||||||
|
{ value: '30d', label: '最近30天' },
|
||||||
|
{ value: '90d', label: '最近90天' },
|
||||||
|
{ value: 'all', label: '全部时间' }
|
||||||
|
]
|
||||||
|
const exportExcelColumnOptions = [
|
||||||
|
{ value: 'compact', label: '精简列', desc: '序号、时间、发送者身份、消息类型、内容' },
|
||||||
|
{ value: 'full', label: '完整列', desc: '含发送者昵称/微信ID/备注' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const getOptionLabel = (options: { value: string; label: string }[], value: string) => {
|
||||||
|
return options.find((option) => option.value === value)?.label ?? value
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderExportTab = () => {
|
||||||
|
const exportExcelColumnsValue = exportDefaultExcelCompactColumns ? 'compact' : 'full'
|
||||||
|
const exportFormatLabel = getOptionLabel(exportFormatOptions, exportDefaultFormat)
|
||||||
|
const exportDateRangeLabel = getOptionLabel(exportDateRangeOptions, exportDefaultDateRange)
|
||||||
|
const exportExcelColumnsLabel = getOptionLabel(exportExcelColumnOptions, exportExcelColumnsValue)
|
||||||
|
|
||||||
|
return (
|
||||||
<div className="tab-content">
|
<div className="tab-content">
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label>默认导出格式</label>
|
<label>默认导出格式</label>
|
||||||
<span className="form-hint">导出页面默认选中的格式</span>
|
<span className="form-hint">导出页面默认选中的格式</span>
|
||||||
<select
|
<div className="select-field" ref={exportFormatDropdownRef}>
|
||||||
value={exportDefaultFormat}
|
<button
|
||||||
onChange={async (e) => {
|
type="button"
|
||||||
const value = e.target.value
|
className={`select-trigger ${showExportFormatSelect ? 'open' : ''}`}
|
||||||
setExportDefaultFormat(value)
|
onClick={() => {
|
||||||
await configService.setExportDefaultFormat(value)
|
setShowExportFormatSelect(!showExportFormatSelect)
|
||||||
showMessage('已更新导出格式默认值', true)
|
setShowExportDateRangeSelect(false)
|
||||||
}}
|
setShowExportExcelColumnsSelect(false)
|
||||||
>
|
}}
|
||||||
<option value="excel">Excel</option>
|
>
|
||||||
<option value="chatlab">ChatLab</option>
|
<span className="select-value">{exportFormatLabel}</span>
|
||||||
<option value="chatlab-jsonl">ChatLab JSONL</option>
|
<ChevronDown size={16} />
|
||||||
<option value="json">JSON</option>
|
</button>
|
||||||
<option value="html">HTML</option>
|
{showExportFormatSelect && (
|
||||||
<option value="txt">TXT</option>
|
<div className="select-dropdown">
|
||||||
<option value="sql">PostgreSQL</option>
|
{exportFormatOptions.map((option) => (
|
||||||
</select>
|
<button
|
||||||
|
key={option.value}
|
||||||
|
type="button"
|
||||||
|
className={`select-option ${exportDefaultFormat === option.value ? 'active' : ''}`}
|
||||||
|
onClick={async () => {
|
||||||
|
setExportDefaultFormat(option.value)
|
||||||
|
await configService.setExportDefaultFormat(option.value)
|
||||||
|
showMessage('已更新导出格式默认值', true)
|
||||||
|
setShowExportFormatSelect(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="option-label">{option.label}</span>
|
||||||
|
{option.desc && <span className="option-desc">{option.desc}</span>}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label>默认导出时间范围</label>
|
<label>默认导出时间范围</label>
|
||||||
<span className="form-hint">控制导出页面的默认时间选择</span>
|
<span className="form-hint">控制导出页面的默认时间选择</span>
|
||||||
<select
|
<div className="select-field" ref={exportDateRangeDropdownRef}>
|
||||||
value={exportDefaultDateRange}
|
<button
|
||||||
onChange={async (e) => {
|
type="button"
|
||||||
const value = e.target.value
|
className={`select-trigger ${showExportDateRangeSelect ? 'open' : ''}`}
|
||||||
setExportDefaultDateRange(value)
|
onClick={() => {
|
||||||
await configService.setExportDefaultDateRange(value)
|
setShowExportDateRangeSelect(!showExportDateRangeSelect)
|
||||||
showMessage('已更新默认导出时间范围', true)
|
setShowExportFormatSelect(false)
|
||||||
}}
|
setShowExportExcelColumnsSelect(false)
|
||||||
>
|
}}
|
||||||
<option value="today">今天</option>
|
>
|
||||||
<option value="7d">最近7天</option>
|
<span className="select-value">{exportDateRangeLabel}</span>
|
||||||
<option value="30d">最近30天</option>
|
<ChevronDown size={16} />
|
||||||
<option value="90d">最近90天</option>
|
</button>
|
||||||
<option value="all">全部时间</option>
|
{showExportDateRangeSelect && (
|
||||||
</select>
|
<div className="select-dropdown">
|
||||||
|
{exportDateRangeOptions.map((option) => (
|
||||||
|
<button
|
||||||
|
key={option.value}
|
||||||
|
type="button"
|
||||||
|
className={`select-option ${exportDefaultDateRange === option.value ? 'active' : ''}`}
|
||||||
|
onClick={async () => {
|
||||||
|
setExportDefaultDateRange(option.value)
|
||||||
|
await configService.setExportDefaultDateRange(option.value)
|
||||||
|
showMessage('已更新默认导出时间范围', true)
|
||||||
|
setShowExportDateRangeSelect(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="option-label">{option.label}</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
@@ -956,21 +1038,45 @@ function SettingsPage() {
|
|||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label>Excel 列显示</label>
|
<label>Excel 列显示</label>
|
||||||
<span className="form-hint">控制 Excel 导出的列字段</span>
|
<span className="form-hint">控制 Excel 导出的列字段</span>
|
||||||
<select
|
<div className="select-field" ref={exportExcelColumnsDropdownRef}>
|
||||||
value={exportDefaultExcelCompactColumns ? 'compact' : 'full'}
|
<button
|
||||||
onChange={async (e) => {
|
type="button"
|
||||||
const compact = e.target.value === 'compact'
|
className={`select-trigger ${showExportExcelColumnsSelect ? 'open' : ''}`}
|
||||||
setExportDefaultExcelCompactColumns(compact)
|
onClick={() => {
|
||||||
await configService.setExportDefaultExcelCompactColumns(compact)
|
setShowExportExcelColumnsSelect(!showExportExcelColumnsSelect)
|
||||||
showMessage(compact ? '已启用精简列' : '已启用完整列', true)
|
setShowExportFormatSelect(false)
|
||||||
}}
|
setShowExportDateRangeSelect(false)
|
||||||
>
|
}}
|
||||||
<option value="compact">精简列(序号、时间、发送者身份、消息类型、内容)</option>
|
>
|
||||||
<option value="full">完整列(含发送者昵称/微信ID/备注)</option>
|
<span className="select-value">{exportExcelColumnsLabel}</span>
|
||||||
</select>
|
<ChevronDown size={16} />
|
||||||
|
</button>
|
||||||
|
{showExportExcelColumnsSelect && (
|
||||||
|
<div className="select-dropdown">
|
||||||
|
{exportExcelColumnOptions.map((option) => (
|
||||||
|
<button
|
||||||
|
key={option.value}
|
||||||
|
type="button"
|
||||||
|
className={`select-option ${exportExcelColumnsValue === option.value ? 'active' : ''}`}
|
||||||
|
onClick={async () => {
|
||||||
|
const compact = option.value === 'compact'
|
||||||
|
setExportDefaultExcelCompactColumns(compact)
|
||||||
|
await configService.setExportDefaultExcelCompactColumns(compact)
|
||||||
|
showMessage(compact ? '已启用精简列' : '已启用完整列', true)
|
||||||
|
setShowExportExcelColumnsSelect(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="option-label">{option.label}</span>
|
||||||
|
{option.desc && <span className="option-desc">{option.desc}</span>}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
const renderCacheTab = () => (
|
const renderCacheTab = () => (
|
||||||
<div className="tab-content">
|
<div className="tab-content">
|
||||||
<p className="section-desc">管理应用缓存数据</p>
|
<p className="section-desc">管理应用缓存数据</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user