feat: 添加动态获取系统标题功能

1. 后端新增公开系统设置接口,仅允许获取id为1或key为"系统标题"的配置项
2. 管理后台登录页和布局页改为动态获取系统标题作为页面标题
3. 两处页面均在挂载时调用接口获取系统标题并更新对应显示文本
This commit is contained in:
jayhgq 2026-06-08 15:01:05 +08:00
parent 2641352f5e
commit 0045ae18cb
3 changed files with 48 additions and 3 deletions

View File

@ -67,6 +67,30 @@ async def get_settings(
return [SystemSettingResponse.model_validate(s) for s in settings] return [SystemSettingResponse.model_validate(s) for s in settings]
@router.get("/public", response_model=SystemSettingResponse)
async def get_public_setting(
setting_id: int = None,
key: str = None,
db: AsyncSession = Depends(get_db),
):
"""公开接口获取系统设置仅允许获取id为1或key为"系统标题"的内容)"""
if setting_id is not None:
if setting_id != 1:
raise HTTPException(status_code=403, detail="无权访问该设置项")
result = await db.execute(select(SystemSetting).filter(SystemSetting.id == setting_id))
elif key is not None:
if key != "系统标题":
raise HTTPException(status_code=403, detail="无权访问该设置项")
result = await db.execute(select(SystemSetting).filter(SystemSetting.key == key))
else:
raise HTTPException(status_code=400, detail="必须提供setting_id或key参数")
setting = result.scalar_one_or_none()
if not setting:
raise HTTPException(status_code=404, detail="设置项不存在")
return setting
@router.get("/{setting_id}", response_model=SystemSettingResponse) @router.get("/{setting_id}", response_model=SystemSettingResponse)
async def get_setting( async def get_setting(
setting_id: int, setting_id: int,

View File

@ -1,7 +1,7 @@
<template> <template>
<el-container class="admin-root"> <el-container class="admin-root">
<el-aside width="220px" class="aside"> <el-aside width="220px" class="aside">
<div class="brand">BookSystem 管理</div> <div class="brand">{{sysTitle}}</div>
<el-menu <el-menu
:default-active="active" :default-active="active"
router router
@ -72,15 +72,17 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted } from "vue"; import { computed, onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import { Key, Setting } from "@element-plus/icons-vue"; import { Key, Setting } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useAuthStore } from "@/modules/admin/stores/auth"; import { useAuthStore } from "@/modules/admin/stores/auth";
import axios from "axios";
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const auth = useAuthStore(); const auth = useAuthStore();
const sysTitle = ref("");
const active = computed(() => route.path); const active = computed(() => route.path);
const pageTitle = computed(() => (route.meta.title as string) || ""); const pageTitle = computed(() => (route.meta.title as string) || "");
@ -105,8 +107,18 @@ const hasAnyPermission = computed(() => {
return hasUserPermission.value || hasRolePermission.value || hasPermissionPermission.value; return hasUserPermission.value || hasRolePermission.value || hasPermissionPermission.value;
}); });
async function getSysTitle() {
const baseURL = import.meta.env.VITE_API_BASE || "/api";
let res = await axios.get(`${baseURL}/settings/public?setting_id=1`)
if (res.data) {
sysTitle.value = res.data.value;
}
}
onMounted(async () => { onMounted(async () => {
try { try {
getSysTitle();
if (!auth.user) { if (!auth.user) {
await auth.fetchProfile(); await auth.fetchProfile();
} }

View File

@ -2,7 +2,7 @@
<div class="login-wrap"> <div class="login-wrap">
<el-card class="card" shadow="hover"> <el-card class="card" shadow="hover">
<template #header> <template #header>
<span class="card-title">管理后台登录</span> <span class="card-title">{{ sysTitle }}</span>
</template> </template>
<el-form ref="formRef" :model="form" :rules="rules" label-width="88px" @submit.prevent> <el-form ref="formRef" :model="form" :rules="rules" label-width="88px" @submit.prevent>
<el-form-item label="用户名" prop="username"> <el-form-item label="用户名" prop="username">
@ -57,6 +57,7 @@ const formRef = ref<FormInstance>();
const loading = ref(false); const loading = ref(false);
const captchaUrl = ref(""); const captchaUrl = ref("");
const captchaId = ref(""); const captchaId = ref("");
const sysTitle = ref("");
const baseURL = import.meta.env.VITE_API_BASE || "/api"; const baseURL = import.meta.env.VITE_API_BASE || "/api";
@ -72,6 +73,13 @@ const rules: FormRules = {
captcha_code: [{ required: true, message: "请输入验证码", trigger: "blur" }], captcha_code: [{ required: true, message: "请输入验证码", trigger: "blur" }],
}; };
async function getSysTitle() {
let res = await axios.get(`${baseURL}/settings/public?setting_id=1`)
if (res.data) {
sysTitle.value = res.data.value;
}
}
async function loadCaptcha() { async function loadCaptcha() {
if (captchaUrl.value.startsWith("blob:")) { if (captchaUrl.value.startsWith("blob:")) {
URL.revokeObjectURL(captchaUrl.value); URL.revokeObjectURL(captchaUrl.value);
@ -135,6 +143,7 @@ async function onSubmit() {
onMounted(() => { onMounted(() => {
loadCaptcha(); loadCaptcha();
getSysTitle();
}); });
</script> </script>