exam11/src/views/WelcomeView.vue

428 lines
16 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 main-background">
<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 shadow-lg p-5 w-100 max-w-md" id="init-section"
v-show="!isDatabaseInitialized">
<div class="text-center">
<div class="mb-6">
<i class="fa fa-database text-primary" style="font-size: 64px;"></i>
</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">
<i v-if="isInitializing" class="fa fa-spinner fa-spin me-2"></i>
<i v-else class="fa fa-refresh me-2"></i>
{{ isInitializing ? '初始化中...' : '数据初始化' }}
</button>
</div>
</div>
<!-- Bootstrap登录卡片 -->
<div class="login-card bg-white rounded 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" id="loginTab" role="tablist">
<li class="nav-item flex-fill" role="presentation">
<button class="nav-link rounded-0 active w-100" id="exam-tab" data-toggle="tab"
data-target="#exam-login" type="button" role="tab" aria-controls="exam-login" aria-selected="true">
<i class="fa fa-graduation-cap me-2"></i>
考生登录
</button>
</li>
<li class="nav-item flex-fill" role="presentation">
<button class="nav-link rounded-0 w-100" id="admin-tab" data-toggle="tab" data-target="#admin-login"
type="button" role="tab" aria-controls="admin-login" aria-selected="false">
<i class="fa fa-cog me-2"></i>
系统管理
</button>
</li>
</ul>
<!-- 登录表单内容 -->
<div class="tab-content fs-5 p-4 border border-left border-right 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">
<font-awesome-icon :icon="['fas', 'id-card']" />
</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">
<font-awesome-icon :icon="['fas', 'key']" />
</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">
<i class="fa fa-sign-in me-2"></i>
登录
</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">
<font-awesome-icon :icon="['fas', '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>
<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">
<i v-if="isLoading" class="fa fa-spinner fa-spin me-2"></i>
<i v-else class="fa fa-sign-in me-2"></i>
{{ isLoading ? '登录中...' : '登录' }}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</el-main>
<Footer />
</el-container>
</div>
</template>
<script>
// 导入组件
import Header from '../components/common/Header.vue'
import Footer from '../components/common/Footer.vue'
import { Message } from 'element-ui'
// 导入Vuex store
import store from '../store/index.js'
export default {
name: 'WelcomeView',
components: {
Header,
Footer
},
data () {
return {
examineeIdCard: '', // 身份证号
examineeAdmissionTicket: '', // 准考证号
adminPassword: '',
isDatabaseInitialized: false,
isInitializing: false,
isLoading: false // 添加加载状态
}
},
mounted () {
console.log('mounted: 调用this.checkDatabaseStatus方法')
this.checkDatabaseStatus()
console.log('mounted: 调用this.checkDatabaseStatus方法完成')
this.checkAndInitializeUserDb()
// 添加:打印路径信息,帮助排查便携模式问题
this.logPathInformation()
},
methods: {
// 新增:打印路径信息
async logPathInformation() {
try {
if (window.electronAPI) {
console.log('===== 路径信息开始 =====');
// 获取并打印appDir
try {
// 通过获取exe路径来间接获取appDir
const exePath = await window.electronAPI.getExePath();
const appDir = exePath ? exePath.substring(0, exePath.lastIndexOf('\\')) : '无法获取';
console.log('应用程序目录(appDir):', appDir);
} catch (error) {
console.error('获取appDir失败:', error);
}
// 获取并打印数据库路径
// try {
// // 由于没有直接获取数据库路径的API我们通过检查数据库状态的日志来推断
// console.log('尝试获取数据库路径信息...');
// // 触发一次数据库检查以生成相关日志
// await window.electronAPI.checkDatabaseInitialized();
// } catch (error) {
// console.error('触发数据库检查失败:', error);
// }
// 尝试直接获取system.db和user.db路径
if (window.electronAPI.getDatabasePaths) {
try {
const paths = await window.electronAPI.getDatabasePaths();
console.log('system.db路径:', paths.systemDbPath);
console.log('user.db路径:', paths.userDbPath);
} catch (error) {
console.error('获取数据库路径失败:', error);
}
}
console.log('===== 路径信息结束 =====');
} else {
console.log('electronAPI不存在无法获取路径信息');
}
} catch (error) {
console.error('打印路径信息时出错:', error);
}
},
// 检查并静默初始化用户数据库
async checkAndInitializeUserDb() {
try {
console.log('检查user.db是否存在...')
const userDbExists = await window.electronAPI.checkUserDbExists()
console.log('user.db存在状态:', userDbExists)
if (!userDbExists) {
console.log('user.db不存在开始静默初始化...')
await window.electronAPI.initializeUserDatabaseSilently()
console.log('user.db静默初始化完成')
}
} catch (error) {
console.error('检查或初始化user.db失败:', error)
// 这里不显示错误信息,因为是静默初始化
}
},
async checkDatabaseStatus () {
try {
console.log('组件挂载 - 开始检查数据库初始化状态')
const initialized = await window.electronAPI.checkDatabaseInitialized()
console.log('组件挂载 - 数据库初始化状态检查完成:', initialized)
this.isDatabaseInitialized = initialized
} catch (error) {
console.error('检查数据库初始化状态失败:', error)
Message.error('检查数据库初始化状态失败,请重试')
}
},
async initializeDatabase () {
try {
console.log('初始化数据库 - 开始')
this.isInitializing = true
Message.info('开始初始化数据库...')
const result = await window.electronAPI.initializeDatabase()
console.log('初始化数据库 - 结果:', result)
// 修复同时处理布尔值true和带success属性的对象
if (result === true || (result && result.success)) {
Message.success('数据库初始化成功!')
console.log('初始化数据库 - 成功,更新初始化状态')
this.isDatabaseInitialized = true
} else {
const errorMessage = result && result.error ? result.error : '未知错误'
Message.error(`数据库初始化失败: ${errorMessage}`)
console.error('初始化数据库 - 失败:', errorMessage)
}
} catch (error) {
console.error('数据库初始化失败:', error)
Message.error(`数据库初始化失败: ${error.message || '未知错误'}`)
} finally {
console.log('初始化数据库 - 结束')
this.isInitializing = false
}
},
async handleExamineeLogin () {
console.log('考生登录 - 开始', {
examineeIdCard: this.examineeIdCard,
examineeAdmissionTicket: this.examineeAdmissionTicket
})
// 清除首尾空格
const idCard = this.examineeIdCard.trim()
const admissionTicket = this.examineeAdmissionTicket.trim()
// 前端验证
if (!idCard || !admissionTicket) {
console.warn('考生登录 - 验证失败: 身份证号和准考证号不能为空')
Message.error('请输入身份证号和准考证号')
return
}
// 设置加载状态
this.isLoading = true
try {
// 调用登录API - 使用正确的参数格式
const result = await window.electronAPI.userLogin({ idCard, admissionTicket })
console.log('考生登录 - 结果:', result)
if (result && result.id) {
console.log('考生登录 - 成功', result)
// 保存用户信息到store
this.$store.commit('setExaminee', result)
Message.success('登录成功')
// 跳转到考生首页
this.$router.push('/examinee/home')
} else {
console.warn('考生登录 - 失败:', result)
Message.error(result && result.error ? result.error : '登录失败,请检查身份证号和准考证号')
}
} catch (error) {
console.error('考生登录 - 异常:', error)
Message.error(`登录失败: ${error.message || '未知错误'}`)
} finally {
// 无论成功失败,都关闭加载状态
this.isLoading = false
}
},
// 修改handleAdminLogin方法
async handleAdminLogin () {
console.log('管理员登录 - 开始', { passwordLength: this.adminPassword.length })
// 前端密码验证
const passwordError = this.validateAdminPassword(this.adminPassword)
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: this.adminPassword
})
console.log('管理员登录 - 登录结果:', result)
if (result && result.success) {
console.log('管理员登录 - 成功更新store状态并跳转')
// 使用新的setAdmin mutation
this.$store.commit('setAdmin', { username: 'admin' })
Message.success('登录成功')
this.$router.push('/admin/home')
} else {
const errorMessage = result && result.message ? result.message : '登录失败'
console.warn('管理员登录 - 失败:', errorMessage)
Message.error(errorMessage)
}
} catch (error) {
console.error('管理员登录 - 异常:', error)
Message.error(`登录异常: ${error.message || '未知错误'}`)
}
},
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
},
// 修改exitExam方法
async exitExam () {
this.$confirm(
'确定要退出考试吗?',
'退出确认',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
// 完全清除store中的数据
this.$store.commit('clearUser')
// 重定向到欢迎页
this.$router.push('/')
}).catch(() => {
// 用户取消操作
console.log('用户取消退出')
})
},
}
}
</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;
}
.main-background {
background-image: url('../assets/bg.jpeg');
background-size: 100% 100%;
/* 拉伸背景图以填满容器 */
background-position: center;
/* 保持居中 */
background-repeat: no-repeat;
/* 避免重复 */
}
/* 适配移动设备 */
@media (max-width: 640px) {
.max-w-md {
max-width: 100%;
}
}
</style>