feat(设置+门户): LOGO 文字配置(校/平台两级,pane 内维护)+ header 徽标旁显示;个人主题保存改 JSON 形态(LOGO文字与主题JSON化)
build / build (push) Successful in 1m27s
build / build (push) Successful in 1m27s
This commit is contained in:
@@ -226,6 +226,20 @@ class Base extends Abstract {
|
||||
return this.postRequest({ url });
|
||||
}
|
||||
|
||||
// ===== LOGO 文字(平台/学校名称,2026-10-09 LOGO 文字轮;后端契约见 SchSettingsController#schLogoText)=====
|
||||
|
||||
/** 读 LOGO 文字(已登录可读):{logoText: string|null, schId=实际命中层}——本校空 → 平台层 → null */
|
||||
getSchLogoText() {
|
||||
const url = path + "/schLogoText";
|
||||
return this.getRequest<{ logoText: string | null; schId: number }>({ url });
|
||||
}
|
||||
|
||||
/** 保存 LOGO 文字(仅学校管理员/超管):trim 后落本级(超管=平台层 0,校管=本校),≤64;空串=清空本级 */
|
||||
saveSchLogoText(logoText: string) {
|
||||
const url = path + "/saveSchLogoText";
|
||||
return this.postRequest({ url, params: { logoText } });
|
||||
}
|
||||
|
||||
// ===== 学校默认头像样式(默认头像轮 2026-09-30;后端契约见 SchSettingsController#schAvatarStyle)=====
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,14 @@
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
& .logo-text {
|
||||
margin-left: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #252b35;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
& .operate-container {
|
||||
flex-shrink: 1;
|
||||
& > li {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<header :class="headerClass">
|
||||
<img v-if="!!logoUrl" :src="baseUrl + '/image/default-logo.png'" v-real-img="logoUrl" class="logo-box" alt="" />
|
||||
<span v-if="logoText" class="logo-text">{{ logoText }}</span>
|
||||
<ul class="operate-container fix">
|
||||
<li v-if="isWidgetIconShow" :class="{ active: isWidgetShow }">
|
||||
<div class="icon-box" v-wave @click="toggleWidgetShow">
|
||||
@@ -265,6 +266,8 @@ const logoUrl = computed(() => {
|
||||
const sysLogo = logoList.value.find(x => x.type == 0);
|
||||
return sysLogo ? sysLogo.url : "";
|
||||
});
|
||||
/** LOGO 文字(平台/学校名称,2026-10-09):存 sch_settings.logo_text(级联读),与 LOGO 图独立 */
|
||||
const logoText = ref("");
|
||||
const isUserCardShow = ref(false),
|
||||
isWallpaperShow = ref(false),
|
||||
isLogoShow = ref(false),
|
||||
@@ -561,6 +564,10 @@ async function onWallpaperSelect(item: any) {
|
||||
async function loadLogoList() {
|
||||
const list = await UserSettingApi.getLogoList();
|
||||
logoList.value = list || [];
|
||||
// LOGO 文字与图并行加载(失败静默——无文字仅显示图,不影响 header)
|
||||
BaseApi.getSchLogoText()
|
||||
.then(res => (logoText.value = res?.logoText || ""))
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
async function logoSuccess(response: any, file: any, fileListt: any) {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* 本文件由 YschTheme scripts/gen-theme.mjs 从 assets-src/pc/theme-core.js 生成(版本 20261009-0054-5732ee2),勿手改。
|
||||
* 本文件由 YschTheme scripts/gen-theme.mjs 从 assets-src/pc/theme-core.js 生成(版本 20261009-1018-fb1c7f6),勿手改。
|
||||
* 分发方式:YschTheme `npm run sync` 拷进各端 src/utils/theme.ts(与 ThemeSwitcher.vue 配套,MD5 对齐报告)。
|
||||
* 运行时档位类名由 /static/js/yh-theme-init.js 在 <head> 内先行挂好,本模块只负责读写与切换。
|
||||
*/
|
||||
|
||||
+78
-5
@@ -501,6 +501,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- LOGO 文字(平台/学校名称,2026-10-09):单值配置存 sch_settings.logo_text,与上方 LOGO 图(logo 表)互不影响 -->
|
||||
<div class="sec-card">
|
||||
<h4>LOGO 文字 <span class="tag">平台/学校名称</span></h4>
|
||||
<div class="logo-text-row">
|
||||
<Input v-model="logoText" maxlength="64" placeholder="如:华阳中学教育集团智慧服务平台" style="width: 340px" />
|
||||
<button class="btn primary sm" :disabled="logoTextSaving" @click="onSaveLogoText">保存文字</button>
|
||||
<button class="btn plain sm" :disabled="logoTextSaving || !layerLogoConfigured" @click="onClearLogoText">清空本级文字</button>
|
||||
</div>
|
||||
<p class="hint">{{ logoTextHitLabel }} · 展示在门户与各子应用顶部导航 LOGO 旁,最长 64 字</p>
|
||||
</div>
|
||||
<!-- 上级只读参考池:校管视角下的平台 LOGO(type=0,不可删,可直接选用为本级 LOGO);超管视角为空 -->
|
||||
<div v-if="upperLogoPool.length > 0" class="sec-card">
|
||||
<h4>平台 LOGO <span class="tag">只读参考</span></h4>
|
||||
@@ -1014,6 +1024,58 @@ async function onSaveLogo() {
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== LOGO 文字(平台/学校名称,2026-10-09 LOGO 文字轮):单值配置存 sch_settings.logo_text,
|
||||
* 与 LOGO 图(logo 表)独立;级联读回填——schId=命中层(校级视角 0=本级未配置、生效的是平台文字回落)===== */
|
||||
const logoText = ref("");
|
||||
const layerLogoTextHitSchId = ref<number | null>(null);
|
||||
const logoTextHasValue = ref(false);
|
||||
const logoTextSaving = ref(false);
|
||||
/** 本级是否真配置过(对齐主题层 layerConfigured 写法:平台层一律按本级口径,校级看命中层) */
|
||||
const layerLogoConfigured = computed(() => logoTextHasValue.value && (curLayer.value === "platform" || layerLogoTextHitSchId.value !== 0));
|
||||
const logoTextHitLabel = computed(() => {
|
||||
if (curLayer.value === "platform") return "平台默认";
|
||||
return layerLogoConfigured.value ? "本校已配置" : "未配置本级,当前生效:平台默认";
|
||||
});
|
||||
|
||||
async function loadLogoText() {
|
||||
try {
|
||||
const res = await BaseApi.getSchLogoText();
|
||||
layerLogoTextHitSchId.value = res?.schId ?? null;
|
||||
logoText.value = res?.logoText || "";
|
||||
logoTextHasValue.value = !!res?.logoText;
|
||||
} catch (e) {
|
||||
/* 读取失败不打扰 */
|
||||
}
|
||||
}
|
||||
|
||||
/** 保存/清空走同一端点(saveSchLogoText):空串=清空本级(后端存 null);成功后回读一次刷新命中态 */
|
||||
async function onSaveLogoText() {
|
||||
if (logoTextSaving.value) return;
|
||||
logoTextSaving.value = true;
|
||||
try {
|
||||
await BaseApi.saveSchLogoText(logoText.value.trim());
|
||||
Message.success("LOGO 文字已保存");
|
||||
await loadLogoText();
|
||||
} catch (error) {
|
||||
Message.error("保存失败:" + error);
|
||||
} finally {
|
||||
logoTextSaving.value = false;
|
||||
}
|
||||
}
|
||||
async function onClearLogoText() {
|
||||
if (logoTextSaving.value) return;
|
||||
logoTextSaving.value = true;
|
||||
try {
|
||||
await BaseApi.saveSchLogoText("");
|
||||
Message.success("已清空本级文字");
|
||||
await loadLogoText();
|
||||
} catch (error) {
|
||||
Message.error("操作失败:" + error);
|
||||
} finally {
|
||||
logoTextSaving.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== wallpaper pane · my 层(个人壁纸,2026-10-02 任务A;S4 三层化后仅 curLayer==='my' 渲染)=====
|
||||
* 能力复制自 Header「设置壁纸」模态框(模态框保留不动):列表 getUserWallpaperList(type 0=系统/1=校区/2=个人)、
|
||||
* 点选即保存 checkWallpaper(与模态框 onClickWallpaper 同语义)、上传走 /api/wallpaperUpload(普通用户落 type=2 个人壁纸)、
|
||||
@@ -1080,7 +1142,10 @@ watch(curPane, pane => {
|
||||
loadMyWallpaperList();
|
||||
}
|
||||
}
|
||||
if (pane === "logo" && isAdmin.value && logoManageList.value.length === 0) loadManageLists();
|
||||
if (pane === "logo" && isAdmin.value) {
|
||||
if (logoManageList.value.length === 0) loadManageLists();
|
||||
loadLogoText();
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
/* ===== desktop:桌面应用三级默认(S6,后端 used_app 级联 + copy-on-write 已就绪,此处只补 UI)=====
|
||||
@@ -1302,13 +1367,13 @@ function keyExists(key: string) {
|
||||
}
|
||||
}
|
||||
|
||||
/** ThemeState → 服务端紧凑编码 theme|sideDeep01|gradOn01|sideFollow01(与 SchSettings 存储形态同款) */
|
||||
function themeToCompact(s: ThemeState): string {
|
||||
return `${s.theme}|${s.sideDeep ? 1 : 0}|${s.gradOn ? 1 : 0}|${s.sideFollow ? 1 : 0}`;
|
||||
/** ThemeState → 服务端 ThemeState JSON 串(2026-10-09 JSON 化契约;后端写侧只收 JSON,旧紧凑串会被拒) */
|
||||
function themeToJson(s: ThemeState): string {
|
||||
return JSON.stringify(s);
|
||||
}
|
||||
/** 外观偏好服务端双写(2026-10-08):本地体验不变,fire-and-forget 补写真源——成功不提示、失败 console.warn 不回滚本地 */
|
||||
function syncMyThemeRemote(s: ThemeState | null) {
|
||||
BaseApi.saveMyTheme(s ? themeToCompact(s) : null).catch((e: any) => console.warn("[appearance] saveMyTheme 失败(本地已生效,不回滚):", e));
|
||||
BaseApi.saveMyTheme(s ? themeToJson(s) : null).catch((e: any) => console.warn("[appearance] saveMyTheme 失败(本地已生效,不回滚):", e));
|
||||
}
|
||||
function syncMyAvatarRemote(style: string | null) {
|
||||
BaseApi.saveMyAvatarStyle(style).catch((e: any) => console.warn("[appearance] saveMyAvatarStyle 失败(本地已生效,不回滚):", e));
|
||||
@@ -2382,6 +2447,14 @@ watch(
|
||||
color: #b3b3b3;
|
||||
font-size: 13px;
|
||||
}
|
||||
/* LOGO 文字行:输入框 + 保存/清空按钮一行排布 */
|
||||
.logo-text-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 14px 0 4px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.logo-item {
|
||||
height: 72px;
|
||||
border-radius: 6px;
|
||||
|
||||
Reference in New Issue
Block a user