diff --git a/app/pages/auth/login.vue b/app/pages/auth/login.vue index a9d2f50..b4e5920 100644 --- a/app/pages/auth/login.vue +++ b/app/pages/auth/login.vue @@ -25,11 +25,11 @@ const { refresh } = useAuthSession() const router = useRouter() async function loginWithGithub() { - window.location.href = '/api/auth/oauth/github/authorize'; + window.location.href = '/api/auth/oauth/github/authorize' } async function loginWithGitea() { - window.location.href = '/api/auth/oauth/gitea/authorize'; + window.location.href = '/api/auth/oauth/gitea/authorize' } async function fetchCaptcha() { @@ -90,84 +90,92 @@ onMounted(() => { @@ -190,161 +198,113 @@ onMounted(() => { overflow: hidden; } -.bg-gradient-top { - position: absolute; - top: 0; - left: 0; - right: 0; - height: 280px; - background: linear-gradient(180deg, rgba(204, 120, 92, 0.08) 0%, transparent 100%); -} - -.bg-gradient-bottom { - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 200px; - background: linear-gradient(0deg, rgba(204, 120, 92, 0.05) 0%, transparent 100%); -} - .bg-accent-block { position: absolute; border-radius: 50%; - filter: blur(80px); + filter: blur(150px); } .bg-accent-block-1 { - width: 500px; - height: 500px; + width: 800px; + height: 800px; background: var(--color-primary); - top: -150px; - right: 10%; + top: -300px; + right: -200px; opacity: 0.1; } .bg-accent-block-2 { - width: 400px; - height: 400px; + width: 600px; + height: 600px; background: var(--color-accent-amber); - bottom: -100px; - left: 20%; + bottom: -200px; + left: -150px; opacity: 0.06; } -.bg-accent-block-3 { - width: 300px; - height: 300px; - background: var(--color-primary); - bottom: 20%; - right: -100px; - opacity: 0.08; -} - .bg-grid { position: absolute; inset: 0; - background-image: radial-gradient(circle, var(--color-hairline) 1px, transparent 1px); - background-size: 20px 20px; - opacity: 0.4; -} - -.bg-spike-spots { - position: absolute; - inset: 0; -} - -.spike { - position: absolute; - width: 40px; - height: 40px; - opacity: 0.06; + background-image: linear-gradient(var(--color-hairline) 1px, transparent 1px), + linear-gradient(90deg, var(--color-hairline) 1px, transparent 1px); + background-size: 48px 48px; + opacity: 0.2; } -.spike::before, -.spike::after { - content: ''; - position: absolute; - background: var(--color-ink); -} - -.spike::before { +.auth-layout { + display: grid; + grid-template-columns: 1.2fr 1fr; + gap: 120px; + max-width: 1000px; width: 100%; - height: 2px; - top: 50%; - left: 0; - transform: translateY(-50%); + padding: 64px; + position: relative; + z-index: 1; + align-items: center; } -.spike::after { - width: 2px; - height: 100%; - left: 50%; - top: 0; - transform: translateX(-50%); +.auth-brand { + display: flex; + flex-direction: column; + gap: 20px; } -.spike-1 { - top: 15%; - left: 10%; - transform: rotate(15deg); +.brand-mark { + margin-bottom: 12px; } -.spike-2 { - top: 25%; - right: 15%; - transform: rotate(45deg); +.brand-wordmark { + font-family: var(--font-display); + font-size: 56px; + font-weight: 400; + color: var(--color-ink); + letter-spacing: -2px; + line-height: 1; + margin: 0; } -.spike-3 { - bottom: 20%; - left: 15%; - transform: rotate(30deg); +.brand-tagline { + font-family: var(--font-body); + font-size: 18px; + color: var(--color-muted); + margin: 0; + letter-spacing: 1px; } -.spike-4 { - bottom: 30%; - right: 10%; - transform: rotate(60deg); +.auth-form-wrap { + display: flex; + flex-direction: column; } -.auth-card { - width: 100%; - max-width: 420px; - background: var(--color-canvas); - border-radius: 12px; - box-shadow: 0 2px 12px rgba(20, 20, 19, 0.06); - padding: 40px; - position: relative; - z-index: 1; - margin: 24px; +.form-header { + margin-bottom: 48px; } -.form-header { - margin-bottom: 32px; +.form-kicker { + font-family: var(--font-body); + font-size: 10px; + font-weight: 500; + color: var(--color-primary); + letter-spacing: 4px; + text-transform: uppercase; + display: block; + margin-bottom: 14px; } .form-title { font-family: var(--font-display); - font-size: 32px; + font-size: 42px; font-weight: 400; color: var(--color-ink); letter-spacing: -1px; - line-height: 1.1; - margin: 0 0 8px; -} - -.form-subtitle { - font-family: var(--font-body); - font-size: 15px; - color: var(--color-muted); + line-height: 1; margin: 0; } .auth-form { display: flex; flex-direction: column; - gap: 20px; + gap: 28px; } .form-field { @@ -353,15 +313,15 @@ onMounted(() => { .form-field input { width: 100%; - padding: 20px 16px 8px; + padding: 22px 16px 8px; font-family: var(--font-body); font-size: 16px; color: var(--color-ink); background: var(--color-canvas); - border: 1.5px solid var(--color-hairline); - border-radius: 8px; + border: none; + border-bottom: 2px solid var(--color-hairline); outline: none; - transition: border-color 0.2s ease, box-shadow 0.2s ease; + transition: border-color 0.2s ease; box-sizing: border-box; } @@ -382,13 +342,12 @@ onMounted(() => { } .form-field input:focus { - border-color: var(--color-primary); - box-shadow: 0 0 0 4px rgba(204, 120, 92, 0.1); + border-bottom-color: var(--color-primary); } .form-field input:focus + label, .form-field input:not(:placeholder-shown) + label { - top: 12px; + top: 10px; font-size: 11px; color: var(--color-primary); letter-spacing: 0.5px; @@ -399,10 +358,11 @@ onMounted(() => { right: 16px; top: 50%; transform: translateY(-50%); - font-size: 12px; + font-size: 11px; color: var(--color-primary); text-decoration: none; font-weight: 500; + letter-spacing: 0.5px; } .field-link:hover { @@ -418,15 +378,14 @@ onMounted(() => { right: 8px; top: 50%; transform: translateY(-50%); - height: 36px; - border-radius: 4px; + height: 40px; cursor: pointer; transition: opacity 0.2s; } .captcha-img :deep(svg) { display: block; - height: 36px; + height: 40px; } .captcha-img.loading { @@ -442,7 +401,7 @@ onMounted(() => { .checkbox-field { display: flex; align-items: center; - gap: 10px; + gap: 12px; cursor: pointer; } @@ -457,7 +416,6 @@ onMounted(() => { width: 18px; height: 18px; border: 1.5px solid var(--color-hairline); - border-radius: 4px; background: var(--color-canvas); display: flex; align-items: center; @@ -483,51 +441,38 @@ onMounted(() => { .checkbox-field span:last-child { font-size: 13px; color: var(--color-muted); + letter-spacing: 0.5px; } .submit-btn { display: flex; align-items: center; justify-content: center; - gap: 12px; + gap: 14px; width: 100%; - padding: 18px 24px; + padding: 20px 32px; font-family: var(--font-body); - font-size: 15px; + font-size: 13px; font-weight: 500; + letter-spacing: 2px; + text-transform: uppercase; color: var(--color-on-primary); - background: var(--color-primary); + background: var(--color-ink); border: none; - border-radius: 8px; cursor: pointer; - transition: background 0.2s ease, transform 0.15s ease; - position: relative; - overflow: hidden; -} - -.submit-btn::before { - content: ''; - position: absolute; - inset: 0; - background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.15), transparent); - transform: translateX(-100%); - transition: transform 0.5s ease; -} - -.submit-btn:hover::before { - transform: translateX(100%); + transition: background 0.2s ease; } .submit-btn:hover { - background: var(--color-primary-active); + background: var(--color-primary); } .submit-btn:active { - transform: scale(0.98); + transform: scale(0.99); } .submit-btn.loading { - opacity: 0.7; + opacity: 0.6; cursor: not-allowed; } @@ -537,14 +482,14 @@ onMounted(() => { } .submit-btn:hover .btn-arrow { - transform: translateX(4px); + transform: translateX(5px); } .form-divider { display: flex; align-items: center; - gap: 16px; - margin: 24px 0; + gap: 20px; + margin: 40px 0; } .divider-line { @@ -554,31 +499,31 @@ onMounted(() => { } .divider-text { - font-size: 12px; + font-size: 10px; color: var(--color-muted-soft); text-transform: uppercase; - letter-spacing: 1px; + letter-spacing: 3px; } .social-row { - display: flex; - gap: 12px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; } .social-btn { - flex: 1; display: flex; align-items: center; justify-content: center; gap: 10px; - padding: 14px 16px; + padding: 16px 20px; font-family: var(--font-body); - font-size: 14px; + font-size: 12px; font-weight: 500; - color: var(--color-muted); + letter-spacing: 1px; + color: var(--color-body); background: var(--color-canvas); - border: 1.5px solid var(--color-hairline); - border-radius: 10px; + border: 1px solid var(--color-hairline); cursor: pointer; transition: all 0.2s ease; } @@ -586,16 +531,16 @@ onMounted(() => { .social-btn:hover { color: var(--color-ink); background: var(--color-surface-soft); - border-color: var(--color-hairline-soft); + border-color: var(--color-ink); } .social-btn:active { - transform: scale(0.97); + transform: scale(0.98); } .form-footer { text-align: center; - margin-top: 24px; + margin-top: 40px; font-size: 14px; color: var(--color-muted); } @@ -609,4 +554,21 @@ onMounted(() => { .form-footer a:hover { text-decoration: underline; } + +@media (max-width: 768px) { + .auth-layout { + grid-template-columns: 1fr; + gap: 64px; + padding: 32px; + } + + .auth-brand { + align-items: center; + text-align: center; + } + + .brand-wordmark { + font-size: 42px; + } +} \ No newline at end of file diff --git a/app/pages/auth/register.vue b/app/pages/auth/register.vue index 4967f7d..a3758f5 100644 --- a/app/pages/auth/register.vue +++ b/app/pages/auth/register.vue @@ -20,6 +20,10 @@ const captcha = reactive({ const registerLoading = ref(false) +async function loginWithGoogle() { + window.location.href = '/api/auth/oauth/google/authorize' +} + async function fetchCaptcha() { captcha.loading = true try { @@ -66,73 +70,81 @@ onMounted(fetchCaptcha) @@ -155,161 +167,113 @@ onMounted(fetchCaptcha) overflow: hidden; } -.bg-gradient-top { - position: absolute; - top: 0; - left: 0; - right: 0; - height: 280px; - background: linear-gradient(180deg, rgba(204, 120, 92, 0.08) 0%, transparent 100%); -} - -.bg-gradient-bottom { - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 200px; - background: linear-gradient(0deg, rgba(204, 120, 92, 0.05) 0%, transparent 100%); -} - .bg-accent-block { position: absolute; border-radius: 50%; - filter: blur(80px); + filter: blur(150px); } .bg-accent-block-1 { - width: 500px; - height: 500px; + width: 800px; + height: 800px; background: var(--color-primary); - top: -150px; - right: 10%; + top: -300px; + right: -200px; opacity: 0.1; } .bg-accent-block-2 { - width: 400px; - height: 400px; + width: 600px; + height: 600px; background: var(--color-accent-amber); - bottom: -100px; - left: 20%; + bottom: -200px; + left: -150px; opacity: 0.06; } -.bg-accent-block-3 { - width: 300px; - height: 300px; - background: var(--color-primary); - bottom: 20%; - right: -100px; - opacity: 0.08; -} - .bg-grid { position: absolute; inset: 0; - background-image: radial-gradient(circle, var(--color-hairline) 1px, transparent 1px); - background-size: 20px 20px; - opacity: 0.4; -} - -.bg-spike-spots { - position: absolute; - inset: 0; -} - -.spike { - position: absolute; - width: 40px; - height: 40px; - opacity: 0.06; + background-image: linear-gradient(var(--color-hairline) 1px, transparent 1px), + linear-gradient(90deg, var(--color-hairline) 1px, transparent 1px); + background-size: 48px 48px; + opacity: 0.2; } -.spike::before, -.spike::after { - content: ''; - position: absolute; - background: var(--color-ink); -} - -.spike::before { +.auth-layout { + display: grid; + grid-template-columns: 1.2fr 1fr; + gap: 120px; + max-width: 1000px; width: 100%; - height: 2px; - top: 50%; - left: 0; - transform: translateY(-50%); + padding: 64px; + position: relative; + z-index: 1; + align-items: center; } -.spike::after { - width: 2px; - height: 100%; - left: 50%; - top: 0; - transform: translateX(-50%); +.auth-brand { + display: flex; + flex-direction: column; + gap: 20px; } -.spike-1 { - top: 15%; - left: 10%; - transform: rotate(15deg); +.brand-mark { + margin-bottom: 12px; } -.spike-2 { - top: 25%; - right: 15%; - transform: rotate(45deg); +.brand-wordmark { + font-family: var(--font-display); + font-size: 56px; + font-weight: 400; + color: var(--color-ink); + letter-spacing: -2px; + line-height: 1; + margin: 0; } -.spike-3 { - bottom: 20%; - left: 15%; - transform: rotate(30deg); +.brand-tagline { + font-family: var(--font-body); + font-size: 18px; + color: var(--color-muted); + margin: 0; + letter-spacing: 1px; } -.spike-4 { - bottom: 30%; - right: 10%; - transform: rotate(60deg); +.auth-form-wrap { + display: flex; + flex-direction: column; } -.auth-card { - width: 100%; - max-width: 420px; - background: var(--color-canvas); - border-radius: 12px; - box-shadow: 0 2px 12px rgba(20, 20, 19, 0.06); - padding: 40px; - position: relative; - z-index: 1; - margin: 24px; +.form-header { + margin-bottom: 48px; } -.form-header { - margin-bottom: 32px; +.form-kicker { + font-family: var(--font-body); + font-size: 10px; + font-weight: 500; + color: var(--color-primary); + letter-spacing: 4px; + text-transform: uppercase; + display: block; + margin-bottom: 14px; } .form-title { font-family: var(--font-display); - font-size: 32px; + font-size: 42px; font-weight: 400; color: var(--color-ink); letter-spacing: -1px; - line-height: 1.1; - margin: 0 0 8px; -} - -.form-subtitle { - font-family: var(--font-body); - font-size: 15px; - color: var(--color-muted); + line-height: 1; margin: 0; } .auth-form { display: flex; flex-direction: column; - gap: 20px; + gap: 28px; } .form-field { @@ -318,15 +282,15 @@ onMounted(fetchCaptcha) .form-field input { width: 100%; - padding: 20px 16px 8px; + padding: 22px 16px 8px; font-family: var(--font-body); font-size: 16px; color: var(--color-ink); background: var(--color-canvas); - border: 1.5px solid var(--color-hairline); - border-radius: 8px; + border: none; + border-bottom: 2px solid var(--color-hairline); outline: none; - transition: border-color 0.2s ease, box-shadow 0.2s ease; + transition: border-color 0.2s ease; box-sizing: border-box; } @@ -347,13 +311,12 @@ onMounted(fetchCaptcha) } .form-field input:focus { - border-color: var(--color-primary); - box-shadow: 0 0 0 4px rgba(204, 120, 92, 0.1); + border-bottom-color: var(--color-primary); } .form-field input:focus + label, .form-field input:not(:placeholder-shown) + label { - top: 12px; + top: 10px; font-size: 11px; color: var(--color-primary); letter-spacing: 0.5px; @@ -368,15 +331,14 @@ onMounted(fetchCaptcha) right: 8px; top: 50%; transform: translateY(-50%); - height: 36px; - border-radius: 4px; + height: 40px; cursor: pointer; transition: opacity 0.2s; } .captcha-img :deep(svg) { display: block; - height: 36px; + height: 40px; } .captcha-img.loading { @@ -387,45 +349,31 @@ onMounted(fetchCaptcha) display: flex; align-items: center; justify-content: center; - gap: 12px; + gap: 14px; width: 100%; - padding: 18px 24px; + padding: 20px 32px; font-family: var(--font-body); - font-size: 15px; + font-size: 13px; font-weight: 500; + letter-spacing: 2px; + text-transform: uppercase; color: var(--color-on-primary); - background: var(--color-primary); + background: var(--color-ink); border: none; - border-radius: 8px; cursor: pointer; - transition: background 0.2s ease, transform 0.15s ease; - position: relative; - overflow: hidden; -} - -.submit-btn::before { - content: ''; - position: absolute; - inset: 0; - background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.15), transparent); - transform: translateX(-100%); - transition: transform 0.5s ease; -} - -.submit-btn:hover::before { - transform: translateX(100%); + transition: background 0.2s ease; } .submit-btn:hover { - background: var(--color-primary-active); + background: var(--color-primary); } .submit-btn:active { - transform: scale(0.98); + transform: scale(0.99); } .submit-btn.loading { - opacity: 0.7; + opacity: 0.6; cursor: not-allowed; } @@ -435,14 +383,14 @@ onMounted(fetchCaptcha) } .submit-btn:hover .btn-arrow { - transform: translateX(4px); + transform: translateX(5px); } .form-divider { display: flex; align-items: center; - gap: 16px; - margin: 24px 0; + gap: 20px; + margin: 40px 0; } .divider-line { @@ -452,10 +400,10 @@ onMounted(fetchCaptcha) } .divider-text { - font-size: 12px; + font-size: 10px; color: var(--color-muted-soft); text-transform: uppercase; - letter-spacing: 1px; + letter-spacing: 3px; } .social-btn { @@ -464,26 +412,31 @@ onMounted(fetchCaptcha) justify-content: center; gap: 12px; width: 100%; - padding: 16px 20px; + padding: 18px 24px; font-family: var(--font-body); - font-size: 14px; + font-size: 12px; font-weight: 500; - color: var(--color-ink); + letter-spacing: 1px; + color: var(--color-body); background: var(--color-canvas); - border: 1.5px solid var(--color-hairline); - border-radius: 8px; + border: 1px solid var(--color-hairline); cursor: pointer; - transition: background 0.2s ease, border-color 0.2s ease; + transition: all 0.2s ease; } .social-btn:hover { + color: var(--color-ink); background: var(--color-surface-soft); - border-color: var(--color-hairline-soft); + border-color: var(--color-ink); +} + +.social-btn:active { + transform: scale(0.98); } .form-footer { text-align: center; - margin-top: 24px; + margin-top: 40px; font-size: 14px; color: var(--color-muted); } @@ -497,4 +450,21 @@ onMounted(fetchCaptcha) .form-footer a:hover { text-decoration: underline; } + +@media (max-width: 768px) { + .auth-layout { + grid-template-columns: 1fr; + gap: 64px; + padding: 32px; + } + + .auth-brand { + align-items: center; + text-align: center; + } + + .brand-wordmark { + font-size: 42px; + } +} \ No newline at end of file diff --git a/packages/bolt-ui/components/ConfigProvider/src/ConfigProvider.vue b/packages/bolt-ui/components/ConfigProvider/src/ConfigProvider.vue index 19cfeec..2588094 100644 --- a/packages/bolt-ui/components/ConfigProvider/src/ConfigProvider.vue +++ b/packages/bolt-ui/components/ConfigProvider/src/ConfigProvider.vue @@ -3,10 +3,10 @@ diff --git a/packages/bolt-ui/components/ConfigProvider/src/config.ts b/packages/bolt-ui/components/ConfigProvider/src/config.ts index dc580f7..4d0ea36 100644 --- a/packages/bolt-ui/components/ConfigProvider/src/config.ts +++ b/packages/bolt-ui/components/ConfigProvider/src/config.ts @@ -1,5 +1,5 @@ import type { LanguagesType } from 'bolt-ui/locales' -export interface IConfig { locale: LanguagesType } +export interface IConfig { locale?: LanguagesType } export const defaultConfig: IConfig = { locale: 'zh' } \ No newline at end of file diff --git a/packages/bolt-ui/components/Container/src/Container.vue b/packages/bolt-ui/components/Container/src/Container.vue index 46f526b..8b70517 100644 --- a/packages/bolt-ui/components/Container/src/Container.vue +++ b/packages/bolt-ui/components/Container/src/Container.vue @@ -6,8 +6,7 @@ \ No newline at end of file diff --git a/packages/drizzle-pkg/db.sqlite b/packages/drizzle-pkg/db.sqlite index d9d0260..330c271 100644 Binary files a/packages/drizzle-pkg/db.sqlite and b/packages/drizzle-pkg/db.sqlite differ