diff --git a/backend/auth/apps/settings/urls.py b/backend/auth/apps/settings/urls.py
index 3c72af9..c3f4b33 100644
--- a/backend/auth/apps/settings/urls.py
+++ b/backend/auth/apps/settings/urls.py
@@ -1,7 +1,11 @@
-from fastapi import APIRouter, Depends, HTTPException
+from fastapi import APIRouter, Depends, HTTPException, File, UploadFile
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, and_
from fastcrud import FastCRUD
+from pathlib import Path
+import os
+import shutil
+from datetime import datetime
from database import get_db
from models import SystemSetting, User
@@ -18,6 +22,10 @@ router = APIRouter(prefix="/settings", tags=["settings"])
# 创建FastCRUD实例
setting_crud = FastCRUD(SystemSetting, SystemSettingResponse)
+# 图片存储目录
+UPLOAD_DIR = Path(__file__).parent.parent.parent / "uploads"
+UPLOAD_DIR.mkdir(exist_ok=True)
+
@router.post("/", response_model=SystemSettingResponse)
async def create_setting(
@@ -36,6 +44,8 @@ async def create_setting(
db_setting = SystemSetting(
key=setting_data.key,
value=setting_data.value,
+ type=setting_data.type or "string",
+ options=setting_data.options,
description=setting_data.description,
)
@@ -129,3 +139,39 @@ async def delete_setting(
# 使用FastCRUD删除设置
deleted = await setting_crud.delete(db, id=setting_id)
return {"message": "设置项删除成功"}
+
+
+@router.post("/upload")
+async def upload_image(
+ file: UploadFile = File(...),
+ current_user: User = Depends(get_current_user),
+):
+ """上传图片"""
+ # 检查文件类型
+ if not file.filename or not file.filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.webp')):
+ raise HTTPException(status_code=400, detail="只支持图片格式(png, jpg, jpeg, gif, webp)")
+
+ # 检查文件大小(2MB)
+ file_size = 0
+ chunk = await file.read(1024)
+ while chunk:
+ file_size += len(chunk)
+ if file_size > 2 * 1024 * 1024:
+ raise HTTPException(status_code=400, detail="文件大小不能超过2MB")
+ chunk = await file.read(1024)
+
+ # 重置文件指针
+ await file.seek(0)
+
+ # 生成文件名
+ timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
+ ext = file.filename.split('.')[-1]
+ filename = f"setting_{timestamp}.{ext}"
+ file_path = UPLOAD_DIR / filename
+
+ # 保存文件
+ with open(file_path, "wb") as buffer:
+ shutil.copyfileobj(file.file, buffer)
+
+ # 返回文件路径
+ return {"url": f"/uploads/{filename}"}
diff --git a/backend/auth/init_data.py b/backend/auth/init_data.py
index 365df89..d4838b6 100644
--- a/backend/auth/init_data.py
+++ b/backend/auth/init_data.py
@@ -50,49 +50,71 @@ async def init_permissions(db: AsyncSession):
# 定义需要初始化的权限(树形结构)
# parentid: 0 = 顶级模块, >0 = 子权限
permission_tree = [
+ # ========================================
# 顶级模块
+ # ========================================
{"name": "权限管理", "code": "perm", "parentid": 0, "description": "权限管理模块"},
+ {"name": "系统设置", "code": "system", "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:system", "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": "system:basic", "parentid": 2, "description": "系统基础配置"},
+ {"name": "高级配置", "code": "system:advanced", "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": "为角色分配权限"},
+ # ========================================
+ # 用户管理操作(parentid=3)
+ # ========================================
+ {"name": "查看列表", "code": "perm:user:list", "parentid": 3, "description": "查看用户列表"},
+ {"name": "查看详情", "code": "perm:user:detail", "parentid": 3, "description": "查看用户详情"},
+ {"name": "搜索", "code": "perm:user:search", "parentid": 3, "description": "搜索用户"},
+ {"name": "创建", "code": "perm:user:create", "parentid": 3, "description": "创建新用户"},
+ {"name": "编辑", "code": "perm:user:edit", "parentid": 3, "description": "编辑用户信息"},
+ {"name": "删除", "code": "perm:user:delete", "parentid": 3, "description": "删除用户"},
+ {"name": "导出", "code": "perm:user:export", "parentid": 3, "description": "导出用户数据"},
+ {"name": "批量操作", "code": "perm:user:batch", "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": "导岀权限数据"},
+ # ========================================
+ # 角色管理操作(parentid=4)
+ # ========================================
+ {"name": "查看列表", "code": "perm:role:list", "parentid": 4, "description": "查看角色列表"},
+ {"name": "查看详情", "code": "perm:role:detail", "parentid": 4, "description": "查看角色详情"},
+ {"name": "搜索", "code": "perm:role:search", "parentid": 4, "description": "搜索角色"},
+ {"name": "创建", "code": "perm:role:create", "parentid": 4, "description": "创建新角色"},
+ {"name": "编辑", "code": "perm:role:edit", "parentid": 4, "description": "编辑角色信息"},
+ {"name": "删除", "code": "perm:role:delete", "parentid": 4, "description": "删除角色"},
+ {"name": "导出", "code": "perm:role:export", "parentid": 4, "description": "导出角色数据"},
+ {"name": "分配权限", "code": "perm:role:assign", "parentid": 4, "description": "为角色分配权限"},
- # 系统设置操作(parentid 为 5,对应系统设置子模块)
- {"name": "查看列表", "code": "perm:system:list", "parentid": 5, "description": "查看系统设置列表"},
- {"name": "查看详情", "code": "perm:system:detail", "parentid": 5, "description": "查看系统设置详情"},
- {"name": "创建", "code": "perm:system:create", "parentid": 5, "description": "创建设置项"},
- {"name": "编辑", "code": "perm:system:edit", "parentid": 5, "description": "编辑设置项"},
- {"name": "删除", "code": "perm:system:delete", "parentid": 5, "description": "删除设置项"},
+ # ========================================
+ # 权限配置操作(parentid=5)
+ # ========================================
+ {"name": "查看列表", "code": "perm:config:list", "parentid": 5, "description": "查看权限列表"},
+ {"name": "查看详情", "code": "perm:config:detail", "parentid": 5, "description": "查看权限详情"},
+ {"name": "搜索", "code": "perm:config:search", "parentid": 5, "description": "搜索权限"},
+ {"name": "创建", "code": "perm:config:create", "parentid": 5, "description": "创建新权限"},
+ {"name": "编辑", "code": "perm:config:edit", "parentid": 5, "description": "编辑权限信息"},
+ {"name": "删除", "code": "perm:config:delete", "parentid": 5, "description": "删除权限"},
+ {"name": "导出", "code": "perm:config:export", "parentid": 5, "description": "导岀权限数据"},
+
+ # ========================================
+ # 系统设置 -> 基础配置操作(parentid=6)
+ # ========================================
+ {"name": "查看配置", "code": "system:basic:view", "parentid": 6, "description": "查看基础配置"},
+ {"name": "修改配置", "code": "system:basic:edit", "parentid": 6, "description": "修改基础配置"},
+
+ # ========================================
+ # 系统设置 -> 高级配置操作(parentid=7)
+ # ========================================
+ {"name": "查看配置", "code": "system:advanced:view", "parentid": 7, "description": "查看高级配置"},
+ {"name": "修改配置", "code": "system:advanced:edit", "parentid": 7, "description": "修改高级配置"},
]
# 检查现有权限
diff --git a/backend/auth/models.py b/backend/auth/models.py
index 723248c..e602496 100644
--- a/backend/auth/models.py
+++ b/backend/auth/models.py
@@ -88,7 +88,9 @@ class SystemSetting(Base):
__tablename__ = "system_setting"
id = Column(Integer, primary_key=True, index=True, comment="设置ID")
key = Column(String(100), nullable=False, unique=True, comment="设置键名")
- value = Column(String(1000), nullable=False, comment="设置值")
+ value = Column(String(2000), nullable=False, comment="设置值")
+ type = Column(String(20), default="string", comment="类型:string/image/select/boolean")
+ options = Column(String(500), nullable=True, comment="下拉选项(用|分隔)")
description = Column(String(255), nullable=True, comment="设置描述")
createtime = Column(DateTime, default=datetime.utcnow, comment="创建时间")
updatetime = Column(
diff --git a/backend/auth/requirements.txt b/backend/auth/requirements.txt
index 7ad7651..46eaa49 100644
--- a/backend/auth/requirements.txt
+++ b/backend/auth/requirements.txt
@@ -28,4 +28,7 @@ asyncpg>=0.31.0
redis>=7.2.0
# 验证码生成
-captcha>=0.7.1
\ No newline at end of file
+captcha>=0.7.1
+
+# 文件上传
+python-multipart>=0.0.9
\ No newline at end of file
diff --git a/backend/auth/schemas.py b/backend/auth/schemas.py
index d950489..1bf5961 100644
--- a/backend/auth/schemas.py
+++ b/backend/auth/schemas.py
@@ -190,7 +190,9 @@ class SystemSettingBase(BaseModel):
"""系统设置基础模型"""
key: str = Field(..., max_length=100, description="设置键名")
- value: str = Field(..., max_length=1000, description="设置值")
+ value: str = Field(..., max_length=2000, description="设置值")
+ type: Optional[str] = Field("string", max_length=20, description="类型:string/image/select/boolean")
+ options: Optional[str] = Field(None, max_length=500, description="下拉选项(用|分隔)")
description: Optional[str] = Field(None, max_length=255, description="设置描述")
model_config = {"extra": "ignore"}
@@ -212,6 +214,8 @@ class SystemSettingResponse(BaseModel):
id: int = Field(..., description="设置ID")
key: str = Field(..., description="设置键名")
value: str = Field(..., description="设置值")
+ type: str = Field(..., description="类型")
+ options: Optional[str] = Field(None, description="下拉选项")
description: Optional[str] = Field(None, description="设置描述")
createtime: datetime = Field(..., description="创建时间")
updatetime: datetime = Field(..., description="更新时间")
diff --git a/frontend/src/modules/admin/layout/AdminLayout.vue b/frontend/src/modules/admin/layout/AdminLayout.vue
index cd37dda..dc30666 100644
--- a/frontend/src/modules/admin/layout/AdminLayout.vue
+++ b/frontend/src/modules/admin/layout/AdminLayout.vue
@@ -98,7 +98,7 @@ const hasPermissionPermission = computed(() => {
});
const hasSystemPermission = computed(() => {
- return auth.permissions.some(p => p.code.startsWith("perm:system"));
+ return auth.permissions.some(p => p.code.startsWith("system:"));
});
const hasAnyPermission = computed(() => {
diff --git a/frontend/src/modules/admin/views/settings/SettingManage.vue b/frontend/src/modules/admin/views/settings/SettingManage.vue
index 509ae7e..08caf08 100644
--- a/frontend/src/modules/admin/views/settings/SettingManage.vue
+++ b/frontend/src/modules/admin/views/settings/SettingManage.vue
@@ -1,25 +1,245 @@
-
+
+
+
+ 系统设置管理
+ 添加设置
+
+
+
+
+
+
+
+
+
+ {{ getTypeLabel(scope.row.type) }}
+
+
+
+
+
+
+ 编辑
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 确定
+
+
diff --git a/frontend/src/modules/admin/views/settings/setting-crud.ts b/frontend/src/modules/admin/views/settings/setting-crud.ts
index 6f4bf1a..54cf9b4 100644
--- a/frontend/src/modules/admin/views/settings/setting-crud.ts
+++ b/frontend/src/modules/admin/views/settings/setting-crud.ts
@@ -1,4 +1,5 @@
import type { CreateCrudOptions } from "@fast-crud/fast-crud";
+import { dict } from "@fast-crud/fast-crud";
import dayjs from "dayjs";
import { http } from "@/modules/admin/api/http";
@@ -6,6 +7,8 @@ export type SettingRow = {
id: number;
key: string;
value: string;
+ type: string;
+ options?: string | null;
description?: string | null;
createtime: string;
updatetime: string;
@@ -71,12 +74,42 @@ export const createSettingCrudOptions: CreateCrudOptions = () => {
rules: [{ required: true, message: "请输入设置键名", trigger: "blur" }],
},
},
+ type: {
+ title: "类型",
+ key: "type",
+ type: "dict-select",
+ column: { width: 120 },
+ dict: dict({
+ data: [
+ { value: "string", label: "字符串" },
+ { value: "image", label: "图片" },
+ { value: "select", label: "下拉列表" },
+ { value: "boolean", label: "布尔值" },
+ ],
+ value: "value",
+ label: "label",
+ }),
+ form: {
+ value: "string",
+ rules: [{ required: true, message: "请选择类型", trigger: "change" }],
+ },
+ },
value: {
title: "设置值",
key: "value",
type: "textarea",
+ column: { width: 200 },
form: {
- rules: [{ required: true, message: "请输入设置值", trigger: "blur" }],
+ rules: [{ required: true, message: "请输入值", trigger: "blur" }],
+ },
+ },
+ options: {
+ title: "选项配置",
+ key: "options",
+ type: "textarea",
+ column: { show: false },
+ form: {
+ placeholder: "多个选项用 | 分隔,如:选项1|选项2|选项3",
},
},
description: {
diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts
index ebce710..c86d2fb 100644
--- a/frontend/src/router/index.ts
+++ b/frontend/src/router/index.ts
@@ -48,7 +48,7 @@ const router = createRouter({
{
path: "settings",
name: "admin-settings",
- meta: { title: "系统设置", permission: "perm:system" },
+ meta: { title: "系统设置", permission: "system:" },
component: () =>
import("@/modules/admin/views/settings/SettingManage.vue"),
},