Files
MrleeAdmin/frontend/app/pages/auth/login.vue
T

285 lines
5.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="auth-page" :class="`theme-${themeMode}`">
<view class="bg-circle bg-circle-primary"></view>
<view class="bg-circle bg-circle-light"></view>
<view class="brand-area">
<view class="brand-mark">
<u-icon name="scan" color="#ffffff" size="52" />
</view>
<text class="brand-title">扫码生产助手</text>
<text class="brand-subtitle">登录后开始扫码录入生产数据</text>
</view>
<view class="auth-panel">
<view class="panel-header">
<text class="panel-title">账号登录</text>
<text class="panel-desc">请输入账号和密码</text>
</view>
<u-form :model="form" :border-bottom="false" label-position="top" label-width="120">
<u-form-item prop="account" :border-bottom="false">
<view class="field-card">
<view class="field-icon">
<u-icon name="account-fill" color="#1677ff" size="36" />
</view>
<u-input v-model="form.account" clearable placeholder="请输入账号/手机号" placeholder-style="color: #a0a7b5;" />
</view>
</u-form-item>
<u-form-item prop="password" :border-bottom="false">
<view class="field-card">
<view class="field-icon">
<u-icon name="lock-fill" color="#1677ff" size="36" />
</view>
<u-input v-model="form.password" type="password" clearable password-icon placeholder="请输入密码" placeholder-style="color: #a0a7b5;" />
</view>
</u-form-item>
</u-form>
<view class="actions">
<u-button type="primary" shape="circle" size="large" :loading="loading" @click="handleLogin">登录</u-button>
</view>
<view class="footer-link">
<text>还没有账号?</text>
<text class="link" @tap="goRegister">立即注册</text>
</view>
</view>
</view>
</template>
<script>
import { login } from '@/api/auth.js'
export default {
data() {
return {
loading: false,
redirectUrl: '/pages/index/index',
form: {
account: '',
password: ''
}
}
},
onLoad(options = {}) {
if (options.redirect) {
this.redirectUrl = decodeURIComponent(options.redirect)
}
},
methods: {
async handleLogin() {
if (!this.form.account || !this.form.password) {
uni.showToast({
title: '请输入账号和密码',
icon: 'none'
})
return
}
this.loading = true
try {
const result = await login({
username: this.form.account,
password: this.form.password
})
const accessToken = result?.access_token || result?.token?.access_token
if (!accessToken) {
throw new Error('登录响应缺少访问令牌')
}
uni.setStorageSync('scanapp_token', accessToken)
if (result?.refresh_token || result?.token?.refresh_token) {
uni.setStorageSync('scanapp_refresh_token', result.refresh_token || result.token.refresh_token)
}
if (result?.user_info) {
uni.setStorageSync('scanapp_user', result.user_info)
}
uni.showToast({ title: '登录成功', icon: 'none' })
setTimeout(() => {
uni.redirectTo({ url: this.redirectUrl })
}, 300)
} catch (error) {
console.error('[scanapp] 登录失败', error)
} finally {
this.loading = false
}
},
goRegister() {
uni.navigateTo({
url: '/pages/auth/register'
})
}
}
}
</script>
<style lang="scss" scoped>
.auth-page {
position: relative;
overflow: hidden;
min-height: 100vh;
padding: 92rpx 40rpx 48rpx;
box-sizing: border-box;
background: linear-gradient(180deg, #eaf4ff 0%, #f6f8fc 50%, #ffffff 100%);
}
.bg-circle {
position: absolute;
border-radius: 50%;
pointer-events: none;
}
.bg-circle-primary {
top: -120rpx;
right: -90rpx;
width: 300rpx;
height: 300rpx;
background: rgba(22, 119, 255, 0.12);
}
.bg-circle-light {
top: 160rpx;
left: -140rpx;
width: 260rpx;
height: 260rpx;
background: rgba(53, 191, 163, 0.12);
}
.brand-area {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 64rpx;
}
.brand-mark {
display: flex;
align-items: center;
justify-content: center;
width: 120rpx;
height: 120rpx;
margin-bottom: 24rpx;
border-radius: 36rpx;
background: linear-gradient(135deg, #1677ff 0%, #35bfa3 100%);
box-shadow: 0 20rpx 46rpx rgba(22, 119, 255, 0.26);
}
.brand-title {
color: #17233d;
font-size: 38rpx;
font-weight: 700;
line-height: 1.35;
}
.brand-subtitle {
margin-top: 12rpx;
color: #6b778c;
font-size: 22rpx;
line-height: 1.5;
}
.auth-panel {
position: relative;
z-index: 1;
padding: 44rpx 32rpx 38rpx;
border: 1rpx solid rgba(255, 255, 255, 0.8);
border-radius: 32rpx;
background: rgba(255, 255, 255, 0.96);
box-shadow: 0 22rpx 60rpx rgba(23, 35, 61, 0.1);
}
.panel-header {
margin-bottom: 24rpx;
}
.panel-title {
display: block;
color: #17233d;
font-size: 28rpx;
font-weight: 700;
line-height: 1.4;
}
.panel-desc {
display: block;
margin-top: 8rpx;
color: #8a94a6;
font-size: 22rpx;
line-height: 1.5;
}
.actions {
margin-top: 36rpx;
}
.field-card {
display: flex;
align-items: center;
width: 100%;
height: 96rpx;
padding: 0 24rpx;
box-sizing: border-box;
border: 1rpx solid #edf1f7;
border-radius: 22rpx;
background: #f8fbff;
}
.field-icon {
display: flex;
align-items: center;
justify-content: center;
width: 52rpx;
height: 52rpx;
margin-right: 14rpx;
border-radius: 16rpx;
background: rgba(22, 119, 255, 0.1);
}
.footer-link {
display: flex;
justify-content: center;
align-items: center;
margin-top: 32rpx;
color: #8a94a6;
font-size: 22rpx;
}
.link {
margin-left: 8rpx;
color: #1677ff;
font-weight: 600;
}
.theme-dark.auth-page {
background: linear-gradient(180deg, #111827 0%, #151923 50%, #151923 100%);
}
.theme-dark .auth-panel {
border-color: #364152;
background: #222936;
box-shadow: none;
}
.theme-dark .field-card {
border-color: #364152;
background: #1c2431;
}
.theme-dark .panel-title {
color: #f2f5fa;
}
.theme-dark .panel-desc,
.theme-dark .footer-link {
color: #aeb9ca;
}
.theme-dark :deep(.u-input__input) {
color: #f2f5fa !important;
}
</style>