问题修改

This commit is contained in:
jiang 2025-12-10 09:10:19 +08:00
parent 5b091d5ec5
commit fa29836d30
12 changed files with 306 additions and 62 deletions

View File

@ -337,7 +337,7 @@ public class DevChangeServiceImpl implements DevChangeService {
}
// 编码重复
String devCode = details.getDevCode();
if (StringUtils.isNotBlank(devCode) && devCodeSet.contains(devCode)) {
if (!devCode.equals("/") && StringUtils.isNotBlank(devCode) && devCodeSet.contains(devCode)) {
return AjaxResult.error("添加的列表中设备编号存在重复:" + devCode);
} else if (StringUtils.isNotBlank(devCode)) {
devCodeSet.add(devCode);

View File

@ -3,6 +3,7 @@ package com.bonus.material.device.domain;
import com.bonus.common.core.annotation.Excel;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Min;
@ -14,45 +15,45 @@ import java.util.Date;
@Data
public class EquipmentImportDTO {
@Excel(name = "装备类目", sort = 1, combo = {})
@Excel(name = "装备类目", sort = 1, combo = {}, align = HorizontalAlignment.CENTER )
@NotBlank(message = "专业不能为空")
private String profession;
@Excel(name = "装备名称", sort = 2)
@Excel(name = "装备名称", sort = 2, align = HorizontalAlignment.CENTER)
@NotBlank(message = "装备名称不能为空")
private String equipmentName;
@Excel(name = "规格型号", sort = 3)
@Excel(name = "规格型号", sort = 3, align = HorizontalAlignment.CENTER)
private String specification;
@Excel(name = "资产原值", sort = 4)
@Excel(name = "资产原值", sort = 4, align = HorizontalAlignment.CENTER)
@DecimalMin(value = "0.00", message = "资产原值不能小于0")
private BigDecimal originalValue;
@Excel(name = "生产厂家", sort = 5, combo = {})
@Excel(name = "生产厂家", sort = 5, combo = {}, align = HorizontalAlignment.CENTER)
private String manufacturer;
@Excel(name = "生产日期", sort = 6, dateFormat = "yyyy-MM-dd")
@Excel(name = "生产日期", sort = 6, dateFormat = "yyyy-MM-dd", align = HorizontalAlignment.CENTER)
@JsonFormat(pattern = "yyyy-MM-dd")
private Date productionDate;
@Excel(name = "下次维保日期", sort = 7, dateFormat = "yyyy-MM-dd")
@Excel(name = "下次维保日期", sort = 7, dateFormat = "yyyy-MM-dd", align = HorizontalAlignment.CENTER)
@JsonFormat(pattern = "yyyy-MM-dd")
private Date nextMaintenanceDate;
@Excel(name = "装备原始编码", sort = 8)
@Excel(name = "装备原始编码", sort = 8, align = HorizontalAlignment.CENTER)
@NotBlank(message = "装备原始编码不能为空")
private String originalCode;
@Excel(name = "最大使用年限", sort = 9)
@Excel(name = "最大使用年限", sort = 9, align = HorizontalAlignment.CENTER)
@Min(value = 0, message = "最大使用年限不能小于0")
private Integer maxServiceYears;
@Excel(name = "计数单位", sort = 10, combo = {})
@Excel(name = "计数单位", sort = 10, combo = {}, align = HorizontalAlignment.CENTER)
@NotBlank(message = "计数单位不能为空")
private String unit;
@Excel(name = "采购日期", sort = 11, dateFormat = "yyyy-MM-dd")
@Excel(name = "采购日期", sort = 11, dateFormat = "yyyy-MM-dd", align = HorizontalAlignment.CENTER)
@JsonFormat(pattern = "yyyy-MM-dd")
private Date purchaseDate;
}

View File

@ -14,6 +14,7 @@ import com.bonus.material.device.domain.vo.LeaseVo;
import com.bonus.material.largeScreen.entity.DevInfoReq;
import com.bonus.material.largeScreen.entity.LeaseInfo;
import com.bonus.material.largeScreen.entity.RentInfo;
import io.swagger.models.auth.In;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
@ -322,5 +323,7 @@ public interface DevInfoMapper {
int getProjectNUm();
DevInfoVo selectToolByMaId(Long maId);
DevInfo getMaStatusByToolId(@Param("id") Long id, @Param("num") Integer num);
}

View File

@ -107,7 +107,12 @@ public class OrderServiceImpl implements OrderService {
DevInfo maInfo;
for (OrderDetailDto orderDetailDto : orderDetailDtos) {
// 先判断要租赁的设备状态是否正常
maInfo = devInfoMapper.getMaStatusByMaId(Long.valueOf(orderDetailDto.getMaId()));
if (orderDetailDto.getDevType().equals("0")) {
maInfo = devInfoMapper.getMaStatusByMaId(Long.valueOf(orderDetailDto.getMaId()));
} else {
maInfo = devInfoMapper.getMaStatusByToolId(Long.valueOf(orderDetailDto.getMaId()), orderDetailDto.getNum());
}
if (maInfo == null || maInfo.getMaStatus() == null) {
throw new RuntimeException("设备信息异常");
}
@ -138,19 +143,19 @@ public class OrderServiceImpl implements OrderService {
orderMapper.insertOrderDetail(orderDetailDto);
}
}
TmTask tmTask = new TmTask();
tmTask.setTaskType(TmTaskTypeEnum.TM_TASK_ORDER.getTaskTypeId());
tmTask.setTaskStatus(OrderStatusEnum.TO_ORDER_PLACED.getStatus());
tmTask.setCode(code);
tmTask.setCreateBy(SecurityUtils.getLoginUser().getUsername());
tmTask.setCreateTime(DateUtils.getNowDate());
tmTask.setBuyerCompanyId(Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId()).orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId()));
if (!CollectionUtils.isEmpty(orderDetailDtos)) {
DevInfoVo devInfoVo = devInfoMapper.selectDevInfoByMaId(Long.valueOf(orderDetailDtos.get(0).getMaId()));
tmTask.setSellerCompanyId(Long.valueOf(devInfoVo.getCompanyId()));
}
tmTask.setNoticeCompanyId(tmTask.getSellerCompanyId());
tmTaskMapper.insertSelective(tmTask);
// TmTask tmTask = new TmTask();
// tmTask.setTaskType(TmTaskTypeEnum.TM_TASK_ORDER.getTaskTypeId());
// tmTask.setTaskStatus(OrderStatusEnum.TO_ORDER_PLACED.getStatus());
// tmTask.setCode(code);
// tmTask.setCreateBy(SecurityUtils.getLoginUser().getUsername());
// tmTask.setCreateTime(DateUtils.getNowDate());
// tmTask.setBuyerCompanyId(Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId()).orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId()));
// if (!CollectionUtils.isEmpty(orderDetailDtos)) {
// DevInfoVo devInfoVo = devInfoMapper.selectDevInfoByMaId(Long.valueOf(orderDetailDtos.get(0).getMaId()));
// tmTask.setSellerCompanyId(Long.valueOf(devInfoVo.getCompanyId()));
// }
// tmTask.setNoticeCompanyId(tmTask.getSellerCompanyId());
// tmTaskMapper.insertSelective(tmTask);
}
return j;
}

