mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 07:16:51 +00:00
修复了导出页面一些小问题
This commit is contained in:
74
src/App.tsx
74
src/App.tsx
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
9
src/services/cloudControl.ts
Normal file
9
src/services/cloudControl.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// 数据收集服务前端接口
|
||||
|
||||
export async function initCloudControl() {
|
||||
return window.electronAPI.cloud.init()
|
||||
}
|
||||
|
||||
export function recordPage(pageName: string) {
|
||||
window.electronAPI.cloud.recordPage(pageName)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
5
src/types/electron.d.ts
vendored
5
src/types/electron.d.ts
vendored
@@ -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 }>
|
||||
|
||||
Reference in New Issue
Block a user