diff --git a/android-webview-app/APP_CHANGELOG.md b/android-webview-app/APP_CHANGELOG.md index 02d59ff..a91583f 100644 --- a/android-webview-app/APP_CHANGELOG.md +++ b/android-webview-app/APP_CHANGELOG.md @@ -1,5 +1,10 @@ # App 更新说明 +# 1.0.17 +- 登录/注册页改为 Vue 实现,统一前端技术栈 +- 登录/注册页接入主题变量体系,自动跟随已保存主题(Claude / 浅色 / 深色) +- 移除登录/注册页独立主题切换控件,主题入口统一由主界面个人空间管理 + # 1.0.16 - 工作区顶部品牌图标改为内联 SVG 渲染(不再依赖静态路径加载) - 修复深色/浅色主题下 logo 颜色适配问题,跟随主题文本色显示 diff --git a/android-webview-app/app/build.gradle.kts b/android-webview-app/app/build.gradle.kts index 009dbbd..d2dc829 100644 --- a/android-webview-app/app/build.gradle.kts +++ b/android-webview-app/app/build.gradle.kts @@ -16,8 +16,8 @@ android { applicationId = "com.cyjai.agent" minSdk = 24 targetSdk = 35 - versionCode = 18 - versionName = "1.0.16" + versionCode = 19 + versionName = "1.0.17" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/static/login.html b/static/login.html index 9ef434b..5c42d21 100644 --- a/static/login.html +++ b/static/login.html @@ -1,207 +1,26 @@ - + - - - + + + 登录 - AI Agent - - - -
-

AI Agent 登录

-
- - -
-
- - -
- - -
- -
- - + + + +
+ + + diff --git a/static/register.html b/static/register.html index e3029c8..85e684f 100644 --- a/static/register.html +++ b/static/register.html @@ -1,156 +1,26 @@ - + - - - + + + 注册 - AI Agent - - - -
-

创建账号

