# Conflicts:
#	ruoyi-admin/src/main/java/com/ruoyi/web/controller/tyre/BaseTyreController.java
#	ruoyi-system/src/main/java/com/ruoyi/system/domain/BaseTyre.java
#	ruoyi-system/src/main/java/com/ruoyi/system/mapper/BaseTyreMapper.java
#	ruoyi-system/src/main/java/com/ruoyi/system/service/IBaseTyreService.java
#	ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BaseTyreServiceImpl.java
master
杨万里 2 months ago
commit 615601866d

@ -12,6 +12,13 @@ import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.BaseCar;
import com.ruoyi.system.domain.CarCheckLifecycleDTO;
import com.ruoyi.system.domain.CarLifecycleDTO;
import com.ruoyi.system.domain.CarLifecycleQuery;
import com.ruoyi.system.domain.CarMaintenanceLifecycleDTO;
import com.ruoyi.system.domain.CarMileageLifecycleDTO;
import com.ruoyi.system.domain.CarTyreInstallLifecycleDTO;
import com.ruoyi.system.service.IBaseCarLifecycleService;
import com.ruoyi.system.service.IBaseCarService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
@ -34,6 +41,9 @@ public class BaseCarController extends BaseController
@Autowired
private IBaseCarService baseCarService;
@Autowired
private IBaseCarLifecycleService baseCarLifecycleService;
@RequiresPermissions("system:car:view")
@GetMapping()
public String car()
@ -169,4 +179,91 @@ public class BaseCarController extends BaseController
return baseCarService.queryCarByRfid(baseCar);
}
/**
*
*/
@RequiresPermissions("system:car:view")
@GetMapping("/lifecycle/view/{carNo}")
public String lifecycleView(@PathVariable("carNo") String carNo, ModelMap mmap)
{
// 弹窗页面只保存车牌入口,明细统一由后端授权后的接口加载。
mmap.put("carNo", carNo);
return prefix + "/lifecycle";
}
/**
*
*/
@RequiresPermissions("system:car:view")
@GetMapping("/lifecycle/{carNo}")
@ResponseBody
public AjaxResult lifecycle(@PathVariable("carNo") String carNo)
{
CarLifecycleDTO lifecycle = baseCarLifecycleService.selectLifecycle(buildLifecycleQuery(carNo));
return AjaxResult.success(lifecycle);
}
/**
*
*/
@RequiresPermissions("system:car:view")
@PostMapping("/lifecycle/{carNo}/install/list")
@ResponseBody
public TableDataInfo lifecycleInstallList(@PathVariable("carNo") String carNo)
{
startPage();
List<CarTyreInstallLifecycleDTO> list = baseCarLifecycleService.selectInstallList(buildLifecycleQuery(carNo));
return getDataTable(list);
}
/**
*
*/
@RequiresPermissions("system:car:view")
@PostMapping("/lifecycle/{carNo}/maintenance/list")
@ResponseBody
public TableDataInfo lifecycleMaintenanceList(@PathVariable("carNo") String carNo)
{
startPage();
List<CarMaintenanceLifecycleDTO> list = baseCarLifecycleService.selectMaintenanceList(buildLifecycleQuery(carNo));
return getDataTable(list);
}
/**
*
*/
@RequiresPermissions("system:car:view")
@PostMapping("/lifecycle/{carNo}/check/list")
@ResponseBody
public TableDataInfo lifecycleCheckList(@PathVariable("carNo") String carNo)
{
startPage();
List<CarCheckLifecycleDTO> list = baseCarLifecycleService.selectCheckList(buildLifecycleQuery(carNo));
return getDataTable(list);
}
/**
*
*/
@RequiresPermissions("system:car:view")
@PostMapping("/lifecycle/{carNo}/mileage/list")
@ResponseBody
public TableDataInfo lifecycleMileageList(@PathVariable("carNo") String carNo)
{
startPage();
List<CarMileageLifecycleDTO> list = baseCarLifecycleService.selectMileageList(buildLifecycleQuery(carNo));
return getDataTable(list);
}
private CarLifecycleQuery buildLifecycleQuery(String carNo)
{
CarLifecycleQuery query = new CarLifecycleQuery();
// DataScope 依赖 BaseEntity 入参承接 params.dataScope因此 Controller 统一构造查询对象。
query.setCarNo(carNo);
return query;
}
}

@ -6,9 +6,11 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.BaseInventory;
import com.ruoyi.system.domain.BaseTyre;
import com.ruoyi.system.domain.vo.InboundBatchPreviewVo;
import com.ruoyi.system.service.IBaseInventoryService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
@ -137,4 +139,64 @@ public class BaseInventoryController extends BaseController
{
return baseInventoryService.OutInventoryByPda(baseInventory,baseTyre);
}
/**
* /
*
* @param inboundCode
* @return
*/
@RequiresPermissions("tyre:inventory:add")
@PostMapping("/batchInbound/preview")
@ResponseBody
public AjaxResult batchInboundPreview(@RequestParam("inboundCode") String inboundCode)
{
InboundBatchPreviewVo data = baseInventoryService.previewBatchByCode(inboundCode);
return AjaxResult.success("批次预览成功", data);
}
/**
*
*
* @param inboundCode
* @return
*/
@RequiresPermissions("tyre:inventory:add")
@Log(title = "轮胎批量入库", businessType = BusinessType.IMPORT)
@PostMapping("/batchInbound")
@ResponseBody
public AjaxResult batchInboundSave(@RequestParam("inboundCode") String inboundCode)
{
int rows = baseInventoryService.batchInboundByCode(inboundCode, ShiroUtils.getLoginName());
return rows > 0 ? AjaxResult.success("批量入库完成,成功处理 " + rows + " 条", rows) : AjaxResult.error("批量入库失败或无可入库轮胎");
}
/**
*
*
* @param inboundCode
* @return
*/
@RequiresPermissions("tyre:inventory:add")
@Log(title = "轮胎批量入库撤回", businessType = BusinessType.UPDATE)
@PostMapping("/batchInbound/rollback")
@ResponseBody
public AjaxResult batchInboundRollback(@RequestParam("inboundCode") String inboundCode)
{
int rows = baseInventoryService.rollbackBatchInboundByCode(inboundCode, ShiroUtils.getLoginName());
return rows > 0 ? AjaxResult.success("批量撤回完成,成功处理 " + rows + " 条", rows) : AjaxResult.error("批量撤回失败或无可撤回轮胎");
}
/**
* Thymeleaf
*
* @return
*/
@RequiresPermissions("tyre:inventory:add")
@GetMapping("/batchInbound")
public String batchInbound()
{
return prefix + "/batchInbound";
}
}

@ -12,6 +12,13 @@ import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.vo.BaseTyreVo;
import com.ruoyi.system.service.IBaseInventoryService;
import com.ruoyi.system.service.IBaseTyreService;
import com.ruoyi.system.service.IRecordCheckService;
import com.ruoyi.system.service.IRecordTyreInstallService;
import com.ruoyi.system.service.IRecordWarehousingService;
import com.ruoyi.system.service.ITyreStatDetailService;
import com.ruoyi.system.domain.vo.InboundBatchPreviewVo;
import com.ruoyi.system.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
@ -53,6 +60,10 @@ public class BaseTyreController extends BaseController
//“库存盘点详情”对话框和“轮胎详情”页签
@Autowired
private ITyreStatDetailService tyreStatDetailService;
@Autowired
private IBaseInventoryService baseInventoryService;
@Autowired
private IBizOrderTireDetailService bizOrderTireDetailService;
@Autowired
@ -72,8 +83,11 @@ public class BaseTyreController extends BaseController
}
/**
*
*
*/
@GetMapping("/detail/{tyreId}")
public String tyreDetil(@PathVariable("tyreId") Long tyreId, Model model)
{
@ -113,12 +127,15 @@ public class BaseTyreController extends BaseController
timelineItem.setColor("primary"); // 蓝色,代表进入
timelineItem.setTime(item.getCreateTime());
}
timelineItem.setType("warehousing");
timelineItem.setDetail("仓库:" + "轮胎仓库"); // 如果有仓库名称字段,可以替换 "轮胎仓库"
timelineItems.add(timelineItem);
}
}
// --- 2.2 查询并转换安装记录 ---
RecordTyreInstall installQuery = new RecordTyreInstall();
installQuery.setTyreRfid(tyre.getTyreEpc());
@ -137,27 +154,18 @@ public class BaseTyreController extends BaseController
}
}
//保养记录
BizOrderTireDetail bizOrderTireDetail = new BizOrderTireDetail();
bizOrderTireDetail.setTireId(tyre.getTyreId());
List<BizOrderTireDetail> bizOrderTireDetailList = bizOrderTireDetailService.selectBizOrderTireDetailList(bizOrderTireDetail);
if (bizOrderTireDetailList != null) {
for (BizOrderTireDetail item : bizOrderTireDetailList) {
//查询质检单信息
Long orderID = item.getOrderId();
BizMaintenanceOrder bizMaintenanceOrder = iBizMaintenanceOrderService.selectBizMaintenanceOrderByOrderId(orderID);
// --- 2.3 查询并转换检查记录 ---
RecordCheck checkQuery = new RecordCheck();
checkQuery.setTyreRfid(tyre.getTyreEpc());
List<RecordCheck> checkList = recordCheckService.selectRecordCheckList(checkQuery);
if (checkList != null) {
for (RecordCheck item : checkList) {
TimelineItem timelineItem = new TimelineItem();
timelineItem.setId(item.getDetailId());
timelineItem.setTitle("轮胎检查保养"+item.getCreateBy());
timelineItem.setId(item.getId());
timelineItem.setTitle("轮胎检查"+item.getCreateBy());
timelineItem.setType("check");
// timelineItem.setDetail(buildCheckDetail(item));
timelineItem.setDetail("场站:" + bizMaintenanceOrder.getFactoryName()+
"|车牌:"+bizMaintenanceOrder.getPlateNumber()+
"|轮位:"+item.getPositionName()+
"|花纹深度:"+item.getTreadDepth()+
"|气压:"+item.getTirePress()+
"|备注:"+item.getRemark()
);
timelineItem.setDetail("深度:" + "17.8mm");
timelineItem.setTime(item.getCreateTime());
timelineItem.setIcon("fa-check-circle");
timelineItem.setColor("warning");
@ -302,14 +310,6 @@ public class BaseTyreController extends BaseController
return info;
}
/**
* PDA
* @param baseTyre
* @return
*/
@PostMapping("/setRfidBarcode")
@ResponseBody
public AjaxResult setRfidBarcode(@Validated BaseTyre baseTyre)
@ -500,6 +500,57 @@ public class BaseTyreController extends BaseController
// 库存盘点链路统一切到新版详情模板,保留旧模板文件给其他场景继续观察或回退。
return prefix + "/typreDetill2";
}
/**
*
*/
@RequiresPermissions("tyre:tyre:receive")
@GetMapping("/receive")
public String receive()
{
return prefix + "/receive";
}
/**
* /
*/
@RequiresPermissions("tyre:tyre:receive")
@PostMapping("/receive/preview")
@ResponseBody
public AjaxResult receivePreview(@RequestParam("inboundCode") String inboundCode)
{
InboundBatchPreviewVo data = baseInventoryService.previewBatchByCode(inboundCode);
return AjaxResult.success("批次预览成功", data);
}
/**
*
*/
@RequiresPermissions("tyre:tyre:receive")
@Log(title = "轮胎收货", businessType = BusinessType.IMPORT)
@PostMapping("/receive")
@ResponseBody
public AjaxResult receiveSubmit(@RequestParam("inboundCode") String inboundCode)
{
int rows = baseInventoryService.batchInboundByCode(inboundCode, ShiroUtils.getLoginName());
return rows > 0 ? AjaxResult.success("收货完成,成功处理 " + rows + " 条", rows)
: AjaxResult.error("收货失败或无可入库轮胎");
}
/**
*
*/
@RequiresPermissions("tyre:tyre:receive")
@Log(title = "轮胎收货撤回", businessType = BusinessType.UPDATE)
@PostMapping("/receive/rollback")
@ResponseBody
public AjaxResult receiveRollback(@RequestParam("inboundCode") String inboundCode)
{
int rows = baseInventoryService.rollbackBatchInboundByCode(inboundCode, ShiroUtils.getLoginName());
return rows > 0 ? AjaxResult.success("收货撤回完成,成功处理 " + rows + " 条", rows)
: AjaxResult.error("收货撤回失败或无可撤回轮胎");
}
@PostMapping("/pdaQueryTyreTimeLine")
@ResponseBody
public AjaxResult pdaQueryTyreTimeLine(BaseTyre baseTyre)

@ -2,6 +2,98 @@
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('车辆基础信息列表')" />
<style>
.car-no-link {
color: #1c84c6;
font-weight: 600;
text-decoration: none;
border-bottom: 1px solid rgba(28, 132, 198, 0.35);
padding-bottom: 2px;
}
.car-no-link:hover,
.car-no-link:focus {
color: #0f6fa8;
text-decoration: none;
border-bottom-color: #0f6fa8;
}
.lifecycle-drawer-mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1980;
display: none;
background: rgba(0, 0, 0, 0.18);
}
.lifecycle-drawer {
position: fixed;
top: 0;
right: 0;
z-index: 1981;
width: 66.6667%;
height: 100%;
background: #f3f3f4;
box-shadow: -4px 0 18px rgba(0, 0, 0, 0.18);
transform: translateX(100%);
transition: transform 0.24s ease;
}
.lifecycle-drawer.open {
transform: translateX(0);
}
.lifecycle-drawer-header {
height: 48px;
padding: 0 14px 0 18px;
display: flex;
align-items: center;
justify-content: space-between;
background: #fff;
border-bottom: 1px solid #e7eaec;
}
.lifecycle-drawer-title {
color: #2f4050;
font-weight: 600;
font-size: 15px;
max-width: calc(100% - 70px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.lifecycle-drawer-close {
width: 32px;
height: 32px;
border: 0;
background: transparent;
color: #676a6c;
font-size: 20px;
line-height: 32px;
}
.lifecycle-drawer-close:hover {
color: #ed5565;
}
.lifecycle-drawer iframe {
width: 100%;
height: calc(100% - 48px);
border: 0;
display: block;
background: #f3f3f4;
}
@media (max-width: 991px) {
.lifecycle-drawer {
width: 92%;
}
}
</style>
</head>
<body class="gray-bg">
<div class="container-div">
@ -57,6 +149,14 @@
</div>
</div>
</div>
<div class="lifecycle-drawer-mask" id="lifecycleDrawerMask" onclick="closeLifecycleDrawer()"></div>
<div class="lifecycle-drawer" id="lifecycleDrawer">
<div class="lifecycle-drawer-header">
<div class="lifecycle-drawer-title" id="lifecycleDrawerTitle">车辆全生命周期</div>
<button type="button" class="lifecycle-drawer-close" onclick="closeLifecycleDrawer()" title="关闭">×</button>
</div>
<iframe id="lifecycleFrame" src="about:blank"></iframe>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('system:car:edit')}]];
@ -83,7 +183,15 @@
},
{
field : 'carNo',
title : '车牌'
title : '车牌',
formatter: function(value, row, index) {
var carNo = $.common.nullToStr(value);
if (!carNo) {
return '-';
}
// 车牌号作为生命周期入口,统一编码放入 data 属性,避免中文车牌或特殊字符破坏 onclick。
return '<a class="car-no-link" href="javascript:void(0)" data-car-no="' + encodeURIComponent(carNo) + '" onclick="openLifecycleDrawer(this)">' + escapeHtml(carNo) + '</a>';
}
},
{
field : 'team',
@ -118,6 +226,35 @@
};
$.table.init(options);
});
function openLifecycleDrawer(target) {
var carNo = decodeURIComponent($(target).attr("data-car-no") || "");
if (!carNo) {
// 没有车牌就无法建立生命周期主线,直接拦截避免后端产生无意义查询。
$.modal.alertWarning("车牌号为空,无法查看生命周期报表");
return;
}
$("#lifecycleDrawerTitle").text("车辆全生命周期 - " + carNo);
$("#lifecycleFrame").attr("src", prefix + "/lifecycle/view/" + encodeURIComponent(carNo));
$("#lifecycleDrawerMask").show();
$("#lifecycleDrawer").addClass("open");
}
function closeLifecycleDrawer() {
$("#lifecycleDrawer").removeClass("open");
$("#lifecycleDrawerMask").hide();
// 关闭时清空 iframe避免用户继续操作已隐藏的生命周期页面。
$("#lifecycleFrame").attr("src", "about:blank");
}
function escapeHtml(value) {
return String(value)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;");
}
</script>
</body>
<!-- 导入区域 -->
@ -135,4 +272,4 @@
</div>
</form>
</script>
</html>
</html>