View File

@ -176,4 +176,5 @@ public class ToBeScrap {
@ApiModelProperty(value = "所属公司id")
private Long companyId;
}

View File

@ -0,0 +1,150 @@
package com.bonus.material.utils;
import com.bonus.common.core.annotation.Excel;
import com.bonus.common.core.utils.poi.ExcelUtil;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
/**
* 自定义的 ExcelUtil全表所有单元格都水平居中
* 通过后处理方式在生成Excel后修改所有单元格样式
*/
public class CenterExcelUtil<T> extends ExcelUtil<T> {
public CenterExcelUtil(Class<T> clazz) {
super(clazz);
}
/**
* 重写导入模板导出方法 - 主要方法
*/
@Override
public void importTemplateExcel(HttpServletResponse response, String sheetName, String title) {
try {
// 1. 将Excel写入到字节数组而不是直接写入响应
ByteArrayOutputStream baos = new ByteArrayOutputStream();
HttpServletResponse tempResponse = createTempResponse(baos);
// 2. 调用父类方法生成模板
super.importTemplateExcel(tempResponse, sheetName, title);
// 3. 获取生成的Excel字节数组
byte[] excelBytes = baos.toByteArray();
// 4. 应用居中样式
byte[] centeredExcelBytes = applyCenterStyle(excelBytes);
// 5. 设置响应头并写入处理后的Excel
setupResponseHeaders(response, sheetName);
response.getOutputStream().write(centeredExcelBytes);
response.getOutputStream().flush();
} catch (Exception e) {
throw new RuntimeException("导出Excel模板失败", e);
}
}
/**
* 创建临时响应对象用于捕获Excel字节数据
*/
private HttpServletResponse createTempResponse(ByteArrayOutputStream baos) throws IOException {
return new HttpServletResponseWrapper(null) {
@Override
public javax.servlet.ServletOutputStream getOutputStream() {
return new javax.servlet.ServletOutputStream() {
@Override
public void write(int b) {
baos.write(b);
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setWriteListener(javax.servlet.WriteListener writeListener) {
// 空实现
}
};
}
};
}
/**
* 应用居中样式到所有单元格
*/
private byte[] applyCenterStyle(byte[] excelBytes) throws IOException {
try (ByteArrayInputStream bais = new ByteArrayInputStream(excelBytes);
Workbook workbook = WorkbookFactory.create(bais);
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
// 遍历所有工作表
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
Sheet sheet = workbook.getSheetAt(i);
if (sheet == null) continue;
// 遍历所有存在的行
for (int rowIndex = sheet.getFirstRowNum(); rowIndex <= sheet.getLastRowNum(); rowIndex++) {
Row row = sheet.getRow(rowIndex);
if (row == null) continue;
// 遍历所有存在的单元格
for (int cellIndex = row.getFirstCellNum(); cellIndex <= row.getLastCellNum(); cellIndex++) {
Cell cell = row.getCell(cellIndex);
if (cell == null) continue;
// 设置单元格居中
setCellCenterStyle(workbook, cell);
}
}
}
workbook.write(baos);
return baos.toByteArray();
}
}
/**
* 设置单元格居中样式
*/
private void setCellCenterStyle(Workbook workbook, Cell cell) {
// 获取当前样式
CellStyle currentStyle = cell.getCellStyle();
// 创建新样式
CellStyle newStyle = workbook.createCellStyle();
// 复制原有样式
newStyle.cloneStyleFrom(currentStyle);
// 设置水平居中
newStyle.setAlignment(HorizontalAlignment.CENTER);
newStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 保持原有的数据格式
if (currentStyle.getDataFormatString() != null) {
newStyle.setDataFormat(Short.parseShort(currentStyle.getDataFormatString()));
}
// 应用新样式
cell.setCellStyle(newStyle);
}
/**
* 设置响应头
*/
private void setupResponseHeaders(HttpServletResponse response, String fileName) throws IOException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName + ".xlsx");
}
}

