fix: 插件更新时保留 data 文件夹 (#1584)
Some checks are pending
Build NapCat Artifacts / Build-Framework (push) Waiting to run
Build NapCat Artifacts / Build-Shell (push) Waiting to run

* fix: 修复 qq_login.tsx 类型错误

- onSelectionChange 的 key 参数可能为 null,添加空值检查

* fix: 插件更新时保留 data 文件夹

- 更新插件时备份 data 文件夹,解压后恢复

- 添加异常处理,确保解压失败时也能恢复 data 文件夹
This commit is contained in:
Qiao 2026-02-03 09:55:21 +08:00 committed by GitHub
parent 74b1da67d8
commit 2dcf8004ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 7 deletions

View File

@ -157,6 +157,8 @@ async function downloadFile (url: string, destPath: string, customMirror?: strin
async function extractPlugin (zipPath: string, pluginId: string): Promise<void> {
const PLUGINS_DIR = getPluginsDir();
const pluginDir = path.join(PLUGINS_DIR, pluginId);
const dataDir = path.join(pluginDir, 'data');
const tempDataDir = path.join(PLUGINS_DIR, `${pluginId}.data.backup`);
console.log(`[extractPlugin] PLUGINS_DIR: ${PLUGINS_DIR}`);
console.log(`[extractPlugin] pluginId: ${pluginId}`);
@ -169,8 +171,19 @@ async function extractPlugin (zipPath: string, pluginId: string): Promise<void>
console.log(`[extractPlugin] Created plugins root directory: ${PLUGINS_DIR}`);
}
// 如果目录已存在,先删除
// 如果目录已存在,先备份 data 文件夹,再删除
let hasDataBackup = false;
if (fs.existsSync(pluginDir)) {
// 备份 data 文件夹
if (fs.existsSync(dataDir)) {
console.log(`[extractPlugin] Backing up data directory: ${dataDir}`);
if (fs.existsSync(tempDataDir)) {
fs.rmSync(tempDataDir, { recursive: true, force: true });
}
fs.renameSync(dataDir, tempDataDir);
hasDataBackup = true;
}
console.log(`[extractPlugin] Directory exists, removing: ${pluginDir}`);
fs.rmSync(pluginDir, { recursive: true, force: true });
}
@ -179,10 +192,35 @@ async function extractPlugin (zipPath: string, pluginId: string): Promise<void>
fs.mkdirSync(pluginDir, { recursive: true });
console.log(`[extractPlugin] Created directory: ${pluginDir}`);
// 解压
await compressing.zip.uncompress(zipPath, pluginDir);
try {
// 解压
await compressing.zip.uncompress(zipPath, pluginDir);
console.log(`[extractPlugin] Plugin extracted to: ${pluginDir}`);
console.log(`[extractPlugin] Plugin extracted to: ${pluginDir}`);
// 恢复 data 文件夹
if (hasDataBackup && fs.existsSync(tempDataDir)) {
// 如果新版本也有 data 文件夹,先删除
if (fs.existsSync(dataDir)) {
fs.rmSync(dataDir, { recursive: true, force: true });
}
console.log(`[extractPlugin] Restoring data directory: ${dataDir}`);
fs.renameSync(tempDataDir, dataDir);
}
} catch (e) {
// 解压失败时,尝试恢复 data 文件夹
if (hasDataBackup && fs.existsSync(tempDataDir)) {
console.log(`[extractPlugin] Extract failed, restoring data directory`);
if (!fs.existsSync(pluginDir)) {
fs.mkdirSync(pluginDir, { recursive: true });
}
if (fs.existsSync(dataDir)) {
fs.rmSync(dataDir, { recursive: true, force: true });
}
fs.renameSync(tempDataDir, dataDir);
}
throw e;
}
// 列出解压后的文件
const files = fs.readdirSync(pluginDir);

View File

@ -112,9 +112,9 @@ export default function QQLoginPage () {
// 仅在扫码登录 Tab 下才弹窗,或者错误不是"二维码已过期"
// 如果是 "二维码已过期",且不在 qrcode tab则不弹窗
const isQrCodeExpired = friendlyMsg.includes('二维码') && (friendlyMsg.includes('过期') || friendlyMsg.includes('失效'));
if (!isQrCodeExpired || activeTab === 'qrcode') {
dialog.alert({
dialog.alert({
title: '登录失败',
content: friendlyMsg,
confirmText: '确定',
@ -222,7 +222,7 @@ export default function QQLoginPage () {
isDisabled={isLoading}
size='lg'
selectedKey={activeTab}
onSelectionChange={(key) => setActiveTab(key.toString())}
onSelectionChange={(key) => key !== null && setActiveTab(key.toString())}
>
<Tab key='shortcut' title='快速登录'>
<QuickLogin