601 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="certificate-management">
<!-- 顶部操作栏 -->
<div class="toolbar">
<h2>全部证书</h2>
<div class="toolbar-actions">
<button class="btn btn-primary" @click="addCertificate">添加证书</button>
<div class="filter-dropdown">
<select v-model="selectedExam" class="filter-select">
<option value="">考试</option>
<option value="exam1">期末考试</option>
<option value="exam2">期中考试</option>
<option value="exam3">模拟考试</option>
</select>
</div>
<div class="search-box">
<input type="text" placeholder="请输入关键词" v-model="searchKeyword" />
<button class="btn btn-search" @click="searchCertificates">搜索</button>
</div>
</div>
</div>
<!-- 证书网格展示 -->
<div class="certificate-grid">
<div v-for="certificate in filteredCertificates" :key="certificate.id" class="certificate-card" @click="viewCertificateDetail(certificate)">
<div class="certificate-thumbnail">
<img :src="certificate.thumbnail" :alt="certificate.name" class="certificate-image" />
</div>
<div class="certificate-info">
<div class="certificate-name">{{ certificate.name }}</div>
<div class="certificate-category">证书分类: {{ certificate.category }}</div>
</div>
<div class="file-menu">
<button class="file-menu-btn" @click.stop="toggleFileMenu(certificate.id)">
<img src="/images/teacher/more.png" alt="更多操作" class="more-icon" />
</button>
<div v-if="activeFileMenu === certificate.id" class="file-menu-dropdown">
<div class="menu-item" @click.stop="downloadCertificate(certificate)">
<img src="/images/teacher/download.png" alt="下载" class="menu-icon" />
<span>下载</span>
</div>
<div class="menu-item" @click.stop="editCertificate(certificate)">
<img src="/images/teacher/edit.png" alt="编辑" class="menu-icon" />
<span>编辑</span>
</div>
<div class="menu-item" @click.stop="deleteCertificate(certificate)">
<img src="/images/teacher/delete.png" alt="删除" class="menu-icon" />
<span>删除</span>
</div>
</div>
</div>
</div>
</div>
<!-- 添加证书模态框 -->
<div v-if="showAddModal" class="modal-overlay" @click="closeAddModal">
<div class="modal-content" @click.stop>
<div class="modal-header">
<h3>添加证书</h3>
<button class="modal-close" @click="closeAddModal">×</button>
</div>
<div class="modal-body">
<p>添加证书功能正在开发中...</p>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useMessage } from 'naive-ui'
import { useRouter, useRoute } from 'vue-router'
const message = useMessage()
const router = useRouter()
const route = useRoute()
// 搜索和筛选
const searchKeyword = ref('')
const selectedExam = ref('')
// 模态框控制
const showAddModal = ref(false)
const activeFileMenu = ref<number | null>(null)
// 证书数据
const certificates = ref([
{
id: 1,
name: '证书名称证书名称',
category: '分类名称',
title: '荣誉证书',
issuer: '某某2021年大学生某某协会',
badge: '第一名',
thumbnail: '/images/teacher/certificate.png'
},
{
id: 2,
name: '优秀学员证书',
category: '学习成果',
title: '荣誉证书',
issuer: '某某2021年大学生某某协会',
badge: '优秀',
thumbnail: '/images/teacher/certificate.png'
},
{
id: 3,
name: '技能认证证书',
category: '技能认证',
title: '荣誉证书',
issuer: '某某2021年大学生某某协会',
badge: '通过',
thumbnail: '/images/teacher/certificate.png'
},
{
id: 4,
name: '竞赛获奖证书',
category: '竞赛奖励',
title: '荣誉证书',
issuer: '某某2021年大学生某某协会',
badge: '二等奖',
thumbnail: '/images/teacher/certificate.png'
},
{
id: 5,
name: '培训结业证书',
category: '培训认证',
title: '荣誉证书',
issuer: '某某2021年大学生某某协会',
badge: '结业',
thumbnail: '/images/teacher/certificate.png'
},
{
id: 6,
name: '项目完成证书',
category: '项目认证',
title: '荣誉证书',
issuer: '某某2021年大学生某某协会',
badge: '完成',
thumbnail: '/images/teacher/certificate.png'
}
])
// 过滤后的证书
const filteredCertificates = computed(() => {
let filtered = certificates.value
if (searchKeyword.value) {
filtered = filtered.filter((cert: any) =>
cert.name.toLowerCase().includes(searchKeyword.value.toLowerCase()) ||
cert.category.toLowerCase().includes(searchKeyword.value.toLowerCase())
)
}
if (selectedExam.value) {
// 这里可以根据考试类型进行筛选
filtered = filtered.filter((cert: any) => cert.category === selectedExam.value)
}
return filtered
})
// 方法
const addCertificate = () => {
// 从当前路径中提取课程ID
const currentPath = route.path;
const courseIdMatch = currentPath.match(/\/course-editor\/(\d+)/);
const courseId = courseIdMatch ? courseIdMatch[1] : '1';
// 跳转到添加证书页面
const targetPath = `/teacher/course-editor/${courseId}/certificate/add`;
router.push(targetPath);
}
const closeAddModal = () => {
showAddModal.value = false
}
const searchCertificates = () => {
message.info('搜索证书: ' + searchKeyword.value)
}
const toggleFileMenu = (id: number) => {
console.log('点击了更多操作按钮ID:', id)
activeFileMenu.value = activeFileMenu.value === id ? null : id
console.log('当前激活的菜单:', activeFileMenu.value)
}
const downloadCertificate = (certificate: any) => {
message.success(`下载证书: ${certificate.name}`)
activeFileMenu.value = null
}
const editCertificate = (certificate: any) => {
message.info(`编辑证书: ${certificate.name}`)
activeFileMenu.value = null
}
const deleteCertificate = (certificate: any) => {
if (confirm(`确定要删除证书 "${certificate.name}" 吗?`)) {
const index = certificates.value.findIndex((c: any) => c.id === certificate.id)
if (index > -1) {
certificates.value.splice(index, 1)
message.success('删除成功')
}
}
activeFileMenu.value = null
}
const viewCertificateDetail = (certificate: any) => {
console.log('点击了证书卡片:', certificate);
// 从当前路径中提取课程ID
const currentPath = route.path;
console.log('当前路径:', currentPath);
const courseIdMatch = currentPath.match(/\/course-editor\/(\d+)/);
const courseId = courseIdMatch ? courseIdMatch[1] : '1';
console.log('提取的课程ID:', courseId);
const targetPath = `/teacher/course-editor/${courseId}/certificate/detail/${certificate.id}`;
console.log('目标路径:', targetPath);
router.push(targetPath);
}
// 点击外部关闭更多操作菜单
const closeFileMenu = () => {
activeFileMenu.value = null
}
// 监听点击事件
document.addEventListener('click', closeFileMenu)
</script>
<style scoped>
.certificate-management {
width: 100%;
background: #fff;
height: 100%;
overflow: auto;
}
/* 顶部工具栏 */
.toolbar {
display: flex;
justify-content: space-between;
align-items: center;
margin-right: 25px;
background: #fff;
padding: 30px 0 20px 30px;
border-bottom: 2px solid #F6F6F6;
}
.toolbar h2 {
margin: 0;
font-size: 18px;
color: #333;
}
.toolbar-actions {
display: flex;
align-items: center;
gap: 10px;
}
.btn {
padding: 7px 16px;
border: none;
font-size: 14px;
cursor: pointer;
transition: all 0.3s ease;
border-radius: 2px;
}
.btn-primary {
background: #0288D1;
color: white;
}
.btn-primary:hover {
background: #40a9ff;
}
.btn-search {
background: #0288D1;
color: white;
border: none;
padding: 6px 16px;
cursor: pointer;
font-size: 14px;
}
.btn-search:hover {
background: #0277bd;
}
/* 筛选下拉框 */
.filter-dropdown {
position: relative;
}
.filter-select {
padding: 6px 12px;
border: 1px solid #F1F3F4;
border-radius: 2px;
font-size: 14px;
background: white;
cursor: pointer;
outline: none;
}
.filter-select:focus {
border-color: #0288D1;
}
/* 搜索框 */
.search-box {
display: flex;
align-items: center;
border: 1px solid #F1F3F4;
border-radius: 2px;
overflow: hidden;
}
.search-box input {
border: none;
padding: 6px 12px;
outline: none;
width: 200px;
font-size: 14px;
}
/* 证书网格 */
.certificate-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 20px;
padding: 30px;
}
/* 证书卡片 */
.certificate-card {
padding: 50px 20px 10px 20px;
position: relative;
background: white;
border: 1.5px solid #D8D8D8;
overflow: hidden;
transition: all 0.3s ease;
cursor: pointer;
min-height: 215px;
}
.certificate-card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
background-color: #F3F5F8;
}
/* 证书缩略图 */
.certificate-thumbnail {
position: relative;
height: 120px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.certificate-image {
width: 100%;
height: 100%;
object-fit: contain;
}
.certificate-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
/* 证书信息 */
.certificate-info {
padding: 5px 20px;
}
.certificate-name {
font-size: 14px;
font-weight: 500;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.certificate-category {
font-size: 11px;
color: #999;
}
/* 文件菜单 */
.file-menu {
position: absolute;
top: 10px;
right: 10px;
z-index: 10;
}
.file-menu-btn {
width: 30px;
height: 30px;
border: none;
background: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.more-icon {
width: 16px;
height: 16px;
object-fit: contain;
}
.file-menu-dropdown {
position: absolute;
top: 100%;
right: 0;
background: white;
border-radius: 4px;
z-index: 20;
min-width: 60px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.menu-item {
display: flex;
align-items: center;
gap: 4px;
padding: 6px 10px;
font-size: 10px;
color: #333;
cursor: pointer;
transition: all 0.3s ease;
white-space: nowrap;
}
.menu-icon {
width: 12px;
height: 12px;
object-fit: contain;
flex-shrink: 0;
}
.menu-item:hover {
background: #f5f5f5;
}
.menu-item:first-child {
border-radius: 4px 4px 0 0;
}
.menu-item:last-child {
border-radius: 0 0 4px 4px;
}
/* 模态框 */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background: white;
border-radius: 8px;
width: 90%;
max-width: 500px;
max-height: 80vh;
overflow: hidden;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
border-bottom: 1px solid #e6e6e6;
}
.modal-header h3 {
margin: 0;
font-size: 18px;
color: #333;
}
.modal-close {
background: none;
border: none;
font-size: 24px;
color: #999;
cursor: pointer;
padding: 0;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
}
.modal-close:hover {
color: #333;
}
.modal-body {
padding: 20px;
}
/* 响应式设计 */
@media (max-width: 1400px) {
.certificate-grid {
grid-template-columns: repeat(4, 1fr);
gap: 15px;
padding: 20px;
}
}
@media (max-width: 1200px) {
.certificate-grid {
grid-template-columns: repeat(3, 1fr);
gap: 15px;
padding: 20px;
}
}
@media (max-width: 900px) {
.certificate-grid {
grid-template-columns: repeat(2, 1fr);
gap: 15px;
padding: 20px;
}
}
@media (max-width: 768px) {
.toolbar {
flex-direction: column;
gap: 15px;
align-items: flex-start;
}
.toolbar-actions {
flex-wrap: wrap;
gap: 8px;
}
.search-box input {
width: 150px;
}
.certificate-grid {
grid-template-columns: repeat(2, 1fr);
gap: 10px;
padding: 15px;
}
.certificate-thumbnail {
height: 150px;
}
}
@media (max-width: 480px) {
.toolbar-actions {
flex-direction: column;
width: 100%;
}
.search-box {
width: 100%;
}
.search-box input {
width: 100%;
}
.certificate-grid {
grid-template-columns: 1fr;
padding: 10px;
}
}
</style>