commit
dc25f05ad6
@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar"]
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
# Vue 3 + Vite
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
|
||||
Learn more about IDE Support for Vue in the [Vue Docs Scaling up Guide](https://vuejs.org/guide/scaling-up/tooling.html#ide-support).
|
||||
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>random-roll-call-vue</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "random-roll-call-vue",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.13.2",
|
||||
"echarts": "^6.0.0",
|
||||
"element-plus": "^2.11.8",
|
||||
"vue": "^3.5.24",
|
||||
"vue-echarts": "^8.0.1",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"unplugin-auto-import": "^20.2.0",
|
||||
"unplugin-vue-components": "^30.0.0",
|
||||
"vite": "^7.2.4"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 496 B |
@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-empty v-if="!students || students.length === 0" description="暂无学生数据" />
|
||||
<v-chart v-else class="chart" :option="chartOption" autoresize />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { use } from 'echarts/core';
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
import { BarChart } from 'echarts/charts';
|
||||
import {
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
} from 'echarts/components';
|
||||
import VChart from "vue-echarts";
|
||||
import { computed } from 'vue';
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
BarChart,
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
]);
|
||||
|
||||
const props = defineProps({
|
||||
students: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const chartOption = computed(() => {
|
||||
const sortedStudents = [...props.students].sort((a, b) => b.points - a.points);
|
||||
const topStudents = sortedStudents.slice(0, 10);
|
||||
|
||||
return {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'shadow' }
|
||||
},
|
||||
grid: {
|
||||
left: '3%', right: '4%', bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
boundaryGap: [0, 0.01],
|
||||
// 【新增点】调整坐标轴样式以适应深色背景
|
||||
axisLabel: { color: '#fff' },
|
||||
splitLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.2)' } }
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
data: topStudents.map(s => s.name).reverse(),
|
||||
axisLabel: { color: '#fff' } // 调整坐标轴样式
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '积分',
|
||||
type: 'bar',
|
||||
data: topStudents.map(s => s.points).reverse(),
|
||||
// 【修改点】为柱状图添加漂亮的渐变色
|
||||
itemStyle: {
|
||||
borderRadius: [0, 5, 5, 0],
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0, y: 0, x2: 1, y2: 0,
|
||||
colorStops: [
|
||||
{ offset: 0, color: '#23d5ab' },
|
||||
{ offset: 1, color: '#23a6d5' }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chart {
|
||||
height: 450px;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,14 @@
|
||||
import { createApp } from 'vue'
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
import App from './App.vue'
|
||||
|
||||
import './styles/global.css'
|
||||
|
||||
import VChart from "vue-echarts";
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.component("v-chart", VChart);
|
||||
app.use(ElementPlus)
|
||||
app.mount('#app')
|
||||
@ -0,0 +1,60 @@
|
||||
import axios from 'axios';
|
||||
|
||||
// --- MOCK DATA ---
|
||||
// This data simulates what our backend database would store.
|
||||
let mockStudents = [
|
||||
{ id: '2024001', name: '张三', major: '软件工程', points: 5, callCount: 2 },
|
||||
{ id: '2024002', name: '李四', major: '软件工程', points: 8, callCount: 3 },
|
||||
{ id: '2024003', name: '王五', major: '计算机科学', points: 2, callCount: 1 },
|
||||
{ id: '2024004', name: '赵六', major: '网络工程', points: 10, callCount: 4 },
|
||||
];
|
||||
|
||||
/**
|
||||
* Simulates network delay.
|
||||
* @param {number} ms - Milliseconds to wait.
|
||||
*/
|
||||
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
// --- MOCK API FUNCTIONS ---
|
||||
// These functions mimic the behavior of real API calls.
|
||||
|
||||
export const studentApi = {
|
||||
/**
|
||||
* Fetches the list of all students.
|
||||
* In the future, this will be: return axios.get('/api/students');
|
||||
*/
|
||||
getStudents: async () => {
|
||||
console.log("API: Fetching all students...");
|
||||
await sleep(500); // Simulate network latency
|
||||
return { data: [...mockStudents] }; // Return a copy
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates a specific student's data.
|
||||
* @param {object} studentData - The student object with updated info.
|
||||
* In the future, this will be: return axios.put(`/api/students/${studentData.id}`, studentData);
|
||||
*/
|
||||
updateStudent: async (studentData) => {
|
||||
console.log(`API: Updating student ${studentData.id}...`, studentData);
|
||||
await sleep(300);
|
||||
const index = mockStudents.findIndex(s => s.id === studentData.id);
|
||||
if (index !== -1) {
|
||||
mockStudents[index] = studentData;
|
||||
return { data: { ...studentData } }; // Return a copy
|
||||
} else {
|
||||
throw new Error("Student not found!");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Imports a new list of students, replacing the old one.
|
||||
* @param {Array} newStudents - Array of new student objects.
|
||||
* In the future, this will be: return axios.post('/api/students/import', newStudents);
|
||||
*/
|
||||
importStudents: async (newStudents) => {
|
||||
console.log("API: Importing new students...");
|
||||
await sleep(400);
|
||||
mockStudents = newStudents;
|
||||
return { data: [...mockStudents] };
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,87 @@
|
||||
/* --- 全局美化样式 --- */
|
||||
|
||||
/* 1. 引入更适合屏幕阅读的字体 (可选,但推荐) */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&display=swap');
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Noto Sans SC', sans-serif;
|
||||
|
||||
/*
|
||||
【【【 修改点 】】】
|
||||
移除了之前的动态渐变和动画代码。
|
||||
替换为一个固定、优雅的深灰色系渐变背景。
|
||||
*/
|
||||
background: linear-gradient(135deg, #29323c 0%, #485563 100%);
|
||||
background-attachment: fixed; /* 确保背景在滚动时不会移动 */
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 【【【 修改点 】】】: 删除了 @keyframes gradientBG {...} 动画规则 */
|
||||
|
||||
/* 3. 美化 Element Plus 的卡片组件 (样式保持不变,它们与新背景完美兼容) */
|
||||
.box-card {
|
||||
border: 1px solid rgba(255, 255, 255, 0.18) !important;
|
||||
background: rgba(255, 255, 255, 0.1) !important;
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border-radius: 12px !important;
|
||||
color: #fff !important;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.box-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
|
||||
}
|
||||
|
||||
/* 4. 修改卡片头部样式 */
|
||||
.el-card__header {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.18) !important;
|
||||
color: #fff !important;
|
||||
font-size: 1.1em;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 5. 美化表格,使其适应深色背景 */
|
||||
.el-table, .el-table__expanded-cell {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.el-table th, .el-table tr {
|
||||
background-color: transparent !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.el-table td, .el-table th.is-leaf {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.18) !important;
|
||||
}
|
||||
|
||||
.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell,
|
||||
.el-table--enable-row-hover .el-table__body tr:hover>td {
|
||||
background-color: rgba(255, 255, 255, 0.1) !important;
|
||||
}
|
||||
|
||||
/* 6. 调整其他组件以适应新主题 */
|
||||
.el-dialog {
|
||||
background: rgba(40, 40, 40, 0.85);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border-radius: 12px;
|
||||
}
|
||||
.el-dialog .el-dialog__title, .el-dialog .el-dialog__body {
|
||||
color: #fff !important;
|
||||
}
|
||||
.el-empty__description {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* 待点名区域的文字颜色 */
|
||||
.el-card span[style*="color: #c0c4cc"] {
|
||||
color: rgba(255, 255, 255, 0.7) !important;
|
||||
}
|
||||
|
||||
/* 被点名学生的学号颜色 */
|
||||
.el-card p[style*="color: #909399"] {
|
||||
color: rgba(255, 255, 255, 0.8) !important;
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
// vite.config.js
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
Components({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
],
|
||||
})
|
||||
Loading…
Reference in new issue