@ -0,0 +1,594 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<th:block th:include="include :: header('车辆全生命周期')" />
<style>
.detail-shell {
padding: 15px;
}
.summary-card,
.info-card,
.timeline-card {
background: #fff;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
margin-bottom: 16px;
}
.summary-card {
padding: 20px 24px;
}
.summary-title {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 16px;
}
.summary-name {
font-size: 34px;
font-weight: 700;
color: #2f4050;
line-height: 1.2;
margin-bottom: 10px;
word-break: break-all;
}
.summary-meta {
color: #666;
font-size: 14px;
line-height: 1.9;
}
.summary-counts {
min-width: 360px;
display: grid;
grid-template-columns: repeat(2, minmax(130px, 1fr));
gap: 10px;
}
.count-item {
border: 1px solid #edf1f2;
border-radius: 8px;
padding: 10px 12px;
background: #fafbfc;
}
.count-value {
font-size: 22px;
font-weight: 700;
color: #1c84c6;
line-height: 1.2;
}
.count-label {
color: #7a8590;
font-size: 12px;
margin-top: 4px;
}
.info-card {
padding: 18px 20px 10px;
}
.section-title {
font-size: 16px;
font-weight: 600;
color: #2f4050;
margin-bottom: 14px;
}
.section-title i {
margin-right: 6px;
color: #666;
}
.info-table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
margin-bottom: 16px;
}
.info-table th,
.info-table td {
border: 1px solid #edf1f2;
padding: 12px 14px;
font-size: 14px;
word-break: break-all;
}
.info-table th {
width: 28%;
color: #7a8590;
font-weight: 500;
background: #fafbfc;
}
.info-table td {
color: #2f4050;
background: #fff;
}
.tyre-block {
border: 1px solid #edf1f2;
border-radius: 8px;
padding: 12px 14px;
margin-bottom: 12px;
background: #fff;
}
.tyre-title {
display: flex;
justify-content: space-between;
gap: 10px;
color: #2f4050;
font-weight: 600;
margin-bottom: 8px;
}
.tyre-meta {
color: #666;
font-size: 13px;
line-height: 1.8;
word-break: break-all;
}
.timeline-card {
padding: 18px 18px 12px;
min-height: 520px;
}
.timeline-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 18px;
}
.timeline-header .title {
font-size: 18px;
font-weight: 600;
color: #2f4050;
}
.mini-tip {
font-size: 12px;
color: #999;
}
.life-list {
list-style: none;
padding: 0;
margin: 0;
position: relative;
}
.life-list:before {
content: "";
position: absolute;
left: 22px;
top: 8px;
bottom: 8px;
width: 2px;
background: #e4e7ea;
}
.life-item {
position: relative;
padding-left: 58px;
margin-bottom: 22px;
}
.life-dot {
position: absolute;
left: 12px;
top: 4px;
width: 22px;
height: 22px;
border-radius: 50%;
border: 3px solid #d7ebf8;
background: #1c84c6;
text-align: center;
color: #fff;
line-height: 16px;
font-size: 11px;
}
.life-dot.install {
background: #1c84c6;
border-color: #d7ebf8;
}
.life-dot.maintenance {
background: #f8ac59;
border-color: #fde6c8;
}
.life-dot.check {
background: #1ab394;
border-color: #d7f0eb;
}
.life-dot.mileage {
background: #23c6c8;
border-color: #d7f4f4;
}
.life-time {
color: #909399;
font-size: 12px;
margin-bottom: 4px;
}
.life-title {
color: #2f4050;
font-weight: 600;
margin-bottom: 8px;
word-break: break-all;
}
.life-body {
color: #666;
line-height: 1.7;
font-size: 13px;
}
.life-detail-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 6px 14px;
}
.life-detail {
min-width: 0;
word-break: break-all;
}
.life-detail .label-title {
color: #8a929a;
}
.life-description {
margin-top: 8px;
padding: 8px 10px;
border-left: 3px solid #e4e7ea;
background: #fafbfc;
color: #666;
word-break: break-all;
}
.text-muted-dash {
color: #999;
}
@media (max-width: 991px) {
.summary-title {
flex-direction: column;
}
.summary-counts {
min-width: 0;
width: 100%;
}
}
@media (max-width: 640px) {
.summary-counts,
.life-detail-grid {
grid-template-columns: 1fr;
}
.summary-name {
font-size: 26px;
}
}
</style>
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content detail-shell">
<input id="carNo" type="hidden" th:value="${carNo}"/>
<div class="summary-card">
<div class="summary-title">
<div>
<div class="summary-name" id="summaryName">车辆:-</div>
<div class="summary-meta" id="summaryMeta">正在加载...</div>
</div>
<div class="summary-counts" id="summaryCounts"></div>
</div>
</div>
<div class="row">
<div class="col-lg-4 col-md-5 col-sm-12">
<div class="info-card">
<div class="section-title"><i class="fa fa-bookmark"></i>基本信息</div>
<table class="info-table" id="vehicleInfo"></table>
</div>
<div class="info-card">
<div class="section-title"><i class="fa fa-truck"></i>当前装车轮胎</div>
<div id="mountedTyres">
<div class="text-center text-muted-dash" style="padding: 40px 0;">正在加载...</div>
</div>
</div>
</div>
<div class="col-lg-8 col-md-7 col-sm-12">
<div class="timeline-card">
<div class="timeline-header">
<span class="title">生命周期时间轴</span>
<span class="mini-tip">按时间倒序展示,包含装卸、维保、质检、里程记录</span>
</div>
<ul class="life-list" id="timelineList"></ul>
<div class="text-center text-muted-dash" id="emptyTimeline" style="display: none; padding: 80px 0;">
暂无生命周期记录
</div>
</div>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "tyre/car";
var carNo = $("#carNo").val();
$(function () {
loadLifecycle();
// 兜底关闭父窗口 loading避免 iframe 加载时序导致遮罩残留。
if (window.parent && window.parent !== window && window.parent.$ && window.parent.$.modal) {
window.parent.$.modal.closeLoading();
}
});
function loadLifecycle() {
$.get(prefix + "/lifecycle/" + encodeURIComponent(carNo), function (result) {
if (result.code != web_status.SUCCESS) {
$.modal.alertError(result.msg);
return;
}
var data = result.data || {};
renderSummary(data);
renderVehicleInfo(data.car || {});
renderMountedTyres(data.mountedTyres || []);
renderTimeline(data.recentEvents || []);
});
}
function renderSummary(data) {
var car = data.car || {};
$("#summaryName").html("车辆:" + safeText(car.carNo));
$("#summaryMeta").html([
"所属车队:" + safeText(car.team),
"线路:" + safeText(car.line),
"车型:" + safeText(car.type),
// "当前里程:" + safeText(car.inputMileage)
].join("<br/>"));
$("#summaryCounts").html([
countItem("装卸记录", data.installCount),
countItem("维保工单", data.maintenanceCount),
countItem("质检记录", data.checkCount),
countItem("里程记录", data.mileageCount)
].join(""));
}
function renderVehicleInfo(car) {
$("#vehicleInfo").html([
tableRow("车牌", car.carNo),
tableRow("车队", car.team),
tableRow("线路", car.line),
tableRow("车型", car.type),
// tableRow("车辆主键", car.carId),
// tableRow("部门ID", car.deptId),
// tableRow("最近工单里程", car.inputMileage)
].join(""));
}
function renderMountedTyres(rows) {
if (!rows.length) {
$("#mountedTyres").html('<div class="text-center text-muted-dash" style="padding: 40px 0;">暂无当前装车轮胎</div>');
return;
}
var html = [];
$.each(rows, function (index, item) {
// 当前装车轮胎作为车辆当前状态展示,便于和时间轴历史装卸节点互相核对。
html.push('<div class="tyre-block">');
html.push('<div class="tyre-title"><span>' + safeText(item.tyreNo || item.selfNo || item.tyreEpc) + '</span><span>' + safeText(item.wheelPostion) + '</span></div>');
html.push('<div class="tyre-meta">');
html.push('自编号:' + safeText(item.selfNo) + '<br/>');
html.push('RFID' + safeText(item.tyreEpc) + '<br/>');
html.push('品牌/规格:' + safeText(joinText(item.tyreBrand, item.tyreModel)) + '<br/>');
html.push('花纹深度:' + safeText(item.patternDepth));
html.push('</div></div>');
});
$("#mountedTyres").html(html.join(""));
}
function renderTimeline(rows) {
if (!rows.length) {
$("#timelineList").empty();
$("#emptyTimeline").show();
return;
}
$("#emptyTimeline").hide();
var html = [];
$.each(rows, function (index, item) {
html.push('<li class="life-item">');
html.push('<span class="life-dot ' + eventClass(item.eventType) + '">' + eventIcon(item.eventType) + '</span>');
html.push('<div class="life-time">' + safeText(item.eventTime) + '</div>');
html.push('<div class="life-title">' + safeText(eventTitle(item)) + '</div>');
html.push('<div class="life-body">' + eventDetails(item) + '</div>');
html.push('</li>');
});
$("#timelineList").html(html.join(""));
}
function eventDetails(item) {
var details = [];
if (item.eventType == "INSTALL") {
// 装卸节点保留轮胎、轮位、里程和花纹深度,方便追溯“何时装到哪个轮位、卸下时状态如何”。
details.push(detail("胎号", item.tyreNo));
details.push(detail("自编号", item.selfNo));
details.push(detail("RFID", item.tyreRfid));
details.push(detail("品牌/规格", joinText(item.tyreBrand, item.tyreModel)));
details.push(detail("轮位", item.wheelPostion));
details.push(detail("里程", item.mileage));
details.push(detail("花纹深度", item.patternDepth));
details.push(detail("动作", installTypeFormatter(item.status)));
} else if (item.eventType == "MAINTENANCE") {
// 工单节点展示工单号和站点,排查车辆维保历史时不用再跳转列表反查。
details.push(detail("工单号", item.orderNo));
details.push(detail("维保类型", orderTypeFormatter(item.typeCode)));
details.push(detail("状态", statusFormatter(item.status)));
details.push(detail("维修站点", item.factoryName));
details.push(detail("录入里程", item.inputMileage));
details.push(detail("上次里程", item.lastMileage));
details.push(detail("维保日期", item.maintainDate));
} else if (item.eventType == "CHECK") {
// 质检节点通过曾装车轮胎间接归属车辆,页面上明确展示轮胎身份,避免误以为质检表直接有车牌。
details.push(detail("胎号", item.tyreNo));
details.push(detail("自编号", item.selfNo));
details.push(detail("RFID", item.tyreRfid));
details.push(detail("品牌/规格", joinText(item.tyreBrand, item.tyreModel)));
details.push(detail("保养类型", item.maintenanceType));
details.push(detail("车辆里程", item.mileage));
details.push(detail("花纹深度", item.patternDepth));
details.push(detail("处理意见", item.result));
} else if (item.eventType == "MILEAGE") {
// 里程节点展示安装/卸下时间窗,提醒用户该记录是按轮胎 RFID 间接关联车辆。
details.push(detail("胎号", item.tyreNo));
details.push(detail("自编号", item.selfNo));
details.push(detail("RFID", item.tyreRfid));
details.push(detail("品牌/规格", joinText(item.tyreBrand, item.tyreModel)));
details.push(detail("安装时间", item.startTime));
details.push(detail("卸下时间", item.endTime));
details.push(detail("记录里程", item.mileage));
details.push(detail("花纹深度", item.patternDepth));
}
var html = '<div class="life-detail-grid">' + details.join("") + '</div>';
if (item.description) {
html += '<div class="life-description">补充说明:' + safeText(item.description) + '</div>';
}
return html;
}
function eventTitle(item) {
if (item.eventType == "INSTALL") {
return installTypeFormatter(item.status) + "轮胎:" + displayValue(item.tyreNo || item.selfNo || item.tyreRfid);
}
if (item.eventType == "MAINTENANCE") {
return orderTypeFormatter(item.typeCode) + "" + displayValue(item.orderNo);
}
if (item.eventType == "CHECK") {
return "轮胎质检:" + displayValue(item.tyreNo || item.selfNo || item.tyreRfid);
}
if (item.eventType == "MILEAGE") {
return "轮胎里程:" + displayValue(item.tyreNo || item.selfNo || item.tyreRfid);
}
return displayValue(item.eventType);
}
function eventClass(type) {
if (type == "MAINTENANCE") {
return "maintenance";
}
if (type == "CHECK") {
return "check";
}
if (type == "MILEAGE") {
return "mileage";
}
return "install";
}
function eventIcon(type) {
if (type == "MAINTENANCE") {
return "维";
}
if (type == "CHECK") {
return "检";
}
if (type == "MILEAGE") {
return "里";
}
return "装";
}
function detail(name, value) {
return '<div class="life-detail"><span class="label-title">' + safeText(name) + '</span>' + safeText(value) + '</div>';
}
function tableRow(name, value) {
return '<tr><th>' + safeText(name) + '</th><td>' + safeText(value) + '</td></tr>';
}
function countItem(name, value) {
return '<div class="count-item"><div class="count-value">' + safeText(value) + '</div><div class="count-label">' + safeText(name) + '</div></div>';
}
function joinText(left, right) {
var first = displayValue(left);
var second = displayValue(right);
if (first == "-" && second == "-") {
return "-";
}
return (first == "-" ? "" : first) + (second == "-" ? "" : " / " + second);
}
function displayValue(value) {
var text = $.common.nullToStr(value);
return text === "" ? "-" : text;
}
function safeText(value) {
return escapeHtml(displayValue(value));
}
function escapeHtml(value) {
return String(value)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;");
}
function installTypeFormatter(value) {
if (value == "0") {
return "安装";
}
if (value == "1") {
return "卸下";
}
return displayValue(value);
}
function orderTypeFormatter(value) {
if (value == "1") {
return "二级保养";
}
if (value == "4") {
return "月检";
}
return displayValue(value);
}
function statusFormatter(value) {
if (value == "UNSTARTED") {
return "未开始";
}
if (value == "PROCESSING") {
return "执行中";
}
if (value == "COMPLETED") {
return "已完成";
}
return displayValue(value);
}
</script>
</body>
</html>

