diff --git a/migrations/versions/d4e5f6a7b8c9_add_cookie_manager_menus.py b/migrations/versions/d4e5f6a7b8c9_add_cookie_manager_menus.py new file mode 100644 index 0000000..4f371b9 --- /dev/null +++ b/migrations/versions/d4e5f6a7b8c9_add_cookie_manager_menus.py @@ -0,0 +1,96 @@ +"""add cookie manager menus + +「Cookie管理」一级菜单 + 二级「登录用户」/「登录网站」及各权限点, +此前只在本地库里手工 INSERT 过,从未随迁移分发。 + +由于 data/ 目录被 .gitignore 排除、部署环境数据库是独立 volume, +只同步代码无法带上这些菜单行,导致线上后台看不到 Cookie 管理模块。 + +本迁移以幂等方式补齐: +- 记录不存在 → 插入 +- 已存在但 open_type 为空 → 补齐为 _iframe(兼容早期手工插入的数据) + +不依赖数据库方言的 UPSERT 语法,SQLite / MySQL 均可执行。 + +Revision ID: d4e5f6a7b8c9 +Revises: b2c3d4e5f6a7 +""" +from alembic import op +import sqlalchemy as sa +import datetime + + +# revision identifiers, used by Alembic. +revision = 'd4e5f6a7b8c9' +down_revision = 'b2c3d4e5f6a7' +branch_labels = None +depends_on = None + + +# (id, name, type, code, url, open_type, parent_id, icon, sort, enable) +MENUS = [ + (76, 'Cookie管理', '0', '', '', '', 0, 'layui-icon layui-icon-ear-phone', 5, 1), + (77, '登录用户', '1', 'system:cookie-user:main', '/system/cookie-user/', '_iframe', + 76, 'layui-icon layui-icon-username', 1, 1), + (78, '登录用户新增', '2', 'system:cookie-user:add', '', '', 77, '', 1, 1), + (79, '登录用户编辑', '2', 'system:cookie-user:edit', '', '', 77, '', 2, 1), + (80, '登录用户删除', '2', 'system:cookie-user:remove', '', '', 77, '', 3, 1), + (81, '登录网站', '1', 'system:cookie-site:main', '/system/cookie-site/', '_iframe', + 76, 'layui-icon layui-icon-web', 2, 1), + (82, '登录网站新增', '2', 'system:cookie-site:add', '', '', 81, '', 1, 1), + (83, '登录网站编辑', '2', 'system:cookie-site:edit', '', '', 81, '', 2, 1), + (84, '登录网站删除', '2', 'system:cookie-site:remove', '', '', 81, '', 3, 1), +] + + +def upgrade(): + conn = op.get_bind() + now = datetime.datetime.now() + + for mid, name, mtype, code, url, open_type, parent_id, icon, sort, enable in MENUS: + row = conn.execute( + sa.text("SELECT id, open_type FROM admin_power WHERE id = :id"), + {"id": mid}, + ).fetchone() + + if row is None: + conn.execute( + sa.text( + "INSERT INTO admin_power " + "(id, name, type, code, url, open_type, parent_id, icon, sort, " + " enable, create_time, update_time) " + "VALUES (:id, :name, :type, :code, :url, :open_type, :parent_id, " + " :icon, :sort, :enable, :ct, :ut)" + ), + { + "id": mid, "name": name, "type": mtype, "code": code, + "url": url, "open_type": open_type, "parent_id": parent_id, + "icon": icon, "sort": sort, "enable": enable, + "ct": now, "ut": now, + }, + ) + elif not row[1] and open_type: + # 历史数据:菜单已存在但打开方式为空,补齐 _iframe + conn.execute( + sa.text("UPDATE admin_power SET open_type = :ot WHERE id = :id"), + {"ot": open_type, "id": mid}, + ) + + +def downgrade(): + conn = op.get_bind() + ids = [m[0] for m in MENUS] + + # 先清角色-权限关联,避免外键/脏数据残留 + conn.execute( + sa.text("DELETE FROM admin_role_power WHERE power_id IN :ids").bindparams( + sa.bindparam("ids", expanding=True) + ), + {"ids": ids}, + ) + conn.execute( + sa.text("DELETE FROM admin_power WHERE id IN :ids").bindparams( + sa.bindparam("ids", expanding=True) + ), + {"ids": ids}, + )