601 lines
13 KiB
Vue
601 lines
13 KiB
Vue
<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>
|