mirror of
https://github.com/ILoveBingLu/CipherTalk.git
synced 2026-04-11 06:02:15 +08:00
feat: 添加自定义系统提示词和风格选项,优化AI摘要功能
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
**一款现代化的微信聊天记录查看与分析工具**
|
||||
|
||||
[](LICENSE)
|
||||
[](package.json)
|
||||
[](package.json)
|
||||
[]()
|
||||
[]()
|
||||
[]()
|
||||
@@ -315,10 +315,10 @@ export const useChatStore = create<ChatStore>((set) => ({
|
||||
|
||||
| 渠道 | 链接 |
|
||||
|:---:|:---|
|
||||
| 🌐 **官方网站** | [密语 CipherTalk](https://miyuapp.aiqji.com) |
|
||||
| 🌐 **官方网站** | [密语 CipherTalk](https://miyu.aiqji.com) |
|
||||
| 🐛 **问题反馈** | [GitHub Issues](https://github.com/ILoveBingLu/CipherTalk/issues) |
|
||||
| 💬 **讨论交流** | [GitHub Discussions](https://github.com/ILoveBingLu/CipherTalk/discussions) |
|
||||
| 📱 **Telegram 群组** | [加入群聊](https://t.me/+toZ7bY15IZo3NjVl) |
|
||||
| 📱 **Telegram 群组** | [加入群聊](https://t.me/CipherTalkChat) |
|
||||
| ⭐ **项目主页** | [GitHub Repository](https://github.com/ILoveBingLu/CipherTalk) |
|
||||
|
||||
</div>
|
||||
|
||||
@@ -3197,7 +3197,11 @@ function registerIpcHandlers() {
|
||||
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
|
||||
}) => {
|
||||
try {
|
||||
const { aiService } = await import('./services/ai/aiService')
|
||||
@@ -3280,7 +3284,11 @@ function registerIpcHandlers() {
|
||||
apiKey: options.apiKey,
|
||||
model: options.model,
|
||||
detail: options.detail,
|
||||
customRequirement: options.customRequirement
|
||||
systemPromptPreset: options.systemPromptPreset,
|
||||
customSystemPrompt: options.customSystemPrompt,
|
||||
customRequirement: options.customRequirement,
|
||||
sessionName: options.sessionName,
|
||||
enableThinking: options.enableThinking
|
||||
},
|
||||
(chunk: string) => {
|
||||
// 发送流式数据到渲染进程
|
||||
|
||||
@@ -400,6 +400,11 @@ contextBridge.exposeInMainWorld('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
|
||||
}) => ipcRenderer.invoke('ai:generateSummary', sessionId, timeRange, options),
|
||||
onSummaryChunk: (callback: (chunk: string) => void) => {
|
||||
ipcRenderer.on('ai:summaryChunk', (_, chunk) => callback(chunk))
|
||||
|
||||
@@ -28,6 +28,8 @@ export interface SummaryOptions {
|
||||
model?: string
|
||||
language?: 'zh' | 'en'
|
||||
detail?: 'simple' | 'normal' | 'detailed'
|
||||
systemPromptPreset?: 'default' | 'decision-focus' | 'action-focus' | 'risk-focus' | 'custom'
|
||||
customSystemPrompt?: string
|
||||
customRequirement?: string // 用户自定义要求
|
||||
sessionName?: string // 会话名称
|
||||
enableThinking?: boolean // 是否启用思考模式(推理模式)
|
||||
@@ -163,7 +165,12 @@ class AIService {
|
||||
/**
|
||||
* 获取系统提示词
|
||||
*/
|
||||
private getSystemPrompt(language: string = 'zh', detail: string = 'normal'): string {
|
||||
private getSystemPrompt(
|
||||
language: string = 'zh',
|
||||
detail: string = 'normal',
|
||||
preset: 'default' | 'decision-focus' | 'action-focus' | 'risk-focus' | 'custom' = 'default',
|
||||
customSystemPrompt?: string
|
||||
): string {
|
||||
const detailInstructions = {
|
||||
simple: '生成极简摘要,字数控制在 100 字以内。只保留最核心的事件和结论,忽略寒暄和琐碎细节。',
|
||||
normal: '生成内容适中的摘要。涵盖对话主要话题、关键信息点及明确的约定事项。',
|
||||
@@ -176,7 +183,7 @@ class AIService {
|
||||
detailed: '深度详尽'
|
||||
}
|
||||
|
||||
return `### 角色定义
|
||||
const basePrompt = `### 角色定义
|
||||
你是一位拥有 10 年经验的高级情报分析师和沟通专家,擅长从琐碎、碎片化的聊天记录中精准提取高价值信息。
|
||||
|
||||
### 任务描述
|
||||
@@ -210,6 +217,24 @@ ${detailInstructions[detail as keyof typeof detailInstructions] || detailInstruc
|
||||
|
||||
---
|
||||
*注:若对应部分无相关内容,请直接忽略该标题。*`
|
||||
|
||||
const presetInstructionMap: Record<string, string> = {
|
||||
'default': '保持通用摘要风格,兼顾信息完整性与可读性。',
|
||||
'decision-focus': '重点提取所有决策、结论、拍板事项。若有意见分歧,请明确分歧点和最终取舍。',
|
||||
'action-focus': '重点提取可执行事项:负责人、截止时间、前置依赖、下一步动作。尽量转写为清单。',
|
||||
'risk-focus': '重点提取风险、阻塞、争议、潜在误解及其影响范围,并给出可执行的缓解建议。'
|
||||
}
|
||||
|
||||
if (preset === 'custom') {
|
||||
const custom = (customSystemPrompt || '').trim()
|
||||
if (custom) {
|
||||
return `${basePrompt}\n\n### 用户自定义系统提示词\n${custom}`
|
||||
}
|
||||
return `${basePrompt}\n\n### 提示\n当前选择了自定义系统提示词,但内容为空。请按默认规则输出。`
|
||||
}
|
||||
|
||||
const presetInstruction = presetInstructionMap[preset] || presetInstructionMap.default
|
||||
return `${basePrompt}\n\n### 风格偏好\n${presetInstruction}`
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -433,7 +458,14 @@ ${detailInstructions[detail as keyof typeof detailInstructions] || detailInstruc
|
||||
const formattedMessages = this.formatMessages(messages, contacts, options.sessionId)
|
||||
|
||||
// 构建提示词
|
||||
const systemPrompt = this.getSystemPrompt(options.language, options.detail)
|
||||
const presetFromConfig = (this.configService.get('aiSystemPromptPreset') as any) || 'default'
|
||||
const customSystemPromptFromConfig = (this.configService.get('aiCustomSystemPrompt') as string) || ''
|
||||
const systemPrompt = this.getSystemPrompt(
|
||||
options.language,
|
||||
options.detail,
|
||||
options.systemPromptPreset || presetFromConfig,
|
||||
options.customSystemPrompt ?? customSystemPromptFromConfig
|
||||
)
|
||||
|
||||
// 使用会话名称优化提示词
|
||||
const targetName = options.sessionName || options.sessionId
|
||||
|
||||
@@ -64,6 +64,8 @@ interface ConfigSchema {
|
||||
}
|
||||
aiDefaultTimeRange: number
|
||||
aiSummaryDetail: 'simple' | 'normal' | 'detailed'
|
||||
aiSystemPromptPreset: 'default' | 'decision-focus' | 'action-focus' | 'risk-focus' | 'custom'
|
||||
aiCustomSystemPrompt: string
|
||||
aiEnableCache: boolean
|
||||
aiEnableThinking: boolean // 是否显示思考过程
|
||||
aiMessageLimit: number // 摘要提取的消息条数限制
|
||||
@@ -102,6 +104,8 @@ const defaults: ConfigSchema = {
|
||||
aiProviderConfigs: {}, // 空对象,用户配置后填充
|
||||
aiDefaultTimeRange: 7, // 默认7天
|
||||
aiSummaryDetail: 'normal',
|
||||
aiSystemPromptPreset: 'default',
|
||||
aiCustomSystemPrompt: '',
|
||||
aiEnableCache: true,
|
||||
aiEnableThinking: true, // 默认显示思考过程
|
||||
aiMessageLimit: 3000 // 默认3000条,用户可调至5000
|
||||
@@ -199,6 +203,31 @@ export class ConfigService {
|
||||
} catch (e) {
|
||||
console.error('迁移 AI 配置失败:', e)
|
||||
}
|
||||
|
||||
// 迁移:兼容旧字段 baseUrl -> baseURL
|
||||
try {
|
||||
const aiConfigsRow = this.db.prepare("SELECT value FROM config WHERE key = 'aiProviderConfigs'").get() as { value: string } | undefined
|
||||
if (aiConfigsRow) {
|
||||
const aiConfigs = JSON.parse(aiConfigsRow.value || '{}') as Record<string, any>
|
||||
let changed = false
|
||||
|
||||
for (const providerId of Object.keys(aiConfigs)) {
|
||||
const cfg = aiConfigs[providerId]
|
||||
if (cfg && !cfg.baseURL && cfg.baseUrl) {
|
||||
cfg.baseURL = cfg.baseUrl
|
||||
delete cfg.baseUrl
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
this.db.prepare("INSERT OR REPLACE INTO config (key, value) VALUES (?, ?)").run('aiProviderConfigs', JSON.stringify(aiConfigs))
|
||||
console.log('[Config] AI 提供商配置字段已迁移: baseUrl -> baseURL')
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('迁移 AI baseURL 字段失败:', e)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('初始化配置数据库失败:', e)
|
||||
}
|
||||
@@ -313,8 +342,16 @@ export class ConfigService {
|
||||
}
|
||||
|
||||
getAIProviderConfig(providerId: string): { apiKey: string; model: string; baseURL?: string } | null {
|
||||
const configs = this.get('aiProviderConfigs')
|
||||
return configs[providerId] || null
|
||||
const configs = this.get('aiProviderConfigs') as any
|
||||
const providerConfig = configs?.[providerId]
|
||||
if (!providerConfig) return null
|
||||
|
||||
// 兼容历史字段 baseUrl
|
||||
if (!providerConfig.baseURL && providerConfig.baseUrl) {
|
||||
providerConfig.baseURL = providerConfig.baseUrl
|
||||
}
|
||||
|
||||
return providerConfig
|
||||
}
|
||||
|
||||
setAIProviderConfig(providerId: string, config: { apiKey: string; model: string; baseURL?: string }): void {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ciphertalk",
|
||||
"version": "2.2.8",
|
||||
"version": "2.2.9",
|
||||
"description": "密语 - 微信聊天记录查看工具",
|
||||
"author": "ILoveBingLu",
|
||||
"license": "CC-BY-NC-SA-4.0",
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
src/types/electron.d.ts
vendored
2
src/types/electron.d.ts
vendored
@@ -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