Commit 10a82a20 by DaiJiezhang

style: 移除全站副标题并清理 eyebrow 样式

删除侧边栏品牌副标题、账号权限页与历史参考页副标题,
连同登录页早已停用的 login-brand__eyebrow 一并清理,
eyebrow 这个类自此在源码中不再出现。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
parent 51396263
......@@ -30,5 +30,5 @@ export default {
return { authState, logout, canVisit, isAdministrator, retryConnection };
},
template: `<main v-if="authState.connectionError" class="auth-network-error" role="alert"><section class="auth-network-error__panel"><h1>网络连接异常</h1><p>暂时无法确认登录状态,请检查网络后重试。</p><button type="button" @click="retryConnection">重新连接</button></section></main><main v-else-if="!authState.ready" class="auth-loading" role="status" aria-live="polite">正在验证登录状态…</main><RouterView v-else-if="$route.path === '/login'" /><div v-else class="app-shell"><aside class="sidebar"><p class="eyebrow">学有为资产</p><h1>学有为资产后台</h1><nav aria-label="主导航"><RouterLink v-if="canVisit('overview')" to="/overview">总览</RouterLink><RouterLink v-if="canVisit('domain')" to="/domain">域名资料</RouterLink><RouterLink v-if="canVisit('company-profile')" to="/company-profiles">公司档案</RouterLink><RouterLink v-if="canVisit('reference-wecom')" to="/reference/wecom">企微资料</RouterLink><RouterLink v-if="canVisit('phone-assets')" to="/phone-assets">手机号资产</RouterLink><RouterLink v-if="isAdministrator()" to="/device-assets">设备资产管理</RouterLink><RouterLink v-if="canVisit('alerts')" to="/alerts">提醒中心</RouterLink><RouterLink v-if="isAdministrator()" class="settings-link" to="/settings/users-permissions"><span aria-hidden="true">⚙</span> 账号与权限</RouterLink></nav><button class="logout-button" @click="logout">退出登录</button></aside><main class="content"><RouterView /></main></div>`
template: `<main v-if="authState.connectionError" class="auth-network-error" role="alert"><section class="auth-network-error__panel"><h1>网络连接异常</h1><p>暂时无法确认登录状态,请检查网络后重试。</p><button type="button" @click="retryConnection">重新连接</button></section></main><main v-else-if="!authState.ready" class="auth-loading" role="status" aria-live="polite">正在验证登录状态…</main><RouterView v-else-if="$route.path === '/login'" /><div v-else class="app-shell"><aside class="sidebar"><h1>学有为资产后台</h1><nav aria-label="主导航"><RouterLink v-if="canVisit('overview')" to="/overview">总览</RouterLink><RouterLink v-if="canVisit('domain')" to="/domain">域名资料</RouterLink><RouterLink v-if="canVisit('company-profile')" to="/company-profiles">公司档案</RouterLink><RouterLink v-if="canVisit('reference-wecom')" to="/reference/wecom">企微资料</RouterLink><RouterLink v-if="canVisit('phone-assets')" to="/phone-assets">手机号资产</RouterLink><RouterLink v-if="isAdministrator()" to="/device-assets">设备资产管理</RouterLink><RouterLink v-if="canVisit('alerts')" to="/alerts">提醒中心</RouterLink><RouterLink v-if="isAdministrator()" class="settings-link" to="/settings/users-permissions"><span aria-hidden="true">⚙</span> 账号与权限</RouterLink></nav><button class="logout-button" @click="logout">退出登录</button></aside><main class="content"><RouterView /></main></div>`
};
......@@ -27,4 +27,4 @@ export default { setup() { const users = ref([]); const lockedAccounts = ref([])
function openPassword(user) { target.value = user; password.value = ''; passwordOpen.value = true; }
/** 代码作用(白话):把新密码提交给后端并立即从页面内存清除;关联文件:system-user-api-client.js、V1__system_user_auth_permissions.sql。关联逻辑(调用链/数据流):新密码 -> BCrypt -> 数据库触发器 -> 旧会话失效。 */
async function savePassword() { try { await resetSystemUserPassword(target.value.id, password.value); password.value = ''; passwordOpen.value = false; ElMessage.success('密码已更新,旧会话已失效'); await load(); } catch (error) { ElMessage.error(error.message || '密码更新失败'); } }
load(); return { users, lockedAccounts, loading, dialogOpen, passwordOpen, form, pages, roles, editingId, isDeveloper, isAdministratorRole, target, password, load, openCreate, openEdit, save, openPassword, savePassword, unlockAccount, formatLockTime }; }, template: `<section class="user-permission-page"><header class="page-header"><div><p class="eyebrow">设置 / 账号与权限</p><h2>账号与权限</h2><p>开发者账号 Jeddy 不会在此页面显示;逐页权限由此面板独立配置。</p></div><el-button type="primary" @click="openCreate">新增账号</el-button></header><section v-if="lockedAccounts.length" class="reference-card user-permission-page__locked"><h3>登录锁定({{ lockedAccounts.length }})</h3><p>连续输错密码 20 次的账号会被锁定 24 小时。若为误触发或被他人恶意锁定,可在此立即解除。</p><el-table :data="lockedAccounts"><el-table-column prop="username" label="账号名" /><el-table-column prop="failures" label="失败次数" width="110" /><el-table-column label="锁定至"><template #default="scope">{{ formatLockTime(scope.row.lockedUntil) }}</template></el-table-column><el-table-column label="操作" width="140"><template #default="scope"><el-button link type="primary" @click="unlockAccount(scope.row)">解除锁定</el-button></template></el-table-column></el-table></section><section class="reference-card user-permission-page__accounts"><div class="user-permission-page__grid-wrap"><el-table :data="users" v-loading="loading"><el-table-column prop="username" label="用户名" /><el-table-column prop="roleCode" label="角色" /><el-table-column prop="status" label="状态" /><el-table-column label="操作" width="210"><template #default="scope"><el-button link @click="openEdit(scope.row)">编辑权限</el-button><el-button v-if="isDeveloper" link type="primary" @click="openPassword(scope.row)">设置密码</el-button></template></el-table-column></el-table></div></section><el-dialog v-model="dialogOpen" :title="editingId ? '编辑账号与权限' : '新增账号'" width="680px"><el-form label-width="112px"><el-form-item label="用户名" v-if="!editingId"><el-input v-model="form.username" /></el-form-item><el-form-item label="角色"><el-select v-model="form.roleCode"><el-option v-for="role in roles" :key="role.value" :label="role.label" :value="role.value" /></el-select></el-form-item><el-form-item label="账号状态" v-if="editingId"><el-select v-model="form.status"><el-option label="启用" value="ACTIVE" /><el-option label="禁用" value="DISABLED" /></el-select></el-form-item><el-form-item label="初始密码" v-if="!editingId && isDeveloper"><el-input v-model="form.password" type="password" show-password /><small>12-72 位</small></el-form-item><el-alert v-if="!editingId && !isDeveloper" title="超级管理员创建的账号会保持禁用且不设密码,需由开发者设置密码后再启用。" type="info" :closable="false" /><el-divider>页面权限</el-divider><div v-if="isAdministratorRole" class="permission-hint">超级管理员固定拥有全部页面的编辑权限。</div><el-form-item v-for="page in pages" :key="page.key" :label="page.label"><el-radio-group v-model="form.pagePermissions[page.key]" :disabled="isAdministratorRole"><el-radio value="NONE">无权限</el-radio><el-radio value="READ">只读</el-radio><el-radio value="EDIT">编辑</el-radio></el-radio-group></el-form-item></el-form><template #footer><el-button @click="dialogOpen=false">取消</el-button><el-button type="primary" @click="save">保存</el-button></template></el-dialog><el-dialog v-model="passwordOpen" title="设置账号密码" width="420px"><p>仅开发者可以设置密码:{{ target?.username }}</p><el-input v-model="password" type="password" show-password placeholder="12-72 位且不含用户名" /><template #footer><el-button @click="passwordOpen=false">取消</el-button><el-button type="primary" @click="savePassword">确认设置</el-button></template></el-dialog></section>` };
load(); return { users, lockedAccounts, loading, dialogOpen, passwordOpen, form, pages, roles, editingId, isDeveloper, isAdministratorRole, target, password, load, openCreate, openEdit, save, openPassword, savePassword, unlockAccount, formatLockTime }; }, template: `<section class="user-permission-page"><header class="page-header"><div><h2>账号与权限</h2><p>开发者账号 Jeddy 不会在此页面显示;逐页权限由此面板独立配置。</p></div><el-button type="primary" @click="openCreate">新增账号</el-button></header><section v-if="lockedAccounts.length" class="reference-card user-permission-page__locked"><h3>登录锁定({{ lockedAccounts.length }})</h3><p>连续输错密码 20 次的账号会被锁定 24 小时。若为误触发或被他人恶意锁定,可在此立即解除。</p><el-table :data="lockedAccounts"><el-table-column prop="username" label="账号名" /><el-table-column prop="failures" label="失败次数" width="110" /><el-table-column label="锁定至"><template #default="scope">{{ formatLockTime(scope.row.lockedUntil) }}</template></el-table-column><el-table-column label="操作" width="140"><template #default="scope"><el-button link type="primary" @click="unlockAccount(scope.row)">解除锁定</el-button></template></el-table-column></el-table></section><section class="reference-card user-permission-page__accounts"><div class="user-permission-page__grid-wrap"><el-table :data="users" v-loading="loading"><el-table-column prop="username" label="用户名" /><el-table-column prop="roleCode" label="角色" /><el-table-column prop="status" label="状态" /><el-table-column label="操作" width="210"><template #default="scope"><el-button link @click="openEdit(scope.row)">编辑权限</el-button><el-button v-if="isDeveloper" link type="primary" @click="openPassword(scope.row)">设置密码</el-button></template></el-table-column></el-table></div></section><el-dialog v-model="dialogOpen" :title="editingId ? '编辑账号与权限' : '新增账号'" width="680px"><el-form label-width="112px"><el-form-item label="用户名" v-if="!editingId"><el-input v-model="form.username" /></el-form-item><el-form-item label="角色"><el-select v-model="form.roleCode"><el-option v-for="role in roles" :key="role.value" :label="role.label" :value="role.value" /></el-select></el-form-item><el-form-item label="账号状态" v-if="editingId"><el-select v-model="form.status"><el-option label="启用" value="ACTIVE" /><el-option label="禁用" value="DISABLED" /></el-select></el-form-item><el-form-item label="初始密码" v-if="!editingId && isDeveloper"><el-input v-model="form.password" type="password" show-password /><small>12-72 位</small></el-form-item><el-alert v-if="!editingId && !isDeveloper" title="超级管理员创建的账号会保持禁用且不设密码,需由开发者设置密码后再启用。" type="info" :closable="false" /><el-divider>页面权限</el-divider><div v-if="isAdministratorRole" class="permission-hint">超级管理员固定拥有全部页面的编辑权限。</div><el-form-item v-for="page in pages" :key="page.key" :label="page.label"><el-radio-group v-model="form.pagePermissions[page.key]" :disabled="isAdministratorRole"><el-radio value="NONE">无权限</el-radio><el-radio value="READ">只读</el-radio><el-radio value="EDIT">编辑</el-radio></el-radio-group></el-form-item></el-form><template #footer><el-button @click="dialogOpen=false">取消</el-button><el-button type="primary" @click="save">保存</el-button></template></el-dialog><el-dialog v-model="passwordOpen" title="设置账号密码" width="420px"><p>仅开发者可以设置密码:{{ target?.username }}</p><el-input v-model="password" type="password" show-password placeholder="12-72 位且不含用户名" /><template #footer><el-button @click="passwordOpen=false">取消</el-button><el-button type="primary" @click="savePassword">确认设置</el-button></template></el-dialog></section>` };
......@@ -26,7 +26,7 @@ export default {
template: `
<section class="reference-page">
<header class="page-header">
<div><p class="eyebrow">LEGACY REFERENCE</p><h2>{{ content.title }}</h2><p>{{ content.description }}</p></div>
<div><h2>{{ content.title }}</h2><p>{{ content.description }}</p></div>
<span class="reference-badge">旧界面参考,不可操作</span>
</header>
<article class="reference-card">
......
......@@ -12,13 +12,13 @@ body { margin: 0; }
.login-brand { display: flex; align-items: center; justify-content: center; gap: 16px; margin: 0 auto 14px; }
.login-brand__mark { display: grid; grid-template-columns: repeat(3, 4px); gap: 3px; align-content: center; justify-content: center; width: 56px; height: 56px; overflow: hidden; border: 1px solid rgba(255, 255, 255, .18); border-radius: 18px; background: linear-gradient(145deg, rgba(170, 208, 255, .22), rgba(109, 146, 255, .10)); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .30), 0 12px 30px rgba(68, 121, 255, .18); }
.login-brand__mark span { width: 4px; border-radius: 999px; background: rgba(255, 255, 255, .92); box-shadow: 0 0 8px rgba(187, 218, 255, .72); }.login-brand__mark span:nth-child(1) { height: 15px; }.login-brand__mark span:nth-child(2) { height: 25px; }.login-brand__mark span:nth-child(3) { height: 19px; }
.login-brand__eyebrow { margin: 0 0 5px; color: rgba(211, 226, 255, .66); font-size: 10px; font-weight: 600; letter-spacing: .16em; }.login-brand h1 { margin: 0; color: var(--login-text-primary); font-size: clamp(22px, 2vw, 28px); font-weight: 700; line-height: 1.25; letter-spacing: .04em; text-shadow: 0 4px 18px rgba(5, 12, 28, .25); white-space: nowrap; }
.login-brand h1 { margin: 0; color: var(--login-text-primary); font-size: clamp(22px, 2vw, 28px); font-weight: 700; line-height: 1.25; letter-spacing: .04em; text-shadow: 0 4px 18px rgba(5, 12, 28, .25); white-space: nowrap; }
.login-panel__intro { margin: 0 0 26px; color: var(--login-text-secondary); font-size: 14px; text-align: center; }
.login-form__item.el-form-item { margin-bottom: 16px; }.login-form__input .el-input__wrapper { min-height: 60px; padding: 0 18px; border: 1px solid var(--login-field-border); border-radius: 18px; background: linear-gradient(160deg, rgba(255, 255, 255, .012), rgba(255, 255, 255, .003)); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .035), inset 0 -1px 0 rgba(255, 255, 255, .008), 0 6px 18px rgba(5, 10, 22, .025); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); transition: border-color .2s ease, box-shadow .2s ease, background .2s ease; }.login-form__input .el-input__wrapper:hover { border-color: rgba(211, 225, 255, .13); }.login-form__input .el-input__wrapper.is-focus { border-color: var(--login-field-focus); background: linear-gradient(160deg, rgba(255, 255, 255, .025), rgba(255, 255, 255, .007)); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .055), 0 0 0 4px rgba(136, 182, 255, .055), 0 10px 24px rgba(4, 11, 24, .055); }.login-form__input .el-input__inner { color: var(--login-text-primary); }.login-form__input .el-input__inner::placeholder { color: rgba(224, 231, 255, .58); }.login-form__input .el-input__password { color: rgba(229, 236, 255, .74); }.login-form__input .el-input__password:hover { color: rgba(255, 255, 255, .96); }
.login-submit.el-button { width: 100%; height: 60px; margin-top: 8px; border: 1px solid rgba(205, 224, 255, .18); border-radius: 18px; background: linear-gradient(135deg, rgba(194, 223, 255, .46) 0%, rgba(120, 168, 255, .46) 40%, rgba(84, 127, 255, .50) 100%); color: #fff; font-size: 17px; font-weight: 700; letter-spacing: .08em; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 18px 30px rgba(60, 103, 207, .18), 0 4px 10px rgba(4, 9, 18, .16); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); transition: transform .2s ease, box-shadow .2s ease, opacity .2s ease, background .2s ease; }.login-submit.el-button:hover { transform: translateY(-1px); background: linear-gradient(135deg, rgba(194, 223, 255, .56), rgba(120, 168, 255, .56) 40%, rgba(84, 127, 255, .60)); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .42), 0 22px 36px rgba(60, 103, 207, .22), 0 6px 14px rgba(4, 9, 18, .22); }.login-submit.el-button:active { transform: translateY(1px) scale(.99); }.login-submit.el-button.is-loading, .login-submit.el-button.is-disabled { opacity: .76; transform: none; }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) { .login-panel { background: linear-gradient(145deg, rgba(10, 18, 37, .72), rgba(4, 8, 19, .62)); }.login-form__input .el-input__wrapper { background: rgba(7, 15, 32, .72); } }
@media (max-width: 980px) { .login-page { justify-content: center; padding-right: 24px; padding-left: 24px; background-position: 64% center; }.login-panel { margin: 0 auto; } }
@media (max-width: 640px) { .login-page { align-items: center; min-height: 100dvh; padding: 18px; background-position: 63% center; }.login-panel { padding: 26px 22px 24px; border-radius: 26px; }.login-brand { gap: 12px; justify-content: flex-start; }.login-brand__mark { width: 48px; height: 48px; border-radius: 16px; }.login-brand h1 { font-size: clamp(19px, 5.6vw, 22px); letter-spacing: .02em; }.login-brand__eyebrow { font-size: 9px; }.login-panel__intro { margin-bottom: 22px; text-align: left; }.login-form__input .el-input__wrapper, .login-submit.el-button { min-height: 56px; height: 56px; font-size: 16px; }.login-form__input .el-input__inner { font-size: 16px; } }
@media (max-width: 640px) { .login-page { align-items: center; min-height: 100dvh; padding: 18px; background-position: 63% center; }.login-panel { padding: 26px 22px 24px; border-radius: 26px; }.login-brand { gap: 12px; justify-content: flex-start; }.login-brand__mark { width: 48px; height: 48px; border-radius: 16px; }.login-brand h1 { font-size: clamp(19px, 5.6vw, 22px); letter-spacing: .02em; }.login-panel__intro { margin-bottom: 22px; text-align: left; }.login-form__input .el-input__wrapper, .login-submit.el-button { min-height: 56px; height: 56px; font-size: 16px; }.login-form__input .el-input__inner { font-size: 16px; } }
.logout-button { width: 100%; margin-top: 24px; padding: 10px 12px; border: 1px solid #496b8c; border-radius: 8px; color: #cbd5e1; background: transparent; cursor: pointer; }.logout-button:hover { color:#fff; background:#1f3b59; }
/* 后台外壳:把高度锁死在一屏,滚动交给侧栏和内容区各自承担,列表页才能按剩余空间计算表格高度。 */
.app-shell { height: 100dvh; min-height: 100dvh; overflow: hidden; display: grid; grid-template-columns: 232px minmax(0, 1fr); }
......@@ -30,7 +30,6 @@ body { margin: 0; }
.sidebar .settings-link { margin-top: 16px; border-top: 1px solid #385673; border-radius: 0; padding-top: 18px; }
.content { min-width: 0; height: 100%; overflow-y: auto; padding: 40px; }
.user-permission-page { max-width: 1180px; margin: 0 auto; }.user-permission-page small { display:block; margin-top:6px; color:#64748b; }.permission-hint { margin:-4px 0 16px; color:#64748b; font-size:13px; }
.eyebrow { margin: 0 0 8px; color: #5f8fcb; font-size: 12px; font-weight: 700; letter-spacing: .08em; }
.reference-page, .placeholder { max-width: 1180px; margin: 0 auto; }
.page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; margin-bottom: 28px; }
.page-header h2, .placeholder h2 { margin: 0 0 8px; font-size: 28px; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment