Merge pull request 'feat: add flutter mobile console and refine login ui' (#2) from codex/mobile-console-pr-clean into main

Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
2026-05-15 00:31:43 +08:00
87 changed files with 9822 additions and 157 deletions
+16 -157
View File
@@ -12,7 +12,7 @@ const router = useRouter();
const authStore = useAuthStore();
const loading = ref(false);
const { backendUnavailable, backendMessage } = useBackendStatus();
const { themeMode, resolvedTheme } = useUiPreferences();
const { themeMode } = useUiPreferences();
const form = reactive({
username: "admin",
@@ -52,39 +52,11 @@ async function handleLogin() {
<template>
<div class="login-screen">
<section class="login-hero">
<div class="login-hero__eyebrow">Live Recorder</div>
<h1 class="login-hero__title">把直播录制做成可长期维护的专业控制台</h1>
<p class="login-hero__subtitle">
统一管理直播间自动开录恢复流程系统日志事件脚本和日报回顾让录制系统像真正的运维平台一样稳定工作
</p>
<div class="login-hero__grid">
<article class="login-hero__tile">
<strong>实时监控</strong>
<span>直播间自动开录决策会话与分片状态集中可见</span>
</article>
<article class="login-hero__tile">
<strong>恢复能力</strong>
<span>中断转码暂停录制重启恢复都有统一入口</span>
</article>
<article class="login-hero__tile">
<strong>自动化</strong>
<span>邮件Webhook事件脚本与自定义日志全部贯通</span>
</article>
<article class="login-hero__tile">
<strong>回顾分析</strong>
<span>时间轴和日报帮助我们快速复盘每一场直播</span>
</article>
</div>
</section>
<section class="login-panel surface-card">
<div class="login-panel__header">
<div>
<div class="login-panel__kicker">Sign In</div>
<h2 class="login-panel__title">进入控制台</h2>
<p class="login-panel__subtitle">默认账户为 <span class="monospace">admin / Admin@123</span></p>
<div class="login-panel__eyebrow">Live Recorder</div>
<h1 class="login-panel__title">登录</h1>
</div>
<el-select v-model="themeMode" size="small" class="login-panel__theme-select">
@@ -123,14 +95,9 @@ async function handleLogin() {
</el-form-item>
<el-button class="login-form__submit" type="primary" :loading="loading" @click="handleLogin">
登录控制台
登录
</el-button>
</el-form>
<div class="login-panel__footer">
<span>当前主题{{ resolvedTheme === "dark" ? "深色" : "浅色" }}</span>
<span>双端适配Web / Mobile</span>
</div>
</section>
</div>
</template>
@@ -139,78 +106,12 @@ async function handleLogin() {
.login-screen {
min-height: 100vh;
display: grid;
grid-template-columns: minmax(0, 1.2fr) minmax(360px, 440px);
gap: 48px;
padding: 48px 56px;
}
.login-hero {
display: grid;
align-content: center;
gap: 24px;
}
.login-hero__eyebrow,
.login-panel__kicker {
color: var(--accent);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
}
.login-hero__title {
margin: 0;
max-width: 11ch;
color: var(--text-primary);
font-size: clamp(44px, 5vw, 72px);
font-weight: 780;
letter-spacing: -0.065em;
line-height: 0.94;
}
.login-hero__subtitle {
max-width: 60ch;
margin: 0;
color: var(--text-secondary);
font-size: 16px;
line-height: 1.85;
}
.login-hero__grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
max-width: 720px;
}
.login-hero__tile {
display: grid;
gap: 8px;
padding: 18px;
border-radius: 10px;
border: 1px solid var(--border-subtle);
background: rgba(255, 255, 255, 0.42);
box-shadow: var(--shadow-soft);
}
:global(html[data-theme="dark"]) .login-hero__tile {
background: rgba(255, 255, 255, 0.02);
}
.login-hero__tile strong {
color: var(--text-primary);
font-size: 14px;
}
.login-hero__tile span {
color: var(--text-secondary);
font-size: 13px;
line-height: 1.65;
place-items: center;
padding: 24px;
}
.login-panel {
align-self: center;
width: min(100%, 420px);
padding: 24px;
}
@@ -222,6 +123,14 @@ async function handleLogin() {
margin-bottom: 18px;
}
.login-panel__eyebrow {
color: var(--accent);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
}
.login-panel__title {
margin: 6px 0 0;
color: var(--text-primary);
@@ -230,13 +139,6 @@ async function handleLogin() {
letter-spacing: -0.045em;
}
.login-panel__subtitle {
margin: 10px 0 0;
color: var(--text-secondary);
font-size: 13px;
line-height: 1.6;
}
.login-panel__theme-select {
width: 122px;
}
@@ -250,59 +152,16 @@ async function handleLogin() {
margin-top: 8px;
}
.login-panel__footer {
display: flex;
justify-content: space-between;
gap: 12px;
margin-top: 18px;
padding-top: 16px;
border-top: 1px solid var(--border-subtle);
color: var(--text-muted);
font-size: 12px;
}
@media (max-width: 1100px) {
.login-screen {
grid-template-columns: 1fr;
gap: 28px;
padding: 28px 20px;
}
.login-hero__grid {
grid-template-columns: 1fr;
max-width: none;
}
.login-panel {
width: 100%;
max-width: 480px;
}
}
@media (max-width: 767px) {
.login-screen {
padding: 18px 14px 24px;
}
.login-hero {
gap: 18px;
}
.login-hero__title {
max-width: none;
font-size: clamp(34px, 12vw, 48px);
}
.login-hero__subtitle {
font-size: 14px;
}
.login-panel {
padding: 18px;
}
.login-panel__header,
.login-panel__footer {
.login-panel__header {
flex-direction: column;
}