130 lines
4.2 KiB
Vue
130 lines
4.2 KiB
Vue
<script lang="ts" setup>
|
|
/**
|
|
* 询价后台登录页:视觉 1:1 对齐 admin/LoginView(居中白卡片 + 品牌区,无验证码)。
|
|
* 鉴权走 Jeecg loginApi;主账 inquiry 配置关闭图形验证码(jeecg.loginCaptchaEnabled=false)。
|
|
*
|
|
* 禁止写死 admin/123456:退出后再进登录页会误显示测试账号。
|
|
* 仅记住上次成功登录的账号(不存密码),方便换人登录时改账号。
|
|
*/
|
|
import { reactive, ref, toRaw } from 'vue';
|
|
import { ConfigProvider, message } from 'ant-design-vue';
|
|
import { useUserStore } from '/@/store/modules/user';
|
|
import ProtoIcon from '/@/views/inquiry/components/ProtoIcon.vue';
|
|
import '/@/views/inquiry/styles/admin-prototype.css';
|
|
import '/@/views/inquiry/styles/admin-fidelity.css';
|
|
|
|
const LAST_USERNAME_KEY = 'inquiry_admin_last_username';
|
|
|
|
function readLastUsername(): string {
|
|
try {
|
|
return String(localStorage.getItem(LAST_USERNAME_KEY) || '').trim();
|
|
} catch {
|
|
return '';
|
|
}
|
|
}
|
|
|
|
function rememberUsername(username: string) {
|
|
try {
|
|
localStorage.setItem(LAST_USERNAME_KEY, username);
|
|
} catch {
|
|
/* 隐私模式等写失败时忽略 */
|
|
}
|
|
}
|
|
|
|
const userStore = useUserStore();
|
|
const loading = ref(false);
|
|
const form = reactive({
|
|
username: readLastUsername(),
|
|
password: '',
|
|
});
|
|
|
|
const themeToken = {
|
|
colorPrimary: '#155eef',
|
|
borderRadius: 8,
|
|
fontFamily: 'Inter, PingFang SC, Microsoft YaHei, Noto Sans SC, system-ui, sans-serif',
|
|
fontSize: 11,
|
|
controlHeight: 34,
|
|
controlHeightLG: 40,
|
|
colorText: '#172033',
|
|
colorTextSecondary: '#667085',
|
|
colorBorder: '#d9e2ef',
|
|
};
|
|
|
|
async function onSubmit() {
|
|
if (!form.username.trim() || !form.password.trim()) {
|
|
message.warning('请输入账号和密码');
|
|
return;
|
|
}
|
|
loading.value = true;
|
|
try {
|
|
const username = form.username.trim();
|
|
const { userInfo } = await userStore.login(
|
|
toRaw({
|
|
username,
|
|
password: form.password,
|
|
// 主账已关验证码;仍传空字段以兼容 LoginParams 类型
|
|
captcha: '',
|
|
checkKey: '',
|
|
mode: 'none',
|
|
goHome: true,
|
|
})
|
|
);
|
|
if (userInfo) {
|
|
rememberUsername(username);
|
|
// 成功后清空密码,避免浏览器后退/再进登录页时残留明文
|
|
form.password = '';
|
|
message.success(`登录成功,欢迎 ${userInfo.realname || userInfo.username}`);
|
|
}
|
|
} catch (e: any) {
|
|
message.error(e?.message || '登录失败');
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<ConfigProvider :theme="{ token: themeToken }">
|
|
<div class="login-page inquiry-login-page">
|
|
<div class="login-card">
|
|
<div class="login-brand">
|
|
<div class="login-brand-mark">
|
|
<ProtoIcon name="bot" :size="22" />
|
|
</div>
|
|
<h1>友通达智能体运营后台</h1>
|
|
<p>管理询价工单、人员配置与系统权限</p>
|
|
</div>
|
|
|
|
<a-form :model="form" layout="vertical" @finish="onSubmit">
|
|
<a-form-item label="账号" name="username" :rules="[{ required: true, message: '请输入账号' }]">
|
|
<a-input v-model:value="form.username" size="large" placeholder="请输入账号" allow-clear autocomplete="username" />
|
|
</a-form-item>
|
|
<a-form-item label="密码" name="password" :rules="[{ required: true, message: '请输入密码' }]">
|
|
<a-input-password v-model:value="form.password" size="large" placeholder="请输入密码" autocomplete="current-password" />
|
|
</a-form-item>
|
|
<a-button type="primary" html-type="submit" size="large" block :loading="loading"> 登录 </a-button>
|
|
</a-form>
|
|
</div>
|
|
</div>
|
|
</ConfigProvider>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.inquiry-login-page :deep(.ant-form-item-label > label) {
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
color: #344054;
|
|
}
|
|
|
|
.login-brand-mark {
|
|
width: 56px;
|
|
height: 56px;
|
|
border-radius: 14px;
|
|
display: grid;
|
|
place-items: center;
|
|
color: #fff;
|
|
background: linear-gradient(145deg, #1d4ed8, #0f172a);
|
|
box-shadow: 0 10px 24px rgba(21, 94, 239, 0.28);
|
|
}
|
|
</style>
|