211 lines
5.5 KiB
Vue
211 lines
5.5 KiB
Vue
<template>
|
||
<AppPage :show-footer="true" bg-cover :style="{ backgroundImage: `url(${bgImg})` }">
|
||
<div
|
||
style="transform: translateY(25px)"
|
||
class="m-auto max-w-700 min-w-345 f-c-c rounded-10 bg-white bg-opacity-60 p-15 card-shadow"
|
||
dark:bg-dark
|
||
>
|
||
<div hidden w-380 px-20 py-35 md:block>
|
||
<img src="@/assets/images/login_banner.webp" w-full alt="login_banner" />
|
||
</div>
|
||
|
||
<div w-320 flex-col px-20 py-35>
|
||
<h5 f-c-c text-24 font-normal color="#6a6a6a">
|
||
<img src="@/assets/images/logo.png" height="50" class="mr-10" />
|
||
{{ title }}
|
||
</h5>
|
||
<!-- 接口线路选择 -->
|
||
<div mt-20>
|
||
<n-select
|
||
v-model:value="selectedEndpoint"
|
||
:options="endpointOptions"
|
||
placeholder="选择接口线路"
|
||
size="large"
|
||
@update:value="handleEndpointChange"
|
||
/>
|
||
</div>
|
||
<div mt-10>
|
||
<n-input
|
||
v-model:value="loginInfo.name"
|
||
autofocus
|
||
class="h-50 items-center pl-10 text-16"
|
||
placeholder="请输入账号"
|
||
:maxlength="20"
|
||
/>
|
||
</div>
|
||
<div mt-10>
|
||
<n-input
|
||
v-model:value="loginInfo.password"
|
||
class="h-50 items-center pl-10 text-16"
|
||
type="password"
|
||
show-password-on="mousedown"
|
||
placeholder="请输入密码"
|
||
:maxlength="20"
|
||
@keypress.enter="handleLogin"
|
||
/>
|
||
</div>
|
||
|
||
<div mt-20>
|
||
<n-checkbox
|
||
:checked="isRemember"
|
||
label="记住我"
|
||
:on-update:checked="(val) => (isRemember = val)"
|
||
/>
|
||
</div>
|
||
|
||
<div mt-20>
|
||
<n-button
|
||
h-50
|
||
w-full
|
||
rounded-5
|
||
text-16
|
||
type="primary"
|
||
:loading="loading"
|
||
@click="handleLogin"
|
||
>
|
||
登录
|
||
</n-button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</AppPage>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { lStorage, setToken } from '@/utils'
|
||
import { useStorage } from '@vueuse/core'
|
||
import bgImg from '@/assets/images/login_bg.webp'
|
||
import api from './api'
|
||
import { addDynamicRoutes } from '@/router'
|
||
import {
|
||
getAvailableEndpoints,
|
||
setCurrentEndpoint,
|
||
getCurrentEndpoint,
|
||
initApiEndpoint,
|
||
} from '@/utils/api-config'
|
||
|
||
const title = import.meta.env.VITE_TITLE
|
||
|
||
const router = useRouter()
|
||
const { query } = useRoute()
|
||
|
||
const loginInfo = ref({
|
||
name: '',
|
||
password: '',
|
||
})
|
||
|
||
initLoginInfo()
|
||
|
||
function initLoginInfo() {
|
||
const localLoginInfo = lStorage.get('loginInfo')
|
||
if (localLoginInfo) {
|
||
loginInfo.value.name = localLoginInfo.name || ''
|
||
loginInfo.value.password = localLoginInfo.password || ''
|
||
}
|
||
}
|
||
|
||
const isRemember = useStorage('isRemember', false)
|
||
const loading = ref(false)
|
||
|
||
// 接口线路相关
|
||
const selectedEndpoint = ref('primary')
|
||
const endpointOptions = ref([])
|
||
|
||
// 初始化接口配置
|
||
initApiEndpoint()
|
||
const currentEndpoint = getCurrentEndpoint()
|
||
selectedEndpoint.value = currentEndpoint.key
|
||
|
||
// 加载接口选项
|
||
function loadEndpointOptions() {
|
||
const endpoints = getAvailableEndpoints()
|
||
endpointOptions.value = endpoints.map((endpoint) => ({
|
||
label: endpoint.name,
|
||
value: endpoint.key,
|
||
}))
|
||
}
|
||
|
||
// 处理接口切换
|
||
function handleEndpointChange(value) {
|
||
if (setCurrentEndpoint(value)) {
|
||
selectedEndpoint.value = value
|
||
$message.success(`已切换到${endpointOptions.value.find((opt) => opt.value === value)?.label}`)
|
||
} else {
|
||
$message.error('接口切换失败')
|
||
}
|
||
}
|
||
|
||
// 初始化
|
||
onMounted(() => {
|
||
loadEndpointOptions()
|
||
})
|
||
|
||
// 获取第一个可用的路由页面
|
||
function getFirstAvailableRoute(menuData) {
|
||
if (!menuData || !Array.isArray(menuData)) return null
|
||
|
||
// 递归查找第一个type为2的路由(页面路由)
|
||
function findFirstPageRoute(routes) {
|
||
for (const route of routes) {
|
||
if (route.type === 2 && route.route) {
|
||
return route.route
|
||
}
|
||
if (route.subMenu && route.subMenu.length) {
|
||
const found = findFirstPageRoute(route.subMenu)
|
||
if (found) return found
|
||
}
|
||
}
|
||
return null
|
||
}
|
||
|
||
return findFirstPageRoute(menuData)
|
||
}
|
||
|
||
async function handleLogin() {
|
||
const { name, password } = loginInfo.value
|
||
if (!name || !password) {
|
||
$message.warning('请输入用户名和密码')
|
||
return
|
||
}
|
||
try {
|
||
loading.value = true
|
||
$message.loading('正在验证...')
|
||
|
||
console.log('开始登录请求...')
|
||
console.log('登录数据:', { phone: name, password: password.toString() })
|
||
console.log('当前选中接口:', selectedEndpoint.value)
|
||
|
||
const res = await api.loginWithMultiEndpoint({ phone: name, password: password.toString() })
|
||
|
||
console.log('登录响应:', res)
|
||
$message.success('登录成功')
|
||
window.localStorage.setItem('menu', JSON.stringify(res.data.auth))
|
||
setToken(res.data.token)
|
||
if (isRemember.value) {
|
||
lStorage.set('loginInfo', { name, password })
|
||
} else {
|
||
lStorage.remove('loginInfo')
|
||
}
|
||
|
||
// 先添加动态路由
|
||
await addDynamicRoutes()
|
||
|
||
// 获取第一个可用的路由页面
|
||
const firstRoute = getFirstAvailableRoute(res.data.auth)
|
||
|
||
if (query.redirect) {
|
||
const path = query.redirect
|
||
Reflect.deleteProperty(query, 'redirect')
|
||
router.push({ path, query })
|
||
} else {
|
||
// 跳转到第一个可用路由,如果没有则跳转到工作台
|
||
router.push(firstRoute || '/workbench')
|
||
}
|
||
} catch (error) {
|
||
console.error('登录请求失败:', error)
|
||
$message.removeMessage()
|
||
}
|
||
loading.value = false
|
||
}
|
||
</script>
|