Merge remote-tracking branch 'origin/ah-simple' into ah-simple

This commit is contained in:
itcast 2025-10-29 18:41:17 +08:00
commit 02928c3ab3
27 changed files with 906 additions and 273 deletions

View File

@ -1,11 +1,19 @@
package com.bonus.material.devchange.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.bonus.common.core.web.controller.BaseController;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.material.contract.domain.BmContract;
import com.bonus.material.devchange.domain.*;
import com.bonus.material.devchange.service.MaDevInfoService;
import com.bonus.material.devchange.service.MaDevInfoServiceImpl;
import com.bonus.material.device.domain.vo.DevInfoPropertyVo;
import com.bonus.material.device.domain.vo.DevMergeVo;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
@ -13,8 +21,17 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* 设备台账-总览表
@ -44,6 +61,7 @@ public class MaDevInfoController extends BaseController {
}
}
@ApiOperation(value = "设备台账-上下架")
@PostMapping("/updateDeviceStatus")
public AjaxResult updateDeviceStatus(@RequestBody DevMergeVo o) {
@ -143,4 +161,218 @@ public class MaDevInfoController extends BaseController {
}
/**
* 导出设备信息为Excel
*
* @param o 查询条件同列表接口
* @param response 响应对象
*/
@ApiOperation("导出设备信息Excel")
@PostMapping("/export")
public void export(MaDevInfo o, HttpServletResponse response) throws IOException {
// 1. 查询所有符合条件的数据忽略分页
List<MaDevInfo> dataList = service.list(o);
// 2. 转换数据为导出格式处理特殊字段
List<Map<String, Object>> exportData = dataList.stream()
.map(this::convertToExportMap)
.collect(Collectors.toList());
// 生成Excel时 headerMap 的顺序添加表头
ExcelWriter writer = ExcelUtil.getWriter();
Map<String, String> headerMap = getExportHeaderMap();
// headerMap 的顺序添加别名LinkedHashMap保证顺序
headerMap.forEach((prop, label) -> writer.addHeaderAlias(prop, label));
// 显式设置导出的字段顺序与表头一致
writer.setOnlyAlias(true); // 只导出有别名的字段
writer.write(exportData, true);
// 5. 设置响应头触发下载
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("设备信息表_" + System.currentTimeMillis(), "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
// 6. 输出流写入
try (ServletOutputStream out = response.getOutputStream()) {
writer.flush(out, true);
} finally {
writer.close();
}
}
/**
* 转换设备信息为导出Map处理特殊字段
*/
private Map<String, Object> convertToExportMap(MaDevInfo item) {
Set<String> headerProps = getExportHeaderMap().keySet();
// 使用 LinkedHashMap 保持顺序
Map<String, Object> map = new LinkedHashMap<>();
// 1. 先添加表头中定义的字段确保顺序与表头一致
for (String prop : headerProps) {
// 从对象中获取字段值忽略不存在的字段
Object value = BeanUtil.getProperty(item, prop);
map.put(prop, value);
}
map.put("process", item.getMainProcess() + ">" + item.getSubProcess());
map.put("devType", item.getMainCategory() + ">" + item.getSubCategory() + ">" + item.getBranch());
Object productionDate = item.getProductionDate();
if (productionDate != null) {
map.put("productionDate", formatDateToYmd(productionDate));
}
// 格式化采购日期purchaseDate只保留年月日
Object purchaseDate = item.getPurchaseDate();
if (purchaseDate != null) {
map.put("purchaseDate", formatDateToYmd(purchaseDate));
}
// 格式化采购日期purchaseDate只保留年月日
Object nextMaintenanceDate = item.getNextMaintenanceDate();
if (purchaseDate != null) {
map.put("nextMaintenanceDate", formatDateToYmd(nextMaintenanceDate));
}
// 格式化采购日期purchaseDate只保留年月日
Object expirationTime = item.getExpirationTime();
if (purchaseDate != null) {
map.put("expirationTime", formatDateToYmd(expirationTime));
}
map.put("status", convertStatusToText(Integer.valueOf(item.getStatus())));
map.put("upDownStatus", convertUpDownStatusToText(Integer.valueOf(item.getUpDownStatus())));
List<DevInfoPropertyVo> propertyVoList = item.getPropertyVoList();
if (CollUtil.isNotEmpty(propertyVoList)) {
for (int i = 0; i < propertyVoList.size() && i < 9; i++) {
DevInfoPropertyVo property = propertyVoList.get(i);
int index = i + 1;
map.put("featureItem" + index, property.getPropertyName());
map.put("featureValue" + index, property.getPropertyValue());
}
}
for (int i = 1; i <= 9; i++) {
map.putIfAbsent("featureItem" + i, "");
map.putIfAbsent("featureValue" + i, "");
}
// 4. 最终过滤确保只保留表头中的字段防止处理过程中新增多余字段
map.keySet().retainAll(headerProps);
return map;
}
/**
* 工具方法将时间对象格式化为 "yyyy-MM-dd"兼容Date和LocalDate
*/
private String formatDateToYmd(Object dateObj) {
if (dateObj == null) {
return "";
}
// 处理java.util.Date类型
if (dateObj instanceof Date) {
return DateUtil.format((Date) dateObj, "yyyy-MM-dd");
}
// 处理java.time.LocalDate类型
if (dateObj instanceof LocalDate) {
return ((LocalDate) dateObj).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
// 处理java.time.LocalDateTime类型截取日期部分
if (dateObj instanceof LocalDateTime) {
return ((LocalDateTime) dateObj).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
// 其他类型直接返回字符串避免转换失败
return dateObj.toString();
}
/**
* 导出表头映射prop -> label- 兼容 Java 8
*/
private Map<String, String> getExportHeaderMap() {
Map<String, String> headerMap = new LinkedHashMap<>();
// 1. 基础字段映射已有部分保持不变
headerMap.put("province", "所属省份");
headerMap.put("propertyUnit", "产权单位");
headerMap.put("major", "专业");
headerMap.put("process", "工序");
headerMap.put("devType", "装备类目");
headerMap.put("name", "类型分支");
headerMap.put("specificationModel", "规格型号");
headerMap.put("code", "装备编码");
headerMap.put("status", "装备状态");
headerMap.put("upDownStatus", "上下架状态");
headerMap.put("serviceLife", "使用年限");
headerMap.put("usingProject", "使用项目");
headerMap.put("expirationTime", "使用到期时间");
headerMap.put("usageCount", "使用次数");
headerMap.put("repairCount", "维修次数");
headerMap.put("originalCode", "装备原始编码");
headerMap.put("unit", "计量单位");
headerMap.put("manufacturer", "生产厂家");
headerMap.put("productionDate", "出厂日期");
headerMap.put("purchaseDate", "采购日期");
headerMap.put("originalValue", "资产原值(元)");
headerMap.put("maxServiceLifeYears", "最大使用年限(年)");
headerMap.put("nextMaintenanceDate", "下次维保日期");
// 2. 补全特征项和特征值的中文映射关键补充
for (int i = 1; i <= 9; i++) {
headerMap.put("featureItem" + i, "特征项" + i); // 如featureItem1"特征项1"
headerMap.put("featureValue" + i, "特征值" + i); // 如featureValue1"特征值1"
}
return headerMap;
}
/**
* 装备状态枚举转文本根据实际枚举实现
*/
/**
* 装备状态枚举转文本兼容 Java 8
*/
private String convertStatusToText(Integer status) {
if (status == null) {
return "";
}
// 传统 switch 语句Java 8 支持
String statusText;
switch (status) {
case 1:
statusText = "在库";
break;
case 2:
statusText = "自用";
break;
case 3:
statusText = "共享";
break;
case 4:
statusText = "退役";
break;
case 5:
statusText = "维修";
break;
default:
statusText = "未知";
break;
}
return statusText;
}
/**
* 上下架状态枚举转文本根据实际枚举实现
*/
private String convertUpDownStatusToText(Integer upDownStatus) {
if (upDownStatus == null) return "";
// 示例实际项目中替换为枚举映射
return upDownStatus == 1 ? "上架" : "下架";
}
}

View File

@ -338,4 +338,6 @@ public class MaDevInfo {
private String upDownStatus;
private String remainingStopYear;
}

View File

@ -73,7 +73,7 @@ public class DevChangeServiceImpl implements DevChangeService {
@Override
public AjaxResult updateDevChangeInfo(CsDeviceChangeVo vo) {
try {
String username = SecurityUtils.getLoginUser().getUsername();
String username = SecurityUtils.getLoginUser().getSysUser().getNickName();
vo.setCreateUser(username);
String proCode = vo.getProCode();
if (StringUtils.isBlank(proCode)) {
@ -149,7 +149,7 @@ public class DevChangeServiceImpl implements DevChangeService {
@Override
public AjaxResult updateDevChangeInfo3(CsDeviceChangeVo vo) {
try {
String username = SecurityUtils.getLoginUser().getUsername();
String username = SecurityUtils.getLoginUser().getSysUser().getNickName();
vo.setCreateUser(username);
if (StringUtils.isBlank(vo.getType())) {
return AjaxResult.error("请上传类型type:1入库 2出库 3 退役 4 维修");
@ -206,7 +206,8 @@ public class DevChangeServiceImpl implements DevChangeService {
@Override
public AjaxResult updateDevChangeInfo2(CsDeviceChangeVo vo) {
try {
String username = SecurityUtils.getLoginUser().getUsername();
String username = SecurityUtils.getLoginUser().getSysUser().getNickName();
vo.setCreateUser(username);
if (StringUtils.isBlank(vo.getType())) {
return AjaxResult.error("请上传类型type:1入库 2出库 3 退役 4 维修");
@ -271,7 +272,7 @@ public class DevChangeServiceImpl implements DevChangeService {
@Override
public AjaxResult addChangeInfo(CsDeviceChangeVo vo) {
try {
String username = SecurityUtils.getLoginUser().getUsername();
String username = SecurityUtils.getLoginUser().getSysUser().getNickName();
vo.setCreateUser(username);
String proCode = vo.getProCode();
if (StringUtils.isBlank(proCode)) {

View File

@ -246,8 +246,9 @@ public class DevMergeServiceImpl implements DevMergeService {
maDevQc.setQcCom(Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId()).orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId()).toString());
maDevQc.setNextCheckTime(maDevInfo.getNextMaintenanceDate());
qcMapper.insertDevQc(maDevQc);
devInfoMapper.insertDevInfoProperties(Long.valueOf(maDevInfo.getMaId()), maDevInfo.getPropertyVoList());
if (!CollectionUtils.isEmpty(maDevInfo.getPropertyVoList())) {
devInfoMapper.insertDevInfoProperties(Long.valueOf(maDevInfo.getMaId()), maDevInfo.getPropertyVoList());
}
devMergeMapper.insertOrderDevReal(String.valueOf(maDevInfo.getOrderId()), Long.valueOf(maDevInfo.getMaId()));
maDevInfo.getAppearanceImages().forEach(item -> {
// 这里编写对每个 image 的处理逻辑比如打印处理等
@ -364,7 +365,9 @@ public class DevMergeServiceImpl implements DevMergeService {
if (i > 0) {
devInfoMapper.deleteDevInfoProperties(Long.valueOf(maDevInfo.getMaId()));
devMergeMapper.delFile(maDevInfo.getMaId());
devInfoMapper.insertDevInfoProperties(Long.valueOf(maDevInfo.getMaId()), maDevInfo.getPropertyVoList());
if (!CollectionUtils.isEmpty(maDevInfo.getPropertyVoList())) {
devInfoMapper.insertDevInfoProperties(Long.valueOf(maDevInfo.getMaId()), maDevInfo.getPropertyVoList());
}
MaDevQc maDevQc = new MaDevQc();
maDevQc.setMaId(maDevInfo.getMaId());
maDevQc.setQcCode(maDevInfo.getCode());

View File

@ -2,14 +2,14 @@ package com.bonus.material.largeScreen.controller;
import com.bonus.common.core.web.controller.BaseController;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.core.web.page.TableDataInfo;
import com.bonus.material.device.domain.DevInfo;
import com.bonus.material.device.domain.vo.DevInfoVo;
import com.bonus.material.largeScreen.service.ProvinceScreenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.ArrayList;
@ -32,13 +32,14 @@ public class ProvinceScreenController extends BaseController {
/**
* 装备总量总价值
*
* @return
*/
@ApiOperation("装备总量,总价值")
@GetMapping("/getTotalEquipment")
public AjaxResult getTotalEquipment() {
try {
Map<String,Object> res = provinceScreenService.getTotalEquipment();
Map<String, Object> res = provinceScreenService.getTotalEquipment();
return AjaxResult.success(res);
} catch (Exception e) {
return AjaxResult.error("装备总量,总价值异常");
@ -46,14 +47,15 @@ public class ProvinceScreenController extends BaseController {
}
/**
*线路装备变电装备电缆装备
* 线路装备变电装备电缆装备
*
* @return
*/
@ApiOperation("线路装备,变电装备,电缆装备")
@GetMapping("/getEquipmentClassification")
public AjaxResult getEquipmentClassification() {
try {
Map<String,Object> res = provinceScreenService.getEquipmentClassification();
Map<String, Object> res = provinceScreenService.getEquipmentClassification();
return AjaxResult.success(res);
} catch (Exception e) {
log.error("错误", e);
@ -64,13 +66,14 @@ public class ProvinceScreenController extends BaseController {
/**
* 单位装备配置
*
* @return
*/
@ApiOperation("单位装备配置")
@GetMapping("/getUnitEquipmentConfiguration")
public AjaxResult getUnitEquipmentConfiguration() {
try {
List<Map<String,Object>> res = provinceScreenService.getUnitEquipmentConfiguration();
List<Map<String, Object>> res = provinceScreenService.getUnitEquipmentConfiguration();
if (res == null) {
logger.warn("单位装备配置数据为空");
return AjaxResult.success(new ArrayList<>());
@ -85,13 +88,14 @@ public class ProvinceScreenController extends BaseController {
/**
* 装备状态
*
* @return
*/
@ApiOperation("装备状态")
@GetMapping("/getEquipmentStatus")
public AjaxResult getEquipmentStatus() {
try {
List<Map<String,Object>> res = provinceScreenService.getEquipmentStatus();
List<Map<String, Object>> res = provinceScreenService.getEquipmentStatus();
return AjaxResult.success(res);
} catch (Exception e) {
return AjaxResult.error("装备状态异常");
@ -100,13 +104,14 @@ public class ProvinceScreenController extends BaseController {
/**
* 项目装备
*
* @return
*/
@ApiOperation("项目装备")
@GetMapping("/getProjectEquipment")
public AjaxResult getProjectEquipment() {
try {
Map<String,Object> res = provinceScreenService.getProjectEquipment();
Map<String, Object> res = provinceScreenService.getProjectEquipment();
return AjaxResult.success(res);
} catch (Exception e) {
return AjaxResult.error("项目装备异常");
@ -115,13 +120,14 @@ public class ProvinceScreenController extends BaseController {
/**
* 各单位装备在用率情况
*
* @return
*/
@ApiOperation("各单位装备在用率情况")
@GetMapping("/getDeptEquipment")
public AjaxResult getDeptEquipment() {
try {
List<Map<String,Object>> res = provinceScreenService.getDeptEquipment();
List<Map<String, Object>> res = provinceScreenService.getDeptEquipment();
return AjaxResult.success(res);
} catch (Exception e) {
return AjaxResult.error("项目装备异常");
@ -130,44 +136,14 @@ public class ProvinceScreenController extends BaseController {
/**
* 工程在用装备情况
*
* @return
*/
@ApiOperation("工程在用装备情况")
@GetMapping("/getEquipmentUse")
public AjaxResult getEquipmentUse() {
public AjaxResult getEquipmentUse(String proCode, String type) {
try {
List<Map<String,Object>> res = provinceScreenService.getEquipmentUse();
Map<String,Object> map = new HashMap<>();
map.put("projectName","石桥-大陇π入万济变、大陇-阳湖T接万济变 35kV架空线路工程");
map.put("inUser","82");
map.put("scale","172");
map.put("usage","47.67");
res.add(map);
map = new HashMap<>();
map.put("projectName","淮南泥河110kV变电站新建工程");
map.put("inUser","66");
map.put("scale","170");
map.put("usage","48.67");
res.add(map);
map = new HashMap<>();
map.put("projectName","安徽黄山市徽州区呈坎35kV变电站新建工程");
map.put("inUser","68");
map.put("scale","160");
map.put("usage","49.67");
res.add(map);
map = new HashMap<>();
map.put("projectName","凌云220kV变电站新建工程");
map.put("inUser","65");
map.put("scale","175");
map.put("usage","45.67");
res.add(map);
map = new HashMap<>();
map.put("projectName","东坡110kV变电站新建工程");
map.put("inUser","68");
map.put("scale","174");
map.put("usage","49.67");
res.add(map);
return AjaxResult.success(res);
return provinceScreenService.getEquipmentUse(proCode, type);
} catch (Exception e) {
return AjaxResult.error("工程在用装备情况异常");
}
@ -175,13 +151,14 @@ public class ProvinceScreenController extends BaseController {
/**
* 装备在用率统计
*
* @return
*/
@ApiOperation("装备在用率统计")
@GetMapping("/getUsageStatistics")
public AjaxResult getUsageStatistics(Integer type) {
try {
List<Map<String,Object>> res = provinceScreenService.getUsageStatistics(type);
List<Map<String, Object>> res = provinceScreenService.getUsageStatistics(type);
return AjaxResult.success(res);
} catch (Exception e) {
return AjaxResult.error("装备在用率统计异常");
@ -190,28 +167,46 @@ public class ProvinceScreenController extends BaseController {
/**
* 在库装备数
*
* @return
*/
@ApiOperation("在库装备数")
@GetMapping("/getEquipmentNumber")
public AjaxResult getEquipmentNumber() {
try {
List<Map<String,Object>> res = provinceScreenService.getEquipmentNumber();
List<Map<String, Object>> res = provinceScreenService.getEquipmentNumber();
return AjaxResult.success(res);
} catch (Exception e) {
return AjaxResult.error("在库装备数异常");
}
}
@ApiOperation(value = "收藏装备列表")
@GetMapping("/getUsageStatisticsDetails")
public TableDataInfo getUsageStatisticsDetails() {
startPage();
List<Map<String, Object>> usageStatisticsDetails = provinceScreenService.getUsageStatisticsDetails();
return getDataTable(usageStatisticsDetails);
}
@ApiOperation(value = "收藏装备列表")
@GetMapping("/getEquipmentDetails")
public TableDataInfo getEquipmentDetails(String proName) {
startPage();
List<Map<String, Object>> usageStatisticsDetails = provinceScreenService.getEquipmentDetails(proName);
return getDataTable(usageStatisticsDetails);
}
/**
* 机械化率
*
* @return
*/
@ApiOperation("机械化率")
@GetMapping("/getMechanizationRate")
public AjaxResult getMechanizationRate() {
try {
List<Map<String,Object>> res = provinceScreenService.getMechanizationRate();
List<Map<String, Object>> res = provinceScreenService.getMechanizationRate();
return AjaxResult.success(res);
} catch (Exception e) {
return AjaxResult.error("在库装备数异常");

View File

@ -1,5 +1,7 @@
package com.bonus.material.largeScreen.service;
import com.bonus.common.core.web.domain.AjaxResult;
import java.util.List;
import java.util.Map;
@ -7,57 +9,71 @@ public interface ProvinceScreenService {
/**
* 装备总量总价值
*
* @return
*/
Map<String, Object> getTotalEquipment();
/**
*线路装备变电装备电缆装备
* 线路装备变电装备电缆装备
*
* @return
*/
Map<String, Object> getEquipmentClassification();
/**
* 单位装备配置
*
* @return
*/
List<Map<String,Object>> getUnitEquipmentConfiguration();
List<Map<String, Object>> getUnitEquipmentConfiguration();
/**
* 装备状态
*
* @return
*/
List<Map<String,Object>> getEquipmentStatus();
List<Map<String, Object>> getEquipmentStatus();
/**
* 项目装备
*
* @return
*/
Map<String, Object> getProjectEquipment();
/**
* 各单位装备在用率情况
*
* @return
*/
List<Map<String, Object>> getDeptEquipment();
/**
* 工程在用装备情况
*
* @return
*/
List<Map<String, Object>> getEquipmentUse();
AjaxResult getEquipmentUse(String proCode, String proType);
List<Map<String, Object>> getEquipmentDetails(String proName);
/**
* 装备在用率统计
*
* @return
*/
List<Map<String, Object>> getUsageStatistics(Integer type);
/**
* 在库装备数
*
* @return
*/
List<Map<String, Object>> getEquipmentNumber();
List<Map<String, Object>> getMechanizationRate();
List<Map<String, Object>> getUsageStatisticsDetails();
}

View File

@ -1,6 +1,7 @@
package com.bonus.material.largeScreen.service.impl;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.material.basic.domain.SysDeptVO;
import com.bonus.material.device.mapper.DevInfoMapper;
import com.bonus.material.equipment.domain.DeptConfigRateSummary;
@ -149,6 +150,8 @@ public class ProvinceScreenServiceImpl implements ProvinceScreenService {
*/
@Override
public List<Map<String, Object>> getUnitEquipmentConfiguration() {
devInfoMapper.getUnitEquipmentConfiguration();
if (sysDeptMapper == null) {
log.error("sysDeptMapper is null");
return new ArrayList<>();
@ -175,6 +178,7 @@ public class ProvinceScreenServiceImpl implements ProvinceScreenService {
Map<String, Object> dept = new HashMap<>();
dept.put("deptName", sysDeptNew.getDeptName() != null ? sysDeptNew.getDeptName() : "未知部门");
dept.put("deptAbbreviation", sysDeptNew.getDeptAbbreviation() != null ? sysDeptNew.getDeptAbbreviation() : "未知部门");
devInfoReq.setOwnCo(Math.toIntExact(sysDeptNew.getDeptId()));
// 部门定位
@ -192,7 +196,6 @@ public class ProvinceScreenServiceImpl implements ProvinceScreenService {
devInfoReq.setTypeId(1);
int lineNum = devInfoMapper.getLineNum(devInfoReq);
dept.put("lineNum", lineNum);
// 变电
devInfoReq.setTypeId(2);
int substationNum = devInfoMapper.getLineNum(devInfoReq);
@ -214,10 +217,7 @@ public class ProvinceScreenServiceImpl implements ProvinceScreenService {
if (list != null) {
for (DeptConfigRateSummary deptConfigRateSummary : list) {
if (deptConfigRateSummary != null &&
deptConfigRateSummary.getDeptId() != null &&
deptConfigRateSummary.getDeptId().equals(sysDeptNew.getDeptId())) {
if (deptConfigRateSummary != null) {
// 总数
dept.put("configRate", deptConfigRateSummary.getConfigRate() != null ?
deptConfigRateSummary.getConfigRate() : 0.0);
@ -326,46 +326,7 @@ public class ProvinceScreenServiceImpl implements ProvinceScreenService {
*/
@Override
public List<Map<String, Object>> getDeptEquipment() {
List<Map<String, Object>> res = new ArrayList<>();
SysDept sysDept = new SysDept();
List<SysDeptVO> sysDeptList = sysDeptMapper.selectDeptVOList(sysDept);
for (SysDeptVO sysDeptNew : sysDeptList) {
Map<String, Object> dept = new HashMap<>();
DevInfoReq devInfoReq = new DevInfoReq();
devInfoReq.setOwnCo(Math.toIntExact(sysDeptNew.getDeptId()));
//装备总数
Integer sum = devInfoMapper.getTotalEquipment(devInfoReq);
//自用2
devInfoReq.setChangeStatus("2");
Integer inUse = devInfoMapper.getTotalEquipment(devInfoReq);
devInfoReq.setChangeStatus("3");
Integer share = devInfoMapper.getTotalEquipment(devInfoReq);
inUse = inUse + share;
dept.put("name", sysDeptNew.getDeptName());
//在用率
dept.put("proportion", sum > 0 ? (inUse * 100) / sum : 0);
//周转率
int turnoverRate = devInfoMapper.getTurnoverRate();
dept.put("turnoverRate", sum > 0 ? (turnoverRate * 100) / sum : 0);
dept.put("inUse", inUse);
res.add(dept);
}
// 核心排序逻辑按proportion数值降序排序高在用率优先
// res.sort((map1, map2) -> {
// // 1. 提取两个map中的proportion字符串
// String proportion1 = (String) map1.get("proportion");
// String proportion2 = (String) map2.get("proportion");
// // 2. 处理null值默认视为0%
// proportion1 = proportion1 == null ? "0%" : proportion1;
// proportion2 = proportion2 == null ? "0%" : proportion2;
// // 3. 去掉"%"符号转为Integer数值核心步骤
// // 注意若proportion含小数"83.5%"需转为Double此处按整数处理适配原代码逻辑
// int propValue1 = Integer.parseInt(proportion1.replace("%", ""));
// int propValue2 = Integer.parseInt(proportion2.replace("%", ""));
// // 4. 数值降序排序高在用率在前升序用propValue1 - propValue2
// return propValue2 - propValue1;
// });
return res;
return maTypeMapper.getDeptEquipment();
}
/**
@ -374,9 +335,22 @@ public class ProvinceScreenServiceImpl implements ProvinceScreenService {
* @return
*/
@Override
public List<Map<String, Object>> getEquipmentUse() {
List<Map<String, Object>> res = new ArrayList<>();
return res;
public AjaxResult getEquipmentUse(String proCode, String proType) {
Map<String, Object> res = new HashMap<>();
Integer proNum = maTypeMapper.getProNum(proType);
Integer equipmentNum = maTypeMapper.getEquipmentNum(proType);
res.put("proNum", proNum);
res.put("equipmentNum", equipmentNum);
res.put("equipmentUse", maTypeMapper.getEquipmentUse(proCode, proType));
return AjaxResult.success(res);
}
/**
* @return
*/
@Override
public List<Map<String, Object>> getEquipmentDetails(String proName) {
return maTypeMapper.getEquipmentDetails(proName);
}
/**
@ -387,7 +361,7 @@ public class ProvinceScreenServiceImpl implements ProvinceScreenService {
@Override
public List<Map<String, Object>> getUsageStatistics(Integer type) {
List<Map<String, Object>> res = new ArrayList<>();
/* List<Map<String, Object>> res = new ArrayList<>();
List<MaType> maTypeList = new ArrayList<>();
//获取装备在用率 查询全部
if (StringUtils.isNull(type)) {
@ -431,8 +405,8 @@ public class ProvinceScreenServiceImpl implements ProvinceScreenService {
int propValue2 = Integer.parseInt(proportion2.replace("%", ""));
// 4. 数值降序排序高在用率在前升序用propValue1 - propValue2
return propValue2 - propValue1;
});
return res.subList(0, 10);
});*/
return maTypeMapper.getUsageStatistics(type);
}
/**
@ -455,6 +429,7 @@ public class ProvinceScreenServiceImpl implements ProvinceScreenService {
devInfoReq.setChangeStatus("1");
Integer inStock = devInfoMapper.getTotalEquipment(devInfoReq);
dept.put("location", sysDeptNew.getLocation());
dept.put("deptAbbreviation", sysDeptNew.getDeptAbbreviation() != null ? sysDeptNew.getDeptAbbreviation() : "未知部门");
dept.put("name", sysDeptNew.getDeptName());
dept.put("num", inStock);
res.add(dept);
@ -467,6 +442,14 @@ public class ProvinceScreenServiceImpl implements ProvinceScreenService {
return null;
}
/**
* @return
*/
@Override
public List<Map<String, Object>> getUsageStatisticsDetails() {
return maTypeMapper.getUsageStatisticsDetails();
}
/**
* 统计数量
*/

View File

@ -7,6 +7,7 @@ import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
* 工机具类型管理 数据层
@ -100,4 +101,20 @@ public interface MaTypeMapper {
List<MaType> selectMaTypeTreeBy5Level(Integer type);
List<MaType> selectMaTypeTreeBy5Level2(Integer type);
List<Map<String, Object>> getUsageStatistics(Integer type);
List<Map<String, Object>> getUsageStatisticsDetails();
List<Map<String, Object>> getEquipmentUse(@Param("proCode") String proCode, @Param("proType") String proType);
List<Map<String, Object>> getEquipmentDetails(String proName);
Integer getProNum(@Param("proType") String proType);
Integer getEquipmentNum(@Param("proType") String proType);
List<Map<String, Object>> getDeptEquipment();
}

View File

@ -11,9 +11,7 @@ public interface MaSupplierMapper {
MaSupplier selectById(@Param("supplierId") Long supplierId);
List<MaSupplier> list(@Param("supplierCode") String supplierCode,
@Param("supplierName") String supplierName,
@Param("status") Integer status);
List<MaSupplier> list(MaSupplier query);
int insert(MaSupplier supplier);

View File

@ -21,7 +21,7 @@ public class MaSupplierServiceImpl implements MaSupplierService {
@Override
public List<MaSupplier> list(MaSupplier query) {
return maSupplierMapper.list(query.getSupplierCode(), query.getSupplierName(), query.getStatus());
return maSupplierMapper.list(query);
}
@Override

View File

@ -0,0 +1,57 @@
package com.bonus.material.task;
import com.bonus.material.task.domain.UseRate;
import com.bonus.material.task.mapper.UseRateMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@Slf4j
@Component
public class UseRateTask {
@Resource
private UseRateMapper mapper;
/**
* 每晚11点执行统计并保存设备当日使用情况
* 优化点异常处理日志记录事务控制空集合判断
*/
@Scheduled(cron = "0 0 23 * * ?")
//@Scheduled(cron = "0/10 * * * * ?") // 每10秒执行
@Transactional(rollbackFor = Exception.class) // 确保数据一致性异常时回滚
public void collectDailyDeviceUsage() {
log.info("【设备每日使用统计】任务开始执行");
long startTime = System.currentTimeMillis();
try {
// 1. 查询待统计的设备数据
List<UseRate> useRates = mapper.selectUseRate();
log.info("【设备每日使用统计】查询到待处理设备数量:{}", useRates.size());
// 2. 空集合判断避免无效插入
if (useRates.isEmpty()) {
log.warn("【设备每日使用统计】未查询到设备数据,无需执行插入");
return;
}
// 3. 批量插入优先使用批量插入效率更高
int insertCount = mapper.insertUseRate(useRates); // 改用之前定义的批量插入方法
log.info("【设备每日使用统计】批量插入完成,成功插入 {} 条记录", insertCount);
} catch (Exception e) {
// 4. 异常捕获与日志记录避免任务中断
log.error("【设备每日使用统计】任务执行失败", e); // 打印完整堆栈便于排查
throw e; // 若有事务抛出异常触发回滚
} finally {
// 5. 记录任务耗时
long costTime = System.currentTimeMillis() - startTime;
log.info("【设备每日使用统计】任务执行结束,耗时:{}ms", costTime);
}
}
}

View File

@ -0,0 +1,19 @@
package com.bonus.material.task.domain;
import lombok.Data;
@Data
public class UseRate {
/**
* 设备id
*/
private Integer maId;
/**
* 设备状态
*/
private Integer status;
/**
* 设备类型
*/
private Integer typeId;
}

View File

@ -0,0 +1,24 @@
package com.bonus.material.task.mapper;
import com.bonus.material.task.domain.UseRate;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UseRateMapper {
/**
* 插入每个设备的每天的在用状态
*
* @param useRate 数据
* @return 条数
*/
Integer insertUseRate(List<UseRate> useRate);
/**
* 查询设备信息
*
* @return 设备信息
*/
List<UseRate> selectUseRate();
}

View File

@ -26,7 +26,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ifnull(sum(mdi.buy_price * mdi.device_count),0) as totalValue,
COUNT(1) as deviceQuantity
from ma_dev_info mdi
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
where mdi.is_active = 1 and mtv.MaxTypeId = #{typeId} and mdi.on_company = #{companyId}
<if test="year == 1">
and TIMESTAMPDIFF(YEAR,mdi.production_date, NOW()) <![CDATA[ < ]]> 5
@ -53,7 +53,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
mdi.change_status as status,
mtv.maxTypeId as typeId
from ma_dev_info mdi
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
where mdi.is_active = 1 and mdi.on_company = #{companyId}
<if test="typeId != null">
and mtv.MaxTypeId = #{typeId}
@ -80,7 +80,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
when TIMESTAMPDIFF(DAY, NOW(),mdq.next_check_time) <![CDATA[ < ]]> 0 then '已超期'
else '未检' end as situation
from ma_dev_info mdi
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
left join ma_dev_qc mdq on mdq.ma_id = mdi.ma_id
where mdi.is_active = 1 and mdi.on_company = #{companyId} and mdi.change_status != 4
order by TIMESTAMPDIFF(YEAR, NOW(),mdq.next_check_time)
@ -89,7 +89,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select
count(DISTINCT mdi.ma_id)
from ma_dev_info mdi
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
left join ma_dev_qc mdq on mdq.ma_id = mdi.ma_id
where mdi.is_active = 1 and mdi.on_company = #{companyId} and mdi.change_status != 4
</select>
@ -99,7 +99,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
mtv.devCategory as procedureName,
concat('差',TIMESTAMPDIFF(DAY, NOW(),mdi.expiration_time),'天退役') as situation
from ma_dev_info mdi
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
where mdi.is_active = 1 and mdi.on_company = #{companyId} and mdi.change_status != 4
order by TIMESTAMPDIFF(YEAR, NOW(),mdi.expiration_time)
</select>
@ -108,7 +108,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select
count(DISTINCT mdi.ma_id)
from ma_dev_info mdi
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
where mdi.is_active = 1 and mdi.on_company = #{companyId} and mdi.change_status != 4
</select>
@ -116,7 +116,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select
count(1)
from ma_dev_info mdi
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
where mdi.is_active = 1 and mdi.on_company = #{companyId} and mdi.change_status != 3
</select>
@ -128,7 +128,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
mdi.device_name as deviceName,
CONCAT(ROUND(count(cdcd.dev_id)/mdi.device_count, 2),'次/年') as turnoverRate
from ma_dev_info mdi
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
left join cs_device_change_details cdcd on cdcd.dev_id = mdi.ma_id
left join cs_device_change cdc on cdc.id = cdcd.change_id
where mdi.is_active = 1 and mdi.on_company = #{companyId} and mdi.change_status != 4 and cdc.type = 2 and cdc.del_flag = 0
@ -144,7 +144,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
sum(mdi.buy_price * mdi.device_count) as investAmount
from jj_sing_project jsp
left join ma_dev_info mdi on mdi.on_project = jsp.id
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
where mdi.is_active = 1 and mdi.on_company = #{companyId} and mdi.change_status in (2,3)
<if test="voltageLevel != null">
and jsp.voltage = #{voltageLevel}
@ -161,7 +161,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select DISTINCT count(1)
from jj_sing_project jsp
left join ma_dev_info mdi on mdi.on_project = jsp.id
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
where mdi.is_active = 1
and mdi.on_company = #{companyId}
and mdi.change_status in (2, 3)
@ -182,7 +182,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select DISTINCT ifnull(sum(mdi.device_count),0) as num
from jj_sing_project jsp
left join ma_dev_info mdi on mdi.on_project = jsp.id
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
where mdi.is_active = 1
and mdi.on_company = #{companyId}
and mdi.change_status in (2, 3)
@ -206,7 +206,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
sum(mdi.device_count) as useNum
from jj_sing_project jsp
left join ma_dev_info mdi on mdi.on_project = jsp.id
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
<!-- left join coordinate_point cp on cp.name = jsp.county-->
where mdi.is_active = 1
<!-- and mdi.change_status in (2,3)-->
@ -221,7 +221,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ifnull(sum(mdi.device_count),0) as useNum
from jj_sing_project jsp
left join ma_dev_info mdi on mdi.on_project = jsp.id
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
where mdi.is_active = 1
and mdi.change_status in (1,5)
and jsp.city = #{city}
@ -233,7 +233,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
from (select DISTINCT ifnull(sum(mdi.device_count), 0) as useNum
from jj_sing_project jsp
left join ma_dev_info mdi on mdi.on_project = jsp.id
left join ma_type_view mtv on mtv.typeId = mdi.type_id
INNER join ma_type_view mtv on mtv.typeId = mdi.type_id
where mdi.is_active = 1
and (mdi.change_status in (2, 3) or mdi.change_status is null)
and jsp.city != #{city}) r

View File

@ -30,7 +30,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="list" resultType="com.bonus.material.contract.domain.BmContract">
select id, content, contract_code as contractCode, contract_name as contractName, status, create_time as createTime, update_time as updateTime, owner_id as ownerId, owner_com as ownerCom from bm_contract
<where>
owner_com = #{ownerCom}
<if test="contractCode != null and contractCode != ''">
and contract_code like concat('%', #{contractCode}, '%')
</if>

View File

@ -70,7 +70,7 @@
dev.on_project proId,dev.change_status AS status
FROM ma_dev_info dev
left join bm_company_info bci on bci.company_id=dev.on_company
left join ma_type_view mt on mt.typeId=dev.type_id
INNER join ma_type_view mt on mt.typeId=dev.type_id
LEFT JOIN (SELECT max( next_check_time) next_check_time,ma_id from ma_dev_qc GROUP BY ma_id ) mdq on
dev.ma_id=mdq.ma_id
left join jj_sing_project pro on pro.pro_code=dev.on_project
@ -203,7 +203,7 @@
FROM cs_device_change_details dcd
left join ma_dev_info dev on dcd.dev_id = dev.ma_id
left join bm_company_info bci on bci.company_id = dev.on_company
left join ma_type_view mt on mt.typeId = dev.type_id
INNER join ma_type_view mt on mt.typeId = dev.type_id
LEFT JOIN
(SELECT max(next_check_time) next_check_time, ma_id
from ma_dev_qc

View File

@ -254,22 +254,7 @@
count(distinct if(mdi.change_status = '5', mdi.ma_id, null)) as underRepair
FROM
ma_dev_info mdi
LEFT JOIN ma_dev_qc mdq ON mdq.ma_id = mdi.ma_id
LEFT JOIN sys_dept sd ON sd.dept_id = mdi.on_company
LEFT JOIN bm_company_info c ON sd.dept_id = c.company_id
LEFT JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
WHERE mdi.is_active = 1
<if test="typeId != null">
and (
mtv.mainGxId = #{typeId}
or mtv.childGxId = #{typeId}
or mtv.devCategoryId = #{typeId}
or mtv.devSubcategoryId = #{typeId}
or mtv.devNameId = #{typeId}
or mtv.devModelId = #{typeId}
or mtv.maxTypeId = #{typeId}
)
</if>
</select>
<select id="getProperties" resultType="com.bonus.material.device.domain.vo.DevInfoPropertyVo">
@ -350,7 +335,7 @@
AND `status` IN ( 2, 3 )) AS usageCount,
sc.name AS province
from ma_dev_info mdi
LEFT JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
LEFT JOIN jj_sing_project jsp ON mdi.on_project = jsp.pro_code
LEFT JOIN sys_dept sd ON sd.dept_id = mdi.on_company
LEFT JOIN (SELECT max( next_check_time) next_check_time,ma_id from ma_dev_qc GROUP BY ma_id ) mdq on
@ -365,8 +350,6 @@
or mtv.childGxId = #{typeId}
or mtv.devCategoryId = #{typeId}
or mtv.devSubcategoryId = #{typeId}
or mtv.devNameId = #{typeId}
or mtv.devModelId = #{typeId}
or mtv.maxTypeId = #{typeId}
)
</if>
@ -479,7 +462,7 @@
mdq.next_check_time AS nextMaintenanceDate,
mdi.max_working_hours AS maxServiceLifeYears
from ma_dev_info mdi
LEFT JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
LEFT JOIN jj_sing_project jsp ON mdi.on_project = jsp.pro_code
LEFT JOIN sys_dept sd ON sd.dept_id = mdi.on_company
LEFT JOIN (SELECT max( next_check_time) next_check_time,ma_id from ma_dev_qc GROUP BY ma_id ) mdq on

View File

@ -56,10 +56,10 @@
) a
<where>
<if test="actualStartYear != null and actualStartYear != ''">
and years_diff between #{actualStartYear} and #{actualStopYear}
and yearsDiff between #{actualStartYear} and #{actualStopYear}
</if>
<if test="remainingStartYear != null and remainingStartYear != ''">
and remaining_years between #{remainingStartYear} and #{remainingStopYear}
and remainingYears between #{remainingStartYear} and #{remainingStopYear}
</if>
<if test="isWarn != null and isWarn != ''">
<if test="isWarn == 1">

View File

@ -78,7 +78,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ma_dev_info d
LEFT JOIN sys_dept sd ON d.on_company = sd.dept_id
LEFT JOIN bm_company_info c ON sd.dept_id = c.company_id
LEFT JOIN ma_type_view mtv ON mtv.typeId = d.type_id
INNER JOIN ma_type_view mtv ON mtv.typeId = d.type_id
LEFT JOIN bm_file_info bfi on d.ma_id = bfi.model_id and bfi.file_type = '0' and bfi.task_type = '17'
LEFT JOIN ma_dev_file mdf on d.ma_id = mdf.ma_id and mdf.file_type = '1' and mdf.is_active = '1'
<where>
@ -229,7 +229,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
LEFT JOIN sys_dept sd ON d.on_company = sd.dept_id
LEFT JOIN bm_company_info c ON sd.dept_id = c.company_id
LEFT JOIN ma_hot_search h ON d.ma_id = h.ma_id
LEFT JOIN ma_type_view mtv ON mtv.typeId = d.type_id
INNER JOIN ma_type_view mtv ON mtv.typeId = d.type_id
LEFT JOIN ma_type mt4 ON mt4.type_id = d.type_id and mt4.del_flag = '0'
LEFT JOIN ma_type mt3 ON mt3.type_id = mt4.parent_id and mt3.del_flag = '0'
LEFT JOIN ma_type mt2 ON mt2.type_id = mt3.parent_id and mt2.del_flag = '0'
@ -1369,50 +1369,30 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="getLineNum" resultType="java.lang.Integer">
select count(1)
from ma_dev_info mdi
left join ma_type mt on mdi.type_id = mt.type_id
left join ma_type mt1 on mt.parent_id = mt1.type_id
left join ma_type mt2 on mt1.parent_id = mt2.type_id
left join ma_type mt3 on mt2.parent_id = mt3.type_id
left join ma_type mt4 on mt3.parent_id = mt4.type_id
left join ma_type mt5 on mt4.parent_id = mt5.type_id
left join ma_type mt6 on mt5.parent_id = mt6.type_id
where mt6.type_id = #{typeId} and mdi.is_active ='1'
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
where mtv.maxTypeId = #{typeId}
and mdi.is_active = '1'
</select>
<select id="getLinePrice" resultType="java.math.BigDecimal">
select sum(mdi.buy_price)
from ma_dev_info mdi
left join ma_type mt on mdi.type_id = mt.type_id
left join ma_type mt1 on mt.parent_id = mt1.type_id
left join ma_type mt2 on mt1.parent_id = mt2.type_id
left join ma_type mt3 on mt2.parent_id = mt3.type_id
left join ma_type mt4 on mt3.parent_id = mt4.type_id
left join ma_type mt5 on mt4.parent_id = mt5.type_id
left join ma_type mt6 on mt5.parent_id = mt6.type_id
where mt6.type_id = #{typeId} and mdi.is_active ='1'
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
where mtv.maxTypeId = #{typeId}
and mdi.is_active = '1'
</select>
<select id="getLineProductionDateList" resultType="java.lang.String">
select production_date
from ma_dev_info mdi
left join ma_type mt on mdi.type_id = mt.type_id
left join ma_type mt1 on mt.parent_id = mt1.type_id
left join ma_type mt2 on mt1.parent_id = mt2.type_id
left join ma_type mt3 on mt2.parent_id = mt3.type_id
left join ma_type mt4 on mt3.parent_id = mt4.type_id
left join ma_type mt5 on mt4.parent_id = mt5.type_id
left join ma_type mt6 on mt5.parent_id = mt6.type_id
where mt6.type_id = #{typeId} and mdi.is_active ='1'
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
where mtv.maxTypeId = #{typeId}
and mdi.is_active = '1'
</select>
<select id="getUnitEquipmentConfiguration" resultType="com.bonus.material.equipment.domain.SysDept">
select production_date
from ma_dev_info mdi
left join ma_type mt on mdi.type_id = mt.type_id
left join ma_type mt1 on mt.parent_id = mt1.type_id
left join ma_type mt2 on mt1.parent_id = mt2.type_id
left join ma_type mt3 on mt2.parent_id = mt3.type_id
left join ma_type mt4 on mt3.parent_id = mt4.type_id
left join ma_type mt5 on mt4.parent_id = mt5.type_id
left join ma_type mt6 on mt5.parent_id = mt6.type_id
where mt6.type_id = #{id} and mdi.is_active ='1'
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
where mtv.maxTypeId = #{typeId}
and mdi.is_active = '1'
</select>
<select id="getPrice" resultType="java.math.BigDecimal">
select SUM(buy_price) from ma_dev_info where is_active ='1' and on_company = #{deptId}
@ -1456,7 +1436,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ma_dev_info d
LEFT JOIN sys_dept sd ON d.on_company = sd.dept_id
LEFT JOIN bm_company_info c ON sd.dept_id = c.company_id
LEFT JOIN ma_type_view mtv ON mtv.typeId = d.type_id
INNER JOIN ma_type_view mtv ON mtv.typeId = d.type_id
<where>
<if test="maId != null "> and d.ma_id = #{maId}</if>
<if test="code != null and code != ''"> and d.code = #{code}</if>
@ -1527,10 +1507,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="getTotalEquipmentByLevel" resultType="java.lang.Integer">
select count(1)
from ma_dev_info mdi
left join ma_type mt on mdi.type_id = mt.type_id
left join ma_type mt1 on mt.parent_id = mt1.type_id
left join ma_type mt2 on mt1.parent_id = mt2.type_id
where mt2.type_id = #{typeId} and mdi.is_active ='1'
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
where mtv.typeId = #{typeId} and mdi.is_active ='1'
<if test="changeStatus != null ">
AND change_status = #{changeStatus}
</if>
@ -1539,13 +1517,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select count(1) from cs_device_change_details cdcd
left join cs_device_change cdc on cdcd.change_id = cdc.id
left join ma_dev_info mdi on mdi.ma_id = cdcd.dev_id
left join ma_type mt on mdi.type_id = mt.type_id
left join ma_type mt1 on mt.parent_id = mt1.type_id
left join ma_type mt2 on mt1.parent_id = mt2.type_id
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
where cdcd.del_flag = '0'
AND cdc.create_time >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
AND cdc.create_time >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
<if test="typeId != null ">
AND mt2.type_id = #{typeId}
AND mtv.typeId = #{typeId}
</if>
</select>
</mapper>

View File

@ -68,7 +68,7 @@
LEFT JOIN cs_device_status cds ON cdrd.cs_id = cds.id
LEFT JOIN sys_dept sd ON d.on_company = sd.dept_id
LEFT JOIN bm_company_info c ON sd.dept_id = c.company_id
LEFT JOIN ma_type_view mtv ON mtv.typeId = d.type_id
INNER JOIN ma_type_view mtv ON mtv.typeId = d.type_id
<where>
<if test="orderId != null and orderId != ''">
and cdrd.cs_id = #{orderId}
@ -248,7 +248,7 @@
type_name AS label,
parent_id AS parentId
FROM ma_type
WHERE parent_id IS NULL
WHERE parent_id = '0'
AND del_flag = '0'; -- 排除已删除的数据
</select>
<select id="findSecondAndThirdLevelTypes" resultType="java.util.Map">
@ -262,7 +262,7 @@
JOIN ma_type t2 ON t1.type_id = t2.parent_id
OR t1.type_id = (SELECT parent_id FROM ma_type WHERE type_id = t2.parent_id)
WHERE t1.type_id = #{firstLevelId} -- 一级类型ID
AND t1.parent_id IS NULL -- 确保t1是一级类型
AND t1.parent_id = '0' -- 确保t1是一级类型
AND t2.del_flag = '0'
</select>
@ -325,7 +325,7 @@
AND t5.del_flag = '0' -- 五级
) AS all_levels ON t.type_id = all_levels.type_id
WHERE t1.type_id = #{firstLevelId}
AND t1.parent_id IS NULL -- 确保是一级类型
AND t1.parent_id = '0' -- 确保是一级类型
AND t.del_flag = '0'
</select>
<select id="selectTodayOrderCount" resultType="java.lang.Integer">
@ -379,7 +379,7 @@
from cs_device_status cds
LEFT JOIN cs_device_real_dev cdrd ON cdrd.cs_id = cds.id
LEFT JOIN ma_dev_info mdi ON cdrd.dev_id = mdi.ma_id
LEFT JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
LEFT JOIN jj_sing_project jsp ON mdi.on_project = jsp.pro_code
LEFT JOIN sys_dept sd ON sd.dept_id = mdi.on_company
LEFT JOIN (SELECT max( next_check_time) next_check_time,ma_id from ma_dev_qc GROUP BY ma_id ) mdq on
@ -413,7 +413,9 @@
<if test="propertyUnitId != null and propertyUnitId != ''">
and sd.dept_id = #{propertyUnitId}
</if>
<if test="entryStatus != null and entryStatus != ''">
and mdi.entry_status = #{entryStatus}
</if>
<if test="manufacturerId != null and manufacturerId != ''">
and mdi.brand = #{manufacturerId}
</if>
@ -478,7 +480,7 @@
from cs_device_status cds
LEFT JOIN cs_device_real_dev cdrd ON cdrd.cs_id = cds.id
LEFT JOIN ma_dev_info mdi ON cdrd.dev_id = mdi.ma_id
LEFT JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
LEFT JOIN jj_sing_project jsp ON mdi.on_project = jsp.pro_code
LEFT JOIN sys_dept sd ON sd.dept_id = mdi.on_company
LEFT JOIN (SELECT max( next_check_time) next_check_time,ma_id from ma_dev_qc GROUP BY ma_id ) mdq on

View File

@ -8,9 +8,9 @@
d.dept_name,
d.order_num,
d.leader,
d.dept_abbreviation,
d.dept_type,
d.location,
d.dept_abbreviation,
d.dept_type,
d.location,
d.phone,
d.status,
d.del_flag,

View File

@ -785,7 +785,7 @@
END) AS fiveOrTen
FROM
ma_dev_info mdi
LEFT JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
WHERE
-- 过滤目标proType只处理需要的三类
mtv.proType IN ('变电施工类', '架空输电线路工程', '电缆(海缆)工程')
@ -827,7 +827,7 @@
ELSE 0
END) AS fiveOrTen
FROM ma_dev_info mdi
LEFT JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
WHERE mdi.change_status != '4'
and mdi.is_active = '1'
and
@ -841,7 +841,7 @@
sum(mdi.buy_price) AS price,
mtv.devSubcategory AS name
FROM ma_dev_info mdi
LEFT JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id and mdi.change_status != '4' and mdi.is_active ='1'
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id and mdi.change_status != '4' and mdi.is_active ='1'
WHERE
-- 过滤目标proType只处理需要的三类
mtv.maxTypeId IN (#{type})
@ -850,6 +850,7 @@
ORDER BY
price DESC
Limit 10
</select>
<select id="statByTypeAndAgeByCity" resultType="java.util.Map">
SELECT sd.dept_name AS name,
@ -871,7 +872,7 @@
AND mdi.change_status != '4'
AND mdi.is_active = '1'
-- 左连接类型表不在这里加maxTypeId条件避免过滤主表
LEFT JOIN ma_type_view mtv
INNER JOIN ma_type_view mtv
ON mtv.typeId = mdi.type_id
GROUP BY sd.dept_id, sd.dept_name -- 按部门分组,确保所有部门都被列出
ORDER BY count DESC
@ -885,15 +886,15 @@
ELSE 0
END) AS count,
SUM(CASE
WHEN mtv.maxTypeId = 5080 THEN 1 -- 仅当类型符合时计数
WHEN mtv.maxTypeId = 1 THEN 1 -- 仅当类型符合时计数
ELSE 0
END) AS cableCount,
SUM(CASE
WHEN mtv.maxTypeId = 5010 THEN 1 -- 仅当类型符合时计数
WHEN mtv.maxTypeId = 3 THEN 1 -- 仅当类型符合时计数
ELSE 0
END) AS substationCount,
SUM(CASE
WHEN mtv.maxTypeId = 5474 THEN 1 -- 仅当类型符合时计数
WHEN mtv.maxTypeId = 2 THEN 1 -- 仅当类型符合时计数
ELSE 0
END) AS lineCount
FROM sys_dept sd
@ -903,7 +904,7 @@
AND mdi.change_status != '4'
AND mdi.is_active = '1'
-- 左连接类型表不在这里加maxTypeId条件避免过滤主表
LEFT JOIN ma_type_view mtv
INNER JOIN ma_type_view mtv
ON mtv.typeId = mdi.type_id
GROUP BY sd.dept_id, sd.dept_name -- 按部门分组,确保所有部门都被列出
ORDER BY count DESC
@ -911,67 +912,70 @@
<select id="statByTypeAndAgeByTurnoverRate" resultType="java.util.Map">
SELECT DATE_FORMAT(cdcd.use_time, '%Y/%m') AS month,-- 月份
-- 统计不同类型设备的有效使用次数status为2/3
SUM(CASE WHEN mtv.maxTypeId = 5080 AND cdcd.`status` IN (2, 3) THEN 1 ELSE 0 END) AS cableCount,
SUM(CASE WHEN mtv.maxTypeId = 5010 AND cdcd.`status` IN (2, 3) THEN 1 ELSE 0 END) AS substationCount,
SUM(CASE WHEN mtv.maxTypeId = 5474 AND cdcd.`status` IN (2, 3) THEN 1 ELSE 0 END) AS lineCount
SUM(CASE WHEN mtv.maxTypeId = 1 AND cdcd.`status` IN (2, 3) THEN 1 ELSE 0 END) AS cableCount,
SUM(CASE WHEN mtv.maxTypeId = 3 AND cdcd.`status` IN (2, 3) THEN 1 ELSE 0 END) AS substationCount,
SUM(CASE WHEN mtv.maxTypeId = 2 AND cdcd.`status` IN (2, 3) THEN 1 ELSE 0 END) AS lineCount
FROM cs_device_change_details cdcd -- 左连接设备表(过滤有效设备)
LEFT JOIN ma_dev_info mdi ON cdcd.dev_id = mdi.ma_id -- 关联设备ID
AND mdi.change_status != '4'
AND mdi.is_active = '1' -- 左连接类型表(获取设备类型)
LEFT JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id -- 过滤无效的使用时间可选避免NULL的月份
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id -- 过滤无效的使用时间可选避免NULL的月份
WHERE cdcd.use_time IS NOT NULL
AND mdi.ma_id IS NOT NULL -- 按「设备ID+月份」分组(核心修正)
GROUP BY DATE_FORMAT(cdcd.use_time, '%Y/%m') -- 按月份和设备ID排序结果更清晰
ORDER BY month;
</select>
<select id="statByTypeAndAgeByUsageRate" resultType="java.util.Map">
SELECT DATE_FORMAT(cdcd.use_time, '%Y/%m') AS month,
-- 计算各类型的使用比例(有效使用次数 / 该类型总设备数)
SUM(CASE WHEN mtv.maxTypeId = 5080 AND cdcd.`status` IN (2, 3) THEN 1 ELSE 0 END)
/ total.cable_total AS cableCount,
SUM(CASE WHEN mtv.maxTypeId = 5010 AND cdcd.`status` IN (2, 3) THEN 1 ELSE 0 END)
/ total.substation_total AS substationCount,
SUM(CASE WHEN mtv.maxTypeId = 5474 AND cdcd.`status` IN (2, 3) THEN 1 ELSE 0 END)
/ total.line_total AS lineCount
FROM cs_device_change_details cdcd
-- 左连接设备表(过滤有效设备)
LEFT JOIN ma_dev_info mdi
ON cdcd.dev_id = mdi.ma_id
AND mdi.change_status != '4'
AND mdi.is_active = '1'
-- 左连接类型表(获取设备类型)
LEFT JOIN ma_type_view mtv
ON mtv.typeId = mdi.type_id
-- 一次性计算所有类型的总设备数(复用结果)
CROSS JOIN (SELECT
-- 计算5080类型的总设备数
COUNT(DISTINCT CASE WHEN mtv.maxTypeId = 5080 THEN mdi.ma_id END) AS cable_total,
-- 计算5010类型的总设备数
COUNT(DISTINCT CASE WHEN mtv.maxTypeId = 5010 THEN mdi.ma_id END) AS substation_total,
-- 计算5474类型的总设备数
COUNT(DISTINCT CASE WHEN mtv.maxTypeId = 5474 THEN mdi.ma_id END) AS line_total
FROM ma_dev_info mdi
-- 这里用INNER JOIN更合适因为需要mtv.maxTypeId匹配
INNER JOIN ma_type_view mtv
ON mtv.typeId = mdi.type_id
WHERE mdi.change_status != '4'
AND mdi.is_active = '1') total
-- 过滤条件(确保使用时间有效,且设备存在)
WHERE cdcd.use_time IS NOT NULL
AND mdi.ma_id IS NOT NULL
-- 按月份分组
GROUP BY DATE_FORMAT(cdcd.use_time, '%Y/%m'),
total.cable_total, -- 子查询结果是常量,分组时带上不影响结果,避免某些数据库报错
total.substation_total,
total.line_total,
cdcd.dev_id
ORDER BY month;
-- 统计每月各类型设备的平均在用率(优化性能版)
SELECT DATE_FORMAT(stat_date, '%Y-%m') AS month,
COUNT(stat_date) AS validDays,
ROUND(AVG(cable_total), 2) AS cableCount, -- 明确字段含义5080类型月均在用率
ROUND(AVG(substation_total), 2) AS substationCount, -- 5010类型月均在用率
ROUND(AVG(line_total), 2) AS lineCount -- 5474类型月均在用率
FROM (
-- 子查询:按日计算各类型在用率(简化逻辑+减少重复计算)
SELECT dt.stat_date,
-- 计算5080类型当日在用率复用总设备数变量
ROUND(
IF(dt.total_devs = 0, 0, dt.cable_use / dt.total_devs * 100),
2
) AS cable_total,
-- 计算5010类型当日在用率
ROUND(
IF(dt.total_devs = 0, 0, dt.substation_use / dt.total_devs * 100),
2
) AS substation_total,
-- 计算5474类型当日在用率
ROUND(
IF(dt.total_devs = 0, 0, dt.line_use / dt.total_devs * 100),
2
) AS line_total
FROM (
-- 子查询2预计算每日总设备数和各类型在用设备数减少函数调用
SELECT DATE(mddu.create_time) AS stat_date,
COUNT(DISTINCT mddu.ma_id) AS total_devs, -- 当日总设备数(去重)
-- 5080类型当日在用设备数status=1且类型=5080
COUNT(DISTINCT CASE
WHEN mddu.status = 1 AND mtv.maxTypeId = 1
THEN mddu.ma_id END) AS cable_use,
-- 5010类型当日在用设备数
COUNT(DISTINCT CASE
WHEN mddu.status = 1 AND mtv.maxTypeId = 3
THEN mddu.ma_id END) AS substation_use,
-- 5474类型当日在用设备数
COUNT(DISTINCT CASE
WHEN mddu.status = 1 AND mtv.maxTypeId = 2
THEN mddu.ma_id END) AS line_use
FROM ma_dev_daily_use mddu
-- 关联类型表时过滤目标类型,减少关联数据量(核心优化)
INNER JOIN ma_type_view mtv
ON mtv.typeId = mddu.type_id
AND mtv.maxTypeId IN (1, 3, 2) -- 只关联需要的类型
GROUP BY DATE(mddu.create_time)) AS dt -- dt = daily_total每日统计基础数据
) AS daily_stats
GROUP BY DATE_FORMAT(stat_date, '%Y-%m')
ORDER BY month DESC; -- 按月份倒序,便于查看最新数据
</select>
</mapper>

View File

@ -69,7 +69,8 @@
from ma_type
</sql>
<insert id="insertType" parameterType="com.bonus.material.ma.vo.MaType" useGeneratedKeys="true" keyProperty="typeId">
<insert id="insertType" parameterType="com.bonus.material.ma.vo.MaType" useGeneratedKeys="true"
keyProperty="typeId">
insert into ma_type
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="typeName != null and typeName != ''">type_name,</if>
@ -211,7 +212,7 @@
</delete>
<select id="selectMaTypeList" parameterType="String" resultMap="MaTypeResult">
select DISTINCT m.type_id, m.type_name, m.parent_id, m.storage_num, m.unit_name, m.manage_type,
select DISTINCT m.type_id, m.type_name, m.parent_id, m.storage_num, m.unit_name, m.manage_type,
m.lease_price,m.eff_time, m.rent_price, m.buy_price, m.pay_price, m.level, m.rated_load, m.test_load,
m.holding_time, m.warn_num, mtf.file_name photoName, mtf.file_url photoUrl,
mtf2.file_name documentName, mtf2.file_url documentUrl, mtk.user_id keeperUserId,
@ -413,7 +414,7 @@
</select>
<select id="getMaTypeSelect" resultType="com.bonus.material.ma.vo.MaType">
select m.type_id, m.type_name, m.parent_id, m.storage_num, m.manage_type,
select m.type_id, m.type_name, m.parent_id, m.storage_num, m.manage_type,
m.lease_price,m.eff_time, m.rent_price, m.buy_price, m.pay_price, m.level, m.rated_load, m.test_load,
m.holding_time, m.warn_num, m.del_flag, m.create_by, m.create_time,
m.remark, m.company_id, m.maintenance_alarm_day
@ -424,7 +425,7 @@
</select>
<select id="getListByParentId" resultMap="MaTypeResult">
select DISTINCT m.type_id, m.type_name, m.parent_id, m.storage_num, m.unit_name, m.manage_type,
select DISTINCT m.type_id, m.type_name, m.parent_id, m.storage_num, m.unit_name, m.manage_type,
m.lease_price,m.rent_price, m.eff_time, m.buy_price, m.pay_price, m.level, m.rated_load, m.test_load,
m.holding_time, m.warn_num, mtf.file_name photoName, mtf.file_url photoUrl,
mtf2.file_name documentName, mtf2.file_url documentUrl, mtk.user_id keeperUserId,
@ -598,18 +599,298 @@
</if>
</select>
<select id="selectMaTypeTreeBy5Level" resultType="com.bonus.material.ma.vo.MaType">
select type_id, type_name from ma_type where del_flag = '0' and level = '5'
select type_id, type_name
from ma_type
where del_flag = '0'
and level = '5'
</select>
<select id="selectMaTypeTreeBy5Level2" resultType="com.bonus.material.ma.vo.MaType">
select
mtv.typeId, mtv.devSubcategory as typeName
mtv.typeId, mtv.devSubcategory as typeName
from
ma_type_view mtv
ma_type_view mtv
<if test="type != null and type != 0">
where mtv.maxTypeId = #{type}
</if>
</select>
<select id="getUsageStatistics" resultType="java.util.Map">
-- 按装备小类统计:小类在用率 + 近12个月每月出库次数无记录时显示0
SELECT
-- 装备小类ID兼容两边的小类标识避免NULL
COALESCE(ur.device_id, oc.device_id) AS name,
-- 小类整体在用率保留2位小数
ur.use_rate_percent AS proportion,
-- 近12个月每月出库次数无记录时默认0
IFNULL(oc.monthly_outbound_count, 0) AS turnoverRate
FROM (
-- 子查询1按小类统计在用率
SELECT
mtv.devSubcategory AS device_id, -- 装备小类如“电缆小类A”
-- 计算小类的整体在用率:小类内所有设备的在用天数 / 总记录天数
ROUND(
IF(
-- 小类总记录天数(去重所有设备的记录日期)
COUNT(DISTINCT DATE(mddu.create_time), mdi.ma_id) = 0, -- 精确到“设备+日期”去重
0,
-- 小类内所有设备的在用天数(状态=1的“设备+日期”去重计数)
COUNT(DISTINCT CASE WHEN mddu.status = 1 THEN CONCAT(mdi.ma_id, DATE(mddu.create_time)) END)
/ COUNT(DISTINCT CONCAT(mdi.ma_id, DATE(mddu.create_time))) * 100
),
2
) AS use_rate_percent
FROM ma_dev_info mdi
-- 关联每日使用记录,获取设备状态
LEFT JOIN ma_dev_daily_use mddu ON mddu.ma_id = mdi.ma_id
-- 关联类型视图获取小类devSubcategory和大类maxTypeId=5080
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
WHERE
mdi.is_active = '1'
AND mdi.change_status != '4'
AND mdi.entry_status = '1'
<if test="type != null and type != 0">
AND mtv.maxTypeId = #{type}
</if>
GROUP BY mtv.devSubcategory -- 按小类分组
) AS ur -- ur = use_rate小类在用率
-- 关联小类的出库记录统计
LEFT JOIN (
-- 子查询2按小类统计近12个月每月出库次数
SELECT
mtv.devSubcategory AS device_id, -- 装备小类
DATE_FORMAT(cdcd.use_time, '%Y-%m') AS stat_year_month, -- 统计年月
COUNT(*) AS monthly_outbound_count -- 当月出库次数(小类内所有设备)
FROM cs_device_change_details cdcd
-- 关联设备信息表,筛选有效设备
LEFT JOIN ma_dev_info mdi ON mdi.ma_id = cdcd.dev_id
-- 关联类型视图,限定小类和大类
INNER JOIN ma_type_view mtv ON mtv.typeId = mdi.type_id
WHERE
cdcd.`use_time` is not null -- 出库状态
AND mdi.is_active = '1'
AND cdcd.use_time >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH) -- 近12个月
<if test="type != null and type != 0">
AND mtv.maxTypeId = #{type}
</if>
GROUP BY mtv.devSubcategory, DATE_FORMAT(cdcd.use_time, '%Y-%m') -- 按小类+年月分组
) AS oc -- oc = outbound_count小类出库次数
ON ur.device_id = oc.device_id -- 按小类关联
-- 排序:先小类,再年月倒序(最新月份在前)
ORDER BY
proportion DESC
LIMIT 5
</select>
<select id="getUsageStatisticsDetails" resultType="java.util.Map">
-- 合并查询:设备在用率 + 近12个月每月出库次数无出库记录时显示0
SELECT
-- 设备ID兼容两边的设备ID
COALESCE(ur.device_id, oc.device_id) AS deviceId,
-- 设备在用率无数据时可能为0由子查询已处理
ur.name AS name,
ur.use_rate_percent AS proportion,
-- 近12个月每月出库次数无记录时默认0
IFNULL(oc.monthly_outbound_count, 0) AS turnoverRate
FROM (
-- 子查询1计算设备在用率
SELECT mdi.ma_id AS device_id,
mdi.device_name AS name,
ROUND(
IF(
COUNT(DISTINCT DATE(mddu.create_time)) = 0,
0,
COUNT(DISTINCT CASE WHEN mddu.status = 1 THEN DATE(mddu.create_time) END)
/ COUNT(DISTINCT DATE(mddu.create_time)) * 100
),
2
) AS use_rate_percent
FROM ma_dev_info mdi
LEFT JOIN ma_dev_daily_use mddu ON mddu.ma_id = mdi.ma_id
WHERE mdi.is_active = '1'
AND mdi.change_status != '4'
AND mdi.entry_status = '1'
GROUP BY mdi.ma_id) AS ur
-- 关联出库记录子查询
LEFT JOIN (
-- 子查询2计算近12个月每月出库次数
SELECT cdcd.dev_id AS device_id,
mdi.device_name AS name,
DATE_FORMAT(cdcd.use_time, '%Y-%m') AS stat_year_month,
COUNT(*) AS monthly_outbound_count
FROM cs_device_change_details cdcd
LEFT JOIN ma_dev_info mdi ON mdi.ma_id = cdcd.dev_id
WHERE cdcd.`use_time` is not null -- 出库状态
AND mdi.is_active = '1'
AND mdi.change_status != '4'
AND mdi.entry_status = '1'
AND cdcd.use_time >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
GROUP BY cdcd.dev_id, DATE_FORMAT(cdcd.use_time, '%Y-%m')) AS oc ON ur.device_id = oc.device_id
ORDER BY proportion DESC
</select>
<select id="getEquipmentUse" resultType="java.util.Map">
SELECT
-- 工程基础信息
jsp.pro_code AS proCode,
jsp.pro_name AS projectName,
-- 该工程的装备数量(有效设备)
COUNT(DISTINCT mdi.ma_id) AS inUser,
-- 生成60-100的随机规模值保留0位小数整数
FLOOR(RAND() * (100 - 60 + 1) + 60) AS scale,
-- 计算:装备数/规模×100保留2位小数避免除数为0
ROUND(
IF(
COUNT(DISTINCT mdi.ma_id) = 0, -- 若装备数为0结果为0
0,
COUNT(DISTINCT mdi.ma_id) / FLOOR(RAND() * (100 - 60 + 1) + 60) * 100
),
2
) AS `usage`
FROM jj_sing_project jsp
-- 左连接设备表关联“工程编码”jsp.pro_code和“设备所属工程”mdi.on_project
LEFT JOIN ma_dev_info mdi
ON mdi.on_project = jsp.pro_code
-- 可选:筛选“有效设备”(排除未激活/已报废的设备,根据业务补充)
AND mdi.is_active = '1' -- 假设is_active=1代表设备有效
AND mdi.change_status IN (2, 3)
AND mdi.entry_status = '1'
<where>
<if test="proCode != null and proCode != ''">
AND jsp.pro_code = #{proCode}
</if>
<if test="proType!= null and proType != ''">
AND jsp.project_type = #{proType}
</if>
</where>
-- 按工程分组,统计每个工程的设备数量
GROUP BY jsp.pro_code, jsp.pro_name -- 按工程编码+名称分组(确保工程唯一)
-- 可选:排序(按设备数量倒序,查看设备最多的工程)
ORDER BY inUser DESC
</select>
<select id="getProNum" resultType="java.lang.Integer">
SELECT
COUNT(1)
FROM jj_sing_project jsp
<where>
<if test="proType!= null and proType != ''">
AND jsp.project_type = #{proType}
</if>
</where>
</select>
<select id="getEquipmentNum" resultType="java.lang.Integer">
SELECT
COUNT(DISTINCT mdi.ma_id) AS equipmentNum
FROM jj_sing_project jsp
-- 左连接设备表关联“工程编码”jsp.pro_code和“设备所属工程”mdi.on_project
LEFT JOIN ma_dev_info mdi
ON mdi.on_project = jsp.pro_code
-- 可选:筛选“有效设备”(排除未激活/已报废的设备,根据业务补充)
AND mdi.is_active = '1' -- 假设is_active=1代表设备有效
AND mdi.change_status IN (2, 3)
AND mdi.entry_status = '1'
<where>
<if test="proType!= null and proType != ''">
AND jsp.project_type = #{proType}
</if>
</where>
</select>
<select id="getEquipmentDetails" resultType="java.util.Map">
SELECT
-- 工程基础信息
jsp.pro_code AS proCode,
jsp.pro_name AS proName,
jsp.voltage AS voltage,
jsp.project_type_name AS projectTypeName,
-- 该工程的装备数量(有效设备)
COUNT(DISTINCT mdi.ma_id) AS inUser,
-- 生成60-100的随机规模值保留0位小数整数
FLOOR(RAND() * (100 - 60 + 1) + 60) AS scale,
-- 计算:装备数/规模×100保留2位小数避免除数为0
ROUND(
IF(
COUNT(DISTINCT mdi.ma_id) = 0, -- 若装备数为0结果为0
0,
COUNT(DISTINCT mdi.ma_id) / FLOOR(RAND() * (100 - 60 + 1) + 60) * 100
),
2
) AS `usage`
FROM jj_sing_project jsp
-- 左连接设备表关联“工程编码”jsp.pro_code和“设备所属工程”mdi.on_project
LEFT JOIN ma_dev_info mdi
ON mdi.on_project = jsp.pro_code
-- 可选:筛选“有效设备”(排除未激活/已报废的设备,根据业务补充)
AND mdi.is_active = '1' -- 假设is_active=1代表设备有效
AND mdi.change_status IN (2, 3)
AND mdi.entry_status = '1'
<where>
<if test="proName != null and proName != ''">
AND jsp.pro_name like concat('%', #{proName}, '%')
</if>
</where>
-- 按工程分组,统计每个工程的设备数量
GROUP BY jsp.pro_code, jsp.pro_name -- 按工程编码+名称分组(确保工程唯一)
-- 可选:排序(按设备数量倒序,查看设备最多的工程)
ORDER BY inUser DESC
</select>
<select id="getDeptEquipment">
-- 按单位统计:设备在用率 + 近12个月每月出库次数含无数据单位MySQL 5 兼容版)
SELECT
-- 单位唯一标识取自sys_dept全量单位确保无数据单位也显示
sd_all.dept_id AS deptId,
-- 单位名称sys_dept表中字段为dept_name
sd_all.dept_name AS name,
-- 单位设备在用率无数据时显示0
IFNULL(ur.use_rate_percent, 0) AS proportion,
-- 近12个月每月出库次数无记录时显示0
IFNULL(oc.monthly_outbound_count, 0) AS turnoverRate
FROM
-- 核心先获取sys_dept表中所有单位确保无数据单位不丢失
sys_dept sd_all
-- 左连接“在用率统计结果”全量单位关联在用率数据无数据则为NULL
LEFT JOIN (
-- 子查询1按单位统计设备在用率MySQL 5 多字段去重兼容)
SELECT sd.dept_id,
ROUND(
IF(
-- 用CONCAT解决MySQL 5 不支持多字段DISTINCT的问题
COUNT(DISTINCT CONCAT(mdi.ma_id, '_', DATE(mddu.create_time))) = 0,
0,
-- 单位内在用天数 ÷ 单位总记录天数 × 100%
COUNT(DISTINCT CASE
WHEN mddu.`status` = 1
THEN CONCAT(mdi.ma_id, '_', DATE(mddu.create_time)) END)
/ COUNT(DISTINCT CONCAT(mdi.ma_id, '_', DATE(mddu.create_time))) * 100
),
2
) AS use_rate_percent
FROM ma_dev_info mdi
LEFT JOIN ma_dev_daily_use mddu ON mddu.ma_id = mdi.ma_id
LEFT JOIN sys_dept sd ON sd.dept_id = mdi.on_company
WHERE mdi.is_active = '1'
AND mdi.change_status != '4'
AND mdi.entry_status = '1'
GROUP BY sd.dept_id) AS ur ON sd_all.dept_id = ur.dept_id
-- 左连接“出库次数统计结果”全量单位关联出库数据无数据则为NULL
LEFT JOIN (
-- 子查询2按单位统计近12个月每月出库次数
SELECT sd.dept_id,
DATE_FORMAT(cdcd.use_time, '%Y-%m') AS stat_year_month,
COUNT(*) AS monthly_outbound_count
FROM cs_device_change_details cdcd
INNER JOIN ma_dev_info mdi
ON mdi.ma_id = cdcd.dev_id
AND mdi.is_active = '1'
LEFT JOIN sys_dept sd ON sd.dept_id = mdi.on_company
WHERE cdcd.`status` = 2 -- 出库状态(按实际业务调整)
AND cdcd.use_time IS NOT NULL
AND cdcd.use_time >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
GROUP BY sd.dept_id, DATE_FORMAT(cdcd.use_time, '%Y-%m')) AS oc ON sd_all.dept_id = oc.dept_id
-- 可选按单位ID排序确保结果顺序稳定
ORDER BY proportion DESC
</select>
<delete id="deleteMaTypePropertyNames">
delete

View File

@ -148,10 +148,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
mdi.on_company as sellerCompany,
up.dept_name AS czcompanyName,
mdi.person AS person,
mdi.person_phone AS personPhone,
sd.phone AS personPhone,
su.phonenumber AS phoneNumber,
su.nick_name as buyerName,
su2.nick_name as sellerName,
sd.dept_name as sellerName,
moi.address,
moi.order_id,
dept.dept_name as companyName
@ -159,6 +159,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ma_order_details hh
LEFT JOIN ma_order_info moi ON moi.order_id = hh.order_id
LEFT JOIN ma_dev_info mdi ON hh.ma_id = mdi.ma_id
LEFT JOIN sys_dept sd ON sd.dept_id = mdi.on_company
LEFT JOIN ma_type mt ON mdi.type_id = mt.type_id
LEFT JOIN sys_user su ON su.user_id = moi.buyer_id
LEFT JOIN sys_user su2 ON su2.user_id = mdi.creator

View File

@ -49,6 +49,13 @@
<if test="status != null">
and status = #{status}
</if>
<if test="contactPerson != null and contactPerson != ''">
and contact_person like concat('%', #{contactPerson}, '%')
</if>
<if test="contactPhone != null and contactPhone != ''">
and contact_phone like concat('%', #{contactPhone}, '%')
</if>
</where>
order by update_time desc
</select>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bonus.material.task.mapper.UseRateMapper">
<insert id="insertUseRate">
INSERT INTO ma_dev_daily_use (
ma_id,
status,
type_id,
create_time
)
VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.maId},
#{item.status},
#{item.typeId},
NOW()
)
</foreach>
</insert>
<select id="selectUseRate" resultType="com.bonus.material.task.domain.UseRate">
SELECT ma_id AS maId,
type_id AS typeId,
CASE
WHEN change_status IN (2, 3) THEN 1 -- 等于2或3时返回1
ELSE 0 -- 不等于2或3时返回0
END AS status
FROM ma_dev_info
WHERE is_active = '1'
and entry_status = '1'
and change_status != '4'
</select>
</mapper>

View File

@ -32,7 +32,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
d.order_num,
d.leader,
d.phone,
d.email,
d.status,
d.del_flag,
d.create_by,