预约实验室是教师所拥有的权限。所以我们应该用教师角色进行登录了。
1、前端
1.1、创建预约实验室页面
可以复制粘贴我们之前在AddList.vue中的代码,再进行修改
<template>
<div>
<div style="min-height: 500px; justify-content: center;position: relative" id="map" />
<!-- 对话框 -->
<el-dialog v-model="dialogVisible" title="添加实验室">
<el-form ref="addFormRef" :model="addForm" :rules="rules" label-width="100px" class="ruleForm" status-icon>
<el-form-item label="实验室名称" prop="title">
<el-input v-model="addForm.title" />
</el-form-item>
<el-form-item label="容纳人数" prop="capacity">
<el-input v-model="addForm.capacity" type="number" />
</el-form-item>
<!-- 下拉列表 -->
<el-form-item label="实验室类型" prop="lab_type">
<el-select v-model="addForm.lab_type" class="m-2" placeholder="请选择实验室类型" size="large" style="width: 100%;">
<el-option v-for="item in LabType" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="所属学院" prop="college_type">
<el-select v-model="addForm.college_type" class="m-2" placeholder="请选择学院" size="large" style="width: 100%;">
<el-option v-for="item in CollegeType" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleConfirm()">
更新
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { onMounted, ref, reactive } from "vue";
import { Scene, ImageLayer, PointLayer, Popup } from '@antv/l7';
import { Map } from '@antv/l7-maps';
import { LabType, CollegeType } from '../../util/type'
import axios from "axios";
let scene, popup;
onMounted(() => {
// 创建Scene场景
scene = new Scene({
id: 'map',
map: new Map({
// center中心坐标,很关键,将来这个中心坐标的位置就是500,500的这样一个位置。将来我们要靠它来计算我们的偏移量的。
center: [500, 500],
// zoom放大:现在是放大3倍
zoom: 3,
version: 'SIMPLE',
mapSize: 1000,
// 最大是5倍
maxZoom: 5,
// 最小是2倍
minZoom: 2,
pitchEnabled: false,
// 旋转:禁用
rotateEnabled: false
})
});
// 设置背景颜色
scene.setBgColor('rgb(94, 182, 140)');
// 创建imagelayer图片场景
const imagelayer = new ImageLayer({}).source(
'/bg.jpg',
{
parser: {
type: 'image',
// 左下角它的一个坐标位置360✖400
// 右上角的是640✖600
extent: [360, 400, 640, 600]
}
}
);
scene.on('loaded', () => {
getList()
scene.addLayer(imagelayer);
});
})
const getList = async () => {
var res = await axios.get("/adminapi/labs")
// console.log(res.data);
// map映射我们想要的结构
var list = res.data.map(item => ({
x: item.x,
y: item.y,
t: "预约"+item.title
}))
// 调用文字标注方法
addTextLayer(list)
}
// 添加
const dialogVisible = ref(false)
const addFormRef = ref()
const addForm = reactive({
title: "",
capacity: "",
lab_type: "",
college_type: "",
x: 0,
y: 0
})
const rules = reactive({
title: [
{ required: true, message: '请输入实验室名称', trigger: 'blur' }
],
capacity: [
{ required: true, message: '请输入容纳人数', trigger: 'blur' }
],
lab_type: [
{ required: true, message: '请选择实验室类型', trigger: 'blur' }
],
college_type: [
{ required: true, message: '请选择学院类型', trigger: 'blur' }
]
})
const handleConfirm = () => {
addFormRef.value.validate(async (valid) => {
if (valid) {
dialogVisible.value = false
console.log(addForm);
// 发送axios.post
await axios.post(`/adminapi/labs`, addForm)
// 添加文字标注
addTextLayer([
{
"x": addForm.x,
"y": addForm.y,
"t": addForm.title
}
])
}
})
}
const addTextLayer = (data) => {
const textlayer = new PointLayer({ zIndex: 2 })
.source(
data,
{
parser: {
type: 'json',
x: 'x',
y: 'y'
}
}
)
.shape('t', 'text')
.size(14)
.active({
color: '#00f',
mix: 0.9
})
.color('rgb(13,71,161)')
.style({
textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
spacing: 2, // 字符间距
fontWeight: '800',
padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
stroke: '#ffffff', // 描边颜色
strokeWidth: 2, // 描边宽度
textAllowOverlap: true
});
scene.addLayer(textlayer);
}
</script>
<style></style>
预约3号实验室信息显示出来了,它跟我们的实验室列表的名字一一对应,地理位置也没有改变。
通过管理员账号新建实验室,等你再用教师角色预约的时候,我们就能看到新的预约实验室了。
1.2、点击文字弹出对话框
文字绑定点击事件
点击文字直接打印出对应的对象,所以在地理可视化中能支持文字绑定事件响应,而且形参上还给我们传来了我们需要的信息,在feature中里面有title、x、y,它们被feature包装。我们可以基于此时获取的feature来动态改变对话框上的title。
1.3、修改对话框中的字段和校验规则
1.4、获取当前点击的这一项,并且显示对话框![](https://img-blog.csdnimg.cn/a80d673744ff4a91824e4d4c962942ae.png)
1.5、预约课节和预约原因![](https://img-blog.csdnimg.cn/d0133096b60246fea0009711191859f1.png)
1.6、预约时间
1.6.1、把字体改成中文
1.6.2、 禁用日期选择函数disabledDate
这个组件还没用完,等我们选择某一天之后应该还有一个时间选择了一个回调,而这个回调中我们应该去判断这一天中的某一节课是不是可选的,如果不可选就禁用,但这个功能需要后端的配合。
1.7、测试
我们测试一下前端是否可以提交数据
都提交进去了。
2.后端创建接口
2.1、数据库中创建表
0 审核中,1 审核通过 2 被驳回
2.2、pojo层
2.3、dao层
2.4、xml![](https://img-blog.csdnimg.cn/96f8a823fa9a4dc89e19af312dbdae9c.png)
2.5、service层
2.6、controller层
2.7、运行启动后去测试
3、在前端补充代码
现在前端中缺少lab_id字段和book_username字段。
我们导入useUserStore,解构出user对象,就是当前登录用户信息,等我们再点击确认的时候,把book_username加上去,就是我们的user.username,传给后端,把原来的东西“...”展开放在一个的对象中。
在list中加入新字段id
前后端完成,我们一起来实现一下预约实验室
4、消息提示
5、课节禁用
5.1、回调函数
我们后端传入对应的lab_id和book_time,那它就应该给我们筛选出这一个实验室在这一天的所有的数据给我们返回来。那么前端就需要检索出来,因为它返回回来的数据里面一定包含课节book_class,所以我们前端接收的是我们一个课节数组,如果它给我们的数组不是完整的数组,我们可以直接进行一个过滤就可以了,到时候我们利用这个数组好控制我们的下拉列表中是不是哪一项改禁用的,就这样一个前端应该给它的这样的一个数据。
注意:后端在查询数据库的时候需要控制一下book_state不等于2,我们提交给后端中数据有一个state预约实验室的审核状态,book_state是0的时候应该返回数据,因为此时是审核中的,所以别人也不能预约,如果它的值是1的话,审核通过,那别人更不可能预约了。如果值是2的是审核不通过,管理员驳回了,别人或者还是当前这个人就还可以预约,把理由好好写写。
所以说在后端查询数据库的时候要把book_state这个值做一下筛选判断,不能等于2,所以只能等于0和1。
注意:前端向后端发送请求不能用get,要用post,因为我们这里需要传入的那个book_time,后端接收的是一个date类型的,但是由于我们的axios在get请求的时候会对于日期做一个转化,强行转成字符串的日期格式,在get参数中后端获取不到,所以在这里可能会有点问题。
在post请求中,发送axios中的时间会自动转化为ISO 8601格式。传给后端,能正常的进行一个接收。
该格式表示日期和时间的字符串,具有统一的格式和易读性。这可以确保在不同的系统和语言之间正确解析和处理时间数据。
ISO 8601格式是一种国际标准化组织(ISO)定义的日期和时间表示格式。它使用’YYYY-MM-DD’的形式来表示日期,并且可以扩展到包含时间、时区和其他相关信息。该格式的设计旨在提供一种统一的方法来表示日期和时间,以便各个国家和地区都可以方便地解析和交换日期和时间信息。
5.2、后端创建接口
测试![](https://img-blog.csdnimg.cn/91c2e044e7574816b4f23af4f6cc0211.png)
5.3、前端