320 lines
13 KiB
Vue
320 lines
13 KiB
Vue
<template>
|
||
<div class="welcome-container">
|
||
<el-container>
|
||
<Header />
|
||
|
||
<!-- 主要内容区域 -->
|
||
<el-main>
|
||
<div class="d-flex align-items-center justify-content-center p-4" style="padding: 0; width: 600px;">
|
||
<!-- 数据库初始化提示卡片 -->
|
||
<div class="login-card bg-white rounded-4 shadow-lg p-5 w-100 max-w-md" id="init-section" v-show="!isDatabaseInitialized">
|
||
<div class="text-center">
|
||
<div class="mb-6">
|
||
<FontAwesomeIcon icon="fa-solid fa-database" class="text-primary" style="font-size: 64px;" />
|
||
</div>
|
||
<h2 class="display-6 mb-4">系统未初始化</h2>
|
||
<p class="fs-5 mb-6 text-muted">请点击下方按钮进行系统初始化,初始化完成后将自动显示登录界面</p>
|
||
<button id="initialize-db" @click="initializeDatabase" class="btn btn-primary px-8 py-3 fs-5" :disabled="isInitializing">
|
||
<FontAwesomeIcon v-if="isInitializing" icon="fa-solid fa-spinner fa-spin" class="me-2" />
|
||
<FontAwesomeIcon v-else icon="fa-solid fa-sync-alt" class="me-2" />
|
||
{{ isInitializing ? '初始化中...' : '数据初始化' }}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Bootstrap登录卡片 -->
|
||
<div class="login-card bg-white rounded-4 shadow-lg p-5 w-100 max-w-md" id="login-section" style="height: 500px;" v-show="isDatabaseInitialized">
|
||
<!-- 原有登录卡片内容保持不变 -->
|
||
<!-- 登录类型切换标签页 -->
|
||
<ul class="nav nav-tabs fs-4 nav-justified" id="loginTab" role="tablist">
|
||
<li class="nav-item" role="presentation">
|
||
<button class="nav-link rounded-0 active" id="exam-tab" data-bs-toggle="tab" data-bs-target="#exam-login" type="button" role="tab" aria-controls="exam-login" aria-selected="true">
|
||
<FontAwesomeIcon icon="fa-solid fa-user-graduate" class="me-2" />
|
||
考生登录
|
||
</button>
|
||
</li>
|
||
<li class="nav-item" role="presentation">
|
||
<button class="nav-link rounded-0" id="admin-tab" data-bs-toggle="tab" data-bs-target="#admin-login" type="button" role="tab" aria-controls="admin-login" aria-selected="false">
|
||
<FontAwesomeIcon icon="fa-solid fa-user-cog" class="me-2" />
|
||
系统管理
|
||
</button>
|
||
</li>
|
||
</ul>
|
||
|
||
<!-- 登录表单内容 -->
|
||
<div class="tab-content fs-5 p-4 border-1 border-start border-end border-bottom" id="loginTabContent" style="height: calc(100% - 60px);">
|
||
<!-- 原有表单内容保持不变 -->
|
||
<!-- 考生登录表单 -->
|
||
<div class="h-100 tab-pane fade show active" id="exam-login" role="tabpanel" aria-labelledby="exam-tab">
|
||
<form @submit.prevent="handleExamineeLogin" class="d-flex flex-column h-100">
|
||
<div class="mb-3 flex-grow-1 d-flex flex-column justify-content-center">
|
||
<label for="examineeIdCard" class="form-label">身份证号</label>
|
||
<div class="input-group input-group-lg">
|
||
<span class="input-group-text">
|
||
<FontAwesomeIcon icon="fa-solid fa-id-card-alt" />
|
||
</span>
|
||
<input type="text" class="form-control" id="examineeIdCard" v-model="examineeIdCard" required>
|
||
</div>
|
||
</div>
|
||
<div class="mb-3 flex-grow-1 d-flex flex-column justify-content-center">
|
||
<label for="examineeAdmissionTicket" class="form-label">准考证号</label>
|
||
<div class="input-group input-group-lg">
|
||
<span class="input-group-text">
|
||
<FontAwesomeIcon icon="fa-solid fa-ticket-alt" />
|
||
</span>
|
||
<input type="text" class="form-control" id="examineeAdmissionTicket" v-model="examineeAdmissionTicket" required>
|
||
</div>
|
||
</div>
|
||
<div class="mt-4 flex-grow-1 d-flex flex-column justify-content-end">
|
||
<button type="submit" class="btn btn-primary w-100 py-2 fs-5">
|
||
<FontAwesomeIcon icon="fa-solid fa-sign-in-alt" class="me-2" />
|
||
登录
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- 管理员登录表单 -->
|
||
<div class="h-100 tab-pane fade" id="admin-login" role="tabpanel" aria-labelledby="admin-tab">
|
||
<form @submit.prevent="handleAdminLogin" class="d-flex flex-column h-100">
|
||
<div class="mb-3 flex-grow-1 d-flex flex-column justify-content-center">
|
||
<label for="password" class="form-label">管理员密码</label>
|
||
<div class="input-group input-group-lg">
|
||
<span class="input-group-text">
|
||
<FontAwesomeIcon icon="fa-solid fa-lock" />
|
||
</span>
|
||
<input type="password" class="form-control" id="password" v-model="adminPassword" required>
|
||
</div>
|
||
<div id="admin-error-message" class="text-danger mt-2" style="display: none;"></div>
|
||
</div><!-- 结束:.mb-3.flex-grow-1.d-flex.flex-column.justify-content-center -->
|
||
<div class="mt-4 flex-grow-1 d-flex flex-column justify-content-end">
|
||
<button type="submit" class="btn btn-primary w-100 py-2 fs-5" :disabled="isLoading">
|
||
<FontAwesomeIcon v-if="isLoading" icon="fa-solid fa-spinner fa-spin" class="me-2" />
|
||
<FontAwesomeIcon v-else icon="fa-solid fa-sign-in-alt" class="me-2" />
|
||
{{ isLoading ? '登录中...' : '登录' }}
|
||
</button>
|
||
</div><!-- 结束:.mt-4.flex-grow-1.d-flex.flex-column.justify-content-end -->
|
||
</form>
|
||
</div><!-- 结束:#admin-login -->
|
||
</div><!-- 结束:#loginTabContent -->
|
||
</div><!-- 结束:.login-card -->
|
||
</div><!-- 结束:.d-flex.align-items-center.justify-content-center -->
|
||
</el-main>
|
||
|
||
<Footer />
|
||
</el-container>
|
||
</div><!-- 结束:.welcome-container -->
|
||
</template>
|
||
|
||
<script setup>
|
||
// 导入组件
|
||
import Header from '@/components/common/Header.vue'
|
||
import Footer from '@/components/common/Footer.vue'
|
||
import { useRouter } from 'vue-router'
|
||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||
import { ref, onMounted } from 'vue'
|
||
import { ElMessage } from 'element-plus'
|
||
|
||
// 响应式数据
|
||
const router = useRouter()
|
||
const examineeIdCard = ref('') // 身份证号
|
||
const examineeAdmissionTicket = ref('') // 准考证号
|
||
const adminPassword = ref('')
|
||
const isDatabaseInitialized = ref(false)
|
||
const isInitializing = ref(false)
|
||
const isLoading = ref(false) // 添加加载状态
|
||
|
||
// 在组件挂载时检查数据库初始化状态
|
||
onMounted(async () => {
|
||
try {
|
||
console.log('组件挂载 - 开始检查数据库初始化状态');
|
||
const initialized = await window.electronAPI.checkDatabaseInitialized();
|
||
console.log('组件挂载 - 数据库初始化状态检查完成:', initialized);
|
||
isDatabaseInitialized.value = initialized;
|
||
} catch (error) {
|
||
console.error('检查数据库初始化状态失败:', error);
|
||
ElMessage.error('检查数据库初始化状态失败,请重试');
|
||
}
|
||
});
|
||
|
||
// 初始化数据库方法
|
||
const initializeDatabase = async () => {
|
||
try {
|
||
console.log('初始化数据库 - 开始');
|
||
isInitializing.value = true;
|
||
ElMessage.info('开始初始化数据库...');
|
||
|
||
const result = await window.electronAPI.initializeDatabase();
|
||
console.log('初始化数据库 - 结果:', result);
|
||
|
||
// 修复:同时处理布尔值true和带success属性的对象
|
||
if (result === true || (result && result.success)) {
|
||
ElMessage.success('数据库初始化成功!');
|
||
console.log('初始化数据库 - 成功,更新初始化状态');
|
||
isDatabaseInitialized.value = true;
|
||
} else {
|
||
const errorMessage = result && result.error ? result.error : '未知错误';
|
||
ElMessage.error(`数据库初始化失败: ${errorMessage}`);
|
||
console.error('初始化数据库 - 失败:', errorMessage);
|
||
}
|
||
} catch (error) {
|
||
console.error('数据库初始化失败:', error);
|
||
ElMessage.error(`数据库初始化失败: ${error.message || '未知错误'}`);
|
||
} finally {
|
||
console.log('初始化数据库 - 结束');
|
||
isInitializing.value = false;
|
||
}
|
||
};
|
||
|
||
// 导入用户状态管理
|
||
import { useUserStore } from '@/store/userStore'
|
||
|
||
// 获取用户状态管理
|
||
const userStore = useUserStore()
|
||
|
||
// 考生登录方法
|
||
const handleExamineeLogin = async () => {
|
||
console.log('考生登录 - 开始', {
|
||
examineeIdCard: examineeIdCard.value,
|
||
examineeAdmissionTicket: examineeAdmissionTicket.value
|
||
});
|
||
|
||
// 清除首尾空格
|
||
const idCard = examineeIdCard.value.trim();
|
||
const admissionTicket = examineeAdmissionTicket.value.trim();
|
||
|
||
// 前端验证
|
||
if (!idCard || !admissionTicket) {
|
||
console.warn('考生登录 - 验证失败: 身份证号和准考证号不能为空');
|
||
ElMessage.error('请输入身份证号和准考证号');
|
||
return;
|
||
}
|
||
|
||
// 设置加载状态
|
||
isLoading.value = true;
|
||
|
||
try {
|
||
// 调用登录API
|
||
const result = await window.electronAPI.userLogin(idCard, admissionTicket);
|
||
console.log(result);
|
||
|
||
if (result && result.id) {
|
||
console.log('考生登录 - 成功', result);
|
||
// 保存用户信息到store - 修改这里
|
||
userStore.setExaminee({
|
||
...result
|
||
});
|
||
ElMessage.success('登录成功');
|
||
// 跳转到考生首页
|
||
router.push('/examinee/home');
|
||
} else {
|
||
console.warn('考生登录 - 失败:', result);
|
||
ElMessage.error(result.error || '登录失败,请检查身份证号和准考证号');
|
||
}
|
||
} catch (error) {
|
||
console.error('考生登录 - 异常:', error);
|
||
ElMessage.error('登录失败,请重试');
|
||
} finally {
|
||
// 无论成功失败,都关闭加载状态
|
||
isLoading.value = false;
|
||
}
|
||
};
|
||
|
||
// 管理员登录方法
|
||
const handleAdminLogin = async () => {
|
||
console.log('管理员登录 - 开始', { passwordLength: adminPassword.value.length });
|
||
|
||
// 前端密码验证
|
||
const passwordError = validateAdminPassword(adminPassword.value);
|
||
if (passwordError) {
|
||
console.warn('管理员登录 - 验证失败:', passwordError);
|
||
const errorElement = document.getElementById('admin-error-message');
|
||
if (errorElement) {
|
||
errorElement.textContent = passwordError;
|
||
errorElement.style.display = 'block';
|
||
}
|
||
return;
|
||
}
|
||
|
||
// 清除之前的错误信息
|
||
const errorElement = document.getElementById('admin-error-message');
|
||
if (errorElement) {
|
||
errorElement.style.display = 'none';
|
||
}
|
||
|
||
try {
|
||
console.log('管理员登录 - 调用主进程登录方法');
|
||
// 使用新的adminLogin方法
|
||
const result = await window.electronAPI.adminLogin({
|
||
username: 'admin',
|
||
password: adminPassword.value
|
||
});
|
||
console.log('管理员登录 - 登录结果:', result);
|
||
|
||
if (result && result.success) {
|
||
console.log('管理员登录 - 成功,跳转到管理首页');
|
||
ElMessage.success('登录成功');
|
||
router.push('/admin/home');
|
||
} else {
|
||
const errorMessage = result && result.message ? result.message : '登录失败';
|
||
console.warn('管理员登录 - 失败:', errorMessage);
|
||
ElMessage.error(errorMessage);
|
||
}
|
||
} catch (error) {
|
||
console.error('管理员登录 - 异常:', error);
|
||
ElMessage.error(`登录异常: ${error.message || '未知错误'}`);
|
||
}
|
||
};
|
||
|
||
// 管理员密码验证函数
|
||
const validateAdminPassword = (password) => {
|
||
// 检查密码是否为空
|
||
if (!password) {
|
||
return '请输入管理员密码';
|
||
}
|
||
// 检查密码长度
|
||
if (password.length < 4 || password.length > 32) {
|
||
return '密码长度必须在4-32个字符之间';
|
||
}
|
||
// 检查密码是否只包含英文大小写和数字
|
||
const regex = /^[A-Za-z0-9]+$/;
|
||
if (!regex.test(password)) {
|
||
return '密码只能包含英文大小写字母和数字';
|
||
}
|
||
return null;
|
||
};
|
||
</script>
|
||
|
||
<style scoped>/* 自定义样式 */
|
||
.bg-primary {
|
||
background-color: #1E88E5 !important;
|
||
/* 蓝色主题 */
|
||
}
|
||
|
||
.text-primary {
|
||
color: #1E88E5 !important;
|
||
}
|
||
|
||
/* 确保容器占满高度 */
|
||
.welcome-container,
|
||
.el-container {
|
||
height: 100vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* 让主内容区自动扩展并居中 */
|
||
.el-main {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* 适配移动设备 */
|
||
@media (max-width: 640px) {
|
||
.max-w-md {
|
||
max-width: 100%;
|
||
}
|
||
}
|
||
</style> |