mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-24 23:06:51 +00:00
feat(export): split default media options
This commit is contained in:
@@ -220,6 +220,29 @@
|
||||
background: var(--bg-primary);
|
||||
}
|
||||
|
||||
.media-default-grid {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 8px 12px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-bottom: 0;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--text-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.log-status {
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
@@ -354,6 +377,11 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.media-default-grid {
|
||||
max-width: 360px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.concurrency-inline-options {
|
||||
max-width: 360px;
|
||||
margin-bottom: 0;
|
||||
@@ -391,6 +419,7 @@
|
||||
.select-field,
|
||||
.settings-time-range-field,
|
||||
.log-toggle-line,
|
||||
.media-default-grid,
|
||||
.concurrency-inline-options,
|
||||
.format-grid {
|
||||
max-width: none;
|
||||
|
||||
@@ -15,7 +15,7 @@ export interface ExportDefaultsSettingsPatch {
|
||||
format?: string
|
||||
avatars?: boolean
|
||||
dateRange?: ExportDateRangeSelection
|
||||
media?: boolean
|
||||
media?: configService.ExportDefaultMediaConfig
|
||||
voiceAsText?: boolean
|
||||
excelCompactColumns?: boolean
|
||||
concurrency?: number
|
||||
@@ -62,7 +62,12 @@ export function ExportDefaultsSettingsForm({
|
||||
const [exportDefaultFormat, setExportDefaultFormat] = useState('excel')
|
||||
const [exportDefaultAvatars, setExportDefaultAvatars] = useState(true)
|
||||
const [exportDefaultDateRange, setExportDefaultDateRange] = useState<ExportDateRangeSelection>(() => createDefaultExportDateRangeSelection())
|
||||
const [exportDefaultMedia, setExportDefaultMedia] = useState(false)
|
||||
const [exportDefaultMedia, setExportDefaultMedia] = useState<configService.ExportDefaultMediaConfig>({
|
||||
images: true,
|
||||
videos: true,
|
||||
voices: true,
|
||||
emojis: true
|
||||
})
|
||||
const [exportDefaultVoiceAsText, setExportDefaultVoiceAsText] = useState(false)
|
||||
const [exportDefaultExcelCompactColumns, setExportDefaultExcelCompactColumns] = useState(true)
|
||||
const [exportDefaultConcurrency, setExportDefaultConcurrency] = useState(2)
|
||||
@@ -85,7 +90,12 @@ export function ExportDefaultsSettingsForm({
|
||||
setExportDefaultFormat(savedFormat || 'excel')
|
||||
setExportDefaultAvatars(savedAvatars ?? true)
|
||||
setExportDefaultDateRange(resolveExportDateRangeConfig(savedDateRange))
|
||||
setExportDefaultMedia(savedMedia ?? false)
|
||||
setExportDefaultMedia(savedMedia ?? {
|
||||
images: true,
|
||||
videos: true,
|
||||
voices: true,
|
||||
emojis: true
|
||||
})
|
||||
setExportDefaultVoiceAsText(savedVoiceAsText ?? false)
|
||||
setExportDefaultExcelCompactColumns(savedExcelCompactColumns ?? true)
|
||||
setExportDefaultConcurrency(savedConcurrency ?? 2)
|
||||
@@ -237,27 +247,66 @@ export function ExportDefaultsSettingsForm({
|
||||
|
||||
<div className="form-group">
|
||||
<div className="form-copy">
|
||||
<label>默认导出媒体文件</label>
|
||||
<span className="form-hint">控制图片/语音/表情的默认导出开关</span>
|
||||
<label>默认导出媒体内容</label>
|
||||
<span className="form-hint">控制图片、视频、语音、表情包的默认导出开关</span>
|
||||
</div>
|
||||
<div className="form-control">
|
||||
<div className="log-toggle-line">
|
||||
<span className="log-status">{exportDefaultMedia ? '已开启' : '已关闭'}</span>
|
||||
<label className="switch" htmlFor="shared-export-default-media">
|
||||
<div className="media-default-grid">
|
||||
<label>
|
||||
<input
|
||||
id="shared-export-default-media"
|
||||
className="switch-input"
|
||||
type="checkbox"
|
||||
checked={exportDefaultMedia}
|
||||
checked={exportDefaultMedia.images}
|
||||
onChange={async (e) => {
|
||||
const enabled = e.target.checked
|
||||
setExportDefaultMedia(enabled)
|
||||
await configService.setExportDefaultMedia(enabled)
|
||||
onDefaultsChanged?.({ media: enabled })
|
||||
notify(enabled ? '已开启默认媒体导出' : '已关闭默认媒体导出', true)
|
||||
const next = { ...exportDefaultMedia, images: e.target.checked }
|
||||
setExportDefaultMedia(next)
|
||||
await configService.setExportDefaultMedia(next)
|
||||
onDefaultsChanged?.({ media: next })
|
||||
notify(`已${e.target.checked ? '开启' : '关闭'}默认导出图片`, true)
|
||||
}}
|
||||
/>
|
||||
<span className="switch-slider" />
|
||||
图片
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={exportDefaultMedia.voices}
|
||||
onChange={async (e) => {
|
||||
const next = { ...exportDefaultMedia, voices: e.target.checked }
|
||||
setExportDefaultMedia(next)
|
||||
await configService.setExportDefaultMedia(next)
|
||||
onDefaultsChanged?.({ media: next })
|
||||
notify(`已${e.target.checked ? '开启' : '关闭'}默认导出语音`, true)
|
||||
}}
|
||||
/>
|
||||
语音
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={exportDefaultMedia.videos}
|
||||
onChange={async (e) => {
|
||||
const next = { ...exportDefaultMedia, videos: e.target.checked }
|
||||
setExportDefaultMedia(next)
|
||||
await configService.setExportDefaultMedia(next)
|
||||
onDefaultsChanged?.({ media: next })
|
||||
notify(`已${e.target.checked ? '开启' : '关闭'}默认导出视频`, true)
|
||||
}}
|
||||
/>
|
||||
视频
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={exportDefaultMedia.emojis}
|
||||
onChange={async (e) => {
|
||||
const next = { ...exportDefaultMedia, emojis: e.target.checked }
|
||||
setExportDefaultMedia(next)
|
||||
await configService.setExportDefaultMedia(next)
|
||||
onDefaultsChanged?.({ media: next })
|
||||
notify(`已${e.target.checked ? '开启' : '关闭'}默认导出表情包`, true)
|
||||
}}
|
||||
/>
|
||||
表情包
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1288,7 +1288,12 @@ function ExportPage() {
|
||||
const [exportDefaultFormat, setExportDefaultFormat] = useState<TextExportFormat>('excel')
|
||||
const [exportDefaultAvatars, setExportDefaultAvatars] = useState(true)
|
||||
const [exportDefaultDateRangeSelection, setExportDefaultDateRangeSelection] = useState<ExportDateRangeSelection>(() => createDefaultExportDateRangeSelection())
|
||||
const [exportDefaultMedia, setExportDefaultMedia] = useState(false)
|
||||
const [exportDefaultMedia, setExportDefaultMedia] = useState<configService.ExportDefaultMediaConfig>({
|
||||
images: true,
|
||||
videos: true,
|
||||
voices: true,
|
||||
emojis: true
|
||||
})
|
||||
const [exportDefaultVoiceAsText, setExportDefaultVoiceAsText] = useState(false)
|
||||
const [exportDefaultExcelCompactColumns, setExportDefaultExcelCompactColumns] = useState(true)
|
||||
const [exportDefaultConcurrency, setExportDefaultConcurrency] = useState(2)
|
||||
@@ -1301,11 +1306,11 @@ function ExportPage() {
|
||||
},
|
||||
useAllTime: false,
|
||||
exportAvatars: true,
|
||||
exportMedia: false,
|
||||
exportMedia: true,
|
||||
exportImages: true,
|
||||
exportVoices: true,
|
||||
exportVideos: true,
|
||||
exportEmojis: true,
|
||||
exportEmojis: true,
|
||||
exportVoiceAsText: false,
|
||||
excelCompactColumns: true,
|
||||
txtColumns: defaultTxtColumns,
|
||||
@@ -1831,7 +1836,12 @@ function ExportPage() {
|
||||
setLastSnsExportPostCount(savedSnsPostCount)
|
||||
setExportDefaultFormat((savedFormat as TextExportFormat) || 'excel')
|
||||
setExportDefaultAvatars(savedAvatars ?? true)
|
||||
setExportDefaultMedia(savedMedia ?? false)
|
||||
setExportDefaultMedia(savedMedia ?? {
|
||||
images: true,
|
||||
videos: true,
|
||||
voices: true,
|
||||
emojis: true
|
||||
})
|
||||
setExportDefaultVoiceAsText(savedVoiceAsText ?? false)
|
||||
setExportDefaultExcelCompactColumns(savedExcelCompactColumns ?? true)
|
||||
setExportDefaultConcurrency(savedConcurrency ?? 2)
|
||||
@@ -1854,7 +1864,16 @@ function ExportPage() {
|
||||
...prev,
|
||||
format: ((savedFormat as TextExportFormat) || 'excel'),
|
||||
exportAvatars: savedAvatars ?? true,
|
||||
exportMedia: savedMedia ?? prev.exportMedia,
|
||||
exportMedia: Boolean(
|
||||
(savedMedia?.images ?? prev.exportImages) ||
|
||||
(savedMedia?.voices ?? prev.exportVoices) ||
|
||||
(savedMedia?.videos ?? prev.exportVideos) ||
|
||||
(savedMedia?.emojis ?? prev.exportEmojis)
|
||||
),
|
||||
exportImages: savedMedia?.images ?? prev.exportImages,
|
||||
exportVoices: savedMedia?.voices ?? prev.exportVoices,
|
||||
exportVideos: savedMedia?.videos ?? prev.exportVideos,
|
||||
exportEmojis: savedMedia?.emojis ?? prev.exportEmojis,
|
||||
exportVoiceAsText: savedVoiceAsText ?? prev.exportVoiceAsText,
|
||||
excelCompactColumns: savedExcelCompactColumns ?? prev.excelCompactColumns,
|
||||
txtColumns,
|
||||
@@ -3214,7 +3233,16 @@ function ExportPage() {
|
||||
exportAvatars: exportDefaultAvatars,
|
||||
useAllTime: exportDefaultDateRangeSelection.useAllTime,
|
||||
dateRange: nextDateRange,
|
||||
exportMedia: exportDefaultMedia,
|
||||
exportMedia: Boolean(
|
||||
exportDefaultMedia.images ||
|
||||
exportDefaultMedia.voices ||
|
||||
exportDefaultMedia.videos ||
|
||||
exportDefaultMedia.emojis
|
||||
),
|
||||
exportImages: exportDefaultMedia.images,
|
||||
exportVoices: exportDefaultMedia.voices,
|
||||
exportVideos: exportDefaultMedia.videos,
|
||||
exportEmojis: exportDefaultMedia.emojis,
|
||||
exportVoiceAsText: exportDefaultVoiceAsText,
|
||||
excelCompactColumns: exportDefaultExcelCompactColumns,
|
||||
exportConcurrency: exportDefaultConcurrency
|
||||
@@ -3772,7 +3800,12 @@ function ExportPage() {
|
||||
|
||||
await configService.setExportDefaultFormat(options.format)
|
||||
await configService.setExportDefaultAvatars(options.exportAvatars)
|
||||
await configService.setExportDefaultMedia(Boolean(options.exportImages || options.exportVoices || options.exportVideos || options.exportEmojis))
|
||||
await configService.setExportDefaultMedia({
|
||||
images: options.exportImages,
|
||||
voices: options.exportVoices,
|
||||
videos: options.exportVideos,
|
||||
emojis: options.exportEmojis
|
||||
})
|
||||
await configService.setExportDefaultVoiceAsText(options.exportVoiceAsText)
|
||||
await configService.setExportDefaultExcelCompactColumns(options.excelCompactColumns)
|
||||
await configService.setExportDefaultTxtColumns(options.txtColumns)
|
||||
@@ -5215,8 +5248,17 @@ function ExportPage() {
|
||||
if (patch.dateRange) {
|
||||
setExportDefaultDateRangeSelection(patch.dateRange)
|
||||
}
|
||||
if (typeof patch.media === 'boolean') {
|
||||
setExportDefaultMedia(patch.media)
|
||||
if (patch.media) {
|
||||
const mediaPatch = patch.media
|
||||
setExportDefaultMedia(mediaPatch)
|
||||
setOptions(prev => ({
|
||||
...prev,
|
||||
exportMedia: Boolean(mediaPatch.images || mediaPatch.voices || mediaPatch.videos || mediaPatch.emojis),
|
||||
exportImages: mediaPatch.images,
|
||||
exportVoices: mediaPatch.voices,
|
||||
exportVideos: mediaPatch.videos,
|
||||
exportEmojis: mediaPatch.emojis
|
||||
}))
|
||||
}
|
||||
if (typeof patch.voiceAsText === 'boolean') {
|
||||
setExportDefaultVoiceAsText(patch.voiceAsText)
|
||||
|
||||
@@ -78,6 +78,20 @@ export interface WxidConfig {
|
||||
updatedAt?: number
|
||||
}
|
||||
|
||||
export interface ExportDefaultMediaConfig {
|
||||
images: boolean
|
||||
videos: boolean
|
||||
voices: boolean
|
||||
emojis: boolean
|
||||
}
|
||||
|
||||
const DEFAULT_EXPORT_MEDIA_CONFIG: ExportDefaultMediaConfig = {
|
||||
images: true,
|
||||
videos: true,
|
||||
voices: true,
|
||||
emojis: true
|
||||
}
|
||||
|
||||
// 获取解密密钥
|
||||
export async function getDecryptKey(): Promise<string | null> {
|
||||
const value = await config.get(CONFIG_KEYS.DECRYPT_KEY)
|
||||
@@ -364,15 +378,36 @@ export async function setExportDefaultDateRange(range: ExportDefaultDateRangeCon
|
||||
}
|
||||
|
||||
// 获取导出默认媒体设置
|
||||
export async function getExportDefaultMedia(): Promise<boolean | null> {
|
||||
export async function getExportDefaultMedia(): Promise<ExportDefaultMediaConfig | null> {
|
||||
const value = await config.get(CONFIG_KEYS.EXPORT_DEFAULT_MEDIA)
|
||||
if (typeof value === 'boolean') return value
|
||||
if (typeof value === 'boolean') {
|
||||
return {
|
||||
images: value,
|
||||
videos: value,
|
||||
voices: value,
|
||||
emojis: value
|
||||
}
|
||||
}
|
||||
if (value && typeof value === 'object') {
|
||||
const raw = value as Partial<Record<keyof ExportDefaultMediaConfig, unknown>>
|
||||
return {
|
||||
images: typeof raw.images === 'boolean' ? raw.images : DEFAULT_EXPORT_MEDIA_CONFIG.images,
|
||||
videos: typeof raw.videos === 'boolean' ? raw.videos : DEFAULT_EXPORT_MEDIA_CONFIG.videos,
|
||||
voices: typeof raw.voices === 'boolean' ? raw.voices : DEFAULT_EXPORT_MEDIA_CONFIG.voices,
|
||||
emojis: typeof raw.emojis === 'boolean' ? raw.emojis : DEFAULT_EXPORT_MEDIA_CONFIG.emojis
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// 设置导出默认媒体设置
|
||||
export async function setExportDefaultMedia(enabled: boolean): Promise<void> {
|
||||
await config.set(CONFIG_KEYS.EXPORT_DEFAULT_MEDIA, enabled)
|
||||
export async function setExportDefaultMedia(media: ExportDefaultMediaConfig): Promise<void> {
|
||||
await config.set(CONFIG_KEYS.EXPORT_DEFAULT_MEDIA, {
|
||||
images: media.images,
|
||||
videos: media.videos,
|
||||
voices: media.voices,
|
||||
emojis: media.emojis
|
||||
})
|
||||
}
|
||||
|
||||
// 获取导出默认语音转文字
|
||||
|
||||
Reference in New Issue
Block a user