@ -0,0 +1,181 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('轮胎批量入库')" />
<style>
.batch-panel { padding: 15px; }
.batch-actions { margin-top: 10px; }
.batch-summary { margin-top: 15px; }
.batch-table { margin-top: 10px; max-height: 360px; overflow: auto; }
</style>
</head>
<body class="gray-bg">
<div class="container-div batch-panel">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="batchForm" class="form-inline">
<div class="form-group">
<label>入库编码:</label>
<input id="inboundCode" name="inboundCode" type="text" class="form-control" placeholder="请输入入库编码" autocomplete="off"/>
</div>
<div class="batch-actions">
<a class="btn btn-primary" onclick="previewBatch()" shiro:hasPermission="tyre:inventory:batch">
<i class="fa fa-search"></i> 预览批次
</a>
<a class="btn btn-success" onclick="submitBatch()" shiro:hasPermission="tyre:inventory:batch">
<i class="fa fa-upload"></i> 一键入库
</a>
<a class="btn btn-danger" onclick="rollbackBatch()" shiro:hasPermission="tyre:inventory:batchRollback">
<i class="fa fa-undo"></i> 撤回入库
</a>
</div>
</form>
</div>
<div class="col-sm-12 batch-summary" id="summaryPanel" style="display:none;"></div>
<div class="col-sm-12 batch-table" id="detailPanel" style="display:none;"></div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "tyre/inventory";
var processing = false;
function normalizeCode() {
var code = $.trim($("#inboundCode").val());
if (!code) {
$.modal.alertWarning("请输入入库编码");
return "";
}
return code;
}
function previewBatch() {
var code = normalizeCode();
if (!code) {
return;
}
postBatch(prefix + "/batchInbound/preview", code, function (data) {
renderPreview(data);
});
}
function submitBatch() {
var code = normalizeCode();
if (!code) {
return;
}
$.modal.confirm("确认按入库编码 [" + escapeHtml(code) + "] 一键入库?", function () {
// 入库是批量写库存与流水的动作,前端二次确认用于避免现场误点。
postBatch(prefix + "/batchInbound", code, function (data) {
renderResult("批量入库完成", data);
});
});
}
function rollbackBatch() {
var code = normalizeCode();
if (!code) {
return;
}
$.modal.confirm("确认撤回入库编码 [" + escapeHtml(code) + "] 仍在库的库存记录?", function () {
// 撤回只处理仍在库的当前库存记录,已发生后续出库的轮胎由后端跳过。
postBatch(prefix + "/batchInbound/rollback", code, function (data) {
renderResult("批量撤回完成", data);
});
});
}
function postBatch(url, code, callback) {
if (processing) {
return;
}
processing = true;
setButtonsDisabled(true);
$.modal.loading("处理中,请稍候...");
$.ajax({
url: url,
type: "post",
data: { inboundCode: code },
success: function (res) {
if (res.code === 0) {
callback(res.data || {});
} else {
$.modal.alertError(res.msg || "操作失败");
}
},
error: function () {
$.modal.alertError("请求失败,请稍后重试");
},
complete: function () {
$.modal.closeLoading();
processing = false;
setButtonsDisabled(false);
}
});
}
function renderPreview(data) {
var html = "<div class='alert alert-info'>批次:" + escapeHtml(data.inboundCode) +
",共 " + (data.total || 0) + " 条,已存在 " + (data.exists || 0) +
" 条,待入库 " + (data.pending || 0) + " 条</div>";
$("#summaryPanel").html(html).show();
renderItems(data.items || [], "status");
}
function renderResult(title, data) {
if (typeof data === "number") {
// 后端写操作按 RuoYi Service 风格返回影响条数,页面只展示本次实际成功处理数。
$("#summaryPanel").html("<div class='alert alert-success'>" + title + ",成功处理 " + data + " 条</div>").show();
$("#detailPanel").hide().empty();
return;
}
var html = "<div class='alert alert-success'>" + title + ",批次:" + escapeHtml(data.inboundCode) +
",共 " + (data.total || 0) + " 条,成功 " + (data.success || 0) +
" 条,跳过 " + (data.skip || 0) + " 条,失败 " + (data.fail || 0) + " 条</div>";
$("#summaryPanel").html(html).show();
renderFailures(data.failures || []);
}
function renderItems(items, statusField) {
var rows = items.map(function (item) {
return "<tr><td>" + escapeHtml(item.tyreEpc) + "</td><td>" + escapeHtml(item.tyreNo) +
"</td><td>" + escapeHtml(item.tyreBrand) + "</td><td>" + escapeHtml(item.tyreModel) +
"</td><td>" + escapeHtml(item[statusField]) + "</td></tr>";
}).join("");
var table = "<table class='table table-bordered table-striped'><thead><tr><th>RFID标签</th><th>胎号</th><th>品牌</th><th>型号</th><th>状态</th></tr></thead><tbody>" + rows + "</tbody></table>";
$("#detailPanel").html(table).show();
}
function renderFailures(failures) {
if (!failures.length) {
$("#detailPanel").hide().empty();
return;
}
var rows = failures.map(function (item) {
return "<tr><td>" + escapeHtml(item.tyreEpc) + "</td><td>" + escapeHtml(item.tyreNo) +
"</td><td>" + escapeHtml(item.reason) + "</td></tr>";
}).join("");
var table = "<table class='table table-bordered table-striped'><thead><tr><th>RFID标签</th><th>胎号</th><th>失败原因</th></tr></thead><tbody>" + rows + "</tbody></table>";
$("#detailPanel").html(table).show();
}
function setButtonsDisabled(disabled) {
$(".batch-actions .btn").toggleClass("disabled", disabled);
}
function escapeHtml(value) {
return String(value == null ? "" : value)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;");
}
$("#batchForm").on("submit", function (e) {
e.preventDefault();
previewBatch();
});
</script>
</body>
</html>

@ -62,6 +62,9 @@
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="tyre:inventory:export">
<i class="fa fa-download"></i> 导出
</a>
<a class="btn btn-info" onclick="openBatchInbound()" shiro:hasPermission="tyre:inventory:batch">
<i class="fa fa-upload"></i> 批量入库
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
@ -154,6 +157,11 @@
$.table.init(options);
});
function openBatchInbound() {
// 批量入库归并在库存信息入口下,仍用独立页签承载预览/入库/撤回,避免挤占库存列表操作区。
$.modal.openTab("轮胎批量入库", prefix + "/batchInbound");
}
/* 用户管理-新增-选择部门树 */
function selectDeptTree() {
var treeId = $("#treeId").val();
@ -186,4 +194,4 @@
}
</script>
</body>
</html>
</html>

@ -0,0 +1,115 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('轮胎收货')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12">
<form id="formId" class="form-inline">
<div class="form-group">
<label>入库编码:</label>
<input id="inboundCode" name="inboundCode" type="text"
class="form-control" placeholder="请输入供应商提供的入库编码" autocomplete="off"
style="width: 280px;"/>
</div>
<a class="btn btn-primary" onclick="doPreview()"><i class="fa fa-search"></i> 查询</a>
</form>
<div id="previewPanel" class="mt20" style="display:none;">
<div class="alert alert-info" id="previewSummary"></div>
<div class="table-responsive" style="max-height: 300px; overflow-y: auto;">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>RFID</th>
<th>胎号</th>
<th>品牌</th>
<th>型号</th>
<th>状态</th>
</tr>
</thead>
<tbody id="previewTbody"></tbody>
</table>
</div>
</div>
<div class="text-right mt20">
<a id="confirmBtn" class="btn btn-success disabled" onclick="doConfirm()"
shiro:hasPermission="tyre:tyre:receive">
<i class="fa fa-check"></i> 确认入库
</a>
</div>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "tyre/tyre";
var lastPreview = null;
function doPreview() {
var code = $.trim($("#inboundCode").val());
if (!code) { $.modal.alertWarning("请输入入库编码"); return; }
$.modal.loading("正在查询...");
$.ajax({
url: prefix + "/receive/preview",
type: "post",
data: { inboundCode: code },
success: function (res) {
$.modal.closeLoading();
if (res.code !== 0) { $.modal.alertError(res.msg); return; }
lastPreview = res.data || {};
renderPreview(lastPreview);
$("#confirmBtn").toggleClass("disabled", !(lastPreview.pending > 0));
},
error: function () {
$.modal.closeLoading();
$.modal.alertError("网络异常,请重试");
}
});
}
function renderPreview(data) {
var summary = "批次:" + data.inboundCode + ",共 " + data.total + " 条,已入库 "
+ data.exists + " 条,<b style='color:red'>待入库 " + data.pending + " 条</b>";
$("#previewSummary").html(summary);
var rows = "";
var items = data.items || [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
var statusLabel = item.status === '待入库'
? '<span class="label label-warning">待入库</span>'
: '<span class="label label-success">已存在库存记录</span>';
rows += "<tr><td>" + (item.tyreEpc || '') + "</td><td>" + (item.tyreNo || '')
+ "</td><td>" + (item.tyreBrand || '') + "</td><td>" + (item.tyreModel || '')
+ "</td><td>" + statusLabel + "</td></tr>";
}
$("#previewTbody").html(rows);
$("#previewPanel").show();
}
function doConfirm() {
if (!lastPreview || !lastPreview.pending || lastPreview.pending <= 0) { return; }
var code = lastPreview.inboundCode;
$.modal.confirm("确认按批次 [" + code + "] 一次性入库 " + lastPreview.pending + " 条?", function () {
$.modal.loading("正在入库...");
$.ajax({
url: prefix + "/receive",
type: "post",
data: { inboundCode: code },
success: function (res) {
$.modal.closeLoading();
if (res.code !== 0) { $.modal.alertError(res.msg); return; }
$.modal.msgSuccess("已入库 " + res.data + " 条");
doPreview();
},
error: function () {
$.modal.closeLoading();
$.modal.alertError("网络异常,请重试");
}
});
});
}
</script>
</body>
</html>

