mirror of
https://github.com/ILoveBingLu/CipherTalk.git
synced 2026-05-23 04:53:24 +08:00
feat: 添加自定义系统提示词和风格选项,优化AI摘要功能
This commit is contained in:
@@ -12,7 +12,7 @@ function WhatsNewModal({ onClose, version }: WhatsNewModalProps) {
|
||||
{
|
||||
icon: <Package size={20} />,
|
||||
title: '优化',
|
||||
desc: '优化图片密钥获取。'
|
||||
desc: '优化AI摘要。'
|
||||
},
|
||||
// {
|
||||
// icon: <Image size={20} />,
|
||||
@@ -29,11 +29,11 @@ function WhatsNewModal({ onClose, version }: WhatsNewModalProps) {
|
||||
// title: '分类导出',
|
||||
// desc: '导出时可按群聊或个人聊天筛选,支持日期范围过滤。'
|
||||
// }
|
||||
// {
|
||||
// icon: <Aperture size={20} />,
|
||||
// title: '朋友圈',
|
||||
// desc: '评论内的表情包已完成解密!'
|
||||
// }
|
||||
{
|
||||
icon: <Aperture size={20} />,
|
||||
title: '朋友圈',
|
||||
desc: '评论内的图片已完成解密!'
|
||||
}
|
||||
]
|
||||
|
||||
const handleTelegram = () => {
|
||||
|
||||
@@ -238,6 +238,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
.custom-system-prompt-textarea {
|
||||
width: 100%;
|
||||
min-height: 160px;
|
||||
resize: vertical;
|
||||
padding: 12px 14px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 12px;
|
||||
background: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--primary);
|
||||
}
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
||||
@@ -103,6 +103,10 @@ interface AISummarySettingsProps {
|
||||
setDefaultTimeRange: (val: number) => void
|
||||
summaryDetail: 'simple' | 'normal' | 'detailed'
|
||||
setSummaryDetail: (val: 'simple' | 'normal' | 'detailed') => void
|
||||
systemPromptPreset: 'default' | 'decision-focus' | 'action-focus' | 'risk-focus' | 'custom'
|
||||
setSystemPromptPreset: (val: 'default' | 'decision-focus' | 'action-focus' | 'risk-focus' | 'custom') => void
|
||||
customSystemPrompt: string
|
||||
setCustomSystemPrompt: (val: string) => void
|
||||
enableThinking: boolean
|
||||
setEnableThinking: (val: boolean) => void
|
||||
messageLimit: number
|
||||
@@ -121,6 +125,10 @@ function AISummarySettings({
|
||||
setDefaultTimeRange,
|
||||
summaryDetail,
|
||||
setSummaryDetail,
|
||||
systemPromptPreset,
|
||||
setSystemPromptPreset,
|
||||
customSystemPrompt,
|
||||
setCustomSystemPrompt,
|
||||
enableThinking,
|
||||
setEnableThinking,
|
||||
messageLimit,
|
||||
@@ -331,6 +339,13 @@ function AISummarySettings({
|
||||
{ value: 7, label: '最近 7 天' },
|
||||
{ value: 30, label: '最近 30 天' }
|
||||
]
|
||||
const systemPromptPresetOptions = [
|
||||
{ value: 'default', label: '通用平衡(默认)' },
|
||||
{ value: 'decision-focus', label: '决策优先(重点提炼结论)' },
|
||||
{ value: 'action-focus', label: '行动优先(重点提炼待办)' },
|
||||
{ value: 'risk-focus', label: '风险优先(重点识别阻塞与风险)' },
|
||||
{ value: 'custom', label: '自定义系统提示词' }
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="tab-content ai-summary-settings">
|
||||
@@ -558,6 +573,37 @@ function AISummarySettings({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 className="section-title">系统提示词风格</h3>
|
||||
<div className="settings-form" style={{ marginTop: '8px' }}>
|
||||
<div className="form-group">
|
||||
<label>提示词模板</label>
|
||||
<CustomSelect
|
||||
value={systemPromptPreset}
|
||||
onChange={setSystemPromptPreset}
|
||||
options={systemPromptPresetOptions}
|
||||
/>
|
||||
<div className="form-hint">
|
||||
选择摘要的分析侧重。若选“自定义系统提示词”,将使用你编写的提示词作为额外系统指令。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{systemPromptPreset === 'custom' && (
|
||||
<div className="form-group">
|
||||
<label>自定义系统提示词</label>
|
||||
<textarea
|
||||
className="custom-system-prompt-textarea"
|
||||
placeholder="例如:你是一名项目经理助手。请优先输出任务清单,按负责人和截止时间分组。"
|
||||
value={customSystemPrompt}
|
||||
onChange={(e) => setCustomSystemPrompt(e.target.value)}
|
||||
rows={8}
|
||||
/>
|
||||
<div className="form-hint">
|
||||
建议描述:角色、输出结构、重点关注项、禁止项。留空则回退默认规则。
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 4. 使用统计 */}
|
||||
{usageStats && (
|
||||
<>
|
||||
|
||||
@@ -143,7 +143,7 @@ function AISummaryWindow() {
|
||||
|
||||
try {
|
||||
// 检查 API 配置 - 使用新的配置服务
|
||||
const { getAiApiKey, getAiProvider, getAiModel, getAiSummaryDetail, getAiEnableThinking } = await import('../services/config')
|
||||
const { getAiApiKey, getAiProvider, getAiModel, getAiSummaryDetail, getAiEnableThinking, getAiSystemPromptPreset, getAiCustomSystemPrompt } = await import('../services/config')
|
||||
|
||||
const apiKey = await getAiApiKey()
|
||||
console.log('[AISummaryWindow] 当前 API Key:', apiKey ? '已配置' : '未配置', '长度:', apiKey?.length)
|
||||
@@ -159,8 +159,10 @@ function AISummaryWindow() {
|
||||
const model = await getAiModel()
|
||||
const detail = await getAiSummaryDetail()
|
||||
const enableThinking = await getAiEnableThinking()
|
||||
const systemPromptPreset = await getAiSystemPromptPreset()
|
||||
const customSystemPrompt = await getAiCustomSystemPrompt()
|
||||
|
||||
console.log('[AISummaryWindow] 配置信息:', { provider, model, detail, enableThinking })
|
||||
console.log('[AISummaryWindow] 配置信息:', { provider, model, detail, enableThinking, systemPromptPreset })
|
||||
|
||||
// 监听流式输出
|
||||
let internalThinkMode = false
|
||||
@@ -225,6 +227,8 @@ function AISummaryWindow() {
|
||||
apiKey: apiKey as string,
|
||||
model: model || 'glm-4.5-flash',
|
||||
detail: detail || 'normal',
|
||||
systemPromptPreset,
|
||||
customSystemPrompt,
|
||||
customRequirement: customRequirement,
|
||||
sessionName: sessionName,
|
||||
enableThinking: enableThinking !== false // 默认启用
|
||||
|
||||
@@ -132,6 +132,8 @@ function SettingsPage() {
|
||||
const [aiModel, setAiModelState] = useState('')
|
||||
const [aiDefaultTimeRange, setAiDefaultTimeRangeState] = useState<number>(7)
|
||||
const [aiSummaryDetail, setAiSummaryDetailState] = useState<'simple' | 'normal' | 'detailed'>('normal')
|
||||
const [aiSystemPromptPreset, setAiSystemPromptPresetState] = useState<'default' | 'decision-focus' | 'action-focus' | 'risk-focus' | 'custom'>('default')
|
||||
const [aiCustomSystemPrompt, setAiCustomSystemPromptState] = useState<string>('')
|
||||
const [aiEnableThinking, setAiEnableThinkingState] = useState<boolean>(true)
|
||||
const [aiMessageLimit, setAiMessageLimitState] = useState<number>(3000)
|
||||
|
||||
@@ -205,6 +207,8 @@ function SettingsPage() {
|
||||
const savedAiModel = await configService.getAiModel()
|
||||
const savedAiDefaultTimeRange = await configService.getAiDefaultTimeRange()
|
||||
const savedAiSummaryDetail = await configService.getAiSummaryDetail()
|
||||
const savedAiSystemPromptPreset = await configService.getAiSystemPromptPreset()
|
||||
const savedAiCustomSystemPrompt = await configService.getAiCustomSystemPrompt()
|
||||
const savedAiEnableThinking = await configService.getAiEnableThinking()
|
||||
const savedAiMessageLimit = await configService.getAiMessageLimit()
|
||||
|
||||
@@ -213,6 +217,8 @@ function SettingsPage() {
|
||||
setAiModelState(savedAiModel)
|
||||
setAiDefaultTimeRangeState(savedAiDefaultTimeRange)
|
||||
setAiSummaryDetailState(savedAiSummaryDetail)
|
||||
setAiSystemPromptPresetState(savedAiSystemPromptPreset)
|
||||
setAiCustomSystemPromptState(savedAiCustomSystemPrompt)
|
||||
setAiEnableThinkingState(savedAiEnableThinking)
|
||||
setAiMessageLimitState(savedAiMessageLimit)
|
||||
} catch (e) {
|
||||
@@ -722,6 +728,8 @@ function SettingsPage() {
|
||||
await configService.setAiModel(aiModel)
|
||||
await configService.setAiDefaultTimeRange(aiDefaultTimeRange)
|
||||
await configService.setAiSummaryDetail(aiSummaryDetail)
|
||||
await configService.setAiSystemPromptPreset(aiSystemPromptPreset)
|
||||
await configService.setAiCustomSystemPrompt(aiCustomSystemPrompt)
|
||||
await configService.setAiEnableThinking(aiEnableThinking)
|
||||
await configService.setAiMessageLimit(aiMessageLimit)
|
||||
|
||||
@@ -2593,6 +2601,10 @@ function SettingsPage() {
|
||||
setDefaultTimeRange={setAiDefaultTimeRangeState}
|
||||
summaryDetail={aiSummaryDetail}
|
||||
setSummaryDetail={setAiSummaryDetailState}
|
||||
systemPromptPreset={aiSystemPromptPreset}
|
||||
setSystemPromptPreset={setAiSystemPromptPresetState}
|
||||
customSystemPrompt={aiCustomSystemPrompt}
|
||||
setCustomSystemPrompt={setAiCustomSystemPromptState}
|
||||
enableThinking={aiEnableThinking}
|
||||
setEnableThinking={setAiEnableThinkingState}
|
||||
messageLimit={aiMessageLimit}
|
||||
|
||||
+35
-3
@@ -342,7 +342,15 @@ export async function setAiProvider(provider: string): Promise<void> {
|
||||
export async function getAiProviderConfig(providerId: string): Promise<{ apiKey: string; model: string; baseURL?: string } | null> {
|
||||
const configs = await config.get('aiProviderConfigs')
|
||||
const allConfigs = (configs as any) || {}
|
||||
return allConfigs[providerId] || null
|
||||
const providerConfig = allConfigs[providerId]
|
||||
if (!providerConfig) return null
|
||||
|
||||
// 兼容旧字段 baseUrl
|
||||
if (!providerConfig.baseURL && providerConfig.baseUrl) {
|
||||
providerConfig.baseURL = providerConfig.baseUrl
|
||||
}
|
||||
|
||||
return providerConfig
|
||||
}
|
||||
|
||||
// 设置指定提供商的配置
|
||||
@@ -372,7 +380,8 @@ export async function setAiApiKey(key: string): Promise<void> {
|
||||
const existingConfig = await getAiProviderConfig(currentProvider)
|
||||
await setAiProviderConfig(currentProvider, {
|
||||
apiKey: key,
|
||||
model: existingConfig?.model || ''
|
||||
model: existingConfig?.model || '',
|
||||
baseURL: existingConfig?.baseURL
|
||||
})
|
||||
}
|
||||
|
||||
@@ -389,7 +398,8 @@ export async function setAiModel(model: string): Promise<void> {
|
||||
const existingConfig = await getAiProviderConfig(currentProvider)
|
||||
await setAiProviderConfig(currentProvider, {
|
||||
apiKey: existingConfig?.apiKey || '',
|
||||
model: model
|
||||
model: model,
|
||||
baseURL: existingConfig?.baseURL
|
||||
})
|
||||
}
|
||||
|
||||
@@ -415,6 +425,28 @@ export async function setAiSummaryDetail(detail: 'simple' | 'normal' | 'detailed
|
||||
await config.set('aiSummaryDetail', detail)
|
||||
}
|
||||
|
||||
// 获取系统提示词模板
|
||||
export async function getAiSystemPromptPreset(): Promise<'default' | 'decision-focus' | 'action-focus' | 'risk-focus' | 'custom'> {
|
||||
const value = await config.get('aiSystemPromptPreset')
|
||||
return (value as 'default' | 'decision-focus' | 'action-focus' | 'risk-focus' | 'custom') || 'default'
|
||||
}
|
||||
|
||||
// 设置系统提示词模板
|
||||
export async function setAiSystemPromptPreset(preset: 'default' | 'decision-focus' | 'action-focus' | 'risk-focus' | 'custom'): Promise<void> {
|
||||
await config.set('aiSystemPromptPreset', preset)
|
||||
}
|
||||
|
||||
// 获取自定义系统提示词
|
||||
export async function getAiCustomSystemPrompt(): Promise<string> {
|
||||
const value = await config.get('aiCustomSystemPrompt')
|
||||
return (value as string) || ''
|
||||
}
|
||||
|
||||
// 设置自定义系统提示词
|
||||
export async function setAiCustomSystemPrompt(prompt: string): Promise<void> {
|
||||
await config.set('aiCustomSystemPrompt', prompt || '')
|
||||
}
|
||||
|
||||
// 获取是否启用思考模式
|
||||
export async function getAiEnableThinking(): Promise<boolean> {
|
||||
const value = await config.get('aiEnableThinking')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { create } from 'zustand'
|
||||
|
||||
export type ThemeId = 'cloud-dancer' | 'corundum-blue' | 'kiwi-green' | 'spicy-red' | 'teal-water' | 'new-year'
|
||||
export type ThemeId = 'cloud-dancer' | 'corundum-blue' | 'kiwi-green' | 'spicy-red' | 'teal-water' | 'new-year' | 'sakura-mist'
|
||||
export type ThemeMode = 'light' | 'dark' | 'system'
|
||||
export type AppIcon = 'default' | 'xinnian'
|
||||
|
||||
@@ -54,6 +54,13 @@ export const themes: ThemeInfo[] = [
|
||||
description: 'Happy New Year 2026',
|
||||
primaryColor: '#E60012',
|
||||
bgColor: '#FFF0F0'
|
||||
},
|
||||
{
|
||||
id: 'sakura-mist',
|
||||
name: '樱雾粉',
|
||||
description: '温柔、治愈的高级粉',
|
||||
primaryColor: '#D86A8A',
|
||||
bgColor: '#FFF2F7'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
+40
-1
@@ -164,6 +164,26 @@
|
||||
--logo-invert: 0;
|
||||
}
|
||||
|
||||
// 樱雾粉主题
|
||||
[data-theme="sakura-mist"][data-mode="light"],
|
||||
[data-theme="sakura-mist"]:not([data-mode]) {
|
||||
--primary: #D86A8A;
|
||||
--primary-hover: #C55B7A;
|
||||
--primary-light: rgba(216, 106, 138, 0.12);
|
||||
--bg-primary: #FFF2F7;
|
||||
--bg-secondary: rgba(255, 255, 255, 0.82);
|
||||
--bg-tertiary: rgba(216, 106, 138, 0.05);
|
||||
--bg-hover: rgba(216, 106, 138, 0.08);
|
||||
--text-primary: #4B2D38;
|
||||
--text-secondary: #7A5865;
|
||||
--text-tertiary: #A78492;
|
||||
--border-color: rgba(216, 106, 138, 0.16);
|
||||
--bg-gradient: linear-gradient(135deg, #FFF2F7 0%, #FFE6F0 100%);
|
||||
--primary-gradient: linear-gradient(135deg, #D86A8A 0%, #F08FB1 100%);
|
||||
--card-bg: rgba(255, 255, 255, 0.82);
|
||||
--logo-invert: 0;
|
||||
}
|
||||
|
||||
// ==================== 深色主题 ====================
|
||||
|
||||
// 云上舞白 - 深色
|
||||
@@ -280,6 +300,25 @@
|
||||
--logo-invert: 1;
|
||||
}
|
||||
|
||||
// 樱雾粉 - 深色
|
||||
[data-theme="sakura-mist"][data-mode="dark"] {
|
||||
--primary: #F08FB1;
|
||||
--primary-hover: #F6A3C0;
|
||||
--primary-light: rgba(240, 143, 177, 0.18);
|
||||
--bg-primary: #24161D;
|
||||
--bg-secondary: rgba(44, 30, 38, 0.92);
|
||||
--bg-tertiary: rgba(255, 255, 255, 0.06);
|
||||
--bg-hover: rgba(255, 255, 255, 0.1);
|
||||
--text-primary: #FFEAF2;
|
||||
--text-secondary: #DDBAC8;
|
||||
--text-tertiary: #AC8796;
|
||||
--border-color: rgba(255, 255, 255, 0.12);
|
||||
--bg-gradient: linear-gradient(135deg, #24161D 0%, #34212A 100%);
|
||||
--primary-gradient: linear-gradient(135deg, #D86A8A 0%, #F08FB1 100%);
|
||||
--card-bg: rgba(44, 30, 38, 0.92);
|
||||
--logo-invert: 1;
|
||||
}
|
||||
|
||||
// 重置样式
|
||||
* {
|
||||
margin: 0;
|
||||
@@ -384,4 +423,4 @@ img {
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+2
@@ -780,6 +780,8 @@ export interface ElectronAPI {
|
||||
apiKey: string
|
||||
model: string
|
||||
detail: 'simple' | 'normal' | 'detailed'
|
||||
systemPromptPreset?: 'default' | 'decision-focus' | 'action-focus' | 'risk-focus' | 'custom'
|
||||
customSystemPrompt?: string
|
||||
customRequirement?: string
|
||||
sessionName?: string
|
||||
enableThinking?: boolean
|
||||
|
||||
Reference in New Issue
Block a user