package migration import ( "time" ) // GetAllMigrations 返回所有迁移定义 func GetAllMigrations() []Migration { return []Migration{ { Version: "20250101_000001", Description: "Create initial tables - users, categories, photos", Timestamp: time.Date(2025, 1, 1, 0, 0, 1, 0, time.UTC), UpSQL: ` -- 用户表 CREATE TABLE IF NOT EXISTS user ( id INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, email VARCHAR(100) UNIQUE NOT NULL, avatar VARCHAR(255) DEFAULT '', status INTEGER DEFAULT 1, -- 1:启用 0:禁用 created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 分类表 CREATE TABLE IF NOT EXISTS category ( id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(100) NOT NULL, description TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 照片表 CREATE TABLE IF NOT EXISTS photo ( id INTEGER PRIMARY KEY AUTOINCREMENT, title VARCHAR(255) NOT NULL, description TEXT, file_path VARCHAR(500) NOT NULL, thumbnail_path VARCHAR(500), user_id INTEGER NOT NULL, category_id INTEGER, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES user(id), FOREIGN KEY (category_id) REFERENCES category(id) ); -- 创建索引 CREATE INDEX IF NOT EXISTS idx_user_username ON user(username); CREATE INDEX IF NOT EXISTS idx_user_email ON user(email); CREATE INDEX IF NOT EXISTS idx_photo_user_id ON photo(user_id); CREATE INDEX IF NOT EXISTS idx_photo_category_id ON photo(category_id); CREATE INDEX IF NOT EXISTS idx_photo_created_at ON photo(created_at); `, DownSQL: ` -- 删除索引 DROP INDEX IF EXISTS idx_photo_created_at; DROP INDEX IF EXISTS idx_photo_category_id; DROP INDEX IF EXISTS idx_photo_user_id; DROP INDEX IF EXISTS idx_user_email; DROP INDEX IF EXISTS idx_user_username; -- 删除表(注意外键约束,先删除依赖表) DROP TABLE IF EXISTS photo; DROP TABLE IF EXISTS category; DROP TABLE IF EXISTS user; `, }, { Version: "20250101_000002", Description: "Insert default admin user and categories", Timestamp: time.Date(2025, 1, 1, 0, 0, 2, 0, time.UTC), UpSQL: ` -- 插入默认管理员用户 INSERT OR IGNORE INTO user (username, password, email, avatar, status) VALUES ('admin', '$2a$10$K8H7YjN5hOcE0zWTz1YuAuYqFyQ9cqUdFHJgJdKxA5wGv3LUQHgKq', 'admin@example.com', '', 1); -- 密码是 admin123 的 bcrypt 哈希 -- 插入默认分类 INSERT OR IGNORE INTO category (name, description) VALUES ('风景', '自然风景摄影作品'), ('人像', '人物肖像摄影作品'), ('建筑', '建筑摄影作品'), ('街拍', '街头摄影作品'); `, DownSQL: ` -- 删除默认数据(保留用户数据的完整性) DELETE FROM photo WHERE category_id IN (SELECT id FROM category WHERE name IN ('风景', '人像', '建筑', '街拍')); DELETE FROM category WHERE name IN ('风景', '人像', '建筑', '街拍'); DELETE FROM user WHERE username = 'admin' AND email = 'admin@example.com'; `, }, { Version: "20250111_000001", Description: "Add photo metadata fields - EXIF data, tags, location", Timestamp: time.Date(2025, 1, 11, 0, 0, 1, 0, time.UTC), UpSQL: ` -- 为照片表添加元数据字段 ALTER TABLE photo ADD COLUMN exif_data TEXT DEFAULT '{}'; ALTER TABLE photo ADD COLUMN tags VARCHAR(500) DEFAULT ''; ALTER TABLE photo ADD COLUMN location VARCHAR(200) DEFAULT ''; ALTER TABLE photo ADD COLUMN camera_model VARCHAR(100) DEFAULT ''; ALTER TABLE photo ADD COLUMN lens_model VARCHAR(100) DEFAULT ''; ALTER TABLE photo ADD COLUMN focal_length INTEGER DEFAULT 0; ALTER TABLE photo ADD COLUMN aperture VARCHAR(10) DEFAULT ''; ALTER TABLE photo ADD COLUMN shutter_speed VARCHAR(20) DEFAULT ''; ALTER TABLE photo ADD COLUMN iso INTEGER DEFAULT 0; ALTER TABLE photo ADD COLUMN flash_used BOOLEAN DEFAULT FALSE; ALTER TABLE photo ADD COLUMN orientation INTEGER DEFAULT 1; -- 创建标签索引(用于搜索) CREATE INDEX IF NOT EXISTS idx_photo_tags ON photo(tags); CREATE INDEX IF NOT EXISTS idx_photo_location ON photo(location); `, DownSQL: ` -- 删除索引 DROP INDEX IF EXISTS idx_photo_location; DROP INDEX IF EXISTS idx_photo_tags; -- 注意:SQLite 不支持 DROP COLUMN,需要重建表 -- 创建临时表(不包含新添加的列) CREATE TABLE photo_temp ( id INTEGER PRIMARY KEY AUTOINCREMENT, title VARCHAR(255) NOT NULL, description TEXT, file_path VARCHAR(500) NOT NULL, thumbnail_path VARCHAR(500), user_id INTEGER NOT NULL, category_id INTEGER, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES user(id), FOREIGN KEY (category_id) REFERENCES category(id) ); -- 复制数据 INSERT INTO photo_temp (id, title, description, file_path, thumbnail_path, user_id, category_id, created_at, updated_at) SELECT id, title, description, file_path, thumbnail_path, user_id, category_id, created_at, updated_at FROM photo; -- 删除原表 DROP TABLE photo; -- 重命名临时表 ALTER TABLE photo_temp RENAME TO photo; -- 重新创建索引 CREATE INDEX IF NOT EXISTS idx_photo_user_id ON photo(user_id); CREATE INDEX IF NOT EXISTS idx_photo_category_id ON photo(category_id); CREATE INDEX IF NOT EXISTS idx_photo_created_at ON photo(created_at); `, }, { Version: "20250111_000002", Description: "Create photo collections and favorites system", Timestamp: time.Date(2025, 1, 11, 0, 0, 2, 0, time.UTC), UpSQL: ` -- 照片集合表 CREATE TABLE IF NOT EXISTS collection ( id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(100) NOT NULL, description TEXT, user_id INTEGER NOT NULL, is_public BOOLEAN DEFAULT FALSE, cover_photo_id INTEGER, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES user(id), FOREIGN KEY (cover_photo_id) REFERENCES photo(id) ); -- 照片集合关联表(多对多) CREATE TABLE IF NOT EXISTS collection_photo ( id INTEGER PRIMARY KEY AUTOINCREMENT, collection_id INTEGER NOT NULL, photo_id INTEGER NOT NULL, sort_order INTEGER DEFAULT 0, added_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (collection_id) REFERENCES collection(id) ON DELETE CASCADE, FOREIGN KEY (photo_id) REFERENCES photo(id) ON DELETE CASCADE, UNIQUE(collection_id, photo_id) ); -- 用户收藏表 CREATE TABLE IF NOT EXISTS user_favorite ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, photo_id INTEGER NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE, FOREIGN KEY (photo_id) REFERENCES photo(id) ON DELETE CASCADE, UNIQUE(user_id, photo_id) ); -- 创建索引 CREATE INDEX IF NOT EXISTS idx_collection_user_id ON collection(user_id); CREATE INDEX IF NOT EXISTS idx_collection_public ON collection(is_public); CREATE INDEX IF NOT EXISTS idx_collection_photo_collection ON collection_photo(collection_id); CREATE INDEX IF NOT EXISTS idx_collection_photo_photo ON collection_photo(photo_id); CREATE INDEX IF NOT EXISTS idx_user_favorite_user ON user_favorite(user_id); CREATE INDEX IF NOT EXISTS idx_user_favorite_photo ON user_favorite(photo_id); `, DownSQL: ` -- 删除索引 DROP INDEX IF EXISTS idx_user_favorite_photo; DROP INDEX IF EXISTS idx_user_favorite_user; DROP INDEX IF EXISTS idx_collection_photo_photo; DROP INDEX IF EXISTS idx_collection_photo_collection; DROP INDEX IF EXISTS idx_collection_public; DROP INDEX IF EXISTS idx_collection_user_id; -- 删除表 DROP TABLE IF EXISTS user_favorite; DROP TABLE IF EXISTS collection_photo; DROP TABLE IF EXISTS collection; `, }, { Version: "20250111_000003", Description: "Add user profile and preferences", Timestamp: time.Date(2025, 1, 11, 0, 0, 3, 0, time.UTC), UpSQL: ` -- 为用户表添加更多字段 ALTER TABLE user ADD COLUMN bio TEXT DEFAULT ''; ALTER TABLE user ADD COLUMN website VARCHAR(255) DEFAULT ''; ALTER TABLE user ADD COLUMN location VARCHAR(100) DEFAULT ''; ALTER TABLE user ADD COLUMN birth_date DATE; ALTER TABLE user ADD COLUMN phone VARCHAR(20) DEFAULT ''; ALTER TABLE user ADD COLUMN is_verified BOOLEAN DEFAULT FALSE; ALTER TABLE user ADD COLUMN last_login_at DATETIME; -- 用户设置表 CREATE TABLE IF NOT EXISTS user_setting ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER UNIQUE NOT NULL, theme VARCHAR(20) DEFAULT 'light', -- light, dark, auto language VARCHAR(10) DEFAULT 'zh-CN', timezone VARCHAR(50) DEFAULT 'Asia/Shanghai', email_notifications BOOLEAN DEFAULT TRUE, public_profile BOOLEAN DEFAULT TRUE, show_exif BOOLEAN DEFAULT TRUE, watermark_enabled BOOLEAN DEFAULT FALSE, watermark_text VARCHAR(100) DEFAULT '', watermark_position VARCHAR(20) DEFAULT 'bottom-right', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE ); -- 为新字段创建索引 CREATE INDEX IF NOT EXISTS idx_user_verified ON user(is_verified); CREATE INDEX IF NOT EXISTS idx_user_last_login ON user(last_login_at); `, DownSQL: ` -- 删除索引 DROP INDEX IF EXISTS idx_user_last_login; DROP INDEX IF EXISTS idx_user_verified; -- 删除用户设置表 DROP TABLE IF EXISTS user_setting; -- SQLite 不支持 DROP COLUMN,需要重建用户表 CREATE TABLE user_temp ( id INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, email VARCHAR(100) UNIQUE NOT NULL, avatar VARCHAR(255) DEFAULT '', status INTEGER DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 复制原始数据 INSERT INTO user_temp (id, username, password, email, avatar, status, created_at, updated_at) SELECT id, username, password, email, avatar, status, created_at, updated_at FROM user; -- 删除原表 DROP TABLE user; -- 重命名临时表 ALTER TABLE user_temp RENAME TO user; -- 重新创建索引 CREATE INDEX IF NOT EXISTS idx_user_username ON user(username); CREATE INDEX IF NOT EXISTS idx_user_email ON user(email); `, }, } } // GetMigrationByVersion 根据版本号获取迁移 func GetMigrationByVersion(version string) *Migration { migrations := GetAllMigrations() for _, migration := range migrations { if migration.Version == version { return &migration } } return nil } // GetLatestMigrationVersion 获取最新的迁移版本 func GetLatestMigrationVersion() string { migrations := GetAllMigrations() if len(migrations) == 0 { return "" } latest := migrations[0] for _, migration := range migrations { if migration.Version > latest.Version { latest = migration } } return latest.Version }