Compare commits

..
8 Commits
Author SHA1 Message Date
电摇小子andClaude Opus 4.7 a740a50e79 fix: 使用 pnpm/action-setup@v4 安装 pnpm
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 11:04:19 +08:00
电摇小子andClaude Opus 4.7 ffe797b3e4 fix: 使用 corepack 启用 pnpm 替代 npm install -g
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 11:01:37 +08:00
电摇小子andClaude Opus 4.7 9cd6061c0f fix: 使用 pnpm@7 匹配项目要求
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 10:39:23 +08:00
电摇小子andClaude Opus 4.7 67d86f7834 fix: 修复 release workflow - 改用 npm 安装 pnpm 和 artifacts 上传
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 10:38:03 +08:00
电摇小子andClaude Opus 4.7 a6138fd62b chore: 添加 GitHub Actions 自动构建 release workflow
- 推送 v* 标签时自动在 macOS 多架构构建 .dmg
- 自动创建 GitHub Release 并附加构建产物
- 升级版本至 v1.1.0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 10:20:32 +08:00
电摇小子andClaude Opus 4.7 d1763757be docs: 更新 README,添加多模型服务支持说明
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 10:12:57 +08:00
电摇小子andClaude Opus 4.7 a4dfa542d1 feat: 支持多模型服务配置 (Key/Base URL/模型名)
- 后端 ai:chat 支持 baseURL 参数,可配置任意 OpenAI 兼容 API
- 前端 UI 增加 Base URL 输入框和模型选择下拉 (DeepSeek/GPT-4o/Claude/Moonshot)
- 配置通过 localStorage 持久化,支持从 .env 文件读取默认値
- 统一错误提示,移除 DeepSeek 硬编码引用

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 10:11:25 +08:00
电摇小子 9fb1d14c41 doc: 更新文档 2026-04-08 11:01:03 +08:00
11 changed files with 133 additions and 21 deletions
+3 -1
View File
@@ -1,8 +1,10 @@
# WeChat Database Key (Optional, can be entered in UI) # WeChat Database Key (Optional, can be entered in UI)
VITE_DB_KEY= VITE_DB_KEY=
# DeepSeek API Key (Optional, can be entered in UI) # AI API Configuration (Optional, can be entered in UI)
VITE_DEEPSEEK_API_KEY= VITE_DEEPSEEK_API_KEY=
VITE_AI_BASE_URL=https://api.deepseek.com
VITE_AI_MODEL=deepseek-chat
# Message types to filter out (comma separated) # Message types to filter out (comma separated)
VITE_FILTER_MSG_TYPES=分享消息,图片,表情包,视频 VITE_FILTER_MSG_TYPES=分享消息,图片,表情包,视频
+59
View File
@@ -0,0 +1,59 @@
name: Build & Release
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: macos-latest
strategy:
matrix:
platform: [x64, arm64]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: '7'
- name: Install Dependencies
run: pnpm install
- name: Build
run: pnpm build
- name: Build DMG
run: pnpm run build:mac:${{ matrix.platform }}
- name: Upload DMG
uses: actions/upload-artifact@v4
with:
name: dmg-${{ matrix.platform }}
path: out/mac-*/WechatExplorer-*.dmg
release:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
pattern: dmg-*
path: artifacts
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: artifacts/**/*
generate_release_notes: true
+1
View File
@@ -5,3 +5,4 @@ out
.DS_Store .DS_Store
.eslintcache .eslintcache
*.log* *.log*
.omc
+7 -5
View File
@@ -22,7 +22,7 @@ MAC系统 获取微信聊天记录 AI一键生成群聊总结
- **聊天记录查看**: 浏览微信好友和群聊的聊天记录。 - **聊天记录查看**: 浏览微信好友和群聊的聊天记录。
- **全局搜索**: 快速搜索聊天内容。 - **全局搜索**: 快速搜索聊天内容。
- **AI 智能总结**: 集成 DeepSeek AI,一键总结群聊精华内容,生成话题报告。 - **AI 智能总结**: 支持多模型服务配置(DeepSeek/GPT-4o/Claude/Moonshot,一键总结群聊精华内容,生成话题报告。
- **图片生成**: 将 AI 总结的内容生成精美图片,方便分享。 - **图片生成**: 将 AI 总结的内容生成精美图片,方便分享。
- **数据导出**: 支持导出聊天记录为 CSV 文件(今日、昨日、近7天或全部)。 - **数据导出**: 支持导出聊天记录为 CSV 文件(今日、昨日、近7天或全部)。
- **安全隐私**: 所有数据仅在本地处理,AI 功能需自行配置 API Key。 - **安全隐私**: 所有数据仅在本地处理,AI 功能需自行配置 API Key。
@@ -31,13 +31,14 @@ MAC系统 获取微信聊天记录 AI一键生成群聊总结
### 使用前置要求 ### 使用前置要求
- 微信>=4.0 无法使用 - **微信版本**: 推荐使用微信 **4.0 以下**版本(4.0以上版本不支持数据库解密)
- 微信<=4.0 需要获取自己微信本地数据库密码 获取方式参考: [Mac 导出微信聊天记录](https://blog.vcvit.me/2024/08/02/mac-export-wechat-chat-records/) - 微信 <= 4.0: 可正常使用,获取数据库密码方式参考:[Mac 导出微信聊天记录](https://blog.vcvit.me/2024/08/02/mac-export-wechat-chat-records/)
- 如果无法获取本地数据库密码 则无法使用当前项目 - 微信 >= 4.0: 如需使用,推荐使用 [WeFlow](https://github.com/hicccc77/WeFlow)
- 如无法获取本地数据库密码,则无法使用当前项目
- Node.js (推荐 v16+) - Node.js (推荐 v16+)
- pnpm@7 - pnpm@7
- 解密后的微信数据库文件 (`.db`) 和对应的密钥 - 解密后的微信数据库文件 (`.db`) 和对应的密钥
- [DeepSeek API Key](https://www.deepseek.com/) (用于 AI 总结功能) - AI API Key(支持 OpenAI 兼容 API,可选 DeepSeek/GPT/Claude/Moonshot 等)
## ⚠️ 免责声明 ## ⚠️ 免责声明
@@ -46,3 +47,4 @@ MAC系统 获取微信聊天记录 AI一键生成群聊总结
## 🔗 参考 ## 🔗 参考
- [WechatMessageExplorer](https://github.com/svcvit/WechatMessageExplorer) - [WechatMessageExplorer](https://github.com/svcvit/WechatMessageExplorer)
- [WeFlow](https://github.com/hicccc77/WeFlow)
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
# 获取当前版本号(从 package.json 读取)
VERSION=$(jq -r '.version' package.json)
# 格式化为新的 tag(在版本号前加上 "v"
TAG="v${VERSION}"
# 输出当前生成的 tag
echo "生成的 tag: $TAG"
# 创建并推送 tag 到远程
git tag $TAG
git push origin $TAG
echo "Tag $TAG 已经推送到远程仓库!"
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "wechatexplorer", "name": "wechatexplorer",
"version": "1.0.3", "version": "1.1.0",
"description": "mac 版本获取微信聊天记录, AI群聊总结助手", "description": "mac 版本获取微信聊天记录, AI群聊总结助手",
"keywords": [ "keywords": [
"wechat", "wechat",
+9
View File
@@ -0,0 +1,9 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_DEEPSEEK_API_KEY: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
+8 -6
View File
@@ -181,22 +181,24 @@ app.whenReady().then(() => {
async ( async (
_, _,
messages: { role: string; content: string }[], messages: { role: string; content: string }[],
options?: { apiKey?: string; model?: string } options?: { apiKey?: string; model?: string; baseURL?: string }
) => { ) => {
// @ts-ignore: vite env // @ts-ignore: vite env
const apiKey = options?.apiKey || import.meta.env.VITE_DEEPSEEK_API_KEY const apiKey = options?.apiKey || import.meta.env.VITE_DEEPSEEK_API_KEY
const model = options?.model || 'deepseek-chat' const model = options?.model || import.meta.env.VITE_AI_MODEL || 'deepseek-chat'
const baseURL =
options?.baseURL || import.meta.env.VITE_AI_BASE_URL || 'https://api.deepseek.com'
if (!apiKey) { if (!apiKey) {
return { success: false, error: '未配置 DeepSeek API Key' } return { success: false, error: '未配置 API Key' }
} }
// 动态导入以避免如果未安装或初始类型缺失的问题 // 动态导入以避免如果未安装或初始类型缺失的问题
const { OpenAI } = await import('openai') const { OpenAI } = await import('openai')
const openai = new OpenAI({ const openai = new OpenAI({
baseURL: 'https://api.deepseek.com', baseURL,
apiKey: apiKey apiKey
}) })
try { try {
const completion = await openai.chat.completions.create({ const completion = await openai.chat.completions.create({
@@ -206,7 +208,7 @@ app.whenReady().then(() => {
}) })
return { success: true, data: completion.choices[0].message.content } return { success: true, data: completion.choices[0].message.content }
} catch (error: unknown) { } catch (error: unknown) {
console.error('DeepSeek API Error:', error) console.error('AI API Error:', error)
const errorMessage = error instanceof Error ? error.message : 'Unknown error' const errorMessage = error instanceof Error ? error.message : 'Unknown error'
return { success: false, error: errorMessage } return { success: false, error: errorMessage }
} }
+26 -6
View File
@@ -52,11 +52,16 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
// AI Settings // AI Settings
const [showSettingsModal, setShowSettingsModal] = useState(false) const [showSettingsModal, setShowSettingsModal] = useState(false)
const [apiKey, setApiKey] = useState(() => localStorage.getItem('deepseek_api_key') || '') const [apiKey, setApiKey] = useState(() => localStorage.getItem('ai_api_key') || '')
const [model, setModel] = useState('deepseek-chat') const [baseURL, setBaseURL] = useState(
() => localStorage.getItem('ai_base_url') || 'https://api.deepseek.com'
)
const [model, setModel] = useState(() => localStorage.getItem('ai_model') || 'deepseek-chat')
const handleSaveSettings = (): void => { const handleSaveSettings = (): void => {
localStorage.setItem('deepseek_api_key', apiKey) localStorage.setItem('ai_api_key', apiKey)
localStorage.setItem('ai_base_url', baseURL)
localStorage.setItem('ai_model', model)
setShowSettingsModal(false) setShowSettingsModal(false)
AIChat() AIChat()
} }
@@ -186,7 +191,7 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
{ role: 'system', content: systemPrompt }, { role: 'system', content: systemPrompt },
{ role: 'user', content: prompt } { role: 'user', content: prompt }
], ],
{ apiKey, model } { apiKey, model, baseURL }
) )
if (result.success && result.data) { if (result.success && result.data) {
@@ -482,22 +487,37 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
<div className="modal-content" onClick={(e) => e.stopPropagation()}> <div className="modal-content" onClick={(e) => e.stopPropagation()}>
<h3>AI </h3> <h3>AI </h3>
<div className="form-group" style={{ marginBottom: '15px' }}> <div className="form-group" style={{ marginBottom: '15px' }}>
<label style={{ display: 'block', marginBottom: '5px' }}>:</label> <label style={{ display: 'block', marginBottom: '5px' }}>:</label>
<select <select
value={model} value={model}
onChange={(e) => setModel(e.target.value)} onChange={(e) => setModel(e.target.value)}
style={{ width: '100%', padding: '8px' }} style={{ width: '100%', padding: '8px' }}
> >
<option value="deepseek-chat">DeepSeek Chat</option> <option value="deepseek-chat">DeepSeek Chat</option>
<option value="gpt-4o">GPT-4o</option>
<option value="gpt-4o-mini">GPT-4o Mini</option>
<option value="gpt-4-turbo">GPT-4 Turbo</option>
<option value="claude-3-5-sonnet-20240620">Claude 3.5 Sonnet</option>
<option value="moonshot-v1-8k">Moonshot V1</option>
</select> </select>
</div> </div>
<div className="form-group" style={{ marginBottom: '15px' }}>
<label style={{ display: 'block', marginBottom: '5px' }}>Base URL:</label>
<input
type="text"
value={baseURL}
onChange={(e) => setBaseURL(e.target.value)}
placeholder="https://api.deepseek.com"
style={{ width: '95%', padding: '8px' }}
/>
</div>
<div className="form-group" style={{ marginBottom: '20px' }}> <div className="form-group" style={{ marginBottom: '20px' }}>
<label style={{ display: 'block', marginBottom: '5px' }}>API Key:</label> <label style={{ display: 'block', marginBottom: '5px' }}>API Key:</label>
<input <input
type="password" type="password"
value={apiKey} value={apiKey}
onChange={(e) => setApiKey(e.target.value)} onChange={(e) => setApiKey(e.target.value)}
placeholder="Enter your DeepSeek API Key" placeholder="Enter your API Key"
style={{ width: '95%', padding: '8px' }} style={{ width: '95%', padding: '8px' }}
/> />
</div> </div>
+2 -1
View File
@@ -1,4 +1,5 @@
{ {
"files": [], "files": [],
"references": [{ "path": "./tsconfig.node.json" }, { "path": "./tsconfig.web.json" }] "references": [{ "path": "./tsconfig.node.json" }, { "path": "./tsconfig.web.json" }],
"include": ["src", "vite-env.d.ts"]
} }
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"extends": "@electron-toolkit/tsconfig/tsconfig.node.json", "extends": "@electron-toolkit/tsconfig/tsconfig.node.json",
"include": ["electron.vite.config.*", "src/main/**/*", "src/preload/**/*", "src/shared/**/*"], "include": ["electron.vite.config.*", "src/main/**/*", "src/preload/**/*", "src/shared/**/*", "src/env.d.ts"],
"compilerOptions": { "compilerOptions": {
"composite": true, "composite": true,
"types": ["electron-vite/node"] "types": ["electron-vite/node"]