Merge remote-tracking branch 'origin/0.8.X' into 0.8.X
This commit is contained in:
@@ -8,3 +8,10 @@ export function getAcidTypingPrefill(currentCoilNo) {
|
||||
})
|
||||
}
|
||||
|
||||
export function getGalvanize1TypingPrefill(params) {
|
||||
return request({
|
||||
url: '/pocket/galvanize1/crmPdoExcoil/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<!-- 第四行:材质 + 表面质量 -->
|
||||
<div class="info-grid-item label-cell">材质</div>
|
||||
<div class="info-grid-item value-cell">
|
||||
<div class="nob">{{ content.materialWithManufacturer || '' }}</div>
|
||||
<div class="nob">{{ materialWithManufacturer || '' }}</div>
|
||||
</div>
|
||||
<div class="info-grid-item label-cell">表面状态</div>
|
||||
<div class="info-grid-item value-cell">
|
||||
@@ -434,10 +434,14 @@ export default {
|
||||
.nob {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
font-family: '黑体', serif;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* 打印样式 - 强制单页,适配180mm x 100mm纸张,保持原有样式不变 */
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<!-- 第四行:材质 + 表面质量 -->
|
||||
<div class="info-grid-item label-cell">材质</div>
|
||||
<div class="info-grid-item value-cell">
|
||||
<div class="nob">{{ content.materialWithManufacturer || '' }}</div>
|
||||
<div class="nob">{{ materialWithManufacturer || '' }}</div>
|
||||
</div>
|
||||
<div class="info-grid-item label-cell">镀层种类</div>
|
||||
<div class="info-grid-item value-cell">
|
||||
@@ -102,7 +102,7 @@
|
||||
<!-- 第八行:生产日期(跨3列) -->
|
||||
<div class="info-grid-item label-cell">生产日期</div>
|
||||
<div class="info-grid-item value-cell">
|
||||
<div>{{ parseTime(content.updateTime, '{y}-{m}-{d}') }}</div>
|
||||
<div class="nob">{{ parseTime(content.updateTime, '{y}-{m}-{d}') }}</div>
|
||||
<!-- <input type="text" class="nob" :value=" /> -->
|
||||
</div>
|
||||
</div>
|
||||
@@ -437,8 +437,12 @@ export default {
|
||||
height: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
font-family: '黑体', serif;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* 打印样式 - 强制单页,适配180mm x 100mm纸张,保持原有样式不变 */
|
||||
|
||||
@@ -333,6 +333,9 @@ export default {
|
||||
.nob {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
font-family: '黑体', serif;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<!-- 第四行:材质 + 表面质量 -->
|
||||
<div class="info-grid-item label-cell">材质</div>
|
||||
<div class="info-grid-item value-cell">
|
||||
<div class="nob">{{ content.materialWithManufacturer || '' }}</div>
|
||||
<div class="nob">{{ materialWithManufacturer || '' }}</div>
|
||||
<!-- <input type="text" class="nob" :value="content.materialWithManufacturer || ''" /> -->
|
||||
</div>
|
||||
<div class="info-grid-item label-cell">质量要求</div>
|
||||
@@ -392,7 +392,7 @@ export default {
|
||||
.info-grid-item {
|
||||
border: 1px solid #000;
|
||||
padding: 0.1em;
|
||||
font-size: 1.05em;
|
||||
font-size: 1.2em;
|
||||
height: 2em;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
@@ -443,8 +443,12 @@ export default {
|
||||
height: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
font-family: '黑体', serif;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* 打印样式 - 强制单页,适配180mm x 100mm纸张,保持原有样式不变 */
|
||||
|
||||
@@ -253,6 +253,10 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
font-family: '黑体', serif;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* 打印样式 */
|
||||
|
||||
@@ -246,6 +246,10 @@ export default {
|
||||
word-break: break-all;
|
||||
overflow-wrap: break-word;
|
||||
white-space: normal;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
font-family: '黑体', serif;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* 打印样式 - 强制单页,适配100mm x 80mm纸张,保持原有样式不变 */
|
||||
|
||||
@@ -244,6 +244,7 @@ export default {
|
||||
.nob {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 1.2em;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
@@ -253,6 +254,10 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
font-family: '黑体', serif;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* 打印样式 */
|
||||
|
||||
@@ -454,7 +454,7 @@
|
||||
|
||||
<el-dialog title="分步加工" :visible.sync="stepSpilt.visible" width="1400px" append-to-body>
|
||||
<step-split @print="handlePrintLabel" @complete="handleComposeSplit" :actionId="stepSpilt.actionId"
|
||||
:coilId="stepSpilt.coilId" :actionStatus="stepSpilt.actionStatus" />
|
||||
:coilId="stepSpilt.coilId" :actionStatus="stepSpilt.actionStatus" :actionType="stepSpilt.actionType" />
|
||||
</el-dialog>
|
||||
|
||||
<label-render ref="labelRender" v-show="false" :content="labelRender.data" :labelType="labelRender.type" />
|
||||
@@ -577,7 +577,8 @@ export default {
|
||||
visible: false,
|
||||
coilId: null,
|
||||
actionId: null,
|
||||
actionStatus: null
|
||||
actionStatus: null,
|
||||
actionType: null,
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -642,6 +643,10 @@ export default {
|
||||
// 如果待操作列表为空,则加载数据
|
||||
if (this.pendingActionList.length === 0) {
|
||||
this.getPendingAction()
|
||||
console.log(this.useSpecialSplit)
|
||||
if (this.useSpecialSplit) {
|
||||
this.getStepSplitList()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -673,15 +678,16 @@ export default {
|
||||
// 立即加载物料列表(不依赖字典)
|
||||
// this.getMaterialCoil()
|
||||
// 尝试加载待操作列表(如果字典已加载)
|
||||
this.$nextTick(() => {
|
||||
if (this.acidRollingActionType) {
|
||||
this.actionQueryParams.actionType = this.acidRollingActionType
|
||||
this.getPendingAction()
|
||||
if (this.useSpecialSplit) {
|
||||
this.getStepSplitList()
|
||||
}
|
||||
}
|
||||
})
|
||||
// this.$nextTick(() => {
|
||||
// if (this.acidRollingActionType) {
|
||||
// this.actionQueryParams.actionType = this.acidRollingActionType
|
||||
// this.getPendingAction()
|
||||
// console.log(this.useSpecialSplit)
|
||||
// if (this.useSpecialSplit) {
|
||||
// this.getStepSplitList()
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
},
|
||||
mounted() {
|
||||
// 确保在mounted时也尝试加载(字典数据可能此时才加载完成)
|
||||
@@ -689,6 +695,10 @@ export default {
|
||||
if (this.acidRollingActionType && !this.actionQueryParams.actionType) {
|
||||
this.actionQueryParams.actionType = this.acidRollingActionType
|
||||
this.getPendingAction()
|
||||
console.log(this.useSpecialSplit)
|
||||
if (this.useSpecialSplit) {
|
||||
this.getStepSplitList()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -1008,6 +1018,7 @@ export default {
|
||||
this.stepSpilt.coilId = row.coilId
|
||||
this.stepSpilt.actionId = row.actionId
|
||||
this.stepSpilt.actionStatus = row.actionStatus
|
||||
this.stepSpilt.actionType = row.actionType
|
||||
this.stepSpilt.visible = true
|
||||
// this.buttonLoading = true
|
||||
// this.getPendingAction()
|
||||
|
||||
@@ -67,8 +67,13 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- <el-descriptions :column="1" border title="二级数据" v-if="showSplitForm"></el-descriptions>
|
||||
<el-table v-if="showSplitForm"></el-table> -->
|
||||
<el-descriptions :column="1" border title="镀锌二级数据" v-if="actionType == 501 && showSplitForm"></el-descriptions>
|
||||
<el-table v-if="actionType == 501 && showSplitForm" v-loading="zincLoading" :data="zincList" border stripe @row-click="handleZincItemClick">
|
||||
<el-table-column prop="enterCoilNo" label="入场钢卷号" />
|
||||
<el-table-column prop="createTime" label="生产开始时间" />
|
||||
<el-table-column prop="endTime" label="生产结束时间" />
|
||||
<el-table-column prop="shiftNo" label="班组" />
|
||||
</el-table>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
@@ -197,6 +202,7 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="info" @click="copyFromSourceCoil" icon="el-icon-document-copy">复制源卷信息</el-button>
|
||||
<el-button :loading="buttonLoading" type="primary" @click="addSplit">提交分条</el-button>
|
||||
<el-button :loading="buttonLoading" @click="resetSplitForm">重置</el-button>
|
||||
</el-form-item>
|
||||
@@ -268,6 +274,7 @@
|
||||
<script>
|
||||
import { getMaterialCoil, listMaterialCoil, createSpecialChild, completeSpecialSplit, updateMaterialCoilSimple, checkCoilNo, delMaterialCoil } from '@/api/wms/coil'
|
||||
import { completeAction, getPendingAction, updatePendingAction } from '@/api/wms/pendingAction'
|
||||
import { getGalvanize1TypingPrefill } from '@/api/pocket/acidTyping';
|
||||
import ProductSelect from "@/components/KLPService/ProductSelect";
|
||||
import RawMaterialSelect from "@/components/KLPService/RawMaterialSelect";
|
||||
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
|
||||
@@ -280,7 +287,7 @@ export default {
|
||||
name: 'StepSplit',
|
||||
props: {
|
||||
actionId: {
|
||||
type: String,
|
||||
type: [String, Number],
|
||||
required: true,
|
||||
},
|
||||
coilId: {
|
||||
@@ -291,6 +298,10 @@ export default {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
actionType: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
ProductSelect,
|
||||
@@ -398,7 +409,10 @@ export default {
|
||||
defectCode: null,
|
||||
degree: null,
|
||||
remark: null
|
||||
}
|
||||
},
|
||||
|
||||
zincList: [],
|
||||
zincLoading: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -427,6 +441,16 @@ export default {
|
||||
// 若actionId变化需要重新加载数据,可在此补充逻辑
|
||||
},
|
||||
},
|
||||
actionType: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
console.log('actionType', val)
|
||||
if (val == 501) {
|
||||
// 获取镀锌线二级系统数据
|
||||
this.getZincList()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 查询待分条的钢卷信息
|
||||
@@ -443,6 +467,16 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
async getZincList() {
|
||||
this.zincLoading = true
|
||||
const res = await getGalvanize1TypingPrefill({
|
||||
pageSize: 10,
|
||||
pageNum: 1,
|
||||
})
|
||||
this.zincList = res.rows || []
|
||||
this.zincLoading = false
|
||||
},
|
||||
|
||||
async handlePrint(row) {
|
||||
this.$emit('print', row)
|
||||
},
|
||||
@@ -557,6 +591,20 @@ export default {
|
||||
this.showSplitForm = false
|
||||
},
|
||||
|
||||
handleZincItemClick(row) {
|
||||
this.splitForm = {
|
||||
...this.splitForm,
|
||||
team: row.shiftNo,
|
||||
// enterCoilNo: row.enterCoilNo,
|
||||
productionStartTime: row.createTime,
|
||||
productionEndTime: row.endTime,
|
||||
itemType: 'product',
|
||||
materialType: '成品',
|
||||
length: row.exitLength,
|
||||
netWeight: row.exitNetWeight,
|
||||
}
|
||||
},
|
||||
|
||||
// 编辑分条项
|
||||
async handleEditSplit(row) {
|
||||
this.showSplitForm = true
|
||||
@@ -766,6 +814,52 @@ export default {
|
||||
if (!dict) return code;
|
||||
const item = dict.find(item => item.value === code);
|
||||
return item ? item.label : code;
|
||||
},
|
||||
|
||||
// 复制源卷信息到分条表单
|
||||
copyFromSourceCoil() {
|
||||
// 复制除了指定字段之外的其他字段
|
||||
const excludeFields = ['enterCoilNo', 'currentCoilNo', 'coilId', 'createTime', 'createBy'];
|
||||
|
||||
// 构建要复制的字段
|
||||
const copiedFields = {
|
||||
supplierCoilNo: this.coilInfo.supplierCoilNo,
|
||||
warehouseId: this.coilInfo.warehouseId,
|
||||
actualWarehouseId: this.coilInfo.actualWarehouseId,
|
||||
team: this.coilInfo.team,
|
||||
materialType: this.coilInfo.materialType,
|
||||
itemType: this.coilInfo.itemType,
|
||||
itemId: this.coilInfo.itemId,
|
||||
qualityStatus: this.coilInfo.qualityStatus,
|
||||
trimmingRequirement: this.coilInfo.trimmingRequirement,
|
||||
packingStatus: this.coilInfo.packingStatus,
|
||||
packagingRequirement: this.coilInfo.packagingRequirement,
|
||||
grossWeight: parseFloat(this.coilInfo.grossWeight) || null,
|
||||
netWeight: parseFloat(this.coilInfo.netWeight) || null,
|
||||
length: parseFloat(this.coilInfo.length) || null,
|
||||
actualLength: parseFloat(this.coilInfo.actualLength) || null,
|
||||
actualWidth: parseFloat(this.coilInfo.actualWidth) || null,
|
||||
temperGrade: this.coilInfo.temperGrade,
|
||||
coatingType: this.coilInfo.coatingType,
|
||||
remark: this.coilInfo.remark,
|
||||
productionStartTime: this.coilInfo.productionStartTime,
|
||||
productionEndTime: this.coilInfo.productionEndTime,
|
||||
productionDuration: this.coilInfo.productionDuration,
|
||||
formattedDuration: this.coilInfo.productionDuration ? this.formatDuration(this.coilInfo.productionDuration * 60 * 1000) : ''
|
||||
};
|
||||
|
||||
// 合并到分条表单
|
||||
this.splitForm = {
|
||||
...this.splitForm,
|
||||
...copiedFields
|
||||
};
|
||||
|
||||
// 同步材料类型和长度显示状态
|
||||
if (this.splitForm.materialType) {
|
||||
this.handleMaterialTypeChange(this.splitForm.materialType);
|
||||
}
|
||||
|
||||
this.$message.success('已复制源卷信息,请根据需要修改');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -85,9 +85,9 @@
|
||||
<el-card class="form-card">
|
||||
<div slot="header" class="card-header">
|
||||
<span><i class="el-icon-edit-outline"></i> {{ '更新信息' }}</span>
|
||||
<!-- <el-button type="text" size="mini" @click="copyFromCurrent" icon="el-icon-document-copy">
|
||||
复制当前信息
|
||||
</el-button> -->
|
||||
<el-button type="text" size="mini" @click="copyFromCurrent" icon="el-icon-document-copy">
|
||||
复制源卷信息
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-form ref="updateForm" :model="updateForm" :rules="rules" label-width="80px" size="small">
|
||||
@@ -820,23 +820,43 @@ export default {
|
||||
|
||||
// 复制当前信息到更新表单
|
||||
copyFromCurrent() {
|
||||
const itemType = this.currentInfo.materialType === '原料' ? 'raw_material' : 'product';
|
||||
this.updateForm = {
|
||||
currentCoilNo: this.currentInfo.currentCoilNo,
|
||||
// 复制除了指定字段之外的其他字段
|
||||
const excludeFields = ['enterCoilNo', 'currentCoilNo', 'coilId', 'createTime', 'createBy'];
|
||||
|
||||
// 构建要复制的字段
|
||||
const copiedFields = {
|
||||
team: this.currentInfo.team,
|
||||
materialType: this.currentInfo.materialType,
|
||||
// 不复制 itemType 和 itemId,让它们由 materialType 自动决定
|
||||
itemType,
|
||||
itemType: this.currentInfo.itemType,
|
||||
itemId: this.currentInfo.itemId,
|
||||
grossWeight: parseFloat(this.currentInfo.grossWeight) || null,
|
||||
netWeight: parseFloat(this.currentInfo.netWeight) || null,
|
||||
warehouseId: this.currentInfo.warehouseId,
|
||||
actualWarehouseId: this.currentInfo.actualWarehouseId,
|
||||
length: parseFloat(this.currentInfo.length) || null,
|
||||
remark: this.currentInfo.remark
|
||||
actualLength: parseFloat(this.currentInfo.actualLength) || null,
|
||||
actualWidth: parseFloat(this.currentInfo.actualWidth) || null,
|
||||
temperGrade: this.currentInfo.temperGrade,
|
||||
coatingType: this.currentInfo.coatingType,
|
||||
qualityStatus: this.currentInfo.qualityStatus,
|
||||
packagingRequirement: this.currentInfo.packagingRequirement,
|
||||
packingStatus: this.currentInfo.packingStatus,
|
||||
trimmingRequirement: this.currentInfo.trimmingRequirement,
|
||||
remark: this.currentInfo.remark,
|
||||
productionStartTime: this.currentInfo.productionStartTime,
|
||||
productionEndTime: this.currentInfo.productionEndTime,
|
||||
productionDuration: this.currentInfo.productionDuration,
|
||||
formattedDuration: this.currentInfo.productionDuration ? this.formatDuration(this.currentInfo.productionDuration * 60 * 1000) : ''
|
||||
};
|
||||
|
||||
// 合并到更新表单
|
||||
this.updateForm = {
|
||||
...this.updateForm,
|
||||
...copiedFields
|
||||
};
|
||||
|
||||
// materialType 会触发 watch,自动设置 itemType 并加载物品列表
|
||||
this.$message.success('已复制当前信息,包含' + this.currentInfo.materialType + '类型的相关信息, 请根据需要修改');
|
||||
this.$message.success('已复制源卷信息,请根据需要修改');
|
||||
},
|
||||
|
||||
// 保存更新
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="入职时间" prop="changeTime">
|
||||
<el-date-picker clearable v-model="queryParams.changeTime" type="date" value-format="yyyy-MM-dd"
|
||||
placeholder="请选择入职时间">
|
||||
</el-date-picker>
|
||||
<el-form-item label="入职时间">
|
||||
<el-date-picker
|
||||
v-model="queryParams.changeTimeRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
style="width: 240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="异动原因" prop="changeReason">
|
||||
<el-input
|
||||
@@ -280,6 +286,9 @@ export default {
|
||||
infoId: undefined,
|
||||
changeType: 0,
|
||||
changeTime: undefined,
|
||||
changeStartTime: undefined,
|
||||
changeEndTime: undefined,
|
||||
changeTimeRange: [],
|
||||
changeReason: undefined,
|
||||
changeHandler: undefined,
|
||||
attachment: undefined,
|
||||
@@ -387,12 +396,23 @@ export default {
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
// 处理时间范围
|
||||
if (this.queryParams.changeTimeRange && this.queryParams.changeTimeRange.length === 2) {
|
||||
this.queryParams.changeStartTime = this.queryParams.changeTimeRange[0];
|
||||
this.queryParams.changeEndTime = this.queryParams.changeTimeRange[1];
|
||||
} else {
|
||||
this.queryParams.changeStartTime = undefined;
|
||||
this.queryParams.changeEndTime = undefined;
|
||||
}
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.queryParams.changeTimeRange = [];
|
||||
this.queryParams.changeStartTime = undefined;
|
||||
this.queryParams.changeEndTime = undefined;
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
|
||||
@@ -33,6 +33,17 @@
|
||||
<el-option label="已转正" value="1" />
|
||||
<el-option label="未转正" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="转正时间">
|
||||
<el-date-picker
|
||||
v-model="queryParams.regularTimeRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
style="width: 240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="在职情况" prop="isLeave">
|
||||
<el-select v-model="queryParams.isLeave" placeholder="请选择在职情况" clearable @change="handleQuery">
|
||||
@@ -106,6 +117,7 @@
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
<el-button v-if="scope.row.isLeave === 0 && scope.row.isRegular === 0" size="mini" type="text" icon="el-icon-check"
|
||||
@click="handleResignation(scope.row)">转正</el-button>
|
||||
<el-button v-if="scope.row.isRegular === 1" size="mini" type="text" icon="el-icon-view" @click="handleViewRegular(scope.row)">转正记录</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -232,22 +244,6 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<!-- 备注和附件 -->
|
||||
<el-card class="mb-4" shadow="hover">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" v-if="!form.infoId">
|
||||
<el-form-item label="附件" prop="attachment">
|
||||
<file-upload v-model="attachment"></file-upload>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
@@ -286,13 +282,34 @@
|
||||
<el-button @click="cancelResignation">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 查看转正记录对话框 -->
|
||||
<el-dialog title="转正记录" :visible.sync="regularRecordOpen" width="500px" append-to-body>
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="转正时间">
|
||||
{{ regularRecord.changeTime }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="转正原因">
|
||||
{{ regularRecord.changeReason }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="负责人">
|
||||
{{ regularRecord.changeHandler }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="附件">
|
||||
<file-upload v-model="regularRecord.attachment"></file-upload>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="备注">
|
||||
{{ regularRecord.remark }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listEmployeeInfo, getEmployeeInfo, delEmployeeInfo, updateEmployeeInfo } from "@/api/wms/employeeInfo";
|
||||
import { listDept } from "@/api/wms/dept";
|
||||
import { employeeEntry, employeeLeave, employeeRegular } from '@/api/wms/employeeChange'
|
||||
import { employeeEntry, employeeRegular, listEmployeeChange } from '@/api/wms/employeeChange'
|
||||
|
||||
export default {
|
||||
name: "EmployeeInfo",
|
||||
@@ -329,6 +346,11 @@ export default {
|
||||
age: undefined,
|
||||
gender: undefined,
|
||||
education: undefined,
|
||||
isRegular: undefined,
|
||||
isLeave: undefined,
|
||||
regularStartTime: undefined,
|
||||
regularEndTime: undefined,
|
||||
regularTimeRange: [],
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
@@ -360,7 +382,17 @@ export default {
|
||||
}
|
||||
],
|
||||
},
|
||||
resignationAttachment: undefined
|
||||
resignationAttachment: undefined,
|
||||
// 转正记录相关
|
||||
regularRecordOpen: false,
|
||||
regularRecord: {
|
||||
name: undefined,
|
||||
changeTime: undefined,
|
||||
changeReason: undefined,
|
||||
changeHandler: undefined,
|
||||
attachment: undefined,
|
||||
remark: undefined
|
||||
}
|
||||
};
|
||||
},
|
||||
dicts: ['hrm_employee_education'],
|
||||
@@ -383,6 +415,17 @@ export default {
|
||||
this.deptList = response.data;
|
||||
});
|
||||
},
|
||||
|
||||
/** 查询转正记录 */
|
||||
getRegularRecords() {
|
||||
listEmployeeChange({
|
||||
infoId: this.form.infoId,
|
||||
changeType: "2"
|
||||
}).then(response => {
|
||||
this.regularRecord = response.rows[0];
|
||||
});
|
||||
},
|
||||
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
@@ -417,12 +460,23 @@ export default {
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
// 处理时间范围
|
||||
if (this.queryParams.regularTimeRange && this.queryParams.regularTimeRange.length === 2) {
|
||||
this.queryParams.regularStartTime = this.queryParams.regularTimeRange[0];
|
||||
this.queryParams.regularEndTime = this.queryParams.regularTimeRange[1];
|
||||
} else {
|
||||
this.queryParams.regularStartTime = undefined;
|
||||
this.queryParams.regularEndTime = undefined;
|
||||
}
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.queryParams.regularTimeRange = [];
|
||||
this.queryParams.regularStartTime = undefined;
|
||||
this.queryParams.regularEndTime = undefined;
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
@@ -462,20 +516,6 @@ export default {
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
} else {
|
||||
employeeEntry({
|
||||
changeType: 0,
|
||||
changeTime: this.form.entryTime,
|
||||
changeHandler: this.$store.getters.nickName,
|
||||
attachment: this.attachment,
|
||||
...this.form
|
||||
}).then(response => {
|
||||
this.$modal.msgSuccess("员工入职成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -581,7 +621,7 @@ export default {
|
||||
type = 'info';
|
||||
} else if (diffDays >= 90) {
|
||||
// 3个月以上未转正
|
||||
type = 'warning';
|
||||
type = 'danger';
|
||||
}
|
||||
} else {
|
||||
// 已转正
|
||||
@@ -589,6 +629,20 @@ export default {
|
||||
}
|
||||
|
||||
return { days: diffDays, type, status };
|
||||
},
|
||||
|
||||
/** 查看转正记录 */
|
||||
handleViewRegular(row) {
|
||||
this.form = row;
|
||||
this.getRegularRecords();
|
||||
this.regularRecordOpen = true;
|
||||
},
|
||||
|
||||
/** 下载附件 */
|
||||
downloadAttachment(attachment) {
|
||||
if (attachment) {
|
||||
window.open(attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -33,6 +33,17 @@
|
||||
<el-option label="已转正" value="1" />
|
||||
<el-option label="未转正" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="入职时间">
|
||||
<el-date-picker
|
||||
v-model="queryParams.entryTimeRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
style="width: 240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="在职情况" prop="isLeave">
|
||||
<el-select v-model="queryParams.isLeave" placeholder="请选择在职情况" clearable @change="handleQuery">
|
||||
@@ -328,6 +339,11 @@ export default {
|
||||
age: undefined,
|
||||
gender: undefined,
|
||||
education: undefined,
|
||||
isRegular: undefined,
|
||||
isLeave: undefined,
|
||||
entryStartTime: undefined,
|
||||
entryEndTime: undefined,
|
||||
entryTimeRange: [],
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
@@ -423,12 +439,23 @@ export default {
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
// 处理时间范围
|
||||
if (this.queryParams.entryTimeRange && this.queryParams.entryTimeRange.length === 2) {
|
||||
this.queryParams.entryStartTime = this.queryParams.entryTimeRange[0];
|
||||
this.queryParams.entryEndTime = this.queryParams.entryTimeRange[1];
|
||||
} else {
|
||||
this.queryParams.entryStartTime = undefined;
|
||||
this.queryParams.entryEndTime = undefined;
|
||||
}
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.queryParams.entryTimeRange = [];
|
||||
this.queryParams.entryStartTime = undefined;
|
||||
this.queryParams.entryEndTime = undefined;
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
@@ -587,7 +614,7 @@ export default {
|
||||
type = 'info';
|
||||
} else if (diffDays >= 90) {
|
||||
// 3个月以上未转正
|
||||
type = 'warning';
|
||||
type = 'danger';
|
||||
}
|
||||
} else {
|
||||
// 已转正
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="离职时间" prop="changeTime">
|
||||
<el-date-picker clearable v-model="queryParams.changeTime" type="date" value-format="yyyy-MM-dd"
|
||||
placeholder="请选择离职时间">
|
||||
</el-date-picker>
|
||||
<el-form-item label="离职时间">
|
||||
<el-date-picker
|
||||
v-model="queryParams.changeTimeRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
style="width: 240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="异动原因" prop="changeReason">
|
||||
<el-input
|
||||
@@ -138,6 +144,9 @@ export default {
|
||||
infoId: undefined,
|
||||
changeType: 1,
|
||||
changeTime: undefined,
|
||||
changeStartTime: undefined,
|
||||
changeEndTime: undefined,
|
||||
changeTimeRange: [],
|
||||
changeReason: undefined,
|
||||
changeHandler: undefined,
|
||||
attachment: undefined,
|
||||
@@ -245,12 +254,23 @@ export default {
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
// 处理时间范围
|
||||
if (this.queryParams.changeTimeRange && this.queryParams.changeTimeRange.length === 2) {
|
||||
this.queryParams.changeStartTime = this.queryParams.changeTimeRange[0];
|
||||
this.queryParams.changeEndTime = this.queryParams.changeTimeRange[1];
|
||||
} else {
|
||||
this.queryParams.changeStartTime = undefined;
|
||||
this.queryParams.changeEndTime = undefined;
|
||||
}
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.queryParams.changeTimeRange = [];
|
||||
this.queryParams.changeStartTime = undefined;
|
||||
this.queryParams.changeEndTime = undefined;
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
|
||||
@@ -10,6 +10,17 @@
|
||||
<el-form-item label="新部门" prop="newDept">
|
||||
<el-input v-model="queryParams.newDept" placeholder="请输入新部门" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="转岗时间">
|
||||
<el-date-picker
|
||||
v-model="queryParams.transferTimeRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
style="width: 240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="转岗经办人" prop="transferHandler">
|
||||
<el-input v-model="queryParams.transferHandler" placeholder="请输入转岗经办人" clearable
|
||||
@keyup.enter.native="handleQuery" />
|
||||
@@ -146,6 +157,9 @@ export default {
|
||||
newDept: undefined,
|
||||
newJobType: undefined,
|
||||
transferHandler: undefined,
|
||||
transferStartTime: undefined,
|
||||
transferEndTime: undefined,
|
||||
transferTimeRange: [],
|
||||
},
|
||||
// 部门列表
|
||||
deptList: [],
|
||||
@@ -233,12 +247,23 @@ export default {
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
// 处理时间范围
|
||||
if (this.queryParams.transferTimeRange && this.queryParams.transferTimeRange.length === 2) {
|
||||
this.queryParams.transferStartTime = this.queryParams.transferTimeRange[0];
|
||||
this.queryParams.transferEndTime = this.queryParams.transferTimeRange[1];
|
||||
} else {
|
||||
this.queryParams.transferStartTime = undefined;
|
||||
this.queryParams.transferEndTime = undefined;
|
||||
}
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.queryParams.transferTimeRange = [];
|
||||
this.queryParams.transferStartTime = undefined;
|
||||
this.queryParams.transferEndTime = undefined;
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
|
||||
730
klp-ui/src/views/wms/hrm/report/employee.vue
Normal file
730
klp-ui/src/views/wms/hrm/report/employee.vue
Normal file
@@ -0,0 +1,730 @@
|
||||
<template>
|
||||
<div class="employee-report" v-loading="loading">
|
||||
<!-- 第一行:时间段筛选 -->
|
||||
<div class="filter-section">
|
||||
<el-form :inline="true" class="demo-form-inline">
|
||||
<el-form-item label="调动时间">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
format="yyyy-MM-dd hh:mm:ss"
|
||||
value-format="yyyy-MM-dd hh:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="入职时间">
|
||||
<el-date-picker
|
||||
v-model="employeeDateRange"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
format="yyyy-MM-dd hh:mm:ss"
|
||||
value-format="yyyy-MM-dd hh:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
<el-button @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 第二行:员工情况统计信息和图表 -->
|
||||
<div class="stats-section">
|
||||
<div class="stats-cards">
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-item">
|
||||
<div class="stat-value">{{ stats.totalEmployees }}</div>
|
||||
<div class="stat-label">总人数</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-item">
|
||||
<div class="stat-value">{{ stats.entryCount }}</div>
|
||||
<div class="stat-label">入职人数</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-item">
|
||||
<div class="stat-value">{{ stats.leaveCount }}</div>
|
||||
<div class="stat-label">离职人数</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-item">
|
||||
<div class="stat-value">{{ stats.regularCount }}</div>
|
||||
<div class="stat-label">转正人数</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-item">
|
||||
<div class="stat-value">{{ stats.transferCount }}</div>
|
||||
<div class="stat-label">调岗次数</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 第三行:互动筛选图表区 -->
|
||||
<div class="interactive-charts-section">
|
||||
<el-card shadow="hover" class="chart-card">
|
||||
<!-- <div slot="header" class="clearfix">
|
||||
<span>学历分布</span>
|
||||
</div> -->
|
||||
<div id="educationChart" style="width: 100%; height: 300px;"></div>
|
||||
</el-card>
|
||||
<el-card shadow="hover" class="chart-card">
|
||||
<!-- <div slot="header" class="clearfix">
|
||||
<span>年龄段分布</span>
|
||||
</div> -->
|
||||
<div id="ageChart" style="width: 100%; height: 300px;"></div>
|
||||
</el-card>
|
||||
<el-card shadow="hover" class="chart-card">
|
||||
<!-- <div slot="header" class="clearfix">
|
||||
<span>性别分布</span>
|
||||
</div> -->
|
||||
<div id="genderChart" style="width: 100%; height: 300px;"></div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 第四行:多轴折线图 -->
|
||||
<div class="trend-section">
|
||||
<!-- <el-card shadow="hover"> -->
|
||||
<!-- <div slot="header" class="clearfix">
|
||||
<span>员工变动趋势</span>
|
||||
</div> -->
|
||||
<div id="trendChart" style="width: 100%; height: 400px;"></div>
|
||||
<!-- </el-card> -->
|
||||
</div>
|
||||
|
||||
<!-- 第五行:明细数据表 -->
|
||||
<div class="details-section">
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane label="当前员工" name="current">
|
||||
<el-table :data="currentEmployees" style="width: 100%" height="400">
|
||||
<el-table-column prop="name" label="员工姓名" />
|
||||
<el-table-column prop="dept" label="部门" />
|
||||
<el-table-column prop="jobType" label="职位" />
|
||||
<el-table-column prop="entryTime" label="入职日期" />
|
||||
<!-- <el-table-column prop="status" label="状态" /> -->
|
||||
<el-table-column prop="education" label="学历" />
|
||||
<el-table-column prop="age" label="年龄" />
|
||||
<el-table-column prop="gender" label="性别" />
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="离职记录" name="leave">
|
||||
<el-table :data="leaveRecords" style="width: 100%" height="400">
|
||||
<el-table-column prop="wmsEmployeeInfo.name" label="员工姓名" />
|
||||
<el-table-column prop="wmsEmployeeInfo.dept" label="部门" />
|
||||
<el-table-column prop="wmsEmployeeInfo.jobType" label="职位" />
|
||||
<el-table-column prop="changeTime" label="离职日期" />
|
||||
<el-table-column prop="changeReason" label="离职原因" />
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="入职记录" name="entry">
|
||||
<el-table :data="entryRecords" style="width: 100%" height="400">
|
||||
<el-table-column prop="wmsEmployeeInfo.name" label="员工姓名" />
|
||||
<el-table-column prop="wmsEmployeeInfo.dept" label="部门" />
|
||||
<el-table-column prop="wmsEmployeeInfo.jobType" label="职位" />
|
||||
<el-table-column prop="entryDate" label="入职日期" />
|
||||
<el-table-column prop="wmsEmployeeInfo.education" label="学历" />
|
||||
<el-table-column prop="wmsEmployeeInfo.gender" label="性别" />
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="转正记录" name="regular">
|
||||
<el-table :data="regularRecords" style="width: 100%" height="400">
|
||||
<el-table-column prop="wmsEmployeeInfo.name" label="员工姓名" />
|
||||
<el-table-column prop="wmsEmployeeInfo.dept" label="部门" />
|
||||
<el-table-column prop="wmsEmployeeInfo.jobType" label="职位" />
|
||||
<el-table-column prop="regularDate" label="转正日期" />
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="调岗记录" name="transfer">
|
||||
<el-table :data="transferRecords" style="width: 100%" height="400">
|
||||
<el-table-column prop="wmsEmployeeInfo.name" label="员工姓名" />
|
||||
<el-table-column prop="transferTime" label="调岗日期" />
|
||||
<el-table-column prop="oldDept" label="原部门" />
|
||||
<el-table-column prop="oldJobType" label="原职位" />
|
||||
<el-table-column prop="newDept" label="新部门" />
|
||||
<el-table-column prop="newJobType" label="新职位" />
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from 'echarts'
|
||||
import { listEmployeeInfo } from '@/api/wms/employeeInfo'
|
||||
import { listEmployeeChange } from '@/api/wms/employeeChange'
|
||||
import { listEmployeeTransfer } from '@/api/wms/employeeTransfer'
|
||||
|
||||
export default {
|
||||
name: 'EmployeeReport',
|
||||
data() {
|
||||
return {
|
||||
dateRange: this.getMonthRange(), // 默认选中本月
|
||||
employeeDateRange: ['', ''],
|
||||
shortcuts: [
|
||||
{
|
||||
text: '本月',
|
||||
value: () => {
|
||||
return this.getMonthRange()
|
||||
}
|
||||
},
|
||||
{
|
||||
text: '上个月',
|
||||
value: () => {
|
||||
const date = new Date()
|
||||
const firstDay = new Date(date.getFullYear(), date.getMonth() - 1, 1, 0, 0, 0)
|
||||
const lastDay = new Date(date.getFullYear(), date.getMonth(), 0, 23, 59, 59)
|
||||
|
||||
// 格式化日期为yyyy-MM-dd HH:mm:ss格式
|
||||
const formatDate = (date) => {
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||
}
|
||||
|
||||
return [formatDate(firstDay), formatDate(lastDay)]
|
||||
}
|
||||
},
|
||||
{
|
||||
text: '近三个月',
|
||||
value: () => {
|
||||
const date = new Date()
|
||||
const lastDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
|
||||
const firstDay = new Date(date.getFullYear(), date.getMonth() - 2, 1, 0, 0, 0)
|
||||
|
||||
// 格式化日期为yyyy-MM-dd HH:mm:ss格式
|
||||
const formatDate = (date) => {
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||
}
|
||||
|
||||
return [formatDate(firstDay), formatDate(lastDay)]
|
||||
}
|
||||
},
|
||||
{
|
||||
text: '本年',
|
||||
value: () => {
|
||||
const date = new Date()
|
||||
const firstDay = new Date(date.getFullYear(), 0, 1, 0, 0, 0)
|
||||
const lastDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
|
||||
|
||||
// 格式化日期为yyyy-MM-dd HH:mm:ss格式
|
||||
const formatDate = (date) => {
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||
}
|
||||
|
||||
return [formatDate(firstDay), formatDate(lastDay)]
|
||||
}
|
||||
}
|
||||
],
|
||||
stats: {
|
||||
totalEmployees: 0,
|
||||
regularEmployees: 0,
|
||||
probationEmployees: 0,
|
||||
entryCount: 0,
|
||||
leaveCount: 0,
|
||||
regularCount: 0,
|
||||
transferCount: 0
|
||||
},
|
||||
currentEmployees: [],
|
||||
leaveRecords: [],
|
||||
entryRecords: [],
|
||||
regularRecords: [],
|
||||
transferRecords: [],
|
||||
activeTab: 'current',
|
||||
charts: {},
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 默认设置为当前月
|
||||
this.dateRange = this.getMonthRange()
|
||||
this.initCharts()
|
||||
this.handleQuery()
|
||||
},
|
||||
methods: {
|
||||
getMonthRange() {
|
||||
const date = new Date()
|
||||
// 当月第一天,00:00:00
|
||||
const firstDay = new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0)
|
||||
// 当月最后一天,23:59:59
|
||||
const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0, 23, 59, 59)
|
||||
|
||||
// 格式化日期为yyyy-MM-dd HH:mm:ss格式
|
||||
const formatDate = (date) => {
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||
}
|
||||
|
||||
return [formatDate(firstDay), formatDate(lastDay)]
|
||||
},
|
||||
initCharts() {
|
||||
this.charts.educationChart = echarts.init(document.getElementById('educationChart'))
|
||||
this.charts.ageChart = echarts.init(document.getElementById('ageChart'))
|
||||
this.charts.genderChart = echarts.init(document.getElementById('genderChart'))
|
||||
this.charts.trendChart = echarts.init(document.getElementById('trendChart'))
|
||||
|
||||
// 监听窗口大小变化,自适应图表
|
||||
window.addEventListener('resize', () => {
|
||||
Object.values(this.charts).forEach(chart => chart.resize())
|
||||
})
|
||||
},
|
||||
handleQuery() {
|
||||
const queryParams = {
|
||||
startTime: this.dateRange ? this.dateRange[0] : '',
|
||||
endTime: this.dateRange ? this.dateRange[1] : '',
|
||||
entryStartTime: this.employeeDateRange ? this.employeeDateRange[0] : '',
|
||||
entryEndTime: this.employeeDateRange ? this.employeeDateRange[1] : '',
|
||||
}
|
||||
this.loadData(queryParams)
|
||||
},
|
||||
async loadData(queryParams) {
|
||||
this.loading = true
|
||||
try {
|
||||
await Promise.all([
|
||||
this.loadEmployeeData(queryParams),
|
||||
this.loadChangeData(queryParams),
|
||||
this.loadTransferData(queryParams)
|
||||
])
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
resetQuery() {
|
||||
this.dateRange = this.getMonthRange()
|
||||
this.handleQuery()
|
||||
},
|
||||
loadEmployeeData(queryParams) {
|
||||
console.log(queryParams)
|
||||
return new Promise((resolve) => {
|
||||
listEmployeeInfo(queryParams).then(response => {
|
||||
const data = response.rows
|
||||
this.currentEmployees = data
|
||||
|
||||
// 统计当前员工信息
|
||||
this.stats.totalEmployees = data.length
|
||||
this.stats.regularEmployees = data.filter(item => item.status === '已转正').length
|
||||
this.stats.probationEmployees = data.filter(item => item.status === '试用期').length
|
||||
|
||||
// 生成学历分布图表
|
||||
this.updateEducationChart()
|
||||
// 生成年龄段分布图表
|
||||
this.updateAgeChart()
|
||||
// 生成性别分布图表
|
||||
this.updateGenderChart()
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
loadChangeData(queryParams) {
|
||||
return new Promise((resolve) => {
|
||||
listEmployeeChange({
|
||||
changeStartTime: queryParams.startTime,
|
||||
changeEndTime: queryParams.endTime
|
||||
}).then(response => {
|
||||
const data = response.rows
|
||||
|
||||
// 分类处理异动记录
|
||||
this.entryRecords = data.filter(item => item.changeType == 0)
|
||||
this.leaveRecords = data.filter(item => item.changeType == 1)
|
||||
this.regularRecords = data.filter(item => item.changeType == 2)
|
||||
|
||||
// 统计异动数据
|
||||
this.stats.entryCount = this.entryRecords.length
|
||||
this.stats.leaveCount = this.leaveRecords.length
|
||||
this.stats.regularCount = this.regularRecords.length
|
||||
|
||||
// 更新趋势图表
|
||||
this.updateTrendChart()
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
loadTransferData(queryParams) {
|
||||
return new Promise((resolve) => {
|
||||
listEmployeeTransfer({
|
||||
transferStartTime: queryParams.startTime,
|
||||
transferEndTime: queryParams.endTime
|
||||
}).then(response => {
|
||||
const data = response.rows
|
||||
console.log(data, '调岗记录')
|
||||
this.transferRecords = data
|
||||
this.stats.transferCount = data.length
|
||||
|
||||
// 更新趋势图表
|
||||
this.updateTrendChart()
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
updateEducationChart() {
|
||||
// 统计学历分布
|
||||
const educationData = {}
|
||||
this.currentEmployees.forEach(emp => {
|
||||
const edu = emp.education || '未知'
|
||||
educationData[edu] = (educationData[edu] || 0) + 1
|
||||
})
|
||||
|
||||
const option = {
|
||||
title: {
|
||||
text: '学历分布',
|
||||
left: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '学历',
|
||||
type: 'pie',
|
||||
radius: '50%',
|
||||
data: Object.entries(educationData).map(([name, value]) => ({ name, value })),
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.charts.educationChart.setOption(option)
|
||||
},
|
||||
updateAgeChart() {
|
||||
// 统计年龄段分布
|
||||
const ageGroups = {
|
||||
'20岁以下': 0,
|
||||
'20-30岁': 0,
|
||||
'30-40岁': 0,
|
||||
'40-50岁': 0,
|
||||
'50岁以上': 0
|
||||
}
|
||||
|
||||
this.currentEmployees.forEach(emp => {
|
||||
const age = parseInt(emp.age) || 0
|
||||
if (age < 20) ageGroups['20岁以下']++
|
||||
else if (age < 30) ageGroups['20-30岁']++
|
||||
else if (age < 40) ageGroups['30-40岁']++
|
||||
else if (age < 50) ageGroups['40-50岁']++
|
||||
else ageGroups['50岁以上']++
|
||||
})
|
||||
|
||||
const option = {
|
||||
title: {
|
||||
text: '年龄段分布',
|
||||
left: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: Object.keys(ageGroups)
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '人数',
|
||||
type: 'bar',
|
||||
data: Object.values(ageGroups),
|
||||
itemStyle: {
|
||||
color: '#409EFF'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.charts.ageChart.setOption(option)
|
||||
},
|
||||
updateGenderChart() {
|
||||
// 统计性别分布
|
||||
const genderData = {
|
||||
'男': 0,
|
||||
'女': 0
|
||||
}
|
||||
this.currentEmployees.forEach(emp => {
|
||||
if (emp.gender === '男' || emp.gender === '女') {
|
||||
genderData[emp.gender]++
|
||||
}
|
||||
})
|
||||
|
||||
const option = {
|
||||
title: {
|
||||
text: '性别分布',
|
||||
left: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '性别',
|
||||
type: 'pie',
|
||||
radius: '50%',
|
||||
data: Object.entries(genderData).map(([name, value]) => ({ name, value })),
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.charts.genderChart.setOption(option)
|
||||
},
|
||||
updateTrendChart() {
|
||||
// 生成时间序列数据
|
||||
const timeRange = this.generateTimeRange()
|
||||
const trendData = {
|
||||
entry: new Array(timeRange.length).fill(0),
|
||||
leave: new Array(timeRange.length).fill(0),
|
||||
regular: new Array(timeRange.length).fill(0),
|
||||
transfer: new Array(timeRange.length).fill(0)
|
||||
}
|
||||
|
||||
// 提取日期部分的辅助函数
|
||||
const getDatePart = (datetime) => {
|
||||
if (!datetime) return ''
|
||||
return datetime.split(' ')[0]
|
||||
}
|
||||
|
||||
// 填充入职数据
|
||||
this.entryRecords.forEach(record => {
|
||||
const datePart = getDatePart(record.changeTime)
|
||||
const index = timeRange.indexOf(datePart)
|
||||
if (index !== -1) trendData.entry[index]++
|
||||
})
|
||||
|
||||
// 填充离职数据
|
||||
this.leaveRecords.forEach(record => {
|
||||
const datePart = getDatePart(record.changeTime)
|
||||
const index = timeRange.indexOf(datePart)
|
||||
if (index !== -1) trendData.leave[index]++
|
||||
})
|
||||
|
||||
// 填充转正数据
|
||||
this.regularRecords.forEach(record => {
|
||||
const datePart = getDatePart(record.changeTime)
|
||||
const index = timeRange.indexOf(datePart)
|
||||
if (index !== -1) trendData.regular[index]++
|
||||
})
|
||||
|
||||
// 填充调岗数据
|
||||
this.transferRecords.forEach(record => {
|
||||
const datePart = getDatePart(record.transferTime)
|
||||
const index = timeRange.indexOf(datePart)
|
||||
if (index !== -1) trendData.transfer[index]++
|
||||
})
|
||||
|
||||
const option = {
|
||||
title: {
|
||||
text: '员工变动趋势',
|
||||
left: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
legend: {
|
||||
data: ['入职', '离职', '转正', '调岗'],
|
||||
bottom: 0
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '15%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: timeRange
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '入职',
|
||||
type: 'line',
|
||||
stack: 'Total',
|
||||
data: trendData.entry,
|
||||
itemStyle: {
|
||||
color: '#67C23A'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '离职',
|
||||
type: 'line',
|
||||
stack: 'Total',
|
||||
data: trendData.leave,
|
||||
itemStyle: {
|
||||
color: '#F56C6C'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '转正',
|
||||
type: 'line',
|
||||
stack: 'Total',
|
||||
data: trendData.regular,
|
||||
itemStyle: {
|
||||
color: '#409EFF'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '调岗',
|
||||
type: 'line',
|
||||
stack: 'Total',
|
||||
data: trendData.transfer,
|
||||
itemStyle: {
|
||||
color: '#E6A23C'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.charts.trendChart.setOption(option)
|
||||
},
|
||||
generateTimeRange() {
|
||||
// 生成时间范围内的日期数组
|
||||
const start = this.dateRange && this.dateRange[0] ? new Date(this.dateRange[0]) : new Date()
|
||||
const end = this.dateRange && this.dateRange[1] ? new Date(this.dateRange[1]) : new Date()
|
||||
const timeRange = []
|
||||
|
||||
// 如果没有设置时间范围,默认显示最近30天
|
||||
if (!this.dateRange || !this.dateRange[0] || !this.dateRange[1]) {
|
||||
const thirtyDaysAgo = new Date()
|
||||
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30)
|
||||
start.setTime(thirtyDaysAgo.getTime())
|
||||
}
|
||||
|
||||
const current = new Date(start)
|
||||
while (current <= end) {
|
||||
const dateStr = current.toISOString().split('T')[0]
|
||||
timeRange.push(dateStr)
|
||||
current.setDate(current.getDate() + 1)
|
||||
}
|
||||
|
||||
return timeRange
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.employee-report {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
margin-bottom: 20px;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.stats-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.stats-cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #409EFF;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.stats-chart {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.interactive-charts-section {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.chart-card {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.trend-section {
|
||||
margin-bottom: 20px;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.details-section {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,8 +1,34 @@
|
||||
<template>
|
||||
<div class="coil-table">
|
||||
<!-- 其他props -->
|
||||
<div class="table-controls">
|
||||
<div class="filter-section">
|
||||
<el-input v-model="filterKeyword" placeholder="输入关键词筛选" clearable @input="handleFilterChange"
|
||||
style="width: 200px; margin-right: 10px" />
|
||||
<el-select v-model="filterColumn" placeholder="选择筛选字段" @change="handleFilterChange"
|
||||
style="width: 200px; margin-right: 10px"
|
||||
multiple
|
||||
collapse-tags>
|
||||
<el-option v-for="column in columns" :key="column.prop" :label="column.title" :value="column.prop" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="sort-section">
|
||||
<el-select v-model="sortField" placeholder="选择排序字段" @change="handleSortChange"
|
||||
style="width: 150px; margin-right: 10px">
|
||||
<el-option v-for="column in columns" :key="column.prop" :label="column.title" :value="column.prop" />
|
||||
</el-select>
|
||||
<el-select v-model="sortDirection" placeholder="选择排序方向" @change="handleSortChange" style="width: 100px">
|
||||
<el-option label="升序" value="asc" />
|
||||
<el-option label="降序" value="desc" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-pagination layout="total, sizes, prev, pager, next, jumper" :total="total" :page-size.sync="pageSize"
|
||||
:page-sizes="[10, 20, 50, 100, 200, 500, 1000]" @size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange" />
|
||||
</div>
|
||||
|
||||
<el-table :data="tableData" style="width: 100%" height="calc(100vh - 320px)" border>
|
||||
<el-table-column v-for="column in columns" :key="column.prop" :prop="column.prop" :label="column.title" :width="column.width" :align="column.align">
|
||||
<el-table-column v-for="column in columns" :key="column.prop" :prop="column.prop" :label="column.title"
|
||||
:width="column.width" :align="column.align">
|
||||
<template slot-scope="scope">
|
||||
<!-- 特殊 prop 渲染逻辑 -->
|
||||
<template v-if="column.prop === 'enterCoilNo'">
|
||||
@@ -18,6 +44,10 @@
|
||||
<template v-else-if="column.prop === 'status'">
|
||||
{{ scope.row.status === 0 ? '在库' : '已出库' }}
|
||||
</template>
|
||||
<!-- 生产耗时,单位分钟,渲染为xx天xx小时xx分钟 -->
|
||||
<template v-else-if="column.prop === 'productionDuration'">
|
||||
{{ formatProductionDuration(scope.row.productionDuration) }}
|
||||
</template>
|
||||
<!-- 默认渲染 -->
|
||||
<template v-else>
|
||||
{{ scope.row[column.prop] }}
|
||||
@@ -25,14 +55,6 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-if="showPagination"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
:page-size.sync="pageSize"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -62,20 +84,80 @@ export default {
|
||||
return {
|
||||
pageNum: 1,
|
||||
pageSize: 1000,
|
||||
// 排序相关
|
||||
sortField: '',
|
||||
sortDirection: 'asc',
|
||||
// 筛选相关
|
||||
filterKeyword: '',
|
||||
filterColumn: [],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 默认选中所有列
|
||||
this.filterColumn = this.columns.map(column => column.prop)
|
||||
},
|
||||
computed: {
|
||||
// 处理排序和筛选后的数据
|
||||
processedData() {
|
||||
let result = [...this.data]
|
||||
|
||||
// 筛选逻辑
|
||||
if (this.filterColumn.length > 0 && this.filterKeyword) {
|
||||
const keyword = this.filterKeyword.toLowerCase()
|
||||
result = result.filter(item => {
|
||||
// 只要有一个字段匹配,就保留该记录
|
||||
return this.filterColumn.some(column => {
|
||||
const value = item[column]
|
||||
if (value === null || value === undefined) return false
|
||||
return String(value).toLowerCase().includes(keyword)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 排序逻辑
|
||||
if (this.sortField) {
|
||||
result.sort((a, b) => {
|
||||
const aValue = a[this.sortField]
|
||||
const bValue = b[this.sortField]
|
||||
|
||||
// 处理null和undefined
|
||||
if (aValue === null || aValue === undefined) return 1
|
||||
if (bValue === null || bValue === undefined) return -1
|
||||
|
||||
// 字符串比较
|
||||
if (typeof aValue === 'string' && typeof bValue === 'string') {
|
||||
return this.sortDirection === 'asc'
|
||||
? aValue.localeCompare(bValue)
|
||||
: bValue.localeCompare(aValue)
|
||||
}
|
||||
|
||||
// 数字比较
|
||||
if (typeof aValue === 'number' && typeof bValue === 'number') {
|
||||
return this.sortDirection === 'asc'
|
||||
? aValue - bValue
|
||||
: bValue - aValue
|
||||
}
|
||||
|
||||
// 其他类型比较
|
||||
return this.sortDirection === 'asc'
|
||||
? String(aValue).localeCompare(String(bValue))
|
||||
: String(bValue).localeCompare(String(aValue))
|
||||
})
|
||||
}
|
||||
|
||||
return result
|
||||
},
|
||||
// 内部实现前端分页逻辑
|
||||
tableData() {
|
||||
return this.data.slice((this.pageNum - 1) * this.pageSize, this.pageNum * this.pageSize)
|
||||
return this.processedData.slice((this.pageNum - 1) * this.pageSize, this.pageNum * this.pageSize)
|
||||
},
|
||||
// 计算总页数
|
||||
totalPage() {
|
||||
return Math.ceil(this.data.length / this.pageSize)
|
||||
return Math.ceil(this.processedData.length / this.pageSize)
|
||||
},
|
||||
// 计算总条数
|
||||
total() {
|
||||
return this.data.length
|
||||
return this.processedData.length
|
||||
},
|
||||
// 是否展示分页组件
|
||||
showPagination() {
|
||||
@@ -92,6 +174,72 @@ export default {
|
||||
handleCurrentChange(val) {
|
||||
this.pageNum = val
|
||||
},
|
||||
// 生产耗时,单位分钟,渲染为xx天xx小时xx分钟
|
||||
formatProductionDuration(duration) {
|
||||
if (!duration || isNaN(duration)) {
|
||||
return '0分钟'
|
||||
}
|
||||
const days = Math.floor(duration / 1440)
|
||||
const hours = Math.floor((duration - days * 1440) / 60)
|
||||
const minutes = duration - days * 1440 - hours * 60
|
||||
let result = ''
|
||||
if (days > 0) {
|
||||
result += `${days}天`
|
||||
}
|
||||
if (hours > 0) {
|
||||
result += `${hours}小时`
|
||||
}
|
||||
if (minutes > 0 || (days === 0 && hours === 0)) {
|
||||
result += `${minutes}分钟`
|
||||
}
|
||||
return result
|
||||
},
|
||||
// 处理筛选条件变化
|
||||
handleFilterChange() {
|
||||
this.pageNum = 1
|
||||
},
|
||||
// 处理排序规则变化
|
||||
handleSortChange() {
|
||||
this.pageNum = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.coil-table {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.table-controls {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.filter-section,
|
||||
.sort-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.el-pagination {
|
||||
margin-top: 0px !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.table-controls {
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.filter-section,
|
||||
.sort-section {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -136,8 +136,15 @@ export default {
|
||||
optionalProps: [
|
||||
{ label: '入场钢卷号', value: 'enterCoilNo' },
|
||||
{ label: '当前钢卷号', value: 'currentCoilNo' },
|
||||
{ label: '厂家钢卷号', value: 'supplierCoilNo' },
|
||||
{ label: '逻辑库区', value: 'warehouseName' },
|
||||
{ label: '实际库区', value: 'actualWarehouseName' },
|
||||
|
||||
{ label: '质量状态', value: 'qualityStatus' },
|
||||
{ label: '切边要求', value: 'trimmingRequirement' },
|
||||
{ label: '打包状态', value: 'packingStatus' },
|
||||
{ label: '包装要求', value: 'packagingRequirement' },
|
||||
|
||||
{ label: '产品类型', value: 'itemId' },
|
||||
{ label: '品名', value: 'itemName' },
|
||||
{ label: '宽度', value: 'computedWidth' },
|
||||
|
||||
@@ -59,11 +59,11 @@ const calcAbSummary = (list) => {
|
||||
returnWeight: 0,
|
||||
|
||||
// 计入技术部的钢卷占比
|
||||
jishuRate: 0,
|
||||
jishuRate: 0,
|
||||
// 计入小钢卷库的钢卷占比
|
||||
miniRate: 0,
|
||||
miniRate: 0,
|
||||
// 计入废品库的钢卷占比
|
||||
rubbishRate: 0,
|
||||
rubbishRate: 0,
|
||||
// 计入退货库的钢卷占比
|
||||
returnRate: 0,
|
||||
}
|
||||
@@ -76,22 +76,28 @@ const calcAbSummary = (list) => {
|
||||
// 技术部
|
||||
const coil = list[i];
|
||||
// 技术部
|
||||
if (coil.warehouseId == '2019583656787259393') {
|
||||
if (coil.warehouseId == '2019583656787259393' || coil.qualityStatus == 'O') {
|
||||
o['jishuCount'] = o['jishuCount'] + 1
|
||||
o['jishuWeight'] = o['jishuWeight'] + parseFloat(coil.netWeight) || 0
|
||||
}
|
||||
// 小刚卷库
|
||||
if (coil.warehouseId == '2019583325311414274') {
|
||||
else if (coil.warehouseId == '2019583325311414274') {
|
||||
o['miniCount'] = o['miniCount'] + 1
|
||||
o['miniWeight'] = o['miniWeight'] + parseFloat(coil.netWeight) || 0
|
||||
}
|
||||
// 废品库
|
||||
if (coil.warehouseId == '2019583429955104769') {
|
||||
// 废品库, 或者之状态为D-,D,D+,C-,C,C+其中之一
|
||||
else if (coil.warehouseId == '2019583429955104769'
|
||||
|| coil.qualityStatus == 'D-' ||
|
||||
coil.qualityStatus == 'D' ||
|
||||
coil.qualityStatus == 'D+' ||
|
||||
coil.qualityStatus == 'C-' ||
|
||||
coil.qualityStatus == 'C' ||
|
||||
coil.qualityStatus == 'C+') {
|
||||
o['rubbishCount'] = o['rubbishCount'] + 1
|
||||
o['rubbishWeight'] = o['rubbishWeight'] + parseFloat(coil.netWeight) || 0
|
||||
}
|
||||
// 退货库
|
||||
if (coil.warehouseId == '2019583137616310273') {
|
||||
else if (coil.warehouseId == '2019583137616310273') {
|
||||
o['returnCount'] = o['returnCount'] + 1
|
||||
o['returnWeight'] = o['returnWeight'] + parseFloat(coil.netWeight) || 0
|
||||
}
|
||||
@@ -133,35 +139,35 @@ const calcTeamSummary = (list) => {
|
||||
|
||||
const calcMSummary = (list, lossList) => {
|
||||
// 统计,需要二外处理M卷,也就是钢卷的currentCoilNo中带有M的钢卷,在统计产出钢卷的数量和重量时需要忽略并记录,并且在统计消耗钢卷的总重量时也需要移除
|
||||
|
||||
|
||||
// 筛选出 M 卷
|
||||
const mCoils = list.filter(item => item.currentCoilNo && item.currentCoilNo.includes('M'))
|
||||
// 非 M 卷
|
||||
const nonMCoils = list.filter(item => !item.currentCoilNo || !item.currentCoilNo.includes('M'))
|
||||
|
||||
|
||||
// 非 M 卷作为产出统计
|
||||
const outCount = nonMCoils.length
|
||||
const outTotalWeight = nonMCoils.reduce((acc, cur) => acc + (parseFloat(cur.netWeight) || 0), 0)
|
||||
const outAvgWeight = outCount > 0 ? (outTotalWeight / outCount)?.toFixed(2) : 0
|
||||
|
||||
|
||||
// 计算产出的 M 卷总重量
|
||||
const mOutTotalWeight = mCoils.reduce((acc, cur) => acc + (parseFloat(cur.netWeight) || 0), 0)
|
||||
|
||||
|
||||
// 消耗钢卷统计(数量包括所有卷,但总重量减去产出的 M 卷重量)
|
||||
const lossCount = lossList.length
|
||||
const lossTotalWeight = lossList.reduce((acc, cur) => acc + (parseFloat(cur.netWeight) || 0), 0) - mOutTotalWeight
|
||||
const lossAvgWeight = lossCount > 0 ? (lossTotalWeight / lossCount)?.toFixed(2) : 0
|
||||
|
||||
|
||||
// 合计
|
||||
const totalCount = outCount + lossCount
|
||||
const totalWeight = parseFloat((outTotalWeight + lossTotalWeight).toFixed(2))
|
||||
const totalAvgWeight = totalCount > 0 ? (totalWeight / totalCount)?.toFixed(2) : 0
|
||||
|
||||
|
||||
// 成品比率
|
||||
const passRate = outCount > 0 && lossTotalWeight > 0 ? (outTotalWeight / lossTotalWeight) : 0
|
||||
// 损失比率
|
||||
const lossRate = totalCount > 0 ? (1 - passRate) : 0
|
||||
|
||||
|
||||
// 异常率,成品在warehouseId在'2019583656787259393',
|
||||
// '2019583325311414274',
|
||||
// '2019583429955104769',
|
||||
@@ -172,7 +178,7 @@ const calcMSummary = (list, lossList) => {
|
||||
|
||||
// 正品率(1-异常率)
|
||||
const passRate2 = totalCount != 0 ? (1 - abRate) : 0
|
||||
|
||||
|
||||
return {
|
||||
outCount,
|
||||
outTotalWeight: outTotalWeight.toFixed(2),
|
||||
|
||||
@@ -26,6 +26,16 @@ const defaultColumns = {
|
||||
prop: "productionEndTime",
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: "生产耗时",
|
||||
prop: "productionDuration",
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '质量状态',
|
||||
prop: 'qualityStatus',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: "逻辑库区",
|
||||
prop: "warehouseName",
|
||||
@@ -92,6 +102,11 @@ const defaultColumns = {
|
||||
prop: "warehouseName",
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '质量状态',
|
||||
prop: 'qualityStatus',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: "产品类型",
|
||||
prop: "itemId",
|
||||
@@ -148,6 +163,11 @@ const defaultColumns = {
|
||||
prop: "warehouseName",
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '质量状态',
|
||||
prop: 'qualityStatus',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: "产品类型",
|
||||
prop: "itemId",
|
||||
@@ -209,6 +229,11 @@ const defaultColumns = {
|
||||
prop: "warehouseName",
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '质量状态',
|
||||
prop: 'qualityStatus',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: "产品类型",
|
||||
prop: "itemId",
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<el-row>
|
||||
<el-form label-width="80px" inline>
|
||||
<el-form-item label="开始时间" prop="startDate">
|
||||
<el-date-picker style="width: 200px;" v-model="queryParams.startDate" type="date" value-format="yyyy-MM-dd"
|
||||
<el-date-picker style="width: 200px;" v-model="queryParams.byCreateTimeStart" type="date" value-format="yyyy-MM-dd"
|
||||
placeholder="选择开始日期" @change="handleDateChange"></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束时间" prop="endDate">
|
||||
<el-date-picker style="width: 200px;" v-model="queryParams.endDate" type="date" value-format="yyyy-MM-dd"
|
||||
<el-date-picker style="width: 200px;" v-model="queryParams.byCreateTimeEnd" type="date" value-format="yyyy-MM-dd"
|
||||
placeholder="选择结束日期" @change="handleDateChange"></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="入场钢卷号" prop="enterCoilNo">
|
||||
@@ -222,7 +222,7 @@ export default {
|
||||
lossList: [],
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 9999,
|
||||
pageSize: 99999,
|
||||
date: currentDate, // 绑定日期选择器的默认值(当天)
|
||||
byCreateTimeStart: start, // 默认当天0点
|
||||
byCreateTimeEnd: end, // 默认当天23:59:59
|
||||
@@ -250,6 +250,8 @@ export default {
|
||||
|
||||
lossColumns: [],
|
||||
outputColumns: [],
|
||||
|
||||
actionIds: '',
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -335,7 +337,7 @@ export default {
|
||||
actionStatus: 2,
|
||||
warehouseId: this.queryParams.planId,
|
||||
actionType,
|
||||
pageSize: 9999,
|
||||
pageSize: 99999,
|
||||
pageNum: 1,
|
||||
startTime: this.queryParams.byCreateTimeStart,
|
||||
endTime: this.queryParams.byCreateTimeEnd,
|
||||
@@ -343,6 +345,7 @@ export default {
|
||||
})
|
||||
}))
|
||||
const actions = resultList.flatMap(item => item.rows)
|
||||
this.actionIds = actions.map(item => item.actionId).join(',')
|
||||
const coilIds = actions.map(item => item.coilId).join(',')
|
||||
console.log(coilIds)
|
||||
if (!coilIds) {
|
||||
|
||||
@@ -197,7 +197,7 @@ export default {
|
||||
lossList: [],
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 9999,
|
||||
pageSize: 99999,
|
||||
date: currentDate, // 绑定日期选择器的默认值(当天)
|
||||
byCreateTimeStart: start, // 默认当天0点
|
||||
byCreateTimeEnd: end, // 默认当天23:59:59
|
||||
@@ -301,9 +301,7 @@ export default {
|
||||
computedWidth: parseFloat(width),
|
||||
}
|
||||
})
|
||||
// this.loading = false
|
||||
this.getLossList()
|
||||
// this.loading = false
|
||||
})
|
||||
},
|
||||
async getLossList() {
|
||||
@@ -313,7 +311,7 @@ export default {
|
||||
actionStatus: 2,
|
||||
warehouseId: this.queryParams.planId,
|
||||
actionType,
|
||||
pageSize: 9999,
|
||||
pageSize: 99999,
|
||||
pageNum: 1,
|
||||
startTime: this.queryParams.byCreateTimeStart,
|
||||
endTime: this.queryParams.byCreateTimeEnd,
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.klp.controller;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.*;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.validate.AddGroup;
|
||||
import com.klp.common.core.validate.EditGroup;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.common.utils.poi.ExcelUtil;
|
||||
import com.klp.domain.vo.WmsCoilPackingDetailVo;
|
||||
import com.klp.domain.bo.WmsCoilPackingDetailBo;
|
||||
import com.klp.service.IWmsCoilPackingDetailService;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 钢卷打包明细(存储每个钢卷的库区/重量信息)
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/wms/coilPackingDetail")
|
||||
public class WmsCoilPackingDetailController extends BaseController {
|
||||
|
||||
private final IWmsCoilPackingDetailService iWmsCoilPackingDetailService;
|
||||
|
||||
/**
|
||||
* 查询钢卷打包明细(存储每个钢卷的库区/重量信息)列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<WmsCoilPackingDetailVo> list(WmsCoilPackingDetailBo bo, PageQuery pageQuery) {
|
||||
return iWmsCoilPackingDetailService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出钢卷打包明细(存储每个钢卷的库区/重量信息)列表
|
||||
*/
|
||||
@Log(title = "钢卷打包明细(存储每个钢卷的库区/重量信息)", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(WmsCoilPackingDetailBo bo, HttpServletResponse response) {
|
||||
List<WmsCoilPackingDetailVo> list = iWmsCoilPackingDetailService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "钢卷打包明细(存储每个钢卷的库区/重量信息)", WmsCoilPackingDetailVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取钢卷打包明细(存储每个钢卷的库区/重量信息)详细信息
|
||||
*
|
||||
* @param detailId 主键
|
||||
*/
|
||||
@GetMapping("/{detailId}")
|
||||
public R<WmsCoilPackingDetailVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long detailId) {
|
||||
return R.ok(iWmsCoilPackingDetailService.queryById(detailId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增钢卷打包明细(存储每个钢卷的库区/重量信息)
|
||||
*/
|
||||
@Log(title = "钢卷打包明细(存储每个钢卷的库区/重量信息)", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody WmsCoilPackingDetailBo bo) {
|
||||
return toAjax(iWmsCoilPackingDetailService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改钢卷打包明细(存储每个钢卷的库区/重量信息)
|
||||
*/
|
||||
@Log(title = "钢卷打包明细(存储每个钢卷的库区/重量信息)", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WmsCoilPackingDetailBo bo) {
|
||||
return toAjax(iWmsCoilPackingDetailService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除钢卷打包明细(存储每个钢卷的库区/重量信息)
|
||||
*
|
||||
* @param detailIds 主键串
|
||||
*/
|
||||
@Log(title = "钢卷打包明细(存储每个钢卷的库区/重量信息)", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{detailIds}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] detailIds) {
|
||||
return toAjax(iWmsCoilPackingDetailService.deleteWithValidByIds(Arrays.asList(detailIds), true));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.klp.controller;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.*;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import com.klp.common.annotation.RepeatSubmit;
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.validate.AddGroup;
|
||||
import com.klp.common.core.validate.EditGroup;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.common.utils.poi.ExcelUtil;
|
||||
import com.klp.domain.vo.WmsCoilPackingRecordVo;
|
||||
import com.klp.domain.bo.WmsCoilPackingRecordBo;
|
||||
import com.klp.service.IWmsCoilPackingRecordService;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 钢卷打包记录主(打包待发区专用)
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/wms/coilPackingRecord")
|
||||
public class WmsCoilPackingRecordController extends BaseController {
|
||||
|
||||
private final IWmsCoilPackingRecordService iWmsCoilPackingRecordService;
|
||||
|
||||
/**
|
||||
* 查询钢卷打包记录主(打包待发区专用)列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<WmsCoilPackingRecordVo> list(WmsCoilPackingRecordBo bo, PageQuery pageQuery) {
|
||||
return iWmsCoilPackingRecordService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出钢卷打包记录主(打包待发区专用)列表
|
||||
*/
|
||||
@Log(title = "钢卷打包记录主(打包待发区专用)", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(WmsCoilPackingRecordBo bo, HttpServletResponse response) {
|
||||
List<WmsCoilPackingRecordVo> list = iWmsCoilPackingRecordService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "钢卷打包记录主(打包待发区专用)", WmsCoilPackingRecordVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取钢卷打包记录主(打包待发区专用)详细信息
|
||||
*
|
||||
* @param packingId 主键
|
||||
*/
|
||||
@GetMapping("/{packingId}")
|
||||
public R<WmsCoilPackingRecordVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long packingId) {
|
||||
return R.ok(iWmsCoilPackingRecordService.queryById(packingId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增钢卷打包记录主(打包待发区专用)
|
||||
*/
|
||||
@Log(title = "钢卷打包记录主(打包待发区专用)", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody WmsCoilPackingRecordBo bo) {
|
||||
return toAjax(iWmsCoilPackingRecordService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改钢卷打包记录主(打包待发区专用)
|
||||
*/
|
||||
@Log(title = "钢卷打包记录主(打包待发区专用)", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WmsCoilPackingRecordBo bo) {
|
||||
return toAjax(iWmsCoilPackingRecordService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除钢卷打包记录主(打包待发区专用)
|
||||
*
|
||||
* @param packingIds 主键串
|
||||
*/
|
||||
@Log(title = "钢卷打包记录主(打包待发区专用)", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{packingIds}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] packingIds) {
|
||||
return toAjax(iWmsCoilPackingRecordService.deleteWithValidByIds(Arrays.asList(packingIds), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行钢卷打包操作
|
||||
*/
|
||||
@Log(title = "钢卷打包", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/execute")
|
||||
public R<Void> executePacking(@Validated(AddGroup.class) @RequestBody WmsCoilPackingRecordBo bo) {
|
||||
return toAjax(iWmsCoilPackingRecordService.packing(bo));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.klp.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 钢卷打包明细(存储每个钢卷的库区/重量信息)对象 wms_coil_packing_detail
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("wms_coil_packing_detail")
|
||||
public class WmsCoilPackingDetail extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID=1L;
|
||||
|
||||
/**
|
||||
* 明细主键ID
|
||||
*/
|
||||
@TableId(value = "detail_id")
|
||||
private Long detailId;
|
||||
/**
|
||||
* 关联打包主表ID
|
||||
*/
|
||||
private Long packingId;
|
||||
/**
|
||||
* 关联钢卷ID(wms_material_coil.coil_id)
|
||||
*/
|
||||
private Long coilId;
|
||||
/**
|
||||
* 该钢卷打包前的库区ID
|
||||
*/
|
||||
private Long fromWarehouseId;
|
||||
/**
|
||||
* 该钢卷打包后的库区ID(打包待发区)
|
||||
*/
|
||||
private Long toWarehouseId;
|
||||
/**
|
||||
* 该钢卷的毛重
|
||||
*/
|
||||
private BigDecimal coilGrossWeight;
|
||||
/**
|
||||
* 该钢卷的净重
|
||||
*/
|
||||
private BigDecimal coilNetWeight;
|
||||
/**
|
||||
* 删除标志(0=正常,1=已删除)
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer delFlag;
|
||||
/**
|
||||
* 该钢卷的打包备注(如:库区A-钢卷1001)
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.klp.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
/**
|
||||
* 钢卷打包记录主(打包待发区专用)对象 wms_coil_packing_record
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("wms_coil_packing_record")
|
||||
public class WmsCoilPackingRecord extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID=1L;
|
||||
|
||||
/**
|
||||
* 打包记录主键ID
|
||||
*/
|
||||
@TableId(value = "packing_id")
|
||||
private Long packingId;
|
||||
/**
|
||||
* 打包单号(自定义规则:年份后两位+月份+当日打包序号,如25100001)
|
||||
*/
|
||||
private String packingNo;
|
||||
/**
|
||||
* 打包钢卷数量(累计卷数,自动计算)
|
||||
*/
|
||||
private Long coilCount;
|
||||
/**
|
||||
* 打包总毛重(累计重量)
|
||||
*/
|
||||
private BigDecimal totalGrossWeight;
|
||||
/**
|
||||
* 打包总净重(累计重量)
|
||||
*/
|
||||
private BigDecimal totalNetWeight;
|
||||
/**
|
||||
* 销售人员姓名(冗余存储,避免关联查询)
|
||||
*/
|
||||
private String saleName;
|
||||
/**
|
||||
* 打包批次号(如第一批/第二批,或自定义编码:251001-01)
|
||||
*/
|
||||
private String batchNo;
|
||||
/**
|
||||
* 打包状态(0=待打包,1=已打包完成,2=已取消)
|
||||
*/
|
||||
private Integer packingStatus;
|
||||
/**
|
||||
* 打包完成时间
|
||||
*/
|
||||
private Date packingTime;
|
||||
/**
|
||||
* 打包操作人
|
||||
*/
|
||||
private String packingBy;
|
||||
/**
|
||||
* 库区操作备注(如移入打包待发区原因)
|
||||
*/
|
||||
private String warehouseRemark;
|
||||
/**
|
||||
* 删除标志(0=正常,1=已删除)
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer delFlag;
|
||||
/**
|
||||
* 整体打包备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -132,6 +132,9 @@ public class WmsMaterialCoil extends BaseEntity {
|
||||
//销售id
|
||||
private Long saleId;
|
||||
|
||||
//销售人员姓名
|
||||
private String saleName;
|
||||
|
||||
|
||||
//新增长度字段
|
||||
private BigDecimal length;
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.klp.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 钢卷打包明细(存储每个钢卷的库区/重量信息)业务对象 wms_coil_packing_detail
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class WmsCoilPackingDetailBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 明细主键ID
|
||||
*/
|
||||
private Long detailId;
|
||||
|
||||
/**
|
||||
* 关联打包主表ID
|
||||
*/
|
||||
private Long packingId;
|
||||
|
||||
/**
|
||||
* 关联钢卷ID(wms_material_coil.coil_id)
|
||||
*/
|
||||
private Long coilId;
|
||||
|
||||
/**
|
||||
* 该钢卷打包前的库区ID
|
||||
*/
|
||||
private Long fromWarehouseId;
|
||||
|
||||
/**
|
||||
* 该钢卷打包后的库区ID(打包待发区)
|
||||
*/
|
||||
private Long toWarehouseId;
|
||||
|
||||
/**
|
||||
* 该钢卷的毛重
|
||||
*/
|
||||
private BigDecimal coilGrossWeight;
|
||||
|
||||
/**
|
||||
* 该钢卷的净重
|
||||
*/
|
||||
private BigDecimal coilNetWeight;
|
||||
|
||||
/**
|
||||
* 该钢卷的打包备注(如:库区A-钢卷1001)
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
private String saleName;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.klp.domain.bo;
|
||||
|
||||
import com.klp.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
/**
|
||||
* 钢卷打包记录主(打包待发区专用)业务对象 wms_coil_packing_record
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class WmsCoilPackingRecordBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 打包记录主键ID
|
||||
*/
|
||||
private Long packingId;
|
||||
|
||||
/**
|
||||
* 打包单号(自定义规则:年份后两位+月份+当日打包序号,如25100001)
|
||||
*/
|
||||
private String packingNo;
|
||||
|
||||
/**
|
||||
* 打包钢卷数量(累计卷数,自动计算)
|
||||
*/
|
||||
private Long coilCount;
|
||||
|
||||
/**
|
||||
* 打包总毛重(累计重量)
|
||||
*/
|
||||
private BigDecimal totalGrossWeight;
|
||||
|
||||
/**
|
||||
* 打包总净重(累计重量)
|
||||
*/
|
||||
private BigDecimal totalNetWeight;
|
||||
|
||||
/**
|
||||
* 销售人员姓名(冗余存储,避免关联查询)
|
||||
*/
|
||||
private String saleName;
|
||||
|
||||
/**
|
||||
* 打包批次号(如第一批/第二批,或自定义编码:251001-01)
|
||||
*/
|
||||
private String batchNo;
|
||||
|
||||
/**
|
||||
* 打包状态(0=待打包,1=已打包完成,2=已取消)
|
||||
*/
|
||||
private Integer packingStatus;
|
||||
|
||||
/**
|
||||
* 打包完成时间
|
||||
*/
|
||||
private Date packingTime;
|
||||
|
||||
/**
|
||||
* 打包操作人
|
||||
*/
|
||||
private String packingBy;
|
||||
|
||||
/**
|
||||
* 库区操作备注(如移入打包待发区原因)
|
||||
*/
|
||||
private String warehouseRemark;
|
||||
|
||||
/**
|
||||
* 整体打包备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 打包明细列表
|
||||
*/
|
||||
private List<WmsCoilPackingDetailBo> details;
|
||||
|
||||
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import javax.validation.constraints.*;
|
||||
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
/**
|
||||
* 员工异动(入职/离职)业务对象 wms_employee_change
|
||||
@@ -39,6 +40,19 @@ public class WmsEmployeeChangeBo extends BaseEntity {
|
||||
*/
|
||||
private Date changeTime;
|
||||
|
||||
/**
|
||||
* 异动时间开始 带时分秒
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date changeStartTime;
|
||||
|
||||
/**
|
||||
* 异动时间结束
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date changeEndTime;
|
||||
/**
|
||||
* 异动原因(离职必填,入职可选)
|
||||
*/
|
||||
|
||||
@@ -7,6 +7,7 @@ import javax.validation.constraints.*;
|
||||
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
/**
|
||||
* 员工信息业务对象 wms_employee_info
|
||||
@@ -79,6 +80,20 @@ public class WmsEmployeeInfoBo extends BaseEntity {
|
||||
*/
|
||||
private Date entryTime;
|
||||
|
||||
/**
|
||||
* 入职时间开始
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date entryStartTime;
|
||||
|
||||
/**
|
||||
* 入职时间结束
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date entryEndTime;
|
||||
|
||||
/**
|
||||
* 紧急联系人
|
||||
*/
|
||||
@@ -115,4 +130,17 @@ public class WmsEmployeeInfoBo extends BaseEntity {
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date regularTime;
|
||||
|
||||
// 转正开始时间
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date regularStartTime;
|
||||
|
||||
// 转正结束时间
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date regularEndTime;
|
||||
|
||||
|
||||
private Boolean sortByRegularTime;
|
||||
private Boolean sortByEntryTime;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import javax.validation.constraints.*;
|
||||
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
/**
|
||||
* 员工转岗记录业务对象 wms_employee_transfer
|
||||
@@ -54,6 +55,20 @@ public class WmsEmployeeTransferBo extends BaseEntity {
|
||||
*/
|
||||
private Date transferTime;
|
||||
|
||||
/**
|
||||
* 转岗时间开始
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date transferStartTime;
|
||||
|
||||
/**
|
||||
* 转岗时间结束
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date transferEndTime;
|
||||
|
||||
/**
|
||||
* 转岗原因
|
||||
*/
|
||||
|
||||
@@ -214,6 +214,11 @@ public class WmsMaterialCoilBo extends BaseEntity {
|
||||
*/
|
||||
private Boolean excludeBound;
|
||||
|
||||
/**
|
||||
* 是否排除已打包的钢卷(true=列表不返回已打包钢卷)
|
||||
*/
|
||||
private Boolean excludePacked;
|
||||
|
||||
/**
|
||||
* 是否在列表中返回“发货单明细绑定信息”(true=返回 bound + 绑定来源信息)
|
||||
* 默认不返回,避免不需要的场景变慢。
|
||||
@@ -223,6 +228,9 @@ public class WmsMaterialCoilBo extends BaseEntity {
|
||||
//销售id
|
||||
private Long saleId;
|
||||
|
||||
//销售人员姓名
|
||||
private String saleName;
|
||||
|
||||
|
||||
//新增长度字段
|
||||
private BigDecimal length;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.klp.domain.vo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.klp.domain.vo.WmsMaterialCoilVo;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.klp.common.annotation.ExcelDictFormat;
|
||||
import com.klp.common.convert.ExcelDictConvert;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
/**
|
||||
* 钢卷打包明细(存储每个钢卷的库区/重量信息)视图对象 wms_coil_packing_detail
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class WmsCoilPackingDetailVo {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 明细主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "明细主键ID")
|
||||
private Long detailId;
|
||||
|
||||
/**
|
||||
* 关联打包主表ID
|
||||
*/
|
||||
@ExcelProperty(value = "关联打包主表ID")
|
||||
private Long packingId;
|
||||
|
||||
/**
|
||||
* 关联钢卷ID(wms_material_coil.coil_id)
|
||||
*/
|
||||
@ExcelProperty(value = "关联钢卷ID", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "w=ms_material_coil.coil_id")
|
||||
private Long coilId;
|
||||
|
||||
/**
|
||||
* 该钢卷打包前的库区ID
|
||||
*/
|
||||
@ExcelProperty(value = "该钢卷打包前的库区ID")
|
||||
private Long fromWarehouseId;
|
||||
|
||||
/**
|
||||
* 该钢卷打包后的库区ID(打包待发区)
|
||||
*/
|
||||
@ExcelProperty(value = "该钢卷打包后的库区ID", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "打=包待发区")
|
||||
private Long toWarehouseId;
|
||||
|
||||
/**
|
||||
* 该钢卷的毛重
|
||||
*/
|
||||
@ExcelProperty(value = "该钢卷的毛重")
|
||||
private BigDecimal coilGrossWeight;
|
||||
|
||||
/**
|
||||
* 该钢卷的净重
|
||||
*/
|
||||
@ExcelProperty(value = "该钢卷的净重")
|
||||
private BigDecimal coilNetWeight;
|
||||
|
||||
/**
|
||||
* 该钢卷的打包备注(如:库区A-钢卷1001)
|
||||
*/
|
||||
@ExcelProperty(value = "该钢卷的打包备注", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "如=:库区A-钢卷1001")
|
||||
private String remark;
|
||||
|
||||
|
||||
/**
|
||||
* 钢卷完整信息
|
||||
*/
|
||||
private WmsMaterialCoilVo coil;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.klp.domain.vo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.klp.common.annotation.ExcelDictFormat;
|
||||
import com.klp.common.convert.ExcelDictConvert;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
/**
|
||||
* 钢卷打包记录主(打包待发区专用)视图对象 wms_coil_packing_record
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class WmsCoilPackingRecordVo {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 打包记录主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "打包记录主键ID")
|
||||
private Long packingId;
|
||||
|
||||
/**
|
||||
* 打包单号(自定义规则:年份后两位+月份+当日打包序号,如25100001)
|
||||
*/
|
||||
@ExcelProperty(value = "打包单号", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "自=定义规则:年份后两位+月份+当日打包序号,如25100001")
|
||||
private String packingNo;
|
||||
|
||||
/**
|
||||
* 打包钢卷数量(累计卷数,自动计算)
|
||||
*/
|
||||
@ExcelProperty(value = "打包钢卷数量", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "累=计卷数,自动计算")
|
||||
private Long coilCount;
|
||||
|
||||
/**
|
||||
* 打包总毛重(累计重量)
|
||||
*/
|
||||
@ExcelProperty(value = "打包总毛重", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "累=计重量")
|
||||
private BigDecimal totalGrossWeight;
|
||||
|
||||
/**
|
||||
* 打包总净重(累计重量)
|
||||
*/
|
||||
@ExcelProperty(value = "打包总净重", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "累=计重量")
|
||||
private BigDecimal totalNetWeight;
|
||||
|
||||
/**
|
||||
* 销售人员姓名(冗余存储,避免关联查询)
|
||||
*/
|
||||
@ExcelProperty(value = "销售人员姓名", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "冗=余存储,避免关联查询")
|
||||
private String saleName;
|
||||
|
||||
/**
|
||||
* 打包批次号(如第一批/第二批,或自定义编码:251001-01)
|
||||
*/
|
||||
@ExcelProperty(value = "打包批次号", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "如=第一批/第二批,或自定义编码:251001-01")
|
||||
private String batchNo;
|
||||
|
||||
/**
|
||||
* 打包状态(0=待打包,1=已打包完成,2=已取消)
|
||||
*/
|
||||
@ExcelProperty(value = "打包状态", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "0==待打包,1=已打包完成,2=已取消")
|
||||
private Integer packingStatus;
|
||||
|
||||
/**
|
||||
* 打包完成时间
|
||||
*/
|
||||
@ExcelProperty(value = "打包完成时间")
|
||||
private Date packingTime;
|
||||
|
||||
/**
|
||||
* 打包操作人
|
||||
*/
|
||||
@ExcelProperty(value = "打包操作人")
|
||||
private String packingBy;
|
||||
|
||||
/**
|
||||
* 库区操作备注(如移入打包待发区原因)
|
||||
*/
|
||||
@ExcelProperty(value = "库区操作备注", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "如=移入打包待发区原因")
|
||||
private String warehouseRemark;
|
||||
|
||||
/**
|
||||
* 整体打包备注
|
||||
*/
|
||||
@ExcelProperty(value = "整体打包备注")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 明细列表
|
||||
*/
|
||||
private List<WmsCoilPackingDetailVo> details;
|
||||
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.klp.domain.vo;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.klp.common.annotation.Excel;
|
||||
import com.klp.common.annotation.ExcelDictFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@@ -173,9 +174,11 @@ public class WmsMaterialCoilAllExportVo {
|
||||
private Date updateTime;
|
||||
|
||||
// 数据类型
|
||||
@Excel(name = "数据类型", readConverterExp = "0=历史,1=当前")
|
||||
private Integer dataType;
|
||||
|
||||
@ExcelProperty(value = "数据类型")
|
||||
private String dataTypeText;
|
||||
|
||||
// 调制度
|
||||
@ExcelProperty(value = "调制度")
|
||||
private String temperGrade;
|
||||
@@ -188,6 +191,14 @@ public class WmsMaterialCoilAllExportVo {
|
||||
private String businessPurpose;
|
||||
|
||||
// 是否与订单相关 readConverterExp
|
||||
@Excel(name = "是否与订单相关", readConverterExp = "0=否,1=是")
|
||||
private Integer isRelatedToOrder;
|
||||
|
||||
@ExcelProperty(value = "是否与订单相关")
|
||||
private String isRelatedToOrderText;
|
||||
|
||||
/**
|
||||
* 销售人员
|
||||
*/
|
||||
@ExcelProperty(value = "销售人员")
|
||||
private String saleName;
|
||||
}
|
||||
|
||||
@@ -184,4 +184,20 @@ public class WmsMaterialCoilExportVo {
|
||||
|
||||
// 是否与订单相关 readConverterExp
|
||||
private Integer isRelatedToOrder;
|
||||
|
||||
/**
|
||||
* 钢卷ID 此处不展示在报表只是方便set值
|
||||
*/
|
||||
private Long coilId;
|
||||
|
||||
/**
|
||||
* 操作完成时间(根据actionIds查询wms_coil_pending_action表获取)
|
||||
*/
|
||||
@ExcelProperty(value = "操作完成时间")
|
||||
private Date actionCompleteTime;
|
||||
|
||||
/**
|
||||
* 销售人员
|
||||
*/
|
||||
private String saleName;
|
||||
}
|
||||
|
||||
@@ -474,5 +474,7 @@ public class WmsMaterialCoilVo extends BaseEntity {
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date actionCompleteTime;
|
||||
|
||||
private String saleNickName;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.klp.mapper;
|
||||
|
||||
import com.klp.domain.WmsCoilPackingDetail;
|
||||
import com.klp.domain.vo.WmsCoilPackingDetailVo;
|
||||
import com.klp.common.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 钢卷打包明细(存储每个钢卷的库区/重量信息)Mapper接口
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
public interface WmsCoilPackingDetailMapper extends BaseMapperPlus<WmsCoilPackingDetailMapper, WmsCoilPackingDetail, WmsCoilPackingDetailVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.klp.mapper;
|
||||
|
||||
import com.klp.domain.WmsCoilPackingRecord;
|
||||
import com.klp.domain.vo.WmsCoilPackingRecordVo;
|
||||
import com.klp.common.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 钢卷打包记录主(打包待发区专用)Mapper接口
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
public interface WmsCoilPackingRecordMapper extends BaseMapperPlus<WmsCoilPackingRecordMapper, WmsCoilPackingRecord, WmsCoilPackingRecordVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.klp.service;
|
||||
|
||||
import com.klp.domain.WmsCoilPackingDetail;
|
||||
import com.klp.domain.vo.WmsCoilPackingDetailVo;
|
||||
import com.klp.domain.bo.WmsCoilPackingDetailBo;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 钢卷打包明细(存储每个钢卷的库区/重量信息)Service接口
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
public interface IWmsCoilPackingDetailService {
|
||||
|
||||
/**
|
||||
* 查询钢卷打包明细(存储每个钢卷的库区/重量信息)
|
||||
*/
|
||||
WmsCoilPackingDetailVo queryById(Long detailId);
|
||||
|
||||
/**
|
||||
* 查询钢卷打包明细(存储每个钢卷的库区/重量信息)列表
|
||||
*/
|
||||
TableDataInfo<WmsCoilPackingDetailVo> queryPageList(WmsCoilPackingDetailBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询钢卷打包明细(存储每个钢卷的库区/重量信息)列表
|
||||
*/
|
||||
List<WmsCoilPackingDetailVo> queryList(WmsCoilPackingDetailBo bo);
|
||||
|
||||
/**
|
||||
* 新增钢卷打包明细(存储每个钢卷的库区/重量信息)
|
||||
*/
|
||||
Boolean insertByBo(WmsCoilPackingDetailBo bo);
|
||||
|
||||
/**
|
||||
* 修改钢卷打包明细(存储每个钢卷的库区/重量信息)
|
||||
*/
|
||||
Boolean updateByBo(WmsCoilPackingDetailBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除钢卷打包明细(存储每个钢卷的库区/重量信息)信息
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.klp.service;
|
||||
|
||||
import com.klp.domain.WmsCoilPackingRecord;
|
||||
import com.klp.domain.vo.WmsCoilPackingRecordVo;
|
||||
import com.klp.domain.bo.WmsCoilPackingRecordBo;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 钢卷打包记录主(打包待发区专用)Service接口
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
public interface IWmsCoilPackingRecordService {
|
||||
|
||||
/**
|
||||
* 查询钢卷打包记录主(打包待发区专用)
|
||||
*/
|
||||
WmsCoilPackingRecordVo queryById(Long packingId);
|
||||
|
||||
/**
|
||||
* 查询钢卷打包记录主(打包待发区专用)列表
|
||||
*/
|
||||
TableDataInfo<WmsCoilPackingRecordVo> queryPageList(WmsCoilPackingRecordBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询钢卷打包记录主(打包待发区专用)列表
|
||||
*/
|
||||
List<WmsCoilPackingRecordVo> queryList(WmsCoilPackingRecordBo bo);
|
||||
|
||||
/**
|
||||
* 新增钢卷打包记录主(打包待发区专用)
|
||||
*/
|
||||
Boolean insertByBo(WmsCoilPackingRecordBo bo);
|
||||
|
||||
/**
|
||||
* 修改钢卷打包记录主(打包待发区专用)
|
||||
*/
|
||||
Boolean updateByBo(WmsCoilPackingRecordBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除钢卷打包记录主(打包待发区专用)信息
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 执行钢卷打包操作
|
||||
*
|
||||
* @param bo 打包业务对象
|
||||
* @return 是否成功
|
||||
*/
|
||||
Boolean packing(WmsCoilPackingRecordBo bo);
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package com.klp.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.klp.common.utils.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.klp.domain.bo.WmsCoilPackingDetailBo;
|
||||
import com.klp.domain.bo.WmsMaterialCoilBo;
|
||||
import com.klp.domain.vo.WmsCoilPackingDetailVo;
|
||||
import com.klp.domain.vo.WmsMaterialCoilVo;
|
||||
import com.klp.domain.WmsCoilPackingDetail;
|
||||
import com.klp.mapper.WmsCoilPackingDetailMapper;
|
||||
import com.klp.service.IWmsCoilPackingDetailService;
|
||||
import com.klp.service.IWmsMaterialCoilService;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 钢卷打包明细(存储每个钢卷的库区/重量信息)Service业务层处理
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class WmsCoilPackingDetailServiceImpl implements IWmsCoilPackingDetailService {
|
||||
|
||||
private final WmsCoilPackingDetailMapper baseMapper;
|
||||
private final IWmsMaterialCoilService iWmsMaterialCoilService;
|
||||
|
||||
/**
|
||||
* 查询钢卷打包明细(存储每个钢卷的库区/重量信息)
|
||||
*/
|
||||
@Override
|
||||
public WmsCoilPackingDetailVo queryById(Long detailId){
|
||||
return baseMapper.selectVoById(detailId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询钢卷打包明细(存储每个钢卷的库区/重量信息)列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<WmsCoilPackingDetailVo> queryPageList(WmsCoilPackingDetailBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<WmsCoilPackingDetail> lqw = buildQueryWrapper(bo);
|
||||
Page<WmsCoilPackingDetailVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
|
||||
if (result.getRecords() != null && !result.getRecords().isEmpty()) {
|
||||
enrichCoilInfo(result.getRecords());
|
||||
}
|
||||
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询钢卷打包明细(存储每个钢卷的库区/重量信息)列表
|
||||
*/
|
||||
@Override
|
||||
public List<WmsCoilPackingDetailVo> queryList(WmsCoilPackingDetailBo bo) {
|
||||
LambdaQueryWrapper<WmsCoilPackingDetail> lqw = buildQueryWrapper(bo);
|
||||
List<WmsCoilPackingDetailVo> list = baseMapper.selectVoList(lqw);
|
||||
|
||||
if (list != null && !list.isEmpty()) {
|
||||
enrichCoilInfo(list);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private void enrichCoilInfo(List<WmsCoilPackingDetailVo> detailVos) {
|
||||
List<Long> coilIds = detailVos.stream()
|
||||
.map(WmsCoilPackingDetailVo::getCoilId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (coilIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo();
|
||||
coilBo.setCoilIds(StringUtils.join(coilIds, ","));
|
||||
List<WmsMaterialCoilVo> coilVoList = iWmsMaterialCoilService.queryList(coilBo);
|
||||
|
||||
Map<Long, WmsMaterialCoilVo> coilMap = coilVoList.stream()
|
||||
.collect(Collectors.toMap(WmsMaterialCoilVo::getCoilId, v -> v, (a, b) -> a));
|
||||
|
||||
for (WmsCoilPackingDetailVo detailVo : detailVos) {
|
||||
detailVo.setCoil(coilMap.get(detailVo.getCoilId()));
|
||||
}
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<WmsCoilPackingDetail> buildQueryWrapper(WmsCoilPackingDetailBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<WmsCoilPackingDetail> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(bo.getPackingId() != null, WmsCoilPackingDetail::getPackingId, bo.getPackingId());
|
||||
lqw.eq(bo.getCoilId() != null, WmsCoilPackingDetail::getCoilId, bo.getCoilId());
|
||||
lqw.eq(bo.getFromWarehouseId() != null, WmsCoilPackingDetail::getFromWarehouseId, bo.getFromWarehouseId());
|
||||
lqw.eq(bo.getToWarehouseId() != null, WmsCoilPackingDetail::getToWarehouseId, bo.getToWarehouseId());
|
||||
lqw.eq(bo.getCoilGrossWeight() != null, WmsCoilPackingDetail::getCoilGrossWeight, bo.getCoilGrossWeight());
|
||||
lqw.eq(bo.getCoilNetWeight() != null, WmsCoilPackingDetail::getCoilNetWeight, bo.getCoilNetWeight());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增钢卷打包明细(存储每个钢卷的库区/重量信息)
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(WmsCoilPackingDetailBo bo) {
|
||||
WmsCoilPackingDetail add = BeanUtil.toBean(bo, WmsCoilPackingDetail.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setDetailId(add.getDetailId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改钢卷打包明细(存储每个钢卷的库区/重量信息)
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(WmsCoilPackingDetailBo bo) {
|
||||
WmsCoilPackingDetail update = BeanUtil.toBean(bo, WmsCoilPackingDetail.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(WmsCoilPackingDetail entity){
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除钢卷打包明细(存储每个钢卷的库区/重量信息)
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if(isValid){
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
package com.klp.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.klp.common.helper.LoginHelper;
|
||||
import com.klp.common.utils.StringUtils;
|
||||
import com.klp.domain.WmsCoilPackingDetail;
|
||||
import com.klp.domain.WmsMaterialCoil;
|
||||
import com.klp.domain.bo.WmsCoilPackingDetailBo;
|
||||
import com.klp.domain.bo.WmsMaterialCoilBo;
|
||||
import com.klp.domain.vo.WmsMaterialCoilVo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.klp.domain.bo.WmsCoilPackingRecordBo;
|
||||
import com.klp.domain.vo.WmsCoilPackingRecordVo;
|
||||
import com.klp.domain.vo.WmsCoilPackingDetailVo;
|
||||
import com.klp.domain.WmsCoilPackingRecord;
|
||||
import com.klp.mapper.WmsCoilPackingRecordMapper;
|
||||
import com.klp.mapper.WmsCoilPackingDetailMapper;
|
||||
import com.klp.mapper.WmsMaterialCoilMapper;
|
||||
import com.klp.service.IWmsCoilPackingRecordService;
|
||||
import com.klp.service.IWmsMaterialCoilService;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 钢卷打包记录主(打包待发区专用)Service业务层处理
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-03-23
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class WmsCoilPackingRecordServiceImpl implements IWmsCoilPackingRecordService {
|
||||
|
||||
private final WmsCoilPackingRecordMapper baseMapper;
|
||||
private final WmsMaterialCoilMapper wmsMaterialCoilMapper;
|
||||
private final WmsCoilPackingDetailMapper detailMapper;
|
||||
private final IWmsMaterialCoilService iWmsMaterialCoilService;
|
||||
|
||||
/**
|
||||
* 查询钢卷打包记录主(打包待发区专用)
|
||||
*/
|
||||
@Override
|
||||
public WmsCoilPackingRecordVo queryById(Long packingId){
|
||||
return baseMapper.selectVoById(packingId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询钢卷打包记录主(打包待发区专用)列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<WmsCoilPackingRecordVo> queryPageList(WmsCoilPackingRecordBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<WmsCoilPackingRecord> lqw = buildQueryWrapper(bo);
|
||||
Page<WmsCoilPackingRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
private void enrichRecordWithDetails(WmsCoilPackingRecordVo recordVo) {
|
||||
Long packingId = recordVo.getPackingId();
|
||||
|
||||
LambdaQueryWrapper<WmsCoilPackingDetail> detailLqw = Wrappers.lambdaQuery();
|
||||
detailLqw.eq(WmsCoilPackingDetail::getPackingId, packingId);
|
||||
List<WmsCoilPackingDetail> details = detailMapper.selectList(detailLqw);
|
||||
|
||||
if (details == null || details.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Long> coilIds = new ArrayList<>();
|
||||
for (WmsCoilPackingDetail detail : details) {
|
||||
coilIds.add(detail.getCoilId());
|
||||
}
|
||||
|
||||
Map<Long, WmsMaterialCoilVo> coilMap = new HashMap<>();
|
||||
if (!coilIds.isEmpty()) {
|
||||
WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo();
|
||||
coilBo.setCoilIds(StringUtils.join(coilIds, ","));
|
||||
List<WmsMaterialCoilVo> coilVoList = iWmsMaterialCoilService.queryList(coilBo);
|
||||
for (WmsMaterialCoilVo coilVo : coilVoList) {
|
||||
coilMap.put(coilVo.getCoilId(), coilVo);
|
||||
}
|
||||
}
|
||||
|
||||
List<WmsCoilPackingDetailVo> detailVos = new ArrayList<>();
|
||||
for (WmsCoilPackingDetail detail : details) {
|
||||
WmsCoilPackingDetailVo detailVo = BeanUtil.toBean(detail, WmsCoilPackingDetailVo.class);
|
||||
detailVo.setCoil(coilMap.get(detail.getCoilId()));
|
||||
detailVos.add(detailVo);
|
||||
}
|
||||
|
||||
recordVo.setDetails(detailVos);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询钢卷打包记录主(打包待发区专用)列表
|
||||
*/
|
||||
@Override
|
||||
public List<WmsCoilPackingRecordVo> queryList(WmsCoilPackingRecordBo bo) {
|
||||
LambdaQueryWrapper<WmsCoilPackingRecord> lqw = buildQueryWrapper(bo);
|
||||
List<WmsCoilPackingRecordVo> list = baseMapper.selectVoList(lqw);
|
||||
|
||||
if (list != null && !list.isEmpty()) {
|
||||
for (WmsCoilPackingRecordVo recordVo : list) {
|
||||
enrichRecordWithDetails(recordVo);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<WmsCoilPackingRecord> buildQueryWrapper(WmsCoilPackingRecordBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<WmsCoilPackingRecord> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getPackingNo()), WmsCoilPackingRecord::getPackingNo, bo.getPackingNo());
|
||||
lqw.eq(bo.getCoilCount() != null, WmsCoilPackingRecord::getCoilCount, bo.getCoilCount());
|
||||
lqw.eq(bo.getTotalGrossWeight() != null, WmsCoilPackingRecord::getTotalGrossWeight, bo.getTotalGrossWeight());
|
||||
lqw.eq(bo.getTotalNetWeight() != null, WmsCoilPackingRecord::getTotalNetWeight, bo.getTotalNetWeight());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getSaleName()), WmsCoilPackingRecord::getSaleName, bo.getSaleName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getBatchNo()), WmsCoilPackingRecord::getBatchNo, bo.getBatchNo());
|
||||
lqw.eq(bo.getPackingStatus() != null, WmsCoilPackingRecord::getPackingStatus, bo.getPackingStatus());
|
||||
lqw.eq(bo.getPackingTime() != null, WmsCoilPackingRecord::getPackingTime, bo.getPackingTime());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getPackingBy()), WmsCoilPackingRecord::getPackingBy, bo.getPackingBy());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getWarehouseRemark()), WmsCoilPackingRecord::getWarehouseRemark, bo.getWarehouseRemark());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增钢卷打包记录主(打包待发区专用)
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(WmsCoilPackingRecordBo bo) {
|
||||
WmsCoilPackingRecord add = BeanUtil.toBean(bo, WmsCoilPackingRecord.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setPackingId(add.getPackingId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改钢卷打包记录主(打包待发区专用)
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(WmsCoilPackingRecordBo bo) {
|
||||
WmsCoilPackingRecord update = BeanUtil.toBean(bo, WmsCoilPackingRecord.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(WmsCoilPackingRecord entity){
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除钢卷打包记录主(打包待发区专用)
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if(isValid){
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行钢卷打包操作
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean packing(WmsCoilPackingRecordBo bo) {
|
||||
List<WmsCoilPackingDetailBo> details = bo.getDetails();
|
||||
if (details == null || details.isEmpty()) {
|
||||
throw new RuntimeException("打包明细不能为空");
|
||||
}
|
||||
|
||||
BigDecimal totalGrossWeight = BigDecimal.ZERO;
|
||||
BigDecimal totalNetWeight = BigDecimal.ZERO;
|
||||
|
||||
for (WmsCoilPackingDetailBo detailBo : details) {
|
||||
Long coilId = detailBo.getCoilId();
|
||||
Long toWarehouseId = detailBo.getToWarehouseId();
|
||||
String saleName = detailBo.getSaleName();
|
||||
|
||||
if (coilId == null || toWarehouseId == null) {
|
||||
throw new RuntimeException("钢卷ID和目标库区ID不能为空");
|
||||
}
|
||||
|
||||
WmsMaterialCoil coil = wmsMaterialCoilMapper.selectById(coilId);
|
||||
if (coil == null) {
|
||||
throw new RuntimeException("钢卷不存在,coilId: " + coilId);
|
||||
}
|
||||
|
||||
detailBo.setFromWarehouseId(coil.getWarehouseId());
|
||||
detailBo.setCoilGrossWeight(coil.getGrossWeight());
|
||||
detailBo.setCoilNetWeight(coil.getNetWeight());
|
||||
|
||||
totalGrossWeight = totalGrossWeight.add(coil.getGrossWeight() != null ? coil.getGrossWeight() : BigDecimal.ZERO);
|
||||
totalNetWeight = totalNetWeight.add(coil.getNetWeight() != null ? coil.getNetWeight() : BigDecimal.ZERO);
|
||||
|
||||
WmsMaterialCoil updateCoil = new WmsMaterialCoil();
|
||||
updateCoil.setCoilId(coilId);
|
||||
updateCoil.setWarehouseId(toWarehouseId);
|
||||
updateCoil.setSaleName(saleName);
|
||||
wmsMaterialCoilMapper.updateById(updateCoil);
|
||||
}
|
||||
|
||||
WmsCoilPackingRecord record = new WmsCoilPackingRecord();
|
||||
record.setPackingNo(bo.getPackingNo());
|
||||
record.setCoilCount((long) details.size());
|
||||
record.setTotalGrossWeight(totalGrossWeight);
|
||||
record.setTotalNetWeight(totalNetWeight);
|
||||
record.setSaleName(bo.getSaleName());
|
||||
record.setBatchNo(bo.getBatchNo());
|
||||
record.setPackingStatus(1);
|
||||
record.setPackingTime(new Date());
|
||||
record.setPackingBy(bo.getPackingBy());
|
||||
record.setWarehouseRemark(bo.getWarehouseRemark());
|
||||
record.setRemark(bo.getRemark());
|
||||
|
||||
baseMapper.insert(record);
|
||||
|
||||
for (WmsCoilPackingDetailBo detailBo : details) {
|
||||
WmsCoilPackingDetail detail = new WmsCoilPackingDetail();
|
||||
detail.setPackingId(record.getPackingId());
|
||||
detail.setCoilId(detailBo.getCoilId());
|
||||
detail.setFromWarehouseId(detailBo.getFromWarehouseId());
|
||||
detail.setToWarehouseId(detailBo.getToWarehouseId());
|
||||
detail.setCoilGrossWeight(detailBo.getCoilGrossWeight());
|
||||
detail.setCoilNetWeight(detailBo.getCoilNetWeight());
|
||||
detail.setRemark(detailBo.getRemark());
|
||||
|
||||
detailMapper.insert(detail);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -82,9 +82,13 @@ public class WmsEmployeeChangeServiceImpl implements IWmsEmployeeChangeService {
|
||||
lqw.eq(bo.getInfoId() != null, WmsEmployeeChange::getInfoId, bo.getInfoId());
|
||||
lqw.eq(bo.getChangeType() != null, WmsEmployeeChange::getChangeType, bo.getChangeType());
|
||||
lqw.eq(bo.getChangeTime() != null, WmsEmployeeChange::getChangeTime, bo.getChangeTime());
|
||||
lqw.ge(bo.getChangeStartTime() != null, WmsEmployeeChange::getChangeTime, bo.getChangeStartTime());
|
||||
lqw.le(bo.getChangeEndTime() != null, WmsEmployeeChange::getChangeTime, bo.getChangeEndTime());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getChangeReason()), WmsEmployeeChange::getChangeReason, bo.getChangeReason());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getChangeHandler()), WmsEmployeeChange::getChangeHandler, bo.getChangeHandler());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getAttachment()), WmsEmployeeChange::getAttachment, bo.getAttachment());
|
||||
// 按照变动时间倒叙排序
|
||||
lqw.orderByDesc(WmsEmployeeChange::getChangeTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,8 @@ public class WmsEmployeeInfoServiceImpl implements IWmsEmployeeInfoService {
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getHomeAddress()), WmsEmployeeInfo::getHomeAddress, bo.getHomeAddress());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getPhone()), WmsEmployeeInfo::getPhone, bo.getPhone());
|
||||
lqw.eq(bo.getEntryTime() != null, WmsEmployeeInfo::getEntryTime, bo.getEntryTime());
|
||||
lqw.ge(bo.getEntryStartTime() != null, WmsEmployeeInfo::getEntryTime, bo.getEntryStartTime());
|
||||
lqw.le(bo.getEntryEndTime() != null, WmsEmployeeInfo::getEntryTime, bo.getEntryEndTime());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getEmergencyContact()), WmsEmployeeInfo::getEmergencyContact, bo.getEmergencyContact());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getRelationship()), WmsEmployeeInfo::getRelationship, bo.getRelationship());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getEmergencyContactPhone()), WmsEmployeeInfo::getEmergencyContactPhone, bo.getEmergencyContactPhone());
|
||||
@@ -80,6 +82,21 @@ public class WmsEmployeeInfoServiceImpl implements IWmsEmployeeInfoService {
|
||||
lqw.eq(bo.getIsLeave() != null, WmsEmployeeInfo::getIsLeave, bo.getIsLeave());
|
||||
// 是否转正
|
||||
lqw.eq(bo.getIsRegular() != null, WmsEmployeeInfo::getIsRegular, bo.getIsRegular());
|
||||
|
||||
// 按照转正开始时间和转正结束时间进行查询
|
||||
lqw.ge(bo.getRegularStartTime() != null, WmsEmployeeInfo::getRegularTime, bo.getRegularStartTime());
|
||||
lqw.le(bo.getRegularEndTime() != null, WmsEmployeeInfo::getRegularTime, bo.getRegularEndTime());
|
||||
|
||||
// 排序逻辑:优先判断入职时间排序,其次转正时间排序,默认创建时间倒序
|
||||
if (Boolean.TRUE.equals(bo.getSortByEntryTime())) {
|
||||
lqw.orderByDesc(WmsEmployeeInfo::getEntryTime);
|
||||
} else if (Boolean.TRUE.equals(bo.getSortByRegularTime())) {
|
||||
lqw.orderByDesc(WmsEmployeeInfo::getRegularTime);
|
||||
} else {
|
||||
// 默认按照创建时间倒序排序 (假设实体类中有 createTime 字段,若字段名不同请调整)
|
||||
lqw.orderByDesc(WmsEmployeeInfo::getCreateTime);
|
||||
}
|
||||
|
||||
return lqw;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,10 +89,15 @@ public class WmsEmployeeTransferServiceImpl implements IWmsEmployeeTransferServi
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getNewDept()), WmsEmployeeTransfer::getNewDept, bo.getNewDept());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getNewJobType()), WmsEmployeeTransfer::getNewJobType, bo.getNewJobType());
|
||||
lqw.eq(bo.getTransferTime() != null, WmsEmployeeTransfer::getTransferTime, bo.getTransferTime());
|
||||
lqw.ge(bo.getTransferStartTime() != null, WmsEmployeeTransfer::getTransferTime, bo.getTransferStartTime());
|
||||
lqw.le(bo.getTransferEndTime() != null, WmsEmployeeTransfer::getTransferTime, bo.getTransferEndTime());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getTransferReason()), WmsEmployeeTransfer::getTransferReason, bo.getTransferReason());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getTransferHandler()), WmsEmployeeTransfer::getTransferHandler, bo.getTransferHandler());
|
||||
lqw.eq(bo.getApprovalStatus() != null, WmsEmployeeTransfer::getApprovalStatus, bo.getApprovalStatus());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getAttachment()), WmsEmployeeTransfer::getAttachment, bo.getAttachment());
|
||||
|
||||
// 按照转岗时间倒叙排序
|
||||
lqw.orderByDesc(WmsEmployeeTransfer::getTransferTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
|
||||
@@ -518,6 +518,11 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
||||
}
|
||||
}
|
||||
|
||||
// 销售人员姓名模糊查询
|
||||
if (bo.getSaleName() != null && !bo.getSaleName().isEmpty()) {
|
||||
qw.like("su.nick_name", bo.getSaleName());
|
||||
}
|
||||
|
||||
// 仅查询废品:质量状态为 D+、D、D-
|
||||
if (Boolean.TRUE.equals(bo.getOnlyScrap())) {
|
||||
qw.in("mc.quality_status", java.util.Arrays.asList("C+", "C", "C-", "D+", "D", "D-"));
|
||||
@@ -528,6 +533,11 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
||||
qw.apply("NOT EXISTS (SELECT 1 FROM wms_delivery_waybill_detail d WHERE d.del_flag = 0 AND d.coil_id = mc.coil_id)");
|
||||
}
|
||||
|
||||
// 排除已打包的钢卷(防止重复打包)
|
||||
if (Boolean.TRUE.equals(bo.getExcludePacked())) {
|
||||
qw.apply("NOT EXISTS (SELECT 1 FROM wms_coil_packing_detail pd WHERE pd.del_flag = 0 AND pd.coil_id = mc.coil_id)");
|
||||
}
|
||||
|
||||
// 组合 item_id 条件:改为使用 EXISTS 子查询,替代预查询 + IN
|
||||
boolean hasSelectType = StringUtils.isNotBlank(bo.getSelectType());
|
||||
boolean hasAnyItemFilter = StringUtils.isNotBlank(bo.getItemMaterial())
|
||||
@@ -2421,10 +2431,42 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
||||
*/
|
||||
@Override
|
||||
public List<WmsMaterialCoilExportVo> queryExportList(WmsMaterialCoilBo bo) {
|
||||
Map<Long, Date> coilIdCompleteTimeMap = new HashMap<>();
|
||||
|
||||
if ((bo.getCoilIds() == null || bo.getCoilIds().isEmpty())
|
||||
&& bo.getActionIds() != null && !bo.getActionIds().isEmpty()) {
|
||||
String[] actionIdArr = bo.getActionIds().split(",");
|
||||
List<Long> actionIdList = Arrays.stream(actionIdArr)
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isEmpty())
|
||||
.map(Long::parseLong)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
LambdaQueryWrapper<WmsCoilPendingAction> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(WmsCoilPendingAction::getActionId, actionIdList);
|
||||
|
||||
List<WmsCoilPendingAction> actions = coilPendingActionMapper.selectList(queryWrapper);
|
||||
|
||||
if (actions != null && !actions.isEmpty()) {
|
||||
for (WmsCoilPendingAction action : actions) {
|
||||
coilIdCompleteTimeMap.put(action.getCoilId(), action.getCompleteTime());
|
||||
}
|
||||
|
||||
bo.setCoilIds(actions.stream()
|
||||
.map(a -> String.valueOf(a.getCoilId()))
|
||||
.collect(Collectors.joining(",")));
|
||||
}
|
||||
}
|
||||
|
||||
QueryWrapper<WmsMaterialCoil> lqw = buildQueryWrapperPlus(bo);
|
||||
List<WmsMaterialCoilExportVo> wmsMaterialCoilExportVos = baseMapper.selectExportList(lqw);
|
||||
// 遍历数据,根据状态替换日期字段,并处理空值兜底
|
||||
wmsMaterialCoilExportVos.stream().forEach(vo -> {
|
||||
// 设置action完成时间
|
||||
if (coilIdCompleteTimeMap.containsKey(vo.getCoilId())) {
|
||||
vo.setActionCompleteTime(coilIdCompleteTimeMap.get(vo.getCoilId()));
|
||||
}
|
||||
|
||||
// 判断查询条件中的status是否为1(已发货)
|
||||
if (bo.getStatus() != null && bo.getStatus() == 1) {
|
||||
Date finalDate = null;
|
||||
@@ -2466,6 +2508,17 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
||||
if (Objects.equals(vo.getDataType(), 0)) {
|
||||
vo.setActualWarehouseName(null);
|
||||
}
|
||||
// 转换数据类型:0=历史,1=现存
|
||||
if (vo.getDataType() != null) {
|
||||
String dataTypeText = vo.getDataType() == 0 ? "历史" : "现存";
|
||||
vo.setDataTypeText(dataTypeText);
|
||||
}
|
||||
|
||||
// 转换是否与订单相关:0=否,1=是
|
||||
if (vo.getIsRelatedToOrder() != null) {
|
||||
String isRelatedText = vo.getIsRelatedToOrder() == 0 ? "否" : "是";
|
||||
vo.setIsRelatedToOrderText(isRelatedText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.entity.SysUser;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.exception.ServiceException;
|
||||
import com.klp.common.utils.StringUtils;
|
||||
import com.klp.config.StampProperties;
|
||||
import com.klp.domain.WmsApproval;
|
||||
import com.klp.domain.WmsApprovalTask;
|
||||
@@ -207,6 +208,7 @@ public class WmsSealReqServiceImpl implements IWmsSealReqService {
|
||||
lqw.eq(bo.getEmpId() != null, WmsSealReq::getEmpId, bo.getEmpId());
|
||||
lqw.eq(bo.getSealType() != null, WmsSealReq::getSealType, bo.getSealType());
|
||||
lqw.eq(bo.getStatus() != null, WmsSealReq::getStatus, bo.getStatus());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), WmsSealReq::getCreateBy, bo.getCreateBy());
|
||||
lqw.orderByDesc(WmsSealReq::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?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.klp.mapper.WmsCoilPackingDetailMapper">
|
||||
|
||||
<resultMap type="com.klp.domain.WmsCoilPackingDetail" id="WmsCoilPackingDetailResult">
|
||||
<result property="detailId" column="detail_id"/>
|
||||
<result property="packingId" column="packing_id"/>
|
||||
<result property="coilId" column="coil_id"/>
|
||||
<result property="fromWarehouseId" column="from_warehouse_id"/>
|
||||
<result property="toWarehouseId" column="to_warehouse_id"/>
|
||||
<result property="coilGrossWeight" column="coil_gross_weight"/>
|
||||
<result property="coilNetWeight" column="coil_net_weight"/>
|
||||
<result property="delFlag" column="del_flag"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="remark" column="remark"/>
|
||||
</resultMap>
|
||||
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?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.klp.mapper.WmsCoilPackingRecordMapper">
|
||||
|
||||
<resultMap type="com.klp.domain.WmsCoilPackingRecord" id="WmsCoilPackingRecordResult">
|
||||
<result property="packingId" column="packing_id"/>
|
||||
<result property="packingNo" column="packing_no"/>
|
||||
<result property="coilCount" column="coil_count"/>
|
||||
<result property="totalGrossWeight" column="total_gross_weight"/>
|
||||
<result property="totalNetWeight" column="total_net_weight"/>
|
||||
<result property="saleName" column="sale_name"/>
|
||||
<result property="batchNo" column="batch_no"/>
|
||||
<result property="packingStatus" column="packing_status"/>
|
||||
<result property="packingTime" column="packing_time"/>
|
||||
<result property="packingBy" column="packing_by"/>
|
||||
<result property="warehouseRemark" column="warehouse_remark"/>
|
||||
<result property="delFlag" column="del_flag"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="remark" column="remark"/>
|
||||
</resultMap>
|
||||
|
||||
|
||||
</mapper>
|
||||
@@ -35,6 +35,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="saleId" column="sale_id"/>
|
||||
<result property="saleName" column="sale_name"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 统计查询专用的ResultMap -->
|
||||
@@ -117,7 +119,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
mc.business_purpose,
|
||||
mc.is_related_to_order,
|
||||
mc.exclusive_status,
|
||||
su.nick_name AS saleName,
|
||||
mc.sale_name AS saleName,
|
||||
su.nick_name AS saleNickName,
|
||||
w.warehouse_name AS warehouseName,
|
||||
nw.warehouse_name AS nextWarehouseName,
|
||||
aw.actual_warehouse_name AS actualWarehouseName,
|
||||
@@ -213,7 +216,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
mc.business_purpose,
|
||||
mc.is_related_to_order,
|
||||
mc.exclusive_status,
|
||||
su.nick_name AS saleName,
|
||||
mc.sale_name AS saleName,
|
||||
su.nick_name AS saleNickName,
|
||||
w.warehouse_name AS warehouseName,
|
||||
nw.warehouse_name AS nextWarehouseName,
|
||||
aw.actual_warehouse_name AS actualWarehouseName,
|
||||
@@ -474,6 +478,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
END AS itemTypeDesc,
|
||||
-- 物品ID
|
||||
mc.item_id AS itemId,
|
||||
-- 钢卷ID
|
||||
mc.coil_id AS coilId,
|
||||
-- 数据类型
|
||||
mc.data_type AS dataType,
|
||||
-- 逻辑库区
|
||||
@@ -516,6 +522,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
mc.quality_status AS qualityStatus,
|
||||
-- 打包状态(直接展示原始值)
|
||||
mc.packing_status AS packingStatus,
|
||||
-- 销售
|
||||
mc.sale_name AS saleName,
|
||||
-- 库存状态(中文显示)
|
||||
CASE
|
||||
WHEN mc.status = 0 THEN '在库'
|
||||
@@ -601,6 +609,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
mc.packaging_requirement AS packagingRequirement,
|
||||
mc.quality_status AS qualityStatus,
|
||||
mc.packing_status AS packingStatus,
|
||||
mc.sale_name AS saleName,
|
||||
CASE
|
||||
WHEN mc.status = 0 THEN '在库'
|
||||
WHEN mc.status = 1 THEN '已发货'
|
||||
|
||||
Reference in New Issue
Block a user