diff --git a/backend/auth/__pycache__/init_data.cpython-313.pyc b/backend/auth/__pycache__/init_data.cpython-313.pyc index 501cd71..ba6fff6 100644 Binary files a/backend/auth/__pycache__/init_data.cpython-313.pyc and b/backend/auth/__pycache__/init_data.cpython-313.pyc differ diff --git a/backend/auth/__pycache__/models.cpython-313.pyc b/backend/auth/__pycache__/models.cpython-313.pyc index 9ab9849..c064206 100644 Binary files a/backend/auth/__pycache__/models.cpython-313.pyc and b/backend/auth/__pycache__/models.cpython-313.pyc differ diff --git a/backend/auth/__pycache__/schemas.cpython-313.pyc b/backend/auth/__pycache__/schemas.cpython-313.pyc index d8aee0c..61b0b9e 100644 Binary files a/backend/auth/__pycache__/schemas.cpython-313.pyc and b/backend/auth/__pycache__/schemas.cpython-313.pyc differ diff --git a/backend/auth/apps/permissions/__pycache__/urls.cpython-313.pyc b/backend/auth/apps/permissions/__pycache__/urls.cpython-313.pyc index 308c4b6..8f9f371 100644 Binary files a/backend/auth/apps/permissions/__pycache__/urls.cpython-313.pyc and b/backend/auth/apps/permissions/__pycache__/urls.cpython-313.pyc differ diff --git a/backend/auth/apps/permissions/urls.py b/backend/auth/apps/permissions/urls.py index cdb9adb..02455f3 100644 --- a/backend/auth/apps/permissions/urls.py +++ b/backend/auth/apps/permissions/urls.py @@ -2,12 +2,14 @@ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from fastcrud import FastCRUD +from typing import Dict, Any from database import get_db from models import Permission, Role from schemas import ( PermissionCreate, PermissionResponse, + PermissionTreeResponse, RolePermissionAssign, RolePermissionResponse, ) @@ -37,6 +39,7 @@ async def create_permission( db_permission = Permission( name=permission_data.name, code=permission_data.code, + parentid=permission_data.parentid, description=permission_data.description, ) @@ -58,6 +61,40 @@ async def get_permissions( return permissions +@router.get("/tree", response_model=list[PermissionTreeResponse]) +async def get_permission_tree( + db: AsyncSession = Depends(get_db), + current_user: User = Depends(get_current_user), +): + """获取权限树形结构(基于 parentid)""" + # 获取所有权限 + result = await db.execute(select(Permission)) + permissions = result.scalars().all() + + # 转换为字典,便于查找 + perm_dict = {perm.id: { + "id": perm.id, + "name": perm.name, + "code": perm.code, + "parentid": perm.parentid, + "description": perm.description, + "children": [] + } for perm in permissions} + + # 构建树形结构 + tree = [] + for perm_id, perm_data in perm_dict.items(): + parentid = perm_data["parentid"] + if parentid == 0: + # 顶级节点 + tree.append(perm_data) + elif parentid in perm_dict: + # 子节点,添加到父节点的 children + perm_dict[parentid]["children"].append(perm_data) + + return tree + + @router.get("/{permission_id}", response_model=PermissionResponse) async def get_permission( permission_id: int, diff --git a/backend/auth/booksystem.db b/backend/auth/booksystem.db deleted file mode 100644 index e67a57a..0000000 Binary files a/backend/auth/booksystem.db and /dev/null differ diff --git a/backend/auth/init_data.py b/backend/auth/init_data.py index 6afc64b..ab64344 100644 --- a/backend/auth/init_data.py +++ b/backend/auth/init_data.py @@ -1,66 +1,129 @@ from sqlalchemy.ext.asyncio import AsyncSession -from sqlalchemy import select +from sqlalchemy import select, text from models import Role, User, Permission from utils.password import get_password_hash +async def ensure_permission_table_structure(db: AsyncSession): + """确保 permission 表结构符合最新要求""" + print("检查并更新 permission 表结构...") + + # 检查表是否存在 + result = await db.execute( + text("SELECT table_name FROM information_schema.tables WHERE table_name = 'permission'") + ) + table_exists = result.scalar_one_or_none() + + if not table_exists: + print("permission 表不存在,将由 SQLAlchemy 创建") + return + + # 检查是否缺少 parentid 字段 + result = await db.execute( + text("SELECT column_name FROM information_schema.columns WHERE table_name = 'permission'") + ) + existing_columns = {row[0] for row in result.fetchall()} + + # 添加 parentid 字段 + if 'parentid' not in existing_columns: + try: + await db.execute(text("ALTER TABLE permission ADD COLUMN IF NOT EXISTS parentid INTEGER DEFAULT 0")) + print("添加 parentid 字段成功") + except Exception as e: + print(f"添加 parentid 字段失败: {e}") + + # 删除旧字段(如果存在) + for old_column in ['module', 'submodule', 'action']: + if old_column in existing_columns: + try: + await db.execute(text(f"ALTER TABLE permission DROP COLUMN IF EXISTS {old_column}")) + print(f"删除旧字段 {old_column} 成功") + except Exception as e: + print(f"删除旧字段 {old_column} 失败: {e}") + + await db.commit() + print("permission 表结构更新完成") + + async def init_permissions(db: AsyncSession): - """初始化权限数据""" - # 定义需要初始化的权限 - required_permissions = [ - {"name": "用户管理", "code": "user:manage", "description": "用户管理权限"}, - {"name": "用户查询", "code": "user:read", "description": "用户查询权限"}, - {"name": "用户创建", "code": "user:create", "description": "用户创建权限"}, - {"name": "用户更新", "code": "user:update", "description": "用户更新权限"}, - {"name": "用户删除", "code": "user:delete", "description": "用户删除权限"}, - {"name": "角色管理", "code": "role:manage", "description": "角色管理权限"}, - {"name": "角色查询", "code": "role:read", "description": "角色查询权限"}, - {"name": "角色创建", "code": "role:create", "description": "角色创建权限"}, - {"name": "角色更新", "code": "role:update", "description": "角色更新权限"}, - {"name": "角色删除", "code": "role:delete", "description": "角色删除权限"}, - {"name": "权限管理", "code": "permission:manage", "description": "权限管理权限"}, - {"name": "权限查询", "code": "permission:read", "description": "权限查询权限"}, - {"name": "权限创建", "code": "permission:create", "description": "权限创建权限"}, - {"name": "权限更新", "code": "permission:update", "description": "权限更新权限"}, - {"name": "权限删除", "code": "permission:delete", "description": "权限删除权限"}, + """初始化权限数据(树形结构)""" + # 定义需要初始化的权限(树形结构) + # parentid: 0 = 顶级模块, >0 = 子权限 + permission_tree = [ + # 顶级模块 + {"name": "权限管理", "code": "perm", "parentid": 0, "description": "权限管理模块"}, + + # 二级子模块 + {"name": "用户管理", "code": "perm:user", "parentid": 1, "description": "用户管理子模块"}, + {"name": "角色管理", "code": "perm:role", "parentid": 1, "description": "角色管理子模块"}, + {"name": "权限配置", "code": "perm:config", "parentid": 1, "description": "权限配置子模块"}, + + # 用户管理操作 + {"name": "查看列表", "code": "perm:user:list", "parentid": 2, "description": "查看用户列表"}, + {"name": "查看详情", "code": "perm:user:detail", "parentid": 2, "description": "查看用户详情"}, + {"name": "搜索", "code": "perm:user:search", "parentid": 2, "description": "搜索用户"}, + {"name": "创建", "code": "perm:user:create", "parentid": 2, "description": "创建新用户"}, + {"name": "编辑", "code": "perm:user:edit", "parentid": 2, "description": "编辑用户信息"}, + {"name": "删除", "code": "perm:user:delete", "parentid": 2, "description": "删除用户"}, + {"name": "导出", "code": "perm:user:export", "parentid": 2, "description": "导出用户数据"}, + + # 角色管理操作 + {"name": "查看列表", "code": "perm:role:list", "parentid": 3, "description": "查看角色列表"}, + {"name": "查看详情", "code": "perm:role:detail", "parentid": 3, "description": "查看角色详情"}, + {"name": "搜索", "code": "perm:role:search", "parentid": 3, "description": "搜索角色"}, + {"name": "创建", "code": "perm:role:create", "parentid": 3, "description": "创建新角色"}, + {"name": "编辑", "code": "perm:role:edit", "parentid": 3, "description": "编辑角色信息"}, + {"name": "删除", "code": "perm:role:delete", "parentid": 3, "description": "删除角色"}, + {"name": "导出", "code": "perm:role:export", "parentid": 3, "description": "导出角色数据"}, + {"name": "分配权限", "code": "perm:role:assign", "parentid": 3, "description": "为角色分配权限"}, + + # 权限配置操作 + {"name": "查看列表", "code": "perm:config:list", "parentid": 4, "description": "查看权限列表"}, + {"name": "查看详情", "code": "perm:config:detail", "parentid": 4, "description": "查看权限详情"}, + {"name": "搜索", "code": "perm:config:search", "parentid": 4, "description": "搜索权限"}, + {"name": "创建", "code": "perm:config:create", "parentid": 4, "description": "创建新权限"}, + {"name": "编辑", "code": "perm:config:edit", "parentid": 4, "description": "编辑权限信息"}, + {"name": "删除", "code": "perm:config:delete", "parentid": 4, "description": "删除权限"}, + {"name": "导出", "code": "perm:config:export", "parentid": 4, "description": "导岀权限数据"}, ] # 检查现有权限 result = await db.execute(select(Permission)) existing_permissions = result.scalars().all() - existing_permission_codes = {perm.code for perm in existing_permissions} + existing_permission_codes = {perm.code: perm for perm in existing_permissions} - # 检查需要创建或更新的权限 - permissions_to_add = [] - permissions_to_update = [] + # 创建或更新权限 + created_count = 0 + updated_count = 0 - for perm_data in required_permissions: + for perm_data in permission_tree: perm_code = perm_data["code"] if perm_code not in existing_permission_codes: # 权限不存在,需要创建 - permissions_to_add.append(Permission(**perm_data)) + db.add(Permission(**perm_data)) + created_count += 1 else: # 权限存在,检查是否需要更新 - existing_perm = next( - perm for perm in existing_permissions if perm.code == perm_code - ) - if existing_perm.name != perm_data["name"] or existing_perm.description != perm_data["description"]: + existing_perm = existing_permission_codes[perm_code] + update_needed = False + + if existing_perm.name != perm_data["name"]: existing_perm.name = perm_data["name"] + update_needed = True + if existing_perm.parentid != perm_data["parentid"]: + existing_perm.parentid = perm_data["parentid"] + update_needed = True + if existing_perm.description != perm_data["description"]: existing_perm.description = perm_data["description"] - permissions_to_update.append(existing_perm) + update_needed = True + + if update_needed: + updated_count += 1 - # 执行创建和更新操作 - if permissions_to_add: - for perm in permissions_to_add: - db.add(perm) + if created_count > 0 or updated_count > 0: await db.commit() - print(f"创建了 {len(permissions_to_add)} 个权限") - - if permissions_to_update: - await db.commit() - print(f"更新了 {len(permissions_to_update)} 个权限") - - if not permissions_to_add and not permissions_to_update: + print(f"创建了 {created_count} 个权限,更新了 {updated_count} 个权限") + else: print("权限数据已存在且无需更新,跳过初始化") print("权限数据初始化/更新完成") @@ -293,6 +356,7 @@ async def init_test_user(db: AsyncSession): async def init_all_data(db: AsyncSession): """初始化所有数据""" print("开始初始化数据库数据...") + await ensure_permission_table_structure(db) await init_roles(db) await init_permissions(db) await init_role_permissions(db) diff --git a/backend/auth/models.py b/backend/auth/models.py index 420e7e5..b428964 100644 --- a/backend/auth/models.py +++ b/backend/auth/models.py @@ -56,8 +56,9 @@ class Permission(Base): __tablename__ = "permission" id = Column(Integer, primary_key=True, index=True, comment="权限ID") - name = Column(String(50), nullable=False, comment="权限名称") - code = Column(String(50), nullable=False, unique=True, comment="权限编码") + name = Column(String(100), nullable=False, comment="权限名称") + code = Column(String(100), nullable=False, unique=True, comment="权限编码") + parentid = Column(Integer, default=0, comment="父权限ID(0表示顶级模块)") description = Column(String(255), nullable=True, comment="权限描述") createtime = Column(DateTime, default=datetime.utcnow, comment="创建时间") updatetime = Column( diff --git a/backend/auth/schemas.py b/backend/auth/schemas.py index 36e4dba..e535743 100644 --- a/backend/auth/schemas.py +++ b/backend/auth/schemas.py @@ -112,8 +112,9 @@ class RoleResponse(RoleBase): class PermissionBase(BaseModel): """权限基础模型""" - name: str = Field(..., max_length=50, description="权限名称") - code: str = Field(..., max_length=50, description="权限编码") + name: str = Field(..., max_length=100, description="权限名称") + code: str = Field(..., max_length=100, description="权限编码") + parentid: int = Field(0, description="父权限ID(0表示顶级模块)") description: Optional[str] = Field(None, max_length=255, description="权限描述") @@ -133,6 +134,17 @@ class PermissionResponse(PermissionBase): from_attributes = True +class PermissionTreeResponse(BaseModel): + """权限树响应模型""" + + id: int = Field(..., description="权限ID") + name: str = Field(..., description="权限名称") + code: str = Field(..., description="权限编码") + parentid: int = Field(..., description="父权限ID") + description: Optional[str] = Field(None, description="权限描述") + children: list = Field([], description="子权限列表") + + # 角色权限关联相关模型 class RolePermissionAssign(BaseModel): """角色权限分配模型"""