8.6 KiB
8.6 KiB
全局配置表迁移实施指南
概述
当前 comindex.uvue 使用的是 key 后缀方式的全局配置(如 company_name_zh),需要迁移到新的主表+翻译表设计。
当前状态分析
当前使用的表结构
-- 原有设计(key后缀方式)
ak_global_configs (
config_key VARCHAR, -- 如: company_name_zh, company_name_en
config_value TEXT,
config_type VARCHAR,
is_active BOOLEAN
)
新设计的表结构
-- 新设计(主表+翻译表)
ak_global_config (
id UUID,
config_key VARCHAR, -- 如: company_name
config_category VARCHAR,
is_translatable BOOLEAN,
default_value TEXT
)
ak_global_config_translations (
config_id UUID,
language_code VARCHAR, -- zh, en, tw, ja
translated_value TEXT
)
迁移步骤
1. 数据库迁移
Step 1: 创建新表结构
# 执行新表结构创建脚本
psql -h your-host -U your-user -d your-db -f improved_global_config_with_translation.sql
Step 2: 数据迁移脚本
创建数据迁移脚本:
-- migrate_global_config_data.sql
DO $$
DECLARE
config_record RECORD;
zh_value TEXT;
en_value TEXT;
tw_value TEXT;
ja_value TEXT;
BEGIN
-- 迁移公司名称
SELECT config_value INTO zh_value FROM ak_global_configs WHERE config_key = 'company_name_zh' AND is_active = true;
SELECT config_value INTO en_value FROM ak_global_configs WHERE config_key = 'company_name_en' AND is_active = true;
SELECT config_value INTO tw_value FROM ak_global_configs WHERE config_key = 'company_name_tw' AND is_active = true;
SELECT config_value INTO ja_value FROM ak_global_configs WHERE config_key = 'company_name_ja' AND is_active = true;
-- 插入主配置
INSERT INTO ak_global_config (config_key, config_category, is_translatable, sort_order)
VALUES ('company_name', 'company', true, 1)
ON CONFLICT (config_key) DO NOTHING;
-- 获取配置ID并插入翻译
SELECT id INTO config_record FROM ak_global_config WHERE config_key = 'company_name';
IF zh_value IS NOT NULL THEN
INSERT INTO ak_global_config_translations (config_id, language_code, translated_value)
VALUES (config_record.id, 'zh', zh_value)
ON CONFLICT (config_id, language_code) DO UPDATE SET translated_value = EXCLUDED.translated_value;
END IF;
IF en_value IS NOT NULL THEN
INSERT INTO ak_global_config_translations (config_id, language_code, translated_value)
VALUES (config_record.id, 'en', en_value)
ON CONFLICT (config_id, language_code) DO UPDATE SET translated_value = EXCLUDED.translated_value;
END IF;
IF tw_value IS NOT NULL THEN
INSERT INTO ak_global_config_translations (config_id, language_code, translated_value)
VALUES (config_record.id, 'tw', tw_value)
ON CONFLICT (config_id, language_code) DO UPDATE SET translated_value = EXCLUDED.translated_value;
END IF;
IF ja_value IS NOT NULL THEN
INSERT INTO ak_global_config_translations (config_id, language_code, translated_value)
VALUES (config_record.id, 'ja', ja_value)
ON CONFLICT (config_id, language_code) DO UPDATE SET translated_value = EXCLUDED.translated_value;
END IF;
-- 迁移公司标语
SELECT config_value INTO zh_value FROM ak_global_configs WHERE config_key = 'company_slogan_zh' AND is_active = true;
SELECT config_value INTO en_value FROM ak_global_configs WHERE config_key = 'company_slogan_en' AND is_active = true;
SELECT config_value INTO tw_value FROM ak_global_configs WHERE config_key = 'company_slogan_tw' AND is_active = true;
SELECT config_value INTO ja_value FROM ak_global_configs WHERE config_key = 'company_slogan_ja' AND is_active = true;
INSERT INTO ak_global_config (config_key, config_category, is_translatable, sort_order)
VALUES ('company_slogan', 'company', true, 2)
ON CONFLICT (config_key) DO NOTHING;
SELECT id INTO config_record FROM ak_global_config WHERE config_key = 'company_slogan';
IF zh_value IS NOT NULL THEN
INSERT INTO ak_global_config_translations (config_id, language_code, translated_value)
VALUES (config_record.id, 'zh', zh_value)
ON CONFLICT (config_id, language_code) DO UPDATE SET translated_value = EXCLUDED.translated_value;
END IF;
IF en_value IS NOT NULL THEN
INSERT INTO ak_global_config_translations (config_id, language_code, translated_value)
VALUES (config_record.id, 'en', en_value)
ON CONFLICT (config_id, language_code) DO UPDATE SET translated_value = EXCLUDED.translated_value;
END IF;
IF tw_value IS NOT NULL THEN
INSERT INTO ak_global_config_translations (config_id, language_code, translated_value)
VALUES (config_record.id, 'tw', tw_value)
ON CONFLICT (config_id, language_code) DO UPDATE SET translated_value = EXCLUDED.translated_value;
END IF;
IF ja_value IS NOT NULL THEN
INSERT INTO ak_global_config_translations (config_id, language_code, translated_value)
VALUES (config_record.id, 'ja', ja_value)
ON CONFLICT (config_id, language_code) DO UPDATE SET translated_value = EXCLUDED.translated_value;
END IF;
-- 继续迁移其他配置项...
-- (公司地址、热门搜索等,按照相同模式)
RAISE NOTICE '数据迁移完成!';
END $$;
2. 前端代码更新
当前代码问题
// 当前使用的旧方式
const result = await supa
.from('ak_global_configs') // 复数表名
.select('*')
.eq('is_active', true)
// 基于语言后缀的配置获取
const nameConfig = companyConfigMap.value.get(`company_name${langSuffix}`)
解决方案
我已经在 comindex.uvue 中添加了新的配置加载函数,它支持:
- 主方法: 使用 RPC 函数
get_config_by_language - 备用方法: 查询视图
vw_global_config_multilingual - 兜底方案: 使用硬编码的默认值
迁移验证
// 测试新配置加载
const testNewConfig = async () => {
try {
const { data, error } = await supa
.rpc('get_config_by_language', { lang_code: 'zh' })
console.log('新配置系统测试:', data)
if (error) {
console.error('RPC调用失败:', error)
// 测试备用方法
const { data: fallbackData } = await supa
.from('vw_global_config_multilingual')
.select('*')
.eq('language_code', 'zh')
.eq('is_active', true)
console.log('备用方法测试:', fallbackData)
}
} catch (e) {
console.error('配置测试失败:', e)
}
}
3. 渐进式迁移策略
阶段1: 并行运行
- 保持原有
ak_global_configs表不变 - 新建
ak_global_config和ak_global_config_translations表 - 前端代码支持两种方式,优先使用新方式
阶段2: 数据同步
- 将原有数据迁移到新表结构
- 验证数据完整性和功能正常性
- 监控性能和错误
阶段3: 完全切换
- 前端代码移除旧方式的兼容代码
- 删除或重命名原有表(如有需要)
4. 验证清单
数据验证
- 所有配置项都已迁移到新表
- 多语言翻译完整且正确
- 配置分类和排序正确
- 非翻译配置项的默认值正确
功能验证
- 页面加载时配置正确显示
- 语言切换时配置正确更新
- 错误处理和默认值生效
- 性能满足要求
兼容性验证
- 新旧系统可以并行运行
- 备用方案正常工作
- 数据回滚方案可行
5. 回滚计划
如果迁移出现问题,可以:
- 立即回滚: 在前端代码中禁用新配置方式
- 数据回滚: 从备份恢复原有表数据
- 配置回滚: 重新启用旧的配置获取逻辑
6. 监控和优化
性能监控
- 配置加载时间
- 数据库查询性能
- 错误率和成功率
优化建议
- 配置数据缓存
- 批量查询优化
- 索引优化
部署建议
测试环境部署
- 执行
improved_global_config_with_translation.sql - 执行数据迁移脚本
- 部署更新后的前端代码
- 进行功能测试
生产环境部署
- 维护窗口期间执行数据库迁移
- 部署前端代码更新
- 监控系统运行状况
- 准备快速回滚方案
总结
新的全局配置系统提供了:
- ✅ 更科学的数据结构设计
- ✅ 更易维护的多语言支持
- ✅ 更好的扩展性和灵活性
- ✅ 向后兼容的迁移方案
通过渐进式迁移,可以确保业务连续性,同时升级到更现代化的配置管理方案。