修复了导出页面一些小问题

This commit is contained in:
cc
2026-03-04 22:46:31 +08:00
parent d3adae42fe
commit 53398707aa
15 changed files with 321 additions and 23 deletions

View File

@@ -26,6 +26,7 @@ import NotificationWindow from './pages/NotificationWindow'
import { useAppStore } from './stores/appStore'
import { themes, useThemeStore, type ThemeId, type ThemeMode } from './stores/themeStore'
import * as configService from './services/config'
import * as cloudControl from './services/cloudControl'
import { Download, X, Shield } from 'lucide-react'
import './App.scss'
@@ -75,6 +76,9 @@ function App() {
const [agreementChecked, setAgreementChecked] = useState(false)
const [agreementLoading, setAgreementLoading] = useState(true)
// 数据收集同意状态
const [showAnalyticsConsent, setShowAnalyticsConsent] = useState(false)
useEffect(() => {
const root = document.documentElement
const body = document.body
@@ -170,6 +174,12 @@ function App() {
const agreed = await configService.getAgreementAccepted()
if (!agreed) {
setShowAgreement(true)
} else {
// 协议已同意,检查数据收集同意状态
const consent = await configService.getAnalyticsConsent()
if (consent === null) {
setShowAnalyticsConsent(true)
}
}
} catch (e) {
console.error('检查协议状态失败:', e)
@@ -180,16 +190,44 @@ function App() {
checkAgreement()
}, [])
// 初始化数据收集
useEffect(() => {
cloudControl.initCloudControl()
}, [])
// 记录页面访问
useEffect(() => {
const path = location.pathname
if (path && path !== '/') {
cloudControl.recordPage(path)
}
}, [location.pathname])
const handleAgree = async () => {
if (!agreementChecked) return
await configService.setAgreementAccepted(true)
setShowAgreement(false)
// 协议同意后,检查数据收集同意
const consent = await configService.getAnalyticsConsent()
if (consent === null) {
setShowAnalyticsConsent(true)
}
}
const handleDisagree = () => {
window.electronAPI.window.close()
}
const handleAnalyticsAllow = async () => {
await configService.setAnalyticsConsent(true)
setShowAnalyticsConsent(false)
}
const handleAnalyticsDeny = async () => {
await configService.setAnalyticsConsent(false)
window.electronAPI.window.close()
}
// 监听启动时的更新通知
useEffect(() => {
if (isNotificationWindow) return // Skip updates in notification window
@@ -439,6 +477,42 @@ function App() {
</div>
)}
{/* 数据收集同意弹窗 */}
{showAnalyticsConsent && !agreementLoading && (
<div className="agreement-overlay">
<div className="agreement-modal">
<div className="agreement-header">
<Shield size={32} />
<h2>使</h2>
</div>
<div className="agreement-content">
<div className="agreement-text">
<p> WeFlow 使</p>
<h4></h4>
<p> 使使使</p>
<p> </p>
<p> </p>
<h4></h4>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
</div>
</div>
<div className="agreement-footer">
<div className="agreement-actions">
<button className="btn btn-secondary" onClick={handleAnalyticsDeny}></button>
<button className="btn btn-primary" onClick={handleAnalyticsAllow}></button>
</div>
</div>
</div>
</div>
)}
{/* 更新提示对话框 */}
<UpdateDialog
open={showUpdateDialog}

View File

@@ -23,6 +23,7 @@ interface ExportOptions {
exportVideos: boolean
exportEmojis: boolean
exportVoiceAsText: boolean
exportQuotedContent: boolean
excelCompactColumns: boolean
txtColumns: string[]
displayNamePreference: 'group-nickname' | 'remark' | 'nickname'
@@ -95,6 +96,7 @@ function ExportPage() {
exportVideos: true,
exportEmojis: true,
exportVoiceAsText: false,
exportQuotedContent: true,
excelCompactColumns: true,
txtColumns: defaultTxtColumns,
displayNamePreference: 'remark',
@@ -131,8 +133,9 @@ function ExportPage() {
}
const sessionsResult = await window.electronAPI.chat.getSessions()
if (sessionsResult.success && sessionsResult.sessions) {
setSessions(sessionsResult.sessions)
setFilteredSessions(sessionsResult.sessions)
const validSessions = sessionsResult.sessions.filter((s: { username: string }) => s.username !== 'floatbottle_folder_session')
setSessions(validSessions)
setFilteredSessions(validSessions)
}
} catch (e) {
console.error('加载会话失败:', e)
@@ -350,6 +353,7 @@ function ExportPage() {
exportVideos: options.exportMedia && options.exportVideos,
exportEmojis: options.exportMedia && options.exportEmojis,
exportVoiceAsText: options.exportVoiceAsText, // 即使不导出媒体,也可以导出语音转文字内容
exportQuotedContent: options.exportQuotedContent,
excelCompactColumns: options.excelCompactColumns,
txtColumns: options.txtColumns,
displayNamePreference: options.displayNamePreference,
@@ -774,6 +778,20 @@ function ExportPage() {
<div className="media-option-divider"></div>
<label className="media-checkbox-row">
<div className="media-checkbox-info">
<span className="media-checkbox-title"></span>
<span className="media-checkbox-desc"></span>
</div>
<input
type="checkbox"
checked={options.exportQuotedContent}
onChange={e => setOptions({ ...options, exportQuotedContent: e.target.checked })}
/>
</label>
<div className="media-option-divider"></div>
<label className={`media-checkbox-row ${!options.exportMedia ? 'disabled' : ''}`}>
<div className="media-checkbox-info">
<span className="media-checkbox-title"></span>

View File

@@ -0,0 +1,9 @@
// 数据收集服务前端接口
export async function initCloudControl() {
return window.electronAPI.cloud.init()
}
export function recordPage(pageName: string) {
window.electronAPI.cloud.recordPage(pageName)
}

View File

@@ -48,7 +48,10 @@ export const CONFIG_KEYS = {
NOTIFICATION_FILTER_LIST: 'notificationFilterList',
// 词云
WORD_CLOUD_EXCLUDE_WORDS: 'wordCloudExcludeWords'
WORD_CLOUD_EXCLUDE_WORDS: 'wordCloudExcludeWords',
// 数据收集
ANALYTICS_CONSENT: 'analyticsConsent'
} as const
export interface WxidConfig {
@@ -482,3 +485,15 @@ export async function getWordCloudExcludeWords(): Promise<string[]> {
export async function setWordCloudExcludeWords(words: string[]): Promise<void> {
await config.set(CONFIG_KEYS.WORD_CLOUD_EXCLUDE_WORDS, words)
}
// 获取数据收集同意状态
export async function getAnalyticsConsent(): Promise<boolean | null> {
const value = await config.get(CONFIG_KEYS.ANALYTICS_CONSENT)
if (typeof value === 'boolean') return value
return null
}
// 设置数据收集同意状态
export async function setAnalyticsConsent(consent: boolean): Promise<void> {
await config.set(CONFIG_KEYS.ANALYTICS_CONSENT, consent)
}

View File

@@ -527,6 +527,11 @@ export interface ElectronAPI {
deleteSnsPost: (postId: string) => Promise<{ success: boolean; error?: string }>
downloadEmoji: (params: { url: string; encryptUrl?: string; aesKey?: string }) => Promise<{ success: boolean; localPath?: string; error?: string }>
}
cloud: {
init: () => Promise<void>
recordPage: (pageName: string) => Promise<void>
getLogs: () => Promise<string[]>
}
http: {
start: (port?: number) => Promise<{ success: boolean; port?: number; error?: string }>
stop: () => Promise<{ success: boolean }>