@ -76,6 +76,7 @@
<script th:inline="javascript">
var prefix = ctx + "tyre/tyre";
var stockType = [[${stockType}]];
var datas = [[${@dict.getType('tyre_type')}]];
$(function() {
var options = {
@ -131,8 +132,8 @@
}, {
field: 'tyreType',
title: '轮胎类型',
formatter: function(value) {
return $.common.isEmpty(value) ? stockType : value;
formatter: function(value, row, index) {
return $.table.selectDictLabel(datas, value);
}
}, {
field: 'tyreBrand',

@ -185,8 +185,10 @@
<div>
<div class="summary-name" th:text="'胎号:' + ${tyre.tyreNo}">胎号:-</div>
<div class="summary-meta">
<div th:text="'所属场站:' + (${#strings.isEmpty(tyre.deptName)} ? '-' : tyre.deptName)">所属场站:-</div>
<div th:text="'所属车队:' + (${#strings.isEmpty(tyre.team)} ? '-' : tyre.team)">所属车队:-</div>
<div th:text="'所在车辆:' + ${#strings.isEmpty(tyre.carNo) ? '-' : tyre.carNo}">所在车辆:-</div>
<div th:text="'所属公司:' + ${#strings.isEmpty(tyre.company) ? '-' : tyre.company}">所属公司:-</div>
<div th:text="'所属修理厂:' + ${#strings.isEmpty(tyre.team) ? '-' : tyre.team}">所属修理厂:-</div>
<div th:text="'所属车队:' + ${#strings.isEmpty(tyre.carTeam) ? '-' : tyre.carTeam}">所属车队:-</div>
</div>
<span class="summary-link" th:text="${tyre.tyreNo}">-</span>
</div>
@ -244,8 +246,8 @@
<!-- <td th:text="${tyreStatusText}">在库</td>-->
<!-- </tr>-->
<tr>
<th>轮胎类</th>
<td th:text="${#strings.isEmpty(tyre.tyreType) ? '-' : tyre.tyreType}">-</td>
<th>轮胎类</th>
<td th:text="${#strings.isEmpty(tyre.tyreType) ? '-' : @dict.getLabel('tyre_type', tyre.tyreType)}">-</td>
<th>初始花纹深度(mm)</th>
<td th:text="${#strings.isEmpty(tyre.patternDepth) ? '-' : tyre.patternDepth}">-</td>
<!-- <th>剩余花纹深度(mm)</th>-->

@ -22,6 +22,10 @@
<p>轮胎芯片:</p>
<input type="text" name="tyreEpc"/>
</li>
<li>
<p>入库编码:</p>
<input type="text" name="inboundCode"/>
</li>
<li>
轮胎品牌:<select name="tyreBrand" th:with="type=${@dict.getType('brand')}">
<option value="">所有</option>
@ -76,6 +80,9 @@
<a class="btn btn-info" onclick="$.table.importExcel()" shiro:hasPermission="tyre:tyre:import">
<i class="fa fa-upload"></i> 导入
</a>
<a class="btn btn-info" onclick="openReceive()" shiro:hasPermission="tyre:tyre:receive">
<i class="fa fa-inbox"></i> 收货
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
@ -88,6 +95,7 @@
var removeFlag = [[${@permission.hasPermi('tyre:tyre:remove')}]];
var prefix = ctx + "tyre/tyre";
var datas = [[${@dict.getType('tyre_type')}]];
var inventoryStatusDict = [[${@dict.getType('inventory_status')}]];
// 1. 定义点击后的处理函数
function showDetail(tyreId) {
// 这里使用了若依框架常用的 $.modal.open 方法
@ -157,6 +165,17 @@
formatter: function(value, row, index) {
return $.table.selectDictLabel(datas, value);
}
},
{
field : 'inventoryStatus',
title : '库存状态',
formatter: function(value, row, index) {
// 约定base_tyre.inventory_status 为空表示“已发货待入库”(批量导入默认态),非空按字典 inventory_status 翻译
if ($.common.isEmpty(value)) {
return '<span class="label label-warning">已发货待入库</span>';
}
return $.table.selectDictLabel(inventoryStatusDict, value);
}
},
{
field : 'carNo',
@ -190,6 +209,10 @@
field : 'createBy',
title : '创建人'
},
{
field : 'inboundCode',
title : '入库编码'
},
{
title: '操作',
align: 'center',
@ -203,20 +226,27 @@
};
$.table.init(options);
});
function openReceive() {
var url = ctx + "tyre/tyre/receive";
$.modal.openOptions({ title: "收货", url: url, width: 720, height: 520 });
}
</script>
<script id="importTpl" type="text/template">
<form enctype="multipart/form-data" class="mt20 mb10">
<div class="col-xs-offset-1">
<input type="file" id="file" name="file"/>
<div class="mt10 pt5">
<input type="checkbox" id="updateSupport" name="updateSupport" title="如果轮胎已经存在,更新这条数据。"> 是否更新已经存在的轮胎数据
&nbsp; <a onclick="$.table.importTemplate()" class="btn btn-default btn-xs"><i class="fa fa-file-excel-o"></i> 下载模板</a>
</div>
<font color="red" class="pull-left mt10">
提示仅允许导入“xls”或“xlsx”格式文件
</font>
<div class="mt10 pt5">
<input type="checkbox" id="updateSupport" name="updateSupport" title="如果轮胎已经存在,更新这条数据。"> 是否更新已经存在的轮胎数据
&nbsp; <a onclick="$.table.importTemplate()" class="btn btn-default btn-xs"><i class="fa fa-file-excel-o"></i> 下载模板</a>
</div>
<div class="mt10 pt5 text-danger">
入库编码填写说明Excel 第一行必须填写默认入库编码,后续空行自动沿用最近一次出现的编码;如中途填写新编码,则从该行开始切换为新批次,直到再次填写其他编码。
</div>
<font color="red" class="pull-left mt10">
提示仅允许导入“xls”或“xlsx”格式文件
</font>
</div>
</form>
</script>
</body>
</html>
</html>

@ -35,6 +35,10 @@ public class BaseTyre extends BaseEntity
@Excel(name = "RFID标签")
private String tyreEpc;
/** 入库编码 */
@Excel(name = "入库编码", prompt = "第一行必填;后续空行继承最近一次出现的编码;中途填写新编码则从该行开始切换批次。")
private String inboundCode;
/** 轮胎品牌 */
@Excel(name = "轮胎品牌")
private String tyreBrand;
@ -52,8 +56,6 @@ public class BaseTyre extends BaseEntity
private String tyrePattern;
@Excel(name = "轮胎初始深度")
private String patternDepth;
@Excel(name = "标准气压")
private String pressure;
@Excel(name = "轮胎沟槽数")
private String grooves;
/** 轮胎类别 */
@ -76,6 +78,11 @@ public class BaseTyre extends BaseEntity
@Excel(name = "所在轮位")
private String wheelPostion;
/**
* inventory_status
*
*/
private String inventoryStatus;
public String getPressure() {
return pressure;
}
@ -136,6 +143,15 @@ public class BaseTyre extends BaseEntity
this.selfNo = selfNo;
}
public String getInboundCode() {
return inboundCode;
}
public void setInboundCode(String inboundCode) {
// 供应商 Excel 容易带前后空格,统一收口避免同一批次因空格拆成两个编码。
this.inboundCode = inboundCode == null ? null : inboundCode.trim();
}
public Long getDeptId() {
return deptId;
}
@ -160,6 +176,14 @@ public class BaseTyre extends BaseEntity
this.wheelPostion = wheelPostion;
}
public String getInventoryStatus() {
return inventoryStatus;
}
public void setInventoryStatus(String inventoryStatus) {
this.inventoryStatus = inventoryStatus;
}
public void setTyreId(Long tyreId)
{
this.tyreId = tyreId;
@ -261,7 +285,9 @@ public class BaseTyre extends BaseEntity
.append("tyreNo", getTyreNo())
.append("tyreEpc", getTyreEpc())
.append("inboundCode", getInboundCode())
.append("tyreBrand", getTyreBrand())
.append("tyreModel", getTyreModel())
@ -275,7 +301,9 @@ public class BaseTyre extends BaseEntity
.append("team", getTeam())
.append("deptName", getDeptName())
.append("inventoryStatus", getInventoryStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())

@ -0,0 +1,146 @@
package com.ruoyi.system.domain;
import java.io.Serializable;
import java.util.Date;
/**
* DTO
* <p>
* /Tab
* record_check
* </p>
*/
public class CarCheckLifecycleDTO implements Serializable
{
private static final long serialVersionUID = 1L;
/** 质检记录主键ID对应 record_check.id。 */
private Long id;
/** 轮胎RFID编码唯一标识一条轮胎实物。 */
private String tyreRfid;
/** 轮胎自编号(轮胎编号),业务展示用。 */
private String tyreNo;
/** 轮胎品牌,例如:米其林、普利司通等。 */
private String tyreBrand;
/** 轮胎规格型号例如295/80R22.5。 */
private String tyreModel;
/** 质检结果,例如:合格、不合格、建议更换等字典值。 */
private String result;
/** 质检时的维保类型/检测类型,例如:一级保养、二级保养、日常巡检。 */
private String maintenanceType;
/** 质检时记录的行驶里程(字符串形式保留原始录入值)。 */
private String mileage;
/** 质检时测量的花纹深度(毫米),用于评估轮胎磨损程度。 */
private String patternDepth;
/** 质检记录创建时间,即质检实际发生时间。 */
private Date createTime;
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getTyreRfid()
{
return tyreRfid;
}
public void setTyreRfid(String tyreRfid)
{
this.tyreRfid = tyreRfid;
}
public String getTyreNo()
{
return tyreNo;
}
public void setTyreNo(String tyreNo)
{
this.tyreNo = tyreNo;
}
public String getTyreBrand()
{
return tyreBrand;
}
public void setTyreBrand(String tyreBrand)
{
this.tyreBrand = tyreBrand;
}
public String getTyreModel()
{
return tyreModel;
}
public void setTyreModel(String tyreModel)
{
this.tyreModel = tyreModel;
}
public String getResult()
{
return result;
}
public void setResult(String result)
{
this.result = result;
}
public String getMaintenanceType()
{
return maintenanceType;
}
public void setMaintenanceType(String maintenanceType)
{
this.maintenanceType = maintenanceType;
}
public String getMileage()
{
return mileage;
}
public void setMileage(String mileage)
{
this.mileage = mileage;
}
public String getPatternDepth()
{
return patternDepth;
}
public void setPatternDepth(String patternDepth)
{
this.patternDepth = patternDepth;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
}

@ -0,0 +1,109 @@
package com.ruoyi.system.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* DTO
* <p>
*
* 线
*
* </p>
*/
public class CarLifecycleDTO implements Serializable
{
private static final long serialVersionUID = 1L;
/** 车辆主档概要,用于弹窗头部确认当前报表对象。包含车牌号、所属车队、线路、车型及最近录入里程。 */
private CarLifecycleSummaryDTO car;
/** 当前装车轮胎快照,数量较少(通常不超过车辆轮位数),随概要一次返回用于首屏快速展示。 */
private List<CarMountedTyreDTO> mountedTyres = new ArrayList<>();
/** 最近事件时间线,聚合装卸与维保两类关键事件,按时间倒序排列,用于快速定位最新动作。 */
private List<CarLifecycleEventDTO> recentEvents = new ArrayList<>();
/** 该车辆历史轮胎装卸记录总条数,用于前端分页组件初始化总页数。 */
private Integer installCount;
/** 该车辆关联维保工单总条数,用于前端分页组件初始化总页数。 */
private Integer maintenanceCount;
/** 该车辆关联轮胎质检记录总条数,用于前端分页组件初始化总页数。 */
private Integer checkCount;
/** 该车辆关联轮胎里程记录总条数,用于前端分页组件初始化总页数。 */
private Integer mileageCount;
public CarLifecycleSummaryDTO getCar()
{
return car;
}
public void setCar(CarLifecycleSummaryDTO car)
{
this.car = car;
}
public List<CarMountedTyreDTO> getMountedTyres()
{
return mountedTyres;
}
public void setMountedTyres(List<CarMountedTyreDTO> mountedTyres)
{
this.mountedTyres = mountedTyres;
}
public List<CarLifecycleEventDTO> getRecentEvents()
{
return recentEvents;
}
public void setRecentEvents(List<CarLifecycleEventDTO> recentEvents)
{
this.recentEvents = recentEvents;
}
public Integer getInstallCount()
{
return installCount;
}
public void setInstallCount(Integer installCount)
{
this.installCount = installCount;
}
public Integer getMaintenanceCount()
{
return maintenanceCount;
}
public void setMaintenanceCount(Integer maintenanceCount)
{
this.maintenanceCount = maintenanceCount;
}
public Integer getCheckCount()
{
return checkCount;
}
public void setCheckCount(Integer checkCount)
{
this.checkCount = checkCount;
}
public Integer getMileageCount()
{
return mileageCount;
}
public void setMileageCount(Integer mileageCount)
{
this.mileageCount = mileageCount;
}
}

@ -0,0 +1,304 @@
package com.ruoyi.system.domain;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* DTO
* <p>
* 线
* 便eventType
* INSTALL MAINTENANCE
* </p>
*/
public class CarLifecycleEventDTO implements Serializable
{
private static final long serialVersionUID = 1L;
/** 事件类型字典值区分数据来源。例如INSTALL轮胎装卸、MAINTENANCE维保工单。 */
private String eventType;
/** 事件发生时间,统一取各来源表中的操作/创建时间,用于时间轴排序。 */
private Date eventTime;
/** 轮胎RFID编码仅在事件类型为轮胎装卸时有效。 */
private String tyreRfid;
/** 轮胎编号,业务展示用。 */
private String tyreNo;
/** 轮胎自编号,与 tyreNo 区分,用于内部管理。 */
private String selfNo;
/** 轮胎品牌。 */
private String tyreBrand;
/** 轮胎规格型号。 */
private String tyreModel;
/** 轮位名称,例如:左前轮、右后第二轴等,仅在装卸事件中有效。 */
private String wheelPostion;
/** 事件关联的行驶里程(字符串形式,保留原始录入格式)。 */
private String mileage;
/** 事件关联的花纹深度(毫米),用于磨损评估。 */
private String patternDepth;
/** 状态字典值,例如:工单状态、轮胎状态等,视 eventType 而定。 */
private String status;
/** 工单编号,仅在事件类型为维保工单时有效。 */
private String orderNo;
/** 类型编码,例如:维保类型字典值、操作类型字典值。 */
private String typeCode;
/** 修理厂/工厂名称,仅在维保工单事件中有效。 */
private String factoryName;
/** 录入里程(数值型),维保工单或质检记录中由用户录入的当前总里程。 */
private BigDecimal inputMileage;
/** 上次里程(数值型),维保工单中记录的上一次保养时的里程。 */
private BigDecimal lastMileage;
/** 保养/维修日期,维保工单事件中的计划或实际执行日期。 */
private Date maintainDate;
/** 事件描述/故障描述,维保工单中的故障现象或备注信息。 */
private String description;
/** 质检结果,仅在轮胎质检相关事件中有效。 */
private String result;
/** 维保/检测类型字典值,例如:一级保养、二级保养、日常巡检。 */
private String maintenanceType;
/** 轮胎里程记录开始时间,仅在里程类事件中有效。 */
private Date startTime;
/** 轮胎里程记录结束时间,仅在里程类事件中有效。 */
private Date endTime;
public String getEventType()
{
return eventType;
}
public void setEventType(String eventType)
{
this.eventType = eventType;
}
public Date getEventTime()
{
return eventTime;
}
public void setEventTime(Date eventTime)
{
this.eventTime = eventTime;
}
public String getTyreRfid()
{
return tyreRfid;
}
public void setTyreRfid(String tyreRfid)
{
this.tyreRfid = tyreRfid;
}
public String getTyreNo()
{
return tyreNo;
}
public void setTyreNo(String tyreNo)
{
this.tyreNo = tyreNo;
}
public String getSelfNo()
{
return selfNo;
}
public void setSelfNo(String selfNo)
{
this.selfNo = selfNo;
}
public String getTyreBrand()
{
return tyreBrand;
}
public void setTyreBrand(String tyreBrand)
{
this.tyreBrand = tyreBrand;
}
public String getTyreModel()
{
return tyreModel;
}
public void setTyreModel(String tyreModel)
{
this.tyreModel = tyreModel;
}
public String getWheelPostion()
{
return wheelPostion;
}
public void setWheelPostion(String wheelPostion)
{
this.wheelPostion = wheelPostion;
}
public String getMileage()
{
return mileage;
}
public void setMileage(String mileage)
{
this.mileage = mileage;
}
public String getPatternDepth()
{
return patternDepth;
}
public void setPatternDepth(String patternDepth)
{
this.patternDepth = patternDepth;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
public String getOrderNo()
{
return orderNo;
}
public void setOrderNo(String orderNo)
{
this.orderNo = orderNo;
}
public String getTypeCode()
{
return typeCode;
}
public void setTypeCode(String typeCode)
{
this.typeCode = typeCode;
}
public String getFactoryName()
{
return factoryName;
}
public void setFactoryName(String factoryName)
{
this.factoryName = factoryName;
}
public BigDecimal getInputMileage()
{
return inputMileage;
}
public void setInputMileage(BigDecimal inputMileage)
{
this.inputMileage = inputMileage;
}
public BigDecimal getLastMileage()
{
return lastMileage;
}
public void setLastMileage(BigDecimal lastMileage)
{
this.lastMileage = lastMileage;
}
public Date getMaintainDate()
{
return maintainDate;
}
public void setMaintainDate(Date maintainDate)
{
this.maintainDate = maintainDate;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public String getResult()
{
return result;
}
public void setResult(String result)
{
this.result = result;
}
public String getMaintenanceType()
{
return maintenanceType;
}
public void setMaintenanceType(String maintenanceType)
{
this.maintenanceType = maintenanceType;
}
public Date getStartTime()
{
return startTime;
}
public void setStartTime(Date startTime)
{
this.startTime = startTime;
}
public Date getEndTime()
{
return endTime;
}
public void setEndTime(Date endTime)
{
this.endTime = endTime;
}
}

@ -0,0 +1,55 @@
package com.ruoyi.system.domain;
import com.ruoyi.common.core.domain.BaseEntity;
/**
*
* <p>
* {@link BaseEntity}pageNum / pageSize
* deptAlias / userAlias
*
* carNo Service carId使 carId
* </p>
*/
public class CarLifecycleQuery extends BaseEntity
{
private static final long serialVersionUID = 1L;
/**
*
* <p>
* Service
* varchar(50)
* </p>
*/
private String carNo;
/**
* ID Service
* <p>
*
*
* </p>
*/
private Long carId;
public String getCarNo()
{
return carNo;
}
public void setCarNo(String carNo)
{
this.carNo = carNo;
}
public Long getCarId()
{
return carId;
}
public void setCarId(Long carId)
{
this.carId = carId;
}
}

@ -0,0 +1,113 @@
package com.ruoyi.system.domain;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* DTO
* <p>
*
* base_car / {@link BaseCarLifecycleMapper#selectLifecycleCar}
* </p>
*/
public class CarLifecycleSummaryDTO implements Serializable
{
private static final long serialVersionUID = 1L;
/** 车辆主键IDbase_car 表的唯一标识,用于后续子查询精确关联。 */
private Long carId;
/** 车牌号车辆的唯一业务标识例如粤B12345。 */
private String carNo;
/** 所属部门ID关联 sys_dept用于数据权限过滤。 */
private Long deptId;
/** 所属车队名称由部门ID关联翻译而来前端直接展示。 */
private String team;
/** 线路名称,车辆运营的公交/客运线路。 */
private String line;
/** 车型,例如:纯电动大巴、混合动力公交等字典值。 */
private String type;
/**
*
* <p>
* input_mileage
* 使 BigDecimal
* </p>
*/
private BigDecimal inputMileage;
public Long getCarId()
{
return carId;
}
public void setCarId(Long carId)
{
this.carId = carId;
}
public String getCarNo()
{
return carNo;
}
public void setCarNo(String carNo)
{
this.carNo = carNo;
}
public Long getDeptId()
{
return deptId;
}
public void setDeptId(Long deptId)
{
this.deptId = deptId;
}
public String getTeam()
{
return team;
}
public void setTeam(String team)
{
this.team = team;
}
public String getLine()
{
return line;
}
public void setLine(String line)
{
this.line = line;
}
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
public BigDecimal getInputMileage()
{
return inputMileage;
}
public void setInputMileage(BigDecimal inputMileage)
{
this.inputMileage = inputMileage;
}
}

@ -0,0 +1,160 @@
package com.ruoyi.system.domain;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* DTO
* <p>
* Tab
* biz_maintenance_order plate_number
* </p>
*/
public class CarMaintenanceLifecycleDTO implements Serializable
{
private static final long serialVersionUID = 1L;
/** 工单主键ID对应 biz_maintenance_order.order_id。 */
private Long orderId;
/** 工单编号业务展示的唯一编号例如WB202401150001。 */
private String orderNo;
/** 车辆ID对应工单表中的 vehicle_id 外键(若存在)。 */
private Long vehicleId;
/** 车牌号,工单中直接记录的车牌号,用于与车辆主档确认关联。 */
private String plateNumber;
/** 维保类型编码,字典值,例如:一级保养、二级保养、小修、大修。 */
private String typeCode;
/** 工单状态编码,字典值,例如:待派工、维修中、已完成、已结算。 */
private String status;
/** 录入里程,本次维保/保养时车辆的总行驶里程(数值型)。 */
private BigDecimal inputMileage;
/** 上次里程,上一次保养时记录的里程,用于计算两次保养间的行驶距离。 */
private BigDecimal lastMileage;
/** 保养/维修日期,工单的计划或实际执行日期。 */
private Date maintainDate;
/** 修理厂名称,执行本次维保的外部或内部修理厂。 */
private String factoryName;
/** 故障描述/备注,记录车辆故障现象、维修内容或用户补充说明。 */
private String description;
public Long getOrderId()
{
return orderId;
}
public void setOrderId(Long orderId)
{
this.orderId = orderId;
}
public String getOrderNo()
{
return orderNo;
}
public void setOrderNo(String orderNo)
{
this.orderNo = orderNo;
}
public Long getVehicleId()
{
return vehicleId;
}
public void setVehicleId(Long vehicleId)
{
this.vehicleId = vehicleId;
}
public String getPlateNumber()
{
return plateNumber;
}
public void setPlateNumber(String plateNumber)
{
this.plateNumber = plateNumber;
}
public String getTypeCode()
{
return typeCode;
}
public void setTypeCode(String typeCode)
{
this.typeCode = typeCode;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
public BigDecimal getInputMileage()
{
return inputMileage;
}
public void setInputMileage(BigDecimal inputMileage)
{
this.inputMileage = inputMileage;
}
public BigDecimal getLastMileage()
{
return lastMileage;
}
public void setLastMileage(BigDecimal lastMileage)
{
this.lastMileage = lastMileage;
}
public Date getMaintainDate()
{
return maintainDate;
}
public void setMaintainDate(Date maintainDate)
{
this.maintainDate = maintainDate;
}
public String getFactoryName()
{
return factoryName;
}
public void setFactoryName(String factoryName)
{
this.factoryName = factoryName;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
}

@ -0,0 +1,120 @@
package com.ruoyi.system.domain;
import java.io.Serializable;
import java.util.Date;
/**
* DTO
* <p>
* Tab
* RFID record_tyre_mileage
* </p>
*/
public class CarMileageLifecycleDTO implements Serializable
{
private static final long serialVersionUID = 1L;
/** 里程记录主键ID对应 record_tyre_mileage.id。 */
private Long id;
/** 轮胎RFID编码唯一标识轮胎实物关联 record_tyre_mileage 中的轮胎标识。 */
private String tyreRfid;
/** 轮胎编号,业务展示用。 */
private String tyreNo;
/** 轮胎品牌。 */
private String tyreBrand;
/** 里程统计开始时间,即该轮胎装车或本次统计周期的起始时间点。 */
private Date startTime;
/** 里程统计结束时间,即该轮胎卸车或本次统计周期的结束时间点。 */
private Date endTime;
/** 该统计周期内累计行驶里程(公里),数值型。 */
private Long mileage;
/** 统计结束时的花纹深度(毫米),用于与起始深度对比评估磨损速率。 */
private String patternDepth;
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getTyreRfid()
{
return tyreRfid;
}
public void setTyreRfid(String tyreRfid)
{
this.tyreRfid = tyreRfid;
}
public String getTyreNo()
{
return tyreNo;
}
public void setTyreNo(String tyreNo)
{
this.tyreNo = tyreNo;
}
public String getTyreBrand()
{
return tyreBrand;
}
public void setTyreBrand(String tyreBrand)
{
this.tyreBrand = tyreBrand;
}
public Date getStartTime()
{
return startTime;
}
public void setStartTime(Date startTime)
{
this.startTime = startTime;
}
public Date getEndTime()
{
return endTime;
}
public void setEndTime(Date endTime)
{
this.endTime = endTime;
}
public Long getMileage()
{
return mileage;
}
public void setMileage(Long mileage)
{
this.mileage = mileage;
}
public String getPatternDepth()
{
return patternDepth;
}
public void setPatternDepth(String patternDepth)
{
this.patternDepth = patternDepth;
}
}

@ -0,0 +1,120 @@
package com.ruoyi.system.domain;
import java.io.Serializable;
/**
* DTO
* <p>
*
*
* record_tyre_install
* </p>
*/
public class CarMountedTyreDTO implements Serializable
{
private static final long serialVersionUID = 1L;
/** 轮胎主键ID对应 base_tyre.id。 */
private Long tyreId;
/** 轮胎编号,业务展示的唯一编号。 */
private String tyreNo;
/** 轮胎自编号,与 tyreNo 区分,用于仓库或车队内部管理。 */
private String selfNo;
/** 轮胎RFID/EPC编码物联网识别标签用于RFID读写器扫描匹配。 */
private String tyreEpc;
/** 轮胎品牌,例如:米其林、固特异。 */
private String tyreBrand;
/** 轮胎规格型号例如12R22.5、295/80R22.5。 */
private String tyreModel;
/** 轮位名称,例如:左前转向轮、右后驱动轴第二轴等,指示轮胎安装在车辆的具体位置。 */
private String wheelPostion;
/** 当前花纹深度(毫米),反映轮胎剩余磨损寿命,用于安全预警。 */
private String patternDepth;
public Long getTyreId()
{
return tyreId;
}
public void setTyreId(Long tyreId)
{
this.tyreId = tyreId;
}
public String getTyreNo()
{
return tyreNo;
}
public void setTyreNo(String tyreNo)
{
this.tyreNo = tyreNo;
}
public String getSelfNo()
{
return selfNo;
}
public void setSelfNo(String selfNo)
{
this.selfNo = selfNo;
}
public String getTyreEpc()
{
return tyreEpc;
}
public void setTyreEpc(String tyreEpc)
{
this.tyreEpc = tyreEpc;
}
public String getTyreBrand()
{
return tyreBrand;
}
public void setTyreBrand(String tyreBrand)
{
this.tyreBrand = tyreBrand;
}
public String getTyreModel()
{
return tyreModel;
}
public void setTyreModel(String tyreModel)
{
this.tyreModel = tyreModel;
}
public String getWheelPostion()
{
return wheelPostion;
}
public void setWheelPostion(String wheelPostion)
{
this.wheelPostion = wheelPostion;
}
public String getPatternDepth()
{
return patternDepth;
}
public void setPatternDepth(String patternDepth)
{
this.patternDepth = patternDepth;
}
}

@ -0,0 +1,160 @@
package com.ruoyi.system.domain;
import java.io.Serializable;
import java.util.Date;
/**
* DTO
* <p>
* /Tab
* record_tyre_install car_no
*
* </p>
*/
public class CarTyreInstallLifecycleDTO implements Serializable
{
private static final long serialVersionUID = 1L;
/** 装卸记录主键ID对应 record_tyre_install.id。 */
private Long id;
/** 轮胎RFID编码唯一标识被操作的轮胎实物。 */
private String tyreRfid;
/** 操作类型字典值例如INSTALL安装、UNINSTALL卸下、SWAP换位。 */
private String installType;
/** 操作时的车辆行驶里程(公里),数值型,记录动作发生瞬间的车辆总里程。 */
private Long mileage;
/** 操作发生时间,即装卸动作的实际执行时间/录入时间。 */
private Date createTime;
/** 轮位名称,例如:左前轮、右后第二轴,指示轮胎安装或卸下的具体位置。 */
private String wheelPostion;
/** 操作时的花纹深度(毫米),用于追溯轮胎在每次装卸时的磨损状态。 */
private String patternDepth;
/** 轮胎编号,被操作轮胎的业务展示编号。 */
private String tyreNo;
/** 轮胎自编号,被操作轮胎的内部管理编号。 */
private String selfNo;
/** 轮胎品牌。 */
private String tyreBrand;
/** 轮胎规格型号。 */
private String tyreModel;
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getTyreRfid()
{
return tyreRfid;
}
public void setTyreRfid(String tyreRfid)
{
this.tyreRfid = tyreRfid;
}
public String getInstallType()
{
return installType;
}
public void setInstallType(String installType)
{
this.installType = installType;
}
public Long getMileage()
{
return mileage;
}
public void setMileage(Long mileage)
{
this.mileage = mileage;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public String getWheelPostion()
{
return wheelPostion;
}
public void setWheelPostion(String wheelPostion)
{
this.wheelPostion = wheelPostion;
}
public String getPatternDepth()
{
return patternDepth;
}
public void setPatternDepth(String patternDepth)
{
this.patternDepth = patternDepth;
}
public String getTyreNo()
{
return tyreNo;
}
public void setTyreNo(String tyreNo)
{
this.tyreNo = tyreNo;
}
public String getSelfNo()
{
return selfNo;
}
public void setSelfNo(String selfNo)
{
this.selfNo = selfNo;
}
public String getTyreBrand()
{
return tyreBrand;
}
public void setTyreBrand(String tyreBrand)
{
this.tyreBrand = tyreBrand;
}
public String getTyreModel()
{
return tyreModel;
}
public void setTyreModel(String tyreModel)
{
this.tyreModel = tyreModel;
}
}

@ -6,6 +6,7 @@ import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.apache.poi.ss.usermodel.IndexedColors;
public class BaseTyreVo {
private static final long serialVersionUID = 1L;
@ -38,6 +39,12 @@ public class BaseTyreVo {
@Excel(name = "轮胎沟槽数")
private String grooves;
/** 入库编码 */
@Excel(name = "入库编码", color = IndexedColors.RED,
prompt = "Excel 第一行必须填写默认入库编码,后续空行自动沿用最近一次出现的编码;" +
"如中途填写新编码,则从该行开始切换为新批次,直到再次填写其他编码。" )
private String inboundCode;
public @NotBlank(message = "胎号不能为空") String getTyreNo() {
return tyreNo;
}
@ -54,6 +61,15 @@ public class BaseTyreVo {
this.tyreEpc = tyreEpc;
}
public String getInboundCode() {
return inboundCode;
}
public void setInboundCode(String inboundCode) {
// 入库编码是批量入库的业务键,导入阶段先去空格,避免后续按编码查询不到。
this.inboundCode = inboundCode == null ? null : inboundCode.trim();
}
public String getTyreBrand() {
return tyreBrand;
}

@ -0,0 +1,69 @@
package com.ruoyi.system.domain.vo;
/**
*
*
* @author zch
*/
public class InboundBatchPreviewItemVo
{
private String tyreEpc; // 轮胎 RFID/EPC 唯一标识
private String tyreNo; // 轮胎外部编号
private String tyreBrand; // 轮胎品牌
private String tyreModel; // 轮胎型号
private String status; // 状态:待入库 / 已存在库存记录
public String getTyreEpc()
{
return tyreEpc;
}
public void setTyreEpc(String tyreEpc)
{
this.tyreEpc = tyreEpc;
}
public String getTyreNo()
{
return tyreNo;
}
public void setTyreNo(String tyreNo)
{
this.tyreNo = tyreNo;
}
public String getTyreBrand()
{
return tyreBrand;
}
public void setTyreBrand(String tyreBrand)
{
this.tyreBrand = tyreBrand;
}
public String getTyreModel()
{
return tyreModel;
}
public void setTyreModel(String tyreModel)
{
this.tyreModel = tyreModel;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
}

@ -0,0 +1,71 @@
package com.ruoyi.system.domain.vo;
import java.util.List;
/**
*
*
* @author zch
*/
public class InboundBatchPreviewVo
{
private String inboundCode; // 入库编码
private int total; // 批次轮胎总数
private int exists; // 已存在库存记录的数量
private int pending; // 待入库数量total - exists
private List<InboundBatchPreviewItemVo> items; // 批次明细列表
public String getInboundCode()
{
return inboundCode;
}
public void setInboundCode(String inboundCode)
{
this.inboundCode = inboundCode;
}
public int getTotal()
{
return total;
}
public void setTotal(int total)
{
this.total = total;
}
public int getExists()
{
return exists;
}
public void setExists(int exists)
{
this.exists = exists;
}
public int getPending()
{
return pending;
}
public void setPending(int pending)
{
this.pending = pending;
}
public List<InboundBatchPreviewItemVo> getItems()
{
return items;
}
public void setItems(List<InboundBatchPreviewItemVo> items)
{
this.items = items;
}
}

@ -0,0 +1,152 @@
package com.ruoyi.system.mapper;
import java.util.List;
import com.ruoyi.system.domain.CarCheckLifecycleDTO;
import com.ruoyi.system.domain.CarLifecycleEventDTO;
import com.ruoyi.system.domain.CarLifecycleQuery;
import com.ruoyi.system.domain.CarLifecycleSummaryDTO;
import com.ruoyi.system.domain.CarMaintenanceLifecycleDTO;
import com.ruoyi.system.domain.CarMileageLifecycleDTO;
import com.ruoyi.system.domain.CarMountedTyreDTO;
import com.ruoyi.system.domain.CarTyreInstallLifecycleDTO;
/**
* Mapper
* <p>
*
*
* 1. carNo join sys_dept {@link DataScope}
* 2. selectLifecycleCar / selectMountedTyres / selectRecentEvents / count*select*List
* 3. 使 carId
* </p>
*/
public interface BaseCarLifecycleMapper
{
/**
*
* <p>
* SQL join sys_dept d/u {@link DataScope} /
* Service 访
* </p>
*
* @param query carNo
* @return DTO null
*/
public CarLifecycleSummaryDTO selectLifecycleCar(CarLifecycleQuery query);
/**
*
* <p>
* <=
* installType='INSTALL'
* </p>
*
* @param query carId
* @return
*/
public List<CarMountedTyreDTO> selectMountedTyres(CarLifecycleQuery query);
/**
* 线TopN
* <p>
* N 10
*
* </p>
*
* @param query carId
* @return
*/
public List<CarLifecycleEventDTO> selectRecentEvents(CarLifecycleQuery query);
/**
*
* <p>
*
* pageNum / pageSize使
* </p>
*
* @param query carId
* @return
*/
public List<CarTyreInstallLifecycleDTO> selectInstallList(CarLifecycleQuery query);
/**
*
* <p>
* plate_number = carNo biz_maintenance_order
* maintain_date
* </p>
*
* @param query carId
* @return
*/
public List<CarMaintenanceLifecycleDTO> selectMaintenanceList(CarLifecycleQuery query);
/**
*
* <p>
* RFID record_check
* SQL 使 join record_tyre_install
* </p>
*
* @param query carId
* @return
*/
public List<CarCheckLifecycleDTO> selectCheckList(CarLifecycleQuery query);
/**
*
* <p>
* RFID record_tyre_mileage
*
* </p>
*
* @param query carId
* @return
*/
public List<CarMileageLifecycleDTO> selectMileageList(CarLifecycleQuery query);
/**
*
* <p>
* installCount
* </p>
*
* @param query carId
* @return 0
*/
public int countInstallRecords(CarLifecycleQuery query);
/**
*
* <p>
* maintenanceCount
* </p>
*
* @param query carId
* @return 0
*/
public int countMaintenanceOrders(CarLifecycleQuery query);
/**
*
* <p>
* checkCount
* </p>
*
* @param query carId
* @return 0
*/
public int countCheckRecords(CarLifecycleQuery query);
/**
*
* <p>
* mileageCount
* </p>
*
* @param query carId
* @return 0
*/
public int countMileageRecords(CarLifecycleQuery query);
}

@ -4,6 +4,7 @@ package com.ruoyi.system.mapper;
import com.ruoyi.common.core.domain.entity.SysDeptVo;
import com.ruoyi.system.domain.BaseInventory;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
@ -73,4 +74,14 @@ public interface BaseInventoryMapper
int queryInCar();
int queryCarTotal();
/**
* RFID
*
* @param tyreRfid RFID
* @return
*/
int deleteInStockBaseInventoryByEpc(@Param("tyreRfid") String tyreRfid);
}

@ -5,6 +5,7 @@ package com.ruoyi.system.mapper;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.system.domain.BaseTyre;
import com.ruoyi.system.domain.vo.BaseTyreVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
@ -73,5 +74,22 @@ public interface BaseTyreMapper
List<Map> vTyreStockSummary(SysDept sysDept);
/**
*
*
* @param inboundCode
* @return
*/
List<BaseTyre> selectByInboundCode(@Param("inboundCode") String inboundCode);
/**
*
*
* @param inboundCode
* @return
*/
int countBaseTyreByInboundCode(@Param("inboundCode") String inboundCode);
BaseTyre selectBaseTyreByKeyParam(BaseTyre baseTyre);
}

@ -0,0 +1,55 @@
package com.ruoyi.system.service;
import java.util.List;
import com.ruoyi.system.domain.CarCheckLifecycleDTO;
import com.ruoyi.system.domain.CarLifecycleDTO;
import com.ruoyi.system.domain.CarLifecycleQuery;
import com.ruoyi.system.domain.CarMaintenanceLifecycleDTO;
import com.ruoyi.system.domain.CarMileageLifecycleDTO;
import com.ruoyi.system.domain.CarTyreInstallLifecycleDTO;
/**
* Service
*/
public interface IBaseCarLifecycleService
{
/**
*
*
* @param query
* @return
*/
public CarLifecycleDTO selectLifecycle(CarLifecycleQuery query);
/**
*
*
* @param query
* @return
*/
public List<CarTyreInstallLifecycleDTO> selectInstallList(CarLifecycleQuery query);
/**
*
*
* @param query
* @return
*/
public List<CarMaintenanceLifecycleDTO> selectMaintenanceList(CarLifecycleQuery query);
/**
*
*
* @param query
* @return
*/
public List<CarCheckLifecycleDTO> selectCheckList(CarLifecycleQuery query);
/**
*
*
* @param query
* @return
*/
public List<CarMileageLifecycleDTO> selectMileageList(CarLifecycleQuery query);
}

@ -4,6 +4,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDeptVo;
import com.ruoyi.system.domain.BaseInventory;
import com.ruoyi.system.domain.BaseTyre;
import com.ruoyi.system.domain.vo.InboundBatchPreviewVo;
import java.util.List;
@ -74,4 +75,31 @@ public interface IBaseInventoryService
int queryInCar();
int queryCarTotal();
/**
*
*
* @param inboundCode
* @return
*/
InboundBatchPreviewVo previewBatchByCode(String inboundCode);
/**
* 使
*
* @param inboundCode
* @param operName
* @return
*/
int batchInboundByCode(String inboundCode, String operName);
/**
*
*
* @param inboundCode
* @param operName
* @return
*/
int rollbackBatchInboundByCode(String inboundCode, String operName);
}

@ -76,5 +76,14 @@ public interface IBaseTyreService
List<Map> vTyreStockSummary(SysDept sysDept);
/**
*
*
* @param inboundCode
* @return
*/
List<BaseTyre> selectBaseTyresByInboundCode(String inboundCode);
Map pdaQueryTyreTimeLine(BaseTyre baseTyre);
}

@ -0,0 +1,31 @@
package com.ruoyi.system.service;
import com.ruoyi.system.domain.BaseTyre;
/**
*
*
* @author zch
*/
public interface IInboundBatchService
{
/**
*
*
* @param tyre
* @param operName
* @param inboundCode
* @return true=false=
*/
boolean inboundOne(BaseTyre tyre, String operName, String inboundCode);
/**
*
*
* @param tyre
* @param operName
* @param inboundCode
* @return true=false=
*/
boolean rollbackOne(BaseTyre tyre, String operName, String inboundCode);
}

@ -0,0 +1,196 @@
package com.ruoyi.system.service.impl;
import java.util.List;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.CarCheckLifecycleDTO;
import com.ruoyi.system.domain.CarLifecycleDTO;
import com.ruoyi.system.domain.CarLifecycleQuery;
import com.ruoyi.system.domain.CarLifecycleSummaryDTO;
import com.ruoyi.system.domain.CarMaintenanceLifecycleDTO;
import com.ruoyi.system.domain.CarMileageLifecycleDTO;
import com.ruoyi.system.domain.CarTyreInstallLifecycleDTO;
import com.ruoyi.system.mapper.BaseCarLifecycleMapper;
import com.ruoyi.system.service.IBaseCarLifecycleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Service
* <p>
* carNo {@link #buildAuthorizedCar(CarLifecycleQuery)}
* 123 carId
* {@link DataScope}system:car:view/
* </p>
*/
@Service
public class BaseCarLifecycleServiceImpl implements IBaseCarLifecycleService
{
@Autowired
private BaseCarLifecycleMapper baseCarLifecycleMapper;
/**
*
* <p>
*
* - 线
* - mountedTyres
* - 线recentEvents
* - installCount / maintenanceCount / checkCount / mileageCount
*
* </p>
*
* @param query carNo
* @return DTO
* @throws ServiceException /
*/
@Override
@DataScope(deptAlias = "d", userAlias = "u")
public CarLifecycleDTO selectLifecycle(CarLifecycleQuery query)
{
CarLifecycleSummaryDTO car = buildAuthorizedCar(query);
CarLifecycleDTO dto = new CarLifecycleDTO();
dto.setCar(car);
dto.setMountedTyres(baseCarLifecycleMapper.selectMountedTyres(query));
dto.setRecentEvents(baseCarLifecycleMapper.selectRecentEvents(query));
dto.setInstallCount(baseCarLifecycleMapper.countInstallRecords(query));
dto.setMaintenanceCount(baseCarLifecycleMapper.countMaintenanceOrders(query));
dto.setCheckCount(baseCarLifecycleMapper.countCheckRecords(query));
dto.setMileageCount(baseCarLifecycleMapper.countMileageRecords(query));
return dto;
}
/**
* /
* <p>
*
* RFID/
* </p>
*
* @param query buildAuthorizedCar carId
* @return null
* @throws ServiceException 访
*/
@Override
@DataScope(deptAlias = "d", userAlias = "u")
public List<CarTyreInstallLifecycleDTO> selectInstallList(CarLifecycleQuery query)
{
buildAuthorizedCar(query);
return baseCarLifecycleMapper.selectInstallList(query);
}
/**
* /
* <p>
* {@code biz_maintenance_order.plate_number = carNo}
*
* maintain_date
* </p>
*
* @param query buildAuthorizedCar carId
* @return
* @throws ServiceException 访
*/
@Override
@DataScope(deptAlias = "d", userAlias = "u")
public List<CarMaintenanceLifecycleDTO> selectMaintenanceList(CarLifecycleQuery query)
{
buildAuthorizedCar(query);
return baseCarLifecycleMapper.selectMaintenanceList(query);
}
/**
* /
* <p>
*
* record_tyre_install car_no record_check
* RFID
* </p>
*
* @param query buildAuthorizedCar carId
* @return
* @throws ServiceException 访
*/
@Override
@DataScope(deptAlias = "d", userAlias = "u")
public List<CarCheckLifecycleDTO> selectCheckList(CarLifecycleQuery query)
{
buildAuthorizedCar(query);
return baseCarLifecycleMapper.selectCheckList(query);
}
/**
* /
* <p>
* record_tyre_mileage
* RFID
* 使
* </p>
*
* @param query buildAuthorizedCar carId
* @return
* @throws ServiceException 访
*/
@Override
@DataScope(deptAlias = "d", userAlias = "u")
public List<CarMileageLifecycleDTO> selectMileageList(CarLifecycleQuery query)
{
buildAuthorizedCar(query);
return baseCarLifecycleMapper.selectMileageList(query);
}
/**
*
* <p>
*
* 1. {@link #validateQuery(CarLifecycleQuery)}
* 2. Mapper SQL {@code DataScope} /d/u
* 3. null访
* 4. carId query
* </p>
*
* @param query
* @return DTO
* @throws ServiceException
*/
private CarLifecycleSummaryDTO buildAuthorizedCar(CarLifecycleQuery query)
{
validateQuery(query);
CarLifecycleSummaryDTO car = baseCarLifecycleMapper.selectLifecycleCar(query);
if (car == null)
{
// 统一“无权限”和“不存在”的提示,避免通过接口探测车辆主档是否存在。
throw new ServiceException("车辆不存在或无权限访问");
}
query.setCarId(car.getCarId());
return car;
}
/**
*
* <p>
*
* 1. query null carNo
* 2. 50 base_car.car_no varchar(50)
* 3. trim query SQL
* </p>
*
* @param query
* @throws ServiceException
*/
private void validateQuery(CarLifecycleQuery query)
{
if (query == null || StringUtils.isBlank(query.getCarNo()))
{
throw new ServiceException("车牌号不能为空");
}
String carNo = query.getCarNo().trim();
if (carNo.length() > 50)
{
// base_car.car_no 当前按 varchar(50) 设计,超长路径参数直接拒绝更利于定位异常调用。
throw new ServiceException("车牌号长度超过限制");
}
query.setCarNo(carNo);
}
}

@ -5,21 +5,27 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDeptVo;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.BaseInventory;
import com.ruoyi.system.domain.BaseTyre;
import com.ruoyi.system.domain.RecordWarehousing;
import com.ruoyi.system.domain.vo.InboundBatchPreviewItemVo;
import com.ruoyi.system.domain.vo.InboundBatchPreviewVo;
import com.ruoyi.system.mapper.BaseInventoryMapper;
import com.ruoyi.system.mapper.BaseTyreMapper;
import com.ruoyi.system.mapper.RecordWarehousingMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.IBaseInventoryService;
import com.ruoyi.system.service.IInboundBatchService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -42,6 +48,10 @@ public class BaseInventoryServiceImpl implements IBaseInventoryService
@Autowired
private SysUserMapper sysUserMapper;
@Autowired
private IInboundBatchService inboundBatchService;
private static final Logger log = LoggerFactory.getLogger(BaseInventoryServiceImpl.class);
/**
@ -153,6 +163,7 @@ public class BaseInventoryServiceImpl implements IBaseInventoryService
baseTyre.setTeam(team);
baseTyre.setCreateBy(baseInventory.getCreateBy());
baseTyre.setDeptId(sysUser.getDeptId());
baseTyre.setInventoryStatus("0"); // 入库后库存状态置为在仓
baseTyreMapper.insertBaseTyre(baseTyre);
}else {
baseTyre.setTyreId(baseTyres.getTyreId());
@ -160,6 +171,7 @@ public class BaseInventoryServiceImpl implements IBaseInventoryService
baseTyre.setTeam(team);
baseTyre.setUpdateBy(baseInventory.getCreateBy());
baseTyre.setDeptId(sysUser.getDeptId());
baseTyre.setInventoryStatus("0"); // 入库后库存状态置为在仓
baseTyreMapper.updateBaseTyre(baseTyre);
}
}
@ -222,4 +234,167 @@ public class BaseInventoryServiceImpl implements IBaseInventoryService
public int queryCarTotal() {
return baseInventoryMapper.queryCarTotal();
}
/**
*
*
* @param inboundCode
* @return
*/
@Override
public InboundBatchPreviewVo previewBatchByCode(String inboundCode) {
if (StringUtils.isEmpty(inboundCode))
{
throw new ServiceException("入库编码不能为空"); // 前置参数校验
}
String code = normalizeInboundCode(inboundCode); // 标准化入库编码,去除前后空白
List<BaseTyre> tyres = baseTyreMapper.selectByInboundCode(code); // 按编码查询批次下的所有轮胎基础档案
if (StringUtils.isEmpty(tyres))
{
throw new ServiceException("未找到入库编码为 " + code + " 的批次"); // 无数据时给出明确提示
}
// Service 层只返回业务数据,避免把 AjaxResult 这种 Web 响应模型下沉到业务层。
return buildBatchPreview(code, tyres); // 组装预览视图,统计总条数、已入库条数与待入库条数
}
/**
*
*
* @param inboundCode
* @param operName
* @return
*/
@Override
public int batchInboundByCode(String inboundCode, String operName) {
if (StringUtils.isEmpty(inboundCode))
{
throw new ServiceException("入库编码不能为空"); // 前置参数校验
}
String code = normalizeInboundCode(inboundCode); // 标准化入库编码
List<BaseTyre> tyres = baseTyreMapper.selectByInboundCode(code); // 查询批次下所有轮胎
if (StringUtils.isEmpty(tyres))
{
throw new ServiceException("未找到入库编码为 " + code + " 的批次"); // 无数据时阻断
}
int success = 0; // 统计实际成功写入库存的条数
for (BaseTyre tyre : tyres)
{
try
{
boolean inserted = inboundBatchService.inboundOne(tyre, operName, code); // 逐条调用独立事务入库
if (inserted)
{
success++; // 写入成功则计数累加
}
else
{
// 已存在库存时按幂等跳过,不计入本次成功写入条数。
log.info("批量入库跳过已在库轮胎inboundCode={}, tyreEpc={}", code, tyre.getTyreEpc()); // 记录幂等跳过日志
}
}
catch (Exception e)
{
log.error("批量入库失败inboundCode={}, tyreEpc={}", code, tyre.getTyreEpc(), e); // 单条异常不影响整体批次,仅记录日志
}
}
return success; // 返回实际成功入库条数
}
/**
*
*
* @param inboundCode
* @param operName
* @return
*/
@Override
public int rollbackBatchInboundByCode(String inboundCode, String operName) {
if (StringUtils.isEmpty(inboundCode))
{
throw new ServiceException("入库编码不能为空"); // 前置参数校验
}
String code = normalizeInboundCode(inboundCode); // 标准化入库编码
List<BaseTyre> tyres = baseTyreMapper.selectByInboundCode(code); // 查询批次下所有轮胎
if (StringUtils.isEmpty(tyres))
{
throw new ServiceException("未找到入库编码为 " + code + " 的批次"); // 无数据时阻断
}
int success = 0; // 统计实际成功撤回的条数
for (BaseTyre tyre : tyres)
{
try
{
boolean rollback = inboundBatchService.rollbackOne(tyre, operName, code); // 逐条调用独立事务撤回
if (rollback)
{
success++; // 撤回成功则计数累加
}
else
{
// 不在库或已出库的记录不能撤回,按幂等跳过,不计入成功撤回条数。
log.info("批量入库撤回跳过非在库轮胎inboundCode={}, tyreEpc={}", code, tyre.getTyreEpc()); // 记录幂等跳过日志
}
}
catch (Exception e)
{
log.error("批量入库撤回失败inboundCode={}, tyreEpc={}", code, tyre.getTyreEpc(), e); // 单条异常不影响整体批次,仅记录日志
}
}
return success; // 返回实际成功撤回条数
}
/**
*
*
* @param inboundCode
* @return
*/
private String normalizeInboundCode(String inboundCode)
{
return inboundCode.trim(); // 去除前后空白,避免首尾空格导致批次查询不一致
}
/**
*
*
* @param inboundCode
* @param tyres
* @return
*/
private InboundBatchPreviewVo buildBatchPreview(String inboundCode, List<BaseTyre> tyres)
{
int exists = 0; // 统计已入库的轮胎条数
List<InboundBatchPreviewItemVo> items = new ArrayList<>(); // 明细列表
for (BaseTyre tyre : tyres)
{
BaseInventory probe = new BaseInventory(); // 构造库存查询探针
probe.setTyreRfid(tyre.getTyreEpc()); // 按 RFID 查询库存
BaseInventory inventory = baseInventoryMapper.selectBaseInventoryByEpc(probe); // 查询当前是否已入库
if (inventory != null)
{
exists++; // 已存在库存记录则累加
}
InboundBatchPreviewItemVo item = new InboundBatchPreviewItemVo(); // 构造预览明细项
item.setTyreEpc(tyre.getTyreEpc()); // 轮胎 RFID
item.setTyreNo(tyre.getTyreNo()); // 轮胎外部编号
item.setTyreBrand(tyre.getTyreBrand()); // 轮胎品牌
item.setTyreModel(tyre.getTyreModel()); // 轮胎型号
// 预览时直接给出状态,现场可在入库前确认哪些会被跳过。
item.setStatus(inventory == null ? "待入库" : "已存在库存记录"); // 状态区分:未入库 / 已存在
items.add(item); // 加入明细列表
}
InboundBatchPreviewVo data = new InboundBatchPreviewVo(); // 构造预览结果对象
data.setInboundCode(inboundCode); // 批次入库编码
data.setTotal(tyres.size()); // 批次轮胎总数
data.setExists(exists); // 已入库数量
data.setPending(tyres.size() - exists); // 待入库数量 = 总数 - 已存在
data.setItems(items); // 明细数据
return data; // 返回预览结果
}
}

@ -10,12 +10,8 @@ import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.BaseCar;
import com.ruoyi.system.domain.BaseTyre;
import com.ruoyi.system.domain.RecordTyreInstall;
import com.ruoyi.system.domain.RecordWarehousing;
import com.ruoyi.system.domain.vo.BaseTyreVo;
import com.ruoyi.system.mapper.BaseTyreMapper;
import com.ruoyi.system.mapper.RecordTyreInstallMapper;
import com.ruoyi.system.mapper.RecordWarehousingMapper;
import com.ruoyi.system.service.IBaseTyreService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -24,8 +20,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.ruoyi.common.utils.ShiroUtils.getLoginName;
@ -176,6 +174,31 @@ public class BaseTyreServiceImpl implements IBaseTyreService
int failureNum = 0;
StringBuilder successMsg = new StringBuilder();
StringBuilder failureMsg = new StringBuilder();
String currentInboundCode = null; // 当前行生效的入库编码,空行时继承上一行
Set<String> inboundCodes = new HashSet<>(); // 收集本次导入涉及的所有入库编码,用于全局唯一校验
for (BaseTyreVo baseTyreVo : baseTyreVoList)
{
String rowInboundCode = baseTyreVo.getInboundCode(); // 读取 Excel 当前行的入库编码
if (StringUtils.isNotEmpty(rowInboundCode))
{
currentInboundCode = rowInboundCode.trim(); // 遇到非空编码时更新当前生效编码并去空白
inboundCodes.add(currentInboundCode); // 加入编码集合,后续做全局唯一校验
}
if (StringUtils.isEmpty(currentInboundCode))
{
throw new ServiceException("入库编码不能为空,请在导入模板第一行填写默认入库编码!"); // 首行及继承后仍为空则阻断导入
}
// 入库编码按 Excel 行顺序分段继承:空行沿用最近一次出现的编码,遇到新编码则切换到新批次。
baseTyreVo.setInboundCode(currentInboundCode); // 回写最终生效的入库编码到当前行
}
for (String inboundCode : inboundCodes)
{
// 入库编码只按编码本身做全局唯一校验,不绑定供应商,号段由用户自行规划。
if (baseTyreMapper.countBaseTyreByInboundCode(inboundCode) > 0)
{
throw new ServiceException("入库编码 " + inboundCode + " 已存在,请更换本批次唯一入库编码!"); // 任一编码重复即整体阻断,防止批次混用
}
}
for (BaseTyreVo baseTyreVo : baseTyreVoList)
{
@ -225,6 +248,11 @@ public class BaseTyreServiceImpl implements IBaseTyreService
return mapList;
}
@Override
public List<BaseTyre> selectBaseTyresByInboundCode(String inboundCode) {
return baseTyreMapper.selectByInboundCode(inboundCode);
}
@Override
public Map pdaQueryTyreTimeLine(BaseTyre baseTyre) {
Map map = new HashMap();

@ -0,0 +1,160 @@
package com.ruoyi.system.service.impl;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.BaseInventory;
import com.ruoyi.system.domain.BaseTyre;
import com.ruoyi.system.domain.RecordWarehousing;
import com.ruoyi.system.mapper.BaseInventoryMapper;
import com.ruoyi.system.mapper.BaseTyreMapper;
import com.ruoyi.system.mapper.RecordWarehousingMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.IInboundBatchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
/**
*
*
* @author zch
*/
@Service
public class InboundBatchServiceImpl implements IInboundBatchService
{
@Autowired
private BaseInventoryMapper baseInventoryMapper; // 库存数据访问
@Autowired
private BaseTyreMapper baseTyreMapper; // 轮胎基础档案数据访问
@Autowired
private RecordWarehousingMapper recordWarehousingMapper; // 入库流水数据访问
@Autowired
private SysUserMapper sysUserMapper; // 用户数据访问,用于读取操作人部门
/**
* 使
*
* @param tyre
* @param operName
* @param inboundCode
* @return true false
*/
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public boolean inboundOne(BaseTyre tyre, String operName, String inboundCode)
{
BaseInventory probe = new BaseInventory(); // 构造查询探针
probe.setTyreRfid(tyre.getTyreEpc()); // 按轮胎 RFID 查找库存
BaseInventory existed = baseInventoryMapper.selectBaseInventoryByEpc(probe); // 查询是否已入库
if (existed != null)
{
return false; // 已存在库存记录,幂等跳过
}
Date now = DateUtils.getNowDate(); // 获取当前系统时间
BaseInventory inventory = new BaseInventory(); // 新建库存记录
inventory.setTyreRfid(tyre.getTyreEpc()); // 绑定轮胎 RFID
inventory.setTyreOutsideId(tyre.getTyreNo()); // 绑定轮胎外部编号
inventory.setNumber(1L); // 数量默认为 1
inventory.setStatus("0"); //参考insertInventoryByPda
inventory.setCreateBy(operName); // 记录创建人
inventory.setCreateTime(now); // 记录创建时间
inventory.setUpdateTime(now); // 记录更新时间
inventory.setRemark("批量入库[" + inboundCode + "]"); // 备注携带批次号
int inventoryRows = baseInventoryMapper.insertBaseInventory(inventory); // 写入库存表
if (inventoryRows <= 0)
{
throw new ServiceException("库存写入失败"); // 写入失败则抛异常触发回滚
}
RecordWarehousing record = new RecordWarehousing(); // 新建入库流水
record.setTyreRfid(tyre.getTyreEpc()); // 绑定轮胎 RFID
record.setType("0"); // 参考insertInventoryByPda
record.setCreateBy(operName); // 记录操作人
record.setCreateTime(now); // 记录操作时间
record.setRemark("批量入库[" + inboundCode + "]"); // 备注携带批次号
int recordRows = recordWarehousingMapper.insertRecordWarehousing(record); // 写入流水表
if (recordRows <= 0)
{
throw new ServiceException("入库流水写入失败"); // 写入失败则抛异常触发回滚
}
syncBaseTyreOwner(tyre, operName, now); // 同步轮胎归属信息到当前操作人部门
return true; // 单条入库成功
}
/**
* PDA
*/
private void syncBaseTyreOwner(BaseTyre tyre, String operName, Date now)
{
if (tyre.getTyreId() == null)
{
throw new ServiceException("轮胎基础档案ID不能为空"); // 档案 ID 必传校验
}
SysUser sysUser = sysUserMapper.selectUserByLoginName(operName); // 按登录名查询用户信息
if (sysUser == null || sysUser.getDeptId() == null)
{
throw new ServiceException("未找到操作人部门信息"); // 校验操作人及所属部门
}
BaseTyre updateTyre = new BaseTyre(); // 构造更新对象
updateTyre.setTyreId(tyre.getTyreId()); // 指定待更新的轮胎档案
updateTyre.setTeam(baseTyreMapper.getTeamByUser(operName)); // 同步车队归属
updateTyre.setDeptId(sysUser.getDeptId()); // 同步部门归属
updateTyre.setInventoryStatus("0"); // 入库后库存状态更新为在仓0=在仓1=出仓NULL=已发货待入库)
updateTyre.setUpdateBy(operName); // 记录更新人
updateTyre.setUpdateTime(now); // 记录更新时间
int tyreRows = baseTyreMapper.updateBaseTyre(updateTyre); // 执行更新
if (tyreRows <= 0)
{
throw new ServiceException("轮胎归属信息同步失败"); // 更新失败抛异常
}
}
/**
* 使
*
* @param tyre
* @param operName
* @param inboundCode
* @return true false
*/
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public boolean rollbackOne(BaseTyre tyre, String operName, String inboundCode)
{
BaseInventory probe = new BaseInventory(); // 构造查询探针
probe.setTyreRfid(tyre.getTyreEpc()); // 按轮胎 RFID 查找库存
BaseInventory existed = baseInventoryMapper.selectBaseInventoryByEpc(probe); // 查询当前库存状态
if (existed == null || !"0".equals(existed.getStatus()))
{
return false; // 库存不存在或非在库状态时不允许撤回,幂等跳过
}
int deleteRows = baseInventoryMapper.deleteInStockBaseInventoryByEpc(tyre.getTyreEpc()); // 删除在库记录
if (deleteRows <= 0)
{
throw new ServiceException("库存撤回失败"); // 删除失败抛异常
}
RecordWarehousing record = new RecordWarehousing(); // 新建撤回流水
record.setTyreRfid(tyre.getTyreEpc()); // 绑定轮胎 RFID
record.setType("1"); // 1 表示撤回类型
record.setCreateBy(operName); // 记录操作人
record.setCreateTime(DateUtils.getNowDate()); // 记录操作时间
record.setRemark("批量入库撤回[" + inboundCode + "]"); // 备注携带批次号
int recordRows = recordWarehousingMapper.insertRecordWarehousing(record); // 写入流水表
if (recordRows <= 0)
{
throw new ServiceException("撤回流水写入失败"); // 写入失败抛异常
}
return true; // 单条撤回成功
}
}

@ -0,0 +1,269 @@
<?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.ruoyi.system.mapper.BaseCarLifecycleMapper">
<resultMap type="CarLifecycleSummaryDTO" id="CarLifecycleSummaryResult">
<result property="carId" column="car_id"/>
<result property="carNo" column="car_no"/>
<result property="deptId" column="dept_id"/>
<result property="team" column="team"/>
<result property="line" column="line"/>
<result property="type" column="type"/>
<result property="inputMileage" column="input_mileage"/>
</resultMap>
<select id="selectLifecycleCar" parameterType="CarLifecycleQuery" resultMap="CarLifecycleSummaryResult">
select b.id as car_id,
b.car_no,
b.dept_id,
d.dept_name as team,
b.line,
b.type,
max(o.input_mileage) as input_mileage
from base_car b
left join sys_dept d on d.dept_id = b.dept_id
left join sys_user u on u.dept_id = d.dept_id
left join biz_maintenance_order o on o.plate_number = b.car_no
where b.car_no = #{carNo}
${params.dataScope}
group by b.id, b.car_no, b.dept_id, d.dept_name, b.line, b.type
</select>
<select id="selectMountedTyres" parameterType="CarLifecycleQuery" resultType="CarMountedTyreDTO">
select bt.tyre_id as tyreId,
bt.tyre_no as tyreNo,
bt.self_no as selfNo,
bt.tyre_epc as tyreEpc,
bt.tyre_brand as tyreBrand,
bt.tyre_model as tyreModel,
bt.wheel_postion as wheelPostion,
bt.pattern_depth as patternDepth
from base_tyre bt
where bt.car_no = #{carNo}
order by bt.wheel_postion, bt.tyre_id
</select>
<select id="selectInstallList" parameterType="CarLifecycleQuery" resultType="CarTyreInstallLifecycleDTO">
select rti.id as id,
rti.tyre_rfid as tyreRfid,
rti.type as installType,
rti.mileage as mileage,
rti.create_time as createTime,
rti.wheel_postion as wheelPostion,
rti.pattern_depth as patternDepth,
bt.tyre_no as tyreNo,
bt.self_no as selfNo,
bt.tyre_brand as tyreBrand,
bt.tyre_model as tyreModel
from record_tyre_install rti
left join base_tyre bt on bt.tyre_epc = rti.tyre_rfid
where rti.car_no = #{carNo}
order by rti.create_time desc, rti.id desc
</select>
<select id="selectMaintenanceList" parameterType="CarLifecycleQuery" resultType="CarMaintenanceLifecycleDTO">
select o.order_id as orderId,
o.order_no as orderNo,
o.vehicle_id as vehicleId,
o.plate_number as plateNumber,
o.type_code as typeCode,
o.status as status,
o.input_mileage as inputMileage,
o.last_mileage as lastMileage,
o.maintain_date as maintainDate,
d.dept_name as factoryName,
o.description as description
from biz_maintenance_order o
left join sys_dept d on d.dept_id = o.factory_id
where o.plate_number = #{carNo}
order by o.maintain_date desc, o.order_id desc
</select>
<select id="selectCheckList" parameterType="CarLifecycleQuery" resultType="CarCheckLifecycleDTO">
select rc.id as id,
rc.tyre_rfid as tyreRfid,
bt.tyre_no as tyreNo,
bt.tyre_brand as tyreBrand,
bt.tyre_model as tyreModel,
rc.result as result,
rc.maintenance_type as maintenanceType,
rc.mileage as mileage,
rc.pattern_depth as patternDepth,
rc.create_time as createTime
from record_check rc
inner join (
select distinct tyre_rfid
from record_tyre_install
where car_no = #{carNo}
and tyre_rfid is not null
) car_tyre on car_tyre.tyre_rfid = rc.tyre_rfid
left join base_tyre bt on bt.tyre_epc = rc.tyre_rfid
order by rc.create_time desc, rc.id desc
</select>
<select id="selectMileageList" parameterType="CarLifecycleQuery" resultType="CarMileageLifecycleDTO">
select rtm.id as id,
rtm.tyre_rfid as tyreRfid,
bt.tyre_no as tyreNo,
bt.tyre_brand as tyreBrand,
rtm.start_time as startTime,
rtm.end_time as endTime,
rtm.mileage as mileage,
rtm.pattern_depth as patternDepth
from record_tyre_mileage rtm
inner join (
select distinct tyre_rfid
from record_tyre_install
where car_no = #{carNo}
and tyre_rfid is not null
) car_tyre on car_tyre.tyre_rfid = rtm.tyre_rfid
left join base_tyre bt on bt.tyre_epc = rtm.tyre_rfid
order by rtm.start_time desc, rtm.id desc
</select>
<select id="selectRecentEvents" parameterType="CarLifecycleQuery" resultType="CarLifecycleEventDTO">
select 'INSTALL' as eventType,
rti.create_time as eventTime,
rti.tyre_rfid as tyreRfid,
bt.tyre_no as tyreNo,
bt.self_no as selfNo,
bt.tyre_brand as tyreBrand,
bt.tyre_model as tyreModel,
rti.wheel_postion as wheelPostion,
rti.mileage as mileage,
rti.pattern_depth as patternDepth,
rti.type as status,
null as orderNo,
null as typeCode,
null as factoryName,
null as inputMileage,
null as lastMileage,
null as maintainDate,
null as description,
null as result,
null as maintenanceType,
null as startTime,
null as endTime
from record_tyre_install rti
left join base_tyre bt on bt.tyre_epc = rti.tyre_rfid
where rti.car_no = #{carNo}
union all
select 'MAINTENANCE' as eventType,
o.maintain_date as eventTime,
null as tyreRfid,
null as tyreNo,
null as selfNo,
null as tyreBrand,
null as tyreModel,
null as wheelPostion,
o.input_mileage as mileage,
null as patternDepth,
o.status as status,
o.order_no as orderNo,
o.type_code as typeCode,
d.dept_name as factoryName,
o.input_mileage as inputMileage,
o.last_mileage as lastMileage,
o.maintain_date as maintainDate,
o.description as description,
null as result,
null as maintenanceType,
null as startTime,
null as endTime
from biz_maintenance_order o
left join sys_dept d on d.dept_id = o.factory_id
where o.plate_number = #{carNo}
union all
select 'CHECK' as eventType,
rc.create_time as eventTime,
rc.tyre_rfid as tyreRfid,
bt.tyre_no as tyreNo,
bt.self_no as selfNo,
bt.tyre_brand as tyreBrand,
bt.tyre_model as tyreModel,
null as wheelPostion,
rc.mileage as mileage,
rc.pattern_depth as patternDepth,
null as status,
null as orderNo,
null as typeCode,
null as factoryName,
null as inputMileage,
null as lastMileage,
null as maintainDate,
null as description,
rc.result as result,
rc.maintenance_type as maintenanceType,
null as startTime,
null as endTime
from record_check rc
inner join (
select distinct tyre_rfid
from record_tyre_install
where car_no = #{carNo}
and tyre_rfid is not null
) car_tyre on car_tyre.tyre_rfid = rc.tyre_rfid
left join base_tyre bt on bt.tyre_epc = rc.tyre_rfid
union all
select 'MILEAGE' as eventType,
rtm.start_time as eventTime,
rtm.tyre_rfid as tyreRfid,
bt.tyre_no as tyreNo,
bt.self_no as selfNo,
bt.tyre_brand as tyreBrand,
bt.tyre_model as tyreModel,
null as wheelPostion,
rtm.mileage as mileage,
rtm.pattern_depth as patternDepth,
null as status,
null as orderNo,
null as typeCode,
null as factoryName,
null as inputMileage,
null as lastMileage,
null as maintainDate,
null as description,
null as result,
null as maintenanceType,
rtm.start_time as startTime,
rtm.end_time as endTime
from record_tyre_mileage rtm
inner join (
select distinct tyre_rfid
from record_tyre_install
where car_no = #{carNo}
and tyre_rfid is not null
) car_tyre on car_tyre.tyre_rfid = rtm.tyre_rfid
left join base_tyre bt on bt.tyre_epc = rtm.tyre_rfid
order by eventTime desc
</select>
<select id="countInstallRecords" parameterType="CarLifecycleQuery" resultType="int">
select count(1)
from record_tyre_install rti
where rti.car_no = #{carNo}
</select>
<select id="countMaintenanceOrders" parameterType="CarLifecycleQuery" resultType="int">
select count(1)
from biz_maintenance_order o
where o.plate_number = #{carNo}
</select>
<select id="countCheckRecords" parameterType="CarLifecycleQuery" resultType="int">
select count(distinct rc.id)
from record_check rc
inner join record_tyre_install rti on rti.tyre_rfid = rc.tyre_rfid
where rti.car_no = #{carNo}
</select>
<select id="countMileageRecords" parameterType="CarLifecycleQuery" resultType="int">
select count(distinct rtm.id)
from record_tyre_mileage rtm
inner join record_tyre_install rti on rti.tyre_rfid = rtm.tyre_rfid
where rti.car_no = #{carNo}
</select>
</mapper>

@ -143,4 +143,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
delete from base_inventory where tyre_rfid = #{tyreRfid}
</delete>
</mapper>
<delete id="deleteInStockBaseInventoryByEpc">
delete from base_inventory
where tyre_rfid = #{tyreRfid}
and status = '0'
</delete>
</mapper>

@ -9,6 +9,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="tyreNo" column="tyre_no" />
<result property="selfNo" column="self_no" />
<result property="tyreEpc" column="tyre_epc" />
<result property="inboundCode" column="inbound_code" />
<result property="tyreBrand" column="tyre_brand" />
<result property="tyreModel" column="tyre_model" />
<result property="tyreLevel" column="tyre_level" />
@ -28,15 +29,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="company" column="company" />
<result property="carTeam" column="carTeam" />
<result property="grooves" column="grooves" />
<result property="inventoryStatus" column="inventory_status" />
</resultMap>
<sql id="selectBaseTyreVo">
select d.tyre_id, d.tyre_no, d.self_no, d.tyre_epc, d.tyre_brand, d.tyre_model, d.tyre_level, d.tyre_pattern,
d.grooves, d.pattern_depth, d.tyre_type, d.team, d.create_by, d.create_time, d.update_by, d.update_time,
d.remark, d.car_no, d.wheel_postion, d.dept_id, sd.dept_name
d.grooves, d.pattern_depth, d.tyre_type, d.team, d.inbound_code, d.inventory_status, d.create_by, d.create_time, d.update_by, d.update_time,
d.remark, d.car_no, d.wheel_postion, d.dept_id, tyre_dept.dept_name,
company_dept.dept_name as company, car_dept.dept_name as carTeam
from base_tyre d
left join sys_dept sd on sd.dept_id = d.dept_id
<!-- 详情页与 tyre.html 列表页保持同一口径:公司/车队跟随当前安装车辆,修理厂跟随轮胎档案 team。 -->
left join base_car bc on bc.car_no = d.car_no
left join sys_dept car_dept on car_dept.dept_id = bc.dept_id
left join sys_dept repair_dept on repair_dept.dept_id = car_dept.parent_id
left join sys_dept company_dept on company_dept.dept_id = repair_dept.parent_id
left join sys_dept tyre_dept on tyre_dept.dept_id = d.dept_id
</sql>
<select id="selectBaseTyreList" parameterType="BaseTyre" resultMap="BaseTyreResult">
@ -45,6 +53,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
tyre_no,
self_no,
tyre_epc,
d.inbound_code,
tyre_brand,
tyre_model,
tyre_level,
@ -60,7 +69,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
d.update_time,
d.remark,
d.car_no,
wheel_postion
wheel_postion,
d.inventory_status
FROM
base_tyre d
LEFT JOIN sys_user su ON su.login_name = d.create_by
@ -72,6 +82,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="tyreNo != null and tyreNo != ''"> and tyre_no like concat('%', #{tyreNo}, '%')</if>
<if test="selfNo != null and selfNo != ''"> and self_no like concat('%', #{selfNo}, '%')</if>
<if test="tyreEpc != null and tyreEpc != ''"> and tyre_epc like concat('%', #{tyreEpc}, '%')</if>
<if test="inboundCode != null and inboundCode != ''"> and d.inbound_code = #{inboundCode}</if>
<if test="tyreBrand != null and tyreBrand != ''"> and tyre_brand like concat('%', #{tyreBrand}, '%')</if>
<if test="tyreModel != null and tyreModel != ''"> and tyre_model = #{tyreModel}</if>
<if test="tyreLevel != null and tyreLevel != ''"> and tyre_level = #{tyreLevel}</if>
@ -85,6 +96,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
AND date_format(d.create_time,'%Y%m%d') &lt;= date_format(#{params.endTime},'%Y%m%d')
</if>
<if test="inventoryStatus != null and inventoryStatus != ''">
AND d.inventory_status = #{inventoryStatus}
</if>
${params.dataScope}
</select>
@ -102,6 +116,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="tyreEpc != null and tyreEpc != ''"> and d.tyre_epc like concat('%', #{tyreEpc}, '%')</if>
</where>
</select>
<select id="getTeamByUser" resultType="java.lang.String">
SELECT
dept_name
@ -169,6 +184,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="tyreNo != null and tyreNo != ''">tyre_no,</if>
<if test="selfNo != null and selfNo != ''">self_no,</if>
<if test="tyreEpc != null and tyreEpc != ''">tyre_epc,</if>
<if test="inboundCode != null and inboundCode != ''">inbound_code,</if>
<if test="tyreBrand != null and tyreBrand != ''">tyre_brand,</if>
<if test="tyreModel != null and tyreModel != ''">tyre_model,</if>
<if test="tyreLevel != null and tyreLevel != ''">tyre_level,</if>
@ -183,12 +199,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="remark != null and remark != ''">remark,</if>
<if test="deptId != null and deptId != ''">dept_id,</if>
<if test="patternDepth != null and patternDepth != ''">pattern_depth,</if>
<if test="inventoryStatus != null and inventoryStatus != ''">inventory_status,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="tyreId != null ">#{tyreId},</if>
<if test="tyreNo != null and tyreNo != ''">#{tyreNo},</if>
<if test="selfNo != null and selfNo != ''">#{selfNo},</if>
<if test="tyreEpc != null and tyreEpc != ''">#{tyreEpc},</if>
<if test="inboundCode != null and inboundCode != ''">#{inboundCode},</if>
<if test="tyreBrand != null and tyreBrand != ''">#{tyreBrand},</if>
<if test="tyreModel != null and tyreModel != ''">#{tyreModel},</if>
<if test="tyreLevel != null and tyreLevel != ''">#{tyreLevel},</if>
@ -203,6 +221,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="remark != null and remark != ''">#{remark},</if>
<if test="deptId != null and deptId != ''">#{deptId},</if>
<if test="patternDepth != null and patternDepth != ''">#{patternDepth},</if>
<if test="inventoryStatus != null and inventoryStatus != ''">#{inventoryStatus},</if>
</trim>
</insert>
@ -212,6 +231,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="tyreNo != null and tyreNo != ''">tyre_no = #{tyreNo},</if>
<if test="selfNo != null and selfNo != ''">self_no = #{selfNo},</if>
<if test="tyreEpc != null and tyreEpc != ''">tyre_epc = #{tyreEpc},</if>
<if test="inboundCode != null and inboundCode != ''">inbound_code = #{inboundCode},</if>
<if test="tyreBrand != null and tyreBrand != ''">tyre_brand = #{tyreBrand},</if>
<if test="tyreModel != null and tyreModel != ''">tyre_model = #{tyreModel},</if>
<if test="tyreLevel != null and tyreLevel != ''">tyre_level = #{tyreLevel},</if>
@ -226,6 +246,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="remark != null and remark != ''">remark = #{remark},</if>
<if test="carNo != null ">car_no = #{carNo},</if>
<if test="wheelPostion != null ">wheel_postion = #{wheelPostion},</if>
<if test="inventoryStatus != null">inventory_status = #{inventoryStatus},</if>
</trim>
where tyre_id = #{tyreId}
</update>
@ -240,5 +261,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{tyreId}
</foreach>
</delete>
</mapper>
<select id="selectByInboundCode" resultMap="BaseTyreResult">
<include refid="selectBaseTyreVo"/>
where d.inbound_code = #{inboundCode}
and d.tyre_epc is not null
and d.tyre_epc &lt;&gt; ''
order by d.tyre_id
</select>
<select id="countBaseTyreByInboundCode" resultType="int">
select count(1)
from base_tyre
where inbound_code = #{inboundCode}
</select>
</mapper>

Loading…
Cancel
Save