2023.6.16
1. 精进了一些功能 2. 修复了一些BUG 3. 整合了前端
@ -2,6 +2,10 @@ package com.sdut.labex.Factory;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.sdut.labex.entity.BorrowInfo;
|
||||
import com.sdut.labex.utils.UserHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* File: BorrowInfoFactory
|
||||
@ -9,17 +13,23 @@ import com.sdut.labex.entity.BorrowInfo;
|
||||
* Author: springforest
|
||||
* Description:
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
public class BorrowInfoFactory {
|
||||
public static BorrowInfo createBorrowInfo(JSONObject jsonObject) {
|
||||
BorrowInfo borrowInfo = new BorrowInfo();
|
||||
try {
|
||||
borrowInfo.setId(jsonObject.getInteger("id"));
|
||||
borrowInfo.setApplyUser(jsonObject.getString("applyUser"));
|
||||
borrowInfo.setTime(jsonObject.getString("time"));
|
||||
borrowInfo.setApplyUser(UserHolder.getUser().getUsername());
|
||||
borrowInfo.setDate(jsonObject.getDate("date"));
|
||||
borrowInfo.setApplyDate(jsonObject.getDate("applyDate"));
|
||||
borrowInfo.setApplyDate(new Date());
|
||||
borrowInfo.setIsAdmit(jsonObject.getInteger("isAdmit"));
|
||||
borrowInfo.setRoomName(jsonObject.getString("roomName"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("json解析错误");
|
||||
return null;
|
||||
}
|
||||
|
||||
return borrowInfo;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.sdut.labex.config;
|
||||
|
||||
import com.sdut.labex.interceptor.TokenInterceptor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@ -17,10 +18,10 @@ public class MVBConfig implements WebMvcConfigurer {
|
||||
@Resource
|
||||
private TokenInterceptor tokenInterceptor;
|
||||
|
||||
//@Override
|
||||
//public void addInterceptors(InterceptorRegistry registry) {
|
||||
// registry.addInterceptor(tokenInterceptor)
|
||||
// .excludePathPatterns("/login/**")
|
||||
// .excludePathPatterns("/register/**");
|
||||
//}
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(tokenInterceptor)
|
||||
.excludePathPatterns("/login/**")
|
||||
.excludePathPatterns("/register/**");
|
||||
}
|
||||
}
|
||||
|
@ -10,9 +10,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* File: BorrowInfoController
|
||||
@ -29,35 +27,13 @@ public class BorrowInfoController {
|
||||
|
||||
@PostMapping("/borrowInfo")
|
||||
public ResVo addBorrowInfo(@RequestBody JSONObject jsonObject) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("name", jsonObject.getString("username"));
|
||||
map.put("date", jsonObject.getString("date"));
|
||||
map.put("reason", jsonObject.getString("reason"));
|
||||
map.put("applyDate", jsonObject.getString("applyDate"));
|
||||
map.put("roomName", jsonObject.getString("roomName"));
|
||||
|
||||
JSONArray timeList = jsonObject.getJSONArray("time");
|
||||
|
||||
boolean isAnyRoomBorrowed = false;
|
||||
|
||||
BorrowInfo borrowInfo = BorrowInfoFactory.createBorrowInfo(jsonObject);
|
||||
List<String> list = new ArrayList<>();
|
||||
for (Object item : timeList) {
|
||||
map.put("time", item.toString());
|
||||
int code = borrowInfoService.isBorrowed(map);
|
||||
if (code == 1) {
|
||||
return ResVo.error("借用失败,所选时段教室被占用");
|
||||
} else if (code == 0) {
|
||||
isAnyRoomBorrowed = true;
|
||||
list.add(item.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (isAnyRoomBorrowed) {
|
||||
for (Object item : timeList) {
|
||||
map.put("time", item.toString());
|
||||
borrowInfoService.borrow(map);
|
||||
}
|
||||
}
|
||||
|
||||
return ResVo.ok("借用成功");
|
||||
return borrowInfoService.borrow(list, borrowInfo);
|
||||
}
|
||||
|
||||
@PostMapping("/borrowInfo/notBorrowedYet")
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.sdut.labex.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.sdut.labex.service.TableService;
|
||||
import com.sdut.labex.utils.ResVo;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -19,9 +20,10 @@ public class TableController {
|
||||
@Resource
|
||||
private TableService tableService;
|
||||
|
||||
@GetMapping("/getUnusedTable/{date}/{roomName}")
|
||||
public ResVo getUnusedTable(@PathVariable("date") String date,
|
||||
@PathVariable("roomName") String roomName) {
|
||||
@PostMapping("/getUnusedTable")
|
||||
public ResVo getUnusedTable(@RequestBody JSONObject jsonObject) {
|
||||
String roomName = jsonObject.getString("roomName");
|
||||
String date = jsonObject.getString("date");
|
||||
if (roomName.equals("")) {
|
||||
roomName = "9教207";
|
||||
}
|
||||
|
@ -21,10 +21,10 @@ public class TimeOptionController {
|
||||
@Resource
|
||||
private TimeOptionService timeOptionService;
|
||||
|
||||
@PostMapping("/timeOption")
|
||||
public ResVo addTimeOption(@RequestBody JSONObject jsonObject) {
|
||||
@PostMapping("/timeOption/{name}")
|
||||
public ResVo addTimeOption(@PathVariable("name") String name) {
|
||||
TimeOption timeOption = new TimeOption();
|
||||
timeOption.setName(jsonObject.getString("name"));
|
||||
timeOption.setName(name);
|
||||
return timeOptionService.addTimeOption(timeOption);
|
||||
}
|
||||
|
||||
@ -36,9 +36,9 @@ public class TimeOptionController {
|
||||
return timeOptionService.updateTimeOption(timeOption);
|
||||
}
|
||||
|
||||
@DeleteMapping("/timeOption")
|
||||
public ResVo deleteTimeOption(@RequestBody JSONObject jsonObject) {
|
||||
return timeOptionService.deleteTimeOption(jsonObject.getInteger("id"));
|
||||
@DeleteMapping("/timeOption/{id}")
|
||||
public ResVo deleteTimeOption(@PathVariable("id") Integer id) {
|
||||
return timeOptionService.deleteTimeOption(id);
|
||||
}
|
||||
|
||||
@GetMapping("/timeOption")
|
||||
|
@ -50,4 +50,16 @@ public class UserController {
|
||||
User user = UserFactory.createUser(jsonObject);
|
||||
return userService.update(user);
|
||||
}
|
||||
|
||||
@PostMapping("/user/{pageNum}/{pageSize}")
|
||||
public ResVo getUser(@RequestBody JSONObject jsonObject, @PathVariable("pageNum") int pageNum, @PathVariable("pageSize") int pageSize) {
|
||||
User user = UserFactory.createUser(jsonObject);
|
||||
return userService.getUser(pageNum, pageSize, user);
|
||||
}
|
||||
|
||||
@PostMapping("/user")
|
||||
public ResVo add(@RequestBody JSONObject jsonObject) {
|
||||
User user = UserFactory.createUser(jsonObject);
|
||||
return userService.add(user);
|
||||
}
|
||||
}
|
||||
|
@ -20,14 +20,10 @@ import java.util.Map;
|
||||
public interface BorrowInfoMapper extends BaseMapper<BorrowInfo> {
|
||||
public Page<BorrowInfo> queryBorrowInfoByOptions(Page<BorrowInfo> page, BorrowInfo borrowInfo);
|
||||
|
||||
public BorrowInfo borrow(Map<String, String> map);
|
||||
|
||||
public void addTimeTable(Map<String, String> map);
|
||||
|
||||
public List<BorrowInfo> listAllByDateAndRoom(String date, String room);
|
||||
|
||||
public BorrowInfo isBorrowed(@Param("roomName") String roomName, @Param("time") String time, @Param("date") String date);
|
||||
|
||||
public List<Room> notBorrowedYet(@Param("timeList") List<String> timeList, @Param("date") String date);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.sdut.labex.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.sdut.labex.entity.User;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@ -15,4 +16,6 @@ import java.util.List;
|
||||
@Mapper
|
||||
public interface UserMapper extends BaseMapper<User> {
|
||||
public void insertBatch(List<User> list);
|
||||
|
||||
public Page<User> getUser(Page<User> page, User user);
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import com.sdut.labex.entity.BorrowInfo;
|
||||
import com.sdut.labex.utils.ResVo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author springforest
|
||||
@ -14,7 +13,7 @@ import java.util.Map;
|
||||
*/
|
||||
public interface BorrowInfoService extends IService<BorrowInfo> {
|
||||
|
||||
public ResVo borrow(Map<String, String> map);
|
||||
public ResVo borrow(List<String> timeList, BorrowInfo borrowInfo);
|
||||
|
||||
public ResVo deleteBorrowInfoById(Integer id);
|
||||
|
||||
@ -22,7 +21,7 @@ public interface BorrowInfoService extends IService<BorrowInfo> {
|
||||
|
||||
public ResVo notBorrowedYet(List<String> timeList, String date);
|
||||
|
||||
public int isBorrowed(Map<String, String> map);
|
||||
public int isBorrowed(BorrowInfo borrowInfo);
|
||||
|
||||
|
||||
}
|
||||
|
@ -24,4 +24,6 @@ public interface UserService extends IService<User> {
|
||||
public ResVo update(User user);
|
||||
|
||||
public ResVo addBatch(MultipartFile file);
|
||||
|
||||
public ResVo getUser(int pageNum, int pageSize, User user);
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.sdut.labex.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.sdut.labex.entity.BorrowInfo;
|
||||
@ -8,14 +10,12 @@ import com.sdut.labex.mapper.BorrowInfoMapper;
|
||||
import com.sdut.labex.service.BorrowInfoService;
|
||||
import com.sdut.labex.utils.ResVo;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author springforest
|
||||
@ -33,20 +33,34 @@ public class BorrowInfoServiceImpl extends ServiceImpl<BorrowInfoMapper, BorrowI
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Override
|
||||
public ResVo borrow(Map<String, String> map) {
|
||||
try {
|
||||
synchronized (this) {//线程锁
|
||||
//默认为通过审核(0未审核,1通过,2拒绝)
|
||||
map.put("isAdmit", "1");
|
||||
borrowInfoMapper.borrow(map);
|
||||
public ResVo borrow(List<String> timeList, BorrowInfo borrowInfo) {
|
||||
boolean isAnyRoomBorrowed = false;
|
||||
|
||||
for (String item : timeList) {
|
||||
BorrowInfo newBorrowInfo = new BorrowInfo();
|
||||
BeanUtil.copyProperties(borrowInfo, newBorrowInfo); // 使用BeanUtil进行属性拷贝
|
||||
newBorrowInfo.setTime(item.toString());
|
||||
int code = this.isBorrowed(newBorrowInfo);
|
||||
if (code == 1) {
|
||||
return ResVo.error("借用失败,所选时段教室被占用");
|
||||
} else if (code == 0) {
|
||||
isAnyRoomBorrowed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isAnyRoomBorrowed) {
|
||||
for (String item : timeList) {
|
||||
BorrowInfo newBorrowInfo = new BorrowInfo();
|
||||
BeanUtil.copyProperties(borrowInfo, newBorrowInfo);
|
||||
newBorrowInfo.setTime(item.toString());
|
||||
newBorrowInfo.setIsAdmit(1);
|
||||
borrowInfoMapper.insert(newBorrowInfo);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return ResVo.error("借用失败");
|
||||
}
|
||||
return ResVo.ok("借用成功");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ResVo deleteBorrowInfoById(Integer id) {
|
||||
if (borrowInfoMapper.selectById(id) == null) {
|
||||
@ -75,32 +89,20 @@ public class BorrowInfoServiceImpl extends ServiceImpl<BorrowInfoMapper, BorrowI
|
||||
|
||||
@Override
|
||||
public ResVo notBorrowedYet(List<String> timeList, String date) {
|
||||
List<Room> RBI;
|
||||
String key = "notBorrowedYet:" + timeList.toString() + "_" + date;
|
||||
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
|
||||
//拆箱的 'redisTemplate.hasKey(key)' 可能产生 'java.lang.NullPointerException
|
||||
if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
|
||||
//缓存命中
|
||||
return (ResVo) valueOperations.get(key);
|
||||
} else {
|
||||
//缓存未命中,先添加缓存
|
||||
RBI = borrowInfoMapper.notBorrowedYet(timeList, date);
|
||||
List<Room> RBI = borrowInfoMapper.notBorrowedYet(timeList, date);
|
||||
|
||||
Map<String, Object> res = new HashMap<>();
|
||||
res.put("list", RBI);
|
||||
//存入缓存
|
||||
valueOperations.set(key, ResVo.ok(res));
|
||||
//设置过期时间
|
||||
redisTemplate.expire(key, 12, TimeUnit.HOURS);
|
||||
return ResVo.ok(res);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isBorrowed(Map<String, String> map) {
|
||||
String date = map.get("date");
|
||||
String time = map.get("time");
|
||||
String roomName = map.get("roomName");
|
||||
if (borrowInfoMapper.isBorrowed(roomName, time, date) != null) {
|
||||
public int isBorrowed(BorrowInfo borrowInfo) {
|
||||
QueryWrapper<BorrowInfo> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.select("id").eq("room_name", borrowInfo.getRoomName())
|
||||
.eq("time", borrowInfo.getTime()).eq("date", borrowInfo.getDate());
|
||||
|
||||
if (borrowInfoMapper.selectOne(queryWrapper) != null) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.sdut.labex.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.sdut.labex.dto.TimeTable;
|
||||
import com.sdut.labex.entity.BorrowInfo;
|
||||
import com.sdut.labex.entity.Room;
|
||||
@ -39,45 +40,37 @@ public class TableServiceImpl implements TableService {
|
||||
|
||||
@Override
|
||||
public ResVo getUnUsedTable(String room, String date) {
|
||||
List<BorrowInfo> borrowedList = borrowInfoMapper.listAllByDateAndRoom(room, date);
|
||||
log.info("borrowedList: " + borrowedList.toString());
|
||||
Map<String, List<String>> tempMap = new HashMap<>();
|
||||
// 获取所有教室
|
||||
List<Room> roomList = roomMapper.selectList(null);
|
||||
// 获取所有时间(按顺序)
|
||||
List<TimeOption> timeOptionList = timeOptionMapper.selectList(null);
|
||||
QueryWrapper<BorrowInfo> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("date", date);
|
||||
List<BorrowInfo> borrowedList = borrowInfoMapper.selectList(queryWrapper);
|
||||
|
||||
Map<String, Set<String>> tempMap = new HashMap<>();
|
||||
List<Room> roomList = roomMapper.selectList(null);
|
||||
List<TimeOption> timeOptionList = timeOptionMapper.selectList(new QueryWrapper<TimeOption>().orderByAsc("order_number"));
|
||||
|
||||
try {
|
||||
for (TimeOption time : timeOptionList) {
|
||||
List<String> rooms = new ArrayList<>();
|
||||
Set<String> rooms = new HashSet<>();
|
||||
tempMap.put(time.getName(), rooms);
|
||||
}
|
||||
|
||||
for (BorrowInfo item : borrowedList) {
|
||||
log.info(item.toString());
|
||||
tempMap.get(item.getTime()).add(item.getRoomName());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return ResVo.error("解析时间或记录出错");
|
||||
}
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
List<List<String>> res = new ArrayList<>();
|
||||
|
||||
// 获取不在borrowedList中的教室
|
||||
for (TimeOption key : timeOptionList) {
|
||||
List<String> rooms = new ArrayList<>();
|
||||
for (Room item : roomList) {
|
||||
if (!tempMap.get(key.getName()).contains(item.getName())) {
|
||||
for (Room item : roomMapper.selectList(new QueryWrapper<Room>().in("name", tempMap.get(key.getName())))) {
|
||||
rooms.add(item.getName());
|
||||
}
|
||||
}
|
||||
res.add(rooms);
|
||||
}
|
||||
|
||||
if (room != null && !room.isEmpty()) {
|
||||
for (List<String> rooms : res) {
|
||||
rooms.removeIf(r -> !r.equals(room));
|
||||
rooms.removeIf(r -> !r.contains(room));
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,6 +78,7 @@ public class TableServiceImpl implements TableService {
|
||||
return ResVo.ok(map);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ResVo uploadTable(MultipartFile file, String startDate, String roomName) {
|
||||
try {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.sdut.labex.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.sdut.labex.entity.User;
|
||||
import com.sdut.labex.mapper.UserMapper;
|
||||
@ -17,6 +18,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* File: UserServiceImpl
|
||||
@ -44,7 +46,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
|
||||
map.put("id", user.getId());
|
||||
map.put("role", user.getRole());
|
||||
map.put("username", user.getUsername());
|
||||
map.put("classId", user.getClassName());
|
||||
map.put("className", user.getClassName());
|
||||
map.put("department", user.getDepartment());
|
||||
String token = JWTUtil.getTokenByMap(map);
|
||||
map.put("token", token);
|
||||
@ -121,7 +123,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
|
||||
return ResVo.error("解析Excel出错");
|
||||
}
|
||||
|
||||
int startRow = 0;
|
||||
int startRow = 1;
|
||||
int endRow = excel.totalRows;
|
||||
List<User> list = new ArrayList<>();
|
||||
for (int i = startRow; i < endRow; i++) {
|
||||
@ -129,13 +131,20 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
|
||||
|
||||
//学号
|
||||
try {
|
||||
if (excel.readCell(i, 0) == null) {
|
||||
break;
|
||||
}
|
||||
user.setId(excel.readCell(i, 0));
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return ResVo.error("Excel格式错误:第" + (i + 1) + "行第1列");
|
||||
}
|
||||
//姓名
|
||||
try {
|
||||
if (excel.readCell(i, 1) == null) {
|
||||
return ResVo.error("Excel格式错误:第" + (i + 1) + "行第2列");
|
||||
}
|
||||
user.setUsername(excel.readCell(i, 1));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@ -147,6 +156,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
|
||||
user.setRole("student");
|
||||
//班级
|
||||
try {
|
||||
if (excel.readCell(i, 2) == null) {
|
||||
return ResVo.error("Excel格式错误:第" + (i + 1) + "行第3列");
|
||||
}
|
||||
user.setClassName(excel.readCell(i, 2));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@ -154,6 +166,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
|
||||
}
|
||||
//学院
|
||||
try {
|
||||
if (excel.readCell(i, 3) == null) {
|
||||
return ResVo.error("Excel格式错误:第" + (i + 1) + "行第4列");
|
||||
}
|
||||
user.setDepartment(excel.readCell(i, 3));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@ -162,12 +177,24 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
|
||||
|
||||
list.add(user);
|
||||
}
|
||||
|
||||
userMapper.deleteBatchIds(list.stream().map(User::getId).collect(Collectors.toList()));
|
||||
try {
|
||||
userMapper.insertBatch(list);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return ResVo.error("批量添加失败");
|
||||
}
|
||||
return ResVo.ok();
|
||||
return ResVo.ok("批量添加成功" + list.size() + "条数据");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResVo getUser(int pageNum, int pageSize, User user) {
|
||||
Page<User> page = new Page<>(pageNum, pageSize);
|
||||
userMapper.getUser(page, user);
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("total", page.getTotal());
|
||||
map.put("list", page.getRecords());
|
||||
return ResVo.ok(map);
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,6 @@
|
||||
insert into borrow_info (apply_user, time, date, apply_date, is_admit, room_name)
|
||||
VALUES (#{applyUser}, #{time}, #{date}, #{applyDate}, 1, #{roomName});
|
||||
</insert>
|
||||
<insert id="borrow" parameterType="map">
|
||||
insert into borrow_info(name, time, date, applyDate, isAdmit, room_name)
|
||||
values (#{name}, #{time}, #{date}, #{applyDate}, #{isAdmit}, #{roomName})
|
||||
</insert>
|
||||
|
||||
<select id="queryBorrowInfoByOptions" resultType="com.sdut.labex.entity.BorrowInfo">
|
||||
select *
|
||||
@ -39,13 +35,7 @@
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
<select id="isBorrowed" resultType="com.sdut.labex.entity.BorrowInfo">
|
||||
select *
|
||||
from borrow_info
|
||||
where date = #{date}
|
||||
and time = #{time}
|
||||
and roomName = #{roomName};
|
||||
</select>
|
||||
|
||||
<select id="notBorrowedYet" resultType="com.sdut.labex.entity.Room">
|
||||
SELECT *
|
||||
FROM room
|
||||
|
@ -21,4 +21,15 @@
|
||||
#{item.role})
|
||||
</foreach>
|
||||
</insert>
|
||||
<select id="getUser" resultType="com.sdut.labex.entity.User" parameterType="object">
|
||||
select * from user
|
||||
<where>
|
||||
<if test="user.id != ''">
|
||||
and id = #{user.id}
|
||||
</if>
|
||||
<if test="user.username != ''">
|
||||
and username = #{user.username}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
|
0
web/babel.config.js
Normal file → Executable file
0
web/jsconfig.json
Normal file → Executable file
0
web/package-lock.json
generated
Normal file → Executable file
0
web/package.json
Normal file → Executable file
0
web/public/favicon.ico
Normal file → Executable file
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
0
web/public/index.html
Normal file → Executable file
59
web/src/App.vue
Normal file → Executable file
@ -1,34 +1,59 @@
|
||||
<template>
|
||||
<img src="./assets/logo.png">
|
||||
<div>
|
||||
<p>
|
||||
If Element Plus is successfully added to this project, you'll see an
|
||||
<code v-text="'<el-button>'"></code>
|
||||
below
|
||||
</p>
|
||||
<el-button type="primary">el-button</el-button>
|
||||
<div class="background">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
<HelloWorld msg="Welcome to Your Vue.js App"/>
|
||||
<Footer/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HelloWorld from './components/HelloWorld.vue'
|
||||
|
||||
import Footer from "@/components/Footer";
|
||||
export default {
|
||||
name: 'App',
|
||||
mounted() {
|
||||
document.title = "计算机科学与技术学院教室预约系统";
|
||||
|
||||
},
|
||||
created() {
|
||||
this.bodyScale()
|
||||
},
|
||||
methods:{
|
||||
bodyScale() {
|
||||
var devicewidth = document.documentElement.clientWidth; //获取当前分辨率下的可视区域宽度
|
||||
var scale = devicewidth / 1800; // 除以设计稿的尺寸
|
||||
document.body.style.zoom = scale; // 放大缩小相应倍数
|
||||
}
|
||||
},
|
||||
components: {
|
||||
HelloWorld
|
||||
Footer
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.background{
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
min-width: 1024px;
|
||||
min-height: 900px !important;
|
||||
/*width: 1440px;*/
|
||||
/*height: 900px;*/
|
||||
/*display: flex;*/
|
||||
/*justify-content: center;*/
|
||||
/*min-width: 1440px;*/
|
||||
}
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
font-family: Noto Sans SC, emoji;
|
||||
/*position: absolute;*/
|
||||
/*top: 0;*/
|
||||
/*right: 0;*/
|
||||
/*left: 0;*/
|
||||
/*bottom: 0;*/
|
||||
/*margin: auto;*/
|
||||
/*overflow-x: hidden;*/
|
||||
/*min-width: 1024px !important;*/
|
||||
/*min-height: 1080px !important;*/
|
||||
}
|
||||
</style>
|
||||
|
BIN
web/src/assets/img/loginBac.png
Executable file
After Width: | Height: | Size: 46 KiB |
BIN
web/src/assets/img/logo.png
Executable file
After Width: | Height: | Size: 803 B |
BIN
web/src/assets/img/logoW.png
Executable file
After Width: | Height: | Size: 51 KiB |
BIN
web/src/assets/img/picture/211.png
Executable file
After Width: | Height: | Size: 535 KiB |
BIN
web/src/assets/img/picture/other.jpg
Executable file
After Width: | Height: | Size: 328 KiB |
BIN
web/src/assets/img/院标2.0.png
Executable file
After Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 6.7 KiB |
21
web/src/components/Footer.vue
Normal file
@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<div style="display: flex;width: 100%;justify-content: center">
|
||||
<el-button style="border: 1px solid transparent" text @click="dialogVisible = true">© 2023 . All Rights Reserved | Designed by 张开源、臧群、彭凯 | 1.0
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Footer",
|
||||
data(){
|
||||
return{
|
||||
dialogVisible:false,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -1,59 +0,0 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br>
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HelloWorld',
|
||||
props: {
|
||||
msg: String
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
120
web/src/components/Table.vue
Normal file
@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<!--教室使用情况表-->
|
||||
<h4>可用教室</h4>
|
||||
<el-table :data="tableData" border>
|
||||
<el-table-column prop="date"/>
|
||||
<el-table-column v-for="(val,index) in timeSet" :key="index" :label="val" align="center">
|
||||
<template #default="scope">
|
||||
<el-space direction="vertical">
|
||||
<div v-for="(room,i) in scope.row.rooms[index]">
|
||||
<el-tag size="small">{{ room }}</el-tag>
|
||||
</div>
|
||||
</el-space>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-form label-width="120px" :inline="true" style="margin-top: 20px;margin-bottom: -20px">
|
||||
<el-form-item label="教室筛选">
|
||||
<div v-for="(item,i) in rooms">
|
||||
<el-tag type="warning" @click="subForm.roomName = item.name" style="cursor: pointer;margin-right: 20px;">
|
||||
{{ item.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Table",
|
||||
props: ["msg"],
|
||||
data() {
|
||||
return {
|
||||
rooms: [],
|
||||
subForm: {
|
||||
date: '',
|
||||
roomName: ''
|
||||
},
|
||||
timeSet: ['第一节', '第二节', '第三节', '第四节', '第五节', '第六节', '第七节', '第八节', '第九节', '第十节'],
|
||||
tableData: [],
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'msg.date'(newVal, oldVal) {
|
||||
//监测到日期变化,自动更新时间
|
||||
this.subForm.date = newVal;
|
||||
this.init();
|
||||
},
|
||||
'subForm.roomName'(newVal, oldVal) {
|
||||
//监测到教室变化,自动更新时间
|
||||
this.init();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
//此处传递的是引用
|
||||
this.subForm.date = this.$props.msg.date;
|
||||
this.subForm.roomName = this.$props.msg.roomName;
|
||||
this.init();
|
||||
this.getAllRoom();
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
//初始化表格数据函数
|
||||
this.tableData = [];
|
||||
//因为borrowForm中的Date会在发送请求的时候发生变化,所以在此处先取出来
|
||||
let tempDate = this.subForm.date;
|
||||
for (let i = 0; i < 7; i++) {
|
||||
this.tableData.push({
|
||||
date: this.setTimes(tempDate, i).substring(5, 10),
|
||||
rooms: []
|
||||
})
|
||||
this.subForm.date = this.setTimes(tempDate, i);
|
||||
setTimeout(() => {
|
||||
this.getTableData(i);
|
||||
}, 200);
|
||||
}
|
||||
//将日期恢复至最初的时间,防止下次调用时改变周期
|
||||
this.subForm.date = tempDate;
|
||||
},
|
||||
getAllRoom() {
|
||||
this.$http({
|
||||
method: 'get',
|
||||
url: '/room'
|
||||
}).then(res => {
|
||||
this.rooms = res.data.list;
|
||||
})
|
||||
},
|
||||
getTableData(offset) {
|
||||
this.$http({
|
||||
url: '/getUnusedTable',
|
||||
method: 'post',
|
||||
data: this.subForm
|
||||
}).then(res => {
|
||||
this.tableData[offset].rooms = res.data.list;
|
||||
})
|
||||
},
|
||||
//以指定的时间为基准,获取偏移量
|
||||
setTimes(selDate, offset) {
|
||||
let dataOp = null;
|
||||
if (selDate != null) {
|
||||
//selDate的格式为2022-10-14,先转换
|
||||
let year = parseInt(selDate.substring(0, 4));
|
||||
//Date中月份是0-11
|
||||
let month = parseInt(selDate.substring(5, 7)) - 1;
|
||||
let day = parseInt(selDate.substring(8, 10));
|
||||
dataOp = new Date(year, month, day);
|
||||
} else {
|
||||
//获取当前时间
|
||||
dataOp = new Date()
|
||||
}
|
||||
|
||||
dataOp.setDate(dataOp.getDate() + offset)
|
||||
return String(dataOp.getFullYear()) + '-' + String((dataOp.getMonth() + 1) < 10 ? '0' + (dataOp.getMonth() + 1) : (dataOp.getMonth() + 1)) + '-' + ((dataOp.getDate() + 1) <= 10 ? '0' + (dataOp.getDate()) : (dataOp.getDate()));
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
19
web/src/main.js
Normal file → Executable file
@ -3,7 +3,26 @@ import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import installElementPlus from './plugins/element'
|
||||
import axios from "axios";
|
||||
|
||||
|
||||
const app = createApp(App)
|
||||
installElementPlus(app)
|
||||
app.use(store).use(router).mount('#app')
|
||||
|
||||
app.config.globalProperties.$http = axios;
|
||||
//接口请求的基准路径
|
||||
axios.defaults.baseURL = 'http://localhost:8080/';
|
||||
// axios.defaults.baseURL = 'http://211.64.28.110:8080/';
|
||||
|
||||
// 添加请求拦截器
|
||||
|
||||
axios.interceptors.request.use(config => {
|
||||
// 在发送请求之前做些什么
|
||||
// 判断是否存在token,如果存在将每个页面header添加token
|
||||
if (sessionStorage.getItem("token")) {
|
||||
config.headers.token = sessionStorage.getItem("token");
|
||||
}
|
||||
|
||||
return config
|
||||
})
|
||||
|
0
web/src/plugins/element.js
Normal file → Executable file
80
web/src/router/index.js
Normal file → Executable file
@ -1,20 +1,64 @@
|
||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
import HomeView from '../views/HomeView.vue'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: HomeView
|
||||
redirect:'/Login'
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'about',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
|
||||
path: '/Home',
|
||||
name: 'Home',
|
||||
redirect: '/BorrowRoom',
|
||||
component: () => import('../views/Home.vue'),
|
||||
//---------------------教室借用相关-----------------------------
|
||||
children:[
|
||||
{
|
||||
path: '/BorrowRoom',
|
||||
name: 'BorrowRoom',
|
||||
component: () => import('../views/BorrowRoom/BorrowRoom.vue')
|
||||
},
|
||||
{
|
||||
path: '/BorrowInfoList',
|
||||
name: 'BorrowInfoList',
|
||||
component: () => import('../views/BorrowRoom/RecordList.vue')
|
||||
},
|
||||
//---------------------管理员部分-----------------------------
|
||||
{
|
||||
path: '/Admit',
|
||||
name: 'Admit',
|
||||
component: () => import('../views/Admin/Admit.vue')
|
||||
},
|
||||
{
|
||||
path: '/UserManage',
|
||||
name: 'UserManage',
|
||||
component: () => import('../views/Admin/UserManage.vue')
|
||||
},
|
||||
{
|
||||
path: '/RoomTimeAndReasonManage',
|
||||
name: 'RoomTimeAndReasonManage',
|
||||
component: () => import('../views/Admin/RoomAndTimeManage.vue')
|
||||
},
|
||||
{
|
||||
path: '/Personal',
|
||||
name: 'Personal',
|
||||
component: () => import('../views/Personal.vue')
|
||||
},
|
||||
//---------------------教师--------------------------------------------------------------------------
|
||||
{
|
||||
path: '/ApplyExperiment',
|
||||
name: 'ApplyExperiment',
|
||||
component: () => import('../views/ApplyExperiment/ApplyExperiment.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
//---------------------用户/Admin--------------------------------------------------------------------
|
||||
{
|
||||
path: '/Login',
|
||||
name: 'Login',
|
||||
component: () => import('../views/Login.vue')
|
||||
},
|
||||
|
||||
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
@ -22,4 +66,22 @@ const router = createRouter({
|
||||
routes
|
||||
})
|
||||
|
||||
//导航守卫
|
||||
//开启前先做白名单
|
||||
router.beforeEach((to, from, next) => {
|
||||
//页面拦截
|
||||
if (to.name !== 'Login') {
|
||||
let role = window.sessionStorage.getItem("role");
|
||||
// let token = window.sessionStorage.getItem("token");
|
||||
if (!role) {
|
||||
// return next({ name: 'Login' });
|
||||
}
|
||||
return next();
|
||||
} else {
|
||||
return next();
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
export default router
|
||||
|
0
web/src/store/index.js
Normal file → Executable file
@ -1,5 +0,0 @@
|
||||
<template>
|
||||
<div class="about">
|
||||
<h1>This is an about page</h1>
|
||||
</div>
|
||||
</template>
|
99
web/src/views/Admin/Admit.vue
Normal file
@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<el-table :data="admitlist" stripe border v-loading="loading" :highlight-current-row="true">
|
||||
<el-table-column align="center" prop="date" label="日期" width="120" />
|
||||
<el-table-column align="center" prop="time" label="时间" width="120" />
|
||||
<el-table-column align="center" prop="roomName" label="教室名称" width="100" />
|
||||
<el-table-column align="center" prop="reason" label="用途" width="150"/>
|
||||
<el-table-column align="center" prop="name" label="借用人" />
|
||||
<el-table-column align="center" prop="applyDate" label="申请时间" width="180"/>
|
||||
<el-table-column align="center" label="操作">
|
||||
<template #default="scope">
|
||||
<el-button type="success" @click="access(scope.row.id)" v-show="userInfo.role === 'admin'">允许</el-button>
|
||||
<el-button type="danger" @click="deny(scope.row.id)" v-show="userInfo.role === 'admin'">拒绝</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ElMessage} from "element-plus";
|
||||
|
||||
export default {
|
||||
name: "Admit",
|
||||
data(){
|
||||
return{
|
||||
loading: true,
|
||||
userInfo:{
|
||||
userId:'',
|
||||
role:'',
|
||||
username:'',
|
||||
userDepart:'',
|
||||
},
|
||||
admitlist:[],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.userInfo.role = window.sessionStorage.getItem("role");
|
||||
this.userInfo.userId = window.sessionStorage.getItem("userId");
|
||||
this.getAllAdmit()
|
||||
},
|
||||
methods:{
|
||||
getAllAdmit(){
|
||||
this.loading = true;
|
||||
this.$http({
|
||||
url:'/admit',
|
||||
method:'get',
|
||||
}).then(({data})=>{
|
||||
if (data.code !== 200){
|
||||
ElMessage({
|
||||
message: '信息获取失败',
|
||||
type: 'error',
|
||||
})
|
||||
}else {
|
||||
this.admitlist = data.list;
|
||||
}
|
||||
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
access(id){
|
||||
this.loading = true;
|
||||
this.$http({
|
||||
url:'/admit/access/' + id,
|
||||
method:'put',
|
||||
}).then(({data})=>{
|
||||
if (data.code !== 200){
|
||||
ElMessage({
|
||||
message: '操作失败',
|
||||
type: 'error',
|
||||
})
|
||||
}else {
|
||||
this.getAllAdmit();
|
||||
}
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
deny(id){
|
||||
this.loading = true;
|
||||
this.$http({
|
||||
url:'/admit/deny/' + id,
|
||||
method:'put',
|
||||
}).then(({data})=>{
|
||||
if (data.code !== 200){
|
||||
ElMessage({
|
||||
message: '操作失败',
|
||||
type: 'error',
|
||||
})
|
||||
}else {
|
||||
this.getAllAdmit();
|
||||
}
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
274
web/src/views/Admin/RoomAndTimeManage.vue
Normal file
@ -0,0 +1,274 @@
|
||||
<template>
|
||||
<el-page-header content="系统管理" style="margin-bottom: 30px" @back="this.$router.push('/Login')"/>
|
||||
<div class="bac" style="padding-left: 40px">
|
||||
<el-space>
|
||||
<!--时间管理-->
|
||||
<el-card shadow="always" :v-loading="isLoading" style="width: 500px;height: 300px">
|
||||
<el-space style="margin-bottom: 10px">
|
||||
<el-input placeholder="时间段名称" v-model="this.timeName"/>
|
||||
<el-button @click="addTime">添加时间段</el-button>
|
||||
</el-space>
|
||||
<el-table
|
||||
:data="times"
|
||||
highlight-current-row
|
||||
max-height="220">
|
||||
<el-table-column label="ID" prop="id"></el-table-column>
|
||||
<el-table-column label="时间段名称" prop="name"></el-table-column>
|
||||
<el-table-column label="操作" >
|
||||
<template #default="scope">
|
||||
<el-button type="danger" @click="removeTime(scope.row.id)" v-show="scope.row.id!==0">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-space>
|
||||
|
||||
<!--教室管理-->
|
||||
<el-card shadow="always" :v-loading="isLoading" style="width: 1050px;height: 450px;margin-top: 40px;">
|
||||
<el-space>
|
||||
<el-button @click="dialogVisible = true" style="margin-bottom: 10px">添加教室</el-button>
|
||||
</el-space>
|
||||
<el-table
|
||||
:data="rooms"
|
||||
highlight-current-row
|
||||
max-height="500">
|
||||
<el-table-column align="center" label="ID" prop="id" width="50px"></el-table-column>
|
||||
<el-table-column align="center" label="教室名称" prop="name" ></el-table-column>
|
||||
<el-table-column align="center" label="描述" prop="description" width="300px"></el-table-column>
|
||||
<el-table-column align="center" label="状态">
|
||||
<template #default="scope">
|
||||
<el-tag v-show="scope.row.status === 1">可用</el-tag>
|
||||
<el-tag type="danger" v-show="scope.row.status === 2">维护中</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" >
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="getRoomFromRow(scope.row)">更新</el-button>
|
||||
<el-button type="danger" @click="removeRoom(scope.row.id)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!--添加教室-->
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
title="活动管理"
|
||||
width="30%"
|
||||
>
|
||||
<el-form
|
||||
label-width="100px"
|
||||
:model="roomInfo"
|
||||
style="max-width: 460px"
|
||||
>
|
||||
<el-form-item label="教室ID">
|
||||
<el-input v-model="roomInfo.id" :disabled="isUpdate"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="教室名称">
|
||||
<el-input v-model="roomInfo.name" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input v-model="roomInfo.description" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-switch
|
||||
v-model="roomInfo.status"
|
||||
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
|
||||
active-text="可用"
|
||||
inactive-text="维护"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmForm">确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ElMessage, ElMessageBox} from "element-plus";
|
||||
let formData = new FormData();
|
||||
export default {
|
||||
name: "RoomAndTimeManage",
|
||||
data(){
|
||||
return{
|
||||
dialogVisible:false,
|
||||
isLoading:true,
|
||||
//时间段
|
||||
timeName:'',
|
||||
times:[],
|
||||
//教室
|
||||
roomInfo:{
|
||||
id:'',
|
||||
name:'',
|
||||
description:'',
|
||||
status:true,
|
||||
imgUrl:'',
|
||||
},
|
||||
rooms:[],
|
||||
isUpdate:false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getAllTime();
|
||||
this.getAllRoom();
|
||||
},
|
||||
methods:{
|
||||
//时间段
|
||||
getAllTime(){
|
||||
this.$http({
|
||||
method:'get',
|
||||
url:'/timeOption'
|
||||
}).then(({data}) =>{
|
||||
this.times = data.list;
|
||||
})
|
||||
},
|
||||
addTime(){
|
||||
this.$http({
|
||||
method:'post',
|
||||
url:'/timeOption/' + this.timeName,
|
||||
}).then(({data})=>{
|
||||
if (data.code ===200){
|
||||
//利用延时解决更新列表错误的问题
|
||||
this.timer = setTimeout(() => { //设置延迟执行
|
||||
this.getAllTime();
|
||||
this.timeName = '';
|
||||
}, 100);
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
removeTime(id){
|
||||
this.$http({
|
||||
method:'delete',
|
||||
url:'/timeOption/' + id,
|
||||
}).then(({data})=>{
|
||||
if (data.code === 200){
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功',
|
||||
})
|
||||
this.getAllTime();
|
||||
}
|
||||
})
|
||||
},
|
||||
//教室
|
||||
getAllRoom(){
|
||||
this.$http({
|
||||
method:'get',
|
||||
url:'/room'
|
||||
}).then(res =>{
|
||||
this.rooms = res.data.list;
|
||||
})
|
||||
},
|
||||
confirmForm(){
|
||||
if (this.isUpdate) {
|
||||
this.updateRoom();
|
||||
}else {
|
||||
this.addRoom()
|
||||
}
|
||||
},
|
||||
addRoom(){
|
||||
if (this.roomInfo.status){
|
||||
this.roomInfo.status = '1';
|
||||
}else {
|
||||
this.roomInfo.status = '2';
|
||||
}
|
||||
this.$http({
|
||||
method:'post',
|
||||
url:'/room',
|
||||
data:this.roomInfo
|
||||
}).then(({data})=>{
|
||||
if (data.code ===200){
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '添加成功',
|
||||
})
|
||||
}else {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: data.msg,
|
||||
})
|
||||
}
|
||||
})
|
||||
this.dialogVisible = false;
|
||||
this.roomInfo.status = true;
|
||||
this.roomInfo.name = '';
|
||||
this.roomInfo.imgUrl = '';
|
||||
this.roomInfo.description = '';
|
||||
this.isUpdate = false;
|
||||
//利用延时解决更新列表错误的问题
|
||||
this.timer = setTimeout(() => { //设置延迟执行
|
||||
this.getAllTime();
|
||||
this.getAllRoom();
|
||||
}, 100);
|
||||
|
||||
},
|
||||
removeRoom(id){
|
||||
this.$http({
|
||||
method:'delete',
|
||||
url:'/room/' + id,
|
||||
}).then(({data})=>{
|
||||
if (data.code === 200){
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功',
|
||||
})
|
||||
this.getAllRoom();
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
getRoomFromRow(row) {
|
||||
this.isUpdate = true;
|
||||
this.roomInfo = JSON.parse(JSON.stringify(row));
|
||||
this.dialogVisible = true;
|
||||
this.roomInfo.status = this.roomInfo.status === 1;
|
||||
},
|
||||
|
||||
updateRoom(){
|
||||
if (this.roomInfo.status){
|
||||
this.roomInfo.status = '1';
|
||||
}else {
|
||||
this.roomInfo.status = '2';
|
||||
}
|
||||
this.$http({
|
||||
method: 'put',
|
||||
url: '/room',
|
||||
data: this.roomInfo
|
||||
}).then(({data}) => {
|
||||
if (data.code === 200) {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '修改成功',
|
||||
})
|
||||
} else {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: data.msg,
|
||||
})
|
||||
}
|
||||
})
|
||||
this.timer = setTimeout(() => { //设置延迟执行
|
||||
this.getAllTime();
|
||||
this.getAllRoom();
|
||||
}, 200);
|
||||
|
||||
this.dialogVisible = false;
|
||||
this.roomInfo.status = true;
|
||||
this.roomInfo.name = '';
|
||||
this.roomInfo.imgUrl = '';
|
||||
this.roomInfo.description = '';
|
||||
this.isUpdate = false;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
222
web/src/views/Admin/UserManage.vue
Normal file
@ -0,0 +1,222 @@
|
||||
<template>
|
||||
|
||||
<el-page-header content="用户管理" style="margin-bottom: 30px" @back="this.$router.push('/Login')"/>
|
||||
<el-card style="max-width: 1200px;margin:0 auto;background-color: #f9fafb">
|
||||
<div style="display: flex;justify-content: space-between;align-items: center">
|
||||
<el-space>
|
||||
<el-button type="primary" style="margin-right: 10px;" @click="dialogVisibleForAdd = true">添加成员</el-button>
|
||||
<el-upload :on-change="fileChange" :show-file-list="false" :auto-upload="false">
|
||||
<el-button type="warning" :loading="loading">上传</el-button>
|
||||
</el-upload>
|
||||
</el-space>>
|
||||
</div>
|
||||
<!--表格展示-->
|
||||
<div style="margin-top: 20px">
|
||||
<el-table :data="userList" border stripe v-loading="loading">
|
||||
<el-table-column align="center" prop="id" label="ID"/>
|
||||
<el-table-column align="center" prop="username" label="姓名" />
|
||||
<el-table-column align="center" prop="className" label="班级"/>
|
||||
<el-table-column align="center" prop="department" label="学院"/>
|
||||
<el-table-column align="center" prop="role" label="身份"/>
|
||||
<el-table-column align="center" label="操作">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="update(scope.row)">
|
||||
<span style="margin-left: 3px">更新</span>
|
||||
</el-button>
|
||||
<el-button type="danger" @click="remove(scope.row.id)">
|
||||
<span style="margin-left: 3px">删除</span>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<el-pagination
|
||||
@size-change="getUser"
|
||||
@current-change="getUser"
|
||||
v-model:current-page="pageNum"
|
||||
|
||||
v-model:page-size="pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total">
|
||||
</el-pagination>
|
||||
<!--添加用户的对话框-->
|
||||
<el-dialog title="添加用户" v-model="dialogVisibleForAdd" width="30%" style="padding-top: 30px">
|
||||
<el-form ref="addForm" :model="addForm" label-width="100px">
|
||||
<el-form-item label="工号">
|
||||
<el-input :disabled="isEdit" v-model="addForm.id" placeholder="请输入工号..."></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="addForm.username" placeholder="请输入姓名..."></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="班级">
|
||||
<el-input v-model="addForm.className" placeholder="请输入班级..."></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="学院">
|
||||
<el-input v-model="addForm.department" placeholder="请输入班级..."></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码">
|
||||
<el-input v-model="addForm.password" placeholder="请输入密码..."></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="身份">
|
||||
<el-input v-model="addForm.role" placeholder="请输入密码..."></el-input>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="addUser">确 定</el-button>
|
||||
<el-button @click="dialogVisibleForAdd = false">取 消</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ElMessage, ElMessageBox} from "element-plus";
|
||||
let formData = new FormData;
|
||||
export default {
|
||||
name: "UserManage",
|
||||
data() {
|
||||
return {
|
||||
loading:true,
|
||||
isEdit:false,
|
||||
|
||||
pageSize:30,
|
||||
pageNum:1,
|
||||
total:0,
|
||||
|
||||
addForm:{
|
||||
id:'',
|
||||
username:'',
|
||||
role:'teacher',
|
||||
password:'123456',
|
||||
className:'',
|
||||
department:''
|
||||
},
|
||||
userList:[],
|
||||
dialogVisibleForAdd: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getUser();
|
||||
},
|
||||
methods: {
|
||||
getUser() {
|
||||
this.loading = true;
|
||||
this.userList = [];
|
||||
this.$http({
|
||||
method: 'post',
|
||||
url: '/user/' + this.pageNum + '/' + this.pageSize,
|
||||
data:{
|
||||
id:'',
|
||||
username:''
|
||||
}
|
||||
}).then(({data}) => {
|
||||
this.userList = data.list;
|
||||
this.total = data.total;
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
addUser() {
|
||||
let method = '';
|
||||
if(this.isEdit){
|
||||
method = 'put';
|
||||
}else {
|
||||
method = 'post';
|
||||
}
|
||||
this.$http({
|
||||
method: method,
|
||||
url: '/user' ,
|
||||
data: this.addForm
|
||||
}).then(({data}) => {
|
||||
if (data.code === 200) {
|
||||
ElMessage({
|
||||
message: '操作成功',
|
||||
type: 'success'
|
||||
})
|
||||
this.isEdit = false;
|
||||
this.dialogVisibleForAdd = false;
|
||||
this.addForm.username = '';
|
||||
this.addForm.id = '';
|
||||
this.addForm.password = '123456';
|
||||
this.getUser();
|
||||
}else {
|
||||
ElMessage({
|
||||
message: data.msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
update(row){
|
||||
this.addForm = JSON.parse(JSON.stringify(row));
|
||||
this.isEdit = true;
|
||||
|
||||
this.dialogVisibleForAdd = true;
|
||||
},
|
||||
remove(id) {
|
||||
ElMessageBox.confirm(
|
||||
'该操作不可撤销',
|
||||
'警告',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
this.$http({
|
||||
method: 'delete',
|
||||
url: '/user/' + id,
|
||||
}).then(res => {
|
||||
this.getUser();
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功',
|
||||
})
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: 'info',
|
||||
message: '删除已取消',
|
||||
})
|
||||
})
|
||||
},
|
||||
fileChange(files, fileList) {
|
||||
formData.append('file', files.raw)
|
||||
files = null;
|
||||
this.loading = true;
|
||||
this.$http({
|
||||
method: 'post',
|
||||
url: '/addUserBatch',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
}).then(res => {
|
||||
if (res.data.code === 200) {
|
||||
this.$notify({
|
||||
title: '上传成功',
|
||||
message: res.data.msg,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
this.$notify({
|
||||
title: '文件解析失败',
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
formData = null;
|
||||
formData = new FormData();
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
114
web/src/views/ApplyExperiment/ApplyExperiment.vue
Normal file
@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<el-page-header content="实验项目申请" style="margin-bottom: 30px" @back="this.$router.push('/Home')"/>
|
||||
<el-card>
|
||||
<div>
|
||||
<form @submit.prevent="onSubmit">
|
||||
<el-form-item label="项目名称">
|
||||
<el-input v-model="form.name" type="text" id="name" required/>
|
||||
</el-form-item>
|
||||
<el-form-item label="项目类型">
|
||||
<el-checkbox-group v-model="form.type">
|
||||
<el-checkbox label="类型一" name="type" />
|
||||
<el-checkbox label="类型二" name="type" />
|
||||
<el-checkbox label="类型三" name="type" />
|
||||
<el-checkbox label="类型四" name="type" />
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.desc" type="textarea" style="margin-left: 30px"/>
|
||||
</el-form-item>
|
||||
<el-form-item class="btn-Ex">
|
||||
<el-button type="primary" @click="onSubmit">确认</el-button>
|
||||
<el-button @click="cancelApply">取消</el-button>
|
||||
</el-form-item>
|
||||
</form>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card style="margin-top: 10px">
|
||||
<span style="width: 100%">待规划项目</span>
|
||||
<el-radio-group v-model="size">
|
||||
<el-radio label="large">Large</el-radio>
|
||||
<el-radio>Default</el-radio>
|
||||
<el-radio label="small">Small</el-radio>
|
||||
</el-radio-group>
|
||||
<el-table :data="itemList" style="width: 100%">
|
||||
<el-table-column fixed prop="name" label="项目名称" width="150" />
|
||||
<el-table-column prop="type" label="项目种类" width="120" />
|
||||
<el-table-column prop="state" label="审批状态" width="120" />
|
||||
<el-table-column prop="address" label="项目描述" width="600" />
|
||||
<el-table-column fixed="right" label="操作" width="120">
|
||||
<template #default>
|
||||
<el-button link type="primary" size="small" @click="setting"
|
||||
>Detail</el-button
|
||||
>
|
||||
<el-button link type="primary" size="small">设置</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const size = ref('')
|
||||
computed(() => {
|
||||
const marginMap = {
|
||||
large: '32px',
|
||||
default: '28px',
|
||||
small: '24px',
|
||||
}
|
||||
return {
|
||||
marginTop: marginMap[size.value] || marginMap.default,
|
||||
}
|
||||
});
|
||||
export default {
|
||||
name: 'ApplyExperiment',
|
||||
data() {
|
||||
return {
|
||||
itemList: [],
|
||||
form: {
|
||||
name: '',
|
||||
type: [],
|
||||
desc: '',
|
||||
},
|
||||
size:'',
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 在组件挂载后立即从后台获取元素列表
|
||||
axios.get('http://localhost:8080/room').then(response => {
|
||||
this.itemList = response.data;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
onSubmit() {
|
||||
axios.post('http://localhost:8080/room', this.form)
|
||||
.then(response => {
|
||||
console.log(response.data);
|
||||
// 处理成功响应
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
// 处理错误
|
||||
});
|
||||
},
|
||||
cancelApply(){
|
||||
this.$router.push('/Home');
|
||||
},
|
||||
setting(){
|
||||
this.$router.push('/BorrowRoom')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.btn-Ex {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
234
web/src/views/BorrowRoom/BorrowRoom.vue
Normal file
@ -0,0 +1,234 @@
|
||||
<template>
|
||||
<el-page-header content="借用登记" style="margin-bottom: 30px" @back="this.$router.push('/Login')"/>
|
||||
<el-card>
|
||||
<Table :msg="borrowForm"/>
|
||||
<el-divider/>
|
||||
<div>
|
||||
<el-form label-width="120px" :inline="true">
|
||||
<el-form-item label="日期">
|
||||
<el-date-picker
|
||||
v-model="borrowForm.date"
|
||||
type="date"
|
||||
placeholder="请选择借用日期"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
@change="getRoom"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="时间">
|
||||
<el-select
|
||||
v-model="borrowForm.time"
|
||||
placeholder="请选择借用时间"
|
||||
style="width: 200px"
|
||||
multiple
|
||||
collapse-tags
|
||||
@change="getRoom"
|
||||
placement="right"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in TimeOption"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-divider/>
|
||||
<div style="margin-left:20px;margin-right:20px;padding-left: 70px;padding-top: 40px;padding-bottom: 30px">
|
||||
<el-space :size="45" wrap>
|
||||
<div v-for="(item,i) in Rooms">
|
||||
<el-card :body-style="{ padding: '0px' }" style="width: 200px;">
|
||||
|
||||
<div style="padding: 14px">
|
||||
<div style="margin-bottom: 10px">{{ item.name }}</div>
|
||||
<div style="width: 100%;padding-left: 10px;padding-right: 10px">
|
||||
<el-space wrap v-for="(subItem,j) in item.description">
|
||||
<el-tag style="margin-top: 10px">{{ subItem }}</el-tag>
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button type="primary" @click="preBorrow(item.name)" v-if="item.status === 1" style="width: 100%">
|
||||
借用该教室
|
||||
</el-button>
|
||||
<el-button type="info" disabled v-if="item.status === 2" style="width: 100%">维护中</el-button>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-space>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-dialog
|
||||
v-model="confirmDialogVisible"
|
||||
title="请确认您的借用信息"
|
||||
width="30%"
|
||||
>
|
||||
<el-form label-width="120px">
|
||||
<el-form-item label="教室">
|
||||
{{ borrowForm.roomName }}
|
||||
</el-form-item>
|
||||
<el-form-item label="借用日期">
|
||||
{{ borrowForm.date }}
|
||||
</el-form-item>
|
||||
<el-form-item label="借用时间">
|
||||
<el-space v-for="(item,i) in borrowForm.time">
|
||||
<el-tag>{{ item }}</el-tag>
|
||||
</el-space>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="confirmDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmBorrow">确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ElMessage, ElMessageBox} from "element-plus";
|
||||
import Table from "../../components/Table"
|
||||
|
||||
export default {
|
||||
name: "BorrowRoom",
|
||||
data() {
|
||||
return {
|
||||
TimeOption: [],
|
||||
userInfo: {
|
||||
userId: '',
|
||||
role: '',
|
||||
username: '',
|
||||
userDepart: '',
|
||||
newPwd: '',
|
||||
oldPwd: ''
|
||||
},
|
||||
|
||||
Rooms: [],
|
||||
|
||||
isMedia: '',
|
||||
|
||||
borrowForm: {
|
||||
applyUser: '',
|
||||
time: [],
|
||||
date: '',
|
||||
roomName: '',
|
||||
},
|
||||
|
||||
confirmDialogVisible: false,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
//因为执行顺序问题,不宜使用Table组件中的setTimes
|
||||
this.borrowForm.date = this.setTimes(0);
|
||||
},
|
||||
mounted() {
|
||||
this.userInfo.role = window.sessionStorage.getItem('role');
|
||||
this.userInfo.username = window.sessionStorage.getItem("username");
|
||||
this.userInfo.userId = window.sessionStorage.getItem("userId");
|
||||
this.getAllTimeOptions();
|
||||
},
|
||||
methods: {
|
||||
getRoom() {
|
||||
if (this.borrowForm.date === '' || this.borrowForm.time.length === 0) {
|
||||
return;
|
||||
}
|
||||
this.$http({
|
||||
method: 'post',
|
||||
url: '/borrowInfo/notBorrowedYet',
|
||||
data: this.borrowForm
|
||||
}).then(({data}) => {
|
||||
if (data.code !== 200) {
|
||||
ElMessage({
|
||||
message: '教室信息获取失败,请联系管理员',
|
||||
type: 'error',
|
||||
})
|
||||
} else {
|
||||
this.Rooms = data.list;
|
||||
|
||||
for (let i = 0; i < this.Rooms.length; i++) {
|
||||
this.Rooms[i].description = this.Rooms[i].description.split(';');
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
//借用请求预处理
|
||||
preBorrow(roomName) {
|
||||
if (this.borrowForm.date === '' || this.borrowForm.time.length === 0) {
|
||||
ElMessage({
|
||||
message: '请完善借用信息',
|
||||
type: 'warning',
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
this.borrowForm.roomName = roomName;
|
||||
//添加借用人信息
|
||||
this.borrowForm.applyUser = this.userInfo.username;
|
||||
this.confirmDialogVisible = true;
|
||||
},
|
||||
|
||||
confirmBorrow() {
|
||||
this.confirmDialogVisible = false;
|
||||
this.$http({
|
||||
method: 'post',
|
||||
url: '/borrowInfo',
|
||||
data: this.borrowForm
|
||||
}).then(res => {
|
||||
if (res.data.code !== 200) {
|
||||
ElMessage({
|
||||
message: '登记失败,' + res.data.msg,
|
||||
type: 'warning',
|
||||
})
|
||||
} else {
|
||||
this.messageAlert();
|
||||
this.getRoom();
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
messageAlert() {
|
||||
ElMessageBox.confirm(
|
||||
'登记成功',
|
||||
{
|
||||
confirmButtonText: '确认',
|
||||
type: 'success',
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
getAllTimeOptions() {
|
||||
this.$http({
|
||||
url: '/timeOption',
|
||||
method: 'get',
|
||||
}).then(({data}) => {
|
||||
for (let i = 0; i < data.list.length; i++) {
|
||||
this.TimeOption.push({
|
||||
label: data.list[i].name,
|
||||
key: data.list[i].name,
|
||||
value: data.list[i].name
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
//以指定的时间为基准,获取偏移量
|
||||
setTimes(offset) {
|
||||
//获取当前时间
|
||||
let dataOp = new Date()
|
||||
|
||||
dataOp.setDate(dataOp.getDate() + offset)
|
||||
return String(dataOp.getFullYear()) + '-' + String((dataOp.getMonth() + 1) < 10 ? '0' + (dataOp.getMonth() + 1) : (dataOp.getMonth() + 1)) + '-' + ((dataOp.getDate() + 1) <= 10 ? '0' + (dataOp.getDate()) : (dataOp.getDate()));
|
||||
},
|
||||
|
||||
},
|
||||
components: {
|
||||
Table,
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
278
web/src/views/BorrowRoom/RecordList.vue
Normal file
@ -0,0 +1,278 @@
|
||||
<template>
|
||||
<el-page-header content="借用记录" style="margin-bottom: 30px" @back="this.$router.push('/Login')"/>
|
||||
<el-card>
|
||||
<el-form label-width="120px">
|
||||
<el-form-item label="日期">
|
||||
<el-date-picker
|
||||
v-model="subForm.date"
|
||||
type="date"
|
||||
placeholder="请选择借用日期"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
@change="getBorrowInfo"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="时间">
|
||||
<el-select
|
||||
v-model="subForm.time"
|
||||
placeholder="请选择借用时间"
|
||||
style="width: 200px"
|
||||
@change="getBorrowInfo"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in TimeOption"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="教室">
|
||||
<el-select
|
||||
v-model="subForm.roomName"
|
||||
placeholder="请选择教室"
|
||||
style="width: 200px"
|
||||
@change="getBorrowInfo">
|
||||
<el-option
|
||||
v-for="item in Rooms"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="导入课表" v-show="userInfo.role === 'admin'">
|
||||
<a href="/static/template.xls" download="课表模板.xlsx">
|
||||
<el-button type="primary" style="margin-right: 10px;" :loading="loading">下载模板</el-button>
|
||||
</a>
|
||||
<el-breadcrumb :separator-icon="ArrowRight" style="margin-right: 20px;">
|
||||
<el-date-picker v-model="this.startDate" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD" placeholder="学期开始日期"/>
|
||||
</el-breadcrumb>
|
||||
<el-upload :on-change="fileChange" :show-file-list="false" :auto-upload="false">
|
||||
<el-button type="warning" :loading="loading">上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="下载记录" v-show="userInfo.role === 'admin'">
|
||||
<el-button type="primary" @click="exportExcel">导出记录</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-divider />
|
||||
<div>
|
||||
<el-table :data="borrowInfo" stripe border v-loading="loading" :highlight-current-row="true">
|
||||
<el-table-column align="center" prop="date" label="日期" width="120" />
|
||||
<el-table-column align="center" prop="time" label="时间" width="120" />
|
||||
<el-table-column align="center" prop="roomName" label="教室名称" width="100" />
|
||||
<el-table-column align="center" prop="reason" label="用途" width="180"/>
|
||||
<el-table-column align="center" prop="name" label="借用人" />
|
||||
<el-table-column align="center" prop="applyDate" label="申请时间" width="200"/>
|
||||
<el-table-column align="center" width="100" label="状态">
|
||||
<template #default="scope">
|
||||
<el-tag v-show="scope.row.isAdmit === '0'" type="warning">待审核</el-tag>
|
||||
<el-tag v-show="scope.row.isAdmit === '2'" type="danger">拒绝</el-tag>
|
||||
<el-tag v-show="scope.row.isAdmit === '1'" type="success">通过</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" @click="cancel(scope.row.id)" v-show="userInfo.role === 'admin' || userInfo.username === scope.row.name">撤销</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
@size-change="getBorrowInfo"
|
||||
@current-change="getBorrowInfo"
|
||||
v-model:current-page="subForm.pageNum"
|
||||
|
||||
v-model:page-size="subForm.pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="subForm.total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ElMessage} from "element-plus";
|
||||
let formData = new FormData;
|
||||
export default {
|
||||
name: "BorrowInfoList",
|
||||
data(){
|
||||
return{
|
||||
loading:true,
|
||||
TimeOption:[],
|
||||
Rooms:[],
|
||||
|
||||
userInfo:{
|
||||
userId:'',
|
||||
role:'',
|
||||
username:'',
|
||||
userDepart:'',
|
||||
},
|
||||
|
||||
borrowInfo:[],
|
||||
|
||||
subForm:{
|
||||
date:'',
|
||||
time:'',
|
||||
reason:'',
|
||||
userId:'',
|
||||
roomName:'',
|
||||
pageNum:1,
|
||||
pageSize: 30,
|
||||
total:0
|
||||
},
|
||||
|
||||
startDate:null,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.userInfo.role = window.sessionStorage.getItem("role");
|
||||
this.userInfo.userId = window.sessionStorage.getItem("userId");
|
||||
this.userInfo.username = window.sessionStorage.getItem("username");
|
||||
this.getBorrowInfo();
|
||||
this.getAllRooms();
|
||||
this.getAllTimeOptions();
|
||||
console.log(this.userInfo)
|
||||
},
|
||||
methods:{
|
||||
getAllTimeOptions(){
|
||||
this.loading = true;
|
||||
this.$http({
|
||||
url:'/timeOption',
|
||||
method:'get',
|
||||
}).then(({data})=>{
|
||||
for(let i=0;i<data.list.length;i++){
|
||||
this.TimeOption.push({
|
||||
label:data.list[i].name,
|
||||
key:data.list[i].name,
|
||||
value:data.list[i].name
|
||||
})
|
||||
}
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
getAllRooms(){
|
||||
this.loading = true;
|
||||
this.$http({
|
||||
url:'/room',
|
||||
method:'get',
|
||||
}).then(({data})=>{
|
||||
for(let i=0;i<data.list.length;i++){
|
||||
this.Rooms.push({
|
||||
label:data.list[i].name,
|
||||
key:data.list[i].name,
|
||||
value:data.list[i].name
|
||||
})
|
||||
}
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
getBorrowInfo(){
|
||||
this.loading = true;
|
||||
this.$http({
|
||||
method:'post',
|
||||
url: '/borrowInfo',
|
||||
data:this.subForm
|
||||
}).then(res =>{
|
||||
console.log(res);
|
||||
if (res.data.code !== 200){
|
||||
ElMessage({
|
||||
message: '教室信息获取失败',
|
||||
type: 'error',
|
||||
})
|
||||
}else {
|
||||
this.borrowInfo = res.data.RBI;
|
||||
this.subForm.total = res.data.total;
|
||||
}
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
cancel(id){
|
||||
this.$http({
|
||||
method:'delete',
|
||||
url: '/borrowInfo/' + parseInt(id),
|
||||
}).then(res =>{
|
||||
ElMessage({
|
||||
message: '撤销成功',
|
||||
type: 'success',
|
||||
})
|
||||
this.getBorrowInfo();
|
||||
})
|
||||
},
|
||||
|
||||
fileChange(files, fileList) {
|
||||
formData.append('file', files.raw)
|
||||
files = null;
|
||||
this.importTimeTable();
|
||||
},
|
||||
|
||||
importTimeTable(){
|
||||
this.loading = true;
|
||||
if (this.startDate === null || this.subForm.roomName === ''){
|
||||
alert("请选择日期和教室");
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
formData.append("startDate",this.startDate);
|
||||
formData.append("roomName",this.subForm.roomName);
|
||||
|
||||
this.$http({
|
||||
method: 'post',
|
||||
url: '/file/importTimeTable',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
}).then(res => {
|
||||
if (res.data.code === 200) {
|
||||
this.$notify({
|
||||
title: '上传成功',
|
||||
message: '',
|
||||
type: 'success'
|
||||
});
|
||||
this.getBorrowInfo();
|
||||
} else {
|
||||
this.$notify({
|
||||
title: '文件解析失败',
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
formData = null;
|
||||
formData = new FormData();
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
exportExcel() {
|
||||
this.loading = true;
|
||||
this.$http({
|
||||
method: 'get',
|
||||
url: '/borrowInfo/exportExcel',
|
||||
responseType: "arraybuffer"
|
||||
}).then((file) => {
|
||||
//流文件下载
|
||||
let content = file.data;
|
||||
// 组装a标签
|
||||
let elink = document.createElement("a");
|
||||
// 设置下载文件名
|
||||
|
||||
elink.download ="借用记录.xls";
|
||||
elink.style.display = "none";
|
||||
let blob = new Blob([content], {type: "application/xls"})
|
||||
elink.href = URL.createObjectURL(blob);
|
||||
document.body.appendChild(elink);
|
||||
elink.click();
|
||||
document.body.removeChild(elink);
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
58
web/src/views/Home.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div class="background">
|
||||
<el-container>
|
||||
<el-aside width="200px">
|
||||
<div style="height: 100%;background-color: #334154">
|
||||
<el-menu
|
||||
active-text-color="#1989FA"
|
||||
background-color="#334154"
|
||||
class="el-menu-vertical-demo"
|
||||
default-active="2"
|
||||
text-color="#fff"
|
||||
:router="true">
|
||||
<div style="height: 70px;width: 100%;padding-top: 20px">
|
||||
<img src="../assets/img/logoW.png" style="height: 60%;width: 80%; margin-left: 20px;margin-top: 5px" alt="">
|
||||
</div>
|
||||
<el-menu-item index="/ApplyExperiment">实验项目申请</el-menu-item>
|
||||
<el-menu-item index="/BorrowRoom">教室借用</el-menu-item>
|
||||
<el-menu-item index="/RecordList">记录查询</el-menu-item>
|
||||
<el-menu-item index="/Admit" >项目审核</el-menu-item>
|
||||
<el-menu-item index="/UserManage" >用户管理</el-menu-item>
|
||||
<el-menu-item index="/RoomTimeAndReasonManage" >系统管理</el-menu-item>
|
||||
<el-menu-item index="/Personal">个人信息</el-menu-item>
|
||||
</el-menu>
|
||||
</div>
|
||||
</el-aside>
|
||||
<el-main>
|
||||
<router-view></router-view>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Home",
|
||||
data(){
|
||||
return{
|
||||
userInfo:{
|
||||
userId:'',
|
||||
role:'',
|
||||
username:'',
|
||||
userDepart:'',
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.userInfo.role = window.sessionStorage.getItem("role");
|
||||
this.userInfo.userId = window.sessionStorage.getItem("userId");
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.background{
|
||||
width: 1440px;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
@ -1,18 +0,0 @@
|
||||
<template>
|
||||
<div class="home">
|
||||
<img alt="Vue logo" src="../assets/logo.png">
|
||||
<HelloWorld msg="Welcome to Your Vue.js App"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// @ is an alias to /src
|
||||
import HelloWorld from '@/components/HelloWorld.vue'
|
||||
|
||||
export default {
|
||||
name: 'HomeView',
|
||||
components: {
|
||||
HelloWorld
|
||||
}
|
||||
}
|
||||
</script>
|
97
web/src/views/Login.vue
Normal file
@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<div class="bac">
|
||||
<div class="loginBox">
|
||||
<p>账号密码登陆</p>
|
||||
<el-space direction="vertical" :size="30">
|
||||
<el-input v-model="subform.id" placeholder="学号" clearable style="width: 240px;height: 40px;"/>
|
||||
<el-input v-model="subform.password" placeholder="密码" type="password" style="width: 240px;height: 40px;"/>
|
||||
</el-space>
|
||||
<el-button type="primary" @click="login()" @keyup.enter="login()" style="width: 240px;height: 40px;font-size: 14px">登陆</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Avatar, Key } from '@element-plus/icons-vue'
|
||||
import {ElNotification} from "element-plus";
|
||||
export default {
|
||||
name: 'Login',
|
||||
data(){
|
||||
return{
|
||||
subform:{
|
||||
id:'',
|
||||
password:'',
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener('keydown', this.handleEnterKey);
|
||||
},
|
||||
methods:{
|
||||
handleEnterKey(){
|
||||
// 检查是否按下回车键(keyCode为13)
|
||||
if (event.keyCode === 13) {
|
||||
// 触发按钮的点击事件
|
||||
this.login();
|
||||
}
|
||||
},
|
||||
login(){
|
||||
this.$http({
|
||||
method:'post',
|
||||
url:'/login',
|
||||
data:this.subform
|
||||
}).then(res =>{
|
||||
if(res.data.code!==200){
|
||||
ElNotification({
|
||||
title: '登陆失败',
|
||||
message: res.data.msg,
|
||||
type: 'warning',
|
||||
})
|
||||
}else if (res.data.code === 200){
|
||||
ElNotification({
|
||||
title: '登陆成功',
|
||||
message: '你好,' + res.data.username,
|
||||
type: 'success',
|
||||
})
|
||||
|
||||
//保存信息
|
||||
window.sessionStorage.setItem('role',res.data.role);
|
||||
window.sessionStorage.setItem('username',res.data.username);
|
||||
window.sessionStorage.setItem('userId', res.data.id.toString());
|
||||
window.sessionStorage.setItem('token', res.data.token);
|
||||
|
||||
this.$router.push('/Home');
|
||||
}else {
|
||||
ElNotification({
|
||||
title: '服务器错误',
|
||||
message: '工具人QQ:3231977651',
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
components:{
|
||||
Avatar,
|
||||
Key
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.bac{
|
||||
width: 1440px;
|
||||
height: 900px;
|
||||
background: url("../assets/img/loginBac.png");
|
||||
}
|
||||
|
||||
.loginBox{
|
||||
width: 250px;
|
||||
height: 320px;
|
||||
position: absolute;
|
||||
left: 62%;
|
||||
top: 320px;
|
||||
}
|
||||
</style>
|
92
web/src/views/Personal.vue
Normal file
@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<!--个人信息-->
|
||||
<el-page-header content="个人信息" style="margin-bottom: 30px" @back="this.$router.push('/Login')"/>
|
||||
<el-card style="padding-left: 60px;padding-right: 60px">
|
||||
<el-descriptions title="个人信息" border>
|
||||
<el-descriptions-item label="用户ID">{{userInfo.userId}}</el-descriptions-item>
|
||||
<el-descriptions-item label="用户名">{{userInfo.username}}</el-descriptions-item>
|
||||
<el-descriptions-item label="身份">{{userInfo.role}}</el-descriptions-item>
|
||||
<el-descriptions-item label="操作">
|
||||
<el-button type="primary" @click="pwdVisable=true">修改密码</el-button>
|
||||
<el-button type="danger" @click="logout">退出</el-button>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
<el-dialog
|
||||
v-model="pwdVisable"
|
||||
title="修改密码"
|
||||
width="30%"
|
||||
>
|
||||
<el-form label-width="120px">
|
||||
<el-form-item label="旧密码">
|
||||
<el-input v-model="userInfo.oldPwd"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="新密码">
|
||||
<el-input v-model="userInfo.newPwd"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="pwdVisable = false">取消</el-button>
|
||||
<el-button type="primary" @click="changePwd">确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ElMessage} from "element-plus";
|
||||
|
||||
export default {
|
||||
name: "Personal",
|
||||
data(){
|
||||
return{
|
||||
userInfo:{
|
||||
userId:'',
|
||||
role:'',
|
||||
username:'',
|
||||
userDepart:'',
|
||||
newPwd:'',
|
||||
oldPwd:''
|
||||
},
|
||||
pwdVisable:false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.userInfo.role = window.sessionStorage.getItem('role');
|
||||
this.userInfo.name = window.sessionStorage.getItem("username");
|
||||
this.userInfo.username = window.sessionStorage.getItem("username");
|
||||
this.userInfo.userId = window.sessionStorage.getItem("userId");
|
||||
},
|
||||
methods:{
|
||||
changePwd(){
|
||||
this.$http({
|
||||
url:'/changePwd',
|
||||
method:'put',
|
||||
data:this.userInfo
|
||||
}).then(({data})=> {
|
||||
if (data.code === 200){
|
||||
ElMessage({
|
||||
message: '修改成功',
|
||||
type: 'success',
|
||||
})
|
||||
this.pwdVisable = false;
|
||||
}else {
|
||||
ElMessage({
|
||||
message: '修改失败,' + data.msg,
|
||||
type: 'warning',
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
logout(){
|
||||
window.sessionStorage.clear();
|
||||
this.$router.push('/Login')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
20
web/vue.config.js
Normal file → Executable file
@ -2,3 +2,23 @@ const { defineConfig } = require('@vue/cli-service')
|
||||
module.exports = defineConfig({
|
||||
transpileDependencies: true
|
||||
})
|
||||
|
||||
// module.exports = {
|
||||
// chainWebpack: config => {
|
||||
// config.module
|
||||
// .rule('vue')
|
||||
// .use('vue-loader')
|
||||
// .tap(options => {
|
||||
// options.compilerOptions.isCustomElement = tag => tag.startsWith('el-')
|
||||
// return options
|
||||
// })
|
||||
//
|
||||
// config.module
|
||||
// .rule('ts')
|
||||
// .use('ts-loader')
|
||||
// .tap(options => {
|
||||
// options.appendTsSuffixTo = [/\.vue$/]
|
||||
// return options
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|