-
- - -
-
- - -
-
- - -
-
- - -
- -
- -
- - + + + +
+ + + diff --git a/static/src/auth/LoginApp.vue b/static/src/auth/LoginApp.vue new file mode 100644 index 0000000..05c68d2 --- /dev/null +++ b/static/src/auth/LoginApp.vue @@ -0,0 +1,143 @@ + + + diff --git a/static/src/auth/RegisterApp.vue b/static/src/auth/RegisterApp.vue new file mode 100644 index 0000000..5a95e43 --- /dev/null +++ b/static/src/auth/RegisterApp.vue @@ -0,0 +1,125 @@ + + + diff --git a/static/src/auth/auth.scss b/static/src/auth/auth.scss new file mode 100644 index 0000000..81bd3ba --- /dev/null +++ b/static/src/auth/auth.scss @@ -0,0 +1,133 @@ +@use '../styles/base/tokens'; + +:root, +body { + margin: 0; + min-height: 100%; +} + +body { + min-height: 100vh; + font-family: + -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', sans-serif; + background: var(--claude-bg); + color: var(--claude-text); +} + +.auth-page { + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: 24px; + box-sizing: border-box; +} + +.auth-card { + width: min(100%, 390px); + padding: 30px; + border-radius: 18px; + background: var(--theme-surface-soft); + border: 1px solid var(--theme-control-border, var(--claude-border)); + box-shadow: var(--theme-shadow-mid, var(--claude-shadow)); + backdrop-filter: blur(8px); +} + +.auth-title { + margin: 0; + font-size: 1.4rem; +} + +.auth-subtitle { + margin-top: 8px; + margin-bottom: 0; + font-size: 0.9rem; + color: var(--claude-text-secondary); +} + +.auth-form-group { + margin-top: 14px; +} + +.auth-label { + display: block; + margin-bottom: 6px; + font-size: 0.86rem; + color: var(--claude-text-secondary); +} + +.auth-input { + width: 100%; + min-height: 46px; + box-sizing: border-box; + border-radius: 12px; + border: 1px solid var(--theme-control-border, var(--claude-border)); + background: var(--theme-surface-strong); + color: var(--claude-text); + padding: 11px 12px; + font-size: 0.95rem; + transition: + border-color 0.2s ease, + box-shadow 0.2s ease; +} + +.auth-input:focus { + outline: none; + border-color: var(--claude-accent-strong); + box-shadow: 0 0 0 3px var(--claude-highlight); +} + +.auth-button { + width: 100%; + margin-top: 18px; + border: none; + border-radius: 999px; + min-height: 44px; + font-size: 0.95rem; + cursor: pointer; + background: linear-gradient(135deg, var(--claude-accent), var(--claude-accent-strong)); + color: #fff; + transition: + transform 0.15s ease, + filter 0.15s ease; +} + +.auth-button:hover:not(:disabled) { + transform: translateY(-1px); + filter: brightness(1.02); +} + +.auth-button:disabled, +.auth-secondary-button:disabled { + opacity: 0.65; + cursor: not-allowed; +} + +.auth-secondary-button { + width: 100%; + margin-top: 10px; + border-radius: 999px; + min-height: 42px; + border: 1px solid var(--claude-accent-strong); + background: var(--theme-surface-strong); + color: var(--claude-accent-strong); + cursor: pointer; +} + +.auth-error { + min-height: 1.2em; + margin-top: 12px; + color: #e85b57; + font-size: 0.86rem; +} + +.auth-link { + margin-top: 16px; + font-size: 0.86rem; + color: var(--claude-text-secondary); +} + +.auth-link a { + color: var(--claude-accent-strong); + text-decoration: none; +} diff --git a/static/src/auth/loginMain.ts b/static/src/auth/loginMain.ts new file mode 100644 index 0000000..0619556 --- /dev/null +++ b/static/src/auth/loginMain.ts @@ -0,0 +1,5 @@ +import { createApp } from 'vue'; +import LoginApp from './LoginApp.vue'; +import './auth.scss'; + +createApp(LoginApp).mount('#auth-app'); diff --git a/static/src/auth/registerMain.ts b/static/src/auth/registerMain.ts new file mode 100644 index 0000000..a3f0535 --- /dev/null +++ b/static/src/auth/registerMain.ts @@ -0,0 +1,5 @@ +import { createApp } from 'vue'; +import RegisterApp from './RegisterApp.vue'; +import './auth.scss'; + +createApp(RegisterApp).mount('#auth-app'); diff --git a/static/src/auth/theme.ts b/static/src/auth/theme.ts new file mode 100644 index 0000000..1a7d5c5 --- /dev/null +++ b/static/src/auth/theme.ts @@ -0,0 +1,25 @@ +export type ThemeKey = 'claude' | 'light' | 'dark'; + +const THEME_STORAGE_KEY = 'agents_ui_theme'; + +export const isThemeKey = (value: unknown): value is ThemeKey => + value === 'claude' || value === 'light' || value === 'dark'; + +export const loadTheme = (): ThemeKey => { + if (typeof window === 'undefined') return 'claude'; + const saved = window.localStorage.getItem(THEME_STORAGE_KEY); + return isThemeKey(saved) ? saved : 'claude'; +}; + +export const applyTheme = (theme: ThemeKey) => { + const root = document.documentElement; + root.setAttribute('data-theme', theme); + document.body.setAttribute('data-theme', theme); +}; + +export const setTheme = (theme: ThemeKey) => { + if (typeof window !== 'undefined') { + window.localStorage.setItem(THEME_STORAGE_KEY, theme); + } + applyTheme(theme); +}; diff --git a/vite.config.ts b/vite.config.ts index d39eabf..44138b6 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -4,10 +4,18 @@ import vue from '@vitejs/plugin-vue'; const entry = fileURLToPath(new URL('./static/src/main.ts', import.meta.url)); const adminEntry = fileURLToPath(new URL('./static/src/admin/main.ts', import.meta.url)); -const adminPolicyEntry = fileURLToPath(new URL('./static/src/admin/policyMain.ts', import.meta.url)); -const adminCustomToolsEntry = fileURLToPath(new URL('./static/src/admin/customToolsMain.ts', import.meta.url)); -const adminCustomToolsGuideEntry = fileURLToPath(new URL('./static/src/admin/customToolsGuideMain.ts', import.meta.url)); +const adminPolicyEntry = fileURLToPath( + new URL('./static/src/admin/policyMain.ts', import.meta.url) +); +const adminCustomToolsEntry = fileURLToPath( + new URL('./static/src/admin/customToolsMain.ts', import.meta.url) +); +const adminCustomToolsGuideEntry = fileURLToPath( + new URL('./static/src/admin/customToolsGuideMain.ts', import.meta.url) +); const adminApiEntry = fileURLToPath(new URL('./static/src/admin/apiMain.ts', import.meta.url)); +const loginEntry = fileURLToPath(new URL('./static/src/auth/loginMain.ts', import.meta.url)); +const registerEntry = fileURLToPath(new URL('./static/src/auth/registerMain.ts', import.meta.url)); export default defineConfig({ plugins: [vue()], @@ -21,7 +29,9 @@ export default defineConfig({ adminPolicy: adminPolicyEntry, adminCustomTools: adminCustomToolsEntry, adminCustomToolsGuide: adminCustomToolsGuideEntry, - adminApi: adminApiEntry + adminApi: adminApiEntry, + login: loginEntry, + register: registerEntry }, output: { entryFileNames: 'assets/[name].js',