增加仅切换注册表功能,防止覆盖删除数据

This commit is contained in:
2025-10-11 16:10:12 +08:00
parent 9cd1abfe75
commit 8de12dbcfc
3 changed files with 114 additions and 19 deletions
+8
View File
@@ -1262,6 +1262,14 @@ router.put('/registry/config', async (req, res) => {
// 更新配置 // 更新配置
const updatedConfig = await downloadService.cacheConfigManager.updateConfig(updateData); const updatedConfig = await downloadService.cacheConfigManager.updateConfig(updateData);
// 如果更新了存储模式,需要重新加载存储模式配置
if (storageMode) {
const reloadResult = await downloadService.downloadRegistry.reloadStorageMode();
if (!reloadResult.success) {
logger.warn('重新加载存储模式失败:', reloadResult.error);
}
}
res.json({ res.json({
success: true, success: true,
data: { data: {
+27
View File
@@ -73,6 +73,33 @@ class DownloadRegistry {
} }
} }
/**
* 重新加载存储模式配置(用于切换存储模式时)
*/
async reloadStorageMode() {
try {
await this.loadStorageMode();
// 根据新的存储模式重新初始化相应的存储
if (this.storageMode === 'database') {
if (!this.registryDatabase && this.databaseManager) {
await this.initDatabaseStorage();
}
} else {
// JSON模式下确保注册表已加载
if (!this.loaded) {
await this.initJsonStorage();
}
}
logger.info(`存储模式已切换到: ${this.storageMode}`);
return { success: true, storageMode: this.storageMode };
} catch (error) {
logger.error('重新加载存储模式失败:', error);
return { success: false, error: error.message };
}
}
/** /**
* 初始化数据库存储 * 初始化数据库存储
*/ */
+64 -4
View File
@@ -111,6 +111,40 @@
</span> </span>
</div> </div>
<!-- 迁移选项 -->
<div v-if="hasStorageModeChanges" class="migration-options">
<div class="migration-option-title">切换方式选择</div>
<div class="migration-option-group">
<div class="migration-option" :class="{ active: migrationMode === 'switch-only' }">
<label>
<input type="radio" v-model="migrationMode" value="switch-only" />
<div class="option-content">
<div class="option-header">
<SvgIcon name="switch" class="option-icon" />
<span class="option-title">仅切换读取方式</span>
<span class="option-badge safe">安全</span>
</div>
<small class="option-description">只改变数据读取方式不迁移数据保持两边数据独立</small>
</div>
</label>
</div>
<div class="migration-option" :class="{ active: migrationMode === 'migrate-data' }">
<label>
<input type="radio" v-model="migrationMode" value="migrate-data" />
<div class="option-content">
<div class="option-header">
<SvgIcon name="transfer" class="option-icon" />
<span class="option-title">迁移数据并切换</span>
<span class="option-badge warning">覆盖</span>
</div>
<small class="option-description">将当前数据迁移到目标存储并切换会覆盖目标存储的现有数据</small>
</div>
</label>
</div>
</div>
</div>
<div class="action-buttons"> <div class="action-buttons">
<button <button
@click="applyStorageModeConfig" @click="applyStorageModeConfig"
@@ -118,7 +152,7 @@
:disabled="migrationLoading || !hasStorageModeChanges || (selectedStorageMode === 'database' && !databaseConnected)" :disabled="migrationLoading || !hasStorageModeChanges || (selectedStorageMode === 'database' && !databaseConnected)"
> >
<SvgIcon name="save" class="btn-icon" /> <SvgIcon name="save" class="btn-icon" />
{{ migrationLoading ? '应用中...' : '应用配置' }} {{ migrationLoading ? '应用中...' : getApplyButtonText() }}
</button> </button>
<button <button
@@ -322,12 +356,22 @@ const databaseConnected = ref(false);
const storageMode = ref<'json' | 'database'>('json'); const storageMode = ref<'json' | 'database'>('json');
const selectedStorageMode = ref<'json' | 'database'>('json'); // 用户选择的存储模式 const selectedStorageMode = ref<'json' | 'database'>('json'); // 用户选择的存储模式
const migrationLoading = ref(false); const migrationLoading = ref(false);
const migrationMode = ref<'switch-only' | 'migrate-data'>('switch-only'); // 迁移模式选择
// 计算属性:检查存储模式是否有变更 // 计算属性:检查存储模式是否有变更
const hasStorageModeChanges = computed(() => { const hasStorageModeChanges = computed(() => {
return selectedStorageMode.value !== storageMode.value; return selectedStorageMode.value !== storageMode.value;
}); });
// 计算应用按钮文本
const getApplyButtonText = () => {
if (migrationMode.value === 'switch-only') {
return '仅切换读取方式';
} else {
return '迁移数据并切换';
}
};
// 从store中获取响应式数据 // 从store中获取响应式数据
const { stats, loading, error, config } = storeToRefs(registryStore); const { stats, loading, error, config } = storeToRefs(registryStore);
@@ -652,9 +696,17 @@ const applyStorageModeConfig = async () => {
return; return;
} }
const confirmMessage = selectedStorageMode.value === 'database' // 根据迁移模式生成不同的确认消息
? '确定要切换到数据库存储模式吗?这将使用MySQL数据库存储注册表数据。' let confirmMessage = '';
: '确定要切换到JSON文件存储模式吗?这将使用本地JSON文件存储注册表数据。'; if (migrationMode.value === 'switch-only') {
confirmMessage = selectedStorageMode.value === 'database'
? '确定要切换到数据库存储模式吗?这将仅改变读取方式,不会迁移现有数据。'
: '确定要切换到JSON文件存储模式吗?这将仅改变读取方式,不会迁移现有数据。';
} else {
confirmMessage = selectedStorageMode.value === 'database'
? '确定要迁移数据并切换到数据库存储模式吗?这将把JSON数据迁移到数据库并覆盖数据库中的现有数据。'
: '确定要迁移数据并切换到JSON文件存储模式吗?这将把数据库数据迁移到JSON文件并覆盖JSON文件中的现有数据。';
}
if (!confirm(confirmMessage)) { if (!confirm(confirmMessage)) {
return; return;
@@ -663,6 +715,8 @@ const applyStorageModeConfig = async () => {
try { try {
migrationLoading.value = true; migrationLoading.value = true;
if (migrationMode.value === 'migrate-data') {
// 执行数据迁移
if (selectedStorageMode.value === 'database') { if (selectedStorageMode.value === 'database') {
// 从JSON迁移到数据库 // 从JSON迁移到数据库
const result = await databaseService.migrateData('json-to-db'); const result = await databaseService.migrateData('json-to-db');
@@ -682,6 +736,12 @@ const applyStorageModeConfig = async () => {
throw new Error(result.error || '迁移到JSON失败'); throw new Error(result.error || '迁移到JSON失败');
} }
} }
} else {
// 仅切换存储模式,不迁移数据
storageMode.value = selectedStorageMode.value;
const modeText = selectedStorageMode.value === 'database' ? '数据库存储' : 'JSON文件存储';
showSuccess(`已切换到${modeText}模式,数据读取方式已更改`);
}
// 保存存储模式配置到后端 // 保存存储模式配置到后端
await saveStorageModeConfig(selectedStorageMode.value); await saveStorageModeConfig(selectedStorageMode.value);