# Vue-实验室预约系统
**Repository Path**: cricosly/vue-laboratory-reservation-system
## Basic Information
- **Project Name**: Vue-实验室预约系统
- **Description**: 一个允许教师灵活预约课程实验时间的实验室预约系统
- **Primary Language**: Unknown
- **License**: AGPL-3.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 1
- **Created**: 2024-05-21
- **Last Updated**: 2025-07-29
## Categories & Tags
**Categories**: Uncategorized
**Tags**: Vue, Ant-Design, Element-UI, TypeScript
## README
" Vue-Laboratory "
基于 Vue3 + TypeScript 的实验室预约系统【纯Vue前端版】


## 快速开始
1. 克隆本仓库到本地
2. 安装Node.js 20
3. 安装依赖
```
npm install
```
4. 本地启动
```
npm run dev
```
5. 打包生产环境
```
npm run build
```
6. 体验用户
```
账号: admin
密码: admin
```
## 技术框架
**开发环境**
>Visual Studio Code ^1.89.1
Node.js ^20.11.1
......
**Vite/Vue3前端框架**
>Vite ^5.1.5
Vue ^3.4.21
Vue-router ^4.3.0
VueUse ^10.9.0 (替代Pinia/Axios)
......
**Ant-Design-Vue: ^4.2.1 UI框架**
>layout 布局,协助进行页面级整体布局。
ant-design/icons-vue 图标
Notification 通知提醒框
......
**Element-Plus: ^2.7.3 UI框架**
>Icon 图标
Form 表单
Slider 滑动输入条
Message 全局提示
Popconfirm 气泡确认框
Tabs 卡片风格标签页
Input Number 数字输入框
......
## 约定
**课程**
课程有课时规定,`1节课=1课时`
**实验室**
系统默认包含4个实验室可以预约
包括`905实验室、906实验室、907实验室、908实验室`
**预约**
共`18`周课程,每周`7`天皆可预约
每天的节次规定`按段预约`,即`1~2`节、`3~4`节、`5~6`节、`7~8`节为一段
**登录**
系统需`登录使用`,并根据登录信息验证教师身份
预约基于登录的身份进行,系统有6位老师,用户名密码一致
> admin
1001
1002
1003
1004
1005
## 需求与设计
**课程管理**
1、教师可以查看自己的课程
2、教师可以创建包含课程名称,学时的实验课若干
3、后续基于录入的课程进行预约
3、教师可以修改已有课程,修改后同步修改预约情况信息里的课程名字
```js
// 更新ytimes预约表中对应课程的名字
if (editingCourse && editingCourse.name !== editForm.value.name) {
ytimesR.value = ytimesR.value.map((ytime) => {
if (ytime.cid === editingCourse?.cid) {
return { ...ytime, cname: editForm.value.name }
}
return ytime
})
}
```
4、教师可以删除已有课程,已有预约信息的课程无法删除
```js
// 删除课程
const deleteCourse = (course: Course) => {
// 在预约表中检查课程是否存在
const isInYtimes = ytimesR.value.some((ytime) => ytime.cid === course.cid)
if (isInYtimes) {
// 如果在预约表中存在,则拒绝删除并给出提示
error('错误! 该课程存在预约信息,不能删除')
return // 直接返回,不执行后续删除操作
}
const index = tableData.value.findIndex((c) => c.cid === course.cid)
if (index !== -1) {
tableData.value.splice(index, 1)
}
}
```
**课表信息**
1、可以查看所有的周次每天的所有课程安排情况
2、课程信息表示为:
> 课程名称
> 老师名称
> 实验室 / 周次
3、通过颜色区分实验室
```js
// 实验室颜色映射
const roomColorMap: { [key: string]: string } = {
'905': '#eea6b7', // 实验室905对应红色
'906': 'rgb(137, 222, 255)', // 实验室906对应蓝色
'907': '#5dbe8a', // 实验室907对应绿色
'908': '#f6ad8f' // 实验室908对应橙色
// 其他实验室...
}
```
4、突出显示当前登录老师自己的课程,红色虚线框为当前登录老师的课程
```js
const borderColor = (name: string) => {
return userS.value.name === name ? '2px dashed #ee2746' : ''
}
```
**实验室预约**
1、分每个实验室以大表格形式渲染显示18周内每天每段的占用情况
2、红色为当前登录老师的课程占用情况,蓝色为其他老师的课程占用情况
3、实验时间固定,预约需要选择课程、实验室、周次、星期、节次
4、预约学时不能大于剩余学时,预约成功后更新剩余学时
```js
// 学时冲突检查
if (appointmentHours > remainHours!) {
error('错误! 预约学时不可超过剩余学时')
return // 退出函数,不保存更改
}
// 更新课程剩余学时
const index = coursesR.value.findIndex((c) => c.cid === newCourse!.cid)
// 如果找到了索引,更新课程的剩余学时
if (index !== -1) {
const updatedCourse = { ...newCourse, remainhours: newRemainHours }
coursesR.value.splice(index, 1, updatedCourse)
}
```
5、预约实验室时间冲突:同一个实验室,同一时间不能有多门课程
6、预约个人时间冲突:同一个老师,同一时间不能在不同的实验室上课
```js
// 时间冲突检查
function checkConflict(addForm: Ytime, ytimes: Ytime[]): string {
for (const ytime of ytimes) {
// 实验室时间冲突
if (addForm.room === ytime.room) {
if (
// 星期相同
addForm.day === ytime.day &&
// 节次相同
addForm.time![0] === ytime.time![0] &&
addForm.time![1] === ytime.time![1]
) {
// 周次有交集
if (!(addForm.end! < ytime.start! || addForm.start! > ytime.end!)) {
// 存在冲突
return '实验室时间冲突'
}
}
}
// 个人时间冲突
if (addForm.uid === ytime.uid) {
if (
// 星期相同
addForm.day === ytime.day &&
// 节次相同
addForm.time![0] === ytime.time![0] &&
addForm.time![1] === ytime.time![1]
) {
// 周次有交集
if (!(addForm.end! < ytime.start! || addForm.start! > ytime.end!)) {
// 存在冲突
return '个人时间冲突'
}
}
}
}
// 无冲突
return '可预约'
}
```
## 打包部署
所有文件的引用必修使用相对路径
`vite.config.ts`添加配置,按相对路径编译。
```js
export default defineConfig({
plugins: [vue()],
base: './', // 相对路径打包
// ...
})
```
运行`npm run build`命令,在项目下生成编译结果`dist`目录。
```shell
npm run build
```
打包报错,大小超限制
`vite.config.ts`添加配置
加大限制的大小将500kb改成2500kb或者更大
分解块,将大块分解成更小的块
```ts
build: {
chunkSizeWarningLimit: 2500,
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString()
}
}
}
}
},
```
资源管理器进入`dist`目录,将目录下全部文件(`index.html`+`assets`)压缩为`zip`文件。
将`zip`文件扩展名修改为`war`,即`dist.war`。`zip/war`使用相同的压缩算法。
注意:压缩包内`不要嵌套文件夹`,内部直接就是`dist`目录中的文件
登录平台,上传war包自动部署。
基于腾讯云轻量级应用服务器进行部署
使用Xftp、Xshell进行部署管理
Nginx配置文件 nginx.conf
```config
server {
location / {
root /var/Vue-Laboratory;
index index.html index.htm;
try_files $uri $uri/ /index.html; # 解决404
}
```