feat(theme): 皮肤包管理收敛平台级+命名表单-新顶层路由/theme-manage(meta.superOnly守卫+页面watch双兜底),ThemeManage升级全屏页复用新抽WorkbenchHeader(工作台同款深色顶栏backTo=/workbench),工作台超管工具行加皮肤包管理按钮,删SiteManage兜底按钮,旧/theme重定向新页;上传/添加皮肤包改表单弹窗(zip+显示名/描述;添加=源包+标识名+命名一步),内置包可改显示名/描述(无参数区+恢复默认名称);openEdit未注册主题保留原值并告警(themeEdit util,不再静默归一default);mock删modId=7菜单节点;SiteWizard预览内容源v-model对齐path语义(W4遗留);vitest 62/62+build通过
build / build (push) Successful in 2m17s

This commit is contained in:
chenxing
2026-09-08 20:25:57 +08:00
parent 604d77049b
commit 9ba4cb135a
12 changed files with 553 additions and 218 deletions
+14 -64
View File
@@ -8,6 +8,7 @@ import config from "@/assets/config/host.config";
import { SchoolCard, SchoolOption, ThemeVo } from "@/types/cms";
import { portalUrlOf } from "@/utils/sitePath";
import ThemePicker from "@/components/theme/ThemePicker.vue";
import WorkbenchHeader from "@/components/WorkbenchHeader.vue";
/**
* 学校工作台(一级页,docs/09 §3.3 方案A):全屏无壳。
@@ -23,10 +24,6 @@ const loading = ref(false);
const themes = ref<ThemeVo[]>([]);
const isSuper = computed(() => store.isSuperAdmin);
const userInfo = computed(() => ({
name: store.session.baseUserName || "管理员",
avatar: store.session.baseUserAvatar,
}));
async function run() {
loading.value = true;
@@ -74,6 +71,11 @@ function goAllSites() {
}
}
/** 超管平台级皮肤包管理(不再挂左侧菜单,工作台直达) */
function goThemeManage() {
router.push("/theme-manage");
}
/* ===== 添加学校(超管):绑定已有学校 + 初始化主站 ===== */
const modalVisible = ref(false);
const saving = ref(false);
@@ -131,7 +133,9 @@ function onSchoolPick(id: number) {
form.value.schName = opt?.name || "";
if (opt) {
form.value.name = `${opt.name}门户网站`;
form.value.code = `sch-${opt.id}`;
// R1 学校主站编码规则:1 + 学校ID左补零至4位(总长5位,如 id=13 → 10013);
// id≥10000 时 LPAD 不截断、编码自然超5位(当前学校量级不会触达)
form.value.code = `1${String(opt.id).padStart(4, "0")}`;
}
}
@@ -159,30 +163,12 @@ async function create() {
}
}
const linkUserInfo = () => {
window.location.href = config.baseHost + "/v/userinfo";
};
const logout = () => {
const url = "/cas/logout?service=" + window.location.href;
window.location.href = config.ssoHost + url;
};
onMounted(run);
</script>
<template>
<div class="workbench">
<header class="wb-header">
<h4>云海CMS · 学校工作台</h4>
<div class="wb-header-aside">
<img :src="userInfo.avatar" v-if="userInfo.avatar" class="wb-avatar" @click="linkUserInfo" />
<a class="name" href="javascript:void(0);" @click="linkUserInfo">{{ userInfo.name }}</a>
<span class="delimiter"></span>
<a href="javascript:;" class="logout" @click="logout" title="退出登陆">
<i class="iconfont icon-logout"></i>
</a>
</div>
</header>
<WorkbenchHeader title="云海CMS · 学校工作台" />
<!-- 操作工具行(Notice search-wrap 同款灰底条):按钮居左,账号区保持在深色 header 右侧 -->
<div class="wb-toolbar" v-if="isSuper">
@@ -190,6 +176,10 @@ onMounted(run);
<Icon type="ios-globe" />
全部站点总览
</Button>
<Button class="wb-btn" @click="goThemeManage">
<Icon type="ios-brush" />
皮肤包管理
</Button>
<Button type="primary" class="wb-btn" @click="openAdd">
<Icon type="ios-add" />
添加学校
@@ -281,46 +271,6 @@ onMounted(run);
flex-direction: column;
background: #f5f7fa;
}
.wb-header {
height: 56px;
flex-shrink: 0;
background: #1f2a3a;
color: #fff;
display: flex;
align-items: center;
padding: 0 24px;
h4 {
color: #fff;
font-size: 16px;
margin: 0;
}
.wb-header-aside {
margin-left: auto;
display: flex;
align-items: center;
gap: 10px;
.name {
color: #fff;
}
.delimiter {
width: 1px;
height: 16px;
background: rgba(255, 255, 255, 0.3);
display: inline-block;
}
.wb-avatar {
width: 28px;
height: 28px;
border-radius: 50%;
cursor: pointer;
}
.logout {
color: #fff;
display: inline-flex;
align-items: center;
}
}
}
/* 工具行:Notice front .search-wrap 同款(#f7f7f7 底 + 10px 16px 内边距 ≈ 52px 高),按钮居左 */
.wb-toolbar {
flex-shrink: 0;