electron-vue-exam-single/src/views/WelcomeView.vue

320 lines
13 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>
<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>