Skip to content

Commit b766e05

Browse files
committed
feat: add warning card for db key
1 parent d13e1dc commit b766e05

6 files changed

Lines changed: 103 additions & 7 deletions

File tree

frontend/composables/useApi.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,13 @@ export const useApi = () => {
358358
method: 'GET',
359359
})
360360
}
361-
361+
362+
const getWxStatus = () => {
363+
return useFetch('/api/wechat/status', {
364+
method: 'GET',
365+
})
366+
}
367+
362368
return {
363369
detectWechat,
364370
detectCurrentAccount,
@@ -392,5 +398,6 @@ export const useApi = () => {
392398
getWrappedAnnualCard,
393399
getDbKey,
394400
getImageKey,
401+
getWxStatus,
395402
}
396403
}

frontend/pages/decrypt.vue

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,19 @@
361361
</div>
362362
</div>
363363
</div>
364+
365+
<!-- 警告渲染 -->
366+
<transition name="fade">
367+
<div v-if="warning" class="bg-amber-50 border border-amber-200 rounded-lg p-4 mt-6 flex items-start">
368+
<svg class="h-5 w-5 mr-2 flex-shrink-0 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
369+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
370+
</svg>
371+
<div>
372+
<p class="font-semibold text-amber-800">温馨提示</p>
373+
<p class="text-sm mt-1 text-amber-700">{{ warning }}</p>
374+
</div>
375+
</div>
376+
</transition>
364377