View File

@ -667,6 +667,7 @@
AND (cdcd.dev_code = '/' OR cdcd.dev_code = b.tool_code)
WHERE cdcd.del_flag = 0
AND cdcd.dev_type IN ('1', '2')
AND cdcd.is_finished != '1'
AND cdcd.change_id = #{id}
</select>
@ -1097,6 +1098,7 @@
SET is_finished ='1',
real_num = num
WHERE change_id = #{id}
AND is_finished != '1'
AND del_flag = '0'
</update>
<update id="updateGj">

View File

@ -248,14 +248,23 @@
<select id="deviceCount" resultType="com.bonus.material.devchange.domain.DeviceCountBean">
SELECT count(distinct if(mdi.change_status = '1', mdi.ma_id, null)) as inStock,
count(distinct if(mdi.change_status = '2', mdi.ma_id, null)) as ownUse,
count(distinct if(mdi.change_status = '3', mdi.ma_id, null)) as share,
count(distinct if(mdi.change_status = '5', mdi.ma_id, null)) as underRepair
count(distinct if(mdi.change_status = '2', mdi.ma_id, null)) as ownUse,
count(distinct if(mdi.change_status = '3', mdi.ma_id, null)) as share,
count(distinct if(mdi.change_status = '5', mdi.ma_id, null)) as underRepair
FROM ma_dev_info mdi
WHERE mdi.is_active = 1
<if test="companyId != null">
AND mdi.on_company = #{companyId}
</if>
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
mdi.ma_id = mdq.ma_id
LEFT JOIN ma_supplier ms ON ms.supplier_id = mdi.supplier_id
LEFT JOIN sys_cnarea sc ON sc.area_code = mdi.province_id
<where>
mdi.is_active = '1' and mdi.entry_status = '1'
<if test="companyId != null">
AND mdi.on_company = #{companyId}
</if>
</where>
</select>
<select id="getProperties" resultType="com.bonus.material.device.domain.vo.DevInfoPropertyVo">
@ -485,10 +494,20 @@
<select id="selectTotalDeviceCount" resultType="java.lang.Integer">
SELECT COUNT(1)
FROM ma_dev_info WHERE is_active = '1' and entry_status = '1'
<if test="companyId != null">
AND on_company = #{companyId}
</if>
from ma_dev_info mdi
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
mdi.ma_id = mdq.ma_id
LEFT JOIN ma_supplier ms ON ms.supplier_id = mdi.supplier_id
LEFT JOIN sys_cnarea sc ON sc.area_code = mdi.province_id
<where>
mdi.is_active = '1' and mdi.entry_status = '1'
<if test="companyId != null">
AND mdi.on_company = #{companyId}
</if>
</where>
</select>
<select id="batchGetProperties" resultType="com.bonus.material.device.domain.vo.DevInfoPropertyVo">
select mtp.id AS id,

