forked from liweijie/education
1、教学楼添加批量删除功能;
2、教学楼导入代号从excel获取,不要自己生成
This commit is contained in:
+14
-3
@@ -5,6 +5,8 @@ import com.roomroot.jwgl.service.BuildService;
|
|||||||
import com.roomroot.jwgl.unit.PageQuery;
|
import com.roomroot.jwgl.unit.PageQuery;
|
||||||
import com.roomroot.jwgl.unit.PageResult;
|
import com.roomroot.jwgl.unit.PageResult;
|
||||||
import com.roomroot.jwgl.unit.Result;
|
import com.roomroot.jwgl.unit.Result;
|
||||||
|
import com.roomroot.jwgl.vo.build.BuildDeleteResultVO;
|
||||||
|
import com.roomroot.jwgl.vo.build.BuildImportResultVO;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -40,6 +42,15 @@ public class BuildController {
|
|||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除教学楼(已绑定教学场地的跳过不删)
|
||||||
|
*/
|
||||||
|
@PostMapping("/batchDelete")
|
||||||
|
public Result<BuildDeleteResultVO> batchDelete(@RequestBody List<String> ids) {
|
||||||
|
BuildDeleteResultVO result = buildService.batchDelete(ids);
|
||||||
|
return Result.success(result.getMessage(), result);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新教学楼
|
* 更新教学楼
|
||||||
*/
|
*/
|
||||||
@@ -77,9 +88,9 @@ public class BuildController {
|
|||||||
* 导入Excel文件
|
* 导入Excel文件
|
||||||
*/
|
*/
|
||||||
@PostMapping("/import")
|
@PostMapping("/import")
|
||||||
public Result<Integer> importExcel(@RequestParam("file") MultipartFile file) {
|
public Result<BuildImportResultVO> importExcel(@RequestParam("file") MultipartFile file) {
|
||||||
int count = buildService.importExcel(file);
|
BuildImportResultVO result = buildService.importExcel(file);
|
||||||
return Result.success("导入成功", count);
|
return Result.success(result.getMessage(), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.roomroot.jwgl.service;
|
|||||||
import com.roomroot.jwgl.entity.JXLB;
|
import com.roomroot.jwgl.entity.JXLB;
|
||||||
import com.roomroot.jwgl.unit.PageQuery;
|
import com.roomroot.jwgl.unit.PageQuery;
|
||||||
import com.roomroot.jwgl.unit.PageResult;
|
import com.roomroot.jwgl.unit.PageResult;
|
||||||
|
import com.roomroot.jwgl.vo.build.BuildDeleteResultVO;
|
||||||
|
import com.roomroot.jwgl.vo.build.BuildImportResultVO;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@@ -23,11 +25,25 @@ public interface BuildService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除教学楼
|
* 删除教学楼
|
||||||
|
* <p>
|
||||||
|
* 已绑定教学场地(教室表存在引用该教学楼代号的未删除记录)时不允许删除。
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param id 主键
|
* @param id 主键
|
||||||
*/
|
*/
|
||||||
void delete(String id);
|
void delete(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除教学楼
|
||||||
|
* <p>
|
||||||
|
* 逐条校验教学场地绑定情况:已绑定教学场地的教学楼跳过不删,其余正常删除。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param ids 主键列表
|
||||||
|
* @return 删除结果(删除/跳过数量与明细)
|
||||||
|
*/
|
||||||
|
BuildDeleteResultVO batchDelete(List<String> ids);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新教学楼
|
* 更新教学楼
|
||||||
*
|
*
|
||||||
@@ -62,11 +78,15 @@ public interface BuildService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 导入Excel文件
|
* 导入Excel文件
|
||||||
|
* <p>
|
||||||
|
* 教学楼代号从模板「教学楼标识号」列读取(原样保留英文字母),留空则自动生成;
|
||||||
|
* 代号已存在的行跳过,不覆盖库中已有数据。
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param file Excel文件
|
* @param file Excel文件
|
||||||
* @return 导入数量
|
* @return 导入结果(新增/跳过数量与明细)
|
||||||
*/
|
*/
|
||||||
int importExcel(MultipartFile file);
|
BuildImportResultVO importExcel(MultipartFile file);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载模板文件
|
* 下载模板文件
|
||||||
|
|||||||
+145
-17
@@ -2,17 +2,24 @@ package com.roomroot.jwgl.service.impl;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.roomroot.common.utils.StringUtils;
|
||||||
|
import com.roomroot.jwgl.entity.JSB;
|
||||||
import com.roomroot.jwgl.entity.JXLB;
|
import com.roomroot.jwgl.entity.JXLB;
|
||||||
import com.roomroot.jwgl.mapper.BuildMapper;
|
import com.roomroot.jwgl.mapper.BuildMapper;
|
||||||
|
import com.roomroot.jwgl.mapper.ClassRoomMapper;
|
||||||
import com.roomroot.jwgl.service.BuildService;
|
import com.roomroot.jwgl.service.BuildService;
|
||||||
|
import com.roomroot.jwgl.unit.BusinessException;
|
||||||
import com.roomroot.jwgl.unit.PageQuery;
|
import com.roomroot.jwgl.unit.PageQuery;
|
||||||
import com.roomroot.jwgl.unit.PageResult;
|
import com.roomroot.jwgl.unit.PageResult;
|
||||||
import com.roomroot.jwgl.utils.UuidUtil;
|
import com.roomroot.jwgl.utils.UuidUtil;
|
||||||
|
import com.roomroot.jwgl.vo.build.BuildDeleteResultVO;
|
||||||
|
import com.roomroot.jwgl.vo.build.BuildImportResultVO;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
import org.apache.poi.ss.usermodel.*;
|
import org.apache.poi.ss.usermodel.*;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
@@ -20,7 +27,12 @@ import jakarta.servlet.http.HttpServletResponse;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 教学楼表服务实现类
|
* 教学楼表服务实现类
|
||||||
@@ -31,6 +43,9 @@ public class BuildServiceImpl implements BuildService {
|
|||||||
@Resource
|
@Resource
|
||||||
private BuildMapper buildMapper;
|
private BuildMapper buildMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ClassRoomMapper classRoomMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(JXLB jxlb) {
|
public void add(JXLB jxlb) {
|
||||||
String uuid = UuidUtil.getUUID();
|
String uuid = UuidUtil.getUUID();
|
||||||
@@ -49,10 +64,80 @@ public class BuildServiceImpl implements BuildService {
|
|||||||
@Override
|
@Override
|
||||||
public void delete(String id) {
|
public void delete(String id) {
|
||||||
JXLB jxlb = getById(id);
|
JXLB jxlb = getById(id);
|
||||||
|
if (jxlb == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assertNotBound(jxlb);
|
||||||
jxlb.setDelFlag(1);
|
jxlb.setDelFlag(1);
|
||||||
buildMapper.updateById(jxlb);
|
buildMapper.updateById(jxlb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public BuildDeleteResultVO batchDelete(List<String> ids) {
|
||||||
|
BuildDeleteResultVO result = new BuildDeleteResultVO();
|
||||||
|
if (ids == null || ids.isEmpty()) {
|
||||||
|
result.setMessage("未选择要删除的教学楼");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<JXLB> builds = buildMapper.selectBatchIds(ids);
|
||||||
|
|
||||||
|
// 一次性查出这些教学楼代号下未删除的教学场地,按代号分组计数
|
||||||
|
Set<String> codeSet = builds.stream()
|
||||||
|
.map(JXLB::getJxldh)
|
||||||
|
.filter(StringUtils::isNotEmpty)
|
||||||
|
.map(String::trim)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
Map<String, Long> boundCountMap = codeSet.isEmpty()
|
||||||
|
? new HashMap<>()
|
||||||
|
: classRoomMapper.selectList(new LambdaQueryWrapper<JSB>()
|
||||||
|
.select(JSB::getJxldh)
|
||||||
|
.eq(JSB::getDelFlag, 0)
|
||||||
|
.in(JSB::getJxldh, codeSet))
|
||||||
|
.stream()
|
||||||
|
.filter(jsb -> StringUtils.isNotEmpty(jsb.getJxldh()))
|
||||||
|
.collect(Collectors.groupingBy(jsb -> jsb.getJxldh().trim(), Collectors.counting()));
|
||||||
|
|
||||||
|
for (JXLB jxlb : builds) {
|
||||||
|
// 已删除的不再处理
|
||||||
|
if (jxlb.getDelFlag() != null && jxlb.getDelFlag() == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 已绑定教学场地的教学楼跳过,不允许删除
|
||||||
|
long boundCount = StringUtils.isEmpty(jxlb.getJxldh())
|
||||||
|
? 0
|
||||||
|
: boundCountMap.getOrDefault(jxlb.getJxldh().trim(), 0L);
|
||||||
|
if (boundCount > 0) {
|
||||||
|
result.addSkip("教学楼 " + jxlb.getJxlmc() + "(代号 " + jxlb.getJxldh()
|
||||||
|
+ ")已绑定 " + boundCount + " 间教学场地,未删除");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
jxlb.setDelFlag(1);
|
||||||
|
buildMapper.updateById(jxlb);
|
||||||
|
result.setDeleteCount(result.getDeleteCount() + 1);
|
||||||
|
}
|
||||||
|
result.setMessage(String.format("已删除 %d 条,跳过 %d 条",
|
||||||
|
result.getDeleteCount(), result.getSkipCount()));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验教学楼未绑定教学场地(教室表),已绑定则抛出业务异常
|
||||||
|
*/
|
||||||
|
private void assertNotBound(JXLB jxlb) {
|
||||||
|
if (StringUtils.isEmpty(jxlb.getJxldh())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Long boundCount = classRoomMapper.selectCount(new LambdaQueryWrapper<JSB>()
|
||||||
|
.eq(JSB::getDelFlag, 0)
|
||||||
|
.eq(JSB::getJxldh, jxlb.getJxldh().trim()));
|
||||||
|
if (boundCount != null && boundCount > 0) {
|
||||||
|
throw new BusinessException("教学楼 " + jxlb.getJxlmc() + "(代号 " + jxlb.getJxldh()
|
||||||
|
+ ")已绑定 " + boundCount + " 间教学场地,不允许删除");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(JXLB jxlb) {
|
public void update(JXLB jxlb) {
|
||||||
buildMapper.updateById(jxlb);
|
buildMapper.updateById(jxlb);
|
||||||
@@ -93,13 +178,29 @@ public class BuildServiceImpl implements BuildService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int importExcel(MultipartFile file) {
|
public BuildImportResultVO importExcel(MultipartFile file) {
|
||||||
try (InputStream is = file.getInputStream();
|
try (InputStream is = file.getInputStream();
|
||||||
Workbook workbook = file.getOriginalFilename().endsWith(".xlsx")
|
Workbook workbook = file.getOriginalFilename().endsWith(".xlsx")
|
||||||
? new XSSFWorkbook(is) : new HSSFWorkbook(is)) {
|
? new XSSFWorkbook(is) : new HSSFWorkbook(is)) {
|
||||||
|
|
||||||
Sheet sheet = workbook.getSheetAt(0);
|
// 模板数据写在「教学楼表」sheet,取不到时兜底取第一个 sheet
|
||||||
int count = 0;
|
Sheet sheet = workbook.getSheet("教学楼表");
|
||||||
|
if (sheet == null) {
|
||||||
|
sheet = workbook.getSheetAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildImportResultVO result = new BuildImportResultVO();
|
||||||
|
|
||||||
|
// 库中已有教学楼代号集合,导入命中即跳过(不覆盖已有数据);
|
||||||
|
// 导入中新写入的代号也加入集合,避免同一文件内代号重复
|
||||||
|
Set<String> existingJxldh = new HashSet<>();
|
||||||
|
for (JXLB existing : buildMapper.selectList(new LambdaQueryWrapper<JXLB>()
|
||||||
|
.select(JXLB::getJxldh)
|
||||||
|
.eq(JXLB::getDelFlag, 0))) {
|
||||||
|
if (StringUtils.isNotEmpty(existing.getJxldh())) {
|
||||||
|
existingJxldh.add(existing.getJxldh().trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 在循环外获取起始序号
|
// 在循环外获取起始序号
|
||||||
int nextNum = getNextNumber();
|
int nextNum = getNextNumber();
|
||||||
@@ -109,29 +210,56 @@ public class BuildServiceImpl implements BuildService {
|
|||||||
Row row = sheet.getRow(i);
|
Row row = sheet.getRow(i);
|
||||||
if (row == null) continue;
|
if (row == null) continue;
|
||||||
|
|
||||||
JXLB jxlb = new JXLB();
|
// 教学楼标识号(代号,可含英文字母,原样保留)
|
||||||
|
String jxldh = getCellValue(row, 0);
|
||||||
|
// 序号
|
||||||
|
String xh = getCellValue(row, 1);
|
||||||
|
// 教学楼名称
|
||||||
|
String jxlmc = getCellValue(row, 2);
|
||||||
|
// 地点
|
||||||
|
String dd = getCellValue(row, 3);
|
||||||
|
// 备注
|
||||||
|
String bz = getCellValue(row, 4);
|
||||||
|
|
||||||
// 生成序号(数字字符串)和教学楼代号(三位补零)
|
// 整行空白则跳过
|
||||||
jxlb.setXh(String.valueOf(nextNum));
|
if (StringUtils.isEmpty(jxldh) && StringUtils.isEmpty(xh)
|
||||||
jxlb.setJxldh(String.format("%03d", nextNum));
|
&& StringUtils.isEmpty(jxlmc) && StringUtils.isEmpty(dd)
|
||||||
|
&& StringUtils.isEmpty(bz)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(jxldh)) {
|
||||||
|
// 代号留空时按现有最大序号 +1 自动生成三位补零编号,已占用则继续向后取号
|
||||||
|
jxldh = String.format("%03d", nextNum);
|
||||||
|
while (existingJxldh.contains(jxldh)) {
|
||||||
|
jxldh = String.format("%03d", ++nextNum);
|
||||||
|
}
|
||||||
|
} else if (existingJxldh.contains(jxldh)) {
|
||||||
|
// 填写的代号已存在则跳过该行
|
||||||
|
result.addSkip("第" + (i + 1) + "行:教学楼代号 " + jxldh + " 已存在,已跳过");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JXLB jxlb = new JXLB();
|
||||||
|
// 序号留空时按自增序号生成
|
||||||
|
jxlb.setXh(StringUtils.isEmpty(xh) ? String.valueOf(nextNum) : xh);
|
||||||
|
jxlb.setJxldh(jxldh);
|
||||||
nextNum++; // 递增序号
|
nextNum++; // 递增序号
|
||||||
|
|
||||||
// 教学楼名称
|
jxlb.setJxlmc(jxlmc);
|
||||||
jxlb.setJxlmc(getCellValue(row, 2));
|
jxlb.setDd(dd);
|
||||||
|
jxlb.setBz(bz);
|
||||||
// 地点
|
|
||||||
jxlb.setDd(getCellValue(row, 3));
|
|
||||||
|
|
||||||
// 备注
|
|
||||||
jxlb.setBz(getCellValue(row, 4));
|
|
||||||
|
|
||||||
jxlb.setId(UuidUtil.getUUID());
|
jxlb.setId(UuidUtil.getUUID());
|
||||||
jxlb.setDelFlag(0);
|
jxlb.setDelFlag(0);
|
||||||
|
|
||||||
buildMapper.insert(jxlb);
|
buildMapper.insert(jxlb);
|
||||||
count++;
|
existingJxldh.add(jxldh);
|
||||||
|
result.setInsertCount(result.getInsertCount() + 1);
|
||||||
}
|
}
|
||||||
return count;
|
result.setMessage(String.format("共导入 %d 条,跳过 %d 条",
|
||||||
|
result.getInsertCount(), result.getSkipCount()));
|
||||||
|
return result;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Excel解析失败: " + e.getMessage(), e);
|
throw new RuntimeException("Excel解析失败: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
package com.roomroot.jwgl.vo.build;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 教学楼批量删除结果。
|
||||||
|
* <p>
|
||||||
|
* 用于返回批量删除的执行结果:删除数、跳过数(已绑定教学场地不允许删除)与跳过明细。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BuildDeleteResultVO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实际删除的教学楼数。
|
||||||
|
*/
|
||||||
|
private Integer deleteCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 因"已绑定教学场地"而跳过的条数。
|
||||||
|
*/
|
||||||
|
private Integer skipCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳过明细(教学楼 XXX(代号 XXX)已绑定教学场地,未删除)。
|
||||||
|
*/
|
||||||
|
private List<String> skipList = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结果提示信息。
|
||||||
|
*/
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录一条跳过明细。
|
||||||
|
*
|
||||||
|
* @param detail 明细文本
|
||||||
|
*/
|
||||||
|
public void addSkip(String detail) {
|
||||||
|
this.skipCount++;
|
||||||
|
if (this.skipList.size() < 50) {
|
||||||
|
this.skipList.add(detail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
package com.roomroot.jwgl.vo.build;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 教学楼导入结果。
|
||||||
|
* <p>
|
||||||
|
* 用于返回导入操作的执行结果:新增数、跳过数(教学楼代号已存在)与跳过明细。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BuildImportResultVO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实际新增的教学楼数。
|
||||||
|
*/
|
||||||
|
private Integer insertCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 因"教学楼代号已存在"而跳过的条数(不覆盖库中已有数据)。
|
||||||
|
*/
|
||||||
|
private Integer skipCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳过明细(第 N 行:教学楼代号 XXX 已存在)。
|
||||||
|
*/
|
||||||
|
private List<String> skipList = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结果提示信息。
|
||||||
|
*/
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录一条跳过明细。
|
||||||
|
*
|
||||||
|
* @param detail 明细文本
|
||||||
|
*/
|
||||||
|
public void addSkip(String detail) {
|
||||||
|
this.skipCount++;
|
||||||
|
if (this.skipList.size() < 50) {
|
||||||
|
this.skipList.add(detail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ export function addBuild(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除教学楼(后端仅提供单条删除,参数为 id)
|
* 删除教学楼(参数为 id,已绑定教学场地时后端会拒绝)
|
||||||
* POST /build/delete
|
* POST /build/delete
|
||||||
*/
|
*/
|
||||||
export function deleteBuild(id) {
|
export function deleteBuild(id) {
|
||||||
@@ -28,6 +28,20 @@ export function deleteBuild(id) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除教学楼
|
||||||
|
* POST /build/batchDelete
|
||||||
|
* 已绑定教学场地的教学楼会跳过不删,返回 { deleteCount, skipCount, skipList, message }
|
||||||
|
* @param ids 教学楼ID数组
|
||||||
|
*/
|
||||||
|
export function batchDeleteBuild(ids) {
|
||||||
|
return request({
|
||||||
|
url: '/build/batchDelete',
|
||||||
|
method: 'post',
|
||||||
|
data: ids
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新教学楼
|
* 更新教学楼
|
||||||
* POST /build/update
|
* POST /build/update
|
||||||
|
|||||||
@@ -95,7 +95,7 @@
|
|||||||
<el-button icon="el-icon-download" :loading="importDialog.downloading" @click="handleDownloadTemplate">
|
<el-button icon="el-icon-download" :loading="importDialog.downloading" @click="handleDownloadTemplate">
|
||||||
下载导入模板
|
下载导入模板
|
||||||
</el-button>
|
</el-button>
|
||||||
<span class="tip-text">模板 sheet 为「教学楼表」,只需填写教学楼名称/地点/备注</span>
|
<span class="tip-text">模板 sheet 为「教学楼表」,教学楼标识号留空则自动生成,代号已存在的行将跳过</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="数据文件">
|
<el-form-item label="数据文件">
|
||||||
<div class="file-input">
|
<div class="file-input">
|
||||||
@@ -110,7 +110,12 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="导入结果" v-if="importDialog.result">
|
<el-form-item label="导入结果" v-if="importDialog.result">
|
||||||
<div class="import-result">
|
<div class="import-result">
|
||||||
共导入 <span class="num">{{ importDialog.result }}</span> 条教学楼数据。
|
共导入 <span class="num">{{ importDialog.result.insertCount }}</span> 条教学楼数据<template
|
||||||
|
v-if="importDialog.result.skipCount > 0">,跳过 <span
|
||||||
|
class="num warn">{{ importDialog.result.skipCount }}</span> 条(教学楼代号已存在)</template>。
|
||||||
|
<div v-if="importDialog.result.skipList && importDialog.result.skipList.length" class="skip-detail">
|
||||||
|
<div v-for="(item, idx) in importDialog.result.skipList" :key="idx">{{ item }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -127,7 +132,7 @@
|
|||||||
import { saveAs } from 'file-saver'
|
import { saveAs } from 'file-saver'
|
||||||
import {
|
import {
|
||||||
addBuild,
|
addBuild,
|
||||||
deleteBuild,
|
batchDeleteBuild,
|
||||||
updateBuild,
|
updateBuild,
|
||||||
listBuild,
|
listBuild,
|
||||||
importBuild,
|
importBuild,
|
||||||
@@ -318,7 +323,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
/* ---------- 删除(后端仅提供单条删除,多选时逐条调用) ---------- */
|
/* ---------- 删除(批量删除,已绑定教学场地的由后端跳过) ---------- */
|
||||||
handleBatchDelete() {
|
handleBatchDelete() {
|
||||||
const rows = this.selectedRows || []
|
const rows = this.selectedRows || []
|
||||||
if (rows.length === 0) {
|
if (rows.length === 0) {
|
||||||
@@ -326,7 +331,7 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const names = rows.map(row => row.jxlmc || row.jxldh).join('、')
|
const names = rows.map(row => row.jxlmc || row.jxldh).join('、')
|
||||||
this.$confirm('确定删除选中的 ' + rows.length + ' 条教学楼数据吗?' + '(' + names + ')', '提示', {
|
this.$confirm('确定删除选中的 ' + rows.length + ' 条教学楼数据吗?' + '(' + names + ')已绑定教学场地的教学楼不会被删除。', '提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
@@ -335,13 +340,23 @@ export default {
|
|||||||
|
|
||||||
doBatchDelete(rows) {
|
doBatchDelete(rows) {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
const tasks = rows.map(row => deleteBuild(row.id))
|
batchDeleteBuild(rows.map(row => row.id)).then(response => {
|
||||||
Promise.all(tasks).then(() => {
|
const data = (response && response.data) || {}
|
||||||
this.$message.success('已删除 ' + rows.length + ' 条教学楼数据')
|
const deleteCount = data.deleteCount || 0
|
||||||
|
const skipList = data.skipList || []
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
if (skipList.length > 0) {
|
||||||
|
const detailHtml = skipList.map(item => '<div>' + item + '</div>').join('')
|
||||||
|
this.$alert(
|
||||||
|
'已删除 ' + deleteCount + ' 条,' + skipList.length + ' 条因已绑定教学场地未删除。<br/>' + detailHtml,
|
||||||
|
'删除结果',
|
||||||
|
{ dangerouslyUseHTMLString: true, confirmButtonText: '确定' }
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this.$message.success('已删除 ' + deleteCount + ' 条教学楼数据')
|
||||||
|
}
|
||||||
this.fetchList()
|
this.fetchList()
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.$message.error('部分数据删除失败,请刷新后重试')
|
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.fetchList()
|
this.fetchList()
|
||||||
})
|
})
|
||||||
@@ -406,11 +421,16 @@ export default {
|
|||||||
}
|
}
|
||||||
this.importDialog.importing = true
|
this.importDialog.importing = true
|
||||||
importBuild(this.importDialog.file).then(response => {
|
importBuild(this.importDialog.file).then(response => {
|
||||||
const count = (response && response.data) || 0
|
const data = (response && response.data) || {}
|
||||||
this.clearImportFile()
|
this.clearImportFile()
|
||||||
this.importDialog.importing = false
|
this.importDialog.importing = false
|
||||||
this.importDialog.result = count
|
this.importDialog.result = {
|
||||||
this.$message.success('导入成功,共导入 ' + count + ' 条')
|
insertCount: data.insertCount || 0,
|
||||||
|
skipCount: data.skipCount || 0,
|
||||||
|
skipList: data.skipList || []
|
||||||
|
}
|
||||||
|
const skipTip = data.skipCount > 0 ? ',跳过 ' + data.skipCount + ' 条已存在代号' : ''
|
||||||
|
this.$message.success('导入成功,共导入 ' + (data.insertCount || 0) + ' 条' + skipTip)
|
||||||
this.fetchList()
|
this.fetchList()
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.importDialog.importing = false
|
this.importDialog.importing = false
|
||||||
@@ -492,6 +512,18 @@ export default {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #67c23a;
|
color: #67c23a;
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
|
|
||||||
|
&.warn {
|
||||||
|
color: #e6a23c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-detail {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #909399;
|
||||||
|
max-height: 120px;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user