365378
<!-- 错误提示 -->
366379
<transition name="fade">
@@ -403,10 +416,11 @@
403416
import { ref, reactive, computed, onMounted } from 'vue'
404417
import { useApi } from '~/composables/useApi'
405418
406-
const { decryptDatabase, saveMediaKeys, getSavedKeys, getDbKey, getImageKey } = useApi()
419+
const { decryptDatabase, saveMediaKeys, getSavedKeys, getDbKey, getImageKey, getWxStatus } = useApi()
407420
408421
const loading = ref(false)
409422
const error = ref('')
423+
const warning = ref('') // 警告,用于密钥提示
410424
const currentStep = ref(0)
411425
const mediaAccount = ref('')
412426
const isGettingDbKey = ref(false)
@@ -496,10 +510,29 @@ const handleGetDbKey = async () => {
496510
isGettingDbKey.value = true
497511
498512
error.value = ''
499-
513+
warning.value = ''
500514
formErrors.key = ''
501515
502516
try {
517+
const { data: statusData, error: statusError } = await getWxStatus()
518+
519+
if (statusError.value) {
520+
error.value = '无法获取微信状态: ' + statusError.value.message
521+
isGettingDbKey.value = false
522+
return
523+
}
524+
525+
const wxStatus = statusData.value?.wx_status
526+
527+
if (wxStatus?.is_running) {
528+
warning.value = '检测到微信正在运行,5秒后将终止进程并重启以获取密钥!!'
529+
await new Promise(resolve => setTimeout(resolve, 5000))
530+
} else {
531+
// 没有逻辑
532+
}
533+
534+
warning.value = '正在启动微信以获取密钥,请确保微信未开启“自动登录”,并在启动后 1 分钟内完成登录操作。'
535+
503536
const { data, error: fetchError } = await getDbKey()
504537
505538
if (fetchError.value) {
@@ -509,14 +542,14 @@ const handleGetDbKey = async () => {
509542
510543
const res = data.value
511544
512-
if (res && (res.status === 0)) {
545+
if (res && res.status === 0) {
513546
if (res.data?.db_key) {
514547
formData.key = res.data.db_key
548+
warning.value = ''
515549
}
516550
517-
// 有错误信息且不是ok时弹出提示
518551
if (res.errmsg && res.errmsg !== 'ok') {
519-
error.value = res.errmsg
552+
warning.value = res.errmsg
520553
}
521554
} else {
522555
error.value = '获取失败: ' + (res?.errmsg || '未知错误')
@@ -536,6 +569,7 @@ const handleGetImageKey = async () => {
536569
manualKeyErrors.aes_key = ''
537570
538571
error.value = ''
572+
warning.value = ''
539573
540574
try {
541575
const { data, fetchError } = await getImageKey()
@@ -573,6 +607,7 @@ const applyManualKeys = () => {
573607
manualKeyErrors.xor_key = ''
574608
manualKeyErrors.aes_key = ''
575609
error.value = ''
610+
warning.value = ''
576611
577612
const aes = normalizeAesKey(manualKeys.aes_key)
578613
if (!aes.ok) {
@@ -666,6 +701,7 @@ const handleDecrypt = async () => {
666701
667702
loading.value = true
668703
error.value = ''
704+
warning.value = ''
669705
670706
try {
671707
const result = await decryptDatabase({
@@ -712,6 +748,7 @@ const decryptAllImages = async () => {
712748
mediaDecrypting.value = true
713749
mediaDecryptResult.value = null
714750
error.value = ''
751+
warning.value = ''
715752
716753
// 重置进度
717754
decryptProgress.current = 0
@@ -787,6 +824,7 @@ const decryptAllImages = async () => {
787824
// 从密钥步骤进入图片解密步骤
788825
const goToMediaDecryptStep = async () => {
789826
error.value = ''
827+
warning.value = ''
790828
// 校验并应用(未填写则允许直接进入,后端会使用已保存密钥或报错提示)
791829
const ok = applyManualKeys()
792830
if (!ok || manualKeyErrors.xor_key || manualKeyErrors.aes_key) return

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dependencies = [
2020
"pilk>=0.2.4",
2121
"pypinyin>=0.53.0",
2222
"wx_key",
23+
"packaging",
2324
]
2425

2526
[project.optional-dependencies]

src/wechat_decrypt_tool/routers/keys.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from fastapi import APIRouter
44

55
from ..key_store import get_account_keys_from_store
6+
from ..key_service import get_db_key_workflow
67
from ..media_helpers import _load_media_keys, _resolve_account_dir
78
from ..path_fix import PathFixRoute
89

src/wechat_decrypt_tool/routers/wechat_detection.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from typing import Optional
2-
2+
import psutil
33
from fastapi import APIRouter
44

55
from ..logging_config import get_logger
@@ -71,3 +71,49 @@ async def detect_current_account(data_root_path: Optional[str] = None):
7171
'error': str(e),
7272
'data': None,
7373
}
74+
75+
76+
@router.get("/api/wechat/status", summary="检查微信运行状态")
77+
async def check_wechat_status():
78+
"""
79+
检查系统中是否有 Weixin.exe 或 WeChat.exe 进程在运行
80+
返回: status=0 成功, wx_status={is_running: bool, pid: int, ...}
81+
"""
82+
process_name_targets = ["Weixin.exe", "WeChat.exe"]
83+
84+
wx_status = {
85+
"is_running": False,
86+
"pid": None,
87+
"exe_path": None,
88+
"memory_usage_mb": 0.0
89+
}
90+
91+
try:
92+
for proc in psutil.process_iter(['pid', 'name', 'exe', 'memory_info']):
93+
try:
94+
if proc.info['name'] and proc.info['name'] in process_name_targets:
95+
wx_status["is_running"] = True
96+
wx_status["pid"] = proc.info['pid']
97+
wx_status["exe_path"] = proc.info['exe']
98+
99+
mem = proc.info['memory_info']
100+
if mem:
101+
wx_status["memory_usage_mb"] = round(mem.rss / (1024 * 1024), 2)
102+
103+
break
104+
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
105+
continue
106+
107+
return {
108+
"status": 0,
109+
"errmsg": "ok",
110+
"wx_status": wx_status
111+
}
112+
113+
except Exception as e:
114+
# 即使出错也返回 JSON,但 status 非 0
115+
return {
116+
"status": -1,
117+
"errmsg": f"检查进程失败: {str(e)}",
118+
"wx_status": wx_status
119+
}

uv.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)