View File

@ -79,5 +79,19 @@
</if>
</if>
</where>
ORDER BY
-- 1. 先按状态类型排序:告警在前,正常在后
CASE
WHEN a.status LIKE '%告警%' THEN 0
ELSE 1
END,
-- 2. 告警内部:已超期在前,即将超期在后
CASE
WHEN a.status LIKE '%已超%' THEN 0
WHEN a.status LIKE '%即将超期%' THEN 1
ELSE 2
END,
-- 3. 按剩余可用年限从少到多排序(数值排序)
(a.expirationYears - ROUND(TIMESTAMPDIFF(DAY, a.productionDate, NOW()) / 365.25, 1))
</select>
</mapper>

View File

@ -1680,4 +1680,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
GROUP BY sd.dept_id, sd.dept_name -- 按部门分组,确保所有部门都被列出
ORDER BY totalValue DESC
</select>
<select id="getMaStatusByToolId" resultType="com.bonus.material.device.domain.DevInfo">
SELECT id AS id,
'1' AS maStatus
FROM tool_ledger
WHERE available_num >= #{num}
and id = #{id}
</select>
</mapper>

View File

@ -609,5 +609,6 @@
SELECT typeId
FROM ma_type_view
WHERE CONCAT_WS('/', proType, mainGx, childGx, devCategory, devSubcategory) = #{profession}
LIMIT 1
</select>
</mapper>

View File

@ -4,20 +4,24 @@
<select id="getInStockList" resultType="com.bonus.material.scrap.domain.ToBeScrap">
SELECT t.* FROM (
SELECT
CONCAT(tl.id,'-','工具') as keyId,
tl.id,
'工具' AS type,
'2' as devType,
tl.type_id as typeId,
CONCAT(tt2.type_name, '/', tt3.type_name, '/', tt4.type_name) AS groupName,
tt4.type_name as typeName,
tt5.type_name as typeModelName,
CASE tl.manage_mode WHEN 0 THEN '编码管理' ELSE '数量管理' END manageMode,
tl.tool_code as `devCode`,
CASE tl.manage_mode WHEN 0 THEN IFNULL(tl.total_num, 0) ELSE IFNULL(tl.available_num, 0) END inStockNum
CONCAT(tl.id,'-','工具') as keyId,
tl.id,
'工具' AS type,
'2' as devType,
tl.type_id as typeId,
CONCAT(tt2.type_name, '/', tt3.type_name, '/', tt4.type_name) AS groupName,
tt4.type_name as typeName,
tt5.type_name as typeModelName,
CASE tl.manage_mode WHEN 0 THEN '编码管理' ELSE '数量管理' END manageMode,
tl.tool_code as `devCode`,
CASE tl.manage_mode WHEN 0 THEN IFNULL(tl.total_num, 0) ELSE IFNULL(tl.available_num, 0) END inStockNum,
'-' AS productionDate,
'-' AS expirationYears,
'-' AS status
FROM
tool_ledger tl
tool_ledger tl
LEFT JOIN tool_type tt5 on tt5.type_id = tl.type_id
LEFT JOIN tool_type tt4 on tt4.type_id = tt5.parent_id
LEFT JOIN tool_type tt3 on tt3.type_id = tt4.parent_id
@ -44,21 +48,42 @@
</if>
UNION
SELECT * FROM (
SELECT
CONCAT(mdi.ma_id,'-','装备') as keyId,
mdi.ma_id as id,
'装备' as type,
'1' as devType,
mdi.type_id as typeId,
CONCAT(mt2.type_name, '/', mt3.type_name, '/', mt4.type_name) AS groupName,
mdi.device_name as typeName,
mdi.item_type_model as typeModelName,
'编码管理' as manageMode,
mdi.`code` as `devCode`,
mdi.device_count as inStockNum
CONCAT(mdi.ma_id,'-','装备') as keyId,
mdi.ma_id as id,
'装备' as type,
'1' as devType,
mdi.type_id as typeId,
CONCAT(mt2.type_name, '/', mt3.type_name, '/', mt4.type_name) AS groupName,
mdi.device_name as typeName,
mdi.item_type_model as typeModelName,
'编码管理' as manageMode,
mdi.`code` as `devCode`,
mdi.device_count as inStockNum,
mdi.production_date AS productionDate,
mdi.max_working_hours AS expirationYears,
CASE
-- 告警2已超期剩余年限≤0
WHEN ROUND(TIMESTAMPDIFF(DAY, mdi.production_date, NOW()) / 365.25, 1) &gt;= mdi.max_working_hours
THEN CONCAT('告警:已超最大使用年限', ROUND(
ROUND(TIMESTAMPDIFF(DAY, mdi.production_date, NOW()) / 365.25, 1) - mdi.max_working_hours,
1
), '年')
-- 告警1未超期但剩余可用年限≤1年相差小于等于1年
WHEN (mdi.max_working_hours - ROUND(TIMESTAMPDIFF(DAY, mdi.production_date, NOW()) / 365.25, 1)) &lt;= 1
THEN CONCAT('告警:即将超期,剩余可用年限', ROUND(
mdi.max_working_hours - ROUND(TIMESTAMPDIFF(DAY, mdi.production_date, NOW()) / 365.25, 1),
1
), '年')
-- 正常未超期且剩余可用年限1年相差大于1年
ELSE CONCAT('正常:剩余可用年限', ROUND(
mdi.max_working_hours - ROUND(TIMESTAMPDIFF(DAY, mdi.production_date, NOW()) / 365.25, 1),
1
), '年')
END AS status
FROM
ma_dev_info mdi
ma_dev_info mdi
LEFT JOIN ma_type mt5 on mt5.type_id = mdi.type_id
LEFT JOIN ma_type mt4 on mt4.type_id = mt5.parent_id
LEFT JOIN ma_type mt3 on mt3.type_id = mt4.parent_id
@ -79,6 +104,22 @@
<if test='devType == "2"'>
AND 1=0
</if>
) a
) t
ORDER BY
-- 1. 先按状态类型排序:告警在前,正常在后
CASE
WHEN t.status LIKE '%告警%' THEN 0
ELSE 1
END,
-- 2. 告警内部:已超期在前,即将超期在后
CASE
WHEN t.status LIKE '%已超%' THEN 0
WHEN t.status LIKE '%即将超期%' THEN 1
ELSE 2
END,
-- 3. 按剩余可用年限从少到多排序(数值排序)
(t.expirationYears - ROUND(TIMESTAMPDIFF(DAY, t.productionDate, NOW()) / 365.25, 1))
</select>
<select id="getScrapApplyList" resultType="com.bonus.material.scrap.domain.ToBeScrap">